From 2ae4b6b20e2004dccf80d804ae52b073377c2f5b Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Thu, 22 Oct 2015 04:05:00 +0530 Subject: firewire: nosy: Replace timeval with timespec64 32 bit systems using 'struct timeval' will break in the year 2038, so we replace the code appropriately. However, this driver is not broken in 2038 since we are using only the microseconds portion of the current time. This patch replaces timeval with timespec64. Signed-off-by: Amitoj Kaur Chawla Reviewed-by: Arnd Bergmann Signed-off-by: Stefan Richter --- drivers/firewire/nosy.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c index 76b2d390f6ec..8a46077129ac 100644 --- a/drivers/firewire/nosy.c +++ b/drivers/firewire/nosy.c @@ -33,6 +33,7 @@ #include /* required for linux/wait.h */ #include #include +#include #include #include #include @@ -413,17 +414,18 @@ static void packet_irq_handler(struct pcilynx *lynx) { struct client *client; - u32 tcode_mask, tcode; + u32 tcode_mask, tcode, timestamp; size_t length; - struct timeval tv; + struct timespec64 ts64; /* FIXME: Also report rcv_speed. */ length = __le32_to_cpu(lynx->rcv_pcl->pcl_status) & 0x00001fff; tcode = __le32_to_cpu(lynx->rcv_buffer[1]) >> 4 & 0xf; - do_gettimeofday(&tv); - lynx->rcv_buffer[0] = (__force __le32)tv.tv_usec; + ktime_get_real_ts64(&ts64); + timestamp = ts64.tv_nsec / NSEC_PER_USEC; + lynx->rcv_buffer[0] = (__force __le32)timestamp; if (length == PHY_PACKET_SIZE) tcode_mask = 1 << TCODE_PHY_PACKET; -- cgit v1.2.3 From a354cf00c71390c46927335fe20b65f38a528b59 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 1 Nov 2015 15:52:13 +0100 Subject: firewire: ohci: propagate return code from soft_reset to probe and resume software_reset() may fail - due to unresponsive chip with -EBUSY (-16), or - due to ejected or unseated card with -ENODEV (-19). Let the PCI probe and resume routines log the actual error code instead of hardwired -EBUSY. Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index c2f5117fd8cb..8bf89267dc25 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2278,9 +2278,10 @@ static int ohci_enable(struct fw_card *card, u32 lps, version, irqs; int i, ret; - if (software_reset(ohci)) { + ret = software_reset(ohci); + if (ret < 0) { ohci_err(ohci, "failed to reset ohci card\n"); - return -EBUSY; + return ret; } /* -- cgit v1.2.3 From d590faf9e8f8509a0a0aa79c38e87fcc6b913248 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 27 Nov 2015 14:55:56 +0100 Subject: iio: adis_buffer: Fix out-of-bounds memory access The SPI tx and rx buffers are both supposed to be scan_bytes amount of bytes large and a common allocation is used to allocate both buffers. This puts the beginning of the tx buffer scan_bytes bytes after the rx buffer. The initialization of the tx buffer pointer is done adding scan_bytes to the beginning of the rx buffer, but since the rx buffer is of type __be16 this will actually add two times as much and the tx buffer ends up pointing after the allocated buffer. Fix this by using scan_count, which is scan_bytes / 2, instead of scan_bytes when initializing the tx buffer pointer. Fixes: aacff892cbd5 ("staging:iio:adis: Preallocate transfer message") Signed-off-by: Lars-Peter Clausen Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis_buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c index cb32b593f1c5..36607d52fee0 100644 --- a/drivers/iio/imu/adis_buffer.c +++ b/drivers/iio/imu/adis_buffer.c @@ -43,7 +43,7 @@ int adis_update_scan_mode(struct iio_dev *indio_dev, return -ENOMEM; rx = adis->buffer; - tx = rx + indio_dev->scan_bytes; + tx = rx + scan_count; spi_message_init(&adis->msg); -- cgit v1.2.3 From 7f83773ced2f9f41dec5e6eb3eb4a7ef23ca1d75 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Fri, 20 Nov 2015 11:30:17 +0100 Subject: efi/esrt: Don't preformat name kobject_init_and_add takes a format string+args, so there's no reason to do this formatting in advance. Signed-off-by: Rasmus Villemoes Cc: Peter Jones Signed-off-by: Matt Fleming --- drivers/firmware/efi/esrt.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c index 22c5285f7705..75feb3f5829b 100644 --- a/drivers/firmware/efi/esrt.c +++ b/drivers/firmware/efi/esrt.c @@ -167,14 +167,11 @@ static struct kset *esrt_kset; static int esre_create_sysfs_entry(void *esre, int entry_num) { struct esre_entry *entry; - char name[20]; entry = kzalloc(sizeof(*entry), GFP_KERNEL); if (!entry) return -ENOMEM; - sprintf(name, "entry%d", entry_num); - entry->kobj.kset = esrt_kset; if (esrt->fw_resource_version == 1) { @@ -182,7 +179,7 @@ static int esre_create_sysfs_entry(void *esre, int entry_num) entry->esre.esre1 = esre; rc = kobject_init_and_add(&entry->kobj, &esre1_ktype, NULL, - "%s", name); + "entry%d", entry_num); if (rc) { kfree(entry); return rc; -- cgit v1.2.3 From 50a0cb565246f20d59cdb161778531e4b19d35ac Mon Sep 17 00:00:00 2001 From: Sai Praneeth Date: Wed, 9 Dec 2015 15:41:08 -0800 Subject: x86/efi-bgrt: Fix kernel panic when mapping BGRT data Starting with this commit 35eb8b81edd4 ("x86/efi: Build our own page table structures") efi regions have a separate page directory called "efi_pgd". In order to access any efi region we have to first shift %cr3 to this page table. In the bgrt code we are trying to copy bgrt_header and image, but these regions fall under "EFI_BOOT_SERVICES_DATA" and to access these regions we have to shift %cr3 to efi_pgd and not doing so will cause page fault as shown below. [ 0.251599] Last level dTLB entries: 4KB 64, 2MB 0, 4MB 0, 1GB 4 [ 0.259126] Freeing SMP alternatives memory: 32K (ffffffff8230e000 - ffffffff82316000) [ 0.271803] BUG: unable to handle kernel paging request at fffffffefce35002 [ 0.279740] IP: [] efi_bgrt_init+0x144/0x1fd [ 0.286383] PGD 300f067 PUD 0 [ 0.289879] Oops: 0000 [#1] SMP [ 0.293566] Modules linked in: [ 0.297039] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.4.0-rc1-eywa-eywa-built-in-47041+ #2 [ 0.306619] Hardware name: Intel Corporation Skylake Client platform/Skylake Y LPDDR3 RVP3, BIOS SKLSE2R1.R00.B104.B01.1511110114 11/11/2015 [ 0.320925] task: ffffffff820134c0 ti: ffffffff82000000 task.ti: ffffffff82000000 [ 0.329420] RIP: 0010:[] [] efi_bgrt_init+0x144/0x1fd [ 0.338821] RSP: 0000:ffffffff82003f18 EFLAGS: 00010246 [ 0.344852] RAX: fffffffefce35000 RBX: fffffffefce35000 RCX: fffffffefce2b000 [ 0.352952] RDX: 000000008a82b000 RSI: ffffffff8235bb80 RDI: 000000008a835000 [ 0.361050] RBP: ffffffff82003f30 R08: 000000008a865000 R09: ffffffffff202850 [ 0.369149] R10: ffffffff811ad62f R11: 0000000000000000 R12: 0000000000000000 [ 0.377248] R13: ffff88016dbaea40 R14: ffffffff822622c0 R15: ffffffff82003fb0 [ 0.385348] FS: 0000000000000000(0000) GS:ffff88016d800000(0000) knlGS:0000000000000000 [ 0.394533] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 0.401054] CR2: fffffffefce35002 CR3: 000000000300c000 CR4: 00000000003406f0 [ 0.409153] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 0.417252] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 0.425350] Stack: [ 0.427638] ffffffffffffffff ffffffff82256900 ffff88016dbaea40 ffffffff82003f40 [ 0.436086] ffffffff821bbce0 ffffffff82003f88 ffffffff8219c0c2 0000000000000000 [ 0.444533] ffffffff8219ba4a ffffffff822622c0 0000000000083000 00000000ffffffff [ 0.452978] Call Trace: [ 0.455763] [] efi_late_init+0x9/0xb [ 0.461697] [] start_kernel+0x463/0x47f [ 0.467928] [] ? set_init_arg+0x55/0x55 [ 0.474159] [] ? early_idt_handler_array+0x120/0x120 [ 0.481669] [] x86_64_start_reservations+0x2a/0x2c [ 0.488982] [] x86_64_start_kernel+0x13d/0x14c [ 0.495897] Code: 00 41 b4 01 48 8b 78 28 e8 09 36 01 00 48 85 c0 48 89 c3 75 13 48 c7 c7 f8 ac d3 81 31 c0 e8 d7 3b fb fe e9 b5 00 00 00 45 84 e4 <44> 8b 6b 02 74 0d be 06 00 00 00 48 89 df e8 ae 34 0$ [ 0.518151] RIP [] efi_bgrt_init+0x144/0x1fd [ 0.524888] RSP [ 0.528851] CR2: fffffffefce35002 [ 0.532615] ---[ end trace 7b06521e6ebf2aea ]--- [ 0.537852] Kernel panic - not syncing: Attempted to kill the idle task! As said above one way to fix this bug is to shift %cr3 to efi_pgd but we are not doing that way because it leaks inner details of how we switch to EFI page tables into a new call site and it also adds duplicate code. Instead, we remove the call to efi_lookup_mapped_addr() and always perform early_mem*() instead of early_io*() because we want to remap RAM regions and not I/O regions. We also delete efi_lookup_mapped_addr() because we are no longer using it. Signed-off-by: Sai Praneeth Prakhya Reported-by: Wendy Wang Cc: Borislav Petkov Cc: Josh Triplett Cc: Ricardo Neri Cc: Ravi Shankar Signed-off-by: Matt Fleming --- arch/x86/platform/efi/efi-bgrt.c | 39 ++++++++++++++------------------------- drivers/firmware/efi/efi.c | 32 -------------------------------- 2 files changed, 14 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/arch/x86/platform/efi/efi-bgrt.c b/arch/x86/platform/efi/efi-bgrt.c index 9a52b5c4438f..bf51f4c02562 100644 --- a/arch/x86/platform/efi/efi-bgrt.c +++ b/arch/x86/platform/efi/efi-bgrt.c @@ -31,8 +31,7 @@ struct bmp_header { void __init efi_bgrt_init(void) { acpi_status status; - void __iomem *image; - bool ioremapped = false; + void *image; struct bmp_header bmp_header; if (acpi_disabled) @@ -73,20 +72,14 @@ void __init efi_bgrt_init(void) return; } - image = efi_lookup_mapped_addr(bgrt_tab->image_address); + image = early_memremap(bgrt_tab->image_address, sizeof(bmp_header)); if (!image) { - image = early_ioremap(bgrt_tab->image_address, - sizeof(bmp_header)); - ioremapped = true; - if (!image) { - pr_err("Ignoring BGRT: failed to map image header memory\n"); - return; - } + pr_err("Ignoring BGRT: failed to map image header memory\n"); + return; } - memcpy_fromio(&bmp_header, image, sizeof(bmp_header)); - if (ioremapped) - early_iounmap(image, sizeof(bmp_header)); + memcpy(&bmp_header, image, sizeof(bmp_header)); + early_memunmap(image, sizeof(bmp_header)); bgrt_image_size = bmp_header.size; bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL | __GFP_NOWARN); @@ -96,18 +89,14 @@ void __init efi_bgrt_init(void) return; } - if (ioremapped) { - image = early_ioremap(bgrt_tab->image_address, - bmp_header.size); - if (!image) { - pr_err("Ignoring BGRT: failed to map image memory\n"); - kfree(bgrt_image); - bgrt_image = NULL; - return; - } + image = early_memremap(bgrt_tab->image_address, bmp_header.size); + if (!image) { + pr_err("Ignoring BGRT: failed to map image memory\n"); + kfree(bgrt_image); + bgrt_image = NULL; + return; } - memcpy_fromio(bgrt_image, image, bgrt_image_size); - if (ioremapped) - early_iounmap(image, bmp_header.size); + memcpy(bgrt_image, image, bgrt_image_size); + early_memunmap(image, bmp_header.size); } diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 027ca212179f..e9c458ba9353 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -324,38 +324,6 @@ u64 __init efi_mem_desc_end(efi_memory_desc_t *md) return end; } -/* - * We can't ioremap data in EFI boot services RAM, because we've already mapped - * it as RAM. So, look it up in the existing EFI memory map instead. Only - * callable after efi_enter_virtual_mode and before efi_free_boot_services. - */ -void __iomem *efi_lookup_mapped_addr(u64 phys_addr) -{ - struct efi_memory_map *map; - void *p; - map = efi.memmap; - if (!map) - return NULL; - if (WARN_ON(!map->map)) - return NULL; - for (p = map->map; p < map->map_end; p += map->desc_size) { - efi_memory_desc_t *md = p; - u64 size = md->num_pages << EFI_PAGE_SHIFT; - u64 end = md->phys_addr + size; - if (!(md->attribute & EFI_MEMORY_RUNTIME) && - md->type != EFI_BOOT_SERVICES_CODE && - md->type != EFI_BOOT_SERVICES_DATA) - continue; - if (!md->virt_addr) - continue; - if (phys_addr >= md->phys_addr && phys_addr < end) { - phys_addr += md->virt_addr - md->phys_addr; - return (__force void __iomem *)(unsigned long)phys_addr; - } - } - return NULL; -} - static __initdata efi_config_table_type_t common_tables[] = { {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20}, {ACPI_TABLE_GUID, "ACPI", &efi.acpi}, -- cgit v1.2.3 From 06e668ac91c93eb10bd21dfcc8891493722db29a Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Wed, 16 Dec 2015 19:18:37 +0200 Subject: drm/i915: Apply broader WaRsDisableCoarsePowerGating for guc also commit 344df9809f45 ("drm/i915/skl: Disable coarse power gating up until F0") failed to take into account that the same workaround is used in guc when forcewake is sampled. Wrap the condition check inside a macro and use it in both places to fix the guc side scope. Cc: Dave Gordon Cc: Sagar Arun Kamble Reviewed-by: Sagar Arun Kamble Signed-off-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1450286318-6854-1-git-send-email-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 5 +++++ drivers/gpu/drm/i915/i915_guc_submission.c | 6 ++---- drivers/gpu/drm/i915/intel_pm.c | 4 +--- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f0f75d7c0d94..9b82c4532893 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2576,6 +2576,11 @@ struct drm_i915_cmd_table { /* Early gen2 have a totally busted CS tlb and require pinned batches. */ #define HAS_BROKEN_CS_TLB(dev) (IS_I830(dev) || IS_845G(dev)) + +/* WaRsDisableCoarsePowerGating:skl,bxt */ +#define NEEDS_WaRsDisableCoarsePowerGating(dev) (IS_BXT_REVID(dev, 0, BXT_REVID_A1) || \ + ((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) && \ + IS_SKL_REVID(dev, 0, SKL_REVID_F0))) /* * dp aux and gmbus irq on gen4 seems to be able to generate legacy interrupts * even when in MSI mode. This results in spurious interrupt warnings if the diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 05aa7e61cbe0..9cc3b8474dae 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -158,10 +158,8 @@ static int host2guc_sample_forcewake(struct intel_guc *guc, data[0] = HOST2GUC_ACTION_SAMPLE_FORCEWAKE; /* WaRsDisableCoarsePowerGating:skl,bxt */ - if (!intel_enable_rc6(dev_priv->dev) || - IS_BXT_REVID(dev, 0, BXT_REVID_A1) || - (IS_SKL_GT3(dev) && IS_SKL_REVID(dev, 0, SKL_REVID_E0)) || - (IS_SKL_GT4(dev) && IS_SKL_REVID(dev, 0, SKL_REVID_E0))) + if (!intel_enable_rc6(dev) || + NEEDS_WaRsDisableCoarsePowerGating(dev)) data[1] = 0; else /* bit 0 and 1 are for Render and Media domain separately */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8d0d6f59a72b..02fe081878ad 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4713,9 +4713,7 @@ static void gen9_enable_rc6(struct drm_device *dev) * 3b: Enable Coarse Power Gating only when RC6 is enabled. * WaRsDisableCoarsePowerGating:skl,bxt - Render/Media PG need to be disabled with RC6. */ - if (IS_BXT_REVID(dev, 0, BXT_REVID_A1) || - ((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) && - IS_SKL_REVID(dev, 0, SKL_REVID_F0))) + if (NEEDS_WaRsDisableCoarsePowerGating(dev)) I915_WRITE(GEN9_PG_ENABLE, 0); else I915_WRITE(GEN9_PG_ENABLE, (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? -- cgit v1.2.3 From c08ae18560aaed50fed306a2e11f36ce70130f65 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sat, 19 Dec 2015 14:14:54 +0100 Subject: iio-light: Use a signed return type for ltr501_match_samp_freq() The return type "unsigned int" was used by the ltr501_match_samp_freq() function despite of the aspect that it will eventually return a negative error code. Improve this implementation detail by deletion of the type modifier then. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Acked-by: Peter Meerwald-Stadler Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/light/ltr501.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index 809a961b9a7f..6bf89d8f3741 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -180,7 +180,7 @@ static const struct ltr501_samp_table ltr501_ps_samp_table[] = { {500000, 2000000} }; -static unsigned int ltr501_match_samp_freq(const struct ltr501_samp_table *tab, +static int ltr501_match_samp_freq(const struct ltr501_samp_table *tab, int len, int val, int val2) { int i, freq; -- cgit v1.2.3 From c140330b5e6b5bc2262ffb2f50bfeea06a482699 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 18 Nov 2015 15:19:39 +0000 Subject: drm/i915: Move Braswell stop_machine GGTT insertion workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There was a silent conflict between commit 0a878716265e9af9f697264dc2e858fcc060d833 Author: Daniel Vetter Date: Thu Oct 15 14:23:01 2015 +0200 drm/i915: restore ggtt double-bind avoidance and commit 5bab6f60cb4d1417ad7c599166bcfec87529c1a2 Author: Chris Wilson Date: Fri Oct 23 18:43:32 2015 +0100 drm/i915: Serialise updates to GGTT with access through GGTT on Braswell thankfully caught by the extra WARN safegaurd in 0a878716. Since we now override the GGTT insert_pages callback when installing the aliasing ppgtt, we assert that the callback is the original ggtt routine. However, on Braswell we now use a different insertion routine to serialise access through the GGTT with updating the PTE and hence the conflict. To avoid the conflict, move the custom insertion routine for Braswell down a level. Reported-by: Ville Syrjälä Cc: Ville Syrjälä Cc: Michel Thierry Cc: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1447859979-20107-1-git-send-email-chris@chris-wilson.co.uk Reviewed-by: Ville Syrjälä Tested-by: Ville Syrjälä Cc: drm-intel-fixes@lists.freedesktop.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 50 +++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 52bc6c3dfe04..56f4f2e58d53 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2384,6 +2384,32 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); } +struct insert_entries { + struct i915_address_space *vm; + struct sg_table *st; + uint64_t start; + enum i915_cache_level level; + u32 flags; +}; + +static int gen8_ggtt_insert_entries__cb(void *_arg) +{ + struct insert_entries *arg = _arg; + gen8_ggtt_insert_entries(arg->vm, arg->st, + arg->start, arg->level, arg->flags); + return 0; +} + +static void gen8_ggtt_insert_entries__BKL(struct i915_address_space *vm, + struct sg_table *st, + uint64_t start, + enum i915_cache_level level, + u32 flags) +{ + struct insert_entries arg = { vm, st, start, level, flags }; + stop_machine(gen8_ggtt_insert_entries__cb, &arg, NULL); +} + /* * Binds an object into the global gtt with the specified cache level. The object * will be accessible to the GPU via commands whose operands reference offsets @@ -2560,26 +2586,6 @@ static int ggtt_bind_vma(struct i915_vma *vma, return 0; } -struct ggtt_bind_vma__cb { - struct i915_vma *vma; - enum i915_cache_level cache_level; - u32 flags; -}; - -static int ggtt_bind_vma__cb(void *_arg) -{ - struct ggtt_bind_vma__cb *arg = _arg; - return ggtt_bind_vma(arg->vma, arg->cache_level, arg->flags); -} - -static int ggtt_bind_vma__BKL(struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags) -{ - struct ggtt_bind_vma__cb arg = { vma, cache_level, flags }; - return stop_machine(ggtt_bind_vma__cb, &arg, NULL); -} - static int aliasing_gtt_bind_vma(struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags) @@ -3048,8 +3054,8 @@ static int gen8_gmch_probe(struct drm_device *dev, dev_priv->gtt.base.bind_vma = ggtt_bind_vma; dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma; - if (IS_CHERRYVIEW(dev)) - dev_priv->gtt.base.bind_vma = ggtt_bind_vma__BKL; + if (IS_CHERRYVIEW(dev_priv)) + dev_priv->gtt.base.insert_entries = gen8_ggtt_insert_entries__BKL; return ret; } -- cgit v1.2.3 From 61fb3980dd396880ffba48523b1e27579868b82b Mon Sep 17 00:00:00 2001 From: Gary Wang Date: Tue, 15 Dec 2015 12:40:30 +0800 Subject: drm/i915: Correct max delay for HDMI hotplug live status checking The total delay of HDMI hotplug detecting with 30ms have already been split into a resolution of 3 retries of 10ms each, for the worst cases. But it still suffered from only waiting 10ms at most in intel_hdmi_detect(). This patch corrects it by reading hotplug status with 4 times at most for 30ms delay. v2: - straight up to loop execution for more clear in code readability - mdelay will replace with msleep by Daniel's new patch drm/i915: mdelay(10) considered harmful - suggest to re-evaluate try times for being compatible to old HDMI monitor Reviewed-by: Cooper Chiou Tested-by: Gary Wang Cc: Jani Nikula Cc: Daniel Vetter Cc: Gavin Hindman Cc: Sonika Jindal Cc: Shashank Sharma Signed-off-by: Gary Wang [danvet: fixup conflict with s/mdelay/msleep/ patch.] Cc: drm-intel-fixes@lists.freedesktop.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 478e31fda067..79ebce2f68b1 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1385,17 +1385,18 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); struct drm_i915_private *dev_priv = to_i915(connector->dev); bool live_status = false; - unsigned int retry = 3; + unsigned int try; DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); - while (!live_status && --retry) { + for (try = 0; !live_status && try < 4; try++) { + if (try) + msleep(10); live_status = intel_digital_port_connected(dev_priv, hdmi_to_dig_port(intel_hdmi)); - msleep(10); } if (!live_status) -- cgit v1.2.3 From 1a5a9ce70f088d1c7e8e3b2c8f92cac876d8f9df Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 17 Dec 2015 09:49:57 -0800 Subject: drm/i915: Limit VF cache invalidate workaround usage to gen9 It is unclear if this is even required on BXT. v2: Make sure to set the default value to false. Uncertain how my compiler doesn't complain with v1. Cc: Imre Deak Signed-off-by: Ben Widawsky Link: http://patchwork.freedesktop.org/patch/msgid/1450374597-7021-1-git-send-email-benjamin.widawsky@intel.com Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 3aa614731d7e..ca5c0e8a3bf5 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1698,7 +1698,7 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request, struct intel_ringbuffer *ringbuf = request->ringbuf; struct intel_engine_cs *ring = ringbuf->ring; u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; - bool vf_flush_wa; + bool vf_flush_wa = false; u32 flags = 0; int ret; @@ -1719,14 +1719,14 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request, flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; flags |= PIPE_CONTROL_QW_WRITE; flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; - } - /* - * On GEN9+ Before VF_CACHE_INVALIDATE we need to emit a NULL pipe - * control. - */ - vf_flush_wa = INTEL_INFO(ring->dev)->gen >= 9 && - flags & PIPE_CONTROL_VF_CACHE_INVALIDATE; + /* + * On GEN9: before VF_CACHE_INVALIDATE we need to emit a NULL + * pipe control. + */ + if (IS_GEN9(ring->dev)) + vf_flush_wa = true; + } ret = intel_logical_ring_begin(request, vf_flush_wa ? 12 : 6); if (ret) -- cgit v1.2.3 From c838d719d62592e8cb519ffbdd36311e44e9cb53 Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Fri, 18 Dec 2015 13:08:15 +0200 Subject: drm/i915: Decouple struct i915_params i915 into i915_params.h Otherwise usage in the i915 debug macros yields problems due to i915_drv.h <-> i915_trace.h <-> intel_drv.h include loops. v2: - Document not-so-obvious need for linux/cache.h (Chris) Reviewed-by: Chris Wilson Signed-off-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/1450436898-20408-2-git-send-email-joonas.lahtinen@linux.intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 40 ++-------------------- drivers/gpu/drm/i915/i915_params.c | 1 + drivers/gpu/drm/i915/i915_params.h | 68 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 38 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_params.h (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9b82c4532893..89788dead96a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -34,6 +34,7 @@ #include #include +#include "i915_params.h" #include "i915_reg.h" #include "intel_bios.h" #include "intel_ringbuffer.h" @@ -2670,44 +2671,7 @@ extern int i915_max_ioctl; extern int i915_suspend_switcheroo(struct drm_device *dev, pm_message_t state); extern int i915_resume_switcheroo(struct drm_device *dev); -/* i915_params.c */ -struct i915_params { - int modeset; - int panel_ignore_lid; - int semaphores; - int lvds_channel_mode; - int panel_use_ssc; - int vbt_sdvo_panel_type; - int enable_rc6; - int enable_dc; - int enable_fbc; - int enable_ppgtt; - int enable_execlists; - int enable_psr; - unsigned int preliminary_hw_support; - int disable_power_well; - int enable_ips; - int invert_brightness; - int enable_cmd_parser; - /* leave bools at the end to not create holes */ - bool enable_hangcheck; - bool fastboot; - bool prefault_disable; - bool load_detect_test; - bool reset; - bool disable_display; - bool disable_vtd_wa; - bool enable_guc_submission; - int guc_log_level; - int use_mmio_flip; - int mmio_debug; - bool verbose_state_checks; - bool nuclear_pageflip; - int edp_vswing; -}; -extern struct i915_params i915 __read_mostly; - - /* i915_dma.c */ +/* i915_dma.c */ extern int i915_driver_load(struct drm_device *, unsigned long flags); extern int i915_driver_unload(struct drm_device *); extern int i915_driver_open(struct drm_device *dev, struct drm_file *file); diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 835d6099c769..8d90c256520a 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -22,6 +22,7 @@ * IN THE SOFTWARE. */ +#include "i915_params.h" #include "i915_drv.h" struct i915_params i915 __read_mostly = { diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h new file mode 100644 index 000000000000..353951c13049 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_params.h @@ -0,0 +1,68 @@ +/* + * Copyright © 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef _I915_PARAMS_H_ +#define _I915_PARAMS_H_ + +#include /* for __read_mostly */ + +struct i915_params { + int modeset; + int panel_ignore_lid; + int semaphores; + int lvds_channel_mode; + int panel_use_ssc; + int vbt_sdvo_panel_type; + int enable_rc6; + int enable_dc; + int enable_fbc; + int enable_ppgtt; + int enable_execlists; + int enable_psr; + unsigned int preliminary_hw_support; + int disable_power_well; + int enable_ips; + int invert_brightness; + int enable_cmd_parser; + /* leave bools at the end to not create holes */ + bool enable_hangcheck; + bool fastboot; + bool prefault_disable; + bool load_detect_test; + bool reset; + bool disable_display; + bool disable_vtd_wa; + bool enable_guc_submission; + int guc_log_level; + int use_mmio_flip; + int mmio_debug; + bool verbose_state_checks; + bool nuclear_pageflip; + int edp_vswing; +}; + +extern struct i915_params i915 __read_mostly; + +#endif + -- cgit v1.2.3 From 482bfe5cc707b5bf5fb40d76377110fac125adee Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Fri, 18 Dec 2015 13:08:16 +0200 Subject: drm/i915: Reorder i915_params struct. Move all the bool variables to the end as per the comment. Reviewed-by: Chris Wilson Signed-off-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/1450436898-20408-3-git-send-email-joonas.lahtinen@linux.intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_params.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 353951c13049..529929073120 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -45,6 +45,10 @@ struct i915_params { int enable_ips; int invert_brightness; int enable_cmd_parser; + int guc_log_level; + int use_mmio_flip; + int mmio_debug; + int edp_vswing; /* leave bools at the end to not create holes */ bool enable_hangcheck; bool fastboot; @@ -54,12 +58,8 @@ struct i915_params { bool disable_display; bool disable_vtd_wa; bool enable_guc_submission; - int guc_log_level; - int use_mmio_flip; - int mmio_debug; bool verbose_state_checks; bool nuclear_pageflip; - int edp_vswing; }; extern struct i915_params i915 __read_mostly; -- cgit v1.2.3 From b29ec92c4f5e6d45d8bae8194e664427a01c6687 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 18 Dec 2015 19:24:39 +0200 Subject: drm/i915: Workaround CHV pipe C cursor fail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turns out CHV pipe C was glued on somewhat poorly, and there's something wrong with the cursor. If the cursor straddles the left screen edge, and is then moved away from the edge or disabled, the pipe will often underrun. If enough underruns are triggered quickly enough the pipe will fall over and die (it just scans out a solid color and reports a constant underrun). We need to turn the disp2d power well off and on again to recover the pipe. None of that is very nice for the user, so let's just refuse to place the cursor in the compromised position. The ddx appears to fall back to swcursor when the ioctl returns an error, so theoretically there's no loss of functionality for the user (discounting swcursor bugs). I suppose most cursors images actually have the hotspot not exactly at 0,0 so under typical conditions the fallback will in fact kick in as soon as the cursor touches the left edge of the screen. Any atomic compositor should anyway be prepared to fall back to GPU composition when things don't work out, so there should be no problem with those. Other things that I tried to solve this include flipping all display related clock gating knobs I could find, increasing the minimum gtt alignment all the way up to 512k. I also tried to see if there are more specific screen coordinates that hit the bug, but the findings were somewhat inconclusive. Sometimes the failures happen almost across the whole left edge, sometimes more at the very top and around the bottom half. I wasn't able to find any real pattern to these variations, so it seems our only choice is to just refuse to straddle the left screen edge at all. Cc: stable@vger.kernel.org Cc: Jason Plum Testcase: igt/kms_chv_cursor_fail Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92826 Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1450459479-16286-1-git-send-email-ville.syrjala@linux.intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 11af6f52b3e4..7d01b986a012 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14059,6 +14059,7 @@ intel_check_cursor_plane(struct drm_plane *plane, struct drm_crtc *crtc = crtc_state->base.crtc; struct drm_framebuffer *fb = state->base.fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); + enum pipe pipe = to_intel_plane(plane)->pipe; unsigned stride; int ret; @@ -14092,6 +14093,22 @@ intel_check_cursor_plane(struct drm_plane *plane, return -EINVAL; } + /* + * There's something wrong with the cursor on CHV pipe C. + * If it straddles the left edge of the screen then + * moving it away from the edge or disabling it often + * results in a pipe underrun, and often that can lead to + * dead pipe (constant underrun reported, and it scans + * out just a solid color). To recover from that, the + * display power well must be turned off and on again. + * Refuse the put the cursor into that compromised position. + */ + if (IS_CHERRYVIEW(plane->dev) && pipe == PIPE_C && + state->visible && state->base.crtc_x < 0) { + DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n"); + return -EINVAL; + } + return 0; } -- cgit v1.2.3 From 4601b933c9dcb6802e3289d62bcdb52ea32425d6 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sat, 19 Dec 2015 15:40:39 +0100 Subject: drm/i915: Remove obsolete code from intelfb_alloc() Clean up after 0c82312f3f15 ("drm/i915: Pin the ifbdev for the info->system_base GGTT mmapping"): At each of the remaining "goto out" in intelfb_alloc(), fb can only be either an ERR_PTR or NULL, so the call to drm_framebuffer_unreference() is now obsolete. Cc: Daniel Vetter Cc: Chris Wilson Signed-off-by: Lukas Wunner Link: http://patchwork.freedesktop.org/patch/msgid/56756c41.c306c20a.d0602.1830SMTPIN_ADDED_MISSING@mx.google.com Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_fbdev.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index bea75cafc623..09840f4380f9 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -119,7 +119,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper, { struct intel_fbdev *ifbdev = container_of(helper, struct intel_fbdev, helper); - struct drm_framebuffer *fb = NULL; + struct drm_framebuffer *fb; struct drm_device *dev = helper->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct drm_mode_fb_cmd2 mode_cmd = {}; @@ -171,8 +171,6 @@ static int intelfb_alloc(struct drm_fb_helper *helper, out: mutex_unlock(&dev->struct_mutex); - if (!IS_ERR_OR_NULL(fb)) - drm_framebuffer_unreference(fb); return ret; } -- cgit v1.2.3 From 32753cb863af32eadc63330a6b9eaa481f83d341 Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Fri, 18 Dec 2015 14:27:26 +0200 Subject: drm/i915: Simplify _STATE_ debug macros Take advantage of WARN return value to simplify the flow. Cc: Rob Clark Reviewed-by: Chris Wilson Reported-by: Chris Wilson Signed-off-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/1450441647-23924-2-git-send-email-joonas.lahtinen@linux.intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 89788dead96a..e0782b0fed73 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -88,23 +88,18 @@ */ #define I915_STATE_WARN(condition, format...) ({ \ int __ret_warn_on = !!(condition); \ - if (unlikely(__ret_warn_on)) { \ - if (i915.verbose_state_checks) \ - WARN(1, format); \ - else \ + if (unlikely(__ret_warn_on)) \ + if (!WARN(i915.verbose_state_checks, format)) \ DRM_ERROR(format); \ - } \ unlikely(__ret_warn_on); \ }) #define I915_STATE_WARN_ON(condition) ({ \ int __ret_warn_on = !!(condition); \ - if (unlikely(__ret_warn_on)) { \ - if (i915.verbose_state_checks) \ - WARN(1, "WARN_ON(" #condition ")\n"); \ - else \ + if (unlikely(__ret_warn_on)) \ + if (!WARN(i915.verbose_state_checks, \ + "WARN_ON(" #condition ")\n")) \ DRM_ERROR("WARN_ON(" #condition ")\n"); \ - } \ unlikely(__ret_warn_on); \ }) -- cgit v1.2.3 From 152b22627c67c6e5f29ad6ec939ac7e6f52e6c7d Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Fri, 18 Dec 2015 14:27:27 +0200 Subject: drm/i915: Compile-time concatenate WARN_ON macro strings Using __stringify(x) instead of #x adds support for macros as a parameter and compile-time concatenation reduces the runtime overhead. Slightly increases the .text size but should not matter. v2: - Define I915_STATE_WARN_ON though I915_STATE_WARN (Bikeshed inspiration by Chris) v3: - More specific commit message v4: - Do not directly pass arbitary string as format, instead guard with "%s" (Dave) Cc: Rob Clark Cc: Dave Gordon Reviewed-by: Chris Wilson (v3) Acked-by: Daniel Vetter Signed-off-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/1450441647-23924-3-git-send-email-joonas.lahtinen@linux.intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e0782b0fed73..1d8279c220b4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -70,11 +70,11 @@ BUILD_BUG_ON(__i915_warn_cond); \ WARN(__i915_warn_cond, "WARN_ON(" #x ")"); }) #else -#define WARN_ON(x) WARN((x), "WARN_ON(%s)", #x ) +#define WARN_ON(x) WARN((x), "%s", "WARN_ON(" __stringify(x) ")") #endif #undef WARN_ON_ONCE -#define WARN_ON_ONCE(x) WARN_ONCE((x), "WARN_ON_ONCE(%s)", #x ) +#define WARN_ON_ONCE(x) WARN_ONCE((x), "%s", "WARN_ON_ONCE(" __stringify(x) ")") #define MISSING_CASE(x) WARN(1, "Missing switch case (%lu) in %s\n", \ (long) (x), __func__); @@ -94,14 +94,8 @@ unlikely(__ret_warn_on); \ }) -#define I915_STATE_WARN_ON(condition) ({ \ - int __ret_warn_on = !!(condition); \ - if (unlikely(__ret_warn_on)) \ - if (!WARN(i915.verbose_state_checks, \ - "WARN_ON(" #condition ")\n")) \ - DRM_ERROR("WARN_ON(" #condition ")\n"); \ - unlikely(__ret_warn_on); \ -}) +#define I915_STATE_WARN_ON(x) \ + I915_STATE_WARN((x), "%s", "WARN_ON(" __stringify(x) ")") static inline const char *yesno(bool v) { -- cgit v1.2.3 From 0bff4858653312a10c83709e0009c3adb87e6f1e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 10 Dec 2015 18:22:31 +0200 Subject: drm/i915: Unbreak check_digital_port_conflicts() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Atomic changes broke check_digital_port_conflicts(). It needs to look at the global situation instead of just trying to find a conflict within the current atomic state. This bug made my HSW explode spectacularly after I had split the DDI encoders into separate DP and HDMI encoders. With the fix, things seem much more solid. I hope holding the connection_mutex is enough protection that we can actually walk the connectors even if they're not part of the current atomic state... v2: Regenerate the patch so that it actually applies (Jani) Cc: stable@vger.kernel.org Cc: Ander Conselvan de Oliveira Fixes: 5448a00d3f06 ("drm/i915: Don't use staged config in check_digital_port_conflicts()") Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1449764551-12466-1-git-send-email-ville.syrjala@linux.intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_display.c | 12 ++++++++---- 1 file changed, 8 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 7d01b986a012..f1598f765e3a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12270,18 +12270,22 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, static bool check_digital_port_conflicts(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; - struct intel_encoder *encoder; struct drm_connector *connector; - struct drm_connector_state *connector_state; unsigned int used_ports = 0; - int i; /* * Walk the connector list instead of the encoder * list to detect the problem on ddi platforms * where there's just one encoder per digital port. */ - for_each_connector_in_state(state, connector, connector_state, i) { + drm_for_each_connector(connector, dev) { + struct drm_connector_state *connector_state; + struct intel_encoder *encoder; + + connector_state = drm_atomic_get_existing_connector_state(state, connector); + if (!connector_state) + connector_state = connector->state; + if (!connector_state->best_encoder) continue; -- cgit v1.2.3 From dd97950a4cb7218fac38570e2e12c57a2cfd8312 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Dec 2015 15:10:52 +0200 Subject: drm/i915/bios: add proper documentation for the Video BIOS Table (VBT) Add an overview and documentation for the VBT/BDB header structures. Acked-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/3d826d4600688ca3518713776ab5bd8a8fc9f20f.1450702954.git.jani.nikula@intel.com --- Documentation/DocBook/gpu.tmpl | 6 ++++++ drivers/gpu/drm/i915/intel_bios.c | 24 +++++++++++++++++++++++- drivers/gpu/drm/i915/intel_bios.h | 38 ++++++++++++++++++++++++++++---------- 3 files changed, 57 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl index 03f01e76add7..0061f22d126d 100644 --- a/Documentation/DocBook/gpu.tmpl +++ b/Documentation/DocBook/gpu.tmpl @@ -4108,6 +4108,12 @@ int num_ioctls; !Pdrivers/gpu/drm/i915/intel_csr.c csr support for dmc !Idrivers/gpu/drm/i915/intel_csr.c + + Video BIOS Table (VBT) +!Pdrivers/gpu/drm/i915/intel_bios.c Video BIOS Table (VBT) +!Idrivers/gpu/drm/i915/intel_bios.c +!Idrivers/gpu/drm/i915/intel_bios.h + diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index eba3e0f87181..b6ccba13779e 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -31,6 +31,28 @@ #include "i915_drv.h" #include "intel_bios.h" +/** + * DOC: Video BIOS Table (VBT) + * + * The Video BIOS Table, or VBT, provides platform and board specific + * configuration information to the driver that is not discoverable or available + * through other means. The configuration is mostly related to display + * hardware. The VBT is available via the ACPI OpRegion or, on older systems, in + * the PCI ROM. + * + * The VBT consists of a VBT Header (defined as &struct vbt_header), a BDB + * Header (&struct bdb_header), and a number of BIOS Data Blocks (BDB) that + * contain the actual configuration information. The VBT Header, and thus the + * VBT, begins with "$VBT" signature. The VBT Header contains the offset of the + * BDB Header. The data blocks are concatenated after the BDB Header. The data + * blocks have a 1-byte Block ID, 2-byte Block Size, and Block Size bytes of + * data. (Block 53, the MIPI Sequence Block is an exception.) + * + * The driver parses the VBT during load. The relevant information is stored in + * driver private data for ease of use, and the actual VBT is not read after + * that. + */ + #define SLAVE_ADDR1 0x70 #define SLAVE_ADDR2 0x72 @@ -1285,7 +1307,7 @@ static const struct vbt_header *find_vbt(void __iomem *bios, size_t size) /** * intel_bios_init - find VBT and initialize settings from the BIOS - * @dev: DRM device + * @dev_priv: i915 device instance * * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers * to appropriate values. diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 54eac1003a1e..2dc46a98c332 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -28,22 +28,40 @@ #ifndef _I830_BIOS_H_ #define _I830_BIOS_H_ +/** + * struct vbt_header - VBT Header structure + * @signature: VBT signature, always starts with "$VBT" + * @version: Version of this structure + * @header_size: Size of this structure + * @vbt_size: Size of VBT (VBT Header, BDB Header and data blocks) + * @vbt_checksum: Checksum + * @reserved0: Reserved + * @bdb_offset: Offset of &struct bdb_header from beginning of VBT + * @aim_offset: Offsets of add-in data blocks from beginning of VBT + */ struct vbt_header { - u8 signature[20]; /**< Always starts with 'VBT$' */ - u16 version; /**< decimal */ - u16 header_size; /**< in bytes */ - u16 vbt_size; /**< in bytes */ + u8 signature[20]; + u16 version; + u16 header_size; + u16 vbt_size; u8 vbt_checksum; u8 reserved0; - u32 bdb_offset; /**< from beginning of VBT */ - u32 aim_offset[4]; /**< from beginning of VBT */ + u32 bdb_offset; + u32 aim_offset[4]; } __packed; +/** + * struct bdb_header - BDB Header structure + * @signature: BDB signature "BIOS_DATA_BLOCK" + * @version: Version of the data block definitions + * @header_size: Size of this structure + * @bdb_size: Size of BDB (BDB Header and data blocks) + */ struct bdb_header { - u8 signature[16]; /**< Always 'BIOS_DATA_BLOCK' */ - u16 version; /**< decimal */ - u16 header_size; /**< in bytes */ - u16 bdb_size; /**< in bytes */ + u8 signature[16]; + u16 version; + u16 header_size; + u16 bdb_size; } __packed; /* strictly speaking, this is a "skip" block, but it has interesting info */ -- cgit v1.2.3 From bf8a0af0cc9f9de9e54aefd1afd8c23b91809e41 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 24 Nov 2015 11:29:02 +0100 Subject: drm/i915/skl: Do not allow scaling when crtc is disabled. This fixes a warning when the crtc is turned off. In that case fb will be NULL, and crtc_clock will be 0. Because the crtc is no longer active this is not a bug, and shouldn't trigger the WARN_ON. Also remove handling a null crtc_state, with all transitional helpers gone this can no longer happen. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1448360945-5723-2-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f1598f765e3a..9928ca4027be 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13850,7 +13850,7 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state struct drm_i915_private *dev_priv; int crtc_clock, cdclk; - if (!intel_crtc || !crtc_state) + if (!intel_crtc || !crtc_state->base.enable) return DRM_PLANE_HELPER_NO_SCALING; dev = intel_crtc->base.dev; -- cgit v1.2.3 From 565602d7501a3e83580289d7d6da9b15838cfbe3 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 10 Dec 2015 12:33:57 +0100 Subject: drm/i915: Do not acquire crtc state to check clock during modeset, v4. Parallel modesets are still not allowed, but this will allow updating a different crtc during a modeset if the clock is not changed. Additionally when all pipes are DPMS off the cdclk will be lowered to the minimum allowed. Changes since v1: - Add dev_priv->active_crtcs for tracking which crtcs are active. - Rename min_cdclk to min_pixclk and move to dev_priv. - Add a active_crtcs mask which is updated atomically. - Add intel_atomic_state->modeset which is set on modesets. - Commit new pixclk/active_crtcs right after state swap. Changes since v2: - Make the changes related to max_pixel_rate calculations more readable. Changes since v3: - Add cherryview and missing WARN_ON to readout. Signed-off-by: Maarten Lankhorst Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/i915_drv.h | 5 ++ drivers/gpu/drm/i915/intel_atomic.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 143 +++++++++++++++++++++++++---------- drivers/gpu/drm/i915/intel_drv.h | 7 +- 4 files changed, 116 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1d8279c220b4..73da52a20c82 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1819,8 +1819,13 @@ struct drm_i915_private { struct intel_pipe_crc pipe_crc[I915_MAX_PIPES]; #endif + /* dpll and cdclk state is protected by connection_mutex */ int num_shared_dpll; struct intel_shared_dpll shared_dplls[I915_NUM_PLLS]; + + unsigned int active_crtcs; + unsigned int min_pixclk[I915_MAX_PIPES]; + int dpio_phy_iosf_port[I915_NUM_PHYS_VLV]; struct i915_workarounds workarounds; diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index d0b1c9afa35e..4625f8a9ba12 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -308,5 +308,5 @@ void intel_atomic_state_clear(struct drm_atomic_state *s) { struct intel_atomic_state *state = to_intel_atomic_state(s); drm_atomic_state_default_clear(&state->base); - state->dpll_set = false; + state->dpll_set = state->modeset = false; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9928ca4027be..83320695a716 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6063,22 +6063,31 @@ static int broxton_calc_cdclk(struct drm_i915_private *dev_priv, static int intel_mode_max_pixclk(struct drm_device *dev, struct drm_atomic_state *state) { - struct intel_crtc *intel_crtc; - struct intel_crtc_state *crtc_state; - int max_pixclk = 0; + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + unsigned max_pixclk = 0, i; + enum pipe pipe; - for_each_intel_crtc(dev, intel_crtc) { - crtc_state = intel_atomic_get_crtc_state(state, intel_crtc); - if (IS_ERR(crtc_state)) - return PTR_ERR(crtc_state); + memcpy(intel_state->min_pixclk, dev_priv->min_pixclk, + sizeof(intel_state->min_pixclk)); - if (!crtc_state->base.enable) - continue; + for_each_crtc_in_state(state, crtc, crtc_state, i) { + int pixclk = 0; + + if (crtc_state->enable) + pixclk = crtc_state->adjusted_mode.crtc_clock; - max_pixclk = max(max_pixclk, - crtc_state->base.adjusted_mode.crtc_clock); + intel_state->min_pixclk[i] = pixclk; } + if (!intel_state->active_crtcs) + return 0; + + for_each_pipe(dev_priv, pipe) + max_pixclk = max(intel_state->min_pixclk[pipe], max_pixclk); + return max_pixclk; } @@ -6383,6 +6392,9 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) for_each_power_domain(domain, domains) intel_display_power_put(dev_priv, domain); intel_crtc->enabled_power_domains = 0; + + dev_priv->active_crtcs &= ~(1 << intel_crtc->pipe); + dev_priv->min_pixclk[intel_crtc->pipe] = 0; } /* @@ -9679,29 +9691,41 @@ static void broxton_modeset_commit_cdclk(struct drm_atomic_state *old_state) /* compute the max rate for new configuration */ static int ilk_max_pixel_rate(struct drm_atomic_state *state) { - struct intel_crtc *intel_crtc; + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); + struct drm_i915_private *dev_priv = state->dev->dev_private; + struct drm_crtc *crtc; + struct drm_crtc_state *cstate; struct intel_crtc_state *crtc_state; - int max_pixel_rate = 0; + unsigned max_pixel_rate = 0, i; + enum pipe pipe; - for_each_intel_crtc(state->dev, intel_crtc) { - int pixel_rate; + memcpy(intel_state->min_pixclk, dev_priv->min_pixclk, + sizeof(intel_state->min_pixclk)); - crtc_state = intel_atomic_get_crtc_state(state, intel_crtc); - if (IS_ERR(crtc_state)) - return PTR_ERR(crtc_state); + for_each_crtc_in_state(state, crtc, cstate, i) { + int pixel_rate; - if (!crtc_state->base.enable) + crtc_state = to_intel_crtc_state(cstate); + if (!crtc_state->base.enable) { + intel_state->min_pixclk[i] = 0; continue; + } pixel_rate = ilk_pipe_pixel_rate(crtc_state); /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */ - if (IS_BROADWELL(state->dev) && crtc_state->ips_enabled) + if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled) pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95); - max_pixel_rate = max(max_pixel_rate, pixel_rate); + intel_state->min_pixclk[i] = pixel_rate; } + if (!intel_state->active_crtcs) + return 0; + + for_each_pipe(dev_priv, pipe) + max_pixel_rate = max(intel_state->min_pixclk[pipe], max_pixel_rate); + return max_pixel_rate; } @@ -13208,15 +13232,27 @@ static int intel_modeset_all_pipes(struct drm_atomic_state *state) static int intel_modeset_checks(struct drm_atomic_state *state) { - struct drm_device *dev = state->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int ret; + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); + struct drm_i915_private *dev_priv = state->dev->dev_private; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + int ret = 0, i; if (!check_digital_port_conflicts(state)) { DRM_DEBUG_KMS("rejecting conflicting digital port configuration\n"); return -EINVAL; } + intel_state->modeset = true; + intel_state->active_crtcs = dev_priv->active_crtcs; + + for_each_crtc_in_state(state, crtc, crtc_state, i) { + if (crtc_state->active) + intel_state->active_crtcs |= 1 << i; + else + intel_state->active_crtcs &= ~(1 << i); + } + /* * See if the config requires any additional preparation, e.g. * to adjust global state with pipes off. We need to do this @@ -13240,7 +13276,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state) intel_modeset_clear_plls(state); - if (IS_HASWELL(dev)) + if (IS_HASWELL(dev_priv)) return haswell_mode_set_planes_workaround(state); return 0; @@ -13458,12 +13494,12 @@ static int intel_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, bool async) { + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc_state *crtc_state; struct drm_crtc *crtc; - int ret = 0; - int i; - bool any_ms = false; + int ret = 0, i; + bool hw_check = intel_state->modeset; ret = intel_atomic_prepare_commit(dev, state, async); if (ret) { @@ -13474,13 +13510,18 @@ static int intel_atomic_commit(struct drm_device *dev, drm_atomic_helper_swap_state(dev, state); dev_priv->wm.config = to_intel_atomic_state(state)->wm_config; + if (intel_state->modeset) { + memcpy(dev_priv->min_pixclk, intel_state->min_pixclk, + sizeof(intel_state->min_pixclk)); + dev_priv->active_crtcs = intel_state->active_crtcs; + } + for_each_crtc_in_state(state, crtc, crtc_state, i) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); if (!needs_modeset(crtc->state)) continue; - any_ms = true; intel_pre_plane_update(intel_crtc); if (crtc_state->active) { @@ -13505,7 +13546,7 @@ static int intel_atomic_commit(struct drm_device *dev, * update the the output configuration. */ intel_modeset_update_crtc_state(state); - if (any_ms) { + if (intel_state->modeset) { intel_shared_dpll_commit(state); drm_atomic_helper_update_legacy_modeset_state(state->dev, state); @@ -13532,7 +13573,7 @@ static int intel_atomic_commit(struct drm_device *dev, put_domains = modeset_get_crtc_power_domains(crtc); /* make sure intel_modeset_check_state runs */ - any_ms = true; + hw_check = true; } if (!modeset) @@ -13559,7 +13600,7 @@ static int intel_atomic_commit(struct drm_device *dev, drm_atomic_helper_cleanup_planes(dev, state); mutex_unlock(&dev->struct_mutex); - if (any_ms) + if (hw_check) intel_modeset_check_state(dev, state); drm_atomic_state_free(state); @@ -15591,16 +15632,40 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) struct intel_connector *connector; int i; + dev_priv->active_crtcs = 0; + for_each_intel_crtc(dev, crtc) { - __drm_atomic_helper_crtc_destroy_state(&crtc->base, crtc->base.state); - memset(crtc->config, 0, sizeof(*crtc->config)); - crtc->config->base.crtc = &crtc->base; + struct intel_crtc_state *crtc_state = crtc->config; + int pixclk = 0; - crtc->active = dev_priv->display.get_pipe_config(crtc, - crtc->config); + __drm_atomic_helper_crtc_destroy_state(&crtc->base, &crtc_state->base); + memset(crtc_state, 0, sizeof(*crtc_state)); + crtc_state->base.crtc = &crtc->base; - crtc->base.state->active = crtc->active; - crtc->base.enabled = crtc->active; + crtc_state->base.active = crtc_state->base.enable = + dev_priv->display.get_pipe_config(crtc, crtc_state); + + crtc->base.enabled = crtc_state->base.enable; + crtc->active = crtc_state->base.active; + + if (crtc_state->base.active) { + dev_priv->active_crtcs |= 1 << crtc->pipe; + + if (IS_BROADWELL(dev_priv)) { + pixclk = ilk_pipe_pixel_rate(crtc_state); + + /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */ + if (crtc_state->ips_enabled) + pixclk = DIV_ROUND_UP(pixclk * 100, 95); + } else if (IS_VALLEYVIEW(dev_priv) || + IS_CHERRYVIEW(dev_priv) || + IS_BROXTON(dev_priv)) + pixclk = crtc_state->base.adjusted_mode.crtc_clock; + else + WARN_ON(dev_priv->display.modeset_calc_cdclk); + } + + dev_priv->min_pixclk[crtc->pipe] = pixclk; readout_plane_state(crtc); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index d523ebb2f89d..9b051e908845 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -246,7 +246,12 @@ struct intel_atomic_state { struct drm_atomic_state base; unsigned int cdclk; - bool dpll_set; + + bool dpll_set, modeset; + + unsigned int active_crtcs; + unsigned int min_pixclk[I915_MAX_PIPES]; + struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS]; struct intel_wm_config wm_config; }; -- cgit v1.2.3 From 1a617b77658e0ab1cb58a9412c5a02f862bd4fcd Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 3 Dec 2015 14:31:06 +0100 Subject: drm/i915: Keep track of the cdclk as if all crtc's were active. On skylake when calculating plane visibility with the crtc in dpms off mode the real cdclk may be different from what it would be if the crtc was active. This may result in a WARN_ON(cdclk < crtc_clock) from skl_max_scale. The fix is to keep a atomic_cdclk that would be true if all crtc's were active. This is required to get the same calculations done correctly regardless of dpms mode. Signed-off-by: Maarten Lankhorst Reviewed-by: Mika Kahola Link: http://patchwork.freedesktop.org/patch/msgid/1447945645-32005-12-git-send-email-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_display.c | 55 ++++++++++++++++++++++++------------ drivers/gpu/drm/i915/intel_drv.h | 6 ++++ 3 files changed, 44 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 73da52a20c82..cf7e0fce01ac 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1774,7 +1774,7 @@ struct drm_i915_private { unsigned int fsb_freq, mem_freq, is_ddr3; unsigned int skl_boot_cdclk; - unsigned int cdclk_freq, max_cdclk_freq; + unsigned int cdclk_freq, max_cdclk_freq, atomic_cdclk_freq; unsigned int max_dotclk_freq; unsigned int hpll_freq; unsigned int czclk_freq; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 83320695a716..30cd48ea61e8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5370,6 +5370,7 @@ static void modeset_put_power_domains(struct drm_i915_private *dev_priv, static void modeset_update_crtc_power_domains(struct drm_atomic_state *state) { + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); struct drm_device *dev = state->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned long put_domains[I915_MAX_PIPES] = {}; @@ -5383,13 +5384,9 @@ static void modeset_update_crtc_power_domains(struct drm_atomic_state *state) modeset_get_crtc_power_domains(crtc); } - if (dev_priv->display.modeset_commit_cdclk) { - unsigned int cdclk = to_intel_atomic_state(state)->cdclk; - - if (cdclk != dev_priv->cdclk_freq && - !WARN_ON(!state->allow_modeset)) - dev_priv->display.modeset_commit_cdclk(state); - } + if (dev_priv->display.modeset_commit_cdclk && + intel_state->dev_cdclk != dev_priv->cdclk_freq) + dev_priv->display.modeset_commit_cdclk(state); for (i = 0; i < I915_MAX_PIPES; i++) if (put_domains[i]) @@ -6096,13 +6093,18 @@ static int valleyview_modeset_calc_cdclk(struct drm_atomic_state *state) struct drm_device *dev = state->dev; struct drm_i915_private *dev_priv = dev->dev_private; int max_pixclk = intel_mode_max_pixclk(dev, state); + struct intel_atomic_state *intel_state = + to_intel_atomic_state(state); if (max_pixclk < 0) return max_pixclk; - to_intel_atomic_state(state)->cdclk = + intel_state->cdclk = intel_state->dev_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk); + if (!intel_state->active_crtcs) + intel_state->dev_cdclk = valleyview_calc_cdclk(dev_priv, 0); + return 0; } @@ -6111,13 +6113,18 @@ static int broxton_modeset_calc_cdclk(struct drm_atomic_state *state) struct drm_device *dev = state->dev; struct drm_i915_private *dev_priv = dev->dev_private; int max_pixclk = intel_mode_max_pixclk(dev, state); + struct intel_atomic_state *intel_state = + to_intel_atomic_state(state); if (max_pixclk < 0) return max_pixclk; - to_intel_atomic_state(state)->cdclk = + intel_state->cdclk = intel_state->dev_cdclk = broxton_calc_cdclk(dev_priv, max_pixclk); + if (!intel_state->active_crtcs) + intel_state->dev_cdclk = broxton_calc_cdclk(dev_priv, 0); + return 0; } @@ -6160,8 +6167,10 @@ static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv) static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state) { struct drm_device *dev = old_state->dev; - unsigned int req_cdclk = to_intel_atomic_state(old_state)->cdclk; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_atomic_state *old_intel_state = + to_intel_atomic_state(old_state); + unsigned req_cdclk = old_intel_state->dev_cdclk; /* * FIXME: We can end up here with all power domains off, yet @@ -9683,7 +9692,9 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv) static void broxton_modeset_commit_cdclk(struct drm_atomic_state *old_state) { struct drm_device *dev = old_state->dev; - unsigned int req_cdclk = to_intel_atomic_state(old_state)->cdclk; + struct intel_atomic_state *old_intel_state = + to_intel_atomic_state(old_state); + unsigned int req_cdclk = old_intel_state->dev_cdclk; broxton_set_cdclk(dev, req_cdclk); } @@ -9809,6 +9820,7 @@ static void broadwell_set_cdclk(struct drm_device *dev, int cdclk) static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(state->dev); + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); int max_pixclk = ilk_max_pixel_rate(state); int cdclk; @@ -9831,7 +9843,9 @@ static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state) return -EINVAL; } - to_intel_atomic_state(state)->cdclk = cdclk; + intel_state->cdclk = intel_state->dev_cdclk = cdclk; + if (!intel_state->active_crtcs) + intel_state->dev_cdclk = 337500; return 0; } @@ -9839,7 +9853,9 @@ static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state) static void broadwell_modeset_commit_cdclk(struct drm_atomic_state *old_state) { struct drm_device *dev = old_state->dev; - unsigned int req_cdclk = to_intel_atomic_state(old_state)->cdclk; + struct intel_atomic_state *old_intel_state = + to_intel_atomic_state(old_state); + unsigned req_cdclk = old_intel_state->dev_cdclk; broadwell_set_cdclk(dev, req_cdclk); } @@ -13261,18 +13277,15 @@ static int intel_modeset_checks(struct drm_atomic_state *state) * adjusted_mode bits in the crtc directly. */ if (dev_priv->display.modeset_calc_cdclk) { - unsigned int cdclk; - ret = dev_priv->display.modeset_calc_cdclk(state); - cdclk = to_intel_atomic_state(state)->cdclk; - if (!ret && cdclk != dev_priv->cdclk_freq) + if (!ret && intel_state->dev_cdclk != dev_priv->cdclk_freq) ret = intel_modeset_all_pipes(state); if (ret < 0) return ret; } else - to_intel_atomic_state(state)->cdclk = dev_priv->cdclk_freq; + to_intel_atomic_state(state)->cdclk = dev_priv->atomic_cdclk_freq; intel_modeset_clear_plls(state); @@ -13514,6 +13527,7 @@ static int intel_atomic_commit(struct drm_device *dev, memcpy(dev_priv->min_pixclk, intel_state->min_pixclk, sizeof(intel_state->min_pixclk)); dev_priv->active_crtcs = intel_state->active_crtcs; + dev_priv->atomic_cdclk_freq = intel_state->cdclk; } for_each_crtc_in_state(state, crtc, crtc_state, i) { @@ -15235,7 +15249,12 @@ static void i915_disable_vga(struct drm_device *dev) void intel_modeset_init_hw(struct drm_device *dev) { + struct drm_i915_private *dev_priv = dev->dev_private; + intel_update_cdclk(dev); + + dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq; + intel_prepare_ddi(dev); intel_init_clock_gating(dev); intel_enable_gt_powersave(dev); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 9b051e908845..0438b575e1fa 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -247,6 +247,12 @@ struct intel_atomic_state { unsigned int cdclk; + /* + * Calculated device cdclk, can be different from cdclk + * only when all crtc's are DPMS off. + */ + unsigned int dev_cdclk; + bool dpll_set, modeset; unsigned int active_crtcs; -- cgit v1.2.3 From 35c08f43462206efb999ebc2478443e8d611161d Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 3 Dec 2015 14:31:07 +0100 Subject: drm/i915: Calculate visibility in check_plane correctly regardless of dpms. When the crtc is configured but not active we currently clip to (0,0)x(0,0). This results in differences in calculations depending on dpms setting. When the crtc is enabled but not active run check_plane as if it were on, but afterwards set plane_state->visible = false for the checks. Signed-off-by: Maarten Lankhorst Reviewed-by: Mika Kahola Link: http://patchwork.freedesktop.org/patch/msgid/1447945645-32005-13-git-send-email-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic_plane.c | 4 ++-- drivers/gpu/drm/i915/intel_display.c | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index c6bb0fc1edfb..856c3118bb87 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -152,9 +152,9 @@ static int intel_plane_atomic_check(struct drm_plane *plane, intel_state->clip.x1 = 0; intel_state->clip.y1 = 0; intel_state->clip.x2 = - crtc_state->base.active ? crtc_state->pipe_src_w : 0; + crtc_state->base.enable ? crtc_state->pipe_src_w : 0; intel_state->clip.y2 = - crtc_state->base.active ? crtc_state->pipe_src_h : 0; + crtc_state->base.enable ? crtc_state->pipe_src_h : 0; if (state->fb && intel_rotation_90_or_270(state->rotation)) { if (!(state->fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 30cd48ea61e8..eea2cd26ba17 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11873,8 +11873,13 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, if (!was_crtc_enabled && WARN_ON(was_visible)) was_visible = false; - if (!is_crtc_enabled && WARN_ON(visible)) - visible = false; + /* + * Visibility is calculated as if the crtc was on, but + * after scaler setup everything depends on it being off + * when the crtc isn't active. + */ + if (!is_crtc_enabled) + to_intel_plane_state(plane_state)->visible = visible = false; if (!was_visible && !visible) return 0; -- cgit v1.2.3 From f8d03ea0053b23de42c828d559016eabe0b91523 Mon Sep 17 00:00:00 2001 From: Gary Wang Date: Wed, 23 Dec 2015 16:11:35 +0800 Subject: drm/i915: increase the tries for HDMI hotplug live status checking The total delay of HDMI hotplug detecting with 30ms is sometimes not enoughtfor HDMI live status up with specific HDMI monitors in BSW platform. After doing experiments for following monitors, it needs 80ms at least for those worst cases. Lenovo L246 1xwA (4 failed, necessary hot-plug delay: 58/40/60/40ms) Philips HH2AP (9 failed, necessary hot-plug delay: 80/50/50/60/46/40/58/58/39ms) BENQ ET-0035-N (6 failed, necessary hot-plug delay: 60/50/50/80/80/40ms) DELL U2713HM (2 failed, necessary hot-plug delay: 58/59ms) HP HP-LP2475w (5 failed, necessary hot-plug delay: 70/50/40/60/40ms) It looks like 70-80 ms is BSW platform needs in some bad cases of the monitors at this end (8 times delay at most). Keep less than 100ms for HDCP pulse HPD low (with at least 100ms) to respond a plug out. Reviewed-by: Cooper Chiou Tested-by: Gary Wang Cc: Gavin Hindman Cc: Sonika Jindal Cc: Shashank Sharma Cc: Shobhit Kumar Signed-off-by: Gary Wang Link: http://patchwork.freedesktop.org/patch/msgid/1450858295-12804-1-git-send-email-gary.c.wang@intel.com Tested-by: Shobhit Kumar Cc: drm-intel-fixes@lists.freedesktop.org Fixes: 237ed86c693d ("drm/i915: Check live status before reading edid") Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 drivers/gpu/drm/i915/intel_hdmi.c (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c old mode 100644 new mode 100755 index 79ebce2f68b1..054aa7613390 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1392,7 +1392,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); - for (try = 0; !live_status && try < 4; try++) { + for (try = 0; !live_status && try < 9; try++) { if (try) msleep(10); live_status = intel_digital_port_connected(dev_priv, -- cgit v1.2.3 From eba51190f3c6ffcb685fc100a4234095b0146150 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 29 Dec 2015 14:20:43 -0800 Subject: drm/i915: Fix whitespace (trivial) Signed-off-by: Ben Widawsky Link: http://patchwork.freedesktop.org/patch/msgid/1451427643-7266-1-git-send-email-benjamin.widawsky@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_lrc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index ca5c0e8a3bf5..973487a73be1 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -538,8 +538,8 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring) WARN(1, "Preemption without Lite Restore\n"); } - if ((status & GEN8_CTX_STATUS_ACTIVE_IDLE) || - (status & GEN8_CTX_STATUS_ELEMENT_SWITCH)) { + if ((status & GEN8_CTX_STATUS_ACTIVE_IDLE) || + (status & GEN8_CTX_STATUS_ELEMENT_SWITCH)) { if (execlists_check_remove_request(ring, status_id)) submit_contexts++; } -- cgit v1.2.3 From 505abf99c7315f2229b873cca7a0514481a118e6 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 26 Dec 2015 21:16:14 +0900 Subject: iio: adc: mcp3422: Add support for MCP3425 The MCP3425 is a single channel up to 16-bit A/D converter which has features: - On-Board Programmable Gain Amplifier (PGA): - Gains of 1, 2, 4 or 8 - Programmable Data Rate Options: - 15 SPS (16 bits), 60 SPS (14 bits), 240 SPS (12 bits) The mcp3422 driver also supports the MCP3421 which is a single channel. So we can support MCP3425 with a little changes to mcp3422 driver. Signed-off-by: Akinobu Mita Cc: Sascha Hauer Cc: Angelo Compagnucci Cc: Peter Meerwald Cc: linux-iio@vger.kernel.org Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/iio/adc/mcp3422.txt | 1 + drivers/iio/adc/Kconfig | 6 +++--- drivers/iio/adc/mcp3422.c | 7 +++++-- 3 files changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/iio/adc/mcp3422.txt b/Documentation/devicetree/bindings/iio/adc/mcp3422.txt index dcae4ccfcc52..82bcce07255d 100644 --- a/Documentation/devicetree/bindings/iio/adc/mcp3422.txt +++ b/Documentation/devicetree/bindings/iio/adc/mcp3422.txt @@ -6,6 +6,7 @@ Required properties: "microchip,mcp3422" or "microchip,mcp3423" or "microchip,mcp3424" or + "microchip,mcp3425" or "microchip,mcp3426" or "microchip,mcp3427" or "microchip,mcp3428" diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 605ff42c4631..d0dc39a95555 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -265,11 +265,11 @@ config MCP320X called mcp320x. config MCP3422 - tristate "Microchip Technology MCP3422/3/4/6/7/8 driver" + tristate "Microchip Technology MCP3421/2/3/4/5/6/7/8 driver" depends on I2C help - Say yes here to build support for Microchip Technology's - MCP3422, MCP3423, MCP3424, MCP3426, MCP3427 or MCP3428 + Say yes here to build support for Microchip Technology's MCP3421 + MCP3422, MCP3423, MCP3424, MCP3425, MCP3426, MCP3427 or MCP3428 analog to digital converters. This driver can also be built as a module. If so, the module will be diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c index 6eca7aea8a37..ebad83e3fbf7 100644 --- a/drivers/iio/adc/mcp3422.c +++ b/drivers/iio/adc/mcp3422.c @@ -1,11 +1,12 @@ /* - * mcp3422.c - driver for the Microchip mcp3422/3/4/6/7/8 chip family + * mcp3422.c - driver for the Microchip mcp3421/2/3/4/5/6/7/8 chip family * * Copyright (C) 2013, Angelo Compagnucci * Author: Angelo Compagnucci * * Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/22088b.pdf * http://ww1.microchip.com/downloads/en/DeviceDoc/22226a.pdf + * http://ww1.microchip.com/downloads/en/DeviceDoc/22072b.pdf * * This driver exports the value of analog input voltage to sysfs, the * voltage unit is nV. @@ -357,6 +358,7 @@ static int mcp3422_probe(struct i2c_client *client, switch (adc->id) { case 1: + case 5: indio_dev->channels = mcp3421_channels; indio_dev->num_channels = ARRAY_SIZE(mcp3421_channels); break; @@ -395,6 +397,7 @@ static const struct i2c_device_id mcp3422_id[] = { { "mcp3422", 2 }, { "mcp3423", 3 }, { "mcp3424", 4 }, + { "mcp3425", 5 }, { "mcp3426", 6 }, { "mcp3427", 7 }, { "mcp3428", 8 }, @@ -421,5 +424,5 @@ static struct i2c_driver mcp3422_driver = { module_i2c_driver(mcp3422_driver); MODULE_AUTHOR("Angelo Compagnucci "); -MODULE_DESCRIPTION("Microchip mcp3422/3/4/6/7/8 driver"); +MODULE_DESCRIPTION("Microchip mcp3421/2/3/4/5/6/7/8 driver"); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 35f739679a18d7a9680960c9cfc472ef012682dd Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 26 Dec 2015 21:17:22 +0900 Subject: iio: dac: mcp4725: Add basic support for MCP4726 MCP4726 is a single channel 12-bit DAC. We can support MCP4726 with a little changes to mcp4725 driver. In power-down mode, they have different selection of VOUT pull-down registers. MCP4726 also has features: - Output gain options: 1x, 2x - Voltage reference selection: VDD, VREF (Unbuffered or Buffered) But these are not supported in this change. (1x gain, VDD is selected) datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22272C.pdf Signed-off-by: Akinobu Mita Cc: Jonathan Cameron Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald Cc: linux-iio@vger.kernel.org Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 2 + drivers/iio/dac/Kconfig | 4 +- drivers/iio/dac/mcp4725.c | 87 +++++++++++++++++++++++++-------- 3 files changed, 71 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 0439c2aaf741..8fadd272ad8a 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -497,7 +497,9 @@ Description: 6kohm_to_gnd: connected to ground via a 6kOhm resistor, 20kohm_to_gnd: connected to ground via a 20kOhm resistor, 100kohm_to_gnd: connected to ground via an 100kOhm resistor, + 125kohm_to_gnd: connected to ground via an 125kOhm resistor, 500kohm_to_gnd: connected to ground via a 500kOhm resistor, + 640kohm_to_gnd: connected to ground via a 640kOhm resistor, three_state: left floating. For a list of available output power down options read outX_powerdown_mode_available. If Y is not present the diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index e701e28fb1cd..5263c5125fbb 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -176,11 +176,11 @@ config MAX5821 10 bits DAC. config MCP4725 - tristate "MCP4725 DAC driver" + tristate "MCP4725/6 DAC driver" depends on I2C ---help--- Say Y here if you want to build a driver for the Microchip - MCP 4725 12-bit digital-to-analog converter (DAC) with I2C + MCP 4725/6 12-bit digital-to-analog converter (DAC) with I2C interface. To compile this driver as a module, choose M here: the module diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index 43d14588448d..fb4b3364d8e0 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -1,5 +1,5 @@ /* - * mcp4725.c - Support for Microchip MCP4725 + * mcp4725.c - Support for Microchip MCP4725/6 * * Copyright (C) 2012 Peter Meerwald * @@ -134,6 +134,12 @@ static const char * const mcp4725_powerdown_modes[] = { "500kohm_to_gnd" }; +static const char * const mcp4726_powerdown_modes[] = { + "1kohm_to_gnd", + "125kohm_to_gnd", + "640kohm_to_gnd" +}; + static int mcp4725_get_powerdown_mode(struct iio_dev *indio_dev, const struct iio_chan_spec *chan) { @@ -182,11 +188,24 @@ static ssize_t mcp4725_write_powerdown(struct iio_dev *indio_dev, return len; } -static const struct iio_enum mcp4725_powerdown_mode_enum = { - .items = mcp4725_powerdown_modes, - .num_items = ARRAY_SIZE(mcp4725_powerdown_modes), - .get = mcp4725_get_powerdown_mode, - .set = mcp4725_set_powerdown_mode, +enum { + MCP4725, + MCP4726, +}; + +static const struct iio_enum mcp472x_powerdown_mode_enum[] = { + [MCP4725] = { + .items = mcp4725_powerdown_modes, + .num_items = ARRAY_SIZE(mcp4725_powerdown_modes), + .get = mcp4725_get_powerdown_mode, + .set = mcp4725_set_powerdown_mode, + }, + [MCP4726] = { + .items = mcp4726_powerdown_modes, + .num_items = ARRAY_SIZE(mcp4726_powerdown_modes), + .get = mcp4725_get_powerdown_mode, + .set = mcp4725_set_powerdown_mode, + }, }; static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = { @@ -196,19 +215,46 @@ static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = { .write = mcp4725_write_powerdown, .shared = IIO_SEPARATE, }, - IIO_ENUM("powerdown_mode", IIO_SEPARATE, &mcp4725_powerdown_mode_enum), - IIO_ENUM_AVAILABLE("powerdown_mode", &mcp4725_powerdown_mode_enum), + IIO_ENUM("powerdown_mode", IIO_SEPARATE, + &mcp472x_powerdown_mode_enum[MCP4725]), + IIO_ENUM_AVAILABLE("powerdown_mode", + &mcp472x_powerdown_mode_enum[MCP4725]), + { }, +}; + +static const struct iio_chan_spec_ext_info mcp4726_ext_info[] = { + { + .name = "powerdown", + .read = mcp4725_read_powerdown, + .write = mcp4725_write_powerdown, + .shared = IIO_SEPARATE, + }, + IIO_ENUM("powerdown_mode", IIO_SEPARATE, + &mcp472x_powerdown_mode_enum[MCP4726]), + IIO_ENUM_AVAILABLE("powerdown_mode", + &mcp472x_powerdown_mode_enum[MCP4726]), { }, }; -static const struct iio_chan_spec mcp4725_channel = { - .type = IIO_VOLTAGE, - .indexed = 1, - .output = 1, - .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), - .ext_info = mcp4725_ext_info, +static const struct iio_chan_spec mcp472x_channel[] = { + [MCP4725] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .output = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .ext_info = mcp4725_ext_info, + }, + [MCP4726] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .output = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .ext_info = mcp4726_ext_info, + }, }; static int mcp4725_set_value(struct iio_dev *indio_dev, int val) @@ -301,7 +347,7 @@ static int mcp4725_probe(struct i2c_client *client, indio_dev->dev.parent = &client->dev; indio_dev->info = &mcp4725_info; - indio_dev->channels = &mcp4725_channel; + indio_dev->channels = &mcp472x_channel[id->driver_data]; indio_dev->num_channels = 1; indio_dev->modes = INDIO_DIRECT_MODE; @@ -315,7 +361,7 @@ static int mcp4725_probe(struct i2c_client *client, } pd = (inbuf[0] >> 1) & 0x3; data->powerdown = pd > 0 ? true : false; - data->powerdown_mode = pd ? pd-1 : 2; /* 500kohm_to_gnd */ + data->powerdown_mode = pd ? pd - 1 : 2; /* largest register to gnd */ data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4); return iio_device_register(indio_dev); @@ -328,7 +374,8 @@ static int mcp4725_remove(struct i2c_client *client) } static const struct i2c_device_id mcp4725_id[] = { - { "mcp4725", 0 }, + { "mcp4725", MCP4725 }, + { "mcp4726", MCP4726 }, { } }; MODULE_DEVICE_TABLE(i2c, mcp4725_id); @@ -345,5 +392,5 @@ static struct i2c_driver mcp4725_driver = { module_i2c_driver(mcp4725_driver); MODULE_AUTHOR("Peter Meerwald "); -MODULE_DESCRIPTION("MCP4725 12-bit DAC"); +MODULE_DESCRIPTION("MCP4725/6 12-bit DAC"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 9979e320b559264333a77c73131ae88cefca15e5 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Sat, 26 Dec 2015 20:56:30 -0800 Subject: iio: proximity: lidar: correct return value lidar_i2c_xfer() function was never a non-positive value on error, and this correct that with a -EIO return code. Fixes: 366e65633cf4 ("iio: proximity: lidar: optimize i2c transactions") Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/pulsedlight-lidar-lite-v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c index 93e29fb67fa0..db35e04a0637 100644 --- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c +++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c @@ -87,7 +87,7 @@ static int lidar_i2c_xfer(struct lidar_data *data, u8 reg, u8 *val, int len) ret = i2c_transfer(client->adapter, msg, 2); - return (ret == 2) ? 0 : ret; + return (ret == 2) ? 0 : -EIO; } static int lidar_smbus_xfer(struct lidar_data *data, u8 reg, u8 *val, int len) -- cgit v1.2.3 From b11a34607ded9b3dfb1992da47ac94bdf5945d53 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Tue, 29 Dec 2015 21:44:48 -0800 Subject: iio: health: max30100: add config for LED current Allow the current for both RED and IR LEDs to be set via an device tree property setting. This is an optional setting that is useful for applications that have a known glass attenuation factor. Signed-off-by: Matt Ranostay Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/health/max30100.txt | 8 +++ drivers/iio/health/max30100.c | 81 ++++++++++++++++++++-- 2 files changed, 83 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/iio/health/max30100.txt b/Documentation/devicetree/bindings/iio/health/max30100.txt index f6fbac66ad06..295a9edfa4fd 100644 --- a/Documentation/devicetree/bindings/iio/health/max30100.txt +++ b/Documentation/devicetree/bindings/iio/health/max30100.txt @@ -11,11 +11,19 @@ Required properties: Refer to interrupt-controller/interrupts.txt for generic interrupt client node bindings. +Optional properties: + - maxim,led-current-microamp: configuration for LED current in microamperes + while the engine is running. First indexed value is the configuration for + the RED LED, and second value is for the IR LED. + + Refer to the datasheet for the allowed current values. + Example: max30100@057 { compatible = "maxim,max30100"; reg = <57>; + maxim,led-current-microamp = <24000 50000>; interrupt-parent = <&gpio1>; interrupts = <16 2>; }; diff --git a/drivers/iio/health/max30100.c b/drivers/iio/health/max30100.c index 9d1c81f91dd7..09db89359544 100644 --- a/drivers/iio/health/max30100.c +++ b/drivers/iio/health/max30100.c @@ -13,7 +13,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * TODO: allow LED current and pulse length controls via device tree properties + * TODO: enable pulse length controls via device tree properties */ #include @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +66,7 @@ #define MAX30100_REG_SPO2_CONFIG_1600US 0x3 #define MAX30100_REG_LED_CONFIG 0x09 +#define MAX30100_REG_LED_CONFIG_LED_MASK 0x0f #define MAX30100_REG_LED_CONFIG_RED_LED_SHIFT 4 #define MAX30100_REG_LED_CONFIG_24MA 0x07 @@ -111,6 +113,12 @@ static const struct regmap_config max30100_regmap_config = { .volatile_reg = max30100_is_volatile_reg, }; +static const unsigned int max30100_led_current_mapping[] = { + 4400, 7600, 11000, 14200, 17400, + 20800, 24000, 27100, 30600, 33800, + 37000, 40200, 43600, 46800, 50000 +}; + static const unsigned long max30100_scan_masks[] = {0x3, 0}; static const struct iio_chan_spec max30100_channels[] = { @@ -243,15 +251,76 @@ static irqreturn_t max30100_interrupt_handler(int irq, void *private) return IRQ_HANDLED; } +static int max30100_get_current_idx(unsigned int val, int *reg) +{ + int idx; + + /* LED turned off */ + if (val == 0) { + *reg = 0; + return 0; + } + + for (idx = 0; idx < ARRAY_SIZE(max30100_led_current_mapping); idx++) { + if (max30100_led_current_mapping[idx] == val) { + *reg = idx + 1; + return 0; + } + } + + return -EINVAL; +} + +static int max30100_led_init(struct max30100_data *data) +{ + struct device *dev = &data->client->dev; + struct device_node *np = dev->of_node; + unsigned int val[2]; + int reg, ret; + + ret = of_property_read_u32_array(np, "maxim,led-current-microamp", + (unsigned int *) &val, 2); + if (ret) { + /* Default to 24 mA RED LED, 50 mA IR LED */ + reg = (MAX30100_REG_LED_CONFIG_24MA << + MAX30100_REG_LED_CONFIG_RED_LED_SHIFT) | + MAX30100_REG_LED_CONFIG_50MA; + dev_warn(dev, "no led-current-microamp set"); + + return regmap_write(data->regmap, MAX30100_REG_LED_CONFIG, reg); + } + + /* RED LED current */ + ret = max30100_get_current_idx(val[0], ®); + if (ret) { + dev_err(dev, "invalid RED current setting %d", val[0]); + return ret; + } + + ret = regmap_update_bits(data->regmap, MAX30100_REG_LED_CONFIG, + MAX30100_REG_LED_CONFIG_LED_MASK << + MAX30100_REG_LED_CONFIG_RED_LED_SHIFT, + reg << MAX30100_REG_LED_CONFIG_RED_LED_SHIFT); + if (ret) + return ret; + + /* IR LED current */ + ret = max30100_get_current_idx(val[1], ®); + if (ret) { + dev_err(dev, "invalid IR current setting %d", val[1]); + return ret; + } + + return regmap_update_bits(data->regmap, MAX30100_REG_LED_CONFIG, + MAX30100_REG_LED_CONFIG_LED_MASK, reg); +} + static int max30100_chip_init(struct max30100_data *data) { int ret; - /* RED IR LED = 24mA, IR LED = 50mA */ - ret = regmap_write(data->regmap, MAX30100_REG_LED_CONFIG, - (MAX30100_REG_LED_CONFIG_24MA << - MAX30100_REG_LED_CONFIG_RED_LED_SHIFT) | - MAX30100_REG_LED_CONFIG_50MA); + /* setup LED current settings */ + ret = max30100_led_init(data); if (ret) return ret; -- cgit v1.2.3 From 01cc5235604d61018712c11a14d74230f6a38bf4 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Sat, 2 Jan 2016 14:04:39 +0100 Subject: iio: add IIO_TRIGGER dependency to STK8BA50 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ran into this on UML: drivers/iio/accel/stk8ba50.c: In function ‘stk8ba50_data_rdy_trigger_set_state’: drivers/iio/accel/stk8ba50.c:163:9: error: implicit declaration of function ‘iio_trigger_get_drvdata’ [-Werror=implicit-function-declaration] iio_trigger_get_drvdata() is defined only when IIO_TRIGGER is selected. Signed-off-by: Vegard Nossum Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/accel/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 969428dd6329..16cc5c691a55 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -173,6 +173,7 @@ config STK8312 config STK8BA50 tristate "Sensortek STK8BA50 3-Axis Accelerometer Driver" depends on I2C + depends on IIO_TRIGGER help Say yes here to get support for the Sensortek STK8BA50 3-axis accelerometer. -- cgit v1.2.3 From 005ce0713006a76d2b0c924ce0e2629e5d8510c3 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Sat, 2 Jan 2016 14:04:40 +0100 Subject: iio: add HAS_IOMEM dependency to VF610_ADC Ran into this on UML: drivers/built-in.o: In function `vf610_adc_probe': drivers/iio/adc/vf610_adc.c:744: undefined reference to `devm_ioremap_resource' devm_ioremap_resource() is defined only when HAS_IOMEM is selected. Signed-off-by: Vegard Nossum Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 7868c744fd4b..1e7aded53117 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -372,6 +372,7 @@ config TWL6030_GPADC config VF610_ADC tristate "Freescale vf610 ADC driver" depends on OF + depends on HAS_IOMEM select IIO_BUFFER select IIO_TRIGGERED_BUFFER help -- cgit v1.2.3 From c0559ae2fb91fc558d0eb390c17d32d6c309fb06 Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Tue, 29 Dec 2015 16:57:30 +0530 Subject: Staging: iio: cdc: ad7150: Prefer using the BIT macro Replace bit shifting on 1 with the BIT(x) macro Signed-off-by: Shraddha Barke Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7150.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index e8d0ff2d5c9b..0b934f7801d5 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -21,8 +21,8 @@ */ #define AD7150_STATUS 0 -#define AD7150_STATUS_OUT1 (1 << 3) -#define AD7150_STATUS_OUT2 (1 << 5) +#define AD7150_STATUS_OUT1 BIT(3) +#define AD7150_STATUS_OUT2 BIT(5) #define AD7150_CH1_DATA_HIGH 1 #define AD7150_CH2_DATA_HIGH 3 #define AD7150_CH1_AVG_HIGH 5 @@ -36,7 +36,7 @@ #define AD7150_CH2_TIMEOUT 13 #define AD7150_CH2_SETUP 14 #define AD7150_CFG 15 -#define AD7150_CFG_FIX (1 << 7) +#define AD7150_CFG_FIX BIT(7) #define AD7150_PD_TIMER 16 #define AD7150_CH1_CAPDAC 17 #define AD7150_CH2_CAPDAC 18 -- cgit v1.2.3 From c4f0ebd91467c701b32879bf6091e5c91c6e79c1 Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Tue, 29 Dec 2015 16:57:31 +0530 Subject: Staging: iio: cdc: ad7150: Fix alignment should match open parenthesis Fix the checkpatch warning of alignment should match open parenthesis. Signed-off-by: Shraddha Barke Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7150.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index 0b934f7801d5..f6b9a10326ea 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -160,8 +160,9 @@ static int ad7150_read_event_config(struct iio_dev *indio_dev, /* lock should be held */ static int ad7150_write_event_params(struct iio_dev *indio_dev, - unsigned int chan, enum iio_event_type type, - enum iio_event_direction dir) + unsigned int chan, + enum iio_event_type type, + enum iio_event_direction dir) { int ret; u16 value; @@ -209,8 +210,9 @@ static int ad7150_write_event_params(struct iio_dev *indio_dev, } static int ad7150_write_event_config(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, enum iio_event_type type, - enum iio_event_direction dir, int state) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, int state) { u8 thresh_type, cfg, adaptive; int ret; @@ -302,11 +304,11 @@ static int ad7150_read_event_value(struct iio_dev *indio_dev, } static int ad7150_write_event_value(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int val, int val2) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) { int ret; struct ad7150_chip_info *chip = iio_priv(indio_dev); @@ -365,9 +367,9 @@ static ssize_t ad7150_show_timeout(struct device *dev, } static ssize_t ad7150_store_timeout(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7150_chip_info *chip = iio_priv(indio_dev); @@ -580,7 +582,7 @@ static const struct iio_info ad7150_info = { */ static int ad7150_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { int ret; struct ad7150_chip_info *chip; -- cgit v1.2.3 From 62ab420f7458feb4ef1fa2ef094ee00af9844253 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Wed, 30 Dec 2015 10:59:29 -0500 Subject: i915: correctly handling failed allocation Since devm_kzalloc can be failed, it needs to be checked if not, NULL dereference could be happened. Signed-off-by: Insu Yun Link: http://patchwork.freedesktop.org/patch/msgid/1451491169-35068-1-git-send-email-wuninsu@gmail.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index a5e99ac305da..aa1f7bc8f4d0 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -666,6 +666,8 @@ struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id) /* This is cheating a bit with the cleanup. */ vbt_panel = devm_kzalloc(dev->dev, sizeof(*vbt_panel), GFP_KERNEL); + if (!vbt_panel) + return NULL; vbt_panel->intel_dsi = intel_dsi; drm_panel_init(&vbt_panel->panel); -- cgit v1.2.3 From 934acce3c069a3d8b14085957248444145d9ec1b Mon Sep 17 00:00:00 2001 From: Michał Winiarski Date: Tue, 29 Dec 2015 18:24:52 +0100 Subject: drm/i915: Avoid writing relocs with addresses in non-canonical form MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to PRM, some parts of HW require the addresses to be in a canonical form, where bits [63:48] == [47]. Let's convert addresses to canonical form prior to relocating and return converted offsets to userspace. We also need to make sure that userspace is using addresses in canonical form in case of softpin. v2: Whitespace fixup, gen8_canonical_addr description (Chris, Ville) v3: Rebase on top of softpin, fix a hole in relocate_entry, s/expect/require (Chris) v4: Handle softpin in validate_exec_list (Chris) v5: Convert back to canonical form at copy_to_user time (Chris) v6: Don't use struct exec_object2 in place of exec_object v7: Use sign_extend64 for converting to canonical form (Joonas), reject non-canonical and non-page-aligned offset for softpin (Chris) v8: Convert back to non-canonical form in a function, split the test for EXEC_OBJECT_PINNED (Chris) v9: s/canonial/canonical, drop accidental double newline (Chris) Cc: Chris Wilson Cc: Michel Thierry Cc: Ville Syrjälä Signed-off-by: Michał Winiarski Link: http://patchwork.freedesktop.org/patch/msgid/1451409892-13708-1-git-send-email-michal.winiarski@intel.com Testcase: igt/gem_bad_reloc/negative-reloc-blt Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92699 Cc: drm-intel-fixes@lists.freedesktop.org Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 52 +++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 5d01ea680dc1..dccb517361b3 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -249,6 +249,31 @@ static inline int use_cpu_reloc(struct drm_i915_gem_object *obj) obj->cache_level != I915_CACHE_NONE); } +/* Used to convert any address to canonical form. + * Starting from gen8, some commands (e.g. STATE_BASE_ADDRESS, + * MI_LOAD_REGISTER_MEM and others, see Broadwell PRM Vol2a) require the + * addresses to be in a canonical form: + * "GraphicsAddress[63:48] are ignored by the HW and assumed to be in correct + * canonical form [63:48] == [47]." + */ +#define GEN8_HIGH_ADDRESS_BIT 47 +static inline uint64_t gen8_canonical_addr(uint64_t address) +{ + return sign_extend64(address, GEN8_HIGH_ADDRESS_BIT); +} + +static inline uint64_t gen8_noncanonical_addr(uint64_t address) +{ + return address & ((1ULL << (GEN8_HIGH_ADDRESS_BIT + 1)) - 1); +} + +static inline uint64_t +relocation_target(struct drm_i915_gem_relocation_entry *reloc, + uint64_t target_offset) +{ + return gen8_canonical_addr((int)reloc->delta + target_offset); +} + static int relocate_entry_cpu(struct drm_i915_gem_object *obj, struct drm_i915_gem_relocation_entry *reloc, @@ -256,7 +281,7 @@ relocate_entry_cpu(struct drm_i915_gem_object *obj, { struct drm_device *dev = obj->base.dev; uint32_t page_offset = offset_in_page(reloc->offset); - uint64_t delta = reloc->delta + target_offset; + uint64_t delta = relocation_target(reloc, target_offset); char *vaddr; int ret; @@ -292,7 +317,7 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj, { struct drm_device *dev = obj->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - uint64_t delta = reloc->delta + target_offset; + uint64_t delta = relocation_target(reloc, target_offset); uint64_t offset; void __iomem *reloc_page; int ret; @@ -347,7 +372,7 @@ relocate_entry_clflush(struct drm_i915_gem_object *obj, { struct drm_device *dev = obj->base.dev; uint32_t page_offset = offset_in_page(reloc->offset); - uint64_t delta = (int)reloc->delta + target_offset; + uint64_t delta = relocation_target(reloc, target_offset); char *vaddr; int ret; @@ -395,7 +420,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, target_i915_obj = target_vma->obj; target_obj = &target_vma->obj->base; - target_offset = target_vma->node.start; + target_offset = gen8_canonical_addr(target_vma->node.start); /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and * pipe_control writes because the gpu doesn't properly redirect them @@ -994,6 +1019,21 @@ validate_exec_list(struct drm_device *dev, if (exec[i].flags & invalid_flags) return -EINVAL; + /* Offset can be used as input (EXEC_OBJECT_PINNED), reject + * any non-page-aligned or non-canonical addresses. + */ + if (exec[i].flags & EXEC_OBJECT_PINNED) { + if (exec[i].offset != + gen8_canonical_addr(exec[i].offset & PAGE_MASK)) + return -EINVAL; + + /* From drm_mm perspective address space is continuous, + * so from this point we're always using non-canonical + * form internally. + */ + exec[i].offset = gen8_noncanonical_addr(exec[i].offset); + } + if (exec[i].alignment && !is_power_of_2(exec[i].alignment)) return -EINVAL; @@ -1687,6 +1727,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, /* Copy the new buffer offsets back to the user's exec list. */ for (i = 0; i < args->buffer_count; i++) { + exec2_list[i].offset = + gen8_canonical_addr(exec2_list[i].offset); ret = __copy_to_user(&user_exec_list[i].offset, &exec2_list[i].offset, sizeof(user_exec_list[i].offset)); @@ -1752,6 +1794,8 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data, int i; for (i = 0; i < args->buffer_count; i++) { + exec2_list[i].offset = + gen8_canonical_addr(exec2_list[i].offset); ret = __copy_to_user(&user_exec_list[i].offset, &exec2_list[i].offset, sizeof(user_exec_list[i].offset)); -- cgit v1.2.3 From c1a415e261aad096b3458ba9157fefd123aa7cbf Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 4 Dec 2015 15:58:54 +0000 Subject: drm/i915: Disable shrinker for non-swapped backed objects If the system has no available swap pages, we cannot make forward progress in the shrinker by releasing active pages, only by releasing purgeable pages which are immediately reaped. Take total_swap_pages into account when counting up available objects to be shrunk and subsequently shrinking them. By doing so, we avoid unbinding objects that cannot be shrunk and so wasting CPU cycles flushing those objects from the GPU to the system and then immediately back again (as they will more than likely be reused shortly after). Based on a patch by Akash Goel. v2: frontswap registers extra swap pages available for the system, so it is already include in the count of available swap pages. v3: Use get_nr_swap_pages() to query the currently available amount of swap space. This should also stop us from shrinking the GPU buffers if we ever run out of swap space. Though at that point, we would expect the oom-notifier to be running and failing miserably... Reported-by: Akash Goel Signed-off-by: Chris Wilson Cc: linux-mm@kvack.org Cc: Akash Goel Cc: sourab.gupta@intel.com Link: http://patchwork.freedesktop.org/patch/msgid/1449244734-25733-2-git-send-email-chris@chris-wilson.co.uk Acked-by: Johannes Weiner Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_shrinker.c | 60 +++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index f7df54a8ee2b..16da9c1422cc 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -47,6 +47,46 @@ static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task) #endif } +static int num_vma_bound(struct drm_i915_gem_object *obj) +{ + struct i915_vma *vma; + int count = 0; + + list_for_each_entry(vma, &obj->vma_list, vma_link) { + if (drm_mm_node_allocated(&vma->node)) + count++; + if (vma->pin_count) + count++; + } + + return count; +} + +static bool swap_available(void) +{ + return get_nr_swap_pages() > 0; +} + +static bool can_release_pages(struct drm_i915_gem_object *obj) +{ + /* Only report true if by unbinding the object and putting its pages + * we can actually make forward progress towards freeing physical + * pages. + * + * If the pages are pinned for any other reason than being bound + * to the GPU, simply unbinding from the GPU is not going to succeed + * in releasing our pin count on the pages themselves. + */ + if (obj->pages_pin_count != num_vma_bound(obj)) + return false; + + /* We can only return physical pages to the system if we can either + * discard the contents (because the user has marked them as being + * purgeable) or if we can move their contents out to swap. + */ + return swap_available() || obj->madv == I915_MADV_DONTNEED; +} + /** * i915_gem_shrink - Shrink buffer object caches * @dev_priv: i915 device @@ -129,6 +169,9 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, if ((flags & I915_SHRINK_ACTIVE) == 0 && obj->active) continue; + if (!can_release_pages(obj)) + continue; + drm_gem_object_reference(&obj->base); /* For the unbound phase, this should be a no-op! */ @@ -188,21 +231,6 @@ static bool i915_gem_shrinker_lock(struct drm_device *dev, bool *unlock) return true; } -static int num_vma_bound(struct drm_i915_gem_object *obj) -{ - struct i915_vma *vma; - int count = 0; - - list_for_each_entry(vma, &obj->vma_list, vma_link) { - if (drm_mm_node_allocated(&vma->node)) - count++; - if (vma->pin_count) - count++; - } - - return count; -} - static unsigned long i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc) { @@ -222,7 +250,7 @@ i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc) count += obj->base.size >> PAGE_SHIFT; list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { - if (!obj->active && obj->pages_pin_count == num_vma_bound(obj)) + if (!obj->active && can_release_pages(obj)) count += obj->base.size >> PAGE_SHIFT; } -- cgit v1.2.3 From a7e02199ae430c0b41ee2b3079ccbbaff2393baf Mon Sep 17 00:00:00 2001 From: Alex Dai Date: Wed, 16 Dec 2015 11:45:55 -0800 Subject: drm/i915/guc: Move GuC wq_check_space to alloc_request_extras Split GuC work queue space checking from submission and move it to ring_alloc_request_extras. The reason is that failure in later i915_add_request() won't be handled. In the case timeout happens, driver can return early in order to handle the error. v1: Move wq_reserve_space to ring_reserve_space v2: Move wq_reserve_space to alloc_request_extras (Chris Wilson) v3: The work queue head pointer is cached by driver now. So we can quickly return if space is available. s/reserve/check/g (Dave Gordon) v4: Update cached wq head after ring doorbell; check wq space before ring doorbell in case unexpected error happens; call wq space check only when GuC submission is enabled. (Dave Gordon) Signed-off-by: Alex Dai Link: http://patchwork.freedesktop.org/patch/msgid/1450295155-10050-1-git-send-email-yu.dai@intel.com Reviewed-by: Dave Gordon Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_guc_submission.c | 39 ++++++++++++++++++------------ drivers/gpu/drm/i915/intel_guc.h | 2 ++ drivers/gpu/drm/i915/intel_lrc.c | 13 ++++++++++ 3 files changed, 39 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 9cc3b8474dae..8b00f4619b1e 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -244,6 +244,9 @@ static int guc_ring_doorbell(struct i915_guc_client *gc) db_exc.cookie = 1; } + /* Finally, update the cached copy of the GuC's WQ head */ + gc->wq_head = desc->head; + kunmap_atomic(base); return ret; } @@ -469,28 +472,30 @@ static void guc_fini_ctx_desc(struct intel_guc *guc, sizeof(desc) * client->ctx_index); } -/* Get valid workqueue item and return it back to offset */ -static int guc_get_workqueue_space(struct i915_guc_client *gc, u32 *offset) +int i915_guc_wq_check_space(struct i915_guc_client *gc) { struct guc_process_desc *desc; void *base; u32 size = sizeof(struct guc_wq_item); int ret = -ETIMEDOUT, timeout_counter = 200; + if (!gc) + return 0; + + /* Quickly return if wq space is available since last time we cache the + * head position. */ + if (CIRC_SPACE(gc->wq_tail, gc->wq_head, gc->wq_size) >= size) + return 0; + base = kmap_atomic(i915_gem_object_get_page(gc->client_obj, 0)); desc = base + gc->proc_desc_offset; while (timeout_counter-- > 0) { - if (CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size) >= size) { - *offset = gc->wq_tail; + gc->wq_head = desc->head; - /* advance the tail for next workqueue item */ - gc->wq_tail += size; - gc->wq_tail &= gc->wq_size - 1; - - /* this will break the loop */ - timeout_counter = 0; + if (CIRC_SPACE(gc->wq_tail, gc->wq_head, gc->wq_size) >= size) { ret = 0; + break; } if (timeout_counter) @@ -508,12 +513,16 @@ static int guc_add_workqueue_item(struct i915_guc_client *gc, enum intel_ring_id ring_id = rq->ring->id; struct guc_wq_item *wqi; void *base; - u32 tail, wq_len, wq_off = 0; - int ret; + u32 tail, wq_len, wq_off, space; + + space = CIRC_SPACE(gc->wq_tail, gc->wq_head, gc->wq_size); + if (WARN_ON(space < sizeof(struct guc_wq_item))) + return -ENOSPC; /* shouldn't happen */ - ret = guc_get_workqueue_space(gc, &wq_off); - if (ret) - return ret; + /* postincrement WQ tail for next time */ + wq_off = gc->wq_tail; + gc->wq_tail += sizeof(struct guc_wq_item); + gc->wq_tail &= gc->wq_size - 1; /* For now workqueue item is 4 DWs; workqueue buffer is 2 pages. So we * should not have the case where structure wqi is across page, neither diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index 822952235dcf..e8612c9afbc9 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -43,6 +43,7 @@ struct i915_guc_client { uint32_t wq_offset; uint32_t wq_size; uint32_t wq_tail; + uint32_t wq_head; /* GuC submission statistics & status */ uint64_t submissions[I915_NUM_RINGS]; @@ -122,5 +123,6 @@ int i915_guc_submit(struct i915_guc_client *client, struct drm_i915_gem_request *rq); void i915_guc_submission_disable(struct drm_device *dev); void i915_guc_submission_fini(struct drm_device *dev); +int i915_guc_wq_check_space(struct i915_guc_client *client); #endif diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 973487a73be1..e09505827394 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -670,6 +670,19 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request return ret; } + if (i915.enable_guc_submission) { + /* + * Check that the GuC has space for the request before + * going any further, as the i915_add_request() call + * later on mustn't fail ... + */ + struct intel_guc *guc = &request->i915->guc; + + ret = i915_guc_wq_check_space(guc->execbuf_client); + if (ret) + return ret; + } + return 0; } -- cgit v1.2.3 From 95a66f7e711d091ea277fcde2d1dd11e6b8e9468 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Fri, 18 Dec 2015 12:00:08 -0800 Subject: drm/i915/guc: Expose (intel)_lr_context_size() The GuC code needs to know the size of a logical context, so we expose get_lr_context_size(), renaming it intel_lr_context__size() to fit the naming conventions for nonstatic functions. For: VIZ-2021 Signed-off-by: Dave Gordon Signed-off-by: Alex Dai Reviewed-by: Dave Gordon Link: http://patchwork.freedesktop.org/patch/msgid/1450468812-4882-2-git-send-email-yu.dai@intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 4 ++-- drivers/gpu/drm/i915/intel_lrc.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index e09505827394..808515cef607 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -2399,7 +2399,7 @@ void intel_lr_context_free(struct intel_context *ctx) } } -static uint32_t get_lr_context_size(struct intel_engine_cs *ring) +uint32_t intel_lr_context_size(struct intel_engine_cs *ring) { int ret = 0; @@ -2467,7 +2467,7 @@ int intel_lr_context_deferred_alloc(struct intel_context *ctx, WARN_ON(ctx->legacy_hw_ctx.rcs_state != NULL); WARN_ON(ctx->engine[ring->id].state); - context_size = round_up(get_lr_context_size(ring), 4096); + context_size = round_up(intel_lr_context_size(ring), 4096); /* One extra page as the sharing data between driver and GuC */ context_size += PAGE_SIZE * LRC_PPHWSP_PN; diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 0b821b91723a..ae90f86a2849 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -84,6 +84,7 @@ static inline void intel_logical_ring_emit_reg(struct intel_ringbuffer *ringbuf, #define LRC_STATE_PN (LRC_PPHWSP_PN + 1) void intel_lr_context_free(struct intel_context *ctx); +uint32_t intel_lr_context_size(struct intel_engine_cs *ring); int intel_lr_context_deferred_alloc(struct intel_context *ctx, struct intel_engine_cs *ring); void intel_lr_context_unpin(struct drm_i915_gem_request *req); -- cgit v1.2.3 From 68371a954ca4581a6468835f63d6f82783471591 Mon Sep 17 00:00:00 2001 From: Alex Dai Date: Fri, 18 Dec 2015 12:00:09 -0800 Subject: drm/i915/guc: Add GuC ADS (Addition Data Structure) - allocation The GuC firmware uses this for various purposes. The ADS itself is a chunk of memory created by driver to share with GuC. Its members are usually addresses telling where GuC to access them, including things like scheduler policies, register list that will be saved and restored during reset etc. This is the first patch of a series to enable GuC ADS. For now, we only create the ADS obj whilst keep it disabled. v1: remove dead code checking return of kmap_atomic (Chris Wilson) v2: use kmap instead of the atomic version of it. Signed-off-by: Alex Dai Reviewed-by: Dave Gordon Link: http://patchwork.freedesktop.org/patch/msgid/1450468812-4882-3-git-send-email-yu.dai@intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_guc_reg.h | 1 + drivers/gpu/drm/i915/i915_guc_submission.c | 45 ++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_guc.h | 2 ++ drivers/gpu/drm/i915/intel_guc_fwif.h | 31 +++++++++++++++++++- 4 files changed, 78 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h index 685c7991e24f..e4ba5822289b 100644 --- a/drivers/gpu/drm/i915/i915_guc_reg.h +++ b/drivers/gpu/drm/i915/i915_guc_reg.h @@ -40,6 +40,7 @@ #define GS_MIA_CORE_STATE (1 << GS_MIA_SHIFT) #define SOFT_SCRATCH(n) _MMIO(0xc180 + (n) * 4) +#define SOFT_SCRATCH_COUNT 16 #define UOS_RSA_SCRATCH(i) _MMIO(0xc200 + (i) * 4) #define UOS_RSA_SCRATCH_MAX_COUNT 64 diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 8b00f4619b1e..7e6c5272e734 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -839,6 +839,46 @@ static void guc_create_log(struct intel_guc *guc) guc->log_flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags; } +static void guc_create_ads(struct intel_guc *guc) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + struct drm_i915_gem_object *obj; + struct guc_ads *ads; + struct intel_engine_cs *ring; + struct page *page; + u32 size, i; + + /* The ads obj includes the struct itself and buffers passed to GuC */ + size = sizeof(struct guc_ads); + + obj = guc->ads_obj; + if (!obj) { + obj = gem_allocate_guc_obj(dev_priv->dev, PAGE_ALIGN(size)); + if (!obj) + return; + + guc->ads_obj = obj; + } + + page = i915_gem_object_get_page(obj, 0); + ads = kmap(page); + + /* + * The GuC requires a "Golden Context" when it reinitialises + * engines after a reset. Here we use the Render ring default + * context, which must already exist and be pinned in the GGTT, + * so its address won't change after we've told the GuC where + * to find it. + */ + ring = &dev_priv->ring[RCS]; + ads->golden_context_lrca = ring->status_page.gfx_addr; + + for_each_ring(ring, dev_priv, i) + ads->eng_state_size[i] = intel_lr_context_size(ring); + + kunmap(page); +} + /* * Set up the memory resources to be shared with the GuC. At this point, * we require just one object that can be mapped through the GGTT. @@ -865,6 +905,8 @@ int i915_guc_submission_init(struct drm_device *dev) guc_create_log(guc); + guc_create_ads(guc); + return 0; } @@ -903,6 +945,9 @@ void i915_guc_submission_fini(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_guc *guc = &dev_priv->guc; + gem_release_guc_obj(dev_priv->guc.ads_obj); + guc->ads_obj = NULL; + gem_release_guc_obj(dev_priv->guc.log_obj); guc->log_obj = NULL; diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index e8612c9afbc9..045b1491ff7a 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -89,6 +89,8 @@ struct intel_guc { uint32_t log_flags; struct drm_i915_gem_object *log_obj; + struct drm_i915_gem_object *ads_obj; + struct drm_i915_gem_object *ctx_pool_obj; struct ida ctx_ids; diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index 40b2ea572e16..bc9829eaabb3 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h @@ -81,11 +81,14 @@ #define GUC_CTL_CTXINFO 0 #define GUC_CTL_CTXNUM_IN16_SHIFT 0 #define GUC_CTL_BASE_ADDR_SHIFT 12 + #define GUC_CTL_ARAT_HIGH 1 #define GUC_CTL_ARAT_LOW 2 + #define GUC_CTL_DEVICE_INFO 3 #define GUC_CTL_GTTYPE_SHIFT 0 #define GUC_CTL_COREFAMILY_SHIFT 7 + #define GUC_CTL_LOG_PARAMS 4 #define GUC_LOG_VALID (1 << 0) #define GUC_LOG_NOTIFY_ON_HALF_FULL (1 << 1) @@ -97,9 +100,12 @@ #define GUC_LOG_ISR_PAGES 3 #define GUC_LOG_ISR_SHIFT 9 #define GUC_LOG_BUF_ADDR_SHIFT 12 + #define GUC_CTL_PAGE_FAULT_CONTROL 5 + #define GUC_CTL_WA 6 #define GUC_CTL_WA_UK_BY_DRIVER (1 << 3) + #define GUC_CTL_FEATURE 7 #define GUC_CTL_VCS2_ENABLED (1 << 0) #define GUC_CTL_KERNEL_SUBMISSIONS (1 << 1) @@ -109,6 +115,7 @@ #define GUC_CTL_PREEMPTION_LOG (1 << 5) #define GUC_CTL_ENABLE_SLPC (1 << 7) #define GUC_CTL_RESET_ON_PREMPT_FAILURE (1 << 8) + #define GUC_CTL_DEBUG 8 #define GUC_LOG_VERBOSITY_SHIFT 0 #define GUC_LOG_VERBOSITY_LOW (0 << GUC_LOG_VERBOSITY_SHIFT) @@ -118,9 +125,19 @@ /* Verbosity range-check limits, without the shift */ #define GUC_LOG_VERBOSITY_MIN 0 #define GUC_LOG_VERBOSITY_MAX 3 +#define GUC_LOG_VERBOSITY_MASK 0x0000000f +#define GUC_LOG_DESTINATION_MASK (3 << 4) +#define GUC_LOG_DISABLED (1 << 6) +#define GUC_PROFILE_ENABLED (1 << 7) +#define GUC_WQ_TRACK_ENABLED (1 << 8) +#define GUC_ADS_ENABLED (1 << 9) +#define GUC_DEBUG_RESERVED (1 << 10) +#define GUC_ADS_ADDR_SHIFT 11 +#define GUC_ADS_ADDR_MASK 0xfffff800 + #define GUC_CTL_RSRVD 9 -#define GUC_CTL_MAX_DWORDS (GUC_CTL_RSRVD + 1) +#define GUC_CTL_MAX_DWORDS (SOFT_SCRATCH_COUNT - 2) /* [1..14] */ /** * DOC: GuC Firmware Layout @@ -299,6 +316,18 @@ struct guc_context_desc { #define GUC_POWER_D2 3 #define GUC_POWER_D3 4 +/* GuC Additional Data Struct */ + +struct guc_ads { + u32 reg_state_addr; + u32 reg_state_buffer; + u32 golden_context_lrca; + u32 scheduler_policies; + u32 reserved0[3]; + u32 eng_state_size[I915_NUM_RINGS]; + u32 reserved2[4]; +} __packed; + /* This Action will be programmed in C180 - SOFT_SCRATCH_O_REG */ enum host2guc_action { HOST2GUC_ACTION_DEFAULT = 0x0, -- cgit v1.2.3 From 463704d07f4cb0767714a67eaaf1ee47eef36fd8 Mon Sep 17 00:00:00 2001 From: Alex Dai Date: Fri, 18 Dec 2015 12:00:10 -0800 Subject: drm/i915/guc: Add GuC ADS - scheduler policies GuC supports different scheduling policies for its four internal queues. Currently these have been set to the same default values as KMD_NORMAL queue. Particularly POLICY_MAX_NUM_WI is set to 15 to match GuC internal maximum submit queue numbers to avoid an out-of-space problem. This value indicates max number of work items allowed to be queued for one DPC process. A smaller value will let GuC schedule more frequently while a larger number may increase chances to optimize cmds (such as collapse cmds from same lrc) with risks that keeps CS idle. v1: tidy up code Signed-off-by: Alex Dai Reviewed-by: Dave Gordon Link: http://patchwork.freedesktop.org/patch/msgid/1450468812-4882-4-git-send-email-yu.dai@intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_guc_submission.c | 32 ++++++++++++++++++++- drivers/gpu/drm/i915/intel_guc_fwif.h | 45 ++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 7e6c5272e734..1eb8db8d1feb 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -839,17 +839,40 @@ static void guc_create_log(struct intel_guc *guc) guc->log_flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags; } +static void init_guc_policies(struct guc_policies *policies) +{ + struct guc_policy *policy; + u32 p, i; + + policies->dpc_promote_time = 500000; + policies->max_num_work_items = POLICY_MAX_NUM_WI; + + for (p = 0; p < GUC_CTX_PRIORITY_NUM; p++) { + for (i = 0; i < I915_NUM_RINGS; i++) { + policy = &policies->policy[p][i]; + + policy->execution_quantum = 1000000; + policy->preemption_time = 500000; + policy->fault_time = 250000; + policy->policy_flags = 0; + } + } + + policies->is_valid = 1; +} + static void guc_create_ads(struct intel_guc *guc) { struct drm_i915_private *dev_priv = guc_to_i915(guc); struct drm_i915_gem_object *obj; struct guc_ads *ads; + struct guc_policies *policies; struct intel_engine_cs *ring; struct page *page; u32 size, i; /* The ads obj includes the struct itself and buffers passed to GuC */ - size = sizeof(struct guc_ads); + size = sizeof(struct guc_ads) + sizeof(struct guc_policies); obj = guc->ads_obj; if (!obj) { @@ -876,6 +899,13 @@ static void guc_create_ads(struct intel_guc *guc) for_each_ring(ring, dev_priv, i) ads->eng_state_size[i] = intel_lr_context_size(ring); + /* GuC scheduling policies */ + policies = (void *)ads + sizeof(struct guc_ads); + init_guc_policies(policies); + + ads->scheduler_policies = i915_gem_obj_ggtt_offset(obj) + + sizeof(struct guc_ads); + kunmap(page); } diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index bc9829eaabb3..1ce5f5ba3147 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h @@ -39,6 +39,7 @@ #define GUC_CTX_PRIORITY_HIGH 1 #define GUC_CTX_PRIORITY_KMD_NORMAL 2 #define GUC_CTX_PRIORITY_NORMAL 3 +#define GUC_CTX_PRIORITY_NUM 4 #define GUC_MAX_GPU_CONTEXTS 1024 #define GUC_INVALID_CTX_ID GUC_MAX_GPU_CONTEXTS @@ -316,6 +317,50 @@ struct guc_context_desc { #define GUC_POWER_D2 3 #define GUC_POWER_D3 4 +/* Scheduling policy settings */ + +/* Reset engine upon preempt failure */ +#define POLICY_RESET_ENGINE (1<<0) +/* Preempt to idle on quantum expiry */ +#define POLICY_PREEMPT_TO_IDLE (1<<1) + +#define POLICY_MAX_NUM_WI 15 + +struct guc_policy { + /* Time for one workload to execute. (in micro seconds) */ + u32 execution_quantum; + u32 reserved1; + + /* Time to wait for a preemption request to completed before issuing a + * reset. (in micro seconds). */ + u32 preemption_time; + + /* How much time to allow to run after the first fault is observed. + * Then preempt afterwards. (in micro seconds) */ + u32 fault_time; + + u32 policy_flags; + u32 reserved[2]; +} __packed; + +struct guc_policies { + struct guc_policy policy[GUC_CTX_PRIORITY_NUM][I915_NUM_RINGS]; + + /* In micro seconds. How much time to allow before DPC processing is + * called back via interrupt (to prevent DPC queue drain starving). + * Typically 1000s of micro seconds (example only, not granularity). */ + u32 dpc_promote_time; + + /* Must be set to take these new values. */ + u32 is_valid; + + /* Max number of WIs to process per call. A large value may keep CS + * idle. */ + u32 max_num_work_items; + + u32 reserved[19]; +} __packed; + /* GuC Additional Data Struct */ struct guc_ads { -- cgit v1.2.3 From 5c148e044e55304073de3cc2b41c80b1a780687f Mon Sep 17 00:00:00 2001 From: Alex Dai Date: Fri, 18 Dec 2015 12:00:11 -0800 Subject: drm/i915/guc: Add GuC ADS - MMIO reg state GuC needs to know which registers and how they will be saved and restored during event such as engine reset or power state changes. For now only the base address of reg state is initialized. The detail register table probably will be setup in future GuC TDR or Preemption patch series. Signed-off-by: Alex Dai Reviewed-by: Dave Gordon Link: http://patchwork.freedesktop.org/patch/msgid/1450468812-4882-5-git-send-email-yu.dai@intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_guc_submission.c | 22 +++++++++++++++++- drivers/gpu/drm/i915/intel_guc_fwif.h | 37 ++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 1eb8db8d1feb..9c244247c13e 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -867,12 +867,15 @@ static void guc_create_ads(struct intel_guc *guc) struct drm_i915_gem_object *obj; struct guc_ads *ads; struct guc_policies *policies; + struct guc_mmio_reg_state *reg_state; struct intel_engine_cs *ring; struct page *page; u32 size, i; /* The ads obj includes the struct itself and buffers passed to GuC */ - size = sizeof(struct guc_ads) + sizeof(struct guc_policies); + size = sizeof(struct guc_ads) + sizeof(struct guc_policies) + + sizeof(struct guc_mmio_reg_state) + + GUC_S3_SAVE_SPACE_PAGES * PAGE_SIZE; obj = guc->ads_obj; if (!obj) { @@ -906,6 +909,23 @@ static void guc_create_ads(struct intel_guc *guc) ads->scheduler_policies = i915_gem_obj_ggtt_offset(obj) + sizeof(struct guc_ads); + /* MMIO reg state */ + reg_state = (void *)policies + sizeof(struct guc_policies); + + for (i = 0; i < I915_NUM_RINGS; i++) { + reg_state->mmio_white_list[i].mmio_start = + dev_priv->ring[i].mmio_base + GUC_MMIO_WHITE_LIST_START; + + /* Nothing to be saved or restored for now. */ + reg_state->mmio_white_list[i].count = 0; + } + + ads->reg_state_addr = ads->scheduler_policies + + sizeof(struct guc_policies); + + ads->reg_state_buffer = ads->reg_state_addr + + sizeof(struct guc_mmio_reg_state); + kunmap(page); } diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index 1ce5f5ba3147..b4632f0bf7b2 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h @@ -361,6 +361,43 @@ struct guc_policies { u32 reserved[19]; } __packed; +/* GuC MMIO reg state struct */ + +#define GUC_REGSET_FLAGS_NONE 0x0 +#define GUC_REGSET_POWERCYCLE 0x1 +#define GUC_REGSET_MASKED 0x2 +#define GUC_REGSET_ENGINERESET 0x4 +#define GUC_REGSET_SAVE_DEFAULT_VALUE 0x8 +#define GUC_REGSET_SAVE_CURRENT_VALUE 0x10 + +#define GUC_REGSET_MAX_REGISTERS 20 +#define GUC_MMIO_WHITE_LIST_START 0x24d0 +#define GUC_MMIO_WHITE_LIST_MAX 12 +#define GUC_S3_SAVE_SPACE_PAGES 10 + +struct guc_mmio_regset { + struct __packed { + u32 offset; + u32 value; + u32 flags; + } registers[GUC_REGSET_MAX_REGISTERS]; + + u32 values_valid; + u32 number_of_registers; +} __packed; + +struct guc_mmio_reg_state { + struct guc_mmio_regset global_reg; + struct guc_mmio_regset engine_reg[I915_NUM_RINGS]; + + /* MMIO registers that are set as non privileged */ + struct __packed { + u32 mmio_start; + u32 offsets[GUC_MMIO_WHITE_LIST_MAX]; + u32 count; + } mmio_white_list[I915_NUM_RINGS]; +} __packed; + /* GuC Additional Data Struct */ struct guc_ads { -- cgit v1.2.3 From b6a5cd7ea246b68240d49ef78cc339ef8595c10c Mon Sep 17 00:00:00 2001 From: Alex Dai Date: Fri, 18 Dec 2015 12:00:12 -0800 Subject: drm/i915/guc: Add GuC ADS - enabling ADS Set ADS enabling flag during GuC init. Signed-off-by: Alex Dai Reviewed-by: Dave Gordon Link: http://patchwork.freedesktop.org/patch/msgid/1450468812-4882-6-git-send-email-yu.dai@intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_guc_loader.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 550921f2ef7d..d20788ffd341 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -165,6 +165,13 @@ static void set_guc_init_params(struct drm_i915_private *dev_priv) i915.guc_log_level << GUC_LOG_VERBOSITY_SHIFT; } + if (guc->ads_obj) { + u32 ads = (u32)i915_gem_obj_ggtt_offset(guc->ads_obj) + >> PAGE_SHIFT; + params[GUC_CTL_DEBUG] |= ads << GUC_ADS_ADDR_SHIFT; + params[GUC_CTL_DEBUG] |= GUC_ADS_ENABLED; + } + /* If GuC submission is enabled, set up additional parameters here */ if (i915.enable_guc_submission) { u32 pgs = i915_gem_obj_ggtt_offset(dev_priv->guc.ctx_pool_obj); -- cgit v1.2.3 From 513485fd10b17bd6870379ef9fff397419f20798 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Dec 2015 15:10:53 +0200 Subject: drm/i915/bios: fix header define name for intel_bios.h Just for OCD. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/730e41760133dbaa1e3ab1b91631ada18676810c.1450702954.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_bios.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 2dc46a98c332..21c162e01189 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -25,8 +25,8 @@ * */ -#ifndef _I830_BIOS_H_ -#define _I830_BIOS_H_ +#ifndef _INTEL_BIOS_H_ +#define _INTEL_BIOS_H_ /** * struct vbt_header - VBT Header structure @@ -983,4 +983,4 @@ enum mipi_gpio_pin_index { MIPI_GPIO_MAX }; -#endif /* _I830_BIOS_H_ */ +#endif /* _INTEL_BIOS_H_ */ -- cgit v1.2.3 From 0f8689f5bb569d2ff19f5248b2d3940ad6d35504 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Dec 2015 15:10:54 +0200 Subject: drm/i915/bios: split the MIPI DSI VBT block parsing to two There's two blocks to parse, have one function per block. The existing one cuts neatly into two. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/6c9598e2b4d07e8d264617cdfe8b6527a74261f7.1450702954.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_bios.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index b6ccba13779e..5ea6087c40c1 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -765,16 +765,12 @@ static u8 *goto_next_sequence(u8 *data, int *size) } static void -parse_mipi(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) +parse_mipi_config(struct drm_i915_private *dev_priv, + const struct bdb_header *bdb) { const struct bdb_mipi_config *start; - const struct bdb_mipi_sequence *sequence; const struct mipi_config *config; const struct mipi_pps_data *pps; - u8 *data; - const u8 *seq_data; - int i, panel_id, seq_size; - u16 block_size; /* parse MIPI blocks only if LFP type is MIPI */ if (!dev_priv->vbt.has_mipi) @@ -820,8 +816,22 @@ parse_mipi(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) /* We have mandatory mipi config blocks. Initialize as generic panel */ dev_priv->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID; +} + +static void +parse_mipi_sequence(struct drm_i915_private *dev_priv, + const struct bdb_header *bdb) +{ + const struct bdb_mipi_sequence *sequence; + const u8 *seq_data; + u8 *data; + u16 block_size; + int i, panel_id, seq_size; + + /* Only our generic panel driver uses the sequence block. */ + if (dev_priv->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID) + return; - /* Check if we have sequence block as well */ sequence = find_section(bdb, BDB_MIPI_SEQUENCE); if (!sequence) { DRM_DEBUG_KMS("No MIPI Sequence found, parsing complete\n"); @@ -1359,7 +1369,8 @@ intel_bios_init(struct drm_i915_private *dev_priv) parse_driver_features(dev_priv, bdb); parse_edp(dev_priv, bdb); parse_psr(dev_priv, bdb); - parse_mipi(dev_priv, bdb); + parse_mipi_config(dev_priv, bdb); + parse_mipi_sequence(dev_priv, bdb); parse_ddi_ports(dev_priv, bdb); if (bios) -- cgit v1.2.3 From 08c0888b28d75cf4ee9ca0bbe1a2c55ddef87423 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Dec 2015 15:10:55 +0200 Subject: drm/i915/bios: have get_blocksize() support MIPI sequence block v3+ Have get_blocksize() support the special case of MIPI sequence block v3+ which has a separate field for size. Provide and use abstractions for getting the blocksize given a pointer to the block "envelope", i.e. pointer to the block id, and given a pointer to the block payload data. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/e935bd5e119a83dd91214c47e6cd4f6ce8b2a17e.1450702954.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_bios.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 5ea6087c40c1..961ae7f6d075 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -58,6 +58,22 @@ static int panel_type; +/* Get BDB block size given a pointer to Block ID. */ +static u32 _get_blocksize(const u8 *block_base) +{ + /* The MIPI Sequence Block v3+ has a separate size field. */ + if (*block_base == BDB_MIPI_SEQUENCE && *(block_base + 3) >= 3) + return *((const u32 *)(block_base + 4)); + else + return *((const u16 *)(block_base + 1)); +} + +/* Get BDB block size give a pointer to data after Block ID and Block Size. */ +static u32 get_blocksize(const void *block_data) +{ + return _get_blocksize(block_data - 3); +} + static const void * find_section(const void *_bdb, int section_id) { @@ -74,14 +90,8 @@ find_section(const void *_bdb, int section_id) /* walk the sections looking for section_id */ while (index + 3 < total) { current_id = *(base + index); - index++; - - current_size = *((const u16 *)(base + index)); - index += 2; - - /* The MIPI Sequence Block v3+ has a separate size field. */ - if (current_id == BDB_MIPI_SEQUENCE && *(base + index) >= 3) - current_size = *((const u32 *)(base + index + 1)); + current_size = _get_blocksize(base + index); + index += 3; if (index + current_size > total) return NULL; @@ -95,16 +105,6 @@ find_section(const void *_bdb, int section_id) return NULL; } -static u16 -get_blocksize(const void *p) -{ - u16 *block_ptr, block_size; - - block_ptr = (u16 *)((char *)p - 2); - block_size = *block_ptr; - return block_size; -} - static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, const struct lvds_dvo_timing *dvo_timing) -- cgit v1.2.3 From 5db72099e8ec26a480420fc8b9326902a1a4ef69 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 5 Jan 2016 15:50:51 +0200 Subject: drm/i915/bios: abstract finding the panel sequence block Make the whole thing easier to read. While at it, make the parsing more robust, and ensure we don't read past buffer being parsed. v2: improve commit message (Daniel) Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1452001851-8967-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_bios.c | 76 +++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 961ae7f6d075..422ba76700e3 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -697,7 +697,7 @@ parse_psr(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) dev_priv->vbt.psr.tp2_tp3_wakeup_time = psr_table->tp2_tp3_wakeup_time; } -static u8 *goto_next_sequence(u8 *data, int *size) +static u8 *goto_next_sequence(u8 *data, u16 *size) { u16 len; int tmp = *size; @@ -818,15 +818,52 @@ parse_mipi_config(struct drm_i915_private *dev_priv, dev_priv->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID; } +/* Find the sequence block and size for the given panel. */ +static const u8 * +find_panel_sequence_block(const struct bdb_mipi_sequence *sequence, + u16 panel_id, u16 *seq_size) +{ + u32 total = get_blocksize(sequence); + const u8 *data = &sequence->data[0]; + u8 current_id; + u16 current_size; + int index = 0; + int i; + + for (i = 0; i < MAX_MIPI_CONFIGURATIONS && index + 3 < total; i++) { + current_id = *(data + index); + index++; + + current_size = *((const u16 *)(data + index)); + index += 2; + + if (index + current_size > total) { + DRM_ERROR("Invalid sequence block\n"); + return NULL; + } + + if (current_id == panel_id) { + *seq_size = current_size; + return data + index; + } + + index += current_size; + } + + DRM_ERROR("Sequence block detected but no valid configuration\n"); + + return NULL; +} + static void parse_mipi_sequence(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) { const struct bdb_mipi_sequence *sequence; const u8 *seq_data; + u16 seq_size; u8 *data; u16 block_size; - int i, panel_id, seq_size; /* Only our generic panel driver uses the sequence block. */ if (dev_priv->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID) @@ -853,40 +890,11 @@ parse_mipi_sequence(struct drm_i915_private *dev_priv, */ dev_priv->vbt.dsi.seq_version = sequence->version; - seq_data = &sequence->data[0]; - - /* - * sequence block is variable length and hence we need to parse and - * get the sequence data for specific panel id - */ - for (i = 0; i < MAX_MIPI_CONFIGURATIONS; i++) { - panel_id = *seq_data; - seq_size = *((u16 *) (seq_data + 1)); - if (panel_id == panel_type) - break; - - /* skip the sequence including seq header of 3 bytes */ - seq_data = seq_data + 3 + seq_size; - if ((seq_data - &sequence->data[0]) > block_size) { - DRM_ERROR("Sequence start is beyond sequence block size, corrupted sequence block\n"); - return; - } - } - - if (i == MAX_MIPI_CONFIGURATIONS) { - DRM_ERROR("Sequence block detected but no valid configuration\n"); + seq_data = find_panel_sequence_block(sequence, panel_type, &seq_size); + if (!seq_data) return; - } - - /* check if found sequence is completely within the sequence block - * just being paranoid */ - if (seq_size > block_size) { - DRM_ERROR("Corrupted sequence/size, bailing out\n"); - return; - } - /* skip the panel id(1 byte) and seq size(2 bytes) */ - dev_priv->vbt.dsi.data = kmemdup(seq_data + 3, seq_size, GFP_KERNEL); + dev_priv->vbt.dsi.data = kmemdup(seq_data, seq_size, GFP_KERNEL); if (!dev_priv->vbt.dsi.data) return; -- cgit v1.2.3 From 8d3ed2f3139792d9900602aa5f790032baa0a22a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Dec 2015 15:10:57 +0200 Subject: drm/i915/bios: rewrite sequence block parsing Make everything a bit more readable and clear. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/e8f2a62d78d90981a6b49fdf9ab3594f60a46033.1450702954.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_bios.c | 158 +++++++++++++------------------------- drivers/gpu/drm/i915/intel_bios.h | 4 +- 3 files changed, 57 insertions(+), 107 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index cf7e0fce01ac..c6dd4db29cea 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1477,7 +1477,7 @@ struct intel_vbt_data { u8 seq_version; u32 size; u8 *data; - u8 *sequence[MIPI_SEQ_MAX]; + const u8 *sequence[MIPI_SEQ_MAX]; } dsi; int crt_ddc_pin; diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 422ba76700e3..71c739e33101 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -697,73 +697,6 @@ parse_psr(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) dev_priv->vbt.psr.tp2_tp3_wakeup_time = psr_table->tp2_tp3_wakeup_time; } -static u8 *goto_next_sequence(u8 *data, u16 *size) -{ - u16 len; - int tmp = *size; - - if (--tmp < 0) - return NULL; - - /* goto first element */ - data++; - while (1) { - switch (*data) { - case MIPI_SEQ_ELEM_SEND_PKT: - /* - * skip by this element payload size - * skip elem id, command flag and data type - */ - tmp -= 5; - if (tmp < 0) - return NULL; - - data += 3; - len = *((u16 *)data); - - tmp -= len; - if (tmp < 0) - return NULL; - - /* skip by len */ - data = data + 2 + len; - break; - case MIPI_SEQ_ELEM_DELAY: - /* skip by elem id, and delay is 4 bytes */ - tmp -= 5; - if (tmp < 0) - return NULL; - - data += 5; - break; - case MIPI_SEQ_ELEM_GPIO: - tmp -= 3; - if (tmp < 0) - return NULL; - - data += 3; - break; - default: - DRM_ERROR("Unknown element\n"); - return NULL; - } - - /* end of sequence ? */ - if (*data == 0) - break; - } - - /* goto next sequence or end of block byte */ - if (--tmp < 0) - return NULL; - - data++; - - /* update amount of data left for the sequence block to be parsed */ - *size = tmp; - return data; -} - static void parse_mipi_config(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) @@ -855,6 +788,39 @@ find_panel_sequence_block(const struct bdb_mipi_sequence *sequence, return NULL; } +static int goto_next_sequence(const u8 *data, int index, int total) +{ + u16 len; + + /* Skip Sequence Byte. */ + for (index = index + 1; index < total; index += len) { + u8 operation_byte = *(data + index); + index++; + + switch (operation_byte) { + case MIPI_SEQ_ELEM_END: + return index; + case MIPI_SEQ_ELEM_SEND_PKT: + if (index + 4 > total) + return 0; + + len = *((const u16 *)(data + index + 2)) + 4; + break; + case MIPI_SEQ_ELEM_DELAY: + len = 4; + break; + case MIPI_SEQ_ELEM_GPIO: + len = 2; + break; + default: + DRM_ERROR("Unknown operation byte\n"); + return 0; + } + } + + return 0; +} + static void parse_mipi_sequence(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) @@ -863,7 +829,7 @@ parse_mipi_sequence(struct drm_i915_private *dev_priv, const u8 *seq_data; u16 seq_size; u8 *data; - u16 block_size; + int index = 0; /* Only our generic panel driver uses the sequence block. */ if (dev_priv->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID) @@ -883,59 +849,43 @@ parse_mipi_sequence(struct drm_i915_private *dev_priv, DRM_DEBUG_DRIVER("Found MIPI sequence block\n"); - block_size = get_blocksize(sequence); - - /* - * parse the sequence block for individual sequences - */ - dev_priv->vbt.dsi.seq_version = sequence->version; - seq_data = find_panel_sequence_block(sequence, panel_type, &seq_size); if (!seq_data) return; - dev_priv->vbt.dsi.data = kmemdup(seq_data, seq_size, GFP_KERNEL); - if (!dev_priv->vbt.dsi.data) + data = kmemdup(seq_data, seq_size, GFP_KERNEL); + if (!data) return; - /* - * loop into the sequence data and split into multiple sequneces - * There are only 5 types of sequences as of now - */ - data = dev_priv->vbt.dsi.data; - dev_priv->vbt.dsi.size = seq_size; + /* Parse the sequences, store pointers to each sequence. */ + for (;;) { + u8 seq_id = *(data + index); + if (seq_id == MIPI_SEQ_END) + break; - /* two consecutive 0x00 indicate end of all sequences */ - while (1) { - int seq_id = *data; - if (MIPI_SEQ_MAX > seq_id && seq_id > MIPI_SEQ_UNDEFINED) { - dev_priv->vbt.dsi.sequence[seq_id] = data; - DRM_DEBUG_DRIVER("Found mipi sequence - %d\n", seq_id); - } else { - DRM_ERROR("undefined sequence\n"); + if (seq_id >= MIPI_SEQ_MAX) { + DRM_ERROR("Unknown sequence %u\n", seq_id); goto err; } - /* partial parsing to skip elements */ - data = goto_next_sequence(data, &seq_size); + dev_priv->vbt.dsi.sequence[seq_id] = data + index; - if (data == NULL) { - DRM_ERROR("Sequence elements going beyond block itself. Sequence block parsing failed\n"); + index = goto_next_sequence(data, index, seq_size); + if (!index) { + DRM_ERROR("Invalid sequence %u\n", seq_id); goto err; } - - if (*data == 0) - break; /* end of sequence reached */ } - DRM_DEBUG_DRIVER("MIPI related vbt parsing complete\n"); + dev_priv->vbt.dsi.data = data; + dev_priv->vbt.dsi.size = seq_size; + dev_priv->vbt.dsi.seq_version = sequence->version; + + DRM_DEBUG_DRIVER("MIPI related VBT parsing complete\n"); return; -err: - kfree(dev_priv->vbt.dsi.data); - dev_priv->vbt.dsi.data = NULL; - /* error during parsing so set all pointers to null - * because of partial parsing */ +err: + kfree(data); memset(dev_priv->vbt.dsi.sequence, 0, sizeof(dev_priv->vbt.dsi.sequence)); } diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 21c162e01189..4e87df16e7b3 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -954,7 +954,7 @@ struct bdb_mipi_sequence { /* MIPI Sequnece Block definitions */ enum mipi_seq { - MIPI_SEQ_UNDEFINED = 0, + MIPI_SEQ_END = 0, MIPI_SEQ_ASSERT_RESET, MIPI_SEQ_INIT_OTP, MIPI_SEQ_DISPLAY_ON, @@ -964,7 +964,7 @@ enum mipi_seq { }; enum mipi_seq_element { - MIPI_SEQ_ELEM_UNDEFINED = 0, + MIPI_SEQ_ELEM_END = 0, MIPI_SEQ_ELEM_SEND_PKT, MIPI_SEQ_ELEM_DELAY, MIPI_SEQ_ELEM_GPIO, -- cgit v1.2.3 From 5cda0d20f949a111758b897c33f249f097f01727 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Dec 2015 15:10:58 +0200 Subject: drm/i915/dsi: be defensive about out of bounds sequence id Untie the VBT based generic panel driver from the VBT parsing, so that the two don't have to be updated in lockstep. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/7a6e3e7c4404c0e4dbcf003acd8737a6ecbe218f.1450702954.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index aa1f7bc8f4d0..c6aea69230e8 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -246,14 +246,21 @@ static const fn_mipi_elem_exec exec_elem[] = { */ static const char * const seq_name[] = { - "UNDEFINED", - "MIPI_SEQ_ASSERT_RESET", - "MIPI_SEQ_INIT_OTP", - "MIPI_SEQ_DISPLAY_ON", - "MIPI_SEQ_DISPLAY_OFF", - "MIPI_SEQ_DEASSERT_RESET" + [MIPI_SEQ_ASSERT_RESET] = "MIPI_SEQ_ASSERT_RESET", + [MIPI_SEQ_INIT_OTP] = "MIPI_SEQ_INIT_OTP", + [MIPI_SEQ_DISPLAY_ON] = "MIPI_SEQ_DISPLAY_ON", + [MIPI_SEQ_DISPLAY_OFF] = "MIPI_SEQ_DISPLAY_OFF", + [MIPI_SEQ_DEASSERT_RESET] = "MIPI_SEQ_DEASSERT_RESET", }; +static const char *sequence_name(enum mipi_seq seq_id) +{ + if (seq_id < ARRAY_SIZE(seq_name) && seq_name[seq_id]) + return seq_name[seq_id]; + else + return "(unknown)"; +} + static void generic_exec_sequence(struct intel_dsi *intel_dsi, const u8 *data) { fn_mipi_elem_exec mipi_elem_exec; @@ -262,7 +269,8 @@ static void generic_exec_sequence(struct intel_dsi *intel_dsi, const u8 *data) if (!data) return; - DRM_DEBUG_DRIVER("Starting MIPI sequence - %s\n", seq_name[*data]); + DRM_DEBUG_DRIVER("Starting MIPI sequence %u - %s\n", + *data, sequence_name(*data)); /* go to the first element of the sequence */ data++; -- cgit v1.2.3 From 28c72840a787559851aa8d70a18bb5ac41b73b53 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Dec 2015 15:10:59 +0200 Subject: drm/i915/dsi: be defensive about out of bounds operation byte Untie the VBT based generic panel driver from the VBT parsing, so that the two don't have to be updated in lockstep. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/01c71ac89a9db8bc7b8ae0fb05c50a5fae362dc4.1450702954.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index c6aea69230e8..9bd920809697 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -232,11 +232,9 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) typedef const u8 * (*fn_mipi_elem_exec)(struct intel_dsi *intel_dsi, const u8 *data); static const fn_mipi_elem_exec exec_elem[] = { - NULL, /* reserved */ - mipi_exec_send_packet, - mipi_exec_delay, - mipi_exec_gpio, - NULL, /* status read; later */ + [MIPI_SEQ_ELEM_SEND_PKT] = mipi_exec_send_packet, + [MIPI_SEQ_ELEM_DELAY] = mipi_exec_delay, + [MIPI_SEQ_ELEM_GPIO] = mipi_exec_gpio, }; /* @@ -264,7 +262,6 @@ static const char *sequence_name(enum mipi_seq seq_id) static void generic_exec_sequence(struct intel_dsi *intel_dsi, const u8 *data) { fn_mipi_elem_exec mipi_elem_exec; - int index; if (!data) return; @@ -277,15 +274,14 @@ static void generic_exec_sequence(struct intel_dsi *intel_dsi, const u8 *data) /* parse each byte till we reach end of sequence byte - 0x00 */ while (1) { - index = *data; - mipi_elem_exec = exec_elem[index]; - if (!mipi_elem_exec) { - DRM_ERROR("Unsupported MIPI element, skipping sequence execution\n"); + u8 operation_byte = *data++; + if (operation_byte >= ARRAY_SIZE(exec_elem) || + !exec_elem[operation_byte]) { + DRM_ERROR("Unsupported MIPI operation byte %u\n", + operation_byte); return; } - - /* goto element payload */ - data++; + mipi_elem_exec = exec_elem[operation_byte]; /* execute the element specific rotines */ data = mipi_elem_exec(intel_dsi, data); -- cgit v1.2.3 From c5d46ee20675379105bfd1ce422fe50169106e62 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Tue, 5 Jan 2016 12:21:33 +0000 Subject: drm/i915: add kerneldoc for intel_lr_context_size() This function was recently renamed & exposed, so now it gets documented Signed-off-by: Dave Gordon Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1451996493-16079-1-git-send-email-david.s.gordon@intel.com --- drivers/gpu/drm/i915/intel_lrc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 808515cef607..8096c6a79424 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -2399,6 +2399,20 @@ void intel_lr_context_free(struct intel_context *ctx) } } +/** + * intel_lr_context_size() - return the size of the context for an engine + * @ring: which engine to find the context size for + * + * Each engine may require a different amount of space for a context image, + * so when allocating (or copying) an image, this function can be used to + * find the right size for the specific engine. + * + * Return: size (in bytes) of an engine-specific context image + * + * Note: this size includes the HWSP, which is part of the context image + * in LRC mode, but does not include the "shared data page" used with + * GuC submission. The caller should account for this if using the GuC. + */ uint32_t intel_lr_context_size(struct intel_engine_cs *ring) { int ret = 0; -- cgit v1.2.3 From c5236470feb59e357ce4d5fa58d26f0fbe432e54 Mon Sep 17 00:00:00 2001 From: Ankitprasad Sharma Date: Tue, 22 Dec 2015 11:50:44 +0530 Subject: drm/i915: Allow use of get_dma_address for stolen backed objects i915_gem_object_get_dma_address function is used to retrieve the dma address of a particular page so as to map it in a given GTT entry for CPU access. This function would be used for stolen backed objects also for tasks like pwrite, clearing of the pages etc. So the obj->get_page.sg needs to be initialized for the stolen objects also. Signed-off-by: Ankitprasad Sharma Link: http://patchwork.freedesktop.org/patch/msgid/1450765253-32104-2-git-send-email-ankitprasad.r.sharma@intel.com Reviewed-by: Tvrtko Ursulin Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_stolen.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 3476877fc0d6..c384dc9c8a63 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -569,6 +569,9 @@ _i915_gem_object_create_stolen(struct drm_device *dev, if (obj->pages == NULL) goto cleanup; + obj->get_page.sg = obj->pages->sgl; + obj->get_page.last = 0; + i915_gem_object_pin_pages(obj); obj->stolen = stolen; -- cgit v1.2.3 From becd9ca2de656ccd8d02c434742388aead336147 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 5 Jan 2016 17:54:07 +0100 Subject: drm/i915: Tune down rpm wakelock debug checks They're causing massive amounts of dmesg noise and hence CI noise all over the place. Enabling them for a bit was good enough to refresh our task list of what's still needed to enable rpm by default. To make sure we're not forgetting to make this noisy again add a FIXME comment. Fixes: da5827c36607 ("drm/i915: add assert_rpm_wakelock_held helper") Cc: Imre Deak Cc: drm-intel-fixes@lists.freedesktop.org Cc: Chris Wilson Acked-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1452012847-4737-1-git-send-email-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 0438b575e1fa..a3b2025da563 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1453,8 +1453,10 @@ static inline void assert_rpm_wakelock_held(struct drm_i915_private *dev_priv) { assert_rpm_device_not_suspended(dev_priv); - WARN_ONCE(!atomic_read(&dev_priv->pm.wakeref_count), - "RPM wakelock ref not held during HW access"); + /* FIXME: Needs to be converted back to WARN_ONCE, but currently causes + * too much noise. */ + if (!atomic_read(&dev_priv->pm.wakeref_count)) + DRM_DEBUG_DRIVER("RPM wakelock ref not held during HW access"); } static inline int -- cgit v1.2.3 From 42f1cae8c079bcceb3cff079fddc3ff8852c788f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 27 Nov 2015 13:28:55 +0000 Subject: drm/i915: Restore inhibiting the load of the default context Following a GPU reset, we may leave the context in a poorly defined state, and reloading from that context will leave the GPU flummoxed. For secondary contexts, this will lead to that context being banned - but currently it is also causing the default context to become banned, leading to turmoil in the shared state. This is a regression from commit 6702cf16e0ba8b0129f5aa1b6609d4e9c70bc13b [v4.1] Author: Ben Widawsky Date: Mon Mar 16 16:00:58 2015 +0000 drm/i915: Initialize all contexts which quietly introduced the removal of the MI_RESTORE_INHIBIT on the default context. v2: Mark the global default context as uninitialized on GPU reset so that the context-local workarounds are reloaded upon re-enabling. Signed-off-by: Chris Wilson Cc: Michel Thierry Cc: Mika Kuoppala Cc: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1448630935-27377-1-git-send-email-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala Cc: stable@vger.kernel.org [danvet: This seems to fix a gpu hand on after the first resume, resulting in any future suspend operation failing with -EIO because the gpu seems to be in a funky state. Somehow this patch fixes that.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 900ffd044db8..c25083c78ba7 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -347,6 +347,10 @@ void i915_gem_context_reset(struct drm_device *dev) i915_gem_context_unreference(lctx); ring->last_context = NULL; } + + /* Force the GPU state to be reinitialised on enabling */ + if (ring->default_context) + ring->default_context->legacy_hw_ctx.initialized = false; } } @@ -715,7 +719,7 @@ static int do_switch(struct drm_i915_gem_request *req) if (ret) goto unpin_out; - if (!to->legacy_hw_ctx.initialized) { + if (!to->legacy_hw_ctx.initialized || i915_gem_context_is_default(to)) { hw_flags |= MI_RESTORE_INHIBIT; /* NB: If we inhibit the restore, the context is not allowed to * die because future work may end up depending on valid address -- cgit v1.2.3 From 0a8d8a8667c7e66f4fa2498be18d47f8b296b430 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 3 Dec 2015 11:37:38 -0800 Subject: drm/i915: Setup clipped src/dest coordinates during FB reconstruction (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plane state objects contain two copies of src/dest coordinates: the original (requested by userspace) coordinates in the base drm_plane_state object, and a second, clipped copy (i.e., what we actually want to program to the hardware) in intel_plane_state. We've only been setting up the former set of values during boot time FB reconstruction, but we should really be initializing both. Note that the code here probably still needs some more work since we make a lot of assumptions about how the BIOS programmed the hardware that may not always be true, especially on gen9+; e.g., * Primary plane might not be positioned at 0,0 * Primary plane could have been rotated by the BIOS * Primary plane might be scaled * The BIOS fb might be a single "extended mode" FB that spans multiple displays. * ...etc... v2: Reword/expand commit message description of assumptions we make Signed-off-by: Matt Roper Reviewed-by(v1): Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1449171462-30763-4-git-send-email-matthew.d.roper@intel.com Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/intel_display.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index eea2cd26ba17..c1a3969f3d4c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2598,6 +2598,8 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, struct drm_plane_state *plane_state = primary->state; struct drm_crtc_state *crtc_state = intel_crtc->base.state; struct intel_plane *intel_plane = to_intel_plane(primary); + struct intel_plane_state *intel_state = + to_intel_plane_state(plane_state); struct drm_framebuffer *fb; if (!plane_config->fb) @@ -2659,6 +2661,15 @@ valid_fb: plane_state->crtc_w = fb->width; plane_state->crtc_h = fb->height; + intel_state->src.x1 = plane_state->src_x; + intel_state->src.y1 = plane_state->src_y; + intel_state->src.x2 = plane_state->src_x + plane_state->src_w; + intel_state->src.y2 = plane_state->src_y + plane_state->src_h; + intel_state->dst.x1 = plane_state->crtc_x; + intel_state->dst.y1 = plane_state->crtc_y; + intel_state->dst.x2 = plane_state->crtc_x + plane_state->crtc_w; + intel_state->dst.y2 = plane_state->crtc_y + plane_state->crtc_h; + obj = intel_fb_obj(fb); if (obj->tiling_mode != I915_TILING_NONE) dev_priv->preserve_bios_swizzle = true; -- cgit v1.2.3 From ee91a15972cc70efa4d17b4bbdb61ff314528110 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 3 Dec 2015 11:37:39 -0800 Subject: drm/i915: Convert hsw_compute_linetime_wm to use in-flight state When watermark calculation was moved up to the atomic check phase, the code was updated to calculate based on in-flight atomic state rather than already-committed state. However the hsw_compute_linetime_wm() didn't get updated and continued to pull values out of the currently-committed CRTC state. On platforms that call this function (HSW/BDW only), this will cause problems when we go to enable the CRTC since we'll pull the current mode (off) rather than the mode we're calculating for and wind up with a divide by zero error. This was an oversight in commit: commit a28170f3389f4e42db95e595b0d86384a79de696 Author: Matt Roper Date: Thu Sep 24 15:53:16 2015 -0700 drm/i915: Calculate ILK-style watermarks during atomic check (v3) Signed-off-by: Matt Roper Link: http://patchwork.freedesktop.org/patch/msgid/1449171462-30763-5-git-send-email-matthew.d.roper@intel.com Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/intel_pm.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 02fe081878ad..0f22d11937b4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1998,14 +1998,19 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv, } static uint32_t -hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc) +hsw_compute_linetime_wm(struct drm_device *dev, + struct intel_crtc_state *cstate) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = + &cstate->base.adjusted_mode; u32 linetime, ips_linetime; - if (!intel_crtc->active) + if (!cstate->base.active) + return 0; + if (WARN_ON(adjusted_mode->crtc_clock == 0)) + return 0; + if (WARN_ON(dev_priv->cdclk_freq == 0)) return 0; /* The WM are computed with base on how long it takes to fill a single @@ -2313,8 +2318,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, pristate, sprstate, curstate, &pipe_wm->wm[0]); if (IS_HASWELL(dev) || IS_BROADWELL(dev)) - pipe_wm->linetime = hsw_compute_linetime_wm(dev, - &intel_crtc->base); + pipe_wm->linetime = hsw_compute_linetime_wm(dev, cstate); /* LP0 watermarks always use 1/2 DDB partitioning */ ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max); -- cgit v1.2.3 From 151268821e6f08956b28b6ff90fae187a5b230b8 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 3 Dec 2015 11:37:40 -0800 Subject: drm/i915: Add extra paranoia to ILK watermark calculations Our low-level watermark calculation functions don't get called when the CRTC is disabled or the relevant plane is invisible, so they should never see a zero htotal or zero bpp. However add some checks to ensure this is true so that we don't wind up dividing by zero if we make a mistake elsewhere in the driver (which the atomic watermark series has revealed we might be). References: http://lists.freedesktop.org/archives/intel-gfx/2015-October/077370.html Signed-off-by: Matt Roper Link: http://patchwork.freedesktop.org/patch/msgid/1449171462-30763-6-git-send-email-matthew.d.roper@intel.com Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/intel_pm.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0f22d11937b4..f9cbd2e81f54 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1672,6 +1672,9 @@ uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config) if (pipe_h < pfit_h) pipe_h = pfit_h; + if (WARN_ON(!pfit_w || !pfit_h)) + return pixel_rate; + pixel_rate = div_u64((uint64_t) pixel_rate * pipe_w * pipe_h, pfit_w * pfit_h); } @@ -1703,6 +1706,8 @@ static uint32_t ilk_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal, if (WARN(latency == 0, "Latency value missing\n")) return UINT_MAX; + if (WARN_ON(!pipe_htotal)) + return UINT_MAX; ret = (latency * pixel_rate) / (pipe_htotal * 10000); ret = (ret + 1) * horiz_pixels * bytes_per_pixel; @@ -1713,6 +1718,17 @@ static uint32_t ilk_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal, static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels, uint8_t bytes_per_pixel) { + /* + * Neither of these should be possible since this function shouldn't be + * called if the CRTC is off or the plane is invisible. But let's be + * extra paranoid to avoid a potential divide-by-zero if we screw up + * elsewhere in the driver. + */ + if (WARN_ON(!bytes_per_pixel)) + return 0; + if (WARN_ON(!horiz_pixels)) + return 0; + return DIV_ROUND_UP(pri_val * 64, horiz_pixels * bytes_per_pixel) + 2; } -- cgit v1.2.3 From d93c037246104e403436ffe339bcb832185d0627 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 3 Dec 2015 11:37:41 -0800 Subject: drm/i915: Sanitize watermarks after hardware state readout (v4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although we can do a good job of reading out hardware state, the graphics firmware may have programmed the watermarks in a creative way that doesn't match how i915 would have chosen to program them. We shouldn't trust the firmware's watermark programming, but should rather re-calculate how we think WM's should be programmed and then shove those values into the hardware. We can do this pretty easily by creating a dummy top-level state, running it through the check process to calculate all the values, and then just programming the watermarks for each CRTC. v2: Move watermark sanitization after our BIOS fb reconstruction; the watermark calculations that we do here need to look at pstate->fb, which isn't setup yet in intel_modeset_setup_hw_state(), even though we have an enabled & visible plane. v3: - Don't move 'active = optimal' watermark assignment; we just undo that change in the next patch anyway. (Ville) - Move atomic helper locking fix to separate patch. (Maarten) v4: - Grab connection_mutex before calling atomic helper to duplicate state. The connector loop inside the helper will throw a WARN if we don't hold something to protect the connector list (and the helper itself doesn't try to lock the list). - Make failure to calculate watermarks for inherited state a WARN() since it probably indicates a serious problem in either our state readout code or our watermark code for this platform. Cc: Maarten Lankhorst Cc: Ville Syrjälä Signed-off-by: Matt Roper Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_display.c | 79 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_pm.c | 10 +++-- 3 files changed, 86 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c6dd4db29cea..bde9c764b415 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -623,6 +623,7 @@ struct drm_i915_display_funcs { struct dpll *best_clock); int (*compute_pipe_wm)(struct intel_crtc *crtc, struct drm_atomic_state *state); + void (*program_watermarks)(struct intel_crtc_state *cstate); void (*update_wm)(struct drm_crtc *crtc); int (*modeset_calc_cdclk)(struct drm_atomic_state *state); void (*modeset_commit_cdclk)(struct drm_atomic_state *state); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c1a3969f3d4c..043adfa65203 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15276,6 +15276,78 @@ void intel_modeset_init_hw(struct drm_device *dev) intel_enable_gt_powersave(dev); } +/* + * Calculate what we think the watermarks should be for the state we've read + * out of the hardware and then immediately program those watermarks so that + * we ensure the hardware settings match our internal state. + * + * We can calculate what we think WM's should be by creating a duplicate of the + * current state (which was constructed during hardware readout) and running it + * through the atomic check code to calculate new watermark values in the + * state object. + */ +static void sanitize_watermarks(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_atomic_state *state; + struct drm_crtc *crtc; + struct drm_crtc_state *cstate; + struct drm_modeset_acquire_ctx ctx; + int ret; + int i; + + /* Only supported on platforms that use atomic watermark design */ + if (!dev_priv->display.program_watermarks) + return; + + /* + * We need to hold connection_mutex before calling duplicate_state so + * that the connector loop is protected. + */ + drm_modeset_acquire_init(&ctx, 0); +retry: + ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx); + if (ret == -EDEADLK) { + drm_modeset_backoff(&ctx); + goto retry; + } else if (WARN_ON(ret)) { + return; + } + + state = drm_atomic_helper_duplicate_state(dev, &ctx); + if (WARN_ON(IS_ERR(state))) + return; + + ret = intel_atomic_check(dev, state); + if (ret) { + /* + * If we fail here, it means that the hardware appears to be + * programmed in a way that shouldn't be possible, given our + * understanding of watermark requirements. This might mean a + * mistake in the hardware readout code or a mistake in the + * watermark calculations for a given platform. Raise a WARN + * so that this is noticeable. + * + * If this actually happens, we'll have to just leave the + * BIOS-programmed watermarks untouched and hope for the best. + */ + WARN(true, "Could not determine valid watermarks for inherited state\n"); + return; + } + + /* Write calculated watermark values back */ + to_i915(dev)->wm.config = to_intel_atomic_state(state)->wm_config; + for_each_crtc_in_state(state, crtc, cstate, i) { + struct intel_crtc_state *cs = to_intel_crtc_state(cstate); + + dev_priv->display.program_watermarks(cs); + } + + drm_atomic_state_free(state); + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); +} + void intel_modeset_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -15396,6 +15468,13 @@ void intel_modeset_init(struct drm_device *dev) */ intel_find_initial_plane_obj(crtc, &plane_config); } + + /* + * Make sure hardware watermarks really match the state we read out. + * Note that we need to do this after reconstructing the BIOS fb's + * since the watermark calculation done here will use pstate->fb. + */ + sanitize_watermarks(dev); } static void intel_enable_pipe_a(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f9cbd2e81f54..db3ca41ce16b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3617,9 +3617,11 @@ static void skl_update_wm(struct drm_crtc *crtc) dev_priv->wm.skl_hw = *results; } -static void ilk_program_watermarks(struct drm_i915_private *dev_priv) +static void ilk_program_watermarks(struct intel_crtc_state *cstate) { - struct drm_device *dev = dev_priv->dev; + struct drm_crtc *crtc = cstate->base.crtc; + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = to_i915(dev); struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm; struct ilk_wm_maximums max; struct intel_wm_config *config = &dev_priv->wm.config; @@ -3650,7 +3652,6 @@ static void ilk_program_watermarks(struct drm_i915_private *dev_priv) static void ilk_update_wm(struct drm_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); @@ -3670,7 +3671,7 @@ static void ilk_update_wm(struct drm_crtc *crtc) intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk; - ilk_program_watermarks(dev_priv); + ilk_program_watermarks(cstate); } static void skl_pipe_wm_active_state(uint32_t val, @@ -7000,6 +7001,7 @@ void intel_init_pm(struct drm_device *dev) dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) { dev_priv->display.update_wm = ilk_update_wm; dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm; + dev_priv->display.program_watermarks = ilk_program_watermarks; } else { DRM_DEBUG_KMS("Failed to read display plane latency. " "Disable CxSR\n"); -- cgit v1.2.3 From 31d10b5701964ed8806193807279ee7b4235e491 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 6 Jan 2016 13:54:43 +0100 Subject: drm/i915: Allow fuzzy matching in intel_compare_link_m_n This prevents a unnecessary modeset on a dell XPS 13 (2016). N is always a power of 2, which means that for fuzzy matching we should compare for inequality on the n values, then do fuzzy matching on the m values. Signed-off-by: Maarten Lankhorst Tested-by: Kenneth Graunke Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/568D0E93.304@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 043adfa65203..ab0b406ee8ca 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12577,19 +12577,22 @@ intel_compare_m_n(unsigned int m, unsigned int n, BUILD_BUG_ON(DATA_LINK_M_N_MASK > INT_MAX); - if (m > m2) { - while (m > m2) { + if (n > n2) { + while (n > n2) { m2 <<= 1; n2 <<= 1; } - } else if (m < m2) { - while (m < m2) { + } else if (n < n2) { + while (n < n2) { m <<= 1; n <<= 1; } } - return m == m2 && n == n2; + if (n != n2) + return false; + + return intel_fuzzy_clock_check(m, m2); } static bool -- cgit v1.2.3 From 2dfb0b816d224379efc534764388745c474abeb4 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 7 Jan 2016 10:29:10 +0200 Subject: drm/i915: shut up gen8+ SDE irq dmesg noise, again We still keep getting [ 4.249930] [drm:gen8_irq_handler [i915]] *ERROR* The master control interrupt lied (SDE)! This reverts commit 820da7ae46332fa709b171eb7ba57cbd023fa6df Author: Jani Nikula Date: Wed Nov 25 16:47:23 2015 +0200 Revert "drm/i915: shut up gen8+ SDE irq dmesg noise" which in itself is a revert, so this is just doing commit 97e5ed1111dcc5300a0f59a55248cd243937a8ab Author: Daniel Vetter Date: Fri Oct 23 10:56:12 2015 +0200 drm/i915: shut up gen8+ SDE irq dmesg noise all over again. I'll stop pretending I understand what's going on like I did when I thought I'd fixed this for good in commit 6a39d7c986be4fd18eb019e9cdbf774ec36c9f77 Author: Jani Nikula Date: Wed Nov 25 16:47:22 2015 +0200 drm/i915: fix the SDE irq dmesg warnings properly Reported-by: Chris Wilson Reference: http://mid.gmane.org/20151213124945.GA5715@nuc-i3427.alporthouse.com Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92084 Cc: drm-intel-fixes@lists.freedesktop.org Fixes: 820da7ae4633 ("Revert "drm/i915: shut up gen8+ SDE irq dmesg noise"") Acked-by: Chris Wilson Acked-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1452155350-14658-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_irq.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 3f8c753997ba..fa8afa7860ae 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2414,9 +2414,13 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) spt_irq_handler(dev, pch_iir); else cpt_irq_handler(dev, pch_iir); - } else - DRM_ERROR("The master control interrupt lied (SDE)!\n"); - + } else { + /* + * Like on previous PCH there seems to be something + * fishy going on with forwarding PCH interrupts. + */ + DRM_DEBUG_DRIVER("The master control interrupt lied (SDE)!\n"); + } } I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); -- cgit v1.2.3 From 396e33ae204f52abebec9e578f44c749305500f4 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Wed, 6 Jan 2016 11:34:30 -0800 Subject: drm/i915: Add two-stage ILK-style watermark programming (v10) In addition to calculating final watermarks, let's also pre-calculate a set of intermediate watermark values at atomic check time. These intermediate watermarks are a combination of the watermarks for the old state and the new state; they should satisfy the requirements of both states which means they can be programmed immediately when we commit the atomic state (without waiting for a vblank). Once the vblank does happen, we can then re-program watermarks to the more optimal final value. v2: Significant rebasing/rewriting. v3: - Move 'need_postvbl_update' flag to CRTC state (Daniel) - Don't forget to check intermediate watermark values for validity (Maarten) - Don't due async watermark optimization; just do it at the end of the atomic transaction, after waiting for vblanks. We do want it to be async eventually, but adding that now will cause more trouble for Maarten's in-progress work. (Maarten) - Don't allocate space in crtc_state for intermediate watermarks on platforms that don't need it (gen9+). - Move WaCxSRDisabledForSpriteScaling:ivb into intel_begin_crtc_commit now that ilk_update_wm is gone. v4: - Add a wm_mutex to cover updates to intel_crtc->active and the need_postvbl_update flag. Since we don't have async yet it isn't terribly important yet, but might as well add it now. - Change interface to program watermarks. Platforms will now expose .initial_watermarks() and .optimize_watermarks() functions to do watermark programming. These should lock wm_mutex, copy the appropriate state values into intel_crtc->active, and then call the internal program watermarks function. v5: - Skip intermediate watermark calculation/check during initial hardware readout since we don't trust the existing HW values (and don't have valid values of our own yet). - Don't try to call .optimize_watermarks() on platforms that don't have atomic watermarks yet. (Maarten) v6: - Rebase v7: - Further rebase v8: - A few minor indentation and line length fixes v9: - Yet another rebase since Maarten's patches reworked a bunch of the code (wm_pre, wm_post, etc.) that this was previously based on. v10: - Move wm_mutex to dev_priv to protect against racing commits against disjoint CRTC sets. (Maarten) - Drop unnecessary clearing of cstate->wm.need_postvbl_update (Maarten) Cc: Maarten Lankhorst Signed-off-by: Matt Roper Link: http://patchwork.freedesktop.org/patch/msgid/1452108870-24204-1-git-send-email-matthew.d.roper@intel.com Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_dma.c | 1 + drivers/gpu/drm/i915/i915_drv.h | 13 ++- drivers/gpu/drm/i915/intel_atomic.c | 1 + drivers/gpu/drm/i915/intel_display.c | 92 +++++++++++++++++++- drivers/gpu/drm/i915/intel_drv.h | 28 +++++- drivers/gpu/drm/i915/intel_pm.c | 162 ++++++++++++++++++++++++----------- 6 files changed, 241 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 988a3806512a..44a896ce32e6 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -893,6 +893,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) mutex_init(&dev_priv->sb_lock); mutex_init(&dev_priv->modeset_restore_lock); mutex_init(&dev_priv->av_mutex); + mutex_init(&dev_priv->wm.wm_mutex); intel_pm_setup(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bde9c764b415..61b9d910b912 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -623,7 +623,11 @@ struct drm_i915_display_funcs { struct dpll *best_clock); int (*compute_pipe_wm)(struct intel_crtc *crtc, struct drm_atomic_state *state); - void (*program_watermarks)(struct intel_crtc_state *cstate); + int (*compute_intermediate_wm)(struct drm_device *dev, + struct intel_crtc *intel_crtc, + struct intel_crtc_state *newstate); + void (*initial_watermarks)(struct intel_crtc_state *cstate); + void (*optimize_watermarks)(struct intel_crtc_state *cstate); void (*update_wm)(struct drm_crtc *crtc); int (*modeset_calc_cdclk)(struct drm_atomic_state *state); void (*modeset_commit_cdclk)(struct drm_atomic_state *state); @@ -1927,6 +1931,13 @@ struct drm_i915_private { }; uint8_t max_level; + + /* + * Should be held around atomic WM register writing; also + * protects * intel_crtc->wm.active and + * cstate->wm.need_postvbl_update. + */ + struct mutex wm_mutex; } wm; struct i915_runtime_pm pm; diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 4625f8a9ba12..9682d94af710 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -97,6 +97,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) crtc_state->disable_lp_wm = false; crtc_state->disable_cxsr = false; crtc_state->wm_changed = false; + crtc_state->wm.need_postvbl_update = false; return &crtc_state->base; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ab0b406ee8ca..24b3503f94be 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4858,7 +4858,42 @@ static void intel_pre_plane_update(struct intel_crtc *crtc) intel_set_memory_cxsr(dev_priv, false); } - if (!needs_modeset(&pipe_config->base) && pipe_config->wm_changed) + /* + * IVB workaround: must disable low power watermarks for at least + * one frame before enabling scaling. LP watermarks can be re-enabled + * when scaling is disabled. + * + * WaCxSRDisabledForSpriteScaling:ivb + */ + if (pipe_config->disable_lp_wm) { + ilk_disable_lp_wm(dev); + intel_wait_for_vblank(dev, crtc->pipe); + } + + /* + * If we're doing a modeset, we're done. No need to do any pre-vblank + * watermark programming here. + */ + if (needs_modeset(&pipe_config->base)) + return; + + /* + * For platforms that support atomic watermarks, program the + * 'intermediate' watermarks immediately. On pre-gen9 platforms, these + * will be the intermediate values that are safe for both pre- and + * post- vblank; when vblank happens, the 'active' values will be set + * to the final 'target' values and we'll do this again to get the + * optimal watermarks. For gen9+ platforms, the values we program here + * will be the final target values which will get automatically latched + * at vblank time; no further programming will be necessary. + * + * If a platform hasn't been transitioned to atomic watermarks yet, + * we'll continue to update watermarks the old way, if flags tell + * us to. + */ + if (dev_priv->display.initial_watermarks != NULL) + dev_priv->display.initial_watermarks(pipe_config); + else if (pipe_config->wm_changed) intel_update_watermarks(&crtc->base); } @@ -11918,6 +11953,11 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, pipe_config->wm_changed = true; } + /* Pre-gen9 platforms need two-step watermark updates */ + if (pipe_config->wm_changed && INTEL_INFO(dev)->gen < 9 && + dev_priv->display.optimize_watermarks) + to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true; + if (visible || was_visible) intel_crtc->atomic.fb_bits |= to_intel_plane(plane)->frontbuffer_bit; @@ -12074,8 +12114,29 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, ret = 0; if (dev_priv->display.compute_pipe_wm) { ret = dev_priv->display.compute_pipe_wm(intel_crtc, state); - if (ret) + if (ret) { + DRM_DEBUG_KMS("Target pipe watermarks are invalid\n"); + return ret; + } + } + + if (dev_priv->display.compute_intermediate_wm && + !to_intel_atomic_state(state)->skip_intermediate_wm) { + if (WARN_ON(!dev_priv->display.compute_pipe_wm)) + return 0; + + /* + * Calculate 'intermediate' watermarks that satisfy both the + * old state and the new state. We can program these + * immediately. + */ + ret = dev_priv->display.compute_intermediate_wm(crtc->dev, + intel_crtc, + pipe_config); + if (ret) { + DRM_DEBUG_KMS("No valid intermediate pipe watermarks are possible\n"); return ret; + } } if (INTEL_INFO(dev)->gen >= 9) { @@ -13530,6 +13591,7 @@ static int intel_atomic_commit(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc_state *crtc_state; struct drm_crtc *crtc; + struct intel_crtc_state *intel_cstate; int ret = 0, i; bool hw_check = intel_state->modeset; @@ -13629,6 +13691,20 @@ static int intel_atomic_commit(struct drm_device *dev, drm_atomic_helper_wait_for_vblanks(dev, state); + /* + * Now that the vblank has passed, we can go ahead and program the + * optimal watermarks on platforms that need two-step watermark + * programming. + * + * TODO: Move this (and other cleanup) to an async worker eventually. + */ + for_each_crtc_in_state(state, crtc, crtc_state, i) { + intel_cstate = to_intel_crtc_state(crtc->state); + + if (dev_priv->display.optimize_watermarks) + dev_priv->display.optimize_watermarks(intel_cstate); + } + mutex_lock(&dev->struct_mutex); drm_atomic_helper_cleanup_planes(dev, state); mutex_unlock(&dev->struct_mutex); @@ -15300,7 +15376,7 @@ static void sanitize_watermarks(struct drm_device *dev) int i; /* Only supported on platforms that use atomic watermark design */ - if (!dev_priv->display.program_watermarks) + if (!dev_priv->display.optimize_watermarks) return; /* @@ -15321,6 +15397,13 @@ retry: if (WARN_ON(IS_ERR(state))) return; + /* + * Hardware readout is the only time we don't want to calculate + * intermediate watermarks (since we don't trust the current + * watermarks). + */ + to_intel_atomic_state(state)->skip_intermediate_wm = true; + ret = intel_atomic_check(dev, state); if (ret) { /* @@ -15343,7 +15426,8 @@ retry: for_each_crtc_in_state(state, crtc, cstate, i) { struct intel_crtc_state *cs = to_intel_crtc_state(cstate); - dev_priv->display.program_watermarks(cs); + cs->wm.need_postvbl_update = true; + dev_priv->display.optimize_watermarks(cs); } drm_atomic_state_free(state); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a3b2025da563..b7a33f6cbbbc 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -260,6 +260,12 @@ struct intel_atomic_state { struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS]; struct intel_wm_config wm_config; + + /* + * Current watermarks can't be trusted during hardware readout, so + * don't bother calculating intermediate watermarks. + */ + bool skip_intermediate_wm; }; struct intel_plane_state { @@ -507,13 +513,29 @@ struct intel_crtc_state { struct { /* - * optimal watermarks, programmed post-vblank when this state - * is committed + * Optimal watermarks, programmed post-vblank when this state + * is committed. */ union { struct intel_pipe_wm ilk; struct skl_pipe_wm skl; } optimal; + + /* + * Intermediate watermarks; these can be programmed immediately + * since they satisfy both the current configuration we're + * switching away from and the new configuration we're switching + * to. + */ + struct intel_pipe_wm intermediate; + + /* + * Platforms with two-step watermark programming will need to + * update watermark programming post-vblank to switch from the + * safe intermediate watermarks to the optimal final + * watermarks. + */ + bool need_postvbl_update; } wm; }; @@ -600,6 +622,7 @@ struct intel_crtc { struct intel_pipe_wm ilk; struct skl_pipe_wm skl; } active; + /* allow CxSR on this pipe */ bool cxsr_allowed; } wm; @@ -1566,6 +1589,7 @@ void skl_wm_get_hw_state(struct drm_device *dev); void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, struct skl_ddb_allocation *ddb /* out */); uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config); +bool ilk_disable_lp_wm(struct drm_device *dev); /* intel_sdvo.c */ bool intel_sdvo_init(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index db3ca41ce16b..9df9e9a22f3c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2273,6 +2273,29 @@ static void skl_setup_wm_latency(struct drm_device *dev) intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency); } +static bool ilk_validate_pipe_wm(struct drm_device *dev, + struct intel_pipe_wm *pipe_wm) +{ + /* LP0 watermark maximums depend on this pipe alone */ + const struct intel_wm_config config = { + .num_pipes_active = 1, + .sprites_enabled = pipe_wm->sprites_enabled, + .sprites_scaled = pipe_wm->sprites_scaled, + }; + struct ilk_wm_maximums max; + + /* LP0 watermarks always use 1/2 DDB partitioning */ + ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max); + + /* At least LP0 must be valid */ + if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0])) { + DRM_DEBUG_KMS("LP0 watermark invalid\n"); + return false; + } + + return true; +} + /* Compute new watermarks for the pipe */ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, struct drm_atomic_state *state) @@ -2287,10 +2310,6 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, struct intel_plane_state *sprstate = NULL; struct intel_plane_state *curstate = NULL; int level, max_level = ilk_wm_max_level(dev); - /* LP0 watermark maximums depend on this pipe alone */ - struct intel_wm_config config = { - .num_pipes_active = 1, - }; struct ilk_wm_maximums max; cstate = intel_atomic_get_crtc_state(state, intel_crtc); @@ -2313,21 +2332,18 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, curstate = to_intel_plane_state(ps); } - config.sprites_enabled = sprstate->visible; - config.sprites_scaled = sprstate->visible && + pipe_wm->pipe_enabled = cstate->base.active; + pipe_wm->sprites_enabled = sprstate->visible; + pipe_wm->sprites_scaled = sprstate->visible && (drm_rect_width(&sprstate->dst) != drm_rect_width(&sprstate->src) >> 16 || drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16); - pipe_wm->pipe_enabled = cstate->base.active; - pipe_wm->sprites_enabled = config.sprites_enabled; - pipe_wm->sprites_scaled = config.sprites_scaled; - /* ILK/SNB: LP2+ watermarks only w/o sprites */ if (INTEL_INFO(dev)->gen <= 6 && sprstate->visible) max_level = 1; /* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */ - if (config.sprites_scaled) + if (pipe_wm->sprites_scaled) max_level = 0; ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate, @@ -2336,12 +2352,8 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, if (IS_HASWELL(dev) || IS_BROADWELL(dev)) pipe_wm->linetime = hsw_compute_linetime_wm(dev, cstate); - /* LP0 watermarks always use 1/2 DDB partitioning */ - ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max); - - /* At least LP0 must be valid */ - if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0])) - return -EINVAL; + if (!ilk_validate_pipe_wm(dev, pipe_wm)) + return false; ilk_compute_wm_reg_maximums(dev, 1, &max); @@ -2365,6 +2377,59 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, return 0; } +/* + * Build a set of 'intermediate' watermark values that satisfy both the old + * state and the new state. These can be programmed to the hardware + * immediately. + */ +static int ilk_compute_intermediate_wm(struct drm_device *dev, + struct intel_crtc *intel_crtc, + struct intel_crtc_state *newstate) +{ + struct intel_pipe_wm *a = &newstate->wm.intermediate; + struct intel_pipe_wm *b = &intel_crtc->wm.active.ilk; + int level, max_level = ilk_wm_max_level(dev); + + /* + * Start with the final, target watermarks, then combine with the + * currently active watermarks to get values that are safe both before + * and after the vblank. + */ + *a = newstate->wm.optimal.ilk; + a->pipe_enabled |= b->pipe_enabled; + a->sprites_enabled |= b->sprites_enabled; + a->sprites_scaled |= b->sprites_scaled; + + for (level = 0; level <= max_level; level++) { + struct intel_wm_level *a_wm = &a->wm[level]; + const struct intel_wm_level *b_wm = &b->wm[level]; + + a_wm->enable &= b_wm->enable; + a_wm->pri_val = max(a_wm->pri_val, b_wm->pri_val); + a_wm->spr_val = max(a_wm->spr_val, b_wm->spr_val); + a_wm->cur_val = max(a_wm->cur_val, b_wm->cur_val); + a_wm->fbc_val = max(a_wm->fbc_val, b_wm->fbc_val); + } + + /* + * We need to make sure that these merged watermark values are + * actually a valid configuration themselves. If they're not, + * there's no safe way to transition from the old state to + * the new state, so we need to fail the atomic transaction. + */ + if (!ilk_validate_pipe_wm(dev, a)) + return -EINVAL; + + /* + * If our intermediate WM are identical to the final WM, then we can + * omit the post-vblank programming; only update if it's different. + */ + if (memcmp(a, &newstate->wm.optimal.ilk, sizeof(*a)) != 0) + newstate->wm.need_postvbl_update = false; + + return 0; +} + /* * Merge the watermarks from all active pipes for a specific level. */ @@ -2377,9 +2442,7 @@ static void ilk_merge_wm_level(struct drm_device *dev, ret_wm->enable = true; for_each_intel_crtc(dev, intel_crtc) { - const struct intel_crtc_state *cstate = - to_intel_crtc_state(intel_crtc->base.state); - const struct intel_pipe_wm *active = &cstate->wm.optimal.ilk; + const struct intel_pipe_wm *active = &intel_crtc->wm.active.ilk; const struct intel_wm_level *wm = &active->wm[level]; if (!active->pipe_enabled) @@ -2527,15 +2590,14 @@ static void ilk_compute_wm_results(struct drm_device *dev, /* LP0 register values */ for_each_intel_crtc(dev, intel_crtc) { - const struct intel_crtc_state *cstate = - to_intel_crtc_state(intel_crtc->base.state); enum pipe pipe = intel_crtc->pipe; - const struct intel_wm_level *r = &cstate->wm.optimal.ilk.wm[0]; + const struct intel_wm_level *r = + &intel_crtc->wm.active.ilk.wm[0]; if (WARN_ON(!r->enable)) continue; - results->wm_linetime[pipe] = cstate->wm.optimal.ilk.linetime; + results->wm_linetime[pipe] = intel_crtc->wm.active.ilk.linetime; results->wm_pipe[pipe] = (r->pri_val << WM0_PIPE_PLANE_SHIFT) | @@ -2742,7 +2804,7 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv, dev_priv->wm.hw = *results; } -static bool ilk_disable_lp_wm(struct drm_device *dev) +bool ilk_disable_lp_wm(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -3617,11 +3679,9 @@ static void skl_update_wm(struct drm_crtc *crtc) dev_priv->wm.skl_hw = *results; } -static void ilk_program_watermarks(struct intel_crtc_state *cstate) +static void ilk_program_watermarks(struct drm_i915_private *dev_priv) { - struct drm_crtc *crtc = cstate->base.crtc; - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_device *dev = dev_priv->dev; struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm; struct ilk_wm_maximums max; struct intel_wm_config *config = &dev_priv->wm.config; @@ -3650,28 +3710,28 @@ static void ilk_program_watermarks(struct intel_crtc_state *cstate) ilk_write_wm_values(dev_priv, &results); } -static void ilk_update_wm(struct drm_crtc *crtc) +static void ilk_initial_watermarks(struct intel_crtc_state *cstate) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); - - WARN_ON(cstate->base.active != intel_crtc->active); + struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev); + struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); - /* - * IVB workaround: must disable low power watermarks for at least - * one frame before enabling scaling. LP watermarks can be re-enabled - * when scaling is disabled. - * - * WaCxSRDisabledForSpriteScaling:ivb - */ - if (cstate->disable_lp_wm) { - ilk_disable_lp_wm(crtc->dev); - intel_wait_for_vblank(crtc->dev, intel_crtc->pipe); - } + mutex_lock(&dev_priv->wm.wm_mutex); + intel_crtc->wm.active.ilk = cstate->wm.intermediate; + ilk_program_watermarks(dev_priv); + mutex_unlock(&dev_priv->wm.wm_mutex); +} - intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk; +static void ilk_optimize_watermarks(struct intel_crtc_state *cstate) +{ + struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev); + struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); - ilk_program_watermarks(cstate); + mutex_lock(&dev_priv->wm.wm_mutex); + if (cstate->wm.need_postvbl_update) { + intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk; + ilk_program_watermarks(dev_priv); + } + mutex_unlock(&dev_priv->wm.wm_mutex); } static void skl_pipe_wm_active_state(uint32_t val, @@ -6999,9 +7059,13 @@ void intel_init_pm(struct drm_device *dev) dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) || (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] && dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) { - dev_priv->display.update_wm = ilk_update_wm; dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm; - dev_priv->display.program_watermarks = ilk_program_watermarks; + dev_priv->display.compute_intermediate_wm = + ilk_compute_intermediate_wm; + dev_priv->display.initial_watermarks = + ilk_initial_watermarks; + dev_priv->display.optimize_watermarks = + ilk_optimize_watermarks; } else { DRM_DEBUG_KMS("Failed to read display plane latency. " "Disable CxSR\n"); -- cgit v1.2.3 From 2fde13910c8c3cf04011bf867d45de447be6d525 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 7 Jan 2016 11:54:06 +0100 Subject: drm/i915: Use passed plane state for sprite planes, v4. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't use plane->state directly, use the pointer from commit_plane. Changes since v1: - Fix uses of plane->state->rotation and color key to use the passed state too. - Only pass crtc_state and plane_state to update_plane. Changes since v2: - Rebased. Changes since v3: - Small whitespace changes and only assign 1 variable per line. - Constify plane_state and crtc_state. (vsyrjala) Signed-off-by: Maarten Lankhorst Cc: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1452164052-21752-2-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_drv.h | 10 +-- drivers/gpu/drm/i915/intel_sprite.c | 124 ++++++++++++++++++++---------------- 2 files changed, 71 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index b7a33f6cbbbc..6f3850beccd9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -681,16 +681,12 @@ struct intel_plane { /* * NOTE: Do not place new plane state fields here (e.g., when adding * new plane properties). New runtime state should now be placed in - * the intel_plane_state structure and accessed via drm_plane->state. + * the intel_plane_state structure and accessed via plane_state. */ void (*update_plane)(struct drm_plane *plane, - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t x, uint32_t y, - uint32_t src_w, uint32_t src_h); + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state); void (*disable_plane)(struct drm_plane *plane, struct drm_crtc *crtc); int (*check_plane)(struct drm_plane *plane, diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index f8bf6222fe48..4f9ebc117a34 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -178,28 +178,33 @@ void intel_pipe_update_end(struct intel_crtc *crtc) } static void -skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t x, uint32_t y, - uint32_t src_w, uint32_t src_h) +skl_update_plane(struct drm_plane *drm_plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_device *dev = drm_plane->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_plane *intel_plane = to_intel_plane(drm_plane); + struct drm_framebuffer *fb = plane_state->base.fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); const int pipe = intel_plane->pipe; const int plane = intel_plane->plane + 1; u32 plane_ctl, stride_div, stride; - const struct drm_intel_sprite_colorkey *key = - &to_intel_plane_state(drm_plane->state)->ckey; + const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; u32 surf_addr; u32 tile_height, plane_offset, plane_size; unsigned int rotation; int x_offset, y_offset; - struct intel_crtc_state *crtc_state = to_intel_crtc(crtc)->config; - int scaler_id; + int crtc_x = plane_state->dst.x1; + int crtc_y = plane_state->dst.y1; + uint32_t crtc_w = drm_rect_width(&plane_state->dst); + uint32_t crtc_h = drm_rect_height(&plane_state->dst); + uint32_t x = plane_state->src.x1 >> 16; + uint32_t y = plane_state->src.y1 >> 16; + uint32_t src_w = drm_rect_width(&plane_state->src) >> 16; + uint32_t src_h = drm_rect_height(&plane_state->src) >> 16; + const struct intel_scaler *scaler = + &crtc_state->scaler_state.scalers[plane_state->scaler_id]; plane_ctl = PLANE_CTL_ENABLE | PLANE_CTL_PIPE_GAMMA_ENABLE | @@ -208,14 +213,12 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, plane_ctl |= skl_plane_ctl_format(fb->pixel_format); plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]); - rotation = drm_plane->state->rotation; + rotation = plane_state->base.rotation; plane_ctl |= skl_plane_ctl_rotation(rotation); stride_div = intel_fb_stride_alignment(dev, fb->modifier[0], fb->pixel_format); - scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id; - /* Sizes are 0 based */ src_w--; src_h--; @@ -256,13 +259,13 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, I915_WRITE(PLANE_SIZE(pipe, plane), plane_size); /* program plane scaler */ - if (scaler_id >= 0) { + if (plane_state->scaler_id >= 0) { uint32_t ps_ctrl = 0; + int scaler_id = plane_state->scaler_id; DRM_DEBUG_KMS("plane = %d PS_PLANE_SEL(plane) = 0x%x\n", plane, PS_PLANE_SEL(plane)); - ps_ctrl = PS_SCALER_EN | PS_PLANE_SEL(plane) | - crtc_state->scaler_state.scalers[scaler_id].mode; + ps_ctrl = PS_SCALER_EN | PS_PLANE_SEL(plane) | scaler->mode; I915_WRITE(SKL_PS_CTRL(pipe, scaler_id), ps_ctrl); I915_WRITE(SKL_PS_PWR_GATE(pipe, scaler_id), 0); I915_WRITE(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y); @@ -334,24 +337,29 @@ chv_update_csc(struct intel_plane *intel_plane, uint32_t format) } static void -vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t x, uint32_t y, - uint32_t src_w, uint32_t src_h) +vlv_update_plane(struct drm_plane *dplane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_device *dev = dplane->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_plane *intel_plane = to_intel_plane(dplane); + struct drm_framebuffer *fb = plane_state->base.fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); int pipe = intel_plane->pipe; int plane = intel_plane->plane; u32 sprctl; unsigned long sprsurf_offset, linear_offset; int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); - const struct drm_intel_sprite_colorkey *key = - &to_intel_plane_state(dplane->state)->ckey; + const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; + int crtc_x = plane_state->dst.x1; + int crtc_y = plane_state->dst.y1; + uint32_t crtc_w = drm_rect_width(&plane_state->dst); + uint32_t crtc_h = drm_rect_height(&plane_state->dst); + uint32_t x = plane_state->src.x1 >> 16; + uint32_t y = plane_state->src.y1 >> 16; + uint32_t src_w = drm_rect_width(&plane_state->src) >> 16; + uint32_t src_h = drm_rect_height(&plane_state->src) >> 16; sprctl = SP_ENABLE; @@ -421,7 +429,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, fb->pitches[0]); linear_offset -= sprsurf_offset; - if (dplane->state->rotation == BIT(DRM_ROTATE_180)) { + if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { sprctl |= SP_ROTATE_180; x += src_w; @@ -474,23 +482,28 @@ vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) } static void -ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t x, uint32_t y, - uint32_t src_w, uint32_t src_h) +ivb_update_plane(struct drm_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_device *dev = plane->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_plane *intel_plane = to_intel_plane(plane); + struct drm_framebuffer *fb = plane_state->base.fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); enum pipe pipe = intel_plane->pipe; u32 sprctl, sprscale = 0; unsigned long sprsurf_offset, linear_offset; int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); - const struct drm_intel_sprite_colorkey *key = - &to_intel_plane_state(plane->state)->ckey; + const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; + int crtc_x = plane_state->dst.x1; + int crtc_y = plane_state->dst.y1; + uint32_t crtc_w = drm_rect_width(&plane_state->dst); + uint32_t crtc_h = drm_rect_height(&plane_state->dst); + uint32_t x = plane_state->src.x1 >> 16; + uint32_t y = plane_state->src.y1 >> 16; + uint32_t src_w = drm_rect_width(&plane_state->src) >> 16; + uint32_t src_h = drm_rect_height(&plane_state->src) >> 16; sprctl = SPRITE_ENABLE; @@ -550,7 +563,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, pixel_size, fb->pitches[0]); linear_offset -= sprsurf_offset; - if (plane->state->rotation == BIT(DRM_ROTATE_180)) { + if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { sprctl |= SPRITE_ROTATE_180; /* HSW and BDW does this automagically in hardware */ @@ -612,23 +625,28 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) } static void -ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t x, uint32_t y, - uint32_t src_w, uint32_t src_h) +ilk_update_plane(struct drm_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_device *dev = plane->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_plane *intel_plane = to_intel_plane(plane); + struct drm_framebuffer *fb = plane_state->base.fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); int pipe = intel_plane->pipe; unsigned long dvssurf_offset, linear_offset; u32 dvscntr, dvsscale; int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); - const struct drm_intel_sprite_colorkey *key = - &to_intel_plane_state(plane->state)->ckey; + const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; + int crtc_x = plane_state->dst.x1; + int crtc_y = plane_state->dst.y1; + uint32_t crtc_w = drm_rect_width(&plane_state->dst); + uint32_t crtc_h = drm_rect_height(&plane_state->dst); + uint32_t x = plane_state->src.x1 >> 16; + uint32_t y = plane_state->src.y1 >> 16; + uint32_t src_w = drm_rect_width(&plane_state->src) >> 16; + uint32_t src_h = drm_rect_height(&plane_state->src) >> 16; dvscntr = DVS_ENABLE; @@ -684,7 +702,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, pixel_size, fb->pitches[0]); linear_offset -= dvssurf_offset; - if (plane->state->rotation == BIT(DRM_ROTATE_180)) { + if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { dvscntr |= DVS_ROTATE_180; x += src_w; @@ -917,23 +935,17 @@ static void intel_commit_sprite_plane(struct drm_plane *plane, struct intel_plane_state *state) { - struct drm_crtc *crtc = state->base.crtc; struct intel_plane *intel_plane = to_intel_plane(plane); - struct drm_framebuffer *fb = state->base.fb; - - crtc = crtc ? crtc : plane->crtc; if (state->visible) { - intel_plane->update_plane(plane, crtc, fb, - state->dst.x1, state->dst.y1, - drm_rect_width(&state->dst), - drm_rect_height(&state->dst), - state->src.x1 >> 16, - state->src.y1 >> 16, - drm_rect_width(&state->src) >> 16, - drm_rect_height(&state->src) >> 16); + struct intel_crtc_state *crtc_state = + to_intel_crtc(state->base.crtc)->config; + + intel_plane->update_plane(plane, crtc_state, state); } else { - intel_plane->disable_plane(plane, crtc); + struct drm_crtc *crtc = state->base.crtc; + + intel_plane->disable_plane(plane, crtc ?: plane->crtc); } } -- cgit v1.2.3 From a758e68458258f0d8664bdf8fa833bddfdabbed6 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 7 Jan 2016 11:54:07 +0100 Subject: drm/i915: Do not use commit_plane for sprite planes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use update_plane and disable_plane directly. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1452164052-21752-3-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_atomic_plane.c | 12 +++++++++++- drivers/gpu/drm/i915/intel_sprite.c | 19 ------------------- 2 files changed, 11 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index 856c3118bb87..969aa410deaa 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -194,8 +194,18 @@ static void intel_plane_atomic_update(struct drm_plane *plane, struct intel_plane *intel_plane = to_intel_plane(plane); struct intel_plane_state *intel_state = to_intel_plane_state(plane->state); + struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc; + struct drm_crtc_state *crtc_state = + drm_atomic_get_existing_crtc_state(old_state->state, crtc); - intel_plane->commit_plane(plane, intel_state); + if (intel_plane->commit_plane) + intel_plane->commit_plane(plane, intel_state); + else if (intel_state->visible) + intel_plane->update_plane(plane, + to_intel_crtc_state(crtc_state), + intel_state); + else + intel_plane->disable_plane(plane, crtc); } const struct drm_plane_helper_funcs intel_plane_helper_funcs = { diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 4f9ebc117a34..73dfb38886b9 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -931,24 +931,6 @@ intel_check_sprite_plane(struct drm_plane *plane, return 0; } -static void -intel_commit_sprite_plane(struct drm_plane *plane, - struct intel_plane_state *state) -{ - struct intel_plane *intel_plane = to_intel_plane(plane); - - if (state->visible) { - struct intel_crtc_state *crtc_state = - to_intel_crtc(state->base.crtc)->config; - - intel_plane->update_plane(plane, crtc_state, state); - } else { - struct drm_crtc *crtc = state->base.crtc; - - intel_plane->disable_plane(plane, crtc ?: plane->crtc); - } -} - int intel_sprite_set_colorkey(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -1130,7 +1112,6 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) intel_plane->plane = plane; intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane); intel_plane->check_plane = intel_check_sprite_plane; - intel_plane->commit_plane = intel_commit_sprite_plane; possible_crtcs = (1 << pipe); ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs, &intel_plane_funcs, -- cgit v1.2.3 From edd62601dd6a08e5f25cb84033e7fd9371032a13 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 7 Jan 2016 11:54:08 +0100 Subject: drm/i915: Remove some visibility checks from intel_crtc_update_cursor. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is duplicated with intel_check_cursor_plane, and with all non-atomic paths removed this should be dead code. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1452164052-21752-4-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 24b3503f94be..4fe0c4d02fda 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -85,8 +85,6 @@ static const uint32_t intel_cursor_formats[] = { DRM_FORMAT_ARGB8888, }; -static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on); - static void i9xx_crtc_clock_get(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config); static void ironlake_pch_clock_get(struct intel_crtc *crtc, @@ -10237,25 +10235,13 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, base = intel_crtc->cursor_addr; - if (x >= intel_crtc->config->pipe_src_w) - on = false; - - if (y >= intel_crtc->config->pipe_src_h) - on = false; - if (x < 0) { - if (x + cursor_state->crtc_w <= 0) - on = false; - pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; x = -x; } pos |= x << CURSOR_X_SHIFT; if (y < 0) { - if (y + cursor_state->crtc_h <= 0) - on = false; - pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; y = -y; } -- cgit v1.2.3 From f28580214407d1adeb08ad8dd0af059bf6220a51 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 7 Jan 2016 11:54:09 +0100 Subject: drm/i915: Make disable_cursor_plane similar to commit_cursor_plane. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update cursor_addr when disable_plane is called. This is required to make commit_cursor_plane take a crtc_state and a plane_state. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1452164052-21752-5-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4fe0c4d02fda..0483c2429a9d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14256,6 +14256,9 @@ static void intel_disable_cursor_plane(struct drm_plane *plane, struct drm_crtc *crtc) { + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + intel_crtc->cursor_addr = 0; intel_crtc_update_cursor(crtc, false); } -- cgit v1.2.3 From 55a08b3f2bb0d69ba486c5d88602647fa6649de9 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 7 Jan 2016 11:54:10 +0100 Subject: drm/i915: Use the plane state for cursor updates. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cursor planes grab the state from plane->state instead of the state that was passed. The only updates are atomic now, so use the plane_state that's passed in. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1452164052-21752-6-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 92 ++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0483c2429a9d..07715f985da1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10112,16 +10112,17 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, return true; } -static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on) +static void i845_update_cursor(struct drm_crtc *crtc, u32 base, + const struct intel_plane_state *plane_state) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); uint32_t cntl = 0, size = 0; - if (on) { - unsigned int width = intel_crtc->base.cursor->state->crtc_w; - unsigned int height = intel_crtc->base.cursor->state->crtc_h; + if (plane_state && plane_state->visible) { + unsigned int width = plane_state->base.crtc_w; + unsigned int height = plane_state->base.crtc_h; unsigned int stride = roundup_pow_of_two(width) * 4; switch (stride) { @@ -10174,7 +10175,8 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on) } } -static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on) +static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, + const struct intel_plane_state *plane_state) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -10182,9 +10184,9 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on) int pipe = intel_crtc->pipe; uint32_t cntl = 0; - if (on) { + if (plane_state && plane_state->visible) { cntl = MCURSOR_GAMMA_ENABLE; - switch (intel_crtc->base.cursor->state->crtc_w) { + switch (plane_state->base.crtc_w) { case 64: cntl |= CURSOR_MODE_64_ARGB_AX; break; @@ -10195,17 +10197,17 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on) cntl |= CURSOR_MODE_256_ARGB_AX; break; default: - MISSING_CASE(intel_crtc->base.cursor->state->crtc_w); + MISSING_CASE(plane_state->base.crtc_w); return; } cntl |= pipe << 28; /* Connect to correct pipe */ if (HAS_DDI(dev)) cntl |= CURSOR_PIPE_CSC_ENABLE; - } - if (crtc->cursor->state->rotation == BIT(DRM_ROTATE_180)) - cntl |= CURSOR_ROTATE_180; + if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) + cntl |= CURSOR_ROTATE_180; + } if (intel_crtc->cursor_cntl != cntl) { I915_WRITE(CURCNTR(pipe), cntl); @@ -10222,44 +10224,45 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on) /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ static void intel_crtc_update_cursor(struct drm_crtc *crtc, - bool on) + const struct intel_plane_state *plane_state) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; - struct drm_plane_state *cursor_state = crtc->cursor->state; - int x = cursor_state->crtc_x; - int y = cursor_state->crtc_y; - u32 base = 0, pos = 0; + u32 base = intel_crtc->cursor_addr; + u32 pos = 0; - base = intel_crtc->cursor_addr; + if (plane_state) { + int x = plane_state->base.crtc_x; + int y = plane_state->base.crtc_y; - if (x < 0) { - pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; - x = -x; - } - pos |= x << CURSOR_X_SHIFT; + if (x < 0) { + pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; + x = -x; + } + pos |= x << CURSOR_X_SHIFT; - if (y < 0) { - pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; - y = -y; + if (y < 0) { + pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; + y = -y; + } + pos |= y << CURSOR_Y_SHIFT; + + /* ILK+ do this automagically */ + if (HAS_GMCH_DISPLAY(dev) && + plane_state->base.rotation == BIT(DRM_ROTATE_180)) { + base += (plane_state->base.crtc_h * + plane_state->base.crtc_w - 1) * 4; + } } - pos |= y << CURSOR_Y_SHIFT; I915_WRITE(CURPOS(pipe), pos); - /* ILK+ do this automagically */ - if (HAS_GMCH_DISPLAY(dev) && - crtc->cursor->state->rotation == BIT(DRM_ROTATE_180)) { - base += (cursor_state->crtc_h * - cursor_state->crtc_w - 1) * 4; - } - if (IS_845G(dev) || IS_I865G(dev)) - i845_update_cursor(crtc, base, on); + i845_update_cursor(crtc, base, plane_state); else - i9xx_update_cursor(crtc, base, on); + i9xx_update_cursor(crtc, base, plane_state); } static bool cursor_size_ok(struct drm_device *dev, @@ -14259,22 +14262,20 @@ intel_disable_cursor_plane(struct drm_plane *plane, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); intel_crtc->cursor_addr = 0; - intel_crtc_update_cursor(crtc, false); + intel_crtc_update_cursor(crtc, NULL); } static void -intel_commit_cursor_plane(struct drm_plane *plane, - struct intel_plane_state *state) +intel_update_cursor_plane(struct drm_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *state) { - struct drm_crtc *crtc = state->base.crtc; + struct drm_crtc *crtc = crtc_state->base.crtc; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_device *dev = plane->dev; - struct intel_crtc *intel_crtc; struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb); uint32_t addr; - crtc = crtc ? crtc : plane->crtc; - intel_crtc = to_intel_crtc(crtc); - if (!obj) addr = 0; else if (!INTEL_INFO(dev)->cursor_needs_physical) @@ -14283,8 +14284,7 @@ intel_commit_cursor_plane(struct drm_plane *plane, addr = obj->phys_handle->busaddr; intel_crtc->cursor_addr = addr; - - intel_crtc_update_cursor(crtc, state->visible); + intel_crtc_update_cursor(crtc, state); } static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, @@ -14310,7 +14310,7 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, cursor->plane = pipe; cursor->frontbuffer_bit = INTEL_FRONTBUFFER_CURSOR(pipe); cursor->check_plane = intel_check_cursor_plane; - cursor->commit_plane = intel_commit_cursor_plane; + cursor->update_plane = intel_update_cursor_plane; cursor->disable_plane = intel_disable_cursor_plane; drm_universal_plane_init(dev, &cursor->base, 0, -- cgit v1.2.3 From a8d201af68506b375b701d0d8dbe8487034256f2 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 7 Jan 2016 11:54:11 +0100 Subject: drm/i915: Use plane state for primary plane updates. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass in the atomic states to allow for proper updates. This removes uses of intel_crtc->config and direct access to plane->state. This breaks the last bit of kgdboc, but that appears to be dead code. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1452164052-21752-7-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/i915_drv.h | 3 - drivers/gpu/drm/i915/intel_display.c | 248 +++++++++++++++-------------------- 2 files changed, 103 insertions(+), 148 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 61b9d910b912..8cf655c6fc03 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -652,9 +652,6 @@ struct drm_i915_display_funcs { struct drm_i915_gem_object *obj, struct drm_i915_gem_request *req, uint32_t flags); - void (*update_primary_plane)(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int x, int y); void (*hpd_irq_setup)(struct drm_device *dev); /* clock updates for mode set */ /* cursor updates */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 07715f985da1..738d0dca47a8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2679,36 +2679,23 @@ valid_fb: obj->frontbuffer_bits |= to_intel_plane(primary)->frontbuffer_bit; } -static void i9xx_update_primary_plane(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int x, int y) +static void i9xx_update_primary_plane(struct drm_plane *primary, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { - struct drm_device *dev = crtc->dev; + struct drm_device *dev = primary->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct drm_plane *primary = crtc->primary; - bool visible = to_intel_plane_state(primary->state)->visible; - struct drm_i915_gem_object *obj; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_framebuffer *fb = plane_state->base.fb; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); int plane = intel_crtc->plane; unsigned long linear_offset; + int x = plane_state->src.x1 >> 16; + int y = plane_state->src.y1 >> 16; u32 dspcntr; i915_reg_t reg = DSPCNTR(plane); int pixel_size; - if (!visible || !fb) { - I915_WRITE(reg, 0); - if (INTEL_INFO(dev)->gen >= 4) - I915_WRITE(DSPSURF(plane), 0); - else - I915_WRITE(DSPADDR(plane), 0); - POSTING_READ(reg); - return; - } - - obj = intel_fb_obj(fb); - if (WARN_ON(obj == NULL)) - return; - pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); dspcntr = DISPPLANE_GAMMA_ENABLE; @@ -2723,13 +2710,13 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc, * which should always be the user's requested size. */ I915_WRITE(DSPSIZE(plane), - ((intel_crtc->config->pipe_src_h - 1) << 16) | - (intel_crtc->config->pipe_src_w - 1)); + ((crtc_state->pipe_src_h - 1) << 16) | + (crtc_state->pipe_src_w - 1)); I915_WRITE(DSPPOS(plane), 0); } else if (IS_CHERRYVIEW(dev) && plane == PLANE_B) { I915_WRITE(PRIMSIZE(plane), - ((intel_crtc->config->pipe_src_h - 1) << 16) | - (intel_crtc->config->pipe_src_w - 1)); + ((crtc_state->pipe_src_h - 1) << 16) | + (crtc_state->pipe_src_w - 1)); I915_WRITE(PRIMPOS(plane), 0); I915_WRITE(PRIMCNSTALPHA(plane), 0); } @@ -2780,17 +2767,17 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc, intel_crtc->dspaddr_offset = linear_offset; } - if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) { + if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { dspcntr |= DISPPLANE_ROTATE_180; - x += (intel_crtc->config->pipe_src_w - 1); - y += (intel_crtc->config->pipe_src_h - 1); + x += (crtc_state->pipe_src_w - 1); + y += (crtc_state->pipe_src_h - 1); /* Finding the last pixel of the last line of the display data and adding to linear_offset*/ linear_offset += - (intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] + - (intel_crtc->config->pipe_src_w - 1) * pixel_size; + (crtc_state->pipe_src_h - 1) * fb->pitches[0] + + (crtc_state->pipe_src_w - 1) * pixel_size; } intel_crtc->adjusted_x = x; @@ -2809,37 +2796,40 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc, POSTING_READ(reg); } -static void ironlake_update_primary_plane(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int x, int y) +static void i9xx_disable_primary_plane(struct drm_plane *primary, + struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct drm_plane *primary = crtc->primary; - bool visible = to_intel_plane_state(primary->state)->visible; - struct drm_i915_gem_object *obj; int plane = intel_crtc->plane; - unsigned long linear_offset; - u32 dspcntr; - i915_reg_t reg = DSPCNTR(plane); - int pixel_size; - if (!visible || !fb) { - I915_WRITE(reg, 0); + I915_WRITE(DSPCNTR(plane), 0); + if (INTEL_INFO(dev_priv)->gen >= 4) I915_WRITE(DSPSURF(plane), 0); - POSTING_READ(reg); - return; - } - - obj = intel_fb_obj(fb); - if (WARN_ON(obj == NULL)) - return; + else + I915_WRITE(DSPADDR(plane), 0); + POSTING_READ(DSPCNTR(plane)); +} - pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); +static void ironlake_update_primary_plane(struct drm_plane *primary, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) +{ + struct drm_device *dev = primary->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_framebuffer *fb = plane_state->base.fb; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); + int plane = intel_crtc->plane; + unsigned long linear_offset; + u32 dspcntr; + i915_reg_t reg = DSPCNTR(plane); + int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); + int x = plane_state->src.x1 >> 16; + int y = plane_state->src.y1 >> 16; dspcntr = DISPPLANE_GAMMA_ENABLE; - dspcntr |= DISPLAY_PLANE_ENABLE; if (IS_HASWELL(dev) || IS_BROADWELL(dev)) @@ -2881,18 +2871,18 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc, pixel_size, fb->pitches[0]); linear_offset -= intel_crtc->dspaddr_offset; - if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) { + if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { dspcntr |= DISPPLANE_ROTATE_180; if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) { - x += (intel_crtc->config->pipe_src_w - 1); - y += (intel_crtc->config->pipe_src_h - 1); + x += (crtc_state->pipe_src_w - 1); + y += (crtc_state->pipe_src_h - 1); /* Finding the last pixel of the last line of the display data and adding to linear_offset*/ linear_offset += - (intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] + - (intel_crtc->config->pipe_src_w - 1) * pixel_size; + (crtc_state->pipe_src_h - 1) * fb->pitches[0] + + (crtc_state->pipe_src_w - 1) * pixel_size; } } @@ -3083,36 +3073,30 @@ u32 skl_plane_ctl_rotation(unsigned int rotation) return 0; } -static void skylake_update_primary_plane(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int x, int y) +static void skylake_update_primary_plane(struct drm_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { - struct drm_device *dev = crtc->dev; + struct drm_device *dev = plane->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct drm_plane *plane = crtc->primary; - bool visible = to_intel_plane_state(plane->state)->visible; - struct drm_i915_gem_object *obj; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_framebuffer *fb = plane_state->base.fb; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); int pipe = intel_crtc->pipe; u32 plane_ctl, stride_div, stride; u32 tile_height, plane_offset, plane_size; - unsigned int rotation; + unsigned int rotation = plane_state->base.rotation; int x_offset, y_offset; u32 surf_addr; - struct intel_crtc_state *crtc_state = intel_crtc->config; - struct intel_plane_state *plane_state; - int src_x = 0, src_y = 0, src_w = 0, src_h = 0; - int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0; - int scaler_id = -1; - - plane_state = to_intel_plane_state(plane->state); - - if (!visible || !fb) { - I915_WRITE(PLANE_CTL(pipe, 0), 0); - I915_WRITE(PLANE_SURF(pipe, 0), 0); - POSTING_READ(PLANE_CTL(pipe, 0)); - return; - } + int scaler_id = plane_state->scaler_id; + int src_x = plane_state->src.x1 >> 16; + int src_y = plane_state->src.y1 >> 16; + int src_w = drm_rect_width(&plane_state->src) >> 16; + int src_h = drm_rect_height(&plane_state->src) >> 16; + int dst_x = plane_state->dst.x1; + int dst_y = plane_state->dst.y1; + int dst_w = drm_rect_width(&plane_state->dst); + int dst_h = drm_rect_height(&plane_state->dst); plane_ctl = PLANE_CTL_ENABLE | PLANE_CTL_PIPE_GAMMA_ENABLE | @@ -3121,41 +3105,26 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc, plane_ctl |= skl_plane_ctl_format(fb->pixel_format); plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]); plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE; - - rotation = plane->state->rotation; plane_ctl |= skl_plane_ctl_rotation(rotation); - obj = intel_fb_obj(fb); stride_div = intel_fb_stride_alignment(dev, fb->modifier[0], fb->pixel_format); surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0); WARN_ON(drm_rect_width(&plane_state->src) == 0); - scaler_id = plane_state->scaler_id; - src_x = plane_state->src.x1 >> 16; - src_y = plane_state->src.y1 >> 16; - src_w = drm_rect_width(&plane_state->src) >> 16; - src_h = drm_rect_height(&plane_state->src) >> 16; - dst_x = plane_state->dst.x1; - dst_y = plane_state->dst.y1; - dst_w = drm_rect_width(&plane_state->dst); - dst_h = drm_rect_height(&plane_state->dst); - - WARN_ON(x != src_x || y != src_y); - if (intel_rotation_90_or_270(rotation)) { /* stride = Surface height in tiles */ tile_height = intel_tile_height(dev, fb->pixel_format, fb->modifier[0], 0); stride = DIV_ROUND_UP(fb->height, tile_height); - x_offset = stride * tile_height - y - src_h; - y_offset = x; + x_offset = stride * tile_height - src_y - src_h; + y_offset = src_x; plane_size = (src_w - 1) << 16 | (src_h - 1); } else { stride = fb->pitches[0] / stride_div; - x_offset = x; - y_offset = y; + x_offset = src_x; + y_offset = src_y; plane_size = (src_h - 1) << 16 | (src_w - 1); } plane_offset = y_offset << 16 | x_offset; @@ -3188,20 +3157,30 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc, POSTING_READ(PLANE_SURF(pipe, 0)); } -/* Assume fb object is pinned & idle & fenced and just update base pointers */ -static int -intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, - int x, int y, enum mode_set_atomic state) +static void skylake_disable_primary_plane(struct drm_plane *primary, + struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; + int pipe = to_intel_crtc(crtc)->pipe; if (dev_priv->fbc.deactivate) dev_priv->fbc.deactivate(dev_priv); - dev_priv->display.update_primary_plane(crtc, fb, x, y); + I915_WRITE(PLANE_CTL(pipe, 0), 0); + I915_WRITE(PLANE_SURF(pipe, 0), 0); + POSTING_READ(PLANE_SURF(pipe, 0)); +} - return 0; +/* Assume fb object is pinned & idle & fenced and just update base pointers */ +static int +intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, + int x, int y, enum mode_set_atomic state) +{ + /* Support for kgdboc is disabled, this needs a major rework. */ + DRM_ERROR("legacy panic handler not supported any more.\n"); + + return -ENODEV; } static void intel_complete_page_flips(struct drm_device *dev) @@ -3228,8 +3207,10 @@ static void intel_update_primary_planes(struct drm_device *dev) drm_modeset_lock_crtc(crtc, &plane->base); plane_state = to_intel_plane_state(plane->base.state); - if (crtc->state->active && plane_state->base.fb) - plane->commit_plane(&plane->base, plane_state); + if (plane_state->visible) + plane->update_plane(&plane->base, + to_intel_crtc_state(crtc->state), + plane_state); drm_modeset_unlock_crtc(crtc); } @@ -14037,32 +14018,6 @@ intel_check_primary_plane(struct drm_plane *plane, &state->visible); } -static void -intel_commit_primary_plane(struct drm_plane *plane, - struct intel_plane_state *state) -{ - struct drm_crtc *crtc = state->base.crtc; - struct drm_framebuffer *fb = state->base.fb; - struct drm_device *dev = plane->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - - crtc = crtc ? crtc : plane->crtc; - - dev_priv->display.update_primary_plane(crtc, fb, - state->src.x1 >> 16, - state->src.y1 >> 16); -} - -static void -intel_disable_primary_plane(struct drm_plane *plane, - struct drm_crtc *crtc) -{ - struct drm_device *dev = plane->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - - dev_priv->display.update_primary_plane(crtc, NULL, 0, 0); -} - static void intel_begin_crtc_commit(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { @@ -14147,20 +14102,33 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, primary->plane = pipe; primary->frontbuffer_bit = INTEL_FRONTBUFFER_PRIMARY(pipe); primary->check_plane = intel_check_primary_plane; - primary->commit_plane = intel_commit_primary_plane; - primary->disable_plane = intel_disable_primary_plane; if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4) primary->plane = !pipe; if (INTEL_INFO(dev)->gen >= 9) { intel_primary_formats = skl_primary_formats; num_formats = ARRAY_SIZE(skl_primary_formats); + + primary->update_plane = skylake_update_primary_plane; + primary->disable_plane = skylake_disable_primary_plane; + } else if (HAS_PCH_SPLIT(dev)) { + intel_primary_formats = i965_primary_formats; + num_formats = ARRAY_SIZE(i965_primary_formats); + + primary->update_plane = ironlake_update_primary_plane; + primary->disable_plane = i9xx_disable_primary_plane; } else if (INTEL_INFO(dev)->gen >= 4) { intel_primary_formats = i965_primary_formats; num_formats = ARRAY_SIZE(i965_primary_formats); + + primary->update_plane = i9xx_update_primary_plane; + primary->disable_plane = i9xx_disable_primary_plane; } else { intel_primary_formats = i8xx_primary_formats; num_formats = ARRAY_SIZE(i8xx_primary_formats); + + primary->update_plane = i9xx_update_primary_plane; + primary->disable_plane = i9xx_disable_primary_plane; } drm_universal_plane_init(dev, &primary->base, 0, @@ -14988,8 +14956,6 @@ static void intel_init_display(struct drm_device *dev) haswell_crtc_compute_clock; dev_priv->display.crtc_enable = haswell_crtc_enable; dev_priv->display.crtc_disable = haswell_crtc_disable; - dev_priv->display.update_primary_plane = - skylake_update_primary_plane; } else if (HAS_DDI(dev)) { dev_priv->display.get_pipe_config = haswell_get_pipe_config; dev_priv->display.get_initial_plane_config = @@ -14998,8 +14964,6 @@ static void intel_init_display(struct drm_device *dev) haswell_crtc_compute_clock; dev_priv->display.crtc_enable = haswell_crtc_enable; dev_priv->display.crtc_disable = haswell_crtc_disable; - dev_priv->display.update_primary_plane = - ironlake_update_primary_plane; } else if (HAS_PCH_SPLIT(dev)) { dev_priv->display.get_pipe_config = ironlake_get_pipe_config; dev_priv->display.get_initial_plane_config = @@ -15008,8 +14972,6 @@ static void intel_init_display(struct drm_device *dev) ironlake_crtc_compute_clock; dev_priv->display.crtc_enable = ironlake_crtc_enable; dev_priv->display.crtc_disable = ironlake_crtc_disable; - dev_priv->display.update_primary_plane = - ironlake_update_primary_plane; } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { dev_priv->display.get_pipe_config = i9xx_get_pipe_config; dev_priv->display.get_initial_plane_config = @@ -15017,8 +14979,6 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock; dev_priv->display.crtc_enable = valleyview_crtc_enable; dev_priv->display.crtc_disable = i9xx_crtc_disable; - dev_priv->display.update_primary_plane = - i9xx_update_primary_plane; } else { dev_priv->display.get_pipe_config = i9xx_get_pipe_config; dev_priv->display.get_initial_plane_config = @@ -15026,8 +14986,6 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock; dev_priv->display.crtc_enable = i9xx_crtc_enable; dev_priv->display.crtc_disable = i9xx_crtc_disable; - dev_priv->display.update_primary_plane = - i9xx_update_primary_plane; } /* Returns the core display clock speed */ -- cgit v1.2.3 From c03242b1317694e50e2c781026bb7bee8dfcc2bb Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 7 Jan 2016 11:54:12 +0100 Subject: drm/i915: Remove commit_plane function pointer. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With sprites, cursors and primary planes taking the atomic state this is now unused. It's removed in a separate commit to allow a revert. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1452164052-21752-8-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_atomic_plane.c | 4 +--- drivers/gpu/drm/i915/intel_drv.h | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index 969aa410deaa..e0b851a0004a 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -198,9 +198,7 @@ static void intel_plane_atomic_update(struct drm_plane *plane, struct drm_crtc_state *crtc_state = drm_atomic_get_existing_crtc_state(old_state->state, crtc); - if (intel_plane->commit_plane) - intel_plane->commit_plane(plane, intel_state); - else if (intel_state->visible) + if (intel_state->visible) intel_plane->update_plane(plane, to_intel_crtc_state(crtc_state), intel_state); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6f3850beccd9..bdfe4035e074 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -692,8 +692,6 @@ struct intel_plane { int (*check_plane)(struct drm_plane *plane, struct intel_crtc_state *crtc_state, struct intel_plane_state *state); - void (*commit_plane)(struct drm_plane *plane, - struct intel_plane_state *state); }; struct intel_watermark_params { -- cgit v1.2.3 From 16fbc291cb87c7defcd13ad715d3e4af0d523e43 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 6 Jan 2016 12:08:36 +0000 Subject: drm/i915/kbl: Enable PW1 and Misc I/O power wells My kbl stopped working because of this. Fixes regression from commit 2f693e28b8df69f67beced5e18bb2b91c2bfcec2 Author: Damien Lespiau Date: Wed Nov 4 19:24:12 2015 +0200 drm/i915: Make turning on/off PW1 and Misc I/O part of the init/fini sequences Cc: Damien Lespiau Cc: Paulo Zanoni Cc: Patrik Jakobsson Cc: Imre Deak Signed-off-by: Michel Thierry Link: http://patchwork.freedesktop.org/patch/msgid/1452082116-16770-1-git-send-email-michel.thierry@intel.com Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_runtime_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index ddbdbffe829a..4b44e6862a27 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -1851,7 +1851,7 @@ void skl_pw1_misc_io_init(struct drm_i915_private *dev_priv) { struct i915_power_well *well; - if (!IS_SKYLAKE(dev_priv)) + if (!(IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))) return; well = lookup_power_well(dev_priv, SKL_DISP_PW_1); @@ -1865,7 +1865,7 @@ void skl_pw1_misc_io_fini(struct drm_i915_private *dev_priv) { struct i915_power_well *well; - if (!IS_SKYLAKE(dev_priv)) + if (!(IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))) return; well = lookup_power_well(dev_priv, SKL_DISP_PW_1); -- cgit v1.2.3 From 5590a5f0af78c73c94de8c63ca580bff31b97c1e Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 5 Jan 2016 10:30:05 -0800 Subject: drm/i915: Cleanup some of the CSB handling I think this patch is a worthwhile cleanup even if it might look only marginally useful. It gets more useful in upcoming patches and for handling of future GEN platforms. The only non-mechanical part of this is the removal of the extra & operation on the ring->next_context_status_buffer. This is safe because right above this, we already did a modulus operation. Signed-off-by: Ben Widawsky Link: http://patchwork.freedesktop.org/patch/msgid/1452018609-10142-2-git-send-email-benjamin.widawsky@intel.com Reviewed-by: Michel Thierry Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 6 +++--- drivers/gpu/drm/i915/intel_lrc.c | 15 +++++++++------ drivers/gpu/drm/i915/intel_lrc.h | 18 ++++++++++++++++-- 3 files changed, 28 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 0fc38bb7276c..3b05bd189eab 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2092,13 +2092,13 @@ static int i915_execlists(struct seq_file *m, void *data) seq_printf(m, "\tStatus pointer: 0x%08X\n", status_pointer); read_pointer = ring->next_context_status_buffer; - write_pointer = status_pointer & 0x07; + write_pointer = GEN8_CSB_WRITE_PTR(status_pointer); if (read_pointer > write_pointer) - write_pointer += 6; + write_pointer += GEN8_CSB_ENTRIES; seq_printf(m, "\tRead pointer: 0x%08X, write pointer 0x%08X\n", read_pointer, write_pointer); - for (i = 0; i < 6; i++) { + for (i = 0; i < GEN8_CSB_ENTRIES; i++) { status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, i)); ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, i)); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 8096c6a79424..7fb2035b71eb 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -516,7 +516,7 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring) status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(ring)); read_pointer = ring->next_context_status_buffer; - write_pointer = status_pointer & GEN8_CSB_PTR_MASK; + write_pointer = GEN8_CSB_WRITE_PTR(status_pointer); if (read_pointer > write_pointer) write_pointer += GEN8_CSB_ENTRIES; @@ -559,10 +559,11 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring) WARN(submit_contexts > 2, "More than two context complete events?\n"); ring->next_context_status_buffer = write_pointer % GEN8_CSB_ENTRIES; + /* Update the read pointer to the old write pointer. Manual ringbuffer + * management ftw */ I915_WRITE(RING_CONTEXT_STATUS_PTR(ring), - _MASKED_FIELD(GEN8_CSB_PTR_MASK << 8, - ((u32)ring->next_context_status_buffer & - GEN8_CSB_PTR_MASK) << 8)); + _MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, + ring->next_context_status_buffer << 8)); } static int execlists_context_queue(struct drm_i915_gem_request *request) @@ -1506,9 +1507,11 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring) * | Suspend-to-idle (freeze) | Suspend-to-RAM (mem) | * BDW | CSB regs not reset | CSB regs reset | * CHT | CSB regs not reset | CSB regs not reset | + * SKL | ? | ? | + * BXT | ? | ? | */ - next_context_status_buffer_hw = (I915_READ(RING_CONTEXT_STATUS_PTR(ring)) - & GEN8_CSB_PTR_MASK); + next_context_status_buffer_hw = + GEN8_CSB_WRITE_PTR(I915_READ(RING_CONTEXT_STATUS_PTR(ring))); /* * When the CSB registers are reset (also after power-up / gpu reset), diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index ae90f86a2849..de41ad6cd63d 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -25,8 +25,6 @@ #define _INTEL_LRC_H_ #define GEN8_LR_CONTEXT_ALIGN 4096 -#define GEN8_CSB_ENTRIES 6 -#define GEN8_CSB_PTR_MASK 0x07 /* Execlists regs */ #define RING_ELSP(ring) _MMIO((ring)->mmio_base + 0x230) @@ -40,6 +38,22 @@ #define RING_CONTEXT_STATUS_BUF_HI(ring, i) _MMIO((ring)->mmio_base + 0x370 + (i) * 8 + 4) #define RING_CONTEXT_STATUS_PTR(ring) _MMIO((ring)->mmio_base + 0x3a0) +/* The docs specify that the write pointer wraps around after 5h, "After status + * is written out to the last available status QW at offset 5h, this pointer + * wraps to 0." + * + * Therefore, one must infer than even though there are 3 bits available, 6 and + * 7 appear to be * reserved. + */ +#define GEN8_CSB_ENTRIES 6 +#define GEN8_CSB_PTR_MASK 0x7 +#define GEN8_CSB_READ_PTR_MASK (GEN8_CSB_PTR_MASK << 8) +#define GEN8_CSB_WRITE_PTR_MASK (GEN8_CSB_PTR_MASK << 0) +#define GEN8_CSB_WRITE_PTR(csb_status) \ + (((csb_status) & GEN8_CSB_WRITE_PTR_MASK) >> 0) +#define GEN8_CSB_READ_PTR(csb_status) \ + (((csb_status) & GEN8_CSB_READ_PTR_MASK) >> 8) + /* Logical Rings */ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request); int intel_logical_ring_reserve_space(struct drm_i915_gem_request *request); -- cgit v1.2.3 From f764a8b146547b643d40b90a304ff99389edf352 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 5 Jan 2016 10:30:06 -0800 Subject: drm/i915: Change WARN to ERROR in CSB count There is no point in emitting a WARN since the backtrace will always be the same. Errors have actually become easier to spot given the large number of WARNs which exist today in modesetting paths. Signed-off-by: Ben Widawsky Reviewed-by: Michel Thierry Link: http://patchwork.freedesktop.org/patch/msgid/1452018609-10142-3-git-send-email-benjamin.widawsky@intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 7fb2035b71eb..14affaa2a0ba 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -556,7 +556,9 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring) spin_unlock(&ring->execlist_lock); - WARN(submit_contexts > 2, "More than two context complete events?\n"); + if (unlikely(submit_contexts > 2)) + DRM_ERROR("More than two context complete events?\n"); + ring->next_context_status_buffer = write_pointer % GEN8_CSB_ENTRIES; /* Update the read pointer to the old write pointer. Manual ringbuffer -- cgit v1.2.3 From 91a4103206e3386aa3ea53b25d23f52913353e3a Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 5 Jan 2016 10:30:07 -0800 Subject: drm/i915: Extract CSB status read This is a useful thing to have around as a function because the mechanism may change in the future. There is a net increase in LOC here, and it will continue to be the case on GEN8 and GEN9 - but future GENs may have an alternate mechanism for doing this. Signed-off-by: Ben Widawsky Reviewed-by: Michel Thierry Link: http://patchwork.freedesktop.org/patch/msgid/1452018609-10142-4-git-send-email-benjamin.widawsky@intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 14affaa2a0ba..23839ff04e27 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -496,6 +496,19 @@ static bool execlists_check_remove_request(struct intel_engine_cs *ring, return false; } +static void get_context_status(struct intel_engine_cs *ring, + u8 read_pointer, + u32 *status, u32 *context_id) +{ + struct drm_i915_private *dev_priv = ring->dev->dev_private; + + if (WARN_ON(read_pointer >= GEN8_CSB_ENTRIES)) + return; + + *status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, read_pointer)); + *context_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, read_pointer)); +} + /** * intel_lrc_irq_handler() - handle Context Switch interrupts * @ring: Engine Command Streamer to handle. @@ -523,9 +536,9 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring) spin_lock(&ring->execlist_lock); while (read_pointer < write_pointer) { - read_pointer++; - status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, read_pointer % GEN8_CSB_ENTRIES)); - status_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, read_pointer % GEN8_CSB_ENTRIES)); + + get_context_status(ring, ++read_pointer % GEN8_CSB_ENTRIES, + &status, &status_id); if (status & GEN8_CTX_STATUS_IDLE_ACTIVE) continue; -- cgit v1.2.3 From 07c519134417d92c2e1a536e2b66d4ffff4b3be0 Mon Sep 17 00:00:00 2001 From: Lyude Date: Thu, 7 Jan 2016 10:43:28 -0500 Subject: drm/i915: intel_hpd_init(): Fix suspend/resume reprobing This fixes reprobing of display connectors on resume. After some talking with danvet on IRC, I learned that calling drm_helper_hpd_irq_event() does actually trigger a full reprobe of each connector's status. It turns out this is the actual reason reprobing on resume hasn't been working (this was observed on a T440s): - We call hpd_init() - We check each connector for a couple of things before marking connector->polled with DRM_CONNECTOR_POLL_HPD, one of which is an active encoder. Of course, a disconnected port won't have an active encoder, so we don't add the flag to any of the connectors. - We call drm_helper_hpd_irq_event() - drm_helper_irq_event() checks each connector for the DRM_CONNECTOR_POLL_HPD flag. The only one that has it is eDP-1, so we skip reprobing each connector except that one. In addition, we also now avoid setting connector->polled to DRM_CONNECTOR_POLL_HPD for MST connectors, since their reprobing is handled by the mst helpers. This is probably what was originally intended to happen here. Changes since V1: * Use the explanation of the issue as the commit message instead * Change the title of the commit, since this does more then just stop a check for an encoder now * Add "Fixes" line for the patch that introduced this regression * Don't enable DRM_CONNECTOR_POLL_HPD for mst connectors Changes since V2: * Put patch changelog above Signed-off-by * Follow Daniel Vetter's suggestion for making the code here a bit more legible Fixes: 0e32b39ceed6 ("drm/i915: add DP 1.2 MST support (v0.7)") Cc: stable@vger.kernel.org Signed-off-by: Lyude Link: http://patchwork.freedesktop.org/patch/msgid/1452181408-14777-1-git-send-email-cpaul@redhat.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_hotplug.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c index a294a3cbaea1..bee673005d48 100644 --- a/drivers/gpu/drm/i915/intel_hotplug.c +++ b/drivers/gpu/drm/i915/intel_hotplug.c @@ -468,9 +468,14 @@ void intel_hpd_init(struct drm_i915_private *dev_priv) list_for_each_entry(connector, &mode_config->connector_list, head) { struct intel_connector *intel_connector = to_intel_connector(connector); connector->polled = intel_connector->polled; - if (connector->encoder && !connector->polled && I915_HAS_HOTPLUG(dev) && intel_connector->encoder->hpd_pin > HPD_NONE) - connector->polled = DRM_CONNECTOR_POLL_HPD; + + /* MST has a dynamic intel_connector->encoder and it's reprobing + * is all handled by the MST helpers. */ if (intel_connector->mst_port) + continue; + + if (!connector->polled && I915_HAS_HOTPLUG(dev) && + intel_connector->encoder->hpd_pin > HPD_NONE) connector->polled = DRM_CONNECTOR_POLL_HPD; } -- cgit v1.2.3 From 2e78416e763261fa8187429b7ea053d369fa7f79 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Tue, 5 Jan 2016 11:11:27 -0800 Subject: drm/i915: Update Skylake DDI translation table for HDMI. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When debuging an intermittent corrupted screen I suspected on DDI translation table and checked we are out of date with the spec. I'm not sure this will fix my bug yet, but it is always good to follow the spec. v2: Ville caught a switched i-boost value. Thanks! Cc: Ville Syrjälä Signed-off-by: Rodrigo Vivi Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1452021087-21673-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_ddi.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 5c0801895aa7..7961fcc2adda 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -226,26 +226,26 @@ static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { { 0x00000018, 0x000000A1, 0x0 }, { 0x00000018, 0x00000098, 0x0 }, { 0x00004013, 0x00000088, 0x0 }, - { 0x00006012, 0x00000087, 0x0 }, + { 0x80006012, 0x000000CD, 0x1 }, { 0x00000018, 0x000000DF, 0x0 }, - { 0x00003015, 0x00000087, 0x0 }, /* Default */ - { 0x00003015, 0x000000C7, 0x0 }, - { 0x00000018, 0x000000C7, 0x0 }, + { 0x80003015, 0x000000CD, 0x1 }, /* Default */ + { 0x80003015, 0x000000C0, 0x1 }, + { 0x80000018, 0x000000C0, 0x1 }, }; /* Skylake Y */ static const struct ddi_buf_trans skl_y_ddi_translations_hdmi[] = { { 0x00000018, 0x000000A1, 0x0 }, { 0x00005012, 0x000000DF, 0x0 }, - { 0x00007011, 0x00000084, 0x0 }, + { 0x80007011, 0x000000CB, 0x3 }, { 0x00000018, 0x000000A4, 0x0 }, { 0x00000018, 0x0000009D, 0x0 }, { 0x00004013, 0x00000080, 0x0 }, - { 0x00006013, 0x000000C7, 0x0 }, + { 0x80006013, 0x000000C0, 0x3 }, { 0x00000018, 0x0000008A, 0x0 }, - { 0x00003015, 0x000000C7, 0x0 }, /* Default */ - { 0x80003015, 0x000000C7, 0x7 }, /* Uses I_boost level 0x7 */ - { 0x00000018, 0x000000C7, 0x0 }, + { 0x80003015, 0x000000C0, 0x3 }, /* Default */ + { 0x80003015, 0x000000C0, 0x3 }, + { 0x80000018, 0x000000C0, 0x3 }, }; struct bxt_ddi_buf_trans { -- cgit v1.2.3 From 63ebce1fe883c26a1838c81795adc6134b5a386b Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Tue, 5 Jan 2016 07:58:31 -0800 Subject: drm/i915: Update Skylake DDI translation table for DP. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When reviewing DDI translation table I noticed few changes we haven't incorporated yet and it is always good to follow latest spec. Signed-off-by: Rodrigo Vivi Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1452009511-15064-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_ddi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 7961fcc2adda..f271f7c0e9ac 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -145,7 +145,7 @@ static const struct ddi_buf_trans skl_ddi_translations_dp[] = { static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = { { 0x0000201B, 0x000000A2, 0x0 }, { 0x00005012, 0x00000088, 0x0 }, - { 0x00007011, 0x00000087, 0x0 }, + { 0x80007011, 0x000000CD, 0x0 }, { 0x80009010, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */ { 0x0000201B, 0x0000009D, 0x0 }, { 0x80005012, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */ @@ -158,7 +158,7 @@ static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = { static const struct ddi_buf_trans skl_y_ddi_translations_dp[] = { { 0x00000018, 0x000000A2, 0x0 }, { 0x00005012, 0x00000088, 0x0 }, - { 0x00007011, 0x00000087, 0x0 }, + { 0x80007011, 0x000000CD, 0x0 }, { 0x80009010, 0x000000C0, 0x3 }, /* Uses I_boost level 0x3 */ { 0x00000018, 0x0000009D, 0x0 }, { 0x80005012, 0x000000C0, 0x3 }, /* Uses I_boost level 0x3 */ -- cgit v1.2.3 From d7097cffdbc06e7d1c71bfc53151160237241f48 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Tue, 5 Jan 2016 11:18:55 -0800 Subject: drm/i915: Cleaning up DDI translation tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional changes. That state the obvious and just duplicate the place we need to change whenever the table is updated. So let's clean it. Cc: Ville Syrjälä Signed-off-by: Rodrigo Vivi Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1452021535-22641-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_ddi.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index f271f7c0e9ac..612400fab559 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -133,12 +133,12 @@ static const struct ddi_buf_trans skl_ddi_translations_dp[] = { { 0x00002016, 0x000000A0, 0x0 }, { 0x00005012, 0x0000009B, 0x0 }, { 0x00007011, 0x00000088, 0x0 }, - { 0x80009010, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */ + { 0x80009010, 0x000000C0, 0x1 }, { 0x00002016, 0x0000009B, 0x0 }, { 0x00005012, 0x00000088, 0x0 }, - { 0x80007011, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */ + { 0x80007011, 0x000000C0, 0x1 }, { 0x00002016, 0x000000DF, 0x0 }, - { 0x80005012, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */ + { 0x80005012, 0x000000C0, 0x1 }, }; /* Skylake U */ @@ -146,12 +146,12 @@ static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = { { 0x0000201B, 0x000000A2, 0x0 }, { 0x00005012, 0x00000088, 0x0 }, { 0x80007011, 0x000000CD, 0x0 }, - { 0x80009010, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */ + { 0x80009010, 0x000000C0, 0x1 }, { 0x0000201B, 0x0000009D, 0x0 }, - { 0x80005012, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */ - { 0x80007011, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */ + { 0x80005012, 0x000000C0, 0x1 }, + { 0x80007011, 0x000000C0, 0x1 }, { 0x00002016, 0x00000088, 0x0 }, - { 0x80005012, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */ + { 0x80005012, 0x000000C0, 0x1 }, }; /* Skylake Y */ @@ -159,12 +159,12 @@ static const struct ddi_buf_trans skl_y_ddi_translations_dp[] = { { 0x00000018, 0x000000A2, 0x0 }, { 0x00005012, 0x00000088, 0x0 }, { 0x80007011, 0x000000CD, 0x0 }, - { 0x80009010, 0x000000C0, 0x3 }, /* Uses I_boost level 0x3 */ + { 0x80009010, 0x000000C0, 0x3 }, { 0x00000018, 0x0000009D, 0x0 }, - { 0x80005012, 0x000000C0, 0x3 }, /* Uses I_boost level 0x3 */ - { 0x80007011, 0x000000C0, 0x3 }, /* Uses I_boost level 0x3 */ + { 0x80005012, 0x000000C0, 0x3 }, + { 0x80007011, 0x000000C0, 0x3 }, { 0x00000018, 0x00000088, 0x0 }, - { 0x80005012, 0x000000C0, 0x3 }, /* Uses I_boost level 0x3 */ + { 0x80005012, 0x000000C0, 0x3 }, }; /* -- cgit v1.2.3 From 61642ff03523995918c452ef41adf0795d54d909 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Tue, 1 Dec 2015 17:56:12 +0200 Subject: drm/i915: Inspect subunit states on hangcheck If head seems stuck and engine in question is rcs, inspect subunit state transitions from undone to done, before deciding that this really is a hang instead of limited progress. Only account the transitions of subunits from undone to done once, to prevent unstable subunit states to keep us falsely active. As this adds one extra steps to hangcheck heuristics, before hang is declared, it adds 1500ms to to detect hang for render ring to a total of 7500ms. We could sample the subunit states on first head stuck condition but decide not to do so only in order to mimic old behaviour. This way the check order of promotion from seqno > atchd > instdone is consistently done. v2: Deal with unstable done states (Arun) Clear instdone progress on head and seqno movement (Chris) Report raw and accumulated instdone's in in debugfs (Chris) Return HANGCHECK_ACTIVE on undone->done References: https://bugs.freedesktop.org/show_bug.cgi?id=93029 Cc: Chris Wilson Cc: Dave Gordon Cc: Daniel Vetter Cc: Arun Siluvery Reviewed-by: Chris Wilson Signed-off-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1448985372-19535-1-git-send-email-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 20 ++++++++++- drivers/gpu/drm/i915/i915_irq.c | 62 ++++++++++++++++++++++++++++++--- drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 3 files changed, 77 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3b05bd189eab..e3377abc0d4d 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1331,7 +1331,8 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) struct intel_engine_cs *ring; u64 acthd[I915_NUM_RINGS]; u32 seqno[I915_NUM_RINGS]; - int i; + u32 instdone[I915_NUM_INSTDONE_REG]; + int i, j; if (!i915.enable_hangcheck) { seq_printf(m, "Hangcheck disabled\n"); @@ -1345,6 +1346,8 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) acthd[i] = intel_ring_get_active_head(ring); } + i915_get_extra_instdone(dev, instdone); + intel_runtime_pm_put(dev_priv); if (delayed_work_pending(&dev_priv->gpu_error.hangcheck_work)) { @@ -1365,6 +1368,21 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) (long long)ring->hangcheck.max_acthd); seq_printf(m, "\tscore = %d\n", ring->hangcheck.score); seq_printf(m, "\taction = %d\n", ring->hangcheck.action); + + if (ring->id == RCS) { + seq_puts(m, "\tinstdone read ="); + + for (j = 0; j < I915_NUM_INSTDONE_REG; j++) + seq_printf(m, " 0x%08x", instdone[j]); + + seq_puts(m, "\n\tinstdone accu ="); + + for (j = 0; j < I915_NUM_INSTDONE_REG; j++) + seq_printf(m, " 0x%08x", + ring->hangcheck.instdone[j]); + + seq_puts(m, "\n"); + } } return 0; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index fa8afa7860ae..b775decf9d27 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2949,14 +2949,44 @@ static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv) ring->hangcheck.deadlock = 0; } -static enum intel_ring_hangcheck_action -ring_stuck(struct intel_engine_cs *ring, u64 acthd) +static bool subunits_stuck(struct intel_engine_cs *ring) { - struct drm_device *dev = ring->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - u32 tmp; + u32 instdone[I915_NUM_INSTDONE_REG]; + bool stuck; + int i; + + if (ring->id != RCS) + return true; + + i915_get_extra_instdone(ring->dev, instdone); + /* There might be unstable subunit states even when + * actual head is not moving. Filter out the unstable ones by + * accumulating the undone -> done transitions and only + * consider those as progress. + */ + stuck = true; + for (i = 0; i < I915_NUM_INSTDONE_REG; i++) { + const u32 tmp = instdone[i] | ring->hangcheck.instdone[i]; + + if (tmp != ring->hangcheck.instdone[i]) + stuck = false; + + ring->hangcheck.instdone[i] |= tmp; + } + + return stuck; +} + +static enum intel_ring_hangcheck_action +head_stuck(struct intel_engine_cs *ring, u64 acthd) +{ if (acthd != ring->hangcheck.acthd) { + + /* Clear subunit states on head movement */ + memset(ring->hangcheck.instdone, 0, + sizeof(ring->hangcheck.instdone)); + if (acthd > ring->hangcheck.max_acthd) { ring->hangcheck.max_acthd = acthd; return HANGCHECK_ACTIVE; @@ -2965,6 +2995,24 @@ ring_stuck(struct intel_engine_cs *ring, u64 acthd) return HANGCHECK_ACTIVE_LOOP; } + if (!subunits_stuck(ring)) + return HANGCHECK_ACTIVE; + + return HANGCHECK_HUNG; +} + +static enum intel_ring_hangcheck_action +ring_stuck(struct intel_engine_cs *ring, u64 acthd) +{ + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum intel_ring_hangcheck_action ha; + u32 tmp; + + ha = head_stuck(ring, acthd); + if (ha != HANGCHECK_HUNG) + return ha; + if (IS_GEN2(dev)) return HANGCHECK_HUNG; @@ -3106,7 +3154,11 @@ static void i915_hangcheck_elapsed(struct work_struct *work) if (ring->hangcheck.score > 0) ring->hangcheck.score--; + /* Clear head and subunit states on seqno movement */ ring->hangcheck.acthd = ring->hangcheck.max_acthd = 0; + + memset(ring->hangcheck.instdone, 0, + sizeof(ring->hangcheck.instdone)); } ring->hangcheck.seqno = seqno; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 49574ffe54bc..7349d9258191 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -93,6 +93,7 @@ struct intel_ring_hangcheck { int score; enum intel_ring_hangcheck_action action; int deadlock; + u32 instdone[I915_NUM_INSTDONE_REG]; }; struct intel_ringbuffer { -- cgit v1.2.3 From 8a47eb198d6e59e5d2509324287d0d913b2d5af1 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Tue, 15 Dec 2015 19:24:47 +0200 Subject: drm/i915: Consolidate unclaimed mmio detection Access the unclaimed reg detection register through one helper which also does cleanup. Note that we now access the register only if the platform has the actual non claimed access bit. This prevents reading the register with gens that doesn't have the register or the unclaimed bit, when debug_mmio > 0. Note that we post after clearing the bit. This makes sure that the next unclaimed write access would get detected also if it happened right after clearing, and not fold into the previous detection. v2: s/unclaimed_reg_access/check_for_unclaimed_mmio (Chris) debug log on unclaimed detection on uncore init (Joonas) v3: remove posting read (Ville) Cc: Joonas Lahtinen Cc: Chris Wilson Cc: Paulo Zanoni Reviewed-by: Chris Wilson Signed-off-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1450200287-24080-1-git-send-email-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/intel_uncore.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 277e60ae0e47..358cb9cb219e 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -327,13 +327,31 @@ static void intel_uncore_ellc_detect(struct drm_device *dev) } } +static bool +check_for_unclaimed_mmio(struct drm_i915_private *dev_priv) +{ + u32 dbg; + + if (!HAS_FPGA_DBG_UNCLAIMED(dev_priv)) + return false; + + dbg = __raw_i915_read32(dev_priv, FPGA_DBG); + if (likely(!(dbg & FPGA_DBG_RM_NOCLAIM))) + return false; + + __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM); + + return true; +} + static void __intel_uncore_early_sanitize(struct drm_device *dev, bool restore_forcewake) { struct drm_i915_private *dev_priv = dev->dev_private; - if (HAS_FPGA_DBG_UNCLAIMED(dev)) - __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM); + /* clear out unclaimed reg detection bit */ + if (check_for_unclaimed_mmio(dev_priv)) + DRM_DEBUG("unclaimed mmio detected on uncore init, clearing\n"); /* clear out old GT FIFO errors */ if (IS_GEN6(dev) || IS_GEN7(dev)) @@ -594,10 +612,9 @@ hsw_unclaimed_reg_debug(struct drm_i915_private *dev_priv, if (!i915.mmio_debug) return; - if (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM) { + if (check_for_unclaimed_mmio(dev_priv)) { WARN(1, "Unclaimed register detected %s %s register 0x%x\n", when, op, i915_mmio_reg_offset(reg)); - __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM); i915.mmio_debug--; /* Only report the first N failures */ } } @@ -610,11 +627,10 @@ hsw_unclaimed_reg_detect(struct drm_i915_private *dev_priv) if (i915.mmio_debug || !mmio_debug_once) return; - if (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM) { + if (check_for_unclaimed_mmio(dev_priv)) { DRM_DEBUG("Unclaimed register detected, " "enabling oneshot unclaimed register reporting. " "Please use i915.mmio_debug=N for more information.\n"); - __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM); i915.mmio_debug = mmio_debug_once--; } } @@ -1582,11 +1598,6 @@ bool intel_has_gpu_reset(struct drm_device *dev) void intel_uncore_check_errors(struct drm_device *dev) { - struct drm_i915_private *dev_priv = dev->dev_private; - - if (HAS_FPGA_DBG_UNCLAIMED(dev) && - (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) { + if (check_for_unclaimed_mmio(to_i915(dev))) DRM_ERROR("Unclaimed register before interrupt\n"); - __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM); - } } -- cgit v1.2.3 From fc97618bf373b496858eca463e5154085835ae41 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Tue, 15 Dec 2015 16:25:07 +0200 Subject: drm/i915: Introduce intel_uncore_unclaimed_mmio Currently interrupt code is the only place checking for the unclaimed register access prior to actual register macros using the same functionality. Rename the function and make it return bool so that the possible error message context is clear in the caller side. The motivation is to allow usage of unclaimed detection on arbitrary places. v2: rebase, s/access/mmio, s/dev/dev_priv Reviewed-by: Chris Wilson Signed-off-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1450189512-30360-2-git-send-email-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_irq.c | 3 ++- drivers/gpu/drm/i915/intel_uncore.c | 5 ++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8cf655c6fc03..aa32e8872a95 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2717,7 +2717,7 @@ extern void intel_uncore_sanitize(struct drm_device *dev); extern void intel_uncore_early_sanitize(struct drm_device *dev, bool restore_forcewake); extern void intel_uncore_init(struct drm_device *dev); -extern void intel_uncore_check_errors(struct drm_device *dev); +extern bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv); extern void intel_uncore_fini(struct drm_device *dev); extern void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore); const char *intel_uncore_forcewake_domain_to_str(const enum forcewake_domain_id id); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b775decf9d27..e7e44a972905 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2190,7 +2190,8 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) /* We get interrupts on unclaimed registers, so check for this before we * do any I915_{READ,WRITE}. */ - intel_uncore_check_errors(dev); + if (intel_uncore_unclaimed_mmio(dev_priv)) + DRM_ERROR("Unclaimed register before interrupt\n"); /* disable master interrupt before clearing iir */ de_ier = I915_READ(DEIER); diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 358cb9cb219e..7ab5916f90dd 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1596,8 +1596,7 @@ bool intel_has_gpu_reset(struct drm_device *dev) return intel_get_gpu_reset(dev) != NULL; } -void intel_uncore_check_errors(struct drm_device *dev) +bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv) { - if (check_for_unclaimed_mmio(to_i915(dev))) - DRM_ERROR("Unclaimed register before interrupt\n"); + return check_for_unclaimed_mmio(dev_priv); } -- cgit v1.2.3 From 55ec45c2ced1a4b1e7cd2e7e306101f328958760 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Tue, 15 Dec 2015 16:25:08 +0200 Subject: drm/i915: Detect and clear unclaimed access on resume If something, the usual suspect being bios, access hw behind our back, don't let it slide into situation where normal register access will detect this and spit out a warn on into dmesg. On some bdw bioses this happens during igt/bat run always and as there is not much we can do about it, its better just to detect and flush this explicitly on resume and only print a debug message. v2: use DRM_DEBUG_DRIVER (Chris) v3: s/access/mmio, s/prior/prior to, s/dev/dev_priv Testcase: igt/pm_rpm/basic-rte Cc: Chris Wilson Cc: Paulo Zanoni Cc: Daniel Vetter Reviewed-by: Chris Wilson [Mika: fixed merge conflict] Signed-off-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1450189512-30360-3-git-send-email-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3ac616d7363b..288fec7691dc 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1501,6 +1501,10 @@ static int intel_runtime_suspend(struct device *device) enable_rpm_wakeref_asserts(dev_priv); WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count)); + + if (intel_uncore_unclaimed_mmio(dev_priv)) + DRM_ERROR("Unclaimed access detected prior to suspending\n"); + dev_priv->pm.suspended = true; /* @@ -1549,6 +1553,8 @@ static int intel_runtime_resume(struct device *device) intel_opregion_notify_adapter(dev, PCI_D0); dev_priv->pm.suspended = false; + if (intel_uncore_unclaimed_mmio(dev_priv)) + DRM_DEBUG_DRIVER("Unclaimed access during suspend, bios?\n"); intel_guc_resume(dev); -- cgit v1.2.3 From 7571494004d88249bcee2a20fa74cb50753676fe Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Wed, 16 Dec 2015 09:26:48 +0200 Subject: drm/i915: Do one shot unclaimed mmio detection less frequently We have done unclaimed register access check in normal (mmio_debug=0) mode once per write. This adds probability of finding the exact sequence where we did the bad access, but also adds burden to each write. As we have mmio_debug available for more fine grained analysis, give up accuracy of detecting correct spot at the first occurrence by doing the one shot detection and arming of mmio_debug in hangcheck and in modeset. This removes the write path performance burden. v2: Remove gratuitous DRM_DEBUG and return value, comments (Chris) Cc: Chris Wilson Cc: Paulo Zanoni Reviewed-by: Chris Wilson Signed-off-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1450250808-14864-1-git-send-email-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 3 +++ drivers/gpu/drm/i915/i915_irq.c | 11 ++++++----- drivers/gpu/drm/i915/intel_display.c | 13 +++++++++++++ drivers/gpu/drm/i915/intel_uncore.c | 37 ++++++++++++++++++------------------ 4 files changed, 40 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index aa32e8872a95..6ef03eea3518 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -718,6 +718,8 @@ struct intel_uncore { i915_reg_t reg_post; u32 val_reset; } fw_domain[FW_DOMAIN_ID_COUNT]; + + int unclaimed_mmio_check; }; /* Iterate over initialised fw domains */ @@ -2718,6 +2720,7 @@ extern void intel_uncore_early_sanitize(struct drm_device *dev, bool restore_forcewake); extern void intel_uncore_init(struct drm_device *dev); extern bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv); +extern void intel_uncore_arm_unclaimed_mmio_detection(struct drm_i915_private *dev_priv); extern void intel_uncore_fini(struct drm_device *dev); extern void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore); const char *intel_uncore_forcewake_domain_to_str(const enum forcewake_domain_id id); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index e7e44a972905..f04d799153ca 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2188,11 +2188,6 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) /* IRQs are synced during runtime_suspend, we don't require a wakeref */ disable_rpm_wakeref_asserts(dev_priv); - /* We get interrupts on unclaimed registers, so check for this before we - * do any I915_{READ,WRITE}. */ - if (intel_uncore_unclaimed_mmio(dev_priv)) - DRM_ERROR("Unclaimed register before interrupt\n"); - /* disable master interrupt before clearing iir */ de_ier = I915_READ(DEIER); I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); @@ -3081,6 +3076,12 @@ static void i915_hangcheck_elapsed(struct work_struct *work) */ DISABLE_RPM_WAKEREF_ASSERTS(dev_priv); + /* As enabling the GPU requires fairly extensive mmio access, + * periodically arm the mmio checker to see if we are triggering + * any invalid access. + */ + intel_uncore_arm_unclaimed_mmio_detection(dev_priv); + for_each_ring(ring, dev_priv, i) { u64 acthd; u32 seqno; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 738d0dca47a8..3edf22ad7673 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13684,6 +13684,19 @@ static int intel_atomic_commit(struct drm_device *dev, drm_atomic_state_free(state); + /* As one of the primary mmio accessors, KMS has a high likelihood + * of triggering bugs in unclaimed access. After we finish + * modesetting, see if an error has been flagged, and if so + * enable debugging for the next modeset - and hope we catch + * the culprit. + * + * XXX note that we assume display power is on at this point. + * This might hold true now but we need to add pm helper to check + * unclaimed only when the hardware is on, as atomic commits + * can happen also when the device is completely off. + */ + intel_uncore_arm_unclaimed_mmio_detection(dev_priv); + return 0; } diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 7ab5916f90dd..c7af339a6366 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -619,22 +619,6 @@ hsw_unclaimed_reg_debug(struct drm_i915_private *dev_priv, } } -static void -hsw_unclaimed_reg_detect(struct drm_i915_private *dev_priv) -{ - static bool mmio_debug_once = true; - - if (i915.mmio_debug || !mmio_debug_once) - return; - - if (check_for_unclaimed_mmio(dev_priv)) { - DRM_DEBUG("Unclaimed register detected, " - "enabling oneshot unclaimed register reporting. " - "Please use i915.mmio_debug=N for more information.\n"); - i915.mmio_debug = mmio_debug_once--; - } -} - #define GEN2_READ_HEADER(x) \ u##x val = 0; \ assert_rpm_wakelock_held(dev_priv); @@ -914,7 +898,6 @@ hsw_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool t gen6_gt_check_fifodbg(dev_priv); \ } \ hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \ - hsw_unclaimed_reg_detect(dev_priv); \ GEN6_WRITE_FOOTER; \ } @@ -949,7 +932,6 @@ gen8_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool __force_wake_get(dev_priv, FORCEWAKE_RENDER); \ __raw_i915_write##x(dev_priv, reg, val); \ hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \ - hsw_unclaimed_reg_detect(dev_priv); \ GEN6_WRITE_FOOTER; \ } @@ -1019,7 +1001,6 @@ gen9_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, \ __force_wake_get(dev_priv, fw_engine); \ __raw_i915_write##x(dev_priv, reg, val); \ hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \ - hsw_unclaimed_reg_detect(dev_priv); \ GEN6_WRITE_FOOTER; \ } @@ -1239,6 +1220,8 @@ void intel_uncore_init(struct drm_device *dev) intel_uncore_fw_domains_init(dev); __intel_uncore_early_sanitize(dev, false); + dev_priv->uncore.unclaimed_mmio_check = 1; + switch (INTEL_INFO(dev)->gen) { default: case 9: @@ -1600,3 +1583,19 @@ bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv) { return check_for_unclaimed_mmio(dev_priv); } + +void +intel_uncore_arm_unclaimed_mmio_detection(struct drm_i915_private *dev_priv) +{ + if (unlikely(i915.mmio_debug || + dev_priv->uncore.unclaimed_mmio_check <= 0)) + return; + + if (unlikely(intel_uncore_unclaimed_mmio(dev_priv))) { + DRM_DEBUG("Unclaimed register detected, " + "enabling oneshot unclaimed register reporting. " + "Please use i915.mmio_debug=N for more information.\n"); + i915.mmio_debug++; + dev_priv->uncore.unclaimed_mmio_check--; + } +} -- cgit v1.2.3 From 4bd0a25d9be2963a15e16126022214e88580103f Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Tue, 15 Dec 2015 16:25:10 +0200 Subject: drm/i915: Streamline unclaimed reg debug trace Remove char* assignments and add branching hint and also constify the parameters. This results in a 35 bytes shorter fast path, so author boldly assumes it helps without doing in-depth assembly analysis. v2: use WARN's branching (Chris), commit name (Joonas) Cc: Joonas Lahtinen Cc: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1450189512-30360-5-git-send-email-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/intel_uncore.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index c7af339a6366..bd0933cefe5d 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -604,19 +604,19 @@ ilk_dummy_write(struct drm_i915_private *dev_priv) static void hsw_unclaimed_reg_debug(struct drm_i915_private *dev_priv, - i915_reg_t reg, bool read, bool before) + const i915_reg_t reg, + const bool read, + const bool before) { - const char *op = read ? "reading" : "writing to"; - const char *when = before ? "before" : "after"; - - if (!i915.mmio_debug) + if (likely(!i915.mmio_debug)) return; - if (check_for_unclaimed_mmio(dev_priv)) { - WARN(1, "Unclaimed register detected %s %s register 0x%x\n", - when, op, i915_mmio_reg_offset(reg)); + if (WARN(check_for_unclaimed_mmio(dev_priv), + "Unclaimed register detected %s %s register 0x%x\n", + before ? "before" : "after", + read ? "reading" : "writing to", + i915_mmio_reg_offset(reg))) i915.mmio_debug--; /* Only report the first N failures */ - } } #define GEN2_READ_HEADER(x) \ -- cgit v1.2.3 From 8ac3e1bb76cc2e1585be3a5fa7551480e69487c8 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Tue, 15 Dec 2015 19:45:42 +0200 Subject: drm/i915: Add non claimed mmio checking for vlv/chv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Imre mentioned that chv might also have capability to track unclaimed mmio accesses. Ville added that both chv and vlv has this capability and he had already made this way back [1]. Mimic what Ville's patch does but adapt on top of less frequent mmio accesses by omitting checking always on reg writes. This patch is untested as of now. v2: overflow handling and posting omitted (Ville) References: [1] http://lists.freedesktop.org/archives/intel-gfx/2013-May/027599.html Cc: Imre Deak Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1450201542-22918-1-git-send-email-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 5 +++++ drivers/gpu/drm/i915/intel_uncore.c | 31 +++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 7510d508e373..556a458d669e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1711,6 +1711,11 @@ enum skl_disp_power_wells { #define FPGA_DBG _MMIO(0x42300) #define FPGA_DBG_RM_NOCLAIM (1<<31) +#define CLAIM_ER _MMIO(VLV_DISPLAY_BASE + 0x2028) +#define CLAIM_ER_CLR (1 << 31) +#define CLAIM_ER_OVERFLOW (1 << 16) +#define CLAIM_ER_CTR_MASK 0xffff + #define DERRMR _MMIO(0x44050) /* Note that HBLANK events are reserved on bdw+ */ #define DERRMR_PIPEA_SCANLINE (1<<0) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index bd0933cefe5d..d0973e08e7eb 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -328,13 +328,10 @@ static void intel_uncore_ellc_detect(struct drm_device *dev) } static bool -check_for_unclaimed_mmio(struct drm_i915_private *dev_priv) +fpga_check_for_unclaimed_mmio(struct drm_i915_private *dev_priv) { u32 dbg; - if (!HAS_FPGA_DBG_UNCLAIMED(dev_priv)) - return false; - dbg = __raw_i915_read32(dev_priv, FPGA_DBG); if (likely(!(dbg & FPGA_DBG_RM_NOCLAIM))) return false; @@ -344,6 +341,32 @@ check_for_unclaimed_mmio(struct drm_i915_private *dev_priv) return true; } +static bool +vlv_check_for_unclaimed_mmio(struct drm_i915_private *dev_priv) +{ + u32 cer; + + cer = __raw_i915_read32(dev_priv, CLAIM_ER); + if (likely(!(cer & (CLAIM_ER_OVERFLOW | CLAIM_ER_CTR_MASK)))) + return false; + + __raw_i915_write32(dev_priv, CLAIM_ER, CLAIM_ER_CLR); + + return true; +} + +static bool +check_for_unclaimed_mmio(struct drm_i915_private *dev_priv) +{ + if (HAS_FPGA_DBG_UNCLAIMED(dev_priv)) + return fpga_check_for_unclaimed_mmio(dev_priv); + + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + return vlv_check_for_unclaimed_mmio(dev_priv); + + return false; +} + static void __intel_uncore_early_sanitize(struct drm_device *dev, bool restore_forcewake) { -- cgit v1.2.3 From d7d85d85c8b60e74df5129f147de29bc21228421 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Jan 2016 12:45:39 +0200 Subject: drm/i915/dsi: abstract get pclk platform differences MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hide away the platform differences in intel_dsi_get_pckl() within intel_dsi_pll.c. No functional changes. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1452249940-2605-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi.c | 9 ++------- drivers/gpu/drm/i915/intel_dsi.h | 3 +-- drivers/gpu/drm/i915/intel_dsi_pll.c | 12 ++++++++++-- 3 files changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 4ab168dd36bf..328cd58cb5fe 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -702,7 +702,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, static void intel_dsi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { - u32 pclk = 0; + u32 pclk; DRM_DEBUG_KMS("\n"); pipe_config->has_dsi_encoder = true; @@ -713,12 +713,7 @@ static void intel_dsi_get_config(struct intel_encoder *encoder, */ pipe_config->dpll_hw_state.dpll_md = 0; - if (IS_BROXTON(encoder->base.dev)) - pclk = bxt_get_dsi_pclk(encoder, pipe_config->pipe_bpp); - else if (IS_VALLEYVIEW(encoder->base.dev) || - IS_CHERRYVIEW(encoder->base.dev)) - pclk = vlv_get_dsi_pclk(encoder, pipe_config->pipe_bpp); - + pclk = intel_dsi_get_pclk(encoder, pipe_config->pipe_bpp); if (!pclk) return; diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 02551ff228c2..de7be7f3fb42 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -126,8 +126,7 @@ static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder) extern void intel_enable_dsi_pll(struct intel_encoder *encoder); extern void intel_disable_dsi_pll(struct intel_encoder *encoder); -extern u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp); -extern u32 bxt_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp); +extern u32 intel_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp); extern void intel_dsi_reset_clocks(struct intel_encoder *encoder, enum port port); diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index fbd2b51810ca..4c5bb7dd95a2 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -322,7 +322,7 @@ static void assert_bpp_mismatch(int pixel_format, int pipe_bpp) bpp, pipe_bpp); } -u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp) +static u32 vlv_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); @@ -384,7 +384,7 @@ u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp) return pclk; } -u32 bxt_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp) +static u32 bxt_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp) { u32 pclk; u32 dsi_clk; @@ -419,6 +419,14 @@ u32 bxt_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp) return pclk; } +u32 intel_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp) +{ + if (IS_BROXTON(encoder->base.dev)) + return bxt_dsi_get_pclk(encoder, pipe_bpp); + else + return vlv_dsi_get_pclk(encoder, pipe_bpp); +} + static void vlv_dsi_reset_clocks(struct intel_encoder *encoder, enum port port) { u32 temp; -- cgit v1.2.3 From b5c0bbc4fe1acf7843639597ecdea59bc0037e9e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Jan 2016 12:45:40 +0200 Subject: drm/i915/dsi: remove unused dsi_rr_formula() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dsi_rr_formula() function has been unused for almost two years, since commit 44d4c6eebb2ef04f698c292bb6eda5f2e80c663b Author: Shobhit Kumar Date: Tue Dec 10 12:14:56 2013 +0530 drm/i915: Compute dsi_clk from pixel clock citing the reason as pixel clock based calculation being recommended in the MIPI host controller documentation. Remove the dead code, we can always bring it back if it's needed. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1452249940-2605-2-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_pll.c | 81 ------------------------------------ 1 file changed, 81 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index 4c5bb7dd95a2..bb5e95a1a453 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -30,14 +30,6 @@ #include "i915_drv.h" #include "intel_dsi.h" -#define DSI_HSS_PACKET_SIZE 4 -#define DSI_HSE_PACKET_SIZE 4 -#define DSI_HSA_PACKET_EXTRA_SIZE 6 -#define DSI_HBP_PACKET_EXTRA_SIZE 6 -#define DSI_HACTIVE_PACKET_EXTRA_SIZE 6 -#define DSI_HFP_PACKET_EXTRA_SIZE 6 -#define DSI_EOTP_PACKET_SIZE 4 - static int dsi_pixel_format_bpp(int pixel_format) { int bpp; @@ -71,77 +63,6 @@ static const u32 lfsr_converts[] = { 71, 35, 273, 136, 324, 418, 465, 488, 500, 506 /* 91 - 100 */ }; -#ifdef DSI_CLK_FROM_RR - -static u32 dsi_rr_formula(const struct drm_display_mode *mode, - int pixel_format, int video_mode_format, - int lane_count, bool eotp) -{ - u32 bpp; - u32 hactive, vactive, hfp, hsync, hbp, vfp, vsync, vbp; - u32 hsync_bytes, hbp_bytes, hactive_bytes, hfp_bytes; - u32 bytes_per_line, bytes_per_frame; - u32 num_frames; - u32 bytes_per_x_frames, bytes_per_x_frames_x_lanes; - u32 dsi_bit_clock_hz; - u32 dsi_clk; - - bpp = dsi_pixel_format_bpp(pixel_format); - - hactive = mode->hdisplay; - vactive = mode->vdisplay; - hfp = mode->hsync_start - mode->hdisplay; - hsync = mode->hsync_end - mode->hsync_start; - hbp = mode->htotal - mode->hsync_end; - - vfp = mode->vsync_start - mode->vdisplay; - vsync = mode->vsync_end - mode->vsync_start; - vbp = mode->vtotal - mode->vsync_end; - - hsync_bytes = DIV_ROUND_UP(hsync * bpp, 8); - hbp_bytes = DIV_ROUND_UP(hbp * bpp, 8); - hactive_bytes = DIV_ROUND_UP(hactive * bpp, 8); - hfp_bytes = DIV_ROUND_UP(hfp * bpp, 8); - - bytes_per_line = DSI_HSS_PACKET_SIZE + hsync_bytes + - DSI_HSA_PACKET_EXTRA_SIZE + DSI_HSE_PACKET_SIZE + - hbp_bytes + DSI_HBP_PACKET_EXTRA_SIZE + - hactive_bytes + DSI_HACTIVE_PACKET_EXTRA_SIZE + - hfp_bytes + DSI_HFP_PACKET_EXTRA_SIZE; - - /* - * XXX: Need to accurately calculate LP to HS transition timeout and add - * it to bytes_per_line/bytes_per_frame. - */ - - if (eotp && video_mode_format == VIDEO_MODE_BURST) - bytes_per_line += DSI_EOTP_PACKET_SIZE; - - bytes_per_frame = vsync * bytes_per_line + vbp * bytes_per_line + - vactive * bytes_per_line + vfp * bytes_per_line; - - if (eotp && - (video_mode_format == VIDEO_MODE_NON_BURST_WITH_SYNC_PULSE || - video_mode_format == VIDEO_MODE_NON_BURST_WITH_SYNC_EVENTS)) - bytes_per_frame += DSI_EOTP_PACKET_SIZE; - - num_frames = drm_mode_vrefresh(mode); - bytes_per_x_frames = num_frames * bytes_per_frame; - - bytes_per_x_frames_x_lanes = bytes_per_x_frames / lane_count; - - /* the dsi clock is divided by 2 in the hardware to get dsi ddr clock */ - dsi_bit_clock_hz = bytes_per_x_frames_x_lanes * 8; - dsi_clk = dsi_bit_clock_hz / 1000; - - if (eotp && video_mode_format == VIDEO_MODE_BURST) - dsi_clk *= 2; - - return dsi_clk; -} - -#else - /* Get DSI clock from pixel clock */ static u32 dsi_clk_from_pclk(u32 pclk, int pixel_format, int lane_count) { @@ -155,8 +76,6 @@ static u32 dsi_clk_from_pclk(u32 pclk, int pixel_format, int lane_count) return dsi_clk_khz; } -#endif - static int dsi_calc_mnp(struct drm_i915_private *dev_priv, struct dsi_mnp *dsi_mnp, int target_dsi_clk) { -- cgit v1.2.3 From 8d7a1c4a579c4ecfe360044c24dc1fbf97096752 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 7 Jan 2016 16:49:39 -0800 Subject: drm/i915/kbl: Adding missing IS_KABYLAKE checks. When adding IS_KABYLAKE definition I didn't included the DC states related because I was planing to include them with the patch that fixes DMC firmware loading, but I forgot them. Meanwhile this runtime pm code changed a lot for Skylake. Well, I didn't expect that this would crash the machine and I just noticed now that Sarah warned me our driver wasn't working. Thanks Sarah. Michel had found the main error first and his fix had better details on the history and got merged already: commit 16fbc291cb87c7defcd13ad715d3e4af0d523e43 Author: Michel Thierry Date: Wed Jan 6 12:08:36 2016 +0000 drm/i915/kbl: Enable PW1 and Misc I/O power wells This one is a follow-up adding the other remaining missing pieces. v2: Rebased on top of Michel's patch as explained above. Cc: Sarah Sharp Signed-off-by: Rodrigo Vivi Reviewed-by: Michel Thierry Link: http://patchwork.freedesktop.org/patch/msgid/1452214179-22361-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_csr.c | 5 +++-- drivers/gpu/drm/i915/intel_runtime_pm.c | 15 ++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 9bb63a85997a..3f2850029c17 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -278,7 +278,8 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, csr->version = css_header->version; - if (IS_SKYLAKE(dev) && csr->version < SKL_CSR_VERSION_REQUIRED) { + if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) && + csr->version < SKL_CSR_VERSION_REQUIRED) { DRM_INFO("Refusing to load old Skylake DMC firmware v%u.%u," " please upgrade to v%u.%u or later" " [https://01.org/linuxgraphics/intel-linux-graphics-firmwares].\n", @@ -421,7 +422,7 @@ void intel_csr_ucode_init(struct drm_i915_private *dev_priv) if (!HAS_CSR(dev_priv)) return; - if (IS_SKYLAKE(dev_priv)) + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) csr->fw_path = I915_CSR_SKL; else if (IS_BROXTON(dev_priv)) csr->fw_path = I915_CSR_BXT; diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 4b44e6862a27..89a7dd83e91f 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -532,7 +532,8 @@ static void assert_can_enable_dc5(struct drm_i915_private *dev_priv) bool pg2_enabled = intel_display_power_well_is_enabled(dev_priv, SKL_DISP_PW_2); - WARN_ONCE(!IS_SKYLAKE(dev), "Platform doesn't support DC5.\n"); + WARN_ONCE(!IS_SKYLAKE(dev) && !IS_KABYLAKE(dev), + "Platform doesn't support DC5.\n"); WARN_ONCE(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n"); WARN_ONCE(pg2_enabled, "PG2 not disabled to enable DC5.\n"); @@ -568,7 +569,8 @@ static void assert_can_enable_dc6(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; - WARN_ONCE(!IS_SKYLAKE(dev), "Platform doesn't support DC6.\n"); + WARN_ONCE(!IS_SKYLAKE(dev) && !IS_KABYLAKE(dev), + "Platform doesn't support DC6.\n"); WARN_ONCE(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n"); WARN_ONCE(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE, "Backlight is not disabled.\n"); @@ -595,7 +597,8 @@ static void gen9_disable_dc5_dc6(struct drm_i915_private *dev_priv) { assert_can_disable_dc5(dev_priv); - if (IS_SKYLAKE(dev_priv) && i915.enable_dc != 0 && i915.enable_dc != 1) + if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && + i915.enable_dc != 0 && i915.enable_dc != 1) assert_can_disable_dc6(dev_priv); gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); @@ -783,7 +786,8 @@ static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv, static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - if (IS_SKYLAKE(dev_priv) && i915.enable_dc != 0 && i915.enable_dc != 1) + if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && + i915.enable_dc != 0 && i915.enable_dc != 1) skl_enable_dc6(dev_priv); else gen9_enable_dc5(dev_priv); @@ -795,7 +799,8 @@ static void gen9_dc_off_power_well_sync_hw(struct drm_i915_private *dev_priv, if (power_well->count > 0) { gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); } else { - if (IS_SKYLAKE(dev_priv) && i915.enable_dc != 0 && + if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && + i915.enable_dc != 0 && i915.enable_dc != 1) gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6); else -- cgit v1.2.3 From cd7feaaad68edd12959843ccee9ecfcf05ecdbfe Mon Sep 17 00:00:00 2001 From: "Boyer, Wayne" Date: Wed, 6 Jan 2016 17:15:29 -0800 Subject: drm/i915: Don't warn if the workaround list is empty part 2. Extend the same reasoning as in the patch listed below. It's not an error for the workaround list to be empty if no workarounds are needed. commit 02235808b61cd9382d224b0df263193006dd9913 Author: Francisco Jerez Date: Wed Oct 7 14:44:01 2015 +0300 drm/i915: Don't warn if the workaround list is empty. Signed-off-by: Wayne Boyer Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1452129330-3484-2-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_lrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 23839ff04e27..f7fac5f3b5ce 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1116,7 +1116,7 @@ static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req) struct drm_i915_private *dev_priv = dev->dev_private; struct i915_workarounds *w = &dev_priv->workarounds; - if (WARN_ON_ONCE(w->count == 0)) + if (w->count == 0) return 0; ring->gpu_caches_dirty = true; -- cgit v1.2.3 From 97a249e98a72d6b79fb7350a8dd56b147e9d5bdb Mon Sep 17 00:00:00 2001 From: Yong Li Date: Wed, 6 Jan 2016 09:09:43 +0800 Subject: iio: dac: mcp4725: set iio name property in sysfs Without this change, the name entity for mcp4725 is missing in /sys/bus/iio/devices/iio\:device*/name With this change, name is reported correctly Signed-off-by: Yong Li Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/dac/mcp4725.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index 43d14588448d..b4dde8315210 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -300,6 +300,7 @@ static int mcp4725_probe(struct i2c_client *client, data->client = client; indio_dev->dev.parent = &client->dev; + indio_dev->name = id->name; indio_dev->info = &mcp4725_info; indio_dev->channels = &mcp4725_channel; indio_dev->num_channels = 1; -- cgit v1.2.3 From a9fd053b56c6bb14972ab7a19da0b575fe4c5d66 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 19 Nov 2015 10:15:17 +0100 Subject: iio: st_sensors: support active-low interrupts Most ST MEMS Sensors that support interrupts can also handle sending an active low interrupt, i.e. going from high to low on data ready (or other interrupt) and thus triggering on a falling edge to the interrupt controller. Set up logic to inspect the interrupt line we get for a sensor: if it is triggering on rising edge, leave everything alone, but if it triggers on falling edges, set up active low, and if unsupported configurations appear: warn with errors and reconfigure the interrupt to a rising edge, which all interrupt generating sensors support. Create a local header for st_sensors_core.h to share functions between the sensor core and the trigger setup code. Cc: Giuseppe Barba Cc: Denis Ciocca Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_core.c | 16 +++++++ drivers/iio/common/st_sensors/st_sensors_core.c | 6 ++- drivers/iio/common/st_sensors/st_sensors_core.h | 8 ++++ drivers/iio/common/st_sensors/st_sensors_trigger.c | 52 +++++++++++++++++----- drivers/iio/gyro/st_gyro_core.c | 15 +++++++ drivers/iio/magnetometer/st_magn_core.c | 4 ++ drivers/iio/pressure/st_pressure_core.c | 8 ++++ include/linux/iio/common/st_sensors.h | 4 ++ 8 files changed, 101 insertions(+), 12 deletions(-) create mode 100644 drivers/iio/common/st_sensors/st_sensors_core.h (limited to 'drivers') diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 70f042797f15..a03a1417dd63 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -67,6 +67,8 @@ #define ST_ACCEL_1_DRDY_IRQ_ADDR 0x22 #define ST_ACCEL_1_DRDY_IRQ_INT1_MASK 0x10 #define ST_ACCEL_1_DRDY_IRQ_INT2_MASK 0x08 +#define ST_ACCEL_1_IHL_IRQ_ADDR 0x25 +#define ST_ACCEL_1_IHL_IRQ_MASK 0x02 #define ST_ACCEL_1_MULTIREAD_BIT true /* CUSTOM VALUES FOR SENSOR 2 */ @@ -92,6 +94,8 @@ #define ST_ACCEL_2_DRDY_IRQ_ADDR 0x22 #define ST_ACCEL_2_DRDY_IRQ_INT1_MASK 0x02 #define ST_ACCEL_2_DRDY_IRQ_INT2_MASK 0x10 +#define ST_ACCEL_2_IHL_IRQ_ADDR 0x22 +#define ST_ACCEL_2_IHL_IRQ_MASK 0x80 #define ST_ACCEL_2_MULTIREAD_BIT true /* CUSTOM VALUES FOR SENSOR 3 */ @@ -125,6 +129,8 @@ #define ST_ACCEL_3_DRDY_IRQ_ADDR 0x23 #define ST_ACCEL_3_DRDY_IRQ_INT1_MASK 0x80 #define ST_ACCEL_3_DRDY_IRQ_INT2_MASK 0x00 +#define ST_ACCEL_3_IHL_IRQ_ADDR 0x23 +#define ST_ACCEL_3_IHL_IRQ_MASK 0x40 #define ST_ACCEL_3_IG1_EN_ADDR 0x23 #define ST_ACCEL_3_IG1_EN_MASK 0x08 #define ST_ACCEL_3_MULTIREAD_BIT false @@ -169,6 +175,8 @@ #define ST_ACCEL_5_DRDY_IRQ_ADDR 0x22 #define ST_ACCEL_5_DRDY_IRQ_INT1_MASK 0x04 #define ST_ACCEL_5_DRDY_IRQ_INT2_MASK 0x20 +#define ST_ACCEL_5_IHL_IRQ_ADDR 0x22 +#define ST_ACCEL_5_IHL_IRQ_MASK 0x80 #define ST_ACCEL_5_IG1_EN_ADDR 0x21 #define ST_ACCEL_5_IG1_EN_MASK 0x08 #define ST_ACCEL_5_MULTIREAD_BIT false @@ -292,6 +300,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .addr = ST_ACCEL_1_DRDY_IRQ_ADDR, .mask_int1 = ST_ACCEL_1_DRDY_IRQ_INT1_MASK, .mask_int2 = ST_ACCEL_1_DRDY_IRQ_INT2_MASK, + .addr_ihl = ST_ACCEL_1_IHL_IRQ_ADDR, + .mask_ihl = ST_ACCEL_1_IHL_IRQ_MASK, }, .multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT, .bootime = 2, @@ -355,6 +365,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .addr = ST_ACCEL_2_DRDY_IRQ_ADDR, .mask_int1 = ST_ACCEL_2_DRDY_IRQ_INT1_MASK, .mask_int2 = ST_ACCEL_2_DRDY_IRQ_INT2_MASK, + .addr_ihl = ST_ACCEL_2_IHL_IRQ_ADDR, + .mask_ihl = ST_ACCEL_2_IHL_IRQ_MASK, }, .multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT, .bootime = 2, @@ -430,6 +442,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .addr = ST_ACCEL_3_DRDY_IRQ_ADDR, .mask_int1 = ST_ACCEL_3_DRDY_IRQ_INT1_MASK, .mask_int2 = ST_ACCEL_3_DRDY_IRQ_INT2_MASK, + .addr_ihl = ST_ACCEL_3_IHL_IRQ_ADDR, + .mask_ihl = ST_ACCEL_3_IHL_IRQ_MASK, .ig1 = { .en_addr = ST_ACCEL_3_IG1_EN_ADDR, .en_mask = ST_ACCEL_3_IG1_EN_MASK, @@ -537,6 +551,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .addr = ST_ACCEL_5_DRDY_IRQ_ADDR, .mask_int1 = ST_ACCEL_5_DRDY_IRQ_INT1_MASK, .mask_int2 = ST_ACCEL_5_DRDY_IRQ_INT2_MASK, + .addr_ihl = ST_ACCEL_5_IHL_IRQ_ADDR, + .mask_ihl = ST_ACCEL_5_IHL_IRQ_MASK, }, .multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT, .bootime = 2, /* guess */ diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 8447c31e27f2..f5a2d445d0c0 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -18,13 +18,15 @@ #include #include +#include "st_sensors_core.h" + static inline u32 st_sensors_get_unaligned_le24(const u8 *p) { return (s32)((p[0] | p[1] << 8 | p[2] << 16) << 8) >> 8; } -static int st_sensors_write_data_with_mask(struct iio_dev *indio_dev, - u8 reg_addr, u8 mask, u8 data) +int st_sensors_write_data_with_mask(struct iio_dev *indio_dev, + u8 reg_addr, u8 mask, u8 data) { int err; u8 new_data; diff --git a/drivers/iio/common/st_sensors/st_sensors_core.h b/drivers/iio/common/st_sensors/st_sensors_core.h new file mode 100644 index 000000000000..cd88098ff6f1 --- /dev/null +++ b/drivers/iio/common/st_sensors/st_sensors_core.h @@ -0,0 +1,8 @@ +/* + * Local functions in the ST Sensors core + */ +#ifndef __ST_SENSORS_CORE_H +#define __ST_SENSORS_CORE_H +int st_sensors_write_data_with_mask(struct iio_dev *indio_dev, + u8 reg_addr, u8 mask, u8 data); +#endif diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c index 3e907040c2c7..6a8c98327945 100644 --- a/drivers/iio/common/st_sensors/st_sensors_trigger.c +++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c @@ -14,32 +14,65 @@ #include #include #include - #include - +#include "st_sensors_core.h" int st_sensors_allocate_trigger(struct iio_dev *indio_dev, const struct iio_trigger_ops *trigger_ops) { - int err; + int err, irq; struct st_sensor_data *sdata = iio_priv(indio_dev); + unsigned long irq_trig; sdata->trig = iio_trigger_alloc("%s-trigger", indio_dev->name); if (sdata->trig == NULL) { - err = -ENOMEM; dev_err(&indio_dev->dev, "failed to allocate iio trigger.\n"); - goto iio_trigger_alloc_error; + return -ENOMEM; } - err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev), + irq = sdata->get_irq_data_ready(indio_dev); + irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq)); + /* + * If the IRQ is triggered on falling edge, we need to mark the + * interrupt as active low, if the hardware supports this. + */ + if (irq_trig == IRQF_TRIGGER_FALLING) { + if (!sdata->sensor_settings->drdy_irq.addr_ihl) { + dev_err(&indio_dev->dev, + "falling edge specified for IRQ but hardware " + "only support rising edge, will request " + "rising edge\n"); + irq_trig = IRQF_TRIGGER_RISING; + } else { + /* Set up INT active low i.e. falling edge */ + err = st_sensors_write_data_with_mask(indio_dev, + sdata->sensor_settings->drdy_irq.addr_ihl, + sdata->sensor_settings->drdy_irq.mask_ihl, 1); + if (err < 0) + goto iio_trigger_free; + dev_info(&indio_dev->dev, + "interrupts on the falling edge\n"); + } + } else if (irq_trig == IRQF_TRIGGER_RISING) { + dev_info(&indio_dev->dev, + "interrupts on the rising edge\n"); + + } else { + dev_err(&indio_dev->dev, + "unsupported IRQ trigger specified (%lx), only " + "rising and falling edges supported, enforce " + "rising edge\n", irq_trig); + irq_trig = IRQF_TRIGGER_RISING; + } + err = request_threaded_irq(irq, iio_trigger_generic_data_rdy_poll, NULL, - IRQF_TRIGGER_RISING, + irq_trig, sdata->trig->name, sdata->trig); if (err) { dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n"); - goto request_irq_error; + goto iio_trigger_free; } iio_trigger_set_drvdata(sdata->trig, indio_dev); @@ -57,9 +90,8 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, iio_trigger_register_error: free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig); -request_irq_error: +iio_trigger_free: iio_trigger_free(sdata->trig); -iio_trigger_alloc_error: return err; } EXPORT_SYMBOL(st_sensors_allocate_trigger); diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index 02eddcebeea3..110f95b6e52f 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -185,6 +185,11 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { .drdy_irq = { .addr = ST_GYRO_1_DRDY_IRQ_ADDR, .mask_int2 = ST_GYRO_1_DRDY_IRQ_INT2_MASK, + /* + * The sensor has IHL (active low) and open + * drain settings, but only for INT1 and not + * for the DRDY line on INT2. + */ }, .multi_read_bit = ST_GYRO_1_MULTIREAD_BIT, .bootime = 2, @@ -248,6 +253,11 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { .drdy_irq = { .addr = ST_GYRO_2_DRDY_IRQ_ADDR, .mask_int2 = ST_GYRO_2_DRDY_IRQ_INT2_MASK, + /* + * The sensor has IHL (active low) and open + * drain settings, but only for INT1 and not + * for the DRDY line on INT2. + */ }, .multi_read_bit = ST_GYRO_2_MULTIREAD_BIT, .bootime = 2, @@ -307,6 +317,11 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { .drdy_irq = { .addr = ST_GYRO_3_DRDY_IRQ_ADDR, .mask_int2 = ST_GYRO_3_DRDY_IRQ_INT2_MASK, + /* + * The sensor has IHL (active low) and open + * drain settings, but only for INT1 and not + * for the DRDY line on INT2. + */ }, .multi_read_bit = ST_GYRO_3_MULTIREAD_BIT, .bootime = 2, diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index b27f0146647b..501f858df413 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c @@ -175,6 +175,8 @@ #define ST_MAGN_3_BDU_MASK 0x10 #define ST_MAGN_3_DRDY_IRQ_ADDR 0x62 #define ST_MAGN_3_DRDY_INT_MASK 0x01 +#define ST_MAGN_3_IHL_IRQ_ADDR 0x63 +#define ST_MAGN_3_IHL_IRQ_MASK 0x04 #define ST_MAGN_3_FS_AVL_15000_GAIN 1500 #define ST_MAGN_3_MULTIREAD_BIT false #define ST_MAGN_3_OUT_X_L_ADDR 0x68 @@ -480,6 +482,8 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = { .drdy_irq = { .addr = ST_MAGN_3_DRDY_IRQ_ADDR, .mask_int1 = ST_MAGN_3_DRDY_INT_MASK, + .addr_ihl = ST_MAGN_3_IHL_IRQ_ADDR, + .mask_ihl = ST_MAGN_3_IHL_IRQ_MASK, }, .multi_read_bit = ST_MAGN_3_MULTIREAD_BIT, .bootime = 2, diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index b39a2fb0671c..172393ad34af 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -62,6 +62,8 @@ #define ST_PRESS_LPS331AP_DRDY_IRQ_ADDR 0x22 #define ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK 0x04 #define ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK 0x20 +#define ST_PRESS_LPS331AP_IHL_IRQ_ADDR 0x22 +#define ST_PRESS_LPS331AP_IHL_IRQ_MASK 0x80 #define ST_PRESS_LPS331AP_MULTIREAD_BIT true #define ST_PRESS_LPS331AP_TEMP_OFFSET 42500 @@ -100,6 +102,8 @@ #define ST_PRESS_LPS25H_DRDY_IRQ_ADDR 0x23 #define ST_PRESS_LPS25H_DRDY_IRQ_INT1_MASK 0x01 #define ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK 0x10 +#define ST_PRESS_LPS25H_IHL_IRQ_ADDR 0x22 +#define ST_PRESS_LPS25H_IHL_IRQ_MASK 0x80 #define ST_PRESS_LPS25H_MULTIREAD_BIT true #define ST_PRESS_LPS25H_TEMP_OFFSET 42500 #define ST_PRESS_LPS25H_OUT_XL_ADDR 0x28 @@ -220,6 +224,8 @@ static const struct st_sensor_settings st_press_sensors_settings[] = { .addr = ST_PRESS_LPS331AP_DRDY_IRQ_ADDR, .mask_int1 = ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK, .mask_int2 = ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK, + .addr_ihl = ST_PRESS_LPS331AP_IHL_IRQ_ADDR, + .mask_ihl = ST_PRESS_LPS331AP_IHL_IRQ_MASK, }, .multi_read_bit = ST_PRESS_LPS331AP_MULTIREAD_BIT, .bootime = 2, @@ -304,6 +310,8 @@ static const struct st_sensor_settings st_press_sensors_settings[] = { .addr = ST_PRESS_LPS25H_DRDY_IRQ_ADDR, .mask_int1 = ST_PRESS_LPS25H_DRDY_IRQ_INT1_MASK, .mask_int2 = ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK, + .addr_ihl = ST_PRESS_LPS25H_IHL_IRQ_ADDR, + .mask_ihl = ST_PRESS_LPS25H_IHL_IRQ_MASK, }, .multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT, .bootime = 2, diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 2fe939c73cd2..6670c3d25c58 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -119,6 +119,8 @@ struct st_sensor_bdu { * @addr: address of the register. * @mask_int1: mask to enable/disable IRQ on INT1 pin. * @mask_int2: mask to enable/disable IRQ on INT2 pin. + * @addr_ihl: address to enable/disable active low on the INT lines. + * @mask_ihl: mask to enable/disable active low on the INT lines. * struct ig1 - represents the Interrupt Generator 1 of sensors. * @en_addr: address of the enable ig1 register. * @en_mask: mask to write the on/off value for enable. @@ -127,6 +129,8 @@ struct st_sensor_data_ready_irq { u8 addr; u8 mask_int1; u8 mask_int2; + u8 addr_ihl; + u8 mask_ihl; struct { u8 en_addr; u8 en_mask; -- cgit v1.2.3 From f78c5f96547e6eaa894557730af3f66b8116c5c2 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 5 Jan 2016 15:56:42 +0100 Subject: iio: ak8975: constify ak_def structures The ak_def structures are never modified, so declare them as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8975.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index b13936dacc78..9c5c9ef3f1da 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -252,7 +252,7 @@ struct ak_def { u8 data_regs[3]; }; -static struct ak_def ak_def_array[AK_MAX_TYPE] = { +static const struct ak_def ak_def_array[AK_MAX_TYPE] = { { .type = AK8975, .raw_to_gauss = ak8975_raw_to_gauss, @@ -360,7 +360,7 @@ static struct ak_def ak_def_array[AK_MAX_TYPE] = { */ struct ak8975_data { struct i2c_client *client; - struct ak_def *def; + const struct ak_def *def; struct attribute_group attrs; struct mutex lock; u8 asa[3]; -- cgit v1.2.3 From db1a6aa2afa50803fbd801631bb9756eeff96dbe Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 00:04:02 +0100 Subject: drm/i915: Update DRIVER_DATE to 20160111 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6ef03eea3518..747d2d84a18c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -59,7 +59,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20151218" +#define DRIVER_DATE "20160111" #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */ -- cgit v1.2.3 From bcf8be279c79df6a8a17d9c3e1f9bc926444a87c Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 8 Dec 2015 15:52:56 +0100 Subject: drm/i915: Widen return value for reservation_object_wait_timeout_rcu to long. This fixes a spurious warning from an integer overflow on 64-bits systems. The function may return MAX_SCHEDULE_TIMEOUT which gets truncated to -1. Explicitly handling this by casting to lret fixes it. Signed-off-by: Maarten Lankhorst Reported-and-tested-by: Joseph Yasi Tested-by: Andreas Reis Reviewed-by: Daniel Vetter Cc: drm-intel-fixes@lists.freedesktop.org Fixes: 3c28ff22f6e20c ("i915: wait for fence in prepare_plane_fb") Link: http://patchwork.freedesktop.org/patch/msgid/5666EEC8.2000403@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3edf22ad7673..259f2ca57447 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13902,13 +13902,15 @@ intel_prepare_plane_fb(struct drm_plane *plane, /* For framebuffer backed by dmabuf, wait for fence */ if (obj && obj->base.dma_buf) { - ret = reservation_object_wait_timeout_rcu(obj->base.dma_buf->resv, - false, true, - MAX_SCHEDULE_TIMEOUT); - if (ret == -ERESTARTSYS) - return ret; + long lret; + + lret = reservation_object_wait_timeout_rcu(obj->base.dma_buf->resv, + false, true, + MAX_SCHEDULE_TIMEOUT); + if (lret == -ERESTARTSYS) + return lret; - WARN_ON(ret < 0); + WARN(lret < 0, "waiting returns %li\n", lret); } if (!obj) { -- cgit v1.2.3 From 9c053501b950cf4dcea3dbbcd42da65e376acce6 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Fri, 8 Jan 2016 15:51:19 +0200 Subject: drm/i915: Enable mmio_debug for vlv/chv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With commit 8ac3e1bb76cc ("drm/i915: Add non claimed mmio checking for vlv/chv") we now have chv/vlv support in place for detecting unclaimed access. Also the perf hit of extra mmio read is now only suffered if mmio_debug is set. This allows us to stuff the macro for unclaimed reg detection inside a generic gen6 register access, as now all gens using these macros uses also unclaimed debugs, the one exception being snb. We gain more clean and generic macros and only downside is that snb will suffer one branch perf hit without upside. Note that the hsw write path debug register check now happens before fifo check, but this should not make any real difference. As vlv/chv use the generic gen6 access macros, the consequence is that they gain the mmio_debug feature. Cc: Ville Syrjälä Cc: Chris Wilson Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1452261080-6979-1-git-send-email-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/intel_uncore.c | 41 ++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index d0973e08e7eb..0b47bc891dc7 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -626,14 +626,11 @@ ilk_dummy_write(struct drm_i915_private *dev_priv) } static void -hsw_unclaimed_reg_debug(struct drm_i915_private *dev_priv, - const i915_reg_t reg, - const bool read, - const bool before) +__unclaimed_reg_debug(struct drm_i915_private *dev_priv, + const i915_reg_t reg, + const bool read, + const bool before) { - if (likely(!i915.mmio_debug)) - return; - if (WARN(check_for_unclaimed_mmio(dev_priv), "Unclaimed register detected %s %s register 0x%x\n", before ? "before" : "after", @@ -642,6 +639,18 @@ hsw_unclaimed_reg_debug(struct drm_i915_private *dev_priv, i915.mmio_debug--; /* Only report the first N failures */ } +static inline void +unclaimed_reg_debug(struct drm_i915_private *dev_priv, + const i915_reg_t reg, + const bool read, + const bool before) +{ + if (likely(!i915.mmio_debug)) + return; + + __unclaimed_reg_debug(dev_priv, reg, read, before); +} + #define GEN2_READ_HEADER(x) \ u##x val = 0; \ assert_rpm_wakelock_held(dev_priv); @@ -687,9 +696,11 @@ __gen2_read(64) unsigned long irqflags; \ u##x val = 0; \ assert_rpm_wakelock_held(dev_priv); \ - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags) + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); \ + unclaimed_reg_debug(dev_priv, reg, true, true) #define GEN6_READ_FOOTER \ + unclaimed_reg_debug(dev_priv, reg, true, false); \ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \ trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \ return val @@ -722,11 +733,9 @@ static inline void __force_wake_get(struct drm_i915_private *dev_priv, static u##x \ gen6_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ GEN6_READ_HEADER(x); \ - hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \ if (NEEDS_FORCE_WAKE(offset)) \ __force_wake_get(dev_priv, FORCEWAKE_RENDER); \ val = __raw_i915_read##x(dev_priv, reg); \ - hsw_unclaimed_reg_debug(dev_priv, reg, true, false); \ GEN6_READ_FOOTER; \ } @@ -774,7 +783,6 @@ static u##x \ gen9_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ enum forcewake_domains fw_engine; \ GEN6_READ_HEADER(x); \ - hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \ if (!SKL_NEEDS_FORCE_WAKE(offset)) \ fw_engine = 0; \ else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \ @@ -788,7 +796,6 @@ gen9_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ if (fw_engine) \ __force_wake_get(dev_priv, fw_engine); \ val = __raw_i915_read##x(dev_priv, reg); \ - hsw_unclaimed_reg_debug(dev_priv, reg, true, false); \ GEN6_READ_FOOTER; \ } @@ -887,9 +894,11 @@ __gen2_write(64) unsigned long irqflags; \ trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \ assert_rpm_wakelock_held(dev_priv); \ - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags) + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); \ + unclaimed_reg_debug(dev_priv, reg, false, true) #define GEN6_WRITE_FOOTER \ + unclaimed_reg_debug(dev_priv, reg, false, false); \ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags) #define __gen6_write(x) \ @@ -915,12 +924,10 @@ hsw_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool t if (NEEDS_FORCE_WAKE(offset)) { \ __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ } \ - hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \ __raw_i915_write##x(dev_priv, reg, val); \ if (unlikely(__fifo_ret)) { \ gen6_gt_check_fifodbg(dev_priv); \ } \ - hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \ GEN6_WRITE_FOOTER; \ } @@ -950,11 +957,9 @@ static bool is_gen8_shadowed(struct drm_i915_private *dev_priv, static void \ gen8_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ GEN6_WRITE_HEADER; \ - hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \ if (NEEDS_FORCE_WAKE(offset) && !is_gen8_shadowed(dev_priv, reg)) \ __force_wake_get(dev_priv, FORCEWAKE_RENDER); \ __raw_i915_write##x(dev_priv, reg, val); \ - hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \ GEN6_WRITE_FOOTER; \ } @@ -1008,7 +1013,6 @@ gen9_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, \ bool trace) { \ enum forcewake_domains fw_engine; \ GEN6_WRITE_HEADER; \ - hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \ if (!SKL_NEEDS_FORCE_WAKE(offset) || \ is_gen9_shadowed(dev_priv, reg)) \ fw_engine = 0; \ @@ -1023,7 +1027,6 @@ gen9_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, \ if (fw_engine) \ __force_wake_get(dev_priv, fw_engine); \ __raw_i915_write##x(dev_priv, reg, val); \ - hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \ GEN6_WRITE_FOOTER; \ } -- cgit v1.2.3 From bc3b9346cd47148db8601fb425a4949902c475ec Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Fri, 8 Jan 2016 15:51:20 +0200 Subject: drm/i915: Arm the unclaimed mmio debugs on suspend path If we go into suspend with unclaimed access detected, it would be nice to catch that access on a next suspend path. So instead of just notifying about it, arm the unclaimed mmio checks on suspend side. We want to keep the asymmetry on resume, as if it was on resume path, it was not driver that is responsible so no point in arming mmio debugs. Cc: Chris Wilson Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1452261080-6979-2-git-send-email-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_uncore.c | 7 +++++-- 3 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 288fec7691dc..9de993d5fed2 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1502,7 +1502,7 @@ static int intel_runtime_suspend(struct device *device) enable_rpm_wakeref_asserts(dev_priv); WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count)); - if (intel_uncore_unclaimed_mmio(dev_priv)) + if (intel_uncore_arm_unclaimed_mmio_detection(dev_priv)) DRM_ERROR("Unclaimed access detected prior to suspending\n"); dev_priv->pm.suspended = true; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 747d2d84a18c..104bd1809936 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2720,7 +2720,7 @@ extern void intel_uncore_early_sanitize(struct drm_device *dev, bool restore_forcewake); extern void intel_uncore_init(struct drm_device *dev); extern bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv); -extern void intel_uncore_arm_unclaimed_mmio_detection(struct drm_i915_private *dev_priv); +extern bool intel_uncore_arm_unclaimed_mmio_detection(struct drm_i915_private *dev_priv); extern void intel_uncore_fini(struct drm_device *dev); extern void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore); const char *intel_uncore_forcewake_domain_to_str(const enum forcewake_domain_id id); diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 0b47bc891dc7..c3c13dc929cb 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1610,12 +1610,12 @@ bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv) return check_for_unclaimed_mmio(dev_priv); } -void +bool intel_uncore_arm_unclaimed_mmio_detection(struct drm_i915_private *dev_priv) { if (unlikely(i915.mmio_debug || dev_priv->uncore.unclaimed_mmio_check <= 0)) - return; + return false; if (unlikely(intel_uncore_unclaimed_mmio(dev_priv))) { DRM_DEBUG("Unclaimed register detected, " @@ -1623,5 +1623,8 @@ intel_uncore_arm_unclaimed_mmio_detection(struct drm_i915_private *dev_priv) "Please use i915.mmio_debug=N for more information.\n"); i915.mmio_debug++; dev_priv->uncore.unclaimed_mmio_check--; + return true; } + + return false; } -- cgit v1.2.3 From f4d64936afb414fd5af3ac301919407273fb74a4 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Dec 2015 15:11:00 +0200 Subject: drm/i915/bios: interpret the i2c element MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add parsing of the i2c element, defined in MIPI sequence block v2. Drop the status operation byte while at it, that does not exist. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/d8a2998977feee2f5b5ad609aaca787adfb41479.1450702954.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_bios.c | 5 +++++ drivers/gpu/drm/i915/intel_bios.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 71c739e33101..69040a73c09a 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -812,6 +812,11 @@ static int goto_next_sequence(const u8 *data, int index, int total) case MIPI_SEQ_ELEM_GPIO: len = 2; break; + case MIPI_SEQ_ELEM_I2C: + if (index + 7 > total) + return 0; + len = *(data + index + 6) + 7; + break; default: DRM_ERROR("Unknown operation byte\n"); return 0; diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 4e87df16e7b3..411b33794536 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -968,7 +968,7 @@ enum mipi_seq_element { MIPI_SEQ_ELEM_SEND_PKT, MIPI_SEQ_ELEM_DELAY, MIPI_SEQ_ELEM_GPIO, - MIPI_SEQ_ELEM_STATUS, + MIPI_SEQ_ELEM_I2C, /* sequence block v2+ */ MIPI_SEQ_ELEM_MAX }; -- cgit v1.2.3 From e534f7a2f795081817e95dee0a92bf0293b7a878 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Dec 2015 15:11:01 +0200 Subject: drm/i915/bios: add sequences for MIPI sequence block v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Properly parse the new sequences added in MIPI sequence block v2. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/cc1551bdfc4392d02413b78179f3a65c786c75ab.1450702954.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_bios.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 411b33794536..6146f1b0cf48 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -960,6 +960,9 @@ enum mipi_seq { MIPI_SEQ_DISPLAY_ON, MIPI_SEQ_DISPLAY_OFF, MIPI_SEQ_DEASSERT_RESET, + MIPI_SEQ_BACKLIGHT_ON, /* sequence block v2+ */ + MIPI_SEQ_BACKLIGHT_OFF, /* sequence block v2+ */ + MIPI_SEQ_TEAR_ON, /* sequence block v2+ */ MIPI_SEQ_MAX }; -- cgit v1.2.3 From 29bbdcb0e3a1602cf81f4afdf86fe127d3833b3f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 11 Jan 2016 15:29:08 +0200 Subject: drm/i915: skip the i2c element in the generic VBT DSI driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't choke on unknown elements when we do know how to skip them. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1452518948-16469-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 9bd920809697..b98cec635676 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -229,12 +229,18 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) return data; } +static const u8 *mipi_exec_i2c_skip(struct intel_dsi *intel_dsi, const u8 *data) +{ + return data + *(data + 6) + 7; +} + typedef const u8 * (*fn_mipi_elem_exec)(struct intel_dsi *intel_dsi, const u8 *data); static const fn_mipi_elem_exec exec_elem[] = { [MIPI_SEQ_ELEM_SEND_PKT] = mipi_exec_send_packet, [MIPI_SEQ_ELEM_DELAY] = mipi_exec_delay, [MIPI_SEQ_ELEM_GPIO] = mipi_exec_gpio, + [MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c_skip, }; /* -- cgit v1.2.3 From 4b42dfbbd8e5f0cd8b7a3f16d719046d363f6b57 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Dec 2015 15:11:03 +0200 Subject: drm/i915/bios: add defines for v3 sequence block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New sequences, new operations within sequences. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/96335b9fb875f79882d694360bff060251bd2f17.1450702954.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_bios.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 6146f1b0cf48..350d4e0f75a4 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -963,6 +963,9 @@ enum mipi_seq { MIPI_SEQ_BACKLIGHT_ON, /* sequence block v2+ */ MIPI_SEQ_BACKLIGHT_OFF, /* sequence block v2+ */ MIPI_SEQ_TEAR_ON, /* sequence block v2+ */ + MIPI_SEQ_TEAR_OFF, /* sequence block v3+ */ + MIPI_SEQ_POWER_ON, /* sequence block v3+ */ + MIPI_SEQ_POWER_OFF, /* sequence block v3+ */ MIPI_SEQ_MAX }; @@ -972,6 +975,8 @@ enum mipi_seq_element { MIPI_SEQ_ELEM_DELAY, MIPI_SEQ_ELEM_GPIO, MIPI_SEQ_ELEM_I2C, /* sequence block v2+ */ + MIPI_SEQ_ELEM_SPI, /* sequence block v3+ */ + MIPI_SEQ_ELEM_PMIC, /* sequence block v3+ */ MIPI_SEQ_ELEM_MAX }; -- cgit v1.2.3 From 2a33d93486f247924e46b5402b8ffb43d1b9b38c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 11 Jan 2016 15:15:02 +0200 Subject: drm/i915/bios: add support for MIPI sequence block v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The changes since the sequence block v2 are: * The whole MIPI bios data block has a separate 32-bit size field since v3, stored after the version. This facilitates big sequences. * The size of the panel specific sequence blocks has grown to 32 bits. This facilitates big sequences. * The elements within sequences now have an 8-bit size field following the operation byte. This facilitates skipping unknown new operation bytes, i.e. forward compatibility. v2 (of the patch): use DRM_ERROR for unknown operation byte v3 (of the patch): even more bounds checking (Ville) Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1452518102-3154-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_bios.c | 96 ++++++++++++++++++++++++++---- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 9 +++ 2 files changed, 94 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 69040a73c09a..15ba52bd2538 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -754,21 +754,33 @@ parse_mipi_config(struct drm_i915_private *dev_priv, /* Find the sequence block and size for the given panel. */ static const u8 * find_panel_sequence_block(const struct bdb_mipi_sequence *sequence, - u16 panel_id, u16 *seq_size) + u16 panel_id, u32 *seq_size) { u32 total = get_blocksize(sequence); const u8 *data = &sequence->data[0]; u8 current_id; - u16 current_size; + u32 current_size; + int header_size = sequence->version >= 3 ? 5 : 3; int index = 0; int i; - for (i = 0; i < MAX_MIPI_CONFIGURATIONS && index + 3 < total; i++) { + /* skip new block size */ + if (sequence->version >= 3) + data += 4; + + for (i = 0; i < MAX_MIPI_CONFIGURATIONS && index < total; i++) { + if (index + header_size > total) { + DRM_ERROR("Invalid sequence block (header)\n"); + return NULL; + } + current_id = *(data + index); - index++; + if (sequence->version >= 3) + current_size = *((const u32 *)(data + index + 1)); + else + current_size = *((const u16 *)(data + index + 1)); - current_size = *((const u16 *)(data + index)); - index += 2; + index += header_size; if (index + current_size > total) { DRM_ERROR("Invalid sequence block\n"); @@ -826,13 +838,71 @@ static int goto_next_sequence(const u8 *data, int index, int total) return 0; } +static int goto_next_sequence_v3(const u8 *data, int index, int total) +{ + int seq_end; + u16 len; + + /* + * Could skip sequence based on Size of Sequence alone, but also do some + * checking on the structure. + */ + if (total < 5) { + DRM_ERROR("Too small sequence size\n"); + return 0; + } + + seq_end = index + *((const u32 *)(data + 1)); + if (seq_end > total) { + DRM_ERROR("Invalid sequence size\n"); + return 0; + } + + /* Skip Sequence Byte and Size of Sequence. */ + for (index = index + 5; index < total; index += len) { + u8 operation_byte = *(data + index); + index++; + + if (operation_byte == MIPI_SEQ_ELEM_END) { + if (index != seq_end) { + DRM_ERROR("Invalid element structure\n"); + return 0; + } + return index; + } + + len = *(data + index); + index++; + + /* + * FIXME: Would be nice to check elements like for v1/v2 in + * goto_next_sequence() above. + */ + switch (operation_byte) { + case MIPI_SEQ_ELEM_SEND_PKT: + case MIPI_SEQ_ELEM_DELAY: + case MIPI_SEQ_ELEM_GPIO: + case MIPI_SEQ_ELEM_I2C: + case MIPI_SEQ_ELEM_SPI: + case MIPI_SEQ_ELEM_PMIC: + break; + default: + DRM_ERROR("Unknown operation byte %u\n", + operation_byte); + break; + } + } + + return 0; +} + static void parse_mipi_sequence(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) { const struct bdb_mipi_sequence *sequence; const u8 *seq_data; - u16 seq_size; + u32 seq_size; u8 *data; int index = 0; @@ -847,12 +917,13 @@ parse_mipi_sequence(struct drm_i915_private *dev_priv, } /* Fail gracefully for forward incompatible sequence block. */ - if (sequence->version >= 3) { - DRM_ERROR("Unable to parse MIPI Sequence Block v3+\n"); + if (sequence->version >= 4) { + DRM_ERROR("Unable to parse MIPI Sequence Block v%u\n", + sequence->version); return; } - DRM_DEBUG_DRIVER("Found MIPI sequence block\n"); + DRM_DEBUG_DRIVER("Found MIPI sequence block v%u\n", sequence->version); seq_data = find_panel_sequence_block(sequence, panel_type, &seq_size); if (!seq_data) @@ -875,7 +946,10 @@ parse_mipi_sequence(struct drm_i915_private *dev_priv, dev_priv->vbt.dsi.sequence[seq_id] = data + index; - index = goto_next_sequence(data, index, seq_size); + if (sequence->version >= 3) + index = goto_next_sequence_v3(data, index, seq_size); + else + index = goto_next_sequence(data, index, seq_size); if (!index) { DRM_ERROR("Invalid sequence %u\n", seq_id); goto err; diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index b98cec635676..a7d22ebef3fa 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -267,6 +267,7 @@ static const char *sequence_name(enum mipi_seq seq_id) static void generic_exec_sequence(struct intel_dsi *intel_dsi, const u8 *data) { + struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev); fn_mipi_elem_exec mipi_elem_exec; if (!data) @@ -278,6 +279,10 @@ static void generic_exec_sequence(struct intel_dsi *intel_dsi, const u8 *data) /* go to the first element of the sequence */ data++; + /* Skip Size of Sequence. */ + if (dev_priv->vbt.dsi.seq_version >= 3) + data += 4; + /* parse each byte till we reach end of sequence byte - 0x00 */ while (1) { u8 operation_byte = *data++; @@ -289,6 +294,10 @@ static void generic_exec_sequence(struct intel_dsi *intel_dsi, const u8 *data) } mipi_elem_exec = exec_elem[operation_byte]; + /* Skip Size of Operation. */ + if (dev_priv->vbt.dsi.seq_version >= 3) + data++; + /* execute the element specific rotines */ data = mipi_elem_exec(intel_dsi, data); -- cgit v1.2.3 From 407957827935bc951a706c09b0a395480c087748 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 5 Jan 2016 17:06:48 +0200 Subject: drm/i915/dsi: skip unknown elements for sequence block v3+ The sequence block has sizes of elements after the operation byte since sequence block v3. Use it to skip elements we don't support yet. v2: remove redundant exec_elem[operation_byte] check (Daniel) Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1452006408-27688-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 42 ++++++++++++++++-------------- 1 file changed, 23 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index a7d22ebef3fa..92d5972ec715 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -283,31 +283,35 @@ static void generic_exec_sequence(struct intel_dsi *intel_dsi, const u8 *data) if (dev_priv->vbt.dsi.seq_version >= 3) data += 4; - /* parse each byte till we reach end of sequence byte - 0x00 */ while (1) { u8 operation_byte = *data++; - if (operation_byte >= ARRAY_SIZE(exec_elem) || - !exec_elem[operation_byte]) { + u8 operation_size = 0; + + if (operation_byte == MIPI_SEQ_ELEM_END) + break; + + if (operation_byte < ARRAY_SIZE(exec_elem)) + mipi_elem_exec = exec_elem[operation_byte]; + else + mipi_elem_exec = NULL; + + /* Size of Operation. */ + if (dev_priv->vbt.dsi.seq_version >= 3) + operation_size = *data++; + + if (mipi_elem_exec) { + data = mipi_elem_exec(intel_dsi, data); + } else if (operation_size) { + /* We have size, skip. */ + DRM_DEBUG_KMS("Unsupported MIPI operation byte %u\n", + operation_byte); + data += operation_size; + } else { + /* No size, can't skip without parsing. */ DRM_ERROR("Unsupported MIPI operation byte %u\n", operation_byte); return; } - mipi_elem_exec = exec_elem[operation_byte]; - - /* Skip Size of Operation. */ - if (dev_priv->vbt.dsi.seq_version >= 3) - data++; - - /* execute the element specific rotines */ - data = mipi_elem_exec(intel_dsi, data); - - /* - * After processing the element, data should point to - * next element or end of sequence - * check if have we reached end of sequence - */ - if (*data == 0x00) - break; } } -- cgit v1.2.3 From c67fed8534139fcf5f0184cd4dea062f631d0d6f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Dec 2015 15:11:06 +0200 Subject: drm/i915/dsi: reduce tedious repetition Make it a bit tidier and safer. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/cab24a84811ddbae72d8c3a5f59d29f57b1d3aad.1450702954.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 62 +++++++++++------------------- 1 file changed, 22 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 92d5972ec715..66d0b73725df 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -265,18 +265,30 @@ static const char *sequence_name(enum mipi_seq seq_id) return "(unknown)"; } -static void generic_exec_sequence(struct intel_dsi *intel_dsi, const u8 *data) +static void generic_exec_sequence(struct drm_panel *panel, enum mipi_seq seq_id) { + struct vbt_panel *vbt_panel = to_vbt_panel(panel); + struct intel_dsi *intel_dsi = vbt_panel->intel_dsi; struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev); + const u8 *data; fn_mipi_elem_exec mipi_elem_exec; - if (!data) + if (WARN_ON(seq_id >= ARRAY_SIZE(dev_priv->vbt.dsi.sequence))) return; - DRM_DEBUG_DRIVER("Starting MIPI sequence %u - %s\n", - *data, sequence_name(*data)); + data = dev_priv->vbt.dsi.sequence[seq_id]; + if (!data) { + DRM_DEBUG_KMS("MIPI sequence %d - %s not available\n", + seq_id, sequence_name(seq_id)); + return; + } - /* go to the first element of the sequence */ + WARN_ON(*data != seq_id); + + DRM_DEBUG_KMS("Starting MIPI sequence %d - %s\n", + seq_id, sequence_name(seq_id)); + + /* Skip Sequence Byte. */ data++; /* Skip Size of Sequence. */ @@ -317,59 +329,29 @@ static void generic_exec_sequence(struct intel_dsi *intel_dsi, const u8 *data) static int vbt_panel_prepare(struct drm_panel *panel) { - struct vbt_panel *vbt_panel = to_vbt_panel(panel); - struct intel_dsi *intel_dsi = vbt_panel->intel_dsi; - struct drm_device *dev = intel_dsi->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - const u8 *sequence; - - sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_ASSERT_RESET]; - generic_exec_sequence(intel_dsi, sequence); - - sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP]; - generic_exec_sequence(intel_dsi, sequence); + generic_exec_sequence(panel, MIPI_SEQ_ASSERT_RESET); + generic_exec_sequence(panel, MIPI_SEQ_INIT_OTP); return 0; } static int vbt_panel_unprepare(struct drm_panel *panel) { - struct vbt_panel *vbt_panel = to_vbt_panel(panel); - struct intel_dsi *intel_dsi = vbt_panel->intel_dsi; - struct drm_device *dev = intel_dsi->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - const u8 *sequence; - - sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET]; - generic_exec_sequence(intel_dsi, sequence); + generic_exec_sequence(panel, MIPI_SEQ_DEASSERT_RESET); return 0; } static int vbt_panel_enable(struct drm_panel *panel) { - struct vbt_panel *vbt_panel = to_vbt_panel(panel); - struct intel_dsi *intel_dsi = vbt_panel->intel_dsi; - struct drm_device *dev = intel_dsi->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - const u8 *sequence; - - sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_DISPLAY_ON]; - generic_exec_sequence(intel_dsi, sequence); + generic_exec_sequence(panel, MIPI_SEQ_DISPLAY_ON); return 0; } static int vbt_panel_disable(struct drm_panel *panel) { - struct vbt_panel *vbt_panel = to_vbt_panel(panel); - struct intel_dsi *intel_dsi = vbt_panel->intel_dsi; - struct drm_device *dev = intel_dsi->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - const u8 *sequence; - - sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_DISPLAY_OFF]; - generic_exec_sequence(intel_dsi, sequence); + generic_exec_sequence(panel, MIPI_SEQ_DISPLAY_OFF); return 0; } -- cgit v1.2.3 From bc95ce7f397232f8d0cacec94aa426b90e87d024 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 5 Jan 2016 17:08:17 +0200 Subject: drm/i915/dsi: add debug printing of the new sequence block names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1452006497-28517-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 66d0b73725df..1d43e6f37fc1 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -255,6 +255,12 @@ static const char * const seq_name[] = { [MIPI_SEQ_DISPLAY_ON] = "MIPI_SEQ_DISPLAY_ON", [MIPI_SEQ_DISPLAY_OFF] = "MIPI_SEQ_DISPLAY_OFF", [MIPI_SEQ_DEASSERT_RESET] = "MIPI_SEQ_DEASSERT_RESET", + [MIPI_SEQ_BACKLIGHT_ON] = "MIPI_SEQ_BACKLIGHT_ON", + [MIPI_SEQ_BACKLIGHT_OFF] = "MIPI_SEQ_BACKLIGHT_OFF", + [MIPI_SEQ_TEAR_ON] = "MIPI_SEQ_TEAR_ON", + [MIPI_SEQ_TEAR_OFF] = "MIPI_SEQ_TEAR_OFF", + [MIPI_SEQ_POWER_ON] = "MIPI_SEQ_POWER_ON", + [MIPI_SEQ_POWER_OFF] = "MIPI_SEQ_POWER_OFF", }; static const char *sequence_name(enum mipi_seq seq_id) -- cgit v1.2.3 From 7eb08a25a4104ec6b2dfd78939606cff44a394e1 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 11 Jan 2016 14:08:35 +0000 Subject: drm/i915/bdw+: Replace list_del+list_add_tail with list_move_tail Same effect for slightly less source code and resulting binary. Signed-off-by: Tvrtko Ursulin Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1452521321-4032-2-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/intel_lrc.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index f7fac5f3b5ce..ab344e0b878c 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -431,9 +431,8 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring) /* Same ctx: ignore first request, as second request * will update tail past first request's workload */ cursor->elsp_submitted = req0->elsp_submitted; - list_del(&req0->execlist_link); - list_add_tail(&req0->execlist_link, - &ring->execlist_retired_req_list); + list_move_tail(&req0->execlist_link, + &ring->execlist_retired_req_list); req0 = cursor; } else { req1 = cursor; @@ -485,9 +484,8 @@ static bool execlists_check_remove_request(struct intel_engine_cs *ring, "Never submitted head request\n"); if (--head_req->elsp_submitted <= 0) { - list_del(&head_req->execlist_link); - list_add_tail(&head_req->execlist_link, - &ring->execlist_retired_req_list); + list_move_tail(&head_req->execlist_link, + &ring->execlist_retired_req_list); return true; } } @@ -608,9 +606,8 @@ static int execlists_context_queue(struct drm_i915_gem_request *request) if (request->ctx == tail_req->ctx) { WARN(tail_req->elsp_submitted != 0, "More than 2 already-submitted reqs queued\n"); - list_del(&tail_req->execlist_link); - list_add_tail(&tail_req->execlist_link, - &ring->execlist_retired_req_list); + list_move_tail(&tail_req->execlist_link, + &ring->execlist_retired_req_list); } } -- cgit v1.2.3 From d919161b67b1ed4a374dae685840a601bbeb1347 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 8 Dec 2015 19:59:36 +0200 Subject: drm/i915: Pass the correct encoder to intel_ddi_clk_select() with MST MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We're supposed to pass the primary DP encoder to intel_ddi_clk_select(), not the fake MST encoder. Do so. There's no real bug here though, since intel_ddi_clk_select() only checks if the encoder type is EDP (which it isn't for either the primary DP encoder or the fake MST encoder), and it gets the DDI port via intel_ddi_get_encoder_port() (which knows how to do the fake->primary->port dance itself). Fixes: e404ba8 ("drm/i915: Setup DDI clk for MST on SKL") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1449597590-6971-2-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp_mst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 8b608c2cd070..5cb168dc2f0c 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -184,7 +184,7 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder) intel_mst->port = found->port; if (intel_dp->active_mst_links == 0) { - intel_ddi_clk_select(encoder, intel_crtc->config); + intel_ddi_clk_select(&intel_dig_port->base, intel_crtc->config); intel_dp_set_link_params(intel_dp, intel_crtc->config); -- cgit v1.2.3 From 10e7bec38bbda47653b46d4e1257876124824a9b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 8 Dec 2015 19:59:37 +0200 Subject: drm/i915: Check max number of lanes when registering DDI ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DDI A and E share some of the lanes, so check that we have enough lanes for the purpose we need before registering the encoders. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1449597590-6971-3-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 612400fab559..a69db463557f 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -3282,6 +3282,33 @@ void intel_ddi_init(struct drm_device *dev, enum port port) struct intel_encoder *intel_encoder; struct drm_encoder *encoder; bool init_hdmi, init_dp; + int max_lanes; + + if (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) { + switch (port) { + case PORT_A: + max_lanes = 4; + break; + case PORT_E: + max_lanes = 0; + break; + default: + max_lanes = 4; + break; + } + } else { + switch (port) { + case PORT_A: + max_lanes = 2; + break; + case PORT_E: + max_lanes = 2; + break; + default: + max_lanes = 4; + break; + } + } init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi || dev_priv->vbt.ddi_port_info[port].supports_hdmi); @@ -3292,6 +3319,15 @@ void intel_ddi_init(struct drm_device *dev, enum port port) return; } + if (WARN(max_lanes == 0, + "No lanes for port %c\n", port_name(port))) + return; + + if (WARN(init_hdmi && max_lanes < 4, + "Not enough lanes (%d) for HDMI on port %c\n", + max_lanes, port_name(port))) + init_hdmi = false; + intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); if (!intel_dig_port) return; -- cgit v1.2.3 From ccb1a8319015d31a51e8206b66ab3aaea07417ba Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 8 Dec 2015 19:59:38 +0200 Subject: drm/i915: Store max lane count in intel_digital_port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than having open coded checks for the DDI A/E configuration, just store the max supported lane count in intel_digital_port. We had an open coded check for DDI A, but not for DDI E. So we may have been vilating the DDI E max lane count. Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 10 +--------- drivers/gpu/drm/i915/intel_dp.c | 13 +++++++------ drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_hdmi.c | 6 ++++++ 4 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index a69db463557f..1e9d292d4037 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -3319,15 +3319,6 @@ void intel_ddi_init(struct drm_device *dev, enum port port) return; } - if (WARN(max_lanes == 0, - "No lanes for port %c\n", port_name(port))) - return; - - if (WARN(init_hdmi && max_lanes < 4, - "Not enough lanes (%d) for HDMI on port %c\n", - max_lanes, port_name(port))) - init_hdmi = false; - intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); if (!intel_dig_port) return; @@ -3351,6 +3342,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) & (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES); + intel_dig_port->max_lanes = max_lanes; /* * Bspec says that DDI_A_4_LANES is the only supported configuration diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5332eb7657e1..9e02dd789b86 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -157,14 +157,9 @@ intel_dp_max_link_bw(struct intel_dp *intel_dp) static u8 intel_dp_max_lane_count(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = intel_dig_port->base.base.dev; u8 source_max, sink_max; - source_max = 4; - if (HAS_DDI(dev) && intel_dig_port->port == PORT_A && - (intel_dig_port->saved_port_bits & DDI_A_4_LANES) == 0) - source_max = 2; - + source_max = intel_dig_port->max_lanes; sink_max = drm_dp_max_lane_count(intel_dp->dpcd); return min(source_max, sink_max); @@ -5839,6 +5834,11 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, enum port port = intel_dig_port->port; int type, ret; + if (WARN(intel_dig_port->max_lanes < 1, + "Not enough lanes (%d) for DP on port %c\n", + intel_dig_port->max_lanes, port_name(port))) + return false; + intel_dp->pps_pipe = INVALID_PIPE; /* intel_dp vfuncs */ @@ -6037,6 +6037,7 @@ intel_dp_init(struct drm_device *dev, intel_dig_port->port = port; dev_priv->dig_port_map[port] = intel_encoder; intel_dig_port->dp.output_reg = output_reg; + intel_dig_port->max_lanes = 4; intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; if (IS_CHERRYVIEW(dev)) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index bdfe4035e074..32de7e478f8f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -845,6 +845,7 @@ struct intel_digital_port { struct intel_hdmi hdmi; enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool); bool release_cl2_override; + uint8_t max_lanes; /* for communication with audio component; protected by av_mutex */ const struct drm_connector *audio_connector; }; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 054aa7613390..d4ed7aa9927e 100755 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -2033,6 +2033,11 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, enum port port = intel_dig_port->port; uint8_t alternate_ddc_pin; + if (WARN(intel_dig_port->max_lanes < 4, + "Not enough lanes (%d) for HDMI on port %c\n", + intel_dig_port->max_lanes, port_name(port))) + return; + drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA); drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); @@ -2218,6 +2223,7 @@ void intel_hdmi_init(struct drm_device *dev, dev_priv->dig_port_map[port] = intel_encoder; intel_dig_port->hdmi.hdmi_reg = hdmi_reg; intel_dig_port->dp.output_reg = INVALID_MMIO_REG; + intel_dig_port->max_lanes = 4; intel_hdmi_init_connector(intel_dig_port, intel_connector); } -- cgit v1.2.3 From acee29988e9a22a343728c36954d2ea6f9c0c970 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 8 Dec 2015 19:59:39 +0200 Subject: drm/i915: Remove pointless 'ddi_translations' local variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit skl_get_buf_trans_*() don't need the 'ddi_translations' local variable since all they with is assign and return. Just return the right thing directly and get rid of the local variable. v2: Resolve conflicts due to KBL Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter (v1) --- drivers/gpu/drm/i915/intel_ddi.c | 44 +++++++++++++++------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 1e9d292d4037..b8b4a3103cf1 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -348,75 +348,63 @@ intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port) return i915_mmio_reg_valid(intel_dig_port->hdmi.hdmi_reg); } -static const struct ddi_buf_trans *skl_get_buf_trans_dp(struct drm_device *dev, - int *n_entries) +static const struct ddi_buf_trans * +skl_get_buf_trans_dp(struct drm_device *dev, int *n_entries) { - const struct ddi_buf_trans *ddi_translations; - if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) { - ddi_translations = skl_y_ddi_translations_dp; *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp); + return skl_y_ddi_translations_dp; } else if (IS_SKL_ULT(dev) || IS_KBL_ULT(dev)) { - ddi_translations = skl_u_ddi_translations_dp; *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); + return skl_u_ddi_translations_dp; } else { - ddi_translations = skl_ddi_translations_dp; *n_entries = ARRAY_SIZE(skl_ddi_translations_dp); + return skl_ddi_translations_dp; } - - return ddi_translations; } -static const struct ddi_buf_trans *skl_get_buf_trans_edp(struct drm_device *dev, - int *n_entries) +static const struct ddi_buf_trans * +skl_get_buf_trans_edp(struct drm_device *dev, int *n_entries) { struct drm_i915_private *dev_priv = dev->dev_private; - const struct ddi_buf_trans *ddi_translations; if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) { if (dev_priv->edp_low_vswing) { - ddi_translations = skl_y_ddi_translations_edp; *n_entries = ARRAY_SIZE(skl_y_ddi_translations_edp); + return skl_y_ddi_translations_edp; } else { - ddi_translations = skl_y_ddi_translations_dp; *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp); + return skl_y_ddi_translations_dp; } } else if (IS_SKL_ULT(dev) || IS_KBL_ULT(dev)) { if (dev_priv->edp_low_vswing) { - ddi_translations = skl_u_ddi_translations_edp; *n_entries = ARRAY_SIZE(skl_u_ddi_translations_edp); + return skl_u_ddi_translations_edp; } else { - ddi_translations = skl_u_ddi_translations_dp; *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); + return skl_u_ddi_translations_dp; } } else { if (dev_priv->edp_low_vswing) { - ddi_translations = skl_ddi_translations_edp; *n_entries = ARRAY_SIZE(skl_ddi_translations_edp); + return skl_ddi_translations_edp; } else { - ddi_translations = skl_ddi_translations_dp; *n_entries = ARRAY_SIZE(skl_ddi_translations_dp); + return skl_ddi_translations_dp; } } - - return ddi_translations; } static const struct ddi_buf_trans * -skl_get_buf_trans_hdmi(struct drm_device *dev, - int *n_entries) +skl_get_buf_trans_hdmi(struct drm_device *dev, int *n_entries) { - const struct ddi_buf_trans *ddi_translations; - if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) { - ddi_translations = skl_y_ddi_translations_hdmi; *n_entries = ARRAY_SIZE(skl_y_ddi_translations_hdmi); + return skl_y_ddi_translations_hdmi; } else { - ddi_translations = skl_ddi_translations_hdmi; *n_entries = ARRAY_SIZE(skl_ddi_translations_hdmi); + return skl_ddi_translations_hdmi; } - - return ddi_translations; } /* -- cgit v1.2.3 From cd1101cb271ba6b7cd407ca750a038d89df357a1 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 8 Dec 2015 19:59:40 +0200 Subject: drm/i915: Eliminate duplicated skl_get_buf_trans_dp() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit skl_get_buf_trans_edp() effectively contains another copy of skl_get_buf_trans_dp(). Remove the duplication and just call skl_get_buf_trans_dp() from skl_get_buf_trans_edp(). v2: Resolve conflicts due to KBL Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter (v1) --- drivers/gpu/drm/i915/intel_ddi.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index b8b4a3103cf1..9f8b28faa8e2 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -368,31 +368,20 @@ skl_get_buf_trans_edp(struct drm_device *dev, int *n_entries) { struct drm_i915_private *dev_priv = dev->dev_private; - if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) { - if (dev_priv->edp_low_vswing) { + if (dev_priv->edp_low_vswing) { + if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) { *n_entries = ARRAY_SIZE(skl_y_ddi_translations_edp); return skl_y_ddi_translations_edp; - } else { - *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp); - return skl_y_ddi_translations_dp; - } - } else if (IS_SKL_ULT(dev) || IS_KBL_ULT(dev)) { - if (dev_priv->edp_low_vswing) { + } else if (IS_SKL_ULT(dev) || IS_KBL_ULT(dev)) { *n_entries = ARRAY_SIZE(skl_u_ddi_translations_edp); return skl_u_ddi_translations_edp; } else { - *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); - return skl_u_ddi_translations_dp; - } - } else { - if (dev_priv->edp_low_vswing) { *n_entries = ARRAY_SIZE(skl_ddi_translations_edp); return skl_ddi_translations_edp; - } else { - *n_entries = ARRAY_SIZE(skl_ddi_translations_dp); - return skl_ddi_translations_dp; } } + + return skl_get_buf_trans_dp(dev, n_entries); } static const struct ddi_buf_trans * -- cgit v1.2.3 From 78ab0baea270af82a33c142f7f12bca4cdff6728 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 8 Dec 2015 19:59:41 +0200 Subject: drm/i915: Pass around dev_priv for ddi buffer programming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the ddi buffer programming code a bit more neat by passing around dev_priv instead of dev. v2: Resolve conflicts due to KBL Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter (v1) --- drivers/gpu/drm/i915/intel_ddi.c | 79 +++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 9f8b28faa8e2..c47146473471 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -301,8 +301,8 @@ static const struct bxt_ddi_buf_trans bxt_ddi_translations_hdmi[] = { { 154, 0x9A, 1, 128, true }, /* 9: 1200 0 */ }; -static void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, - enum port port, int type); +static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv, + u32 level, enum port port, int type); static void ddi_get_encoder_port(struct intel_encoder *intel_encoder, struct intel_digital_port **dig_port, @@ -349,12 +349,12 @@ intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port) } static const struct ddi_buf_trans * -skl_get_buf_trans_dp(struct drm_device *dev, int *n_entries) +skl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) { - if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) { + if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv)) { *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp); return skl_y_ddi_translations_dp; - } else if (IS_SKL_ULT(dev) || IS_KBL_ULT(dev)) { + } else if (IS_SKL_ULT(dev_priv) || IS_KBL_ULT(dev_priv)) { *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); return skl_u_ddi_translations_dp; } else { @@ -364,15 +364,13 @@ skl_get_buf_trans_dp(struct drm_device *dev, int *n_entries) } static const struct ddi_buf_trans * -skl_get_buf_trans_edp(struct drm_device *dev, int *n_entries) +skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) { - struct drm_i915_private *dev_priv = dev->dev_private; - if (dev_priv->edp_low_vswing) { - if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) { + if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv)) { *n_entries = ARRAY_SIZE(skl_y_ddi_translations_edp); return skl_y_ddi_translations_edp; - } else if (IS_SKL_ULT(dev) || IS_KBL_ULT(dev)) { + } else if (IS_SKL_ULT(dev_priv) || IS_KBL_ULT(dev_priv)) { *n_entries = ARRAY_SIZE(skl_u_ddi_translations_edp); return skl_u_ddi_translations_edp; } else { @@ -381,13 +379,13 @@ skl_get_buf_trans_edp(struct drm_device *dev, int *n_entries) } } - return skl_get_buf_trans_dp(dev, n_entries); + return skl_get_buf_trans_dp(dev_priv, n_entries); } static const struct ddi_buf_trans * -skl_get_buf_trans_hdmi(struct drm_device *dev, int *n_entries) +skl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries) { - if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) { + if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv)) { *n_entries = ARRAY_SIZE(skl_y_ddi_translations_hdmi); return skl_y_ddi_translations_hdmi; } else { @@ -403,10 +401,9 @@ skl_get_buf_trans_hdmi(struct drm_device *dev, int *n_entries) * in either FDI or DP modes only, as HDMI connections will work with both * of those */ -static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, - bool supports_hdmi) +static void intel_prepare_ddi_buffers(struct drm_i915_private *dev_priv, + enum port port, bool supports_hdmi) { - struct drm_i915_private *dev_priv = dev->dev_private; u32 iboost_bit = 0; int i, n_hdmi_entries, n_dp_entries, n_edp_entries, hdmi_default_entry, size; @@ -417,28 +414,28 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, const struct ddi_buf_trans *ddi_translations_hdmi; const struct ddi_buf_trans *ddi_translations; - if (IS_BROXTON(dev)) { + if (IS_BROXTON(dev_priv)) { if (!supports_hdmi) return; /* Vswing programming for HDMI */ - bxt_ddi_vswing_sequence(dev, hdmi_level, port, + bxt_ddi_vswing_sequence(dev_priv, hdmi_level, port, INTEL_OUTPUT_HDMI); return; - } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { + } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { ddi_translations_fdi = NULL; ddi_translations_dp = - skl_get_buf_trans_dp(dev, &n_dp_entries); + skl_get_buf_trans_dp(dev_priv, &n_dp_entries); ddi_translations_edp = - skl_get_buf_trans_edp(dev, &n_edp_entries); + skl_get_buf_trans_edp(dev_priv, &n_edp_entries); ddi_translations_hdmi = - skl_get_buf_trans_hdmi(dev, &n_hdmi_entries); + skl_get_buf_trans_hdmi(dev_priv, &n_hdmi_entries); hdmi_default_entry = 8; /* If we're boosting the current, set bit 31 of trans1 */ if (dev_priv->vbt.ddi_port_info[port].hdmi_boost_level || dev_priv->vbt.ddi_port_info[port].dp_boost_level) iboost_bit = 1<<31; - } else if (IS_BROADWELL(dev)) { + } else if (IS_BROADWELL(dev_priv)) { ddi_translations_fdi = bdw_ddi_translations_fdi; ddi_translations_dp = bdw_ddi_translations_dp; ddi_translations_edp = bdw_ddi_translations_edp; @@ -447,7 +444,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp); n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); hdmi_default_entry = 7; - } else if (IS_HASWELL(dev)) { + } else if (IS_HASWELL(dev_priv)) { ddi_translations_fdi = hsw_ddi_translations_fdi; ddi_translations_dp = hsw_ddi_translations_dp; ddi_translations_edp = hsw_ddi_translations_dp; @@ -478,7 +475,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, size = n_dp_entries; break; case PORT_D: - if (intel_dp_is_edp(dev, PORT_D)) { + if (intel_dp_is_edp(dev_priv->dev, PORT_D)) { ddi_translations = ddi_translations_edp; size = n_edp_entries; } else { @@ -545,7 +542,7 @@ void intel_prepare_ddi(struct drm_device *dev) supports_hdmi = intel_dig_port && intel_dig_port_supports_hdmi(intel_dig_port); - intel_prepare_ddi_buffers(dev, port, supports_hdmi); + intel_prepare_ddi_buffers(to_i915(dev), port, supports_hdmi); visited[port] = true; } } @@ -2062,10 +2059,9 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc) TRANS_CLK_SEL_DISABLED); } -static void skl_ddi_set_iboost(struct drm_device *dev, u32 level, - enum port port, int type) +static void skl_ddi_set_iboost(struct drm_i915_private *dev_priv, + u32 level, enum port port, int type) { - struct drm_i915_private *dev_priv = dev->dev_private; const struct ddi_buf_trans *ddi_translations; uint8_t iboost; uint8_t dp_iboost, hdmi_iboost; @@ -2080,21 +2076,21 @@ static void skl_ddi_set_iboost(struct drm_device *dev, u32 level, if (dp_iboost) { iboost = dp_iboost; } else { - ddi_translations = skl_get_buf_trans_dp(dev, &n_entries); + ddi_translations = skl_get_buf_trans_dp(dev_priv, &n_entries); iboost = ddi_translations[level].i_boost; } } else if (type == INTEL_OUTPUT_EDP) { if (dp_iboost) { iboost = dp_iboost; } else { - ddi_translations = skl_get_buf_trans_edp(dev, &n_entries); + ddi_translations = skl_get_buf_trans_edp(dev_priv, &n_entries); iboost = ddi_translations[level].i_boost; } } else if (type == INTEL_OUTPUT_HDMI) { if (hdmi_iboost) { iboost = hdmi_iboost; } else { - ddi_translations = skl_get_buf_trans_hdmi(dev, &n_entries); + ddi_translations = skl_get_buf_trans_hdmi(dev_priv, &n_entries); iboost = ddi_translations[level].i_boost; } } else { @@ -2119,10 +2115,9 @@ static void skl_ddi_set_iboost(struct drm_device *dev, u32 level, I915_WRITE(DISPIO_CR_TX_BMU_CR0, reg); } -static void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, - enum port port, int type) +static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv, + u32 level, enum port port, int type) { - struct drm_i915_private *dev_priv = dev->dev_private; const struct bxt_ddi_buf_trans *ddi_translations; u32 n_entries, i; uint32_t val; @@ -2237,7 +2232,7 @@ static uint32_t translate_signal_level(int signal_levels) uint32_t ddi_signal_levels(struct intel_dp *intel_dp) { struct intel_digital_port *dport = dp_to_dig_port(intel_dp); - struct drm_device *dev = dport->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); struct intel_encoder *encoder = &dport->base; uint8_t train_set = intel_dp->train_set[0]; int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | @@ -2247,10 +2242,10 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp) level = translate_signal_level(signal_levels); - if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) - skl_ddi_set_iboost(dev, level, port, encoder->type); - else if (IS_BROXTON(dev)) - bxt_ddi_vswing_sequence(dev, level, port, encoder->type); + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) + skl_ddi_set_iboost(dev_priv, level, port, encoder->type); + else if (IS_BROXTON(dev_priv)) + bxt_ddi_vswing_sequence(dev_priv, level, port, encoder->type); return DDI_BUF_TRANS_SELECT(level); } @@ -2333,8 +2328,8 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) if (IS_BROXTON(dev)) { hdmi_level = dev_priv->vbt. ddi_port_info[port].hdmi_level_shift; - bxt_ddi_vswing_sequence(dev, hdmi_level, port, - INTEL_OUTPUT_HDMI); + bxt_ddi_vswing_sequence(dev_priv, hdmi_level, port, + INTEL_OUTPUT_HDMI); } intel_hdmi->set_infoframes(encoder, crtc->config->has_hdmi_sink, -- cgit v1.2.3 From 10afa0b65fe21cac67e8b19e8b98bde39befc525 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 8 Dec 2015 19:59:43 +0200 Subject: drm/i915: Reject >9 ddi translation entried if port != A/E on SKL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only DDI A and E support 10 translation entries in DP mode. For the other ports the tenth entry is reserved for HDMI. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1449597590-6971-9-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index c47146473471..3edb10a4f0b4 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -435,6 +435,10 @@ static void intel_prepare_ddi_buffers(struct drm_i915_private *dev_priv, if (dev_priv->vbt.ddi_port_info[port].hdmi_boost_level || dev_priv->vbt.ddi_port_info[port].dp_boost_level) iboost_bit = 1<<31; + + if (WARN_ON(port != PORT_A && + port != PORT_E && n_edp_entries > 9)) + n_edp_entries = 9; } else if (IS_BROADWELL(dev_priv)) { ddi_translations_fdi = bdw_ddi_translations_fdi; ddi_translations_dp = bdw_ddi_translations_dp; @@ -2084,6 +2088,11 @@ static void skl_ddi_set_iboost(struct drm_i915_private *dev_priv, iboost = dp_iboost; } else { ddi_translations = skl_get_buf_trans_edp(dev_priv, &n_entries); + + if (WARN_ON(port != PORT_A && + port != PORT_E && n_entries > 9)) + n_entries = 9; + iboost = ddi_translations[level].i_boost; } } else if (type == INTEL_OUTPUT_HDMI) { -- cgit v1.2.3 From 6a7e4f99897f31708ff9ea01875d9ff112bebe90 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 8 Dec 2015 19:59:44 +0200 Subject: drm/i915: Kill intel_prepare_ddi() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the ddi buffer translation programming to occur from the encoder .pre_enable() hook, for just the ddi port we are enabling. Previously we used to reprogram the translations for all ddi ports during init and during power well enabling. v2: s/intel_prepare_ddi_buffers/intel_prepare_ddi_buffer/ (Daniel) Resolve conflicts due to dev_priv->atomic_cdclk_freq Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 1 - drivers/gpu/drm/i915/intel_ddi.c | 99 ++++++++++----------------------- drivers/gpu/drm/i915/intel_display.c | 3 - drivers/gpu/drm/i915/intel_dp_mst.c | 2 + drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_runtime_pm.c | 12 ---- 6 files changed, 31 insertions(+), 88 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 9de993d5fed2..f17a2b0c2493 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1077,7 +1077,6 @@ static int bxt_resume_prepare(struct drm_i915_private *dev_priv) */ broxton_init_cdclk(dev); broxton_ddi_phy_init(dev); - intel_prepare_ddi(dev); return 0; } diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 3edb10a4f0b4..2ed64725470a 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -342,12 +342,6 @@ enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) return port; } -static bool -intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port) -{ - return i915_mmio_reg_valid(intel_dig_port->hdmi.hdmi_reg); -} - static const struct ddi_buf_trans * skl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) { @@ -401,28 +395,34 @@ skl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries) * in either FDI or DP modes only, as HDMI connections will work with both * of those */ -static void intel_prepare_ddi_buffers(struct drm_i915_private *dev_priv, - enum port port, bool supports_hdmi) +void intel_prepare_ddi_buffer(struct intel_encoder *encoder) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); u32 iboost_bit = 0; int i, n_hdmi_entries, n_dp_entries, n_edp_entries, hdmi_default_entry, size; - int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; + int hdmi_level; + enum port port; const struct ddi_buf_trans *ddi_translations_fdi; const struct ddi_buf_trans *ddi_translations_dp; const struct ddi_buf_trans *ddi_translations_edp; const struct ddi_buf_trans *ddi_translations_hdmi; const struct ddi_buf_trans *ddi_translations; + port = intel_ddi_get_encoder_port(encoder); + hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; + if (IS_BROXTON(dev_priv)) { - if (!supports_hdmi) + if (encoder->type != INTEL_OUTPUT_HDMI) return; /* Vswing programming for HDMI */ bxt_ddi_vswing_sequence(dev_priv, hdmi_level, port, INTEL_OUTPUT_HDMI); return; - } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { + } + + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { ddi_translations_fdi = NULL; ddi_translations_dp = skl_get_buf_trans_dp(dev_priv, &n_dp_entries); @@ -468,30 +468,18 @@ static void intel_prepare_ddi_buffers(struct drm_i915_private *dev_priv, hdmi_default_entry = 7; } - switch (port) { - case PORT_A: + switch (encoder->type) { + case INTEL_OUTPUT_EDP: ddi_translations = ddi_translations_edp; size = n_edp_entries; break; - case PORT_B: - case PORT_C: + case INTEL_OUTPUT_DISPLAYPORT: + case INTEL_OUTPUT_HDMI: ddi_translations = ddi_translations_dp; size = n_dp_entries; break; - case PORT_D: - if (intel_dp_is_edp(dev_priv->dev, PORT_D)) { - ddi_translations = ddi_translations_edp; - size = n_edp_entries; - } else { - ddi_translations = ddi_translations_dp; - size = n_dp_entries; - } - break; - case PORT_E: - if (ddi_translations_fdi) - ddi_translations = ddi_translations_fdi; - else - ddi_translations = ddi_translations_dp; + case INTEL_OUTPUT_ANALOG: + ddi_translations = ddi_translations_fdi; size = n_dp_entries; break; default: @@ -505,7 +493,7 @@ static void intel_prepare_ddi_buffers(struct drm_i915_private *dev_priv, ddi_translations[i].trans2); } - if (!supports_hdmi) + if (encoder->type != INTEL_OUTPUT_HDMI) return; /* Choose a good default if VBT is badly populated */ @@ -520,37 +508,6 @@ static void intel_prepare_ddi_buffers(struct drm_i915_private *dev_priv, ddi_translations_hdmi[hdmi_level].trans2); } -/* Program DDI buffers translations for DP. By default, program ports A-D in DP - * mode and port E for FDI. - */ -void intel_prepare_ddi(struct drm_device *dev) -{ - struct intel_encoder *intel_encoder; - bool visited[I915_MAX_PORTS] = { 0, }; - - if (!HAS_DDI(dev)) - return; - - for_each_intel_encoder(dev, intel_encoder) { - struct intel_digital_port *intel_dig_port; - enum port port; - bool supports_hdmi; - - if (intel_encoder->type == INTEL_OUTPUT_DSI) - continue; - - ddi_get_encoder_port(intel_encoder, &intel_dig_port, &port); - if (visited[port]) - continue; - - supports_hdmi = intel_dig_port && - intel_dig_port_supports_hdmi(intel_dig_port); - - intel_prepare_ddi_buffers(to_i915(dev), port, supports_hdmi); - visited[port] = true; - } -} - static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, enum port port) { @@ -579,8 +536,14 @@ void hsw_fdi_link_train(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_encoder *encoder; u32 temp, i, rx_ctl_val; + for_each_encoder_on_crtc(dev, crtc, encoder) { + WARN_ON(encoder->type != INTEL_OUTPUT_ANALOG); + intel_prepare_ddi_buffer(encoder); + } + /* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the * mode set "sequence for CRT port" document: * - TP1 to TP2 time with the default value @@ -2306,12 +2269,12 @@ void intel_ddi_clk_select(struct intel_encoder *encoder, static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) { struct drm_encoder *encoder = &intel_encoder->base; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(encoder->dev); struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); enum port port = intel_ddi_get_encoder_port(intel_encoder); int type = intel_encoder->type; - int hdmi_level; + + intel_prepare_ddi_buffer(intel_encoder); if (type == INTEL_OUTPUT_EDP) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); @@ -2329,17 +2292,11 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); intel_dp_start_link_train(intel_dp); - if (port != PORT_A || INTEL_INFO(dev)->gen >= 9) + if (port != PORT_A || INTEL_INFO(dev_priv)->gen >= 9) intel_dp_stop_link_train(intel_dp); } else if (type == INTEL_OUTPUT_HDMI) { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); - if (IS_BROXTON(dev)) { - hdmi_level = dev_priv->vbt. - ddi_port_info[port].hdmi_level_shift; - bxt_ddi_vswing_sequence(dev_priv, hdmi_level, port, - INTEL_OUTPUT_HDMI); - } intel_hdmi->set_infoframes(encoder, crtc->config->has_hdmi_sink, &crtc->config->base.adjusted_mode); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 259f2ca57447..20e99a0c5536 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9710,8 +9710,6 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv) val |= PCH_LP_PARTITION_LEVEL_DISABLE; I915_WRITE(SOUTH_DSPCLK_GATE_D, val); } - - intel_prepare_ddi(dev); } static void broxton_modeset_commit_cdclk(struct drm_atomic_state *old_state) @@ -15312,7 +15310,6 @@ void intel_modeset_init_hw(struct drm_device *dev) dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq; - intel_prepare_ddi(dev); intel_init_clock_gating(dev); intel_enable_gt_powersave(dev); } diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 5cb168dc2f0c..6f4762dc5a94 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -184,6 +184,8 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder) intel_mst->port = found->port; if (intel_dp->active_mst_links == 0) { + intel_prepare_ddi_buffer(&intel_dig_port->base); + intel_ddi_clk_select(&intel_dig_port->base, intel_crtc->config); intel_dp_set_link_params(intel_dp, intel_crtc->config); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 32de7e478f8f..e27954d2edad 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1025,7 +1025,7 @@ void intel_crt_init(struct drm_device *dev); /* intel_ddi.c */ void intel_ddi_clk_select(struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config); -void intel_prepare_ddi(struct drm_device *dev); +void intel_prepare_ddi_buffer(struct intel_encoder *encoder); void hsw_fdi_link_train(struct drm_crtc *crtc); void intel_ddi_init(struct drm_device *dev, enum port port); enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder); diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 89a7dd83e91f..bbca527184d0 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -626,7 +626,6 @@ void skl_disable_dc6(struct drm_i915_private *dev_priv) static void skl_set_power_well(struct drm_i915_private *dev_priv, struct i915_power_well *power_well, bool enable) { - struct drm_device *dev = dev_priv->dev; uint32_t tmp, fuse_status; uint32_t req_mask, state_mask; bool is_enabled, enable_requested, check_fuse_status = false; @@ -670,17 +669,6 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv, !I915_READ(HSW_PWR_WELL_BIOS), "Invalid for power well status to be enabled, unless done by the BIOS, \ when request is to disable!\n"); - if (power_well->data == SKL_DISP_PW_2) { - /* - * DDI buffer programming unnecessary during - * driver-load/resume as it's already done - * during modeset initialization then. It's - * also invalid here as encoder list is still - * uninitialized. - */ - if (!dev_priv->power_domains.initializing) - intel_prepare_ddi(dev); - } I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask); } -- cgit v1.2.3 From 7d3fdfff23852fe458a0d0979a3555fe60f1e563 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 11 Jan 2016 20:48:32 +0200 Subject: drm/i915: Cleanup phys status page too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restore the lost phys status page cleanup. Fixes the following splat with DMA_API_DEBUG=y: WARNING: CPU: 0 PID: 21615 at ../lib/dma-debug.c:974 dma_debug_device_change+0x190/0x1f0() pci 0000:00:02.0: DMA-API: device driver has pending DMA allocations while released from device [count=1] One of leaked entries details: [device address=0x0000000023163000] [size=4096 bytes] [mapped with DMA_BIDIRECTIONAL] [mapped as coherent] Modules linked in: i915(-) i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm sha256_generic hmac drbg ctr ccm sch_fq_codel binfmt_misc joydev mousedev arc4 ath5k iTCO_wdt mac80211 smsc_ircc2 ath snd_intel8x0m snd_intel8x0 snd_ac97_codec ac97_bus psmouse snd_pcm input_leds i2c_i801 pcspkr snd_timer cfg80211 snd soundcore i2c_core ehci_pci firewire_ohci ehci_hcd firewire_core lpc_ich 8139too rfkill crc_itu_t mfd_core mii usbcore rng_core intel_agp intel_gtt usb_common agpgart irda crc_ccitt fujitsu_laptop led_class parport_pc video parport evdev backlight CPU: 0 PID: 21615 Comm: rmmod Tainted: G U 4.4.0-rc4-mgm-ovl+ #4 Hardware name: FUJITSU SIEMENS LIFEBOOK S6120/FJNB16C, BIOS Version 1.26 05/10/2004 e31a3de0 e31a3de0 e31a3d9c c128d4bd e31a3dd0 c1045a0c c15e00c4 e31a3dfc 0000546f c15dfad2 000003ce c12b3740 000003ce c12b3740 00000000 00000001 f61fb8a0 e31a3de8 c1045a83 00000009 e31a3de0 c15e00c4 e31a3dfc e31a3e4c Call Trace: [] dump_stack+0x16/0x19 [] warn_slowpath_common+0x8c/0xd0 [] ? dma_debug_device_change+0x190/0x1f0 [] ? dma_debug_device_change+0x190/0x1f0 [] warn_slowpath_fmt+0x33/0x40 [] dma_debug_device_change+0x190/0x1f0 [] notifier_call_chain+0x59/0x70 [] __blocking_notifier_call_chain+0x3f/0x80 [] blocking_notifier_call_chain+0x1f/0x30 [] __device_release_driver+0xc3/0xf0 [] driver_detach+0x97/0xa0 [] bus_remove_driver+0x40/0x90 [] driver_unregister+0x28/0x60 [] ? trace_hardirqs_on_caller+0x12c/0x1d0 [] pci_unregister_driver+0x18/0x80 [] drm_pci_exit+0x87/0xb0 [drm] [] i915_exit+0x1b/0x1ee [i915] [] SyS_delete_module+0x14c/0x210 [] ? trace_hardirqs_on_caller+0x12c/0x1d0 [] ? ____fput+0xd/0x10 [] do_fast_syscall_32+0xa4/0x450 [] sysenter_past_esp+0x3b/0x5d ---[ end trace c2ecbc77760f10a0 ]--- Mapped at: [] debug_dma_alloc_coherent+0x33/0x90 [] drm_pci_alloc+0x18c/0x1e0 [drm] [] intel_init_ring_buffer+0x2af/0x490 [i915] [] intel_init_render_ring_buffer+0x130/0x750 [i915] [] i915_gem_init_rings+0x1e/0x110 [i915] v2: s/BUG_ON/WARN_ON/ since dim doens't like the former anymore Cc: Chris Wilson Fixes: 5c6c600 ("drm/i915: Remove DRI1 ring accessors and API") Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson (v1) Link: http://patchwork.freedesktop.org/patch/msgid/1452538112-5331-1-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 339701d7a9a5..d9e0b400294d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1899,6 +1899,17 @@ i915_dispatch_execbuffer(struct drm_i915_gem_request *req, return 0; } +static void cleanup_phys_status_page(struct intel_engine_cs *ring) +{ + struct drm_i915_private *dev_priv = to_i915(ring->dev); + + if (!dev_priv->status_page_dmah) + return; + + drm_pci_free(ring->dev, dev_priv->status_page_dmah); + ring->status_page.page_addr = NULL; +} + static void cleanup_status_page(struct intel_engine_cs *ring) { struct drm_i915_gem_object *obj; @@ -1915,9 +1926,9 @@ static void cleanup_status_page(struct intel_engine_cs *ring) static int init_status_page(struct intel_engine_cs *ring) { - struct drm_i915_gem_object *obj; + struct drm_i915_gem_object *obj = ring->status_page.obj; - if ((obj = ring->status_page.obj) == NULL) { + if (obj == NULL) { unsigned flags; int ret; @@ -2162,7 +2173,7 @@ static int intel_init_ring_buffer(struct drm_device *dev, if (ret) goto error; } else { - BUG_ON(ring->id != RCS); + WARN_ON(ring->id != RCS); ret = init_phys_status_page(ring); if (ret) goto error; @@ -2208,7 +2219,12 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) if (ring->cleanup) ring->cleanup(ring); - cleanup_status_page(ring); + if (I915_NEED_GFX_HWS(ring->dev)) { + cleanup_status_page(ring); + } else { + WARN_ON(ring->id != RCS); + cleanup_phys_status_page(ring); + } i915_cmd_parser_fini_ring(ring); i915_gem_batch_pool_fini(&ring->batch_pool); -- cgit v1.2.3 From b7792d8b54cc0e66b94d625d70761d086cad1dd3 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 14 Dec 2015 18:23:43 +0200 Subject: drm/i915: Wait for pipe to start before sampling vblank timestamps on gen2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We use the vblank timestamps to generate the vblank frame counter value on gen2. That means we need the pipe scanout position to be accurate when we call drm_crtc_vblank_on(), otherwise the frame counter guesstimate may jump when the pipe actually start. What I observed on my 85x is that the DSL initially reads 0, and when the pipe actually starts DSL jumps to vblank_start. On gen2 DSL==0 means actually vtotal-1 (see update_scanline_offset()), so if we initially get vtotal-1, and then very quickly vblank_start (or thereabouts), the scanout position will appear to jump backwards by approximately one vblank length. Which means the frame counter guesstimate will also jump backwards. That's no good, so let's make sure the pipe has started before we call drm_crtc_vblank_on(). Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1450110229-30450-5-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 20e99a0c5536..9c87d5784f1a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2151,6 +2151,17 @@ static void intel_enable_pipe(struct intel_crtc *crtc) I915_WRITE(reg, val | PIPECONF_ENABLE); POSTING_READ(reg); + + /* + * Until the pipe starts DSL will read as 0, which would cause + * an apparent vblank timestamp jump, which messes up also the + * frame count when it's derived from the timestamps. So let's + * wait for the pipe to start properly before we call + * drm_crtc_vblank_on() + */ + if (dev->max_vblank_count == 0 && + wait_for(intel_get_crtc_scanline(crtc) != crtc->scanline_offset, 50)) + DRM_ERROR("pipe %c didn't start\n", pipe_name(pipe)); } /** -- cgit v1.2.3 From 52b69c849ab4a343e696a0e45d557550f15450a6 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 14 Dec 2015 18:23:46 +0200 Subject: drm/i915: Allow 27 bytes child_dev for VBT <109 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit My 85x has VBT version 108 which has a child dev size of 27 bytes. Let's allow that without printing an error. We still want to reject the actual parsin since for that we need the child device size to be at least 33 bytes. So we should still check for that, but let's make it print a debug message only instead of an error. While at it, toss in a BUILD_BUG_ON() to verify our struct old_child_dev_config is in fact 33 bytes. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1450110229-30450-8-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/intel_bios.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 15ba52bd2538..1de16f21121a 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1157,7 +1157,10 @@ parse_device_mapping(struct drm_i915_private *dev_priv, DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n"); return; } - if (bdb->version < 195) { + if (bdb->version < 109) { + expected_size = 27; + } else if (bdb->version < 195) { + BUILD_BUG_ON(sizeof(struct old_child_dev_config) != 33); expected_size = sizeof(struct old_child_dev_config); } else if (bdb->version == 195) { expected_size = 37; @@ -1170,18 +1173,18 @@ parse_device_mapping(struct drm_i915_private *dev_priv, bdb->version, expected_size); } - /* The legacy sized child device config is the minimum we need. */ - if (p_defs->child_dev_size < sizeof(struct old_child_dev_config)) { - DRM_ERROR("Child device config size %u is too small.\n", - p_defs->child_dev_size); - return; - } - /* Flag an error for unexpected size, but continue anyway. */ if (p_defs->child_dev_size != expected_size) DRM_ERROR("Unexpected child device config size %u (expected %u for VBT version %u)\n", p_defs->child_dev_size, expected_size, bdb->version); + /* The legacy sized child device config is the minimum we need. */ + if (p_defs->child_dev_size < sizeof(struct old_child_dev_config)) { + DRM_DEBUG_KMS("Child device config size %u is too small.\n", + p_defs->child_dev_size); + return; + } + /* get the block size of general definitions */ block_size = get_blocksize(p_defs); /* get the number of child device */ -- cgit v1.2.3 From 7244f309b0fc6508ec585e723ae92057f5bd5855 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 14 Dec 2015 18:23:47 +0200 Subject: drm/i915: Expect child dev size of 22 bytes for VBT < 106 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit My 830 has VBT version 105 with child device size of 22 bytes. Let's assume that's correct and adjust our expectations. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1450110229-30450-9-git-send-email-ville.syrjala@linux.intel.com Acked-by: Jani Nikula --- drivers/gpu/drm/i915/intel_bios.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 1de16f21121a..12e2f8b8bf9c 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1157,7 +1157,9 @@ parse_device_mapping(struct drm_i915_private *dev_priv, DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n"); return; } - if (bdb->version < 109) { + if (bdb->version < 106) { + expected_size = 22; + } else if (bdb->version < 109) { expected_size = 27; } else if (bdb->version < 195) { BUILD_BUG_ON(sizeof(struct old_child_dev_config) != 33); -- cgit v1.2.3 From 9d611c033beeeb8ea914184675058a3c82933f3c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 14 Dec 2015 18:23:49 +0200 Subject: drm/i915: Use MI_BATCH_BUFFER_START on 830/845 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MI_BATCH_BUFFER is nasty since it requires that userspace pass in the correct batch length. Let's switch to using MI_BATCH_BUFFER_START instead (like we do on other platforms). Then we don't have to specify the batch length at all, and the CS will instead execute until it sees the MI_BATCH_BUFFER_END. We still need the batch length since we do the CS TLB workaround and copy the batch into the permanently pinned scratch object and execute it from there. But for this we can simply use the batch object length when the user hasn't specified the actual batch length. So specifying the batch length becomes just a way to optimize the batch copy a little bit. We lost batch_len from a bunch of igts (including the quiesce batch) so without this igt is utterly broken on 830/845. Also some igts such as gem_cpu_reloc never specified the batch_len and so didn't work. With MI_BATCH_BUFFER_START we don't have to fix up igt every time someone forgets that 830/845 exist. Cc: Chris Wilson Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1450110229-30450-11-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 3 +++ drivers/gpu/drm/i915/intel_ringbuffer.c | 6 ++---- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index dccb517361b3..d469c4779ff5 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1309,6 +1309,9 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params, exec_start = params->batch_obj_vm_offset + params->args_batch_start_offset; + if (exec_len == 0) + exec_len = params->batch_obj->base.size; + ret = ring->dispatch_execbuffer(params->request, exec_start, exec_len, params->dispatch_flags); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index d9e0b400294d..4060acf0601a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1865,15 +1865,13 @@ i830_dispatch_execbuffer(struct drm_i915_gem_request *req, offset = cs_offset; } - ret = intel_ring_begin(req, 4); + ret = intel_ring_begin(req, 2); if (ret) return ret; - intel_ring_emit(ring, MI_BATCH_BUFFER); + intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); - intel_ring_emit(ring, offset + len - 8); - intel_ring_emit(ring, MI_NOOP); intel_ring_advance(ring); return 0; -- cgit v1.2.3 From ceccad59100e2b8fa6b2ba38351ba5e730324f0f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 12 Jan 2016 17:28:16 +0200 Subject: drm/i915: Only complain about n_edp_entries with eDP ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 10afa0b65fe2 ("drm/i915: Reject >9 ddi translation entried if port != A/E on SKL") added sanity checks to make sure we don't end up with too many ddi translation values for eDP ports, but it actually failed to check if the port is eDP. We still look up the edp translations for non-eDP ports, but don't use them, so we shouldn't be complaining about them either. Fixes: 10afa0b65fe2 ("drm/i915: Reject >9 ddi translation entried if port != A/E on SKL") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1452612496-9201-1-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 2ed64725470a..25d9e5ccdebd 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -436,8 +436,9 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder) dev_priv->vbt.ddi_port_info[port].dp_boost_level) iboost_bit = 1<<31; - if (WARN_ON(port != PORT_A && - port != PORT_E && n_edp_entries > 9)) + if (WARN_ON(encoder->type == INTEL_OUTPUT_EDP && + port != PORT_A && port != PORT_E && + n_edp_entries > 9)) n_edp_entries = 9; } else if (IS_BROADWELL(dev_priv)) { ddi_translations_fdi = bdw_ddi_translations_fdi; -- cgit v1.2.3 From 0cd1262de7b7509bbbcd650a9918e8895dee6d73 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 12 Jan 2016 07:13:37 -0800 Subject: drm/i915: Handle error paths during watermark sanitization properly (v3) sanitize_watermarks() does not properly handle errors returned by drm_atomic_helper_duplicate_state(). Make failures drop locks before returning. We also change the lock of connection_mutex to a drm_modeset_lock_all_ctx() to make sure any EDEADLK's are handled earlier. v2: Change call to lock connetion_mutex with a call to drm_modeset_lock_all_ctx(). This ensures that any lock contention is handled earlier and drm_atomic_helper_duplicate_state() won't return EDEADLK. (Maarten) v3: Drop locks properly in more error paths. (Maarten) Cc: Daniel Vetter Cc: Maarten Lankhorst Signed-off-by: Matt Roper Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1452611617-32144-1-git-send-email-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/intel_display.c | 9 +++++---- 1 file changed, 5 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 9c87d5784f1a..3b79981735c8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15355,17 +15355,17 @@ static void sanitize_watermarks(struct drm_device *dev) */ drm_modeset_acquire_init(&ctx, 0); retry: - ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx); + ret = drm_modeset_lock_all_ctx(dev, &ctx); if (ret == -EDEADLK) { drm_modeset_backoff(&ctx); goto retry; } else if (WARN_ON(ret)) { - return; + goto fail; } state = drm_atomic_helper_duplicate_state(dev, &ctx); if (WARN_ON(IS_ERR(state))) - return; + goto fail; /* * Hardware readout is the only time we don't want to calculate @@ -15388,7 +15388,7 @@ retry: * BIOS-programmed watermarks untouched and hope for the best. */ WARN(true, "Could not determine valid watermarks for inherited state\n"); - return; + goto fail; } /* Write calculated watermark values back */ @@ -15401,6 +15401,7 @@ retry: } drm_atomic_state_free(state); +fail: drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); } -- cgit v1.2.3 From 1892faa9ec5d51b07d646cbd5597cd30e049aa51 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Mon, 11 Jan 2016 11:39:27 +0000 Subject: drm/i915/gen9: Set PIN_ZONE_4G end to 4GB - 1 page Kernel and userspace are able to handle 4GB (1<<32) address space range, but "A32 Stateless Model" is not. According to documentation, A32 accesses are based on General State Base Address and bound checking is in place. Because size field (instruction State Base Address) limitation, it is not possible to address full 4GB memory region. A32 Stateless Model is used by some libraries and without this patch, the last page of 4GB address space is not accessible in 32bit processes. Reported-by: Artur Harasimiuk Signed-off-by: Michel Thierry Link: http://patchwork.freedesktop.org/patch/msgid/1452512367-23614-1-git-send-email-michel.thierry@intel.com Cc: drm-intel-fixes@lists.freedesktop.org Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d8efc9dfbc48..2c24ff394b2a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3484,7 +3484,7 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, if (flags & PIN_MAPPABLE) end = min_t(u64, end, dev_priv->gtt.mappable_end); if (flags & PIN_ZONE_4G) - end = min_t(u64, end, (1ULL << 32)); + end = min_t(u64, end, (1ULL << 32) - PAGE_SIZE); if (alignment == 0) alignment = flags & PIN_MAPPABLE ? fence_alignment : -- cgit v1.2.3 From e32192e1ae9884200ee340e7c839bf24f4f1f928 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 12 Jan 2016 16:04:06 +0000 Subject: drm/i915/gen8: Tidy display interrupt processing One bugfix and a few tidy-ups: * Pipe fault logging was broken on Gen9+. * Removed some unnecessary local variables. * Removed unnecessary initializers. * Decreased pipe iir block indentation level. * Grouped variable initialization close to use sites. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1452614647-13973-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_irq.c | 131 ++++++++++++++++++++-------------------- 1 file changed, 67 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index f04d799153ca..7972ceee6096 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2268,11 +2268,9 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) { struct drm_device *dev = arg; struct drm_i915_private *dev_priv = dev->dev_private; - u32 master_ctl; + u32 master_ctl, iir; irqreturn_t ret = IRQ_NONE; - uint32_t tmp = 0; enum pipe pipe; - u32 aux_mask = GEN8_AUX_CHANNEL_A; if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; @@ -2280,10 +2278,6 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) /* IRQs are synced during runtime_suspend, we don't require a wakeref */ disable_rpm_wakeref_asserts(dev_priv); - if (INTEL_INFO(dev_priv)->gen >= 9) - aux_mask |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C | - GEN9_AUX_CHANNEL_D; - master_ctl = I915_READ_FW(GEN8_MASTER_IRQ); master_ctl &= ~GEN8_MASTER_IRQ_CONTROL; if (!master_ctl) @@ -2296,11 +2290,11 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) ret = gen8_gt_irq_handler(dev_priv, master_ctl); if (master_ctl & GEN8_DE_MISC_IRQ) { - tmp = I915_READ(GEN8_DE_MISC_IIR); - if (tmp) { - I915_WRITE(GEN8_DE_MISC_IIR, tmp); + iir = I915_READ(GEN8_DE_MISC_IIR); + if (iir) { + I915_WRITE(GEN8_DE_MISC_IIR, iir); ret = IRQ_HANDLED; - if (tmp & GEN8_DE_MISC_GSE) + if (iir & GEN8_DE_MISC_GSE) intel_opregion_asle_intr(dev); else DRM_ERROR("Unexpected DE Misc interrupt\n"); @@ -2310,33 +2304,40 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) } if (master_ctl & GEN8_DE_PORT_IRQ) { - tmp = I915_READ(GEN8_DE_PORT_IIR); - if (tmp) { + iir = I915_READ(GEN8_DE_PORT_IIR); + if (iir) { + u32 tmp_mask; bool found = false; - u32 hotplug_trigger = 0; - - if (IS_BROXTON(dev_priv)) - hotplug_trigger = tmp & BXT_DE_PORT_HOTPLUG_MASK; - else if (IS_BROADWELL(dev_priv)) - hotplug_trigger = tmp & GEN8_PORT_DP_A_HOTPLUG; - I915_WRITE(GEN8_DE_PORT_IIR, tmp); + I915_WRITE(GEN8_DE_PORT_IIR, iir); ret = IRQ_HANDLED; - if (tmp & aux_mask) { + tmp_mask = GEN8_AUX_CHANNEL_A; + if (INTEL_INFO(dev_priv)->gen >= 9) + tmp_mask |= GEN9_AUX_CHANNEL_B | + GEN9_AUX_CHANNEL_C | + GEN9_AUX_CHANNEL_D; + + if (iir & tmp_mask) { dp_aux_irq_handler(dev); found = true; } - if (hotplug_trigger) { - if (IS_BROXTON(dev)) - bxt_hpd_irq_handler(dev, hotplug_trigger, hpd_bxt); - else - ilk_hpd_irq_handler(dev, hotplug_trigger, hpd_bdw); - found = true; + if (IS_BROXTON(dev_priv)) { + tmp_mask = iir & BXT_DE_PORT_HOTPLUG_MASK; + if (tmp_mask) { + bxt_hpd_irq_handler(dev, tmp_mask, hpd_bxt); + found = true; + } + } else if (IS_BROADWELL(dev_priv)) { + tmp_mask = iir & GEN8_PORT_DP_A_HOTPLUG; + if (tmp_mask) { + ilk_hpd_irq_handler(dev, tmp_mask, hpd_bdw); + found = true; + } } - if (IS_BROXTON(dev) && (tmp & BXT_DE_PORT_GMBUS)) { + if (IS_BROXTON(dev) && (iir & BXT_DE_PORT_GMBUS)) { gmbus_irq_handler(dev); found = true; } @@ -2349,49 +2350,51 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) } for_each_pipe(dev_priv, pipe) { - uint32_t pipe_iir, flip_done = 0, fault_errors = 0; + u32 flip_done, fault_errors; if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe))) continue; - pipe_iir = I915_READ(GEN8_DE_PIPE_IIR(pipe)); - if (pipe_iir) { - ret = IRQ_HANDLED; - I915_WRITE(GEN8_DE_PIPE_IIR(pipe), pipe_iir); + iir = I915_READ(GEN8_DE_PIPE_IIR(pipe)); + if (!iir) { + DRM_ERROR("The master control interrupt lied (DE PIPE)!\n"); + continue; + } - if (pipe_iir & GEN8_PIPE_VBLANK && - intel_pipe_handle_vblank(dev, pipe)) - intel_check_page_flip(dev, pipe); + ret = IRQ_HANDLED; + I915_WRITE(GEN8_DE_PIPE_IIR(pipe), iir); - if (INTEL_INFO(dev_priv)->gen >= 9) - flip_done = pipe_iir & GEN9_PIPE_PLANE1_FLIP_DONE; - else - flip_done = pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE; + if (iir & GEN8_PIPE_VBLANK && + intel_pipe_handle_vblank(dev, pipe)) + intel_check_page_flip(dev, pipe); - if (flip_done) { - intel_prepare_page_flip(dev, pipe); - intel_finish_page_flip_plane(dev, pipe); - } + flip_done = iir; + if (INTEL_INFO(dev_priv)->gen >= 9) + flip_done &= GEN9_PIPE_PLANE1_FLIP_DONE; + else + flip_done &= GEN8_PIPE_PRIMARY_FLIP_DONE; - if (pipe_iir & GEN8_PIPE_CDCLK_CRC_DONE) - hsw_pipe_crc_irq_handler(dev, pipe); + if (flip_done) { + intel_prepare_page_flip(dev, pipe); + intel_finish_page_flip_plane(dev, pipe); + } - if (pipe_iir & GEN8_PIPE_FIFO_UNDERRUN) - intel_cpu_fifo_underrun_irq_handler(dev_priv, - pipe); + if (iir & GEN8_PIPE_CDCLK_CRC_DONE) + hsw_pipe_crc_irq_handler(dev, pipe); + if (iir & GEN8_PIPE_FIFO_UNDERRUN) + intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); - if (INTEL_INFO(dev_priv)->gen >= 9) - fault_errors = pipe_iir & GEN9_DE_PIPE_IRQ_FAULT_ERRORS; - else - fault_errors = pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS; + fault_errors = iir; + if (INTEL_INFO(dev_priv)->gen >= 9) + fault_errors &= GEN9_DE_PIPE_IRQ_FAULT_ERRORS; + else + fault_errors &= GEN8_DE_PIPE_IRQ_FAULT_ERRORS; - if (fault_errors) - DRM_ERROR("Fault errors on pipe %c\n: 0x%08x", - pipe_name(pipe), - pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS); - } else - DRM_ERROR("The master control interrupt lied (DE PIPE)!\n"); + if (fault_errors) + DRM_ERROR("Fault errors on pipe %c\n: 0x%08x", + pipe_name(pipe), + fault_errors); } if (HAS_PCH_SPLIT(dev) && !HAS_PCH_NOP(dev) && @@ -2401,15 +2404,15 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) * scheme also closed the SDE interrupt handling race we've seen * on older pch-split platforms. But this needs testing. */ - u32 pch_iir = I915_READ(SDEIIR); - if (pch_iir) { - I915_WRITE(SDEIIR, pch_iir); + iir = I915_READ(SDEIIR); + if (iir) { + I915_WRITE(SDEIIR, iir); ret = IRQ_HANDLED; if (HAS_PCH_SPT(dev_priv)) - spt_irq_handler(dev, pch_iir); + spt_irq_handler(dev, iir); else - cpt_irq_handler(dev, pch_iir); + cpt_irq_handler(dev, iir); } else { /* * Like on previous PCH there seems to be something -- cgit v1.2.3 From f11a0f46a2c32207a47322610ae4b214b5bab23e Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 12 Jan 2016 16:04:07 +0000 Subject: drm/i915/gen8: Factor out display interrupt handling Tidy quite long interrupt service routine by factoring out the display part. This simplifies the exit path a little bit, makes the code a bit more readable, and potentialy makes code reuse in the future easier. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1452614647-13973-2-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_irq.c | 53 ++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 7972ceee6096..25a89373df63 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2264,31 +2264,14 @@ static void bxt_hpd_irq_handler(struct drm_device *dev, u32 hotplug_trigger, intel_hpd_irq_handler(dev, pin_mask, long_mask); } -static irqreturn_t gen8_irq_handler(int irq, void *arg) +static irqreturn_t +gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) { - struct drm_device *dev = arg; - struct drm_i915_private *dev_priv = dev->dev_private; - u32 master_ctl, iir; + struct drm_device *dev = dev_priv->dev; irqreturn_t ret = IRQ_NONE; + u32 iir; enum pipe pipe; - if (!intel_irqs_enabled(dev_priv)) - return IRQ_NONE; - - /* IRQs are synced during runtime_suspend, we don't require a wakeref */ - disable_rpm_wakeref_asserts(dev_priv); - - master_ctl = I915_READ_FW(GEN8_MASTER_IRQ); - master_ctl &= ~GEN8_MASTER_IRQ_CONTROL; - if (!master_ctl) - goto out; - - I915_WRITE_FW(GEN8_MASTER_IRQ, 0); - - /* Find, clear, then process each source of interrupt */ - - ret = gen8_gt_irq_handler(dev_priv, master_ctl); - if (master_ctl & GEN8_DE_MISC_IRQ) { iir = I915_READ(GEN8_DE_MISC_IIR); if (iir) { @@ -2422,10 +2405,36 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) } } + return ret; +} + +static irqreturn_t gen8_irq_handler(int irq, void *arg) +{ + struct drm_device *dev = arg; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 master_ctl; + irqreturn_t ret; + + if (!intel_irqs_enabled(dev_priv)) + return IRQ_NONE; + + master_ctl = I915_READ_FW(GEN8_MASTER_IRQ); + master_ctl &= ~GEN8_MASTER_IRQ_CONTROL; + if (!master_ctl) + return IRQ_NONE; + + I915_WRITE_FW(GEN8_MASTER_IRQ, 0); + + /* IRQs are synced during runtime_suspend, we don't require a wakeref */ + disable_rpm_wakeref_asserts(dev_priv); + + /* Find, clear, then process each source of interrupt */ + ret = gen8_gt_irq_handler(dev_priv, master_ctl); + ret |= gen8_de_irq_handler(dev_priv, master_ctl); + I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); POSTING_READ_FW(GEN8_MASTER_IRQ); -out: enable_rpm_wakeref_asserts(dev_priv); return ret; -- cgit v1.2.3 From c9cacf9349ae4ce516627dac931766bfe98df793 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 12 Jan 2016 17:32:34 +0000 Subject: drm/i915: Extract vfunc setup from logical ring initializers Majority of them was duplicated code and only render ring currently overrides some of them. We can save some lines of code and also take away the confusion on why bsd2 did not do the seqno coherency workaround. (VCS2 ring does not exist on platforms where workaround is needed but that was not documented in the code.) Signed-off-by: Tvrtko Ursulin Cc: Chris Wilson Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1452619956-27014-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/intel_lrc.c | 88 +++++++++++++--------------------------- 1 file changed, 29 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index ab344e0b878c..e29cf1c73745 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1942,7 +1942,28 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *ring) ring->dev = NULL; } -static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *ring) +static void +logical_ring_default_vfuncs(struct drm_device *dev, + struct intel_engine_cs *ring) +{ + /* Default vfuncs which can be overriden by each engine. */ + ring->init_hw = gen8_init_common_ring; + ring->emit_request = gen8_emit_request; + ring->emit_flush = gen8_emit_flush; + ring->irq_get = gen8_logical_ring_get_irq; + ring->irq_put = gen8_logical_ring_put_irq; + ring->emit_bb_start = gen8_emit_bb_start; + if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { + ring->get_seqno = bxt_a_get_seqno; + ring->set_seqno = bxt_a_set_seqno; + } else { + ring->get_seqno = gen8_get_seqno; + ring->set_seqno = gen8_set_seqno; + } +} + +static int +logical_ring_init(struct drm_device *dev, struct intel_engine_cs *ring) { int ret; @@ -2003,24 +2024,16 @@ static int logical_render_ring_init(struct drm_device *dev) if (HAS_L3_DPF(dev)) ring->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT; + logical_ring_default_vfuncs(dev, ring); + + /* Override some for render ring. */ if (INTEL_INFO(dev)->gen >= 9) ring->init_hw = gen9_init_render_ring; else ring->init_hw = gen8_init_render_ring; ring->init_context = gen8_init_rcs_context; ring->cleanup = intel_fini_pipe_control; - if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { - ring->get_seqno = bxt_a_get_seqno; - ring->set_seqno = bxt_a_set_seqno; - } else { - ring->get_seqno = gen8_get_seqno; - ring->set_seqno = gen8_set_seqno; - } - ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush_render; - ring->irq_get = gen8_logical_ring_get_irq; - ring->irq_put = gen8_logical_ring_put_irq; - ring->emit_bb_start = gen8_emit_bb_start; ring->dev = dev; @@ -2060,19 +2073,7 @@ static int logical_bsd_ring_init(struct drm_device *dev) ring->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; - ring->init_hw = gen8_init_common_ring; - if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { - ring->get_seqno = bxt_a_get_seqno; - ring->set_seqno = bxt_a_set_seqno; - } else { - ring->get_seqno = gen8_get_seqno; - ring->set_seqno = gen8_set_seqno; - } - ring->emit_request = gen8_emit_request; - ring->emit_flush = gen8_emit_flush; - ring->irq_get = gen8_logical_ring_get_irq; - ring->irq_put = gen8_logical_ring_put_irq; - ring->emit_bb_start = gen8_emit_bb_start; + logical_ring_default_vfuncs(dev, ring); return logical_ring_init(dev, ring); } @@ -2090,14 +2091,7 @@ static int logical_bsd2_ring_init(struct drm_device *dev) ring->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; - ring->init_hw = gen8_init_common_ring; - ring->get_seqno = gen8_get_seqno; - ring->set_seqno = gen8_set_seqno; - ring->emit_request = gen8_emit_request; - ring->emit_flush = gen8_emit_flush; - ring->irq_get = gen8_logical_ring_get_irq; - ring->irq_put = gen8_logical_ring_put_irq; - ring->emit_bb_start = gen8_emit_bb_start; + logical_ring_default_vfuncs(dev, ring); return logical_ring_init(dev, ring); } @@ -2115,19 +2109,7 @@ static int logical_blt_ring_init(struct drm_device *dev) ring->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT; - ring->init_hw = gen8_init_common_ring; - if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { - ring->get_seqno = bxt_a_get_seqno; - ring->set_seqno = bxt_a_set_seqno; - } else { - ring->get_seqno = gen8_get_seqno; - ring->set_seqno = gen8_set_seqno; - } - ring->emit_request = gen8_emit_request; - ring->emit_flush = gen8_emit_flush; - ring->irq_get = gen8_logical_ring_get_irq; - ring->irq_put = gen8_logical_ring_put_irq; - ring->emit_bb_start = gen8_emit_bb_start; + logical_ring_default_vfuncs(dev, ring); return logical_ring_init(dev, ring); } @@ -2145,19 +2127,7 @@ static int logical_vebox_ring_init(struct drm_device *dev) ring->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT; - ring->init_hw = gen8_init_common_ring; - if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { - ring->get_seqno = bxt_a_get_seqno; - ring->set_seqno = bxt_a_set_seqno; - } else { - ring->get_seqno = gen8_get_seqno; - ring->set_seqno = gen8_set_seqno; - } - ring->emit_request = gen8_emit_request; - ring->emit_flush = gen8_emit_flush; - ring->irq_get = gen8_logical_ring_get_irq; - ring->irq_put = gen8_logical_ring_put_irq; - ring->emit_bb_start = gen8_emit_bb_start; + logical_ring_default_vfuncs(dev, ring); return logical_ring_init(dev, ring); } -- cgit v1.2.3 From d9f3af96c2426bbe5b71b8875ee0ce3a01065c33 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 12 Jan 2016 17:32:35 +0000 Subject: drm/i915: Compact logical ring interrupt initialization Identically to vfuncs interrupt mask initialization can also be compacted for more readable code. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1452619956-27014-2-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/intel_lrc.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index e29cf1c73745..4a6ba0a4aa3d 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1962,6 +1962,13 @@ logical_ring_default_vfuncs(struct drm_device *dev, } } +static inline void +logical_ring_default_irqs(struct intel_engine_cs *ring, unsigned shift) +{ + ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT << shift; + ring->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift; +} + static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *ring) { @@ -2017,10 +2024,8 @@ static int logical_render_ring_init(struct drm_device *dev) ring->name = "render ring"; ring->id = RCS; ring->mmio_base = RENDER_RING_BASE; - ring->irq_enable_mask = - GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT; - ring->irq_keep_mask = - GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT; + + logical_ring_default_irqs(ring, GEN8_RCS_IRQ_SHIFT); if (HAS_L3_DPF(dev)) ring->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT; @@ -2068,11 +2073,8 @@ static int logical_bsd_ring_init(struct drm_device *dev) ring->name = "bsd ring"; ring->id = VCS; ring->mmio_base = GEN6_BSD_RING_BASE; - ring->irq_enable_mask = - GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; - ring->irq_keep_mask = - GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; + logical_ring_default_irqs(ring, GEN8_VCS1_IRQ_SHIFT); logical_ring_default_vfuncs(dev, ring); return logical_ring_init(dev, ring); @@ -2086,11 +2088,8 @@ static int logical_bsd2_ring_init(struct drm_device *dev) ring->name = "bds2 ring"; ring->id = VCS2; ring->mmio_base = GEN8_BSD2_RING_BASE; - ring->irq_enable_mask = - GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; - ring->irq_keep_mask = - GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; + logical_ring_default_irqs(ring, GEN8_VCS2_IRQ_SHIFT); logical_ring_default_vfuncs(dev, ring); return logical_ring_init(dev, ring); @@ -2104,11 +2103,8 @@ static int logical_blt_ring_init(struct drm_device *dev) ring->name = "blitter ring"; ring->id = BCS; ring->mmio_base = BLT_RING_BASE; - ring->irq_enable_mask = - GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; - ring->irq_keep_mask = - GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT; + logical_ring_default_irqs(ring, GEN8_BCS_IRQ_SHIFT); logical_ring_default_vfuncs(dev, ring); return logical_ring_init(dev, ring); @@ -2122,11 +2118,8 @@ static int logical_vebox_ring_init(struct drm_device *dev) ring->name = "video enhancement ring"; ring->id = VECS; ring->mmio_base = VEBOX_RING_BASE; - ring->irq_enable_mask = - GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT; - ring->irq_keep_mask = - GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT; + logical_ring_default_irqs(ring, GEN8_VECS_IRQ_SHIFT); logical_ring_default_vfuncs(dev, ring); return logical_ring_init(dev, ring); -- cgit v1.2.3 From ec8a9776cc5c98decbc905c9fa4a885564b7a7c3 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 12 Jan 2016 17:32:36 +0000 Subject: drm/i915: Fix bsd2 ring name Chris Wilson noticed the "bds2" typo. Signed-off-by: Tvrtko Ursulin Cc: Chris Wilson Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1452619956-27014-3-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/intel_lrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 4a6ba0a4aa3d..5027699c5291 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -2085,7 +2085,7 @@ static int logical_bsd2_ring_init(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *ring = &dev_priv->ring[VCS2]; - ring->name = "bds2 ring"; + ring->name = "bsd2 ring"; ring->id = VCS2; ring->mmio_base = GEN8_BSD2_RING_BASE; -- cgit v1.2.3 From 657fb5fbadb3ef286ababaf6809d5594767d8063 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 13 Jan 2016 22:48:40 +0800 Subject: drm/i915: use kobj_to_dev() Use kobj_to_dev() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/f5db8b56cd177972c901d01aa87ba763735438a9.1452696179.git.geliangtang@163.com --- drivers/gpu/drm/i915/i915_sysfs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 37e3f0ddf8e0..c6188dddb341 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -164,7 +164,7 @@ i915_l3_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t offset, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct drm_minor *dminor = dev_to_drm_minor(dev); struct drm_device *drm_dev = dminor->dev; struct drm_i915_private *dev_priv = drm_dev->dev_private; @@ -200,7 +200,7 @@ i915_l3_write(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t offset, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct drm_minor *dminor = dev_to_drm_minor(dev); struct drm_device *drm_dev = dminor->dev; struct drm_i915_private *dev_priv = drm_dev->dev_private; @@ -521,7 +521,7 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj, loff_t off, size_t count) { - struct device *kdev = container_of(kobj, struct device, kobj); + struct device *kdev = kobj_to_dev(kobj); struct drm_minor *minor = dev_to_drm_minor(kdev); struct drm_device *dev = minor->dev; struct i915_error_state_file_priv error_priv; @@ -556,7 +556,7 @@ static ssize_t error_state_write(struct file *file, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *kdev = container_of(kobj, struct device, kobj); + struct device *kdev = kobj_to_dev(kobj); struct drm_minor *minor = dev_to_drm_minor(kdev); struct drm_device *dev = minor->dev; int ret; -- cgit v1.2.3 From b5c653384f84b0ccb97e9cf942b6e8ed759221bf Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 12 Jan 2016 21:08:31 +0200 Subject: drm/i915: Pass modifier instead of tiling_mode to gen4_compute_page_offset() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for handling more than X tiling, pass the fb modifier to gen4_compute_page_offset() instead of the obj->tiling_mode. Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1452625717-9713-2-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 12 ++++++------ drivers/gpu/drm/i915/intel_drv.h | 4 ++-- drivers/gpu/drm/i915/intel_sprite.c | 21 ++++++++++----------- 3 files changed, 18 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3b79981735c8..e39c724aca89 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2449,11 +2449,11 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb, * is assumed to be a power-of-two. */ unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv, int *x, int *y, - unsigned int tiling_mode, + uint64_t fb_modifier, unsigned int cpp, unsigned int pitch) { - if (tiling_mode != I915_TILING_NONE) { + if (fb_modifier != DRM_FORMAT_MOD_NONE) { unsigned int tile_rows, tiles; tile_rows = *y / 8; @@ -2769,8 +2769,8 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, if (INTEL_INFO(dev)->gen >= 4) { intel_crtc->dspaddr_offset = - intel_gen4_compute_page_offset(dev_priv, - &x, &y, obj->tiling_mode, + intel_gen4_compute_page_offset(dev_priv, &x, &y, + fb->modifier[0], pixel_size, fb->pitches[0]); linear_offset -= intel_crtc->dspaddr_offset; @@ -2877,8 +2877,8 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, linear_offset = y * fb->pitches[0] + x * pixel_size; intel_crtc->dspaddr_offset = - intel_gen4_compute_page_offset(dev_priv, - &x, &y, obj->tiling_mode, + intel_gen4_compute_page_offset(dev_priv, &x, &y, + fb->modifier[0], pixel_size, fb->pitches[0]); linear_offset -= intel_crtc->dspaddr_offset; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index e27954d2edad..015538287171 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1198,8 +1198,8 @@ void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state); #define assert_pipe_disabled(d, p) assert_pipe(d, p, false) unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv, int *x, int *y, - unsigned int tiling_mode, - unsigned int bpp, + uint64_t fb_modifier, + unsigned int cpp, unsigned int pitch); void intel_prepare_reset(struct drm_device *dev); void intel_finish_reset(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 73dfb38886b9..3c596c9f0305 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -422,9 +422,8 @@ vlv_update_plane(struct drm_plane *dplane, crtc_h--; linear_offset = y * fb->pitches[0] + x * pixel_size; - sprsurf_offset = intel_gen4_compute_page_offset(dev_priv, - &x, &y, - obj->tiling_mode, + sprsurf_offset = intel_gen4_compute_page_offset(dev_priv, &x, &y, + fb->modifier[0], pixel_size, fb->pitches[0]); linear_offset -= sprsurf_offset; @@ -557,10 +556,10 @@ ivb_update_plane(struct drm_plane *plane, sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; linear_offset = y * fb->pitches[0] + x * pixel_size; - sprsurf_offset = - intel_gen4_compute_page_offset(dev_priv, - &x, &y, obj->tiling_mode, - pixel_size, fb->pitches[0]); + sprsurf_offset = intel_gen4_compute_page_offset(dev_priv, &x, &y, + fb->modifier[0], + pixel_size, + fb->pitches[0]); linear_offset -= sprsurf_offset; if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { @@ -696,10 +695,10 @@ ilk_update_plane(struct drm_plane *plane, dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; linear_offset = y * fb->pitches[0] + x * pixel_size; - dvssurf_offset = - intel_gen4_compute_page_offset(dev_priv, - &x, &y, obj->tiling_mode, - pixel_size, fb->pitches[0]); + dvssurf_offset = intel_gen4_compute_page_offset(dev_priv, &x, &y, + fb->modifier[0], + pixel_size, + fb->pitches[0]); linear_offset -= dvssurf_offset; if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { -- cgit v1.2.3 From 7b49f94839660a82f1f40ee95cfe70245b4444d7 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 12 Jan 2016 21:08:32 +0200 Subject: drm/i915: Factor out intel_tile_width() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull the tile width calculations from intel_fb_stride_alignment() into a new function intel_tile_width(). Also take the opportunity to pass aroun dev_priv instead of dev to intel_fb_stride_alignment(). v2: Reorder argumnents to be more consistent with other functions Change intel_fb_stride_alignment() to accept dev_priv instead of dev v3: Deal with Y tilling (Daniel) Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1452625717-9713-3-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 85 +++++++++++++++++++++--------------- drivers/gpu/drm/i915/intel_drv.h | 4 +- drivers/gpu/drm/i915/intel_sprite.c | 2 +- 3 files changed, 54 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e39c724aca89..d86e47a9cf6f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2223,6 +2223,43 @@ static bool need_vtd_wa(struct drm_device *dev) return false; } +static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv, + uint64_t fb_modifier, unsigned int cpp) +{ + switch (fb_modifier) { + case DRM_FORMAT_MOD_NONE: + return cpp; + case I915_FORMAT_MOD_X_TILED: + if (IS_GEN2(dev_priv)) + return 128; + else + return 512; + case I915_FORMAT_MOD_Y_TILED: + if (IS_GEN2(dev_priv) || HAS_128_BYTE_Y_TILING(dev_priv)) + return 128; + else + return 512; + case I915_FORMAT_MOD_Yf_TILED: + switch (cpp) { + case 1: + return 64; + case 2: + case 4: + return 128; + case 8: + case 16: + return 256; + default: + MISSING_CASE(cpp); + return cpp; + } + break; + default: + MISSING_CASE(fb_modifier); + return cpp; + } +} + unsigned int intel_tile_height(struct drm_device *dev, uint32_t pixel_format, uint64_t fb_format_modifier, unsigned int plane) @@ -2914,37 +2951,15 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, POSTING_READ(reg); } -u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier, - uint32_t pixel_format) +u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv, + uint64_t fb_modifier, uint32_t pixel_format) { - u32 bits_per_pixel = drm_format_plane_cpp(pixel_format, 0) * 8; - - /* - * The stride is either expressed as a multiple of 64 bytes - * chunks for linear buffers or in number of tiles for tiled - * buffers. - */ - switch (fb_modifier) { - case DRM_FORMAT_MOD_NONE: - return 64; - case I915_FORMAT_MOD_X_TILED: - if (INTEL_INFO(dev)->gen == 2) - return 128; - return 512; - case I915_FORMAT_MOD_Y_TILED: - /* No need to check for old gens and Y tiling since this is - * about the display engine and those will be blocked before - * we get here. - */ - return 128; - case I915_FORMAT_MOD_Yf_TILED: - if (bits_per_pixel == 8) - return 64; - else - return 128; - default: - MISSING_CASE(fb_modifier); + if (fb_modifier == DRM_FORMAT_MOD_NONE) { return 64; + } else { + int cpp = drm_format_plane_cpp(pixel_format, 0); + + return intel_tile_width(dev_priv, fb_modifier, cpp); } } @@ -3118,7 +3133,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane, plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE; plane_ctl |= skl_plane_ctl_rotation(rotation); - stride_div = intel_fb_stride_alignment(dev, fb->modifier[0], + stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0], fb->pixel_format); surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0); @@ -9305,7 +9320,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, fb->width = ((val >> 0) & 0x1fff) + 1; val = I915_READ(PLANE_STRIDE(pipe, 0)); - stride_mult = intel_fb_stride_alignment(dev, fb->modifier[0], + stride_mult = intel_fb_stride_alignment(dev_priv, fb->modifier[0], fb->pixel_format); fb->pitches[0] = (val & 0x3ff) * stride_mult; @@ -11391,8 +11406,8 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc, stride = DIV_ROUND_UP(fb->height, tile_height); } else { stride = fb->pitches[0] / - intel_fb_stride_alignment(dev, fb->modifier[0], - fb->pixel_format); + intel_fb_stride_alignment(dev_priv, fb->modifier[0], + fb->pixel_format); } /* @@ -14776,6 +14791,7 @@ static int intel_framebuffer_init(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_i915_gem_object *obj) { + struct drm_i915_private *dev_priv = to_i915(dev); unsigned int aligned_height; int ret; u32 pitch_limit, stride_alignment; @@ -14817,7 +14833,8 @@ static int intel_framebuffer_init(struct drm_device *dev, return -EINVAL; } - stride_alignment = intel_fb_stride_alignment(dev, mode_cmd->modifier[0], + stride_alignment = intel_fb_stride_alignment(dev_priv, + mode_cmd->modifier[0], mode_cmd->pixel_format); if (mode_cmd->pitches[0] & (stride_alignment - 1)) { DRM_DEBUG("pitch (%d) must be at least %u byte aligned\n", diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 015538287171..9a8075b785ac 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1070,8 +1070,8 @@ unsigned int intel_fb_align_height(struct drm_device *dev, uint64_t fb_format_modifier); void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire, enum fb_op_origin origin); -u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier, - uint32_t pixel_format); +u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv, + uint64_t fb_modifier, uint32_t pixel_format); /* intel_audio.c */ void intel_init_audio(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 3c596c9f0305..766c33ad0309 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -216,7 +216,7 @@ skl_update_plane(struct drm_plane *drm_plane, rotation = plane_state->base.rotation; plane_ctl |= skl_plane_ctl_rotation(rotation); - stride_div = intel_fb_stride_alignment(dev, fb->modifier[0], + stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0], fb->pixel_format); /* Sizes are 0 based */ -- cgit v1.2.3 From 832be82f87c2bf711d8d7aaeb59da925b4573f6c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 12 Jan 2016 21:08:33 +0200 Subject: drm/i915: Redo intel_tile_height() as intel_tile_size() / intel_tile_width() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I find more usual to think about tile widths than heights, so changing the intel_tile_height() to calculate the tile height as tile_size/tile_width is easier than the opposite to the poor brain. v2: Reorder arguments for consistency Constify dev_priv arguments Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1452625717-9713-4-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 89 ++++++++++++------------------------ drivers/gpu/drm/i915/intel_drv.h | 5 +- drivers/gpu/drm/i915/intel_sprite.c | 5 +- 3 files changed, 34 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d86e47a9cf6f..9c20c2ee742f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2223,6 +2223,11 @@ static bool need_vtd_wa(struct drm_device *dev) return false; } +static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv) +{ + return IS_GEN2(dev_priv) ? 2048 : 4096; +} + static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv, uint64_t fb_modifier, unsigned int cpp) { @@ -2260,67 +2265,34 @@ static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv, } } -unsigned int -intel_tile_height(struct drm_device *dev, uint32_t pixel_format, - uint64_t fb_format_modifier, unsigned int plane) +unsigned int intel_tile_height(const struct drm_i915_private *dev_priv, + uint64_t fb_modifier, unsigned int cpp) { - unsigned int tile_height; - uint32_t pixel_bytes; - - switch (fb_format_modifier) { - case DRM_FORMAT_MOD_NONE: - tile_height = 1; - break; - case I915_FORMAT_MOD_X_TILED: - tile_height = IS_GEN2(dev) ? 16 : 8; - break; - case I915_FORMAT_MOD_Y_TILED: - tile_height = 32; - break; - case I915_FORMAT_MOD_Yf_TILED: - pixel_bytes = drm_format_plane_cpp(pixel_format, plane); - switch (pixel_bytes) { - default: - case 1: - tile_height = 64; - break; - case 2: - case 4: - tile_height = 32; - break; - case 8: - tile_height = 16; - break; - case 16: - WARN_ONCE(1, - "128-bit pixels are not supported for display!"); - tile_height = 16; - break; - } - break; - default: - MISSING_CASE(fb_format_modifier); - tile_height = 1; - break; - } - - return tile_height; + if (fb_modifier == DRM_FORMAT_MOD_NONE) + return 1; + else + return intel_tile_size(dev_priv) / + intel_tile_width(dev_priv, fb_modifier, cpp); } unsigned int intel_fb_align_height(struct drm_device *dev, unsigned int height, - uint32_t pixel_format, uint64_t fb_format_modifier) + uint32_t pixel_format, uint64_t fb_modifier) { - return ALIGN(height, intel_tile_height(dev, pixel_format, - fb_format_modifier, 0)); + unsigned int cpp = drm_format_plane_cpp(pixel_format, 0); + unsigned int tile_height = intel_tile_height(to_i915(dev), fb_modifier, cpp); + + return ALIGN(height, tile_height); } static void intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, const struct drm_plane_state *plane_state) { + struct drm_i915_private *dev_priv = to_i915(fb->dev); struct intel_rotation_info *info = &view->params.rotation_info; unsigned int tile_height, tile_pitch; + unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0); *view = i915_ggtt_view_normal; @@ -2338,22 +2310,19 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, info->uv_offset = fb->offsets[1]; info->fb_modifier = fb->modifier[0]; - tile_height = intel_tile_height(fb->dev, fb->pixel_format, - fb->modifier[0], 0); + tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp); tile_pitch = PAGE_SIZE / tile_height; info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_pitch); info->height_pages = DIV_ROUND_UP(fb->height, tile_height); info->size = info->width_pages * info->height_pages * PAGE_SIZE; if (info->pixel_format == DRM_FORMAT_NV12) { - tile_height = intel_tile_height(fb->dev, fb->pixel_format, - fb->modifier[0], 1); + cpp = drm_format_plane_cpp(fb->pixel_format, 1); + tile_height = intel_tile_height(dev_priv, fb->modifier[1], cpp); tile_pitch = PAGE_SIZE / tile_height; - info->width_pages_uv = DIV_ROUND_UP(fb->pitches[0], tile_pitch); - info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, - tile_height); - info->size_uv = info->width_pages_uv * info->height_pages_uv * - PAGE_SIZE; + info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_pitch); + info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height); + info->size_uv = info->width_pages_uv * info->height_pages_uv * PAGE_SIZE; } } @@ -3140,9 +3109,10 @@ static void skylake_update_primary_plane(struct drm_plane *plane, WARN_ON(drm_rect_width(&plane_state->src) == 0); if (intel_rotation_90_or_270(rotation)) { + int cpp = drm_format_plane_cpp(fb->pixel_format, 0); + /* stride = Surface height in tiles */ - tile_height = intel_tile_height(dev, fb->pixel_format, - fb->modifier[0], 0); + tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp); stride = DIV_ROUND_UP(fb->height, tile_height); x_offset = stride * tile_height - src_y - src_h; y_offset = src_x; @@ -11401,8 +11371,7 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc, */ if (intel_rotation_90_or_270(rotation)) { /* stride = Surface height in tiles */ - tile_height = intel_tile_height(dev, fb->pixel_format, - fb->modifier[0], 0); + tile_height = intel_tile_height(dev_priv, fb->modifier[0], 0); stride = DIV_ROUND_UP(fb->height, tile_height); } else { stride = fb->pitches[0] / diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 9a8075b785ac..6aaaa8d3b81a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1155,9 +1155,8 @@ int intel_plane_atomic_set_property(struct drm_plane *plane, int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, struct drm_plane_state *plane_state); -unsigned int -intel_tile_height(struct drm_device *dev, uint32_t pixel_format, - uint64_t fb_format_modifier, unsigned int plane); +unsigned int intel_tile_height(const struct drm_i915_private *dev_priv, + uint64_t fb_modifier, unsigned int cpp); static inline bool intel_rotation_90_or_270(unsigned int rotation) diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 766c33ad0309..64083d720a00 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -239,9 +239,10 @@ skl_update_plane(struct drm_plane *drm_plane, surf_addr = intel_plane_obj_offset(intel_plane, obj, 0); if (intel_rotation_90_or_270(rotation)) { + int cpp = drm_format_plane_cpp(fb->pixel_format, 0); + /* stride: Surface height in tiles */ - tile_height = intel_tile_height(dev, fb->pixel_format, - fb->modifier[0], 0); + tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp); stride = DIV_ROUND_UP(fb->height, tile_height); plane_size = (src_w << 16) | src_h; x_offset = stride * tile_height - y - (src_h + 1); -- cgit v1.2.3 From d9b3288ecf2fe33b46335d2c93bc5ae50d486d0b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 12 Jan 2016 21:08:34 +0200 Subject: drm/i915: change intel_fill_fb_ggtt_view() to use the real tile size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the actual tile size as to compute stuff in intel_fill_fb_ggtt_view() instead of assuming it's PAGE_SIZE. I suppose it doesn't matter since we don't use the results on gen2 platforms where the tile size is 2k. v2: Update due to CbCr plane Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1452625717-9713-5-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9c20c2ee742f..79900341f944 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2291,8 +2291,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, { struct drm_i915_private *dev_priv = to_i915(fb->dev); struct intel_rotation_info *info = &view->params.rotation_info; - unsigned int tile_height, tile_pitch; - unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0); + unsigned int tile_size, tile_width, tile_height, cpp; *view = i915_ggtt_view_normal; @@ -2310,19 +2309,24 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, info->uv_offset = fb->offsets[1]; info->fb_modifier = fb->modifier[0]; - tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp); - tile_pitch = PAGE_SIZE / tile_height; - info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_pitch); + tile_size = intel_tile_size(dev_priv); + + cpp = drm_format_plane_cpp(fb->pixel_format, 0); + tile_width = intel_tile_width(dev_priv, cpp, fb->modifier[0]); + tile_height = tile_size / tile_width; + + info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width); info->height_pages = DIV_ROUND_UP(fb->height, tile_height); - info->size = info->width_pages * info->height_pages * PAGE_SIZE; + info->size = info->width_pages * info->height_pages * tile_size; if (info->pixel_format == DRM_FORMAT_NV12) { cpp = drm_format_plane_cpp(fb->pixel_format, 1); - tile_height = intel_tile_height(dev_priv, fb->modifier[1], cpp); - tile_pitch = PAGE_SIZE / tile_height; - info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_pitch); + tile_width = intel_tile_width(dev_priv, fb->modifier[1], cpp); + tile_height = tile_size / tile_width; + + info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width); info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height); - info->size_uv = info->width_pages_uv * info->height_pages_uv * PAGE_SIZE; + info->size_uv = info->width_pages_uv * info->height_pages_uv * tile_size; } } -- cgit v1.2.3 From d843310d146452105e2bc54b8d82e52ad727697f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 12 Jan 2016 21:08:35 +0200 Subject: drm/i915: Use intel_tile_{size,width,height}() in intel_gen4_compute_page_offset() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make intel_gen4_compute_page_offset() ready for other tiling formats besied X-tile by getting the tile dimensions through intel_tile_{size,width,height}(). Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1452625717-9713-6-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 79900341f944..8a76e29256ef 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2464,15 +2464,20 @@ unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv, unsigned int pitch) { if (fb_modifier != DRM_FORMAT_MOD_NONE) { + unsigned int tile_size, tile_width, tile_height; unsigned int tile_rows, tiles; - tile_rows = *y / 8; - *y %= 8; + tile_size = intel_tile_size(dev_priv); + tile_width = intel_tile_width(dev_priv, fb_modifier, cpp); + tile_height = tile_size / tile_width; + + tile_rows = *y / tile_height; + *y %= tile_height; - tiles = *x / (512/cpp); - *x %= 512/cpp; + tiles = *x / (tile_width/cpp); + *x %= tile_width/cpp; - return tile_rows * pitch * 8 + tiles * 4096; + return tile_rows * pitch * tile_height + tiles * tile_size; } else { unsigned int alignment = intel_linear_alignment(dev_priv) - 1; unsigned int offset; -- cgit v1.2.3 From ce1e5c140ce945ef6fc4ee4803f0c2f774873d8f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 12 Jan 2016 21:08:36 +0200 Subject: drm/i915: s/intel_gen4_compute_page_offset/intel_compute_tile_offset/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since intel_gen4_compute_page_offset() can now handle tiling formats all the way down to gen2, rename it to intel_compute_tile_offset(). Not that we actually use it on gen2/3 since there's no DSPSURF etc. registers which would take a page aligned address. v2: s/page/tile/ (Daniel) Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1452625717-9713-7-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 26 +++++++++++++------------- drivers/gpu/drm/i915/intel_drv.h | 10 +++++----- drivers/gpu/drm/i915/intel_sprite.c | 24 ++++++++++++------------ 3 files changed, 30 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8a76e29256ef..bffeacf86189 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2457,11 +2457,11 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb, /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel * is assumed to be a power-of-two. */ -unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv, - int *x, int *y, - uint64_t fb_modifier, - unsigned int cpp, - unsigned int pitch) +unsigned long intel_compute_tile_offset(struct drm_i915_private *dev_priv, + int *x, int *y, + uint64_t fb_modifier, + unsigned int cpp, + unsigned int pitch) { if (fb_modifier != DRM_FORMAT_MOD_NONE) { unsigned int tile_size, tile_width, tile_height; @@ -2784,10 +2784,10 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, if (INTEL_INFO(dev)->gen >= 4) { intel_crtc->dspaddr_offset = - intel_gen4_compute_page_offset(dev_priv, &x, &y, - fb->modifier[0], - pixel_size, - fb->pitches[0]); + intel_compute_tile_offset(dev_priv, &x, &y, + fb->modifier[0], + pixel_size, + fb->pitches[0]); linear_offset -= intel_crtc->dspaddr_offset; } else { intel_crtc->dspaddr_offset = linear_offset; @@ -2892,10 +2892,10 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, linear_offset = y * fb->pitches[0] + x * pixel_size; intel_crtc->dspaddr_offset = - intel_gen4_compute_page_offset(dev_priv, &x, &y, - fb->modifier[0], - pixel_size, - fb->pitches[0]); + intel_compute_tile_offset(dev_priv, &x, &y, + fb->modifier[0], + pixel_size, + fb->pitches[0]); linear_offset -= intel_crtc->dspaddr_offset; if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { dspcntr |= DISPPLANE_ROTATE_180; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6aaaa8d3b81a..059b46e22c31 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1195,11 +1195,11 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state); #define assert_pipe_enabled(d, p) assert_pipe(d, p, true) #define assert_pipe_disabled(d, p) assert_pipe(d, p, false) -unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv, - int *x, int *y, - uint64_t fb_modifier, - unsigned int cpp, - unsigned int pitch); +unsigned long intel_compute_tile_offset(struct drm_i915_private *dev_priv, + int *x, int *y, + uint64_t fb_modifier, + unsigned int cpp, + unsigned int pitch); void intel_prepare_reset(struct drm_device *dev); void intel_finish_reset(struct drm_device *dev); void hsw_enable_pc8(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 64083d720a00..22589fce9a50 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -423,10 +423,10 @@ vlv_update_plane(struct drm_plane *dplane, crtc_h--; linear_offset = y * fb->pitches[0] + x * pixel_size; - sprsurf_offset = intel_gen4_compute_page_offset(dev_priv, &x, &y, - fb->modifier[0], - pixel_size, - fb->pitches[0]); + sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y, + fb->modifier[0], + pixel_size, + fb->pitches[0]); linear_offset -= sprsurf_offset; if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { @@ -557,10 +557,10 @@ ivb_update_plane(struct drm_plane *plane, sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; linear_offset = y * fb->pitches[0] + x * pixel_size; - sprsurf_offset = intel_gen4_compute_page_offset(dev_priv, &x, &y, - fb->modifier[0], - pixel_size, - fb->pitches[0]); + sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y, + fb->modifier[0], + pixel_size, + fb->pitches[0]); linear_offset -= sprsurf_offset; if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { @@ -696,10 +696,10 @@ ilk_update_plane(struct drm_plane *plane, dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; linear_offset = y * fb->pitches[0] + x * pixel_size; - dvssurf_offset = intel_gen4_compute_page_offset(dev_priv, &x, &y, - fb->modifier[0], - pixel_size, - fb->pitches[0]); + dvssurf_offset = intel_compute_tile_offset(dev_priv, &x, &y, + fb->modifier[0], + pixel_size, + fb->pitches[0]); linear_offset -= dvssurf_offset; if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { -- cgit v1.2.3 From 603525d72219f8aee13f2c029b91c7c1435a01a7 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 12 Jan 2016 21:08:37 +0200 Subject: drm/i915: Refactor intel_surf_alignment() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull the code to determine the surface alignment for both linear and tiled surfaces into a separate function intel_surf_alignment(). This will be used not only for the vma alignment but actually aligning the plane SURF once SKL+ starts using intel_compute_page_offset() (since SKL+ needs >4K alignment for tiled surfaces too). Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1452625717-9713-8-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 45 +++++++++++++++++------------------- 1 file changed, 21 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bffeacf86189..e5eb341c6ca3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2330,7 +2330,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, } } -static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv) +static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_priv) { if (INTEL_INFO(dev_priv)->gen >= 9) return 256 * 1024; @@ -2343,6 +2343,25 @@ static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv) return 0; } +static unsigned int intel_surf_alignment(const struct drm_i915_private *dev_priv, + uint64_t fb_modifier) +{ + switch (fb_modifier) { + case DRM_FORMAT_MOD_NONE: + return intel_linear_alignment(dev_priv); + case I915_FORMAT_MOD_X_TILED: + if (INTEL_INFO(dev_priv)->gen >= 9) + return 256 * 1024; + return 0; + case I915_FORMAT_MOD_Y_TILED: + case I915_FORMAT_MOD_Yf_TILED: + return 1 * 1024 * 1024; + default: + MISSING_CASE(fb_modifier); + return 0; + } +} + int intel_pin_and_fence_fb_obj(struct drm_plane *plane, struct drm_framebuffer *fb, @@ -2357,29 +2376,7 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane, WARN_ON(!mutex_is_locked(&dev->struct_mutex)); - switch (fb->modifier[0]) { - case DRM_FORMAT_MOD_NONE: - alignment = intel_linear_alignment(dev_priv); - break; - case I915_FORMAT_MOD_X_TILED: - if (INTEL_INFO(dev)->gen >= 9) - alignment = 256 * 1024; - else { - /* pin() will align the object as required by fence */ - alignment = 0; - } - break; - case I915_FORMAT_MOD_Y_TILED: - case I915_FORMAT_MOD_Yf_TILED: - if (WARN_ONCE(INTEL_INFO(dev)->gen < 9, - "Y tiling bo slipped through, driver bug!\n")) - return -EINVAL; - alignment = 1 * 1024 * 1024; - break; - default: - MISSING_CASE(fb->modifier[0]); - return -EINVAL; - } + alignment = intel_surf_alignment(dev_priv, fb->modifier[0]); intel_fill_fb_ggtt_view(&view, fb, plane_state); -- cgit v1.2.3 From e57e58bd390a6843db58560bf7b8341665d2e058 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 12 Jan 2016 19:18:06 +0000 Subject: iommu/vt-d: Fix mm refcounting to hold mm_count not mm_users MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Holding mm_users works OK for graphics, which was the first user of SVM with VT-d. However, it works less well for other devices, where we actually do a mmap() from the file descriptor to which the SVM PASID state is tied. In this case on process exit we end up with a recursive reference count: - The MM remains alive until the file is closed and the driver's release() call ends up unbinding the PASID. - The VMA corresponding to the mmap() remains intact until the MM is destroyed. - Thus the file isn't closed, even when exit_files() runs, because the VMA is still holding a reference to it. And the MM remains alive… To address this issue, we *stop* holding mm_users while the PASID is bound. We already hold mm_count by virtue of the MMU notifier, and that can be made to be sufficient. It means that for a period during process exit, the fun part of mmput() has happened and exit_mmap() has been called so the MM is basically defunct. But the PGD still exists and the PASID is still bound to it. During this period, we have to be very careful — exit_mmap() doesn't use mm->mmap_sem because it doesn't expect anyone else to be touching the MM (quite reasonably, since mm_users is zero). So we also need to fix the fault handler to just report failure if mm_users is already zero, and to temporarily bump mm_users while handling any faults. Additionally, exit_mmap() calls mmu_notifier_release() *before* it tears down the page tables, which is too early for us to flush the IOTLB for this PASID. And __mmu_notifier_release() removes every notifier from the list, so when exit_mmap() finally *does* tear down the mappings and clear the page tables, we don't get notified. So we work around this by clearing the PASID table entry in our MMU notifier release() callback. That way, the hardware *can't* get any pages back from the page tables before they get cleared. Hardware designers have confirmed that the resulting 'PASID not present' faults should be handled just as gracefully as 'page not present' faults, the important criterion being that they don't perturb the operation for any *other* PASID in the system. Signed-off-by: David Woodhouse Cc: stable@vger.kernel.org --- drivers/iommu/intel-svm.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index 50464833d0b8..97a818992d6d 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c @@ -249,12 +249,30 @@ static void intel_flush_pasid_dev(struct intel_svm *svm, struct intel_svm_dev *s static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm) { struct intel_svm *svm = container_of(mn, struct intel_svm, notifier); + struct intel_svm_dev *sdev; + /* This might end up being called from exit_mmap(), *before* the page + * tables are cleared. And __mmu_notifier_release() will delete us from + * the list of notifiers so that our invalidate_range() callback doesn't + * get called when the page tables are cleared. So we need to protect + * against hardware accessing those page tables. + * + * We do it by clearing the entry in the PASID table and then flushing + * the IOTLB and the PASID table caches. This might upset hardware; + * perhaps we'll want to point the PASID to a dummy PGD (like the zero + * page) so that we end up taking a fault that the hardware really + * *has* to handle gracefully without affecting other processes. + */ svm->iommu->pasid_table[svm->pasid].val = 0; + wmb(); + + rcu_read_lock(); + list_for_each_entry_rcu(sdev, &svm->devs, list) { + intel_flush_pasid_dev(svm, sdev, svm->pasid); + intel_flush_svm_range_dev(svm, sdev, 0, -1, 0, !svm->mm); + } + rcu_read_unlock(); - /* There's no need to do any flush because we can't get here if there - * are any devices left anyway. */ - WARN_ON(!list_empty(&svm->devs)); } static const struct mmu_notifier_ops intel_mmuops = { @@ -379,7 +397,6 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_ goto out; } iommu->pasid_table[svm->pasid].val = (u64)__pa(mm->pgd) | 1; - mm = NULL; } else iommu->pasid_table[svm->pasid].val = (u64)__pa(init_mm.pgd) | 1 | (1ULL << 11); wmb(); @@ -442,11 +459,11 @@ int intel_svm_unbind_mm(struct device *dev, int pasid) kfree_rcu(sdev, rcu); if (list_empty(&svm->devs)) { - mmu_notifier_unregister(&svm->notifier, svm->mm); idr_remove(&svm->iommu->pasid_idr, svm->pasid); if (svm->mm) - mmput(svm->mm); + mmu_notifier_unregister(&svm->notifier, svm->mm); + /* We mandate that no page faults may be outstanding * for the PASID when intel_svm_unbind_mm() is called. * If that is not obeyed, subtle errors will happen. @@ -551,6 +568,9 @@ static irqreturn_t prq_event_thread(int irq, void *d) * any faults on kernel addresses. */ if (!svm->mm) goto bad_req; + /* If the mm is already defunct, don't handle faults. */ + if (!atomic_inc_not_zero(&svm->mm->mm_users)) + goto bad_req; down_read(&svm->mm->mmap_sem); vma = find_extend_vma(svm->mm, address); if (!vma || address < vma->vm_start) @@ -567,6 +587,7 @@ static irqreturn_t prq_event_thread(int irq, void *d) result = QI_RESP_SUCCESS; invalid: up_read(&svm->mm->mmap_sem); + mmput(svm->mm); bad_req: /* Accounting for major/minor faults? */ rcu_read_lock(); -- cgit v1.2.3 From fda3bec12d0979aae3f02ee645913d66fbc8a26e Mon Sep 17 00:00:00 2001 From: CQ Tang Date: Wed, 13 Jan 2016 21:15:03 +0000 Subject: iommu/vt-d: Fix 64-bit accesses to 32-bit DMAR_GSTS_REG This is a 32-bit register. Apparently harmless on real hardware, but causing justified warnings in simulation. Signed-off-by: CQ Tang Signed-off-by: David Woodhouse Cc: stable@vger.kernel.org --- drivers/iommu/dmar.c | 2 +- drivers/iommu/intel_irq_remapping.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 80e3c176008e..55a19e49205b 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -1347,7 +1347,7 @@ void dmar_disable_qi(struct intel_iommu *iommu) raw_spin_lock_irqsave(&iommu->register_lock, flags); - sts = dmar_readq(iommu->reg + DMAR_GSTS_REG); + sts = readl(iommu->reg + DMAR_GSTS_REG); if (!(sts & DMA_GSTS_QIES)) goto end; diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 1fae1881648c..e9b241b1c9dd 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -629,7 +629,7 @@ static void iommu_disable_irq_remapping(struct intel_iommu *iommu) raw_spin_lock_irqsave(&iommu->register_lock, flags); - sts = dmar_readq(iommu->reg + DMAR_GSTS_REG); + sts = readl(iommu->reg + DMAR_GSTS_REG); if (!(sts & DMA_GSTS_IRES)) goto end; -- cgit v1.2.3 From 354210f8046cc801d6001f10c5c32967932b09a2 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sat, 19 Dec 2015 09:59:37 -0500 Subject: Revert "mac80211_hwsim: support any address in userspace" This reverts commit cd37a90b2a417e5882414e19954eeed174aa4d29. Different userspace programs interpreted HWSIM_ATTR_ADDR_TRANSMITTER and HWSIM_ATTR_ADDR_RECEIVER differently: some expected it to be an unchanging hardware address that is tied to the radio despite which address is configured on the interface, while others expected to be a copy of the address in the frame (the configured address). The intent of the original authors is unclear. The latter interpretation doesn't really work properly with multiple vifs and broadcast frames. Also, as the TA is already in the frame, userspace programs can actually support configured addresses in the former interpretation by mapping between them and the supplied HWSIM_ATTR_ADDR_TRANSMITTER. So, in the interest of API stability, revert to the previous mode of operation and going forward use the former interpretation. Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index c32889a1e39c..a28414c50edf 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -991,7 +991,8 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, goto nla_put_failure; } - if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER, ETH_ALEN, hdr->addr2)) + if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER, + ETH_ALEN, data->addresses[1].addr)) goto nla_put_failure; /* We get the skb->data */ @@ -2736,7 +2737,7 @@ static struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr(const u8 *addr) spin_lock_bh(&hwsim_radio_lock); list_for_each_entry(data, &hwsim_radios, list) { - if (mac80211_hwsim_addr_match(data, addr)) { + if (memcmp(data->addresses[1].addr, addr, ETH_ALEN) == 0) { _found = true; break; } -- cgit v1.2.3 From 50ea05efaf3bed7dd34bcc2635a8b3f53bd0ccc1 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 30 Dec 2015 16:06:04 +0200 Subject: mac80211: pass block ack session timeout to to driver Currently mac80211 does not inform the driver of the session block ack timeout when starting a rx aggregation session. Drivers that manage the reorder buffer need to know this parameter. Seeing that there are now too many arguments for the drv_ampdu_action() function, wrap them inside a structure. Signed-off-by: Sara Sharon Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/ath10k/mac.c | 7 +-- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 7 +-- drivers/net/wireless/ath/ath9k/main.c | 8 ++-- drivers/net/wireless/ath/carl9170/main.c | 8 ++-- drivers/net/wireless/ath/wcn36xx/main.c | 8 ++-- .../broadcom/brcm80211/brcmsmac/mac80211_if.c | 8 ++-- drivers/net/wireless/intel/iwlegacy/4965-mac.c | 8 ++-- drivers/net/wireless/intel/iwlegacy/4965.h | 4 +- drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c | 9 ++-- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 9 ++-- drivers/net/wireless/mac80211_hwsim.c | 8 ++-- drivers/net/wireless/marvell/mwl8k.c | 10 ++-- drivers/net/wireless/mediatek/mt7601u/main.c | 8 ++-- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 7 +-- drivers/net/wireless/ralink/rt2x00/rt2800lib.h | 4 +- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +-- drivers/net/wireless/realtek/rtlwifi/core.c | 8 ++-- drivers/net/wireless/rsi/rsi_91x_mac80211.c | 19 +++----- drivers/net/wireless/st/cw1200/sta.c | 4 +- drivers/net/wireless/st/cw1200/sta.h | 4 +- drivers/net/wireless/ti/wlcore/main.c | 8 ++-- include/net/mac80211.h | 44 ++++++++++++------ net/mac80211/agg-rx.c | 25 ++++++++-- net/mac80211/agg-tx.c | 53 ++++++++++++++-------- net/mac80211/driver-ops.c | 10 ++-- net/mac80211/driver-ops.h | 4 +- net/mac80211/trace.h | 43 ++++++++++-------- 27 files changed, 202 insertions(+), 139 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 6146a293601a..368de5e5a04f 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6366,12 +6366,13 @@ static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) static int ath10k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct ath10k *ar = hw->priv; struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; ath10k_dbg(ar, ATH10K_DBG_MAC, "mac ampdu vdev_id %i sta %pM tid %hu action %d\n", arvif->vdev_id, sta->addr, tid, action); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index fe1fd1a5ae15..639294a9e34d 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1657,13 +1657,14 @@ static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw, static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct ath9k_htc_priv *priv = hw->priv; struct ath9k_htc_sta *ista; int ret = 0; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; mutex_lock(&priv->mutex); ath9k_htc_ps_wakeup(priv); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c1b33fdcca08..cf58a304e9f0 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1864,14 +1864,16 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) static int ath9k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); bool flush = false; int ret = 0; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; mutex_lock(&sc->mutex); diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 19d3d64416bf..4d1527a2e292 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1413,10 +1413,12 @@ static void carl9170_ampdu_work(struct work_struct *work) static int carl9170_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; struct ar9170 *ar = hw->priv; struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; struct carl9170_sta_tid *tid_info; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 7c169abdbafe..a27279c2c695 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -857,12 +857,14 @@ static int wcn36xx_resume(struct ieee80211_hw *hw) static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct wcn36xx *wcn = hw->priv; struct wcn36xx_sta *sta_priv = NULL; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", action, tid); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c index bec2dc1ca2e4..61ae2768132a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c @@ -818,13 +818,15 @@ brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static int brcms_ops_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct brcms_info *wl = hw->priv; struct scb *scb = &wl->wlc->pri_scb; int status; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u8 buf_size = params->buf_size; if (WARN_ON(scb->magic != SCB_MAGIC)) return -EIDRM; diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c index fd38aa0763e4..b75f4ef3cdc7 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c @@ -5982,12 +5982,14 @@ il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 * ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct il_priv *il = hw->priv; int ret = -EINVAL; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; D_HT("A-MPDU action on addr %pM tid %d\n", sta->addr, tid); diff --git a/drivers/net/wireless/intel/iwlegacy/4965.h b/drivers/net/wireless/intel/iwlegacy/4965.h index 8ab8706f9422..e432715e02d8 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965.h +++ b/drivers/net/wireless/intel/iwlegacy/4965.h @@ -182,9 +182,7 @@ void il4965_mac_update_tkip_key(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 * ssn, - u8 buf_size, bool amsdu); + struct ieee80211_ampdu_params *params); int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c index 29ea1c6705b4..151721e4040c 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c @@ -732,12 +732,15 @@ static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg) static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); int ret = -EINVAL; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; + u8 buf_size = params->buf_size; struct iwl_station_priv *sta_priv = (void *) sta->drv_priv; IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index d70a1716f3e0..1bd3f0b700d3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -837,13 +837,16 @@ iwl_mvm_ampdu_check_trigger(struct iwl_mvm *mvm, struct ieee80211_vif *vif, static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, - u16 *ssn, u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); int ret; bool tx_agg_ref = false; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; + u8 buf_size = params->buf_size; IWL_DEBUG_HT(mvm, "A-MPDU action on addr %pM tid %d: action %d\n", sta->addr, tid, action); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index c32889a1e39c..e31a94fd6135 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1845,10 +1845,12 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw, static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + switch (action) { case IEEE80211_AMPDU_TX_START: ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c index 30e3aaae32e2..088429d0a634 100644 --- a/drivers/net/wireless/marvell/mwl8k.c +++ b/drivers/net/wireless/marvell/mwl8k.c @@ -5421,11 +5421,13 @@ static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx, static int mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { - + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; + u8 buf_size = params->buf_size; int i, rc = 0; struct mwl8k_priv *priv = hw->priv; struct mwl8k_ampdu_stream *stream; diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c index f715eee39851..e70dd9523911 100644 --- a/drivers/net/wireless/mediatek/mt7601u/main.c +++ b/drivers/net/wireless/mediatek/mt7601u/main.c @@ -334,11 +334,13 @@ static int mt7601u_set_rts_threshold(struct ieee80211_hw *hw, u32 value) static int mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, - bool amsdu) + struct ieee80211_ampdu_params *params) { struct mt7601u_dev *dev = hw->priv; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv; WARN_ON(msta->wcid.idx > GROUP_WCID(0)); diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index 9733b31a780d..69c1c09687a3 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -7935,10 +7935,11 @@ u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) EXPORT_SYMBOL_GPL(rt2800_get_tsf); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv; int ret = 0; diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h index 440790b92b19..83f1a44fb9b4 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h @@ -218,9 +218,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, const struct ieee80211_tx_queue_params *params); u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu); + struct ieee80211_ampdu_params *params); int rt2800_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey); void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 6aed923a709a..7d820c395375 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -5375,13 +5375,13 @@ static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static int rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, - bool amsdu) + struct ieee80211_ampdu_params *params) { struct rtl8xxxu_priv *priv = hw->priv; struct device *dev = &priv->udev->dev; u8 ampdu_factor, ampdu_density; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; switch (action) { case IEEE80211_AMPDU_TX_START: diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index 4ae421ef30d9..f2507610314b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.c +++ b/drivers/net/wireless/realtek/rtlwifi/core.c @@ -1371,11 +1371,13 @@ static void rtl_op_sta_notify(struct ieee80211_hw *hw, static int rtl_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; switch (action) { case IEEE80211_AMPDU_TX_START: diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index b5bcc933a2a6..4df992de7d07 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -659,29 +659,24 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw, * informs the f/w regarding this. * @hw: Pointer to the ieee80211_hw structure. * @vif: Pointer to the ieee80211_vif structure. - * @action: ieee80211_ampdu_mlme_action enum. - * @sta: Pointer to the ieee80211_sta structure. - * @tid: Traffic identifier. - * @ssn: Pointer to ssn value. - * @buf_size: Buffer size (for kernel version > 2.6.38). - * @amsdu: is AMSDU in AMPDU allowed + * @params: Pointer to A-MPDU action parameters * * Return: status: 0 on success, negative error code on failure. */ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - unsigned short tid, - unsigned short *ssn, - unsigned char buf_size, - bool amsdu) + struct ieee80211_ampdu_params *params) { int status = -EOPNOTSUPP; struct rsi_hw *adapter = hw->priv; struct rsi_common *common = adapter->priv; u16 seq_no = 0; u8 ii = 0; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; + u8 buf_size = params->buf_size; for (ii = 0; ii < RSI_MAX_VIFS; ii++) { if (vif == adapter->vifs[ii]) diff --git a/drivers/net/wireless/st/cw1200/sta.c b/drivers/net/wireless/st/cw1200/sta.c index 06321c799c90..d0ddcde6c695 100644 --- a/drivers/net/wireless/st/cw1200/sta.c +++ b/drivers/net/wireless/st/cw1200/sta.c @@ -2129,9 +2129,7 @@ void cw1200_mcast_timeout(unsigned long arg) int cw1200_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { /* Aggregation is implemented fully in firmware, * including block ack negotiation. Do not allow diff --git a/drivers/net/wireless/st/cw1200/sta.h b/drivers/net/wireless/st/cw1200/sta.h index bebb3379017f..a0bacaa39b31 100644 --- a/drivers/net/wireless/st/cw1200/sta.h +++ b/drivers/net/wireless/st/cw1200/sta.h @@ -109,9 +109,7 @@ void cw1200_bss_info_changed(struct ieee80211_hw *dev, u32 changed); int cw1200_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu); + struct ieee80211_ampdu_params *params); void cw1200_suspend_resume(struct cw1200_common *priv, struct wsm_suspend_resume *arg); diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index d1109c4f0f0d..45662cf3169f 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -5187,14 +5187,16 @@ out: static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct wl1271 *wl = hw->priv; struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; u8 hlid, *ba_bitmap; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu action %d tid %d", action, tid); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index bdee1cc19c7e..6c9c559394b0 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2702,6 +2702,33 @@ enum ieee80211_ampdu_mlme_action { IEEE80211_AMPDU_TX_OPERATIONAL, }; +/** + * struct ieee80211_ampdu_params - AMPDU action parameters + * + * @action: the ampdu action, value from %ieee80211_ampdu_mlme_action. + * @sta: peer of this AMPDU session + * @tid: tid of the BA session + * @ssn: start sequence number of the session. TX/RX_STOP can pass 0. When + * action is set to %IEEE80211_AMPDU_RX_START the driver passes back the + * actual ssn value used to start the session and writes the value here. + * @buf_size: reorder buffer size (number of subframes). Valid only when the + * action is set to %IEEE80211_AMPDU_RX_START or + * %IEEE80211_AMPDU_TX_OPERATIONAL + * @amsdu: indicates the peer's ability to receive A-MSDU within A-MPDU. + * valid when the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL + * @timeout: BA session timeout. Valid only when the action is set to + * %IEEE80211_AMPDU_RX_START + */ +struct ieee80211_ampdu_params { + enum ieee80211_ampdu_mlme_action action; + struct ieee80211_sta *sta; + u16 tid; + u16 ssn; + u8 buf_size; + bool amsdu; + u16 timeout; +}; + /** * enum ieee80211_frame_release_type - frame release reason * @IEEE80211_FRAME_RELEASE_PSPOLL: frame released for PS-Poll @@ -3046,15 +3073,9 @@ enum ieee80211_reconfig_type { * @ampdu_action: Perform a certain A-MPDU action * The RA/TID combination determines the destination and TID we want * the ampdu action to be performed for. The action is defined through - * ieee80211_ampdu_mlme_action. Starting sequence number (@ssn) - * is the first frame we expect to perform the action on. Notice - * that TX/RX_STOP can pass NULL for this parameter. - * The @buf_size parameter is valid only when the action is set to - * %IEEE80211_AMPDU_RX_START or %IEEE80211_AMPDU_TX_OPERATIONAL and - * indicates the reorder buffer size (number of subframes) for this - * session. + * ieee80211_ampdu_mlme_action. * When the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL the driver - * may neither send aggregates containing more subframes than this + * may neither send aggregates containing more subframes than @buf_size * nor send aggregates in a way that lost frames would exceed the * buffer size. If just limiting the aggregate size, this would be * possible with a buf_size of 8: @@ -3065,9 +3086,6 @@ enum ieee80211_reconfig_type { * buffer size of 8. Correct ways to retransmit #1 would be: * - TX: 1 or 18 or 81 * Even "189" would be wrong since 1 could be lost again. - * The @amsdu parameter is valid when the action is set to - * %IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's ability - * to receive A-MSDU within A-MPDU. * * Returns a negative error code on failure. * The callback can sleep. @@ -3409,9 +3427,7 @@ struct ieee80211_ops { int (*tx_last_beacon)(struct ieee80211_hw *hw); int (*ampdu_action)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu); + struct ieee80211_ampdu_params *params); int (*get_survey)(struct ieee80211_hw *hw, int idx, struct survey_info *survey); void (*rfkill_poll)(struct ieee80211_hw *hw); diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 78672737fe3e..ec80db7c955c 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -7,6 +7,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2007, Michael Wu * Copyright 2007-2010, Intel Corporation + * Copyright(c) 2015 Intel Deutschland GmbH * * 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 @@ -61,6 +62,14 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, { struct ieee80211_local *local = sta->local; struct tid_ampdu_rx *tid_rx; + struct ieee80211_ampdu_params params = { + .sta = &sta->sta, + .action = IEEE80211_AMPDU_RX_STOP, + .tid = tid, + .amsdu = false, + .timeout = 0, + .ssn = 0, + }; lockdep_assert_held(&sta->ampdu_mlme.mtx); @@ -78,8 +87,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator", (int)reason); - if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, - &sta->sta, tid, NULL, 0, false)) + if (drv_ampdu_action(local, sta->sdata, ¶ms)) sdata_info(sta->sdata, "HW problem - can not stop rx aggregation for %pM tid %d\n", sta->sta.addr, tid); @@ -237,6 +245,15 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, { struct ieee80211_local *local = sta->sdata->local; struct tid_ampdu_rx *tid_agg_rx; + struct ieee80211_ampdu_params params = { + .sta = &sta->sta, + .action = IEEE80211_AMPDU_RX_START, + .tid = tid, + .amsdu = false, + .timeout = timeout, + .ssn = start_seq_num, + }; + int i, ret = -EOPNOTSUPP; u16 status = WLAN_STATUS_REQUEST_DECLINED; @@ -275,6 +292,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, /* make sure the size doesn't exceed the maximum supported by the hw */ if (buf_size > local->hw.max_rx_aggregation_subframes) buf_size = local->hw.max_rx_aggregation_subframes; + params.buf_size = buf_size; /* examine state machine */ mutex_lock(&sta->ampdu_mlme.mtx); @@ -322,8 +340,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, for (i = 0; i < buf_size; i++) __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]); - ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, - &sta->sta, tid, &start_seq_num, buf_size, false); + ret = drv_ampdu_action(local, sta->sdata, ¶ms); ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n", sta->sta.addr, tid, ret); if (ret) { diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index ff757181b0a8..4932e9f243a2 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -7,6 +7,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2007, Michael Wu * Copyright 2007-2010, Intel Corporation + * Copyright(c) 2015 Intel Deutschland GmbH * * 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 @@ -295,7 +296,14 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, { struct ieee80211_local *local = sta->local; struct tid_ampdu_tx *tid_tx; - enum ieee80211_ampdu_mlme_action action; + struct ieee80211_ampdu_params params = { + .sta = &sta->sta, + .tid = tid, + .buf_size = 0, + .amsdu = false, + .timeout = 0, + .ssn = 0, + }; int ret; lockdep_assert_held(&sta->ampdu_mlme.mtx); @@ -304,10 +312,10 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, case AGG_STOP_DECLINED: case AGG_STOP_LOCAL_REQUEST: case AGG_STOP_PEER_REQUEST: - action = IEEE80211_AMPDU_TX_STOP_CONT; + params.action = IEEE80211_AMPDU_TX_STOP_CONT; break; case AGG_STOP_DESTROY_STA: - action = IEEE80211_AMPDU_TX_STOP_FLUSH; + params.action = IEEE80211_AMPDU_TX_STOP_FLUSH; break; default: WARN_ON_ONCE(1); @@ -330,9 +338,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, spin_unlock_bh(&sta->lock); if (reason != AGG_STOP_DESTROY_STA) return -EALREADY; - ret = drv_ampdu_action(local, sta->sdata, - IEEE80211_AMPDU_TX_STOP_FLUSH_CONT, - &sta->sta, tid, NULL, 0, false); + params.action = IEEE80211_AMPDU_TX_STOP_FLUSH_CONT; + ret = drv_ampdu_action(local, sta->sdata, ¶ms); WARN_ON_ONCE(ret); return 0; } @@ -381,8 +388,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, WLAN_BACK_INITIATOR; tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST; - ret = drv_ampdu_action(local, sta->sdata, action, - &sta->sta, tid, NULL, 0, false); + ret = drv_ampdu_action(local, sta->sdata, ¶ms); /* HW shall not deny going back to legacy */ if (WARN_ON(ret)) { @@ -445,7 +451,14 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) struct tid_ampdu_tx *tid_tx; struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; - u16 start_seq_num; + struct ieee80211_ampdu_params params = { + .sta = &sta->sta, + .action = IEEE80211_AMPDU_TX_START, + .tid = tid, + .buf_size = 0, + .amsdu = false, + .timeout = 0, + }; int ret; tid_tx = rcu_dereference_protected_tid_tx(sta, tid); @@ -467,10 +480,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) */ synchronize_net(); - start_seq_num = sta->tid_seq[tid] >> 4; - - ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, - &sta->sta, tid, &start_seq_num, 0, false); + params.ssn = sta->tid_seq[tid] >> 4; + ret = drv_ampdu_action(local, sdata, ¶ms); if (ret) { ht_dbg(sdata, "BA request denied - HW unavailable for %pM tid %d\n", @@ -499,7 +510,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) /* send AddBA request */ ieee80211_send_addba_request(sdata, sta->sta.addr, tid, - tid_tx->dialog_token, start_seq_num, + tid_tx->dialog_token, params.ssn, IEEE80211_MAX_AMPDU_BUF, tid_tx->timeout); } @@ -684,18 +695,24 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, struct sta_info *sta, u16 tid) { struct tid_ampdu_tx *tid_tx; + struct ieee80211_ampdu_params params = { + .sta = &sta->sta, + .action = IEEE80211_AMPDU_TX_OPERATIONAL, + .tid = tid, + .timeout = 0, + .ssn = 0, + }; lockdep_assert_held(&sta->ampdu_mlme.mtx); tid_tx = rcu_dereference_protected_tid_tx(sta, tid); + params.buf_size = tid_tx->buf_size; + params.amsdu = tid_tx->amsdu; ht_dbg(sta->sdata, "Aggregation is on for %pM tid %d\n", sta->sta.addr, tid); - drv_ampdu_action(local, sta->sdata, - IEEE80211_AMPDU_TX_OPERATIONAL, - &sta->sta, tid, NULL, tid_tx->buf_size, - tid_tx->amsdu); + drv_ampdu_action(local, sta->sdata, ¶ms); /* * synchronize with TX path, while splicing the TX path diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c index ca1fe5576103..c258f1041d33 100644 --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c @@ -284,9 +284,7 @@ int drv_switch_vif_chanctx(struct ieee80211_local *local, int drv_ampdu_action(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, - u16 *ssn, u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { int ret = -EOPNOTSUPP; @@ -296,12 +294,10 @@ int drv_ampdu_action(struct ieee80211_local *local, if (!check_sdata_in_driver(sdata)) return -EIO; - trace_drv_ampdu_action(local, sdata, action, sta, tid, - ssn, buf_size, amsdu); + trace_drv_ampdu_action(local, sdata, params); if (local->ops->ampdu_action) - ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, - sta, tid, ssn, buf_size, amsdu); + ret = local->ops->ampdu_action(&local->hw, &sdata->vif, params); trace_drv_return_int(local, ret); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 154ce4b13406..18b0d65baff0 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -585,9 +585,7 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local) int drv_ampdu_action(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, - u16 *ssn, u8 buf_size, bool amsdu); + struct ieee80211_ampdu_params *params); static inline int drv_get_survey(struct ieee80211_local *local, int idx, struct survey_info *survey) diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index a6b4442776a0..2b0a17ee907a 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -80,7 +80,23 @@ #define KEY_PR_FMT " cipher:0x%x, flags=%#x, keyidx=%d, hw_key_idx=%d" #define KEY_PR_ARG __entry->cipher, __entry->flags, __entry->keyidx, __entry->hw_key_idx - +#define AMPDU_ACTION_ENTRY __field(enum ieee80211_ampdu_mlme_action, \ + ieee80211_ampdu_mlme_action) \ + STA_ENTRY \ + __field(u16, tid) \ + __field(u16, ssn) \ + __field(u8, buf_size) \ + __field(bool, amsdu) \ + __field(u16, timeout) +#define AMPDU_ACTION_ASSIGN STA_NAMED_ASSIGN(params->sta); \ + __entry->tid = params->tid; \ + __entry->ssn = params->ssn; \ + __entry->buf_size = params->buf_size; \ + __entry->amsdu = params->amsdu; \ + __entry->timeout = params->timeout; +#define AMPDU_ACTION_PR_FMT STA_PR_FMT " tid %d, ssn %d, buf_size %u, amsdu %d, timeout %d" +#define AMPDU_ACTION_PR_ARG STA_PR_ARG, __entry->tid, __entry->ssn, \ + __entry->buf_size, __entry->amsdu, __entry->timeout /* * Tracing for driver callbacks. @@ -970,38 +986,25 @@ DEFINE_EVENT(local_only_evt, drv_tx_last_beacon, TRACE_EVENT(drv_ampdu_action, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, - u16 *ssn, u8 buf_size, bool amsdu), + struct ieee80211_ampdu_params *params), - TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size, amsdu), + TP_ARGS(local, sdata, params), TP_STRUCT__entry( LOCAL_ENTRY - STA_ENTRY - __field(u32, action) - __field(u16, tid) - __field(u16, ssn) - __field(u8, buf_size) - __field(bool, amsdu) VIF_ENTRY + AMPDU_ACTION_ENTRY ), TP_fast_assign( LOCAL_ASSIGN; VIF_ASSIGN; - STA_ASSIGN; - __entry->action = action; - __entry->tid = tid; - __entry->ssn = ssn ? *ssn : 0; - __entry->buf_size = buf_size; - __entry->amsdu = amsdu; + AMPDU_ACTION_ASSIGN; ), TP_printk( - LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d amsdu:%d", - LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, - __entry->tid, __entry->buf_size, __entry->amsdu + LOCAL_PR_FMT VIF_PR_FMT AMPDU_ACTION_PR_FMT, + LOCAL_PR_ARG, VIF_PR_ARG, AMPDU_ACTION_PR_ARG ) ); -- cgit v1.2.3 From 87ad321287ae99a8932af1a19ac99849284a62bd Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 14 Jan 2016 12:53:34 +0200 Subject: drm/i915: add onoff utility function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a common function to return "on" or "off" string based on the argument, and drop the local versions of it. This is the onoff version of commit 42a8ca4cb4a48ddbf40e8edb291425e76bcdc230 Author: Jani Nikula Date: Thu Aug 27 16:23:30 2015 +0300 drm/i915: add yesno utility function Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1452768814-29787-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 6 +++--- drivers/gpu/drm/i915/i915_drv.h | 5 +++++ drivers/gpu/drm/i915/intel_display.c | 30 ++++++++++++------------------ drivers/gpu/drm/i915/intel_dp.c | 9 ++------- drivers/gpu/drm/i915/intel_pm.c | 11 +++++------ 5 files changed, 27 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index f17a2b0c2493..975af3568521 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1335,8 +1335,8 @@ static int vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv, return 0; DRM_DEBUG_KMS("waiting for GT wells to go %s (%08x)\n", - wait_for_on ? "on" : "off", - I915_READ(VLV_GTLC_PW_STATUS)); + onoff(wait_for_on), + I915_READ(VLV_GTLC_PW_STATUS)); /* * RC6 transitioning can be delayed up to 2 msec (see @@ -1345,7 +1345,7 @@ static int vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv, err = wait_for(COND, 3); if (err) DRM_ERROR("timeout waiting for GT wells to go %s\n", - wait_for_on ? "on" : "off"); + onoff(wait_for_on)); return err; #undef COND diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 104bd1809936..eb7bb97f7316 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -102,6 +102,11 @@ static inline const char *yesno(bool v) return v ? "yes" : "no"; } +static inline const char *onoff(bool v) +{ + return v ? "on" : "off"; +} + enum pipe { INVALID_PIPE = -1, PIPE_A = 0, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e5eb341c6ca3..aa24f79d85bf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1150,11 +1150,6 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc) } } -static const char *state_string(bool enabled) -{ - return enabled ? "on" : "off"; -} - /* Only for pre-ILK configs */ void assert_pll(struct drm_i915_private *dev_priv, enum pipe pipe, bool state) @@ -1166,7 +1161,7 @@ void assert_pll(struct drm_i915_private *dev_priv, cur_state = !!(val & DPLL_VCO_ENABLE); I915_STATE_WARN(cur_state != state, "PLL state assertion failure (expected %s, current %s)\n", - state_string(state), state_string(cur_state)); + onoff(state), onoff(cur_state)); } /* XXX: the dsi pll is shared between MIPI DSI ports */ @@ -1182,7 +1177,7 @@ static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state) cur_state = val & DSI_PLL_VCO_EN; I915_STATE_WARN(cur_state != state, "DSI PLL state assertion failure (expected %s, current %s)\n", - state_string(state), state_string(cur_state)); + onoff(state), onoff(cur_state)); } #define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true) #define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false) @@ -1206,14 +1201,13 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv, bool cur_state; struct intel_dpll_hw_state hw_state; - if (WARN (!pll, - "asserting DPLL %s with no DPLL\n", state_string(state))) + if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state))) return; cur_state = pll->get_hw_state(dev_priv, pll, &hw_state); I915_STATE_WARN(cur_state != state, "%s assertion failure (expected %s, current %s)\n", - pll->name, state_string(state), state_string(cur_state)); + pll->name, onoff(state), onoff(cur_state)); } static void assert_fdi_tx(struct drm_i915_private *dev_priv, @@ -1233,7 +1227,7 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv, } I915_STATE_WARN(cur_state != state, "FDI TX state assertion failure (expected %s, current %s)\n", - state_string(state), state_string(cur_state)); + onoff(state), onoff(cur_state)); } #define assert_fdi_tx_enabled(d, p) assert_fdi_tx(d, p, true) #define assert_fdi_tx_disabled(d, p) assert_fdi_tx(d, p, false) @@ -1248,7 +1242,7 @@ static void assert_fdi_rx(struct drm_i915_private *dev_priv, cur_state = !!(val & FDI_RX_ENABLE); I915_STATE_WARN(cur_state != state, "FDI RX state assertion failure (expected %s, current %s)\n", - state_string(state), state_string(cur_state)); + onoff(state), onoff(cur_state)); } #define assert_fdi_rx_enabled(d, p) assert_fdi_rx(d, p, true) #define assert_fdi_rx_disabled(d, p) assert_fdi_rx(d, p, false) @@ -1280,7 +1274,7 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, cur_state = !!(val & FDI_RX_PLL_ENABLE); I915_STATE_WARN(cur_state != state, "FDI RX PLL assertion failure (expected %s, current %s)\n", - state_string(state), state_string(cur_state)); + onoff(state), onoff(cur_state)); } void assert_panel_unlocked(struct drm_i915_private *dev_priv, @@ -1338,7 +1332,7 @@ static void assert_cursor(struct drm_i915_private *dev_priv, I915_STATE_WARN(cur_state != state, "cursor on pipe %c assertion failure (expected %s, current %s)\n", - pipe_name(pipe), state_string(state), state_string(cur_state)); + pipe_name(pipe), onoff(state), onoff(cur_state)); } #define assert_cursor_enabled(d, p) assert_cursor(d, p, true) #define assert_cursor_disabled(d, p) assert_cursor(d, p, false) @@ -1365,7 +1359,7 @@ void assert_pipe(struct drm_i915_private *dev_priv, I915_STATE_WARN(cur_state != state, "pipe %c assertion failure (expected %s, current %s)\n", - pipe_name(pipe), state_string(state), state_string(cur_state)); + pipe_name(pipe), onoff(state), onoff(cur_state)); } static void assert_plane(struct drm_i915_private *dev_priv, @@ -1378,7 +1372,7 @@ static void assert_plane(struct drm_i915_private *dev_priv, cur_state = !!(val & DISPLAY_PLANE_ENABLE); I915_STATE_WARN(cur_state != state, "plane %c assertion failure (expected %s, current %s)\n", - plane_name(plane), state_string(state), state_string(cur_state)); + plane_name(plane), onoff(state), onoff(cur_state)); } #define assert_plane_enabled(d, p) assert_plane(d, p, true) @@ -16317,7 +16311,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, for_each_pipe(dev_priv, i) { err_printf(m, "Pipe [%d]:\n", i); err_printf(m, " Power: %s\n", - error->pipe[i].power_domain_on ? "on" : "off"); + onoff(error->pipe[i].power_domain_on)); err_printf(m, " SRC: %08x\n", error->pipe[i].source); err_printf(m, " STAT: %08x\n", error->pipe[i].stat); @@ -16345,7 +16339,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, err_printf(m, "CPU transcoder: %c\n", transcoder_name(error->transcoder[i].cpu_transcoder)); err_printf(m, " Power: %s\n", - error->transcoder[i].power_domain_on ? "on" : "off"); + onoff(error->transcoder[i].power_domain_on)); err_printf(m, " CONF: %08x\n", error->transcoder[i].conf); err_printf(m, " HTOTAL: %08x\n", error->transcoder[i].htotal); err_printf(m, " HBLANK: %08x\n", error->transcoder[i].hblank); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9e02dd789b86..3999afa440bd 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2238,11 +2238,6 @@ static void intel_edp_backlight_power(struct intel_connector *connector, _intel_edp_backlight_off(intel_dp); } -static const char *state_string(bool enabled) -{ - return enabled ? "on" : "off"; -} - static void assert_dp_port(struct intel_dp *intel_dp, bool state) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -2252,7 +2247,7 @@ static void assert_dp_port(struct intel_dp *intel_dp, bool state) I915_STATE_WARN(cur_state != state, "DP port %c state assertion failure (expected %s, current %s)\n", port_name(dig_port->port), - state_string(state), state_string(cur_state)); + onoff(state), onoff(cur_state)); } #define assert_dp_port_disabled(d) assert_dp_port((d), false) @@ -2262,7 +2257,7 @@ static void assert_edp_pll(struct drm_i915_private *dev_priv, bool state) I915_STATE_WARN(cur_state != state, "eDP PLL state assertion failure (expected %s, current %s)\n", - state_string(state), state_string(cur_state)); + onoff(state), onoff(cur_state)); } #define assert_edp_pll_enabled(d) assert_edp_pll((d), true) #define assert_edp_pll_disabled(d) assert_edp_pll((d), false) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9df9e9a22f3c..465ca76df201 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4590,13 +4590,13 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode) } if (HAS_RC6p(dev)) DRM_DEBUG_KMS("Enabling RC6 states: RC6 %s RC6p %s RC6pp %s\n", - (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", - (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", - (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); + onoff(mode & GEN6_RC_CTL_RC6_ENABLE), + onoff(mode & GEN6_RC_CTL_RC6p_ENABLE), + onoff(mode & GEN6_RC_CTL_RC6pp_ENABLE)); else DRM_DEBUG_KMS("Enabling RC6 states: RC6 %s\n", - (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off"); + onoff(mode & GEN6_RC_CTL_RC6_ENABLE)); } static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6) @@ -4774,8 +4774,7 @@ static void gen9_enable_rc6(struct drm_device *dev) /* 3a: Enable RC6 */ if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE) rc6_mask = GEN6_RC_CTL_RC6_ENABLE; - DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? - "on" : "off"); + DRM_INFO("RC6 %s\n", onoff(rc6_mask & GEN6_RC_CTL_RC6_ENABLE)); /* WaRsUseTimeoutMode */ if (IS_SKL_REVID(dev, 0, SKL_REVID_D0) || IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { -- cgit v1.2.3 From f1ecaf8f9c9924badd4c8f690e39632d31edb500 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 14 Jan 2016 14:53:34 +0200 Subject: drm/i915: Start WM computation from scratch on ILK-BDW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ilk_compute_pipe_wm() assumes as zeroed pipe_wm structure when it starts. We used to pass such a zeroed struct in, but this got broken when the pipe_wm structure got embedded in the crtc state. To fix it without too much fuzz, we need to resort to a memset(). Fixes: 4e0963c7663b ("drm/i915: Calculate pipe watermarks into CRTC state (v3)") Cc: Matt Roper Signed-off-by: Ville Syrjälä Reviewed-by: Matt Roper Link: http://patchwork.freedesktop.org/patch/msgid/1452776015-22076-1-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_pm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 465ca76df201..966c4c2c416f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2317,6 +2317,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, return PTR_ERR(cstate); pipe_wm = &cstate->wm.optimal.ilk; + memset(pipe_wm, 0, sizeof(*pipe_wm)); for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { ps = drm_atomic_get_plane_state(state, -- cgit v1.2.3 From d890565c44447db08fd9d07f5b02928a07a88c7e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 14 Jan 2016 14:53:35 +0200 Subject: drm/i915: Use the active wm config for merging on ILK-BDW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ilk_program_watermarks() is supposed to merge the active watermarks from all pipes. Thus we need to use the active config too instead of some precomputed stuff. Fixes: aa363136866c ("drm/i915: Calculate watermark configuration during atomic check (v2)") Cc: Matt Roper Signed-off-by: Ville Syrjälä Reviewed-by: Matt Roper Link: http://patchwork.freedesktop.org/patch/msgid/1452776015-22076-2-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_pm.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 966c4c2c416f..6b2b3e331a09 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3680,23 +3680,43 @@ static void skl_update_wm(struct drm_crtc *crtc) dev_priv->wm.skl_hw = *results; } +static void ilk_compute_wm_config(struct drm_device *dev, + struct intel_wm_config *config) +{ + struct intel_crtc *crtc; + + /* Compute the currently _active_ config */ + for_each_intel_crtc(dev, crtc) { + const struct intel_pipe_wm *wm = &crtc->wm.active.ilk; + + if (!wm->pipe_enabled) + continue; + + config->sprites_enabled |= wm->sprites_enabled; + config->sprites_scaled |= wm->sprites_scaled; + config->num_pipes_active++; + } +} + static void ilk_program_watermarks(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm; struct ilk_wm_maximums max; - struct intel_wm_config *config = &dev_priv->wm.config; + struct intel_wm_config config = {}; struct ilk_wm_values results = {}; enum intel_ddb_partitioning partitioning; - ilk_compute_wm_maximums(dev, 1, config, INTEL_DDB_PART_1_2, &max); - ilk_wm_merge(dev, config, &max, &lp_wm_1_2); + ilk_compute_wm_config(dev, &config); + + ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max); + ilk_wm_merge(dev, &config, &max, &lp_wm_1_2); /* 5/6 split only in single pipe config on IVB+ */ if (INTEL_INFO(dev)->gen >= 7 && - config->num_pipes_active == 1 && config->sprites_enabled) { - ilk_compute_wm_maximums(dev, 1, config, INTEL_DDB_PART_5_6, &max); - ilk_wm_merge(dev, config, &max, &lp_wm_5_6); + config.num_pipes_active == 1 && config.sprites_enabled) { + ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max); + ilk_wm_merge(dev, &config, &max, &lp_wm_5_6); best_lp_wm = ilk_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6); } else { -- cgit v1.2.3 From 965fd602a6436f689f4f2fe40a6789582778ccd5 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 13 Jan 2016 18:59:39 -0800 Subject: drm/i915: Make sure DC writes are coherent on flush. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to set the DC FLUSH PIPE_CONTROL bit on Gen7+ to guarantee that writes performed via the HDC are visible in memory. Fixes an intermittent failure in a Piglit test that writes to a BO from a shader using GL atomic counters (implemented as HDC untyped atomics) and then expects the memory to read back the same value after mapping it on the CPU. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=91298 Tested-by: Mark Janes Cc: Rodrigo Vivi Cc: stable@vger.kernel.org Signed-off-by: Francisco Jerez Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1452740379-3194-1-git-send-email-currojerez@riseup.net Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_lrc.c | 1 + drivers/gpu/drm/i915/intel_ringbuffer.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 5027699c5291..f5d89c845ede 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1735,6 +1735,7 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request, if (flush_domains) { flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; + flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; flags |= PIPE_CONTROL_FLUSH_ENABLE; } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 4060acf0601a..8cd8aabcc3ff 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -331,6 +331,7 @@ gen7_render_ring_flush(struct drm_i915_gem_request *req, if (flush_domains) { flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; + flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; flags |= PIPE_CONTROL_FLUSH_ENABLE; } if (invalidate_domains) { @@ -403,6 +404,7 @@ gen8_render_ring_flush(struct drm_i915_gem_request *req, if (flush_domains) { flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; + flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; flags |= PIPE_CONTROL_FLUSH_ENABLE; } if (invalidate_domains) { -- cgit v1.2.3 From 6765bd6dd28eb3c087e5011a2944c00872dd5906 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 14 Jan 2016 17:12:07 +0200 Subject: drm/i915/bios: Fix the sequence size calculations for MIPI seq v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two errors in a single line. The size was read from the wrong offset, and the end index didn't take the five bytes for sequence byte and size of sequence into account. Fix it all, and break up the calculations a bit to make it clearer. Cc: Ville Syrjälä Reported-and-tested-by: Mika Kahola Reviewed-by: Ville Syrjälä Fixes: 2a33d93486f2 ("drm/i915/bios: add support for MIPI sequence block v3") Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1452784327-27258-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_bios.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 12e2f8b8bf9c..bf62a19c8f69 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -842,6 +842,7 @@ static int goto_next_sequence_v3(const u8 *data, int index, int total) { int seq_end; u16 len; + u32 size_of_sequence; /* * Could skip sequence based on Size of Sequence alone, but also do some @@ -852,14 +853,24 @@ static int goto_next_sequence_v3(const u8 *data, int index, int total) return 0; } - seq_end = index + *((const u32 *)(data + 1)); + /* Skip Sequence Byte. */ + index++; + + /* + * Size of Sequence. Excludes the Sequence Byte and the size itself, + * includes MIPI_SEQ_ELEM_END byte, excludes the final MIPI_SEQ_END + * byte. + */ + size_of_sequence = *((const uint32_t *)(data + index)); + index += 4; + + seq_end = index + size_of_sequence; if (seq_end > total) { DRM_ERROR("Invalid sequence size\n"); return 0; } - /* Skip Sequence Byte and Size of Sequence. */ - for (index = index + 5; index < total; index += len) { + for (; index < total; index += len) { u8 operation_byte = *(data + index); index++; -- cgit v1.2.3 From 013dd9e038723bbd2aa67be51847384b75be8253 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 13 Jan 2016 16:35:20 +0200 Subject: drm/i915/dp: fall back to 18 bpp when sink capability is unknown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per DP spec, the source device should fall back to 18 bpp, VESA range RGB when the sink capability is unknown. Fix the color depth clamping. 18 bpp color depth should ensure full color range in automatic mode. The clamping has been HDMI specific since its introduction in commit 996a2239f93b03c5972923f04b097f65565c5bed Author: Daniel Vetter Date: Fri Apr 19 11:24:34 2013 +0200 drm/i915: Disable high-bpc on pre-1.4 EDID screens Cc: stable@vger.kernel.org Reported-and-tested-by: Dihan Wickremasuriya Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=105331 Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1452695720-7076-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_display.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index aa24f79d85bf..68a98570f658 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12157,11 +12157,21 @@ connected_sink_compute_bpp(struct intel_connector *connector, pipe_config->pipe_bpp = connector->base.display_info.bpc*3; } - /* Clamp bpp to 8 on screens without EDID 1.4 */ - if (connector->base.display_info.bpc == 0 && bpp > 24) { - DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of 24\n", - bpp); - pipe_config->pipe_bpp = 24; + /* Clamp bpp to default limit on screens without EDID 1.4 */ + if (connector->base.display_info.bpc == 0) { + int type = connector->base.connector_type; + int clamp_bpp = 24; + + /* Fall back to 18 bpp when DP sink capability is unknown. */ + if (type == DRM_MODE_CONNECTOR_DisplayPort || + type == DRM_MODE_CONNECTOR_eDP) + clamp_bpp = 18; + + if (bpp > clamp_bpp) { + DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of %d\n", + bpp, clamp_bpp); + pipe_config->pipe_bpp = clamp_bpp; + } } } -- cgit v1.2.3 From f02b4b72d12cbae7020a959e2ed0410a464b4cc4 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 15 Jan 2016 11:34:21 +0100 Subject: clockevents/tcb_clksrc: Prevent disabling an already disabled clock clockevents_exchange_device is calling clockevents_shutdown() on the new clockenvents device but it may have never been enabled in the first place. This results in the tcb clock being disabled without being enabled first: ------------[ cut here ]------------ WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:680 clk_disable+0x28/0x34() Modules linked in: CPU: 0 PID: 1 Comm: swapper Not tainted 4.4.0+ #6 Hardware name: Atmel AT91SAM9 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (warn_slowpath_common+0x78/0xa0) [] (warn_slowpath_common) from [] (warn_slowpath_null+0x18/0x20) [] (warn_slowpath_null) from [] (clk_disable+0x28/0x34) [] (clk_disable) from [] (tc_shutdown+0x38/0x4c) [] (tc_shutdown) from [] (clockevents_switch_state+0x38/0x6c) [] (clockevents_switch_state) from [] (clockevents_shutdown+0x10/0x24) [] (clockevents_shutdown) from [] (tick_check_new_device+0x84/0xac) [] (tick_check_new_device) from [] (clockevents_register_device+0x7c/0x108) [] (clockevents_register_device) from [] (tcb_clksrc_init+0x390/0x3e8) [] (tcb_clksrc_init) from [] (do_one_initcall+0x114/0x1d4) [] (do_one_initcall) from [] (kernel_init_freeable+0xfc/0x1b8) [] (kernel_init_freeable) from [] (kernel_init+0x8/0xe0) [] (kernel_init) from [] (ret_from_fork+0x14/0x24) ---[ end trace 0000000000000001 ]--- Check what state we were in before trying to disable the clock. Fixes: cf4541c101ea ("clockevents/drivers/tcb_clksrc: Migrate to new 'set-state' interface") Signed-off-by: Alexandre Belloni Cc: Nicolas Ferre Cc: Boris Brezillon Cc: linux-arm-kernel@lists.infradead.org Cc: Daniel Lezcano Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1452854061-30370-1-git-send-email-alexandre.belloni@free-electrons.com Signed-off-by: Thomas Gleixner --- drivers/clocksource/tcb_clksrc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c index 6ee91401918e..4da2af9694a2 100644 --- a/drivers/clocksource/tcb_clksrc.c +++ b/drivers/clocksource/tcb_clksrc.c @@ -98,7 +98,8 @@ static int tc_shutdown(struct clock_event_device *d) __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR)); __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR)); - clk_disable(tcd->clk); + if (!clockevent_state_detached(d)) + clk_disable(tcd->clk); return 0; } -- cgit v1.2.3 From e160e4db833c7e8587ec3c88efaed0d84f1bcf42 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 14 Jan 2016 13:48:24 -0500 Subject: drm/amdgpu: fix tonga smu resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Need to make sure smu buffers are pinned on resume. This matches what Fiji does. Cc: stable@vger.kernel.org Reviewed-by: Junwei Zhang Reviewed-by: Christian König Reviewed-by: Ken Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/tonga_dpm.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c b/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c index f4a1346525fe..0497784b3652 100644 --- a/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c @@ -122,25 +122,12 @@ static int tonga_dpm_hw_fini(void *handle) static int tonga_dpm_suspend(void *handle) { - return 0; + return tonga_dpm_hw_fini(handle); } static int tonga_dpm_resume(void *handle) { - int ret; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - mutex_lock(&adev->pm.mutex); - - ret = tonga_smu_start(adev); - if (ret) { - DRM_ERROR("SMU start failed\n"); - goto fail; - } - -fail: - mutex_unlock(&adev->pm.mutex); - return ret; + return tonga_dpm_hw_init(handle); } static int tonga_dpm_set_clockgating_state(void *handle, -- cgit v1.2.3 From 7776a69386179ea477f501aa222692b9856ec56c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Oct 2015 10:59:16 -0400 Subject: drm/amdgpu: Add some tweaks to gfx 8 soft reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Junwei Zhang Reviewed-by: Christian König Reviewed-by: Ken Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 13235d84e5a6..95c0cdfbd1b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -4186,7 +4186,18 @@ static int gfx_v8_0_soft_reset(void *handle) gfx_v8_0_cp_gfx_enable(adev, false); /* Disable MEC parsing/prefetching */ - /* XXX todo */ + gfx_v8_0_cp_compute_enable(adev, false); + + if (grbm_soft_reset || srbm_soft_reset) { + tmp = RREG32(mmGMCON_DEBUG); + tmp = REG_SET_FIELD(tmp, + GMCON_DEBUG, GFX_STALL, 1); + tmp = REG_SET_FIELD(tmp, + GMCON_DEBUG, GFX_CLEAR, 1); + WREG32(mmGMCON_DEBUG, tmp); + + udelay(50); + } if (grbm_soft_reset) { tmp = RREG32(mmGRBM_SOFT_RESET); @@ -4215,6 +4226,16 @@ static int gfx_v8_0_soft_reset(void *handle) WREG32(mmSRBM_SOFT_RESET, tmp); tmp = RREG32(mmSRBM_SOFT_RESET); } + + if (grbm_soft_reset || srbm_soft_reset) { + tmp = RREG32(mmGMCON_DEBUG); + tmp = REG_SET_FIELD(tmp, + GMCON_DEBUG, GFX_STALL, 0); + tmp = REG_SET_FIELD(tmp, + GMCON_DEBUG, GFX_CLEAR, 0); + WREG32(mmGMCON_DEBUG, tmp); + } + /* Wait a little for things to settle down */ udelay(50); gfx_v8_0_print_status((void *)adev); -- cgit v1.2.3 From 92752d9974882e2e5384e92668f02a134f9c7463 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 15 Jan 2016 14:46:29 +0100 Subject: mtd: mtk-nor: Drop bogus __init from mtk_nor_init() WARNING: drivers/mtd/spi-nor/mtk-quadspi.o(.text+0x77e): Section mismatch in reference from the function mtk_nor_drv_probe() to the function .init.text:mtk_nor_init() The function mtk_nor_drv_probe() references the function __init mtk_nor_init(). This is often because mtk_nor_drv_probe lacks a __init annotation or the annotation of mtk_nor_init is wrong. Drop the bogus __init from mtk_nor_init() to kill this warning. Signed-off-by: Geert Uytterhoeven Signed-off-by: Brian Norris --- drivers/mtd/spi-nor/mtk-quadspi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/spi-nor/mtk-quadspi.c b/drivers/mtd/spi-nor/mtk-quadspi.c index d5f850d035bb..8bed1a4cb79c 100644 --- a/drivers/mtd/spi-nor/mtk-quadspi.c +++ b/drivers/mtd/spi-nor/mtk-quadspi.c @@ -371,8 +371,8 @@ static int mt8173_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, return ret; } -static int __init mtk_nor_init(struct mt8173_nor *mt8173_nor, - struct device_node *flash_node) +static int mtk_nor_init(struct mt8173_nor *mt8173_nor, + struct device_node *flash_node) { int ret; struct spi_nor *nor; -- cgit v1.2.3 From f9bdbd6c46c8ce0bb95f5b708a4a4a4b6b9a5917 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 13 Jan 2016 22:38:08 +0100 Subject: mtd: nuc900_nand: read correct SMISR register The nuc900_nand driver has always passed an incorrect register address in its nuc900_check_rb() function, which cannot possibly work, and in some configurations gives us a build warning: drivers/mtd/nand/nuc900_nand.c: In function 'nuc900_check_rb': drivers/mtd/nand/nuc900_nand.c:27:23: warning: passing argument 1 of '__raw_readl' makes pointer from integer without a cast [-Wint-conversion] #define REG_SMISR 0xac drivers/mtd/nand/nuc900_nand.c:118:20: note: in expansion of macro 'REG_SMISR' val = __raw_readl(REG_SMISR); This makes sure we actually read from the register rather than from (void *)0x000000ac in user space. I suspect nobody noticed this before because the nuc900_nand_devready() function never gets called, or nobody uses this driver on an upstream kernel. Possibly even both. Signed-off-by: Arnd Bergmann Signed-off-by: Brian Norris --- drivers/mtd/nand/nuc900_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index 220ddfcf29f5..dbc5b571c2bb 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c @@ -113,7 +113,7 @@ static int nuc900_check_rb(struct nuc900_nand *nand) { unsigned int val; spin_lock(&nand->lock); - val = __raw_readl(REG_SMISR); + val = __raw_readl(nand->reg + REG_SMISR); val &= READYBUSY; spin_unlock(&nand->lock); -- cgit v1.2.3 From ab7cad331155bab5e81381b5e34a333220718385 Mon Sep 17 00:00:00 2001 From: zhangqing Date: Tue, 12 Jan 2016 03:05:56 -0800 Subject: regulator: fan53555: fill set_suspend_enable/disable callback Setting the set_suspend_enable/disable callback to support enable and disable the dcdc when system is suspend. Signed-off-by: zhangqing Reviewed-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/fan53555.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 4940e8287df6..2cb5cc311610 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -114,6 +114,22 @@ static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV) return 0; } +static int fan53555_set_suspend_enable(struct regulator_dev *rdev) +{ + struct fan53555_device_info *di = rdev_get_drvdata(rdev); + + return regmap_update_bits(di->regmap, di->sleep_reg, + VSEL_BUCK_EN, VSEL_BUCK_EN); +} + +static int fan53555_set_suspend_disable(struct regulator_dev *rdev) +{ + struct fan53555_device_info *di = rdev_get_drvdata(rdev); + + return regmap_update_bits(di->regmap, di->sleep_reg, + VSEL_BUCK_EN, 0); +} + static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode) { struct fan53555_device_info *di = rdev_get_drvdata(rdev); @@ -192,6 +208,8 @@ static struct regulator_ops fan53555_regulator_ops = { .set_mode = fan53555_set_mode, .get_mode = fan53555_get_mode, .set_ramp_delay = fan53555_set_ramp, + .set_suspend_enable = fan53555_set_suspend_enable, + .set_suspend_disable = fan53555_set_suspend_disable, }; static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di) -- cgit v1.2.3 From 0f48eedacf1914c000c7bebdc44de15412baa6f1 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 12 Jan 2016 18:28:51 +0100 Subject: regulator: da9210: fix lockdep warning Commit 70cfef26267474 ("regulator: Add lockdep asserts to help detecting locking misuse") successfully created this WARN, let's fix it: [ 1.218660] WARNING: CPU: 0 PID: 553 at drivers/regulator/core.c:3646 regulator_notifier_call_chain+0x5c/0x88() ... [ 1.220278] [] (regulator_notifier_call_chain) from [] (da9210_irq_handler+0x74/0x10c) [ 1.220412] r7:c0080cac r6:eb1daa00 r5:e64bbf10 r4:00000002 [ 1.220547] [] (da9210_irq_handler) from [] (irq_thread_fn+0x2c/0x44) ... Signed-off-by: Wolfram Sang Signed-off-by: Mark Brown --- drivers/regulator/da9210-regulator.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c index b3517830edb6..cfd6e8af67ec 100644 --- a/drivers/regulator/da9210-regulator.c +++ b/drivers/regulator/da9210-regulator.c @@ -132,6 +132,8 @@ static irqreturn_t da9210_irq_handler(int irq, void *data) if (error < 0) goto error_i2c; + mutex_lock(&chip->rdev->mutex); + if (val & DA9210_E_OVCURR) { regulator_notifier_call_chain(chip->rdev, REGULATOR_EVENT_OVER_CURRENT, @@ -155,6 +157,9 @@ static irqreturn_t da9210_irq_handler(int irq, void *data) NULL); handled |= DA9210_E_VMAX; } + + mutex_unlock(&chip->rdev->mutex); + if (handled) { /* Clear handled events */ error = regmap_write(chip->regmap, DA9210_REG_EVENT_B, handled); -- cgit v1.2.3 From 22a33632fb607a18148815548478265a672d5295 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Wed, 13 Jan 2016 16:20:07 +0200 Subject: spi: pxa2xx: Remove CONFIG_SPI_PXA2XX_DMA After removal of legacy PXA DMA code by the commit 6356437e65c2 ("spi: spi-pxa2xx: remove legacy PXA DMA bits") the CONFIG_SPI_PXA2XX_DMA follows the CONFIG_SPI_PXA2XX and cannot be disabled alone. Therefore remove this config symbol and dead definitions from the spi-pxa2xx.h. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 4 ---- drivers/spi/Makefile | 3 +-- drivers/spi/spi-pxa2xx.h | 35 ----------------------------------- 3 files changed, 1 insertion(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 8b9c2a38d1cc..c0604aecf45f 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -415,10 +415,6 @@ config SPI_PPC4xx help This selects a driver for the PPC4xx SPI Controller. -config SPI_PXA2XX_DMA - def_bool y - depends on SPI_PXA2XX - config SPI_PXA2XX tristate "PXA2xx SSP SPI master" depends on (ARCH_PXA || PCI || ACPI) diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 31fb7fb2a0b6..13cee44ec94d 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -61,8 +61,7 @@ obj-$(CONFIG_SPI_TI_QSPI) += spi-ti-qspi.o obj-$(CONFIG_SPI_ORION) += spi-orion.o obj-$(CONFIG_SPI_PL022) += spi-pl022.o obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o -spi-pxa2xx-platform-objs := spi-pxa2xx.o -spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA) += spi-pxa2xx-dma.o +spi-pxa2xx-platform-objs := spi-pxa2xx.o spi-pxa2xx-dma.o obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o obj-$(CONFIG_SPI_QUP) += spi-qup.o diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h index 58efa98313aa..8e781c8b4374 100644 --- a/drivers/spi/spi-pxa2xx.h +++ b/drivers/spi/spi-pxa2xx.h @@ -147,20 +147,9 @@ static inline void write_SSSR_CS(struct driver_data *drv_data, u32 val) extern int pxa2xx_spi_flush(struct driver_data *drv_data); extern void *pxa2xx_spi_next_transfer(struct driver_data *drv_data); -/* - * Select the right DMA implementation. - */ -#if defined(CONFIG_SPI_PXA2XX_DMA) -#define SPI_PXA2XX_USE_DMA 1 #define MAX_DMA_LEN SZ_64K #define DEFAULT_DMA_CR1 (SSCR1_TSRE | SSCR1_RSRE | SSCR1_TRAIL) -#else -#undef SPI_PXA2XX_USE_DMA -#define MAX_DMA_LEN 0 -#define DEFAULT_DMA_CR1 0 -#endif -#ifdef SPI_PXA2XX_USE_DMA extern bool pxa2xx_spi_dma_is_possible(size_t len); extern int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data); extern irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data); @@ -173,29 +162,5 @@ extern int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip, u8 bits_per_word, u32 *burst_code, u32 *threshold); -#else -static inline bool pxa2xx_spi_dma_is_possible(size_t len) { return false; } -static inline int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data) -{ - return 0; -} -#define pxa2xx_spi_dma_transfer NULL -static inline void pxa2xx_spi_dma_prepare(struct driver_data *drv_data, - u32 dma_burst) {} -static inline void pxa2xx_spi_dma_start(struct driver_data *drv_data) {} -static inline int pxa2xx_spi_dma_setup(struct driver_data *drv_data) -{ - return 0; -} -static inline void pxa2xx_spi_dma_release(struct driver_data *drv_data) {} -static inline int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip, - struct spi_device *spi, - u8 bits_per_word, - u32 *burst_code, - u32 *threshold) -{ - return -ENODEV; -} -#endif #endif /* SPI_PXA2XX_H */ -- cgit v1.2.3 From ebea7c0545d4d5e554b84c3ee8072f13c3fdd2ba Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 13 Jan 2016 21:51:29 +0100 Subject: spi: fix counting in spi-loopback-test code These variables are always used uninitialized: drivers/spi/spi-loopback-test.c: In function 'spi_test_run_iter': drivers/spi/spi-loopback-test.c:768:17: warning: 'rx_count' may be used uninitialized in this function [-Wmaybe-uninitialized] drivers/spi/spi-loopback-test.c:762:17: warning: 'tx_count' may be used uninitialized in this function [-Wmaybe-uninitialized] Adding an explicit initialization seems to be the only workable solution here, to make the code behave correctly and build without warning. Fixes: 84e0c4e5e2c4 ("spi: add loopback test driver to allow for spi_master regression tests") Signed-off-by: Arnd Bergmann Acked-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/spi/spi-loopback-test.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c index 894616f687b0..cf4bb36bee25 100644 --- a/drivers/spi/spi-loopback-test.c +++ b/drivers/spi/spi-loopback-test.c @@ -761,6 +761,7 @@ static int spi_test_run_iter(struct spi_device *spi, test.iterate_transfer_mask = 1; /* count number of transfers with tx/rx_buf != NULL */ + rx_count = tx_count = 0; for (i = 0; i < test.transfer_count; i++) { if (test.transfers[i].tx_buf) tx_count++; -- cgit v1.2.3 From d51fe1f393a6b99e9133a3360036af2c21983ec2 Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Wed, 13 Jan 2016 22:41:12 +0100 Subject: regmap: pass buffer size to regmap_raw_read() in regcache_hw_init() regcache_hw_init() uses regmap_raw_read() to initialize cache when reg_defaults_raw isn't provided. The last parameter to regmap_raw_read() is buffer size in bytes, however regcache_hw_init() called it with number of registers to read instead, which cause problem if they aren't one byte wide in cache. This wasn't triggered by any of current in-tree drivers since they either have one-byte registers or provide reg_defaults_raw explicitly. Signed-off-by: Maciej S. Szmigiero Signed-off-by: Mark Brown --- drivers/base/regmap/regcache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 4c07802986b2..45ae91eb6be9 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -57,7 +57,7 @@ static int regcache_hw_init(struct regmap *map) bool cache_bypass = map->cache_bypass; dev_warn(map->dev, "No cache defaults, reading back from HW\n"); - /* Bypass the cache access till data read from HW*/ + /* Bypass the cache access till data read from HW */ map->cache_bypass = true; tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL); if (!tmp_buf) { @@ -65,7 +65,7 @@ static int regcache_hw_init(struct regmap *map) goto err_free; } ret = regmap_raw_read(map, 0, tmp_buf, - map->num_reg_defaults_raw); + map->cache_size_raw); map->cache_bypass = cache_bypass; if (ret < 0) goto err_cache_free; -- cgit v1.2.3 From 0b05e1e0c945ff4e8635890982fafa5434b262d9 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 14 Jan 2016 15:22:09 +0200 Subject: drm/i915: Don't leak framebuffer_references if drm_framebuffer_init() fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't increment obj->framebuffer_references until we know we actually managed to create the framebuffer. Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1452777736-4909-2-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 3 ++- 1 file changed, 2 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 68a98570f658..c532c3d605ac 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14905,7 +14905,6 @@ static int intel_framebuffer_init(struct drm_device *dev, drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); intel_fb->obj = obj; - intel_fb->obj->framebuffer_references++; ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); if (ret) { @@ -14913,6 +14912,8 @@ static int intel_framebuffer_init(struct drm_device *dev, return ret; } + intel_fb->obj->framebuffer_references++; + return 0; } -- cgit v1.2.3 From b5e16987a09ef3e3215f0d14a0d99b4e83ab7e91 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 14 Jan 2016 15:22:10 +0200 Subject: drm/i915: Set i915_ggtt_view_normal type explicitly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just for clarity set the type for i915_ggtt_view_normal explicitly. While at it fix the indentation fail for i915_ggtt_view_rotated. Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1452777736-4909-3-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_gem_gtt.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 56f4f2e58d53..d7f9ddd52840 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -96,9 +96,11 @@ static int i915_get_ggtt_vma_pages(struct i915_vma *vma); -const struct i915_ggtt_view i915_ggtt_view_normal; +const struct i915_ggtt_view i915_ggtt_view_normal = { + .type = I915_GGTT_VIEW_NORMAL, +}; const struct i915_ggtt_view i915_ggtt_view_rotated = { - .type = I915_GGTT_VIEW_ROTATED + .type = I915_GGTT_VIEW_ROTATED, }; static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt) -- cgit v1.2.3 From 2d7f3bdb2cf6656386cb9ca1b02dd6df66fb05e8 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 14 Jan 2016 15:22:11 +0200 Subject: drm/i915: Pass the dma_addr_t array as const to rotate_pages() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rotate_pages() doesn't modify the passed in dma addresses, so make them const. Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1452777736-4909-4-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index d7f9ddd52840..7377b6725c33 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3331,7 +3331,7 @@ i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj, } static struct scatterlist * -rotate_pages(dma_addr_t *in, unsigned int offset, +rotate_pages(const dma_addr_t *in, unsigned int offset, unsigned int width, unsigned int height, struct sg_table *st, struct scatterlist *sg) { -- cgit v1.2.3 From 27e177190891d2ad5174a434d8f09b9315520585 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Thu, 14 Jan 2016 16:38:13 +0100 Subject: iio:adc:at91_adc8xx: introduce new atmel adc driver This driver supports the new version of the Atmel ADC device introduced with the SAMA5D2 SoC family. Signed-off-by: Ludovic Desroches Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/adc/at91-sama5d2_adc.txt | 28 ++ drivers/iio/adc/Kconfig | 11 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/at91-sama5d2_adc.c | 509 +++++++++++++++++++++ 4 files changed, 549 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt create mode 100644 drivers/iio/adc/at91-sama5d2_adc.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt b/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt new file mode 100644 index 000000000000..3223684a643b --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt @@ -0,0 +1,28 @@ +* AT91 SAMA5D2 Analog to Digital Converter (ADC) + +Required properties: + - compatible: Should be "atmel,sama5d2-adc". + - reg: Should contain ADC registers location and length. + - interrupts: Should contain the IRQ line for the ADC. + - clocks: phandle to device clock. + - clock-names: Must be "adc_clk". + - vref-supply: Supply used as reference for conversions. + - vddana-supply: Supply for the adc device. + - atmel,min-sample-rate-hz: Minimum sampling rate, it depends on SoC. + - atmel,max-sample-rate-hz: Maximum sampling rate, it depends on SoC. + - atmel,startup-time-ms: Startup time expressed in ms, it depends on SoC. + +Example: + +adc: adc@fc030000 { + compatible = "atmel,sama5d2-adc"; + reg = <0xfc030000 0x100>; + interrupts = <40 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&adc_clk>; + clock-names = "adc_clk"; + atmel,min-sample-rate-hz = <200000>; + atmel,max-sample-rate-hz = <20000000>; + atmel,startup-time-ms = <4>; + vddana-supply = <&vdd_3v3_lp_reg>; + vref-supply = <&vdd_3v3_lp_reg>; +} diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index d0dc39a95555..af4cb8e167b7 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -131,6 +131,17 @@ config AT91_ADC To compile this driver as a module, choose M here: the module will be called at91_adc. +config AT91_SAMA5D2_ADC + tristate "Atmel AT91 SAMA5D2 ADC" + depends on ARCH_AT91 + depends on INPUT + help + Say yes here to build support for Atmel SAMA5D2 ADC which is + available on SAMA5D2 SoC family. + + To compile this driver as a module, choose M here: the module will be + called at91-sama5d2_adc. + config AXP288_ADC tristate "X-Powers AXP288 ADC driver" depends on MFD_AXP20X diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 6435780e9b71..fb57e12dbde2 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_AD7793) += ad7793.o obj-$(CONFIG_AD7887) += ad7887.o obj-$(CONFIG_AD799X) += ad799x.o obj-$(CONFIG_AT91_ADC) += at91_adc.o +obj-$(CONFIG_AT91_SAMA5D2_ADC) += at91-sama5d2_adc.o obj-$(CONFIG_AXP288_ADC) += axp288_adc.o obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c new file mode 100644 index 000000000000..ecb2d90c9c06 --- /dev/null +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -0,0 +1,509 @@ +/* + * Atmel ADC driver for SAMA5D2 devices and compatible. + * + * Copyright (C) 2015 Atmel, + * 2015 Ludovic Desroches + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Control Register */ +#define AT91_SAMA5D2_CR 0x00 +/* Software Reset */ +#define AT91_SAMA5D2_CR_SWRST BIT(0) +/* Start Conversion */ +#define AT91_SAMA5D2_CR_START BIT(1) +/* Touchscreen Calibration */ +#define AT91_SAMA5D2_CR_TSCALIB BIT(2) +/* Comparison Restart */ +#define AT91_SAMA5D2_CR_CMPRST BIT(4) + +/* Mode Register */ +#define AT91_SAMA5D2_MR 0x04 +/* Trigger Selection */ +#define AT91_SAMA5D2_MR_TRGSEL(v) ((v) << 1) +/* ADTRG */ +#define AT91_SAMA5D2_MR_TRGSEL_TRIG0 0 +/* TIOA0 */ +#define AT91_SAMA5D2_MR_TRGSEL_TRIG1 1 +/* TIOA1 */ +#define AT91_SAMA5D2_MR_TRGSEL_TRIG2 2 +/* TIOA2 */ +#define AT91_SAMA5D2_MR_TRGSEL_TRIG3 3 +/* PWM event line 0 */ +#define AT91_SAMA5D2_MR_TRGSEL_TRIG4 4 +/* PWM event line 1 */ +#define AT91_SAMA5D2_MR_TRGSEL_TRIG5 5 +/* TIOA3 */ +#define AT91_SAMA5D2_MR_TRGSEL_TRIG6 6 +/* RTCOUT0 */ +#define AT91_SAMA5D2_MR_TRGSEL_TRIG7 7 +/* Sleep Mode */ +#define AT91_SAMA5D2_MR_SLEEP BIT(5) +/* Fast Wake Up */ +#define AT91_SAMA5D2_MR_FWUP BIT(6) +/* Prescaler Rate Selection */ +#define AT91_SAMA5D2_MR_PRESCAL(v) ((v) << AT91_SAMA5D2_MR_PRESCAL_OFFSET) +#define AT91_SAMA5D2_MR_PRESCAL_OFFSET 8 +#define AT91_SAMA5D2_MR_PRESCAL_MAX 0xff +/* Startup Time */ +#define AT91_SAMA5D2_MR_STARTUP(v) ((v) << 16) +/* Analog Change */ +#define AT91_SAMA5D2_MR_ANACH BIT(23) +/* Tracking Time */ +#define AT91_SAMA5D2_MR_TRACKTIM(v) ((v) << 24) +#define AT91_SAMA5D2_MR_TRACKTIM_MAX 0xff +/* Transfer Time */ +#define AT91_SAMA5D2_MR_TRANSFER(v) ((v) << 28) +#define AT91_SAMA5D2_MR_TRANSFER_MAX 0x3 +/* Use Sequence Enable */ +#define AT91_SAMA5D2_MR_USEQ BIT(31) + +/* Channel Sequence Register 1 */ +#define AT91_SAMA5D2_SEQR1 0x08 +/* Channel Sequence Register 2 */ +#define AT91_SAMA5D2_SEQR2 0x0c +/* Channel Enable Register */ +#define AT91_SAMA5D2_CHER 0x10 +/* Channel Disable Register */ +#define AT91_SAMA5D2_CHDR 0x14 +/* Channel Status Register */ +#define AT91_SAMA5D2_CHSR 0x18 +/* Last Converted Data Register */ +#define AT91_SAMA5D2_LCDR 0x20 +/* Interrupt Enable Register */ +#define AT91_SAMA5D2_IER 0x24 +/* Interrupt Disable Register */ +#define AT91_SAMA5D2_IDR 0x28 +/* Interrupt Mask Register */ +#define AT91_SAMA5D2_IMR 0x2c +/* Interrupt Status Register */ +#define AT91_SAMA5D2_ISR 0x30 +/* Last Channel Trigger Mode Register */ +#define AT91_SAMA5D2_LCTMR 0x34 +/* Last Channel Compare Window Register */ +#define AT91_SAMA5D2_LCCWR 0x38 +/* Overrun Status Register */ +#define AT91_SAMA5D2_OVER 0x3c +/* Extended Mode Register */ +#define AT91_SAMA5D2_EMR 0x40 +/* Compare Window Register */ +#define AT91_SAMA5D2_CWR 0x44 +/* Channel Gain Register */ +#define AT91_SAMA5D2_CGR 0x48 +/* Channel Offset Register */ +#define AT91_SAMA5D2_COR 0x4c +/* Channel Data Register 0 */ +#define AT91_SAMA5D2_CDR0 0x50 +/* Analog Control Register */ +#define AT91_SAMA5D2_ACR 0x94 +/* Touchscreen Mode Register */ +#define AT91_SAMA5D2_TSMR 0xb0 +/* Touchscreen X Position Register */ +#define AT91_SAMA5D2_XPOSR 0xb4 +/* Touchscreen Y Position Register */ +#define AT91_SAMA5D2_YPOSR 0xb8 +/* Touchscreen Pressure Register */ +#define AT91_SAMA5D2_PRESSR 0xbc +/* Trigger Register */ +#define AT91_SAMA5D2_TRGR 0xc0 +/* Correction Select Register */ +#define AT91_SAMA5D2_COSR 0xd0 +/* Correction Value Register */ +#define AT91_SAMA5D2_CVR 0xd4 +/* Channel Error Correction Register */ +#define AT91_SAMA5D2_CECR 0xd8 +/* Write Protection Mode Register */ +#define AT91_SAMA5D2_WPMR 0xe4 +/* Write Protection Status Register */ +#define AT91_SAMA5D2_WPSR 0xe8 +/* Version Register */ +#define AT91_SAMA5D2_VERSION 0xfc + +#define AT91_AT91_SAMA5D2_CHAN(num, addr) \ + { \ + .type = IIO_VOLTAGE, \ + .channel = num, \ + .address = addr, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 12, \ + }, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ + .datasheet_name = "CH"#num, \ + .indexed = 1, \ + } + +#define at91_adc_readl(st, reg) readl_relaxed(st->base + reg) +#define at91_adc_writel(st, reg, val) writel_relaxed(val, st->base + reg) + +struct at91_adc_soc_info { + unsigned startup_time; + unsigned min_sample_rate; + unsigned max_sample_rate; +}; + +struct at91_adc_state { + void __iomem *base; + int irq; + struct clk *per_clk; + struct regulator *reg; + struct regulator *vref; + u32 vref_uv; + const struct iio_chan_spec *chan; + bool conversion_done; + u32 conversion_value; + struct at91_adc_soc_info soc_info; + wait_queue_head_t wq_data_available; + /* + * lock to prevent concurrent 'single conversion' requests through + * sysfs. + */ + struct mutex lock; +}; + +static const struct iio_chan_spec at91_adc_channels[] = { + AT91_AT91_SAMA5D2_CHAN(0, 0x50), + AT91_AT91_SAMA5D2_CHAN(1, 0x54), + AT91_AT91_SAMA5D2_CHAN(2, 0x58), + AT91_AT91_SAMA5D2_CHAN(3, 0x5c), + AT91_AT91_SAMA5D2_CHAN(4, 0x60), + AT91_AT91_SAMA5D2_CHAN(5, 0x64), + AT91_AT91_SAMA5D2_CHAN(6, 0x68), + AT91_AT91_SAMA5D2_CHAN(7, 0x6c), + AT91_AT91_SAMA5D2_CHAN(8, 0x70), + AT91_AT91_SAMA5D2_CHAN(9, 0x74), + AT91_AT91_SAMA5D2_CHAN(10, 0x78), + AT91_AT91_SAMA5D2_CHAN(11, 0x7c), +}; + +static unsigned at91_adc_startup_time(unsigned startup_time_min, + unsigned adc_clk_khz) +{ + const unsigned startup_lookup[] = { + 0, 8, 16, 24, + 64, 80, 96, 112, + 512, 576, 640, 704, + 768, 832, 896, 960 + }; + unsigned ticks_min, i; + + /* + * Since the adc frequency is checked before, there is no reason + * to not meet the startup time constraint. + */ + + ticks_min = startup_time_min * adc_clk_khz / 1000; + for (i = 0; i < ARRAY_SIZE(startup_lookup); i++) + if (startup_lookup[i] > ticks_min) + break; + + return i; +} + +static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq) +{ + struct iio_dev *indio_dev = iio_priv_to_dev(st); + unsigned f_per, prescal, startup; + + f_per = clk_get_rate(st->per_clk); + prescal = (f_per / (2 * freq)) - 1; + + startup = at91_adc_startup_time(st->soc_info.startup_time, + freq / 1000); + + at91_adc_writel(st, AT91_SAMA5D2_MR, + AT91_SAMA5D2_MR_TRANSFER(2) + | AT91_SAMA5D2_MR_STARTUP(startup) + | AT91_SAMA5D2_MR_PRESCAL(prescal)); + + dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u\n", + freq, startup, prescal); +} + +static unsigned at91_adc_get_sample_freq(struct at91_adc_state *st) +{ + unsigned f_adc, f_per = clk_get_rate(st->per_clk); + unsigned mr, prescal; + + mr = at91_adc_readl(st, AT91_SAMA5D2_MR); + prescal = (mr >> AT91_SAMA5D2_MR_PRESCAL_OFFSET) + & AT91_SAMA5D2_MR_PRESCAL_MAX; + f_adc = f_per / (2 * (prescal + 1)); + + return f_adc; +} + +static irqreturn_t at91_adc_interrupt(int irq, void *private) +{ + struct iio_dev *indio = private; + struct at91_adc_state *st = iio_priv(indio); + u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR); + u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR); + + if (status & imr) { + st->conversion_value = at91_adc_readl(st, st->chan->address); + st->conversion_done = true; + wake_up_interruptible(&st->wq_data_available); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static int at91_adc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct at91_adc_state *st = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&st->lock); + + st->chan = chan; + + at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel)); + at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel)); + at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START); + + ret = wait_event_interruptible_timeout(st->wq_data_available, + st->conversion_done, + msecs_to_jiffies(1000)); + if (ret == 0) + ret = -ETIMEDOUT; + + if (ret > 0) { + *val = st->conversion_value; + ret = IIO_VAL_INT; + st->conversion_done = false; + } + + at91_adc_writel(st, AT91_SAMA5D2_IDR, BIT(chan->channel)); + at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel)); + + mutex_unlock(&st->lock); + return ret; + + case IIO_CHAN_INFO_SCALE: + *val = st->vref_uv / 1000; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; + + case IIO_CHAN_INFO_SAMP_FREQ: + *val = at91_adc_get_sample_freq(st); + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + +static int at91_adc_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct at91_adc_state *st = iio_priv(indio_dev); + + if (mask != IIO_CHAN_INFO_SAMP_FREQ) + return -EINVAL; + + if (val < st->soc_info.min_sample_rate || + val > st->soc_info.max_sample_rate) + return -EINVAL; + + at91_adc_setup_samp_freq(st, val); + + return 0; +} + +static const struct iio_info at91_adc_info = { + .read_raw = &at91_adc_read_raw, + .write_raw = &at91_adc_write_raw, + .driver_module = THIS_MODULE, +}; + +static int at91_adc_probe(struct platform_device *pdev) +{ + struct iio_dev *indio_dev; + struct at91_adc_state *st; + struct resource *res; + int ret; + + indio_dev = devm_iio_device_alloc(&pdev->dev, + sizeof(struct at91_adc_state)); + if (!indio_dev) + return -ENOMEM; + + indio_dev->dev.parent = &pdev->dev; + indio_dev->name = dev_name(&pdev->dev); + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &at91_adc_info; + indio_dev->channels = at91_adc_channels; + indio_dev->num_channels = ARRAY_SIZE(at91_adc_channels); + + st = iio_priv(indio_dev); + + ret = of_property_read_u32(pdev->dev.of_node, + "atmel,min-sample-rate-hz", + &st->soc_info.min_sample_rate); + if (ret) { + dev_err(&pdev->dev, + "invalid or missing value for atmel,min-sample-rate-hz\n"); + return ret; + } + + ret = of_property_read_u32(pdev->dev.of_node, + "atmel,max-sample-rate-hz", + &st->soc_info.max_sample_rate); + if (ret) { + dev_err(&pdev->dev, + "invalid or missing value for atmel,max-sample-rate-hz\n"); + return ret; + } + + ret = of_property_read_u32(pdev->dev.of_node, "atmel,startup-time-ms", + &st->soc_info.startup_time); + if (ret) { + dev_err(&pdev->dev, + "invalid or missing value for atmel,startup-time-ms\n"); + return ret; + } + + init_waitqueue_head(&st->wq_data_available); + mutex_init(&st->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + + st->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(st->base)) + return PTR_ERR(st->base); + + st->irq = platform_get_irq(pdev, 0); + if (st->irq <= 0) { + if (!st->irq) + st->irq = -ENXIO; + + return st->irq; + } + + st->per_clk = devm_clk_get(&pdev->dev, "adc_clk"); + if (IS_ERR(st->per_clk)) + return PTR_ERR(st->per_clk); + + st->reg = devm_regulator_get(&pdev->dev, "vddana"); + if (IS_ERR(st->reg)) + return PTR_ERR(st->reg); + + st->vref = devm_regulator_get(&pdev->dev, "vref"); + if (IS_ERR(st->vref)) + return PTR_ERR(st->vref); + + ret = devm_request_irq(&pdev->dev, st->irq, at91_adc_interrupt, 0, + pdev->dev.driver->name, indio_dev); + if (ret) + return ret; + + ret = regulator_enable(st->reg); + if (ret) + return ret; + + ret = regulator_enable(st->vref); + if (ret) + goto reg_disable; + + st->vref_uv = regulator_get_voltage(st->vref); + if (st->vref_uv <= 0) { + ret = -EINVAL; + goto vref_disable; + } + + at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST); + at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff); + + at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate); + + ret = clk_prepare_enable(st->per_clk); + if (ret) + goto vref_disable; + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto per_clk_disable_unprepare; + + dev_info(&pdev->dev, "version: %x\n", + readl_relaxed(st->base + AT91_SAMA5D2_VERSION)); + + return 0; + +per_clk_disable_unprepare: + clk_disable_unprepare(st->per_clk); +vref_disable: + regulator_disable(st->vref); +reg_disable: + regulator_disable(st->reg); + return ret; +} + +static int at91_adc_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct at91_adc_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + clk_disable_unprepare(st->per_clk); + + regulator_disable(st->vref); + regulator_disable(st->reg); + + return 0; +} + +static const struct of_device_id at91_adc_dt_match[] = { + { + .compatible = "atmel,sama5d2-adc", + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, at91_adc_dt_match); + +static struct platform_driver at91_adc_driver = { + .probe = at91_adc_probe, + .remove = at91_adc_remove, + .driver = { + .name = "at91-sama5d2_adc", + .of_match_table = at91_adc_dt_match, + }, +}; +module_platform_driver(at91_adc_driver) + +MODULE_AUTHOR("Ludovic Desroches "); +MODULE_DESCRIPTION("Atmel AT91 SAMA5D2 ADC"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From b9cd7a254d17dac8098517afdebdac482e59aec4 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Fri, 15 Jan 2016 09:54:18 +0100 Subject: MAINTAINERS: add entry for Atmel SAMA5D2 ADC driver Signed-off-by: Ludovic Desroches Signed-off-by: Jonathan Cameron --- MAINTAINERS | 6 ++++++ drivers/iio/adc/Kconfig | 3 +-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 9bff63cf326e..6ddb488d78f6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1903,6 +1903,12 @@ M: Nicolas Ferre S: Supported F: drivers/tty/serial/atmel_serial.c +ATMEL SAMA5D2 ADC DRIVER +M: Ludovic Desroches +L: linux-iio@vger.kernel.org +S: Supported +F: drivers/iio/adc/at91-sama5d2_adc.c + ATMEL Audio ALSA driver M: Nicolas Ferre L: alsa-devel@alsa-project.org (moderated for non-subscribers) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index af4cb8e167b7..60673b40f2c3 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -133,8 +133,7 @@ config AT91_ADC config AT91_SAMA5D2_ADC tristate "Atmel AT91 SAMA5D2 ADC" - depends on ARCH_AT91 - depends on INPUT + depends on ARCH_AT91 || COMPILE_TEST help Say yes here to build support for Atmel SAMA5D2 ADC which is available on SAMA5D2 SoC family. -- cgit v1.2.3 From fa34e6dd44d7c02c8a8468ce4a52a7506f907bef Mon Sep 17 00:00:00 2001 From: Gabriele Mazzotta Date: Tue, 12 Jan 2016 16:21:39 +0100 Subject: iio: light: acpi-als: Report data as processed As per the ACPI specification (Revision 5.0) [1], the data coming from the sensor represent the ambient light illuminance reading expressed in lux. So use IIO_CHAN_INFO_PROCESSED to signify that the data are pre-processed. However, to keep backward ABI compatibility, the IIO_CHAN_INFO_RAW bit is not removed. [1] http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf This issue has also been responsible for at least one userspace bug report hence marking what is a small semantic fix really for stable. [2] https://github.com/hadess/iio-sensor-proxy/issues/46 Signed-off-by: Gabriele Mazzotta Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/light/acpi-als.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/light/acpi-als.c b/drivers/iio/light/acpi-als.c index 60537ec0c923..53201d99a16c 100644 --- a/drivers/iio/light/acpi-als.c +++ b/drivers/iio/light/acpi-als.c @@ -54,7 +54,9 @@ static const struct iio_chan_spec acpi_als_channels[] = { .realbits = 32, .storagebits = 32, }, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + /* _RAW is here for backward ABI compatibility */ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_PROCESSED), }, }; @@ -152,7 +154,7 @@ static int acpi_als_read_raw(struct iio_dev *indio_dev, s32 temp_val; int ret; - if (mask != IIO_CHAN_INFO_RAW) + if ((mask != IIO_CHAN_INFO_PROCESSED) && (mask != IIO_CHAN_INFO_RAW)) return -EINVAL; /* we support only illumination (_ALI) so far. */ -- cgit v1.2.3 From 4ea71e5cee8ad52407ee95c3548d0887eedae301 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 8 Jan 2016 00:40:30 +0900 Subject: iio: adc: mcp320x: support more differential voltage measurement mcp320x driver supports the pseudo-differential mode by in_voltage'IN+'-voltage'IN-'_raw where (IN+, IN-) = (0, 1), (2, 3), ... mcp320x chips except MCP3X01 can also select swapped IN+ and IN- pairs in the pseudo-differential mode. i.e. in_voltage'IN+'-voltage'IN-'_raw where (IN+, IN-) = (1, 0), (3, 2), ... If the voltage level of IN+ is equal to or less than IN-, the resultant code will be 000h. So it is useful to provide these, too. Signed-off-by: Akinobu Mita Cc: Oskar Andero Cc: Jonathan Cameron Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald Cc: linux-iio@vger.kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mcp320x.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c index d1c05f6eed18..a850ca7d1eda 100644 --- a/drivers/iio/adc/mcp320x.c +++ b/drivers/iio/adc/mcp320x.c @@ -187,26 +187,27 @@ out: .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ } -#define MCP320X_VOLTAGE_CHANNEL_DIFF(num) \ +#define MCP320X_VOLTAGE_CHANNEL_DIFF(chan1, chan2) \ { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ - .channel = (num * 2), \ - .channel2 = (num * 2 + 1), \ - .address = (num * 2), \ + .channel = (chan1), \ + .channel2 = (chan2), \ + .address = (chan1), \ .differential = 1, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ } static const struct iio_chan_spec mcp3201_channels[] = { - MCP320X_VOLTAGE_CHANNEL_DIFF(0), + MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1), }; static const struct iio_chan_spec mcp3202_channels[] = { MCP320X_VOLTAGE_CHANNEL(0), MCP320X_VOLTAGE_CHANNEL(1), - MCP320X_VOLTAGE_CHANNEL_DIFF(0), + MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1), + MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0), }; static const struct iio_chan_spec mcp3204_channels[] = { @@ -214,8 +215,10 @@ static const struct iio_chan_spec mcp3204_channels[] = { MCP320X_VOLTAGE_CHANNEL(1), MCP320X_VOLTAGE_CHANNEL(2), MCP320X_VOLTAGE_CHANNEL(3), - MCP320X_VOLTAGE_CHANNEL_DIFF(0), - MCP320X_VOLTAGE_CHANNEL_DIFF(1), + MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1), + MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0), + MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3), + MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2), }; static const struct iio_chan_spec mcp3208_channels[] = { @@ -227,10 +230,14 @@ static const struct iio_chan_spec mcp3208_channels[] = { MCP320X_VOLTAGE_CHANNEL(5), MCP320X_VOLTAGE_CHANNEL(6), MCP320X_VOLTAGE_CHANNEL(7), - MCP320X_VOLTAGE_CHANNEL_DIFF(0), - MCP320X_VOLTAGE_CHANNEL_DIFF(1), - MCP320X_VOLTAGE_CHANNEL_DIFF(2), - MCP320X_VOLTAGE_CHANNEL_DIFF(3), + MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1), + MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0), + MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3), + MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2), + MCP320X_VOLTAGE_CHANNEL_DIFF(4, 5), + MCP320X_VOLTAGE_CHANNEL_DIFF(5, 4), + MCP320X_VOLTAGE_CHANNEL_DIFF(6, 7), + MCP320X_VOLTAGE_CHANNEL_DIFF(7, 6), }; static const struct iio_info mcp320x_info = { -- cgit v1.2.3 From 9d0be85d4e2cfa2519ae16efe7ff4a7150c43c0b Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Fri, 1 Jan 2016 18:05:34 +0000 Subject: iio:adc:ti_am335x_adc Fix buffered mode by identifying as software buffer. Whilst this part has a hardware buffer, the identifcation that IIO cares about is the userspace facing end. It this case we push individual elements from the hardware fifo into the software interface (specifically a kfifo) rather than providing direct reads through to a hardware buffer (as we still do in the sca3000 for example). Technically the original specification as a hardware buffer could be considered wrong, but it didn't matter until the patch listed below. Result is that any attempt to enable the buffer will return -EINVAL Fixes: 225d59adf1c8 ("iio: Specify supported modes for buffers") Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti_am335x_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 942320e32753..c1e05532d437 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -289,7 +289,7 @@ static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev, goto error_kfifo_free; indio_dev->setup_ops = setup_ops; - indio_dev->modes |= INDIO_BUFFER_HARDWARE; + indio_dev->modes |= INDIO_BUFFER_SOFTWARE; return 0; -- cgit v1.2.3 From 99222c9e4de7feb22c93b19a92b35fcdad73ed42 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Thu, 7 Jan 2016 20:17:33 +0800 Subject: clk: rockchip: rk3036: fix the FLAGs for clock mux The DFLAGS are used for the clock dividers, the CLKSEL_CON flags of COMPOSITE_NODIV type should be MFLAGS. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3036.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index ebce98033fbb..7e3b41cd3e5b 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -224,16 +224,16 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { RK2928_CLKGATE_CON(2), 2, GFLAGS), COMPOSITE_NODIV(SCLK_TIMER0, "sclk_timer0", mux_timer_p, CLK_IGNORE_UNUSED, - RK2928_CLKSEL_CON(2), 4, 1, DFLAGS, + RK2928_CLKSEL_CON(2), 4, 1, MFLAGS, RK2928_CLKGATE_CON(1), 0, GFLAGS), COMPOSITE_NODIV(SCLK_TIMER1, "sclk_timer1", mux_timer_p, CLK_IGNORE_UNUSED, - RK2928_CLKSEL_CON(2), 5, 1, DFLAGS, + RK2928_CLKSEL_CON(2), 5, 1, MFLAGS, RK2928_CLKGATE_CON(1), 1, GFLAGS), COMPOSITE_NODIV(SCLK_TIMER2, "sclk_timer2", mux_timer_p, CLK_IGNORE_UNUSED, - RK2928_CLKSEL_CON(2), 6, 1, DFLAGS, + RK2928_CLKSEL_CON(2), 6, 1, MFLAGS, RK2928_CLKGATE_CON(2), 4, GFLAGS), COMPOSITE_NODIV(SCLK_TIMER3, "sclk_timer3", mux_timer_p, CLK_IGNORE_UNUSED, - RK2928_CLKSEL_CON(2), 7, 1, DFLAGS, + RK2928_CLKSEL_CON(2), 7, 1, MFLAGS, RK2928_CLKGATE_CON(2), 5, GFLAGS), MUX(0, "uart_pll_clk", mux_pll_src_apll_dpll_gpll_usb480m_p, 0, @@ -279,13 +279,13 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { RK2928_CLKGATE_CON(3), 2, GFLAGS), COMPOSITE_NODIV(0, "sclk_sdmmc_src", mux_mmc_src_p, 0, - RK2928_CLKSEL_CON(12), 8, 2, DFLAGS, + RK2928_CLKSEL_CON(12), 8, 2, MFLAGS, RK2928_CLKGATE_CON(2), 11, GFLAGS), DIV(SCLK_SDMMC, "sclk_sdmmc", "sclk_sdmmc_src", 0, RK2928_CLKSEL_CON(11), 0, 7, DFLAGS), COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0, - RK2928_CLKSEL_CON(12), 10, 2, DFLAGS, + RK2928_CLKSEL_CON(12), 10, 2, MFLAGS, RK2928_CLKGATE_CON(2), 13, GFLAGS), DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0, RK2928_CLKSEL_CON(11), 8, 7, DFLAGS), -- cgit v1.2.3 From b29de2de5049e064d172862b1feeddeb650c3ee8 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Thu, 7 Jan 2016 20:17:34 +0800 Subject: clk: rockchip: rk3036: fix uarts clock error Due to a copy-paste error the uart1 and uart2 clock div set incorrect, fix it. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3036.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index 7e3b41cd3e5b..04b5249bcf0b 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -242,11 +242,11 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { RK2928_CLKSEL_CON(13), 0, 7, DFLAGS, RK2928_CLKGATE_CON(1), 8, GFLAGS), COMPOSITE_NOMUX(0, "uart1_src", "uart_pll_clk", 0, - RK2928_CLKSEL_CON(13), 0, 7, DFLAGS, - RK2928_CLKGATE_CON(1), 8, GFLAGS), + RK2928_CLKSEL_CON(14), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(1), 10, GFLAGS), COMPOSITE_NOMUX(0, "uart2_src", "uart_pll_clk", 0, - RK2928_CLKSEL_CON(13), 0, 7, DFLAGS, - RK2928_CLKGATE_CON(1), 8, GFLAGS), + RK2928_CLKSEL_CON(15), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(1), 12, GFLAGS), COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(17), 0, RK2928_CLKGATE_CON(1), 9, GFLAGS, -- cgit v1.2.3 From c40519350e1d7db03e35e57509352c55948648ba Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Thu, 7 Jan 2016 20:17:35 +0800 Subject: clk: rockchip: rk3036: fix the div offset for emac clock Due to reference to old version TRM, there are incorrect emac clock node. The SEL_21_9 is used for the parent div, the SEL_21_4 is used for the child div. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3036.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index 04b5249bcf0b..1f00fab72dfb 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -344,12 +344,12 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { RK2928_CLKGATE_CON(10), 5, GFLAGS), COMPOSITE_NOGATE(0, "mac_pll_src", mux_pll_src_3plls_p, 0, - RK2928_CLKSEL_CON(21), 0, 2, MFLAGS, 4, 5, DFLAGS), + RK2928_CLKSEL_CON(21), 0, 2, MFLAGS, 9, 5, DFLAGS), MUX(SCLK_MACREF, "mac_clk_ref", mux_mac_p, CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(21), 3, 1, MFLAGS), COMPOSITE_NOMUX(SCLK_MAC, "mac_clk", "mac_clk_ref", 0, - RK2928_CLKSEL_CON(21), 9, 5, DFLAGS, + RK2928_CLKSEL_CON(21), 4, 5, DFLAGS, RK2928_CLKGATE_CON(2), 6, GFLAGS), MUX(SCLK_HDMI, "dclk_hdmi", mux_dclk_p, 0, -- cgit v1.2.3 From 3d667920bc8fc0c3b39e4e740352d9367fa4916e Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Thu, 7 Jan 2016 20:17:36 +0800 Subject: clk: rockchip: rk3036: rename emac ext source clock There is only support rmii in the RK3036, so we should use the correct ext clock name as described in the TRM. Signed-off-by: Xing Zheng [update dt-binding document as well] Signed-off-by: Heiko Stuebner --- Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt | 2 +- drivers/clk/rockchip/clk-rk3036.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt index ace05992a262..20df350b9ef3 100644 --- a/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt @@ -30,7 +30,7 @@ that they are defined using standard clock bindings with following clock-output-names: - "xin24m" - crystal input - required, - "ext_i2s" - external I2S clock - optional, - - "ext_gmac" - external GMAC clock - optional + - "rmii_clkin" - external EMAC clock - optional Example: Clock controller node: diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index 1f00fab72dfb..bc7fbac83ab7 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -133,7 +133,7 @@ PNAME(mux_spdif_p) = { "spdif_src", "spdif_frac", "xin12m" }; PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" }; PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" }; PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" }; -PNAME(mux_mac_p) = { "mac_pll_src", "ext_gmac" }; +PNAME(mux_mac_p) = { "mac_pll_src", "rmii_clkin" }; PNAME(mux_dclk_p) = { "dclk_lcdc", "dclk_cru" }; static struct rockchip_pll_clock rk3036_pll_clks[] __initdata = { -- cgit v1.2.3 From 8931f8e02979e4180566907019d432527c80abf7 Mon Sep 17 00:00:00 2001 From: Jianqun xu Date: Thu, 7 Jan 2016 17:18:07 +0800 Subject: clk: rockchip: rk3368: fix some clock gates Reference to the Rockchip RK3368 TRM v1.1, some clock gates need to be updated. Signed-off-by: Jianqun xu Signed-off-by: Caesar Wang Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3368.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index be0ede522269..21f3ea909fab 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -780,13 +780,13 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK3368_CLKGATE_CON(20), 0, GFLAGS), /* pclk_pd_alive gates */ - GATE(PCLK_TIMER1, "pclk_timer1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 8, GFLAGS), - GATE(PCLK_TIMER0, "pclk_timer0", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 7, GFLAGS), - GATE(0, "pclk_alive_niu", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 12, GFLAGS), - GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 11, GFLAGS), - GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 3, GFLAGS), - GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 2, GFLAGS), - GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 1, GFLAGS), + GATE(PCLK_TIMER1, "pclk_timer1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 13, GFLAGS), + GATE(PCLK_TIMER0, "pclk_timer0", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 12, GFLAGS), + GATE(0, "pclk_alive_niu", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(22), 9, GFLAGS), + GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(22), 8, GFLAGS), + GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 3, GFLAGS), + GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 2, GFLAGS), + GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 1, GFLAGS), /* * pclk_vio gates @@ -796,12 +796,12 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { GATE(0, "pclk_dphytx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS), /* pclk_pd_pmu gates */ - GATE(PCLK_PMUGRF, "pclk_pmugrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 0, GFLAGS), - GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3368_CLKGATE_CON(17), 4, GFLAGS), - GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 3, GFLAGS), - GATE(0, "pclk_pmu_noc", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 2, GFLAGS), - GATE(0, "pclk_intmem1", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 1, GFLAGS), - GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 2, GFLAGS), + GATE(PCLK_PMUGRF, "pclk_pmugrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 5, GFLAGS), + GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3368_CLKGATE_CON(23), 4, GFLAGS), + GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 3, GFLAGS), + GATE(0, "pclk_pmu_noc", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 2, GFLAGS), + GATE(0, "pclk_intmem1", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 1, GFLAGS), + GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 0, GFLAGS), /* timer gates */ GATE(0, "sclk_timer15", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 11, GFLAGS), -- cgit v1.2.3 From ce90d092bcd96b646b370121f0f1508270627f98 Mon Sep 17 00:00:00 2001 From: Mark Yao Date: Tue, 12 Jan 2016 15:51:12 +0800 Subject: drm/rockchip: Don't build rockchip_drm_vop as modules rockchip_drm_vop's module init had moved to rockchip_vop_reg.c so no need to build rockchip_drm_vop.ko Signed-off-by: Mark Yao --- drivers/gpu/drm/rockchip/Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile index d1dc0f7b01db..a4e03bcde035 100644 --- a/drivers/gpu/drm/rockchip/Makefile +++ b/drivers/gpu/drm/rockchip/Makefile @@ -3,10 +3,9 @@ # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o rockchip_drm_fbdev.o \ - rockchip_drm_gem.o + rockchip_drm_gem.o rockchip_drm_vop.o obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o -obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_drm_vop.o \ - rockchip_vop_reg.o +obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_vop_reg.o -- cgit v1.2.3 From 63087aae5a7976a4557d16873146eae03948ec74 Mon Sep 17 00:00:00 2001 From: Mark Yao Date: Tue, 12 Jan 2016 16:04:39 +0800 Subject: drm/rockchip: cleanup unnecessary export symbol Now rockchip_drm_vop.c is build into rockchipdrm.ko, so no need to export following symbol anymore: rockchip_drm_dma_attach_device rockchip_drm_dma_detach_device rockchip_drm_dma_attach_device rockchip_drm_dma_detach_device rockchip_register_crtc_funcs rockchip_unregister_crtc_funcs rockchip_fb_get_gem_obj Signed-off-by: Mark Yao --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 4 ---- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 1 - 2 files changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 8397d1b62ef9..a0d51ccb6ea4 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -55,14 +55,12 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, return arm_iommu_attach_device(dev, mapping); } -EXPORT_SYMBOL_GPL(rockchip_drm_dma_attach_device); void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, struct device *dev) { arm_iommu_detach_device(dev); } -EXPORT_SYMBOL_GPL(rockchip_drm_dma_detach_device); int rockchip_register_crtc_funcs(struct drm_crtc *crtc, const struct rockchip_crtc_funcs *crtc_funcs) @@ -77,7 +75,6 @@ int rockchip_register_crtc_funcs(struct drm_crtc *crtc, return 0; } -EXPORT_SYMBOL_GPL(rockchip_register_crtc_funcs); void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc) { @@ -89,7 +86,6 @@ void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc) priv->crtc_funcs[pipe] = NULL; } -EXPORT_SYMBOL_GPL(rockchip_unregister_crtc_funcs); static struct drm_crtc *rockchip_crtc_from_pipe(struct drm_device *drm, int pipe) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index f7844883cb76..dd1f8d3c98d8 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -39,7 +39,6 @@ struct drm_gem_object *rockchip_fb_get_gem_obj(struct drm_framebuffer *fb, return rk_fb->obj[plane]; } -EXPORT_SYMBOL_GPL(rockchip_fb_get_gem_obj); static void rockchip_drm_fb_destroy(struct drm_framebuffer *fb) { -- cgit v1.2.3 From c7647f8681feeb6c0957e3cf5daed1fbf8b3a5af Mon Sep 17 00:00:00 2001 From: John Keeping Date: Tue, 12 Jan 2016 18:05:18 +0000 Subject: drm/rockchip: vop: fix mask when updating interrupts Commit dbb3d94 (drm/rockchip: vop: move interrupt registers into vop_data) introduced new macros for updating the interrupt control registers but these always use the mask from the register definition without refining it for the particular bits that are being changed. This means that whenever we enable/disable a particular interrupt we end up disabling all of the others as a side effect. Signed-off-by: John Keeping --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 46c2a8dfd8aa..fd370548d7d7 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -43,8 +43,8 @@ #define REG_SET(x, base, reg, v, mode) \ __REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v) -#define REG_SET_MASK(x, base, reg, v, mode) \ - __REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v) +#define REG_SET_MASK(x, base, reg, mask, v, mode) \ + __REG_SET_##mode(x, base + reg.offset, mask, reg.shift, v) #define VOP_WIN_SET(x, win, name, v) \ REG_SET(x, win->base, win->phy->name, v, RELAXED) @@ -58,16 +58,18 @@ #define VOP_INTR_GET(vop, name) \ vop_read_reg(vop, 0, &vop->data->ctrl->name) -#define VOP_INTR_SET(vop, name, v) \ - REG_SET(vop, 0, vop->data->intr->name, v, NORMAL) +#define VOP_INTR_SET(vop, name, mask, v) \ + REG_SET_MASK(vop, 0, vop->data->intr->name, mask, v, NORMAL) #define VOP_INTR_SET_TYPE(vop, name, type, v) \ do { \ - int i, reg = 0; \ + int i, reg = 0, mask = 0; \ for (i = 0; i < vop->data->intr->nintrs; i++) { \ - if (vop->data->intr->intrs[i] & type) \ + if (vop->data->intr->intrs[i] & type) { \ reg |= (v) << i; \ + mask |= 1 << i; \ + } \ } \ - VOP_INTR_SET(vop, name, reg); \ + VOP_INTR_SET(vop, name, mask, reg); \ } while (0) #define VOP_INTR_GET_TYPE(vop, name, type) \ vop_get_intr_type(vop, &vop->data->intr->name, type) -- cgit v1.2.3 From 484bb6c969523aa547d854bb57104339ee4aa800 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Thu, 14 Jan 2016 09:59:02 +0100 Subject: drm/rockchip/dsi: fix handling mipi_dsi_pixel_format_to_bpp result The function can return negative value so it should be assigned to signed variable. The problem has been detected using patch scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci. Signed-off-by: Andrzej Hajda Reviewed-by: Chris Zhong --- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index 7bfe243c6173..f8f8f29fb7c3 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c @@ -461,10 +461,11 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi) { - unsigned int bpp, i, pre; + unsigned int i, pre; unsigned long mpclk, pllref, tmp; unsigned int m = 1, n = 1, target_mbps = 1000; unsigned int max_mbps = dptdin_map[ARRAY_SIZE(dptdin_map) - 1].max_mbps; + int bpp; bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); if (bpp < 0) { -- cgit v1.2.3 From 07096bd3c9d83f043c733c592974aa8ea93ba2db Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Thu, 14 Jan 2016 14:00:09 +0800 Subject: drm/crtc_helper/set_config: Remove redundant handling when set->fb is NULL We've done sanity NULL pointer check on set->fb at the beginning of drm_crtc_helper_set_config() and bailed out if necessary, thus any later on check or case handling is redundant. Signed-off-by: Liu Ying Link: http://patchwork.freedesktop.org/patch/msgid/1452751210-19216-1-git-send-email-gnuiyl@gmail.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc_helper.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index a02a7f9a6a9d..63e88819b91e 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -578,8 +578,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) if (set->crtc->primary->fb == NULL) { DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); mode_changed = true; - } else if (set->fb == NULL) { - mode_changed = true; } else if (set->fb->pixel_format != set->crtc->primary->fb->pixel_format) { mode_changed = true; -- cgit v1.2.3 From 2deafc7e163be631183bdfc066e2f636e7818e00 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Thu, 14 Jan 2016 14:00:10 +0800 Subject: drm/crtc_helper/set_config: Remove redundant NULL pointer check on set->mode We've done sanity NULL pointer check on set->mode at the beginning of drm_crtc_helper_set_config() and bailed out if necessary, thus any later on check is redundant. Signed-off-by: Liu Ying Link: http://patchwork.freedesktop.org/patch/msgid/1452751210-19216-2-git-send-email-gnuiyl@gmail.com Signed-off-by: Daniel Vetter --- 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 63e88819b91e..5d4bc6441d88 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -588,7 +588,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) if (set->x != set->crtc->x || set->y != set->crtc->y) fb_changed = true; - if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { + if (!drm_mode_equal(set->mode, &set->crtc->mode)) { DRM_DEBUG_KMS("modes are different, full mode set\n"); drm_mode_debug_printmodeline(&set->crtc->mode); drm_mode_debug_printmodeline(set->mode); -- cgit v1.2.3 From c6c5c7fa7f3ec7d35541e9e4c6feb4ccd6cca7c9 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 18 Jan 2016 11:36:35 +0800 Subject: drm/atomic-helper: Remove redundant local var old_crtc_state in disable_outputs One of the two local variables old_crtc_state is redundantly defined in the function disable_outputs(). It has only a scope partway through the block for_each_connector_in_state. So, let's remove it and use the one which has the scope within the function disable_outputs(). Signed-off-by: Liu Ying Link: http://patchwork.freedesktop.org/patch/msgid/1453088195-2564-1-git-send-email-gnuiyl@gmail.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 57cccd68ca52..b9d8b5393955 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -617,7 +617,6 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) for_each_connector_in_state(old_state, connector, old_conn_state, i) { const struct drm_encoder_helper_funcs *funcs; struct drm_encoder *encoder; - struct drm_crtc_state *old_crtc_state; /* Shut down everything that's in the changeset and currently * still on. So need to check the old, saved state. */ -- cgit v1.2.3 From e0313db047c2f2e368c95a8f03653f9723678e82 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 15 Jan 2016 15:11:12 +0000 Subject: drm/i915: Only grab timestamps when needed No need to call ktime_get_raw_ns twice per unlimited wait and can also elimate a local variable. v2: Added comment about silencing the compiler warning. (Daniel Vetter) Signed-off-by: Tvrtko Ursulin Reviewed-by: Dave Gordon Acked-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1452870672-13901-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_gem.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index ddc21d4b388d..6b0102da859c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1251,7 +1251,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req, int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE; DEFINE_WAIT(wait); unsigned long timeout_expire; - s64 before, now; + s64 before = 0; /* Only to silence a compiler warning. */ int ret; WARN(!intel_irqs_enabled(dev_priv), "IRQs disabled"); @@ -1271,14 +1271,17 @@ int __i915_wait_request(struct drm_i915_gem_request *req, return -ETIME; timeout_expire = jiffies + nsecs_to_jiffies_timeout(*timeout); + + /* + * Record current time in case interrupted by signal, or wedged. + */ + before = ktime_get_raw_ns(); } if (INTEL_INFO(dev_priv)->gen >= 6) gen6_rps_boost(dev_priv, rps, req->emitted_jiffies); - /* Record current time in case interrupted by signal, or wedged */ trace_i915_gem_request_wait_begin(req); - before = ktime_get_raw_ns(); /* Optimistic spin for the next jiffie before touching IRQs */ ret = __i915_spin_request(req, state); @@ -1343,11 +1346,10 @@ int __i915_wait_request(struct drm_i915_gem_request *req, finish_wait(&ring->irq_queue, &wait); out: - now = ktime_get_raw_ns(); trace_i915_gem_request_wait_end(req); if (timeout) { - s64 tres = *timeout - (now - before); + s64 tres = *timeout - (ktime_get_raw_ns() - before); *timeout = tres < 0 ? 0 : tres; -- cgit v1.2.3 From ca82580c9ceace0d52fe7376b8a72bb3b36f612b Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 15 Jan 2016 15:10:27 +0000 Subject: drm/i915: Do not call API requiring struct_mutex where it is not available LRC code was calling GEM API like i915_gem_obj_ggtt_offset from places where the struct_mutex cannot be grabbed (irq handlers). To avoid that this patch caches some interesting bits and values in the engine and context structures. Some usages are also removed where they are not needed like a few asserts which are either impossible or have been checked already during engine initialization. Side benefit is also that interrupt handlers and command submission stop evaluating invariant conditionals, like what Gen we are running on, on every interrupt and every command submitted. This patch deals with logical ring context id and descriptors while subsequent patches will deal with the remaining issues. v2: * Cache the VMA instead of the address. (Chris Wilson) * Incorporate Dave Gordon's good comments and function name. v3: * Extract ctx descriptor template to a function and group functions dealing with ctx descriptor & co together near top of the file. (Dave Gordon) Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Cc: Daniel Vetter Cc: Dave Gordon Link: http://patchwork.freedesktop.org/patch/msgid/1452870629-13830-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 15 ++-- drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_gem_gtt.h | 1 - drivers/gpu/drm/i915/intel_lrc.c | 151 +++++++++++++++++++------------- drivers/gpu/drm/i915/intel_lrc.h | 4 +- drivers/gpu/drm/i915/intel_ringbuffer.h | 2 + 6 files changed, 103 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e3377abc0d4d..0b3550f05026 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1994,12 +1994,13 @@ static int i915_context_status(struct seq_file *m, void *unused) } static void i915_dump_lrc_obj(struct seq_file *m, - struct intel_engine_cs *ring, - struct drm_i915_gem_object *ctx_obj) + struct intel_context *ctx, + struct intel_engine_cs *ring) { struct page *page; uint32_t *reg_state; int j; + struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state; unsigned long ggtt_offset = 0; if (ctx_obj == NULL) { @@ -2009,7 +2010,7 @@ static void i915_dump_lrc_obj(struct seq_file *m, } seq_printf(m, "CONTEXT: %s %u\n", ring->name, - intel_execlists_ctx_id(ctx_obj)); + intel_execlists_ctx_id(ctx, ring)); if (!i915_gem_obj_ggtt_bound(ctx_obj)) seq_puts(m, "\tNot bound in GGTT\n"); @@ -2058,8 +2059,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) list_for_each_entry(ctx, &dev_priv->context_list, link) { for_each_ring(ring, dev_priv, i) { if (ring->default_context != ctx) - i915_dump_lrc_obj(m, ring, - ctx->engine[i].state); + i915_dump_lrc_obj(m, ctx, ring); } } @@ -2133,11 +2133,8 @@ static int i915_execlists(struct seq_file *m, void *data) seq_printf(m, "\t%d requests in queue\n", count); if (head_req) { - struct drm_i915_gem_object *ctx_obj; - - ctx_obj = head_req->ctx->engine[ring_id].state; seq_printf(m, "\tHead request id: %u\n", - intel_execlists_ctx_id(ctx_obj)); + intel_execlists_ctx_id(head_req->ctx, ring)); seq_printf(m, "\tHead request tail: %u\n", head_req->tail); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index eb7bb97f7316..acff98b9c148 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -888,6 +888,8 @@ struct intel_context { struct drm_i915_gem_object *state; struct intel_ringbuffer *ringbuf; int pin_count; + struct i915_vma *lrc_vma; + u64 lrc_desc; } engine[I915_NUM_RINGS]; struct list_head link; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index b448ad832dcf..e5737963ab79 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -44,7 +44,6 @@ typedef uint64_t gen8_ppgtt_pml4e_t; #define gtt_total_entries(gtt) ((gtt).base.total >> PAGE_SHIFT) - /* gen6-hsw has bit 11-4 for physical addr bit 39-32 */ #define GEN6_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0xff0)) #define GEN6_PTE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index f5d89c845ede..86042dc1802c 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -263,65 +263,92 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists return 0; } +static void +logical_ring_init_platform_invariants(struct intel_engine_cs *ring) +{ + struct drm_device *dev = ring->dev; + + ring->disable_lite_restore_wa = (IS_SKL_REVID(dev, 0, SKL_REVID_B0) || + IS_BXT_REVID(dev, 0, BXT_REVID_A1)) && + (ring->id == VCS || ring->id == VCS2); + + ring->ctx_desc_template = GEN8_CTX_VALID; + ring->ctx_desc_template |= GEN8_CTX_ADDRESSING_MODE(dev) << + GEN8_CTX_ADDRESSING_MODE_SHIFT; + if (IS_GEN8(dev)) + ring->ctx_desc_template |= GEN8_CTX_L3LLC_COHERENT; + ring->ctx_desc_template |= GEN8_CTX_PRIVILEGE; + + /* TODO: WaDisableLiteRestore when we start using semaphore + * signalling between Command Streamers */ + /* ring->ctx_desc_template |= GEN8_CTX_FORCE_RESTORE; */ + + /* WaEnableForceRestoreInCtxtDescForVCS:skl */ + /* WaEnableForceRestoreInCtxtDescForVCS:bxt */ + if (ring->disable_lite_restore_wa) + ring->ctx_desc_template |= GEN8_CTX_FORCE_RESTORE; +} + /** - * intel_execlists_ctx_id() - get the Execlists Context ID - * @ctx_obj: Logical Ring Context backing object. + * intel_lr_context_descriptor_update() - calculate & cache the descriptor + * descriptor for a pinned context * - * Do not confuse with ctx->id! Unfortunately we have a name overload - * here: the old context ID we pass to userspace as a handler so that - * they can refer to a context, and the new context ID we pass to the - * ELSP so that the GPU can inform us of the context status via - * interrupts. + * @ctx: Context to work on + * @ring: Engine the descriptor will be used with * - * Return: 20-bits globally unique context ID. + * The context descriptor encodes various attributes of a context, + * including its GTT address and some flags. Because it's fairly + * expensive to calculate, we'll just do it once and cache the result, + * which remains valid until the context is unpinned. + * + * This is what a descriptor looks like, from LSB to MSB: + * bits 0-11: flags, GEN8_CTX_* (cached in ctx_desc_template) + * bits 12-31: LRCA, GTT address of (the HWSP of) this context + * bits 32-51: ctx ID, a globally unique tag (the LRCA again!) + * bits 52-63: reserved, may encode the engine ID (for GuC) */ -u32 intel_execlists_ctx_id(struct drm_i915_gem_object *ctx_obj) +static void +intel_lr_context_descriptor_update(struct intel_context *ctx, + struct intel_engine_cs *ring) { - u32 lrca = i915_gem_obj_ggtt_offset(ctx_obj) + - LRC_PPHWSP_PN * PAGE_SIZE; + uint64_t lrca, desc; - /* LRCA is required to be 4K aligned so the more significant 20 bits - * are globally unique */ - return lrca >> 12; -} + lrca = ctx->engine[ring->id].lrc_vma->node.start + + LRC_PPHWSP_PN * PAGE_SIZE; -static bool disable_lite_restore_wa(struct intel_engine_cs *ring) -{ - struct drm_device *dev = ring->dev; + desc = ring->ctx_desc_template; /* bits 0-11 */ + desc |= lrca; /* bits 12-31 */ + desc |= (lrca >> PAGE_SHIFT) << GEN8_CTX_ID_SHIFT; /* bits 32-51 */ - return (IS_SKL_REVID(dev, 0, SKL_REVID_B0) || - IS_BXT_REVID(dev, 0, BXT_REVID_A1)) && - (ring->id == VCS || ring->id == VCS2); + ctx->engine[ring->id].lrc_desc = desc; } uint64_t intel_lr_context_descriptor(struct intel_context *ctx, struct intel_engine_cs *ring) { - struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state; - uint64_t desc; - uint64_t lrca = i915_gem_obj_ggtt_offset(ctx_obj) + - LRC_PPHWSP_PN * PAGE_SIZE; - - WARN_ON(lrca & 0xFFFFFFFF00000FFFULL); - - desc = GEN8_CTX_VALID; - desc |= GEN8_CTX_ADDRESSING_MODE(dev) << GEN8_CTX_ADDRESSING_MODE_SHIFT; - if (IS_GEN8(ctx_obj->base.dev)) - desc |= GEN8_CTX_L3LLC_COHERENT; - desc |= GEN8_CTX_PRIVILEGE; - desc |= lrca; - desc |= (u64)intel_execlists_ctx_id(ctx_obj) << GEN8_CTX_ID_SHIFT; - - /* TODO: WaDisableLiteRestore when we start using semaphore - * signalling between Command Streamers */ - /* desc |= GEN8_CTX_FORCE_RESTORE; */ - - /* WaEnableForceRestoreInCtxtDescForVCS:skl */ - /* WaEnableForceRestoreInCtxtDescForVCS:bxt */ - if (disable_lite_restore_wa(ring)) - desc |= GEN8_CTX_FORCE_RESTORE; + return ctx->engine[ring->id].lrc_desc; +} - return desc; +/** + * intel_execlists_ctx_id() - get the Execlists Context ID + * @ctx: Context to get the ID for + * @ring: Engine to get the ID for + * + * Do not confuse with ctx->id! Unfortunately we have a name overload + * here: the old context ID we pass to userspace as a handler so that + * they can refer to a context, and the new context ID we pass to the + * ELSP so that the GPU can inform us of the context status via + * interrupts. + * + * The context ID is a portion of the context descriptor, so we can + * just extract the required part from the cached descriptor. + * + * Return: 20-bits globally unique context ID. + */ +u32 intel_execlists_ctx_id(struct intel_context *ctx, + struct intel_engine_cs *ring) +{ + return intel_lr_context_descriptor(ctx, ring) >> GEN8_CTX_ID_SHIFT; } static void execlists_elsp_write(struct drm_i915_gem_request *rq0, @@ -369,8 +396,6 @@ static int execlists_update_context(struct drm_i915_gem_request *rq) uint32_t *reg_state; BUG_ON(!ctx_obj); - WARN_ON(!i915_gem_obj_is_pinned(ctx_obj)); - WARN_ON(!i915_gem_obj_is_pinned(rb_obj)); page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN); reg_state = kmap_atomic(page); @@ -477,9 +502,7 @@ static bool execlists_check_remove_request(struct intel_engine_cs *ring, execlist_link); if (head_req != NULL) { - struct drm_i915_gem_object *ctx_obj = - head_req->ctx->engine[ring->id].state; - if (intel_execlists_ctx_id(ctx_obj) == request_id) { + if (intel_execlists_ctx_id(head_req->ctx, ring) == request_id) { WARN(head_req->elsp_submitted == 0, "Never submitted head request\n"); @@ -556,7 +579,7 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring) } } - if (disable_lite_restore_wa(ring)) { + if (ring->disable_lite_restore_wa) { /* Prevent a ctx to preempt itself */ if ((status & GEN8_CTX_STATUS_ACTIVE_IDLE) && (submit_contexts != 0)) @@ -1039,14 +1062,16 @@ int logical_ring_flush_all_caches(struct drm_i915_gem_request *req) } static int intel_lr_context_do_pin(struct intel_engine_cs *ring, - struct drm_i915_gem_object *ctx_obj, - struct intel_ringbuffer *ringbuf) + struct intel_context *ctx) { struct drm_device *dev = ring->dev; struct drm_i915_private *dev_priv = dev->dev_private; - int ret = 0; + struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state; + struct intel_ringbuffer *ringbuf = ctx->engine[ring->id].ringbuf; + int ret; WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex)); + ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN, PIN_OFFSET_BIAS | GUC_WOPCM_TOP); if (ret) @@ -1056,6 +1081,8 @@ static int intel_lr_context_do_pin(struct intel_engine_cs *ring, if (ret) goto unpin_ctx_obj; + ctx->engine[ring->id].lrc_vma = i915_gem_obj_to_ggtt(ctx_obj); + intel_lr_context_descriptor_update(ctx, ring); ctx_obj->dirty = true; /* Invalidate GuC TLB. */ @@ -1074,11 +1101,9 @@ static int intel_lr_context_pin(struct drm_i915_gem_request *rq) { int ret = 0; struct intel_engine_cs *ring = rq->ring; - struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring->id].state; - struct intel_ringbuffer *ringbuf = rq->ringbuf; if (rq->ctx->engine[ring->id].pin_count++ == 0) { - ret = intel_lr_context_do_pin(ring, ctx_obj, ringbuf); + ret = intel_lr_context_do_pin(ring, rq->ctx); if (ret) goto reset_pin_count; } @@ -1100,6 +1125,8 @@ void intel_lr_context_unpin(struct drm_i915_gem_request *rq) if (--rq->ctx->engine[ring->id].pin_count == 0) { intel_unpin_ringbuffer_obj(ringbuf); i915_gem_object_ggtt_unpin(ctx_obj); + rq->ctx->engine[ring->id].lrc_vma = NULL; + rq->ctx->engine[ring->id].lrc_desc = 0; } } } @@ -1939,6 +1966,9 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *ring) ring->status_page.obj = NULL; } + ring->disable_lite_restore_wa = false; + ring->ctx_desc_template = 0; + lrc_destroy_wa_ctx_obj(ring); ring->dev = NULL; } @@ -1989,6 +2019,8 @@ logical_ring_init(struct drm_device *dev, struct intel_engine_cs *ring) INIT_LIST_HEAD(&ring->execlist_retired_req_list); spin_lock_init(&ring->execlist_lock); + logical_ring_init_platform_invariants(ring); + ret = i915_cmd_parser_init_ring(ring); if (ret) goto error; @@ -1998,10 +2030,7 @@ logical_ring_init(struct drm_device *dev, struct intel_engine_cs *ring) goto error; /* As this is the default context, always pin it */ - ret = intel_lr_context_do_pin( - ring, - ring->default_context->engine[ring->id].state, - ring->default_context->engine[ring->id].ringbuf); + ret = intel_lr_context_do_pin(ring, ring->default_context); if (ret) { DRM_ERROR( "Failed to pin and map ringbuffer %s: %d\n", diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index de41ad6cd63d..49af638f6213 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -107,13 +107,15 @@ void intel_lr_context_reset(struct drm_device *dev, uint64_t intel_lr_context_descriptor(struct intel_context *ctx, struct intel_engine_cs *ring); +u32 intel_execlists_ctx_id(struct intel_context *ctx, + struct intel_engine_cs *ring); + /* Execlists */ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists); struct i915_execbuffer_params; int intel_execlists_submission(struct i915_execbuffer_params *params, struct drm_i915_gem_execbuffer2 *args, struct list_head *vmas); -u32 intel_execlists_ctx_id(struct drm_i915_gem_object *ctx_obj); void intel_lrc_irq_handler(struct intel_engine_cs *ring); void intel_execlists_retire_requests(struct intel_engine_cs *ring); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 7349d9258191..85ce2272f92c 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -269,6 +269,8 @@ struct intel_engine_cs { struct list_head execlist_queue; struct list_head execlist_retired_req_list; u8 next_context_status_buffer; + bool disable_lite_restore_wa; + u32 ctx_desc_template; u32 irq_keep_mask; /* bitmask for interrupts that should not be masked */ int (*emit_request)(struct drm_i915_gem_request *request); int (*emit_flush)(struct drm_i915_gem_request *request, -- cgit v1.2.3 From 0eb973d31d0aadb6bc801fd6d796afecbbfc3d5b Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 15 Jan 2016 15:10:28 +0000 Subject: drm/i915: Cache ringbuffer GTT VMA Purpose is to avoid calling i915_gem_obj_ggtt_offset from the interrupt context without the big lock held. v2: Renamed gtt_start to gtt_offset. (Daniel Vetter) v3: Cache the VMA instead of address. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Cc: Daniel Vetter Cc: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1452870629-13830-2-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/intel_lrc.c | 3 +-- drivers/gpu/drm/i915/intel_ringbuffer.c | 3 +++ drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 86042dc1802c..588cad58a196 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -391,7 +391,6 @@ static int execlists_update_context(struct drm_i915_gem_request *rq) struct intel_engine_cs *ring = rq->ring; struct i915_hw_ppgtt *ppgtt = rq->ctx->ppgtt; struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring->id].state; - struct drm_i915_gem_object *rb_obj = rq->ringbuf->obj; struct page *page; uint32_t *reg_state; @@ -401,7 +400,7 @@ static int execlists_update_context(struct drm_i915_gem_request *rq) reg_state = kmap_atomic(page); reg_state[CTX_RING_TAIL+1] = rq->tail; - reg_state[CTX_RING_BUFFER_START+1] = i915_gem_obj_ggtt_offset(rb_obj); + reg_state[CTX_RING_BUFFER_START+1] = rq->ringbuf->vma->node.start; if (ppgtt && !USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) { /* True 32b PPGTT with dynamic page allocation: update PDP diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 8cd8aabcc3ff..d4e33ac02efa 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1999,6 +1999,7 @@ void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf) else iounmap(ringbuf->virtual_start); ringbuf->virtual_start = NULL; + ringbuf->vma = NULL; i915_gem_object_ggtt_unpin(ringbuf->obj); } @@ -2065,6 +2066,8 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, } } + ringbuf->vma = i915_gem_obj_to_ggtt(obj); + return 0; } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 85ce2272f92c..ede57954080e 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -99,6 +99,7 @@ struct intel_ring_hangcheck { struct intel_ringbuffer { struct drm_i915_gem_object *obj; void __iomem *virtual_start; + struct i915_vma *vma; struct intel_engine_cs *ring; struct list_head link; -- cgit v1.2.3 From 82352e908acd36d7244c75a008c9f27a2ced44d5 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 15 Jan 2016 17:12:45 +0000 Subject: drm/i915: Cache LRC state page in the context LRC lifetime is well defined so we can cache the page pointing to the object backing store in the context in order to avoid walking over the object SG page list from the interrupt context without the big lock held. v2: Also cache the mapping. (Chris Wilson) v3: Unmap on the error path. v4: No need to cache the page. (Chris Wilson) v5: No need to dirty the page on unpin. (Chris Wilson) v6: kmap() cannot fail and use kmap_to_page to simplify unpin. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Cc: Chris Wilson Cc: Dave Gordon Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1452877965-32042-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_lrc.c | 39 +++++++++++++++++++++------------------ 2 files changed, 22 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index acff98b9c148..af301482e6f8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -890,6 +890,7 @@ struct intel_context { int pin_count; struct i915_vma *lrc_vma; u64 lrc_desc; + uint32_t *lrc_reg_state; } engine[I915_NUM_RINGS]; struct list_head link; diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 588cad58a196..faaf49077fea 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -390,14 +390,7 @@ static int execlists_update_context(struct drm_i915_gem_request *rq) { struct intel_engine_cs *ring = rq->ring; struct i915_hw_ppgtt *ppgtt = rq->ctx->ppgtt; - struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring->id].state; - struct page *page; - uint32_t *reg_state; - - BUG_ON(!ctx_obj); - - page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN); - reg_state = kmap_atomic(page); + uint32_t *reg_state = rq->ctx->engine[ring->id].lrc_reg_state; reg_state[CTX_RING_TAIL+1] = rq->tail; reg_state[CTX_RING_BUFFER_START+1] = rq->ringbuf->vma->node.start; @@ -414,8 +407,6 @@ static int execlists_update_context(struct drm_i915_gem_request *rq) ASSIGN_CTX_PDP(ppgtt, reg_state, 0); } - kunmap_atomic(reg_state); - return 0; } @@ -1067,6 +1058,7 @@ static int intel_lr_context_do_pin(struct intel_engine_cs *ring, struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state; struct intel_ringbuffer *ringbuf = ctx->engine[ring->id].ringbuf; + struct page *lrc_state_page; int ret; WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex)); @@ -1076,12 +1068,19 @@ static int intel_lr_context_do_pin(struct intel_engine_cs *ring, if (ret) return ret; + lrc_state_page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN); + if (WARN_ON(!lrc_state_page)) { + ret = -ENODEV; + goto unpin_ctx_obj; + } + ret = intel_pin_and_map_ringbuffer_obj(ring->dev, ringbuf); if (ret) goto unpin_ctx_obj; ctx->engine[ring->id].lrc_vma = i915_gem_obj_to_ggtt(ctx_obj); intel_lr_context_descriptor_update(ctx, ring); + ctx->engine[ring->id].lrc_reg_state = kmap(lrc_state_page); ctx_obj->dirty = true; /* Invalidate GuC TLB. */ @@ -1119,14 +1118,18 @@ void intel_lr_context_unpin(struct drm_i915_gem_request *rq) struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring->id].state; struct intel_ringbuffer *ringbuf = rq->ringbuf; - if (ctx_obj) { - WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex)); - if (--rq->ctx->engine[ring->id].pin_count == 0) { - intel_unpin_ringbuffer_obj(ringbuf); - i915_gem_object_ggtt_unpin(ctx_obj); - rq->ctx->engine[ring->id].lrc_vma = NULL; - rq->ctx->engine[ring->id].lrc_desc = 0; - } + WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex)); + + if (!ctx_obj) + return; + + if (--rq->ctx->engine[ring->id].pin_count == 0) { + kunmap(kmap_to_page(rq->ctx->engine[ring->id].lrc_reg_state)); + intel_unpin_ringbuffer_obj(ringbuf); + i915_gem_object_ggtt_unpin(ctx_obj); + rq->ctx->engine[ring->id].lrc_vma = NULL; + rq->ctx->engine[ring->id].lrc_desc = 0; + rq->ctx->engine[ring->id].lrc_reg_state = NULL; } } -- cgit v1.2.3 From a9d8adad731171559b24eb27c9db4a64238b7ef0 Mon Sep 17 00:00:00 2001 From: Alex Dai Date: Wed, 13 Jan 2016 11:01:50 -0800 Subject: drm/i915/guc: Fix a memory leak where guc->execbuf_client is not freed During driver unloading, the guc_client created for command submission needs to be released to avoid memory leak. The struct_mutex needs to be held before tearing down GuC. v1: Move i915_guc_submission_disable out of i915_guc_submission_fini and take struct_mutex lock before release GuC client. (Dave Gordon) v2: Add the locking for failure case in guc_fw_fetch. (Dave Gordon) Add i915_guc_submission_fini for failure case in intel_guc_ucode_load. Signed-off-by: Alex Dai Reviewed-by: Dave Gordon Link: http://patchwork.freedesktop.org/patch/msgid/1452711710-4505-1-git-send-email-yu.dai@intel.com --- drivers/gpu/drm/i915/intel_guc_loader.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index d20788ffd341..3accd914490f 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -445,6 +445,7 @@ fail: direct_interrupts_to_host(dev_priv); i915_guc_submission_disable(dev); + i915_guc_submission_fini(dev); return err; } @@ -561,10 +562,12 @@ fail: DRM_ERROR("Failed to fetch GuC firmware from %s (error %d)\n", guc_fw->guc_fw_path, err); + mutex_lock(&dev->struct_mutex); obj = guc_fw->guc_fw_obj; if (obj) drm_gem_object_unreference(&obj->base); guc_fw->guc_fw_obj = NULL; + mutex_unlock(&dev->struct_mutex); release_firmware(fw); /* OK even if fw is NULL */ guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_FAIL; @@ -631,10 +634,11 @@ void intel_guc_ucode_fini(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; + mutex_lock(&dev->struct_mutex); direct_interrupts_to_host(dev_priv); + i915_guc_submission_disable(dev); i915_guc_submission_fini(dev); - mutex_lock(&dev->struct_mutex); if (guc_fw->guc_fw_obj) drm_gem_object_unreference(&guc_fw->guc_fw_obj->base); guc_fw->guc_fw_obj = NULL; -- cgit v1.2.3 From 693bdc28a733dba68b86af295e7509812fec35d9 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 15 Jan 2016 20:46:53 +0200 Subject: drm/i915: Don't reject primary plane windowing with color keying enabled on SKL+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On SKL+ plane scaling is mutually exclusive with color keying. The code check for this, but during some refactoring the code got changed to also reject primary plane windowing when color keying is used. There is no such restriction in the hardware, so restore the original logic. Cc: Maarten Lankhorst Fixes: 061e4b8d650a ("drm/i915: clean up atomic plane check functions, v2.") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1452883613-28549-1-git-send-email-ville.syrjala@linux.intel.com Cc: stable@vger.kernel.org Reviewed-by: Matt Roper Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/intel_display.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ccb3e3f47450..9b6e726666c3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14019,11 +14019,12 @@ intel_check_primary_plane(struct drm_plane *plane, int max_scale = DRM_PLANE_HELPER_NO_SCALING; bool can_position = false; - /* use scaler when colorkey is not required */ - if (INTEL_INFO(plane->dev)->gen >= 9 && - state->ckey.flags == I915_SET_COLORKEY_NONE) { - min_scale = 1; - max_scale = skl_max_scale(to_intel_crtc(crtc), crtc_state); + if (INTEL_INFO(plane->dev)->gen >= 9) { + /* use scaler when colorkey is not required */ + if (state->ckey.flags == I915_SET_COLORKEY_NONE) { + min_scale = 1; + max_scale = skl_max_scale(to_intel_crtc(crtc), crtc_state); + } can_position = true; } -- cgit v1.2.3 From fa5a7970d372c9c9beb3a0ce79ee1d0c23387d0a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 15 Oct 2015 17:01:58 +0300 Subject: drm/i915: skl_update_scaler() wants a rotation bitmask instead of bit number MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass BIT(DRM_ROTATE_0) instead of DRM_ROTATE_0 to skl_update_scaler(). The former is a mask, the latter just the bit number. Fortunately the only thing skl_update_scaler() does with the rotation is check if it's 90/270 degrees or not, and so in this case it would still do the right thing. Cc: Chandra Konduru Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1444917718-28495-1-git-send-email-ville.syrjala@linux.intel.com Fixes: 6156a45602f9 ("drm/i915: skylake primary plane scaling using shared scalers") Reviewed-by: Matt Roper --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9b6e726666c3..a851cb70479e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4438,7 +4438,7 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state) intel_crtc->base.base.id, intel_crtc->pipe, SKL_CRTC_INDEX); return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX, - &state->scaler_state.scaler_id, DRM_ROTATE_0, + &state->scaler_state.scaler_id, BIT(DRM_ROTATE_0), state->pipe_src_w, state->pipe_src_h, adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_vdisplay); } -- cgit v1.2.3 From aa45950bac01bf9319328e67696cf0b231cec39d Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Mon, 18 Jan 2016 23:54:20 +0800 Subject: drm/i915: use hlist_for_each_entry Use hlist_for_each_entry() instead of hlist_for_each() to simplify the code. Signed-off-by: Geliang Tang Link: http://patchwork.freedesktop.org/patch/msgid/b80568b2990ebcc145229a132f045e852ac51ad6.1453126187.git.geliangtang@163.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index d469c4779ff5..4edf1c062210 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -193,13 +193,10 @@ static struct i915_vma *eb_get_vma(struct eb_vmas *eb, unsigned long handle) return eb->lut[handle]; } else { struct hlist_head *head; - struct hlist_node *node; + struct i915_vma *vma; head = &eb->buckets[handle & eb->and]; - hlist_for_each(node, head) { - struct i915_vma *vma; - - vma = hlist_entry(node, struct i915_vma, exec_node); + hlist_for_each_entry(vma, head, exec_node) { if (vma->exec_handle == handle) return vma; } -- cgit v1.2.3 From d9202af2ffa083f096684fd5f4b530aebbc07439 Mon Sep 17 00:00:00 2001 From: Timo Teräs Date: Sat, 16 Jan 2016 20:22:07 -0800 Subject: Input: rotary_encoder - convert to devm-* api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use managed resource API for simplifying error paths. Signed-off-by: Timo Teräs Signed-off-by: Dmitry Torokhov --- drivers/input/misc/rotary_encoder.c | 86 +++++++++++-------------------------- 1 file changed, 25 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 8aee71986430..ebbadf3f0579 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -211,8 +211,8 @@ static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct devic if (!of_id || !np) return NULL; - pdata = kzalloc(sizeof(struct rotary_encoder_platform_data), - GFP_KERNEL); + pdata = devm_kzalloc(dev, sizeof(struct rotary_encoder_platform_data), + GFP_KERNEL); if (!pdata) return ERR_PTR(-ENOMEM); @@ -277,12 +277,13 @@ static int rotary_encoder_probe(struct platform_device *pdev) } } - encoder = kzalloc(sizeof(struct rotary_encoder), GFP_KERNEL); - input = input_allocate_device(); - if (!encoder || !input) { - err = -ENOMEM; - goto exit_free_mem; - } + encoder = devm_kzalloc(dev, sizeof(struct rotary_encoder), GFP_KERNEL); + if (!encoder) + return -ENOMEM; + + input = devm_input_allocate_device(dev); + if (!input) + return -ENOMEM; encoder->input = input; encoder->pdata = pdata; @@ -301,16 +302,18 @@ static int rotary_encoder_probe(struct platform_device *pdev) } /* request the GPIOs */ - err = gpio_request_one(pdata->gpio_a, GPIOF_IN, dev_name(dev)); + err = devm_gpio_request_one(dev, pdata->gpio_a, GPIOF_IN, + dev_name(dev)); if (err) { dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_a); - goto exit_free_mem; + return err; } - err = gpio_request_one(pdata->gpio_b, GPIOF_IN, dev_name(dev)); + err = devm_gpio_request_one(dev, pdata->gpio_b, GPIOF_IN, + dev_name(dev)); if (err) { dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_b); - goto exit_free_gpio_a; + return err; } encoder->irq_a = gpio_to_irq(pdata->gpio_a); @@ -331,30 +334,29 @@ static int rotary_encoder_probe(struct platform_device *pdev) default: dev_err(dev, "'%d' is not a valid steps-per-period value\n", pdata->steps_per_period); - err = -EINVAL; - goto exit_free_gpio_b; + return -EINVAL; } - err = request_irq(encoder->irq_a, handler, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - DRV_NAME, encoder); + err = devm_request_irq(dev, encoder->irq_a, handler, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + DRV_NAME, encoder); if (err) { dev_err(dev, "unable to request IRQ %d\n", encoder->irq_a); - goto exit_free_gpio_b; + return err; } - err = request_irq(encoder->irq_b, handler, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - DRV_NAME, encoder); + err = devm_request_irq(dev, encoder->irq_b, handler, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + DRV_NAME, encoder); if (err) { dev_err(dev, "unable to request IRQ %d\n", encoder->irq_b); - goto exit_free_irq_a; + return err; } err = input_register_device(input); if (err) { dev_err(dev, "failed to register input device\n"); - goto exit_free_irq_b; + return err; } device_init_wakeup(&pdev->dev, pdata->wakeup_source); @@ -362,43 +364,6 @@ static int rotary_encoder_probe(struct platform_device *pdev) platform_set_drvdata(pdev, encoder); return 0; - -exit_free_irq_b: - free_irq(encoder->irq_b, encoder); -exit_free_irq_a: - free_irq(encoder->irq_a, encoder); -exit_free_gpio_b: - gpio_free(pdata->gpio_b); -exit_free_gpio_a: - gpio_free(pdata->gpio_a); -exit_free_mem: - input_free_device(input); - kfree(encoder); - if (!dev_get_platdata(&pdev->dev)) - kfree(pdata); - - return err; -} - -static int rotary_encoder_remove(struct platform_device *pdev) -{ - struct rotary_encoder *encoder = platform_get_drvdata(pdev); - const struct rotary_encoder_platform_data *pdata = encoder->pdata; - - device_init_wakeup(&pdev->dev, false); - - free_irq(encoder->irq_a, encoder); - free_irq(encoder->irq_b, encoder); - gpio_free(pdata->gpio_a); - gpio_free(pdata->gpio_b); - - input_unregister_device(encoder->input); - kfree(encoder); - - if (!dev_get_platdata(&pdev->dev)) - kfree(pdata); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -432,7 +397,6 @@ static SIMPLE_DEV_PM_OPS(rotary_encoder_pm_ops, static struct platform_driver rotary_encoder_driver = { .probe = rotary_encoder_probe, - .remove = rotary_encoder_remove, .driver = { .name = DRV_NAME, .pm = &rotary_encoder_pm_ops, -- cgit v1.2.3 From 599b082095432f083da89ff53d95b4a878e1fca1 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Fri, 8 Jan 2016 17:14:54 -0800 Subject: HID: wacom - request tool info only when we get general events Move wacom_intuos_schedule_prox_event inside wacom_intuos_general so we don't call it when general event data isn't ready. Signed-off-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 99ef77fcfb80..d5dc59af5bbf 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -750,13 +750,6 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) return 2; } - /* don't report other events if we don't know the ID */ - if (!wacom->id[idx]) { - /* but reschedule a read of the current tool */ - wacom_intuos_schedule_prox_event(wacom); - return 1; - } - return 0; } @@ -897,6 +890,13 @@ static int wacom_intuos_general(struct wacom_wac *wacom) data[0] != WACOM_REPORT_INTUOS_PEN) return 0; + /* don't report events if we don't know the tool ID */ + if (!wacom->id[idx]) { + /* but reschedule a read of the current tool */ + wacom_intuos_schedule_prox_event(wacom); + return 1; + } + x = (be16_to_cpup((__be16 *)&data[2]) << 1) | ((data[9] >> 1) & 1); y = (be16_to_cpup((__be16 *)&data[4]) << 1) | (data[9] & 1); distance = data[9] >> 2; -- cgit v1.2.3 From 4750f5fe293ae34d334189a77da844f8754862ef Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Fri, 8 Jan 2016 17:15:48 -0800 Subject: HID: wacom - make sure wacom_intuos_inout only process in/out events Move general events related data validation to wacom_intuos_general. Signed-off-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index d5dc59af5bbf..c92ea1a24ee4 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -580,11 +580,12 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; struct input_dev *input = wacom->pen_input; - int idx = 0; + int idx = (features->type == INTUOS) ? (data[1] & 0x01) : 0; - /* tool number */ - if (features->type == INTUOS) - idx = data[1] & 0x01; + if (!(((data[1] & 0xfc) == 0xc0) || /* in prox */ + ((data[1] & 0xfe) == 0x20) || /* in range */ + ((data[1] & 0xfe) == 0x80))) /* out prox */ + return 0; /* Enter report */ if ((data[1] & 0xfc) == 0xc0) { @@ -676,26 +677,6 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) return 1; } - /* - * don't report events for invalid data - */ - /* older I4 styli don't work with new Cintiqs */ - if ((!((wacom->id[idx] >> 20) & 0x01) && - (features->type == WACOM_21UX2)) || - /* Only large Intuos support Lense Cursor */ - (wacom->tool[idx] == BTN_TOOL_LENS && - (features->type == INTUOS3 || - features->type == INTUOS3S || - features->type == INTUOS4 || - features->type == INTUOS4S || - features->type == INTUOS5 || - features->type == INTUOS5S || - features->type == INTUOSPM || - features->type == INTUOSPS)) || - /* Cintiq doesn't send data when RDY bit isn't set */ - (features->type == CINTIQ && !(data[1] & 0x40))) - return 1; - wacom->shared->stylus_in_proximity = true; if (wacom->shared->touch_down) return 1; @@ -897,6 +878,26 @@ static int wacom_intuos_general(struct wacom_wac *wacom) return 1; } + /* + * don't report events for invalid data + */ + /* older I4 styli don't work with new Cintiqs */ + if ((!((wacom->id[idx] >> 20) & 0x01) && + (features->type == WACOM_21UX2)) || + /* Only large Intuos support Lense Cursor */ + (wacom->tool[idx] == BTN_TOOL_LENS && + (features->type == INTUOS3 || + features->type == INTUOS3S || + features->type == INTUOS4 || + features->type == INTUOS4S || + features->type == INTUOS5 || + features->type == INTUOS5S || + features->type == INTUOSPM || + features->type == INTUOSPS)) || + /* Cintiq doesn't send data when RDY bit isn't set */ + (features->type == CINTIQ && !(data[1] & 0x40))) + return 1; + x = (be16_to_cpup((__be16 *)&data[2]) << 1) | ((data[9] >> 1) & 1); y = (be16_to_cpup((__be16 *)&data[4]) << 1) | (data[9] & 1); distance = data[9] >> 2; -- cgit v1.2.3 From c1b03f5511d6aeab3c141c133b492ea492207e64 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Fri, 8 Jan 2016 17:16:06 -0800 Subject: HID: wacom - Cleanup touch arbitration logic stylus_in_proximity was introduced to support touch arbitration before in range was supported. With in range event, the logic changed. stylus_in_proximity should be set for both in prox and in range events. To finish a clean touch arbitration logic, we should send touch up (if it was down) before posting any general pen events. Signed-off-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index c92ea1a24ee4..28f6a9e2ad6f 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -674,19 +674,22 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) wacom->tool[idx] = BTN_TOOL_PEN; break; } + wacom->shared->stylus_in_proximity = true; return 1; } - wacom->shared->stylus_in_proximity = true; - if (wacom->shared->touch_down) - return 1; + /* in Range */ + if ((data[1] & 0xfe) == 0x20) { + wacom->shared->stylus_in_proximity = true; - /* in Range while exiting */ - if (((data[1] & 0xfe) == 0x20) && wacom->reporting_data) { - input_report_key(input, BTN_TOUCH, 0); - input_report_abs(input, ABS_PRESSURE, 0); - input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max); - return 2; + /* in Range while exiting */ + if (wacom->reporting_data) { + input_report_key(input, BTN_TOUCH, 0); + input_report_abs(input, ABS_PRESSURE, 0); + input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max); + return 2; + } + return 1; } /* Exit report */ @@ -871,6 +874,9 @@ static int wacom_intuos_general(struct wacom_wac *wacom) data[0] != WACOM_REPORT_INTUOS_PEN) return 0; + if (wacom->shared->touch_down) + return 1; + /* don't report events if we don't know the tool ID */ if (!wacom->id[idx]) { /* but reschedule a read of the current tool */ -- cgit v1.2.3 From 526d6e7b57062c494346149fb2d6aff0be78ed89 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Fri, 8 Jan 2016 17:16:25 -0800 Subject: HID: wacom - Add quirks for INTUOSHT2 in range events INTUOSHT2 in range event is not used to indicate in proximity state. INTUOSHT2 only has one stylus. Signed-off-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 28f6a9e2ad6f..e92e1e855a72 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -613,6 +613,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) case 0x885: /* Intuos3 Marker Pen */ case 0x802: /* Intuos4/5 13HD/24HD General Pen */ case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */ + case 0x8e2: /* IntuosHT2 pen */ case 0x022: case 0x100804: /* Intuos4/5 13HD/24HD Art Pen */ case 0x140802: /* Intuos4/5 13HD/24HD Classic Pen */ @@ -680,7 +681,8 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) /* in Range */ if ((data[1] & 0xfe) == 0x20) { - wacom->shared->stylus_in_proximity = true; + if (features->type != INTUOSHT2) + wacom->shared->stylus_in_proximity = true; /* in Range while exiting */ if (wacom->reporting_data) { -- cgit v1.2.3 From 19f4c2ba869517048add62c202f9645b6adf5dfb Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 8 Jan 2016 17:58:49 +0100 Subject: HID: sony: do not bail out when the sixaxis refuses the output report When setting the operational mode, some third party (Speedlink Strike-FX) gamepads refuse the output report. Failing here means we refuse to initialize the gamepad while this should be harmless. The weird part is that the initial commit that added this: a7de9b8 ("HID: sony: Enable Gasia third-party PS3 controllers") mentions this very same controller as one requiring this output report. Anyway, it's broken for one user at least, so let's change it. We will report an error, but at least the controller should work. And no, these devices present themselves as legacy Sony controllers (VID:PID of 054C:0268, as in the official ones) so there are no ways of discriminating them from the official ones. https://bugzilla.redhat.com/show_bug.cgi?id=1255325 Reported-and-tested-by: Max Fedotov Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 9b8db0e0ef1c..b2d2fae7a082 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -1420,8 +1420,10 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev) } ret = hid_hw_output_report(hdev, buf, 1); - if (ret < 0) - hid_err(hdev, "can't set operational mode: step 3\n"); + if (ret < 0) { + hid_info(hdev, "can't set operational mode: step 3, ignoring\n"); + ret = 0; + } out: kfree(buf); -- cgit v1.2.3 From 74500cc859431de12469f12b8e711d65efdc7604 Mon Sep 17 00:00:00 2001 From: Scott Moreau Date: Wed, 13 Jan 2016 07:40:42 -0700 Subject: HID: sony: Add nyko core controller support This adds rumble and LED support for nyko core controllers using the sino lite chip vendor:1345 product:3008, for PS3. Setting operational mode and output reports are the same as sixaxis but the input report has a different format since the PS3 accepts HID usb devices. For it to work, an exception is needed to skip overriding the report descriptor and use the original one. Signed-off-by: Scott Moreau Acked-by: Antonio Ospite Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 3 +++ drivers/hid/hid-sony.c | 7 +++++++ 3 files changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 7e89288b1537..7c1193a4c86f 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2003,6 +2003,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) }, { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, { HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b6ff6e78ac54..a382cab8e575 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -872,6 +872,9 @@ #define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002 #define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x1000 +#define USB_VENDOR_ID_SINO_LITE 0x1345 +#define USB_DEVICE_ID_SINO_LITE_CONTROLLER 0x3008 + #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST 0x0046 diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index b2d2fae7a082..123b11a25ce6 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -50,6 +50,7 @@ #define MOTION_CONTROLLER_BT BIT(8) #define NAVIGATION_CONTROLLER_USB BIT(9) #define NAVIGATION_CONTROLLER_BT BIT(10) +#define SINO_LITE_CONTROLLER BIT(11) #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT) @@ -1118,6 +1119,9 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, { struct sony_sc *sc = hid_get_drvdata(hdev); + if (sc->quirks & SINO_LITE_CONTROLLER) + return rdesc; + /* * Some Sony RF receivers wrongly declare the mouse pointer as a * a constant non-data variable. @@ -2523,6 +2527,9 @@ static const struct hid_device_id sony_devices[] = { .driver_data = DUALSHOCK4_CONTROLLER_USB }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), .driver_data = DUALSHOCK4_CONTROLLER_BT }, + /* Nyko Core Controller for PS3 */ + { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER), + .driver_data = SIXAXIS_CONTROLLER_USB | SINO_LITE_CONTROLLER }, { } }; MODULE_DEVICE_TABLE(hid, sony_devices); -- cgit v1.2.3 From ad07b7a6cf8898e1ec76a2641f6186c80d0b8a29 Mon Sep 17 00:00:00 2001 From: Scott Moreau Date: Wed, 13 Jan 2016 07:40:43 -0700 Subject: HID: sony: Fixup output reports for the nyko core controller The nyko core controller uses the same output report format as the sixaxis controllers, but it expects the report id at offset 1. This does not interfere with the official controllers as this byte is considered a padding byte by the current code. Signed-off-by: Scott Moreau Acked-by: Antonio Ospite Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 123b11a25ce6..173af01ca080 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -1802,7 +1802,7 @@ static void sixaxis_send_output_report(struct sony_sc *sc) static const union sixaxis_output_report_01 default_report = { .buf = { 0x01, - 0x00, 0xff, 0x00, 0xff, 0x00, + 0x01, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 0x32, -- cgit v1.2.3 From 25aaa3a1e5dba6256fd4a548f088ee1ebbc4b5f8 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 19 Jan 2016 09:26:48 +0100 Subject: drm: initialize default rotation value to DRM_ROTATE_0 When no console framebuffer is enabled, the default plane state is defined by plane reset function. If driver uses generic helper, then rotation property is set to zero. This is not a valid value for that enum. This patch sets default rotation value to DRM_ROTATE_0. Signed-off-by: Marek Szyprowski Link: http://patchwork.freedesktop.org/patch/msgid/1453192008-13283-1-git-send-email-m.szyprowski@samsung.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index b9d8b5393955..f0c39840bacf 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2532,8 +2532,10 @@ void drm_atomic_helper_plane_reset(struct drm_plane *plane) kfree(plane->state); plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL); - if (plane->state) + if (plane->state) { plane->state->plane = plane; + plane->state->rotation = BIT(DRM_ROTATE_0); + } } EXPORT_SYMBOL(drm_atomic_helper_plane_reset); -- cgit v1.2.3 From cbfc2d26ac7364b45fbc6f5790a043c72c8a2230 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 13 Jan 2016 17:38:15 +0000 Subject: drm/i915: Demote user facing DMC firmware load failure message This is an expected error given the lack of the firmware so emit it at KERN_NOTICE and not KERN_ERROR. Also include the firmware URL in the user facing message so that the user can investigate and fix the issue on their own, and also explain the consequence in plain language. The complete failure message, including the first line from the firmware loader, becomes i915 0000:00:02.0: Direct firmware load for i915/skl_dmc_ver1.bin failed with error -2 i915 0000:00:02.0: Failed to load DMC firmware [https://01.org/linuxgraphics/intel-linux-graphics-firmwares], disabling runtime power management. Signed-off-by: Chris Wilson Cc: Damien Lespiau Cc: Imre Deak Cc: Sunil Kamath Cc: Daniel Vetter Cc: Animesh Manna Cc: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1452706695-13518-1-git-send-email-chris@chris-wilson.co.uk Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_csr.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 3f2850029c17..5c2f9a40c81b 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -44,6 +44,8 @@ #define I915_CSR_SKL "i915/skl_dmc_ver1.bin" #define I915_CSR_BXT "i915/bxt_dmc_ver1.bin" +#define FIRMWARE_URL "https://01.org/linuxgraphics/intel-linux-graphics-firmwares" + MODULE_FIRMWARE(I915_CSR_SKL); MODULE_FIRMWARE(I915_CSR_BXT); @@ -282,7 +284,7 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, csr->version < SKL_CSR_VERSION_REQUIRED) { DRM_INFO("Refusing to load old Skylake DMC firmware v%u.%u," " please upgrade to v%u.%u or later" - " [https://01.org/linuxgraphics/intel-linux-graphics-firmwares].\n", + " [" FIRMWARE_URL "].\n", CSR_VERSION_MAJOR(csr->version), CSR_VERSION_MINOR(csr->version), CSR_VERSION_MAJOR(SKL_CSR_VERSION_REQUIRED), @@ -400,7 +402,10 @@ out: CSR_VERSION_MAJOR(csr->version), CSR_VERSION_MINOR(csr->version)); } else { - DRM_ERROR("Failed to load DMC firmware, disabling rpm\n"); + dev_notice(dev_priv->dev->dev, + "Failed to load DMC firmware" + " [" FIRMWARE_URL "]," + " disabling runtime power management.\n"); } release_firmware(fw); -- cgit v1.2.3 From 5137b354bc8a5c04edb10d83f8bdb0bf8896fd68 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 18 Jan 2016 22:40:37 -0800 Subject: HID: fix out of bound access in extract() and implement() extract() and implement() access buffer containing reports in 64-bit chunks, but there is no guarantee that buffers are padded to 64 bit boundary. In fact, KASAN has caught such OOB access with i2c-hid and Synaptics touch controller. Instead of trying to hunt all parties that allocate buffers and make sure they are padded, let's switch extract() and implement() to byte access. It is a bit slower, bit we are not dealing with super fast devices here. Also let's fix link to the HID spec while we are at it. Signed-off-by: Dmitry Torokhov Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 90 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 7e89288b1537..16c2c660ab5a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1075,7 +1075,7 @@ static u32 s32ton(__s32 value, unsigned n) * Extract/implement a data field from/to a little endian report (bit array). * * Code sort-of follows HID spec: - * http://www.usb.org/developers/devclass_docs/HID1_11.pdf + * http://www.usb.org/developers/hidpage/HID1_11.pdf * * While the USB HID spec allows unlimited length bit fields in "report * descriptors", most devices never use more than 16 bits. @@ -1083,20 +1083,37 @@ static u32 s32ton(__s32 value, unsigned n) * Search linux-kernel and linux-usb-devel archives for "hid-core extract". */ -__u32 hid_field_extract(const struct hid_device *hid, __u8 *report, - unsigned offset, unsigned n) -{ - u64 x; +static u32 __extract(u8 *report, unsigned offset, int n) +{ + unsigned int idx = offset / 8; + unsigned int bit_nr = 0; + unsigned int bit_shift = offset % 8; + int bits_to_copy = 8 - bit_shift; + u32 value = 0; + u32 mask = n < 32 ? (1U << n) - 1 : ~0U; + + while (n > 0) { + value |= ((u32)report[idx] >> bit_shift) << bit_nr; + n -= bits_to_copy; + bit_nr += bits_to_copy; + bits_to_copy = 8; + bit_shift = 0; + idx++; + } + + return value & mask; +} - if (n > 32) +u32 hid_field_extract(const struct hid_device *hid, u8 *report, + unsigned offset, unsigned n) +{ + if (n > 32) { hid_warn(hid, "hid_field_extract() called with n (%d) > 32! (%s)\n", n, current->comm); + n = 32; + } - report += offset >> 3; /* adjust byte index */ - offset &= 7; /* now only need bit offset into one byte */ - x = get_unaligned_le64(report); - x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */ - return (u32) x; + return __extract(report, offset, n); } EXPORT_SYMBOL_GPL(hid_field_extract); @@ -1106,31 +1123,56 @@ EXPORT_SYMBOL_GPL(hid_field_extract); * The data mangled in the bit stream remains in little endian * order the whole time. It make more sense to talk about * endianness of register values by considering a register - * a "cached" copy of the little endiad bit stream. + * a "cached" copy of the little endian bit stream. */ -static void implement(const struct hid_device *hid, __u8 *report, - unsigned offset, unsigned n, __u32 value) + +static void __implement(u8 *report, unsigned offset, int n, u32 value) +{ + unsigned int idx = offset / 8; + unsigned int size = offset + n; + unsigned int bit_shift = offset % 8; + int bits_to_set = 8 - bit_shift; + u8 bit_mask = 0xff << bit_shift; + + while (n - bits_to_set >= 0) { + report[idx] &= ~bit_mask; + report[idx] |= value << bit_shift; + value >>= bits_to_set; + n -= bits_to_set; + bits_to_set = 8; + bit_mask = 0xff; + bit_shift = 0; + idx++; + } + + /* last nibble */ + if (n) { + if (size % 8) + bit_mask &= (1U << (size % 8)) - 1; + report[idx] &= ~bit_mask; + report[idx] |= (value << bit_shift) & bit_mask; + } +} + +static void implement(const struct hid_device *hid, u8 *report, + unsigned offset, unsigned n, u32 value) { - u64 x; - u64 m = (1ULL << n) - 1; + u64 m; - if (n > 32) + if (n > 32) { hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n", __func__, n, current->comm); + n = 32; + } + m = (1ULL << n) - 1; if (value > m) hid_warn(hid, "%s() called with too large value %d! (%s)\n", __func__, value, current->comm); WARN_ON(value > m); value &= m; - report += offset >> 3; - offset &= 7; - - x = get_unaligned_le64(report); - x &= ~(m << offset); - x |= ((u64)value) << offset; - put_unaligned_le64(x, report); + __implement(report, offset, n, value); } /* -- cgit v1.2.3 From 50220dead1650609206efe91f0cc116132d59b3f Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 19 Jan 2016 12:34:58 +0100 Subject: HID: core: prevent out-of-bound readings Plugging a Logitech DJ receiver with KASAN activated raises a bunch of out-of-bound readings. The fields are allocated up to MAX_USAGE, meaning that potentially, we do not have enough fields to fit the incoming values. Add checks and silence KASAN. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 16c2c660ab5a..3f6ac5f2862d 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1293,6 +1293,7 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, /* Ignore report if ErrorRollOver */ if (!(field->flags & HID_MAIN_ITEM_VARIABLE) && value[n] >= min && value[n] <= max && + value[n] - min < field->maxusage && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1) goto exit; } @@ -1305,11 +1306,13 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, } if (field->value[n] >= min && field->value[n] <= max + && field->value[n] - min < field->maxusage && field->usage[field->value[n] - min].hid && search(value, field->value[n], count)) hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt); if (value[n] >= min && value[n] <= max + && value[n] - min < field->maxusage && field->usage[value[n] - min].hid && search(field->value, value[n], count)) hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt); -- cgit v1.2.3 From 9571e1d84042f5670df9fabdcbe7dd5da3abe43e Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Tue, 19 Jan 2016 17:59:46 +0900 Subject: drm/amdgpu: Use drm_calloc_large for VM page_tables array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It can be big, depending on the VM address space size, which is tunable via the vm_size module parameter. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93721 Reviewed-by: Christian König Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index aefc668e6b5d..9599f7559b3d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1282,7 +1282,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm) { const unsigned align = min(AMDGPU_VM_PTB_ALIGN_SIZE, AMDGPU_VM_PTE_COUNT * 8); - unsigned pd_size, pd_entries, pts_size; + unsigned pd_size, pd_entries; int i, r; for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { @@ -1300,8 +1300,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm) pd_entries = amdgpu_vm_num_pdes(adev); /* allocate page table array */ - pts_size = pd_entries * sizeof(struct amdgpu_vm_pt); - vm->page_tables = kzalloc(pts_size, GFP_KERNEL); + vm->page_tables = drm_calloc_large(pd_entries, sizeof(struct amdgpu_vm_pt)); if (vm->page_tables == NULL) { DRM_ERROR("Cannot allocate memory for page table array\n"); return -ENOMEM; @@ -1361,7 +1360,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) for (i = 0; i < amdgpu_vm_num_pdes(adev); i++) amdgpu_bo_unref(&vm->page_tables[i].entry.robj); - kfree(vm->page_tables); + drm_free_large(vm->page_tables); amdgpu_bo_unref(&vm->page_directory); fence_put(vm->page_directory_fence); -- cgit v1.2.3 From 3466904d38ff1e63f0a19cb31166db67f2d05c61 Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Mon, 18 Jan 2016 17:00:03 -0500 Subject: drm/amdgpu: Allow the driver to load if amdgpu.powerplay=1 on asics without powerplay support Avoid setting pp_enabled if there is no powerplay implementation. Signed-off-by: Jordan Lazare Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c index 5ee9a0690278..b9d0d55f6b47 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c @@ -99,13 +99,24 @@ static int amdgpu_pp_early_init(void *handle) #ifdef CONFIG_DRM_AMD_POWERPLAY switch (adev->asic_type) { - case CHIP_TONGA: - case CHIP_FIJI: - adev->pp_enabled = (amdgpu_powerplay > 0) ? true : false; - break; - default: - adev->pp_enabled = (amdgpu_powerplay > 0) ? true : false; - break; + case CHIP_TONGA: + case CHIP_FIJI: + adev->pp_enabled = (amdgpu_powerplay == 0) ? false : true; + break; + case CHIP_CARRIZO: + case CHIP_STONEY: + adev->pp_enabled = (amdgpu_powerplay > 0) ? true : false; + break; + /* These chips don't have powerplay implemenations */ + case CHIP_BONAIRE: + case CHIP_HAWAII: + case CHIP_KABINI: + case CHIP_MULLINS: + case CHIP_KAVERI: + case CHIP_TOPAZ: + default: + adev->pp_enabled = false; + break; } #else adev->pp_enabled = false; -- cgit v1.2.3 From 5dc3b7b9eb7efbd0dd57cef50ed29c2a709bf51b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 15 Jan 2016 16:00:30 +0100 Subject: brcmfmac: add missing include linux/module.h is required for defining module parameters Signed-off-by: Felix Fietkau Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 4265b50faa98..cfee477a6eb1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include "core.h" -- cgit v1.2.3 From b7e2d195cc523bd92ed7a64aac089421dbab2a2d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 18 Jan 2016 20:39:56 +0100 Subject: ssb: mark ssb_bus_register as __maybe_unused The SoC variant of the ssb code is now optional like the other ones, which means we can build the framwork without any front-end, but that results in a warning: drivers/ssb/main.c:616:12: warning: 'ssb_bus_register' defined but not used [-Wunused-function] This annotates the ssb_bus_register function as __maybe_unused to shut up the warning. A configuration like this will not work on any hardware of course, but we still want this to silently build without warnings if the configuration is allowed in the first place. Signed-off-by: Arnd Bergmann Fixes: 845da6e58e19 ("ssb: add Kconfig entry for compiling SoC related code") Acked-by: Michael Buesch Signed-off-by: Kalle Valo --- drivers/ssb/main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index cde5ff7529eb..d1a750760cf3 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -613,9 +613,10 @@ out: return err; } -static int ssb_bus_register(struct ssb_bus *bus, - ssb_invariants_func_t get_invariants, - unsigned long baseaddr) +static int __maybe_unused +ssb_bus_register(struct ssb_bus *bus, + ssb_invariants_func_t get_invariants, + unsigned long baseaddr) { int err; -- cgit v1.2.3 From e0045bf80f62779ba75ba04513020d60e59f5298 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Tue, 19 Jan 2016 12:39:24 +0100 Subject: brcmfmac: fix sdio sg table alloc crash With commit 7d34b0560567 ("brcmfmac: Move all module parameters to one place") a bug was introduced causing a null pointer exception. This patch fixes the bug by initializing the sg table till after the settings have been initialized. Fixes: 7d34b0560567 ("brcmfmac: Move all module parameters to one place") Reported-by: Marc Zyngier Tested-by: Marc Zyngier Reviewed-by: Arend Van Spriel Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 40 ++++++++-------------- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 5 +++ .../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 1 + 3 files changed, 21 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index 53637399bb99..b98db8a0a069 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -879,11 +879,24 @@ int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn) return 0; } -static void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev) +void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev) { + struct sdio_func *func; + struct mmc_host *host; + uint max_blocks; uint nents; int err; + func = sdiodev->func[2]; + host = func->card->host; + sdiodev->sg_support = host->max_segs > 1; + max_blocks = min_t(uint, host->max_blk_count, 511u); + sdiodev->max_request_size = min_t(uint, host->max_req_size, + max_blocks * func->cur_blksize); + sdiodev->max_segment_count = min_t(uint, host->max_segs, + SG_MAX_SINGLE_ALLOC); + sdiodev->max_segment_size = host->max_seg_size; + if (!sdiodev->sg_support) return; @@ -1021,9 +1034,6 @@ static void brcmf_sdiod_host_fixup(struct mmc_host *host) static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) { - struct sdio_func *func; - struct mmc_host *host; - uint max_blocks; int ret = 0; sdiodev->num_funcs = 2; @@ -1054,26 +1064,6 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) goto out; } - /* - * determine host related variables after brcmf_sdiod_probe() - * as func->cur_blksize is properly set and F2 init has been - * completed successfully. - */ - func = sdiodev->func[2]; - host = func->card->host; - sdiodev->sg_support = host->max_segs > 1; - max_blocks = min_t(uint, host->max_blk_count, 511u); - sdiodev->max_request_size = min_t(uint, host->max_req_size, - max_blocks * func->cur_blksize); - sdiodev->max_segment_count = min_t(uint, host->max_segs, - SG_MAX_SINGLE_ALLOC); - sdiodev->max_segment_size = host->max_seg_size; - - /* allocate scatter-gather table. sg support - * will be disabled upon allocation failure. - */ - brcmf_sdiod_sgtable_alloc(sdiodev); - ret = brcmf_sdiod_freezer_attach(sdiodev); if (ret) goto out; @@ -1084,7 +1074,7 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) ret = -ENODEV; goto out; } - brcmf_sdiod_host_fixup(host); + brcmf_sdiod_host_fixup(sdiodev->func[2]->card->host); out: if (ret) brcmf_sdiod_remove(sdiodev); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index dd6614332836..a14d9d9da094 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -4114,6 +4114,11 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) goto fail; } + /* allocate scatter-gather table. sg support + * will be disabled upon allocation failure. + */ + brcmf_sdiod_sgtable_alloc(bus->sdiodev); + /* Query the F2 block size, set roundup accordingly */ bus->blocksize = bus->sdiodev->func[2]->cur_blksize; bus->roundup = min(max_roundup, bus->blocksize); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h index 5ec7a6d87672..23f223150cef 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h @@ -342,6 +342,7 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, /* Issue an abort to the specified function */ int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn); +void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev); void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev, enum brcmf_sdiod_state state); #ifdef CONFIG_PM_SLEEP -- cgit v1.2.3 From f3272e7a7456240209e758d6a995acbae1d21e8e Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Mon, 18 Jan 2016 15:59:36 +0000 Subject: drm/i915/gen9: Correct max save/restore register count during gpu reset with GuC In GuC submission mode, driver has to provide a list of registers to be save/restored during gpu reset, make the max no. of registers value consistent with that of the value defined in FW. If they are not in sync then register save/restore during gpu reset won't work as expected. Cc: Alex Dai Cc: Dave Gordon Signed-off-by: Arun Siluvery Link: http://patchwork.freedesktop.org/patch/msgid/1453132776-22229-1-git-send-email-arun.siluvery@linux.intel.com Reviewed-by: Alex Dai Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_guc_fwif.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index b4632f0bf7b2..1856a4740b83 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h @@ -370,7 +370,7 @@ struct guc_policies { #define GUC_REGSET_SAVE_DEFAULT_VALUE 0x8 #define GUC_REGSET_SAVE_CURRENT_VALUE 0x10 -#define GUC_REGSET_MAX_REGISTERS 20 +#define GUC_REGSET_MAX_REGISTERS 25 #define GUC_MMIO_WHITE_LIST_START 0x24d0 #define GUC_MMIO_WHITE_LIST_MAX 12 #define GUC_S3_SAVE_SPACE_PAGES 10 -- cgit v1.2.3 From 5f2f3cad8b878b23f17a11dd5af4f4a2cc41c797 Mon Sep 17 00:00:00 2001 From: Sowmini Varadhan Date: Mon, 18 Jan 2016 16:12:09 -0500 Subject: sunvnet: Initialize network_header and transport_header in vnet_rx_one() vnet_fullcsum() accesses ip_hdr() and transport header to compute the checksum for IPv4 packets, so these need to be initialized in skb created in vnet_rx_one(). Signed-off-by: Sowmini Varadhan Signed-off-by: David S. Miller --- drivers/net/ethernet/sun/sunvnet.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index cc106d892e29..23fa29877f5b 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c @@ -389,17 +389,27 @@ static int vnet_rx_one(struct vnet_port *port, struct vio_net_desc *desc) if (vio_version_after_eq(&port->vio, 1, 8)) { struct vio_net_dext *dext = vio_net_ext(desc); + skb_reset_network_header(skb); + if (dext->flags & VNET_PKT_HCK_IPV4_HDRCKSUM) { if (skb->protocol == ETH_P_IP) { - struct iphdr *iph = (struct iphdr *)skb->data; + struct iphdr *iph = ip_hdr(skb); iph->check = 0; ip_send_check(iph); } } if ((dext->flags & VNET_PKT_HCK_FULLCKSUM) && - skb->ip_summed == CHECKSUM_NONE) - vnet_fullcsum(skb); + skb->ip_summed == CHECKSUM_NONE) { + if (skb->protocol == htons(ETH_P_IP)) { + struct iphdr *iph = ip_hdr(skb); + int ihl = iph->ihl * 4; + + skb_reset_transport_header(skb); + skb_set_transport_header(skb, ihl); + vnet_fullcsum(skb); + } + } if (dext->flags & VNET_PKT_HCK_IPV4_HDRCKSUM_OK) { skb->ip_summed = CHECKSUM_PARTIAL; skb->csum_level = 0; -- cgit v1.2.3 From 8483d152db61c5baf5452b844ef65b96ee9a6cfb Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 21 Dec 2015 16:11:44 -0800 Subject: drm/vc4: Remove broken attempt at GPU reset using genpd. I've tested and confirmed that it doesn't actually work. We'll need to sort out how to do this properly later, but for now just remove it since it also caused build breakage due to using CONFIG_PM_SLEEP functions without our Kconfig depending on PM_SLEEP. Signed-off-by: Eric Anholt Acked-by: Sudip Mukherjee --- drivers/gpu/drm/vc4/vc4_v3d.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index 424d515ffcda..314ff71db978 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -144,19 +144,16 @@ int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused) } #endif /* CONFIG_DEBUG_FS */ -/* - * Asks the firmware to turn on power to the V3D engine. - * - * This may be doable with just the clocks interface, though this - * packet does some other register setup from the firmware, too. - */ int vc4_v3d_set_power(struct vc4_dev *vc4, bool on) { - if (on) - return pm_generic_poweroff(&vc4->v3d->pdev->dev); - else - return pm_generic_resume(&vc4->v3d->pdev->dev); + /* XXX: This interface is needed for GPU reset, and the way to + * do it is to turn our power domain off and back on. We + * can't just reset from within the driver, because the reset + * bits are in the power domain's register area, and get set + * during the poweron process. + */ + return 0; } static void vc4_v3d_init_hw(struct drm_device *dev) -- cgit v1.2.3 From c240906d36653944d5c049df7ce667a7e8bea6ac Mon Sep 17 00:00:00 2001 From: John Keeping Date: Tue, 19 Jan 2016 10:46:58 +0000 Subject: drm/atomic-helper: Export framebuffer_changed() The Rockchip driver cannot use drm_atomic_helper_wait_for_vblanks() because it has hardware counters for neither vblanks nor scanlines. In order to simplify re-implementing the functionality for this driver, export the framebuffer_changed() helper so it can be reused. Signed-off-by: John Keeping Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 24 ++++++++++++++++++++---- include/drm/drm_atomic_helper.h | 4 ++++ 2 files changed, 24 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 57cccd68ca52..7c523060a076 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -946,9 +946,23 @@ static void wait_for_fences(struct drm_device *dev, } } -static bool framebuffer_changed(struct drm_device *dev, - struct drm_atomic_state *old_state, - struct drm_crtc *crtc) +/** + * drm_atomic_helper_framebuffer_changed - check if framebuffer has changed + * @dev: DRM device + * @old_state: atomic state object with old state structures + * @crtc: DRM crtc + * + * Checks whether the framebuffer used for this CRTC changes as a result of + * the atomic update. This is useful for drivers which cannot use + * drm_atomic_helper_wait_for_vblanks() and need to reimplement its + * functionality. + * + * Returns: + * true if the framebuffer changed. + */ +bool drm_atomic_helper_framebuffer_changed(struct drm_device *dev, + struct drm_atomic_state *old_state, + struct drm_crtc *crtc) { struct drm_plane *plane; struct drm_plane_state *old_plane_state; @@ -965,6 +979,7 @@ static bool framebuffer_changed(struct drm_device *dev, return false; } +EXPORT_SYMBOL(drm_atomic_helper_framebuffer_changed); /** * drm_atomic_helper_wait_for_vblanks - wait for vblank on crtcs @@ -999,7 +1014,8 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, if (old_state->legacy_cursor_update) continue; - if (!framebuffer_changed(dev, old_state, crtc)) + if (!drm_atomic_helper_framebuffer_changed(dev, + old_state, crtc)) continue; ret = drm_crtc_vblank_get(crtc); diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 89d008dc08e2..fe5efada9d68 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -42,6 +42,10 @@ int drm_atomic_helper_commit(struct drm_device *dev, struct drm_atomic_state *state, bool async); +bool drm_atomic_helper_framebuffer_changed(struct drm_device *dev, + struct drm_atomic_state *old_state, + struct drm_crtc *crtc); + void drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, struct drm_atomic_state *old_state); -- cgit v1.2.3 From f2227f469782e55765deacb8ebcc7ec05fe04013 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Tue, 19 Jan 2016 10:46:59 +0000 Subject: drm/rockchip: don't wait for vblank if fb hasn't changed As commented in drm_atomic_helper_wait_for_vblanks(), userspace relies on cursor ioctls being unsynced. Converting the rockchip driver to atomic has significantly impacted cursor performance by making every cursor update wait for vblank. By skipping the vblank sync when the framebuffer has not changed (as is done in drm_atomic_helper_wait_for_vblanks()) we can avoid this for the common case of moving the cursor and only need to delay the cursor ioctl when the cursor icon changes. We cannot add the check on legacy_cursor_update since that results in the cursor bo being unreferenced while the hardware may still be reading it. Fully supporting unsynced cursor updates is left for the future when the atomic helper framework supports async updates. Signed-off-by: John Keeping Tested-by: Heiko Stuebner --- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index dd1f8d3c98d8..87c77c4b5e50 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -177,7 +177,7 @@ static void rockchip_crtc_wait_for_update(struct drm_crtc *crtc) } static void -rockchip_atomic_wait_for_complete(struct drm_atomic_state *old_state) +rockchip_atomic_wait_for_complete(struct drm_device *dev, struct drm_atomic_state *old_state) { struct drm_crtc_state *old_crtc_state; struct drm_crtc *crtc; @@ -193,6 +193,10 @@ rockchip_atomic_wait_for_complete(struct drm_atomic_state *old_state) if (!crtc->state->active) continue; + if (!drm_atomic_helper_framebuffer_changed(dev, + old_state, crtc)) + continue; + ret = drm_crtc_vblank_get(crtc); if (ret != 0) continue; @@ -240,7 +244,7 @@ rockchip_atomic_commit_complete(struct rockchip_atomic_commit *commit) drm_atomic_helper_commit_planes(dev, state, true); - rockchip_atomic_wait_for_complete(state); + rockchip_atomic_wait_for_complete(dev, state); drm_atomic_helper_cleanup_planes(dev, state); -- cgit v1.2.3 From c9ad1d9946e849ac3d8821d91e136d7fd728dec5 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Tue, 19 Jan 2016 10:47:00 +0000 Subject: drm/rockchip: explain why we can't wait_for_vblanks Signed-off-by: John Keeping --- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 87c77c4b5e50..3b8f652698f8 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -176,6 +176,21 @@ static void rockchip_crtc_wait_for_update(struct drm_crtc *crtc) crtc_funcs->wait_for_update(crtc); } +/* + * We can't use drm_atomic_helper_wait_for_vblanks() because rk3288 and rk3066 + * have hardware counters for neither vblanks nor scanlines, which results in + * a race where: + * | <-- HW vsync irq and reg take effect + * plane_commit --> | + * get_vblank and wait --> | + * | <-- handle_vblank, vblank->count + 1 + * cleanup_fb --> | + * iommu crash --> | + * | <-- HW vsync irq and reg take effect + * + * This function is equivalent but uses rockchip_crtc_wait_for_update() instead + * of waiting for vblank_count to change. + */ static void rockchip_atomic_wait_for_complete(struct drm_device *dev, struct drm_atomic_state *old_state) { -- cgit v1.2.3 From 38e5cced0173657853cf1f058b59f869630cad7a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 18 Jan 2016 09:19:46 +0200 Subject: drm/i915/sdvo: revert bogus kernel-doc comments to normal comments The comments were never proper kernel-doc, but with SDVO it's not worth the trouble to make them kernel-doc. Just turn them into normal comments. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1453101588-18008-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_sdvo_regs.h | 76 +++++++++++++++++----------------- 1 file changed, 38 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 2e2d4eb4a00d..db0ed499268a 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h @@ -24,8 +24,8 @@ * Eric Anholt */ -/** - * @file SDVO command definitions and structures. +/* + * SDVO command definitions and structures. */ #define SDVO_OUTPUT_FIRST (0) @@ -66,39 +66,39 @@ struct intel_sdvo_caps { #define DTD_FLAG_VSYNC_POSITIVE (1 << 2) #define DTD_FLAG_INTERLACE (1 << 7) -/** This matches the EDID DTD structure, more or less */ +/* This matches the EDID DTD structure, more or less */ struct intel_sdvo_dtd { struct { - u16 clock; /**< pixel clock, in 10kHz units */ - u8 h_active; /**< lower 8 bits (pixels) */ - u8 h_blank; /**< lower 8 bits (pixels) */ - u8 h_high; /**< upper 4 bits each h_active, h_blank */ - u8 v_active; /**< lower 8 bits (lines) */ - u8 v_blank; /**< lower 8 bits (lines) */ - u8 v_high; /**< upper 4 bits each v_active, v_blank */ + u16 clock; /* pixel clock, in 10kHz units */ + u8 h_active; /* lower 8 bits (pixels) */ + u8 h_blank; /* lower 8 bits (pixels) */ + u8 h_high; /* upper 4 bits each h_active, h_blank */ + u8 v_active; /* lower 8 bits (lines) */ + u8 v_blank; /* lower 8 bits (lines) */ + u8 v_high; /* upper 4 bits each v_active, v_blank */ } part1; struct { - u8 h_sync_off; /**< lower 8 bits, from hblank start */ - u8 h_sync_width; /**< lower 8 bits (pixels) */ - /** lower 4 bits each vsync offset, vsync width */ + u8 h_sync_off; /* lower 8 bits, from hblank start */ + u8 h_sync_width; /* lower 8 bits (pixels) */ + /* lower 4 bits each vsync offset, vsync width */ u8 v_sync_off_width; - /** + /* * 2 high bits of hsync offset, 2 high bits of hsync width, * bits 4-5 of vsync offset, and 2 high bits of vsync width. */ u8 sync_off_width_high; u8 dtd_flags; u8 sdvo_flags; - /** bits 6-7 of vsync offset at bits 6-7 */ + /* bits 6-7 of vsync offset at bits 6-7 */ u8 v_sync_off_high; u8 reserved; } part2; } __packed; struct intel_sdvo_pixel_clock_range { - u16 min; /**< pixel clock, in 10kHz units */ - u16 max; /**< pixel clock, in 10kHz units */ + u16 min; /* pixel clock, in 10kHz units */ + u16 max; /* pixel clock, in 10kHz units */ } __packed; struct intel_sdvo_preferred_input_timing_args { @@ -144,7 +144,7 @@ struct intel_sdvo_preferred_input_timing_args { #define SDVO_CMD_RESET 0x01 -/** Returns a struct intel_sdvo_caps */ +/* Returns a struct intel_sdvo_caps */ #define SDVO_CMD_GET_DEVICE_CAPS 0x02 #define SDVO_CMD_GET_FIRMWARE_REV 0x86 @@ -152,7 +152,7 @@ struct intel_sdvo_preferred_input_timing_args { # define SDVO_DEVICE_FIRMWARE_MAJOR SDVO_I2C_RETURN_1 # define SDVO_DEVICE_FIRMWARE_PATCH SDVO_I2C_RETURN_2 -/** +/* * Reports which inputs are trained (managed to sync). * * Devices must have trained within 2 vsyncs of a mode change. @@ -164,10 +164,10 @@ struct intel_sdvo_get_trained_inputs_response { unsigned int pad:6; } __packed; -/** Returns a struct intel_sdvo_output_flags of active outputs. */ +/* Returns a struct intel_sdvo_output_flags of active outputs. */ #define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04 -/** +/* * Sets the current set of active outputs. * * Takes a struct intel_sdvo_output_flags. Must be preceded by a SET_IN_OUT_MAP @@ -175,7 +175,7 @@ struct intel_sdvo_get_trained_inputs_response { */ #define SDVO_CMD_SET_ACTIVE_OUTPUTS 0x05 -/** +/* * Returns the current mapping of SDVO inputs to outputs on the device. * * Returns two struct intel_sdvo_output_flags structures. @@ -185,29 +185,29 @@ struct intel_sdvo_in_out_map { u16 in0, in1; }; -/** +/* * Sets the current mapping of SDVO inputs to outputs on the device. * * Takes two struct i380_sdvo_output_flags structures. */ #define SDVO_CMD_SET_IN_OUT_MAP 0x07 -/** +/* * Returns a struct intel_sdvo_output_flags of attached displays. */ #define SDVO_CMD_GET_ATTACHED_DISPLAYS 0x0b -/** +/* * Returns a struct intel_sdvo_ouptut_flags of displays supporting hot plugging. */ #define SDVO_CMD_GET_HOT_PLUG_SUPPORT 0x0c -/** +/* * Takes a struct intel_sdvo_output_flags. */ #define SDVO_CMD_SET_ACTIVE_HOT_PLUG 0x0d -/** +/* * Returns a struct intel_sdvo_output_flags of displays with hot plug * interrupts enabled. */ @@ -221,7 +221,7 @@ struct intel_sdvo_get_interrupt_event_source_response { unsigned int pad:6; } __packed; -/** +/* * Selects which input is affected by future input commands. * * Commands affected include SET_INPUT_TIMINGS_PART[12], @@ -234,7 +234,7 @@ struct intel_sdvo_set_target_input_args { unsigned int pad:7; } __packed; -/** +/* * Takes a struct intel_sdvo_output_flags of which outputs are targeted by * future output commands. * @@ -280,7 +280,7 @@ struct intel_sdvo_set_target_input_args { # define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH (2 << 4) # define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6 -/** +/* * Generates a DTD based on the given width, height, and flags. * * This will be supported by any device supporting scaling or interlaced @@ -300,24 +300,24 @@ struct intel_sdvo_set_target_input_args { #define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1 0x1b #define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2 0x1c -/** Returns a struct intel_sdvo_pixel_clock_range */ +/* Returns a struct intel_sdvo_pixel_clock_range */ #define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE 0x1d -/** Returns a struct intel_sdvo_pixel_clock_range */ +/* Returns a struct intel_sdvo_pixel_clock_range */ #define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e -/** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */ +/* Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */ #define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f -/** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ +/* Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ #define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20 -/** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ +/* Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ #define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21 # define SDVO_CLOCK_RATE_MULT_1X (1 << 0) # define SDVO_CLOCK_RATE_MULT_2X (1 << 1) # define SDVO_CLOCK_RATE_MULT_4X (1 << 3) #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27 -/** 6 bytes of bit flags for TV formats shared by all TV format functions */ +/* 6 bytes of bit flags for TV formats shared by all TV format functions */ struct intel_sdvo_tv_format { unsigned int ntsc_m:1; unsigned int ntsc_j:1; @@ -376,7 +376,7 @@ struct intel_sdvo_tv_format { #define SDVO_CMD_SET_TV_FORMAT 0x29 -/** Returns the resolutiosn that can be used with the given TV format */ +/* Returns the resolutiosn that can be used with the given TV format */ #define SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT 0x83 struct intel_sdvo_sdtv_resolution_request { unsigned int ntsc_m:1; @@ -539,7 +539,7 @@ struct intel_sdvo_hdtv_resolution_reply { #define SDVO_CMD_GET_MAX_PANEL_POWER_SEQUENCING 0x2d #define SDVO_CMD_GET_PANEL_POWER_SEQUENCING 0x2e #define SDVO_CMD_SET_PANEL_POWER_SEQUENCING 0x2f -/** +/* * The panel power sequencing parameters are in units of milliseconds. * The high fields are bits 8:9 of the 10-bit values. */ -- cgit v1.2.3 From e2828914723a0739058c263af4f74a05a9bd85bb Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 18 Jan 2016 09:19:47 +0200 Subject: drm/i915: turn some bogus kernel-doc comments to normal comments Apparently accidental or misplaced /** kernel-doc comments, confusing the tool. Turn them to normal comments. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1453101588-18008-2-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6b2b3e331a09..7e6e70054d6a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4138,7 +4138,7 @@ void intel_update_watermarks(struct drm_crtc *crtc) dev_priv->display.update_wm(crtc); } -/** +/* * Lock protecting IPS related data structures */ DEFINE_SPINLOCK(mchdev_lock); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index ede57954080e..91ac8a9bd903 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -410,7 +410,7 @@ intel_write_status_page(struct intel_engine_cs *ring, ring->status_page.page_addr[reg] = value; } -/** +/* * Reads a dword out of the status page, which is written to from the command * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or * MI_STORE_DATA_IMM. -- cgit v1.2.3 From 18afd443f7f92c3cf514af531e020c8d992e49ac Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 18 Jan 2016 09:19:48 +0200 Subject: drm/i915: add DOC: headline to RC6 kernel-doc Without the DOC:, kernel-doc confuses the documentation block for something else. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1453101588-18008-3-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7e6e70054d6a..180555553fa2 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -32,6 +32,8 @@ #include /** + * DOC: RC6 + * * RC6 is a special power stage which allows the GPU to enter an very * low-voltage mode when idle, using down to 0V while at this stage. This * stage is entered automatically when the GPU is idle when RC6 support is -- cgit v1.2.3 From bf22045250fafbe733277e13300eaa240ba2104d Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 19 Jan 2016 11:43:04 -0800 Subject: Revert "drm/i915: Add two-stage ILK-style watermark programming (v10)" This reverts commit 396e33ae204f52abebec9e578f44c749305500f4. This commit was triggering some FIFO underrun warnings on ILK-IVB platforms (but surprisingly not on HSW/BDW that share more or less the same codepaths). These underruns were caught by the continuous integration (CI) system and could be reproduced consistently when running the basic acceptance tests (BAT) on the affected platforms. Note that this revert will cause a visible regression for some end-users; the "flicker when mouse moves between monitors in X" issue that was reported before this patch was merged will now return. However regressions that are visible to CI have higher priority since they prevent proper testing of future patches on those platforms. Hopefully we'll be able to figure out the cause of the underruns quickly and remerge an improved version of this patch to fix the regression. Cc: Daniel Vetter Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93640 Signed-off-by: Matt Roper Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453232584-8543-1-git-send-email-matthew.d.roper@intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 1 - drivers/gpu/drm/i915/i915_drv.h | 13 +-- drivers/gpu/drm/i915/intel_atomic.c | 1 - drivers/gpu/drm/i915/intel_display.c | 92 +------------------- drivers/gpu/drm/i915/intel_drv.h | 28 +----- drivers/gpu/drm/i915/intel_pm.c | 162 +++++++++++------------------------ 6 files changed, 56 insertions(+), 241 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index a0f5659032fc..d70d96fe553b 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -896,7 +896,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) mutex_init(&dev_priv->sb_lock); mutex_init(&dev_priv->modeset_restore_lock); mutex_init(&dev_priv->av_mutex); - mutex_init(&dev_priv->wm.wm_mutex); intel_pm_setup(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index af301482e6f8..d3b98c228683 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -628,11 +628,7 @@ struct drm_i915_display_funcs { struct dpll *best_clock); int (*compute_pipe_wm)(struct intel_crtc *crtc, struct drm_atomic_state *state); - int (*compute_intermediate_wm)(struct drm_device *dev, - struct intel_crtc *intel_crtc, - struct intel_crtc_state *newstate); - void (*initial_watermarks)(struct intel_crtc_state *cstate); - void (*optimize_watermarks)(struct intel_crtc_state *cstate); + void (*program_watermarks)(struct intel_crtc_state *cstate); void (*update_wm)(struct drm_crtc *crtc); int (*modeset_calc_cdclk)(struct drm_atomic_state *state); void (*modeset_commit_cdclk)(struct drm_atomic_state *state); @@ -1938,13 +1934,6 @@ struct drm_i915_private { }; uint8_t max_level; - - /* - * Should be held around atomic WM register writing; also - * protects * intel_crtc->wm.active and - * cstate->wm.need_postvbl_update. - */ - struct mutex wm_mutex; } wm; struct i915_runtime_pm pm; diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 9682d94af710..4625f8a9ba12 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -97,7 +97,6 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) crtc_state->disable_lp_wm = false; crtc_state->disable_cxsr = false; crtc_state->wm_changed = false; - crtc_state->wm.need_postvbl_update = false; return &crtc_state->base; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a851cb70479e..3260fc639b07 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4833,42 +4833,7 @@ static void intel_pre_plane_update(struct intel_crtc *crtc) intel_set_memory_cxsr(dev_priv, false); } - /* - * IVB workaround: must disable low power watermarks for at least - * one frame before enabling scaling. LP watermarks can be re-enabled - * when scaling is disabled. - * - * WaCxSRDisabledForSpriteScaling:ivb - */ - if (pipe_config->disable_lp_wm) { - ilk_disable_lp_wm(dev); - intel_wait_for_vblank(dev, crtc->pipe); - } - - /* - * If we're doing a modeset, we're done. No need to do any pre-vblank - * watermark programming here. - */ - if (needs_modeset(&pipe_config->base)) - return; - - /* - * For platforms that support atomic watermarks, program the - * 'intermediate' watermarks immediately. On pre-gen9 platforms, these - * will be the intermediate values that are safe for both pre- and - * post- vblank; when vblank happens, the 'active' values will be set - * to the final 'target' values and we'll do this again to get the - * optimal watermarks. For gen9+ platforms, the values we program here - * will be the final target values which will get automatically latched - * at vblank time; no further programming will be necessary. - * - * If a platform hasn't been transitioned to atomic watermarks yet, - * we'll continue to update watermarks the old way, if flags tell - * us to. - */ - if (dev_priv->display.initial_watermarks != NULL) - dev_priv->display.initial_watermarks(pipe_config); - else if (pipe_config->wm_changed) + if (!needs_modeset(&pipe_config->base) && pipe_config->wm_changed) intel_update_watermarks(&crtc->base); } @@ -11914,11 +11879,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, pipe_config->wm_changed = true; } - /* Pre-gen9 platforms need two-step watermark updates */ - if (pipe_config->wm_changed && INTEL_INFO(dev)->gen < 9 && - dev_priv->display.optimize_watermarks) - to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true; - if (visible || was_visible) intel_crtc->atomic.fb_bits |= to_intel_plane(plane)->frontbuffer_bit; @@ -12075,29 +12035,8 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, ret = 0; if (dev_priv->display.compute_pipe_wm) { ret = dev_priv->display.compute_pipe_wm(intel_crtc, state); - if (ret) { - DRM_DEBUG_KMS("Target pipe watermarks are invalid\n"); - return ret; - } - } - - if (dev_priv->display.compute_intermediate_wm && - !to_intel_atomic_state(state)->skip_intermediate_wm) { - if (WARN_ON(!dev_priv->display.compute_pipe_wm)) - return 0; - - /* - * Calculate 'intermediate' watermarks that satisfy both the - * old state and the new state. We can program these - * immediately. - */ - ret = dev_priv->display.compute_intermediate_wm(crtc->dev, - intel_crtc, - pipe_config); - if (ret) { - DRM_DEBUG_KMS("No valid intermediate pipe watermarks are possible\n"); + if (ret) return ret; - } } if (INTEL_INFO(dev)->gen >= 9) { @@ -13562,7 +13501,6 @@ static int intel_atomic_commit(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc_state *crtc_state; struct drm_crtc *crtc; - struct intel_crtc_state *intel_cstate; int ret = 0, i; bool hw_check = intel_state->modeset; @@ -13662,20 +13600,6 @@ static int intel_atomic_commit(struct drm_device *dev, drm_atomic_helper_wait_for_vblanks(dev, state); - /* - * Now that the vblank has passed, we can go ahead and program the - * optimal watermarks on platforms that need two-step watermark - * programming. - * - * TODO: Move this (and other cleanup) to an async worker eventually. - */ - for_each_crtc_in_state(state, crtc, crtc_state, i) { - intel_cstate = to_intel_crtc_state(crtc->state); - - if (dev_priv->display.optimize_watermarks) - dev_priv->display.optimize_watermarks(intel_cstate); - } - mutex_lock(&dev->struct_mutex); drm_atomic_helper_cleanup_planes(dev, state); mutex_unlock(&dev->struct_mutex); @@ -15342,7 +15266,7 @@ static void sanitize_watermarks(struct drm_device *dev) int i; /* Only supported on platforms that use atomic watermark design */ - if (!dev_priv->display.optimize_watermarks) + if (!dev_priv->display.program_watermarks) return; /* @@ -15363,13 +15287,6 @@ retry: if (WARN_ON(IS_ERR(state))) goto fail; - /* - * Hardware readout is the only time we don't want to calculate - * intermediate watermarks (since we don't trust the current - * watermarks). - */ - to_intel_atomic_state(state)->skip_intermediate_wm = true; - ret = intel_atomic_check(dev, state); if (ret) { /* @@ -15392,8 +15309,7 @@ retry: for_each_crtc_in_state(state, crtc, cstate, i) { struct intel_crtc_state *cs = to_intel_crtc_state(cstate); - cs->wm.need_postvbl_update = true; - dev_priv->display.optimize_watermarks(cs); + dev_priv->display.program_watermarks(cs); } drm_atomic_state_free(state); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 059b46e22c31..15917e3a3352 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -260,12 +260,6 @@ struct intel_atomic_state { struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS]; struct intel_wm_config wm_config; - - /* - * Current watermarks can't be trusted during hardware readout, so - * don't bother calculating intermediate watermarks. - */ - bool skip_intermediate_wm; }; struct intel_plane_state { @@ -513,29 +507,13 @@ struct intel_crtc_state { struct { /* - * Optimal watermarks, programmed post-vblank when this state - * is committed. + * optimal watermarks, programmed post-vblank when this state + * is committed */ union { struct intel_pipe_wm ilk; struct skl_pipe_wm skl; } optimal; - - /* - * Intermediate watermarks; these can be programmed immediately - * since they satisfy both the current configuration we're - * switching away from and the new configuration we're switching - * to. - */ - struct intel_pipe_wm intermediate; - - /* - * Platforms with two-step watermark programming will need to - * update watermark programming post-vblank to switch from the - * safe intermediate watermarks to the optimal final - * watermarks. - */ - bool need_postvbl_update; } wm; }; @@ -622,7 +600,6 @@ struct intel_crtc { struct intel_pipe_wm ilk; struct skl_pipe_wm skl; } active; - /* allow CxSR on this pipe */ bool cxsr_allowed; } wm; @@ -1583,7 +1560,6 @@ void skl_wm_get_hw_state(struct drm_device *dev); void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, struct skl_ddb_allocation *ddb /* out */); uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config); -bool ilk_disable_lp_wm(struct drm_device *dev); /* intel_sdvo.c */ bool intel_sdvo_init(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 180555553fa2..20bf854eae8c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2275,29 +2275,6 @@ static void skl_setup_wm_latency(struct drm_device *dev) intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency); } -static bool ilk_validate_pipe_wm(struct drm_device *dev, - struct intel_pipe_wm *pipe_wm) -{ - /* LP0 watermark maximums depend on this pipe alone */ - const struct intel_wm_config config = { - .num_pipes_active = 1, - .sprites_enabled = pipe_wm->sprites_enabled, - .sprites_scaled = pipe_wm->sprites_scaled, - }; - struct ilk_wm_maximums max; - - /* LP0 watermarks always use 1/2 DDB partitioning */ - ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max); - - /* At least LP0 must be valid */ - if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0])) { - DRM_DEBUG_KMS("LP0 watermark invalid\n"); - return false; - } - - return true; -} - /* Compute new watermarks for the pipe */ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, struct drm_atomic_state *state) @@ -2312,6 +2289,10 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, struct intel_plane_state *sprstate = NULL; struct intel_plane_state *curstate = NULL; int level, max_level = ilk_wm_max_level(dev); + /* LP0 watermark maximums depend on this pipe alone */ + struct intel_wm_config config = { + .num_pipes_active = 1, + }; struct ilk_wm_maximums max; cstate = intel_atomic_get_crtc_state(state, intel_crtc); @@ -2335,18 +2316,21 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, curstate = to_intel_plane_state(ps); } - pipe_wm->pipe_enabled = cstate->base.active; - pipe_wm->sprites_enabled = sprstate->visible; - pipe_wm->sprites_scaled = sprstate->visible && + config.sprites_enabled = sprstate->visible; + config.sprites_scaled = sprstate->visible && (drm_rect_width(&sprstate->dst) != drm_rect_width(&sprstate->src) >> 16 || drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16); + pipe_wm->pipe_enabled = cstate->base.active; + pipe_wm->sprites_enabled = config.sprites_enabled; + pipe_wm->sprites_scaled = config.sprites_scaled; + /* ILK/SNB: LP2+ watermarks only w/o sprites */ if (INTEL_INFO(dev)->gen <= 6 && sprstate->visible) max_level = 1; /* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */ - if (pipe_wm->sprites_scaled) + if (config.sprites_scaled) max_level = 0; ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate, @@ -2355,8 +2339,12 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, if (IS_HASWELL(dev) || IS_BROADWELL(dev)) pipe_wm->linetime = hsw_compute_linetime_wm(dev, cstate); - if (!ilk_validate_pipe_wm(dev, pipe_wm)) - return false; + /* LP0 watermarks always use 1/2 DDB partitioning */ + ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max); + + /* At least LP0 must be valid */ + if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0])) + return -EINVAL; ilk_compute_wm_reg_maximums(dev, 1, &max); @@ -2380,59 +2368,6 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, return 0; } -/* - * Build a set of 'intermediate' watermark values that satisfy both the old - * state and the new state. These can be programmed to the hardware - * immediately. - */ -static int ilk_compute_intermediate_wm(struct drm_device *dev, - struct intel_crtc *intel_crtc, - struct intel_crtc_state *newstate) -{ - struct intel_pipe_wm *a = &newstate->wm.intermediate; - struct intel_pipe_wm *b = &intel_crtc->wm.active.ilk; - int level, max_level = ilk_wm_max_level(dev); - - /* - * Start with the final, target watermarks, then combine with the - * currently active watermarks to get values that are safe both before - * and after the vblank. - */ - *a = newstate->wm.optimal.ilk; - a->pipe_enabled |= b->pipe_enabled; - a->sprites_enabled |= b->sprites_enabled; - a->sprites_scaled |= b->sprites_scaled; - - for (level = 0; level <= max_level; level++) { - struct intel_wm_level *a_wm = &a->wm[level]; - const struct intel_wm_level *b_wm = &b->wm[level]; - - a_wm->enable &= b_wm->enable; - a_wm->pri_val = max(a_wm->pri_val, b_wm->pri_val); - a_wm->spr_val = max(a_wm->spr_val, b_wm->spr_val); - a_wm->cur_val = max(a_wm->cur_val, b_wm->cur_val); - a_wm->fbc_val = max(a_wm->fbc_val, b_wm->fbc_val); - } - - /* - * We need to make sure that these merged watermark values are - * actually a valid configuration themselves. If they're not, - * there's no safe way to transition from the old state to - * the new state, so we need to fail the atomic transaction. - */ - if (!ilk_validate_pipe_wm(dev, a)) - return -EINVAL; - - /* - * If our intermediate WM are identical to the final WM, then we can - * omit the post-vblank programming; only update if it's different. - */ - if (memcmp(a, &newstate->wm.optimal.ilk, sizeof(*a)) != 0) - newstate->wm.need_postvbl_update = false; - - return 0; -} - /* * Merge the watermarks from all active pipes for a specific level. */ @@ -2445,7 +2380,9 @@ static void ilk_merge_wm_level(struct drm_device *dev, ret_wm->enable = true; for_each_intel_crtc(dev, intel_crtc) { - const struct intel_pipe_wm *active = &intel_crtc->wm.active.ilk; + const struct intel_crtc_state *cstate = + to_intel_crtc_state(intel_crtc->base.state); + const struct intel_pipe_wm *active = &cstate->wm.optimal.ilk; const struct intel_wm_level *wm = &active->wm[level]; if (!active->pipe_enabled) @@ -2593,14 +2530,15 @@ static void ilk_compute_wm_results(struct drm_device *dev, /* LP0 register values */ for_each_intel_crtc(dev, intel_crtc) { + const struct intel_crtc_state *cstate = + to_intel_crtc_state(intel_crtc->base.state); enum pipe pipe = intel_crtc->pipe; - const struct intel_wm_level *r = - &intel_crtc->wm.active.ilk.wm[0]; + const struct intel_wm_level *r = &cstate->wm.optimal.ilk.wm[0]; if (WARN_ON(!r->enable)) continue; - results->wm_linetime[pipe] = intel_crtc->wm.active.ilk.linetime; + results->wm_linetime[pipe] = cstate->wm.optimal.ilk.linetime; results->wm_pipe[pipe] = (r->pri_val << WM0_PIPE_PLANE_SHIFT) | @@ -2807,7 +2745,7 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv, dev_priv->wm.hw = *results; } -bool ilk_disable_lp_wm(struct drm_device *dev) +static bool ilk_disable_lp_wm(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -3700,9 +3638,11 @@ static void ilk_compute_wm_config(struct drm_device *dev, } } -static void ilk_program_watermarks(struct drm_i915_private *dev_priv) +static void ilk_program_watermarks(struct intel_crtc_state *cstate) { - struct drm_device *dev = dev_priv->dev; + struct drm_crtc *crtc = cstate->base.crtc; + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = to_i915(dev); struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm; struct ilk_wm_maximums max; struct intel_wm_config config = {}; @@ -3733,28 +3673,28 @@ static void ilk_program_watermarks(struct drm_i915_private *dev_priv) ilk_write_wm_values(dev_priv, &results); } -static void ilk_initial_watermarks(struct intel_crtc_state *cstate) +static void ilk_update_wm(struct drm_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev); - struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); - - mutex_lock(&dev_priv->wm.wm_mutex); - intel_crtc->wm.active.ilk = cstate->wm.intermediate; - ilk_program_watermarks(dev_priv); - mutex_unlock(&dev_priv->wm.wm_mutex); -} + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); -static void ilk_optimize_watermarks(struct intel_crtc_state *cstate) -{ - struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev); - struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); + WARN_ON(cstate->base.active != intel_crtc->active); - mutex_lock(&dev_priv->wm.wm_mutex); - if (cstate->wm.need_postvbl_update) { - intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk; - ilk_program_watermarks(dev_priv); + /* + * IVB workaround: must disable low power watermarks for at least + * one frame before enabling scaling. LP watermarks can be re-enabled + * when scaling is disabled. + * + * WaCxSRDisabledForSpriteScaling:ivb + */ + if (cstate->disable_lp_wm) { + ilk_disable_lp_wm(crtc->dev); + intel_wait_for_vblank(crtc->dev, intel_crtc->pipe); } - mutex_unlock(&dev_priv->wm.wm_mutex); + + intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk; + + ilk_program_watermarks(cstate); } static void skl_pipe_wm_active_state(uint32_t val, @@ -7081,13 +7021,9 @@ void intel_init_pm(struct drm_device *dev) dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) || (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] && dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) { + dev_priv->display.update_wm = ilk_update_wm; dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm; - dev_priv->display.compute_intermediate_wm = - ilk_compute_intermediate_wm; - dev_priv->display.initial_watermarks = - ilk_initial_watermarks; - dev_priv->display.optimize_watermarks = - ilk_optimize_watermarks; + dev_priv->display.program_watermarks = ilk_program_watermarks; } else { DRM_DEBUG_KMS("Failed to read display plane latency. " "Disable CxSR\n"); -- cgit v1.2.3 From 3f36b93797bd773eb27e31cf53e3d1f9e64c77ab Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 19 Jan 2016 15:25:17 +0000 Subject: drm/i915: Do not put big intel_crtc_state on the stack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Having this on stack triggers the -Wframe-larger-than=1024 and is not nice to put such big things on the kernel stack anyway. This required a little bit of refactoring to handle the new failure path from vlv_force_pll_on. v2: Corrected some whitespace. Signed-off-by: Tvrtko Ursulin Cc: Daniel Vetter Cc: John Harrison Cc: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453217117-26125-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 60 +++++++++++++++++++++++------------- drivers/gpu/drm/i915/intel_dp.c | 8 +++-- drivers/gpu/drm/i915/intel_drv.h | 4 +-- 3 files changed, 46 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 3260fc639b07..f5c7f9fbb5ff 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7600,26 +7600,34 @@ static void chv_prepare_pll(struct intel_crtc *crtc, * in cases where we need the PLL enabled even when @pipe is not going to * be enabled. */ -void vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, - const struct dpll *dpll) +int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, + const struct dpll *dpll) { struct intel_crtc *crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe)); - struct intel_crtc_state pipe_config = { - .base.crtc = &crtc->base, - .pixel_multiplier = 1, - .dpll = *dpll, - }; + struct intel_crtc_state *pipe_config; + + pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL); + if (!pipe_config) + return -ENOMEM; + + pipe_config->base.crtc = &crtc->base; + pipe_config->pixel_multiplier = 1; + pipe_config->dpll = *dpll; if (IS_CHERRYVIEW(dev)) { - chv_compute_dpll(crtc, &pipe_config); - chv_prepare_pll(crtc, &pipe_config); - chv_enable_pll(crtc, &pipe_config); + chv_compute_dpll(crtc, pipe_config); + chv_prepare_pll(crtc, pipe_config); + chv_enable_pll(crtc, pipe_config); } else { - vlv_compute_dpll(crtc, &pipe_config); - vlv_prepare_pll(crtc, &pipe_config); - vlv_enable_pll(crtc, &pipe_config); + vlv_compute_dpll(crtc, pipe_config); + vlv_prepare_pll(crtc, pipe_config); + vlv_enable_pll(crtc, pipe_config); } + + kfree(pipe_config); + + return 0; } /** @@ -10793,7 +10801,7 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; struct drm_display_mode *mode; - struct intel_crtc_state pipe_config; + struct intel_crtc_state *pipe_config; int htot = I915_READ(HTOTAL(cpu_transcoder)); int hsync = I915_READ(HSYNC(cpu_transcoder)); int vtot = I915_READ(VTOTAL(cpu_transcoder)); @@ -10804,6 +10812,12 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, if (!mode) return NULL; + pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL); + if (!pipe_config) { + kfree(mode); + return NULL; + } + /* * Construct a pipe_config sufficient for getting the clock info * back out of crtc_clock_get. @@ -10811,14 +10825,14 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, * Note, if LVDS ever uses a non-1 pixel multiplier, we'll need * to use a real value here instead. */ - pipe_config.cpu_transcoder = (enum transcoder) pipe; - pipe_config.pixel_multiplier = 1; - pipe_config.dpll_hw_state.dpll = I915_READ(DPLL(pipe)); - pipe_config.dpll_hw_state.fp0 = I915_READ(FP0(pipe)); - pipe_config.dpll_hw_state.fp1 = I915_READ(FP1(pipe)); - i9xx_crtc_clock_get(intel_crtc, &pipe_config); - - mode->clock = pipe_config.port_clock / pipe_config.pixel_multiplier; + pipe_config->cpu_transcoder = (enum transcoder) pipe; + pipe_config->pixel_multiplier = 1; + pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(pipe)); + pipe_config->dpll_hw_state.fp0 = I915_READ(FP0(pipe)); + pipe_config->dpll_hw_state.fp1 = I915_READ(FP1(pipe)); + i9xx_crtc_clock_get(intel_crtc, pipe_config); + + mode->clock = pipe_config->port_clock / pipe_config->pixel_multiplier; mode->hdisplay = (htot & 0xffff) + 1; mode->htotal = ((htot & 0xffff0000) >> 16) + 1; mode->hsync_start = (hsync & 0xffff) + 1; @@ -10830,6 +10844,8 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, drm_mode_set_name(mode); + kfree(pipe_config); + return mode; } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 17612548c58d..e2bea710614f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -335,8 +335,12 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) release_cl_override = IS_CHERRYVIEW(dev) && !chv_phy_powergate_ch(dev_priv, phy, ch, true); - vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ? - &chv_dpll[0].dpll : &vlv_dpll[0].dpll); + if (vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ? + &chv_dpll[0].dpll : &vlv_dpll[0].dpll)) { + DRM_ERROR("Failed to force on pll for pipe %c!\n", + pipe_name(pipe)); + return; + } } /* diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 15917e3a3352..bc970125ec76 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1154,8 +1154,8 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv, struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, struct intel_crtc_state *state); -void vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, - const struct dpll *dpll); +int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, + const struct dpll *dpll); void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe); /* modesetting asserts */ -- cgit v1.2.3 From 70c0616d5a8458ae9148d74309cede07ba2f5164 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 20 Jan 2016 10:59:34 +0000 Subject: drm/fb_cma_helper: remove duplicate const from drm_fb_cma_alloc Duplicated const, only one is required. Also reformat line to ensure it is less than 80 columns wide. Signed-off-by: Colin Ian King Link: http://patchwork.freedesktop.org/patch/msgid/1453287574-3645-1-git-send-email-colin.king@canonical.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_cma_helper.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index c895b6fddbd8..bb88e3df9257 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -74,7 +74,8 @@ static struct drm_framebuffer_funcs drm_fb_cma_funcs = { }; static struct drm_fb_cma *drm_fb_cma_alloc(struct drm_device *dev, - const const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_cma_object **obj, + const struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_cma_object **obj, unsigned int num_planes) { struct drm_fb_cma *fb_cma; -- cgit v1.2.3 From e794129444aba459e9bedf5080bfb4605f933c32 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 19 Jan 2016 18:23:17 +0200 Subject: drm/i915: Fix NULL plane->fb oops on SKL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In this atomic age, we can't trust the plane->fb pointer anymore. It might get update too late. Instead we are supposed to use the plane_state->fb pointer instead. Let's do that in intel_plane_obj_offset() and avoid problems from dereferencing the potentially stale plane->fb pointer. Paulo found this with 'kms_frontbuffer_tracking --show-hidden --run-subtest nop-1p-rte' but it can be reproduced with just plain old kms_setplane. I was too lazy to bisect this, so not sure exactly when it broke. The most obvious candidate commit ce7f17285639 ("drm/i915: Fix i915_ggtt_view_equal to handle rotation correctly") was actually still fine, so it must have broken some time after that. Here's the resulting fireworks: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] intel_fill_fb_ggtt_view+0x1b/0x15a [i915] PGD 8a5f6067 PUD 8a5f5067 PMD 0 Oops: 0000 [#1] PREEMPT SMP Modules linked in: i915 i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm intel_gtt agpgart netconsole mousedev hid_generic psmouse usbhid atkbd libps2 coretemp hwmon efi_pstore intel_rapl iosf_mbi x86_pkg_temp_thermal efivars pcspkr e1000e sdhci_pci ptp pps_core sdhci i2c_i801 mmc_core i2c_hid hid i8042 serio evdev sch_fq_codel ip_tables x_tables ipv6 autofs4 CPU: 1 PID: 260 Comm: kms_plane Not tainted 4.4.0-skl+ #171 Hardware name: Intel Corporation Skylake Client platform/Skylake Y LPDDR3 RVP3, BIOS SKLSE2R1.R00.B104.B00.1511030553 11/03/2015 task: ffff88008bde2d80 ti: ffff88008a6ec000 task.ti: ffff88008a6ec000 RIP: 0010:[] [] intel_fill_fb_ggtt_view+0x1b/0x15a [i915] RSP: 0018:ffff88008a6efa10 EFLAGS: 00010086 RAX: 0000000000000001 RBX: ffff8801674f4240 RCX: 0000000000000014 RDX: ffff88008a7440c0 RSI: 0000000000000000 RDI: ffff88008a6efa40 RBP: ffff88008a6efa30 R08: ffff88008bde3598 R09: 0000000000000001 R10: ffff88008b782000 R11: 0000000000000000 R12: 0000000000000000 R13: ffff88008a7440c0 R14: 0000000000000000 R15: ffff88008a7449c0 FS: 00007fa0c07a28c0(0000) GS:ffff88016ec40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 000000008a6ff000 CR4: 00000000003406e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Stack: ffff8801674f4240 0000000000000000 ffff88008a7440c0 0000000000000000 ffff88008a6efaa0 ffffffffa02daf25 ffffffff814ec80e 0000000000070298 ffff8800850d0000 ffff88008a6efaa0 ffffffffa02c49c2 0000000000000002 Call Trace: [] intel_plane_obj_offset+0x2d/0xa9 [i915] [] ? _raw_spin_unlock_irqrestore+0x4b/0x60 [] ? gen9_write32+0x2e8/0x3b8 [i915] [] skl_update_plane+0x203/0x4c5 [i915] [] intel_plane_atomic_update+0x53/0x6a [i915] [] drm_atomic_helper_commit_planes_on_crtc+0x142/0x1d5 [drm_kms_helper] [] intel_atomic_commit+0x1262/0x1350 [i915] [] ? __drm_atomic_helper_crtc_duplicate_state+0x2f/0x41 [drm_kms_helper] [] ? drm_atomic_check_only+0x3e3/0x552 [drm] [] drm_atomic_commit+0x4d/0x52 [drm] [] drm_atomic_helper_update_plane+0xcb/0x118 [drm_kms_helper] [] __setplane_internal+0x1c8/0x224 [drm] [] drm_mode_setplane+0x14e/0x172 [drm] [] drm_ioctl+0x265/0x3ad [drm] [] ? drm_mode_cursor_common+0x158/0x158 [drm] [] ? current_kernel_time64+0x5e/0x98 [] ? trace_hardirqs_on_caller+0x17a/0x196 [] do_vfs_ioctl+0x42b/0x4ea [] ? __fget_light+0x4d/0x71 [] SyS_ioctl+0x43/0x61 [] entry_SYSCALL_64_fastpath+0x12/0x6f Cc: drm-intel-fixes@lists.freedesktop.org Cc: Paulo Zanoni Testcase: igt/kms_plane Reported-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1453220597-28973-1-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f5c7f9fbb5ff..06ab6df8ad48 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2940,7 +2940,7 @@ u32 intel_plane_obj_offset(struct intel_plane *intel_plane, struct i915_vma *vma; u64 offset; - intel_fill_fb_ggtt_view(&view, intel_plane->base.fb, + intel_fill_fb_ggtt_view(&view, intel_plane->base.state->fb, intel_plane->base.state); vma = i915_gem_obj_to_ggtt_view(obj, &view); -- cgit v1.2.3 From 849674e4fb175e47b7504249f7367367b18fe6a1 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Wed, 20 Jan 2016 13:52:20 -0800 Subject: MD: rename some functions These short function names are hard to search. Rename them to make vim happy. Signed-off-by: Shaohua Li --- drivers/md/faulty.c | 18 +++++++++--------- drivers/md/raid1.c | 21 +++++++++++---------- drivers/md/raid10.c | 20 ++++++++++---------- drivers/md/raid5.c | 45 +++++++++++++++++++++++---------------------- 4 files changed, 53 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c index 4a8e15058e8b..685aa2d77e25 100644 --- a/drivers/md/faulty.c +++ b/drivers/md/faulty.c @@ -170,7 +170,7 @@ static void add_sector(struct faulty_conf *conf, sector_t start, int mode) conf->nfaults = n+1; } -static void make_request(struct mddev *mddev, struct bio *bio) +static void faulty_make_request(struct mddev *mddev, struct bio *bio) { struct faulty_conf *conf = mddev->private; int failit = 0; @@ -226,7 +226,7 @@ static void make_request(struct mddev *mddev, struct bio *bio) generic_make_request(bio); } -static void status(struct seq_file *seq, struct mddev *mddev) +static void faulty_status(struct seq_file *seq, struct mddev *mddev) { struct faulty_conf *conf = mddev->private; int n; @@ -259,7 +259,7 @@ static void status(struct seq_file *seq, struct mddev *mddev) } -static int reshape(struct mddev *mddev) +static int faulty_reshape(struct mddev *mddev) { int mode = mddev->new_layout & ModeMask; int count = mddev->new_layout >> ModeShift; @@ -299,7 +299,7 @@ static sector_t faulty_size(struct mddev *mddev, sector_t sectors, int raid_disk return sectors; } -static int run(struct mddev *mddev) +static int faulty_run(struct mddev *mddev) { struct md_rdev *rdev; int i; @@ -327,7 +327,7 @@ static int run(struct mddev *mddev) md_set_array_sectors(mddev, faulty_size(mddev, 0, 0)); mddev->private = conf; - reshape(mddev); + faulty_reshape(mddev); return 0; } @@ -344,11 +344,11 @@ static struct md_personality faulty_personality = .name = "faulty", .level = LEVEL_FAULTY, .owner = THIS_MODULE, - .make_request = make_request, - .run = run, + .make_request = faulty_make_request, + .run = faulty_run, .free = faulty_free, - .status = status, - .check_reshape = reshape, + .status = faulty_status, + .check_reshape = faulty_reshape, .size = faulty_size, }; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index c4b913409226..4e3843f7d245 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1044,7 +1044,7 @@ static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule) kfree(plug); } -static void make_request(struct mddev *mddev, struct bio * bio) +static void raid1_make_request(struct mddev *mddev, struct bio * bio) { struct r1conf *conf = mddev->private; struct raid1_info *mirror; @@ -1422,7 +1422,7 @@ read_again: wake_up(&conf->wait_barrier); } -static void status(struct seq_file *seq, struct mddev *mddev) +static void raid1_status(struct seq_file *seq, struct mddev *mddev) { struct r1conf *conf = mddev->private; int i; @@ -1439,7 +1439,7 @@ static void status(struct seq_file *seq, struct mddev *mddev) seq_printf(seq, "]"); } -static void error(struct mddev *mddev, struct md_rdev *rdev) +static void raid1_error(struct mddev *mddev, struct md_rdev *rdev) { char b[BDEVNAME_SIZE]; struct r1conf *conf = mddev->private; @@ -2472,7 +2472,8 @@ static int init_resync(struct r1conf *conf) * that can be installed to exclude normal IO requests. */ -static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipped) +static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr, + int *skipped) { struct r1conf *conf = mddev->private; struct r1bio *r1_bio; @@ -2890,7 +2891,7 @@ static struct r1conf *setup_conf(struct mddev *mddev) } static void raid1_free(struct mddev *mddev, void *priv); -static int run(struct mddev *mddev) +static int raid1_run(struct mddev *mddev) { struct r1conf *conf; int i; @@ -3170,15 +3171,15 @@ static struct md_personality raid1_personality = .name = "raid1", .level = 1, .owner = THIS_MODULE, - .make_request = make_request, - .run = run, + .make_request = raid1_make_request, + .run = raid1_run, .free = raid1_free, - .status = status, - .error_handler = error, + .status = raid1_status, + .error_handler = raid1_error, .hot_add_disk = raid1_add_disk, .hot_remove_disk= raid1_remove_disk, .spare_active = raid1_spare_active, - .sync_request = sync_request, + .sync_request = raid1_sync_request, .resize = raid1_resize, .size = raid1_size, .check_reshape = raid1_reshape, diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index ce959b4ae4df..1c1447dd3417 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1442,7 +1442,7 @@ retry_write: one_write_done(r10_bio); } -static void make_request(struct mddev *mddev, struct bio *bio) +static void raid10_make_request(struct mddev *mddev, struct bio *bio) { struct r10conf *conf = mddev->private; sector_t chunk_mask = (conf->geo.chunk_mask & conf->prev.chunk_mask); @@ -1484,7 +1484,7 @@ static void make_request(struct mddev *mddev, struct bio *bio) wake_up(&conf->wait_barrier); } -static void status(struct seq_file *seq, struct mddev *mddev) +static void raid10_status(struct seq_file *seq, struct mddev *mddev) { struct r10conf *conf = mddev->private; int i; @@ -1562,7 +1562,7 @@ static int enough(struct r10conf *conf, int ignore) _enough(conf, 1, ignore); } -static void error(struct mddev *mddev, struct md_rdev *rdev) +static void raid10_error(struct mddev *mddev, struct md_rdev *rdev) { char b[BDEVNAME_SIZE]; struct r10conf *conf = mddev->private; @@ -2802,7 +2802,7 @@ static int init_resync(struct r10conf *conf) * */ -static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, +static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, int *skipped) { struct r10conf *conf = mddev->private; @@ -3523,7 +3523,7 @@ static struct r10conf *setup_conf(struct mddev *mddev) return ERR_PTR(err); } -static int run(struct mddev *mddev) +static int raid10_run(struct mddev *mddev) { struct r10conf *conf; int i, disk_idx, chunk_size; @@ -4617,15 +4617,15 @@ static struct md_personality raid10_personality = .name = "raid10", .level = 10, .owner = THIS_MODULE, - .make_request = make_request, - .run = run, + .make_request = raid10_make_request, + .run = raid10_run, .free = raid10_free, - .status = status, - .error_handler = error, + .status = raid10_status, + .error_handler = raid10_error, .hot_add_disk = raid10_add_disk, .hot_remove_disk= raid10_remove_disk, .spare_active = raid10_spare_active, - .sync_request = sync_request, + .sync_request = raid10_sync_request, .quiesce = raid10_quiesce, .size = raid10_size, .resize = raid10_resize, diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index a086014dcd49..b4f02c9959f2 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2496,7 +2496,7 @@ static void raid5_build_block(struct stripe_head *sh, int i, int previous) dev->sector = raid5_compute_blocknr(sh, i, previous); } -static void error(struct mddev *mddev, struct md_rdev *rdev) +static void raid5_error(struct mddev *mddev, struct md_rdev *rdev) { char b[BDEVNAME_SIZE]; struct r5conf *conf = mddev->private; @@ -2958,7 +2958,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, * If several bio share a stripe. The bio bi_phys_segments acts as a * reference count to avoid race. The reference count should already be * increased before this function is called (for example, in - * make_request()), so other bio sharing this stripe will not free the + * raid5_make_request()), so other bio sharing this stripe will not free the * stripe. If a stripe is owned by one stripe, the stripe lock will * protect it. */ @@ -5135,7 +5135,7 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi) } } -static void make_request(struct mddev *mddev, struct bio * bi) +static void raid5_make_request(struct mddev *mddev, struct bio * bi) { struct r5conf *conf = mddev->private; int dd_idx; @@ -5225,7 +5225,7 @@ static void make_request(struct mddev *mddev, struct bio * bi) new_sector = raid5_compute_sector(conf, logical_sector, previous, &dd_idx, NULL); - pr_debug("raid456: make_request, sector %llu logical %llu\n", + pr_debug("raid456: raid5_make_request, sector %llu logical %llu\n", (unsigned long long)new_sector, (unsigned long long)logical_sector); @@ -5575,7 +5575,8 @@ ret: return retn; } -static inline sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipped) +static inline sector_t raid5_sync_request(struct mddev *mddev, sector_t sector_nr, + int *skipped) { struct r5conf *conf = mddev->private; struct stripe_head *sh; @@ -6674,7 +6675,7 @@ static int only_parity(int raid_disk, int algo, int raid_disks, int max_degraded return 0; } -static int run(struct mddev *mddev) +static int raid5_run(struct mddev *mddev) { struct r5conf *conf; int working_disks = 0; @@ -7048,7 +7049,7 @@ static void raid5_free(struct mddev *mddev, void *priv) mddev->to_remove = &raid5_attrs_group; } -static void status(struct seq_file *seq, struct mddev *mddev) +static void raid5_status(struct seq_file *seq, struct mddev *mddev) { struct r5conf *conf = mddev->private; int i; @@ -7864,15 +7865,15 @@ static struct md_personality raid6_personality = .name = "raid6", .level = 6, .owner = THIS_MODULE, - .make_request = make_request, - .run = run, + .make_request = raid5_make_request, + .run = raid5_run, .free = raid5_free, - .status = status, - .error_handler = error, + .status = raid5_status, + .error_handler = raid5_error, .hot_add_disk = raid5_add_disk, .hot_remove_disk= raid5_remove_disk, .spare_active = raid5_spare_active, - .sync_request = sync_request, + .sync_request = raid5_sync_request, .resize = raid5_resize, .size = raid5_size, .check_reshape = raid6_check_reshape, @@ -7887,15 +7888,15 @@ static struct md_personality raid5_personality = .name = "raid5", .level = 5, .owner = THIS_MODULE, - .make_request = make_request, - .run = run, + .make_request = raid5_make_request, + .run = raid5_run, .free = raid5_free, - .status = status, - .error_handler = error, + .status = raid5_status, + .error_handler = raid5_error, .hot_add_disk = raid5_add_disk, .hot_remove_disk= raid5_remove_disk, .spare_active = raid5_spare_active, - .sync_request = sync_request, + .sync_request = raid5_sync_request, .resize = raid5_resize, .size = raid5_size, .check_reshape = raid5_check_reshape, @@ -7911,15 +7912,15 @@ static struct md_personality raid4_personality = .name = "raid4", .level = 4, .owner = THIS_MODULE, - .make_request = make_request, - .run = run, + .make_request = raid5_make_request, + .run = raid5_run, .free = raid5_free, - .status = status, - .error_handler = error, + .status = raid5_status, + .error_handler = raid5_error, .hot_add_disk = raid5_add_disk, .hot_remove_disk= raid5_remove_disk, .spare_active = raid5_spare_active, - .sync_request = sync_request, + .sync_request = raid5_sync_request, .resize = raid5_resize, .size = raid5_size, .check_reshape = raid5_check_reshape, -- cgit v1.2.3 From fb7a6ae7554f15b5b0b7f31b02ed4ef40a8c2eb6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 15 Jan 2016 14:39:08 +0100 Subject: hisi_sas: SCSI_HISI_SAS should depend on HAS_DMA If NO_DMA=y: ERROR: "dma_map_sg" [drivers/scsi/hisi_sas/hisi_sas_v1_hw.ko] undefined! ERROR: "dma_pool_alloc" [drivers/scsi/hisi_sas/hisi_sas_v1_hw.ko] undefined! ERROR: "dma_unmap_sg" [drivers/scsi/hisi_sas/hisi_sas_v1_hw.ko] undefined! ERROR: "dma_unmap_sg" [drivers/scsi/hisi_sas/hisi_sas_main.ko] undefined! ERROR: "dma_set_mask" [drivers/scsi/hisi_sas/hisi_sas_main.ko] undefined! ERROR: "dma_map_sg" [drivers/scsi/hisi_sas/hisi_sas_main.ko] undefined! ERROR: "dma_pool_destroy" [drivers/scsi/hisi_sas/hisi_sas_main.ko] undefined! ERROR: "dma_free_coherent" [drivers/scsi/hisi_sas/hisi_sas_main.ko] undefined! ERROR: "dma_pool_free" [drivers/scsi/hisi_sas/hisi_sas_main.ko] undefined! ERROR: "dma_alloc_coherent" [drivers/scsi/hisi_sas/hisi_sas_main.ko] undefined! ERROR: "dma_pool_alloc" [drivers/scsi/hisi_sas/hisi_sas_main.ko] undefined! ERROR: "dma_supported" [drivers/scsi/hisi_sas/hisi_sas_main.ko] undefined! ERROR: "dma_pool_create" [drivers/scsi/hisi_sas/hisi_sas_main.ko] undefined! Add a dependency on HAS_DMA to fix this. Signed-off-by: Geert Uytterhoeven Reviewed-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/hisi_sas/Kconfig b/drivers/scsi/hisi_sas/Kconfig index 37a0c7156087..2c05021636a5 100644 --- a/drivers/scsi/hisi_sas/Kconfig +++ b/drivers/scsi/hisi_sas/Kconfig @@ -1,5 +1,6 @@ config SCSI_HISI_SAS tristate "HiSilicon SAS" + depends on HAS_DMA select SCSI_SAS_LIBSAS select BLK_DEV_INTEGRITY help -- cgit v1.2.3 From c142ce0d3c6b070c248cef4bbe3a0f58cfd61f3f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 15 Jan 2016 14:39:09 +0100 Subject: hisi_sas: Restrict SCSI_HISI_SAS to arm64 The HiSilicon SAS HBA is available in HiSilicon arm64 SoCs only. Restrict it to arm64, unless compile-testing. Signed-off-by: Geert Uytterhoeven Reviewed-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/hisi_sas/Kconfig b/drivers/scsi/hisi_sas/Kconfig index 2c05021636a5..b67661836c9f 100644 --- a/drivers/scsi/hisi_sas/Kconfig +++ b/drivers/scsi/hisi_sas/Kconfig @@ -1,6 +1,7 @@ config SCSI_HISI_SAS tristate "HiSilicon SAS" depends on HAS_DMA + depends on ARM64 || COMPILE_TEST select SCSI_SAS_LIBSAS select BLK_DEV_INTEGRITY help -- cgit v1.2.3 From d0eb20a863ba7dc1d3f4b841639671f134560be2 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Wed, 20 Jan 2016 11:01:23 -0500 Subject: sd: Optimal I/O size is in bytes, not sectors Commit ca369d51b3e1 ("block/sd: Fix device-imposed transfer length limits") accidentally switched optimal I/O size reporting from bytes to block layer sectors. Signed-off-by: Martin K. Petersen Reported-by: Christian Borntraeger Tested-by: Christian Borntraeger Fixes: ca369d51b3e1649be4a72addd6d6a168cfb3f537 Cc: stable@vger.kernel.org # 4.4+ Reviewed-by: James E.J. Bottomley Reviewed-by: Ewan D. Milne Reviewed-by: Matthew R. Ochs --- drivers/scsi/sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 4e08d1cd704d..ec163d08f6c3 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2893,7 +2893,7 @@ static int sd_revalidate_disk(struct gendisk *disk) sdkp->opt_xfer_blocks <= SD_DEF_XFER_BLOCKS && sdkp->opt_xfer_blocks * sdp->sector_size >= PAGE_CACHE_SIZE) rw_max = q->limits.io_opt = - logical_to_sectors(sdp, sdkp->opt_xfer_blocks); + sdkp->opt_xfer_blocks * sdp->sector_size; else rw_max = BLK_DEF_MAX_SECTORS; -- cgit v1.2.3 From e3c4abdb3bc9b76bedd416ecc5c27633a2f8afed Mon Sep 17 00:00:00 2001 From: Mark Yao Date: Wed, 23 Sep 2015 12:34:34 +0800 Subject: drm/rockchip: fix wrong pitch/size using on gem args->pitch and args->size may not be set by userspace, sometimes userspace only malloc args and not memset args to zero, then args->pitch and args->size is random, it is very danger to use pitch/size on gem. pitch's type is u32, and min_pitch's type is int, example, pitch is 0xffffffff, then pitch < min_pitch return true, then gem will alloc very very big bufffer, it would eat all the memory and cause kernel crash. Stop using pitch/size from args, calc them from other args. Signed-off-by: Mark Yao --- drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index d908321b94ce..18e07338c6e5 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -234,13 +234,8 @@ int rockchip_gem_dumb_create(struct drm_file *file_priv, /* * align to 64 bytes since Mali requires it. */ - min_pitch = ALIGN(min_pitch, 64); - - if (args->pitch < min_pitch) - args->pitch = min_pitch; - - if (args->size < args->pitch * args->height) - args->size = args->pitch * args->height; + args->pitch = ALIGN(min_pitch, 64); + args->size = args->pitch * args->height; rk_obj = rockchip_gem_create_with_handle(file_priv, dev, args->size, &args->handle); -- cgit v1.2.3 From 81e8f2e930fe76b9814c71b9d87c30760b5eb705 Mon Sep 17 00:00:00 2001 From: Manfred Rudigier Date: Wed, 20 Jan 2016 11:22:28 +0100 Subject: net: dp83640: Fix tx timestamp overflow handling. PHY status frames are not reliable, the PHY may not be able to send them during heavy receive traffic. This overflow condition is signaled by the PHY in the next status frame, but the driver did not make use of it. Instead it always reported wrong tx timestamps to user space after an overflow happened because it assigned newly received tx timestamps to old packets in the queue. This commit fixes this issue by clearing the tx timestamp queue every time an overflow happens, so that no timestamps are delivered for overflow packets. This way time stamping will continue correctly after an overflow. Signed-off-by: Manfred Rudigier Acked-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/phy/dp83640.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 180f69952779..7a240fce3a7e 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -846,6 +846,11 @@ static void decode_rxts(struct dp83640_private *dp83640, struct skb_shared_hwtstamps *shhwtstamps = NULL; struct sk_buff *skb; unsigned long flags; + u8 overflow; + + overflow = (phy_rxts->ns_hi >> 14) & 0x3; + if (overflow) + pr_debug("rx timestamp queue overflow, count %d\n", overflow); spin_lock_irqsave(&dp83640->rx_lock, flags); @@ -888,6 +893,7 @@ static void decode_txts(struct dp83640_private *dp83640, struct skb_shared_hwtstamps shhwtstamps; struct sk_buff *skb; u64 ns; + u8 overflow; /* We must already have the skb that triggered this. */ @@ -897,6 +903,17 @@ static void decode_txts(struct dp83640_private *dp83640, pr_debug("have timestamp but tx_queue empty\n"); return; } + + overflow = (phy_txts->ns_hi >> 14) & 0x3; + if (overflow) { + pr_debug("tx timestamp queue overflow, count %d\n", overflow); + while (skb) { + skb_complete_tx_timestamp(skb, NULL); + skb = skb_dequeue(&dp83640->tx_queue); + } + return; + } + ns = phy2txts(phy_txts); memset(&shhwtstamps, 0, sizeof(shhwtstamps)); shhwtstamps.hwtstamp = ns_to_ktime(ns); -- cgit v1.2.3 From 26827088392196d0e8464dae599bd5ff9992cb82 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Tue, 19 Jan 2016 19:02:53 +0000 Subject: drm/i915: simplify allocation of driver-internal requests There are a number of places where the driver needs a request, but isn't working on behalf of any specific user or in a specific context. At present, we associate them with the per-engine default context. A future patch will abolish those per-engine context pointers; but we can already eliminate a lot of the references to them, just by making the allocator allow NULL as a shorthand for "an appropriate context for this ring", which will mean that the callers don't need to know anything about how the "appropriate context" is found (e.g. per-ring vs per-device, etc). So this patch renames the existing i915_gem_request_alloc(), and makes it local (static inline), and replaces it with a wrapper that provides a default if the context is NULL, and also has a nicer calling convention (doesn't require a pointer to an output parameter). Then we change all callers to use the new convention: OLD: err = i915_gem_request_alloc(ring, user_ctx, &req); if (err) ... NEW: req = i915_gem_request_alloc(ring, user_ctx); if (IS_ERR(req)) ... OLD: err = i915_gem_request_alloc(ring, ring->default_context, &req); if (err) ... NEW: req = i915_gem_request_alloc(ring, NULL); if (IS_ERR(req)) ... v4: Rebased Signed-off-by: Dave Gordon Reviewed-by: Nick Hoath Link: http://patchwork.freedesktop.org/patch/msgid/1453230175-19330-2-git-send-email-david.s.gordon@intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 6 ++-- drivers/gpu/drm/i915/i915_gem.c | 55 +++++++++++++++++++++++------- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 14 +++++--- drivers/gpu/drm/i915/intel_display.c | 6 ++-- drivers/gpu/drm/i915/intel_lrc.c | 9 +++-- drivers/gpu/drm/i915/intel_overlay.c | 24 ++++++------- 6 files changed, 74 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d3b98c228683..125659488756 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2268,9 +2268,9 @@ struct drm_i915_gem_request { }; -int i915_gem_request_alloc(struct intel_engine_cs *ring, - struct intel_context *ctx, - struct drm_i915_gem_request **req_out); +struct drm_i915_gem_request * __must_check +i915_gem_request_alloc(struct intel_engine_cs *engine, + struct intel_context *ctx); void i915_gem_request_cancel(struct drm_i915_gem_request *req); void i915_gem_request_free(struct kref *req_ref); int i915_gem_request_add_to_client(struct drm_i915_gem_request *req, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6b0102da859c..8e716b6b5d59 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2690,9 +2690,10 @@ void i915_gem_request_free(struct kref *req_ref) kmem_cache_free(req->i915->requests, req); } -int i915_gem_request_alloc(struct intel_engine_cs *ring, - struct intel_context *ctx, - struct drm_i915_gem_request **req_out) +static inline int +__i915_gem_request_alloc(struct intel_engine_cs *ring, + struct intel_context *ctx, + struct drm_i915_gem_request **req_out) { struct drm_i915_private *dev_priv = to_i915(ring->dev); struct drm_i915_gem_request *req; @@ -2755,6 +2756,31 @@ err: return ret; } +/** + * i915_gem_request_alloc - allocate a request structure + * + * @engine: engine that we wish to issue the request on. + * @ctx: context that the request will be associated with. + * This can be NULL if the request is not directly related to + * any specific user context, in which case this function will + * choose an appropriate context to use. + * + * Returns a pointer to the allocated request if successful, + * or an error code if not. + */ +struct drm_i915_gem_request * +i915_gem_request_alloc(struct intel_engine_cs *engine, + struct intel_context *ctx) +{ + struct drm_i915_gem_request *req; + int err; + + if (ctx == NULL) + ctx = engine->default_context; + err = __i915_gem_request_alloc(engine, ctx, &req); + return err ? ERR_PTR(err) : req; +} + void i915_gem_request_cancel(struct drm_i915_gem_request *req) { intel_ring_reserved_space_cancel(req->ringbuf); @@ -3172,9 +3198,13 @@ __i915_gem_object_sync(struct drm_i915_gem_object *obj, return 0; if (*to_req == NULL) { - ret = i915_gem_request_alloc(to, to->default_context, to_req); - if (ret) - return ret; + struct drm_i915_gem_request *req; + + req = i915_gem_request_alloc(to, NULL); + if (IS_ERR(req)) + return PTR_ERR(req); + + *to_req = req; } trace_i915_gem_ring_sync_to(*to_req, from, from_req); @@ -3374,9 +3404,9 @@ int i915_gpu_idle(struct drm_device *dev) if (!i915.enable_execlists) { struct drm_i915_gem_request *req; - ret = i915_gem_request_alloc(ring, ring->default_context, &req); - if (ret) - return ret; + req = i915_gem_request_alloc(ring, NULL); + if (IS_ERR(req)) + return PTR_ERR(req); ret = i915_switch_context(req); if (ret) { @@ -4871,10 +4901,9 @@ i915_gem_init_hw(struct drm_device *dev) for_each_ring(ring, dev_priv, i) { struct drm_i915_gem_request *req; - WARN_ON(!ring->default_context); - - ret = i915_gem_request_alloc(ring, ring->default_context, &req); - if (ret) { + req = i915_gem_request_alloc(ring, NULL); + if (IS_ERR(req)) { + ret = PTR_ERR(req); i915_gem_cleanup_ringbuffer(dev); goto out; } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 4edf1c062210..dc32018ee2e9 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1381,6 +1381,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, struct drm_i915_gem_exec_object2 *exec) { struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_request *req = NULL; struct eb_vmas *eb; struct drm_i915_gem_object *batch_obj; struct drm_i915_gem_exec_object2 shadow_exec_entry; @@ -1602,11 +1603,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, params->batch_obj_vm_offset = i915_gem_obj_offset(batch_obj, vm); /* Allocate a request for this batch buffer nice and early. */ - ret = i915_gem_request_alloc(ring, ctx, ¶ms->request); - if (ret) + req = i915_gem_request_alloc(ring, ctx); + if (IS_ERR(req)) { + ret = PTR_ERR(req); goto err_batch_unpin; + } - ret = i915_gem_request_add_to_client(params->request, file); + ret = i915_gem_request_add_to_client(req, file); if (ret) goto err_batch_unpin; @@ -1622,6 +1625,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, params->dispatch_flags = dispatch_flags; params->batch_obj = batch_obj; params->ctx = ctx; + params->request = req; ret = dev_priv->gt.execbuf_submit(params, args, &eb->vmas); @@ -1645,8 +1649,8 @@ err: * must be freed again. If it was submitted then it is being tracked * on the active request list and no clean up is required here. */ - if (ret && params->request) - i915_gem_request_cancel(params->request); + if (ret && req) + i915_gem_request_cancel(req); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 06ab6df8ad48..8104511ad302 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11690,9 +11690,11 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, obj->last_write_req); } else { if (!request) { - ret = i915_gem_request_alloc(ring, ring->default_context, &request); - if (ret) + request = i915_gem_request_alloc(ring, NULL); + if (IS_ERR(request)) { + ret = PTR_ERR(request); goto cleanup_unpin; + } } ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, request, diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index faaf49077fea..ec2482daffa6 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -2520,11 +2520,10 @@ int intel_lr_context_deferred_alloc(struct intel_context *ctx, if (ctx != ring->default_context && ring->init_context) { struct drm_i915_gem_request *req; - ret = i915_gem_request_alloc(ring, - ctx, &req); - if (ret) { - DRM_ERROR("ring create req: %d\n", - ret); + req = i915_gem_request_alloc(ring, ctx); + if (IS_ERR(req)) { + ret = PTR_ERR(req); + DRM_ERROR("ring create req: %d\n", ret); goto error_ringbuf; } diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 76f1980a7541..9168413fe204 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -240,9 +240,9 @@ static int intel_overlay_on(struct intel_overlay *overlay) WARN_ON(overlay->active); WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE)); - ret = i915_gem_request_alloc(ring, ring->default_context, &req); - if (ret) - return ret; + req = i915_gem_request_alloc(ring, NULL); + if (IS_ERR(req)) + return PTR_ERR(req); ret = intel_ring_begin(req, 4); if (ret) { @@ -283,9 +283,9 @@ static int intel_overlay_continue(struct intel_overlay *overlay, if (tmp & (1 << 17)) DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp); - ret = i915_gem_request_alloc(ring, ring->default_context, &req); - if (ret) - return ret; + req = i915_gem_request_alloc(ring, NULL); + if (IS_ERR(req)) + return PTR_ERR(req); ret = intel_ring_begin(req, 2); if (ret) { @@ -349,9 +349,9 @@ static int intel_overlay_off(struct intel_overlay *overlay) * of the hw. Do it in both cases */ flip_addr |= OFC_UPDATE; - ret = i915_gem_request_alloc(ring, ring->default_context, &req); - if (ret) - return ret; + req = i915_gem_request_alloc(ring, NULL); + if (IS_ERR(req)) + return PTR_ERR(req); ret = intel_ring_begin(req, 6); if (ret) { @@ -423,9 +423,9 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay) /* synchronous slowpath */ struct drm_i915_gem_request *req; - ret = i915_gem_request_alloc(ring, ring->default_context, &req); - if (ret) - return ret; + req = i915_gem_request_alloc(ring, NULL); + if (IS_ERR(req)) + return PTR_ERR(req); ret = intel_ring_begin(req, 2); if (ret) { -- cgit v1.2.3 From ed54c1a1d11cbc09a3cc14f8fc1a0fb129efb64d Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Tue, 19 Jan 2016 19:02:54 +0000 Subject: drm/i915: abolish separate per-ring default_context pointers Now that we've eliminated a lot of uses of ring->default_context, we can eliminate the pointer itself. All the engines share the same default intel_context, so we can just keep a single reference to it in the dev_priv structure rather than one in each of the engine[] elements. This make refcounting more sensible too, as we now have a refcount of one for the one pointer, rather than a refcount of one but multiple pointers. From an idea by Chris Wilson. v2: transform an extra instance of ring->default_context introduced by 42f1cae8c drm/i915: Restore inhibiting the load of the default context That patch's commentary includes: v2: Mark the global default context as uninitialized on GPU reset so that the context-local workarounds are reloaded upon re-enabling The code implementing that now also benefits from the replacement of the multiple (per-ring) pointers to the default context with a single pointer to the unique kernel context. v4: Rebased, remove underused local (Nick Hoath) Signed-off-by: Dave Gordon Reviewed-by: Nick Hoath Cc: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1453230175-19330-3-git-send-email-david.s.gordon@intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 4 ++-- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_gem.c | 6 +++--- drivers/gpu/drm/i915/i915_gem_context.c | 29 +++++++++++------------------ drivers/gpu/drm/i915/i915_gpu_error.c | 2 +- drivers/gpu/drm/i915/i915_guc_submission.c | 6 +++--- drivers/gpu/drm/i915/intel_lrc.c | 17 +++++++++-------- drivers/gpu/drm/i915/intel_ringbuffer.h | 1 - 8 files changed, 31 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 0b3550f05026..37c2c5009d9a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1961,7 +1961,7 @@ static int i915_context_status(struct seq_file *m, void *unused) seq_puts(m, "HW context "); describe_ctx(m, ctx); for_each_ring(ring, dev_priv, i) { - if (ring->default_context == ctx) + if (dev_priv->kernel_context == ctx) seq_printf(m, "(default context %s) ", ring->name); } @@ -2058,7 +2058,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) list_for_each_entry(ctx, &dev_priv->context_list, link) { for_each_ring(ring, dev_priv, i) { - if (ring->default_context != ctx) + if (dev_priv->kernel_context != ctx) i915_dump_lrc_obj(m, ctx, ring); } } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 125659488756..840368de3f4f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1948,6 +1948,8 @@ struct drm_i915_private { void (*stop_ring)(struct intel_engine_cs *ring); } gt; + struct intel_context *kernel_context; + bool edp_low_vswing; /* perform PHY state sanity checks? */ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8e716b6b5d59..06abe1bf5afc 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2680,7 +2680,7 @@ void i915_gem_request_free(struct kref *req_ref) if (ctx) { if (i915.enable_execlists) { - if (ctx != req->ring->default_context) + if (ctx != req->i915->kernel_context) intel_lr_context_unpin(req); } @@ -2776,7 +2776,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, int err; if (ctx == NULL) - ctx = engine->default_context; + ctx = to_i915(engine->dev)->kernel_context; err = __i915_gem_request_alloc(engine, ctx, &req); return err ? ERR_PTR(err) : req; } @@ -4864,7 +4864,7 @@ i915_gem_init_hw(struct drm_device *dev) */ init_unused_rings(dev); - BUG_ON(!dev_priv->ring[RCS].default_context); + BUG_ON(!dev_priv->kernel_context); ret = i915_ppgtt_init_hw(dev); if (ret) { diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index c25083c78ba7..6a4f64b03db6 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -347,22 +347,20 @@ void i915_gem_context_reset(struct drm_device *dev) i915_gem_context_unreference(lctx); ring->last_context = NULL; } - - /* Force the GPU state to be reinitialised on enabling */ - if (ring->default_context) - ring->default_context->legacy_hw_ctx.initialized = false; } + + /* Force the GPU state to be reinitialised on enabling */ + dev_priv->kernel_context->legacy_hw_ctx.initialized = false; } int i915_gem_context_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_context *ctx; - int i; /* Init should only be called once per module load. Eventually the * restriction on the context_disabled check can be loosened. */ - if (WARN_ON(dev_priv->ring[RCS].default_context)) + if (WARN_ON(dev_priv->kernel_context)) return 0; if (intel_vgpu_active(dev) && HAS_LOGICAL_RING_CONTEXTS(dev)) { @@ -392,12 +390,7 @@ int i915_gem_context_init(struct drm_device *dev) return PTR_ERR(ctx); } - for (i = 0; i < I915_NUM_RINGS; i++) { - struct intel_engine_cs *ring = &dev_priv->ring[i]; - - /* NB: RCS will hold a ref for all rings */ - ring->default_context = ctx; - } + dev_priv->kernel_context = ctx; DRM_DEBUG_DRIVER("%s context support initialized\n", i915.enable_execlists ? "LR" : @@ -408,7 +401,7 @@ int i915_gem_context_init(struct drm_device *dev) void i915_gem_context_fini(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_context *dctx = dev_priv->ring[RCS].default_context; + struct intel_context *dctx = dev_priv->kernel_context; int i; if (dctx->legacy_hw_ctx.rcs_state) { @@ -435,17 +428,17 @@ void i915_gem_context_fini(struct drm_device *dev) i915_gem_object_ggtt_unpin(dctx->legacy_hw_ctx.rcs_state); } - for (i = 0; i < I915_NUM_RINGS; i++) { + for (i = I915_NUM_RINGS; --i >= 0;) { struct intel_engine_cs *ring = &dev_priv->ring[i]; - if (ring->last_context) + if (ring->last_context) { i915_gem_context_unreference(ring->last_context); - - ring->default_context = NULL; - ring->last_context = NULL; + ring->last_context = NULL; + } } i915_gem_context_unreference(dctx); + dev_priv->kernel_context = NULL; } int i915_gem_context_enable(struct drm_i915_gem_request *req) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 06ca4082735b..7eeb24427785 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1050,7 +1050,7 @@ static void i915_gem_record_rings(struct drm_device *dev, if (request) rbuf = request->ctx->engine[ring->id].ringbuf; else - rbuf = ring->default_context->engine[ring->id].ringbuf; + rbuf = dev_priv->kernel_context->engine[ring->id].ringbuf; } else rbuf = ring->buffer; diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 9c244247c13e..51ae5c1f806d 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -964,7 +964,7 @@ int i915_guc_submission_enable(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_guc *guc = &dev_priv->guc; - struct intel_context *ctx = dev_priv->ring[RCS].default_context; + struct intel_context *ctx = dev_priv->kernel_context; struct i915_guc_client *client; /* client for execbuf submission */ @@ -1021,7 +1021,7 @@ int intel_guc_suspend(struct drm_device *dev) if (!i915.enable_guc_submission) return 0; - ctx = dev_priv->ring[RCS].default_context; + ctx = dev_priv->kernel_context; data[0] = HOST2GUC_ACTION_ENTER_S_STATE; /* any value greater than GUC_POWER_D0 */ @@ -1047,7 +1047,7 @@ int intel_guc_resume(struct drm_device *dev) if (!i915.enable_guc_submission) return 0; - ctx = dev_priv->ring[RCS].default_context; + ctx = dev_priv->kernel_context; data[0] = HOST2GUC_ACTION_EXIT_S_STATE; data[1] = GUC_POWER_D0; diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index ec2482daffa6..2c6da4013b1a 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -598,7 +598,7 @@ static int execlists_context_queue(struct drm_i915_gem_request *request) struct drm_i915_gem_request *cursor; int num_elements = 0; - if (request->ctx != ring->default_context) + if (request->ctx != request->i915->kernel_context) intel_lr_context_pin(request); i915_gem_request_reference(request); @@ -690,7 +690,7 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request request->ringbuf = request->ctx->engine[request->ring->id].ringbuf; - if (request->ctx != request->ring->default_context) { + if (request->ctx != request->i915->kernel_context) { ret = intel_lr_context_pin(request); if (ret) return ret; @@ -1006,7 +1006,7 @@ void intel_execlists_retire_requests(struct intel_engine_cs *ring) struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state; - if (ctx_obj && (ctx != ring->default_context)) + if (ctx_obj && (ctx != req->i915->kernel_context)) intel_lr_context_unpin(req); list_del(&req->execlist_link); i915_gem_request_unreference(req); @@ -1529,7 +1529,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring) u8 next_context_status_buffer_hw; lrc_setup_hardware_status_page(ring, - ring->default_context->engine[ring->id].state); + dev_priv->kernel_context->engine[ring->id].state); I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask)); I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff); @@ -2005,6 +2005,7 @@ logical_ring_default_irqs(struct intel_engine_cs *ring, unsigned shift) static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *ring) { + struct intel_context *dctx = to_i915(dev)->kernel_context; int ret; /* Intentionally left blank. */ @@ -2027,12 +2028,12 @@ logical_ring_init(struct drm_device *dev, struct intel_engine_cs *ring) if (ret) goto error; - ret = intel_lr_context_deferred_alloc(ring->default_context, ring); + ret = intel_lr_context_deferred_alloc(dctx, ring); if (ret) goto error; /* As this is the default context, always pin it */ - ret = intel_lr_context_do_pin(ring, ring->default_context); + ret = intel_lr_context_do_pin(ring, dctx); if (ret) { DRM_ERROR( "Failed to pin and map ringbuffer %s: %d\n", @@ -2398,7 +2399,7 @@ void intel_lr_context_free(struct intel_context *ctx) ctx->engine[i].ringbuf; struct intel_engine_cs *ring = ringbuf->ring; - if (ctx == ring->default_context) { + if (ctx == ctx->i915->kernel_context) { intel_unpin_ringbuffer_obj(ringbuf); i915_gem_object_ggtt_unpin(ctx_obj); } @@ -2517,7 +2518,7 @@ int intel_lr_context_deferred_alloc(struct intel_context *ctx, ctx->engine[ring->id].ringbuf = ringbuf; ctx->engine[ring->id].state = ctx_obj; - if (ctx != ring->default_context && ring->init_context) { + if (ctx != ctx->i915->kernel_context && ring->init_context) { struct drm_i915_gem_request *req; req = i915_gem_request_alloc(ring, ctx); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 91ac8a9bd903..0014fcaa5a0c 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -309,7 +309,6 @@ struct intel_engine_cs { wait_queue_head_t irq_queue; - struct intel_context *default_context; struct intel_context *last_context; struct intel_ring_hangcheck hangcheck; -- cgit v1.2.3 From e28e404c3e93378c6ef3e2e6c9c5b1ab51e54bc4 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Tue, 19 Jan 2016 19:02:55 +0000 Subject: drm/i915: tidy up a few leftovers There are a few bits of code which the transformations implemented by the previous patch reveal to be suboptimal, once the notion of a per- ring default context has gone away. So this tidies up the leftovers. It could have been squashed into the previous patch, but that would have made that patch less clearly a simple transformation. In particular, any change which alters the code block structure or indentation has been deferred into this separate patch, because such things tend to make diffs more difficult to read. v4: Rebased Signed-off-by: Dave Gordon Reviewed-by: Nick Hoath Link: http://patchwork.freedesktop.org/patch/msgid/1453230175-19330-4-git-send-email-david.s.gordon@intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 15 +++++---------- drivers/gpu/drm/i915/i915_gem.c | 6 ++---- drivers/gpu/drm/i915/intel_lrc.c | 38 +++++++++++++++++-------------------- 3 files changed, 24 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 37c2c5009d9a..c5db23511184 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1960,11 +1960,8 @@ static int i915_context_status(struct seq_file *m, void *unused) seq_puts(m, "HW context "); describe_ctx(m, ctx); - for_each_ring(ring, dev_priv, i) { - if (dev_priv->kernel_context == ctx) - seq_printf(m, "(default context %s) ", - ring->name); - } + if (ctx == dev_priv->kernel_context) + seq_printf(m, "(kernel context) "); if (i915.enable_execlists) { seq_putc(m, '\n'); @@ -2056,12 +2053,10 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) if (ret) return ret; - list_for_each_entry(ctx, &dev_priv->context_list, link) { - for_each_ring(ring, dev_priv, i) { - if (dev_priv->kernel_context != ctx) + list_for_each_entry(ctx, &dev_priv->context_list, link) + if (ctx != dev_priv->kernel_context) + for_each_ring(ring, dev_priv, i) i915_dump_lrc_obj(m, ctx, ring); - } - } mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 06abe1bf5afc..6a3e4ee7f7e2 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2679,10 +2679,8 @@ void i915_gem_request_free(struct kref *req_ref) i915_gem_request_remove_from_client(req); if (ctx) { - if (i915.enable_execlists) { - if (ctx != req->i915->kernel_context) - intel_lr_context_unpin(req); - } + if (i915.enable_execlists && ctx != req->i915->kernel_context) + intel_lr_context_unpin(req); i915_gem_context_unreference(ctx); } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 2c6da4013b1a..134379dc4dd9 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -686,16 +686,10 @@ static int execlists_move_to_gpu(struct drm_i915_gem_request *req, int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request) { - int ret; + int ret = 0; request->ringbuf = request->ctx->engine[request->ring->id].ringbuf; - if (request->ctx != request->i915->kernel_context) { - ret = intel_lr_context_pin(request); - if (ret) - return ret; - } - if (i915.enable_guc_submission) { /* * Check that the GuC has space for the request before @@ -709,7 +703,10 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request return ret; } - return 0; + if (request->ctx != request->i915->kernel_context) + ret = intel_lr_context_pin(request); + + return ret; } static int logical_ring_wait_for_space(struct drm_i915_gem_request *req, @@ -2391,22 +2388,21 @@ void intel_lr_context_free(struct intel_context *ctx) { int i; - for (i = 0; i < I915_NUM_RINGS; i++) { + for (i = I915_NUM_RINGS; --i >= 0; ) { + struct intel_ringbuffer *ringbuf = ctx->engine[i].ringbuf; struct drm_i915_gem_object *ctx_obj = ctx->engine[i].state; - if (ctx_obj) { - struct intel_ringbuffer *ringbuf = - ctx->engine[i].ringbuf; - struct intel_engine_cs *ring = ringbuf->ring; + if (!ctx_obj) + continue; - if (ctx == ctx->i915->kernel_context) { - intel_unpin_ringbuffer_obj(ringbuf); - i915_gem_object_ggtt_unpin(ctx_obj); - } - WARN_ON(ctx->engine[ring->id].pin_count); - intel_ringbuffer_free(ringbuf); - drm_gem_object_unreference(&ctx_obj->base); + if (ctx == ctx->i915->kernel_context) { + intel_unpin_ringbuffer_obj(ringbuf); + i915_gem_object_ggtt_unpin(ctx_obj); } + + WARN_ON(ctx->engine[i].pin_count); + intel_ringbuffer_free(ringbuf); + drm_gem_object_unreference(&ctx_obj->base); } } @@ -2481,7 +2477,7 @@ static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring, */ int intel_lr_context_deferred_alloc(struct intel_context *ctx, - struct intel_engine_cs *ring) + struct intel_engine_cs *ring) { struct drm_device *dev = ring->dev; struct drm_i915_gem_object *ctx_obj; -- cgit v1.2.3 From 6fa283b07e708913aa5fb38a3a20ba7adc05ba56 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 19 Jan 2016 21:00:56 +0100 Subject: drm/i915: Tune down "GT register while GT waking disabled" message We've had this since forever, and's randomly reporting issues and as such causing piles&piles of CI noise. Mika is working on proper debug infrastructure for this, and on fixing this properly. Meanwhile make CI more useful for everyone else. Cc: Mika Kuoppala Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93121 Signed-off-by: Daniel Vetter Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1453233656-12955-1-git-send-email-daniel.vetter@ffwll.ch --- drivers/gpu/drm/i915/i915_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 975af3568521..706b8eabfaf4 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1356,7 +1356,7 @@ static void vlv_check_no_gt_access(struct drm_i915_private *dev_priv) if (!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEERR)) return; - DRM_ERROR("GT register access while GT waking disabled\n"); + DRM_DEBUG_DRIVER("GT register access while GT waking disabled\n"); I915_WRITE(VLV_GTLC_PW_STATUS, VLV_GTLC_ALLOWWAKEERR); } -- cgit v1.2.3 From c81eeea6c14b212016104f4256c65f93ad230a86 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Wed, 20 Jan 2016 12:32:23 +0200 Subject: drm/i915: Limit the auto arming of mmio debugs on vlv/chv The capability to detect unclaimed register access was recently introduced for vlv/chv platforms. Apparently there are plenty of unclaimed access on these platforms, resulting in new dmesg warns. But as we are trying to form a beachhead for CI/Bat, all new warns are adding to the noise and thus not desirable at this point in time. Make it so that if in these platforms the automatic arming was responsible for mmio_debug enabling, ignore the warns. If user/dev wants to fix these, he can still do so by i915.mmio_debug=1234. Cc: Daniel Vetter Signed-off-by: Mika Kuoppala Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453285943-24614-1-git-send-email-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/intel_uncore.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index c3c13dc929cb..bfa79e5c214e 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -631,6 +631,15 @@ __unclaimed_reg_debug(struct drm_i915_private *dev_priv, const bool read, const bool before) { + /* XXX. We limit the auto arming traces for mmio + * debugs on these platforms. There are just too many + * revealed by these and CI/Bat suffers from the noise. + * Please fix and then re-enable the automatic traces. + */ + if (i915.mmio_debug < 2 && + (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))) + return; + if (WARN(check_for_unclaimed_mmio(dev_priv), "Unclaimed register detected %s %s register 0x%x\n", before ? "before" : "after", -- cgit v1.2.3 From 7c17d377374ddbcfb7873366559fc4ed8b296e11 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 20 Jan 2016 15:43:35 +0200 Subject: drm/i915: Use ordered seqno write interrupt generation on gen8+ execlists Broadwell and later currently use the same unordered command sequence to update the seqno in the HWS status page and then assert the user interrupt. We should apply the w/a from legacy (where we do an mmio read to delay the seqno read after the interrupt), but this is not enough to enforce coherent seqno visibilty on Skylake. Rather than search for the proper post-interrupt seqno barrier, use a strongly ordered command sequence to write the seqno, then assert the user interrupt from the ring. v2: Move around the wa tail dwords to avoid adding duplicate code. v3: Add references, comments on workarounds and bit5 check. References: https://bugs.freedesktop.org/show_bug.cgi?id=93693 Testcase: igt/gem_ring_sync_loop #skl Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1453297415-17793-1-git-send-email-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/intel_lrc.c | 89 ++++++++++++++++++++++----------- drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 2 files changed, 62 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 134379dc4dd9..7f47948d5c40 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -760,23 +760,34 @@ static int logical_ring_wait_for_space(struct drm_i915_gem_request *req, * on a queue waiting for the ELSP to be ready to accept a new context submission. At that * point, the tail *inside* the context is updated and the ELSP written to. */ -static void +static int intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request) { - struct intel_engine_cs *ring = request->ring; + struct intel_ringbuffer *ringbuf = request->ringbuf; struct drm_i915_private *dev_priv = request->i915; - intel_logical_ring_advance(request->ringbuf); + intel_logical_ring_advance(ringbuf); + request->tail = ringbuf->tail; - request->tail = request->ringbuf->tail; + /* + * Here we add two extra NOOPs as padding to avoid + * lite restore of a context with HEAD==TAIL. + * + * Caller must reserve WA_TAIL_DWORDS for us! + */ + intel_logical_ring_emit(ringbuf, MI_NOOP); + intel_logical_ring_emit(ringbuf, MI_NOOP); + intel_logical_ring_advance(ringbuf); - if (intel_ring_stopped(ring)) - return; + if (intel_ring_stopped(request->ring)) + return 0; if (dev_priv->guc.execbuf_client) i915_guc_submit(dev_priv->guc.execbuf_client, request); else execlists_context_queue(request); + + return 0; } static void __wrap_ring_buffer(struct intel_ringbuffer *ringbuf) @@ -1845,44 +1856,65 @@ static void bxt_a_set_seqno(struct intel_engine_cs *ring, u32 seqno) intel_flush_status_page(ring, I915_GEM_HWS_INDEX); } +/* + * Reserve space for 2 NOOPs at the end of each request to be + * used as a workaround for not being allowed to do lite + * restore with HEAD==TAIL (WaIdleLiteRestore). + */ +#define WA_TAIL_DWORDS 2 + +static inline u32 hws_seqno_address(struct intel_engine_cs *engine) +{ + return engine->status_page.gfx_addr + I915_GEM_HWS_INDEX_ADDR; +} + static int gen8_emit_request(struct drm_i915_gem_request *request) { struct intel_ringbuffer *ringbuf = request->ringbuf; - struct intel_engine_cs *ring = ringbuf->ring; - u32 cmd; int ret; - /* - * Reserve space for 2 NOOPs at the end of each request to be - * used as a workaround for not being allowed to do lite - * restore with HEAD==TAIL (WaIdleLiteRestore). - */ - ret = intel_logical_ring_begin(request, 8); + ret = intel_logical_ring_begin(request, 6 + WA_TAIL_DWORDS); if (ret) return ret; - cmd = MI_STORE_DWORD_IMM_GEN4; - cmd |= MI_GLOBAL_GTT; + /* w/a: bit 5 needs to be zero for MI_FLUSH_DW address. */ + BUILD_BUG_ON(I915_GEM_HWS_INDEX_ADDR & (1 << 5)); - intel_logical_ring_emit(ringbuf, cmd); intel_logical_ring_emit(ringbuf, - (ring->status_page.gfx_addr + - (I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT))); + (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW); + intel_logical_ring_emit(ringbuf, + hws_seqno_address(request->ring) | + MI_FLUSH_DW_USE_GTT); intel_logical_ring_emit(ringbuf, 0); intel_logical_ring_emit(ringbuf, i915_gem_request_get_seqno(request)); intel_logical_ring_emit(ringbuf, MI_USER_INTERRUPT); intel_logical_ring_emit(ringbuf, MI_NOOP); - intel_logical_ring_advance_and_submit(request); + return intel_logical_ring_advance_and_submit(request); +} - /* - * Here we add two extra NOOPs as padding to avoid - * lite restore of a context with HEAD==TAIL. - */ - intel_logical_ring_emit(ringbuf, MI_NOOP); - intel_logical_ring_emit(ringbuf, MI_NOOP); - intel_logical_ring_advance(ringbuf); +static int gen8_emit_request_render(struct drm_i915_gem_request *request) +{ + struct intel_ringbuffer *ringbuf = request->ringbuf; + int ret; - return 0; + ret = intel_logical_ring_begin(request, 6 + WA_TAIL_DWORDS); + if (ret) + return ret; + + /* w/a for post sync ops following a GPGPU operation we + * need a prior CS_STALL, which is emitted by the flush + * following the batch. + */ + intel_logical_ring_emit(ringbuf, GFX_OP_PIPE_CONTROL(5)); + intel_logical_ring_emit(ringbuf, + (PIPE_CONTROL_GLOBAL_GTT_IVB | + PIPE_CONTROL_CS_STALL | + PIPE_CONTROL_QW_WRITE)); + intel_logical_ring_emit(ringbuf, hws_seqno_address(request->ring)); + intel_logical_ring_emit(ringbuf, 0); + intel_logical_ring_emit(ringbuf, i915_gem_request_get_seqno(request)); + intel_logical_ring_emit(ringbuf, MI_USER_INTERRUPT); + return intel_logical_ring_advance_and_submit(request); } static int intel_lr_context_render_state_init(struct drm_i915_gem_request *req) @@ -2069,6 +2101,7 @@ static int logical_render_ring_init(struct drm_device *dev) ring->init_context = gen8_init_rcs_context; ring->cleanup = intel_fini_pipe_control; ring->emit_flush = gen8_emit_flush_render; + ring->emit_request = gen8_emit_request_render; ring->dev = dev; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 0014fcaa5a0c..b6c7cd2b8a40 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -426,6 +426,7 @@ intel_write_status_page(struct intel_engine_cs *ring, * The area from dword 0x30 to 0x3ff is available for driver usage. */ #define I915_GEM_HWS_INDEX 0x30 +#define I915_GEM_HWS_INDEX_ADDR (I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT) #define I915_GEM_HWS_SCRATCH_INDEX 0x40 #define I915_GEM_HWS_SCRATCH_ADDR (I915_GEM_HWS_SCRATCH_INDEX << MI_STORE_DWORD_INDEX_SHIFT) -- cgit v1.2.3 From de1add360522c876c25ef2bbbbab1c94bdb509ab Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 15 Jan 2016 15:12:50 +0000 Subject: drm/i915: Decouple execbuf uAPI from internal implementation At the moment execbuf ring selection is fully coupled to internal ring ids which is not a good thing on its own. This dependency is also spread between two source files and not spelled out at either side which makes it hidden and fragile. This patch decouples this dependency by introducing an explicit translation table of execbuf uAPI to ring id close to the only call site (i915_gem_do_execbuffer). This way we are free to change driver internal implementation details without breaking userspace. All state relating to the uAPI is now contained in, or next to, i915_gem_do_execbuffer. As a side benefit, this patch decreases the compiled size of i915_gem_do_execbuffer. v2: Extract ring selection into eb_select_ring. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Cc: Daniel Vetter Cc: Chris Wilson Reviewed-by: Chris Wilson Acked-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1452870770-13981-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.h | 4 +- drivers/gpu/drm/i915/i915_gem.c | 2 + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 139 +++++++++++++++-------------- drivers/gpu/drm/i915/intel_ringbuffer.h | 10 +-- 4 files changed, 81 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 840368de3f4f..204661f9873d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -334,7 +334,7 @@ struct drm_i915_file_private { unsigned boosts; } rps; - struct intel_engine_cs *bsd_ring; + unsigned int bsd_ring; }; enum intel_dpll_id { @@ -1299,7 +1299,7 @@ struct i915_gem_mm { bool busy; /* the indicator for dispatch video commands on two BSD rings */ - int bsd_ring_dispatch_index; + unsigned int bsd_ring_dispatch_index; /** Bit 6 swizzling required for X tiling */ uint32_t bit_6_swizzle_x; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6a3e4ee7f7e2..0ed731ed6976 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5141,6 +5141,8 @@ int i915_gem_open(struct drm_device *dev, struct drm_file *file) spin_lock_init(&file_priv->mm.lock); INIT_LIST_HEAD(&file_priv->mm.request_list); + file_priv->bsd_ring = -1; + ret = i915_gem_context_open(dev, file); if (ret) kfree(file_priv); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index dc32018ee2e9..2dc08ce1079a 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1325,33 +1325,23 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params, /** * Find one BSD ring to dispatch the corresponding BSD command. - * The Ring ID is returned. + * The ring index is returned. */ -static int gen8_dispatch_bsd_ring(struct drm_device *dev, - struct drm_file *file) +static unsigned int +gen8_dispatch_bsd_ring(struct drm_i915_private *dev_priv, struct drm_file *file) { - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_file_private *file_priv = file->driver_priv; - /* Check whether the file_priv is using one ring */ - if (file_priv->bsd_ring) - return file_priv->bsd_ring->id; - else { - /* If no, use the ping-pong mechanism to select one ring */ - int ring_id; - - mutex_lock(&dev->struct_mutex); - if (dev_priv->mm.bsd_ring_dispatch_index == 0) { - ring_id = VCS; - dev_priv->mm.bsd_ring_dispatch_index = 1; - } else { - ring_id = VCS2; - dev_priv->mm.bsd_ring_dispatch_index = 0; - } - file_priv->bsd_ring = &dev_priv->ring[ring_id]; - mutex_unlock(&dev->struct_mutex); - return ring_id; + /* Check whether the file_priv has already selected one ring. */ + if ((int)file_priv->bsd_ring < 0) { + /* If not, use the ping-pong mechanism to select one. */ + mutex_lock(&dev_priv->dev->struct_mutex); + file_priv->bsd_ring = dev_priv->mm.bsd_ring_dispatch_index; + dev_priv->mm.bsd_ring_dispatch_index ^= 1; + mutex_unlock(&dev_priv->dev->struct_mutex); } + + return file_priv->bsd_ring; } static struct drm_i915_gem_object * @@ -1374,6 +1364,63 @@ eb_get_batch(struct eb_vmas *eb) return vma->obj; } +#define I915_USER_RINGS (4) + +static const enum intel_ring_id user_ring_map[I915_USER_RINGS + 1] = { + [I915_EXEC_DEFAULT] = RCS, + [I915_EXEC_RENDER] = RCS, + [I915_EXEC_BLT] = BCS, + [I915_EXEC_BSD] = VCS, + [I915_EXEC_VEBOX] = VECS +}; + +static int +eb_select_ring(struct drm_i915_private *dev_priv, + struct drm_file *file, + struct drm_i915_gem_execbuffer2 *args, + struct intel_engine_cs **ring) +{ + unsigned int user_ring_id = args->flags & I915_EXEC_RING_MASK; + + if (user_ring_id > I915_USER_RINGS) { + DRM_DEBUG("execbuf with unknown ring: %u\n", user_ring_id); + return -EINVAL; + } + + if ((user_ring_id != I915_EXEC_BSD) && + ((args->flags & I915_EXEC_BSD_MASK) != 0)) { + DRM_DEBUG("execbuf with non bsd ring but with invalid " + "bsd dispatch flags: %d\n", (int)(args->flags)); + return -EINVAL; + } + + if (user_ring_id == I915_EXEC_BSD && HAS_BSD2(dev_priv)) { + unsigned int bsd_idx = args->flags & I915_EXEC_BSD_MASK; + + if (bsd_idx == I915_EXEC_BSD_DEFAULT) { + bsd_idx = gen8_dispatch_bsd_ring(dev_priv, file); + } else if (bsd_idx >= I915_EXEC_BSD_RING1 && + bsd_idx <= I915_EXEC_BSD_RING2) { + bsd_idx--; + } else { + DRM_DEBUG("execbuf with unknown bsd ring: %u\n", + bsd_idx); + return -EINVAL; + } + + *ring = &dev_priv->ring[_VCS(bsd_idx)]; + } else { + *ring = &dev_priv->ring[user_ring_map[user_ring_id]]; + } + + if (!intel_ring_initialized(*ring)) { + DRM_DEBUG("execbuf with invalid ring: %u\n", user_ring_id); + return -EINVAL; + } + + return 0; +} + static int i915_gem_do_execbuffer(struct drm_device *dev, void *data, struct drm_file *file, @@ -1412,51 +1459,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, if (args->flags & I915_EXEC_IS_PINNED) dispatch_flags |= I915_DISPATCH_PINNED; - if ((args->flags & I915_EXEC_RING_MASK) > LAST_USER_RING) { - DRM_DEBUG("execbuf with unknown ring: %d\n", - (int)(args->flags & I915_EXEC_RING_MASK)); - return -EINVAL; - } - - if (((args->flags & I915_EXEC_RING_MASK) != I915_EXEC_BSD) && - ((args->flags & I915_EXEC_BSD_MASK) != 0)) { - DRM_DEBUG("execbuf with non bsd ring but with invalid " - "bsd dispatch flags: %d\n", (int)(args->flags)); - return -EINVAL; - } - - if ((args->flags & I915_EXEC_RING_MASK) == I915_EXEC_DEFAULT) - ring = &dev_priv->ring[RCS]; - else if ((args->flags & I915_EXEC_RING_MASK) == I915_EXEC_BSD) { - if (HAS_BSD2(dev)) { - int ring_id; - - switch (args->flags & I915_EXEC_BSD_MASK) { - case I915_EXEC_BSD_DEFAULT: - ring_id = gen8_dispatch_bsd_ring(dev, file); - ring = &dev_priv->ring[ring_id]; - break; - case I915_EXEC_BSD_RING1: - ring = &dev_priv->ring[VCS]; - break; - case I915_EXEC_BSD_RING2: - ring = &dev_priv->ring[VCS2]; - break; - default: - DRM_DEBUG("execbuf with unknown bsd ring: %d\n", - (int)(args->flags & I915_EXEC_BSD_MASK)); - return -EINVAL; - } - } else - ring = &dev_priv->ring[VCS]; - } else - ring = &dev_priv->ring[(args->flags & I915_EXEC_RING_MASK) - 1]; - - if (!intel_ring_initialized(ring)) { - DRM_DEBUG("execbuf with invalid ring: %d\n", - (int)(args->flags & I915_EXEC_RING_MASK)); - return -EINVAL; - } + ret = eb_select_ring(dev_priv, file, args, &ring); + if (ret) + return ret; if (args->buffer_count < 1) { DRM_DEBUG("execbuf with %d buffers\n", args->buffer_count); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index b6c7cd2b8a40..5b44ca63405d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -149,14 +149,14 @@ struct i915_ctx_workarounds { struct intel_engine_cs { const char *name; enum intel_ring_id { - RCS = 0x0, - VCS, + RCS = 0, BCS, - VECS, - VCS2 + VCS, + VCS2, /* Keep instances of the same type engine together. */ + VECS } id; #define I915_NUM_RINGS 5 -#define LAST_USER_RING (VECS + 1) +#define _VCS(n) (VCS + (n)) u32 mmio_base; struct drm_device *dev; struct intel_ringbuffer *buffer; -- cgit v1.2.3 From 426960bed3217f72a1b7bb94f084d79cc616ec0f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 15 Jan 2016 16:51:46 +0000 Subject: drm/i915: Seal busy-ioctl uABI and prevent leaking of internal ids Tvrtko was looking through the execbuffer-ioctl and noticed that the uABI was tightly coupled to our internal engine identifiers. Close inspection also revealed that we leak those internal engine identifiers through the busy-ioctl, and those internal identifiers already do not match the user identifiers. Fortuitiously, there is only one user of the set of busy rings from the busy-ioctl, and they only wish to choose between the RENDER and the BLT engines. Let's fix the userspace ABI while we still can. v2: Update the uAPI documentation to explain the identifiers. Signed-off-by: Chris Wilson Testcase: igt/gem_busy Cc: Tvrtko Ursulin Cc: Daniel Vetter Reviewed-by: Tvrtko Ursulin Acked-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1452876706-21620-1-git-send-email-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 18 ++++++++++++++---- drivers/gpu/drm/i915/intel_lrc.c | 5 +++++ drivers/gpu/drm/i915/intel_ringbuffer.c | 5 +++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + include/uapi/drm/i915_drm.h | 33 +++++++++++++++++++++++++++++---- 5 files changed, 54 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0ed731ed6976..371bbb28c471 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4358,10 +4358,20 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, if (ret) goto unref; - BUILD_BUG_ON(I915_NUM_RINGS > 16); - args->busy = obj->active << 16; - if (obj->last_write_req) - args->busy |= obj->last_write_req->ring->id; + args->busy = 0; + if (obj->active) { + int i; + + for (i = 0; i < I915_NUM_RINGS; i++) { + struct drm_i915_gem_request *req; + + req = obj->last_read_req[i]; + if (req) + args->busy |= 1 << (16 + req->ring->exec_id); + } + if (obj->last_write_req) + args->busy |= obj->last_write_req->ring->exec_id; + } unref: drm_gem_object_unreference(&obj->base); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 7f47948d5c40..73d4347429df 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -2085,6 +2085,7 @@ static int logical_render_ring_init(struct drm_device *dev) ring->name = "render ring"; ring->id = RCS; + ring->exec_id = I915_EXEC_RENDER; ring->mmio_base = RENDER_RING_BASE; logical_ring_default_irqs(ring, GEN8_RCS_IRQ_SHIFT); @@ -2135,6 +2136,7 @@ static int logical_bsd_ring_init(struct drm_device *dev) ring->name = "bsd ring"; ring->id = VCS; + ring->exec_id = I915_EXEC_BSD; ring->mmio_base = GEN6_BSD_RING_BASE; logical_ring_default_irqs(ring, GEN8_VCS1_IRQ_SHIFT); @@ -2150,6 +2152,7 @@ static int logical_bsd2_ring_init(struct drm_device *dev) ring->name = "bsd2 ring"; ring->id = VCS2; + ring->exec_id = I915_EXEC_BSD; ring->mmio_base = GEN8_BSD2_RING_BASE; logical_ring_default_irqs(ring, GEN8_VCS2_IRQ_SHIFT); @@ -2165,6 +2168,7 @@ static int logical_blt_ring_init(struct drm_device *dev) ring->name = "blitter ring"; ring->id = BCS; + ring->exec_id = I915_EXEC_BLT; ring->mmio_base = BLT_RING_BASE; logical_ring_default_irqs(ring, GEN8_BCS_IRQ_SHIFT); @@ -2180,6 +2184,7 @@ static int logical_vebox_ring_init(struct drm_device *dev) ring->name = "video enhancement ring"; ring->id = VECS; + ring->exec_id = I915_EXEC_VEBOX; ring->mmio_base = VEBOX_RING_BASE; logical_ring_default_irqs(ring, GEN8_VECS_IRQ_SHIFT); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index d4e33ac02efa..9030e2bca0c0 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2683,6 +2683,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ring->name = "render ring"; ring->id = RCS; + ring->exec_id = I915_EXEC_RENDER; ring->mmio_base = RENDER_RING_BASE; if (INTEL_INFO(dev)->gen >= 8) { @@ -2831,6 +2832,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) ring->name = "bsd ring"; ring->id = VCS; + ring->exec_id = I915_EXEC_BSD; ring->write_tail = ring_write_tail; if (INTEL_INFO(dev)->gen >= 6) { @@ -2907,6 +2909,7 @@ int intel_init_bsd2_ring_buffer(struct drm_device *dev) ring->name = "bsd2 ring"; ring->id = VCS2; + ring->exec_id = I915_EXEC_BSD; ring->write_tail = ring_write_tail; ring->mmio_base = GEN8_BSD2_RING_BASE; @@ -2937,6 +2940,7 @@ int intel_init_blt_ring_buffer(struct drm_device *dev) ring->name = "blitter ring"; ring->id = BCS; + ring->exec_id = I915_EXEC_BLT; ring->mmio_base = BLT_RING_BASE; ring->write_tail = ring_write_tail; @@ -2994,6 +2998,7 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev) ring->name = "video enhancement ring"; ring->id = VECS; + ring->exec_id = I915_EXEC_VEBOX; ring->mmio_base = VEBOX_RING_BASE; ring->write_tail = ring_write_tail; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 5b44ca63405d..b12f2aabd104 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -157,6 +157,7 @@ struct intel_engine_cs { } id; #define I915_NUM_RINGS 5 #define _VCS(n) (VCS + (n)) + unsigned int exec_id; u32 mmio_base; struct drm_device *dev; struct intel_ringbuffer *buffer; diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index acf21026c78a..6a19371391fa 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -812,10 +812,35 @@ struct drm_i915_gem_busy { /** Handle of the buffer to check for busy */ __u32 handle; - /** Return busy status (1 if busy, 0 if idle). - * The high word is used to indicate on which rings the object - * currently resides: - * 16:31 - busy (r or r/w) rings (16 render, 17 bsd, 18 blt, etc) + /** Return busy status + * + * A return of 0 implies that the object is idle (after + * having flushed any pending activity), and a non-zero return that + * the object is still in-flight on the GPU. (The GPU has not yet + * signaled completion for all pending requests that reference the + * object.) + * + * The returned dword is split into two fields to indicate both + * the engines on which the object is being read, and the + * engine on which it is currently being written (if any). + * + * The low word (bits 0:15) indicate if the object is being written + * to by any engine (there can only be one, as the GEM implicit + * synchronisation rules force writes to be serialised). Only the + * engine for the last write is reported. + * + * The high word (bits 16:31) are a bitmask of which engines are + * currently reading from the object. Multiple engines may be + * reading from the object simultaneously. + * + * The value of each engine is the same as specified in the + * EXECBUFFER2 ioctl, i.e. I915_EXEC_RENDER, I915_EXEC_BSD etc. + * Note I915_EXEC_DEFAULT is a symbolic value and is mapped to + * the I915_EXEC_RENDER engine for execution, and so it is never + * reported as active itself. Some hardware may have parallel + * execution engines, e.g. multiple media engines, which are + * mapped to the same identifier in the EXECBUFFER2 ioctl and + * so are not separately reported for busyness. */ __u32 busy; }; -- cgit v1.2.3 From d742c969b3ad9c83ac57579dfd56c90dd437db37 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 13 Jan 2016 14:52:52 +0100 Subject: ath10k: prevent txrx running for too long On multicore systems it was possible for the txrx tasklet to keep on running for long periods of time on a single CPU due to tx completion processing. Another CPU could feed the running tasklet for an indefinite amount of time. The tasklet is now guaranteed to run a finite amount of time and is limited by HTT CE Rx ring depth. This improves behavior when RPS is used on target system and might improve TCP handling as well. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_rx.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 91afa3ae414c..3079434b5d9b 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2156,10 +2156,18 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) { struct ath10k_htt *htt = (struct ath10k_htt *)ptr; struct ath10k *ar = htt->ar; + struct sk_buff_head tx_q; struct htt_resp *resp; struct sk_buff *skb; + unsigned long flags; - while ((skb = skb_dequeue(&htt->tx_compl_q))) { + __skb_queue_head_init(&tx_q); + + spin_lock_irqsave(&htt->tx_compl_q.lock, flags); + skb_queue_splice_init(&htt->tx_compl_q, &tx_q); + spin_unlock_irqrestore(&htt->tx_compl_q.lock, flags); + + while ((skb = __skb_dequeue(&tx_q))) { ath10k_htt_rx_frm_tx_compl(htt->ar, skb); dev_kfree_skb_any(skb); } -- cgit v1.2.3 From de46c015c9b703bb8abb91856ed45e3639c7e7d2 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 13 Jan 2016 21:16:28 +0530 Subject: ath10k: add support for parsing per STA rx_duration for 10.2.4 Add support for parsing 'peer_rx_duration' as part of 10.2.4 peer_stats. Also register PEER_STATS service for parsing 'rx_duration' (and for any new fields to be added as part of peer_stats). Have checks for backward compatibility with older 10.2.4 firmware incase PEER_STATS service is not enabled Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/wmi.c | 22 ++++++++++++++++++++-- drivers/net/wireless/ath/ath10k/wmi.h | 12 ++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 7840cf3ef7a6..d47a08568bdc 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -159,6 +159,7 @@ struct ath10k_fw_stats_peer { u32 peer_rssi; u32 peer_tx_rate; u32 peer_rx_rate; /* 10x only */ + u32 rx_duration; }; struct ath10k_fw_stats_vdev { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index a7c3d299639b..c610d1761940 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2862,11 +2862,20 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar, /* fw doesn't implement vdev stats */ for (i = 0; i < num_peer_stats; i++) { - const struct wmi_10_2_4_peer_stats *src; + const struct wmi_10_2_4_ext_peer_stats *src; struct ath10k_fw_stats_peer *dst; + int stats_len; + bool ext_peer_stats_support; + + ext_peer_stats_support = test_bit(WMI_SERVICE_PEER_STATS, + ar->wmi.svc_map); + if (ext_peer_stats_support) + stats_len = sizeof(struct wmi_10_2_4_ext_peer_stats); + else + stats_len = sizeof(struct wmi_10_2_4_peer_stats); src = (void *)skb->data; - if (!skb_pull(skb, sizeof(*src))) + if (!skb_pull(skb, stats_len)) return -EPROTO; dst = kzalloc(sizeof(*dst), GFP_ATOMIC); @@ -2876,6 +2885,9 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar, ath10k_wmi_pull_peer_stats(&src->common.old, dst); dst->peer_rx_rate = __le32_to_cpu(src->common.peer_rx_rate); + + if (ext_peer_stats_support) + dst->rx_duration = __le32_to_cpu(src->rx_duration); /* FIXME: expose 10.2 specific values */ list_add_tail(&dst->list, &stats->peers); @@ -5517,6 +5529,9 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar) test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map)) features |= WMI_10_2_COEX_GPIO; + if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) + features |= WMI_10_2_PEER_STATS; + cmd->resource_config.feature_mask = __cpu_to_le32(features); memcpy(&cmd->resource_config.common, &config, sizeof(config)); @@ -7126,6 +7141,9 @@ ath10k_wmi_fw_peer_stats_fill(const struct ath10k_fw_stats_peer *peer, "Peer TX rate", peer->peer_tx_rate); len += scnprintf(buf + len, buf_len - len, "%30s %u\n", "Peer RX rate", peer->peer_rx_rate); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "Peer RX duration", peer->rx_duration); + len += scnprintf(buf + len, buf_len - len, "\n"); *length = len; } diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index d85ad7855d20..e1bb02ba207d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -177,6 +177,7 @@ enum wmi_service { WMI_SERVICE_BSS_CHANNEL_INFO_64, WMI_SERVICE_EXT_RES_CFG_SUPPORT, WMI_SERVICE_MESH, + WMI_SERVICE_PEER_STATS, /* keep last */ WMI_SERVICE_MAX, @@ -213,6 +214,7 @@ enum wmi_10x_service { WMI_10X_SERVICE_BSS_CHANNEL_INFO_64, WMI_10X_SERVICE_MESH, WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT, + WMI_10X_SERVICE_PEER_STATS, }; enum wmi_main_service { @@ -386,6 +388,7 @@ static inline char *wmi_service_name(int service_id) SVCSTR(WMI_SERVICE_BSS_CHANNEL_INFO_64); SVCSTR(WMI_SERVICE_EXT_RES_CFG_SUPPORT); SVCSTR(WMI_SERVICE_MESH); + SVCSTR(WMI_SERVICE_PEER_STATS); default: return NULL; } @@ -463,6 +466,8 @@ static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out, WMI_SERVICE_MESH, len); SVCMAP(WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT, WMI_SERVICE_EXT_RES_CFG_SUPPORT, len); + SVCMAP(WMI_10X_SERVICE_PEER_STATS, + WMI_SERVICE_PEER_STATS, len); } static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out, @@ -2417,6 +2422,7 @@ enum wmi_10_2_feature_mask { WMI_10_2_RX_BATCH_MODE = BIT(0), WMI_10_2_ATF_CONFIG = BIT(1), WMI_10_2_COEX_GPIO = BIT(3), + WMI_10_2_PEER_STATS = BIT(7), }; struct wmi_resource_config_10_2 { @@ -4230,6 +4236,12 @@ struct wmi_10_2_4_peer_stats { __le32 unknown_value; /* FIXME: what is this word? */ } __packed; +struct wmi_10_2_4_ext_peer_stats { + struct wmi_10_2_peer_stats common; + __le32 peer_rssi_changed; + __le32 rx_duration; +} __packed; + struct wmi_10_4_peer_stats { struct wmi_mac_addr peer_macaddr; __le32 peer_rssi; -- cgit v1.2.3 From 962b7a0e77015802f0ceefe6f0e3cad3f10fd4f8 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Mon, 4 Jan 2016 10:08:54 +0100 Subject: HID: add HID_QUIRK_NOGET to Quanta 3003 too dmesg shows a lot of: [ 1374.890348] hid-multitouch 0003:0408:3003.0007: usb_submit_urb(ctrl) failed: -1 [ 1384.916388] hid-multitouch 0003:0408:3003.0007: usb_submit_urb(ctrl) failed: -1 [ 1384.916432] hid-multitouch 0003:0408:3003.0007: timeout initializing reports Add the quirk and make the touchscreen happy. Signed-off-by: Benjamin Tissoires Tested-by: Jim lovell Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b6ff6e78ac54..bfd2c9d834d0 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -800,6 +800,7 @@ #define USB_VENDOR_ID_QUANTA 0x0408 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH 0x3000 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001 0x3001 +#define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003 0x3003 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008 #define USB_VENDOR_ID_RAZER 0x1532 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 7dd0953cd70f..6f0db54c4a9f 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -106,6 +106,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, { USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, -- cgit v1.2.3 From ceb6560a4cf3a2667209e6869f4fb8f6da6ef55f Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Thu, 21 Jan 2016 10:42:31 +0530 Subject: net/irda: bfin_sir: remove duplicate defines The defconfig build of blackfin is failing with the error: arch/blackfin/include/asm/bfin_serial.h:269:0: warning: "port_membase" redefined drivers/net/irda/bfin_sir.h:85:0: note: this is the location of the previous definition arch/blackfin/include/asm/bfin_serial.h:382:0: warning: "get_lsr_cache" redefined drivers/net/irda/bfin_sir.h:86:0: note: this is the location of the previous definition arch/blackfin/include/asm/bfin_serial.h:383:0: warning: "put_lsr_cache" redefined drivers/net/irda/bfin_sir.h:87:0: note: this is the location of the previous definition port_membase, get_lsr_cache, put_lsr_cache are already defined in the architecture files, no need to define them again in the driver. Signed-off-by: Sudip Mukherjee Signed-off-by: David S. Miller --- drivers/net/irda/bfin_sir.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/irda/bfin_sir.h b/drivers/net/irda/bfin_sir.h index 29cbde8501ed..d47cf14bb4a5 100644 --- a/drivers/net/irda/bfin_sir.h +++ b/drivers/net/irda/bfin_sir.h @@ -82,9 +82,6 @@ struct bfin_sir_self { #define DRIVER_NAME "bfin_sir" -#define port_membase(port) (((struct bfin_sir_port *)(port))->membase) -#define get_lsr_cache(port) (((struct bfin_sir_port *)(port))->lsr) -#define put_lsr_cache(port, v) (((struct bfin_sir_port *)(port))->lsr = (v)) #include static const unsigned short per[][4] = { -- cgit v1.2.3 From d5c3d84657db57bd23ecd58b97f1c99dd42a7b80 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 18 Jan 2016 19:33:06 -0800 Subject: net: phy: Avoid polling PHY with PHY_IGNORE_INTERRUPTS Commit 2c7b49212a86 ("phy: fix the use of PHY_IGNORE_INTERRUPT") changed a hunk in phy_state_machine() in the PHY_RUNNING case which was not needed. The change essentially makes the PHY library treat PHY devices with PHY_IGNORE_INTERRUPT to keep polling for the PHY device, even though the intent is not to do it. Fix this by reverting that specific hunk, which makes the PHY state machine wait for state changes, and stay in the PHY_RUNNING state for as long as needed. Fixes: 2c7b49212a86 ("phy: fix the use of PHY_IGNORE_INTERRUPT") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 8763bb20988a..42b4c1eb7a90 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -905,10 +905,10 @@ void phy_state_machine(struct work_struct *work) phydev->adjust_link(phydev->attached_dev); break; case PHY_RUNNING: - /* Only register a CHANGE if we are polling or ignoring - * interrupts and link changed since latest checking. + /* Only register a CHANGE if we are polling and link changed + * since latest checking. */ - if (!phy_interrupt_is_valid(phydev)) { + if (phydev->irq == PHY_POLL) { old_link = phydev->link; err = phy_read_status(phydev); if (err) @@ -1000,8 +1000,13 @@ void phy_state_machine(struct work_struct *work) phy_state_to_str(old_state), phy_state_to_str(phydev->state)); - queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, - PHY_STATE_TIME * HZ); + /* Only re-schedule a PHY state machine change if we are polling the + * PHY, if PHY_IGNORE_INTERRUPT is set, then we will be moving + * between states from phy_mac_interrupt() + */ + if (phydev->irq == PHY_POLL) + queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, + PHY_STATE_TIME * HZ); } void phy_mac_interrupt(struct phy_device *phydev, int new_link) -- cgit v1.2.3 From deccd16f91f930af8e91ffbbfc839d0ad8da999d Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 18 Jan 2016 19:33:07 -0800 Subject: net: phy: Fix phy_mac_interrupt() Commit 5ea94e7686a3 ("phy: add phy_mac_interrupt()") to use with PHY_IGNORE_INTERRUPT added a cancel_work_sync() into phy_mac_interrupt() which is allowed to sleep, whereas phy_mac_interrupt() is expected to be callable from interrupt context. Now that we have fixed how the PHY state machine treats PHY_IGNORE_INTERRUPT with respect to state changes, we can just set the new link state, and queue the PHY state machine for execution so it is going to read the new link state. For that to work properly, we need to update phy_change() not to try to invoke any interrupt callbacks if we have configured the PHY device for PHY_IGNORE_INTERRUPT, because that PHY device and its driver are not required to implement those. Fixes: 5ea94e7686a3 ("phy: add phy_mac_interrupt() to use with PHY_IGNORE_INTERRUPT") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 42b4c1eb7a90..5590b9c182c9 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -692,25 +692,29 @@ void phy_change(struct work_struct *work) struct phy_device *phydev = container_of(work, struct phy_device, phy_queue); - if (phydev->drv->did_interrupt && - !phydev->drv->did_interrupt(phydev)) - goto ignore; + if (phy_interrupt_is_valid(phydev)) { + if (phydev->drv->did_interrupt && + !phydev->drv->did_interrupt(phydev)) + goto ignore; - if (phy_disable_interrupts(phydev)) - goto phy_err; + if (phy_disable_interrupts(phydev)) + goto phy_err; + } mutex_lock(&phydev->lock); if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state)) phydev->state = PHY_CHANGELINK; mutex_unlock(&phydev->lock); - atomic_dec(&phydev->irq_disable); - enable_irq(phydev->irq); + if (phy_interrupt_is_valid(phydev)) { + atomic_dec(&phydev->irq_disable); + enable_irq(phydev->irq); - /* Reenable interrupts */ - if (PHY_HALTED != phydev->state && - phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED)) - goto irq_enable_err; + /* Reenable interrupts */ + if (PHY_HALTED != phydev->state && + phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED)) + goto irq_enable_err; + } /* reschedule state queue work to run as soon as possible */ cancel_delayed_work_sync(&phydev->state_queue); @@ -1011,9 +1015,10 @@ void phy_state_machine(struct work_struct *work) void phy_mac_interrupt(struct phy_device *phydev, int new_link) { - cancel_work_sync(&phydev->phy_queue); phydev->link = new_link; - schedule_work(&phydev->phy_queue); + + /* Trigger a state machine change */ + queue_work(system_power_efficient_wq, &phydev->phy_queue); } EXPORT_SYMBOL(phy_mac_interrupt); -- cgit v1.2.3 From 49f7a471e4d172fc80140beccf6b3409b117b130 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 18 Jan 2016 19:33:08 -0800 Subject: net: bcmgenet: Properly configure PHY to ignore interrupt By the time we execute bcmgenet_mii_probe(), the MDIO bus structure has long been allocated and registered. Overirring the PHY interrupt using the MDIO bus structure has no chance to work anymore, because of_mdiobus_register() has call phy_device_create() for use, which copied the MDIO bus address's irq for the PHY into the PHY device "irq" member. Since we do have a proper reference to a PHY device in bcmgenet_mii_probe(), just assign the desired IRQ value here. Fixes: aa09677cba42 ("net: bcmgenet: add MDIO routines") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmmii.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index 0d775964b060..457c3bc8cfff 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -401,7 +401,7 @@ int bcmgenet_mii_probe(struct net_device *dev) * Ethernet MAC ISRs */ if (priv->internal_phy) - priv->mii_bus->irq[phydev->mdio.addr] = PHY_IGNORE_INTERRUPT; + priv->phydev->irq = PHY_IGNORE_INTERRUPT; return 0; } -- cgit v1.2.3 From 35e2d1152b22eae99c961affbe85374bef05a775 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Wed, 20 Jan 2016 16:22:47 -0800 Subject: tunnels: Allow IPv6 UDP checksums to be correctly controlled. When configuring checksums on UDP tunnels, the flags are different for IPv4 vs. IPv6 (and reversed). However, when lightweight tunnels are enabled the flags used are always the IPv4 versions, which are ignored in the IPv6 code paths. This uses the correct IPv6 flags, so checksums can be controlled appropriately. Fixes: a725e514 ("vxlan: metadata based tunneling for IPv6") Fixes: abe492b4 ("geneve: UDP checksum configuration via netlink") Signed-off-by: Jesse Gross Acked-by: Jiri Benc Signed-off-by: David S. Miller --- drivers/net/geneve.c | 4 ++-- drivers/net/vxlan.c | 23 ++++++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 7456569f53c1..0b14ac3b8d11 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -980,9 +980,9 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, opts = ip_tunnel_info_opts(info); if (key->tun_flags & TUNNEL_CSUM) - flags |= GENEVE_F_UDP_CSUM; + flags &= ~GENEVE_F_UDP_ZERO_CSUM6_TX; else - flags &= ~GENEVE_F_UDP_CSUM; + flags |= GENEVE_F_UDP_ZERO_CSUM6_TX; err = geneve6_build_skb(dst, skb, key->tun_flags, vni, info->options_len, opts, diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 2d88c799d2ac..a85b1fcb3130 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1985,11 +1985,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, vxlan->cfg.port_max, true); if (info) { - if (info->key.tun_flags & TUNNEL_CSUM) - flags |= VXLAN_F_UDP_CSUM; - else - flags &= ~VXLAN_F_UDP_CSUM; - ttl = info->key.ttl; tos = info->key.tos; @@ -2004,8 +1999,15 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, goto drop; sk = vxlan->vn4_sock->sock->sk; - if (info && (info->key.tun_flags & TUNNEL_DONT_FRAGMENT)) - df = htons(IP_DF); + if (info) { + if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT) + df = htons(IP_DF); + + if (info->key.tun_flags & TUNNEL_CSUM) + flags |= VXLAN_F_UDP_CSUM; + else + flags &= ~VXLAN_F_UDP_CSUM; + } memset(&fl4, 0, sizeof(fl4)); fl4.flowi4_oif = rdst ? rdst->remote_ifindex : 0; @@ -2101,6 +2103,13 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, return; } + if (info) { + if (info->key.tun_flags & TUNNEL_CSUM) + flags &= ~VXLAN_F_UDP_ZERO_CSUM6_TX; + else + flags |= VXLAN_F_UDP_ZERO_CSUM6_TX; + } + ttl = ttl ? : ip6_dst_hoplimit(ndst); err = vxlan6_xmit_skb(ndst, sk, skb, dev, &saddr, &dst->sin6.sin6_addr, 0, ttl, src_port, dst_port, htonl(vni << 8), md, -- cgit v1.2.3 From 48189d6aaf1ed1b382666289a94a50e5269a8946 Mon Sep 17 00:00:00 2001 From: yankejian Date: Wed, 20 Jan 2016 16:00:19 +0800 Subject: net: hns: enet specifies a reference to dsaf This patch replace the assoication between dsaf and enet from string matching to object reference. It requires the DTS to be updated within BIOS. Thanks god it can be done for all released boards. Signed-off-by: Kejian Yan Acked-by: Rob Herring Acked-by: Yisen Zhuang Signed-off-by: David S. Miller --- .../devicetree/bindings/net/hisilicon-hns-dsaf.txt | 5 +---- .../devicetree/bindings/net/hisilicon-hns-nic.txt | 7 ++++--- arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi | 19 +++++++++---------- drivers/net/ethernet/hisilicon/hns/hnae.c | 17 +++++++---------- drivers/net/ethernet/hisilicon/hns/hnae.h | 7 +++++-- drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c | 4 ++++ drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 10 +--------- drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h | 1 + drivers/net/ethernet/hisilicon/hns/hns_enet.c | 15 +++++++++------ drivers/net/ethernet/hisilicon/hns/hns_enet.h | 2 +- 10 files changed, 42 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt b/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt index 80411b2f0490..ecacfa44b1eb 100644 --- a/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt +++ b/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt @@ -4,8 +4,6 @@ Required properties: - compatible: should be "hisilicon,hns-dsaf-v1" or "hisilicon,hns-dsaf-v2". "hisilicon,hns-dsaf-v1" is for hip05. "hisilicon,hns-dsaf-v2" is for Hi1610 and Hi1612. -- dsa-name: dsa fabric name who provide this interface. - should be "dsafX", X is the dsaf id. - mode: dsa fabric mode string. only support one of dsaf modes like these: "2port-64vf", "6port-16rss", @@ -26,9 +24,8 @@ Required properties: Example: -dsa: dsa@c7000000 { +dsaf0: dsa@c7000000 { compatible = "hisilicon,hns-dsaf-v1"; - dsa_name = "dsaf0"; mode = "6port-16rss"; interrupt-parent = <&mbigen_dsa>; reg = <0x0 0xC0000000 0x0 0x420000 diff --git a/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt b/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt index 41d19be7011e..e6a9d1c30878 100644 --- a/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt +++ b/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt @@ -4,8 +4,9 @@ Required properties: - compatible: "hisilicon,hns-nic-v1" or "hisilicon,hns-nic-v2". "hisilicon,hns-nic-v1" is for hip05. "hisilicon,hns-nic-v2" is for Hi1610 and Hi1612. -- ae-name: accelerator name who provides this interface, - is simply a name referring to the name of name in the accelerator node. +- ae-handle: accelerator engine handle for hns, + specifies a reference to the associating hardware driver node. + see Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt - port-id: is the index of port provided by DSAF (the accelerator). DSAF can connect to 8 PHYs. Port 0 to 1 are both used for adminstration purpose. They are called debug ports. @@ -41,7 +42,7 @@ Example: ethernet@0{ compatible = "hisilicon,hns-nic-v1"; - ae-name = "dsaf0"; + ae-handle = <&dsaf0>; port-id = <0>; local-mac-address = [a2 14 e4 4b 56 76]; }; diff --git a/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi b/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi index da7b6e613257..933cba359918 100644 --- a/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi @@ -23,9 +23,8 @@ soc0: soc@000000000 { }; }; - dsa: dsa@c7000000 { + dsaf0: dsa@c7000000 { compatible = "hisilicon,hns-dsaf-v1"; - dsa_name = "dsaf0"; mode = "6port-16rss"; interrupt-parent = <&mbigen_dsa>; @@ -127,7 +126,7 @@ soc0: soc@000000000 { eth0: ethernet@0{ compatible = "hisilicon,hns-nic-v1"; - ae-name = "dsaf0"; + ae-handle = <&dsaf0>; port-id = <0>; local-mac-address = [00 00 00 01 00 58]; status = "disabled"; @@ -135,14 +134,14 @@ soc0: soc@000000000 { }; eth1: ethernet@1{ compatible = "hisilicon,hns-nic-v1"; - ae-name = "dsaf0"; + ae-handle = <&dsaf0>; port-id = <1>; status = "disabled"; dma-coherent; }; eth2: ethernet@2{ compatible = "hisilicon,hns-nic-v1"; - ae-name = "dsaf0"; + ae-handle = <&dsaf0>; port-id = <2>; local-mac-address = [00 00 00 01 00 5a]; status = "disabled"; @@ -150,7 +149,7 @@ soc0: soc@000000000 { }; eth3: ethernet@3{ compatible = "hisilicon,hns-nic-v1"; - ae-name = "dsaf0"; + ae-handle = <&dsaf0>; port-id = <3>; local-mac-address = [00 00 00 01 00 5b]; status = "disabled"; @@ -158,7 +157,7 @@ soc0: soc@000000000 { }; eth4: ethernet@4{ compatible = "hisilicon,hns-nic-v1"; - ae-name = "dsaf0"; + ae-handle = <&dsaf0>; port-id = <4>; local-mac-address = [00 00 00 01 00 5c]; status = "disabled"; @@ -166,7 +165,7 @@ soc0: soc@000000000 { }; eth5: ethernet@5{ compatible = "hisilicon,hns-nic-v1"; - ae-name = "dsaf0"; + ae-handle = <&dsaf0>; port-id = <5>; local-mac-address = [00 00 00 01 00 5d]; status = "disabled"; @@ -174,7 +173,7 @@ soc0: soc@000000000 { }; eth6: ethernet@6{ compatible = "hisilicon,hns-nic-v1"; - ae-name = "dsaf0"; + ae-handle = <&dsaf0>; port-id = <6>; local-mac-address = [00 00 00 01 00 5e]; status = "disabled"; @@ -182,7 +181,7 @@ soc0: soc@000000000 { }; eth7: ethernet@7{ compatible = "hisilicon,hns-nic-v1"; - ae-name = "dsaf0"; + ae-handle = <&dsaf0>; port-id = <7>; local-mac-address = [00 00 00 01 00 5f]; status = "disabled"; diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c b/drivers/net/ethernet/hisilicon/hns/hnae.c index b3645297477e..3bfe36f9405b 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.c +++ b/drivers/net/ethernet/hisilicon/hns/hnae.c @@ -95,21 +95,17 @@ static struct hnae_buf_ops hnae_bops = { static int __ae_match(struct device *dev, const void *data) { struct hnae_ae_dev *hdev = cls_to_ae_dev(dev); - const char *ae_id = data; - if (!strncmp(ae_id, hdev->name, AE_NAME_SIZE)) - return 1; - - return 0; + return hdev->dev->of_node == data; } -static struct hnae_ae_dev *find_ae(const char *ae_id) +static struct hnae_ae_dev *find_ae(const struct device_node *ae_node) { struct device *dev; - WARN_ON(!ae_id); + WARN_ON(!ae_node); - dev = class_find_device(hnae_class, NULL, ae_id, __ae_match); + dev = class_find_device(hnae_class, NULL, ae_node, __ae_match); return dev ? cls_to_ae_dev(dev) : NULL; } @@ -316,7 +312,8 @@ EXPORT_SYMBOL(hnae_reinit_handle); * return handle ptr or ERR_PTR */ struct hnae_handle *hnae_get_handle(struct device *owner_dev, - const char *ae_id, u32 port_id, + const struct device_node *ae_node, + u32 port_id, struct hnae_buf_ops *bops) { struct hnae_ae_dev *dev; @@ -324,7 +321,7 @@ struct hnae_handle *hnae_get_handle(struct device *owner_dev, int i, j; int ret; - dev = find_ae(ae_id); + dev = find_ae(ae_node); if (!dev) return ERR_PTR(-ENODEV); diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index 6ca94dc3dda3..1cbcb9fa3fb5 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -524,8 +524,11 @@ struct hnae_handle { #define ring_to_dev(ring) ((ring)->q->dev->dev) -struct hnae_handle *hnae_get_handle(struct device *owner_dev, const char *ae_id, - u32 port_id, struct hnae_buf_ops *bops); +struct hnae_handle *hnae_get_handle(struct device *owner_dev, + const struct device_node *ae_node, + u32 port_id, + struct hnae_buf_ops *bops); + void hnae_put_handle(struct hnae_handle *handle); int hnae_ae_register(struct hnae_ae_dev *dev, struct module *owner); void hnae_ae_unregister(struct hnae_ae_dev *dev); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index 522b264866b4..a0070d0e740d 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -847,6 +847,7 @@ static struct hnae_ae_ops hns_dsaf_ops = { int hns_dsaf_ae_init(struct dsaf_device *dsaf_dev) { struct hnae_ae_dev *ae_dev = &dsaf_dev->ae_dev; + static atomic_t id = ATOMIC_INIT(-1); switch (dsaf_dev->dsaf_ver) { case AE_VERSION_1: @@ -858,6 +859,9 @@ int hns_dsaf_ae_init(struct dsaf_device *dsaf_dev) default: break; } + + snprintf(ae_dev->name, AE_NAME_SIZE, "%s%d", DSAF_DEVICE_NAME, + (int)atomic_inc_return(&id)); ae_dev->ops = &hns_dsaf_ops; ae_dev->dev = dsaf_dev->dev; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 1c33bd06bd5c..9439f04962e1 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -35,7 +35,7 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev) int ret, i; u32 desc_num; u32 buf_size; - const char *name, *mode_str; + const char *mode_str; struct device_node *np = dsaf_dev->dev->of_node; if (of_device_is_compatible(np, "hisilicon,hns-dsaf-v1")) @@ -43,14 +43,6 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev) else dsaf_dev->dsaf_ver = AE_VERSION_2; - ret = of_property_read_string(np, "dsa_name", &name); - if (ret) { - dev_err(dsaf_dev->dev, "get dsaf name fail, ret=%d!\n", ret); - return ret; - } - strncpy(dsaf_dev->ae_dev.name, name, AE_NAME_SIZE); - dsaf_dev->ae_dev.name[AE_NAME_SIZE - 1] = '\0'; - ret = of_property_read_string(np, "mode", &mode_str); if (ret) { dev_err(dsaf_dev->dev, "get dsaf mode fail, ret=%d!\n", ret); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index 31c312f9826e..40205b910f80 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -18,6 +18,7 @@ struct hns_mac_cb; #define DSAF_DRV_NAME "hns_dsaf" #define DSAF_MOD_VERSION "v1.0" +#define DSAF_DEVICE_NAME "dsaf" #define HNS_DSAF_DEBUG_NW_REG_OFFSET 0x100000 diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 0e30846a24f8..3f77ff77abbc 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -1802,7 +1802,7 @@ static int hns_nic_try_get_ae(struct net_device *ndev) int ret; h = hnae_get_handle(&priv->netdev->dev, - priv->ae_name, priv->port_id, NULL); + priv->ae_node, priv->port_id, NULL); if (IS_ERR_OR_NULL(h)) { ret = PTR_ERR(h); dev_dbg(priv->dev, "has not handle, register notifier!\n"); @@ -1880,13 +1880,16 @@ static int hns_nic_dev_probe(struct platform_device *pdev) else priv->enet_ver = AE_VERSION_2; - ret = of_property_read_string(node, "ae-name", &priv->ae_name); - if (ret) - goto out_read_string_fail; + priv->ae_node = (void *)of_parse_phandle(node, "ae-handle", 0); + if (IS_ERR_OR_NULL(priv->ae_node)) { + ret = PTR_ERR(priv->ae_node); + dev_err(dev, "not find ae-handle\n"); + goto out_read_prop_fail; + } ret = of_property_read_u32(node, "port-id", &priv->port_id); if (ret) - goto out_read_string_fail; + goto out_read_prop_fail; hns_init_mac_addr(ndev); @@ -1945,7 +1948,7 @@ static int hns_nic_dev_probe(struct platform_device *pdev) out_notify_fail: (void)cancel_work_sync(&priv->service_task); -out_read_string_fail: +out_read_prop_fail: free_netdev(ndev); return ret; } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.h b/drivers/net/ethernet/hisilicon/hns/hns_enet.h index 4b75270f014e..c68ab3d34fc2 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.h @@ -51,7 +51,7 @@ struct hns_nic_ops { }; struct hns_nic_priv { - const char *ae_name; + const struct device_node *ae_node; u32 enet_ver; u32 port_id; int phy_mode; -- cgit v1.2.3 From 2c832293e09be2f998ea916650927c8ccd5b4b3b Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Wed, 20 Jan 2016 16:36:25 +0800 Subject: net: mvneta: fix trivial cut-off issue in mvneta_ethtool_update_stats When s->type is T_REG_64, the high 32bits are lost in val. This patch fixes this trivial issue. Signed-off-by: Jisheng Zhang Fixes: 9b0cdefa4cd5 ("net: mvneta: add ethtool statistics") Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index fabc8df40392..4a8ed5bc3140 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -3242,26 +3242,25 @@ static void mvneta_ethtool_update_stats(struct mvneta_port *pp) const struct mvneta_statistic *s; void __iomem *base = pp->base; u32 high, low, val; + u64 val64; int i; for (i = 0, s = mvneta_statistics; s < mvneta_statistics + ARRAY_SIZE(mvneta_statistics); s++, i++) { - val = 0; - switch (s->type) { case T_REG_32: val = readl_relaxed(base + s->offset); + pp->ethtool_stats[i] += val; break; case T_REG_64: /* Docs say to read low 32-bit then high */ low = readl_relaxed(base + s->offset); high = readl_relaxed(base + s->offset + 4); - val = (u64)high << 32 | low; + val64 = (u64)high << 32 | low; + pp->ethtool_stats[i] += val64; break; } - - pp->ethtool_stats[i] += val; } } -- cgit v1.2.3 From 0e03f563a04207cc8e5db6afe63309a585995de7 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Wed, 20 Jan 2016 19:27:22 +0800 Subject: net: mvneta: sort the headers in alphabetic order Sorting the headers in alphabetic order will help to reduce the conflict when adding new headers in the future. Signed-off-by: Jisheng Zhang Acked-by: Thomas Petazzoni Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 4a8ed5bc3140..07d837dc39de 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -11,28 +11,28 @@ * warranty of any kind, whether express or implied. */ -#include -#include +#include +#include #include -#include -#include +#include #include -#include -#include #include -#include -#include -#include #include -#include +#include +#include +#include +#include #include +#include #include #include #include -#include #include -#include -#include +#include +#include +#include +#include +#include /* Registers */ #define MVNETA_RXQ_CONFIG_REG(q) (0x1400 + ((q) << 2)) -- cgit v1.2.3 From 2804ba4edef5b4de01d4c580eb9ab4000f822a53 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Wed, 20 Jan 2016 19:27:23 +0800 Subject: net: mvneta: Try to get named core clock first Some platforms may provide more than one clk for the mvneta IP, for example Marvell BG4CT provides one clk for the mac core, and one clk for the AXI bus logic. To support for more than one clock, we'll need to distinguish between the clock by name. Change clock probing to first try to get "core" clock before falling back to unnamed clock. Signed-off-by: Jisheng Zhang Acked-by: Thomas Petazzoni Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 07d837dc39de..406705580a33 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -3604,7 +3604,9 @@ static int mvneta_probe(struct platform_device *pdev) pp->indir[0] = rxq_def; - pp->clk = devm_clk_get(&pdev->dev, NULL); + pp->clk = devm_clk_get(&pdev->dev, "core"); + if (IS_ERR(pp->clk)) + pp->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(pp->clk)) { err = PTR_ERR(pp->clk); goto err_put_phy_node; -- cgit v1.2.3 From 15cc4a4a99ebfbbb696e85dca30680b522811a44 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Wed, 20 Jan 2016 19:27:24 +0800 Subject: net: mvneta: get optional bus clk Some platforms may provide more than one clk for the mvneta IP, for example Marvell BG4CT provides one clk for the mac core, and one clk for the AXI bus logic. Obviously this bus clk also need to be enabled. This patch adds this optional "bus" clk support. Signed-off-by: Jisheng Zhang Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 406705580a33..662c2ee268c7 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -373,6 +373,8 @@ struct mvneta_port { /* Core clock */ struct clk *clk; + /* AXI clock */ + struct clk *clk_bus; u8 mcast_count[256]; u16 tx_ring_size; u16 rx_ring_size; @@ -3614,6 +3616,10 @@ static int mvneta_probe(struct platform_device *pdev) clk_prepare_enable(pp->clk); + pp->clk_bus = devm_clk_get(&pdev->dev, "bus"); + if (!IS_ERR(pp->clk_bus)) + clk_prepare_enable(pp->clk_bus); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); pp->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(pp->base)) { @@ -3725,6 +3731,7 @@ err_free_stats: err_free_ports: free_percpu(pp->ports); err_clk: + clk_disable_unprepare(pp->clk_bus); clk_disable_unprepare(pp->clk); err_put_phy_node: of_node_put(phy_node); @@ -3742,6 +3749,7 @@ static int mvneta_remove(struct platform_device *pdev) struct mvneta_port *pp = netdev_priv(dev); unregister_netdev(dev); + clk_disable_unprepare(pp->clk_bus); clk_disable_unprepare(pp->clk); free_percpu(pp->ports); free_percpu(pp->stats); -- cgit v1.2.3 From 0a9c453eef65fed569757e21423400cfcd55e206 Mon Sep 17 00:00:00 2001 From: Teresa Remmet Date: Wed, 20 Jan 2016 13:40:35 +0100 Subject: net: phy: smsc: Fix disabling energy detect mode When the lan87xx_read_status function is getting called the energy detect mode is enabled again even if it has been disabled by device tree. Added private struct to check the energy detect status. Signed-off-by: Teresa Remmet Signed-off-by: David S. Miller --- drivers/net/phy/smsc.c | 54 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index e485f2653c82..2e21e9366f76 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -24,6 +24,10 @@ #include #include +struct smsc_phy_priv { + bool energy_enable; +}; + static int smsc_phy_config_intr(struct phy_device *phydev) { int rc = phy_write (phydev, MII_LAN83C185_IM, @@ -43,19 +47,14 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev) static int smsc_phy_config_init(struct phy_device *phydev) { - int __maybe_unused len; - struct device *dev __maybe_unused = &phydev->mdio.dev; - struct device_node *of_node __maybe_unused = dev->of_node; + struct smsc_phy_priv *priv = phydev->priv; + int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); - int enable_energy = 1; if (rc < 0) return rc; - if (of_find_property(of_node, "smsc,disable-energy-detect", &len)) - enable_energy = 0; - - if (enable_energy) { + if (priv->energy_enable) { /* Enable energy detect mode for this SMSC Transceivers */ rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc | MII_LAN83C185_EDPWRDOWN); @@ -110,10 +109,13 @@ static int lan911x_config_init(struct phy_device *phydev) */ static int lan87xx_read_status(struct phy_device *phydev) { + struct smsc_phy_priv *priv = phydev->priv; + int err = genphy_read_status(phydev); - int i; - if (!phydev->link) { + if (!phydev->link && priv->energy_enable) { + int i; + /* Disable EDPD to wake up PHY */ int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); if (rc < 0) @@ -149,6 +151,26 @@ static int lan87xx_read_status(struct phy_device *phydev) return err; } +static int smsc_phy_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct device_node *of_node = dev->of_node; + struct smsc_phy_priv *priv; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->energy_enable = true; + + if (of_property_read_bool(of_node, "smsc,disable-energy-detect")) + priv->energy_enable = false; + + phydev->priv = priv; + + return 0; +} + static struct phy_driver smsc_phy_driver[] = { { .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */ @@ -159,6 +181,8 @@ static struct phy_driver smsc_phy_driver[] = { | SUPPORTED_Asym_Pause), .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG, + .probe = smsc_phy_probe, + /* basic functions */ .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, @@ -180,6 +204,8 @@ static struct phy_driver smsc_phy_driver[] = { | SUPPORTED_Asym_Pause), .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG, + .probe = smsc_phy_probe, + /* basic functions */ .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, @@ -201,6 +227,8 @@ static struct phy_driver smsc_phy_driver[] = { | SUPPORTED_Asym_Pause), .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG, + .probe = smsc_phy_probe, + /* basic functions */ .config_aneg = genphy_config_aneg, .read_status = lan87xx_read_status, @@ -222,6 +250,8 @@ static struct phy_driver smsc_phy_driver[] = { | SUPPORTED_Asym_Pause), .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG, + .probe = smsc_phy_probe, + /* basic functions */ .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, @@ -242,6 +272,8 @@ static struct phy_driver smsc_phy_driver[] = { | SUPPORTED_Asym_Pause), .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG, + .probe = smsc_phy_probe, + /* basic functions */ .config_aneg = genphy_config_aneg, .read_status = lan87xx_read_status, @@ -263,6 +295,8 @@ static struct phy_driver smsc_phy_driver[] = { | SUPPORTED_Asym_Pause), .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG, + .probe = smsc_phy_probe, + /* basic functions */ .config_aneg = genphy_config_aneg, .read_status = lan87xx_read_status, -- cgit v1.2.3 From f0442df2156a2171e40f1643c60103e6333f4e7e Mon Sep 17 00:00:00 2001 From: John Keeping Date: Thu, 21 Jan 2016 18:19:34 +0000 Subject: drm/rockchip: respect CONFIG_DRM_FBDEV_EMULATION If DRM_FBDEV_EMULATION is not selected in the config then we can save a bit of space by not including the framebuffer code. Signed-off-by: John Keeping --- drivers/gpu/drm/rockchip/Makefile | 3 ++- drivers/gpu/drm/rockchip/rockchip_drm_fbdev.h | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile index a4e03bcde035..f6a809afceec 100644 --- a/drivers/gpu/drm/rockchip/Makefile +++ b/drivers/gpu/drm/rockchip/Makefile @@ -2,8 +2,9 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o rockchip_drm_fbdev.o \ +rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \ rockchip_drm_gem.o rockchip_drm_vop.o +rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.h b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.h index 50432e9b5b37..73718c5f5bbf 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.h @@ -15,7 +15,18 @@ #ifndef _ROCKCHIP_DRM_FBDEV_H #define _ROCKCHIP_DRM_FBDEV_H +#ifdef CONFIG_DRM_FBDEV_EMULATION int rockchip_drm_fbdev_init(struct drm_device *dev); void rockchip_drm_fbdev_fini(struct drm_device *dev); +#else +static inline int rockchip_drm_fbdev_init(struct drm_device *dev) +{ + return 0; +} + +static inline void rockchip_drm_fbdev_fini(struct drm_device *dev) +{ +} +#endif #endif /* _ROCKCHIP_DRM_FBDEV_H */ -- cgit v1.2.3 From 0106ef5146f9e89e4dc9354f308ecaddb9617310 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 20 Jan 2016 10:13:42 +0100 Subject: PM / domains: fix lockdep issue for all subdomains During genpd_poweron, genpd->lock is acquired recursively for each parent (master) domain, which are separate objects. This confuses lockdep, which considers every operation on genpd->lock as being done on the same lock class. This leads to the following false positive warning: ============================================= [ INFO: possible recursive locking detected ] 4.4.0-rc4-xu3s #32 Not tainted --------------------------------------------- swapper/0/1 is trying to acquire lock: (&genpd->lock){+.+...}, at: [] __genpd_poweron+0x64/0x108 but task is already holding lock: (&genpd->lock){+.+...}, at: [] genpd_dev_pm_attach+0x168/0x1b8 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&genpd->lock); lock(&genpd->lock); *** DEADLOCK *** May be due to missing lock nesting notation 3 locks held by swapper/0/1: #0: (&dev->mutex){......}, at: [] __driver_attach+0x48/0x98 #1: (&dev->mutex){......}, at: [] __driver_attach+0x58/0x98 #2: (&genpd->lock){+.+...}, at: [] genpd_dev_pm_attach+0x168/0x1b8 stack backtrace: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.4.0-rc4-xu3s #32 Hardware name: SAMSUNG EXYNOS (Flattened Device Tree) [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0x84/0xc4) [] (dump_stack) from [] (__lock_acquire+0x1f88/0x215c) [] (__lock_acquire) from [] (lock_acquire+0xa4/0xd0) [] (lock_acquire) from [] (mutex_lock_nested+0x70/0x4d4) [] (mutex_lock_nested) from [] (__genpd_poweron+0x64/0x108) [] (__genpd_poweron) from [] (genpd_dev_pm_attach+0x170/0x1b8) [] (genpd_dev_pm_attach) from [] (platform_drv_probe+0x2c/0xac) [] (platform_drv_probe) from [] (driver_probe_device+0x208/0x2fc) [] (driver_probe_device) from [] (__driver_attach+0x94/0x98) [] (__driver_attach) from [] (bus_for_each_dev+0x68/0x9c) [] (bus_for_each_dev) from [] (bus_add_driver+0x1a0/0x218) [] (bus_add_driver) from [] (driver_register+0x78/0xf8) [] (driver_register) from [] (exynos_drm_register_drivers+0x28/0x74) [] (exynos_drm_register_drivers) from [] (exynos_drm_init+0x6c/0xc4) [] (exynos_drm_init) from [] (do_one_initcall+0x90/0x1dc) [] (do_one_initcall) from [] (kernel_init_freeable+0x158/0x1f8) [] (kernel_init_freeable) from [] (kernel_init+0x8/0xe8) [] (kernel_init) from [] (ret_from_fork+0x14/0x24) This patch replaces mutex_lock with mutex_lock_nested() and uses recursion depth to annotate each genpd->lock operation with separate lockdep subclass. Reported-by: Anand Moon Signed-off-by: Marek Szyprowski Tested-by: Anand Moon Tested-by: Tobias Jakobi Acked-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index b80379012840..e02ddf65bc43 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -170,16 +170,15 @@ static void genpd_queue_power_off_work(struct generic_pm_domain *genpd) queue_work(pm_wq, &genpd->power_off_work); } -static int genpd_poweron(struct generic_pm_domain *genpd); - /** * __genpd_poweron - Restore power to a given PM domain and its masters. * @genpd: PM domain to power up. + * @depth: nesting count for lockdep. * * Restore power to @genpd and all of its masters so that it is possible to * resume a device belonging to it. */ -static int __genpd_poweron(struct generic_pm_domain *genpd) +static int __genpd_poweron(struct generic_pm_domain *genpd, unsigned int depth) { struct gpd_link *link; int ret = 0; @@ -194,11 +193,16 @@ static int __genpd_poweron(struct generic_pm_domain *genpd) * with it. */ list_for_each_entry(link, &genpd->slave_links, slave_node) { - genpd_sd_counter_inc(link->master); + struct generic_pm_domain *master = link->master; + + genpd_sd_counter_inc(master); + + mutex_lock_nested(&master->lock, depth + 1); + ret = __genpd_poweron(master, depth + 1); + mutex_unlock(&master->lock); - ret = genpd_poweron(link->master); if (ret) { - genpd_sd_counter_dec(link->master); + genpd_sd_counter_dec(master); goto err; } } @@ -230,11 +234,12 @@ static int genpd_poweron(struct generic_pm_domain *genpd) int ret; mutex_lock(&genpd->lock); - ret = __genpd_poweron(genpd); + ret = __genpd_poweron(genpd, 0); mutex_unlock(&genpd->lock); return ret; } + static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev) { return GENPD_DEV_CALLBACK(genpd, int, save_state, dev); @@ -482,7 +487,7 @@ static int pm_genpd_runtime_resume(struct device *dev) } mutex_lock(&genpd->lock); - ret = __genpd_poweron(genpd); + ret = __genpd_poweron(genpd, 0); mutex_unlock(&genpd->lock); if (ret) -- cgit v1.2.3 From 6f16886b7c050c934305b1f285c3458ff1b6e4e4 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 21 Jan 2016 11:19:29 +0000 Subject: cpuidle: fix fallback mechanism for suspend to idle in absence of enter_freeze Commit 51164251f5c3 "sched / idle: Drop default_idle_call() fallback from call_cpuidle()" made find_deepest_state() return non-negative value and check all the states with index > 0. Also as a result, find_deepest_state() returns 0 even when enter_freeze callbacks are not implemented and enter_freeze_proper() is called which ends up crashing the kernel. This patch updates the check for index > 0 in cpuidle_enter_freeze and cpuidle_idle_call(when idle_should_freeze is true) to restore the suspend-to-idle functionality in absence of enter_freeze callback. Fixes: 51164251f5c3 "sched / idle: Drop default_idle_call() fallback from call_cpuidle()" Signed-off-by: Sudeep Holla Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle.c | 2 +- kernel/sched/idle.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 046423b0c5ca..f996efc56605 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -153,7 +153,7 @@ int cpuidle_enter_freeze(struct cpuidle_driver *drv, struct cpuidle_device *dev) * be frozen safely. */ index = find_deepest_state(drv, dev, UINT_MAX, 0, true); - if (index >= 0) + if (index > 0) enter_freeze_proper(drv, dev, index); return index; diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index 34852ee70d54..30f7b6ad3920 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c @@ -162,7 +162,7 @@ static void cpuidle_idle_call(void) */ if (idle_should_freeze()) { entered_state = cpuidle_enter_freeze(drv, dev); - if (entered_state >= 0) { + if (entered_state > 0) { local_irq_enable(); goto exit_idle; } -- cgit v1.2.3 From 4b5ece24ce564176f8ad786ad02b681a373bc615 Mon Sep 17 00:00:00 2001 From: Eric Huang Date: Tue, 19 Jan 2016 14:28:56 -0500 Subject: drm/amd/amdgpu: Improve amdgpu_dpm* macros to avoid unexpected result (v2) The two macros returns are values which probably are used in the expression of calculation. Without the brackets the result of the expression may be wrong. v2: agd: squash both patches together Reviewed-by: Alex Deucher Signed-off-by: Eric Huang --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 44 ++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 313b0cc8d676..82edf95b7740 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -2278,60 +2278,60 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_dpm_enable_bapm(adev, e) (adev)->pm.funcs->enable_bapm((adev), (e)) #define amdgpu_dpm_get_temperature(adev) \ - (adev)->pp_enabled ? \ + ((adev)->pp_enabled ? \ (adev)->powerplay.pp_funcs->get_temperature((adev)->powerplay.pp_handle) : \ - (adev)->pm.funcs->get_temperature((adev)) + (adev)->pm.funcs->get_temperature((adev))) #define amdgpu_dpm_set_fan_control_mode(adev, m) \ - (adev)->pp_enabled ? \ + ((adev)->pp_enabled ? \ (adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m)) : \ - (adev)->pm.funcs->set_fan_control_mode((adev), (m)) + (adev)->pm.funcs->set_fan_control_mode((adev), (m))) #define amdgpu_dpm_get_fan_control_mode(adev) \ - (adev)->pp_enabled ? \ + ((adev)->pp_enabled ? \ (adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle) : \ - (adev)->pm.funcs->get_fan_control_mode((adev)) + (adev)->pm.funcs->get_fan_control_mode((adev))) #define amdgpu_dpm_set_fan_speed_percent(adev, s) \ - (adev)->pp_enabled ? \ + ((adev)->pp_enabled ? \ (adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ - (adev)->pm.funcs->set_fan_speed_percent((adev), (s)) + (adev)->pm.funcs->set_fan_speed_percent((adev), (s))) #define amdgpu_dpm_get_fan_speed_percent(adev, s) \ - (adev)->pp_enabled ? \ + ((adev)->pp_enabled ? \ (adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ - (adev)->pm.funcs->get_fan_speed_percent((adev), (s)) + (adev)->pm.funcs->get_fan_speed_percent((adev), (s))) #define amdgpu_dpm_get_sclk(adev, l) \ - (adev)->pp_enabled ? \ + ((adev)->pp_enabled ? \ (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l)) : \ - (adev)->pm.funcs->get_sclk((adev), (l)) + (adev)->pm.funcs->get_sclk((adev), (l))) #define amdgpu_dpm_get_mclk(adev, l) \ - (adev)->pp_enabled ? \ + ((adev)->pp_enabled ? \ (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (l)) : \ - (adev)->pm.funcs->get_mclk((adev), (l)) + (adev)->pm.funcs->get_mclk((adev), (l))) #define amdgpu_dpm_force_performance_level(adev, l) \ - (adev)->pp_enabled ? \ + ((adev)->pp_enabled ? \ (adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l)) : \ - (adev)->pm.funcs->force_performance_level((adev), (l)) + (adev)->pm.funcs->force_performance_level((adev), (l))) #define amdgpu_dpm_powergate_uvd(adev, g) \ - (adev)->pp_enabled ? \ + ((adev)->pp_enabled ? \ (adev)->powerplay.pp_funcs->powergate_uvd((adev)->powerplay.pp_handle, (g)) : \ - (adev)->pm.funcs->powergate_uvd((adev), (g)) + (adev)->pm.funcs->powergate_uvd((adev), (g))) #define amdgpu_dpm_powergate_vce(adev, g) \ - (adev)->pp_enabled ? \ + ((adev)->pp_enabled ? \ (adev)->powerplay.pp_funcs->powergate_vce((adev)->powerplay.pp_handle, (g)) : \ - (adev)->pm.funcs->powergate_vce((adev), (g)) + (adev)->pm.funcs->powergate_vce((adev), (g))) #define amdgpu_dpm_debugfs_print_current_performance_level(adev, m) \ - (adev)->pp_enabled ? \ + ((adev)->pp_enabled ? \ (adev)->powerplay.pp_funcs->print_current_performance_level((adev)->powerplay.pp_handle, (m)) : \ - (adev)->pm.funcs->debugfs_print_current_performance_level((adev), (m)) + (adev)->pm.funcs->debugfs_print_current_performance_level((adev), (m))) #define amdgpu_dpm_get_current_power_state(adev) \ (adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle) -- cgit v1.2.3 From 78d0e182b6c1f5336f6e8cbb197f403276dabc7f Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 19 Jan 2016 12:48:14 +0100 Subject: drm/amdgpu: fix amdgpu_bo_pin_restricted VRAM placing v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We could pin BOs into invisible VRAM otherwise. v2: make logic more readable as suggested by Michel Cc: stable@vger.kernel.org Signed-off-by: Christian König Reviewed-by: Alex Deucher (v1) Reviewed-by: Rex Zhu (v1) Reviewed-by: Michel Dänzer --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index c3ce103b6a33..a2a16acee34d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -399,7 +399,8 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, } if (fpfn > bo->placements[i].fpfn) bo->placements[i].fpfn = fpfn; - if (lpfn && lpfn < bo->placements[i].lpfn) + if (!bo->placements[i].lpfn || + (lpfn && lpfn < bo->placements[i].lpfn)) bo->placements[i].lpfn = lpfn; bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; } -- cgit v1.2.3 From 9441f964f8e39374ab175e0a8fe870e1a2f02af1 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 20 Jan 2016 12:15:09 -0500 Subject: drm/amdgpu: add a message to indicate when powerplay is enabled (v2) Makes it clear to the user which power management path is in use. v2: make consistent with dpm Reviewed-by: Rex Zhu Reviewed-by: Tom St Denis Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 8f5d5edcf193..aa67244a77ae 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -64,6 +64,11 @@ static int pp_sw_init(void *handle) if (ret == 0) ret = hwmgr->hwmgr_func->backend_init(hwmgr); + if (ret) + printk("amdgpu: powerplay initialization failed\n"); + else + printk("amdgpu: powerplay initialized\n"); + return ret; } -- cgit v1.2.3 From cc78eb22885bba64445cde438ba098de0104920f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 22 Jan 2016 00:13:15 -0500 Subject: drm/radeon: properly byte swap vce firmware setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Firmware is LE. Need to properly byteswap some of the fields so they are interpreted correctly by the driver on BE systems. Reviewed-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/vce_v1_0.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/vce_v1_0.c b/drivers/gpu/drm/radeon/vce_v1_0.c index 07a0d378e122..a01efe39a820 100644 --- a/drivers/gpu/drm/radeon/vce_v1_0.c +++ b/drivers/gpu/drm/radeon/vce_v1_0.c @@ -178,12 +178,12 @@ int vce_v1_0_load_fw(struct radeon_device *rdev, uint32_t *data) return -EINVAL; } - for (i = 0; i < sign->num; ++i) { - if (sign->val[i].chip_id == chip_id) + for (i = 0; i < le32_to_cpu(sign->num); ++i) { + if (le32_to_cpu(sign->val[i].chip_id) == chip_id) break; } - if (i == sign->num) + if (i == le32_to_cpu(sign->num)) return -EINVAL; data += (256 - 64) / 4; @@ -191,18 +191,18 @@ int vce_v1_0_load_fw(struct radeon_device *rdev, uint32_t *data) data[1] = sign->val[i].nonce[1]; data[2] = sign->val[i].nonce[2]; data[3] = sign->val[i].nonce[3]; - data[4] = sign->len + 64; + data[4] = cpu_to_le32(le32_to_cpu(sign->len) + 64); memset(&data[5], 0, 44); memcpy(&data[16], &sign[1], rdev->vce_fw->size - sizeof(*sign)); - data += data[4] / 4; + data += le32_to_cpu(data[4]) / 4; data[0] = sign->val[i].sigval[0]; data[1] = sign->val[i].sigval[1]; data[2] = sign->val[i].sigval[2]; data[3] = sign->val[i].sigval[3]; - rdev->vce.keyselect = sign->val[i].keyselect; + rdev->vce.keyselect = le32_to_cpu(sign->val[i].keyselect); return 0; } -- cgit v1.2.3 From f8efca2f1783050368c71e978ee32d3aa692637b Mon Sep 17 00:00:00 2001 From: Gao Pan Date: Mon, 18 Jan 2016 15:44:01 +0800 Subject: spi: imx: fix spi resource leak with dma transfer In spi_imx_dma_transfer(), when desc_rx = dmaengine_prep_slave_sg() fails, the context goes to label no_dma and then return. However, the memory allocated for desc_tx has not been freed yet, which leads to resource leak. Signed-off-by: Gao Pan Reviewed-by: Fugang Duan Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index d98c33cb64f9..6a4ff27f4357 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -929,7 +929,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, tx->sgl, tx->nents, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_tx) - goto no_dma; + goto tx_nodma; desc_tx->callback = spi_imx_dma_tx_callback; desc_tx->callback_param = (void *)spi_imx; @@ -941,7 +941,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, rx->sgl, rx->nents, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_rx) - goto no_dma; + goto rx_nodma; desc_rx->callback = spi_imx_dma_rx_callback; desc_rx->callback_param = (void *)spi_imx; @@ -1008,7 +1008,9 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, return ret; -no_dma: +rx_nodma: + dmaengine_terminate_all(master->dma_tx); +tx_nodma: pr_warn_once("%s %s: DMA not available, falling back to PIO\n", dev_driver_string(&master->dev), dev_name(&master->dev)); -- cgit v1.2.3 From 5cfa1e4e0deced0cccedb4b30facb8a8e68e209b Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Fri, 22 Jan 2016 18:58:26 +0800 Subject: spi/fsl-espi: Correct the maximum transaction length The maximum length during one transcation is 64KiB. Signed-off-by: Hou Zhiqiang Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 7fd6a4c009d2..7cb0c1921495 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -84,7 +84,7 @@ struct fsl_espi_transfer { /* SPCOM register values */ #define SPCOM_CS(x) ((x) << 30) #define SPCOM_TRANLEN(x) ((x) << 0) -#define SPCOM_TRANLEN_MAX 0xFFFF /* Max transaction length */ +#define SPCOM_TRANLEN_MAX 0x10000 /* Max transaction length */ #define AUTOSUSPEND_TIMEOUT 2000 @@ -233,7 +233,7 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) reinit_completion(&mpc8xxx_spi->done); /* Set SPCOM[CS] and SPCOM[TRANLEN] field */ - if ((t->len - 1) > SPCOM_TRANLEN_MAX) { + if (t->len > SPCOM_TRANLEN_MAX) { dev_err(mpc8xxx_spi->dev, "Transaction length (%d)" " beyond the SPCOM[TRANLEN] field\n", t->len); return -EINVAL; -- cgit v1.2.3 From 41f2d9905646b1cd4be5852b273c06b6a6d23a80 Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 21 Jan 2016 12:56:52 +0100 Subject: drm/amdgpu: fix next_rptr handling for debugfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That somehow got lost. Signed-off-by: Christian König Reviewed-by: Chunming Zhou Acked-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 78e9b0f14661..d1f234dd2126 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -487,7 +487,7 @@ static int amdgpu_debugfs_ring_info(struct seq_file *m, void *data) seq_printf(m, "rptr: 0x%08x [%5d]\n", rptr, rptr); - rptr_next = ~0; + rptr_next = le32_to_cpu(*ring->next_rptr_cpu_addr); seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr); -- cgit v1.2.3 From 23819f2eaab87080b0190ed94a0728fc8ea84711 Mon Sep 17 00:00:00 2001 From: Christophe Jaillet Date: Sun, 10 Jan 2016 07:46:39 +0100 Subject: mtd: nand: mpc5121: use 'of_machine_is_compatible' to simplify code The current code is the same as 'of_machine_is_compatible'. So use it in order to remove a few lines of code and to be more consistent with other parts of the kernel. Signed-off-by: Christophe JAILLET Reviewed-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/mpc5121_nfc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 6b93e899d4e9..5d7843ffff6a 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c @@ -626,7 +626,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd) static int mpc5121_nfc_probe(struct platform_device *op) { - struct device_node *rootnode, *dn = op->dev.of_node; + struct device_node *dn = op->dev.of_node; struct clk *clk; struct device *dev = &op->dev; struct mpc5121_nfc_prv *prv; @@ -712,18 +712,15 @@ static int mpc5121_nfc_probe(struct platform_device *op) chip->ecc.mode = NAND_ECC_SOFT; /* Support external chip-select logic on ADS5121 board */ - rootnode = of_find_node_by_path("/"); - if (of_device_is_compatible(rootnode, "fsl,mpc5121ads")) { + if (of_machine_is_compatible("fsl,mpc5121ads")) { retval = ads5121_chipselect_init(mtd); if (retval) { dev_err(dev, "Chipselect init error!\n"); - of_node_put(rootnode); return retval; } chip->select_chip = ads5121_select_chip; } - of_node_put(rootnode); /* Enable NFC clock */ clk = devm_clk_get(dev, "ipg"); -- cgit v1.2.3 From 8ebc5637154dc58378c85ea7d0047fbc72cfc2d7 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Wed, 2 Dec 2015 12:01:06 +0100 Subject: mtd: nand: add NAND_NEED_SCRAMBLING flag to the H27UCG8T2ATR-BC definition The H27UCG8T2ATR-BC requires an external data scrambler. Reflect this constraint in the nand_flash_ids definition. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_ids.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index a8804a3da076..ccc05f5b2695 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -50,8 +50,8 @@ struct nand_flash_dev nand_flash_ids[] = { SZ_16K, SZ_8K, SZ_4M, 0, 6, 1280, NAND_ECC_INFO(40, SZ_1K) }, {"H27UCG8T2ATR-BC 64G 3.3V 8-bit", { .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} }, - SZ_8K, SZ_8K, SZ_2M, 0, 6, 640, NAND_ECC_INFO(40, SZ_1K), - 4 }, + SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640, + NAND_ECC_INFO(40, SZ_1K), 4 }, LEGACY_ID_NAND("NAND 4MiB 5V 8-bit", 0x6B, 4, SZ_8K, SP_OPTIONS), LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS), -- cgit v1.2.3 From 4be4e03efc7f45ec002e8eddc83c22f80fed392c Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Wed, 2 Dec 2015 12:01:07 +0100 Subject: mtd: nand: sunxi: add randomizer support Add support for the randomizer engine available in Allwinner's NFC IP. Randomization is useful to support modern NAND chips which are sensitive to repeated patterns. On such NANDs you might experience an unexpectedly high number of bitflips when you repeat the same pattern all over a given NAND block. Randomizing input data mitigate this problem by avoiding such repeated patterns. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/sunxi_nand.c | 287 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 261 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 51e10a35fe08..5f700719d5c2 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -60,6 +60,7 @@ #define NFC_REG_ECC_ERR_CNT(x) ((0x0040 + (x)) & ~0x3) #define NFC_REG_USER_DATA(x) (0x0050 + ((x) * 4)) #define NFC_REG_SPARE_AREA 0x00A0 +#define NFC_REG_PAT_ID 0x00A4 #define NFC_RAM0_BASE 0x0400 #define NFC_RAM1_BASE 0x0800 @@ -538,6 +539,174 @@ static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); } +/* These seed values have been extracted from Allwinner's BSP */ +static const u16 sunxi_nfc_randomizer_page_seeds[] = { + 0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72, + 0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436, + 0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d, + 0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130, + 0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56, + 0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55, + 0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb, + 0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17, + 0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62, + 0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064, + 0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126, + 0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e, + 0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3, + 0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b, + 0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d, + 0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db, +}; + +/* + * sunxi_nfc_randomizer_ecc512_seeds and sunxi_nfc_randomizer_ecc1024_seeds + * have been generated using + * sunxi_nfc_randomizer_step(seed, (step_size * 8) + 15), which is what + * the randomizer engine does internally before de/scrambling OOB data. + * + * Those tables are statically defined to avoid calculating randomizer state + * at runtime. + */ +static const u16 sunxi_nfc_randomizer_ecc512_seeds[] = { + 0x3346, 0x367f, 0x1f18, 0x769a, 0x4f64, 0x068c, 0x2ef1, 0x6b64, + 0x28a9, 0x15d7, 0x30f8, 0x3659, 0x53db, 0x7c5f, 0x71d4, 0x4409, + 0x26eb, 0x03cc, 0x655d, 0x47d4, 0x4daa, 0x0877, 0x712d, 0x3617, + 0x3264, 0x49aa, 0x7f9e, 0x588e, 0x4fbc, 0x7176, 0x7f91, 0x6c6d, + 0x4b95, 0x5fb7, 0x3844, 0x4037, 0x0184, 0x081b, 0x0ee8, 0x5b91, + 0x293d, 0x1f71, 0x0e6f, 0x402b, 0x5122, 0x1e52, 0x22be, 0x3d2d, + 0x75bc, 0x7c60, 0x6291, 0x1a2f, 0x61d4, 0x74aa, 0x4140, 0x29ab, + 0x472d, 0x2852, 0x017e, 0x15e8, 0x5ec2, 0x17cf, 0x7d0f, 0x06b8, + 0x117a, 0x6b94, 0x789b, 0x3126, 0x6ac5, 0x5be7, 0x150f, 0x51f8, + 0x7889, 0x0aa5, 0x663d, 0x77e8, 0x0b87, 0x3dcb, 0x360d, 0x218b, + 0x512f, 0x7dc9, 0x6a4d, 0x630a, 0x3547, 0x1dd2, 0x5aea, 0x69a5, + 0x7bfa, 0x5e4f, 0x1519, 0x6430, 0x3a0e, 0x5eb3, 0x5425, 0x0c7a, + 0x5540, 0x3670, 0x63c1, 0x31e9, 0x5a39, 0x2de7, 0x5979, 0x2891, + 0x1562, 0x014b, 0x5b05, 0x2756, 0x5a34, 0x13aa, 0x6cb5, 0x2c36, + 0x5e72, 0x1306, 0x0861, 0x15ef, 0x1ee8, 0x5a37, 0x7ac4, 0x45dd, + 0x44c4, 0x7266, 0x2f41, 0x3ccc, 0x045e, 0x7d40, 0x7c66, 0x0fa0, +}; + +static const u16 sunxi_nfc_randomizer_ecc1024_seeds[] = { + 0x2cf5, 0x35f1, 0x63a4, 0x5274, 0x2bd2, 0x778b, 0x7285, 0x32b6, + 0x6a5c, 0x70d6, 0x757d, 0x6769, 0x5375, 0x1e81, 0x0cf3, 0x3982, + 0x6787, 0x042a, 0x6c49, 0x1925, 0x56a8, 0x40a9, 0x063e, 0x7bd9, + 0x4dbf, 0x55ec, 0x672e, 0x7334, 0x5185, 0x4d00, 0x232a, 0x7e07, + 0x445d, 0x6b92, 0x528f, 0x4255, 0x53ba, 0x7d82, 0x2a2e, 0x3a4e, + 0x75eb, 0x450c, 0x6844, 0x1b5d, 0x581a, 0x4cc6, 0x0379, 0x37b2, + 0x419f, 0x0e92, 0x6b27, 0x5624, 0x01e3, 0x07c1, 0x44a5, 0x130c, + 0x13e8, 0x5910, 0x0876, 0x60c5, 0x54e3, 0x5b7f, 0x2269, 0x509f, + 0x7665, 0x36fd, 0x3e9a, 0x0579, 0x6295, 0x14ef, 0x0a81, 0x1bcc, + 0x4b16, 0x64db, 0x0514, 0x4f07, 0x0591, 0x3576, 0x6853, 0x0d9e, + 0x259f, 0x38b7, 0x64fb, 0x3094, 0x4693, 0x6ddd, 0x29bb, 0x0bc8, + 0x3f47, 0x490e, 0x0c0e, 0x7933, 0x3c9e, 0x5840, 0x398d, 0x3e68, + 0x4af1, 0x71f5, 0x57cf, 0x1121, 0x64eb, 0x3579, 0x15ac, 0x584d, + 0x5f2a, 0x47e2, 0x6528, 0x6eac, 0x196e, 0x6b96, 0x0450, 0x0179, + 0x609c, 0x06e1, 0x4626, 0x42c7, 0x273e, 0x486f, 0x0705, 0x1601, + 0x145b, 0x407e, 0x062b, 0x57a5, 0x53f9, 0x5659, 0x4410, 0x3ccd, +}; + +static u16 sunxi_nfc_randomizer_step(u16 state, int count) +{ + state &= 0x7fff; + + /* + * This loop is just a simple implementation of a Fibonacci LFSR using + * the x16 + x15 + 1 polynomial. + */ + while (count--) + state = ((state >> 1) | + (((state ^ (state >> 1)) & 1) << 14)) & 0x7fff; + + return state; +} + +static u16 sunxi_nfc_randomizer_state(struct mtd_info *mtd, int page, bool ecc) +{ + const u16 *seeds = sunxi_nfc_randomizer_page_seeds; + int mod = mtd->erasesize / mtd->writesize; + + if (mod > ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds)) + mod = ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds); + + if (ecc) { + if (mtd->ecc_step_size == 512) + seeds = sunxi_nfc_randomizer_ecc512_seeds; + else + seeds = sunxi_nfc_randomizer_ecc1024_seeds; + } + + return seeds[page % mod]; +} + +static void sunxi_nfc_randomizer_config(struct mtd_info *mtd, + int page, bool ecc) +{ + struct nand_chip *nand = mtd->priv; + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + u32 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL); + u16 state; + + if (!(nand->options & NAND_NEED_SCRAMBLING)) + return; + + ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL); + state = sunxi_nfc_randomizer_state(mtd, page, ecc); + ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_SEED_MSK; + writel(ecc_ctl | NFC_RANDOM_SEED(state), nfc->regs + NFC_REG_ECC_CTL); +} + +static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd) +{ + struct nand_chip *nand = mtd->priv; + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + + if (!(nand->options & NAND_NEED_SCRAMBLING)) + return; + + writel(readl(nfc->regs + NFC_REG_ECC_CTL) | NFC_RANDOM_EN, + nfc->regs + NFC_REG_ECC_CTL); +} + +static void sunxi_nfc_randomizer_disable(struct mtd_info *mtd) +{ + struct nand_chip *nand = mtd->priv; + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + + if (!(nand->options & NAND_NEED_SCRAMBLING)) + return; + + writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_EN, + nfc->regs + NFC_REG_ECC_CTL); +} + +static void sunxi_nfc_randomize_bbm(struct mtd_info *mtd, int page, u8 *bbm) +{ + u16 state = sunxi_nfc_randomizer_state(mtd, page, true); + + bbm[0] ^= state; + bbm[1] ^= sunxi_nfc_randomizer_step(state, 8); +} + +static void sunxi_nfc_randomizer_write_buf(struct mtd_info *mtd, + const uint8_t *buf, int len, + bool ecc, int page) +{ + sunxi_nfc_randomizer_config(mtd, page, ecc); + sunxi_nfc_randomizer_enable(mtd); + sunxi_nfc_write_buf(mtd, buf, len); + sunxi_nfc_randomizer_disable(mtd); +} + +static void sunxi_nfc_randomizer_read_buf(struct mtd_info *mtd, uint8_t *buf, + int len, bool ecc, int page) +{ + sunxi_nfc_randomizer_config(mtd, page, ecc); + sunxi_nfc_randomizer_enable(mtd); + sunxi_nfc_read_buf(mtd, buf, len); + sunxi_nfc_randomizer_disable(mtd); +} + static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd) { struct nand_chip *nand = mtd_to_nand(mtd); @@ -574,18 +743,20 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, u8 *data, int data_off, u8 *oob, int oob_off, int *cur_off, - unsigned int *max_bitflips) + unsigned int *max_bitflips, + bool bbm, int page) { struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct nand_ecc_ctrl *ecc = &nand->ecc; + int raw_mode = 0; u32 status; int ret; if (*cur_off != data_off) nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1); - sunxi_nfc_read_buf(mtd, NULL, ecc->size); + sunxi_nfc_randomizer_read_buf(mtd, NULL, ecc->size, false, page); if (data_off + ecc->size != oob_off) nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); @@ -594,25 +765,54 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, if (ret) return ret; + sunxi_nfc_randomizer_enable(mtd); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, nfc->regs + NFC_REG_CMD); ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); + sunxi_nfc_randomizer_disable(mtd); if (ret) return ret; + *cur_off = oob_off + ecc->bytes + 4; + status = readl(nfc->regs + NFC_REG_ECC_ST); + if (status & NFC_ECC_PAT_FOUND(0)) { + u8 pattern = 0xff; + + if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1))) + pattern = 0x0; + + memset(data, pattern, ecc->size); + memset(oob, pattern, ecc->bytes + 4); + + return 1; + } + ret = NFC_ECC_ERR_CNT(0, readl(nfc->regs + NFC_REG_ECC_ERR_CNT(0))); memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); - sunxi_nfc_read_buf(mtd, oob, ecc->bytes + 4); + sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4, true, page); if (status & NFC_ECC_ERR(0)) { + /* + * Re-read the data with the randomizer disabled to identify + * bitflips in erased pages. + */ + if (nand->options & NAND_NEED_SCRAMBLING) { + nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1); + nand->read_buf(mtd, data, ecc->size); + nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); + nand->read_buf(mtd, oob, ecc->bytes + 4); + } + ret = nand_check_erased_ecc_chunk(data, ecc->size, oob, ecc->bytes + 4, NULL, 0, ecc->strength); + if (ret >= 0) + raw_mode = 1; } else { /* * The engine protects 4 bytes of OOB data per chunk. @@ -620,6 +820,10 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, */ sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(0)), oob); + + /* De-randomize the Bad Block Marker. */ + if (bbm && nand->options & NAND_NEED_SCRAMBLING) + sunxi_nfc_randomize_bbm(mtd, page, oob); } if (ret < 0) { @@ -629,13 +833,12 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, *max_bitflips = max_t(unsigned int, *max_bitflips, ret); } - *cur_off = oob_off + ecc->bytes + 4; - - return 0; + return raw_mode; } static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd, - u8 *oob, int *cur_off) + u8 *oob, int *cur_off, + bool randomize, int page) { struct nand_chip *nand = mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc = &nand->ecc; @@ -649,7 +852,11 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd, nand->cmdfunc(mtd, NAND_CMD_RNDOUT, offset + mtd->writesize, -1); - sunxi_nfc_read_buf(mtd, oob + offset, len); + if (!randomize) + sunxi_nfc_read_buf(mtd, oob + offset, len); + else + sunxi_nfc_randomizer_read_buf(mtd, oob + offset, len, + false, page); *cur_off = mtd->oobsize + mtd->writesize; } @@ -662,7 +869,8 @@ static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf) static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, const u8 *data, int data_off, const u8 *oob, int oob_off, - int *cur_off) + int *cur_off, bool bbm, + int page) { struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); @@ -672,11 +880,20 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, if (data_off != *cur_off) nand->cmdfunc(mtd, NAND_CMD_RNDIN, data_off, -1); - sunxi_nfc_write_buf(mtd, data, ecc->size); + sunxi_nfc_randomizer_write_buf(mtd, data, ecc->size, false, page); /* Fill OOB data in */ - writel(sunxi_nfc_buf_to_user_data(oob), - nfc->regs + NFC_REG_USER_DATA(0)); + if ((nand->options & NAND_NEED_SCRAMBLING) && bbm) { + u8 user_data[4]; + + memcpy(user_data, oob, 4); + sunxi_nfc_randomize_bbm(mtd, page, user_data); + writel(sunxi_nfc_buf_to_user_data(user_data), + nfc->regs + NFC_REG_USER_DATA(0)); + } else { + writel(sunxi_nfc_buf_to_user_data(oob), + nfc->regs + NFC_REG_USER_DATA(0)); + } if (data_off + ecc->size != oob_off) nand->cmdfunc(mtd, NAND_CMD_RNDIN, oob_off, -1); @@ -685,11 +902,13 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, if (ret) return ret; + sunxi_nfc_randomizer_enable(mtd); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ACCESS_DIR | NFC_ECC_OP, nfc->regs + NFC_REG_CMD); ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); + sunxi_nfc_randomizer_disable(mtd); if (ret) return ret; @@ -699,7 +918,8 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, } static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd, - u8 *oob, int *cur_off) + u8 *oob, int *cur_off, + int page) { struct nand_chip *nand = mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc = &nand->ecc; @@ -713,7 +933,7 @@ static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd, nand->cmdfunc(mtd, NAND_CMD_RNDIN, offset + mtd->writesize, -1); - sunxi_nfc_write_buf(mtd, oob + offset, len); + sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page); *cur_off = mtd->oobsize + mtd->writesize; } @@ -725,6 +945,7 @@ static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc = &chip->ecc; unsigned int max_bitflips = 0; int ret, i, cur_off = 0; + bool raw_mode = false; sunxi_nfc_hw_ecc_enable(mtd); @@ -736,13 +957,17 @@ static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd, ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob, oob_off + mtd->writesize, - &cur_off, &max_bitflips); - if (ret) + &cur_off, &max_bitflips, + !i, page); + if (ret < 0) return ret; + else if (ret) + raw_mode = true; } if (oob_required) - sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off); + sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off, + !raw_mode, page); sunxi_nfc_hw_ecc_disable(mtd); @@ -767,13 +992,14 @@ static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd, ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob, oob_off + mtd->writesize, - &cur_off); + &cur_off, !i, page); if (ret) return ret; } - if (oob_required) - sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi, &cur_off); + if (oob_required || (chip->options & NAND_NEED_SCRAMBLING)) + sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi, + &cur_off, page); sunxi_nfc_hw_ecc_disable(mtd); @@ -788,6 +1014,7 @@ static int sunxi_nfc_hw_syndrome_ecc_read_page(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc = &chip->ecc; unsigned int max_bitflips = 0; int ret, i, cur_off = 0; + bool raw_mode = false; sunxi_nfc_hw_ecc_enable(mtd); @@ -799,13 +1026,16 @@ static int sunxi_nfc_hw_syndrome_ecc_read_page(struct mtd_info *mtd, ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob, oob_off, &cur_off, - &max_bitflips); - if (ret) + &max_bitflips, !i, page); + if (ret < 0) return ret; + else if (ret) + raw_mode = true; } if (oob_required) - sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off); + sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off, + !raw_mode, page); sunxi_nfc_hw_ecc_disable(mtd); @@ -829,13 +1059,15 @@ static int sunxi_nfc_hw_syndrome_ecc_write_page(struct mtd_info *mtd, const u8 *oob = chip->oob_poi + (i * (ecc->bytes + 4)); ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, - oob, oob_off, &cur_off); + oob, oob_off, &cur_off, + false, page); if (ret) return ret; } - if (oob_required) - sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi, &cur_off); + if (oob_required || (chip->options & NAND_NEED_SCRAMBLING)) + sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi, + &cur_off, page); sunxi_nfc_hw_ecc_disable(mtd); @@ -1345,6 +1577,9 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, if (nand->bbt_options & NAND_BBT_USE_FLASH) nand->bbt_options |= NAND_BBT_NO_OOB; + if (nand->options & NAND_NEED_SCRAMBLING) + nand->options |= NAND_NO_SUBPAGE_WRITE; + ret = sunxi_nand_chip_init_timings(chip, np); if (ret) { dev_err(dev, "could not configure chip timings: %d\n", ret); -- cgit v1.2.3 From b186b4dcb79b1914c3dadb27ac72dafaa4267998 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 22 Jan 2016 11:41:05 +0100 Subject: ACPI: Revert "ACPI / video: Add Dell Inspiron 5737 to the blacklist" The quirk to get "acpi_backlight=vendor" behavior by default on the Dell Inspiron 5737 was added before we started doing "acpi_backlight=native" by default on Win8 ready machines. Since we now avoid using acpi-video as backlight driver on these machines by default (using the native driver instead) we no longer need this quirk. Moreover the vendor driver does not work after a suspend/resume where as the native driver does. This reverts commit 08a56226d847 (ACPI / video: Add Dell Inspiron 5737 to the blacklist). Link: https://bugzilla.kernel.org/show_bug.cgi?id=111061 Cc: 3.19+ # 3.19+ Reported-and-tested-by: erusan@gmail.com Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video_detect.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 90e2d54be526..1316ddd92fac 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -135,14 +135,6 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"), }, }, - { - .callback = video_detect_force_vendor, - .ident = "Dell Inspiron 5737", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5737"), - }, - }, /* * These models have a working acpi_video backlight control, and using -- cgit v1.2.3 From d7bdcc3f57eef075122906e3f38abe2a06868750 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Mon, 18 Jan 2016 09:41:55 +0100 Subject: iio:adc:at91-sama5d2: fix vref_uv type vref_uv has to be an int. Signed-off-by: Ludovic Desroches Reported-by: Julia Lawall Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index ecb2d90c9c06..f2d8bd5deac9 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -171,7 +171,7 @@ struct at91_adc_state { struct clk *per_clk; struct regulator *reg; struct regulator *vref; - u32 vref_uv; + int vref_uv; const struct iio_chan_spec *chan; bool conversion_done; u32 conversion_value; -- cgit v1.2.3 From 61be8fde635bf4f7eecaf06af23e7db3c318596a Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Mon, 18 Jan 2016 09:41:56 +0100 Subject: iio:adc:at91-sama5d2: code cleanup Use var type for sizeof argument instead of the struct name. Signed-off-by: Ludovic Desroches Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index f2d8bd5deac9..dbee13ad33a3 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -353,8 +353,7 @@ static int at91_adc_probe(struct platform_device *pdev) struct resource *res; int ret; - indio_dev = devm_iio_device_alloc(&pdev->dev, - sizeof(struct at91_adc_state)); + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; -- cgit v1.2.3 From 4b04266abe3ea0c5c8f7a82b4d69f0f8e1e81b0a Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Sat, 16 Jan 2016 15:35:20 +0100 Subject: iio: mma8452: add freefall detection for Freescale's accelerometers This adds freefall event detection to the supported devices. It adds the in_accel_x&y&z_mag_falling_en iio event attribute, which activates freefall mode. In freefall mode, the current acceleration magnitude (AND combination of all axis values) is compared to the specified threshold. If it falls under the threshold (in_accel_mag_falling_value), the appropriate IIO event code is generated. This is what the sysfs "events" directory for these devices looks like after this change: -rw-r--r-- 4096 Oct 23 08:45 in_accel_mag_falling_period -rw-r--r-- 4096 Oct 23 08:45 in_accel_mag_falling_value -rw-r--r-- 4096 Oct 23 08:45 in_accel_mag_rising_period -rw-r--r-- 4096 Oct 23 08:45 in_accel_mag_rising_value -r--r--r-- 4096 Oct 23 08:45 in_accel_scale -rw-r--r-- 4096 Oct 23 08:45 in_accel_x&y&z_mag_falling_en -rw-r--r-- 4096 Oct 23 08:45 in_accel_x_mag_rising_en -rw-r--r-- 4096 Oct 23 08:45 in_accel_y_mag_rising_en -rw-r--r-- 4096 Oct 23 08:45 in_accel_z_mag_rising_en Signed-off-by: Martin Kepplinger Signed-off-by: Christoph Muellner Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma8452.c | 160 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 144 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index ccc632a7cf01..77b71c2dfd72 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -15,7 +15,7 @@ * * 7-bit I2C slave address 0x1c/0x1d (pin selectable) * - * TODO: orientation / freefall events, autosleep + * TODO: orientation events, autosleep */ #include @@ -416,6 +416,51 @@ fail: return ret; } +/* returns >0 if in freefall mode, 0 if not or <0 if an error occured */ +static int mma8452_freefall_mode_enabled(struct mma8452_data *data) +{ + int val; + const struct mma_chip_info *chip = data->chip_info; + + val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg); + if (val < 0) + return val; + + return !(val & MMA8452_FF_MT_CFG_OAE); +} + +static int mma8452_set_freefall_mode(struct mma8452_data *data, bool state) +{ + int val; + const struct mma_chip_info *chip = data->chip_info; + + if ((state && mma8452_freefall_mode_enabled(data)) || + (!state && !(mma8452_freefall_mode_enabled(data)))) + return 0; + + val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg); + if (val < 0) + return val; + + if (state) { + val |= BIT(idx_x + chip->ev_cfg_chan_shift); + val |= BIT(idx_y + chip->ev_cfg_chan_shift); + val |= BIT(idx_z + chip->ev_cfg_chan_shift); + val &= ~MMA8452_FF_MT_CFG_OAE; + } else { + val &= ~BIT(idx_x + chip->ev_cfg_chan_shift); + val &= ~BIT(idx_y + chip->ev_cfg_chan_shift); + val &= ~BIT(idx_z + chip->ev_cfg_chan_shift); + val |= MMA8452_FF_MT_CFG_OAE; + } + + val = mma8452_change_config(data, chip->ev_cfg, val); + if (val) + return val; + + return 0; +} + static int mma8452_set_hp_filter_frequency(struct mma8452_data *data, int val, int val2) { @@ -609,12 +654,22 @@ static int mma8452_read_event_config(struct iio_dev *indio_dev, const struct mma_chip_info *chip = data->chip_info; int ret; - ret = i2c_smbus_read_byte_data(data->client, - data->chip_info->ev_cfg); - if (ret < 0) - return ret; + switch (dir) { + case IIO_EV_DIR_FALLING: + return mma8452_freefall_mode_enabled(data); + case IIO_EV_DIR_RISING: + if (mma8452_freefall_mode_enabled(data)) + return 0; + + ret = i2c_smbus_read_byte_data(data->client, + data->chip_info->ev_cfg); + if (ret < 0) + return ret; - return !!(ret & BIT(chan->scan_index + chip->ev_cfg_chan_shift)); + return !!(ret & BIT(chan->scan_index + chip->ev_cfg_chan_shift)); + default: + return -EINVAL; + } } static int mma8452_write_event_config(struct iio_dev *indio_dev, @@ -627,19 +682,35 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev, const struct mma_chip_info *chip = data->chip_info; int val; - val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg); - if (val < 0) - return val; + switch (dir) { + case IIO_EV_DIR_FALLING: + return mma8452_set_freefall_mode(data, state); + case IIO_EV_DIR_RISING: + val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg); + if (val < 0) + return val; + + if (state) { + if (mma8452_freefall_mode_enabled(data)) { + val &= ~BIT(idx_x + chip->ev_cfg_chan_shift); + val &= ~BIT(idx_y + chip->ev_cfg_chan_shift); + val &= ~BIT(idx_z + chip->ev_cfg_chan_shift); + val |= MMA8452_FF_MT_CFG_OAE; + } + val |= BIT(chan->scan_index + chip->ev_cfg_chan_shift); + } else { + if (mma8452_freefall_mode_enabled(data)) + return 0; - if (state) - val |= BIT(chan->scan_index + chip->ev_cfg_chan_shift); - else - val &= ~BIT(chan->scan_index + chip->ev_cfg_chan_shift); + val &= ~BIT(chan->scan_index + chip->ev_cfg_chan_shift); + } - val |= chip->ev_cfg_ele; - val |= MMA8452_FF_MT_CFG_OAE; + val |= chip->ev_cfg_ele; - return mma8452_change_config(data, chip->ev_cfg, val); + return mma8452_change_config(data, chip->ev_cfg, val); + default: + return -EINVAL; + } } static void mma8452_transient_interrupt(struct iio_dev *indio_dev) @@ -652,6 +723,16 @@ static void mma8452_transient_interrupt(struct iio_dev *indio_dev) if (src < 0) return; + if (mma8452_freefall_mode_enabled(data)) { + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_AND_Y_AND_Z, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_FALLING), + ts); + return; + } + if (src & data->chip_info->ev_src_xe) iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X, @@ -745,6 +826,27 @@ static int mma8452_reg_access_dbg(struct iio_dev *indio_dev, return 0; } +static const struct iio_event_spec mma8452_freefall_event[] = { + { + .type = IIO_EV_TYPE_MAG, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD) | + BIT(IIO_EV_INFO_HIGH_PASS_FILTER_3DB) + }, +}; + +static const struct iio_event_spec mma8652_freefall_event[] = { + { + .type = IIO_EV_TYPE_MAG, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD) + }, +}; + static const struct iio_event_spec mma8452_transient_event[] = { { .type = IIO_EV_TYPE_MAG, @@ -781,6 +883,24 @@ static struct attribute_group mma8452_event_attribute_group = { .attrs = mma8452_event_attributes, }; +#define MMA8452_FREEFALL_CHANNEL(modifier) { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = modifier, \ + .scan_index = -1, \ + .event_spec = mma8452_freefall_event, \ + .num_event_specs = ARRAY_SIZE(mma8452_freefall_event), \ +} + +#define MMA8652_FREEFALL_CHANNEL(modifier) { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = modifier, \ + .scan_index = -1, \ + .event_spec = mma8652_freefall_event, \ + .num_event_specs = ARRAY_SIZE(mma8652_freefall_event), \ +} + #define MMA8452_CHANNEL(axis, idx, bits) { \ .type = IIO_ACCEL, \ .modified = 1, \ @@ -827,6 +947,7 @@ static const struct iio_chan_spec mma8452_channels[] = { MMA8452_CHANNEL(Y, idx_y, 12), MMA8452_CHANNEL(Z, idx_z, 12), IIO_CHAN_SOFT_TIMESTAMP(idx_ts), + MMA8452_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z), }; static const struct iio_chan_spec mma8453_channels[] = { @@ -834,6 +955,7 @@ static const struct iio_chan_spec mma8453_channels[] = { MMA8452_CHANNEL(Y, idx_y, 10), MMA8452_CHANNEL(Z, idx_z, 10), IIO_CHAN_SOFT_TIMESTAMP(idx_ts), + MMA8452_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z), }; static const struct iio_chan_spec mma8652_channels[] = { @@ -841,6 +963,7 @@ static const struct iio_chan_spec mma8652_channels[] = { MMA8652_CHANNEL(Y, idx_y, 12), MMA8652_CHANNEL(Z, idx_z, 12), IIO_CHAN_SOFT_TIMESTAMP(idx_ts), + MMA8652_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z), }; static const struct iio_chan_spec mma8653_channels[] = { @@ -848,6 +971,7 @@ static const struct iio_chan_spec mma8653_channels[] = { MMA8652_CHANNEL(Y, idx_y, 10), MMA8652_CHANNEL(Z, idx_z, 10), IIO_CHAN_SOFT_TIMESTAMP(idx_ts), + MMA8652_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z), }; enum { @@ -1190,6 +1314,10 @@ static int mma8452_probe(struct i2c_client *client, if (ret < 0) goto buffer_cleanup; + ret = mma8452_set_freefall_mode(data, false); + if (ret) + return ret; + return 0; buffer_cleanup: -- cgit v1.2.3 From 36775d57016ec311780c3beed3173ae6fb59f0e2 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Sat, 16 Jan 2016 15:35:21 +0100 Subject: iio: mma8452: whitespace cleanup Signed-off-by: Martin Kepplinger Signed-off-by: Christoph Muellner Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma8452.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 77b71c2dfd72..843169effb34 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -85,8 +85,8 @@ #define MMA8452_INT_FF_MT BIT(2) #define MMA8452_INT_TRANS BIT(5) -#define MMA8452_DEVICE_ID 0x2a -#define MMA8453_DEVICE_ID 0x3a +#define MMA8452_DEVICE_ID 0x2a +#define MMA8453_DEVICE_ID 0x3a #define MMA8652_DEVICE_ID 0x4a #define MMA8653_DEVICE_ID 0x5a -- cgit v1.2.3 From 244a93f651937a7f587f8ddf3d8c09516cacf5bd Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Sat, 16 Jan 2016 15:35:22 +0100 Subject: iio: mma8452: add support for MMA8451Q This adds support for this series' 14 bit accelerometer chip, MMA8451Q. It's datasheet is available at the vendor's website: https://cache.freescale.com/files/sensors/doc/data_sheet/MMA8451Q.pdf Signed-off-by: Martin Kepplinger Signed-off-by: Christoph Muellner Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/accel/mma8452.txt | 4 ++- drivers/iio/accel/Kconfig | 2 +- drivers/iio/accel/mma8452.c | 42 ++++++++++++++++++---- 3 files changed, 40 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/iio/accel/mma8452.txt b/Documentation/devicetree/bindings/iio/accel/mma8452.txt index 3c10e8581144..165937e1ac1c 100644 --- a/Documentation/devicetree/bindings/iio/accel/mma8452.txt +++ b/Documentation/devicetree/bindings/iio/accel/mma8452.txt @@ -1,8 +1,10 @@ -Freescale MMA8452Q, MMA8453Q, MMA8652FC or MMA8653FC triaxial accelerometer +Freescale MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC or MMA8653FC +triaxial accelerometer Required properties: - compatible: should contain one of + * "fsl,mma8451" * "fsl,mma8452" * "fsl,mma8453" * "fsl,mma8652" diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index edc29b173f6c..d9feaa3c1fb8 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -143,7 +143,7 @@ config MMA8452 select IIO_TRIGGERED_BUFFER help Say yes here to build support for the following Freescale 3-axis - accelerometers: MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC. + accelerometers: MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC. To compile this driver as a module, choose M here: the module will be called mma8452. diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 843169effb34..7f4994f32a90 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -1,6 +1,7 @@ /* * mma8452.c - Support for following Freescale 3-axis accelerometers: * + * MMA8451Q (14 bit) * MMA8452Q (12 bit) * MMA8453Q (10 bit) * MMA8652FC (12 bit) @@ -85,6 +86,7 @@ #define MMA8452_INT_FF_MT BIT(2) #define MMA8452_INT_TRANS BIT(5) +#define MMA8451_DEVICE_ID 0x1a #define MMA8452_DEVICE_ID 0x2a #define MMA8453_DEVICE_ID 0x3a #define MMA8652_DEVICE_ID 0x4a @@ -942,6 +944,14 @@ static struct attribute_group mma8452_event_attribute_group = { .num_event_specs = ARRAY_SIZE(mma8452_motion_event), \ } +static const struct iio_chan_spec mma8451_channels[] = { + MMA8452_CHANNEL(X, idx_x, 14), + MMA8452_CHANNEL(Y, idx_y, 14), + MMA8452_CHANNEL(Z, idx_z, 14), + IIO_CHAN_SOFT_TIMESTAMP(idx_ts), + MMA8452_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z), +}; + static const struct iio_chan_spec mma8452_channels[] = { MMA8452_CHANNEL(X, idx_x, 12), MMA8452_CHANNEL(Y, idx_y, 12), @@ -975,6 +985,7 @@ static const struct iio_chan_spec mma8653_channels[] = { }; enum { + mma8451, mma8452, mma8453, mma8652, @@ -982,17 +993,34 @@ enum { }; static const struct mma_chip_info mma_chip_info_table[] = { - [mma8452] = { - .chip_id = MMA8452_DEVICE_ID, - .channels = mma8452_channels, - .num_channels = ARRAY_SIZE(mma8452_channels), + [mma8451] = { + .chip_id = MMA8451_DEVICE_ID, + .channels = mma8451_channels, + .num_channels = ARRAY_SIZE(mma8451_channels), /* * Hardware has fullscale of -2G, -4G, -8G corresponding to - * raw value -2048 for 12 bit or -512 for 10 bit. + * raw value -8192 for 14 bit, -2048 for 12 bit or -512 for 10 + * bit. * The userspace interface uses m/s^2 and we declare micro units * So scale factor for 12 bit here is given by: - * g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665 + * g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665 */ + .mma_scales = { {0, 2394}, {0, 4788}, {0, 9577} }, + .ev_cfg = MMA8452_TRANSIENT_CFG, + .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE, + .ev_cfg_chan_shift = 1, + .ev_src = MMA8452_TRANSIENT_SRC, + .ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE, + .ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE, + .ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE, + .ev_ths = MMA8452_TRANSIENT_THS, + .ev_ths_mask = MMA8452_TRANSIENT_THS_MASK, + .ev_count = MMA8452_TRANSIENT_COUNT, + }, + [mma8452] = { + .chip_id = MMA8452_DEVICE_ID, + .channels = mma8452_channels, + .num_channels = ARRAY_SIZE(mma8452_channels), .mma_scales = { {0, 9577}, {0, 19154}, {0, 38307} }, .ev_cfg = MMA8452_TRANSIENT_CFG, .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE, @@ -1173,6 +1201,7 @@ static int mma8452_reset(struct i2c_client *client) } static const struct of_device_id mma8452_dt_ids[] = { + { .compatible = "fsl,mma8451", .data = &mma_chip_info_table[mma8451] }, { .compatible = "fsl,mma8452", .data = &mma_chip_info_table[mma8452] }, { .compatible = "fsl,mma8453", .data = &mma_chip_info_table[mma8453] }, { .compatible = "fsl,mma8652", .data = &mma_chip_info_table[mma8652] }, @@ -1209,6 +1238,7 @@ static int mma8452_probe(struct i2c_client *client, return ret; switch (ret) { + case MMA8451_DEVICE_ID: case MMA8452_DEVICE_ID: case MMA8453_DEVICE_ID: case MMA8652_DEVICE_ID: -- cgit v1.2.3 From 7ca6574a7afb669b0b4b30dd63adeb310e97e250 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 22 Jan 2016 17:49:22 +0000 Subject: iio: adc: axp288: remove redundant duplicate const on axp288_adc_channels duplicate const can be removed, it is redundant. Found by static analysis using smatch. Signed-off-by: Colin Ian King Signed-off-by: Jonathan Cameron --- drivers/iio/adc/axp288_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c index 0c904edd6c00..7fd24949c0c1 100644 --- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c @@ -46,7 +46,7 @@ struct axp288_adc_info { struct regmap *regmap; }; -static const struct iio_chan_spec const axp288_adc_channels[] = { +static const struct iio_chan_spec axp288_adc_channels[] = { { .indexed = 1, .type = IIO_TEMP, -- cgit v1.2.3 From 12197bf21c26e23053fa6223f3a731a965542986 Mon Sep 17 00:00:00 2001 From: Romain Izard Date: Wed, 13 Jan 2016 17:34:13 +0100 Subject: mtd: atmel_nand: Do not warn on bitflips When using multi-bit ECC, it is normal for the NAND Flash driver to correct bit errors during the life of the product. Those errors will only be cleared once a threshold has been reached, and corrections can occur regularly before this. Use only dev_dbg and not dev_info to report the bitflips, to keep the system log clean when everything works correctly. Signed-off-by: Romain Izard Acked-by: Wenyou Yang Reviewed-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/atmel_nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index bddcf83d6859..0ae6cba5bef5 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -825,7 +825,7 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc, *(buf + byte_pos) ^= (1 << bit_pos); pos = sector_num * host->pmecc_sector_size + byte_pos; - dev_info(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", + dev_dbg(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", pos, bit_pos, err_byte, *(buf + byte_pos)); } else { /* Bit flip in OOB area */ @@ -835,7 +835,7 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc, ecc[tmp] ^= (1 << bit_pos); pos = tmp + nand_chip->ecc.layout->eccpos[0]; - dev_info(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", + dev_dbg(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", pos, bit_pos, err_byte, ecc[tmp]); } -- cgit v1.2.3 From 46c135c208a3a80bd7f12dee0032bbc6d507a0d9 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 22 Jan 2016 18:57:13 -0800 Subject: mtd: nand: sunxi: use mtd_div_by_ws() helper Suggested-by: Richard Weinberger Signed-off-by: Brian Norris Acked-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 5f700719d5c2..b5ea6b312df0 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -624,7 +624,7 @@ static u16 sunxi_nfc_randomizer_step(u16 state, int count) static u16 sunxi_nfc_randomizer_state(struct mtd_info *mtd, int page, bool ecc) { const u16 *seeds = sunxi_nfc_randomizer_page_seeds; - int mod = mtd->erasesize / mtd->writesize; + int mod = mtd_div_by_ws(mtd->erasesize, mtd); if (mod > ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds)) mod = ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds); -- cgit v1.2.3 From 54ca3cd594db58d65b3670f2af452c1104b09ac6 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 14 Jan 2016 15:44:49 +0100 Subject: mtd: nand: remove EXPORT_SYMBOL of nand_scan_bbt() Since commit 17799359e7b3fa6ef4f2bf926cd6821cf7903ecf ("mtd: nand_bbt: make nand_scan_bbt() static"), the nand_scan_bbt() function is marked as static but is still exported using EXPORT_SYMBOL(), which doesn't make much sense. This commit gets rid of the useless EXPORT_SYMBOL. Signed-off-by: Thomas Petazzoni Reviewed-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_bbt.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 4b6a7085b442..2fbb523df066 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -1373,5 +1373,3 @@ int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs) return ret; } - -EXPORT_SYMBOL(nand_scan_bbt); -- cgit v1.2.3 From fd2a2f20c7a8173acd4858e5178eb40fd7c025b9 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 14 Jan 2016 15:44:50 +0100 Subject: mtd: onenand: make onenand_scan_bbt() static Like was done in commit 17799359e7b3fa6ef4f2bf926cd6821cf7903ecf ("mtd: nand_bbt: make nand_scan_bbt() static") for the NAND code, this commit makes the onenand_scan_bbt() function static in the OneNAND code, since it is only used in onenand_bbt.c itself. Consequently, the EXPORT_SYMBOL() and declaration in bbm.h are also removed. Signed-off-by: Thomas Petazzoni Reviewed-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/onenand/onenand_bbt.c | 3 +-- include/linux/mtd/bbm.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c index 08d0085f3e93..5f8d47073c97 100644 --- a/drivers/mtd/onenand/onenand_bbt.c +++ b/drivers/mtd/onenand/onenand_bbt.c @@ -179,7 +179,7 @@ static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) * by the onenand_release function. * */ -int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) +static int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) { struct onenand_chip *this = mtd->priv; struct bbm_info *bbm = this->bbm; @@ -248,5 +248,4 @@ int onenand_default_bbt(struct mtd_info *mtd) return onenand_scan_bbt(mtd, bbm->badblock_pattern); } -EXPORT_SYMBOL(onenand_scan_bbt); EXPORT_SYMBOL(onenand_default_bbt); diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h index 36bb6a503f19..3bf8f954b642 100644 --- a/include/linux/mtd/bbm.h +++ b/include/linux/mtd/bbm.h @@ -166,7 +166,6 @@ struct bbm_info { }; /* OneNAND BBT interface */ -extern int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd); extern int onenand_default_bbt(struct mtd_info *mtd); #endif /* __LINUX_MTD_BBM_H */ -- cgit v1.2.3 From d652436102b1580d8d968a2047decbb737cc4e6d Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 14 Jan 2016 15:44:51 +0100 Subject: mtd: onenand: unexport onenand_default_bbt() The onenand_default_bbt() function is only used by the OneNAND core and not by drivers, so there is no real need to export it. Additionally, the corresponding nand_default_bbt() for regular NANDs is not exported either, so for consistency reasons, this commit removes the EXPORT_SYMBOL on onenand_default_bbt(). Signed-off-by: Thomas Petazzoni Reviewed-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/onenand/onenand_bbt.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c index 5f8d47073c97..680188a88130 100644 --- a/drivers/mtd/onenand/onenand_bbt.c +++ b/drivers/mtd/onenand/onenand_bbt.c @@ -247,5 +247,3 @@ int onenand_default_bbt(struct mtd_info *mtd) return onenand_scan_bbt(mtd, bbm->badblock_pattern); } - -EXPORT_SYMBOL(onenand_default_bbt); -- cgit v1.2.3 From 2a36a5c30eab9cd1c9d2d08bd27cd763325d70c5 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 5 Dec 2015 02:09:43 +0100 Subject: mtd: bcm47xxpart: limit scanned flash area on BCM47XX (MIPS) only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We allowed using bcm47xxpart on BCM5301X arch with commit: 9e3afa5f5c7 ("mtd: bcm47xxpart: allow enabling on ARCH_BCM_5301X") BCM5301X devices may contain some partitions in higher memory, e.g. Netgear R8000 has board_data at 0x2600000. To detect them we should use size limit on MIPS only. Signed-off-by: Rafał Miłecki Signed-off-by: Brian Norris --- drivers/mtd/bcm47xxpart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c index 8282f47bcf5d..b06d4c4553ed 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c @@ -118,8 +118,8 @@ static int bcm47xxpart_parse(struct mtd_info *master, /* Parse block by block looking for magics */ for (offset = 0; offset <= master->size - blocksize; offset += blocksize) { - /* Nothing more in higher memory */ - if (offset >= 0x2000000) + /* Nothing more in higher memory on BCM47XX (MIPS) */ + if (config_enabled(CONFIG_BCM47XX) && offset >= 0x2000000) break; if (curr_part >= BCM47XXPART_MAX_PARTS) { -- cgit v1.2.3 From 36bcc0c9c2bc8f56569cd735ba531a51358d7c2b Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sun, 6 Dec 2015 11:31:38 +0100 Subject: mtd: bcm47xxpart: don't fail because of bit-flips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bit-flip errors may occur on NAND flashes and are harmless. Handle them gracefully as read content is still reliable and can be parsed. Signed-off-by: Rafał Miłecki Signed-off-by: Brian Norris --- drivers/mtd/bcm47xxpart.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c index b06d4c4553ed..845dd27d9f41 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c @@ -66,11 +66,13 @@ static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master, { uint32_t buf; size_t bytes_read; + int err; - if (mtd_read(master, offset, sizeof(buf), &bytes_read, - (uint8_t *)&buf) < 0) { - pr_err("mtd_read error while parsing (offset: 0x%X)!\n", - offset); + err = mtd_read(master, offset, sizeof(buf), &bytes_read, + (uint8_t *)&buf); + if (err && !mtd_is_bitflip(err)) { + pr_err("mtd_read error while parsing (offset: 0x%X): %d\n", + offset, err); goto out_default; } @@ -95,6 +97,7 @@ static int bcm47xxpart_parse(struct mtd_info *master, int trx_part = -1; int last_trx_part = -1; int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, }; + int err; /* * Some really old flashes (like AT45DB*) had smaller erasesize-s, but @@ -128,10 +131,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, } /* Read beginning of the block */ - if (mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ, - &bytes_read, (uint8_t *)buf) < 0) { - pr_err("mtd_read error while parsing (offset: 0x%X)!\n", - offset); + err = mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ, + &bytes_read, (uint8_t *)buf); + if (err && !mtd_is_bitflip(err)) { + pr_err("mtd_read error while parsing (offset: 0x%X): %d\n", + offset, err); continue; } @@ -254,10 +258,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, } /* Read middle of the block */ - if (mtd_read(master, offset + 0x8000, 0x4, - &bytes_read, (uint8_t *)buf) < 0) { - pr_err("mtd_read error while parsing (offset: 0x%X)!\n", - offset); + err = mtd_read(master, offset + 0x8000, 0x4, &bytes_read, + (uint8_t *)buf); + if (err && !mtd_is_bitflip(err)) { + pr_err("mtd_read error while parsing (offset: 0x%X): %d\n", + offset, err); continue; } @@ -277,10 +282,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, } offset = master->size - possible_nvram_sizes[i]; - if (mtd_read(master, offset, 0x4, &bytes_read, - (uint8_t *)buf) < 0) { - pr_err("mtd_read error while reading at offset 0x%X!\n", - offset); + err = mtd_read(master, offset, 0x4, &bytes_read, + (uint8_t *)buf); + if (err && !mtd_is_bitflip(err)) { + pr_err("mtd_read error while reading (offset 0x%X): %d\n", + offset, err); continue; } -- cgit v1.2.3 From 026918e71111afe88382f8d800a852d3e36bf3d4 Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Wed, 2 Dec 2015 16:47:40 -0600 Subject: mtd: nand: gpmi: add gpmi dsm supend/resume support i.MX6SX supports deep sleep mode(DSM) that may turn off GPMI/BCH power during suspend, add gpmi nand suspend/resume function to release DMA channel in suspend function and re-init GPMI/BCH controller during resume function. Although it is not necessary to restore GPMI/BCH registers value for i.MX6QDL, the code doesn't distinguish different platforms to keep the code simple. Signed-off-by: Huang Shijie Signed-off-by: Han Xu Signed-off-by: Brian Norris --- drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 47 +++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 235ddcb58f39..9c311b06018b 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -1,7 +1,7 @@ /* * Freescale GPMI NAND Flash Driver * - * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. + * Copyright (C) 2010-2015 Freescale Semiconductor, Inc. * Copyright (C) 2008 Embedded Alley Solutions, Inc. * * This program is free software; you can redistribute it and/or modify @@ -2033,9 +2033,54 @@ static int gpmi_nand_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int gpmi_pm_suspend(struct device *dev) +{ + struct gpmi_nand_data *this = dev_get_drvdata(dev); + + release_dma_channels(this); + return 0; +} + +static int gpmi_pm_resume(struct device *dev) +{ + struct gpmi_nand_data *this = dev_get_drvdata(dev); + int ret; + + ret = acquire_dma_channels(this); + if (ret < 0) + return ret; + + /* re-init the GPMI registers */ + this->flags &= ~GPMI_TIMING_INIT_OK; + ret = gpmi_init(this); + if (ret) { + dev_err(this->dev, "Error setting GPMI : %d\n", ret); + return ret; + } + + /* re-init the BCH registers */ + ret = bch_set_geometry(this); + if (ret) { + dev_err(this->dev, "Error setting BCH : %d\n", ret); + return ret; + } + + /* re-init others */ + gpmi_extra_init(this); + + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +static const struct dev_pm_ops gpmi_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(gpmi_pm_suspend, gpmi_pm_resume) +}; + static struct platform_driver gpmi_nand_driver = { .driver = { .name = "gpmi-nand", + .pm = &gpmi_pm_ops, .of_match_table = gpmi_nand_id_table, }, .probe = gpmi_nand_probe, -- cgit v1.2.3 From b8b0e465ddb0c9cb16089ddfed68a8569e006465 Mon Sep 17 00:00:00 2001 From: Han Xu Date: Wed, 2 Dec 2015 16:47:43 -0600 Subject: mtd: nand: gpmi: may use minimum required ecc for 744 oobsize NAND By default NAND driver will choose the highest ecc strength that oob could contain, in this case, for some 8K+744 NAND flash, the ecc strength will be up to 52bit, which beyonds the i.MX6QDL BCH capability (40bit). This patch allows the NAND driver try to use minimum required ecc strength if it failed to use the highest ecc, even without explicitly claiming "fsl,use-minimum-ecc" in dts. Signed-off-by: Han Xu Acked-by: Huang Shijie Signed-off-by: Brian Norris --- drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 9c311b06018b..8122c699ccf2 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -136,7 +136,7 @@ static inline bool gpmi_check_ecc(struct gpmi_nand_data *this) * * We may have available oob space in this case. */ -static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this) +static int set_geometry_by_ecc_info(struct gpmi_nand_data *this) { struct bch_geometry *geo = &this->bch_geometry; struct nand_chip *chip = &this->nand; @@ -145,7 +145,7 @@ static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this) unsigned int block_mark_bit_offset; if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) - return false; + return -EINVAL; switch (chip->ecc_step_ds) { case SZ_512: @@ -158,19 +158,19 @@ static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this) dev_err(this->dev, "unsupported nand chip. ecc bits : %d, ecc size : %d\n", chip->ecc_strength_ds, chip->ecc_step_ds); - return false; + return -EINVAL; } geo->ecc_chunk_size = chip->ecc_step_ds; geo->ecc_strength = round_up(chip->ecc_strength_ds, 2); if (!gpmi_check_ecc(this)) - return false; + return -EINVAL; /* Keep the C >= O */ if (geo->ecc_chunk_size < mtd->oobsize) { dev_err(this->dev, "unsupported nand chip. ecc size: %d, oob size : %d\n", chip->ecc_step_ds, mtd->oobsize); - return false; + return -EINVAL; } /* The default value, see comment in the legacy_set_geometry(). */ @@ -242,7 +242,7 @@ static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this) + ALIGN(geo->ecc_chunk_count, 4); if (!this->swap_block_mark) - return true; + return 0; /* For bit swap. */ block_mark_bit_offset = mtd->writesize * 8 - @@ -251,7 +251,7 @@ static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this) geo->block_mark_byte_offset = block_mark_bit_offset / 8; geo->block_mark_bit_offset = block_mark_bit_offset % 8; - return true; + return 0; } static int legacy_set_geometry(struct gpmi_nand_data *this) @@ -285,7 +285,8 @@ static int legacy_set_geometry(struct gpmi_nand_data *this) geo->ecc_strength = get_ecc_strength(this); if (!gpmi_check_ecc(this)) { dev_err(this->dev, - "required ecc strength of the NAND chip: %d is not supported by the GPMI controller (%d)\n", + "ecc strength: %d cannot be supported by the controller (%d)\n" + "try to use minimum ecc strength that NAND chip required\n", geo->ecc_strength, this->devdata->bch_max_ecc_strength); return -EINVAL; @@ -366,10 +367,11 @@ static int legacy_set_geometry(struct gpmi_nand_data *this) int common_nfc_set_geometry(struct gpmi_nand_data *this) { - if (of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc") - && set_geometry_by_ecc_info(this)) - return 0; - return legacy_set_geometry(this); + if ((of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc")) + || legacy_set_geometry(this)) + return set_geometry_by_ecc_info(this); + + return 0; } struct dma_chan *get_dma_chan(struct gpmi_nand_data *this) -- cgit v1.2.3 From e88b7f7d6ca47531af602cfb6abdb31ea13eabc3 Mon Sep 17 00:00:00 2001 From: Romain Izard Date: Fri, 15 Jan 2016 11:34:56 +0100 Subject: mtd: atmel_nand: Simplify error messages The error messages when the ECC controller is misconfigured through the device tree are very precise. As a result they can (and will) get obsolete when new revisions of the controller appear. Simplify them before adding the support for the new revision. Signed-off-by: Romain Izard Signed-off-by: Brian Norris --- drivers/mtd/nand/atmel_nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 0ae6cba5bef5..ad9f4b062049 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -1550,7 +1550,7 @@ static int atmel_of_init_port(struct atmel_nand_host *host, if ((val != 2) && (val != 4) && (val != 8) && (val != 12) && (val != 24)) { dev_err(host->dev, - "Unsupported PMECC correction capability: %d; should be 2, 4, 8, 12 or 24\n", + "Required ECC strength not supported: %u\n", val); return -EINVAL; } @@ -1560,7 +1560,7 @@ static int atmel_of_init_port(struct atmel_nand_host *host, if (of_property_read_u32(np, "atmel,pmecc-sector-size", &val) == 0) { if ((val != 512) && (val != 1024)) { dev_err(host->dev, - "Unsupported PMECC sector size: %d; should be 512 or 1024 bytes\n", + "Required ECC sector size not supported: %u\n", val); return -EINVAL; } -- cgit v1.2.3 From 8ce06d379a06b4d5c9f944bb60e80b084d16bfc0 Mon Sep 17 00:00:00 2001 From: Romain Izard Date: Fri, 15 Jan 2016 11:34:57 +0100 Subject: mtd: atmel_nand: Use of_device_get_match_data Remove the need for forward declaration and the risk for a null pointer when accessing the private part of the compatible match table, by using the newly introduced of_device_get_match_data function. Signed-off-by: Romain Izard Signed-off-by: Brian Norris --- drivers/mtd/nand/atmel_nand.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index ad9f4b062049..affe7a7e9ad7 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -1486,8 +1486,6 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) ecc_writel(host->ecc, CR, ATMEL_ECC_RST); } -static const struct of_device_id atmel_nand_dt_ids[]; - static int atmel_of_init_port(struct atmel_nand_host *host, struct device_node *np) { @@ -1498,7 +1496,7 @@ static int atmel_of_init_port(struct atmel_nand_host *host, enum of_gpio_flags flags = 0; host->caps = (struct atmel_nand_caps *) - of_match_device(atmel_nand_dt_ids, host->dev)->data; + of_device_get_match_data(host->dev); if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) { if (val >= 32) { -- cgit v1.2.3 From 2c3033a0664dfae91e1dee7fabac10f24354b958 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Sat, 23 Jan 2016 15:44:19 -0500 Subject: ACPI / PCI / hotplug: unlock in error path in acpiphp_enable_slot() In acpiphp_enable_slot(), there is a missing unlock path when error occurred. It needs to be unlocked before returning an error. Signed-off-by: Insu Yun Cc: All applicable Signed-off-by: Rafael J. Wysocki --- drivers/pci/hotplug/acpiphp_glue.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index ff538568a617..0b3e0bfa7be5 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -953,8 +953,10 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) { pci_lock_rescan_remove(); - if (slot->flags & SLOT_IS_GOING_AWAY) + if (slot->flags & SLOT_IS_GOING_AWAY) { + pci_unlock_rescan_remove(); return -ENODEV; + } /* configure all functions */ if (!(slot->flags & SLOT_ENABLED)) -- cgit v1.2.3 From 131497acd88a4456d99247cee457baefd2817835 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Delgado Date: Sat, 16 Jan 2016 14:24:07 +0100 Subject: iio: add ad5761 DAC driver ad5761 is a 1-channel DAC with configurable output range. The driver uses the regulator interface for its voltage ref. It shares its register layout with ad5761r, ad5721 and ad5721r. Differences: ad5761* are 16 bit, ad5721* are 12 bits. ad57*1r have an internal reference. Signed-off-by: Ricardo Ribalda Delgado Signed-off-by: Jonathan Cameron --- CREDITS | 1 + drivers/iio/dac/Kconfig | 10 + drivers/iio/dac/Makefile | 1 + drivers/iio/dac/ad5761.c | 430 +++++++++++++++++++++++++++++++++++ include/linux/platform_data/ad5761.h | 44 ++++ 5 files changed, 486 insertions(+) create mode 100644 drivers/iio/dac/ad5761.c create mode 100644 include/linux/platform_data/ad5761.h (limited to 'drivers') diff --git a/CREDITS b/CREDITS index 8207cc62ee9d..44ea433d70a1 100644 --- a/CREDITS +++ b/CREDITS @@ -3035,6 +3035,7 @@ D: PLX USB338x driver D: PCA9634 driver D: Option GTM671WFS D: Fintek F81216A +D: AD5761 iio driver D: Various kernel hacks S: Qtechnology A/S S: Valby Langgade 142 diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index 5263c5125fbb..5dc71505da61 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -111,6 +111,16 @@ config AD5755 To compile this driver as a module, choose M here: the module will be called ad5755. +config AD5761 + tristate "Analog Devices AD5761/61R/21/21R DAC driver" + depends on SPI_MASTER + help + Say yes here to build support for Analog Devices AD5761, AD5761R, AD5721, + AD5721R Digital to Analog Converter. + + To compile this driver as a module, choose M here: the + module will be called ad5761. + config AD5764 tristate "Analog Devices AD5764/64R/44/44R DAC driver" depends on SPI_MASTER diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index 63ae05633e0c..cb525b53fc7b 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_AD5504) += ad5504.o obj-$(CONFIG_AD5446) += ad5446.o obj-$(CONFIG_AD5449) += ad5449.o obj-$(CONFIG_AD5755) += ad5755.o +obj-$(CONFIG_AD5761) += ad5761.o obj-$(CONFIG_AD5764) += ad5764.o obj-$(CONFIG_AD5791) += ad5791.o obj-$(CONFIG_AD5686) += ad5686.o diff --git a/drivers/iio/dac/ad5761.c b/drivers/iio/dac/ad5761.c new file mode 100644 index 000000000000..d6510d6928b3 --- /dev/null +++ b/drivers/iio/dac/ad5761.c @@ -0,0 +1,430 @@ +/* + * AD5721, AD5721R, AD5761, AD5761R, Voltage Output Digital to Analog Converter + * + * Copyright 2016 Qtechnology A/S + * 2016 Ricardo Ribalda + * + * Licensed under the GPL-2. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define AD5761_ADDR(addr) ((addr & 0xf) << 16) +#define AD5761_ADDR_NOOP 0x0 +#define AD5761_ADDR_DAC_WRITE 0x3 +#define AD5761_ADDR_CTRL_WRITE_REG 0x4 +#define AD5761_ADDR_SW_DATA_RESET 0x7 +#define AD5761_ADDR_DAC_READ 0xb +#define AD5761_ADDR_CTRL_READ_REG 0xc +#define AD5761_ADDR_SW_FULL_RESET 0xf + +#define AD5761_CTRL_USE_INTVREF BIT(5) +#define AD5761_CTRL_ETS BIT(6) + +/** + * struct ad5761_chip_info - chip specific information + * @int_vref: Value of the internal reference voltage in mV - 0 if external + * reference voltage is used + * @channel: channel specification +*/ + +struct ad5761_chip_info { + unsigned long int_vref; + const struct iio_chan_spec channel; +}; + +struct ad5761_range_params { + int m; + int c; +}; + +enum ad5761_supported_device_ids { + ID_AD5721, + ID_AD5721R, + ID_AD5761, + ID_AD5761R, +}; + +/** + * struct ad5761_state - driver instance specific data + * @spi: spi_device + * @vref_reg: reference voltage regulator + * @use_intref: true when the internal voltage reference is used + * @vref: actual voltage reference in mVolts + * @range: output range mode used + * @data: cache aligned spi buffer + */ +struct ad5761_state { + struct spi_device *spi; + struct regulator *vref_reg; + + bool use_intref; + int vref; + enum ad5761_voltage_range range; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + union { + __be32 d32; + u8 d8[4]; + } data[3] ____cacheline_aligned; +}; + +static const struct ad5761_range_params ad5761_range_params[] = { + [AD5761_VOLTAGE_RANGE_M10V_10V] = { + .m = 80, + .c = 40, + }, + [AD5761_VOLTAGE_RANGE_0V_10V] = { + .m = 40, + .c = 0, + }, + [AD5761_VOLTAGE_RANGE_M5V_5V] = { + .m = 40, + .c = 20, + }, + [AD5761_VOLTAGE_RANGE_0V_5V] = { + .m = 20, + .c = 0, + }, + [AD5761_VOLTAGE_RANGE_M2V5_7V5] = { + .m = 40, + .c = 10, + }, + [AD5761_VOLTAGE_RANGE_M3V_3V] = { + .m = 24, + .c = 12, + }, + [AD5761_VOLTAGE_RANGE_0V_16V] = { + .m = 64, + .c = 0, + }, + [AD5761_VOLTAGE_RANGE_0V_20V] = { + .m = 80, + .c = 0, + }, +}; + +static int _ad5761_spi_write(struct ad5761_state *st, u8 addr, u16 val) +{ + st->data[0].d32 = cpu_to_be32(AD5761_ADDR(addr) | val); + + return spi_write(st->spi, &st->data[0].d8[1], 3); +} + +static int ad5761_spi_write(struct iio_dev *indio_dev, u8 addr, u16 val) +{ + struct ad5761_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&indio_dev->mlock); + ret = _ad5761_spi_write(st, addr, val); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int _ad5761_spi_read(struct ad5761_state *st, u8 addr, u16 *val) +{ + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = &st->data[0].d8[1], + .bits_per_word = 8, + .len = 3, + .cs_change = true, + }, { + .tx_buf = &st->data[1].d8[1], + .rx_buf = &st->data[2].d8[1], + .bits_per_word = 8, + .len = 3, + }, + }; + + st->data[0].d32 = cpu_to_be32(AD5761_ADDR(addr)); + st->data[1].d32 = cpu_to_be32(AD5761_ADDR(AD5761_ADDR_NOOP)); + + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); + + *val = be32_to_cpu(st->data[2].d32); + + return ret; +} + +static int ad5761_spi_read(struct iio_dev *indio_dev, u8 addr, u16 *val) +{ + struct ad5761_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&indio_dev->mlock); + ret = _ad5761_spi_read(st, addr, val); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int ad5761_spi_set_range(struct ad5761_state *st, + enum ad5761_voltage_range range) +{ + u16 aux; + int ret; + + aux = (range & 0x7) | AD5761_CTRL_ETS; + + if (st->use_intref) + aux |= AD5761_CTRL_USE_INTVREF; + + ret = _ad5761_spi_write(st, AD5761_ADDR_SW_FULL_RESET, 0); + if (ret) + return ret; + + ret = _ad5761_spi_write(st, AD5761_ADDR_CTRL_WRITE_REG, aux); + if (ret) + return ret; + + st->range = range; + + return 0; +} + +static int ad5761_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + struct ad5761_state *st; + int ret; + u16 aux; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = ad5761_spi_read(indio_dev, AD5761_ADDR_DAC_READ, &aux); + if (ret) + return ret; + *val = aux >> chan->scan_type.shift; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + st = iio_priv(indio_dev); + *val = st->vref * ad5761_range_params[st->range].m; + *val /= 10; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_OFFSET: + st = iio_priv(indio_dev); + *val = -(1 << chan->scan_type.realbits); + *val *= ad5761_range_params[st->range].c; + *val /= ad5761_range_params[st->range].m; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int ad5761_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + u16 aux; + + if (mask != IIO_CHAN_INFO_RAW) + return -EINVAL; + + if (val2 || (val << chan->scan_type.shift) > 0xffff || val < 0) + return -EINVAL; + + aux = val << chan->scan_type.shift; + + return ad5761_spi_write(indio_dev, AD5761_ADDR_DAC_WRITE, aux); +} + +static const struct iio_info ad5761_info = { + .read_raw = &ad5761_read_raw, + .write_raw = &ad5761_write_raw, + .driver_module = THIS_MODULE, +}; + +#define AD5761_CHAN(_bits) { \ + .type = IIO_VOLTAGE, \ + .output = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = (_bits), \ + .storagebits = 16, \ + .shift = 16 - (_bits), \ + }, \ +} + +static const struct ad5761_chip_info ad5761_chip_infos[] = { + [ID_AD5721] = { + .int_vref = 0, + .channel = AD5761_CHAN(12), + }, + [ID_AD5721R] = { + .int_vref = 2500, + .channel = AD5761_CHAN(12), + }, + [ID_AD5761] = { + .int_vref = 0, + .channel = AD5761_CHAN(16), + }, + [ID_AD5761R] = { + .int_vref = 2500, + .channel = AD5761_CHAN(16), + }, +}; + +static int ad5761_get_vref(struct ad5761_state *st, + const struct ad5761_chip_info *chip_info) +{ + int ret; + + st->vref_reg = devm_regulator_get_optional(&st->spi->dev, "vref"); + if (PTR_ERR(st->vref_reg) == -ENODEV) { + /* Use Internal regulator */ + if (!chip_info->int_vref) { + dev_err(&st->spi->dev, + "Voltage reference not found\n"); + return -EIO; + } + + st->use_intref = true; + st->vref = chip_info->int_vref; + return 0; + } + + if (IS_ERR(st->vref_reg)) { + dev_err(&st->spi->dev, + "Error getting voltage reference regulator\n"); + return PTR_ERR(st->vref_reg); + } + + ret = regulator_enable(st->vref_reg); + if (ret) { + dev_err(&st->spi->dev, + "Failed to enable voltage reference\n"); + return ret; + } + + ret = regulator_get_voltage(st->vref_reg); + if (ret < 0) { + dev_err(&st->spi->dev, + "Failed to get voltage reference value\n"); + goto disable_regulator_vref; + } + + if (ret < 2000000 || ret > 3000000) { + dev_warn(&st->spi->dev, + "Invalid external voltage ref. value %d uV\n", ret); + ret = -EIO; + goto disable_regulator_vref; + } + + st->vref = ret / 1000; + st->use_intref = false; + + return 0; + +disable_regulator_vref: + regulator_disable(st->vref_reg); + st->vref_reg = NULL; + return ret; +} + +static int ad5761_probe(struct spi_device *spi) +{ + struct iio_dev *iio_dev; + struct ad5761_state *st; + int ret; + const struct ad5761_chip_info *chip_info = + &ad5761_chip_infos[spi_get_device_id(spi)->driver_data]; + enum ad5761_voltage_range voltage_range = AD5761_VOLTAGE_RANGE_0V_5V; + struct ad5761_platform_data *pdata = dev_get_platdata(&spi->dev); + + iio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!iio_dev) + return -ENOMEM; + + st = iio_priv(iio_dev); + + st->spi = spi; + spi_set_drvdata(spi, iio_dev); + + ret = ad5761_get_vref(st, chip_info); + if (ret) + return ret; + + if (pdata) + voltage_range = pdata->voltage_range; + + ret = ad5761_spi_set_range(st, voltage_range); + if (ret) + goto disable_regulator_err; + + iio_dev->dev.parent = &spi->dev; + iio_dev->info = &ad5761_info; + iio_dev->modes = INDIO_DIRECT_MODE; + iio_dev->channels = &chip_info->channel; + iio_dev->num_channels = 1; + iio_dev->name = spi_get_device_id(st->spi)->name; + ret = iio_device_register(iio_dev); + if (ret) + goto disable_regulator_err; + + return 0; + +disable_regulator_err: + if (!IS_ERR_OR_NULL(st->vref_reg)) + regulator_disable(st->vref_reg); + + return ret; +} + +static int ad5761_remove(struct spi_device *spi) +{ + struct iio_dev *iio_dev = spi_get_drvdata(spi); + struct ad5761_state *st = iio_priv(iio_dev); + + iio_device_unregister(iio_dev); + + if (!IS_ERR_OR_NULL(st->vref_reg)) + regulator_disable(st->vref_reg); + + return 0; +} + +static const struct spi_device_id ad5761_id[] = { + {"ad5721", ID_AD5721}, + {"ad5721r", ID_AD5721R}, + {"ad5761", ID_AD5761}, + {"ad5761r", ID_AD5761R}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad5761_id); + +static struct spi_driver ad5761_driver = { + .driver = { + .name = "ad5761", + }, + .probe = ad5761_probe, + .remove = ad5761_remove, + .id_table = ad5761_id, +}; +module_spi_driver(ad5761_driver); + +MODULE_AUTHOR("Ricardo Ribalda "); +MODULE_DESCRIPTION("Analog Devices AD5721, AD5721R, AD5761, AD5761R driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/platform_data/ad5761.h b/include/linux/platform_data/ad5761.h new file mode 100644 index 000000000000..7bd8ed7d978e --- /dev/null +++ b/include/linux/platform_data/ad5761.h @@ -0,0 +1,44 @@ +/* + * AD5721, AD5721R, AD5761, AD5761R, Voltage Output Digital to Analog Converter + * + * Copyright 2016 Qtechnology A/S + * 2016 Ricardo Ribalda + * + * Licensed under the GPL-2. + */ +#ifndef __LINUX_PLATFORM_DATA_AD5761_H__ +#define __LINUX_PLATFORM_DATA_AD5761_H__ + +/** + * enum ad5761_voltage_range - Voltage range the AD5761 is configured for. + * @AD5761_VOLTAGE_RANGE_M10V_10V: -10V to 10V + * @AD5761_VOLTAGE_RANGE_0V_10V: 0V to 10V + * @AD5761_VOLTAGE_RANGE_M5V_5V: -5V to 5V + * @AD5761_VOLTAGE_RANGE_0V_5V: 0V to 5V + * @AD5761_VOLTAGE_RANGE_M2V5_7V5: -2.5V to 7.5V + * @AD5761_VOLTAGE_RANGE_M3V_3V: -3V to 3V + * @AD5761_VOLTAGE_RANGE_0V_16V: 0V to 16V + * @AD5761_VOLTAGE_RANGE_0V_20V: 0V to 20V + */ + +enum ad5761_voltage_range { + AD5761_VOLTAGE_RANGE_M10V_10V, + AD5761_VOLTAGE_RANGE_0V_10V, + AD5761_VOLTAGE_RANGE_M5V_5V, + AD5761_VOLTAGE_RANGE_0V_5V, + AD5761_VOLTAGE_RANGE_M2V5_7V5, + AD5761_VOLTAGE_RANGE_M3V_3V, + AD5761_VOLTAGE_RANGE_0V_16V, + AD5761_VOLTAGE_RANGE_0V_20V, +}; + +/** + * struct ad5761_platform_data - AD5761 DAC driver platform data + * @voltage_range: Voltage range the AD5761 is configured for + */ + +struct ad5761_platform_data { + enum ad5761_voltage_range voltage_range; +}; + +#endif -- cgit v1.2.3 From b6acb0cfc21293a1bfc283e9217f58f7474ef728 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 23 Jan 2016 19:33:10 +0000 Subject: Staging: iio: adc: fix indent on break statement Fix indent warning when building with gcc 6: drivers/staging/iio/adc/ad7192.c:239:4: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] Signed-off-by: Colin Ian King Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 92211039ffa9..92f2b72cce30 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -236,7 +236,7 @@ static int ad7192_setup(struct ad7192_state *st, st->mclk = pdata->ext_clk_hz; else st->mclk = AD7192_INT_FREQ_MHZ; - break; + break; default: ret = -EINVAL; goto out; -- cgit v1.2.3 From 7b08c67fa5ae66c2d07fd506de57de67b7a7e5d6 Mon Sep 17 00:00:00 2001 From: Oren Givon Date: Thu, 21 Jan 2016 11:18:34 +0200 Subject: iwlwifi: add new 3168 series devices support Add new sub-system PCI IDs to the 3168 series. Added 0x2010, 0x2050 and 0x2150 sub-system IDs. Signed-off-by: Oren Givon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 6261a68cae90..944e88ab13a8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -378,7 +378,10 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x3165, 0x8110, iwl3165_2ac_cfg)}, /* 3168 Series */ + {IWL_PCI_DEVICE(0x24FB, 0x2010, iwl3168_2ac_cfg)}, {IWL_PCI_DEVICE(0x24FB, 0x2110, iwl3168_2ac_cfg)}, + {IWL_PCI_DEVICE(0x24FB, 0x2050, iwl3168_2ac_cfg)}, + {IWL_PCI_DEVICE(0x24FB, 0x2150, iwl3168_2ac_cfg)}, {IWL_PCI_DEVICE(0x24FB, 0x0000, iwl3168_2ac_cfg)}, /* 7265 Series */ -- cgit v1.2.3 From 9baa03982b06a62ac817b4983f2da7ca66d4f331 Mon Sep 17 00:00:00 2001 From: Oren Givon Date: Thu, 21 Jan 2016 11:11:11 +0200 Subject: iwlwifi: add device ID for 8265 Signed-off-by: Oren Givon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 944e88ab13a8..00335ea6b3eb 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -478,6 +478,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x24F3, 0x0000, iwl8265_2ac_cfg)}, {IWL_PCI_DEVICE(0x24FD, 0x0010, iwl8265_2ac_cfg)}, {IWL_PCI_DEVICE(0x24FD, 0x8010, iwl8265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x24FD, 0x0810, iwl8265_2ac_cfg)}, /* 9000 Series */ {IWL_PCI_DEVICE(0x9DF0, 0x2A10, iwl5165_2ac_cfg)}, -- cgit v1.2.3 From 947eaebc318d63ada82901cea86c586ac3d854f0 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 24 Jan 2016 22:49:17 +0100 Subject: drm/i915: Update DRIVER_DATE to 20160124 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 204661f9873d..afb0beee9975 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -59,7 +59,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20160111" +#define DRIVER_DATE "20160124" #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */ -- cgit v1.2.3 From ee16bbd289a63e3036d31dcd809e411e9a5dbd5d Mon Sep 17 00:00:00 2001 From: Yakir Yang Date: Fri, 15 Jan 2016 19:54:14 +0800 Subject: clk: rockchip: rk3036: enable the CLK_IGNORE_UNUSED flag for hclk_vio_bus HCLK_VIO_BUS is the noc bus controller clock for display module, due to it shouldn't belong to any driver, but we need it enabled, so just mark it as the CLK_IGNORE_UNUSED flag. Signed-off-by: Yakir Yang Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3036.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index ebce98033fbb..9c317a3b81e5 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -376,7 +376,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { GATE(ACLK_VIO, "aclk_vio", "aclk_disp1_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(6), 13, GFLAGS), GATE(ACLK_LCDC, "aclk_lcdc", "aclk_disp1_pre", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS), - GATE(HCLK_VIO_BUS, "hclk_vio_bus", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(6), 12, GFLAGS), + GATE(HCLK_VIO_BUS, "hclk_vio_bus", "hclk_disp_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(6), 12, GFLAGS), GATE(HCLK_LCDC, "hclk_lcdc", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS), /* hclk_video gates */ -- cgit v1.2.3 From 535ebd428aeb07c3327947281306f2943f2c9faa Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 19 Jan 2016 10:01:08 +0100 Subject: clk: rockchip: rk3368: fix cpuclk mux bit of big cpu-cluster Both clusters have their mux bit in bit 7 of their respective register. For whatever reason the big cluster currently lists bit 15 which is definitly wrong. Fixes: 3536c97a52db ("clk: rockchip: add rk3368 clock controller") Reported-by: Zhang Qing Signed-off-by: Heiko Stuebner Reviewed-by: zhangqing Cc: stable@vger.kernel.org --- drivers/clk/rockchip/clk-rk3368.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index be0ede522269..473b36f0830a 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -165,7 +165,7 @@ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkb_data = { .core_reg = RK3368_CLKSEL_CON(0), .div_core_shift = 0, .div_core_mask = 0x1f, - .mux_core_shift = 15, + .mux_core_shift = 7, }; static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = { -- cgit v1.2.3 From c6d5fe2ca8286f35a79f7345c9378c39d48a1527 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 19 Jan 2016 10:09:22 +0100 Subject: clk: rockchip: rk3368: fix cpuclk core dividers Similar to commit 9880d4277f6a ("clk: rockchip: fix rk3288 cpuclk core dividers") it seems the cpuclk dividers are one to high on the rk3368 as well. And again similar to the previous fix, we opt to make the divider list contain the values to be written to use the same paradigm for them on all supported socs. Fixes: 3536c97a52db ("clk: rockchip: add rk3368 clock controller") Reported-by: Zhang Qing Signed-off-by: Heiko Stuebner Reviewed-by: zhangqing Cc: stable@vger.kernel.org --- drivers/clk/rockchip/clk-rk3368.c | 40 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index 473b36f0830a..82a0c3e528ce 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -218,29 +218,29 @@ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = { } static struct rockchip_cpuclk_rate_table rk3368_cpuclkb_rates[] __initdata = { - RK3368_CPUCLKB_RATE(1512000000, 2, 6, 6), - RK3368_CPUCLKB_RATE(1488000000, 2, 5, 5), - RK3368_CPUCLKB_RATE(1416000000, 2, 5, 5), - RK3368_CPUCLKB_RATE(1200000000, 2, 4, 4), - RK3368_CPUCLKB_RATE(1008000000, 2, 4, 4), - RK3368_CPUCLKB_RATE( 816000000, 2, 3, 3), - RK3368_CPUCLKB_RATE( 696000000, 2, 3, 3), - RK3368_CPUCLKB_RATE( 600000000, 2, 2, 2), - RK3368_CPUCLKB_RATE( 408000000, 2, 2, 2), - RK3368_CPUCLKB_RATE( 312000000, 2, 2, 2), + RK3368_CPUCLKB_RATE(1512000000, 1, 5, 5), + RK3368_CPUCLKB_RATE(1488000000, 1, 4, 4), + RK3368_CPUCLKB_RATE(1416000000, 1, 4, 4), + RK3368_CPUCLKB_RATE(1200000000, 1, 3, 3), + RK3368_CPUCLKB_RATE(1008000000, 1, 3, 3), + RK3368_CPUCLKB_RATE( 816000000, 1, 2, 2), + RK3368_CPUCLKB_RATE( 696000000, 1, 2, 2), + RK3368_CPUCLKB_RATE( 600000000, 1, 1, 1), + RK3368_CPUCLKB_RATE( 408000000, 1, 1, 1), + RK3368_CPUCLKB_RATE( 312000000, 1, 1, 1), }; static struct rockchip_cpuclk_rate_table rk3368_cpuclkl_rates[] __initdata = { - RK3368_CPUCLKL_RATE(1512000000, 2, 7, 7), - RK3368_CPUCLKL_RATE(1488000000, 2, 6, 6), - RK3368_CPUCLKL_RATE(1416000000, 2, 6, 6), - RK3368_CPUCLKL_RATE(1200000000, 2, 5, 5), - RK3368_CPUCLKL_RATE(1008000000, 2, 5, 5), - RK3368_CPUCLKL_RATE( 816000000, 2, 4, 4), - RK3368_CPUCLKL_RATE( 696000000, 2, 3, 3), - RK3368_CPUCLKL_RATE( 600000000, 2, 3, 3), - RK3368_CPUCLKL_RATE( 408000000, 2, 2, 2), - RK3368_CPUCLKL_RATE( 312000000, 2, 2, 2), + RK3368_CPUCLKL_RATE(1512000000, 1, 6, 6), + RK3368_CPUCLKL_RATE(1488000000, 1, 5, 5), + RK3368_CPUCLKL_RATE(1416000000, 1, 5, 5), + RK3368_CPUCLKL_RATE(1200000000, 1, 4, 4), + RK3368_CPUCLKL_RATE(1008000000, 1, 4, 4), + RK3368_CPUCLKL_RATE( 816000000, 1, 3, 3), + RK3368_CPUCLKL_RATE( 696000000, 1, 2, 2), + RK3368_CPUCLKL_RATE( 600000000, 1, 2, 2), + RK3368_CPUCLKL_RATE( 408000000, 1, 1, 1), + RK3368_CPUCLKL_RATE( 312000000, 1, 1, 1), }; static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { -- cgit v1.2.3 From 0f28d98463498c61c61a38aacbf9f69e92e85e9d Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 20 Jan 2016 19:22:38 +0100 Subject: clk: rockchip: rk3368: fix parents of video encoder/decoder The vdpu and vepu clocks can also be parented to the npll and current parent list also is wrong as it would use the npll as "usbphy" source, so adapt the parent to the correct one. Fixes: 3536c97a52db ("clk: rockchip: add rk3368 clock controller") Signed-off-by: Heiko Stuebner Reviewed-by: zhangqing Cc: stable@vger.kernel.org --- drivers/clk/rockchip/clk-rk3368.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index 82a0c3e528ce..990e1dc7529d 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -384,10 +384,10 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { * Clock-Architecture Diagram 3 */ - COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_usb_p, 0, + COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_npll_usb_p, 0, RK3368_CLKSEL_CON(15), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3368_CLKGATE_CON(4), 6, GFLAGS), - COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb_p, 0, + COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_npll_usb_p, 0, RK3368_CLKSEL_CON(15), 14, 2, MFLAGS, 8, 5, DFLAGS, RK3368_CLKGATE_CON(4), 7, GFLAGS), -- cgit v1.2.3 From fd0c0740fac17a014704ef89d8c8b1768711ca59 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 20 Jan 2016 21:47:57 +0100 Subject: clk: rockchip: rk3368: fix hdmi_cec gate-register Fix a typo making the sclk_hdmi_cec access a wrong register to handle its gate. Fixes: 3536c97a52db ("clk: rockchip: add rk3368 clock controller") Signed-off-by: Heiko Stuebner Reviewed-by: zhangqing Cc: stable@vger.kernel.org --- drivers/clk/rockchip/clk-rk3368.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index 990e1dc7529d..7016ed24bbe5 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -442,7 +442,7 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { GATE(SCLK_HDMI_HDCP, "sclk_hdmi_hdcp", "xin24m", 0, RK3368_CLKGATE_CON(4), 13, GFLAGS), GATE(SCLK_HDMI_CEC, "sclk_hdmi_cec", "xin32k", 0, - RK3368_CLKGATE_CON(5), 12, GFLAGS), + RK3368_CLKGATE_CON(4), 12, GFLAGS), COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0, RK3368_CLKSEL_CON(21), 15, 1, MFLAGS, -- cgit v1.2.3 From 6f31ef2c5c3487fc69c2a34573db88b2f46498ba Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 8 Jan 2016 17:14:42 -0800 Subject: clk: sunxi: Drop clk.h include This file is a clock provider, not a clk consumer. Drop the clk.h include. Cc: Jens Kuske Cc: Maxime Ripard Signed-off-by: Stephen Boyd Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-sun8i-bus-gates.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-sun8i-bus-gates.c b/drivers/clk/sunxi/clk-sun8i-bus-gates.c index e32d18ba252b..1113eb98c9b4 100644 --- a/drivers/clk/sunxi/clk-sun8i-bus-gates.c +++ b/drivers/clk/sunxi/clk-sun8i-bus-gates.c @@ -17,7 +17,6 @@ * GNU General Public License for more details. */ -#include #include #include #include -- cgit v1.2.3 From 2d3e8f70317cc6df93465e51f451d41bad32e010 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 22 Dec 2015 12:27:43 +0000 Subject: drivers: sunxi-rsb: fix error output type "len" is actually a size_t in this function here, so properly annotate the dev_err printf type to allow compilation for 64-bit architectures. Signed-off-by: Andre Przywara Acked-by: Arnd Bergmann Signed-off-by: Maxime Ripard --- drivers/bus/sunxi-rsb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c index 25996e256110..795c9d9c96a6 100644 --- a/drivers/bus/sunxi-rsb.c +++ b/drivers/bus/sunxi-rsb.c @@ -330,7 +330,7 @@ static int sunxi_rsb_read(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr, cmd = RSB_CMD_RD32; break; default: - dev_err(rsb->dev, "Invalid access width: %d\n", len); + dev_err(rsb->dev, "Invalid access width: %zd\n", len); return -EINVAL; } @@ -372,7 +372,7 @@ static int sunxi_rsb_write(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr, cmd = RSB_CMD_WR32; break; default: - dev_err(rsb->dev, "Invalid access width: %d\n", len); + dev_err(rsb->dev, "Invalid access width: %zd\n", len); return -EINVAL; } -- cgit v1.2.3 From 4ac7a65f8070098187b1e2afa992848366aae079 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Fri, 22 Jan 2016 15:54:42 -0800 Subject: md-cluster: fix missing memory free There are several places we allocate dlm_lock_resource, but not free it. leave() need free a lock resource too (from Guoqing) Cc: Goldwyn Rodrigues Cc: Guoqing Jiang Cc: NeilBrown Signed-off-by: Shaohua Li --- drivers/md/md-cluster.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c index 0ded8e97751d..dd97d4245822 100644 --- a/drivers/md/md-cluster.c +++ b/drivers/md/md-cluster.c @@ -293,6 +293,7 @@ static void recover_bitmaps(struct md_thread *thread) dlm_unlock: dlm_unlock_sync(bm_lockres); clear_bit: + lockres_free(bm_lockres); clear_bit(slot, &cinfo->recovery_map); } } @@ -682,8 +683,10 @@ static int gather_all_resync_info(struct mddev *mddev, int total_slots) bm_lockres = lockres_init(mddev, str, NULL, 1); if (!bm_lockres) return -ENOMEM; - if (i == (cinfo->slot_number - 1)) + if (i == (cinfo->slot_number - 1)) { + lockres_free(bm_lockres); continue; + } bm_lockres->flags |= DLM_LKF_NOQUEUE; ret = dlm_lock_sync(bm_lockres, DLM_LOCK_PW); @@ -858,6 +861,7 @@ static int leave(struct mddev *mddev) lockres_free(cinfo->token_lockres); lockres_free(cinfo->ack_lockres); lockres_free(cinfo->no_new_dev_lockres); + lockres_free(cinfo->resync_lockres); lockres_free(cinfo->bitmap_lockres); unlock_all_bitmaps(mddev); dlm_release_lockspace(cinfo->lockspace, 2); -- cgit v1.2.3 From fc2561ec0afcd89e2ec6f28a82a9219582844964 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Fri, 22 Jan 2016 16:40:02 -0800 Subject: md-cluster: delete useless code page->index already considers node offset. The node_offset calculation in write_sb_page is useless and confusion. Cc: Goldwyn Rodrigues Cc: NeilBrown Acked-by: Guoqing Jiang Signed-off-by: Shaohua Li --- drivers/md/bitmap.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 4f22e919787a..d80cce499a56 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -210,10 +210,6 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) struct block_device *bdev; struct mddev *mddev = bitmap->mddev; struct bitmap_storage *store = &bitmap->storage; - int node_offset = 0; - - if (mddev_is_clustered(bitmap->mddev)) - node_offset = bitmap->cluster_slot * store->file_pages; while ((rdev = next_active_rdev(rdev, mddev)) != NULL) { int size = PAGE_SIZE; -- cgit v1.2.3 From 6220f4ebd7b4db499238c2dc91268a9c473fd01c Mon Sep 17 00:00:00 2001 From: Thorsten Leemhuis Date: Sun, 17 Jan 2016 16:03:04 +0100 Subject: hwmon: (dell-smm) Blacklist Dell Studio XPS 8000 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since Linux 4.0 the CPU fan speed is going up and down on Dell Studio XPS 8000 and 8100 for unknown reasons. The 8100 was already blacklisted in commit a4b45b25f18d ("hwmon: (dell-smm) Blacklist Dell Studio XPS 8100"). This patch blacklists the XPS 8000. Without further debugging on the affected machine, it is not possible to find the problem. For more details see https://bugzilla.kernel.org/show_bug.cgi?id=100121 Signed-off-by: Thorsten Leemhuis Acked-by: Pali Rohár Cc: stable@vger.kernel.org # v4.0+, will need backport Signed-off-by: Guenter Roeck --- drivers/hwmon/dell-smm-hwmon.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index c8487894b312..c43318d3416e 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c @@ -930,6 +930,17 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = { MODULE_DEVICE_TABLE(dmi, i8k_dmi_table); static struct dmi_system_id i8k_blacklist_dmi_table[] __initdata = { + { + /* + * CPU fan speed going up and down on Dell Studio XPS 8000 + * for unknown reasons. + */ + .ident = "Dell Studio XPS 8000", + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Studio XPS 8000"), + }, + }, { /* * CPU fan speed going up and down on Dell Studio XPS 8100 -- cgit v1.2.3 From 9c2863b53fcd54e40e30d25ac83eca2e31fda1e1 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Tue, 8 Dec 2015 02:32:01 +0200 Subject: usb: ohci: nxp: clean up included header files Remove mach/irq.h from the list of included headers, there is no compilation dependency on this include file, the change is needed to prevent a compilation failure, when mach/irq.h is removed. Additionally remove other unneeded includes. Signed-off-by: Vladimir Zapolskiy Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-nxp.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c index cfa94275c52c..ebacf97fc406 100644 --- a/drivers/usb/host/ohci-nxp.c +++ b/drivers/usb/host/ohci-nxp.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -32,13 +31,7 @@ #include "ohci.h" - #include -#include -#include - -#include -#include #define USB_CONFIG_BASE 0x31020000 #define PWRMAN_BASE 0x40004000 -- cgit v1.2.3 From fcb42e232a2dd3904f09107bf02904b760a0dd9a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 27 Dec 2015 21:50:29 +0100 Subject: usb: renesas_usbhs: constify usbhs_pkt_handle structures The usbhs_pkt_handle structures are never modified, so declare them as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Acked-by: Yoshihiro Shimoda Signed-off-by: Greg Kroah-Hartman --- drivers/usb/renesas_usbhs/fifo.c | 20 ++++++++++---------- drivers/usb/renesas_usbhs/fifo.h | 20 ++++++++++---------- drivers/usb/renesas_usbhs/pipe.h | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index c0f5c652d272..b4de70ee16d3 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -46,7 +46,7 @@ static int usbhsf_null_handle(struct usbhs_pkt *pkt, int *is_done) return -EINVAL; } -static struct usbhs_pkt_handle usbhsf_null_handler = { +static const struct usbhs_pkt_handle usbhsf_null_handler = { .prepare = usbhsf_null_handle, .try_run = usbhsf_null_handle, }; @@ -422,12 +422,12 @@ static int usbhs_dcp_dir_switch_done(struct usbhs_pkt *pkt, int *is_done) return 0; } -struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler = { +const struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler = { .prepare = usbhs_dcp_dir_switch_to_write, .try_run = usbhs_dcp_dir_switch_done, }; -struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler = { +const struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler = { .prepare = usbhs_dcp_dir_switch_to_read, .try_run = usbhs_dcp_dir_switch_done, }; @@ -449,7 +449,7 @@ static int usbhsf_dcp_data_stage_try_push(struct usbhs_pkt *pkt, int *is_done) return pkt->handler->prepare(pkt, is_done); } -struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler = { +const struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler = { .prepare = usbhsf_dcp_data_stage_try_push, }; @@ -488,7 +488,7 @@ static int usbhsf_dcp_data_stage_prepare_pop(struct usbhs_pkt *pkt, return pkt->handler->prepare(pkt, is_done); } -struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler = { +const struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler = { .prepare = usbhsf_dcp_data_stage_prepare_pop, }; @@ -600,7 +600,7 @@ static int usbhsf_pio_prepare_push(struct usbhs_pkt *pkt, int *is_done) return usbhsf_pio_try_push(pkt, is_done); } -struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = { +const struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = { .prepare = usbhsf_pio_prepare_push, .try_run = usbhsf_pio_try_push, }; @@ -730,7 +730,7 @@ usbhs_fifo_read_busy: return ret; } -struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler = { +const struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler = { .prepare = usbhsf_prepare_pop, .try_run = usbhsf_pio_try_pop, }; @@ -747,7 +747,7 @@ static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt, int *is_done) return 0; } -struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler = { +const struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler = { .prepare = usbhsf_ctrl_stage_end, .try_run = usbhsf_ctrl_stage_end, }; @@ -934,7 +934,7 @@ static int usbhsf_dma_push_done(struct usbhs_pkt *pkt, int *is_done) return 0; } -struct usbhs_pkt_handle usbhs_fifo_dma_push_handler = { +const struct usbhs_pkt_handle usbhs_fifo_dma_push_handler = { .prepare = usbhsf_dma_prepare_push, .dma_done = usbhsf_dma_push_done, }; @@ -1182,7 +1182,7 @@ static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done) return usbhsf_dma_pop_done_with_rx_irq(pkt, is_done); } -struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler = { +const struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler = { .prepare = usbhsf_dma_prepare_pop, .try_run = usbhsf_dma_try_pop, .dma_done = usbhsf_dma_pop_done diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h index c7d9b86d51bf..8b98507d7abc 100644 --- a/drivers/usb/renesas_usbhs/fifo.h +++ b/drivers/usb/renesas_usbhs/fifo.h @@ -54,7 +54,7 @@ struct usbhs_pkt_handle; struct usbhs_pkt { struct list_head node; struct usbhs_pipe *pipe; - struct usbhs_pkt_handle *handler; + const struct usbhs_pkt_handle *handler; void (*done)(struct usbhs_priv *priv, struct usbhs_pkt *pkt); struct work_struct work; @@ -86,18 +86,18 @@ void usbhs_fifo_clear_dcp(struct usbhs_pipe *pipe); /* * packet info */ -extern struct usbhs_pkt_handle usbhs_fifo_pio_push_handler; -extern struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler; -extern struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler; +extern const struct usbhs_pkt_handle usbhs_fifo_pio_push_handler; +extern const struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler; +extern const struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler; -extern struct usbhs_pkt_handle usbhs_fifo_dma_push_handler; -extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler; +extern const struct usbhs_pkt_handle usbhs_fifo_dma_push_handler; +extern const struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler; -extern struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler; -extern struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler; +extern const struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler; +extern const struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler; -extern struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler; -extern struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler; +extern const struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler; +extern const struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler; void usbhs_pkt_init(struct usbhs_pkt *pkt); void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index 3212ab51e844..7835747f9803 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -38,7 +38,7 @@ struct usbhs_pipe { #define USBHS_PIPE_FLAGS_IS_DIR_HOST (1 << 2) #define USBHS_PIPE_FLAGS_IS_RUNNING (1 << 3) - struct usbhs_pkt_handle *handler; + const struct usbhs_pkt_handle *handler; void *mod_private; }; -- cgit v1.2.3 From 64f10edf0751727154e843e8bcf59fb659e579a2 Mon Sep 17 00:00:00 2001 From: Chase Metzger Date: Tue, 22 Dec 2015 20:19:45 -0800 Subject: usb: core: devio.c: Removed unnecessary space Removed an unnecessary space between a function name and arguments. Signed-off-by: Chase Metzger Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 59e7a3369084..6aac2425dd9f 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1903,7 +1903,7 @@ static int proc_releaseinterface(struct usb_dev_state *ps, void __user *arg) ret = releaseintf(ps, ifnum); if (ret < 0) return ret; - destroy_async_on_interface (ps, ifnum); + destroy_async_on_interface(ps, ifnum); return 0; } -- cgit v1.2.3 From 73a02d32458ecff5b6241e7e7bd6445f70400bad Mon Sep 17 00:00:00 2001 From: Rahul Pathak Date: Fri, 11 Dec 2015 05:40:51 +0000 Subject: usb: Use memdup_user to reuse the code Fixing coccicheck warning which recommends to use memdup_user instead to reimplement its code, using memdup_user simplifies the code ./drivers/usb/core/devio.c:1398:11-18: WARNING opportunity for memdup_user Signed-off-by: Rahul Pathak Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 6aac2425dd9f..054eb534c495 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1378,11 +1378,10 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb number_of_packets = uurb->number_of_packets; isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * number_of_packets; - isopkt = kmalloc(isofrmlen, GFP_KERNEL); - if (!isopkt) - return -ENOMEM; - if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) { - ret = -EFAULT; + isopkt = memdup_user(iso_frame_desc, isofrmlen); + if (IS_ERR(isopkt)) { + ret = PTR_ERR(isopkt); + isopkt = NULL; goto error; } for (totlen = u = 0; u < number_of_packets; u++) { -- cgit v1.2.3 From 8a1b2725a60d3267135c15e80984b4406054f650 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 10 Dec 2015 09:59:25 +0200 Subject: usb: define USB_SPEED_SUPER_PLUS speed for SuperSpeedPlus USB3.1 devices Add a new USB_SPEED_SUPER_PLUS device speed, and make sure usb core can handle the new speed. In most cases the behaviour is the same as with USB_SPEED_SUPER SuperSpeed devices. In a few places we add a "Plus" string to inform the user of the new speed. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/common/common.c | 1 + drivers/usb/core/config.c | 3 ++- drivers/usb/core/devices.c | 10 ++++++---- drivers/usb/core/hcd-pci.c | 2 +- drivers/usb/core/hcd.c | 6 +++--- drivers/usb/core/hub.c | 26 +++++++++++++++----------- drivers/usb/core/urb.c | 3 ++- drivers/usb/core/usb.h | 2 +- include/uapi/linux/usb/ch9.h | 1 + 9 files changed, 32 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c index e6ec125e4485..49fbfe8b0f24 100644 --- a/drivers/usb/common/common.c +++ b/drivers/usb/common/common.c @@ -51,6 +51,7 @@ static const char *const speed_names[] = { [USB_SPEED_HIGH] = "high-speed", [USB_SPEED_WIRELESS] = "wireless", [USB_SPEED_SUPER] = "super-speed", + [USB_SPEED_SUPER_PLUS] = "super-speed-plus", }; const char *usb_speed_string(enum usb_device_speed speed) diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 5050760f5e17..bbcf4009f99e 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -191,6 +191,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, if (usb_endpoint_xfer_int(d)) { i = 1; switch (to_usb_device(ddev)->speed) { + case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: case USB_SPEED_HIGH: /* Many device manufacturers are using full-speed @@ -274,7 +275,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, } /* Parse a possible SuperSpeed endpoint companion descriptor */ - if (to_usb_device(ddev)->speed == USB_SPEED_SUPER) + if (to_usb_device(ddev)->speed >= USB_SPEED_SUPER) usb_parse_ss_endpoint_companion(ddev, cfgno, inum, asnum, endpoint, buffer, size); diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index cffa0a0d7de2..b35a6a52210f 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -221,7 +221,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, break; case USB_ENDPOINT_XFER_INT: type = "Int."; - if (speed == USB_SPEED_HIGH || speed == USB_SPEED_SUPER) + if (speed == USB_SPEED_HIGH || speed >= USB_SPEED_SUPER) interval = 1 << (desc->bInterval - 1); else interval = desc->bInterval; @@ -230,7 +230,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, return start; } interval *= (speed == USB_SPEED_HIGH || - speed == USB_SPEED_SUPER) ? 125 : 1000; + speed >= USB_SPEED_SUPER) ? 125 : 1000; if (interval % 1000) unit = 'u'; else { @@ -322,7 +322,7 @@ static char *usb_dump_config_descriptor(char *start, char *end, if (start > end) return start; - if (speed == USB_SPEED_SUPER) + if (speed >= USB_SPEED_SUPER) mul = 8; else mul = 2; @@ -534,6 +534,8 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, speed = "480"; break; case USB_SPEED_SUPER: speed = "5000"; break; + case USB_SPEED_SUPER_PLUS: + speed = "10000"; break; default: speed = "??"; } @@ -553,7 +555,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, /* super/high speed reserves 80%, full/low reserves 90% */ if (usbdev->speed == USB_SPEED_HIGH || - usbdev->speed == USB_SPEED_SUPER) + usbdev->speed >= USB_SPEED_SUPER) max = 800; else max = FRAME_TIME_MAX_USECS_ALLOC; diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 9eb1cff28bd4..22a9ac25b850 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -197,7 +197,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) * The xHCI driver has its own irq management * make sure irq setup is not touched for xhci in generic hcd code */ - if ((driver->flags & HCD_MASK) != HCD_USB3) { + if ((driver->flags & HCD_MASK) < HCD_USB3) { if (!dev->irq) { dev_err(&dev->dev, "Found HC with no IRQ. Check BIOS/PCI %s setup!\n", diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index df0e3b92533a..0e38ce60d7d5 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1078,7 +1078,7 @@ static int register_root_hub(struct usb_hcd *hcd) retval = usb_get_bos_descriptor(usb_dev); if (!retval) { usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev); - } else if (usb_dev->speed == USB_SPEED_SUPER) { + } else if (usb_dev->speed >= USB_SPEED_SUPER) { mutex_unlock(&usb_bus_list_lock); dev_dbg(parent_dev, "can't read %s bos descriptor %d\n", dev_name(&usb_dev->dev), retval); @@ -2112,7 +2112,7 @@ int usb_alloc_streams(struct usb_interface *interface, hcd = bus_to_hcd(dev->bus); if (!hcd->driver->alloc_streams || !hcd->driver->free_streams) return -EINVAL; - if (dev->speed != USB_SPEED_SUPER) + if (dev->speed < USB_SPEED_SUPER) return -EINVAL; if (dev->state < USB_STATE_CONFIGURED) return -ENODEV; @@ -2160,7 +2160,7 @@ int usb_free_streams(struct usb_interface *interface, dev = interface_to_usbdev(interface); hcd = bus_to_hcd(dev->bus); - if (dev->speed != USB_SPEED_SUPER) + if (dev->speed < USB_SPEED_SUPER) return -EINVAL; /* Double-free is not allowed */ diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 51b436918f78..6bdff0ad3930 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -298,7 +298,7 @@ static void usb_set_lpm_parameters(struct usb_device *udev) unsigned int hub_u1_del; unsigned int hub_u2_del; - if (!udev->lpm_capable || udev->speed != USB_SPEED_SUPER) + if (!udev->lpm_capable || udev->speed < USB_SPEED_SUPER) return; hub = usb_hub_to_struct_hub(udev->parent); @@ -2645,7 +2645,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub) */ static bool use_new_scheme(struct usb_device *udev, int retry) { - if (udev->speed == USB_SPEED_SUPER) + if (udev->speed >= USB_SPEED_SUPER) return false; return USE_NEW_SCHEME(retry); @@ -3989,7 +3989,7 @@ int usb_disable_lpm(struct usb_device *udev) struct usb_hcd *hcd; if (!udev || !udev->parent || - udev->speed != USB_SPEED_SUPER || + udev->speed < USB_SPEED_SUPER || !udev->lpm_capable || udev->state < USB_STATE_DEFAULT) return 0; @@ -4048,7 +4048,7 @@ void usb_enable_lpm(struct usb_device *udev) struct usb_port *port_dev; if (!udev || !udev->parent || - udev->speed != USB_SPEED_SUPER || + udev->speed < USB_SPEED_SUPER || !udev->lpm_capable || udev->state < USB_STATE_DEFAULT) return; @@ -4323,7 +4323,9 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, retval = -ENODEV; - if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != udev->speed) { + /* Don't allow speed changes at reset, except usb 3.0 to faster */ + if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != udev->speed && + !(oldspeed == USB_SPEED_SUPER && udev->speed > oldspeed)) { dev_dbg(&udev->dev, "device reset changed speed!\n"); goto fail; } @@ -4335,6 +4337,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, * reported as 0xff in the device descriptor). WUSB1.0[4.8.1]. */ switch (udev->speed) { + case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: case USB_SPEED_WIRELESS: /* fixed at 512 */ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512); @@ -4361,7 +4364,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, else speed = usb_speed_string(udev->speed); - if (udev->speed != USB_SPEED_SUPER) + if (udev->speed < USB_SPEED_SUPER) dev_info(&udev->dev, "%s %s USB device number %d using %s\n", (udev->config) ? "reset" : "new", speed, @@ -4485,11 +4488,12 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, devnum, retval); goto fail; } - if (udev->speed == USB_SPEED_SUPER) { + if (udev->speed >= USB_SPEED_SUPER) { devnum = udev->devnum; dev_info(&udev->dev, - "%s SuperSpeed USB device number %d using %s\n", + "%s SuperSpeed%s USB device number %d using %s\n", (udev->config) ? "reset" : "new", + (udev->speed == USB_SPEED_SUPER_PLUS) ? "Plus" : "", devnum, udev->bus->controller->driver->name); } @@ -4528,7 +4532,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, * got from those devices show they aren't superspeed devices. Warm * reset the port attached by the devices can fix them. */ - if ((udev->speed == USB_SPEED_SUPER) && + if ((udev->speed >= USB_SPEED_SUPER) && (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) { dev_err(&udev->dev, "got a wrong device descriptor, " "warm reset device\n"); @@ -4539,7 +4543,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, } if (udev->descriptor.bMaxPacketSize0 == 0xff || - udev->speed == USB_SPEED_SUPER) + udev->speed >= USB_SPEED_SUPER) i = 512; else i = udev->descriptor.bMaxPacketSize0; @@ -4749,7 +4753,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, udev->level = hdev->level + 1; udev->wusb = hub_is_wusb(hub); - /* Only USB 3.0 devices are connected to SuperSpeed hubs. */ + /* Devices connected to SuperSpeed hubs are USB 3.0 or later */ if (hub_is_superspeed(hub->hdev)) udev->speed = USB_SPEED_SUPER; else diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 3d274778caaf..c601e25b609f 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -401,7 +401,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) /* SuperSpeed isoc endpoints have up to 16 bursts of up to * 3 packets each */ - if (dev->speed == USB_SPEED_SUPER) { + if (dev->speed >= USB_SPEED_SUPER) { int burst = 1 + ep->ss_ep_comp.bMaxBurst; int mult = USB_SS_MULT(ep->ss_ep_comp.bmAttributes); max *= burst; @@ -499,6 +499,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) } /* too big? */ switch (dev->speed) { + case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: /* units are 125us */ /* Handle up to 2^(16-1) microframes */ if (urb->interval > (1 << 15)) diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 05b5e17abf92..53318126ed91 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -45,7 +45,7 @@ static inline unsigned usb_get_max_power(struct usb_device *udev, struct usb_host_config *c) { /* SuperSpeed power is in 8 mA units; others are in 2 mA units */ - unsigned mul = (udev->speed == USB_SPEED_SUPER ? 8 : 2); + unsigned mul = (udev->speed >= USB_SPEED_SUPER ? 8 : 2); return c->desc.bMaxPower * mul; } diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h index 4338eb7b09b3..779a62aafafe 100644 --- a/include/uapi/linux/usb/ch9.h +++ b/include/uapi/linux/usb/ch9.h @@ -954,6 +954,7 @@ enum usb_device_speed { USB_SPEED_HIGH, /* usb 2.0 */ USB_SPEED_WIRELESS, /* wireless (usb 2.5) */ USB_SPEED_SUPER, /* usb 3.0 */ + USB_SPEED_SUPER_PLUS, /* usb 3.1 */ }; -- cgit v1.2.3 From 5f9c3a668b3f75768aec686901d7a4c8782983df Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 10 Dec 2015 09:59:26 +0200 Subject: usb: set USB 3.1 roothub device speed to USB_SPEED_SUPER_PLUS A hcd roothub that supports HCD_USB31 is running at SuperSpeedPlus speed Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 0e38ce60d7d5..ff3073d522a8 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2778,9 +2778,11 @@ int usb_add_hcd(struct usb_hcd *hcd, rhdev->speed = USB_SPEED_WIRELESS; break; case HCD_USB3: - case HCD_USB31: rhdev->speed = USB_SPEED_SUPER; break; + case HCD_USB31: + rhdev->speed = USB_SPEED_SUPER_PLUS; + break; default: retval = -EINVAL; goto err_set_rh_speed; -- cgit v1.2.3 From b2316645ca5ea93eb8f637f57199fbbe88bee07d Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 10 Dec 2015 09:59:27 +0200 Subject: usb: show speed "10000" in sysfs for USB 3.1 SuperSpeedPlus devices The same way as SuperSpeed devices show "5000" as device speed we wan't to show "10000" as the default speed for SuperSpeedPlus devices in sysfs. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/sysfs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 65b6e6b84043..f195320d35c0 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -141,6 +141,9 @@ static ssize_t speed_show(struct device *dev, struct device_attribute *attr, case USB_SPEED_SUPER: speed = "5000"; break; + case USB_SPEED_SUPER_PLUS: + speed = "10000"; + break; default: speed = "unknown"; } -- cgit v1.2.3 From 9508e3b7a70c11370d70252147b75d3024754970 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 10 Dec 2015 09:59:28 +0200 Subject: usb: add device descriptor for usb 3.1 root hub Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index ff3073d522a8..bca13a0e0326 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -128,6 +128,27 @@ static inline int is_root_hub(struct usb_device *udev) #define KERNEL_REL bin2bcd(((LINUX_VERSION_CODE >> 16) & 0x0ff)) #define KERNEL_VER bin2bcd(((LINUX_VERSION_CODE >> 8) & 0x0ff)) +/* usb 3.1 root hub device descriptor */ +static const u8 usb31_rh_dev_descriptor[18] = { + 0x12, /* __u8 bLength; */ + USB_DT_DEVICE, /* __u8 bDescriptorType; Device */ + 0x10, 0x03, /* __le16 bcdUSB; v3.1 */ + + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x03, /* __u8 bDeviceProtocol; USB 3 hub */ + 0x09, /* __u8 bMaxPacketSize0; 2^9 = 512 Bytes */ + + 0x6b, 0x1d, /* __le16 idVendor; Linux Foundation 0x1d6b */ + 0x03, 0x00, /* __le16 idProduct; device 0x0003 */ + KERNEL_VER, KERNEL_REL, /* __le16 bcdDevice */ + + 0x03, /* __u8 iManufacturer; */ + 0x02, /* __u8 iProduct; */ + 0x01, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + /* usb 3.0 root hub device descriptor */ static const u8 usb3_rh_dev_descriptor[18] = { 0x12, /* __u8 bLength; */ @@ -557,6 +578,8 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) case USB_DT_DEVICE << 8: switch (hcd->speed) { case HCD_USB31: + bufp = usb31_rh_dev_descriptor; + break; case HCD_USB3: bufp = usb3_rh_dev_descriptor; break; -- cgit v1.2.3 From 0cdd49a1d1a483d80170d9e592f832274e8bce1b Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 10 Dec 2015 09:59:29 +0200 Subject: usb: Support USB 3.1 extended port status request usb 3.1 extend the hub get-port-status request by adding different request types. the new request types return 4 additional bytes called extended port status, these bytes are returned after the regular portstatus and portchange values. The extended port status contains a speed ID for the currently used sublink speed. A table of supported Speed IDs with details about the link is provided by the hub in the device descriptor BOS SuperSpeedPlus device capability Sublink Speed Attributes. Support this new request. Ask for the extended port status after port reset if hub supports USB 3.1. If link is running at SuperSpeedPlus set the device speed to USB_SPEED_SUPER_PLUS Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 8 ++++- drivers/usb/core/hub.c | 70 +++++++++++++++++++++++++++++++++++++------ drivers/usb/core/hub.h | 7 +++++ include/uapi/linux/usb/ch11.h | 21 +++++++++++++ 4 files changed, 96 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index bca13a0e0326..9af9506352f3 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -668,9 +668,15 @@ nongeneric: /* non-generic request */ switch (typeReq) { case GetHubStatus: - case GetPortStatus: len = 4; break; + case GetPortStatus: + if (wValue == HUB_PORT_STATUS) + len = 4; + else + /* other port status types return 8 bytes */ + len = 8; + break; case GetHubDescriptor: len = sizeof (struct usb_hub_descriptor); break; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 6bdff0ad3930..3c9b22eb78ca 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -537,29 +537,34 @@ static int get_hub_status(struct usb_device *hdev, /* * USB 2.0 spec Section 11.24.2.7 + * USB 3.1 takes into use the wValue and wLength fields, spec Section 10.16.2.6 */ static int get_port_status(struct usb_device *hdev, int port1, - struct usb_port_status *data) + void *data, u16 value, u16 length) { int i, status = -ETIMEDOUT; for (i = 0; i < USB_STS_RETRIES && (status == -ETIMEDOUT || status == -EPIPE); i++) { status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), - USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port1, - data, sizeof(*data), USB_STS_TIMEOUT); + USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, value, + port1, data, length, USB_STS_TIMEOUT); } return status; } -static int hub_port_status(struct usb_hub *hub, int port1, - u16 *status, u16 *change) +static int hub_ext_port_status(struct usb_hub *hub, int port1, int type, + u16 *status, u16 *change, u32 *ext_status) { int ret; + int len = 4; + + if (type != HUB_PORT_STATUS) + len = 8; mutex_lock(&hub->status_mutex); - ret = get_port_status(hub->hdev, port1, &hub->status->port); - if (ret < 4) { + ret = get_port_status(hub->hdev, port1, &hub->status->port, type, len); + if (ret < len) { if (ret != -ENODEV) dev_err(hub->intfdev, "%s failed (err = %d)\n", __func__, ret); @@ -568,13 +573,22 @@ static int hub_port_status(struct usb_hub *hub, int port1, } else { *status = le16_to_cpu(hub->status->port.wPortStatus); *change = le16_to_cpu(hub->status->port.wPortChange); - + if (type != HUB_PORT_STATUS && ext_status) + *ext_status = le32_to_cpu( + hub->status->port.dwExtPortStatus); ret = 0; } mutex_unlock(&hub->status_mutex); return ret; } +static int hub_port_status(struct usb_hub *hub, int port1, + u16 *status, u16 *change) +{ + return hub_ext_port_status(hub, port1, HUB_PORT_STATUS, + status, change, NULL); +} + static void kick_hub_wq(struct usb_hub *hub) { struct usb_interface *intf; @@ -2612,6 +2626,32 @@ out_authorized: return result; } +/* + * Return 1 if port speed is SuperSpeedPlus, 0 otherwise + * check it from the link protocol field of the current speed ID attribute. + * current speed ID is got from ext port status request. Sublink speed attribute + * table is returned with the hub BOS SSP device capability descriptor + */ +static int port_speed_is_ssp(struct usb_device *hdev, int speed_id) +{ + int ssa_count; + u32 ss_attr; + int i; + struct usb_ssp_cap_descriptor *ssp_cap = hdev->bos->ssp_cap; + + if (!ssp_cap) + return 0; + + ssa_count = le32_to_cpu(ssp_cap->bmAttributes) & + USB_SSP_SUBLINK_SPEED_ATTRIBS; + + for (i = 0; i <= ssa_count; i++) { + ss_attr = le32_to_cpu(ssp_cap->bmSublinkSpeedAttr[i]); + if (speed_id == (ss_attr & USB_SSP_SUBLINK_SPEED_SSID)) + return !!(ss_attr & USB_SSP_SUBLINK_SPEED_LP); + } + return 0; +} /* Returns 1 if @hub is a WUSB root hub, 0 otherwise */ static unsigned hub_is_wusb(struct usb_hub *hub) @@ -2676,6 +2716,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, int delay_time, ret; u16 portstatus; u16 portchange; + u32 ext_portstatus = 0; for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT; @@ -2684,7 +2725,14 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, msleep(delay); /* read and decode port status */ - ret = hub_port_status(hub, port1, &portstatus, &portchange); + if (hub_is_superspeedplus(hub->hdev)) + ret = hub_ext_port_status(hub, port1, + HUB_EXT_PORT_STATUS, + &portstatus, &portchange, + &ext_portstatus); + else + ret = hub_port_status(hub, port1, &portstatus, + &portchange); if (ret < 0) return ret; @@ -2727,6 +2775,10 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, if (hub_is_wusb(hub)) udev->speed = USB_SPEED_WIRELESS; + else if (hub_is_superspeedplus(hub->hdev) && + port_speed_is_ssp(hub->hdev, ext_portstatus & + USB_EXT_PORT_STAT_RX_SPEED_ID)) + udev->speed = USB_SPEED_SUPER_PLUS; else if (hub_is_superspeed(hub->hdev)) udev->speed = USB_SPEED_SUPER; else if (portstatus & USB_PORT_STAT_HIGH_SPEED) diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 45d070dd1d03..34c1a7e22aae 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -140,6 +140,13 @@ static inline int hub_is_superspeed(struct usb_device *hdev) return hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS; } +static inline int hub_is_superspeedplus(struct usb_device *hdev) +{ + return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS && + le16_to_cpu(hdev->descriptor.bcdUSB) >= 0x0310 && + hdev->bos->ssp_cap); +} + static inline unsigned hub_power_on_good_delay(struct usb_hub *hub) { unsigned delay = hub->descriptor->bPwrOn2PwrGood * 2; diff --git a/include/uapi/linux/usb/ch11.h b/include/uapi/linux/usb/ch11.h index 331499d597fa..361297e96f58 100644 --- a/include/uapi/linux/usb/ch11.h +++ b/include/uapi/linux/usb/ch11.h @@ -29,6 +29,14 @@ #define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE) #define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER) +/* + * Port status type for GetPortStatus requests added in USB 3.1 + * See USB 3.1 spec Table 10-12 + */ +#define HUB_PORT_STATUS 0 +#define HUB_PORT_PD_STATUS 1 +#define HUB_EXT_PORT_STATUS 2 + /* * Hub class requests * See USB 2.0 spec Table 11-16 @@ -97,10 +105,13 @@ /* * Hub Status and Hub Change results * See USB 2.0 spec Table 11-19 and Table 11-20 + * USB 3.1 extends the port status request and may return 4 additional bytes. + * See USB 3.1 spec section 10.16.2.6 Table 10-12 and 10-15 */ struct usb_port_status { __le16 wPortStatus; __le16 wPortChange; + __le32 dwExtPortStatus; } __attribute__ ((packed)); /* @@ -172,6 +183,16 @@ struct usb_port_status { #define USB_PORT_STAT_C_LINK_STATE 0x0040 #define USB_PORT_STAT_C_CONFIG_ERROR 0x0080 +/* + * USB 3.1 dwExtPortStatus field masks + * See USB 3.1 spec 10.16.2.6.3 Table 10-15 + */ + +#define USB_EXT_PORT_STAT_RX_SPEED_ID 0x0000000f +#define USB_EXT_PORT_STAT_TX_SPEED_ID 0x000000f0 +#define USB_EXT_PORT_STAT_RX_LANES 0x00000f00 +#define USB_EXT_PORT_STAT_TX_LANES 0x0000f000 + /* * wHubCharacteristics (masks) * See USB 2.0 spec Table 11-13, offset 3 -- cgit v1.2.3 From d58593426e5cf41009f2e9d6eec3f47fe0cbedeb Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Mon, 28 Dec 2015 23:00:15 +0800 Subject: extcon: Use to_i2c_client for both rt8973a and sm5502 Use to_i2c_client() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-rt8973a.c | 4 ++-- drivers/extcon/extcon-sm5502.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-rt8973a.c b/drivers/extcon/extcon-rt8973a.c index e1bb82809bef..7635a8eaf4c6 100644 --- a/drivers/extcon/extcon-rt8973a.c +++ b/drivers/extcon/extcon-rt8973a.c @@ -663,7 +663,7 @@ MODULE_DEVICE_TABLE(of, rt8973a_dt_match); #ifdef CONFIG_PM_SLEEP static int rt8973a_muic_suspend(struct device *dev) { - struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); + struct i2c_client *i2c = to_i2c_client(dev); struct rt8973a_muic_info *info = i2c_get_clientdata(i2c); enable_irq_wake(info->irq); @@ -673,7 +673,7 @@ static int rt8973a_muic_suspend(struct device *dev) static int rt8973a_muic_resume(struct device *dev) { - struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); + struct i2c_client *i2c = to_i2c_client(dev); struct rt8973a_muic_info *info = i2c_get_clientdata(i2c); disable_irq_wake(info->irq); diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c index 7aac3cc7efd7..571de2e6e7c4 100644 --- a/drivers/extcon/extcon-sm5502.c +++ b/drivers/extcon/extcon-sm5502.c @@ -655,7 +655,7 @@ MODULE_DEVICE_TABLE(of, sm5502_dt_match); #ifdef CONFIG_PM_SLEEP static int sm5502_muic_suspend(struct device *dev) { - struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); + struct i2c_client *i2c = to_i2c_client(dev); struct sm5502_muic_info *info = i2c_get_clientdata(i2c); enable_irq_wake(info->irq); @@ -665,7 +665,7 @@ static int sm5502_muic_suspend(struct device *dev) static int sm5502_muic_resume(struct device *dev) { - struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); + struct i2c_client *i2c = to_i2c_client(dev); struct sm5502_muic_info *info = i2c_get_clientdata(i2c); disable_irq_wake(info->irq); -- cgit v1.2.3 From b51b387020ee1c2bc27bf9121ca9b9d4113e433d Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Wed, 23 Dec 2015 21:34:07 -0800 Subject: extcon: gpio: Fix typo in comment This patch fixes the typo in comment of extcon-gpio.c driver. - 'interrput' -> 'interrupt' Signed-off-by: Moritz Fischer Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index 279ff8f6637d..d023789f0fda 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c @@ -126,7 +126,7 @@ static int gpio_extcon_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&data->work, gpio_extcon_work); /* - * Request the interrput of gpio to detect whether external connector + * Request the interrupt of gpio to detect whether external connector * is attached or detached. */ ret = devm_request_any_context_irq(&pdev->dev, data->irq, -- cgit v1.2.3 From 8b45b6a0741678902810d7be95e635c210fbb198 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 9 Nov 2015 10:10:15 +0900 Subject: extcon: Add the EXTCON_CHG_USB_SDP to support SDP charing port This patch adds the new EXTCON_CHG_USB_SDP connector to support SDP (Standard Downstream Port) USB charging port. The commit 11eecf910bd8 ("extcon: Modify the id and name of external connector") add the new EXTCON_CHG_USB_SDP connector which support the both data transfer and usb charging at the same time. Signed-off-by: Chanwoo Choi Reviewed-by: Krzysztof Kozlowski --- drivers/extcon/extcon-max14577.c | 3 +++ drivers/extcon/extcon-max77693.c | 12 +++++++++++- drivers/extcon/extcon-max77843.c | 3 +++ drivers/extcon/extcon-max8997.c | 3 +++ drivers/extcon/extcon-rt8973a.c | 4 ++++ drivers/extcon/extcon-sm5502.c | 4 ++++ 6 files changed, 28 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-max14577.c b/drivers/extcon/extcon-max14577.c index b30ab97ce75f..852a7112f451 100644 --- a/drivers/extcon/extcon-max14577.c +++ b/drivers/extcon/extcon-max14577.c @@ -150,6 +150,7 @@ enum max14577_muic_acc_type { static const unsigned int max14577_extcon_cable[] = { EXTCON_USB, + EXTCON_CHG_USB_SDP, EXTCON_CHG_USB_DCP, EXTCON_CHG_USB_FAST, EXTCON_CHG_USB_SLOW, @@ -454,6 +455,8 @@ static int max14577_muic_chg_handler(struct max14577_muic_info *info) return ret; extcon_set_cable_state_(info->edev, EXTCON_USB, attached); + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + attached); break; case MAX14577_CHARGER_TYPE_DEDICATED_CHG: extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_DCP, diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index fdf8f5d4d4e9..f17cb76b567c 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -204,6 +204,7 @@ enum max77693_muic_acc_type { static const unsigned int max77693_extcon_cable[] = { EXTCON_USB, EXTCON_USB_HOST, + EXTCON_CHG_USB_SDP, EXTCON_CHG_USB_DCP, EXTCON_CHG_USB_FAST, EXTCON_CHG_USB_SLOW, @@ -512,8 +513,11 @@ static int max77693_muic_dock_handler(struct max77693_muic_info *info, break; case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: /* Dock-Audio */ dock_id = EXTCON_DOCK; - if (!attached) + if (!attached) { extcon_set_cable_state_(info->edev, EXTCON_USB, false); + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + false); + } break; default: dev_err(info->dev, "failed to detect %s dock device\n", @@ -601,6 +605,8 @@ static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info) if (ret < 0) return ret; extcon_set_cable_state_(info->edev, EXTCON_USB, attached); + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + attached); break; case MAX77693_MUIC_GND_MHL: case MAX77693_MUIC_GND_MHL_VB: @@ -830,6 +836,8 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info) */ extcon_set_cable_state_(info->edev, EXTCON_USB, attached); + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + attached); if (!cable_attached) extcon_set_cable_state_(info->edev, EXTCON_DOCK, @@ -899,6 +907,8 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info) extcon_set_cable_state_(info->edev, EXTCON_USB, attached); + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + attached); break; case MAX77693_CHARGER_TYPE_DEDICATED_CHG: /* Only TA cable */ diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c index 74dfb7f4f277..7bbc30097771 100644 --- a/drivers/extcon/extcon-max77843.c +++ b/drivers/extcon/extcon-max77843.c @@ -122,6 +122,7 @@ enum max77843_muic_charger_type { static const unsigned int max77843_extcon_cable[] = { EXTCON_USB, EXTCON_USB_HOST, + EXTCON_CHG_USB_SDP, EXTCON_CHG_USB_DCP, EXTCON_CHG_USB_CDP, EXTCON_CHG_USB_FAST, @@ -486,6 +487,8 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info) return ret; extcon_set_cable_state_(info->edev, EXTCON_USB, attached); + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + attached); break; case MAX77843_MUIC_CHG_DOWNSTREAM: ret = max77843_muic_set_path(info, diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c index b2b13b3dce14..9a89320d09a8 100644 --- a/drivers/extcon/extcon-max8997.c +++ b/drivers/extcon/extcon-max8997.c @@ -148,6 +148,7 @@ struct max8997_muic_info { static const unsigned int max8997_extcon_cable[] = { EXTCON_USB, EXTCON_USB_HOST, + EXTCON_CHG_USB_SDP, EXTCON_CHG_USB_DCP, EXTCON_CHG_USB_FAST, EXTCON_CHG_USB_SLOW, @@ -334,6 +335,8 @@ static int max8997_muic_handle_usb(struct max8997_muic_info *info, break; case MAX8997_USB_DEVICE: extcon_set_cable_state_(info->edev, EXTCON_USB, attached); + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + attached); break; default: dev_err(info->dev, "failed to detect %s usb cable\n", diff --git a/drivers/extcon/extcon-rt8973a.c b/drivers/extcon/extcon-rt8973a.c index 7635a8eaf4c6..97e074d70eca 100644 --- a/drivers/extcon/extcon-rt8973a.c +++ b/drivers/extcon/extcon-rt8973a.c @@ -93,6 +93,7 @@ static struct reg_data rt8973a_reg_data[] = { static const unsigned int rt8973a_extcon_cable[] = { EXTCON_USB, EXTCON_USB_HOST, + EXTCON_CHG_USB_SDP, EXTCON_CHG_USB_DCP, EXTCON_JIG, EXTCON_NONE, @@ -398,6 +399,9 @@ static int rt8973a_muic_cable_handler(struct rt8973a_muic_info *info, /* Change the state of external accessory */ extcon_set_cable_state_(info->edev, id, attached); + if (id == EXTCON_USB) + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + attached); return 0; } diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c index 571de2e6e7c4..df769a17e736 100644 --- a/drivers/extcon/extcon-sm5502.c +++ b/drivers/extcon/extcon-sm5502.c @@ -95,6 +95,7 @@ static struct reg_data sm5502_reg_data[] = { static const unsigned int sm5502_extcon_cable[] = { EXTCON_USB, EXTCON_USB_HOST, + EXTCON_CHG_USB_SDP, EXTCON_CHG_USB_DCP, EXTCON_NONE, }; @@ -411,6 +412,9 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info, /* Change the state of external accessory */ extcon_set_cable_state_(info->edev, id, attached); + if (id == EXTCON_USB) + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + attached); return 0; } -- cgit v1.2.3 From 03bf1adbd68d349eaccf16d42e0ef7e368c3716a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 29 Dec 2015 16:32:03 +0000 Subject: extcon: arizona: Use DAPM mutex helper functions We should be using the helper functions to lock the DAPM mutex not accessing it directly. There are no ill effects of this as the moment but it is best practice, and the implementation could be changed in the future. Signed-off-by: Charles Keepax Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-arizona.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index c121d01a5cd6..1d8e0a57bd51 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c @@ -185,7 +185,7 @@ static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info, break; }; - mutex_lock(&arizona->dapm->card->dapm_mutex); + snd_soc_dapm_mutex_lock(arizona->dapm); arizona->hpdet_clamp = clamp; @@ -227,7 +227,7 @@ static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info, ret); } - mutex_unlock(&arizona->dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(arizona->dapm); } static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode) -- cgit v1.2.3 From c9784a467380dfbd8070c735e651af07331172d9 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Thu, 7 Jan 2016 08:39:33 +0800 Subject: dmaengine: dw: fix a typo for bitfields of CTL_LO The offset of SINC should be 9, not 7, here fix this typo. Signed-off-by: Jie Yang Acked-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/dw/regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h index 241ff2b1402b..0a50c18d85b8 100644 --- a/drivers/dma/dw/regs.h +++ b/drivers/dma/dw/regs.h @@ -150,7 +150,7 @@ enum dw_dma_msize { #define DWC_CTLL_DST_INC (0<<7) /* DAR update/not */ #define DWC_CTLL_DST_DEC (1<<7) #define DWC_CTLL_DST_FIX (2<<7) -#define DWC_CTLL_SRC_INC (0<<7) /* SAR update/not */ +#define DWC_CTLL_SRC_INC (0<<9) /* SAR update/not */ #define DWC_CTLL_SRC_DEC (1<<9) #define DWC_CTLL_SRC_FIX (2<<9) #define DWC_CTLL_DST_MSIZE(n) ((n)<<11) /* burst, #elements */ -- cgit v1.2.3 From 94901e1b24496f04bd59176b7f87406e71505e27 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Thu, 7 Jan 2016 23:05:48 +0100 Subject: dmaengine: ep93xx: Treat STALL and NFB IRQs same way Debugging ALSA hangups it was found that EP9302 (latest E2 rev.) DMA controller sometimes asserts STALL interrupt instead of NFB interrupt. Simply ignoring the difference and simply acting upon the amount of data we still have to transfer seems to work fine. This somehow sounds similar to M2M issue which is already dealt with in the driver, when the controller asserts DONE interrupt too early. The issue is not documented in Cirrus Logic erratas for EP93XX, but original Cirrus DMA driver from 2003 (not based on DMA API) did the similar handling of STALL interrupt. In-tree driver (6d831c65) did it also, before conversion to DMA engine API. Signed-off-by: Alexander Sverdlin Signed-off-by: Vinod Koul --- drivers/dma/ep93xx_dma.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index 57ff46284f15..21f08cc3352b 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c @@ -421,23 +421,25 @@ static int m2p_hw_interrupt(struct ep93xx_dma_chan *edmac) desc->size); } - switch (irq_status & (M2P_INTERRUPT_STALL | M2P_INTERRUPT_NFB)) { - case M2P_INTERRUPT_STALL: - /* Disable interrupts */ - control = readl(edmac->regs + M2P_CONTROL); - control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT); - m2p_set_control(edmac, control); - - return INTERRUPT_DONE; - - case M2P_INTERRUPT_NFB: - if (ep93xx_dma_advance_active(edmac)) - m2p_fill_desc(edmac); + /* + * Even latest E2 silicon revision sometimes assert STALL interrupt + * instead of NFB. Therefore we treat them equally, basing on the + * amount of data we still have to transfer. + */ + if (!(irq_status & (M2P_INTERRUPT_STALL | M2P_INTERRUPT_NFB))) + return INTERRUPT_UNKNOWN; + if (ep93xx_dma_advance_active(edmac)) { + m2p_fill_desc(edmac); return INTERRUPT_NEXT_BUFFER; } - return INTERRUPT_UNKNOWN; + /* Disable interrupts */ + control = readl(edmac->regs + M2P_CONTROL); + control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT); + m2p_set_control(edmac, control); + + return INTERRUPT_DONE; } /* -- cgit v1.2.3 From 8319f84adb49b5c6d69bbce86442e26c2277376f Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Fri, 8 Jan 2016 14:48:17 -0700 Subject: dmaengine: ioatdma: Squelch framesize warnings CC [M] drivers/dma/ioat/prep.o drivers/dma/ioat/prep.c: In function 'ioat_prep_pqxor': drivers/dma/ioat/prep.c:682:1: warning: the frame size of 1048 bytes is larger than 1024 bytes [-Wframe-larger-than=] } ^ drivers/dma/ioat/prep.c: In function 'ioat_prep_pqxor_val': drivers/dma/ioat/prep.c:714:1: warning: the frame size of 1048 bytes is larger than 1024 bytes [-Wframe-larger-than=] } gcc version 5.3.1 20151219 (Ubuntu 5.3.1-4ubuntu1) Cc: Vinod Koul Cc: Dan Williams Cc: Dave Jiang Cc: Prarit Bhargava Cc: Nicholas Mc Guire Cc: Jarkko Nikula Signed-off-by: Tim Gardner Signed-off-by: Vinod Koul --- drivers/dma/ioat/prep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/ioat/prep.c b/drivers/dma/ioat/prep.c index 6bb4a13a8fbd..243421af888f 100644 --- a/drivers/dma/ioat/prep.c +++ b/drivers/dma/ioat/prep.c @@ -26,7 +26,7 @@ #include "hw.h" #include "dma.h" -#define MAX_SCF 1024 +#define MAX_SCF 256 /* provide a lookup table for setting the source address in the base or * extended descriptor of an xor or pq descriptor -- cgit v1.2.3 From cae058610465029cee113ac41c7f5cf881f5cfed Mon Sep 17 00:00:00 2001 From: Sriram Dash Date: Thu, 17 Dec 2015 17:02:35 +0530 Subject: drivers/usb/host: fsl: Set DMA_MASK of usb platform device Set DMA_MASK of usb platform device properly. Signed-off-by: Sriram Dash Signed-off-by: Ramneek Mehresh Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fsl-mph-dr-of.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 0c382652a399..1044b0f9d656 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -17,6 +17,7 @@ #include #include #include +#include struct fsl_usb2_dev_data { char *dr_mode; /* controller mode */ @@ -96,7 +97,11 @@ static struct platform_device *fsl_usb2_device_register( pdev->dev.parent = &ofdev->dev; pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask; - *pdev->dev.dma_mask = *ofdev->dev.dma_mask; + + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &ofdev->dev.coherent_dma_mask; + else + dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); retval = platform_device_add_data(pdev, pdata, sizeof(*pdata)); if (retval) -- cgit v1.2.3 From 6f5429d986f81a5c16d451c5d63d829a785f470a Mon Sep 17 00:00:00 2001 From: Sriram Dash Date: Fri, 18 Dec 2015 14:16:29 +0530 Subject: drivers/usb/host/fsl: Port USB EHCI host driver for LS102xA Change Power architecture specific APIs such as in_be32/out_be32 for registers read/write. Instead using ioread/writebe32 which are defined for power as well as arm architecture Signed-off-by: Nikhil Badola Signed-off-by: Sriram Dash Signed-off-by: Ramneek Mehresh Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-fsl.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 3b6eb219de1a..9f5ffb629973 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "ehci.h" #include "ehci-fsl.h" @@ -241,7 +242,8 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, * to portsc */ if (pdata->check_phy_clk_valid) { - if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & PHY_CLK_VALID)) { + if (!(ioread32be(non_ehci + FSL_SOC_USB_CTRL) & + PHY_CLK_VALID)) { dev_warn(hcd->self.controller, "USB PHY clock invalid\n"); return -EINVAL; @@ -273,9 +275,11 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci) /* Setup Snooping for all the 4GB space */ /* SNOOP1 starts from 0x0, size 2G */ - out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0 | SNOOP_SIZE_2GB); + iowrite32be(0x0 | SNOOP_SIZE_2GB, + non_ehci + FSL_SOC_USB_SNOOP1); /* SNOOP2 starts from 0x80000000, size 2G */ - out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB); + iowrite32be(0x80000000 | SNOOP_SIZE_2GB, + non_ehci + FSL_SOC_USB_SNOOP2); } /* Deal with USB erratum A-005275 */ @@ -309,13 +313,13 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci) if (pdata->have_sysif_regs) { #ifdef CONFIG_FSL_SOC_BOOKE - out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008); - out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080); + iowrite32be(0x00000008, non_ehci + FSL_SOC_USB_PRICTRL); + iowrite32be(0x00000080, non_ehci + FSL_SOC_USB_AGECNTTHRSH); #else - out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c); - out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040); + iowrite32be(0x0000000c, non_ehci + FSL_SOC_USB_PRICTRL); + iowrite32be(0x00000040, non_ehci + FSL_SOC_USB_AGECNTTHRSH); #endif - out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); + iowrite32be(0x00000001, non_ehci + FSL_SOC_USB_SICTRL); } return 0; @@ -554,7 +558,7 @@ static int ehci_fsl_drv_suspend(struct device *dev) if (!fsl_deep_sleep()) return 0; - ehci_fsl->usb_ctrl = in_be32(non_ehci + FSL_SOC_USB_CTRL); + ehci_fsl->usb_ctrl = ioread32be(non_ehci + FSL_SOC_USB_CTRL); return 0; } @@ -577,7 +581,7 @@ static int ehci_fsl_drv_resume(struct device *dev) usb_root_hub_lost_power(hcd->self.root_hub); /* Restore USB PHY settings and enable the controller. */ - out_be32(non_ehci + FSL_SOC_USB_CTRL, ehci_fsl->usb_ctrl); + iowrite32be(ehci_fsl->usb_ctrl, non_ehci + FSL_SOC_USB_CTRL); ehci_reset(ehci); ehci_fsl_reinit(ehci); -- cgit v1.2.3 From f8868ed0078a8456ac725103a97cbe6d833e13f3 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 10 Dec 2015 16:49:14 +0200 Subject: usb: core: use kbasename() instead of open-coded variant kbasename() helper is dedicated to find a last part of the filename or pathname. USB core uses open-coded variant of that helper. Replace some lines of code by kbasename() call. The current users do not have trailing slash and we are on the safe side to make such change. I dig a history of the code under question up and found the patch [1] that brought it along with the same to tty layer. The check for trailing slash looks like copy'n'paste thing and I consider it as redundant. [1] http://www.kernel.org/pub/linux/kernel//people/akpm/patches/2.5/2.5.69/2.5.69-mm3/broken-out/linus.patch Signed-off-by: Andy Shevchenko Cc: Greg Kroah-Hartman Cc: Rasmus Villemoes Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/file.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index ea337a718cc1..822ced9639aa 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "usb.h" @@ -155,7 +156,6 @@ int usb_register_dev(struct usb_interface *intf, int minor_base = class_driver->minor_base; int minor; char name[20]; - char *temp; #ifdef CONFIG_USB_DYNAMIC_MINORS /* @@ -192,14 +192,9 @@ int usb_register_dev(struct usb_interface *intf, /* create a usb class device for this usb interface */ snprintf(name, sizeof(name), class_driver->name, minor - minor_base); - temp = strrchr(name, '/'); - if (temp && (temp[1] != '\0')) - ++temp; - else - temp = name; intf->usb_dev = device_create(usb_class->class, &intf->dev, MKDEV(USB_MAJOR, minor), class_driver, - "%s", temp); + "%s", kbasename(name)); if (IS_ERR(intf->usb_dev)) { down_write(&minor_rwsem); usb_minors[minor] = NULL; -- cgit v1.2.3 From 352d9e2ee85b43170388599a17cd7b219f270163 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 5 Dec 2015 13:15:06 +0100 Subject: USB: bcma: make helper creating platform dev more generic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Having "bool ohci" argument in bcma_hcd_create_pdev function limited it to support two cases only (OHCI and EHCI) and put too much logic in it. Lets make caller pass all required data. This adds few extra arguments to the function call but will allow us to reuse this code and handle more cases in the future (e.g. add XHCI support). Signed-off-by: Rafał Miłecki Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/bcma-hcd.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c index 291aaa2baed8..dea12e9085ce 100644 --- a/drivers/usb/host/bcma-hcd.c +++ b/drivers/usb/host/bcma-hcd.c @@ -244,7 +244,10 @@ static const struct usb_ehci_pdata ehci_pdata = { static const struct usb_ohci_pdata ohci_pdata = { }; -static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr) +static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, + const char *name, u32 addr, + const void *data, + size_t size) { struct platform_device *hci_dev; struct resource hci_res[2]; @@ -259,8 +262,7 @@ static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, boo hci_res[1].start = dev->irq; hci_res[1].flags = IORESOURCE_IRQ; - hci_dev = platform_device_alloc(ohci ? "ohci-platform" : - "ehci-platform" , 0); + hci_dev = platform_device_alloc(name, 0); if (!hci_dev) return ERR_PTR(-ENOMEM); @@ -271,12 +273,8 @@ static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, boo ARRAY_SIZE(hci_res)); if (ret) goto err_alloc; - if (ohci) - ret = platform_device_add_data(hci_dev, &ohci_pdata, - sizeof(ohci_pdata)); - else - ret = platform_device_add_data(hci_dev, &ehci_pdata, - sizeof(ehci_pdata)); + if (data) + ret = platform_device_add_data(hci_dev, data, size); if (ret) goto err_alloc; ret = platform_device_add(hci_dev); @@ -333,11 +331,15 @@ static int bcma_hcd_probe(struct bcma_device *dev) && chipinfo->rev == 0) ohci_addr = 0x18009000; - usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr); + usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, "ohci-platform", + ohci_addr, &ohci_pdata, + sizeof(ohci_pdata)); if (IS_ERR(usb_dev->ohci_dev)) return PTR_ERR(usb_dev->ohci_dev); - usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr); + usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, "ehci-platform", + dev->addr, &ehci_pdata, + sizeof(ehci_pdata)); if (IS_ERR(usb_dev->ehci_dev)) { err = PTR_ERR(usb_dev->ehci_dev); goto err_unregister_ohci_dev; -- cgit v1.2.3 From adbff3a4f93d8501e8ae11906268e21b086d57ed Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 5 Dec 2015 13:15:07 +0100 Subject: USB: bcma: separate code initializing USB 2.0 core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This splits one big probing function into two smaller ones. The main one is now responsible for the generic stuff: allocating memory & enabling power using GPIO. The new one contains code that is specific to the USB 2.0 bcma core. This will allow adding support for the USB 3.0 bcma core (handling XHCI) in the future. Signed-off-by: Rafał Miłecki Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/bcma-hcd.c | 59 ++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c index dea12e9085ce..963e2d0e8f92 100644 --- a/drivers/usb/host/bcma-hcd.c +++ b/drivers/usb/host/bcma-hcd.c @@ -35,6 +35,7 @@ MODULE_DESCRIPTION("Common USB driver for BCMA Bus"); MODULE_LICENSE("GPL"); struct bcma_hcd_device { + struct bcma_device *core; struct platform_device *ehci_dev; struct platform_device *ohci_dev; struct gpio_desc *gpio_desc; @@ -288,31 +289,16 @@ err_alloc: return ERR_PTR(ret); } -static int bcma_hcd_probe(struct bcma_device *dev) +static int bcma_hcd_usb20_init(struct bcma_hcd_device *usb_dev) { - int err; + struct bcma_device *dev = usb_dev->core; + struct bcma_chipinfo *chipinfo = &dev->bus->chipinfo; u32 ohci_addr; - struct bcma_hcd_device *usb_dev; - struct bcma_chipinfo *chipinfo; - - chipinfo = &dev->bus->chipinfo; - - /* TODO: Probably need checks here; is the core connected? */ + int err; if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32))) return -EOPNOTSUPP; - usb_dev = devm_kzalloc(&dev->dev, sizeof(struct bcma_hcd_device), - GFP_KERNEL); - if (!usb_dev) - return -ENOMEM; - - if (dev->dev.of_node) - usb_dev->gpio_desc = devm_get_gpiod_from_child(&dev->dev, "vcc", - &dev->dev.of_node->fwnode); - if (!IS_ERR_OR_NULL(usb_dev->gpio_desc)) - gpiod_direction_output(usb_dev->gpio_desc, 1); - switch (dev->id.id) { case BCMA_CORE_NS_USB20: bcma_hcd_init_chip_arm(dev); @@ -345,7 +331,6 @@ static int bcma_hcd_probe(struct bcma_device *dev) goto err_unregister_ohci_dev; } - bcma_set_drvdata(dev, usb_dev); return 0; err_unregister_ohci_dev: @@ -353,6 +338,40 @@ err_unregister_ohci_dev: return err; } +static int bcma_hcd_probe(struct bcma_device *core) +{ + int err; + struct bcma_hcd_device *usb_dev; + + /* TODO: Probably need checks here; is the core connected? */ + + usb_dev = devm_kzalloc(&core->dev, sizeof(struct bcma_hcd_device), + GFP_KERNEL); + if (!usb_dev) + return -ENOMEM; + usb_dev->core = core; + + if (core->dev.of_node) + usb_dev->gpio_desc = devm_get_gpiod_from_child(&core->dev, "vcc", + &core->dev.of_node->fwnode); + if (!IS_ERR_OR_NULL(usb_dev->gpio_desc)) + gpiod_direction_output(usb_dev->gpio_desc, 1); + + switch (core->id.id) { + case BCMA_CORE_USB20_HOST: + case BCMA_CORE_NS_USB20: + err = bcma_hcd_usb20_init(usb_dev); + if (err) + return err; + break; + default: + return -ENODEV; + } + + bcma_set_drvdata(core, usb_dev); + return 0; +} + static void bcma_hcd_remove(struct bcma_device *dev) { struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev); -- cgit v1.2.3 From 132f5005abbd480b66c58f8113ed876b99b6318e Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Thu, 10 Dec 2015 18:28:53 -0600 Subject: usb: host: ehci-msm: Allow LS devices to work Disable the silicon quirk which is normally enabled for HSIC host mode. This would otherwise prevent low speed devices from enumerating properly. Signed-off-by: Jack Pham Signed-off-by: Timur Tabi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-msm.c | 2 ++ include/linux/usb/msm_hsusb_hw.h | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index c23e2858c815..aed499d64029 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -61,6 +61,8 @@ static int ehci_msm_reset(struct usb_hcd *hcd) writel(0x8, USB_AHBMODE); /* Disable streaming mode and select host mode */ writel(0x13, USB_USBMODE); + /* Disable ULPI_TX_PKT_EN_CLR_FIX which is valid only for HSIC */ + writel(readl(USB_GENCONFIG_2) & ~ULPI_TX_PKT_EN_CLR_FIX, USB_GENCONFIG_2); return 0; } diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h index e159b39f67a2..974c3796a23f 100644 --- a/include/linux/usb/msm_hsusb_hw.h +++ b/include/linux/usb/msm_hsusb_hw.h @@ -22,6 +22,7 @@ #define USB_AHBBURST (MSM_USB_BASE + 0x0090) #define USB_AHBMODE (MSM_USB_BASE + 0x0098) #define USB_GENCONFIG_2 (MSM_USB_BASE + 0x00a0) +#define ULPI_TX_PKT_EN_CLR_FIX BIT(19) #define USB_CAPLENGTH (MSM_USB_BASE + 0x0100) /* 8 bit */ -- cgit v1.2.3 From c4398ef609ed1f39b65190867837a6bf517616b6 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Thu, 10 Dec 2015 18:28:54 -0600 Subject: usb: host: ehci-msm: Remove dependency on OTG PHY Currently the EHCI MSM driver has a hard dependency to be created by an OTG layer, namely the phy-msm-usb driver. In some cases or board configurations we want to allow the EHCI host to be instantiated without OTG capability. Instead, relax the dependency on having an OTG PHY being present and call usb_add_hcd() directly. Signed-off-by: Jack Pham Signed-off-by: Timur Tabi Reviewed-by: Andy Gross Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-msm.c | 53 ++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index aed499d64029..e1004bc8ca8e 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -106,9 +106,9 @@ static int ehci_msm_probe(struct platform_device *pdev) } /* - * OTG driver takes care of PHY initialization, clock management, - * powering up VBUS, mapping of registers address space and power - * management. + * If there is an OTG driver, let it take care of PHY initialization, + * clock management, powering up VBUS, mapping of registers address + * space and power management. */ if (pdev->dev.of_node) phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0); @@ -116,27 +116,35 @@ static int ehci_msm_probe(struct platform_device *pdev) phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); if (IS_ERR(phy)) { - dev_err(&pdev->dev, "unable to find transceiver\n"); - ret = -EPROBE_DEFER; - goto put_hcd; - } - - ret = otg_set_host(phy->otg, &hcd->self); - if (ret < 0) { - dev_err(&pdev->dev, "unable to register with transceiver\n"); - goto put_hcd; + if (PTR_ERR(phy) == -EPROBE_DEFER) { + dev_err(&pdev->dev, "unable to find transceiver\n"); + ret = -EPROBE_DEFER; + goto put_hcd; + } + phy = NULL; } hcd->usb_phy = phy; device_init_wakeup(&pdev->dev, 1); - /* - * OTG device parent of HCD takes care of putting - * hardware into low power mode. - */ - pm_runtime_no_callbacks(&pdev->dev); - pm_runtime_enable(&pdev->dev); - /* FIXME: need to call usb_add_hcd() here? */ + if (phy && phy->otg) { + /* + * MSM OTG driver takes care of adding the HCD and + * placing hardware into low power mode via runtime PM. + */ + ret = otg_set_host(phy->otg, &hcd->self); + if (ret < 0) { + dev_err(&pdev->dev, "unable to register with transceiver\n"); + goto put_hcd; + } + + pm_runtime_no_callbacks(&pdev->dev); + pm_runtime_enable(&pdev->dev); + } else { + ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); + if (ret) + goto put_hcd; + } return 0; @@ -154,9 +162,10 @@ static int ehci_msm_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); - otg_set_host(hcd->usb_phy->otg, NULL); - - /* FIXME: need to call usb_remove_hcd() here? */ + if (hcd->usb_phy && hcd->usb_phy->otg) + otg_set_host(hcd->usb_phy->otg, NULL); + else + usb_remove_hcd(hcd); usb_put_hcd(hcd); -- cgit v1.2.3 From f13f0e65606c4877a9c16b3a8d1272fcaaa987a8 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Thu, 10 Dec 2015 18:28:55 -0600 Subject: usb: host: ehci-msm: Add support for ACPI probing Allow the EHCI MSM driver to probe against an ACPI enumerated device with ID QCOM8040. Signed-off-by: Jack Pham Signed-off-by: Timur Tabi Reviewed-by: Andy Gross Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-msm.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index e1004bc8ca8e..102837e58bbf 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "ehci.h" @@ -202,6 +203,12 @@ static const struct dev_pm_ops ehci_msm_dev_pm_ops = { .resume = ehci_msm_pm_resume, }; +static const struct acpi_device_id msm_ehci_acpi_ids[] = { + { "QCOM8040", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, msm_ehci_acpi_ids); + static const struct of_device_id msm_ehci_dt_match[] = { { .compatible = "qcom,ehci-host", }, {} @@ -215,6 +222,7 @@ static struct platform_driver ehci_msm_driver = { .name = "msm_hsusb_host", .pm = &ehci_msm_dev_pm_ops, .of_match_table = msm_ehci_dt_match, + .acpi_match_table = ACPI_PTR(msm_ehci_acpi_ids), }, }; -- cgit v1.2.3 From e8f55b91482247b0b11b2f2f12188d9be55bbd19 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Thu, 10 Dec 2015 18:28:56 -0600 Subject: usb: host: ehci-msm: Fix register initialization The default value for the 'transceiver select' field of the PORTSC register may not always be correct. Previously the phy-msm-usb driver would do this for us, but since ehci-msm can now be instantiated standalone without any PHY driver, the register needs to be explicitly initialized to ULPI mode to properly communicate with the PHY. This is not readily apparent, as firmware or bootloader code also happen to pre-initialize this for us. However, it can manifest when performing a driver unbind/rebind as follows: cd /sys/bus/platform/drivers/msm_hsusb_host echo QCOM8040:00 > unbind echo QCOM8040:00 > bind The EHCI core executes a controller reset as part of this, and as a result the register in question would revert to its default state and must be re-initialized properly. Furthermore this may be useful in the future when adding PM suspend/resume support. Signed-off-by: Jack Pham Signed-off-by: Timur Tabi Reviewed-by: Andy Gross Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-msm.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 102837e58bbf..b71947d04fed 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -56,6 +56,8 @@ static int ehci_msm_reset(struct usb_hcd *hcd) if (retval) return retval; + /* select ULPI phy and clear other status/control bits in PORTSC */ + writel(PORTSC_PTS_ULPI, USB_PORTSC); /* bursts of unspecified length. */ writel(0, USB_AHBBURST); /* Use the AHB transactor, allow posted data writes */ -- cgit v1.2.3 From 4bb3cad7125ba03255025cf1e4e7c638e4757f6c Mon Sep 17 00:00:00 2001 From: Azriel Samson Date: Thu, 10 Dec 2015 18:28:57 -0600 Subject: usb: host: ehci-msm: Register usb shutdown function Registering usb_hcd_platform_shutdown to be called during shutdown. This is a generic function that performs the generic host stack's shutdown. It ensures that USB operations do not continue while kexec boots a new kernel. Signed-off-by: Azriel Samson Signed-off-by: Timur Tabi Reviewed-by: Andy Gross Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-msm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index b71947d04fed..3e226ef6ca62 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -220,6 +220,7 @@ MODULE_DEVICE_TABLE(of, msm_ehci_dt_match); static struct platform_driver ehci_msm_driver = { .probe = ehci_msm_probe, .remove = ehci_msm_remove, + .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "msm_hsusb_host", .pm = &ehci_msm_dev_pm_ops, -- cgit v1.2.3 From d8ff463a4ef22f090df21a3c5b34b336e80b72ca Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Mon, 4 Jan 2016 16:14:43 +0800 Subject: ehci-hcd: Cleanup memory resources when ehci_halt fails The driver calls ehci_mem_init to allocate memory resources. But these resources are not freed when ehci_halt fails. This patch adds "ehci_mem_cleanup" in error handling code to fix this problem. Signed-off-by: Jia-Ju Bai Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 14178bbf0694..00e77cc91053 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -675,8 +675,10 @@ int ehci_setup(struct usb_hcd *hcd) return retval; retval = ehci_halt(ehci); - if (retval) + if (retval) { + ehci_mem_cleanup(ehci); return retval; + } ehci_reset(ehci); -- cgit v1.2.3 From e3e2e36c106a1e4212c65ba5b5d2bcb3455cb354 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Mon, 4 Jan 2016 16:14:29 +0800 Subject: ehci-hcd: Disable memory-write-invalidate when the driver is removed The driver calls pci_set_mwi to enable memory-write-invalidate when it is initialized, but does not call pci_clear_mwi when it is removed. Many other drivers calls pci_clear_mwi when pci_set_mwi is called, such as r8169, 8139cp and e1000. This patch adds a function "ehci_pci_remove" to remove the pci driver. This function calls pci_clear_mwi and usb_hcd_pci_remove, which can fix the problem. Signed-off-by: Jia-Ju Bai Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-pci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 2a5d2fd76040..3b3649d88c5f 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -377,6 +377,12 @@ static int ehci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) return usb_hcd_pci_probe(pdev, id); } +static void ehci_pci_remove(struct pci_dev *pdev) +{ + pci_clear_mwi(pdev); + usb_hcd_pci_remove(pdev); +} + /* PCI driver selection metadata; PCI hotplugging uses this */ static const struct pci_device_id pci_ids [] = { { /* handle any USB 2.0 EHCI controller */ @@ -396,7 +402,7 @@ static struct pci_driver ehci_pci_driver = { .id_table = pci_ids, .probe = ehci_pci_probe, - .remove = usb_hcd_pci_remove, + .remove = ehci_pci_remove, .shutdown = usb_hcd_pci_shutdown, #ifdef CONFIG_PM -- cgit v1.2.3 From 2f4c8e554bd38c78b5edb43e5ff8bc2341bc276a Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sat, 19 Dec 2015 00:34:26 +0800 Subject: usb: host: fotg210: use list_for_each_entry_safe Use list_for_each_entry_safe() instead of list_for_each_safe() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fotg210-hcd.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index 2341af4f3490..360a5e95abca 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -2267,7 +2267,7 @@ static unsigned qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) { struct fotg210_qtd *last, *end = qh->dummy; - struct list_head *entry, *tmp; + struct fotg210_qtd *qtd, *tmp; int last_status; int stopped; unsigned count = 0; @@ -2301,12 +2301,10 @@ rescan: * then let the queue advance. * if queue is stopped, handles unlinks. */ - list_for_each_safe(entry, tmp, &qh->qtd_list) { - struct fotg210_qtd *qtd; + list_for_each_entry_safe(qtd, tmp, &qh->qtd_list, qtd_list) { struct urb *urb; u32 token = 0; - qtd = list_entry(entry, struct fotg210_qtd, qtd_list); urb = qtd->urb; /* clean up any state from previous QTD ...*/ @@ -2544,14 +2542,11 @@ retry_xacterr: * used for cleanup after errors, before HC sees an URB's TDs. */ static void qtd_list_free(struct fotg210_hcd *fotg210, struct urb *urb, - struct list_head *qtd_list) + struct list_head *head) { - struct list_head *entry, *temp; - - list_for_each_safe(entry, temp, qtd_list) { - struct fotg210_qtd *qtd; + struct fotg210_qtd *qtd, *temp; - qtd = list_entry(entry, struct fotg210_qtd, qtd_list); + list_for_each_entry_safe(qtd, temp, head, qtd_list) { list_del(&qtd->qtd_list); fotg210_qtd_free(fotg210, qtd); } -- cgit v1.2.3 From 553c23605717cf4754d9cf35e6428df85c271a39 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sun, 20 Dec 2015 00:11:50 +0800 Subject: usb: host: max3421-hcd: use list_for_each_entry* Use list_for_each_entry*() instead of list_for_each*() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/max3421-hcd.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index bd98706d1ce9..c369c29e496d 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -797,19 +797,16 @@ max3421_check_unlink(struct usb_hcd *hcd) { struct spi_device *spi = to_spi_device(hcd->self.controller); struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd); - struct list_head *pos, *upos, *next_upos; struct max3421_ep *max3421_ep; struct usb_host_endpoint *ep; - struct urb *urb; + struct urb *urb, *next; unsigned long flags; int retval = 0; spin_lock_irqsave(&max3421_hcd->lock, flags); - list_for_each(pos, &max3421_hcd->ep_list) { - max3421_ep = container_of(pos, struct max3421_ep, ep_list); + list_for_each_entry(max3421_ep, &max3421_hcd->ep_list, ep_list) { ep = max3421_ep->ep; - list_for_each_safe(upos, next_upos, &ep->urb_list) { - urb = container_of(upos, struct urb, urb_list); + list_for_each_entry_safe(urb, next, &ep->urb_list, urb_list) { if (urb->unlinked) { retval = 1; dev_dbg(&spi->dev, "%s: URB %p unlinked=%d", @@ -1184,22 +1181,19 @@ dump_eps(struct usb_hcd *hcd) struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd); struct max3421_ep *max3421_ep; struct usb_host_endpoint *ep; - struct list_head *pos, *upos; char ubuf[512], *dp, *end; unsigned long flags; struct urb *urb; int epnum, ret; spin_lock_irqsave(&max3421_hcd->lock, flags); - list_for_each(pos, &max3421_hcd->ep_list) { - max3421_ep = container_of(pos, struct max3421_ep, ep_list); + list_for_each_entry(max3421_ep, &max3421_hcd->ep_list, ep_list) { ep = max3421_ep->ep; dp = ubuf; end = dp + sizeof(ubuf); *dp = '\0'; - list_for_each(upos, &ep->urb_list) { - urb = container_of(upos, struct urb, urb_list); + list_for_each_entry(urb, &ep->urb_list, urb_list) { ret = snprintf(dp, end - dp, " %p(%d.%s %d/%d)", urb, usb_pipetype(urb->pipe), usb_urb_dir_in(urb) ? "IN" : "OUT", -- cgit v1.2.3 From 7b1585f2099ad65382b09f240e0c3ecdb7bfa92e Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sat, 19 Dec 2015 00:34:28 +0800 Subject: usb: host: oxu210hp-hcd: use list_for_each_entry_safe Use list_for_each_entry_safe() instead of list_for_each_safe() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/oxu210hp-hcd.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index bc74aca8a54c..4e4d601af35c 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -981,7 +981,7 @@ static int qh_schedule(struct oxu_hcd *oxu, struct ehci_qh *qh); static unsigned qh_completions(struct oxu_hcd *oxu, struct ehci_qh *qh) { struct ehci_qtd *last = NULL, *end = qh->dummy; - struct list_head *entry, *tmp; + struct ehci_qtd *qtd, *tmp; int stopped; unsigned count = 0; int do_status = 0; @@ -1006,12 +1006,10 @@ static unsigned qh_completions(struct oxu_hcd *oxu, struct ehci_qh *qh) * then let the queue advance. * if queue is stopped, handles unlinks. */ - list_for_each_safe(entry, tmp, &qh->qtd_list) { - struct ehci_qtd *qtd; + list_for_each_entry_safe(qtd, tmp, &qh->qtd_list, qtd_list) { struct urb *urb; u32 token = 0; - qtd = list_entry(entry, struct ehci_qtd, qtd_list); urb = qtd->urb; /* Clean up any state from previous QTD ...*/ @@ -1174,14 +1172,11 @@ halt: * used for cleanup after errors, before HC sees an URB's TDs. */ static void qtd_list_free(struct oxu_hcd *oxu, - struct urb *urb, struct list_head *qtd_list) + struct urb *urb, struct list_head *head) { - struct list_head *entry, *temp; - - list_for_each_safe(entry, temp, qtd_list) { - struct ehci_qtd *qtd; + struct ehci_qtd *qtd, *temp; - qtd = list_entry(entry, struct ehci_qtd, qtd_list); + list_for_each_entry_safe(qtd, temp, head, qtd_list) { list_del(&qtd->qtd_list); oxu_qtd_free(oxu, qtd); } -- cgit v1.2.3 From 4e5d7a82d3acf8b53f3d72153de142c0ab608b56 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sat, 19 Dec 2015 00:34:29 +0800 Subject: usb: host: u132-hcd: use list_for_each_entry Use list_for_each_entry() instead of list_for_each() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/u132-hcd.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 05c85c7baf84..43d52931b5bf 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -1309,13 +1309,9 @@ static void u132_hcd_ring_work_scheduler(struct work_struct *work) u132_ring_put_kref(u132, ring); return; } else if (ring->curr_endp) { - struct u132_endp *last_endp = ring->curr_endp; - struct list_head *scan; - struct list_head *head = &last_endp->endp_ring; + struct u132_endp *endp, *last_endp = ring->curr_endp; unsigned long wakeup = 0; - list_for_each(scan, head) { - struct u132_endp *endp = list_entry(scan, - struct u132_endp, endp_ring); + list_for_each_entry(endp, &last_endp->endp_ring, endp_ring) { if (endp->queue_next == endp->queue_last) { } else if ((endp->delayed == 0) || time_after_eq(jiffies, endp->jiffies)) { @@ -2393,14 +2389,12 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, static int dequeue_from_overflow_chain(struct u132 *u132, struct u132_endp *endp, struct urb *urb) { - struct list_head *scan; - struct list_head *head = &endp->urb_more; - list_for_each(scan, head) { - struct u132_urbq *urbq = list_entry(scan, struct u132_urbq, - urb_more); + struct u132_urbq *urbq; + + list_for_each_entry(urbq, &endp->urb_more, urb_more) { if (urbq->urb == urb) { struct usb_hcd *hcd = u132_to_hcd(u132); - list_del(scan); + list_del(&urbq->urb_more); endp->queue_size -= 1; urb->error_count = 0; usb_hcd_giveback_urb(hcd, urb, 0); -- cgit v1.2.3 From 32540ba237411244f04ef783bf0fa61041ab592d Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sat, 19 Dec 2015 00:34:31 +0800 Subject: usb: chipidea: debug: use list_for_each_entry Use list_for_each_entry() instead of list_for_each() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/debug.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index a4f7db2e18dd..de5c5092d078 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c @@ -172,7 +172,6 @@ static int ci_requests_show(struct seq_file *s, void *data) { struct ci_hdrc *ci = s->private; unsigned long flags; - struct list_head *ptr = NULL; struct ci_hw_req *req = NULL; struct td_node *node, *tmpnode; unsigned i, j, qsize = sizeof(struct ci_hw_td)/sizeof(u32); @@ -184,9 +183,7 @@ static int ci_requests_show(struct seq_file *s, void *data) spin_lock_irqsave(&ci->lock, flags); for (i = 0; i < ci->hw_ep_max; i++) - list_for_each(ptr, &ci->ci_hw_ep[i].qh.queue) { - req = list_entry(ptr, struct ci_hw_req, queue); - + list_for_each_entry(req, &ci->ci_hw_ep[i].qh.queue, queue) { list_for_each_entry_safe(node, tmpnode, &req->tds, td) { seq_printf(s, "EP=%02i: TD=%08X %s\n", i % (ci->hw_ep_max / 2), -- cgit v1.2.3 From f6281af9d62e128aa6efad29cf7265062af114f2 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sat, 19 Dec 2015 00:34:33 +0800 Subject: usb: gadget: rndis: use list_for_each_entry_safe Use list_for_each_entry_safe() instead of list_for_each_safe() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/rndis.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c index 70d3917cc003..34a76db2c8fd 100644 --- a/drivers/usb/gadget/function/rndis.c +++ b/drivers/usb/gadget/function/rndis.c @@ -914,7 +914,7 @@ struct rndis_params *rndis_register(void (*resp_avail)(void *v), void *v) params->media_state = RNDIS_MEDIA_STATE_DISCONNECTED; params->resp_avail = resp_avail; params->v = v; - INIT_LIST_HEAD(&(params->resp_queue)); + INIT_LIST_HEAD(¶ms->resp_queue); pr_debug("%s: configNr = %d\n", __func__, i); return params; @@ -1006,12 +1006,9 @@ EXPORT_SYMBOL_GPL(rndis_add_hdr); void rndis_free_response(struct rndis_params *params, u8 *buf) { - rndis_resp_t *r; - struct list_head *act, *tmp; + rndis_resp_t *r, *n; - list_for_each_safe(act, tmp, &(params->resp_queue)) - { - r = list_entry(act, rndis_resp_t, list); + list_for_each_entry_safe(r, n, ¶ms->resp_queue, list) { if (r && r->buf == buf) { list_del(&r->list); kfree(r); @@ -1022,14 +1019,11 @@ EXPORT_SYMBOL_GPL(rndis_free_response); u8 *rndis_get_next_response(struct rndis_params *params, u32 *length) { - rndis_resp_t *r; - struct list_head *act, *tmp; + rndis_resp_t *r, *n; if (!length) return NULL; - list_for_each_safe(act, tmp, &(params->resp_queue)) - { - r = list_entry(act, rndis_resp_t, list); + list_for_each_entry_safe(r, n, ¶ms->resp_queue, list) { if (!r->send) { r->send = 1; *length = r->length; @@ -1053,7 +1047,7 @@ static rndis_resp_t *rndis_add_response(struct rndis_params *params, u32 length) r->length = length; r->send = 0; - list_add_tail(&r->list, &(params->resp_queue)); + list_add_tail(&r->list, ¶ms->resp_queue); return r; } -- cgit v1.2.3 From aa742683bbea9f2faa28ec2f61745abf2ad86a9d Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 19 Jan 2016 10:51:09 +0100 Subject: USB: uas: add full support for RESPONSE IU Some devices send response IUs when you'd expect a sense IU. As a response to a wrong LUN that is within spec. We cannot get away without handling for response IUs. This version fixes the issues Hans raised. Signed-off-by: Oliver Neukum Reviewed-by: Hans de Goede Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/uas.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 9ff9404f99d7..44b096c1737b 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -246,6 +246,29 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, } } +static bool uas_evaluate_response_iu(struct response_iu *riu, struct scsi_cmnd *cmnd) +{ + u8 response_code = riu->response_code; + + switch (response_code) { + case RC_INCORRECT_LUN: + cmnd->result = DID_BAD_TARGET << 16; + break; + case RC_TMF_SUCCEEDED: + cmnd->result = DID_OK << 16; + break; + case RC_TMF_NOT_SUPPORTED: + cmnd->result = DID_TARGET_FAILURE << 16; + break; + default: + uas_log_cmd_state(cmnd, "response iu", response_code); + cmnd->result = DID_ERROR << 16; + break; + } + + return response_code == RC_TMF_SUCCEEDED; +} + static void uas_stat_cmplt(struct urb *urb) { struct iu *iu = urb->transfer_buffer; @@ -258,6 +281,7 @@ static void uas_stat_cmplt(struct urb *urb) unsigned long flags; unsigned int idx; int status = urb->status; + bool success; spin_lock_irqsave(&devinfo->lock, flags); @@ -313,13 +337,13 @@ static void uas_stat_cmplt(struct urb *urb) uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB); break; case IU_ID_RESPONSE: - uas_log_cmd_state(cmnd, "unexpected response iu", - ((struct response_iu *)iu)->response_code); - /* Error, cancel data transfers */ - data_in_urb = usb_get_urb(cmdinfo->data_in_urb); - data_out_urb = usb_get_urb(cmdinfo->data_out_urb); cmdinfo->state &= ~COMMAND_INFLIGHT; - cmnd->result = DID_ERROR << 16; + success = uas_evaluate_response_iu((struct response_iu *)iu, cmnd); + if (!success) { + /* Error, cancel data transfers */ + data_in_urb = usb_get_urb(cmdinfo->data_in_urb); + data_out_urb = usb_get_urb(cmdinfo->data_out_urb); + } uas_try_complete(cmnd, __func__); break; default: -- cgit v1.2.3 From 69ab55d7be6c3d69fa2e38f2a2bed4e91b9edf8d Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 23 Dec 2015 21:26:50 +0800 Subject: USB: core, devio: use to_usb_device Use to_usb_device() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 2 +- drivers/usb/core/usb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 054eb534c495..13a4b9f48739 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -848,7 +848,7 @@ static struct usb_device *usbdev_lookup_by_devt(dev_t devt) (void *) (unsigned long) devt, match_devt); if (!dev) return NULL; - return container_of(dev, struct usb_device, dev); + return to_usb_device(dev); } /* diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index ebb29caa3fe4..49b011f951b3 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -241,7 +241,7 @@ static int __each_dev(struct device *dev, void *data) if (!is_usb_device(dev)) return 0; - return arg->fn(container_of(dev, struct usb_device, dev), arg->data); + return arg->fn(to_usb_device(dev), arg->data); } /** -- cgit v1.2.3 From 6ae706aeaf42cd2fe6e541c72af6e2c0befe057c Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 23 Dec 2015 21:26:51 +0800 Subject: USB: core, wusbcore: use bus_to_hcd Use bus_to_hcd() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 6 +++--- drivers/usb/core/hub.c | 2 +- drivers/usb/core/usb.c | 2 +- drivers/usb/wusbcore/wusbhc.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 9af9506352f3..232c8c93dd3a 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2237,7 +2237,7 @@ int usb_hcd_get_frame_number (struct usb_device *udev) int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) { - struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); + struct usb_hcd *hcd = bus_to_hcd(rhdev->bus); int status; int old_state = hcd->state; @@ -2286,7 +2286,7 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) { - struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); + struct usb_hcd *hcd = bus_to_hcd(rhdev->bus); int status; int old_state = hcd->state; @@ -2400,7 +2400,7 @@ int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num) * boards with root hubs hooked up to internal devices (instead of * just the OTG port) may need more attention to resetting... */ - hcd = container_of (bus, struct usb_hcd, self); + hcd = bus_to_hcd(bus); if (port_num && hcd->driver->start_port_reset) status = hcd->driver->start_port_reset(hcd, port_num); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 3c9b22eb78ca..9ec5733b62f4 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2659,7 +2659,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub) struct usb_hcd *hcd; if (hub->hdev->parent != NULL) /* not a root hub? */ return 0; - hcd = container_of(hub->hdev->bus, struct usb_hcd, self); + hcd = bus_to_hcd(hub->hdev->bus); return hcd->wireless; } diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 49b011f951b3..16ade41759cd 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -397,7 +397,7 @@ struct device_type usb_device_type = { /* Returns 1 if @usb_bus is WUSB, 0 otherwise */ static unsigned usb_bus_is_wusb(struct usb_bus *bus) { - struct usb_hcd *hcd = container_of(bus, struct usb_hcd, self); + struct usb_hcd *hcd = bus_to_hcd(bus); return hcd->wireless; } diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/usb/wusbcore/wusbhc.h index 41838db7f85c..8c5bd000739b 100644 --- a/drivers/usb/wusbcore/wusbhc.h +++ b/drivers/usb/wusbcore/wusbhc.h @@ -336,7 +336,7 @@ static inline struct usb_hcd *usb_hcd_get_by_usb_dev(struct usb_device *usb_dev) { struct usb_hcd *usb_hcd; - usb_hcd = container_of(usb_dev->bus, struct usb_hcd, self); + usb_hcd = bus_to_hcd(usb_dev->bus); return usb_get_hcd(usb_hcd); } -- cgit v1.2.3 From 20db5513b4085d4beb78e7129cf7e56fe4ddafde Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 23 Dec 2015 21:26:52 +0800 Subject: USB: host: use to_platform_device Use to_platform_device() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-platform.c | 6 ++---- drivers/usb/host/ehci-st.c | 6 ++---- drivers/usb/host/ohci-platform.c | 6 ++---- drivers/usb/host/ohci-st.c | 6 ++---- 4 files changed, 8 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index bd7082f297bb..1757ebb471b6 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -345,8 +345,7 @@ static int ehci_platform_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_ehci_pdata *pdata = dev_get_platdata(dev); - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); bool do_wakeup = device_may_wakeup(dev); int ret; @@ -364,8 +363,7 @@ static int ehci_platform_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_ehci_pdata *pdata = dev_get_platdata(dev); - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); if (pdata->power_on) { diff --git a/drivers/usb/host/ehci-st.c b/drivers/usb/host/ehci-st.c index b7c5cfa37a83..a94ed677d937 100644 --- a/drivers/usb/host/ehci-st.c +++ b/drivers/usb/host/ehci-st.c @@ -287,8 +287,7 @@ static int st_ehci_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_ehci_pdata *pdata = dev_get_platdata(dev); - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); bool do_wakeup = device_may_wakeup(dev); int ret; @@ -308,8 +307,7 @@ static int st_ehci_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_ehci_pdata *pdata = dev_get_platdata(dev); - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); int err; pinctrl_pm_select_default_state(dev); diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index c2669f185f65..ae1c988da146 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c @@ -310,8 +310,7 @@ static int ohci_platform_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_ohci_pdata *pdata = dev->platform_data; - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); bool do_wakeup = device_may_wakeup(dev); int ret; @@ -329,8 +328,7 @@ static int ohci_platform_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_ohci_pdata *pdata = dev_get_platdata(dev); - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); if (pdata->power_on) { int err = pdata->power_on(pdev); diff --git a/drivers/usb/host/ohci-st.c b/drivers/usb/host/ohci-st.c index df9028e0d9b4..acf2eb2a5676 100644 --- a/drivers/usb/host/ohci-st.c +++ b/drivers/usb/host/ohci-st.c @@ -270,8 +270,7 @@ static int st_ohci_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_ohci_pdata *pdata = dev->platform_data; - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); bool do_wakeup = device_may_wakeup(dev); int ret; @@ -289,8 +288,7 @@ static int st_ohci_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_ohci_pdata *pdata = dev_get_platdata(dev); - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); int err; if (pdata->power_on) { -- cgit v1.2.3 From f74a039c7e0bf6b7ed71b10dddfdafcf1e87e5ae Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Fri, 15 Jan 2016 18:41:28 +0100 Subject: usb-misc: sisusbvga: Fix coding style: horizontal whitespace changes This patch fixes whitespace coding style issues that can be fixed within a single line. This patch fixes the following checkpatch warnings: - 83 ERROR: space required after that ',' - 13 ERROR: switch and case should be at the same indent - 08 WARNING: please, no spaces at the start of a line - 03 ERROR: space required before the open parenthesis '(' - 04 WARNING: suspect code indent for conditional statements - 01 WARNING: space prohibited between function name and open parenthesis - 01 ERROR: spaces required around that '=' - 01 ERROR: code indent should use tabs where possible Signed-off-by: Peter Senna Tschudin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 953 ++++++++++++++++++------------------ 1 file changed, 471 insertions(+), 482 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 8efbabacc84e..616a87d7219b 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -243,7 +243,7 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, /* Set up context */ sisusb->urbout_context[index].actual_length = (timeout) ? - NULL : actual_length; + NULL : actual_length; /* Declare this urb/buffer in use */ sisusb->urbstatus[index] |= SU_URB_BUSY; @@ -254,8 +254,8 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, /* If OK, and if timeout > 0, wait for completion */ if ((retval == 0) && timeout) { wait_event_timeout(sisusb->wait_q, - (!(sisusb->urbstatus[index] & SU_URB_BUSY)), - timeout); + (!(sisusb->urbstatus[index] & SU_URB_BUSY)), + timeout); if (sisusb->urbstatus[index] & SU_URB_BUSY) { /* URB timed out... kill it and report error */ usb_kill_urb(urb); @@ -375,7 +375,7 @@ static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len, do { passsize = thispass = (sisusb->obufsize < count) ? - sisusb->obufsize : count; + sisusb->obufsize : count; if (index < 0) index = sisusb_get_free_outbuf(sisusb); @@ -549,7 +549,7 @@ static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len, } static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len, - struct sisusb_packet *packet) + struct sisusb_packet *packet) { int ret; ssize_t bytes_transferred = 0; @@ -634,7 +634,7 @@ static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len, */ static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type, - u32 addr, u8 data) + u32 addr, u8 data) { struct sisusb_packet packet; int ret; @@ -647,7 +647,7 @@ static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type, } static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type, - u32 addr, u16 data) + u32 addr, u16 data) { struct sisusb_packet packet; int ret = 0; @@ -655,36 +655,36 @@ static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type, packet.address = addr & ~3; switch (addr & 3) { - case 0: - packet.header = (type << 6) | 0x0003; - packet.data = (u32)data; - ret = sisusb_send_packet(sisusb, 10, &packet); - break; - case 1: - packet.header = (type << 6) | 0x0006; - packet.data = (u32)data << 8; - ret = sisusb_send_packet(sisusb, 10, &packet); - break; - case 2: - packet.header = (type << 6) | 0x000c; - packet.data = (u32)data << 16; - ret = sisusb_send_packet(sisusb, 10, &packet); - break; - case 3: - packet.header = (type << 6) | 0x0008; - packet.data = (u32)data << 24; - ret = sisusb_send_packet(sisusb, 10, &packet); - packet.header = (type << 6) | 0x0001; - packet.address = (addr & ~3) + 4; - packet.data = (u32)data >> 8; - ret |= sisusb_send_packet(sisusb, 10, &packet); + case 0: + packet.header = (type << 6) | 0x0003; + packet.data = (u32)data; + ret = sisusb_send_packet(sisusb, 10, &packet); + break; + case 1: + packet.header = (type << 6) | 0x0006; + packet.data = (u32)data << 8; + ret = sisusb_send_packet(sisusb, 10, &packet); + break; + case 2: + packet.header = (type << 6) | 0x000c; + packet.data = (u32)data << 16; + ret = sisusb_send_packet(sisusb, 10, &packet); + break; + case 3: + packet.header = (type << 6) | 0x0008; + packet.data = (u32)data << 24; + ret = sisusb_send_packet(sisusb, 10, &packet); + packet.header = (type << 6) | 0x0001; + packet.address = (addr & ~3) + 4; + packet.data = (u32)data >> 8; + ret |= sisusb_send_packet(sisusb, 10, &packet); } return ret; } static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type, - u32 addr, u32 data) + u32 addr, u32 data) { struct sisusb_packet packet; int ret = 0; @@ -692,40 +692,40 @@ static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type, packet.address = addr & ~3; switch (addr & 3) { - case 0: - packet.header = (type << 6) | 0x0007; - packet.data = data & 0x00ffffff; - ret = sisusb_send_packet(sisusb, 10, &packet); - break; - case 1: - packet.header = (type << 6) | 0x000e; - packet.data = data << 8; - ret = sisusb_send_packet(sisusb, 10, &packet); - break; - case 2: - packet.header = (type << 6) | 0x000c; - packet.data = data << 16; - ret = sisusb_send_packet(sisusb, 10, &packet); - packet.header = (type << 6) | 0x0001; - packet.address = (addr & ~3) + 4; - packet.data = (data >> 16) & 0x00ff; - ret |= sisusb_send_packet(sisusb, 10, &packet); - break; - case 3: - packet.header = (type << 6) | 0x0008; - packet.data = data << 24; - ret = sisusb_send_packet(sisusb, 10, &packet); - packet.header = (type << 6) | 0x0003; - packet.address = (addr & ~3) + 4; - packet.data = (data >> 8) & 0xffff; - ret |= sisusb_send_packet(sisusb, 10, &packet); + case 0: + packet.header = (type << 6) | 0x0007; + packet.data = data & 0x00ffffff; + ret = sisusb_send_packet(sisusb, 10, &packet); + break; + case 1: + packet.header = (type << 6) | 0x000e; + packet.data = data << 8; + ret = sisusb_send_packet(sisusb, 10, &packet); + break; + case 2: + packet.header = (type << 6) | 0x000c; + packet.data = data << 16; + ret = sisusb_send_packet(sisusb, 10, &packet); + packet.header = (type << 6) | 0x0001; + packet.address = (addr & ~3) + 4; + packet.data = (data >> 16) & 0x00ff; + ret |= sisusb_send_packet(sisusb, 10, &packet); + break; + case 3: + packet.header = (type << 6) | 0x0008; + packet.data = data << 24; + ret = sisusb_send_packet(sisusb, 10, &packet); + packet.header = (type << 6) | 0x0003; + packet.address = (addr & ~3) + 4; + packet.data = (data >> 8) & 0xffff; + ret |= sisusb_send_packet(sisusb, 10, &packet); } return ret; } static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type, - u32 addr, u32 data) + u32 addr, u32 data) { struct sisusb_packet packet; int ret = 0; @@ -733,37 +733,37 @@ static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type, packet.address = addr & ~3; switch (addr & 3) { - case 0: - packet.header = (type << 6) | 0x000f; - packet.data = data; - ret = sisusb_send_packet(sisusb, 10, &packet); - break; - case 1: - packet.header = (type << 6) | 0x000e; - packet.data = data << 8; - ret = sisusb_send_packet(sisusb, 10, &packet); - packet.header = (type << 6) | 0x0001; - packet.address = (addr & ~3) + 4; - packet.data = data >> 24; - ret |= sisusb_send_packet(sisusb, 10, &packet); - break; - case 2: - packet.header = (type << 6) | 0x000c; - packet.data = data << 16; - ret = sisusb_send_packet(sisusb, 10, &packet); - packet.header = (type << 6) | 0x0003; - packet.address = (addr & ~3) + 4; - packet.data = data >> 16; - ret |= sisusb_send_packet(sisusb, 10, &packet); - break; - case 3: - packet.header = (type << 6) | 0x0008; - packet.data = data << 24; - ret = sisusb_send_packet(sisusb, 10, &packet); - packet.header = (type << 6) | 0x0007; - packet.address = (addr & ~3) + 4; - packet.data = data >> 8; - ret |= sisusb_send_packet(sisusb, 10, &packet); + case 0: + packet.header = (type << 6) | 0x000f; + packet.data = data; + ret = sisusb_send_packet(sisusb, 10, &packet); + break; + case 1: + packet.header = (type << 6) | 0x000e; + packet.data = data << 8; + ret = sisusb_send_packet(sisusb, 10, &packet); + packet.header = (type << 6) | 0x0001; + packet.address = (addr & ~3) + 4; + packet.data = data >> 24; + ret |= sisusb_send_packet(sisusb, 10, &packet); + break; + case 2: + packet.header = (type << 6) | 0x000c; + packet.data = data << 16; + ret = sisusb_send_packet(sisusb, 10, &packet); + packet.header = (type << 6) | 0x0003; + packet.address = (addr & ~3) + 4; + packet.data = data >> 16; + ret |= sisusb_send_packet(sisusb, 10, &packet); + break; + case 3: + packet.header = (type << 6) | 0x0008; + packet.data = data << 24; + ret = sisusb_send_packet(sisusb, 10, &packet); + packet.header = (type << 6) | 0x0007; + packet.address = (addr & ~3) + 4; + packet.data = data >> 8; + ret |= sisusb_send_packet(sisusb, 10, &packet); } return ret; @@ -803,9 +803,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, length &= 0x00ffffff; while (length) { - - switch (length) { - + switch (length) { case 1: if (userbuffer) { if (get_user(swap8, (u8 __user *)userbuffer)) @@ -892,88 +890,88 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, default: if ((length & ~3) > 0x10000) { - packet.header = 0x001f; - packet.address = 0x000001d4; - packet.data = addr; - ret = sisusb_send_bridge_packet(sisusb, 10, - &packet, 0); - packet.header = 0x001f; - packet.address = 0x000001d0; - packet.data = (length & ~3); - ret |= sisusb_send_bridge_packet(sisusb, 10, - &packet, 0); - packet.header = 0x001f; - packet.address = 0x000001c0; - packet.data = flag | 0x16; - ret |= sisusb_send_bridge_packet(sisusb, 10, - &packet, 0); - if (userbuffer) { - ret |= sisusb_send_bulk_msg(sisusb, + packet.header = 0x001f; + packet.address = 0x000001d4; + packet.data = addr; + ret = sisusb_send_bridge_packet(sisusb, 10, + &packet, 0); + packet.header = 0x001f; + packet.address = 0x000001d0; + packet.data = (length & ~3); + ret |= sisusb_send_bridge_packet(sisusb, 10, + &packet, 0); + packet.header = 0x001f; + packet.address = 0x000001c0; + packet.data = flag | 0x16; + ret |= sisusb_send_bridge_packet(sisusb, 10, + &packet, 0); + if (userbuffer) { + ret |= sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_LBULK_OUT, (length & ~3), NULL, userbuffer, 0, bytes_written, 0, 1); - userbuffer += (*bytes_written); - } else if (fromkern) { - ret |= sisusb_send_bulk_msg(sisusb, + userbuffer += (*bytes_written); + } else if (fromkern) { + ret |= sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_LBULK_OUT, (length & ~3), kernbuffer, NULL, 0, bytes_written, 0, 1); - kernbuffer += (*bytes_written); - } else { - ret |= sisusb_send_bulk_msg(sisusb, + kernbuffer += (*bytes_written); + } else { + ret |= sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_LBULK_OUT, (length & ~3), NULL, NULL, index, bytes_written, 0, 1); - kernbuffer += ((*bytes_written) & - (sisusb->obufsize-1)); - } + kernbuffer += ((*bytes_written) & + (sisusb->obufsize-1)); + } } else { - packet.header = 0x001f; - packet.address = 0x00000194; - packet.data = addr; - ret = sisusb_send_bridge_packet(sisusb, 10, - &packet, 0); - packet.header = 0x001f; - packet.address = 0x00000190; - packet.data = (length & ~3); - ret |= sisusb_send_bridge_packet(sisusb, 10, - &packet, 0); - if (sisusb->flagb0 != 0x16) { packet.header = 0x001f; - packet.address = 0x00000180; - packet.data = flag | 0x16; + packet.address = 0x00000194; + packet.data = addr; + ret = sisusb_send_bridge_packet(sisusb, 10, + &packet, 0); + packet.header = 0x001f; + packet.address = 0x00000190; + packet.data = (length & ~3); ret |= sisusb_send_bridge_packet(sisusb, 10, - &packet, 0); - sisusb->flagb0 = 0x16; - } - if (userbuffer) { - ret |= sisusb_send_bulk_msg(sisusb, + &packet, 0); + if (sisusb->flagb0 != 0x16) { + packet.header = 0x001f; + packet.address = 0x00000180; + packet.data = flag | 0x16; + ret |= sisusb_send_bridge_packet(sisusb, + 10, &packet, 0); + sisusb->flagb0 = 0x16; + } + if (userbuffer) { + ret |= sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_BULK_OUT, (length & ~3), NULL, userbuffer, 0, bytes_written, 0, 1); - userbuffer += (*bytes_written); - } else if (fromkern) { - ret |= sisusb_send_bulk_msg(sisusb, + userbuffer += (*bytes_written); + } else if (fromkern) { + ret |= sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_BULK_OUT, (length & ~3), kernbuffer, NULL, 0, bytes_written, 0, 1); - kernbuffer += (*bytes_written); - } else { - ret |= sisusb_send_bulk_msg(sisusb, + kernbuffer += (*bytes_written); + } else { + ret |= sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_BULK_OUT, (length & ~3), NULL, NULL, index, bytes_written, 0, 1); - kernbuffer += ((*bytes_written) & - (sisusb->obufsize-1)); - } + kernbuffer += ((*bytes_written) & + (sisusb->obufsize-1)); + } } if (ret) { msgcount++; @@ -985,10 +983,10 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, } addr += (*bytes_written); length -= (*bytes_written); - } + } - if (ret) - break; + if (ret) + break; } @@ -1000,7 +998,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, */ static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type, - u32 addr, u8 *data) + u32 addr, u8 *data) { struct sisusb_packet packet; int ret; @@ -1014,7 +1012,7 @@ static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type, } static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type, - u32 addr, u16 *data) + u32 addr, u16 *data) { struct sisusb_packet packet; int ret = 0; @@ -1024,36 +1022,36 @@ static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type, packet.address = addr & ~3; switch (addr & 3) { - case 0: - packet.header = (type << 6) | 0x0003; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = (u16)(packet.data); - break; - case 1: - packet.header = (type << 6) | 0x0006; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = (u16)(packet.data >> 8); - break; - case 2: - packet.header = (type << 6) | 0x000c; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = (u16)(packet.data >> 16); - break; - case 3: - packet.header = (type << 6) | 0x0008; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = (u16)(packet.data >> 24); - packet.header = (type << 6) | 0x0001; - packet.address = (addr & ~3) + 4; - ret |= sisusb_send_packet(sisusb, 6, &packet); - *data |= (u16)(packet.data << 8); + case 0: + packet.header = (type << 6) | 0x0003; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = (u16)(packet.data); + break; + case 1: + packet.header = (type << 6) | 0x0006; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = (u16)(packet.data >> 8); + break; + case 2: + packet.header = (type << 6) | 0x000c; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = (u16)(packet.data >> 16); + break; + case 3: + packet.header = (type << 6) | 0x0008; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = (u16)(packet.data >> 24); + packet.header = (type << 6) | 0x0001; + packet.address = (addr & ~3) + 4; + ret |= sisusb_send_packet(sisusb, 6, &packet); + *data |= (u16)(packet.data << 8); } return ret; } static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type, - u32 addr, u32 *data) + u32 addr, u32 *data) { struct sisusb_packet packet; int ret = 0; @@ -1061,40 +1059,40 @@ static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type, packet.address = addr & ~3; switch (addr & 3) { - case 0: - packet.header = (type << 6) | 0x0007; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = packet.data & 0x00ffffff; - break; - case 1: - packet.header = (type << 6) | 0x000e; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = packet.data >> 8; - break; - case 2: - packet.header = (type << 6) | 0x000c; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = packet.data >> 16; - packet.header = (type << 6) | 0x0001; - packet.address = (addr & ~3) + 4; - ret |= sisusb_send_packet(sisusb, 6, &packet); - *data |= ((packet.data & 0xff) << 16); - break; - case 3: - packet.header = (type << 6) | 0x0008; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = packet.data >> 24; - packet.header = (type << 6) | 0x0003; - packet.address = (addr & ~3) + 4; - ret |= sisusb_send_packet(sisusb, 6, &packet); - *data |= ((packet.data & 0xffff) << 8); + case 0: + packet.header = (type << 6) | 0x0007; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = packet.data & 0x00ffffff; + break; + case 1: + packet.header = (type << 6) | 0x000e; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = packet.data >> 8; + break; + case 2: + packet.header = (type << 6) | 0x000c; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = packet.data >> 16; + packet.header = (type << 6) | 0x0001; + packet.address = (addr & ~3) + 4; + ret |= sisusb_send_packet(sisusb, 6, &packet); + *data |= ((packet.data & 0xff) << 16); + break; + case 3: + packet.header = (type << 6) | 0x0008; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = packet.data >> 24; + packet.header = (type << 6) | 0x0003; + packet.address = (addr & ~3) + 4; + ret |= sisusb_send_packet(sisusb, 6, &packet); + *data |= ((packet.data & 0xffff) << 8); } return ret; } static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type, - u32 addr, u32 *data) + u32 addr, u32 *data) { struct sisusb_packet packet; int ret = 0; @@ -1102,37 +1100,37 @@ static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type, packet.address = addr & ~3; switch (addr & 3) { - case 0: - packet.header = (type << 6) | 0x000f; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = packet.data; - break; - case 1: - packet.header = (type << 6) | 0x000e; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = packet.data >> 8; - packet.header = (type << 6) | 0x0001; - packet.address = (addr & ~3) + 4; - ret |= sisusb_send_packet(sisusb, 6, &packet); - *data |= (packet.data << 24); - break; - case 2: - packet.header = (type << 6) | 0x000c; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = packet.data >> 16; - packet.header = (type << 6) | 0x0003; - packet.address = (addr & ~3) + 4; - ret |= sisusb_send_packet(sisusb, 6, &packet); - *data |= (packet.data << 16); - break; - case 3: - packet.header = (type << 6) | 0x0008; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = packet.data >> 24; - packet.header = (type << 6) | 0x0007; - packet.address = (addr & ~3) + 4; - ret |= sisusb_send_packet(sisusb, 6, &packet); - *data |= (packet.data << 8); + case 0: + packet.header = (type << 6) | 0x000f; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = packet.data; + break; + case 1: + packet.header = (type << 6) | 0x000e; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = packet.data >> 8; + packet.header = (type << 6) | 0x0001; + packet.address = (addr & ~3) + 4; + ret |= sisusb_send_packet(sisusb, 6, &packet); + *data |= (packet.data << 24); + break; + case 2: + packet.header = (type << 6) | 0x000c; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = packet.data >> 16; + packet.header = (type << 6) | 0x0003; + packet.address = (addr & ~3) + 4; + ret |= sisusb_send_packet(sisusb, 6, &packet); + *data |= (packet.data << 16); + break; + case 3: + packet.header = (type << 6) | 0x0008; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = packet.data >> 24; + packet.header = (type << 6) | 0x0007; + packet.address = (addr & ~3) + 4; + ret |= sisusb_send_packet(sisusb, 6, &packet); + *data |= (packet.data << 8); } return ret; @@ -1152,13 +1150,10 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, length &= 0x00ffffff; while (length) { - - switch (length) { - + switch (length) { case 1: - ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, - addr, &buf[0]); + addr, &buf[0]); if (!ret) { (*bytes_read)++; if (userbuffer) { @@ -1174,7 +1169,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, case 2: ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, - addr, &swap16); + addr, &swap16); if (!ret) { (*bytes_read) += 2; if (userbuffer) { @@ -1189,7 +1184,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, case 3: ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM, - addr, &swap32); + addr, &swap32); if (!ret) { (*bytes_read) += 3; #ifdef __BIG_ENDIAN @@ -1214,7 +1209,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, default: ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, - addr, &swap32); + addr, &swap32); if (!ret) { (*bytes_read) += 4; if (userbuffer) { @@ -1230,10 +1225,9 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, addr += 4; length -= 4; } - } - - if (ret) - break; + } + if (ret) + break; } return ret; @@ -1350,20 +1344,24 @@ sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest, static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb) { - static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; - char destbuffer[10]; - size_t dummy; - int i,j; - - sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy); - - for(i = 1; i <= 7; i++) { - dev_dbg(&sisusb->sisusb_dev->dev, "sisusb: rwtest %d bytes\n", i); - sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy); - for(j = 0; j < i; j++) { - dev_dbg(&sisusb->sisusb_dev->dev, "rwtest read[%d] = %x\n", j, destbuffer[j]); + static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; + char destbuffer[10]; + size_t dummy; + int i, j; + + sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy); + + for (i = 1; i <= 7; i++) { + dev_dbg(&sisusb->sisusb_dev->dev, + "sisusb: rwtest %d bytes\n", i); + sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, + i, &dummy); + for (j = 0; j < i; j++) { + dev_dbg(&sisusb->sisusb_dev->dev, + "rwtest read[%d] = %x\n", + j, destbuffer[j]); + } } - } } #endif @@ -1437,17 +1435,17 @@ sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length) * a defined mode (640x480@60Hz) */ -#define GETREG(r,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d) -#define SETREG(r,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d) -#define SETIREG(r,i,d) sisusb_setidxreg(sisusb, r, i, d) -#define GETIREG(r,i,d) sisusb_getidxreg(sisusb, r, i, d) -#define SETIREGOR(r,i,o) sisusb_setidxregor(sisusb, r, i, o) -#define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a) -#define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o) -#define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d) -#define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d) -#define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) -#define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) +#define GETREG(r, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d) +#define SETREG(r, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d) +#define SETIREG(r, i, d) sisusb_setidxreg(sisusb, r, i, d) +#define GETIREG(r, i, d) sisusb_getidxreg(sisusb, r, i, d) +#define SETIREGOR(r, i, o) sisusb_setidxregor(sisusb, r, i, o) +#define SETIREGAND(r, i, a) sisusb_setidxregand(sisusb, r, i, a) +#define SETIREGANDOR(r, i, a, o) sisusb_setidxregandor(sisusb, r, i, a, o) +#define READL(a, d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d) +#define WRITEL(a, d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d) +#define READB(a, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) +#define WRITEB(a, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) static int sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype) @@ -1526,7 +1524,7 @@ sisusb_getbuswidth(struct sisusb_usb_data *sisusb, int *bw, int *chab) } if ((t1 != 0x456789ab) || (t0 != 0x01234567)) { *chab = 1; *bw = 64; - ret |= SETIREGANDOR(SISSR, 0x14, 0xfc,0x01); + ret |= SETIREGANDOR(SISSR, 0x14, 0xfc, 0x01); ret |= sisusb_triggersr16(sisusb, ramtype); ret |= WRITEL(ramptr + 0, 0x89abcdef); @@ -1775,18 +1773,18 @@ sisusb_setup_screen(struct sisusb_usb_data *sisusb, int clrall, int drwfr) for (i = 0; i < modex; i++) { address = sisusb->vrambase + (i * bpp); ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, - address, 0xf100); + address, 0xf100); address += (modex * (modey-1) * bpp); ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, - address, 0xf100); + address, 0xf100); } for (i = 0; i < modey; i++) { address = sisusb->vrambase + ((i * modex) * bpp); ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, - address, 0xf100); + address, 0xf100); address += ((modex - 1) * bpp); ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, - address, 0xf100); + address, 0xf100); } } @@ -1799,23 +1797,23 @@ sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines) int ret = 0, i, j, modex, modey, bpp, du; u8 sr31, cr63, tmp8; static const char attrdata[] = { - 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x01,0x00,0x00,0x00 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x01, 0x00, 0x00, 0x00 }; static const char crtcrdata[] = { - 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3, + 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3, 0xff }; static const char grcdata[] = { - 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff }; static const char crtcdata[] = { - 0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e, - 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05, + 0x5f, 0x4f, 0x4f, 0x83, 0x55, 0x81, 0x0b, 0x3e, + 0xe9, 0x8b, 0xdf, 0xe8, 0x0c, 0x00, 0x00, 0x05, 0x00 }; @@ -2081,12 +2079,12 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab); if (iret) { dev_err(&sisusb->sisusb_dev->dev,"RAM size detection failed, assuming 8MB video RAM\n"); - ret |= SETIREG(SISSR,0x14,0x31); + ret |= SETIREG(SISSR, 0x14, 0x31); /* TODO */ } } else { dev_err(&sisusb->sisusb_dev->dev, "DDR RAM device found, assuming 8MB video RAM\n"); - ret |= SETIREG(SISSR,0x14,0x31); + ret |= SETIREG(SISSR, 0x14, 0x31); /* *** TODO *** */ } @@ -2127,7 +2125,7 @@ sisusb_get_ramconfig(struct sisusb_usb_data *sisusb) static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'}; static const int busSDR[4] = {64, 64, 128, 128}; static const int busDDR[4] = {32, 32, 64, 64}; - static const int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2}; + static const int busDDRA[4] = {64+32, 64+32, (64+32)*2, (64+32)*2}; sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8); sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82); @@ -2366,7 +2364,7 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) *(tempbufb++) = 0x0700 | bootstring[i++]; ret |= sisusb_copy_memory(sisusb, tempbuf, - sisusb->vrambase, 8192, &written); + sisusb->vrambase, 8192, &written); vfree(tempbuf); @@ -2380,7 +2378,7 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) } if (sisusb->sisusb_cursor_size_from >= 0 && - sisusb->sisusb_cursor_size_to >= 0) { + sisusb->sisusb_cursor_size_to >= 0) { sisusb_setidxreg(sisusb, SISCR, 0x0a, sisusb->sisusb_cursor_size_from); sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0, @@ -2392,7 +2390,7 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) } slot = sisusb->sisusb_cursor_loc; - if(slot < 0) slot = 0; + if (slot < 0) slot = 0; sisusb->sisusb_cursor_loc = -1; sisusb->bad_cursor_pos = 1; @@ -2444,7 +2442,7 @@ sisusb_open(struct inode *inode, struct file *file) if (!sisusb->devinit) { if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH || - sisusb->sisusb_dev->speed == USB_SPEED_SUPER) { + sisusb->sisusb_dev->speed == USB_SPEED_SUPER) { if (sisusb_init_gfxdevice(sisusb, 0)) { mutex_unlock(&sisusb->lock); dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n"); @@ -2539,7 +2537,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) } if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE && - (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { + (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE + @@ -2551,45 +2549,44 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) * in machine-endianness. */ switch (count) { + case 1: + if (sisusb_read_memio_byte(sisusb, + SISUSB_TYPE_IO, + address, &buf8)) + errno = -EIO; + else if (put_user(buf8, (u8 __user *)buffer)) + errno = -EFAULT; + else + bytes_read = 1; - case 1: - if (sisusb_read_memio_byte(sisusb, - SISUSB_TYPE_IO, - address, &buf8)) - errno = -EIO; - else if (put_user(buf8, (u8 __user *)buffer)) - errno = -EFAULT; - else - bytes_read = 1; - - break; + break; - case 2: - if (sisusb_read_memio_word(sisusb, - SISUSB_TYPE_IO, - address, &buf16)) - errno = -EIO; - else if (put_user(buf16, (u16 __user *)buffer)) - errno = -EFAULT; - else - bytes_read = 2; + case 2: + if (sisusb_read_memio_word(sisusb, + SISUSB_TYPE_IO, + address, &buf16)) + errno = -EIO; + else if (put_user(buf16, (u16 __user *)buffer)) + errno = -EFAULT; + else + bytes_read = 2; - break; + break; - case 4: - if (sisusb_read_memio_long(sisusb, - SISUSB_TYPE_IO, - address, &buf32)) - errno = -EIO; - else if (put_user(buf32, (u32 __user *)buffer)) - errno = -EFAULT; - else - bytes_read = 4; + case 4: + if (sisusb_read_memio_long(sisusb, + SISUSB_TYPE_IO, + address, &buf32)) + errno = -EIO; + else if (put_user(buf32, (u32 __user *)buffer)) + errno = -EFAULT; + else + bytes_read = 4; - break; + break; - default: - errno = -EIO; + default: + errno = -EIO; } @@ -2604,7 +2601,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) * Remember: Data delivered is never endian-corrected */ errno = sisusb_read_mem_bulk(sisusb, address, - NULL, count, buffer, &bytes_read); + NULL, count, buffer, &bytes_read); if (bytes_read) errno = bytes_read; @@ -2620,13 +2617,13 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) * Remember: Data delivered is never endian-corrected */ errno = sisusb_read_mem_bulk(sisusb, address, - NULL, count, buffer, &bytes_read); + NULL, count, buffer, &bytes_read); if (bytes_read) errno = bytes_read; } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE && - (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) { + (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) { if (count != 4) { mutex_unlock(&sisusb->lock); @@ -2682,7 +2679,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, } if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE && - (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { + (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE + @@ -2694,45 +2691,44 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, * in machine-endianness. */ switch (count) { + case 1: + if (get_user(buf8, (u8 __user *)buffer)) + errno = -EFAULT; + else if (sisusb_write_memio_byte(sisusb, + SISUSB_TYPE_IO, + address, buf8)) + errno = -EIO; + else + bytes_written = 1; - case 1: - if (get_user(buf8, (u8 __user *)buffer)) - errno = -EFAULT; - else if (sisusb_write_memio_byte(sisusb, - SISUSB_TYPE_IO, - address, buf8)) - errno = -EIO; - else - bytes_written = 1; - - break; + break; - case 2: - if (get_user(buf16, (u16 __user *)buffer)) - errno = -EFAULT; - else if (sisusb_write_memio_word(sisusb, - SISUSB_TYPE_IO, - address, buf16)) - errno = -EIO; - else - bytes_written = 2; + case 2: + if (get_user(buf16, (u16 __user *)buffer)) + errno = -EFAULT; + else if (sisusb_write_memio_word(sisusb, + SISUSB_TYPE_IO, + address, buf16)) + errno = -EIO; + else + bytes_written = 2; - break; + break; - case 4: - if (get_user(buf32, (u32 __user *)buffer)) - errno = -EFAULT; - else if (sisusb_write_memio_long(sisusb, - SISUSB_TYPE_IO, - address, buf32)) - errno = -EIO; - else - bytes_written = 4; + case 4: + if (get_user(buf32, (u32 __user *)buffer)) + errno = -EFAULT; + else if (sisusb_write_memio_long(sisusb, + SISUSB_TYPE_IO, + address, buf32)) + errno = -EIO; + else + bytes_written = 4; - break; + break; - default: - errno = -EIO; + default: + errno = -EIO; } } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && @@ -2749,7 +2745,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, * mode or if YUV data is being transferred). */ errno = sisusb_write_mem_bulk(sisusb, address, NULL, - count, buffer, 0, &bytes_written); + count, buffer, 0, &bytes_written); if (bytes_written) errno = bytes_written; @@ -2767,7 +2763,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, * in advance. */ errno = sisusb_write_mem_bulk(sisusb, address, NULL, - count, buffer, 0, &bytes_written); + count, buffer, 0, &bytes_written); if (bytes_written) errno = bytes_written; @@ -2849,105 +2845,99 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y, SISUSB_PCI_IOPORTBASE; switch (y->operation) { - case SUCMD_GET: - retval = sisusb_getidxreg(sisusb, port, - y->data0, &y->data1); - if (!retval) { - if (copy_to_user((void __user *)arg, y, - sizeof(*y))) - retval = -EFAULT; - } - break; + case SUCMD_GET: + retval = sisusb_getidxreg(sisusb, port, y->data0, &y->data1); + if (!retval) { + if (copy_to_user((void __user *)arg, y, sizeof(*y))) + retval = -EFAULT; + } + break; - case SUCMD_SET: - retval = sisusb_setidxreg(sisusb, port, - y->data0, y->data1); - break; + case SUCMD_SET: + retval = sisusb_setidxreg(sisusb, port, y->data0, y->data1); + break; - case SUCMD_SETOR: - retval = sisusb_setidxregor(sisusb, port, - y->data0, y->data1); - break; + case SUCMD_SETOR: + retval = sisusb_setidxregor(sisusb, port, y->data0, y->data1); + break; - case SUCMD_SETAND: - retval = sisusb_setidxregand(sisusb, port, - y->data0, y->data1); - break; + case SUCMD_SETAND: + retval = sisusb_setidxregand(sisusb, port, y->data0, y->data1); + break; - case SUCMD_SETANDOR: - retval = sisusb_setidxregandor(sisusb, port, - y->data0, y->data1, y->data2); - break; + case SUCMD_SETANDOR: + retval = sisusb_setidxregandor(sisusb, port, y->data0, + y->data1, y->data2); + break; - case SUCMD_SETMASK: - retval = sisusb_setidxregmask(sisusb, port, - y->data0, y->data1, y->data2); - break; + case SUCMD_SETMASK: + retval = sisusb_setidxregmask(sisusb, port, y->data0, + y->data1, y->data2); + break; - case SUCMD_CLRSCR: - /* Gfx core must be initialized */ - if (!sisusb->gfxinit) - return -ENODEV; + case SUCMD_CLRSCR: + /* Gfx core must be initialized */ + if (!sisusb->gfxinit) + return -ENODEV; - length = (y->data0 << 16) | (y->data1 << 8) | y->data2; - address = y->data3 - - SISUSB_PCI_PSEUDO_MEMBASE + + length = (y->data0 << 16) | (y->data1 << 8) | y->data2; + address = y->data3 - SISUSB_PCI_PSEUDO_MEMBASE + SISUSB_PCI_MEMBASE; - retval = sisusb_clear_vram(sisusb, address, length); - break; + retval = sisusb_clear_vram(sisusb, address, length); + break; - case SUCMD_HANDLETEXTMODE: - retval = 0; + case SUCMD_HANDLETEXTMODE: + retval = 0; #ifdef INCL_SISUSB_CON - /* Gfx core must be initialized, SiS_Pr must exist */ - if (!sisusb->gfxinit || !sisusb->SiS_Pr) - return -ENODEV; + /* Gfx core must be initialized, SiS_Pr must exist */ + if (!sisusb->gfxinit || !sisusb->SiS_Pr) + return -ENODEV; - switch (y->data0) { - case 0: - retval = sisusb_reset_text_mode(sisusb, 0); - break; - case 1: - sisusb->textmodedestroyed = 1; - break; - } -#endif + switch (y->data0) { + case 0: + retval = sisusb_reset_text_mode(sisusb, 0); + break; + case 1: + sisusb->textmodedestroyed = 1; break; + } +#endif + break; #ifdef INCL_SISUSB_CON - case SUCMD_SETMODE: - /* Gfx core must be initialized, SiS_Pr must exist */ - if (!sisusb->gfxinit || !sisusb->SiS_Pr) - return -ENODEV; + case SUCMD_SETMODE: + /* Gfx core must be initialized, SiS_Pr must exist */ + if (!sisusb->gfxinit || !sisusb->SiS_Pr) + return -ENODEV; - retval = 0; + retval = 0; - sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30; - sisusb->SiS_Pr->sisusb = (void *)sisusb; + sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30; + sisusb->SiS_Pr->sisusb = (void *)sisusb; - if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3)) - retval = -EINVAL; + if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3)) + retval = -EINVAL; - break; + break; - case SUCMD_SETVESAMODE: - /* Gfx core must be initialized, SiS_Pr must exist */ - if (!sisusb->gfxinit || !sisusb->SiS_Pr) - return -ENODEV; + case SUCMD_SETVESAMODE: + /* Gfx core must be initialized, SiS_Pr must exist */ + if (!sisusb->gfxinit || !sisusb->SiS_Pr) + return -ENODEV; - retval = 0; + retval = 0; - sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30; - sisusb->SiS_Pr->sisusb = (void *)sisusb; + sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30; + sisusb->SiS_Pr->sisusb = (void *)sisusb; - if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3)) - retval = -EINVAL; + if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3)) + retval = -EINVAL; - break; + break; #endif - default: - retval = -EINVAL; + default: + retval = -EINVAL; } if (retval > 0) @@ -2978,52 +2968,51 @@ sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } switch (cmd) { + case SISUSB_GET_CONFIG_SIZE: - case SISUSB_GET_CONFIG_SIZE: + if (put_user(sizeof(x), argp)) + retval = -EFAULT; - if (put_user(sizeof(x), argp)) - retval = -EFAULT; - - break; + break; - case SISUSB_GET_CONFIG: - - x.sisusb_id = SISUSB_ID; - x.sisusb_version = SISUSB_VERSION; - x.sisusb_revision = SISUSB_REVISION; - x.sisusb_patchlevel = SISUSB_PATCHLEVEL; - x.sisusb_gfxinit = sisusb->gfxinit; - x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE; - x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE; - x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE; - x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE; - x.sisusb_vramsize = sisusb->vramsize; - x.sisusb_minor = sisusb->minor; - x.sisusb_fbdevactive= 0; + case SISUSB_GET_CONFIG: + + x.sisusb_id = SISUSB_ID; + x.sisusb_version = SISUSB_VERSION; + x.sisusb_revision = SISUSB_REVISION; + x.sisusb_patchlevel = SISUSB_PATCHLEVEL; + x.sisusb_gfxinit = sisusb->gfxinit; + x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE; + x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE; + x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE; + x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE; + x.sisusb_vramsize = sisusb->vramsize; + x.sisusb_minor = sisusb->minor; + x.sisusb_fbdevactive = 0; #ifdef INCL_SISUSB_CON - x.sisusb_conactive = sisusb->haveconsole ? 1 : 0; + x.sisusb_conactive = sisusb->haveconsole ? 1 : 0; #else - x.sisusb_conactive = 0; + x.sisusb_conactive = 0; #endif - memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved)); + memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved)); - if (copy_to_user((void __user *)arg, &x, sizeof(x))) - retval = -EFAULT; + if (copy_to_user((void __user *)arg, &x, sizeof(x))) + retval = -EFAULT; - break; + break; - case SISUSB_COMMAND: + case SISUSB_COMMAND: - if (copy_from_user(&y, (void __user *)arg, sizeof(y))) - retval = -EFAULT; - else - retval = sisusb_handle_command(sisusb, &y, arg); + if (copy_from_user(&y, (void __user *)arg, sizeof(y))) + retval = -EFAULT; + else + retval = sisusb_handle_command(sisusb, &y, arg); - break; + break; - default: - retval = -ENOTTY; - break; + default: + retval = -ENOTTY; + break; } err_out: @@ -3038,14 +3027,14 @@ sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg) long retval; switch (cmd) { - case SISUSB_GET_CONFIG_SIZE: - case SISUSB_GET_CONFIG: - case SISUSB_COMMAND: - retval = sisusb_ioctl(f, cmd, arg); - return retval; + case SISUSB_GET_CONFIG_SIZE: + case SISUSB_GET_CONFIG: + case SISUSB_COMMAND: + retval = sisusb_ioctl(f, cmd, arg); + return retval; - default: - return -ENOIOCTLCMD; + default: + return -ENOIOCTLCMD; } } #endif @@ -3070,14 +3059,14 @@ static struct usb_class_driver usb_sisusb_class = { }; static int sisusb_probe(struct usb_interface *intf, - const struct usb_device_id *id) + const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); struct sisusb_usb_data *sisusb; int retval = 0, i; dev_info(&dev->dev, "USB2VGA dongle found at address %d\n", - dev->devnum); + dev->devnum); /* Allocate memory for our private */ sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL); @@ -3254,7 +3243,7 @@ static const struct usb_device_id sisusb_table[] = { { } }; -MODULE_DEVICE_TABLE (usb, sisusb_table); +MODULE_DEVICE_TABLE(usb, sisusb_table); static struct usb_driver sisusb_driver = { .name = "sisusb", -- cgit v1.2.3 From 06e21efa2d344b5e29bf680e623fa76dbcb62580 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Fri, 15 Jan 2016 18:41:29 +0100 Subject: usb-misc: sisusbvga: Fix coding style: vertical whitespace changes This patch fixes whitespace coding style issues that can't be fixed without adding newlines. This patch fixes the following checkpatch warnings: - 20 ERROR: trailing statements should be on next line - 15 WARNING: line over 80 characters - 03 WARNING: Missing a blank line after declarations - 01 ERROR: space required after that ',' Five lines over 80 characters are left. The first three wont change as the fix would require split the cast and variable name in different lines which makes the code less readable. The last two will be fixed by other patch in the series. Signed-off-by: Peter Senna Tschudin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 494 +++++++++++++++++------------------- 1 file changed, 236 insertions(+), 258 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 616a87d7219b..ea0e1ad5d4bc 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -71,8 +71,7 @@ MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES static struct usb_driver sisusb_driver; -static void -sisusb_free_buffers(struct sisusb_usb_data *sisusb) +static void sisusb_free_buffers(struct sisusb_usb_data *sisusb) { int i; @@ -88,8 +87,7 @@ sisusb_free_buffers(struct sisusb_usb_data *sisusb) } } -static void -sisusb_free_urbs(struct sisusb_usb_data *sisusb) +static void sisusb_free_urbs(struct sisusb_usb_data *sisusb) { int i; @@ -108,8 +106,7 @@ sisusb_free_urbs(struct sisusb_usb_data *sisusb) /* out-urb management */ /* Return 1 if all free, 0 otherwise */ -static int -sisusb_all_free(struct sisusb_usb_data *sisusb) +static int sisusb_all_free(struct sisusb_usb_data *sisusb) { int i; @@ -124,8 +121,7 @@ sisusb_all_free(struct sisusb_usb_data *sisusb) } /* Kill all busy URBs */ -static void -sisusb_kill_all_busy(struct sisusb_usb_data *sisusb) +static void sisusb_kill_all_busy(struct sisusb_usb_data *sisusb) { int i; @@ -141,20 +137,17 @@ sisusb_kill_all_busy(struct sisusb_usb_data *sisusb) } /* Return 1 if ok, 0 if error (not all complete within timeout) */ -static int -sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb) +static int sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb) { int timeout = 5 * HZ, i = 1; - wait_event_timeout(sisusb->wait_q, - (i = sisusb_all_free(sisusb)), - timeout); + wait_event_timeout(sisusb->wait_q, (i = sisusb_all_free(sisusb)), + timeout); return i; } -static int -sisusb_outurb_available(struct sisusb_usb_data *sisusb) +static int sisusb_outurb_available(struct sisusb_usb_data *sisusb) { int i; @@ -168,20 +161,17 @@ sisusb_outurb_available(struct sisusb_usb_data *sisusb) return -1; } -static int -sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb) +static int sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb) { int i, timeout = 5 * HZ; wait_event_timeout(sisusb->wait_q, - ((i = sisusb_outurb_available(sisusb)) >= 0), - timeout); + ((i = sisusb_outurb_available(sisusb)) >= 0), timeout); return i; } -static int -sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb) +static int sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb) { int i; @@ -193,8 +183,7 @@ sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb) return i; } -static void -sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index) +static void sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index) { if ((index >= 0) && (index < sisusb->numobufs)) sisusb->urbstatus[index] &= ~SU_URB_ALLOC; @@ -202,8 +191,7 @@ sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index) /* completion callback */ -static void -sisusb_bulk_completeout(struct urb *urb) +static void sisusb_bulk_completeout(struct urb *urb) { struct sisusb_urb_context *context = urb->context; struct sisusb_usb_data *sisusb; @@ -225,9 +213,9 @@ sisusb_bulk_completeout(struct urb *urb) wake_up(&sisusb->wait_q); } -static int -sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, void *data, - int len, int *actual_length, int timeout, unsigned int tflags) +static int sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, + unsigned int pipe, void *data, int len, int *actual_length, + int timeout, unsigned int tflags) { struct urb *urb = sisusb->sisurbout[index]; int retval, byteswritten = 0; @@ -236,7 +224,8 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, urb->transfer_flags = 0; usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len, - sisusb_bulk_completeout, &sisusb->urbout_context[index]); + sisusb_bulk_completeout, + &sisusb->urbout_context[index]); urb->transfer_flags |= tflags; urb->actual_length = 0; @@ -277,8 +266,7 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, /* completion callback */ -static void -sisusb_bulk_completein(struct urb *urb) +static void sisusb_bulk_completein(struct urb *urb) { struct sisusb_usb_data *sisusb = urb->context; @@ -289,9 +277,9 @@ sisusb_bulk_completein(struct urb *urb) wake_up(&sisusb->wait_q); } -static int -sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data, - int len, int *actual_length, int timeout, unsigned int tflags) +static int sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, + unsigned int pipe, void *data, int len, + int *actual_length, int timeout, unsigned int tflags) { struct urb *urb = sisusb->sisurbin; int retval, readbytes = 0; @@ -405,14 +393,9 @@ static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len, if (!sisusb->sisusb_dev) return -ENODEV; - result = sisusb_bulkout_msg(sisusb, - index, - pipe, - buffer, - thispass, - &transferred_len, - async ? 0 : 5 * HZ, - tflags); + result = sisusb_bulkout_msg(sisusb, index, pipe, + buffer, thispass, &transferred_len, + async ? 0 : 5 * HZ, tflags); if (result == -ETIMEDOUT) { @@ -500,13 +483,8 @@ static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len, thispass = (bufsize < count) ? bufsize : count; - result = sisusb_bulkin_msg(sisusb, - pipe, - buffer, - thispass, - &transferred_len, - 5 * HZ, - tflags); + result = sisusb_bulkin_msg(sisusb, pipe, buffer, thispass, + &transferred_len, 5 * HZ, tflags); if (transferred_len) thispass = transferred_len; @@ -585,8 +563,7 @@ static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len, } static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len, - struct sisusb_packet *packet, - unsigned int tflags) + struct sisusb_packet *packet, unsigned int tflags) { int ret; ssize_t bytes_transferred = 0; @@ -780,9 +757,8 @@ static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type, */ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, - char *kernbuffer, int length, - const char __user *userbuffer, int index, - ssize_t *bytes_written) + char *kernbuffer, int length, const char __user *userbuffer, + int index, ssize_t *bytes_written) { struct sisusb_packet packet; int ret = 0; @@ -811,9 +787,8 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, } else swap8 = kernbuffer[0]; - ret = sisusb_write_memio_byte(sisusb, - SISUSB_TYPE_MEM, - addr, swap8); + ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, + addr, swap8); if (!ret) (*bytes_written)++; @@ -827,10 +802,8 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, } else swap16 = *((u16 *)kernbuffer); - ret = sisusb_write_memio_word(sisusb, - SISUSB_TYPE_MEM, - addr, - swap16); + ret = sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, + addr, swap16); if (!ret) (*bytes_written) += 2; @@ -861,10 +834,8 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, kernbuffer[0]; #endif - ret = sisusb_write_memio_24bit(sisusb, - SISUSB_TYPE_MEM, - addr, - swap32); + ret = sisusb_write_memio_24bit(sisusb, SISUSB_TYPE_MEM, + addr, swap32); if (!ret) (*bytes_written) += 3; @@ -878,10 +849,8 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, } else swap32 = *((u32 *)kernbuffer); - ret = sisusb_write_memio_long(sisusb, - SISUSB_TYPE_MEM, - addr, - swap32); + ret = sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, + addr, swap32); if (!ret) (*bytes_written) += 4; @@ -976,10 +945,13 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, if (ret) { msgcount++; if (msgcount < 500) - dev_err(&sisusb->sisusb_dev->dev, "Wrote %zd of %d bytes, error %d\n", - *bytes_written, length, ret); + dev_err(&sisusb->sisusb_dev->dev, + "Wrote %zd of %d bytes, error %d\n", + *bytes_written, length, + ret); else if (msgcount == 500) - dev_err(&sisusb->sisusb_dev->dev, "Too many errors, logging stopped\n"); + dev_err(&sisusb->sisusb_dev->dev, + "Too many errors, logging stopped\n"); } addr += (*bytes_written); length -= (*bytes_written); @@ -1137,8 +1109,8 @@ static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type, } static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, - char *kernbuffer, int length, - char __user *userbuffer, ssize_t *bytes_read) + char *kernbuffer, int length, char __user *userbuffer, + ssize_t *bytes_read) { int ret = 0; char buf[4]; @@ -1157,8 +1129,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, if (!ret) { (*bytes_read)++; if (userbuffer) { - if (put_user(buf[0], - (u8 __user *)userbuffer)) { + if (put_user(buf[0], (u8 __user *)userbuffer)) { return -EFAULT; } } else { @@ -1173,8 +1144,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, if (!ret) { (*bytes_read) += 2; if (userbuffer) { - if (put_user(swap16, - (u16 __user *)userbuffer)) + if (put_user(swap16, (u16 __user *)userbuffer)) return -EFAULT; } else { *((u16 *)kernbuffer) = swap16; @@ -1197,7 +1167,8 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, buf[0] = swap32 & 0xff; #endif if (userbuffer) { - if (copy_to_user(userbuffer, &buf[0], 3)) + if (copy_to_user(userbuffer, + &buf[0], 3)) return -EFAULT; } else { kernbuffer[0] = buf[0]; @@ -1213,8 +1184,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, if (!ret) { (*bytes_read) += 4; if (userbuffer) { - if (put_user(swap32, - (u32 __user *)userbuffer)) + if (put_user(swap32, (u32 __user *)userbuffer)) return -EFAULT; userbuffer += 4; @@ -1236,40 +1206,39 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, /* High level: Gfx (indexed) register access */ #ifdef INCL_SISUSB_CON -int -sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data) +int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data) { return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data); } -int -sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data) +int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data) { return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data); } #endif -int -sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data) +int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, + u8 index, u8 data) { int ret; + ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index); ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data); return ret; } -int -sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data) +int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, + u8 index, u8 *data) { int ret; + ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index); ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data); return ret; } -int -sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, - u8 myand, u8 myor) +int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, + u8 myand, u8 myor) { int ret; u8 tmp; @@ -1282,12 +1251,12 @@ sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, return ret; } -static int -sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx, - u8 data, u8 mask) +static int sisusb_setidxregmask(struct sisusb_usb_data *sisusb, + int port, u8 idx, u8 data, u8 mask) { int ret; u8 tmp; + ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx); ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp); tmp &= ~(mask); @@ -1296,14 +1265,14 @@ sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx, return ret; } -int -sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor) +int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, + u8 index, u8 myor) { return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor)); } -int -sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand) +int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, + u8 idx, u8 myand) { return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00)); } @@ -1311,38 +1280,35 @@ sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand) /* Write/read video ram */ #ifdef INCL_SISUSB_CON -int -sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data) +int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data) { return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data)); } -int -sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data) +int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data) { return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data)); } -int -sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, - u32 dest, int length, size_t *bytes_written) +int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, + u32 dest, int length, size_t *bytes_written) { - return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written)); + return(sisusb_write_mem_bulk(sisusb, dest, src, length, + NULL, 0, bytes_written)); } #ifdef SISUSBENDIANTEST -int -sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest, - u32 src, int length, size_t *bytes_written) +int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest, + u32 src, int length, size_t *bytes_written) { - return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written)); + return(sisusb_read_mem_bulk(sisusb, src, dest, length, + NULL, bytes_written)); } #endif #endif #ifdef SISUSBENDIANTEST -static void -sisusb_testreadwrite(struct sisusb_usb_data *sisusb) +static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb) { static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; char destbuffer[10]; @@ -1367,8 +1333,8 @@ sisusb_testreadwrite(struct sisusb_usb_data *sisusb) /* access pci config registers (reg numbers 0, 4, 8, etc) */ -static int -sisusb_write_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 data) +static int sisusb_write_pci_config(struct sisusb_usb_data *sisusb, + int regnum, u32 data) { struct sisusb_packet packet; int ret; @@ -1380,8 +1346,8 @@ sisusb_write_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 data) return ret; } -static int -sisusb_read_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 *data) +static int sisusb_read_pci_config(struct sisusb_usb_data *sisusb, + int regnum, u32 *data) { struct sisusb_packet packet; int ret; @@ -1395,8 +1361,8 @@ sisusb_read_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 *data) /* Clear video RAM */ -static int -sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length) +static int sisusb_clear_vram(struct sisusb_usb_data *sisusb, + u32 address, int length) { int ret, i; ssize_t j; @@ -1447,8 +1413,7 @@ sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length) #define READB(a, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) #define WRITEB(a, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) -static int -sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype) +static int sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype) { int ret; u8 tmp8; @@ -1478,8 +1443,8 @@ sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype) return ret; } -static int -sisusb_getbuswidth(struct sisusb_usb_data *sisusb, int *bw, int *chab) +static int sisusb_getbuswidth(struct sisusb_usb_data *sisusb, + int *bw, int *chab) { int ret; u8 ramtype, done = 0; @@ -1591,8 +1556,7 @@ sisusb_getbuswidth(struct sisusb_usb_data *sisusb, int *bw, int *chab) return ret; } -static int -sisusb_verify_mclk(struct sisusb_usb_data *sisusb) +static int sisusb_verify_mclk(struct sisusb_usb_data *sisusb) { int ret = 0; u32 ramptr = SISUSB_PCI_MEMBASE; @@ -1620,10 +1584,8 @@ sisusb_verify_mclk(struct sisusb_usb_data *sisusb) return ret; } -static int -sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, int index, - u8 rankno, u8 chab, const u8 dramtype[][5], - int bw) +static int sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, + int index, u8 rankno, u8 chab, const u8 dramtype[][5], int bw) { int ret = 0, ranksize; u8 tmp; @@ -1639,7 +1601,9 @@ sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, int index, return ret; tmp = 0; - while ((ranksize >>= 1) > 0) tmp += 0x10; + while ((ranksize >>= 1) > 0) + tmp += 0x10; + tmp |= ((rankno - 1) << 2); tmp |= ((bw / 64) & 0x02); tmp |= (chab & 0x01); @@ -1652,8 +1616,8 @@ sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, int index, return ret; } -static int -sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, u32 inc, int testn) +static int sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, + u32 inc, int testn) { int ret = 0, i; u32 j, tmp; @@ -1667,7 +1631,9 @@ sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, u32 inc, int testn) for (i = 0, j = 0; i < testn; i++) { ret |= READL(sisusb->vrambase + j, &tmp); - if (tmp != j) return ret; + if (tmp != j) + return ret; + j += inc; } @@ -1675,9 +1641,8 @@ sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, u32 inc, int testn) return ret; } -static int -sisusb_check_ranks(struct sisusb_usb_data *sisusb, int *iret, int rankno, - int idx, int bw, const u8 rtype[][5]) +static int sisusb_check_ranks(struct sisusb_usb_data *sisusb, + int *iret, int rankno, int idx, int bw, const u8 rtype[][5]) { int ret = 0, i, i2ret; u32 inc; @@ -1685,10 +1650,8 @@ sisusb_check_ranks(struct sisusb_usb_data *sisusb, int *iret, int rankno, *iret = 0; for (i = rankno; i >= 1; i--) { - inc = 1 << (rtype[idx][2] + - rtype[idx][1] + - rtype[idx][0] + - bw / 64 + i); + inc = 1 << (rtype[idx][2] + rtype[idx][1] + rtype[idx][0] + + bw / 64 + i); ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2); if (!i2ret) return ret; @@ -1708,9 +1671,8 @@ sisusb_check_ranks(struct sisusb_usb_data *sisusb, int *iret, int rankno, return ret; } -static int -sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, int bw, - int chab) +static int sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, + int bw, int chab) { int ret = 0, i2ret = 0, i, j; static const u8 sdramtype[13][5] = { @@ -1734,13 +1696,13 @@ sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, int bw, for (i = 0; i < 13; i++) { ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]); for (j = 2; j > 0; j--) { - ret |= sisusb_set_rank(sisusb, &i2ret, i, j, - chab, sdramtype, bw); + ret |= sisusb_set_rank(sisusb, &i2ret, i, j, chab, + sdramtype, bw); if (!i2ret) continue; - ret |= sisusb_check_ranks(sisusb, &i2ret, j, i, - bw, sdramtype); + ret |= sisusb_check_ranks(sisusb, &i2ret, j, i, bw, + sdramtype); if (i2ret) { *iret = 0; /* ram size found */ return ret; @@ -1751,8 +1713,8 @@ sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, int bw, return ret; } -static int -sisusb_setup_screen(struct sisusb_usb_data *sisusb, int clrall, int drwfr) +static int sisusb_setup_screen(struct sisusb_usb_data *sisusb, + int clrall, int drwfr) { int ret = 0; u32 address; @@ -1791,8 +1753,8 @@ sisusb_setup_screen(struct sisusb_usb_data *sisusb, int clrall, int drwfr) return ret; } -static int -sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines) +static int sisusb_set_default_mode(struct sisusb_usb_data *sisusb, + int touchengines) { int ret = 0, i, j, modex, modey, bpp, du; u8 sr31, cr63, tmp8; @@ -1872,12 +1834,16 @@ sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines) SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5)); SETIREG(SISCR, 0x14, 0x4f); du = (modex / 16) * (bpp * 2); /* offset/pitch */ - if (modex % 16) du += bpp; + if (modex % 16) + du += bpp; + SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f)); SETIREG(SISCR, 0x13, (du & 0xff)); du <<= 5; tmp8 = du >> 8; - if (du & 0xff) tmp8++; + if (du & 0xff) + tmp8++; + SETIREG(SISSR, 0x10, tmp8); SETIREG(SISSR, 0x31, 0x00); /* VCLK */ SETIREG(SISSR, 0x2b, 0x1b); @@ -1923,8 +1889,7 @@ sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines) return ret; } -static int -sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) +static int sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) { int ret = 0, i, j, bw, chab, iret, retry = 3; u8 tmp8, ramtype; @@ -1968,7 +1933,8 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) ret |= GETREG(SISMISCR, &tmp8); ret |= SETREG(SISMISCW, (tmp8 | 0x01)); - if (ret) continue; + if (ret) + continue; /* Reset registers */ ret |= SETIREGAND(SISCR, 0x5b, 0xdf); @@ -1993,7 +1959,8 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) ret |= SETIREG(SISCR, i, 0x00); } - if (ret) continue; + if (ret) + continue; ret |= SETIREG(SISCR, 0x63, 0x80); @@ -2011,13 +1978,16 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) ret |= SETIREG(SISSR, 0x07, 0x18); ret |= SETIREG(SISSR, 0x11, 0x0f); - if (ret) continue; + if (ret) + continue; for (i = 0x15, j = 0; i <= 0x1b; i++, j++) { - ret |= SETIREG(SISSR, i, ramtypetable1[(j*4) + ramtype]); + ret |= SETIREG(SISSR, i, + ramtypetable1[(j*4) + ramtype]); } for (i = 0x40, j = 0; i <= 0x44; i++, j++) { - ret |= SETIREG(SISCR, i, ramtypetable2[(j*4) + ramtype]); + ret |= SETIREG(SISCR, i, + ramtypetable2[(j*4) + ramtype]); } ret |= SETIREG(SISCR, 0x49, 0xaa); @@ -2034,7 +2004,8 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) ret |= SETIREGAND(SISCAP, 0x3f, 0xef); - if (ret) continue; + if (ret) + continue; ret |= SETIREG(SISPART1, 0x00, 0x00); @@ -2056,7 +2027,8 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) ret |= SETIREG(SISSR, 0x32, 0x11); ret |= SETIREG(SISSR, 0x33, 0x00); - if (ret) continue; + if (ret) + continue; ret |= SETIREG(SISCR, 0x83, 0x00); @@ -2078,12 +2050,14 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) if (ramtype <= 1) { ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab); if (iret) { - dev_err(&sisusb->sisusb_dev->dev,"RAM size detection failed, assuming 8MB video RAM\n"); + dev_err(&sisusb->sisusb_dev->dev, + "RAM size detection failed, assuming 8MB video RAM\n"); ret |= SETIREG(SISSR, 0x14, 0x31); /* TODO */ } } else { - dev_err(&sisusb->sisusb_dev->dev, "DDR RAM device found, assuming 8MB video RAM\n"); + dev_err(&sisusb->sisusb_dev->dev, + "DDR RAM device found, assuming 8MB video RAM\n"); ret |= SETIREG(SISSR, 0x14, 0x31); /* *** TODO *** */ } @@ -2115,8 +2089,7 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) #undef READL #undef WRITEL -static void -sisusb_get_ramconfig(struct sisusb_usb_data *sisusb) +static void sisusb_get_ramconfig(struct sisusb_usb_data *sisusb) { u8 tmp8, tmp82, ramtype; int bw = 0; @@ -2133,35 +2106,38 @@ sisusb_get_ramconfig(struct sisusb_usb_data *sisusb) sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024; ramtype &= 0x03; switch ((tmp8 >> 2) & 0x03) { - case 0: ramtypetext1 = "1 ch/1 r"; + case 0: + ramtypetext1 = "1 ch/1 r"; if (tmp82 & 0x10) { bw = 32; } else { bw = busSDR[(tmp8 & 0x03)]; } break; - case 1: ramtypetext1 = "1 ch/2 r"; + case 1: + ramtypetext1 = "1 ch/2 r"; sisusb->vramsize <<= 1; bw = busSDR[(tmp8 & 0x03)]; break; - case 2: ramtypetext1 = "asymmeric"; + case 2: + ramtypetext1 = "asymmeric"; sisusb->vramsize += sisusb->vramsize/2; bw = busDDRA[(tmp8 & 0x03)]; break; - case 3: ramtypetext1 = "2 channel"; + case 3: + ramtypetext1 = "2 channel"; sisusb->vramsize <<= 1; bw = busDDR[(tmp8 & 0x03)]; break; } - - dev_info(&sisusb->sisusb_dev->dev, "%dMB %s %cDR S%cRAM, bus width %d\n", - sisusb->vramsize >> 20, ramtypetext1, - ram_datarate[ramtype], ram_dynamictype[ramtype], bw); + dev_info(&sisusb->sisusb_dev->dev, + "%dMB %s %cDR S%cRAM, bus width %d\n", + sisusb->vramsize >> 20, ramtypetext1, + ram_datarate[ramtype], ram_dynamictype[ramtype], bw); } -static int -sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb) +static int sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb) { struct sisusb_packet packet; int ret; @@ -2239,8 +2215,7 @@ sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb) * of the graphics board. */ -static int -sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen) +static int sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen) { int ret = 0, test = 0; u32 tmp32; @@ -2248,16 +2223,25 @@ sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen) if (sisusb->devinit == 1) { /* Read PCI BARs and see if they have been set up */ ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32); - if (ret) return ret; - if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) test++; + if (ret) + return ret; + + if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) + test++; ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32); - if (ret) return ret; - if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) test++; + if (ret) + return ret; + + if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) + test++; ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32); - if (ret) return ret; - if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) test++; + if (ret) + return ret; + + if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) + test++; } /* No? So reset the device */ @@ -2292,15 +2276,15 @@ sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen) - Upload user font (if available) */ -int -sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) +int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) { int ret = 0, slot = sisusb->font_slot, i; const struct font_desc *myfont; u8 *tempbuf; u16 *tempbufb; size_t written; - static const char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer."; + static const char bootstring[] = + "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer."; static const char bootlogo[] = "(o_ //\\ V_/_"; /* sisusb->lock is down */ @@ -2326,7 +2310,8 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16); /* Upload default font */ - ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0); + ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, + 0, 1, NULL, 16, 0); vfree(tempbuf); @@ -2373,7 +2358,8 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) } else if (sisusb->scrbuf) { ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf, - sisusb->vrambase, sisusb->scrbuf_size, &written); + sisusb->vrambase, sisusb->scrbuf_size, + &written); } @@ -2390,7 +2376,8 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) } slot = sisusb->sisusb_cursor_loc; - if (slot < 0) slot = 0; + if (slot < 0) + slot = 0; sisusb->sisusb_cursor_loc = -1; sisusb->bad_cursor_pos = 1; @@ -2411,8 +2398,7 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) /* fops */ -static int -sisusb_open(struct inode *inode, struct file *file) +static int sisusb_open(struct inode *inode, struct file *file) { struct sisusb_usb_data *sisusb; struct usb_interface *interface; @@ -2445,12 +2431,14 @@ sisusb_open(struct inode *inode, struct file *file) sisusb->sisusb_dev->speed == USB_SPEED_SUPER) { if (sisusb_init_gfxdevice(sisusb, 0)) { mutex_unlock(&sisusb->lock); - dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n"); + dev_err(&sisusb->sisusb_dev->dev, + "Failed to initialize device\n"); return -EIO; } } else { mutex_unlock(&sisusb->lock); - dev_err(&sisusb->sisusb_dev->dev, "Device not attached to USB 2.0 hub\n"); + dev_err(&sisusb->sisusb_dev->dev, + "Device not attached to USB 2.0 hub\n"); return -EIO; } } @@ -2467,8 +2455,7 @@ sisusb_open(struct inode *inode, struct file *file) return 0; } -void -sisusb_delete(struct kref *kref) +void sisusb_delete(struct kref *kref) { struct sisusb_usb_data *sisusb = to_sisusb_dev(kref); @@ -2486,8 +2473,7 @@ sisusb_delete(struct kref *kref) kfree(sisusb); } -static int -sisusb_release(struct inode *inode, struct file *file) +static int sisusb_release(struct inode *inode, struct file *file) { struct sisusb_usb_data *sisusb; @@ -2514,8 +2500,8 @@ sisusb_release(struct inode *inode, struct file *file) return 0; } -static ssize_t -sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) +static ssize_t sisusb_read(struct file *file, char __user *buffer, + size_t count, loff_t *ppos) { struct sisusb_usb_data *sisusb; ssize_t bytes_read = 0; @@ -2539,9 +2525,8 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE && (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { - address = (*ppos) - - SISUSB_PCI_PSEUDO_IOPORTBASE + - SISUSB_PCI_IOPORTBASE; + address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE + + SISUSB_PCI_IOPORTBASE; /* Read i/o ports * Byte, word and long(32) can be read. As this @@ -2550,8 +2535,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) */ switch (count) { case 1: - if (sisusb_read_memio_byte(sisusb, - SISUSB_TYPE_IO, + if (sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, address, &buf8)) errno = -EIO; else if (put_user(buf8, (u8 __user *)buffer)) @@ -2562,8 +2546,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) break; case 2: - if (sisusb_read_memio_word(sisusb, - SISUSB_TYPE_IO, + if (sisusb_read_memio_word(sisusb, SISUSB_TYPE_IO, address, &buf16)) errno = -EIO; else if (put_user(buf16, (u16 __user *)buffer)) @@ -2574,8 +2557,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) break; case 4: - if (sisusb_read_memio_long(sisusb, - SISUSB_TYPE_IO, + if (sisusb_read_memio_long(sisusb, SISUSB_TYPE_IO, address, &buf32)) errno = -EIO; else if (put_user(buf32, (u32 __user *)buffer)) @@ -2590,12 +2572,11 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) } - } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && - (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) { + } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && (*ppos) < + SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) { - address = (*ppos) - - SISUSB_PCI_PSEUDO_MEMBASE + - SISUSB_PCI_MEMBASE; + address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE + + SISUSB_PCI_MEMBASE; /* Read video ram * Remember: Data delivered is never endian-corrected @@ -2607,11 +2588,11 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) errno = bytes_read; } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE && - (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) { + (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + + SISUSB_PCI_MMIOSIZE) { - address = (*ppos) - - SISUSB_PCI_PSEUDO_MMIOBASE + - SISUSB_PCI_MMIOBASE; + address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE + + SISUSB_PCI_MMIOBASE; /* Read MMIO * Remember: Data delivered is never endian-corrected @@ -2655,9 +2636,8 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) return errno ? errno : bytes_read; } -static ssize_t -sisusb_write(struct file *file, const char __user *buffer, size_t count, - loff_t *ppos) +static ssize_t sisusb_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) { struct sisusb_usb_data *sisusb; int errno = 0; @@ -2681,9 +2661,8 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE && (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { - address = (*ppos) - - SISUSB_PCI_PSEUDO_IOPORTBASE + - SISUSB_PCI_IOPORTBASE; + address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE + + SISUSB_PCI_IOPORTBASE; /* Write i/o ports * Byte, word and long(32) can be written. As this @@ -2695,8 +2674,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, if (get_user(buf8, (u8 __user *)buffer)) errno = -EFAULT; else if (sisusb_write_memio_byte(sisusb, - SISUSB_TYPE_IO, - address, buf8)) + SISUSB_TYPE_IO, address, buf8)) errno = -EIO; else bytes_written = 1; @@ -2707,8 +2685,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, if (get_user(buf16, (u16 __user *)buffer)) errno = -EFAULT; else if (sisusb_write_memio_word(sisusb, - SISUSB_TYPE_IO, - address, buf16)) + SISUSB_TYPE_IO, address, buf16)) errno = -EIO; else bytes_written = 2; @@ -2719,8 +2696,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, if (get_user(buf32, (u32 __user *)buffer)) errno = -EFAULT; else if (sisusb_write_memio_long(sisusb, - SISUSB_TYPE_IO, - address, buf32)) + SISUSB_TYPE_IO, address, buf32)) errno = -EIO; else bytes_written = 4; @@ -2732,11 +2708,11 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, } } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && - (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) { + (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + + sisusb->vramsize) { - address = (*ppos) - - SISUSB_PCI_PSEUDO_MEMBASE + - SISUSB_PCI_MEMBASE; + address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE + + SISUSB_PCI_MEMBASE; /* Write video ram. * Buffer is copied 1:1, therefore, on big-endian @@ -2751,11 +2727,11 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, errno = bytes_written; } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE && - (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) { + (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + + SISUSB_PCI_MMIOSIZE) { - address = (*ppos) - - SISUSB_PCI_PSEUDO_MMIOBASE + - SISUSB_PCI_MMIOBASE; + address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE + + SISUSB_PCI_MMIOBASE; /* Write MMIO. * Buffer is copied 1:1, therefore, on big-endian @@ -2769,7 +2745,8 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, errno = bytes_written; } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE && - (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) { + (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + + SISUSB_PCI_PCONFSIZE) { if (count != 4) { mutex_unlock(&sisusb->lock); @@ -2803,8 +2780,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, return errno ? errno : bytes_written; } -static loff_t -sisusb_lseek(struct file *file, loff_t offset, int orig) +static loff_t sisusb_lseek(struct file *file, loff_t offset, int orig) { struct sisusb_usb_data *sisusb; loff_t ret; @@ -2827,9 +2803,8 @@ sisusb_lseek(struct file *file, loff_t offset, int orig) return ret; } -static int -sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y, - unsigned long arg) +static int sisusb_handle_command(struct sisusb_usb_data *sisusb, + struct sisusb_command *y, unsigned long arg) { int retval, port, length; u32 address; @@ -2946,8 +2921,7 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y, return retval; } -static long -sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct sisusb_usb_data *sisusb; struct sisusb_info x; @@ -3021,8 +2995,8 @@ err_out: } #ifdef SISUSB_NEW_CONFIG_COMPAT -static long -sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg) +static long sisusb_compat_ioctl(struct file *f, unsigned int cmd, + unsigned long arg) { long retval; @@ -3081,8 +3055,9 @@ static int sisusb_probe(struct usb_interface *intf, /* Register device */ retval = usb_register_dev(intf, &usb_sisusb_class); if (retval) { - dev_err(&sisusb->sisusb_dev->dev, "Failed to get a minor for device %d\n", - dev->devnum); + dev_err(&sisusb->sisusb_dev->dev, + "Failed to get a minor for device %d\n", + dev->devnum); retval = -ENODEV; goto error_1; } @@ -3128,7 +3103,8 @@ static int sisusb_probe(struct usb_interface *intf, for (i = 0; i < sisusb->numobufs; i++) { if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) { - dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n"); + dev_err(&sisusb->sisusb_dev->dev, + "Failed to allocate URBs\n"); retval = -ENOMEM; goto error_4; } @@ -3137,7 +3113,8 @@ static int sisusb_probe(struct usb_interface *intf, sisusb->urbstatus[i] = 0; } - dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n", sisusb->numobufs); + dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n", + sisusb->numobufs); #ifdef INCL_SISUSB_CON /* Allocate our SiS_Pr */ @@ -3159,17 +3136,18 @@ static int sisusb_probe(struct usb_interface *intf, if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER) { int initscreen = 1; #ifdef INCL_SISUSB_CON - if (sisusb_first_vc > 0 && - sisusb_last_vc > 0 && - sisusb_first_vc <= sisusb_last_vc && - sisusb_last_vc <= MAX_NR_CONSOLES) + if (sisusb_first_vc > 0 && sisusb_last_vc > 0 && + sisusb_first_vc <= sisusb_last_vc && + sisusb_last_vc <= MAX_NR_CONSOLES) initscreen = 0; #endif if (sisusb_init_gfxdevice(sisusb, initscreen)) - dev_err(&sisusb->sisusb_dev->dev, "Failed to early initialize device\n"); + dev_err(&sisusb->sisusb_dev->dev, + "Failed to early initialize device\n"); } else - dev_info(&sisusb->sisusb_dev->dev, "Not attached to USB 2.0 hub, deferring init\n"); + dev_info(&sisusb->sisusb_dev->dev, + "Not attached to USB 2.0 hub, deferring init\n"); sisusb->ready = 1; -- cgit v1.2.3 From f996c49d4fa4e8e33955eb59691e1b116b3d733b Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Fri, 15 Jan 2016 18:41:30 +0100 Subject: usb-misc: sisusbvga: Fix coding style: braces, parenthesis, comment The file drivers/usb/misc/sisusbvga/sisusb.c contained coding style issues reported by checkpatch. This patch fixes the following errors: - 12 WARNING: braces {} are not necessary for single statement blocks - 04 ERROR: return is not a function, parentheses are not required - 03 ERROR: do not initialise statics to 0 - 1 WARNING: else is not generally useful after a break or return - 1 WARNING: braces {} are not necessary for any arm of this statement - 1 WARNING: Block comments use * on subsequent lines One case in which braces are not necessary is left unchanged as other patch of the series will fix it. Signed-off-by: Peter Senna Tschudin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 88 +++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index ea0e1ad5d4bc..26925f74cd92 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -61,8 +61,8 @@ /* Forward declarations / clean-up routines */ #ifdef INCL_SISUSB_CON -static int sisusb_first_vc = 0; -static int sisusb_last_vc = 0; +static int sisusb_first_vc; +static int sisusb_last_vc; module_param_named(first, sisusb_first_vc, int, 0); module_param_named(last, sisusb_last_vc, int, 0); MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)"); @@ -762,7 +762,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, { struct sisusb_packet packet; int ret = 0; - static int msgcount = 0; + static int msgcount; u8 swap8, fromkern = kernbuffer ? 1 : 0; u16 swap16; u32 swap32, flag = (length >> 28) & 1; @@ -1129,12 +1129,10 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, if (!ret) { (*bytes_read)++; if (userbuffer) { - if (put_user(buf[0], (u8 __user *)userbuffer)) { + if (put_user(buf[0], (u8 __user *)userbuffer)) return -EFAULT; - } - } else { + } else kernbuffer[0] = buf[0]; - } } return ret; @@ -1268,13 +1266,13 @@ static int sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor) { - return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor)); + return sisusb_setidxregandor(sisusb, port, index, 0xff, myor); } int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand) { - return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00)); + return sisusb_setidxregandor(sisusb, port, idx, myand, 0x00); } /* Write/read video ram */ @@ -1282,27 +1280,27 @@ int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, #ifdef INCL_SISUSB_CON int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data) { - return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data)); + return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data); } int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data) { - return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data)); + return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data); } int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, u32 dest, int length, size_t *bytes_written) { - return(sisusb_write_mem_bulk(sisusb, dest, src, length, - NULL, 0, bytes_written)); + return sisusb_write_mem_bulk(sisusb, dest, src, length, + NULL, 0, bytes_written); } #ifdef SISUSBENDIANTEST int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest, u32 src, int length, size_t *bytes_written) { - return(sisusb_read_mem_bulk(sisusb, src, dest, length, - NULL, bytes_written)); + return sisusb_read_mem_bulk(sisusb, src, dest, length, + NULL, bytes_written); } #endif #endif @@ -1818,18 +1816,18 @@ static int sisusb_set_default_mode(struct sisusb_usb_data *sisusb, SETIREGAND(SISSR, 0x37, 0xfe); SETREG(SISMISCW, 0xef); /* sync */ SETIREG(SISCR, 0x11, 0x00); /* crtc */ - for (j = 0x00, i = 0; i <= 7; i++, j++) { + for (j = 0x00, i = 0; i <= 7; i++, j++) SETIREG(SISCR, j, crtcdata[i]); - } - for (j = 0x10; i <= 10; i++, j++) { + + for (j = 0x10; i <= 10; i++, j++) SETIREG(SISCR, j, crtcdata[i]); - } - for (j = 0x15; i <= 12; i++, j++) { + + for (j = 0x15; i <= 12; i++, j++) SETIREG(SISCR, j, crtcdata[i]); - } - for (j = 0x0A; i <= 15; i++, j++) { + + for (j = 0x0A; i <= 15; i++, j++) SETIREG(SISSR, j, crtcdata[i]); - } + SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0)); SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5)); SETIREG(SISCR, 0x14, 0x4f); @@ -1943,21 +1941,20 @@ static int sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) ret |= SETREG(SISMISCW, 0x67); - for (i = 0x06; i <= 0x1f; i++) { + for (i = 0x06; i <= 0x1f; i++) ret |= SETIREG(SISSR, i, 0x00); - } - for (i = 0x21; i <= 0x27; i++) { + + for (i = 0x21; i <= 0x27; i++) ret |= SETIREG(SISSR, i, 0x00); - } - for (i = 0x31; i <= 0x3d; i++) { + + for (i = 0x31; i <= 0x3d; i++) ret |= SETIREG(SISSR, i, 0x00); - } - for (i = 0x12; i <= 0x1b; i++) { + + for (i = 0x12; i <= 0x1b; i++) ret |= SETIREG(SISSR, i, 0x00); - } - for (i = 0x79; i <= 0x7c; i++) { + + for (i = 0x79; i <= 0x7c; i++) ret |= SETIREG(SISCR, i, 0x00); - } if (ret) continue; @@ -2108,11 +2105,11 @@ static void sisusb_get_ramconfig(struct sisusb_usb_data *sisusb) switch ((tmp8 >> 2) & 0x03) { case 0: ramtypetext1 = "1 ch/1 r"; - if (tmp82 & 0x10) { + if (tmp82 & 0x10) bw = 32; - } else { + else bw = busSDR[(tmp8 & 0x03)]; - } + break; case 1: ramtypetext1 = "1 ch/2 r"; @@ -2271,10 +2268,10 @@ static int sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen) #ifdef INCL_SISUSB_CON /* Set up default text mode: - - Set text mode (0x03) - - Upload default font - - Upload user font (if available) -*/ + * - Set text mode (0x03) + * - Upload default font + * - Upload user font (if available) + */ int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) { @@ -2405,14 +2402,12 @@ static int sisusb_open(struct inode *inode, struct file *file) int subminor = iminor(inode); interface = usb_find_interface(&sisusb_driver, subminor); - if (!interface) { + if (!interface) return -ENODEV; - } sisusb = usb_get_intfdata(interface); - if (!sisusb) { + if (!sisusb) return -ENODEV; - } mutex_lock(&sisusb->lock); @@ -3088,9 +3083,8 @@ static int sisusb_probe(struct usb_interface *intf, goto error_3; } break; - } else - sisusb->numobufs++; - + } + sisusb->numobufs++; } /* Allocate URBs */ -- cgit v1.2.3 From 662bfe7b537f0c199024b252d451727a76449233 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Fri, 15 Jan 2016 18:41:31 +0100 Subject: usb-misc: sisusbvga: Fix coding style: remove assignment from if tests The file drivers/usb/misc/sisusbvga/sisusb.c had 6 assignments inside if tests. This patch move the assignment outside the test. The changes also fix the remaining 2 lines that were over 80 characters. Signed-off-by: Peter Senna Tschudin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 26925f74cd92..40f360ab406d 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -1378,7 +1378,8 @@ static int sisusb_clear_vram(struct sisusb_usb_data *sisusb, return 0; /* allocate free buffer/urb and clear the buffer */ - if ((i = sisusb_alloc_outbuf(sisusb)) < 0) + i = sisusb_alloc_outbuf(sisusb); + if (i < 0) return -EBUSY; memset(sisusb->obuf[i], 0, sisusb->obufsize); @@ -3067,7 +3068,8 @@ static int sisusb_probe(struct usb_interface *intf, /* Allocate buffers */ sisusb->ibufsize = SISUSB_IBUF_SIZE; - if (!(sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL))) { + sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL); + if (!sisusb->ibuf) { dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for input buffer"); retval = -ENOMEM; goto error_2; @@ -3076,7 +3078,8 @@ static int sisusb_probe(struct usb_interface *intf, sisusb->numobufs = 0; sisusb->obufsize = SISUSB_OBUF_SIZE; for (i = 0; i < NUMOBUFS; i++) { - if (!(sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL))) { + sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL); + if (!sisusb->obuf[i]) { if (i == 0) { dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for output buffer\n"); retval = -ENOMEM; @@ -3088,7 +3091,8 @@ static int sisusb_probe(struct usb_interface *intf, } /* Allocate URBs */ - if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) { + sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL); + if (!sisusb->sisurbin) { dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n"); retval = -ENOMEM; goto error_3; @@ -3096,7 +3100,8 @@ static int sisusb_probe(struct usb_interface *intf, sisusb->completein = 1; for (i = 0; i < sisusb->numobufs; i++) { - if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) { + sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL); + if (!sisusb->sisurbout[i]) { dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n"); retval = -ENOMEM; @@ -3112,7 +3117,8 @@ static int sisusb_probe(struct usb_interface *intf, #ifdef INCL_SISUSB_CON /* Allocate our SiS_Pr */ - if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) { + sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL); + if (!sisusb->SiS_Pr) { dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate SiS_Pr\n"); } #endif -- cgit v1.2.3 From 8a102fd6c99a26a0aa74e3d4bed4092b3c791361 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Fri, 15 Jan 2016 18:41:32 +0100 Subject: usb-misc: sisusbvga: Remove null test before calls to kfree() This patch removes null test before calls to kfree() as kfree() can handle null pointers safely. Signed-off-by: Peter Senna Tschudin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 40f360ab406d..bea6d88f769a 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -76,15 +76,11 @@ static void sisusb_free_buffers(struct sisusb_usb_data *sisusb) int i; for (i = 0; i < NUMOBUFS; i++) { - if (sisusb->obuf[i]) { - kfree(sisusb->obuf[i]); - sisusb->obuf[i] = NULL; - } - } - if (sisusb->ibuf) { - kfree(sisusb->ibuf); - sisusb->ibuf = NULL; + kfree(sisusb->obuf[i]); + sisusb->obuf[i] = NULL; } + kfree(sisusb->ibuf); + sisusb->ibuf = NULL; } static void sisusb_free_urbs(struct sisusb_usb_data *sisusb) -- cgit v1.2.3 From f40849b86862c00f24db10bc11fe2e972c029ec4 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Fri, 15 Jan 2016 18:41:33 +0100 Subject: usb-misc: sisusbvga: Remove memory allocation logs This patch remove three calls to dev_err() from sisusb_probe() as reporting memory allocation failures is redundant: - Remove a call to dev_err() that was reporting unsuccesful call to kzalloc(). - Remove two calls to dev_err() that were reporting unsuccesful calls to kmalloc(). One call to dev_err() reporting memory allocation is left unchanged as the last patch of the series removes it. Signed-off-by: Peter Senna Tschudin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index bea6d88f769a..b3713d57ce01 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -3036,10 +3036,9 @@ static int sisusb_probe(struct usb_interface *intf, /* Allocate memory for our private */ sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL); - if (!sisusb) { - dev_err(&dev->dev, "Failed to allocate memory for private data\n"); + if (!sisusb) return -ENOMEM; - } + kref_init(&sisusb->kref); mutex_init(&(sisusb->lock)); @@ -3066,7 +3065,6 @@ static int sisusb_probe(struct usb_interface *intf, sisusb->ibufsize = SISUSB_IBUF_SIZE; sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL); if (!sisusb->ibuf) { - dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for input buffer"); retval = -ENOMEM; goto error_2; } @@ -3077,7 +3075,6 @@ static int sisusb_probe(struct usb_interface *intf, sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL); if (!sisusb->obuf[i]) { if (i == 0) { - dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for output buffer\n"); retval = -ENOMEM; goto error_3; } -- cgit v1.2.3 From 0e781c2258ffb2a42bf44f62dea8662f38cbfd34 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Fri, 15 Jan 2016 18:41:34 +0100 Subject: usb-misc: sisusbvga: fix error path Remove a call to dev_err() that was reporting an unsuccesful call to kmalloc(), as reporting memory allocation failures is redundant. Instead of logging the error, clean up previously allocated resources and abort the probe with -ENOMEM. Before this change sisusb->SiS_Pr could be dereferenced even if null after failure of memory allocation. Signed-off-by: Peter Senna Tschudin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index b3713d57ce01..a22de52cb083 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -3112,7 +3112,8 @@ static int sisusb_probe(struct usb_interface *intf, /* Allocate our SiS_Pr */ sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL); if (!sisusb->SiS_Pr) { - dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate SiS_Pr\n"); + retval = -ENOMEM; + goto error_4; } #endif -- cgit v1.2.3 From 19454462acb1bdef80542061bdc9b410e4ed1ff6 Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Wed, 30 Dec 2015 12:59:08 +0800 Subject: usb: cdc-acm: handle unlinked urb in acm read callback In current acm driver, the bulk-in callback function ignores the URBs unlinked in usb core. This causes unexpected data loss in some cases. For example, runtime suspend entry will unlinked all urbs and set urb->status to -ENOENT even those urbs might have data not processed yet. Hence, data loss occurs. This patch lets bulk-in callback function handle unlinked urbs to avoid data loss. Signed-off-by: Tang Jian Qiang Signed-off-by: Lu Baolu Cc: stable@vger.kernel.org Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 26ca4f910cb0..8cd193bbd044 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -428,7 +428,8 @@ static void acm_read_bulk_callback(struct urb *urb) set_bit(rb->index, &acm->read_urbs_free); dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n", __func__, status); - return; + if ((status != -ENOENT) || (urb->actual_length == 0)) + return; } usb_mark_last_busy(acm->dev); -- cgit v1.2.3 From ffdb1e369a73b380fce95b05f8498d92c43842b4 Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Wed, 6 Jan 2016 15:10:04 +0800 Subject: usb: cdc-acm: send zero packet for intel 7260 modem For Intel 7260 modem, it is needed for host side to send zero packet if the BULK OUT size is equal to USB endpoint max packet length. Otherwise, modem side may still wait for more data and cannot give response to host side. Signed-off-by: Konrad Leszczynski Signed-off-by: Lu Baolu Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 6 ++++++ drivers/usb/class/cdc-acm.h | 1 + 2 files changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 8cd193bbd044..e4c70dce3e7c 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1405,6 +1405,8 @@ made_compressed_probe: usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), NULL, acm->writesize, acm_write_bulk, snd); snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + if (quirks & SEND_ZERO_PACKET) + snd->urb->transfer_flags |= URB_ZERO_PACKET; snd->instance = acm; } @@ -1862,6 +1864,10 @@ static const struct usb_device_id acm_ids[] = { { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_ACM_PROTO_AT_CDMA) }, + { USB_DEVICE(0x1519, 0x0452), /* Intel 7260 modem */ + .driver_info = SEND_ZERO_PACKET, + }, + { } }; diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index dd9af38e7cda..ccfaba9ab4e4 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h @@ -134,3 +134,4 @@ struct acm { #define IGNORE_DEVICE BIT(5) #define QUIRK_CONTROL_LINE_STATE BIT(6) #define CLEAR_HALT_CONDITIONS BIT(7) +#define SEND_ZERO_PACKET BIT(8) -- cgit v1.2.3 From e912e685f372ab62a2405a1acd923597f524e94a Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Jan 2016 15:45:18 +0100 Subject: cdc-acm:exclude Samsung phone 04e8:685d This phone needs to be handled by a specialised firmware tool and is reported to crash irrevocably if cdc-acm takes it. Signed-off-by: Oliver Neukum CC: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index e4c70dce3e7c..fa4e23930614 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1841,6 +1841,11 @@ static const struct usb_device_id acm_ids[] = { }, #endif + /*Samsung phone in firmware update mode */ + { USB_DEVICE(0x04e8, 0x685d), + .driver_info = IGNORE_DEVICE, + }, + /* Exclude Infineon Flash Loader utility */ { USB_DEVICE(0x058b, 0x0041), .driver_info = IGNORE_DEVICE, -- cgit v1.2.3 From d8f00cd685f5c8e0def8593e520a7fef12c22407 Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Mon, 18 Jan 2016 21:02:42 +0800 Subject: usb: hub: do not clear BOS field during reset device In function usb_reset_and_verify_device, the old BOS descriptor may still be used before allocating a new one. (usb_unlocked_disable_lpm function uses it under the situation that it fails to disable lpm.) So we cannot set the udev->bos to NULL before that, just keep what it was. It will be overwrite when allocating a new one. Crash log: BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 IP: [] usb_enable_link_state+0x2d/0x2f0 Call Trace: [] ? usb_set_lpm_timeout+0x12b/0x140 [] usb_enable_lpm+0x81/0xa0 [] usb_disable_lpm+0xa8/0xc0 [] usb_unlocked_disable_lpm+0x2c/0x50 [] usb_reset_and_verify_device+0xc3/0x710 [] ? usb_sg_wait+0x13d/0x190 [] usb_reset_device+0x133/0x280 [] usb_stor_port_reset+0x61/0x70 [] usb_stor_invoke_transport+0x88/0x520 Signed-off-by: Du, Changbin Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 51b436918f78..350dcd9af5d8 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -5401,7 +5401,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev) } bos = udev->bos; - udev->bos = NULL; for (i = 0; i < SET_CONFIG_TRIES; ++i) { @@ -5494,8 +5493,11 @@ done: usb_set_usb2_hardware_lpm(udev, 1); usb_unlocked_enable_lpm(udev); usb_enable_ltm(udev); - usb_release_bos_descriptor(udev); - udev->bos = bos; + /* release the new BOS descriptor allocated by hub_port_init() */ + if (udev->bos != bos) { + usb_release_bos_descriptor(udev); + udev->bos = bos; + } return 0; re_enumerate: -- cgit v1.2.3 From 9b3f105ef6c75ef4f7f1bd982195db814830d78b Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 17 Sep 2015 08:04:51 +0900 Subject: cpufreq: s5pv210: remove superfluous CONFIG_PM ifdefs CONFIG_PM ifdefs are superfluous and can be removed. Signed-off-by: Bartlomiej Zolnierkiewicz Acked-by: Viresh Kumar Signed-off-by: Kukjin Kim Signed-off-by: Krzysztof Kozlowski --- drivers/cpufreq/s5pv210-cpufreq.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c index 051a8a8224cd..a145b319d171 100644 --- a/drivers/cpufreq/s5pv210-cpufreq.c +++ b/drivers/cpufreq/s5pv210-cpufreq.c @@ -576,10 +576,8 @@ static struct cpufreq_driver s5pv210_driver = { .get = cpufreq_generic_get, .init = s5pv210_cpu_init, .name = "s5pv210", -#ifdef CONFIG_PM .suspend = cpufreq_generic_suspend, .resume = cpufreq_generic_suspend, /* We need to set SLEEP FREQ again */ -#endif }; static struct notifier_block s5pv210_cpufreq_reboot_notifier = { -- cgit v1.2.3 From b5d7a06906a4875524f5c61c0b312828bf6737de Mon Sep 17 00:00:00 2001 From: Iyappan Subramanian Date: Thu, 21 Jan 2016 16:07:41 -0800 Subject: drivers: net: xgene: fix extra IRQ issue For interrupt controller that doesn't support irq_disable and hardware with level interrupt, an extra interrupt may be pending. This patch fixes the issue by setting IRQ_DISABLE_UNLAZY flag for the interrupt line, as suggested by, 'commit e9849777d0e2 ("genirq: Add flag to force mask in disable_irq[_nosync]()")' Signed-off-by: Iyappan Subramanian Tested-by: Toan Le Signed-off-by: David S. Miller --- drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 12 +++++++++--- drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index a4799c1fc7d4..5eb9b20c0eea 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -628,6 +628,7 @@ static int xgene_enet_register_irq(struct net_device *ndev) int ret; ring = pdata->rx_ring; + irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY); ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq, IRQF_SHARED, ring->irq_name, ring); if (ret) @@ -635,6 +636,7 @@ static int xgene_enet_register_irq(struct net_device *ndev) if (pdata->cq_cnt) { ring = pdata->tx_ring->cp_ring; + irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY); ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq, IRQF_SHARED, ring->irq_name, ring); if (ret) { @@ -649,15 +651,19 @@ static int xgene_enet_register_irq(struct net_device *ndev) static void xgene_enet_free_irq(struct net_device *ndev) { struct xgene_enet_pdata *pdata; + struct xgene_enet_desc_ring *ring; struct device *dev; pdata = netdev_priv(ndev); dev = ndev_to_dev(ndev); - devm_free_irq(dev, pdata->rx_ring->irq, pdata->rx_ring); + ring = pdata->rx_ring; + irq_clear_status_flags(ring->irq, IRQ_DISABLE_UNLAZY); + devm_free_irq(dev, ring->irq, ring); if (pdata->cq_cnt) { - devm_free_irq(dev, pdata->tx_ring->cp_ring->irq, - pdata->tx_ring->cp_ring); + ring = pdata->tx_ring->cp_ring; + irq_clear_status_flags(ring->irq, IRQ_DISABLE_UNLAZY); + devm_free_irq(dev, ring->irq, ring); } } diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h index 70d5b62c125a..248dfc40a761 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 9a368aff9cb370298fa02feeffa861f2db497c18 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Fri, 22 Jan 2016 01:39:43 +0100 Subject: pptp: fix illegal memory access caused by multiple bind()s Several times already this has been reported as kasan reports caused by syzkaller and trinity and people always looked at RCU races, but it is much more simple. :) In case we bind a pptp socket multiple times, we simply add it to the callid_sock list but don't remove the old binding. Thus the old socket stays in the bucket with unused call_id indexes and doesn't get cleaned up. This causes various forms of kasan reports which were hard to pinpoint. Simply don't allow multiple binds and correct error handling in pptp_bind. Also keep sk_state bits in place in pptp_connect. Fixes: 00959ade36acad ("PPTP: PPP over IPv4 (Point-to-Point Tunneling Protocol)") Cc: Dmitry Kozlov Cc: Sasha Levin Cc: Dmitry Vyukov Reported-by: Dmitry Vyukov Cc: Dave Jones Reported-by: Dave Jones Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- drivers/net/ppp/pptp.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 90868ca5e341..ae0905ed4a32 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -129,24 +129,27 @@ static int lookup_chan_dst(u16 call_id, __be32 d_addr) return i < MAX_CALLID; } -static int add_chan(struct pppox_sock *sock) +static int add_chan(struct pppox_sock *sock, + struct pptp_addr *sa) { static int call_id; spin_lock(&chan_lock); - if (!sock->proto.pptp.src_addr.call_id) { + if (!sa->call_id) { call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1); if (call_id == MAX_CALLID) { call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, 1); if (call_id == MAX_CALLID) goto out_err; } - sock->proto.pptp.src_addr.call_id = call_id; - } else if (test_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap)) + sa->call_id = call_id; + } else if (test_bit(sa->call_id, callid_bitmap)) { goto out_err; + } - set_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap); - rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], sock); + sock->proto.pptp.src_addr = *sa; + set_bit(sa->call_id, callid_bitmap); + rcu_assign_pointer(callid_sock[sa->call_id], sock); spin_unlock(&chan_lock); return 0; @@ -416,7 +419,6 @@ static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr, struct sock *sk = sock->sk; struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr; struct pppox_sock *po = pppox_sk(sk); - struct pptp_opt *opt = &po->proto.pptp; int error = 0; if (sockaddr_len < sizeof(struct sockaddr_pppox)) @@ -424,10 +426,22 @@ static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr, lock_sock(sk); - opt->src_addr = sp->sa_addr.pptp; - if (add_chan(po)) + if (sk->sk_state & PPPOX_DEAD) { + error = -EALREADY; + goto out; + } + + if (sk->sk_state & PPPOX_BOUND) { error = -EBUSY; + goto out; + } + + if (add_chan(po, &sp->sa_addr.pptp)) + error = -EBUSY; + else + sk->sk_state |= PPPOX_BOUND; +out: release_sock(sk); return error; } @@ -498,7 +512,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, } opt->dst_addr = sp->sa_addr.pptp; - sk->sk_state = PPPOX_CONNECTED; + sk->sk_state |= PPPOX_CONNECTED; end: release_sock(sk); -- cgit v1.2.3 From 40f8cf4b5cb606c593be25cbf71c34d505815b90 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 22 Jan 2016 08:53:45 +0100 Subject: drm/fbdev-helper: Explain how to debug console_lock fun Every new KMS driver writer seems to run into this and wonder how exactly drm_fb_helper_initial_config can die doing nothing at all. Set up some big warnings signs around this newbie trap to avoid future frustration and wasting everyone's time. v2: Edits from Laurent. Cc: Carlos Palminha Cc: Xinliang Liu Cc: laurent.pinchart@ideasonboard.com Reviewed-by: Laurent Pinchart Link: http://patchwork.freedesktop.org/patch/msgid/1453449225-10954-1-git-send-email-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_helper.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 1e103c4c6ee0..76a364e62081 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -2091,6 +2091,27 @@ out: * drm_fb_helper_fill_fix() are provided as helpers to setup simple default * values for the fbdev info structure. * + * HANG DEBUGGING: + * + * When you have fbcon support built-in or already loaded, this function will do + * a full modeset to setup the fbdev console. Due to locking misdesign in the + * VT/fbdev subsystem that entire modeset sequence has to be done while holding + * console_lock. Until console_unlock is called no dmesg lines will be sent out + * to consoles, not even serial console. This means when your driver crashes, + * you will see absolutely nothing else but a system stuck in this function, + * with no further output. Any kind of printk() you place within your own driver + * or in the drm core modeset code will also never show up. + * + * Standard debug practice is to run the fbcon setup without taking the + * console_lock as a hack, to be able to see backtraces and crashes on the + * serial line. This can be done by setting the fb.lockless_register_fb=1 kernel + * cmdline option. + * + * The other option is to just disable fbdev emulation since very likely the + * first modest from userspace will crash in the same way, and is even easier to + * debug. This can be done by setting the drm_kms_helper.fbdev_emulation=0 + * kernel cmdline option. + * * RETURNS: * Zero if everything went ok, nonzero otherwise. */ -- cgit v1.2.3 From bcb877e4dcf21c3ba486fd7cc563126f08c39b8a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 22:40:55 +0100 Subject: drm: kerneldoc for drm_fops.c Just prep work before I throw more drm_event refactorings on top. Acked-by: Daniel Stone Reviewed-by: Alex Deucher Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-2-git-send-email-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter --- Documentation/DocBook/gpu.tmpl | 48 +-------------- drivers/gpu/drm/drm_fops.c | 129 ++++++++++++++++++++++++++++++++++------- include/drm/drmP.h | 17 +++--- 3 files changed, 117 insertions(+), 77 deletions(-) (limited to 'drivers') diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl index a8669330b456..12731c296ff1 100644 --- a/Documentation/DocBook/gpu.tmpl +++ b/Documentation/DocBook/gpu.tmpl @@ -2886,52 +2886,8 @@ void (*postclose) (struct drm_device *, struct drm_file *); File Operations - const struct file_operations *fops - File operations for the DRM device node. - - Drivers must define the file operations structure that forms the DRM - userspace API entry point, even though most of those operations are - implemented in the DRM core. The open, - release and ioctl - operations are handled by - - .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - #ifdef CONFIG_COMPAT - .compat_ioctl = drm_compat_ioctl, - #endif - - - - Drivers that implement private ioctls that requires 32/64bit - compatibility support must provide their own - compat_ioctl handler that processes private - ioctls and calls drm_compat_ioctl for core ioctls. - - - The read and poll - operations provide support for reading DRM events and polling them. They - are implemented by - - .poll = drm_poll, - .read = drm_read, - .llseek = no_llseek, - - - - The memory mapping implementation varies depending on how the driver - manages memory. Pre-GEM drivers will use drm_mmap, - while GEM-aware drivers will use drm_gem_mmap. See - . - - .mmap = drm_gem_mmap, - - - - No other file operation is supported by the DRM API. - +!Pdrivers/gpu/drm/drm_fops.c file operations +!Edrivers/gpu/drm/drm_fops.c IOCTLs diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 1ea8790e5090..1551d65db24e 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -1,4 +1,4 @@ -/** +/* * \file drm_fops.c * File operations for DRM * @@ -44,6 +44,46 @@ /* from BKL pushdown */ DEFINE_MUTEX(drm_global_mutex); +/** + * DOC: file operations + * + * Drivers must define the file operations structure that forms the DRM + * userspace API entry point, even though most of those operations are + * implemented in the DRM core. The mandatory functions are drm_open(), + * drm_read(), drm_ioctl() and drm_compat_ioctl if CONFIG_COMPAT is enabled. + * Drivers which implement private ioctls that require 32/64 bit compatibility + * support must provided their onw .compat_ioctl() handler that processes + * private ioctls and calls drm_compat_ioctl() for core ioctls. + * + * In addition drm_read() and drm_poll() provide support for DRM events. DRM + * events are a generic and extensible means to send asynchronous events to + * userspace through the file descriptor. They are used to send vblank event and + * page flip completions by the KMS API. But drivers can also use it for their + * own needs, e.g. to signal completion of rendering. + * + * The memory mapping implementation will vary depending on how the driver + * manages memory. Legacy drivers will use the deprecated drm_legacy_mmap() + * function, modern drivers should use one of the provided memory-manager + * specific implementations. For GEM-based drivers this is drm_gem_mmap(). + * + * No other file operations are supported by the DRM userspace API. Overall the + * following is an example #file_operations structure: + * + * static const example_drm_fops = { + * .owner = THIS_MODULE, + * .open = drm_open, + * .release = drm_release, + * .unlocked_ioctl = drm_ioctl, + * #ifdef CONFIG_COMPAT + * .compat_ioctl = drm_compat_ioctl, + * #endif + * .poll = drm_poll, + * .read = drm_read, + * .llseek = no_llseek, + * .mmap = drm_gem_mmap, + * }; + */ + static int drm_open_helper(struct file *filp, struct drm_minor *minor); static int drm_setup(struct drm_device * dev) @@ -67,15 +107,17 @@ static int drm_setup(struct drm_device * dev) } /** - * Open file. + * drm_open - open method for DRM file + * @inode: device inode + * @filp: file pointer. * - * \param inode device inode - * \param filp file pointer. - * \return zero on success or a negative number on failure. + * This function must be used by drivers as their .open() #file_operations + * method. It looks up the correct DRM device and instantiates all the per-file + * resources for it. + * + * RETURNS: * - * Searches the DRM device with the same minor number, calls open_helper(), and - * increments the device open count. If the open count was previous at zero, - * i.e., it's the first that the device is open, then calls setup(). + * 0 on success or negative errno value on falure. */ int drm_open(struct inode *inode, struct file *filp) { @@ -112,7 +154,7 @@ err_undo: } EXPORT_SYMBOL(drm_open); -/** +/* * Check whether DRI will run on this CPU. * * \return non-zero if the DRI will run on this CPU, or zero otherwise. @@ -125,7 +167,7 @@ static int drm_cpu_valid(void) return 1; } -/** +/* * drm_new_set_master - Allocate a new master object and become master for the * associated master realm. * @@ -179,7 +221,7 @@ out_err: return ret; } -/** +/* * Called whenever a process opens /dev/drm. * * \param filp file pointer. @@ -333,7 +375,7 @@ static void drm_events_release(struct drm_file *file_priv) spin_unlock_irqrestore(&dev->event_lock, flags); } -/** +/* * drm_legacy_dev_reinit * * Reinitializes a legacy/ums drm device in it's lastclose function. @@ -350,7 +392,7 @@ static void drm_legacy_dev_reinit(struct drm_device *dev) dev->if_version = 0; } -/** +/* * Take down the DRM device. * * \param dev DRM device structure. @@ -387,16 +429,17 @@ int drm_lastclose(struct drm_device * dev) } /** - * Release file. + * drm_release - release method for DRM file + * @inode: device inode + * @filp: file pointer. * - * \param inode device inode - * \param file_priv DRM file private. - * \return zero on success or a negative number on failure. + * This function must be used by drivers as their .release() #file_operations + * method. It frees any resources associated with the open file, and if this is + * the last open file for the DRM device also proceeds to call drm_lastclose(). * - * If the hardware lock is held then free it, and take it again for the kernel - * context since it's necessary to reclaim buffers. Unlink the file private - * data from its list and free it. Decreases the open count and if it reaches - * zero calls drm_lastclose(). + * RETURNS: + * + * Always succeeds and returns 0. */ int drm_release(struct inode *inode, struct file *filp) { @@ -451,7 +494,7 @@ int drm_release(struct inode *inode, struct file *filp) if (file_priv->is_master) { struct drm_master *master = file_priv->master; - /** + /* * Since the master is disappearing, so is the * possibility to lock. */ @@ -508,6 +551,32 @@ int drm_release(struct inode *inode, struct file *filp) } EXPORT_SYMBOL(drm_release); +/** + * drm_read - read method for DRM file + * @filp: file pointer + * @buffer: userspace destination pointer for the read + * @count: count in bytes to read + * @offset: offset to read + * + * This function must be used by drivers as their .read() #file_operations + * method iff they use DRM events for asynchronous signalling to userspace. + * Since events are used by the KMS API for vblank and page flip completion this + * means all modern display drivers must use it. + * + * @offset is ignore, DRM events are read like a pipe. Therefore drivers also + * must set the .llseek() #file_operation to no_llseek(). Polling support is + * provided by drm_poll(). + * + * This function will only ever read a full event. Therefore userspace must + * supply a big enough buffer to fit any event to ensure forward progress. Since + * the maximum event space is currently 4K it's recommended to just use that for + * safety. + * + * RETURNS: + * + * Number of bytes read (always aligned to full events, and can be 0) or a + * negative error code on failure. + */ ssize_t drm_read(struct file *filp, char __user *buffer, size_t count, loff_t *offset) { @@ -578,6 +647,22 @@ put_back_event: } EXPORT_SYMBOL(drm_read); +/** + * drm_poll - poll method for DRM file + * @filp: file pointer + * @wait: poll waiter table + * + * This function must be used by drivers as their .read() #file_operations + * method iff they use DRM events for asynchronous signalling to userspace. + * Since events are used by the KMS API for vblank and page flip completion this + * means all modern display drivers must use it. + * + * See also drm_read(). + * + * RETURNS: + * + * Mask of POLL flags indicating the current status of the file. + */ unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) { struct drm_file *file_priv = filp->private_data; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index d7162cf1c3e1..a46a34fc67b3 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -919,15 +919,14 @@ extern long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags); - /* Device support (drm_fops.h) */ -extern int drm_open(struct inode *inode, struct file *filp); -extern ssize_t drm_read(struct file *filp, char __user *buffer, - size_t count, loff_t *offset); -extern int drm_release(struct inode *inode, struct file *filp); -extern int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv); - - /* Mapping support (drm_vm.h) */ -extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); +/* File Operations (drm_fops.c) */ +int drm_open(struct inode *inode, struct file *filp); +ssize_t drm_read(struct file *filp, char __user *buffer, + size_t count, loff_t *offset); +int drm_release(struct inode *inode, struct file *filp); +int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv); + +unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); /* Misc. IOCTL support (drm_ioctl.c) */ int drm_noop(struct drm_device *dev, void *data, -- cgit v1.2.3 From 2dd500f1870e3d852488c9b30c4ecec91c6e2eea Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 22:40:56 +0100 Subject: drm: Add functions to setup/tear down drm_events. An attempt at not spreading out the file_priv->event_space stuff out quite so far and wide. And I think fixes something in ipp_get_event() that is broken (or if they are doing something more weird/subtle, then breaks it in a fun way). Based upon a patch from Rob Clark, rebased and polished. v2: Spelling fixes (Alex). Cc: Alex Deucher Acked-by: Daniel Stone Reviewed-by: Alex Deucher Cc: Rob Clark Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-3-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Laurent Pinchart Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic.c | 44 ++++++++--------------------- drivers/gpu/drm/drm_crtc.c | 36 +++++++----------------- drivers/gpu/drm/drm_fops.c | 67 ++++++++++++++++++++++++++++++++++++++++++++ include/drm/drmP.h | 7 ++++- 4 files changed, 94 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 3f74193885f1..8fb469c4e4b8 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1347,44 +1347,23 @@ static struct drm_pending_vblank_event *create_vblank_event( struct drm_device *dev, struct drm_file *file_priv, uint64_t user_data) { struct drm_pending_vblank_event *e = NULL; - unsigned long flags; - - spin_lock_irqsave(&dev->event_lock, flags); - if (file_priv->event_space < sizeof e->event) { - spin_unlock_irqrestore(&dev->event_lock, flags); - goto out; - } - file_priv->event_space -= sizeof e->event; - spin_unlock_irqrestore(&dev->event_lock, flags); + int ret; e = kzalloc(sizeof *e, GFP_KERNEL); - if (e == NULL) { - spin_lock_irqsave(&dev->event_lock, flags); - file_priv->event_space += sizeof e->event; - spin_unlock_irqrestore(&dev->event_lock, flags); - goto out; - } + if (!e) + return NULL; e->event.base.type = DRM_EVENT_FLIP_COMPLETE; - e->event.base.length = sizeof e->event; + e->event.base.length = sizeof(e->event); e->event.user_data = user_data; - e->base.event = &e->event.base; - e->base.file_priv = file_priv; - e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; - -out: - return e; -} -static void destroy_vblank_event(struct drm_device *dev, - struct drm_file *file_priv, struct drm_pending_vblank_event *e) -{ - unsigned long flags; + ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base); + if (ret) { + kfree(e); + return NULL; + } - spin_lock_irqsave(&dev->event_lock, flags); - file_priv->event_space += sizeof e->event; - spin_unlock_irqrestore(&dev->event_lock, flags); - kfree(e); + return e; } static int atomic_set_prop(struct drm_atomic_state *state, @@ -1646,8 +1625,7 @@ out: if (!crtc_state->event) continue; - destroy_vblank_event(dev, file_priv, - crtc_state->event); + drm_event_cancel_free(dev, &crtc_state->event->base); } } diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index d40bab29747e..6e6514ef9968 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -5265,7 +5265,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, struct drm_crtc *crtc; struct drm_framebuffer *fb = NULL; struct drm_pending_vblank_event *e = NULL; - unsigned long flags; int ret = -EINVAL; if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || @@ -5316,41 +5315,26 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, } if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { - ret = -ENOMEM; - spin_lock_irqsave(&dev->event_lock, flags); - if (file_priv->event_space < sizeof(e->event)) { - spin_unlock_irqrestore(&dev->event_lock, flags); - goto out; - } - file_priv->event_space -= sizeof(e->event); - spin_unlock_irqrestore(&dev->event_lock, flags); - - e = kzalloc(sizeof(*e), GFP_KERNEL); - if (e == NULL) { - spin_lock_irqsave(&dev->event_lock, flags); - file_priv->event_space += sizeof(e->event); - spin_unlock_irqrestore(&dev->event_lock, flags); + e = kzalloc(sizeof *e, GFP_KERNEL); + if (!e) { + ret = -ENOMEM; goto out; } - e->event.base.type = DRM_EVENT_FLIP_COMPLETE; e->event.base.length = sizeof(e->event); e->event.user_data = page_flip->user_data; - e->base.event = &e->event.base; - e->base.file_priv = file_priv; - e->base.destroy = - (void (*) (struct drm_pending_event *)) kfree; + ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base); + if (ret) { + kfree(e); + goto out; + } } crtc->primary->old_fb = crtc->primary->fb; ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags); if (ret) { - if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { - spin_lock_irqsave(&dev->event_lock, flags); - file_priv->event_space += sizeof(e->event); - spin_unlock_irqrestore(&dev->event_lock, flags); - kfree(e); - } + if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) + drm_event_cancel_free(dev, &e->base); /* Keep the old fb, don't unref it. */ crtc->primary->old_fb = NULL; } else { diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 1551d65db24e..f9eacbb2d1dd 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -676,3 +676,70 @@ unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) return mask; } EXPORT_SYMBOL(drm_poll); + +/** + * drm_event_reserve_init - init a DRM event and reserve space for it + * @dev: DRM device + * @file_priv: DRM file private data + * @p: tracking structure for the pending event + * @e: actual event data to deliver to userspace + * + * This function prepares the passed in event for eventual delivery. If the event + * doesn't get delivered (because the IOCTL fails later on, before queuing up + * anything) then the even must be cancelled and freed using + * drm_event_cancel_free(). + * + * If callers embedded @p into a larger structure it must be allocated with + * kmalloc and @p must be the first member element. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ +int drm_event_reserve_init(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_pending_event *p, + struct drm_event *e) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&dev->event_lock, flags); + + if (file_priv->event_space < e->length) { + ret = -ENOMEM; + goto out; + } + + file_priv->event_space -= e->length; + + p->event = e; + p->file_priv = file_priv; + + /* we *could* pass this in as arg, but everyone uses kfree: */ + p->destroy = (void (*) (struct drm_pending_event *)) kfree; + +out: + spin_unlock_irqrestore(&dev->event_lock, flags); + return ret; +} +EXPORT_SYMBOL(drm_event_reserve_init); + +/** + * drm_event_cancel_free - free a DRM event and release it's space + * @dev: DRM device + * @p: tracking structure for the pending event + * + * This function frees the event @p initialized with drm_event_reserve_init() + * and releases any allocated space. + */ +void drm_event_cancel_free(struct drm_device *dev, + struct drm_pending_event *p) +{ + unsigned long flags; + spin_lock_irqsave(&dev->event_lock, flags); + p->file_priv->event_space += p->event->length; + spin_unlock_irqrestore(&dev->event_lock, flags); + p->destroy(p); +} +EXPORT_SYMBOL(drm_event_cancel_free); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index a46a34fc67b3..04a66468e6e0 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -925,8 +925,13 @@ ssize_t drm_read(struct file *filp, char __user *buffer, size_t count, loff_t *offset); int drm_release(struct inode *inode, struct file *filp); int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv); - unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); +int drm_event_reserve_init(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_pending_event *p, + struct drm_event *e); +void drm_event_cancel_free(struct drm_device *dev, + struct drm_pending_event *p); /* Misc. IOCTL support (drm_ioctl.c) */ int drm_noop(struct drm_device *dev, void *data, -- cgit v1.2.3 From 7142a348e7714102ec705cca5fa2e092f29f4834 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 22:40:57 +0100 Subject: drm/exynos: Use the new event init/free functions Also fixes a bug in IPP with not correctly checking/allocating for space in the event space. Not a too serious bug since it's not a real ringbuffer, just a limit to avoid too much kernel allocations. Cc: Rob Clark Cc: Inki Dae Acked-by: Daniel Stone Reviewed-by: Alex Deucher Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-4-git-send-email-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 31 ++++++++----------------------- drivers/gpu/drm/exynos/exynos_drm_ipp.c | 23 +++++++++-------------- 2 files changed, 17 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index c17efdb238a6..82e7f95dfed9 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -1072,7 +1072,6 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, struct drm_exynos_pending_g2d_event *e; struct g2d_cmdlist_node *node; struct g2d_cmdlist *cmdlist; - unsigned long flags; int size; int ret; @@ -1094,21 +1093,8 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, node->event = NULL; if (req->event_type != G2D_EVENT_NOT) { - spin_lock_irqsave(&drm_dev->event_lock, flags); - if (file->event_space < sizeof(e->event)) { - spin_unlock_irqrestore(&drm_dev->event_lock, flags); - ret = -ENOMEM; - goto err; - } - file->event_space -= sizeof(e->event); - spin_unlock_irqrestore(&drm_dev->event_lock, flags); - e = kzalloc(sizeof(*node->event), GFP_KERNEL); if (!e) { - spin_lock_irqsave(&drm_dev->event_lock, flags); - file->event_space += sizeof(e->event); - spin_unlock_irqrestore(&drm_dev->event_lock, flags); - ret = -ENOMEM; goto err; } @@ -1116,9 +1102,12 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, e->event.base.type = DRM_EXYNOS_G2D_EVENT; e->event.base.length = sizeof(e->event); e->event.user_data = req->user_data; - e->base.event = &e->event.base; - e->base.file_priv = file; - e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; + + ret = drm_event_reserve_init(drm_dev, file, &e->base, &e->event.base); + if (ret) { + kfree(e); + goto err; + } node->event = e; } @@ -1219,12 +1208,8 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, err_unmap: g2d_unmap_cmdlist_gem(g2d, node, file); err_free_event: - if (node->event) { - spin_lock_irqsave(&drm_dev->event_lock, flags); - file->event_space += sizeof(e->event); - spin_unlock_irqrestore(&drm_dev->event_lock, flags); - kfree(node->event); - } + if (node->event) + drm_event_cancel_free(drm_dev, &node->event->base); err: g2d_put_cmdlist(g2d, node); return ret; diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index 67d24236e745..c8819c05e2dd 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -618,27 +618,18 @@ static void ipp_clean_mem_nodes(struct drm_device *drm_dev, mutex_unlock(&c_node->mem_lock); } -static void ipp_free_event(struct drm_pending_event *event) -{ - kfree(event); -} - static int ipp_get_event(struct drm_device *drm_dev, struct drm_exynos_ipp_cmd_node *c_node, struct drm_exynos_ipp_queue_buf *qbuf) { struct drm_exynos_ipp_send_event *e; - unsigned long flags; + int ret; DRM_DEBUG_KMS("ops_id[%d]buf_id[%d]\n", qbuf->ops_id, qbuf->buf_id); e = kzalloc(sizeof(*e), GFP_KERNEL); - if (!e) { - spin_lock_irqsave(&drm_dev->event_lock, flags); - c_node->filp->event_space += sizeof(e->event); - spin_unlock_irqrestore(&drm_dev->event_lock, flags); + if (!e) return -ENOMEM; - } /* make event */ e->event.base.type = DRM_EXYNOS_IPP_EVENT; @@ -646,9 +637,13 @@ static int ipp_get_event(struct drm_device *drm_dev, e->event.user_data = qbuf->user_data; e->event.prop_id = qbuf->prop_id; e->event.buf_id[EXYNOS_DRM_OPS_DST] = qbuf->buf_id; - e->base.event = &e->event.base; - e->base.file_priv = c_node->filp; - e->base.destroy = ipp_free_event; + + ret = drm_event_reserve_init(drm_dev, c_node->filp, &e->base, &e->event.base); + if (ret) { + kfree(e); + return ret; + } + mutex_lock(&c_node->event_lock); list_add_tail(&e->base.link, &c_node->event_list); mutex_unlock(&c_node->event_lock); -- cgit v1.2.3 From 6d3729ac1332e3b63b7a140d29fb60ef77d61af6 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 22:40:58 +0100 Subject: drm/vmwgfx: Use the new event init/free functions Cc: Rob Clark Acked-by: Daniel Stone Reviewed-by: Alex Deucher Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-5-git-send-email-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter --- drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index 8e689b439890..eda93bf52a6e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -1025,38 +1025,26 @@ static int vmw_event_fence_action_create(struct drm_file *file_priv, struct vmw_event_fence_pending *event; struct vmw_fence_manager *fman = fman_from_fence(fence); struct drm_device *dev = fman->dev_priv->dev; - unsigned long irq_flags; int ret; - spin_lock_irqsave(&dev->event_lock, irq_flags); - - ret = (file_priv->event_space < sizeof(event->event)) ? -EBUSY : 0; - if (likely(ret == 0)) - file_priv->event_space -= sizeof(event->event); - - spin_unlock_irqrestore(&dev->event_lock, irq_flags); - - if (unlikely(ret != 0)) { - DRM_ERROR("Failed to allocate event space for this file.\n"); - goto out_no_space; - } - - event = kzalloc(sizeof(*event), GFP_KERNEL); if (unlikely(event == NULL)) { DRM_ERROR("Failed to allocate an event.\n"); ret = -ENOMEM; - goto out_no_event; + goto out_no_space; } event->event.base.type = DRM_VMW_EVENT_FENCE_SIGNALED; event->event.base.length = sizeof(*event); event->event.user_data = user_data; - event->base.event = &event->event.base; - event->base.file_priv = file_priv; - event->base.destroy = (void (*) (struct drm_pending_event *)) kfree; + ret = drm_event_reserve_init(dev, file_priv, &event->base, &event->event.base); + if (unlikely(ret != 0)) { + DRM_ERROR("Failed to allocate event space for this file.\n"); + kfree(event); + goto out_no_space; + } if (flags & DRM_VMW_FE_FLAG_REQ_TIME) ret = vmw_event_fence_action_queue(file_priv, fence, @@ -1076,11 +1064,7 @@ static int vmw_event_fence_action_create(struct drm_file *file_priv, return 0; out_no_queue: - event->base.destroy(&event->base); -out_no_event: - spin_lock_irqsave(&dev->event_lock, irq_flags); - file_priv->event_space += sizeof(*event); - spin_unlock_irqrestore(&dev->event_lock, irq_flags); + drm_event_cancel_free(dev, &event->base); out_no_space: return ret; } -- cgit v1.2.3 From a9c9d9aca4e7cf75d09faa098785ed991db41c65 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 6 Jan 2016 23:28:39 +0800 Subject: zorro: Use kobj_to_dev() Use kobj_to_dev() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Geert Uytterhoeven --- drivers/zorro/zorro-sysfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c index 36b210f9b6b2..9282dbf5abdb 100644 --- a/drivers/zorro/zorro-sysfs.c +++ b/drivers/zorro/zorro-sysfs.c @@ -65,8 +65,7 @@ static ssize_t zorro_read_config(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct zorro_dev *z = to_zorro_dev(container_of(kobj, struct device, - kobj)); + struct zorro_dev *z = to_zorro_dev(kobj_to_dev(kobj)); struct ConfigDev cd; /* Construct a ConfigDev */ -- cgit v1.2.3 From 63d8c7b9c32004506516f498fa05881c8d258442 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 25 Jan 2016 13:55:00 +0800 Subject: clk: sunxi: usb: Sort clk providers by chip family and name The latest addition of H3 USB clocks placed them at the bottom. Move it before A80 (sun9i), so they are sorted by SoC family then name. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-usb.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-usb.c b/drivers/clk/sunxi/clk-usb.c index 67b8e38f4ee9..5432b1c198a4 100644 --- a/drivers/clk/sunxi/clk-usb.c +++ b/drivers/clk/sunxi/clk-usb.c @@ -216,6 +216,18 @@ static void __init sun8i_a23_usb_setup(struct device_node *node) } CLK_OF_DECLARE(sun8i_a23_usb, "allwinner,sun8i-a23-usb-clk", sun8i_a23_usb_setup); +static const struct usb_clk_data sun8i_h3_usb_clk_data __initconst = { + .clk_mask = BIT(19) | BIT(18) | BIT(17) | BIT(16) | + BIT(11) | BIT(10) | BIT(9) | BIT(8), + .reset_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0), +}; + +static void __init sun8i_h3_usb_setup(struct device_node *node) +{ + sunxi_usb_clk_setup(node, &sun8i_h3_usb_clk_data, &sun4i_a10_usb_lock); +} +CLK_OF_DECLARE(sun8i_h3_usb, "allwinner,sun8i-h3-usb-clk", sun8i_h3_usb_setup); + static const struct usb_clk_data sun9i_a80_usb_mod_data __initconst = { .clk_mask = BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1), .reset_mask = BIT(19) | BIT(18) | BIT(17), @@ -243,15 +255,3 @@ static void __init sun9i_a80_usb_phy_setup(struct device_node *node) sunxi_usb_clk_setup(node, &sun9i_a80_usb_phy_data, &a80_usb_phy_lock); } CLK_OF_DECLARE(sun9i_a80_usb_phy, "allwinner,sun9i-a80-usb-phy-clk", sun9i_a80_usb_phy_setup); - -static const struct usb_clk_data sun8i_h3_usb_clk_data __initconst = { - .clk_mask = BIT(19) | BIT(18) | BIT(17) | BIT(16) | - BIT(11) | BIT(10) | BIT(9) | BIT(8), - .reset_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0), -}; - -static void __init sun8i_h3_usb_setup(struct device_node *node) -{ - sunxi_usb_clk_setup(node, &sun8i_h3_usb_clk_data, &sun4i_a10_usb_lock); -} -CLK_OF_DECLARE(sun8i_h3_usb, "allwinner,sun8i-h3-usb-clk", sun8i_h3_usb_setup); -- cgit v1.2.3 From 5017e1b15d4ca8dcc170dc6914f6b2d8cd492bdf Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 19 Jan 2016 11:45:12 -0200 Subject: [media] v4l: vsp1: Fix wrong entities links creation The Media Control framework now requires entities to be registered with the media device before creating links so commit c7621b3044f7 ("[media] v4l: vsp1: separate links creation from entities init") separated link creation from entities init. But unfortunately that patch introduced a regression since wrong links were created causing a boot failure on Renesas boards. This patch fixes the boot issue and also the media graph was compared by Geert Uytterhoeven to make sure that the driver changes required by the Media Control framework next generation did not affect the graph. Reported-by: Geert Uytterhoeven Signed-off-by: Javier Martinez Canillas Tested-by: Geert Uytterhoeven Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_drv.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 42dff9d020af..533bc796391e 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -256,7 +256,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) /* Create links. */ list_for_each_entry(entity, &vsp1->entities, list_dev) { - if (entity->type == VSP1_ENTITY_LIF) { + if (entity->type == VSP1_ENTITY_WPF) { ret = vsp1_wpf_create_links(vsp1, entity); if (ret < 0) goto done; @@ -264,7 +264,10 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) ret = vsp1_rpf_create_links(vsp1, entity); if (ret < 0) goto done; - } else { + } + + if (entity->type != VSP1_ENTITY_LIF && + entity->type != VSP1_ENTITY_RPF) { ret = vsp1_create_links(vsp1, entity); if (ret < 0) goto done; -- cgit v1.2.3 From 333a6515344f5dc4ed0772b8fe252a2246f2e099 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Jan 2016 07:29:13 -0200 Subject: Revert "[media] Postpone the addition of MEDIA_IOC_G_TOPOLOGY" Enable MEDIA_IOC_G_TOPOLOGY ioctl for Kernel 4.6. This reverts commit be0270ec89e6b9b49de7e533dd1f3a89ad34d205. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/media-ioc-g-topology.xml | 3 --- drivers/media/media-device.c | 7 +------ include/uapi/linux/media.h | 6 +----- 3 files changed, 2 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml b/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml index 63152ab9efba..e0d49fa329f0 100644 --- a/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml +++ b/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml @@ -48,9 +48,6 @@ Description - - NOTE: This new ioctl is programmed to be added on Kernel 4.6. Its definition/arguments may change until its final version. - The typical usage of this ioctl is to call it twice. On the first call, the structure defined at &media-v2-topology; should be zeroed. At return, if no errors happen, this ioctl will return the diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 7dae0ac0f3ae..4d1c13de494b 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -234,7 +234,6 @@ static long media_device_setup_link(struct media_device *mdev, return ret; } -#if 0 /* Let's postpone it to Kernel 4.6 */ static long __media_device_get_topology(struct media_device *mdev, struct media_v2_topology *topo) { @@ -390,7 +389,6 @@ static long media_device_get_topology(struct media_device *mdev, return 0; } -#endif static long media_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) @@ -424,14 +422,13 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd, mutex_unlock(&dev->graph_mutex); break; -#if 0 /* Let's postpone it to Kernel 4.6 */ case MEDIA_IOC_G_TOPOLOGY: mutex_lock(&dev->graph_mutex); ret = media_device_get_topology(dev, (struct media_v2_topology __user *)arg); mutex_unlock(&dev->graph_mutex); break; -#endif + default: ret = -ENOIOCTLCMD; } @@ -480,9 +477,7 @@ static long media_device_compat_ioctl(struct file *filp, unsigned int cmd, case MEDIA_IOC_DEVICE_INFO: case MEDIA_IOC_ENUM_ENTITIES: case MEDIA_IOC_SETUP_LINK: -#if 0 /* Let's postpone it to Kernel 4.6 */ case MEDIA_IOC_G_TOPOLOGY: -#endif return media_device_ioctl(filp, cmd, arg); case MEDIA_IOC_ENUM_LINKS32: diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 1e3c8cb43bd7..5dbb208e5451 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -286,7 +286,7 @@ struct media_links_enum { * later, before the adding this API upstream. */ -#if 0 /* Let's postpone it to Kernel 4.6 */ + struct media_v2_entity { __u32 id; char name[64]; /* FIXME: move to a property? (RFC says so) */ @@ -351,7 +351,6 @@ static inline void __user *media_get_uptr(__u64 arg) { return (void __user *)(uintptr_t)arg; } -#endif /* ioctls */ @@ -359,9 +358,6 @@ static inline void __user *media_get_uptr(__u64 arg) #define MEDIA_IOC_ENUM_ENTITIES _IOWR('|', 0x01, struct media_entity_desc) #define MEDIA_IOC_ENUM_LINKS _IOWR('|', 0x02, struct media_links_enum) #define MEDIA_IOC_SETUP_LINK _IOWR('|', 0x03, struct media_link_desc) - -#if 0 /* Let's postpone it to Kernel 4.6 */ #define MEDIA_IOC_G_TOPOLOGY _IOWR('|', 0x04, struct media_v2_topology) -#endif #endif /* __LINUX_MEDIA_H */ -- cgit v1.2.3 From b7c9b91db202452ed91b0620b80a516093f71715 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Fri, 22 Jan 2016 19:02:29 +0900 Subject: clk: shmobile: r8a7795: Add USB3.0 clocks Signed-off-by: Yoshihiro Shimoda Signed-off-by: Geert Uytterhoeven --- drivers/clk/shmobile/r8a7795-cpg-mssr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/shmobile/r8a7795-cpg-mssr.c b/drivers/clk/shmobile/r8a7795-cpg-mssr.c index 13e994772dfd..fc260b3306aa 100644 --- a/drivers/clk/shmobile/r8a7795-cpg-mssr.c +++ b/drivers/clk/shmobile/r8a7795-cpg-mssr.c @@ -122,6 +122,8 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { DEF_MOD("scif2", 310, R8A7795_CLK_S3D4), DEF_MOD("pcie1", 318, R8A7795_CLK_S3D1), DEF_MOD("pcie0", 319, R8A7795_CLK_S3D1), + DEF_MOD("usb3-if1", 327, R8A7795_CLK_S3D1), + DEF_MOD("usb3-if0", 328, R8A7795_CLK_S3D1), DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1), DEF_MOD("audmac0", 502, R8A7795_CLK_S3D4), DEF_MOD("audmac1", 501, R8A7795_CLK_S3D4), -- cgit v1.2.3 From f487c54ddd544e1c9172cd510954f697b77b76e3 Mon Sep 17 00:00:00 2001 From: Peter Dedecker Date: Fri, 8 Jan 2016 12:34:41 +0100 Subject: USB: cp210x: add ID for IAI USB to RS485 adaptor Added the USB serial console device ID for IAI Corp. RCB-CV-USB USB to RS485 adaptor. Signed-off-by: Peter Dedecker Cc: stable Signed-off-by: Johan Hovold --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 9b90ad747d87..987813b8a7f9 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -99,6 +99,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */ { USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ + { USB_DEVICE(0x10C4, 0x81D7) }, /* IAI Corp. RCB-CV-USB USB to RS485 Adaptor */ { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ { USB_DEVICE(0x10C4, 0x81E8) }, /* Zephyr Bioharness */ -- cgit v1.2.3 From d056c9b81918675c6dedbfae042c2329effad786 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 8 Dec 2015 18:49:53 +0100 Subject: reset: remove unnecessary local variable initialization from of_reset_control_get_by_index There is no need to initialize rstc, as it is unconditionally assigned the return value of a kzalloc call before use. Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 87376638948d..4a63b379361c 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -152,7 +152,7 @@ EXPORT_SYMBOL_GPL(reset_control_status); struct reset_control *of_reset_control_get_by_index(struct device_node *node, int index) { - struct reset_control *rstc = ERR_PTR(-EPROBE_DEFER); + struct reset_control *rstc; struct reset_controller_dev *r, *rcdev; struct of_phandle_args args; int rstc_id; -- cgit v1.2.3 From e677774f502635c70cb3180fc51ec7ff8c4b27ea Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 14 Jan 2016 16:24:44 +0100 Subject: reset: Move DT cell size check to the core The core currently doesn't check that the DT cell size matches what the driver declares, which means that every xlate function needs to duplicate that check. Make sure that of_reset_control_get checks for this to avoid duplication and errors. Signed-off-by: Maxime Ripard Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 4a63b379361c..f15f150b79da 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -45,9 +45,6 @@ struct reset_control { static int of_reset_simple_xlate(struct reset_controller_dev *rcdev, const struct of_phandle_args *reset_spec) { - if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells)) - return -EINVAL; - if (reset_spec->args[0] >= rcdev->nr_resets) return -EINVAL; @@ -178,6 +175,11 @@ struct reset_control *of_reset_control_get_by_index(struct device_node *node, return ERR_PTR(-EPROBE_DEFER); } + if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) { + mutex_unlock(&reset_controller_list_mutex); + return ERR_PTR(-EINVAL); + } + rstc_id = rcdev->of_xlate(rcdev, &args); if (rstc_id < 0) { mutex_unlock(&reset_controller_list_mutex); -- cgit v1.2.3 From c41ef91f65ea6151969dde699b206794772d407b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 24 Jan 2016 01:19:57 +0900 Subject: reset: hisilicon: check return value of reset_controller_register() The newly added hisilicon reset driver missed the subsystem-wide fixup by commit d1f15aa09558 ("reset: check return value of reset_controller_register()"). So fix it now. Signed-off-by: Masahiro Yamada Signed-off-by: Philipp Zabel --- drivers/reset/hisilicon/hi6220_reset.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/reset/hisilicon/hi6220_reset.c b/drivers/reset/hisilicon/hi6220_reset.c index 7787a9b1cc67..744b2e796442 100644 --- a/drivers/reset/hisilicon/hi6220_reset.c +++ b/drivers/reset/hisilicon/hi6220_reset.c @@ -83,9 +83,7 @@ static int hi6220_reset_probe(struct platform_device *pdev) data->rc_dev.ops = &hi6220_reset_ops; data->rc_dev.of_node = pdev->dev.of_node; - reset_controller_register(&data->rc_dev); - - return 0; + return reset_controller_register(&data->rc_dev); } static const struct of_device_id hi6220_reset_match[] = { -- cgit v1.2.3 From d566ebc3c06c17b108b5b844f9d08259e3b7ba84 Mon Sep 17 00:00:00 2001 From: zhangqing Date: Mon, 25 Jan 2016 08:56:00 -0800 Subject: clk: rockchip: rk3368: fix edp_24m parent The edp_24m parent select bit define is: 1'b0:xin24m 1'b1:1'b0(dummy) so adapt the parent sel bit to the currect one. Signed-off-by: zhangqing Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3368.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index 7016ed24bbe5..dab759b2d18c 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -121,7 +121,7 @@ PNAME(mux_i2s_2ch_p) = { "i2s_2ch_src", "i2s_2ch_frac", "dummy", "xin12m" }; PNAME(mux_spdif_8ch_p) = { "spdif_8ch_pre", "spdif_8ch_frac", "ext_i2s", "xin12m" }; -PNAME(mux_edp_24m_p) = { "dummy", "xin24m" }; +PNAME(mux_edp_24m_p) = { "xin24m", "dummy" }; PNAME(mux_vip_out_p) = { "vip_src", "xin24m" }; PNAME(mux_usbphy480m_p) = { "usbotg_out", "xin24m" }; PNAME(mux_hsic_usbphy480m_p) = { "usbotg_out", "dummy" }; -- cgit v1.2.3 From 0bbe62eb92755ff7c16c859e96a3877de56e32c9 Mon Sep 17 00:00:00 2001 From: zhangqing Date: Mon, 25 Jan 2016 08:56:01 -0800 Subject: clk: rockchip: rk3368: enable the CLK_SET_RATE_PARENT flag for spdif_8ch SPDIF_8CH set freq need to select parent and calculate parent freq. so just mark it as the CLK_SET_RATE_PARENT flag. Signed-off-by: zhangqing Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3368.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index dab759b2d18c..caf0b944d813 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -353,7 +353,7 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_src", CLK_SET_RATE_PARENT, RK3368_CLKSEL_CON(32), 0, RK3368_CLKGATE_CON(6), 5, GFLAGS), - COMPOSITE_NODIV(SCLK_SPDIF_8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0, + COMPOSITE_NODIV(SCLK_SPDIF_8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, CLK_SET_RATE_PARENT, RK3368_CLKSEL_CON(31), 8, 2, MFLAGS, RK3368_CLKGATE_CON(6), 6, GFLAGS), COMPOSITE(0, "i2s_2ch_src", mux_pll_src_cpll_gpll_p, 0, -- cgit v1.2.3 From e8099067de751106d82333e29ce5b6a76ba653f6 Mon Sep 17 00:00:00 2001 From: zhangqing Date: Mon, 25 Jan 2016 08:56:02 -0800 Subject: clk: rockchip: rk3368: enable the CLK_SET_RATE_PARENT flag for i2s_2ch I2S_2CH set freq need to select parent and calculate parent freq. so just mark it as the CLK_SET_RATE_PARENT flag. Signed-off-by: zhangqing Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3368.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index caf0b944d813..e90abe8bf7c0 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -362,7 +362,7 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { COMPOSITE_FRAC(0, "i2s_2ch_frac", "i2s_2ch_src", CLK_SET_RATE_PARENT, RK3368_CLKSEL_CON(54), 0, RK3368_CLKGATE_CON(5), 14, GFLAGS), - COMPOSITE_NODIV(SCLK_I2S_2CH, "sclk_i2s_2ch", mux_i2s_2ch_p, 0, + COMPOSITE_NODIV(SCLK_I2S_2CH, "sclk_i2s_2ch", mux_i2s_2ch_p, CLK_SET_RATE_PARENT, RK3368_CLKSEL_CON(53), 8, 2, MFLAGS, RK3368_CLKGATE_CON(5), 15, GFLAGS), -- cgit v1.2.3 From 6f3508f61c814ee852c199988a62bd954c50dfc1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 20 Jan 2016 12:54:51 +0300 Subject: EDAC, amd64_edac: Shift wrapping issue in f1x_get_norm_dct_addr() dct_sel_base_off is declared as a u64 but we're only using the lower 32 bits because of a shift wrapping bug. This can possibly truncate the upper 16 bits of DctSelBaseOffset[47:26], causing us to misdecode the CS row. Fixes: c8e518d5673d ('amd64_edac: Sanitize f10_get_base_addr_offset') Signed-off-by: Dan Carpenter Cc: Aravind Gopalakrishnan Cc: linux-edac Cc: Link: http://lkml.kernel.org/r/20160120095451.GB19898@mwanda 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 9eee13ef83a5..d87a47547ba5 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1452,7 +1452,7 @@ static u64 f1x_get_norm_dct_addr(struct amd64_pvt *pvt, u8 range, u64 chan_off; u64 dram_base = get_dram_base(pvt, range); u64 hole_off = f10_dhar_offset(pvt); - u64 dct_sel_base_off = (pvt->dct_sel_hi & 0xFFFFFC00) << 16; + u64 dct_sel_base_off = (u64)(pvt->dct_sel_hi & 0xFFFFFC00) << 16; if (hi_rng) { /* -- cgit v1.2.3 From 4d67e3ce75f97148ed127c53d6b0fc854d8b3867 Mon Sep 17 00:00:00 2001 From: Loc Ho Date: Fri, 22 Jan 2016 13:47:04 -0700 Subject: EDAC, xgene: Add missing SoC register bus error handling Add missing register bus error handling for APM X-Gene EDAC SoC and fix a checking condition for CE error promoted to UE. Signed-off-by: Loc Ho Cc: Arnd Bergmann Cc: devicetree@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-edac Cc: Mauro Carvalho Chehab Cc: patches@apm.com Link: http://lkml.kernel.org/r/1453495625-28006-3-git-send-email-lho@apm.com Signed-off-by: Borislav Petkov --- drivers/edac/xgene_edac.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/xgene_edac.c b/drivers/edac/xgene_edac.c index 41f876414a18..bf19b6e3bd12 100644 --- a/drivers/edac/xgene_edac.c +++ b/drivers/edac/xgene_edac.c @@ -61,6 +61,7 @@ struct xgene_edac { struct regmap *mcba_map; struct regmap *mcbb_map; struct regmap *efuse_map; + struct regmap *rb_map; void __iomem *pcp_csr; spinlock_t lock; struct dentry *dfs; @@ -1057,7 +1058,7 @@ static bool xgene_edac_l3_promote_to_uc_err(u32 l3cesr, u32 l3celr) case 0x041: return true; } - } else if (L3C_ELR_ERRSYN(l3celr) == 9) + } else if (L3C_ELR_ERRWAY(l3celr) == 9) return true; return false; @@ -1353,6 +1354,17 @@ static int xgene_edac_l3_remove(struct xgene_edac_dev_ctx *l3) #define GLBL_MDED_ERRH 0x0848 #define GLBL_MDED_ERRHMASK 0x084c +/* IO Bus Registers */ +#define RBCSR 0x0000 +#define STICKYERR_MASK BIT(0) +#define RBEIR 0x0008 +#define AGENT_OFFLINE_ERR_MASK BIT(30) +#define UNIMPL_RBPAGE_ERR_MASK BIT(29) +#define WORD_ALIGNED_ERR_MASK BIT(28) +#define PAGE_ACCESS_ERR_MASK BIT(27) +#define WRITE_ACCESS_MASK BIT(26) +#define RBERRADDR_RD(src) ((src) & 0x03FFFFFF) + static const char * const soc_mem_err_v1[] = { "10GbE0", "10GbE1", @@ -1470,6 +1482,51 @@ static void xgene_edac_rb_report(struct edac_device_ctl_info *edac_dev) u32 err_addr_hi; u32 reg; + /* If the register bus resource isn't available, just skip it */ + if (!ctx->edac->rb_map) + goto rb_skip; + + /* + * Check RB access errors + * 1. Out of range + * 2. Un-implemented page + * 3. Un-aligned access + * 4. Offline slave IP + */ + if (regmap_read(ctx->edac->rb_map, RBCSR, ®)) + return; + if (reg & STICKYERR_MASK) { + bool write; + u32 address; + + dev_err(edac_dev->dev, "IOB bus access error(s)\n"); + if (regmap_read(ctx->edac->rb_map, RBEIR, ®)) + return; + write = reg & WRITE_ACCESS_MASK ? 1 : 0; + address = RBERRADDR_RD(reg); + if (reg & AGENT_OFFLINE_ERR_MASK) + dev_err(edac_dev->dev, + "IOB bus %s access to offline agent error\n", + write ? "write" : "read"); + if (reg & UNIMPL_RBPAGE_ERR_MASK) + dev_err(edac_dev->dev, + "IOB bus %s access to unimplemented page error\n", + write ? "write" : "read"); + if (reg & WORD_ALIGNED_ERR_MASK) + dev_err(edac_dev->dev, + "IOB bus %s word aligned access error\n", + write ? "write" : "read"); + if (reg & PAGE_ACCESS_ERR_MASK) + dev_err(edac_dev->dev, + "IOB bus %s to page out of range access error\n", + write ? "write" : "read"); + if (regmap_write(ctx->edac->rb_map, RBEIR, 0)) + return; + if (regmap_write(ctx->edac->rb_map, RBCSR, 0)) + return; + } +rb_skip: + /* IOB Bridge agent transaction error interrupt */ reg = readl(ctx->dev_csr + IOBBATRANSERRINTSTS); if (!reg) @@ -1852,6 +1909,17 @@ static int xgene_edac_probe(struct platform_device *pdev) goto out_err; } + /* + * NOTE: The register bus resource is optional for compatibility + * reason. + */ + edac->rb_map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "regmap-rb"); + if (IS_ERR(edac->rb_map)) { + dev_warn(edac->dev, "missing syscon regmap rb\n"); + edac->rb_map = NULL; + } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); edac->pcp_csr = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(edac->pcp_csr)) { -- cgit v1.2.3 From 8163ec29c4c2911291d6fb2e9d5b171e17ce4f43 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 16 Sep 2015 20:31:38 -0300 Subject: [media] v4l: omap3isp: Fix module autoloading Platform drivers needs to export the OF id table and this be built into the module or udev will not have the necessary information to autoload the driver module when the device is registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 0bcfa553c1aa..79a0b953bba3 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2599,6 +2599,7 @@ static const struct of_device_id omap3isp_of_table[] = { { .compatible = "ti,omap3-isp" }, { }, }; +MODULE_DEVICE_TABLE(of, omap3isp_of_table); static struct platform_driver omap3isp_driver = { .probe = isp_probe, -- cgit v1.2.3 From 35c5f63773f77a4bfcc3010f6bcc84bdb74c8954 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Thu, 18 Sep 2014 18:57:48 -0300 Subject: [media] v4l: omap3isp: Move starting the sensor from streamon IOCTL handler to VB2 QOP Move the starting of the sensor from the VIDIOC_STREAMON handler to the videobuf2 queue op start_streaming. This avoids failing starting the stream after vb2_streamon() has already finished. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/ispvideo.c | 49 ++++++++++++++++++------------ 1 file changed, 30 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index 994dfc0813f6..bc37467e2fe5 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -434,10 +434,40 @@ static void isp_video_buffer_queue(struct vb2_buffer *buf) } } +static int isp_video_start_streaming(struct vb2_queue *queue, + unsigned int count) +{ + struct isp_video_fh *vfh = vb2_get_drv_priv(queue); + struct isp_video *video = vfh->video; + struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity); + unsigned long flags; + int ret; + + /* In sensor-to-memory mode, the stream can be started synchronously + * to the stream on command. In memory-to-memory mode, it will be + * started when buffers are queued on both the input and output. + */ + if (pipe->input) + return 0; + + ret = omap3isp_pipeline_set_stream(pipe, + ISP_PIPELINE_STREAM_CONTINUOUS); + if (ret < 0) + return ret; + + spin_lock_irqsave(&video->irqlock, flags); + if (list_empty(&video->dmaqueue)) + video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN; + spin_unlock_irqrestore(&video->irqlock, flags); + + return 0; +} + static const struct vb2_ops isp_video_queue_ops = { .queue_setup = isp_video_queue_setup, .buf_prepare = isp_video_buffer_prepare, .buf_queue = isp_video_buffer_queue, + .start_streaming = isp_video_start_streaming, }; /* @@ -1087,29 +1117,10 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) if (ret < 0) goto err_check_format; - /* In sensor-to-memory mode, the stream can be started synchronously - * to the stream on command. In memory-to-memory mode, it will be - * started when buffers are queued on both the input and output. - */ - if (pipe->input == NULL) { - ret = omap3isp_pipeline_set_stream(pipe, - ISP_PIPELINE_STREAM_CONTINUOUS); - if (ret < 0) - goto err_set_stream; - spin_lock_irqsave(&video->irqlock, flags); - if (list_empty(&video->dmaqueue)) - video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN; - spin_unlock_irqrestore(&video->irqlock, flags); - } - mutex_unlock(&video->stream_lock); return 0; -err_set_stream: - mutex_lock(&video->queue_lock); - vb2_streamoff(&vfh->queue, type); - mutex_unlock(&video->queue_lock); err_check_format: media_entity_pipeline_stop(&video->video.entity); err_pipeline_start: -- cgit v1.2.3 From 87e062d4a93f1d78bd765256c826c338f7a0e921 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Thu, 18 Sep 2014 18:57:49 -0300 Subject: [media] v4l: omap3isp: Return buffers back to videobuf2 if pipeline streamon fails When the video buffer queue was stopped before the stream source was started in omap3isp_streamon(), the buffers were not returned back to videobuf2. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/ispvideo.c | 46 +++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index bc37467e2fe5..f82b470c01f9 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -434,6 +434,30 @@ static void isp_video_buffer_queue(struct vb2_buffer *buf) } } +/* + * omap3isp_video_return_buffers - Return all queued buffers to videobuf2 + * @video: ISP video object + * @state: new state for the returned buffers + * + * Return all buffers queued on the video node to videobuf2 in the given state. + * The buffer state should be VB2_BUF_STATE_QUEUED if called due to an error + * when starting the stream, or VB2_BUF_STATE_ERROR otherwise. + * + * The function must be called with the video irqlock held. + */ +static void omap3isp_video_return_buffers(struct isp_video *video, + enum vb2_buffer_state state) +{ + while (!list_empty(&video->dmaqueue)) { + struct isp_buffer *buf; + + buf = list_first_entry(&video->dmaqueue, + struct isp_buffer, irqlist); + list_del(&buf->irqlist); + vb2_buffer_done(&buf->vb.vb2_buf, state); + } +} + static int isp_video_start_streaming(struct vb2_queue *queue, unsigned int count) { @@ -452,8 +476,12 @@ static int isp_video_start_streaming(struct vb2_queue *queue, ret = omap3isp_pipeline_set_stream(pipe, ISP_PIPELINE_STREAM_CONTINUOUS); - if (ret < 0) + if (ret < 0) { + spin_lock_irqsave(&video->irqlock, flags); + omap3isp_video_return_buffers(video, VB2_BUF_STATE_QUEUED); + spin_unlock_irqrestore(&video->irqlock, flags); return ret; + } spin_lock_irqsave(&video->irqlock, flags); if (list_empty(&video->dmaqueue)) @@ -571,26 +599,16 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video) * omap3isp_video_cancel_stream - Cancel stream on a video node * @video: ISP video object * - * Cancelling a stream mark all buffers on the video node as erroneous and makes - * sure no new buffer can be queued. + * Cancelling a stream returns all buffers queued on the video node to videobuf2 + * in the erroneous state and makes sure no new buffer can be queued. */ void omap3isp_video_cancel_stream(struct isp_video *video) { unsigned long flags; spin_lock_irqsave(&video->irqlock, flags); - - while (!list_empty(&video->dmaqueue)) { - struct isp_buffer *buf; - - buf = list_first_entry(&video->dmaqueue, - struct isp_buffer, irqlist); - list_del(&buf->irqlist); - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); - } - + omap3isp_video_return_buffers(video, VB2_BUF_STATE_ERROR); video->error = true; - spin_unlock_irqrestore(&video->irqlock, flags); } -- cgit v1.2.3 From 18ba53f532f2813cb2b278b662c0bb9b7f0295b5 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Wed, 25 Feb 2015 12:58:14 -0300 Subject: [media] v4l: omap3isp: use vb2_buffer_state enum for vb2 buffer state use the vb2_buffer_state enum for assigning the state of the vb2 buffer, along side making isp_pipeline_state state variable local to the block. This fixes the following sparse warning as well: drivers/media/platform/omap3isp/ispvideo.c:497:35: warning: mixing different enum types drivers/media/platform/omap3isp/ispvideo.c:497:35: int enum isp_pipeline_state versus drivers/media/platform/omap3isp/ispvideo.c:497:35: int enum vb2_buffer_state Signed-off-by: Lad, Prabhakar Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/ispvideo.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index f82b470c01f9..2aff755ff77c 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -517,7 +517,7 @@ static const struct vb2_ops isp_video_queue_ops = { struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video) { struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity); - enum isp_pipeline_state state; + enum vb2_buffer_state vb_state; struct isp_buffer *buf; unsigned long flags; @@ -553,17 +553,19 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video) /* Report pipeline errors to userspace on the capture device side. */ if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) { - state = VB2_BUF_STATE_ERROR; + vb_state = VB2_BUF_STATE_ERROR; pipe->error = false; } else { - state = VB2_BUF_STATE_DONE; + vb_state = VB2_BUF_STATE_DONE; } - vb2_buffer_done(&buf->vb.vb2_buf, state); + vb2_buffer_done(&buf->vb.vb2_buf, vb_state); spin_lock_irqsave(&video->irqlock, flags); if (list_empty(&video->dmaqueue)) { + enum isp_pipeline_state state; + spin_unlock_irqrestore(&video->irqlock, flags); if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) -- cgit v1.2.3 From 514580f99af8eae246820fe324a78087972a7d63 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Thu, 24 Sep 2015 11:00:12 -0300 Subject: [media] v4l: omap3isp: Fix handling platform_get_irq result The function can return negative value. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/assign_signed_to_unsigned.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2046107 Signed-off-by: Andrzej Hajda Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 79a0b953bba3..97f6b1824577 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2528,12 +2528,13 @@ static int isp_probe(struct platform_device *pdev) } /* Interrupt */ - isp->irq_num = platform_get_irq(pdev, 0); - if (isp->irq_num <= 0) { + ret = platform_get_irq(pdev, 0); + if (ret <= 0) { dev_err(isp->dev, "No IRQ resource\n"); ret = -ENODEV; goto error_iommu; } + isp->irq_num = ret; if (devm_request_irq(isp->dev, isp->irq_num, isp_isr, IRQF_SHARED, "OMAP3 ISP", isp)) { -- cgit v1.2.3 From 61d5b9d46d2ea4b3ae9534ed6da608a78ce29ac5 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 10 Nov 2015 21:34:18 -0200 Subject: [media] v4l: omap3isp: preview: Mark output buffer done first The sequence number counter is incremented on each output buffer, and that incremented value is used as the sequence number of that buffer. The input buffer sequence numbering is based just on reading the same counter. If the input buffer is marked done first, its sequence number ends up being that of the output buffer - 1. This is how the resizer works as well. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isppreview.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/omap3isp/isppreview.c b/drivers/media/platform/omap3isp/isppreview.c index 84a96670e2e7..ac30a0f83780 100644 --- a/drivers/media/platform/omap3isp/isppreview.c +++ b/drivers/media/platform/omap3isp/isppreview.c @@ -1480,13 +1480,6 @@ static void preview_isr_buffer(struct isp_prev_device *prev) struct isp_buffer *buffer; int restart = 0; - if (prev->input == PREVIEW_INPUT_MEMORY) { - buffer = omap3isp_video_buffer_next(&prev->video_in); - if (buffer != NULL) - preview_set_inaddr(prev, buffer->dma); - pipe->state |= ISP_PIPELINE_IDLE_INPUT; - } - if (prev->output & PREVIEW_OUTPUT_MEMORY) { buffer = omap3isp_video_buffer_next(&prev->video_out); if (buffer != NULL) { @@ -1496,6 +1489,13 @@ static void preview_isr_buffer(struct isp_prev_device *prev) pipe->state |= ISP_PIPELINE_IDLE_OUTPUT; } + if (prev->input == PREVIEW_INPUT_MEMORY) { + buffer = omap3isp_video_buffer_next(&prev->video_in); + if (buffer != NULL) + preview_set_inaddr(prev, buffer->dma); + pipe->state |= ISP_PIPELINE_IDLE_INPUT; + } + switch (prev->state) { case ISP_PIPELINE_STREAM_SINGLESHOT: if (isp_pipeline_ready(pipe)) -- cgit v1.2.3 From 74d1e7c09caed943efce745061f52231bc4c174e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 29 Dec 2015 12:03:19 -0200 Subject: [media] v4l: omap3isp: Fix data lane shift configuration The data-shift DT property speficies the number of bits to be shifted, but the driver still interprets the value as a multiple of two bits as used by now removed platform data support. Fix it. Signed-off-by: Laurent Pinchart Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 2 +- drivers/media/platform/omap3isp/ispccdc.c | 2 +- drivers/media/platform/omap3isp/omap3isp.h | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 97f6b1824577..67efa9ea551e 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -449,7 +449,7 @@ void omap3isp_configure_bridge(struct isp_device *isp, case CCDC_INPUT_PARALLEL: ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL; ispctrl_val |= parcfg->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT; - shift += parcfg->data_lane_shift * 2; + shift += parcfg->data_lane_shift; break; case CCDC_INPUT_CSI2A: diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c index bb3974c98e37..882310eb45cc 100644 --- a/drivers/media/platform/omap3isp/ispccdc.c +++ b/drivers/media/platform/omap3isp/ispccdc.c @@ -2421,7 +2421,7 @@ static int ccdc_link_validate(struct v4l2_subdev *sd, &((struct isp_bus_cfg *) media_entity_to_v4l2_subdev(link->source->entity) ->host_priv)->bus.parallel; - parallel_shift = parcfg->data_lane_shift * 2; + parallel_shift = parcfg->data_lane_shift; } else { parallel_shift = 0; } diff --git a/drivers/media/platform/omap3isp/omap3isp.h b/drivers/media/platform/omap3isp/omap3isp.h index 190e259a6a2d..443e8f7673e2 100644 --- a/drivers/media/platform/omap3isp/omap3isp.h +++ b/drivers/media/platform/omap3isp/omap3isp.h @@ -33,9 +33,9 @@ enum isp_interface_type { * struct isp_parallel_cfg - Parallel interface configuration * @data_lane_shift: Data lane shifter * 0 - CAMEXT[13:0] -> CAM[13:0] - * 1 - CAMEXT[13:2] -> CAM[11:0] - * 2 - CAMEXT[13:4] -> CAM[9:0] - * 3 - CAMEXT[13:6] -> CAM[7:0] + * 2 - CAMEXT[13:2] -> CAM[11:0] + * 4 - CAMEXT[13:4] -> CAM[9:0] + * 6 - CAMEXT[13:6] -> CAM[7:0] * @clk_pol: Pixel clock polarity * 0 - Sample on rising edge, 1 - Sample on falling edge * @hs_pol: Horizontal synchronization polarity @@ -48,7 +48,7 @@ enum isp_interface_type { * 0 - Normal, 1 - One's complement */ struct isp_parallel_cfg { - unsigned int data_lane_shift:2; + unsigned int data_lane_shift:3; unsigned int clk_pol:1; unsigned int hs_pol:1; unsigned int vs_pol:1; -- cgit v1.2.3 From cac9b50b0d75a1d50d6c056ff65c005f3224c8e0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 12 Jan 2016 12:05:20 +0100 Subject: USB: visor: fix null-deref at probe Fix null-pointer dereference at probe should a (malicious) Treo device lack the expected endpoints. Specifically, the Treo port-setup hack was dereferencing the bulk-in and interrupt-in urbs without first making sure they had been allocated by core. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable Signed-off-by: Johan Hovold --- drivers/usb/serial/visor.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 60afb39eb73c..c53fbb3e0b8c 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -544,6 +544,11 @@ static int treo_attach(struct usb_serial *serial) (serial->num_interrupt_in == 0)) return 0; + if (serial->num_bulk_in < 2 || serial->num_interrupt_in < 2) { + dev_err(&serial->interface->dev, "missing endpoints\n"); + return -ENODEV; + } + /* * It appears that Treos and Kyoceras want to use the * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint, -- cgit v1.2.3 From cb3232138e37129e88240a98a1d2aba2187ff57c Mon Sep 17 00:00:00 2001 From: Vladis Dronov Date: Tue, 12 Jan 2016 15:10:50 +0100 Subject: USB: serial: visor: fix crash on detecting device without write_urbs The visor driver crashes in clie_5_attach() when a specially crafted USB device without bulk-out endpoint is detected. This fix adds a check that the device has proper configuration expected by the driver. Reported-by: Ralf Spenneberg Signed-off-by: Vladis Dronov Fixes: cfb8da8f69b8 ("USB: visor: fix initialisation of UX50/TH55 devices") Cc: stable Signed-off-by: Johan Hovold --- drivers/usb/serial/visor.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index c53fbb3e0b8c..337a0be89fcf 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -602,8 +602,10 @@ static int clie_5_attach(struct usb_serial *serial) */ /* some sanity check */ - if (serial->num_ports < 2) - return -1; + if (serial->num_bulk_out < 2) { + dev_err(&serial->interface->dev, "missing bulk out endpoints\n"); + return -ENODEV; + } /* port 0 now uses the modified endpoint Address */ port = serial->port[0]; -- cgit v1.2.3 From ff4e2494dc17b173468e1713fdf6237fd8578bc7 Mon Sep 17 00:00:00 2001 From: Daniele Palmas Date: Tue, 12 Jan 2016 17:22:06 +0100 Subject: USB: serial: option: Adding support for Telit LE922 This patch adds support for two PIDs of LE922. Signed-off-by: Daniele Palmas Cc: stable Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index f2280606b73c..75350fc550a1 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -268,6 +268,8 @@ static void option_instat_callback(struct urb *urb); #define TELIT_PRODUCT_CC864_SINGLE 0x1006 #define TELIT_PRODUCT_DE910_DUAL 0x1010 #define TELIT_PRODUCT_UE910_V2 0x1012 +#define TELIT_PRODUCT_LE922_USBCFG0 0x1042 +#define TELIT_PRODUCT_LE922_USBCFG3 0x1043 #define TELIT_PRODUCT_LE920 0x1200 #define TELIT_PRODUCT_LE910 0x1201 @@ -615,6 +617,16 @@ static const struct option_blacklist_info telit_le920_blacklist = { .reserved = BIT(1) | BIT(5), }; +static const struct option_blacklist_info telit_le922_blacklist_usbcfg0 = { + .sendsetup = BIT(2), + .reserved = BIT(0) | BIT(1) | BIT(3), +}; + +static const struct option_blacklist_info telit_le922_blacklist_usbcfg3 = { + .sendsetup = BIT(0), + .reserved = BIT(1) | BIT(2) | BIT(3), +}; + static const struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -1160,6 +1172,10 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0), + .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG3), + .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910), .driver_info = (kernel_ulong_t)&telit_le910_blacklist }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), -- cgit v1.2.3 From e03cdf22a2727c60307be6a729233edab3bfda9c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 19 Jan 2016 23:43:13 -0800 Subject: USB: serial: ftdi_sio: add support for Yaesu SCU-18 cable Harald Linden reports that the ftdi_sio driver works properly for the Yaesu SCU-18 cable if the device ids are added to the driver. So let's add them. Reported-by: Harald Linden Cc: stable Signed-off-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index a5a0376bbd48..8c660ae401d8 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -824,6 +824,7 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, + { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_SCU18) }, { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) }, /* Papouch devices based on FTDI chip */ diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 67c6d4469730..a84df2513994 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -615,6 +615,7 @@ */ #define RATOC_VENDOR_ID 0x0584 #define RATOC_PRODUCT_ID_USB60F 0xb020 +#define RATOC_PRODUCT_ID_SCU18 0xb03a /* * Infineon Technologies -- cgit v1.2.3 From e920ebc2f85848f7c21b2fe27a6ea9e798c63568 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 4 Jan 2016 10:48:24 -0200 Subject: [media] soc_camera: cleanup control device on async_unbind I got the following WARN on a simple unbind/bind cycle: root@Lager:/sys/bus/i2c/drivers/adv7180# echo 6-0020 > unbind root@Lager:/sys/bus/i2c/drivers/adv7180# echo 6-0020 > bind [ 31.097652] adv7180 6-0020: chip found @ 0x20 (e6520000.i2c) [ 31.123744] ------------[ cut here ]------------ [ 31.128413] WARNING: CPU: 3 PID: 873 at drivers/media/platform/soc_camera/soc_camera.c:1463 soc_camera_async_bound+0x40/0xa0() [ 31.139896] CPU: 3 PID: 873 Comm: sh Not tainted 4.4.0-rc3-00062-ge8ae2c0b6bca2a #172 [ 31.147815] Hardware name: Generic R8A7790 (Flattened Device Tree) [ 31.154056] Backtrace: [ 31.156575] [] (dump_backtrace) from [] (show_stack+0x20/0x24) [ 31.164233] r6:c05c5b33 r5:00000009 r4:00000000 r3:00404100 [ 31.170017] [] (show_stack) from [] (dump_stack+0x78/0x94) [ 31.177344] [] (dump_stack) from [] (warn_slowpath_common+0x98/0xc4) [ 31.185518] r4:00000000 r3:00000000 [ 31.189172] [] (warn_slowpath_common) from [] (warn_slowpath_null+0x2c/0x34) [ 31.198043] r8:eb38df28 r7:eb38c5d0 r6:eb38de80 r5:e6962810 r4:eb38de80 [ 31.204898] [] (warn_slowpath_null) from [] (soc_camera_async_bound+0x40/0xa0) [ 31.213955] [] (soc_camera_async_bound) from [] (v4l2_async_test_notify+0x9c/0x108) [ 31.223430] r5:eb38c5ec r4:eb38de80 [ 31.227084] [] (v4l2_async_test_notify) from [] (v4l2_async_register_subdev+0x88/0xd0) [ 31.236822] r7:c07115c8 r6:c071160c r5:eb38c5ec r4:eb38de80 [ 31.242622] [] (v4l2_async_register_subdev) from [] (adv7180_probe+0x2c8/0x3a4) [ 31.251753] r8:00000000 r7:00000001 r6:eb38de80 r5:ea973400 r4:eb38de10 r3:00000000 [ 31.259660] [] (adv7180_probe) from [] (i2c_device_probe+0x1a0/0x1e4) This gets fixed by clearing the control device pointer on async_unbind. Signed-off-by: Wolfram Sang Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/soc_camera.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index cc84c6d6a701..46c7186f7867 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -1493,6 +1493,8 @@ static void soc_camera_async_unbind(struct v4l2_async_notifier *notifier, struct soc_camera_async_client, notifier); struct soc_camera_device *icd = platform_get_drvdata(sasc->pdev); + icd->control = NULL; + if (icd->clk) { v4l2_clk_unregister(icd->clk); icd->clk = NULL; -- cgit v1.2.3 From 9b4b92645c5edf16b9e77c5956e13b040ba5ed0f Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Mon, 30 Nov 2015 07:20:15 -0200 Subject: [media] atmel-isi: fix debug message which only show the first format Correct the debug output message to show correct format. Signed-off-by: Josh Wu Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/atmel-isi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c index c398b285180c..1af779ee3c74 100644 --- a/drivers/media/platform/soc_camera/atmel-isi.c +++ b/drivers/media/platform/soc_camera/atmel-isi.c @@ -795,7 +795,7 @@ static int isi_camera_get_formats(struct soc_camera_device *icd, xlate->host_fmt = &isi_camera_formats[i]; xlate->code = code.code; dev_dbg(icd->parent, "Providing format %s using code %d\n", - isi_camera_formats[0].name, code.code); + xlate->host_fmt->name, xlate->code); } break; default: -- cgit v1.2.3 From 77b04a0428ea83d000634f06eb3b37ee92d9f866 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 22 Jan 2016 12:42:47 +0000 Subject: drm/i915: More use of the cached LRC state Since: commit 82352e908acd36d7244c75a008c9f27a2ced44d5 Author: Tvrtko Ursulin Date: Fri Jan 15 17:12:45 2016 +0000 drm/i915: Cache LRC state page in the context and: commit 0eb973d31d0aadb6bc801fd6d796afecbbfc3d5b Author: Tvrtko Ursulin Date: Fri Jan 15 15:10:28 2016 +0000 drm/i915: Cache ringbuffer GTT VMA We can also remove the ring buffer start updates on every context update since the address will not change for the duration of the LRC pin. For GuC we can remove the update altogether because it only cares about the ring buffer start. Signed-off-by: Tvrtko Ursulin Cc: Alex Dai Cc: Dave Gordon Cc: Chris Wilson Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1453466567-33369-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_guc_submission.c | 27 --------------------------- drivers/gpu/drm/i915/intel_lrc.c | 6 ++++-- 2 files changed, 4 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 51ae5c1f806d..7a7e1e5d807b 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -560,29 +560,6 @@ static int guc_add_workqueue_item(struct i915_guc_client *gc, return 0; } -#define CTX_RING_BUFFER_START 0x08 - -/* Update the ringbuffer pointer in a saved context image */ -static void lr_context_update(struct drm_i915_gem_request *rq) -{ - enum intel_ring_id ring_id = rq->ring->id; - struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring_id].state; - struct drm_i915_gem_object *rb_obj = rq->ringbuf->obj; - struct page *page; - uint32_t *reg_state; - - BUG_ON(!ctx_obj); - WARN_ON(!i915_gem_obj_is_pinned(ctx_obj)); - WARN_ON(!i915_gem_obj_is_pinned(rb_obj)); - - page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN); - reg_state = kmap_atomic(page); - - reg_state[CTX_RING_BUFFER_START+1] = i915_gem_obj_ggtt_offset(rb_obj); - - kunmap_atomic(reg_state); -} - /** * i915_guc_submit() - Submit commands through GuC * @client: the guc client where commands will go through @@ -597,10 +574,6 @@ int i915_guc_submit(struct i915_guc_client *client, enum intel_ring_id ring_id = rq->ring->id; int q_ret, b_ret; - /* Need this because of the deferred pin ctx and ring */ - /* Shall we move this right after ring is pinned? */ - lr_context_update(rq); - q_ret = guc_add_workqueue_item(client, rq); if (q_ret == 0) b_ret = guc_ring_doorbell(client); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 73d4347429df..116c10f56e66 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -393,7 +393,6 @@ static int execlists_update_context(struct drm_i915_gem_request *rq) uint32_t *reg_state = rq->ctx->engine[ring->id].lrc_reg_state; reg_state[CTX_RING_TAIL+1] = rq->tail; - reg_state[CTX_RING_BUFFER_START+1] = rq->ringbuf->vma->node.start; if (ppgtt && !USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) { /* True 32b PPGTT with dynamic page allocation: update PDP @@ -1067,6 +1066,7 @@ static int intel_lr_context_do_pin(struct intel_engine_cs *ring, struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state; struct intel_ringbuffer *ringbuf = ctx->engine[ring->id].ringbuf; struct page *lrc_state_page; + uint32_t *lrc_reg_state; int ret; WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex)); @@ -1088,7 +1088,9 @@ static int intel_lr_context_do_pin(struct intel_engine_cs *ring, ctx->engine[ring->id].lrc_vma = i915_gem_obj_to_ggtt(ctx_obj); intel_lr_context_descriptor_update(ctx, ring); - ctx->engine[ring->id].lrc_reg_state = kmap(lrc_state_page); + lrc_reg_state = kmap(lrc_state_page); + lrc_reg_state[CTX_RING_BUFFER_START+1] = ringbuf->vma->node.start; + ctx->engine[ring->id].lrc_reg_state = lrc_reg_state; ctx_obj->dirty = true; /* Invalidate GuC TLB. */ -- cgit v1.2.3 From 397097b026190309f4eec630db0e2f5ba498542e Mon Sep 17 00:00:00 2001 From: Alex Dai Date: Sat, 23 Jan 2016 11:58:14 -0800 Subject: drm/i915/guc: Decouple GuC engine id from ring id Previously GuC uses ring id as engine id because of same definition. But this is not true since this commit: commit de1add360522c876c25ef2bbbbab1c94bdb509ab Author: Tvrtko Ursulin Date: Fri Jan 15 15:12:50 2016 +0000 drm/i915: Decouple execbuf uAPI from internal implementation Added GuC engine id into GuC interface to decouple it from ring id used by driver. v2: Keep ring name print out in debugfs; using for_each_ring() where possible to keep driver consistent. (Chris W.) Signed-off-by: Alex Dai Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/1453579094-29860-1-git-send-email-yu.dai@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 12 +++++----- drivers/gpu/drm/i915/i915_guc_submission.c | 38 ++++++++++++++---------------- drivers/gpu/drm/i915/intel_guc.h | 6 ++--- drivers/gpu/drm/i915/intel_guc_fwif.h | 17 +++++++++---- drivers/gpu/drm/i915/intel_lrc.c | 5 ++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 6 files changed, 45 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index c5db23511184..cea184459256 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2463,9 +2463,9 @@ static void i915_guc_client_info(struct seq_file *m, for_each_ring(ring, dev_priv, i) { seq_printf(m, "\tSubmissions: %llu %s\n", - client->submissions[i], + client->submissions[ring->guc_id], ring->name); - tot += client->submissions[i]; + tot += client->submissions[ring->guc_id]; } seq_printf(m, "\tTotal: %llu\n", tot); } @@ -2502,10 +2502,10 @@ static int i915_guc_info(struct seq_file *m, void *data) seq_printf(m, "\nGuC submissions:\n"); for_each_ring(ring, dev_priv, i) { - seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x %9d\n", - ring->name, guc.submissions[i], - guc.last_seqno[i], guc.last_seqno[i]); - total += guc.submissions[i]; + seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x\n", + ring->name, guc.submissions[ring->guc_id], + guc.last_seqno[ring->guc_id]); + total += guc.submissions[ring->guc_id]; } seq_printf(m, "\t%s: %llu\n", "Total", total); diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 7a7e1e5d807b..d7543efc8a5e 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -376,6 +376,8 @@ static void guc_init_proc_desc(struct intel_guc *guc, static void guc_init_ctx_desc(struct intel_guc *guc, struct i915_guc_client *client) { + struct drm_i915_private *dev_priv = guc_to_i915(guc); + struct intel_engine_cs *ring; struct intel_context *ctx = client->owner; struct guc_context_desc desc; struct sg_table *sg; @@ -388,10 +390,8 @@ static void guc_init_ctx_desc(struct intel_guc *guc, desc.priority = client->priority; desc.db_id = client->doorbell_id; - for (i = 0; i < I915_NUM_RINGS; i++) { - struct guc_execlist_context *lrc = &desc.lrc[i]; - struct intel_ringbuffer *ringbuf = ctx->engine[i].ringbuf; - struct intel_engine_cs *ring; + for_each_ring(ring, dev_priv, i) { + struct guc_execlist_context *lrc = &desc.lrc[ring->guc_id]; struct drm_i915_gem_object *obj; uint64_t ctx_desc; @@ -406,7 +406,6 @@ static void guc_init_ctx_desc(struct intel_guc *guc, if (!obj) break; /* XXX: continue? */ - ring = ringbuf->ring; ctx_desc = intel_lr_context_descriptor(ctx, ring); lrc->context_desc = (u32)ctx_desc; @@ -414,16 +413,16 @@ static void guc_init_ctx_desc(struct intel_guc *guc, lrc->ring_lcra = i915_gem_obj_ggtt_offset(obj) + LRC_STATE_PN * PAGE_SIZE; lrc->context_id = (client->ctx_index << GUC_ELC_CTXID_OFFSET) | - (ring->id << GUC_ELC_ENGINE_OFFSET); + (ring->guc_id << GUC_ELC_ENGINE_OFFSET); - obj = ringbuf->obj; + obj = ctx->engine[i].ringbuf->obj; lrc->ring_begin = i915_gem_obj_ggtt_offset(obj); lrc->ring_end = lrc->ring_begin + obj->base.size - 1; lrc->ring_next_free_location = lrc->ring_begin; lrc->ring_current_tail_pointer_value = 0; - desc.engines_used |= (1 << ring->id); + desc.engines_used |= (1 << ring->guc_id); } WARN_ON(desc.engines_used == 0); @@ -510,7 +509,6 @@ int i915_guc_wq_check_space(struct i915_guc_client *gc) static int guc_add_workqueue_item(struct i915_guc_client *gc, struct drm_i915_gem_request *rq) { - enum intel_ring_id ring_id = rq->ring->id; struct guc_wq_item *wqi; void *base; u32 tail, wq_len, wq_off, space; @@ -544,7 +542,7 @@ static int guc_add_workqueue_item(struct i915_guc_client *gc, wq_len = sizeof(struct guc_wq_item) / sizeof(u32) - 1; wqi->header = WQ_TYPE_INORDER | (wq_len << WQ_LEN_SHIFT) | - (ring_id << WQ_TARGET_SHIFT) | + (rq->ring->guc_id << WQ_TARGET_SHIFT) | WQ_NO_WCFLUSH_WAIT; /* The GuC wants only the low-order word of the context descriptor */ @@ -571,14 +569,14 @@ int i915_guc_submit(struct i915_guc_client *client, struct drm_i915_gem_request *rq) { struct intel_guc *guc = client->guc; - enum intel_ring_id ring_id = rq->ring->id; + unsigned int engine_id = rq->ring->guc_id; int q_ret, b_ret; q_ret = guc_add_workqueue_item(client, rq); if (q_ret == 0) b_ret = guc_ring_doorbell(client); - client->submissions[ring_id] += 1; + client->submissions[engine_id] += 1; if (q_ret) { client->q_fail += 1; client->retcode = q_ret; @@ -588,8 +586,8 @@ int i915_guc_submit(struct i915_guc_client *client, } else { client->retcode = 0; } - guc->submissions[ring_id] += 1; - guc->last_seqno[ring_id] = rq->seqno; + guc->submissions[engine_id] += 1; + guc->last_seqno[engine_id] = rq->seqno; return q_ret; } @@ -821,7 +819,7 @@ static void init_guc_policies(struct guc_policies *policies) policies->max_num_work_items = POLICY_MAX_NUM_WI; for (p = 0; p < GUC_CTX_PRIORITY_NUM; p++) { - for (i = 0; i < I915_NUM_RINGS; i++) { + for (i = GUC_RENDER_ENGINE; i < GUC_MAX_ENGINES_NUM; i++) { policy = &policies->policy[p][i]; policy->execution_quantum = 1000000; @@ -873,7 +871,7 @@ static void guc_create_ads(struct intel_guc *guc) ads->golden_context_lrca = ring->status_page.gfx_addr; for_each_ring(ring, dev_priv, i) - ads->eng_state_size[i] = intel_lr_context_size(ring); + ads->eng_state_size[ring->guc_id] = intel_lr_context_size(ring); /* GuC scheduling policies */ policies = (void *)ads + sizeof(struct guc_ads); @@ -885,12 +883,12 @@ static void guc_create_ads(struct intel_guc *guc) /* MMIO reg state */ reg_state = (void *)policies + sizeof(struct guc_policies); - for (i = 0; i < I915_NUM_RINGS; i++) { - reg_state->mmio_white_list[i].mmio_start = - dev_priv->ring[i].mmio_base + GUC_MMIO_WHITE_LIST_START; + for_each_ring(ring, dev_priv, i) { + reg_state->mmio_white_list[ring->guc_id].mmio_start = + ring->mmio_base + GUC_MMIO_WHITE_LIST_START; /* Nothing to be saved or restored for now. */ - reg_state->mmio_white_list[i].count = 0; + reg_state->mmio_white_list[ring->guc_id].count = 0; } ads->reg_state_addr = ads->scheduler_policies + diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index 045b1491ff7a..73002e901ff2 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -46,7 +46,7 @@ struct i915_guc_client { uint32_t wq_head; /* GuC submission statistics & status */ - uint64_t submissions[I915_NUM_RINGS]; + uint64_t submissions[GUC_MAX_ENGINES_NUM]; uint32_t q_fail; uint32_t b_fail; int retcode; @@ -106,8 +106,8 @@ struct intel_guc { uint32_t action_fail; /* Total number of failures */ int32_t action_err; /* Last error code */ - uint64_t submissions[I915_NUM_RINGS]; - uint32_t last_seqno[I915_NUM_RINGS]; + uint64_t submissions[GUC_MAX_ENGINES_NUM]; + uint32_t last_seqno[GUC_MAX_ENGINES_NUM]; }; /* intel_guc_loader.c */ diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index 1856a4740b83..2de57ffe5e18 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h @@ -44,6 +44,13 @@ #define GUC_MAX_GPU_CONTEXTS 1024 #define GUC_INVALID_CTX_ID GUC_MAX_GPU_CONTEXTS +#define GUC_RENDER_ENGINE 0 +#define GUC_VIDEO_ENGINE 1 +#define GUC_BLITTER_ENGINE 2 +#define GUC_VIDEOENHANCE_ENGINE 3 +#define GUC_VIDEO_ENGINE2 4 +#define GUC_MAX_ENGINES_NUM (GUC_VIDEO_ENGINE2 + 1) + /* Work queue item header definitions */ #define WQ_STATUS_ACTIVE 1 #define WQ_STATUS_SUSPENDED 2 @@ -285,7 +292,7 @@ struct guc_context_desc { u64 db_trigger_phy; u16 db_id; - struct guc_execlist_context lrc[I915_NUM_RINGS]; + struct guc_execlist_context lrc[GUC_MAX_ENGINES_NUM]; u8 attribute; @@ -344,7 +351,7 @@ struct guc_policy { } __packed; struct guc_policies { - struct guc_policy policy[GUC_CTX_PRIORITY_NUM][I915_NUM_RINGS]; + struct guc_policy policy[GUC_CTX_PRIORITY_NUM][GUC_MAX_ENGINES_NUM]; /* In micro seconds. How much time to allow before DPC processing is * called back via interrupt (to prevent DPC queue drain starving). @@ -388,14 +395,14 @@ struct guc_mmio_regset { struct guc_mmio_reg_state { struct guc_mmio_regset global_reg; - struct guc_mmio_regset engine_reg[I915_NUM_RINGS]; + struct guc_mmio_regset engine_reg[GUC_MAX_ENGINES_NUM]; /* MMIO registers that are set as non privileged */ struct __packed { u32 mmio_start; u32 offsets[GUC_MMIO_WHITE_LIST_MAX]; u32 count; - } mmio_white_list[I915_NUM_RINGS]; + } mmio_white_list[GUC_MAX_ENGINES_NUM]; } __packed; /* GuC Additional Data Struct */ @@ -406,7 +413,7 @@ struct guc_ads { u32 golden_context_lrca; u32 scheduler_policies; u32 reserved0[3]; - u32 eng_state_size[I915_NUM_RINGS]; + u32 eng_state_size[GUC_MAX_ENGINES_NUM]; u32 reserved2[4]; } __packed; diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 116c10f56e66..da97bc5666b5 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -2088,6 +2088,7 @@ static int logical_render_ring_init(struct drm_device *dev) ring->name = "render ring"; ring->id = RCS; ring->exec_id = I915_EXEC_RENDER; + ring->guc_id = GUC_RENDER_ENGINE; ring->mmio_base = RENDER_RING_BASE; logical_ring_default_irqs(ring, GEN8_RCS_IRQ_SHIFT); @@ -2139,6 +2140,7 @@ static int logical_bsd_ring_init(struct drm_device *dev) ring->name = "bsd ring"; ring->id = VCS; ring->exec_id = I915_EXEC_BSD; + ring->guc_id = GUC_VIDEO_ENGINE; ring->mmio_base = GEN6_BSD_RING_BASE; logical_ring_default_irqs(ring, GEN8_VCS1_IRQ_SHIFT); @@ -2155,6 +2157,7 @@ static int logical_bsd2_ring_init(struct drm_device *dev) ring->name = "bsd2 ring"; ring->id = VCS2; ring->exec_id = I915_EXEC_BSD; + ring->guc_id = GUC_VIDEO_ENGINE2; ring->mmio_base = GEN8_BSD2_RING_BASE; logical_ring_default_irqs(ring, GEN8_VCS2_IRQ_SHIFT); @@ -2171,6 +2174,7 @@ static int logical_blt_ring_init(struct drm_device *dev) ring->name = "blitter ring"; ring->id = BCS; ring->exec_id = I915_EXEC_BLT; + ring->guc_id = GUC_BLITTER_ENGINE; ring->mmio_base = BLT_RING_BASE; logical_ring_default_irqs(ring, GEN8_BCS_IRQ_SHIFT); @@ -2187,6 +2191,7 @@ static int logical_vebox_ring_init(struct drm_device *dev) ring->name = "video enhancement ring"; ring->id = VECS; ring->exec_id = I915_EXEC_VEBOX; + ring->guc_id = GUC_VIDEOENHANCE_ENGINE; ring->mmio_base = VEBOX_RING_BASE; logical_ring_default_irqs(ring, GEN8_VECS_IRQ_SHIFT); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index b12f2aabd104..566b0ae10ce0 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -158,6 +158,7 @@ struct intel_engine_cs { #define I915_NUM_RINGS 5 #define _VCS(n) (VCS + (n)) unsigned int exec_id; + unsigned int guc_id; u32 mmio_base; struct drm_device *dev; struct intel_ringbuffer *buffer; -- cgit v1.2.3 From 3c97430d22d58b9c47a9a4573e8ae6976a475e3e Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Tue, 5 Jan 2016 12:49:57 -0200 Subject: [media] sh_mobile_ceu_camera: use soc_camera_from_vb2q Use soc_camera_from_vb2q() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index 90c87f2b4ec0..b9f369c0fb94 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -213,8 +213,7 @@ static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq, unsigned int *count, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { - struct soc_camera_device *icd = container_of(vq, - struct soc_camera_device, vb2_vidq); + struct soc_camera_device *icd = soc_camera_from_vb2q(vq); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; @@ -361,8 +360,7 @@ static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb) static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct soc_camera_device *icd = container_of(vb->vb2_queue, - struct soc_camera_device, vb2_vidq); + struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vbuf); @@ -413,8 +411,7 @@ error: static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct soc_camera_device *icd = container_of(vb->vb2_queue, - struct soc_camera_device, vb2_vidq); + struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vbuf); struct sh_mobile_ceu_dev *pcdev = ici->priv; @@ -444,8 +441,7 @@ static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb) static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct soc_camera_device *icd = container_of(vb->vb2_queue, - struct soc_camera_device, vb2_vidq); + struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; @@ -460,7 +456,7 @@ static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb) static void sh_mobile_ceu_stop_streaming(struct vb2_queue *q) { - struct soc_camera_device *icd = container_of(q, struct soc_camera_device, vb2_vidq); + struct soc_camera_device *icd = soc_camera_from_vb2q(q); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; struct list_head *buf_head, *tmp; -- cgit v1.2.3 From 1dff3338539e96b2710c34693a6484585dfd7a78 Mon Sep 17 00:00:00 2001 From: Yoshihiko Mori Date: Sun, 13 Dec 2015 13:27:16 -0200 Subject: [media] soc_camera: rcar_vin: Add R-Car Gen3 support Add chip identification for R-Car Gen3. Signed-off-by: Yoshihiko Mori Signed-off-by: Yoshihiro Kaneko Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/rcar_vin.txt | 1 + drivers/media/platform/soc_camera/rcar_vin.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt index 9dafe6b06cd2..619193ccf7ff 100644 --- a/Documentation/devicetree/bindings/media/rcar_vin.txt +++ b/Documentation/devicetree/bindings/media/rcar_vin.txt @@ -6,6 +6,7 @@ family of devices. The current blocks are always slaves and suppot one input channel which can be either RGB, YUYV or BT656. - compatible: Must be one of the following + - "renesas,vin-r8a7795" for the R8A7795 device - "renesas,vin-r8a7794" for the R8A7794 device - "renesas,vin-r8a7793" for the R8A7793 device - "renesas,vin-r8a7791" for the R8A7791 device diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c index b7fd695b9ed5..dc75a80794fb 100644 --- a/drivers/media/platform/soc_camera/rcar_vin.c +++ b/drivers/media/platform/soc_camera/rcar_vin.c @@ -143,6 +143,7 @@ #define RCAR_VIN_BT656 (1 << 3) enum chip_id { + RCAR_GEN3, RCAR_GEN2, RCAR_H1, RCAR_M1, @@ -1818,6 +1819,7 @@ static struct soc_camera_host_ops rcar_vin_host_ops = { #ifdef CONFIG_OF static const struct of_device_id rcar_vin_of_table[] = { + { .compatible = "renesas,vin-r8a7795", .data = (void *)RCAR_GEN3 }, { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 }, { .compatible = "renesas,vin-r8a7793", .data = (void *)RCAR_GEN2 }, { .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 }, -- cgit v1.2.3 From 368a53df02d61bb849e100219c2a758510062f88 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 22 Nov 2015 07:12:56 -0200 Subject: [media] soc_camera: constify v4l2_subdev_sensor_ops structures The v4l2_subdev_sensor_ops structures are never modified, so declare them as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/soc_camera/mt9m001.c | 2 +- drivers/media/i2c/soc_camera/mt9t031.c | 2 +- drivers/media/i2c/soc_camera/mt9v022.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c index 2e14e52ba2e0..69becc358659 100644 --- a/drivers/media/i2c/soc_camera/mt9m001.c +++ b/drivers/media/i2c/soc_camera/mt9m001.c @@ -632,7 +632,7 @@ static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { .s_mbus_config = mt9m001_s_mbus_config, }; -static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = { +static const struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = { .g_skip_top_lines = mt9m001_g_skip_top_lines, }; diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c index 3b6eeed2e2b9..5c8e3ffe3b27 100644 --- a/drivers/media/i2c/soc_camera/mt9t031.c +++ b/drivers/media/i2c/soc_camera/mt9t031.c @@ -728,7 +728,7 @@ static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { .s_mbus_config = mt9t031_s_mbus_config, }; -static struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = { +static const struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = { .g_skip_top_lines = mt9t031_g_skip_top_lines, }; diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c index c2ba1fb3694d..2721e583bfa0 100644 --- a/drivers/media/i2c/soc_camera/mt9v022.c +++ b/drivers/media/i2c/soc_camera/mt9v022.c @@ -860,7 +860,7 @@ static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { .s_mbus_config = mt9v022_s_mbus_config, }; -static struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = { +static const struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = { .g_skip_top_lines = mt9v022_g_skip_top_lines, }; -- cgit v1.2.3 From 1b4ca5aa9e0867f5cec40f9508dac7414f3b6998 Mon Sep 17 00:00:00 2001 From: Anders Roxell Date: Thu, 14 Jan 2016 22:09:43 -0200 Subject: [media] drivers/media: vsp1_video: fix compile error This was found with the -RT patch enabled, but the fix should apply to non-RT also. Compilation error without this fix: ../drivers/media/platform/vsp1/vsp1_video.c: In function 'vsp1_pipeline_stopped': ../drivers/media/platform/vsp1/vsp1_video.c:524:2: error: expected expression before 'do' spin_unlock_irqrestore(&pipe->irqlock, flags); ^ Signed-off-by: Anders Roxell Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 637d0d6f79fb..b4dca57d1ae3 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -515,7 +515,7 @@ static bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe) bool stopped; spin_lock_irqsave(&pipe->irqlock, flags); - stopped = pipe->state == VSP1_PIPELINE_STOPPED, + stopped = pipe->state == VSP1_PIPELINE_STOPPED; spin_unlock_irqrestore(&pipe->irqlock, flags); return stopped; -- cgit v1.2.3 From 76a563675485849f6f9ad5b30df220438b3628c1 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 8 Dec 2015 12:15:54 -0200 Subject: [media] exynos4-is: fix a format string bug Ironically, 7d4020c3c400 ("[media] exynos4-is: fix some warnings when compiling on arm64") fixed some format string bugs but introduced a new one. buf_index is a simple int, so it should be printed with %d, not %pad (which is correctly used for dma_addr_t). Fixes: 7d4020c3c400 ("[media] exynos4-is: fix some warnings when compiling on arm64") Signed-off-by: Rasmus Villemoes Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-isp-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c index bf9261eb57a1..c0816728cbfe 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp-video.c +++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c @@ -218,8 +218,8 @@ static void isp_video_capture_buffer_queue(struct vb2_buffer *vb) ivb->dma_addr[i]; isp_dbg(2, &video->ve.vdev, - "dma_buf %pad (%d/%d/%d) addr: %pad\n", - &buf_index, ivb->index, i, vb->index, + "dma_buf %d (%d/%d/%d) addr: %pad\n", + buf_index, ivb->index, i, vb->index, &ivb->dma_addr[i]); } -- cgit v1.2.3 From 028635d6b5b42de0e0fe5f5c92e1b99868e81a29 Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Mon, 4 Jan 2016 19:49:36 +0100 Subject: USB: mxu11x0: fix memory leak on usb_serial private data On nominal execution, private data allocated on port_probe and attach are never freed. Add port_remove and release callbacks to free them respectively. Signed-off-by: Mathieu OTHACEHE Signed-off-by: Johan Hovold --- drivers/usb/serial/mxu11x0.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/mxu11x0.c b/drivers/usb/serial/mxu11x0.c index e3c3f57c2d82..619607323bfd 100644 --- a/drivers/usb/serial/mxu11x0.c +++ b/drivers/usb/serial/mxu11x0.c @@ -368,6 +368,16 @@ static int mxu1_port_probe(struct usb_serial_port *port) return 0; } +static int mxu1_port_remove(struct usb_serial_port *port) +{ + struct mxu1_port *mxport; + + mxport = usb_get_serial_port_data(port); + kfree(mxport); + + return 0; +} + static int mxu1_startup(struct usb_serial *serial) { struct mxu1_device *mxdev; @@ -427,6 +437,14 @@ err_free_mxdev: return err; } +static void mxu1_release(struct usb_serial *serial) +{ + struct mxu1_device *mxdev; + + mxdev = usb_get_serial_data(serial); + kfree(mxdev); +} + static int mxu1_write_byte(struct usb_serial_port *port, u32 addr, u8 mask, u8 byte) { @@ -957,7 +975,9 @@ static struct usb_serial_driver mxu11x0_device = { .id_table = mxu1_idtable, .num_ports = 1, .port_probe = mxu1_port_probe, + .port_remove = mxu1_port_remove, .attach = mxu1_startup, + .release = mxu1_release, .open = mxu1_open, .close = mxu1_close, .ioctl = mxu1_ioctl, -- cgit v1.2.3 From 21e4903246029e221ee92e3be3653f2805fac898 Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Thu, 14 Jan 2016 14:24:30 -0500 Subject: clk: tegra: Fix divider on VI_I2C VI-I2C has 16 bits available for its divider. Switch the divider width to 16 instead of 8 so correct rates can be set. Signed-off-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra-periph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 6ad381a888a6..105405ca85ab 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -782,7 +782,7 @@ static struct tegra_periph_init_data periph_clks[] = { NODIV("sor1", mux_clkm_sor1_brick_sor1_src, CLK_SOURCE_SOR1, 15, MASK(1), 183, 0, tegra_clk_sor1, &sor1_lock), MUX8("sdmmc_legacy", mux_pllp_out3_clkm_pllp_pllc4, CLK_SOURCE_SDMMC_LEGACY, 193, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_sdmmc_legacy), MUX8("qspi", mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_QSPI, 211, TEGRA_PERIPH_ON_APB, tegra_clk_qspi), - MUX("vii2c", mux_pllp_pllc_clkm, CLK_SOURCE_VI_I2C, 208, TEGRA_PERIPH_ON_APB, tegra_clk_vi_i2c), + I2C("vii2c", mux_pllp_pllc_clkm, CLK_SOURCE_VI_I2C, 208, tegra_clk_vi_i2c), MUX("mipibif", mux_pllp_clkm, CLK_SOURCE_MIPIBIF, 173, TEGRA_PERIPH_ON_APB, tegra_clk_mipibif), MUX("uartape", mux_pllp_pllc_clkm, CLK_SOURCE_UARTAPE, 212, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_uartape), MUX8("tsecb", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_TSECB, 206, 0, tegra_clk_tsecb), -- cgit v1.2.3 From 4e63959e3773276cc49b488238bd583c53cf54e8 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Mon, 18 Jan 2016 14:10:25 -0200 Subject: [media] s5k6a3: Fix VIDIOC_SUBDEV_G_FMT ioctl for TRY format VIDIOC_SUBDEV_G_FMT ioctl should return TRY format previously set with VIDIOC_SUBDEV_S_FMT. Currently it is not the case as only ACTIVE formats are saved in the driver. Since the driver doesn't alter hardware state in the set_fmt op anyway, the op can save the format in both TRY and ACTIVE case. Signed-off-by: Jacek Anaszewski Acked-by: Kyungmin Park Cc: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5k6a3.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c index b9e43ffa5085..cbe4711e9b31 100644 --- a/drivers/media/i2c/s5k6a3.c +++ b/drivers/media/i2c/s5k6a3.c @@ -144,8 +144,7 @@ static int s5k6a3_set_fmt(struct v4l2_subdev *sd, mf = __s5k6a3_get_format(sensor, cfg, fmt->pad, fmt->which); if (mf) { mutex_lock(&sensor->lock); - if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) - *mf = fmt->format; + *mf = fmt->format; mutex_unlock(&sensor->lock); } return 0; -- cgit v1.2.3 From 76775776a6e3dbe2dc8a84345dca4540969bc014 Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Mon, 18 Jan 2016 14:10:26 -0200 Subject: [media] exynos4-is: Open shouldn't fail when sensor entity is not linked In order to allow for automatic media device entities linking from the level of libv4l plugin the open system call shouldn't fail, as the libv4l plugins can begin their job not until it succeeds. This patch allows for leaving the pipeline not linked on open and postpones verifying it to the moment when streamon callback is called. Signed-off-by: Jacek Anaszewski Acked-by: Kyungmin Park Cc: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/media-dev.c | 95 +++++++++++++++++++++------ 1 file changed, 76 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index f3b2dd30ec77..e79ddbb1e14f 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -185,6 +185,37 @@ error: return ret; } +/** + * __fimc_pipeline_enable - enable power of all pipeline subdevs + * and the sensor clock + * @ep: video pipeline structure + * @fmd: fimc media device + * + * Called with the graph mutex held. + */ +static int __fimc_pipeline_enable(struct exynos_media_pipeline *ep, + struct fimc_md *fmd) +{ + struct fimc_pipeline *p = to_fimc_pipeline(ep); + int ret; + + /* Enable PXLASYNC clock if this pipeline includes FIMC-IS */ + if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP]) { + ret = clk_prepare_enable(fmd->wbclk[CLK_IDX_WB_B]); + if (ret < 0) + return ret; + } + + ret = fimc_pipeline_s_power(p, 1); + if (!ret) + return 0; + + if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP]) + clk_disable_unprepare(fmd->wbclk[CLK_IDX_WB_B]); + + return ret; +} + /** * __fimc_pipeline_open - update the pipeline information, enable power * of all pipeline subdevs and the sensor clock @@ -199,7 +230,6 @@ static int __fimc_pipeline_open(struct exynos_media_pipeline *ep, struct fimc_md *fmd = entity_to_fimc_mdev(me); struct fimc_pipeline *p = to_fimc_pipeline(ep); struct v4l2_subdev *sd; - int ret; if (WARN_ON(p == NULL || me == NULL)) return -EINVAL; @@ -208,24 +238,16 @@ static int __fimc_pipeline_open(struct exynos_media_pipeline *ep, fimc_pipeline_prepare(p, me); sd = p->subdevs[IDX_SENSOR]; - if (sd == NULL) - return -EINVAL; - - /* Disable PXLASYNC clock if this pipeline includes FIMC-IS */ - if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP]) { - ret = clk_prepare_enable(fmd->wbclk[CLK_IDX_WB_B]); - if (ret < 0) - return ret; - } - - ret = fimc_pipeline_s_power(p, 1); - if (!ret) + if (sd == NULL) { + pr_warn("%s(): No sensor subdev\n", __func__); + /* + * Pipeline open cannot fail so as to make it possible + * for the user space to configure the pipeline. + */ return 0; + } - if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP]) - clk_disable_unprepare(fmd->wbclk[CLK_IDX_WB_B]); - - return ret; + return __fimc_pipeline_enable(ep, fmd); } /** @@ -269,10 +291,43 @@ static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on) { IDX_CSIS, IDX_FLITE, IDX_FIMC, IDX_SENSOR, IDX_IS_ISP }, }; struct fimc_pipeline *p = to_fimc_pipeline(ep); + struct fimc_md *fmd = entity_to_fimc_mdev(&p->subdevs[IDX_CSIS]->entity); + enum fimc_subdev_index sd_id; int i, ret = 0; - if (p->subdevs[IDX_SENSOR] == NULL) - return -ENODEV; + if (p->subdevs[IDX_SENSOR] == NULL) { + if (!fmd->user_subdev_api) { + /* + * Sensor must be already discovered if we + * aren't in the user_subdev_api mode + */ + return -ENODEV; + } + + /* Get pipeline sink entity */ + if (p->subdevs[IDX_FIMC]) + sd_id = IDX_FIMC; + else if (p->subdevs[IDX_IS_ISP]) + sd_id = IDX_IS_ISP; + else if (p->subdevs[IDX_FLITE]) + sd_id = IDX_FLITE; + else + return -ENODEV; + + /* + * Sensor could have been linked between open and STREAMON - + * check if this is the case. + */ + fimc_pipeline_prepare(p, &p->subdevs[sd_id]->entity); + + if (p->subdevs[IDX_SENSOR] == NULL) + return -ENODEV; + + ret = __fimc_pipeline_enable(ep, fmd); + if (ret < 0) + return ret; + + } for (i = 0; i < IDX_MAX; i++) { unsigned int idx = seq[on][i]; @@ -282,8 +337,10 @@ static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on) if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) goto error; } + return 0; error: + fimc_pipeline_s_power(p, !on); for (; i >= 0; i--) { unsigned int idx = seq[on][i]; v4l2_subdev_call(p->subdevs[idx], video, s_stream, !on); -- cgit v1.2.3 From a13ddcae4f0bc5e1de761895d0cae2010e1934af Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Mon, 18 Jan 2016 14:10:27 -0200 Subject: [media] exynos4-is: Wait for 100us before opening sensor Some user space use cases result in kernel hangup on the HIC_OPEN_SENSOR command write. In case when a minimalistic application is used for setting up the streaming, the hangups occur only occasionally. In case of GStreamer use cases it is always the case. Signed-off-by: Jacek Anaszewski Acked-by: Kyungmin Park Cc: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-is.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c index 49658ca39e51..979c388ebf60 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.c +++ b/drivers/media/platform/exynos4-is/fimc-is.c @@ -631,6 +631,12 @@ static int fimc_is_hw_open_sensor(struct fimc_is *is, fimc_is_mem_barrier(); + /* + * Some user space use cases hang up here without this + * empirically chosen delay. + */ + udelay(100); + mcuctl_write(HIC_OPEN_SENSOR, is, MCUCTL_REG_ISSR(0)); mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1)); mcuctl_write(sensor->drvdata->id, is, MCUCTL_REG_ISSR(2)); -- cgit v1.2.3 From 420520766a796d36076111139ba1e4fb1aadeadd Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Wed, 30 Dec 2015 11:26:03 -0200 Subject: [media] media: Kconfig: add dependency of HAS_DMA The build of m32r allmodconfig fails with the error: drivers/media/v4l2-core/videobuf2-dma-contig.c:484:2: error: implicit declaration of function 'dma_get_cache_alignment' The build of videobuf2-dma-contig.c depends on HAS_DMA and it is correctly mentioned in the Kconfig but the symbol VIDEO_STI_BDISP also selects VIDEOBUF2_DMA_CONTIG, so it is trying to compile videobuf2-dma-contig.c even though HAS_DMA is not defined. Signed-off-by: Sudip Mukherjee Acked-by: Sakari Ailus Acked-by: Geert Uytterhoeven Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 526359447ff9..8b89ebe16d94 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -215,6 +215,7 @@ config VIDEO_SAMSUNG_EXYNOS_GSC config VIDEO_STI_BDISP tristate "STMicroelectronics BDISP 2D blitter driver" depends on VIDEO_DEV && VIDEO_V4L2 + depends on HAS_DMA depends on ARCH_STI || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG select V4L2_MEM2MEM_DEV -- cgit v1.2.3 From 4152b387da81617c80cb2946b2d56e3958906b3e Mon Sep 17 00:00:00 2001 From: John Ernberg Date: Mon, 25 Jan 2016 12:27:17 +0000 Subject: USB: option: fix Cinterion AHxx enumeration In certain kernel configurations where the cdc_ether and option drivers are compiled as modules there can occur a race condition in enumeration. This causes the option driver to enumerate the ethernet(wwan) interface as usb-serial interfaces. usb-devices output for the modem: T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 5 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=1e2d ProdID=0055 Rev=00.00 S: Manufacturer=Cinterion S: Product=AHx C: #Ifs= 6 Cfg#= 1 Atr=e0 MxPwr=10mA I: If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option I: If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=option I: If#= 4 Alt= 0 #EPs= 1 Cls=02(commc) Sub=06 Prot=00 Driver=cdc_ether I: If#= 5 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=cdc_ether Signed-off-by: John Ernberg Fixes: 1941138e1c02 ("USB: added support for Cinterion's products...") Cc: stable # v3.9: 8ff10bdb14a52 Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 75350fc550a1..db86e512e0fc 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1695,7 +1695,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, - { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) }, + { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX, 0xff) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, -- cgit v1.2.3 From 7d3ccfe697bceec9fdf7b901da4073cc55fa56de Mon Sep 17 00:00:00 2001 From: Joseph Marrero Date: Wed, 25 Nov 2015 20:38:43 -0200 Subject: [media] davinci_vpfe: make checkpatch happy This WARNING was found using the checkpatch tool: Block comments use * on the subsequent lines Signed-off-by: Joseph Marrero Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h b/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h index 7b7e7b26c1e8..3cc9be776f8b 100644 --- a/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h +++ b/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h @@ -538,7 +538,7 @@ struct vpfe_isif_raw_config { }; /********************************************************************** - IPIPE API Structures +* IPIPE API Structures **********************************************************************/ /* IPIPE module configurations */ -- cgit v1.2.3 From 7871597a73b7b8daa7beeba3c36d68f9047d38c2 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 7 Jan 2016 10:46:41 -0200 Subject: [media] tvp5150: Restructure version detection Move the version detection code to a separate function and restructure it to prepare for TVP5151 support. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 79 ++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 6c3769d44b75..f80928156ad7 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1105,13 +1105,53 @@ static const struct v4l2_subdev_ops tvp5150_ops = { I2C Client & Driver ****************************************************************************/ +static int tvp5150_detect_version(struct tvp5150 *core) +{ + struct v4l2_subdev *sd = &core->sd; + struct i2c_client *c = v4l2_get_subdevdata(sd); + unsigned int i; + u16 dev_id; + u16 rom_ver; + u8 regs[4]; + int res; + + /* + * Read consequent registers - TVP5150_MSB_DEV_ID, TVP5150_LSB_DEV_ID, + * TVP5150_ROM_MAJOR_VER, TVP5150_ROM_MINOR_VER + */ + for (i = 0; i < 4; i++) { + res = tvp5150_read(sd, TVP5150_MSB_DEV_ID + i); + if (res < 0) + return res; + regs[i] = res; + } + + dev_id = (regs[0] << 8) | regs[1]; + rom_ver = (regs[2] << 8) | regs[3]; + + v4l2_info(sd, "tvp%04x (%u.%u) chip found @ 0x%02x (%s)\n", + dev_id, regs[2], regs[3], c->addr << 1, c->adapter->name); + + if (dev_id == 0x5150 && rom_ver == 0x0321) { /* TVP51510A */ + v4l2_info(sd, "tvp5150a detected.\n"); + } else if (dev_id == 0x5150 && rom_ver == 0x0400) { /* TVP5150AM1 */ + v4l2_info(sd, "tvp5150am1 detected.\n"); + + /* ITU-T BT.656.4 timing */ + tvp5150_write(sd, TVP5150_REV_SELECT, 0); + } else { + v4l2_info(sd, "*** unknown tvp%04x chip detected.\n", dev_id); + } + + return 0; +} + static int tvp5150_probe(struct i2c_client *c, const struct i2c_device_id *id) { struct tvp5150 *core; struct v4l2_subdev *sd; - int tvp5150_id[4]; - int i, res; + int res; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(c->adapter, @@ -1124,38 +1164,9 @@ static int tvp5150_probe(struct i2c_client *c, sd = &core->sd; v4l2_i2c_subdev_init(sd, c, &tvp5150_ops); - /* - * Read consequent registers - TVP5150_MSB_DEV_ID, TVP5150_LSB_DEV_ID, - * TVP5150_ROM_MAJOR_VER, TVP5150_ROM_MINOR_VER - */ - for (i = 0; i < 4; i++) { - res = tvp5150_read(sd, TVP5150_MSB_DEV_ID + i); - if (res < 0) - return res; - tvp5150_id[i] = res; - } - - v4l_info(c, "chip found @ 0x%02x (%s)\n", - c->addr << 1, c->adapter->name); - - if (tvp5150_id[2] == 4 && tvp5150_id[3] == 0) { /* Is TVP5150AM1 */ - v4l2_info(sd, "tvp%02x%02xam1 detected.\n", - tvp5150_id[0], tvp5150_id[1]); - - /* ITU-T BT.656.4 timing */ - tvp5150_write(sd, TVP5150_REV_SELECT, 0); - } else { - /* Is TVP5150A */ - if (tvp5150_id[2] == 3 || tvp5150_id[3] == 0x21) { - v4l2_info(sd, "tvp%02x%02xa detected.\n", - tvp5150_id[0], tvp5150_id[1]); - } else { - v4l2_info(sd, "*** unknown tvp%02x%02x chip detected.\n", - tvp5150_id[0], tvp5150_id[1]); - v4l2_info(sd, "*** Rom ver is %d.%d\n", - tvp5150_id[2], tvp5150_id[3]); - } - } + res = tvp5150_detect_version(core); + if (res < 0) + return res; core->norm = V4L2_STD_ALL; /* Default is autodetect */ core->input = TVP5150_COMPOSITE1; -- cgit v1.2.3 From 05676b3e33fe2fd693f2c0ff3d058db6ca5e7ed6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 7 Jan 2016 10:46:42 -0200 Subject: [media] tvp5150: Add tvp5151 support Expand the version detection code to identity the tvp5151. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index f80928156ad7..2816ceb4874a 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1139,6 +1139,8 @@ static int tvp5150_detect_version(struct tvp5150 *core) /* ITU-T BT.656.4 timing */ tvp5150_write(sd, TVP5150_REV_SELECT, 0); + } else if (dev_id == 0x5151 && rom_ver == 0x0100) { /* TVP5151 */ + v4l2_info(sd, "tvp5151 detected.\n"); } else { v4l2_info(sd, "*** unknown tvp%04x chip detected.\n", dev_id); } -- cgit v1.2.3 From b1950b8db9896cca59f61b6b7c6d3a14dc782b80 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 7 Jan 2016 10:46:44 -0200 Subject: [media] tvp5150: Add pixel rate control support This patch adds support for the V4L2_CID_PIXEL_RATE control. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 2816ceb4874a..555718ebbf0e 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1174,7 +1174,7 @@ static int tvp5150_probe(struct i2c_client *c, core->input = TVP5150_COMPOSITE1; core->enable = 1; - v4l2_ctrl_handler_init(&core->hdl, 4); + v4l2_ctrl_handler_init(&core->hdl, 5); v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops, V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops, @@ -1183,6 +1183,9 @@ static int tvp5150_probe(struct i2c_client *c, V4L2_CID_SATURATION, 0, 255, 1, 128); v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops, V4L2_CID_HUE, -128, 127, 1, 0); + v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops, + V4L2_CID_PIXEL_RATE, 27000000, + 27000000, 1, 27000000); sd->ctrl_handler = &core->hdl; if (core->hdl.error) { res = core->hdl.error; -- cgit v1.2.3 From 460b6c0831cb52ef349156cfa27e889606b4cb75 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 7 Jan 2016 10:46:45 -0200 Subject: [media] tvp5150: Add s_stream subdev operation support This patch adds the .s_stream subdev operation to the driver. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 555718ebbf0e..08383a273e51 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -952,6 +952,21 @@ static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) I2C Command ****************************************************************************/ +static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) +{ + /* Initializes TVP5150 to its default values */ + /* # set PCLK (27MHz) */ + tvp5150_write(sd, TVP5150_CONF_SHARED_PIN, 0x00); + + /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ + if (enable) + tvp5150_write(sd, TVP5150_MISC_CTL, 0x09); + else + tvp5150_write(sd, TVP5150_MISC_CTL, 0x00); + + return 0; +} + static int tvp5150_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config) { @@ -1073,6 +1088,7 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = { static const struct v4l2_subdev_video_ops tvp5150_video_ops = { .s_std = tvp5150_s_std, + .s_stream = tvp5150_s_stream, .s_routing = tvp5150_s_routing, .s_crop = tvp5150_s_crop, .g_crop = tvp5150_g_crop, -- cgit v1.2.3 From dd3a46bbbe1d49a70a66d95a435a729f7ecd7e8f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 7 Jan 2016 10:46:46 -0200 Subject: [media] tvp5150: Add g_mbus_config subdev operation support This patch adds the .g_mbus_config subdev operation to the driver. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 08383a273e51..e6ce197d8dbc 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -948,6 +948,16 @@ static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) return 0; } +static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, + struct v4l2_mbus_config *cfg) +{ + cfg->type = V4L2_MBUS_BT656; + cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING + | V4L2_MBUS_FIELD_EVEN_LOW | V4L2_MBUS_DATA_ACTIVE_HIGH; + + return 0; +} + /**************************************************************************** I2C Command ****************************************************************************/ @@ -1093,6 +1103,7 @@ static const struct v4l2_subdev_video_ops tvp5150_video_ops = { .s_crop = tvp5150_s_crop, .g_crop = tvp5150_g_crop, .cropcap = tvp5150_cropcap, + .g_mbus_config = tvp5150_g_mbus_config, }; static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { -- cgit v1.2.3 From 14050118afee4d8bd81d22fefa3e986172b08bc6 Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Thu, 14 Jan 2016 14:24:31 -0500 Subject: clk: tegra: Remove improper flags for lock_enable Most PLL's don't actually have LOCK_ENABLE bits. However, most PLL's also had that flag set, which meant that the clk code was trying to enable locks, and inadvertantly flipping bits in other fields. For PLLM, ensure the correct register is used for the misc_register. PLL_MISC0 contains the EN_LCKDET bit which should be used for enabling the lock, and PLLM_MISC1 shouldn't be used at all. Lastly, remove some of the settings which would point to the EN_LCKDET bits for some PLLs. There is no need to enable the locks, and that is done as part of the set_defaults logic already. Signed-off-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra210.c | 42 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 58514c44ea83..f45c9adf7fb2 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -1386,7 +1386,7 @@ static struct tegra_clk_pll_params pll_c_params = { .mdiv_default = 3, .div_nmp = &pllc_nmp, .freq_table = pll_cx_freq_table, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK, .set_defaults = _pllc_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -1425,7 +1425,7 @@ static struct tegra_clk_pll_params pll_c2_params = { .ext_misc_reg[2] = PLLC2_MISC2, .ext_misc_reg[3] = PLLC2_MISC3, .freq_table = pll_cx_freq_table, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK, .set_defaults = _pllc2_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -1455,7 +1455,7 @@ static struct tegra_clk_pll_params pll_c3_params = { .ext_misc_reg[2] = PLLC3_MISC2, .ext_misc_reg[3] = PLLC3_MISC3, .freq_table = pll_cx_freq_table, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK, .set_defaults = _pllc3_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -1505,7 +1505,6 @@ static struct tegra_clk_pll_params pll_c4_vco_params = { .base_reg = PLLC4_BASE, .misc_reg = PLLC4_MISC0, .lock_mask = PLL_BASE_LOCK, - .lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE, .lock_delay = 300, .max_p = PLL_QLIN_PDIV_MAX, .ext_misc_reg[0] = PLLC4_MISC0, @@ -1517,8 +1516,7 @@ static struct tegra_clk_pll_params pll_c4_vco_params = { .div_nmp = &pllss_nmp, .freq_table = pll_c4_vco_freq_table, .set_defaults = tegra210_pllc4_set_defaults, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE | - TEGRA_PLL_VCO_OUT, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_VCO_OUT, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -1559,7 +1557,7 @@ static struct tegra_clk_pll_params pll_m_params = { .vco_min = 800000000, .vco_max = 1866000000, .base_reg = PLLM_BASE, - .misc_reg = PLLM_MISC1, + .misc_reg = PLLM_MISC0, .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLLM_MISC_LOCK_ENABLE, .lock_delay = 300, @@ -1588,7 +1586,6 @@ static struct tegra_clk_pll_params pll_mb_params = { .base_reg = PLLMB_BASE, .misc_reg = PLLMB_MISC0, .lock_mask = PLL_BASE_LOCK, - .lock_enable_bit_idx = PLLMB_MISC_LOCK_ENABLE, .lock_delay = 300, .iddq_reg = PLLMB_MISC0, .iddq_bit_idx = PLLMB_IDDQ_BIT, @@ -1598,7 +1595,7 @@ static struct tegra_clk_pll_params pll_mb_params = { .pdiv_tohw = pll_qlin_pdiv_to_hw, .div_nmp = &pllm_nmp, .freq_table = pll_m_freq_table, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK, .set_defaults = tegra210_pllmb_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -1671,7 +1668,6 @@ static struct tegra_clk_pll_params pll_re_vco_params = { .base_reg = PLLRE_BASE, .misc_reg = PLLRE_MISC0, .lock_mask = PLLRE_MISC_LOCK, - .lock_enable_bit_idx = PLLRE_MISC_LOCK_ENABLE, .lock_delay = 300, .max_p = PLL_QLIN_PDIV_MAX, .ext_misc_reg[0] = PLLRE_MISC0, @@ -1681,8 +1677,7 @@ static struct tegra_clk_pll_params pll_re_vco_params = { .pdiv_tohw = pll_qlin_pdiv_to_hw, .div_nmp = &pllre_nmp, .freq_table = pll_re_vco_freq_table, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_LOCK_MISC | - TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_VCO_OUT, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_LOCK_MISC | TEGRA_PLL_VCO_OUT, .set_defaults = tegra210_pllre_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -1712,7 +1707,6 @@ static struct tegra_clk_pll_params pll_p_params = { .base_reg = PLLP_BASE, .misc_reg = PLLP_MISC0, .lock_mask = PLL_BASE_LOCK, - .lock_enable_bit_idx = PLLP_MISC_LOCK_ENABLE, .lock_delay = 300, .iddq_reg = PLLP_MISC0, .iddq_bit_idx = PLLXP_IDDQ_BIT, @@ -1721,8 +1715,7 @@ static struct tegra_clk_pll_params pll_p_params = { .div_nmp = &pllp_nmp, .freq_table = pll_p_freq_table, .fixed_rate = 408000000, - .flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK | - TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_VCO_OUT, + .flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK | TEGRA_PLL_VCO_OUT, .set_defaults = tegra210_pllp_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -1750,7 +1743,7 @@ static struct tegra_clk_pll_params pll_a1_params = { .ext_misc_reg[2] = PLLA1_MISC2, .ext_misc_reg[3] = PLLA1_MISC3, .freq_table = pll_cx_freq_table, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK, .set_defaults = _plla1_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; @@ -1787,7 +1780,6 @@ static struct tegra_clk_pll_params pll_a_params = { .base_reg = PLLA_BASE, .misc_reg = PLLA_MISC0, .lock_mask = PLL_BASE_LOCK, - .lock_enable_bit_idx = PLLA_MISC_LOCK_ENABLE, .lock_delay = 300, .round_p_to_pdiv = pll_qlin_p_to_pdiv, .pdiv_tohw = pll_qlin_pdiv_to_hw, @@ -1802,8 +1794,7 @@ static struct tegra_clk_pll_params pll_a_params = { .ext_misc_reg[1] = PLLA_MISC1, .ext_misc_reg[2] = PLLA_MISC2, .freq_table = pll_a_freq_table, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_MDIV_NEW | - TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_MDIV_NEW, .set_defaults = tegra210_plla_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, .set_gain = tegra210_clk_pll_set_gain, @@ -1836,7 +1827,6 @@ static struct tegra_clk_pll_params pll_d_params = { .base_reg = PLLD_BASE, .misc_reg = PLLD_MISC0, .lock_mask = PLL_BASE_LOCK, - .lock_enable_bit_idx = PLLD_MISC_LOCK_ENABLE, .lock_delay = 1000, .iddq_reg = PLLD_MISC0, .iddq_bit_idx = PLLD_IDDQ_BIT, @@ -1850,7 +1840,7 @@ static struct tegra_clk_pll_params pll_d_params = { .ext_misc_reg[0] = PLLD_MISC0, .ext_misc_reg[1] = PLLD_MISC1, .freq_table = pll_d_freq_table, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK, .mdiv_default = 1, .set_defaults = tegra210_plld_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, @@ -1876,7 +1866,6 @@ static struct tegra_clk_pll_params pll_d2_params = { .base_reg = PLLD2_BASE, .misc_reg = PLLD2_MISC0, .lock_mask = PLL_BASE_LOCK, - .lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE, .lock_delay = 300, .iddq_reg = PLLD2_BASE, .iddq_bit_idx = PLLSS_IDDQ_BIT, @@ -1897,7 +1886,7 @@ static struct tegra_clk_pll_params pll_d2_params = { .mdiv_default = 1, .freq_table = tegra210_pll_d2_freq_table, .set_defaults = tegra210_plld2_set_defaults, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK, .calc_rate = tegra210_pll_fixed_mdiv_cfg, .set_gain = tegra210_clk_pll_set_gain, .adjust_vco = tegra210_clk_adjust_vco_min, @@ -1920,7 +1909,6 @@ static struct tegra_clk_pll_params pll_dp_params = { .base_reg = PLLDP_BASE, .misc_reg = PLLDP_MISC, .lock_mask = PLL_BASE_LOCK, - .lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE, .lock_delay = 300, .iddq_reg = PLLDP_BASE, .iddq_bit_idx = PLLSS_IDDQ_BIT, @@ -1941,7 +1929,7 @@ static struct tegra_clk_pll_params pll_dp_params = { .mdiv_default = 1, .freq_table = pll_dp_freq_table, .set_defaults = tegra210_plldp_set_defaults, - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .flags = TEGRA_PLL_USE_LOCK, .calc_rate = tegra210_pll_fixed_mdiv_cfg, .set_gain = tegra210_clk_pll_set_gain, .adjust_vco = tegra210_clk_adjust_vco_min, @@ -1973,7 +1961,6 @@ static struct tegra_clk_pll_params pll_u_vco_params = { .base_reg = PLLU_BASE, .misc_reg = PLLU_MISC0, .lock_mask = PLL_BASE_LOCK, - .lock_enable_bit_idx = PLLU_MISC_LOCK_ENABLE, .lock_delay = 1000, .iddq_reg = PLLU_MISC0, .iddq_bit_idx = PLLU_IDDQ_BIT, @@ -1983,8 +1970,7 @@ static struct tegra_clk_pll_params pll_u_vco_params = { .pdiv_tohw = pll_qlin_pdiv_to_hw, .div_nmp = &pllu_nmp, .freq_table = pll_u_freq_table, - .flags = TEGRA_PLLU | TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE | - TEGRA_PLL_VCO_OUT, + .flags = TEGRA_PLLU | TEGRA_PLL_USE_LOCK | TEGRA_PLL_VCO_OUT, .set_defaults = tegra210_pllu_set_defaults, .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; -- cgit v1.2.3 From 09aa2609fe69fd4878e5c0f1319410b46afaab8f Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 7 Jan 2016 10:46:49 -0200 Subject: [media] tvp5150: Initialize the chip on probe After power-up, the tvp5150 decoder is in a unknown state until the RESETB pin is driven LOW which reset all the registers and restarts the chip's internal state machine. The init sequence has some timing constraints and the RESETB signal can only be used if the PDN (Power-down) pin is first released. So, the initialization sequence is as follows: 1- PDN (active-low) is driven HIGH so the chip is power-up 2- A 20 ms delay is needed before sending a RESETB (active-low) signal. 3- The RESETB pulse duration is 500 ns. 4- A 200 us delay is needed for the I2C client to be active after reset. This patch used as a reference the logic in the IGEPv2 board file from the ISEE 2.6.37 vendor tree. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index e6ce197d8dbc..6f4b0f83973e 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -1175,6 +1176,36 @@ static int tvp5150_detect_version(struct tvp5150 *core) return 0; } +static int tvp5150_init(struct i2c_client *c) +{ + struct gpio_desc *pdn_gpio; + struct gpio_desc *reset_gpio; + + pdn_gpio = devm_gpiod_get_optional(&c->dev, "pdn", GPIOD_OUT_HIGH); + if (IS_ERR(pdn_gpio)) + return PTR_ERR(pdn_gpio); + + if (pdn_gpio) { + gpiod_set_value_cansleep(pdn_gpio, 0); + /* Delay time between power supplies active and reset */ + msleep(20); + } + + reset_gpio = devm_gpiod_get_optional(&c->dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(reset_gpio)) + return PTR_ERR(reset_gpio); + + if (reset_gpio) { + /* RESETB pulse duration */ + ndelay(500); + gpiod_set_value_cansleep(reset_gpio, 0); + /* Delay time between end of reset to I2C active */ + usleep_range(200, 250); + } + + return 0; +} + static int tvp5150_probe(struct i2c_client *c, const struct i2c_device_id *id) { @@ -1187,6 +1218,10 @@ static int tvp5150_probe(struct i2c_client *c, I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) return -EIO; + res = tvp5150_init(c); + if (res) + return res; + core = devm_kzalloc(&c->dev, sizeof(*core), GFP_KERNEL); if (!core) return -ENOMEM; -- cgit v1.2.3 From 262c741e0825b29447a9e53b6582afd6b14c3706 Mon Sep 17 00:00:00 2001 From: Eli Cooper Date: Mon, 18 Jan 2016 19:30:19 +0800 Subject: rt2x00: fix monitor mode regression Since commit df1404650ccb ("mac80211: remove support for IFF_PROMISC") monitor mode for rt2x00 has been made effectively useless because the hardware filter is configured to drop packets whose intended recipient is not the device, regardless of the presence of monitor mode interfaces. This patch fixes this regression by adding explicit monitor mode support, and by configuring the hardware filter accordingly. Signed-off-by: Eli Cooper Acked-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2400pci.c | 4 +++- drivers/net/wireless/ralink/rt2x00/rt2500pci.c | 4 +++- drivers/net/wireless/ralink/rt2x00/rt2500usb.c | 4 +++- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 3 ++- drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 + drivers/net/wireless/ralink/rt2x00/rt2x00config.c | 5 +++++ drivers/net/wireless/ralink/rt2x00/rt2x00mac.c | 5 ----- drivers/net/wireless/ralink/rt2x00/rt61pci.c | 4 +++- drivers/net/wireless/ralink/rt2x00/rt73usb.c | 4 +++- 9 files changed, 23 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c index 9a3966cd6fbe..155f343981fe 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c @@ -273,8 +273,10 @@ static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev, !(filter_flags & FIF_PLCPFAIL)); rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, !(filter_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, 1); + rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, + !test_bit(CONFIG_MONITORING, &rt2x00dev->flags)); rt2x00_set_field32(®, RXCSR0_DROP_TODS, + !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) && !rt2x00dev->intf_ap_count); rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg); diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c index 1a6740b4d396..2553cdd74066 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c @@ -274,8 +274,10 @@ static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev, !(filter_flags & FIF_PLCPFAIL)); rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, !(filter_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, 1); + rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, + !test_bit(CONFIG_MONITORING, &rt2x00dev->flags)); rt2x00_set_field32(®, RXCSR0_DROP_TODS, + !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) && !rt2x00dev->intf_ap_count); rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); rt2x00_set_field32(®, RXCSR0_DROP_MCAST, diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c index d26018f30b7d..2d64611de300 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c @@ -437,8 +437,10 @@ static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev, !(filter_flags & FIF_PLCPFAIL)); rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL, !(filter_flags & FIF_CONTROL)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME, 1); + rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME, + !test_bit(CONFIG_MONITORING, &rt2x00dev->flags)); rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS, + !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) && !rt2x00dev->intf_ap_count); rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1); rt2x00_set_field16(®, TXRX_CSR2_DROP_MULTICAST, diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index 9733b31a780d..a26afcab03ed 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -1490,7 +1490,8 @@ void rt2800_config_filter(struct rt2x00_dev *rt2x00dev, !(filter_flags & FIF_FCSFAIL)); rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR, !(filter_flags & FIF_PLCPFAIL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, 1); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, + !test_bit(CONFIG_MONITORING, &rt2x00dev->flags)); rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0); rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1); rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST, diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h index 3282ddb766f4..26427140a963 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h @@ -669,6 +669,7 @@ enum rt2x00_state_flags { CONFIG_POWERSAVING, CONFIG_HT_DISABLED, CONFIG_QOS_DISABLED, + CONFIG_MONITORING, /* * Mark we currently are sequentially reading TX_STA_FIFO register diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00config.c b/drivers/net/wireless/ralink/rt2x00/rt2x00config.c index 7e8bb1198ae9..6a1f508d472f 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00config.c @@ -277,6 +277,11 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, else clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); + if (conf->flags & IEEE80211_CONF_MONITOR) + set_bit(CONFIG_MONITORING, &rt2x00dev->flags); + else + clear_bit(CONFIG_MONITORING, &rt2x00dev->flags); + rt2x00dev->curr_band = conf->chandef.chan->band; rt2x00dev->curr_freq = conf->chandef.chan->center_freq; rt2x00dev->tx_power = conf->power_level; diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c index 3c26ee65a415..13da95a24cf7 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c @@ -385,11 +385,6 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, *total_flags |= FIF_PSPOLL; } - /* - * Check if there is any work left for us. - */ - if (rt2x00dev->packet_filter == *total_flags) - return; rt2x00dev->packet_filter = *total_flags; rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.c b/drivers/net/wireless/ralink/rt2x00/rt61pci.c index c0e730ea1b69..24a3436ef952 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c +++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c @@ -530,8 +530,10 @@ static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev, !(filter_flags & FIF_PLCPFAIL)); rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, !(filter_flags & (FIF_CONTROL | FIF_PSPOLL))); - rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, 1); + rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, + !test_bit(CONFIG_MONITORING, &rt2x00dev->flags)); rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, + !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) && !rt2x00dev->intf_ap_count); rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, diff --git a/drivers/net/wireless/ralink/rt2x00/rt73usb.c b/drivers/net/wireless/ralink/rt2x00/rt73usb.c index 7081e13b4fd6..7bbc86931168 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt73usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt73usb.c @@ -480,8 +480,10 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev, !(filter_flags & FIF_PLCPFAIL)); rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, !(filter_flags & (FIF_CONTROL | FIF_PSPOLL))); - rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, 1); + rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, + !test_bit(CONFIG_MONITORING, &rt2x00dev->flags)); rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, + !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) && !rt2x00dev->intf_ap_count); rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, -- cgit v1.2.3 From c72fc9093718a3f8597249863a1bac345ba00859 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 20 Jan 2016 21:58:39 -0600 Subject: rtlwifi: rtl8821ae: Fix 5G failure when EEPROM is incorrectly encoded Recently, it has been reported that D-Link DWA-582 cards, which use an RTL8812AE chip are not able to scan for 5G networks. The problems started with kernel 4.2, which is the first version that had commit d10101a60372 ("rtlwifi: rtl8821ae: Fix problem with regulatory information"). With this patch, the driver went from setting a default channel plan to using the value derived from EEPROM. Bug reports at https://bugzilla.kernel.org/show_bug.cgi?id=111031 and https://bugzilla.redhat.com/show_bug.cgi?id=1279653 are examples of this problem. The problem was solved once I learned that the internal country code was resulting in a regulatory set with only 2.4 GHz channels. With the RTL8821AE chips available to me, the country code was such that both 2.4 and 5 GHz channels are allowed. The fix is to allow both bands even when the EEPROM is incorrectly encoded. Fixes: d10101a60372 ("rtlwifi: rtl8821ae: Fix problem with regulatory information") Signed-off-by: Larry Finger Cc: littlesmartguy@gmail.com Cc: gabe@codehaus.org Cc: Stable [v4.2+] Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/regd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c index a62bf0a65c32..5be34118e0af 100644 --- a/drivers/net/wireless/realtek/rtlwifi/regd.c +++ b/drivers/net/wireless/realtek/rtlwifi/regd.c @@ -351,7 +351,6 @@ static const struct ieee80211_regdomain *_rtl_regdomain_select( case COUNTRY_CODE_SPAIN: case COUNTRY_CODE_FRANCE: case COUNTRY_CODE_ISRAEL: - case COUNTRY_CODE_WORLD_WIDE_13: return &rtl_regdom_12_13; case COUNTRY_CODE_MKK: case COUNTRY_CODE_MKK1: @@ -360,6 +359,7 @@ static const struct ieee80211_regdomain *_rtl_regdomain_select( return &rtl_regdom_14_60_64; case COUNTRY_CODE_GLOBAL_DOMAIN: return &rtl_regdom_14; + case COUNTRY_CODE_WORLD_WIDE_13: case COUNTRY_CODE_WORLD_WIDE_13_5G_ALL: return &rtl_regdom_12_13_5g_all; default: -- cgit v1.2.3 From 23a9d5dcb6ae114733fac4757b0b154571c21129 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 8 Jan 2016 11:52:04 -0200 Subject: drm/etnaviv: remove owner assignment from platform_driver This platform_driver does not need to set an owner as it will be populated by the driver core. Generated by scripts/coccinelle/api/platform_no_drv_owner.cocci. Signed-off-by: Fabio Estevam Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 5c89ebb52fd2..e8858985f01e 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -668,7 +668,6 @@ static struct platform_driver etnaviv_platform_driver = { .probe = etnaviv_pdev_probe, .remove = etnaviv_pdev_remove, .driver = { - .owner = THIS_MODULE, .name = "etnaviv", .of_match_table = dt_match, }, -- cgit v1.2.3 From 339073ef77e45e87ec4cc8671b2d2328dcfd31f0 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 22 Jan 2016 12:03:03 +0100 Subject: drm/etnaviv: hold object lock while getting pages for coredump While all objects that get coredumped have an active IOVA and thus pages already populated, etnaviv_gem_get_pages() still requires the object lock to be held. Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_dump.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_dump.c b/drivers/gpu/drm/etnaviv/etnaviv_dump.c index bf8fa859e8be..fd7d3e989e79 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_dump.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_dump.c @@ -201,7 +201,9 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu) obj = vram->object; + mutex_lock(&obj->lock); pages = etnaviv_gem_get_pages(obj); + mutex_unlock(&obj->lock); if (pages) { int j; -- cgit v1.2.3 From f6427760a29ba3fd968e27ea567b1ebdd500740b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 24 Jan 2016 17:32:13 +0000 Subject: drm/etnaviv: fix failure path if model is zero Fix the failure path to call pm_runtime_mark_last_busy() when failing due to the model field being zero. Acked-by: Christian Gmeiner Signed-off-by: Russell King Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 056a72e6ed26..e0e68dd7565d 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -511,8 +511,8 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu) if (gpu->identity.model == 0) { dev_err(gpu->dev, "Unknown GPU model\n"); - pm_runtime_put_autosuspend(gpu->dev); - return -ENXIO; + ret = -ENXIO; + goto fail; } ret = etnaviv_hw_reset(gpu); -- cgit v1.2.3 From a2e5f1b3a4f12c8c35313a9052a8928b5b85a391 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 7 Jan 2016 10:46:50 -0200 Subject: [media] tvp5150: Configure data interface via DT The video decoder supports either 8-bit 4:2:2 YUV with discrete syncs or 8-bit ITU-R BT.656 with embedded syncs output format but currently BT.656 it's always reported. Allow to configure the format to use via either platform data or a device tree definition. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 66 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 6f4b0f83973e..57901d613a12 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "tvp5150_reg.h" @@ -43,6 +44,8 @@ struct tvp5150 { u32 input; u32 output; int enable; + + enum v4l2_mbus_type mbus_type; }; static inline struct tvp5150 *to_tvp5150(struct v4l2_subdev *sd) @@ -773,6 +776,10 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val) v4l2_ctrl_handler_setup(&decoder->hdl); tvp5150_set_std(sd, decoder->norm); + + if (decoder->mbus_type == V4L2_MBUS_PARALLEL) + tvp5150_write(sd, TVP5150_DATA_RATE_SEL, 0x40); + return 0; }; @@ -952,7 +959,9 @@ static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg) { - cfg->type = V4L2_MBUS_BT656; + struct tvp5150 *decoder = to_tvp5150(sd); + + cfg->type = decoder->mbus_type; cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_FIELD_EVEN_LOW | V4L2_MBUS_DATA_ACTIVE_HIGH; @@ -965,13 +974,20 @@ static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) { + struct tvp5150 *decoder = to_tvp5150(sd); + /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ + int val = 0x09; + + /* Output format: 8-bit 4:2:2 YUV with discrete sync */ + if (decoder->mbus_type == V4L2_MBUS_PARALLEL) + val = 0x0d; + /* Initializes TVP5150 to its default values */ /* # set PCLK (27MHz) */ tvp5150_write(sd, TVP5150_CONF_SHARED_PIN, 0x00); - /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ if (enable) - tvp5150_write(sd, TVP5150_MISC_CTL, 0x09); + tvp5150_write(sd, TVP5150_MISC_CTL, val); else tvp5150_write(sd, TVP5150_MISC_CTL, 0x00); @@ -1206,11 +1222,42 @@ static int tvp5150_init(struct i2c_client *c) return 0; } +static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) +{ + struct v4l2_of_endpoint bus_cfg; + struct device_node *ep; + unsigned int flags; + int ret = 0; + + ep = of_graph_get_next_endpoint(np, NULL); + if (!ep) + return -EINVAL; + + ret = v4l2_of_parse_endpoint(ep, &bus_cfg); + if (ret) + goto err; + + flags = bus_cfg.bus.parallel.flags; + + if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL && + !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH && + flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH && + flags & V4L2_MBUS_FIELD_EVEN_LOW)) + return -EINVAL; + + decoder->mbus_type = bus_cfg.bus_type; + +err: + of_node_put(ep); + return ret; +} + static int tvp5150_probe(struct i2c_client *c, const struct i2c_device_id *id) { struct tvp5150 *core; struct v4l2_subdev *sd; + struct device_node *np = c->dev.of_node; int res; /* Check if the adapter supports the needed features */ @@ -1225,7 +1272,20 @@ static int tvp5150_probe(struct i2c_client *c, core = devm_kzalloc(&c->dev, sizeof(*core), GFP_KERNEL); if (!core) return -ENOMEM; + sd = &core->sd; + + if (IS_ENABLED(CONFIG_OF) && np) { + res = tvp5150_parse_dt(core, np); + if (res) { + v4l2_err(sd, "DT parsing error: %d\n", res); + return res; + } + } else { + /* Default to BT.656 embedded sync */ + core->mbus_type = V4L2_MBUS_BT656; + } + v4l2_i2c_subdev_init(sd, c, &tvp5150_ops); res = tvp5150_detect_version(core); -- cgit v1.2.3 From 65dc1a5d1efb0ec54ffb715468070890d27d63fc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 21 Jan 2016 16:34:08 +0100 Subject: ath9k_hw: ignore eeprom magic mismatch on flash based devices Many AR913x based devices (maybe others too) do not have a valid EEPROM magic in their calibration data partition. Fixes: 6fa658fd5ab2 ("ath9k: Simplify and fix eeprom endianness swapping") Signed-off-by: Felix Fietkau Acked-by: Martin Blumenstingl Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/eeprom.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index a7afdeee698c..73fb4232f9f2 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -150,18 +150,18 @@ int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size) return -EIO; } - if (magic == AR5416_EEPROM_MAGIC) { - *swap_needed = false; - } else if (swab16(magic) == AR5416_EEPROM_MAGIC) { + *swap_needed = false; + if (swab16(magic) == AR5416_EEPROM_MAGIC) { if (ah->ah_flags & AH_NO_EEP_SWAP) { ath_info(common, "Ignoring endianness difference in EEPROM magic bytes.\n"); - - *swap_needed = false; } else { *swap_needed = true; } - } else { + } else if (magic != AR5416_EEPROM_MAGIC) { + if (ath9k_hw_use_flash(ah)) + return 0; + ath_err(common, "Invalid EEPROM Magic (0x%04x).\n", magic); return -EINVAL; -- cgit v1.2.3 From e7a7104e432c0db8469ca3568daf4f1d1afe3e73 Mon Sep 17 00:00:00 2001 From: Horia Geant? Date: Tue, 12 Jan 2016 17:59:29 +0200 Subject: crypto: caam - make write transactions bufferable on PPC platforms Previous change (see "Fixes" tag) to the MCFGR register clears AWCACHE[0] ("bufferable" AXI3 attribute) (which is "1" at POR). This makes all writes non-bufferable, causing a ~ 5% performance drop for PPC-based platforms. Rework previous change such that MCFGR[AWCACHE]=4'b0011 (bufferable + cacheable) for all platforms. Note: For ARM-based platforms, AWCACHE[0] is ignored by the interconnect IP. Cc: # 4.3+ Fixes: f10967495144 ("crypto: caam - fix snooping for write transactions") Signed-off-by: Horia Geant? Signed-off-by: Herbert Xu --- drivers/crypto/caam/ctrl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index 8abb4bc548cc..69d4a1326fee 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -534,8 +534,8 @@ static int caam_probe(struct platform_device *pdev) * long pointers in master configuration register */ clrsetbits_32(&ctrl->mcr, MCFGR_AWCACHE_MASK, MCFGR_AWCACHE_CACH | - MCFGR_WDENABLE | (sizeof(dma_addr_t) == sizeof(u64) ? - MCFGR_LONG_PTR : 0)); + MCFGR_AWCACHE_BUFF | MCFGR_WDENABLE | + (sizeof(dma_addr_t) == sizeof(u64) ? MCFGR_LONG_PTR : 0)); /* * Read the Compile Time paramters and SCFGR to determine -- cgit v1.2.3 From 7ef930a7b33677b8227d0a19dcc32d891d3cde8d Mon Sep 17 00:00:00 2001 From: Eduard Gavin Date: Thu, 7 Jan 2016 10:46:48 -0200 Subject: [media] tvp5150: Add OF match table The Documentation/devicetree/bindings/media/i2c/tvp5150.txt DT binding doc lists "ti,tvp5150" as the device compatible string but the driver does not have an OF match table. Add the table to the driver so the I2C core can do an OF style match. Signed-off-by: Eduard Gavin Signed-off-by: Javier Martinez Canillas Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 57901d613a12..437f1a7ecb96 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1359,8 +1359,17 @@ static const struct i2c_device_id tvp5150_id[] = { }; MODULE_DEVICE_TABLE(i2c, tvp5150_id); +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id tvp5150_of_match[] = { + { .compatible = "ti,tvp5150", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, tvp5150_of_match); +#endif + static struct i2c_driver tvp5150_driver = { .driver = { + .of_match_table = of_match_ptr(tvp5150_of_match), .name = "tvp5150", }, .probe = tvp5150_probe, -- cgit v1.2.3 From 219a5859c855b1e6e2663eb63a7f942a6bbdfb52 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 19 Nov 2015 22:22:28 +0100 Subject: clk: rockchip: fix usbphy-related clocks The otgphy clocks really only drive the phy blocks. These in turn contain plls that then generate the 480m clocks the clock controller uses to supply some other clocks like uart0, gpu or the video-codec. So fix this structure to actually respect that hirarchy and removed that usb480m fixed-rate clock working as a placeholder till now, as this wouldn't even work if the supplying phy gets turned off while its pll-output gets used elsewhere. Signed-off-by: Heiko Stuebner Reviewed-by: Douglas Anderson Acked-by: Michael Turquette --- arch/arm/boot/dts/rk3288-veyron.dtsi | 2 +- drivers/clk/rockchip/clk-rk3188.c | 11 +++-------- drivers/clk/rockchip/clk-rk3288.c | 16 +++++----------- 3 files changed, 9 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi index 9fce91ffff6f..cb27a8f5a8e2 100644 --- a/arch/arm/boot/dts/rk3288-veyron.dtsi +++ b/arch/arm/boot/dts/rk3288-veyron.dtsi @@ -421,7 +421,7 @@ status = "okay"; assigned-clocks = <&cru SCLK_USBPHY480M_SRC>; - assigned-clock-parents = <&cru SCLK_OTGPHY0>; + assigned-clock-parents = <&usbphy0>; dr_mode = "host"; }; diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index 7f7444cbf6fc..73954907111e 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -343,9 +343,9 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { * the 480m are generated inside the usb block from these clocks, * but they are also a source for the hsicphy clock. */ - GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED, + GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(1), 5, GFLAGS), - GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED, + GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(1), 6, GFLAGS), COMPOSITE(0, "mac_src", mux_mac_p, 0, @@ -662,7 +662,7 @@ static struct clk_div_table div_rk3188_aclk_core_t[] = { { /* sentinel */ }, }; -PNAME(mux_hsicphy_p) = { "sclk_otgphy0", "sclk_otgphy1", +PNAME(mux_hsicphy_p) = { "sclk_otgphy0_480m", "sclk_otgphy1_480m", "gpll", "cpll" }; static struct rockchip_clk_branch rk3188_i2s0_fracmux __initdata = @@ -769,11 +769,6 @@ static void __init rk3188_common_clk_init(struct device_node *np) pr_warn("%s: could not register clock xin12m: %ld\n", __func__, PTR_ERR(clk)); - clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock usb480m: %ld\n", - __func__, PTR_ERR(clk)); - rockchip_clk_register_branches(common_clk_branches, ARRAY_SIZE(common_clk_branches)); diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 984fc187d12e..0d23937c594a 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -195,8 +195,8 @@ PNAME(mux_hsadcout_p) = { "hsadc_src", "ext_hsadc" }; PNAME(mux_edp_24m_p) = { "ext_edp_24m", "xin24m" }; PNAME(mux_tspout_p) = { "cpll", "gpll", "npll", "xin27m" }; -PNAME(mux_usbphy480m_p) = { "sclk_otgphy1", "sclk_otgphy2", - "sclk_otgphy0" }; +PNAME(mux_usbphy480m_p) = { "sclk_otgphy1_480m", "sclk_otgphy2_480m", + "sclk_otgphy0_480m" }; PNAME(mux_hsicphy480m_p) = { "cpll", "gpll", "usbphy480m_src" }; PNAME(mux_hsicphy12m_p) = { "hsicphy12m_xin12m", "hsicphy12m_usbphy" }; @@ -537,11 +537,11 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { RK3288_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3288_CLKGATE_CON(4), 10, GFLAGS), - GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED, + GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(13), 4, GFLAGS), - GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED, + GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(13), 5, GFLAGS), - GATE(SCLK_OTGPHY2, "sclk_otgphy2", "usb480m", CLK_IGNORE_UNUSED, + GATE(SCLK_OTGPHY2, "sclk_otgphy2", "xin24m", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(13), 6, GFLAGS), GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(13), 7, GFLAGS), @@ -894,12 +894,6 @@ static void __init rk3288_clk_init(struct device_node *np) pr_warn("%s: could not register clock xin12m: %ld\n", __func__, PTR_ERR(clk)); - - clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock usb480m: %ld\n", - __func__, PTR_ERR(clk)); - clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre", "hclk_vcodec_pre_v", 0, 1, 4); if (IS_ERR(clk)) -- cgit v1.2.3 From 99e44da7928d4abb3028258ac3cd23a48495cd61 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 24 Jan 2016 12:56:58 -0200 Subject: [media] media: change email address Soon my dibcom.fr/parrot.com-address won't respond anymore. Thus I'm replacing it. And, while being at it, let's adapt some other (old) email-addresses as well. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- Documentation/dvb/README.dvb-usb | 2 +- drivers/media/common/b2c2/flexcop.c | 4 ++-- drivers/media/common/cypress_firmware.c | 2 +- drivers/media/common/cypress_firmware.h | 2 +- drivers/media/dvb-core/dvb-usb-ids.h | 2 +- drivers/media/dvb-frontends/bcm3510.c | 4 ++-- drivers/media/dvb-frontends/bcm3510.h | 2 +- drivers/media/dvb-frontends/bcm3510_priv.h | 2 +- drivers/media/dvb-frontends/dib0070.c | 2 +- drivers/media/dvb-frontends/dib0090.c | 4 ++-- drivers/media/dvb-frontends/dib3000.h | 6 +++--- drivers/media/dvb-frontends/dib3000mb.c | 8 ++++---- drivers/media/dvb-frontends/dib3000mb_priv.h | 2 +- drivers/media/dvb-frontends/dib3000mc.c | 4 ++-- drivers/media/dvb-frontends/dib3000mc.h | 2 +- drivers/media/dvb-frontends/dib7000m.c | 2 +- drivers/media/dvb-frontends/dib7000p.c | 4 ++-- drivers/media/dvb-frontends/dib8000.c | 2 +- drivers/media/dvb-frontends/dib9000.c | 4 ++-- drivers/media/dvb-frontends/dibx000_common.c | 2 +- drivers/media/pci/b2c2/flexcop-pci.c | 2 +- drivers/media/usb/b2c2/flexcop-usb.c | 2 +- drivers/media/usb/dvb-usb-v2/dvb_usb.h | 2 +- drivers/media/usb/dvb-usb-v2/dvb_usb_common.h | 2 +- drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 4 ++-- drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c | 2 +- drivers/media/usb/dvb-usb-v2/usb_urb.c | 2 +- drivers/media/usb/dvb-usb/a800.c | 4 ++-- drivers/media/usb/dvb-usb/cxusb.c | 4 ++-- drivers/media/usb/dvb-usb/dib0700_core.c | 2 +- drivers/media/usb/dvb-usb/dibusb-common.c | 2 +- drivers/media/usb/dvb-usb/dibusb-mb.c | 6 +++--- drivers/media/usb/dvb-usb/dibusb-mc.c | 6 +++--- drivers/media/usb/dvb-usb/dibusb.h | 2 +- drivers/media/usb/dvb-usb/digitv.c | 4 ++-- drivers/media/usb/dvb-usb/dtt200u-fe.c | 2 +- drivers/media/usb/dvb-usb/dtt200u.c | 4 ++-- drivers/media/usb/dvb-usb/dtt200u.h | 2 +- drivers/media/usb/dvb-usb/dvb-usb-common.h | 2 +- drivers/media/usb/dvb-usb/dvb-usb-dvb.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb-firmware.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb-i2c.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb-init.c | 4 ++-- drivers/media/usb/dvb-usb/dvb-usb-remote.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb-urb.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb.h | 2 +- drivers/media/usb/dvb-usb/nova-t-usb2.c | 4 ++-- drivers/media/usb/dvb-usb/ttusb2.c | 2 +- drivers/media/usb/dvb-usb/umt-010.c | 4 ++-- drivers/media/usb/dvb-usb/usb-urb.c | 2 +- drivers/media/usb/dvb-usb/vp702x-fe.c | 2 +- drivers/media/usb/dvb-usb/vp702x.c | 4 ++-- drivers/media/usb/dvb-usb/vp7045-fe.c | 2 +- drivers/media/usb/dvb-usb/vp7045.c | 4 ++-- drivers/media/usb/dvb-usb/vp7045.h | 2 +- 55 files changed, 80 insertions(+), 80 deletions(-) (limited to 'drivers') diff --git a/Documentation/dvb/README.dvb-usb b/Documentation/dvb/README.dvb-usb index 669dc6ce4330..6f4b12f7b844 100644 --- a/Documentation/dvb/README.dvb-usb +++ b/Documentation/dvb/README.dvb-usb @@ -190,7 +190,7 @@ and watch another one. Patches, comments and suggestions are very very welcome. 3. Acknowledgements - Amaury Demol (ademol@dibcom.fr) and Francois Kanounnikoff from DiBcom for + Amaury Demol (Amaury.Demol@parrot.com) and Francois Kanounnikoff from DiBcom for providing specs, code and help, on which the dvb-dibusb, dib3000mb and dib3000mc are based. diff --git a/drivers/media/common/b2c2/flexcop.c b/drivers/media/common/b2c2/flexcop.c index 412c5daf2b48..0f5114d406f8 100644 --- a/drivers/media/common/b2c2/flexcop.c +++ b/drivers/media/common/b2c2/flexcop.c @@ -1,7 +1,7 @@ /* * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III * flexcop.c - main module part - * Copyright (C) 2004-9 Patrick Boettcher + * Copyright (C) 2004-9 Patrick Boettcher * based on skystar2-driver Copyright (C) 2003 Vadim Catana, skystar@moldova.cc * * Acknowledgements: @@ -34,7 +34,7 @@ #include "flexcop.h" #define DRIVER_NAME "B2C2 FlexcopII/II(b)/III digital TV receiver chip" -#define DRIVER_AUTHOR "Patrick Boettcher + * GPL/Linux driver written by Patrick Boettcher * * This driver is "hard-coded" to be used with the 1st generation of * Technisat/B2C2's Air2PC ATSC PCI/USB cards/boxes. The pll-programming @@ -865,5 +865,5 @@ static struct dvb_frontend_ops bcm3510_ops = { }; MODULE_DESCRIPTION("Broadcom BCM3510 ATSC (8VSB/16VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver"); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/bcm3510.h b/drivers/media/dvb-frontends/bcm3510.h index ff66492fb940..961c2eb87c68 100644 --- a/drivers/media/dvb-frontends/bcm3510.h +++ b/drivers/media/dvb-frontends/bcm3510.h @@ -3,7 +3,7 @@ * * Copyright (C) 2001-5, B2C2 inc. * - * GPL/Linux driver written by Patrick Boettcher + * GPL/Linux driver written by Patrick Boettcher * * 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/bcm3510_priv.h b/drivers/media/dvb-frontends/bcm3510_priv.h index 3bb1bc2a04f0..67f24686c31b 100644 --- a/drivers/media/dvb-frontends/bcm3510_priv.h +++ b/drivers/media/dvb-frontends/bcm3510_priv.h @@ -3,7 +3,7 @@ * * Copyright (C) 2001-5, B2C2 inc. * - * GPL/Linux driver written by Patrick Boettcher + * GPL/Linux driver written by Patrick Boettcher * * 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/dib0070.c b/drivers/media/dvb-frontends/dib0070.c index 0b8fb5dd1889..ee7d66997ccd 100644 --- a/drivers/media/dvb-frontends/dib0070.c +++ b/drivers/media/dvb-frontends/dib0070.c @@ -774,6 +774,6 @@ free_mem: } EXPORT_SYMBOL(dib0070_attach); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib0090.c b/drivers/media/dvb-frontends/dib0090.c index 47cb72243b9d..976ee034a430 100644 --- a/drivers/media/dvb-frontends/dib0090.c +++ b/drivers/media/dvb-frontends/dib0090.c @@ -2669,7 +2669,7 @@ free_mem: } EXPORT_SYMBOL(dib0090_fw_register); -MODULE_AUTHOR("Patrick Boettcher "); -MODULE_AUTHOR("Olivier Grenie "); +MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Olivier Grenie "); MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib3000.h b/drivers/media/dvb-frontends/dib3000.h index 6ae9899b5b45..d5dfafb4ef13 100644 --- a/drivers/media/dvb-frontends/dib3000.h +++ b/drivers/media/dvb-frontends/dib3000.h @@ -2,11 +2,11 @@ * public header file of the frontend drivers for mobile DVB-T demodulators * DiBcom 3000M-B and DiBcom 3000P/M-C (http://www.dibcom.fr/) * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * based on GPL code from DibCom, which has * - * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) + * Copyright (C) 2004 Amaury Demol for DiBcom * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -14,7 +14,7 @@ * * Acknowledgements * - * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver + * Amaury Demol from DiBcom for providing specs and driver * sources, on which this driver (and the dvb-dibusb) are based. * * see Documentation/dvb/README.dvb-usb for more information diff --git a/drivers/media/dvb-frontends/dib3000mb.c b/drivers/media/dvb-frontends/dib3000mb.c index 7a61172d0d45..3ca300939f79 100644 --- a/drivers/media/dvb-frontends/dib3000mb.c +++ b/drivers/media/dvb-frontends/dib3000mb.c @@ -2,11 +2,11 @@ * Frontend driver for mobile DVB-T demodulator DiBcom 3000M-B * DiBcom (http://www.dibcom.fr/) * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * based on GPL code from DibCom, which has * - * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) + * Copyright (C) 2004 Amaury Demol for DiBcom * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -14,7 +14,7 @@ * * Acknowledgements * - * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver + * Amaury Demol from DiBcom for providing specs and driver * sources, on which this driver (and the dvb-dibusb) are based. * * see Documentation/dvb/README.dvb-usb for more information @@ -36,7 +36,7 @@ /* Version information */ #define DRIVER_VERSION "0.1" #define DRIVER_DESC "DiBcom 3000M-B DVB-T demodulator" -#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de" +#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@posteo.de" static int debug; module_param(debug, int, 0644); diff --git a/drivers/media/dvb-frontends/dib3000mb_priv.h b/drivers/media/dvb-frontends/dib3000mb_priv.h index 9dc235aa44b7..0459d5c84314 100644 --- a/drivers/media/dvb-frontends/dib3000mb_priv.h +++ b/drivers/media/dvb-frontends/dib3000mb_priv.h @@ -1,7 +1,7 @@ /* * dib3000mb_priv.h * - * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@posteo.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as diff --git a/drivers/media/dvb-frontends/dib3000mc.c b/drivers/media/dvb-frontends/dib3000mc.c index 583d6b7fabed..ac90ed3af37e 100644 --- a/drivers/media/dvb-frontends/dib3000mc.c +++ b/drivers/media/dvb-frontends/dib3000mc.c @@ -2,7 +2,7 @@ * Driver for DiBcom DiB3000MC/P-demodulator. * * Copyright (C) 2004-7 DiBcom (http://www.dibcom.fr/) - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * This code is partially based on the previous dib3000mc.c . * @@ -939,6 +939,6 @@ static struct dvb_frontend_ops dib3000mc_ops = { .read_ucblocks = dib3000mc_read_unc_blocks, }; -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for the DiBcom 3000MC/P COFDM demodulator"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib3000mc.h b/drivers/media/dvb-frontends/dib3000mc.h index 74816f793611..b37e69e6a58c 100644 --- a/drivers/media/dvb-frontends/dib3000mc.h +++ b/drivers/media/dvb-frontends/dib3000mc.h @@ -2,7 +2,7 @@ * Driver for DiBcom DiB3000MC/P-demodulator. * * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/) - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher\@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * This code is partially based on the previous dib3000mc.c . * diff --git a/drivers/media/dvb-frontends/dib7000m.c b/drivers/media/dvb-frontends/dib7000m.c index 35eb71fe3c2b..8b21cccf3c3a 100644 --- a/drivers/media/dvb-frontends/dib7000m.c +++ b/drivers/media/dvb-frontends/dib7000m.c @@ -1465,6 +1465,6 @@ static struct dvb_frontend_ops dib7000m_ops = { .read_ucblocks = dib7000m_read_unc_blocks, }; -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c index 33be5d6b9e10..65ab79ed5e3e 100644 --- a/drivers/media/dvb-frontends/dib7000p.c +++ b/drivers/media/dvb-frontends/dib7000p.c @@ -2834,7 +2834,7 @@ static struct dvb_frontend_ops dib7000p_ops = { .read_ucblocks = dib7000p_read_unc_blocks, }; -MODULE_AUTHOR("Olivier Grenie "); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Olivier Grenie "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index 94c26270fff0..349d2f1f62ce 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -4516,6 +4516,6 @@ void *dib8000_attach(struct dib8000_ops *ops) } EXPORT_SYMBOL(dib8000_attach); -MODULE_AUTHOR("Olivier Grenie "); +MODULE_AUTHOR("Olivier Grenie "); MODULE_DESCRIPTION("Driver for the DiBcom 8000 ISDB-T demodulator"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib9000.c b/drivers/media/dvb-frontends/dib9000.c index 8f92aca0b073..91888a2f5301 100644 --- a/drivers/media/dvb-frontends/dib9000.c +++ b/drivers/media/dvb-frontends/dib9000.c @@ -2589,7 +2589,7 @@ static struct dvb_frontend_ops dib9000_ops = { .read_ucblocks = dib9000_read_unc_blocks, }; -MODULE_AUTHOR("Patrick Boettcher "); -MODULE_AUTHOR("Olivier Grenie "); +MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Olivier Grenie "); MODULE_DESCRIPTION("Driver for the DiBcom 9000 COFDM demodulator"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dibx000_common.c b/drivers/media/dvb-frontends/dibx000_common.c index 43be7238311e..723358d7ca84 100644 --- a/drivers/media/dvb-frontends/dibx000_common.c +++ b/drivers/media/dvb-frontends/dibx000_common.c @@ -510,6 +510,6 @@ u32 systime(void) } EXPORT_SYMBOL(systime); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Common function the DiBcom demodulator family"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/pci/b2c2/flexcop-pci.c b/drivers/media/pci/b2c2/flexcop-pci.c index 8b5e0b3a92a0..4cac1fc233f2 100644 --- a/drivers/media/pci/b2c2/flexcop-pci.c +++ b/drivers/media/pci/b2c2/flexcop-pci.c @@ -39,7 +39,7 @@ MODULE_PARM_DESC(debug, #define DRIVER_VERSION "0.1" #define DRIVER_NAME "flexcop-pci" -#define DRIVER_AUTHOR "Patrick Boettcher " +#define DRIVER_AUTHOR "Patrick Boettcher " struct flexcop_pci { struct pci_dev *pdev; diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c index 0bd969063392..d4bdba60b0f7 100644 --- a/drivers/media/usb/b2c2/flexcop-usb.c +++ b/drivers/media/usb/b2c2/flexcop-usb.c @@ -10,7 +10,7 @@ /* Version information */ #define DRIVER_VERSION "0.1" #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV USB Driver" -#define DRIVER_AUTHOR "Patrick Boettcher " +#define DRIVER_AUTHOR "Patrick Boettcher " /* debug */ #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h index 023d91f7e654..35f27e2e4e28 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h @@ -1,7 +1,7 @@ /* * DVB USB framework * - * Copyright (C) 2004-6 Patrick Boettcher + * Copyright (C) 2004-6 Patrick Boettcher * Copyright (C) 2012 Antti Palosaari * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h b/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h index 45f07090d431..a1622bda2a5e 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h @@ -1,7 +1,7 @@ /* * DVB USB framework * - * Copyright (C) 2004-6 Patrick Boettcher + * Copyright (C) 2004-6 Patrick Boettcher * Copyright (C) 2012 Antti Palosaari * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index f0565bf3673e..5ec159f22399 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -1,7 +1,7 @@ /* * DVB USB framework * - * Copyright (C) 2004-6 Patrick Boettcher + * Copyright (C) 2004-6 Patrick Boettcher * Copyright (C) 2012 Antti Palosaari * * This program is free software; you can redistribute it and/or modify @@ -1129,7 +1129,7 @@ int dvb_usbv2_reset_resume(struct usb_interface *intf) EXPORT_SYMBOL(dvb_usbv2_reset_resume); MODULE_VERSION("2.0"); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_AUTHOR("Antti Palosaari "); MODULE_DESCRIPTION("DVB USB common"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c index 22bdce15ecf3..5bafeb6486be 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c @@ -1,7 +1,7 @@ /* * DVB USB framework * - * Copyright (C) 2004-6 Patrick Boettcher + * Copyright (C) 2004-6 Patrick Boettcher * Copyright (C) 2012 Antti Palosaari * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/usb/dvb-usb-v2/usb_urb.c b/drivers/media/usb/dvb-usb-v2/usb_urb.c index ca8f3c2b1082..55136cde38f5 100644 --- a/drivers/media/usb/dvb-usb-v2/usb_urb.c +++ b/drivers/media/usb/dvb-usb-v2/usb_urb.c @@ -1,6 +1,6 @@ /* usb-urb.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file keeps functions for initializing and handling the diff --git a/drivers/media/usb/dvb-usb/a800.c b/drivers/media/usb/dvb-usb/a800.c index 83684ed023cd..7ba975bea96a 100644 --- a/drivers/media/usb/dvb-usb/a800.c +++ b/drivers/media/usb/dvb-usb/a800.c @@ -1,7 +1,7 @@ /* DVB USB framework compliant Linux driver for the AVerMedia AverTV DVB-T * USB2.0 (A800) DVB-T receiver. * - * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de) * * Thanks to * - AVerMedia who kindly provided information and @@ -185,7 +185,7 @@ static struct usb_driver a800_driver = { module_usb_driver(a800_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("AVerMedia AverTV DVB-T USB 2.0 (A800)"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index ab7151181728..907ac01ae297 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c @@ -13,7 +13,7 @@ * * TODO: Use the cx25840-driver for the analogue part * - * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de) * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org) * Copyright (C) 2006, 2007 Chris Pascoe (c.pascoe@itee.uq.edu.au) * @@ -2314,7 +2314,7 @@ static struct usb_driver cxusb_driver = { module_usb_driver(cxusb_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_AUTHOR("Michael Krufky "); MODULE_AUTHOR("Chris Pascoe "); MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design"); diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index 0d248ce02a9b..c16f999b9d7c 100644 --- a/drivers/media/usb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c @@ -881,7 +881,7 @@ static struct usb_driver dib0700_driver = { module_usb_driver(dib0700_driver); MODULE_FIRMWARE("dvb-usb-dib0700-1.20.fw"); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for devices based on DiBcom DiB0700 - USB bridge"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dibusb-common.c b/drivers/media/usb/dvb-usb/dibusb-common.c index ef3a8f75f82e..35de6095926d 100644 --- a/drivers/media/usb/dvb-usb/dibusb-common.c +++ b/drivers/media/usb/dvb-usb/dibusb-common.c @@ -1,6 +1,6 @@ /* Common methods for dibusb-based-receivers. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 diff --git a/drivers/media/usb/dvb-usb/dibusb-mb.c b/drivers/media/usb/dvb-usb/dibusb-mb.c index a4ac37e0e98b..a0057641cc86 100644 --- a/drivers/media/usb/dvb-usb/dibusb-mb.c +++ b/drivers/media/usb/dvb-usb/dibusb-mb.c @@ -1,10 +1,10 @@ /* DVB USB compliant linux driver for mobile DVB-T USB devices based on * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-B) * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * based on GPL code from DiBcom, which has - * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) + * Copyright (C) 2004 Amaury Demol for DiBcom * * 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 @@ -465,7 +465,7 @@ static struct usb_driver dibusb_driver = { module_usb_driver(dibusb_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dibusb-mc.c b/drivers/media/usb/dvb-usb/dibusb-mc.c index 9d1a59d09c52..08fb8a3f6e0c 100644 --- a/drivers/media/usb/dvb-usb/dibusb-mc.c +++ b/drivers/media/usb/dvb-usb/dibusb-mc.c @@ -1,10 +1,10 @@ /* DVB USB compliant linux driver for mobile DVB-T USB devices based on * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-C/P) * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * based on GPL code from DiBcom, which has - * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) + * Copyright (C) 2004 Amaury Demol for DiBcom * * 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 @@ -143,7 +143,7 @@ static struct usb_driver dibusb_mc_driver = { module_usb_driver(dibusb_mc_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for DiBcom USB2.0 DVB-T (DiB3000M-C/P based) devices"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dibusb.h b/drivers/media/usb/dvb-usb/dibusb.h index 32ab1392313f..3f82163d8ab8 100644 --- a/drivers/media/usb/dvb-usb/dibusb.h +++ b/drivers/media/usb/dvb-usb/dibusb.h @@ -1,6 +1,6 @@ /* Header file for all dibusb-based-receivers. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 diff --git a/drivers/media/usb/dvb-usb/digitv.c b/drivers/media/usb/dvb-usb/digitv.c index 772bde3c5020..63134335c994 100644 --- a/drivers/media/usb/dvb-usb/digitv.c +++ b/drivers/media/usb/dvb-usb/digitv.c @@ -1,7 +1,7 @@ /* DVB USB compliant linux driver for Nebula Electronics uDigiTV DVB-T USB2.0 * receiver * - * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de) * * partly based on the SDK published by Nebula Electronics * @@ -348,7 +348,7 @@ static struct usb_driver digitv_driver = { module_usb_driver(digitv_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for Nebula Electronics uDigiTV DVB-T USB2.0"); MODULE_VERSION("1.0-alpha"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dtt200u-fe.c b/drivers/media/usb/dvb-usb/dtt200u-fe.c index 8637ad1be6be..7e72a1bef76a 100644 --- a/drivers/media/usb/dvb-usb/dtt200u-fe.c +++ b/drivers/media/usb/dvb-usb/dtt200u-fe.c @@ -1,7 +1,7 @@ /* Frontend part of the Linux driver for the WideView/ Yakumo/ Hama/ * Typhoon/ Yuan DVB-T USB2.0 receiver. * - * Copyright (C) 2005 Patrick Boettcher + * Copyright (C) 2005 Patrick Boettcher * * 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 diff --git a/drivers/media/usb/dvb-usb/dtt200u.c b/drivers/media/usb/dvb-usb/dtt200u.c index c357fb3b0a88..ca3b69aa9688 100644 --- a/drivers/media/usb/dvb-usb/dtt200u.c +++ b/drivers/media/usb/dvb-usb/dtt200u.c @@ -1,7 +1,7 @@ /* DVB USB library compliant Linux driver for the WideView/ Yakumo/ Hama/ * Typhoon/ Yuan/ Miglia DVB-T USB2.0 receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * Thanks to Steve Chang from WideView for providing support for the WT-220U. * @@ -362,7 +362,7 @@ static struct usb_driver dtt200u_usb_driver = { module_usb_driver(dtt200u_usb_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D/Miglia DVB-T USB2.0 devices"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dtt200u.h b/drivers/media/usb/dvb-usb/dtt200u.h index 005b0a7df358..efccc399b1cb 100644 --- a/drivers/media/usb/dvb-usb/dtt200u.h +++ b/drivers/media/usb/dvb-usb/dtt200u.h @@ -1,7 +1,7 @@ /* Common header file of Linux driver for the WideView/ Yakumo/ Hama/ * Typhoon/ Yuan DVB-T USB2.0 receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 diff --git a/drivers/media/usb/dvb-usb/dvb-usb-common.h b/drivers/media/usb/dvb-usb/dvb-usb-common.h index 6b7b2a89242e..7e619d638809 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-common.h +++ b/drivers/media/usb/dvb-usb/dvb-usb-common.h @@ -1,6 +1,6 @@ /* dvb-usb-common.h is part of the DVB USB library. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * a header file containing prototypes and types for internal use of the dvb-usb-lib diff --git a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c index 9ddfcab268be..71de19ba0e01 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c @@ -1,6 +1,6 @@ /* dvb-usb-dvb.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file contains functions for initializing and handling the diff --git a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c index 733a7ff7b207..dd048a7c461c 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c @@ -1,6 +1,6 @@ /* dvb-usb-firmware.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file contains functions for downloading the firmware to Cypress FX 1 and 2 based devices. diff --git a/drivers/media/usb/dvb-usb/dvb-usb-i2c.c b/drivers/media/usb/dvb-usb/dvb-usb-i2c.c index 88e4a62abc44..4f0b0adce7f5 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-i2c.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-i2c.c @@ -1,6 +1,6 @@ /* dvb-usb-i2c.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file contains functions for (de-)initializing an I2C adapter. diff --git a/drivers/media/usb/dvb-usb/dvb-usb-init.c b/drivers/media/usb/dvb-usb/dvb-usb-init.c index 1adf325012f7..3896ba9a4179 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-init.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-init.c @@ -3,7 +3,7 @@ * * dvb-usb-init.c * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 @@ -299,6 +299,6 @@ void dvb_usb_device_exit(struct usb_interface *intf) EXPORT_SYMBOL(dvb_usb_device_exit); MODULE_VERSION("1.0"); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dvb-usb-remote.c b/drivers/media/usb/dvb-usb/dvb-usb-remote.c index 7b5dae3077f6..c259f9e43542 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c @@ -1,6 +1,6 @@ /* dvb-usb-remote.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file contains functions for initializing the input-device and for handling remote-control-queries. diff --git a/drivers/media/usb/dvb-usb/dvb-usb-urb.c b/drivers/media/usb/dvb-usb/dvb-usb-urb.c index 5c8f651344fc..95f9097498cb 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-urb.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-urb.c @@ -1,6 +1,6 @@ /* dvb-usb-urb.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file keeps functions for initializing and handling the diff --git a/drivers/media/usb/dvb-usb/dvb-usb.h b/drivers/media/usb/dvb-usb/dvb-usb.h index ce4c4e3b58bb..639c4678c65b 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb.h +++ b/drivers/media/usb/dvb-usb/dvb-usb.h @@ -1,6 +1,6 @@ /* dvb-usb.h is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * the headerfile, all dvb-usb-drivers have to include. diff --git a/drivers/media/usb/dvb-usb/nova-t-usb2.c b/drivers/media/usb/dvb-usb/nova-t-usb2.c index 6c55384e2fca..fc7569e2728d 100644 --- a/drivers/media/usb/dvb-usb/nova-t-usb2.c +++ b/drivers/media/usb/dvb-usb/nova-t-usb2.c @@ -1,7 +1,7 @@ /* DVB USB framework compliant Linux driver for the Hauppauge WinTV-NOVA-T usb2 * DVB-T receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 @@ -227,7 +227,7 @@ static struct usb_driver nova_t_driver = { module_usb_driver(nova_t_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Hauppauge WinTV-NOVA-T usb2"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/ttusb2.c b/drivers/media/usb/dvb-usb/ttusb2.c index f10717311e05..ecc207fbaf3c 100644 --- a/drivers/media/usb/dvb-usb/ttusb2.c +++ b/drivers/media/usb/dvb-usb/ttusb2.c @@ -820,7 +820,7 @@ static struct usb_driver ttusb2_driver = { module_usb_driver(ttusb2_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/umt-010.c b/drivers/media/usb/dvb-usb/umt-010.c index 9b042292e788..58ad5b4f856c 100644 --- a/drivers/media/usb/dvb-usb/umt-010.c +++ b/drivers/media/usb/dvb-usb/umt-010.c @@ -1,7 +1,7 @@ /* DVB USB framework compliant Linux driver for the HanfTek UMT-010 USB2.0 * DVB-T receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 @@ -145,7 +145,7 @@ static struct usb_driver umt_driver = { module_usb_driver(umt_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for HanfTek UMT 010 USB2.0 DVB-T device"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/usb-urb.c b/drivers/media/usb/dvb-usb/usb-urb.c index d62ee0f5a165..89173603be67 100644 --- a/drivers/media/usb/dvb-usb/usb-urb.c +++ b/drivers/media/usb/dvb-usb/usb-urb.c @@ -1,6 +1,6 @@ /* usb-urb.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file keeps functions for initializing and handling the diff --git a/drivers/media/usb/dvb-usb/vp702x-fe.c b/drivers/media/usb/dvb-usb/vp702x-fe.c index d361a72ca0fa..27398c08c69d 100644 --- a/drivers/media/usb/dvb-usb/vp702x-fe.c +++ b/drivers/media/usb/dvb-usb/vp702x-fe.c @@ -4,7 +4,7 @@ * Copyright (C) 2005 Ralph Metzler * Metzler Brothers Systementwicklung GbR * - * Copyright (C) 2005 Patrick Boettcher + * Copyright (C) 2005 Patrick Boettcher * * Thanks to Twinhan who kindly provided hardware and information. * diff --git a/drivers/media/usb/dvb-usb/vp702x.c b/drivers/media/usb/dvb-usb/vp702x.c index ee1e19e36445..40de33de90a7 100644 --- a/drivers/media/usb/dvb-usb/vp702x.c +++ b/drivers/media/usb/dvb-usb/vp702x.c @@ -4,7 +4,7 @@ * Copyright (C) 2005 Ralph Metzler * Metzler Brothers Systementwicklung GbR * - * Copyright (C) 2005 Patrick Boettcher + * Copyright (C) 2005 Patrick Boettcher * * Thanks to Twinhan who kindly provided hardware and information. * @@ -439,7 +439,7 @@ static struct usb_driver vp702x_usb_driver = { module_usb_driver(vp702x_usb_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for Twinhan StarBox DVB-S USB2.0 and clones"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/vp7045-fe.c b/drivers/media/usb/dvb-usb/vp7045-fe.c index e708afc6a57f..7765602ea658 100644 --- a/drivers/media/usb/dvb-usb/vp7045-fe.c +++ b/drivers/media/usb/dvb-usb/vp7045-fe.c @@ -1,7 +1,7 @@ /* DVB frontend part of the Linux driver for TwinhanDTV Alpha/MagicBoxII USB2.0 * DVB-T receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * Thanks to Twinhan who kindly provided hardware and information. * diff --git a/drivers/media/usb/dvb-usb/vp7045.c b/drivers/media/usb/dvb-usb/vp7045.c index d750724132ee..13340af0d39c 100644 --- a/drivers/media/usb/dvb-usb/vp7045.c +++ b/drivers/media/usb/dvb-usb/vp7045.c @@ -2,7 +2,7 @@ * - TwinhanDTV Alpha/MagicBoxII USB2.0 DVB-T receiver * - DigitalNow TinyUSB2 DVB-t receiver * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * Thanks to Twinhan who kindly provided hardware and information. * @@ -296,7 +296,7 @@ static struct usb_driver vp7045_usb_driver = { module_usb_driver(vp7045_usb_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for Twinhan MagicBox/Alpha and DNTV tinyUSB2 DVB-T USB2.0"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/vp7045.h b/drivers/media/usb/dvb-usb/vp7045.h index cf5ec46f8bb1..66499932ca76 100644 --- a/drivers/media/usb/dvb-usb/vp7045.h +++ b/drivers/media/usb/dvb-usb/vp7045.h @@ -1,7 +1,7 @@ /* Common header-file of the Linux driver for the TwinhanDTV Alpha/MagicBoxII * USB2.0 DVB-T receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * Thanks to Twinhan who kindly provided hardware and information. * -- cgit v1.2.3 From 8c20b67f2873bffb37cb64b806af0aca0212dae4 Mon Sep 17 00:00:00 2001 From: zhangqing Date: Mon, 11 Jan 2016 02:36:39 -0800 Subject: soc: rockchip: power-domain: Modify power domain driver for rk3368 This driver is modified to support RK3368 SoC. Signed-off-by: zhangqing Reviewed-by: Caesar Wang Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/pm_domains.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 534c58937a56..6cdffb13c862 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -18,6 +18,7 @@ #include #include #include +#include struct rockchip_domain_info { int pwr_mask; @@ -75,6 +76,9 @@ struct rockchip_pmu { #define DOMAIN_RK3288(pwr, status, req) \ DOMAIN(pwr, status, req, req, (req) + 16) +#define DOMAIN_RK3368(pwr, status, req) \ + DOMAIN(pwr, status, req, (req) + 16, req) + static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd) { struct rockchip_pmu *pmu = pd->pmu; @@ -444,6 +448,14 @@ static const struct rockchip_domain_info rk3288_pm_domains[] = { [RK3288_PD_GPU] = DOMAIN_RK3288(9, 9, 2), }; +static const struct rockchip_domain_info rk3368_pm_domains[] = { + [RK3368_PD_PERI] = DOMAIN_RK3368(13, 12, 6), + [RK3368_PD_VIO] = DOMAIN_RK3368(15, 14, 8), + [RK3368_PD_VIDEO] = DOMAIN_RK3368(14, 13, 7), + [RK3368_PD_GPU_0] = DOMAIN_RK3368(16, 15, 2), + [RK3368_PD_GPU_1] = DOMAIN_RK3368(17, 16, 2), +}; + static const struct rockchip_pmu_info rk3288_pmu = { .pwr_offset = 0x08, .status_offset = 0x0c, @@ -461,11 +473,32 @@ static const struct rockchip_pmu_info rk3288_pmu = { .domain_info = rk3288_pm_domains, }; +static const struct rockchip_pmu_info rk3368_pmu = { + .pwr_offset = 0x0c, + .status_offset = 0x10, + .req_offset = 0x3c, + .idle_offset = 0x40, + .ack_offset = 0x40, + + .core_pwrcnt_offset = 0x48, + .gpu_pwrcnt_offset = 0x50, + + .core_power_transition_time = 24, + .gpu_power_transition_time = 24, + + .num_domains = ARRAY_SIZE(rk3368_pm_domains), + .domain_info = rk3368_pm_domains, +}; + static const struct of_device_id rockchip_pm_domain_dt_match[] = { { .compatible = "rockchip,rk3288-power-controller", .data = (void *)&rk3288_pmu, }, + { + .compatible = "rockchip,rk3368-power-controller", + .data = (void *)&rk3368_pmu, + }, { /* sentinel */ }, }; -- cgit v1.2.3 From 91be260faaf8561dc51e72033c346f6ab28d40d8 Mon Sep 17 00:00:00 2001 From: Nicolas Sugino Date: Thu, 26 Nov 2015 19:00:28 -0200 Subject: [media] dib8000: Add support for Mygica/Geniatech S2870 MyGica/Geniatech S2870 is very similar to the S870 but with dual tuner. The card is recognised as Geniatech STK8096-PVR. [mchehab@osg.samsung.com: Fix some checkpatch.pl issues] Signed-off-by: Nicolas Sugino Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb-usb-ids.h | 1 + drivers/media/usb/dvb-usb/dib0700_devices.c | 77 ++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 474582231b5d..7f5d0865acfd 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h @@ -118,6 +118,7 @@ #define USB_PID_DIBCOM_STK807XP 0x1f90 #define USB_PID_DIBCOM_STK807XPVR 0x1f98 #define USB_PID_DIBCOM_STK8096GP 0x1fa0 +#define USB_PID_DIBCOM_STK8096PVR 0x1faa #define USB_PID_DIBCOM_NIM8096MD 0x1fa8 #define USB_PID_DIBCOM_TFE8096P 0x1f9C #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c index 7ed49646a699..ea0391e32d23 100644 --- a/drivers/media/usb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c @@ -1736,8 +1736,13 @@ static int dib809x_tuner_attach(struct dvb_usb_adapter *adap) struct dib0700_adapter_state *st = adap->priv; struct i2c_adapter *tun_i2c = st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1); - if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL) - return -ENODEV; + if (adap->id == 0) { + if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL) + return -ENODEV; + } else { + if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL) + return -ENODEV; + } st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096_set_param_override; @@ -1773,6 +1778,20 @@ static int stk809x_frontend_attach(struct dvb_usb_adapter *adap) return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; } +static int stk809x_frontend1_attach(struct dvb_usb_adapter *adap) +{ + struct dib0700_adapter_state *state = adap->priv; + + if (!dvb_attach(dib8000_attach, &state->dib8000_ops)) + return -ENODEV; + + state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x82, 0); + + adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]); + + return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; +} + static int nim8096md_tuner_attach(struct dvb_usb_adapter *adap) { struct dib0700_adapter_state *st = adap->priv; @@ -3794,6 +3813,7 @@ struct usb_device_id dib0700_usb_id_table[] = { /* 80 */{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT_2) }, { USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_2002E) }, { USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_2002E_SE) }, + { USB_DEVICE(USB_VID_PCTV, USB_PID_DIBCOM_STK8096PVR) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -4959,6 +4979,59 @@ struct dvb_usb_device_properties dib0700_devices[] = { RC_BIT_NEC, .change_protocol = dib0700_change_protocol, }, + }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, + .num_adapters = 2, + .adapter = { + { + .num_frontends = 1, + .fe = {{ + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk80xx_pid_filter, + .pid_filter_ctrl = stk80xx_pid_filter_ctrl, + .frontend_attach = stk809x_frontend_attach, + .tuner_attach = dib809x_tuner_attach, + + DIB0700_DEFAULT_STREAMING_CONFIG(0x02), + } }, + .size_of_priv = + sizeof(struct dib0700_adapter_state), + }, { + .num_frontends = 1, + .fe = { { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk80xx_pid_filter, + .pid_filter_ctrl = stk80xx_pid_filter_ctrl, + .frontend_attach = stk809x_frontend1_attach, + .tuner_attach = dib809x_tuner_attach, + + DIB0700_DEFAULT_STREAMING_CONFIG(0x03), + } }, + .size_of_priv = + sizeof(struct dib0700_adapter_state), + }, + }, + .num_device_descs = 1, + .devices = { + { "DiBcom STK8096-PVR reference design", + { &dib0700_usb_id_table[83], NULL }, + { NULL }, + }, + }, + + .rc.core = { + .rc_interval = DEFAULT_RC_INTERVAL, + .rc_codes = RC_MAP_DIB0700_RC5_TABLE, + .module_name = "dib0700", + .rc_query = dib0700_rc_query_old_firmware, + .allowed_protos = RC_BIT_RC5 | + RC_BIT_RC6_MCE | + RC_BIT_NEC, + .change_protocol = dib0700_change_protocol, + }, }, }; -- cgit v1.2.3 From 33cb54015f5eebceb360443498430bdfab79778c Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 27 Nov 2015 19:38:44 -0200 Subject: [media] media: rc: nuvoton: mark wakeup-related resources When requesting resources use different names for the normal and the wakeup part. This makes it easier to interpret the output of e.g. /proc/interrupts and /proc/ioports. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 18adf580f502..081435cda30c 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -1079,12 +1079,12 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) goto exit_unregister_device; if (!devm_request_region(&pdev->dev, nvt->cir_wake_addr, - CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) + CIR_IOREG_LENGTH, NVT_DRIVER_NAME "-wake")) goto exit_unregister_device; if (devm_request_irq(&pdev->dev, nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED, - NVT_DRIVER_NAME, (void *)nvt)) + NVT_DRIVER_NAME "-wake", (void *)nvt)) goto exit_unregister_device; device_init_wakeup(&pdev->dev, true); -- cgit v1.2.3 From 464254e5dbd60124936d47be6679a23b42840b51 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 27 Nov 2015 20:02:38 -0200 Subject: [media] media: rc: raw: improve FIFO handling The FIFO is used for ir_raw_event records, however for some historic reason the FIFO is used on a per byte basis. IMHO this adds unneeded complexity. Therefore set up the FIFO for ir_raw_event records. This also allows to define the FIFO statically as part of ir_raw_event_ctrl instead of having to allocate the FIFO dynamically. In addition: - When writing into the FIFO and it's full return ENOSPC instead of ENOMEM thus making it easier to tell between "FIFO full" and "Dynamic memory allocation failed" when the error is propagated to a higher level. Also add an error message. - When reading from the FIFO check whether it's empty. This is not strictly needed here but kfifo_out is annotated "must check" anyway. Successfully tested it with the nuvoton-cir driver. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/rc-core-priv.h | 6 +++++- drivers/media/rc/rc-ir-raw.c | 23 ++++++++--------------- 2 files changed, 13 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index 7359f3d03b64..585d5e52118d 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -16,6 +16,9 @@ #ifndef _RC_CORE_PRIV #define _RC_CORE_PRIV +/* Define the max number of pulse/space transitions to buffer */ +#define MAX_IR_EVENT_SIZE 512 + #include #include #include @@ -35,7 +38,8 @@ struct ir_raw_event_ctrl { struct list_head list; /* to keep track of raw clients */ struct task_struct *thread; spinlock_t lock; - struct kfifo_rec_ptr_1 kfifo; /* fifo for the pulse/space durations */ + /* fifo for the pulse/space durations */ + DECLARE_KFIFO(kfifo, struct ir_raw_event, MAX_IR_EVENT_SIZE); ktime_t last_event; /* when last event occurred */ enum raw_event_type last_type; /* last event type */ struct rc_dev *dev; /* pointer to the parent rc_dev */ diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c index c69807fe2fef..144304c94606 100644 --- a/drivers/media/rc/rc-ir-raw.c +++ b/drivers/media/rc/rc-ir-raw.c @@ -20,9 +20,6 @@ #include #include "rc-core-priv.h" -/* Define the max number of pulse/space transitions to buffer */ -#define MAX_IR_EVENT_SIZE 512 - /* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */ static LIST_HEAD(ir_raw_client_list); @@ -36,14 +33,12 @@ static int ir_raw_event_thread(void *data) struct ir_raw_event ev; struct ir_raw_handler *handler; struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; - int retval; while (!kthread_should_stop()) { spin_lock_irq(&raw->lock); - retval = kfifo_len(&raw->kfifo); - if (retval < sizeof(ev)) { + if (!kfifo_len(&raw->kfifo)) { set_current_state(TASK_INTERRUPTIBLE); if (kthread_should_stop()) @@ -54,7 +49,8 @@ static int ir_raw_event_thread(void *data) continue; } - retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev)); + if(!kfifo_out(&raw->kfifo, &ev, 1)) + dev_err(&raw->dev->dev, "IR event FIFO is empty!\n"); spin_unlock_irq(&raw->lock); mutex_lock(&ir_raw_handler_lock); @@ -87,8 +83,10 @@ int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev) IR_dprintk(2, "sample: (%05dus %s)\n", TO_US(ev->duration), TO_STR(ev->pulse)); - if (kfifo_in(&dev->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) - return -ENOMEM; + if (!kfifo_put(&dev->raw->kfifo, *ev)) { + dev_err(&dev->dev, "IR event FIFO is full!\n"); + return -ENOSPC; + } return 0; } @@ -273,11 +271,7 @@ int ir_raw_event_register(struct rc_dev *dev) dev->raw->dev = dev; dev->change_protocol = change_protocol; - rc = kfifo_alloc(&dev->raw->kfifo, - sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE, - GFP_KERNEL); - if (rc < 0) - goto out; + INIT_KFIFO(dev->raw->kfifo); spin_lock_init(&dev->raw->lock); dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw, @@ -319,7 +313,6 @@ void ir_raw_event_unregister(struct rc_dev *dev) handler->raw_unregister(dev); mutex_unlock(&ir_raw_handler_lock); - kfifo_free(&dev->raw->kfifo); kfree(dev->raw); dev->raw = NULL; } -- cgit v1.2.3 From a2f5106f0de9ca684b8f6daef49cb1236035712e Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Tue, 5 Jan 2016 11:14:55 -0800 Subject: crypto: qat - change name for c6xx dev type change name for c6x dev type to more generic. Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/adf_accel_devices.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/qat/qat_common/adf_accel_devices.h b/drivers/crypto/qat/qat_common/adf_accel_devices.h index f96d427e502c..5a07208ce778 100644 --- a/drivers/crypto/qat/qat_common/adf_accel_devices.h +++ b/drivers/crypto/qat/qat_common/adf_accel_devices.h @@ -55,8 +55,8 @@ #define ADF_DH895XCC_DEVICE_NAME "dh895xcc" #define ADF_DH895XCCVF_DEVICE_NAME "dh895xccvf" -#define ADF_C62X_DEVICE_NAME "c62x" -#define ADF_C62XVF_DEVICE_NAME "c62xvf" +#define ADF_C62X_DEVICE_NAME "c6xx" +#define ADF_C62XVF_DEVICE_NAME "c6xxvf" #define ADF_C3XXX_DEVICE_NAME "c3xxx" #define ADF_C3XXXVF_DEVICE_NAME "c3xxxvf" #define ADF_DH895XCC_PCI_DEVICE_ID 0x435 -- cgit v1.2.3 From 718837c88bf76e3374fc5a3e2b85cd88d1fc2edb Mon Sep 17 00:00:00 2001 From: Pingchao Yang Date: Wed, 6 Jan 2016 17:56:20 +0800 Subject: crypto: qat - remove redundant function call adf_dev_restore(accel_dev) was called in adf_dev_shutdown,no need to call it in adf_device_reset_worker after adf_dev_shutdown was called. Signed-off-by: Yang Pingchao Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/adf_aer.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/crypto/qat/qat_common/adf_aer.c b/drivers/crypto/qat/qat_common/adf_aer.c index e78a1d7d88fc..b40d9c8dad96 100644 --- a/drivers/crypto/qat/qat_common/adf_aer.c +++ b/drivers/crypto/qat/qat_common/adf_aer.c @@ -121,7 +121,6 @@ static void adf_device_reset_worker(struct work_struct *work) adf_dev_restarting_notify(accel_dev); adf_dev_stop(accel_dev); adf_dev_shutdown(accel_dev); - adf_dev_restore(accel_dev); if (adf_dev_init(accel_dev) || adf_dev_start(accel_dev)) { /* The device hanged and we can't restart it so stop here */ dev_err(&GET_DEV(accel_dev), "Restart device failed\n"); -- cgit v1.2.3 From 313becd1ff0eebcc3ee6e6d7e00b3da2f980bb18 Mon Sep 17 00:00:00 2001 From: Krzysztof Koz?owski Date: Mon, 11 Jan 2016 20:45:50 +0900 Subject: crypto: s5p-sss - Fix minor coding style violations Improve a little bit code readability and use dev_info/err for printing messages. Signed-off-by: Krzysztof Kozlowski Acked-by: Vladimir Zapolskiy Signed-off-by: Herbert Xu --- drivers/crypto/s5p-sss.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index f214a8755827..e10284744fd2 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c @@ -224,6 +224,7 @@ static inline struct samsung_aes_variant *find_s5p_sss_version { if (IS_ENABLED(CONFIG_OF) && (pdev->dev.of_node)) { const struct of_device_id *match; + match = of_match_node(s5p_sss_dt_match, pdev->dev.of_node); return (struct samsung_aes_variant *)match->data; @@ -397,7 +398,6 @@ static void s5p_set_aes(struct s5p_aes_dev *dev, static void s5p_aes_crypt_start(struct s5p_aes_dev *dev, unsigned long mode) { struct ablkcipher_request *req = dev->req; - uint32_t aes_control; int err; unsigned long flags; @@ -518,7 +518,7 @@ static int s5p_aes_crypt(struct ablkcipher_request *req, unsigned long mode) struct s5p_aes_dev *dev = ctx->dev; if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) { - pr_err("request size is not exact amount of AES blocks\n"); + dev_err(dev->dev, "request size is not exact amount of AES blocks\n"); return -EINVAL; } @@ -566,7 +566,7 @@ static int s5p_aes_cbc_decrypt(struct ablkcipher_request *req) static int s5p_aes_cra_init(struct crypto_tfm *tfm) { - struct s5p_aes_ctx *ctx = crypto_tfm_ctx(tfm); + struct s5p_aes_ctx *ctx = crypto_tfm_ctx(tfm); ctx->dev = s5p_dev; tfm->crt_ablkcipher.reqsize = sizeof(struct s5p_aes_reqctx); @@ -701,7 +701,7 @@ static int s5p_aes_probe(struct platform_device *pdev) goto err_algs; } - pr_info("s5p-sss driver registered\n"); + dev_info(dev, "s5p-sss driver registered\n"); return 0; -- cgit v1.2.3 From 1e3012d0fdc5e06309c3031e0989a4b564504713 Mon Sep 17 00:00:00 2001 From: Krzysztof Koz?owski Date: Mon, 11 Jan 2016 20:45:51 +0900 Subject: crypto: s5p-sss - Use memcpy_toio for iomem annotated memory Use memcpy_toio to fix following sparse warning: drivers/crypto/s5p-sss.c:386:40: warning: incorrect type in argument 1 (different address spaces) drivers/crypto/s5p-sss.c:386:40: expected void * drivers/crypto/s5p-sss.c:386:40: got void [noderef] * Signed-off-by: Krzysztof Kozlowski Acked-by: Vladimir Zapolskiy Signed-off-by: Herbert Xu --- drivers/crypto/s5p-sss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index e10284744fd2..5f161a9777e3 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c @@ -383,7 +383,7 @@ static void s5p_set_aes(struct s5p_aes_dev *dev, void __iomem *keystart; if (iv) - memcpy(dev->aes_ioaddr + SSS_REG_AES_IV_DATA(0), iv, 0x10); + memcpy_toio(dev->aes_ioaddr + SSS_REG_AES_IV_DATA(0), iv, 0x10); if (keylen == AES_KEYSIZE_256) keystart = dev->aes_ioaddr + SSS_REG_AES_KEY_DATA(0); @@ -392,7 +392,7 @@ static void s5p_set_aes(struct s5p_aes_dev *dev, else keystart = dev->aes_ioaddr + SSS_REG_AES_KEY_DATA(4); - memcpy(keystart, key, keylen); + memcpy_toio(keystart, key, keylen); } static void s5p_aes_crypt_start(struct s5p_aes_dev *dev, unsigned long mode) -- cgit v1.2.3 From ba171135bfa584096ca5ee42c9527777b7d48474 Mon Sep 17 00:00:00 2001 From: "Atta, Ahsan" Date: Mon, 11 Jan 2016 15:23:47 +0000 Subject: crypto: qat - Pack cfg ctl structs -This is required to support 32bit adf_ctl utility on a 64bit driver Signed-off-by: Ahsan Atta Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/adf_cfg_user.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/qat/qat_common/adf_cfg_user.h b/drivers/crypto/qat/qat_common/adf_cfg_user.h index ef5988afd4c6..b5484bfa6996 100644 --- a/drivers/crypto/qat/qat_common/adf_cfg_user.h +++ b/drivers/crypto/qat/qat_common/adf_cfg_user.h @@ -58,7 +58,7 @@ struct adf_user_cfg_key_val { uint64_t padding3; }; enum adf_cfg_val_type type; -}; +} __packed; struct adf_user_cfg_section { char name[ADF_CFG_MAX_SECTION_LEN_IN_BYTES]; @@ -70,7 +70,7 @@ struct adf_user_cfg_section { struct adf_user_cfg_section *next; uint64_t padding3; }; -}; +} __packed; struct adf_user_cfg_ctl_data { union { @@ -78,5 +78,5 @@ struct adf_user_cfg_ctl_data { uint64_t padding; }; uint8_t device_id; -}; +} __packed; #endif -- cgit v1.2.3 From 624144a7eb2c9abcf76722d29f983cdf9801bb2e Mon Sep 17 00:00:00 2001 From: Horia Geant? Date: Tue, 12 Jan 2016 17:14:10 +0200 Subject: crypto: caam - enable LARGE_BURST for enhancing DMA transactions size Increasing CAAM DMA engine transaction size either -reduces the number of required transactions or -adds the ability to transfer more data with same transaction count Signed-off-by: Horia Geant? Signed-off-by: Herbert Xu --- drivers/crypto/caam/ctrl.c | 2 +- drivers/crypto/caam/regs.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index 69d4a1326fee..44d30b45f3cc 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -534,7 +534,7 @@ static int caam_probe(struct platform_device *pdev) * long pointers in master configuration register */ clrsetbits_32(&ctrl->mcr, MCFGR_AWCACHE_MASK, MCFGR_AWCACHE_CACH | - MCFGR_AWCACHE_BUFF | MCFGR_WDENABLE | + MCFGR_AWCACHE_BUFF | MCFGR_WDENABLE | MCFGR_LARGE_BURST | (sizeof(dma_addr_t) == sizeof(u64) ? MCFGR_LONG_PTR : 0)); /* diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h index a8a79975682f..0ba9c40597dc 100644 --- a/drivers/crypto/caam/regs.h +++ b/drivers/crypto/caam/regs.h @@ -455,7 +455,8 @@ struct caam_ctrl { #define MCFGR_AXIPIPE_MASK (0xf << MCFGR_AXIPIPE_SHIFT) #define MCFGR_AXIPRI 0x00000008 /* Assert AXI priority sideband */ -#define MCFGR_BURST_64 0x00000001 /* Max burst size */ +#define MCFGR_LARGE_BURST 0x00000004 /* 128/256-byte burst size */ +#define MCFGR_BURST_64 0x00000001 /* 64-byte burst size */ /* JRSTART register offsets */ #define JRSTART_JR0_START 0x00000001 /* Start Job ring 0 */ -- cgit v1.2.3 From 952bce9792e6bf36fda09c2e5718abb5d9327369 Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Tue, 12 Jan 2016 11:17:38 -0600 Subject: crypto: ccp - Add hash state import and export support Commit 8996eafdcbad ("crypto: ahash - ensure statesize is non-zero") added a check to prevent ahash algorithms from successfully registering if the import and export functions were not implemented. This prevents an oops in the hash_accept function of algif_hash. This commit causes the ccp-crypto module SHA support and AES CMAC support from successfully registering and causing the ccp-crypto module load to fail because the ahash import and export functions are not implemented. Update the CCP Crypto API support to provide import and export support for ahash algorithms. Cc: # 3.14.x- Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto-aes-cmac.c | 23 +++++++++++++++++++++++ drivers/crypto/ccp/ccp-crypto-sha.c | 23 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) (limited to 'drivers') diff --git a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c index d89f20c04266..00207cf5c79b 100644 --- a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c +++ b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c @@ -220,6 +220,26 @@ static int ccp_aes_cmac_digest(struct ahash_request *req) return ccp_aes_cmac_finup(req); } +static int ccp_aes_cmac_export(struct ahash_request *req, void *out) +{ + struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); + struct ccp_aes_cmac_req_ctx *state = out; + + *state = *rctx; + + return 0; +} + +static int ccp_aes_cmac_import(struct ahash_request *req, const void *in) +{ + struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); + const struct ccp_aes_cmac_req_ctx *state = in; + + *rctx = *state; + + return 0; +} + static int ccp_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, unsigned int key_len) { @@ -352,10 +372,13 @@ int ccp_register_aes_cmac_algs(struct list_head *head) alg->final = ccp_aes_cmac_final; alg->finup = ccp_aes_cmac_finup; alg->digest = ccp_aes_cmac_digest; + alg->export = ccp_aes_cmac_export; + alg->import = ccp_aes_cmac_import; alg->setkey = ccp_aes_cmac_setkey; halg = &alg->halg; halg->digestsize = AES_BLOCK_SIZE; + halg->statesize = sizeof(struct ccp_aes_cmac_req_ctx); base = &halg->base; snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "cmac(aes)"); diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c index d14b3f28e010..3aae58def106 100644 --- a/drivers/crypto/ccp/ccp-crypto-sha.c +++ b/drivers/crypto/ccp/ccp-crypto-sha.c @@ -207,6 +207,26 @@ static int ccp_sha_digest(struct ahash_request *req) return ccp_sha_finup(req); } +static int ccp_sha_export(struct ahash_request *req, void *out) +{ + struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); + struct ccp_sha_req_ctx *state = out; + + *state = *rctx; + + return 0; +} + +static int ccp_sha_import(struct ahash_request *req, const void *in) +{ + struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); + const struct ccp_sha_req_ctx *state = in; + + *rctx = *state; + + return 0; +} + static int ccp_sha_setkey(struct crypto_ahash *tfm, const u8 *key, unsigned int key_len) { @@ -403,9 +423,12 @@ static int ccp_register_sha_alg(struct list_head *head, alg->final = ccp_sha_final; alg->finup = ccp_sha_finup; alg->digest = ccp_sha_digest; + alg->export = ccp_sha_export; + alg->import = ccp_sha_import; halg = &alg->halg; halg->digestsize = def->digest_size; + halg->statesize = sizeof(struct ccp_sha_req_ctx); base = &halg->base; snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); -- cgit v1.2.3 From 1900c583c8e24df9d07282598166279187dce832 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Fri, 15 Jan 2016 15:49:31 +0100 Subject: crypto: atmel-sha - fix crash when computing digest on empty message This patch fixes a crash which occured during the computation of the digest of an empty message. Indeed, when processing an empty message, the atmel_sha_handle_queue() function was never called, hence the dd->req pointer remained uninitialized. Later, when the atmel_sha_final_req() function was called, it used to crash while using this uninitialized dd->req pointer. Hence this patch adds missing initializations of dd->req before calls of the atmel_sha_final_req() function. This bug prevented us from passing the tcrypt test suite on SHA algo. Signed-off-by: Cyrille Pitchen Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 20de861aa0ea..006b2aefba30 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -939,6 +939,7 @@ static int atmel_sha_final(struct ahash_request *req) if (err) goto err1; + dd->req = req; dd->flags |= SHA_FLAGS_BUSY; err = atmel_sha_final_req(dd); } else { -- cgit v1.2.3 From f56809c3c6059327aad3e0718bca9c6c756386f6 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Fri, 15 Jan 2016 15:49:32 +0100 Subject: crypto: atmel-sha - fix a race between the 'done' tasklet and the crypto client The 'done' tasklet handler used to check the 'BUSY' flag to either finalize the processing of a crypto request which had just completed or manage the crypto queue to start the next crypto request. On request R1 completion, the driver calls atmel_sha_finish_req(), which: 1 - clears the 'BUSY' flag since the hardware is no longer used and is ready again to process new crypto requests. 2 - notifies the above layer (the client) about the completion of the asynchronous crypto request R1 by calling its base.complete() callback. 3 - schedules the 'done' task to check the crypto queue and start to process the next crypto request (the 'BUSY' flag is supposed to be cleared at that moment) if such a pending request exists. However step 2 might wake the client up so it can now ask our driver to process a new crypto request R2. This request is enqueued by calling the atmel_sha_handle_queue() function, which sets the 'BUSY' flags then starts to process R2. If the 'done' tasklet, scheduled by step 3, runs just after, it would see that the 'BUSY' flag is set then understand that R2 has just completed, which is wrong! So the state of 'BUSY' flag is not a proper way to detect and handle crypto request completion. This patch fixes this race condition by using two different tasklets, one to handle the crypto request completion events, the other to manage the crypto queue if needed. Signed-off-by: Cyrille Pitchen Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 006b2aefba30..75a8cbcf3121 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -122,6 +122,7 @@ struct atmel_sha_dev { spinlock_t lock; int err; struct tasklet_struct done_task; + struct tasklet_struct queue_task; unsigned long flags; struct crypto_queue queue; @@ -788,7 +789,7 @@ static void atmel_sha_finish_req(struct ahash_request *req, int err) req->base.complete(&req->base, err); /* handle new request */ - tasklet_schedule(&dd->done_task); + tasklet_schedule(&dd->queue_task); } static int atmel_sha_hw_init(struct atmel_sha_dev *dd) @@ -1101,16 +1102,18 @@ static struct ahash_alg sha_384_512_algs[] = { }, }; +static void atmel_sha_queue_task(unsigned long data) +{ + struct atmel_sha_dev *dd = (struct atmel_sha_dev *)data; + + atmel_sha_handle_queue(dd, NULL); +} + static void atmel_sha_done_task(unsigned long data) { struct atmel_sha_dev *dd = (struct atmel_sha_dev *)data; int err = 0; - if (!(SHA_FLAGS_BUSY & dd->flags)) { - atmel_sha_handle_queue(dd, NULL); - return; - } - if (SHA_FLAGS_CPU & dd->flags) { if (SHA_FLAGS_OUTPUT_READY & dd->flags) { dd->flags &= ~SHA_FLAGS_OUTPUT_READY; @@ -1367,6 +1370,8 @@ static int atmel_sha_probe(struct platform_device *pdev) tasklet_init(&sha_dd->done_task, atmel_sha_done_task, (unsigned long)sha_dd); + tasklet_init(&sha_dd->queue_task, atmel_sha_queue_task, + (unsigned long)sha_dd); crypto_init_queue(&sha_dd->queue, ATMEL_SHA_QUEUE_LENGTH); @@ -1459,6 +1464,7 @@ err_algs: atmel_sha_dma_cleanup(sha_dd); err_sha_dma: res_err: + tasklet_kill(&sha_dd->queue_task); tasklet_kill(&sha_dd->done_task); sha_dd_err: dev_err(dev, "initialization failed.\n"); @@ -1479,6 +1485,7 @@ static int atmel_sha_remove(struct platform_device *pdev) atmel_sha_unregister_algs(sha_dd); + tasklet_kill(&sha_dd->queue_task); tasklet_kill(&sha_dd->done_task); if (sha_dd->caps.has_dma) -- cgit v1.2.3 From 507c5cc236a2d751ea423a86486a2d1972369549 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Fri, 15 Jan 2016 15:49:33 +0100 Subject: crypto: atmel-sha - add support of sama5d2x SoCs This patch adds support of hardware version 5.1.x embedded inside sama5d2x SoCs. Signed-off-by: Cyrille Pitchen Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 75a8cbcf3121..7327e11e0ccb 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -1279,6 +1279,12 @@ static void atmel_sha_get_cap(struct atmel_sha_dev *dd) /* keep only major version number */ switch (dd->hw_version & 0xff0) { + case 0x510: + dd->caps.has_dma = 1; + dd->caps.has_dualbuff = 1; + dd->caps.has_sha224 = 1; + dd->caps.has_sha_384_512 = 1; + break; case 0x420: dd->caps.has_dma = 1; dd->caps.has_dualbuff = 1; -- cgit v1.2.3 From 7cee3508162a1760bc104c48d14202b01af28e53 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Fri, 15 Jan 2016 15:49:34 +0100 Subject: crypto: atmel-sha - fix context switches This patch saves the value of the internal hash register at the end of an 'update' operation then restores this value before starting the next 'update'. This way the driver can now properly handle context switches. WARNING: only hardware versions from sama5d4x and later provide the needed interface to update the internal hash value. Especially, sama5d3x cannot implement this feature so context switches are still broken. Signed-off-by: Cyrille Pitchen Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha-regs.h | 4 ++ drivers/crypto/atmel-sha.c | 105 ++++++++++++++++++++++++++++++---------- 2 files changed, 84 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/atmel-sha-regs.h b/drivers/crypto/atmel-sha-regs.h index 83b2d7425666..e08897109cab 100644 --- a/drivers/crypto/atmel-sha-regs.h +++ b/drivers/crypto/atmel-sha-regs.h @@ -8,6 +8,8 @@ #define SHA_CR_START (1 << 0) #define SHA_CR_FIRST (1 << 4) #define SHA_CR_SWRST (1 << 8) +#define SHA_CR_WUIHV (1 << 12) +#define SHA_CR_WUIEHV (1 << 13) #define SHA_MR 0x04 #define SHA_MR_MODE_MASK (0x3 << 0) @@ -15,6 +17,8 @@ #define SHA_MR_MODE_AUTO 0x1 #define SHA_MR_MODE_PDC 0x2 #define SHA_MR_PROCDLY (1 << 4) +#define SHA_MR_UIHV (1 << 5) +#define SHA_MR_UIEHV (1 << 6) #define SHA_MR_ALGO_SHA1 (0 << 8) #define SHA_MR_ALGO_SHA256 (1 << 8) #define SHA_MR_ALGO_SHA384 (2 << 8) diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 7327e11e0ccb..da4c3055784f 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -53,6 +53,7 @@ #define SHA_FLAGS_FINUP BIT(16) #define SHA_FLAGS_SG BIT(17) +#define SHA_FLAGS_ALGO_MASK GENMASK(22, 18) #define SHA_FLAGS_SHA1 BIT(18) #define SHA_FLAGS_SHA224 BIT(19) #define SHA_FLAGS_SHA256 BIT(20) @@ -60,6 +61,7 @@ #define SHA_FLAGS_SHA512 BIT(22) #define SHA_FLAGS_ERROR BIT(23) #define SHA_FLAGS_PAD BIT(24) +#define SHA_FLAGS_RESTORE BIT(25) #define SHA_OP_UPDATE 1 #define SHA_OP_FINAL 2 @@ -73,6 +75,7 @@ struct atmel_sha_caps { bool has_dualbuff; bool has_sha224; bool has_sha_384_512; + bool has_uihv; }; struct atmel_sha_dev; @@ -318,7 +321,8 @@ static int atmel_sha_init(struct ahash_request *req) static void atmel_sha_write_ctrl(struct atmel_sha_dev *dd, int dma) { struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req); - u32 valcr = 0, valmr = SHA_MR_MODE_AUTO; + u32 valmr = SHA_MR_MODE_AUTO; + unsigned int i, hashsize = 0; if (likely(dma)) { if (!dd->caps.has_dma) @@ -330,22 +334,62 @@ static void atmel_sha_write_ctrl(struct atmel_sha_dev *dd, int dma) atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY); } - if (ctx->flags & SHA_FLAGS_SHA1) + switch (ctx->flags & SHA_FLAGS_ALGO_MASK) { + case SHA_FLAGS_SHA1: valmr |= SHA_MR_ALGO_SHA1; - else if (ctx->flags & SHA_FLAGS_SHA224) + hashsize = SHA1_DIGEST_SIZE; + break; + + case SHA_FLAGS_SHA224: valmr |= SHA_MR_ALGO_SHA224; - else if (ctx->flags & SHA_FLAGS_SHA256) + hashsize = SHA256_DIGEST_SIZE; + break; + + case SHA_FLAGS_SHA256: valmr |= SHA_MR_ALGO_SHA256; - else if (ctx->flags & SHA_FLAGS_SHA384) + hashsize = SHA256_DIGEST_SIZE; + break; + + case SHA_FLAGS_SHA384: valmr |= SHA_MR_ALGO_SHA384; - else if (ctx->flags & SHA_FLAGS_SHA512) + hashsize = SHA512_DIGEST_SIZE; + break; + + case SHA_FLAGS_SHA512: valmr |= SHA_MR_ALGO_SHA512; + hashsize = SHA512_DIGEST_SIZE; + break; + + default: + break; + } /* Setting CR_FIRST only for the first iteration */ - if (!(ctx->digcnt[0] || ctx->digcnt[1])) - valcr = SHA_CR_FIRST; + if (!(ctx->digcnt[0] || ctx->digcnt[1])) { + atmel_sha_write(dd, SHA_CR, SHA_CR_FIRST); + } else if (dd->caps.has_uihv && (ctx->flags & SHA_FLAGS_RESTORE)) { + const u32 *hash = (const u32 *)ctx->digest; + + /* + * Restore the hardware context: update the User Initialize + * Hash Value (UIHV) with the value saved when the latest + * 'update' operation completed on this very same crypto + * request. + */ + ctx->flags &= ~SHA_FLAGS_RESTORE; + atmel_sha_write(dd, SHA_CR, SHA_CR_WUIHV); + for (i = 0; i < hashsize / sizeof(u32); ++i) + atmel_sha_write(dd, SHA_REG_DIN(i), hash[i]); + atmel_sha_write(dd, SHA_CR, SHA_CR_FIRST); + valmr |= SHA_MR_UIHV; + } + /* + * WARNING: If the UIHV feature is not available, the hardware CANNOT + * process concurrent requests: the internal registers used to store + * the hash/digest are still set to the partial digest output values + * computed during the latest round. + */ - atmel_sha_write(dd, SHA_CR, valcr); atmel_sha_write(dd, SHA_MR, valmr); } @@ -714,23 +758,31 @@ static void atmel_sha_copy_hash(struct ahash_request *req) { struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); u32 *hash = (u32 *)ctx->digest; - int i; + unsigned int i, hashsize; - if (ctx->flags & SHA_FLAGS_SHA1) - for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++) - hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i)); - else if (ctx->flags & SHA_FLAGS_SHA224) - for (i = 0; i < SHA224_DIGEST_SIZE / sizeof(u32); i++) - hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i)); - else if (ctx->flags & SHA_FLAGS_SHA256) - for (i = 0; i < SHA256_DIGEST_SIZE / sizeof(u32); i++) - hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i)); - else if (ctx->flags & SHA_FLAGS_SHA384) - for (i = 0; i < SHA384_DIGEST_SIZE / sizeof(u32); i++) - hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i)); - else - for (i = 0; i < SHA512_DIGEST_SIZE / sizeof(u32); i++) - hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i)); + switch (ctx->flags & SHA_FLAGS_ALGO_MASK) { + case SHA_FLAGS_SHA1: + hashsize = SHA1_DIGEST_SIZE; + break; + + case SHA_FLAGS_SHA224: + case SHA_FLAGS_SHA256: + hashsize = SHA256_DIGEST_SIZE; + break; + + case SHA_FLAGS_SHA384: + case SHA_FLAGS_SHA512: + hashsize = SHA512_DIGEST_SIZE; + break; + + default: + /* Should not happen... */ + return; + } + + for (i = 0; i < hashsize / sizeof(u32); ++i) + hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i)); + ctx->flags |= SHA_FLAGS_RESTORE; } static void atmel_sha_copy_ready_hash(struct ahash_request *req) @@ -1276,6 +1328,7 @@ static void atmel_sha_get_cap(struct atmel_sha_dev *dd) dd->caps.has_dualbuff = 0; dd->caps.has_sha224 = 0; dd->caps.has_sha_384_512 = 0; + dd->caps.has_uihv = 0; /* keep only major version number */ switch (dd->hw_version & 0xff0) { @@ -1284,12 +1337,14 @@ static void atmel_sha_get_cap(struct atmel_sha_dev *dd) dd->caps.has_dualbuff = 1; dd->caps.has_sha224 = 1; dd->caps.has_sha_384_512 = 1; + dd->caps.has_uihv = 1; break; case 0x420: dd->caps.has_dma = 1; dd->caps.has_dualbuff = 1; dd->caps.has_sha224 = 1; dd->caps.has_sha_384_512 = 1; + dd->caps.has_uihv = 1; break; case 0x410: dd->caps.has_dma = 1; -- cgit v1.2.3 From 3947b335bba390701619bd5c76ed8016f71d3017 Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Sun, 17 Jan 2016 10:03:54 +0100 Subject: hwrng: bcm63xx - remove unused variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These variables where left as unused in commit 6229c16060fe ("hwrng: bcm63xx - make use of devm_hwrng_register") Fixes the following warning: drivers/char/hw_random/bcm63xx-rng.c: In function 'bcm63xx_rng_probe': drivers/char/hw_random/bcm63xx-rng.c:85:16: warning: unused variable 'rng' [-Wunused-variable] struct hwrng *rng; ^ drivers/char/hw_random/bcm63xx-rng.c:82:14: warning: unused variable 'clk' [-Wunused-variable] struct clk *clk; Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Florian Fainelli Signed-off-by: Herbert Xu --- drivers/char/hw_random/bcm63xx-rng.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hw_random/bcm63xx-rng.c b/drivers/char/hw_random/bcm63xx-rng.c index 4b31f1387f37..c303f302fb0b 100644 --- a/drivers/char/hw_random/bcm63xx-rng.c +++ b/drivers/char/hw_random/bcm63xx-rng.c @@ -79,10 +79,8 @@ static int bcm63xx_rng_data_read(struct hwrng *rng, u32 *data) static int bcm63xx_rng_probe(struct platform_device *pdev) { struct resource *r; - struct clk *clk; int ret; struct bcm63xx_rng_priv *priv; - struct hwrng *rng; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { -- cgit v1.2.3 From 7b651706712b9774e77d89654949a5b1926d73db Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Sun, 17 Jan 2016 10:03:55 +0100 Subject: hwrng: bcm63xx - add device tree support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds device tree support for BCM6368, which seems to be the only BCM63xx with bcm63xx-rng support. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Florian Fainelli Signed-off-by: Herbert Xu --- drivers/char/hw_random/bcm63xx-rng.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/char/hw_random/bcm63xx-rng.c b/drivers/char/hw_random/bcm63xx-rng.c index c303f302fb0b..38553f0500c9 100644 --- a/drivers/char/hw_random/bcm63xx-rng.c +++ b/drivers/char/hw_random/bcm63xx-rng.c @@ -130,10 +130,17 @@ static int bcm63xx_rng_probe(struct platform_device *pdev) return 0; } +static const struct of_device_id bcm63xx_rng_of_match[] = { + { .compatible = "brcm,bcm6368-rng", }, + {}, +}; +MODULE_DEVICE_TABLE(of, bcm63xx_rng_of_match); + static struct platform_driver bcm63xx_rng_driver = { .probe = bcm63xx_rng_probe, .driver = { .name = "bcm63xx-rng", + .of_match_table = bcm63xx_rng_of_match, }, }; -- cgit v1.2.3 From 90859e6628dcf54a93a5f2017f7b19bc29c2e413 Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Sun, 17 Jan 2016 10:03:56 +0100 Subject: hwrng: bcm63xx - allow building for BMIPS_GENERIC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we have device tree support and BCM6368 is supported in BMIPS_GENERIC, we can use it for BMIPS_GENERIC too. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Florian Fainelli Signed-off-by: Herbert Xu --- drivers/char/hw_random/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index dbf22719462f..8d895908d608 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -77,7 +77,7 @@ config HW_RANDOM_ATMEL config HW_RANDOM_BCM63XX tristate "Broadcom BCM63xx Random Number Generator support" - depends on BCM63XX + depends on BCM63XX || BMIPS_GENERIC default HW_RANDOM ---help--- This driver provides kernel-side support for the Random Number -- cgit v1.2.3 From 0f987e25cb8a9c23bfd70942a580c2698444e4b4 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 19 Jan 2016 09:00:21 +0800 Subject: crypto: ixp4xx - Fix false lastlen uninitialised warning This patch fixes a false positive uninitialised variable warning in aead_perform by moving the source processing in front of the destination processing, thus ensuring that the initialisation of lastlen is always visible to gcc. Reported-by: Arnd Bergmann Signed-off-by: Herbert Xu Acked-by: Arnd Bergmann --- drivers/crypto/ixp4xx_crypto.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index e52496a172d0..2296934455fc 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c @@ -1031,6 +1031,18 @@ static int aead_perform(struct aead_request *req, int encrypt, BUG_ON(ivsize && !req->iv); memcpy(crypt->iv, req->iv, ivsize); + buf = chainup_buffers(dev, req->src, crypt->auth_len, + &src_hook, flags, src_direction); + req_ctx->src = src_hook.next; + crypt->src_buf = src_hook.phys_next; + if (!buf) + goto free_buf_src; + + lastlen = buf->buf_len; + if (lastlen >= authsize) + crypt->icv_rev_aes = buf->phys_addr + + buf->buf_len - authsize; + req_ctx->dst = NULL; if (req->src != req->dst) { @@ -1055,20 +1067,6 @@ static int aead_perform(struct aead_request *req, int encrypt, } } - buf = chainup_buffers(dev, req->src, crypt->auth_len, - &src_hook, flags, src_direction); - req_ctx->src = src_hook.next; - crypt->src_buf = src_hook.phys_next; - if (!buf) - goto free_buf_src; - - if (!encrypt || !req_ctx->dst) { - lastlen = buf->buf_len; - if (lastlen >= authsize) - crypt->icv_rev_aes = buf->phys_addr + - buf->buf_len - authsize; - } - if (unlikely(lastlen < authsize)) { /* The 12 hmac bytes are scattered, * we need to copy them into a safe buffer */ -- cgit v1.2.3 From 7768fb2ee9e907bfa91d13cb698fa68880ddc80a Mon Sep 17 00:00:00 2001 From: "Cabiddu, Giovanni" Date: Tue, 19 Jan 2016 17:34:04 +0000 Subject: crypto: qat - Reduced reqsize in qat_algs req_alloc functions already take into account the request data structure when allocating memory. Signed-off-by: Giovanni Cabiddu Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/qat_algs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c index 59e4c3af15ed..1e8852a8a057 100644 --- a/drivers/crypto/qat/qat_common/qat_algs.c +++ b/drivers/crypto/qat/qat_common/qat_algs.c @@ -1064,8 +1064,7 @@ static int qat_alg_aead_init(struct crypto_aead *tfm, if (IS_ERR(ctx->hash_tfm)) return PTR_ERR(ctx->hash_tfm); ctx->qat_hash_alg = hash; - crypto_aead_set_reqsize(tfm, sizeof(struct aead_request) + - sizeof(struct qat_crypto_request)); + crypto_aead_set_reqsize(tfm, sizeof(struct qat_crypto_request)); return 0; } @@ -1114,8 +1113,7 @@ static int qat_alg_ablkcipher_init(struct crypto_tfm *tfm) struct qat_alg_ablkcipher_ctx *ctx = crypto_tfm_ctx(tfm); spin_lock_init(&ctx->lock); - tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) + - sizeof(struct qat_crypto_request); + tfm->crt_ablkcipher.reqsize = sizeof(struct qat_crypto_request); ctx->tfm = tfm; return 0; } -- cgit v1.2.3 From c5d89a49fcb47e27a9ef96b63bdbe7fbf0504bd8 Mon Sep 17 00:00:00 2001 From: Benjamin Larsson Date: Sat, 28 Nov 2015 23:53:31 -0200 Subject: [media] Add support for Terratec Cinergy S2 Rev.4 Also Add Terratec Cinergy S2 usb id's Signed-off-by: Benjamin Larsson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb-usb-ids.h | 4 ++++ drivers/media/usb/dvb-usb-v2/dvbsky.c | 3 +++ 2 files changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 7f5d0865acfd..750d23f9928d 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h @@ -256,6 +256,10 @@ #define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062 #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 #define USB_PID_TERRATEC_CINERGY_T_XXS_2 0x00ab +#define USB_PID_TERRATEC_CINERGY_S2_R1 0x00a8 +#define USB_PID_TERRATEC_CINERGY_S2_R2 0x00b0 +#define USB_PID_TERRATEC_CINERGY_S2_R3 0x0102 +#define USB_PID_TERRATEC_CINERGY_S2_R4 0x0105 #define USB_PID_TERRATEC_H7 0x10b4 #define USB_PID_TERRATEC_H7_2 0x10a3 #define USB_PID_TERRATEC_H7_3 0x10a5 diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c index 1dd962535f97..2d922b96ed83 100644 --- a/drivers/media/usb/dvb-usb-v2/dvbsky.c +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c @@ -851,6 +851,9 @@ static const struct usb_device_id dvbsky_id_table[] = { USB_PID_TERRATEC_H7_3, &dvbsky_t680c_props, "Terratec H7 Rev.4", RC_MAP_TT_1500) }, + { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R4, + &dvbsky_s960_props, "Terratec Cinergy S2 Rev.4", + RC_MAP_DVBSKY) }, { } }; MODULE_DEVICE_TABLE(usb, dvbsky_id_table); -- cgit v1.2.3 From a561d768c13287ef156863c4ff149306844101fa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Jan 2016 12:47:44 -0200 Subject: [media] dw2102: use the new USB ID Terratec Cinergy S2 macros Now that this was defined at usb-id.h, update the values for USB_PID_TERRATEC_CINERGY_S2_R1 and USB_PID_TERRATEC_CINERGY_S2_R2. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/dw2102.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 14ef25dc6cd3..bc19da5ad3b7 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -1702,13 +1702,13 @@ static struct usb_device_id dw2102_table[] = { [TEVII_S660] = {USB_DEVICE(0x9022, USB_PID_TEVII_S660)}, [PROF_7500] = {USB_DEVICE(0x3034, 0x7500)}, [GENIATECH_SU3000] = {USB_DEVICE(0x1f4d, 0x3000)}, - [TERRATEC_CINERGY_S2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00a8)}, + [TERRATEC_CINERGY_S2] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R1)}, [TEVII_S480_1] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)}, [TEVII_S480_2] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)}, [X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)}, [TEVII_S421] = {USB_DEVICE(0x9022, USB_PID_TEVII_S421)}, [TEVII_S632] = {USB_DEVICE(0x9022, USB_PID_TEVII_S632)}, - [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00b0)}, + [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R2)}, [GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)}, [GENIATECH_T220] = {USB_DEVICE(0x1f4d, 0xD220)}, [TECHNOTREND_S2_4600] = {USB_DEVICE(USB_VID_TECHNOTREND, -- cgit v1.2.3 From 7655a3aea2ca14b9d34af929304f3c08140cc91c Mon Sep 17 00:00:00 2001 From: Matthias Schwarzott Date: Thu, 3 Dec 2015 18:12:50 -0200 Subject: [media] si2165: Reject DVB-T bandwidth auto mode The si2165 does not support bandwidth auto-detection. Reject the request. Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2165.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c index 2b93241d4bc1..659976612392 100644 --- a/drivers/media/dvb-frontends/si2165.c +++ b/drivers/media/dvb-frontends/si2165.c @@ -825,19 +825,19 @@ static int si2165_set_frontend_dvbt(struct dvb_frontend *fe) struct si2165_state *state = fe->demodulator_priv; u32 dvb_rate = 0; u16 bw10k; + u32 bw_hz = p->bandwidth_hz; dprintk("%s: called\n", __func__); if (!state->has_dvbt) return -EINVAL; - if (p->bandwidth_hz > 0) { - dvb_rate = p->bandwidth_hz * 8 / 7; - bw10k = p->bandwidth_hz / 10000; - } else { - dvb_rate = 8 * 8 / 7; - bw10k = 800; - } + /* no bandwidth auto-detection */ + if (bw_hz == 0) + return -EINVAL; + + dvb_rate = bw_hz * 8 / 7; + bw10k = bw_hz / 10000; ret = si2165_adjust_pll_divl(state, 12); if (ret < 0) -- cgit v1.2.3 From a63abe389d56f6f7b1541c2084b453c9dfdb89dc Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 4 Dec 2015 20:20:09 -0200 Subject: [media] exynos4-is: make VIDEO_SAMSUNG_EXYNOS4_IS tristate With CONFIG_V4L2=m and VIDEO_SAMSUNG_EXYNOS4_IS=y, we can select the individual drivers as built-in code when that should not be possible: drivers/built-in.o: In function `s5pcsis_set_fmt': policy.c:(.text+0x13afdc): undefined reference to `v4l_bound_align_image' drivers/built-in.o: In function `s5pcsis_probe': policy.c:(.text+0x13b440): undefined reference to `v4l2_of_parse_endpoint' policy.c:(.text+0x13b72c): undefined reference to `v4l2_subdev_init' Changing VIDEO_SAMSUNG_EXYNOS4_IS to tristate means that the dependency from CONFIG_V4L2 propates to the individual Kconfig symbols and they can only be built as loadable modules if V4L2 or any other of the dependencies itself is a module. Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/exynos4-is/Kconfig b/drivers/media/platform/exynos4-is/Kconfig index 40423c6c5324..57d42c6172c5 100644 --- a/drivers/media/platform/exynos4-is/Kconfig +++ b/drivers/media/platform/exynos4-is/Kconfig @@ -1,6 +1,6 @@ config VIDEO_SAMSUNG_EXYNOS4_IS - bool "Samsung S5P/EXYNOS4 SoC series Camera Subsystem driver" + tristate "Samsung S5P/EXYNOS4 SoC series Camera Subsystem driver" depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST depends on OF && COMMON_CLK -- cgit v1.2.3 From 71d362be0a9896e094601ac5f723f942cdfb0be9 Mon Sep 17 00:00:00 2001 From: Raphael Assenat Date: Sat, 23 Jan 2016 15:35:39 -0500 Subject: HID: usbhid: Fix incorrect product id of old 4nes4snes The correct product ID for the old version of the raphnet 4nes4snes device was 0x0a9d, not 0x0a8d. Signed-off-by: Raphael Assenat Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b6ff6e78ac54..de0fb068602a 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -1047,7 +1047,7 @@ #define USB_DEVICE_ID_RI_KA_WEBMAIL 0x1320 /* Webmail Notifier */ #define USB_VENDOR_ID_MULTIPLE_1781 0x1781 -#define USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD 0x0a8d +#define USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD 0x0a9d #define USB_VENDOR_ID_DRACAL_RAPHNET 0x289b #define USB_DEVICE_ID_RAPHNET_2NES2SNES 0x0002 -- cgit v1.2.3 From 27524ff8cd6c28ea3735f80f0374e0fc5494768f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 9 Dec 2015 11:46:55 -0200 Subject: [media] : cxd2830r: use gpiochip data pointer This makes the driver use the data pointer added to the gpio_chip to store a pointer to the state container instead of relying on container_of(). Cc: Antti Palosaari Signed-off-by: Linus Walleij Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/cxd2820r_core.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c index 24a457d9d803..ba4cb7557aa5 100644 --- a/drivers/media/dvb-frontends/cxd2820r_core.c +++ b/drivers/media/dvb-frontends/cxd2820r_core.c @@ -606,8 +606,7 @@ static int cxd2820r_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) static int cxd2820r_gpio_direction_output(struct gpio_chip *chip, unsigned nr, int val) { - struct cxd2820r_priv *priv = - container_of(chip, struct cxd2820r_priv, gpio_chip); + struct cxd2820r_priv *priv = gpiochip_get_data(chip); u8 gpio[GPIO_COUNT]; dev_dbg(&priv->i2c->dev, "%s: nr=%d val=%d\n", __func__, nr, val); @@ -620,8 +619,7 @@ static int cxd2820r_gpio_direction_output(struct gpio_chip *chip, unsigned nr, static void cxd2820r_gpio_set(struct gpio_chip *chip, unsigned nr, int val) { - struct cxd2820r_priv *priv = - container_of(chip, struct cxd2820r_priv, gpio_chip); + struct cxd2820r_priv *priv = gpiochip_get_data(chip); u8 gpio[GPIO_COUNT]; dev_dbg(&priv->i2c->dev, "%s: nr=%d val=%d\n", __func__, nr, val); @@ -636,8 +634,7 @@ static void cxd2820r_gpio_set(struct gpio_chip *chip, unsigned nr, int val) static int cxd2820r_gpio_get(struct gpio_chip *chip, unsigned nr) { - struct cxd2820r_priv *priv = - container_of(chip, struct cxd2820r_priv, gpio_chip); + struct cxd2820r_priv *priv = gpiochip_get_data(chip); dev_dbg(&priv->i2c->dev, "%s: nr=%d\n", __func__, nr); @@ -731,7 +728,7 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg, priv->gpio_chip.base = -1; /* dynamic allocation */ priv->gpio_chip.ngpio = GPIO_COUNT; priv->gpio_chip.can_sleep = 1; - ret = gpiochip_add(&priv->gpio_chip); + ret = gpiochip_add_data(&priv->gpio_chip, priv); if (ret) goto error; -- cgit v1.2.3 From 21fabbebff0e17c7698ed399cae23958c214cc82 Mon Sep 17 00:00:00 2001 From: Andreas Ziegler Date: Mon, 25 Jan 2016 12:41:19 +0100 Subject: drm/i915: Remove select to deleted STOP_MACHINE from Kconfig Commit 5bab6f60cb4d ("drm/i915: Serialise updates to GGTT with access through GGTT on Braswell") depended upon a working stop_machine() and so forced the selection of STOP_MACHINE. However, commit 86fffe4a61dd ("kernel: remove stop_machine() Kconfig dependency") removed the option STOP_MACHINE from init/Kconfig and ensured that stop_machine() universally works. Due to the order in which the patches were applied, removing the select from DRM_I915 got lost during merging. Remove the now obsolete select statement. Signed-off-by: Andreas Ziegler Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1453722079-2604-1-git-send-email-andreas.ziegler@fau.de Cc: drm-intel-fixes@lists.freedesktop.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index fcd77b27514d..051eab33e4c7 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -10,7 +10,6 @@ config DRM_I915 # the shmem_readpage() which depends upon tmpfs select SHMEM select TMPFS - select STOP_MACHINE select DRM_KMS_HELPER select DRM_PANEL select DRM_MIPI_DSI -- cgit v1.2.3 From 33136b06d54915680c36f4cd89dadef068b88974 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Thu, 21 Jan 2016 21:43:47 +0000 Subject: drm/i915/gen9: Add framework to whitelist specific GPU registers Some of the HW registers are privileged and cannot be written to from non-privileged batch buffers coming from userspace unless they are added to the HW whitelist. This whitelist is maintained by HW and it is different from SW whitelist. Userspace need write access to them to implement preemption related WA. The reason for using this approach is, the register bits that control preemption granularity at the HW level are not context save/restored; so even if we set these bits always in kernel they are going to change once the context is switched out. We can consider making them non-privileged by default but these registers also contain other chicken bits which should not be allowed to be modified. In the later revisions controlling bits are save/restored at context level but in the existing revisions these are exported via other debug registers and should be on the whitelist. This patch adds changes to provide HW with a list of registers to be whitelisted. HW checks this list during execution and provides access accordingly. HW imposes a limit on the number of registers on whitelist and it is per-engine. At this point we are only enabling whitelist for RCS and we don't foresee any requirement for other engines. The registers to be whitelisted are added using generic workaround list mechanism, even these are only enablers for userspace workarounds. But by sharing this mechanism we get some test assets without additional cost (Mika). v2: rebase v3: parameterize RING_FORCE_TO_NONPRIV() as _MMIO() should be limited to i915_reg.h (Ville), drop inline for wa_ring_whitelist_reg (Mika). v4: improvements suggested by Chris Wilson. Clarify that this is HW whitelist and different from the one maintained in driver. This list is engine specific but it gets initialized along with other WA which is RCS specific thing, so make it clear that we are not doing any cross engine setup during initialization. Make HW whitelist count of each engine available in debugfs. Reviewed-by: Chris Wilson Reviewed-by: Mika Kuoppala Cc: Mika Kuoppala Cc: Chris Wilson Signed-off-by: Arun Siluvery Link: http://patchwork.freedesktop.org/patch/msgid/1453412634-29238-2-git-send-email-arun.siluvery@linux.intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 15 ++++++++++----- drivers/gpu/drm/i915/i915_drv.h | 9 ++++++++- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_ringbuffer.c | 17 +++++++++++++++++ 4 files changed, 38 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index cea184459256..863012a2602e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3221,9 +3221,11 @@ static int i915_wa_registers(struct seq_file *m, void *unused) { int i; int ret; + struct intel_engine_cs *ring; struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct i915_workarounds *workarounds = &dev_priv->workarounds; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) @@ -3231,15 +3233,18 @@ static int i915_wa_registers(struct seq_file *m, void *unused) intel_runtime_pm_get(dev_priv); - seq_printf(m, "Workarounds applied: %d\n", dev_priv->workarounds.count); - for (i = 0; i < dev_priv->workarounds.count; ++i) { + seq_printf(m, "Workarounds applied: %d\n", workarounds->count); + for_each_ring(ring, dev_priv, i) + seq_printf(m, "HW whitelist count for %s: %d\n", + ring->name, workarounds->hw_whitelist_count[i]); + for (i = 0; i < workarounds->count; ++i) { i915_reg_t addr; u32 mask, value, read; bool ok; - addr = dev_priv->workarounds.reg[i].addr; - mask = dev_priv->workarounds.reg[i].mask; - value = dev_priv->workarounds.reg[i].value; + addr = workarounds->reg[i].addr; + mask = workarounds->reg[i].mask; + value = workarounds->reg[i].value; read = I915_READ(addr); ok = (value & mask) == (read & mask); seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X, read: 0x%08x, status: %s\n", diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index afb0beee9975..211af534e5d0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1657,11 +1657,18 @@ struct i915_wa_reg { u32 mask; }; -#define I915_MAX_WA_REGS 16 +/* + * RING_MAX_NONPRIV_SLOTS is per-engine but at this point we are only + * allowing it for RCS as we don't foresee any requirement of having + * a whitelist for other engines. When it is really required for + * other engines then the limit need to be increased. + */ +#define I915_MAX_WA_REGS (16 + RING_MAX_NONPRIV_SLOTS) struct i915_workarounds { struct i915_wa_reg reg[I915_MAX_WA_REGS]; u32 count; + u32 hw_whitelist_count[I915_NUM_RINGS]; }; struct i915_virtual_gpu { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0a988895165f..79388147184c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1635,6 +1635,9 @@ enum skl_disp_power_wells { #define RING_WAIT (1<<11) /* gen3+, PRBx_CTL */ #define RING_WAIT_SEMAPHORE (1<<10) /* gen6+ */ +#define RING_FORCE_TO_NONPRIV(base, i) _MMIO(((base)+0x4D0) + (i)*4) +#define RING_MAX_NONPRIV_SLOTS 12 + #define GEN7_TLB_RD_ADDR _MMIO(0x4700) #if 0 diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 9030e2bca0c0..43fa1403159e 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -789,6 +789,22 @@ static int wa_add(struct drm_i915_private *dev_priv, #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val) +static int wa_ring_whitelist_reg(struct intel_engine_cs *ring, i915_reg_t reg) +{ + struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct i915_workarounds *wa = &dev_priv->workarounds; + const uint32_t index = wa->hw_whitelist_count[ring->id]; + + if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS)) + return -EINVAL; + + WA_WRITE(RING_FORCE_TO_NONPRIV(ring->mmio_base, index), + i915_mmio_reg_offset(reg)); + wa->hw_whitelist_count[ring->id]++; + + return 0; +} + static int gen8_init_workarounds(struct intel_engine_cs *ring) { struct drm_device *dev = ring->dev; @@ -1117,6 +1133,7 @@ int init_workarounds_ring(struct intel_engine_cs *ring) WARN_ON(ring->id != RCS); dev_priv->workarounds.count = 0; + dev_priv->workarounds.hw_whitelist_count[RCS] = 0; if (IS_BROADWELL(dev)) return bdw_init_workarounds(ring); -- cgit v1.2.3 From e0f3fa096d6f319d1177b05d824fd8b36517368c Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Thu, 21 Jan 2016 21:43:48 +0000 Subject: drm/i915/gen9: Add GEN8_CS_CHICKEN1 to HW whitelist Required for WaEnablePreemptionGranularityControlByUMD:skl,bxt This register is added to HW whitelist to support WA required for future enabling of pre-emptive command execution, WA implementation will be in userspace and it cannot program this register if it is not on HW whitelist. v2: explain purpose of WA (Chris) Reviewed-by: Nick Hoath Signed-off-by: Arun Siluvery Link: http://patchwork.freedesktop.org/patch/msgid/1453412634-29238-3-git-send-email-arun.siluvery@linux.intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 6 ++++++ 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 79388147184c..511732ea0138 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5998,6 +5998,8 @@ enum skl_disp_power_wells { #define FF_SLICE_CS_CHICKEN2 _MMIO(0x20e4) #define GEN9_TSG_BARRIER_ACK_DISABLE (1<<8) +#define GEN8_CS_CHICKEN1 _MMIO(0x2580) + /* GEN7 chicken */ #define GEN7_COMMON_SLICE_CHICKEN1 _MMIO(0x7010) # define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC ((1<<10) | (1<<26)) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 43fa1403159e..c938b93c4f83 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -910,6 +910,7 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring) struct drm_device *dev = ring->dev; struct drm_i915_private *dev_priv = dev->dev_private; uint32_t tmp; + int ret; /* WaEnableLbsSlaRetryTimerDecrement:skl */ I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) | @@ -980,6 +981,11 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring) /* WaDisableSTUnitPowerOptimization:skl,bxt */ WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE); + /* WaEnablePreemptionGranularityControlByUMD:skl,bxt */ + ret= wa_ring_whitelist_reg(ring, GEN8_CS_CHICKEN1); + if (ret) + return ret; + return 0; } -- cgit v1.2.3 From 3669ab6191b24ee800a5f78d3748b7d96df12115 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Thu, 21 Jan 2016 21:43:49 +0000 Subject: drm/i915/gen9: Add HDC_CHICKEN1 to HW whitelist Required for WaAllowUMDToModifyHDCChicken1:skl,bxt This register is added to HW whitelist to support WA required for future enabling of pre-emptive command execution, WA implementation will be in userspace and it cannot program this register if it is not on HW whitelist. v2: explain purpose of changes (Chris) Reviewed-by: Nick Hoath Signed-off-by: Arun Siluvery Link: http://patchwork.freedesktop.org/patch/msgid/1453412634-29238-4-git-send-email-arun.siluvery@linux.intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 5 +++++ 2 files changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 511732ea0138..ed887cfc47f1 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6045,6 +6045,8 @@ enum skl_disp_power_wells { #define HDC_FORCE_NON_COHERENT (1<<4) #define HDC_BARRIER_PERFORMANCE_DISABLE (1<<10) +#define GEN8_HDC_CHICKEN1 _MMIO(0x7304) + /* GEN9 chicken */ #define SLICE_ECO_CHICKEN0 _MMIO(0x7308) #define PIXEL_MASK_CAMMING_DISABLE (1 << 14) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index c938b93c4f83..62f535c1b78e 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -986,6 +986,11 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring) if (ret) return ret; + /* WaAllowUMDToModifyHDCChicken1:skl,bxt */ + ret = wa_ring_whitelist_reg(ring, GEN8_HDC_CHICKEN1); + if (ret) + return ret; + return 0; } -- cgit v1.2.3 From 2c8580e4e21c17011e78e7ac4e1fbab8b0d632bf Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Thu, 21 Jan 2016 21:43:50 +0000 Subject: drm/i915/bxt: Add GEN9_CS_DEBUG_MODE1 to HW whitelist Required for, WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt WaDisableObjectLevelPreemptionForInstancedDraw:bxt WaDisableObjectLevelPreemtionForInstanceId:bxt According to WA database these are only applicable for BXT:A0 but since A0 and A1 shares the same GT these are extended for A1 as well. These are also required for SKL until B0 but not adding them because they are pre-production steppings. This register is added to HW whitelist to support WA required for future enabling of pre-emptive command execution, WA implementation will be in userspace and it cannot program this register if it is not on HW whitelist. v2: use lower case in register defines (Nick) v3: explain purpose of changes (Chris) Reviewed-by: Nick Hoath Signed-off-by: Arun Siluvery Link: http://patchwork.freedesktop.org/patch/msgid/1453412634-29238-5-git-send-email-arun.siluvery@linux.intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_ringbuffer.c | 9 +++++++++ 2 files changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ed887cfc47f1..c51e7e909457 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5998,6 +5998,7 @@ enum skl_disp_power_wells { #define FF_SLICE_CS_CHICKEN2 _MMIO(0x20e4) #define GEN9_TSG_BARRIER_ACK_DISABLE (1<<8) +#define GEN9_CS_DEBUG_MODE1 _MMIO(0x20ec) #define GEN8_CS_CHICKEN1 _MMIO(0x2580) /* GEN7 chicken */ diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 62f535c1b78e..a99f8340fb47 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1133,6 +1133,15 @@ static int bxt_init_workarounds(struct intel_engine_cs *ring) GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); } + /* WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt */ + /* WaDisableObjectLevelPreemptionForInstancedDraw:bxt */ + /* WaDisableObjectLevelPreemtionForInstanceId:bxt */ + if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { + ret = wa_ring_whitelist_reg(ring, GEN9_CS_DEBUG_MODE1); + if (ret) + return ret; + } + return 0; } -- cgit v1.2.3 From a786d53a2cf14f2c7abb6731f530aef1a8a1086a Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Thu, 21 Jan 2016 21:43:51 +0000 Subject: drm/i915/bxt: Add GEN8_L3SQCREG4 to HW whitelist Required for WaDisableLSQCROPERFforOCL:bxt According to WA database these are only applicable for BXT:A0 but since A0 and A1 shares the same GT these are extended for A1 as well. This register is added to HW whitelist to support WA required for future enabling of pre-emptive command execution, WA implementation will be in userspace and it cannot program this register if it is not on HW whitelist. v2: explain purpose of changes (Chris) Reviewed-by: Nick Hoath Signed-off-by: Arun Siluvery Link: http://patchwork.freedesktop.org/patch/msgid/1453412634-29238-6-git-send-email-arun.siluvery@linux.intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index a99f8340fb47..12eb1e0f786b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1136,10 +1136,15 @@ static int bxt_init_workarounds(struct intel_engine_cs *ring) /* WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt */ /* WaDisableObjectLevelPreemptionForInstancedDraw:bxt */ /* WaDisableObjectLevelPreemtionForInstanceId:bxt */ + /* WaDisableLSQCROPERFforOCL:bxt */ if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { ret = wa_ring_whitelist_reg(ring, GEN9_CS_DEBUG_MODE1); if (ret) return ret; + + ret = wa_ring_whitelist_reg(ring, GEN8_L3SQCREG4); + if (ret) + return ret; } return 0; -- cgit v1.2.3 From 6107497eee9f0f9de6f2aa8708db20842637d472 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Thu, 21 Jan 2016 21:43:52 +0000 Subject: drm/i915/skl: Add GEN8_L3SQCREG4 to HW whitelist Required for WaDisableLSQCROPERFforOCL:skl This register is added to HW whitelist to support WA required for future enabling of pre-emptive command execution, WA implementation will be in userspace and it cannot program this register if it is not on HW whitelist. v2: explain purpose of changes (Chris) Reviewed-by: Nick Hoath Signed-off-by: Arun Siluvery Link: http://patchwork.freedesktop.org/patch/msgid/1453412634-29238-7-git-send-email-arun.siluvery@linux.intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 12eb1e0f786b..262a7ea9e9c4 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1098,6 +1098,11 @@ static int skl_init_workarounds(struct intel_engine_cs *ring) GEN7_HALF_SLICE_CHICKEN1, GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); + /* WaDisableLSQCROPERFforOCL:skl */ + ret = wa_ring_whitelist_reg(ring, GEN8_L3SQCREG4); + if (ret) + return ret; + return skl_tune_iz_hashing(ring); } -- cgit v1.2.3 From a78536e73f35471417df1de561d8e8b83da28734 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Thu, 21 Jan 2016 21:43:53 +0000 Subject: drm/i915/skl: Enable Per context Preemption granularity control Per context preemption granularity control is only available from SKL:E0+ Actual WA is to disable percontext preemption granularity control until D0 which is the default case so this is equivalent to the inverse of WaDisablePerCtxtPreemptionGranularityControl:skl v2: add some detail to commit msg (Chris) Reviewed-by: Nick Hoath Cc: Dave Gordon Signed-off-by: Arun Siluvery Link: http://patchwork.freedesktop.org/patch/msgid/1453412634-29238-8-git-send-email-arun.siluvery@linux.intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_ringbuffer.c | 10 ++++++++++ 2 files changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c51e7e909457..65e32a317d63 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5995,6 +5995,9 @@ enum skl_disp_power_wells { #define SKL_DFSM_CDCLK_LIMIT_450 (2 << 23) #define SKL_DFSM_CDCLK_LIMIT_337_5 (3 << 23) +#define GEN7_FF_SLICE_CS_CHICKEN1 _MMIO(0x20e0) +#define GEN9_FFSC_PERCTX_PREEMPT_CTRL (1<<14) + #define FF_SLICE_CS_CHICKEN2 _MMIO(0x20e4) #define GEN9_TSG_BARRIER_ACK_DISABLE (1<<8) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 262a7ea9e9c4..d07c6a9e7b40 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1046,6 +1046,16 @@ static int skl_init_workarounds(struct intel_engine_cs *ring) if (ret) return ret; + /* + * Actual WA is to disable percontext preemption granularity control + * until D0 which is the default case so this is equivalent to + * !WaDisablePerCtxtPreemptionGranularityControl:skl + */ + if (IS_SKL_REVID(dev, SKL_REVID_E0, REVID_FOREVER)) { + I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, + _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); + } + if (IS_SKL_REVID(dev, 0, SKL_REVID_D0)) { /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */ I915_WRITE(FF_SLICE_CS_CHICKEN2, -- cgit v1.2.3 From 6ecf56ae1d20d00a010a7d6d453031e413c674b8 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Thu, 21 Jan 2016 21:43:54 +0000 Subject: drm/i915/gen9: Add WaOCLCoherentLineFlush This is mainly required for future enabling of pre-emptive command execution. v2: explain purpose of change (Chris) Reviewed-by: Nick Hoath Cc: Dave Gordon Signed-off-by: Arun Siluvery Link: http://patchwork.freedesktop.org/patch/msgid/1453412634-29238-9-git-send-email-arun.siluvery@linux.intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index d07c6a9e7b40..6f5b511bdb5d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -981,6 +981,10 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring) /* WaDisableSTUnitPowerOptimization:skl,bxt */ WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE); + /* WaOCLCoherentLineFlush:skl,bxt */ + I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) | + GEN8_LQSC_FLUSH_COHERENT_LINES)); + /* WaEnablePreemptionGranularityControlByUMD:skl,bxt */ ret= wa_ring_whitelist_reg(ring, GEN8_CS_CHICKEN1); if (ret) -- cgit v1.2.3 From 186bac815227a4c26a0ad2f18c7450015d93ed0a Mon Sep 17 00:00:00 2001 From: Matthew Dawson Date: Mon, 25 Jan 2016 10:34:12 -0500 Subject: drm/radeon: Ensure radeon bo is unreserved in radeon_gem_va_ioctl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found with lockdep while testing gpu reset. Reviewed-by: Christian König Signed-off-by: Matthew Dawson Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_gem.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 3dcc5733ff69..e26c963f2e93 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -663,6 +663,7 @@ int radeon_gem_va_ioctl(struct drm_device *dev, void *data, bo_va = radeon_vm_bo_find(&fpriv->vm, rbo); if (!bo_va) { args->operation = RADEON_VA_RESULT_ERROR; + radeon_bo_unreserve(rbo); drm_gem_object_unreference_unlocked(gobj); return -ENOENT; } -- cgit v1.2.3 From 4ae2182b1e3407de369f8c5d799543b7db74221b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 25 Jan 2016 10:08:00 -0600 Subject: PCI/AER: Flush workqueue on device remove to avoid use-after-free A Root Port's AER structure (rpc) contains a queue of events. aer_irq() enqueues AER status information and schedules aer_isr() to dequeue and process it. When we remove a device, aer_remove() waits for the queue to be empty, then frees the rpc struct. But aer_isr() references the rpc struct after dequeueing and possibly emptying the queue, which can cause a use-after-free error as in the following scenario with two threads, aer_isr() on the left and a concurrent aer_remove() on the right: Thread A Thread B -------- -------- aer_irq(): rpc->prod_idx++ aer_remove(): wait_event(rpc->prod_idx == rpc->cons_idx) # now blocked until queue becomes empty aer_isr(): # ... rpc->cons_idx++ # unblocked because queue is now empty ... kfree(rpc) mutex_unlock(&rpc->rpc_mutex) To prevent this problem, use flush_work() to wait until the last scheduled instance of aer_isr() has completed before freeing the rpc struct in aer_remove(). I reproduced this use-after-free by flashing a device FPGA and re-enumerating the bus to find the new device. With SLUB debug, this crashes with 0x6b bytes (POISON_FREE, the use-after-free magic number) in GPR25: pcieport 0000:00:00.0: AER: Multiple Corrected error received: id=0000 Unable to handle kernel paging request for data at address 0x27ef9e3e Workqueue: events aer_isr GPR24: dd6aa000 6b6b6b6b 605f8378 605f8360 d99b12c0 604fc674 606b1704 d99b12c0 NIP [602f5328] pci_walk_bus+0xd4/0x104 [bhelgaas: changelog, stable tag] Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Bjorn Helgaas CC: stable@vger.kernel.org --- drivers/pci/pcie/aer/aerdrv.c | 4 +--- drivers/pci/pcie/aer/aerdrv.h | 1 - drivers/pci/pcie/aer/aerdrv_core.c | 2 -- 3 files changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 0bf82a20a0fb..48d21e0edd56 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c @@ -262,7 +262,6 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev) rpc->rpd = dev; INIT_WORK(&rpc->dpc_handler, aer_isr); mutex_init(&rpc->rpc_mutex); - init_waitqueue_head(&rpc->wait_release); /* Use PCIe bus function to store rpc into PCIe device */ set_service_data(dev, rpc); @@ -285,8 +284,7 @@ static void aer_remove(struct pcie_device *dev) if (rpc->isr) free_irq(dev->irq, dev); - wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx); - + flush_work(&rpc->dpc_handler); aer_disable_rootport(rpc); kfree(rpc); set_service_data(dev, NULL); diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h index 84420b7c9456..945c939a86c5 100644 --- a/drivers/pci/pcie/aer/aerdrv.h +++ b/drivers/pci/pcie/aer/aerdrv.h @@ -72,7 +72,6 @@ struct aer_rpc { * recovery on the same * root port hierarchy */ - wait_queue_head_t wait_release; }; struct aer_broadcast_data { diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 712392504ed9..521e39c1b66d 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -811,8 +811,6 @@ void aer_isr(struct work_struct *work) while (get_e_source(rpc, &e_src)) aer_isr_one_error(p_device, &e_src); mutex_unlock(&rpc->rpc_mutex); - - wake_up(&rpc->wait_release); } /** -- cgit v1.2.3 From e847396b40d07931f5d2835f73220e16a1a413b3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 21 Dec 2015 22:42:59 +0100 Subject: powerpc: qe_lib/gpio: Be sure to clamp return value As we want gpio_chip .get() calls to be able to return negative error codes and propagate to drivers, we need to go over all drivers and make sure their return values are clamped to [0,1]. We do this by using the ret = !!(val) design pattern. Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij --- drivers/soc/fsl/qe/gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/soc/fsl/qe/gpio.c b/drivers/soc/fsl/qe/gpio.c index aa5c11acf212..65845712571c 100644 --- a/drivers/soc/fsl/qe/gpio.c +++ b/drivers/soc/fsl/qe/gpio.c @@ -63,7 +63,7 @@ static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio) struct qe_pio_regs __iomem *regs = mm_gc->regs; u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio); - return in_be32(®s->cpdata) & pin_mask; + return !!(in_be32(®s->cpdata) & pin_mask); } static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) -- cgit v1.2.3 From 47de9bf8931e6bf9c92fdba9867925d1ce482ab1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Jan 2016 14:39:34 -0200 Subject: [media] tvp5150: Fix breakage for serial usage changeset 460b6c0831cb ("tvp5150: Add s_stream subdev operation support") broke for em28xx-based devices with uses tvp5150. On those devices, touching the TVP5150_MISC_CTL register causes em28xx to stop streaming. I suspect that it uses the 27 MHz clock provided by tvp5150 to feed em28xx. So, change the logic to do nothing on s_stream if the tvp5150 is not set up to work with V4L2_MBUS_PARALLEL. Tested with Hauppauge WinTV USB 2 model 42012 Rev. C186 (USB ID: 2040:4200). Cc: Javier Martinez Canillas Cc: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 437f1a7ecb96..779c6f453cc9 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -975,19 +975,18 @@ static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) { struct tvp5150 *decoder = to_tvp5150(sd); - /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ - int val = 0x09; /* Output format: 8-bit 4:2:2 YUV with discrete sync */ - if (decoder->mbus_type == V4L2_MBUS_PARALLEL) - val = 0x0d; + if (decoder->mbus_type != V4L2_MBUS_PARALLEL) + return 0; /* Initializes TVP5150 to its default values */ /* # set PCLK (27MHz) */ tvp5150_write(sd, TVP5150_CONF_SHARED_PIN, 0x00); + /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ if (enable) - tvp5150_write(sd, TVP5150_MISC_CTL, val); + tvp5150_write(sd, TVP5150_MISC_CTL, 0x09); else tvp5150_write(sd, TVP5150_MISC_CTL, 0x00); -- cgit v1.2.3 From c1ae8f3ad8758b588b4ba02edcb8d413185a10d7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 12 Dec 2015 22:32:01 -0200 Subject: [media] davinci: ccdc_update_raw_params() frees the wrong thing Passing a physical address to free_pages() is a bad idea. config_params->fault_pxl.fpc_table_addr is set to virt_to_phys() of __get_free_pages() return value; what we should pass to free_pages() is its phys_to_virt(). ccdc_close() does that properly, but ccdc_update_raw_params() doesn't. Signed-off-by: Al Viro Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/dm644x_ccdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/davinci/dm644x_ccdc.c b/drivers/media/platform/davinci/dm644x_ccdc.c index ffbefdff6b5e..6fba32bec974 100644 --- a/drivers/media/platform/davinci/dm644x_ccdc.c +++ b/drivers/media/platform/davinci/dm644x_ccdc.c @@ -261,7 +261,7 @@ static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) */ if (raw_params->fault_pxl.fp_num != config_params->fault_pxl.fp_num) { if (fpc_physaddr != NULL) { - free_pages((unsigned long)fpc_physaddr, + free_pages((unsigned long)fpc_virtaddr, get_order (config_params->fault_pxl.fp_num * FP_NUM_BYTES)); -- cgit v1.2.3 From 28d5bdbe5c0adcc11b7b63e65cf002a1ebaf3ca4 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 14 Dec 2015 12:41:51 -0200 Subject: [media] mt9v032: Add reset and standby gpios Add optional reset and standby gpios. The reset gpio is used to reset the chip in power_on(). The standby gpio is not used currently. It is just unset, so the chip is not in standby. Signed-off-by: Markus Pargmann Reviewed-by: Philipp Zabel Acked-by: Rob Herring Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/i2c/mt9v032.txt | 2 ++ drivers/media/i2c/mt9v032.c | 28 ++++++++++++++++++++++ 2 files changed, 30 insertions(+) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/media/i2c/mt9v032.txt b/Documentation/devicetree/bindings/media/i2c/mt9v032.txt index 202565313e82..100f0ae43269 100644 --- a/Documentation/devicetree/bindings/media/i2c/mt9v032.txt +++ b/Documentation/devicetree/bindings/media/i2c/mt9v032.txt @@ -20,6 +20,8 @@ Optional Properties: - link-frequencies: List of allowed link frequencies in Hz. Each frequency is expressed as a 64-bit big-endian integer. +- reset-gpios: GPIO handle which is connected to the reset pin of the chip. +- standby-gpios: GPIO handle which is connected to the standby pin of the chip. For further reading on port node refer to Documentation/devicetree/bindings/media/video-interfaces.txt. diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 2e1d116a64e7..501b37039449 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -251,6 +252,8 @@ struct mt9v032 { struct regmap *regmap; struct clk *clk; + struct gpio_desc *reset_gpio; + struct gpio_desc *standby_gpio; struct mt9v032_platform_data *pdata; const struct mt9v032_model_info *model; @@ -312,16 +315,31 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032) struct regmap *map = mt9v032->regmap; int ret; + if (mt9v032->reset_gpio) + gpiod_set_value_cansleep(mt9v032->reset_gpio, 1); + ret = clk_set_rate(mt9v032->clk, mt9v032->sysclk); if (ret < 0) return ret; + /* System clock has to be enabled before releasing the reset */ ret = clk_prepare_enable(mt9v032->clk); if (ret) return ret; udelay(1); + if (mt9v032->reset_gpio) { + gpiod_set_value_cansleep(mt9v032->reset_gpio, 0); + + /* After releasing reset we need to wait 10 clock cycles + * before accessing the sensor over I2C. As the minimum SYSCLK + * frequency is 13MHz, waiting 1µs will be enough in the worst + * case. + */ + udelay(1); + } + /* Reset the chip and stop data read out */ ret = regmap_write(map, MT9V032_RESET, 1); if (ret < 0) @@ -954,6 +972,16 @@ static int mt9v032_probe(struct i2c_client *client, if (IS_ERR(mt9v032->clk)) return PTR_ERR(mt9v032->clk); + mt9v032->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(mt9v032->reset_gpio)) + return PTR_ERR(mt9v032->reset_gpio); + + mt9v032->standby_gpio = devm_gpiod_get_optional(&client->dev, "standby", + GPIOD_OUT_LOW); + if (IS_ERR(mt9v032->standby_gpio)) + return PTR_ERR(mt9v032->standby_gpio); + mutex_init(&mt9v032->power_lock); mt9v032->pdata = pdata; mt9v032->model = (const void *)did->driver_data; -- cgit v1.2.3 From 23c7d7134147f276a09d0e55011cf682a0051093 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 18 Dec 2015 11:05:25 -0200 Subject: [media] staging: media: lirc: replace NULL comparisons with !var A NULL comparison can be written as if (var) or if (!var). Reported by checkpatch. Signed-off-by: Sudip Mukherjee Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_parallel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c index d009bcb439f0..7df827856de6 100644 --- a/drivers/staging/media/lirc/lirc_parallel.c +++ b/drivers/staging/media/lirc/lirc_parallel.c @@ -647,7 +647,7 @@ static int __init lirc_parallel_init(void) goto exit_device_put; pport = parport_find_base(io); - if (pport == NULL) { + if (!pport) { pr_notice("no port at %x found\n", io); result = -ENXIO; goto exit_device_put; @@ -656,7 +656,7 @@ static int __init lirc_parallel_init(void) pf, kf, lirc_lirc_irq_handler, 0, NULL); parport_put_port(pport); - if (ppdevice == NULL) { + if (!ppdevice) { pr_notice("parport_register_device() failed\n"); result = -ENXIO; goto exit_device_put; -- cgit v1.2.3 From b790aea57ecd31786ec2b00f8551261c57db4bd4 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 18 Dec 2015 11:05:26 -0200 Subject: [media] staging: media: lirc: no space after cast checkpatch complains about space after type cast. [mchehab@osg.samsung.com: removed an obsolete hunk] Signed-off-by: Sudip Mukherjee Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_parallel.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c index 7df827856de6..eed6ffac7c90 100644 --- a/drivers/staging/media/lirc/lirc_parallel.c +++ b/drivers/staging/media/lirc/lirc_parallel.c @@ -286,9 +286,9 @@ static void lirc_lirc_irq_handler(void *blah) /* adjust value to usecs */ __u64 helper; - helper = ((__u64) signal)*1000000; + helper = ((__u64)signal)*1000000; do_div(helper, timer); - signal = (long) helper; + signal = (long)helper; if (signal > LIRC_SFH506_DELAY) data = signal - LIRC_SFH506_DELAY; @@ -393,9 +393,9 @@ static ssize_t lirc_write(struct file *filep, const char __user *buf, size_t n, for (i = 0; i < count; i++) { __u64 helper; - helper = ((__u64) wbuf[i])*timer; + helper = ((__u64)wbuf[i])*timer; do_div(helper, 1000000); - wbuf[i] = (int) helper; + wbuf[i] = (int)helper; } local_irq_save(flags); -- cgit v1.2.3 From 0d2f79c2bb34d9a9631a43b8d5ea7f2968564a6a Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 18 Dec 2015 11:05:27 -0200 Subject: [media] staging: media: lirc: space around operator checkpatch complains about missing space around operators. [mchehab@osg.samsung.com: removed obsolete hunks] Signed-off-by: Sudip Mukherjee Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_parallel.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c index eed6ffac7c90..6e2edb24d9d5 100644 --- a/drivers/staging/media/lirc/lirc_parallel.c +++ b/drivers/staging/media/lirc/lirc_parallel.c @@ -193,7 +193,7 @@ static int lirc_claim(void) return 0; } } - out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); + out(LIRC_LP_CONTROL, LP_PSELECP | LP_PINITP); is_claimed = 1; return 1; } @@ -264,7 +264,7 @@ static void lirc_lirc_irq_handler(void *blah) init = 1; } - timeout = timer/10; /* timeout after 1/10 sec. */ + timeout = timer / 10; /* timeout after 1/10 sec. */ signal = 1; level = lirc_get_timer(); do { @@ -286,7 +286,7 @@ static void lirc_lirc_irq_handler(void *blah) /* adjust value to usecs */ __u64 helper; - helper = ((__u64)signal)*1000000; + helper = ((__u64)signal) * 1000000; do_div(helper, timer); signal = (long)helper; @@ -294,7 +294,7 @@ static void lirc_lirc_irq_handler(void *blah) data = signal - LIRC_SFH506_DELAY; else data = 1; - rbuf_write(PULSE_BIT|data); /* pulse */ + rbuf_write(PULSE_BIT | data); /* pulse */ } lastkt = ktime_get(); #else @@ -331,7 +331,7 @@ static ssize_t lirc_read(struct file *filep, char __user *buf, size_t n, set_current_state(TASK_INTERRUPTIBLE); while (count < n) { if (rptr != wptr) { - if (copy_to_user(buf+count, &rbuf[rptr], + if (copy_to_user(buf + count, &rbuf[rptr], sizeof(int))) { result = -EFAULT; break; @@ -393,7 +393,7 @@ static ssize_t lirc_write(struct file *filep, const char __user *buf, size_t n, for (i = 0; i < count; i++) { __u64 helper; - helper = ((__u64)wbuf[i])*timer; + helper = ((__u64)wbuf[i]) * timer; do_div(helper, 1000000); wbuf[i] = (int)helper; } @@ -664,7 +664,7 @@ static int __init lirc_parallel_init(void) if (parport_claim(ppdevice) != 0) goto skip_init; is_claimed = 1; - out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); + out(LIRC_LP_CONTROL, LP_PSELECP | LP_PINITP); #ifdef LIRC_TIMER if (debug) -- cgit v1.2.3 From d5441ea58ccc70637b75b035dee61685b516a5ca Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sat, 19 Dec 2015 12:28:37 -0200 Subject: [media] gsc-m2m: Use an unsigned data type for a variable The data type "int" was used by the variable "ret" in the gsc_m2m_poll() function despite of the aspect that the type "unsigned int" will usually be needed for the return value from a call of the v4l2_m2m_poll() function. Improve this implementation detail by addition of the type modifier then. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos-gsc/gsc-m2m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c index 93782f15b825..a600e32e2543 100644 --- a/drivers/media/platform/exynos-gsc/gsc-m2m.c +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c @@ -700,7 +700,7 @@ static unsigned int gsc_m2m_poll(struct file *file, { struct gsc_ctx *ctx = fh_to_ctx(file->private_data); struct gsc_dev *gsc = ctx->gsc_dev; - int ret; + unsigned int ret; if (mutex_lock_interruptible(&gsc->lock)) return -ERESTARTSYS; -- cgit v1.2.3 From 2e490139b137bbac3250d594cef3dcbc461ad4cc Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Mon, 21 Dec 2015 11:54:46 -0200 Subject: [media] media: i2c: ov2659: speedup probe if no device connected The ov2659 driver performs device detection and initialization in the following way: - send reset command REG_SOFTWARE_RESET - load array of predefined register's setting (~150 values) - read device version REG_SC_CHIP_ID_H/REG_SC_CHIP_ID_L - check version and exit if invalid. As result, for not connected device there will be >~150 i2c transactions executed before device version checking and exit (there are no failures detected because ov2659 declared as I2C_CLIENT_SCCB and NACKs are ignored in this case). Let's fix that by checking the chip version first and start initialization only if it's supported. Cc: Benoit Parrot Signed-off-by: Grygorii Strashko Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov2659.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 02b9a3440557..1f999e9c0118 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -1321,10 +1321,6 @@ static int ov2659_detect(struct v4l2_subdev *sd) } usleep_range(1000, 2000); - ret = ov2659_init(sd, 0); - if (ret < 0) - return ret; - /* Check sensor revision */ ret = ov2659_read(client, REG_SC_CHIP_ID_H, &pid); if (!ret) @@ -1338,8 +1334,10 @@ static int ov2659_detect(struct v4l2_subdev *sd) dev_err(&client->dev, "Sensor detection failed (%04X, %d)\n", id, ret); - else + else { dev_info(&client->dev, "Found OV%04X sensor\n", id); + ret = ov2659_init(sd, 0); + } } return ret; -- cgit v1.2.3 From c2e5c951c2d10536a9f17647f3440e5f9f639d8b Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sun, 27 Dec 2015 15:23:57 -0200 Subject: [media] si2165: Refactoring for si2165_writereg_mask8() This issue was detected by using the Coccinelle software. 1. Let us return directly if a call of the si2165_readreg8() function failed. 2. Reduce the scope for the local variables "ret" and "tmp" to one branch of an if statement. 3. Delete the jump label "err" then. 4. Return the value from a call of the si2165_writereg8() function without using an extra assignment for the variable "ret" at the end. Signed-off-by: Markus Elfring Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2165.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c index 659976612392..8bf716a8ea58 100644 --- a/drivers/media/dvb-frontends/si2165.c +++ b/drivers/media/dvb-frontends/si2165.c @@ -225,22 +225,18 @@ static int si2165_writereg32(struct si2165_state *state, const u16 reg, u32 val) static int si2165_writereg_mask8(struct si2165_state *state, const u16 reg, u8 val, u8 mask) { - int ret; - u8 tmp; - if (mask != 0xff) { - ret = si2165_readreg8(state, reg, &tmp); + u8 tmp; + int ret = si2165_readreg8(state, reg, &tmp); + if (ret < 0) - goto err; + return ret; val &= mask; tmp &= ~mask; val |= tmp; } - - ret = si2165_writereg8(state, reg, val); -err: - return ret; + return si2165_writereg8(state, reg, val); } #define REG16(reg, val) { (reg), (val) & 0xff }, { (reg)+1, (val)>>8 & 0xff } -- cgit v1.2.3 From 2050d14c6ea23ea7b50b5cc7d05dbf645705cf70 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 28 Dec 2015 12:20:45 -0200 Subject: [media] tuners: Refactoring for m88rs6000t_sleep() This issue was detected by using the Coccinelle software. 1. Let us return directly if a call of the regmap_write() function failed. 2. Delete the jump label "err" then. 3. Return zero as a constant at the end. Signed-off-by: Markus Elfring Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/m88rs6000t.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/tuners/m88rs6000t.c b/drivers/media/tuners/m88rs6000t.c index 504bfbc4027a..9f3e0fd4cad9 100644 --- a/drivers/media/tuners/m88rs6000t.c +++ b/drivers/media/tuners/m88rs6000t.c @@ -461,13 +461,12 @@ static int m88rs6000t_sleep(struct dvb_frontend *fe) dev_dbg(&dev->client->dev, "%s:\n", __func__); ret = regmap_write(dev->regmap, 0x07, 0x6d); - if (ret) - goto err; - usleep_range(5000, 10000); -err: - if (ret) + if (ret) { dev_dbg(&dev->client->dev, "failed=%d\n", ret); - return ret; + return ret; + } + usleep_range(5000, 10000); + return 0; } static int m88rs6000t_get_frequency(struct dvb_frontend *fe, u32 *frequency) -- cgit v1.2.3 From 61f8e1a73296d065abc959e0c0861ffbdfa2d0b3 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 28 Dec 2015 13:36:44 -0200 Subject: [media] r820t: Delete an unnecessary variable initialisation in generic_set_freq() The variable "rc" will be set to an appropriate value from a call of the r820t_set_tv_standard() function. Thus let us omit the explicit initialisation at the beginning. Signed-off-by: Markus Elfring Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/r820t.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c index a7a8452e99d2..6ab35e315fe7 100644 --- a/drivers/media/tuners/r820t.c +++ b/drivers/media/tuners/r820t.c @@ -1295,7 +1295,7 @@ static int generic_set_freq(struct dvb_frontend *fe, v4l2_std_id std, u32 delsys) { struct r820t_priv *priv = fe->tuner_priv; - int rc = -EINVAL; + int rc; u32 lo_freq; tuner_dbg("should set frequency to %d kHz, bw %d MHz\n", -- cgit v1.2.3 From a73cfe527c10bb023f0e22dd8cf37dd418c093e7 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 29 Dec 2015 09:32:41 -0200 Subject: [media] msi2500: Delete an unnecessary check in msi2500_set_usb_adc() This issue was detected by using the Coccinelle software. Return the value from a call of the msi2500_ctrl_msg() function without using an extra check for the variable "ret" at the end. Signed-off-by: Markus Elfring Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/msi2500/msi2500.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c index c104315fdc17..2d33033682af 100644 --- a/drivers/media/usb/msi2500/msi2500.c +++ b/drivers/media/usb/msi2500/msi2500.c @@ -839,8 +839,6 @@ static int msi2500_set_usb_adc(struct msi2500_dev *dev) goto err; ret = msi2500_ctrl_msg(dev, CMD_WREG, reg3); - if (ret) - goto err; err: return ret; } -- cgit v1.2.3 From 3def9ad6d3066e597d0ce86801a81eedb130b04a Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:39:22 -0200 Subject: [media] nuvoton-cir: use request_muxed_region for accessing EFM registers The two EFM ioports are accessed by drivers for other parts of the Nuvoton Super-IO chips too. Therefore access to these ioports needs to be protected by using request_muxed_region (like it's implemented e.g. in hwmon/nct6775 already). Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 081435cda30c..62c82c54ec82 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -80,17 +80,24 @@ static inline void nvt_clear_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg) } /* enter extended function mode */ -static inline void nvt_efm_enable(struct nvt_dev *nvt) +static inline int nvt_efm_enable(struct nvt_dev *nvt) { + if (!request_muxed_region(nvt->cr_efir, 2, NVT_DRIVER_NAME)) + return -EBUSY; + /* Enabling Extended Function Mode explicitly requires writing 2x */ outb(EFER_EFM_ENABLE, nvt->cr_efir); outb(EFER_EFM_ENABLE, nvt->cr_efir); + + return 0; } /* exit extended function mode */ static inline void nvt_efm_disable(struct nvt_dev *nvt) { outb(EFER_EFM_DISABLE, nvt->cr_efir); + + release_region(nvt->cr_efir, 2); } /* -- cgit v1.2.3 From 7a89836e994eaad7a17ae293ea1cd2b5597d2b4e Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:39:34 -0200 Subject: [media] nuvoton-cir: simplify nvt_select_logical_ dev Use nvt_cr_write to simplify nvt_select_logical_ dev. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 62c82c54ec82..2539d4f10a0c 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -107,8 +107,7 @@ static inline void nvt_efm_disable(struct nvt_dev *nvt) */ static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev) { - outb(CR_LOGICAL_DEV_SEL, nvt->cr_efir); - outb(ldev, nvt->cr_efdr); + nvt_cr_write(nvt, ldev, CR_LOGICAL_DEV_SEL); } /* write val to cir config register */ -- cgit v1.2.3 From 1feac493b08a87b912a09b62666ad6d49bd6b87b Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:39:41 -0200 Subject: [media] nuvoton-cir: simplify nvt_cir_tx_inactive Simplify nvt_cir_tx_inactive. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 2539d4f10a0c..f661effac82e 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -742,16 +742,13 @@ static void nvt_cir_log_irqs(u8 status, u8 iren) static bool nvt_cir_tx_inactive(struct nvt_dev *nvt) { unsigned long flags; - bool tx_inactive; u8 tx_state; spin_lock_irqsave(&nvt->tx.lock, flags); tx_state = nvt->tx.tx_state; spin_unlock_irqrestore(&nvt->tx.lock, flags); - tx_inactive = (tx_state == ST_TX_NONE); - - return tx_inactive; + return tx_state == ST_TX_NONE; } /* interrupt service routine for incoming and outgoing CIR data */ -- cgit v1.2.3 From a17ede9ac1d8164e4d0b0b58e21bfa40890818d2 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:40:05 -0200 Subject: [media] nuvoton-cir: factor out logical device disabling Factor out disabling of a logical device. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index f661effac82e..ceb6b95b13fa 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -110,6 +110,15 @@ static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev) nvt_cr_write(nvt, ldev, CR_LOGICAL_DEV_SEL); } +/* select and disable logical device with setting EFM mode*/ +static inline void nvt_disable_logical_dev(struct nvt_dev *nvt, u8 ldev) +{ + nvt_efm_enable(nvt); + nvt_select_logical_dev(nvt, ldev); + nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); + nvt_efm_disable(nvt); +} + /* write val to cir config register */ static inline void nvt_cir_reg_write(struct nvt_dev *nvt, u8 val, u8 offset) { @@ -937,13 +946,8 @@ static void nvt_disable_cir(struct nvt_dev *nvt) nvt_clear_cir_fifo(nvt); nvt_clear_tx_fifo(nvt); - nvt_efm_enable(nvt); - /* disable the CIR logical device */ - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); + nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR); } static int nvt_open(struct rc_dev *dev) @@ -1145,13 +1149,8 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) /* disable all CIR interrupts */ nvt_cir_reg_write(nvt, 0, CIR_IREN); - nvt_efm_enable(nvt); - /* disable cir logical dev */ - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); + nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR); /* make sure wake is enabled */ nvt_enable_wake(nvt); -- cgit v1.2.3 From e1a7d981cfefbf8e0261083a10ccad7dd0af6394 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:40:47 -0200 Subject: [media] nuvoton-cir: fix clearing wake fifo At least on NVT6779D clearing the wake fifo works in learning mode only (although this condition is not mentioned in the chip spec). Setting the clear fifo bit has no effect in wake up mode. Even if clearing the wake fifo should work in wake up mode on other chips this workaround doesn't hurt. If needed the caller of nvt_clear_cir_wake_fifo has to take care of locking. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index ceb6b95b13fa..5f36227a9059 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -370,11 +370,19 @@ static void nvt_clear_cir_fifo(struct nvt_dev *nvt) /* clear out the hardware's cir wake rx fifo */ static void nvt_clear_cir_wake_fifo(struct nvt_dev *nvt) { - u8 val; + u8 val, config; + + config = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON); + + /* clearing wake fifo works in learning mode only */ + nvt_cir_wake_reg_write(nvt, config & ~CIR_WAKE_IRCON_MODE0, + CIR_WAKE_IRCON); val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON); nvt_cir_wake_reg_write(nvt, val | CIR_WAKE_FIFOCON_RXFIFOCLR, CIR_WAKE_FIFOCON); + + nvt_cir_wake_reg_write(nvt, config, CIR_WAKE_IRCON); } /* clear out the hardware's cir tx fifo */ -- cgit v1.2.3 From f2c2ba0e251d0b5211ce0397081b087ac623136f Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:43:18 -0200 Subject: [media] nuvoton-cir: use IR_DEFAULT_TIMEOUT and consider SAMPLE_PERIOD Switch to using the recently introduced IR default timeout value (IR_DEFAULT_TIMEOUT) and consider the value of SAMPLE_PERIOD when calculating the limit count register value. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h index 0ad15d34e9c9..6a3de08a17c0 100644 --- a/drivers/media/rc/nuvoton-cir.h +++ b/drivers/media/rc/nuvoton-cir.h @@ -157,8 +157,8 @@ struct nvt_dev { /* total length of CIR and CIR WAKE */ #define CIR_IOREG_LENGTH 0x0f -/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL (0x7d0 = 2000) */ -#define CIR_RX_LIMIT_COUNT 0x7d0 +/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL */ +#define CIR_RX_LIMIT_COUNT (IR_DEFAULT_TIMEOUT / US_TO_NS(SAMPLE_PERIOD)) /* CIR Regs */ #define CIR_IRCON 0x00 -- cgit v1.2.3 From 0890655c29a88765924c46460f38f33f7e34b5fc Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:40:12 -0200 Subject: [media] nuvoton-cir: factor out logical device enabling Factor out enabling of a logical device. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 5f36227a9059..f6248519b31e 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -110,6 +110,15 @@ static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev) nvt_cr_write(nvt, ldev, CR_LOGICAL_DEV_SEL); } +/* select and enable logical device with setting EFM mode*/ +static inline void nvt_enable_logical_dev(struct nvt_dev *nvt, u8 ldev) +{ + nvt_efm_enable(nvt); + nvt_select_logical_dev(nvt, ldev); + nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); + nvt_efm_disable(nvt); +} + /* select and disable logical device with setting EFM mode*/ static inline void nvt_disable_logical_dev(struct nvt_dev *nvt, u8 ldev) { @@ -924,13 +933,8 @@ static void nvt_enable_cir(struct nvt_dev *nvt) CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, CIR_IRCON); - nvt_efm_enable(nvt); - /* enable the CIR logical device */ - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); /* clear all pending interrupts */ nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); @@ -1176,11 +1180,7 @@ static int nvt_resume(struct pnp_dev *pdev) nvt_set_cir_iren(nvt); /* Enable CIR logical device */ - nvt_efm_enable(nvt); - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); nvt_cir_regs_init(nvt); nvt_cir_wake_regs_init(nvt); -- cgit v1.2.3 From ccca00d6d7c2d6cec282ac3e3942032268d50fe4 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:43:59 -0200 Subject: [media] nuvoton-cir: improve logical device handling Only enable the logical devices after the registers have been initialized. The call to nvt_enable_logical_dev in nvt_resume is not needed as this is done implicitely by nvt_cir_regs_init now. [mchehab@osg.samsung.com: fixed multiline comment to kernel CodingStyle] Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index f6248519b31e..5593a2f5b6c4 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -329,9 +329,8 @@ static void nvt_cir_ldev_init(struct nvt_dev *nvt) val |= psval; nvt_cr_write(nvt, val, psreg); - /* Select CIR logical device and enable */ + /* Select CIR logical device */ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); nvt_cr_write(nvt, nvt->cir_addr >> 8, CR_CIR_BASE_ADDR_HI); nvt_cr_write(nvt, nvt->cir_addr & 0xff, CR_CIR_BASE_ADDR_LO); @@ -344,7 +343,7 @@ static void nvt_cir_ldev_init(struct nvt_dev *nvt) static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt) { - /* Select ACPI logical device, enable it and CIR Wake */ + /* Select ACPI logical device and anable it */ nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); @@ -354,9 +353,8 @@ static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt) /* enable pme interrupt of cir wakeup event */ nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2); - /* Select CIR Wake logical device and enable */ + /* Select CIR Wake logical device */ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); nvt_cr_write(nvt, nvt->cir_wake_addr >> 8, CR_CIR_BASE_ADDR_HI); nvt_cr_write(nvt, nvt->cir_wake_addr & 0xff, CR_CIR_BASE_ADDR_LO); @@ -440,6 +438,9 @@ static void nvt_cir_regs_init(struct nvt_dev *nvt) /* and finally, enable interrupts */ nvt_set_cir_iren(nvt); + + /* enable the CIR logical device */ + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); } static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) @@ -474,6 +475,9 @@ static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) /* clear any and all stray interrupts */ nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); + + /* enable the CIR WAKE logical device */ + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); } static void nvt_enable_wake(struct nvt_dev *nvt) @@ -1051,7 +1055,10 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) nvt_cir_wake_ldev_init(nvt); nvt_efm_disable(nvt); - /* Initialize CIR & CIR Wake Config Registers */ + /* + * Initialize CIR & CIR Wake Config Registers + * and enable logical devices + */ nvt_cir_regs_init(nvt); nvt_cir_wake_regs_init(nvt); @@ -1179,9 +1186,6 @@ static int nvt_resume(struct pnp_dev *pdev) /* open interrupt */ nvt_set_cir_iren(nvt); - /* Enable CIR logical device */ - nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cir_regs_init(nvt); nvt_cir_wake_regs_init(nvt); -- cgit v1.2.3 From 0c6fbfdf8663e26a7e29f6142bd7ac2ac35310af Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:42:56 -0200 Subject: [media] nuvoton-cir: remove unneeded EFM operation in nvt_cir_isr Selecting the logical device in the interrupt handler is not needed as no configuration register is accessed. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 5593a2f5b6c4..ec14b63a280d 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -790,10 +790,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) nvt_dbg_verbose("%s firing", __func__); - nvt_efm_enable(nvt); - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_efm_disable(nvt); - /* * Get IR Status register contents. Write 1 to ack/clear * -- cgit v1.2.3 From d790c9b93b0c37a23680c88b63be0e34744f764e Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:44:13 -0200 Subject: [media] nuvoton-cir: remove unneeded call to nvt_set_cir_iren Calling nvt_set_cir_iren separately is not needed as this is done by nvt_cir_regs_init. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index ec14b63a280d..d396dcc11be5 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -1179,9 +1179,6 @@ static int nvt_resume(struct pnp_dev *pdev) nvt_dbg("%s called", __func__); - /* open interrupt */ - nvt_set_cir_iren(nvt); - nvt_cir_regs_init(nvt); nvt_cir_wake_regs_init(nvt); -- cgit v1.2.3 From fb16aaf58cbe902585fc3a2ce40d74a2de384ac2 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:42:05 -0200 Subject: [media] nuvoton-cir: fix setting ioport base address At least on Zotac CI321 ACPI provides an ioport range for the wake up part but accessing these ioports has no effect. Instead the ioport base address is set to another value already (0xa20 in my case) and accessing this ioport range works. Therefore set a new ioport base address only if the current ioport base address is 0 (register reset default). The need to use the existing base address instead of trying to set an own one doesn't seem to be limited to this specific device as other drivers like hwmon/nct6775 do it the same way. This change was successfully tested on the mentioned device. And the change should be generic enough to not break the driver for other chips (however due to lack of appropriate hardware I wasn't able to test this). [mchehab@osg.samsung.com: Tested on Intel NUC NUC5i7RYB with BIOS version RYBDWi35.86A.0350.2015.0812.1722] Signed-off-by: Heiner Kallweit Tested-by: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index d396dcc11be5..5790ee46a38d 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -161,6 +161,22 @@ static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset) return val; } +/* don't override io address if one is set already */ +static void nvt_set_ioaddr(struct nvt_dev *nvt, unsigned long *ioaddr) +{ + unsigned long old_addr; + + old_addr = nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8; + old_addr |= nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO); + + if (old_addr) + *ioaddr = old_addr; + else { + nvt_cr_write(nvt, *ioaddr >> 8, CR_CIR_BASE_ADDR_HI); + nvt_cr_write(nvt, *ioaddr & 0xff, CR_CIR_BASE_ADDR_LO); + } +} + /* dump current cir register contents */ static void cir_dump_regs(struct nvt_dev *nvt) { @@ -332,8 +348,7 @@ static void nvt_cir_ldev_init(struct nvt_dev *nvt) /* Select CIR logical device */ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, nvt->cir_addr >> 8, CR_CIR_BASE_ADDR_HI); - nvt_cr_write(nvt, nvt->cir_addr & 0xff, CR_CIR_BASE_ADDR_LO); + nvt_set_ioaddr(nvt, &nvt->cir_addr); nvt_cr_write(nvt, nvt->cir_irq, CR_CIR_IRQ_RSRC); @@ -356,8 +371,7 @@ static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt) /* Select CIR Wake logical device */ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); - nvt_cr_write(nvt, nvt->cir_wake_addr >> 8, CR_CIR_BASE_ADDR_HI); - nvt_cr_write(nvt, nvt->cir_wake_addr & 0xff, CR_CIR_BASE_ADDR_LO); + nvt_set_ioaddr(nvt, &nvt->cir_wake_addr); nvt_cr_write(nvt, nvt->cir_wake_irq, CR_CIR_IRQ_RSRC); -- cgit v1.2.3 From 73efe5792bfa73589a7e04abf773f8b7a4c01650 Mon Sep 17 00:00:00 2001 From: Henry Chen Date: Mon, 4 Jan 2016 20:02:52 +0800 Subject: soc: mediatek: PMIC wrap: Clear the vldclr if state machine stay on FSM_VLDCLR state. Sometimes PMIC is too busy to send data in time to cause pmic wrap timeout, because pmic wrap is waiting for FSM_VLDCLR after finishing WACS2_CMD. It just return error when issue happened, so the state machine will stay on FSM_VLDCLR state when data send back later by PMIC and timeout again in next time because pmic wrap waiting for FSM_IDLE state at the beginning of the read/write function. Clear the vldclr when timeout if state machine stay on FSM_VLDCLR. Signed-off-by: Henry Chen Tested-by: Ricky Liang Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 105597a885cb..696071b66c41 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -412,6 +412,20 @@ static bool pwrap_is_fsm_vldclr(struct pmic_wrapper *wrp) return PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_WFVLDCLR; } +/* + * Timeout issue sometimes caused by the last read command + * failed because pmic wrap could not got the FSM_VLDCLR + * in time after finishing WACS2_CMD. It made state machine + * still on FSM_VLDCLR and timeout next time. + * Check the status of FSM and clear the vldclr to recovery the + * error. + */ +static inline void pwrap_leave_fsm_vldclr(struct pmic_wrapper *wrp) +{ + if (pwrap_is_fsm_vldclr(wrp)) + pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR); +} + static bool pwrap_is_sync_idle(struct pmic_wrapper *wrp) { return pwrap_readl(wrp, PWRAP_WACS2_RDATA) & PWRAP_STATE_SYNC_IDLE0; @@ -445,8 +459,10 @@ static int pwrap_write(struct pmic_wrapper *wrp, u32 adr, u32 wdata) int ret; ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle); - if (ret) + if (ret) { + pwrap_leave_fsm_vldclr(wrp); return ret; + } pwrap_writel(wrp, (1 << 31) | ((adr >> 1) << 16) | wdata, PWRAP_WACS2_CMD); @@ -459,8 +475,10 @@ static int pwrap_read(struct pmic_wrapper *wrp, u32 adr, u32 *rdata) int ret; ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle); - if (ret) + if (ret) { + pwrap_leave_fsm_vldclr(wrp); return ret; + } pwrap_writel(wrp, (adr >> 1) << 16, PWRAP_WACS2_CMD); -- cgit v1.2.3 From a3bbfbb0bc6bd40406ef2aea940719312600813e Mon Sep 17 00:00:00 2001 From: Henry Chen Date: Thu, 21 Jan 2016 19:04:00 +0800 Subject: soc: mediatek: PMIC wrap: clear the STAUPD_TRIG bit of WDT_SRC_EN Since STAUPD interrupts aren't handled on mt8173, disable watchdog timeout monitor of STAUPD to avoid WDT_INT triggered by STAUPD. Signed-off-by: Henry Chen Reviewed-by: Daniel Kurtz Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 696071b66c41..0d9b19a78d27 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -60,6 +60,15 @@ #define PWRAP_MAN_CMD_OP_OUTD (0x9 << 8) #define PWRAP_MAN_CMD_OP_OUTQ (0xa << 8) +/* macro for Watch Dog Timer Source */ +#define PWRAP_WDT_SRC_EN_STAUPD_TRIG (1 << 25) +#define PWRAP_WDT_SRC_EN_HARB_STAUPD_DLE (1 << 20) +#define PWRAP_WDT_SRC_EN_HARB_STAUPD_ALE (1 << 6) +#define PWRAP_WDT_SRC_MASK_ALL 0xffffffff +#define PWRAP_WDT_SRC_MASK_NO_STAUPD ~(PWRAP_WDT_SRC_EN_STAUPD_TRIG | \ + PWRAP_WDT_SRC_EN_HARB_STAUPD_DLE | \ + PWRAP_WDT_SRC_EN_HARB_STAUPD_ALE) + /* macro for slave device wrapper registers */ #define PWRAP_DEW_BASE 0xbc00 #define PWRAP_DEW_EVENT_OUT_EN (PWRAP_DEW_BASE + 0x0) @@ -822,7 +831,7 @@ MODULE_DEVICE_TABLE(of, of_pwrap_match_tbl); static int pwrap_probe(struct platform_device *pdev) { - int ret, irq; + int ret, irq, wdt_src; struct pmic_wrapper *wrp; struct device_node *np = pdev->dev.of_node; const struct of_device_id *of_id = @@ -912,7 +921,13 @@ static int pwrap_probe(struct platform_device *pdev) /* Initialize watchdog, may not be done by the bootloader */ pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT); - pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN); + /* + * Since STAUPD was not used on mt8173 platform, + * so STAUPD of WDT_SRC which should be turned off + */ + wdt_src = pwrap_is_mt8173(wrp) ? + PWRAP_WDT_SRC_MASK_NO_STAUPD : PWRAP_WDT_SRC_MASK_ALL; + pwrap_writel(wrp, wdt_src, PWRAP_WDT_SRC_EN); pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN); pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN); -- cgit v1.2.3 From be29523da38f959799fddceb25d052e498ab625a Mon Sep 17 00:00:00 2001 From: Matthias Brugger Date: Wed, 30 Dec 2015 09:30:40 +0100 Subject: soc: mediatek: SCPSYS: use builtin_platform_driver SCPSYS can't be built as module. Use builtin_platform_driver instead. For this probe must not be __init and the data accessed can't be __initconst. Remove this macros. To make the impact as small as possible, fold scp_domain_data into scp_domain via a pointer. Cc: Sascha Hauer Cc: Arnd Bergmann Reported-by: Daniel Kurtz Signed-off-by: Matthias Brugger Reviewed-by: Daniel Kurtz Tested-by: Daniel Kurtz Acked-by: Arnd Bergmann --- drivers/soc/mediatek/mtk-scpsys.c | 49 +++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c index 0221387e5e27..837effe19907 100644 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ b/drivers/soc/mediatek/mtk-scpsys.c @@ -76,7 +76,7 @@ struct scp_domain_data { bool active_wakeup; }; -static const struct scp_domain_data scp_domain_data[] __initconst = { +static const struct scp_domain_data scp_domain_data[] = { [MT8173_POWER_DOMAIN_VDEC] = { .name = "vdec", .sta_mask = PWR_STATUS_VDEC, @@ -174,12 +174,7 @@ struct scp_domain { struct generic_pm_domain genpd; struct scp *scp; struct clk *clk[MAX_CLKS]; - u32 sta_mask; - void __iomem *ctl_addr; - u32 sram_pdn_bits; - u32 sram_pdn_ack_bits; - u32 bus_prot_mask; - bool active_wakeup; + const struct scp_domain_data *data; struct regulator *supply; }; @@ -195,8 +190,9 @@ static int scpsys_domain_is_on(struct scp_domain *scpd) { struct scp *scp = scpd->scp; - u32 status = readl(scp->base + SPM_PWR_STATUS) & scpd->sta_mask; - u32 status2 = readl(scp->base + SPM_PWR_STATUS_2ND) & scpd->sta_mask; + u32 status = readl(scp->base + SPM_PWR_STATUS) & scpd->data->sta_mask; + u32 status2 = readl(scp->base + SPM_PWR_STATUS_2ND) & + scpd->data->sta_mask; /* * A domain is on when both status bits are set. If only one is set @@ -217,8 +213,8 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) struct scp *scp = scpd->scp; unsigned long timeout; bool expired; - void __iomem *ctl_addr = scpd->ctl_addr; - u32 sram_pdn_ack = scpd->sram_pdn_ack_bits; + void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs; + u32 sram_pdn_ack = scpd->data->sram_pdn_ack_bits; u32 val; int ret; int i; @@ -273,7 +269,7 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) val |= PWR_RST_B_BIT; writel(val, ctl_addr); - val &= ~scpd->sram_pdn_bits; + val &= ~scpd->data->sram_pdn_bits; writel(val, ctl_addr); /* wait until SRAM_PDN_ACK all 0 */ @@ -292,9 +288,9 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) expired = true; } - if (scpd->bus_prot_mask) { + if (scpd->data->bus_prot_mask) { ret = mtk_infracfg_clear_bus_protection(scp->infracfg, - scpd->bus_prot_mask); + scpd->data->bus_prot_mask); if (ret) goto err_pwr_ack; } @@ -321,21 +317,21 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) struct scp *scp = scpd->scp; unsigned long timeout; bool expired; - void __iomem *ctl_addr = scpd->ctl_addr; - u32 pdn_ack = scpd->sram_pdn_ack_bits; + void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs; + u32 pdn_ack = scpd->data->sram_pdn_ack_bits; u32 val; int ret; int i; - if (scpd->bus_prot_mask) { + if (scpd->data->bus_prot_mask) { ret = mtk_infracfg_set_bus_protection(scp->infracfg, - scpd->bus_prot_mask); + scpd->data->bus_prot_mask); if (ret) goto out; } val = readl(ctl_addr); - val |= scpd->sram_pdn_bits; + val |= scpd->data->sram_pdn_bits; writel(val, ctl_addr); /* wait until SRAM_PDN_ACK all 1 */ @@ -409,10 +405,10 @@ static bool scpsys_active_wakeup(struct device *dev) genpd = pd_to_genpd(dev->pm_domain); scpd = container_of(genpd, struct scp_domain, genpd); - return scpd->active_wakeup; + return scpd->data->active_wakeup; } -static int __init scpsys_probe(struct platform_device *pdev) +static int scpsys_probe(struct platform_device *pdev) { struct genpd_onecell_data *pd_data; struct resource *res; @@ -485,12 +481,7 @@ static int __init scpsys_probe(struct platform_device *pdev) pd_data->domains[i] = genpd; scpd->scp = scp; - scpd->sta_mask = data->sta_mask; - scpd->ctl_addr = scp->base + data->ctl_offs; - scpd->sram_pdn_bits = data->sram_pdn_bits; - scpd->sram_pdn_ack_bits = data->sram_pdn_ack_bits; - scpd->bus_prot_mask = data->bus_prot_mask; - scpd->active_wakeup = data->active_wakeup; + scpd->data = data; for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) scpd->clk[j] = clk[data->clk_id[j]]; @@ -542,10 +533,12 @@ static const struct of_device_id of_scpsys_match_tbl[] = { }; static struct platform_driver scpsys_drv = { + .probe = scpsys_probe, .driver = { .name = "mtk-scpsys", + .suppress_bind_attrs = true, .owner = THIS_MODULE, .of_match_table = of_match_ptr(of_scpsys_match_tbl), }, }; -builtin_platform_driver_probe(scpsys_drv, scpsys_probe); +builtin_platform_driver(scpsys_drv); -- cgit v1.2.3 From 768e159f433c97f5221a3662217de5a1cb3b9b95 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 21 Jan 2016 17:32:43 +0000 Subject: drm/i915: Improve handling of overlapping objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The generic interval tree we use to speed up range invalidation is an augmented rbtree that can report all overlapping intervals for a given range. Therefore we do not need to degrade to a linear list if we find overlapping objects. Oops. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Michał Winiarski Link: http://patchwork.freedesktop.org/patch/msgid/1453397563-2848-1-git-send-email-chris@chris-wilson.co.uk Reviewed-by: Michał Winiarski Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_userptr.c | 181 +++++++++----------------------- 1 file changed, 50 insertions(+), 131 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 19fb0bddc1cd..74a4d1714879 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -49,21 +49,18 @@ struct i915_mmu_notifier { struct hlist_node node; struct mmu_notifier mn; struct rb_root objects; - struct list_head linear; - bool has_linear; }; struct i915_mmu_object { struct i915_mmu_notifier *mn; + struct drm_i915_gem_object *obj; struct interval_tree_node it; struct list_head link; - struct drm_i915_gem_object *obj; struct work_struct work; - bool active; - bool is_linear; + bool attached; }; -static void __cancel_userptr__worker(struct work_struct *work) +static void cancel_userptr(struct work_struct *work) { struct i915_mmu_object *mo = container_of(work, typeof(*mo), work); struct drm_i915_gem_object *obj = mo->obj; @@ -94,24 +91,22 @@ static void __cancel_userptr__worker(struct work_struct *work) mutex_unlock(&dev->struct_mutex); } -static unsigned long cancel_userptr(struct i915_mmu_object *mo) +static void add_object(struct i915_mmu_object *mo) { - unsigned long end = mo->obj->userptr.ptr + mo->obj->base.size; - - /* The mmu_object is released late when destroying the - * GEM object so it is entirely possible to gain a - * reference on an object in the process of being freed - * since our serialisation is via the spinlock and not - * the struct_mutex - and consequently use it after it - * is freed and then double free it. - */ - if (mo->active && kref_get_unless_zero(&mo->obj->base.refcount)) { - schedule_work(&mo->work); - /* only schedule one work packet to avoid the refleak */ - mo->active = false; - } + if (mo->attached) + return; + + interval_tree_insert(&mo->it, &mo->mn->objects); + mo->attached = true; +} - return end; +static void del_object(struct i915_mmu_object *mo) +{ + if (!mo->attached) + return; + + interval_tree_remove(&mo->it, &mo->mn->objects); + mo->attached = false; } static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn, @@ -122,28 +117,36 @@ static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn, struct i915_mmu_notifier *mn = container_of(_mn, struct i915_mmu_notifier, mn); struct i915_mmu_object *mo; + struct interval_tree_node *it; + LIST_HEAD(cancelled); + + if (RB_EMPTY_ROOT(&mn->objects)) + return; /* interval ranges are inclusive, but invalidate range is exclusive */ end--; spin_lock(&mn->lock); - if (mn->has_linear) { - list_for_each_entry(mo, &mn->linear, link) { - if (mo->it.last < start || mo->it.start > end) - continue; - - cancel_userptr(mo); - } - } else { - struct interval_tree_node *it; + it = interval_tree_iter_first(&mn->objects, start, end); + while (it) { + /* The mmu_object is released late when destroying the + * GEM object so it is entirely possible to gain a + * reference on an object in the process of being freed + * since our serialisation is via the spinlock and not + * the struct_mutex - and consequently use it after it + * is freed and then double free it. To prevent that + * use-after-free we only acquire a reference on the + * object if it is not in the process of being destroyed. + */ + mo = container_of(it, struct i915_mmu_object, it); + if (kref_get_unless_zero(&mo->obj->base.refcount)) + schedule_work(&mo->work); - it = interval_tree_iter_first(&mn->objects, start, end); - while (it) { - mo = container_of(it, struct i915_mmu_object, it); - start = cancel_userptr(mo); - it = interval_tree_iter_next(it, start, end); - } + list_add(&mo->link, &cancelled); + it = interval_tree_iter_next(it, start, end); } + list_for_each_entry(mo, &cancelled, link) + del_object(mo); spin_unlock(&mn->lock); } @@ -164,8 +167,6 @@ i915_mmu_notifier_create(struct mm_struct *mm) spin_lock_init(&mn->lock); mn->mn.ops = &i915_gem_userptr_notifier; mn->objects = RB_ROOT; - INIT_LIST_HEAD(&mn->linear); - mn->has_linear = false; /* Protected by mmap_sem (write-lock) */ ret = __mmu_notifier_register(&mn->mn, mm); @@ -177,85 +178,6 @@ i915_mmu_notifier_create(struct mm_struct *mm) return mn; } -static int -i915_mmu_notifier_add(struct drm_device *dev, - struct i915_mmu_notifier *mn, - struct i915_mmu_object *mo) -{ - struct interval_tree_node *it; - int ret = 0; - - /* By this point we have already done a lot of expensive setup that - * we do not want to repeat just because the caller (e.g. X) has a - * signal pending (and partly because of that expensive setup, X - * using an interrupt timer is likely to get stuck in an EINTR loop). - */ - mutex_lock(&dev->struct_mutex); - - /* Make sure we drop the final active reference (and thereby - * remove the objects from the interval tree) before we do - * the check for overlapping objects. - */ - i915_gem_retire_requests(dev); - - spin_lock(&mn->lock); - it = interval_tree_iter_first(&mn->objects, - mo->it.start, mo->it.last); - if (it) { - struct drm_i915_gem_object *obj; - - /* We only need to check the first object in the range as it - * either has cancelled gup work queued and we need to - * return back to the user to give time for the gup-workers - * to flush their object references upon which the object will - * be removed from the interval-tree, or the the range is - * still in use by another client and the overlap is invalid. - * - * If we do have an overlap, we cannot use the interval tree - * for fast range invalidation. - */ - - obj = container_of(it, struct i915_mmu_object, it)->obj; - if (!obj->userptr.workers) - mn->has_linear = mo->is_linear = true; - else - ret = -EAGAIN; - } else - interval_tree_insert(&mo->it, &mn->objects); - - if (ret == 0) - list_add(&mo->link, &mn->linear); - - spin_unlock(&mn->lock); - mutex_unlock(&dev->struct_mutex); - - return ret; -} - -static bool i915_mmu_notifier_has_linear(struct i915_mmu_notifier *mn) -{ - struct i915_mmu_object *mo; - - list_for_each_entry(mo, &mn->linear, link) - if (mo->is_linear) - return true; - - return false; -} - -static void -i915_mmu_notifier_del(struct i915_mmu_notifier *mn, - struct i915_mmu_object *mo) -{ - spin_lock(&mn->lock); - list_del(&mo->link); - if (mo->is_linear) - mn->has_linear = i915_mmu_notifier_has_linear(mn); - else - interval_tree_remove(&mo->it, &mn->objects); - spin_unlock(&mn->lock); -} - static void i915_gem_userptr_release__mmu_notifier(struct drm_i915_gem_object *obj) { @@ -265,7 +187,9 @@ i915_gem_userptr_release__mmu_notifier(struct drm_i915_gem_object *obj) if (mo == NULL) return; - i915_mmu_notifier_del(mo->mn, mo); + spin_lock(&mo->mn->lock); + del_object(mo); + spin_unlock(&mo->mn->lock); kfree(mo); obj->userptr.mmu_object = NULL; @@ -299,7 +223,6 @@ i915_gem_userptr_init__mmu_notifier(struct drm_i915_gem_object *obj, { struct i915_mmu_notifier *mn; struct i915_mmu_object *mo; - int ret; if (flags & I915_USERPTR_UNSYNCHRONIZED) return capable(CAP_SYS_ADMIN) ? 0 : -EPERM; @@ -316,16 +239,10 @@ i915_gem_userptr_init__mmu_notifier(struct drm_i915_gem_object *obj, return -ENOMEM; mo->mn = mn; - mo->it.start = obj->userptr.ptr; - mo->it.last = mo->it.start + obj->base.size - 1; mo->obj = obj; - INIT_WORK(&mo->work, __cancel_userptr__worker); - - ret = i915_mmu_notifier_add(obj->base.dev, mn, mo); - if (ret) { - kfree(mo); - return ret; - } + mo->it.start = obj->userptr.ptr; + mo->it.last = obj->userptr.ptr + obj->base.size - 1; + INIT_WORK(&mo->work, cancel_userptr); obj->userptr.mmu_object = mo; return 0; @@ -552,8 +469,10 @@ __i915_gem_userptr_set_active(struct drm_i915_gem_object *obj, /* In order to serialise get_pages with an outstanding * cancel_userptr, we must drop the struct_mutex and try again. */ - if (!value || !work_pending(&obj->userptr.mmu_object->work)) - obj->userptr.mmu_object->active = value; + if (!value) + del_object(obj->userptr.mmu_object); + else if (!work_pending(&obj->userptr.mmu_object->work)) + add_object(obj->userptr.mmu_object); else ret = -EAGAIN; spin_unlock(&obj->userptr.mmu_object->mn->lock); -- cgit v1.2.3 From 1803c035efb88afb9d3e7feb279ac29a83216382 Mon Sep 17 00:00:00 2001 From: Nick Hoath Date: Thu, 21 Jan 2016 19:37:45 +0000 Subject: drm/i915: Fix context/engine cleanup order Swap the order of context & engine cleanup, so that contexts are cleaned up first, and *then* engines. This is a more sensible order anyway, but in particular has become necessary since the 'intel_ring_initialized() must be simple and inline' patch, which now uses ring->dev as an 'initialised' flag, so it can now be NULL after engine teardown. This in turn can cause a problem in the context code, which (used to) check the ring->dev->struct_mutex -- causing a fault if ring->dev was NULL. Also rename the cleanup function to reflect what it actually does (cleanup engines, not a ringbuffer), and fix an annoying whitespace issue. v2: Also make the fix in i915_load_modeset_init, not just in i915_driver_unload (Chris Wilson) v3: Had extra stuff in it. v4: Reverted extra stuff (so we're back to v2). Rebased and updated commentary above (Dave Gordon). Signed-off-by: Nick Hoath Signed-off-by: Dave Gordon Reviewed-by: Chris Wilson (v2) Cc: Mika Kuoppala Cc: Daniel Vetter Cc: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1453405067-32890-3-git-send-email-david.s.gordon@intel.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 4 ++-- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 23 ++++++++++++----------- 3 files changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index d70d96fe553b..4725e8d61d0f 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -451,8 +451,8 @@ static int i915_load_modeset_init(struct drm_device *dev) cleanup_gem: mutex_lock(&dev->struct_mutex); - i915_gem_cleanup_ringbuffer(dev); i915_gem_context_fini(dev); + i915_gem_cleanup_engines(dev); mutex_unlock(&dev->struct_mutex); cleanup_irq: intel_guc_ucode_fini(dev); @@ -1196,8 +1196,8 @@ int i915_driver_unload(struct drm_device *dev) intel_guc_ucode_fini(dev); mutex_lock(&dev->struct_mutex); - i915_gem_cleanup_ringbuffer(dev); i915_gem_context_fini(dev); + i915_gem_cleanup_engines(dev); mutex_unlock(&dev->struct_mutex); intel_fbc_cleanup_cfb(dev_priv); i915_gem_cleanup_stolen(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 211af534e5d0..01cc982f5497 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3019,7 +3019,7 @@ int i915_gem_init_rings(struct drm_device *dev); int __must_check i915_gem_init_hw(struct drm_device *dev); int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice); void i915_gem_init_swizzling(struct drm_device *dev); -void i915_gem_cleanup_ringbuffer(struct drm_device *dev); +void i915_gem_cleanup_engines(struct drm_device *dev); int __must_check i915_gpu_idle(struct drm_device *dev); int __must_check i915_gem_suspend(struct drm_device *dev); void __i915_add_request(struct drm_i915_gem_request *req, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 371bbb28c471..799a53ad04f2 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4912,7 +4912,7 @@ i915_gem_init_hw(struct drm_device *dev) req = i915_gem_request_alloc(ring, NULL); if (IS_ERR(req)) { ret = PTR_ERR(req); - i915_gem_cleanup_ringbuffer(dev); + i915_gem_cleanup_engines(dev); goto out; } @@ -4925,7 +4925,7 @@ i915_gem_init_hw(struct drm_device *dev) if (ret && ret != -EIO) { DRM_ERROR("PPGTT enable ring #%d failed %d\n", i, ret); i915_gem_request_cancel(req); - i915_gem_cleanup_ringbuffer(dev); + i915_gem_cleanup_engines(dev); goto out; } @@ -4933,7 +4933,7 @@ i915_gem_init_hw(struct drm_device *dev) if (ret && ret != -EIO) { DRM_ERROR("Context enable ring #%d failed %d\n", i, ret); i915_gem_request_cancel(req); - i915_gem_cleanup_ringbuffer(dev); + i915_gem_cleanup_engines(dev); goto out; } @@ -5008,7 +5008,7 @@ out_unlock: } void -i915_gem_cleanup_ringbuffer(struct drm_device *dev) +i915_gem_cleanup_engines(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *ring; @@ -5017,13 +5017,14 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev) for_each_ring(ring, dev_priv, i) dev_priv->gt.cleanup_ring(ring); - if (i915.enable_execlists) - /* - * Neither the BIOS, ourselves or any other kernel - * expects the system to be in execlists mode on startup, - * so we need to reset the GPU back to legacy mode. - */ - intel_gpu_reset(dev); + if (i915.enable_execlists) { + /* + * Neither the BIOS, ourselves or any other kernel + * expects the system to be in execlists mode on startup, + * so we need to reset the GPU back to legacy mode. + */ + intel_gpu_reset(dev); + } } static void -- cgit v1.2.3 From fb740cf2492cc1e8f2216bc5ad9f5b2c49a32752 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 22:40:59 +0100 Subject: drm: Create drm_send_event helpers Use them in the core vblank code and exynos/vmwgfx drivers. Note that the difference between wake_up_all and _interruptible in vmwgfx doesn't matter since the only waiter is the core code in drm_fops.c. And that is interruptible. v2: Adjust existing kerneldoc too. Reviewed-by: Alex Deucher (v1) Acked-by: Daniel Stone Cc: Alex Deucher Cc: Thomas Hellstrom Cc: Inki Dae Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-6-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Laurent Pinchart [danvet: Squash in compile fixup, spotted by 0-day.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_fops.c | 42 ++++++++++++++++++++++++++++++++- drivers/gpu/drm/drm_irq.c | 7 ++---- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 6 +---- drivers/gpu/drm/exynos/exynos_drm_ipp.c | 6 +---- drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 3 +-- include/drm/drmP.h | 2 ++ 6 files changed, 48 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index f9eacbb2d1dd..e13501e3606e 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -687,7 +687,9 @@ EXPORT_SYMBOL(drm_poll); * This function prepares the passed in event for eventual delivery. If the event * doesn't get delivered (because the IOCTL fails later on, before queuing up * anything) then the even must be cancelled and freed using - * drm_event_cancel_free(). + * drm_event_cancel_free(). Successfully initialized events should be sent out + * using drm_send_event() or drm_send_event_locked() to signal completion of the + * asynchronous event to userspace. * * If callers embedded @p into a larger structure it must be allocated with * kmalloc and @p must be the first member element. @@ -743,3 +745,41 @@ void drm_event_cancel_free(struct drm_device *dev, p->destroy(p); } EXPORT_SYMBOL(drm_event_cancel_free); + +/** + * drm_send_event_locked - send DRM event to file descriptor + * @dev: DRM device + * @e: DRM event to deliver + * + * This function sends the event @e, initialized with drm_event_reserve_init(), + * to its associated userspace DRM file. Callers must already hold + * dev->event_lock, see drm_send_event() for the unlocked version. + */ +void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e) +{ + assert_spin_locked(&dev->event_lock); + + list_add_tail(&e->link, + &e->file_priv->event_list); + wake_up_interruptible(&e->file_priv->event_wait); +} +EXPORT_SYMBOL(drm_send_event_locked); + +/** + * drm_send_event - send DRM event to file descriptor + * @dev: DRM device + * @e: DRM event to deliver + * + * This function sends the event @e, initialized with drm_event_reserve_init(), + * to its associated userspace DRM file. This function acquires dev->event_lock, + * see drm_send_event_locked() for callers which already hold this lock. + */ +void drm_send_event(struct drm_device *dev, struct drm_pending_event *e) +{ + unsigned long irqflags; + + spin_lock_irqsave(&dev->event_lock, irqflags); + drm_send_event_locked(dev, e); + spin_unlock_irqrestore(&dev->event_lock, irqflags); +} +EXPORT_SYMBOL(drm_send_event); diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index d12a4efa651b..4ec8bca643ac 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -983,15 +983,12 @@ static void send_vblank_event(struct drm_device *dev, struct drm_pending_vblank_event *e, unsigned long seq, struct timeval *now) { - assert_spin_locked(&dev->event_lock); - e->event.sequence = seq; e->event.tv_sec = now->tv_sec; e->event.tv_usec = now->tv_usec; - list_add_tail(&e->base.link, - &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); + drm_send_event_locked(dev, &e->base); + trace_drm_vblank_event_delivered(e->base.pid, e->pipe, e->event.sequence); } diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 82e7f95dfed9..99369816ff97 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -880,7 +880,6 @@ static void g2d_finish_event(struct g2d_data *g2d, u32 cmdlist_no) struct g2d_runqueue_node *runqueue_node = g2d->runqueue_node; struct drm_exynos_pending_g2d_event *e; struct timeval now; - unsigned long flags; if (list_empty(&runqueue_node->event_list)) return; @@ -893,10 +892,7 @@ static void g2d_finish_event(struct g2d_data *g2d, u32 cmdlist_no) e->event.tv_usec = now.tv_usec; e->event.cmdlist_no = cmdlist_no; - spin_lock_irqsave(&drm_dev->event_lock, flags); - list_move_tail(&e->base.link, &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); - spin_unlock_irqrestore(&drm_dev->event_lock, flags); + drm_send_event(drm_dev, &e->base); } static irqreturn_t g2d_irq_handler(int irq, void *dev_id) diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index c8819c05e2dd..3eab0d15f0b4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -1407,7 +1407,6 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv, struct drm_exynos_ipp_send_event *e; struct list_head *head; struct timeval now; - unsigned long flags; u32 tbuf_id[EXYNOS_DRM_OPS_MAX] = {0, }; int ret, i; @@ -1520,10 +1519,7 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv, for_each_ipp_ops(i) e->event.buf_id[i] = tbuf_id[i]; - spin_lock_irqsave(&drm_dev->event_lock, flags); - list_move_tail(&e->base.link, &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); - spin_unlock_irqrestore(&drm_dev->event_lock, flags); + drm_send_event(drm_dev, &e->base); mutex_unlock(&c_node->event_lock); DRM_DEBUG_KMS("done cmd[%d]prop_id[%d]buf_id[%d]\n", diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index eda93bf52a6e..e0edf149d9d5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -880,9 +880,8 @@ static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action) } list_del_init(&eaction->fpriv_head); - list_add_tail(&eaction->event->link, &file_priv->event_list); eaction->event = NULL; - wake_up_all(&file_priv->event_wait); + drm_send_event_locked(dev, eaction->event); spin_unlock_irqrestore(&dev->event_lock, irq_flags); } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 04a66468e6e0..306ef32ec086 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -932,6 +932,8 @@ int drm_event_reserve_init(struct drm_device *dev, struct drm_event *e); void drm_event_cancel_free(struct drm_device *dev, struct drm_pending_event *p); +void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e); +void drm_send_event(struct drm_device *dev, struct drm_pending_event *e); /* Misc. IOCTL support (drm_ioctl.c) */ int drm_noop(struct drm_device *dev, void *data, -- cgit v1.2.3 From 0b5ef656f764e6cc1fe1e0aaf080a19560f2f76a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 22:41:00 +0100 Subject: drm/fsl: Remove preclose hook Doesn't do anything, but annoys when auditing them all. Cc: Jianwei Wang Acked-by: Daniel Stone Reviewed-by: Alex Deucher Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-7-git-send-email-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter --- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index fca97d3fc846..9648b7f9a31c 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c @@ -112,10 +112,6 @@ static int fsl_dcu_unload(struct drm_device *dev) return 0; } -static void fsl_dcu_drm_preclose(struct drm_device *dev, struct drm_file *file) -{ -} - static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg) { struct drm_device *dev = arg; @@ -191,7 +187,6 @@ static struct drm_driver fsl_dcu_drm_driver = { | DRIVER_PRIME | DRIVER_ATOMIC, .load = fsl_dcu_load, .unload = fsl_dcu_unload, - .preclose = fsl_dcu_drm_preclose, .irq_handler = fsl_dcu_drm_irq, .get_vblank_counter = drm_vblank_no_hw_counter, .enable_vblank = fsl_dcu_drm_enable_vblank, -- cgit v1.2.3 From d704f8e1a649a6dc1cca693846df96e54d80744f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 22:41:01 +0100 Subject: drm/armada: Remove NULL open/pre/postclose hooks The compiler will do this, but the void hits when grepping all the hooks for a subsystem wide audit are slightly annoying. So remove them for next time around. Cc: Russell King Acked-by: Daniel Stone Reviewed-by: Alex Deucher Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-8-git-send-email-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter --- drivers/gpu/drm/armada/armada_drv.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 3bd7e1cde99e..82043c204b76 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -188,9 +188,6 @@ static const struct file_operations armada_drm_fops = { static struct drm_driver armada_drm_driver = { .load = armada_drm_load, - .open = NULL, - .preclose = NULL, - .postclose = NULL, .lastclose = armada_drm_lastclose, .unload = armada_drm_unload, .set_busid = drm_platform_set_busid, -- cgit v1.2.3 From 941a77b078e6127c4d441439ad1669347750288e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 22:41:02 +0100 Subject: drm/gma500: Remove empty preclose hook I'm auditing them all, empty ones just confuse ... Cc: Patrik Jakobsson Acked-by: Daniel Stone Reviewed-by: Alex Deucher Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-9-git-send-email-daniel.vetter@ffwll.ch Acked-by: Patrik Jakobsson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/gma500/psb_drv.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 92e7e5795398..4e1c6850520e 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -442,14 +442,6 @@ static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd, /* FIXME: do we need to wrap the other side of this */ } -/* - * When a client dies: - * - Check for and clean up flipped page state - */ -static void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv) -{ -} - static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { return drm_get_pci_dev(pdev, ent, &driver); @@ -495,7 +487,6 @@ static struct drm_driver driver = { .load = psb_driver_load, .unload = psb_driver_unload, .lastclose = psb_driver_lastclose, - .preclose = psb_driver_preclose, .set_busid = drm_pci_set_busid, .num_ioctls = ARRAY_SIZE(psb_ioctls), -- cgit v1.2.3 From 09859d2a3c2090ae2452cbf1c8fdde30ba38d934 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 13 Jan 2016 15:31:16 +0100 Subject: drm/crtc-helper: Add caveat to disable_unused_functions doc This shouldn't be used by atomic drivers any more, it confuses the state tracking. Cc: Maxime Ripard Cc: Laurent Pinchart Acked-by: Laurent Pinchart Link: http://patchwork.freedesktop.org/patch/msgid/1452695476-31147-1-git-send-email-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc_helper.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 5d4bc6441d88..9f8b894f4480 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -220,6 +220,15 @@ static void __drm_helper_disable_unused_functions(struct drm_device *dev) * disconnected connectors. Then it will disable all unused encoders and CRTCs * either by calling their disable callback if available or by calling their * dpms callback with DRM_MODE_DPMS_OFF. + * + * NOTE: + * + * This function is part of the legacy modeset helper library and will cause + * major confusion with atomic drivers. This is because atomic helpers guarantee + * to never call ->disable() hooks on a disabled function, or ->enable() hooks + * on an enabled functions. drm_helper_disable_unused_functions() on the other + * hand throws such guarantees into the wind and calls disable hooks + * unconditionally on unused functions. */ void drm_helper_disable_unused_functions(struct drm_device *dev) { -- cgit v1.2.3 From 8d1a0ae724ad74ef7946a45e3b2d3e01f39df02b Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Wed, 13 Jan 2016 23:36:26 -0500 Subject: ARM: perf: Set ARMv7 SDER SUNIDEN bit ARMv7 counters other than the CPU cycle counter only work if the Secure Debug Enable Register (SDER) SUNIDEN bit is set. Since access to the SDER is only possible in secure state, it will only be done if the device tree property "secure-reg-access" is set. Without this: Performance counter stats for 'sleep 1': 14606094 cycles # 0.000 GHz 0 instructions # 0.00 insns per cycle After applying: Performance counter stats for 'sleep 1': 5843809 cycles 2566484 instructions # 0.44 insns per cycle 1.020144000 seconds time elapsed Some platforms (eg i.MX53) may also need additional platform specific setup. Acked-by: Rob Herring Signed-off-by: Martin Fuzzey Signed-off-by: Pooya Keshavarzi Signed-off-by: George G. Davis [will: add warning if property is found on arm64] Signed-off-by: Will Deacon --- Documentation/devicetree/bindings/arm/pmu.txt | 10 ++++++++++ arch/arm/kernel/perf_event_v7.c | 13 ++++++++++++- drivers/perf/arm_pmu.c | 9 +++++++++ include/linux/perf/arm_pmu.h | 1 + 4 files changed, 32 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/arm/pmu.txt b/Documentation/devicetree/bindings/arm/pmu.txt index 56518839f52a..b6056d3bca06 100644 --- a/Documentation/devicetree/bindings/arm/pmu.txt +++ b/Documentation/devicetree/bindings/arm/pmu.txt @@ -46,6 +46,16 @@ Optional properties: - qcom,no-pc-write : Indicates that this PMU doesn't support the 0xc and 0xd events. +- secure-reg-access : Indicates that the ARMv7 Secure Debug Enable Register + (SDER) is accessible. This will cause the driver to do + any setup required that is only possible in ARMv7 secure + state. If not present the ARMv7 SDER will not be touched, + which means the PMU may fail to operate unless external + code (bootloader or security monitor) has performed the + appropriate initialisation. Note that this property is + not valid for non-ARMv7 CPUs or ARMv7 CPUs booting Linux + in Non-secure state. + Example: pmu { diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 4152158f6e6a..15063851cd10 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -712,6 +712,11 @@ static const struct attribute_group *armv7_pmuv2_attr_groups[] = { #define ARMV7_EXCLUDE_USER (1 << 30) #define ARMV7_INCLUDE_HYP (1 << 27) +/* + * Secure debug enable reg + */ +#define ARMV7_SDER_SUNIDEN BIT(1) /* Permit non-invasive debug */ + static inline u32 armv7_pmnc_read(void) { u32 val; @@ -1094,7 +1099,13 @@ static int armv7pmu_set_event_filter(struct hw_perf_event *event, static void armv7pmu_reset(void *info) { struct arm_pmu *cpu_pmu = (struct arm_pmu *)info; - u32 idx, nb_cnt = cpu_pmu->num_events; + u32 idx, nb_cnt = cpu_pmu->num_events, val; + + if (cpu_pmu->secure_access) { + asm volatile("mrc p15, 0, %0, c1, c1, 1" : "=r" (val)); + val |= ARMV7_SDER_SUNIDEN; + asm volatile("mcr p15, 0, %0, c1, c1, 1" : : "r" (val)); + } /* The counter and interrupt enable registers are unknown at reset. */ for (idx = ARMV7_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx) { diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c index 166637f2917c..eb5bee07526b 100644 --- a/drivers/perf/arm_pmu.c +++ b/drivers/perf/arm_pmu.c @@ -889,6 +889,15 @@ int arm_pmu_device_probe(struct platform_device *pdev, if (node && (of_id = of_match_node(of_table, pdev->dev.of_node))) { init_fn = of_id->data; + pmu->secure_access = of_property_read_bool(pdev->dev.of_node, + "secure-reg-access"); + + /* arm64 systems boot only as non-secure */ + if (IS_ENABLED(CONFIG_ARM64) && pmu->secure_access) { + pr_warn("ignoring \"secure-reg-access\" property for arm64\n"); + pmu->secure_access = false; + } + ret = of_pmu_irq_cfg(pmu); if (!ret) ret = init_fn(pmu); diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h index 83b5e34c6580..2d5eaaa90078 100644 --- a/include/linux/perf/arm_pmu.h +++ b/include/linux/perf/arm_pmu.h @@ -104,6 +104,7 @@ struct arm_pmu { atomic_t active_events; struct mutex reserve_mutex; u64 max_period; + bool secure_access; /* 32-bit ARM only */ struct platform_device *plat_device; struct pmu_hw_events __percpu *hw_events; struct notifier_block hotplug_nb; -- cgit v1.2.3 From 426f04684b30ced3632b29b41cb5c97dca500dca Mon Sep 17 00:00:00 2001 From: Martin Roth Date: Sun, 24 Jan 2016 00:56:19 +0200 Subject: 82xx: FCC: Fixing a bug causing to FCC port lock-up (second try) This is an additional patch to the one already submitted recently. The previous patch was not complete, and the FCC port lock-up scenario has been reproduced in lab. I had an opportunity to check the current patch in lab and the FCC port lock no longer freezes, while the previous patch still locks-up the FCC port. The current patch fixes a pointer arithmetic bug (second bug in the same line), which leads FCC port lock-up during underrun/collision handling. Within the tx_startup() function in mac-fcc.c, the address of last BD is not calculated correctly. As a result of wrong calculation of the last BD address, the next transmitted BD may be set to an area out of the transmit BD ring. This actually causes to port lock-up and it is not recoverable. Signed-off-by: Martin Roth Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fs_enet/mac-fcc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c index 52e0091b4fb2..1ba359f17ec6 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c +++ b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c @@ -552,7 +552,7 @@ static void tx_restart(struct net_device *dev) cbd_t __iomem *prev_bd; cbd_t __iomem *last_tx_bd; - last_tx_bd = fep->tx_bd_base + ((fpi->tx_ring - 1) * sizeof(cbd_t)); + last_tx_bd = fep->tx_bd_base + (fpi->tx_ring - 1); /* get the current bd held in TBPTR and scan back from this point */ recheck_bd = curr_tbptr = (cbd_t __iomem *) -- cgit v1.2.3 From db0e51afa481088e6396f11e02018d64113a6578 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 24 Jan 2016 09:22:05 +0000 Subject: net: dsa: fix mv88e6xxx switches Since commit 76e398a62712 ("net: dsa: use switchdev obj for VLAN add/del ops"), the Marvell 88E6xxx switch has been unable to pass traffic between ports - any received traffic is discarded by the switch. Taking a port out of bridge mode and configuring a vlan on it also the port to start passing traffic. With the debugfs files re-instated to allow debug of this issue by comparing the register settings between the working and non-working case, the reason becomes clear: GLOBAL GLOBAL2 SERDES 0 1 2 3 4 5 6 - 7: 1111 707f 2001 2 2 2 2 2 0 2 + 7: 1111 707f 2001 1 1 1 1 1 0 1 Register 7 for the ports is the default vlan tag register, and in the non-working setup, it has been set to 2, despite vlan 2 not being configured. This causes the switch to drop all packets coming in to these ports. The working setup has the default vlan tag register set to 1, which is the default vlan when none is configured. Inspection of the code reveals why. The code prior to this commit was: - for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { ... - if (!err && vlan->flags & BRIDGE_VLAN_INFO_PVID) - err = ds->drv->port_pvid_set(ds, p->port, vid); but the new code is: + for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { ... + } ... + if (pvid) + err = _mv88e6xxx_port_pvid_set(ds, port, vid); This causes the new code to always set the default vlan to one higher than the old code. Fix this. Fixes: 76e398a62712 ("net: dsa: use switchdev obj for VLAN add/del ops") Cc: Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 9fe33fc3c2b9..9cc73bf0a081 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1532,7 +1532,7 @@ int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, /* no PVID with ranges, otherwise it's a bug */ if (pvid) - err = _mv88e6xxx_port_pvid_set(ds, port, vid); + err = _mv88e6xxx_port_pvid_set(ds, port, vlan->vid_end); unlock: mutex_unlock(&ps->smi_mutex); -- cgit v1.2.3 From 5cfa30397bc3677250a3e71aebde7b40ecb2b25a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 24 Jan 2016 16:52:37 +0100 Subject: net: fec: make driver endian-safe The driver treats the device descriptors as CPU-endian, which appears to be correct with the default endianness on both ARM (typically LE) and PowerPC (typically BE) SoCs, indicating that the hardware block is generated differently. Add endianness annotations and byteswaps as necessary. It's not clear that the ifdef there really is correct and shouldn't just be #ifdef CONFIG_ARM, but I also can't test on anything but the i.MX6 HummingBoard where this gets it working with a BE kernel. Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/Makefile | 3 + drivers/net/ethernet/freescale/fec.h | 40 ++++++--- drivers/net/ethernet/freescale/fec_main.c | 130 ++++++++++++++++-------------- 3 files changed, 101 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile index 4097c58d17a7..cbe21dc7e37e 100644 --- a/drivers/net/ethernet/freescale/Makefile +++ b/drivers/net/ethernet/freescale/Makefile @@ -4,6 +4,9 @@ obj-$(CONFIG_FEC) += fec.o fec-objs :=fec_main.o fec_ptp.o +CFLAGS_fec_main.o := -D__CHECK_ENDIAN__ +CFLAGS_fec_ptp.o := -D__CHECK_ENDIAN__ + obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y) obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 99d33e2d35e6..7dd47a0b8cfb 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -190,28 +190,46 @@ /* * Define the buffer descriptor structure. + * + * Evidently, ARM SoCs have the FEC block generated in a + * little endian mode; or at least ARCH_MXC/SOC_IMX28 do, + * so adjust endianness accordingly. */ #if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28) +#define fec32_to_cpu le32_to_cpu +#define fec16_to_cpu le16_to_cpu +#define cpu_to_fec32 cpu_to_le32 +#define cpu_to_fec16 cpu_to_le16 +#define __fec32 __le32 +#define __fec16 __le16 + struct bufdesc { - unsigned short cbd_datlen; /* Data length */ - unsigned short cbd_sc; /* Control and status info */ - unsigned long cbd_bufaddr; /* Buffer address */ + __fec16 cbd_datlen; /* Data length */ + __fec16 cbd_sc; /* Control and status info */ + __fec32 cbd_bufaddr; /* Buffer address */ }; #else +#define fec32_to_cpu be32_to_cpu +#define fec16_to_cpu be16_to_cpu +#define cpu_to_fec32 cpu_to_be32 +#define cpu_to_fec16 cpu_to_be16 +#define __fec32 __be32 +#define __fec16 __be16 + struct bufdesc { - unsigned short cbd_sc; /* Control and status info */ - unsigned short cbd_datlen; /* Data length */ - unsigned long cbd_bufaddr; /* Buffer address */ + __fec16 cbd_sc; /* Control and status info */ + __fec16 cbd_datlen; /* Data length */ + __fec32 cbd_bufaddr; /* Buffer address */ }; #endif struct bufdesc_ex { struct bufdesc desc; - unsigned long cbd_esc; - unsigned long cbd_prot; - unsigned long cbd_bdu; - unsigned long ts; - unsigned short res0[4]; + __fec32 cbd_esc; + __fec32 cbd_prot; + __fec32 cbd_bdu; + __fec32 ts; + __fec16 res0[4]; }; /* diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 502da6f48f95..3f3b9eacc286 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -332,11 +332,13 @@ static void fec_dump(struct net_device *ndev) bdp = txq->tx_bd_base; do { - pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p\n", + pr_info("%3u %c%c 0x%04x 0x%08x %4u %p\n", index, bdp == txq->cur_tx ? 'S' : ' ', bdp == txq->dirty_tx ? 'H' : ' ', - bdp->cbd_sc, bdp->cbd_bufaddr, bdp->cbd_datlen, + fec16_to_cpu(bdp->cbd_sc), + fec32_to_cpu(bdp->cbd_bufaddr), + fec16_to_cpu(bdp->cbd_datlen), txq->tx_skbuff[index]); bdp = fec_enet_get_nextdesc(bdp, fep, 0); index++; @@ -389,7 +391,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, bdp = fec_enet_get_nextdesc(bdp, fep, queue); ebdp = (struct bufdesc_ex *)bdp; - status = bdp->cbd_sc; + status = fec16_to_cpu(bdp->cbd_sc); status &= ~BD_ENET_TX_STATS; status |= (BD_ENET_TX_TC | BD_ENET_TX_READY); frag_len = skb_shinfo(skb)->frags[frag].size; @@ -411,7 +413,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, if (skb->ip_summed == CHECKSUM_PARTIAL) estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; ebdp->cbd_bdu = 0; - ebdp->cbd_esc = estatus; + ebdp->cbd_esc = cpu_to_fec32(estatus); } bufaddr = page_address(this_frag->page.p) + this_frag->page_offset; @@ -435,9 +437,9 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, goto dma_mapping_error; } - bdp->cbd_bufaddr = addr; - bdp->cbd_datlen = frag_len; - bdp->cbd_sc = status; + bdp->cbd_bufaddr = cpu_to_fec32(addr); + bdp->cbd_datlen = cpu_to_fec16(frag_len); + bdp->cbd_sc = cpu_to_fec16(status); } return bdp; @@ -445,8 +447,8 @@ dma_mapping_error: bdp = txq->cur_tx; for (i = 0; i < frag; i++) { bdp = fec_enet_get_nextdesc(bdp, fep, queue); - dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, - bdp->cbd_datlen, DMA_TO_DEVICE); + dma_unmap_single(&fep->pdev->dev, fec32_to_cpu(bdp->cbd_bufaddr), + fec16_to_cpu(bdp->cbd_datlen), DMA_TO_DEVICE); } return ERR_PTR(-ENOMEM); } @@ -483,7 +485,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, /* Fill in a Tx ring entry */ bdp = txq->cur_tx; last_bdp = bdp; - status = bdp->cbd_sc; + status = fec16_to_cpu(bdp->cbd_sc); status &= ~BD_ENET_TX_STATS; /* Set buffer length and buffer pointer */ @@ -539,21 +541,21 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; ebdp->cbd_bdu = 0; - ebdp->cbd_esc = estatus; + ebdp->cbd_esc = cpu_to_fec32(estatus); } index = fec_enet_get_bd_index(txq->tx_bd_base, last_bdp, fep); /* Save skb pointer */ txq->tx_skbuff[index] = skb; - bdp->cbd_datlen = buflen; - bdp->cbd_bufaddr = addr; + bdp->cbd_datlen = cpu_to_fec16(buflen); + bdp->cbd_bufaddr = cpu_to_fec32(addr); /* Send it on its way. Tell FEC it's ready, interrupt when done, * it's the last BD of the frame, and to put the CRC on the end. */ status |= (BD_ENET_TX_READY | BD_ENET_TX_TC); - bdp->cbd_sc = status; + bdp->cbd_sc = cpu_to_fec16(status); /* If this was the last BD in the ring, start at the beginning again. */ bdp = fec_enet_get_nextdesc(last_bdp, fep, queue); @@ -585,7 +587,7 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb, unsigned int estatus = 0; dma_addr_t addr; - status = bdp->cbd_sc; + status = fec16_to_cpu(bdp->cbd_sc); status &= ~BD_ENET_TX_STATS; status |= (BD_ENET_TX_TC | BD_ENET_TX_READY); @@ -607,8 +609,8 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb, return NETDEV_TX_BUSY; } - bdp->cbd_datlen = size; - bdp->cbd_bufaddr = addr; + bdp->cbd_datlen = cpu_to_fec16(size); + bdp->cbd_bufaddr = cpu_to_fec32(addr); if (fep->bufdesc_ex) { if (fep->quirks & FEC_QUIRK_HAS_AVB) @@ -616,7 +618,7 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb, if (skb->ip_summed == CHECKSUM_PARTIAL) estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; ebdp->cbd_bdu = 0; - ebdp->cbd_esc = estatus; + ebdp->cbd_esc = cpu_to_fec32(estatus); } /* Handle the last BD specially */ @@ -625,10 +627,10 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb, if (is_last) { status |= BD_ENET_TX_INTR; if (fep->bufdesc_ex) - ebdp->cbd_esc |= BD_ENET_TX_INT; + ebdp->cbd_esc |= cpu_to_fec32(BD_ENET_TX_INT); } - bdp->cbd_sc = status; + bdp->cbd_sc = cpu_to_fec16(status); return 0; } @@ -647,7 +649,7 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq, unsigned short status; unsigned int estatus = 0; - status = bdp->cbd_sc; + status = fec16_to_cpu(bdp->cbd_sc); status &= ~BD_ENET_TX_STATS; status |= (BD_ENET_TX_TC | BD_ENET_TX_READY); @@ -671,8 +673,8 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq, } } - bdp->cbd_bufaddr = dmabuf; - bdp->cbd_datlen = hdr_len; + bdp->cbd_bufaddr = cpu_to_fec32(dmabuf); + bdp->cbd_datlen = cpu_to_fec16(hdr_len); if (fep->bufdesc_ex) { if (fep->quirks & FEC_QUIRK_HAS_AVB) @@ -680,10 +682,10 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq, if (skb->ip_summed == CHECKSUM_PARTIAL) estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; ebdp->cbd_bdu = 0; - ebdp->cbd_esc = estatus; + ebdp->cbd_esc = cpu_to_fec32(estatus); } - bdp->cbd_sc = status; + bdp->cbd_sc = cpu_to_fec16(status); return 0; } @@ -823,15 +825,15 @@ static void fec_enet_bd_init(struct net_device *dev) /* Initialize the BD for every fragment in the page. */ if (bdp->cbd_bufaddr) - bdp->cbd_sc = BD_ENET_RX_EMPTY; + bdp->cbd_sc = cpu_to_fec16(BD_ENET_RX_EMPTY); else - bdp->cbd_sc = 0; + bdp->cbd_sc = cpu_to_fec16(0); bdp = fec_enet_get_nextdesc(bdp, fep, q); } /* Set the last buffer to wrap */ bdp = fec_enet_get_prevdesc(bdp, fep, q); - bdp->cbd_sc |= BD_SC_WRAP; + bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); rxq->cur_rx = rxq->rx_bd_base; } @@ -844,18 +846,18 @@ static void fec_enet_bd_init(struct net_device *dev) for (i = 0; i < txq->tx_ring_size; i++) { /* Initialize the BD for every fragment in the page. */ - bdp->cbd_sc = 0; + bdp->cbd_sc = cpu_to_fec16(0); if (txq->tx_skbuff[i]) { dev_kfree_skb_any(txq->tx_skbuff[i]); txq->tx_skbuff[i] = NULL; } - bdp->cbd_bufaddr = 0; + bdp->cbd_bufaddr = cpu_to_fec32(0); bdp = fec_enet_get_nextdesc(bdp, fep, q); } /* Set the last buffer to wrap */ bdp = fec_enet_get_prevdesc(bdp, fep, q); - bdp->cbd_sc |= BD_SC_WRAP; + bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); txq->dirty_tx = bdp; } } @@ -947,8 +949,10 @@ fec_restart(struct net_device *ndev) */ if (fep->quirks & FEC_QUIRK_ENET_MAC) { memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN); - writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW); - writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH); + writel((__force u32)cpu_to_be32(temp_mac[0]), + fep->hwp + FEC_ADDR_LOW); + writel((__force u32)cpu_to_be32(temp_mac[1]), + fep->hwp + FEC_ADDR_HIGH); } /* Clear any outstanding interrupt. */ @@ -1222,7 +1226,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) while (bdp != READ_ONCE(txq->cur_tx)) { /* Order the load of cur_tx and cbd_sc */ rmb(); - status = READ_ONCE(bdp->cbd_sc); + status = fec16_to_cpu(READ_ONCE(bdp->cbd_sc)); if (status & BD_ENET_TX_READY) break; @@ -1230,10 +1234,12 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) skb = txq->tx_skbuff[index]; txq->tx_skbuff[index] = NULL; - if (!IS_TSO_HEADER(txq, bdp->cbd_bufaddr)) - dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, - bdp->cbd_datlen, DMA_TO_DEVICE); - bdp->cbd_bufaddr = 0; + if (!IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr))) + dma_unmap_single(&fep->pdev->dev, + fec32_to_cpu(bdp->cbd_bufaddr), + fec16_to_cpu(bdp->cbd_datlen), + DMA_TO_DEVICE); + bdp->cbd_bufaddr = cpu_to_fec32(0); if (!skb) { bdp = fec_enet_get_nextdesc(bdp, fep, queue_id); continue; @@ -1264,7 +1270,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) struct skb_shared_hwtstamps shhwtstamps; struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; - fec_enet_hwtstamp(fep, ebdp->ts, &shhwtstamps); + fec_enet_hwtstamp(fep, fec32_to_cpu(ebdp->ts), &shhwtstamps); skb_tstamp_tx(skb, &shhwtstamps); } @@ -1324,10 +1330,8 @@ fec_enet_new_rxbdp(struct net_device *ndev, struct bufdesc *bdp, struct sk_buff if (off) skb_reserve(skb, fep->rx_align + 1 - off); - bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data, - FEC_ENET_RX_FRSIZE - fep->rx_align, - DMA_FROM_DEVICE); - if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) { + bdp->cbd_bufaddr = cpu_to_fec32(dma_map_single(&fep->pdev->dev, skb->data, FEC_ENET_RX_FRSIZE - fep->rx_align, DMA_FROM_DEVICE)); + if (dma_mapping_error(&fep->pdev->dev, fec32_to_cpu(bdp->cbd_bufaddr))) { if (net_ratelimit()) netdev_err(ndev, "Rx DMA memory map failed\n"); return -ENOMEM; @@ -1349,7 +1353,8 @@ static bool fec_enet_copybreak(struct net_device *ndev, struct sk_buff **skb, if (!new_skb) return false; - dma_sync_single_for_cpu(&fep->pdev->dev, bdp->cbd_bufaddr, + dma_sync_single_for_cpu(&fep->pdev->dev, + fec32_to_cpu(bdp->cbd_bufaddr), FEC_ENET_RX_FRSIZE - fep->rx_align, DMA_FROM_DEVICE); if (!swap) @@ -1396,7 +1401,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) */ bdp = rxq->cur_rx; - while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { + while (!((status = fec16_to_cpu(bdp->cbd_sc)) & BD_ENET_RX_EMPTY)) { if (pkt_received >= budget) break; @@ -1438,7 +1443,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) /* Process the incoming frame. */ ndev->stats.rx_packets++; - pkt_len = bdp->cbd_datlen; + pkt_len = fec16_to_cpu(bdp->cbd_datlen); ndev->stats.rx_bytes += pkt_len; index = fec_enet_get_bd_index(rxq->rx_bd_base, bdp, fep); @@ -1456,7 +1461,8 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) ndev->stats.rx_dropped++; goto rx_processing_done; } - dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, + dma_unmap_single(&fep->pdev->dev, + fec32_to_cpu(bdp->cbd_bufaddr), FEC_ENET_RX_FRSIZE - fep->rx_align, DMA_FROM_DEVICE); } @@ -1475,7 +1481,8 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) /* If this is a VLAN packet remove the VLAN Tag */ vlan_packet_rcvd = false; if ((ndev->features & NETIF_F_HW_VLAN_CTAG_RX) && - fep->bufdesc_ex && (ebdp->cbd_esc & BD_ENET_RX_VLAN)) { + fep->bufdesc_ex && + (ebdp->cbd_esc & cpu_to_fec32(BD_ENET_RX_VLAN))) { /* Push and remove the vlan tag */ struct vlan_hdr *vlan_header = (struct vlan_hdr *) (data + ETH_HLEN); @@ -1491,12 +1498,12 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) /* Get receive timestamp from the skb */ if (fep->hwts_rx_en && fep->bufdesc_ex) - fec_enet_hwtstamp(fep, ebdp->ts, + fec_enet_hwtstamp(fep, fec32_to_cpu(ebdp->ts), skb_hwtstamps(skb)); if (fep->bufdesc_ex && (fep->csum_flags & FLAG_RX_CSUM_ENABLED)) { - if (!(ebdp->cbd_esc & FLAG_RX_CSUM_ERROR)) { + if (!(ebdp->cbd_esc & cpu_to_fec32(FLAG_RX_CSUM_ERROR))) { /* don't check it */ skb->ip_summed = CHECKSUM_UNNECESSARY; } else { @@ -1513,7 +1520,8 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) napi_gro_receive(&fep->napi, skb); if (is_copybreak) { - dma_sync_single_for_device(&fep->pdev->dev, bdp->cbd_bufaddr, + dma_sync_single_for_device(&fep->pdev->dev, + fec32_to_cpu(bdp->cbd_bufaddr), FEC_ENET_RX_FRSIZE - fep->rx_align, DMA_FROM_DEVICE); } else { @@ -1527,12 +1535,12 @@ rx_processing_done: /* Mark the buffer empty */ status |= BD_ENET_RX_EMPTY; - bdp->cbd_sc = status; + bdp->cbd_sc = cpu_to_fec16(status); if (fep->bufdesc_ex) { struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; - ebdp->cbd_esc = BD_ENET_RX_INT; + ebdp->cbd_esc = cpu_to_fec32(BD_ENET_RX_INT); ebdp->cbd_prot = 0; ebdp->cbd_bdu = 0; } @@ -2662,7 +2670,7 @@ static void fec_enet_free_buffers(struct net_device *ndev) rxq->rx_skbuff[i] = NULL; if (skb) { dma_unmap_single(&fep->pdev->dev, - bdp->cbd_bufaddr, + fec32_to_cpu(bdp->cbd_bufaddr), FEC_ENET_RX_FRSIZE - fep->rx_align, DMA_FROM_DEVICE); dev_kfree_skb(skb); @@ -2777,11 +2785,11 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue) } rxq->rx_skbuff[i] = skb; - bdp->cbd_sc = BD_ENET_RX_EMPTY; + bdp->cbd_sc = cpu_to_fec16(BD_ENET_RX_EMPTY); if (fep->bufdesc_ex) { struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; - ebdp->cbd_esc = BD_ENET_RX_INT; + ebdp->cbd_esc = cpu_to_fec32(BD_ENET_RX_INT); } bdp = fec_enet_get_nextdesc(bdp, fep, queue); @@ -2789,7 +2797,7 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue) /* Set the last buffer to wrap. */ bdp = fec_enet_get_prevdesc(bdp, fep, queue); - bdp->cbd_sc |= BD_SC_WRAP; + bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); return 0; err_alloc: @@ -2812,12 +2820,12 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue) if (!txq->tx_bounce[i]) goto err_alloc; - bdp->cbd_sc = 0; - bdp->cbd_bufaddr = 0; + bdp->cbd_sc = cpu_to_fec16(0); + bdp->cbd_bufaddr = cpu_to_fec32(0); if (fep->bufdesc_ex) { struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; - ebdp->cbd_esc = BD_ENET_TX_INT; + ebdp->cbd_esc = cpu_to_fec32(BD_ENET_TX_INT); } bdp = fec_enet_get_nextdesc(bdp, fep, queue); @@ -2825,7 +2833,7 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue) /* Set the last buffer to wrap. */ bdp = fec_enet_get_prevdesc(bdp, fep, queue); - bdp->cbd_sc |= BD_SC_WRAP; + bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); return 0; -- cgit v1.2.3 From 36df745536ab81956cf68329c8049ad07f4a0cf0 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 25 Jan 2016 11:43:09 +0530 Subject: net: macb: fix build warning We are getting build warning about: macb.c:2889:13: warning: 'tx_clk' may be used uninitialized in this function macb.c:2888:11: warning: 'hclk' may be used uninitialized in this function In reality they are not used uninitialized as clk_init() will initialize them, this patch will just silence the warning. Signed-off-by: Sudip Mukherjee Acked-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 9d9984a87d42..50c94104f19c 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -2823,7 +2823,7 @@ static int macb_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct device_node *phy_node; const struct macb_config *macb_config = NULL; - struct clk *pclk, *hclk, *tx_clk; + struct clk *pclk, *hclk = NULL, *tx_clk = NULL; unsigned int queue_mask, num_queues; struct macb_platform_data *pdata; bool native_io; -- cgit v1.2.3 From 62f2aaabcf41b9e69d0356a7c1716b173241c105 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 25 Jan 2016 13:05:20 +0530 Subject: defxx: fix build warning We are getting many build warnings about: 'bar_start' may be used uninitialized and 'bar_len' may be used uninitialized They are not actually uninitialized as dfx_get_bars() will initialize them properly. But still lets have them initialized just to satisfy the compiler (gcc 4.8.2). Signed-off-by: Sudip Mukherjee Acked-by: Maciej W. Rozycki Signed-off-by: David S. Miller --- drivers/net/fddi/defxx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c index 7f975a2c8990..b0de8ecd7fe8 100644 --- a/drivers/net/fddi/defxx.c +++ b/drivers/net/fddi/defxx.c @@ -533,8 +533,8 @@ static int dfx_register(struct device *bdev) const char *print_name = dev_name(bdev); struct net_device *dev; DFX_board_t *bp; /* board pointer */ - resource_size_t bar_start[3]; /* pointers to ports */ - resource_size_t bar_len[3]; /* resource length */ + resource_size_t bar_start[3] = {0}; /* pointers to ports */ + resource_size_t bar_len[3] = {0}; /* resource length */ int alloc_size; /* total buffer size used */ struct resource *region; int err = 0; @@ -3697,8 +3697,8 @@ static void dfx_unregister(struct device *bdev) int dfx_bus_pci = dev_is_pci(bdev); int dfx_bus_tc = DFX_BUS_TC(bdev); int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; - resource_size_t bar_start[3]; /* pointers to ports */ - resource_size_t bar_len[3]; /* resource lengths */ + resource_size_t bar_start[3] = {0}; /* pointers to ports */ + resource_size_t bar_len[3] = {0}; /* resource lengths */ int alloc_size; /* total buffer size used */ unregister_netdev(dev); -- cgit v1.2.3 From 05f3b50ea81d7af5479b55147ef98f8bbcd4a8b9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 25 Jan 2016 11:40:50 +0100 Subject: net: fec: use CONFIG_ARM instead of CONFIG_ARCH_MXC/SOC_IMX28 As Arnd Bergmann points out, using CONFIG_ARCH_MXC and/or SOC_IMX28 is wrong if some other ARM platform uses this device - the operation of the driver would depend on an unrelated ARM platform that might or might not be set for multi-platform kernels. Prior to my previous patch, any other platforms using it would have been broken already due to having the cbd_datlen/cbd_sc fields in the wrong order, but byte ordering correctly, so no such platforms can exist and work today. In any case, it seems likely that only Freescale SoCs use this part, and those are little-endian on ARM, so CONFIG_ARM is safe for them. Signed-off-by: Johannes Berg Reviewed-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec.h | 8 +++----- drivers/net/ethernet/freescale/fec_main.c | 3 +-- 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 7dd47a0b8cfb..2106d72c91dc 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -19,8 +19,7 @@ #include #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M520x) || defined(CONFIG_M532x) || \ - defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28) + defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) /* * Just figures, Motorola would have to change the offsets for * registers in the same peripheral device on different models @@ -192,10 +191,9 @@ * Define the buffer descriptor structure. * * Evidently, ARM SoCs have the FEC block generated in a - * little endian mode; or at least ARCH_MXC/SOC_IMX28 do, - * so adjust endianness accordingly. + * little endian mode so adjust endianness accordingly. */ -#if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28) +#if defined(CONFIG_ARM) #define fec32_to_cpu le32_to_cpu #define fec16_to_cpu le16_to_cpu #define cpu_to_fec32 cpu_to_le32 diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 3f3b9eacc286..41c81f6ec630 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2153,8 +2153,7 @@ static int fec_enet_get_regs_len(struct net_device *ndev) /* List of registers that can be safety be read to dump them with ethtool */ #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M520x) || defined(CONFIG_M532x) || \ - defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28) + defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) static u32 fec_enet_register_offset[] = { FEC_IEVENT, FEC_IMASK, FEC_R_DES_ACTIVE_0, FEC_X_DES_ACTIVE_0, FEC_ECNTRL, FEC_MII_DATA, FEC_MII_SPEED, FEC_MIB_CTRLSTAT, FEC_R_CNTRL, -- cgit v1.2.3 From 757647e10e55c01fb7a9c4356529442e316a7c72 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Mon, 25 Jan 2016 16:00:41 +0100 Subject: hv_netvsc: use skb_get_hash() instead of a homegrown implementation Recent changes to 'struct flow_keys' (e.g commit d34af823ff40 ("net: Add VLAN ID to flow_keys")) introduced a performance regression in netvsc driver. Is problem is, however, not the above mentioned commit but the fact that netvsc_set_hash() function did some assumptions on the struct flow_keys data layout and this is wrong. Get rid of netvsc_set_hash() by switching to skb_get_hash(). This change will also imply switching to Jenkins hash from the currently used Toeplitz but it seems there is no good excuse for Toeplitz to stay. Signed-off-by: Vitaly Kuznetsov Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/hyperv/netvsc_drv.c | 67 ++--------------------------------------- 1 file changed, 3 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 1c8db9afdcda..1d3a66563bac 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -196,65 +196,6 @@ static void *init_ppi_data(struct rndis_message *msg, u32 ppi_size, return ppi; } -union sub_key { - u64 k; - struct { - u8 pad[3]; - u8 kb; - u32 ka; - }; -}; - -/* Toeplitz hash function - * data: network byte order - * return: host byte order - */ -static u32 comp_hash(u8 *key, int klen, void *data, int dlen) -{ - union sub_key subk; - int k_next = 4; - u8 dt; - int i, j; - u32 ret = 0; - - subk.k = 0; - subk.ka = ntohl(*(u32 *)key); - - for (i = 0; i < dlen; i++) { - subk.kb = key[k_next]; - k_next = (k_next + 1) % klen; - dt = ((u8 *)data)[i]; - for (j = 0; j < 8; j++) { - if (dt & 0x80) - ret ^= subk.ka; - dt <<= 1; - subk.k <<= 1; - } - } - - return ret; -} - -static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb) -{ - struct flow_keys flow; - int data_len; - - if (!skb_flow_dissect_flow_keys(skb, &flow, 0) || - !(flow.basic.n_proto == htons(ETH_P_IP) || - flow.basic.n_proto == htons(ETH_P_IPV6))) - return false; - - if (flow.basic.ip_proto == IPPROTO_TCP) - data_len = 12; - else - data_len = 8; - - *hash = comp_hash(netvsc_hash_key, HASH_KEYLEN, &flow, data_len); - - return true; -} - static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb, void *accel_priv, select_queue_fallback_t fallback) { @@ -267,11 +208,9 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb, if (nvsc_dev == NULL || ndev->real_num_tx_queues <= 1) return 0; - if (netvsc_set_hash(&hash, skb)) { - q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] % - ndev->real_num_tx_queues; - skb_set_hash(skb, hash, PKT_HASH_TYPE_L3); - } + hash = skb_get_hash(skb); + q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] % + ndev->real_num_tx_queues; if (!nvsc_dev->chn_table[q_idx]) q_idx = 0; -- cgit v1.2.3 From c85e4924452ae8225c8829f3fa8a2f7baa34bc5c Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Mon, 25 Jan 2016 09:49:31 -0800 Subject: hv_netvsc: Fix book keeping of skb during batching process Since eliminating send_completion_tid from struct hv_netvsc_packet, we haven't add proper book keeping for the skb of the batched packet. This patch fixes this issue and allows the previous skb is properly freed. Otherwise, a panic may happen. Thanks to Simon Xiao for bisecting and analysis. Signed-off-by: Haiyang Zhang Reviewed-by: K. Y. Srinivasan Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 1 + drivers/net/hyperv/netvsc.c | 33 ++++++++++++++++++++++----------- 2 files changed, 23 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index f4130af09244..fcb92c0d0eb9 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -624,6 +624,7 @@ struct nvsp_message { #define RNDIS_PKT_ALIGN_DEFAULT 8 struct multi_send_data { + struct sk_buff *skb; /* skb containing the pkt */ struct hv_netvsc_packet *pkt; /* netvsc pkt pending */ u32 count; /* counter of batched packets */ }; diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 059fc5231601..ec313fc08d82 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -841,6 +841,18 @@ static inline int netvsc_send_pkt( return ret; } +/* Move packet out of multi send data (msd), and clear msd */ +static inline void move_pkt_msd(struct hv_netvsc_packet **msd_send, + struct sk_buff **msd_skb, + struct multi_send_data *msdp) +{ + *msd_skb = msdp->skb; + *msd_send = msdp->pkt; + msdp->skb = NULL; + msdp->pkt = NULL; + msdp->count = 0; +} + int netvsc_send(struct hv_device *device, struct hv_netvsc_packet *packet, struct rndis_message *rndis_msg, @@ -855,6 +867,7 @@ int netvsc_send(struct hv_device *device, unsigned int section_index = NETVSC_INVALID_INDEX; struct multi_send_data *msdp; struct hv_netvsc_packet *msd_send = NULL, *cur_send = NULL; + struct sk_buff *msd_skb = NULL; bool try_batch; bool xmit_more = (skb != NULL) ? skb->xmit_more : false; @@ -897,10 +910,8 @@ int netvsc_send(struct hv_device *device, net_device->send_section_size) { section_index = netvsc_get_next_send_section(net_device); if (section_index != NETVSC_INVALID_INDEX) { - msd_send = msdp->pkt; - msdp->pkt = NULL; - msdp->count = 0; - msd_len = 0; + move_pkt_msd(&msd_send, &msd_skb, msdp); + msd_len = 0; } } @@ -919,31 +930,31 @@ int netvsc_send(struct hv_device *device, packet->total_data_buflen += msd_len; } - if (msdp->pkt) - dev_kfree_skb_any(skb); + if (msdp->skb) + dev_kfree_skb_any(msdp->skb); if (xmit_more && !packet->cp_partial) { + msdp->skb = skb; msdp->pkt = packet; msdp->count++; } else { cur_send = packet; + msdp->skb = NULL; msdp->pkt = NULL; msdp->count = 0; } } else { - msd_send = msdp->pkt; - msdp->pkt = NULL; - msdp->count = 0; + move_pkt_msd(&msd_send, &msd_skb, msdp); cur_send = packet; } if (msd_send) { - m_ret = netvsc_send_pkt(msd_send, net_device, pb, skb); + m_ret = netvsc_send_pkt(msd_send, net_device, NULL, msd_skb); if (m_ret != 0) { netvsc_free_send_slot(net_device, msd_send->send_buf_index); - dev_kfree_skb_any(skb); + dev_kfree_skb_any(msd_skb); } } -- cgit v1.2.3 From fb3296335500aaff61333df8eabbccf28761c79d Mon Sep 17 00:00:00 2001 From: Danesh Petigara Date: Mon, 11 Jan 2016 13:22:26 -0800 Subject: drivers: ata: wake port before DMA stop for ALPM The AHCI driver code stops and starts port DMA engines at will without considering the power state of the particular port. The AHCI specification isn't very clear on how to handle this scenario, leaving implementation open to interpretation. Broadcom's STB SATA host controller is unable to handle port DMA controller restarts when the port in question is in low power mode. When a port enters partial or slumber mode, its PHY is powered down. When a controller restart is requested, the controller's internal state machine expects the PHY to be brought back up by software which never happens in this case, resulting in failures. To avoid this situation, logic is added to manually wake up the port just before its DMA engine is stopped, if the port happens to be in a low power state. HBA initiated power management ensures that the port eventually returns to its configured low power state, when the link is idle (as per the conditions listed in the spec). A new host flag is also added to ensure this logic is only exercised for hosts with the above limitation. tj: Formatting changes. Signed-off-by: Danesh Petigara Reviewed-by: Markus Mayer Signed-off-by: Tejun Heo --- drivers/ata/ahci.h | 1 + drivers/ata/ahci_brcmstb.c | 1 + drivers/ata/libahci.c | 23 ++++++++++++++++++++++- include/linux/libata.h | 1 + 4 files changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index a4faa438889c..a44c75d4c284 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -250,6 +250,7 @@ enum { AHCI_HFLAG_MULTI_MSI = 0, AHCI_HFLAG_MULTI_MSIX = 0, #endif + AHCI_HFLAG_WAKE_BEFORE_STOP = (1 << 22), /* wake before DMA stop */ /* ap->flags bits */ diff --git a/drivers/ata/ahci_brcmstb.c b/drivers/ata/ahci_brcmstb.c index b36cae2fd04b..e87bcec0fd7c 100644 --- a/drivers/ata/ahci_brcmstb.c +++ b/drivers/ata/ahci_brcmstb.c @@ -317,6 +317,7 @@ static int brcm_ahci_probe(struct platform_device *pdev) if (IS_ERR(hpriv)) return PTR_ERR(hpriv); hpriv->plat_data = priv; + hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP; brcm_sata_alpm_init(hpriv); diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index d61740e78d6d..284a176076f5 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -593,8 +593,22 @@ EXPORT_SYMBOL_GPL(ahci_start_engine); int ahci_stop_engine(struct ata_port *ap) { void __iomem *port_mmio = ahci_port_base(ap); + struct ahci_host_priv *hpriv = ap->host->private_data; u32 tmp; + /* + * On some controllers, stopping a port's DMA engine while the port + * is in ALPM state (partial or slumber) results in failures on + * subsequent DMA engine starts. For those controllers, put the + * port back in active state before stopping its DMA engine. + */ + if ((hpriv->flags & AHCI_HFLAG_WAKE_BEFORE_STOP) && + (ap->link.lpm_policy > ATA_LPM_MAX_POWER) && + ahci_set_lpm(&ap->link, ATA_LPM_MAX_POWER, ATA_LPM_WAKE_ONLY)) { + dev_err(ap->host->dev, "Failed to wake up port before engine stop\n"); + return -EIO; + } + tmp = readl(port_mmio + PORT_CMD); /* check if the HBA is idle */ @@ -689,6 +703,9 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, void __iomem *port_mmio = ahci_port_base(ap); if (policy != ATA_LPM_MAX_POWER) { + /* wakeup flag only applies to the max power policy */ + hints &= ~ATA_LPM_WAKE_ONLY; + /* * Disable interrupts on Phy Ready. This keeps us from * getting woken up due to spurious phy ready @@ -704,7 +721,8 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, u32 cmd = readl(port_mmio + PORT_CMD); if (policy == ATA_LPM_MAX_POWER || !(hints & ATA_LPM_HIPM)) { - cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE); + if (!(hints & ATA_LPM_WAKE_ONLY)) + cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE); cmd |= PORT_CMD_ICC_ACTIVE; writel(cmd, port_mmio + PORT_CMD); @@ -712,6 +730,9 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, /* wait 10ms to be sure we've come out of LPM state */ ata_msleep(ap, 10); + + if (hints & ATA_LPM_WAKE_ONLY) + return 0; } else { cmd |= PORT_CMD_ALPE; if (policy == ATA_LPM_MIN_POWER) diff --git a/include/linux/libata.h b/include/linux/libata.h index 851821bfd553..bec2abbd7ab2 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -526,6 +526,7 @@ enum ata_lpm_policy { enum ata_lpm_hints { ATA_LPM_EMPTY = (1 << 0), /* port empty/probing */ ATA_LPM_HIPM = (1 << 1), /* may use HIPM */ + ATA_LPM_WAKE_ONLY = (1 << 2), /* only wake up link */ }; /* forward declarations */ -- cgit v1.2.3 From b00622fc34e9d45069bd6e328dfd47ea2ef61468 Mon Sep 17 00:00:00 2001 From: Shikha Jain Date: Mon, 11 Jan 2016 14:55:45 -0800 Subject: libata: blacklist a Viking flash model for MWDMA corruption Viking flash model VRFDFC22048UCHC-TE causes data corruption in MWDMA mode. Cc: xe-kernel@external.cisco.com Signed-off-by: Shikha Jain Signed-off-by: Anil Veliyankara Madam Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index cbb74719d2c1..55e257c268dd 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4125,6 +4125,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "SAMSUNG CD-ROM SN-124", "N001", ATA_HORKAGE_NODMA }, { "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA }, { " 2GB ATA Flash Disk", "ADMA428M", ATA_HORKAGE_NODMA }, + { "VRFDFC22048UCHC-TE*", NULL, ATA_HORKAGE_NODMA }, /* Odd clown on sil3726/4726 PMPs */ { "Config Disk", NULL, ATA_HORKAGE_DISABLE }, -- cgit v1.2.3 From 566d1827df2ef0cbe921d3d6946ac3007b1a6938 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 15 Jan 2016 15:13:05 -0500 Subject: libata: disable forced PORTS_IMPL for >= AHCI 1.3 Some early controllers incorrectly reported zero ports in PORTS_IMPL register and the ahci driver fabricates PORTS_IMPL from the number of ports in those cases. This hasn't mattered but with the new nvme controllers there are cases where zero PORTS_IMPL is valid and should be honored. Disable the workaround for >= AHCI 1.3. Signed-off-by: Tejun Heo Reported-by: Andy Lutomirski Link: http://lkml.kernel.org/g/CALCETrU7yMvXEDhjAUShoHEhDwifJGapdw--BKxsP0jmjKGmRw@mail.gmail.com Cc: Sergei Shtylyov Cc: stable@vger.kernel.org --- drivers/ata/libahci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 284a176076f5..402967902cbe 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -496,8 +496,8 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv) } } - /* fabricate port_map from cap.nr_ports */ - if (!port_map) { + /* fabricate port_map from cap.nr_ports for < AHCI 1.3 */ + if (!port_map && vers < 0x10300) { port_map = (1 << ahci_nr_ports(cap)) - 1; dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map); -- cgit v1.2.3 From 53eeb48b49410a47a0309bbc0516534ad71c1350 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 15 Jan 2016 19:56:47 +0100 Subject: PCI: imx6: Move imx6_pcie_reset_phy() near other PHY handling functions Move imx6_pcie_reset_phy() near the other PHY related functions in the file. This is a cosmetic change, but also allows to do the following changes without introducing needless forward declarations. Signed-off-by: Lucas Stach Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-imx6.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index fe600964fa50..52c7a0b1254b 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -202,6 +202,23 @@ static int pcie_phy_write(void __iomem *dbi_base, int addr, int data) return 0; } +static void imx6_pcie_reset_phy(struct pcie_port *pp) +{ + u32 tmp; + + pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp); + tmp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN | + PHY_RX_OVRD_IN_LO_RX_PLL_EN); + pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp); + + usleep_range(2000, 3000); + + pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp); + tmp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN | + PHY_RX_OVRD_IN_LO_RX_PLL_EN); + pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp); +} + /* Added for PCI abort handling */ static int imx6q_pcie_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs) @@ -441,23 +458,6 @@ static void imx6_pcie_host_init(struct pcie_port *pp) dw_pcie_msi_init(pp); } -static void imx6_pcie_reset_phy(struct pcie_port *pp) -{ - u32 tmp; - - pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp); - tmp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN | - PHY_RX_OVRD_IN_LO_RX_PLL_EN); - pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp); - - usleep_range(2000, 3000); - - pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp); - tmp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN | - PHY_RX_OVRD_IN_LO_RX_PLL_EN); - pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp); -} - static int imx6_pcie_link_up(struct pcie_port *pp) { u32 rc, debug_r0, rx_valid; -- cgit v1.2.3 From 54a47a83421a3b7ee0e0fab7f65d04179bdf59b6 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 25 Jan 2016 16:49:53 -0600 Subject: PCI: imx6: Move PHY reset into imx6_pcie_establish_link() This adds the PHY reset into a common error path of imx6_pcie_establish_link(), deduplicating some of the debug prints. Also reduce the severity of the "no-link" message in the one place where it is expected to be hit when no peripheral is attached. Signed-off-by: Lucas Stach Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-imx6.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 52c7a0b1254b..69f47ef2a264 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -355,10 +355,6 @@ static int imx6_pcie_wait_for_link(struct pcie_port *pp) usleep_range(100, 1000); } - dev_err(pp->dev, "phy link never came up\n"); - dev_dbg(pp->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", - readl(pp->dbi_base + PCIE_PHY_DEBUG_R0), - readl(pp->dbi_base + PCIE_PHY_DEBUG_R1)); return -EINVAL; } @@ -407,8 +403,10 @@ static int imx6_pcie_establish_link(struct pcie_port *pp) IMX6Q_GPR12_PCIE_CTL_2, 1 << 10); ret = imx6_pcie_wait_for_link(pp); - if (ret) - return ret; + if (ret) { + dev_info(pp->dev, "Link never came up\n"); + goto err_reset_phy; + } /* Allow Gen2 mode after the link is up. */ tmp = readl(pp->dbi_base + PCIE_RC_LCR); @@ -427,19 +425,28 @@ static int imx6_pcie_establish_link(struct pcie_port *pp) ret = imx6_pcie_wait_for_speed_change(pp); if (ret) { dev_err(pp->dev, "Failed to bring link up!\n"); - return ret; + goto err_reset_phy; } /* Make sure link training is finished as well! */ ret = imx6_pcie_wait_for_link(pp); if (ret) { dev_err(pp->dev, "Failed to bring link up!\n"); - return ret; + goto err_reset_phy; } tmp = readl(pp->dbi_base + PCIE_RC_LCSR); dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf); + return 0; + +err_reset_phy: + dev_dbg(pp->dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n", + readl(pp->dbi_base + PCIE_PHY_DEBUG_R0), + readl(pp->dbi_base + PCIE_PHY_DEBUG_R1)); + imx6_pcie_reset_phy(pp); + + return ret; } static void imx6_pcie_host_init(struct pcie_port *pp) @@ -510,11 +517,6 @@ static int imx6_pcie_link_up(struct pcie_port *pp) if ((debug_r0 & 0x3f) != 0x0d) return 0; - dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n"); - dev_dbg(pp->dev, "debug_r0=%08x debug_r1=%08x\n", debug_r0, rc); - - imx6_pcie_reset_phy(pp); - return 0; } -- cgit v1.2.3 From a77c5422d7586003643377afdb9915e76d07d21c Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 25 Jan 2016 16:49:57 -0600 Subject: PCI: imx6: Remove broken Gen2 workaround Remove the remnants of the workaround for erratum ERR005184 which was never completely implemented. The checks alone don't carry any value as we don't act properly on the result. A workaround should be added to the lane speed change in establish_link later. Signed-off-by: Lucas Stach Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-imx6.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 69f47ef2a264..6d7dfdcf4d5c 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -467,7 +467,7 @@ static void imx6_pcie_host_init(struct pcie_port *pp) static int imx6_pcie_link_up(struct pcie_port *pp) { - u32 rc, debug_r0, rx_valid; + u32 rc; int count = 5; /* @@ -501,21 +501,6 @@ static int imx6_pcie_link_up(struct pcie_port *pp) */ usleep_range(1000, 2000); } - /* - * From L0, initiate MAC entry to gen2 if EP/RC supports gen2. - * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2). - * If (MAC/LTSSM.state == Recovery.RcvrLock) - * && (PHY/rx_valid==0) then pulse PHY/rx_reset. Transition - * to gen2 is stuck - */ - pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid); - debug_r0 = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0); - - if (rx_valid & PCIE_PHY_RX_ASIC_OUT_VALID) - return 0; - - if ((debug_r0 & 0x3f) != 0x0d) - return 0; return 0; } -- cgit v1.2.3 From 4d107d3b5a686b5834e533a00b73bf7b1cf59df7 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 25 Jan 2016 16:50:02 -0600 Subject: PCI: imx6: Move link up check into imx6_pcie_wait_for_link() imx6_pcie_link_up() previously used usleep_range() to wait for the link to come up. Since it may be called while holding the config spinlock, the sleep causes a "BUG: scheduling while atomic" error. Instead of waiting for the link to come up in imx6_pcie_link_up(), do the waiting in imx6_pcie_wait_for_link(), where we're not holding a lock and sleeping is allowed. [bhelgaas: changelog, references to bugzilla and f95d3ae77191] Link: https://bugzilla.kernel.org/show_bug.cgi?id=100031 Fixes: f95d3ae77191 ("PCI: imx6: Wait for retraining") Signed-off-by: Lucas Stach Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-imx6.c | 60 +++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 6d7dfdcf4d5c..bd3f7d0ef943 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -349,10 +349,28 @@ static int imx6_pcie_wait_for_link(struct pcie_port *pp) { unsigned int retries; + /* + * Test if the PHY reports that the link is up and also that the LTSSM + * training finished. There are three possible states of the link when + * this code is called: + * 1) The link is DOWN (unlikely) + * The link didn't come up yet for some reason. This usually means + * we have a real problem somewhere, if it happens with a peripheral + * connected. This state calls for inspection of the DEBUG registers. + * 2) The link is UP, but still in LTSSM training + * Wait for the training to finish, which should take a very short + * time. If the training does not finish, we have a problem and we + * need to inspect the DEBUG registers. If the training does finish, + * the link is up and operating correctly. + * 3) The link is UP and no longer in LTSSM training + * The link is up and operating correctly. + */ for (retries = 0; retries < 200; retries++) { - if (dw_pcie_link_up(pp)) + u32 reg = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1); + if ((reg & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP) && + !(reg & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING)) return 0; - usleep_range(100, 1000); + usleep_range(1000, 2000); } return -EINVAL; @@ -467,42 +485,8 @@ static void imx6_pcie_host_init(struct pcie_port *pp) static int imx6_pcie_link_up(struct pcie_port *pp) { - u32 rc; - int count = 5; - - /* - * Test if the PHY reports that the link is up and also that the LTSSM - * training finished. There are three possible states of the link when - * this code is called: - * 1) The link is DOWN (unlikely) - * The link didn't come up yet for some reason. This usually means - * we have a real problem somewhere. Reset the PHY and exit. This - * state calls for inspection of the DEBUG registers. - * 2) The link is UP, but still in LTSSM training - * Wait for the training to finish, which should take a very short - * time. If the training does not finish, we have a problem and we - * need to inspect the DEBUG registers. If the training does finish, - * the link is up and operating correctly. - * 3) The link is UP and no longer in LTSSM training - * The link is up and operating correctly. - */ - while (1) { - rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1); - if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP)) - break; - if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING)) - return 1; - if (!count--) - break; - dev_dbg(pp->dev, "Link is up, but still in training\n"); - /* - * Wait a little bit, then re-check if the link finished - * the training. - */ - usleep_range(1000, 2000); - } - - return 0; + return readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) & + PCIE_PHY_DEBUG_R1_XMLH_LINK_UP; } static struct pcie_host_ops imx6_pcie_host_ops = { -- cgit v1.2.3 From 5cae7615b613381a04d3dd06b8237234cc3f7cc9 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 20 Jan 2016 19:53:02 -0800 Subject: i40e: fix build warnings Fixes following build warnings : drivers/net/ethernet/intel/i40e/i40e_main.c:7057:13: warning: 'i40e_sync_udp_filters_subtask' defined but not used [-Wunused-function] drivers/net/ethernet/intel/i40e/i40e_main.c:8524:13: warning: 'i40e_add_vxlan_port' defined but not used [-Wunused-function] drivers/net/ethernet/intel/i40e/i40e_main.c:8569:13: warning: 'i40e_del_vxlan_port' defined but not used [-Wunused-function] drivers/net/ethernet/intel/i40e/i40e_main.c:8604:13: warning: 'i40e_add_geneve_port' defined but not used [-Wunused-function] drivers/net/ethernet/intel/i40e/i40e_main.c:8651:13: warning: 'i40e_del_geneve_port' defined but not used [-Wunused-function] Fixes: 6a899024058d ("i40e: geneve tunnel offload support") Signed-off-by: Eric Dumazet Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index bb4612c159fd..8f3b53e0dc46 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -7117,9 +7117,7 @@ static void i40e_service_task(struct work_struct *work) i40e_watchdog_subtask(pf); i40e_fdir_reinit_subtask(pf); i40e_sync_filters_subtask(pf); -#if IS_ENABLED(CONFIG_VXLAN) || IS_ENABLED(CONFIG_GENEVE) i40e_sync_udp_filters_subtask(pf); -#endif i40e_clean_adminq_subtask(pf); i40e_service_event_complete(pf); @@ -8515,6 +8513,8 @@ static u8 i40e_get_udp_port_idx(struct i40e_pf *pf, __be16 port) } #endif + +#if IS_ENABLED(CONFIG_VXLAN) /** * i40e_add_vxlan_port - Get notifications about VXLAN ports that come up * @netdev: This physical port's netdev @@ -8524,7 +8524,6 @@ static u8 i40e_get_udp_port_idx(struct i40e_pf *pf, __be16 port) static void i40e_add_vxlan_port(struct net_device *netdev, sa_family_t sa_family, __be16 port) { -#if IS_ENABLED(CONFIG_VXLAN) struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; struct i40e_pf *pf = vsi->back; @@ -8557,7 +8556,6 @@ static void i40e_add_vxlan_port(struct net_device *netdev, pf->udp_ports[next_idx].type = I40E_AQC_TUNNEL_TYPE_VXLAN; pf->pending_udp_bitmap |= BIT_ULL(next_idx); pf->flags |= I40E_FLAG_UDP_FILTER_SYNC; -#endif } /** @@ -8569,7 +8567,6 @@ static void i40e_add_vxlan_port(struct net_device *netdev, static void i40e_del_vxlan_port(struct net_device *netdev, sa_family_t sa_family, __be16 port) { -#if IS_ENABLED(CONFIG_VXLAN) struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; struct i40e_pf *pf = vsi->back; @@ -8592,9 +8589,10 @@ static void i40e_del_vxlan_port(struct net_device *netdev, netdev_warn(netdev, "vxlan port %d was not found, not deleting\n", ntohs(port)); } -#endif } +#endif +#if IS_ENABLED(CONFIG_GENEVE) /** * i40e_add_geneve_port - Get notifications about GENEVE ports that come up * @netdev: This physical port's netdev @@ -8604,7 +8602,6 @@ static void i40e_del_vxlan_port(struct net_device *netdev, static void i40e_add_geneve_port(struct net_device *netdev, sa_family_t sa_family, __be16 port) { -#if IS_ENABLED(CONFIG_GENEVE) struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; struct i40e_pf *pf = vsi->back; @@ -8639,7 +8636,6 @@ static void i40e_add_geneve_port(struct net_device *netdev, pf->flags |= I40E_FLAG_UDP_FILTER_SYNC; dev_info(&pf->pdev->dev, "adding geneve port %d\n", ntohs(port)); -#endif } /** @@ -8651,7 +8647,6 @@ static void i40e_add_geneve_port(struct net_device *netdev, static void i40e_del_geneve_port(struct net_device *netdev, sa_family_t sa_family, __be16 port) { -#if IS_ENABLED(CONFIG_GENEVE) struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; struct i40e_pf *pf = vsi->back; @@ -8677,8 +8672,8 @@ static void i40e_del_geneve_port(struct net_device *netdev, netdev_warn(netdev, "geneve port %d was not found, not deleting\n", ntohs(port)); } -#endif } +#endif static int i40e_get_phys_port_id(struct net_device *netdev, struct netdev_phys_item_id *ppid) -- cgit v1.2.3 From 79febbc19b81b5242339bffb90e4dbea15015dde Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 20 Jan 2016 19:53:17 -0800 Subject: net: i40e: shut up uninitialized variable warnings intel/i40e/i40e_txrx.c: In function 'i40e_xmit_frame_ring': intel/i40e/i40e_txrx.c:2367:20: error: 'oiph' may be used uninitialized in this function [-Werror=maybe-uninitialized] intel/i40e/i40e_txrx.c:2317:16: note: 'oiph' was declared here intel/i40e/i40e_txrx.c:2367:17: error: 'oudph' may be used uninitialized in this function [-Werror=maybe-uninitialized] intel/i40e/i40e_txrx.c:2316:17: note: 'oudph' was declared here Signed-off-by: Arnd Bergmann Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 720516b0e8ee..47bd8b3145a7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -2313,8 +2313,8 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, struct iphdr *this_ip_hdr; u32 network_hdr_len; u8 l4_hdr = 0; - struct udphdr *oudph; - struct iphdr *oiph; + struct udphdr *oudph = NULL; + struct iphdr *oiph = NULL; u32 l4_tunnel = 0; if (skb->encapsulation) { -- cgit v1.2.3 From 2c41b5a775dc2a9d04b56ca6b2827025b8bddeb3 Mon Sep 17 00:00:00 2001 From: Paweł Jarosz Date: Tue, 19 Jan 2016 13:09:20 +0100 Subject: clk: rockchip: add tsadc clock on rk3066 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set clock id for sclk_tsadc gating clock of tsadc in rk3066 Signed-off-by: Paweł Jarosz Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3188.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index 73954907111e..3d4f2c629682 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -605,7 +605,7 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = { GATE(SCLK_TIMER2, "timer2", "xin24m", 0, RK2928_CLKGATE_CON(3), 2, GFLAGS), - COMPOSITE_NOMUX(0, "sclk_tsadc", "xin24m", 0, + COMPOSITE_NOMUX(SCLK_TSADC, "sclk_tsadc", "xin24m", 0, RK2928_CLKSEL_CON(34), 0, 16, DFLAGS, RK2928_CLKGATE_CON(2), 15, GFLAGS), -- cgit v1.2.3 From f95429eccc570dc45d589c327bfcfddcdc3e8228 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 25 Jan 2016 18:06:48 -0500 Subject: drm/radeon: only init fbdev if we have connectors This fixes an issue that was noticed on an optimus/prime laptop with a kernel that was old enough to not support the integrated intel gfx (which was driving all the outputs), but did have support for the discrete radeon gpu. The end result was not falling back to VESA and leaving the user with a black screen. (Plus it is kind of silly to create an framebuffer device if there are no outputs hooked up to the gpu.) Signed-off-by: Rob Clark Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_display.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index b3bb92368ae0..298ea1c453c3 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1670,8 +1670,10 @@ int radeon_modeset_init(struct radeon_device *rdev) /* setup afmt */ radeon_afmt_init(rdev); - radeon_fbdev_init(rdev); - drm_kms_helper_poll_init(rdev->ddev); + if (!list_empty(&rdev->ddev->mode_config.connector_list)) { + radeon_fbdev_init(rdev); + drm_kms_helper_poll_init(rdev->ddev); + } /* do pm late init */ ret = radeon_pm_late_init(rdev); -- cgit v1.2.3 From f49d45c973984eb805eb989b6220aa7c1ee30bc2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 26 Jan 2016 00:30:33 -0500 Subject: drm/amdgpu: don't init fbdev if we don't have any connectors Don't init fbdev if we don't have connectors. E.g., if you have a PX laptop with the displays attached to an IGP with no driver support, you may end up with a blank screen rather than falling back to vesa, etc. Based on a similar radeon patch from Rob Clark. Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index cfb6caad2a73..919146780a15 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -333,6 +333,10 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev) if (!adev->mode_info.mode_config_initialized) return 0; + /* don't init fbdev if there are no connectors */ + if (list_empty(&adev->ddev->mode_config.connector_list)) + return 0; + /* select 8 bpp console on low vram cards */ if (adev->mc.real_vram_size <= (32*1024*1024)) bpp_sel = 8; -- cgit v1.2.3 From a28e35171cb1ff84197e8d271b65aaeb8c404827 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 22 Jan 2016 14:12:02 +0100 Subject: i2c: piix4: Fix SB800 locking We need a single mutex for all 4 shared SMBus ports on the SB800. A per-port mutex doesn't protect us from concurrent access. In theory the mutex should be per PCI device, however in practice we know that there's only ever a single instance of the device in a given system so we can use a global. Also take the mutex during initialization, as first port may be already in use when second port is initialized. Signed-off-by: Jean Delvare Tested-by: Christian Fetzer Reviewed-by: Mika Westerberg [wsa: made mutex static] Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-piix4.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index e04598595073..5fd7505b9018 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -137,6 +137,7 @@ static const struct dmi_system_id piix4_dmi_ibm[] = { }; /* SB800 globals */ +static DEFINE_MUTEX(piix4_mutex_sb800); static const char *piix4_main_port_names_sb800[PIIX4_MAX_ADAPTERS] = { "SDA0", "SDA2", "SDA3", "SDA4" }; @@ -148,7 +149,6 @@ struct i2c_piix4_adapdata { /* SB800 */ bool sb800_main; unsigned short port; - struct mutex *mutex; }; static int piix4_setup(struct pci_dev *PIIX4_dev, @@ -275,10 +275,12 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, else smb_en = (aux) ? 0x28 : 0x2c; + mutex_lock(&piix4_mutex_sb800); outb_p(smb_en, SB800_PIIX4_SMB_IDX); smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1); outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX); smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1); + mutex_unlock(&piix4_mutex_sb800); if (!smb_en) { smb_en_status = smba_en_lo & 0x10; @@ -559,7 +561,7 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, u8 port; int retval; - mutex_lock(adapdata->mutex); + mutex_lock(&piix4_mutex_sb800); outb_p(SB800_PIIX4_PORT_IDX, SB800_PIIX4_SMB_IDX); smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1); @@ -574,7 +576,7 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, outb_p(smba_en_lo, SB800_PIIX4_SMB_IDX + 1); - mutex_unlock(adapdata->mutex); + mutex_unlock(&piix4_mutex_sb800); return retval; } @@ -673,17 +675,10 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba) { - struct mutex *mutex; struct i2c_piix4_adapdata *adapdata; int port; int retval; - mutex = kzalloc(sizeof(*mutex), GFP_KERNEL); - if (mutex == NULL) - return -ENOMEM; - - mutex_init(mutex); - for (port = 0; port < PIIX4_MAX_ADAPTERS; port++) { retval = piix4_add_adapter(dev, smba, piix4_main_port_names_sb800[port], @@ -696,7 +691,6 @@ static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba) adapdata = i2c_get_adapdata(piix4_main_adapters[port]); adapdata->sb800_main = true; adapdata->port = port; - adapdata->mutex = mutex; } return retval; @@ -714,8 +708,6 @@ error: } } - kfree(mutex); - return retval; } @@ -798,10 +790,8 @@ static void piix4_adap_remove(struct i2c_adapter *adap) i2c_del_adapter(adap); if (adapdata->port == 0) { release_region(adapdata->smba, SMBIOSIZE); - if (adapdata->sb800_main) { - kfree(adapdata->mutex); + if (adapdata->sb800_main) release_region(SB800_PIIX4_SMB_IDX, 2); - } } kfree(adapdata); kfree(adap); -- cgit v1.2.3 From 83c60158ebf16417af28b338bc0380cf17f2b9f9 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 25 Jan 2016 12:17:07 +0100 Subject: i2c: piix4: Fully initialize SB800 before it is registered This closes a race window where I2C device drivers attempt to access I2C buses which aren't fully initialized yet. Signed-off-by: Jean Delvare Tested-by: Christian Fetzer Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-piix4.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 5fd7505b9018..f79a84ef1aa4 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -627,6 +627,7 @@ static struct i2c_adapter *piix4_main_adapters[PIIX4_MAX_ADAPTERS]; static struct i2c_adapter *piix4_aux_adapter; static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, + bool sb800_main, unsigned short port, const char *name, struct i2c_adapter **padap) { struct i2c_adapter *adap; @@ -641,7 +642,8 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, adap->owner = THIS_MODULE; adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - adap->algo = &smbus_algorithm; + adap->algo = sb800_main ? &piix4_smbus_algorithm_sb800 + : &smbus_algorithm; adapdata = kzalloc(sizeof(*adapdata), GFP_KERNEL); if (adapdata == NULL) { @@ -651,6 +653,8 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, } adapdata->smba = smba; + adapdata->sb800_main = sb800_main; + adapdata->port = port; /* set up the sysfs linkage to our parent device */ adap->dev.parent = &dev->dev; @@ -680,17 +684,11 @@ static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba) int retval; for (port = 0; port < PIIX4_MAX_ADAPTERS; port++) { - retval = piix4_add_adapter(dev, smba, + retval = piix4_add_adapter(dev, smba, true, port, piix4_main_port_names_sb800[port], &piix4_main_adapters[port]); if (retval < 0) goto error; - - piix4_main_adapters[port]->algo = &piix4_smbus_algorithm_sb800; - - adapdata = i2c_get_adapdata(piix4_main_adapters[port]); - adapdata->sb800_main = true; - adapdata->port = port; } return retval; @@ -748,7 +746,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) return retval; /* Try to register main SMBus adapter, give up if we can't */ - retval = piix4_add_adapter(dev, retval, "main", + retval = piix4_add_adapter(dev, retval, false, 0, "main", &piix4_main_adapters[0]); if (retval < 0) return retval; @@ -775,7 +773,8 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) if (retval > 0) { /* Try to add the aux adapter if it exists, * piix4_add_adapter will clean up if this fails */ - piix4_add_adapter(dev, retval, piix4_aux_port_name_sb800, + piix4_add_adapter(dev, retval, false, 0, + piix4_aux_port_name_sb800, &piix4_aux_adapter); } -- cgit v1.2.3 From 08c6e8cc66282a082484480c1a5641bc27d26c55 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 15 Jan 2016 22:02:12 +0200 Subject: i2c: designware-pci: use IRQF_COND_SUSPEND flag This is effectively reapplies the commit b0898fdaffb2 ("i2c: designware-pci: use IRQF_COND_SUSPEND flag") after the commit d80d134182ba ("i2c: designware: Move common probe code into i2c_dw_probe()"). Original message as follows. The mentioned flag fixes a warning on Intel Edison board since one of the I2C controller shares IRQ line with watchdog timer. Fixes: d80d134182ba (i2c: designware: Move common probe code into i2c_dw_probe()) Signed-off-by: Andy Shevchenko Acked-by: Jarkko Nikula Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index ba9732c236c5..10fbd6d841e0 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -874,7 +874,8 @@ int i2c_dw_probe(struct dw_i2c_dev *dev) i2c_set_adapdata(adap, dev); i2c_dw_disable_int(dev); - r = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, IRQF_SHARED, + r = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, + IRQF_SHARED | IRQF_COND_SUSPEND, dev_name(dev->dev), dev); if (r) { dev_err(dev->dev, "failure requesting irq %i: %d\n", -- cgit v1.2.3 From 2989be09a8a9d62a785137586ad941f916e08f83 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 14 Jan 2016 16:00:41 +0200 Subject: virtio_pci: fix use after free on release KASan detected a use-after-free error in virtio-pci remove code. In virtio_pci_remove(), vp_dev is still used after being freed in unregister_virtio_device() (in virtio_pci_release_dev() more precisely). To fix, keep a reference until cleanup is done. Fixes: 63bd62a08ca4 ("virtio_pci: defer kfree until release callback") Reported-by: Jerome Marchand Cc: stable@vger.kernel.org Cc: Sasha Levin Signed-off-by: Michael S. Tsirkin Tested-by: Jerome Marchand --- drivers/virtio/virtio_pci_common.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c index 36205c27c4d0..f6bed86c17f9 100644 --- a/drivers/virtio/virtio_pci_common.c +++ b/drivers/virtio/virtio_pci_common.c @@ -545,6 +545,7 @@ err_enable_device: static void virtio_pci_remove(struct pci_dev *pci_dev) { struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); + struct device *dev = get_device(&vp_dev->vdev.dev); unregister_virtio_device(&vp_dev->vdev); @@ -554,6 +555,7 @@ static void virtio_pci_remove(struct pci_dev *pci_dev) virtio_pci_modern_remove(vp_dev); pci_disable_device(pci_dev); + put_device(dev); } static struct pci_driver virtio_pci_driver = { -- cgit v1.2.3 From 13d52fe40f1f7bbad49128e8ee6a2fe5e13dd18d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 26 Jan 2016 06:59:39 -0200 Subject: [media] em28xx: fix implementation of s_stream On em28xx driver, s_stream subdev ops was not implemented properly. It was used only to disable stream, never enabling it. That was the root cause of the regression when we added support for s_stream on tvp5150 driver. With that, we can get rid of the changes on tvp5150 side, e. g. changeset 47de9bf8931e ('[media] tvp5150: Fix breakage for serial usage'). Tested video output on em2820+tvp5150 on WinTV USB2 and video and/or vbi output on em288x+tvp5150 on HVR 950. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 0e86ff423c49..6a015e8e8655 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -196,7 +196,6 @@ static void em28xx_wake_i2c(struct em28xx *dev) v4l2_device_call_all(v4l2_dev, 0, core, reset, 0); v4l2_device_call_all(v4l2_dev, 0, video, s_routing, INPUT(dev->ctl_input)->vmux, 0, 0); - v4l2_device_call_all(v4l2_dev, 0, video, s_stream, 0); } static int em28xx_colorlevels_set_default(struct em28xx *dev) @@ -962,6 +961,9 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) f.type = V4L2_TUNER_ANALOG_TV; v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_frequency, &f); + + /* Enable video stream at TV decoder */ + v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 1); } v4l2->streaming_users++; @@ -981,6 +983,9 @@ static void em28xx_stop_streaming(struct vb2_queue *vq) res_free(dev, vq->type); if (v4l2->streaming_users-- == 1) { + /* Disable video stream at TV decoder */ + v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 0); + /* Last active user, so shutdown all the URBS */ em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE); } @@ -1013,6 +1018,9 @@ void em28xx_stop_vbi_streaming(struct vb2_queue *vq) res_free(dev, vq->type); if (v4l2->streaming_users-- == 1) { + /* Disable video stream at TV decoder */ + v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 0); + /* Last active user, so shutdown all the URBS */ em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE); } -- cgit v1.2.3 From 841502d731f1708aae907d5bdf1659e8a372fc9a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 26 Jan 2016 07:13:30 -0200 Subject: Revert "[media] tvp5150: Fix breakage for serial usage" This patch were a workaround for a regression at tvp5150, but it causes troubles on devices with omap3+tvp5151 when working in non-parallel bus mode. Now that em28xx was fixed, we can get rid of that. This reverts commit 47de9bf8931e6bf9c92fdba9867925d1ce482ab1. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 779c6f453cc9..437f1a7ecb96 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -975,18 +975,19 @@ static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) { struct tvp5150 *decoder = to_tvp5150(sd); + /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ + int val = 0x09; /* Output format: 8-bit 4:2:2 YUV with discrete sync */ - if (decoder->mbus_type != V4L2_MBUS_PARALLEL) - return 0; + if (decoder->mbus_type == V4L2_MBUS_PARALLEL) + val = 0x0d; /* Initializes TVP5150 to its default values */ /* # set PCLK (27MHz) */ tvp5150_write(sd, TVP5150_CONF_SHARED_PIN, 0x00); - /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ if (enable) - tvp5150_write(sd, TVP5150_MISC_CTL, 0x09); + tvp5150_write(sd, TVP5150_MISC_CTL, val); else tvp5150_write(sd, TVP5150_MISC_CTL, 0x00); -- cgit v1.2.3 From d8f51227f33fbb34e1e54e315175268f54e573e7 Mon Sep 17 00:00:00 2001 From: Ingo Tuchscherer Date: Fri, 22 Jan 2016 16:18:29 +0100 Subject: s390/zcrypt: Fix cryptographic device id in kernel messages Currently, on card response failures a combination of card domain and domain id is recorded in the kernel messages. According to the message description only the card id will be recorded. The domain id is not relevant, since the whole card including all domains is set offline. Signed-off-by: Ingo Tuchscherer Signed-off-by: Martin Schwidefsky --- drivers/s390/crypto/zcrypt_error.h | 15 +++++++++------ drivers/s390/crypto/zcrypt_msgtype50.c | 9 +++++---- drivers/s390/crypto/zcrypt_msgtype6.c | 20 ++++++++++---------- 3 files changed, 24 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/crypto/zcrypt_error.h b/drivers/s390/crypto/zcrypt_error.h index 7b23f43c7b08..de1b6c1d172c 100644 --- a/drivers/s390/crypto/zcrypt_error.h +++ b/drivers/s390/crypto/zcrypt_error.h @@ -112,9 +112,10 @@ static inline int convert_error(struct zcrypt_device *zdev, atomic_set(&zcrypt_rescan_req, 1); zdev->online = 0; pr_err("Cryptographic device %x failed and was set offline\n", - zdev->ap_dev->qid); + AP_QID_DEVICE(zdev->ap_dev->qid)); ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", - zdev->ap_dev->qid, zdev->online, ehdr->reply_code); + AP_QID_DEVICE(zdev->ap_dev->qid), zdev->online, + ehdr->reply_code); return -EAGAIN; case REP82_ERROR_TRANSPORT_FAIL: case REP82_ERROR_MACHINE_FAILURE: @@ -123,16 +124,18 @@ static inline int convert_error(struct zcrypt_device *zdev, atomic_set(&zcrypt_rescan_req, 1); zdev->online = 0; pr_err("Cryptographic device %x failed and was set offline\n", - zdev->ap_dev->qid); + AP_QID_DEVICE(zdev->ap_dev->qid)); ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", - zdev->ap_dev->qid, zdev->online, ehdr->reply_code); + AP_QID_DEVICE(zdev->ap_dev->qid), zdev->online, + ehdr->reply_code); return -EAGAIN; default: zdev->online = 0; pr_err("Cryptographic device %x failed and was set offline\n", - zdev->ap_dev->qid); + AP_QID_DEVICE(zdev->ap_dev->qid)); ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", - zdev->ap_dev->qid, zdev->online, ehdr->reply_code); + AP_QID_DEVICE(zdev->ap_dev->qid), zdev->online, + ehdr->reply_code); return -EAGAIN; /* repeat the request on a different device. */ } } diff --git a/drivers/s390/crypto/zcrypt_msgtype50.c b/drivers/s390/crypto/zcrypt_msgtype50.c index 74edf2934e7c..eedfaa2cf715 100644 --- a/drivers/s390/crypto/zcrypt_msgtype50.c +++ b/drivers/s390/crypto/zcrypt_msgtype50.c @@ -336,9 +336,10 @@ static int convert_type80(struct zcrypt_device *zdev, /* The result is too short, the CEX2A card may not do that.. */ zdev->online = 0; pr_err("Cryptographic device %x failed and was set offline\n", - zdev->ap_dev->qid); + AP_QID_DEVICE(zdev->ap_dev->qid)); ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", - zdev->ap_dev->qid, zdev->online, t80h->code); + AP_QID_DEVICE(zdev->ap_dev->qid), + zdev->online, t80h->code); return -EAGAIN; /* repeat the request on a different device. */ } @@ -368,9 +369,9 @@ static int convert_response(struct zcrypt_device *zdev, default: /* Unknown response type, this should NEVER EVER happen */ zdev->online = 0; pr_err("Cryptographic device %x failed and was set offline\n", - zdev->ap_dev->qid); + AP_QID_DEVICE(zdev->ap_dev->qid)); ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", - zdev->ap_dev->qid, zdev->online); + AP_QID_DEVICE(zdev->ap_dev->qid), zdev->online); return -EAGAIN; /* repeat the request on a different device. */ } } diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c index 9a2dd472c1cc..21959719daef 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.c +++ b/drivers/s390/crypto/zcrypt_msgtype6.c @@ -572,9 +572,9 @@ static int convert_type86_ica(struct zcrypt_device *zdev, return -EINVAL; zdev->online = 0; pr_err("Cryptographic device %x failed and was set offline\n", - zdev->ap_dev->qid); + AP_QID_DEVICE(zdev->ap_dev->qid)); ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", - zdev->ap_dev->qid, zdev->online, + AP_QID_DEVICE(zdev->ap_dev->qid), zdev->online, msg->hdr.reply_code); return -EAGAIN; /* repeat the request on a different device. */ } @@ -715,9 +715,9 @@ static int convert_response_ica(struct zcrypt_device *zdev, default: /* Unknown response type, this should NEVER EVER happen */ zdev->online = 0; pr_err("Cryptographic device %x failed and was set offline\n", - zdev->ap_dev->qid); + AP_QID_DEVICE(zdev->ap_dev->qid)); ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", - zdev->ap_dev->qid, zdev->online); + AP_QID_DEVICE(zdev->ap_dev->qid), zdev->online); return -EAGAIN; /* repeat the request on a different device. */ } } @@ -747,9 +747,9 @@ static int convert_response_xcrb(struct zcrypt_device *zdev, xcRB->status = 0x0008044DL; /* HDD_InvalidParm */ zdev->online = 0; pr_err("Cryptographic device %x failed and was set offline\n", - zdev->ap_dev->qid); + AP_QID_DEVICE(zdev->ap_dev->qid)); ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", - zdev->ap_dev->qid, zdev->online); + AP_QID_DEVICE(zdev->ap_dev->qid), zdev->online); return -EAGAIN; /* repeat the request on a different device. */ } } @@ -773,9 +773,9 @@ static int convert_response_ep11_xcrb(struct zcrypt_device *zdev, default: /* Unknown response type, this should NEVER EVER happen */ zdev->online = 0; pr_err("Cryptographic device %x failed and was set offline\n", - zdev->ap_dev->qid); + AP_QID_DEVICE(zdev->ap_dev->qid)); ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", - zdev->ap_dev->qid, zdev->online); + AP_QID_DEVICE(zdev->ap_dev->qid), zdev->online); return -EAGAIN; /* repeat the request on a different device. */ } } @@ -800,9 +800,9 @@ static int convert_response_rng(struct zcrypt_device *zdev, default: /* Unknown response type, this should NEVER EVER happen */ zdev->online = 0; pr_err("Cryptographic device %x failed and was set offline\n", - zdev->ap_dev->qid); + AP_QID_DEVICE(zdev->ap_dev->qid)); ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", - zdev->ap_dev->qid, zdev->online); + AP_QID_DEVICE(zdev->ap_dev->qid), zdev->online); return -EAGAIN; /* repeat the request on a different device. */ } } -- cgit v1.2.3 From 0d9bfe9123cfde59bf5c2e375b59d2a7d5061c4c Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Mon, 25 Jan 2016 10:30:27 +0100 Subject: s390/cio: fix measurement characteristics memleak Measurement characteristics are allocated during channel path registration but not freed during deregistration. Fix this by embedding these characteristics inside struct channel_path. Signed-off-by: Sebastian Ott Reviewed-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/chp.c | 6 +++--- drivers/s390/cio/chp.h | 2 +- drivers/s390/cio/chsc.c | 16 ++-------------- 3 files changed, 6 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index c692dfebd0ba..3d2b6c48c18e 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -139,11 +139,11 @@ static ssize_t chp_measurement_chars_read(struct file *filp, device = container_of(kobj, struct device, kobj); chp = to_channelpath(device); - if (!chp->cmg_chars) + if (chp->cmg == -1) return 0; - return memory_read_from_buffer(buf, count, &off, - chp->cmg_chars, sizeof(struct cmg_chars)); + return memory_read_from_buffer(buf, count, &off, &chp->cmg_chars, + sizeof(chp->cmg_chars)); } static struct bin_attribute chp_measurement_chars_attr = { diff --git a/drivers/s390/cio/chp.h b/drivers/s390/cio/chp.h index 4efd5b867cc3..af0232290dc4 100644 --- a/drivers/s390/cio/chp.h +++ b/drivers/s390/cio/chp.h @@ -48,7 +48,7 @@ struct channel_path { /* Channel-measurement related stuff: */ int cmg; int shared; - void *cmg_chars; + struct cmg_chars cmg_chars; }; /* Return channel_path struct for given chpid. */ diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index a831d18596a5..5df0efee54db 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -967,22 +967,19 @@ static void chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv, struct cmg_chars *chars) { - struct cmg_chars *cmg_chars; int i, mask; - cmg_chars = chp->cmg_chars; for (i = 0; i < NR_MEASUREMENT_CHARS; i++) { mask = 0x80 >> (i + 3); if (cmcv & mask) - cmg_chars->values[i] = chars->values[i]; + chp->cmg_chars.values[i] = chars->values[i]; else - cmg_chars->values[i] = 0; + chp->cmg_chars.values[i] = 0; } } int chsc_get_channel_measurement_chars(struct channel_path *chp) { - struct cmg_chars *cmg_chars; int ccode, ret; struct { @@ -1006,11 +1003,6 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp) u32 data[NR_MEASUREMENT_CHARS]; } __attribute__ ((packed)) *scmc_area; - chp->cmg_chars = NULL; - cmg_chars = kmalloc(sizeof(*cmg_chars), GFP_KERNEL); - if (!cmg_chars) - return -ENOMEM; - spin_lock_irq(&chsc_page_lock); memset(chsc_page, 0, PAGE_SIZE); scmc_area = chsc_page; @@ -1042,14 +1034,10 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp) /* No cmg-dependent data. */ goto out; } - chp->cmg_chars = cmg_chars; chsc_initialize_cmg_chars(chp, scmc_area->cmcv, (struct cmg_chars *) &scmc_area->data); out: spin_unlock_irq(&chsc_page_lock); - if (!chp->cmg_chars) - kfree(cmg_chars); - return ret; } -- cgit v1.2.3 From 61f0bfcf8020f02eb09adaef96745d1c1d1b3623 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Mon, 25 Jan 2016 10:31:33 +0100 Subject: s390/cio: ensure consistent measurement state Make sure that in all cases where we could not obtain measurement characteristics the associated fields are set to invalid values. Note: without this change the "shared" capability of a channel path for which we could not obtain the measurement characteristics was incorrectly displayed as 0 (not shared). We will now correctly report "unknown" in this case. Signed-off-by: Sebastian Ott Reviewed-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/chp.c | 13 +++++-------- drivers/s390/cio/chsc.c | 12 ++++++++---- 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index 3d2b6c48c18e..8504629cbf72 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -466,14 +466,11 @@ int chp_new(struct chp_id chpid) ret = -ENODEV; goto out_free; } - /* Get channel-measurement characteristics. */ - if (css_chsc_characteristics.scmc && css_chsc_characteristics.secm) { - ret = chsc_get_channel_measurement_chars(chp); - if (ret) - goto out_free; - } else { - chp->cmg = -1; - } + + ret = chsc_get_channel_measurement_chars(chp); + if (ret) + goto out_free; + dev_set_name(&chp->dev, "chp%x.%02x", chpid.cssid, chpid.id); /* make it known to the system */ diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 5df0efee54db..13747c510c0b 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -1003,6 +1003,12 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp) u32 data[NR_MEASUREMENT_CHARS]; } __attribute__ ((packed)) *scmc_area; + chp->shared = -1; + chp->cmg = -1; + + if (!css_chsc_characteristics.scmc || !css_chsc_characteristics.secm) + return 0; + spin_lock_irq(&chsc_page_lock); memset(chsc_page, 0, PAGE_SIZE); scmc_area = chsc_page; @@ -1023,11 +1029,9 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp) scmc_area->response.code); goto out; } - if (scmc_area->not_valid) { - chp->cmg = -1; - chp->shared = -1; + if (scmc_area->not_valid) goto out; - } + chp->cmg = scmc_area->cmg; chp->shared = scmc_area->shared; if (chp->cmg != 2 && chp->cmg != 3) { -- cgit v1.2.3 From 9f3d6d7a40a178b8a5b5274f4e55fec8c30147c9 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Mon, 25 Jan 2016 10:32:51 +0100 Subject: s390/cio: update measurement characteristics Per channel path measurement characteristics are obtained during channel path registration. However if some properties of a channel path change we don't update the measurement characteristics. Make sure to update the characteristics when we change the properties of a channel path or receive a notification from FW about such a change. Signed-off-by: Sebastian Ott Reviewed-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/chp.c | 12 +++++------- drivers/s390/cio/chsc.c | 17 +++++++++++++++-- 2 files changed, 20 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index 8504629cbf72..50597f9522fe 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -416,7 +416,8 @@ static void chp_release(struct device *dev) * chp_update_desc - update channel-path description * @chp - channel-path * - * Update the channel-path description of the specified channel-path. + * Update the channel-path description of the specified channel-path + * including channel measurement related information. * Return zero on success, non-zero otherwise. */ int chp_update_desc(struct channel_path *chp) @@ -428,8 +429,10 @@ int chp_update_desc(struct channel_path *chp) return rc; rc = chsc_determine_fmt1_channel_path_desc(chp->chpid, &chp->desc_fmt1); + if (rc) + return rc; - return rc; + return chsc_get_channel_measurement_chars(chp); } /** @@ -466,11 +469,6 @@ int chp_new(struct chp_id chpid) ret = -ENODEV; goto out_free; } - - ret = chsc_get_channel_measurement_chars(chp); - if (ret) - goto out_free; - dev_set_name(&chp->dev, "chp%x.%02x", chpid.cssid, chpid.id); /* make it known to the system */ diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 13747c510c0b..c424c0c7367e 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -224,8 +225,9 @@ out_unreg: void chsc_chp_offline(struct chp_id chpid) { - char dbf_txt[15]; + struct channel_path *chp = chpid_to_chp(chpid); struct chp_link link; + char dbf_txt[15]; sprintf(dbf_txt, "chpr%x.%02x", chpid.cssid, chpid.id); CIO_TRACE_EVENT(2, dbf_txt); @@ -236,6 +238,11 @@ void chsc_chp_offline(struct chp_id chpid) link.chpid = chpid; /* Wait until previous actions have settled. */ css_wait_for_slow_path(); + + mutex_lock(&chp->lock); + chp_update_desc(chp); + mutex_unlock(&chp->lock); + for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &link); } @@ -690,8 +697,9 @@ static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow) void chsc_chp_online(struct chp_id chpid) { - char dbf_txt[15]; + struct channel_path *chp = chpid_to_chp(chpid); struct chp_link link; + char dbf_txt[15]; sprintf(dbf_txt, "cadd%x.%02x", chpid.cssid, chpid.id); CIO_TRACE_EVENT(2, dbf_txt); @@ -701,6 +709,11 @@ void chsc_chp_online(struct chp_id chpid) link.chpid = chpid; /* Wait until previous actions have settled. */ css_wait_for_slow_path(); + + mutex_lock(&chp->lock); + chp_update_desc(chp); + mutex_unlock(&chp->lock); + for_each_subchannel_staged(__s390_process_res_acc, NULL, &link); css_schedule_reprobe(); -- cgit v1.2.3 From ca296c571f6929e42dc0ac0bb5c81cdb5323362d Mon Sep 17 00:00:00 2001 From: Oren Givon Date: Thu, 14 Jan 2016 10:24:10 +0200 Subject: iwlwifi: update support for 3168 series firmware and NVM Update the struct which defines the support for 3168 cards. Now it will search for a firmware of this format: iwlwifi-3168-XX.ucode Also, set the minimum version of the ucode to 20. Update the minimum NVM version and minimum NVM calibrations version of the 3168 series. Signed-off-by: Oren Givon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-7000.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c index e60cf141ed79..fa41a5e1c890 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c @@ -74,16 +74,19 @@ #define IWL7260_UCODE_API_MAX 17 #define IWL7265_UCODE_API_MAX 17 #define IWL7265D_UCODE_API_MAX 20 +#define IWL3168_UCODE_API_MAX 20 /* Oldest version we won't warn about */ #define IWL7260_UCODE_API_OK 13 #define IWL7265_UCODE_API_OK 13 #define IWL7265D_UCODE_API_OK 13 +#define IWL3168_UCODE_API_OK 20 /* Lowest firmware API version supported */ #define IWL7260_UCODE_API_MIN 13 #define IWL7265_UCODE_API_MIN 13 #define IWL7265D_UCODE_API_MIN 13 +#define IWL3168_UCODE_API_MIN 20 /* NVM versions */ #define IWL7260_NVM_VERSION 0x0a1d @@ -92,6 +95,8 @@ #define IWL3160_TX_POWER_VERSION 0xffff /* meaningless */ #define IWL3165_NVM_VERSION 0x709 #define IWL3165_TX_POWER_VERSION 0xffff /* meaningless */ +#define IWL3168_NVM_VERSION 0xd01 +#define IWL3168_TX_POWER_VERSION 0xffff /* meaningless */ #define IWL7265_NVM_VERSION 0x0a1d #define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */ #define IWL7265D_NVM_VERSION 0x0c11 @@ -109,6 +114,9 @@ #define IWL3160_FW_PRE "iwlwifi-3160-" #define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode" +#define IWL3168_FW_PRE "iwlwifi-3168-" +#define IWL3168_MODULE_FIRMWARE(api) IWL3168_FW_PRE __stringify(api) ".ucode" + #define IWL7265_FW_PRE "iwlwifi-7265-" #define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode" @@ -180,6 +188,12 @@ static const struct iwl_ht_params iwl7000_ht_params = { .ucode_api_ok = IWL7265_UCODE_API_OK, \ .ucode_api_min = IWL7265_UCODE_API_MIN +#define IWL_DEVICE_3008 \ + IWL_DEVICE_7000_COMMON, \ + .ucode_api_max = IWL3168_UCODE_API_MAX, \ + .ucode_api_ok = IWL3168_UCODE_API_OK, \ + .ucode_api_min = IWL3168_UCODE_API_MIN + #define IWL_DEVICE_7005D \ IWL_DEVICE_7000_COMMON, \ .ucode_api_max = IWL7265D_UCODE_API_MAX, \ @@ -299,11 +313,11 @@ const struct iwl_cfg iwl3165_2ac_cfg = { const struct iwl_cfg iwl3168_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 3168", - .fw_name_pre = IWL7265D_FW_PRE, - IWL_DEVICE_7000, + .fw_name_pre = IWL3168_FW_PRE, + IWL_DEVICE_3008, .ht_params = &iwl7000_ht_params, - .nvm_ver = IWL3165_NVM_VERSION, - .nvm_calib_ver = IWL3165_TX_POWER_VERSION, + .nvm_ver = IWL3168_NVM_VERSION, + .nvm_calib_ver = IWL3168_TX_POWER_VERSION, .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs, .dccm_len = IWL7265_DCCM_LEN, }; @@ -376,5 +390,6 @@ const struct iwl_cfg iwl7265d_n_cfg = { MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); +MODULE_FIRMWARE(IWL3168_MODULE_FIRMWARE(IWL3168_UCODE_API_OK)); MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7265_UCODE_API_OK)); MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7265D_UCODE_API_OK)); -- cgit v1.2.3 From 69c7fda40921c125eeeef6a827f6270ac6aa1baa Mon Sep 17 00:00:00 2001 From: Gregory Greenman Date: Tue, 29 Dec 2015 11:26:35 +0200 Subject: iwlwifi: mvm: rs: fix TPC statistics handling FW behaviour changed and now updates driver about the used TPC reduction in the following cases: 1. In tx response, which is used mostly for a single frame case 2. In BA notification When tx aggregation fails with the initial rate, FW will send to the driver BA notification and will try to transmit with the next rate, but this time without tx power reduction. Thus, in case of a failure with the initial rate, driver will get two BA notifications, the first one with reduced tx power as in the LQ command and the second one with 0 power reduction. This patch adapts the TPC statistics according to the description above: 1. Use BA notifications instead of Tx response 2. For TPC only, drop the optimization which considers empty BA as one MPDU. The reason is that with TPC we want to recover very quickly from a bad power reduction and, therefore we'd like the success ratio to get an immediate hit when failing to get a BA, so we'd switch back to a lower or zero power reduction Signed-off-by: Gregory Greenman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h | 6 +- drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 74 ++++++++++++++-------- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 5 +- 3 files changed, 56 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h index 0036d18334af..ba3f0bbddde8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h @@ -510,6 +510,9 @@ struct iwl_mvm_tx_resp { * @scd_ssn: the index of the last contiguously sent packet * @txed: number of Txed frames in this batch * @txed_2_done: number of Acked frames in this batch + * @reduced_txp: power reduced according to TPC. This is the actual value and + * not a copy from the LQ command. Thus, if not the first rate was used + * for Tx-ing then this value will be set to 0 by FW. */ struct iwl_mvm_ba_notif { __le32 sta_addr_lo32; @@ -524,7 +527,8 @@ struct iwl_mvm_ba_notif { __le16 scd_ssn; u8 txed; u8 txed_2_done; - __le16 reserved1; + u8 reduced_txp; + u8 reserved1; } __packed; /* diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 7bb6fd0e4391..94caa88df442 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -2,6 +2,7 @@ * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * 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 @@ -724,14 +725,28 @@ static int _rs_collect_tx_data(struct iwl_mvm *mvm, return 0; } -static int rs_collect_tx_data(struct iwl_mvm *mvm, - struct iwl_lq_sta *lq_sta, - struct iwl_scale_tbl_info *tbl, - int scale_index, int attempts, int successes, - u8 reduced_txp) +static int rs_collect_tpc_data(struct iwl_mvm *mvm, + struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl, + int scale_index, int attempts, int successes, + u8 reduced_txp) +{ + struct iwl_rate_scale_data *window = NULL; + + if (WARN_ON_ONCE(reduced_txp > TPC_MAX_REDUCTION)) + return -EINVAL; + + window = &tbl->tpc_win[reduced_txp]; + return _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes, + window); +} + +static int rs_collect_tlc_data(struct iwl_mvm *mvm, + struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl, + int scale_index, int attempts, int successes) { struct iwl_rate_scale_data *window = NULL; - int ret; if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) return -EINVAL; @@ -745,16 +760,6 @@ static int rs_collect_tx_data(struct iwl_mvm *mvm, /* Select window for current tx bit rate */ window = &(tbl->win[scale_index]); - - ret = _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes, - window); - if (ret) - return ret; - - if (WARN_ON_ONCE(reduced_txp > TPC_MAX_REDUCTION)) - return -EINVAL; - - window = &tbl->tpc_win[reduced_txp]; return _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes, window); } @@ -1301,17 +1306,30 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, * first index into rate scale table. */ if (info->flags & IEEE80211_TX_STAT_AMPDU) { - /* ampdu_ack_len = 0 marks no BA was received. In this case - * treat it as a single frame loss as we don't want the success - * ratio to dip too quickly because a BA wasn't received + rs_collect_tpc_data(mvm, lq_sta, curr_tbl, lq_rate.index, + info->status.ampdu_len, + info->status.ampdu_ack_len, + reduced_txp); + + /* ampdu_ack_len = 0 marks no BA was received. For TLC, treat + * it as a single frame loss as we don't want the success ratio + * to dip too quickly because a BA wasn't received. + * For TPC, there's no need for this optimisation since we want + * to recover very quickly from a bad power reduction and, + * therefore we'd like the success ratio to get an immediate hit + * when failing to get a BA, so we'd switch back to a lower or + * zero power reduction. When FW transmits agg with a rate + * different from the initial rate, it will not use reduced txp + * and will send BA notification twice (one empty with reduced + * txp equal to the value from LQ and one with reduced txp 0). + * We need to update counters for each txp level accordingly. */ if (info->status.ampdu_ack_len == 0) info->status.ampdu_len = 1; - rs_collect_tx_data(mvm, lq_sta, curr_tbl, lq_rate.index, - info->status.ampdu_len, - info->status.ampdu_ack_len, - reduced_txp); + rs_collect_tlc_data(mvm, lq_sta, curr_tbl, lq_rate.index, + info->status.ampdu_len, + info->status.ampdu_ack_len); /* Update success/fail counts if not searching for new mode */ if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { @@ -1344,9 +1362,13 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, else continue; - rs_collect_tx_data(mvm, lq_sta, tmp_tbl, lq_rate.index, - 1, i < retries ? 0 : legacy_success, - reduced_txp); + rs_collect_tpc_data(mvm, lq_sta, tmp_tbl, + lq_rate.index, 1, + i < retries ? 0 : legacy_success, + reduced_txp); + rs_collect_tlc_data(mvm, lq_sta, tmp_tbl, + lq_rate.index, 1, + i < retries ? 0 : legacy_success); } /* Update success/fail counts if not searching for new mode */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 8bf48a7d0f4e..0914ec2fd574 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -1029,7 +1029,6 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); mvmsta->tid_data[tid].rate_n_flags = le32_to_cpu(tx_resp->initial_rate); - mvmsta->tid_data[tid].reduced_tpc = tx_resp->reduced_tpc; mvmsta->tid_data[tid].tx_time = le16_to_cpu(tx_resp->wireless_media_time); } @@ -1060,7 +1059,7 @@ static void iwl_mvm_tx_info_from_ba_notif(struct ieee80211_tx_info *info, /* TODO: not accounted if the whole A-MPDU failed */ info->status.tx_time = tid_data->tx_time; info->status.status_driver_data[0] = - (void *)(uintptr_t)tid_data->reduced_tpc; + (void *)(uintptr_t)ba_notif->reduced_txp; info->status.status_driver_data[1] = (void *)(uintptr_t)tid_data->rate_n_flags; } @@ -1133,6 +1132,8 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) scd_flow, ba_resp_scd_ssn, ba_notif->txed, ba_notif->txed_2_done); + IWL_DEBUG_TX_REPLY(mvm, "reduced txp from ba notif %d\n", + ba_notif->reduced_txp); tid_data->next_reclaimed = ba_resp_scd_ssn; iwl_mvm_check_ratid_empty(mvm, sta, tid); -- cgit v1.2.3 From 625b4a982788fefe1361daee2ea160192cd80572 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 25 Jan 2016 23:24:04 +0100 Subject: hwrng: stm32 - Fix dependencies for !HAS_IOMEM archs Not every arch has io memory. So, unbreak the build by fixing the dependencies. Signed-off-by: Richard Weinberger Reviewed-by: Daniel Thompson Signed-off-by: Herbert Xu --- drivers/char/hw_random/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index dbf22719462f..ff00331bff49 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -372,6 +372,7 @@ config HW_RANDOM_XGENE config HW_RANDOM_STM32 tristate "STMicroelectronics STM32 random number generator" depends on HW_RANDOM && (ARCH_STM32 || COMPILE_TEST) + depends on HAS_IOMEM help This driver provides kernel-side support for the Random Number Generator hardware found on STM32 microcontrollers. -- cgit v1.2.3 From c1e9b3b0eea12899b7749571af21cc60822cf2b6 Mon Sep 17 00:00:00 2001 From: Anatoly Pugachev Date: Tue, 26 Jan 2016 00:19:02 +0300 Subject: hwrng: n2 - Attach on T5/M5, T7/M7 SPARC CPUs n2rng: Attach on T5/M5, T7/M7 SPARC CPUs (space to tab fixes after variable names) Signed-off-by: Anatoly Pugachev Signed-off-by: Herbert Xu --- drivers/char/hw_random/n2-drv.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 843d6f6aee7a..3b06c1d6cfb2 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c @@ -743,6 +743,16 @@ static const struct of_device_id n2rng_match[] = { .compatible = "SUNW,kt-rng", .data = (void *) 1, }, + { + .name = "random-number-generator", + .compatible = "ORCL,m4-rng", + .data = (void *) 1, + }, + { + .name = "random-number-generator", + .compatible = "ORCL,m7-rng", + .data = (void *) 1, + }, {}, }; MODULE_DEVICE_TABLE(of, n2rng_match); -- cgit v1.2.3 From 774e656e94cdd8db27a8831abb3d35fbb95d2bc6 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 13 Jan 2016 21:16:29 +0530 Subject: ath10k: fix naming Peer stats rssi_changed field in 10.2.4 Fix naming of peer stats rssi_changed field in 10.2.4 to make it more readable. As of now this field is not used, but necessary to pull in fw_stats with appropriate length. Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index e1bb02ba207d..187f495c1fbe 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4233,7 +4233,7 @@ struct wmi_10_2_peer_stats { struct wmi_10_2_4_peer_stats { struct wmi_10_2_peer_stats common; - __le32 unknown_value; /* FIXME: what is this word? */ + __le32 peer_rssi_changed; } __packed; struct wmi_10_2_4_ext_peer_stats { -- cgit v1.2.3 From 1fe374f5b07ed58e485fdbfa7410876e25ce1a78 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 13 Jan 2016 21:16:30 +0530 Subject: ath10k: cleanup setting pdev paramaters Replace the local variable 'burst_enable' with 'param' for mapping and setting pdev paraemeters and with this patch pretty easy to extend support for new parameters adhering to linux kernel coding guidelines Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 6146a293601a..0d7671c778fd 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3988,7 +3988,7 @@ static int ath10k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) static int ath10k_start(struct ieee80211_hw *hw) { struct ath10k *ar = hw->priv; - u32 burst_enable; + u32 param; int ret = 0; /* @@ -4031,13 +4031,15 @@ static int ath10k_start(struct ieee80211_hw *hw) goto err_power_down; } - ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->pmf_qos, 1); + param = ar->wmi.pdev_param->pmf_qos; + ret = ath10k_wmi_pdev_set_param(ar, param, 1); if (ret) { ath10k_warn(ar, "failed to enable PMF QOS: %d\n", ret); goto err_core_stop; } - ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->dynamic_bw, 1); + param = ar->wmi.pdev_param->dynamic_bw; + ret = ath10k_wmi_pdev_set_param(ar, param, 1); if (ret) { ath10k_warn(ar, "failed to enable dynamic BW: %d\n", ret); goto err_core_stop; @@ -4053,8 +4055,8 @@ static int ath10k_start(struct ieee80211_hw *hw) } if (test_bit(WMI_SERVICE_BURST, ar->wmi.svc_map)) { - burst_enable = ar->wmi.pdev_param->burst_enable; - ret = ath10k_wmi_pdev_set_param(ar, burst_enable, 0); + param = ar->wmi.pdev_param->burst_enable; + ret = ath10k_wmi_pdev_set_param(ar, param, 0); if (ret) { ath10k_warn(ar, "failed to disable burst: %d\n", ret); goto err_core_stop; @@ -4072,8 +4074,8 @@ static int ath10k_start(struct ieee80211_hw *hw) * this problem. */ - ret = ath10k_wmi_pdev_set_param(ar, - ar->wmi.pdev_param->arp_ac_override, 0); + param = ar->wmi.pdev_param->arp_ac_override; + ret = ath10k_wmi_pdev_set_param(ar, param, 0); if (ret) { ath10k_warn(ar, "failed to set arp ac override parameter: %d\n", ret); @@ -4092,8 +4094,8 @@ static int ath10k_start(struct ieee80211_hw *hw) } } - ret = ath10k_wmi_pdev_set_param(ar, - ar->wmi.pdev_param->ani_enable, 1); + param = ar->wmi.pdev_param->ani_enable; + ret = ath10k_wmi_pdev_set_param(ar, param, 1); if (ret) { ath10k_warn(ar, "failed to enable ani by default: %d\n", ret); -- cgit v1.2.3 From b4619ea2f72153df42d8ba2894b2af5e621d6df6 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 13 Jan 2016 21:16:31 +0530 Subject: ath10k: rename few function names of firmware stats Prerequisite patch to address checkpatch errors for the next patch in this series, this function names are bit too long, make it short Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/debug.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 2bdf5408b0d9..4fb1e0eb3408 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -276,7 +276,7 @@ static const struct file_operations fops_wmi_services = { .llseek = default_llseek, }; -static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head) +static void ath10k_fw_stats_pdevs_free(struct list_head *head) { struct ath10k_fw_stats_pdev *i, *tmp; @@ -286,7 +286,7 @@ static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head) } } -static void ath10k_debug_fw_stats_vdevs_free(struct list_head *head) +static void ath10k_fw_stats_vdevs_free(struct list_head *head) { struct ath10k_fw_stats_vdev *i, *tmp; @@ -296,7 +296,7 @@ static void ath10k_debug_fw_stats_vdevs_free(struct list_head *head) } } -static void ath10k_debug_fw_stats_peers_free(struct list_head *head) +static void ath10k_fw_stats_peers_free(struct list_head *head) { struct ath10k_fw_stats_peer *i, *tmp; @@ -310,9 +310,9 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar) { spin_lock_bh(&ar->data_lock); ar->debug.fw_stats_done = false; - ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs); - ath10k_debug_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs); - ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers); + ath10k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs); + ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs); + ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers); spin_unlock_bh(&ar->data_lock); } @@ -391,9 +391,9 @@ free: /* In some cases lists have been spliced and cleared. Free up * resources if that is not the case. */ - ath10k_debug_fw_stats_pdevs_free(&stats.pdevs); - ath10k_debug_fw_stats_vdevs_free(&stats.vdevs); - ath10k_debug_fw_stats_peers_free(&stats.peers); + ath10k_fw_stats_pdevs_free(&stats.pdevs); + ath10k_fw_stats_vdevs_free(&stats.vdevs); + ath10k_fw_stats_peers_free(&stats.peers); spin_unlock_bh(&ar->data_lock); } -- cgit v1.2.3 From d57e7f2e7e042a7cef19702abe42f1e9b55d754c Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 13 Jan 2016 21:16:32 +0530 Subject: ath10k: provision to support periodic peer stats update Enable support for periodic peer stats update when peer stats service is enabled. The host to update the peer stats received from the firmware periodically, since firmware will reset this to zero after sometime (due to memory constraints) While enabling periodic peer / vdev stats cleanup the existing list in debugfs if max limit is reached, so that the new stats is updated. Ideally speaking based on 'Michal Kazior's' suggestion we need to completely move to periodic update of all the stats making the 'ping - pong' method obselete. This requires a bit of re-work and some testing as well, also confirmation regarding backward comptability for various firmware and chipsets. Hence allow periodic update only for peer_stats. Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/debug.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 4fb1e0eb3408..3b8da817972b 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -347,7 +347,8 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) * delivered which is treated as end-of-data and is itself discarded */ - if (ar->debug.fw_stats_done) { + if (ar->debug.fw_stats_done && + !test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) { ath10k_warn(ar, "received unsolicited stats update event\n"); goto free; } @@ -372,11 +373,13 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) /* Although this is unlikely impose a sane limit to * prevent firmware from DoS-ing the host. */ + ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers); ath10k_warn(ar, "dropping fw peer stats\n"); goto free; } if (num_vdevs >= BITS_PER_LONG) { + ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs); ath10k_warn(ar, "dropping fw vdev stats\n"); goto free; } -- cgit v1.2.3 From 8351c052194b30f852db6225a568e48ee2a4947b Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 13 Jan 2016 21:16:33 +0530 Subject: ath10k: enable periodic peer stats update Register for 500ms as periodic peer stats update period, and parameters like rx_duration that needs to be tracked in host can be achieved by this provision, also periodic stats update is the future of fw_stats and shall be extended for pdev / vdev stats irrespecitive PEER_STATS service is enabled or not Signed-off-by: Mohammed Shafi Shajakhan [kvalo@qca.qualcomm.com: fix a checkpatch warning] Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 0d7671c778fd..ef0438d2cc8f 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4104,6 +4104,18 @@ static int ath10k_start(struct ieee80211_hw *hw) ar->ani_enabled = true; + if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) { + param = ar->wmi.pdev_param->peer_stats_update_period; + ret = ath10k_wmi_pdev_set_param(ar, param, + PEER_DEFAULT_STATS_UPDATE_PERIOD); + if (ret) { + ath10k_warn(ar, + "failed to set peer stats period : %d\n", + ret); + goto err_core_stop; + } + } + ar->num_started_vdevs = 0; ath10k_regd_update(ar); -- cgit v1.2.3 From 856e7c3084399fb7e029628dbe43dcb9bb7d7b5b Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 13 Jan 2016 21:16:34 +0530 Subject: ath10k: add debugfs support for Per STA total rx duration Add debugfs support for per client total rx duration, track this via the report of Peer stats rx duration reported for every 500ms Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/debug.c | 9 ++++-- drivers/net/wireless/ath/ath10k/debug.h | 6 ++++ drivers/net/wireless/ath/ath10k/debugfs_sta.c | 41 +++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index d47a08568bdc..921b86a4f257 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -316,6 +316,7 @@ struct ath10k_sta { #ifdef CONFIG_MAC80211_DEBUGFS /* protected by conf_mutex */ bool aggr_mode; + u64 rx_duration; #endif }; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 3b8da817972b..8d4148a96af8 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -319,7 +319,7 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar) void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) { struct ath10k_fw_stats stats = {}; - bool is_start, is_started, is_end; + bool is_start, is_started, is_end, peer_stats_svc; size_t num_peers; size_t num_vdevs; int ret; @@ -347,8 +347,8 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) * delivered which is treated as end-of-data and is itself discarded */ - if (ar->debug.fw_stats_done && - !test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) { + peer_stats_svc = test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map); + if (ar->debug.fw_stats_done && !peer_stats_svc) { ath10k_warn(ar, "received unsolicited stats update event\n"); goto free; } @@ -384,6 +384,9 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) goto free; } + if (peer_stats_svc) + ath10k_sta_update_rx_duration(ar, &stats.peers); + list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers); list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs); } diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 814719cf4f22..f273478e2afb 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -153,6 +153,12 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar) #ifdef CONFIG_MAC80211_DEBUGFS void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct dentry *dir); +void ath10k_sta_update_rx_duration(struct ath10k *ar, struct list_head *peer); +#else +static inline void ath10k_sta_update_rx_duration(struct ath10k *ar, + struct list_head *peer) +{ +} #endif /* CONFIG_MAC80211_DEBUGFS */ #ifdef CONFIG_ATH10K_DEBUG diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c index 95b5c49374e0..67ef75b60567 100644 --- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c @@ -18,6 +18,23 @@ #include "wmi-ops.h" #include "debug.h" +void ath10k_sta_update_rx_duration(struct ath10k *ar, struct list_head *head) +{ struct ieee80211_sta *sta; + struct ath10k_fw_stats_peer *peer; + struct ath10k_sta *arsta; + + rcu_read_lock(); + list_for_each_entry(peer, head, list) { + sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr, + NULL); + if (!sta) + continue; + arsta = (struct ath10k_sta *)sta->drv_priv; + arsta->rx_duration += (u64)peer->rx_duration; + } + rcu_read_unlock(); +} + static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -232,6 +249,28 @@ static const struct file_operations fops_delba = { .llseek = default_llseek, }; +static ssize_t ath10k_dbg_sta_read_rx_duration(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_sta *sta = file->private_data; + struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; + char buf[100]; + int len = 0; + + len = scnprintf(buf, sizeof(buf), + "%llu usecs\n", arsta->rx_duration); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_rx_duration = { + .read = ath10k_dbg_sta_read_rx_duration, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct dentry *dir) { @@ -240,4 +279,6 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, debugfs_create_file("addba", S_IWUSR, dir, sta, &fops_addba); debugfs_create_file("addba_resp", S_IWUSR, dir, sta, &fops_addba_resp); debugfs_create_file("delba", S_IWUSR, dir, sta, &fops_delba); + debugfs_create_file("rx_duration", S_IRUGO, dir, sta, + &fops_rx_duration); } -- cgit v1.2.3 From 8b019fb0d0e75e2f682f17742b99c0ca970ca024 Mon Sep 17 00:00:00 2001 From: Yanbo Li Date: Thu, 14 Jan 2016 15:39:19 -0800 Subject: ath10k: remove the p2p notice of absence info from 10.2.4 FW beacon info The p2p NOA never been supported at 10.2.4 FW, remove it to avoid SWBA event parse error for multi beacon interval case. Signed-off-by: Yanbo Li Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 46 ++++++++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath10k/wmi.h | 10 ++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index c610d1761940..0f01a8d99604 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -3256,6 +3256,50 @@ static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb, return 0; } +static int ath10k_wmi_10_2_4_op_pull_swba_ev(struct ath10k *ar, + struct sk_buff *skb, + struct wmi_swba_ev_arg *arg) +{ + struct wmi_10_2_4_host_swba_event *ev = (void *)skb->data; + u32 map; + size_t i; + + if (skb->len < sizeof(*ev)) + return -EPROTO; + + skb_pull(skb, sizeof(*ev)); + arg->vdev_map = ev->vdev_map; + + for (i = 0, map = __le32_to_cpu(ev->vdev_map); map; map >>= 1) { + if (!(map & BIT(0))) + continue; + + /* If this happens there were some changes in firmware and + * ath10k should update the max size of tim_info array. + */ + if (WARN_ON_ONCE(i == ARRAY_SIZE(arg->tim_info))) + break; + + if (__le32_to_cpu(ev->bcn_info[i].tim_info.tim_len) > + sizeof(ev->bcn_info[i].tim_info.tim_bitmap)) { + ath10k_warn(ar, "refusing to parse invalid swba structure\n"); + return -EPROTO; + } + + arg->tim_info[i].tim_len = ev->bcn_info[i].tim_info.tim_len; + arg->tim_info[i].tim_mcast = ev->bcn_info[i].tim_info.tim_mcast; + arg->tim_info[i].tim_bitmap = + ev->bcn_info[i].tim_info.tim_bitmap; + arg->tim_info[i].tim_changed = + ev->bcn_info[i].tim_info.tim_changed; + arg->tim_info[i].tim_num_ps_pending = + ev->bcn_info[i].tim_info.tim_num_ps_pending; + i++; + } + + return 0; +} + static int ath10k_wmi_10_4_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb, struct wmi_swba_ev_arg *arg) @@ -7584,7 +7628,7 @@ static const struct wmi_ops wmi_10_2_4_ops = { .pull_ch_info = ath10k_wmi_op_pull_ch_info_ev, .pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev, .pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev, - .pull_swba = ath10k_wmi_op_pull_swba_ev, + .pull_swba = ath10k_wmi_10_2_4_op_pull_swba_ev, .pull_phyerr_hdr = ath10k_wmi_op_pull_phyerr_ev_hdr, .pull_phyerr = ath10k_wmi_op_pull_phyerr_ev, .pull_rdy = ath10k_wmi_op_pull_rdy_ev, diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 187f495c1fbe..806d4bb6e7d6 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -5454,6 +5454,16 @@ struct wmi_host_swba_event { struct wmi_bcn_info bcn_info[0]; } __packed; +struct wmi_10_2_4_bcn_info { + struct wmi_tim_info tim_info; + /* The 10.2.4 FW doesn't have p2p NOA info */ +} __packed; + +struct wmi_10_2_4_host_swba_event { + __le32 vdev_map; + struct wmi_10_2_4_bcn_info bcn_info[0]; +} __packed; + /* 16 words = 512 client + 1 word = for guard */ #define WMI_10_4_TIM_BITMAP_ARRAY_SIZE 17 -- cgit v1.2.3 From b9a9693fd9aea43f50b107dfc8cbaea317f95a79 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Fri, 27 Nov 2015 09:37:14 +0100 Subject: ath9k: request NOA update when chanctx active Request NOA update when chanctx active, also in case of STA. Signed-off-by: Janusz Dziedzic Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/channel.c | 2 +- drivers/net/wireless/ath/ath9k/main.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 50e614b915f1..0bcb82abd094 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -1454,7 +1454,7 @@ static void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif) if (!sc->p2p_ps_timer) return; - if (vif->type != NL80211_IFTYPE_STATION || !vif->p2p) + if (vif->type != NL80211_IFTYPE_STATION) return; sc->p2p_ps_vif = avp; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c1b33fdcca08..4ae63fd4290e 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -978,7 +978,7 @@ static void ath9k_update_bssid_mask(struct ath_softc *sc, if (ctx->nvifs_assigned != 1) continue; - if (!avp->vif->p2p || !iter_data->has_hw_macaddr) + if (!iter_data->has_hw_macaddr) continue; ether_addr_copy(common->curbssid, avp->bssid); @@ -1255,6 +1255,9 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type); sc->cur_chan->nvifs++; + if (vif->type == NL80211_IFTYPE_STATION && ath9k_is_chanctx_enabled()) + vif->driver_flags |= IEEE80211_VIF_GET_NOA_UPDATE; + if (ath9k_uses_beacons(vif->type)) ath9k_beacon_assign_slot(sc, vif); -- cgit v1.2.3 From aea57edf80c6e96d6dc24757599396af99c02b19 Mon Sep 17 00:00:00 2001 From: Alexander Tsoy Date: Fri, 8 Jan 2016 01:26:03 +0300 Subject: ath9k_htc: add device ID for Toshiba WLM-20U2/GN-1080 This device is available under different marketing names: WLM-20U2 - Wireless USB Dongle for Toshiba TVs GN-1080 - Wireless LAN Module for Toshiba MFPs. Signed-off-by: Alexander Tsoy Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/hif_usb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 165dd202c365..8cbf4904db7b 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -55,6 +55,8 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { .driver_info = AR9280_USB }, /* Buffalo WLI-UV-AG300P */ { USB_DEVICE(0x04da, 0x3904), .driver_info = AR9280_USB }, + { USB_DEVICE(0x0930, 0x0a08), + .driver_info = AR9280_USB }, /* Toshiba WLM-20U2 and GN-1080 */ { USB_DEVICE(0x0cf3, 0x20ff), .driver_info = STORAGE_DEVICE }, -- cgit v1.2.3 From c5a157e4d7d7f1d39dbb382bc3ad7ea9f248ed7d Mon Sep 17 00:00:00 2001 From: Lior David Date: Sun, 17 Jan 2016 12:39:06 +0200 Subject: wil6210: fix privacy flag calculation in change_beacon Currently the privacy flag calculation in change_beacon checks for RSN IE inside proberesp_ies, but normally it is not found there. It works today because of code inside the function wil_fix_bcon, but wil_fix_bcon is not directly related to change_beacon, and it may be changed or removed in the future and break the calculation. To fix this issue, change the privacy flag calculation to check RSN IE inside the beacon itself. The new check is more reliable and will not be sensitive to changes in wil_fix_bcon. Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 20d07ef679e8..182f071f722d 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -828,9 +828,9 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy, wil_print_bcon_data(bcon); } - if (bcon->proberesp_ies && - cfg80211_find_ie(WLAN_EID_RSN, bcon->proberesp_ies, - bcon->proberesp_ies_len)) + if (bcon->tail && + cfg80211_find_ie(WLAN_EID_RSN, bcon->tail, + bcon->tail_len)) privacy = 1; /* in case privacy has changed, need to restart the AP */ -- cgit v1.2.3 From c100c883e785802ab333604237928a65ae62c6bc Mon Sep 17 00:00:00 2001 From: Lior David Date: Sun, 17 Jan 2016 12:39:07 +0200 Subject: wil6210: use extra IEs from probe response In the start_ap/change_beacon API, when we set up probe response offloading, we only use the IE list from the probe response template and not the IE list from the proberesp_ies argument. As a result, we miss important IEs and it causes problems with some scenarios such as P2P. With this change, we merge the list of IEs from the probe response template and proberesp_ies and send the merged list to the FW for offloading. It is still FW responsibility to filter out irrelevant IEs when sending probe response, based on the actual contents of the probe request. Also in case association response termplate is not provided, we will use the merged list of IEs from probe response in the association response as well. Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 141 ++++++++++++++++++++-------- 1 file changed, 102 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 182f071f722d..774352f9e256 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -696,6 +696,79 @@ static int wil_cancel_remain_on_channel(struct wiphy *wiphy, return rc; } +/** + * find a specific IE in a list of IEs + * return a pointer to the beginning of IE in the list + * or NULL if not found + */ +static const u8 *_wil_cfg80211_find_ie(const u8 *ies, u16 ies_len, const u8 *ie, + u16 ie_len) +{ + struct ieee80211_vendor_ie *vie; + u32 oui; + + /* IE tag at offset 0, length at offset 1 */ + if (ie_len < 2 || 2 + ie[1] > ie_len) + return NULL; + + if (ie[0] != WLAN_EID_VENDOR_SPECIFIC) + return cfg80211_find_ie(ie[0], ies, ies_len); + + /* make sure there is room for 3 bytes OUI + 1 byte OUI type */ + if (ie[1] < 4) + return NULL; + vie = (struct ieee80211_vendor_ie *)ie; + oui = vie->oui[0] << 16 | vie->oui[1] << 8 | vie->oui[2]; + return cfg80211_find_vendor_ie(oui, vie->oui_type, ies, + ies_len); +} + +/** + * merge the IEs in two lists into a single list. + * do not include IEs from the second list which exist in the first list. + * add only vendor specific IEs from second list to keep + * the merged list sorted (since vendor-specific IE has the + * highest tag number) + * caller must free the allocated memory for merged IEs + */ +static int _wil_cfg80211_merge_extra_ies(const u8 *ies1, u16 ies1_len, + const u8 *ies2, u16 ies2_len, + u8 **merged_ies, u16 *merged_len) +{ + u8 *buf, *dpos; + const u8 *spos; + + if (ies1_len == 0 && ies2_len == 0) { + *merged_ies = NULL; + *merged_len = 0; + return 0; + } + + buf = kmalloc(ies1_len + ies2_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + memcpy(buf, ies1, ies1_len); + dpos = buf + ies1_len; + spos = ies2; + while (spos + 1 < ies2 + ies2_len) { + /* IE tag at offset 0, length at offset 1 */ + u16 ielen = 2 + spos[1]; + + if (spos + ielen > ies2 + ies2_len) + break; + if (spos[0] == WLAN_EID_VENDOR_SPECIFIC && + !_wil_cfg80211_find_ie(ies1, ies1_len, spos, ielen)) { + memcpy(dpos, spos, ielen); + dpos += ielen; + } + spos += ielen; + } + + *merged_ies = buf; + *merged_len = dpos - buf; + return 0; +} + static void wil_print_bcon_data(struct cfg80211_beacon_data *b) { print_hex_dump_bytes("head ", DUMP_PREFIX_OFFSET, @@ -712,49 +785,49 @@ static void wil_print_bcon_data(struct cfg80211_beacon_data *b) b->assocresp_ies, b->assocresp_ies_len); } -static int wil_fix_bcon(struct wil6210_priv *wil, - struct cfg80211_beacon_data *bcon) -{ - struct ieee80211_mgmt *f = (struct ieee80211_mgmt *)bcon->probe_resp; - size_t hlen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - - if (bcon->probe_resp_len <= hlen) - return 0; - -/* always use IE's from full probe frame, they has more info - * notable RSN - */ - bcon->proberesp_ies = f->u.probe_resp.variable; - bcon->proberesp_ies_len = bcon->probe_resp_len - hlen; - if (!bcon->assocresp_ies) { - bcon->assocresp_ies = bcon->proberesp_ies; - bcon->assocresp_ies_len = bcon->proberesp_ies_len; - } - - return 1; -} - /* internal functions for device reset and starting AP */ static int _wil_cfg80211_set_ies(struct wiphy *wiphy, struct cfg80211_beacon_data *bcon) { int rc; struct wil6210_priv *wil = wiphy_to_wil(wiphy); + u16 len = 0, proberesp_len = 0; + u8 *ies = NULL, *proberesp = NULL; + + if (bcon->probe_resp) { + struct ieee80211_mgmt *f = + (struct ieee80211_mgmt *)bcon->probe_resp; + size_t hlen = offsetof(struct ieee80211_mgmt, + u.probe_resp.variable); + proberesp = f->u.probe_resp.variable; + proberesp_len = bcon->probe_resp_len - hlen; + } + rc = _wil_cfg80211_merge_extra_ies(proberesp, + proberesp_len, + bcon->proberesp_ies, + bcon->proberesp_ies_len, + &ies, &len); - rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len, - bcon->proberesp_ies); if (rc) - return rc; + goto out; - rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len, - bcon->assocresp_ies); + rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, len, ies); + if (rc) + goto out; + + if (bcon->assocresp_ies) + rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, + bcon->assocresp_ies_len, bcon->assocresp_ies); + else + rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, len, ies); #if 0 /* to use beacon IE's, remove this #if 0 */ if (rc) - return rc; + goto out; rc = wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->tail_len, bcon->tail); #endif - +out: + kfree(ies); return rc; } @@ -823,11 +896,6 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy, wil_dbg_misc(wil, "%s()\n", __func__); wil_print_bcon_data(bcon); - if (wil_fix_bcon(wil, bcon)) { - wil_dbg_misc(wil, "Fixed bcon\n"); - wil_print_bcon_data(bcon); - } - if (bcon->tail && cfg80211_find_ie(WLAN_EID_RSN, bcon->tail, bcon->tail_len)) @@ -900,11 +968,6 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, wil_print_bcon_data(bcon); wil_print_crypto(wil, crypto); - if (wil_fix_bcon(wil, bcon)) { - wil_dbg_misc(wil, "Fixed bcon\n"); - wil_print_bcon_data(bcon); - } - rc = _wil_cfg80211_start_ap(wiphy, ndev, info->ssid, info->ssid_len, info->privacy, info->beacon_interval, channel->hw_value, -- cgit v1.2.3 From 640751ac30b2ddfbe06ad712aa7d57a8d89a7eef Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Sun, 17 Jan 2016 12:39:08 +0200 Subject: wil6210: handle tx completions only if vring tx data is enabled wil_vring_fini_tx is called in disconnect in order to free the allocated vrings. wil_vring_fini_tx is disabling the vring_tx_data before napi_synchronize is called in order to avoid the tx handling of this vring, while wil_vring_free is called only after napi finished the current handling of the tx completed packets. Due to that, in case of disconnect, wil6210_netdev_poll_tx can be called when vring->va is not NULL but vring_tx_data[i]->enabled is already disabled. This patch checks vring_tx_data[i]->enabled in wil6210_netdev_poll_tx to prevent handling of disabled vrings. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/netdev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 56aaa2d4fb0e..ecc3c1bdae4b 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -108,8 +108,9 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget) /* always process ALL Tx complete, regardless budget - it is fast */ for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { struct vring *vring = &wil->vring_tx[i]; + struct vring_tx_data *txdata = &wil->vring_tx_data[i]; - if (!vring->va) + if (!vring->va || !txdata->enabled) continue; tx_done += wil_tx_complete(wil, i); -- cgit v1.2.3 From b729aaf066b013458e95cd6c69a5e371eb9ce355 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Sun, 17 Jan 2016 12:39:09 +0200 Subject: wil6210: find TX vring only if vring_tx_data is enabled In TX vring allocation, vring_tx->va is allocated before WMI command to configure the vring is sent to the device. As the WMI command can take time to complete, it can lead to scenarios where vring_tx->va is not NULL but vring is still not enabled. This patch adds a check that vring_tx_data is enabled before returning a valid TX vring. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/txrx.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 7887e6cfd817..c22ee8b3ed9b 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -911,10 +911,11 @@ static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, continue; if (wil->vring2cid_tid[i][0] == cid) { struct vring *v = &wil->vring_tx[i]; + struct vring_tx_data *txdata = &wil->vring_tx_data[i]; wil_dbg_txrx(wil, "%s(%pM) -> [%d]\n", __func__, eth->h_dest, i); - if (v->va) { + if (v->va && txdata->enabled) { return v; } else { wil_dbg_txrx(wil, "vring[%d] not valid\n", i); @@ -935,6 +936,7 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, struct vring *v; int i; u8 cid; + struct vring_tx_data *txdata; /* In the STA mode, it is expected to have only 1 VRING * for the AP we connected to. @@ -942,7 +944,8 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, */ for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { v = &wil->vring_tx[i]; - if (!v->va) + txdata = &wil->vring_tx_data[i]; + if (!v->va || !txdata->enabled) continue; cid = wil->vring2cid_tid[i][0]; @@ -978,12 +981,14 @@ static struct vring *wil_find_tx_bcast_1(struct wil6210_priv *wil, struct sk_buff *skb) { struct vring *v; + struct vring_tx_data *txdata; int i = wil->bcast_vring; if (i < 0) return NULL; v = &wil->vring_tx[i]; - if (!v->va) + txdata = &wil->vring_tx_data[i]; + if (!v->va || !txdata->enabled) return NULL; if (!wil->vring_tx_data[i].dot1x_open && (skb->protocol != cpu_to_be16(ETH_P_PAE))) @@ -1010,11 +1015,13 @@ static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil, u8 cid; struct ethhdr *eth = (void *)skb->data; char *src = eth->h_source; + struct vring_tx_data *txdata; /* find 1-st vring eligible for data */ for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { v = &wil->vring_tx[i]; - if (!v->va) + txdata = &wil->vring_tx_data[i]; + if (!v->va || !txdata->enabled) continue; cid = wil->vring2cid_tid[i][0]; -- cgit v1.2.3 From 0916d9f2b6bea53a830ae5061b63a515c04da62e Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Sun, 17 Jan 2016 12:39:10 +0200 Subject: wil6210: handle multiple connect/disconnect events In the current solution wil6210 configures the vring in a worker and holds only one pending CID. This implementation may lead to race conditions between connect and disconnect events of multiple stations or fast connect/disconnect events of the same station. In order to allow the removal of the connect worker and handling of WMI_VRING_CFG_DONE_EVENTID in the connect event, the WMI replies that provide the reply in a given buffer needs to be handled immediately in the WMI event interrupt thread. To prevent deadlocks, WMI replies that requires additional handling are still handled via the events list. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/main.c | 81 +++++++-------- drivers/net/wireless/ath/wil6210/txrx.c | 3 + drivers/net/wireless/ath/wil6210/wil6210.h | 8 +- drivers/net/wireless/ath/wil6210/wmi.c | 157 +++++++++++++++++++++-------- 4 files changed, 156 insertions(+), 93 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index b39f0bfc591e..0652efed6b5d 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -155,7 +155,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) if (sta->status != wil_sta_unused) { if (!from_event) - wmi_disconnect_sta(wil, sta->addr, reason_code); + wmi_disconnect_sta(wil, sta->addr, reason_code, true); switch (wdev->iftype) { case NL80211_IFTYPE_AP: @@ -195,8 +195,8 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, struct wireless_dev *wdev = wil->wdev; might_sleep(); - wil_dbg_misc(wil, "%s(bssid=%pM, reason=%d, ev%s)\n", __func__, bssid, - reason_code, from_event ? "+" : "-"); + wil_info(wil, "%s(bssid=%pM, reason=%d, ev%s)\n", __func__, bssid, + reason_code, from_event ? "+" : "-"); /* Cases are: * - disconnect single STA, still connected @@ -258,13 +258,16 @@ static void wil_disconnect_worker(struct work_struct *work) static void wil_connect_timer_fn(ulong x) { struct wil6210_priv *wil = (void *)x; + bool q; - wil_dbg_misc(wil, "Connect timeout\n"); + wil_err(wil, "Connect timeout detected, disconnect station\n"); /* reschedule to thread context - disconnect won't - * run from atomic context + * run from atomic context. + * queue on wmi_wq to prevent race with connect event. */ - schedule_work(&wil->disconnect_worker); + q = queue_work(wil->wmi_wq, &wil->disconnect_worker); + wil_dbg_wmi(wil, "queue_work of disconnect_worker -> %d\n", q); } static void wil_scan_timer_fn(ulong x) @@ -369,6 +372,32 @@ static int wil_find_free_vring(struct wil6210_priv *wil) return -EINVAL; } +int wil_tx_init(struct wil6210_priv *wil, int cid) +{ + int rc = -EINVAL, ringid; + + if (cid < 0) { + wil_err(wil, "No connection pending\n"); + goto out; + } + ringid = wil_find_free_vring(wil); + if (ringid < 0) { + wil_err(wil, "No free vring found\n"); + goto out; + } + + wil_dbg_wmi(wil, "Configure for connection CID %d vring %d\n", + cid, ringid); + + rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0); + if (rc) + wil_err(wil, "wil_vring_init_tx for CID %d vring %d failed\n", + cid, ringid); + +out: + return rc; +} + int wil_bcast_init(struct wil6210_priv *wil) { int ri = wil->bcast_vring, rc; @@ -399,41 +428,6 @@ void wil_bcast_fini(struct wil6210_priv *wil) wil_vring_fini_tx(wil, ri); } -static void wil_connect_worker(struct work_struct *work) -{ - int rc, cid, ringid; - struct wil6210_priv *wil = container_of(work, struct wil6210_priv, - connect_worker); - struct net_device *ndev = wil_to_ndev(wil); - - mutex_lock(&wil->mutex); - - cid = wil->pending_connect_cid; - if (cid < 0) { - wil_err(wil, "No connection pending\n"); - goto out; - } - ringid = wil_find_free_vring(wil); - if (ringid < 0) { - wil_err(wil, "No free vring found\n"); - goto out; - } - - wil_dbg_wmi(wil, "Configure for connection CID %d vring %d\n", - cid, ringid); - - rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0); - wil->pending_connect_cid = -1; - if (rc == 0) { - wil->sta[cid].status = wil_sta_connected; - netif_tx_wake_all_queues(ndev); - } else { - wil_disconnect_cid(wil, cid, WLAN_REASON_UNSPECIFIED, true); - } -out: - mutex_unlock(&wil->mutex); -} - int wil_priv_init(struct wil6210_priv *wil) { uint i; @@ -453,12 +447,10 @@ int wil_priv_init(struct wil6210_priv *wil) init_completion(&wil->wmi_ready); init_completion(&wil->wmi_call); - wil->pending_connect_cid = -1; wil->bcast_vring = -1; setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); setup_timer(&wil->scan_timer, wil_scan_timer_fn, (ulong)wil); - INIT_WORK(&wil->connect_worker, wil_connect_worker); INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); @@ -844,7 +836,6 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) } /* init after reset */ - wil->pending_connect_cid = -1; wil->ap_isolate = 0; reinit_completion(&wil->wmi_ready); reinit_completion(&wil->wmi_call); diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index c22ee8b3ed9b..9680b970b863 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -794,6 +794,9 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, txdata->dot1x_open = false; txdata->enabled = 0; wil_vring_free(wil, vring, 1); + wil->vring2cid_tid[id][0] = WIL6210_MAX_CID; + wil->vring2cid_tid[id][1] = 0; + out: return rc; diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 235e205ce2bc..1b8fa1d2bae9 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -581,12 +581,10 @@ struct wil6210_priv { struct workqueue_struct *wmi_wq; /* for deferred calls */ struct work_struct wmi_event_worker; struct workqueue_struct *wq_service; - struct work_struct connect_worker; struct work_struct disconnect_worker; struct work_struct fw_error_worker; /* for FW error recovery */ struct timer_list connect_timer; struct timer_list scan_timer; /* detect scan timeout */ - int pending_connect_cid; struct list_head pending_wmi_ev; /* * protect pending_wmi_ev @@ -756,7 +754,8 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring); int wmi_p2p_cfg(struct wil6210_priv *wil, int channel); int wmi_rxon(struct wil6210_priv *wil, bool on); int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); -int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason); +int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, + bool full_disconnect); int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout); int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason); int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason); @@ -807,6 +806,7 @@ void wil_rx_fini(struct wil6210_priv *wil); int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, int cid, int tid); void wil_vring_fini_tx(struct wil6210_priv *wil, int id); +int wil_tx_init(struct wil6210_priv *wil, int cid); int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size); int wil_bcast_init(struct wil6210_priv *wil); void wil_bcast_fini(struct wil6210_priv *wil); diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index e3ea74cdd4aa..e1a6cb8840ed 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -426,6 +426,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) const size_t assoc_req_ie_offset = sizeof(u16) * 2; /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */ const size_t assoc_resp_ie_offset = sizeof(u16) * 3; + int rc; if (len < sizeof(*evt)) { wil_err(wil, "Connect event too short : %d bytes\n", len); @@ -445,8 +446,8 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) } ch = evt->channel + 1; - wil_dbg_wmi(wil, "Connect %pM channel [%d] cid %d\n", - evt->bssid, ch, evt->cid); + wil_info(wil, "Connect %pM channel [%d] cid %d\n", + evt->bssid, ch, evt->cid); wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1, evt->assoc_info, len - sizeof(*evt), true); @@ -468,20 +469,67 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) assoc_resp_ielen = 0; } + mutex_lock(&wil->mutex); + if (test_bit(wil_status_resetting, wil->status) || + !test_bit(wil_status_fwready, wil->status)) { + wil_err(wil, "status_resetting, cancel connect event, CID %d\n", + evt->cid); + mutex_unlock(&wil->mutex); + /* no need for cleanup, wil_reset will do that */ + return; + } + if ((wdev->iftype == NL80211_IFTYPE_STATION) || (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { if (!test_bit(wil_status_fwconnecting, wil->status)) { wil_err(wil, "Not in connecting state\n"); + mutex_unlock(&wil->mutex); return; } del_timer_sync(&wil->connect_timer); - cfg80211_connect_result(ndev, evt->bssid, - assoc_req_ie, assoc_req_ielen, - assoc_resp_ie, assoc_resp_ielen, - WLAN_STATUS_SUCCESS, GFP_KERNEL); + } + + /* FIXME FW can transmit only ucast frames to peer */ + /* FIXME real ring_id instead of hard coded 0 */ + ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid); + wil->sta[evt->cid].status = wil_sta_conn_pending; + rc = wil_tx_init(wil, evt->cid); + if (rc) { + wil_err(wil, "%s: config tx vring failed for CID %d, rc (%d)\n", + __func__, evt->cid, rc); + wmi_disconnect_sta(wil, wil->sta[evt->cid].addr, + WLAN_REASON_UNSPECIFIED, false); + } else { + wil_info(wil, "%s: successful connection to CID %d\n", + __func__, evt->cid); + } + + if ((wdev->iftype == NL80211_IFTYPE_STATION) || + (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { + if (rc) { + netif_tx_stop_all_queues(ndev); + netif_carrier_off(ndev); + wil_err(wil, + "%s: cfg80211_connect_result with failure\n", + __func__); + cfg80211_connect_result(ndev, evt->bssid, NULL, 0, + NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + goto out; + } else { + cfg80211_connect_result(ndev, evt->bssid, + assoc_req_ie, assoc_req_ielen, + assoc_resp_ie, assoc_resp_ielen, + WLAN_STATUS_SUCCESS, + GFP_KERNEL); + } } else if ((wdev->iftype == NL80211_IFTYPE_AP) || (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { + if (rc) + goto out; + memset(&sinfo, 0, sizeof(sinfo)); sinfo.generation = wil->sinfo_gen++; @@ -492,17 +540,21 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) } cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL); + } else { + wil_err(wil, "%s: unhandled iftype %d for CID %d\n", + __func__, wdev->iftype, evt->cid); + goto out; } - clear_bit(wil_status_fwconnecting, wil->status); - set_bit(wil_status_fwconnected, wil->status); - /* FIXME FW can transmit only ucast frames to peer */ - /* FIXME real ring_id instead of hard coded 0 */ - ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid); - wil->sta[evt->cid].status = wil_sta_conn_pending; + wil->sta[evt->cid].status = wil_sta_connected; + set_bit(wil_status_fwconnected, wil->status); + netif_tx_wake_all_queues(ndev); - wil->pending_connect_cid = evt->cid; - queue_work(wil->wq_service, &wil->connect_worker); +out: + if (rc) + wil->sta[evt->cid].status = wil_sta_unused; + clear_bit(wil_status_fwconnecting, wil->status); + mutex_unlock(&wil->mutex); } static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, @@ -511,8 +563,8 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, struct wmi_disconnect_event *evt = d; u16 reason_code = le16_to_cpu(evt->protocol_reason_status); - wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n", - evt->bssid, reason_code, evt->disconnect_reason); + wil_info(wil, "Disconnect %pM reason [proto %d wmi %d]\n", + evt->bssid, reason_code, evt->disconnect_reason); wil->sinfo_gen++; @@ -727,6 +779,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) void __iomem *src; ulong flags; unsigned n; + unsigned int num_immed_reply = 0; if (!test_bit(wil_status_mbox_ready, wil->status)) { wil_err(wil, "Reset in progress. Cannot handle WMI event\n"); @@ -736,6 +789,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) for (n = 0;; n++) { u16 len; bool q; + bool immed_reply = false; r->head = wil_r(wil, RGF_MBOX + offsetof(struct wil6210_mbox_ctl, rx.head)); @@ -784,6 +838,13 @@ void wmi_recv_cmd(struct wil6210_priv *wil) struct wil6210_mbox_hdr_wmi *wmi = &evt->event.wmi; u16 id = le16_to_cpu(wmi->id); u32 tstamp = le32_to_cpu(wmi->timestamp); + if (wil->reply_id && wil->reply_id == id) { + if (wil->reply_buf) { + memcpy(wil->reply_buf, wmi, + min(len, wil->reply_size)); + immed_reply = true; + } + } wil_dbg_wmi(wil, "WMI event 0x%04x MID %d @%d msec\n", id, wmi->mid, tstamp); @@ -799,15 +860,24 @@ void wmi_recv_cmd(struct wil6210_priv *wil) wil_w(wil, RGF_MBOX + offsetof(struct wil6210_mbox_ctl, rx.tail), r->tail); - /* add to the pending list */ - spin_lock_irqsave(&wil->wmi_ev_lock, flags); - list_add_tail(&evt->list, &wil->pending_wmi_ev); - spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); - q = queue_work(wil->wmi_wq, &wil->wmi_event_worker); - wil_dbg_wmi(wil, "queue_work -> %d\n", q); + if (immed_reply) { + wil_dbg_wmi(wil, "%s: Complete WMI 0x%04x\n", + __func__, wil->reply_id); + kfree(evt); + num_immed_reply++; + complete(&wil->wmi_call); + } else { + /* add to the pending list */ + spin_lock_irqsave(&wil->wmi_ev_lock, flags); + list_add_tail(&evt->list, &wil->pending_wmi_ev); + spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); + q = queue_work(wil->wmi_wq, &wil->wmi_event_worker); + wil_dbg_wmi(wil, "queue_work -> %d\n", q); + } } /* normally, 1 event per IRQ should be processed */ - wil_dbg_wmi(wil, "%s -> %d events queued\n", __func__, n); + wil_dbg_wmi(wil, "%s -> %d events queued, %d completed\n", __func__, + n - num_immed_reply, num_immed_reply); } int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, @@ -1184,7 +1254,8 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) return 0; } -int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason) +int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, + bool full_disconnect) { int rc; u16 reason_code; @@ -1208,19 +1279,20 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason) return rc; } - /* call event handler manually after processing wmi_call, - * to avoid deadlock - disconnect event handler acquires wil->mutex - * while it is already held here - */ - reason_code = le16_to_cpu(reply.evt.protocol_reason_status); - - wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n", - reply.evt.bssid, reason_code, - reply.evt.disconnect_reason); + if (full_disconnect) { + /* call event handler manually after processing wmi_call, + * to avoid deadlock - disconnect event handler acquires + * wil->mutex while it is already held here + */ + reason_code = le16_to_cpu(reply.evt.protocol_reason_status); - wil->sinfo_gen++; - wil6210_disconnect(wil, reply.evt.bssid, reason_code, true); + wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n", + reply.evt.bssid, reason_code, + reply.evt.disconnect_reason); + wil->sinfo_gen++; + wil6210_disconnect(wil, reply.evt.bssid, reason_code, true); + } return 0; } @@ -1348,14 +1420,11 @@ static void wmi_event_handle(struct wil6210_priv *wil, id, wil->reply_id); /* check if someone waits for this event */ if (wil->reply_id && wil->reply_id == id) { - if (wil->reply_buf) { - memcpy(wil->reply_buf, wmi, - min(len, wil->reply_size)); - } else { - wmi_evt_call_handler(wil, id, evt_data, - len - sizeof(*wmi)); - } - wil_dbg_wmi(wil, "Complete WMI 0x%04x\n", id); + WARN_ON(wil->reply_buf); + wmi_evt_call_handler(wil, id, evt_data, + len - sizeof(*wmi)); + wil_dbg_wmi(wil, "%s: Complete WMI 0x%04x\n", + __func__, id); complete(&wil->wmi_call); return; } -- cgit v1.2.3 From 424aecaa797901708e7f260b642d27b077cdb491 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 14 Jan 2016 03:15:13 +0100 Subject: ath9k_hw: add low power tx gain table for AR953x Used in some newer TP-Link AR9533 devices. Signed-off-by: Felix Fietkau Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 3 ++ drivers/net/wireless/ath/ath9k/ar953x_initvals.h | 65 ++++++++++++++++++++++++ 2 files changed, 68 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 8b238c15916d..2fe12b0de5b4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -698,6 +698,9 @@ static void ar9003_tx_gain_table_mode2(struct ath_hw *ah) else if (AR_SREV_9340(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9340Modes_low_ob_db_tx_gain_table_1p0); + else if (AR_SREV_9531_11(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + qca953x_1p1_modes_no_xpa_low_power_tx_gain_table); else if (AR_SREV_9485_11_OR_LATER(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9485Modes_low_ob_db_tx_gain_1_1); diff --git a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h index 6fc0d07e5ec6..c0b90daa3e3d 100644 --- a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h @@ -757,6 +757,71 @@ static const u32 qca953x_1p1_modes_xpa_tx_gain_table[][2] = { {0x00016448, 0x6c927a70}, }; +static const u32 qca953x_1p1_modes_no_xpa_low_power_tx_gain_table[][2] = { + /* Addr allmodes */ + {0x0000a2dc, 0xfff55592}, + {0x0000a2e0, 0xfff99924}, + {0x0000a2e4, 0xfffe1e00}, + {0x0000a2e8, 0xffffe000}, + {0x0000a410, 0x000050d6}, + {0x0000a500, 0x00000069}, + {0x0000a504, 0x0400006b}, + {0x0000a508, 0x0800006d}, + {0x0000a50c, 0x0c000269}, + {0x0000a510, 0x1000026b}, + {0x0000a514, 0x1400026d}, + {0x0000a518, 0x18000669}, + {0x0000a51c, 0x1c00066b}, + {0x0000a520, 0x1d000a68}, + {0x0000a524, 0x21000a6a}, + {0x0000a528, 0x25000a6c}, + {0x0000a52c, 0x29000a6e}, + {0x0000a530, 0x2d0012a9}, + {0x0000a534, 0x310012ab}, + {0x0000a538, 0x350012ad}, + {0x0000a53c, 0x39001b0a}, + {0x0000a540, 0x3d001b0c}, + {0x0000a544, 0x41001b0e}, + {0x0000a548, 0x43001bae}, + {0x0000a54c, 0x45001914}, + {0x0000a550, 0x47001916}, + {0x0000a554, 0x49001b96}, + {0x0000a558, 0x49001b96}, + {0x0000a55c, 0x49001b96}, + {0x0000a560, 0x49001b96}, + {0x0000a564, 0x49001b96}, + {0x0000a568, 0x49001b96}, + {0x0000a56c, 0x49001b96}, + {0x0000a570, 0x49001b96}, + {0x0000a574, 0x49001b96}, + {0x0000a578, 0x49001b96}, + {0x0000a57c, 0x49001b96}, + {0x0000a600, 0x00000000}, + {0x0000a604, 0x00000000}, + {0x0000a608, 0x00000000}, + {0x0000a60c, 0x00000000}, + {0x0000a610, 0x00000000}, + {0x0000a614, 0x00000000}, + {0x0000a618, 0x00804201}, + {0x0000a61c, 0x01408201}, + {0x0000a620, 0x01408502}, + {0x0000a624, 0x01408502}, + {0x0000a628, 0x01408502}, + {0x0000a62c, 0x01408502}, + {0x0000a630, 0x01408502}, + {0x0000a634, 0x01408502}, + {0x0000a638, 0x01408502}, + {0x0000a63c, 0x01408502}, + {0x0000b2dc, 0xfff55592}, + {0x0000b2e0, 0xfff99924}, + {0x0000b2e4, 0xfffe1e00}, + {0x0000b2e8, 0xffffe000}, + {0x00016044, 0x044922db}, + {0x00016048, 0x6c927a70}, + {0x00016444, 0x044922db}, + {0x00016448, 0x6c927a70}, +}; + static const u32 qca953x_2p0_baseband_core[][2] = { /* Addr allmodes */ {0x00009800, 0xafe68e30}, -- cgit v1.2.3 From 344cd850b55e9dfd4f3ec1ba564f8edbc8136aca Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 15 Jan 2016 14:41:30 +0100 Subject: ath9k: Drop useless const on chanctx_event_delta() return type drivers/net/wireless/ath/ath9k/channel.c:230: warning: type qualifiers ignored on function return type Signed-off-by: Geert Uytterhoeven Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/channel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 0bcb82abd094..319cb5f25f58 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -226,7 +226,7 @@ static const char *chanctx_state_string(enum ath_chanctx_state state) } } -static const u32 chanctx_event_delta(struct ath_softc *sc) +static u32 chanctx_event_delta(struct ath_softc *sc) { u64 ms; struct timespec ts, *old; -- cgit v1.2.3 From c1cab1df9b651d999922e0f04d01dc046121a237 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 18 Jan 2016 09:33:46 +0800 Subject: ath9k: avoid ANI restart if no trigger Fixes commit 54da20d83f0e ("ath9k_hw: improve ANI processing and rx desensitizing parameters") Call ath9k_ani_restart() only when the phy error rate reach the ANI immunity threshold. Sync the logic with internal code base. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ani.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 25e45e4d1a60..aa82e1326fff 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -450,7 +450,9 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) } else if (cckPhyErrRate > ah->config.cck_trig_high) { ath9k_hw_ani_cck_err_trigger(ah); aniState->ofdmsTurn = true; - } + } else + return; + ath9k_ani_restart(ah); } } -- cgit v1.2.3 From 66b533d5adb3eb0cd111b07e516ab13a47ed34f5 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 18 Jan 2016 09:33:47 +0800 Subject: ath9k: clean up ANI per-channel pointer checking commit c24bd3620c50 ("ath9k: Do not maintain ANI state per-channel") removed per-channel handling, the code to check 'curchan' also should be removed as never used. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ani.c | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index aa82e1326fff..815efe9fd208 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -126,12 +126,8 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah, static void ath9k_ani_restart(struct ath_hw *ah) { - struct ar5416AniState *aniState; - - if (!ah->curchan) - return; + struct ar5416AniState *aniState = &ah->ani; - aniState = &ah->ani; aniState->listenTime = 0; ENABLE_REGWRITE_BUFFER(ah); @@ -221,12 +217,7 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel, static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) { - struct ar5416AniState *aniState; - - if (!ah->curchan) - return; - - aniState = &ah->ani; + struct ar5416AniState *aniState = &ah->ani; if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1, false); @@ -281,12 +272,7 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel, static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) { - struct ar5416AniState *aniState; - - if (!ah->curchan) - return; - - aniState = &ah->ani; + struct ar5416AniState *aniState = &ah->ani; if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1, @@ -299,9 +285,7 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) */ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) { - struct ar5416AniState *aniState; - - aniState = &ah->ani; + struct ar5416AniState *aniState = &ah->ani; /* lower OFDM noise immunity */ if (aniState->ofdmNoiseImmunityLevel > 0 && @@ -329,7 +313,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) struct ath_common *common = ath9k_hw_common(ah); int ofdm_nil, cck_nil; - if (!ah->curchan) + if (!chan) return; BUG_ON(aniState == NULL); @@ -416,14 +400,10 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah) void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) { - struct ar5416AniState *aniState; + struct ar5416AniState *aniState = &ah->ani; struct ath_common *common = ath9k_hw_common(ah); u32 ofdmPhyErrRate, cckPhyErrRate; - if (!ah->curchan) - return; - - aniState = &ah->ani; if (!ath9k_hw_ani_read_counters(ah)) return; -- cgit v1.2.3 From 3f6cc4e57d304f552abc2bdba716519c5e18b442 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 18 Jan 2016 09:33:48 +0800 Subject: ath9k: do not reset while BB panic(0x4000409) on ar9561 BB panic(0x4000409) observed while AP enabling/disabling bursting. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 201425e7f9cb..abd964691d8c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -2071,7 +2071,8 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) * to be disabled. * * 0x04000409: Packet stuck on receive. - * Full chip reset is required for all chips except AR9340. + * Full chip reset is required for all chips except + * AR9340, AR9531 and AR9561. */ /* @@ -2100,7 +2101,7 @@ bool ar9003_hw_bb_watchdog_check(struct ath_hw *ah) case 0x04000b09: return true; case 0x04000409: - if (AR_SREV_9340(ah) || AR_SREV_9531(ah)) + if (AR_SREV_9340(ah) || AR_SREV_9531(ah) || AR_SREV_9561(ah)) return false; else return true; -- cgit v1.2.3 From 1542bc37842d5d51e4aa71286a08be9615eba884 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 18 Jan 2016 09:33:49 +0800 Subject: ath9k: fix inconsistent use of tab and space in indentation Minor changes for indenting. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 8b4561e8ce1a..54ed2f72d35e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -5485,11 +5485,11 @@ unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah, AR9300_PAPRD_SCALE_1); else { if (chan->channel >= 5700) - return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20), - AR9300_PAPRD_SCALE_1); + return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20), + AR9300_PAPRD_SCALE_1); else if (chan->channel >= 5400) return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40), - AR9300_PAPRD_SCALE_2); + AR9300_PAPRD_SCALE_2); else return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40), AR9300_PAPRD_SCALE_1); -- cgit v1.2.3 From 466b0f0208508b08eb59907fac0958d6da7fa3e2 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 18 Jan 2016 09:33:50 +0800 Subject: ath9k: fix data bus error on ar9300 and ar9580 One crash issue be found on ar9300: RTC_RC reg read leads crash, leading the data bus error, due to RTC_RC reg write not happen properly. Warm Reset trigger in continuous beacon stuck for one of the customer for other chip, noticed the MAC was stuck in RTC reset. After analysis noticed DMA did not complete when RTC was put in reset. So, before resetting the MAC need to make sure there are no pending DMA transactions because this reset does not reset all parts of the chip. The 12th and 11th bit of MAC _DMA_CFG register used to do that. 12 cfg_halt_ack 0x0 0 DMA has not yet halted 1 DMA has halted 11 cfg_halt_req 0x0 0 DMA logic operates normally 1 Request DMA logic to stop so software can reset the MAC The Bit [12] of this register indicates when the halt has taken effect or not. the DMA halt IS NOT recoverable; once software sets bit [11] to request a DMA halt, software must wait for bit [12] to be set and reset the MAC. So, the same thing we implemented for ar9580 chip. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/hw.c | 10 ++++++++++ drivers/net/wireless/ath/ath9k/reg.h | 4 +++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 257f46ed4a04..e7a31016f370 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1368,6 +1368,16 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) if (ath9k_hw_mci_is_enabled(ah)) ar9003_mci_check_gpm_offset(ah); + /* DMA HALT added to resolve ar9300 and ar9580 bus error during + * RTC_RC reg read + */ + if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) { + REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); + ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK, + 20 * AH_WAIT_TIMEOUT); + REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); + } + REG_WRITE(ah, AR_RTC_RC, rst_flags); REGWRITE_BUFFER_FLUSH(ah); diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index caba54ddad25..c8d35febaf0f 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -34,8 +34,10 @@ #define AR_CFG_SWRG 0x00000010 #define AR_CFG_AP_ADHOC_INDICATION 0x00000020 #define AR_CFG_PHOK 0x00000100 -#define AR_CFG_CLK_GATE_DIS 0x00000400 #define AR_CFG_EEBS 0x00000200 +#define AR_CFG_CLK_GATE_DIS 0x00000400 +#define AR_CFG_HALT_REQ 0x00000800 +#define AR_CFG_HALT_ACK 0x00001000 #define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000 #define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17 -- cgit v1.2.3 From eb249a11913d316fc1a27dd07a1e1e43bda9199d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 16:58:08 +0100 Subject: irqchip/s3c24xx: Mark init_eint as __maybe_unused The init_eint array in the s3c24xx irqchip driver is used by every individual chip variant, but Kconfig allows building the driver when they are all disabled, and that leads to a harmless compile-time warning: drivers/irqchip/irq-s3c24xx.c:608:28: error: 'init_eint' defined but not used [-Werror=unused-variable] This marks the array as __maybe_unused to avoid the warning. Signed-off-by: Arnd Bergmann Acked-by: Marc Zyngier Cc: linux-arm-kernel@lists.infradead.org Cc: Jason Cooper Link: http://lkml.kernel.org/r/1453737499-1960073-1-git-send-email-arnd@arndb.de Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-s3c24xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-s3c24xx.c b/drivers/irqchip/irq-s3c24xx.c index c71914e8f596..5dc5a760c723 100644 --- a/drivers/irqchip/irq-s3c24xx.c +++ b/drivers/irqchip/irq-s3c24xx.c @@ -605,7 +605,7 @@ err: return ERR_PTR(ret); } -static struct s3c_irq_data init_eint[32] = { +static struct s3c_irq_data __maybe_unused init_eint[32] = { { .type = S3C_IRQTYPE_NONE, }, /* reserved */ { .type = S3C_IRQTYPE_NONE, }, /* reserved */ { .type = S3C_IRQTYPE_NONE, }, /* reserved */ -- cgit v1.2.3 From 0df337cf92c107fb515c9df6907052a97bd484b9 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 25 Jan 2016 23:24:17 +0100 Subject: irqchip: Fix dependencies for archs w/o HAS_IOMEM Not every arch has io memory. So, unbreak the build by fixing the dependencies. Signed-off-by: Richard Weinberger Cc: user-mode-linux-devel@lists.sourceforge.net Cc: Jason Cooper Cc: Marc Zyngier Link: http://lkml.kernel.org/r/1453760661-1444-19-git-send-email-richard@nod.at Signed-off-by: Thomas Gleixner --- drivers/irqchip/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 11fc2a27fa2e..90ab59107830 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -154,6 +154,7 @@ config TB10X_IRQC config TS4800_IRQ tristate "TS-4800 IRQ controller" select IRQ_DOMAIN + depends on HAS_IOMEM help Support for the TS-4800 FPGA IRQ controller -- cgit v1.2.3 From 14a0db3cdd114da757197193f66786e63649c91e Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 26 Jan 2016 13:52:26 +0000 Subject: of: MSI: Simplify irqdomain lookup So far, when trying to associate a device with its MSI domain, we first lookup the domain using a MSI token, and if this doesn't return anything useful, we pick up any domain matching the same node. This logic is broken for two reasons: 1) Only the generic MSI code (PCI or platform) sets this token to PCI/MSI or platform MSI. So we're guaranteed that if there is something to be found, we will find it with the first call. 2) If we have a convoluted situation where: - a single node implements both wired and MSI interrupts - MSI support for that HW hasn't been compiled in we'll end up using the wired domain for MSIs anyway, and things break badly. So let's just remove __of_get_msi_domain, and replace it by a direct call to irq_find_matching_host, because that's what we really want. Signed-off-by: Marc Zyngier Acked-by: Rob Herring Cc: Greg Kroah-Hartman Cc: Frank Rowand Cc: Grant Likely Cc: Thomas Petazzoni Cc: Jiang Liu Link: http://lkml.kernel.org/r/1453816347-32720-3-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- drivers/of/irq.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 4fa916dffc91..a9ea5525109b 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -680,18 +680,6 @@ u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in) return __of_msi_map_rid(dev, &msi_np, rid_in); } -static struct irq_domain *__of_get_msi_domain(struct device_node *np, - enum irq_domain_bus_token token) -{ - struct irq_domain *d; - - d = irq_find_matching_host(np, token); - if (!d) - d = irq_find_host(np); - - return d; -} - /** * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain * @dev: device for which the mapping is to be done. @@ -707,7 +695,7 @@ struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 rid) struct device_node *np = NULL; __of_msi_map_rid(dev, &np, rid); - return __of_get_msi_domain(np, DOMAIN_BUS_PCI_MSI); + return irq_find_matching_host(np, DOMAIN_BUS_PCI_MSI); } /** @@ -731,7 +719,7 @@ struct irq_domain *of_msi_get_domain(struct device *dev, /* Check for a single msi-parent property */ msi_np = of_parse_phandle(np, "msi-parent", 0); if (msi_np && !of_property_read_bool(msi_np, "#msi-cells")) { - d = __of_get_msi_domain(msi_np, token); + d = irq_find_matching_host(msi_np, token); if (!d) of_node_put(msi_np); return d; @@ -745,7 +733,7 @@ struct irq_domain *of_msi_get_domain(struct device *dev, while (!of_parse_phandle_with_args(np, "msi-parent", "#msi-cells", index, &args)) { - d = __of_get_msi_domain(args.np, token); + d = irq_find_matching_host(args.np, token); if (d) return d; -- cgit v1.2.3 From 2be6d9bfef53d185975b44fd808aece36595e83e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 17:02:49 +0100 Subject: clocksource: Select CLKSRC_MMIO where needed The Tegra clocksource implementation uses the clocksource_mmio helper functions, but currently can be configured without them, which fails: drivers/clocksource/built-in.o: In function `tegra20_init_timer': :(.init.text+0xac): undefined reference to `clocksource_mmio_init' :(.init.text+0x140): undefined reference to `clocksource_mmio_readl_up' The same problem exists for Digicolor: drivers/clocksource/built-in.o: In function `digicolor_timer_init': :(.init.text+0xfa): undefined reference to `clocksource_mmio_init' :(.init.text+0x14c): undefined reference to `clocksource_mmio_readl_down' I've inspected the Kconfig file to look for other cases that I have not yet run into, and added an explicit 'select' to each one to ensure we can successfully link the drivers. Signed-off-by: Arnd Bergmann Cc: linux-arm-kernel@lists.infradead.org Cc: Daniel Lezcano Link: http://lkml.kernel.org/r/1453737776-1960372-1-git-send-email-arnd@arndb.de Signed-off-by: Thomas Gleixner --- drivers/clocksource/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 56777f04d2d9..f70b4f3b4857 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -30,6 +30,7 @@ config CLKSRC_MMIO config DIGICOLOR_TIMER bool "Digicolor timer driver" if COMPILE_TEST depends on GENERIC_CLOCKEVENTS + select CLKSRC_MMIO help Enables the support for the digicolor timer driver. @@ -55,6 +56,7 @@ config ARMADA_370_XP_TIMER bool "Armada 370 and XP timer driver" if COMPILE_TEST depends on ARM select CLKSRC_OF + select CLKSRC_MMIO help Enables the support for the Armada 370 and XP timer driver. @@ -89,6 +91,7 @@ config SUN5I_HSTIMER config TEGRA_TIMER bool "Tegra timer driver" if COMPILE_TEST + select CLKSRC_MMIO depends on ARM help Enables support for the Tegra driver. @@ -263,6 +266,7 @@ config FSL_FTM_TIMER config VF_PIT_TIMER bool + select CLKSRC_MMIO help Support for Period Interrupt Timer on Freescale Vybrid Family SoCs. @@ -394,6 +398,7 @@ config CLKSRC_ST_LPC bool "Low power clocksource found in the LPC" if COMPILE_TEST select CLKSRC_OF if OF depends on HAS_IOMEM + select CLKSRC_MMIO help Enable this option to use the Low Power controller timer as clocksource. -- cgit v1.2.3 From d7023e62c5128bf9f150d792a3ea8c758cb431a3 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 25 Jan 2016 23:24:19 +0100 Subject: clocksource: Fix dependencies for archs w/o HAS_IOMEM Not every arch has io memory. So, unbreak the build by fixing the dependencies. Signed-off-by: Richard Weinberger Cc: user-mode-linux-devel@lists.sourceforge.net Cc: Daniel Lezcano Link: http://lkml.kernel.org/r/1453760661-1444-21-git-send-email-richard@nod.at Signed-off-by: Thomas Gleixner --- drivers/clocksource/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index f70b4f3b4857..33db7406c0e2 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -31,6 +31,7 @@ config DIGICOLOR_TIMER bool "Digicolor timer driver" if COMPILE_TEST depends on GENERIC_CLOCKEVENTS select CLKSRC_MMIO + depends on HAS_IOMEM help Enables the support for the digicolor timer driver. @@ -78,6 +79,7 @@ config ORION_TIMER config SUN4I_TIMER bool "Sun4i timer driver" if COMPILE_TEST depends on GENERIC_CLOCKEVENTS + depends on HAS_IOMEM select CLKSRC_MMIO help Enables support for the Sun4i timer. @@ -99,6 +101,7 @@ config TEGRA_TIMER config VT8500_TIMER bool "VT8500 timer driver" if COMPILE_TEST depends on GENERIC_CLOCKEVENTS + depends on HAS_IOMEM help Enables support for the VT8500 driver. @@ -134,6 +137,7 @@ config CLKSRC_NOMADIK_MTU_SCHED_CLOCK config CLKSRC_DBX500_PRCMU bool "Clocksource PRCMU Timer" if COMPILE_TEST depends on GENERIC_CLOCKEVENTS + depends on HAS_IOMEM help Use the always on PRCMU Timer as clocksource @@ -251,6 +255,7 @@ config CLKSRC_EXYNOS_MCT config CLKSRC_SAMSUNG_PWM bool "PWM timer drvier for Samsung S3C, S5P" if COMPILE_TEST depends on GENERIC_CLOCKEVENTS + depends on HAS_IOMEM help This is a new clocksource driver for the PWM timer found in Samsung S3C, S5P and Exynos SoCs, replacing an earlier driver @@ -260,6 +265,7 @@ config CLKSRC_SAMSUNG_PWM config FSL_FTM_TIMER bool "Freescale FlexTimer Module driver" if COMPILE_TEST depends on GENERIC_CLOCKEVENTS + depends on HAS_IOMEM select CLKSRC_MMIO help Support for Freescale FlexTimer Module (FTM) timer. @@ -364,6 +370,7 @@ config CLKSRC_TANGO_XTAL config CLKSRC_PXA bool "Clocksource for PXA or SA-11x0 platform" if COMPILE_TEST depends on GENERIC_CLOCKEVENTS + depends on HAS_IOMEM select CLKSRC_MMIO help This enables OST0 support available on PXA and SA-11x0 -- cgit v1.2.3 From bb1a793125d9cc61f2d1cff92fe3927fec45d528 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 26 Jan 2016 13:52:27 +0000 Subject: base: Export platform_msi_domain_[alloc,free]_irqs The new function platform_msi_domain_{alloc,free}_irqs are meant to be used in platform drivers, which can be built as modules. Therefore, it makes sense to export them to be used from kernel modules. Signed-off-by: Thomas Petazzoni Acked-by: Marc Zyngier Cc: Greg Kroah-Hartman Cc: Rob Herring Cc: Frank Rowand Cc: Grant Likely Cc: Jiang Liu Link: http://lkml.kernel.org/r/1453816347-32720-4-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- drivers/base/platform-msi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c index 47c43386786b..279e53989374 100644 --- a/drivers/base/platform-msi.c +++ b/drivers/base/platform-msi.c @@ -284,6 +284,7 @@ out_free_priv_data: return err; } +EXPORT_SYMBOL_GPL(platform_msi_domain_alloc_irqs); /** * platform_msi_domain_free_irqs - Free MSI interrupts for @dev @@ -301,6 +302,7 @@ void platform_msi_domain_free_irqs(struct device *dev) msi_domain_free_irqs(dev->msi_domain, dev); platform_msi_free_descs(dev, 0, MAX_DEV_MSIS); } +EXPORT_SYMBOL_GPL(platform_msi_domain_free_irqs); /** * platform_msi_get_host_data - Query the private data associated with -- cgit v1.2.3 From 18aa60ce2751c95d3412ed06a58b8b6cfb6f88f2 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 26 Jan 2016 14:24:15 +0000 Subject: irqchip/gic-v3-its: Recompute the number of pages on page size change When the programming of a GITS_BASERn register fails because of an unsupported ITS page size, we retry it with a smaller page size. Unfortunately, we don't recompute the number of allocated ITS pages, indicating the wrong value computed in the original allocation. A convenient fix is to free the pages we allocated, update the page size, and restart the allocation. This will ensure that we always allocate the right amount in the case of a device table, specially if we have to reduce the allocation order to stay within the boundaries of the ITS maximum allocation. Reported-and-tested-by: Ma Jun Signed-off-by: Marc Zyngier Cc: linux-arm-kernel@lists.infradead.org Cc: Jason Cooper Link: http://lkml.kernel.org/r/1453818255-1289-1-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-gic-v3-its.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index e23d1d18f9d6..3447549fcc93 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -875,6 +875,7 @@ static int its_alloc_tables(const char *node_name, struct its_node *its) } alloc_size = (1 << order) * PAGE_SIZE; +retry_alloc_baser: alloc_pages = (alloc_size / psz); if (alloc_pages > GITS_BASER_PAGES_MAX) { alloc_pages = GITS_BASER_PAGES_MAX; @@ -938,13 +939,16 @@ retry_baser: * size and retry. If we reach 4K, then * something is horribly wrong... */ + free_pages((unsigned long)base, order); + its->tables[i] = NULL; + switch (psz) { case SZ_16K: psz = SZ_4K; - goto retry_baser; + goto retry_alloc_baser; case SZ_64K: psz = SZ_16K; - goto retry_baser; + goto retry_alloc_baser; } } -- cgit v1.2.3 From 25cad69f21f5532d99e2ee73c8ab6512bcab614c Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Mon, 30 Nov 2015 12:50:05 +0100 Subject: base/platform: Fix platform drivers with no probe callback Since b8b2c7d845d5, platform_drv_probe() is called for all platform devices. If drv->probe is NULL, and dev_pm_domain_attach() fails, platform_drv_probe() will return the error code from dev_pm_domain_attach(). This causes real_probe() to enter the "probe_failed" path and set dev->driver to NULL. Before b8b2c7d845d5, real_probe() would assume success if both dev->bus->probe and drv->probe were missing. As a result, a device and driver could be "bound" together just by matching their names; this doesn't work any more after b8b2c7d845d5. This may cause problems later for certain usage of platform_driver_register() and platform_device_register_simple(). I observed a panic while loading the tpm_tis driver with parameter "force=1" (i.e. registering tpm_tis as a platform driver), because tpm_tis_init's assumption that the device returned by platform_device_register_simple() was bound didn't hold any more (tpmm_chip_alloc() dereferences chip->pdev->driver, causing panic). This patch restores the previous (4.3.0 and earlier) behavior of platform_drv_probe() in the case when the associated platform driver has no "probe" function. Fixes: b8b2c7d845d5 ("base/platform: assert that dev_pm_domain callbacks are called unconditionally") Signed-off-by: Martin Wilck Cc: stable # 4.4 Cc: Martin Fuzzey Acked-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 73d6e5d39e33..f437afa17f2b 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -558,10 +558,15 @@ static int platform_drv_probe(struct device *_dev) return ret; ret = dev_pm_domain_attach(_dev, true); - if (ret != -EPROBE_DEFER && drv->probe) { - ret = drv->probe(dev); - if (ret) - dev_pm_domain_detach(_dev, true); + if (ret != -EPROBE_DEFER) { + if (drv->probe) { + ret = drv->probe(dev); + if (ret) + dev_pm_domain_detach(_dev, true); + } else { + /* don't fail if just dev_pm_domain_attach failed */ + ret = 0; + } } if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) { -- cgit v1.2.3 From 9c41242817f4b6d908886c0fdb036d9246c50630 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 23 Jan 2016 15:34:10 -0800 Subject: libnvdimm: fix mode determination for e820 devices Correctly display "safe" mode when a btt is established on a e820/memmap defined pmem namespace. Signed-off-by: Dan Williams --- drivers/nvdimm/namespace_devs.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c index 8ebfcaae3f5a..9edf7eb7d17c 100644 --- a/drivers/nvdimm/namespace_devs.c +++ b/drivers/nvdimm/namespace_devs.c @@ -1277,10 +1277,12 @@ static ssize_t mode_show(struct device *dev, device_lock(dev); claim = ndns->claim; - if (pmem_should_map_pages(dev) || (claim && is_nd_pfn(claim))) - mode = "memory"; - else if (claim && is_nd_btt(claim)) + if (claim && is_nd_btt(claim)) mode = "safe"; + else if (claim && is_nd_pfn(claim)) + mode = "memory"; + else if (!claim && pmem_should_map_pages(dev)) + mode = "memory"; else mode = "raw"; rc = sprintf(buf, "%s\n", mode); -- cgit v1.2.3 From b98c66887ee1aec661dcb88fe17399d5d112ed98 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 21 Jan 2016 15:19:59 +0000 Subject: drm/etnaviv: ignore VG GPUs with FE2.0 Ignore GPUs with a 2.0 front end. These have a different register layout for the front end, which provokes imprecise aborts from the register accesses in the 'gpu' debugfs file. Signed-off-by: Russell King Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index e0e68dd7565d..a9530f59e6fe 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -515,6 +515,14 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu) goto fail; } + /* Exclude VG cores with FE2.0 */ + if (gpu->identity.features & chipFeatures_PIPE_VG && + gpu->identity.features & chipFeatures_FE20) { + dev_info(gpu->dev, "Ignoring GPU with VG and FE2.0\n"); + ret = -ENXIO; + goto fail; + } + ret = etnaviv_hw_reset(gpu); if (ret) goto fail; -- cgit v1.2.3 From e2a2e263e06a0c153234b3e93fb85612d1c454d3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 24 Jan 2016 17:35:43 +0000 Subject: drm/etnaviv: update common and state_hi xml.h files Update the common and state_hi xml.h header files from the etnaviv repository. Acked-by: Christian Gmeiner Signed-off-by: Russell King Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/common.xml.h | 59 +++++++++++++++++++++++++++++----- drivers/gpu/drm/etnaviv/state_hi.xml.h | 26 +++++++++++++-- 2 files changed, 75 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/common.xml.h b/drivers/gpu/drm/etnaviv/common.xml.h index 9e585d51fb78..e881482b5971 100644 --- a/drivers/gpu/drm/etnaviv/common.xml.h +++ b/drivers/gpu/drm/etnaviv/common.xml.h @@ -8,8 +8,8 @@ http://0x04.net/cgit/index.cgi/rules-ng-ng git clone git://0x04.net/rules-ng-ng The rules-ng-ng source files this header was generated from are: -- state_vg.xml ( 5973 bytes, from 2015-03-25 11:26:01) -- common.xml ( 18437 bytes, from 2015-03-25 11:27:41) +- state_hi.xml ( 24309 bytes, from 2015-12-12 09:02:53) +- common.xml ( 18379 bytes, from 2015-12-12 09:02:53) Copyright (C) 2015 */ @@ -30,15 +30,19 @@ Copyright (C) 2015 #define ENDIAN_MODE_NO_SWAP 0x00000000 #define ENDIAN_MODE_SWAP_16 0x00000001 #define ENDIAN_MODE_SWAP_32 0x00000002 +#define chipModel_GC200 0x00000200 #define chipModel_GC300 0x00000300 #define chipModel_GC320 0x00000320 +#define chipModel_GC328 0x00000328 #define chipModel_GC350 0x00000350 #define chipModel_GC355 0x00000355 #define chipModel_GC400 0x00000400 #define chipModel_GC410 0x00000410 #define chipModel_GC420 0x00000420 +#define chipModel_GC428 0x00000428 #define chipModel_GC450 0x00000450 #define chipModel_GC500 0x00000500 +#define chipModel_GC520 0x00000520 #define chipModel_GC530 0x00000530 #define chipModel_GC600 0x00000600 #define chipModel_GC700 0x00000700 @@ -46,9 +50,16 @@ Copyright (C) 2015 #define chipModel_GC860 0x00000860 #define chipModel_GC880 0x00000880 #define chipModel_GC1000 0x00001000 +#define chipModel_GC1500 0x00001500 #define chipModel_GC2000 0x00002000 #define chipModel_GC2100 0x00002100 +#define chipModel_GC2200 0x00002200 +#define chipModel_GC2500 0x00002500 +#define chipModel_GC3000 0x00003000 #define chipModel_GC4000 0x00004000 +#define chipModel_GC5000 0x00005000 +#define chipModel_GC5200 0x00005200 +#define chipModel_GC6400 0x00006400 #define RGBA_BITS_R 0x00000001 #define RGBA_BITS_G 0x00000002 #define RGBA_BITS_B 0x00000004 @@ -160,7 +171,7 @@ Copyright (C) 2015 #define chipMinorFeatures2_UNK8 0x00000100 #define chipMinorFeatures2_UNK9 0x00000200 #define chipMinorFeatures2_UNK10 0x00000400 -#define chipMinorFeatures2_SAMPLERBASE_16 0x00000800 +#define chipMinorFeatures2_HALTI1 0x00000800 #define chipMinorFeatures2_UNK12 0x00001000 #define chipMinorFeatures2_UNK13 0x00002000 #define chipMinorFeatures2_UNK14 0x00004000 @@ -189,7 +200,7 @@ Copyright (C) 2015 #define chipMinorFeatures3_UNK5 0x00000020 #define chipMinorFeatures3_UNK6 0x00000040 #define chipMinorFeatures3_UNK7 0x00000080 -#define chipMinorFeatures3_UNK8 0x00000100 +#define chipMinorFeatures3_FAST_MSAA 0x00000100 #define chipMinorFeatures3_UNK9 0x00000200 #define chipMinorFeatures3_BUG_FIXES10 0x00000400 #define chipMinorFeatures3_UNK11 0x00000800 @@ -199,7 +210,7 @@ Copyright (C) 2015 #define chipMinorFeatures3_UNK15 0x00008000 #define chipMinorFeatures3_UNK16 0x00010000 #define chipMinorFeatures3_UNK17 0x00020000 -#define chipMinorFeatures3_UNK18 0x00040000 +#define chipMinorFeatures3_ACE 0x00040000 #define chipMinorFeatures3_UNK19 0x00080000 #define chipMinorFeatures3_UNK20 0x00100000 #define chipMinorFeatures3_UNK21 0x00200000 @@ -207,7 +218,7 @@ Copyright (C) 2015 #define chipMinorFeatures3_UNK23 0x00800000 #define chipMinorFeatures3_UNK24 0x01000000 #define chipMinorFeatures3_UNK25 0x02000000 -#define chipMinorFeatures3_UNK26 0x04000000 +#define chipMinorFeatures3_NEW_HZ 0x04000000 #define chipMinorFeatures3_UNK27 0x08000000 #define chipMinorFeatures3_UNK28 0x10000000 #define chipMinorFeatures3_UNK29 0x20000000 @@ -229,9 +240,9 @@ Copyright (C) 2015 #define chipMinorFeatures4_UNK13 0x00002000 #define chipMinorFeatures4_UNK14 0x00004000 #define chipMinorFeatures4_UNK15 0x00008000 -#define chipMinorFeatures4_UNK16 0x00010000 +#define chipMinorFeatures4_HALTI2 0x00010000 #define chipMinorFeatures4_UNK17 0x00020000 -#define chipMinorFeatures4_UNK18 0x00040000 +#define chipMinorFeatures4_SMALL_MSAA 0x00040000 #define chipMinorFeatures4_UNK19 0x00080000 #define chipMinorFeatures4_UNK20 0x00100000 #define chipMinorFeatures4_UNK21 0x00200000 @@ -245,5 +256,37 @@ Copyright (C) 2015 #define chipMinorFeatures4_UNK29 0x20000000 #define chipMinorFeatures4_UNK30 0x40000000 #define chipMinorFeatures4_UNK31 0x80000000 +#define chipMinorFeatures5_UNK0 0x00000001 +#define chipMinorFeatures5_UNK1 0x00000002 +#define chipMinorFeatures5_UNK2 0x00000004 +#define chipMinorFeatures5_UNK3 0x00000008 +#define chipMinorFeatures5_UNK4 0x00000010 +#define chipMinorFeatures5_UNK5 0x00000020 +#define chipMinorFeatures5_UNK6 0x00000040 +#define chipMinorFeatures5_UNK7 0x00000080 +#define chipMinorFeatures5_UNK8 0x00000100 +#define chipMinorFeatures5_HALTI3 0x00000200 +#define chipMinorFeatures5_UNK10 0x00000400 +#define chipMinorFeatures5_UNK11 0x00000800 +#define chipMinorFeatures5_UNK12 0x00001000 +#define chipMinorFeatures5_UNK13 0x00002000 +#define chipMinorFeatures5_UNK14 0x00004000 +#define chipMinorFeatures5_UNK15 0x00008000 +#define chipMinorFeatures5_UNK16 0x00010000 +#define chipMinorFeatures5_UNK17 0x00020000 +#define chipMinorFeatures5_UNK18 0x00040000 +#define chipMinorFeatures5_UNK19 0x00080000 +#define chipMinorFeatures5_UNK20 0x00100000 +#define chipMinorFeatures5_UNK21 0x00200000 +#define chipMinorFeatures5_UNK22 0x00400000 +#define chipMinorFeatures5_UNK23 0x00800000 +#define chipMinorFeatures5_UNK24 0x01000000 +#define chipMinorFeatures5_UNK25 0x02000000 +#define chipMinorFeatures5_UNK26 0x04000000 +#define chipMinorFeatures5_UNK27 0x08000000 +#define chipMinorFeatures5_UNK28 0x10000000 +#define chipMinorFeatures5_UNK29 0x20000000 +#define chipMinorFeatures5_UNK30 0x40000000 +#define chipMinorFeatures5_UNK31 0x80000000 #endif /* COMMON_XML */ diff --git a/drivers/gpu/drm/etnaviv/state_hi.xml.h b/drivers/gpu/drm/etnaviv/state_hi.xml.h index 0064f2640396..6a7de5f1454a 100644 --- a/drivers/gpu/drm/etnaviv/state_hi.xml.h +++ b/drivers/gpu/drm/etnaviv/state_hi.xml.h @@ -8,8 +8,8 @@ http://0x04.net/cgit/index.cgi/rules-ng-ng git clone git://0x04.net/rules-ng-ng The rules-ng-ng source files this header was generated from are: -- state_hi.xml ( 23420 bytes, from 2015-03-25 11:47:21) -- common.xml ( 18437 bytes, from 2015-03-25 11:27:41) +- state_hi.xml ( 24309 bytes, from 2015-12-12 09:02:53) +- common.xml ( 18437 bytes, from 2015-12-12 09:02:53) Copyright (C) 2015 */ @@ -182,8 +182,25 @@ Copyright (C) 2015 #define VIVS_HI_CHIP_MINOR_FEATURE_3 0x00000088 +#define VIVS_HI_CHIP_SPECS_3 0x0000008c +#define VIVS_HI_CHIP_SPECS_3_VARYINGS_COUNT__MASK 0x000001f0 +#define VIVS_HI_CHIP_SPECS_3_VARYINGS_COUNT__SHIFT 4 +#define VIVS_HI_CHIP_SPECS_3_VARYINGS_COUNT(x) (((x) << VIVS_HI_CHIP_SPECS_3_VARYINGS_COUNT__SHIFT) & VIVS_HI_CHIP_SPECS_3_VARYINGS_COUNT__MASK) +#define VIVS_HI_CHIP_SPECS_3_GPU_CORE_COUNT__MASK 0x00000007 +#define VIVS_HI_CHIP_SPECS_3_GPU_CORE_COUNT__SHIFT 0 +#define VIVS_HI_CHIP_SPECS_3_GPU_CORE_COUNT(x) (((x) << VIVS_HI_CHIP_SPECS_3_GPU_CORE_COUNT__SHIFT) & VIVS_HI_CHIP_SPECS_3_GPU_CORE_COUNT__MASK) + #define VIVS_HI_CHIP_MINOR_FEATURE_4 0x00000094 +#define VIVS_HI_CHIP_SPECS_4 0x0000009c +#define VIVS_HI_CHIP_SPECS_4_STREAM_COUNT__MASK 0x0001f000 +#define VIVS_HI_CHIP_SPECS_4_STREAM_COUNT__SHIFT 12 +#define VIVS_HI_CHIP_SPECS_4_STREAM_COUNT(x) (((x) << VIVS_HI_CHIP_SPECS_4_STREAM_COUNT__SHIFT) & VIVS_HI_CHIP_SPECS_4_STREAM_COUNT__MASK) + +#define VIVS_HI_CHIP_MINOR_FEATURE_5 0x000000a0 + +#define VIVS_HI_CHIP_PRODUCT_ID 0x000000a8 + #define VIVS_PM 0x00000000 #define VIVS_PM_POWER_CONTROLS 0x00000100 @@ -206,6 +223,11 @@ Copyright (C) 2015 #define VIVS_PM_MODULE_STATUS_MODULE_CLOCK_GATED_FE 0x00000001 #define VIVS_PM_MODULE_STATUS_MODULE_CLOCK_GATED_DE 0x00000002 #define VIVS_PM_MODULE_STATUS_MODULE_CLOCK_GATED_PE 0x00000004 +#define VIVS_PM_MODULE_STATUS_MODULE_CLOCK_GATED_SH 0x00000008 +#define VIVS_PM_MODULE_STATUS_MODULE_CLOCK_GATED_PA 0x00000010 +#define VIVS_PM_MODULE_STATUS_MODULE_CLOCK_GATED_SE 0x00000020 +#define VIVS_PM_MODULE_STATUS_MODULE_CLOCK_GATED_RA 0x00000040 +#define VIVS_PM_MODULE_STATUS_MODULE_CLOCK_GATED_TX 0x00000080 #define VIVS_PM_PULSE_EATER 0x0000010c -- cgit v1.2.3 From 507f899137f9e4f1405820b946063a6db78b2295 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 24 Jan 2016 17:35:48 +0000 Subject: drm/etnaviv: use defined constants for the chip model Use the defined constants in common.xml.h for the chip model rather than coding these as hex numbers. Acked-by: Christian Gmeiner Signed-off-by: Russell King Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index a9530f59e6fe..7dc355ef7c4e 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -173,7 +173,7 @@ static void etnaviv_hw_specs(struct etnaviv_gpu *gpu) /* Convert the register max value */ if (gpu->identity.register_max) gpu->identity.register_max = 1 << gpu->identity.register_max; - else if (gpu->identity.model == 0x0400) + else if (gpu->identity.model == chipModel_GC400) gpu->identity.register_max = 32; else gpu->identity.register_max = 64; @@ -181,10 +181,10 @@ static void etnaviv_hw_specs(struct etnaviv_gpu *gpu) /* Convert thread count */ if (gpu->identity.thread_count) gpu->identity.thread_count = 1 << gpu->identity.thread_count; - else if (gpu->identity.model == 0x0400) + else if (gpu->identity.model == chipModel_GC400) gpu->identity.thread_count = 64; - else if (gpu->identity.model == 0x0500 || - gpu->identity.model == 0x0530) + else if (gpu->identity.model == chipModel_GC500 || + gpu->identity.model == chipModel_GC530) gpu->identity.thread_count = 128; else gpu->identity.thread_count = 256; @@ -206,7 +206,7 @@ static void etnaviv_hw_specs(struct etnaviv_gpu *gpu) if (gpu->identity.vertex_output_buffer_size) { gpu->identity.vertex_output_buffer_size = 1 << gpu->identity.vertex_output_buffer_size; - } else if (gpu->identity.model == 0x0400) { + } else if (gpu->identity.model == chipModel_GC400) { if (gpu->identity.revision < 0x4000) gpu->identity.vertex_output_buffer_size = 512; else if (gpu->identity.revision < 0x4200) @@ -219,9 +219,9 @@ static void etnaviv_hw_specs(struct etnaviv_gpu *gpu) switch (gpu->identity.instruction_count) { case 0: - if ((gpu->identity.model == 0x2000 && + if ((gpu->identity.model == chipModel_GC2000 && gpu->identity.revision == 0x5108) || - gpu->identity.model == 0x880) + gpu->identity.model == chipModel_GC880) gpu->identity.instruction_count = 512; else gpu->identity.instruction_count = 256; @@ -253,7 +253,7 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) /* Special case for older graphic cores. */ if (((chipIdentity & VIVS_HI_CHIP_IDENTITY_FAMILY__MASK) >> VIVS_HI_CHIP_IDENTITY_FAMILY__SHIFT) == 0x01) { - gpu->identity.model = 0x500; /* gc500 */ + gpu->identity.model = chipModel_GC500; gpu->identity.revision = (chipIdentity & VIVS_HI_CHIP_IDENTITY_REVISION__MASK) >> VIVS_HI_CHIP_IDENTITY_REVISION__SHIFT; @@ -269,12 +269,12 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) * same. Only for GC400 family. */ if ((gpu->identity.model & 0xff00) == 0x0400 && - gpu->identity.model != 0x0420) { + gpu->identity.model != chipModel_GC420) { gpu->identity.model = gpu->identity.model & 0x0400; } /* Another special case */ - if (gpu->identity.model == 0x300 && + if (gpu->identity.model == chipModel_GC300 && gpu->identity.revision == 0x2201) { u32 chipDate = gpu_read(gpu, VIVS_HI_CHIP_DATE); u32 chipTime = gpu_read(gpu, VIVS_HI_CHIP_TIME); @@ -295,11 +295,13 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) gpu->identity.features = gpu_read(gpu, VIVS_HI_CHIP_FEATURE); /* Disable fast clear on GC700. */ - if (gpu->identity.model == 0x700) + if (gpu->identity.model == chipModel_GC700) gpu->identity.features &= ~chipFeatures_FAST_CLEAR; - if ((gpu->identity.model == 0x500 && gpu->identity.revision < 2) || - (gpu->identity.model == 0x300 && gpu->identity.revision < 0x2000)) { + if ((gpu->identity.model == chipModel_GC500 && + gpu->identity.revision < 2) || + (gpu->identity.model == chipModel_GC300 && + gpu->identity.revision < 0x2000)) { /* * GC500 rev 1.x and GC300 rev < 2.0 doesn't have these @@ -466,7 +468,8 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu) VIVS_HI_AXI_CONFIG_ARCACHE(2)); /* GC2000 rev 5108 needs a special bus config */ - if (gpu->identity.model == 0x2000 && gpu->identity.revision == 0x5108) { + if (gpu->identity.model == chipModel_GC2000 && + gpu->identity.revision == 0x5108) { u32 bus_config = gpu_read(gpu, VIVS_MC_BUS_CONFIG); bus_config &= ~(VIVS_MC_BUS_CONFIG_FE_BUS_CONFIG__MASK | VIVS_MC_BUS_CONFIG_TX_BUS_CONFIG__MASK); -- cgit v1.2.3 From 52f36ba1d6134f5c1c45deb0da53442a5971358e Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 24 Jan 2016 17:35:54 +0000 Subject: drm/etnaviv: add helper to extract bitfields Add a helper to extract etnaviv bitfields from register values. Acked-by: Christian Gmeiner Signed-off-by: Russell King Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 62 +++++++++++++++-------------------- 1 file changed, 27 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 7dc355ef7c4e..2c27fac0d2de 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -120,6 +120,9 @@ int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value) return 0; } +#define etnaviv_field(val, field) \ + (((val) & field##__MASK) >> field##__SHIFT) + static void etnaviv_hw_specs(struct etnaviv_gpu *gpu) { if (gpu->identity.minor_features0 & @@ -129,37 +132,28 @@ static void etnaviv_hw_specs(struct etnaviv_gpu *gpu) specs[0] = gpu_read(gpu, VIVS_HI_CHIP_SPECS); specs[1] = gpu_read(gpu, VIVS_HI_CHIP_SPECS_2); - gpu->identity.stream_count = - (specs[0] & VIVS_HI_CHIP_SPECS_STREAM_COUNT__MASK) - >> VIVS_HI_CHIP_SPECS_STREAM_COUNT__SHIFT; - gpu->identity.register_max = - (specs[0] & VIVS_HI_CHIP_SPECS_REGISTER_MAX__MASK) - >> VIVS_HI_CHIP_SPECS_REGISTER_MAX__SHIFT; - gpu->identity.thread_count = - (specs[0] & VIVS_HI_CHIP_SPECS_THREAD_COUNT__MASK) - >> VIVS_HI_CHIP_SPECS_THREAD_COUNT__SHIFT; - gpu->identity.vertex_cache_size = - (specs[0] & VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE__MASK) - >> VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE__SHIFT; - gpu->identity.shader_core_count = - (specs[0] & VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT__MASK) - >> VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT__SHIFT; - gpu->identity.pixel_pipes = - (specs[0] & VIVS_HI_CHIP_SPECS_PIXEL_PIPES__MASK) - >> VIVS_HI_CHIP_SPECS_PIXEL_PIPES__SHIFT; + gpu->identity.stream_count = etnaviv_field(specs[0], + VIVS_HI_CHIP_SPECS_STREAM_COUNT); + gpu->identity.register_max = etnaviv_field(specs[0], + VIVS_HI_CHIP_SPECS_REGISTER_MAX); + gpu->identity.thread_count = etnaviv_field(specs[0], + VIVS_HI_CHIP_SPECS_THREAD_COUNT); + gpu->identity.vertex_cache_size = etnaviv_field(specs[0], + VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE); + gpu->identity.shader_core_count = etnaviv_field(specs[0], + VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT); + gpu->identity.pixel_pipes = etnaviv_field(specs[0], + VIVS_HI_CHIP_SPECS_PIXEL_PIPES); gpu->identity.vertex_output_buffer_size = - (specs[0] & VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE__MASK) - >> VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE__SHIFT; - - gpu->identity.buffer_size = - (specs[1] & VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE__MASK) - >> VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE__SHIFT; - gpu->identity.instruction_count = - (specs[1] & VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT__MASK) - >> VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT__SHIFT; - gpu->identity.num_constants = - (specs[1] & VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS__MASK) - >> VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS__SHIFT; + etnaviv_field(specs[0], + VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE); + + gpu->identity.buffer_size = etnaviv_field(specs[1], + VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE); + gpu->identity.instruction_count = etnaviv_field(specs[1], + VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT); + gpu->identity.num_constants = etnaviv_field(specs[1], + VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS); } /* Fill in the stream count if not specified */ @@ -251,12 +245,10 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) chipIdentity = gpu_read(gpu, VIVS_HI_CHIP_IDENTITY); /* Special case for older graphic cores. */ - if (((chipIdentity & VIVS_HI_CHIP_IDENTITY_FAMILY__MASK) - >> VIVS_HI_CHIP_IDENTITY_FAMILY__SHIFT) == 0x01) { + if (etnaviv_field(chipIdentity, VIVS_HI_CHIP_IDENTITY_FAMILY) == 0x01) { gpu->identity.model = chipModel_GC500; - gpu->identity.revision = - (chipIdentity & VIVS_HI_CHIP_IDENTITY_REVISION__MASK) - >> VIVS_HI_CHIP_IDENTITY_REVISION__SHIFT; + gpu->identity.revision = etnaviv_field(chipIdentity, + VIVS_HI_CHIP_IDENTITY_REVISION); } else { gpu->identity.model = gpu_read(gpu, VIVS_HI_CHIP_MODEL); -- cgit v1.2.3 From 472f79dcf21d34f4d667910002482efe3ca4ba34 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 24 Jan 2016 17:35:59 +0000 Subject: drm/etnaviv: add helper for comparing model/revision IDs Add and use a helper for comparing the model and revision IDs. Acked-by: Christian Gmeiner Signed-off-by: Russell King Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 2c27fac0d2de..d5fad472e91f 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -120,6 +120,10 @@ int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value) return 0; } + +#define etnaviv_is_model_rev(gpu, mod, rev) \ + ((gpu)->identity.model == chipModel_##mod && \ + (gpu)->identity.revision == rev) #define etnaviv_field(val, field) \ (((val) & field##__MASK) >> field##__SHIFT) @@ -213,8 +217,7 @@ static void etnaviv_hw_specs(struct etnaviv_gpu *gpu) switch (gpu->identity.instruction_count) { case 0: - if ((gpu->identity.model == chipModel_GC2000 && - gpu->identity.revision == 0x5108) || + if (etnaviv_is_model_rev(gpu, GC2000, 0x5108) || gpu->identity.model == chipModel_GC880) gpu->identity.instruction_count = 512; else @@ -266,8 +269,7 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) } /* Another special case */ - if (gpu->identity.model == chipModel_GC300 && - gpu->identity.revision == 0x2201) { + if (etnaviv_is_model_rev(gpu, GC300, 0x2201)) { u32 chipDate = gpu_read(gpu, VIVS_HI_CHIP_DATE); u32 chipTime = gpu_read(gpu, VIVS_HI_CHIP_TIME); @@ -435,10 +437,9 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu) { u16 prefetch; - if (gpu->identity.model == chipModel_GC320 && - gpu_read(gpu, VIVS_HI_CHIP_TIME) != 0x2062400 && - (gpu->identity.revision == 0x5007 || - gpu->identity.revision == 0x5220)) { + if ((etnaviv_is_model_rev(gpu, GC320, 0x5007) || + etnaviv_is_model_rev(gpu, GC320, 0x5220)) && + gpu_read(gpu, VIVS_HI_CHIP_TIME) != 0x2062400) { u32 mc_memory_debug; mc_memory_debug = gpu_read(gpu, VIVS_MC_DEBUG_MEMORY) & ~0xff; @@ -460,8 +461,7 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu) VIVS_HI_AXI_CONFIG_ARCACHE(2)); /* GC2000 rev 5108 needs a special bus config */ - if (gpu->identity.model == chipModel_GC2000 && - gpu->identity.revision == 0x5108) { + if (etnaviv_is_model_rev(gpu, GC2000, 0x5108)) { u32 bus_config = gpu_read(gpu, VIVS_MC_BUS_CONFIG); bus_config &= ~(VIVS_MC_BUS_CONFIG_FE_BUS_CONFIG__MASK | VIVS_MC_BUS_CONFIG_TX_BUS_CONFIG__MASK); -- cgit v1.2.3 From 602eb48966d7b7f7e64dca8d9ea2842d83bfae73 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 24 Jan 2016 17:36:04 +0000 Subject: drm/etnaviv: add further minor features and varyings count Export further minor feature bitmasks and the varyings count from the GPU specifications registers to userspace. Acked-by: Christian Gmeiner Signed-off-by: Russell King Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 62 ++++++++++++++++++++++++++++++++++- drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 9 +++++ include/uapi/drm/etnaviv_drm.h | 3 ++ 3 files changed, 73 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index d5fad472e91f..7b511ad9f54b 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -72,6 +72,14 @@ int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value) *value = gpu->identity.minor_features3; break; + case ETNAVIV_PARAM_GPU_FEATURES_5: + *value = gpu->identity.minor_features4; + break; + + case ETNAVIV_PARAM_GPU_FEATURES_6: + *value = gpu->identity.minor_features5; + break; + case ETNAVIV_PARAM_GPU_STREAM_COUNT: *value = gpu->identity.stream_count; break; @@ -112,6 +120,10 @@ int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value) *value = gpu->identity.num_constants; break; + case ETNAVIV_PARAM_GPU_NUM_VARYINGS: + *value = gpu->identity.varyings_count; + break; + default: DBG("%s: invalid param: %u", dev_name(gpu->dev), param); return -EINVAL; @@ -131,10 +143,13 @@ static void etnaviv_hw_specs(struct etnaviv_gpu *gpu) { if (gpu->identity.minor_features0 & chipMinorFeatures0_MORE_MINOR_FEATURES) { - u32 specs[2]; + u32 specs[4]; + unsigned int streams; specs[0] = gpu_read(gpu, VIVS_HI_CHIP_SPECS); specs[1] = gpu_read(gpu, VIVS_HI_CHIP_SPECS_2); + specs[2] = gpu_read(gpu, VIVS_HI_CHIP_SPECS_3); + specs[3] = gpu_read(gpu, VIVS_HI_CHIP_SPECS_4); gpu->identity.stream_count = etnaviv_field(specs[0], VIVS_HI_CHIP_SPECS_STREAM_COUNT); @@ -158,6 +173,15 @@ static void etnaviv_hw_specs(struct etnaviv_gpu *gpu) VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT); gpu->identity.num_constants = etnaviv_field(specs[1], VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS); + + gpu->identity.varyings_count = etnaviv_field(specs[2], + VIVS_HI_CHIP_SPECS_3_VARYINGS_COUNT); + + /* This overrides the value from older register if non-zero */ + streams = etnaviv_field(specs[3], + VIVS_HI_CHIP_SPECS_4_STREAM_COUNT); + if (streams) + gpu->identity.stream_count = streams; } /* Fill in the stream count if not specified */ @@ -239,6 +263,30 @@ static void etnaviv_hw_specs(struct etnaviv_gpu *gpu) if (gpu->identity.num_constants == 0) gpu->identity.num_constants = 168; + + if (gpu->identity.varyings_count == 0) { + if (gpu->identity.minor_features1 & chipMinorFeatures1_HALTI0) + gpu->identity.varyings_count = 12; + else + gpu->identity.varyings_count = 8; + } + + /* + * For some cores, two varyings are consumed for position, so the + * maximum varying count needs to be reduced by one. + */ + if (etnaviv_is_model_rev(gpu, GC5000, 0x5434) || + etnaviv_is_model_rev(gpu, GC4000, 0x5222) || + etnaviv_is_model_rev(gpu, GC4000, 0x5245) || + etnaviv_is_model_rev(gpu, GC4000, 0x5208) || + etnaviv_is_model_rev(gpu, GC3000, 0x5435) || + etnaviv_is_model_rev(gpu, GC2200, 0x5244) || + etnaviv_is_model_rev(gpu, GC2100, 0x5108) || + etnaviv_is_model_rev(gpu, GC2000, 0x5108) || + etnaviv_is_model_rev(gpu, GC1500, 0x5246) || + etnaviv_is_model_rev(gpu, GC880, 0x5107) || + etnaviv_is_model_rev(gpu, GC880, 0x5106)) + gpu->identity.varyings_count -= 1; } static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) @@ -305,6 +353,8 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) gpu->identity.minor_features1 = 0; gpu->identity.minor_features2 = 0; gpu->identity.minor_features3 = 0; + gpu->identity.minor_features4 = 0; + gpu->identity.minor_features5 = 0; } else gpu->identity.minor_features0 = gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_0); @@ -317,6 +367,10 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_2); gpu->identity.minor_features3 = gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_3); + gpu->identity.minor_features4 = + gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_4); + gpu->identity.minor_features5 = + gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_5); } /* GC600 idle register reports zero bits where modules aren't present */ @@ -645,6 +699,10 @@ int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m) gpu->identity.minor_features2); seq_printf(m, "\t minor_features3: 0x%08x\n", gpu->identity.minor_features3); + seq_printf(m, "\t minor_features4: 0x%08x\n", + gpu->identity.minor_features4); + seq_printf(m, "\t minor_features5: 0x%08x\n", + gpu->identity.minor_features5); seq_puts(m, "\tspecs\n"); seq_printf(m, "\t stream_count: %d\n", @@ -667,6 +725,8 @@ int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m) gpu->identity.instruction_count); seq_printf(m, "\t num_constants: %d\n", gpu->identity.num_constants); + seq_printf(m, "\t varyings_count: %d\n", + gpu->identity.varyings_count); seq_printf(m, "\taxi: 0x%08x\n", axi); seq_printf(m, "\tidle: 0x%08x\n", idle); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h index c75d50359ab0..f233ac4c7c1c 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h @@ -46,6 +46,12 @@ struct etnaviv_chip_identity { /* Supported minor feature 3 fields. */ u32 minor_features3; + /* Supported minor feature 4 fields. */ + u32 minor_features4; + + /* Supported minor feature 5 fields. */ + u32 minor_features5; + /* Number of streams supported. */ u32 stream_count; @@ -75,6 +81,9 @@ struct etnaviv_chip_identity { /* Buffer size */ u32 buffer_size; + + /* Number of varyings */ + u8 varyings_count; }; struct etnaviv_event { diff --git a/include/uapi/drm/etnaviv_drm.h b/include/uapi/drm/etnaviv_drm.h index 4cc989ad6851..f95e1c43c3fb 100644 --- a/include/uapi/drm/etnaviv_drm.h +++ b/include/uapi/drm/etnaviv_drm.h @@ -48,6 +48,8 @@ struct drm_etnaviv_timespec { #define ETNAVIV_PARAM_GPU_FEATURES_2 0x05 #define ETNAVIV_PARAM_GPU_FEATURES_3 0x06 #define ETNAVIV_PARAM_GPU_FEATURES_4 0x07 +#define ETNAVIV_PARAM_GPU_FEATURES_5 0x08 +#define ETNAVIV_PARAM_GPU_FEATURES_6 0x09 #define ETNAVIV_PARAM_GPU_STREAM_COUNT 0x10 #define ETNAVIV_PARAM_GPU_REGISTER_MAX 0x11 @@ -59,6 +61,7 @@ struct drm_etnaviv_timespec { #define ETNAVIV_PARAM_GPU_BUFFER_SIZE 0x17 #define ETNAVIV_PARAM_GPU_INSTRUCTION_COUNT 0x18 #define ETNAVIV_PARAM_GPU_NUM_CONSTANTS 0x19 +#define ETNAVIV_PARAM_GPU_NUM_VARYINGS 0x1a #define ETNA_MAX_PIPES 4 -- cgit v1.2.3 From 45d16a6d94580cd3c6baed69b5fe441ece599fc4 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 25 Jan 2016 12:41:05 +0100 Subject: drm/etnaviv: fix memory leak in IOMMU init path Plug in error handling to free any allocated ressources in the IOMMU init path. Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 7b511ad9f54b..a33162cf4f4c 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -596,10 +596,9 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu) goto fail; } - /* TODO: we will leak here memory - fix it! */ - gpu->mmu = etnaviv_iommu_new(gpu, iommu, version); if (!gpu->mmu) { + iommu_domain_free(iommu); ret = -ENOMEM; goto fail; } @@ -609,7 +608,7 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu) if (!gpu->buffer) { ret = -ENOMEM; dev_err(gpu->dev, "could not create command buffer\n"); - goto fail; + goto destroy_iommu; } if (gpu->buffer->paddr - gpu->memory_base > 0x80000000) { ret = -EINVAL; @@ -639,6 +638,9 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu) free_buffer: etnaviv_gpu_cmdbuf_free(gpu->buffer); gpu->buffer = NULL; +destroy_iommu: + etnaviv_iommu_destroy(gpu->mmu); + gpu->mmu = NULL; fail: pm_runtime_mark_last_busy(gpu->dev); pm_runtime_put_autosuspend(gpu->dev); -- cgit v1.2.3 From 9f07bb0d4ada68f05b2e51c10720d4688e6adea4 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 25 Jan 2016 15:37:28 +0100 Subject: drm/etnaviv: fix get pages error path in etnaviv_gem_vaddr In case that etnaviv_gem_get_pages is unable to get the required pages the object mutex needs to be unlocked. Also return NULL in this case instead of propagating the error, as callers of this function might not be prepared to handle a pointer error, but expect this call to follow the semantics of a plain vmap to return NULL in case of an error. Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_dump.c | 2 +- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_dump.c b/drivers/gpu/drm/etnaviv/etnaviv_dump.c index fd7d3e989e79..09a759e69dd2 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_dump.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_dump.c @@ -216,7 +216,7 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu) iter.hdr->iova = cpu_to_le64(vram->iova); vaddr = etnaviv_gem_vaddr(&obj->base); - if (vaddr && !IS_ERR(vaddr)) + if (vaddr) memcpy(iter.data, vaddr, obj->base.size); etnaviv_core_dump_header(&iter, ETDUMP_BUF_BO, iter.data + diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index 9f77c3b94cc6..b22712fdd31e 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -361,8 +361,10 @@ void *etnaviv_gem_vaddr(struct drm_gem_object *obj) if (!etnaviv_obj->vaddr) { struct page **pages = etnaviv_gem_get_pages(etnaviv_obj); - if (IS_ERR(pages)) - return ERR_CAST(pages); + if (IS_ERR(pages)) { + mutex_unlock(&etnaviv_obj->lock); + return NULL; + } etnaviv_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT, VM_MAP, pgprot_writecombine(PAGE_KERNEL)); -- cgit v1.2.3 From ce3088fdb51eda7b9ef3d119e7c302c08428f274 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Tue, 26 Jan 2016 18:10:32 +0100 Subject: drm/etnaviv: rename etnaviv_gem_vaddr to etnaviv_gem_vmap This function follows the semantics of vmap() by returning NULL in case of an error. To make things less confusing rename it to make make both functions more closely related. Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_drv.h | 2 +- drivers/gpu/drm/etnaviv/etnaviv_dump.c | 2 +- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 2 +- drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h index d6bd438bd5be..1cd6046e76b1 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h @@ -85,7 +85,7 @@ struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sg); int etnaviv_gem_prime_pin(struct drm_gem_object *obj); void etnaviv_gem_prime_unpin(struct drm_gem_object *obj); -void *etnaviv_gem_vaddr(struct drm_gem_object *obj); +void *etnaviv_gem_vmap(struct drm_gem_object *obj); int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op, struct timespec *timeout); int etnaviv_gem_cpu_fini(struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_dump.c b/drivers/gpu/drm/etnaviv/etnaviv_dump.c index 09a759e69dd2..4a29eeadbf1e 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_dump.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_dump.c @@ -215,7 +215,7 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu) iter.hdr->iova = cpu_to_le64(vram->iova); - vaddr = etnaviv_gem_vaddr(&obj->base); + vaddr = etnaviv_gem_vmap(&obj->base); if (vaddr) memcpy(iter.data, vaddr, obj->base.size); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index b22712fdd31e..1da3d48054c2 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -353,7 +353,7 @@ void etnaviv_gem_put_iova(struct etnaviv_gpu *gpu, struct drm_gem_object *obj) drm_gem_object_unreference_unlocked(obj); } -void *etnaviv_gem_vaddr(struct drm_gem_object *obj) +void *etnaviv_gem_vmap(struct drm_gem_object *obj) { struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c index e94db4f95770..9c054b6c24d6 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c @@ -31,7 +31,7 @@ struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj) void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj) { - return etnaviv_gem_vaddr(obj); + return etnaviv_gem_vmap(obj); } void etnaviv_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) -- cgit v1.2.3 From a0a5ab3e99b8e617221caabf074dcabd1659b9d8 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 25 Jan 2016 15:47:28 +0100 Subject: drm/etnaviv: call correct function when trying to vmap a DMABUF When trying to get the vmap address of an imported buffer, we must call into the appropriate helper function, to allow the exporter to establish the vmap, instead of trying to vmap the buffer on our own. Add an indirection through etnaviv_gem_ops to allow the correct implementation to be called. Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 36 ++++++++++++++++++++--------- drivers/gpu/drm/etnaviv/etnaviv_gem.h | 1 + drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c | 8 +++++++ 3 files changed, 34 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index 1da3d48054c2..4b519e4309b2 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -357,23 +357,35 @@ void *etnaviv_gem_vmap(struct drm_gem_object *obj) { struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); - mutex_lock(&etnaviv_obj->lock); - if (!etnaviv_obj->vaddr) { - struct page **pages = etnaviv_gem_get_pages(etnaviv_obj); - - if (IS_ERR(pages)) { - mutex_unlock(&etnaviv_obj->lock); - return NULL; - } + if (etnaviv_obj->vaddr) + return etnaviv_obj->vaddr; - etnaviv_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT, - VM_MAP, pgprot_writecombine(PAGE_KERNEL)); - } + mutex_lock(&etnaviv_obj->lock); + /* + * Need to check again, as we might have raced with another thread + * while waiting for the mutex. + */ + if (!etnaviv_obj->vaddr) + etnaviv_obj->vaddr = etnaviv_obj->ops->vmap(etnaviv_obj); mutex_unlock(&etnaviv_obj->lock); return etnaviv_obj->vaddr; } +static void *etnaviv_gem_vmap_impl(struct etnaviv_gem_object *obj) +{ + struct page **pages; + + lockdep_assert_held(&obj->lock); + + pages = etnaviv_gem_get_pages(obj); + if (IS_ERR(pages)) + return NULL; + + return vmap(pages, obj->base.size >> PAGE_SHIFT, + VM_MAP, pgprot_writecombine(PAGE_KERNEL)); +} + static inline enum dma_data_direction etnaviv_op_to_dma_dir(u32 op) { if (op & ETNA_PREP_READ) @@ -524,6 +536,7 @@ static void etnaviv_gem_shmem_release(struct etnaviv_gem_object *etnaviv_obj) static const struct etnaviv_gem_ops etnaviv_gem_shmem_ops = { .get_pages = etnaviv_gem_shmem_get_pages, .release = etnaviv_gem_shmem_release, + .vmap = etnaviv_gem_vmap_impl, }; void etnaviv_gem_free_object(struct drm_gem_object *obj) @@ -868,6 +881,7 @@ static void etnaviv_gem_userptr_release(struct etnaviv_gem_object *etnaviv_obj) static const struct etnaviv_gem_ops etnaviv_gem_userptr_ops = { .get_pages = etnaviv_gem_userptr_get_pages, .release = etnaviv_gem_userptr_release, + .vmap = etnaviv_gem_vmap_impl, }; int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file, diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.h b/drivers/gpu/drm/etnaviv/etnaviv_gem.h index a300b4b3d545..ab5df8147a5f 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.h @@ -78,6 +78,7 @@ struct etnaviv_gem_object *to_etnaviv_bo(struct drm_gem_object *obj) struct etnaviv_gem_ops { int (*get_pages)(struct etnaviv_gem_object *); void (*release)(struct etnaviv_gem_object *); + void *(*vmap)(struct etnaviv_gem_object *); }; static inline bool is_active(struct etnaviv_gem_object *etnaviv_obj) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c index 9c054b6c24d6..4e67395f5fa1 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c @@ -77,9 +77,17 @@ static void etnaviv_gem_prime_release(struct etnaviv_gem_object *etnaviv_obj) drm_prime_gem_destroy(&etnaviv_obj->base, etnaviv_obj->sgt); } +static void *etnaviv_gem_prime_vmap_impl(struct etnaviv_gem_object *etnaviv_obj) +{ + lockdep_assert_held(&etnaviv_obj->lock); + + return dma_buf_vmap(etnaviv_obj->base.import_attach->dmabuf); +} + static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = { /* .get_pages should never be called */ .release = etnaviv_gem_prime_release, + .vmap = etnaviv_gem_prime_vmap_impl, }; struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev, -- cgit v1.2.3 From 9a4e7849b5e4e8742d71fa90fbf0722dd0710a56 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 26 Jan 2016 14:49:22 +0000 Subject: component: fix crash on x86_64 with hda audio drivers Maarten reports that the addition of releasing match data to the component helper results in a general protection fault on x86_64. This is caused by the devm resources being freed in reverse order to their allocation, which caused a use-after-free of the match array. Switch the match array to be a more conventional kmalloc/kfree() affair, explicitly freeing it along with the parent match data structure. Reported-by: Maarten Lankhorst Fixes: ce657b1cddf1 ("component: add support for releasing match data") Signed-off-by: Russell King --- drivers/base/component.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/component.c b/drivers/base/component.c index 89f5cf68d80a..05cd26c02449 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c @@ -206,6 +206,8 @@ static void component_match_release(struct device *master, if (mc->release) mc->release(master, mc->data); } + + kfree(match->compare); } static void devm_component_match_release(struct device *dev, void *res) @@ -221,14 +223,14 @@ static int component_match_realloc(struct device *dev, if (match->alloc == num) return 0; - new = devm_kmalloc_array(dev, num, sizeof(*new), GFP_KERNEL); + new = kmalloc_array(num, sizeof(*new), GFP_KERNEL); if (!new) return -ENOMEM; if (match->compare) { memcpy(new, match->compare, sizeof(*new) * min(match->num, num)); - devm_kfree(dev, match->compare); + kfree(match->compare); } match->compare = new; match->alloc = num; -- cgit v1.2.3 From f88f44cbf10cf5bd42d6e46ea6625d9bfa5f155d Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 7 Dec 2015 23:25:59 +0100 Subject: mtd: nand: s3c2410: kill the ->ecc_layout field The s3c2410 is allowing board data to overload the default ECC layout defined inside the driver, but this feature is not used by board specific definitions. Kill this field so that we can easily move to a model where ecclayout are dynamically allocated by the NAND controller driver. Signed-off-by: Boris Brezillon Acked-by: Krzysztof Kozlowski Signed-off-by: Brian Norris --- arch/arm/plat-samsung/devs.c | 9 --------- drivers/mtd/nand/s3c2410.c | 3 --- include/linux/platform_data/mtd-nand-s3c2410.h | 1 - 3 files changed, 13 deletions(-) (limited to 'drivers') diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index b53d4ff3befb..84baa16f4c0b 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c @@ -727,15 +727,6 @@ static int __init s3c_nand_copy_set(struct s3c2410_nand_set *set) return -ENOMEM; } - if (set->ecc_layout) { - ptr = kmemdup(set->ecc_layout, - sizeof(struct nand_ecclayout), GFP_KERNEL); - set->ecc_layout = ptr; - - if (!ptr) - return -ENOMEM; - } - return 0; } diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 01ac74fa3b95..9c9397b54b2c 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -861,9 +861,6 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, chip->ecc.mode = NAND_ECC_SOFT; #endif - if (set->ecc_layout != NULL) - chip->ecc.layout = set->ecc_layout; - if (set->disable_ecc) chip->ecc.mode = NAND_ECC_NONE; diff --git a/include/linux/platform_data/mtd-nand-s3c2410.h b/include/linux/platform_data/mtd-nand-s3c2410.h index 36bb92172f47..c55e42ee57fa 100644 --- a/include/linux/platform_data/mtd-nand-s3c2410.h +++ b/include/linux/platform_data/mtd-nand-s3c2410.h @@ -40,7 +40,6 @@ struct s3c2410_nand_set { char *name; int *nr_map; struct mtd_partition *partitions; - struct nand_ecclayout *ecc_layout; }; struct s3c2410_platform_nand { -- cgit v1.2.3 From d5e83ea7dc510fe8e7b4a54e5a93f3dd760f6d7e Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 7 Dec 2015 23:26:00 +0100 Subject: mtd: nand: jz4740: kill the ->ecc_layout field ->ecc_layout is not used by any board file. Kill this field to avoid any confusion. New boards are encouraged to use the default ECC layout defined in NAND core. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- arch/mips/include/asm/mach-jz4740/jz4740_nand.h | 2 -- drivers/mtd/nand/jz4740_nand.c | 3 --- 2 files changed, 5 deletions(-) (limited to 'drivers') diff --git a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h index 79cff26d8b36..398733e3e2cf 100644 --- a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h +++ b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h @@ -25,8 +25,6 @@ struct jz_nand_platform_data { int num_partitions; struct mtd_partition *partitions; - struct nand_ecclayout *ecc_layout; - unsigned char banks[JZ_NAND_NUM_BANKS]; void (*ident_callback)(struct platform_device *, struct nand_chip *, diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index b19d2a9a5eb9..673ceb2a0b44 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c @@ -427,9 +427,6 @@ static int jz_nand_probe(struct platform_device *pdev) chip->ecc.strength = 4; chip->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK; - if (pdata) - chip->ecc.layout = pdata->ecc_layout; - chip->chip_delay = 50; chip->cmd_ctrl = jz_nand_cmd_ctrl; chip->select_chip = jz_nand_select_chip; -- cgit v1.2.3 From 02db97a9de1c80bd5551ba46d901cb4d912f78f2 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 7 Dec 2015 23:26:01 +0100 Subject: mtd: nand: kill unused ->ecclayout field in platform_nand_chip struct This field is not set in any board file and can thus be dropped. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/plat_nand.c | 1 - include/linux/mtd/nand.h | 2 -- 2 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index a0e26dea1424..e4e50da30444 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c @@ -73,7 +73,6 @@ static int plat_nand_probe(struct platform_device *pdev) data->chip.bbt_options |= pdata->chip.bbt_options; data->chip.ecc.hwctl = pdata->ctrl.hwcontrol; - data->chip.ecc.layout = pdata->chip.ecclayout; data->chip.ecc.mode = NAND_ECC_SOFT; platform_set_drvdata(pdev, data); diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index a13dfd5bc58b..7604f4be3386 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -902,7 +902,6 @@ extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, * @chip_delay: R/B delay value in us * @options: Option flags, e.g. 16bit buswidth * @bbt_options: BBT option flags, e.g. NAND_BBT_USE_FLASH - * @ecclayout: ECC layout info structure * @part_probe_types: NULL-terminated array of probe types */ struct platform_nand_chip { @@ -910,7 +909,6 @@ struct platform_nand_chip { int chip_offset; int nr_partitions; struct mtd_partition *partitions; - struct nand_ecclayout *ecclayout; int chip_delay; unsigned int options; unsigned int bbt_options; -- cgit v1.2.3 From 8be721beb30f14bac915ca1357a0b584d03c0749 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 7 Dec 2015 23:26:02 +0100 Subject: staging: mt29f_spinand: kill unused ecclayout field The spinand_info struct embeds a pointer to an ecclayout definition, but this field is never used in the mt29f driver. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/staging/mt29f_spinand/mt29f_spinand.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.h b/drivers/staging/mt29f_spinand/mt29f_spinand.h index ae62975cf44a..457dc7ffdaf1 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.h +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.h @@ -78,7 +78,6 @@ #define BL_ALL_UNLOCKED 0 struct spinand_info { - struct nand_ecclayout *ecclayout; struct spi_device *spi; void *priv; }; -- cgit v1.2.3 From f771749e3a4905e631dafa073543ef429c7cc855 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 7 Dec 2015 23:26:03 +0100 Subject: mtd: nand: lpc32xx_mlc: fix ecc.size According to the ECC layout description the actual ecc.size is 512 bytes and not mtd->writesize. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/lpc32xx_mlc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c index 9bc435d72a86..d8c3e7afcc0b 100644 --- a/drivers/mtd/nand/lpc32xx_mlc.c +++ b/drivers/mtd/nand/lpc32xx_mlc.c @@ -750,7 +750,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) } nand_chip->ecc.mode = NAND_ECC_HW; - nand_chip->ecc.size = mtd->writesize; + nand_chip->ecc.size = 512; nand_chip->ecc.layout = &lpc32xx_nand_oob; host->mlcsubpages = mtd->writesize / 512; -- cgit v1.2.3 From 420b4629b5b9d08893c459b55a7a266caa734ebd Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 7 Dec 2015 23:26:04 +0100 Subject: mtd: nand: vf610: remove useless mtd->ecclayout assignment The NAND core layer is already taking care of ecclayout propagation. Remove this useless assignment. Signed-off-by: Boris Brezillon Acked-by: Stefan Agner Signed-off-by: Brian Norris --- drivers/mtd/nand/vf610_nfc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 034420f313d5..293feb19b0b1 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -795,8 +795,6 @@ static int vf610_nfc_probe(struct platform_device *pdev) goto error; } - /* propagate ecc.layout to mtd_info */ - mtd->ecclayout = chip->ecc.layout; chip->ecc.read_page = vf610_nfc_read_page; chip->ecc.write_page = vf610_nfc_write_page; -- cgit v1.2.3 From 15c0be7bec002f9a529dd0966d0db96dde176fd0 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 25 Jan 2016 23:24:10 +0100 Subject: mtd: Fix dependencies for !HAS_IOMEM archs Not every arch has io memory. So, unbreak the build by fixing the dependencies. Signed-off-by: Richard Weinberger Acked-by: Geert Uytterhoeven Signed-off-by: Brian Norris --- drivers/mtd/nand/Kconfig | 2 ++ drivers/mtd/spi-nor/Kconfig | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 20f01b3ec23d..545d82b100b6 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -74,6 +74,7 @@ config MTD_NAND_DENALI_SCRATCH_REG_ADDR config MTD_NAND_GPIO tristate "GPIO assisted NAND Flash driver" depends on GPIOLIB || COMPILE_TEST + depends on HAS_IOMEM help This enables a NAND flash driver where control signals are connected to GPIO pins, and commands and data are communicated @@ -463,6 +464,7 @@ config MTD_NAND_MPC5121_NFC config MTD_NAND_VF610_NFC tristate "Support for Freescale NFC for VF610/MPC5125" depends on (SOC_VF610 || COMPILE_TEST) + depends on HAS_IOMEM help Enables support for NAND Flash Controller on some Freescale processors like the VF610, MPC5125, MCF54418 or Kinetis K70. diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig index 0dc927540b3d..83befab4b5b4 100644 --- a/drivers/mtd/spi-nor/Kconfig +++ b/drivers/mtd/spi-nor/Kconfig @@ -9,6 +9,7 @@ if MTD_SPI_NOR config MTD_MT81xx_NOR tristate "Mediatek MT81xx SPI NOR flash controller" + depends on HAS_IOMEM help This enables access to SPI NOR flash, using MT81xx SPI NOR flash controller. This controller does not support generic SPI BUS, it only -- cgit v1.2.3 From e8b63288b37dbb8457b510c9d96f6006da4653f6 Mon Sep 17 00:00:00 2001 From: Alexander Kochetkov Date: Tue, 26 Jan 2016 16:34:00 +0300 Subject: clk: rockchip: add hclk_cpubus to the list of rk3188 critical clocks hclk_cpubus needs to keep running because it is needed for devices like the rom, i2s0 or spdif to be accessible via cpu. Without that all accesses to devices (readl/writel) return wrong data. So add it to the list of critical clocks. Fixes: 78eaf6095cc763c ("clk: rockchip: disable unused clocks") Signed-off-by: Alexander Kochetkov Cc: stable@vger.kernel.org # 4.1.x- Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3188.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index 3d4f2c629682..cc1d09d77edd 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -748,6 +748,7 @@ static const char *const rk3188_critical_clocks[] __initconst = { "hclk_peri", "pclk_cpu", "pclk_peri", + "hclk_cpubus" }; static void __init rk3188_common_clk_init(struct device_node *np) -- cgit v1.2.3 From 13b4389143413a1f18127c07f72c74cad5b563e8 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 20 Jan 2016 11:26:01 -0500 Subject: SCSI: fix crashes in sd and sr runtime PM Runtime suspend during driver probe and removal can cause problems. The driver's runtime_suspend or runtime_resume callbacks may invoked before the driver has finished binding to the device or after the driver has unbound from the device. This problem shows up with the sd and sr drivers, and can cause disk or CD/DVD drives to become unusable as a result. The fix is simple. The drivers store a pointer to the scsi_disk or scsi_cd structure as their private device data when probing is finished, so we simply have to be sure to clear the private data during removal and test it during runtime suspend/resume. This fixes . Signed-off-by: Alan Stern Reported-by: Paul Menzel Reported-by: Erich Schubert Reported-by: Alexandre Rossi Tested-by: Paul Menzel Tested-by: Erich Schubert CC: Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 7 +++++-- drivers/scsi/sr.c | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 4e08d1cd704d..84fa4c46eaa6 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -3268,8 +3268,8 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) struct scsi_disk *sdkp = dev_get_drvdata(dev); int ret = 0; - if (!sdkp) - return 0; /* this can happen */ + if (!sdkp) /* E.g.: runtime suspend following sd_remove() */ + return 0; if (sdkp->WCE && sdkp->media_present) { sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); @@ -3308,6 +3308,9 @@ static int sd_resume(struct device *dev) { struct scsi_disk *sdkp = dev_get_drvdata(dev); + if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */ + return 0; + if (!sdkp->device->manage_start_stop) return 0; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 8bd54a64efd6..64c867405ad4 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -144,6 +144,9 @@ static int sr_runtime_suspend(struct device *dev) { struct scsi_cd *cd = dev_get_drvdata(dev); + if (!cd) /* E.g.: runtime suspend following sr_remove() */ + return 0; + if (cd->media_present) return -EBUSY; else @@ -985,6 +988,7 @@ static int sr_remove(struct device *dev) scsi_autopm_get_device(cd->device); del_gendisk(cd->disk); + dev_set_drvdata(dev, NULL); mutex_lock(&sr_ref_mutex); kref_put(&cd->kref, sr_kref_release); -- cgit v1.2.3 From 0f92db53c10ab608874eea8bbe59491cea2f9a46 Mon Sep 17 00:00:00 2001 From: John Garry Date: Tue, 26 Jan 2016 19:59:12 +0800 Subject: hisi_sas: add dependency for HAS_IOMEM Not every arch has io, so fix build by adding necessary dependency. Signed-off-by: John Garry Suggested-by: Richard Weinberger Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/hisi_sas/Kconfig b/drivers/scsi/hisi_sas/Kconfig index b67661836c9f..d1dd1616f983 100644 --- a/drivers/scsi/hisi_sas/Kconfig +++ b/drivers/scsi/hisi_sas/Kconfig @@ -1,6 +1,6 @@ config SCSI_HISI_SAS tristate "HiSilicon SAS" - depends on HAS_DMA + depends on HAS_DMA && HAS_IOMEM depends on ARM64 || COMPILE_TEST select SCSI_SAS_LIBSAS select BLK_DEV_INTEGRITY -- cgit v1.2.3 From 0f28ede906a8ad44158a6ef9471a5a412343cced Mon Sep 17 00:00:00 2001 From: John Garry Date: Wed, 27 Jan 2016 01:31:17 +0800 Subject: hisi_sas: fix v1 hw check for slot error Completion header bit CMPLT_HDR_RSPNS_XFRD flags whether the response frame is received into host memory, and not whether the response frame has an error. As such, change the decision on whether a slot has an error. Also redundant check on CMPLT_HDR_CMD_CMPLT_MSK is removed. Fixes: 27a3f229 ("hisi_sas: Add cq interrupt handler") Signed-off-by: John Garry Tested-by: Ricardo Salveti Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index d54381149c0d..d04808ef6b2b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1293,13 +1293,10 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba, goto out; } - if (cmplt_hdr_data & CMPLT_HDR_ERR_RCRD_XFRD_MSK) { - if (!(cmplt_hdr_data & CMPLT_HDR_CMD_CMPLT_MSK) || - !(cmplt_hdr_data & CMPLT_HDR_RSPNS_XFRD_MSK)) - ts->stat = SAS_DATA_OVERRUN; - else - slot_err_v1_hw(hisi_hba, task, slot); + if (cmplt_hdr_data & CMPLT_HDR_ERR_RCRD_XFRD_MSK && + !(cmplt_hdr_data & CMPLT_HDR_RSPNS_XFRD_MSK)) { + slot_err_v1_hw(hisi_hba, task, slot); goto out; } -- cgit v1.2.3 From 0bfd464d3fdd5bb322f9cace4cc47f1796545cf7 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:44 -0800 Subject: tty: Wait interruptibly for tty lock on reopen Allow a signal to interrupt the wait for a tty reopen; eg., if the tty has starting final close and is waiting for the device to drain. Signed-off-by: Peter Hurley Cc: stable # 4.4 Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 8 +++++++- drivers/tty/tty_mutex.c | 8 ++++++++ include/linux/tty.h | 1 + 3 files changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 892c92354745..765935b144d6 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2065,7 +2065,12 @@ retry_open: if (tty) { mutex_unlock(&tty_mutex); - tty_lock(tty); + retval = tty_lock_interruptible(tty); + if (retval) { + if (retval == -EINTR) + retval = -ERESTARTSYS; + goto err_unref; + } /* safe to drop the kref from tty_driver_lookup_tty() */ tty_kref_put(tty); retval = tty_reopen(tty); @@ -2152,6 +2157,7 @@ retry_open: return 0; err_unlock: mutex_unlock(&tty_mutex); +err_unref: /* after locks to avoid deadlock */ if (!IS_ERR_OR_NULL(driver)) tty_driver_kref_put(driver); diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c index 77703a391207..d2f3c4cd697f 100644 --- a/drivers/tty/tty_mutex.c +++ b/drivers/tty/tty_mutex.c @@ -19,6 +19,14 @@ void __lockfunc tty_lock(struct tty_struct *tty) } EXPORT_SYMBOL(tty_lock); +int tty_lock_interruptible(struct tty_struct *tty) +{ + if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty)) + return -EIO; + tty_kref_get(tty); + return mutex_lock_interruptible(&tty->legacy_mutex); +} + void __lockfunc tty_unlock(struct tty_struct *tty) { if (WARN(tty->magic != TTY_MAGIC, "U Bad %p\n", tty)) diff --git a/include/linux/tty.h b/include/linux/tty.h index 2fd8708ea888..d9fb4b043f56 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -649,6 +649,7 @@ extern long vt_compat_ioctl(struct tty_struct *tty, /* tty_mutex.c */ /* functions for preparation of BKL removal */ extern void __lockfunc tty_lock(struct tty_struct *tty); +extern int tty_lock_interruptible(struct tty_struct *tty); extern void __lockfunc tty_unlock(struct tty_struct *tty); extern void __lockfunc tty_lock_slave(struct tty_struct *tty); extern void __lockfunc tty_unlock_slave(struct tty_struct *tty); -- cgit v1.2.3 From 7f22f6c935cda600660e623a411fe380015d28d9 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:45 -0800 Subject: tty: Retry failed reopen if tty teardown in-progress A small window exists where a tty reopen will observe the tty just prior to imminent teardown (tty->count == 0); in this case, open() returns EIO to userspace. Instead, retry the open after checking for signals and yielding; this interruptible retry loop allows teardown to commence and initialize a new tty on retry. Never retry the BSD master pty reopen; there is no guarantee the pty pair teardown is imminent since the slave file descriptors may remain open indefinitely. Signed-off-by: Peter Hurley Cc: stable # 4.4 Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 765935b144d6..a1b36bf545e8 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1463,13 +1463,13 @@ static int tty_reopen(struct tty_struct *tty) { struct tty_driver *driver = tty->driver; - if (!tty->count) - return -EIO; - if (driver->type == TTY_DRIVER_TYPE_PTY && driver->subtype == PTY_TYPE_MASTER) return -EIO; + if (!tty->count) + return -EAGAIN; + if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN)) return -EBUSY; @@ -2088,7 +2088,11 @@ retry_open: if (IS_ERR(tty)) { retval = PTR_ERR(tty); - goto err_file; + if (retval != -EAGAIN || signal_pending(current)) + goto err_file; + tty_free_file(filp); + schedule(); + goto retry_open; } tty_add_file(tty, filp); -- cgit v1.2.3 From 5c17c861a357e9458001f021a7afa7aab9937439 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:40:55 -0800 Subject: tty: Fix unsafe ldisc reference via ioctl(TIOCGETD) ioctl(TIOCGETD) retrieves the line discipline id directly from the ldisc because the line discipline id (c_line) in termios is untrustworthy; userspace may have set termios via ioctl(TCSETS*) without actually changing the line discipline via ioctl(TIOCSETD). However, directly accessing the current ldisc via tty->ldisc is unsafe; the ldisc ptr dereferenced may be stale if the line discipline is changing via ioctl(TIOCSETD) or hangup. Wait for the line discipline reference (just like read() or write()) to retrieve the "current" line discipline id. Cc: Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index a1b36bf545e8..5cec01c75691 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2658,6 +2658,28 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) return ret; } +/** + * tiocgetd - get line discipline + * @tty: tty device + * @p: pointer to user data + * + * Retrieves the line discipline id directly from the ldisc. + * + * Locking: waits for ldisc reference (in case the line discipline + * is changing or the tty is being hungup) + */ + +static int tiocgetd(struct tty_struct *tty, int __user *p) +{ + struct tty_ldisc *ld; + int ret; + + ld = tty_ldisc_ref_wait(tty); + ret = put_user(ld->ops->num, p); + tty_ldisc_deref(ld); + return ret; +} + /** * send_break - performed time break * @tty: device to break on @@ -2884,7 +2906,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case TIOCGSID: return tiocgsid(tty, real_tty, p); case TIOCGETD: - return put_user(tty->ldisc->ops->num, (int __user *)p); + return tiocgetd(tty, p); case TIOCSETD: return tiocsetd(tty, p); case TIOCVHANGUP: -- cgit v1.2.3 From 6d27a63caad3f13e96cf065d2d96828c2006be6b Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:40:56 -0800 Subject: n_tty: Fix unsafe reference to "other" ldisc Although n_tty_check_unthrottle() has a valid ldisc reference (since the tty core gets the ldisc ref in tty_read() before calling the line discipline read() method), it does not have a valid ldisc reference to the "other" pty of a pty pair. Since getting an ldisc reference for tty->link essentially open-codes tty_wakeup(), just replace with the equivalent tty_wakeup(). Cc: Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index d9a5fc28fef4..b280abaad91b 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -269,16 +269,13 @@ static void n_tty_check_throttle(struct tty_struct *tty) static void n_tty_check_unthrottle(struct tty_struct *tty) { - if (tty->driver->type == TTY_DRIVER_TYPE_PTY && - tty->link->ldisc->ops->write_wakeup == n_tty_write_wakeup) { + if (tty->driver->type == TTY_DRIVER_TYPE_PTY) { if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE) return; if (!tty->count) return; n_tty_kick_worker(tty); - n_tty_write_wakeup(tty->link); - if (waitqueue_active(&tty->link->write_wait)) - wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT); + tty_wakeup(tty->link); return; } -- cgit v1.2.3 From f4f9edcf9b5289ed96113e79fa65a7bf27ecb096 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:40:58 -0800 Subject: staging/speakup: Use tty_ldisc_ref() for paste kworker As the function documentation for tty_ldisc_ref_wait() notes, it is only callable from a tty file_operations routine; otherwise there is no guarantee the ref won't be NULL. The key difference with the VT's paste_selection() is that is an ioctl, where __speakup_paste_selection() is completely async kworker, kicked off from interrupt context. Fixes: 28a821c30688 ("Staging: speakup: Update __speakup_paste_selection() tty (ab)usage to match vt") Cc: Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/selection.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/speakup/selection.c b/drivers/staging/speakup/selection.c index aa5ab6c80ed4..41ef099b7aa6 100644 --- a/drivers/staging/speakup/selection.c +++ b/drivers/staging/speakup/selection.c @@ -142,7 +142,9 @@ static void __speakup_paste_selection(struct work_struct *work) struct tty_ldisc *ld; DECLARE_WAITQUEUE(wait, current); - ld = tty_ldisc_ref_wait(tty); + ld = tty_ldisc_ref(tty); + if (!ld) + goto tty_unref; tty_buffer_lock_exclusive(&vc->port); add_wait_queue(&vc->paste_wait, &wait); @@ -162,6 +164,7 @@ static void __speakup_paste_selection(struct work_struct *work) tty_buffer_unlock_exclusive(&vc->port); tty_ldisc_deref(ld); +tty_unref: tty_kref_put(tty); } -- cgit v1.2.3 From 73c13c83491142e2ee7850159fc73b5e0967806f Mon Sep 17 00:00:00 2001 From: Phil Reid Date: Fri, 15 Jan 2016 11:32:22 +0800 Subject: gpio: gpio-altera: Remove gpiochip on probe failure. On failure to setup the irq altera_gpio_probe would return an error but not go to cleanup. This resulted in kernel fault "Unable to handle kernel paging request at virtual address xxxxxxxx" later on in of_gpiochip_find_and_xlate. Signed-off-by: Phil Reid Signed-off-by: Linus Walleij --- drivers/gpio/gpio-altera.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c index 2aeaebd1c6e7..3f87a03abc22 100644 --- a/drivers/gpio/gpio-altera.c +++ b/drivers/gpio/gpio-altera.c @@ -312,8 +312,8 @@ static int altera_gpio_probe(struct platform_device *pdev) handle_simple_irq, IRQ_TYPE_NONE); if (ret) { - dev_info(&pdev->dev, "could not add irqchip\n"); - return ret; + dev_err(&pdev->dev, "could not add irqchip\n"); + goto teardown; } gpiochip_set_chained_irqchip(&altera_gc->mmchip.gc, @@ -326,6 +326,7 @@ static int altera_gpio_probe(struct platform_device *pdev) skip_irq: return 0; teardown: + of_mm_gpiochip_remove(&altera_gc->mmchip); pr_err("%s: registration failed with status %d\n", node->full_name, ret); -- cgit v1.2.3 From 8ba5905c163cbfcc4c21ecef7574626649977439 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Mon, 18 Jan 2016 16:38:31 +0100 Subject: pinctrl: st: activate strict mux mode This activates strict mode muxing for the ST pin controllers, as these do not allow GPIO and functions to use the same pin simultaneously. Signed-off-by: Patrice Chotard Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-st.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c index fac844a85cb4..cab66c64149f 100644 --- a/drivers/pinctrl/pinctrl-st.c +++ b/drivers/pinctrl/pinctrl-st.c @@ -985,6 +985,7 @@ static struct pinmux_ops st_pmxops = { .get_function_groups = st_pmx_get_groups, .set_mux = st_pmx_set_mux, .gpio_set_direction = st_pmx_set_gpio_direction, + .strict = true, }; /* Pinconf */ -- cgit v1.2.3 From ee03672d961bdac2ac1e593e9c29b0d3b7320409 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Tue, 26 Jan 2016 15:33:21 +0200 Subject: spi: pxa2xx: Print actual DMA/PIO transfer mode in debug messages Transfer debug messages don't actually show is the transfer really using DMA. Driver may fall back to PIO in case transfer size is not within the certain limits or fails to map DMA buffers but debug messages don't reveal that. Move these debug messages further in pump_transfers() where the actual transfer mode is known and use drv_data->dma_mapped flag instead of chip->enable_dma for printing the mode. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index ab9914ad8365..227e8bad19e6 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1001,19 +1001,6 @@ static void pump_transfers(unsigned long data) "pump_transfers: DMA burst size reduced to match bits_per_word\n"); } - /* NOTE: PXA25x_SSP _could_ use external clocking ... */ - cr0 = pxa2xx_configure_sscr0(drv_data, clk_div, bits); - if (!pxa25x_ssp_comp(drv_data)) - dev_dbg(&message->spi->dev, "%u Hz actual, %s\n", - drv_data->master->max_speed_hz - / (1 + ((cr0 & SSCR0_SCR(0xfff)) >> 8)), - chip->enable_dma ? "DMA" : "PIO"); - else - dev_dbg(&message->spi->dev, "%u Hz actual, %s\n", - drv_data->master->max_speed_hz / 2 - / (1 + ((cr0 & SSCR0_SCR(0x0ff)) >> 8)), - chip->enable_dma ? "DMA" : "PIO"); - message->state = RUNNING_STATE; drv_data->dma_mapped = 0; @@ -1040,6 +1027,19 @@ static void pump_transfers(unsigned long data) write_SSSR_CS(drv_data, drv_data->clear_sr); } + /* NOTE: PXA25x_SSP _could_ use external clocking ... */ + cr0 = pxa2xx_configure_sscr0(drv_data, clk_div, bits); + if (!pxa25x_ssp_comp(drv_data)) + dev_dbg(&message->spi->dev, "%u Hz actual, %s\n", + drv_data->master->max_speed_hz + / (1 + ((cr0 & SSCR0_SCR(0xfff)) >> 8)), + drv_data->dma_mapped ? "DMA" : "PIO"); + else + dev_dbg(&message->spi->dev, "%u Hz actual, %s\n", + drv_data->master->max_speed_hz / 2 + / (1 + ((cr0 & SSCR0_SCR(0x0ff)) >> 8)), + drv_data->dma_mapped ? "DMA" : "PIO"); + if (is_lpss_ssp(drv_data)) { if ((pxa2xx_spi_read(drv_data, SSIRF) & 0xff) != chip->lpss_rx_threshold) -- cgit v1.2.3 From 49f34134aea74f19ca016f055d25ee55ec359dee Mon Sep 17 00:00:00 2001 From: Milo Kim Date: Wed, 13 Jan 2016 16:19:50 +0900 Subject: irqchip/atmel-aic: Fix wrong bit operation for IRQ priority Atmel AIC has common structure for SMR (Source Mode Register). bit[6:5] Interrupt source type bit[2:0] Priority level Other bits are unused. To update new priority value, bit[2:0] should be cleared first and then new priority level can be written. However, aic_common_set_priority() helper clears source type bits instead of priority bits. This patch fixes wrong mask bit operation. Fixes: b1479ebb7720 "irqchip: atmel-aic: Add atmel AIC/AIC5 drivers" Signed-off-by: Milo Kim Acked-by: Boris Brezillon Cc: Jason Cooper Cc: Marc Zyngier Cc: Ludovic Desroches Cc: Nicholas Ferre Cc: stable@vger.kernel.org #v3.17+ Link: http://lkml.kernel.org/r/1452669592-3401-2-git-send-email-milo.kim@ti.com Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-atmel-aic-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-atmel-aic-common.c b/drivers/irqchip/irq-atmel-aic-common.c index b12a5d58546f..37199b9b2cfa 100644 --- a/drivers/irqchip/irq-atmel-aic-common.c +++ b/drivers/irqchip/irq-atmel-aic-common.c @@ -86,7 +86,7 @@ int aic_common_set_priority(int priority, unsigned *val) priority > AT91_AIC_IRQ_MAX_PRIORITY) return -EINVAL; - *val &= AT91_AIC_PRIOR; + *val &= ~AT91_AIC_PRIOR; *val |= priority; return 0; -- cgit v1.2.3 From 3a5242e648a8d009f0e0fd47867592e5265374b6 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 24 Jan 2016 04:25:13 +0900 Subject: pinctrl: pxa: export pxa2xx_pinctrl_init() Building pinctrl-pxa27x.c as a module causes a link error: ERROR: "pxa2xx_pinctrl_init" [drivers/pinctrl/pxa/pinctrl-pxa27x.ko] undefined! Signed-off-by: Masahiro Yamada Acked-by: Robert Jarzmik Signed-off-by: Linus Walleij --- drivers/pinctrl/pxa/pinctrl-pxa2xx.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/pinctrl/pxa/pinctrl-pxa2xx.c b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c index d90e205cf809..216f227c6009 100644 --- a/drivers/pinctrl/pxa/pinctrl-pxa2xx.c +++ b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c @@ -426,6 +426,7 @@ int pxa2xx_pinctrl_init(struct platform_device *pdev, return 0; } +EXPORT_SYMBOL(pxa2xx_pinctrl_init); int pxa2xx_pinctrl_exit(struct platform_device *pdev) { -- cgit v1.2.3 From 84a2c9319dca2cedad13a776c2bc88f41d6beddf Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:16:06 +0800 Subject: block: cryptoloop - Use new skcipher interface This patch replaces uses of blkcipher with the new skcipher interface. Signed-off-by: Herbert Xu --- drivers/block/cryptoloop.c | 48 ++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c index 99e773cb70d0..3d31761c0ed0 100644 --- a/drivers/block/cryptoloop.c +++ b/drivers/block/cryptoloop.c @@ -21,9 +21,9 @@ #include +#include #include #include -#include #include #include #include @@ -46,7 +46,7 @@ cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info) char *cipher; char *mode; char *cmsp = cms; /* c-m string pointer */ - struct crypto_blkcipher *tfm; + struct crypto_skcipher *tfm; /* encryption breaks for non sector aligned offsets */ @@ -82,12 +82,12 @@ cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info) *cmsp++ = ')'; *cmsp = 0; - tfm = crypto_alloc_blkcipher(cms, 0, CRYPTO_ALG_ASYNC); + tfm = crypto_alloc_skcipher(cms, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) return PTR_ERR(tfm); - err = crypto_blkcipher_setkey(tfm, info->lo_encrypt_key, - info->lo_encrypt_key_size); + err = crypto_skcipher_setkey(tfm, info->lo_encrypt_key, + info->lo_encrypt_key_size); if (err != 0) goto out_free_tfm; @@ -96,17 +96,14 @@ cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info) return 0; out_free_tfm: - crypto_free_blkcipher(tfm); + crypto_free_skcipher(tfm); out: return err; } -typedef int (*encdec_cbc_t)(struct blkcipher_desc *desc, - struct scatterlist *sg_out, - struct scatterlist *sg_in, - unsigned int nsg); +typedef int (*encdec_cbc_t)(struct skcipher_request *req); static int cryptoloop_transfer(struct loop_device *lo, int cmd, @@ -114,11 +111,8 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, struct page *loop_page, unsigned loop_off, int size, sector_t IV) { - struct crypto_blkcipher *tfm = lo->key_data; - struct blkcipher_desc desc = { - .tfm = tfm, - .flags = CRYPTO_TFM_REQ_MAY_SLEEP, - }; + struct crypto_skcipher *tfm = lo->key_data; + SKCIPHER_REQUEST_ON_STACK(req, tfm); struct scatterlist sg_out; struct scatterlist sg_in; @@ -127,6 +121,10 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, unsigned in_offs, out_offs; int err; + skcipher_request_set_tfm(req, tfm); + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, + NULL, NULL); + sg_init_table(&sg_out, 1); sg_init_table(&sg_in, 1); @@ -135,13 +133,13 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, in_offs = raw_off; out_page = loop_page; out_offs = loop_off; - encdecfunc = crypto_blkcipher_crt(tfm)->decrypt; + encdecfunc = crypto_skcipher_decrypt; } else { in_page = loop_page; in_offs = loop_off; out_page = raw_page; out_offs = raw_off; - encdecfunc = crypto_blkcipher_crt(tfm)->encrypt; + encdecfunc = crypto_skcipher_encrypt; } while (size > 0) { @@ -152,10 +150,10 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, sg_set_page(&sg_in, in_page, sz, in_offs); sg_set_page(&sg_out, out_page, sz, out_offs); - desc.info = iv; - err = encdecfunc(&desc, &sg_out, &sg_in, sz); + skcipher_request_set_crypt(req, &sg_in, &sg_out, sz, iv); + err = encdecfunc(req); if (err) - return err; + goto out; IV++; size -= sz; @@ -163,7 +161,11 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, out_offs += sz; } - return 0; + err = 0; + +out: + skcipher_request_zero(req); + return err; } static int @@ -175,9 +177,9 @@ cryptoloop_ioctl(struct loop_device *lo, int cmd, unsigned long arg) static int cryptoloop_release(struct loop_device *lo) { - struct crypto_blkcipher *tfm = lo->key_data; + struct crypto_skcipher *tfm = lo->key_data; if (tfm != NULL) { - crypto_free_blkcipher(tfm); + crypto_free_skcipher(tfm); lo->key_data = NULL; return 0; } -- cgit v1.2.3 From fdb89b1b8f814260fd8239b1e09edf9e12c97ef2 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:16:16 +0800 Subject: ppp_mppe: Use skcipher and ahash This patch replaces uses of blkcipher with skcipher, and the long obsolete hash interface with ahash. This is a bug-for-bug conversion and no attempt has been made to fix bugs such as the ignored return values of the crypto operations. Signed-off-by: Herbert Xu --- drivers/net/ppp/ppp_mppe.c | 99 +++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ppp/ppp_mppe.c b/drivers/net/ppp/ppp_mppe.c index 05005c660d4d..f60f7660b451 100644 --- a/drivers/net/ppp/ppp_mppe.c +++ b/drivers/net/ppp/ppp_mppe.c @@ -42,6 +42,8 @@ * deprecated in 2.6 */ +#include +#include #include #include #include @@ -49,7 +51,6 @@ #include #include #include -#include #include #include #include @@ -94,8 +95,8 @@ static inline void sha_pad_init(struct sha_pad *shapad) * State for an MPPE (de)compressor. */ struct ppp_mppe_state { - struct crypto_blkcipher *arc4; - struct crypto_hash *sha1; + struct crypto_skcipher *arc4; + struct crypto_ahash *sha1; unsigned char *sha1_digest; unsigned char master_key[MPPE_MAX_KEY_LEN]; unsigned char session_key[MPPE_MAX_KEY_LEN]; @@ -135,7 +136,7 @@ struct ppp_mppe_state { */ static void get_new_key_from_sha(struct ppp_mppe_state * state) { - struct hash_desc desc; + AHASH_REQUEST_ON_STACK(req, state->sha1); struct scatterlist sg[4]; unsigned int nbytes; @@ -148,10 +149,12 @@ static void get_new_key_from_sha(struct ppp_mppe_state * state) nbytes += setup_sg(&sg[3], sha_pad->sha_pad2, sizeof(sha_pad->sha_pad2)); - desc.tfm = state->sha1; - desc.flags = 0; + ahash_request_set_tfm(req, state->sha1); + ahash_request_set_callback(req, 0, NULL, NULL); + ahash_request_set_crypt(req, sg, state->sha1_digest, nbytes); - crypto_hash_digest(&desc, sg, nbytes, state->sha1_digest); + crypto_ahash_digest(req); + ahash_request_zero(req); } /* @@ -161,20 +164,23 @@ static void get_new_key_from_sha(struct ppp_mppe_state * state) static void mppe_rekey(struct ppp_mppe_state * state, int initial_key) { struct scatterlist sg_in[1], sg_out[1]; - struct blkcipher_desc desc = { .tfm = state->arc4 }; + SKCIPHER_REQUEST_ON_STACK(req, state->arc4); + + skcipher_request_set_tfm(req, state->arc4); + skcipher_request_set_callback(req, 0, NULL, NULL); get_new_key_from_sha(state); if (!initial_key) { - crypto_blkcipher_setkey(state->arc4, state->sha1_digest, - state->keylen); + crypto_skcipher_setkey(state->arc4, state->sha1_digest, + state->keylen); sg_init_table(sg_in, 1); sg_init_table(sg_out, 1); setup_sg(sg_in, state->sha1_digest, state->keylen); setup_sg(sg_out, state->session_key, state->keylen); - if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in, - state->keylen) != 0) { + skcipher_request_set_crypt(req, sg_in, sg_out, state->keylen, + NULL); + if (crypto_skcipher_encrypt(req)) printk(KERN_WARNING "mppe_rekey: cipher_encrypt failed\n"); - } } else { memcpy(state->session_key, state->sha1_digest, state->keylen); } @@ -184,7 +190,8 @@ static void mppe_rekey(struct ppp_mppe_state * state, int initial_key) state->session_key[1] = 0x26; state->session_key[2] = 0x9e; } - crypto_blkcipher_setkey(state->arc4, state->session_key, state->keylen); + crypto_skcipher_setkey(state->arc4, state->session_key, state->keylen); + skcipher_request_zero(req); } /* @@ -204,19 +211,19 @@ static void *mppe_alloc(unsigned char *options, int optlen) goto out; - state->arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + state->arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(state->arc4)) { state->arc4 = NULL; goto out_free; } - state->sha1 = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); + state->sha1 = crypto_alloc_ahash("sha1", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(state->sha1)) { state->sha1 = NULL; goto out_free; } - digestsize = crypto_hash_digestsize(state->sha1); + digestsize = crypto_ahash_digestsize(state->sha1); if (digestsize < MPPE_MAX_KEY_LEN) goto out_free; @@ -237,15 +244,12 @@ static void *mppe_alloc(unsigned char *options, int optlen) return (void *)state; - out_free: - if (state->sha1_digest) - kfree(state->sha1_digest); - if (state->sha1) - crypto_free_hash(state->sha1); - if (state->arc4) - crypto_free_blkcipher(state->arc4); - kfree(state); - out: +out_free: + kfree(state->sha1_digest); + crypto_free_ahash(state->sha1); + crypto_free_skcipher(state->arc4); + kfree(state); +out: return NULL; } @@ -256,13 +260,10 @@ static void mppe_free(void *arg) { struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; if (state) { - if (state->sha1_digest) kfree(state->sha1_digest); - if (state->sha1) - crypto_free_hash(state->sha1); - if (state->arc4) - crypto_free_blkcipher(state->arc4); - kfree(state); + crypto_free_ahash(state->sha1); + crypto_free_skcipher(state->arc4); + kfree(state); } } @@ -368,8 +369,9 @@ mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf, int isize, int osize) { struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; - struct blkcipher_desc desc = { .tfm = state->arc4 }; + SKCIPHER_REQUEST_ON_STACK(req, state->arc4); int proto; + int err; struct scatterlist sg_in[1], sg_out[1]; /* @@ -426,7 +428,13 @@ mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf, sg_init_table(sg_out, 1); setup_sg(sg_in, ibuf, isize); setup_sg(sg_out, obuf, osize); - if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in, isize) != 0) { + + skcipher_request_set_tfm(req, state->arc4); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg_in, sg_out, isize, NULL); + err = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); + if (err) { printk(KERN_DEBUG "crypto_cypher_encrypt failed\n"); return -1; } @@ -475,7 +483,7 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, int osize) { struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; - struct blkcipher_desc desc = { .tfm = state->arc4 }; + SKCIPHER_REQUEST_ON_STACK(req, state->arc4); unsigned ccount; int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED; struct scatterlist sg_in[1], sg_out[1]; @@ -609,9 +617,14 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, sg_init_table(sg_out, 1); setup_sg(sg_in, ibuf, 1); setup_sg(sg_out, obuf, 1); - if (crypto_blkcipher_decrypt(&desc, sg_out, sg_in, 1) != 0) { + + skcipher_request_set_tfm(req, state->arc4); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg_in, sg_out, 1, NULL); + if (crypto_skcipher_decrypt(req)) { printk(KERN_DEBUG "crypto_cypher_decrypt failed\n"); - return DECOMP_ERROR; + osize = DECOMP_ERROR; + goto out_zap_req; } /* @@ -629,9 +642,11 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, /* And finally, decrypt the rest of the packet. */ setup_sg(sg_in, ibuf + 1, isize - 1); setup_sg(sg_out, obuf + 1, osize - 1); - if (crypto_blkcipher_decrypt(&desc, sg_out, sg_in, isize - 1)) { + skcipher_request_set_crypt(req, sg_in, sg_out, isize - 1, NULL); + if (crypto_skcipher_decrypt(req)) { printk(KERN_DEBUG "crypto_cypher_decrypt failed\n"); - return DECOMP_ERROR; + osize = DECOMP_ERROR; + goto out_zap_req; } state->stats.unc_bytes += osize; @@ -642,6 +657,8 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, /* good packet credit */ state->sanity_errors >>= 1; +out_zap_req: + skcipher_request_zero(req); return osize; sanity_error: @@ -714,8 +731,8 @@ static struct compressor ppp_mppe = { static int __init ppp_mppe_init(void) { int answer; - if (!(crypto_has_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC) && - crypto_has_hash("sha1", 0, CRYPTO_ALG_ASYNC))) + if (!(crypto_has_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC) && + crypto_has_ahash("sha1", 0, CRYPTO_ALG_ASYNC))) return -ENODEV; sha_pad = kmalloc(sizeof(struct sha_pad), GFP_KERNEL); -- cgit v1.2.3 From a1d383943fdd4279c852b0e5718bcf13a923e4dc Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:16:26 +0800 Subject: staging: rtl8192e: Replace uses of obsolete blkcipher and hash The interfaces blkcipher and hash are obsolete. This patch replaces them with skcipher and ahash respectively. Signed-off-by: Herbert Xu Acked-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_crypt_tkip.c | 99 +++++++++++++++------------- drivers/staging/rtl8192e/rtllib_crypt_wep.c | 48 ++++++++------ 2 files changed, 82 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c index 2096d78913bd..8eac7cdd5f3e 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c @@ -9,6 +9,8 @@ * more details. */ +#include +#include #include #include #include @@ -18,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -48,10 +49,10 @@ struct rtllib_tkip_data { u32 dot11RSNAStatsTKIPLocalMICFailures; int key_idx; - struct crypto_blkcipher *rx_tfm_arc4; - struct crypto_hash *rx_tfm_michael; - struct crypto_blkcipher *tx_tfm_arc4; - struct crypto_hash *tx_tfm_michael; + struct crypto_skcipher *rx_tfm_arc4; + struct crypto_ahash *rx_tfm_michael; + struct crypto_skcipher *tx_tfm_arc4; + struct crypto_ahash *tx_tfm_michael; /* scratch buffers for virt_to_page() (crypto API) */ u8 rx_hdr[16]; u8 tx_hdr[16]; @@ -65,32 +66,32 @@ static void *rtllib_tkip_init(int key_idx) if (priv == NULL) goto fail; priv->key_idx = key_idx; - priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, - CRYPTO_ALG_ASYNC); + priv->tx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm_arc4)) { pr_debug("Could not allocate crypto API arc4\n"); priv->tx_tfm_arc4 = NULL; goto fail; } - priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0, - CRYPTO_ALG_ASYNC); + priv->tx_tfm_michael = crypto_alloc_ahash("michael_mic", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm_michael)) { pr_debug("Could not allocate crypto API michael_mic\n"); priv->tx_tfm_michael = NULL; goto fail; } - priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, - CRYPTO_ALG_ASYNC); + priv->rx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm_arc4)) { pr_debug("Could not allocate crypto API arc4\n"); priv->rx_tfm_arc4 = NULL; goto fail; } - priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0, - CRYPTO_ALG_ASYNC); + priv->rx_tfm_michael = crypto_alloc_ahash("michael_mic", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm_michael)) { pr_debug("Could not allocate crypto API michael_mic\n"); priv->rx_tfm_michael = NULL; @@ -100,14 +101,10 @@ static void *rtllib_tkip_init(int key_idx) fail: if (priv) { - if (priv->tx_tfm_michael) - crypto_free_hash(priv->tx_tfm_michael); - if (priv->tx_tfm_arc4) - crypto_free_blkcipher(priv->tx_tfm_arc4); - if (priv->rx_tfm_michael) - crypto_free_hash(priv->rx_tfm_michael); - if (priv->rx_tfm_arc4) - crypto_free_blkcipher(priv->rx_tfm_arc4); + crypto_free_ahash(priv->tx_tfm_michael); + crypto_free_skcipher(priv->tx_tfm_arc4); + crypto_free_ahash(priv->rx_tfm_michael); + crypto_free_skcipher(priv->rx_tfm_arc4); kfree(priv); } @@ -120,14 +117,10 @@ static void rtllib_tkip_deinit(void *priv) struct rtllib_tkip_data *_priv = priv; if (_priv) { - if (_priv->tx_tfm_michael) - crypto_free_hash(_priv->tx_tfm_michael); - if (_priv->tx_tfm_arc4) - crypto_free_blkcipher(_priv->tx_tfm_arc4); - if (_priv->rx_tfm_michael) - crypto_free_hash(_priv->rx_tfm_michael); - if (_priv->rx_tfm_arc4) - crypto_free_blkcipher(_priv->rx_tfm_arc4); + crypto_free_ahash(_priv->tx_tfm_michael); + crypto_free_skcipher(_priv->tx_tfm_arc4); + crypto_free_ahash(_priv->rx_tfm_michael); + crypto_free_skcipher(_priv->rx_tfm_arc4); } kfree(priv); } @@ -301,7 +294,6 @@ static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) struct rtllib_hdr_4addr *hdr; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4}; int ret = 0; u8 rc4key[16], *icv; u32 crc; @@ -347,6 +339,8 @@ static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) *pos++ = (tkey->tx_iv32 >> 24) & 0xff; if (!tcb_desc->bHwSec) { + SKCIPHER_REQUEST_ON_STACK(req, tkey->tx_tfm_arc4); + icv = skb_put(skb, 4); crc = ~crc32_le(~0, pos, len); icv[0] = crc; @@ -357,8 +351,12 @@ static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) sg_init_one(&sg, pos, len+4); - crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); - ret = crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); + crypto_skcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); + skcipher_request_set_tfm(req, tkey->tx_tfm_arc4); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); + ret = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); } tkey->tx_iv16++; @@ -384,12 +382,12 @@ static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) struct rtllib_hdr_4addr *hdr; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - struct blkcipher_desc desc = {.tfm = tkey->rx_tfm_arc4}; u8 rc4key[16]; u8 icv[4]; u32 crc; struct scatterlist sg; int plen; + int err; if (skb->len < hdr_len + 8 + 4) return -1; @@ -425,6 +423,8 @@ static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) pos += 8; if (!tcb_desc->bHwSec || (skb->cb[0] == 1)) { + SKCIPHER_REQUEST_ON_STACK(req, tkey->rx_tfm_arc4); + if ((iv32 < tkey->rx_iv32 || (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) && tkey->initialized) { @@ -450,8 +450,13 @@ static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) sg_init_one(&sg, pos, plen+4); - crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); - if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) { + crypto_skcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); + skcipher_request_set_tfm(req, tkey->rx_tfm_arc4); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, plen + 4, NULL); + err = crypto_skcipher_decrypt(req); + skcipher_request_zero(req); + if (err) { if (net_ratelimit()) { netdev_dbg(skb->dev, "Failed to decrypt received packet from %pM\n", @@ -500,11 +505,12 @@ static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) } -static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr, +static int michael_mic(struct crypto_ahash *tfm_michael, u8 *key, u8 *hdr, u8 *data, size_t data_len, u8 *mic) { - struct hash_desc desc; + AHASH_REQUEST_ON_STACK(req, tfm_michael); struct scatterlist sg[2]; + int err; if (tfm_michael == NULL) { pr_warn("michael_mic: tfm_michael == NULL\n"); @@ -514,12 +520,15 @@ static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr, sg_set_buf(&sg[0], hdr, 16); sg_set_buf(&sg[1], data, data_len); - if (crypto_hash_setkey(tfm_michael, key, 8)) + if (crypto_ahash_setkey(tfm_michael, key, 8)) return -1; - desc.tfm = tfm_michael; - desc.flags = 0; - return crypto_hash_digest(&desc, sg, data_len + 16, mic); + ahash_request_set_tfm(req, tfm_michael); + ahash_request_set_callback(req, 0, NULL, NULL); + ahash_request_set_crypt(req, sg, mic, data_len + 16); + err = crypto_ahash_digest(req); + ahash_request_zero(req); + return err; } static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) @@ -655,10 +664,10 @@ static int rtllib_tkip_set_key(void *key, int len, u8 *seq, void *priv) { struct rtllib_tkip_data *tkey = priv; int keyidx; - struct crypto_hash *tfm = tkey->tx_tfm_michael; - struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4; - struct crypto_hash *tfm3 = tkey->rx_tfm_michael; - struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4; + struct crypto_ahash *tfm = tkey->tx_tfm_michael; + struct crypto_skcipher *tfm2 = tkey->tx_tfm_arc4; + struct crypto_ahash *tfm3 = tkey->rx_tfm_michael; + struct crypto_skcipher *tfm4 = tkey->rx_tfm_arc4; keyidx = tkey->key_idx; memset(tkey, 0, sizeof(*tkey)); diff --git a/drivers/staging/rtl8192e/rtllib_crypt_wep.c b/drivers/staging/rtl8192e/rtllib_crypt_wep.c index 21d7eee4c9a9..b3343a5d0fd6 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_wep.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_wep.c @@ -9,6 +9,7 @@ * more details. */ +#include #include #include #include @@ -17,8 +18,6 @@ #include #include "rtllib.h" -#include - #include #include @@ -28,8 +27,8 @@ struct prism2_wep_data { u8 key[WEP_KEY_LEN + 1]; u8 key_len; u8 key_idx; - struct crypto_blkcipher *tx_tfm; - struct crypto_blkcipher *rx_tfm; + struct crypto_skcipher *tx_tfm; + struct crypto_skcipher *rx_tfm; }; @@ -42,13 +41,13 @@ static void *prism2_wep_init(int keyidx) goto fail; priv->key_idx = keyidx; - priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + priv->tx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm)) { pr_debug("rtllib_crypt_wep: could not allocate crypto API arc4\n"); priv->tx_tfm = NULL; goto fail; } - priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + priv->rx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm)) { pr_debug("rtllib_crypt_wep: could not allocate crypto API arc4\n"); priv->rx_tfm = NULL; @@ -62,10 +61,8 @@ static void *prism2_wep_init(int keyidx) fail: if (priv) { - if (priv->tx_tfm) - crypto_free_blkcipher(priv->tx_tfm); - if (priv->rx_tfm) - crypto_free_blkcipher(priv->rx_tfm); + crypto_free_skcipher(priv->tx_tfm); + crypto_free_skcipher(priv->rx_tfm); kfree(priv); } return NULL; @@ -77,10 +74,8 @@ static void prism2_wep_deinit(void *priv) struct prism2_wep_data *_priv = priv; if (_priv) { - if (_priv->tx_tfm) - crypto_free_blkcipher(_priv->tx_tfm); - if (_priv->rx_tfm) - crypto_free_blkcipher(_priv->rx_tfm); + crypto_free_skcipher(_priv->tx_tfm); + crypto_free_skcipher(_priv->rx_tfm); } kfree(priv); } @@ -99,10 +94,10 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) u8 *pos; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - struct blkcipher_desc desc = {.tfm = wep->tx_tfm}; u32 crc; u8 *icv; struct scatterlist sg; + int err; if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 || skb->len < hdr_len){ @@ -140,6 +135,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) memcpy(key + 3, wep->key, wep->key_len); if (!tcb_desc->bHwSec) { + SKCIPHER_REQUEST_ON_STACK(req, wep->tx_tfm); /* Append little-endian CRC32 and encrypt it to produce ICV */ crc = ~crc32_le(~0, pos, len); @@ -150,8 +146,13 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[3] = crc >> 24; sg_init_one(&sg, pos, len+4); - crypto_blkcipher_setkey(wep->tx_tfm, key, klen); - return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); + crypto_skcipher_setkey(wep->tx_tfm, key, klen); + skcipher_request_set_tfm(req, wep->tx_tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); + err = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); + return err; } return 0; @@ -173,10 +174,10 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) u8 keyidx, *pos; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - struct blkcipher_desc desc = {.tfm = wep->rx_tfm}; u32 crc; u8 icv[4]; struct scatterlist sg; + int err; if (skb->len < hdr_len + 8) return -1; @@ -198,9 +199,16 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) plen = skb->len - hdr_len - 8; if (!tcb_desc->bHwSec) { + SKCIPHER_REQUEST_ON_STACK(req, wep->rx_tfm); + sg_init_one(&sg, pos, plen+4); - crypto_blkcipher_setkey(wep->rx_tfm, key, klen); - if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) + crypto_skcipher_setkey(wep->rx_tfm, key, klen); + skcipher_request_set_tfm(req, wep->rx_tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, plen + 4, NULL); + err = crypto_skcipher_decrypt(req); + skcipher_request_zero(req); + if (err) return -7; crc = ~crc32_le(~0, pos, plen); icv[0] = crc; -- cgit v1.2.3 From bbdb23b5d69521a2e3059b33d1f6ed8e1216118a Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:16:36 +0800 Subject: dm crypt: Use skcipher and ahash This patch replaces uses of ablkcipher with skcipher, and the long obsolete hash interface with ahash. Signed-off-by: Herbert Xu --- drivers/md/dm-crypt.c | 93 ++++++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 3147c8d09ea8..06a4e3cfc66a 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -44,7 +45,7 @@ struct convert_context { struct bvec_iter iter_out; sector_t cc_sector; atomic_t cc_pending; - struct ablkcipher_request *req; + struct skcipher_request *req; }; /* @@ -86,7 +87,7 @@ struct crypt_iv_operations { }; struct iv_essiv_private { - struct crypto_hash *hash_tfm; + struct crypto_ahash *hash_tfm; u8 *salt; }; @@ -153,13 +154,13 @@ struct crypt_config { /* ESSIV: struct crypto_cipher *essiv_tfm */ void *iv_private; - struct crypto_ablkcipher **tfms; + struct crypto_skcipher **tfms; unsigned tfms_count; /* * Layout of each crypto request: * - * struct ablkcipher_request + * struct skcipher_request * context * padding * struct dm_crypt_request @@ -189,7 +190,7 @@ static u8 *iv_of_dmreq(struct crypt_config *cc, struct dm_crypt_request *dmreq); /* * Use this to access cipher attributes that are the same for each CPU. */ -static struct crypto_ablkcipher *any_tfm(struct crypt_config *cc) +static struct crypto_skcipher *any_tfm(struct crypt_config *cc) { return cc->tfms[0]; } @@ -263,23 +264,25 @@ static int crypt_iv_plain64_gen(struct crypt_config *cc, u8 *iv, static int crypt_iv_essiv_init(struct crypt_config *cc) { struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; - struct hash_desc desc; + AHASH_REQUEST_ON_STACK(req, essiv->hash_tfm); struct scatterlist sg; struct crypto_cipher *essiv_tfm; int err; sg_init_one(&sg, cc->key, cc->key_size); - desc.tfm = essiv->hash_tfm; - desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; + ahash_request_set_tfm(req, essiv->hash_tfm); + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); + ahash_request_set_crypt(req, &sg, essiv->salt, cc->key_size); - err = crypto_hash_digest(&desc, &sg, cc->key_size, essiv->salt); + err = crypto_ahash_digest(req); + ahash_request_zero(req); if (err) return err; essiv_tfm = cc->iv_private; err = crypto_cipher_setkey(essiv_tfm, essiv->salt, - crypto_hash_digestsize(essiv->hash_tfm)); + crypto_ahash_digestsize(essiv->hash_tfm)); if (err) return err; @@ -290,7 +293,7 @@ static int crypt_iv_essiv_init(struct crypt_config *cc) static int crypt_iv_essiv_wipe(struct crypt_config *cc) { struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; - unsigned salt_size = crypto_hash_digestsize(essiv->hash_tfm); + unsigned salt_size = crypto_ahash_digestsize(essiv->hash_tfm); struct crypto_cipher *essiv_tfm; int r, err = 0; @@ -320,7 +323,7 @@ static struct crypto_cipher *setup_essiv_cpu(struct crypt_config *cc, } if (crypto_cipher_blocksize(essiv_tfm) != - crypto_ablkcipher_ivsize(any_tfm(cc))) { + crypto_skcipher_ivsize(any_tfm(cc))) { ti->error = "Block size of ESSIV cipher does " "not match IV size of block cipher"; crypto_free_cipher(essiv_tfm); @@ -342,7 +345,7 @@ static void crypt_iv_essiv_dtr(struct crypt_config *cc) struct crypto_cipher *essiv_tfm; struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; - crypto_free_hash(essiv->hash_tfm); + crypto_free_ahash(essiv->hash_tfm); essiv->hash_tfm = NULL; kzfree(essiv->salt); @@ -360,7 +363,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, const char *opts) { struct crypto_cipher *essiv_tfm = NULL; - struct crypto_hash *hash_tfm = NULL; + struct crypto_ahash *hash_tfm = NULL; u8 *salt = NULL; int err; @@ -370,14 +373,14 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, } /* Allocate hash algorithm */ - hash_tfm = crypto_alloc_hash(opts, 0, CRYPTO_ALG_ASYNC); + hash_tfm = crypto_alloc_ahash(opts, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(hash_tfm)) { ti->error = "Error initializing ESSIV hash"; err = PTR_ERR(hash_tfm); goto bad; } - salt = kzalloc(crypto_hash_digestsize(hash_tfm), GFP_KERNEL); + salt = kzalloc(crypto_ahash_digestsize(hash_tfm), GFP_KERNEL); if (!salt) { ti->error = "Error kmallocing salt storage in ESSIV"; err = -ENOMEM; @@ -388,7 +391,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, cc->iv_gen_private.essiv.hash_tfm = hash_tfm; essiv_tfm = setup_essiv_cpu(cc, ti, salt, - crypto_hash_digestsize(hash_tfm)); + crypto_ahash_digestsize(hash_tfm)); if (IS_ERR(essiv_tfm)) { crypt_iv_essiv_dtr(cc); return PTR_ERR(essiv_tfm); @@ -399,7 +402,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, bad: if (hash_tfm && !IS_ERR(hash_tfm)) - crypto_free_hash(hash_tfm); + crypto_free_ahash(hash_tfm); kfree(salt); return err; } @@ -419,7 +422,7 @@ static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti, const char *opts) { - unsigned bs = crypto_ablkcipher_blocksize(any_tfm(cc)); + unsigned bs = crypto_skcipher_blocksize(any_tfm(cc)); int log = ilog2(bs); /* we need to calculate how far we must shift the sector count @@ -816,27 +819,27 @@ static void crypt_convert_init(struct crypt_config *cc, } static struct dm_crypt_request *dmreq_of_req(struct crypt_config *cc, - struct ablkcipher_request *req) + struct skcipher_request *req) { return (struct dm_crypt_request *)((char *)req + cc->dmreq_start); } -static struct ablkcipher_request *req_of_dmreq(struct crypt_config *cc, +static struct skcipher_request *req_of_dmreq(struct crypt_config *cc, struct dm_crypt_request *dmreq) { - return (struct ablkcipher_request *)((char *)dmreq - cc->dmreq_start); + return (struct skcipher_request *)((char *)dmreq - cc->dmreq_start); } static u8 *iv_of_dmreq(struct crypt_config *cc, struct dm_crypt_request *dmreq) { return (u8 *)ALIGN((unsigned long)(dmreq + 1), - crypto_ablkcipher_alignmask(any_tfm(cc)) + 1); + crypto_skcipher_alignmask(any_tfm(cc)) + 1); } static int crypt_convert_block(struct crypt_config *cc, struct convert_context *ctx, - struct ablkcipher_request *req) + struct skcipher_request *req) { struct bio_vec bv_in = bio_iter_iovec(ctx->bio_in, ctx->iter_in); struct bio_vec bv_out = bio_iter_iovec(ctx->bio_out, ctx->iter_out); @@ -866,13 +869,13 @@ static int crypt_convert_block(struct crypt_config *cc, return r; } - ablkcipher_request_set_crypt(req, &dmreq->sg_in, &dmreq->sg_out, - 1 << SECTOR_SHIFT, iv); + skcipher_request_set_crypt(req, &dmreq->sg_in, &dmreq->sg_out, + 1 << SECTOR_SHIFT, iv); if (bio_data_dir(ctx->bio_in) == WRITE) - r = crypto_ablkcipher_encrypt(req); + r = crypto_skcipher_encrypt(req); else - r = crypto_ablkcipher_decrypt(req); + r = crypto_skcipher_decrypt(req); if (!r && cc->iv_gen_ops && cc->iv_gen_ops->post) r = cc->iv_gen_ops->post(cc, iv, dmreq); @@ -891,23 +894,23 @@ static void crypt_alloc_req(struct crypt_config *cc, if (!ctx->req) ctx->req = mempool_alloc(cc->req_pool, GFP_NOIO); - ablkcipher_request_set_tfm(ctx->req, cc->tfms[key_index]); + skcipher_request_set_tfm(ctx->req, cc->tfms[key_index]); /* * Use REQ_MAY_BACKLOG so a cipher driver internally backlogs * requests if driver request queue is full. */ - ablkcipher_request_set_callback(ctx->req, + skcipher_request_set_callback(ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, kcryptd_async_done, dmreq_of_req(cc, ctx->req)); } static void crypt_free_req(struct crypt_config *cc, - struct ablkcipher_request *req, struct bio *base_bio) + struct skcipher_request *req, struct bio *base_bio) { struct dm_crypt_io *io = dm_per_bio_data(base_bio, cc->per_bio_data_size); - if ((struct ablkcipher_request *)(io + 1) != req) + if ((struct skcipher_request *)(io + 1) != req) mempool_free(req, cc->req_pool); } @@ -1437,7 +1440,7 @@ static void crypt_free_tfms(struct crypt_config *cc) for (i = 0; i < cc->tfms_count; i++) if (cc->tfms[i] && !IS_ERR(cc->tfms[i])) { - crypto_free_ablkcipher(cc->tfms[i]); + crypto_free_skcipher(cc->tfms[i]); cc->tfms[i] = NULL; } @@ -1450,13 +1453,13 @@ static int crypt_alloc_tfms(struct crypt_config *cc, char *ciphermode) unsigned i; int err; - cc->tfms = kmalloc(cc->tfms_count * sizeof(struct crypto_ablkcipher *), + cc->tfms = kmalloc(cc->tfms_count * sizeof(struct crypto_skcipher *), GFP_KERNEL); if (!cc->tfms) return -ENOMEM; for (i = 0; i < cc->tfms_count; i++) { - cc->tfms[i] = crypto_alloc_ablkcipher(ciphermode, 0, 0); + cc->tfms[i] = crypto_alloc_skcipher(ciphermode, 0, 0); if (IS_ERR(cc->tfms[i])) { err = PTR_ERR(cc->tfms[i]); crypt_free_tfms(cc); @@ -1476,9 +1479,9 @@ static int crypt_setkey_allcpus(struct crypt_config *cc) subkey_size = (cc->key_size - cc->key_extra_size) >> ilog2(cc->tfms_count); for (i = 0; i < cc->tfms_count; i++) { - r = crypto_ablkcipher_setkey(cc->tfms[i], - cc->key + (i * subkey_size), - subkey_size); + r = crypto_skcipher_setkey(cc->tfms[i], + cc->key + (i * subkey_size), + subkey_size); if (r) err = r; } @@ -1645,7 +1648,7 @@ static int crypt_ctr_cipher(struct dm_target *ti, } /* Initialize IV */ - cc->iv_size = crypto_ablkcipher_ivsize(any_tfm(cc)); + cc->iv_size = crypto_skcipher_ivsize(any_tfm(cc)); if (cc->iv_size) /* at least a 64 bit sector number should fit in our buffer */ cc->iv_size = max(cc->iv_size, @@ -1763,21 +1766,21 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) if (ret < 0) goto bad; - cc->dmreq_start = sizeof(struct ablkcipher_request); - cc->dmreq_start += crypto_ablkcipher_reqsize(any_tfm(cc)); + cc->dmreq_start = sizeof(struct skcipher_request); + cc->dmreq_start += crypto_skcipher_reqsize(any_tfm(cc)); cc->dmreq_start = ALIGN(cc->dmreq_start, __alignof__(struct dm_crypt_request)); - if (crypto_ablkcipher_alignmask(any_tfm(cc)) < CRYPTO_MINALIGN) { + if (crypto_skcipher_alignmask(any_tfm(cc)) < CRYPTO_MINALIGN) { /* Allocate the padding exactly */ iv_size_padding = -(cc->dmreq_start + sizeof(struct dm_crypt_request)) - & crypto_ablkcipher_alignmask(any_tfm(cc)); + & crypto_skcipher_alignmask(any_tfm(cc)); } else { /* * If the cipher requires greater alignment than kmalloc * alignment, we don't know the exact position of the * initialization vector. We must assume worst case. */ - iv_size_padding = crypto_ablkcipher_alignmask(any_tfm(cc)); + iv_size_padding = crypto_skcipher_alignmask(any_tfm(cc)); } ret = -ENOMEM; @@ -1922,7 +1925,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio) io = dm_per_bio_data(bio, cc->per_bio_data_size); crypt_io_init(io, cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector)); - io->ctx.req = (struct ablkcipher_request *)(io + 1); + io->ctx.req = (struct skcipher_request *)(io + 1); if (bio_data_dir(io->base_bio) == READ) { if (kcryptd_io_read(io, GFP_NOWAIT)) -- cgit v1.2.3 From a60b7fafd2d3ab51cf085e816627cbb4ef2f311b Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:16:47 +0800 Subject: orinoco: Use ahash This patch replaces uses the long obsolete hash interface with ahash. Signed-off-by: Herbert Xu --- drivers/net/wireless/intersil/orinoco/mic.c | 29 +++++++++++++++---------- drivers/net/wireless/intersil/orinoco/mic.h | 4 ++-- drivers/net/wireless/intersil/orinoco/orinoco.h | 4 ++-- 3 files changed, 21 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intersil/orinoco/mic.c b/drivers/net/wireless/intersil/orinoco/mic.c index fce4a843e656..bc7397d709d3 100644 --- a/drivers/net/wireless/intersil/orinoco/mic.c +++ b/drivers/net/wireless/intersil/orinoco/mic.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include "orinoco.h" #include "mic.h" @@ -16,7 +16,8 @@ /********************************************************************/ int orinoco_mic_init(struct orinoco_private *priv) { - priv->tx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0); + priv->tx_tfm_mic = crypto_alloc_ahash("michael_mic", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm_mic)) { printk(KERN_DEBUG "orinoco_mic_init: could not allocate " "crypto API michael_mic\n"); @@ -24,7 +25,8 @@ int orinoco_mic_init(struct orinoco_private *priv) return -ENOMEM; } - priv->rx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0); + priv->rx_tfm_mic = crypto_alloc_ahash("michael_mic", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm_mic)) { printk(KERN_DEBUG "orinoco_mic_init: could not allocate " "crypto API michael_mic\n"); @@ -38,18 +40,19 @@ int orinoco_mic_init(struct orinoco_private *priv) void orinoco_mic_free(struct orinoco_private *priv) { if (priv->tx_tfm_mic) - crypto_free_hash(priv->tx_tfm_mic); + crypto_free_ahash(priv->tx_tfm_mic); if (priv->rx_tfm_mic) - crypto_free_hash(priv->rx_tfm_mic); + crypto_free_ahash(priv->rx_tfm_mic); } -int orinoco_mic(struct crypto_hash *tfm_michael, u8 *key, +int orinoco_mic(struct crypto_ahash *tfm_michael, u8 *key, u8 *da, u8 *sa, u8 priority, u8 *data, size_t data_len, u8 *mic) { - struct hash_desc desc; + AHASH_REQUEST_ON_STACK(req, tfm_michael); struct scatterlist sg[2]; u8 hdr[ETH_HLEN + 2]; /* size of header + padding */ + int err; if (tfm_michael == NULL) { printk(KERN_WARNING "orinoco_mic: tfm_michael == NULL\n"); @@ -69,11 +72,13 @@ int orinoco_mic(struct crypto_hash *tfm_michael, u8 *key, sg_set_buf(&sg[0], hdr, sizeof(hdr)); sg_set_buf(&sg[1], data, data_len); - if (crypto_hash_setkey(tfm_michael, key, MIC_KEYLEN)) + if (crypto_ahash_setkey(tfm_michael, key, MIC_KEYLEN)) return -1; - desc.tfm = tfm_michael; - desc.flags = 0; - return crypto_hash_digest(&desc, sg, data_len + sizeof(hdr), - mic); + ahash_request_set_tfm(req, tfm_michael); + ahash_request_set_callback(req, 0, NULL, NULL); + ahash_request_set_crypt(req, sg, mic, data_len + sizeof(hdr)); + err = crypto_ahash_digest(req); + ahash_request_zero(req); + return err; } diff --git a/drivers/net/wireless/intersil/orinoco/mic.h b/drivers/net/wireless/intersil/orinoco/mic.h index 04d05bc566d6..ce731d05cc98 100644 --- a/drivers/net/wireless/intersil/orinoco/mic.h +++ b/drivers/net/wireless/intersil/orinoco/mic.h @@ -11,11 +11,11 @@ /* Forward declarations */ struct orinoco_private; -struct crypto_hash; +struct crypto_ahash; int orinoco_mic_init(struct orinoco_private *priv); void orinoco_mic_free(struct orinoco_private *priv); -int orinoco_mic(struct crypto_hash *tfm_michael, u8 *key, +int orinoco_mic(struct crypto_ahash *tfm_michael, u8 *key, u8 *da, u8 *sa, u8 priority, u8 *data, size_t data_len, u8 *mic); diff --git a/drivers/net/wireless/intersil/orinoco/orinoco.h b/drivers/net/wireless/intersil/orinoco/orinoco.h index eebd2be21ee9..2f0c84b1c440 100644 --- a/drivers/net/wireless/intersil/orinoco/orinoco.h +++ b/drivers/net/wireless/intersil/orinoco/orinoco.h @@ -152,8 +152,8 @@ struct orinoco_private { u8 *wpa_ie; int wpa_ie_len; - struct crypto_hash *rx_tfm_mic; - struct crypto_hash *tx_tfm_mic; + struct crypto_ahash *rx_tfm_mic; + struct crypto_ahash *tx_tfm_mic; unsigned int wpa_enabled:1; unsigned int tkip_cm_active:1; -- cgit v1.2.3 From c3a79227185400bd0e48d63ebad97e98097340b2 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:16:57 +0800 Subject: staging: rtl8192u: Use skcipher and ahash This patch replaces uses of blkcipher with skcipher, and the long obsolete hash interface with ahash. Signed-off-by: Herbert Xu Acked-by: Greg Kroah-Hartman --- .../rtl8192u/ieee80211/ieee80211_crypt_tkip.c | 92 ++++++++++++---------- .../rtl8192u/ieee80211/ieee80211_crypt_wep.c | 46 +++++++---- 2 files changed, 81 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c index 908bc2eb4d29..6fa96d57d316 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c @@ -21,7 +21,8 @@ #include "ieee80211.h" -#include +#include +#include #include #include @@ -52,10 +53,10 @@ struct ieee80211_tkip_data { int key_idx; - struct crypto_blkcipher *rx_tfm_arc4; - struct crypto_hash *rx_tfm_michael; - struct crypto_blkcipher *tx_tfm_arc4; - struct crypto_hash *tx_tfm_michael; + struct crypto_skcipher *rx_tfm_arc4; + struct crypto_ahash *rx_tfm_michael; + struct crypto_skcipher *tx_tfm_arc4; + struct crypto_ahash *tx_tfm_michael; /* scratch buffers for virt_to_page() (crypto API) */ u8 rx_hdr[16], tx_hdr[16]; @@ -70,7 +71,7 @@ static void *ieee80211_tkip_init(int key_idx) goto fail; priv->key_idx = key_idx; - priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, + priv->tx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm_arc4)) { printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " @@ -79,7 +80,7 @@ static void *ieee80211_tkip_init(int key_idx) goto fail; } - priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0, + priv->tx_tfm_michael = crypto_alloc_ahash("michael_mic", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm_michael)) { printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " @@ -88,7 +89,7 @@ static void *ieee80211_tkip_init(int key_idx) goto fail; } - priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, + priv->rx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm_arc4)) { printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " @@ -97,7 +98,7 @@ static void *ieee80211_tkip_init(int key_idx) goto fail; } - priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0, + priv->rx_tfm_michael = crypto_alloc_ahash("michael_mic", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm_michael)) { printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " @@ -110,14 +111,10 @@ static void *ieee80211_tkip_init(int key_idx) fail: if (priv) { - if (priv->tx_tfm_michael) - crypto_free_hash(priv->tx_tfm_michael); - if (priv->tx_tfm_arc4) - crypto_free_blkcipher(priv->tx_tfm_arc4); - if (priv->rx_tfm_michael) - crypto_free_hash(priv->rx_tfm_michael); - if (priv->rx_tfm_arc4) - crypto_free_blkcipher(priv->rx_tfm_arc4); + crypto_free_ahash(priv->tx_tfm_michael); + crypto_free_skcipher(priv->tx_tfm_arc4); + crypto_free_ahash(priv->rx_tfm_michael); + crypto_free_skcipher(priv->rx_tfm_arc4); kfree(priv); } @@ -130,14 +127,10 @@ static void ieee80211_tkip_deinit(void *priv) struct ieee80211_tkip_data *_priv = priv; if (_priv) { - if (_priv->tx_tfm_michael) - crypto_free_hash(_priv->tx_tfm_michael); - if (_priv->tx_tfm_arc4) - crypto_free_blkcipher(_priv->tx_tfm_arc4); - if (_priv->rx_tfm_michael) - crypto_free_hash(_priv->rx_tfm_michael); - if (_priv->rx_tfm_arc4) - crypto_free_blkcipher(_priv->rx_tfm_arc4); + crypto_free_ahash(_priv->tx_tfm_michael); + crypto_free_skcipher(_priv->tx_tfm_arc4); + crypto_free_ahash(_priv->rx_tfm_michael); + crypto_free_skcipher(_priv->rx_tfm_arc4); } kfree(priv); } @@ -312,7 +305,6 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) u8 *pos; struct rtl_80211_hdr_4addr *hdr; cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4}; int ret = 0; u8 rc4key[16], *icv; u32 crc; @@ -357,15 +349,21 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) *pos++ = (tkey->tx_iv32 >> 24) & 0xff; if (!tcb_desc->bHwSec) { + SKCIPHER_REQUEST_ON_STACK(req, tkey->tx_tfm_arc4); + icv = skb_put(skb, 4); crc = ~crc32_le(~0, pos, len); icv[0] = crc; icv[1] = crc >> 8; icv[2] = crc >> 16; icv[3] = crc >> 24; - crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); + crypto_skcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); sg_init_one(&sg, pos, len+4); - ret = crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); + skcipher_request_set_tfm(req, tkey->tx_tfm_arc4); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); + ret = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); } tkey->tx_iv16++; @@ -390,12 +388,12 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) u16 iv16; struct rtl_80211_hdr_4addr *hdr; cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - struct blkcipher_desc desc = {.tfm = tkey->rx_tfm_arc4}; u8 rc4key[16]; u8 icv[4]; u32 crc; struct scatterlist sg; int plen; + int err; if (skb->len < hdr_len + 8 + 4) return -1; @@ -429,6 +427,8 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) pos += 8; if (!tcb_desc->bHwSec) { + SKCIPHER_REQUEST_ON_STACK(req, tkey->rx_tfm_arc4); + if (iv32 < tkey->rx_iv32 || (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) { if (net_ratelimit()) { @@ -449,10 +449,16 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) plen = skb->len - hdr_len - 12; - crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); + crypto_skcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); sg_init_one(&sg, pos, plen+4); - if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) { + skcipher_request_set_tfm(req, tkey->rx_tfm_arc4); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, plen + 4, NULL); + + err = crypto_skcipher_decrypt(req); + skcipher_request_zero(req); + if (err) { if (net_ratelimit()) { printk(KERN_DEBUG ": TKIP: failed to decrypt " "received packet from %pM\n", @@ -501,11 +507,12 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) return keyidx; } -static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr, +static int michael_mic(struct crypto_ahash *tfm_michael, u8 *key, u8 *hdr, u8 *data, size_t data_len, u8 *mic) { - struct hash_desc desc; + AHASH_REQUEST_ON_STACK(req, tfm_michael); struct scatterlist sg[2]; + int err; if (tfm_michael == NULL) { printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); @@ -516,12 +523,15 @@ static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr, sg_set_buf(&sg[0], hdr, 16); sg_set_buf(&sg[1], data, data_len); - if (crypto_hash_setkey(tfm_michael, key, 8)) + if (crypto_ahash_setkey(tfm_michael, key, 8)) return -1; - desc.tfm = tfm_michael; - desc.flags = 0; - return crypto_hash_digest(&desc, sg, data_len + 16, mic); + ahash_request_set_tfm(req, tfm_michael); + ahash_request_set_callback(req, 0, NULL, NULL); + ahash_request_set_crypt(req, sg, mic, data_len + 16); + err = crypto_ahash_digest(req); + ahash_request_zero(req); + return err; } static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) @@ -660,10 +670,10 @@ static int ieee80211_tkip_set_key(void *key, int len, u8 *seq, void *priv) { struct ieee80211_tkip_data *tkey = priv; int keyidx; - struct crypto_hash *tfm = tkey->tx_tfm_michael; - struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4; - struct crypto_hash *tfm3 = tkey->rx_tfm_michael; - struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4; + struct crypto_ahash *tfm = tkey->tx_tfm_michael; + struct crypto_skcipher *tfm2 = tkey->tx_tfm_arc4; + struct crypto_ahash *tfm3 = tkey->rx_tfm_michael; + struct crypto_skcipher *tfm4 = tkey->rx_tfm_arc4; keyidx = tkey->key_idx; memset(tkey, 0, sizeof(*tkey)); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c index 681611dc93d3..ababb6de125b 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c @@ -18,7 +18,7 @@ #include "ieee80211.h" -#include +#include #include #include @@ -32,8 +32,8 @@ struct prism2_wep_data { u8 key[WEP_KEY_LEN + 1]; u8 key_len; u8 key_idx; - struct crypto_blkcipher *tx_tfm; - struct crypto_blkcipher *rx_tfm; + struct crypto_skcipher *tx_tfm; + struct crypto_skcipher *rx_tfm; }; @@ -46,10 +46,10 @@ static void *prism2_wep_init(int keyidx) return NULL; priv->key_idx = keyidx; - priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + priv->tx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm)) goto free_priv; - priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + priv->rx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm)) goto free_tx; @@ -58,7 +58,7 @@ static void *prism2_wep_init(int keyidx) return priv; free_tx: - crypto_free_blkcipher(priv->tx_tfm); + crypto_free_skcipher(priv->tx_tfm); free_priv: kfree(priv); return NULL; @@ -70,10 +70,8 @@ static void prism2_wep_deinit(void *priv) struct prism2_wep_data *_priv = priv; if (_priv) { - if (_priv->tx_tfm) - crypto_free_blkcipher(_priv->tx_tfm); - if (_priv->rx_tfm) - crypto_free_blkcipher(_priv->rx_tfm); + crypto_free_skcipher(_priv->tx_tfm); + crypto_free_skcipher(_priv->rx_tfm); } kfree(priv); } @@ -91,10 +89,10 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) u8 key[WEP_KEY_LEN + 3]; u8 *pos; cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - struct blkcipher_desc desc = {.tfm = wep->tx_tfm}; u32 crc; u8 *icv; struct scatterlist sg; + int err; if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 || skb->len < hdr_len) @@ -129,6 +127,8 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) memcpy(key + 3, wep->key, wep->key_len); if (!tcb_desc->bHwSec) { + SKCIPHER_REQUEST_ON_STACK(req, wep->tx_tfm); + /* Append little-endian CRC32 and encrypt it to produce ICV */ crc = ~crc32_le(~0, pos, len); icv = skb_put(skb, 4); @@ -137,10 +137,16 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[2] = crc >> 16; icv[3] = crc >> 24; - crypto_blkcipher_setkey(wep->tx_tfm, key, klen); + crypto_skcipher_setkey(wep->tx_tfm, key, klen); sg_init_one(&sg, pos, len+4); - return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); + skcipher_request_set_tfm(req, wep->tx_tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); + + err = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); + return err; } return 0; @@ -161,10 +167,10 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) u8 key[WEP_KEY_LEN + 3]; u8 keyidx, *pos; cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - struct blkcipher_desc desc = {.tfm = wep->rx_tfm}; u32 crc; u8 icv[4]; struct scatterlist sg; + int err; if (skb->len < hdr_len + 8) return -1; @@ -186,10 +192,18 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) plen = skb->len - hdr_len - 8; if (!tcb_desc->bHwSec) { - crypto_blkcipher_setkey(wep->rx_tfm, key, klen); + SKCIPHER_REQUEST_ON_STACK(req, wep->rx_tfm); + + crypto_skcipher_setkey(wep->rx_tfm, key, klen); sg_init_one(&sg, pos, plen+4); - if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) + skcipher_request_set_tfm(req, wep->rx_tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, plen + 4, NULL); + + err = crypto_skcipher_decrypt(req); + skcipher_request_zero(req); + if (err) return -7; crc = ~crc32_le(~0, pos, plen); -- cgit v1.2.3 From ab1e6fa405b12e290083c4d0a694e82392dbbb66 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:17:07 +0800 Subject: wusb: Use skcipher This patch replaces uses of blkcipher with skcipher. Signed-off-by: Herbert Xu --- drivers/usb/wusbcore/crypto.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/wusbcore/crypto.c b/drivers/usb/wusbcore/crypto.c index 50ce80d604f3..8ed8e34c3492 100644 --- a/drivers/usb/wusbcore/crypto.c +++ b/drivers/usb/wusbcore/crypto.c @@ -45,6 +45,7 @@ * funneled through AES are...16 bytes in size! */ +#include #include #include #include @@ -195,21 +196,22 @@ static void bytewise_xor(void *_bo, const void *_bi1, const void *_bi2, * NOTE: blen is not aligned to a block size, we'll pad zeros, that's * what sg[4] is for. Maybe there is a smarter way to do this. */ -static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc, +static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc, struct crypto_cipher *tfm_aes, void *mic, const struct aes_ccm_nonce *n, const struct aes_ccm_label *a, const void *b, size_t blen) { int result = 0; - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, tfm_cbc); struct aes_ccm_b0 b0; struct aes_ccm_b1 b1; struct aes_ccm_a ax; struct scatterlist sg[4], sg_dst; - void *iv, *dst_buf; - size_t ivsize, dst_size; + void *dst_buf; + size_t dst_size; const u8 bzero[16] = { 0 }; + u8 iv[crypto_skcipher_ivsize(tfm_cbc)]; size_t zero_padding; /* @@ -232,9 +234,7 @@ static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc, goto error_dst_buf; } - iv = crypto_blkcipher_crt(tfm_cbc)->iv; - ivsize = crypto_blkcipher_ivsize(tfm_cbc); - memset(iv, 0, ivsize); + memset(iv, 0, sizeof(iv)); /* Setup B0 */ b0.flags = 0x59; /* Format B0 */ @@ -259,9 +259,11 @@ static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc, sg_set_buf(&sg[3], bzero, zero_padding); sg_init_one(&sg_dst, dst_buf, dst_size); - desc.tfm = tfm_cbc; - desc.flags = 0; - result = crypto_blkcipher_encrypt(&desc, &sg_dst, sg, dst_size); + skcipher_request_set_tfm(req, tfm_cbc); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg, &sg_dst, dst_size, iv); + result = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); if (result < 0) { printk(KERN_ERR "E: can't compute CBC-MAC tag (MIC): %d\n", result); @@ -301,18 +303,18 @@ ssize_t wusb_prf(void *out, size_t out_size, { ssize_t result, bytes = 0, bitr; struct aes_ccm_nonce n = *_n; - struct crypto_blkcipher *tfm_cbc; + struct crypto_skcipher *tfm_cbc; struct crypto_cipher *tfm_aes; u64 sfn = 0; __le64 sfn_le; - tfm_cbc = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); + tfm_cbc = crypto_alloc_skcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm_cbc)) { result = PTR_ERR(tfm_cbc); printk(KERN_ERR "E: can't load CBC(AES): %d\n", (int)result); goto error_alloc_cbc; } - result = crypto_blkcipher_setkey(tfm_cbc, key, 16); + result = crypto_skcipher_setkey(tfm_cbc, key, 16); if (result < 0) { printk(KERN_ERR "E: can't set CBC key: %d\n", (int)result); goto error_setkey_cbc; @@ -345,7 +347,7 @@ error_setkey_aes: crypto_free_cipher(tfm_aes); error_alloc_aes: error_setkey_cbc: - crypto_free_blkcipher(tfm_cbc); + crypto_free_skcipher(tfm_cbc); error_alloc_cbc: return result; } -- cgit v1.2.3 From 9534d67195118c39edf2ec0bb74e59993c4c0677 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:19:21 +0800 Subject: drbd: Use shash and ahash This patch replaces uses of the long obsolete hash interface with either shash (for non-SG users) or ahash. Signed-off-by: Herbert Xu --- drivers/block/drbd/drbd_int.h | 16 +++++------ drivers/block/drbd/drbd_main.c | 16 +++++------ drivers/block/drbd/drbd_nl.c | 59 ++++++++++++++++++++++++-------------- drivers/block/drbd/drbd_receiver.c | 56 +++++++++++++++++------------------- drivers/block/drbd/drbd_worker.c | 43 +++++++++++++++------------ 5 files changed, 103 insertions(+), 87 deletions(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 34bc84efc29e..c227fd4cad75 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -26,13 +26,13 @@ #ifndef _DRBD_INT_H #define _DRBD_INT_H +#include #include #include #include #include #include #include -#include #include #include #include @@ -724,11 +724,11 @@ struct drbd_connection { struct list_head transfer_log; /* all requests not yet fully processed */ - struct crypto_hash *cram_hmac_tfm; - struct crypto_hash *integrity_tfm; /* checksums we compute, updates protected by connection->data->mutex */ - struct crypto_hash *peer_integrity_tfm; /* checksums we verify, only accessed from receiver thread */ - struct crypto_hash *csums_tfm; - struct crypto_hash *verify_tfm; + struct crypto_shash *cram_hmac_tfm; + struct crypto_ahash *integrity_tfm; /* checksums we compute, updates protected by connection->data->mutex */ + struct crypto_ahash *peer_integrity_tfm; /* checksums we verify, only accessed from receiver thread */ + struct crypto_ahash *csums_tfm; + struct crypto_ahash *verify_tfm; void *int_dig_in; void *int_dig_vv; @@ -1524,8 +1524,8 @@ static inline void ov_out_of_sync_print(struct drbd_device *device) } -extern void drbd_csum_bio(struct crypto_hash *, struct bio *, void *); -extern void drbd_csum_ee(struct crypto_hash *, struct drbd_peer_request *, void *); +extern void drbd_csum_bio(struct crypto_ahash *, struct bio *, void *); +extern void drbd_csum_ee(struct crypto_ahash *, struct drbd_peer_request *, void *); /* worker callbacks */ extern int w_e_end_data_req(struct drbd_work *, int); extern int w_e_end_rsdata_req(struct drbd_work *, int); diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 5b43dfb79819..fa209773d494 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1340,7 +1340,7 @@ void drbd_send_ack_dp(struct drbd_peer_device *peer_device, enum drbd_packet cmd struct p_data *dp, int data_size) { if (peer_device->connection->peer_integrity_tfm) - data_size -= crypto_hash_digestsize(peer_device->connection->peer_integrity_tfm); + data_size -= crypto_ahash_digestsize(peer_device->connection->peer_integrity_tfm); _drbd_send_ack(peer_device, cmd, dp->sector, cpu_to_be32(data_size), dp->block_id); } @@ -1629,7 +1629,7 @@ int drbd_send_dblock(struct drbd_peer_device *peer_device, struct drbd_request * sock = &peer_device->connection->data; p = drbd_prepare_command(peer_device, sock); digest_size = peer_device->connection->integrity_tfm ? - crypto_hash_digestsize(peer_device->connection->integrity_tfm) : 0; + crypto_ahash_digestsize(peer_device->connection->integrity_tfm) : 0; if (!p) return -EIO; @@ -1718,7 +1718,7 @@ int drbd_send_block(struct drbd_peer_device *peer_device, enum drbd_packet cmd, p = drbd_prepare_command(peer_device, sock); digest_size = peer_device->connection->integrity_tfm ? - crypto_hash_digestsize(peer_device->connection->integrity_tfm) : 0; + crypto_ahash_digestsize(peer_device->connection->integrity_tfm) : 0; if (!p) return -EIO; @@ -2498,11 +2498,11 @@ void conn_free_crypto(struct drbd_connection *connection) { drbd_free_sock(connection); - crypto_free_hash(connection->csums_tfm); - crypto_free_hash(connection->verify_tfm); - crypto_free_hash(connection->cram_hmac_tfm); - crypto_free_hash(connection->integrity_tfm); - crypto_free_hash(connection->peer_integrity_tfm); + crypto_free_ahash(connection->csums_tfm); + crypto_free_ahash(connection->verify_tfm); + crypto_free_shash(connection->cram_hmac_tfm); + crypto_free_ahash(connection->integrity_tfm); + crypto_free_ahash(connection->peer_integrity_tfm); kfree(connection->int_dig_in); kfree(connection->int_dig_vv); diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index c055c5e12f24..226eb0c9f0fb 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -2160,19 +2160,34 @@ check_net_options(struct drbd_connection *connection, struct net_conf *new_net_c } struct crypto { - struct crypto_hash *verify_tfm; - struct crypto_hash *csums_tfm; - struct crypto_hash *cram_hmac_tfm; - struct crypto_hash *integrity_tfm; + struct crypto_ahash *verify_tfm; + struct crypto_ahash *csums_tfm; + struct crypto_shash *cram_hmac_tfm; + struct crypto_ahash *integrity_tfm; }; static int -alloc_hash(struct crypto_hash **tfm, char *tfm_name, int err_alg) +alloc_shash(struct crypto_shash **tfm, char *tfm_name, int err_alg) { if (!tfm_name[0]) return NO_ERROR; - *tfm = crypto_alloc_hash(tfm_name, 0, CRYPTO_ALG_ASYNC); + *tfm = crypto_alloc_shash(tfm_name, 0, 0); + if (IS_ERR(*tfm)) { + *tfm = NULL; + return err_alg; + } + + return NO_ERROR; +} + +static int +alloc_ahash(struct crypto_ahash **tfm, char *tfm_name, int err_alg) +{ + if (!tfm_name[0]) + return NO_ERROR; + + *tfm = crypto_alloc_ahash(tfm_name, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(*tfm)) { *tfm = NULL; return err_alg; @@ -2187,24 +2202,24 @@ alloc_crypto(struct crypto *crypto, struct net_conf *new_net_conf) char hmac_name[CRYPTO_MAX_ALG_NAME]; enum drbd_ret_code rv; - rv = alloc_hash(&crypto->csums_tfm, new_net_conf->csums_alg, - ERR_CSUMS_ALG); + rv = alloc_ahash(&crypto->csums_tfm, new_net_conf->csums_alg, + ERR_CSUMS_ALG); if (rv != NO_ERROR) return rv; - rv = alloc_hash(&crypto->verify_tfm, new_net_conf->verify_alg, - ERR_VERIFY_ALG); + rv = alloc_ahash(&crypto->verify_tfm, new_net_conf->verify_alg, + ERR_VERIFY_ALG); if (rv != NO_ERROR) return rv; - rv = alloc_hash(&crypto->integrity_tfm, new_net_conf->integrity_alg, - ERR_INTEGRITY_ALG); + rv = alloc_ahash(&crypto->integrity_tfm, new_net_conf->integrity_alg, + ERR_INTEGRITY_ALG); if (rv != NO_ERROR) return rv; if (new_net_conf->cram_hmac_alg[0] != 0) { snprintf(hmac_name, CRYPTO_MAX_ALG_NAME, "hmac(%s)", new_net_conf->cram_hmac_alg); - rv = alloc_hash(&crypto->cram_hmac_tfm, hmac_name, - ERR_AUTH_ALG); + rv = alloc_shash(&crypto->cram_hmac_tfm, hmac_name, + ERR_AUTH_ALG); } return rv; @@ -2212,10 +2227,10 @@ alloc_crypto(struct crypto *crypto, struct net_conf *new_net_conf) static void free_crypto(struct crypto *crypto) { - crypto_free_hash(crypto->cram_hmac_tfm); - crypto_free_hash(crypto->integrity_tfm); - crypto_free_hash(crypto->csums_tfm); - crypto_free_hash(crypto->verify_tfm); + crypto_free_shash(crypto->cram_hmac_tfm); + crypto_free_ahash(crypto->integrity_tfm); + crypto_free_ahash(crypto->csums_tfm); + crypto_free_ahash(crypto->verify_tfm); } int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info) @@ -2292,23 +2307,23 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info) rcu_assign_pointer(connection->net_conf, new_net_conf); if (!rsr) { - crypto_free_hash(connection->csums_tfm); + crypto_free_ahash(connection->csums_tfm); connection->csums_tfm = crypto.csums_tfm; crypto.csums_tfm = NULL; } if (!ovr) { - crypto_free_hash(connection->verify_tfm); + crypto_free_ahash(connection->verify_tfm); connection->verify_tfm = crypto.verify_tfm; crypto.verify_tfm = NULL; } - crypto_free_hash(connection->integrity_tfm); + crypto_free_ahash(connection->integrity_tfm); connection->integrity_tfm = crypto.integrity_tfm; if (connection->cstate >= C_WF_REPORT_PARAMS && connection->agreed_pro_version >= 100) /* Do this without trying to take connection->data.mutex again. */ __drbd_send_protocol(connection, P_PROTOCOL_UPDATE); - crypto_free_hash(connection->cram_hmac_tfm); + crypto_free_shash(connection->cram_hmac_tfm); connection->cram_hmac_tfm = crypto.cram_hmac_tfm; mutex_unlock(&connection->resource->conf_update); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 1957fe8601dc..050aaa1c0350 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1627,7 +1627,7 @@ read_in_block(struct drbd_peer_device *peer_device, u64 id, sector_t sector, digest_size = 0; if (!trim && peer_device->connection->peer_integrity_tfm) { - digest_size = crypto_hash_digestsize(peer_device->connection->peer_integrity_tfm); + digest_size = crypto_ahash_digestsize(peer_device->connection->peer_integrity_tfm); /* * FIXME: Receive the incoming digest into the receive buffer * here, together with its struct p_data? @@ -1741,7 +1741,7 @@ static int recv_dless_read(struct drbd_peer_device *peer_device, struct drbd_req digest_size = 0; if (peer_device->connection->peer_integrity_tfm) { - digest_size = crypto_hash_digestsize(peer_device->connection->peer_integrity_tfm); + digest_size = crypto_ahash_digestsize(peer_device->connection->peer_integrity_tfm); err = drbd_recv_all_warn(peer_device->connection, dig_in, digest_size); if (err) return err; @@ -3321,7 +3321,7 @@ static int receive_protocol(struct drbd_connection *connection, struct packet_in int p_proto, p_discard_my_data, p_two_primaries, cf; struct net_conf *nc, *old_net_conf, *new_net_conf = NULL; char integrity_alg[SHARED_SECRET_MAX] = ""; - struct crypto_hash *peer_integrity_tfm = NULL; + struct crypto_ahash *peer_integrity_tfm = NULL; void *int_dig_in = NULL, *int_dig_vv = NULL; p_proto = be32_to_cpu(p->protocol); @@ -3402,14 +3402,14 @@ static int receive_protocol(struct drbd_connection *connection, struct packet_in * change. */ - peer_integrity_tfm = crypto_alloc_hash(integrity_alg, 0, CRYPTO_ALG_ASYNC); + peer_integrity_tfm = crypto_alloc_ahash(integrity_alg, 0, CRYPTO_ALG_ASYNC); if (!peer_integrity_tfm) { drbd_err(connection, "peer data-integrity-alg %s not supported\n", integrity_alg); goto disconnect; } - hash_size = crypto_hash_digestsize(peer_integrity_tfm); + hash_size = crypto_ahash_digestsize(peer_integrity_tfm); int_dig_in = kmalloc(hash_size, GFP_KERNEL); int_dig_vv = kmalloc(hash_size, GFP_KERNEL); if (!(int_dig_in && int_dig_vv)) { @@ -3439,7 +3439,7 @@ static int receive_protocol(struct drbd_connection *connection, struct packet_in mutex_unlock(&connection->resource->conf_update); mutex_unlock(&connection->data.mutex); - crypto_free_hash(connection->peer_integrity_tfm); + crypto_free_ahash(connection->peer_integrity_tfm); kfree(connection->int_dig_in); kfree(connection->int_dig_vv); connection->peer_integrity_tfm = peer_integrity_tfm; @@ -3457,7 +3457,7 @@ static int receive_protocol(struct drbd_connection *connection, struct packet_in disconnect_rcu_unlock: rcu_read_unlock(); disconnect: - crypto_free_hash(peer_integrity_tfm); + crypto_free_ahash(peer_integrity_tfm); kfree(int_dig_in); kfree(int_dig_vv); conn_request_state(connection, NS(conn, C_DISCONNECTING), CS_HARD); @@ -3469,15 +3469,15 @@ disconnect: * return: NULL (alg name was "") * ERR_PTR(error) if something goes wrong * or the crypto hash ptr, if it worked out ok. */ -static struct crypto_hash *drbd_crypto_alloc_digest_safe(const struct drbd_device *device, +static struct crypto_ahash *drbd_crypto_alloc_digest_safe(const struct drbd_device *device, const char *alg, const char *name) { - struct crypto_hash *tfm; + struct crypto_ahash *tfm; if (!alg[0]) return NULL; - tfm = crypto_alloc_hash(alg, 0, CRYPTO_ALG_ASYNC); + tfm = crypto_alloc_ahash(alg, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { drbd_err(device, "Can not allocate \"%s\" as %s (reason: %ld)\n", alg, name, PTR_ERR(tfm)); @@ -3530,8 +3530,8 @@ static int receive_SyncParam(struct drbd_connection *connection, struct packet_i struct drbd_device *device; struct p_rs_param_95 *p; unsigned int header_size, data_size, exp_max_sz; - struct crypto_hash *verify_tfm = NULL; - struct crypto_hash *csums_tfm = NULL; + struct crypto_ahash *verify_tfm = NULL; + struct crypto_ahash *csums_tfm = NULL; struct net_conf *old_net_conf, *new_net_conf = NULL; struct disk_conf *old_disk_conf = NULL, *new_disk_conf = NULL; const int apv = connection->agreed_pro_version; @@ -3678,14 +3678,14 @@ static int receive_SyncParam(struct drbd_connection *connection, struct packet_i if (verify_tfm) { strcpy(new_net_conf->verify_alg, p->verify_alg); new_net_conf->verify_alg_len = strlen(p->verify_alg) + 1; - crypto_free_hash(peer_device->connection->verify_tfm); + crypto_free_ahash(peer_device->connection->verify_tfm); peer_device->connection->verify_tfm = verify_tfm; drbd_info(device, "using verify-alg: \"%s\"\n", p->verify_alg); } if (csums_tfm) { strcpy(new_net_conf->csums_alg, p->csums_alg); new_net_conf->csums_alg_len = strlen(p->csums_alg) + 1; - crypto_free_hash(peer_device->connection->csums_tfm); + crypto_free_ahash(peer_device->connection->csums_tfm); peer_device->connection->csums_tfm = csums_tfm; drbd_info(device, "using csums-alg: \"%s\"\n", p->csums_alg); } @@ -3729,9 +3729,9 @@ disconnect: mutex_unlock(&connection->resource->conf_update); /* just for completeness: actually not needed, * as this is not reached if csums_tfm was ok. */ - crypto_free_hash(csums_tfm); + crypto_free_ahash(csums_tfm); /* but free the verify_tfm again, if csums_tfm did not work out */ - crypto_free_hash(verify_tfm); + crypto_free_ahash(verify_tfm); conn_request_state(peer_device->connection, NS(conn, C_DISCONNECTING), CS_HARD); return -EIO; } @@ -4925,14 +4925,13 @@ static int drbd_do_auth(struct drbd_connection *connection) { struct drbd_socket *sock; char my_challenge[CHALLENGE_LEN]; /* 64 Bytes... */ - struct scatterlist sg; char *response = NULL; char *right_response = NULL; char *peers_ch = NULL; unsigned int key_len; char secret[SHARED_SECRET_MAX]; /* 64 byte */ unsigned int resp_size; - struct hash_desc desc; + SHASH_DESC_ON_STACK(desc, connection->cram_hmac_tfm); struct packet_info pi; struct net_conf *nc; int err, rv; @@ -4945,12 +4944,12 @@ static int drbd_do_auth(struct drbd_connection *connection) memcpy(secret, nc->shared_secret, key_len); rcu_read_unlock(); - desc.tfm = connection->cram_hmac_tfm; - desc.flags = 0; + desc->tfm = connection->cram_hmac_tfm; + desc->flags = 0; - rv = crypto_hash_setkey(connection->cram_hmac_tfm, (u8 *)secret, key_len); + rv = crypto_shash_setkey(connection->cram_hmac_tfm, (u8 *)secret, key_len); if (rv) { - drbd_err(connection, "crypto_hash_setkey() failed with %d\n", rv); + drbd_err(connection, "crypto_shash_setkey() failed with %d\n", rv); rv = -1; goto fail; } @@ -5011,7 +5010,7 @@ static int drbd_do_auth(struct drbd_connection *connection) goto fail; } - resp_size = crypto_hash_digestsize(connection->cram_hmac_tfm); + resp_size = crypto_shash_digestsize(connection->cram_hmac_tfm); response = kmalloc(resp_size, GFP_NOIO); if (response == NULL) { drbd_err(connection, "kmalloc of response failed\n"); @@ -5019,10 +5018,7 @@ static int drbd_do_auth(struct drbd_connection *connection) goto fail; } - sg_init_table(&sg, 1); - sg_set_buf(&sg, peers_ch, pi.size); - - rv = crypto_hash_digest(&desc, &sg, sg.length, response); + rv = crypto_shash_digest(desc, peers_ch, pi.size, response); if (rv) { drbd_err(connection, "crypto_hash_digest() failed with %d\n", rv); rv = -1; @@ -5070,9 +5066,8 @@ static int drbd_do_auth(struct drbd_connection *connection) goto fail; } - sg_set_buf(&sg, my_challenge, CHALLENGE_LEN); - - rv = crypto_hash_digest(&desc, &sg, sg.length, right_response); + rv = crypto_shash_digest(desc, my_challenge, CHALLENGE_LEN, + right_response); if (rv) { drbd_err(connection, "crypto_hash_digest() failed with %d\n", rv); rv = -1; @@ -5091,6 +5086,7 @@ static int drbd_do_auth(struct drbd_connection *connection) kfree(peers_ch); kfree(response); kfree(right_response); + shash_desc_zero(desc); return rv; } diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index eff716c27b1f..4d87499f0d54 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -274,51 +274,56 @@ void drbd_request_endio(struct bio *bio) complete_master_bio(device, &m); } -void drbd_csum_ee(struct crypto_hash *tfm, struct drbd_peer_request *peer_req, void *digest) +void drbd_csum_ee(struct crypto_ahash *tfm, struct drbd_peer_request *peer_req, void *digest) { - struct hash_desc desc; + AHASH_REQUEST_ON_STACK(req, tfm); struct scatterlist sg; struct page *page = peer_req->pages; struct page *tmp; unsigned len; - desc.tfm = tfm; - desc.flags = 0; + ahash_request_set_tfm(req, tfm); + ahash_request_set_callback(req, 0, NULL, NULL); sg_init_table(&sg, 1); - crypto_hash_init(&desc); + crypto_ahash_init(req); while ((tmp = page_chain_next(page))) { /* all but the last page will be fully used */ sg_set_page(&sg, page, PAGE_SIZE, 0); - crypto_hash_update(&desc, &sg, sg.length); + ahash_request_set_crypt(req, &sg, NULL, sg.length); + crypto_ahash_update(req); page = tmp; } /* and now the last, possibly only partially used page */ len = peer_req->i.size & (PAGE_SIZE - 1); sg_set_page(&sg, page, len ?: PAGE_SIZE, 0); - crypto_hash_update(&desc, &sg, sg.length); - crypto_hash_final(&desc, digest); + ahash_request_set_crypt(req, &sg, digest, sg.length); + crypto_ahash_finup(req); + ahash_request_zero(req); } -void drbd_csum_bio(struct crypto_hash *tfm, struct bio *bio, void *digest) +void drbd_csum_bio(struct crypto_ahash *tfm, struct bio *bio, void *digest) { - struct hash_desc desc; + AHASH_REQUEST_ON_STACK(req, tfm); struct scatterlist sg; struct bio_vec bvec; struct bvec_iter iter; - desc.tfm = tfm; - desc.flags = 0; + ahash_request_set_tfm(req, tfm); + ahash_request_set_callback(req, 0, NULL, NULL); sg_init_table(&sg, 1); - crypto_hash_init(&desc); + crypto_ahash_init(req); bio_for_each_segment(bvec, bio, iter) { sg_set_page(&sg, bvec.bv_page, bvec.bv_len, bvec.bv_offset); - crypto_hash_update(&desc, &sg, sg.length); + ahash_request_set_crypt(req, &sg, NULL, sg.length); + crypto_ahash_update(req); } - crypto_hash_final(&desc, digest); + ahash_request_set_crypt(req, NULL, digest, 0); + crypto_ahash_final(req); + ahash_request_zero(req); } /* MAYBE merge common code with w_e_end_ov_req */ @@ -337,7 +342,7 @@ static int w_e_send_csum(struct drbd_work *w, int cancel) if (unlikely((peer_req->flags & EE_WAS_ERROR) != 0)) goto out; - digest_size = crypto_hash_digestsize(peer_device->connection->csums_tfm); + digest_size = crypto_ahash_digestsize(peer_device->connection->csums_tfm); digest = kmalloc(digest_size, GFP_NOIO); if (digest) { sector_t sector = peer_req->i.sector; @@ -1113,7 +1118,7 @@ int w_e_end_csum_rs_req(struct drbd_work *w, int cancel) * a real fix would be much more involved, * introducing more locking mechanisms */ if (peer_device->connection->csums_tfm) { - digest_size = crypto_hash_digestsize(peer_device->connection->csums_tfm); + digest_size = crypto_ahash_digestsize(peer_device->connection->csums_tfm); D_ASSERT(device, digest_size == di->digest_size); digest = kmalloc(digest_size, GFP_NOIO); } @@ -1163,7 +1168,7 @@ int w_e_end_ov_req(struct drbd_work *w, int cancel) if (unlikely(cancel)) goto out; - digest_size = crypto_hash_digestsize(peer_device->connection->verify_tfm); + digest_size = crypto_ahash_digestsize(peer_device->connection->verify_tfm); digest = kmalloc(digest_size, GFP_NOIO); if (!digest) { err = 1; /* terminate the connection in case the allocation failed */ @@ -1235,7 +1240,7 @@ int w_e_end_ov_reply(struct drbd_work *w, int cancel) di = peer_req->digest; if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) { - digest_size = crypto_hash_digestsize(peer_device->connection->verify_tfm); + digest_size = crypto_ahash_digestsize(peer_device->connection->verify_tfm); digest = kmalloc(digest_size, GFP_NOIO); if (digest) { drbd_csum_ee(peer_device->connection->verify_tfm, peer_req, digest); -- cgit v1.2.3 From 4a31340b36302d46207c6bb54d103d9fb568e916 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:19:31 +0800 Subject: nfc: s3fwrn5: Use shash This patch replaces uses of the long obsolete hash interface with shash. Signed-off-by: Herbert Xu --- drivers/nfc/s3fwrn5/firmware.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/nfc/s3fwrn5/firmware.c b/drivers/nfc/s3fwrn5/firmware.c index 64a90252c57f..5f97da1947e3 100644 --- a/drivers/nfc/s3fwrn5/firmware.c +++ b/drivers/nfc/s3fwrn5/firmware.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include "s3fwrn5.h" @@ -429,8 +429,7 @@ int s3fwrn5_fw_download(struct s3fwrn5_fw_info *fw_info) { struct s3fwrn5_fw_image *fw = &fw_info->fw; u8 hash_data[SHA1_DIGEST_SIZE]; - struct scatterlist sg; - struct hash_desc desc; + struct crypto_shash *tfm; u32 image_size, off; int ret; @@ -438,12 +437,31 @@ int s3fwrn5_fw_download(struct s3fwrn5_fw_info *fw_info) /* Compute SHA of firmware data */ - sg_init_one(&sg, fw->image, image_size); - desc.tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); - crypto_hash_init(&desc); - crypto_hash_update(&desc, &sg, image_size); - crypto_hash_final(&desc, hash_data); - crypto_free_hash(desc.tfm); + tfm = crypto_alloc_shash("sha1", 0, 0); + if (IS_ERR(tfm)) { + ret = PTR_ERR(tfm); + dev_err(&fw_info->ndev->nfc_dev->dev, + "Cannot allocate shash (code=%d)\n", ret); + goto out; + } + + { + SHASH_DESC_ON_STACK(desc, tfm); + + desc->tfm = tfm; + desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; + + ret = crypto_shash_digest(desc, fw->image, image_size, + hash_data); + shash_desc_zero(desc); + } + + crypto_free_shash(tfm); + if (ret) { + dev_err(&fw_info->ndev->nfc_dev->dev, + "Cannot compute hash (code=%d)\n", ret); + goto out; + } /* Firmware update process */ -- cgit v1.2.3 From 5d6ac29b9ebf27bb78ab1984371c672c5a975565 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:19:41 +0800 Subject: iscsi_tcp: Use ahash This patch replaces uses of the long obsolete hash interface with ahash. Signed-off-by: Herbert Xu Reviewed-by: Mike Christie --- drivers/scsi/iscsi_tcp.c | 54 +++++++++++++++++++++++++++------------------ drivers/scsi/iscsi_tcp.h | 4 ++-- drivers/scsi/libiscsi_tcp.c | 29 ++++++++++++++---------- include/scsi/libiscsi_tcp.h | 13 ++++++----- 4 files changed, 58 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 0b8af186e707..2e4c82f8329c 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -26,12 +26,12 @@ * Zhenyu Wang */ +#include #include #include #include #include #include -#include #include #include #include @@ -428,7 +428,7 @@ static void iscsi_sw_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr, * sufficient room. */ if (conn->hdrdgst_en) { - iscsi_tcp_dgst_header(&tcp_sw_conn->tx_hash, hdr, hdrlen, + iscsi_tcp_dgst_header(tcp_sw_conn->tx_hash, hdr, hdrlen, hdr + hdrlen); hdrlen += ISCSI_DIGEST_SIZE; } @@ -454,7 +454,7 @@ iscsi_sw_tcp_send_data_prep(struct iscsi_conn *conn, struct scatterlist *sg, { struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; - struct hash_desc *tx_hash = NULL; + struct ahash_request *tx_hash = NULL; unsigned int hdr_spec_len; ISCSI_SW_TCP_DBG(conn, "offset=%d, datalen=%d %s\n", offset, len, @@ -467,7 +467,7 @@ iscsi_sw_tcp_send_data_prep(struct iscsi_conn *conn, struct scatterlist *sg, WARN_ON(iscsi_padded(len) != iscsi_padded(hdr_spec_len)); if (conn->datadgst_en) - tx_hash = &tcp_sw_conn->tx_hash; + tx_hash = tcp_sw_conn->tx_hash; return iscsi_segment_seek_sg(&tcp_sw_conn->out.data_segment, sg, count, offset, len, @@ -480,7 +480,7 @@ iscsi_sw_tcp_send_linear_data_prep(struct iscsi_conn *conn, void *data, { struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; - struct hash_desc *tx_hash = NULL; + struct ahash_request *tx_hash = NULL; unsigned int hdr_spec_len; ISCSI_SW_TCP_DBG(conn, "datalen=%zd %s\n", len, conn->datadgst_en ? @@ -492,7 +492,7 @@ iscsi_sw_tcp_send_linear_data_prep(struct iscsi_conn *conn, void *data, WARN_ON(iscsi_padded(len) != iscsi_padded(hdr_spec_len)); if (conn->datadgst_en) - tx_hash = &tcp_sw_conn->tx_hash; + tx_hash = tcp_sw_conn->tx_hash; iscsi_segment_init_linear(&tcp_sw_conn->out.data_segment, data, len, NULL, tx_hash); @@ -543,6 +543,7 @@ iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session, struct iscsi_cls_conn *cls_conn; struct iscsi_tcp_conn *tcp_conn; struct iscsi_sw_tcp_conn *tcp_sw_conn; + struct crypto_ahash *tfm; cls_conn = iscsi_tcp_conn_setup(cls_session, sizeof(*tcp_sw_conn), conn_idx); @@ -552,23 +553,28 @@ iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session, tcp_conn = conn->dd_data; tcp_sw_conn = tcp_conn->dd_data; - tcp_sw_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0, - CRYPTO_ALG_ASYNC); - tcp_sw_conn->tx_hash.flags = 0; - if (IS_ERR(tcp_sw_conn->tx_hash.tfm)) + tfm = crypto_alloc_ahash("crc32c", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) goto free_conn; - tcp_sw_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0, - CRYPTO_ALG_ASYNC); - tcp_sw_conn->rx_hash.flags = 0; - if (IS_ERR(tcp_sw_conn->rx_hash.tfm)) - goto free_tx_tfm; - tcp_conn->rx_hash = &tcp_sw_conn->rx_hash; + tcp_sw_conn->tx_hash = ahash_request_alloc(tfm, GFP_KERNEL); + if (!tcp_sw_conn->tx_hash) + goto free_tfm; + ahash_request_set_callback(tcp_sw_conn->tx_hash, 0, NULL, NULL); + + tcp_sw_conn->rx_hash = ahash_request_alloc(tfm, GFP_KERNEL); + if (!tcp_sw_conn->rx_hash) + goto free_tx_hash; + ahash_request_set_callback(tcp_sw_conn->rx_hash, 0, NULL, NULL); + + tcp_conn->rx_hash = tcp_sw_conn->rx_hash; return cls_conn; -free_tx_tfm: - crypto_free_hash(tcp_sw_conn->tx_hash.tfm); +free_tx_hash: + ahash_request_free(tcp_sw_conn->tx_hash); +free_tfm: + crypto_free_ahash(tfm); free_conn: iscsi_conn_printk(KERN_ERR, conn, "Could not create connection due to crc32c " @@ -607,10 +613,14 @@ static void iscsi_sw_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) iscsi_sw_tcp_release_conn(conn); - if (tcp_sw_conn->tx_hash.tfm) - crypto_free_hash(tcp_sw_conn->tx_hash.tfm); - if (tcp_sw_conn->rx_hash.tfm) - crypto_free_hash(tcp_sw_conn->rx_hash.tfm); + ahash_request_free(tcp_sw_conn->rx_hash); + if (tcp_sw_conn->tx_hash) { + struct crypto_ahash *tfm; + + tfm = crypto_ahash_reqtfm(tcp_sw_conn->tx_hash); + ahash_request_free(tcp_sw_conn->tx_hash); + crypto_free_ahash(tfm); + } iscsi_tcp_conn_teardown(cls_conn); } diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index f42ecb238af5..06d42d00a323 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h @@ -45,8 +45,8 @@ struct iscsi_sw_tcp_conn { void (*old_write_space)(struct sock *); /* data and header digests */ - struct hash_desc tx_hash; /* CRC32C (Tx) */ - struct hash_desc rx_hash; /* CRC32C (Rx) */ + struct ahash_request *tx_hash; /* CRC32C (Tx) */ + struct ahash_request *rx_hash; /* CRC32C (Rx) */ /* MIB custom statistics */ uint32_t sendpage_failures_cnt; diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index 60cb6dc3c6f0..63a1d69ff515 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -26,13 +26,13 @@ * Zhenyu Wang */ +#include #include #include #include #include #include #include -#include #include #include #include @@ -214,7 +214,8 @@ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn, } else sg_init_one(&sg, segment->data + segment->copied, copied); - crypto_hash_update(segment->hash, &sg, copied); + ahash_request_set_crypt(segment->hash, &sg, NULL, copied); + crypto_ahash_update(segment->hash); } segment->copied += copied; @@ -260,7 +261,9 @@ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn, * is completely handled in hdr done function. */ if (segment->hash) { - crypto_hash_final(segment->hash, segment->digest); + ahash_request_set_crypt(segment->hash, NULL, + segment->digest, 0); + crypto_ahash_final(segment->hash); iscsi_tcp_segment_splice_digest(segment, recv ? segment->recv_digest : segment->digest); return 0; @@ -310,13 +313,14 @@ iscsi_tcp_segment_recv(struct iscsi_tcp_conn *tcp_conn, } inline void -iscsi_tcp_dgst_header(struct hash_desc *hash, const void *hdr, size_t hdrlen, - unsigned char digest[ISCSI_DIGEST_SIZE]) +iscsi_tcp_dgst_header(struct ahash_request *hash, const void *hdr, + size_t hdrlen, unsigned char digest[ISCSI_DIGEST_SIZE]) { struct scatterlist sg; sg_init_one(&sg, hdr, hdrlen); - crypto_hash_digest(hash, &sg, hdrlen, digest); + ahash_request_set_crypt(hash, &sg, digest, hdrlen); + crypto_ahash_digest(hash); } EXPORT_SYMBOL_GPL(iscsi_tcp_dgst_header); @@ -341,7 +345,7 @@ iscsi_tcp_dgst_verify(struct iscsi_tcp_conn *tcp_conn, */ static inline void __iscsi_segment_init(struct iscsi_segment *segment, size_t size, - iscsi_segment_done_fn_t *done, struct hash_desc *hash) + iscsi_segment_done_fn_t *done, struct ahash_request *hash) { memset(segment, 0, sizeof(*segment)); segment->total_size = size; @@ -349,14 +353,14 @@ __iscsi_segment_init(struct iscsi_segment *segment, size_t size, if (hash) { segment->hash = hash; - crypto_hash_init(hash); + crypto_ahash_init(hash); } } inline void iscsi_segment_init_linear(struct iscsi_segment *segment, void *data, size_t size, iscsi_segment_done_fn_t *done, - struct hash_desc *hash) + struct ahash_request *hash) { __iscsi_segment_init(segment, size, done, hash); segment->data = data; @@ -368,7 +372,8 @@ inline int iscsi_segment_seek_sg(struct iscsi_segment *segment, struct scatterlist *sg_list, unsigned int sg_count, unsigned int offset, size_t size, - iscsi_segment_done_fn_t *done, struct hash_desc *hash) + iscsi_segment_done_fn_t *done, + struct ahash_request *hash) { struct scatterlist *sg; unsigned int i; @@ -431,7 +436,7 @@ static void iscsi_tcp_data_recv_prep(struct iscsi_tcp_conn *tcp_conn) { struct iscsi_conn *conn = tcp_conn->iscsi_conn; - struct hash_desc *rx_hash = NULL; + struct ahash_request *rx_hash = NULL; if (conn->datadgst_en && !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD)) @@ -686,7 +691,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) if (tcp_conn->in.datalen) { struct iscsi_tcp_task *tcp_task = task->dd_data; - struct hash_desc *rx_hash = NULL; + struct ahash_request *rx_hash = NULL; struct scsi_data_buffer *sdb = scsi_in(task->sc); /* diff --git a/include/scsi/libiscsi_tcp.h b/include/scsi/libiscsi_tcp.h index 2a7aa75dd009..30520d5ee3d1 100644 --- a/include/scsi/libiscsi_tcp.h +++ b/include/scsi/libiscsi_tcp.h @@ -26,7 +26,7 @@ struct iscsi_tcp_conn; struct iscsi_segment; struct sk_buff; -struct hash_desc; +struct ahash_request; typedef int iscsi_segment_done_fn_t(struct iscsi_tcp_conn *, struct iscsi_segment *); @@ -38,7 +38,7 @@ struct iscsi_segment { unsigned int total_size; unsigned int total_copied; - struct hash_desc *hash; + struct ahash_request *hash; unsigned char padbuf[ISCSI_PAD_LEN]; unsigned char recv_digest[ISCSI_DIGEST_SIZE]; unsigned char digest[ISCSI_DIGEST_SIZE]; @@ -73,7 +73,7 @@ struct iscsi_tcp_conn { /* control data */ struct iscsi_tcp_recv in; /* TCP receive context */ /* CRC32C (Rx) LLD should set this is they do not offload */ - struct hash_desc *rx_hash; + struct ahash_request *rx_hash; }; struct iscsi_tcp_task { @@ -111,15 +111,16 @@ extern void iscsi_tcp_segment_unmap(struct iscsi_segment *segment); extern void iscsi_segment_init_linear(struct iscsi_segment *segment, void *data, size_t size, iscsi_segment_done_fn_t *done, - struct hash_desc *hash); + struct ahash_request *hash); extern int iscsi_segment_seek_sg(struct iscsi_segment *segment, struct scatterlist *sg_list, unsigned int sg_count, unsigned int offset, size_t size, - iscsi_segment_done_fn_t *done, struct hash_desc *hash); + iscsi_segment_done_fn_t *done, + struct ahash_request *hash); /* digest helpers */ -extern void iscsi_tcp_dgst_header(struct hash_desc *hash, const void *hdr, +extern void iscsi_tcp_dgst_header(struct ahash_request *hash, const void *hdr, size_t hdrlen, unsigned char digest[ISCSI_DIGEST_SIZE]); extern struct iscsi_cls_conn * -- cgit v1.2.3 From 69110e3cedbb8aad1c70d91ed58a9f4f0ed9eec6 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:19:52 +0800 Subject: iscsi-target: Use shash and ahash This patch replaces uses of the long obsolete hash interface with either shash (for non-SG users) or ahash. Signed-off-by: Herbert Xu --- drivers/target/iscsi/iscsi_target.c | 86 ++++++++++++++------------- drivers/target/iscsi/iscsi_target_auth.c | 98 ++++++++++++------------------- drivers/target/iscsi/iscsi_target_login.c | 45 +++++++++----- include/target/iscsi/iscsi_target_core.h | 4 +- 4 files changed, 113 insertions(+), 120 deletions(-) (limited to 'drivers') diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 576a7a43470c..961202f4e9aa 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -16,9 +16,9 @@ * GNU General Public License for more details. ******************************************************************************/ +#include #include #include -#include #include #include #include @@ -1190,7 +1190,7 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, } static u32 iscsit_do_crypto_hash_sg( - struct hash_desc *hash, + struct ahash_request *hash, struct iscsi_cmd *cmd, u32 data_offset, u32 data_length, @@ -1201,7 +1201,7 @@ static u32 iscsit_do_crypto_hash_sg( struct scatterlist *sg; unsigned int page_off; - crypto_hash_init(hash); + crypto_ahash_init(hash); sg = cmd->first_data_sg; page_off = cmd->first_data_sg_off; @@ -1209,7 +1209,8 @@ static u32 iscsit_do_crypto_hash_sg( while (data_length) { u32 cur_len = min_t(u32, data_length, (sg->length - page_off)); - crypto_hash_update(hash, sg, cur_len); + ahash_request_set_crypt(hash, sg, NULL, cur_len); + crypto_ahash_update(hash); data_length -= cur_len; page_off = 0; @@ -1221,33 +1222,34 @@ static u32 iscsit_do_crypto_hash_sg( struct scatterlist pad_sg; sg_init_one(&pad_sg, pad_bytes, padding); - crypto_hash_update(hash, &pad_sg, padding); + ahash_request_set_crypt(hash, &pad_sg, (u8 *)&data_crc, + padding); + crypto_ahash_finup(hash); + } else { + ahash_request_set_crypt(hash, NULL, (u8 *)&data_crc, 0); + crypto_ahash_final(hash); } - crypto_hash_final(hash, (u8 *) &data_crc); return data_crc; } static void iscsit_do_crypto_hash_buf( - struct hash_desc *hash, + struct ahash_request *hash, const void *buf, u32 payload_length, u32 padding, u8 *pad_bytes, u8 *data_crc) { - struct scatterlist sg; + struct scatterlist sg[2]; - crypto_hash_init(hash); + sg_init_table(sg, ARRAY_SIZE(sg)); + sg_set_buf(sg, buf, payload_length); + sg_set_buf(sg + 1, pad_bytes, padding); - sg_init_one(&sg, buf, payload_length); - crypto_hash_update(hash, &sg, payload_length); + ahash_request_set_crypt(hash, sg, data_crc, payload_length + padding); - if (padding) { - sg_init_one(&sg, pad_bytes, padding); - crypto_hash_update(hash, &sg, padding); - } - crypto_hash_final(hash, data_crc); + crypto_ahash_digest(hash); } int @@ -1422,7 +1424,7 @@ iscsit_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, if (conn->conn_ops->DataDigest) { u32 data_crc; - data_crc = iscsit_do_crypto_hash_sg(&conn->conn_rx_hash, cmd, + data_crc = iscsit_do_crypto_hash_sg(conn->conn_rx_hash, cmd, be32_to_cpu(hdr->offset), payload_length, padding, cmd->pad_bytes); @@ -1682,7 +1684,7 @@ static int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, } if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(&conn->conn_rx_hash, + iscsit_do_crypto_hash_buf(conn->conn_rx_hash, ping_data, payload_length, padding, cmd->pad_bytes, (u8 *)&data_crc); @@ -2101,7 +2103,7 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, goto reject; if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(&conn->conn_rx_hash, + iscsit_do_crypto_hash_buf(conn->conn_rx_hash, text_in, payload_length, padding, (u8 *)&pad_bytes, (u8 *)&data_crc); @@ -2440,7 +2442,7 @@ static int iscsit_handle_immediate_data( if (conn->conn_ops->DataDigest) { u32 data_crc; - data_crc = iscsit_do_crypto_hash_sg(&conn->conn_rx_hash, cmd, + data_crc = iscsit_do_crypto_hash_sg(conn->conn_rx_hash, cmd, cmd->write_data_done, length, padding, cmd->pad_bytes); @@ -2553,7 +2555,7 @@ static int iscsit_send_conn_drop_async_message( if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); cmd->tx_size += ISCSI_CRC_LEN; @@ -2683,7 +2685,7 @@ static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn) if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, cmd->pdu, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->pdu, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); iov[0].iov_len += ISCSI_CRC_LEN; @@ -2711,7 +2713,7 @@ static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn) cmd->padding); } if (conn->conn_ops->DataDigest) { - cmd->data_crc = iscsit_do_crypto_hash_sg(&conn->conn_tx_hash, cmd, + cmd->data_crc = iscsit_do_crypto_hash_sg(conn->conn_tx_hash, cmd, datain.offset, datain.length, cmd->padding, cmd->pad_bytes); iov[iov_count].iov_base = &cmd->data_crc; @@ -2857,7 +2859,7 @@ iscsit_send_logout(struct iscsi_cmd *cmd, struct iscsi_conn *conn) if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, &cmd->pdu[0], + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, &cmd->pdu[0], ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); iov[0].iov_len += ISCSI_CRC_LEN; @@ -2915,7 +2917,7 @@ static int iscsit_send_unsolicited_nopin( if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); tx_size += ISCSI_CRC_LEN; @@ -2963,7 +2965,7 @@ iscsit_send_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn) if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); iov[0].iov_len += ISCSI_CRC_LEN; @@ -2993,7 +2995,7 @@ iscsit_send_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn) " padding bytes.\n", padding); } if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->buf_ptr, cmd->buf_ptr_size, padding, (u8 *)&cmd->pad_bytes, (u8 *)&cmd->data_crc); @@ -3049,7 +3051,7 @@ static int iscsit_send_r2t( if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); cmd->iov_misc[0].iov_len += ISCSI_CRC_LEN; @@ -3239,7 +3241,7 @@ static int iscsit_send_response(struct iscsi_cmd *cmd, struct iscsi_conn *conn) } if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->sense_buffer, (cmd->se_cmd.scsi_sense_length + padding), 0, NULL, (u8 *)&cmd->data_crc); @@ -3262,7 +3264,7 @@ static int iscsit_send_response(struct iscsi_cmd *cmd, struct iscsi_conn *conn) if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, cmd->pdu, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->pdu, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); iov[0].iov_len += ISCSI_CRC_LEN; @@ -3332,7 +3334,7 @@ iscsit_send_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn) if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); cmd->iov_misc[0].iov_len += ISCSI_CRC_LEN; @@ -3601,7 +3603,7 @@ static int iscsit_send_text_rsp( if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); iov[0].iov_len += ISCSI_CRC_LEN; @@ -3611,7 +3613,7 @@ static int iscsit_send_text_rsp( } if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->buf_ptr, text_length, 0, NULL, (u8 *)&cmd->data_crc); @@ -3668,7 +3670,7 @@ static int iscsit_send_reject( if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); iov[0].iov_len += ISCSI_CRC_LEN; @@ -3678,7 +3680,7 @@ static int iscsit_send_reject( } if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, cmd->buf_ptr, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->buf_ptr, ISCSI_HDR_LEN, 0, NULL, (u8 *)&cmd->data_crc); iov[iov_count].iov_base = &cmd->data_crc; @@ -4145,7 +4147,7 @@ int iscsi_target_rx_thread(void *arg) goto transport_err; } - iscsit_do_crypto_hash_buf(&conn->conn_rx_hash, + iscsit_do_crypto_hash_buf(conn->conn_rx_hash, buffer, ISCSI_HDR_LEN, 0, NULL, (u8 *)&checksum); @@ -4359,10 +4361,14 @@ int iscsit_close_connection( */ iscsit_check_conn_usage_count(conn); - if (conn->conn_rx_hash.tfm) - crypto_free_hash(conn->conn_rx_hash.tfm); - if (conn->conn_tx_hash.tfm) - crypto_free_hash(conn->conn_tx_hash.tfm); + ahash_request_free(conn->conn_tx_hash); + if (conn->conn_rx_hash) { + struct crypto_ahash *tfm; + + tfm = crypto_ahash_reqtfm(conn->conn_rx_hash); + ahash_request_free(conn->conn_rx_hash); + crypto_free_ahash(tfm); + } free_cpumask_var(conn->conn_cpumask); diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c index 47e249dccb5f..667406fcf4d3 100644 --- a/drivers/target/iscsi/iscsi_target_auth.c +++ b/drivers/target/iscsi/iscsi_target_auth.c @@ -16,9 +16,9 @@ * GNU General Public License for more details. ******************************************************************************/ +#include #include #include -#include #include #include @@ -185,9 +185,8 @@ static int chap_server_compute_md5( unsigned char chap_n[MAX_CHAP_N_SIZE], chap_r[MAX_RESPONSE_LENGTH]; size_t compare_len; struct iscsi_chap *chap = conn->auth_protocol; - struct crypto_hash *tfm; - struct hash_desc desc; - struct scatterlist sg; + struct crypto_shash *tfm = NULL; + struct shash_desc *desc = NULL; int auth_ret = -1, ret, challenge_len; memset(identifier, 0, 10); @@ -245,52 +244,47 @@ static int chap_server_compute_md5( pr_debug("[server] Got CHAP_R=%s\n", chap_r); chap_string_to_hex(client_digest, chap_r, strlen(chap_r)); - tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); + tfm = crypto_alloc_shash("md5", 0, 0); if (IS_ERR(tfm)) { - pr_err("Unable to allocate struct crypto_hash\n"); + tfm = NULL; + pr_err("Unable to allocate struct crypto_shash\n"); goto out; } - desc.tfm = tfm; - desc.flags = 0; - ret = crypto_hash_init(&desc); - if (ret < 0) { - pr_err("crypto_hash_init() failed\n"); - crypto_free_hash(tfm); + desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL); + if (!desc) { + pr_err("Unable to allocate struct shash_desc\n"); goto out; } - sg_init_one(&sg, &chap->id, 1); - ret = crypto_hash_update(&desc, &sg, 1); + desc->tfm = tfm; + desc->flags = 0; + + ret = crypto_shash_init(desc); if (ret < 0) { - pr_err("crypto_hash_update() failed for id\n"); - crypto_free_hash(tfm); + pr_err("crypto_shash_init() failed\n"); goto out; } - sg_init_one(&sg, &auth->password, strlen(auth->password)); - ret = crypto_hash_update(&desc, &sg, strlen(auth->password)); + ret = crypto_shash_update(desc, &chap->id, 1); if (ret < 0) { - pr_err("crypto_hash_update() failed for password\n"); - crypto_free_hash(tfm); + pr_err("crypto_shash_update() failed for id\n"); goto out; } - sg_init_one(&sg, chap->challenge, CHAP_CHALLENGE_LENGTH); - ret = crypto_hash_update(&desc, &sg, CHAP_CHALLENGE_LENGTH); + ret = crypto_shash_update(desc, (char *)&auth->password, + strlen(auth->password)); if (ret < 0) { - pr_err("crypto_hash_update() failed for challenge\n"); - crypto_free_hash(tfm); + pr_err("crypto_shash_update() failed for password\n"); goto out; } - ret = crypto_hash_final(&desc, server_digest); + ret = crypto_shash_finup(desc, chap->challenge, + CHAP_CHALLENGE_LENGTH, server_digest); if (ret < 0) { - pr_err("crypto_hash_final() failed for server digest\n"); - crypto_free_hash(tfm); + pr_err("crypto_shash_finup() failed for challenge\n"); goto out; } - crypto_free_hash(tfm); chap_binaryhex_to_asciihex(response, server_digest, MD5_SIGNATURE_SIZE); pr_debug("[server] MD5 Server Digest: %s\n", response); @@ -306,9 +300,8 @@ static int chap_server_compute_md5( * authentication is not enabled. */ if (!auth->authenticate_target) { - kfree(challenge); - kfree(challenge_binhex); - return 0; + auth_ret = 0; + goto out; } /* * Get CHAP_I. @@ -372,58 +365,37 @@ static int chap_server_compute_md5( /* * Generate CHAP_N and CHAP_R for mutual authentication. */ - tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) { - pr_err("Unable to allocate struct crypto_hash\n"); - goto out; - } - desc.tfm = tfm; - desc.flags = 0; - - ret = crypto_hash_init(&desc); + ret = crypto_shash_init(desc); if (ret < 0) { - pr_err("crypto_hash_init() failed\n"); - crypto_free_hash(tfm); + pr_err("crypto_shash_init() failed\n"); goto out; } /* To handle both endiannesses */ id_as_uchar = id; - sg_init_one(&sg, &id_as_uchar, 1); - ret = crypto_hash_update(&desc, &sg, 1); + ret = crypto_shash_update(desc, &id_as_uchar, 1); if (ret < 0) { - pr_err("crypto_hash_update() failed for id\n"); - crypto_free_hash(tfm); + pr_err("crypto_shash_update() failed for id\n"); goto out; } - sg_init_one(&sg, auth->password_mutual, - strlen(auth->password_mutual)); - ret = crypto_hash_update(&desc, &sg, strlen(auth->password_mutual)); + ret = crypto_shash_update(desc, auth->password_mutual, + strlen(auth->password_mutual)); if (ret < 0) { - pr_err("crypto_hash_update() failed for" + pr_err("crypto_shash_update() failed for" " password_mutual\n"); - crypto_free_hash(tfm); goto out; } /* * Convert received challenge to binary hex. */ - sg_init_one(&sg, challenge_binhex, challenge_len); - ret = crypto_hash_update(&desc, &sg, challenge_len); + ret = crypto_shash_finup(desc, challenge_binhex, challenge_len, + digest); if (ret < 0) { - pr_err("crypto_hash_update() failed for ma challenge\n"); - crypto_free_hash(tfm); + pr_err("crypto_shash_finup() failed for ma challenge\n"); goto out; } - ret = crypto_hash_final(&desc, digest); - if (ret < 0) { - pr_err("crypto_hash_final() failed for ma digest\n"); - crypto_free_hash(tfm); - goto out; - } - crypto_free_hash(tfm); /* * Generate CHAP_N and CHAP_R. */ @@ -440,6 +412,8 @@ static int chap_server_compute_md5( pr_debug("[server] Sending CHAP_R=0x%s\n", response); auth_ret = 0; out: + kzfree(desc); + crypto_free_shash(tfm); kfree(challenge); kfree(challenge_binhex); return auth_ret; diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 96e78c823d13..8436d56c5f0c 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -16,9 +16,9 @@ * GNU General Public License for more details. ******************************************************************************/ +#include #include #include -#include #include #include #include @@ -115,27 +115,36 @@ out_login: */ int iscsi_login_setup_crypto(struct iscsi_conn *conn) { + struct crypto_ahash *tfm; + /* * Setup slicing by CRC32C algorithm for RX and TX libcrypto contexts * which will default to crc32c_intel.ko for cpu_has_xmm4_2, or fallback * to software 1x8 byte slicing from crc32c.ko */ - conn->conn_rx_hash.flags = 0; - conn->conn_rx_hash.tfm = crypto_alloc_hash("crc32c", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(conn->conn_rx_hash.tfm)) { - pr_err("crypto_alloc_hash() failed for conn_rx_tfm\n"); + tfm = crypto_alloc_ahash("crc32c", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) { + pr_err("crypto_alloc_ahash() failed\n"); return -ENOMEM; } - conn->conn_tx_hash.flags = 0; - conn->conn_tx_hash.tfm = crypto_alloc_hash("crc32c", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(conn->conn_tx_hash.tfm)) { - pr_err("crypto_alloc_hash() failed for conn_tx_tfm\n"); - crypto_free_hash(conn->conn_rx_hash.tfm); + conn->conn_rx_hash = ahash_request_alloc(tfm, GFP_KERNEL); + if (!conn->conn_rx_hash) { + pr_err("ahash_request_alloc() failed for conn_rx_hash\n"); + crypto_free_ahash(tfm); + return -ENOMEM; + } + ahash_request_set_callback(conn->conn_rx_hash, 0, NULL, NULL); + + conn->conn_tx_hash = ahash_request_alloc(tfm, GFP_KERNEL); + if (!conn->conn_tx_hash) { + pr_err("ahash_request_alloc() failed for conn_tx_hash\n"); + ahash_request_free(conn->conn_rx_hash); + conn->conn_rx_hash = NULL; + crypto_free_ahash(tfm); return -ENOMEM; } + ahash_request_set_callback(conn->conn_tx_hash, 0, NULL, NULL); return 0; } @@ -1174,10 +1183,14 @@ old_sess_out: iscsit_dec_session_usage_count(conn->sess); } - if (!IS_ERR(conn->conn_rx_hash.tfm)) - crypto_free_hash(conn->conn_rx_hash.tfm); - if (!IS_ERR(conn->conn_tx_hash.tfm)) - crypto_free_hash(conn->conn_tx_hash.tfm); + ahash_request_free(conn->conn_tx_hash); + if (conn->conn_rx_hash) { + struct crypto_ahash *tfm; + + tfm = crypto_ahash_reqtfm(conn->conn_rx_hash); + ahash_request_free(conn->conn_rx_hash); + crypto_free_ahash(tfm); + } free_cpumask_var(conn->conn_cpumask); diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h index 373d3342002b..c3371fa548cb 100644 --- a/include/target/iscsi/iscsi_target_core.h +++ b/include/target/iscsi/iscsi_target_core.h @@ -570,8 +570,8 @@ struct iscsi_conn { spinlock_t response_queue_lock; spinlock_t state_lock; /* libcrypto RX and TX contexts for crc32c */ - struct hash_desc conn_rx_hash; - struct hash_desc conn_tx_hash; + struct ahash_request *conn_rx_hash; + struct ahash_request *conn_tx_hash; /* Used for scheduling TX and RX connection kthreads */ cpumask_var_t conn_cpumask; unsigned int conn_rx_reset_cpumask:1; -- cgit v1.2.3 From bfb2892018ca302d8d659232f5f18f56b4b2b782 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 Jan 2016 14:44:50 +0100 Subject: crypto: sunxi - don't print confusing data gcc correctly warns that the printk output contains a variable that it thinks is not initialized in some cases: drivers/crypto/sunxi-ss/sun4i-ss-cipher.c: In function 'sun4i_ss_cipher_poll': drivers/crypto/sunxi-ss/sun4i-ss-cipher.c:254:76: warning: 'todo' may be used uninitialized in this function [-Wmaybe-uninitialized] drivers/crypto/sunxi-ss/sun4i-ss-cipher.c:144:15: note: 'todo' was declared here A closer look at the function reveals that the variable is always initialized at this point (ileft is guaranteed to be positive at the start), but its contents are not well-defined: Depending on some other variables, it might be either a count in words or bytes, and it could refer to either input or output. The easiest solution apparently is to remove the confusing output and let the reader figure out the state from the other variables. Signed-off-by: Arnd Bergmann Signed-off-by: Herbert Xu --- drivers/crypto/sunxi-ss/sun4i-ss-cipher.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c index a19ee127edca..7be3fbcd8d78 100644 --- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c @@ -251,11 +251,10 @@ static int sun4i_ss_cipher_poll(struct ablkcipher_request *areq) spaces = readl(ss->base + SS_FCSR); rx_cnt = SS_RXFIFO_SPACES(spaces); tx_cnt = SS_TXFIFO_SPACES(spaces); - dev_dbg(ss->dev, "%x %u/%u %u/%u cnt=%u %u/%u %u/%u cnt=%u %u %u\n", + dev_dbg(ss->dev, "%x %u/%u %u/%u cnt=%u %u/%u %u/%u cnt=%u %u\n", mode, oi, mi.length, ileft, areq->nbytes, rx_cnt, - oo, mo.length, oleft, areq->nbytes, tx_cnt, - todo, ob); + oo, mo.length, oleft, areq->nbytes, tx_cnt, ob); if (tx_cnt == 0) continue; -- cgit v1.2.3 From 9a15a87338d9f28593172ec7ec2c628f3ae494b9 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 27 Jan 2016 13:40:29 +0100 Subject: Revert "drm/i915: Fix context/engine cleanup order" This reverts commit 1803c035efb88afb9d3e7feb279ac29a83216382. It seems to blow up on module unload due to a use-after free hitting a BUG_ON with CONFIG_DEBUG_SG. Quoting from Tvrtko's mail: "I've decoded the instructions and it pointed to SG_MAGIC checking: 488b8098010000 mov 0x198(%rax),%rax ba21436587 mov $0x87654321,%edx 488b00 mov (%rax),%rax *** CRASH "Grep showed 0x87654321 is SG_MAGIC, so likely candidate for this code pattern is: static inline struct page *sg_page(struct scatterlist *sg) { BUG_ON(sg->sg_magic != SG_MAGIC); BUG_ON(sg_is_chain(sg)); return (struct page *)((sg)->page_link & ~0x3); } "Which would mean the offender is in intel_logical_ring_cleanup is most likely: ... if (ring->status_page.obj) { kunmap(sg_page(ring->status_page.obj->pages->sgl)); ring->status_page.obj = NULL; } ... "I think that the i915_gem_context_fini will do a final unref on dev_priv->kernel_context and then the ring buff has a copy which is left dangling because: lrc_setup_hardware_status_page(ring, dev_priv->kernel_context->engine[ring->id].state); and: ring->status_page.obj = default_ctx_obj; "Where default_ctx_obj == dev_priv->kernel_context->engine[ring->id].state So indeed looks like the unload ordering is the trigger. In fact it is almost the same fragility wrt/ kernel_context hidden dependency I expressed my worry about in an e-mail yesterday or so. It only shows if CONFIG_DEBUG_SG is set, otherwise it accesses freed memory and probably just survives." This causes serious trouble in our CI system since it took out all gen8+ machines. Not yet clear why this wasn't caught in pre-merge testing. Backtrace from CI, for posterity: [ 163.737836] general protection fault: 0000 [#1] PREEMPT SMP [ 163.737849] Modules linked in: ax88179_178a usbnet mii snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic i915(-) x86_pkg_temp_thermal intel_powerclamp coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm mei_me mei i2c_hid e1000e ptp pps_core [last unloaded: snd_hda_intel] [ 163.737902] CPU: 0 PID: 5812 Comm: rmmod Tainted: G U W 4.5.0-rc1-gfxbench+ #1 [ 163.737911] Hardware name: System manufacturer System Product Name/Z170M-PLUS, BIOS 0505 11/16/2015 [ 163.737920] task: ffff8800bb99cf80 ti: ffff88022ff2c000 task.ti: ffff88022ff2c000 [ 163.737928] RIP: 0010:[] [] intel_logical_ring_cleanup+0x83/0x100 [i915] [ 163.737969] RSP: 0018:ffff88022ff2fd30 EFLAGS: 00010282 [ 163.737975] RAX: 6b6b6b6b6b6b6b6b RBX: ffff8800bb2f31b8 RCX: 0000000000000002 [ 163.737982] RDX: 0000000087654321 RSI: 000000000000000d RDI: ffff8800bb2f31f0 [ 163.737989] RBP: ffff88022ff2fd40 R08: 0000000000000000 R09: 0000000000000001 [ 163.737996] R10: 0000000000000000 R11: 0000000000000000 R12: ffff8800bb2f0000 [ 163.738003] R13: ffff8800bb2f8fc8 R14: ffff8800bb285668 R15: 000055af1ae55210 [ 163.738010] FS: 00007f187014b700(0000) GS:ffff88023bc00000(0000) knlGS:0000000000000000 [ 163.738021] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 163.738030] CR2: 0000558f84e4cbc8 CR3: 000000022cd55000 CR4: 00000000003406f0 [ 163.738039] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 163.738048] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 163.738057] Stack: [ 163.738062] ffff8800bb2f31b8 ffff8800bb2f0000 ffff88022ff2fd70 ffffffffa0180414 [ 163.738079] ffff8800bb2f0000 ffff8800bb285668 ffff8800bb2856c8 ffffffffa0242460 [ 163.738094] ffff88022ff2fd98 ffffffffa0202d30 ffff8800bb285668 ffff8800bb285668 [ 163.738109] Call Trace: [ 163.738140] [] i915_gem_cleanup_engines+0x34/0x60 [i915] [ 163.738185] [] i915_driver_unload+0x150/0x270 [i915] [ 163.738198] [] drm_dev_unregister+0x24/0xa0 [ 163.738208] [] drm_put_dev+0x1e/0x60 [ 163.738225] [] i915_pci_remove+0x10/0x20 [i915] [ 163.738237] [] pci_device_remove+0x34/0xb0 [ 163.738249] [] __device_release_driver+0x95/0x140 [ 163.738259] [] driver_detach+0xb6/0xc0 [ 163.738268] [] bus_remove_driver+0x53/0xd0 [ 163.738278] [] driver_unregister+0x27/0x50 [ 163.738289] [] pci_unregister_driver+0x25/0x70 [ 163.738299] [] drm_pci_exit+0x74/0x90 [ 163.738337] [] i915_exit+0x20/0x1a5 [i915] [ 163.738349] [] SyS_delete_module+0x18f/0x1f0 [ 163.738361] [] entry_SYSCALL_64_fastpath+0x16/0x73 [ 163.738370] Code: ff d0 48 89 df e8 de a1 fd ff 48 8d 7b 38 e8 25 ab fd ff 48 8b 83 90 00 00 00 48 85 c0 74 25 48 8b 80 98 01 00 00 ba 21 43 65 87 <48> 8b 00 48 39 10 75 3c f6 40 08 01 75 38 48 c7 83 90 00 00 00 [ 163.738459] RIP [] intel_logical_ring_cleanup+0x83/0x100 [i915] [ 163.738498] RSP [ 163.738507] ---[ end trace 68f69ce4740fa44f ]--- Cc: Nick Hoath Cc: Dave Gordon Cc: Chris Wilson Cc: Tvrtko Ursulin Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Tested-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 4 ++-- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 23 +++++++++++------------ 3 files changed, 14 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 4725e8d61d0f..d70d96fe553b 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -451,8 +451,8 @@ static int i915_load_modeset_init(struct drm_device *dev) cleanup_gem: mutex_lock(&dev->struct_mutex); + i915_gem_cleanup_ringbuffer(dev); i915_gem_context_fini(dev); - i915_gem_cleanup_engines(dev); mutex_unlock(&dev->struct_mutex); cleanup_irq: intel_guc_ucode_fini(dev); @@ -1196,8 +1196,8 @@ int i915_driver_unload(struct drm_device *dev) intel_guc_ucode_fini(dev); mutex_lock(&dev->struct_mutex); + i915_gem_cleanup_ringbuffer(dev); i915_gem_context_fini(dev); - i915_gem_cleanup_engines(dev); mutex_unlock(&dev->struct_mutex); intel_fbc_cleanup_cfb(dev_priv); i915_gem_cleanup_stolen(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 01cc982f5497..211af534e5d0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3019,7 +3019,7 @@ int i915_gem_init_rings(struct drm_device *dev); int __must_check i915_gem_init_hw(struct drm_device *dev); int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice); void i915_gem_init_swizzling(struct drm_device *dev); -void i915_gem_cleanup_engines(struct drm_device *dev); +void i915_gem_cleanup_ringbuffer(struct drm_device *dev); int __must_check i915_gpu_idle(struct drm_device *dev); int __must_check i915_gem_suspend(struct drm_device *dev); void __i915_add_request(struct drm_i915_gem_request *req, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 799a53ad04f2..371bbb28c471 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4912,7 +4912,7 @@ i915_gem_init_hw(struct drm_device *dev) req = i915_gem_request_alloc(ring, NULL); if (IS_ERR(req)) { ret = PTR_ERR(req); - i915_gem_cleanup_engines(dev); + i915_gem_cleanup_ringbuffer(dev); goto out; } @@ -4925,7 +4925,7 @@ i915_gem_init_hw(struct drm_device *dev) if (ret && ret != -EIO) { DRM_ERROR("PPGTT enable ring #%d failed %d\n", i, ret); i915_gem_request_cancel(req); - i915_gem_cleanup_engines(dev); + i915_gem_cleanup_ringbuffer(dev); goto out; } @@ -4933,7 +4933,7 @@ i915_gem_init_hw(struct drm_device *dev) if (ret && ret != -EIO) { DRM_ERROR("Context enable ring #%d failed %d\n", i, ret); i915_gem_request_cancel(req); - i915_gem_cleanup_engines(dev); + i915_gem_cleanup_ringbuffer(dev); goto out; } @@ -5008,7 +5008,7 @@ out_unlock: } void -i915_gem_cleanup_engines(struct drm_device *dev) +i915_gem_cleanup_ringbuffer(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *ring; @@ -5017,14 +5017,13 @@ i915_gem_cleanup_engines(struct drm_device *dev) for_each_ring(ring, dev_priv, i) dev_priv->gt.cleanup_ring(ring); - if (i915.enable_execlists) { - /* - * Neither the BIOS, ourselves or any other kernel - * expects the system to be in execlists mode on startup, - * so we need to reset the GPU back to legacy mode. - */ - intel_gpu_reset(dev); - } + if (i915.enable_execlists) + /* + * Neither the BIOS, ourselves or any other kernel + * expects the system to be in execlists mode on startup, + * so we need to reset the GPU back to legacy mode. + */ + intel_gpu_reset(dev); } static void -- cgit v1.2.3 From aceb16dc2da58341bda939defaff0682fac13747 Mon Sep 17 00:00:00 2001 From: Maxime Coquelin Date: Thu, 14 Jan 2016 13:16:30 +0100 Subject: pinctrl: Add STM32 MCUs support This patch adds pinctrl and GPIO support to STMicroelectronic's STM32 family of MCUs. While it only supports STM32F429 for now, it has been designed to enable support of other MCUs of the family (e.g. STM32F746). Acked-by: Patrice Chotard Signed-off-by: Maxime Coquelin Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/stm32/Kconfig | 16 + drivers/pinctrl/stm32/Makefile | 5 + drivers/pinctrl/stm32/pinctrl-stm32.c | 834 +++++++++++++++ drivers/pinctrl/stm32/pinctrl-stm32.h | 43 + drivers/pinctrl/stm32/pinctrl-stm32f429.c | 1598 +++++++++++++++++++++++++++++ 7 files changed, 2498 insertions(+) create mode 100644 drivers/pinctrl/stm32/Kconfig create mode 100644 drivers/pinctrl/stm32/Makefile create mode 100644 drivers/pinctrl/stm32/pinctrl-stm32.c create mode 100644 drivers/pinctrl/stm32/pinctrl-stm32.h create mode 100644 drivers/pinctrl/stm32/pinctrl-stm32f429.c (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 99a4c10ed43f..f8405cdeb5fb 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -257,6 +257,7 @@ source "drivers/pinctrl/qcom/Kconfig" source "drivers/pinctrl/samsung/Kconfig" source "drivers/pinctrl/sh-pfc/Kconfig" source "drivers/pinctrl/spear/Kconfig" +source "drivers/pinctrl/stm32/Kconfig" source "drivers/pinctrl/sunxi/Kconfig" source "drivers/pinctrl/uniphier/Kconfig" source "drivers/pinctrl/vt8500/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index bf1b5ca5180b..d4134038cbf9 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_ARCH_QCOM) += qcom/ obj-$(CONFIG_PINCTRL_SAMSUNG) += samsung/ obj-$(CONFIG_PINCTRL_SH_PFC) += sh-pfc/ obj-$(CONFIG_PINCTRL_SPEAR) += spear/ +obj-$(CONFIG_ARCH_STM32) += stm32/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/ obj-$(CONFIG_ARCH_VT8500) += vt8500/ diff --git a/drivers/pinctrl/stm32/Kconfig b/drivers/pinctrl/stm32/Kconfig new file mode 100644 index 000000000000..0f28841b2332 --- /dev/null +++ b/drivers/pinctrl/stm32/Kconfig @@ -0,0 +1,16 @@ +if ARCH_STM32 || COMPILE_TEST + +config PINCTRL_STM32 + bool + depends on OF + select PINMUX + select GENERIC_PINCONF + select GPIOLIB + +config PINCTRL_STM32F429 + bool "STMicroelectronics STM32F429 pin control" if COMPILE_TEST && !MACH_STM32F429 + depends on OF + default MACH_STM32F429 + select PINCTRL_STM32 + +endif diff --git a/drivers/pinctrl/stm32/Makefile b/drivers/pinctrl/stm32/Makefile new file mode 100644 index 000000000000..fc17d4238845 --- /dev/null +++ b/drivers/pinctrl/stm32/Makefile @@ -0,0 +1,5 @@ +# Core +obj-$(CONFIG_PINCTRL_STM32) += pinctrl-stm32.o + +# SoC Drivers +obj-$(CONFIG_PINCTRL_STM32F429) += pinctrl-stm32f429.o diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c new file mode 100644 index 000000000000..d25d4a064bad --- /dev/null +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -0,0 +1,834 @@ +/* + * Copyright (C) Maxime Coquelin 2015 + * Author: Maxime Coquelin + * License terms: GNU General Public License (GPL), version 2 + * + * Heavily based on Mediatek's pinctrl driver + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../core.h" +#include "../pinconf.h" +#include "../pinctrl-utils.h" +#include "pinctrl-stm32.h" + +#define STM32_GPIO_MODER 0x00 +#define STM32_GPIO_TYPER 0x04 +#define STM32_GPIO_SPEEDR 0x08 +#define STM32_GPIO_PUPDR 0x0c +#define STM32_GPIO_IDR 0x10 +#define STM32_GPIO_ODR 0x14 +#define STM32_GPIO_BSRR 0x18 +#define STM32_GPIO_LCKR 0x1c +#define STM32_GPIO_AFRL 0x20 +#define STM32_GPIO_AFRH 0x24 + +#define STM32_GPIO_PINS_PER_BANK 16 + +#define gpio_range_to_bank(chip) \ + container_of(chip, struct stm32_gpio_bank, range) + +#define gpio_chip_to_bank(chip) \ + container_of(chip, struct stm32_gpio_bank, gpio_chip) + +static const char * const stm32_gpio_functions[] = { + "gpio", "af0", "af1", + "af2", "af3", "af4", + "af5", "af6", "af7", + "af8", "af9", "af10", + "af11", "af12", "af13", + "af14", "af15", "analog", +}; + +struct stm32_pinctrl_group { + const char *name; + unsigned long config; + unsigned pin; +}; + +struct stm32_gpio_bank { + void __iomem *base; + struct clk *clk; + spinlock_t lock; + struct gpio_chip gpio_chip; + struct pinctrl_gpio_range range; +}; + +struct stm32_pinctrl { + struct device *dev; + struct pinctrl_dev *pctl_dev; + struct pinctrl_desc pctl_desc; + struct stm32_pinctrl_group *groups; + unsigned ngroups; + const char **grp_names; + struct stm32_gpio_bank *banks; + unsigned nbanks; + const struct stm32_pinctrl_match_data *match_data; +}; + +static inline int stm32_gpio_pin(int gpio) +{ + return gpio % STM32_GPIO_PINS_PER_BANK; +} + +static inline u32 stm32_gpio_get_mode(u32 function) +{ + switch (function) { + case STM32_PIN_GPIO: + return 0; + case STM32_PIN_AF(0) ... STM32_PIN_AF(15): + return 2; + case STM32_PIN_ANALOG: + return 3; + } + + return 0; +} + +static inline u32 stm32_gpio_get_alt(u32 function) +{ + switch (function) { + case STM32_PIN_GPIO: + return 0; + case STM32_PIN_AF(0) ... STM32_PIN_AF(15): + return function - 1; + case STM32_PIN_ANALOG: + return 0; + } + + return 0; +} + +/* GPIO functions */ + +static inline void __stm32_gpio_set(struct stm32_gpio_bank *bank, + unsigned offset, int value) +{ + if (!value) + offset += STM32_GPIO_PINS_PER_BANK; + + clk_enable(bank->clk); + + writel_relaxed(BIT(offset), bank->base + STM32_GPIO_BSRR); + + clk_disable(bank->clk); +} + +static int stm32_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + return pinctrl_request_gpio(chip->base + offset); +} + +static void stm32_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + pinctrl_free_gpio(chip->base + offset); +} + +static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); + int ret; + + clk_enable(bank->clk); + + ret = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset)); + + clk_disable(bank->clk); + + return ret; +} + +static void stm32_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); + + __stm32_gpio_set(bank, offset, value); +} + +static int stm32_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + return pinctrl_gpio_direction_input(chip->base + offset); +} + +static int stm32_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); + + __stm32_gpio_set(bank, offset, value); + pinctrl_gpio_direction_output(chip->base + offset); + + return 0; +} + +static struct gpio_chip stm32_gpio_template = { + .request = stm32_gpio_request, + .free = stm32_gpio_free, + .get = stm32_gpio_get, + .set = stm32_gpio_set, + .direction_input = stm32_gpio_direction_input, + .direction_output = stm32_gpio_direction_output, +}; + +/* Pinctrl functions */ + +static struct stm32_pinctrl_group * +stm32_pctrl_find_group_by_pin(struct stm32_pinctrl *pctl, u32 pin) +{ + int i; + + for (i = 0; i < pctl->ngroups; i++) { + struct stm32_pinctrl_group *grp = pctl->groups + i; + + if (grp->pin == pin) + return grp; + } + + return NULL; +} + +static bool stm32_pctrl_is_function_valid(struct stm32_pinctrl *pctl, + u32 pin_num, u32 fnum) +{ + int i; + + for (i = 0; i < pctl->match_data->npins; i++) { + const struct stm32_desc_pin *pin = pctl->match_data->pins + i; + const struct stm32_desc_function *func = pin->functions; + + if (pin->pin.number != pin_num) + continue; + + while (func && func->name) { + if (func->num == fnum) + return true; + func++; + } + + break; + } + + return false; +} + +static int stm32_pctrl_dt_node_to_map_func(struct stm32_pinctrl *pctl, + u32 pin, u32 fnum, struct stm32_pinctrl_group *grp, + struct pinctrl_map **map, unsigned *reserved_maps, + unsigned *num_maps) +{ + if (*num_maps == *reserved_maps) + return -ENOSPC; + + (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP; + (*map)[*num_maps].data.mux.group = grp->name; + + if (!stm32_pctrl_is_function_valid(pctl, pin, fnum)) { + dev_err(pctl->dev, "invalid function %d on pin %d .\n", + fnum, pin); + return -EINVAL; + } + + (*map)[*num_maps].data.mux.function = stm32_gpio_functions[fnum]; + (*num_maps)++; + + return 0; +} + +static int stm32_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, + struct device_node *node, + struct pinctrl_map **map, + unsigned *reserved_maps, + unsigned *num_maps) +{ + struct stm32_pinctrl *pctl; + struct stm32_pinctrl_group *grp; + struct property *pins; + u32 pinfunc, pin, func; + unsigned long *configs; + unsigned int num_configs; + bool has_config = 0; + unsigned reserve = 0; + int num_pins, num_funcs, maps_per_pin, i, err; + + pctl = pinctrl_dev_get_drvdata(pctldev); + + pins = of_find_property(node, "pinmux", NULL); + if (!pins) { + dev_err(pctl->dev, "missing pins property in node %s .\n", + node->name); + return -EINVAL; + } + + err = pinconf_generic_parse_dt_config(node, pctldev, &configs, + &num_configs); + if (err) + return err; + + if (num_configs) + has_config = 1; + + num_pins = pins->length / sizeof(u32); + num_funcs = num_pins; + maps_per_pin = 0; + if (num_funcs) + maps_per_pin++; + if (has_config && num_pins >= 1) + maps_per_pin++; + + if (!num_pins || !maps_per_pin) + return -EINVAL; + + reserve = num_pins * maps_per_pin; + + err = pinctrl_utils_reserve_map(pctldev, map, + reserved_maps, num_maps, reserve); + if (err) + return err; + + for (i = 0; i < num_pins; i++) { + err = of_property_read_u32_index(node, "pinmux", + i, &pinfunc); + if (err) + return err; + + pin = STM32_GET_PIN_NO(pinfunc); + func = STM32_GET_PIN_FUNC(pinfunc); + + if (pin >= pctl->match_data->npins) { + dev_err(pctl->dev, "invalid pin number.\n"); + return -EINVAL; + } + + if (!stm32_pctrl_is_function_valid(pctl, pin, func)) { + dev_err(pctl->dev, "invalid function.\n"); + return -EINVAL; + } + + grp = stm32_pctrl_find_group_by_pin(pctl, pin); + if (!grp) { + dev_err(pctl->dev, "unable to match pin %d to group\n", + pin); + return -EINVAL; + } + + err = stm32_pctrl_dt_node_to_map_func(pctl, pin, func, grp, map, + reserved_maps, num_maps); + if (err) + return err; + + if (has_config) { + err = pinctrl_utils_add_map_configs(pctldev, map, + reserved_maps, num_maps, grp->name, + configs, num_configs, + PIN_MAP_TYPE_CONFIGS_GROUP); + if (err) + return err; + } + } + + return 0; +} + +static int stm32_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np_config, + struct pinctrl_map **map, unsigned *num_maps) +{ + struct device_node *np; + unsigned reserved_maps; + int ret; + + *map = NULL; + *num_maps = 0; + reserved_maps = 0; + + for_each_child_of_node(np_config, np) { + ret = stm32_pctrl_dt_subnode_to_map(pctldev, np, map, + &reserved_maps, num_maps); + if (ret < 0) { + pinctrl_utils_dt_free_map(pctldev, *map, *num_maps); + return ret; + } + } + + return 0; +} + +static int stm32_pctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + return pctl->ngroups; +} + +static const char *stm32_pctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned group) +{ + struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + return pctl->groups[group].name; +} + +static int stm32_pctrl_get_group_pins(struct pinctrl_dev *pctldev, + unsigned group, + const unsigned **pins, + unsigned *num_pins) +{ + struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + *pins = (unsigned *)&pctl->groups[group].pin; + *num_pins = 1; + + return 0; +} + +static const struct pinctrl_ops stm32_pctrl_ops = { + .dt_node_to_map = stm32_pctrl_dt_node_to_map, + .dt_free_map = pinctrl_utils_dt_free_map, + .get_groups_count = stm32_pctrl_get_groups_count, + .get_group_name = stm32_pctrl_get_group_name, + .get_group_pins = stm32_pctrl_get_group_pins, +}; + + +/* Pinmux functions */ + +static int stm32_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(stm32_gpio_functions); +} + +static const char *stm32_pmx_get_func_name(struct pinctrl_dev *pctldev, + unsigned selector) +{ + return stm32_gpio_functions[selector]; +} + +static int stm32_pmx_get_func_groups(struct pinctrl_dev *pctldev, + unsigned function, + const char * const **groups, + unsigned * const num_groups) +{ + struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + *groups = pctl->grp_names; + *num_groups = pctl->ngroups; + + return 0; +} + +static void stm32_pmx_set_mode(struct stm32_gpio_bank *bank, + int pin, u32 mode, u32 alt) +{ + u32 val; + int alt_shift = (pin % 8) * 4; + int alt_offset = STM32_GPIO_AFRL + (pin / 8) * 4; + unsigned long flags; + + clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + val = readl_relaxed(bank->base + alt_offset); + val &= ~GENMASK(alt_shift + 3, alt_shift); + val |= (alt << alt_shift); + writel_relaxed(val, bank->base + alt_offset); + + val = readl_relaxed(bank->base + STM32_GPIO_MODER); + val &= ~GENMASK(pin * 2 + 1, pin * 2); + val |= mode << (pin * 2); + writel_relaxed(val, bank->base + STM32_GPIO_MODER); + + spin_unlock_irqrestore(&bank->lock, flags); + clk_disable(bank->clk); +} + +static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev, + unsigned function, + unsigned group) +{ + bool ret; + struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct stm32_pinctrl_group *g = pctl->groups + group; + struct pinctrl_gpio_range *range; + struct stm32_gpio_bank *bank; + u32 mode, alt; + int pin; + + ret = stm32_pctrl_is_function_valid(pctl, g->pin, function); + if (!ret) { + dev_err(pctl->dev, "invalid function %d on group %d .\n", + function, group); + return -EINVAL; + } + + range = pinctrl_find_gpio_range_from_pin(pctldev, g->pin); + bank = gpio_range_to_bank(range); + pin = stm32_gpio_pin(g->pin); + + mode = stm32_gpio_get_mode(function); + alt = stm32_gpio_get_alt(function); + + stm32_pmx_set_mode(bank, pin, mode, alt); + + return 0; +} + +static int stm32_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, unsigned gpio, + bool input) +{ + struct stm32_gpio_bank *bank = gpio_range_to_bank(range); + int pin = stm32_gpio_pin(gpio); + + stm32_pmx_set_mode(bank, pin, !input, 0); + + return 0; +} + +static const struct pinmux_ops stm32_pmx_ops = { + .get_functions_count = stm32_pmx_get_funcs_cnt, + .get_function_name = stm32_pmx_get_func_name, + .get_function_groups = stm32_pmx_get_func_groups, + .set_mux = stm32_pmx_set_mux, + .gpio_set_direction = stm32_pmx_gpio_set_direction, +}; + +/* Pinconf functions */ + +static void stm32_pconf_set_driving(struct stm32_gpio_bank *bank, + unsigned offset, u32 drive) +{ + unsigned long flags; + u32 val; + + clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + val = readl_relaxed(bank->base + STM32_GPIO_TYPER); + val &= ~BIT(offset); + val |= drive << offset; + writel_relaxed(val, bank->base + STM32_GPIO_TYPER); + + spin_unlock_irqrestore(&bank->lock, flags); + clk_disable(bank->clk); +} + +static void stm32_pconf_set_speed(struct stm32_gpio_bank *bank, + unsigned offset, u32 speed) +{ + unsigned long flags; + u32 val; + + clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + val = readl_relaxed(bank->base + STM32_GPIO_SPEEDR); + val &= ~GENMASK(offset * 2 + 1, offset * 2); + val |= speed << (offset * 2); + writel_relaxed(val, bank->base + STM32_GPIO_SPEEDR); + + spin_unlock_irqrestore(&bank->lock, flags); + clk_disable(bank->clk); +} + +static void stm32_pconf_set_bias(struct stm32_gpio_bank *bank, + unsigned offset, u32 bias) +{ + unsigned long flags; + u32 val; + + clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + val = readl_relaxed(bank->base + STM32_GPIO_PUPDR); + val &= ~GENMASK(offset * 2 + 1, offset * 2); + val |= bias << (offset * 2); + writel_relaxed(val, bank->base + STM32_GPIO_PUPDR); + + spin_unlock_irqrestore(&bank->lock, flags); + clk_disable(bank->clk); +} + +static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev, + unsigned int pin, enum pin_config_param param, + enum pin_config_param arg) +{ + struct pinctrl_gpio_range *range; + struct stm32_gpio_bank *bank; + int offset, ret = 0; + + range = pinctrl_find_gpio_range_from_pin(pctldev, pin); + bank = gpio_range_to_bank(range); + offset = stm32_gpio_pin(pin); + + switch (param) { + case PIN_CONFIG_DRIVE_PUSH_PULL: + stm32_pconf_set_driving(bank, offset, 0); + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + stm32_pconf_set_driving(bank, offset, 1); + break; + case PIN_CONFIG_SLEW_RATE: + stm32_pconf_set_speed(bank, offset, arg); + break; + case PIN_CONFIG_BIAS_DISABLE: + stm32_pconf_set_bias(bank, offset, 0); + break; + case PIN_CONFIG_BIAS_PULL_UP: + stm32_pconf_set_bias(bank, offset, 1); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + stm32_pconf_set_bias(bank, offset, 2); + break; + case PIN_CONFIG_OUTPUT: + __stm32_gpio_set(bank, offset, arg); + ret = stm32_pmx_gpio_set_direction(pctldev, NULL, pin, false); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int stm32_pconf_group_get(struct pinctrl_dev *pctldev, + unsigned group, + unsigned long *config) +{ + struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + *config = pctl->groups[group].config; + + return 0; +} + +static int stm32_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group, + unsigned long *configs, unsigned num_configs) +{ + struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct stm32_pinctrl_group *g = &pctl->groups[group]; + int i, ret; + + for (i = 0; i < num_configs; i++) { + ret = stm32_pconf_parse_conf(pctldev, g->pin, + pinconf_to_config_param(configs[i]), + pinconf_to_config_argument(configs[i])); + if (ret < 0) + return ret; + + g->config = configs[i]; + } + + return 0; +} + +static const struct pinconf_ops stm32_pconf_ops = { + .pin_config_group_get = stm32_pconf_group_get, + .pin_config_group_set = stm32_pconf_group_set, +}; + +static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, + struct device_node *np) +{ + int bank_nr = pctl->nbanks; + struct stm32_gpio_bank *bank = &pctl->banks[bank_nr]; + struct pinctrl_gpio_range *range = &bank->range; + struct device *dev = pctl->dev; + struct resource res; + struct reset_control *rstc; + int err, npins; + + rstc = of_reset_control_get(np, NULL); + if (!IS_ERR(rstc)) + reset_control_deassert(rstc); + + if (of_address_to_resource(np, 0, &res)) + return -ENODEV; + + bank->base = devm_ioremap_resource(dev, &res); + if (IS_ERR(bank->base)) + return PTR_ERR(bank->base); + + bank->clk = of_clk_get_by_name(np, NULL); + if (IS_ERR(bank->clk)) { + dev_err(dev, "failed to get clk (%ld)\n", PTR_ERR(bank->clk)); + return PTR_ERR(bank->clk); + } + + err = clk_prepare(bank->clk); + if (err) { + dev_err(dev, "failed to prepare clk (%d)\n", err); + return err; + } + + npins = pctl->match_data->npins; + npins -= bank_nr * STM32_GPIO_PINS_PER_BANK; + if (npins < 0) + return -EINVAL; + else if (npins > STM32_GPIO_PINS_PER_BANK) + npins = STM32_GPIO_PINS_PER_BANK; + + bank->gpio_chip = stm32_gpio_template; + bank->gpio_chip.base = bank_nr * STM32_GPIO_PINS_PER_BANK; + bank->gpio_chip.ngpio = npins; + bank->gpio_chip.of_node = np; + bank->gpio_chip.dev = dev; + spin_lock_init(&bank->lock); + + of_property_read_string(np, "st,bank-name", &range->name); + bank->gpio_chip.label = range->name; + + range->id = bank_nr; + range->pin_base = range->base = range->id * STM32_GPIO_PINS_PER_BANK; + range->npins = bank->gpio_chip.ngpio; + range->gc = &bank->gpio_chip; + err = gpiochip_add(&bank->gpio_chip); + if (err) { + dev_err(dev, "Failed to add gpiochip(%d)!\n", bank_nr); + return err; + } + + dev_info(dev, "%s bank added\n", range->name); + return 0; +} + +static int stm32_pctrl_build_state(struct platform_device *pdev) +{ + struct stm32_pinctrl *pctl = platform_get_drvdata(pdev); + int i; + + pctl->ngroups = pctl->match_data->npins; + + /* Allocate groups */ + pctl->groups = devm_kcalloc(&pdev->dev, pctl->ngroups, + sizeof(*pctl->groups), GFP_KERNEL); + if (!pctl->groups) + return -ENOMEM; + + /* We assume that one pin is one group, use pin name as group name. */ + pctl->grp_names = devm_kcalloc(&pdev->dev, pctl->ngroups, + sizeof(*pctl->grp_names), GFP_KERNEL); + if (!pctl->grp_names) + return -ENOMEM; + + for (i = 0; i < pctl->match_data->npins; i++) { + const struct stm32_desc_pin *pin = pctl->match_data->pins + i; + struct stm32_pinctrl_group *group = pctl->groups + i; + + group->name = pin->pin.name; + group->pin = pin->pin.number; + + pctl->grp_names[i] = pin->pin.name; + } + + return 0; +} + +int stm32_pctl_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device_node *child; + const struct of_device_id *match; + struct device *dev = &pdev->dev; + struct stm32_pinctrl *pctl; + struct pinctrl_pin_desc *pins; + int i, ret, banks = 0; + + if (!np) + return -EINVAL; + + match = of_match_device(dev->driver->of_match_table, dev); + if (!match || !match->data) + return -EINVAL; + + if (!of_find_property(np, "pins-are-numbered", NULL)) { + dev_err(dev, "only support pins-are-numbered format\n"); + return -EINVAL; + } + + pctl = devm_kzalloc(dev, sizeof(*pctl), GFP_KERNEL); + if (!pctl) + return -ENOMEM; + + platform_set_drvdata(pdev, pctl); + + pctl->dev = dev; + pctl->match_data = match->data; + ret = stm32_pctrl_build_state(pdev); + if (ret) { + dev_err(dev, "build state failed: %d\n", ret); + return -EINVAL; + } + + for_each_child_of_node(np, child) + if (of_property_read_bool(child, "gpio-controller")) + banks++; + + if (!banks) { + dev_err(dev, "at least one GPIO bank is required\n"); + return -EINVAL; + } + + pctl->banks = devm_kcalloc(dev, banks, sizeof(*pctl->banks), + GFP_KERNEL); + if (!pctl->banks) + return -ENOMEM; + + for_each_child_of_node(np, child) { + if (of_property_read_bool(child, "gpio-controller")) { + ret = stm32_gpiolib_register_bank(pctl, child); + if (ret) + return ret; + + pctl->nbanks++; + } + } + + pins = devm_kcalloc(&pdev->dev, pctl->match_data->npins, sizeof(*pins), + GFP_KERNEL); + if (!pins) + return -ENOMEM; + + for (i = 0; i < pctl->match_data->npins; i++) + pins[i] = pctl->match_data->pins[i].pin; + + pctl->pctl_desc.name = dev_name(&pdev->dev); + pctl->pctl_desc.owner = THIS_MODULE; + pctl->pctl_desc.pins = pins; + pctl->pctl_desc.npins = pctl->match_data->npins; + pctl->pctl_desc.confops = &stm32_pconf_ops; + pctl->pctl_desc.pctlops = &stm32_pctrl_ops; + pctl->pctl_desc.pmxops = &stm32_pmx_ops; + pctl->dev = &pdev->dev; + + pctl->pctl_dev = pinctrl_register(&pctl->pctl_desc, &pdev->dev, pctl); + if (!pctl->pctl_dev) { + dev_err(&pdev->dev, "Failed pinctrl registration\n"); + return -EINVAL; + } + + for (i = 0; i < pctl->nbanks; i++) + pinctrl_add_gpio_range(pctl->pctl_dev, &pctl->banks[i].range); + + dev_info(dev, "Pinctrl STM32 initialized\n"); + + return 0; +} + diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.h b/drivers/pinctrl/stm32/pinctrl-stm32.h new file mode 100644 index 000000000000..1b7c369acd8c --- /dev/null +++ b/drivers/pinctrl/stm32/pinctrl-stm32.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) Maxime Coquelin 2015 + * Author: Maxime Coquelin + * License terms: GNU General Public License (GPL), version 2 + */ +#ifndef __PINCTRL_STM32_H +#define __PINCTRL_STM32_H + +#include +#include + +struct stm32_desc_function { + const char *name; + const unsigned char num; +}; + +struct stm32_desc_pin { + struct pinctrl_pin_desc pin; + const struct stm32_desc_function *functions; +}; + +#define STM32_PIN(_pin, ...) \ + { \ + .pin = _pin, \ + .functions = (struct stm32_desc_function[]){ \ + __VA_ARGS__, { } }, \ + } + +#define STM32_FUNCTION(_num, _name) \ + { \ + .num = _num, \ + .name = _name, \ + } + +struct stm32_pinctrl_match_data { + const struct stm32_desc_pin *pins; + const unsigned int npins; +}; + +int stm32_pctl_probe(struct platform_device *pdev); + +#endif /* __PINCTRL_STM32_H */ + diff --git a/drivers/pinctrl/stm32/pinctrl-stm32f429.c b/drivers/pinctrl/stm32/pinctrl-stm32f429.c new file mode 100644 index 000000000000..f34016b51375 --- /dev/null +++ b/drivers/pinctrl/stm32/pinctrl-stm32f429.c @@ -0,0 +1,1598 @@ +/* + * Copyright (C) Maxime Coquelin 2015 + * Author: Maxime Coquelin + * License terms: GNU General Public License (GPL), version 2 + */ +#include +#include +#include +#include + +#include "pinctrl-stm32.h" + +static const struct stm32_desc_pin stm32f429_pins[] = { + STM32_PIN( + PINCTRL_PIN(0, "PA0"), + STM32_FUNCTION(0, "GPIOA0"), + STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"), + STM32_FUNCTION(3, "TIM5_CH1"), + STM32_FUNCTION(4, "TIM8_ETR"), + STM32_FUNCTION(8, "USART2_CTS"), + STM32_FUNCTION(9, "UART4_TX"), + STM32_FUNCTION(12, "ETH_MII_CRS"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(1, "PA1"), + STM32_FUNCTION(0, "GPIOA1"), + STM32_FUNCTION(2, "TIM2_CH2"), + STM32_FUNCTION(3, "TIM5_CH2"), + STM32_FUNCTION(8, "USART2_RTS"), + STM32_FUNCTION(9, "UART4_RX"), + STM32_FUNCTION(12, "ETH_MII_RX_CLK ETH_RMII_REF_CLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(2, "PA2"), + STM32_FUNCTION(0, "GPIOA2"), + STM32_FUNCTION(2, "TIM2_CH3"), + STM32_FUNCTION(3, "TIM5_CH3"), + STM32_FUNCTION(4, "TIM9_CH1"), + STM32_FUNCTION(8, "USART2_TX"), + STM32_FUNCTION(12, "ETH_MDIO"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(3, "PA3"), + STM32_FUNCTION(0, "GPIOA3"), + STM32_FUNCTION(2, "TIM2_CH4"), + STM32_FUNCTION(3, "TIM5_CH4"), + STM32_FUNCTION(4, "TIM9_CH2"), + STM32_FUNCTION(8, "USART2_RX"), + STM32_FUNCTION(11, "OTG_HS_ULPI_D0"), + STM32_FUNCTION(12, "ETH_MII_COL"), + STM32_FUNCTION(15, "LCD_B5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(4, "PA4"), + STM32_FUNCTION(0, "GPIOA4"), + STM32_FUNCTION(6, "SPI1_NSS"), + STM32_FUNCTION(7, "SPI3_NSS I2S3_WS"), + STM32_FUNCTION(8, "USART2_CK"), + STM32_FUNCTION(13, "OTG_HS_SOF"), + STM32_FUNCTION(14, "DCMI_HSYNC"), + STM32_FUNCTION(15, "LCD_VSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(5, "PA5"), + STM32_FUNCTION(0, "GPIOA5"), + STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"), + STM32_FUNCTION(4, "TIM8_CH1N"), + STM32_FUNCTION(6, "SPI1_SCK"), + STM32_FUNCTION(11, "OTG_HS_ULPI_CK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(6, "PA6"), + STM32_FUNCTION(0, "GPIOA6"), + STM32_FUNCTION(2, "TIM1_BKIN"), + STM32_FUNCTION(3, "TIM3_CH1"), + STM32_FUNCTION(4, "TIM8_BKIN"), + STM32_FUNCTION(6, "SPI1_MISO"), + STM32_FUNCTION(10, "TIM13_CH1"), + STM32_FUNCTION(14, "DCMI_PIXCLK"), + STM32_FUNCTION(15, "LCD_G2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(7, "PA7"), + STM32_FUNCTION(0, "GPIOA7"), + STM32_FUNCTION(2, "TIM1_CH1N"), + STM32_FUNCTION(3, "TIM3_CH2"), + STM32_FUNCTION(4, "TIM8_CH1N"), + STM32_FUNCTION(6, "SPI1_MOSI"), + STM32_FUNCTION(10, "TIM14_CH1"), + STM32_FUNCTION(12, "ETH_MII_RX_DV ETH_RMII_CRS_DV"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(8, "PA8"), + STM32_FUNCTION(0, "GPIOA8"), + STM32_FUNCTION(1, "MCO1"), + STM32_FUNCTION(2, "TIM1_CH1"), + STM32_FUNCTION(5, "I2C3_SCL"), + STM32_FUNCTION(8, "USART1_CK"), + STM32_FUNCTION(11, "OTG_FS_SOF"), + STM32_FUNCTION(15, "LCD_R6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(9, "PA9"), + STM32_FUNCTION(0, "GPIOA9"), + STM32_FUNCTION(2, "TIM1_CH2"), + STM32_FUNCTION(5, "I2C3_SMBA"), + STM32_FUNCTION(8, "USART1_TX"), + STM32_FUNCTION(14, "DCMI_D0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(10, "PA10"), + STM32_FUNCTION(0, "GPIOA10"), + STM32_FUNCTION(2, "TIM1_CH3"), + STM32_FUNCTION(8, "USART1_RX"), + STM32_FUNCTION(11, "OTG_FS_ID"), + STM32_FUNCTION(14, "DCMI_D1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(11, "PA11"), + STM32_FUNCTION(0, "GPIOA11"), + STM32_FUNCTION(2, "TIM1_CH4"), + STM32_FUNCTION(8, "USART1_CTS"), + STM32_FUNCTION(10, "CAN1_RX"), + STM32_FUNCTION(11, "OTG_FS_DM"), + STM32_FUNCTION(15, "LCD_R4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(12, "PA12"), + STM32_FUNCTION(0, "GPIOA12"), + STM32_FUNCTION(2, "TIM1_ETR"), + STM32_FUNCTION(8, "USART1_RTS"), + STM32_FUNCTION(10, "CAN1_TX"), + STM32_FUNCTION(11, "OTG_FS_DP"), + STM32_FUNCTION(15, "LCD_R5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(13, "PA13"), + STM32_FUNCTION(0, "GPIOA13"), + STM32_FUNCTION(1, "JTMS SWDIO"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(14, "PA14"), + STM32_FUNCTION(0, "GPIOA14"), + STM32_FUNCTION(1, "JTCK SWCLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(15, "PA15"), + STM32_FUNCTION(0, "GPIOA15"), + STM32_FUNCTION(1, "JTDI"), + STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"), + STM32_FUNCTION(6, "SPI1_NSS"), + STM32_FUNCTION(7, "SPI3_NSS I2S3_WS"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(16, "PB0"), + STM32_FUNCTION(0, "GPIOB0"), + STM32_FUNCTION(2, "TIM1_CH2N"), + STM32_FUNCTION(3, "TIM3_CH3"), + STM32_FUNCTION(4, "TIM8_CH2N"), + STM32_FUNCTION(10, "LCD_R3"), + STM32_FUNCTION(11, "OTG_HS_ULPI_D1"), + STM32_FUNCTION(12, "ETH_MII_RXD2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(17, "PB1"), + STM32_FUNCTION(0, "GPIOB1"), + STM32_FUNCTION(2, "TIM1_CH3N"), + STM32_FUNCTION(3, "TIM3_CH4"), + STM32_FUNCTION(4, "TIM8_CH3N"), + STM32_FUNCTION(10, "LCD_R6"), + STM32_FUNCTION(11, "OTG_HS_ULPI_D2"), + STM32_FUNCTION(12, "ETH_MII_RXD3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(18, "PB2"), + STM32_FUNCTION(0, "GPIOB2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(19, "PB3"), + STM32_FUNCTION(0, "GPIOB3"), + STM32_FUNCTION(1, "JTDO TRACESWO"), + STM32_FUNCTION(2, "TIM2_CH2"), + STM32_FUNCTION(6, "SPI1_SCK"), + STM32_FUNCTION(7, "SPI3_SCK I2S3_CK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(20, "PB4"), + STM32_FUNCTION(0, "GPIOB4"), + STM32_FUNCTION(1, "NJTRST"), + STM32_FUNCTION(3, "TIM3_CH1"), + STM32_FUNCTION(6, "SPI1_MISO"), + STM32_FUNCTION(7, "SPI3_MISO"), + STM32_FUNCTION(8, "I2S3EXT_SD"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(21, "PB5"), + STM32_FUNCTION(0, "GPIOB5"), + STM32_FUNCTION(3, "TIM3_CH2"), + STM32_FUNCTION(5, "I2C1_SMBA"), + STM32_FUNCTION(6, "SPI1_MOSI"), + STM32_FUNCTION(7, "SPI3_MOSI I2S3_SD"), + STM32_FUNCTION(10, "CAN2_RX"), + STM32_FUNCTION(11, "OTG_HS_ULPI_D7"), + STM32_FUNCTION(12, "ETH_PPS_OUT"), + STM32_FUNCTION(13, "FMC_SDCKE1"), + STM32_FUNCTION(14, "DCMI_D10"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(22, "PB6"), + STM32_FUNCTION(0, "GPIOB6"), + STM32_FUNCTION(3, "TIM4_CH1"), + STM32_FUNCTION(5, "I2C1_SCL"), + STM32_FUNCTION(8, "USART1_TX"), + STM32_FUNCTION(10, "CAN2_TX"), + STM32_FUNCTION(13, "FMC_SDNE1"), + STM32_FUNCTION(14, "DCMI_D5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(23, "PB7"), + STM32_FUNCTION(0, "GPIOB7"), + STM32_FUNCTION(3, "TIM4_CH2"), + STM32_FUNCTION(5, "I2C1_SDA"), + STM32_FUNCTION(8, "USART1_RX"), + STM32_FUNCTION(13, "FMC_NL"), + STM32_FUNCTION(14, "DCMI_VSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(24, "PB8"), + STM32_FUNCTION(0, "GPIOB8"), + STM32_FUNCTION(3, "TIM4_CH3"), + STM32_FUNCTION(4, "TIM10_CH1"), + STM32_FUNCTION(5, "I2C1_SCL"), + STM32_FUNCTION(10, "CAN1_RX"), + STM32_FUNCTION(12, "ETH_MII_TXD3"), + STM32_FUNCTION(13, "SDIO_D4"), + STM32_FUNCTION(14, "DCMI_D6"), + STM32_FUNCTION(15, "LCD_B6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(25, "PB9"), + STM32_FUNCTION(0, "GPIOB9"), + STM32_FUNCTION(3, "TIM4_CH4"), + STM32_FUNCTION(4, "TIM11_CH1"), + STM32_FUNCTION(5, "I2C1_SDA"), + STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"), + STM32_FUNCTION(10, "CAN1_TX"), + STM32_FUNCTION(13, "SDIO_D5"), + STM32_FUNCTION(14, "DCMI_D7"), + STM32_FUNCTION(15, "LCD_B7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(26, "PB10"), + STM32_FUNCTION(0, "GPIOB10"), + STM32_FUNCTION(2, "TIM2_CH3"), + STM32_FUNCTION(5, "I2C2_SCL"), + STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"), + STM32_FUNCTION(8, "USART3_TX"), + STM32_FUNCTION(11, "OTG_HS_ULPI_D3"), + STM32_FUNCTION(12, "ETH_MII_RX_ER"), + STM32_FUNCTION(15, "LCD_G4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(27, "PB11"), + STM32_FUNCTION(0, "GPIOB11"), + STM32_FUNCTION(2, "TIM2_CH4"), + STM32_FUNCTION(5, "I2C2_SDA"), + STM32_FUNCTION(8, "USART3_RX"), + STM32_FUNCTION(11, "OTG_HS_ULPI_D4"), + STM32_FUNCTION(12, "ETH_MII_TX_EN ETH_RMII_TX_EN"), + STM32_FUNCTION(15, "LCD_G5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(28, "PB12"), + STM32_FUNCTION(0, "GPIOB12"), + STM32_FUNCTION(2, "TIM1_BKIN"), + STM32_FUNCTION(5, "I2C2_SMBA"), + STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"), + STM32_FUNCTION(8, "USART3_CK"), + STM32_FUNCTION(10, "CAN2_RX"), + STM32_FUNCTION(11, "OTG_HS_ULPI_D5"), + STM32_FUNCTION(12, "ETH_MII_TXD0 ETH_RMII_TXD0"), + STM32_FUNCTION(13, "OTG_HS_ID"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(29, "PB13"), + STM32_FUNCTION(0, "GPIOB13"), + STM32_FUNCTION(2, "TIM1_CH1N"), + STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"), + STM32_FUNCTION(8, "USART3_CTS"), + STM32_FUNCTION(10, "CAN2_TX"), + STM32_FUNCTION(11, "OTG_HS_ULPI_D6"), + STM32_FUNCTION(12, "ETH_MII_TXD1 ETH_RMII_TXD1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(30, "PB14"), + STM32_FUNCTION(0, "GPIOB14"), + STM32_FUNCTION(2, "TIM1_CH2N"), + STM32_FUNCTION(4, "TIM8_CH2N"), + STM32_FUNCTION(6, "SPI2_MISO"), + STM32_FUNCTION(7, "I2S2EXT_SD"), + STM32_FUNCTION(8, "USART3_RTS"), + STM32_FUNCTION(10, "TIM12_CH1"), + STM32_FUNCTION(13, "OTG_HS_DM"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(31, "PB15"), + STM32_FUNCTION(0, "GPIOB15"), + STM32_FUNCTION(1, "RTC_REFIN"), + STM32_FUNCTION(2, "TIM1_CH3N"), + STM32_FUNCTION(4, "TIM8_CH3N"), + STM32_FUNCTION(6, "SPI2_MOSI I2S2_SD"), + STM32_FUNCTION(10, "TIM12_CH2"), + STM32_FUNCTION(13, "OTG_HS_DP"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(32, "PC0"), + STM32_FUNCTION(0, "GPIOC0"), + STM32_FUNCTION(11, "OTG_HS_ULPI_STP"), + STM32_FUNCTION(13, "FMC_SDNWE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(33, "PC1"), + STM32_FUNCTION(0, "GPIOC1"), + STM32_FUNCTION(12, "ETH_MDC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(34, "PC2"), + STM32_FUNCTION(0, "GPIOC2"), + STM32_FUNCTION(6, "SPI2_MISO"), + STM32_FUNCTION(7, "I2S2EXT_SD"), + STM32_FUNCTION(11, "OTG_HS_ULPI_DIR"), + STM32_FUNCTION(12, "ETH_MII_TXD2"), + STM32_FUNCTION(13, "FMC_SDNE0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(35, "PC3"), + STM32_FUNCTION(0, "GPIOC3"), + STM32_FUNCTION(6, "SPI2_MOSI I2S2_SD"), + STM32_FUNCTION(11, "OTG_HS_ULPI_NXT"), + STM32_FUNCTION(12, "ETH_MII_TX_CLK"), + STM32_FUNCTION(13, "FMC_SDCKE0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(36, "PC4"), + STM32_FUNCTION(0, "GPIOC4"), + STM32_FUNCTION(12, "ETH_MII_RXD0 ETH_RMII_RXD0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(37, "PC5"), + STM32_FUNCTION(0, "GPIOC5"), + STM32_FUNCTION(12, "ETH_MII_RXD1 ETH_RMII_RXD1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(38, "PC6"), + STM32_FUNCTION(0, "GPIOC6"), + STM32_FUNCTION(3, "TIM3_CH1"), + STM32_FUNCTION(4, "TIM8_CH1"), + STM32_FUNCTION(6, "I2S2_MCK"), + STM32_FUNCTION(9, "USART6_TX"), + STM32_FUNCTION(13, "SDIO_D6"), + STM32_FUNCTION(14, "DCMI_D0"), + STM32_FUNCTION(15, "LCD_HSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(39, "PC7"), + STM32_FUNCTION(0, "GPIOC7"), + STM32_FUNCTION(3, "TIM3_CH2"), + STM32_FUNCTION(4, "TIM8_CH2"), + STM32_FUNCTION(7, "I2S3_MCK"), + STM32_FUNCTION(9, "USART6_RX"), + STM32_FUNCTION(13, "SDIO_D7"), + STM32_FUNCTION(14, "DCMI_D1"), + STM32_FUNCTION(15, "LCD_G6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(40, "PC8"), + STM32_FUNCTION(0, "GPIOC8"), + STM32_FUNCTION(3, "TIM3_CH3"), + STM32_FUNCTION(4, "TIM8_CH3"), + STM32_FUNCTION(9, "USART6_CK"), + STM32_FUNCTION(13, "SDIO_D0"), + STM32_FUNCTION(14, "DCMI_D2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(41, "PC9"), + STM32_FUNCTION(0, "GPIOC9"), + STM32_FUNCTION(1, "MCO2"), + STM32_FUNCTION(3, "TIM3_CH4"), + STM32_FUNCTION(4, "TIM8_CH4"), + STM32_FUNCTION(5, "I2C3_SDA"), + STM32_FUNCTION(6, "I2S_CKIN"), + STM32_FUNCTION(13, "SDIO_D1"), + STM32_FUNCTION(14, "DCMI_D3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(42, "PC10"), + STM32_FUNCTION(0, "GPIOC10"), + STM32_FUNCTION(7, "SPI3_SCK I2S3_CK"), + STM32_FUNCTION(8, "USART3_TX"), + STM32_FUNCTION(9, "UART4_TX"), + STM32_FUNCTION(13, "SDIO_D2"), + STM32_FUNCTION(14, "DCMI_D8"), + STM32_FUNCTION(15, "LCD_R2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(43, "PC11"), + STM32_FUNCTION(0, "GPIOC11"), + STM32_FUNCTION(6, "I2S3EXT_SD"), + STM32_FUNCTION(7, "SPI3_MISO"), + STM32_FUNCTION(8, "USART3_RX"), + STM32_FUNCTION(9, "UART4_RX"), + STM32_FUNCTION(13, "SDIO_D3"), + STM32_FUNCTION(14, "DCMI_D4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(44, "PC12"), + STM32_FUNCTION(0, "GPIOC12"), + STM32_FUNCTION(7, "SPI3_MOSI I2S3_SD"), + STM32_FUNCTION(8, "USART3_CK"), + STM32_FUNCTION(9, "UART5_TX"), + STM32_FUNCTION(13, "SDIO_CK"), + STM32_FUNCTION(14, "DCMI_D9"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(45, "PC13"), + STM32_FUNCTION(0, "GPIOC13"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(46, "PC14"), + STM32_FUNCTION(0, "GPIOC14"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(47, "PC15"), + STM32_FUNCTION(0, "GPIOC15"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(48, "PD0"), + STM32_FUNCTION(0, "GPIOD0"), + STM32_FUNCTION(10, "CAN1_RX"), + STM32_FUNCTION(13, "FMC_D2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(49, "PD1"), + STM32_FUNCTION(0, "GPIOD1"), + STM32_FUNCTION(10, "CAN1_TX"), + STM32_FUNCTION(13, "FMC_D3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(50, "PD2"), + STM32_FUNCTION(0, "GPIOD2"), + STM32_FUNCTION(3, "TIM3_ETR"), + STM32_FUNCTION(9, "UART5_RX"), + STM32_FUNCTION(13, "SDIO_CMD"), + STM32_FUNCTION(14, "DCMI_D11"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(51, "PD3"), + STM32_FUNCTION(0, "GPIOD3"), + STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"), + STM32_FUNCTION(8, "USART2_CTS"), + STM32_FUNCTION(13, "FMC_CLK"), + STM32_FUNCTION(14, "DCMI_D5"), + STM32_FUNCTION(15, "LCD_G7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(52, "PD4"), + STM32_FUNCTION(0, "GPIOD4"), + STM32_FUNCTION(8, "USART2_RTS"), + STM32_FUNCTION(13, "FMC_NOE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(53, "PD5"), + STM32_FUNCTION(0, "GPIOD5"), + STM32_FUNCTION(8, "USART2_TX"), + STM32_FUNCTION(13, "FMC_NWE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(54, "PD6"), + STM32_FUNCTION(0, "GPIOD6"), + STM32_FUNCTION(6, "SPI3_MOSI I2S3_SD"), + STM32_FUNCTION(7, "SAI1_SD_A"), + STM32_FUNCTION(8, "USART2_RX"), + STM32_FUNCTION(13, "FMC_NWAIT"), + STM32_FUNCTION(14, "DCMI_D10"), + STM32_FUNCTION(15, "LCD_B2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(55, "PD7"), + STM32_FUNCTION(0, "GPIOD7"), + STM32_FUNCTION(8, "USART2_CK"), + STM32_FUNCTION(13, "FMC_NE1 FMC_NCE2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(56, "PD8"), + STM32_FUNCTION(0, "GPIOD8"), + STM32_FUNCTION(8, "USART3_TX"), + STM32_FUNCTION(13, "FMC_D13"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(57, "PD9"), + STM32_FUNCTION(0, "GPIOD9"), + STM32_FUNCTION(8, "USART3_RX"), + STM32_FUNCTION(13, "FMC_D14"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(58, "PD10"), + STM32_FUNCTION(0, "GPIOD10"), + STM32_FUNCTION(8, "USART3_CK"), + STM32_FUNCTION(13, "FMC_D15"), + STM32_FUNCTION(15, "LCD_B3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(59, "PD11"), + STM32_FUNCTION(0, "GPIOD11"), + STM32_FUNCTION(8, "USART3_CTS"), + STM32_FUNCTION(13, "FMC_A16"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(60, "PD12"), + STM32_FUNCTION(0, "GPIOD12"), + STM32_FUNCTION(3, "TIM4_CH1"), + STM32_FUNCTION(8, "USART3_RTS"), + STM32_FUNCTION(13, "FMC_A17"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(61, "PD13"), + STM32_FUNCTION(0, "GPIOD13"), + STM32_FUNCTION(3, "TIM4_CH2"), + STM32_FUNCTION(13, "FMC_A18"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(62, "PD14"), + STM32_FUNCTION(0, "GPIOD14"), + STM32_FUNCTION(3, "TIM4_CH3"), + STM32_FUNCTION(13, "FMC_D0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(63, "PD15"), + STM32_FUNCTION(0, "GPIOD15"), + STM32_FUNCTION(3, "TIM4_CH4"), + STM32_FUNCTION(13, "FMC_D1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(64, "PE0"), + STM32_FUNCTION(0, "GPIOE0"), + STM32_FUNCTION(3, "TIM4_ETR"), + STM32_FUNCTION(9, "UART8_RX"), + STM32_FUNCTION(13, "FMC_NBL0"), + STM32_FUNCTION(14, "DCMI_D2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(65, "PE1"), + STM32_FUNCTION(0, "GPIOE1"), + STM32_FUNCTION(9, "UART8_TX"), + STM32_FUNCTION(13, "FMC_NBL1"), + STM32_FUNCTION(14, "DCMI_D3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(66, "PE2"), + STM32_FUNCTION(0, "GPIOE2"), + STM32_FUNCTION(1, "TRACECLK"), + STM32_FUNCTION(6, "SPI4_SCK"), + STM32_FUNCTION(7, "SAI1_MCLK_A"), + STM32_FUNCTION(12, "ETH_MII_TXD3"), + STM32_FUNCTION(13, "FMC_A23"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(67, "PE3"), + STM32_FUNCTION(0, "GPIOE3"), + STM32_FUNCTION(1, "TRACED0"), + STM32_FUNCTION(7, "SAI1_SD_B"), + STM32_FUNCTION(13, "FMC_A19"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(68, "PE4"), + STM32_FUNCTION(0, "GPIOE4"), + STM32_FUNCTION(1, "TRACED1"), + STM32_FUNCTION(6, "SPI4_NSS"), + STM32_FUNCTION(7, "SAI1_FS_A"), + STM32_FUNCTION(13, "FMC_A20"), + STM32_FUNCTION(14, "DCMI_D4"), + STM32_FUNCTION(15, "LCD_B0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(69, "PE5"), + STM32_FUNCTION(0, "GPIOE5"), + STM32_FUNCTION(1, "TRACED2"), + STM32_FUNCTION(4, "TIM9_CH1"), + STM32_FUNCTION(6, "SPI4_MISO"), + STM32_FUNCTION(7, "SAI1_SCK_A"), + STM32_FUNCTION(13, "FMC_A21"), + STM32_FUNCTION(14, "DCMI_D6"), + STM32_FUNCTION(15, "LCD_G0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(70, "PE6"), + STM32_FUNCTION(0, "GPIOE6"), + STM32_FUNCTION(1, "TRACED3"), + STM32_FUNCTION(4, "TIM9_CH2"), + STM32_FUNCTION(6, "SPI4_MOSI"), + STM32_FUNCTION(7, "SAI1_SD_A"), + STM32_FUNCTION(13, "FMC_A22"), + STM32_FUNCTION(14, "DCMI_D7"), + STM32_FUNCTION(15, "LCD_G1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(71, "PE7"), + STM32_FUNCTION(0, "GPIOE7"), + STM32_FUNCTION(2, "TIM1_ETR"), + STM32_FUNCTION(9, "UART7_RX"), + STM32_FUNCTION(13, "FMC_D4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(72, "PE8"), + STM32_FUNCTION(0, "GPIOE8"), + STM32_FUNCTION(2, "TIM1_CH1N"), + STM32_FUNCTION(9, "UART7_TX"), + STM32_FUNCTION(13, "FMC_D5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(73, "PE9"), + STM32_FUNCTION(0, "GPIOE9"), + STM32_FUNCTION(2, "TIM1_CH1"), + STM32_FUNCTION(13, "FMC_D6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(74, "PE10"), + STM32_FUNCTION(0, "GPIOE10"), + STM32_FUNCTION(2, "TIM1_CH2N"), + STM32_FUNCTION(13, "FMC_D7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(75, "PE11"), + STM32_FUNCTION(0, "GPIOE11"), + STM32_FUNCTION(2, "TIM1_CH2"), + STM32_FUNCTION(6, "SPI4_NSS"), + STM32_FUNCTION(13, "FMC_D8"), + STM32_FUNCTION(15, "LCD_G3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(76, "PE12"), + STM32_FUNCTION(0, "GPIOE12"), + STM32_FUNCTION(2, "TIM1_CH3N"), + STM32_FUNCTION(6, "SPI4_SCK"), + STM32_FUNCTION(13, "FMC_D9"), + STM32_FUNCTION(15, "LCD_B4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(77, "PE13"), + STM32_FUNCTION(0, "GPIOE13"), + STM32_FUNCTION(2, "TIM1_CH3"), + STM32_FUNCTION(6, "SPI4_MISO"), + STM32_FUNCTION(13, "FMC_D10"), + STM32_FUNCTION(15, "LCD_DE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(78, "PE14"), + STM32_FUNCTION(0, "GPIOE14"), + STM32_FUNCTION(2, "TIM1_CH4"), + STM32_FUNCTION(6, "SPI4_MOSI"), + STM32_FUNCTION(13, "FMC_D11"), + STM32_FUNCTION(15, "LCD_CLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(79, "PE15"), + STM32_FUNCTION(0, "GPIOE15"), + STM32_FUNCTION(2, "TIM1_BKIN"), + STM32_FUNCTION(13, "FMC_D12"), + STM32_FUNCTION(15, "LCD_R7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(80, "PF0"), + STM32_FUNCTION(0, "GPIOF0"), + STM32_FUNCTION(5, "I2C2_SDA"), + STM32_FUNCTION(13, "FMC_A0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(81, "PF1"), + STM32_FUNCTION(0, "GPIOF1"), + STM32_FUNCTION(5, "I2C2_SCL"), + STM32_FUNCTION(13, "FMC_A1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(82, "PF2"), + STM32_FUNCTION(0, "GPIOF2"), + STM32_FUNCTION(5, "I2C2_SMBA"), + STM32_FUNCTION(13, "FMC_A2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(83, "PF3"), + STM32_FUNCTION(0, "GPIOF3"), + STM32_FUNCTION(13, "FMC_A3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(84, "PF4"), + STM32_FUNCTION(0, "GPIOF4"), + STM32_FUNCTION(13, "FMC_A4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(85, "PF5"), + STM32_FUNCTION(0, "GPIOF5"), + STM32_FUNCTION(13, "FMC_A5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(86, "PF6"), + STM32_FUNCTION(0, "GPIOF6"), + STM32_FUNCTION(4, "TIM10_CH1"), + STM32_FUNCTION(6, "SPI5_NSS"), + STM32_FUNCTION(7, "SAI1_SD_B"), + STM32_FUNCTION(9, "UART7_RX"), + STM32_FUNCTION(13, "FMC_NIORD"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(87, "PF7"), + STM32_FUNCTION(0, "GPIOF7"), + STM32_FUNCTION(4, "TIM11_CH1"), + STM32_FUNCTION(6, "SPI5_SCK"), + STM32_FUNCTION(7, "SAI1_MCLK_B"), + STM32_FUNCTION(9, "UART7_TX"), + STM32_FUNCTION(13, "FMC_NREG"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(88, "PF8"), + STM32_FUNCTION(0, "GPIOF8"), + STM32_FUNCTION(6, "SPI5_MISO"), + STM32_FUNCTION(7, "SAI1_SCK_B"), + STM32_FUNCTION(10, "TIM13_CH1"), + STM32_FUNCTION(13, "FMC_NIOWR"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(89, "PF9"), + STM32_FUNCTION(0, "GPIOF9"), + STM32_FUNCTION(6, "SPI5_MOSI"), + STM32_FUNCTION(7, "SAI1_FS_B"), + STM32_FUNCTION(10, "TIM14_CH1"), + STM32_FUNCTION(13, "FMC_CD"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(90, "PF10"), + STM32_FUNCTION(0, "GPIOF10"), + STM32_FUNCTION(13, "FMC_INTR"), + STM32_FUNCTION(14, "DCMI_D11"), + STM32_FUNCTION(15, "LCD_DE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(91, "PF11"), + STM32_FUNCTION(0, "GPIOF11"), + STM32_FUNCTION(6, "SPI5_MOSI"), + STM32_FUNCTION(13, "FMC_SDNRAS"), + STM32_FUNCTION(14, "DCMI_D12"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(92, "PF12"), + STM32_FUNCTION(0, "GPIOF12"), + STM32_FUNCTION(13, "FMC_A6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(93, "PF13"), + STM32_FUNCTION(0, "GPIOF13"), + STM32_FUNCTION(13, "FMC_A7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(94, "PF14"), + STM32_FUNCTION(0, "GPIOF14"), + STM32_FUNCTION(13, "FMC_A8"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(95, "PF15"), + STM32_FUNCTION(0, "GPIOF15"), + STM32_FUNCTION(13, "FMC_A9"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(96, "PG0"), + STM32_FUNCTION(0, "GPIOG0"), + STM32_FUNCTION(13, "FMC_A10"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(97, "PG1"), + STM32_FUNCTION(0, "GPIOG1"), + STM32_FUNCTION(13, "FMC_A11"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(98, "PG2"), + STM32_FUNCTION(0, "GPIOG2"), + STM32_FUNCTION(13, "FMC_A12"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(99, "PG3"), + STM32_FUNCTION(0, "GPIOG3"), + STM32_FUNCTION(13, "FMC_A13"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(100, "PG4"), + STM32_FUNCTION(0, "GPIOG4"), + STM32_FUNCTION(13, "FMC_A14 FMC_BA0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(101, "PG5"), + STM32_FUNCTION(0, "GPIOG5"), + STM32_FUNCTION(13, "FMC_A15 FMC_BA1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(102, "PG6"), + STM32_FUNCTION(0, "GPIOG6"), + STM32_FUNCTION(13, "FMC_INT2"), + STM32_FUNCTION(14, "DCMI_D12"), + STM32_FUNCTION(15, "LCD_R7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(103, "PG7"), + STM32_FUNCTION(0, "GPIOG7"), + STM32_FUNCTION(9, "USART6_CK"), + STM32_FUNCTION(13, "FMC_INT3"), + STM32_FUNCTION(14, "DCMI_D13"), + STM32_FUNCTION(15, "LCD_CLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(104, "PG8"), + STM32_FUNCTION(0, "GPIOG8"), + STM32_FUNCTION(6, "SPI6_NSS"), + STM32_FUNCTION(9, "USART6_RTS"), + STM32_FUNCTION(12, "ETH_PPS_OUT"), + STM32_FUNCTION(13, "FMC_SDCLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(105, "PG9"), + STM32_FUNCTION(0, "GPIOG9"), + STM32_FUNCTION(9, "USART6_RX"), + STM32_FUNCTION(13, "FMC_NE2 FMC_NCE3"), + STM32_FUNCTION(14, "DCMI_VSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(106, "PG10"), + STM32_FUNCTION(0, "GPIOG10"), + STM32_FUNCTION(10, "LCD_G3"), + STM32_FUNCTION(13, "FMC_NCE4_1 FMC_NE3"), + STM32_FUNCTION(14, "DCMI_D2"), + STM32_FUNCTION(15, "LCD_B2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(107, "PG11"), + STM32_FUNCTION(0, "GPIOG11"), + STM32_FUNCTION(12, "ETH_MII_TX_EN ETH_RMII_TX_EN"), + STM32_FUNCTION(13, "FMC_NCE4_2"), + STM32_FUNCTION(14, "DCMI_D3"), + STM32_FUNCTION(15, "LCD_B3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(108, "PG12"), + STM32_FUNCTION(0, "GPIOG12"), + STM32_FUNCTION(6, "SPI6_MISO"), + STM32_FUNCTION(9, "USART6_RTS"), + STM32_FUNCTION(10, "LCD_B4"), + STM32_FUNCTION(13, "FMC_NE4"), + STM32_FUNCTION(15, "LCD_B1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(109, "PG13"), + STM32_FUNCTION(0, "GPIOG13"), + STM32_FUNCTION(6, "SPI6_SCK"), + STM32_FUNCTION(9, "USART6_CTS"), + STM32_FUNCTION(12, "ETH_MII_TXD0 ETH_RMII_TXD0"), + STM32_FUNCTION(13, "FMC_A24"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(110, "PG14"), + STM32_FUNCTION(0, "GPIOG14"), + STM32_FUNCTION(6, "SPI6_MOSI"), + STM32_FUNCTION(9, "USART6_TX"), + STM32_FUNCTION(12, "ETH_MII_TXD1 ETH_RMII_TXD1"), + STM32_FUNCTION(13, "FMC_A25"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(111, "PG15"), + STM32_FUNCTION(0, "GPIOG15"), + STM32_FUNCTION(9, "USART6_CTS"), + STM32_FUNCTION(13, "FMC_SDNCAS"), + STM32_FUNCTION(14, "DCMI_D13"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(112, "PH0"), + STM32_FUNCTION(0, "GPIOH0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(113, "PH1"), + STM32_FUNCTION(0, "GPIOH1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(114, "PH2"), + STM32_FUNCTION(0, "GPIOH2"), + STM32_FUNCTION(12, "ETH_MII_CRS"), + STM32_FUNCTION(13, "FMC_SDCKE0"), + STM32_FUNCTION(15, "LCD_R0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(115, "PH3"), + STM32_FUNCTION(0, "GPIOH3"), + STM32_FUNCTION(12, "ETH_MII_COL"), + STM32_FUNCTION(13, "FMC_SDNE0"), + STM32_FUNCTION(15, "LCD_R1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(116, "PH4"), + STM32_FUNCTION(0, "GPIOH4"), + STM32_FUNCTION(5, "I2C2_SCL"), + STM32_FUNCTION(11, "OTG_HS_ULPI_NXT"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(117, "PH5"), + STM32_FUNCTION(0, "GPIOH5"), + STM32_FUNCTION(5, "I2C2_SDA"), + STM32_FUNCTION(6, "SPI5_NSS"), + STM32_FUNCTION(13, "FMC_SDNWE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(118, "PH6"), + STM32_FUNCTION(0, "GPIOH6"), + STM32_FUNCTION(5, "I2C2_SMBA"), + STM32_FUNCTION(6, "SPI5_SCK"), + STM32_FUNCTION(10, "TIM12_CH1"), + STM32_FUNCTION(12, "ETH_MII_RXD2"), + STM32_FUNCTION(13, "FMC_SDNE1"), + STM32_FUNCTION(14, "DCMI_D8"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(119, "PH7"), + STM32_FUNCTION(0, "GPIOH7"), + STM32_FUNCTION(5, "I2C3_SCL"), + STM32_FUNCTION(6, "SPI5_MISO"), + STM32_FUNCTION(12, "ETH_MII_RXD3"), + STM32_FUNCTION(13, "FMC_SDCKE1"), + STM32_FUNCTION(14, "DCMI_D9"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(120, "PH8"), + STM32_FUNCTION(0, "GPIOH8"), + STM32_FUNCTION(5, "I2C3_SDA"), + STM32_FUNCTION(13, "FMC_D16"), + STM32_FUNCTION(14, "DCMI_HSYNC"), + STM32_FUNCTION(15, "LCD_R2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(121, "PH9"), + STM32_FUNCTION(0, "GPIOH9"), + STM32_FUNCTION(5, "I2C3_SMBA"), + STM32_FUNCTION(10, "TIM12_CH2"), + STM32_FUNCTION(13, "FMC_D17"), + STM32_FUNCTION(14, "DCMI_D0"), + STM32_FUNCTION(15, "LCD_R3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(122, "PH10"), + STM32_FUNCTION(0, "GPIOH10"), + STM32_FUNCTION(3, "TIM5_CH1"), + STM32_FUNCTION(13, "FMC_D18"), + STM32_FUNCTION(14, "DCMI_D1"), + STM32_FUNCTION(15, "LCD_R4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(123, "PH11"), + STM32_FUNCTION(0, "GPIOH11"), + STM32_FUNCTION(3, "TIM5_CH2"), + STM32_FUNCTION(13, "FMC_D19"), + STM32_FUNCTION(14, "DCMI_D2"), + STM32_FUNCTION(15, "LCD_R5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(124, "PH12"), + STM32_FUNCTION(0, "GPIOH12"), + STM32_FUNCTION(3, "TIM5_CH3"), + STM32_FUNCTION(13, "FMC_D20"), + STM32_FUNCTION(14, "DCMI_D3"), + STM32_FUNCTION(15, "LCD_R6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(125, "PH13"), + STM32_FUNCTION(0, "GPIOH13"), + STM32_FUNCTION(4, "TIM8_CH1N"), + STM32_FUNCTION(10, "CAN1_TX"), + STM32_FUNCTION(13, "FMC_D21"), + STM32_FUNCTION(15, "LCD_G2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(126, "PH14"), + STM32_FUNCTION(0, "GPIOH14"), + STM32_FUNCTION(4, "TIM8_CH2N"), + STM32_FUNCTION(13, "FMC_D22"), + STM32_FUNCTION(14, "DCMI_D4"), + STM32_FUNCTION(15, "LCD_G3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(127, "PH15"), + STM32_FUNCTION(0, "GPIOH15"), + STM32_FUNCTION(4, "TIM8_CH3N"), + STM32_FUNCTION(13, "FMC_D23"), + STM32_FUNCTION(14, "DCMI_D11"), + STM32_FUNCTION(15, "LCD_G4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(128, "PI0"), + STM32_FUNCTION(0, "GPIOI0"), + STM32_FUNCTION(3, "TIM5_CH4"), + STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"), + STM32_FUNCTION(13, "FMC_D24"), + STM32_FUNCTION(14, "DCMI_D13"), + STM32_FUNCTION(15, "LCD_G5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(129, "PI1"), + STM32_FUNCTION(0, "GPIOI1"), + STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"), + STM32_FUNCTION(13, "FMC_D25"), + STM32_FUNCTION(14, "DCMI_D8"), + STM32_FUNCTION(15, "LCD_G6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(130, "PI2"), + STM32_FUNCTION(0, "GPIOI2"), + STM32_FUNCTION(4, "TIM8_CH4"), + STM32_FUNCTION(6, "SPI2_MISO"), + STM32_FUNCTION(7, "I2S2EXT_SD"), + STM32_FUNCTION(13, "FMC_D26"), + STM32_FUNCTION(14, "DCMI_D9"), + STM32_FUNCTION(15, "LCD_G7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(131, "PI3"), + STM32_FUNCTION(0, "GPIOI3"), + STM32_FUNCTION(4, "TIM8_ETR"), + STM32_FUNCTION(6, "SPI2_MOSI I2S2_SD"), + STM32_FUNCTION(13, "FMC_D27"), + STM32_FUNCTION(14, "DCMI_D10"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(132, "PI4"), + STM32_FUNCTION(0, "GPIOI4"), + STM32_FUNCTION(4, "TIM8_BKIN"), + STM32_FUNCTION(13, "FMC_NBL2"), + STM32_FUNCTION(14, "DCMI_D5"), + STM32_FUNCTION(15, "LCD_B4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(133, "PI5"), + STM32_FUNCTION(0, "GPIOI5"), + STM32_FUNCTION(4, "TIM8_CH1"), + STM32_FUNCTION(13, "FMC_NBL3"), + STM32_FUNCTION(14, "DCMI_VSYNC"), + STM32_FUNCTION(15, "LCD_B5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(134, "PI6"), + STM32_FUNCTION(0, "GPIOI6"), + STM32_FUNCTION(4, "TIM8_CH2"), + STM32_FUNCTION(13, "FMC_D28"), + STM32_FUNCTION(14, "DCMI_D6"), + STM32_FUNCTION(15, "LCD_B6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(135, "PI7"), + STM32_FUNCTION(0, "GPIOI7"), + STM32_FUNCTION(4, "TIM8_CH3"), + STM32_FUNCTION(13, "FMC_D29"), + STM32_FUNCTION(14, "DCMI_D7"), + STM32_FUNCTION(15, "LCD_B7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(136, "PI8"), + STM32_FUNCTION(0, "GPIOI8"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(137, "PI9"), + STM32_FUNCTION(0, "GPIOI9"), + STM32_FUNCTION(10, "CAN1_RX"), + STM32_FUNCTION(13, "FMC_D30"), + STM32_FUNCTION(15, "LCD_VSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(138, "PI10"), + STM32_FUNCTION(0, "GPIOI10"), + STM32_FUNCTION(12, "ETH_MII_RX_ER"), + STM32_FUNCTION(13, "FMC_D31"), + STM32_FUNCTION(15, "LCD_HSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(139, "PI11"), + STM32_FUNCTION(0, "GPIOI11"), + STM32_FUNCTION(11, "OTG_HS_ULPI_DIR"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(140, "PI12"), + STM32_FUNCTION(0, "GPIOI12"), + STM32_FUNCTION(15, "LCD_HSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(141, "PI13"), + STM32_FUNCTION(0, "GPIOI13"), + STM32_FUNCTION(15, "LCD_VSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(142, "PI14"), + STM32_FUNCTION(0, "GPIOI14"), + STM32_FUNCTION(15, "LCD_CLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(143, "PI15"), + STM32_FUNCTION(0, "GPIOI15"), + STM32_FUNCTION(15, "LCD_R0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(144, "PJ0"), + STM32_FUNCTION(0, "GPIOJ0"), + STM32_FUNCTION(15, "LCD_R1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(145, "PJ1"), + STM32_FUNCTION(0, "GPIOJ1"), + STM32_FUNCTION(15, "LCD_R2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(146, "PJ2"), + STM32_FUNCTION(0, "GPIOJ2"), + STM32_FUNCTION(15, "LCD_R3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(147, "PJ3"), + STM32_FUNCTION(0, "GPIOJ3"), + STM32_FUNCTION(15, "LCD_R4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(148, "PJ4"), + STM32_FUNCTION(0, "GPIOJ4"), + STM32_FUNCTION(15, "LCD_R5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(149, "PJ5"), + STM32_FUNCTION(0, "GPIOJ5"), + STM32_FUNCTION(15, "LCD_R6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(150, "PJ6"), + STM32_FUNCTION(0, "GPIOJ6"), + STM32_FUNCTION(15, "LCD_R7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(151, "PJ7"), + STM32_FUNCTION(0, "GPIOJ7"), + STM32_FUNCTION(15, "LCD_G0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(152, "PJ8"), + STM32_FUNCTION(0, "GPIOJ8"), + STM32_FUNCTION(15, "LCD_G1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(153, "PJ9"), + STM32_FUNCTION(0, "GPIOJ9"), + STM32_FUNCTION(15, "LCD_G2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(154, "PJ10"), + STM32_FUNCTION(0, "GPIOJ10"), + STM32_FUNCTION(15, "LCD_G3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(155, "PJ11"), + STM32_FUNCTION(0, "GPIOJ11"), + STM32_FUNCTION(15, "LCD_G4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(156, "PJ12"), + STM32_FUNCTION(0, "GPIOJ12"), + STM32_FUNCTION(15, "LCD_B0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(157, "PJ13"), + STM32_FUNCTION(0, "GPIOJ13"), + STM32_FUNCTION(15, "LCD_B1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(158, "PJ14"), + STM32_FUNCTION(0, "GPIOJ14"), + STM32_FUNCTION(15, "LCD_B2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(159, "PJ15"), + STM32_FUNCTION(0, "GPIOJ15"), + STM32_FUNCTION(15, "LCD_B3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(160, "PK0"), + STM32_FUNCTION(0, "GPIOK0"), + STM32_FUNCTION(15, "LCD_G5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(161, "PK1"), + STM32_FUNCTION(0, "GPIOK1"), + STM32_FUNCTION(15, "LCD_G6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(162, "PK2"), + STM32_FUNCTION(0, "GPIOK2"), + STM32_FUNCTION(15, "LCD_G7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(163, "PK3"), + STM32_FUNCTION(0, "GPIOK3"), + STM32_FUNCTION(15, "LCD_B4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(164, "PK4"), + STM32_FUNCTION(0, "GPIOK4"), + STM32_FUNCTION(15, "LCD_B5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(165, "PK5"), + STM32_FUNCTION(0, "GPIOK5"), + STM32_FUNCTION(15, "LCD_B6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(166, "PK6"), + STM32_FUNCTION(0, "GPIOK6"), + STM32_FUNCTION(15, "LCD_B7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(167, "PK7"), + STM32_FUNCTION(0, "GPIOK7"), + STM32_FUNCTION(15, "LCD_DE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), +}; + +static struct stm32_pinctrl_match_data stm32f429_match_data = { + .pins = stm32f429_pins, + .npins = ARRAY_SIZE(stm32f429_pins), +}; + +static const struct of_device_id stm32f429_pctrl_match[] = { + { + .compatible = "st,stm32f429-pinctrl", + .data = &stm32f429_match_data, + }, + { } +}; +MODULE_DEVICE_TABLE(of, stm32f429_pctrl_match); + +static struct platform_driver stm32f429_pinctrl_driver = { + .probe = stm32_pctl_probe, + .driver = { + .name = "stm32f429-pinctrl", + .of_match_table = stm32f429_pctrl_match, + }, +}; + +static int __init stm32f429_pinctrl_init(void) +{ + return platform_driver_register(&stm32f429_pinctrl_driver); +} + +module_init(stm32f429_pinctrl_init); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("STM32F429 Pinctrl Driver"); +MODULE_AUTHOR("Maxime Coquelin "); -- cgit v1.2.3 From cc301fd1fcf28f92b122f7f6105db9d7c182cccc Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 4 Jan 2016 12:44:10 -0500 Subject: pinctrl: mediatek: mt8* make driver explicitly non-modular The Kconfig for these drivers are currently: config PINCTRL_MT8127 bool "Mediatek MT8127 pin control" if COMPILE_TEST && !MACH_MT8127 config PINCTRL_MT8135 bool "Mediatek MT8135 pin control" if COMPILE_TEST && !MACH_MT8135 config PINCTRL_MT8173 bool "Mediatek MT8173 pin control" ...meaning that they are currently not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. A recent commit moved these from module_init to arch_initcall already, so the init ordering remains untouched with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. Cc: Daniel Kurtz Cc: Matthias Brugger Cc: Hongzhou Yang Cc: Yingjoe Chen Cc: linux-gpio@vger.kernel.org Cc: linux-mediatek@lists.infradead.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-mt8127.c | 8 +------- drivers/pinctrl/mediatek/pinctrl-mt8135.c | 8 +------- drivers/pinctrl/mediatek/pinctrl-mt8173.c | 8 +------- 3 files changed, 3 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8127.c b/drivers/pinctrl/mediatek/pinctrl-mt8127.c index 98e0bebfdf92..d76491574841 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt8127.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt8127.c @@ -13,7 +13,7 @@ * GNU General Public License for more details. */ -#include +#include #include #include #include @@ -336,7 +336,6 @@ static const struct of_device_id mt8127_pctrl_match[] = { { .compatible = "mediatek,mt8127-pinctrl", }, { } }; -MODULE_DEVICE_TABLE(of, mt8127_pctrl_match); static struct platform_driver mtk_pinctrl_driver = { .probe = mt8127_pinctrl_probe, @@ -350,9 +349,4 @@ static int __init mtk_pinctrl_init(void) { return platform_driver_register(&mtk_pinctrl_driver); } - arch_initcall(mtk_pinctrl_init); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("MediaTek MT8127 Pinctrl Driver"); -MODULE_AUTHOR("Yingjoe Chen "); diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8135.c b/drivers/pinctrl/mediatek/pinctrl-mt8135.c index 1c153b860f36..d8c645f16f21 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt8135.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt8135.c @@ -12,7 +12,7 @@ * GNU General Public License for more details. */ -#include +#include #include #include #include @@ -351,7 +351,6 @@ static const struct of_device_id mt8135_pctrl_match[] = { }, { } }; -MODULE_DEVICE_TABLE(of, mt8135_pctrl_match); static struct platform_driver mtk_pinctrl_driver = { .probe = mt8135_pinctrl_probe, @@ -365,9 +364,4 @@ static int __init mtk_pinctrl_init(void) { return platform_driver_register(&mtk_pinctrl_driver); } - arch_initcall(mtk_pinctrl_init); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("MediaTek Pinctrl Driver"); -MODULE_AUTHOR("Hongzhou Yang "); diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8173.c b/drivers/pinctrl/mediatek/pinctrl-mt8173.c index a62514eb2129..8bfd427b9135 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt8173.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt8173.c @@ -12,7 +12,7 @@ * GNU General Public License for more details. */ -#include +#include #include #include #include @@ -378,7 +378,6 @@ static const struct of_device_id mt8173_pctrl_match[] = { }, { } }; -MODULE_DEVICE_TABLE(of, mt8173_pctrl_match); static struct platform_driver mtk_pinctrl_driver = { .probe = mt8173_pinctrl_probe, @@ -393,9 +392,4 @@ static int __init mtk_pinctrl_init(void) { return platform_driver_register(&mtk_pinctrl_driver); } - arch_initcall(mtk_pinctrl_init); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("MediaTek Pinctrl Driver"); -MODULE_AUTHOR("Hongzhou Yang "); -- cgit v1.2.3 From 23c3960dfe6faea6fa8b8cb0bfedba2a03bda0c1 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 8 Jan 2016 10:50:30 -0800 Subject: pinctrl: freescale: imx: implement gpio_disable_free for Vybrid The Freescale Vybrid SoC has GPIO capabilities as part of the IOMUXC. To enable GPIO's, the gpio_request_enable callback has been implemented, however the corsponding gpio_disable_free callback is missing. So far, disabling (unexporting) a GPIO left the pin in its last state. Implement a proper gpio_disable_free function which clears the three enable bits which influence the state (IBE, OBE and PUE). Signed-off-by: Stefan Agner Signed-off-by: Linus Walleij --- drivers/pinctrl/freescale/pinctrl-imx.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c index a5bb93987378..4c435cfa5d6e 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx.c +++ b/drivers/pinctrl/freescale/pinctrl-imx.c @@ -341,6 +341,31 @@ mux_pin: return 0; } +static void imx_pmx_gpio_disable_free(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, unsigned offset) +{ + struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); + const struct imx_pinctrl_soc_info *info = ipctl->info; + const struct imx_pin_reg *pin_reg; + u32 reg; + + /* + * Only Vybrid has the input/output buffer enable flags (IBE/OBE) + * They are part of the shared mux/conf register. + */ + if (!(info->flags & SHARE_MUX_CONF_REG)) + return; + + pin_reg = &info->pin_regs[offset]; + if (pin_reg->mux_reg == -1) + return; + + /* Clear IBE/OBE/PUE to disable the pin (Hi-Z) */ + reg = readl(ipctl->base + pin_reg->mux_reg); + reg &= ~0x7; + writel(reg, ipctl->base + pin_reg->mux_reg); +} + static int imx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset, bool input) { @@ -377,6 +402,7 @@ static const struct pinmux_ops imx_pmx_ops = { .get_function_groups = imx_pmx_get_groups, .set_mux = imx_pmx_set, .gpio_request_enable = imx_pmx_gpio_request_enable, + .gpio_disable_free = imx_pmx_gpio_disable_free, .gpio_set_direction = imx_pmx_gpio_set_direction, }; -- cgit v1.2.3 From ae6d54fd695d7e1bd7b0bdaf457074ae4b5ad7bb Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 8 Jan 2016 12:25:53 -0800 Subject: pinctrl: qcom: spmi-mpp: Skip pullup on ULT type MPPs The ULT type of MPPs don't have a pullup. Skip configuring the pullup on these types of pins. Cc: Bjorn Andersson Signed-off-by: Stephen Boyd Reviewed-by: Andy Gross Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-spmi-mpp.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c index 2f18323571a6..2a3e5490a483 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c @@ -117,6 +117,7 @@ * @output_enabled: Set to true if MPP output logic is enabled. * @input_enabled: Set to true if MPP input buffer logic is enabled. * @paired: Pin operates in paired mode + * @has_pullup: Pin has support to configure pullup * @num_sources: Number of power-sources supported by this MPP. * @power_source: Current power-source used. * @amux_input: Set the source for analog input. @@ -134,6 +135,7 @@ struct pmic_mpp_pad { bool output_enabled; bool input_enabled; bool paired; + bool has_pullup; unsigned int num_sources; unsigned int power_source; unsigned int amux_input; @@ -477,11 +479,14 @@ static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin, if (ret < 0) return ret; - val = pad->pullup << PMIC_MPP_REG_PULL_SHIFT; + if (pad->has_pullup) { + val = pad->pullup << PMIC_MPP_REG_PULL_SHIFT; - ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_DIG_PULL_CTL, val); - if (ret < 0) - return ret; + ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_DIG_PULL_CTL, + val); + if (ret < 0) + return ret; + } val = pad->amux_input & PMIC_MPP_REG_AIN_ROUTE_MASK; @@ -534,7 +539,8 @@ static void pmic_mpp_config_dbg_show(struct pinctrl_dev *pctldev, seq_printf(s, " %-7s", pmic_mpp_functions[pad->function]); seq_printf(s, " vin-%d", pad->power_source); seq_printf(s, " %d", pad->aout_level); - seq_printf(s, " %-8s", biases[pad->pullup]); + if (pad->has_pullup) + seq_printf(s, " %-8s", biases[pad->pullup]); seq_printf(s, " %-4s", pad->out_value ? "high" : "low"); if (pad->dtest) seq_printf(s, " dtest%d", pad->dtest); @@ -748,12 +754,16 @@ static int pmic_mpp_populate(struct pmic_mpp_state *state, pad->power_source = val >> PMIC_MPP_REG_VIN_SHIFT; pad->power_source &= PMIC_MPP_REG_VIN_MASK; - val = pmic_mpp_read(state, pad, PMIC_MPP_REG_DIG_PULL_CTL); - if (val < 0) - return val; + if (subtype != PMIC_MPP_SUBTYPE_ULT_4CH_NO_ANA_OUT && + subtype != PMIC_MPP_SUBTYPE_ULT_4CH_NO_SINK) { + val = pmic_mpp_read(state, pad, PMIC_MPP_REG_DIG_PULL_CTL); + if (val < 0) + return val; - pad->pullup = val >> PMIC_MPP_REG_PULL_SHIFT; - pad->pullup &= PMIC_MPP_REG_PULL_MASK; + pad->pullup = val >> PMIC_MPP_REG_PULL_SHIFT; + pad->pullup &= PMIC_MPP_REG_PULL_MASK; + pad->has_pullup = true; + } val = pmic_mpp_read(state, pad, PMIC_MPP_REG_AIN_CTL); if (val < 0) -- cgit v1.2.3 From b3c6de492b9ea30a8dcc535d4dc2eaaf0bb3f116 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 21 Jan 2016 16:47:29 +0100 Subject: cleancache: constify cleancache_ops structure The cleancache_ops structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/tmem.c | 2 +- include/linux/cleancache.h | 2 +- mm/cleancache.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/xen/tmem.c b/drivers/xen/tmem.c index 945fc4327201..4ac2ca8a7656 100644 --- a/drivers/xen/tmem.c +++ b/drivers/xen/tmem.c @@ -242,7 +242,7 @@ static int tmem_cleancache_init_shared_fs(char *uuid, size_t pagesize) return xen_tmem_new_pool(shared_uuid, TMEM_POOL_SHARED, pagesize); } -static struct cleancache_ops tmem_cleancache_ops = { +static const struct cleancache_ops tmem_cleancache_ops = { .put_page = tmem_cleancache_put_page, .get_page = tmem_cleancache_get_page, .invalidate_page = tmem_cleancache_flush_page, diff --git a/include/linux/cleancache.h b/include/linux/cleancache.h index bda5ec0b4b4d..cb3e14234502 100644 --- a/include/linux/cleancache.h +++ b/include/linux/cleancache.h @@ -37,7 +37,7 @@ struct cleancache_ops { void (*invalidate_fs)(int); }; -extern int cleancache_register_ops(struct cleancache_ops *ops); +extern int cleancache_register_ops(const struct cleancache_ops *ops); extern void __cleancache_init_fs(struct super_block *); extern void __cleancache_init_shared_fs(struct super_block *); extern int __cleancache_get_page(struct page *); diff --git a/mm/cleancache.c b/mm/cleancache.c index 8fc50811119b..ba5d8f3e6d68 100644 --- a/mm/cleancache.c +++ b/mm/cleancache.c @@ -22,7 +22,7 @@ * cleancache_ops is set by cleancache_register_ops to contain the pointers * to the cleancache "backend" implementation functions. */ -static struct cleancache_ops *cleancache_ops __read_mostly; +static const struct cleancache_ops *cleancache_ops __read_mostly; /* * Counters available via /sys/kernel/debug/cleancache (if debugfs is @@ -49,7 +49,7 @@ static void cleancache_register_ops_sb(struct super_block *sb, void *unused) /* * Register operations for cleancache. Returns 0 on success. */ -int cleancache_register_ops(struct cleancache_ops *ops) +int cleancache_register_ops(const struct cleancache_ops *ops) { if (cmpxchg(&cleancache_ops, NULL, ops)) return -EBUSY; -- cgit v1.2.3 From 6333ef46bbe514a8ece6c432aab6bcf8637b2d7c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Jan 2016 16:38:59 +0000 Subject: regulator: core: Rely on regulator_dev_release to free constraints As we now free the constraints in regulator_dev_release we will still call free on the constraints pointer even if we went down an error path in regulator_register, because it is only allocated after the device_register. As such we no longer need to free rdev->constraints on the error paths, so this patch removes said frees. Fixes: 29f5f4860a8e ("regulator: core: Move more deallocation into class unregister") Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- drivers/regulator/core.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 744c9889f88d..4405be13eb0e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1057,18 +1057,18 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = machine_constraints_voltage(rdev, rdev->constraints); if (ret != 0) - goto out; + return ret; ret = machine_constraints_current(rdev, rdev->constraints); if (ret != 0) - goto out; + return ret; if (rdev->constraints->ilim_uA && ops->set_input_current_limit) { ret = ops->set_input_current_limit(rdev, rdev->constraints->ilim_uA); if (ret < 0) { rdev_err(rdev, "failed to set input limit\n"); - goto out; + return ret; } } @@ -1077,21 +1077,20 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = suspend_prepare(rdev, rdev->constraints->initial_state); if (ret < 0) { rdev_err(rdev, "failed to set suspend state\n"); - goto out; + return ret; } } if (rdev->constraints->initial_mode) { if (!ops->set_mode) { rdev_err(rdev, "no set_mode operation\n"); - ret = -EINVAL; - goto out; + return -EINVAL; } ret = ops->set_mode(rdev, rdev->constraints->initial_mode); if (ret < 0) { rdev_err(rdev, "failed to set initial mode: %d\n", ret); - goto out; + return ret; } } @@ -1102,7 +1101,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = _regulator_do_enable(rdev); if (ret < 0 && ret != -EINVAL) { rdev_err(rdev, "failed to enable\n"); - goto out; + return ret; } } @@ -1111,7 +1110,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); if (ret < 0) { rdev_err(rdev, "failed to set ramp_delay\n"); - goto out; + return ret; } } @@ -1119,7 +1118,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = ops->set_pull_down(rdev); if (ret < 0) { rdev_err(rdev, "failed to set pull down\n"); - goto out; + return ret; } } @@ -1127,7 +1126,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = ops->set_soft_start(rdev); if (ret < 0) { rdev_err(rdev, "failed to set soft start\n"); - goto out; + return ret; } } @@ -1136,16 +1135,12 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = ops->set_over_current_protection(rdev); if (ret < 0) { rdev_err(rdev, "failed to set over current protection\n"); - goto out; + return ret; } } print_constraints(rdev); return 0; -out: - kfree(rdev->constraints); - rdev->constraints = NULL; - return ret; } /** @@ -3979,7 +3974,7 @@ unset_supplies: scrub: regulator_ena_gpio_free(rdev); - kfree(rdev->constraints); + wash: device_unregister(&rdev->dev); /* device core frees rdev */ -- cgit v1.2.3 From 288a89bf436fa3682742d41b2bc1b243ff2ded85 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 25 Jan 2016 11:37:15 -0300 Subject: regulator: mt6397: Add platform device ID table The platform bus_type .match callback attempts to match the platform device name with an entry on the .id_table if provided and fallbacks to match with the driver's name if a table is not provided. Using a platform device ID to match is more explicit, allows the driver to support more than one device and also the MODULE_DEVICE_TABLE macro can be used to export the module aliases information instead of the MODULE_ALIAS. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- drivers/regulator/mt6397-regulator.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/regulator/mt6397-regulator.c b/drivers/regulator/mt6397-regulator.c index a5b2f4762677..585f0399a36b 100644 --- a/drivers/regulator/mt6397-regulator.c +++ b/drivers/regulator/mt6397-regulator.c @@ -317,11 +317,18 @@ static int mt6397_regulator_probe(struct platform_device *pdev) return 0; } +static const struct platform_device_id mt6397_platform_ids[] = { + {"mt6397-regulator", 0}, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(platform, mt6397_platform_ids); + static struct platform_driver mt6397_regulator_driver = { .driver = { .name = "mt6397-regulator", }, .probe = mt6397_regulator_probe, + .id_table = mt6397_platform_ids, }; module_platform_driver(mt6397_regulator_driver); @@ -329,4 +336,3 @@ module_platform_driver(mt6397_regulator_driver); MODULE_AUTHOR("Flora Fu "); MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6397 PMIC"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:mt6397-regulator"); -- cgit v1.2.3 From abbf043b6508f6c90477a183b6975c269e913c7b Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 25 Jan 2016 11:37:16 -0300 Subject: regulator: mt6397: Add OF match table The Documentation/devicetree/bindings/regulator/mt6397-regulator.txt doc mentions that a compatible "mediatek,mt6397-regulator" is required for the MT6397 device node but the driver doesn't provide a OF match table so the platform bus .match fallbacks to match using the driver name instead. This also means that module auto-loading is broken for this driver since the MFD driver that register the device, has a .of_compatible set so the platform .uevent callback reports a OF modalias that's not in the module. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- drivers/regulator/mt6397-regulator.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/regulator/mt6397-regulator.c b/drivers/regulator/mt6397-regulator.c index 585f0399a36b..17a5b6c2d6a9 100644 --- a/drivers/regulator/mt6397-regulator.c +++ b/drivers/regulator/mt6397-regulator.c @@ -323,9 +323,16 @@ static const struct platform_device_id mt6397_platform_ids[] = { }; MODULE_DEVICE_TABLE(platform, mt6397_platform_ids); +static const struct of_device_id mt6397_of_match[] = { + { .compatible = "mediatek,mt6397-regulator", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, mt6397_of_match); + static struct platform_driver mt6397_regulator_driver = { .driver = { .name = "mt6397-regulator", + .of_match_table = of_match_ptr(mt6397_of_match), }, .probe = mt6397_regulator_probe, .id_table = mt6397_platform_ids, -- cgit v1.2.3 From 89250fec1c2b7846cd994e91d8dd7398e67ae129 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 19 Jan 2016 15:26:26 +0200 Subject: drm/i915: Sanitize DMC/CSR ucode cleanup code commit ebae38d061df3deffa7c17b030ea14a5216ee55f Author: Animesh Manna Date: Wed Oct 28 23:58:55 2015 +0200 drm/i915/gen9: csr_init after runtime pm enable moved the DMC/CSR initialization later during driver loading, but didn't move the cleanup earlier correspondingly during unloading. Fix this up. Signed-off-by: Imre Deak Reviewed-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/1453209992-25995-2-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_dma.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index d70d96fe553b..4b2c073f20e7 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -404,7 +404,7 @@ static int i915_load_modeset_init(struct drm_device *dev) ret = intel_irq_install(dev_priv); if (ret) - goto cleanup_gem_stolen; + goto cleanup_csr; intel_setup_gmbus(dev); @@ -458,7 +458,8 @@ cleanup_irq: intel_guc_ucode_fini(dev); drm_irq_uninstall(dev); intel_teardown_gmbus(dev); -cleanup_gem_stolen: +cleanup_csr: + intel_csr_ucode_fini(dev_priv); i915_gem_cleanup_stolen(dev); cleanup_vga_switcheroo: vga_switcheroo_unregister_client(dev->pdev); @@ -945,7 +946,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ret = i915_gem_gtt_init(dev); if (ret) - goto out_freecsr; + goto out_uncore_fini; /* WARNING: Apparently we must kick fbdev drivers before vgacon, * otherwise the vga fbdev driver falls over. */ @@ -1115,8 +1116,7 @@ out_mtrrfree: io_mapping_free(dev_priv->gtt.mappable); out_gtt: i915_global_gtt_cleanup(dev); -out_freecsr: - intel_csr_ucode_fini(dev_priv); +out_uncore_fini: intel_uncore_fini(dev); pci_iounmap(dev->pdev, dev_priv->regs); put_bridge: @@ -1182,6 +1182,8 @@ int i915_driver_unload(struct drm_device *dev) vga_switcheroo_unregister_client(dev->pdev); vga_client_register(dev->pdev, NULL, NULL, NULL); + intel_csr_ucode_fini(dev_priv); + /* Free error state after interrupts are fully disabled. */ cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work); i915_destroy_error_state(dev); @@ -1202,8 +1204,6 @@ int i915_driver_unload(struct drm_device *dev) intel_fbc_cleanup_cfb(dev_priv); i915_gem_cleanup_stolen(dev); - intel_csr_ucode_fini(dev_priv); - intel_teardown_mchbar(dev); destroy_workqueue(dev_priv->hotplug.dp_wq); -- cgit v1.2.3 From 02036cee8373712d154a7cac76e1325f93fce9e5 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 19 Jan 2016 15:26:27 +0200 Subject: drm/i915: Sanitize i915_get_bridge_dev() error path Clarify the name of the label on the error path, making it clear what's being cleaned up. The kmem_cache_destroy() calls are NOPs on the corresponding error path. Signed-off-by: Imre Deak Reviewed-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/1453209992-25995-3-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_dma.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 4b2c073f20e7..5caea9e97fcf 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -916,7 +916,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (i915_get_bridge_dev(dev)) { ret = -EIO; - goto free_priv; + goto out_runtime_pm_put; } mmio_bar = IS_GEN2(dev) ? 1 : 0; @@ -1121,11 +1121,10 @@ out_uncore_fini: pci_iounmap(dev->pdev, dev_priv->regs); put_bridge: pci_dev_put(dev_priv->bridge_dev); -free_priv: kmem_cache_destroy(dev_priv->requests); kmem_cache_destroy(dev_priv->vmas); kmem_cache_destroy(dev_priv->objects); - +out_runtime_pm_put: intel_runtime_pm_put(dev_priv); kfree(dev_priv); -- cgit v1.2.3 From a8a40589257a280b49c7d9b744910036d11aac5d Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 19 Jan 2016 15:26:28 +0200 Subject: drm/i915: Sanitize GEM shrinker init and clean-up Factor out the common GEM shrinker clean-up code and call the shrinker init function from the same function from where the corresponding shrinker clean-up function is called. Also add sanity checking to the shrinker and OOM registration calls. Signed-off-by: Imre Deak Reviewed-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/1453209992-25995-4-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_dma.c | 7 +++---- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 2 -- drivers/gpu/drm/i915/i915_gem_shrinker.c | 16 ++++++++++++++-- 4 files changed, 18 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 5caea9e97fcf..adc5fe728bc5 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1035,6 +1035,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_opregion_setup(dev); i915_gem_load(dev); + i915_gem_shrinker_init(dev_priv); /* On the 945G/GM, the chipset reports the MSI capability on the * integrated graphics even though the support isn't actually there @@ -1098,8 +1099,7 @@ out_power_well: intel_power_domains_fini(dev_priv); drm_vblank_cleanup(dev); out_gem_unload: - WARN_ON(unregister_oom_notifier(&dev_priv->mm.oom_notifier)); - unregister_shrinker(&dev_priv->mm.shrinker); + i915_gem_shrinker_cleanup(dev_priv); if (dev->pdev->msi_enabled) pci_disable_msi(dev->pdev); @@ -1152,8 +1152,7 @@ int i915_driver_unload(struct drm_device *dev) i915_teardown_sysfs(dev); - WARN_ON(unregister_oom_notifier(&dev_priv->mm.oom_notifier)); - unregister_shrinker(&dev_priv->mm.shrinker); + i915_gem_shrinker_cleanup(dev_priv); io_mapping_free(dev_priv->gtt.mappable); arch_phys_wc_del(dev_priv->gtt.mtrr); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 211af534e5d0..abfb8c9e5a8c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3261,6 +3261,7 @@ unsigned long i915_gem_shrink(struct drm_i915_private *dev_priv, #define I915_SHRINK_ACTIVE 0x8 unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv); void i915_gem_shrinker_init(struct drm_i915_private *dev_priv); +void i915_gem_shrinker_cleanup(struct drm_i915_private *dev_priv); /* i915_gem_tiling.c */ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 371bbb28c471..7ce76c24a5c6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5100,8 +5100,6 @@ i915_gem_load(struct drm_device *dev) dev_priv->mm.interruptible = true; - i915_gem_shrinker_init(dev_priv); - mutex_init(&dev_priv->fb_tracking.lock); } diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 16da9c1422cc..58c1e592bbdb 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -367,8 +367,20 @@ void i915_gem_shrinker_init(struct drm_i915_private *dev_priv) dev_priv->mm.shrinker.scan_objects = i915_gem_shrinker_scan; dev_priv->mm.shrinker.count_objects = i915_gem_shrinker_count; dev_priv->mm.shrinker.seeks = DEFAULT_SEEKS; - register_shrinker(&dev_priv->mm.shrinker); + WARN_ON(register_shrinker(&dev_priv->mm.shrinker)); dev_priv->mm.oom_notifier.notifier_call = i915_gem_shrinker_oom; - register_oom_notifier(&dev_priv->mm.oom_notifier); + WARN_ON(register_oom_notifier(&dev_priv->mm.oom_notifier)); +} + +/** + * i915_gem_shrinker_cleanup - Clean up i915 shrinker + * @dev_priv: i915 device + * + * This function unregisters the i915 shrinker and OOM handler. + */ +void i915_gem_shrinker_cleanup(struct drm_i915_private *dev_priv) +{ + WARN_ON(unregister_oom_notifier(&dev_priv->mm.oom_notifier)); + unregister_shrinker(&dev_priv->mm.shrinker); } -- cgit v1.2.3 From d64aa096a4fb0f438563ad8126123766c2190aa8 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 19 Jan 2016 15:26:29 +0200 Subject: drm/i915: Sanitize i915_gem_load() init and clean-up Factor out common clean-up code for the GEM load time init function. Also rename i915_gem_load() to i915_gem_load_init() to have a better match with its new clean-up function. No functional change. Signed-off-by: Imre Deak Reviewed-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/1453209992-25995-5-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_dma.c | 10 +++------- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_gem.c | 11 ++++++++++- 3 files changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index adc5fe728bc5..348366cd471c 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1034,7 +1034,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_setup_mchbar(dev); intel_opregion_setup(dev); - i915_gem_load(dev); + i915_gem_load_init(dev); i915_gem_shrinker_init(dev_priv); /* On the 945G/GM, the chipset reports the MSI capability on the @@ -1121,9 +1121,7 @@ out_uncore_fini: pci_iounmap(dev->pdev, dev_priv->regs); put_bridge: pci_dev_put(dev_priv->bridge_dev); - kmem_cache_destroy(dev_priv->requests); - kmem_cache_destroy(dev_priv->vmas); - kmem_cache_destroy(dev_priv->objects); + i915_gem_load_cleanup(dev); out_runtime_pm_put: intel_runtime_pm_put(dev_priv); @@ -1215,9 +1213,7 @@ int i915_driver_unload(struct drm_device *dev) if (dev_priv->regs != NULL) pci_iounmap(dev->pdev, dev_priv->regs); - kmem_cache_destroy(dev_priv->requests); - kmem_cache_destroy(dev_priv->vmas); - kmem_cache_destroy(dev_priv->objects); + i915_gem_load_cleanup(dev); pci_dev_put(dev_priv->bridge_dev); kfree(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index abfb8c9e5a8c..905e90f25957 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2848,7 +2848,8 @@ int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -void i915_gem_load(struct drm_device *dev); +void i915_gem_load_init(struct drm_device *dev); +void i915_gem_load_cleanup(struct drm_device *dev); void *i915_gem_object_alloc(struct drm_device *dev); void i915_gem_object_free(struct drm_i915_gem_object *obj); void i915_gem_object_init(struct drm_i915_gem_object *obj, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 7ce76c24a5c6..c1bb6a61745c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5034,7 +5034,7 @@ init_ring_lists(struct intel_engine_cs *ring) } void -i915_gem_load(struct drm_device *dev) +i915_gem_load_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int i; @@ -5103,6 +5103,15 @@ i915_gem_load(struct drm_device *dev) mutex_init(&dev_priv->fb_tracking.lock); } +void i915_gem_load_cleanup(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = to_i915(dev); + + kmem_cache_destroy(dev_priv->requests); + kmem_cache_destroy(dev_priv->vmas); + kmem_cache_destroy(dev_priv->objects); +} + void i915_gem_release(struct drm_device *dev, struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; -- cgit v1.2.3 From 399bb5b6db027b1834d10496909d60214779126c Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 19 Jan 2016 15:26:30 +0200 Subject: drm/i915: Move allocation of various workqueues earlier during init Workqueue initalization doesn't depend on any other device specific resource, so move it close to the beginning, so we don't need to consider them when thinking about dependencies for other resources. Also factor out things to separate init/cleanup functions to make i915_driver_load()/unload() clearer, atm it's somewhat difficult to follow there in what order resources are inited/cleaned-up. Suggested-by: Chris Wilson Signed-off-by: Imre Deak Reviewed-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/1453209992-25995-6-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_dma.c | 101 ++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 348366cd471c..1446e6390227 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -856,6 +856,54 @@ static void intel_init_dpio(struct drm_i915_private *dev_priv) } } +static int i915_workqueues_init(struct drm_i915_private *dev_priv) +{ + /* + * The i915 workqueue is primarily used for batched retirement of + * requests (and thus managing bo) once the task has been completed + * by the GPU. i915_gem_retire_requests() is called directly when we + * need high-priority retirement, such as waiting for an explicit + * bo. + * + * It is also used for periodic low-priority events, such as + * idle-timers and recording error state. + * + * All tasks on the workqueue are expected to acquire the dev mutex + * so there is no point in running more than one instance of the + * workqueue at any time. Use an ordered one. + */ + dev_priv->wq = alloc_ordered_workqueue("i915", 0); + if (dev_priv->wq == NULL) + goto out_err; + + dev_priv->hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0); + if (dev_priv->hotplug.dp_wq == NULL) + goto out_free_wq; + + dev_priv->gpu_error.hangcheck_wq = + alloc_ordered_workqueue("i915-hangcheck", 0); + if (dev_priv->gpu_error.hangcheck_wq == NULL) + goto out_free_dp_wq; + + return 0; + +out_free_dp_wq: + destroy_workqueue(dev_priv->hotplug.dp_wq); +out_free_wq: + destroy_workqueue(dev_priv->wq); +out_err: + DRM_ERROR("Failed to allocate workqueues.\n"); + + return -ENOMEM; +} + +static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv) +{ + destroy_workqueue(dev_priv->gpu_error.hangcheck_wq); + destroy_workqueue(dev_priv->hotplug.dp_wq); + destroy_workqueue(dev_priv->wq); +} + /** * i915_driver_load - setup chip and create an initial config * @dev: DRM device @@ -898,6 +946,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) mutex_init(&dev_priv->modeset_restore_lock); mutex_init(&dev_priv->av_mutex); + ret = i915_workqueues_init(dev_priv); + if (ret < 0) + goto out_free_priv; + intel_pm_setup(dev); intel_runtime_pm_get(dev_priv); @@ -992,41 +1044,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev_priv->gtt.mtrr = arch_phys_wc_add(dev_priv->gtt.mappable_base, aperture_size); - /* The i915 workqueue is primarily used for batched retirement of - * requests (and thus managing bo) once the task has been completed - * by the GPU. i915_gem_retire_requests() is called directly when we - * need high-priority retirement, such as waiting for an explicit - * bo. - * - * It is also used for periodic low-priority events, such as - * idle-timers and recording error state. - * - * All tasks on the workqueue are expected to acquire the dev mutex - * so there is no point in running more than one instance of the - * workqueue at any time. Use an ordered one. - */ - dev_priv->wq = alloc_ordered_workqueue("i915", 0); - if (dev_priv->wq == NULL) { - DRM_ERROR("Failed to create our workqueue.\n"); - ret = -ENOMEM; - goto out_mtrrfree; - } - - dev_priv->hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0); - if (dev_priv->hotplug.dp_wq == NULL) { - DRM_ERROR("Failed to create our dp workqueue.\n"); - ret = -ENOMEM; - goto out_freewq; - } - - dev_priv->gpu_error.hangcheck_wq = - alloc_ordered_workqueue("i915-hangcheck", 0); - if (dev_priv->gpu_error.hangcheck_wq == NULL) { - DRM_ERROR("Failed to create our hangcheck workqueue.\n"); - ret = -ENOMEM; - goto out_freedpwq; - } - intel_irq_init(dev_priv); intel_uncore_sanitize(dev); @@ -1106,12 +1123,6 @@ out_gem_unload: intel_teardown_mchbar(dev); pm_qos_remove_request(&dev_priv->pm_qos); - destroy_workqueue(dev_priv->gpu_error.hangcheck_wq); -out_freedpwq: - destroy_workqueue(dev_priv->hotplug.dp_wq); -out_freewq: - destroy_workqueue(dev_priv->wq); -out_mtrrfree: arch_phys_wc_del(dev_priv->gtt.mtrr); io_mapping_free(dev_priv->gtt.mappable); out_gtt: @@ -1124,8 +1135,10 @@ put_bridge: i915_gem_load_cleanup(dev); out_runtime_pm_put: intel_runtime_pm_put(dev_priv); - + i915_workqueues_cleanup(dev_priv); +out_free_priv: kfree(dev_priv); + return ret; } @@ -1202,9 +1215,6 @@ int i915_driver_unload(struct drm_device *dev) intel_teardown_mchbar(dev); - destroy_workqueue(dev_priv->hotplug.dp_wq); - destroy_workqueue(dev_priv->wq); - destroy_workqueue(dev_priv->gpu_error.hangcheck_wq); pm_qos_remove_request(&dev_priv->pm_qos); i915_global_gtt_cleanup(dev); @@ -1215,6 +1225,7 @@ int i915_driver_unload(struct drm_device *dev) i915_gem_load_cleanup(dev); pci_dev_put(dev_priv->bridge_dev); + i915_workqueues_cleanup(dev_priv); kfree(dev_priv); return 0; -- cgit v1.2.3 From ad5c3d3ffbb26094b0b76751aef4ee4e4854996c Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 19 Jan 2016 15:26:31 +0200 Subject: drm/i915: Move MCHBAR setup earlier during init Move the MCHBAR setup right after the MMIO setup, since the two things are logically related and the MCHBAR setup code doesn't depend on any other device specific resource. We'll also need MCHBAR to be ready earlier in an upcoming patch, so this is also a preparation for that. Factor out the init/clean-up code to separate functions to make things clearer in the i915_driver_load()/unload() functions. Suggested-by: Chris Wilson Signed-off-by: Imre Deak Reviewed-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/1453209992-25995-7-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_dma.c | 71 ++++++++++++++++++++++++++--------------- 1 file changed, 45 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 1446e6390227..697807d925c4 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -904,6 +904,46 @@ static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv) destroy_workqueue(dev_priv->wq); } +static int i915_mmio_setup(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = to_i915(dev); + int mmio_bar; + int mmio_size; + + mmio_bar = IS_GEN2(dev) ? 1 : 0; + /* + * Before gen4, the registers and the GTT are behind different BARs. + * However, from gen4 onwards, the registers and the GTT are shared + * in the same BAR, so we want to restrict this ioremap from + * clobbering the GTT which we want ioremap_wc instead. Fortunately, + * the register BAR remains the same size for all the earlier + * generations up to Ironlake. + */ + if (INTEL_INFO(dev)->gen < 5) + mmio_size = 512 * 1024; + else + mmio_size = 2 * 1024 * 1024; + dev_priv->regs = pci_iomap(dev->pdev, mmio_bar, mmio_size); + if (dev_priv->regs == NULL) { + DRM_ERROR("failed to map registers\n"); + + return -EIO; + } + + /* Try to make sure MCHBAR is enabled before poking at it */ + intel_setup_mchbar(dev); + + return 0; +} + +static void i915_mmio_cleanup(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = to_i915(dev); + + intel_teardown_mchbar(dev); + pci_iounmap(dev->pdev, dev_priv->regs); +} + /** * i915_driver_load - setup chip and create an initial config * @dev: DRM device @@ -919,7 +959,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) { struct drm_i915_private *dev_priv; struct intel_device_info *info, *device_info; - int ret = 0, mmio_bar, mmio_size; + int ret = 0; uint32_t aperture_size; info = (struct intel_device_info *) flags; @@ -971,25 +1011,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto out_runtime_pm_put; } - mmio_bar = IS_GEN2(dev) ? 1 : 0; - /* Before gen4, the registers and the GTT are behind different BARs. - * However, from gen4 onwards, the registers and the GTT are shared - * in the same BAR, so we want to restrict this ioremap from - * clobbering the GTT which we want ioremap_wc instead. Fortunately, - * the register BAR remains the same size for all the earlier - * generations up to Ironlake. - */ - if (info->gen < 5) - mmio_size = 512*1024; - else - mmio_size = 2*1024*1024; - - dev_priv->regs = pci_iomap(dev->pdev, mmio_bar, mmio_size); - if (!dev_priv->regs) { - DRM_ERROR("failed to map registers\n"); - ret = -EIO; + ret = i915_mmio_setup(dev); + if (ret < 0) goto put_bridge; - } /* This must be called before any calls to HAS_PCH_* */ intel_detect_pch(dev); @@ -1047,8 +1071,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_irq_init(dev_priv); intel_uncore_sanitize(dev); - /* Try to make sure MCHBAR is enabled before poking at it */ - intel_setup_mchbar(dev); intel_opregion_setup(dev); i915_gem_load_init(dev); @@ -1129,7 +1151,7 @@ out_gtt: i915_global_gtt_cleanup(dev); out_uncore_fini: intel_uncore_fini(dev); - pci_iounmap(dev->pdev, dev_priv->regs); + i915_mmio_cleanup(dev); put_bridge: pci_dev_put(dev_priv->bridge_dev); i915_gem_load_cleanup(dev); @@ -1213,15 +1235,12 @@ int i915_driver_unload(struct drm_device *dev) intel_fbc_cleanup_cfb(dev_priv); i915_gem_cleanup_stolen(dev); - intel_teardown_mchbar(dev); - pm_qos_remove_request(&dev_priv->pm_qos); i915_global_gtt_cleanup(dev); intel_uncore_fini(dev); - if (dev_priv->regs != NULL) - pci_iounmap(dev->pdev, dev_priv->regs); + i915_mmio_cleanup(dev); i915_gem_load_cleanup(dev); pci_dev_put(dev_priv->bridge_dev); -- cgit v1.2.3 From a4eba47b25c7077b5b1473b950ae2ff9bcf19fd5 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 19 Jan 2016 15:26:32 +0200 Subject: drm/i915: Move stolen memory initialization earlier during loading The only device specific dependency of the stolen memory setup is the MMIO mapping and the stolen memory size. Both are already available in i915_gtt_init(), so move the stolen initialization to there. The clean-up code for i915_gtt_init() is in i915_global_gtt_cleanup(), so move the stolen memory clean-up code there too. This will be needed by an upcoming patch that needs the details of the memory we reserve, but the change is also part of our generic goal to move the initialization of resources with no or little dependencies on other device specific resources towards the beginning of the init sequence. Suggested-by: Chris Wilson Signed-off-by: Imre Deak Reviewed-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/1453209992-25995-8-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_dma.c | 10 ---------- drivers/gpu/drm/i915/i915_gem_gtt.c | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 697807d925c4..db9b0c6840a0 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -391,13 +391,6 @@ static int i915_load_modeset_init(struct drm_device *dev) if (ret) goto cleanup_vga_client; - /* Initialise stolen first so that we may reserve preallocated - * objects for the BIOS to KMS transition. - */ - ret = i915_gem_init_stolen(dev); - if (ret) - goto cleanup_vga_switcheroo; - intel_power_domains_init_hw(dev_priv, false); intel_csr_ucode_init(dev_priv); @@ -460,8 +453,6 @@ cleanup_irq: intel_teardown_gmbus(dev); cleanup_csr: intel_csr_ucode_fini(dev_priv); - i915_gem_cleanup_stolen(dev); -cleanup_vga_switcheroo: vga_switcheroo_unregister_client(dev->pdev); cleanup_vga_client: vga_client_register(dev->pdev, NULL, NULL, NULL); @@ -1233,7 +1224,6 @@ int i915_driver_unload(struct drm_device *dev) i915_gem_context_fini(dev); mutex_unlock(&dev->struct_mutex); intel_fbc_cleanup_cfb(dev_priv); - i915_gem_cleanup_stolen(dev); pm_qos_remove_request(&dev_priv->pm_qos); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 7377b6725c33..2ccb2b52e3bb 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2809,6 +2809,8 @@ void i915_global_gtt_cleanup(struct drm_device *dev) ppgtt->base.cleanup(&ppgtt->base); } + i915_gem_cleanup_stolen(dev); + if (drm_mm_initialized(&vm->mm)) { if (intel_vgpu_active(dev)) intel_vgt_deballoon(); @@ -3181,6 +3183,14 @@ int i915_gem_gtt_init(struct drm_device *dev) if (ret) return ret; + /* + * Initialise stolen early so that we may reserve preallocated + * objects for the BIOS to KMS transition. + */ + ret = i915_gem_init_stolen(dev); + if (ret) + goto out_gtt_cleanup; + /* GMADR is the PCI mmio aperture into the global GTT. */ DRM_INFO("Memory usable by graphics device = %lluM\n", gtt->base.total >> 20); @@ -3200,6 +3210,11 @@ int i915_gem_gtt_init(struct drm_device *dev) DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915.enable_ppgtt); return 0; + +out_gtt_cleanup: + gtt->base.cleanup(&dev_priv->gtt.base); + + return ret; } void i915_gem_restore_gtt_mappings(struct drm_device *dev) -- cgit v1.2.3 From b3e919e03ce84d9768c0e1c12066f502c5bbd485 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 25 Jan 2016 21:15:38 +0800 Subject: clk: sunxi: factors: Make struct clk_factors_config table const struct clk_factors_config contains shifts/widths for the factors of the factors clk. This is used to read out the factors from the register value. In no case is it written to, so make it const. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-factors.c | 4 ++-- drivers/clk/sunxi/clk-factors.h | 4 ++-- drivers/clk/sunxi/clk-mod0.c | 2 +- drivers/clk/sunxi/clk-sun9i-core.c | 8 ++++---- drivers/clk/sunxi/clk-sunxi.c | 16 ++++++++-------- 5 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index 59428dbd607a..928c079da193 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c @@ -48,7 +48,7 @@ static unsigned long clk_factors_recalc_rate(struct clk_hw *hw, u32 reg; unsigned long rate; struct clk_factors *factors = to_clk_factors(hw); - struct clk_factors_config *config = factors->config; + const struct clk_factors_config *config = factors->config; /* Fetch the register value */ reg = readl(factors->reg); @@ -123,7 +123,7 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, u8 n = 0, k = 0, m = 0, p = 0; u32 reg; struct clk_factors *factors = to_clk_factors(hw); - struct clk_factors_config *config = factors->config; + const struct clk_factors_config *config = factors->config; unsigned long flags = 0; factors->get_factors((u32 *)&rate, (u32)parent_rate, &n, &k, &m, &p); diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h index 171085ab5513..060319be2b99 100644 --- a/drivers/clk/sunxi/clk-factors.h +++ b/drivers/clk/sunxi/clk-factors.h @@ -23,7 +23,7 @@ struct factors_data { int enable; int mux; int muxmask; - struct clk_factors_config *table; + const struct clk_factors_config *table; void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p); const char *name; }; @@ -31,7 +31,7 @@ struct factors_data { struct clk_factors { struct clk_hw hw; void __iomem *reg; - struct clk_factors_config *config; + const struct clk_factors_config *config; void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p); spinlock_t *lock; }; diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c index d167e1efb927..c67fea1a128d 100644 --- a/drivers/clk/sunxi/clk-mod0.c +++ b/drivers/clk/sunxi/clk-mod0.c @@ -62,7 +62,7 @@ static void sun4i_a10_get_mod0_factors(u32 *freq, u32 parent_rate, } /* user manual says "n" but it's really "p" */ -static struct clk_factors_config sun4i_a10_mod0_config = { +static const struct clk_factors_config sun4i_a10_mod0_config = { .mshift = 0, .mwidth = 4, .pshift = 16, diff --git a/drivers/clk/sunxi/clk-sun9i-core.c b/drivers/clk/sunxi/clk-sun9i-core.c index 6c4c98324d3c..37c85caaef88 100644 --- a/drivers/clk/sunxi/clk-sun9i-core.c +++ b/drivers/clk/sunxi/clk-sun9i-core.c @@ -71,7 +71,7 @@ static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate, *p_ret = p; } -static struct clk_factors_config sun9i_a80_pll4_config = { +static const struct clk_factors_config sun9i_a80_pll4_config = { .mshift = 18, .mwidth = 1, .nshift = 8, @@ -134,7 +134,7 @@ static void sun9i_a80_get_gt_factors(u32 *freq, u32 parent_rate, *m = div; } -static struct clk_factors_config sun9i_a80_gt_config = { +static const struct clk_factors_config sun9i_a80_gt_config = { .mshift = 0, .mwidth = 2, }; @@ -199,7 +199,7 @@ static void sun9i_a80_get_ahb_factors(u32 *freq, u32 parent_rate, *p = _p; } -static struct clk_factors_config sun9i_a80_ahb_config = { +static const struct clk_factors_config sun9i_a80_ahb_config = { .pshift = 0, .pwidth = 2, }; @@ -289,7 +289,7 @@ static void sun9i_a80_get_apb1_factors(u32 *freq, u32 parent_rate, *p = calcp; } -static struct clk_factors_config sun9i_a80_apb1_config = { +static const struct clk_factors_config sun9i_a80_apb1_config = { .mshift = 0, .mwidth = 5, .pshift = 16, diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 5ba2188ee99c..3609f080cc9a 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -608,7 +608,7 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate, * sunxi_factors_clk_setup() - Setup function for factor clocks */ -static struct clk_factors_config sun4i_pll1_config = { +static const struct clk_factors_config sun4i_pll1_config = { .nshift = 8, .nwidth = 5, .kshift = 4, @@ -619,7 +619,7 @@ static struct clk_factors_config sun4i_pll1_config = { .pwidth = 2, }; -static struct clk_factors_config sun6i_a31_pll1_config = { +static const struct clk_factors_config sun6i_a31_pll1_config = { .nshift = 8, .nwidth = 5, .kshift = 4, @@ -629,7 +629,7 @@ static struct clk_factors_config sun6i_a31_pll1_config = { .n_start = 1, }; -static struct clk_factors_config sun8i_a23_pll1_config = { +static const struct clk_factors_config sun8i_a23_pll1_config = { .nshift = 8, .nwidth = 5, .kshift = 4, @@ -641,14 +641,14 @@ static struct clk_factors_config sun8i_a23_pll1_config = { .n_start = 1, }; -static struct clk_factors_config sun4i_pll5_config = { +static const struct clk_factors_config sun4i_pll5_config = { .nshift = 8, .nwidth = 5, .kshift = 4, .kwidth = 2, }; -static struct clk_factors_config sun6i_a31_pll6_config = { +static const struct clk_factors_config sun6i_a31_pll6_config = { .nshift = 8, .nwidth = 5, .kshift = 4, @@ -656,12 +656,12 @@ static struct clk_factors_config sun6i_a31_pll6_config = { .n_start = 1, }; -static struct clk_factors_config sun5i_a13_ahb_config = { +static const struct clk_factors_config sun5i_a13_ahb_config = { .pshift = 4, .pwidth = 2, }; -static struct clk_factors_config sun4i_apb1_config = { +static const struct clk_factors_config sun4i_apb1_config = { .mshift = 0, .mwidth = 5, .pshift = 16, @@ -669,7 +669,7 @@ static struct clk_factors_config sun4i_apb1_config = { }; /* user manual says "n" but it's really "p" */ -static struct clk_factors_config sun7i_a20_out_config = { +static const struct clk_factors_config sun7i_a20_out_config = { .mshift = 8, .mwidth = 5, .pshift = 20, -- cgit v1.2.3 From 08b21d30c6f619aa3718620a7de91207d28bdbc5 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 21 Jan 2016 19:24:44 +0800 Subject: drm/amd/powerplay: Update SMU firmware loading for Stoney Fix firmware init on Stoney when powerplay is enabled. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c | 41 ++++++++++++++++++------ 1 file changed, 32 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c index 873a8d264d5c..ec222c665602 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c @@ -272,6 +272,9 @@ static int cz_start_smu(struct pp_smumgr *smumgr) UCODE_ID_CP_MEC_JT1_MASK | UCODE_ID_CP_MEC_JT2_MASK; + if (smumgr->chip_id == CHIP_STONEY) + fw_to_check &= ~(UCODE_ID_SDMA1_MASK | UCODE_ID_CP_MEC_JT2_MASK); + cz_request_smu_load_fw(smumgr); cz_check_fw_load_finish(smumgr, fw_to_check); @@ -282,7 +285,7 @@ static int cz_start_smu(struct pp_smumgr *smumgr) return ret; } -static uint8_t cz_translate_firmware_enum_to_arg( +static uint8_t cz_translate_firmware_enum_to_arg(struct pp_smumgr *smumgr, enum cz_scratch_entry firmware_enum) { uint8_t ret = 0; @@ -292,7 +295,10 @@ static uint8_t cz_translate_firmware_enum_to_arg( ret = UCODE_ID_SDMA0; break; case CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1: - ret = UCODE_ID_SDMA1; + if (smumgr->chip_id == CHIP_STONEY) + ret = UCODE_ID_SDMA0; + else + ret = UCODE_ID_SDMA1; break; case CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE: ret = UCODE_ID_CP_CE; @@ -307,7 +313,10 @@ static uint8_t cz_translate_firmware_enum_to_arg( ret = UCODE_ID_CP_MEC_JT1; break; case CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2: - ret = UCODE_ID_CP_MEC_JT2; + if (smumgr->chip_id == CHIP_STONEY) + ret = UCODE_ID_CP_MEC_JT1; + else + ret = UCODE_ID_CP_MEC_JT2; break; case CZ_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG: ret = UCODE_ID_GMCON_RENG; @@ -396,7 +405,7 @@ static int cz_smu_populate_single_scratch_task( struct SMU_Task *task = &toc->tasks[cz_smu->toc_entry_used_count++]; task->type = type; - task->arg = cz_translate_firmware_enum_to_arg(fw_enum); + task->arg = cz_translate_firmware_enum_to_arg(smumgr, fw_enum); task->next = is_last ? END_OF_TASK_LIST : cz_smu->toc_entry_used_count; for (i = 0; i < cz_smu->scratch_buffer_length; i++) @@ -433,7 +442,7 @@ static int cz_smu_populate_single_ucode_load_task( struct SMU_Task *task = &toc->tasks[cz_smu->toc_entry_used_count++]; task->type = TASK_TYPE_UCODE_LOAD; - task->arg = cz_translate_firmware_enum_to_arg(fw_enum); + task->arg = cz_translate_firmware_enum_to_arg(smumgr, fw_enum); task->next = is_last ? END_OF_TASK_LIST : cz_smu->toc_entry_used_count; for (i = 0; i < cz_smu->driver_buffer_length; i++) @@ -509,8 +518,14 @@ static int cz_smu_construct_toc_for_vddgfx_exit(struct pp_smumgr *smumgr) CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false); cz_smu_populate_single_ucode_load_task(smumgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); - cz_smu_populate_single_ucode_load_task(smumgr, + + if (smumgr->chip_id == CHIP_STONEY) + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); + else + cz_smu_populate_single_ucode_load_task(smumgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false); + cz_smu_populate_single_ucode_load_task(smumgr, CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, false); @@ -551,7 +566,11 @@ static int cz_smu_construct_toc_for_bootup(struct pp_smumgr *smumgr) cz_smu_populate_single_ucode_load_task(smumgr, CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, false); - cz_smu_populate_single_ucode_load_task(smumgr, + if (smumgr->chip_id == CHIP_STONEY) + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, false); + else + cz_smu_populate_single_ucode_load_task(smumgr, CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1, false); cz_smu_populate_single_ucode_load_task(smumgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, false); @@ -561,7 +580,11 @@ static int cz_smu_construct_toc_for_bootup(struct pp_smumgr *smumgr) CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false); cz_smu_populate_single_ucode_load_task(smumgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); - cz_smu_populate_single_ucode_load_task(smumgr, + if (smumgr->chip_id == CHIP_STONEY) + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); + else + cz_smu_populate_single_ucode_load_task(smumgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false); cz_smu_populate_single_ucode_load_task(smumgr, CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, true); @@ -618,7 +641,7 @@ static int cz_smu_populate_firmware_entries(struct pp_smumgr *smumgr) for (i = 0; i < sizeof(firmware_list)/sizeof(*firmware_list); i++) { - firmware_type = cz_translate_firmware_enum_to_arg( + firmware_type = cz_translate_firmware_enum_to_arg(smumgr, firmware_list[i]); ucode_id = cz_convert_fw_type_to_cgs(firmware_type); -- cgit v1.2.3 From c9a392eac18409f51a071520cf508c0b4ad990e2 Mon Sep 17 00:00:00 2001 From: Slava Grigorev Date: Tue, 26 Jan 2016 16:45:10 -0500 Subject: drm/radeon: cleaned up VCO output settings for DP audio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is preparation for the fixes in the following patches. Signed-off-by: Slava Grigorev Reviewed-by: Alex Deucher Reviewed-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/dce6_afmt.c | 2 +- drivers/gpu/drm/radeon/radeon.h | 2 +- drivers/gpu/drm/radeon/radeon_atombios.c | 12 +++++++----- drivers/gpu/drm/radeon/radeon_audio.c | 8 +------- 4 files changed, 10 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 6bfc46369db1..ea4e3fc2744f 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -315,7 +315,7 @@ void dce6_dp_audio_set_dto(struct radeon_device *rdev, div = 0; if (div) - clock = rdev->clock.gpupll_outputfreq * 10 / div; + clock /= div; WREG32(DCE8_DCCG_AUDIO_DTO1_PHASE, 24000); WREG32(DCE8_DCCG_AUDIO_DTO1_MODULE, clock); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 5ae6db98aa4d..78a51b3eda10 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -268,7 +268,7 @@ struct radeon_clock { uint32_t current_dispclk; uint32_t dp_extclk; uint32_t max_pixel_clock; - uint32_t gpupll_outputfreq; + uint32_t vco_freq; }; /* diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 08fc1b5effa8..9a9363a7e5b9 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1257,12 +1257,14 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) rdev->mode_info.firmware_flags = le16_to_cpu(firmware_info->info.usFirmwareCapability.susAccess); - if (ASIC_IS_DCE8(rdev)) { - rdev->clock.gpupll_outputfreq = + if (ASIC_IS_DCE8(rdev)) + rdev->clock.vco_freq = le32_to_cpu(firmware_info->info_22.ulGPUPLL_OutputFreq); - if (rdev->clock.gpupll_outputfreq == 0) - rdev->clock.gpupll_outputfreq = 360000; /* 3.6 GHz */ - } + else + rdev->clock.vco_freq = rdev->clock.current_dispclk; + + if (rdev->clock.vco_freq == 0) + rdev->clock.vco_freq = 360000; /* 3.6 GHz */ return true; } diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index 2c02e99b5f95..85e1c234f020 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c @@ -739,9 +739,6 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); - struct radeon_connector *radeon_connector = to_radeon_connector(connector); - struct radeon_connector_atom_dig *dig_connector = - radeon_connector->con_priv; if (!dig || !dig->afmt) return; @@ -753,10 +750,7 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, radeon_audio_write_speaker_allocation(encoder); radeon_audio_write_sad_regs(encoder); radeon_audio_write_latency_fields(encoder, mode); - if (rdev->clock.dp_extclk || ASIC_IS_DCE5(rdev)) - radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10); - else - radeon_audio_set_dto(encoder, dig_connector->dp_clock); + radeon_audio_set_dto(encoder, rdev->clock.vco_freq * 10); radeon_audio_set_audio_packet(encoder); radeon_audio_select_pin(encoder); -- cgit v1.2.3 From a64c9dab1c4d05c87ec8a1cb9b48915816462143 Mon Sep 17 00:00:00 2001 From: Slava Grigorev Date: Tue, 26 Jan 2016 16:56:25 -0500 Subject: drm/radeon: Add a common function for DFS handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move encoding of DFS (digital frequency synthesizer) divider into a separate function and improve calculation precision. Signed-off-by: Slava Grigorev Reviewed-by: Alex Deucher Reviewed-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/dce6_afmt.c | 12 ++---------- drivers/gpu/drm/radeon/radeon_audio.c | 12 ++++++++++++ drivers/gpu/drm/radeon/radeon_audio.h | 1 + 3 files changed, 15 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index ea4e3fc2744f..367a916f364e 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -304,18 +304,10 @@ void dce6_dp_audio_set_dto(struct radeon_device *rdev, unsigned int div = (RREG32(DENTIST_DISPCLK_CNTL) & DENTIST_DPREFCLK_WDIVIDER_MASK) >> DENTIST_DPREFCLK_WDIVIDER_SHIFT; - - if (div < 128 && div >= 96) - div -= 64; - else if (div >= 64) - div = div / 2 - 16; - else if (div >= 8) - div /= 4; - else - div = 0; + div = radeon_audio_decode_dfs_div(div); if (div) - clock /= div; + clock = clock * 100 / div; WREG32(DCE8_DCCG_AUDIO_DTO1_PHASE, 24000); WREG32(DCE8_DCCG_AUDIO_DTO1_MODULE, clock); diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index 85e1c234f020..b214663b370d 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c @@ -775,3 +775,15 @@ void radeon_audio_dpms(struct drm_encoder *encoder, int mode) if (radeon_encoder->audio && radeon_encoder->audio->dpms) radeon_encoder->audio->dpms(encoder, mode == DRM_MODE_DPMS_ON); } + +unsigned int radeon_audio_decode_dfs_div(unsigned int div) +{ + if (div >= 8 && div < 64) + return (div - 8) * 25 + 200; + else if (div >= 64 && div < 96) + return (div - 64) * 50 + 1600; + else if (div >= 96 && div < 128) + return (div - 96) * 100 + 3200; + else + return 0; +} diff --git a/drivers/gpu/drm/radeon/radeon_audio.h b/drivers/gpu/drm/radeon/radeon_audio.h index 059cc3012062..5c70cceaa4a6 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.h +++ b/drivers/gpu/drm/radeon/radeon_audio.h @@ -79,5 +79,6 @@ void radeon_audio_fini(struct radeon_device *rdev); void radeon_audio_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode); void radeon_audio_dpms(struct drm_encoder *encoder, int mode); +unsigned int radeon_audio_decode_dfs_div(unsigned int div); #endif -- cgit v1.2.3 From fe6fc1f132b4300c1f6defd43a5d673eb60a820d Mon Sep 17 00:00:00 2001 From: Slava Grigorev Date: Tue, 26 Jan 2016 17:35:57 -0500 Subject: drm/radeon: fix DP audio support for APU with DCE4.1 display engine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Properly setup the DFS divider for DP audio for DCE4.1. Signed-off-by: Slava Grigorev Reviewed-by: Alex Deucher Reviewed-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/evergreen_hdmi.c | 10 +++++++++ drivers/gpu/drm/radeon/evergreend.h | 5 +++++ drivers/gpu/drm/radeon/radeon_atombios.c | 37 +++++++++++++++++++++++++------- 3 files changed, 44 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index 9953356fe263..3cf04a2f44bb 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -289,6 +289,16 @@ void dce4_dp_audio_set_dto(struct radeon_device *rdev, * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator */ + if (ASIC_IS_DCE41(rdev)) { + unsigned int div = (RREG32(DCE41_DENTIST_DISPCLK_CNTL) & + DENTIST_DPREFCLK_WDIVIDER_MASK) >> + DENTIST_DPREFCLK_WDIVIDER_SHIFT; + div = radeon_audio_decode_dfs_div(div); + + if (div) + clock = 100 * clock / div; + } + WREG32(DCCG_AUDIO_DTO1_PHASE, 24000); WREG32(DCCG_AUDIO_DTO1_MODULE, clock); } diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 4aa5f755572b..13b6029d65cc 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -511,6 +511,11 @@ #define DCCG_AUDIO_DTO1_CNTL 0x05cc # define DCCG_AUDIO_DTO1_USE_512FBR_DTO (1 << 3) +#define DCE41_DENTIST_DISPCLK_CNTL 0x049c +# define DENTIST_DPREFCLK_WDIVIDER(x) (((x) & 0x7f) << 24) +# define DENTIST_DPREFCLK_WDIVIDER_MASK (0x7f << 24) +# define DENTIST_DPREFCLK_WDIVIDER_SHIFT 24 + /* DCE 4.0 AFMT */ #define HDMI_CONTROL 0x7030 # define HDMI_KEEPOUT_MODE (1 << 0) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 9a9363a7e5b9..de9a2ffcf5f7 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1106,6 +1106,31 @@ union firmware_info { ATOM_FIRMWARE_INFO_V2_2 info_22; }; +union igp_info { + struct _ATOM_INTEGRATED_SYSTEM_INFO info; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 info_8; +}; + +static void radeon_atombios_get_dentist_vco_freq(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; + + if (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); + rdev->clock.vco_freq = + le32_to_cpu(igp_info->info_6.ulDentistVCOFreq); + } +} + bool radeon_atom_get_clock_info(struct drm_device *dev) { struct radeon_device *rdev = dev->dev_private; @@ -1260,6 +1285,10 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) if (ASIC_IS_DCE8(rdev)) rdev->clock.vco_freq = le32_to_cpu(firmware_info->info_22.ulGPUPLL_OutputFreq); + else if (ASIC_IS_DCE5(rdev)) + rdev->clock.vco_freq = rdev->clock.current_dispclk; + else if (ASIC_IS_DCE41(rdev)) + radeon_atombios_get_dentist_vco_freq(rdev); else rdev->clock.vco_freq = rdev->clock.current_dispclk; @@ -1272,14 +1301,6 @@ 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; - struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; - struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; - struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 info_8; -}; - bool radeon_atombios_sideport_present(struct radeon_device *rdev) { struct radeon_mode_info *mode_info = &rdev->mode_info; -- cgit v1.2.3 From 78ca95c76900e7587d6e076f8162a440f19431ae Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 25 Jan 2016 21:15:39 +0800 Subject: clk: sunxi: factors: Add clk cleanup in sunxi_factors_register() error path sunxi_factors_register() does not check for failures or cleanup after clk_register_composite() or other clk-related calls. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-factors.c | 44 +++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index 928c079da193..3a18abfb6e09 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c @@ -172,7 +172,7 @@ struct clk *sunxi_factors_register(struct device_node *node, struct clk_hw *mux_hw = NULL; const char *clk_name = node->name; const char *parents[FACTORS_MAX_PARENTS]; - int i = 0; + int ret, i = 0; /* if we have a mux, we will have >1 parents */ i = of_clk_parent_fill(node, parents, FACTORS_MAX_PARENTS); @@ -188,7 +188,7 @@ struct clk *sunxi_factors_register(struct device_node *node, factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL); if (!factors) - return NULL; + goto err_factors; /* set up factors properties */ factors->reg = reg; @@ -199,10 +199,8 @@ struct clk *sunxi_factors_register(struct device_node *node, /* Add a gate if this factor clock can be gated */ if (data->enable) { gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); - if (!gate) { - kfree(factors); - return NULL; - } + if (!gate) + goto err_gate; /* set up gate properties */ gate->reg = reg; @@ -214,11 +212,8 @@ struct clk *sunxi_factors_register(struct device_node *node, /* Add a mux if this factor clock can be muxed */ if (data->mux) { mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); - if (!mux) { - kfree(factors); - kfree(gate); - return NULL; - } + if (!mux) + goto err_mux; /* set up gate properties */ mux->reg = reg; @@ -233,11 +228,30 @@ struct clk *sunxi_factors_register(struct device_node *node, mux_hw, &clk_mux_ops, &factors->hw, &clk_factors_ops, gate_hw, &clk_gate_ops, 0); + if (IS_ERR(clk)) + goto err_register; - if (!IS_ERR(clk)) { - of_clk_add_provider(node, of_clk_src_simple_get, clk); - clk_register_clkdev(clk, clk_name, NULL); - } + ret = of_clk_add_provider(node, of_clk_src_simple_get, clk); + if (ret) + goto err_provider; + + ret = clk_register_clkdev(clk, clk_name, NULL); + if (ret) + goto err_clkdev; return clk; + +err_clkdev: + of_clk_del_provider(node); +err_provider: + /* TODO: The composite clock stuff will leak a bit here. */ + clk_unregister(clk); +err_register: + kfree(mux); +err_mux: + kfree(gate); +err_gate: + kfree(factors); +err_factors: + return NULL; } -- cgit v1.2.3 From 4cbeaebb8af1c86691d1a2d3328d82a01f4380a5 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 25 Jan 2016 21:15:40 +0800 Subject: clk: sunxi: factors: Add unregister function sunxi's factors clk did not have an unregister function. This means multiple structs were leaked whenever a factors clk was unregistered. Add an unregister function for it. Also keep pointers to the mux and gate structs so they can be freed. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-factors.c | 25 +++++++++++++++++++++++++ drivers/clk/sunxi/clk-factors.h | 5 +++++ 2 files changed, 30 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index 3a18abfb6e09..a6571177a5c4 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c @@ -202,6 +202,8 @@ struct clk *sunxi_factors_register(struct device_node *node, if (!gate) goto err_gate; + factors->gate = gate; + /* set up gate properties */ gate->reg = reg; gate->bit_idx = data->enable; @@ -215,6 +217,8 @@ struct clk *sunxi_factors_register(struct device_node *node, if (!mux) goto err_mux; + factors->mux = mux; + /* set up gate properties */ mux->reg = reg; mux->shift = data->mux; @@ -255,3 +259,24 @@ err_gate: err_factors: return NULL; } + +void sunxi_factors_unregister(struct device_node *node, struct clk *clk) +{ + struct clk_hw *hw = __clk_get_hw(clk); + struct clk_factors *factors; + const char *name; + + if (!hw) + return; + + factors = to_clk_factors(hw); + name = clk_hw_get_name(hw); + + /* No unregister call for clkdev_* */ + of_clk_del_provider(node); + /* TODO: The composite clock stuff will leak a bit here. */ + clk_unregister(clk); + kfree(factors->mux); + kfree(factors->gate); + kfree(factors); +} diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h index 060319be2b99..7ea1379a7cda 100644 --- a/drivers/clk/sunxi/clk-factors.h +++ b/drivers/clk/sunxi/clk-factors.h @@ -34,6 +34,9 @@ struct clk_factors { const struct clk_factors_config *config; void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p); spinlock_t *lock; + /* for cleanup */ + struct clk_mux *mux; + struct clk_gate *gate; }; struct clk *sunxi_factors_register(struct device_node *node, @@ -41,4 +44,6 @@ struct clk *sunxi_factors_register(struct device_node *node, spinlock_t *lock, void __iomem *reg); +void sunxi_factors_unregister(struct device_node *node, struct clk *clk); + #endif -- cgit v1.2.3 From cfa63688603398e8de4315cd626f81516c88a4c4 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 25 Jan 2016 21:15:42 +0800 Subject: clk: sunxi: factors: Consolidate get_factors parameters into a struct The .get_factors callback of factors_clk has 6 parameters. To extend factors_clk in any way that requires adding parameters to .get_factors would make that list even longer, not to mention changing all the function declarations. Do this once now and consolidate all the parameters into a struct. Also drop the space before function pointer arguments, since checkpatch complains. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-factors.c | 24 ++-- drivers/clk/sunxi/clk-factors.h | 13 ++- drivers/clk/sunxi/clk-mod0.c | 20 ++-- drivers/clk/sunxi/clk-sun8i-mbus.c | 18 +-- drivers/clk/sunxi/clk-sun9i-core.c | 77 +++++-------- drivers/clk/sunxi/clk-sunxi.c | 222 +++++++++++++++---------------------- 6 files changed, 155 insertions(+), 219 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index a6571177a5c4..4a8e36a53287 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c @@ -73,8 +73,13 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { struct clk_factors *factors = to_clk_factors(hw); - factors->get_factors((u32 *)&rate, (u32)*parent_rate, - NULL, NULL, NULL, NULL); + struct factors_request req = { + .rate = rate, + .parent_rate = *parent_rate, + }; + + factors->get_factors(&req); + return rate; } @@ -120,13 +125,16 @@ static int clk_factors_determine_rate(struct clk_hw *hw, static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - u8 n = 0, k = 0, m = 0, p = 0; + struct factors_request req = { + .rate = rate, + .parent_rate = parent_rate, + }; u32 reg; struct clk_factors *factors = to_clk_factors(hw); const struct clk_factors_config *config = factors->config; unsigned long flags = 0; - factors->get_factors((u32 *)&rate, (u32)parent_rate, &n, &k, &m, &p); + factors->get_factors(&req); if (factors->lock) spin_lock_irqsave(factors->lock, flags); @@ -135,10 +143,10 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, reg = readl(factors->reg); /* Set up the new factors - macros do not do anything if width is 0 */ - reg = FACTOR_SET(config->nshift, config->nwidth, reg, n); - reg = FACTOR_SET(config->kshift, config->kwidth, reg, k); - reg = FACTOR_SET(config->mshift, config->mwidth, reg, m); - reg = FACTOR_SET(config->pshift, config->pwidth, reg, p); + reg = FACTOR_SET(config->nshift, config->nwidth, reg, req.n); + reg = FACTOR_SET(config->kshift, config->kwidth, reg, req.k); + reg = FACTOR_SET(config->mshift, config->mwidth, reg, req.m); + reg = FACTOR_SET(config->pshift, config->pwidth, reg, req.p); /* Apply them now */ writel(reg, factors->reg); diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h index 7ea1379a7cda..f09d7c214533 100644 --- a/drivers/clk/sunxi/clk-factors.h +++ b/drivers/clk/sunxi/clk-factors.h @@ -19,12 +19,21 @@ struct clk_factors_config { u8 n_start; }; +struct factors_request { + unsigned long rate; + unsigned long parent_rate; + u8 n; + u8 k; + u8 m; + u8 p; +}; + struct factors_data { int enable; int mux; int muxmask; const struct clk_factors_config *table; - void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p); + void (*getter)(struct factors_request *req); const char *name; }; @@ -32,7 +41,7 @@ struct clk_factors { struct clk_hw hw; void __iomem *reg; const struct clk_factors_config *config; - void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p); + void (*get_factors)(struct factors_request *req); spinlock_t *lock; /* for cleanup */ struct clk_mux *mux; diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c index c67fea1a128d..578bff0dd251 100644 --- a/drivers/clk/sunxi/clk-mod0.c +++ b/drivers/clk/sunxi/clk-mod0.c @@ -28,17 +28,16 @@ * rate = (parent_rate >> p) / (m + 1); */ -static void sun4i_a10_get_mod0_factors(u32 *freq, u32 parent_rate, - u8 *n, u8 *k, u8 *m, u8 *p) +static void sun4i_a10_get_mod0_factors(struct factors_request *req) { u8 div, calcm, calcp; /* These clocks can only divide, so we will never be able to achieve * frequencies higher than the parent frequency */ - if (*freq > parent_rate) - *freq = parent_rate; + if (req->rate > req->parent_rate) + req->rate = req->parent_rate; - div = DIV_ROUND_UP(parent_rate, *freq); + div = DIV_ROUND_UP(req->parent_rate, req->rate); if (div < 16) calcp = 0; @@ -51,14 +50,9 @@ static void sun4i_a10_get_mod0_factors(u32 *freq, u32 parent_rate, calcm = DIV_ROUND_UP(div, 1 << calcp); - *freq = (parent_rate >> calcp) / calcm; - - /* we were called to round the frequency, we can now return */ - if (n == NULL) - return; - - *m = calcm - 1; - *p = calcp; + req->rate = (req->parent_rate >> calcp) / calcm; + req->m = calcm - 1; + req->p = calcp; } /* user manual says "n" but it's really "p" */ diff --git a/drivers/clk/sunxi/clk-sun8i-mbus.c b/drivers/clk/sunxi/clk-sun8i-mbus.c index bf117a636d23..78683f02a37d 100644 --- a/drivers/clk/sunxi/clk-sun8i-mbus.c +++ b/drivers/clk/sunxi/clk-sun8i-mbus.c @@ -26,8 +26,7 @@ * rate = parent_rate / (m + 1); */ -static void sun8i_a23_get_mbus_factors(u32 *freq, u32 parent_rate, - u8 *n, u8 *k, u8 *m, u8 *p) +static void sun8i_a23_get_mbus_factors(struct factors_request *req) { u8 div; @@ -35,21 +34,16 @@ static void sun8i_a23_get_mbus_factors(u32 *freq, u32 parent_rate, * These clocks can only divide, so we will never be able to * achieve frequencies higher than the parent frequency */ - if (*freq > parent_rate) - *freq = parent_rate; + if (req->rate > req->parent_rate) + req->rate = req->parent_rate; - div = DIV_ROUND_UP(parent_rate, *freq); + div = DIV_ROUND_UP(req->parent_rate, req->rate); if (div > 8) div = 8; - *freq = parent_rate / div; - - /* we were called to round the frequency, we can now return */ - if (m == NULL) - return; - - *m = div - 1; + req->rate = req->parent_rate / div; + req->m = div - 1; } static struct clk_factors_config sun8i_a23_mbus_config = { diff --git a/drivers/clk/sunxi/clk-sun9i-core.c b/drivers/clk/sunxi/clk-sun9i-core.c index 37c85caaef88..a81211062ecb 100644 --- a/drivers/clk/sunxi/clk-sun9i-core.c +++ b/drivers/clk/sunxi/clk-sun9i-core.c @@ -32,15 +32,14 @@ * p and m are named div1 and div2 in Allwinner's SDK */ -static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate, - u8 *n_ret, u8 *k, u8 *m_ret, u8 *p_ret) +static void sun9i_a80_get_pll4_factors(struct factors_request *req) { int n; int m = 1; int p = 1; /* Normalize value to a 6 MHz multiple (24 MHz / 4) */ - n = DIV_ROUND_UP(*freq, 6000000); + n = DIV_ROUND_UP(req->rate, 6000000); /* If n is too large switch to steps of 12 MHz */ if (n > 255) { @@ -60,15 +59,10 @@ static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate, else if (n < 12) n = 12; - *freq = ((24000000 * n) >> p) / (m + 1); - - /* we were called to round the frequency, we can now return */ - if (n_ret == NULL) - return; - - *n_ret = n; - *m_ret = m; - *p_ret = p; + req->rate = ((24000000 * n) >> p) / (m + 1); + req->n = n; + req->m = m; + req->p = p; } static const struct clk_factors_config sun9i_a80_pll4_config = { @@ -111,27 +105,21 @@ CLK_OF_DECLARE(sun9i_a80_pll4, "allwinner,sun9i-a80-pll4-clk", sun9i_a80_pll4_se * rate = parent_rate / (m + 1); */ -static void sun9i_a80_get_gt_factors(u32 *freq, u32 parent_rate, - u8 *n, u8 *k, u8 *m, u8 *p) +static void sun9i_a80_get_gt_factors(struct factors_request *req) { u32 div; - if (parent_rate < *freq) - *freq = parent_rate; + if (req->parent_rate < req->rate) + req->rate = req->parent_rate; - div = DIV_ROUND_UP(parent_rate, *freq); + div = DIV_ROUND_UP(req->parent_rate, req->rate); /* maximum divider is 4 */ if (div > 4) div = 4; - *freq = parent_rate / div; - - /* we were called to round the frequency, we can now return */ - if (!m) - return; - - *m = div; + req->rate = req->parent_rate / div; + req->m = div; } static const struct clk_factors_config sun9i_a80_gt_config = { @@ -176,27 +164,21 @@ CLK_OF_DECLARE(sun9i_a80_gt, "allwinner,sun9i-a80-gt-clk", sun9i_a80_gt_setup); * rate = parent_rate >> p; */ -static void sun9i_a80_get_ahb_factors(u32 *freq, u32 parent_rate, - u8 *n, u8 *k, u8 *m, u8 *p) +static void sun9i_a80_get_ahb_factors(struct factors_request *req) { u32 _p; - if (parent_rate < *freq) - *freq = parent_rate; + if (req->parent_rate < req->rate) + req->rate = req->parent_rate; - _p = order_base_2(DIV_ROUND_UP(parent_rate, *freq)); + _p = order_base_2(DIV_ROUND_UP(req->parent_rate, req->rate)); /* maximum p is 3 */ if (_p > 3) _p = 3; - *freq = parent_rate >> _p; - - /* we were called to round the frequency, we can now return */ - if (!p) - return; - - *p = _p; + req->rate = req->parent_rate >> _p; + req->p = _p; } static const struct clk_factors_config sun9i_a80_ahb_config = { @@ -262,31 +244,22 @@ CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-clk", sun9i_a80_apb0_se * rate = (parent_rate >> p) / (m + 1); */ -static void sun9i_a80_get_apb1_factors(u32 *freq, u32 parent_rate, - u8 *n, u8 *k, u8 *m, u8 *p) +static void sun9i_a80_get_apb1_factors(struct factors_request *req) { u32 div; - u8 calcm, calcp; - if (parent_rate < *freq) - *freq = parent_rate; + if (req->parent_rate < req->rate) + req->rate = req->parent_rate; - div = DIV_ROUND_UP(parent_rate, *freq); + div = DIV_ROUND_UP(req->parent_rate, req->rate); /* Highest possible divider is 256 (p = 3, m = 31) */ if (div > 256) div = 256; - calcp = order_base_2(div); - calcm = (parent_rate >> calcp) - 1; - *freq = (parent_rate >> calcp) / (calcm + 1); - - /* we were called to round the frequency, we can now return */ - if (n == NULL) - return; - - *m = calcm; - *p = calcp; + req->p = order_base_2(div); + req->m = (req->parent_rate >> req->p) - 1; + req->rate = (req->parent_rate >> req->p) / (req->m + 1); } static const struct clk_factors_config sun9i_a80_apb1_config = { diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 3609f080cc9a..a57c36c104dc 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -246,49 +246,45 @@ CLK_OF_DECLARE(sun6i_a31_ahb1, "allwinner,sun6i-a31-ahb1-clk", sun6i_ahb1_clk_se * parent_rate is always 24Mhz */ -static void sun4i_get_pll1_factors(u32 *freq, u32 parent_rate, - u8 *n, u8 *k, u8 *m, u8 *p) +static void sun4i_get_pll1_factors(struct factors_request *req) { u8 div; /* Normalize value to a 6M multiple */ - div = *freq / 6000000; - *freq = 6000000 * div; - - /* we were called to round the frequency, we can now return */ - if (n == NULL) - return; + div = req->rate / 6000000; + req->rate = 6000000 * div; /* m is always zero for pll1 */ - *m = 0; + req->m = 0; /* k is 1 only on these cases */ - if (*freq >= 768000000 || *freq == 42000000 || *freq == 54000000) - *k = 1; + if (req->rate >= 768000000 || req->rate == 42000000 || + req->rate == 54000000) + req->k = 1; else - *k = 0; + req->k = 0; /* p will be 3 for divs under 10 */ if (div < 10) - *p = 3; + req->p = 3; /* p will be 2 for divs between 10 - 20 and odd divs under 32 */ else if (div < 20 || (div < 32 && (div & 1))) - *p = 2; + req->p = 2; /* p will be 1 for even divs under 32, divs under 40 and odd pairs * of divs between 40-62 */ else if (div < 40 || (div < 64 && (div & 2))) - *p = 1; + req->p = 1; /* any other entries have p = 0 */ else - *p = 0; + req->p = 0; /* calculate a suitable n based on k and p */ - div <<= *p; - div /= (*k + 1); - *n = div / 4; + div <<= req->p; + div /= (req->k + 1); + req->n = div / 4; } /** @@ -297,15 +293,14 @@ static void sun4i_get_pll1_factors(u32 *freq, u32 parent_rate, * rate = parent_rate * (n + 1) * (k + 1) / (m + 1); * parent_rate should always be 24MHz */ -static void sun6i_a31_get_pll1_factors(u32 *freq, u32 parent_rate, - u8 *n, u8 *k, u8 *m, u8 *p) +static void sun6i_a31_get_pll1_factors(struct factors_request *req) { /* * We can operate only on MHz, this will make our life easier * later. */ - u32 freq_mhz = *freq / 1000000; - u32 parent_freq_mhz = parent_rate / 1000000; + u32 freq_mhz = req->rate / 1000000; + u32 parent_freq_mhz = req->parent_rate / 1000000; /* * Round down the frequency to the closest multiple of either @@ -319,28 +314,20 @@ static void sun6i_a31_get_pll1_factors(u32 *freq, u32 parent_rate, else freq_mhz = round_freq_16; - *freq = freq_mhz * 1000000; - - /* - * If the factors pointer are null, we were just called to - * round down the frequency. - * Exit. - */ - if (n == NULL) - return; + req->rate = freq_mhz * 1000000; /* If the frequency is a multiple of 32 MHz, k is always 3 */ if (!(freq_mhz % 32)) - *k = 3; + req->k = 3; /* If the frequency is a multiple of 9 MHz, k is always 2 */ else if (!(freq_mhz % 9)) - *k = 2; + req->k = 2; /* If the frequency is a multiple of 8 MHz, k is always 1 */ else if (!(freq_mhz % 8)) - *k = 1; + req->k = 1; /* Otherwise, we don't use the k factor */ else - *k = 0; + req->k = 0; /* * If the frequency is a multiple of 2 but not a multiple of @@ -351,27 +338,28 @@ static void sun6i_a31_get_pll1_factors(u32 *freq, u32 parent_rate, * somehow relates to this frequency. */ if ((freq_mhz % 6) == 2 || (freq_mhz % 6) == 4) - *m = 2; + req->m = 2; /* * If the frequency is a multiple of 6MHz, but the factor is * odd, m will be 3 */ else if ((freq_mhz / 6) & 1) - *m = 3; + req->m = 3; /* Otherwise, we end up with m = 1 */ else - *m = 1; + req->m = 1; /* Calculate n thanks to the above factors we already got */ - *n = freq_mhz * (*m + 1) / ((*k + 1) * parent_freq_mhz) - 1; + req->n = freq_mhz * (req->m + 1) / ((req->k + 1) * parent_freq_mhz) + - 1; /* * If n end up being outbound, and that we can still decrease * m, do it. */ - if ((*n + 1) > 31 && (*m + 1) > 1) { - *n = (*n + 1) / 2 - 1; - *m = (*m + 1) / 2 - 1; + if ((req->n + 1) > 31 && (req->m + 1) > 1) { + req->n = (req->n + 1) / 2 - 1; + req->m = (req->m + 1) / 2 - 1; } } @@ -382,45 +370,41 @@ static void sun6i_a31_get_pll1_factors(u32 *freq, u32 parent_rate, * parent_rate is always 24Mhz */ -static void sun8i_a23_get_pll1_factors(u32 *freq, u32 parent_rate, - u8 *n, u8 *k, u8 *m, u8 *p) +static void sun8i_a23_get_pll1_factors(struct factors_request *req) { u8 div; /* Normalize value to a 6M multiple */ - div = *freq / 6000000; - *freq = 6000000 * div; - - /* we were called to round the frequency, we can now return */ - if (n == NULL) - return; + div = req->rate / 6000000; + req->rate = 6000000 * div; /* m is always zero for pll1 */ - *m = 0; + req->m = 0; /* k is 1 only on these cases */ - if (*freq >= 768000000 || *freq == 42000000 || *freq == 54000000) - *k = 1; + if (req->rate >= 768000000 || req->rate == 42000000 || + req->rate == 54000000) + req->k = 1; else - *k = 0; + req->k = 0; /* p will be 2 for divs under 20 and odd divs under 32 */ if (div < 20 || (div < 32 && (div & 1))) - *p = 2; + req->p = 2; /* p will be 1 for even divs under 32, divs under 40 and odd pairs * of divs between 40-62 */ else if (div < 40 || (div < 64 && (div & 2))) - *p = 1; + req->p = 1; /* any other entries have p = 0 */ else - *p = 0; + req->p = 0; /* calculate a suitable n based on k and p */ - div <<= *p; - div /= (*k + 1); - *n = div / 4 - 1; + div <<= req->p; + div /= (req->k + 1); + req->n = div / 4 - 1; } /** @@ -430,29 +414,24 @@ static void sun8i_a23_get_pll1_factors(u32 *freq, u32 parent_rate, * parent_rate is always 24Mhz */ -static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate, - u8 *n, u8 *k, u8 *m, u8 *p) +static void sun4i_get_pll5_factors(struct factors_request *req) { u8 div; /* Normalize value to a parent_rate multiple (24M) */ - div = *freq / parent_rate; - *freq = parent_rate * div; - - /* we were called to round the frequency, we can now return */ - if (n == NULL) - return; + div = req->rate / req->parent_rate; + req->rate = req->parent_rate * div; if (div < 31) - *k = 0; + req->k = 0; else if (div / 2 < 31) - *k = 1; + req->k = 1; else if (div / 3 < 31) - *k = 2; + req->k = 2; else - *k = 3; + req->k = 3; - *n = DIV_ROUND_UP(div, (*k+1)); + req->n = DIV_ROUND_UP(div, (req->k + 1)); } /** @@ -462,24 +441,19 @@ static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate, * parent_rate is always 24Mhz */ -static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate, - u8 *n, u8 *k, u8 *m, u8 *p) +static void sun6i_a31_get_pll6_factors(struct factors_request *req) { u8 div; /* Normalize value to a parent_rate multiple (24M) */ - div = *freq / parent_rate; - *freq = parent_rate * div; + div = req->rate / req->parent_rate; + req->rate = req->parent_rate * div; - /* we were called to round the frequency, we can now return */ - if (n == NULL) - return; - - *k = div / 32; - if (*k > 3) - *k = 3; + req->k = div / 32; + if (req->k > 3) + req->k = 3; - *n = DIV_ROUND_UP(div, (*k+1)) - 1; + req->n = DIV_ROUND_UP(div, (req->k + 1)) - 1; } /** @@ -488,37 +462,32 @@ static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate, * rate = parent_rate >> p */ -static void sun5i_a13_get_ahb_factors(u32 *freq, u32 parent_rate, - u8 *n, u8 *k, u8 *m, u8 *p) +static void sun5i_a13_get_ahb_factors(struct factors_request *req) { u32 div; /* divide only */ - if (parent_rate < *freq) - *freq = parent_rate; + if (req->parent_rate < req->rate) + req->rate = req->parent_rate; /* * user manual says valid speed is 8k ~ 276M, but tests show it * can work at speeds up to 300M, just after reparenting to pll6 */ - if (*freq < 8000) - *freq = 8000; - if (*freq > 300000000) - *freq = 300000000; + if (req->rate < 8000) + req->rate = 8000; + if (req->rate > 300000000) + req->rate = 300000000; - div = order_base_2(DIV_ROUND_UP(parent_rate, *freq)); + div = order_base_2(DIV_ROUND_UP(req->parent_rate, req->rate)); /* p = 0 ~ 3 */ if (div > 3) div = 3; - *freq = parent_rate >> div; + req->rate = req->parent_rate >> div; - /* we were called to round the frequency, we can now return */ - if (p == NULL) - return; - - *p = div; + req->p = div; } /** @@ -527,39 +496,34 @@ static void sun5i_a13_get_ahb_factors(u32 *freq, u32 parent_rate, * rate = (parent_rate >> p) / (m + 1); */ -static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate, - u8 *n, u8 *k, u8 *m, u8 *p) +static void sun4i_get_apb1_factors(struct factors_request *req) { u8 calcm, calcp; + int div; - if (parent_rate < *freq) - *freq = parent_rate; + if (req->parent_rate < req->rate) + req->rate = req->parent_rate; - parent_rate = DIV_ROUND_UP(parent_rate, *freq); + div = DIV_ROUND_UP(req->parent_rate, req->rate); /* Invalid rate! */ - if (parent_rate > 32) + if (div > 32) return; - if (parent_rate <= 4) + if (div <= 4) calcp = 0; - else if (parent_rate <= 8) + else if (div <= 8) calcp = 1; - else if (parent_rate <= 16) + else if (div <= 16) calcp = 2; else calcp = 3; - calcm = (parent_rate >> calcp) - 1; - - *freq = (parent_rate >> calcp) / (calcm + 1); + calcm = (req->parent_rate >> calcp) - 1; - /* we were called to round the frequency, we can now return */ - if (n == NULL) - return; - - *m = calcm; - *p = calcp; + req->rate = (req->parent_rate >> calcp) / (calcm + 1); + req->m = calcm; + req->p = calcp; } @@ -571,17 +535,16 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate, * rate = (parent_rate >> p) / (m + 1); */ -static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate, - u8 *n, u8 *k, u8 *m, u8 *p) +static void sun7i_a20_get_out_factors(struct factors_request *req) { u8 div, calcm, calcp; /* These clocks can only divide, so we will never be able to achieve * frequencies higher than the parent frequency */ - if (*freq > parent_rate) - *freq = parent_rate; + if (req->rate > req->parent_rate) + req->rate = req->parent_rate; - div = DIV_ROUND_UP(parent_rate, *freq); + div = DIV_ROUND_UP(req->parent_rate, req->rate); if (div < 32) calcp = 0; @@ -594,14 +557,9 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate, calcm = DIV_ROUND_UP(div, 1 << calcp); - *freq = (parent_rate >> calcp) / calcm; - - /* we were called to round the frequency, we can now return */ - if (n == NULL) - return; - - *m = calcm - 1; - *p = calcp; + req->rate = (req->parent_rate >> calcp) / calcm; + req->m = calcm - 1; + req->p = calcp; } /** -- cgit v1.2.3 From 16ab8a5cbea463e4d14bf0ce698f11fa64b70ae1 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 27 Jan 2016 11:22:25 -0700 Subject: vfio/noiommu: Don't use iommu_present() to track fake groups Using iommu_present() to determine whether an IOMMU group is real or fake has some problems. First, apparently Power systems don't register an IOMMU on the device bus, so the groups and containers get marked as noiommu and then won't bind to their actual IOMMU driver. Second, I expect we'll run into the same issue as we try to support vGPUs through vfio, since they're likely to emulate this behavior of creating an IOMMU group on a virtual device and then providing a vfio IOMMU backend tailored to the sort of isolation they provide, which won't necessarily be fully compatible with the IOMMU API. The solution here is to use the existing iommudata interface to IOMMU groups, which allows us to easily identify the fake groups we've created for noiommu purposes. The iommudata we set is purely arbitrary since we're only comparing the address, so we use the address of the noiommu switch itself. Reported-by: Alexey Kardashevskiy Reviewed-by: Alexey Kardashevskiy Tested-by: Alexey Kardashevskiy Tested-by: Anatoly Burakov Tested-by: Santosh Shukla Fixes: 03a76b60f8ba ("vfio: Include No-IOMMU mode") Signed-off-by: Alex Williamson --- drivers/vfio/vfio.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 82f25cc1c460..ecca316386f5 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -123,8 +123,8 @@ struct iommu_group *vfio_iommu_group_get(struct device *dev) /* * With noiommu enabled, an IOMMU group will be created for a device * that doesn't already have one and doesn't have an iommu_ops on their - * bus. We use iommu_present() again in the main code to detect these - * fake groups. + * bus. We set iommudata simply to be able to identify these groups + * as special use and for reclamation later. */ if (group || !noiommu || iommu_present(dev->bus)) return group; @@ -134,6 +134,7 @@ struct iommu_group *vfio_iommu_group_get(struct device *dev) return NULL; iommu_group_set_name(group, "vfio-noiommu"); + iommu_group_set_iommudata(group, &noiommu, NULL); ret = iommu_group_add_device(group, dev); iommu_group_put(group); if (ret) @@ -158,7 +159,7 @@ EXPORT_SYMBOL_GPL(vfio_iommu_group_get); void vfio_iommu_group_put(struct iommu_group *group, struct device *dev) { #ifdef CONFIG_VFIO_NOIOMMU - if (!iommu_present(dev->bus)) + if (iommu_group_get_iommudata(group) == &noiommu) iommu_group_remove_device(dev); #endif @@ -190,16 +191,10 @@ static long vfio_noiommu_ioctl(void *iommu_data, return -ENOTTY; } -static int vfio_iommu_present(struct device *dev, void *unused) -{ - return iommu_present(dev->bus) ? 1 : 0; -} - static int vfio_noiommu_attach_group(void *iommu_data, struct iommu_group *iommu_group) { - return iommu_group_for_each_dev(iommu_group, NULL, - vfio_iommu_present) ? -EINVAL : 0; + return iommu_group_get_iommudata(iommu_group) == &noiommu ? 0 : -EINVAL; } static void vfio_noiommu_detach_group(void *iommu_data, @@ -323,8 +318,7 @@ static void vfio_group_unlock_and_free(struct vfio_group *group) /** * Group objects - create, release, get, put, search */ -static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group, - bool iommu_present) +static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group) { struct vfio_group *group, *tmp; struct device *dev; @@ -342,7 +336,9 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group, atomic_set(&group->container_users, 0); atomic_set(&group->opened, 0); group->iommu_group = iommu_group; - group->noiommu = !iommu_present; +#ifdef CONFIG_VFIO_NOIOMMU + group->noiommu = (iommu_group_get_iommudata(iommu_group) == &noiommu); +#endif group->nb.notifier_call = vfio_iommu_group_notifier; @@ -767,7 +763,7 @@ int vfio_add_group_dev(struct device *dev, group = vfio_group_get_from_iommu(iommu_group); if (!group) { - group = vfio_create_group(iommu_group, iommu_present(dev->bus)); + group = vfio_create_group(iommu_group); if (IS_ERR(group)) { iommu_group_put(iommu_group); return PTR_ERR(group); -- cgit v1.2.3 From a06c488da0b0c1eebf710017675f00b9d5f9cf42 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 26 Jan 2016 17:59:30 +0000 Subject: regmap: Add explict native endian flag to DT bindings Currently the binding document says that if no endianness is configured we use native endian but this is not in fact true for all binding types and we do have some devices that really want native endianness such as Broadcom MIPS SoCs where switching the endianness of the CPU also switches the endianness of external IPs. Provide an explicit option for this. Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regmap/regmap.txt | 11 +++++++---- drivers/base/regmap/regmap.c | 2 ++ 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/regmap/regmap.txt b/Documentation/devicetree/bindings/regmap/regmap.txt index b494f8b8ef72..e98a9652ccc8 100644 --- a/Documentation/devicetree/bindings/regmap/regmap.txt +++ b/Documentation/devicetree/bindings/regmap/regmap.txt @@ -5,15 +5,18 @@ Index Device Endianness properties --------------------------------------------------- 1 BE 'big-endian' 2 LE 'little-endian' +3 Native 'native-endian' For one device driver, which will run in different scenarios above on different SoCs using the devicetree, we need one way to simplify this. -Required properties: -- {big,little}-endian: these are boolean properties, if absent - meaning that the CPU and the Device are in the same endianness mode, - these properties are for register values and all the buffers only. +Optional properties: +- {big,little,native}-endian: these are boolean properties, if absent + then the implementation will choose a default based on the device + being controlled. These properties are for register values and all + the buffers only. Native endian means that the CPU and device have + the same endianness. Examples: Scenario 1 : CPU in LE mode & device in LE mode. diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index ee54e841de4a..343263449aff 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -557,6 +557,8 @@ enum regmap_endian regmap_get_val_endian(struct device *dev, endian = REGMAP_ENDIAN_BIG; else if (of_property_read_bool(np, "little-endian")) endian = REGMAP_ENDIAN_LITTLE; + else if (of_property_read_bool(np, "native-endian")) + endian = REGMAP_ENDIAN_NATIVE; /* If the endianness was specified in DT, use that */ if (endian != REGMAP_ENDIAN_DEFAULT) -- cgit v1.2.3 From 57480484f9f7631738ef28b952eca3c9081c4291 Mon Sep 17 00:00:00 2001 From: "Jon Medhurst (Tixy)" Date: Tue, 26 Jan 2016 17:59:13 +0000 Subject: component: Detach components when deleting master struct component_master_add_with_match calls find_components which, if any components already exist, it attaches to the master struct. However, if we later encounter an error the master struct is deleted, leaving components with a dangling pointer to it. If the error was a temporary one, e.g. for probe deferral, then when the master device is re-probed, it will fail to find the required components as they appear to already be attached to a master. Fix this by nulling components pointers to the master struct when it is deleted. This code is factored out into a separate function so it can be shared with component_master_del. Signed-off-by: Jon Medhurst Signed-off-by: Russell King --- drivers/base/component.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/base/component.c b/drivers/base/component.c index 05cd26c02449..2738039aae9e 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c @@ -285,6 +285,24 @@ void component_match_add_release(struct device *master, } EXPORT_SYMBOL(component_match_add_release); +static void free_master(struct master *master) +{ + struct component_match *match = master->match; + int i; + + list_del(&master->node); + + if (match) { + for (i = 0; i < match->num; i++) { + struct component *c = match->compare[i].component; + if (c) + c->master = NULL; + } + } + + kfree(master); +} + int component_master_add_with_match(struct device *dev, const struct component_master_ops *ops, struct component_match *match) @@ -311,11 +329,9 @@ int component_master_add_with_match(struct device *dev, ret = try_to_bring_up_master(master, NULL); - if (ret < 0) { - /* Delete off the list if we weren't successful */ - list_del(&master->node); - kfree(master); - } + if (ret < 0) + free_master(master); + mutex_unlock(&component_mutex); return ret < 0 ? ret : 0; @@ -326,25 +342,12 @@ void component_master_del(struct device *dev, const struct component_master_ops *ops) { struct master *master; - int i; mutex_lock(&component_mutex); master = __master_find(dev, ops); if (master) { - struct component_match *match = master->match; - take_down_master(master); - - list_del(&master->node); - - if (match) { - for (i = 0; i < match->num; i++) { - struct component *c = match->compare[i].component; - if (c) - c->master = NULL; - } - } - kfree(master); + free_master(master); } mutex_unlock(&component_mutex); } -- cgit v1.2.3 From febe6569fae4b5e663f0a31d9dbf054d3b588ff5 Mon Sep 17 00:00:00 2001 From: Jens Kuske Date: Wed, 27 Jan 2016 14:51:13 +0100 Subject: drivers: soc: sunxi: Fix mask generation for SRAM mapping GENMASK is inclusive on both ends, therefor one has to be subtracted from the width. Also fixes the mask for debug output. Signed-off-by: Jens Kuske Signed-off-by: Maxime Ripard --- drivers/soc/sunxi/sunxi_sram.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index bc52670c8f4b..99e354c8f53f 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -117,7 +117,7 @@ static int sunxi_sram_show(struct seq_file *s, void *data) val = readl(base + sram_data->reg); val >>= sram_data->offset; - val &= sram_data->width; + val &= GENMASK(sram_data->width - 1, 0); for (func = sram_data->func; func->func; func++) { seq_printf(s, "\t\t%s%c\n", func->func, @@ -208,7 +208,8 @@ int sunxi_sram_claim(struct device *dev) return -EBUSY; } - mask = GENMASK(sram_data->offset + sram_data->width, sram_data->offset); + mask = GENMASK(sram_data->offset + sram_data->width - 1, + sram_data->offset); val = readl(base + sram_data->reg); val &= ~mask; writel(val | ((device << sram_data->offset) & mask), -- cgit v1.2.3 From 922a9f936e40001f9b921379aab90047d5990923 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 27 Jan 2016 04:50:07 +0000 Subject: regmap: mmio: Convert to regmap_bus and fix accessor usage Currently regmap-mmio uses the __raw accessors to read and write from memory. This is not safe as these interact poorly with spinlocks and are not guaranteed to generate emulated instructions on at least ARM where regmap is commonly used. The APIs that are provided all provide some byte swapping so this is difficult to do with the current regmap-mmio implementation which attempts to use the regmap core byte swapping. We can fix this by modernising the MMIO implementation to use reg_read() and reg_write() operations which were added after the API was implemented and pass simple unsigned integers through to the bus, making use of the formatting provided by the I/O accessors using a similar pattern to that used by the core. This will be less efficient for block I/O operations since we now enable and disable any required clocks per register but it is not clear that any users of regmap-mmio actually use block I/O and there is room to optimise later. This removes support for big endian I/O on 64 bit registers since no I/O accessors are provided, no current users were found and support can be added easily once they are available. In addition make the default endianness little endian. This was the behaviour prior to 29bb45f25ff305 (regmap-mmio: Use native endianness for read/write) and is the behaviour desired by most existing users, the users have been audited and those that need native endianness converted to request it explicitly. Previously native was documented as the default but due to the byte swapping in the accessors this was not correctly implemented. Fixes: 29bb45f25ff305 (regmap-mmio: Use native endianness for read/write) Reported-by: Johannes Berg Tested-by: Johannes Berg Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-mmio.c | 259 ++++++++++++++++++++------------------ 1 file changed, 139 insertions(+), 120 deletions(-) (limited to 'drivers') diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index 8812bfb9e3b8..7526906ca080 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c @@ -25,26 +25,14 @@ struct regmap_mmio_context { void __iomem *regs; - unsigned reg_bytes; unsigned val_bytes; - unsigned pad_bytes; struct clk *clk; -}; -static inline void regmap_mmio_regsize_check(size_t reg_size) -{ - switch (reg_size) { - case 1: - case 2: - case 4: -#ifdef CONFIG_64BIT - case 8: -#endif - break; - default: - BUG(); - } -} + void (*reg_write)(struct regmap_mmio_context *ctx, + unsigned int reg, unsigned int val); + unsigned int (*reg_read)(struct regmap_mmio_context *ctx, + unsigned int reg); +}; static int regmap_mmio_regbits_check(size_t reg_bits) { @@ -88,72 +76,62 @@ static int regmap_mmio_get_min_stride(size_t val_bits) return min_stride; } -static inline void regmap_mmio_count_check(size_t count, u32 offset) +static void regmap_mmio_write8(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writeb(val, ctx->regs + reg); +} + +static void regmap_mmio_write16le(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) { - BUG_ON(count <= offset); + writew(val, ctx->regs + reg); } -static inline unsigned int -regmap_mmio_get_offset(const void *reg, size_t reg_size) +static void regmap_mmio_write16be(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) { - switch (reg_size) { - case 1: - return *(u8 *)reg; - case 2: - return *(u16 *)reg; - case 4: - return *(u32 *)reg; + iowrite16be(val, ctx->regs + reg); +} + +static void regmap_mmio_write32le(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writel(val, ctx->regs + reg); +} + +static void regmap_mmio_write32be(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + iowrite32be(val, ctx->regs + reg); +} + #ifdef CONFIG_64BIT - case 8: - return *(u64 *)reg; -#endif - default: - BUG(); - } +static void regmap_mmio_write64le(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writeq(val, ctx->regs + reg); } +#endif -static int regmap_mmio_gather_write(void *context, - const void *reg, size_t reg_size, - const void *val, size_t val_size) +static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val) { struct regmap_mmio_context *ctx = context; - unsigned int offset; int ret; - regmap_mmio_regsize_check(reg_size); - if (!IS_ERR(ctx->clk)) { ret = clk_enable(ctx->clk); if (ret < 0) return ret; } - offset = regmap_mmio_get_offset(reg, reg_size); - - while (val_size) { - switch (ctx->val_bytes) { - case 1: - __raw_writeb(*(u8 *)val, ctx->regs + offset); - break; - case 2: - __raw_writew(*(u16 *)val, ctx->regs + offset); - break; - case 4: - __raw_writel(*(u32 *)val, ctx->regs + offset); - break; -#ifdef CONFIG_64BIT - case 8: - __raw_writeq(*(u64 *)val, ctx->regs + offset); - break; -#endif - default: - /* Should be caught by regmap_mmio_check_config */ - BUG(); - } - val_size -= ctx->val_bytes; - val += ctx->val_bytes; - offset += ctx->val_bytes; - } + ctx->reg_write(ctx, reg, val); if (!IS_ERR(ctx->clk)) clk_disable(ctx->clk); @@ -161,59 +139,56 @@ static int regmap_mmio_gather_write(void *context, return 0; } -static int regmap_mmio_write(void *context, const void *data, size_t count) +static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx, + unsigned int reg) { - struct regmap_mmio_context *ctx = context; - unsigned int offset = ctx->reg_bytes + ctx->pad_bytes; + return readb(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readw(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return ioread16be(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readl(ctx->regs + reg); +} - regmap_mmio_count_check(count, offset); +static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return ioread32be(ctx->regs + reg); +} - return regmap_mmio_gather_write(context, data, ctx->reg_bytes, - data + offset, count - offset); +#ifdef CONFIG_64BIT +static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readq(ctx->regs + reg); } +#endif -static int regmap_mmio_read(void *context, - const void *reg, size_t reg_size, - void *val, size_t val_size) +static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val) { struct regmap_mmio_context *ctx = context; - unsigned int offset; int ret; - regmap_mmio_regsize_check(reg_size); - if (!IS_ERR(ctx->clk)) { ret = clk_enable(ctx->clk); if (ret < 0) return ret; } - offset = regmap_mmio_get_offset(reg, reg_size); - - while (val_size) { - switch (ctx->val_bytes) { - case 1: - *(u8 *)val = __raw_readb(ctx->regs + offset); - break; - case 2: - *(u16 *)val = __raw_readw(ctx->regs + offset); - break; - case 4: - *(u32 *)val = __raw_readl(ctx->regs + offset); - break; -#ifdef CONFIG_64BIT - case 8: - *(u64 *)val = __raw_readq(ctx->regs + offset); - break; -#endif - default: - /* Should be caught by regmap_mmio_check_config */ - BUG(); - } - val_size -= ctx->val_bytes; - val += ctx->val_bytes; - offset += ctx->val_bytes; - } + *val = ctx->reg_read(ctx, reg); if (!IS_ERR(ctx->clk)) clk_disable(ctx->clk); @@ -232,14 +207,11 @@ static void regmap_mmio_free_context(void *context) kfree(context); } -static struct regmap_bus regmap_mmio = { +static const struct regmap_bus regmap_mmio = { .fast_io = true, - .write = regmap_mmio_write, - .gather_write = regmap_mmio_gather_write, - .read = regmap_mmio_read, + .reg_write = regmap_mmio_write, + .reg_read = regmap_mmio_read, .free_context = regmap_mmio_free_context, - .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, - .val_format_endian_default = REGMAP_ENDIAN_NATIVE, }; static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, @@ -265,24 +237,71 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, if (config->reg_stride < min_stride) return ERR_PTR(-EINVAL); - switch (config->reg_format_endian) { - case REGMAP_ENDIAN_DEFAULT: - case REGMAP_ENDIAN_NATIVE: - break; - default: - return ERR_PTR(-EINVAL); - } - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return ERR_PTR(-ENOMEM); ctx->regs = regs; ctx->val_bytes = config->val_bits / 8; - ctx->reg_bytes = config->reg_bits / 8; - ctx->pad_bytes = config->pad_bits / 8; ctx->clk = ERR_PTR(-ENODEV); + switch (config->reg_format_endian) { + case REGMAP_ENDIAN_DEFAULT: + case REGMAP_ENDIAN_LITTLE: +#ifdef __LITTLE_ENDIAN + case REGMAP_ENDIAN_NATIVE: +#endif + switch (config->val_bits) { + case 8: + ctx->reg_read = regmap_mmio_read8; + ctx->reg_write = regmap_mmio_write8; + break; + case 16: + ctx->reg_read = regmap_mmio_read16le; + ctx->reg_write = regmap_mmio_write16le; + break; + case 32: + ctx->reg_read = regmap_mmio_read32le; + ctx->reg_write = regmap_mmio_write32le; + break; +#ifdef CONFIG_64BIT + case 64: + ctx->reg_read = regmap_mmio_read64le; + ctx->reg_write = regmap_mmio_write64le; + break; +#endif + default: + ret = -EINVAL; + goto err_free; + } + break; + case REGMAP_ENDIAN_BIG: +#ifdef __BIG_ENDIAN + case REGMAP_ENDIAN_NATIVE: +#endif + switch (config->val_bits) { + case 8: + ctx->reg_read = regmap_mmio_read8; + ctx->reg_write = regmap_mmio_write8; + break; + case 16: + ctx->reg_read = regmap_mmio_read16be; + ctx->reg_write = regmap_mmio_write16be; + break; + case 32: + ctx->reg_read = regmap_mmio_read32be; + ctx->reg_write = regmap_mmio_write32be; + break; + default: + ret = -EINVAL; + goto err_free; + } + break; + default: + ret = -EINVAL; + goto err_free; + } + if (clk_id == NULL) return ctx; -- cgit v1.2.3 From b786ae8e269b5b30fea5efaab8cba32ba9aece61 Mon Sep 17 00:00:00 2001 From: Andrew Duggan Date: Tue, 26 Jan 2016 15:40:36 -0800 Subject: HID: rmi: Check that the device is a RMI device in suspend and resume callbacks Commit 092563604217 ("HID: rmi: Disable scanning if the device is not a wake source") introduced a regression for devices which use hid-rmi to handle composite USB devices. The suspend or resume callbacks are not checking that the device is a RMI device before calling rmi_read or rmi_write. This results in dereferencing uninitialized variables on non RMI devices. This patch checks that the RMI_DEVICE flag is set before sending RMI commands to the device. Reported-by: Rodrigo Gomes Signed-off-by: Andrew Duggan Signed-off-by: Jiri Kosina --- drivers/hid/hid-rmi.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c index 67cd059a8f46..9cd2ca34a6be 100644 --- a/drivers/hid/hid-rmi.c +++ b/drivers/hid/hid-rmi.c @@ -594,6 +594,9 @@ static int rmi_suspend(struct hid_device *hdev, pm_message_t message) int ret; u8 buf[RMI_F11_CTRL_REG_COUNT]; + if (!(data->device_flags & RMI_DEVICE)) + return 0; + ret = rmi_read_block(hdev, data->f11.control_base_addr, buf, RMI_F11_CTRL_REG_COUNT); if (ret) @@ -613,6 +616,9 @@ static int rmi_post_reset(struct hid_device *hdev) struct rmi_data *data = hid_get_drvdata(hdev); int ret; + if (!(data->device_flags & RMI_DEVICE)) + return 0; + ret = rmi_reset_attn_mode(hdev); if (ret) { hid_err(hdev, "can not set rmi mode\n"); @@ -640,6 +646,11 @@ static int rmi_post_reset(struct hid_device *hdev) static int rmi_post_resume(struct hid_device *hdev) { + struct rmi_data *data = hid_get_drvdata(hdev); + + if (!(data->device_flags & RMI_DEVICE)) + return 0; + return rmi_reset_attn_mode(hdev); } #endif /* CONFIG_PM */ -- cgit v1.2.3 From cdb300a041f5df1dfbde1367f95109b6449d1371 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Wed, 27 Jan 2016 09:10:37 +0100 Subject: PM / Domains: Fix potential deadlock while adding/removing subdomains We must preserve the same order of how we acquire and release the lock for genpd, as otherwise we may encounter deadlocks. The power on phase of a genpd starts by acquiring its lock. Then it walks the hierarchy of its parent domains to be able to power on these first, as per design of genpd. From a locking perspective this means the locks of the parents becomes acquired after the lock of the subdomain. Let's fix pm_genpd_add|remove_subdomain() to maintain the same order of acquiring/releasing the genpd lock as being applied in the power on/off sequence. Signed-off-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index e02ddf65bc43..2ff818c2ae6b 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1340,8 +1340,8 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, if (!link) return -ENOMEM; - mutex_lock(&genpd->lock); - mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING); + mutex_lock(&subdomain->lock); + mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING); if (genpd->status == GPD_STATE_POWER_OFF && subdomain->status != GPD_STATE_POWER_OFF) { @@ -1364,8 +1364,8 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, genpd_sd_counter_inc(genpd); out: - mutex_unlock(&subdomain->lock); mutex_unlock(&genpd->lock); + mutex_unlock(&subdomain->lock); if (ret) kfree(link); return ret; @@ -1386,7 +1386,8 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain)) return -EINVAL; - mutex_lock(&genpd->lock); + mutex_lock(&subdomain->lock); + mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING); if (!list_empty(&subdomain->slave_links) || subdomain->device_count) { pr_warn("%s: unable to remove subdomain %s\n", genpd->name, @@ -1399,22 +1400,19 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, if (link->slave != subdomain) continue; - mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING); - list_del(&link->master_node); list_del(&link->slave_node); kfree(link); if (subdomain->status != GPD_STATE_POWER_OFF) genpd_sd_counter_dec(genpd); - mutex_unlock(&subdomain->lock); - ret = 0; break; } out: mutex_unlock(&genpd->lock); + mutex_unlock(&subdomain->lock); return ret; } -- cgit v1.2.3 From a3d09c73492e57a1189e410f67e4d2115b23a3a8 Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Wed, 27 Jan 2016 08:29:27 +0100 Subject: PM / Domains: Fix typo in comment Acked-by: Kevin Hilman Signed-off-by: Moritz Fischer Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 2ff818c2ae6b..014024a2fee9 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -160,7 +160,7 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool timed) /** * genpd_queue_power_off_work - Queue up the execution of genpd_poweroff(). - * @genpd: PM domait to power off. + * @genpd: PM domain to power off. * * Queue up the execution of genpd_poweroff() unless it's already been done * before. -- cgit v1.2.3 From 75274b33e779ae40a750bcb4bd0b07c4dfef4746 Mon Sep 17 00:00:00 2001 From: Anders Roxell Date: Wed, 27 Jan 2016 20:26:54 +0100 Subject: cpuidle: coupled: remove unused define cpuidle_coupled_lock This was found with the -RT patch enabled, but the fix should apply to non-RT also. Used multi_v7_defconfig+PREEMPT_RT_FULL=y and this caused a compilation warning without this fix: ../drivers/cpuidle/coupled.c:122:21: warning: 'cpuidle_coupled_lock' defined but not used [-Wunused-variable] Signed-off-by: Anders Roxell Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/coupled.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpuidle/coupled.c b/drivers/cpuidle/coupled.c index 344058f8501a..d5657d50ac40 100644 --- a/drivers/cpuidle/coupled.c +++ b/drivers/cpuidle/coupled.c @@ -119,7 +119,6 @@ struct cpuidle_coupled { #define CPUIDLE_COUPLED_NOT_IDLE (-1) -static DEFINE_MUTEX(cpuidle_coupled_lock); static DEFINE_PER_CPU(struct call_single_data, cpuidle_coupled_poke_cb); /* -- cgit v1.2.3 From e4b133cc4b30b48d488e4e4fffb132f173ce4358 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 25 Jan 2016 22:33:46 +0530 Subject: cpufreq: Fix NULL reference crash while accessing policy->governor_data There is a race discovered by Juri, where we are able to: - create and read a sysfs file before policy->governor_data is being set to a non NULL value. OR - set policy->governor_data to NULL, and reading a file before being destroyed. And so such a crash is reported: Unable to handle kernel NULL pointer dereference at virtual address 0000000c pgd = edfc8000 [0000000c] *pgd=bfc8c835 Internal error: Oops: 17 [#1] SMP ARM Modules linked in: CPU: 4 PID: 1730 Comm: cat Not tainted 4.5.0-rc1+ #463 Hardware name: ARM-Versatile Express task: ee8e8480 ti: ee930000 task.ti: ee930000 PC is at show_ignore_nice_load_gov_pol+0x24/0x34 LR is at show+0x4c/0x60 pc : [] lr : [] psr: a0070013 sp : ee931dd0 ip : ee931de0 fp : ee931ddc r10: ee4bc290 r9 : 00001000 r8 : ef2cb000 r7 : ee4bc200 r6 : ef2cb000 r5 : c0af57b0 r4 : ee4bc2e0 r3 : 00000000 r2 : 00000000 r1 : c0928df4 r0 : ef2cb000 Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none Control: 10c5387d Table: adfc806a DAC: 00000051 Process cat (pid: 1730, stack limit = 0xee930210) Stack: (0xee931dd0 to 0xee932000) 1dc0: ee931dfc ee931de0 c058ae88 c058f1a4 1de0: edce3bc0 c07bfca4 edce3ac0 00001000 ee931e24 ee931e00 c01fcb90 c058ae48 1e00: 00000001 edce3bc0 00000000 00000001 ee931e50 ee8ff480 ee931e34 ee931e28 1e20: c01fb33c c01fcb0c ee931e8c ee931e38 c01a5210 c01fb314 ee931e9c ee931e48 1e40: 00000000 edce3bf0 befe4a00 ee931f78 00000000 00000000 000001e4 00000000 1e60: c00545a8 edce3ac0 00001000 00001000 befe4a00 ee931f78 00000000 00001000 1e80: ee931ed4 ee931e90 c01fbed8 c01a5038 ed085a58 00020000 00000000 00000000 1ea0: c0ad72e4 ee931f78 ee8ff488 ee8ff480 c077f3fc 00001000 befe4a00 ee931f78 1ec0: 00000000 00001000 ee931f44 ee931ed8 c017c328 c01fbdc4 00001000 00000000 1ee0: ee8ff480 00001000 ee931f44 ee931ef8 c017c65c c03deb10 ee931fac ee931f08 1f00: c0009270 c001f290 c0a8d968 ef2cb000 ef2cb000 ee8ff480 00000020 ee8ff480 1f20: ee8ff480 befe4a00 00001000 ee931f78 00000000 00000000 ee931f74 ee931f48 1f40: c017d1ec c017c2f8 c019c724 c019c684 ee8ff480 ee8ff480 00001000 befe4a00 1f60: 00000000 00000000 ee931fa4 ee931f78 c017d2a8 c017d160 00000000 00000000 1f80: 000a9f20 00001000 befe4a00 00000003 c000ffe4 ee930000 00000000 ee931fa8 1fa0: c000fe40 c017d264 000a9f20 00001000 00000003 befe4a00 00001000 00000000 Unable to handle kernel NULL pointer dereference at virtual address 0000000c 1fc0: 000a9f20 00001000 befe4a00 00000003 00000000 00000000 00000003 00000001 pgd = edfc4000 [0000000c] *pgd=bfcac835 1fe0: 00000000 befe49dc 000197f8 b6e35dfc 60070010 00000003 3065b49d 134ac2c9 [] (show_ignore_nice_load_gov_pol) from [] (show+0x4c/0x60) [] (show) from [] (sysfs_kf_seq_show+0x90/0xfc) [] (sysfs_kf_seq_show) from [] (kernfs_seq_show+0x34/0x38) [] (kernfs_seq_show) from [] (seq_read+0x1e4/0x4e4) [] (seq_read) from [] (kernfs_fop_read+0x120/0x1a0) [] (kernfs_fop_read) from [] (__vfs_read+0x3c/0xe0) [] (__vfs_read) from [] (vfs_read+0x98/0x104) [] (vfs_read) from [] (SyS_read+0x50/0x90) [] (SyS_read) from [] (ret_fast_syscall+0x0/0x1c) Code: e5903044 e1a00001 e3081df4 e34c1092 (e593300c) ---[ end trace 5994b9a5111f35ee ]--- Fix that by making sure, policy->governor_data is updated at the right places only. Cc: 4.2+ # 4.2+ Reported-and-tested-by: Juri Lelli Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq_governor.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index bab3a514ec12..e0d111024d48 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -387,16 +387,18 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy, if (!have_governor_per_policy()) cdata->gdbs_data = dbs_data; + policy->governor_data = dbs_data; + ret = sysfs_create_group(get_governor_parent_kobj(policy), get_sysfs_attr(dbs_data)); if (ret) goto reset_gdbs_data; - policy->governor_data = dbs_data; - return 0; reset_gdbs_data: + policy->governor_data = NULL; + if (!have_governor_per_policy()) cdata->gdbs_data = NULL; cdata->exit(dbs_data, !policy->governor->initialized); @@ -417,16 +419,19 @@ static int cpufreq_governor_exit(struct cpufreq_policy *policy, if (!cdbs->shared || cdbs->shared->policy) return -EBUSY; - policy->governor_data = NULL; if (!--dbs_data->usage_count) { sysfs_remove_group(get_governor_parent_kobj(policy), get_sysfs_attr(dbs_data)); + policy->governor_data = NULL; + if (!have_governor_per_policy()) cdata->gdbs_data = NULL; cdata->exit(dbs_data, policy->governor->initialized == 1); kfree(dbs_data); + } else { + policy->governor_data = NULL; } free_common_dbs_info(policy, cdata); -- cgit v1.2.3 From 2dadfd7564ef28391609c7ef896fd85218799012 Mon Sep 17 00:00:00 2001 From: Gautham R Shenoy Date: Wed, 27 Jan 2016 12:02:26 +0530 Subject: cpufreq: Use list_is_last() to check last entry of the policy list Currently next_policy() explicitly checks if a policy is the last policy in the cpufreq_policy_list. Use the standard list_is_last primitive instead. Signed-off-by: Gautham R. Shenoy Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index c35e7da1ed7a..e979ec78b695 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -48,11 +48,11 @@ static struct cpufreq_policy *next_policy(struct cpufreq_policy *policy, bool active) { do { - policy = list_next_entry(policy, policy_list); - /* No more policies in the list */ - if (&policy->policy_list == &cpufreq_policy_list) + if (list_is_last(&policy->policy_list, &cpufreq_policy_list)) return NULL; + + policy = list_next_entry(policy, policy_list); } while (!suitable_policy(policy, active)); return policy; -- cgit v1.2.3 From fb2a24a1c6457d21df9fae0dd66b20c63ba56077 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 16:44:38 +0100 Subject: cpufreq: pxa2xx: fix pxa_cpufreq_change_voltage prototype There are two definitions of pxa_cpufreq_change_voltage, with slightly different prototypes after one of them had its argument marked 'const'. Now the other one (for !CONFIG_REGULATOR) produces a harmless warning: drivers/cpufreq/pxa2xx-cpufreq.c: In function 'pxa_set_target': drivers/cpufreq/pxa2xx-cpufreq.c:291:36: warning: passing argument 1 of 'pxa_cpufreq_change_voltage' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers] ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]); ^ drivers/cpufreq/pxa2xx-cpufreq.c:205:12: note: expected 'struct pxa_freqs *' but argument is of type 'const struct pxa_freqs *' static int pxa_cpufreq_change_voltage(struct pxa_freqs *pxa_freq) ^ This changes the prototype in the same way as the other, which avoids the warning. Fixes: 03c229906311 (cpufreq: pxa: make pxa_freqs arrays const) Signed-off-by: Arnd Bergmann Acked-by: Viresh Kumar Cc: 4.2+ # 4.2+ Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/pxa2xx-cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/pxa2xx-cpufreq.c b/drivers/cpufreq/pxa2xx-cpufreq.c index 1d99c97defa9..096377232747 100644 --- a/drivers/cpufreq/pxa2xx-cpufreq.c +++ b/drivers/cpufreq/pxa2xx-cpufreq.c @@ -202,7 +202,7 @@ static void __init pxa_cpufreq_init_voltages(void) } } #else -static int pxa_cpufreq_change_voltage(struct pxa_freqs *pxa_freq) +static int pxa_cpufreq_change_voltage(const struct pxa_freqs *pxa_freq) { return 0; } -- cgit v1.2.3 From b331bc20d9281213f7fb67912638e0fb5baeb324 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 16:45:48 +0100 Subject: cpufreq: cpufreq-dt: avoid uninitialized variable warnings: gcc warns quite a bit about values returned from allocate_resources() in cpufreq-dt.c: cpufreq-dt.c: In function 'cpufreq_init': cpufreq-dt.c:327:6: error: 'cpu_dev' may be used uninitialized in this function [-Werror=maybe-uninitialized] cpufreq-dt.c:197:17: note: 'cpu_dev' was declared here cpufreq-dt.c:376:2: error: 'cpu_clk' may be used uninitialized in this function [-Werror=maybe-uninitialized] cpufreq-dt.c:199:14: note: 'cpu_clk' was declared here cpufreq-dt.c: In function 'dt_cpufreq_probe': cpufreq-dt.c:461:2: error: 'cpu_clk' may be used uninitialized in this function [-Werror=maybe-uninitialized] cpufreq-dt.c:447:14: note: 'cpu_clk' was declared here The problem is that it's slightly hard for gcc to follow return codes across PTR_ERR() calls. This patch uses explicit assignments to the "ret" variable to make it easier for gcc to verify that the code is actually correct, without the need to add a bogus initialization. Signed-off-by: Arnd Bergmann Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 9bc37c437874..0ca74d070058 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -142,15 +142,16 @@ static int allocate_resources(int cpu, struct device **cdev, try_again: cpu_reg = regulator_get_optional(cpu_dev, reg); - if (IS_ERR(cpu_reg)) { + ret = PTR_ERR_OR_ZERO(cpu_reg); + if (ret) { /* * If cpu's regulator supply node is present, but regulator is * not yet registered, we should try defering probe. */ - if (PTR_ERR(cpu_reg) == -EPROBE_DEFER) { + if (ret == -EPROBE_DEFER) { dev_dbg(cpu_dev, "cpu%d regulator not ready, retry\n", cpu); - return -EPROBE_DEFER; + return ret; } /* Try with "cpu-supply" */ @@ -159,18 +160,16 @@ try_again: goto try_again; } - dev_dbg(cpu_dev, "no regulator for cpu%d: %ld\n", - cpu, PTR_ERR(cpu_reg)); + dev_dbg(cpu_dev, "no regulator for cpu%d: %d\n", cpu, ret); } cpu_clk = clk_get(cpu_dev, NULL); - if (IS_ERR(cpu_clk)) { + ret = PTR_ERR_OR_ZERO(cpu_clk); + if (ret) { /* put regulator */ if (!IS_ERR(cpu_reg)) regulator_put(cpu_reg); - ret = PTR_ERR(cpu_clk); - /* * If cpu's clk node is present, but clock is not yet * registered, we should try defering probe. -- cgit v1.2.3 From c8b710b3e4348119924051551b836c94835331b1 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:46 -0800 Subject: tty: Fix ldisc leak in failed tty_init_dev() release_tty() leaks the ldisc instance when called directly (rather than when releasing the file descriptor from tty_release()). Since tty_ldisc_release() clears tty->ldisc, releasing the ldisc instance at tty teardown if tty->ldisc is non-null is not in danger of double-releasing the ldisc. Remove deinitialize_tty_struct() now that free_tty_struct() always performs the tty_ldisc_deinit(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 5 ++--- drivers/tty/tty_io.c | 20 +++----------------- drivers/tty/tty_ldisc.c | 5 +++-- include/linux/tty.h | 1 - 4 files changed, 8 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index b3110040164a..8cbe802bff1d 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -408,7 +408,7 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, the easy way .. */ retval = tty_init_termios(tty); if (retval) - goto err_deinit_tty; + goto err_free_tty; retval = tty_init_termios(o_tty); if (retval) @@ -447,8 +447,7 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, err_free_termios: if (legacy) tty_free_termios(tty); -err_deinit_tty: - deinitialize_tty_struct(o_tty); +err_free_tty: free_tty_struct(o_tty); err_put_module: module_put(driver->other->owner); diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 5cec01c75691..c9f2365167df 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -172,6 +172,7 @@ void free_tty_struct(struct tty_struct *tty) { if (!tty) return; + tty_ldisc_deinit(tty); put_device(tty->dev); kfree(tty->write_buf); tty->magic = 0xDEADDEAD; @@ -1529,7 +1530,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) tty_lock(tty); retval = tty_driver_install_tty(driver, tty); if (retval < 0) - goto err_deinit_tty; + goto err_free_tty; if (!tty->port) tty->port = driver->ports[idx]; @@ -1551,9 +1552,8 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) /* Return the tty locked so that it cannot vanish under the caller */ return tty; -err_deinit_tty: +err_free_tty: tty_unlock(tty); - deinitialize_tty_struct(tty); free_tty_struct(tty); err_module_put: module_put(driver->owner); @@ -3162,20 +3162,6 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx) return tty; } -/** - * deinitialize_tty_struct - * @tty: tty to deinitialize - * - * This subroutine deinitializes a tty structure that has been newly - * allocated but tty_release cannot be called on that yet. - * - * Locking: none - tty in question must not be exposed at this point - */ -void deinitialize_tty_struct(struct tty_struct *tty) -{ - tty_ldisc_deinit(tty); -} - /** * tty_put_char - write one character to a tty * @tty: tty diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index a054d03c22e7..49f0cea1e538 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -797,7 +797,7 @@ void tty_ldisc_init(struct tty_struct *tty) } /** - * tty_ldisc_init - ldisc cleanup for new tty + * tty_ldisc_deinit - ldisc cleanup for new tty * @tty: tty that was allocated recently * * The tty structure must not becompletely set up (tty_ldisc_setup) when @@ -805,7 +805,8 @@ void tty_ldisc_init(struct tty_struct *tty) */ void tty_ldisc_deinit(struct tty_struct *tty) { - tty_ldisc_put(tty->ldisc); + if (tty->ldisc) + tty_ldisc_put(tty->ldisc); tty->ldisc = NULL; } diff --git a/include/linux/tty.h b/include/linux/tty.h index d9fb4b043f56..64e301dbf7b9 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -509,7 +509,6 @@ extern int tty_alloc_file(struct file *file); extern void tty_add_file(struct tty_struct *tty, struct file *file); extern void tty_free_file(struct file *file); extern void free_tty_struct(struct tty_struct *tty); -extern void deinitialize_tty_struct(struct tty_struct *tty); extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx); extern int tty_release(struct inode *inode, struct file *filp); extern int tty_init_termios(struct tty_struct *tty); -- cgit v1.2.3 From a99cc5d9954651ac7402dcd40b133848303ba596 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:47 -0800 Subject: tty: Remove !tty check from free_tty_struct() free_tty_struct() is never called with NULL tty; the two call sites would already have faulted on earlier access. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index c9f2365167df..a59930e59660 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -170,8 +170,6 @@ static void release_tty(struct tty_struct *tty, int idx); void free_tty_struct(struct tty_struct *tty) { - if (!tty) - return; tty_ldisc_deinit(tty); put_device(tty->dev); kfree(tty->write_buf); -- cgit v1.2.3 From a3123fd0a4a5f9d71afa0ffa82e2086281d81822 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:48 -0800 Subject: tty: Fix tty_init_termios() declaration tty_init_termios() never returns an error; re-declare as void. Remove unnecessary error handling from callers. Remove extern declarations of tty_free_termios() and free_tty_struct() and re-declare in file scope. Signed-off-by: Peter Hurley Acked-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 15 +++------------ drivers/tty/tty_io.c | 13 ++++--------- drivers/usb/serial/console.c | 6 +----- include/linux/tty.h | 4 +--- 4 files changed, 9 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 8cbe802bff1d..7e885a226f88 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -406,13 +406,8 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, if (legacy) { /* We always use new tty termios data so we can do this the easy way .. */ - retval = tty_init_termios(tty); - if (retval) - goto err_free_tty; - - retval = tty_init_termios(o_tty); - if (retval) - goto err_free_termios; + tty_init_termios(tty); + tty_init_termios(o_tty); driver->other->ttys[idx] = o_tty; driver->ttys[idx] = tty; @@ -444,11 +439,7 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, tty->count++; o_tty->count++; return 0; -err_free_termios: - if (legacy) - tty_free_termios(tty); -err_free_tty: - free_tty_struct(o_tty); + err_put_module: module_put(driver->other->owner); err: diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index a59930e59660..742860e583ce 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -168,7 +168,7 @@ static void release_tty(struct tty_struct *tty, int idx); * Locking: none. Must be called after tty is definitely unused */ -void free_tty_struct(struct tty_struct *tty) +static void free_tty_struct(struct tty_struct *tty) { tty_ldisc_deinit(tty); put_device(tty->dev); @@ -1377,7 +1377,7 @@ static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver, * the tty_mutex currently so we can be relaxed about ordering. */ -int tty_init_termios(struct tty_struct *tty) +void tty_init_termios(struct tty_struct *tty) { struct ktermios *tp; int idx = tty->index; @@ -1395,16 +1395,12 @@ int tty_init_termios(struct tty_struct *tty) /* Compatibility until drivers always set this */ tty->termios.c_ispeed = tty_termios_input_baud_rate(&tty->termios); tty->termios.c_ospeed = tty_termios_baud_rate(&tty->termios); - return 0; } EXPORT_SYMBOL_GPL(tty_init_termios); int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty) { - int ret = tty_init_termios(tty); - if (ret) - return ret; - + tty_init_termios(tty); tty_driver_kref_get(driver); tty->count++; driver->ttys[tty->index] = tty; @@ -1566,7 +1562,7 @@ err_release_tty: return ERR_PTR(retval); } -void tty_free_termios(struct tty_struct *tty) +static void tty_free_termios(struct tty_struct *tty) { struct ktermios *tp; int idx = tty->index; @@ -1585,7 +1581,6 @@ void tty_free_termios(struct tty_struct *tty) } *tp = tty->termios; } -EXPORT_SYMBOL(tty_free_termios); /** * tty_flush_works - flush all works of a tty/pty pair diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 3806e7014199..a66b01bb1fa1 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -147,10 +147,7 @@ static int usb_console_setup(struct console *co, char *options) kref_get(&tty->driver->kref); __module_get(tty->driver->owner); tty->ops = &usb_console_fake_tty_ops; - if (tty_init_termios(tty)) { - retval = -ENOMEM; - goto put_tty; - } + tty_init_termios(tty); tty_port_tty_set(&port->port, tty); } @@ -185,7 +182,6 @@ static int usb_console_setup(struct console *co, char *options) fail: tty_port_tty_set(&port->port, NULL); - put_tty: tty_kref_put(tty); reset_open_count: port->port.count = 0; diff --git a/include/linux/tty.h b/include/linux/tty.h index 64e301dbf7b9..d7a7c1efe77f 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -448,7 +448,6 @@ extern int tty_unthrottle_safe(struct tty_struct *tty); extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws); extern void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *tty); -extern void tty_free_termios(struct tty_struct *tty); extern int is_current_pgrp_orphaned(void); extern int is_ignored(int sig); extern int tty_signal(int sig, struct tty_struct *tty); @@ -508,10 +507,9 @@ extern struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx); extern int tty_alloc_file(struct file *file); extern void tty_add_file(struct tty_struct *tty, struct file *file); extern void tty_free_file(struct file *file); -extern void free_tty_struct(struct tty_struct *tty); extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx); extern int tty_release(struct inode *inode, struct file *filp); -extern int tty_init_termios(struct tty_struct *tty); +extern void tty_init_termios(struct tty_struct *tty); extern int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty); -- cgit v1.2.3 From 05de87ed9531dc19d87136c9204d251abebc60d3 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:49 -0800 Subject: tty: Re-declare tty_driver_remove_tty() file scope tty_driver_remove_tty() is only local-scope; declare as static. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 2 +- include/linux/tty.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 742860e583ce..6cffe0d57d70 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1437,7 +1437,7 @@ static int tty_driver_install_tty(struct tty_driver *driver, * * Locking: tty_mutex for now */ -void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *tty) +static void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *tty) { if (driver->ops->remove) driver->ops->remove(driver, tty); diff --git a/include/linux/tty.h b/include/linux/tty.h index d7a7c1efe77f..57c4e03ec2aa 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -446,8 +446,6 @@ extern void tty_unthrottle(struct tty_struct *tty); extern int tty_throttle_safe(struct tty_struct *tty); extern int tty_unthrottle_safe(struct tty_struct *tty); extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws); -extern void tty_driver_remove_tty(struct tty_driver *driver, - struct tty_struct *tty); extern int is_current_pgrp_orphaned(void); extern int is_ignored(int sig); extern int tty_signal(int sig, struct tty_struct *tty); -- cgit v1.2.3 From c1e33af1ed552258405f2e5a72509af039c0441c Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:50 -0800 Subject: pty: Remove pty_unix98_shutdown() The tty core invokes the optional driver shutdown() just before the optional driver remove() (shutdown() has access to the termios and remove() does not). Because pty drivers must prevent the default remove() action, the Unix98 pty drivers define a dummy remove() function. Instead, release the slave index in the remove() method and delete the optional shutdown() method. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 7e885a226f88..be5020d567ae 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -656,20 +656,13 @@ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver, return tty; } -/* We have no need to install and remove our tty objects as devpts does all - the work for us */ - static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) { return pty_common_install(driver, tty, false); } -static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) -{ -} - /* this is called once with whichever end is closed last */ -static void pty_unix98_shutdown(struct tty_struct *tty) +static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) { devpts_kill_index(tty->driver_data, tty->index); } @@ -687,7 +680,6 @@ static const struct tty_operations ptm_unix98_ops = { .unthrottle = pty_unthrottle, .ioctl = pty_unix98_ioctl, .resize = pty_resize, - .shutdown = pty_unix98_shutdown, .cleanup = pty_cleanup }; @@ -705,7 +697,6 @@ static const struct tty_operations pty_unix98_ops = { .set_termios = pty_set_termios, .start = pty_start, .stop = pty_stop, - .shutdown = pty_unix98_shutdown, .cleanup = pty_cleanup, }; -- cgit v1.2.3 From c2bb524b2e1a6eddae65139601bee24cb60856a0 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:51 -0800 Subject: tty: Remove __lockfunc annotation from tty lock functions The tty lock/unlock code does not belong in the special lockfunc section which is treated specially by stack backtraces. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 16 +++++++--------- drivers/tty/tty_mutex.c | 8 ++++---- include/linux/tty.h | 8 ++++---- 3 files changed, 15 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 49f0cea1e538..713cc2d48846 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -304,13 +304,13 @@ void tty_ldisc_deref(struct tty_ldisc *ld) EXPORT_SYMBOL_GPL(tty_ldisc_deref); -static inline int __lockfunc +static inline int __tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) { return ldsem_down_write(&tty->ldisc_sem, timeout); } -static inline int __lockfunc +static inline int __tty_ldisc_lock_nested(struct tty_struct *tty, unsigned long timeout) { return ldsem_down_write_nested(&tty->ldisc_sem, @@ -322,8 +322,7 @@ static inline void __tty_ldisc_unlock(struct tty_struct *tty) ldsem_up_write(&tty->ldisc_sem); } -static int __lockfunc -tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) +static int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) { int ret; @@ -340,7 +339,7 @@ static void tty_ldisc_unlock(struct tty_struct *tty) __tty_ldisc_unlock(tty); } -static int __lockfunc +static int tty_ldisc_lock_pair_timeout(struct tty_struct *tty, struct tty_struct *tty2, unsigned long timeout) { @@ -376,14 +375,13 @@ tty_ldisc_lock_pair_timeout(struct tty_struct *tty, struct tty_struct *tty2, return 0; } -static void __lockfunc -tty_ldisc_lock_pair(struct tty_struct *tty, struct tty_struct *tty2) +static void tty_ldisc_lock_pair(struct tty_struct *tty, struct tty_struct *tty2) { tty_ldisc_lock_pair_timeout(tty, tty2, MAX_SCHEDULE_TIMEOUT); } -static void __lockfunc tty_ldisc_unlock_pair(struct tty_struct *tty, - struct tty_struct *tty2) +static void tty_ldisc_unlock_pair(struct tty_struct *tty, + struct tty_struct *tty2) { __tty_ldisc_unlock(tty); if (tty2) diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c index d2f3c4cd697f..75351e4b77df 100644 --- a/drivers/tty/tty_mutex.c +++ b/drivers/tty/tty_mutex.c @@ -10,7 +10,7 @@ * Getting the big tty mutex. */ -void __lockfunc tty_lock(struct tty_struct *tty) +void tty_lock(struct tty_struct *tty) { if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty)) return; @@ -27,7 +27,7 @@ int tty_lock_interruptible(struct tty_struct *tty) return mutex_lock_interruptible(&tty->legacy_mutex); } -void __lockfunc tty_unlock(struct tty_struct *tty) +void tty_unlock(struct tty_struct *tty) { if (WARN(tty->magic != TTY_MAGIC, "U Bad %p\n", tty)) return; @@ -36,13 +36,13 @@ void __lockfunc tty_unlock(struct tty_struct *tty) } EXPORT_SYMBOL(tty_unlock); -void __lockfunc tty_lock_slave(struct tty_struct *tty) +void tty_lock_slave(struct tty_struct *tty) { if (tty && tty != tty->link) tty_lock(tty); } -void __lockfunc tty_unlock_slave(struct tty_struct *tty) +void tty_unlock_slave(struct tty_struct *tty) { if (tty && tty != tty->link) tty_unlock(tty); diff --git a/include/linux/tty.h b/include/linux/tty.h index 57c4e03ec2aa..83f127673bc9 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -643,11 +643,11 @@ extern long vt_compat_ioctl(struct tty_struct *tty, /* tty_mutex.c */ /* functions for preparation of BKL removal */ -extern void __lockfunc tty_lock(struct tty_struct *tty); +extern void tty_lock(struct tty_struct *tty); extern int tty_lock_interruptible(struct tty_struct *tty); -extern void __lockfunc tty_unlock(struct tty_struct *tty); -extern void __lockfunc tty_lock_slave(struct tty_struct *tty); -extern void __lockfunc tty_unlock_slave(struct tty_struct *tty); +extern void tty_unlock(struct tty_struct *tty); +extern void tty_lock_slave(struct tty_struct *tty); +extern void tty_unlock_slave(struct tty_struct *tty); extern void tty_set_lock_subclass(struct tty_struct *tty); #ifdef CONFIG_PROC_FS -- cgit v1.2.3 From 11e1d4aa4da1d0572b00f040ae91da85d3474f4a Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:52 -0800 Subject: tty: Consolidate noctty checks in tty_open() Evaluate the conditions which prevent this tty being the controlling terminal in one place, just before setting the controlling terminal. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 6cffe0d57d70..741a0d7f51ce 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1960,7 +1960,7 @@ static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp) * Locking: tty_mutex protects get_tty_driver */ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, - int *noctty, int *index) + int *index) { struct tty_driver *driver; @@ -1970,7 +1970,6 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, extern struct tty_driver *console_driver; driver = tty_driver_kref_get(console_driver); *index = fg_console; - *noctty = 1; break; } #endif @@ -1981,7 +1980,6 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, if (driver) { /* Don't let /dev/console block */ filp->f_flags |= O_NONBLOCK; - *noctty = 1; break; } } @@ -2036,14 +2034,13 @@ retry_open: if (retval) return -ENOMEM; - noctty = filp->f_flags & O_NOCTTY; index = -1; retval = 0; tty = tty_open_current_tty(device, filp); if (!tty) { mutex_lock(&tty_mutex); - driver = tty_lookup_driver(device, filp, &noctty, &index); + driver = tty_lookup_driver(device, filp, &index); if (IS_ERR(driver)) { retval = PTR_ERR(driver); goto err_unlock; @@ -2091,10 +2088,6 @@ retry_open: tty_add_file(tty, filp); check_tty_count(tty, __func__); - if (tty->driver->type == TTY_DRIVER_TYPE_PTY && - tty->driver->subtype == PTY_TYPE_MASTER) - noctty = 1; - tty_debug_hangup(tty, "opening (count=%d)\n", tty->count); if (tty->ops->open) @@ -2127,6 +2120,12 @@ retry_open: read_lock(&tasklist_lock); spin_lock_irq(¤t->sighand->siglock); + noctty = (filp->f_flags & O_NOCTTY) || + device == MKDEV(TTY_MAJOR, 0) || + device == MKDEV(TTYAUX_MAJOR, 1) || + (tty->driver->type == TTY_DRIVER_TYPE_PTY && + tty->driver->subtype == PTY_TYPE_MASTER); + if (!noctty && current->signal->leader && !current->signal->tty && -- cgit v1.2.3 From d6203d0c7b738d7ce75d5629b72640b489487cfa Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:53 -0800 Subject: tty: Refactor tty_open() Extract the driver lookup and reopen-or-initialize logic into helper function tty_open_by_driver(). No functional change. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 120 ++++++++++++++++++++++++++++----------------------- 1 file changed, 67 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 741a0d7f51ce..524703a7df2b 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1994,6 +1994,69 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, return driver; } +/** + * tty_open_by_driver - open a tty device + * @device: dev_t of device to open + * @inode: inode of device file + * @filp: file pointer to tty + * + * Performs the driver lookup, checks for a reopen, or otherwise + * performs the first-time tty initialization. + * + * Returns the locked initialized or re-opened &tty_struct + * + * Claims the global tty_mutex to serialize: + * - concurrent first-time tty initialization + * - concurrent tty driver removal w/ lookup + * - concurrent tty removal from driver table + */ +static struct tty_struct *tty_open_by_driver(dev_t device, struct inode *inode, + struct file *filp) +{ + struct tty_struct *tty; + struct tty_driver *driver = NULL; + int index = -1; + int retval; + + mutex_lock(&tty_mutex); + driver = tty_lookup_driver(device, filp, &index); + if (IS_ERR(driver)) { + mutex_unlock(&tty_mutex); + return ERR_CAST(driver); + } + + /* check whether we're reopening an existing tty */ + tty = tty_driver_lookup_tty(driver, inode, index); + if (IS_ERR(tty)) { + mutex_unlock(&tty_mutex); + goto out; + } + + if (tty) { + mutex_unlock(&tty_mutex); + retval = tty_lock_interruptible(tty); + if (retval) { + if (retval == -EINTR) + retval = -ERESTARTSYS; + tty = ERR_PTR(retval); + goto out; + } + /* safe to drop the kref from tty_driver_lookup_tty() */ + tty_kref_put(tty); + retval = tty_reopen(tty); + if (retval < 0) { + tty_unlock(tty); + tty = ERR_PTR(retval); + } + } else { /* Returns with the tty_lock held for now */ + tty = tty_init_dev(driver, index); + mutex_unlock(&tty_mutex); + } +out: + tty_driver_kref_put(driver); + return tty; +} + /** * tty_open - open a tty device * @inode: inode of device file @@ -2022,8 +2085,6 @@ static int tty_open(struct inode *inode, struct file *filp) { struct tty_struct *tty; int noctty, retval; - struct tty_driver *driver = NULL; - int index; dev_t device = inode->i_rdev; unsigned saved_flags = filp->f_flags; @@ -2034,53 +2095,15 @@ retry_open: if (retval) return -ENOMEM; - index = -1; - retval = 0; - tty = tty_open_current_tty(device, filp); - if (!tty) { - mutex_lock(&tty_mutex); - driver = tty_lookup_driver(device, filp, &index); - if (IS_ERR(driver)) { - retval = PTR_ERR(driver); - goto err_unlock; - } - - /* check whether we're reopening an existing tty */ - tty = tty_driver_lookup_tty(driver, inode, index); - if (IS_ERR(tty)) { - retval = PTR_ERR(tty); - goto err_unlock; - } - - if (tty) { - mutex_unlock(&tty_mutex); - retval = tty_lock_interruptible(tty); - if (retval) { - if (retval == -EINTR) - retval = -ERESTARTSYS; - goto err_unref; - } - /* safe to drop the kref from tty_driver_lookup_tty() */ - tty_kref_put(tty); - retval = tty_reopen(tty); - if (retval < 0) { - tty_unlock(tty); - tty = ERR_PTR(retval); - } - } else { /* Returns with the tty_lock held for now */ - tty = tty_init_dev(driver, index); - mutex_unlock(&tty_mutex); - } - - tty_driver_kref_put(driver); - } + if (!tty) + tty = tty_open_by_driver(device, inode, filp); if (IS_ERR(tty)) { + tty_free_file(filp); retval = PTR_ERR(tty); if (retval != -EAGAIN || signal_pending(current)) - goto err_file; - tty_free_file(filp); + return retval; schedule(); goto retry_open; } @@ -2151,15 +2174,6 @@ retry_open: read_unlock(&tasklist_lock); tty_unlock(tty); return 0; -err_unlock: - mutex_unlock(&tty_mutex); -err_unref: - /* after locks to avoid deadlock */ - if (!IS_ERR_OR_NULL(driver)) - tty_driver_kref_put(driver); -err_file: - tty_free_file(filp); - return retval; } -- cgit v1.2.3 From e4cf92ba44b86d287bdf1ef6a70417b98c441c7b Mon Sep 17 00:00:00 2001 From: Oreste Salerno Date: Wed, 27 Jan 2016 13:53:33 -0800 Subject: Input: cyttsp - use devres managed resource allocations Use devm_() functions for allocating memory, input device and IRQ. Signed-off-by: Oreste Salerno Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cyttsp_core.c | 68 +++++++++++++++------------------ drivers/input/touchscreen/cyttsp_core.h | 1 - drivers/input/touchscreen/cyttsp_i2c.c | 10 ----- drivers/input/touchscreen/cyttsp_spi.c | 10 ----- 4 files changed, 30 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index 5b74e8b84e79..2d699808b55a 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -528,6 +528,14 @@ static void cyttsp_close(struct input_dev *dev) cyttsp_disable(ts); } +static void cyttsp_platform_exit(void *data) +{ + struct cyttsp *ts = data; + + if (ts->pdata->exit) + ts->pdata->exit(); +} + struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct device *dev, int irq, size_t xfer_buf_size) { @@ -536,17 +544,16 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct input_dev *input_dev; int error; - if (!pdata || !pdata->name || irq <= 0) { - error = -EINVAL; - goto err_out; - } + if (!pdata || !pdata->name || irq <= 0) + return ERR_PTR(-EINVAL); - ts = kzalloc(sizeof(*ts) + xfer_buf_size, GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ts || !input_dev) { - error = -ENOMEM; - goto err_free_mem; - } + ts = devm_kzalloc(dev, sizeof(*ts) + xfer_buf_size, GFP_KERNEL); + if (!ts) + return ERR_PTR(-ENOMEM); + + input_dev = devm_input_allocate_device(dev); + if (!input_dev) + return ERR_PTR(-ENOMEM); ts->dev = dev; ts->input = input_dev; @@ -557,12 +564,18 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, init_completion(&ts->bl_ready); snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); + error = devm_add_action(dev, cyttsp_platform_exit, ts); + if (error) { + dev_err(dev, "failed to install exit action: %d\n", error); + return ERR_PTR(error); + } + if (pdata->init) { error = pdata->init(); if (error) { dev_err(ts->dev, "platform init failed, err: %d\n", error); - goto err_free_mem; + return ERR_PTR(error); } } @@ -586,53 +599,32 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, input_mt_init_slots(input_dev, CY_MAX_ID, 0); - error = request_threaded_irq(ts->irq, NULL, cyttsp_irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - pdata->name, ts); + error = devm_request_threaded_irq(dev, ts->irq, NULL, cyttsp_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + pdata->name, ts); if (error) { dev_err(ts->dev, "failed to request IRQ %d, err: %d\n", ts->irq, error); - goto err_platform_exit; + return ERR_PTR(error); } disable_irq(ts->irq); error = cyttsp_power_on(ts); if (error) - goto err_free_irq; + return ERR_PTR(error); error = input_register_device(input_dev); if (error) { dev_err(ts->dev, "failed to register input device: %d\n", error); - goto err_free_irq; + return ERR_PTR(error); } return ts; - -err_free_irq: - free_irq(ts->irq, ts); -err_platform_exit: - if (pdata->exit) - pdata->exit(); -err_free_mem: - input_free_device(input_dev); - kfree(ts); -err_out: - return ERR_PTR(error); } EXPORT_SYMBOL_GPL(cyttsp_probe); -void cyttsp_remove(struct cyttsp *ts) -{ - free_irq(ts->irq, ts); - input_unregister_device(ts->input); - if (ts->pdata->exit) - ts->pdata->exit(); - kfree(ts); -} -EXPORT_SYMBOL_GPL(cyttsp_remove); - MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen driver core"); MODULE_AUTHOR("Cypress"); diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h index 07074110a902..c5e7afce6de8 100644 --- a/drivers/input/touchscreen/cyttsp_core.h +++ b/drivers/input/touchscreen/cyttsp_core.h @@ -143,7 +143,6 @@ struct cyttsp { struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct device *dev, int irq, size_t xfer_buf_size); -void cyttsp_remove(struct cyttsp *ts); int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, const void *values); diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c index eee51b3f2e3f..1edfdba96ede 100644 --- a/drivers/input/touchscreen/cyttsp_i2c.c +++ b/drivers/input/touchscreen/cyttsp_i2c.c @@ -56,15 +56,6 @@ static int cyttsp_i2c_probe(struct i2c_client *client, return 0; } -static int cyttsp_i2c_remove(struct i2c_client *client) -{ - struct cyttsp *ts = i2c_get_clientdata(client); - - cyttsp_remove(ts); - - return 0; -} - static const struct i2c_device_id cyttsp_i2c_id[] = { { CY_I2C_NAME, 0 }, { } @@ -77,7 +68,6 @@ static struct i2c_driver cyttsp_i2c_driver = { .pm = &cyttsp_pm_ops, }, .probe = cyttsp_i2c_probe, - .remove = cyttsp_i2c_remove, .id_table = cyttsp_i2c_id, }; diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c index bbeeb2488b57..3c9d18b1b6ef 100644 --- a/drivers/input/touchscreen/cyttsp_spi.c +++ b/drivers/input/touchscreen/cyttsp_spi.c @@ -170,22 +170,12 @@ static int cyttsp_spi_probe(struct spi_device *spi) return 0; } -static int cyttsp_spi_remove(struct spi_device *spi) -{ - struct cyttsp *ts = spi_get_drvdata(spi); - - cyttsp_remove(ts); - - return 0; -} - static struct spi_driver cyttsp_spi_driver = { .driver = { .name = CY_SPI_NAME, .pm = &cyttsp_pm_ops, }, .probe = cyttsp_spi_probe, - .remove = cyttsp_spi_remove, }; module_spi_driver(cyttsp_spi_driver); -- cgit v1.2.3 From 69a124029b4bfcfc66b477ad2c3298f06c905ee6 Mon Sep 17 00:00:00 2001 From: Oreste Salerno Date: Wed, 27 Jan 2016 13:55:20 -0800 Subject: Input: cyttsp - check return value of input_mt_init_slots Signed-off-by: Oreste Salerno Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cyttsp_core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index 2d699808b55a..b6653aa06108 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -597,7 +597,11 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, CY_MAXZ, 0, 0); - input_mt_init_slots(input_dev, CY_MAX_ID, 0); + error = input_mt_init_slots(input_dev, CY_MAX_ID, 0); + if (error) { + dev_err(dev, "Unable to init MT slots.\n"); + return ERR_PTR(error); + } error = devm_request_threaded_irq(dev, ts->irq, NULL, cyttsp_irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, -- cgit v1.2.3 From 707b61bba8b16adb6a2cbc72b71a75e09cb0f81a Mon Sep 17 00:00:00 2001 From: Oreste Salerno Date: Wed, 27 Jan 2016 13:55:43 -0800 Subject: Input: cyttsp - switch to using device properties Drop support for platform data passed via a C-structure and switch to device properties instead, which should make the driver compatible with all platforms: OF, ACPI and static boards. Static boards should use property sets to communicate device parameters to the driver. Signed-off-by: Oreste Salerno Acked-by: Rob Herring Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/cyttsp.txt | 95 ++++++++++++++ drivers/input/touchscreen/cyttsp_core.c | 136 ++++++++++++++------- drivers/input/touchscreen/cyttsp_core.h | 9 +- include/linux/input/cyttsp.h | 15 --- 4 files changed, 197 insertions(+), 58 deletions(-) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/cyttsp.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/input/touchscreen/cyttsp.txt b/Documentation/devicetree/bindings/input/touchscreen/cyttsp.txt new file mode 100644 index 000000000000..b75d4cfd2c36 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/cyttsp.txt @@ -0,0 +1,95 @@ +* Cypress cyttsp touchscreen controller + +Required properties: + - compatible : must be "cypress,cyttsp-i2c" or "cypress,cyttsp-spi" + - reg : Device I2C address or SPI chip select number + - spi-max-frequency : Maximum SPI clocking speed of the device (for cyttsp-spi) + - interrupt-parent : the phandle for the gpio controller + (see interrupt binding[0]). + - interrupts : (gpio) interrupt to which the chip is connected + (see interrupt binding[0]). + - bootloader-key : the 8-byte bootloader key that is required to switch + the chip from bootloader mode (default mode) to + application mode. + This property has to be specified as an array of 8 + '/bits/ 8' values. + +Optional properties: + - reset-gpios : the reset gpio the chip is connected to + (see GPIO binding[1] for more details). + - touchscreen-size-x : horizontal resolution of touchscreen (in pixels) + - touchscreen-size-y : vertical resolution of touchscreen (in pixels) + - touchscreen-fuzz-x : horizontal noise value of the absolute input device + (in pixels) + - touchscreen-fuzz-y : vertical noise value of the absolute input device + (in pixels) + - active-distance : the distance in pixels beyond which a touch must move + before movement is detected and reported by the device. + Valid values: 0-15. + - active-interval-ms : the minimum period in ms between consecutive + scanning/processing cycles when the chip is in active mode. + Valid values: 0-255. + - lowpower-interval-ms : the minimum period in ms between consecutive + scanning/processing cycles when the chip is in low-power mode. + Valid values: 0-2550 + - touch-timeout-ms : minimum time in ms spent in the active power state while no + touches are detected before entering low-power mode. + Valid values: 0-2550 + - use-handshake : enable register-based handshake (boolean). This should + only be used if the chip is configured to use 'blocking + communication with timeout' (in this case the device + generates an interrupt at the end of every + scanning/processing cycle). + +[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt +[1]: Documentation/devicetree/bindings/gpio/gpio.txt + +Example: + &i2c1 { + /* ... */ + cyttsp@a { + compatible = "cypress,cyttsp-i2c"; + reg = <0xa>; + interrupt-parent = <&gpio0>; + interrupts = <28 0>; + reset-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>; + + touchscreen-size-x = <800>; + touchscreen-size-y = <480>; + touchscreen-fuzz-x = <4>; + touchscreen-fuzz-y = <7>; + + bootloader-key = /bits/ 8 <0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08>; + active-distance = <8>; + active-interval-ms = <0>; + lowpower-interval-ms = <200>; + touch-timeout-ms = <100>; + }; + + /* ... */ + }; + + &mcspi1 { + /* ... */ + cyttsp@0 { + compatible = "cypress,cyttsp-spi"; + spi-max-frequency = <6000000>; + reg = <0>; + interrupt-parent = <&gpio0>; + interrupts = <28 0>; + reset-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>; + + touchscreen-size-x = <800>; + touchscreen-size-y = <480>; + touchscreen-fuzz-x = <4>; + touchscreen-fuzz-y = <7>; + + bootloader-key = /bits/ 8 <0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08>; + active-distance = <8>; + active-interval-ms = <0>; + lowpower-interval-ms = <200>; + touch-timeout-ms = <100>; + }; + + /* ... */ + }; diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index b6653aa06108..8814b6c87097 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -30,9 +30,12 @@ #include #include #include +#include #include #include #include +#include +#include #include "cyttsp_core.h" @@ -57,6 +60,7 @@ #define CY_DELAY_DFLT 20 /* ms */ #define CY_DELAY_MAX 500 #define CY_ACT_DIST_DFLT 0xF8 +#define CY_ACT_DIST_MASK 0x0F #define CY_HNDSHK_BIT 0x80 /* device mode bits */ #define CY_OPERATE_MODE 0x00 @@ -120,7 +124,7 @@ static int ttsp_send_command(struct cyttsp *ts, u8 cmd) static int cyttsp_handshake(struct cyttsp *ts) { - if (ts->pdata->use_hndshk) + if (ts->use_hndshk) return ttsp_send_command(ts, ts->xy_data.hst_mode ^ CY_HNDSHK_BIT); @@ -142,9 +146,9 @@ static int cyttsp_exit_bl_mode(struct cyttsp *ts) u8 bl_cmd[sizeof(bl_command)]; memcpy(bl_cmd, bl_command, sizeof(bl_command)); - if (ts->pdata->bl_keys) + if (ts->bl_keys) memcpy(&bl_cmd[sizeof(bl_command) - CY_NUM_BL_KEYS], - ts->pdata->bl_keys, CY_NUM_BL_KEYS); + ts->bl_keys, CY_NUM_BL_KEYS); error = ttsp_write_block_data(ts, CY_REG_BASE, sizeof(bl_cmd), bl_cmd); @@ -217,14 +221,14 @@ static int cyttsp_set_sysinfo_regs(struct cyttsp *ts) { int retval = 0; - if (ts->pdata->act_intrvl != CY_ACT_INTRVL_DFLT || - ts->pdata->tch_tmout != CY_TCH_TMOUT_DFLT || - ts->pdata->lp_intrvl != CY_LP_INTRVL_DFLT) { + if (ts->act_intrvl != CY_ACT_INTRVL_DFLT || + ts->tch_tmout != CY_TCH_TMOUT_DFLT || + ts->lp_intrvl != CY_LP_INTRVL_DFLT) { u8 intrvl_ray[] = { - ts->pdata->act_intrvl, - ts->pdata->tch_tmout, - ts->pdata->lp_intrvl + ts->act_intrvl, + ts->tch_tmout, + ts->lp_intrvl }; /* set intrvl registers */ @@ -263,7 +267,7 @@ out: static int cyttsp_act_dist_setup(struct cyttsp *ts) { - u8 act_dist_setup = ts->pdata->act_dist; + u8 act_dist_setup = ts->act_dist; /* Init gesture; active distance setup */ return ttsp_write_block_data(ts, CY_REG_ACT_DIST, @@ -528,25 +532,82 @@ static void cyttsp_close(struct input_dev *dev) cyttsp_disable(ts); } -static void cyttsp_platform_exit(void *data) +static int cyttsp_parse_properties(struct cyttsp *ts) { - struct cyttsp *ts = data; + struct device *dev = ts->dev; + u32 dt_value; + int ret; + + ts->bl_keys = devm_kzalloc(dev, CY_NUM_BL_KEYS, GFP_KERNEL); + if (!ts->bl_keys) + return -ENOMEM; + + /* Set some default values */ + ts->use_hndshk = false; + ts->act_dist = CY_ACT_DIST_DFLT; + ts->act_intrvl = CY_ACT_INTRVL_DFLT; + ts->tch_tmout = CY_TCH_TMOUT_DFLT; + ts->lp_intrvl = CY_LP_INTRVL_DFLT; + + ret = device_property_read_u8_array(dev, "bootloader-key", + ts->bl_keys, CY_NUM_BL_KEYS); + if (ret) { + dev_err(dev, + "bootloader-key property could not be retrieved\n"); + return ret; + } + + ts->use_hndshk = device_property_present(dev, "use-handshake"); + + if (!device_property_read_u32(dev, "active-distance", &dt_value)) { + if (dt_value > 15) { + dev_err(dev, "active-distance (%u) must be [0-15]\n", + dt_value); + return -EINVAL; + } + ts->act_dist &= ~CY_ACT_DIST_MASK; + ts->act_dist |= dt_value; + } + + if (!device_property_read_u32(dev, "active-interval-ms", &dt_value)) { + if (dt_value > 255) { + dev_err(dev, "active-interval-ms (%u) must be [0-255]\n", + dt_value); + return -EINVAL; + } + ts->act_intrvl = dt_value; + } - if (ts->pdata->exit) - ts->pdata->exit(); + if (!device_property_read_u32(dev, "lowpower-interval-ms", &dt_value)) { + if (dt_value > 2550) { + dev_err(dev, "lowpower-interval-ms (%u) must be [0-2550]\n", + dt_value); + return -EINVAL; + } + /* Register value is expressed in 0.01s / bit */ + ts->lp_intrvl = dt_value / 10; + } + + if (!device_property_read_u32(dev, "touch-timeout-ms", &dt_value)) { + if (dt_value > 2550) { + dev_err(dev, "touch-timeout-ms (%u) must be [0-2550]\n", + dt_value); + return -EINVAL; + } + /* Register value is expressed in 0.01s / bit */ + ts->tch_tmout = dt_value / 10; + } + + return 0; } struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct device *dev, int irq, size_t xfer_buf_size) { - const struct cyttsp_platform_data *pdata = dev_get_platdata(dev); struct cyttsp *ts; struct input_dev *input_dev; int error; - if (!pdata || !pdata->name || irq <= 0) - return ERR_PTR(-EINVAL); - ts = devm_kzalloc(dev, sizeof(*ts) + xfer_buf_size, GFP_KERNEL); if (!ts) return ERR_PTR(-ENOMEM); @@ -557,29 +618,24 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, ts->dev = dev; ts->input = input_dev; - ts->pdata = dev_get_platdata(dev); ts->bus_ops = bus_ops; ts->irq = irq; - init_completion(&ts->bl_ready); - snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); - - error = devm_add_action(dev, cyttsp_platform_exit, ts); - if (error) { - dev_err(dev, "failed to install exit action: %d\n", error); + ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(ts->reset_gpio)) { + error = PTR_ERR(ts->reset_gpio); + dev_err(dev, "Failed to request reset gpio, error %d\n", error); return ERR_PTR(error); } - if (pdata->init) { - error = pdata->init(); - if (error) { - dev_err(ts->dev, "platform init failed, err: %d\n", - error); - return ERR_PTR(error); - } - } + error = cyttsp_parse_properties(ts); + if (error) + return ERR_PTR(error); + + init_completion(&ts->bl_ready); + snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); - input_dev->name = pdata->name; + input_dev->name = "Cypress TTSP TouchScreen"; input_dev->phys = ts->phys; input_dev->id.bustype = bus_ops->bustype; input_dev->dev.parent = ts->dev; @@ -589,13 +645,9 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, input_set_drvdata(input_dev, ts); - __set_bit(EV_ABS, input_dev->evbit); - input_set_abs_params(input_dev, ABS_MT_POSITION_X, - 0, pdata->maxx, 0, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_Y, - 0, pdata->maxy, 0, 0); - input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, - 0, CY_MAXZ, 0, 0); + input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X); + input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y); + touchscreen_parse_properties(input_dev, true); error = input_mt_init_slots(input_dev, CY_MAX_ID, 0); if (error) { @@ -605,7 +657,7 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, error = devm_request_threaded_irq(dev, ts->irq, NULL, cyttsp_irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - pdata->name, ts); + "cyttsp", ts); if (error) { dev_err(ts->dev, "failed to request IRQ %d, err: %d\n", ts->irq, error); diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h index c5e7afce6de8..7835e2bacf5a 100644 --- a/drivers/input/touchscreen/cyttsp_core.h +++ b/drivers/input/touchscreen/cyttsp_core.h @@ -129,7 +129,6 @@ struct cyttsp { int irq; struct input_dev *input; char phys[32]; - const struct cyttsp_platform_data *pdata; const struct cyttsp_bus_ops *bus_ops; struct cyttsp_bootloader_data bl_data; struct cyttsp_sysinfo_data sysinfo_data; @@ -138,6 +137,14 @@ struct cyttsp { enum cyttsp_state state; bool suspended; + struct gpio_desc *reset_gpio; + bool use_hndshk; + u8 act_dist; + u8 act_intrvl; + u8 tch_tmout; + u8 lp_intrvl; + u8 *bl_keys; + u8 xfer_buf[] ____cacheline_aligned; }; diff --git a/include/linux/input/cyttsp.h b/include/linux/input/cyttsp.h index 5af7c66f1fca..586c8c95dcb0 100644 --- a/include/linux/input/cyttsp.h +++ b/include/linux/input/cyttsp.h @@ -40,19 +40,4 @@ /* Active distance in pixels for a gesture to be reported */ #define CY_ACT_DIST_DFLT 0xF8 /* pixels */ -struct cyttsp_platform_data { - u32 maxx; - u32 maxy; - bool use_hndshk; - u8 act_dist; /* Active distance */ - u8 act_intrvl; /* Active refresh interval; ms */ - u8 tch_tmout; /* Active touch timeout; ms */ - u8 lp_intrvl; /* Low power refresh interval; ms */ - int (*init)(void); - void (*exit)(void); - char *name; - s16 irq_gpio; - u8 *bl_keys; -}; - #endif /* _CYTTSP_H_ */ -- cgit v1.2.3 From 8fb81d20019db3dea4126e3eac7ef8dc89b10b9e Mon Sep 17 00:00:00 2001 From: Oreste Salerno Date: Wed, 27 Jan 2016 13:58:38 -0800 Subject: Input: cyttsp - perform hard reset of the chip during probe Since we removed support for calling an init() callback from the platform data, introduce a function which initializes the chip by performing a hard reset, using the reset gpio defined in the device properties. Signed-off-by: Oreste Salerno Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cyttsp_core.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index 8814b6c87097..91cda8f8119d 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -240,6 +240,16 @@ static int cyttsp_set_sysinfo_regs(struct cyttsp *ts) return retval; } +static void cyttsp_hard_reset(struct cyttsp *ts) +{ + if (ts->reset_gpio) { + gpiod_set_value_cansleep(ts->reset_gpio, 1); + msleep(CY_DELAY_DFLT); + gpiod_set_value_cansleep(ts->reset_gpio, 0); + msleep(CY_DELAY_DFLT); + } +} + static int cyttsp_soft_reset(struct cyttsp *ts) { unsigned long timeout; @@ -666,6 +676,8 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, disable_irq(ts->irq); + cyttsp_hard_reset(ts); + error = cyttsp_power_on(ts); if (error) return ERR_PTR(error); -- cgit v1.2.3 From 46560388c476c8471fde7712c10f9fad8d0d1875 Mon Sep 17 00:00:00 2001 From: Ray Jui Date: Wed, 27 Jan 2016 16:52:24 -0600 Subject: PCI: iproc: Allow multiple devices except on PAXC Commit 943ebae781f5 ("PCI: iproc: Add PAXC interface support") only allowed device 0, which is a regression on BCMA-based platforms. All systems support only one device, a Root Port at 00:00.0, on the root bus. PAXC-based systems support only the Root Port (00:00.0) and a single device (with multiple functions) below it, e.g., 01:00.0, 01:00.1, etc. Non-PAXC systems support arbitrary devices below the Root Port. [bhelgaas: changelog, fold in removal of MAX_NUM_PAXC_PF check] Fixes: 943ebae781f5 ("PCI: iproc: Add PAXC interface support") Reported-by: Rafal Milecki Signed-off-by: Ray Jui Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-iproc.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pcie-iproc.c b/drivers/pci/host/pcie-iproc.c index 5816bceddb65..a576aeeb22da 100644 --- a/drivers/pci/host/pcie-iproc.c +++ b/drivers/pci/host/pcie-iproc.c @@ -64,7 +64,6 @@ #define OARR_SIZE_CFG BIT(OARR_SIZE_CFG_SHIFT) #define MAX_NUM_OB_WINDOWS 2 -#define MAX_NUM_PAXC_PF 4 #define IPROC_PCIE_REG_INVALID 0xffff @@ -170,20 +169,6 @@ static inline void iproc_pcie_ob_write(struct iproc_pcie *pcie, writel(val, pcie->base + offset + (window * 8)); } -static inline bool iproc_pcie_device_is_valid(struct iproc_pcie *pcie, - unsigned int slot, - unsigned int fn) -{ - if (slot > 0) - return false; - - /* PAXC can only support limited number of functions */ - if (pcie->type == IPROC_PCIE_PAXC && fn >= MAX_NUM_PAXC_PF) - return false; - - return true; -} - /** * Note access to the configuration registers are protected at the higher layer * by 'pci_lock' in drivers/pci/access.c @@ -199,11 +184,11 @@ static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus, u32 val; u16 offset; - if (!iproc_pcie_device_is_valid(pcie, slot, fn)) - return NULL; - /* root complex access */ if (busno == 0) { + if (slot > 0 || fn > 0) + return NULL; + iproc_pcie_write_reg(pcie, IPROC_PCIE_CFG_IND_ADDR, where & CFG_IND_ADDR_MASK); offset = iproc_pcie_reg_offset(pcie, IPROC_PCIE_CFG_IND_DATA); @@ -213,6 +198,14 @@ static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus, return (pcie->base + offset); } + /* + * PAXC is connected to an internally emulated EP within the SoC. It + * allows only one device. + */ + if (pcie->type == IPROC_PCIE_PAXC) + if (slot > 0) + return NULL; + /* EP device access */ val = (busno << CFG_ADDR_BUS_NUM_SHIFT) | (slot << CFG_ADDR_DEV_NUM_SHIFT) | -- cgit v1.2.3 From 6aa56785e735fcfffffef7655f113b56f05c0df5 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:40:50 -0800 Subject: staging: digi: Replace open-coded tty_wakeup() The open-coded tty_wakeup()s are attempts to workaround fixed bugs in the line discipline write_wakeup() method. Replace with tty_wakeup(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgap/dgap.c | 28 ++++++---------------------- drivers/staging/dgnc/dgnc_tty.c | 18 ++---------------- 2 files changed, 8 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index bad355100825..dfbae215aec3 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -1665,9 +1665,7 @@ static void dgap_input(struct channel_t *ch) } static void dgap_write_wakeup(struct board_t *bd, struct channel_t *ch, - struct un_t *un, u32 mask, - unsigned long *irq_flags1, - unsigned long *irq_flags2) + struct un_t *un, u32 mask) { if (!(un->un_flags & mask)) return; @@ -1677,17 +1675,7 @@ static void dgap_write_wakeup(struct board_t *bd, struct channel_t *ch, if (!(un->un_flags & UN_ISOPEN)) return; - if ((un->un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - un->un_tty->ldisc->ops->write_wakeup) { - spin_unlock_irqrestore(&ch->ch_lock, *irq_flags2); - spin_unlock_irqrestore(&bd->bd_lock, *irq_flags1); - - (un->un_tty->ldisc->ops->write_wakeup)(un->un_tty); - - spin_lock_irqsave(&bd->bd_lock, *irq_flags1); - spin_lock_irqsave(&ch->ch_lock, *irq_flags2); - } - wake_up_interruptible(&un->un_tty->write_wait); + tty_wakeup(un->un_tty); wake_up_interruptible(&un->un_flags_wait); } @@ -1952,10 +1940,8 @@ static int dgap_event(struct board_t *bd) * Process Transmit low. */ if (reason & IFTLW) { - dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_LOW, - &lock_flags, &lock_flags2); - dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_LOW, - &lock_flags, &lock_flags2); + dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_LOW); + dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_LOW); if (ch->ch_flags & CH_WLOW) { ch->ch_flags &= ~CH_WLOW; wake_up_interruptible(&ch->ch_flags_wait); @@ -1966,10 +1952,8 @@ static int dgap_event(struct board_t *bd) * Process Transmit empty. */ if (reason & IFTEM) { - dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_EMPTY, - &lock_flags, &lock_flags2); - dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_EMPTY, - &lock_flags, &lock_flags2); + dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_EMPTY); + dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_EMPTY); if (ch->ch_flags & CH_WEMPTY) { ch->ch_flags &= ~CH_WEMPTY; wake_up_interruptible(&ch->ch_flags_wait); diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index b79eab084c02..4a3d2c6f7eac 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -933,14 +933,7 @@ void dgnc_wakeup_writes(struct channel_t *ch) } if (ch->ch_tun.un_flags & UN_ISOPEN) { - if ((ch->ch_tun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - ch->ch_tun.un_tty->ldisc->ops->write_wakeup) { - spin_unlock_irqrestore(&ch->ch_lock, flags); - ch->ch_tun.un_tty->ldisc->ops->write_wakeup(ch->ch_tun.un_tty); - spin_lock_irqsave(&ch->ch_lock, flags); - } - - wake_up_interruptible(&ch->ch_tun.un_tty->write_wait); + tty_wakeup(ch->ch_tun.un_tty); /* * If unit is set to wait until empty, check to make sure @@ -975,14 +968,7 @@ void dgnc_wakeup_writes(struct channel_t *ch) } if (ch->ch_pun.un_flags & UN_ISOPEN) { - if ((ch->ch_pun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - ch->ch_pun.un_tty->ldisc->ops->write_wakeup) { - spin_unlock_irqrestore(&ch->ch_lock, flags); - ch->ch_pun.un_tty->ldisc->ops->write_wakeup(ch->ch_pun.un_tty); - spin_lock_irqsave(&ch->ch_lock, flags); - } - - wake_up_interruptible(&ch->ch_pun.un_tty->write_wait); + tty_wakeup(ch->ch_pun.un_tty); /* * If unit is set to wait until empty, check to make sure -- cgit v1.2.3 From 46b94e779e8a53b83e8d84e5aeb443d8b8bd45ea Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:40:51 -0800 Subject: serial: 68328: Remove bogus ldisc reset As the #warning indicates, the open-coded ldisc reset was always not ok. Not only is this code long dead, but now it would have no effect as the ldisc is destroyed when this driver's close() method returns; remove. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/68328serial.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index 0982c1a44187..90639b590a10 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -1054,17 +1054,7 @@ static void rs_close(struct tty_struct *tty, struct file *filp) tty_ldisc_flush(tty); tty->closing = 0; tty_port_tty_set(&info->tport, NULL); -#warning "This is not and has never been valid so fix it" -#if 0 - if (tty->ldisc.num != ldiscs[N_TTY].num) { - if (tty->ldisc.close) - (tty->ldisc.close)(tty); - tty->ldisc = ldiscs[N_TTY]; - tty->termios.c_line = N_TTY; - if (tty->ldisc.open) - (tty->ldisc.open)(tty); - } -#endif + if (port->blocked_open) { if (port->close_delay) msleep_interruptible(jiffies_to_msecs(port->close_delay)); -- cgit v1.2.3 From fdfb719e93b55a50f90da2059dc450e7c0c48e8f Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:40:54 -0800 Subject: tty: Remove chars_in_buffer() line discipline method The chars_in_buffer() line discipline method serves no functional purpose, other than as a (dubious) debugging aid for mostly bit-rotting drivers. Despite being documented as an optional method, every caller is unconditionally executed (although conditionally compiled). Furthermore, direct tty->ldisc access without an ldisc ref is unsafe. Lastly, N_TTY's chars_in_buffer() has warned of removal since 3.12. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- Documentation/serial/tty.txt | 3 --- drivers/tty/amiserial.c | 6 ++---- drivers/tty/cyclades.c | 8 ++++---- drivers/tty/n_gsm.c | 16 ---------------- drivers/tty/n_tty.c | 23 ----------------------- drivers/tty/rocket.c | 6 ++---- drivers/tty/serial/crisv10.c | 12 +++++------- include/linux/tty_ldisc.h | 7 ------- 8 files changed, 13 insertions(+), 68 deletions(-) (limited to 'drivers') diff --git a/Documentation/serial/tty.txt b/Documentation/serial/tty.txt index bc3842dc323a..798cba82c762 100644 --- a/Documentation/serial/tty.txt +++ b/Documentation/serial/tty.txt @@ -72,9 +72,6 @@ flush_buffer() - (optional) May be called at any point between open and close, and instructs the line discipline to empty its input buffer. -chars_in_buffer() - (optional) Report the number of bytes in the input - buffer. - set_termios() - (optional) Called on termios structure changes. The caller passes the old termios data and the current data is in the tty. Called under the diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 2caaf5a2516d..6ba5681b6385 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -965,8 +965,7 @@ static void rs_throttle(struct tty_struct * tty) struct serial_state *info = tty->driver_data; unsigned long flags; #ifdef SERIAL_DEBUG_THROTTLE - printk("throttle %s: %d....\n", tty_name(tty), - tty->ldisc.chars_in_buffer(tty)); + printk("throttle %s ....\n", tty_name(tty)); #endif if (serial_paranoia_check(info, tty->name, "rs_throttle")) @@ -988,8 +987,7 @@ static void rs_unthrottle(struct tty_struct * tty) struct serial_state *info = tty->driver_data; unsigned long flags; #ifdef SERIAL_DEBUG_THROTTLE - printk("unthrottle %s: %d....\n", tty_name(tty), - tty->ldisc.chars_in_buffer(tty)); + printk("unthrottle %s ....\n", tty_name(tty)); #endif if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index abbed201dc74..a48e7e66b970 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -2852,8 +2852,8 @@ static void cy_throttle(struct tty_struct *tty) unsigned long flags; #ifdef CY_DEBUG_THROTTLE - printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d\n", tty_name(tty), - tty->ldisc.chars_in_buffer(tty), info->line); + printk(KERN_DEBUG "cyc:throttle %s ...ttyC%d\n", tty_name(tty), + info->line); #endif if (serial_paranoia_check(info, tty->name, "cy_throttle")) @@ -2891,8 +2891,8 @@ static void cy_unthrottle(struct tty_struct *tty) unsigned long flags; #ifdef CY_DEBUG_THROTTLE - printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n", - tty_name(tty), tty_chars_in_buffer(tty), info->line); + printk(KERN_DEBUG "cyc:unthrottle %s ...ttyC%d\n", + tty_name(tty), info->line); #endif if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c3fe026d3168..e3cc27749344 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2303,21 +2303,6 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, /* If clogged call tty_throttle(tty); */ } -/** - * gsmld_chars_in_buffer - report available bytes - * @tty: tty device - * - * Report the number of characters buffered to be delivered to user - * at this instant in time. - * - * Locking: gsm lock - */ - -static ssize_t gsmld_chars_in_buffer(struct tty_struct *tty) -{ - return 0; -} - /** * gsmld_flush_buffer - clean input queue * @tty: terminal device @@ -2830,7 +2815,6 @@ static struct tty_ldisc_ops tty_ldisc_packet = { .open = gsmld_open, .close = gsmld_close, .flush_buffer = gsmld_flush_buffer, - .chars_in_buffer = gsmld_chars_in_buffer, .read = gsmld_read, .write = gsmld_write, .ioctl = gsmld_ioctl, diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index b280abaad91b..90eca2605fbf 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -380,28 +380,6 @@ static void n_tty_flush_buffer(struct tty_struct *tty) up_write(&tty->termios_rwsem); } -/** - * n_tty_chars_in_buffer - report available bytes - * @tty: tty device - * - * Report the number of characters buffered to be delivered to user - * at this instant in time. - * - * Locking: exclusive termios_rwsem - */ - -static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty) -{ - ssize_t n; - - WARN_ONCE(1, "%s is deprecated and scheduled for removal.", __func__); - - down_write(&tty->termios_rwsem); - n = chars_in_buffer(tty); - up_write(&tty->termios_rwsem); - return n; -} - /** * is_utf8_continuation - utf8 multibyte check * @c: byte to check @@ -2525,7 +2503,6 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = { .open = n_tty_open, .close = n_tty_close, .flush_buffer = n_tty_flush_buffer, - .chars_in_buffer = n_tty_chars_in_buffer, .read = n_tty_read, .write = n_tty_write, .ioctl = n_tty_ioctl, diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index 802eac7e561b..f624b93a237f 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -1360,8 +1360,7 @@ static void rp_throttle(struct tty_struct *tty) struct r_port *info = tty->driver_data; #ifdef ROCKET_DEBUG_THROTTLE - printk(KERN_INFO "throttle %s: %d....\n", tty->name, - tty->ldisc.chars_in_buffer(tty)); + printk(KERN_INFO "throttle %s ....\n", tty->name); #endif if (rocket_paranoia_check(info, "rp_throttle")) @@ -1377,8 +1376,7 @@ static void rp_unthrottle(struct tty_struct *tty) { struct r_port *info = tty->driver_data; #ifdef ROCKET_DEBUG_THROTTLE - printk(KERN_INFO "unthrottle %s: %d....\n", tty->name, - tty->ldisc.chars_in_buffer(tty)); + printk(KERN_INFO "unthrottle %s ....\n", tty->name); #endif if (rocket_paranoia_check(info, "rp_unthrottle")) diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index f13f2ebd215b..e98aef797065 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -2968,7 +2968,7 @@ static int rs_raw_write(struct tty_struct *tty, local_save_flags(flags); DFLOW(DEBUG_LOG(info->line, "write count %i ", count)); - DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty))); + DFLOW(DEBUG_LOG(info->line, "ldisc\n")); /* The local_irq_disable/restore_flags pairs below are needed @@ -3161,10 +3161,9 @@ rs_throttle(struct tty_struct * tty) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; #ifdef SERIAL_DEBUG_THROTTLE - printk("throttle %s: %lu....\n", tty_name(tty), - (unsigned long)tty->ldisc.chars_in_buffer(tty)); + printk("throttle %s ....\n", tty_name(tty)); #endif - DFLOW(DEBUG_LOG(info->line,"rs_throttle %lu\n", tty->ldisc.chars_in_buffer(tty))); + DFLOW(DEBUG_LOG(info->line,"rs_throttle\n")); /* Do RTS before XOFF since XOFF might take some time */ if (tty->termios.c_cflag & CRTSCTS) { @@ -3181,10 +3180,9 @@ rs_unthrottle(struct tty_struct * tty) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; #ifdef SERIAL_DEBUG_THROTTLE - printk("unthrottle %s: %lu....\n", tty_name(tty), - (unsigned long)tty->ldisc.chars_in_buffer(tty)); + printk("unthrottle %s ....\n", tty_name(tty)); #endif - DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc %d\n", tty->ldisc.chars_in_buffer(tty))); + DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc\n")); DFLOW(DEBUG_LOG(info->line,"rs_unthrottle flip.count: %i\n", tty->flip.count)); /* Do RTS before XOFF since XOFF might take some time */ if (tty->termios.c_cflag & CRTSCTS) { diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index 00c9d688d7b7..6101ab8dc148 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -25,12 +25,6 @@ * buffers of any input characters it may have queued to be * delivered to the user mode process. * - * ssize_t (*chars_in_buffer)(struct tty_struct *tty); - * - * This function returns the number of input characters the line - * discipline may have queued up to be delivered to the user mode - * process. - * * ssize_t (*read)(struct tty_struct * tty, struct file * file, * unsigned char * buf, size_t nr); * @@ -188,7 +182,6 @@ struct tty_ldisc_ops { int (*open)(struct tty_struct *); void (*close)(struct tty_struct *); void (*flush_buffer)(struct tty_struct *tty); - ssize_t (*chars_in_buffer)(struct tty_struct *tty); ssize_t (*read)(struct tty_struct *tty, struct file *file, unsigned char __user *buf, size_t nr); ssize_t (*write)(struct tty_struct *tty, struct file *file, -- cgit v1.2.3 From ece53405a1f8ddf60b78e1365addcad521b2c93f Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:40:57 -0800 Subject: tty: Reset c_line from driver's init_termios After the ldisc is released, but before the tty is destroyed, the termios is saved (in tty_free_termios()); this termios is restored if a new tty is created on next open(). However, the line discipline is always reset, which is not obvious in the current method. Instead, reset as part of the restore. Restore the original line discipline, which may not have been N_TTY. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 5 +++-- drivers/tty/tty_ldisc.c | 3 --- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 524703a7df2b..71a9409c8d7e 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1387,9 +1387,10 @@ void tty_init_termios(struct tty_struct *tty) else { /* Check for lazy saved data */ tp = tty->driver->termios[idx]; - if (tp != NULL) + if (tp != NULL) { tty->termios = *tp; - else + tty->termios.c_line = tty->driver->init_termios.c_line; + } else tty->termios = tty->driver->init_termios; } /* Compatibility until drivers always set this */ diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 713cc2d48846..b2e8210639dd 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -743,9 +743,6 @@ static void tty_ldisc_kill(struct tty_struct *tty) tty_ldisc_put(tty->ldisc); /* Force an oops if we mess this up */ tty->ldisc = NULL; - - /* Ensure the next open requests the N_TTY ldisc */ - tty_set_termios_ldisc(tty, N_TTY); } /** -- cgit v1.2.3 From c0cc1c5d6b67289ea2e77346e0161506b0d4f393 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:40:59 -0800 Subject: tty: Fix comments for tty_ldisc_get() tty_ldisc_get() returns ERR_PTR() values if unsuccessful, not NULL; fix function header documentation. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index b2e8210639dd..4008f5f65345 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -140,9 +140,16 @@ static void put_ldops(struct tty_ldisc_ops *ldops) * @disc: ldisc number * * Takes a reference to a line discipline. Deals with refcounts and - * module locking counts. Returns NULL if the discipline is not available. - * Returns a pointer to the discipline and bumps the ref count if it is - * available + * module locking counts. + * + * Returns: -EINVAL if the discipline index is not [N_TTY..NR_LDISCS] or + * if the discipline is not registered + * -EAGAIN if request_module() failed to load or register the + * the discipline + * -ENOMEM if allocation failure + * + * Otherwise, returns a pointer to the discipline and bumps the + * ref count * * Locking: * takes tty_ldiscs_lock to guard against ldisc races -- cgit v1.2.3 From 5b6e6832f41c9422753804671ee06af37ac8caf6 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:00 -0800 Subject: tty: Fix comments for tty_ldisc_release() tty_ldisc_kill() sets tty->ldisc to NULL; _not_ to N_TTY with a valid but unopened ldisc. Fix function header documentation. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 4008f5f65345..14d2165ba270 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -757,8 +757,7 @@ static void tty_ldisc_kill(struct tty_struct *tty) * @tty: tty being shut down (or one end of pty pair) * * Called during the final close of a tty or a pty pair in order to shut - * down the line discpline layer. On exit, each ldisc assigned is N_TTY and - * each ldisc has not been opened. + * down the line discpline layer. On exit, each tty's ldisc is NULL. */ void tty_ldisc_release(struct tty_struct *tty) -- cgit v1.2.3 From e55afd11a48354c810caf6b6ad4c103016a88230 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:01 -0800 Subject: tty: Prepare for destroying line discipline on hangup tty file_operations (read/write/ioctl) wait for the ldisc reference indefinitely (until ldisc lifetime events, such as hangup or TIOCSETD, finish). Since hangup now destroys the ldisc and does not instance another copy, file_operations must now be prepared to receive a NULL ldisc reference from tty_ldisc_ref_wait(): CPU 0 CPU 1 ----- ----- (*f_op->read)() => tty_read() __tty_hangup() ... f_op = &hung_up_tty_fops; ... tty_ldisc_hangup() tty_ldisc_lock() tty_ldisc_kill() tty->ldisc = NULL tty_ldisc_unlock() ld = tty_ldisc_ref_wait() /* ld == NULL */ Instead, the action taken now is to return the same value as if the tty had been hungup a moment earlier: CPU 0 CPU 1 ----- ----- __tty_hangup() ... f_op = &hung_up_tty_fops; (*f_op->read)() => hung_up_tty_read() return 0; ... tty_ldisc_hangup() tty_ldisc_lock() tty_ldisc_kill() tty->ldisc = NULL tty_ldisc_unlock() Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 14 ++++++++++++++ drivers/tty/tty_ldisc.c | 4 ++-- drivers/tty/vt/selection.c | 2 ++ 3 files changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 71a9409c8d7e..eb26754b2e5d 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1068,6 +1068,8 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, /* We want to wait for the line discipline to sort out in this situation */ ld = tty_ldisc_ref_wait(tty); + if (!ld) + return hung_up_tty_read(file, buf, count, ppos); if (ld->ops->read) i = ld->ops->read(tty, file, buf, count); else @@ -1242,6 +1244,8 @@ static ssize_t tty_write(struct file *file, const char __user *buf, if (tty->ops->write_room == NULL) tty_err(tty, "missing write_room method\n"); ld = tty_ldisc_ref_wait(tty); + if (!ld) + return hung_up_tty_write(file, buf, count, ppos); if (!ld->ops->write) ret = -EIO; else @@ -2201,6 +2205,8 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) return 0; ld = tty_ldisc_ref_wait(tty); + if (!ld) + return hung_up_tty_poll(filp, wait); if (ld->ops->poll) ret = ld->ops->poll(tty, filp, wait); tty_ldisc_deref(ld); @@ -2290,6 +2296,8 @@ static int tiocsti(struct tty_struct *tty, char __user *p) return -EFAULT; tty_audit_tiocsti(tty, ch); ld = tty_ldisc_ref_wait(tty); + if (!ld) + return -EIO; ld->ops->receive_buf(tty, &ch, &mbz, 1); tty_ldisc_deref(ld); return 0; @@ -2682,6 +2690,8 @@ static int tiocgetd(struct tty_struct *tty, int __user *p) int ret; ld = tty_ldisc_ref_wait(tty); + if (!ld) + return -EIO; ret = put_user(ld->ops->num, p); tty_ldisc_deref(ld); return ret; @@ -2979,6 +2989,8 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return retval; } ld = tty_ldisc_ref_wait(tty); + if (!ld) + return hung_up_tty_ioctl(file, cmd, arg); retval = -EINVAL; if (ld->ops->ioctl) { retval = ld->ops->ioctl(tty, file, cmd, arg); @@ -3007,6 +3019,8 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, } ld = tty_ldisc_ref_wait(tty); + if (!ld) + return hung_up_tty_compat_ioctl(file, cmd, arg); if (ld->ops->compat_ioctl) retval = ld->ops->compat_ioctl(tty, file, cmd, arg); else diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 14d2165ba270..d6805e1aee59 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -262,8 +262,8 @@ const struct file_operations tty_ldiscs_proc_fops = { * against a discipline change, such as an existing ldisc reference * (which we check for) * - * Note: only callable from a file_operations routine (which - * guarantees tty->ldisc != NULL when the lock is acquired). + * Note: a file_operations routine (read/poll/write) should use this + * function to wait for any ldisc lifetime events to finish. */ struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 381a2b13682c..4dd9dd2270a0 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -347,6 +347,8 @@ int paste_selection(struct tty_struct *tty) console_unlock(); ld = tty_ldisc_ref_wait(tty); + if (!ld) + return -EIO; /* ldisc was hung up */ tty_buffer_lock_exclusive(&vc->port); add_wait_queue(&vc->paste_wait, &wait); -- cgit v1.2.3 From a570a49abd343102ce681bbf8273897c3c9fd2d1 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:02 -0800 Subject: tty: Handle NULL tty->ldisc In preparation of destroying line discipline on hangup, fix ldisc core operations to properly handle when the tty's ldisc is NULL. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index d6805e1aee59..982af70c95ce 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -269,7 +269,8 @@ const struct file_operations tty_ldiscs_proc_fops = { struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) { ldsem_down_read(&tty->ldisc_sem, MAX_SCHEDULE_TIMEOUT); - WARN_ON(!tty->ldisc); + if (!tty->ldisc) + ldsem_up_read(&tty->ldisc_sem); return tty->ldisc; } EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); @@ -460,7 +461,7 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) if (ret) clear_bit(TTY_LDISC_OPEN, &tty->flags); - tty_ldisc_debug(tty, "%p: opened\n", tty->ldisc); + tty_ldisc_debug(tty, "%p: opened\n", ld); return ret; } return 0; @@ -481,7 +482,7 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) clear_bit(TTY_LDISC_OPEN, &tty->flags); if (ld->ops->close) ld->ops->close(tty); - tty_ldisc_debug(tty, "%p: closed\n", tty->ldisc); + tty_ldisc_debug(tty, "%p: closed\n", ld); } /** @@ -544,6 +545,11 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (retval) goto err; + if (!tty->ldisc) { + retval = -EIO; + goto out; + } + /* Check the no-op case */ if (tty->ldisc->ops->num == ldisc) goto out; @@ -659,7 +665,7 @@ void tty_ldisc_hangup(struct tty_struct *tty) int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS; int err = 0; - tty_ldisc_debug(tty, "%p: closing\n", tty->ldisc); + tty_ldisc_debug(tty, "%p: hangup\n", tty->ldisc); ld = tty_ldisc_ref(tty); if (ld != NULL) { @@ -743,6 +749,8 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) static void tty_ldisc_kill(struct tty_struct *tty) { + if (!tty->ldisc) + return; /* * Now kill off the ldisc */ -- cgit v1.2.3 From 6ffeb4b2782b31f3d7158795a451ad371955e8a2 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:03 -0800 Subject: tty: Move tty_ldisc_kill() In preparation for destroying the line discipline instance on hangup, move tty_ldisc_kill() to eliminate needless forward declarations. No functional change. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 982af70c95ce..eac33e104ccc 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -600,6 +600,25 @@ err: return retval; } +/** + * tty_ldisc_kill - teardown ldisc + * @tty: tty being released + * + * Perform final close of the ldisc and reset tty->ldisc + */ +static void tty_ldisc_kill(struct tty_struct *tty) +{ + if (!tty->ldisc) + return; + /* + * Now kill off the ldisc + */ + tty_ldisc_close(tty, tty->ldisc); + tty_ldisc_put(tty->ldisc); + /* Force an oops if we mess this up */ + tty->ldisc = NULL; +} + /** * tty_reset_termios - reset terminal state * @tty: tty to reset @@ -747,19 +766,6 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) return 0; } -static void tty_ldisc_kill(struct tty_struct *tty) -{ - if (!tty->ldisc) - return; - /* - * Now kill off the ldisc - */ - tty_ldisc_close(tty, tty->ldisc); - tty_ldisc_put(tty->ldisc); - /* Force an oops if we mess this up */ - tty->ldisc = NULL; -} - /** * tty_ldisc_release - release line discipline * @tty: tty being shut down (or one end of pty pair) -- cgit v1.2.3 From c12da96f801a3f45b0634c966b9e7cda307daa72 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:04 -0800 Subject: tty: Use 'disc' for line discipline index name tty->ldisc is a ptr to struct tty_ldisc, but unfortunately 'ldisc' is also used as a parameter or local name to refer to the line discipline index value (ie, N_TTY, N_GSM, etc.); instead prefer the name used by the line discipline registration/ref counting functions. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 6 +++--- drivers/tty/tty_ldisc.c | 22 +++++++++++----------- include/linux/tty.h | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index eb26754b2e5d..7f556e3c1515 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2662,13 +2662,13 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _ static int tiocsetd(struct tty_struct *tty, int __user *p) { - int ldisc; + int disc; int ret; - if (get_user(ldisc, p)) + if (get_user(disc, p)) return -EFAULT; - ret = tty_set_ldisc(tty, ldisc); + ret = tty_set_ldisc(tty, disc); return ret; } diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index eac33e104ccc..45aa31b923e5 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -417,7 +417,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); /** * tty_set_termios_ldisc - set ldisc field * @tty: tty structure - * @num: line discipline number + * @disc: line discipline number * * This is probably overkill for real world processors but * they are not on hot paths so a little discipline won't do @@ -430,10 +430,10 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); * Locking: takes termios_rwsem */ -static void tty_set_termios_ldisc(struct tty_struct *tty, int num) +static void tty_set_termios_ldisc(struct tty_struct *tty, int disc) { down_write(&tty->termios_rwsem); - tty->termios.c_line = num; + tty->termios.c_line = disc; up_write(&tty->termios_rwsem); tty->disc_data = NULL; @@ -531,12 +531,12 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) * the close of one side of a tty/pty pair, and eventually hangup. */ -int tty_set_ldisc(struct tty_struct *tty, int ldisc) +int tty_set_ldisc(struct tty_struct *tty, int disc) { int retval; struct tty_ldisc *old_ldisc, *new_ldisc; - new_ldisc = tty_ldisc_get(tty, ldisc); + new_ldisc = tty_ldisc_get(tty, disc); if (IS_ERR(new_ldisc)) return PTR_ERR(new_ldisc); @@ -551,7 +551,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) } /* Check the no-op case */ - if (tty->ldisc->ops->num == ldisc) + if (tty->ldisc->ops->num == disc) goto out; if (test_bit(TTY_HUPPED, &tty->flags)) { @@ -567,7 +567,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) /* Now set up the new line discipline. */ tty->ldisc = new_ldisc; - tty_set_termios_ldisc(tty, ldisc); + tty_set_termios_ldisc(tty, disc); retval = tty_ldisc_open(tty, new_ldisc); if (retval < 0) { @@ -639,15 +639,15 @@ static void tty_reset_termios(struct tty_struct *tty) /** * tty_ldisc_reinit - reinitialise the tty ldisc * @tty: tty to reinit - * @ldisc: line discipline to reinitialize + * @disc: line discipline to reinitialize * * Switch the tty to a line discipline and leave the ldisc * state closed */ -static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) +static int tty_ldisc_reinit(struct tty_struct *tty, int disc) { - struct tty_ldisc *ld = tty_ldisc_get(tty, ldisc); + struct tty_ldisc *ld = tty_ldisc_get(tty, disc); if (IS_ERR(ld)) return -1; @@ -658,7 +658,7 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) * Switch the line discipline back */ tty->ldisc = ld; - tty_set_termios_ldisc(tty, ldisc); + tty_set_termios_ldisc(tty, disc); return 0; } diff --git a/include/linux/tty.h b/include/linux/tty.h index 83f127673bc9..e3b0afbde7b9 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -570,7 +570,7 @@ static inline int tty_port_users(struct tty_port *port) extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc); extern int tty_unregister_ldisc(int disc); -extern int tty_set_ldisc(struct tty_struct *tty, int ldisc); +extern int tty_set_ldisc(struct tty_struct *tty, int disc); extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty); extern void tty_ldisc_release(struct tty_struct *tty); extern void tty_ldisc_init(struct tty_struct *tty); -- cgit v1.2.3 From 7896f30d6fc602f02198999acca4840620288990 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:05 -0800 Subject: tty: Refactor tty_ldisc_reinit() for reuse At tty hangup, the line discipline instance is reinitialized by closing the current ldisc instance and opening a new instance. This operation is complicated by error recovery: if the attempt to reinit the current line discipline fails, the line discipline is reset to N_TTY (which should not but can fail). Re-purpose tty_ldisc_reinit() to return a valid, open line discipline instance, or otherwise, an error. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 53 +++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 45aa31b923e5..e18c8e864110 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -641,26 +641,41 @@ static void tty_reset_termios(struct tty_struct *tty) * @tty: tty to reinit * @disc: line discipline to reinitialize * - * Switch the tty to a line discipline and leave the ldisc - * state closed + * Completely reinitialize the line discipline state, by closing the + * current instance and opening a new instance. If an error occurs opening + * the new non-N_TTY instance, the instance is dropped and tty->ldisc reset + * to NULL. The caller can then retry with N_TTY instead. + * + * Returns 0 if successful, otherwise error code < 0 */ static int tty_ldisc_reinit(struct tty_struct *tty, int disc) { - struct tty_ldisc *ld = tty_ldisc_get(tty, disc); + struct tty_ldisc *ld; + int retval; - if (IS_ERR(ld)) - return -1; + ld = tty_ldisc_get(tty, disc); + if (IS_ERR(ld)) { + BUG_ON(disc == N_TTY); + return PTR_ERR(ld); + } - tty_ldisc_close(tty, tty->ldisc); - tty_ldisc_put(tty->ldisc); - /* - * Switch the line discipline back - */ + if (tty->ldisc) { + tty_ldisc_close(tty, tty->ldisc); + tty_ldisc_put(tty->ldisc); + } + + /* switch the line discipline */ tty->ldisc = ld; tty_set_termios_ldisc(tty, disc); - - return 0; + retval = tty_ldisc_open(tty, tty->ldisc); + if (retval) { + if (!WARN_ON(disc == N_TTY)) { + tty_ldisc_put(tty->ldisc); + tty->ldisc = NULL; + } + } + return retval; } /** @@ -716,19 +731,13 @@ void tty_ldisc_hangup(struct tty_struct *tty) reopen a new ldisc. We could defer the reopen to the next open but it means auditing a lot of other paths so this is a FIXME */ - if (reset == 0) { + if (reset == 0) + err = tty_ldisc_reinit(tty, tty->termios.c_line); - if (!tty_ldisc_reinit(tty, tty->termios.c_line)) - err = tty_ldisc_open(tty, tty->ldisc); - else - err = 1; - } /* If the re-open fails or we reset then go to N_TTY. The N_TTY open cannot fail */ - if (reset || err) { - BUG_ON(tty_ldisc_reinit(tty, N_TTY)); - WARN_ON(tty_ldisc_open(tty, tty->ldisc)); - } + if (reset || err < 0) + tty_ldisc_reinit(tty, N_TTY); } tty_ldisc_unlock(tty); if (reset) -- cgit v1.2.3 From 892d1fa7eaaed9d3c04954cb140c34ebc3393932 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:06 -0800 Subject: tty: Destroy ldisc instance on hangup Currently, when the tty is hungup, the ldisc is re-instanced; ie., the current instance is destroyed and a new instance is created. The purpose of this design was to guarantee a valid, open ldisc for the lifetime of the tty. However, now that tty buffers are owned by and have lifetime equivalent to the tty_port (since v3.10), any data received immediately after the ldisc is re-instanced may cause continued driver i/o operations concurrently with the driver's hangup() operation. For drivers that shutdown h/w on hangup, this is unexpected and usually bad. For example, the serial core may free the xmit buffer page concurrently with an in-progress write() operation (triggered by echo). With the existing stable and robust ldisc reference handling, the cleaned-up tty_reopen(), the straggling unsafe ldisc use cleaned up, and the preparation to properly handle a NULL tty->ldisc, the ldisc instance can be destroyed and only re-instanced when the tty is re-opened. If the tty was opened as /dev/console or /dev/tty0, the original behavior of re-instancing the ldisc is retained (the 'reinit' parameter to tty_ldisc_hangup() is true). This is required since those file descriptors are never hungup. This patch has neglible impact on userspace; the tty file_operations ptr is changed to point to the hungup file operations _before_ the ldisc instance is destroyed, so only racing file operations might now retrieve a NULL ldisc reference (which is simply handled as if the hungup file operation had been called instead -- see "tty: Prepare for destroying line discipline on hangup"). This resolves a long-standing FIXME and several crash reports. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 12 ++++++------ drivers/tty/tty_ldisc.c | 40 +++++++++++++++++----------------------- include/linux/tty.h | 3 ++- 3 files changed, 25 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 7f556e3c1515..d3ecbb513fa1 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -727,7 +727,7 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) while (refs--) tty_kref_put(tty); - tty_ldisc_hangup(tty); + tty_ldisc_hangup(tty, cons_filp != NULL); spin_lock_irq(&tty->ctrl_lock); clear_bit(TTY_THROTTLED, &tty->flags); @@ -752,10 +752,9 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) } else if (tty->ops->hangup) tty->ops->hangup(tty); /* - * We don't want to have driver/ldisc interactions beyond - * the ones we did here. The driver layer expects no - * calls after ->hangup() from the ldisc side. However we - * can't yet guarantee all that. + * We don't want to have driver/ldisc interactions beyond the ones + * we did here. The driver layer expects no calls after ->hangup() + * from the ldisc side, which is now guaranteed. */ set_bit(TTY_HUPPED, &tty->flags); tty_unlock(tty); @@ -1475,7 +1474,8 @@ static int tty_reopen(struct tty_struct *tty) tty->count++; - WARN_ON(!tty->ldisc); + if (!tty->ldisc) + return tty_ldisc_reinit(tty, tty->termios.c_line); return 0; } diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index e18c8e864110..c6f970d63060 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -257,6 +257,9 @@ const struct file_operations tty_ldiscs_proc_fops = { * reference to it. If the line discipline is in flux then * wait patiently until it changes. * + * Returns: NULL if the tty has been hungup and not re-opened with + * a new file descriptor, otherwise valid ldisc reference + * * Note: Must not be called from an IRQ/timer context. The caller * must also be careful not to hold other locks that will deadlock * against a discipline change, such as an existing ldisc reference @@ -642,14 +645,15 @@ static void tty_reset_termios(struct tty_struct *tty) * @disc: line discipline to reinitialize * * Completely reinitialize the line discipline state, by closing the - * current instance and opening a new instance. If an error occurs opening - * the new non-N_TTY instance, the instance is dropped and tty->ldisc reset - * to NULL. The caller can then retry with N_TTY instead. + * current instance, if there is one, and opening a new instance. If + * an error occurs opening the new non-N_TTY instance, the instance + * is dropped and tty->ldisc reset to NULL. The caller can then retry + * with N_TTY instead. * * Returns 0 if successful, otherwise error code < 0 */ -static int tty_ldisc_reinit(struct tty_struct *tty, int disc) +int tty_ldisc_reinit(struct tty_struct *tty, int disc) { struct tty_ldisc *ld; int retval; @@ -693,11 +697,9 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int disc) * tty itself so we must be careful about locking rules. */ -void tty_ldisc_hangup(struct tty_struct *tty) +void tty_ldisc_hangup(struct tty_struct *tty, bool reinit) { struct tty_ldisc *ld; - int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS; - int err = 0; tty_ldisc_debug(tty, "%p: hangup\n", tty->ldisc); @@ -725,25 +727,17 @@ void tty_ldisc_hangup(struct tty_struct *tty) */ tty_ldisc_lock(tty, MAX_SCHEDULE_TIMEOUT); - if (tty->ldisc) { + if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) + tty_reset_termios(tty); - /* At this point we have a halted ldisc; we want to close it and - reopen a new ldisc. We could defer the reopen to the next - open but it means auditing a lot of other paths so this is - a FIXME */ - if (reset == 0) - err = tty_ldisc_reinit(tty, tty->termios.c_line); - - /* If the re-open fails or we reset then go to N_TTY. The - N_TTY open cannot fail */ - if (reset || err < 0) - tty_ldisc_reinit(tty, N_TTY); + if (tty->ldisc) { + if (reinit) { + if (tty_ldisc_reinit(tty, tty->termios.c_line) < 0) + tty_ldisc_reinit(tty, N_TTY); + } else + tty_ldisc_kill(tty); } tty_ldisc_unlock(tty); - if (reset) - tty_reset_termios(tty); - - tty_ldisc_debug(tty, "%p: re-opened\n", tty->ldisc); } /** diff --git a/include/linux/tty.h b/include/linux/tty.h index e3b0afbde7b9..95e52c6b9696 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -490,7 +490,8 @@ extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt); extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *); extern void tty_ldisc_deref(struct tty_ldisc *); extern struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *); -extern void tty_ldisc_hangup(struct tty_struct *tty); +extern void tty_ldisc_hangup(struct tty_struct *tty, bool reset); +extern int tty_ldisc_reinit(struct tty_struct *tty, int disc); extern const struct file_operations tty_ldiscs_proc_fops; extern void tty_wakeup(struct tty_struct *tty); -- cgit v1.2.3 From 133b1306f2068b124a4a00f537896a16786cc544 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:07 -0800 Subject: tty: Document c_line == N_TTY initial condition The line discipline id is stored in the tty's termios; document the implicit initial value of N_TTY. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index d3ecbb513fa1..3c90ad44b585 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -123,7 +123,8 @@ struct ktermios tty_std_termios = { /* for the benefit of tty drivers */ ECHOCTL | ECHOKE | IEXTEN, .c_cc = INIT_C_CC, .c_ispeed = 38400, - .c_ospeed = 38400 + .c_ospeed = 38400, + /* .c_line = N_TTY, */ }; EXPORT_SYMBOL(tty_std_termios); -- cgit v1.2.3 From 9de2a7cef983579c725564950384e4ea205a7684 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:08 -0800 Subject: tty: Avoid unnecessary temporaries for tty->ldisc tty_ldisc_setup() is race-free and can reference tty->ldisc without snapshots. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index c6f970d63060..4cb5e572c7b8 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -752,17 +752,14 @@ void tty_ldisc_hangup(struct tty_struct *tty, bool reinit) int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) { - struct tty_ldisc *ld = tty->ldisc; - int retval; - - retval = tty_ldisc_open(tty, ld); + int retval = tty_ldisc_open(tty, tty->ldisc); if (retval) return retval; if (o_tty) { retval = tty_ldisc_open(o_tty, o_tty->ldisc); if (retval) { - tty_ldisc_close(tty, ld); + tty_ldisc_close(tty, tty->ldisc); return retval; } } -- cgit v1.2.3 From d1d027eff5693c3cea71e4ce2f1c3a707baec02d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:35:18 -0800 Subject: tty: Unexport system-wide tty_mutex tty_mutex is a core, system-wide lock; there is no reason for any code outside the tty core to have direct access. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 3c90ad44b585..cb0a0c82279b 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -135,10 +135,8 @@ EXPORT_SYMBOL(tty_std_termios); LIST_HEAD(tty_drivers); /* linked list of tty drivers */ -/* Mutex to protect creating and releasing a tty. This is shared with - vt.c for deeply disgusting hack reasons */ +/* Mutex to protect creating and releasing a tty */ DEFINE_MUTEX(tty_mutex); -EXPORT_SYMBOL(tty_mutex); /* Spinlock to protect the tty->tty_files list */ DEFINE_SPINLOCK(tty_files_lock); -- cgit v1.2.3 From 27228732aa94f3883433fab2f43eee373c638f2f Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:35:19 -0800 Subject: tty: Eliminate global symbol tty_ldisc_N_TTY Reduce global tty symbols; move and rename tty_ldisc_begin() as n_tty_init() and redefine the N_TTY ldisc ops as file scope. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 12 ++++++++---- drivers/tty/tty_io.c | 2 +- drivers/tty/tty_ldisc.c | 6 ------ include/linux/tty.h | 3 +-- 4 files changed, 10 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 90eca2605fbf..dae628f19912 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2497,7 +2497,7 @@ static void n_tty_fasync(struct tty_struct *tty, int on) } } -struct tty_ldisc_ops tty_ldisc_N_TTY = { +static struct tty_ldisc_ops n_tty_ops = { .magic = TTY_LDISC_MAGIC, .name = "n_tty", .open = n_tty_open, @@ -2518,14 +2518,18 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = { * n_tty_inherit_ops - inherit N_TTY methods * @ops: struct tty_ldisc_ops where to save N_TTY methods * - * Enables a 'subclass' line discipline to 'inherit' N_TTY - * methods. + * Enables a 'subclass' line discipline to 'inherit' N_TTY methods. */ void n_tty_inherit_ops(struct tty_ldisc_ops *ops) { - *ops = tty_ldisc_N_TTY; + *ops = n_tty_ops; ops->owner = NULL; ops->refcount = ops->flags = 0; } EXPORT_SYMBOL_GPL(n_tty_inherit_ops); + +void __init n_tty_init(void) +{ + tty_register_ldisc(N_TTY, &n_tty_ops); +} diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index cb0a0c82279b..798acb690092 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3576,7 +3576,7 @@ void __init console_init(void) initcall_t *call; /* Setup the default TTY line discipline. */ - tty_ldisc_begin(); + n_tty_init(); /* * set up the console device so that later boot sequences can diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 4cb5e572c7b8..68947f6de5ad 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -824,9 +824,3 @@ void tty_ldisc_deinit(struct tty_struct *tty) tty_ldisc_put(tty->ldisc); tty->ldisc = NULL; } - -void tty_ldisc_begin(void) -{ - /* Setup the default TTY line discipline. */ - (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY); -} diff --git a/include/linux/tty.h b/include/linux/tty.h index 95e52c6b9696..f6c07fd12ef4 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -576,7 +576,6 @@ extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty); extern void tty_ldisc_release(struct tty_struct *tty); extern void tty_ldisc_init(struct tty_struct *tty); extern void tty_ldisc_deinit(struct tty_struct *tty); -extern void tty_ldisc_begin(void); static inline int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p, char *f, int count) @@ -593,8 +592,8 @@ static inline int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p, /* n_tty.c */ -extern struct tty_ldisc_ops tty_ldisc_N_TTY; extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops); +extern void __init n_tty_init(void); /* tty_audit.c */ #ifdef CONFIG_AUDIT -- cgit v1.2.3 From e802ca0e1892865acdde90f1aaed37333c5660c2 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:35:21 -0800 Subject: tty: Move tty_check_change() helper Move is_ignored() to drivers/tty/tty_io.c and re-declare in file scope. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 6 ------ drivers/tty/tty_io.c | 6 ++++++ include/linux/tty.h | 1 - 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index dae628f19912..f4555a261420 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1763,12 +1763,6 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, return n_tty_receive_buf_common(tty, cp, fp, count, 1); } -int is_ignored(int sig) -{ - return (sigismember(¤t->blocked, sig) || - current->sighand->action[sig-1].sa.sa_handler == SIG_IGN); -} - /** * n_tty_set_termios - termios data changed * @tty: terminal diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 798acb690092..e8996fc3ff1c 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -381,6 +381,12 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) EXPORT_SYMBOL_GPL(tty_find_polling_driver); #endif +static int is_ignored(int sig) +{ + return (sigismember(¤t->blocked, sig) || + current->sighand->action[sig-1].sa.sa_handler == SIG_IGN); +} + /** * tty_check_change - check for POSIX terminal changes * @tty: tty to check diff --git a/include/linux/tty.h b/include/linux/tty.h index 26a9b4b3efe9..ba7120dccccb 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -445,7 +445,6 @@ extern int tty_throttle_safe(struct tty_struct *tty); extern int tty_unthrottle_safe(struct tty_struct *tty); extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws); extern int is_current_pgrp_orphaned(void); -extern int is_ignored(int sig); extern void tty_hangup(struct tty_struct *tty); extern void tty_vhangup(struct tty_struct *tty); extern int tty_hung_up_p(struct file *filp); -- cgit v1.2.3 From 4a510969374ab8853451c337e43d28fb864e43fd Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:35:23 -0800 Subject: tty: Make tty_files_lock per-tty Access to tty->tty_files list is always per-tty, never for all ttys simultaneously. Replace global tty_files_lock spinlock with per-tty ->files_lock. Initialize when the ->tty_files list is inited, in alloc_tty_struct(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 25 ++++++++++++------------- include/linux/tty.h | 2 +- security/selinux/hooks.c | 4 ++-- 3 files changed, 15 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index e8996fc3ff1c..c5b4274584dc 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -138,9 +138,6 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */ /* Mutex to protect creating and releasing a tty */ DEFINE_MUTEX(tty_mutex); -/* Spinlock to protect the tty->tty_files list */ -DEFINE_SPINLOCK(tty_files_lock); - static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); ssize_t redirected_tty_write(struct file *, const char __user *, @@ -202,9 +199,9 @@ void tty_add_file(struct tty_struct *tty, struct file *file) priv->tty = tty; priv->file = file; - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); list_add(&priv->list, &tty->tty_files); - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); } /** @@ -225,10 +222,11 @@ void tty_free_file(struct file *file) static void tty_del_file(struct file *file) { struct tty_file_private *priv = file->private_data; + struct tty_struct *tty = priv->tty; - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); list_del(&priv->list); - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); tty_free_file(file); } @@ -286,11 +284,11 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) struct list_head *p; int count = 0; - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); list_for_each(p, &tty->tty_files) { count++; } - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); if (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_SLAVE && tty->link && tty->link->count) @@ -713,7 +711,7 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) workqueue with the lock held */ check_tty_count(tty, "tty_hangup"); - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); /* This breaks for file handles being sent over AF_UNIX sockets ? */ list_for_each_entry(priv, &tty->tty_files, list) { filp = priv->file; @@ -725,7 +723,7 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) __tty_fasync(-1, filp, 0); /* can't block */ filp->f_op = &hung_up_tty_fops; } - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); refs = tty_signal_session_leader(tty, exit_session); /* Account for the p->signal references we killed */ @@ -1637,9 +1635,9 @@ static void release_one_tty(struct work_struct *work) tty_driver_kref_put(driver); module_put(owner); - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); list_del_init(&tty->tty_files); - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); put_pid(tty->pgrp); put_pid(tty->session); @@ -3176,6 +3174,7 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx) mutex_init(&tty->atomic_write_lock); spin_lock_init(&tty->ctrl_lock); spin_lock_init(&tty->flow_lock); + spin_lock_init(&tty->files_lock); INIT_LIST_HEAD(&tty->tty_files); INIT_WORK(&tty->SAK_work, do_SAK_work); diff --git a/include/linux/tty.h b/include/linux/tty.h index da16b5980c25..780adbfc6dce 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -302,6 +302,7 @@ struct tty_struct { struct work_struct hangup_work; void *disc_data; void *driver_data; + spinlock_t files_lock; /* protects tty_files list */ struct list_head tty_files; #define N_TTY_BUF_SIZE 4096 @@ -508,7 +509,6 @@ extern int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty); extern struct mutex tty_mutex; -extern spinlock_t tty_files_lock; #define tty_is_writelocked(tty) (mutex_is_locked(&tty->atomic_write_lock)) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index f8110cfd80ff..8010bc5391c3 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2415,7 +2415,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, tty = get_current_tty(); if (tty) { - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); if (!list_empty(&tty->tty_files)) { struct tty_file_private *file_priv; @@ -2430,7 +2430,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE)) drop_tty = 1; } - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); tty_kref_put(tty); } /* Reset controlling tty. */ -- cgit v1.2.3 From a6ed4a18ba6a6f5a01e024b9d221d6439bf6ca4c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 27 Jan 2016 15:42:25 -0800 Subject: Input: xpad - remove unused function There are two definitions of xpad_identify_controller(), one is used when CONFIG_JOYSTICK_XPAD_LEDS is set, but the other one is empty and never used, and we get a gcc warning about it: drivers/input/joystick/xpad.c:1210:13: warning: 'xpad_identify_controller' defined but not used [-Wunused-function] This removes the second definition. Signed-off-by: Arnd Bergmann Fixes: cae705baa40b ("Input: xpad - re-send LED command on present event") Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 6727954ab74b..e8a84d12b7ff 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -1207,7 +1207,6 @@ static void xpad_led_disconnect(struct usb_xpad *xpad) #else static int xpad_led_probe(struct usb_xpad *xpad) { return 0; } static void xpad_led_disconnect(struct usb_xpad *xpad) { } -static void xpad_identify_controller(struct usb_xpad *xpad) { } #endif static int xpad_start_input(struct usb_xpad *xpad) -- cgit v1.2.3 From af6e94634d0a77aa42a9fdee35abd00a95b4ca54 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 27 Jan 2016 15:43:32 -0800 Subject: Input: sirfsoc-onkey - allow modular build CONFIG_INPUT may itself be a loadable module, but the sirf power key driver is listed as 'bool', which makes it possible to select a broken configuration with the driver built-in but the subsystem not loaded. In this configuration, we get a link error: drivers/input/built-in.o: In function `sirfsoc_pwrc_isr': drivers/input/misc/sirfsoc-onkey.c:63: undefined reference to `input_event' drivers/input/built-in.o: In function `sirfsoc_pwrc_isr': include/linux/input.h:414: undefined reference to `input_event' drivers/input/built-in.o: In function `sirfsoc_pwrc_probe': drivers/input/misc/sirfsoc-onkey.c:132: undefined reference to `devm_input_allocate_device' drivers/input/misc/sirfsoc-onkey.c:139: undefined reference to `input_set_capability' drivers/input/misc/sirfsoc-onkey.c:161: undefined reference to `input_register_device' drivers/input/built-in.o: In function `sirfsoc_pwrc_report_event': drivers/input/misc/sirfsoc-onkey.c:48: undefined reference to `input_event' drivers/input/built-in.o: In function `sirfsoc_pwrc_report_event': include/linux/input.h:414: undefined reference to `input_event' drivers/input/built-in.o:(.debug_addr+0x24): undefined reference to `input_event' drivers/input/built-in.o:(.debug_addr+0xbc): undefined reference to `devm_input_allocate_device' drivers/input/built-in.o:(.debug_addr+0x104): undefined reference to `input_set_capability' drivers/input/built-in.o:(.debug_addr+0x128): undefined reference to `input_register_device' This marks the driver as 'tristate' so it becomes possible to have it in a loadable module, mainly to help with randconfig builds. We also have to add a missing semicolon here, which ended up not being needed in built-in mode because the following MODULE_DEVICE_TABLE is an empty macro followed by another semicolon then. Signed-off-by: Arnd Bergmann Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 2 +- drivers/input/misc/sirfsoc-onkey.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index d6d16fa78281..1f2337abcf2f 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -733,7 +733,7 @@ config INPUT_XEN_KBDDEV_FRONTEND module will be called xen-kbdfront. config INPUT_SIRFSOC_ONKEY - bool "CSR SiRFSoC power on/off/suspend key support" + tristate "CSR SiRFSoC power on/off/suspend key support" depends on ARCH_SIRF && OF default y help diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c index 9d5b89befe6f..ed7237f19539 100644 --- a/drivers/input/misc/sirfsoc-onkey.c +++ b/drivers/input/misc/sirfsoc-onkey.c @@ -101,7 +101,7 @@ static void sirfsoc_pwrc_close(struct input_dev *input) static const struct of_device_id sirfsoc_pwrc_of_match[] = { { .compatible = "sirf,prima2-pwrc" }, {}, -} +}; MODULE_DEVICE_TABLE(of, sirfsoc_pwrc_of_match); static int sirfsoc_pwrc_probe(struct platform_device *pdev) -- cgit v1.2.3 From 497e1b3f6b6d3cf2206d15687eb7bfa0ab0e968d Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Wed, 27 Jan 2016 15:44:09 -0800 Subject: Input: cap11xx - add missing of_node_put for_each_child_of_node performs an of_node_get on each iteration, so to break out of the loop an of_node_put is required. Found using Coccinelle. Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/cap11xx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c index 378db10001df..4401be225d64 100644 --- a/drivers/input/keyboard/cap11xx.c +++ b/drivers/input/keyboard/cap11xx.c @@ -304,8 +304,10 @@ static int cap11xx_init_leds(struct device *dev, led->cdev.brightness = LED_OFF; error = of_property_read_u32(child, "reg", ®); - if (error != 0 || reg >= num_leds) + if (error != 0 || reg >= num_leds) { + of_node_put(child); return -EINVAL; + } led->reg = reg; led->priv = priv; @@ -313,8 +315,10 @@ static int cap11xx_init_leds(struct device *dev, INIT_WORK(&led->work, cap11xx_led_work); error = devm_led_classdev_register(dev, &led->cdev); - if (error) + if (error) { + of_node_put(child); return error; + } priv->num_leds++; led++; -- cgit v1.2.3 From 015bb5e134544492d840cee17d7442194cfb0fe4 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Sat, 16 Jan 2016 10:35:47 -0800 Subject: Input: serio - drop warnings in case of EPROBE_DEFER from serio_find_driver() Now serio_find_driver() will print warnings in case device_attach() returns -EPROBE_DEFER. Those warnings are obsolete, in genral, because: - DD core can report the same if required - since commit 013c074f8642 ("PM / sleep: prohibit devices probing during suspend/hibernation") the devices probing is prohibited during System suspend and deferred device will be carefully reprobed once Resume is finished. Hence, drop warnings in case of EPROBE_DEFER from serio_find_driver(). Signed-off-by: Grygorii Strashko Acked-by: Rafael J. Wysocki Signed-off-by: Dmitry Torokhov --- drivers/input/serio/serio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 8f828975ab10..1ca7f551e2da 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -134,7 +134,7 @@ static void serio_find_driver(struct serio *serio) int error; error = device_attach(&serio->dev); - if (error < 0) + if (error < 0 && error != -EPROBE_DEFER) dev_warn(&serio->dev, "device_attach() failed for %s (%s), error: %d\n", serio->phys, serio->name, error); -- cgit v1.2.3 From d4f1b06d685d11ebdaccf11c0db1cb3c78736862 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 16 Jan 2016 10:04:49 -0800 Subject: Input: vmmouse - fix absolute device registration We should set device's capabilities first, and then register it, otherwise various handlers already present in the kernel will not be able to connect to the device. Reported-by: Lauri Kasanen Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/vmmouse.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c index e272f06258ce..a3f0f5a47490 100644 --- a/drivers/input/mouse/vmmouse.c +++ b/drivers/input/mouse/vmmouse.c @@ -458,8 +458,6 @@ int vmmouse_init(struct psmouse *psmouse) priv->abs_dev = abs_dev; psmouse->private = priv; - input_set_capability(rel_dev, EV_REL, REL_WHEEL); - /* Set up and register absolute device */ snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); @@ -475,10 +473,6 @@ int vmmouse_init(struct psmouse *psmouse) abs_dev->id.version = psmouse->model; abs_dev->dev.parent = &psmouse->ps2dev.serio->dev; - error = input_register_device(priv->abs_dev); - if (error) - goto init_fail; - /* Set absolute device capabilities */ input_set_capability(abs_dev, EV_KEY, BTN_LEFT); input_set_capability(abs_dev, EV_KEY, BTN_RIGHT); @@ -488,6 +482,13 @@ int vmmouse_init(struct psmouse *psmouse) input_set_abs_params(abs_dev, ABS_X, 0, VMMOUSE_MAX_X, 0, 0); input_set_abs_params(abs_dev, ABS_Y, 0, VMMOUSE_MAX_Y, 0, 0); + error = input_register_device(priv->abs_dev); + if (error) + goto init_fail; + + /* Add wheel capability to the relative device */ + input_set_capability(rel_dev, EV_REL, REL_WHEEL); + psmouse->protocol_handler = vmmouse_process_byte; psmouse->disconnect = vmmouse_disconnect; psmouse->reconnect = vmmouse_reconnect; -- cgit v1.2.3 From d7c0ba40ebb32510e2c5d80a392474320cab8a2d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:25 -0800 Subject: tty: audit: Early-out pty master reads earlier Reads from pty masters are not logged; early-out before taking locks. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 3d245cd3d8e6..ead924e4bd53 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -276,16 +276,16 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, if (unlikely(size == 0)) return; + if (tty->driver->type == TTY_DRIVER_TYPE_PTY + && tty->driver->subtype == PTY_TYPE_MASTER) + return; + spin_lock_irqsave(¤t->sighand->siglock, flags); audit_log_tty_passwd = current->signal->audit_tty_log_passwd; spin_unlock_irqrestore(¤t->sighand->siglock, flags); if (!audit_log_tty_passwd && icanon && !L_ECHO(tty)) return; - if (tty->driver->type == TTY_DRIVER_TYPE_PTY - && tty->driver->subtype == PTY_TYPE_MASTER) - return; - buf = tty_audit_buf_get(tty, icanon); if (!buf) return; -- cgit v1.2.3 From eab25a5cd1f91b5c7991affe95f24ce188b8021f Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:26 -0800 Subject: tty: audit: Never audit packet mode tty audit never logs pty master reads, but packet mode only works for pty masters, so tty_audit_add_data() was never logging packet mode anyway. Don't audit packet mode data. As those are the lone call sites, remove tty_put_user(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index f4555a261420..bacafda44bf3 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -153,15 +153,6 @@ static inline unsigned char *echo_buf_addr(struct n_tty_data *ldata, size_t i) return &ldata->echo_buf[i & (N_TTY_BUF_SIZE - 1)]; } -static inline int tty_put_user(struct tty_struct *tty, unsigned char x, - unsigned char __user *ptr) -{ - struct n_tty_data *ldata = tty->disc_data; - - tty_audit_add_data(tty, &x, 1, ldata->icanon); - return put_user(x, ptr); -} - static int tty_copy_to_user(struct tty_struct *tty, void __user *to, size_t tail, size_t n) { @@ -2197,11 +2188,11 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, cs = tty->link->ctrl_status; tty->link->ctrl_status = 0; spin_unlock_irq(&tty->link->ctrl_lock); - if (tty_put_user(tty, cs, b++)) { + if (put_user(cs, b)) { retval = -EFAULT; - b--; break; } + b++; nr--; break; } @@ -2247,11 +2238,11 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, /* Deal with packet mode. */ if (packet && b == buf) { - if (tty_put_user(tty, TIOCPKT_DATA, b++)) { + if (put_user(TIOCPKT_DATA, b)) { retval = -EFAULT; - b--; break; } + b++; nr--; } -- cgit v1.2.3 From 309426ae69cdf35b0d72a8bd59a5081f8ddccddd Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:27 -0800 Subject: tty: audit: Remove icanon mode from call chain The tty termios bits cannot change while n_tty_read() is in the i/o loop; the termios_rwsem ensures mutual exclusion with termios changes in n_tty_set_termios(). Check L_ICANON() directly and eliminate icanon parameter. NB: tty_audit_add_data() => tty_audit_buf_get() => tty_audit_buf_alloc() is a single path; ie., tty_audit_buf_get() and tty_audit_buf_alloc() have no other callers. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 6 +++--- drivers/tty/tty_audit.c | 22 +++++++++------------- include/linux/tty.h | 4 ++-- 3 files changed, 14 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index bacafda44bf3..4fbc5defbcd8 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -162,7 +162,7 @@ static int tty_copy_to_user(struct tty_struct *tty, void __user *to, int uncopied; if (n > size) { - tty_audit_add_data(tty, from, size, ldata->icanon); + tty_audit_add_data(tty, from, size); uncopied = copy_to_user(to, from, size); if (uncopied) return uncopied; @@ -171,7 +171,7 @@ static int tty_copy_to_user(struct tty_struct *tty, void __user *to, from = ldata->read_buf; } - tty_audit_add_data(tty, from, n, ldata->icanon); + tty_audit_add_data(tty, from, n); return copy_to_user(to, from, n); } @@ -1978,7 +1978,7 @@ static int copy_from_read_buf(struct tty_struct *tty, retval = copy_to_user(*b, from, n); n -= retval; is_eof = n == 1 && *from == EOF_CHAR(tty); - tty_audit_add_data(tty, from, n, ldata->icanon); + tty_audit_add_data(tty, from, n); smp_store_release(&ldata->read_tail, ldata->read_tail + n); /* Turn single EOF into zero-length read */ if (L_EXTPROC(tty) && ldata->icanon && is_eof && diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index ead924e4bd53..d2a004abeb5e 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -22,8 +22,7 @@ struct tty_audit_buf { unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */ }; -static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor, - unsigned icanon) +static struct tty_audit_buf *tty_audit_buf_alloc(struct tty_struct *tty) { struct tty_audit_buf *buf; @@ -35,9 +34,9 @@ static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor, goto err_buf; atomic_set(&buf->count, 1); mutex_init(&buf->mutex); - buf->major = major; - buf->minor = minor; - buf->icanon = icanon; + buf->major = tty->driver->major; + buf->minor = tty->driver->minor_start + tty->index; + buf->icanon = !!L_ICANON(tty); buf->valid = 0; return buf; @@ -216,8 +215,7 @@ int tty_audit_push_current(void) * if TTY auditing is disabled or out of memory. Otherwise, return a new * reference to the buffer. */ -static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, - unsigned icanon) +static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty) { struct tty_audit_buf *buf, *buf2; unsigned long flags; @@ -234,9 +232,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, } spin_unlock_irqrestore(¤t->sighand->siglock, flags); - buf2 = tty_audit_buf_alloc(tty->driver->major, - tty->driver->minor_start + tty->index, - icanon); + buf2 = tty_audit_buf_alloc(tty); if (buf2 == NULL) { audit_log_lost("out of memory in TTY auditing"); return NULL; @@ -265,13 +261,13 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, * * Audit @data of @size from @tty, if necessary. */ -void tty_audit_add_data(struct tty_struct *tty, const void *data, - size_t size, unsigned icanon) +void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) { struct tty_audit_buf *buf; int major, minor; int audit_log_tty_passwd; unsigned long flags; + unsigned int icanon = !!L_ICANON(tty); if (unlikely(size == 0)) return; @@ -286,7 +282,7 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, if (!audit_log_tty_passwd && icanon && !L_ECHO(tty)) return; - buf = tty_audit_buf_get(tty, icanon); + buf = tty_audit_buf_get(tty); if (!buf) return; diff --git a/include/linux/tty.h b/include/linux/tty.h index 780adbfc6dce..c011dc205e5c 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -593,7 +593,7 @@ extern void __init n_tty_init(void); /* tty_audit.c */ #ifdef CONFIG_AUDIT extern void tty_audit_add_data(struct tty_struct *tty, const void *data, - size_t size, unsigned icanon); + size_t size); extern void tty_audit_exit(void); extern void tty_audit_fork(struct signal_struct *sig); extern void tty_audit_tiocsti(struct tty_struct *tty, char ch); @@ -601,7 +601,7 @@ extern void tty_audit_push(struct tty_struct *tty); extern int tty_audit_push_current(void); #else static inline void tty_audit_add_data(struct tty_struct *tty, const void *data, - size_t size, unsigned icanon) + size_t size) { } static inline void tty_audit_tiocsti(struct tty_struct *tty, char ch) -- cgit v1.2.3 From a75c9b091226c0062a498d1cb65f9f6b858ebe55 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:28 -0800 Subject: tty: audit: Defer audit buffer association The tty audit buffer used to audit/record tty input is allocated on the process's first call to tty_audit_add_data(), and not freed until the process exits. On each call to tty_audit_add_data(), the current tty is compared (by major:minor) with the last tty associated with the audit buffer, and if the tty has changed the existing data is logged to the audit log. The audit buffer is then re-associated with the new tty. Currently, the audit buffer is immediately associated with the tty; however, the association must be re-checked when the buffer is locked prior to copying the tty input. This extra step is always necessary, since a concurrent read of a different tty by another thread of the process may have used the buffer in between allocation and buffer lock. Rather than associate the audit buffer with the tty at allocation, leave the buffer initially un-associated (null dev_t); simply let the re-association check also perform the initial association. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index d2a004abeb5e..9effa81acdfc 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -22,7 +22,7 @@ struct tty_audit_buf { unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */ }; -static struct tty_audit_buf *tty_audit_buf_alloc(struct tty_struct *tty) +static struct tty_audit_buf *tty_audit_buf_alloc(void) { struct tty_audit_buf *buf; @@ -34,9 +34,9 @@ static struct tty_audit_buf *tty_audit_buf_alloc(struct tty_struct *tty) goto err_buf; atomic_set(&buf->count, 1); mutex_init(&buf->mutex); - buf->major = tty->driver->major; - buf->minor = tty->driver->minor_start + tty->index; - buf->icanon = !!L_ICANON(tty); + buf->major = 0; + buf->minor = 0; + buf->icanon = 0; buf->valid = 0; return buf; @@ -211,11 +211,11 @@ int tty_audit_push_current(void) /** * tty_audit_buf_get - Get an audit buffer. * - * Get an audit buffer for @tty, allocate it if necessary. Return %NULL + * Get an audit buffer, allocate it if necessary. Return %NULL * if TTY auditing is disabled or out of memory. Otherwise, return a new * reference to the buffer. */ -static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty) +static struct tty_audit_buf *tty_audit_buf_get(void) { struct tty_audit_buf *buf, *buf2; unsigned long flags; @@ -232,7 +232,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty) } spin_unlock_irqrestore(¤t->sighand->siglock, flags); - buf2 = tty_audit_buf_alloc(tty); + buf2 = tty_audit_buf_alloc(); if (buf2 == NULL) { audit_log_lost("out of memory in TTY auditing"); return NULL; @@ -282,7 +282,7 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) if (!audit_log_tty_passwd && icanon && !L_ECHO(tty)) return; - buf = tty_audit_buf_get(tty); + buf = tty_audit_buf_get(); if (!buf) return; -- cgit v1.2.3 From f229c2c161de94a404fa16a17cb93c4a06938af5 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:29 -0800 Subject: tty: audit: Take siglock directly lock_task_sighand() is for situations where the struct task_struct* may disappear while trying to deref the sighand; this never applies to 'current'. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 9effa81acdfc..5f65653cee48 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -180,22 +180,19 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) int tty_audit_push_current(void) { struct tty_audit_buf *buf = ERR_PTR(-EPERM); - struct task_struct *tsk = current; unsigned long flags; - if (!lock_task_sighand(tsk, &flags)) - return -ESRCH; - - if (tsk->signal->audit_tty) { - buf = tsk->signal->tty_audit_buf; + spin_lock_irqsave(¤t->sighand->siglock, flags); + if (current->signal->audit_tty) { + buf = current->signal->tty_audit_buf; if (buf) atomic_inc(&buf->count); } - unlock_task_sighand(tsk, &flags); + spin_unlock_irqrestore(¤t->sighand->siglock, flags); /* * Return 0 when signal->audit_tty set - * but tsk->signal->tty_audit_buf == NULL. + * but current->signal->tty_audit_buf == NULL. */ if (!buf || IS_ERR(buf)) return PTR_ERR(buf); -- cgit v1.2.3 From b50819f437c094b4beb2e8684fbe12bbe79fb331 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:30 -0800 Subject: tty: audit: Ignore current association for audit push In canonical read mode, each line read and logged is pushed separately with tty_audit_push(). For all single-threaded processes and multi-threaded processes reading from only one tty, this patch has no effect; the last line read will still be the entry pushed to the audit log because the tty association cannot have changed between tty_audit_add_data() and tty_audit_push(). For multi-threaded processes reading from different ttys concurrently, the audit log will have mixed log entries anyway. Consider two ttys audited concurrently: CPU0 CPU1 ---------- ------------ tty_audit_add_data(ttyA) tty_audit_add_data(ttyB) tty_audit_push() tty_audit_add_data(ttyB) tty_audit_push() This patch will now cause the ttyB output to be split into separate audit log entries. However, this possibility is equally likely without this patch: CPU0 CPU1 ---------- ------------ tty_audit_add_data(ttyB) tty_audit_add_data(ttyA) tty_audit_push() tty_audit_add_data(ttyB) tty_audit_push() Mixed canonical and non-canonical reads have similar races. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 2 +- drivers/tty/tty_audit.c | 11 +++-------- include/linux/tty.h | 4 ++-- 3 files changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 4fbc5defbcd8..827206914b02 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2072,7 +2072,7 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, ldata->line_start = ldata->read_tail; else ldata->push = 0; - tty_audit_push(tty); + tty_audit_push(); } return 0; } diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 5f65653cee48..5ae48396e265 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -313,9 +313,9 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) /** * tty_audit_push - Push buffered data out * - * Make sure no audit data is pending for @tty on the current process. + * Make sure no audit data is pending on the current process. */ -void tty_audit_push(struct tty_struct *tty) +void tty_audit_push(void) { struct tty_audit_buf *buf; unsigned long flags; @@ -331,13 +331,8 @@ void tty_audit_push(struct tty_struct *tty) spin_unlock_irqrestore(¤t->sighand->siglock, flags); if (buf) { - int major, minor; - - major = tty->driver->major; - minor = tty->driver->minor_start + tty->index; mutex_lock(&buf->mutex); - if (buf->major == major && buf->minor == minor) - tty_audit_buf_push(buf); + tty_audit_buf_push(buf); mutex_unlock(&buf->mutex); tty_audit_buf_put(buf); } diff --git a/include/linux/tty.h b/include/linux/tty.h index c011dc205e5c..83d74dcfb3c8 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -597,7 +597,7 @@ extern void tty_audit_add_data(struct tty_struct *tty, const void *data, extern void tty_audit_exit(void); extern void tty_audit_fork(struct signal_struct *sig); extern void tty_audit_tiocsti(struct tty_struct *tty, char ch); -extern void tty_audit_push(struct tty_struct *tty); +extern void tty_audit_push(void); extern int tty_audit_push_current(void); #else static inline void tty_audit_add_data(struct tty_struct *tty, const void *data, @@ -613,7 +613,7 @@ static inline void tty_audit_exit(void) static inline void tty_audit_fork(struct signal_struct *sig) { } -static inline void tty_audit_push(struct tty_struct *tty) +static inline void tty_audit_push(void) { } static inline int tty_audit_push_current(void) -- cgit v1.2.3 From 37282a77954aa2dbb339d15902290f25b868d2e8 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:31 -0800 Subject: tty: audit: Combine push functions tty_audit_push() and tty_audit_push_current() perform identical tasks; eliminate the tty_audit_push() implementation and the tty_audit_push_current() name. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 35 +++-------------------------------- include/linux/tty.h | 8 ++------ kernel/audit.c | 2 +- 3 files changed, 6 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 5ae48396e265..6b82c3ce321f 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -172,12 +172,11 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) } /** - * tty_audit_push_current - Flush current's pending audit data + * tty_audit_push - Flush current's pending audit data * - * Try to lock sighand and get a reference to the tty audit buffer if available. - * Flush the buffer or return an appropriate error code. + * Returns 0 if success, -EPERM if tty audit is disabled */ -int tty_audit_push_current(void) +int tty_audit_push(void) { struct tty_audit_buf *buf = ERR_PTR(-EPERM); unsigned long flags; @@ -309,31 +308,3 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) mutex_unlock(&buf->mutex); tty_audit_buf_put(buf); } - -/** - * tty_audit_push - Push buffered data out - * - * Make sure no audit data is pending on the current process. - */ -void tty_audit_push(void) -{ - struct tty_audit_buf *buf; - unsigned long flags; - - spin_lock_irqsave(¤t->sighand->siglock, flags); - if (likely(!current->signal->audit_tty)) { - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - return; - } - buf = current->signal->tty_audit_buf; - if (buf) - atomic_inc(&buf->count); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - - if (buf) { - mutex_lock(&buf->mutex); - tty_audit_buf_push(buf); - mutex_unlock(&buf->mutex); - tty_audit_buf_put(buf); - } -} diff --git a/include/linux/tty.h b/include/linux/tty.h index 83d74dcfb3c8..dea7d54d00d4 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -597,8 +597,7 @@ extern void tty_audit_add_data(struct tty_struct *tty, const void *data, extern void tty_audit_exit(void); extern void tty_audit_fork(struct signal_struct *sig); extern void tty_audit_tiocsti(struct tty_struct *tty, char ch); -extern void tty_audit_push(void); -extern int tty_audit_push_current(void); +extern int tty_audit_push(void); #else static inline void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) @@ -613,10 +612,7 @@ static inline void tty_audit_exit(void) static inline void tty_audit_fork(struct signal_struct *sig) { } -static inline void tty_audit_push(void) -{ -} -static inline int tty_audit_push_current(void) +static inline int tty_audit_push(void) { return 0; } diff --git a/kernel/audit.c b/kernel/audit.c index 3a3e5deeda8d..610f221df069 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -920,7 +920,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (err == 1) { /* match or error */ err = 0; if (msg_type == AUDIT_USER_TTY) { - err = tty_audit_push_current(); + err = tty_audit_push(); if (err) break; } -- cgit v1.2.3 From 4d240b6442824df3b5e401459789bab5ee7777ae Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:32 -0800 Subject: tty: audit: Track tty association with dev_t Use dev_t instead of separate major/minor fields to track tty audit buffer association. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 6b82c3ce321f..50380d87061d 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -16,7 +16,7 @@ struct tty_audit_buf { atomic_t count; struct mutex mutex; /* Protects all data below */ - int major, minor; /* The TTY which the data is from */ + dev_t dev; /* The TTY which the data is from */ unsigned icanon:1; size_t valid; unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */ @@ -34,8 +34,7 @@ static struct tty_audit_buf *tty_audit_buf_alloc(void) goto err_buf; atomic_set(&buf->count, 1); mutex_init(&buf->mutex); - buf->major = 0; - buf->minor = 0; + buf->dev = MKDEV(0, 0); buf->icanon = 0; buf->valid = 0; return buf; @@ -59,7 +58,7 @@ static void tty_audit_buf_put(struct tty_audit_buf *buf) tty_audit_buf_free(buf); } -static void tty_audit_log(const char *description, int major, int minor, +static void tty_audit_log(const char *description, dev_t dev, unsigned char *data, size_t size) { struct audit_buffer *ab; @@ -75,7 +74,7 @@ static void tty_audit_log(const char *description, int major, int minor, audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d" " minor=%d comm=", description, pid, uid, - loginuid, sessionid, major, minor); + loginuid, sessionid, MAJOR(dev), MINOR(dev)); get_task_comm(name, tsk); audit_log_untrustedstring(ab, name); audit_log_format(ab, " data="); @@ -98,7 +97,7 @@ static void tty_audit_buf_push(struct tty_audit_buf *buf) buf->valid = 0; return; } - tty_audit_log("tty", buf->major, buf->minor, buf->data, buf->valid); + tty_audit_log("tty", buf->dev, buf->data, buf->valid); buf->valid = 0; } @@ -141,7 +140,8 @@ void tty_audit_fork(struct signal_struct *sig) void tty_audit_tiocsti(struct tty_struct *tty, char ch) { struct tty_audit_buf *buf; - int major, minor, should_audit; + dev_t dev; + int should_audit; unsigned long flags; spin_lock_irqsave(¤t->sighand->siglock, flags); @@ -151,11 +151,10 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) atomic_inc(&buf->count); spin_unlock_irqrestore(¤t->sighand->siglock, flags); - major = tty->driver->major; - minor = tty->driver->minor_start + tty->index; + dev = MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index; if (buf) { mutex_lock(&buf->mutex); - if (buf->major == major && buf->minor == minor) + if (buf->dev == dev) tty_audit_buf_push(buf); mutex_unlock(&buf->mutex); tty_audit_buf_put(buf); @@ -167,7 +166,7 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) auid = audit_get_loginuid(current); sessionid = audit_get_sessionid(current); - tty_audit_log("ioctl=TIOCSTI", major, minor, &ch, 1); + tty_audit_log("ioctl=TIOCSTI", dev, &ch, 1); } } @@ -260,10 +259,10 @@ static struct tty_audit_buf *tty_audit_buf_get(void) void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) { struct tty_audit_buf *buf; - int major, minor; int audit_log_tty_passwd; unsigned long flags; unsigned int icanon = !!L_ICANON(tty); + dev_t dev; if (unlikely(size == 0)) return; @@ -283,13 +282,10 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) return; mutex_lock(&buf->mutex); - major = tty->driver->major; - minor = tty->driver->minor_start + tty->index; - if (buf->major != major || buf->minor != minor - || buf->icanon != icanon) { + dev = MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index; + if (buf->dev != dev || buf->icanon != icanon) { tty_audit_buf_push(buf); - buf->major = major; - buf->minor = minor; + buf->dev = dev; buf->icanon = icanon; } do { -- cgit v1.2.3 From 2e28d38ae1d9ced6ac2deb4001aca3f267304cdb Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:33 -0800 Subject: tty: audit: Handle tty audit enable atomically The audit_tty and audit_tty_log_passwd fields are actually bool values, so merge into single memory location to access atomically. NB: audit log operations may still occur after tty audit is disabled which is consistent with the existing functionality Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 53 ++++++++++++++++++++----------------------------- include/linux/audit.h | 4 ++++ include/linux/sched.h | 1 - kernel/audit.c | 25 +++++++++++------------ 4 files changed, 38 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 50380d87061d..3d90f88c5ff9 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -131,7 +131,6 @@ void tty_audit_exit(void) void tty_audit_fork(struct signal_struct *sig) { sig->audit_tty = current->signal->audit_tty; - sig->audit_tty_log_passwd = current->signal->audit_tty_log_passwd; } /** @@ -141,11 +140,9 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) { struct tty_audit_buf *buf; dev_t dev; - int should_audit; unsigned long flags; spin_lock_irqsave(¤t->sighand->siglock, flags); - should_audit = current->signal->audit_tty; buf = current->signal->tty_audit_buf; if (buf) atomic_inc(&buf->count); @@ -160,7 +157,7 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) tty_audit_buf_put(buf); } - if (should_audit && audit_enabled) { + if (audit_enabled && (current->signal->audit_tty & AUDIT_TTY_ENABLE)) { kuid_t auid; unsigned int sessionid; @@ -177,29 +174,25 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) */ int tty_audit_push(void) { - struct tty_audit_buf *buf = ERR_PTR(-EPERM); + struct tty_audit_buf *buf; unsigned long flags; + if (~current->signal->audit_tty & AUDIT_TTY_ENABLE) + return -EPERM; + spin_lock_irqsave(¤t->sighand->siglock, flags); - if (current->signal->audit_tty) { - buf = current->signal->tty_audit_buf; - if (buf) - atomic_inc(&buf->count); - } + buf = current->signal->tty_audit_buf; + if (buf) + atomic_inc(&buf->count); spin_unlock_irqrestore(¤t->sighand->siglock, flags); - /* - * Return 0 when signal->audit_tty set - * but current->signal->tty_audit_buf == NULL. - */ - if (!buf || IS_ERR(buf)) - return PTR_ERR(buf); - - mutex_lock(&buf->mutex); - tty_audit_buf_push(buf); - mutex_unlock(&buf->mutex); + if (buf) { + mutex_lock(&buf->mutex); + tty_audit_buf_push(buf); + mutex_unlock(&buf->mutex); - tty_audit_buf_put(buf); + tty_audit_buf_put(buf); + } return 0; } @@ -218,8 +211,6 @@ static struct tty_audit_buf *tty_audit_buf_get(void) buf = NULL; buf2 = NULL; spin_lock_irqsave(¤t->sighand->siglock, flags); - if (likely(!current->signal->audit_tty)) - goto out; buf = current->signal->tty_audit_buf; if (buf) { atomic_inc(&buf->count); @@ -233,9 +224,10 @@ static struct tty_audit_buf *tty_audit_buf_get(void) return NULL; } - spin_lock_irqsave(¤t->sighand->siglock, flags); - if (!current->signal->audit_tty) + if (~current->signal->audit_tty & AUDIT_TTY_ENABLE) goto out; + + spin_lock_irqsave(¤t->sighand->siglock, flags); buf = current->signal->tty_audit_buf; if (!buf) { current->signal->tty_audit_buf = buf2; @@ -259,9 +251,8 @@ static struct tty_audit_buf *tty_audit_buf_get(void) void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) { struct tty_audit_buf *buf; - int audit_log_tty_passwd; - unsigned long flags; unsigned int icanon = !!L_ICANON(tty); + unsigned int audit_tty; dev_t dev; if (unlikely(size == 0)) @@ -271,10 +262,10 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) && tty->driver->subtype == PTY_TYPE_MASTER) return; - spin_lock_irqsave(¤t->sighand->siglock, flags); - audit_log_tty_passwd = current->signal->audit_tty_log_passwd; - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - if (!audit_log_tty_passwd && icanon && !L_ECHO(tty)) + audit_tty = READ_ONCE(current->signal->audit_tty); + if (~audit_tty & AUDIT_TTY_ENABLE) + return; + if ((~audit_tty & AUDIT_TTY_LOG_PASSWD) && icanon && !L_ECHO(tty)) return; buf = tty_audit_buf_get(); diff --git a/include/linux/audit.h b/include/linux/audit.h index b40ed5df5542..e38e3fc13ea8 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -109,6 +109,10 @@ extern int audit_classify_compat_syscall(int abi, unsigned syscall); /* maximized args number that audit_socketcall can process */ #define AUDITSC_ARGS 6 +/* bit values for ->signal->audit_tty */ +#define AUDIT_TTY_ENABLE BIT(0) +#define AUDIT_TTY_LOG_PASSWD BIT(1) + struct filename; extern void audit_log_session_info(struct audit_buffer *ab); diff --git a/include/linux/sched.h b/include/linux/sched.h index a10494a94cc3..a389222e9703 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -775,7 +775,6 @@ struct signal_struct { #endif #ifdef CONFIG_AUDIT unsigned audit_tty; - unsigned audit_tty_log_passwd; struct tty_audit_buf *tty_audit_buf; #endif diff --git a/kernel/audit.c b/kernel/audit.c index 610f221df069..2651e423b2dc 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1030,20 +1030,19 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) break; case AUDIT_TTY_GET: { struct audit_tty_status s; - struct task_struct *tsk = current; + unsigned int t; - spin_lock(&tsk->sighand->siglock); - s.enabled = tsk->signal->audit_tty; - s.log_passwd = tsk->signal->audit_tty_log_passwd; - spin_unlock(&tsk->sighand->siglock); + t = READ_ONCE(current->signal->audit_tty); + s.enabled = t & AUDIT_TTY_ENABLE; + s.log_passwd = !!(t & AUDIT_TTY_LOG_PASSWD); audit_send_reply(skb, seq, AUDIT_TTY_GET, 0, 0, &s, sizeof(s)); break; } case AUDIT_TTY_SET: { struct audit_tty_status s, old; - struct task_struct *tsk = current; struct audit_buffer *ab; + unsigned int t; memset(&s, 0, sizeof(s)); /* guard against past and future API changes */ @@ -1053,14 +1052,14 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) (s.log_passwd != 0 && s.log_passwd != 1)) err = -EINVAL; - spin_lock(&tsk->sighand->siglock); - old.enabled = tsk->signal->audit_tty; - old.log_passwd = tsk->signal->audit_tty_log_passwd; - if (!err) { - tsk->signal->audit_tty = s.enabled; - tsk->signal->audit_tty_log_passwd = s.log_passwd; + if (err) + t = READ_ONCE(current->signal->audit_tty); + else { + t = s.enabled | (-s.log_passwd & AUDIT_TTY_LOG_PASSWD); + t = xchg(¤t->signal->audit_tty, t); } - spin_unlock(&tsk->sighand->siglock); + old.enabled = t & AUDIT_TTY_ENABLE; + old.log_passwd = !!(t & AUDIT_TTY_LOG_PASSWD); audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); audit_log_format(ab, " op=tty_set old-enabled=%d new-enabled=%d" -- cgit v1.2.3 From 5c8b3185c41cd7f7c1e39c6e300daac8ef547e7e Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:34 -0800 Subject: tty: audit: Remove false memory optimization The tty audit buffer is allocated at first use and not freed until the process exits. If tty audit is turned off after the audit buffer has been allocated, no effort is made to release the buffer. So re-checking if tty audit has just been turned off when tty audit was just on is false optimization; the likelihood of triggering this condition is exceedingly small. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 3d90f88c5ff9..79439846d29d 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -200,8 +200,7 @@ int tty_audit_push(void) * tty_audit_buf_get - Get an audit buffer. * * Get an audit buffer, allocate it if necessary. Return %NULL - * if TTY auditing is disabled or out of memory. Otherwise, return a new - * reference to the buffer. + * if out of memory. Otherwise, return a new reference to the buffer. */ static struct tty_audit_buf *tty_audit_buf_get(void) { @@ -224,9 +223,6 @@ static struct tty_audit_buf *tty_audit_buf_get(void) return NULL; } - if (~current->signal->audit_tty & AUDIT_TTY_ENABLE) - goto out; - spin_lock_irqsave(¤t->sighand->siglock, flags); buf = current->signal->tty_audit_buf; if (!buf) { -- cgit v1.2.3 From 5493090fc2341d9f28bdd9e81445fe0a130bafc2 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:35 -0800 Subject: tty: audit: Remove tty_audit_buf reference counting When tty_audit_exit() is called from do_exit(), the process is single-threaded. Since the tty_audit_buf is only shared by threads of a process, no other thread can be concurrently accessing the tty_audit_buf during or after tty_audit_exit(). Thus, no other thread can be holding an extra tty_audit_buf reference which would prevent tty_audit_exit() from freeing the tty_audit_buf. As that is the only purpose of the ref counting, remove the reference counting and free the tty_audit_buf directly. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 47 +++++++---------------------------------------- 1 file changed, 7 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 79439846d29d..71ba8baee14d 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -14,7 +14,6 @@ #include struct tty_audit_buf { - atomic_t count; struct mutex mutex; /* Protects all data below */ dev_t dev; /* The TTY which the data is from */ unsigned icanon:1; @@ -32,7 +31,6 @@ static struct tty_audit_buf *tty_audit_buf_alloc(void) buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL); if (!buf->data) goto err_buf; - atomic_set(&buf->count, 1); mutex_init(&buf->mutex); buf->dev = MKDEV(0, 0); buf->icanon = 0; @@ -52,12 +50,6 @@ static void tty_audit_buf_free(struct tty_audit_buf *buf) kfree(buf); } -static void tty_audit_buf_put(struct tty_audit_buf *buf) -{ - if (atomic_dec_and_test(&buf->count)) - tty_audit_buf_free(buf); -} - static void tty_audit_log(const char *description, dev_t dev, unsigned char *data, size_t size) { @@ -106,6 +98,9 @@ static void tty_audit_buf_push(struct tty_audit_buf *buf) * * Make sure all buffered data is written out and deallocate the buffer. * Only needs to be called if current->signal->tty_audit_buf != %NULL. + * + * The process is single-threaded at this point; no other threads share + * current->signal. */ void tty_audit_exit(void) { @@ -116,11 +111,8 @@ void tty_audit_exit(void) if (!buf) return; - mutex_lock(&buf->mutex); tty_audit_buf_push(buf); - mutex_unlock(&buf->mutex); - - tty_audit_buf_put(buf); + tty_audit_buf_free(buf); } /** @@ -140,21 +132,14 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) { struct tty_audit_buf *buf; dev_t dev; - unsigned long flags; - - spin_lock_irqsave(¤t->sighand->siglock, flags); - buf = current->signal->tty_audit_buf; - if (buf) - atomic_inc(&buf->count); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); dev = MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index; + buf = current->signal->tty_audit_buf; if (buf) { mutex_lock(&buf->mutex); if (buf->dev == dev) tty_audit_buf_push(buf); mutex_unlock(&buf->mutex); - tty_audit_buf_put(buf); } if (audit_enabled && (current->signal->audit_tty & AUDIT_TTY_ENABLE)) { @@ -175,23 +160,15 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) int tty_audit_push(void) { struct tty_audit_buf *buf; - unsigned long flags; if (~current->signal->audit_tty & AUDIT_TTY_ENABLE) return -EPERM; - spin_lock_irqsave(¤t->sighand->siglock, flags); buf = current->signal->tty_audit_buf; - if (buf) - atomic_inc(&buf->count); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - if (buf) { mutex_lock(&buf->mutex); tty_audit_buf_push(buf); mutex_unlock(&buf->mutex); - - tty_audit_buf_put(buf); } return 0; } @@ -207,15 +184,9 @@ static struct tty_audit_buf *tty_audit_buf_get(void) struct tty_audit_buf *buf, *buf2; unsigned long flags; - buf = NULL; - buf2 = NULL; - spin_lock_irqsave(¤t->sighand->siglock, flags); buf = current->signal->tty_audit_buf; - if (buf) { - atomic_inc(&buf->count); - goto out; - } - spin_unlock_irqrestore(¤t->sighand->siglock, flags); + if (buf) + return buf; buf2 = tty_audit_buf_alloc(); if (buf2 == NULL) { @@ -230,9 +201,6 @@ static struct tty_audit_buf *tty_audit_buf_get(void) buf = buf2; buf2 = NULL; } - atomic_inc(&buf->count); - /* Fall through */ - out: spin_unlock_irqrestore(¤t->sighand->siglock, flags); if (buf2) tty_audit_buf_free(buf2); @@ -289,5 +257,4 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) tty_audit_buf_push(buf); } while (size != 0); mutex_unlock(&buf->mutex); - tty_audit_buf_put(buf); } -- cgit v1.2.3 From fbaa122718a1235f4f83baa3abaad21cfefdbc9d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:36 -0800 Subject: tty: audit: Simplify first-use allocation The first-use tty audit buffer allocation is a potential race amongst multiple attempts at 'first-use'; only one 'winner' is acceptable. The successful buffer assignment occurs if tty_audit_buf == NULL (which will also be the return from cmpxchg()); otherwise, another racer 'won' and this buffer allocation is freed. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 71ba8baee14d..6e33e41ec74d 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -181,30 +181,22 @@ int tty_audit_push(void) */ static struct tty_audit_buf *tty_audit_buf_get(void) { - struct tty_audit_buf *buf, *buf2; - unsigned long flags; + struct tty_audit_buf *buf; buf = current->signal->tty_audit_buf; if (buf) return buf; - buf2 = tty_audit_buf_alloc(); - if (buf2 == NULL) { + buf = tty_audit_buf_alloc(); + if (buf == NULL) { audit_log_lost("out of memory in TTY auditing"); return NULL; } - spin_lock_irqsave(¤t->sighand->siglock, flags); - buf = current->signal->tty_audit_buf; - if (!buf) { - current->signal->tty_audit_buf = buf2; - buf = buf2; - buf2 = NULL; - } - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - if (buf2) - tty_audit_buf_free(buf2); - return buf; + /* Race to use this buffer, free it if another wins */ + if (cmpxchg(¤t->signal->tty_audit_buf, NULL, buf) != NULL) + tty_audit_buf_free(buf); + return current->signal->tty_audit_buf; } /** -- cgit v1.2.3 From f17c3662745ea5fd4510c3dff19f9975552e1865 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:37 -0800 Subject: tty: audit: Check audit enable first Audit is unlikely to be enabled; check first to exit asap. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 6e33e41ec74d..269e41f45832 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -211,6 +211,10 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) unsigned int audit_tty; dev_t dev; + audit_tty = READ_ONCE(current->signal->audit_tty); + if (~audit_tty & AUDIT_TTY_ENABLE) + return; + if (unlikely(size == 0)) return; @@ -218,9 +222,6 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) && tty->driver->subtype == PTY_TYPE_MASTER) return; - audit_tty = READ_ONCE(current->signal->audit_tty); - if (~audit_tty & AUDIT_TTY_ENABLE) - return; if ((~audit_tty & AUDIT_TTY_LOG_PASSWD) && icanon && !L_ECHO(tty)) return; -- cgit v1.2.3 From 82b5c93a00169614a75d5fa3b5974f832a7857c7 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:38 -0800 Subject: tty: audit: Always push audit buffer before TIOCSTI The data read from another tty may be relevant to the action of the TIOCSTI ioctl; log the audit buffer immediately. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 269e41f45832..fa461dc5b111 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -130,19 +130,13 @@ void tty_audit_fork(struct signal_struct *sig) */ void tty_audit_tiocsti(struct tty_struct *tty, char ch) { - struct tty_audit_buf *buf; dev_t dev; dev = MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index; - buf = current->signal->tty_audit_buf; - if (buf) { - mutex_lock(&buf->mutex); - if (buf->dev == dev) - tty_audit_buf_push(buf); - mutex_unlock(&buf->mutex); - } + if (tty_audit_push()) + return; - if (audit_enabled && (current->signal->audit_tty & AUDIT_TTY_ENABLE)) { + if (audit_enabled) { kuid_t auid; unsigned int sessionid; -- cgit v1.2.3 From 55b6314a17e8ad53233e9d0ebf6328734720e93b Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:39 -0800 Subject: tty: audit: Poison tty_audit_buf while process exits Warn if tty_audit_buf use is attempted after tty_audit_exit() has already freed it. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index fa461dc5b111..66d53fcf4da0 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -21,6 +21,15 @@ struct tty_audit_buf { unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */ }; +static struct tty_audit_buf *tty_audit_buf_ref(void) +{ + struct tty_audit_buf *buf; + + buf = current->signal->tty_audit_buf; + WARN_ON(buf == ERR_PTR(-ESRCH)); + return buf; +} + static struct tty_audit_buf *tty_audit_buf_alloc(void) { struct tty_audit_buf *buf; @@ -106,8 +115,7 @@ void tty_audit_exit(void) { struct tty_audit_buf *buf; - buf = current->signal->tty_audit_buf; - current->signal->tty_audit_buf = NULL; + buf = xchg(¤t->signal->tty_audit_buf, ERR_PTR(-ESRCH)); if (!buf) return; @@ -158,8 +166,8 @@ int tty_audit_push(void) if (~current->signal->audit_tty & AUDIT_TTY_ENABLE) return -EPERM; - buf = current->signal->tty_audit_buf; - if (buf) { + buf = tty_audit_buf_ref(); + if (!IS_ERR_OR_NULL(buf)) { mutex_lock(&buf->mutex); tty_audit_buf_push(buf); mutex_unlock(&buf->mutex); @@ -171,13 +179,14 @@ int tty_audit_push(void) * tty_audit_buf_get - Get an audit buffer. * * Get an audit buffer, allocate it if necessary. Return %NULL - * if out of memory. Otherwise, return a new reference to the buffer. + * if out of memory or ERR_PTR(-ESRCH) if tty_audit_exit() has already + * occurred. Otherwise, return a new reference to the buffer. */ static struct tty_audit_buf *tty_audit_buf_get(void) { struct tty_audit_buf *buf; - buf = current->signal->tty_audit_buf; + buf = tty_audit_buf_ref(); if (buf) return buf; @@ -190,7 +199,7 @@ static struct tty_audit_buf *tty_audit_buf_get(void) /* Race to use this buffer, free it if another wins */ if (cmpxchg(¤t->signal->tty_audit_buf, NULL, buf) != NULL) tty_audit_buf_free(buf); - return current->signal->tty_audit_buf; + return tty_audit_buf_ref(); } /** @@ -220,7 +229,7 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) return; buf = tty_audit_buf_get(); - if (!buf) + if (IS_ERR_OR_NULL(buf)) return; mutex_lock(&buf->mutex); -- cgit v1.2.3 From 98ee377144935857d8ad5d7d70cdab1da4ede32e Mon Sep 17 00:00:00 2001 From: Chris Diamand Date: Wed, 27 Jan 2016 17:04:35 -0800 Subject: Input: byd - add BYD PS/2 touchpad driver Driver for the BYD BTP10463 touchpad, found in PC Specialist `Lafite' laptops. This patch sends the magic command sequence which causes the touchpad to stream intellimouse-style packets. Gestures are detected inside the touchpad, and exposed as special values in the Z component of each packet - absolute coordinates are not supported, even in the Windows driver. At present, this supports two-finger vertical and horizontal scrolling, and provides the framework to expose the other gestures it can recognize. Signed-off-by: Chris Diamand Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/Kconfig | 10 ++ drivers/input/mouse/Makefile | 1 + drivers/input/mouse/byd.c | 337 +++++++++++++++++++++++++++++++++++++ drivers/input/mouse/byd.h | 18 ++ drivers/input/mouse/psmouse-base.c | 14 ++ drivers/input/mouse/psmouse.h | 1 + 6 files changed, 381 insertions(+) create mode 100644 drivers/input/mouse/byd.c create mode 100644 drivers/input/mouse/byd.h (limited to 'drivers') diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 17f97e5e11e7..096abb4ad5cd 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -48,6 +48,16 @@ config MOUSE_PS2_ALPS If unsure, say Y. +config MOUSE_PS2_BYD + bool "BYD PS/2 mouse protocol extension" if EXPERT + default y + depends on MOUSE_PS2 + help + Say Y here if you have a BYD PS/2 touchpad connected to + your system. + + If unsure, say Y. + config MOUSE_PS2_LOGIPS2PP bool "Logitech PS/2++ mouse protocol extension" if EXPERT default y diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index ee6a6e9563d4..6168b134937b 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -28,6 +28,7 @@ cyapatp-objs := cyapa.o cyapa_gen3.o cyapa_gen5.o cyapa_gen6.o psmouse-objs := psmouse-base.o synaptics.o focaltech.o psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o +psmouse-$(CONFIG_MOUSE_PS2_BYD) += byd.o psmouse-$(CONFIG_MOUSE_PS2_ELANTECH) += elantech.o psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o diff --git a/drivers/input/mouse/byd.c b/drivers/input/mouse/byd.c new file mode 100644 index 000000000000..9425e0f6c5ce --- /dev/null +++ b/drivers/input/mouse/byd.c @@ -0,0 +1,337 @@ +/* + * BYD TouchPad PS/2 mouse driver + * + * Copyright (C) 2015 Chris Diamand + * + * 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 +#include +#include +#include + +#include "psmouse.h" +#include "byd.h" + +#define PS2_Y_OVERFLOW BIT_MASK(7) +#define PS2_X_OVERFLOW BIT_MASK(6) +#define PS2_Y_SIGN BIT_MASK(5) +#define PS2_X_SIGN BIT_MASK(4) +#define PS2_ALWAYS_1 BIT_MASK(3) +#define PS2_MIDDLE BIT_MASK(2) +#define PS2_RIGHT BIT_MASK(1) +#define PS2_LEFT BIT_MASK(0) + +/* + * The touchpad reports gestures in the last byte of each packet. It can take + * any of the following values: + */ + +/* One-finger scrolling in one of the edge scroll zones. */ +#define BYD_SCROLLUP 0xCA +#define BYD_SCROLLDOWN 0x36 +#define BYD_SCROLLLEFT 0xCB +#define BYD_SCROLLRIGHT 0x35 +/* Two-finger scrolling. */ +#define BYD_2DOWN 0x2B +#define BYD_2UP 0xD5 +#define BYD_2LEFT 0xD6 +#define BYD_2RIGHT 0x2A +/* Pinching in or out. */ +#define BYD_ZOOMOUT 0xD8 +#define BYD_ZOOMIN 0x28 +/* Three-finger swipe. */ +#define BYD_3UP 0xD3 +#define BYD_3DOWN 0x2D +#define BYD_3LEFT 0xD4 +#define BYD_3RIGHT 0x2C +/* Four-finger swipe. */ +#define BYD_4UP 0xCD +#define BYD_4DOWN 0x33 + +int byd_detect(struct psmouse *psmouse, bool set_properties) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + unsigned char param[4]; + + param[0] = 0x03; + param[1] = 0x00; + param[2] = 0x00; + param[3] = 0x00; + + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) + return -1; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) + return -1; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) + return -1; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) + return -1; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) + return -1; + + if (param[1] != 0x03 || param[2] != 0x64) + return -ENODEV; + + psmouse_dbg(psmouse, "BYD touchpad detected\n"); + + if (set_properties) { + psmouse->vendor = "BYD"; + psmouse->name = "TouchPad"; + } + + return 0; +} + +static psmouse_ret_t byd_process_byte(struct psmouse *psmouse) +{ + struct input_dev *dev = psmouse->dev; + u8 *pkt = psmouse->packet; + + if (psmouse->pktcnt > 0 && !(pkt[0] & PS2_ALWAYS_1)) { + psmouse_warn(psmouse, "Always_1 bit not 1. pkt[0] = %02x\n", + pkt[0]); + return PSMOUSE_BAD_DATA; + } + + if (psmouse->pktcnt < psmouse->pktsize) + return PSMOUSE_GOOD_DATA; + + /* Otherwise, a full packet has been received */ + switch (pkt[3]) { + case 0: { + /* Standard packet */ + /* Sign-extend if a sign bit is set. */ + unsigned int signx = pkt[0] & PS2_X_SIGN ? ~0xFF : 0; + unsigned int signy = pkt[0] & PS2_Y_SIGN ? ~0xFF : 0; + int dx = signx | (int) pkt[1]; + int dy = signy | (int) pkt[2]; + + input_report_rel(psmouse->dev, REL_X, dx); + input_report_rel(psmouse->dev, REL_Y, -dy); + + input_report_key(psmouse->dev, BTN_LEFT, pkt[0] & PS2_LEFT); + input_report_key(psmouse->dev, BTN_RIGHT, pkt[0] & PS2_RIGHT); + input_report_key(psmouse->dev, BTN_MIDDLE, pkt[0] & PS2_MIDDLE); + break; + } + + case BYD_SCROLLDOWN: + case BYD_2DOWN: + input_report_rel(dev, REL_WHEEL, -1); + break; + + case BYD_SCROLLUP: + case BYD_2UP: + input_report_rel(dev, REL_WHEEL, 1); + break; + + case BYD_SCROLLLEFT: + case BYD_2LEFT: + input_report_rel(dev, REL_HWHEEL, -1); + break; + + case BYD_SCROLLRIGHT: + case BYD_2RIGHT: + input_report_rel(dev, REL_HWHEEL, 1); + break; + + case BYD_ZOOMOUT: + case BYD_ZOOMIN: + case BYD_3UP: + case BYD_3DOWN: + case BYD_3LEFT: + case BYD_3RIGHT: + case BYD_4UP: + case BYD_4DOWN: + break; + + default: + psmouse_warn(psmouse, + "Unrecognized Z: pkt = %02x %02x %02x %02x\n", + psmouse->packet[0], psmouse->packet[1], + psmouse->packet[2], psmouse->packet[3]); + return PSMOUSE_BAD_DATA; + } + + input_sync(dev); + + return PSMOUSE_FULL_PACKET; +} + +/* Send a sequence of bytes, where each is ACKed before the next is sent. */ +static int byd_send_sequence(struct psmouse *psmouse, const u8 *seq, size_t len) +{ + unsigned int i; + + for (i = 0; i < len; ++i) { + if (ps2_command(&psmouse->ps2dev, NULL, seq[i])) + return -1; + } + return 0; +} + +/* Keep scrolling after fingers are removed. */ +#define SCROLL_INERTIAL 0x01 +#define SCROLL_NO_INERTIAL 0x02 + +/* Clicking can be done by tapping or pressing. */ +#define CLICK_BOTH 0x01 +/* Clicking can only be done by pressing. */ +#define CLICK_PRESS_ONLY 0x02 + +static int byd_enable(struct psmouse *psmouse) +{ + const u8 seq1[] = { 0xE2, 0x00, 0xE0, 0x02, 0xE0 }; + const u8 seq2[] = { + 0xD3, 0x01, + 0xD0, 0x00, + 0xD0, 0x04, + /* Whether clicking is done by tapping or pressing. */ + 0xD4, CLICK_PRESS_ONLY, + 0xD5, 0x01, + 0xD7, 0x03, + /* Vertical and horizontal one-finger scroll zone inertia. */ + 0xD8, SCROLL_INERTIAL, + 0xDA, 0x05, + 0xDB, 0x02, + 0xE4, 0x05, + 0xD6, 0x01, + 0xDE, 0x04, + 0xE3, 0x01, + 0xCF, 0x00, + 0xD2, 0x03, + /* Vertical and horizontal two-finger scrolling inertia. */ + 0xE5, SCROLL_INERTIAL, + 0xD9, 0x02, + 0xD9, 0x07, + 0xDC, 0x03, + 0xDD, 0x03, + 0xDF, 0x03, + 0xE1, 0x03, + 0xD1, 0x00, + 0xCE, 0x00, + 0xCC, 0x00, + 0xE0, 0x00, + 0xE2, 0x01 + }; + u8 param[4]; + + if (byd_send_sequence(psmouse, seq1, ARRAY_SIZE(seq1))) + return -1; + + /* Send a 0x01 command, which should return 4 bytes. */ + if (ps2_command(&psmouse->ps2dev, param, 0x0401)) + return -1; + + if (byd_send_sequence(psmouse, seq2, ARRAY_SIZE(seq2))) + return -1; + + return 0; +} + +/* + * Send the set of PS/2 commands required to make it identify as an + * intellimouse with 4-byte instead of 3-byte packets. + */ +static int byd_send_intellimouse_sequence(struct psmouse *psmouse) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + u8 param[4]; + int i; + const struct { + u16 command; + u8 arg; + } seq[] = { + { PSMOUSE_CMD_RESET_BAT, 0 }, + { PSMOUSE_CMD_RESET_BAT, 0 }, + { PSMOUSE_CMD_GETID, 0 }, + { PSMOUSE_CMD_SETSCALE11, 0 }, + { PSMOUSE_CMD_SETSCALE11, 0 }, + { PSMOUSE_CMD_SETSCALE11, 0 }, + { PSMOUSE_CMD_GETINFO, 0 }, + { PSMOUSE_CMD_SETRES, 0x03 }, + { PSMOUSE_CMD_SETRATE, 0xC8 }, + { PSMOUSE_CMD_SETRATE, 0x64 }, + { PSMOUSE_CMD_SETRATE, 0x50 }, + { PSMOUSE_CMD_GETID, 0 }, + { PSMOUSE_CMD_SETRATE, 0xC8 }, + { PSMOUSE_CMD_SETRATE, 0xC8 }, + { PSMOUSE_CMD_SETRATE, 0x50 }, + { PSMOUSE_CMD_GETID, 0 }, + { PSMOUSE_CMD_SETRATE, 0x64 }, + { PSMOUSE_CMD_SETRES, 0x03 }, + { PSMOUSE_CMD_ENABLE, 0 } + }; + + memset(param, 0, sizeof(param)); + for (i = 0; i < ARRAY_SIZE(seq); ++i) { + param[0] = seq[i].arg; + if (ps2_command(ps2dev, param, seq[i].command)) + return -1; + } + + return 0; +} + +static int byd_reset_touchpad(struct psmouse *psmouse) +{ + if (byd_send_intellimouse_sequence(psmouse)) + return -EIO; + + if (byd_enable(psmouse)) + return -EIO; + + return 0; +} + +static int byd_reconnect(struct psmouse *psmouse) +{ + int retry = 0, error = 0; + + psmouse_dbg(psmouse, "Reconnect\n"); + do { + psmouse_reset(psmouse); + if (retry) + ssleep(1); + error = byd_detect(psmouse, 0); + } while (error && ++retry < 3); + + if (error) + return error; + + psmouse_dbg(psmouse, "Reconnected after %d attempts\n", retry); + + error = byd_reset_touchpad(psmouse); + if (error) { + psmouse_err(psmouse, "Unable to initialize device\n"); + return error; + } + + return 0; +} + +int byd_init(struct psmouse *psmouse) +{ + struct input_dev *dev = psmouse->dev; + + if (psmouse_reset(psmouse)) + return -EIO; + + if (byd_reset_touchpad(psmouse)) + return -EIO; + + psmouse->reconnect = byd_reconnect; + psmouse->protocol_handler = byd_process_byte; + psmouse->pktsize = 4; + psmouse->resync_time = 0; + + __set_bit(BTN_MIDDLE, dev->keybit); + __set_bit(REL_WHEEL, dev->relbit); + __set_bit(REL_HWHEEL, dev->relbit); + + return 0; +} diff --git a/drivers/input/mouse/byd.h b/drivers/input/mouse/byd.h new file mode 100644 index 000000000000..d6c120cf36cd --- /dev/null +++ b/drivers/input/mouse/byd.h @@ -0,0 +1,18 @@ +#ifndef _BYD_H +#define _BYD_H + +#ifdef CONFIG_MOUSE_PS2_BYD +int byd_detect(struct psmouse *psmouse, bool set_properties); +int byd_init(struct psmouse *psmouse); +#else +static inline int byd_detect(struct psmouse *psmouse, bool set_properties) +{ + return -ENOSYS; +} +static inline int byd_init(struct psmouse *psmouse) +{ + return -ENOSYS; +} +#endif /* CONFIG_MOUSE_PS2_BYD */ + +#endif /* _BYD_H */ diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index b9e4ee34c132..39d1becd35c9 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -37,6 +37,7 @@ #include "cypress_ps2.h" #include "focaltech.h" #include "vmmouse.h" +#include "byd.h" #define DRIVER_DESC "PS/2 mouse driver" @@ -841,6 +842,15 @@ static const struct psmouse_protocol psmouse_protocols[] = { .detect = vmmouse_detect, .init = vmmouse_init, }, +#endif +#ifdef CONFIG_MOUSE_PS2_BYD + { + .type = PSMOUSE_BYD, + .name = "BydPS/2", + .alias = "byd", + .detect = byd_detect, + .init = byd_init, + }, #endif { .type = PSMOUSE_AUTO, @@ -1105,6 +1115,10 @@ static int psmouse_extensions(struct psmouse *psmouse, if (psmouse_try_protocol(psmouse, PSMOUSE_TOUCHKIT_PS2, &max_proto, set_properties, true)) return PSMOUSE_TOUCHKIT_PS2; + + if (psmouse_try_protocol(psmouse, PSMOUSE_BYD, + &max_proto, set_properties, true)) + return PSMOUSE_BYD; } /* diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index ad5a5a1ea872..e0ca6cda3d16 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -104,6 +104,7 @@ enum psmouse_type { PSMOUSE_CYPRESS, PSMOUSE_FOCALTECH, PSMOUSE_VMMOUSE, + PSMOUSE_BYD, PSMOUSE_AUTO /* This one should always be last */ }; -- cgit v1.2.3 From 60dee3ca27b3613e6519df52d02eadf71f853859 Mon Sep 17 00:00:00 2001 From: Gioh Kim Date: Wed, 27 Jan 2016 12:02:09 +0100 Subject: hwmon: (fam15h_power) Add bit masking for tdp_limit Add bit masking to read ApmTdpLimit precisely Signed-off-by: Gioh Kim Acked-by: Borislav Petkov Acked-by: Huang Rui Signed-off-by: Guenter Roeck --- drivers/hwmon/fam15h_power.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index f77eb971ce95..4f695d8fcafa 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -90,7 +90,15 @@ static ssize_t show_power(struct device *dev, pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5), REG_TDP_LIMIT3, &val); - tdp_limit = val >> 16; + /* + * On Carrizo and later platforms, ApmTdpLimit bit field + * is extended to 16:31 from 16:28. + */ + if (boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model >= 0x60) + tdp_limit = val >> 16; + else + tdp_limit = (val >> 16) & 0x1fff; + curr_pwr_watts = ((u64)(tdp_limit + data->base_tdp)) << running_avg_range; curr_pwr_watts -= running_avg_capture; -- cgit v1.2.3 From 4332e0144fe44cfc9a9c851f0edcab92ead2adbd Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 20 Jan 2016 13:57:31 -0500 Subject: gpio: 104-idi-48: Allow IRQ sharing The ACCES 104-IDI-48 can differentiate between its own and other devices' interrupt requests. Therefore, IRQ sharing is possible and should be permitted. Signed-off-by: William Breathitt Gray Signed-off-by: Linus Walleij --- drivers/gpio/gpio-104-idi-48.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c index 52eed328ce99..285a075e1fd7 100644 --- a/drivers/gpio/gpio-104-idi-48.c +++ b/drivers/gpio/gpio-104-idi-48.c @@ -267,7 +267,8 @@ static int __init idi_48_probe(struct platform_device *pdev) goto err_gpiochip_irqchip_add; } - err = request_irq(irq, idi_48_irq_handler, 0, name, idi48gpio); + err = request_irq(irq, idi_48_irq_handler, IRQF_SHARED, name, + idi48gpio); if (err) { dev_err(dev, "IRQ handler registering failed (%d)\n", err); goto err_request_irq; -- cgit v1.2.3 From 9c26df9b27b67c607f4881551222f36d8bde865b Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 20 Jan 2016 13:45:33 -0500 Subject: gpio: Add GPIO support for the WinSystems WS16C48 The WinSystems WS16C48 device provides 48 lines of digital I/O. In addition, the first 24 lines may be used for interrupt-handled edge detection; rising edge detection and falling edge detection are supported. This driver provides GPIO and IRQ support for these 48 channels of digital I/O. The base port address for the device may be configured via the ws16c48_base module parameter. The interrupt line number for the device may be configured via the ws16c48_irq module parameter. Signed-off-by: William Breathitt Gray Signed-off-by: Linus Walleij --- MAINTAINERS | 6 + drivers/gpio/Kconfig | 9 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-ws16c48.c | 436 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 452 insertions(+) create mode 100644 drivers/gpio/gpio-ws16c48.c (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 30aca4aa5467..0ba80b692723 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11871,6 +11871,12 @@ M: David Härdeman S: Maintained F: drivers/media/rc/winbond-cir.c +WINSYSTEMS WS16C48 GPIO DRIVER +M: William Breathitt Gray +L: linux-gpio@vger.kernel.org +S: Maintained +F: drivers/gpio/gpio-ws16c48.c + WIMAX STACK M: Inaky Perez-Gonzalez M: linux-wimax@intel.com diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index c88dd24a4b1f..b5337f2e0eb4 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -570,6 +570,15 @@ config GPIO_TS5500 blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600 LCD port. +config GPIO_WS16C48 + tristate "WinSystems WS16C48 GPIO support" + select GPIOLIB_IRQCHIP + help + Enables GPIO support for the WinSystems WS16C48. The base port address + for the device may be configured via the ws16c48_base module + parameter. The interrupt line number for the device may be configured + via the ws16c48_irq module parameter. + endmenu menu "I2C GPIO expanders" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ece7d7cbdc80..73121b1b3b94 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -111,6 +111,7 @@ obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o +obj-$(CONFIG_GPIO_WS16C48) += gpio-ws16c48.o obj-$(CONFIG_GPIO_XGENE) += gpio-xgene.o obj-$(CONFIG_GPIO_XGENE_SB) += gpio-xgene-sb.o obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o diff --git a/drivers/gpio/gpio-ws16c48.c b/drivers/gpio/gpio-ws16c48.c new file mode 100644 index 000000000000..9dd947993476 --- /dev/null +++ b/drivers/gpio/gpio-ws16c48.c @@ -0,0 +1,436 @@ +/* + * GPIO driver for the WinSystems WS16C48 + * Copyright (C) 2016 William Breathitt Gray + * + * 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. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned ws16c48_base; +module_param(ws16c48_base, uint, 0); +MODULE_PARM_DESC(ws16c48_base, "WinSystems WS16C48 base address"); +static unsigned ws16c48_irq; +module_param(ws16c48_irq, uint, 0); +MODULE_PARM_DESC(ws16c48_irq, "WinSystems WS16C48 interrupt line number"); + +/** + * struct ws16c48_gpio - GPIO device private data structure + * @chip: instance of the gpio_chip + * @io_state: bit I/O state (whether bit is set to input or output) + * @out_state: output bits state + * @lock: synchronization lock to prevent I/O race conditions + * @irq_mask: I/O bits affected by interrupts + * @flow_mask: IRQ flow type mask for the respective I/O bits + * @base: base port address of the GPIO device + * @extent: extent of port address region of the GPIO device + * @irq: Interrupt line number + */ +struct ws16c48_gpio { + struct gpio_chip chip; + unsigned char io_state[6]; + unsigned char out_state[6]; + spinlock_t lock; + unsigned long irq_mask; + unsigned long flow_mask; + unsigned base; + unsigned extent; + unsigned irq; +}; + +static int ws16c48_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + + return !!(ws16c48gpio->io_state[port] & mask); +} + +static int ws16c48_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + unsigned long flags; + + spin_lock_irqsave(&ws16c48gpio->lock, flags); + + ws16c48gpio->io_state[port] |= mask; + ws16c48gpio->out_state[port] &= ~mask; + outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port); + + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + + return 0; +} + +static int ws16c48_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + unsigned long flags; + + spin_lock_irqsave(&ws16c48gpio->lock, flags); + + ws16c48gpio->io_state[port] &= ~mask; + if (value) + ws16c48gpio->out_state[port] |= mask; + else + ws16c48gpio->out_state[port] &= ~mask; + outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port); + + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + + return 0; +} + +static int ws16c48_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + unsigned long flags; + unsigned port_state; + + spin_lock_irqsave(&ws16c48gpio->lock, flags); + + /* ensure that GPIO is set for input */ + if (!(ws16c48gpio->io_state[port] & mask)) { + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + return -EINVAL; + } + + port_state = inb(ws16c48gpio->base + port); + + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + + return !!(port_state & mask); +} + +static void ws16c48_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + unsigned long flags; + + spin_lock_irqsave(&ws16c48gpio->lock, flags); + + /* ensure that GPIO is set for output */ + if (ws16c48gpio->io_state[port] & mask) { + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + return; + } + + if (value) + ws16c48gpio->out_state[port] |= mask; + else + ws16c48gpio->out_state[port] &= ~mask; + outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port); + + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); +} + +static void ws16c48_irq_ack(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned long offset = irqd_to_hwirq(data); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + unsigned long flags; + unsigned port_state; + + /* only the first 3 ports support interrupts */ + if (port > 2) + return; + + spin_lock_irqsave(&ws16c48gpio->lock, flags); + + port_state = ws16c48gpio->irq_mask >> (8*port); + + outb(0x80, ws16c48gpio->base + 7); + outb(port_state & ~mask, ws16c48gpio->base + 8 + port); + outb(port_state | mask, ws16c48gpio->base + 8 + port); + outb(0xC0, ws16c48gpio->base + 7); + + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); +} + +static void ws16c48_irq_mask(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned long offset = irqd_to_hwirq(data); + const unsigned long mask = BIT(offset); + const unsigned port = offset / 8; + unsigned long flags; + + /* only the first 3 ports support interrupts */ + if (port > 2) + return; + + spin_lock_irqsave(&ws16c48gpio->lock, flags); + + ws16c48gpio->irq_mask &= ~mask; + + outb(0x80, ws16c48gpio->base + 7); + outb(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port); + outb(0xC0, ws16c48gpio->base + 7); + + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); +} + +static void ws16c48_irq_unmask(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned long offset = irqd_to_hwirq(data); + const unsigned long mask = BIT(offset); + const unsigned port = offset / 8; + unsigned long flags; + + /* only the first 3 ports support interrupts */ + if (port > 2) + return; + + spin_lock_irqsave(&ws16c48gpio->lock, flags); + + ws16c48gpio->irq_mask |= mask; + + outb(0x80, ws16c48gpio->base + 7); + outb(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port); + outb(0xC0, ws16c48gpio->base + 7); + + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); +} + +static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned long offset = irqd_to_hwirq(data); + const unsigned long mask = BIT(offset); + const unsigned port = offset / 8; + unsigned long flags; + + /* only the first 3 ports support interrupts */ + if (port > 2) + return -EINVAL; + + spin_lock_irqsave(&ws16c48gpio->lock, flags); + + switch (flow_type) { + case IRQ_TYPE_NONE: + break; + case IRQ_TYPE_EDGE_RISING: + ws16c48gpio->flow_mask |= mask; + break; + case IRQ_TYPE_EDGE_FALLING: + ws16c48gpio->flow_mask &= ~mask; + break; + default: + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + return -EINVAL; + } + + outb(0x40, ws16c48gpio->base + 7); + outb(ws16c48gpio->flow_mask >> (8*port), ws16c48gpio->base + 8 + port); + outb(0xC0, ws16c48gpio->base + 7); + + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + + return 0; +} + +static struct irq_chip ws16c48_irqchip = { + .name = "ws16c48", + .irq_ack = ws16c48_irq_ack, + .irq_mask = ws16c48_irq_mask, + .irq_unmask = ws16c48_irq_unmask, + .irq_set_type = ws16c48_irq_set_type +}; + +static irqreturn_t ws16c48_irq_handler(int irq, void *dev_id) +{ + struct ws16c48_gpio *const ws16c48gpio = dev_id; + struct gpio_chip *const chip = &ws16c48gpio->chip; + unsigned long int_pending; + unsigned long port; + unsigned long int_id; + unsigned long gpio; + + int_pending = inb(ws16c48gpio->base + 6) & 0x7; + if (!int_pending) + return IRQ_NONE; + + /* loop until all pending interrupts are handled */ + do { + for_each_set_bit(port, &int_pending, 3) { + int_id = inb(ws16c48gpio->base + 8 + port); + for_each_set_bit(gpio, &int_id, 8) + generic_handle_irq(irq_find_mapping( + chip->irqdomain, gpio + 8*port)); + } + + int_pending = inb(ws16c48gpio->base + 6) & 0x7; + } while (int_pending); + + return IRQ_HANDLED; +} + +static int __init ws16c48_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct ws16c48_gpio *ws16c48gpio; + const unsigned base = ws16c48_base; + const unsigned extent = 16; + const char *const name = dev_name(dev); + int err; + const unsigned irq = ws16c48_irq; + + ws16c48gpio = devm_kzalloc(dev, sizeof(*ws16c48gpio), GFP_KERNEL); + if (!ws16c48gpio) + return -ENOMEM; + + if (!request_region(base, extent, name)) { + dev_err(dev, "Unable to lock %s port addresses (0x%X-0x%X)\n", + name, base, base + extent); + err = -EBUSY; + goto err_lock_io_port; + } + + ws16c48gpio->chip.label = name; + ws16c48gpio->chip.parent = dev; + ws16c48gpio->chip.owner = THIS_MODULE; + ws16c48gpio->chip.base = -1; + ws16c48gpio->chip.ngpio = 48; + ws16c48gpio->chip.get_direction = ws16c48_gpio_get_direction; + ws16c48gpio->chip.direction_input = ws16c48_gpio_direction_input; + ws16c48gpio->chip.direction_output = ws16c48_gpio_direction_output; + ws16c48gpio->chip.get = ws16c48_gpio_get; + ws16c48gpio->chip.set = ws16c48_gpio_set; + ws16c48gpio->base = base; + ws16c48gpio->extent = extent; + ws16c48gpio->irq = irq; + + spin_lock_init(&ws16c48gpio->lock); + + dev_set_drvdata(dev, ws16c48gpio); + + err = gpiochip_add_data(&ws16c48gpio->chip, ws16c48gpio); + if (err) { + dev_err(dev, "GPIO registering failed (%d)\n", err); + goto err_gpio_register; + } + + /* Disable IRQ by default */ + outb(0x80, base + 7); + outb(0, base + 8); + outb(0, base + 9); + outb(0, base + 10); + outb(0xC0, base + 7); + + err = gpiochip_irqchip_add(&ws16c48gpio->chip, &ws16c48_irqchip, 0, + handle_edge_irq, IRQ_TYPE_NONE); + if (err) { + dev_err(dev, "Could not add irqchip (%d)\n", err); + goto err_gpiochip_irqchip_add; + } + + err = request_irq(irq, ws16c48_irq_handler, IRQF_SHARED, name, + ws16c48gpio); + if (err) { + dev_err(dev, "IRQ handler registering failed (%d)\n", err); + goto err_request_irq; + } + + return 0; + +err_request_irq: +err_gpiochip_irqchip_add: + gpiochip_remove(&ws16c48gpio->chip); +err_gpio_register: + release_region(base, extent); +err_lock_io_port: + return err; +} + +static int ws16c48_remove(struct platform_device *pdev) +{ + struct ws16c48_gpio *const ws16c48gpio = platform_get_drvdata(pdev); + + free_irq(ws16c48gpio->irq, ws16c48gpio); + gpiochip_remove(&ws16c48gpio->chip); + release_region(ws16c48gpio->base, ws16c48gpio->extent); + + return 0; +} + +static struct platform_device *ws16c48_device; + +static struct platform_driver ws16c48_driver = { + .driver = { + .name = "ws16c48" + }, + .remove = ws16c48_remove +}; + +static void __exit ws16c48_exit(void) +{ + platform_device_unregister(ws16c48_device); + platform_driver_unregister(&ws16c48_driver); +} + +static int __init ws16c48_init(void) +{ + int err; + + ws16c48_device = platform_device_alloc(ws16c48_driver.driver.name, -1); + if (!ws16c48_device) + return -ENOMEM; + + err = platform_device_add(ws16c48_device); + if (err) + goto err_platform_device; + + err = platform_driver_probe(&ws16c48_driver, ws16c48_probe); + if (err) + goto err_platform_driver; + + return 0; + +err_platform_driver: + platform_device_del(ws16c48_device); +err_platform_device: + platform_device_put(ws16c48_device); + return err; +} + +module_init(ws16c48_init); +module_exit(ws16c48_exit); + +MODULE_AUTHOR("William Breathitt Gray "); +MODULE_DESCRIPTION("WinSystems WS16C48 GPIO driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From df94e702277e14889af5eef5fbfc3a33261c8b33 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 21 Jan 2016 14:13:23 +0100 Subject: ath10k: rename some HTT events New names make a bit more sense. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.c | 8 ++++---- drivers/net/wireless/ath/ath10k/htt.h | 8 ++++---- drivers/net/wireless/ath/ath10k/htt_rx.c | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c index 3e6ba63dfdff..7561f22f10f9 100644 --- a/drivers/net/wireless/ath/ath10k/htt.c +++ b/drivers/net/wireless/ath/ath10k/htt.c @@ -131,12 +131,12 @@ static const enum htt_t2h_msg_type htt_10_4_t2h_msg_types[] = { [HTT_10_4_T2H_MSG_TYPE_AGGR_CONF] = HTT_T2H_MSG_TYPE_AGGR_CONF, [HTT_10_4_T2H_MSG_TYPE_TX_FETCH_IND] = HTT_T2H_MSG_TYPE_TX_FETCH_IND, - [HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONF] = - HTT_T2H_MSG_TYPE_TX_FETCH_CONF, + [HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONFIRM] = + HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM, [HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD] = HTT_T2H_MSG_TYPE_STATS_NOUPLOAD, - [HTT_10_4_T2H_MSG_TYPE_TX_LOW_LATENCY_IND] = - HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND, + [HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND] = + HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND, }; int ath10k_htt_connect(struct ath10k_htt *htt) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 47ca048feaf0..edd3b9070de9 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -413,10 +413,10 @@ enum htt_10_4_t2h_msg_type { HTT_10_4_T2H_MSG_TYPE_EN_STATS = 0x14, HTT_10_4_T2H_MSG_TYPE_AGGR_CONF = 0x15, HTT_10_4_T2H_MSG_TYPE_TX_FETCH_IND = 0x16, - HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONF = 0x17, + HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONFIRM = 0x17, HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD = 0x18, /* 0x19 to 0x2f are reserved */ - HTT_10_4_T2H_MSG_TYPE_TX_LOW_LATENCY_IND = 0x30, + HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND = 0x30, /* keep this last */ HTT_10_4_T2H_NUM_MSGS }; @@ -449,8 +449,8 @@ enum htt_t2h_msg_type { HTT_T2H_MSG_TYPE_TEST, HTT_T2H_MSG_TYPE_EN_STATS, HTT_T2H_MSG_TYPE_TX_FETCH_IND, - HTT_T2H_MSG_TYPE_TX_FETCH_CONF, - HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND, + HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM, + HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND, /* keep this last */ HTT_T2H_NUM_MSGS }; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 3079434b5d9b..84abe4f25c73 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2125,8 +2125,8 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) break; case HTT_T2H_MSG_TYPE_EN_STATS: case HTT_T2H_MSG_TYPE_TX_FETCH_IND: - case HTT_T2H_MSG_TYPE_TX_FETCH_CONF: - case HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND: + case HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM: + case HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND: default: ath10k_warn(ar, "htt event (%d) not handled\n", resp->hdr.msg_type); -- cgit v1.2.3 From 22e6b3bc5d9668dc711665d255efad89c527b4d6 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 21 Jan 2016 14:13:24 +0100 Subject: ath10k: add new htt definitions These definitions are associated with some improvements upcomming for 10.4 and QCA99X0. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 153 +++++++++++++++++++++++++++++++++- 1 file changed, 150 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index edd3b9070de9..0c5628dafabf 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -52,6 +52,7 @@ enum htt_h2t_msg_type { /* host-to-target */ /* This command is used for sending management frames in HTT < 3.0. * HTT >= 3.0 uses TX_FRM for everything. */ HTT_H2T_MSG_TYPE_MGMT_TX = 7, + HTT_H2T_MSG_TYPE_TX_FETCH_RESP = 11, HTT_H2T_NUM_MSGS /* keep this last */ }; @@ -1306,9 +1307,43 @@ struct htt_frag_desc_bank_id { * so we use a conservatively safe value for now */ #define HTT_FRAG_DESC_BANK_MAX 4 -#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_MASK 0x03 -#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_LSB 0 -#define HTT_FRAG_DESC_BANK_CFG_INFO_SWAP (1 << 2) +#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_MASK 0x03 +#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_LSB 0 +#define HTT_FRAG_DESC_BANK_CFG_INFO_SWAP BIT(2) +#define HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_VALID BIT(3) +#define HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE_MASK BIT(4) +#define HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE_LSB 4 + +enum htt_q_depth_type { + HTT_Q_DEPTH_TYPE_BYTES = 0, + HTT_Q_DEPTH_TYPE_MSDUS = 1, +}; + +#define HTT_TX_Q_STATE_NUM_PEERS (TARGET_10_4_NUM_QCACHE_PEERS_MAX + \ + TARGET_10_4_NUM_VDEVS) +#define HTT_TX_Q_STATE_NUM_TIDS 8 +#define HTT_TX_Q_STATE_ENTRY_SIZE 1 +#define HTT_TX_Q_STATE_ENTRY_MULTIPLIER 0 + +/** + * htt_q_state_conf - part of htt_frag_desc_bank_cfg for host q state config + * + * Defines host q state format and behavior. See htt_q_state. + * + * @record_size: Defines the size of each host q entry in bytes. In practice + * however firmware (at least 10.4.3-00191) ignores this host + * configuration value and uses hardcoded value of 1. + * @record_multiplier: This is valid only when q depth type is MSDUs. It + * defines the exponent for the power of 2 multiplication. + */ +struct htt_q_state_conf { + __le32 paddr; + __le16 num_peers; + __le16 num_tids; + u8 record_size; + u8 record_multiplier; + u8 pad[2]; +} __packed; struct htt_frag_desc_bank_cfg { u8 info; /* HTT_FRAG_DESC_BANK_CFG_INFO_ */ @@ -1316,6 +1351,114 @@ struct htt_frag_desc_bank_cfg { u8 desc_size; __le32 bank_base_addrs[HTT_FRAG_DESC_BANK_MAX]; struct htt_frag_desc_bank_id bank_id[HTT_FRAG_DESC_BANK_MAX]; + struct htt_q_state_conf q_state; +} __packed; + +#define HTT_TX_Q_STATE_ENTRY_COEFFICIENT 128 +#define HTT_TX_Q_STATE_ENTRY_FACTOR_MASK 0x3f +#define HTT_TX_Q_STATE_ENTRY_FACTOR_LSB 0 +#define HTT_TX_Q_STATE_ENTRY_EXP_MASK 0xc0 +#define HTT_TX_Q_STATE_ENTRY_EXP_LSB 6 + +/** + * htt_q_state - shared between host and firmware via DMA + * + * This structure is used for the host to expose it's software queue state to + * firmware so that its rate control can schedule fetch requests for optimized + * performance. This is most notably used for MU-MIMO aggregation when multiple + * MU clients are connected. + * + * @count: Each element defines the host queue depth. When q depth type was + * configured as HTT_Q_DEPTH_TYPE_BYTES then each entry is defined as: + * FACTOR * 128 * 8^EXP (see HTT_TX_Q_STATE_ENTRY_FACTOR_MASK and + * HTT_TX_Q_STATE_ENTRY_EXP_MASK). When q depth type was configured as + * HTT_Q_DEPTH_TYPE_MSDUS the number of packets is scaled by 2 ** + * record_multiplier (see htt_q_state_conf). + * @map: Used by firmware to quickly check which host queues are not empty. It + * is a bitmap simply saying. + * @seq: Used by firmware to quickly check if the host queues were updated + * since it last checked. + * + * FIXME: Is the q_state map[] size calculation really correct? + */ +struct htt_q_state { + u8 count[HTT_TX_Q_STATE_NUM_TIDS][HTT_TX_Q_STATE_NUM_PEERS]; + u32 map[HTT_TX_Q_STATE_NUM_TIDS][(HTT_TX_Q_STATE_NUM_PEERS + 31) / 32]; + __le32 seq; +} __packed; + +#define HTT_TX_FETCH_RECORD_INFO_PEER_ID_MASK 0x0fff +#define HTT_TX_FETCH_RECORD_INFO_PEER_ID_LSB 0 +#define HTT_TX_FETCH_RECORD_INFO_TID_MASK 0xf000 +#define HTT_TX_FETCH_RECORD_INFO_TID_LSB 12 + +struct htt_tx_fetch_record { + __le16 info; /* HTT_TX_FETCH_IND_RECORD_INFO_ */ + __le16 num_msdus; + __le32 num_bytes; +} __packed; + +struct htt_tx_fetch_ind { + u8 pad0; + __le16 fetch_seq_num; + __le32 token; + __le16 num_resp_ids; + __le16 num_records; + struct htt_tx_fetch_record records[0]; + __le32 resp_ids[0]; /* ath10k_htt_get_tx_fetch_ind_resp_ids() */ +} __packed; + +static inline void * +ath10k_htt_get_tx_fetch_ind_resp_ids(struct htt_tx_fetch_ind *ind) +{ + return (void *)&ind->records[le16_to_cpu(ind->num_records)]; +} + +struct htt_tx_fetch_resp { + u8 pad0; + __le16 resp_id; + __le16 fetch_seq_num; + __le16 num_records; + __le32 token; + struct htt_tx_fetch_record records[0]; +} __packed; + +struct htt_tx_fetch_confirm { + u8 pad0; + __le16 num_resp_ids; + __le32 resp_ids[0]; +} __packed; + +enum htt_tx_mode_switch_mode { + HTT_TX_MODE_SWITCH_PUSH = 0, + HTT_TX_MODE_SWITCH_PUSH_PULL = 1, +}; + +#define HTT_TX_MODE_SWITCH_IND_INFO0_ENABLE BIT(0) +#define HTT_TX_MODE_SWITCH_IND_INFO0_NUM_RECORDS_MASK 0xfffe +#define HTT_TX_MODE_SWITCH_IND_INFO0_NUM_RECORDS_LSB 1 + +#define HTT_TX_MODE_SWITCH_IND_INFO1_MODE_MASK 0x0003 +#define HTT_TX_MODE_SWITCH_IND_INFO1_MODE_LSB 0 +#define HTT_TX_MODE_SWITCH_IND_INFO1_THRESHOLD_MASK 0xfffc +#define HTT_TX_MODE_SWITCH_IND_INFO1_THRESHOLD_LSB 2 + +#define HTT_TX_MODE_SWITCH_RECORD_INFO0_PEER_ID_MASK 0x0fff +#define HTT_TX_MODE_SWITCH_RECORD_INFO0_PEER_ID_LSB 0 +#define HTT_TX_MODE_SWITCH_RECORD_INFO0_TID_MASK 0xf000 +#define HTT_TX_MODE_SWITCH_RECORD_INFO0_TID_LSB 12 + +struct htt_tx_mode_switch_record { + __le16 info0; /* HTT_TX_MODE_SWITCH_RECORD_INFO0_ */ + __le16 num_max_msdus; +} __packed; + +struct htt_tx_mode_switch_ind { + u8 pad0; + __le16 info0; /* HTT_TX_MODE_SWITCH_IND_INFO0_ */ + __le16 info1; /* HTT_TX_MODE_SWITCH_IND_INFO1_ */ + u8 pad1[2]; + struct htt_tx_mode_switch_record records[0]; } __packed; union htt_rx_pn_t { @@ -1340,6 +1483,7 @@ struct htt_cmd { struct htt_oob_sync_req oob_sync_req; struct htt_aggr_conf aggr_conf; struct htt_frag_desc_bank_cfg frag_desc_bank_cfg; + struct htt_tx_fetch_resp tx_fetch_resp; }; } __packed; @@ -1364,6 +1508,9 @@ struct htt_resp { struct htt_rx_pn_ind rx_pn_ind; struct htt_rx_offload_ind rx_offload_ind; struct htt_rx_in_ord_ind rx_in_ord_ind; + struct htt_tx_fetch_ind tx_fetch_ind; + struct htt_tx_fetch_confirm tx_fetch_confirm; + struct htt_tx_mode_switch_ind tx_mode_switch_ind; }; } __packed; -- cgit v1.2.3 From 9b783763aa9623dedeed77bec158f7377cb87750 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 21 Jan 2016 14:13:25 +0100 Subject: ath10k: add new FW_FEATURE_PEER_FLOW_CONTROL This feature flag will be used for firmware which supports pull-push model where host shares it's software queue state with firmware and firmware generates fetch requests telling host which queues to dequeue tx from. Primary function of this is improved MU-MIMO performance with multiple clients. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 1 + drivers/net/wireless/ath/ath10k/core.h | 9 +++++++++ 2 files changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index b41eb3f4ee56..48a26206c5c1 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -217,6 +217,7 @@ static const char *const ath10k_core_fw_feature_str[] = { [ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode", [ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca", [ATH10K_FW_FEATURE_MFP_SUPPORT] = "mfp", + [ATH10K_FW_FEATURE_PEER_FLOW_CONTROL] = "peer-flow-ctrl", }; static unsigned int ath10k_core_get_fw_feature_str(char *buf, diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 921b86a4f257..5067a0ff4e89 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -512,6 +512,15 @@ enum ath10k_fw_features { /* Firmware supports management frame protection */ ATH10K_FW_FEATURE_MFP_SUPPORT = 12, + /* Firmware supports pull-push model where host shares it's software + * queue state with firmware and firmware generates fetch requests + * telling host which queues to dequeue tx from. + * + * Primary function of this is improved MU-MIMO performance with + * multiple clients. + */ + ATH10K_FW_FEATURE_PEER_FLOW_CONTROL = 13, + /* keep last */ ATH10K_FW_FEATURE_COUNT, }; -- cgit v1.2.3 From 575fc89500d37839eb24ecd258982b24edefed6f Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 21 Jan 2016 14:13:26 +0100 Subject: ath10k: clean up cont frag desc init code This makes the code easier to extend and re-use. While at it fix _warn to _err. Other than that there are no functional changes. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_tx.c | 58 ++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index b3adadb5f824..28b8d7af8506 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -97,6 +97,41 @@ void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id) idr_remove(&htt->pending_tx, msdu_id); } +static void ath10k_htt_tx_free_cont_frag_desc(struct ath10k_htt *htt) +{ + size_t size; + + if (!htt->frag_desc.vaddr) + return; + + size = htt->max_num_pending_tx * sizeof(struct htt_msdu_ext_desc); + + dma_free_coherent(htt->ar->dev, + size, + htt->frag_desc.vaddr, + htt->frag_desc.paddr); +} + +static int ath10k_htt_tx_alloc_cont_frag_desc(struct ath10k_htt *htt) +{ + struct ath10k *ar = htt->ar; + size_t size; + + if (!ar->hw_params.continuous_frag_desc) + return 0; + + size = htt->max_num_pending_tx * sizeof(struct htt_msdu_ext_desc); + htt->frag_desc.vaddr = dma_alloc_coherent(ar->dev, size, + &htt->frag_desc.paddr, + GFP_KERNEL); + if (!htt->frag_desc.vaddr) { + ath10k_err(ar, "failed to alloc fragment desc memory\n"); + return -ENOMEM; + } + + return 0; +} + int ath10k_htt_tx_alloc(struct ath10k_htt *htt) { struct ath10k *ar = htt->ar; @@ -118,20 +153,12 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt) goto free_idr_pending_tx; } - if (!ar->hw_params.continuous_frag_desc) - goto skip_frag_desc_alloc; - - size = htt->max_num_pending_tx * sizeof(struct htt_msdu_ext_desc); - htt->frag_desc.vaddr = dma_alloc_coherent(ar->dev, size, - &htt->frag_desc.paddr, - GFP_KERNEL); - if (!htt->frag_desc.vaddr) { - ath10k_warn(ar, "failed to alloc fragment desc memory\n"); - ret = -ENOMEM; + ret = ath10k_htt_tx_alloc_cont_frag_desc(htt); + if (ret) { + ath10k_err(ar, "failed to alloc cont frag desc: %d\n", ret); goto free_txbuf; } -skip_frag_desc_alloc: return 0; free_txbuf: @@ -139,8 +166,10 @@ free_txbuf: sizeof(struct ath10k_htt_txbuf); dma_free_coherent(htt->ar->dev, size, htt->txbuf.vaddr, htt->txbuf.paddr); + free_idr_pending_tx: idr_destroy(&htt->pending_tx); + return ret; } @@ -174,12 +203,7 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt) htt->txbuf.paddr); } - if (htt->frag_desc.vaddr) { - size = htt->max_num_pending_tx * - sizeof(struct htt_msdu_ext_desc); - dma_free_coherent(htt->ar->dev, size, htt->frag_desc.vaddr, - htt->frag_desc.paddr); - } + ath10k_htt_tx_free_cont_frag_desc(htt); } void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) -- cgit v1.2.3 From 9b15873628050fe59ebbfae200be7d50ce5e1491 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 21 Jan 2016 14:13:27 +0100 Subject: ath10k: implement basic support for new tx path firmware This allows to use the new firmware which implements the new tx data path. Without this patch firmware supporting new tx path stops responding shortly after booting. This patch doesn't implement the entire pull-push logic available in the new firmware. This will be done in subsequent patches. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 8 +++ drivers/net/wireless/ath/ath10k/htt_rx.c | 4 +- drivers/net/wireless/ath/ath10k/htt_tx.c | 88 +++++++++++++++++++++++++++++--- 3 files changed, 91 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 0c5628dafabf..13391ea4422d 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1665,6 +1665,14 @@ struct ath10k_htt { dma_addr_t paddr; struct ath10k_htt_txbuf *vaddr; } txbuf; + + struct { + struct htt_q_state *vaddr; + dma_addr_t paddr; + u16 num_peers; + u16 num_tids; + enum htt_q_depth_type type; + } tx_q_state; }; #define RX_HTT_HDR_STATUS_LEN 64 diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 84abe4f25c73..cc957a625605 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2123,10 +2123,12 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) break; case HTT_T2H_MSG_TYPE_AGGR_CONF: break; - case HTT_T2H_MSG_TYPE_EN_STATS: case HTT_T2H_MSG_TYPE_TX_FETCH_IND: case HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM: case HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND: + /* TODO: Implement pull-push logic */ + break; + case HTT_T2H_MSG_TYPE_EN_STATS: default: ath10k_warn(ar, "htt event (%d) not handled\n", resp->hdr.msg_type); diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 28b8d7af8506..95acb727c068 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -132,6 +132,50 @@ static int ath10k_htt_tx_alloc_cont_frag_desc(struct ath10k_htt *htt) return 0; } +static void ath10k_htt_tx_free_txq(struct ath10k_htt *htt) +{ + struct ath10k *ar = htt->ar; + size_t size; + + if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features)) + return; + + size = sizeof(*htt->tx_q_state.vaddr); + + dma_unmap_single(ar->dev, htt->tx_q_state.paddr, size, DMA_TO_DEVICE); + kfree(htt->tx_q_state.vaddr); +} + +static int ath10k_htt_tx_alloc_txq(struct ath10k_htt *htt) +{ + struct ath10k *ar = htt->ar; + size_t size; + int ret; + + if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features)) + return 0; + + htt->tx_q_state.num_peers = HTT_TX_Q_STATE_NUM_PEERS; + htt->tx_q_state.num_tids = HTT_TX_Q_STATE_NUM_TIDS; + htt->tx_q_state.type = HTT_Q_DEPTH_TYPE_BYTES; + + size = sizeof(*htt->tx_q_state.vaddr); + htt->tx_q_state.vaddr = kzalloc(size, GFP_KERNEL); + if (!htt->tx_q_state.vaddr) + return -ENOMEM; + + htt->tx_q_state.paddr = dma_map_single(ar->dev, htt->tx_q_state.vaddr, + size, DMA_TO_DEVICE); + ret = dma_mapping_error(ar->dev, htt->tx_q_state.paddr); + if (ret) { + ath10k_warn(ar, "failed to dma map tx_q_state: %d\n", ret); + kfree(htt->tx_q_state.vaddr); + return -EIO; + } + + return 0; +} + int ath10k_htt_tx_alloc(struct ath10k_htt *htt) { struct ath10k *ar = htt->ar; @@ -159,8 +203,17 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt) goto free_txbuf; } + ret = ath10k_htt_tx_alloc_txq(htt); + if (ret) { + ath10k_err(ar, "failed to alloc txq: %d\n", ret); + goto free_frag_desc; + } + return 0; +free_frag_desc: + ath10k_htt_tx_free_cont_frag_desc(htt); + free_txbuf: size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf); @@ -203,6 +256,7 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt) htt->txbuf.paddr); } + ath10k_htt_tx_free_txq(htt); ath10k_htt_tx_free_cont_frag_desc(htt); } @@ -292,7 +346,9 @@ int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt) struct ath10k *ar = htt->ar; struct sk_buff *skb; struct htt_cmd *cmd; + struct htt_frag_desc_bank_cfg *cfg; int ret, size; + u8 info; if (!ar->hw_params.continuous_frag_desc) return 0; @@ -310,14 +366,30 @@ int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt) skb_put(skb, size); cmd = (struct htt_cmd *)skb->data; cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_FRAG_DESC_BANK_CFG; - cmd->frag_desc_bank_cfg.info = 0; - cmd->frag_desc_bank_cfg.num_banks = 1; - cmd->frag_desc_bank_cfg.desc_size = sizeof(struct htt_msdu_ext_desc); - cmd->frag_desc_bank_cfg.bank_base_addrs[0] = - __cpu_to_le32(htt->frag_desc.paddr); - cmd->frag_desc_bank_cfg.bank_id[0].bank_min_id = 0; - cmd->frag_desc_bank_cfg.bank_id[0].bank_max_id = - __cpu_to_le16(htt->max_num_pending_tx - 1); + + info = 0; + info |= SM(htt->tx_q_state.type, + HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE); + + if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features)) + info |= HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_VALID; + + cfg = &cmd->frag_desc_bank_cfg; + cfg->info = info; + cfg->num_banks = 1; + cfg->desc_size = sizeof(struct htt_msdu_ext_desc); + cfg->bank_base_addrs[0] = __cpu_to_le32(htt->frag_desc.paddr); + cfg->bank_id[0].bank_min_id = 0; + cfg->bank_id[0].bank_max_id = __cpu_to_le16(htt->max_num_pending_tx - + 1); + + cfg->q_state.paddr = cpu_to_le32(htt->tx_q_state.paddr); + cfg->q_state.num_peers = cpu_to_le16(htt->tx_q_state.num_peers); + cfg->q_state.num_tids = cpu_to_le16(htt->tx_q_state.num_tids); + cfg->q_state.record_size = HTT_TX_Q_STATE_ENTRY_SIZE; + cfg->q_state.record_multiplier = HTT_TX_Q_STATE_ENTRY_MULTIPLIER; + + ath10k_dbg(ar, ATH10K_DBG_HTT, "htt frag desc bank cmd\n"); ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb); if (ret) { -- cgit v1.2.3 From f52f517189dea69614bbee9ec5ab2fe366905b16 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:22 +0530 Subject: ath10k: make some of ath10k_pci_* func reusable Some of static functions present in pci.c file are reusable in ahb (qca4019) case. Remove static word for those reusable functions and have those function prototype declaration in pci.h file. So that, pci.h header file can be included in ahb module and reused. There is no functionality changes done in this patch. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 63 +++++++++++++++++------------------ drivers/net/wireless/ath/ath10k/pci.h | 32 ++++++++++++++++++ 2 files changed, 63 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index ee925c618535..956e548fd4a7 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -94,7 +94,6 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = { static void ath10k_pci_buffer_cleanup(struct ath10k *ar); static int ath10k_pci_cold_reset(struct ath10k *ar); static int ath10k_pci_safe_chip_reset(struct ath10k *ar); -static int ath10k_pci_wait_for_target_init(struct ath10k *ar); static int ath10k_pci_init_irq(struct ath10k *ar); static int ath10k_pci_deinit_irq(struct ath10k *ar); static int ath10k_pci_request_irq(struct ath10k *ar); @@ -687,7 +686,7 @@ void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val) ath10k_pci_write32(ar, PCIE_LOCAL_BASE_ADDRESS + addr, val); } -static bool ath10k_pci_irq_pending(struct ath10k *ar) +bool ath10k_pci_irq_pending(struct ath10k *ar) { u32 cause; @@ -700,7 +699,7 @@ static bool ath10k_pci_irq_pending(struct ath10k *ar) return false; } -static void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar) +void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar) { /* IMPORTANT: INTR_CLR register has to be set after * INTR_ENABLE is set to 0, otherwise interrupt can not be @@ -716,7 +715,7 @@ static void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar) PCIE_INTR_ENABLE_ADDRESS); } -static void ath10k_pci_enable_legacy_irq(struct ath10k *ar) +void ath10k_pci_enable_legacy_irq(struct ath10k *ar) { ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS, @@ -809,7 +808,7 @@ static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) } } -static void ath10k_pci_rx_post(struct ath10k *ar) +void ath10k_pci_rx_post(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int i; @@ -818,7 +817,7 @@ static void ath10k_pci_rx_post(struct ath10k *ar) ath10k_pci_rx_post_pipe(&ar_pci->pipe_info[i]); } -static void ath10k_pci_rx_replenish_retry(unsigned long ptr) +void ath10k_pci_rx_replenish_retry(unsigned long ptr) { struct ath10k *ar = (void *)ptr; @@ -1007,8 +1006,8 @@ static int __ath10k_pci_diag_read_hi(struct ath10k *ar, void *dest, #define ath10k_pci_diag_read_hi(ar, dest, src, len) \ __ath10k_pci_diag_read_hi(ar, dest, HI_ITEM(src), len) -static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, - const void *data, int nbytes) +int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, + const void *data, int nbytes) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ret = 0; @@ -1263,8 +1262,8 @@ static void ath10k_pci_htt_rx_cb(struct ath10k_ce_pipe *ce_state) ath10k_pci_process_rx_cb(ce_state, ath10k_pci_htt_rx_deliver); } -static int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, - struct ath10k_hif_sg_item *items, int n_items) +int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, + struct ath10k_hif_sg_item *items, int n_items) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci_pipe *pci_pipe = &ar_pci->pipe_info[pipe_id]; @@ -1332,13 +1331,13 @@ err: return err; } -static int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf, - size_t buf_len) +int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf, + size_t buf_len) { return ath10k_pci_diag_read_mem(ar, address, buf, buf_len); } -static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) +u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -1406,8 +1405,8 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar) queue_work(ar->workqueue, &ar->restart_work); } -static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, - int force) +void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, + int force) { ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif send complete check\n"); @@ -1432,7 +1431,7 @@ static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, ath10k_ce_per_engine_service(ar, pipe); } -static void ath10k_pci_kill_tasklet(struct ath10k *ar) +void ath10k_pci_kill_tasklet(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int i; @@ -1446,8 +1445,8 @@ static void ath10k_pci_kill_tasklet(struct ath10k *ar) del_timer_sync(&ar_pci->rx_post_retry); } -static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, - u8 *ul_pipe, u8 *dl_pipe) +int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, + u8 *ul_pipe, u8 *dl_pipe) { const struct service_to_pipe *entry; bool ul_set = false, dl_set = false; @@ -1491,8 +1490,8 @@ static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, return 0; } -static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, - u8 *ul_pipe, u8 *dl_pipe) +void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, + u8 *ul_pipe, u8 *dl_pipe) { ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif get default pipe\n"); @@ -1668,7 +1667,7 @@ static void ath10k_pci_buffer_cleanup(struct ath10k *ar) } } -static void ath10k_pci_ce_deinit(struct ath10k *ar) +void ath10k_pci_ce_deinit(struct ath10k *ar) { int i; @@ -1676,7 +1675,7 @@ static void ath10k_pci_ce_deinit(struct ath10k *ar) ath10k_ce_deinit_pipe(ar, i); } -static void ath10k_pci_flush(struct ath10k *ar) +void ath10k_pci_flush(struct ath10k *ar) { ath10k_pci_kill_tasklet(ar); ath10k_pci_buffer_cleanup(ar); @@ -1711,9 +1710,9 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) spin_unlock_irqrestore(&ar_pci->ps_lock, flags); } -static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, - void *req, u32 req_len, - void *resp, u32 *resp_len) +int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, + void *req, u32 req_len, + void *resp, u32 *resp_len) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci_pipe *pci_tx = &ar_pci->pipe_info[BMI_CE_NUM_TO_TARG]; @@ -1907,7 +1906,7 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar) return 1; } -static int ath10k_pci_init_config(struct ath10k *ar) +int ath10k_pci_init_config(struct ath10k *ar) { u32 interconnect_targ_addr; u32 pcie_state_targ_addr = 0; @@ -2071,7 +2070,7 @@ static void ath10k_pci_override_ce_config(struct ath10k *ar) target_service_to_ce_map_wlan[15].pipenum = __cpu_to_le32(1); } -static int ath10k_pci_alloc_pipes(struct ath10k *ar) +int ath10k_pci_alloc_pipes(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci_pipe *pipe; @@ -2102,7 +2101,7 @@ static int ath10k_pci_alloc_pipes(struct ath10k *ar) return 0; } -static void ath10k_pci_free_pipes(struct ath10k *ar) +void ath10k_pci_free_pipes(struct ath10k *ar) { int i; @@ -2110,7 +2109,7 @@ static void ath10k_pci_free_pipes(struct ath10k *ar) ath10k_ce_free_pipe(ar, i); } -static int ath10k_pci_init_pipes(struct ath10k *ar) +int ath10k_pci_init_pipes(struct ath10k *ar) { int i, ret; @@ -2453,7 +2452,7 @@ err_sleep: return ret; } -static void ath10k_pci_hif_power_down(struct ath10k *ar) +void ath10k_pci_hif_power_down(struct ath10k *ar) { ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power down\n"); @@ -2722,7 +2721,7 @@ static void ath10k_pci_free_irq(struct ath10k *ar) free_irq(ar_pci->pdev->irq + i, ar); } -static void ath10k_pci_init_irq_tasklets(struct ath10k *ar) +void ath10k_pci_init_irq_tasklets(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int i; @@ -2808,7 +2807,7 @@ static int ath10k_pci_deinit_irq(struct ath10k *ar) return 0; } -static int ath10k_pci_wait_for_target_init(struct ath10k *ar) +int ath10k_pci_wait_for_target_init(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); unsigned long timeout; diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index f91bf333cb75..ae76131aa081 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -253,6 +253,38 @@ u32 ath10k_pci_read32(struct ath10k *ar, u32 offset); u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr); u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr); +int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, + struct ath10k_hif_sg_item *items, int n_items); +int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf, + size_t buf_len); +int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, + const void *data, int nbytes); +int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, void *req, u32 req_len, + void *resp, u32 *resp_len); +int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, + u8 *ul_pipe, u8 *dl_pipe); +void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, u8 *ul_pipe, + u8 *dl_pipe); +void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, + int force); +u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe); +void ath10k_pci_hif_power_down(struct ath10k *ar); +int ath10k_pci_alloc_pipes(struct ath10k *ar); +void ath10k_pci_free_pipes(struct ath10k *ar); +void ath10k_pci_free_pipes(struct ath10k *ar); +void ath10k_pci_rx_replenish_retry(unsigned long ptr); +void ath10k_pci_ce_deinit(struct ath10k *ar); +void ath10k_pci_init_irq_tasklets(struct ath10k *ar); +void ath10k_pci_kill_tasklet(struct ath10k *ar); +int ath10k_pci_init_pipes(struct ath10k *ar); +int ath10k_pci_init_config(struct ath10k *ar); +void ath10k_pci_rx_post(struct ath10k *ar); +void ath10k_pci_flush(struct ath10k *ar); +void ath10k_pci_enable_legacy_irq(struct ath10k *ar); +bool ath10k_pci_irq_pending(struct ath10k *ar); +void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar); +int ath10k_pci_wait_for_target_init(struct ath10k *ar); + /* QCA6174 is known to have Tx/Rx issues when SOC_WAKE register is poked too * frequently. To avoid this put SoC to sleep after a very conservative grace * period. Adjust with great care. -- cgit v1.2.3 From 4ddb3299aa49ddeb40680d7427d3259d32aefa6d Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:23 +0530 Subject: ath10k: make ath10k_pci_read32/write32() ops more generic ath10k_pci_read32/write32() does work more specific to PCI by ensuring pci wake/sleep for every read and write. There is a plan to use most of stuff available in pci.c (irq stuff, copy engine, etc) for AHB case. Such kind of pci wake/sleep for every read/write is not required in AHB case (qca4019). All those reusable areas in pci.c and ce.c calls ath10k_pci_read32/write32() for low level read and write. In fact, ath10k_pci_read32/write32() should do what it does today for PCI case. But for AHB, it has to do differently. To make ath10k_pci_read32/write32() more generic, new function pointers are added in ar_pci for the function which does operation more close to the bus. Later, corresponding bus specific read and write function will be mapped to that. ath10k_pci_read32/write32() are changed to call directly those function pointers without worrying which bus underlying to it. Also, the function to get number of bank is changed in the same way. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 34 +++++++++++++++++++++++++++++++--- drivers/net/wireless/ath/ath10k/pci.h | 8 ++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 956e548fd4a7..c5f6604fa76d 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -619,7 +619,7 @@ static void ath10k_pci_sleep_sync(struct ath10k *ar) spin_unlock_irqrestore(&ar_pci->ps_lock, flags); } -void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value) +static void ath10k_bus_pci_write32(struct ath10k *ar, u32 offset, u32 value) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ret; @@ -641,7 +641,7 @@ void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value) ath10k_pci_sleep(ar); } -u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) +static u32 ath10k_bus_pci_read32(struct ath10k *ar, u32 offset) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); u32 val; @@ -666,6 +666,20 @@ u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) return val; } +inline void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + ar_pci->bus_ops->write32(ar, offset, value); +} + +inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + return ar_pci->bus_ops->read32(ar, offset); +} + u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr) { return ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + addr); @@ -1906,6 +1920,13 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar) return 1; } +static int ath10k_bus_get_num_banks(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + return ar_pci->bus_ops->get_num_banks(ar); +} + int ath10k_pci_init_config(struct ath10k *ar) { u32 interconnect_targ_addr; @@ -2017,7 +2038,7 @@ int ath10k_pci_init_config(struct ath10k *ar) /* first bank is switched to IRAM */ ealloc_value |= ((HI_EARLY_ALLOC_MAGIC << HI_EARLY_ALLOC_MAGIC_SHIFT) & HI_EARLY_ALLOC_MAGIC_MASK); - ealloc_value |= ((ath10k_pci_get_num_banks(ar) << + ealloc_value |= ((ath10k_bus_get_num_banks(ar) << HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) & HI_EARLY_ALLOC_IRAM_BANKS_MASK); @@ -2988,6 +3009,12 @@ static bool ath10k_pci_chip_is_supported(u32 dev_id, u32 chip_id) return false; } +static const struct ath10k_bus_ops ath10k_pci_bus_ops = { + .read32 = ath10k_bus_pci_read32, + .write32 = ath10k_bus_pci_write32, + .get_num_banks = ath10k_pci_get_num_banks, +}; + static int ath10k_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_dev) { @@ -3038,6 +3065,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ar_pci->ar = ar; ar->dev_id = pci_dev->device; ar_pci->pci_ps = pci_ps; + ar_pci->bus_ops = &ath10k_pci_bus_ops; ar->id.vendor = pdev->vendor; ar->id.device = pdev->device; diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index ae76131aa081..41f3faced84c 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -157,6 +157,12 @@ struct ath10k_pci_supp_chip { u32 rev_id; }; +struct ath10k_bus_ops { + u32 (*read32)(struct ath10k *ar, u32 offset); + void (*write32)(struct ath10k *ar, u32 offset, u32 value); + int (*get_num_banks)(struct ath10k *ar); +}; + struct ath10k_pci { struct pci_dev *pdev; struct device *dev; @@ -225,6 +231,8 @@ struct ath10k_pci { * on MMIO read/write. */ bool pci_ps; + + const struct ath10k_bus_ops *bus_ops; }; static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) -- cgit v1.2.3 From 90188f807f2a8bada8e165b932b56f7e03b0a9b9 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:24 +0530 Subject: ath10k: pull reusable code from pci probe and remove for ahb Some of the code present in ath10k_pci_{probe|remove} are reusable in ahb case too. To avoid code duplication, move reusable code to new functions. Later, those new functions can be called from ahb module's probe and exit functions. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 64 +++++++++++++++++++++++------------ drivers/net/wireless/ath/ath10k/pci.h | 2 ++ 2 files changed, 44 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index c5f6604fa76d..6ef878c1eebc 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -3009,6 +3009,37 @@ static bool ath10k_pci_chip_is_supported(u32 dev_id, u32 chip_id) return false; } +int ath10k_pci_setup_resource(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ret; + + spin_lock_init(&ar_pci->ce_lock); + spin_lock_init(&ar_pci->ps_lock); + + setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, + (unsigned long)ar); + + if (QCA_REV_6174(ar)) + ath10k_pci_override_ce_config(ar); + + ret = ath10k_pci_alloc_pipes(ar); + if (ret) { + ath10k_err(ar, "failed to allocate copy engine pipes: %d\n", + ret); + return ret; + } + + return 0; +} + +void ath10k_pci_release_resource(struct ath10k *ar) +{ + ath10k_pci_kill_tasklet(ar); + ath10k_pci_ce_deinit(ar); + ath10k_pci_free_pipes(ar); +} + static const struct ath10k_bus_ops ath10k_pci_bus_ops = { .read32 = ath10k_bus_pci_read32, .write32 = ath10k_bus_pci_write32, @@ -3072,34 +3103,25 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ar->id.subsystem_vendor = pdev->subsystem_vendor; ar->id.subsystem_device = pdev->subsystem_device; - spin_lock_init(&ar_pci->ce_lock); - spin_lock_init(&ar_pci->ps_lock); - - setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, - (unsigned long)ar); setup_timer(&ar_pci->ps_timer, ath10k_pci_ps_timer, (unsigned long)ar); - ret = ath10k_pci_claim(ar); + ret = ath10k_pci_setup_resource(ar); if (ret) { - ath10k_err(ar, "failed to claim device: %d\n", ret); + ath10k_err(ar, "failed to setup resource: %d\n", ret); goto err_core_destroy; } - if (QCA_REV_6174(ar)) - ath10k_pci_override_ce_config(ar); - - ret = ath10k_pci_alloc_pipes(ar); + ret = ath10k_pci_claim(ar); if (ret) { - ath10k_err(ar, "failed to allocate copy engine pipes: %d\n", - ret); - goto err_sleep; + ath10k_err(ar, "failed to claim device: %d\n", ret); + goto err_free_pipes; } ret = ath10k_pci_force_wake(ar); if (ret) { ath10k_warn(ar, "failed to wake up device : %d\n", ret); - goto err_free_pipes; + goto err_sleep; } ath10k_pci_ce_deinit(ar); @@ -3108,7 +3130,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ret = ath10k_pci_init_irq(ar); if (ret) { ath10k_err(ar, "failed to init irqs: %d\n", ret); - goto err_free_pipes; + goto err_sleep; } ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n", @@ -3154,13 +3176,13 @@ err_free_irq: err_deinit_irq: ath10k_pci_deinit_irq(ar); -err_free_pipes: - ath10k_pci_free_pipes(ar); - err_sleep: ath10k_pci_sleep_sync(ar); ath10k_pci_release(ar); +err_free_pipes: + ath10k_pci_free_pipes(ar); + err_core_destroy: ath10k_core_destroy(ar); @@ -3184,10 +3206,8 @@ static void ath10k_pci_remove(struct pci_dev *pdev) ath10k_core_unregister(ar); ath10k_pci_free_irq(ar); - ath10k_pci_kill_tasklet(ar); ath10k_pci_deinit_irq(ar); - ath10k_pci_ce_deinit(ar); - ath10k_pci_free_pipes(ar); + ath10k_pci_release_resource(ar); ath10k_pci_sleep_sync(ar); ath10k_pci_release(ar); ath10k_core_destroy(ar); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 41f3faced84c..fcfdbca8e55e 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -292,6 +292,8 @@ void ath10k_pci_enable_legacy_irq(struct ath10k *ar); bool ath10k_pci_irq_pending(struct ath10k *ar); void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar); int ath10k_pci_wait_for_target_init(struct ath10k *ar); +int ath10k_pci_setup_resource(struct ath10k *ar); +void ath10k_pci_release_resource(struct ath10k *ar); /* QCA6174 is known to have Tx/Rx issues when SOC_WAKE register is poked too * frequently. To avoid this put SoC to sleep after a very conservative grace -- cgit v1.2.3 From 0b523ced9a3cd05abf240e913b2d80e7d0fa3478 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:25 +0530 Subject: ath10k: add basic skeleton to support ahb qca4019 uses ahb instead of pci where it slightly differs in device enumeration, clock control, reset control, etc. Good thing is that ahb also uses copy engine for the data transaction. So, the most of the stuff implemented in pci.c/ce.c are reusable in ahb case too. Device enumeration in ahb case comes through platform driver/device model. All resource details like irq, memory map, clocks, etc for qca4019 can be fetched from of_node of platform device. Simply flow would look like, device tree => platform device (kernel) => platform driver (ath10k) Device tree entry will have all qca4019 resource details and the same info will be passed to kernel. Kernel will prepare new platform device for that entry and expose DT info to of_node in platform device. Later, ath10k would register platform driver with unique compatible name and then kernels binds to corresponding compatible entry & calls ath10k ahb probe functions. From there onwards, ath10k will take control of it and move forward. New bool flag CONFIG_ATH10K_AHB is added in Kconfig to conditionally enable ahb support in ath10k. On enabling this flag, ath10k_pci.ko will have ahb support. This patch adds only basic skeleton and few macros to support ahb in the context of qca4019. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/Kconfig | 6 +++ drivers/net/wireless/ath/ath10k/Makefile | 2 + drivers/net/wireless/ath/ath10k/ahb.c | 67 ++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 41 +++++++++++++++++++ drivers/net/wireless/ath/ath10k/core.h | 3 ++ drivers/net/wireless/ath/ath10k/debug.h | 1 + drivers/net/wireless/ath/ath10k/hw.h | 2 + drivers/net/wireless/ath/ath10k/pci.c | 8 ++++ drivers/net/wireless/ath/ath10k/pci.h | 1 + 9 files changed, 131 insertions(+) create mode 100644 drivers/net/wireless/ath/ath10k/ahb.c create mode 100644 drivers/net/wireless/ath/ath10k/ahb.h (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig index 03aa35f999a1..d7f207a6b0e0 100644 --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig @@ -15,6 +15,12 @@ config ATH10K_PCI ---help--- This module adds support for PCIE bus +config ATH10K_AHB + bool "Atheros ath10k AHB support" + depends on ATH10K_PCI && OF + ---help--- + This module adds support for AHB bus + config ATH10K_DEBUG bool "Atheros ath10k debugging" depends on ATH10K diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile index c04fb00e7930..930fadd940d8 100644 --- a/drivers/net/wireless/ath/ath10k/Makefile +++ b/drivers/net/wireless/ath/ath10k/Makefile @@ -25,5 +25,7 @@ obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o ath10k_pci-y += pci.o \ ce.o +ath10k_pci-$(CONFIG_ATH10K_AHB) += ahb.o + # for tracing framework to find trace.h CFLAGS_trace.o := -I$(src) diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c new file mode 100644 index 000000000000..129f4f4491d0 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016 Qualcomm Atheros, Inc. All rights reserved. + * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include "core.h" +#include "debug.h" +#include "ahb.h" + +static const struct of_device_id ath10k_ahb_of_match[] = { + /* TODO: enable this entry once everything in place. + * { .compatible = "qcom,ipq4019-wifi", + * .data = (void *)ATH10K_HW_QCA4019 }, + */ + { } +}; + +MODULE_DEVICE_TABLE(of, ath10k_ahb_of_match); + +static int ath10k_ahb_probe(struct platform_device *pdev) +{ + return 0; +} + +static int ath10k_ahb_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver ath10k_ahb_driver = { + .driver = { + .name = "ath10k_ahb", + .of_match_table = ath10k_ahb_of_match, + }, + .probe = ath10k_ahb_probe, + .remove = ath10k_ahb_remove, +}; + +int ath10k_ahb_init(void) +{ + int ret; + + printk(KERN_ERR "AHB support is still work in progress\n"); + + ret = platform_driver_register(&ath10k_ahb_driver); + if (ret) + printk(KERN_ERR "failed to register ath10k ahb driver: %d\n", + ret); + return ret; +} + +void ath10k_ahb_exit(void) +{ + platform_driver_unregister(&ath10k_ahb_driver); +} diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h new file mode 100644 index 000000000000..d1afe93f9329 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016 Qualcomm Atheros, Inc. All rights reserved. + * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _AHB_H_ +#define _AHB_H_ + +#include + +#ifdef CONFIG_ATH10K_AHB + +int ath10k_ahb_init(void); +void ath10k_ahb_exit(void); + +#else /* CONFIG_ATH10K_AHB */ + +static inline int ath10k_ahb_init(void) +{ + return 0; +} + +static inline void ath10k_ahb_exit(void) +{ +} + +#endif /* CONFIG_ATH10K_AHB */ + +#endif /* _AHB_H_ */ diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 5067a0ff4e89..2e411b5258c2 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -69,6 +69,7 @@ struct ath10k; enum ath10k_bus { ATH10K_BUS_PCI, + ATH10K_BUS_AHB, }; static inline const char *ath10k_bus_str(enum ath10k_bus bus) @@ -76,6 +77,8 @@ static inline const char *ath10k_bus_str(enum ath10k_bus bus) switch (bus) { case ATH10K_BUS_PCI: return "pci"; + case ATH10K_BUS_AHB: + return "ahb"; } return "unknown"; diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index f273478e2afb..6206edd7c49f 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -37,6 +37,7 @@ enum ath10k_debug_mask { ATH10K_DBG_TESTMODE = 0x00001000, ATH10K_DBG_WMI_PRINT = 0x00002000, ATH10K_DBG_PCI_PS = 0x00004000, + ATH10K_DBG_AHB = 0x00008000, ATH10K_DBG_ANY = 0xffffffff, }; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 0678831e8671..f8850155140a 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -200,6 +200,7 @@ enum ath10k_hw_rev { ATH10K_HW_QCA6174, ATH10K_HW_QCA99X0, ATH10K_HW_QCA9377, + ATH10K_HW_QCA4019, }; struct ath10k_hw_regs { @@ -253,6 +254,7 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, #define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174) #define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0) #define QCA_REV_9377(ar) ((ar)->hw_rev == ATH10K_HW_QCA9377) +#define QCA_REV_40XX(ar) ((ar)->hw_rev == ATH10K_HW_QCA4019) /* Known pecularities: * - raw appears in nwifi decap, raw and nwifi appear in ethernet decap diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 6ef878c1eebc..0e338b657210 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -851,6 +851,7 @@ static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr) 0x7ff) << 21; break; case ATH10K_HW_QCA99X0: + case ATH10K_HW_QCA4019: val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS); break; } @@ -1529,6 +1530,7 @@ static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) CORE_CTRL_ADDRESS, val); break; case ATH10K_HW_QCA99X0: + case ATH10K_HW_QCA4019: /* TODO: Find appropriate register configuration for QCA99X0 * to mask irq/MSI. */ @@ -1551,6 +1553,7 @@ static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar) CORE_CTRL_ADDRESS, val); break; case ATH10K_HW_QCA99X0: + case ATH10K_HW_QCA4019: /* TODO: Find appropriate register configuration for QCA99X0 * to unmask irq/MSI. */ @@ -3231,6 +3234,10 @@ static int __init ath10k_pci_init(void) printk(KERN_ERR "failed to register ath10k pci driver: %d\n", ret); + ret = ath10k_ahb_init(); + if (ret) + printk(KERN_ERR "ahb init failed: %d\n", ret); + return ret; } module_init(ath10k_pci_init); @@ -3238,6 +3245,7 @@ module_init(ath10k_pci_init); static void __exit ath10k_pci_exit(void) { pci_unregister_driver(&ath10k_pci_driver); + ath10k_ahb_exit(); } module_exit(ath10k_pci_exit); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index fcfdbca8e55e..c2d4a79aa29a 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -22,6 +22,7 @@ #include "hw.h" #include "ce.h" +#include "ahb.h" /* * maximum number of bytes that can be handled atomically by DiagRead/DiagWrite -- cgit v1.2.3 From 37a219a556b01b3236156ecf58717c1e41b552d9 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:26 +0530 Subject: ath10k: include qca4019 register map table New register table is added for qca4019 to tell about it's register mapping details. Nothing much other than this. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 4 ++++ drivers/net/wireless/ath/ath10k/hw.c | 39 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/hw.h | 2 ++ 3 files changed, 45 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 48a26206c5c1..1f4a27881936 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1980,6 +1980,10 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, ar->regs = &qca99x0_regs; ar->hw_values = &qca99x0_values; break; + case ATH10K_HW_QCA4019: + ar->regs = &qca4019_regs; + ar->hw_values = &qca4019_values; + break; default: ath10k_err(ar, "unsupported core hardware revision %d\n", hw_rev); diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index 7b84d08a5154..f544d48518c3 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -109,6 +109,38 @@ const struct ath10k_hw_regs qca99x0_regs = { .pcie_intr_clr_address = 0x00000010, }; +const struct ath10k_hw_regs qca4019_regs = { + .rtc_soc_base_address = 0x00080000, + .soc_core_base_address = 0x00082000, + .ce_wrapper_base_address = 0x0004d000, + .ce0_base_address = 0x0004a000, + .ce1_base_address = 0x0004a400, + .ce2_base_address = 0x0004a800, + .ce3_base_address = 0x0004ac00, + .ce4_base_address = 0x0004b000, + .ce5_base_address = 0x0004b400, + .ce6_base_address = 0x0004b800, + .ce7_base_address = 0x0004bc00, + /* qca4019 supports upto 12 copy engines. Since base address + * of ce8 to ce11 are not directly referred in the code, + * no need have them in separate members in this table. + * Copy Engine Address + * CE8 0x0004c000 + * CE9 0x0004c400 + * CE10 0x0004c800 + * CE11 0x0004cc00 + */ + .soc_reset_control_si0_rst_mask = 0x00000001, + .soc_reset_control_ce_rst_mask = 0x00000100, + .soc_chip_id_address = 0x000000ec, + .fw_indicator_address = 0x0004f00c, + .ce_wrap_intr_sum_host_msi_lsb = 0x0000000c, + .ce_wrap_intr_sum_host_msi_mask = 0x00fff000, + .pcie_intr_fw_mask = 0x00100000, + .pcie_intr_ce_mask_all = 0x000fff00, + .pcie_intr_clr_address = 0x00000010, +}; + const struct ath10k_hw_values qca988x_values = { .rtc_state_val_on = 3, .ce_count = 8, @@ -136,6 +168,13 @@ const struct ath10k_hw_values qca99x0_values = { .ce_desc_meta_data_lsb = 4, }; +const struct ath10k_hw_values qca4019_values = { + .ce_count = 12, + .num_target_ce_config_wlan = 10, + .ce_desc_meta_data_mask = 0xFFF0, + .ce_desc_meta_data_lsb = 4, +}; + void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev) { diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index f8850155140a..f57a37bfc9f6 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -233,6 +233,7 @@ struct ath10k_hw_regs { extern const struct ath10k_hw_regs qca988x_regs; extern const struct ath10k_hw_regs qca6174_regs; extern const struct ath10k_hw_regs qca99x0_regs; +extern const struct ath10k_hw_regs qca4019_regs; struct ath10k_hw_values { u32 rtc_state_val_on; @@ -246,6 +247,7 @@ struct ath10k_hw_values { extern const struct ath10k_hw_values qca988x_values; extern const struct ath10k_hw_values qca6174_values; extern const struct ath10k_hw_values qca99x0_values; +extern const struct ath10k_hw_values qca4019_values; void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev); -- cgit v1.2.3 From 7f8e79cdc2534559e3e38f5aee0b9f78e57e8fb3 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:27 +0530 Subject: ath10k: add helper functions in ahb.c for reg rd/wr qca4019 deals with below register memory region to control the clock, reset, etc. - Memory to control wifi core - gcc (outside of wifi) - tcsr (outside of wifi) Add new helper functions to perform read/write in above registers spaces. Actual ioremap for above registers are done in later patch. Struct ath10k_ahb is introduced to maintain ahb specific info and memory this struct will be allocated in the continuation of struct ath10k_pci (again, memory ath10k_ahb is allocated in the later patch). Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ahb.c | 55 +++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 7 +++++ drivers/net/wireless/ath/ath10k/pci.h | 6 ++++ 3 files changed, 68 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 129f4f4491d0..eab4b47237e0 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -17,6 +17,7 @@ #include #include "core.h" #include "debug.h" +#include "pci.h" #include "ahb.h" static const struct of_device_id ath10k_ahb_of_match[] = { @@ -29,6 +30,60 @@ static const struct of_device_id ath10k_ahb_of_match[] = { MODULE_DEVICE_TABLE(of, ath10k_ahb_of_match); +static inline struct ath10k_ahb *ath10k_ahb_priv(struct ath10k *ar) +{ + return &((struct ath10k_pci *)ar->drv_priv)->ahb[0]; +} + +static void ath10k_ahb_write32(struct ath10k *ar, u32 offset, u32 value) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + iowrite32(value, ar_ahb->mem + offset); +} + +static u32 ath10k_ahb_read32(struct ath10k *ar, u32 offset) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + return ioread32(ar_ahb->mem + offset); +} + +static u32 ath10k_ahb_gcc_read32(struct ath10k *ar, u32 offset) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + return ioread32(ar_ahb->gcc_mem + offset); +} + +static void ath10k_ahb_tcsr_write32(struct ath10k *ar, u32 offset, u32 value) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + iowrite32(value, ar_ahb->tcsr_mem + offset); +} + +static u32 ath10k_ahb_tcsr_read32(struct ath10k *ar, u32 offset) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + return ioread32(ar_ahb->tcsr_mem + offset); +} + +static u32 ath10k_ahb_soc_read32(struct ath10k *ar, u32 addr) +{ + return ath10k_ahb_read32(ar, RTC_SOC_BASE_ADDRESS + addr); +} + +static int ath10k_ahb_get_num_banks(struct ath10k *ar) +{ + if (ar->hw_rev == ATH10K_HW_QCA4019) + return 1; + + ath10k_warn(ar, "unknown number of banks, assuming 1\n"); + return 1; +} + static int ath10k_ahb_probe(struct platform_device *pdev) { return 0; diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h index d1afe93f9329..77d15af59c4a 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.h +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -20,6 +20,13 @@ #include +struct ath10k_ahb { + struct platform_device *pdev; + void __iomem *mem; + void __iomem *gcc_mem; + void __iomem *tcsr_mem; +}; + #ifdef CONFIG_ATH10K_AHB int ath10k_ahb_init(void); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index c2d4a79aa29a..249c73a69800 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -234,6 +234,12 @@ struct ath10k_pci { bool pci_ps; const struct ath10k_bus_ops *bus_ops; + + /* Keep this entry in the last, memory for struct ath10k_ahb is + * allocated (ahb support enabled case) in the continuation of + * this struct. + */ + struct ath10k_ahb ahb[0]; }; static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) -- cgit v1.2.3 From 8beff219c528d19c66e9d2c40fa868d7e7c2e36f Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:28 +0530 Subject: ath10k: add clock ctrl related functions in ahb pre qca4019 chipsets has/uses internal clock generator for the operation. But, qca4019 uses external clocks supplied from outside of target (ie, outside of wifi core). Three different clocks (cmd clock, ref clock, rtc clock) comes into picture in qca4019. All those clocks needs to configured with help of global clock controller (gcc) to make qca4019 functioning. Add functions for clock init/deinit, clock enable/disable in ahb. This is just a preparation, functions added in this patch will be used in later patches. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ahb.c | 123 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 4 ++ 2 files changed, 127 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index eab4b47237e0..11185c0dc6ad 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -15,6 +15,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include +#include #include "core.h" #include "debug.h" #include "pci.h" @@ -84,6 +85,128 @@ static int ath10k_ahb_get_num_banks(struct ath10k *ar) return 1; } +static int ath10k_ahb_clock_init(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + struct device *dev; + int ret; + + dev = &ar_ahb->pdev->dev; + + ar_ahb->cmd_clk = clk_get(dev, "wifi_wcss_cmd"); + if (IS_ERR_OR_NULL(ar_ahb->cmd_clk)) { + ath10k_err(ar, "failed to get cmd clk: %ld\n", + PTR_ERR(ar_ahb->cmd_clk)); + ret = ar_ahb->cmd_clk ? PTR_ERR(ar_ahb->cmd_clk) : -ENODEV; + goto out; + } + + ar_ahb->ref_clk = clk_get(dev, "wifi_wcss_ref"); + if (IS_ERR_OR_NULL(ar_ahb->ref_clk)) { + ath10k_err(ar, "failed to get ref clk: %ld\n", + PTR_ERR(ar_ahb->ref_clk)); + ret = ar_ahb->ref_clk ? PTR_ERR(ar_ahb->ref_clk) : -ENODEV; + goto err_cmd_clk_put; + } + + ar_ahb->rtc_clk = clk_get(dev, "wifi_wcss_rtc"); + if (IS_ERR_OR_NULL(ar_ahb->rtc_clk)) { + ath10k_err(ar, "failed to get rtc clk: %ld\n", + PTR_ERR(ar_ahb->rtc_clk)); + ret = ar_ahb->rtc_clk ? PTR_ERR(ar_ahb->rtc_clk) : -ENODEV; + goto err_ref_clk_put; + } + + return 0; + +err_ref_clk_put: + clk_put(ar_ahb->ref_clk); + +err_cmd_clk_put: + clk_put(ar_ahb->cmd_clk); + +out: + return ret; +} + +static void ath10k_ahb_clock_deinit(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + if (!IS_ERR_OR_NULL(ar_ahb->cmd_clk)) + clk_put(ar_ahb->cmd_clk); + + if (!IS_ERR_OR_NULL(ar_ahb->ref_clk)) + clk_put(ar_ahb->ref_clk); + + if (!IS_ERR_OR_NULL(ar_ahb->rtc_clk)) + clk_put(ar_ahb->rtc_clk); + + ar_ahb->cmd_clk = NULL; + ar_ahb->ref_clk = NULL; + ar_ahb->rtc_clk = NULL; +} + +static int ath10k_ahb_clock_enable(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + struct device *dev; + int ret; + + dev = &ar_ahb->pdev->dev; + + if (IS_ERR_OR_NULL(ar_ahb->cmd_clk) || + IS_ERR_OR_NULL(ar_ahb->ref_clk) || + IS_ERR_OR_NULL(ar_ahb->rtc_clk)) { + ath10k_err(ar, "clock(s) is/are not initialized\n"); + ret = -EIO; + goto out; + } + + ret = clk_prepare_enable(ar_ahb->cmd_clk); + if (ret) { + ath10k_err(ar, "failed to enable cmd clk: %d\n", ret); + goto out; + } + + ret = clk_prepare_enable(ar_ahb->ref_clk); + if (ret) { + ath10k_err(ar, "failed to enable ref clk: %d\n", ret); + goto err_cmd_clk_disable; + } + + ret = clk_prepare_enable(ar_ahb->rtc_clk); + if (ret) { + ath10k_err(ar, "failed to enable rtc clk: %d\n", ret); + goto err_ref_clk_disable; + } + + return 0; + +err_ref_clk_disable: + clk_disable_unprepare(ar_ahb->ref_clk); + +err_cmd_clk_disable: + clk_disable_unprepare(ar_ahb->cmd_clk); + +out: + return ret; +} + +static void ath10k_ahb_clock_disable(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + if (!IS_ERR_OR_NULL(ar_ahb->cmd_clk)) + clk_disable_unprepare(ar_ahb->cmd_clk); + + if (!IS_ERR_OR_NULL(ar_ahb->ref_clk)) + clk_disable_unprepare(ar_ahb->ref_clk); + + if (!IS_ERR_OR_NULL(ar_ahb->rtc_clk)) + clk_disable_unprepare(ar_ahb->rtc_clk); +} + static int ath10k_ahb_probe(struct platform_device *pdev) { return 0; diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h index 77d15af59c4a..753b4330075a 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.h +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -25,6 +25,10 @@ struct ath10k_ahb { void __iomem *mem; void __iomem *gcc_mem; void __iomem *tcsr_mem; + + struct clk *cmd_clk; + struct clk *ref_clk; + struct clk *rtc_clk; }; #ifdef CONFIG_ATH10K_AHB -- cgit v1.2.3 From 14854bfd9daaa20778db64f224a957c2abaab6fe Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:29 +0530 Subject: ath10k: add reset ctrl related functions in ahb To perform reset on qca4019 wifi, multiple reset lines needs to be toggled in a sequence with help of reset controller support in the kernel. This patch adds functions to reset control init/deinit and release reset. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/Kconfig | 2 +- drivers/net/wireless/ath/ath10k/ahb.c | 138 ++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 6 ++ 3 files changed, 145 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig index d7f207a6b0e0..db1ca629cbd6 100644 --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig @@ -17,7 +17,7 @@ config ATH10K_PCI config ATH10K_AHB bool "Atheros ath10k AHB support" - depends on ATH10K_PCI && OF + depends on ATH10K_PCI && OF && RESET_CONTROLLER ---help--- This module adds support for AHB bus diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 11185c0dc6ad..d1f197220e30 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -16,6 +16,7 @@ */ #include #include +#include #include "core.h" #include "debug.h" #include "pci.h" @@ -207,6 +208,143 @@ static void ath10k_ahb_clock_disable(struct ath10k *ar) clk_disable_unprepare(ar_ahb->rtc_clk); } +static int ath10k_ahb_rst_ctrl_init(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + struct device *dev; + int ret; + + dev = &ar_ahb->pdev->dev; + + ar_ahb->core_cold_rst = reset_control_get(dev, "wifi_core_cold"); + if (IS_ERR_OR_NULL(ar_ahb->core_cold_rst)) { + ath10k_err(ar, "failed to get core cold rst ctrl: %ld\n", + PTR_ERR(ar_ahb->core_cold_rst)); + ret = ar_ahb->core_cold_rst ? + PTR_ERR(ar_ahb->core_cold_rst) : -ENODEV; + goto out; + } + + ar_ahb->radio_cold_rst = reset_control_get(dev, "wifi_radio_cold"); + if (IS_ERR_OR_NULL(ar_ahb->radio_cold_rst)) { + ath10k_err(ar, "failed to get radio cold rst ctrl: %ld\n", + PTR_ERR(ar_ahb->radio_cold_rst)); + ret = ar_ahb->radio_cold_rst ? + PTR_ERR(ar_ahb->radio_cold_rst) : -ENODEV; + goto err_core_cold_rst_put; + } + + ar_ahb->radio_warm_rst = reset_control_get(dev, "wifi_radio_warm"); + if (IS_ERR_OR_NULL(ar_ahb->radio_warm_rst)) { + ath10k_err(ar, "failed to get radio warm rst ctrl: %ld\n", + PTR_ERR(ar_ahb->radio_warm_rst)); + ret = ar_ahb->radio_warm_rst ? + PTR_ERR(ar_ahb->radio_warm_rst) : -ENODEV; + goto err_radio_cold_rst_put; + } + + ar_ahb->radio_srif_rst = reset_control_get(dev, "wifi_radio_srif"); + if (IS_ERR_OR_NULL(ar_ahb->radio_srif_rst)) { + ath10k_err(ar, "failed to get radio srif rst ctrl: %ld\n", + PTR_ERR(ar_ahb->radio_srif_rst)); + ret = ar_ahb->radio_srif_rst ? + PTR_ERR(ar_ahb->radio_srif_rst) : -ENODEV; + goto err_radio_warm_rst_put; + } + + ar_ahb->cpu_init_rst = reset_control_get(dev, "wifi_cpu_init"); + if (IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) { + ath10k_err(ar, "failed to get cpu init rst ctrl: %ld\n", + PTR_ERR(ar_ahb->cpu_init_rst)); + ret = ar_ahb->cpu_init_rst ? + PTR_ERR(ar_ahb->cpu_init_rst) : -ENODEV; + goto err_radio_srif_rst_put; + } + + return 0; + +err_radio_srif_rst_put: + reset_control_put(ar_ahb->radio_srif_rst); + +err_radio_warm_rst_put: + reset_control_put(ar_ahb->radio_warm_rst); + +err_radio_cold_rst_put: + reset_control_put(ar_ahb->radio_cold_rst); + +err_core_cold_rst_put: + reset_control_put(ar_ahb->core_cold_rst); + +out: + return ret; +} + +static void ath10k_ahb_rst_ctrl_deinit(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + if (!IS_ERR_OR_NULL(ar_ahb->core_cold_rst)) + reset_control_put(ar_ahb->core_cold_rst); + + if (!IS_ERR_OR_NULL(ar_ahb->radio_cold_rst)) + reset_control_put(ar_ahb->radio_cold_rst); + + if (!IS_ERR_OR_NULL(ar_ahb->radio_warm_rst)) + reset_control_put(ar_ahb->radio_warm_rst); + + if (!IS_ERR_OR_NULL(ar_ahb->radio_srif_rst)) + reset_control_put(ar_ahb->radio_srif_rst); + + if (!IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) + reset_control_put(ar_ahb->cpu_init_rst); + + ar_ahb->core_cold_rst = NULL; + ar_ahb->radio_cold_rst = NULL; + ar_ahb->radio_warm_rst = NULL; + ar_ahb->radio_srif_rst = NULL; + ar_ahb->cpu_init_rst = NULL; +} + +static int ath10k_ahb_release_reset(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + int ret; + + if (IS_ERR_OR_NULL(ar_ahb->radio_cold_rst) || + IS_ERR_OR_NULL(ar_ahb->radio_warm_rst) || + IS_ERR_OR_NULL(ar_ahb->radio_srif_rst) || + IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) { + ath10k_err(ar, "rst ctrl(s) is/are not initialized\n"); + return -EINVAL; + } + + ret = reset_control_deassert(ar_ahb->radio_cold_rst); + if (ret) { + ath10k_err(ar, "failed to deassert radio cold rst: %d\n", ret); + return ret; + } + + ret = reset_control_deassert(ar_ahb->radio_warm_rst); + if (ret) { + ath10k_err(ar, "failed to deassert radio warm rst: %d\n", ret); + return ret; + } + + ret = reset_control_deassert(ar_ahb->radio_srif_rst); + if (ret) { + ath10k_err(ar, "failed to deassert radio srif rst: %d\n", ret); + return ret; + } + + ret = reset_control_deassert(ar_ahb->cpu_init_rst); + if (ret) { + ath10k_err(ar, "failed to deassert cpu init rst: %d\n", ret); + return ret; + } + + return 0; +} + static int ath10k_ahb_probe(struct platform_device *pdev) { return 0; diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h index 753b4330075a..2904b7bc9459 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.h +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -29,6 +29,12 @@ struct ath10k_ahb { struct clk *cmd_clk; struct clk *ref_clk; struct clk *rtc_clk; + + struct reset_control *core_cold_rst; + struct reset_control *radio_cold_rst; + struct reset_control *radio_warm_rst; + struct reset_control *radio_srif_rst; + struct reset_control *cpu_init_rst; }; #ifdef CONFIG_ATH10K_AHB -- cgit v1.2.3 From 133df0f849bc7b5448c62272986af626f2bda6bd Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:30 +0530 Subject: ath10k: add chip and bus halt logic in ahb Add function to perform chip halt sequence and function to halt axi bus in ahb module. Mainly used in the scenario like driver unload. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ahb.c | 113 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 15 +++++ 2 files changed, 128 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index d1f197220e30..230507890fbf 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -345,6 +345,119 @@ static int ath10k_ahb_release_reset(struct ath10k *ar) return 0; } +static void ath10k_ahb_halt_axi_bus(struct ath10k *ar, u32 haltreq_reg, + u32 haltack_reg) +{ + unsigned long timeout; + u32 val; + + /* Issue halt axi bus request */ + val = ath10k_ahb_tcsr_read32(ar, haltreq_reg); + val |= AHB_AXI_BUS_HALT_REQ; + ath10k_ahb_tcsr_write32(ar, haltreq_reg, val); + + /* Wait for axi bus halted ack */ + timeout = jiffies + msecs_to_jiffies(ATH10K_AHB_AXI_BUS_HALT_TIMEOUT); + do { + val = ath10k_ahb_tcsr_read32(ar, haltack_reg); + if (val & AHB_AXI_BUS_HALT_ACK) + break; + + mdelay(1); + } while (time_before(jiffies, timeout)); + + if (!(val & AHB_AXI_BUS_HALT_ACK)) { + ath10k_err(ar, "failed to halt axi bus: %d\n", val); + return; + } + + ath10k_dbg(ar, ATH10K_DBG_AHB, "axi bus halted\n"); +} + +static void ath10k_ahb_halt_chip(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + u32 core_id, glb_cfg_reg, haltreq_reg, haltack_reg; + u32 val; + int ret; + + if (IS_ERR_OR_NULL(ar_ahb->core_cold_rst) || + IS_ERR_OR_NULL(ar_ahb->radio_cold_rst) || + IS_ERR_OR_NULL(ar_ahb->radio_warm_rst) || + IS_ERR_OR_NULL(ar_ahb->radio_srif_rst) || + IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) { + ath10k_err(ar, "rst ctrl(s) is/are not initialized\n"); + return; + } + + core_id = ath10k_ahb_read32(ar, ATH10K_AHB_WLAN_CORE_ID_REG); + + switch (core_id) { + case 0: + glb_cfg_reg = ATH10K_AHB_TCSR_WIFI0_GLB_CFG; + haltreq_reg = ATH10K_AHB_TCSR_WCSS0_HALTREQ; + haltack_reg = ATH10K_AHB_TCSR_WCSS0_HALTACK; + break; + case 1: + glb_cfg_reg = ATH10K_AHB_TCSR_WIFI1_GLB_CFG; + haltreq_reg = ATH10K_AHB_TCSR_WCSS1_HALTREQ; + haltack_reg = ATH10K_AHB_TCSR_WCSS1_HALTACK; + break; + default: + ath10k_err(ar, "invalid core id %d found, skipping reset sequence\n", + core_id); + return; + } + + ath10k_ahb_halt_axi_bus(ar, haltreq_reg, haltack_reg); + + val = ath10k_ahb_tcsr_read32(ar, glb_cfg_reg); + val |= TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK; + ath10k_ahb_tcsr_write32(ar, glb_cfg_reg, val); + + ret = reset_control_assert(ar_ahb->core_cold_rst); + if (ret) + ath10k_err(ar, "failed to assert core cold rst: %d\n", ret); + msleep(1); + + ret = reset_control_assert(ar_ahb->radio_cold_rst); + if (ret) + ath10k_err(ar, "failed to assert radio cold rst: %d\n", ret); + msleep(1); + + ret = reset_control_assert(ar_ahb->radio_warm_rst); + if (ret) + ath10k_err(ar, "failed to assert radio warm rst: %d\n", ret); + msleep(1); + + ret = reset_control_assert(ar_ahb->radio_srif_rst); + if (ret) + ath10k_err(ar, "failed to assert radio srif rst: %d\n", ret); + msleep(1); + + ret = reset_control_assert(ar_ahb->cpu_init_rst); + if (ret) + ath10k_err(ar, "failed to assert cpu init rst: %d\n", ret); + msleep(10); + + /* Clear halt req and core clock disable req before + * deasserting wifi core reset. + */ + val = ath10k_ahb_tcsr_read32(ar, haltreq_reg); + val &= ~AHB_AXI_BUS_HALT_REQ; + ath10k_ahb_tcsr_write32(ar, haltreq_reg, val); + + val = ath10k_ahb_tcsr_read32(ar, glb_cfg_reg); + val &= ~TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK; + ath10k_ahb_tcsr_write32(ar, glb_cfg_reg, val); + + ret = reset_control_deassert(ar_ahb->core_cold_rst); + if (ret) + ath10k_err(ar, "failed to deassert core cold rst: %d\n", ret); + + ath10k_dbg(ar, ATH10K_DBG_AHB, "core %d reset done\n", core_id); +} + static int ath10k_ahb_probe(struct platform_device *pdev) { return 0; diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h index 2904b7bc9459..4761eeb475d6 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.h +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -39,6 +39,21 @@ struct ath10k_ahb { #ifdef CONFIG_ATH10K_AHB +#define ATH10K_AHB_WLAN_CORE_ID_REG 0x82030 + +#define ATH10K_AHB_TCSR_WIFI0_GLB_CFG 0x49000 +#define ATH10K_AHB_TCSR_WIFI1_GLB_CFG 0x49004 +#define TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK BIT(25) + +#define ATH10K_AHB_TCSR_WCSS0_HALTREQ 0x52000 +#define ATH10K_AHB_TCSR_WCSS1_HALTREQ 0x52010 +#define ATH10K_AHB_TCSR_WCSS0_HALTACK 0x52004 +#define ATH10K_AHB_TCSR_WCSS1_HALTACK 0x52014 + +#define ATH10K_AHB_AXI_BUS_HALT_TIMEOUT 10 /* msec */ +#define AHB_AXI_BUS_HALT_REQ 1 +#define AHB_AXI_BUS_HALT_ACK 1 + int ath10k_ahb_init(void); void ath10k_ahb_exit(void); -- cgit v1.2.3 From 1c44fcb9234c80bbf9e4043deab8492e1c0dcf99 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:31 +0530 Subject: ath10k: include irq related functions in ahb Add irq related functions to register,handle,release,disable interrupt. qca4019 supports msi interrupt, but it has the problem. Until the issue gets sorted out, only legacy interrupt model is enabled and used. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ahb.c | 44 +++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 2 ++ 2 files changed, 46 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 230507890fbf..29d0b6c6b35c 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -458,6 +458,50 @@ static void ath10k_ahb_halt_chip(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_AHB, "core %d reset done\n", core_id); } +static irqreturn_t ath10k_ahb_interrupt_handler(int irq, void *arg) +{ + struct ath10k *ar = arg; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + if (!ath10k_pci_irq_pending(ar)) + return IRQ_NONE; + + ath10k_pci_disable_and_clear_legacy_irq(ar); + tasklet_schedule(&ar_pci->intr_tq); + + return IRQ_HANDLED; +} + +static int ath10k_ahb_request_irq_legacy(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + int ret; + + ret = request_irq(ar_ahb->irq, + ath10k_ahb_interrupt_handler, + IRQF_SHARED, "ath10k_ahb", ar); + if (ret) { + ath10k_warn(ar, "failed to request legacy irq %d: %d\n", + ar_ahb->irq, ret); + return ret; + } + + return 0; +} + +static void ath10k_ahb_release_irq_legacy(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + free_irq(ar_ahb->irq, ar); +} + +static void ath10k_ahb_irq_disable(struct ath10k *ar) +{ + ath10k_ce_disable_interrupts(ar); + ath10k_pci_disable_and_clear_legacy_irq(ar); +} + static int ath10k_ahb_probe(struct platform_device *pdev) { return 0; diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h index 4761eeb475d6..97c40e47dc02 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.h +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -26,6 +26,8 @@ struct ath10k_ahb { void __iomem *gcc_mem; void __iomem *tcsr_mem; + int irq; + struct clk *cmd_clk; struct clk *ref_clk; struct clk *rtc_clk; -- cgit v1.2.3 From 704dc4e36769218145d30c41e81a5fbfed3977c7 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:32 +0530 Subject: ath10k: add resource init and deinit in ahb Add function to gather resources required for qca4019 to operate (memory, irq, dma setting, clock init , rest control init) and function release those resources when it's not needed. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ahb.c | 122 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 7 ++ 2 files changed, 129 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 29d0b6c6b35c..d83a864515a2 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -15,6 +15,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include +#include +#include #include #include #include "core.h" @@ -502,6 +504,126 @@ static void ath10k_ahb_irq_disable(struct ath10k *ar) ath10k_pci_disable_and_clear_legacy_irq(ar); } +static int ath10k_ahb_resource_init(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + struct platform_device *pdev; + struct device *dev; + struct resource *res; + int ret; + + pdev = ar_ahb->pdev; + dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ath10k_err(ar, "failed to get memory resource\n"); + ret = -ENXIO; + goto out; + } + + ar_ahb->mem = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(ar_ahb->mem)) { + ath10k_err(ar, "mem ioremap error\n"); + ret = PTR_ERR(ar_ahb->mem); + goto out; + } + + ar_ahb->mem_len = resource_size(res); + + ar_ahb->gcc_mem = ioremap_nocache(ATH10K_GCC_REG_BASE, + ATH10K_GCC_REG_SIZE); + if (!ar_ahb->gcc_mem) { + ath10k_err(ar, "gcc mem ioremap error\n"); + ret = -ENOMEM; + goto err_mem_unmap; + } + + ar_ahb->tcsr_mem = ioremap_nocache(ATH10K_TCSR_REG_BASE, + ATH10K_TCSR_REG_SIZE); + if (!ar_ahb->tcsr_mem) { + ath10k_err(ar, "tcsr mem ioremap error\n"); + ret = -ENOMEM; + goto err_gcc_mem_unmap; + } + + ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); + if (ret) { + ath10k_err(ar, "failed to set 32-bit dma mask: %d\n", ret); + goto err_tcsr_mem_unmap; + } + + ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); + if (ret) { + ath10k_err(ar, "failed to set 32-bit consistent dma: %d\n", + ret); + goto err_tcsr_mem_unmap; + } + + ret = ath10k_ahb_clock_init(ar); + if (ret) + goto err_tcsr_mem_unmap; + + ret = ath10k_ahb_rst_ctrl_init(ar); + if (ret) + goto err_clock_deinit; + + ar_ahb->irq = platform_get_irq_byname(pdev, "legacy"); + if (ar_ahb->irq < 0) { + ath10k_err(ar, "failed to get irq number: %d\n", ar_ahb->irq); + goto err_clock_deinit; + } + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "irq: %d\n", ar_ahb->irq); + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "mem: 0x%p mem_len: %lu gcc mem: 0x%p tcsr_mem: 0x%p\n", + ar_ahb->mem, ar_ahb->mem_len, + ar_ahb->gcc_mem, ar_ahb->tcsr_mem); + return 0; + +err_clock_deinit: + ath10k_ahb_clock_deinit(ar); + +err_tcsr_mem_unmap: + iounmap(ar_ahb->tcsr_mem); + +err_gcc_mem_unmap: + ar_ahb->tcsr_mem = NULL; + iounmap(ar_ahb->gcc_mem); + +err_mem_unmap: + ar_ahb->gcc_mem = NULL; + devm_iounmap(&pdev->dev, ar_ahb->mem); + +out: + ar_ahb->mem = NULL; + return ret; +} + +static void ath10k_ahb_resource_deinit(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + struct device *dev; + + dev = &ar_ahb->pdev->dev; + + if (ar_ahb->mem) + devm_iounmap(dev, ar_ahb->mem); + + if (ar_ahb->gcc_mem) + iounmap(ar_ahb->gcc_mem); + + if (ar_ahb->tcsr_mem) + iounmap(ar_ahb->tcsr_mem); + + ar_ahb->mem = NULL; + ar_ahb->gcc_mem = NULL; + ar_ahb->tcsr_mem = NULL; + + ath10k_ahb_clock_deinit(ar); + ath10k_ahb_rst_ctrl_deinit(ar); +} + static int ath10k_ahb_probe(struct platform_device *pdev) { return 0; diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h index 97c40e47dc02..5bd01b49132b 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.h +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -23,6 +23,7 @@ struct ath10k_ahb { struct platform_device *pdev; void __iomem *mem; + unsigned long mem_len; void __iomem *gcc_mem; void __iomem *tcsr_mem; @@ -41,6 +42,12 @@ struct ath10k_ahb { #ifdef CONFIG_ATH10K_AHB +#define ATH10K_GCC_REG_BASE 0x1800000 +#define ATH10K_GCC_REG_SIZE 0x60000 + +#define ATH10K_TCSR_REG_BASE 0x1900000 +#define ATH10K_TCSR_REG_SIZE 0x80000 + #define ATH10K_AHB_WLAN_CORE_ID_REG 0x82030 #define ATH10K_AHB_TCSR_WIFI0_GLB_CFG 0x49000 -- cgit v1.2.3 From 0d87c9208a17cb82fed66e29180078ab603086ea Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:33 +0530 Subject: ath10k: expose hif ops for ahb Like how pci.c exposes hif ops for the bus specific operation, expose similar hif ops table for ahb with all required functions linked to it. Many ath10k_pci_* functions are reused here in hif ops table. If something is not sharable, new functions are added for ahb and linked to hif ops table. Finally, make ath10k_ahb_probe/remove() to perform what is expected out of it. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ahb.c | 271 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 5 + drivers/net/wireless/ath/ath10k/hw.h | 1 + 3 files changed, 277 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index d83a864515a2..bd62bc19e758 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -624,13 +624,284 @@ static void ath10k_ahb_resource_deinit(struct ath10k *ar) ath10k_ahb_rst_ctrl_deinit(ar); } +static int ath10k_ahb_prepare_device(struct ath10k *ar) +{ + u32 val; + int ret; + + ret = ath10k_ahb_clock_enable(ar); + if (ret) { + ath10k_err(ar, "failed to enable clocks\n"); + return ret; + } + + /* Clock for the target is supplied from outside of target (ie, + * external clock module controlled by the host). Target needs + * to know what frequency target cpu is configured which is needed + * for target internal use. Read target cpu frequency info from + * gcc register and write into target's scratch register where + * target expects this information. + */ + val = ath10k_ahb_gcc_read32(ar, ATH10K_AHB_GCC_FEPLL_PLL_DIV); + ath10k_ahb_write32(ar, ATH10K_AHB_WIFI_SCRATCH_5_REG, val); + + ret = ath10k_ahb_release_reset(ar); + if (ret) + goto err_clk_disable; + + ath10k_ahb_irq_disable(ar); + + ath10k_ahb_write32(ar, FW_INDICATOR_ADDRESS, FW_IND_HOST_READY); + + ret = ath10k_pci_wait_for_target_init(ar); + if (ret) + goto err_halt_chip; + + return 0; + +err_halt_chip: + ath10k_ahb_halt_chip(ar); + +err_clk_disable: + ath10k_ahb_clock_disable(ar); + + return ret; +} + +static int ath10k_ahb_chip_reset(struct ath10k *ar) +{ + int ret; + + ath10k_ahb_halt_chip(ar); + ath10k_ahb_clock_disable(ar); + + ret = ath10k_ahb_prepare_device(ar); + if (ret) + return ret; + + return 0; +} + +static int ath10k_ahb_wake_target_cpu(struct ath10k *ar) +{ + u32 addr, val; + + addr = SOC_CORE_BASE_ADDRESS | CORE_CTRL_ADDRESS; + val = ath10k_ahb_read32(ar, addr); + val |= ATH10K_AHB_CORE_CTRL_CPU_INTR_MASK; + ath10k_ahb_write32(ar, addr, val); + + return 0; +} + +static int ath10k_ahb_hif_start(struct ath10k *ar) +{ + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif start\n"); + + ath10k_ce_enable_interrupts(ar); + ath10k_pci_enable_legacy_irq(ar); + + ath10k_pci_rx_post(ar); + + return 0; +} + +static void ath10k_ahb_hif_stop(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif stop\n"); + + ath10k_ahb_irq_disable(ar); + synchronize_irq(ar_ahb->irq); + + ath10k_pci_flush(ar); +} + +static int ath10k_ahb_hif_power_up(struct ath10k *ar) +{ + int ret; + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif power up\n"); + + ret = ath10k_ahb_chip_reset(ar); + if (ret) { + ath10k_err(ar, "failed to reset chip: %d\n", ret); + goto out; + } + + ret = ath10k_pci_init_pipes(ar); + if (ret) { + ath10k_err(ar, "failed to initialize CE: %d\n", ret); + goto out; + } + + ret = ath10k_pci_init_config(ar); + if (ret) { + ath10k_err(ar, "failed to setup init config: %d\n", ret); + goto err_ce_deinit; + } + + ret = ath10k_ahb_wake_target_cpu(ar); + if (ret) { + ath10k_err(ar, "could not wake up target CPU: %d\n", ret); + goto err_ce_deinit; + } + + return 0; + +err_ce_deinit: + ath10k_pci_ce_deinit(ar); +out: + return ret; +} + +static const struct ath10k_hif_ops ath10k_ahb_hif_ops = { + .tx_sg = ath10k_pci_hif_tx_sg, + .diag_read = ath10k_pci_hif_diag_read, + .diag_write = ath10k_pci_diag_write_mem, + .exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg, + .start = ath10k_ahb_hif_start, + .stop = ath10k_ahb_hif_stop, + .map_service_to_pipe = ath10k_pci_hif_map_service_to_pipe, + .get_default_pipe = ath10k_pci_hif_get_default_pipe, + .send_complete_check = ath10k_pci_hif_send_complete_check, + .get_free_queue_number = ath10k_pci_hif_get_free_queue_number, + .power_up = ath10k_ahb_hif_power_up, + .power_down = ath10k_pci_hif_power_down, + .read32 = ath10k_ahb_read32, + .write32 = ath10k_ahb_write32, +}; + +static const struct ath10k_bus_ops ath10k_ahb_bus_ops = { + .read32 = ath10k_ahb_read32, + .write32 = ath10k_ahb_write32, + .get_num_banks = ath10k_ahb_get_num_banks, +}; + static int ath10k_ahb_probe(struct platform_device *pdev) { + struct ath10k *ar; + struct ath10k_ahb *ar_ahb; + struct ath10k_pci *ar_pci; + const struct of_device_id *of_id; + enum ath10k_hw_rev hw_rev; + size_t size; + int ret; + u32 chip_id; + + of_id = of_match_device(ath10k_ahb_of_match, &pdev->dev); + if (!of_id) { + dev_err(&pdev->dev, "failed to find matching device tree id\n"); + return -EINVAL; + } + + hw_rev = (enum ath10k_hw_rev)of_id->data; + + size = sizeof(*ar_pci) + sizeof(*ar_ahb); + ar = ath10k_core_create(size, &pdev->dev, ATH10K_BUS_AHB, + hw_rev, &ath10k_ahb_hif_ops); + if (!ar) { + dev_err(&pdev->dev, "failed to allocate core\n"); + return -ENOMEM; + } + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "ahb probe\n"); + + ar_pci = ath10k_pci_priv(ar); + ar_ahb = ath10k_ahb_priv(ar); + + ar_ahb->pdev = pdev; + platform_set_drvdata(pdev, ar); + + ret = ath10k_ahb_resource_init(ar); + if (ret) + goto err_core_destroy; + + ar->dev_id = 0; + ar_pci->mem = ar_ahb->mem; + ar_pci->mem_len = ar_ahb->mem_len; + ar_pci->ar = ar; + ar_pci->bus_ops = &ath10k_ahb_bus_ops; + + ret = ath10k_pci_setup_resource(ar); + if (ret) { + ath10k_err(ar, "failed to setup resource: %d\n", ret); + goto err_resource_deinit; + } + + ath10k_pci_init_irq_tasklets(ar); + + ret = ath10k_ahb_request_irq_legacy(ar); + if (ret) + goto err_free_pipes; + + ret = ath10k_ahb_prepare_device(ar); + if (ret) + goto err_free_irq; + + ath10k_pci_ce_deinit(ar); + + chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS); + if (chip_id == 0xffffffff) { + ath10k_err(ar, "failed to get chip id\n"); + goto err_halt_device; + } + + ret = ath10k_core_register(ar, chip_id); + if (ret) { + ath10k_err(ar, "failed to register driver core: %d\n", ret); + goto err_halt_device; + } + return 0; + +err_halt_device: + ath10k_ahb_halt_chip(ar); + ath10k_ahb_clock_disable(ar); + +err_free_irq: + ath10k_ahb_release_irq_legacy(ar); + +err_free_pipes: + ath10k_pci_free_pipes(ar); + +err_resource_deinit: + ath10k_ahb_resource_deinit(ar); + +err_core_destroy: + ath10k_core_destroy(ar); + platform_set_drvdata(pdev, NULL); + + return ret; } static int ath10k_ahb_remove(struct platform_device *pdev) { + struct ath10k *ar = platform_get_drvdata(pdev); + struct ath10k_ahb *ar_ahb; + + if (!ar) + return -EINVAL; + + ar_ahb = ath10k_ahb_priv(ar); + + if (!ar_ahb) + return -EINVAL; + + ath10k_dbg(ar, ATH10K_DBG_AHB, "ahb remove\n"); + + ath10k_core_unregister(ar); + ath10k_ahb_irq_disable(ar); + ath10k_ahb_release_irq_legacy(ar); + ath10k_pci_release_resource(ar); + ath10k_ahb_halt_chip(ar); + ath10k_ahb_clock_disable(ar); + ath10k_ahb_resource_deinit(ar); + ath10k_core_destroy(ar); + + platform_set_drvdata(pdev, NULL); + return 0; } diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h index 5bd01b49132b..d43e375215c8 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.h +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -48,6 +48,9 @@ struct ath10k_ahb { #define ATH10K_TCSR_REG_BASE 0x1900000 #define ATH10K_TCSR_REG_SIZE 0x80000 +#define ATH10K_AHB_GCC_FEPLL_PLL_DIV 0x2f020 +#define ATH10K_AHB_WIFI_SCRATCH_5_REG 0x4f014 + #define ATH10K_AHB_WLAN_CORE_ID_REG 0x82030 #define ATH10K_AHB_TCSR_WIFI0_GLB_CFG 0x49000 @@ -63,6 +66,8 @@ struct ath10k_ahb { #define AHB_AXI_BUS_HALT_REQ 1 #define AHB_AXI_BUS_HALT_ACK 1 +#define ATH10K_AHB_CORE_CTRL_CPU_INTR_MASK 1 + int ath10k_ahb_init(void); void ath10k_ahb_exit(void); diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index f57a37bfc9f6..4217bdbe9f01 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -605,6 +605,7 @@ enum ath10k_hw_4addr_pad { #define FW_INDICATOR_ADDRESS ar->regs->fw_indicator_address #define FW_IND_EVENT_PENDING 1 #define FW_IND_INITIALIZED 2 +#define FW_IND_HOST_READY 0x80000000 /* HOST_REG interrupt from firmware */ #define PCIE_INTR_FIRMWARE_MASK ar->regs->pcie_intr_fw_mask -- cgit v1.2.3 From 1b06d64f73746c30ddba43bb57c30ba9a126f53b Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 20 Jan 2016 13:50:11 -0500 Subject: gpio: Add GPIO support for the ACCES 104-DIO-48E The ACCES 104-DIO-48E device provides 48 lines digital I/O via two Programmable Peripheral Interface (PPI) chips of type 82C55. Bit C3 at each 24-bit Group can be used as an external interrupt, triggered by a rising edge. This driver provides GPIO and IRQ support for these 48 channels of digital I/O. The base port address for the device may be configured via the dio_48e_base module parameter. The interrupt line number for the device may be configured via the dio_48e_irq module parameter. Signed-off-by: William Breathitt Gray Signed-off-by: Linus Walleij --- MAINTAINERS | 6 + drivers/gpio/Kconfig | 9 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-104-dio-48e.c | 439 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 455 insertions(+) create mode 100644 drivers/gpio/gpio-104-dio-48e.c (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 0ba80b692723..f043e957698d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -240,6 +240,12 @@ L: lm-sensors@lm-sensors.org S: Maintained F: drivers/hwmon/abituguru3.c +ACCES 104-DIO-48E GPIO DRIVER +M: William Breathitt Gray +L: linux-gpio@vger.kernel.org +S: Maintained +F: drivers/gpio/gpio-104-dio-48e.c + ACCES 104-IDI-48 GPIO DRIVER M: "William Breathitt Gray" L: linux-gpio@vger.kernel.org diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b5337f2e0eb4..5e317486a8cc 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -487,6 +487,15 @@ endmenu menu "Port-mapped I/O GPIO drivers" depends on X86 # Unconditional I/O space access +config GPIO_104_DIO_48E + tristate "ACCES 104-DIO-48E GPIO support" + select GPIOLIB_IRQCHIP + help + Enables GPIO support for the ACCES 104-DIO-48E family. The base port + address for the device may be configured via the dio_48e_base module + parameter. The interrupt line number for the device may be configured + via the dio_48e_irq module parameter. + config GPIO_104_IDIO_16 tristate "ACCES 104-IDIO-16 GPIO support" select GPIOLIB_IRQCHIP diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 73121b1b3b94..d4cc4f3d3674 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o # Device drivers. Generally keep list sorted alphabetically obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o +obj-$(CONFIG_GPIO_104_DIO_48E) += gpio-104-dio-48e.o obj-$(CONFIG_GPIO_104_IDIO_16) += gpio-104-idio-16.o obj-$(CONFIG_GPIO_104_IDI_48) += gpio-104-idi-48.o obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c new file mode 100644 index 000000000000..279de392ac6c --- /dev/null +++ b/drivers/gpio/gpio-104-dio-48e.c @@ -0,0 +1,439 @@ +/* + * GPIO driver for the ACCES 104-DIO-48E + * Copyright (C) 2016 William Breathitt Gray + * + * 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. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned dio_48e_base; +module_param(dio_48e_base, uint, 0); +MODULE_PARM_DESC(dio_48e_base, "ACCES 104-DIO-48E base address"); +static unsigned dio_48e_irq; +module_param(dio_48e_irq, uint, 0); +MODULE_PARM_DESC(dio_48e_irq, "ACCES 104-DIO-48E interrupt line number"); + +/** + * struct dio48e_gpio - GPIO device private data structure + * @chip: instance of the gpio_chip + * @io_state: bit I/O state (whether bit is set to input or output) + * @out_state: output bits state + * @control: Control registers state + * @lock: synchronization lock to prevent I/O race conditions + * @base: base port address of the GPIO device + * @extent: extent of port address region of the GPIO device + * @irq: Interrupt line number + * @irq_mask: I/O bits affected by interrupts + */ +struct dio48e_gpio { + struct gpio_chip chip; + unsigned char io_state[6]; + unsigned char out_state[6]; + unsigned char control[2]; + spinlock_t lock; + unsigned base; + unsigned extent; + unsigned irq; + unsigned char irq_mask; +}; + +static int dio48e_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + + return !!(dio48egpio->io_state[port] & mask); +} + +static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); + const unsigned io_port = offset / 8; + const unsigned control_port = io_port / 2; + const unsigned control_addr = dio48egpio->base + 3 + control_port*4; + unsigned long flags; + unsigned control; + + spin_lock_irqsave(&dio48egpio->lock, flags); + + /* Check if configuring Port C */ + if (io_port == 2 || io_port == 5) { + /* Port C can be configured by nibble */ + if (offset % 8 > 3) { + dio48egpio->io_state[io_port] |= 0xF0; + dio48egpio->control[control_port] |= BIT(3); + } else { + dio48egpio->io_state[io_port] |= 0x0F; + dio48egpio->control[control_port] |= BIT(0); + } + } else { + dio48egpio->io_state[io_port] |= 0xFF; + if (io_port == 0 || io_port == 3) + dio48egpio->control[control_port] |= BIT(4); + else + dio48egpio->control[control_port] |= BIT(1); + } + + control = BIT(7) | dio48egpio->control[control_port]; + outb(control, control_addr); + control &= ~BIT(7); + outb(control, control_addr); + + spin_unlock_irqrestore(&dio48egpio->lock, flags); + + return 0; +} + +static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); + const unsigned io_port = offset / 8; + const unsigned control_port = io_port / 2; + const unsigned mask = BIT(offset % 8); + const unsigned control_addr = dio48egpio->base + 3 + control_port*4; + const unsigned out_port = (io_port > 2) ? io_port + 1 : io_port; + unsigned long flags; + unsigned control; + + spin_lock_irqsave(&dio48egpio->lock, flags); + + /* Check if configuring Port C */ + if (io_port == 2 || io_port == 5) { + /* Port C can be configured by nibble */ + if (offset % 8 > 3) { + dio48egpio->io_state[io_port] &= 0x0F; + dio48egpio->control[control_port] &= ~BIT(3); + } else { + dio48egpio->io_state[io_port] &= 0xF0; + dio48egpio->control[control_port] &= ~BIT(0); + } + } else { + dio48egpio->io_state[io_port] &= 0x00; + if (io_port == 0 || io_port == 3) + dio48egpio->control[control_port] &= ~BIT(4); + else + dio48egpio->control[control_port] &= ~BIT(1); + } + + if (value) + dio48egpio->out_state[io_port] |= mask; + else + dio48egpio->out_state[io_port] &= ~mask; + + control = BIT(7) | dio48egpio->control[control_port]; + outb(control, control_addr); + + outb(dio48egpio->out_state[io_port], dio48egpio->base + out_port); + + control &= ~BIT(7); + outb(control, control_addr); + + spin_unlock_irqrestore(&dio48egpio->lock, flags); + + return 0; +} + +static int dio48e_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + const unsigned in_port = (port > 2) ? port + 1 : port; + unsigned long flags; + unsigned port_state; + + spin_lock_irqsave(&dio48egpio->lock, flags); + + /* ensure that GPIO is set for input */ + if (!(dio48egpio->io_state[port] & mask)) { + spin_unlock_irqrestore(&dio48egpio->lock, flags); + return -EINVAL; + } + + port_state = inb(dio48egpio->base + in_port); + + spin_unlock_irqrestore(&dio48egpio->lock, flags); + + return !!(port_state & mask); +} + +static void dio48e_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + const unsigned out_port = (port > 2) ? port + 1 : port; + unsigned long flags; + + spin_lock_irqsave(&dio48egpio->lock, flags); + + if (value) + dio48egpio->out_state[port] |= mask; + else + dio48egpio->out_state[port] &= ~mask; + + outb(dio48egpio->out_state[port], dio48egpio->base + out_port); + + spin_unlock_irqrestore(&dio48egpio->lock, flags); +} + +static void dio48e_irq_ack(struct irq_data *data) +{ +} + +static void dio48e_irq_mask(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); + const unsigned long offset = irqd_to_hwirq(data); + unsigned long flags; + + /* only bit 3 on each respective Port C supports interrupts */ + if (offset != 19 && offset != 43) + return; + + spin_lock_irqsave(&dio48egpio->lock, flags); + + if (offset == 19) + dio48egpio->irq_mask &= ~BIT(0); + else + dio48egpio->irq_mask &= ~BIT(1); + + if (!dio48egpio->irq_mask) + /* disable interrupts */ + inb(dio48egpio->base + 0xB); + + spin_unlock_irqrestore(&dio48egpio->lock, flags); +} + +static void dio48e_irq_unmask(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); + const unsigned long offset = irqd_to_hwirq(data); + unsigned long flags; + + /* only bit 3 on each respective Port C supports interrupts */ + if (offset != 19 && offset != 43) + return; + + spin_lock_irqsave(&dio48egpio->lock, flags); + + if (!dio48egpio->irq_mask) { + /* enable interrupts */ + outb(0x00, dio48egpio->base + 0xF); + outb(0x00, dio48egpio->base + 0xB); + } + + if (offset == 19) + dio48egpio->irq_mask |= BIT(0); + else + dio48egpio->irq_mask |= BIT(1); + + spin_unlock_irqrestore(&dio48egpio->lock, flags); +} + +static int dio48e_irq_set_type(struct irq_data *data, unsigned flow_type) +{ + const unsigned long offset = irqd_to_hwirq(data); + + /* only bit 3 on each respective Port C supports interrupts */ + if (offset != 19 && offset != 43) + return -EINVAL; + + if (flow_type != IRQ_TYPE_NONE && flow_type != IRQ_TYPE_EDGE_RISING) + return -EINVAL; + + return 0; +} + +static struct irq_chip dio48e_irqchip = { + .name = "104-dio-48e", + .irq_ack = dio48e_irq_ack, + .irq_mask = dio48e_irq_mask, + .irq_unmask = dio48e_irq_unmask, + .irq_set_type = dio48e_irq_set_type +}; + +static irqreturn_t dio48e_irq_handler(int irq, void *dev_id) +{ + struct dio48e_gpio *const dio48egpio = dev_id; + struct gpio_chip *const chip = &dio48egpio->chip; + const unsigned long irq_mask = dio48egpio->irq_mask; + unsigned long gpio; + + for_each_set_bit(gpio, &irq_mask, 2) + generic_handle_irq(irq_find_mapping(chip->irqdomain, + 19 + gpio*24)); + + spin_lock(&dio48egpio->lock); + + outb(0x00, dio48egpio->base + 0xF); + + spin_unlock(&dio48egpio->lock); + + return IRQ_HANDLED; +} + +static int __init dio48e_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct dio48e_gpio *dio48egpio; + const unsigned base = dio_48e_base; + const unsigned extent = 16; + const char *const name = dev_name(dev); + int err; + const unsigned irq = dio_48e_irq; + + dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL); + if (!dio48egpio) + return -ENOMEM; + + if (!request_region(base, extent, name)) { + dev_err(dev, "Unable to lock %s port addresses (0x%X-0x%X)\n", + name, base, base + extent); + err = -EBUSY; + goto err_lock_io_port; + } + + dio48egpio->chip.label = name; + dio48egpio->chip.parent = dev; + dio48egpio->chip.owner = THIS_MODULE; + dio48egpio->chip.base = -1; + dio48egpio->chip.ngpio = 48; + dio48egpio->chip.get_direction = dio48e_gpio_get_direction; + dio48egpio->chip.direction_input = dio48e_gpio_direction_input; + dio48egpio->chip.direction_output = dio48e_gpio_direction_output; + dio48egpio->chip.get = dio48e_gpio_get; + dio48egpio->chip.set = dio48e_gpio_set; + dio48egpio->base = base; + dio48egpio->extent = extent; + dio48egpio->irq = irq; + + spin_lock_init(&dio48egpio->lock); + + dev_set_drvdata(dev, dio48egpio); + + err = gpiochip_add_data(&dio48egpio->chip, dio48egpio); + if (err) { + dev_err(dev, "GPIO registering failed (%d)\n", err); + goto err_gpio_register; + } + + /* initialize all GPIO as output */ + outb(0x80, base + 3); + outb(0x00, base); + outb(0x00, base + 1); + outb(0x00, base + 2); + outb(0x00, base + 3); + outb(0x80, base + 7); + outb(0x00, base + 4); + outb(0x00, base + 5); + outb(0x00, base + 6); + outb(0x00, base + 7); + + /* disable IRQ by default */ + inb(base + 0xB); + + err = gpiochip_irqchip_add(&dio48egpio->chip, &dio48e_irqchip, 0, + handle_edge_irq, IRQ_TYPE_NONE); + if (err) { + dev_err(dev, "Could not add irqchip (%d)\n", err); + goto err_gpiochip_irqchip_add; + } + + err = request_irq(irq, dio48e_irq_handler, 0, name, dio48egpio); + if (err) { + dev_err(dev, "IRQ handler registering failed (%d)\n", err); + goto err_request_irq; + } + + return 0; + +err_request_irq: +err_gpiochip_irqchip_add: + gpiochip_remove(&dio48egpio->chip); +err_gpio_register: + release_region(base, extent); +err_lock_io_port: + return err; +} + +static int dio48e_remove(struct platform_device *pdev) +{ + struct dio48e_gpio *const dio48egpio = platform_get_drvdata(pdev); + + free_irq(dio48egpio->irq, dio48egpio); + gpiochip_remove(&dio48egpio->chip); + release_region(dio48egpio->base, dio48egpio->extent); + + return 0; +} + +static struct platform_device *dio48e_device; + +static struct platform_driver dio48e_driver = { + .driver = { + .name = "104-dio-48e" + }, + .remove = dio48e_remove +}; + +static void __exit dio48e_exit(void) +{ + platform_device_unregister(dio48e_device); + platform_driver_unregister(&dio48e_driver); +} + +static int __init dio48e_init(void) +{ + int err; + + dio48e_device = platform_device_alloc(dio48e_driver.driver.name, -1); + if (!dio48e_device) + return -ENOMEM; + + err = platform_device_add(dio48e_device); + if (err) + goto err_platform_device; + + err = platform_driver_probe(&dio48e_driver, dio48e_probe); + if (err) + goto err_platform_driver; + + return 0; + +err_platform_driver: + platform_device_del(dio48e_device); +err_platform_device: + platform_device_put(dio48e_device); + return err; +} + +module_init(dio48e_init); +module_exit(dio48e_exit); + +MODULE_AUTHOR("William Breathitt Gray "); +MODULE_DESCRIPTION("ACCES 104-DIO-48E GPIO driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 1920906f59652b9ac45dff69d56044a98b11233b Mon Sep 17 00:00:00 2001 From: Peter Hung Date: Fri, 22 Jan 2016 15:23:33 +0800 Subject: gpio-f7188x: Add F81866 GPIO supports Add F81866 GPIO supports Fintek F81866 is a SuperIO. It contains HWMON/GPIO/Serial Ports. and it has totally 72(9x8 sets) gpio pins. Here is the PDF spec: http://www.alldatasheet.com/datasheet-pdf/pdf/459085/FINTEK/F81866AD-I.html The control method is the same with F7188x, but we should care the address of GPIO8x. GPIO address is below: GPIO0x based: 0xf0 GPIO1x based: 0xe0 GPIO2x based: 0xd0 GPIO3x based: 0xc0 GPIO4x based: 0xb0 GPIO5x based: 0xa0 GPIO6x based: 0x90 GPIO7x based: 0x80 GPIO8x based: 0x88 <-- not 0x70. Signed-off-by: Peter Hung Acked-by: Simon Guinot Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 4 ++-- drivers/gpio/gpio-f7188x.c | 27 ++++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 5e317486a8cc..f9f52ec549b7 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -515,10 +515,10 @@ config GPIO_104_IDI_48 via the idi_48_irq module parameter. config GPIO_F7188X - tristate "F71869, F71869A, F71882FG and F71889F GPIO support" + tristate "F71869, F71869A, F71882FG, F71889F and F81866 GPIO support" help This option enables support for GPIOs found on Fintek Super-I/O - chips F71869, F71869A, F71882FG and F71889F. + chips F71869, F71869A, F71882FG, F71889F and F81866. To compile this driver as a module, choose M here: the module will be called f7188x-gpio. diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index d62fd6bbaf82..0417798c45f1 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c @@ -1,5 +1,5 @@ /* - * GPIO driver for Fintek Super-I/O F71869, F71869A, F71882 and F71889 + * GPIO driver for Fintek Super-I/O F71869, F71869A, F71882, F71889 and F81866 * * Copyright (C) 2010-2013 LaCie * @@ -36,14 +36,16 @@ #define SIO_F71869A_ID 0x1007 /* F71869A chipset ID */ #define SIO_F71882_ID 0x0541 /* F71882 chipset ID */ #define SIO_F71889_ID 0x0909 /* F71889 chipset ID */ +#define SIO_F81866_ID 0x1010 /* F81866 chipset ID */ -enum chips { f71869, f71869a, f71882fg, f71889f }; +enum chips { f71869, f71869a, f71882fg, f71889f, f81866 }; static const char * const f7188x_names[] = { "f71869", "f71869a", "f71882fg", "f71889f", + "f81866", }; struct f7188x_sio { @@ -190,6 +192,18 @@ static struct f7188x_gpio_bank f71889_gpio_bank[] = { F7188X_GPIO_BANK(70, 8, 0x80), }; +static struct f7188x_gpio_bank f81866_gpio_bank[] = { + F7188X_GPIO_BANK(0, 8, 0xF0), + F7188X_GPIO_BANK(10, 8, 0xE0), + F7188X_GPIO_BANK(20, 8, 0xD0), + F7188X_GPIO_BANK(30, 8, 0xC0), + F7188X_GPIO_BANK(40, 8, 0xB0), + F7188X_GPIO_BANK(50, 8, 0xA0), + F7188X_GPIO_BANK(60, 8, 0x90), + F7188X_GPIO_BANK(70, 8, 0x80), + F7188X_GPIO_BANK(80, 8, 0x88), +}; + static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) { int err; @@ -318,6 +332,10 @@ static int f7188x_gpio_probe(struct platform_device *pdev) data->nr_bank = ARRAY_SIZE(f71889_gpio_bank); data->bank = f71889_gpio_bank; break; + case f81866: + data->nr_bank = ARRAY_SIZE(f81866_gpio_bank); + data->bank = f81866_gpio_bank; + break; default: return -ENODEV; } @@ -395,6 +413,9 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio) case SIO_F71889_ID: sio->type = f71889f; break; + case SIO_F81866_ID: + sio->type = f81866; + break; default: pr_info(DRVNAME ": Unsupported Fintek device 0x%04x\n", devid); goto err; @@ -485,6 +506,6 @@ static void __exit f7188x_gpio_exit(void) } module_exit(f7188x_gpio_exit); -MODULE_DESCRIPTION("GPIO driver for Super-I/O chips F71869, F71869A, F71882FG and F71889F"); +MODULE_DESCRIPTION("GPIO driver for Super-I/O chips F71869, F71869A, F71882FG, F71889F and F81866"); MODULE_AUTHOR("Simon Guinot "); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 1286558e45fd90fd0faf5d41df35f511c51f25e7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 22 Jan 2016 01:56:30 +0100 Subject: ath9k: do not limit the number of DFS channel interfaces to 1 I think this limit was added when CSA with multiple interfaces wasn't working yet. It should no longer be necessary Signed-off-by: Felix Fietkau Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/init.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index ab7a1ac37849..d4e0ac946c3a 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -751,14 +751,6 @@ static const struct ieee80211_iface_combination if_comb_multi[] = { #endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */ -static const struct ieee80211_iface_limit if_dfs_limits[] = { - { .max = 1, .types = BIT(NL80211_IFTYPE_AP) | -#ifdef CONFIG_MAC80211_MESH - BIT(NL80211_IFTYPE_MESH_POINT) | -#endif - BIT(NL80211_IFTYPE_ADHOC) }, -}; - static const struct ieee80211_iface_combination if_comb[] = { { .limits = if_limits, @@ -766,6 +758,11 @@ static const struct ieee80211_iface_combination if_comb[] = { .max_interfaces = 2048, .num_different_channels = 1, .beacon_int_infra_match = true, +#ifdef CONFIG_ATH9K_DFS_CERTIFIED + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40), +#endif }, { .limits = wds_limits, @@ -774,18 +771,6 @@ static const struct ieee80211_iface_combination if_comb[] = { .num_different_channels = 1, .beacon_int_infra_match = true, }, -#ifdef CONFIG_ATH9K_DFS_CERTIFIED - { - .limits = if_dfs_limits, - .n_limits = ARRAY_SIZE(if_dfs_limits), - .max_interfaces = 1, - .num_different_channels = 1, - .beacon_int_infra_match = true, - .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | - BIT(NL80211_CHAN_WIDTH_20) | - BIT(NL80211_CHAN_WIDTH_40), - } -#endif }; #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT -- cgit v1.2.3 From 15b6b804b6e43297d9c05306554a39d8891966f9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 28 Jan 2016 12:06:46 +0300 Subject: drm/vmwgfx: fix a NULL dereference We dereference "eaction->event" inside the call to drm_send_event_locked() so should hold off on setting it to NULL until afterward. Fixes: fb740cf2492c ("drm: Create drm_send_event helpers") Signed-off-by: Dan Carpenter Link: http://patchwork.freedesktop.org/patch/msgid/20160128090646.GA5824@mwanda Signed-off-by: Daniel Vetter --- drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index e0edf149d9d5..37c305b62608 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -880,8 +880,8 @@ static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action) } list_del_init(&eaction->fpriv_head); - eaction->event = NULL; drm_send_event_locked(dev, eaction->event); + eaction->event = NULL; spin_unlock_irqrestore(&dev->event_lock, irq_flags); } -- cgit v1.2.3 From 5df7fd46b70bcc5517dcfbd433719cea9ebe5eff Mon Sep 17 00:00:00 2001 From: Liu Gang Date: Tue, 12 Jan 2016 20:10:09 +0800 Subject: gpio/qoriq: Add qoriq platforms support The gpio-mpc8xxx.c should can support qoriq and Layerscape platforms. Signed-off-by: Liu Gang Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f9f52ec549b7..00f17673e7e0 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -281,12 +281,14 @@ config GPIO_MPC5200 depends on PPC_MPC52xx config GPIO_MPC8XXX - bool "MPC512x/MPC8xxx GPIO support" + bool "MPC512x/MPC8xxx/QorIQ GPIO support" depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \ - FSL_SOC_BOOKE || PPC_86xx + FSL_SOC_BOOKE || PPC_86xx || ARCH_LAYERSCAPE || ARM || \ + COMPILE_TEST + select GPIO_GENERIC help Say Y here if you're going to use hardware that connects to the - MPC512x/831x/834x/837x/8572/8610 GPIOs. + MPC512x/831x/834x/837x/8572/8610/QorIQ GPIOs. config GPIO_MVEBU def_bool y -- cgit v1.2.3 From 148b95eea00b15ee65a57fe1bd4256d325575e00 Mon Sep 17 00:00:00 2001 From: Biao Huang Date: Wed, 27 Jan 2016 09:24:42 +0800 Subject: pinctrl: mediatek: Add Pinctrl/GPIO/EINT driver for mt2701 Add mt2701 support using mediatek common pinctrl driver. MT2701 have some special pins need an extra setting register than other ICs, so adding this support to common code. Signed-off-by: Biao Huang Acked-by: Yingjoe Chen Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/Kconfig | 6 + drivers/pinctrl/mediatek/Makefile | 1 + drivers/pinctrl/mediatek/pinctrl-mt2701.c | 586 +++++++ drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 14 + drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 12 +- drivers/pinctrl/mediatek/pinctrl-mtk-mt2701.h | 2323 +++++++++++++++++++++++++ 6 files changed, 2941 insertions(+), 1 deletion(-) create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt2701.c create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt2701.h (limited to 'drivers') diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig index 02f6f92df86c..13e9939d9b3a 100644 --- a/drivers/pinctrl/mediatek/Kconfig +++ b/drivers/pinctrl/mediatek/Kconfig @@ -9,6 +9,12 @@ config PINCTRL_MTK_COMMON select OF_GPIO # For ARMv7 SoCs +config PINCTRL_MT2701 + bool "Mediatek MT2701 pin control" if COMPILE_TEST && !MACH_MT2701 + depends on OF + default MACH_MT2701 + select PINCTRL_MTK_COMMON + config PINCTRL_MT8135 bool "Mediatek MT8135 pin control" if COMPILE_TEST && !MACH_MT8135 depends on OF diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile index eb923d64d387..da30314a5ddc 100644 --- a/drivers/pinctrl/mediatek/Makefile +++ b/drivers/pinctrl/mediatek/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_PINCTRL_MTK_COMMON) += pinctrl-mtk-common.o # SoC Drivers +obj-$(CONFIG_PINCTRL_MT2701) += pinctrl-mt2701.o obj-$(CONFIG_PINCTRL_MT8135) += pinctrl-mt8135.o obj-$(CONFIG_PINCTRL_MT8127) += pinctrl-mt8127.o obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o diff --git a/drivers/pinctrl/mediatek/pinctrl-mt2701.c b/drivers/pinctrl/mediatek/pinctrl-mt2701.c new file mode 100644 index 000000000000..65b0d3e69b36 --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-mt2701.c @@ -0,0 +1,586 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * Author: Biao Huang + * + * 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. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pinctrl-mtk-common.h" +#include "pinctrl-mtk-mt2701.h" + +/** + * struct mtk_spec_pinmux_set + * - For special pins' mode setting + * @pin: The pin number. + * @offset: The offset of extra setting register. + * @bit: The bit of extra setting register. + */ +struct mtk_spec_pinmux_set { + unsigned short pin; + unsigned short offset; + unsigned char bit; +}; + +#define MTK_PINMUX_SPEC(_pin, _offset, _bit) \ + { \ + .pin = _pin, \ + .offset = _offset, \ + .bit = _bit, \ + } + +static const struct mtk_drv_group_desc mt2701_drv_grp[] = { + /* 0E4E8SR 4/8/12/16 */ + MTK_DRV_GRP(4, 16, 1, 2, 4), + /* 0E2E4SR 2/4/6/8 */ + MTK_DRV_GRP(2, 8, 1, 2, 2), + /* E8E4E2 2/4/6/8/10/12/14/16 */ + MTK_DRV_GRP(2, 16, 0, 2, 2) +}; + +static const struct mtk_pin_drv_grp mt2701_pin_drv[] = { + MTK_PIN_DRV_GRP(0, 0xf50, 0, 1), + MTK_PIN_DRV_GRP(1, 0xf50, 0, 1), + MTK_PIN_DRV_GRP(2, 0xf50, 0, 1), + MTK_PIN_DRV_GRP(3, 0xf50, 0, 1), + MTK_PIN_DRV_GRP(4, 0xf50, 0, 1), + MTK_PIN_DRV_GRP(5, 0xf50, 0, 1), + MTK_PIN_DRV_GRP(6, 0xf50, 0, 1), + MTK_PIN_DRV_GRP(7, 0xf50, 4, 1), + MTK_PIN_DRV_GRP(8, 0xf50, 4, 1), + MTK_PIN_DRV_GRP(9, 0xf50, 4, 1), + MTK_PIN_DRV_GRP(10, 0xf50, 8, 1), + MTK_PIN_DRV_GRP(11, 0xf50, 8, 1), + MTK_PIN_DRV_GRP(12, 0xf50, 8, 1), + MTK_PIN_DRV_GRP(13, 0xf50, 8, 1), + MTK_PIN_DRV_GRP(14, 0xf50, 12, 0), + MTK_PIN_DRV_GRP(15, 0xf50, 12, 0), + MTK_PIN_DRV_GRP(16, 0xf60, 0, 0), + MTK_PIN_DRV_GRP(17, 0xf60, 0, 0), + MTK_PIN_DRV_GRP(18, 0xf60, 4, 0), + MTK_PIN_DRV_GRP(19, 0xf60, 4, 0), + MTK_PIN_DRV_GRP(20, 0xf60, 4, 0), + MTK_PIN_DRV_GRP(21, 0xf60, 4, 0), + MTK_PIN_DRV_GRP(22, 0xf60, 8, 0), + MTK_PIN_DRV_GRP(23, 0xf60, 8, 0), + MTK_PIN_DRV_GRP(24, 0xf60, 8, 0), + MTK_PIN_DRV_GRP(25, 0xf60, 8, 0), + MTK_PIN_DRV_GRP(26, 0xf60, 8, 0), + MTK_PIN_DRV_GRP(27, 0xf60, 12, 0), + MTK_PIN_DRV_GRP(28, 0xf60, 12, 0), + MTK_PIN_DRV_GRP(29, 0xf60, 12, 0), + MTK_PIN_DRV_GRP(30, 0xf60, 0, 0), + MTK_PIN_DRV_GRP(31, 0xf60, 0, 0), + MTK_PIN_DRV_GRP(32, 0xf60, 0, 0), + MTK_PIN_DRV_GRP(33, 0xf70, 0, 0), + MTK_PIN_DRV_GRP(34, 0xf70, 0, 0), + MTK_PIN_DRV_GRP(35, 0xf70, 0, 0), + MTK_PIN_DRV_GRP(36, 0xf70, 0, 0), + MTK_PIN_DRV_GRP(37, 0xf70, 0, 0), + MTK_PIN_DRV_GRP(38, 0xf70, 4, 0), + MTK_PIN_DRV_GRP(39, 0xf70, 8, 1), + MTK_PIN_DRV_GRP(40, 0xf70, 8, 1), + MTK_PIN_DRV_GRP(41, 0xf70, 8, 1), + MTK_PIN_DRV_GRP(42, 0xf70, 8, 1), + MTK_PIN_DRV_GRP(43, 0xf70, 12, 0), + MTK_PIN_DRV_GRP(44, 0xf70, 12, 0), + MTK_PIN_DRV_GRP(45, 0xf70, 12, 0), + MTK_PIN_DRV_GRP(47, 0xf80, 0, 0), + MTK_PIN_DRV_GRP(48, 0xf80, 0, 0), + MTK_PIN_DRV_GRP(49, 0xf80, 4, 0), + MTK_PIN_DRV_GRP(50, 0xf70, 4, 0), + MTK_PIN_DRV_GRP(51, 0xf70, 4, 0), + MTK_PIN_DRV_GRP(52, 0xf70, 4, 0), + MTK_PIN_DRV_GRP(53, 0xf80, 12, 0), + MTK_PIN_DRV_GRP(54, 0xf80, 12, 0), + MTK_PIN_DRV_GRP(55, 0xf80, 12, 0), + MTK_PIN_DRV_GRP(56, 0xf80, 12, 0), + MTK_PIN_DRV_GRP(60, 0xf90, 8, 1), + MTK_PIN_DRV_GRP(61, 0xf90, 8, 1), + MTK_PIN_DRV_GRP(62, 0xf90, 8, 1), + MTK_PIN_DRV_GRP(63, 0xf90, 12, 1), + MTK_PIN_DRV_GRP(64, 0xf90, 12, 1), + MTK_PIN_DRV_GRP(65, 0xf90, 12, 1), + MTK_PIN_DRV_GRP(66, 0xfa0, 0, 1), + MTK_PIN_DRV_GRP(67, 0xfa0, 0, 1), + MTK_PIN_DRV_GRP(68, 0xfa0, 0, 1), + MTK_PIN_DRV_GRP(69, 0xfa0, 0, 1), + MTK_PIN_DRV_GRP(70, 0xfa0, 0, 1), + MTK_PIN_DRV_GRP(71, 0xfa0, 0, 1), + MTK_PIN_DRV_GRP(72, 0xf80, 4, 0), + MTK_PIN_DRV_GRP(73, 0xf80, 4, 0), + MTK_PIN_DRV_GRP(74, 0xf80, 4, 0), + MTK_PIN_DRV_GRP(85, 0xda0, 0, 2), + MTK_PIN_DRV_GRP(86, 0xd90, 0, 2), + MTK_PIN_DRV_GRP(87, 0xdb0, 0, 2), + MTK_PIN_DRV_GRP(88, 0xdb0, 0, 2), + MTK_PIN_DRV_GRP(89, 0xdb0, 0, 2), + MTK_PIN_DRV_GRP(90, 0xdb0, 0, 2), + MTK_PIN_DRV_GRP(105, 0xd40, 0, 2), + MTK_PIN_DRV_GRP(106, 0xd30, 0, 2), + MTK_PIN_DRV_GRP(107, 0xd50, 0, 2), + MTK_PIN_DRV_GRP(108, 0xd50, 0, 2), + MTK_PIN_DRV_GRP(109, 0xd50, 0, 2), + MTK_PIN_DRV_GRP(110, 0xd50, 0, 2), + MTK_PIN_DRV_GRP(111, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(112, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(113, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(114, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(115, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(116, 0xcd0, 0, 2), + MTK_PIN_DRV_GRP(117, 0xcc0, 0, 2), + MTK_PIN_DRV_GRP(118, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(119, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(120, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(121, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(126, 0xf80, 4, 0), + MTK_PIN_DRV_GRP(188, 0xf70, 4, 0), + MTK_PIN_DRV_GRP(189, 0xfe0, 8, 0), + MTK_PIN_DRV_GRP(190, 0xfe0, 8, 0), + MTK_PIN_DRV_GRP(191, 0xfe0, 8, 0), + MTK_PIN_DRV_GRP(192, 0xfe0, 8, 0), + MTK_PIN_DRV_GRP(193, 0xfe0, 8, 0), + MTK_PIN_DRV_GRP(194, 0xfe0, 12, 0), + MTK_PIN_DRV_GRP(195, 0xfe0, 12, 0), + MTK_PIN_DRV_GRP(196, 0xfe0, 12, 0), + MTK_PIN_DRV_GRP(197, 0xfe0, 12, 0), + MTK_PIN_DRV_GRP(198, 0xfe0, 12, 0), + MTK_PIN_DRV_GRP(199, 0xf50, 4, 1), + MTK_PIN_DRV_GRP(200, 0xfd0, 0, 0), + MTK_PIN_DRV_GRP(201, 0xfd0, 0, 0), + MTK_PIN_DRV_GRP(202, 0xfd0, 0, 0), + MTK_PIN_DRV_GRP(203, 0xfd0, 4, 0), + MTK_PIN_DRV_GRP(204, 0xfd0, 4, 0), + MTK_PIN_DRV_GRP(205, 0xfd0, 4, 0), + MTK_PIN_DRV_GRP(206, 0xfd0, 4, 0), + MTK_PIN_DRV_GRP(207, 0xfd0, 4, 0), + MTK_PIN_DRV_GRP(208, 0xfd0, 8, 0), + MTK_PIN_DRV_GRP(209, 0xfd0, 8, 0), + MTK_PIN_DRV_GRP(210, 0xfd0, 12, 1), + MTK_PIN_DRV_GRP(211, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(212, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(213, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(214, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(215, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(216, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(217, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(218, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(219, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(220, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(221, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(222, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(223, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(224, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(225, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(226, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(227, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(228, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(229, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(230, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(231, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(232, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(233, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(234, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(235, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(236, 0xff0, 4, 0), + MTK_PIN_DRV_GRP(237, 0xff0, 4, 0), + MTK_PIN_DRV_GRP(238, 0xff0, 4, 0), + MTK_PIN_DRV_GRP(239, 0xff0, 4, 0), + MTK_PIN_DRV_GRP(240, 0xff0, 4, 0), + MTK_PIN_DRV_GRP(241, 0xff0, 4, 0), + MTK_PIN_DRV_GRP(242, 0xff0, 8, 0), + MTK_PIN_DRV_GRP(243, 0xff0, 8, 0), + MTK_PIN_DRV_GRP(248, 0xf00, 0, 0), + MTK_PIN_DRV_GRP(249, 0xfc0, 0, 2), + MTK_PIN_DRV_GRP(250, 0xfc0, 0, 2), + MTK_PIN_DRV_GRP(251, 0xfc0, 0, 2), + MTK_PIN_DRV_GRP(252, 0xfc0, 0, 2), + MTK_PIN_DRV_GRP(253, 0xfc0, 0, 2), + MTK_PIN_DRV_GRP(254, 0xfc0, 0, 2), + MTK_PIN_DRV_GRP(255, 0xfc0, 0, 2), + MTK_PIN_DRV_GRP(256, 0xfc0, 0, 2), + MTK_PIN_DRV_GRP(257, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(258, 0xcb0, 0, 2), + MTK_PIN_DRV_GRP(259, 0xc90, 0, 2), + MTK_PIN_DRV_GRP(260, 0x3a0, 0, 2), + MTK_PIN_DRV_GRP(261, 0xd50, 0, 2), + MTK_PIN_DRV_GRP(262, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(263, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(264, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(265, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(266, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(267, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(268, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(269, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(270, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(271, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(272, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(273, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(274, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(275, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(276, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(277, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(278, 0xf70, 8, 1), +}; + +static const struct mtk_pin_spec_pupd_set_samereg mt2701_spec_pupd[] = { + MTK_PIN_PUPD_SPEC_SR(111, 0xd00, 12, 13, 14), /* ms0 data7 */ + MTK_PIN_PUPD_SPEC_SR(112, 0xd00, 8, 9, 10), /* ms0 data6 */ + MTK_PIN_PUPD_SPEC_SR(113, 0xd00, 4, 5, 6), /* ms0 data5 */ + MTK_PIN_PUPD_SPEC_SR(114, 0xd00, 0, 1, 2), /* ms0 data4 */ + MTK_PIN_PUPD_SPEC_SR(115, 0xd10, 0, 1, 2), /* ms0 rstb */ + MTK_PIN_PUPD_SPEC_SR(116, 0xcd0, 8, 9, 10), /* ms0 cmd */ + MTK_PIN_PUPD_SPEC_SR(117, 0xcc0, 8, 9, 10), /* ms0 clk */ + MTK_PIN_PUPD_SPEC_SR(118, 0xcf0, 12, 13, 14), /* ms0 data3 */ + MTK_PIN_PUPD_SPEC_SR(119, 0xcf0, 8, 9, 10), /* ms0 data2 */ + MTK_PIN_PUPD_SPEC_SR(120, 0xcf0, 4, 5, 6), /* ms0 data1 */ + MTK_PIN_PUPD_SPEC_SR(121, 0xcf0, 0, 1, 2), /* ms0 data0 */ + + MTK_PIN_PUPD_SPEC_SR(105, 0xd40, 8, 9, 10), /* ms1 cmd */ + MTK_PIN_PUPD_SPEC_SR(106, 0xd30, 8, 9, 10), /* ms1 clk */ + MTK_PIN_PUPD_SPEC_SR(107, 0xd60, 0, 1, 2), /* ms1 dat0 */ + MTK_PIN_PUPD_SPEC_SR(108, 0xd60, 10, 9, 8), /* ms1 dat1 */ + MTK_PIN_PUPD_SPEC_SR(109, 0xd60, 4, 5, 6), /* ms1 dat2 */ + MTK_PIN_PUPD_SPEC_SR(110, 0xc60, 12, 13, 14), /* ms1 dat3 */ + + MTK_PIN_PUPD_SPEC_SR(85, 0xda0, 8, 9, 10), /* ms2 cmd */ + MTK_PIN_PUPD_SPEC_SR(86, 0xd90, 8, 9, 10), /* ms2 clk */ + MTK_PIN_PUPD_SPEC_SR(87, 0xdc0, 0, 1, 2), /* ms2 dat0 */ + MTK_PIN_PUPD_SPEC_SR(88, 0xdc0, 10, 9, 8), /* ms2 dat1 */ + MTK_PIN_PUPD_SPEC_SR(89, 0xdc0, 4, 5, 6), /* ms2 dat2 */ + MTK_PIN_PUPD_SPEC_SR(90, 0xdc0, 12, 13, 14), /* ms2 dat3 */ + + MTK_PIN_PUPD_SPEC_SR(249, 0x140, 0, 1, 2), /* ms0e rstb */ + MTK_PIN_PUPD_SPEC_SR(250, 0x130, 12, 13, 14), /* ms0e dat7 */ + MTK_PIN_PUPD_SPEC_SR(251, 0x130, 8, 9, 10), /* ms0e dat6 */ + MTK_PIN_PUPD_SPEC_SR(252, 0x130, 4, 5, 6), /* ms0e dat5 */ + MTK_PIN_PUPD_SPEC_SR(253, 0x130, 0, 1, 2), /* ms0e dat4 */ + MTK_PIN_PUPD_SPEC_SR(254, 0xf40, 12, 13, 14), /* ms0e dat3 */ + MTK_PIN_PUPD_SPEC_SR(255, 0xf40, 8, 9, 10), /* ms0e dat2 */ + MTK_PIN_PUPD_SPEC_SR(256, 0xf40, 4, 5, 6), /* ms0e dat1 */ + MTK_PIN_PUPD_SPEC_SR(257, 0xf40, 0, 1, 2), /* ms0e dat0 */ + MTK_PIN_PUPD_SPEC_SR(258, 0xcb0, 8, 9, 10), /* ms0e cmd */ + MTK_PIN_PUPD_SPEC_SR(259, 0xc90, 8, 9, 10), /* ms0e clk */ + MTK_PIN_PUPD_SPEC_SR(261, 0x140, 8, 9, 10), /* ms1 ins */ +}; + +static int mt2701_spec_pull_set(struct regmap *regmap, unsigned int pin, + unsigned char align, bool isup, unsigned int r1r0) +{ + return mtk_pctrl_spec_pull_set_samereg(regmap, mt2701_spec_pupd, + ARRAY_SIZE(mt2701_spec_pupd), pin, align, isup, r1r0); +} + +static const struct mtk_pin_ies_smt_set mt2701_ies_set[] = { + MTK_PIN_IES_SMT_SPEC(0, 6, 0xb20, 0), + MTK_PIN_IES_SMT_SPEC(7, 9, 0xb20, 1), + MTK_PIN_IES_SMT_SPEC(10, 13, 0xb30, 3), + MTK_PIN_IES_SMT_SPEC(14, 15, 0xb30, 13), + MTK_PIN_IES_SMT_SPEC(16, 17, 0xb40, 7), + MTK_PIN_IES_SMT_SPEC(18, 21, 0xb40, 13), + MTK_PIN_IES_SMT_SPEC(22, 26, 0xb40, 13), + MTK_PIN_IES_SMT_SPEC(27, 29, 0xb40, 13), + MTK_PIN_IES_SMT_SPEC(30, 32, 0xb40, 7), + MTK_PIN_IES_SMT_SPEC(33, 37, 0xb40, 13), + MTK_PIN_IES_SMT_SPEC(38, 38, 0xb20, 13), + MTK_PIN_IES_SMT_SPEC(39, 42, 0xb40, 13), + MTK_PIN_IES_SMT_SPEC(43, 45, 0xb20, 10), + MTK_PIN_IES_SMT_SPEC(47, 48, 0xb20, 11), + MTK_PIN_IES_SMT_SPEC(49, 49, 0xb20, 12), + MTK_PIN_IES_SMT_SPEC(50, 52, 0xb20, 13), + MTK_PIN_IES_SMT_SPEC(53, 56, 0xb20, 14), + MTK_PIN_IES_SMT_SPEC(57, 58, 0xb20, 15), + MTK_PIN_IES_SMT_SPEC(59, 59, 0xb30, 10), + MTK_PIN_IES_SMT_SPEC(60, 62, 0xb30, 0), + MTK_PIN_IES_SMT_SPEC(63, 65, 0xb30, 1), + MTK_PIN_IES_SMT_SPEC(66, 71, 0xb30, 2), + MTK_PIN_IES_SMT_SPEC(72, 74, 0xb20, 12), + MTK_PIN_IES_SMT_SPEC(75, 76, 0xb30, 3), + MTK_PIN_IES_SMT_SPEC(77, 78, 0xb30, 4), + MTK_PIN_IES_SMT_SPEC(79, 82, 0xb30, 5), + MTK_PIN_IES_SMT_SPEC(83, 84, 0xb30, 2), + MTK_PIN_IES_SMT_SPEC(85, 85, 0xda0, 4), + MTK_PIN_IES_SMT_SPEC(86, 86, 0xd90, 4), + MTK_PIN_IES_SMT_SPEC(87, 90, 0xdb0, 4), + MTK_PIN_IES_SMT_SPEC(101, 104, 0xb30, 6), + MTK_PIN_IES_SMT_SPEC(105, 105, 0xd40, 4), + MTK_PIN_IES_SMT_SPEC(106, 106, 0xd30, 4), + MTK_PIN_IES_SMT_SPEC(107, 110, 0xd50, 4), + MTK_PIN_IES_SMT_SPEC(111, 115, 0xce0, 4), + MTK_PIN_IES_SMT_SPEC(116, 116, 0xcd0, 4), + MTK_PIN_IES_SMT_SPEC(117, 117, 0xcc0, 4), + MTK_PIN_IES_SMT_SPEC(118, 121, 0xce0, 4), + MTK_PIN_IES_SMT_SPEC(122, 125, 0xb30, 7), + MTK_PIN_IES_SMT_SPEC(126, 126, 0xb20, 12), + MTK_PIN_IES_SMT_SPEC(127, 142, 0xb30, 9), + MTK_PIN_IES_SMT_SPEC(143, 160, 0xb30, 10), + MTK_PIN_IES_SMT_SPEC(161, 168, 0xb30, 12), + MTK_PIN_IES_SMT_SPEC(169, 183, 0xb30, 10), + MTK_PIN_IES_SMT_SPEC(184, 186, 0xb30, 9), + MTK_PIN_IES_SMT_SPEC(187, 187, 0xb30, 14), + MTK_PIN_IES_SMT_SPEC(188, 188, 0xb20, 13), + MTK_PIN_IES_SMT_SPEC(189, 193, 0xb30, 15), + MTK_PIN_IES_SMT_SPEC(194, 198, 0xb40, 0), + MTK_PIN_IES_SMT_SPEC(199, 199, 0xb20, 1), + MTK_PIN_IES_SMT_SPEC(200, 202, 0xb40, 1), + MTK_PIN_IES_SMT_SPEC(203, 207, 0xb40, 2), + MTK_PIN_IES_SMT_SPEC(208, 209, 0xb40, 3), + MTK_PIN_IES_SMT_SPEC(210, 210, 0xb40, 4), + MTK_PIN_IES_SMT_SPEC(211, 235, 0xb40, 5), + MTK_PIN_IES_SMT_SPEC(236, 241, 0xb40, 6), + MTK_PIN_IES_SMT_SPEC(242, 243, 0xb40, 7), + MTK_PIN_IES_SMT_SPEC(244, 247, 0xb40, 8), + MTK_PIN_IES_SMT_SPEC(248, 248, 0xb40, 9), + MTK_PIN_IES_SMT_SPEC(249, 257, 0xfc0, 4), + MTK_PIN_IES_SMT_SPEC(258, 258, 0xcb0, 4), + MTK_PIN_IES_SMT_SPEC(259, 259, 0xc90, 4), + MTK_PIN_IES_SMT_SPEC(260, 260, 0x3a0, 4), + MTK_PIN_IES_SMT_SPEC(261, 261, 0xd50, 4), + MTK_PIN_IES_SMT_SPEC(262, 277, 0xb40, 12), + MTK_PIN_IES_SMT_SPEC(278, 278, 0xb40, 13), +}; + +static const struct mtk_pin_ies_smt_set mt2701_smt_set[] = { + MTK_PIN_IES_SMT_SPEC(0, 6, 0xb50, 0), + MTK_PIN_IES_SMT_SPEC(7, 9, 0xb50, 1), + MTK_PIN_IES_SMT_SPEC(10, 13, 0xb60, 3), + MTK_PIN_IES_SMT_SPEC(14, 15, 0xb60, 13), + MTK_PIN_IES_SMT_SPEC(16, 17, 0xb70, 7), + MTK_PIN_IES_SMT_SPEC(18, 21, 0xb70, 13), + MTK_PIN_IES_SMT_SPEC(22, 26, 0xb70, 13), + MTK_PIN_IES_SMT_SPEC(27, 29, 0xb70, 13), + MTK_PIN_IES_SMT_SPEC(30, 32, 0xb70, 7), + MTK_PIN_IES_SMT_SPEC(33, 37, 0xb70, 13), + MTK_PIN_IES_SMT_SPEC(38, 38, 0xb50, 13), + MTK_PIN_IES_SMT_SPEC(39, 42, 0xb70, 13), + MTK_PIN_IES_SMT_SPEC(43, 45, 0xb50, 10), + MTK_PIN_IES_SMT_SPEC(47, 48, 0xb50, 11), + MTK_PIN_IES_SMT_SPEC(49, 49, 0xb50, 12), + MTK_PIN_IES_SMT_SPEC(50, 52, 0xb50, 13), + MTK_PIN_IES_SMT_SPEC(53, 56, 0xb50, 14), + MTK_PIN_IES_SMT_SPEC(57, 58, 0xb50, 15), + MTK_PIN_IES_SMT_SPEC(59, 59, 0xb60, 10), + MTK_PIN_IES_SMT_SPEC(60, 62, 0xb60, 0), + MTK_PIN_IES_SMT_SPEC(63, 65, 0xb60, 1), + MTK_PIN_IES_SMT_SPEC(66, 71, 0xb60, 2), + MTK_PIN_IES_SMT_SPEC(72, 74, 0xb50, 12), + MTK_PIN_IES_SMT_SPEC(75, 76, 0xb60, 3), + MTK_PIN_IES_SMT_SPEC(77, 78, 0xb60, 4), + MTK_PIN_IES_SMT_SPEC(79, 82, 0xb60, 5), + MTK_PIN_IES_SMT_SPEC(83, 84, 0xb60, 2), + MTK_PIN_IES_SMT_SPEC(85, 85, 0xda0, 11), + MTK_PIN_IES_SMT_SPEC(86, 86, 0xd90, 11), + MTK_PIN_IES_SMT_SPEC(87, 87, 0xdc0, 3), + MTK_PIN_IES_SMT_SPEC(88, 88, 0xdc0, 7), + MTK_PIN_IES_SMT_SPEC(89, 89, 0xdc0, 11), + MTK_PIN_IES_SMT_SPEC(90, 90, 0xdc0, 15), + MTK_PIN_IES_SMT_SPEC(101, 104, 0xb60, 6), + MTK_PIN_IES_SMT_SPEC(105, 105, 0xd40, 11), + MTK_PIN_IES_SMT_SPEC(106, 106, 0xd30, 11), + MTK_PIN_IES_SMT_SPEC(107, 107, 0xd60, 3), + MTK_PIN_IES_SMT_SPEC(108, 108, 0xd60, 7), + MTK_PIN_IES_SMT_SPEC(109, 109, 0xd60, 11), + MTK_PIN_IES_SMT_SPEC(110, 110, 0xd60, 15), + MTK_PIN_IES_SMT_SPEC(111, 111, 0xd00, 15), + MTK_PIN_IES_SMT_SPEC(112, 112, 0xd00, 11), + MTK_PIN_IES_SMT_SPEC(113, 113, 0xd00, 7), + MTK_PIN_IES_SMT_SPEC(114, 114, 0xd00, 3), + MTK_PIN_IES_SMT_SPEC(115, 115, 0xd10, 3), + MTK_PIN_IES_SMT_SPEC(116, 116, 0xcd0, 11), + MTK_PIN_IES_SMT_SPEC(117, 117, 0xcc0, 11), + MTK_PIN_IES_SMT_SPEC(118, 118, 0xcf0, 15), + MTK_PIN_IES_SMT_SPEC(119, 119, 0xcf0, 11), + MTK_PIN_IES_SMT_SPEC(120, 120, 0xcf0, 7), + MTK_PIN_IES_SMT_SPEC(121, 121, 0xcf0, 3), + MTK_PIN_IES_SMT_SPEC(122, 125, 0xb60, 7), + MTK_PIN_IES_SMT_SPEC(126, 126, 0xb50, 12), + MTK_PIN_IES_SMT_SPEC(127, 142, 0xb60, 9), + MTK_PIN_IES_SMT_SPEC(143, 160, 0xb60, 10), + MTK_PIN_IES_SMT_SPEC(161, 168, 0xb60, 12), + MTK_PIN_IES_SMT_SPEC(169, 183, 0xb60, 10), + MTK_PIN_IES_SMT_SPEC(184, 186, 0xb60, 9), + MTK_PIN_IES_SMT_SPEC(187, 187, 0xb60, 14), + MTK_PIN_IES_SMT_SPEC(188, 188, 0xb50, 13), + MTK_PIN_IES_SMT_SPEC(189, 193, 0xb60, 15), + MTK_PIN_IES_SMT_SPEC(194, 198, 0xb70, 0), + MTK_PIN_IES_SMT_SPEC(199, 199, 0xb50, 1), + MTK_PIN_IES_SMT_SPEC(200, 202, 0xb70, 1), + MTK_PIN_IES_SMT_SPEC(203, 207, 0xb70, 2), + MTK_PIN_IES_SMT_SPEC(208, 209, 0xb70, 3), + MTK_PIN_IES_SMT_SPEC(210, 210, 0xb70, 4), + MTK_PIN_IES_SMT_SPEC(211, 235, 0xb70, 5), + MTK_PIN_IES_SMT_SPEC(236, 241, 0xb70, 6), + MTK_PIN_IES_SMT_SPEC(242, 243, 0xb70, 7), + MTK_PIN_IES_SMT_SPEC(244, 247, 0xb70, 8), + MTK_PIN_IES_SMT_SPEC(248, 248, 0xb70, 9), + MTK_PIN_IES_SMT_SPEC(249, 249, 0x140, 3), + MTK_PIN_IES_SMT_SPEC(250, 250, 0x130, 15), + MTK_PIN_IES_SMT_SPEC(251, 251, 0x130, 11), + MTK_PIN_IES_SMT_SPEC(252, 252, 0x130, 7), + MTK_PIN_IES_SMT_SPEC(253, 253, 0x130, 3), + MTK_PIN_IES_SMT_SPEC(254, 254, 0xf40, 15), + MTK_PIN_IES_SMT_SPEC(255, 255, 0xf40, 11), + MTK_PIN_IES_SMT_SPEC(256, 256, 0xf40, 7), + MTK_PIN_IES_SMT_SPEC(257, 257, 0xf40, 3), + MTK_PIN_IES_SMT_SPEC(258, 258, 0xcb0, 11), + MTK_PIN_IES_SMT_SPEC(259, 259, 0xc90, 11), + MTK_PIN_IES_SMT_SPEC(260, 260, 0x3a0, 11), + MTK_PIN_IES_SMT_SPEC(261, 261, 0x0b0, 3), + MTK_PIN_IES_SMT_SPEC(262, 277, 0xb70, 12), + MTK_PIN_IES_SMT_SPEC(278, 278, 0xb70, 13), +}; + +static int mt2701_ies_smt_set(struct regmap *regmap, unsigned int pin, + unsigned char align, int value, enum pin_config_param arg) +{ + if (arg == PIN_CONFIG_INPUT_ENABLE) + return mtk_pconf_spec_set_ies_smt_range(regmap, mt2701_ies_set, + ARRAY_SIZE(mt2701_ies_set), pin, align, value); + else if (arg == PIN_CONFIG_INPUT_SCHMITT_ENABLE) + return mtk_pconf_spec_set_ies_smt_range(regmap, mt2701_smt_set, + ARRAY_SIZE(mt2701_smt_set), pin, align, value); + return -EINVAL; +} + +static const struct mtk_spec_pinmux_set mt2701_spec_pinmux[] = { + MTK_PINMUX_SPEC(22, 0xb10, 3), + MTK_PINMUX_SPEC(23, 0xb10, 4), + MTK_PINMUX_SPEC(24, 0xb10, 5), + MTK_PINMUX_SPEC(29, 0xb10, 9), + MTK_PINMUX_SPEC(208, 0xb10, 7), + MTK_PINMUX_SPEC(209, 0xb10, 8), + MTK_PINMUX_SPEC(203, 0xf20, 0), + MTK_PINMUX_SPEC(204, 0xf20, 1), + MTK_PINMUX_SPEC(249, 0xef0, 0), + MTK_PINMUX_SPEC(250, 0xef0, 0), + MTK_PINMUX_SPEC(251, 0xef0, 0), + MTK_PINMUX_SPEC(252, 0xef0, 0), + MTK_PINMUX_SPEC(253, 0xef0, 0), + MTK_PINMUX_SPEC(254, 0xef0, 0), + MTK_PINMUX_SPEC(255, 0xef0, 0), + MTK_PINMUX_SPEC(256, 0xef0, 0), + MTK_PINMUX_SPEC(257, 0xef0, 0), + MTK_PINMUX_SPEC(258, 0xef0, 0), + MTK_PINMUX_SPEC(259, 0xef0, 0), + MTK_PINMUX_SPEC(260, 0xef0, 0), +}; + +static void mt2701_spec_pinmux_set(struct regmap *reg, unsigned int pin, + unsigned int mode) +{ + unsigned int i, value, mask; + unsigned int info_num = ARRAY_SIZE(mt2701_spec_pinmux); + unsigned int spec_flag; + + for (i = 0; i < info_num; i++) { + if (pin == mt2701_spec_pinmux[i].pin) + break; + } + + if (i == info_num) + return; + + spec_flag = (mode >> 3); + mask = BIT(mt2701_spec_pinmux[i].bit); + if (!spec_flag) + value = mask; + else + value = 0; + regmap_update_bits(reg, mt2701_spec_pinmux[i].offset, mask, value); +} + +static void mt2701_spec_dir_set(unsigned int *reg_addr, unsigned int pin) +{ + if (pin > 175) + *reg_addr += 0x10; +} + +static const struct mtk_pinctrl_devdata mt2701_pinctrl_data = { + .pins = mtk_pins_mt2701, + .npins = ARRAY_SIZE(mtk_pins_mt2701), + .grp_desc = mt2701_drv_grp, + .n_grp_cls = ARRAY_SIZE(mt2701_drv_grp), + .pin_drv_grp = mt2701_pin_drv, + .n_pin_drv_grps = ARRAY_SIZE(mt2701_pin_drv), + .spec_pull_set = mt2701_spec_pull_set, + .spec_ies_smt_set = mt2701_ies_smt_set, + .spec_pinmux_set = mt2701_spec_pinmux_set, + .spec_dir_set = mt2701_spec_dir_set, + .dir_offset = 0x0000, + .pullen_offset = 0x0150, + .pullsel_offset = 0x0280, + .dout_offset = 0x0500, + .din_offset = 0x0630, + .pinmux_offset = 0x0760, + .type1_start = 280, + .type1_end = 280, + .port_shf = 4, + .port_mask = 0x1f, + .port_align = 4, + .eint_offsets = { + .name = "mt2701_eint", + .stat = 0x000, + .ack = 0x040, + .mask = 0x080, + .mask_set = 0x0c0, + .mask_clr = 0x100, + .sens = 0x140, + .sens_set = 0x180, + .sens_clr = 0x1c0, + .soft = 0x200, + .soft_set = 0x240, + .soft_clr = 0x280, + .pol = 0x300, + .pol_set = 0x340, + .pol_clr = 0x380, + .dom_en = 0x400, + .dbnc_ctrl = 0x500, + .dbnc_set = 0x600, + .dbnc_clr = 0x700, + .port_mask = 6, + .ports = 6, + }, + .ap_num = 169, + .db_cnt = 16, +}; + +static int mt2701_pinctrl_probe(struct platform_device *pdev) +{ + return mtk_pctrl_init(pdev, &mt2701_pinctrl_data, NULL); +} + +static const struct of_device_id mt2701_pctrl_match[] = { + { .compatible = "mediatek,mt2701-pinctrl", }, + {} +}; +MODULE_DEVICE_TABLE(of, mt2701_pctrl_match); + +static struct platform_driver mtk_pinctrl_driver = { + .probe = mt2701_pinctrl_probe, + .driver = { + .name = "mediatek-mt2701-pinctrl", + .owner = THIS_MODULE, + .of_match_table = mt2701_pctrl_match, + .pm = &mtk_eint_pm_ops, + }, +}; + +static int __init mtk_pinctrl_init(void) +{ + return platform_driver_register(&mtk_pinctrl_driver); +} +arch_initcall(mtk_pinctrl_init); diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 16d48a4ed225..8cac73d9c382 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -47,6 +47,8 @@ static const char * const mtk_gpio_functions[] = { "func0", "func1", "func2", "func3", "func4", "func5", "func6", "func7", + "func8", "func9", "func10", "func11", + "func12", "func13", "func14", "func15", }; /* @@ -81,6 +83,9 @@ static int mtk_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, reg_addr = mtk_get_port(pctl, offset) + pctl->devdata->dir_offset; bit = BIT(offset & 0xf); + if (pctl->devdata->spec_dir_set) + pctl->devdata->spec_dir_set(®_addr, offset); + if (input) /* Different SoC has different alignment offset. */ reg_addr = CLR_ADDR(reg_addr, pctl); @@ -675,9 +680,14 @@ static int mtk_pmx_set_mode(struct pinctrl_dev *pctldev, unsigned int mask = (1L << GPIO_MODE_BITS) - 1; struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + if (pctl->devdata->spec_pinmux_set) + pctl->devdata->spec_pinmux_set(mtk_get_regmap(pctl, pin), + pin, mode); + reg_addr = ((pin / MAX_GPIO_MODE_PER_REG) << pctl->devdata->port_shf) + pctl->devdata->pinmux_offset; + mode &= mask; bit = pin % MAX_GPIO_MODE_PER_REG; mask <<= (GPIO_MODE_BITS * bit); val = (mode << (GPIO_MODE_BITS * bit)); @@ -754,6 +764,10 @@ static int mtk_gpio_get_direction(struct gpio_chip *chip, unsigned offset) reg_addr = mtk_get_port(pctl, offset) + pctl->devdata->dir_offset; bit = BIT(offset & 0xf); + + if (pctl->devdata->spec_dir_set) + pctl->devdata->spec_dir_set(®_addr, offset); + regmap_read(pctl->regmap1, reg_addr, &read_val); return !(read_val & bit); } diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h index 55a534338931..8543bc478a1e 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h @@ -209,7 +209,14 @@ struct mtk_eint_offsets { * means when user set smt, input enable is set at the same time. So they * also need special control. If special control is success, this should * return 0, otherwise return non-zero value. - * + * @spec_pinmux_set: In some cases, there are two pinmux functions share + * the same value in the same segment of pinmux control register. If user + * want to use one of the two functions, they need an extra bit setting to + * select the right one. + * @spec_dir_set: In very few SoCs, direction control registers are not + * arranged continuously, they may be cut to parts. So they need special + * dir setting. + * @dir_offset: The direction register offset. * @pullen_offset: The pull-up/pull-down enable register offset. * @pinmux_offset: The pinmux register offset. @@ -234,6 +241,9 @@ struct mtk_pinctrl_devdata { unsigned char align, bool isup, unsigned int arg); int (*spec_ies_smt_set)(struct regmap *reg, unsigned int pin, unsigned char align, int value, enum pin_config_param arg); + void (*spec_pinmux_set)(struct regmap *reg, unsigned int pin, + unsigned int mode); + void (*spec_dir_set)(unsigned int *reg_addr, unsigned int pin); unsigned int dir_offset; unsigned int ies_offset; unsigned int smt_offset; diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt2701.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt2701.h new file mode 100644 index 000000000000..f90642078c31 --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt2701.h @@ -0,0 +1,2323 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * Author: Biao Huang + * + * 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. + * + * 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. + */ + +#ifndef __PINCTRL_MTK_MT2701_H +#define __PINCTRL_MTK_MT2701_H + +#include +#include "pinctrl-mtk-common.h" + +static const struct mtk_desc_pin mtk_pins_mt2701[] = { + MTK_PIN( + PINCTRL_PIN(0, "PWRAP_SPI0_MI"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 148), + MTK_FUNCTION(0, "GPIO0"), + MTK_FUNCTION(1, "PWRAP_SPIDO"), + MTK_FUNCTION(2, "PWRAP_SPIDI") + ), + MTK_PIN( + PINCTRL_PIN(1, "PWRAP_SPI0_MO"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 149), + MTK_FUNCTION(0, "GPIO1"), + MTK_FUNCTION(1, "PWRAP_SPIDI"), + MTK_FUNCTION(2, "PWRAP_SPIDO") + ), + MTK_PIN( + PINCTRL_PIN(2, "PWRAP_INT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 150), + MTK_FUNCTION(0, "GPIO2"), + MTK_FUNCTION(1, "PWRAP_INT") + ), + MTK_PIN( + PINCTRL_PIN(3, "PWRAP_SPI0_CK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 151), + MTK_FUNCTION(0, "GPIO3"), + MTK_FUNCTION(1, "PWRAP_SPICK_I") + ), + MTK_PIN( + PINCTRL_PIN(4, "PWRAP_SPI0_CSN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 152), + MTK_FUNCTION(0, "GPIO4"), + MTK_FUNCTION(1, "PWRAP_SPICS_B_I") + ), + MTK_PIN( + PINCTRL_PIN(5, "PWRAP_SPI0_CK2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 153), + MTK_FUNCTION(0, "GPIO5"), + MTK_FUNCTION(1, "PWRAP_SPICK2_I"), + MTK_FUNCTION(5, "ANT_SEL1") + ), + MTK_PIN( + PINCTRL_PIN(6, "PWRAP_SPI0_CSN2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 154), + MTK_FUNCTION(0, "GPIO6"), + MTK_FUNCTION(1, "PWRAP_SPICS2_B_I"), + MTK_FUNCTION(5, "ANT_SEL0"), + MTK_FUNCTION(7, "DBG_MON_A[0]") + ), + MTK_PIN( + PINCTRL_PIN(7, "SPI1_CSN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 155), + MTK_FUNCTION(0, "GPIO7"), + MTK_FUNCTION(1, "SPI1_CS"), + MTK_FUNCTION(4, "KCOL0"), + MTK_FUNCTION(7, "DBG_MON_B[12]") + ), + MTK_PIN( + PINCTRL_PIN(8, "SPI1_MI"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 156), + MTK_FUNCTION(0, "GPIO8"), + MTK_FUNCTION(1, "SPI1_MI"), + MTK_FUNCTION(2, "SPI1_MO"), + MTK_FUNCTION(4, "KCOL1"), + MTK_FUNCTION(7, "DBG_MON_B[13]") + ), + MTK_PIN( + PINCTRL_PIN(9, "SPI1_MO"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 157), + MTK_FUNCTION(0, "GPIO9"), + MTK_FUNCTION(1, "SPI1_MO"), + MTK_FUNCTION(2, "SPI1_MI"), + MTK_FUNCTION(3, "EXT_FRAME_SYNC"), + MTK_FUNCTION(4, "KCOL2"), + MTK_FUNCTION(7, "DBG_MON_B[14]") + ), + MTK_PIN( + PINCTRL_PIN(10, "RTC32K_CK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 158), + MTK_FUNCTION(0, "GPIO10"), + MTK_FUNCTION(1, "RTC32K_CK") + ), + MTK_PIN( + PINCTRL_PIN(11, "WATCHDOG"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 159), + MTK_FUNCTION(0, "GPIO11"), + MTK_FUNCTION(1, "WATCHDOG") + ), + MTK_PIN( + PINCTRL_PIN(12, "SRCLKENA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 160), + MTK_FUNCTION(0, "GPIO12"), + MTK_FUNCTION(1, "SRCLKENA") + ), + MTK_PIN( + PINCTRL_PIN(13, "SRCLKENAI"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 161), + MTK_FUNCTION(0, "GPIO13"), + MTK_FUNCTION(1, "SRCLKENAI") + ), + MTK_PIN( + PINCTRL_PIN(14, "URXD2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 162), + MTK_FUNCTION(0, "GPIO14"), + MTK_FUNCTION(1, "URXD2"), + MTK_FUNCTION(2, "UTXD2"), + MTK_FUNCTION(5, "SRCCLKENAI2"), + MTK_FUNCTION(7, "DBG_MON_B[30]") + ), + MTK_PIN( + PINCTRL_PIN(15, "UTXD2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 163), + MTK_FUNCTION(0, "GPIO15"), + MTK_FUNCTION(1, "UTXD2"), + MTK_FUNCTION(2, "URXD2"), + MTK_FUNCTION(7, "DBG_MON_B[31]") + ), + MTK_PIN( + PINCTRL_PIN(16, "I2S5_DATA_IN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 164), + MTK_FUNCTION(0, "GPIO16"), + MTK_FUNCTION(1, "I2S5_DATA_IN"), + MTK_FUNCTION(3, "PCM_RX"), + MTK_FUNCTION(4, "ANT_SEL4") + ), + MTK_PIN( + PINCTRL_PIN(17, "I2S5_BCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 165), + MTK_FUNCTION(0, "GPIO17"), + MTK_FUNCTION(1, "I2S5_BCK"), + MTK_FUNCTION(3, "PCM_CLK0"), + MTK_FUNCTION(4, "ANT_SEL2") + ), + MTK_PIN( + PINCTRL_PIN(18, "PCM_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 166), + MTK_FUNCTION(0, "GPIO18"), + MTK_FUNCTION(1, "PCM_CLK0"), + MTK_FUNCTION(2, "MRG_CLK"), + MTK_FUNCTION(4, "MM_TEST_CK"), + MTK_FUNCTION(5, "CONN_DSP_JCK"), + MTK_FUNCTION(6, "WCN_PCM_CLKO"), + MTK_FUNCTION(7, "DBG_MON_A[3]") + ), + MTK_PIN( + PINCTRL_PIN(19, "PCM_SYNC"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 167), + MTK_FUNCTION(0, "GPIO19"), + MTK_FUNCTION(1, "PCM_SYNC"), + MTK_FUNCTION(2, "MRG_SYNC"), + MTK_FUNCTION(5, "CONN_DSP_JINTP"), + MTK_FUNCTION(6, "WCN_PCM_SYNC"), + MTK_FUNCTION(7, "DBG_MON_A[5]") + ), + MTK_PIN( + PINCTRL_PIN(20, "PCM_RX"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO20"), + MTK_FUNCTION(1, "PCM_RX"), + MTK_FUNCTION(2, "MRG_RX"), + MTK_FUNCTION(3, "MRG_TX"), + MTK_FUNCTION(4, "PCM_TX"), + MTK_FUNCTION(5, "CONN_DSP_JDI"), + MTK_FUNCTION(6, "WCN_PCM_RX"), + MTK_FUNCTION(7, "DBG_MON_A[4]") + ), + MTK_PIN( + PINCTRL_PIN(21, "PCM_TX"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO21"), + MTK_FUNCTION(1, "PCM_TX"), + MTK_FUNCTION(2, "MRG_TX"), + MTK_FUNCTION(3, "MRG_RX"), + MTK_FUNCTION(4, "PCM_RX"), + MTK_FUNCTION(5, "CONN_DSP_JMS"), + MTK_FUNCTION(6, "WCN_PCM_TX"), + MTK_FUNCTION(7, "DBG_MON_A[2]") + ), + MTK_PIN( + PINCTRL_PIN(22, "EINT0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 0), + MTK_FUNCTION(0, "GPIO22"), + MTK_FUNCTION(1, "UCTS0"), + MTK_FUNCTION(3, "KCOL3"), + MTK_FUNCTION(4, "CONN_DSP_JDO"), + MTK_FUNCTION(5, "EXT_FRAME_SYNC"), + MTK_FUNCTION(7, "DBG_MON_A[30]"), + MTK_FUNCTION(10, "PCIE0_PERST_N") + ), + MTK_PIN( + PINCTRL_PIN(23, "EINT1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 1), + MTK_FUNCTION(0, "GPIO23"), + MTK_FUNCTION(1, "URTS0"), + MTK_FUNCTION(3, "KCOL2"), + MTK_FUNCTION(4, "CONN_MCU_TDO"), + MTK_FUNCTION(5, "EXT_FRAME_SYNC"), + MTK_FUNCTION(7, "DBG_MON_A[29]"), + MTK_FUNCTION(10, "PCIE1_PERST_N") + ), + MTK_PIN( + PINCTRL_PIN(24, "EINT2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 2), + MTK_FUNCTION(0, "GPIO24"), + MTK_FUNCTION(1, "UCTS1"), + MTK_FUNCTION(3, "KCOL1"), + MTK_FUNCTION(4, "CONN_MCU_DBGACK_N"), + MTK_FUNCTION(7, "DBG_MON_A[28]"), + MTK_FUNCTION(10, "PCIE2_PERST_N") + ), + MTK_PIN( + PINCTRL_PIN(25, "EINT3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 3), + MTK_FUNCTION(0, "GPIO25"), + MTK_FUNCTION(1, "URTS1"), + MTK_FUNCTION(3, "KCOL0"), + MTK_FUNCTION(4, "CONN_MCU_DBGI_N"), + MTK_FUNCTION(7, "DBG_MON_A[27]") + ), + MTK_PIN( + PINCTRL_PIN(26, "EINT4"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 4), + MTK_FUNCTION(0, "GPIO26"), + MTK_FUNCTION(1, "UCTS3"), + MTK_FUNCTION(2, "DRV_VBUS_P1"), + MTK_FUNCTION(3, "KROW3"), + MTK_FUNCTION(4, "CONN_MCU_TCK0"), + MTK_FUNCTION(5, "CONN_MCU_AICE_JCKC"), + MTK_FUNCTION(6, "PCIE2_WAKE_N"), + MTK_FUNCTION(7, "DBG_MON_A[26]") + ), + MTK_PIN( + PINCTRL_PIN(27, "EINT5"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 5), + MTK_FUNCTION(0, "GPIO27"), + MTK_FUNCTION(1, "URTS3"), + MTK_FUNCTION(2, "IDDIG_P1"), + MTK_FUNCTION(3, "KROW2"), + MTK_FUNCTION(4, "CONN_MCU_TDI"), + MTK_FUNCTION(6, "PCIE1_WAKE_N"), + MTK_FUNCTION(7, "DBG_MON_A[25]") + ), + MTK_PIN( + PINCTRL_PIN(28, "EINT6"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 6), + MTK_FUNCTION(0, "GPIO28"), + MTK_FUNCTION(1, "DRV_VBUS"), + MTK_FUNCTION(3, "KROW1"), + MTK_FUNCTION(4, "CONN_MCU_TRST_B"), + MTK_FUNCTION(6, "PCIE0_WAKE_N"), + MTK_FUNCTION(7, "DBG_MON_A[24]") + ), + MTK_PIN( + PINCTRL_PIN(29, "EINT7"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 7), + MTK_FUNCTION(0, "GPIO29"), + MTK_FUNCTION(1, "IDDIG"), + MTK_FUNCTION(2, "MSDC1_WP"), + MTK_FUNCTION(3, "KROW0"), + MTK_FUNCTION(4, "CONN_MCU_TMS"), + MTK_FUNCTION(5, "CONN_MCU_AICE_JMSC"), + MTK_FUNCTION(7, "DBG_MON_A[23]"), + MTK_FUNCTION(14, "PCIE2_PERST_N") + ), + MTK_PIN( + PINCTRL_PIN(30, "I2S5_LRCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 12), + MTK_FUNCTION(0, "GPIO30"), + MTK_FUNCTION(1, "I2S5_LRCK"), + MTK_FUNCTION(3, "PCM_SYNC"), + MTK_FUNCTION(4, "ANT_SEL1") + ), + MTK_PIN( + PINCTRL_PIN(31, "I2S5_MCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 13), + MTK_FUNCTION(0, "GPIO31"), + MTK_FUNCTION(1, "I2S5_MCLK"), + MTK_FUNCTION(4, "ANT_SEL0") + ), + MTK_PIN( + PINCTRL_PIN(32, "I2S5_DATA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 14), + MTK_FUNCTION(0, "GPIO32"), + MTK_FUNCTION(1, "I2S5_DATA"), + MTK_FUNCTION(2, "I2S5_DATA_BYPS"), + MTK_FUNCTION(3, "PCM_TX"), + MTK_FUNCTION(4, "ANT_SEL3") + ), + MTK_PIN( + PINCTRL_PIN(33, "I2S1_DATA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 15), + MTK_FUNCTION(0, "GPIO33"), + MTK_FUNCTION(1, "I2S1_DATA"), + MTK_FUNCTION(2, "I2S1_DATA_BYPS"), + MTK_FUNCTION(3, "PCM_TX"), + MTK_FUNCTION(4, "IMG_TEST_CK"), + MTK_FUNCTION(5, "G1_RXD0"), + MTK_FUNCTION(6, "WCN_PCM_TX"), + MTK_FUNCTION(7, "DBG_MON_B[8]") + ), + MTK_PIN( + PINCTRL_PIN(34, "I2S1_DATA_IN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 16), + MTK_FUNCTION(0, "GPIO34"), + MTK_FUNCTION(1, "I2S1_DATA_IN"), + MTK_FUNCTION(3, "PCM_RX"), + MTK_FUNCTION(4, "VDEC_TEST_CK"), + MTK_FUNCTION(5, "G1_RXD1"), + MTK_FUNCTION(6, "WCN_PCM_RX"), + MTK_FUNCTION(7, "DBG_MON_B[7]") + ), + MTK_PIN( + PINCTRL_PIN(35, "I2S1_BCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 17), + MTK_FUNCTION(0, "GPIO35"), + MTK_FUNCTION(1, "I2S1_BCK"), + MTK_FUNCTION(3, "PCM_CLK0"), + MTK_FUNCTION(5, "G1_RXD2"), + MTK_FUNCTION(6, "WCN_PCM_CLKO"), + MTK_FUNCTION(7, "DBG_MON_B[9]") + ), + MTK_PIN( + PINCTRL_PIN(36, "I2S1_LRCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 18), + MTK_FUNCTION(0, "GPIO36"), + MTK_FUNCTION(1, "I2S1_LRCK"), + MTK_FUNCTION(3, "PCM_SYNC"), + MTK_FUNCTION(5, "G1_RXD3"), + MTK_FUNCTION(6, "WCN_PCM_SYNC"), + MTK_FUNCTION(7, "DBG_MON_B[10]") + ), + MTK_PIN( + PINCTRL_PIN(37, "I2S1_MCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 19), + MTK_FUNCTION(0, "GPIO37"), + MTK_FUNCTION(1, "I2S1_MCLK"), + MTK_FUNCTION(5, "G1_RXDV"), + MTK_FUNCTION(7, "DBG_MON_B[11]") + ), + MTK_PIN( + PINCTRL_PIN(38, "I2S2_DATA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 20), + MTK_FUNCTION(0, "GPIO38"), + MTK_FUNCTION(2, "I2S2_DATA_BYPS"), + MTK_FUNCTION(3, "PCM_TX"), + MTK_FUNCTION(4, "DMIC_DAT0") + ), + MTK_PIN( + PINCTRL_PIN(39, "JTMS"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 21), + MTK_FUNCTION(0, "GPIO39"), + MTK_FUNCTION(1, "JTMS"), + MTK_FUNCTION(2, "CONN_MCU_TMS"), + MTK_FUNCTION(3, "CONN_MCU_AICE_JMSC"), + MTK_FUNCTION(4, "DFD_TMS_XI") + ), + MTK_PIN( + PINCTRL_PIN(40, "JTCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 22), + MTK_FUNCTION(0, "GPIO40"), + MTK_FUNCTION(1, "JTCK"), + MTK_FUNCTION(2, "CONN_MCU_TCK1"), + MTK_FUNCTION(3, "CONN_MCU_AICE_JCKC"), + MTK_FUNCTION(4, "DFD_TCK_XI") + ), + MTK_PIN( + PINCTRL_PIN(41, "JTDI"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 23), + MTK_FUNCTION(0, "GPIO41"), + MTK_FUNCTION(1, "JTDI"), + MTK_FUNCTION(2, "CONN_MCU_TDI"), + MTK_FUNCTION(4, "DFD_TDI_XI") + ), + MTK_PIN( + PINCTRL_PIN(42, "JTDO"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 24), + MTK_FUNCTION(0, "GPIO42"), + MTK_FUNCTION(1, "JTDO"), + MTK_FUNCTION(2, "CONN_MCU_TDO"), + MTK_FUNCTION(4, "DFD_TDO") + ), + MTK_PIN( + PINCTRL_PIN(43, "NCLE"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 25), + MTK_FUNCTION(0, "GPIO43"), + MTK_FUNCTION(1, "NCLE"), + MTK_FUNCTION(2, "EXT_XCS2") + ), + MTK_PIN( + PINCTRL_PIN(44, "NCEB1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 26), + MTK_FUNCTION(0, "GPIO44"), + MTK_FUNCTION(1, "NCEB1"), + MTK_FUNCTION(2, "IDDIG") + ), + MTK_PIN( + PINCTRL_PIN(45, "NCEB0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 27), + MTK_FUNCTION(0, "GPIO45"), + MTK_FUNCTION(1, "NCEB0"), + MTK_FUNCTION(2, "DRV_VBUS") + ), + MTK_PIN( + PINCTRL_PIN(46, "IR"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 28), + MTK_FUNCTION(0, "GPIO46"), + MTK_FUNCTION(1, "IR") + ), + MTK_PIN( + PINCTRL_PIN(47, "NREB"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 29), + MTK_FUNCTION(0, "GPIO47"), + MTK_FUNCTION(1, "NREB"), + MTK_FUNCTION(2, "IDDIG_P1") + ), + MTK_PIN( + PINCTRL_PIN(48, "NRNB"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 30), + MTK_FUNCTION(0, "GPIO48"), + MTK_FUNCTION(1, "NRNB"), + MTK_FUNCTION(2, "DRV_VBUS_P1") + ), + MTK_PIN( + PINCTRL_PIN(49, "I2S0_DATA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 31), + MTK_FUNCTION(0, "GPIO49"), + MTK_FUNCTION(1, "I2S0_DATA"), + MTK_FUNCTION(2, "I2S0_DATA_BYPS"), + MTK_FUNCTION(3, "PCM_TX"), + MTK_FUNCTION(6, "WCN_I2S_DO"), + MTK_FUNCTION(7, "DBG_MON_B[3]") + ), + MTK_PIN( + PINCTRL_PIN(50, "I2S2_BCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 32), + MTK_FUNCTION(0, "GPIO50"), + MTK_FUNCTION(1, "I2S2_BCK"), + MTK_FUNCTION(3, "PCM_CLK0"), + MTK_FUNCTION(4, "DMIC_SCK1") + ), + MTK_PIN( + PINCTRL_PIN(51, "I2S2_DATA_IN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 33), + MTK_FUNCTION(0, "GPIO51"), + MTK_FUNCTION(1, "I2S2_DATA_IN"), + MTK_FUNCTION(3, "PCM_RX"), + MTK_FUNCTION(4, "DMIC_SCK0") + ), + MTK_PIN( + PINCTRL_PIN(52, "I2S2_LRCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 34), + MTK_FUNCTION(0, "GPIO52"), + MTK_FUNCTION(1, "I2S2_LRCK"), + MTK_FUNCTION(3, "PCM_SYNC"), + MTK_FUNCTION(4, "DMIC_DAT1") + ), + MTK_PIN( + PINCTRL_PIN(53, "SPI0_CSN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 35), + MTK_FUNCTION(0, "GPIO53"), + MTK_FUNCTION(1, "SPI0_CS"), + MTK_FUNCTION(3, "SPDIF"), + MTK_FUNCTION(4, "ADC_CK"), + MTK_FUNCTION(5, "PWM1"), + MTK_FUNCTION(7, "DBG_MON_A[7]") + ), + MTK_PIN( + PINCTRL_PIN(54, "SPI0_CK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 36), + MTK_FUNCTION(0, "GPIO54"), + MTK_FUNCTION(1, "SPI0_CK"), + MTK_FUNCTION(3, "SPDIF_IN1"), + MTK_FUNCTION(4, "ADC_DAT_IN"), + MTK_FUNCTION(7, "DBG_MON_A[10]") + ), + MTK_PIN( + PINCTRL_PIN(55, "SPI0_MI"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 37), + MTK_FUNCTION(0, "GPIO55"), + MTK_FUNCTION(1, "SPI0_MI"), + MTK_FUNCTION(2, "SPI0_MO"), + MTK_FUNCTION(3, "MSDC1_WP"), + MTK_FUNCTION(4, "ADC_WS"), + MTK_FUNCTION(5, "PWM2"), + MTK_FUNCTION(7, "DBG_MON_A[8]") + ), + MTK_PIN( + PINCTRL_PIN(56, "SPI0_MO"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 38), + MTK_FUNCTION(0, "GPIO56"), + MTK_FUNCTION(1, "SPI0_MO"), + MTK_FUNCTION(2, "SPI0_MI"), + MTK_FUNCTION(3, "SPDIF_IN0"), + MTK_FUNCTION(7, "DBG_MON_A[9]") + ), + MTK_PIN( + PINCTRL_PIN(57, "SDA1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 39), + MTK_FUNCTION(0, "GPIO57"), + MTK_FUNCTION(1, "SDA1") + ), + MTK_PIN( + PINCTRL_PIN(58, "SCL1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 40), + MTK_FUNCTION(0, "GPIO58"), + MTK_FUNCTION(1, "SCL1") + ), + MTK_PIN( + PINCTRL_PIN(59, "RAMBUF_I_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO59"), + MTK_FUNCTION(1, "RAMBUF_I_CLK") + ), + MTK_PIN( + PINCTRL_PIN(60, "WB_RSTB"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 41), + MTK_FUNCTION(0, "GPIO60"), + MTK_FUNCTION(1, "WB_RSTB"), + MTK_FUNCTION(7, "DBG_MON_A[11]") + ), + MTK_PIN( + PINCTRL_PIN(61, "F2W_DATA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 42), + MTK_FUNCTION(0, "GPIO61"), + MTK_FUNCTION(1, "F2W_DATA"), + MTK_FUNCTION(7, "DBG_MON_A[16]") + ), + MTK_PIN( + PINCTRL_PIN(62, "F2W_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 43), + MTK_FUNCTION(0, "GPIO62"), + MTK_FUNCTION(1, "F2W_CK"), + MTK_FUNCTION(7, "DBG_MON_A[15]") + ), + MTK_PIN( + PINCTRL_PIN(63, "WB_SCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 44), + MTK_FUNCTION(0, "GPIO63"), + MTK_FUNCTION(1, "WB_SCLK"), + MTK_FUNCTION(7, "DBG_MON_A[13]") + ), + MTK_PIN( + PINCTRL_PIN(64, "WB_SDATA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 45), + MTK_FUNCTION(0, "GPIO64"), + MTK_FUNCTION(1, "WB_SDATA"), + MTK_FUNCTION(7, "DBG_MON_A[12]") + ), + MTK_PIN( + PINCTRL_PIN(65, "WB_SEN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 46), + MTK_FUNCTION(0, "GPIO65"), + MTK_FUNCTION(1, "WB_SEN"), + MTK_FUNCTION(7, "DBG_MON_A[14]") + ), + MTK_PIN( + PINCTRL_PIN(66, "WB_CRTL0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 47), + MTK_FUNCTION(0, "GPIO66"), + MTK_FUNCTION(1, "WB_CRTL0"), + MTK_FUNCTION(5, "DFD_NTRST_XI"), + MTK_FUNCTION(7, "DBG_MON_A[17]") + ), + MTK_PIN( + PINCTRL_PIN(67, "WB_CRTL1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 48), + MTK_FUNCTION(0, "GPIO67"), + MTK_FUNCTION(1, "WB_CRTL1"), + MTK_FUNCTION(5, "DFD_TMS_XI"), + MTK_FUNCTION(7, "DBG_MON_A[18]") + ), + MTK_PIN( + PINCTRL_PIN(68, "WB_CRTL2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 49), + MTK_FUNCTION(0, "GPIO68"), + MTK_FUNCTION(1, "WB_CRTL2"), + MTK_FUNCTION(5, "DFD_TCK_XI"), + MTK_FUNCTION(7, "DBG_MON_A[19]") + ), + MTK_PIN( + PINCTRL_PIN(69, "WB_CRTL3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 50), + MTK_FUNCTION(0, "GPIO69"), + MTK_FUNCTION(1, "WB_CRTL3"), + MTK_FUNCTION(5, "DFD_TDI_XI"), + MTK_FUNCTION(7, "DBG_MON_A[20]") + ), + MTK_PIN( + PINCTRL_PIN(70, "WB_CRTL4"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 51), + MTK_FUNCTION(0, "GPIO70"), + MTK_FUNCTION(1, "WB_CRTL4"), + MTK_FUNCTION(5, "DFD_TDO"), + MTK_FUNCTION(7, "DBG_MON_A[21]") + ), + MTK_PIN( + PINCTRL_PIN(71, "WB_CRTL5"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 52), + MTK_FUNCTION(0, "GPIO71"), + MTK_FUNCTION(1, "WB_CRTL5"), + MTK_FUNCTION(7, "DBG_MON_A[22]") + ), + MTK_PIN( + PINCTRL_PIN(72, "I2S0_DATA_IN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 53), + MTK_FUNCTION(0, "GPIO72"), + MTK_FUNCTION(1, "I2S0_DATA_IN"), + MTK_FUNCTION(3, "PCM_RX"), + MTK_FUNCTION(4, "PWM0"), + MTK_FUNCTION(5, "DISP_PWM"), + MTK_FUNCTION(6, "WCN_I2S_DI"), + MTK_FUNCTION(7, "DBG_MON_B[2]") + ), + MTK_PIN( + PINCTRL_PIN(73, "I2S0_LRCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 54), + MTK_FUNCTION(0, "GPIO73"), + MTK_FUNCTION(1, "I2S0_LRCK"), + MTK_FUNCTION(3, "PCM_SYNC"), + MTK_FUNCTION(6, "WCN_I2S_LRCK"), + MTK_FUNCTION(7, "DBG_MON_B[5]") + ), + MTK_PIN( + PINCTRL_PIN(74, "I2S0_BCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 55), + MTK_FUNCTION(0, "GPIO74"), + MTK_FUNCTION(1, "I2S0_BCK"), + MTK_FUNCTION(3, "PCM_CLK0"), + MTK_FUNCTION(6, "WCN_I2S_BCK"), + MTK_FUNCTION(7, "DBG_MON_B[4]") + ), + MTK_PIN( + PINCTRL_PIN(75, "SDA0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 56), + MTK_FUNCTION(0, "GPIO75"), + MTK_FUNCTION(1, "SDA0") + ), + MTK_PIN( + PINCTRL_PIN(76, "SCL0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 57), + MTK_FUNCTION(0, "GPIO76"), + MTK_FUNCTION(1, "SCL0") + ), + MTK_PIN( + PINCTRL_PIN(77, "SDA2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 58), + MTK_FUNCTION(0, "GPIO77"), + MTK_FUNCTION(1, "SDA2") + ), + MTK_PIN( + PINCTRL_PIN(78, "SCL2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 59), + MTK_FUNCTION(0, "GPIO78"), + MTK_FUNCTION(1, "SCL2") + ), + MTK_PIN( + PINCTRL_PIN(79, "URXD0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 60), + MTK_FUNCTION(0, "GPIO79"), + MTK_FUNCTION(1, "URXD0"), + MTK_FUNCTION(2, "UTXD0") + ), + MTK_PIN( + PINCTRL_PIN(80, "UTXD0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 61), + MTK_FUNCTION(0, "GPIO80"), + MTK_FUNCTION(1, "UTXD0"), + MTK_FUNCTION(2, "URXD0") + ), + MTK_PIN( + PINCTRL_PIN(81, "URXD1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 62), + MTK_FUNCTION(0, "GPIO81"), + MTK_FUNCTION(1, "URXD1"), + MTK_FUNCTION(2, "UTXD1") + ), + MTK_PIN( + PINCTRL_PIN(82, "UTXD1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 63), + MTK_FUNCTION(0, "GPIO82"), + MTK_FUNCTION(1, "UTXD1"), + MTK_FUNCTION(2, "URXD1") + ), + MTK_PIN( + PINCTRL_PIN(83, "LCM_RST"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 64), + MTK_FUNCTION(0, "GPIO83"), + MTK_FUNCTION(1, "LCM_RST"), + MTK_FUNCTION(2, "VDAC_CK_XI"), + MTK_FUNCTION(7, "DBG_MON_B[1]") + ), + MTK_PIN( + PINCTRL_PIN(84, "DSI_TE"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 65), + MTK_FUNCTION(0, "GPIO84"), + MTK_FUNCTION(1, "DSI_TE"), + MTK_FUNCTION(7, "DBG_MON_B[0]") + ), + MTK_PIN( + PINCTRL_PIN(85, "MSDC2_CMD"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 66), + MTK_FUNCTION(0, "GPIO85"), + MTK_FUNCTION(1, "MSDC2_CMD"), + MTK_FUNCTION(2, "ANT_SEL0"), + MTK_FUNCTION(3, "SDA1"), + MTK_FUNCTION(6, "I2SOUT_BCK") + ), + MTK_PIN( + PINCTRL_PIN(86, "MSDC2_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 67), + MTK_FUNCTION(0, "GPIO86"), + MTK_FUNCTION(1, "MSDC2_CLK"), + MTK_FUNCTION(2, "ANT_SEL1"), + MTK_FUNCTION(3, "SCL1"), + MTK_FUNCTION(6, "I2SOUT_LRCK") + ), + MTK_PIN( + PINCTRL_PIN(87, "MSDC2_DAT0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 68), + MTK_FUNCTION(0, "GPIO87"), + MTK_FUNCTION(1, "MSDC2_DAT0"), + MTK_FUNCTION(2, "ANT_SEL2"), + MTK_FUNCTION(5, "UTXD0"), + MTK_FUNCTION(6, "I2SOUT_DATA_OUT") + ), + MTK_PIN( + PINCTRL_PIN(88, "MSDC2_DAT1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 71), + MTK_FUNCTION(0, "GPIO88"), + MTK_FUNCTION(1, "MSDC2_DAT1"), + MTK_FUNCTION(2, "ANT_SEL3"), + MTK_FUNCTION(3, "PWM0"), + MTK_FUNCTION(5, "URXD0"), + MTK_FUNCTION(6, "PWM1") + ), + MTK_PIN( + PINCTRL_PIN(89, "MSDC2_DAT2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 72), + MTK_FUNCTION(0, "GPIO89"), + MTK_FUNCTION(1, "MSDC2_DAT2"), + MTK_FUNCTION(2, "ANT_SEL4"), + MTK_FUNCTION(3, "SDA2"), + MTK_FUNCTION(5, "UTXD1"), + MTK_FUNCTION(6, "PWM2") + ), + MTK_PIN( + PINCTRL_PIN(90, "MSDC2_DAT3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 73), + MTK_FUNCTION(0, "GPIO90"), + MTK_FUNCTION(1, "MSDC2_DAT3"), + MTK_FUNCTION(2, "ANT_SEL5"), + MTK_FUNCTION(3, "SCL2"), + MTK_FUNCTION(4, "EXT_FRAME_SYNC"), + MTK_FUNCTION(5, "URXD1"), + MTK_FUNCTION(6, "PWM3") + ), + MTK_PIN( + PINCTRL_PIN(91, "TDN3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI91"), + MTK_FUNCTION(1, "TDN3") + ), + MTK_PIN( + PINCTRL_PIN(92, "TDP3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI92"), + MTK_FUNCTION(1, "TDP3") + ), + MTK_PIN( + PINCTRL_PIN(93, "TDN2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI93"), + MTK_FUNCTION(1, "TDN2") + ), + MTK_PIN( + PINCTRL_PIN(94, "TDP2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI94"), + MTK_FUNCTION(1, "TDP2") + ), + MTK_PIN( + PINCTRL_PIN(95, "TCN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI95"), + MTK_FUNCTION(1, "TCN") + ), + MTK_PIN( + PINCTRL_PIN(96, "TCP"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI96"), + MTK_FUNCTION(1, "TCP") + ), + MTK_PIN( + PINCTRL_PIN(97, "TDN1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI97"), + MTK_FUNCTION(1, "TDN1") + ), + MTK_PIN( + PINCTRL_PIN(98, "TDP1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI98"), + MTK_FUNCTION(1, "TDP1") + ), + MTK_PIN( + PINCTRL_PIN(99, "TDN0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI99"), + MTK_FUNCTION(1, "TDN0") + ), + MTK_PIN( + PINCTRL_PIN(100, "TDP0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI100"), + MTK_FUNCTION(1, "TDP0") + ), + MTK_PIN( + PINCTRL_PIN(101, "SPI2_CSN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 74), + MTK_FUNCTION(0, "GPIO101"), + MTK_FUNCTION(1, "SPI2_CS"), + MTK_FUNCTION(3, "SCL3"), + MTK_FUNCTION(4, "KROW0") + ), + MTK_PIN( + PINCTRL_PIN(102, "SPI2_MI"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 75), + MTK_FUNCTION(0, "GPIO102"), + MTK_FUNCTION(1, "SPI2_MI"), + MTK_FUNCTION(2, "SPI2_MO"), + MTK_FUNCTION(3, "SDA3"), + MTK_FUNCTION(4, "KROW1") + ), + MTK_PIN( + PINCTRL_PIN(103, "SPI2_MO"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 76), + MTK_FUNCTION(0, "GPIO103"), + MTK_FUNCTION(1, "SPI2_MO"), + MTK_FUNCTION(2, "SPI2_MI"), + MTK_FUNCTION(3, "SCL3"), + MTK_FUNCTION(4, "KROW2") + ), + MTK_PIN( + PINCTRL_PIN(104, "SPI2_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 77), + MTK_FUNCTION(0, "GPIO104"), + MTK_FUNCTION(1, "SPI2_CK"), + MTK_FUNCTION(3, "SDA3"), + MTK_FUNCTION(4, "KROW3") + ), + MTK_PIN( + PINCTRL_PIN(105, "MSDC1_CMD"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 78), + MTK_FUNCTION(0, "GPIO105"), + MTK_FUNCTION(1, "MSDC1_CMD"), + MTK_FUNCTION(2, "ANT_SEL0"), + MTK_FUNCTION(3, "SDA1"), + MTK_FUNCTION(6, "I2SOUT_BCK"), + MTK_FUNCTION(7, "DBG_MON_B[27]") + ), + MTK_PIN( + PINCTRL_PIN(106, "MSDC1_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 79), + MTK_FUNCTION(0, "GPIO106"), + MTK_FUNCTION(1, "MSDC1_CLK"), + MTK_FUNCTION(2, "ANT_SEL1"), + MTK_FUNCTION(3, "SCL1"), + MTK_FUNCTION(6, "I2SOUT_LRCK"), + MTK_FUNCTION(7, "DBG_MON_B[28]") + ), + MTK_PIN( + PINCTRL_PIN(107, "MSDC1_DAT0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 80), + MTK_FUNCTION(0, "GPIO107"), + MTK_FUNCTION(1, "MSDC1_DAT0"), + MTK_FUNCTION(2, "ANT_SEL2"), + MTK_FUNCTION(5, "UTXD0"), + MTK_FUNCTION(6, "I2SOUT_DATA_OUT"), + MTK_FUNCTION(7, "DBG_MON_B[26]") + ), + MTK_PIN( + PINCTRL_PIN(108, "MSDC1_DAT1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 81), + MTK_FUNCTION(0, "GPIO108"), + MTK_FUNCTION(1, "MSDC1_DAT1"), + MTK_FUNCTION(2, "ANT_SEL3"), + MTK_FUNCTION(3, "PWM0"), + MTK_FUNCTION(5, "URXD0"), + MTK_FUNCTION(6, "PWM1"), + MTK_FUNCTION(7, "DBG_MON_B[25]") + ), + MTK_PIN( + PINCTRL_PIN(109, "MSDC1_DAT2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 82), + MTK_FUNCTION(0, "GPIO109"), + MTK_FUNCTION(1, "MSDC1_DAT2"), + MTK_FUNCTION(2, "ANT_SEL4"), + MTK_FUNCTION(3, "SDA2"), + MTK_FUNCTION(5, "UTXD1"), + MTK_FUNCTION(6, "PWM2"), + MTK_FUNCTION(7, "DBG_MON_B[24]") + ), + MTK_PIN( + PINCTRL_PIN(110, "MSDC1_DAT3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 83), + MTK_FUNCTION(0, "GPIO110"), + MTK_FUNCTION(1, "MSDC1_DAT3"), + MTK_FUNCTION(2, "ANT_SEL5"), + MTK_FUNCTION(3, "SCL2"), + MTK_FUNCTION(4, "EXT_FRAME_SYNC"), + MTK_FUNCTION(5, "URXD1"), + MTK_FUNCTION(6, "PWM3"), + MTK_FUNCTION(7, "DBG_MON_B[23]") + ), + MTK_PIN( + PINCTRL_PIN(111, "MSDC0_DAT7"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 84), + MTK_FUNCTION(0, "GPIO111"), + MTK_FUNCTION(1, "MSDC0_DAT7"), + MTK_FUNCTION(4, "NLD7") + ), + MTK_PIN( + PINCTRL_PIN(112, "MSDC0_DAT6"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 85), + MTK_FUNCTION(0, "GPIO112"), + MTK_FUNCTION(1, "MSDC0_DAT6"), + MTK_FUNCTION(4, "NLD6") + ), + MTK_PIN( + PINCTRL_PIN(113, "MSDC0_DAT5"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 86), + MTK_FUNCTION(0, "GPIO113"), + MTK_FUNCTION(1, "MSDC0_DAT5"), + MTK_FUNCTION(4, "NLD5") + ), + MTK_PIN( + PINCTRL_PIN(114, "MSDC0_DAT4"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 87), + MTK_FUNCTION(0, "GPIO114"), + MTK_FUNCTION(1, "MSDC0_DAT4"), + MTK_FUNCTION(4, "NLD4") + ), + MTK_PIN( + PINCTRL_PIN(115, "MSDC0_RSTB"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 88), + MTK_FUNCTION(0, "GPIO115"), + MTK_FUNCTION(1, "MSDC0_RSTB"), + MTK_FUNCTION(4, "NLD8") + ), + MTK_PIN( + PINCTRL_PIN(116, "MSDC0_CMD"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 89), + MTK_FUNCTION(0, "GPIO116"), + MTK_FUNCTION(1, "MSDC0_CMD"), + MTK_FUNCTION(4, "NALE") + ), + MTK_PIN( + PINCTRL_PIN(117, "MSDC0_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 90), + MTK_FUNCTION(0, "GPIO117"), + MTK_FUNCTION(1, "MSDC0_CLK"), + MTK_FUNCTION(4, "NWEB") + ), + MTK_PIN( + PINCTRL_PIN(118, "MSDC0_DAT3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 91), + MTK_FUNCTION(0, "GPIO118"), + MTK_FUNCTION(1, "MSDC0_DAT3"), + MTK_FUNCTION(4, "NLD3") + ), + MTK_PIN( + PINCTRL_PIN(119, "MSDC0_DAT2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 92), + MTK_FUNCTION(0, "GPIO119"), + MTK_FUNCTION(1, "MSDC0_DAT2"), + MTK_FUNCTION(4, "NLD2") + ), + MTK_PIN( + PINCTRL_PIN(120, "MSDC0_DAT1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 93), + MTK_FUNCTION(0, "GPIO120"), + MTK_FUNCTION(1, "MSDC0_DAT1"), + MTK_FUNCTION(4, "NLD1") + ), + MTK_PIN( + PINCTRL_PIN(121, "MSDC0_DAT0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 94), + MTK_FUNCTION(0, "GPIO121"), + MTK_FUNCTION(1, "MSDC0_DAT0"), + MTK_FUNCTION(4, "NLD0"), + MTK_FUNCTION(5, "WATCHDOG") + ), + MTK_PIN( + PINCTRL_PIN(122, "CEC"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 95), + MTK_FUNCTION(0, "GPIO122"), + MTK_FUNCTION(1, "CEC"), + MTK_FUNCTION(4, "SDA2"), + MTK_FUNCTION(5, "URXD0") + ), + MTK_PIN( + PINCTRL_PIN(123, "HTPLG"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 96), + MTK_FUNCTION(0, "GPIO123"), + MTK_FUNCTION(1, "HTPLG"), + MTK_FUNCTION(4, "SCL2"), + MTK_FUNCTION(5, "UTXD0") + ), + MTK_PIN( + PINCTRL_PIN(124, "HDMISCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 97), + MTK_FUNCTION(0, "GPIO124"), + MTK_FUNCTION(1, "HDMISCK"), + MTK_FUNCTION(4, "SDA1"), + MTK_FUNCTION(5, "PWM3") + ), + MTK_PIN( + PINCTRL_PIN(125, "HDMISD"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 98), + MTK_FUNCTION(0, "GPIO125"), + MTK_FUNCTION(1, "HDMISD"), + MTK_FUNCTION(4, "SCL1"), + MTK_FUNCTION(5, "PWM4") + ), + MTK_PIN( + PINCTRL_PIN(126, "I2S0_MCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 99), + MTK_FUNCTION(0, "GPIO126"), + MTK_FUNCTION(1, "I2S0_MCLK"), + MTK_FUNCTION(6, "WCN_I2S_MCLK"), + MTK_FUNCTION(7, "DBG_MON_B[6]") + ), + MTK_PIN( + PINCTRL_PIN(127, "RAMBUF_IDATA0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO127"), + MTK_FUNCTION(1, "RAMBUF_IDATA0") + ), + MTK_PIN( + PINCTRL_PIN(128, "RAMBUF_IDATA1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO128"), + MTK_FUNCTION(1, "RAMBUF_IDATA1") + ), + MTK_PIN( + PINCTRL_PIN(129, "RAMBUF_IDATA2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO129"), + MTK_FUNCTION(1, "RAMBUF_IDATA2") + ), + MTK_PIN( + PINCTRL_PIN(130, "RAMBUF_IDATA3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO130"), + MTK_FUNCTION(1, "RAMBUF_IDATA3") + ), + MTK_PIN( + PINCTRL_PIN(131, "RAMBUF_IDATA4"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO131"), + MTK_FUNCTION(1, "RAMBUF_IDATA4") + ), + MTK_PIN( + PINCTRL_PIN(132, "RAMBUF_IDATA5"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO132"), + MTK_FUNCTION(1, "RAMBUF_IDATA5") + ), + MTK_PIN( + PINCTRL_PIN(133, "RAMBUF_IDATA6"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO133"), + MTK_FUNCTION(1, "RAMBUF_IDATA6") + ), + MTK_PIN( + PINCTRL_PIN(134, "RAMBUF_IDATA7"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO134"), + MTK_FUNCTION(1, "RAMBUF_IDATA7") + ), + MTK_PIN( + PINCTRL_PIN(135, "RAMBUF_IDATA8"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO135"), + MTK_FUNCTION(1, "RAMBUF_IDATA8") + ), + MTK_PIN( + PINCTRL_PIN(136, "RAMBUF_IDATA9"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO136"), + MTK_FUNCTION(1, "RAMBUF_IDATA9") + ), + MTK_PIN( + PINCTRL_PIN(137, "RAMBUF_IDATA10"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO137"), + MTK_FUNCTION(1, "RAMBUF_IDATA10") + ), + MTK_PIN( + PINCTRL_PIN(138, "RAMBUF_IDATA11"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO138"), + MTK_FUNCTION(1, "RAMBUF_IDATA11") + ), + MTK_PIN( + PINCTRL_PIN(139, "RAMBUF_IDATA12"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO139"), + MTK_FUNCTION(1, "RAMBUF_IDATA12") + ), + MTK_PIN( + PINCTRL_PIN(140, "RAMBUF_IDATA13"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO140"), + MTK_FUNCTION(1, "RAMBUF_IDATA13") + ), + MTK_PIN( + PINCTRL_PIN(141, "RAMBUF_IDATA14"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO141"), + MTK_FUNCTION(1, "RAMBUF_IDATA14") + ), + MTK_PIN( + PINCTRL_PIN(142, "RAMBUF_IDATA15"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO142"), + MTK_FUNCTION(1, "RAMBUF_IDATA15") + ), + MTK_PIN( + PINCTRL_PIN(143, "RAMBUF_ODATA0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO143"), + MTK_FUNCTION(1, "RAMBUF_ODATA0") + ), + MTK_PIN( + PINCTRL_PIN(144, "RAMBUF_ODATA1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO144"), + MTK_FUNCTION(1, "RAMBUF_ODATA1") + ), + MTK_PIN( + PINCTRL_PIN(145, "RAMBUF_ODATA2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO145"), + MTK_FUNCTION(1, "RAMBUF_ODATA2") + ), + MTK_PIN( + PINCTRL_PIN(146, "RAMBUF_ODATA3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO146"), + MTK_FUNCTION(1, "RAMBUF_ODATA3") + ), + MTK_PIN( + PINCTRL_PIN(147, "RAMBUF_ODATA4"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO147"), + MTK_FUNCTION(1, "RAMBUF_ODATA4") + ), + MTK_PIN( + PINCTRL_PIN(148, "RAMBUF_ODATA5"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO148"), + MTK_FUNCTION(1, "RAMBUF_ODATA5") + ), + MTK_PIN( + PINCTRL_PIN(149, "RAMBUF_ODATA6"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO149"), + MTK_FUNCTION(1, "RAMBUF_ODATA6") + ), + MTK_PIN( + PINCTRL_PIN(150, "RAMBUF_ODATA7"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO150"), + MTK_FUNCTION(1, "RAMBUF_ODATA7") + ), + MTK_PIN( + PINCTRL_PIN(151, "RAMBUF_ODATA8"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO151"), + MTK_FUNCTION(1, "RAMBUF_ODATA8") + ), + MTK_PIN( + PINCTRL_PIN(152, "RAMBUF_ODATA9"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO152"), + MTK_FUNCTION(1, "RAMBUF_ODATA9") + ), + MTK_PIN( + PINCTRL_PIN(153, "RAMBUF_ODATA10"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO153"), + MTK_FUNCTION(1, "RAMBUF_ODATA10") + ), + MTK_PIN( + PINCTRL_PIN(154, "RAMBUF_ODATA11"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO154"), + MTK_FUNCTION(1, "RAMBUF_ODATA11") + ), + MTK_PIN( + PINCTRL_PIN(155, "RAMBUF_ODATA12"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO155"), + MTK_FUNCTION(1, "RAMBUF_ODATA12") + ), + MTK_PIN( + PINCTRL_PIN(156, "RAMBUF_ODATA13"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO156"), + MTK_FUNCTION(1, "RAMBUF_ODATA13") + ), + MTK_PIN( + PINCTRL_PIN(157, "RAMBUF_ODATA14"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO157"), + MTK_FUNCTION(1, "RAMBUF_ODATA14") + ), + MTK_PIN( + PINCTRL_PIN(158, "RAMBUF_ODATA15"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO158"), + MTK_FUNCTION(1, "RAMBUF_ODATA15") + ), + MTK_PIN( + PINCTRL_PIN(159, "RAMBUF_BE0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO159"), + MTK_FUNCTION(1, "RAMBUF_BE0") + ), + MTK_PIN( + PINCTRL_PIN(160, "RAMBUF_BE1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO160"), + MTK_FUNCTION(1, "RAMBUF_BE1") + ), + MTK_PIN( + PINCTRL_PIN(161, "AP2PT_INT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO161"), + MTK_FUNCTION(1, "AP2PT_INT") + ), + MTK_PIN( + PINCTRL_PIN(162, "AP2PT_INT_CLR"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO162"), + MTK_FUNCTION(1, "AP2PT_INT_CLR") + ), + MTK_PIN( + PINCTRL_PIN(163, "PT2AP_INT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO163"), + MTK_FUNCTION(1, "PT2AP_INT") + ), + MTK_PIN( + PINCTRL_PIN(164, "PT2AP_INT_CLR"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO164"), + MTK_FUNCTION(1, "PT2AP_INT_CLR") + ), + MTK_PIN( + PINCTRL_PIN(165, "AP2UP_INT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO165"), + MTK_FUNCTION(1, "AP2UP_INT") + ), + MTK_PIN( + PINCTRL_PIN(166, "AP2UP_INT_CLR"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO166"), + MTK_FUNCTION(1, "AP2UP_INT_CLR") + ), + MTK_PIN( + PINCTRL_PIN(167, "UP2AP_INT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO167"), + MTK_FUNCTION(1, "UP2AP_INT") + ), + MTK_PIN( + PINCTRL_PIN(168, "UP2AP_INT_CLR"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO168"), + MTK_FUNCTION(1, "UP2AP_INT_CLR") + ), + MTK_PIN( + PINCTRL_PIN(169, "RAMBUF_ADDR0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO169"), + MTK_FUNCTION(1, "RAMBUF_ADDR0") + ), + MTK_PIN( + PINCTRL_PIN(170, "RAMBUF_ADDR1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO170"), + MTK_FUNCTION(1, "RAMBUF_ADDR1") + ), + MTK_PIN( + PINCTRL_PIN(171, "RAMBUF_ADDR2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO171"), + MTK_FUNCTION(1, "RAMBUF_ADDR2") + ), + MTK_PIN( + PINCTRL_PIN(172, "RAMBUF_ADDR3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO172"), + MTK_FUNCTION(1, "RAMBUF_ADDR3") + ), + MTK_PIN( + PINCTRL_PIN(173, "RAMBUF_ADDR4"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO173"), + MTK_FUNCTION(1, "RAMBUF_ADDR4") + ), + MTK_PIN( + PINCTRL_PIN(174, "RAMBUF_ADDR5"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO174"), + MTK_FUNCTION(1, "RAMBUF_ADDR5") + ), + MTK_PIN( + PINCTRL_PIN(175, "RAMBUF_ADDR6"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO175"), + MTK_FUNCTION(1, "RAMBUF_ADDR6") + ), + MTK_PIN( + PINCTRL_PIN(176, "RAMBUF_ADDR7"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO176"), + MTK_FUNCTION(1, "RAMBUF_ADDR7") + ), + MTK_PIN( + PINCTRL_PIN(177, "RAMBUF_ADDR8"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO177"), + MTK_FUNCTION(1, "RAMBUF_ADDR8") + ), + MTK_PIN( + PINCTRL_PIN(178, "RAMBUF_ADDR9"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO178"), + MTK_FUNCTION(1, "RAMBUF_ADDR9") + ), + MTK_PIN( + PINCTRL_PIN(179, "RAMBUF_ADDR10"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO179"), + MTK_FUNCTION(1, "RAMBUF_ADDR10") + ), + MTK_PIN( + PINCTRL_PIN(180, "RAMBUF_RW"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO180"), + MTK_FUNCTION(1, "RAMBUF_RW") + ), + MTK_PIN( + PINCTRL_PIN(181, "RAMBUF_LAST"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO181"), + MTK_FUNCTION(1, "RAMBUF_LAST") + ), + MTK_PIN( + PINCTRL_PIN(182, "RAMBUF_HP"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO182"), + MTK_FUNCTION(1, "RAMBUF_HP") + ), + MTK_PIN( + PINCTRL_PIN(183, "RAMBUF_REQ"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO183"), + MTK_FUNCTION(1, "RAMBUF_REQ") + ), + MTK_PIN( + PINCTRL_PIN(184, "RAMBUF_ALE"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO184"), + MTK_FUNCTION(1, "RAMBUF_ALE") + ), + MTK_PIN( + PINCTRL_PIN(185, "RAMBUF_DLE"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO185"), + MTK_FUNCTION(1, "RAMBUF_DLE") + ), + MTK_PIN( + PINCTRL_PIN(186, "RAMBUF_WDLE"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO186"), + MTK_FUNCTION(1, "RAMBUF_WDLE") + ), + MTK_PIN( + PINCTRL_PIN(187, "RAMBUF_O_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO187"), + MTK_FUNCTION(1, "RAMBUF_O_CLK") + ), + MTK_PIN( + PINCTRL_PIN(188, "I2S2_MCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 100), + MTK_FUNCTION(0, "GPIO188"), + MTK_FUNCTION(1, "I2S2_MCLK") + ), + MTK_PIN( + PINCTRL_PIN(189, "I2S3_DATA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 101), + MTK_FUNCTION(0, "GPIO189"), + MTK_FUNCTION(2, "I2S3_DATA_BYPS"), + MTK_FUNCTION(3, "PCM_TX") + ), + MTK_PIN( + PINCTRL_PIN(190, "I2S3_DATA_IN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 102), + MTK_FUNCTION(0, "GPIO190"), + MTK_FUNCTION(1, "I2S3_DATA_IN"), + MTK_FUNCTION(3, "PCM_RX") + ), + MTK_PIN( + PINCTRL_PIN(191, "I2S3_BCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 103), + MTK_FUNCTION(0, "GPIO191"), + MTK_FUNCTION(1, "I2S3_BCK"), + MTK_FUNCTION(3, "PCM_CLK0") + ), + MTK_PIN( + PINCTRL_PIN(192, "I2S3_LRCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 104), + MTK_FUNCTION(0, "GPIO192"), + MTK_FUNCTION(1, "I2S3_LRCK"), + MTK_FUNCTION(3, "PCM_SYNC") + ), + MTK_PIN( + PINCTRL_PIN(193, "I2S3_MCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 105), + MTK_FUNCTION(0, "GPIO193"), + MTK_FUNCTION(1, "I2S3_MCLK") + ), + MTK_PIN( + PINCTRL_PIN(194, "I2S4_DATA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 106), + MTK_FUNCTION(0, "GPIO194"), + MTK_FUNCTION(1, "I2S4_DATA"), + MTK_FUNCTION(2, "I2S4_DATA_BYPS"), + MTK_FUNCTION(3, "PCM_TX") + ), + MTK_PIN( + PINCTRL_PIN(195, "I2S4_DATA_IN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 107), + MTK_FUNCTION(0, "GPIO195"), + MTK_FUNCTION(1, "I2S4_DATA_IN"), + MTK_FUNCTION(3, "PCM_RX") + ), + MTK_PIN( + PINCTRL_PIN(196, "I2S4_BCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 108), + MTK_FUNCTION(0, "GPIO196"), + MTK_FUNCTION(1, "I2S4_BCK"), + MTK_FUNCTION(3, "PCM_CLK0") + ), + MTK_PIN( + PINCTRL_PIN(197, "I2S4_LRCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 109), + MTK_FUNCTION(0, "GPIO197"), + MTK_FUNCTION(1, "I2S4_LRCK"), + MTK_FUNCTION(3, "PCM_SYNC") + ), + MTK_PIN( + PINCTRL_PIN(198, "I2S4_MCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 110), + MTK_FUNCTION(0, "GPIO198"), + MTK_FUNCTION(1, "I2S4_MCLK") + ), + MTK_PIN( + PINCTRL_PIN(199, "SPI1_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 111), + MTK_FUNCTION(0, "GPIO199"), + MTK_FUNCTION(1, "SPI1_CK"), + MTK_FUNCTION(3, "EXT_FRAME_SYNC"), + MTK_FUNCTION(4, "KCOL3"), + MTK_FUNCTION(7, "DBG_MON_B[15]") + ), + MTK_PIN( + PINCTRL_PIN(200, "SPDIF_OUT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 112), + MTK_FUNCTION(0, "GPIO200"), + MTK_FUNCTION(1, "SPDIF_OUT"), + MTK_FUNCTION(5, "G1_TXD3"), + MTK_FUNCTION(6, "URXD2"), + MTK_FUNCTION(7, "DBG_MON_B[16]") + ), + MTK_PIN( + PINCTRL_PIN(201, "SPDIF_IN0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 113), + MTK_FUNCTION(0, "GPIO201"), + MTK_FUNCTION(1, "SPDIF_IN0"), + MTK_FUNCTION(5, "G1_TXEN"), + MTK_FUNCTION(6, "UTXD2"), + MTK_FUNCTION(7, "DBG_MON_B[17]") + ), + MTK_PIN( + PINCTRL_PIN(202, "SPDIF_IN1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 114), + MTK_FUNCTION(0, "GPIO202"), + MTK_FUNCTION(1, "SPDIF_IN1") + ), + MTK_PIN( + PINCTRL_PIN(203, "PWM0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 115), + MTK_FUNCTION(0, "GPIO203"), + MTK_FUNCTION(1, "PWM0"), + MTK_FUNCTION(2, "DISP_PWM"), + MTK_FUNCTION(5, "G1_TXD2"), + MTK_FUNCTION(7, "DBG_MON_B[18]"), + MTK_FUNCTION(9, "I2S2_DATA") + ), + MTK_PIN( + PINCTRL_PIN(204, "PWM1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 116), + MTK_FUNCTION(0, "GPIO204"), + MTK_FUNCTION(1, "PWM1"), + MTK_FUNCTION(2, "CLKM3"), + MTK_FUNCTION(5, "G1_TXD1"), + MTK_FUNCTION(7, "DBG_MON_B[19]"), + MTK_FUNCTION(9, "I2S3_DATA") + ), + MTK_PIN( + PINCTRL_PIN(205, "PWM2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 117), + MTK_FUNCTION(0, "GPIO205"), + MTK_FUNCTION(1, "PWM2"), + MTK_FUNCTION(2, "CLKM2"), + MTK_FUNCTION(5, "G1_TXD0"), + MTK_FUNCTION(7, "DBG_MON_B[20]") + ), + MTK_PIN( + PINCTRL_PIN(206, "PWM3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 118), + MTK_FUNCTION(0, "GPIO206"), + MTK_FUNCTION(1, "PWM3"), + MTK_FUNCTION(2, "CLKM1"), + MTK_FUNCTION(3, "EXT_FRAME_SYNC"), + MTK_FUNCTION(5, "G1_TXC"), + MTK_FUNCTION(7, "DBG_MON_B[21]") + ), + MTK_PIN( + PINCTRL_PIN(207, "PWM4"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 119), + MTK_FUNCTION(0, "GPIO207"), + MTK_FUNCTION(1, "PWM4"), + MTK_FUNCTION(2, "CLKM0"), + MTK_FUNCTION(3, "EXT_FRAME_SYNC"), + MTK_FUNCTION(5, "G1_RXC"), + MTK_FUNCTION(7, "DBG_MON_B[22]") + ), + MTK_PIN( + PINCTRL_PIN(208, "AUD_EXT_CK1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 120), + MTK_FUNCTION(0, "GPIO208"), + MTK_FUNCTION(1, "AUD_EXT_CK1"), + MTK_FUNCTION(2, "PWM0"), + MTK_FUNCTION(4, "ANT_SEL5"), + MTK_FUNCTION(5, "DISP_PWM"), + MTK_FUNCTION(7, "DBG_MON_A[31]"), + MTK_FUNCTION(11, "PCIE0_PERST_N") + ), + MTK_PIN( + PINCTRL_PIN(209, "AUD_EXT_CK2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 121), + MTK_FUNCTION(0, "GPIO209"), + MTK_FUNCTION(1, "AUD_EXT_CK2"), + MTK_FUNCTION(2, "MSDC1_WP"), + MTK_FUNCTION(5, "PWM1"), + MTK_FUNCTION(7, "DBG_MON_A[32]"), + MTK_FUNCTION(11, "PCIE1_PERST_N") + ), + MTK_PIN( + PINCTRL_PIN(210, "AUD_CLOCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO210"), + MTK_FUNCTION(1, "AUD_CLOCK") + ), + MTK_PIN( + PINCTRL_PIN(211, "DVP_RESET"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO211"), + MTK_FUNCTION(1, "DVP_RESET") + ), + MTK_PIN( + PINCTRL_PIN(212, "DVP_CLOCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO212"), + MTK_FUNCTION(1, "DVP_CLOCK") + ), + MTK_PIN( + PINCTRL_PIN(213, "DVP_CS"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO213"), + MTK_FUNCTION(1, "DVP_CS") + ), + MTK_PIN( + PINCTRL_PIN(214, "DVP_CK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO214"), + MTK_FUNCTION(1, "DVP_CK") + ), + MTK_PIN( + PINCTRL_PIN(215, "DVP_DI"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO215"), + MTK_FUNCTION(1, "DVP_DI") + ), + MTK_PIN( + PINCTRL_PIN(216, "DVP_DO"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO216"), + MTK_FUNCTION(1, "DVP_DO") + ), + MTK_PIN( + PINCTRL_PIN(217, "AP_CS"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO217"), + MTK_FUNCTION(1, "AP_CS") + ), + MTK_PIN( + PINCTRL_PIN(218, "AP_CK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO218"), + MTK_FUNCTION(1, "AP_CK") + ), + MTK_PIN( + PINCTRL_PIN(219, "AP_DI"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO219"), + MTK_FUNCTION(1, "AP_DI") + ), + MTK_PIN( + PINCTRL_PIN(220, "AP_DO"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO220"), + MTK_FUNCTION(1, "AP_DO") + ), + MTK_PIN( + PINCTRL_PIN(221, "DVD_BCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO221"), + MTK_FUNCTION(1, "DVD_BCLK") + ), + MTK_PIN( + PINCTRL_PIN(222, "T8032_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO222"), + MTK_FUNCTION(1, "T8032_CLK") + ), + MTK_PIN( + PINCTRL_PIN(223, "AP_BCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO223"), + MTK_FUNCTION(1, "AP_BCLK") + ), + MTK_PIN( + PINCTRL_PIN(224, "HOST_CS"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO224"), + MTK_FUNCTION(1, "HOST_CS") + ), + MTK_PIN( + PINCTRL_PIN(225, "HOST_CK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO225"), + MTK_FUNCTION(1, "HOST_CK") + ), + MTK_PIN( + PINCTRL_PIN(226, "HOST_DO0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO226"), + MTK_FUNCTION(1, "HOST_DO0") + ), + MTK_PIN( + PINCTRL_PIN(227, "HOST_DO1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO227"), + MTK_FUNCTION(1, "HOST_DO1") + ), + MTK_PIN( + PINCTRL_PIN(228, "SLV_CS"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO228"), + MTK_FUNCTION(1, "SLV_CS") + ), + MTK_PIN( + PINCTRL_PIN(229, "SLV_CK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO229"), + MTK_FUNCTION(1, "SLV_CK") + ), + MTK_PIN( + PINCTRL_PIN(230, "SLV_DI0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO230"), + MTK_FUNCTION(1, "SLV_DI0") + ), + MTK_PIN( + PINCTRL_PIN(231, "SLV_DI1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO231"), + MTK_FUNCTION(1, "SLV_DI1") + ), + MTK_PIN( + PINCTRL_PIN(232, "AP2DSP_INT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO232"), + MTK_FUNCTION(1, "AP2DSP_INT") + ), + MTK_PIN( + PINCTRL_PIN(233, "AP2DSP_INT_CLR"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO233"), + MTK_FUNCTION(1, "AP2DSP_INT_CLR") + ), + MTK_PIN( + PINCTRL_PIN(234, "DSP2AP_INT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO234"), + MTK_FUNCTION(1, "DSP2AP_INT") + ), + MTK_PIN( + PINCTRL_PIN(235, "DSP2AP_INT_CLR"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO235"), + MTK_FUNCTION(1, "DSP2AP_INT_CLR") + ), + MTK_PIN( + PINCTRL_PIN(236, "EXT_SDIO3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 122), + MTK_FUNCTION(0, "GPIO236"), + MTK_FUNCTION(1, "EXT_SDIO3"), + MTK_FUNCTION(2, "IDDIG"), + MTK_FUNCTION(7, "DBG_MON_A[1]") + ), + MTK_PIN( + PINCTRL_PIN(237, "EXT_SDIO2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 123), + MTK_FUNCTION(0, "GPIO237"), + MTK_FUNCTION(1, "EXT_SDIO2"), + MTK_FUNCTION(2, "DRV_VBUS") + ), + MTK_PIN( + PINCTRL_PIN(238, "EXT_SDIO1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 124), + MTK_FUNCTION(0, "GPIO238"), + MTK_FUNCTION(1, "EXT_SDIO1"), + MTK_FUNCTION(2, "IDDIG_P1") + ), + MTK_PIN( + PINCTRL_PIN(239, "EXT_SDIO0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 125), + MTK_FUNCTION(0, "GPIO239"), + MTK_FUNCTION(1, "EXT_SDIO0"), + MTK_FUNCTION(2, "DRV_VBUS_P1") + ), + MTK_PIN( + PINCTRL_PIN(240, "EXT_XCS"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 126), + MTK_FUNCTION(0, "GPIO240"), + MTK_FUNCTION(1, "EXT_XCS") + ), + MTK_PIN( + PINCTRL_PIN(241, "EXT_SCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 127), + MTK_FUNCTION(0, "GPIO241"), + MTK_FUNCTION(1, "EXT_SCK") + ), + MTK_PIN( + PINCTRL_PIN(242, "URTS2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 128), + MTK_FUNCTION(0, "GPIO242"), + MTK_FUNCTION(1, "URTS2"), + MTK_FUNCTION(2, "UTXD3"), + MTK_FUNCTION(3, "URXD3"), + MTK_FUNCTION(4, "SCL1"), + MTK_FUNCTION(7, "DBG_MON_B[32]") + ), + MTK_PIN( + PINCTRL_PIN(243, "UCTS2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 129), + MTK_FUNCTION(0, "GPIO243"), + MTK_FUNCTION(1, "UCTS2"), + MTK_FUNCTION(2, "URXD3"), + MTK_FUNCTION(3, "UTXD3"), + MTK_FUNCTION(4, "SDA1"), + MTK_FUNCTION(7, "DBG_MON_A[6]") + ), + MTK_PIN( + PINCTRL_PIN(244, "HDMI_SDA_RX"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 130), + MTK_FUNCTION(0, "GPIO244"), + MTK_FUNCTION(1, "HDMI_SDA_RX") + ), + MTK_PIN( + PINCTRL_PIN(245, "HDMI_SCL_RX"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 131), + MTK_FUNCTION(0, "GPIO245"), + MTK_FUNCTION(1, "HDMI_SCL_RX") + ), + MTK_PIN( + PINCTRL_PIN(246, "MHL_SENCE"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 132), + MTK_FUNCTION(0, "GPIO246") + ), + MTK_PIN( + PINCTRL_PIN(247, "HDMI_HPD_CBUS_RX"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 69), + MTK_FUNCTION(0, "GPIO247"), + MTK_FUNCTION(1, "HDMI_HPD_RX") + ), + MTK_PIN( + PINCTRL_PIN(248, "HDMI_TESTOUTP_RX"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 133), + MTK_FUNCTION(0, "GPIO248"), + MTK_FUNCTION(1, "HDMI_TESTOUTP_RX") + ), + MTK_PIN( + PINCTRL_PIN(249, "MSDC0E_RSTB"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 134), + MTK_FUNCTION(0, "GPIO249"), + MTK_FUNCTION(1, "MSDC0E_RSTB") + ), + MTK_PIN( + PINCTRL_PIN(250, "MSDC0E_DAT7"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 135), + MTK_FUNCTION(0, "GPIO250"), + MTK_FUNCTION(1, "MSDC3_DAT7"), + MTK_FUNCTION(6, "PCIE0_CLKREQ_N") + ), + MTK_PIN( + PINCTRL_PIN(251, "MSDC0E_DAT6"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 136), + MTK_FUNCTION(0, "GPIO251"), + MTK_FUNCTION(1, "MSDC3_DAT6"), + MTK_FUNCTION(6, "PCIE0_WAKE_N") + ), + MTK_PIN( + PINCTRL_PIN(252, "MSDC0E_DAT5"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 137), + MTK_FUNCTION(0, "GPIO252"), + MTK_FUNCTION(1, "MSDC3_DAT5"), + MTK_FUNCTION(6, "PCIE1_CLKREQ_N") + ), + MTK_PIN( + PINCTRL_PIN(253, "MSDC0E_DAT4"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 138), + MTK_FUNCTION(0, "GPIO253"), + MTK_FUNCTION(1, "MSDC3_DAT4"), + MTK_FUNCTION(6, "PCIE1_WAKE_N") + ), + MTK_PIN( + PINCTRL_PIN(254, "MSDC0E_DAT3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 139), + MTK_FUNCTION(0, "GPIO254"), + MTK_FUNCTION(1, "MSDC3_DAT3"), + MTK_FUNCTION(6, "PCIE2_CLKREQ_N") + ), + MTK_PIN( + PINCTRL_PIN(255, "MSDC0E_DAT2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 140), + MTK_FUNCTION(0, "GPIO255"), + MTK_FUNCTION(1, "MSDC3_DAT2"), + MTK_FUNCTION(6, "PCIE2_WAKE_N") + ), + MTK_PIN( + PINCTRL_PIN(256, "MSDC0E_DAT1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 141), + MTK_FUNCTION(0, "GPIO256"), + MTK_FUNCTION(1, "MSDC3_DAT1") + ), + MTK_PIN( + PINCTRL_PIN(257, "MSDC0E_DAT0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 142), + MTK_FUNCTION(0, "GPIO257"), + MTK_FUNCTION(1, "MSDC3_DAT0") + ), + MTK_PIN( + PINCTRL_PIN(258, "MSDC0E_CMD"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 143), + MTK_FUNCTION(0, "GPIO258"), + MTK_FUNCTION(1, "MSDC3_CMD") + ), + MTK_PIN( + PINCTRL_PIN(259, "MSDC0E_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 144), + MTK_FUNCTION(0, "GPIO259"), + MTK_FUNCTION(1, "MSDC3_CLK") + ), + MTK_PIN( + PINCTRL_PIN(260, "MSDC0E_DSL"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 145), + MTK_FUNCTION(0, "GPIO260"), + MTK_FUNCTION(1, "MSDC3_DSL") + ), + MTK_PIN( + PINCTRL_PIN(261, "MSDC1_INS"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 146), + MTK_FUNCTION(0, "GPIO261"), + MTK_FUNCTION(1, "MSDC1_INS"), + MTK_FUNCTION(7, "DBG_MON_B[29]") + ), + MTK_PIN( + PINCTRL_PIN(262, "G2_TXEN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 8), + MTK_FUNCTION(0, "GPIO262"), + MTK_FUNCTION(1, "G2_TXEN") + ), + MTK_PIN( + PINCTRL_PIN(263, "G2_TXD3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 9), + MTK_FUNCTION(0, "GPIO263"), + MTK_FUNCTION(1, "G2_TXD3"), + MTK_FUNCTION(6, "ANT_SEL5") + ), + MTK_PIN( + PINCTRL_PIN(264, "G2_TXD2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 10), + MTK_FUNCTION(0, "GPIO264"), + MTK_FUNCTION(1, "G2_TXD2"), + MTK_FUNCTION(6, "ANT_SEL4") + ), + MTK_PIN( + PINCTRL_PIN(265, "G2_TXD1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 11), + MTK_FUNCTION(0, "GPIO265"), + MTK_FUNCTION(1, "G2_TXD1"), + MTK_FUNCTION(6, "ANT_SEL3") + ), + MTK_PIN( + PINCTRL_PIN(266, "G2_TXD0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO266"), + MTK_FUNCTION(1, "G2_TXD0"), + MTK_FUNCTION(6, "ANT_SEL2") + ), + MTK_PIN( + PINCTRL_PIN(267, "G2_TXC"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO267"), + MTK_FUNCTION(1, "G2_TXC") + ), + MTK_PIN( + PINCTRL_PIN(268, "G2_RXC"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO268"), + MTK_FUNCTION(1, "G2_RXC") + ), + MTK_PIN( + PINCTRL_PIN(269, "G2_RXD0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO269"), + MTK_FUNCTION(1, "G2_RXD0") + ), + MTK_PIN( + PINCTRL_PIN(270, "G2_RXD1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO270"), + MTK_FUNCTION(1, "G2_RXD1") + ), + MTK_PIN( + PINCTRL_PIN(271, "G2_RXD2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO271"), + MTK_FUNCTION(1, "G2_RXD2") + ), + MTK_PIN( + PINCTRL_PIN(272, "G2_RXD3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO272"), + MTK_FUNCTION(1, "G2_RXD3") + ), + MTK_PIN( + PINCTRL_PIN(273, "ESW_INT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 168), + MTK_FUNCTION(0, "GPIO273"), + MTK_FUNCTION(1, "ESW_INT") + ), + MTK_PIN( + PINCTRL_PIN(274, "G2_RXDV"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO274"), + MTK_FUNCTION(1, "G2_RXDV") + ), + MTK_PIN( + PINCTRL_PIN(275, "MDC"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO275"), + MTK_FUNCTION(1, "MDC"), + MTK_FUNCTION(6, "ANT_SEL0") + ), + MTK_PIN( + PINCTRL_PIN(276, "MDIO"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO276"), + MTK_FUNCTION(1, "MDIO"), + MTK_FUNCTION(6, "ANT_SEL1") + ), + MTK_PIN( + PINCTRL_PIN(277, "ESW_RST"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO277"), + MTK_FUNCTION(1, "ESW_RST") + ), + MTK_PIN( + PINCTRL_PIN(278, "JTAG_RESET"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 147), + MTK_FUNCTION(0, "GPIO278"), + MTK_FUNCTION(1, "JTAG_RESET") + ), + MTK_PIN( + PINCTRL_PIN(279, "USB3_RES_BOND"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO279"), + MTK_FUNCTION(1, "USB3_RES_BOND") + ), +}; + +#endif /* __PINCTRL_MTK_MT2701_H */ -- cgit v1.2.3 From 64051150c6402be83d77ea343f98755e998cae80 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 24 Jan 2016 00:31:08 +0900 Subject: pinctrl: pxa: guard sub-directory with CONFIG_PINCTRL_PXA CONFIG_PINCTRL_PXA is more suitable than CONFIG_ARCH_PXA to guard the drivers/pinctrl/pxa/ directory. Signed-off-by: Masahiro Yamada Signed-off-by: Linus Walleij --- drivers/pinctrl/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index d4134038cbf9..ab66e3575193 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -46,7 +46,7 @@ obj-y += freescale/ obj-$(CONFIG_X86) += intel/ obj-$(CONFIG_PINCTRL_MVEBU) += mvebu/ obj-y += nomadik/ -obj-$(CONFIG_ARCH_PXA) += pxa/ +obj-$(CONFIG_PINCTRL_PXA) += pxa/ obj-$(CONFIG_ARCH_QCOM) += qcom/ obj-$(CONFIG_PINCTRL_SAMSUNG) += samsung/ obj-$(CONFIG_PINCTRL_SH_PFC) += sh-pfc/ -- cgit v1.2.3 From d9da6aa035c6dfdb003ff9776532b9b356d83f15 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 27 Jan 2016 13:41:09 +0000 Subject: drm/i915: Fix VCS ring selection after uapi decoupling This got broken in: commit de1add360522c876c25ef2bbbbab1c94bdb509ab Author: Tvrtko Ursulin Date: Fri Jan 15 15:12:50 2016 +0000 drm/i915: Decouple execbuf uAPI from internal implementation BSD ring flags need to be shifted before they can be considered indices into the ring array. Reported by Zhipeng Gong. v2: Simplify the code. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Cc: Daniel Vetter Cc: Chris Wilson Cc: Zhipeng Gong Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1453902069-31353-1-git-send-email-tvrtko.ursulin@linux.intel.com Testcase: igt/gem_exec_basic # bdw-gt3 --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 1 + include/uapi/drm/i915_drm.h | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 2dc08ce1079a..5cb57f642ac1 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1401,6 +1401,7 @@ eb_select_ring(struct drm_i915_private *dev_priv, bsd_idx = gen8_dispatch_bsd_ring(dev_priv, file); } else if (bsd_idx >= I915_EXEC_BSD_RING1 && bsd_idx <= I915_EXEC_BSD_RING2) { + bsd_idx >>= I915_EXEC_BSD_SHIFT; bsd_idx--; } else { DRM_DEBUG("execbuf with unknown bsd ring: %u\n", diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 6a19371391fa..a5524cc95ff8 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -772,10 +772,12 @@ struct drm_i915_gem_execbuffer2 { #define I915_EXEC_HANDLE_LUT (1<<12) /** Used for switching BSD rings on the platforms with two BSD rings */ -#define I915_EXEC_BSD_MASK (3<<13) -#define I915_EXEC_BSD_DEFAULT (0<<13) /* default ping-pong mode */ -#define I915_EXEC_BSD_RING1 (1<<13) -#define I915_EXEC_BSD_RING2 (2<<13) +#define I915_EXEC_BSD_SHIFT (13) +#define I915_EXEC_BSD_MASK (3 << I915_EXEC_BSD_SHIFT) +/* default ping-pong mode */ +#define I915_EXEC_BSD_DEFAULT (0 << I915_EXEC_BSD_SHIFT) +#define I915_EXEC_BSD_RING1 (1 << I915_EXEC_BSD_SHIFT) +#define I915_EXEC_BSD_RING2 (2 << I915_EXEC_BSD_SHIFT) /** Tell the kernel that the batchbuffer is processed by * the resource streamer. -- cgit v1.2.3 From 39178bb2b3e78cfcb9b6311fa9e2b8d6e3cfe51f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 16:59:09 +0100 Subject: pinctrl: nomadik: hide unused functions The nomadik pinctrl driver has two functions that are only used for debugfs output and are otherwise unused: drivers/pinctrl/nomadik/pinctrl-abx500.c:194:12: error: 'abx500_get_pull_updown' defined but not used drivers/pinctrl/nomadik/pinctrl-abx500.c:471:12: error: 'abx500_get_mode' defined but not used This makes the function definitions conditional to avoid the harmless warnings. Signed-off-by: Arnd Bergmann Signed-off-by: Linus Walleij --- drivers/pinctrl/nomadik/pinctrl-abx500.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c index 085e60106ec2..1f7469c9857d 100644 --- a/drivers/pinctrl/nomadik/pinctrl-abx500.c +++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c @@ -191,6 +191,7 @@ static void abx500_gpio_set(struct gpio_chip *chip, unsigned offset, int val) dev_err(pct->dev, "%s write failed (%d)\n", __func__, ret); } +#ifdef CONFIG_DEBUG_FS static int abx500_get_pull_updown(struct abx500_pinctrl *pct, int offset, enum abx500_gpio_pull_updown *pull_updown) { @@ -226,6 +227,7 @@ out: return ret; } +#endif static int abx500_set_pull_updown(struct abx500_pinctrl *pct, int offset, enum abx500_gpio_pull_updown val) @@ -468,6 +470,7 @@ out: return ret; } +#ifdef CONFIG_DEBUG_FS static int abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip, unsigned gpio) { @@ -553,8 +556,6 @@ out: return ret; } -#ifdef CONFIG_DEBUG_FS - #include static void abx500_gpio_dbg_show_one(struct seq_file *s, -- cgit v1.2.3 From 411a1fb80fb6d7cf50b8ff3811d25dbf262d6328 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 27 Jan 2016 22:38:30 +0100 Subject: pinctrl: nomadik: stn8815 CLCD alternate functions The STn8815 has 22 dedicated pins for CLCD with up to 16 bits in parallel, but pins 32 thru 39 can be used for an additional CLCD signal lines 16 thru 23. Signed-off-by: Linus Walleij --- drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c b/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c index 587b222f12f3..e852048c4c04 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c @@ -287,6 +287,10 @@ static const unsigned i2c0_a_1_pins[] = { STN8815_PIN_D3, STN8815_PIN_D2 }; /* Altfunction B */ static const unsigned u1_b_1_pins[] = { STN8815_PIN_B16, STN8815_PIN_A16 }; static const unsigned i2cusb_b_1_pins[] = { STN8815_PIN_C21, STN8815_PIN_C20 }; +static const unsigned clcd_16_23_b_1_pins[] = { STN8815_PIN_AB6, + STN8815_PIN_AA6, STN8815_PIN_Y6, STN8815_PIN_Y5, STN8815_PIN_AA5, + STN8815_PIN_AB5, STN8815_PIN_AB4, STN8815_PIN_Y4 }; + #define STN8815_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins, \ .npins = ARRAY_SIZE(a##_pins), .altsetting = b } @@ -302,6 +306,7 @@ static const struct nmk_pingroup nmk_stn8815_groups[] = { STN8815_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A), STN8815_PIN_GROUP(u1_b_1, NMK_GPIO_ALT_B), STN8815_PIN_GROUP(i2cusb_b_1, NMK_GPIO_ALT_B), + STN8815_PIN_GROUP(clcd_16_23_b_1, NMK_GPIO_ALT_B), }; /* We use this macro to define the groups applicable to a function */ @@ -314,6 +319,7 @@ STN8815_FUNC_GROUPS(u1, "u1_a_1", "u1_b_1"); STN8815_FUNC_GROUPS(i2c1, "i2c1_a_1"); STN8815_FUNC_GROUPS(i2c0, "i2c0_a_1"); STN8815_FUNC_GROUPS(i2cusb, "i2cusb_b_1"); +STN8815_FUNC_GROUPS(clcd, "clcd_16_23_b_1"); #define FUNCTION(fname) \ { \ @@ -329,6 +335,7 @@ static const struct nmk_function nmk_stn8815_functions[] = { FUNCTION(i2c1), FUNCTION(i2c0), FUNCTION(i2cusb), + FUNCTION(clcd), }; static const struct nmk_pinctrl_soc_data nmk_stn8815_soc = { -- cgit v1.2.3 From f785d98711925aceb198fb96abd786fd19fad657 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 22 Jan 2016 17:35:26 +0000 Subject: drm/amdgpu: fix non-ANSI declaration of amdgpu_amdkfd_gfx_*_get_functions() amdgpu_amdkfd_gfx_7_get_functions and amdgpu_amdkfd_gfx_8_0_get_functions have no parameters, so use the normal void parameter convention to make them match their prototypes in the header file drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h Signed-off-by: Colin Ian King Signed-off-by: Oded Gabbay --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c index 0e1376317683..362bedc9e507 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c @@ -154,7 +154,7 @@ static const struct kfd2kgd_calls kfd2kgd = { .get_fw_version = get_fw_version }; -struct kfd2kgd_calls *amdgpu_amdkfd_gfx_7_get_functions() +struct kfd2kgd_calls *amdgpu_amdkfd_gfx_7_get_functions(void) { return (struct kfd2kgd_calls *)&kfd2kgd; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c index 79fa5c7de856..04b744d64b57 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c @@ -115,7 +115,7 @@ static const struct kfd2kgd_calls kfd2kgd = { .get_fw_version = get_fw_version }; -struct kfd2kgd_calls *amdgpu_amdkfd_gfx_8_0_get_functions() +struct kfd2kgd_calls *amdgpu_amdkfd_gfx_8_0_get_functions(void) { return (struct kfd2kgd_calls *)&kfd2kgd; } -- cgit v1.2.3 From 642f0f2a1563b5ab6f5de896f602177ac1f06652 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Mon, 25 Jan 2016 23:03:57 +0530 Subject: drm/amdkfd: Remove unnecessary cast in kfree Remove an unnecassary cast in the argument to kfree. Found using Coccinelle. The semantic patch used to find this is as follows: // @@ type T; expression *f; @@ - kfree((T *)(f)); + kfree(f); // Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Oded Gabbay --- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 9be007081b72..a902ae037398 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -194,7 +194,7 @@ static void kfd_process_wq_release(struct work_struct *work) kfree(p); - kfree((void *)work); + kfree(work); } static void kfd_process_destroy_delayed(struct rcu_head *rcu) -- cgit v1.2.3 From 3a42a042f5cbefa925484a9bc4abd1bfeec5d779 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 24 Jan 2016 00:32:09 +0900 Subject: pinctrl: sunxi: guard sub-directory with CONFIG_PINCTRL_SUNXI CONFIG_PINCTRL_SUNXI is more suitable than CONFIG_ARCH_SUNXI to guard the drivers/pinctrl/sunxi/ directory. (I renamed CONFIG_PINCTRL_SUNXI_COMMON to CONFIG_PINCTRL_SUNXI.) Signed-off-by: Masahiro Yamada Acked-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/Makefile | 2 +- drivers/pinctrl/sunxi/Kconfig | 30 +++++++++++++++--------------- drivers/pinctrl/sunxi/Makefile | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index ab66e3575193..d25dcbd28dfa 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -52,7 +52,7 @@ obj-$(CONFIG_PINCTRL_SAMSUNG) += samsung/ obj-$(CONFIG_PINCTRL_SH_PFC) += sh-pfc/ obj-$(CONFIG_PINCTRL_SPEAR) += spear/ obj-$(CONFIG_ARCH_STM32) += stm32/ -obj-$(CONFIG_ARCH_SUNXI) += sunxi/ +obj-$(CONFIG_PINCTRL_SUNXI) += sunxi/ obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/ obj-$(CONFIG_ARCH_VT8500) += vt8500/ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig index f8dbc8bec0e1..ac8388e67340 100644 --- a/drivers/pinctrl/sunxi/Kconfig +++ b/drivers/pinctrl/sunxi/Kconfig @@ -1,67 +1,67 @@ if ARCH_SUNXI -config PINCTRL_SUNXI_COMMON +config PINCTRL_SUNXI bool select PINMUX select GENERIC_PINCONF config PINCTRL_SUN4I_A10 def_bool MACH_SUN4I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN5I_A10S def_bool MACH_SUN5I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN5I_A13 def_bool MACH_SUN5I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN6I_A31 def_bool MACH_SUN6I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN6I_A31S def_bool MACH_SUN6I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN6I_A31_R def_bool MACH_SUN6I depends on RESET_CONTROLLER - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN7I_A20 def_bool MACH_SUN7I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN8I_A23 def_bool MACH_SUN8I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN8I_A33 def_bool MACH_SUN8I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN8I_A83T def_bool MACH_SUN8I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN8I_A23_R def_bool MACH_SUN8I depends on RESET_CONTROLLER - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN8I_H3 def_bool MACH_SUN8I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN9I_A80 def_bool MACH_SUN9I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN9I_A80_R def_bool MACH_SUN9I depends on RESET_CONTROLLER - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI endif diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile index ef82f22bb9ef..dac1bd0cda4a 100644 --- a/drivers/pinctrl/sunxi/Makefile +++ b/drivers/pinctrl/sunxi/Makefile @@ -1,5 +1,5 @@ # Core -obj-$(CONFIG_PINCTRL_SUNXI_COMMON) += pinctrl-sunxi.o +obj-y += pinctrl-sunxi.o # SoC Drivers obj-$(CONFIG_PINCTRL_SUN4I_A10) += pinctrl-sun4i-a10.o -- cgit v1.2.3 From ff21a635dd1a9c6ca378847160897649cdbbfae4 Mon Sep 17 00:00:00 2001 From: Edwin Velds Date: Mon, 11 Jan 2016 00:25:15 +0100 Subject: HID: logitech-hidpp: Force feedback support for the Logitech G920 This patch implements force feedback support for the Logitech G920 Driving Force Racing Wheel. It is a generic implementation of feature 0x8123 of the Logitech HID++ protocol and should be usable for any future devices that implement this feature. This patch should be applied after the basic G920 support patch by Simon Wood: http://www.spinics.net/lists/linux-input/msg42174.html The driving supports everything that is supported by the G920 firmware: FF_CONSTANT FF_PERIODIC FF_SINE FF_SQUARE FF_SAW_UP FF_SAW_DOWN FF_TRIANGLE FF_SPRING FF_DAMPER FF_AUTOCENTER FF_GAIN and for version 2 firmware also: FF_FRICTION FF_INERTIA FF_RAMP Both envelopes and replay values are supported as well, but some problems may occur when using firmware release 1. There is also a small residual clockwise damper in the wheel when using the first firmware release. All problems are fixed in the soon te be released firmware version 2. The default spring is disabled by permanently placing a spring force in the wheel. This spring is also used as the autocenter spring. Note: The wheel _DOES_NOT_ auto switch to Logitech/HID mode (it is stuck in XBox since the xpad changes where not included). Michal has an alternative approach documented here (and the changes should be submitted upstream to usb_modeswitch project): === Create a file named "046d:c261" in "/etc/usb_modeswitch.d" with the following content: DefaultVendor=046d DefaultProduct=c261 MessageEndpoint=01 ResponseEndpoint=01 TargetClass=0x03 MessageContent="0f00010142" Then run "usb_modeswitch -c /etc/modeswitch.d/046d:c291" as root and watch the magic happen:) === [jkosina@suse.cz: added information about mode switching from Simon] [jkosina@suse.cz: fixed a few stylistic issues pointed out by Simon] [jkosina@suse.cz: fix merge conflict due to to_hid_device() changes] Signed-off-by: Edwin Velds Tested-by: Elias Vanderstuyft Tested-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/hid-logitech-hidpp.c | 701 +++++++++++++++++++++++++++++++++------ 1 file changed, 593 insertions(+), 108 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index bd2ab476c65e..2869bbff0899 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -15,13 +15,19 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include +#include #include #include #include #include #include #include +#include +#include +#include #include +#include "usbhid/usbhid.h" #include "hid-ids.h" MODULE_LICENSE("GPL"); @@ -773,6 +779,589 @@ static void hidpp_touchpad_raw_xy_event(struct hidpp_device *hidpp_dev, } } +/* -------------------------------------------------------------------------- */ +/* 0x8123: Force feedback support */ +/* -------------------------------------------------------------------------- */ + +#define HIDPP_FF_GET_INFO 0x01 +#define HIDPP_FF_RESET_ALL 0x11 +#define HIDPP_FF_DOWNLOAD_EFFECT 0x21 +#define HIDPP_FF_SET_EFFECT_STATE 0x31 +#define HIDPP_FF_DESTROY_EFFECT 0x41 +#define HIDPP_FF_GET_APERTURE 0x51 +#define HIDPP_FF_SET_APERTURE 0x61 +#define HIDPP_FF_GET_GLOBAL_GAINS 0x71 +#define HIDPP_FF_SET_GLOBAL_GAINS 0x81 + +#define HIDPP_FF_EFFECT_STATE_GET 0x00 +#define HIDPP_FF_EFFECT_STATE_STOP 0x01 +#define HIDPP_FF_EFFECT_STATE_PLAY 0x02 +#define HIDPP_FF_EFFECT_STATE_PAUSE 0x03 + +#define HIDPP_FF_EFFECT_CONSTANT 0x00 +#define HIDPP_FF_EFFECT_PERIODIC_SINE 0x01 +#define HIDPP_FF_EFFECT_PERIODIC_SQUARE 0x02 +#define HIDPP_FF_EFFECT_PERIODIC_TRIANGLE 0x03 +#define HIDPP_FF_EFFECT_PERIODIC_SAWTOOTHUP 0x04 +#define HIDPP_FF_EFFECT_PERIODIC_SAWTOOTHDOWN 0x05 +#define HIDPP_FF_EFFECT_SPRING 0x06 +#define HIDPP_FF_EFFECT_DAMPER 0x07 +#define HIDPP_FF_EFFECT_FRICTION 0x08 +#define HIDPP_FF_EFFECT_INERTIA 0x09 +#define HIDPP_FF_EFFECT_RAMP 0x0A + +#define HIDPP_FF_EFFECT_AUTOSTART 0x80 + +#define HIDPP_FF_EFFECTID_NONE -1 +#define HIDPP_FF_EFFECTID_AUTOCENTER -2 + +#define HIDPP_FF_MAX_PARAMS 20 +#define HIDPP_FF_RESERVED_SLOTS 1 + +struct hidpp_ff_private_data { + struct hidpp_device *hidpp; + u8 feature_index; + u8 version; + u16 gain; + s16 range; + u8 slot_autocenter; + u8 num_effects; + int *effect_ids; + struct workqueue_struct *wq; + atomic_t workqueue_size; +}; + +struct hidpp_ff_work_data { + struct work_struct work; + struct hidpp_ff_private_data *data; + int effect_id; + u8 command; + u8 params[HIDPP_FF_MAX_PARAMS]; + u8 size; +}; + +static const signed short hiddpp_ff_effects[] = { + FF_CONSTANT, + FF_PERIODIC, + FF_SINE, + FF_SQUARE, + FF_SAW_UP, + FF_SAW_DOWN, + FF_TRIANGLE, + FF_SPRING, + FF_DAMPER, + FF_AUTOCENTER, + FF_GAIN, + -1 +}; + +static const signed short hiddpp_ff_effects_v2[] = { + FF_RAMP, + FF_FRICTION, + FF_INERTIA, + -1 +}; + +static const u8 HIDPP_FF_CONDITION_CMDS[] = { + HIDPP_FF_EFFECT_SPRING, + HIDPP_FF_EFFECT_FRICTION, + HIDPP_FF_EFFECT_DAMPER, + HIDPP_FF_EFFECT_INERTIA +}; + +static const char *HIDPP_FF_CONDITION_NAMES[] = { + "spring", + "friction", + "damper", + "inertia" +}; + + +static u8 hidpp_ff_find_effect(struct hidpp_ff_private_data *data, int effect_id) +{ + int i; + + for (i = 0; i < data->num_effects; i++) + if (data->effect_ids[i] == effect_id) + return i+1; + + return 0; +} + +static void hidpp_ff_work_handler(struct work_struct *w) +{ + struct hidpp_ff_work_data *wd = container_of(w, struct hidpp_ff_work_data, work); + struct hidpp_ff_private_data *data = wd->data; + struct hidpp_report response; + u8 slot; + int ret; + + /* add slot number if needed */ + switch (wd->effect_id) { + case HIDPP_FF_EFFECTID_AUTOCENTER: + wd->params[0] = data->slot_autocenter; + break; + case HIDPP_FF_EFFECTID_NONE: + /* leave slot as zero */ + break; + default: + /* find current slot for effect */ + wd->params[0] = hidpp_ff_find_effect(data, wd->effect_id); + break; + } + + /* send command and wait for reply */ + ret = hidpp_send_fap_command_sync(data->hidpp, data->feature_index, + wd->command, wd->params, wd->size, &response); + + if (ret) { + hid_err(data->hidpp->hid_dev, "Failed to send command to device!\n"); + goto out; + } + + /* parse return data */ + switch (wd->command) { + case HIDPP_FF_DOWNLOAD_EFFECT: + slot = response.fap.params[0]; + if (slot > 0 && slot <= data->num_effects) { + if (wd->effect_id >= 0) + /* regular effect uploaded */ + data->effect_ids[slot-1] = wd->effect_id; + else if (wd->effect_id >= HIDPP_FF_EFFECTID_AUTOCENTER) + /* autocenter spring uploaded */ + data->slot_autocenter = slot; + } + break; + case HIDPP_FF_DESTROY_EFFECT: + if (wd->effect_id >= 0) + /* regular effect destroyed */ + data->effect_ids[wd->params[0]-1] = -1; + else if (wd->effect_id >= HIDPP_FF_EFFECTID_AUTOCENTER) + /* autocenter spring destoyed */ + data->slot_autocenter = 0; + break; + case HIDPP_FF_SET_GLOBAL_GAINS: + data->gain = (wd->params[0] << 8) + wd->params[1]; + break; + case HIDPP_FF_SET_APERTURE: + data->range = (wd->params[0] << 8) + wd->params[1]; + break; + default: + /* no action needed */ + break; + } + +out: + atomic_dec(&data->workqueue_size); + kfree(wd); +} + +static int hidpp_ff_queue_work(struct hidpp_ff_private_data *data, int effect_id, u8 command, u8 *params, u8 size) +{ + struct hidpp_ff_work_data *wd = kzalloc(sizeof(*wd), GFP_KERNEL); + int s; + + if (!wd) + return -ENOMEM; + + INIT_WORK(&wd->work, hidpp_ff_work_handler); + + wd->data = data; + wd->effect_id = effect_id; + wd->command = command; + wd->size = size; + memcpy(wd->params, params, size); + + atomic_inc(&data->workqueue_size); + queue_work(data->wq, &wd->work); + + /* warn about excessive queue size */ + s = atomic_read(&data->workqueue_size); + if (s >= 20 && s % 20 == 0) + hid_warn(data->hidpp->hid_dev, "Force feedback command queue contains %d commands, causing substantial delays!", s); + + return 0; +} + +static int hidpp_ff_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) +{ + struct hidpp_ff_private_data *data = dev->ff->private; + u8 params[20]; + u8 size; + int force; + + /* set common parameters */ + params[2] = effect->replay.length >> 8; + params[3] = effect->replay.length & 255; + params[4] = effect->replay.delay >> 8; + params[5] = effect->replay.delay & 255; + + switch (effect->type) { + case FF_CONSTANT: + force = (effect->u.constant.level * fixp_sin16((effect->direction * 360) >> 16)) >> 15; + params[1] = HIDPP_FF_EFFECT_CONSTANT; + params[6] = force >> 8; + params[7] = force & 255; + params[8] = effect->u.constant.envelope.attack_level >> 7; + params[9] = effect->u.constant.envelope.attack_length >> 8; + params[10] = effect->u.constant.envelope.attack_length & 255; + params[11] = effect->u.constant.envelope.fade_level >> 7; + params[12] = effect->u.constant.envelope.fade_length >> 8; + params[13] = effect->u.constant.envelope.fade_length & 255; + size = 14; + dbg_hid("Uploading constant force level=%d in dir %d = %d\n", + effect->u.constant.level, + effect->direction, force); + dbg_hid(" envelope attack=(%d, %d ms) fade=(%d, %d ms)\n", + effect->u.constant.envelope.attack_level, + effect->u.constant.envelope.attack_length, + effect->u.constant.envelope.fade_level, + effect->u.constant.envelope.fade_length); + break; + case FF_PERIODIC: + { + switch (effect->u.periodic.waveform) { + case FF_SINE: + params[1] = HIDPP_FF_EFFECT_PERIODIC_SINE; + break; + case FF_SQUARE: + params[1] = HIDPP_FF_EFFECT_PERIODIC_SQUARE; + break; + case FF_SAW_UP: + params[1] = HIDPP_FF_EFFECT_PERIODIC_SAWTOOTHUP; + break; + case FF_SAW_DOWN: + params[1] = HIDPP_FF_EFFECT_PERIODIC_SAWTOOTHDOWN; + break; + case FF_TRIANGLE: + params[1] = HIDPP_FF_EFFECT_PERIODIC_TRIANGLE; + break; + default: + hid_err(data->hidpp->hid_dev, "Unexpected periodic waveform type %i!\n", effect->u.periodic.waveform); + return -EINVAL; + } + force = (effect->u.periodic.magnitude * fixp_sin16((effect->direction * 360) >> 16)) >> 15; + params[6] = effect->u.periodic.magnitude >> 8; + params[7] = effect->u.periodic.magnitude & 255; + params[8] = effect->u.periodic.offset >> 8; + params[9] = effect->u.periodic.offset & 255; + params[10] = effect->u.periodic.period >> 8; + params[11] = effect->u.periodic.period & 255; + params[12] = effect->u.periodic.phase >> 8; + params[13] = effect->u.periodic.phase & 255; + params[14] = effect->u.periodic.envelope.attack_level >> 7; + params[15] = effect->u.periodic.envelope.attack_length >> 8; + params[16] = effect->u.periodic.envelope.attack_length & 255; + params[17] = effect->u.periodic.envelope.fade_level >> 7; + params[18] = effect->u.periodic.envelope.fade_length >> 8; + params[19] = effect->u.periodic.envelope.fade_length & 255; + size = 20; + dbg_hid("Uploading periodic force mag=%d/dir=%d, offset=%d, period=%d ms, phase=%d\n", + effect->u.periodic.magnitude, effect->direction, + effect->u.periodic.offset, + effect->u.periodic.period, + effect->u.periodic.phase); + dbg_hid(" envelope attack=(%d, %d ms) fade=(%d, %d ms)\n", + effect->u.periodic.envelope.attack_level, + effect->u.periodic.envelope.attack_length, + effect->u.periodic.envelope.fade_level, + effect->u.periodic.envelope.fade_length); + break; + } + case FF_RAMP: + params[1] = HIDPP_FF_EFFECT_RAMP; + force = (effect->u.ramp.start_level * fixp_sin16((effect->direction * 360) >> 16)) >> 15; + params[6] = force >> 8; + params[7] = force & 255; + force = (effect->u.ramp.end_level * fixp_sin16((effect->direction * 360) >> 16)) >> 15; + params[8] = force >> 8; + params[9] = force & 255; + params[10] = effect->u.ramp.envelope.attack_level >> 7; + params[11] = effect->u.ramp.envelope.attack_length >> 8; + params[12] = effect->u.ramp.envelope.attack_length & 255; + params[13] = effect->u.ramp.envelope.fade_level >> 7; + params[14] = effect->u.ramp.envelope.fade_length >> 8; + params[15] = effect->u.ramp.envelope.fade_length & 255; + size = 16; + dbg_hid("Uploading ramp force level=%d -> %d in dir %d = %d\n", + effect->u.ramp.start_level, + effect->u.ramp.end_level, + effect->direction, force); + dbg_hid(" envelope attack=(%d, %d ms) fade=(%d, %d ms)\n", + effect->u.ramp.envelope.attack_level, + effect->u.ramp.envelope.attack_length, + effect->u.ramp.envelope.fade_level, + effect->u.ramp.envelope.fade_length); + break; + case FF_FRICTION: + case FF_INERTIA: + case FF_SPRING: + case FF_DAMPER: + params[1] = HIDPP_FF_CONDITION_CMDS[effect->type - FF_SPRING]; + params[6] = effect->u.condition[0].left_saturation >> 9; + params[7] = (effect->u.condition[0].left_saturation >> 1) & 255; + params[8] = effect->u.condition[0].left_coeff >> 8; + params[9] = effect->u.condition[0].left_coeff & 255; + params[10] = effect->u.condition[0].deadband >> 9; + params[11] = (effect->u.condition[0].deadband >> 1) & 255; + params[12] = effect->u.condition[0].center >> 8; + params[13] = effect->u.condition[0].center & 255; + params[14] = effect->u.condition[0].right_coeff >> 8; + params[15] = effect->u.condition[0].right_coeff & 255; + params[16] = effect->u.condition[0].right_saturation >> 9; + params[17] = (effect->u.condition[0].right_saturation >> 1) & 255; + size = 18; + dbg_hid("Uploading %s force left coeff=%d, left sat=%d, right coeff=%d, right sat=%d\n", + HIDPP_FF_CONDITION_NAMES[effect->type - FF_SPRING], + effect->u.condition[0].left_coeff, + effect->u.condition[0].left_saturation, + effect->u.condition[0].right_coeff, + effect->u.condition[0].right_saturation); + dbg_hid(" deadband=%d, center=%d\n", + effect->u.condition[0].deadband, + effect->u.condition[0].center); + break; + default: + hid_err(data->hidpp->hid_dev, "Unexpected force type %i!\n", effect->type); + return -EINVAL; + } + + return hidpp_ff_queue_work(data, effect->id, HIDPP_FF_DOWNLOAD_EFFECT, params, size); +} + +static int hidpp_ff_playback(struct input_dev *dev, int effect_id, int value) +{ + struct hidpp_ff_private_data *data = dev->ff->private; + u8 params[2]; + + params[1] = value ? HIDPP_FF_EFFECT_STATE_PLAY : HIDPP_FF_EFFECT_STATE_STOP; + + dbg_hid("St%sing playback of effect %d.\n", value?"art":"opp", effect_id); + + return hidpp_ff_queue_work(data, effect_id, HIDPP_FF_SET_EFFECT_STATE, params, ARRAY_SIZE(params)); +} + +static int hidpp_ff_erase_effect(struct input_dev *dev, int effect_id) +{ + struct hidpp_ff_private_data *data = dev->ff->private; + u8 slot = 0; + + dbg_hid("Erasing effect %d.\n", effect_id); + + return hidpp_ff_queue_work(data, effect_id, HIDPP_FF_DESTROY_EFFECT, &slot, 1); +} + +static void hidpp_ff_set_autocenter(struct input_dev *dev, u16 magnitude) +{ + struct hidpp_ff_private_data *data = dev->ff->private; + u8 params[18]; + + dbg_hid("Setting autocenter to %d.\n", magnitude); + + /* start a standard spring effect */ + params[1] = HIDPP_FF_EFFECT_SPRING | HIDPP_FF_EFFECT_AUTOSTART; + /* zero delay and duration */ + params[2] = params[3] = params[4] = params[5] = 0; + /* set coeff to 25% of saturation */ + params[8] = params[14] = magnitude >> 11; + params[9] = params[15] = (magnitude >> 3) & 255; + params[6] = params[16] = magnitude >> 9; + params[7] = params[17] = (magnitude >> 1) & 255; + /* zero deadband and center */ + params[10] = params[11] = params[12] = params[13] = 0; + + hidpp_ff_queue_work(data, HIDPP_FF_EFFECTID_AUTOCENTER, HIDPP_FF_DOWNLOAD_EFFECT, params, ARRAY_SIZE(params)); +} + +static void hidpp_ff_set_gain(struct input_dev *dev, u16 gain) +{ + struct hidpp_ff_private_data *data = dev->ff->private; + u8 params[4]; + + dbg_hid("Setting gain to %d.\n", gain); + + params[0] = gain >> 8; + params[1] = gain & 255; + params[2] = 0; /* no boost */ + params[3] = 0; + + hidpp_ff_queue_work(data, HIDPP_FF_EFFECTID_NONE, HIDPP_FF_SET_GLOBAL_GAINS, params, ARRAY_SIZE(params)); +} + +static ssize_t hidpp_ff_range_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct hid_device *hid = to_hid_device(dev); + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); + struct input_dev *idev = hidinput->input; + struct hidpp_ff_private_data *data = idev->ff->private; + + return scnprintf(buf, PAGE_SIZE, "%u\n", data->range); +} + +static ssize_t hidpp_ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct hid_device *hid = to_hid_device(dev); + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); + struct input_dev *idev = hidinput->input; + struct hidpp_ff_private_data *data = idev->ff->private; + u8 params[2]; + int range = simple_strtoul(buf, NULL, 10); + + range = clamp(range, 180, 900); + + params[0] = range >> 8; + params[1] = range & 0x00FF; + + hidpp_ff_queue_work(data, -1, HIDPP_FF_SET_APERTURE, params, ARRAY_SIZE(params)); + + return count; +} + +static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, hidpp_ff_range_show, hidpp_ff_range_store); + +static void hidpp_ff_destroy(struct ff_device *ff) +{ + struct hidpp_ff_private_data *data = ff->private; + + kfree(data->effect_ids); +} + +int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index) +{ + struct hid_device *hid = hidpp->hid_dev; + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); + struct input_dev *dev = hidinput->input; + const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor); + const u16 bcdDevice = le16_to_cpu(udesc->bcdDevice); + struct ff_device *ff; + struct hidpp_report response; + struct hidpp_ff_private_data *data; + int error, j, num_slots; + u8 version; + + if (!dev) { + hid_err(hid, "Struct input_dev not set!\n"); + return -EINVAL; + } + + /* Get firmware release */ + version = bcdDevice & 255; + + /* Set supported force feedback capabilities */ + for (j = 0; hiddpp_ff_effects[j] >= 0; j++) + set_bit(hiddpp_ff_effects[j], dev->ffbit); + if (version > 1) + for (j = 0; hiddpp_ff_effects_v2[j] >= 0; j++) + set_bit(hiddpp_ff_effects_v2[j], dev->ffbit); + + /* Read number of slots available in device */ + error = hidpp_send_fap_command_sync(hidpp, feature_index, + HIDPP_FF_GET_INFO, NULL, 0, &response); + if (error) { + if (error < 0) + return error; + hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n", + __func__, error); + return -EPROTO; + } + + num_slots = response.fap.params[0] - HIDPP_FF_RESERVED_SLOTS; + + error = input_ff_create(dev, num_slots); + + if (error) { + hid_err(dev, "Failed to create FF device!\n"); + return error; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + data->effect_ids = kcalloc(num_slots, sizeof(int), GFP_KERNEL); + if (!data->effect_ids) { + kfree(data); + return -ENOMEM; + } + data->hidpp = hidpp; + data->feature_index = feature_index; + data->version = version; + data->slot_autocenter = 0; + data->num_effects = num_slots; + for (j = 0; j < num_slots; j++) + data->effect_ids[j] = -1; + + ff = dev->ff; + ff->private = data; + + ff->upload = hidpp_ff_upload_effect; + ff->erase = hidpp_ff_erase_effect; + ff->playback = hidpp_ff_playback; + ff->set_gain = hidpp_ff_set_gain; + ff->set_autocenter = hidpp_ff_set_autocenter; + ff->destroy = hidpp_ff_destroy; + + + /* reset all forces */ + error = hidpp_send_fap_command_sync(hidpp, feature_index, + HIDPP_FF_RESET_ALL, NULL, 0, &response); + + /* Read current Range */ + error = hidpp_send_fap_command_sync(hidpp, feature_index, + HIDPP_FF_GET_APERTURE, NULL, 0, &response); + if (error) + hid_warn(hidpp->hid_dev, "Failed to read range from device!\n"); + data->range = error ? 900 : get_unaligned_be16(&response.fap.params[0]); + + /* Create sysfs interface */ + error = device_create_file(&(hidpp->hid_dev->dev), &dev_attr_range); + if (error) + hid_warn(hidpp->hid_dev, "Unable to create sysfs interface for \"range\", errno %d!\n", error); + + /* Read the current gain values */ + error = hidpp_send_fap_command_sync(hidpp, feature_index, + HIDPP_FF_GET_GLOBAL_GAINS, NULL, 0, &response); + if (error) + hid_warn(hidpp->hid_dev, "Failed to read gain values from device!\n"); + data->gain = error ? 0xffff : get_unaligned_be16(&response.fap.params[0]); + /* ignore boost value at response.fap.params[2] */ + + /* init the hardware command queue */ + data->wq = create_singlethread_workqueue("hidpp-ff-sendqueue"); + atomic_set(&data->workqueue_size, 0); + + /* initialize with zero autocenter to get wheel in usable state */ + hidpp_ff_set_autocenter(dev, 0); + + hid_info(hid, "Force feeback support loaded (firmware release %d).\n", version); + + return 0; +} + +int hidpp_ff_deinit(struct hid_device *hid) +{ + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); + struct input_dev *dev = hidinput->input; + struct hidpp_ff_private_data *data; + + if (!dev) { + hid_err(hid, "Struct input_dev not found!\n"); + return -EINVAL; + } + + hid_info(hid, "Unloading HID++ force feedback.\n"); + data = dev->ff->private; + if (!data) { + hid_err(hid, "Private data not found!\n"); + return -EINVAL; + } + + destroy_workqueue(data->wq); + device_remove_file(&hid->dev, &dev_attr_range); + + return 0; +} + + /* ************************************************************************** */ /* */ /* Device Support */ @@ -1301,121 +1890,22 @@ static int k400_connect(struct hid_device *hdev, bool connected) #define HIDPP_PAGE_G920_FORCE_FEEDBACK 0x8123 -/* Using session ID = 1 */ -#define CMD_G920_FORCE_GET_APERTURE 0x51 -#define CMD_G920_FORCE_SET_APERTURE 0x61 - -struct g920_private_data { - u8 force_feature; - u16 range; -}; - -static ssize_t g920_range_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct hid_device *hid = to_hid_device(dev); - struct hidpp_device *hidpp = hid_get_drvdata(hid); - struct g920_private_data *pdata; - - pdata = hidpp->private_data; - if (!pdata) { - hid_err(hid, "Private driver data not found!\n"); - return -EINVAL; - } - - return scnprintf(buf, PAGE_SIZE, "%u\n", pdata->range); -} - -static ssize_t g920_range_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hid = to_hid_device(dev); - struct hidpp_device *hidpp = hid_get_drvdata(hid); - struct g920_private_data *pdata; - struct hidpp_report response; - u8 params[2]; - int ret; - u16 range = simple_strtoul(buf, NULL, 10); - - pdata = hidpp->private_data; - if (!pdata) { - hid_err(hid, "Private driver data not found!\n"); - return -EINVAL; - } - - if (range < 180) - range = 180; - else if (range > 900) - range = 900; - - params[0] = range >> 8; - params[1] = range & 0x00FF; - - ret = hidpp_send_fap_command_sync(hidpp, pdata->force_feature, - CMD_G920_FORCE_SET_APERTURE, params, 2, &response); - if (ret) - return ret; - - pdata->range = range; - return count; -} - -static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, g920_range_show, g920_range_store); - -static int g920_allocate(struct hid_device *hdev) -{ - struct hidpp_device *hidpp = hid_get_drvdata(hdev); - struct g920_private_data *pdata; - - pdata = devm_kzalloc(&hdev->dev, sizeof(struct g920_private_data), - GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - hidpp->private_data = pdata; - - return 0; -} - static int g920_get_config(struct hidpp_device *hidpp) { - struct g920_private_data *pdata = hidpp->private_data; - struct hidpp_report response; u8 feature_type; u8 feature_index; int ret; - pdata = hidpp->private_data; - if (!pdata) { - hid_err(hidpp->hid_dev, "Private driver data not found!\n"); - return -EINVAL; - } - /* Find feature and store for later use */ ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_G920_FORCE_FEEDBACK, &feature_index, &feature_type); if (ret) return ret; - pdata->force_feature = feature_index; - - /* Read current Range */ - ret = hidpp_send_fap_command_sync(hidpp, feature_index, - CMD_G920_FORCE_GET_APERTURE, NULL, 0, &response); - if (ret > 0) { - hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n", - __func__, ret); - return -EPROTO; - } - if (ret) - return ret; - - pdata->range = get_unaligned_be16(&response.fap.params[0]); - - /* Create sysfs interface */ - ret = device_create_file(&(hidpp->hid_dev->dev), &dev_attr_range); + ret = hidpp_ff_init(hidpp, feature_index); if (ret) - hid_warn(hidpp->hid_dev, "Unable to create sysfs interface for \"range\", errno %d\n", ret); + hid_warn(hidpp->hid_dev, "Unable to initialize force feedback support, errno %d\n", + ret); return 0; } @@ -1739,10 +2229,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = k400_allocate(hdev); if (ret) goto allocate_fail; - } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { - ret = g920_allocate(hdev); - if (ret) - goto allocate_fail; } INIT_WORK(&hidpp->work, delayed_work_cb); @@ -1825,7 +2311,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) hid_hw_open_failed: hid_device_io_stop(hdev); if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { - device_remove_file(&hdev->dev, &dev_attr_range); hid_hw_close(hdev); hid_hw_stop(hdev); } @@ -1843,7 +2328,7 @@ static void hidpp_remove(struct hid_device *hdev) struct hidpp_device *hidpp = hid_get_drvdata(hdev); if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { - device_remove_file(&hdev->dev, &dev_attr_range); + hidpp_ff_deinit(hdev); hid_hw_close(hdev); } hid_hw_stop(hdev); -- cgit v1.2.3 From af2e628d6be7a510e2667c3b5358350464d0f5b7 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 28 Jan 2016 14:28:39 +0100 Subject: HID: logitech-hidpp: limit visibility of init/deinit functions hidpp_ff_init() and hidpp_ff_deinit() are not used outside of hid-logitech-hidpp.c, so let's make them static. Signed-off-by: Jiri Kosina --- drivers/hid/hid-logitech-hidpp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 2869bbff0899..2e2515a4c070 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -1226,7 +1226,7 @@ static void hidpp_ff_destroy(struct ff_device *ff) kfree(data->effect_ids); } -int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index) +static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index) { struct hid_device *hid = hidpp->hid_dev; struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); @@ -1337,7 +1337,7 @@ int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index) return 0; } -int hidpp_ff_deinit(struct hid_device *hid) +static int hidpp_ff_deinit(struct hid_device *hid) { struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); struct input_dev *dev = hidinput->input; -- cgit v1.2.3 From ccdbddfeff58788f7887f39a681b73c3d95b1d2f Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 30 Dec 2015 22:16:38 +0800 Subject: gpio: davinci: use irq_data_get_chip_type Use irq_data_get_chip_type() instead of container_of(). Signed-off-by: Geliang Tang Reviewed-by: Grygorii Strashko Acked-by: Santosh Shilimkar Signed-off-by: Linus Walleij --- drivers/gpio/gpio-davinci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index ec58f4288649..845edffbcc3f 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -432,8 +432,7 @@ static struct irq_chip *davinci_gpio_get_irq_chip(unsigned int irq) { static struct irq_chip_type gpio_unbanked; - gpio_unbanked = *container_of(irq_get_chip(irq), - struct irq_chip_type, chip); + gpio_unbanked = *irq_data_get_chip_type(irq_get_irq_data(irq)); return &gpio_unbanked.chip; }; -- cgit v1.2.3 From 633f67a51d078bea627f22d6208442e1e1f391cb Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Sun, 17 Jan 2016 16:49:07 +0100 Subject: HSI: nokia-modem: add n950 and n9 support The Nokia N950 and Nokia N9 also have a SSI connected modem, which use the same protocols as the Nokia N900, but with increased link speed (96000 kbps instead of 55000 kbps) and with less GPIOs. Since it's unclear, if the N950 and the N9 use exactly the same modem, each of them gets their own compatible string. Acked-by: Rob Herring Tested-by: Aaro Koskinen Signed-off-by: Sebastian Reichel --- Documentation/devicetree/bindings/hsi/nokia-modem.txt | 12 +++++++----- drivers/hsi/clients/nokia-modem.c | 2 ++ 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/hsi/nokia-modem.txt b/Documentation/devicetree/bindings/hsi/nokia-modem.txt index 8a979780452b..53de1d9d0b95 100644 --- a/Documentation/devicetree/bindings/hsi/nokia-modem.txt +++ b/Documentation/devicetree/bindings/hsi/nokia-modem.txt @@ -7,6 +7,8 @@ properties are needed by the Nokia modem HSI client: Required properties: - compatible: Should be one of "nokia,n900-modem" + "nokia,n950-modem" + "nokia,n9-modem" - hsi-channel-names: Should contain the following strings "mcsaab-control" "speech-control" @@ -15,11 +17,11 @@ Required properties: - gpios: Should provide a GPIO handler for each GPIO listed in gpio-names - gpio-names: Should contain the following strings - "cmt_apeslpx" - "cmt_rst_rq" - "cmt_en" - "cmt_rst" - "cmt_bsi" + "cmt_apeslpx" (for n900, n950, n9) + "cmt_rst_rq" (for n900, n950, n9) + "cmt_en" (for n900, n950, n9) + "cmt_rst" (for n900) + "cmt_bsi" (for n900) - interrupts: Should be IRQ handle for modem's reset indication Example: diff --git a/drivers/hsi/clients/nokia-modem.c b/drivers/hsi/clients/nokia-modem.c index 7f82c911ad74..c000780d931f 100644 --- a/drivers/hsi/clients/nokia-modem.c +++ b/drivers/hsi/clients/nokia-modem.c @@ -281,6 +281,8 @@ static int nokia_modem_remove(struct device *dev) #ifdef CONFIG_OF static const struct of_device_id nokia_modem_of_match[] = { { .compatible = "nokia,n900-modem", }, + { .compatible = "nokia,n950-modem", }, + { .compatible = "nokia,n9-modem", }, {}, }; MODULE_DEVICE_TABLE(of, nokia_modem_of_match); -- cgit v1.2.3 From 28b8d66e0c1cc6c02b8159ae44aec359e12feefa Mon Sep 17 00:00:00 2001 From: Nicolai Hähnle Date: Wed, 27 Jan 2016 11:04:19 -0500 Subject: drm/amdgpu: only move pt bos in LRU list on success MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a race condition in the error case: since the pt bos have not necessarily been reserved in case of an error, we could move a pt bo that is currently in the middle of being evicted/moved by another process, which then resulted in a BUG_ON in ttm_bo_add_to_lru. Reviewed-by: Christian König Signed-off-by: Nicolai Hähnle Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 6f89f8e034d0..b882e8175615 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -478,9 +478,9 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo struct amdgpu_fpriv *fpriv = parser->filp->driver_priv; unsigned i; - amdgpu_vm_move_pt_bos_in_lru(parser->adev, &fpriv->vm); - if (!error) { + amdgpu_vm_move_pt_bos_in_lru(parser->adev, &fpriv->vm); + /* Sort the buffer list from the smallest to largest buffer, * which affects the order of buffers in the LRU list. * This assures that the smallest buffers are added first -- cgit v1.2.3 From 87d99063be016ceee90723a13365a40b21eec0d9 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Sun, 17 Jan 2016 16:49:08 +0100 Subject: HSI: ssi-protocol: Use handshake logic from n950 When using the ssi-protocol driver with the Nokia N950, the following error is thrown during modem powered up sequence. [13852.274993] port0: SSI error: 0x01 [13852.279205] ssi-protocol ssi-protocol: RX error detected [13852.284820] ssi-protocol ssi-protocol: Main state: 1 [13852.290069] ssi-protocol ssi-protocol: Recv state: 0 [13852.295288] ssi-protocol ssi-protocol: Send state: 0 [13852.300537] ssi-protocol ssi-protocol: CMT Offline [13852.305603] ssi-protocol ssi-protocol: Wake test 1 [13852.310638] ssi-protocol ssi-protocol: Data RX id: 0 [13852.315887] ssi-protocol ssi-protocol: Data TX id: 0 [13856.001464] ssi-protocol ssi-protocol: Watchdog trigerred [13856.007293] ssi-protocol ssi-protocol: Main state: 1 [13856.012542] ssi-protocol ssi-protocol: Recv state: 0 [13856.017761] ssi-protocol ssi-protocol: Send state: 0 [13856.023010] ssi-protocol ssi-protocol: CMT Offline [13856.028045] ssi-protocol ssi-protocol: Wake test 0 [13856.033111] ssi-protocol ssi-protocol: Data RX id: 0 [13856.038330] ssi-protocol ssi-protocol: Data TX id: 0 This patch fixes the issue by using the handshake setup from the Nokia N950 kernel. The new handshake sequence also works with the N900, so there is no need to differentiate between both modems. Tested-by: Aaro Koskinen Signed-off-by: Sebastian Reichel --- drivers/hsi/clients/ssi_protocol.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c index a38af68cf326..6595d2091268 100644 --- a/drivers/hsi/clients/ssi_protocol.c +++ b/drivers/hsi/clients/ssi_protocol.c @@ -521,13 +521,7 @@ static void ssip_start_rx(struct hsi_client *cl) * high transition. Therefore we need to ignore the sencond UP event. */ if ((ssi->main_state != ACTIVE) || (ssi->recv_state == RECV_READY)) { - if (ssi->main_state == INIT) { - ssi->main_state = HANDSHAKE; - spin_unlock(&ssi->lock); - ssip_send_bootinfo_req_cmd(cl); - } else { - spin_unlock(&ssi->lock); - } + spin_unlock(&ssi->lock); return; } ssip_set_rxstate(ssi, RECV_READY); @@ -671,6 +665,7 @@ static void ssip_rx_bootinforeq(struct hsi_client *cl, u32 cmd) ssip_error(cl); /* Fall through */ case INIT: + case HANDSHAKE: spin_lock(&ssi->lock); ssi->main_state = HANDSHAKE; if (!ssi->waketest) { @@ -688,9 +683,6 @@ static void ssip_rx_bootinforeq(struct hsi_client *cl, u32 cmd) msg->complete = ssip_release_cmd; hsi_async_write(cl, msg); break; - case HANDSHAKE: - /* Ignore */ - break; default: dev_dbg(&cl->device, "Wrong state M(%d)\n", ssi->main_state); break; @@ -939,9 +931,11 @@ static int ssip_pn_open(struct net_device *dev) ssi->waketest = 1; ssi_waketest(cl, 1); /* FIXME: To be removed */ } - ssi->main_state = INIT; + ssi->main_state = HANDSHAKE; spin_unlock_bh(&ssi->lock); + ssip_send_bootinfo_req_cmd(cl); + return 0; } -- cgit v1.2.3 From bb07698fc8d13ec74f4f5bd87b04953777ee6982 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Tue, 26 Jan 2016 11:30:18 +0800 Subject: clk: rockchip: fix wrong mmc phase shift for rk3228 mmc sample shift is 0 for rk3228 refer to user manaul. So it's broken if we enable mmc tuning for rk3228. Fixes: 307a2e9ac ("clk: rockchip: add clock controller for rk3228") Signed-off-by: Shawn Lin Reviewed-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3228.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index 981a50205339..97f49aab8d42 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c @@ -605,13 +605,13 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { /* PD_MMC */ MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK3228_SDMMC_CON0, 1), - MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3228_SDMMC_CON1, 1), + MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3228_SDMMC_CON1, 0), MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK3228_SDIO_CON0, 1), - MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3228_SDIO_CON1, 1), + MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3228_SDIO_CON1, 0), MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK3228_EMMC_CON0, 1), - MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 1), + MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 0), }; static const char *const rk3228_critical_clocks[] __initconst = { -- cgit v1.2.3 From e5292823c142c9873d7d18cf34e7d97fd8a38f86 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 28 Jan 2016 10:29:54 +0000 Subject: drm/i915: Make LRC (un)pinning work on context and engine Previously intel_lr_context_(un)pin were operating on requests which is in conflict with their names. If we make them take a context and an engine, it makes the names make more sense and it also makes future fixes possible. v2: Rebase for default_context/kernel_context change. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Cc: Chris Wilson Cc: Nick Hoath --- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/intel_lrc.c | 49 ++++++++++++++++++++-------------------- drivers/gpu/drm/i915/intel_lrc.h | 3 ++- 3 files changed, 28 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c1bb6a61745c..a928823507c5 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2680,7 +2680,7 @@ void i915_gem_request_free(struct kref *req_ref) if (ctx) { if (i915.enable_execlists && ctx != req->i915->kernel_context) - intel_lr_context_unpin(req); + intel_lr_context_unpin(ctx, req->ring); i915_gem_context_unreference(ctx); } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index da97bc5666b5..6c95aa19cc90 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -225,7 +225,8 @@ enum { #define GEN8_CTX_ID_SHIFT 32 #define CTX_RCS_INDIRECT_CTX_OFFSET_DEFAULT 0x17 -static int intel_lr_context_pin(struct drm_i915_gem_request *rq); +static int intel_lr_context_pin(struct intel_context *ctx, + struct intel_engine_cs *engine); static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring, struct drm_i915_gem_object *default_ctx_obj); @@ -598,7 +599,7 @@ static int execlists_context_queue(struct drm_i915_gem_request *request) int num_elements = 0; if (request->ctx != request->i915->kernel_context) - intel_lr_context_pin(request); + intel_lr_context_pin(request->ctx, ring); i915_gem_request_reference(request); @@ -703,7 +704,7 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request } if (request->ctx != request->i915->kernel_context) - ret = intel_lr_context_pin(request); + ret = intel_lr_context_pin(request->ctx, request->ring); return ret; } @@ -1014,7 +1015,8 @@ void intel_execlists_retire_requests(struct intel_engine_cs *ring) ctx->engine[ring->id].state; if (ctx_obj && (ctx != req->i915->kernel_context)) - intel_lr_context_unpin(req); + intel_lr_context_unpin(ctx, ring); + list_del(&req->execlist_link); i915_gem_request_unreference(req); } @@ -1058,8 +1060,8 @@ int logical_ring_flush_all_caches(struct drm_i915_gem_request *req) return 0; } -static int intel_lr_context_do_pin(struct intel_engine_cs *ring, - struct intel_context *ctx) +static int intel_lr_context_do_pin(struct intel_context *ctx, + struct intel_engine_cs *ring) { struct drm_device *dev = ring->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -1105,41 +1107,40 @@ unpin_ctx_obj: return ret; } -static int intel_lr_context_pin(struct drm_i915_gem_request *rq) +static int intel_lr_context_pin(struct intel_context *ctx, + struct intel_engine_cs *engine) { int ret = 0; - struct intel_engine_cs *ring = rq->ring; - if (rq->ctx->engine[ring->id].pin_count++ == 0) { - ret = intel_lr_context_do_pin(ring, rq->ctx); + if (ctx->engine[engine->id].pin_count++ == 0) { + ret = intel_lr_context_do_pin(ctx, engine); if (ret) goto reset_pin_count; } return ret; reset_pin_count: - rq->ctx->engine[ring->id].pin_count = 0; + ctx->engine[engine->id].pin_count = 0; return ret; } -void intel_lr_context_unpin(struct drm_i915_gem_request *rq) +void intel_lr_context_unpin(struct intel_context *ctx, + struct intel_engine_cs *engine) { - struct intel_engine_cs *ring = rq->ring; - struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring->id].state; - struct intel_ringbuffer *ringbuf = rq->ringbuf; + struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state; - WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex)); + WARN_ON(!mutex_is_locked(&engine->dev->struct_mutex)); - if (!ctx_obj) + if (WARN_ON_ONCE(!ctx_obj)) return; - if (--rq->ctx->engine[ring->id].pin_count == 0) { - kunmap(kmap_to_page(rq->ctx->engine[ring->id].lrc_reg_state)); - intel_unpin_ringbuffer_obj(ringbuf); + if (--ctx->engine[engine->id].pin_count == 0) { + kunmap(kmap_to_page(ctx->engine[engine->id].lrc_reg_state)); + intel_unpin_ringbuffer_obj(ctx->engine[engine->id].ringbuf); i915_gem_object_ggtt_unpin(ctx_obj); - rq->ctx->engine[ring->id].lrc_vma = NULL; - rq->ctx->engine[ring->id].lrc_desc = 0; - rq->ctx->engine[ring->id].lrc_reg_state = NULL; + ctx->engine[engine->id].lrc_vma = NULL; + ctx->engine[engine->id].lrc_desc = 0; + ctx->engine[engine->id].lrc_reg_state = NULL; } } @@ -2064,7 +2065,7 @@ logical_ring_init(struct drm_device *dev, struct intel_engine_cs *ring) goto error; /* As this is the default context, always pin it */ - ret = intel_lr_context_do_pin(ring, dctx); + ret = intel_lr_context_do_pin(dctx, ring); if (ret) { DRM_ERROR( "Failed to pin and map ringbuffer %s: %d\n", diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 49af638f6213..e6cda3e225d0 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -101,7 +101,8 @@ void intel_lr_context_free(struct intel_context *ctx); uint32_t intel_lr_context_size(struct intel_engine_cs *ring); int intel_lr_context_deferred_alloc(struct intel_context *ctx, struct intel_engine_cs *ring); -void intel_lr_context_unpin(struct drm_i915_gem_request *req); +void intel_lr_context_unpin(struct intel_context *ctx, + struct intel_engine_cs *engine); void intel_lr_context_reset(struct drm_device *dev, struct intel_context *ctx); uint64_t intel_lr_context_descriptor(struct intel_context *ctx, -- cgit v1.2.3 From 321fe304f1dd2dca025141b1d3211415af59020f Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 28 Jan 2016 10:29:55 +0000 Subject: drm/i915: Make LRC pinning own a reference to the context Will simplify the following fix and sounds logical. v2: Add some whitespace to separate logic better. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Cc: Chris Wilson Cc: Nick Hoath --- drivers/gpu/drm/i915/intel_lrc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 6c95aa19cc90..61e64d78adbd 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1116,6 +1116,8 @@ static int intel_lr_context_pin(struct intel_context *ctx, ret = intel_lr_context_do_pin(ctx, engine); if (ret) goto reset_pin_count; + + i915_gem_context_reference(ctx); } return ret; @@ -1141,6 +1143,8 @@ void intel_lr_context_unpin(struct intel_context *ctx, ctx->engine[engine->id].lrc_vma = NULL; ctx->engine[engine->id].lrc_desc = 0; ctx->engine[engine->id].lrc_reg_state = NULL; + + i915_gem_context_unreference(ctx); } } -- cgit v1.2.3 From a0b4a6a8dbb147159602f0f82847ccd87bee5de8 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 28 Jan 2016 10:29:56 +0000 Subject: drm/i915: Extract context unpinning to its own function Will enable cleaner implementation of a following fix and easier code unification in the future. Idea and code by Chris Wilson. v2: Do not return before last_contexts on engines are unpinned. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Cc: Chris Wilson --- drivers/gpu/drm/i915/i915_gem_context.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 6a4f64b03db6..bba17b9f1be5 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -321,6 +321,14 @@ err_destroy: return ERR_PTR(ret); } +static void i915_gem_context_unpin(struct intel_context *ctx, + struct intel_engine_cs *engine) +{ + if (engine->id == RCS && ctx->legacy_hw_ctx.rcs_state) + i915_gem_object_ggtt_unpin(ctx->legacy_hw_ctx.rcs_state); + i915_gem_context_unreference(ctx); +} + void i915_gem_context_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -329,22 +337,15 @@ void i915_gem_context_reset(struct drm_device *dev) if (i915.enable_execlists) { struct intel_context *ctx; - list_for_each_entry(ctx, &dev_priv->context_list, link) { + list_for_each_entry(ctx, &dev_priv->context_list, link) intel_lr_context_reset(dev, ctx); - } - - return; } for (i = 0; i < I915_NUM_RINGS; i++) { struct intel_engine_cs *ring = &dev_priv->ring[i]; - struct intel_context *lctx = ring->last_context; - - if (lctx) { - if (lctx->legacy_hw_ctx.rcs_state && i == RCS) - i915_gem_object_ggtt_unpin(lctx->legacy_hw_ctx.rcs_state); - i915_gem_context_unreference(lctx); + if (ring->last_context) { + i915_gem_context_unpin(ring->last_context, ring); ring->last_context = NULL; } } @@ -417,13 +418,6 @@ void i915_gem_context_fini(struct drm_device *dev) * to offset the do_switch part, so that i915_gem_context_unreference() * can then free the base object correctly. */ WARN_ON(!dev_priv->ring[RCS].last_context); - if (dev_priv->ring[RCS].last_context == dctx) { - /* Fake switch to NULL context */ - WARN_ON(dctx->legacy_hw_ctx.rcs_state->active); - i915_gem_object_ggtt_unpin(dctx->legacy_hw_ctx.rcs_state); - i915_gem_context_unreference(dctx); - dev_priv->ring[RCS].last_context = NULL; - } i915_gem_object_ggtt_unpin(dctx->legacy_hw_ctx.rcs_state); } @@ -432,7 +426,7 @@ void i915_gem_context_fini(struct drm_device *dev) struct intel_engine_cs *ring = &dev_priv->ring[i]; if (ring->last_context) { - i915_gem_context_unreference(ring->last_context); + i915_gem_context_unpin(ring->last_context, ring); ring->last_context = NULL; } } -- cgit v1.2.3 From f4e2deceb6aaab661be3e13191cd13da3dd3b9c2 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 28 Jan 2016 10:29:57 +0000 Subject: drm/i915: Fix premature LRC unpin in GuC mode In GuC mode LRC pinning lifetime depends exclusively on the request liftime. Since that is terminated by the seqno update that opens up a race condition between GPU finishing writing out the context image and the driver unpinning the LRC. To extend the LRC lifetime we will employ a similar approach to what legacy ringbuffer submission does. We will start tracking the last submitted context per engine and keep it pinned until it is replaced by another one. Note that the driver unload path is a bit fragile and could benefit greatly from efforts to unify the legacy and exec list submission code paths. At the moment i915_gem_context_fini has special casing for the two which are potentialy not needed, and also depends on i915_gem_cleanup_ringbuffer running before itself. v2: * Move pinning into engine->emit_request and actually fix the reference/unreference logic. (Chris Wilson) * ring->dev can be NULL on driver unload so use a different route towards it. v3: * Rebase. * Handle the reset path. (Chris Wilson) * Exclude default context from the pinning - it is impossible to get it right before default context special casing in general is eliminated. v4: * Rebased & moved context tracking to intel_logical_ring_advance_and_submit. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Issue: VIZ-4277 Cc: Chris Wilson Cc: Nick Hoath Link: http://patchwork.freedesktop.org/patch/msgid/1453976997-25424-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_gem_context.c | 10 +++++++--- drivers/gpu/drm/i915/intel_lrc.c | 16 ++++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index bba17b9f1be5..83a097c94911 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -324,9 +324,13 @@ err_destroy: static void i915_gem_context_unpin(struct intel_context *ctx, struct intel_engine_cs *engine) { - if (engine->id == RCS && ctx->legacy_hw_ctx.rcs_state) - i915_gem_object_ggtt_unpin(ctx->legacy_hw_ctx.rcs_state); - i915_gem_context_unreference(ctx); + if (i915.enable_execlists) { + intel_lr_context_unpin(ctx, engine); + } else { + if (engine->id == RCS && ctx->legacy_hw_ctx.rcs_state) + i915_gem_object_ggtt_unpin(ctx->legacy_hw_ctx.rcs_state); + i915_gem_context_unreference(ctx); + } } void i915_gem_context_reset(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 61e64d78adbd..3a03646e343d 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -765,6 +765,7 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request) { struct intel_ringbuffer *ringbuf = request->ringbuf; struct drm_i915_private *dev_priv = request->i915; + struct intel_engine_cs *engine = request->ring; intel_logical_ring_advance(ringbuf); request->tail = ringbuf->tail; @@ -779,9 +780,20 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request) intel_logical_ring_emit(ringbuf, MI_NOOP); intel_logical_ring_advance(ringbuf); - if (intel_ring_stopped(request->ring)) + if (intel_ring_stopped(engine)) return 0; + if (engine->last_context != request->ctx) { + if (engine->last_context) + intel_lr_context_unpin(engine->last_context, engine); + if (request->ctx != request->i915->kernel_context) { + intel_lr_context_pin(request->ctx, engine); + engine->last_context = request->ctx; + } else { + engine->last_context = NULL; + } + } + if (dev_priv->guc.execbuf_client) i915_guc_submit(dev_priv->guc.execbuf_client, request); else @@ -1131,7 +1143,7 @@ void intel_lr_context_unpin(struct intel_context *ctx, { struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state; - WARN_ON(!mutex_is_locked(&engine->dev->struct_mutex)); + WARN_ON(!mutex_is_locked(&ctx->i915->dev->struct_mutex)); if (WARN_ON_ONCE(!ctx_obj)) return; -- cgit v1.2.3 From 0aa498d59c67d925f2a53fdffd1d447727d65c22 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Thu, 28 Jan 2016 10:48:09 +0000 Subject: Fix pointer tests in error-handling paths In the error-handling paths of i915_gem_do_execbuffer() and intel_crtc_page_flip(), the local pointer-to-request variables were expected to be either valid pointers or NULL. Since 2682708 drm/i915: simplify allocation of driver-internal requests they could also be ERR_PTR() values, so the tests need to be updated to accommodate this case. Signed-off-by: Dave Gordon Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/1453978089-29127-1-git-send-email-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 5cb57f642ac1..8fd00d279447 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1655,7 +1655,7 @@ err: * must be freed again. If it was submitted then it is being tracked * on the active request list and no clean up is required here. */ - if (ret && req) + if (ret && !IS_ERR_OR_NULL(req)) i915_gem_request_cancel(req); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8104511ad302..b88cdac747eb 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11726,7 +11726,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, cleanup_unpin: intel_unpin_fb_obj(fb, crtc->primary->state); cleanup_pending: - if (request) + if (!IS_ERR_OR_NULL(request)) i915_gem_request_cancel(request); atomic_dec(&intel_crtc->unpin_work_count); mutex_unlock(&dev->struct_mutex); -- cgit v1.2.3 From 7723f47dc685c7152d3ce217f09f036ec7f3f5ce Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 20 Jan 2016 21:05:22 +0200 Subject: drm/i915: Rename the rotated gtt view member to 'rotated' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also rename 'rotation_info' to 'rotated' to match the view type exactly, this should avoid confusion which union members is valid for each view type. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1453316739-13296-2-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 4 ++-- drivers/gpu/drm/i915/i915_gem_gtt.h | 2 +- drivers/gpu/drm/i915/intel_display.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 2ccb2b52e3bb..5b660ff7fbde 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3381,7 +3381,7 @@ static struct sg_table * intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, struct drm_i915_gem_object *obj) { - struct intel_rotation_info *rot_info = &ggtt_view->params.rotation_info; + struct intel_rotation_info *rot_info = &ggtt_view->params.rotated; unsigned int size_pages = rot_info->size >> PAGE_SHIFT; unsigned int size_pages_uv; struct sg_page_iter sg_iter; @@ -3613,7 +3613,7 @@ i915_ggtt_view_size(struct drm_i915_gem_object *obj, if (view->type == I915_GGTT_VIEW_NORMAL) { return obj->base.size; } else if (view->type == I915_GGTT_VIEW_ROTATED) { - return view->params.rotation_info.size; + return view->params.rotated.size; } else if (view->type == I915_GGTT_VIEW_PARTIAL) { return view->params.partial.size << PAGE_SHIFT; } else { diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index e5737963ab79..f520c90e5377 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -155,7 +155,7 @@ struct i915_ggtt_view { u64 offset; unsigned int size; } partial; - struct intel_rotation_info rotation_info; + struct intel_rotation_info rotated; } params; struct sg_table *pages; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b88cdac747eb..f54e11922353 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2284,7 +2284,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, const struct drm_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(fb->dev); - struct intel_rotation_info *info = &view->params.rotation_info; + struct intel_rotation_info *info = &view->params.rotated; unsigned int tile_size, tile_width, tile_height, cpp; *view = i915_ggtt_view_normal; @@ -2951,7 +2951,7 @@ u32 intel_plane_obj_offset(struct intel_plane *intel_plane, offset = vma->node.start; if (plane == 1) { - offset += vma->ggtt_view.params.rotation_info.uv_start_page * + offset += vma->ggtt_view.params.rotated.uv_start_page * PAGE_SIZE; } -- cgit v1.2.3 From 871302555b1dd19d91b8f78ae1d3790773098ed3 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 20 Jan 2016 21:05:23 +0200 Subject: drm/i915: Pass stride to rotate_pages() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass stride in addition to width and height to rotate_pages(). For now width and stride are the same, but once framebuffer offsets enter the scene that may no longer be the case. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1453316739-13296-3-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 5b660ff7fbde..b5aac6eb1d61 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3348,6 +3348,7 @@ i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj, static struct scatterlist * rotate_pages(const dma_addr_t *in, unsigned int offset, unsigned int width, unsigned int height, + unsigned int stride, struct sg_table *st, struct scatterlist *sg) { unsigned int column, row; @@ -3359,7 +3360,7 @@ rotate_pages(const dma_addr_t *in, unsigned int offset, } for (column = 0; column < width; column++) { - src_idx = width * (height - 1) + column; + src_idx = stride * (height - 1) + column; for (row = 0; row < height; row++) { st->nents++; /* We don't need the pages, but need to initialize @@ -3370,7 +3371,7 @@ rotate_pages(const dma_addr_t *in, unsigned int offset, sg_dma_address(sg) = in[offset + src_idx]; sg_dma_len(sg) = PAGE_SIZE; sg = sg_next(sg); - src_idx -= width; + src_idx -= stride; } } @@ -3423,6 +3424,7 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, /* Rotate the pages. */ sg = rotate_pages(page_addr_list, 0, rot_info->width_pages, rot_info->height_pages, + rot_info->width_pages, st, NULL); /* Append the UV plane if NV12. */ @@ -3438,6 +3440,7 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, rotate_pages(page_addr_list, uv_start_page, rot_info->width_pages_uv, rot_info->height_pages_uv, + rot_info->width_pages_uv, st, sg); } -- cgit v1.2.3 From 11d23e6fa186f91cc6b1ccf27bbb14810c9baefe Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 20 Jan 2016 21:05:24 +0200 Subject: drm/i915: Pass rotation_info to intel_rotate_fb_obj_pages() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_rotate_fb_obj_pages() doens't need the entire gtt view, just the rotation info suffices. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1453316739-13296-4-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index b5aac6eb1d61..715a771f0b31 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3379,10 +3379,9 @@ rotate_pages(const dma_addr_t *in, unsigned int offset, } static struct sg_table * -intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, +intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info, struct drm_i915_gem_object *obj) { - struct intel_rotation_info *rot_info = &ggtt_view->params.rotated; unsigned int size_pages = rot_info->size >> PAGE_SHIFT; unsigned int size_pages_uv; struct sg_page_iter sg_iter; @@ -3522,7 +3521,7 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma) vma->ggtt_view.pages = vma->obj->pages; else if (vma->ggtt_view.type == I915_GGTT_VIEW_ROTATED) vma->ggtt_view.pages = - intel_rotate_fb_obj_pages(&vma->ggtt_view, vma->obj); + intel_rotate_fb_obj_pages(&vma->ggtt_view.params.rotated, vma->obj); else if (vma->ggtt_view.type == I915_GGTT_VIEW_PARTIAL) vma->ggtt_view.pages = intel_partial_pages(&vma->ggtt_view, vma->obj); -- cgit v1.2.3 From 54ea9da88fc89bbba0c2f888bdb265d9fd6a3945 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 20 Jan 2016 21:05:25 +0200 Subject: drm/i915: Make display gtt offsets u32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using 'unsigned long' for ggtt offsets doesn't make much sense. Use 'u32' instead since we've not yet seen a >4GiB ggtt. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1453316739-13296-5-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++------------ drivers/gpu/drm/i915/intel_drv.h | 12 ++++++------ drivers/gpu/drm/i915/intel_sprite.c | 6 +++--- 3 files changed, 19 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f54e11922353..97af94a12960 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2448,11 +2448,11 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb, /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel * is assumed to be a power-of-two. */ -unsigned long intel_compute_tile_offset(struct drm_i915_private *dev_priv, - int *x, int *y, - uint64_t fb_modifier, - unsigned int cpp, - unsigned int pitch) +u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv, + int *x, int *y, + uint64_t fb_modifier, + unsigned int cpp, + unsigned int pitch) { if (fb_modifier != DRM_FORMAT_MOD_NONE) { unsigned int tile_size, tile_width, tile_height; @@ -2706,14 +2706,12 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, struct drm_framebuffer *fb = plane_state->base.fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); int plane = intel_crtc->plane; - unsigned long linear_offset; - int x = plane_state->src.x1 >> 16; - int y = plane_state->src.y1 >> 16; + u32 linear_offset; u32 dspcntr; i915_reg_t reg = DSPCNTR(plane); - int pixel_size; - - pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); + int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); + int x = plane_state->src.x1 >> 16; + int y = plane_state->src.y1 >> 16; dspcntr = DISPPLANE_GAMMA_ENABLE; @@ -2839,7 +2837,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, struct drm_framebuffer *fb = plane_state->base.fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); int plane = intel_crtc->plane; - unsigned long linear_offset; + u32 linear_offset; u32 dspcntr; i915_reg_t reg = DSPCNTR(plane); int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index bc970125ec76..f620023ed134 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -575,7 +575,7 @@ struct intel_crtc { /* Display surface base address adjustement for pageflips. Note that on * gen4+ this only adjusts up to a tile, offsets within a tile are * handled in the hw itself (with the TILEOFF register). */ - unsigned long dspaddr_offset; + u32 dspaddr_offset; int adjusted_x; int adjusted_y; @@ -1172,11 +1172,11 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state); #define assert_pipe_enabled(d, p) assert_pipe(d, p, true) #define assert_pipe_disabled(d, p) assert_pipe(d, p, false) -unsigned long intel_compute_tile_offset(struct drm_i915_private *dev_priv, - int *x, int *y, - uint64_t fb_modifier, - unsigned int cpp, - unsigned int pitch); +u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv, + int *x, int *y, + uint64_t fb_modifier, + unsigned int cpp, + unsigned int pitch); void intel_prepare_reset(struct drm_device *dev); void intel_finish_reset(struct drm_device *dev); void hsw_enable_pc8(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 0875c8e0ec0a..f1ee7db0811a 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -350,7 +350,7 @@ vlv_update_plane(struct drm_plane *dplane, int pipe = intel_plane->pipe; int plane = intel_plane->plane; u32 sprctl; - unsigned long sprsurf_offset, linear_offset; + u32 sprsurf_offset, linear_offset; int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; int crtc_x = plane_state->dst.x1; @@ -493,7 +493,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_i915_gem_object *obj = intel_fb_obj(fb); enum pipe pipe = intel_plane->pipe; u32 sprctl, sprscale = 0; - unsigned long sprsurf_offset, linear_offset; + u32 sprsurf_offset, linear_offset; int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; int crtc_x = plane_state->dst.x1; @@ -635,8 +635,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb = plane_state->base.fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); int pipe = intel_plane->pipe; - unsigned long dvssurf_offset, linear_offset; u32 dvscntr, dvsscale; + u32 dvssurf_offset, linear_offset; int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; int crtc_x = plane_state->dst.x1; -- cgit v1.2.3 From ac484963f979b6ab490183f0e09a3a17175f5758 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 20 Jan 2016 21:05:26 +0200 Subject: drm/i915: Standardize on 'cpp' for bytes per pixel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We more or less randomly call the "bytes per pixel" value 'cpp', 'bytes_per_pixel', 'pixel_size', or even 'bpp'. Let's just pick one and stick to it. I've chosen 'cpp'. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1453316739-13296-6-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 22 +++--- drivers/gpu/drm/i915/intel_pm.c | 128 +++++++++++++++++------------------ drivers/gpu/drm/i915/intel_sprite.c | 34 ++++------ 3 files changed, 87 insertions(+), 97 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 97af94a12960..23cce7df74b0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2709,7 +2709,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, u32 linear_offset; u32 dspcntr; i915_reg_t reg = DSPCNTR(plane); - int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); + int cpp = drm_format_plane_cpp(fb->pixel_format, 0); int x = plane_state->src.x1 >> 16; int y = plane_state->src.y1 >> 16; @@ -2769,13 +2769,12 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, if (IS_G4X(dev)) dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; - linear_offset = y * fb->pitches[0] + x * pixel_size; + linear_offset = y * fb->pitches[0] + x * cpp; if (INTEL_INFO(dev)->gen >= 4) { intel_crtc->dspaddr_offset = intel_compute_tile_offset(dev_priv, &x, &y, - fb->modifier[0], - pixel_size, + fb->modifier[0], cpp, fb->pitches[0]); linear_offset -= intel_crtc->dspaddr_offset; } else { @@ -2792,7 +2791,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, data and adding to linear_offset*/ linear_offset += (crtc_state->pipe_src_h - 1) * fb->pitches[0] + - (crtc_state->pipe_src_w - 1) * pixel_size; + (crtc_state->pipe_src_w - 1) * cpp; } intel_crtc->adjusted_x = x; @@ -2840,7 +2839,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, u32 linear_offset; u32 dspcntr; i915_reg_t reg = DSPCNTR(plane); - int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); + int cpp = drm_format_plane_cpp(fb->pixel_format, 0); int x = plane_state->src.x1 >> 16; int y = plane_state->src.y1 >> 16; @@ -2879,11 +2878,10 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; - linear_offset = y * fb->pitches[0] + x * pixel_size; + linear_offset = y * fb->pitches[0] + x * cpp; intel_crtc->dspaddr_offset = intel_compute_tile_offset(dev_priv, &x, &y, - fb->modifier[0], - pixel_size, + fb->modifier[0], cpp, fb->pitches[0]); linear_offset -= intel_crtc->dspaddr_offset; if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { @@ -2897,7 +2895,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, data and adding to linear_offset*/ linear_offset += (crtc_state->pipe_src_h - 1) * fb->pitches[0] + - (crtc_state->pipe_src_w - 1) * pixel_size; + (crtc_state->pipe_src_w - 1) * cpp; } } @@ -14682,10 +14680,12 @@ u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier, u32 gen = INTEL_INFO(dev)->gen; if (gen >= 9) { + int cpp = drm_format_plane_cpp(pixel_format, 0); + /* "The stride in bytes must not exceed the of the size of 8K * pixels and 32K bytes." */ - return min(8192*drm_format_plane_cpp(pixel_format, 0), 32768); + return min(8192 * cpp, 32768); } else if (gen >= 5 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) { return 32*1024; } else if (gen >= 4) { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 20bf854eae8c..31bc4ea395ac 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -548,7 +548,7 @@ static const struct intel_watermark_params i845_wm_info = { * intel_calculate_wm - calculate watermark level * @clock_in_khz: pixel clock * @wm: chip FIFO params - * @pixel_size: display pixel size + * @cpp: bytes per pixel * @latency_ns: memory latency for the platform * * Calculate the watermark level (the level at which the display plane will @@ -564,8 +564,7 @@ static const struct intel_watermark_params i845_wm_info = { */ static unsigned long intel_calculate_wm(unsigned long clock_in_khz, const struct intel_watermark_params *wm, - int fifo_size, - int pixel_size, + int fifo_size, int cpp, unsigned long latency_ns) { long entries_required, wm_size; @@ -576,7 +575,7 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz, * clocks go from a few thousand to several hundred thousand. * latency is usually a few thousand */ - entries_required = ((clock_in_khz / 1000) * pixel_size * latency_ns) / + entries_required = ((clock_in_khz / 1000) * cpp * latency_ns) / 1000; entries_required = DIV_ROUND_UP(entries_required, wm->cacheline_size); @@ -640,13 +639,13 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc) crtc = single_enabled_crtc(dev); if (crtc) { const struct drm_display_mode *adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode; - int pixel_size = crtc->primary->state->fb->bits_per_pixel / 8; + int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); int clock = adjusted_mode->crtc_clock; /* Display SR */ wm = intel_calculate_wm(clock, &pineview_display_wm, pineview_display_wm.fifo_size, - pixel_size, latency->display_sr); + cpp, latency->display_sr); reg = I915_READ(DSPFW1); reg &= ~DSPFW_SR_MASK; reg |= FW_WM(wm, SR); @@ -656,7 +655,7 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc) /* cursor SR */ wm = intel_calculate_wm(clock, &pineview_cursor_wm, pineview_display_wm.fifo_size, - pixel_size, latency->cursor_sr); + cpp, latency->cursor_sr); reg = I915_READ(DSPFW3); reg &= ~DSPFW_CURSOR_SR_MASK; reg |= FW_WM(wm, CURSOR_SR); @@ -665,7 +664,7 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc) /* Display HPLL off SR */ wm = intel_calculate_wm(clock, &pineview_display_hplloff_wm, pineview_display_hplloff_wm.fifo_size, - pixel_size, latency->display_hpll_disable); + cpp, latency->display_hpll_disable); reg = I915_READ(DSPFW3); reg &= ~DSPFW_HPLL_SR_MASK; reg |= FW_WM(wm, HPLL_SR); @@ -674,7 +673,7 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc) /* cursor HPLL off SR */ wm = intel_calculate_wm(clock, &pineview_cursor_hplloff_wm, pineview_display_hplloff_wm.fifo_size, - pixel_size, latency->cursor_hpll_disable); + cpp, latency->cursor_hpll_disable); reg = I915_READ(DSPFW3); reg &= ~DSPFW_HPLL_CURSOR_MASK; reg |= FW_WM(wm, HPLL_CURSOR); @@ -698,7 +697,7 @@ static bool g4x_compute_wm0(struct drm_device *dev, { struct drm_crtc *crtc; const struct drm_display_mode *adjusted_mode; - int htotal, hdisplay, clock, pixel_size; + int htotal, hdisplay, clock, cpp; int line_time_us, line_count; int entries, tlb_miss; @@ -713,10 +712,10 @@ static bool g4x_compute_wm0(struct drm_device *dev, clock = adjusted_mode->crtc_clock; htotal = adjusted_mode->crtc_htotal; hdisplay = to_intel_crtc(crtc)->config->pipe_src_w; - pixel_size = crtc->primary->state->fb->bits_per_pixel / 8; + cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); /* Use the small buffer method to calculate plane watermark */ - entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000; + entries = ((clock * cpp / 1000) * display_latency_ns) / 1000; tlb_miss = display->fifo_size*display->cacheline_size - hdisplay * 8; if (tlb_miss > 0) entries += tlb_miss; @@ -728,7 +727,7 @@ static bool g4x_compute_wm0(struct drm_device *dev, /* Use the large buffer method to calculate cursor watermark */ line_time_us = max(htotal * 1000 / clock, 1); line_count = (cursor_latency_ns / line_time_us + 1000) / 1000; - entries = line_count * crtc->cursor->state->crtc_w * pixel_size; + entries = line_count * crtc->cursor->state->crtc_w * cpp; tlb_miss = cursor->fifo_size*cursor->cacheline_size - hdisplay * 8; if (tlb_miss > 0) entries += tlb_miss; @@ -784,7 +783,7 @@ static bool g4x_compute_srwm(struct drm_device *dev, { struct drm_crtc *crtc; const struct drm_display_mode *adjusted_mode; - int hdisplay, htotal, pixel_size, clock; + int hdisplay, htotal, cpp, clock; unsigned long line_time_us; int line_count, line_size; int small, large; @@ -800,21 +799,21 @@ static bool g4x_compute_srwm(struct drm_device *dev, clock = adjusted_mode->crtc_clock; htotal = adjusted_mode->crtc_htotal; hdisplay = to_intel_crtc(crtc)->config->pipe_src_w; - pixel_size = crtc->primary->state->fb->bits_per_pixel / 8; + cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); line_time_us = max(htotal * 1000 / clock, 1); line_count = (latency_ns / line_time_us + 1000) / 1000; - line_size = hdisplay * pixel_size; + line_size = hdisplay * cpp; /* Use the minimum of the small and large buffer method for primary */ - small = ((clock * pixel_size / 1000) * latency_ns) / 1000; + small = ((clock * cpp / 1000) * latency_ns) / 1000; large = line_count * line_size; entries = DIV_ROUND_UP(min(small, large), display->cacheline_size); *display_wm = entries + display->guard_size; /* calculate the self-refresh watermark for display cursor */ - entries = line_count * pixel_size * crtc->cursor->state->crtc_w; + entries = line_count * cpp * crtc->cursor->state->crtc_w; entries = DIV_ROUND_UP(entries, cursor->cacheline_size); *cursor_wm = entries + cursor->guard_size; @@ -906,13 +905,13 @@ enum vlv_wm_level { static unsigned int vlv_wm_method2(unsigned int pixel_rate, unsigned int pipe_htotal, unsigned int horiz_pixels, - unsigned int bytes_per_pixel, + unsigned int cpp, unsigned int latency) { unsigned int ret; ret = (latency * pixel_rate) / (pipe_htotal * 10000); - ret = (ret + 1) * horiz_pixels * bytes_per_pixel; + ret = (ret + 1) * horiz_pixels * cpp; ret = DIV_ROUND_UP(ret, 64); return ret; @@ -941,7 +940,7 @@ static uint16_t vlv_compute_wm_level(struct intel_plane *plane, int level) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - int clock, htotal, pixel_size, width, wm; + int clock, htotal, cpp, width, wm; if (dev_priv->wm.pri_latency[level] == 0) return USHRT_MAX; @@ -949,7 +948,7 @@ static uint16_t vlv_compute_wm_level(struct intel_plane *plane, if (!state->visible) return 0; - pixel_size = drm_format_plane_cpp(state->base.fb->pixel_format, 0); + cpp = drm_format_plane_cpp(state->base.fb->pixel_format, 0); clock = crtc->config->base.adjusted_mode.crtc_clock; htotal = crtc->config->base.adjusted_mode.crtc_htotal; width = crtc->config->pipe_src_w; @@ -965,7 +964,7 @@ static uint16_t vlv_compute_wm_level(struct intel_plane *plane, */ wm = 63; } else { - wm = vlv_wm_method2(clock, htotal, width, pixel_size, + wm = vlv_wm_method2(clock, htotal, width, cpp, dev_priv->wm.pri_latency[level] * 10); } @@ -1439,7 +1438,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc) int clock = adjusted_mode->crtc_clock; int htotal = adjusted_mode->crtc_htotal; int hdisplay = to_intel_crtc(crtc)->config->pipe_src_w; - int pixel_size = crtc->primary->state->fb->bits_per_pixel / 8; + int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); unsigned long line_time_us; int entries; @@ -1447,7 +1446,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc) /* Use ns/us then divide to preserve precision */ entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * - pixel_size * hdisplay; + cpp * hdisplay; entries = DIV_ROUND_UP(entries, I915_FIFO_LINE_SIZE); srwm = I965_FIFO_SIZE - entries; if (srwm < 0) @@ -1457,7 +1456,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc) entries, srwm); entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * - pixel_size * crtc->cursor->state->crtc_w; + cpp * crtc->cursor->state->crtc_w; entries = DIV_ROUND_UP(entries, i965_cursor_wm_info.cacheline_size); cursor_sr = i965_cursor_wm_info.fifo_size - @@ -1518,7 +1517,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) crtc = intel_get_crtc_for_plane(dev, 0); if (intel_crtc_active(crtc)) { const struct drm_display_mode *adjusted_mode; - int cpp = crtc->primary->state->fb->bits_per_pixel / 8; + int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); if (IS_GEN2(dev)) cpp = 4; @@ -1540,7 +1539,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) crtc = intel_get_crtc_for_plane(dev, 1); if (intel_crtc_active(crtc)) { const struct drm_display_mode *adjusted_mode; - int cpp = crtc->primary->state->fb->bits_per_pixel / 8; + int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); if (IS_GEN2(dev)) cpp = 4; @@ -1586,7 +1585,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) int clock = adjusted_mode->crtc_clock; int htotal = adjusted_mode->crtc_htotal; int hdisplay = to_intel_crtc(enabled)->config->pipe_src_w; - int pixel_size = enabled->primary->state->fb->bits_per_pixel / 8; + int cpp = drm_format_plane_cpp(enabled->primary->state->fb->pixel_format, 0); unsigned long line_time_us; int entries; @@ -1594,7 +1593,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) /* Use ns/us then divide to preserve precision */ entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * - pixel_size * hdisplay; + cpp * hdisplay; entries = DIV_ROUND_UP(entries, wm_info->cacheline_size); DRM_DEBUG_KMS("self-refresh entries: %d\n", entries); srwm = wm_info->fifo_size - entries; @@ -1685,15 +1684,14 @@ uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config) } /* latency must be in 0.1us units. */ -static uint32_t ilk_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel, - uint32_t latency) +static uint32_t ilk_wm_method1(uint32_t pixel_rate, uint8_t cpp, uint32_t latency) { uint64_t ret; if (WARN(latency == 0, "Latency value missing\n")) return UINT_MAX; - ret = (uint64_t) pixel_rate * bytes_per_pixel * latency; + ret = (uint64_t) pixel_rate * cpp * latency; ret = DIV_ROUND_UP_ULL(ret, 64 * 10000) + 2; return ret; @@ -1701,7 +1699,7 @@ static uint32_t ilk_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel, /* latency must be in 0.1us units. */ static uint32_t ilk_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal, - uint32_t horiz_pixels, uint8_t bytes_per_pixel, + uint32_t horiz_pixels, uint8_t cpp, uint32_t latency) { uint32_t ret; @@ -1712,13 +1710,13 @@ static uint32_t ilk_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal, return UINT_MAX; ret = (latency * pixel_rate) / (pipe_htotal * 10000); - ret = (ret + 1) * horiz_pixels * bytes_per_pixel; + ret = (ret + 1) * horiz_pixels * cpp; ret = DIV_ROUND_UP(ret, 64) + 2; return ret; } static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels, - uint8_t bytes_per_pixel) + uint8_t cpp) { /* * Neither of these should be possible since this function shouldn't be @@ -1726,12 +1724,12 @@ static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels, * extra paranoid to avoid a potential divide-by-zero if we screw up * elsewhere in the driver. */ - if (WARN_ON(!bytes_per_pixel)) + if (WARN_ON(!cpp)) return 0; if (WARN_ON(!horiz_pixels)) return 0; - return DIV_ROUND_UP(pri_val * 64, horiz_pixels * bytes_per_pixel) + 2; + return DIV_ROUND_UP(pri_val * 64, horiz_pixels * cpp) + 2; } struct ilk_wm_maximums { @@ -1750,13 +1748,14 @@ static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate, uint32_t mem_value, bool is_lp) { - int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0; + int cpp = pstate->base.fb ? + drm_format_plane_cpp(pstate->base.fb->pixel_format, 0) : 0; uint32_t method1, method2; if (!cstate->base.active || !pstate->visible) return 0; - method1 = ilk_wm_method1(ilk_pipe_pixel_rate(cstate), bpp, mem_value); + method1 = ilk_wm_method1(ilk_pipe_pixel_rate(cstate), cpp, mem_value); if (!is_lp) return method1; @@ -1764,8 +1763,7 @@ static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate, method2 = ilk_wm_method2(ilk_pipe_pixel_rate(cstate), cstate->base.adjusted_mode.crtc_htotal, drm_rect_width(&pstate->dst), - bpp, - mem_value); + cpp, mem_value); return min(method1, method2); } @@ -1778,18 +1776,18 @@ static uint32_t ilk_compute_spr_wm(const struct intel_crtc_state *cstate, const struct intel_plane_state *pstate, uint32_t mem_value) { - int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0; + int cpp = pstate->base.fb ? + drm_format_plane_cpp(pstate->base.fb->pixel_format, 0) : 0; uint32_t method1, method2; if (!cstate->base.active || !pstate->visible) return 0; - method1 = ilk_wm_method1(ilk_pipe_pixel_rate(cstate), bpp, mem_value); + method1 = ilk_wm_method1(ilk_pipe_pixel_rate(cstate), cpp, mem_value); method2 = ilk_wm_method2(ilk_pipe_pixel_rate(cstate), cstate->base.adjusted_mode.crtc_htotal, drm_rect_width(&pstate->dst), - bpp, - mem_value); + cpp, mem_value); return min(method1, method2); } @@ -1801,7 +1799,8 @@ static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate, const struct intel_plane_state *pstate, uint32_t mem_value) { - int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0; + int cpp = pstate->base.fb ? + drm_format_plane_cpp(pstate->base.fb->pixel_format, 0) : 0; if (!cstate->base.active || !pstate->visible) return 0; @@ -1809,8 +1808,7 @@ static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate, return ilk_wm_method2(ilk_pipe_pixel_rate(cstate), cstate->base.adjusted_mode.crtc_htotal, drm_rect_width(&pstate->dst), - bpp, - mem_value); + cpp, mem_value); } /* Only for WM_LP. */ @@ -1818,12 +1816,13 @@ static uint32_t ilk_compute_fbc_wm(const struct intel_crtc_state *cstate, const struct intel_plane_state *pstate, uint32_t pri_val) { - int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0; + int cpp = pstate->base.fb ? + drm_format_plane_cpp(pstate->base.fb->pixel_format, 0) : 0; if (!cstate->base.active || !pstate->visible) return 0; - return ilk_wm_fbc(pri_val, drm_rect_width(&pstate->dst), bpp); + return ilk_wm_fbc(pri_val, drm_rect_width(&pstate->dst), cpp); } static unsigned int ilk_display_fifo_size(const struct drm_device *dev) @@ -3042,26 +3041,25 @@ static uint32_t skl_pipe_pixel_rate(const struct intel_crtc_state *config) /* * The max latency should be 257 (max the punit can code is 255 and we add 2us - * for the read latency) and bytes_per_pixel should always be <= 8, so that + * for the read latency) and cpp should always be <= 8, so that * should allow pixel_rate up to ~2 GHz which seems sufficient since max * 2xcdclk is 1350 MHz and the pixel rate should never exceed that. */ -static uint32_t skl_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel, - uint32_t latency) +static uint32_t skl_wm_method1(uint32_t pixel_rate, uint8_t cpp, uint32_t latency) { uint32_t wm_intermediate_val, ret; if (latency == 0) return UINT_MAX; - wm_intermediate_val = latency * pixel_rate * bytes_per_pixel / 512; + wm_intermediate_val = latency * pixel_rate * cpp / 512; ret = DIV_ROUND_UP(wm_intermediate_val, 1000); return ret; } static uint32_t skl_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal, - uint32_t horiz_pixels, uint8_t bytes_per_pixel, + uint32_t horiz_pixels, uint8_t cpp, uint64_t tiling, uint32_t latency) { uint32_t ret; @@ -3071,7 +3069,7 @@ static uint32_t skl_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal, if (latency == 0) return UINT_MAX; - plane_bytes_per_line = horiz_pixels * bytes_per_pixel; + plane_bytes_per_line = horiz_pixels * cpp; if (tiling == I915_FORMAT_MOD_Y_TILED || tiling == I915_FORMAT_MOD_Yf_TILED) { @@ -3121,23 +3119,21 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint32_t plane_bytes_per_line, plane_blocks_per_line; uint32_t res_blocks, res_lines; uint32_t selected_result; - uint8_t bytes_per_pixel; + uint8_t cpp; if (latency == 0 || !cstate->base.active || !fb) return false; - bytes_per_pixel = drm_format_plane_cpp(fb->pixel_format, 0); + cpp = drm_format_plane_cpp(fb->pixel_format, 0); method1 = skl_wm_method1(skl_pipe_pixel_rate(cstate), - bytes_per_pixel, - latency); + cpp, latency); method2 = skl_wm_method2(skl_pipe_pixel_rate(cstate), cstate->base.adjusted_mode.crtc_htotal, cstate->pipe_src_w, - bytes_per_pixel, - fb->modifier[0], + cpp, fb->modifier[0], latency); - plane_bytes_per_line = cstate->pipe_src_w * bytes_per_pixel; + plane_bytes_per_line = cstate->pipe_src_w * cpp; plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || @@ -3145,11 +3141,11 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint32_t min_scanlines = 4; uint32_t y_tile_minimum; if (intel_rotation_90_or_270(plane->state->rotation)) { - int bpp = (fb->pixel_format == DRM_FORMAT_NV12) ? + int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ? drm_format_plane_cpp(fb->pixel_format, 1) : drm_format_plane_cpp(fb->pixel_format, 0); - switch (bpp) { + switch (cpp) { case 1: min_scanlines = 16; break; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index f1ee7db0811a..a2582c455b36 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -351,7 +351,7 @@ vlv_update_plane(struct drm_plane *dplane, int plane = intel_plane->plane; u32 sprctl; u32 sprsurf_offset, linear_offset; - int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); + int cpp = drm_format_plane_cpp(fb->pixel_format, 0); const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; int crtc_x = plane_state->dst.x1; int crtc_y = plane_state->dst.y1; @@ -422,10 +422,9 @@ vlv_update_plane(struct drm_plane *dplane, crtc_w--; crtc_h--; - linear_offset = y * fb->pitches[0] + x * pixel_size; + linear_offset = y * fb->pitches[0] + x * cpp; sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y, - fb->modifier[0], - pixel_size, + fb->modifier[0], cpp, fb->pitches[0]); linear_offset -= sprsurf_offset; @@ -434,7 +433,7 @@ vlv_update_plane(struct drm_plane *dplane, x += src_w; y += src_h; - linear_offset += src_h * fb->pitches[0] + src_w * pixel_size; + linear_offset += src_h * fb->pitches[0] + src_w * cpp; } if (key->flags) { @@ -494,7 +493,7 @@ ivb_update_plane(struct drm_plane *plane, enum pipe pipe = intel_plane->pipe; u32 sprctl, sprscale = 0; u32 sprsurf_offset, linear_offset; - int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); + int cpp = drm_format_plane_cpp(fb->pixel_format, 0); const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; int crtc_x = plane_state->dst.x1; int crtc_y = plane_state->dst.y1; @@ -556,10 +555,9 @@ ivb_update_plane(struct drm_plane *plane, if (crtc_w != src_w || crtc_h != src_h) sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; - linear_offset = y * fb->pitches[0] + x * pixel_size; + linear_offset = y * fb->pitches[0] + x * cpp; sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y, - fb->modifier[0], - pixel_size, + fb->modifier[0], cpp, fb->pitches[0]); linear_offset -= sprsurf_offset; @@ -570,8 +568,7 @@ ivb_update_plane(struct drm_plane *plane, if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) { x += src_w; y += src_h; - linear_offset += src_h * fb->pitches[0] + - src_w * pixel_size; + linear_offset += src_h * fb->pitches[0] + src_w * cpp; } } @@ -637,7 +634,7 @@ ilk_update_plane(struct drm_plane *plane, int pipe = intel_plane->pipe; u32 dvscntr, dvsscale; u32 dvssurf_offset, linear_offset; - int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); + int cpp = drm_format_plane_cpp(fb->pixel_format, 0); const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; int crtc_x = plane_state->dst.x1; int crtc_y = plane_state->dst.y1; @@ -695,10 +692,9 @@ ilk_update_plane(struct drm_plane *plane, if (crtc_w != src_w || crtc_h != src_h) dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; - linear_offset = y * fb->pitches[0] + x * pixel_size; + linear_offset = y * fb->pitches[0] + x * cpp; dvssurf_offset = intel_compute_tile_offset(dev_priv, &x, &y, - fb->modifier[0], - pixel_size, + fb->modifier[0], cpp, fb->pitches[0]); linear_offset -= dvssurf_offset; @@ -707,7 +703,7 @@ ilk_update_plane(struct drm_plane *plane, x += src_w; y += src_h; - linear_offset += src_h * fb->pitches[0] + src_w * pixel_size; + linear_offset += src_h * fb->pitches[0] + src_w * cpp; } if (key->flags) { @@ -772,7 +768,6 @@ intel_check_sprite_plane(struct drm_plane *plane, int hscale, vscale; int max_scale, min_scale; bool can_scale; - int pixel_size; if (!fb) { state->visible = false; @@ -894,6 +889,7 @@ intel_check_sprite_plane(struct drm_plane *plane, /* Check size restrictions when scaling */ if (state->visible && (src_w != crtc_w || src_h != crtc_h)) { unsigned int width_bytes; + int cpp = drm_format_plane_cpp(fb->pixel_format, 0); WARN_ON(!can_scale); @@ -905,9 +901,7 @@ intel_check_sprite_plane(struct drm_plane *plane, if (src_w < 3 || src_h < 3) state->visible = false; - pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); - width_bytes = ((src_x * pixel_size) & 63) + - src_w * pixel_size; + width_bytes = ((src_x * cpp) & 63) + src_w * cpp; if (INTEL_INFO(dev)->gen < 9 && (src_w > 2048 || src_h > 2048 || width_bytes > 4096 || fb->pitches[0] > 4096)) { -- cgit v1.2.3 From b16bb01fd2d599ba5cbc031b2c5318eba29efbc7 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 20 Jan 2016 21:05:28 +0200 Subject: drm/i915: Fix intel_tile_width() parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fb_modifiers and cpp arguments passed to intel_tile_width() in intel_fill_fb_ggtt_view() got accidentally swapped around. I'm pretty sure I fixed this already, but could be I lost the fix accidentally during some rebases or something. Anyway, fix it up for real. Fixes: d9b3288ecf2f ("drm/i915: change intel_fill_fb_ggtt_view() to use the real tile size") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1453316739-13296-8-git-send-email-ville.syrjala@linux.intel.com Testcase: igt/kms_rotation_crc/primary-rotation-90 Reviewed-by: Daniel Vetter Cc: drm-intel-fixes@lists.freedesktop.org --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 23cce7df74b0..304fc9637026 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2306,7 +2306,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, tile_size = intel_tile_size(dev_priv); cpp = drm_format_plane_cpp(fb->pixel_format, 0); - tile_width = intel_tile_width(dev_priv, cpp, fb->modifier[0]); + tile_width = intel_tile_width(dev_priv, fb->modifier[0], cpp); tile_height = tile_size / tile_width; info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width); -- cgit v1.2.3 From 33d7136336a94feade73b08b9c4bd1420df4e572 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:45:08 -0800 Subject: n_tty: Always wake up read()/poll() if new input A read() in non-canonical mode when VMIN > 0 and VTIME == 0 does not complete until at least VMIN chars have been read (or the user buffer is full). In this infrequent read mode, n_tty_read() attempts to reduce wakeups by computing the amount of data still necessary to complete the read (minimum_to_wake) and only waking the read()/poll() when that much unread data has been processed. This is the only read mode for which new data does not necessarily generate a wakeup. However, this optimization is broken and commonly leads to hung reads even though the necessary amount of data has been received. Since the optimization is of marginal value anyway, just remove the whole thing. This also remedies a race between a concurrent poll() and read() in this mode, where the poll() can reset the minimum_to_wake of the read() (and vice versa). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 827206914b02..d04f398d5de3 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -113,8 +113,6 @@ struct n_tty_data { DECLARE_BITMAP(read_flags, N_TTY_BUF_SIZE); unsigned char echo_buf[N_TTY_BUF_SIZE]; - int minimum_to_wake; - /* consumer-published */ size_t read_tail; size_t line_start; @@ -1633,7 +1631,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, /* publish read_head to consumer */ smp_store_release(&ldata->commit_head, ldata->read_head); - if ((read_cnt(ldata) >= ldata->minimum_to_wake) || L_EXTPROC(tty)) { + if (read_cnt(ldata)) { kill_fasync(&tty->fasync, SIGIO, POLL_IN); wake_up_interruptible_poll(&tty->read_wait, POLLIN); } @@ -1900,7 +1898,6 @@ static int n_tty_open(struct tty_struct *tty) reset_buffer_flags(tty->disc_data); ldata->column = 0; ldata->canon_column = 0; - ldata->minimum_to_wake = 1; ldata->num_overrun = 0; ldata->no_room = 0; ldata->lnext = 0; @@ -2163,14 +2160,9 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, minimum = MIN_CHAR(tty); if (minimum) { time = (HZ / 10) * TIME_CHAR(tty); - if (time) - ldata->minimum_to_wake = 1; - else if (!waitqueue_active(&tty->read_wait) || - (ldata->minimum_to_wake > minimum)) - ldata->minimum_to_wake = minimum; } else { timeout = (HZ / 10) * TIME_CHAR(tty); - ldata->minimum_to_wake = minimum = 1; + minimum = 1; } } @@ -2197,10 +2189,6 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, break; } - if (((minimum - (b - buf)) < ldata->minimum_to_wake) && - ((minimum - (b - buf)) >= 1)) - ldata->minimum_to_wake = (minimum - (b - buf)); - done = check_other_done(tty); if (!input_available_p(tty, 0)) { @@ -2266,9 +2254,6 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, up_read(&tty->termios_rwsem); remove_wait_queue(&tty->read_wait, &wait); - if (!waitqueue_active(&tty->read_wait)) - ldata->minimum_to_wake = minimum; - mutex_unlock(&ldata->atomic_read_lock); if (b - buf) @@ -2403,7 +2388,6 @@ break_out: static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, poll_table *wait) { - struct n_tty_data *ldata = tty->disc_data; unsigned int mask = 0; poll_wait(file, &tty->read_wait, wait); @@ -2416,12 +2400,6 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, mask |= POLLPRI | POLLIN | POLLRDNORM; if (tty_hung_up_p(file)) mask |= POLLHUP; - if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) { - if (MIN_CHAR(tty) && !TIME_CHAR(tty)) - ldata->minimum_to_wake = MIN_CHAR(tty); - else - ldata->minimum_to_wake = 1; - } if (tty->ops->write && !tty_is_writelocked(tty) && tty_chars_in_buffer(tty) < WAKEUP_CHARS && tty_write_room(tty) > 0) @@ -2472,14 +2450,6 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file, static void n_tty_fasync(struct tty_struct *tty, int on) { - struct n_tty_data *ldata = tty->disc_data; - - if (!waitqueue_active(&tty->read_wait)) { - if (on) - ldata->minimum_to_wake = 1; - else if (!tty->fasync) - ldata->minimum_to_wake = N_TTY_BUF_SIZE; - } } static struct tty_ldisc_ops n_tty_ops = { -- cgit v1.2.3 From bee6741ca022f051ea1b46e16fb2ff0097643181 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:45:09 -0800 Subject: tty, n_tty: Remove fasync() ldisc notification Only the N_TTY line discipline implements the signal-driven i/o notification enabled/disabled by fcntl(F_SETFL, O_ASYNC). The ldisc fasync() notification is sent to the ldisc when the enable state has changed (the tty core is notified via the fasync() VFS file operation). The N_TTY line discipline used the enable state to change the wakeup condition (minimum_to_wake = 1) for notifying the signal handler i/o is available. However, just the presence of data is sufficient and necessary to signal i/o is available, so changing minimum_to_wake is unnecessary (and creates a race condition with read() and poll() which may be concurrently updating minimum_to_wake). Furthermore, since the kill_fasync() VFS helper performs no action if the fasync list is empty, calling unconditionally is preferred; if signal driven i/o just has been disabled, no signal will be sent by kill_fasync() anyway so notification of the change via the ldisc fasync() method is superfluous. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 5 ----- drivers/tty/tty_io.c | 8 -------- include/linux/tty_ldisc.h | 6 ------ 3 files changed, 19 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index d04f398d5de3..a93e4c7e82ae 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2448,10 +2448,6 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file, } } -static void n_tty_fasync(struct tty_struct *tty, int on) -{ -} - static struct tty_ldisc_ops n_tty_ops = { .magic = TTY_LDISC_MAGIC, .name = "n_tty", @@ -2465,7 +2461,6 @@ static struct tty_ldisc_ops n_tty_ops = { .poll = n_tty_poll, .receive_buf = n_tty_receive_buf, .write_wakeup = n_tty_write_wakeup, - .fasync = n_tty_fasync, .receive_buf2 = n_tty_receive_buf2, }; diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index c5b4274584dc..7533ab1abe72 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2219,7 +2219,6 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) static int __tty_fasync(int fd, struct file *filp, int on) { struct tty_struct *tty = file_tty(filp); - struct tty_ldisc *ldisc; unsigned long flags; int retval = 0; @@ -2230,13 +2229,6 @@ static int __tty_fasync(int fd, struct file *filp, int on) if (retval <= 0) goto out; - ldisc = tty_ldisc_ref(tty); - if (ldisc) { - if (ldisc->ops->fasync) - ldisc->ops->fasync(tty, on); - tty_ldisc_deref(ldisc); - } - if (on) { enum pid_type type; struct pid *pid; diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index 6101ab8dc148..3971cf0eb467 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -98,11 +98,6 @@ * seek to perform this action quickly but should wait until * any pending driver I/O is completed. * - * void (*fasync)(struct tty_struct *, int on) - * - * Notify line discipline when signal-driven I/O is enabled or - * disabled. - * * void (*dcd_change)(struct tty_struct *tty, unsigned int status) * * Tells the discipline that the DCD pin has changed its status. @@ -202,7 +197,6 @@ struct tty_ldisc_ops { char *fp, int count); void (*write_wakeup)(struct tty_struct *); void (*dcd_change)(struct tty_struct *, unsigned int); - void (*fasync)(struct tty_struct *tty, int on); int (*receive_buf2)(struct tty_struct *, const unsigned char *cp, char *fp, int count); -- cgit v1.2.3 From f557474ca3a23800dffb790846bcb121fa046c71 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:45:10 -0800 Subject: tty: Add fasync() hung up file operation VFS uses a two-stage check-and-call method for invoking file_operations methods, without explicitly snapshotting either the file_operations ptr or the function ptr. Since the tty core is one of the few VFS users that changes the f_op file_operations ptr of the file descriptor (when the tty has been hung up), and since the likelihood of the compiler generating a reload of either f_op or the function ptr is basically nil, just define a hung up fasync() file operation that returns an error. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 7533ab1abe72..0140c8669ada 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -468,6 +468,11 @@ static long hung_up_tty_compat_ioctl(struct file *file, return cmd == TIOCSPGRP ? -ENOTTY : -EIO; } +static int hung_up_tty_fasync(int fd, struct file *file, int on) +{ + return -ENOTTY; +} + static const struct file_operations tty_fops = { .llseek = no_llseek, .read = tty_read, @@ -500,6 +505,7 @@ static const struct file_operations hung_up_tty_fops = { .unlocked_ioctl = hung_up_tty_ioctl, .compat_ioctl = hung_up_tty_compat_ioctl, .release = tty_release, + .fasync = hung_up_tty_fasync, }; static DEFINE_SPINLOCK(redirect_lock); -- cgit v1.2.3 From a8f3a29718f77df3116955d100756f67fafabec0 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:45:11 -0800 Subject: tty: Fix ioctl(FIOASYNC) on hungup file A small race window exists which allows signal-driven async i/o to be enabled for the tty when the file ptr has already been hungup and signal-driven i/o has been disabled: CPU 0 CPU 1 ----- ------ ioctl_fioasync(on) filp->f_op->fasync(on) __tty_hangup() tty_fasync(on) tty_lock() tty_lock() ... . filp->f_op = &hung_up_tty_fops; (waiting) __tty_fasync(off) . tty_unlock() /* gets tty lock */ /* enables FASYNC */ Check the tty has not been hungup while holding tty_lock. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 0140c8669ada..8d26ed79bb4c 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2260,10 +2260,11 @@ out: static int tty_fasync(int fd, struct file *filp, int on) { struct tty_struct *tty = file_tty(filp); - int retval; + int retval = -ENOTTY; tty_lock(tty); - retval = __tty_fasync(fd, filp, on); + if (!tty_hung_up_p(filp)) + retval = __tty_fasync(fd, filp, on); tty_unlock(tty); return retval; -- cgit v1.2.3 From 7bccc36544a8b4a7d768f8ccdd6001a52872aca9 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:45:12 -0800 Subject: n_tty: Fix stuck write wakeup If signal-driven i/o is disabled while write wakeup is pending (ie., n_tty_write() has set TTY_DO_WRITE_WAKEUP but then signal-driven i/o is disabled), the TTY_DO_WRITE_WAKEUP bit will never be cleared and will cause tty_wakeup() to always call n_tty_write_wakeup. Unconditionally clear the write wakeup, and since kill_fasync() already checks if the fasync ptr is null, call kill_fasync() unconditionally as well. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index a93e4c7e82ae..086fd9983caa 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -228,8 +228,8 @@ static ssize_t chars_in_buffer(struct tty_struct *tty) static void n_tty_write_wakeup(struct tty_struct *tty) { - if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) - kill_fasync(&tty->fasync, SIGIO, POLL_OUT); + clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + kill_fasync(&tty->fasync, SIGIO, POLL_OUT); } static void n_tty_check_throttle(struct tty_struct *tty) -- cgit v1.2.3 From ffb91a459c6cacb10972f5dff893fb1292bac85d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:45:13 -0800 Subject: n_tty: Remove tty count checks from unthrottle Since n_tty_check_unthrottle() is only called from n_tty_read() which only originates from a userspace read(), the tty count cannot be 0; the read() guarantees the file descriptor has not yet been released. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 086fd9983caa..5ae661cd236e 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -261,8 +261,6 @@ static void n_tty_check_unthrottle(struct tty_struct *tty) if (tty->driver->type == TTY_DRIVER_TYPE_PTY) { if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE) return; - if (!tty->count) - return; n_tty_kick_worker(tty); tty_wakeup(tty->link); return; @@ -281,8 +279,6 @@ static void n_tty_check_unthrottle(struct tty_struct *tty) tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE); if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE) break; - if (!tty->count) - break; n_tty_kick_worker(tty); unthrottled = tty_unthrottle_safe(tty); if (!unthrottled) -- cgit v1.2.3 From 87108bc9870ae86ca4fcc05115a134af7a0f4e96 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:45:14 -0800 Subject: tty: n_tty: fix SIGIO for output According to fcntl(2), "a SIGIO signal is sent whenever input or output becomes possible on that file descriptor", i.e. after the output buffer was full and now has space for new data. But in fact SIGIO is sent after every write. n_tty_write() should set TTY_DO_WRITE_WAKEUP only when not all data could be written to the buffer. [pjh: Also fixes missed SIGIO if amt written just happens to be [ amount still to write Signed-off-by: Johannes Stezenbach [pjh: minor patch edits and re-submit] Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 5ae661cd236e..fad365aa1f5c 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2361,7 +2361,7 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, } break_out: remove_wait_queue(&tty->write_wait, &wait); - if (b - buf != nr && tty->fasync) + if (nr && tty->fasync) set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); up_read(&tty->termios_rwsem); return (b - buf) ? b - buf : retval; -- cgit v1.2.3 From 3f6b3ce071d3a3632c82b53077d21f5beab3a4aa Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:39:31 -0800 Subject: serial: 8250: Refactor serial8250_rx_chars() inner loop Factor the read/process one char inner loop to a separate helper function serial8250_read_char(). No functional change. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 120 +++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 8d262bce97e4..7580d713cde5 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1412,6 +1412,67 @@ static void serial8250_enable_ms(struct uart_port *port) serial8250_rpm_put(up); } +static void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr) +{ + struct uart_port *port = &up->port; + unsigned char ch; + char flag = TTY_NORMAL; + + if (likely(lsr & UART_LSR_DR)) + ch = serial_in(up, UART_RX); + else + /* + * Intel 82571 has a Serial Over Lan device that will + * set UART_LSR_BI without setting UART_LSR_DR when + * it receives a break. To avoid reading from the + * receive buffer without UART_LSR_DR bit set, we + * just force the read character to be 0 + */ + ch = 0; + + port->icount.rx++; + + lsr |= up->lsr_saved_flags; + up->lsr_saved_flags = 0; + + if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { + if (lsr & UART_LSR_BI) { + lsr &= ~(UART_LSR_FE | UART_LSR_PE); + port->icount.brk++; + /* + * We do the SysRQ and SAK checking + * here because otherwise the break + * may get masked by ignore_status_mask + * or read_status_mask. + */ + if (uart_handle_break(port)) + return; + } else if (lsr & UART_LSR_PE) + port->icount.parity++; + else if (lsr & UART_LSR_FE) + port->icount.frame++; + if (lsr & UART_LSR_OE) + port->icount.overrun++; + + /* + * Mask off conditions which should be ignored. + */ + lsr &= port->read_status_mask; + + if (lsr & UART_LSR_BI) { + DEBUG_INTR("handling break...."); + flag = TTY_BREAK; + } else if (lsr & UART_LSR_PE) + flag = TTY_PARITY; + else if (lsr & UART_LSR_FE) + flag = TTY_FRAME; + } + if (uart_handle_sysrq_char(port, ch)) + return; + + uart_insert_char(port, lsr, UART_LSR_OE, ch, flag); +} + /* * serial8250_rx_chars: processes according to the passed in LSR * value, and returns the remaining LSR bits not handled @@ -1421,67 +1482,10 @@ unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) { struct uart_port *port = &up->port; - unsigned char ch; int max_count = 256; - char flag; do { - if (likely(lsr & UART_LSR_DR)) - ch = serial_in(up, UART_RX); - else - /* - * Intel 82571 has a Serial Over Lan device that will - * set UART_LSR_BI without setting UART_LSR_DR when - * it receives a break. To avoid reading from the - * receive buffer without UART_LSR_DR bit set, we - * just force the read character to be 0 - */ - ch = 0; - - flag = TTY_NORMAL; - port->icount.rx++; - - lsr |= up->lsr_saved_flags; - up->lsr_saved_flags = 0; - - if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { - if (lsr & UART_LSR_BI) { - lsr &= ~(UART_LSR_FE | UART_LSR_PE); - port->icount.brk++; - /* - * We do the SysRQ and SAK checking - * here because otherwise the break - * may get masked by ignore_status_mask - * or read_status_mask. - */ - if (uart_handle_break(port)) - goto ignore_char; - } else if (lsr & UART_LSR_PE) - port->icount.parity++; - else if (lsr & UART_LSR_FE) - port->icount.frame++; - if (lsr & UART_LSR_OE) - port->icount.overrun++; - - /* - * Mask off conditions which should be ignored. - */ - lsr &= port->read_status_mask; - - if (lsr & UART_LSR_BI) { - DEBUG_INTR("handling break...."); - flag = TTY_BREAK; - } else if (lsr & UART_LSR_PE) - flag = TTY_PARITY; - else if (lsr & UART_LSR_FE) - flag = TTY_FRAME; - } - if (uart_handle_sysrq_char(port, ch)) - goto ignore_char; - - uart_insert_char(port, lsr, UART_LSR_OE, ch, flag); - -ignore_char: + serial8250_read_char(up, lsr); lsr = serial_in(up, UART_LSR); } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (--max_count > 0)); spin_unlock(&port->lock); -- cgit v1.2.3 From d22f8f10683c8c0f2675d9fd411a06facaf07c1b Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:39:32 -0800 Subject: serial: 8250: Fix lost rx state When max_count is reached, the rx loop exits. However, UART_LSR has already been read so those char flags are lost, and subsequent rx status will be for the wrong byte until the rx fifo drains. Reported-by: George Spelvin Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 7580d713cde5..48680565c991 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1478,16 +1478,17 @@ static void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr) * value, and returns the remaining LSR bits not handled * by this Rx routine. */ -unsigned char -serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) +unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) { struct uart_port *port = &up->port; int max_count = 256; do { serial8250_read_char(up, lsr); + if (--max_count == 0) + break; lsr = serial_in(up, UART_LSR); - } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (--max_count > 0)); + } while (lsr & (UART_LSR_DR | UART_LSR_BI)); spin_unlock(&port->lock); tty_flip_buffer_push(&port->state->port); spin_lock(&port->lock); -- cgit v1.2.3 From 6a597a38cbaf067019db96645f36e0b1f01f306a Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:39:33 -0800 Subject: serial: 8250: Remove low_latency workaround The defunct low_latency input steering executed flush_to_ldisc() directly from interrupt context so dropping the port lock was necessary to avoid deadlock. That steering was removed by commit a9c3f68f3cd8d55f809fbdb0c138ed061ea1bd25 Author: Peter Hurley Date: Sat Feb 22 07:31:21 2014 -0500 tty: Fix low_latency BUG Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 48680565c991..9ef77a52c4f2 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1489,9 +1489,8 @@ unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) break; lsr = serial_in(up, UART_LSR); } while (lsr & (UART_LSR_DR | UART_LSR_BI)); - spin_unlock(&port->lock); + tty_flip_buffer_push(&port->state->port); - spin_lock(&port->lock); return lsr; } EXPORT_SYMBOL_GPL(serial8250_rx_chars); -- cgit v1.2.3 From d70a7b1626d64c8c57fb9258a81f427198b60700 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:39:34 -0800 Subject: serial: 8250: Unlink uart console ptr if console setup fails If console setup fails (eg., there is no valid port at that index), unlink the console ptr; otherwise, when the driver unloads, the console will be unregistered (even though setup, and thus registration, failed) and a console disabled message will be printed. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index c9720a97a977..8031e428894f 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -597,6 +597,7 @@ static void univ8250_console_write(struct console *co, const char *s, static int univ8250_console_setup(struct console *co, char *options) { struct uart_port *port; + int retval; /* * Check whether an invalid uart number has been specified, and @@ -609,7 +610,10 @@ static int univ8250_console_setup(struct console *co, char *options) /* link port to console */ port->cons = co; - return serial8250_console_setup(port, options, false); + retval = serial8250_console_setup(port, options, false); + if (retval != 0) + port->cons = NULL; + return retval; } /** -- cgit v1.2.3 From 611e0d83a83724340d4bf0eed610af01401b2ff4 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:39:35 -0800 Subject: serial: 8250: Wait for irq to complete before shutdown After masking all interrupts, wait for the irq handler to complete before continuing shutdown. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 9ef77a52c4f2..57b3a80b4359 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2088,8 +2088,12 @@ void serial8250_do_shutdown(struct uart_port *port) /* * Disable interrupts from this port */ + spin_lock_irqsave(&port->lock, flags); up->ier = 0; serial_port_out(port, UART_IER, 0); + spin_unlock_irqrestore(&port->lock, flags); + + synchronize_irq(port->irq); if (up->dma) serial8250_release_dma(up); -- cgit v1.2.3 From cee10c8cd3fde3da428ffafd4eb8847892a34d52 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:39:36 -0800 Subject: serial: 8250: Unfold < 80 char lines Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 57b3a80b4359..0bd3c6baa300 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1523,11 +1523,9 @@ void serial8250_tx_chars(struct uart_8250_port *up) port->icount.tx++; if (uart_circ_empty(xmit)) break; - if (up->capabilities & UART_CAP_HFIFO) { - if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) != - BOTH_EMPTY) - break; - } + if ((up->capabilities & UART_CAP_HFIFO) && + (serial_in(up, UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY) + break; } while (--count > 0); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) @@ -2753,8 +2751,7 @@ serial8250_verify_port(struct uart_port *port, struct serial_struct *ser) return 0; } -static const char * -serial8250_type(struct uart_port *port) +static const char *serial8250_type(struct uart_port *port) { int type = port->type; -- cgit v1.2.3 From c9c10d912a91735a966d81114b28c4cff81dda59 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:36:08 -0800 Subject: tty: rocket: Remove private close_wait This driver's private completion variable, close_wait, is no longer used for wait since "tty: Remove ASYNC_CLOSING checks in open()/hangup"; remove. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/rocket.c | 2 -- drivers/tty/rocket_int.h | 1 - 2 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index f624b93a237f..9dd02daf45ca 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -643,7 +643,6 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) info->chan = chan; tty_port_init(&info->port); info->port.ops = &rocket_port_ops; - init_completion(&info->close_wait); info->flags &= ~ROCKET_MODE_MASK; switch (pc104[board][line]) { case 422: @@ -1049,7 +1048,6 @@ static void rp_close(struct tty_struct *tty, struct file *filp) mutex_unlock(&port->mutex); tty_port_tty_set(port, NULL); - complete_all(&info->close_wait); atomic_dec(&rp_num_ports_open); #ifdef ROCKET_DEBUG_OPEN diff --git a/drivers/tty/rocket_int.h b/drivers/tty/rocket_int.h index 67e0f1e778a2..ef1e1be6b26d 100644 --- a/drivers/tty/rocket_int.h +++ b/drivers/tty/rocket_int.h @@ -1144,7 +1144,6 @@ struct r_port { int read_status_mask; int cps; - struct completion close_wait; /* Not yet matching the core */ spinlock_t slock; struct mutex write_mtx; }; -- cgit v1.2.3 From 7f71b2c1441877141651d96c9a380bfb32e2ff78 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:36:09 -0800 Subject: n_tty: Ignore all read data when closing On final port close (and thus final tty close), only output flow control requests in the input data should be processed. Ignore all other input data, including parity errors, overruns and breaks. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index fad365aa1f5c..fb76a7d80e7e 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1524,8 +1524,6 @@ n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp, flag = *fp++; if (likely(flag == TTY_NORMAL)) n_tty_receive_char_closing(tty, *cp++); - else - n_tty_receive_char_flagged(tty, *cp++, flag); } } -- cgit v1.2.3 From 2d73b069f816742ba607f65f9dbbff2885365951 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:36:11 -0800 Subject: staging: dgap: Remove redundant write_wait wakeups Waking the write_wait queue is exactly what tty_wakeup() does; remove the open-coded wakeups. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgap/dgap.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index dfbae215aec3..5413ed8c29ff 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -3155,8 +3155,6 @@ static void dgap_tty_flush_buffer(struct tty_struct *tty) spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - if (waitqueue_active(&tty->write_wait)) - wake_up_interruptible(&tty->write_wait); tty_wakeup(tty); } @@ -4953,10 +4951,6 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, ch->ch_pun.un_flags &= ~(UN_LOW | UN_EMPTY); wake_up_interruptible(&ch->ch_pun.un_flags_wait); } - if (waitqueue_active(&tty->write_wait)) - wake_up_interruptible(&tty->write_wait); - - /* Can't hold any locks when calling tty_wakeup! */ spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); tty_wakeup(tty); -- cgit v1.2.3 From 8d082cd300ab422b7ee9f4629a1c470e4f0d90d5 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:36:13 -0800 Subject: tty: Unify receive_buf() code paths Instead of two distinct code branches for receive_buf() handling, use tty_ldisc_receive_buf() as the single code path. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 39 ++++++++++++++++++++++++++++----------- include/linux/tty.h | 16 ++-------------- 2 files changed, 30 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 3cd31e0d4bd9..a946e49a2626 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -435,25 +435,42 @@ int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, } EXPORT_SYMBOL_GPL(tty_prepare_flip_string); +/** + * tty_ldisc_receive_buf - forward data to line discipline + * @ld: line discipline to process input + * @p: char buffer + * @f: TTY_* flags buffer + * @count: number of bytes to process + * + * Callers other than flush_to_ldisc() need to exclude the kworker + * from concurrent use of the line discipline, see paste_selection(). + * + * Returns the number of bytes not processed + */ +int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p, + char *f, int count) +{ + if (ld->ops->receive_buf2) + count = ld->ops->receive_buf2(ld->tty, p, f, count); + else { + count = min_t(int, count, ld->tty->receive_room); + if (count && ld->ops->receive_buf) + ld->ops->receive_buf(ld->tty, p, f, count); + } + return count; +} +EXPORT_SYMBOL_GPL(tty_ldisc_receive_buf); static int -receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count) +receive_buf(struct tty_ldisc *ld, struct tty_buffer *head, int count) { - struct tty_ldisc *disc = tty->ldisc; unsigned char *p = char_buf_ptr(head, head->read); char *f = NULL; if (~head->flags & TTYB_NORMAL) f = flag_buf_ptr(head, head->read); - if (disc->ops->receive_buf2) - count = disc->ops->receive_buf2(tty, p, f, count); - else { - count = min_t(int, count, tty->receive_room); - if (count && disc->ops->receive_buf) - disc->ops->receive_buf(tty, p, f, count); - } - return count; + return tty_ldisc_receive_buf(ld, p, f, count); } /** @@ -514,7 +531,7 @@ static void flush_to_ldisc(struct work_struct *work) continue; } - count = receive_buf(tty, head, count); + count = receive_buf(disc, head, count); if (!count) break; head->read += count; diff --git a/include/linux/tty.h b/include/linux/tty.h index 03e4015fa033..3b09f235db66 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -571,20 +571,8 @@ extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty); extern void tty_ldisc_release(struct tty_struct *tty); extern void tty_ldisc_init(struct tty_struct *tty); extern void tty_ldisc_deinit(struct tty_struct *tty); - -static inline int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p, - char *f, int count) -{ - if (ld->ops->receive_buf2) - count = ld->ops->receive_buf2(ld->tty, p, f, count); - else { - count = min_t(int, count, ld->tty->receive_room); - if (count && ld->ops->receive_buf) - ld->ops->receive_buf(ld->tty, p, f, count); - } - return count; -} - +extern int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p, + char *f, int count); /* n_tty.c */ extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops); -- cgit v1.2.3 From 5823323ea5ed41ea08ef0a36013369d0c65a23de Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:36:14 -0800 Subject: tty: Allow unreadable mess to be > 80 chars Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_port.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 846ed481c24f..a76aec2ca480 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -510,10 +510,8 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty) if (port->blocked_open) { spin_unlock_irqrestore(&port->lock, flags); - if (port->close_delay) { - msleep_interruptible( - jiffies_to_msecs(port->close_delay)); - } + if (port->close_delay) + msleep_interruptible(jiffies_to_msecs(port->close_delay)); spin_lock_irqsave(&port->lock, flags); wake_up_interruptible(&port->open_wait); } -- cgit v1.2.3 From 9db276f8f02145068d8c04614bc28c2a4532a8c7 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:36:15 -0800 Subject: tty: Use termios c_*flag macros Expressions of the form "tty->termios.c_*flag & FLAG" are more clearly expressed with the termios flags macros, I_FLAG(), C_FLAG(), O_FLAG(), and L_FLAG(). Convert treewide. Signed-off-by: Peter Hurley Acked-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/char/pcmcia/synclink_cs.c | 21 ++++++++------------- drivers/mmc/card/sdio_uart.c | 14 +++++++------- drivers/staging/dgap/dgap.c | 2 +- drivers/staging/dgnc/dgnc_tty.c | 2 +- drivers/tty/amiserial.c | 22 ++++++++-------------- drivers/tty/cyclades.c | 14 ++++++-------- drivers/tty/isicom.c | 3 +-- drivers/tty/mxser.c | 10 ++++------ drivers/tty/n_gsm.c | 6 +++--- drivers/tty/pty.c | 3 +-- drivers/tty/rocket.c | 8 ++++---- drivers/tty/serial/68328serial.c | 4 +--- drivers/tty/serial/crisv10.c | 18 +++++++----------- drivers/tty/serial/jsm/jsm_tty.c | 3 +-- drivers/tty/serial/serial_core.c | 20 +++++++++----------- drivers/tty/synclink.c | 23 +++++++++-------------- drivers/tty/synclink_gt.c | 19 +++++++------------ drivers/tty/synclinkmp.c | 19 +++++++------------ drivers/tty/tty_ioctl.c | 12 ++++++------ drivers/tty/tty_port.c | 2 +- drivers/usb/serial/cypress_m8.c | 3 +-- drivers/usb/serial/digi_acceleport.c | 8 ++++---- drivers/usb/serial/io_edgeport.c | 4 ++-- drivers/usb/serial/mct_u232.c | 2 +- drivers/usb/serial/mos7720.c | 4 ++-- drivers/usb/serial/mos7840.c | 4 ++-- net/irda/ircomm/ircomm_tty.c | 11 +++++------ net/irda/ircomm/ircomm_tty_ioctl.c | 13 ++++--------- 28 files changed, 113 insertions(+), 161 deletions(-) (limited to 'drivers') diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 45df4bf914f8..22c27652e46a 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -1349,7 +1349,7 @@ static void shutdown(MGSLPC_INFO * info, struct tty_struct *tty) /* TODO:disable interrupts instead of reset to preserve signal states */ reset_device(info); - if (!tty || tty->termios.c_cflag & HUPCL) { + if (!tty || C_HUPCL(tty)) { info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); set_signals(info); } @@ -1390,7 +1390,7 @@ static void mgslpc_program_hw(MGSLPC_INFO *info, struct tty_struct *tty) port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI); get_signals(info); - if (info->netcount || (tty && (tty->termios.c_cflag & CREAD))) + if (info->netcount || (tty && C_CREAD(tty))) rx_start(info); spin_unlock_irqrestore(&info->lock, flags); @@ -1733,7 +1733,7 @@ static void mgslpc_throttle(struct tty_struct * tty) if (I_IXOFF(tty)) mgslpc_send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock, flags); info->serial_signals &= ~SerialSignal_RTS; set_signals(info); @@ -1762,7 +1762,7 @@ static void mgslpc_unthrottle(struct tty_struct * tty) mgslpc_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock, flags); info->serial_signals |= SerialSignal_RTS; set_signals(info); @@ -2306,8 +2306,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term mgslpc_change_params(info, tty); /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) { info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); spin_lock_irqsave(&info->lock, flags); set_signals(info); @@ -2315,21 +2314,17 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) { info->serial_signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) info->serial_signals |= SerialSignal_RTS; - } spin_lock_irqsave(&info->lock, flags); set_signals(info); spin_unlock_irqrestore(&info->lock, flags); } /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + if (old_termios->c_cflag & CRTSCTS && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; tx_release(tty); } diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index d2de5925b73e..5415056f9aa5 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c @@ -493,7 +493,7 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port) if (status & UART_MSR_DCTS) { port->icount.cts++; tty = tty_port_tty_get(&port->port); - if (tty && (tty->termios.c_cflag & CRTSCTS)) { + if (tty && C_CRTSCTS(tty)) { int cts = (status & UART_MSR_CTS); if (tty->hw_stopped) { if (cts) { @@ -648,10 +648,10 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) sdio_uart_change_speed(port, &tty->termios, NULL); - if (tty->termios.c_cflag & CBAUD) + if (C_BAUD(tty)) sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) tty->hw_stopped = 1; @@ -833,7 +833,7 @@ static void sdio_uart_throttle(struct tty_struct *tty) { struct sdio_uart_port *port = tty->driver_data; - if (!I_IXOFF(tty) && !(tty->termios.c_cflag & CRTSCTS)) + if (!I_IXOFF(tty) && !C_CRTSCTS(tty)) return; if (sdio_uart_claim_func(port) != 0) @@ -844,7 +844,7 @@ static void sdio_uart_throttle(struct tty_struct *tty) sdio_uart_start_tx(port); } - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) sdio_uart_clear_mctrl(port, TIOCM_RTS); sdio_uart_irq(port->func); @@ -855,7 +855,7 @@ static void sdio_uart_unthrottle(struct tty_struct *tty) { struct sdio_uart_port *port = tty->driver_data; - if (!I_IXOFF(tty) && !(tty->termios.c_cflag & CRTSCTS)) + if (!I_IXOFF(tty) && !C_CRTSCTS(tty)) return; if (sdio_uart_claim_func(port) != 0) @@ -870,7 +870,7 @@ static void sdio_uart_unthrottle(struct tty_struct *tty) } } - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) sdio_uart_set_mctrl(port, TIOCM_RTS); sdio_uart_irq(port->func); diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index 5413ed8c29ff..294c1c83aa4d 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -1530,7 +1530,7 @@ static void dgap_input(struct channel_t *ch) if ((bd->state != BOARD_READY) || !tp || (tp->magic != TTY_MAGIC) || !(ch->ch_tun.un_flags & UN_ISOPEN) || - !(tp->termios.c_cflag & CREAD) || + !C_CREAD(tp) || (ch->ch_tun.un_flags & UN_CLOSING)) { writew(head, &bs->rx_tail); writeb(1, &bs->idata); diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 4a3d2c6f7eac..8b1ba65a6984 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -541,7 +541,7 @@ void dgnc_input(struct channel_t *ch) */ if (!tp || (tp->magic != TTY_MAGIC) || !(ch->ch_tun.un_flags & UN_ISOPEN) || - !(tp->termios.c_cflag & CREAD) || + !C_CREAD(tp) || (ch->ch_tun.un_flags & UN_CLOSING)) { ch->ch_r_head = tail; diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 6ba5681b6385..eacf4c9f3b29 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -639,7 +639,7 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info) custom.adkcon = AC_UARTBRK; mb(); - if (tty->termios.c_cflag & HUPCL) + if (C_HUPCL(tty)) info->MCR &= ~(SER_DTR|SER_RTS); rtsdtr_ctrl(info->MCR); @@ -974,7 +974,7 @@ static void rs_throttle(struct tty_struct * tty) if (I_IXOFF(tty)) rs_send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) info->MCR &= ~SER_RTS; local_irq_save(flags); @@ -999,7 +999,7 @@ static void rs_unthrottle(struct tty_struct * tty) else rs_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) info->MCR |= SER_RTS; local_irq_save(flags); rtsdtr_ctrl(info->MCR); @@ -1332,8 +1332,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_speed(tty, info, old_termios); /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && - !(cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) { info->MCR &= ~(SER_DTR|SER_RTS); local_irq_save(flags); rtsdtr_ctrl(info->MCR); @@ -1341,21 +1340,17 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - (cflag & CBAUD)) { + if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { info->MCR |= SER_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) info->MCR |= SER_RTS; - } local_irq_save(flags); rtsdtr_ctrl(info->MCR); local_irq_restore(flags); } /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; rs_start(tty); } @@ -1367,8 +1362,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) * XXX It's not clear whether the current behavior is correct * or not. Hence, this may change..... */ - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios.c_cflag & CLOCAL)) + if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty)) wake_up_interruptible(&info->open_wait); #endif } diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index a48e7e66b970..d67e542bab1c 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -1440,7 +1440,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) info->port.xmit_buf = NULL; free_page((unsigned long)temp); } - if (tty->termios.c_cflag & HUPCL) + if (C_HUPCL(tty)) cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR); cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR); @@ -1469,7 +1469,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) free_page((unsigned long)temp); } - if (tty->termios.c_cflag & HUPCL) + if (C_HUPCL(tty)) tty_port_lower_dtr_rts(&info->port); set_bit(TTY_IO_ERROR, &tty->flags); @@ -2795,8 +2795,7 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) cy_set_line_char(info, tty); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; cy_start(tty); } @@ -2807,8 +2806,7 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) * XXX It's not clear whether the current behavior is correct * or not. Hence, this may change..... */ - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios.c_cflag & CLOCAL)) + if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty)) wake_up_interruptible(&info->port.open_wait); #endif } /* cy_set_termios */ @@ -2868,7 +2866,7 @@ static void cy_throttle(struct tty_struct *tty) info->throttle = 1; } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { if (!cy_is_Z(card)) { spin_lock_irqsave(&card->card_lock, flags); cyy_change_rts_dtr(info, 0, TIOCM_RTS); @@ -2905,7 +2903,7 @@ static void cy_unthrottle(struct tty_struct *tty) cy_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { card = info->card; if (!cy_is_Z(card)) { spin_lock_irqsave(&card->card_lock, flags); diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c index 99875949bfb7..8bf67630018b 100644 --- a/drivers/tty/isicom.c +++ b/drivers/tty/isicom.c @@ -1204,8 +1204,7 @@ static void isicom_set_termios(struct tty_struct *tty, isicom_config_port(tty); spin_unlock_irqrestore(&port->card->card_lock, flags); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; isicom_start(tty); } diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 4c4a23674569..e9600cece8da 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -1864,7 +1864,7 @@ static void mxser_stoprx(struct tty_struct *tty) } } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { info->MCR &= ~UART_MCR_RTS; outb(info->MCR, info->ioaddr + UART_MCR); } @@ -1901,7 +1901,7 @@ static void mxser_unthrottle(struct tty_struct *tty) } } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { info->MCR |= UART_MCR_RTS; outb(info->MCR, info->ioaddr + UART_MCR); } @@ -1949,15 +1949,13 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi mxser_change_speed(tty, old_termios); spin_unlock_irqrestore(&info->slock, flags); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; mxser_start(tty); } /* Handle sw stopped */ - if ((old_termios->c_iflag & IXON) && - !(tty->termios.c_iflag & IXON)) { + if ((old_termios->c_iflag & IXON) && !I_IXON(tty)) { tty->stopped = 0; if (info->board->chip_flag) { diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index e3cc27749344..c01620780f5b 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -1066,7 +1066,7 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci, /* Carrier drop -> hangup */ if (tty) { if ((mlines & TIOCM_CD) == 0 && (dlci->modem_rx & TIOCM_CD)) - if (!(tty->termios.c_cflag & CLOCAL)) + if (!C_CLOCAL(tty)) tty_hangup(tty); } if (brk & 0x01) @@ -3116,7 +3116,7 @@ static void gsmtty_throttle(struct tty_struct *tty) struct gsm_dlci *dlci = tty->driver_data; if (dlci->state == DLCI_CLOSED) return; - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) dlci->modem_tx &= ~TIOCM_DTR; dlci->throttled = 1; /* Send an MSC with DTR cleared */ @@ -3128,7 +3128,7 @@ static void gsmtty_unthrottle(struct tty_struct *tty) struct gsm_dlci *dlci = tty->driver_data; if (dlci->state == DLCI_CLOSED) return; - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) dlci->modem_tx |= TIOCM_DTR; dlci->throttled = 0; /* Send an MSC with DTR set */ diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index be5020d567ae..78170e7aa3a3 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -263,8 +263,7 @@ static void pty_set_termios(struct tty_struct *tty, { /* See if packet mode change of state. */ if (tty->link && tty->link->packet) { - int extproc = (old_termios->c_lflag & EXTPROC) | - (tty->termios.c_lflag & EXTPROC); + int extproc = (old_termios->c_lflag & EXTPROC) | L_EXTPROC(tty); int old_flow = ((old_termios->c_iflag & IXON) && (old_termios->c_cc[VSTOP] == '\023') && (old_termios->c_cc[VSTART] == '\021')); diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index 9dd02daf45ca..2ab3b6fdb675 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -959,7 +959,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) tty->alt_speed = 460800; configure_r_port(tty, info, NULL); - if (tty->termios.c_cflag & CBAUD) { + if (C_BAUD(tty)) { sSetDTR(cp); sSetRTS(cp); } @@ -1084,18 +1084,18 @@ static void rp_set_termios(struct tty_struct *tty, cp = &info->channel; /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) { sClrDTR(cp); sClrRTS(cp); } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && (tty->termios.c_cflag & CBAUD)) { + if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) { sSetRTS(cp); sSetDTR(cp); } - if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios.c_cflag & CRTSCTS)) + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) rp_start(tty); } diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index 90639b590a10..4931212e5cf6 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -976,10 +976,8 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_speed(info, tty); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) rs_start(tty); - } /* diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index e98aef797065..37f10c4a3faf 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -1413,9 +1413,8 @@ rs_stop(struct tty_struct *tty) xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->port.tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, stop); - if (tty->termios.c_iflag & IXON ) { + if (I_IXON(tty)) xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); - } *((unsigned long *)&info->ioport[REG_XOFF]) = xoff; local_irq_restore(flags); @@ -1436,9 +1435,8 @@ rs_start(struct tty_struct *tty) info->xmit.tail,SERIAL_XMIT_SIZE))); xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable); - if (tty->termios.c_iflag & IXON ) { + if (I_IXON(tty)) xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); - } *((unsigned long *)&info->ioport[REG_XOFF]) = xoff; if (!info->uses_dma_out && @@ -3166,7 +3164,7 @@ rs_throttle(struct tty_struct * tty) DFLOW(DEBUG_LOG(info->line,"rs_throttle\n")); /* Do RTS before XOFF since XOFF might take some time */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { /* Turn off RTS line */ e100_rts(info, 0); } @@ -3185,7 +3183,7 @@ rs_unthrottle(struct tty_struct * tty) DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc\n")); DFLOW(DEBUG_LOG(info->line,"rs_unthrottle flip.count: %i\n", tty->flip.count)); /* Do RTS before XOFF since XOFF might take some time */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { /* Assert RTS line */ e100_rts(info, 1); } @@ -3553,8 +3551,7 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_speed(info); /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) rs_start(tty); } @@ -3765,9 +3762,8 @@ block_til_ready(struct tty_struct *tty, struct file * filp, return 0; } - if (tty->termios.c_cflag & CLOCAL) { - do_clocal = 1; - } + if (C_CLOCAL(tty)) + do_clocal = 1; /* * Block waiting for the carrier detect and the line to become diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c index 524e86ab3cae..00cac10ae75a 100644 --- a/drivers/tty/serial/jsm/jsm_tty.c +++ b/drivers/tty/serial/jsm/jsm_tty.c @@ -569,8 +569,7 @@ void jsm_input(struct jsm_channel *ch) *If the device is not open, or CREAD is off, flush *input data and return immediately. */ - if (!tp || - !(tp->termios.c_cflag & CREAD) ) { + if (!tp || !C_CREAD(tp)) { jsm_dbg(READ, &ch->ch_bd->pci_dev, "input. dropping %d bytes on port %d...\n", diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index b1f54ab1818c..1efdc2b476ea 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -171,14 +171,12 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, */ uart_change_speed(tty, state, NULL); - if (init_hw) { - /* - * Setup the RTS and DTR signals once the - * port is open and ready to respond. - */ - if (tty->termios.c_cflag & CBAUD) - uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); - } + /* + * Setup the RTS and DTR signals once the + * port is open and ready to respond. + */ + if (init_hw && C_BAUD(tty)) + uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); } /* @@ -240,7 +238,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) if (uart_console(uport) && tty) uport->cons->cflag = tty->termios.c_cflag; - if (!tty || (tty->termios.c_cflag & HUPCL)) + if (!tty || C_HUPCL(tty)) uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); uart_port_shutdown(port); @@ -639,7 +637,7 @@ static void uart_throttle(struct tty_struct *tty) if (I_IXOFF(tty)) mask |= UPSTAT_AUTOXOFF; - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) mask |= UPSTAT_AUTORTS; if (port->status & mask) { @@ -662,7 +660,7 @@ static void uart_unthrottle(struct tty_struct *tty) if (I_IXOFF(tty)) mask |= UPSTAT_AUTOXOFF; - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) mask |= UPSTAT_AUTORTS; if (port->status & mask) { diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 6188059fd523..f5476e270734 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c @@ -2363,7 +2363,7 @@ static void mgsl_throttle(struct tty_struct * tty) if (I_IXOFF(tty)) mgsl_send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->irq_spinlock,flags); info->serial_signals &= ~SerialSignal_RTS; usc_set_serial_signals(info); @@ -2397,7 +2397,7 @@ static void mgsl_unthrottle(struct tty_struct * tty) mgsl_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->irq_spinlock,flags); info->serial_signals |= SerialSignal_RTS; usc_set_serial_signals(info); @@ -3039,30 +3039,25 @@ static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termio mgsl_change_params(info); /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) { info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); spin_lock_irqsave(&info->irq_spinlock,flags); usc_set_serial_signals(info); spin_unlock_irqrestore(&info->irq_spinlock,flags); } - + /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) { info->serial_signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) info->serial_signals |= SerialSignal_RTS; - } spin_lock_irqsave(&info->irq_spinlock,flags); usc_set_serial_signals(info); spin_unlock_irqrestore(&info->irq_spinlock,flags); } - + /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + if (old_termios->c_cflag & CRTSCTS && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; mgsl_start(tty); } @@ -3281,7 +3276,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, return 0; } - if (tty->termios.c_cflag & CLOCAL) + if (C_CLOCAL(tty)) do_clocal = true; /* Wait for carrier detect and the line to become diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index 5505ea842179..c0a2f5a1b1c2 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -774,8 +774,7 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_params(info); /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) { info->signals &= ~(SerialSignal_RTS | SerialSignal_DTR); spin_lock_irqsave(&info->lock,flags); set_signals(info); @@ -783,21 +782,17 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) { info->signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) info->signals |= SerialSignal_RTS; - } spin_lock_irqsave(&info->lock,flags); set_signals(info); spin_unlock_irqrestore(&info->lock,flags); } /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; tx_release(tty); } @@ -1362,7 +1357,7 @@ static void throttle(struct tty_struct * tty) DBGINFO(("%s throttle\n", info->device_name)); if (I_IXOFF(tty)) send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock,flags); info->signals &= ~SerialSignal_RTS; set_signals(info); @@ -1387,7 +1382,7 @@ static void unthrottle(struct tty_struct * tty) else send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock,flags); info->signals |= SerialSignal_RTS; set_signals(info); @@ -3280,7 +3275,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, return 0; } - if (tty->termios.c_cflag & CLOCAL) + if (C_CLOCAL(tty)) do_clocal = true; /* Wait for carrier detect and the line to become diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index fb00a06dfa4b..4b314b63a2ed 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c @@ -871,8 +871,7 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_params(info); /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) { info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); spin_lock_irqsave(&info->lock,flags); set_signals(info); @@ -880,21 +879,17 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) { info->serial_signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) info->serial_signals |= SerialSignal_RTS; - } spin_lock_irqsave(&info->lock,flags); set_signals(info); spin_unlock_irqrestore(&info->lock,flags); } /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + if (old_termios->c_cflag & CRTSCTS && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; tx_release(tty); } @@ -1472,7 +1467,7 @@ static void throttle(struct tty_struct * tty) if (I_IXOFF(tty)) send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock,flags); info->serial_signals &= ~SerialSignal_RTS; set_signals(info); @@ -1501,7 +1496,7 @@ static void unthrottle(struct tty_struct * tty) send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock,flags); info->serial_signals |= SerialSignal_RTS; set_signals(info); @@ -3297,7 +3292,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, return 0; } - if (tty->termios.c_cflag & CLOCAL) + if (C_CLOCAL(tty)) do_clocal = true; /* Wait for carrier detect and the line to become diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index 0ea351388724..23bf5bb1d8bf 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -719,16 +719,16 @@ static int get_sgflags(struct tty_struct *tty) { int flags = 0; - if (!(tty->termios.c_lflag & ICANON)) { - if (tty->termios.c_lflag & ISIG) + if (!L_ICANON(tty)) { + if (L_ISIG(tty)) flags |= 0x02; /* cbreak */ else flags |= 0x20; /* raw */ } - if (tty->termios.c_lflag & ECHO) + if (L_ECHO(tty)) flags |= 0x08; /* echo */ - if (tty->termios.c_oflag & OPOST) - if (tty->termios.c_oflag & ONLCR) + if (O_OPOST(tty)) + if (O_ONLCR(tty)) flags |= 0x10; /* crmod */ return flags; } @@ -908,7 +908,7 @@ static int tty_change_softcar(struct tty_struct *tty, int arg) tty->termios.c_cflag |= bit; if (tty->ops->set_termios) tty->ops->set_termios(tty, &old); - if ((tty->termios.c_cflag & CLOCAL) != bit) + if (C_CLOCAL(tty) != bit) ret = -EINVAL; up_write(&tty->termios_rwsem); return ret; diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index a76aec2ca480..0473fc7543f7 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -370,7 +370,7 @@ int tty_port_block_til_ready(struct tty_port *port, } if (filp->f_flags & O_NONBLOCK) { /* Indicate we are open */ - if (tty->termios.c_cflag & CBAUD) + if (C_BAUD(tty)) tty_port_raise_dtr_rts(port); port->flags |= ASYNC_NORMAL_ACTIVE; return 0; diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 01bf53392819..b283eb8b86d6 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -1165,8 +1165,7 @@ static void cypress_read_int_callback(struct urb *urb) /* hangup, as defined in acm.c... this might be a bad place for it * though */ - if (tty && !(tty->termios.c_cflag & CLOCAL) && - !(priv->current_status & UART_CD)) { + if (tty && !C_CLOCAL(tty) && !(priv->current_status & UART_CD)) { dev_dbg(dev, "%s - calling hangup\n", __func__); tty_hangup(tty); goto continue_read; diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 12b0e67473ba..010a42a92688 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -695,11 +695,11 @@ static void digi_set_termios(struct tty_struct *tty, arg = -1; /* reassert DTR and (maybe) RTS on transition from B0 */ - if ((old_cflag&CBAUD) == B0) { + if ((old_cflag & CBAUD) == B0) { /* don't set RTS if using hardware flow control */ /* and throttling input */ modem_signals = TIOCM_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) modem_signals |= TIOCM_RTS; digi_set_modem_signals(port, modem_signals, 1); @@ -1491,8 +1491,8 @@ static int digi_read_oob_callback(struct urb *urb) rts = 0; if (tty) - rts = tty->termios.c_cflag & CRTSCTS; - + rts = C_CRTSCTS(tty); + if (tty && opcode == DIGI_CMD_READ_INPUT_SIGNALS) { spin_lock(&priv->dp_port_lock); /* convert from digi flags to termiox flags */ diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index f49327d20ee8..f3007ecdd1b4 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -1398,7 +1398,7 @@ static void edge_throttle(struct tty_struct *tty) } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { edge_port->shadowMCR &= ~MCR_RTS; status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); @@ -1435,7 +1435,7 @@ static void edge_unthrottle(struct tty_struct *tty) return; } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { edge_port->shadowMCR |= MCR_RTS; send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index fd707d6a10e2..4446b8d70ac2 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -428,7 +428,7 @@ static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port) * either. */ spin_lock_irqsave(&priv->lock, flags); - if (tty && (tty->termios.c_cflag & CBAUD)) + if (tty && C_BAUD(tty)) priv->control_state = TIOCM_DTR | TIOCM_RTS; else priv->control_state = 0; diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 78b4f64c6b00..2eddbe538cda 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1308,7 +1308,7 @@ static void mos7720_throttle(struct tty_struct *tty) } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { mos7720_port->shadowMCR &= ~UART_MCR_RTS; write_mos_reg(port->serial, port->port_number, MOS7720_MCR, mos7720_port->shadowMCR); @@ -1338,7 +1338,7 @@ static void mos7720_unthrottle(struct tty_struct *tty) } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { mos7720_port->shadowMCR |= UART_MCR_RTS; write_mos_reg(port->serial, port->port_number, MOS7720_MCR, mos7720_port->shadowMCR); diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 2c69bfcdacc6..02ea975754f5 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1425,7 +1425,7 @@ static void mos7840_throttle(struct tty_struct *tty) return; } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { mos7840_port->shadowMCR &= ~MCR_RTS; status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mos7840_port->shadowMCR); @@ -1466,7 +1466,7 @@ static void mos7840_unthrottle(struct tty_struct *tty) } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { mos7840_port->shadowMCR |= MCR_RTS; status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mos7840_port->shadowMCR); diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index a4237707f79d..1776fe5715e5 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -287,14 +287,14 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, if (filp->f_flags & O_NONBLOCK) { /* nonblock mode is set */ - if (tty->termios.c_cflag & CBAUD) + if (C_BAUD(tty)) tty_port_raise_dtr_rts(port); port->flags |= ASYNC_NORMAL_ACTIVE; pr_debug("%s(), O_NONBLOCK requested!\n", __func__); return 0; } - if (tty->termios.c_cflag & CLOCAL) { + if (C_CLOCAL(tty)) { pr_debug("%s(), doing CLOCAL!\n", __func__); do_clocal = 1; } @@ -806,7 +806,7 @@ static void ircomm_tty_throttle(struct tty_struct *tty) ircomm_tty_send_xchar(tty, STOP_CHAR(tty)); /* Hardware flow control? */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { self->settings.dte &= ~IRCOMM_RTS; self->settings.dte |= IRCOMM_DELTA_RTS; @@ -831,12 +831,11 @@ static void ircomm_tty_unthrottle(struct tty_struct *tty) IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); /* Using software flow control? */ - if (I_IXOFF(tty)) { + if (I_IXOFF(tty)) ircomm_tty_send_xchar(tty, START_CHAR(tty)); - } /* Using hardware flow control? */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { self->settings.dte |= (IRCOMM_RTS|IRCOMM_DELTA_RTS); ircomm_param_request(self, IRCOMM_DTE, TRUE); diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c index 75ccdbd0728e..d3687aaa23de 100644 --- a/net/irda/ircomm/ircomm_tty_ioctl.c +++ b/net/irda/ircomm/ircomm_tty_ioctl.c @@ -158,26 +158,21 @@ void ircomm_tty_set_termios(struct tty_struct *tty, ircomm_tty_change_speed(self, tty); /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && - !(cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) { self->settings.dte &= ~(IRCOMM_DTR|IRCOMM_RTS); ircomm_param_request(self, IRCOMM_DTE, TRUE); } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - (cflag & CBAUD)) { + if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { self->settings.dte |= IRCOMM_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) self->settings.dte |= IRCOMM_RTS; - } ircomm_param_request(self, IRCOMM_DTE, TRUE); } /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; ircomm_tty_start(tty); -- cgit v1.2.3 From f5291ecca148e1a4a75498177862040f9ab7b600 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:23:55 -0800 Subject: serial: core: Fold __uart_put_char() into caller uart_put_char() is the required interface; manually inline __uart_put_char(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 1efdc2b476ea..06b1ddc1d76d 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -483,12 +483,15 @@ static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, spin_unlock_irq(&uport->lock); } -static inline int __uart_put_char(struct uart_port *port, - struct circ_buf *circ, unsigned char c) +static int uart_put_char(struct tty_struct *tty, unsigned char c) { + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->uart_port; + struct circ_buf *circ; unsigned long flags; int ret = 0; + circ = &state->xmit; if (!circ->buf) return 0; @@ -502,13 +505,6 @@ static inline int __uart_put_char(struct uart_port *port, return ret; } -static int uart_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct uart_state *state = tty->driver_data; - - return __uart_put_char(state->uart_port, &state->xmit, ch); -} - static void uart_flush_chars(struct tty_struct *tty) { uart_start(tty); -- cgit v1.2.3 From 3abe8c7671a53f2243d1279a1017d3f4483d34c4 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:23:56 -0800 Subject: serial: core: Fold do_uart_get_info() into caller do_uart_get_info() has a single caller: uart_get_info(). Manually inline do_uart_get_info(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 06b1ddc1d76d..b1785d112e2e 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -671,14 +671,18 @@ static void uart_unthrottle(struct tty_struct *tty) uart_set_mctrl(port, TIOCM_RTS); } -static void do_uart_get_info(struct tty_port *port, - struct serial_struct *retinfo) +static void uart_get_info(struct tty_port *port, struct serial_struct *retinfo) { struct uart_state *state = container_of(port, struct uart_state, port); struct uart_port *uport = state->uart_port; memset(retinfo, 0, sizeof(*retinfo)); + /* + * Ensure the state we copy is consistent and no hardware changes + * occur as we go + */ + mutex_lock(&port->mutex); retinfo->type = uport->type; retinfo->line = uport->line; retinfo->port = uport->iobase; @@ -697,15 +701,6 @@ static void do_uart_get_info(struct tty_port *port, retinfo->io_type = uport->iotype; retinfo->iomem_reg_shift = uport->regshift; retinfo->iomem_base = (void *)(unsigned long)uport->mapbase; -} - -static void uart_get_info(struct tty_port *port, - struct serial_struct *retinfo) -{ - /* Ensure the state we copy is consistent and no hardware changes - occur as we go */ - mutex_lock(&port->mutex); - do_uart_get_info(port, retinfo); mutex_unlock(&port->mutex); } @@ -713,6 +708,7 @@ static int uart_get_info_user(struct tty_port *port, struct serial_struct __user *retinfo) { struct serial_struct tmp; + uart_get_info(port, &tmp); if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) -- cgit v1.2.3 From 39b3d8929f3d2104772046977ba0781eaf032df4 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:23:57 -0800 Subject: serial: core: Use tty->index for port # in debug messages The uart port may have already been removed by uart_remove_one_port(); use equivalent tty->index (which is always valid in these contexts) instead. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index b1785d112e2e..1e7430c60ee6 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1381,8 +1381,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) uport = state->uart_port; port = &state->port; - - pr_debug("uart_close(%d) called\n", uport ? uport->line : -1); + pr_debug("uart_close(%d) called\n", tty->index); if (!port->count || tty_port_close_start(port, tty, filp) == 0) return; @@ -1500,7 +1499,7 @@ static void uart_hangup(struct tty_struct *tty) struct tty_port *port = &state->port; unsigned long flags; - pr_debug("uart_hangup(%d)\n", state->uart_port->line); + pr_debug("uart_hangup(%d)\n", tty->index); mutex_lock(&port->mutex); if (port->flags & ASYNC_NORMAL_ACTIVE) { -- cgit v1.2.3 From 35373abbce3e63754f96792cc1e5a4b329d3c737 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:23:58 -0800 Subject: serial: Fix ASYNC_* => UPF_* flags misuse The UPF_* flags are the correct values to use for struct uart_port and struct old_serial_port/SERIAL_PORT_DFNS. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- arch/alpha/include/asm/serial.h | 8 ++++---- arch/frv/include/asm/serial.h | 2 +- arch/m68k/include/asm/serial.h | 8 ++++---- arch/mips/pmcs-msp71xx/msp_serial.c | 2 +- arch/mn10300/include/asm/serial.h | 10 +++++----- arch/xtensa/platforms/xt2000/setup.c | 2 +- drivers/tty/serial/serial_ks8695.c | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/arch/alpha/include/asm/serial.h b/arch/alpha/include/asm/serial.h index 22909b83f473..e31557fc06cc 100644 --- a/arch/alpha/include/asm/serial.h +++ b/arch/alpha/include/asm/serial.h @@ -14,11 +14,11 @@ /* Standard COM flags (except for COM4, because of the 8514 problem) */ #ifdef CONFIG_SERIAL_8250_DETECT_IRQ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ) -#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ) +#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ) +#define STD_COM4_FLAGS (UPF_BOOT_AUTOCONF | UPF_AUTO_IRQ) #else -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) -#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF +#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST) +#define STD_COM4_FLAGS UPF_BOOT_AUTOCONF #endif #define SERIAL_PORT_DFNS \ diff --git a/arch/frv/include/asm/serial.h b/arch/frv/include/asm/serial.h index dbb825998689..bce0d0d07e60 100644 --- a/arch/frv/include/asm/serial.h +++ b/arch/frv/include/asm/serial.h @@ -13,6 +13,6 @@ */ #define BASE_BAUD 0 -#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF +#define STD_COM_FLAGS UPF_BOOT_AUTOCONF #define SERIAL_PORT_DFNS diff --git a/arch/m68k/include/asm/serial.h b/arch/m68k/include/asm/serial.h index 06d0cb19b4e1..6d4497049b4b 100644 --- a/arch/m68k/include/asm/serial.h +++ b/arch/m68k/include/asm/serial.h @@ -18,11 +18,11 @@ /* Standard COM flags (except for COM4, because of the 8514 problem) */ #ifdef CONFIG_SERIAL_8250_DETECT_IRQ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ) -#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ) +#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ) +#define STD_COM4_FLAGS (UPF_BOOT_AUTOCONF | UPF_AUTO_IRQ) #else -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) -#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF +#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST) +#define STD_COM4_FLAGS UPF_BOOT_AUTOCONF #endif #ifdef CONFIG_ISA diff --git a/arch/mips/pmcs-msp71xx/msp_serial.c b/arch/mips/pmcs-msp71xx/msp_serial.c index d304be22b963..8e6e8db8dd5f 100644 --- a/arch/mips/pmcs-msp71xx/msp_serial.c +++ b/arch/mips/pmcs-msp71xx/msp_serial.c @@ -110,7 +110,7 @@ void __init msp_serial_setup(void) up.uartclk = uartclk; up.regshift = 2; up.iotype = UPIO_MEM; - up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + up.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; up.type = PORT_16550A; up.line = 0; up.serial_out = msp_serial_out; diff --git a/arch/mn10300/include/asm/serial.h b/arch/mn10300/include/asm/serial.h index c1990218f18c..594ebff15d3f 100644 --- a/arch/mn10300/include/asm/serial.h +++ b/arch/mn10300/include/asm/serial.h @@ -14,15 +14,15 @@ /* Standard COM flags (except for COM4, because of the 8514 problem) */ #ifdef CONFIG_SERIAL_8250_DETECT_IRQ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ) -#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ) +#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ) +#define STD_COM4_FLAGS (UPF_BOOT_AUTOCONF | UPF_AUTO_IRQ) #else -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) -#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF +#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST) +#define STD_COM4_FLAGS UPF_BOOT_AUTOCONF #endif #ifdef CONFIG_SERIAL_8250_MANY_PORTS -#define FOURPORT_FLAGS ASYNC_FOURPORT +#define FOURPORT_FLAGS UPF_FOURPORT #define ACCENT_FLAGS 0 #define BOCA_FLAGS 0 #define HUB6_FLAGS 0 diff --git a/arch/xtensa/platforms/xt2000/setup.c b/arch/xtensa/platforms/xt2000/setup.c index 87678961a8c8..5f4bd71971d6 100644 --- a/arch/xtensa/platforms/xt2000/setup.c +++ b/arch/xtensa/platforms/xt2000/setup.c @@ -113,7 +113,7 @@ void platform_heartbeat(void) } //#define RS_TABLE_SIZE 2 -//#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) +//#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF|UPF_SKIP_TEST) #define _SERIAL_PORT(_base,_irq) \ { \ diff --git a/drivers/tty/serial/serial_ks8695.c b/drivers/tty/serial/serial_ks8695.c index b4decf8787de..57f152394af5 100644 --- a/drivers/tty/serial/serial_ks8695.c +++ b/drivers/tty/serial/serial_ks8695.c @@ -554,7 +554,7 @@ static struct uart_port ks8695uart_ports[SERIAL_KS8695_NR] = { .uartclk = KS8695_CLOCK_RATE * 16, .fifosize = 16, .ops = &ks8695uart_pops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, } }; -- cgit v1.2.3 From f9d1083da00514ef36a06e915f32b7304ae5b5bd Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:23:59 -0800 Subject: serial: core: Cleanup uart_open() exit If aborting uart_open() unsuccessfully, retval is non-zero, so the existing fall-through exit is equivalent. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 1e7430c60ee6..5cf069756497 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1622,15 +1622,12 @@ static int uart_open(struct tty_struct *tty, struct file *filp) /* * If we succeeded, wait until the port is ready. */ +err_unlock: mutex_unlock(&port->mutex); if (retval == 0) retval = tty_port_block_til_ready(port, tty, filp); - end: return retval; -err_unlock: - mutex_unlock(&port->mutex); - goto end; } static const char *uart_type(struct uart_port *port) -- cgit v1.2.3 From 5e3880273fa3c85bc8f14b9719d2c4be00dd3279 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:24:00 -0800 Subject: serial: core: Remove cast from void ptr in uart_open() void * promotes to any pointer type; remove type cast. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 5cf069756497..9fa42acca7c0 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1580,7 +1580,7 @@ static void uart_dtr_rts(struct tty_port *port, int onoff) */ static int uart_open(struct tty_struct *tty, struct file *filp) { - struct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state; + struct uart_driver *drv = tty->driver->driver_state; int retval, line = tty->index; struct uart_state *state = drv->state + line; struct tty_port *port = &state->port; -- cgit v1.2.3 From 968af29836297388743d208a360bac6f1a690148 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:24:01 -0800 Subject: serial: core: Unfold < 80 char lines Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 9fa42acca7c0..fa7f442424cf 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1686,17 +1686,13 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i) seq_printf(m, " tx:%d rx:%d", uport->icount.tx, uport->icount.rx); if (uport->icount.frame) - seq_printf(m, " fe:%d", - uport->icount.frame); + seq_printf(m, " fe:%d", uport->icount.frame); if (uport->icount.parity) - seq_printf(m, " pe:%d", - uport->icount.parity); + seq_printf(m, " pe:%d", uport->icount.parity); if (uport->icount.brk) - seq_printf(m, " brk:%d", - uport->icount.brk); + seq_printf(m, " brk:%d", uport->icount.brk); if (uport->icount.overrun) - seq_printf(m, " oe:%d", - uport->icount.overrun); + seq_printf(m, " oe:%d", uport->icount.overrun); #define INFOBIT(bit, str) \ if (uport->mctrl & (bit)) \ @@ -1731,8 +1727,7 @@ static int uart_proc_show(struct seq_file *m, void *v) struct uart_driver *drv = ttydrv->driver_state; int i; - seq_printf(m, "serinfo:1.0 driver%s%s revision:%s\n", - "", "", ""); + seq_printf(m, "serinfo:1.0 driver%s%s revision:%s\n", "", "", ""); for (i = 0; i < drv->nr; i++) uart_line_info(m, drv, i); return 0; -- cgit v1.2.3 From b4749b97ae41f02775967bd109a15b2e223f86be Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:24:02 -0800 Subject: serial: core: Perform RTS signalling before soft flow ctrl When throttling, time is of the essence; try RTS signalling before soft flow control, which will take longer. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index fa7f442424cf..be9359fdf5c7 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -641,11 +641,11 @@ static void uart_throttle(struct tty_struct *tty) mask &= ~port->status; } - if (mask & UPSTAT_AUTOXOFF) - uart_send_xchar(tty, STOP_CHAR(tty)); - if (mask & UPSTAT_AUTORTS) uart_clear_mctrl(port, TIOCM_RTS); + + if (mask & UPSTAT_AUTOXOFF) + uart_send_xchar(tty, STOP_CHAR(tty)); } static void uart_unthrottle(struct tty_struct *tty) @@ -664,11 +664,11 @@ static void uart_unthrottle(struct tty_struct *tty) mask &= ~port->status; } - if (mask & UPSTAT_AUTOXOFF) - uart_send_xchar(tty, START_CHAR(tty)); - if (mask & UPSTAT_AUTORTS) uart_set_mctrl(port, TIOCM_RTS); + + if (mask & UPSTAT_AUTOXOFF) + uart_send_xchar(tty, START_CHAR(tty)); } static void uart_get_info(struct tty_port *port, struct serial_struct *retinfo) -- cgit v1.2.3 From cd7b4b3944381713038d39240098908ffeec647d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:51:38 -0800 Subject: tty: mxser: Remove ASYNC_CLOSING The tty core no longer provides ASYNC_CLOSING. Use private flag for same purpose, which is to clear the fifos at each and every interrupt during driver close(). The driver uses this sledgehammer approach because its close/shutdown sequence is hopelessly borked. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index e9600cece8da..9a0791e523b5 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -254,6 +254,7 @@ struct mxser_port { int xmit_head; int xmit_tail; int xmit_cnt; + int closing; struct ktermios normal_termios; @@ -1081,6 +1082,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) return; if (tty_port_close_start(port, tty, filp) == 0) return; + info->closing = 1; mutex_lock(&port->mutex); mxser_close_port(port); mxser_flush_buffer(tty); @@ -1091,6 +1093,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) mxser_shutdown_port(port); clear_bit(ASYNCB_INITIALIZED, &port->flags); mutex_unlock(&port->mutex); + info->closing = 0; /* Right now the tty_port set is done outside of the close_end helper as we don't yet have everyone using refcounts */ tty_port_close_end(port, tty); @@ -2253,10 +2256,8 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) break; iir &= MOXA_MUST_IIR_MASK; tty = tty_port_tty_get(&port->port); - if (!tty || - (port->port.flags & ASYNC_CLOSING) || - !(port->port.flags & - ASYNC_INITIALIZED)) { + if (!tty || port->closing || + !(port->port.flags & ASYNC_INITIALIZED)) { status = inb(port->ioaddr + UART_LSR); outb(0x27, port->ioaddr + UART_FCR); inb(port->ioaddr + UART_MSR); -- cgit v1.2.3 From a657eecd022d82c5b1795243f54389112f42c7f9 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:51:39 -0800 Subject: isdn: Remove ASYNC_CLOSING The tty core no longer provides ASYNC_CLOSING. Use private flag for same purpose, which is to disable AT-emulator output (why this is necessary is not clear). Cc: Karsten Keil Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/i4l/isdn_tty.c | 12 ++++++------ include/linux/isdn.h | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 2175225af742..947d5c978b8f 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1572,7 +1572,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) #endif return; } - port->flags |= ASYNC_CLOSING; + info->closing = 1; tty->closing = 1; /* @@ -1603,6 +1603,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) info->ncarrier = 0; tty_port_close_end(port, tty); + info->closing = 0; #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_close normal exit\n"); #endif @@ -2236,7 +2237,7 @@ isdn_tty_at_cout(char *msg, modem_info *info) l = strlen(msg); spin_lock_irqsave(&info->readlock, flags); - if (port->flags & ASYNC_CLOSING) { + if (info->closing) { spin_unlock_irqrestore(&info->readlock, flags); return; } @@ -2386,13 +2387,12 @@ isdn_tty_modem_result(int code, modem_info *info) case RESULT_NO_CARRIER: #ifdef ISDN_DEBUG_MODEM_HUP printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n", - (info->port.flags & ASYNC_CLOSING), - (!info->port.tty)); + info->closing, !info->port.tty); #endif m->mdmreg[REG_RINGCNT] = 0; del_timer(&info->nc_timer); info->ncarrier = 0; - if ((info->port.flags & ASYNC_CLOSING) || (!info->port.tty)) + if (info->closing || !info->port.tty) return; #ifdef CONFIG_ISDN_AUDIO @@ -2525,7 +2525,7 @@ isdn_tty_modem_result(int code, modem_info *info) } } if (code == RESULT_NO_CARRIER) { - if ((info->port.flags & ASYNC_CLOSING) || (!info->port.tty)) + if (info->closing || (!info->port.tty)) return; if (info->port.flags & ASYNC_CHECK_CD) diff --git a/include/linux/isdn.h b/include/linux/isdn.h index 1e9a0f2a8626..df97c8444f5d 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -319,6 +319,7 @@ typedef struct modem_info { int online; /* 1 = B-Channel is up, drop data */ /* 2 = B-Channel is up, deliver d.*/ int dialing; /* Dial in progress or ATA */ + int closing; int rcvsched; /* Receive needs schedule */ int isdn_driver; /* Index to isdn-driver */ int isdn_channel; /* Index to isdn-channel */ -- cgit v1.2.3 From afc5ab096581e1ad6e7e7d1533a6bbb1d2b12455 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:51:40 -0800 Subject: tty: Remove ASYNC_CLOSING The tty core no longer provides nor uses ASYNC_CLOSING; remove from tty_port_close_start() and tty_port_close_end() as well as tty drivers which open-code these state changes. Unfortunately, even though the bit is masked from userspace, its inclusion in a uapi header precludes removing the macro. Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux-s390@vger.kernel.org Cc: Mikael Starvik Cc: Jesper Nilsson Cc: linux-cris-kernel@axis.com Cc: Samuel Ortiz Cc: "David S. Miller" Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/s390/char/con3215.c | 3 +-- drivers/tty/rocket.c | 2 +- drivers/tty/serial/68328serial.c | 3 +-- drivers/tty/serial/crisv10.c | 3 +-- drivers/tty/serial/serial_core.c | 1 - drivers/tty/tty_port.c | 3 +-- net/irda/ircomm/ircomm_tty.c | 4 ---- 7 files changed, 5 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 7d82bbcb12df..e7e078b3c7e6 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -643,7 +643,6 @@ static void raw3215_shutdown(struct raw3215_info *raw) if ((raw->flags & RAW3215_WORKING) || raw->queued_write != NULL || raw->queued_read != NULL) { - raw->port.flags |= ASYNC_CLOSING; add_wait_queue(&raw->empty_wait, &wait); set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); @@ -651,7 +650,7 @@ static void raw3215_shutdown(struct raw3215_info *raw) spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); remove_wait_queue(&raw->empty_wait, &wait); set_current_state(TASK_RUNNING); - raw->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING); + raw->port.flags &= ~ASYNC_INITIALIZED; } spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); } diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index 2ab3b6fdb675..0b802cdd70d0 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -1042,7 +1042,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp) } } spin_lock_irq(&port->lock); - info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE); + info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_NORMAL_ACTIVE); tty->closing = 0; spin_unlock_irq(&port->lock); mutex_unlock(&port->mutex); diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index 4931212e5cf6..9587ed1242fe 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -1028,7 +1028,6 @@ static void rs_close(struct tty_struct *tty, struct file *filp) local_irq_restore(flags); return; } - port->flags |= ASYNC_CLOSING; /* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. @@ -1058,7 +1057,7 @@ static void rs_close(struct tty_struct *tty, struct file *filp) msleep_interruptible(jiffies_to_msecs(port->close_delay)); wake_up_interruptible(&port->open_wait); } - port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + port->flags &= ~ASYNC_NORMAL_ACTIVE; local_irq_restore(flags); } diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index 37f10c4a3faf..c0172bf54a9b 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -3610,7 +3610,6 @@ rs_close(struct tty_struct *tty, struct file * filp) local_irq_restore(flags); return; } - info->port.flags |= ASYNC_CLOSING; /* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. @@ -3649,7 +3648,7 @@ rs_close(struct tty_struct *tty, struct file * filp) schedule_timeout_interruptible(info->port.close_delay); wake_up_interruptible(&info->port.open_wait); } - info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + info->port.flags &= ~ASYNC_NORMAL_ACTIVE; local_irq_restore(flags); /* port closed */ diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index be9359fdf5c7..85829f8568e7 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1423,7 +1423,6 @@ static void uart_close(struct tty_struct *tty, struct file *filp) * Wake up anyone trying to open this port. */ clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); - clear_bit(ASYNCB_CLOSING, &port->flags); spin_unlock_irq(&port->lock); wake_up_interruptible(&port->open_wait); diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 0473fc7543f7..dbcca30a54b1 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -476,7 +476,6 @@ int tty_port_close_start(struct tty_port *port, spin_unlock_irqrestore(&port->lock, flags); return 0; } - set_bit(ASYNCB_CLOSING, &port->flags); spin_unlock_irqrestore(&port->lock, flags); tty->closing = 1; @@ -515,7 +514,7 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty) spin_lock_irqsave(&port->lock, flags); wake_up_interruptible(&port->open_wait); } - port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); + port->flags &= ~ASYNC_NORMAL_ACTIVE; spin_unlock_irqrestore(&port->lock, flags); } EXPORT_SYMBOL(tty_port_close_end); diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 1776fe5715e5..da126ee6d218 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -1267,10 +1267,6 @@ static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m) seq_printf(m, "%cASYNC_LOW_LATENCY", sep); sep = '|'; } - if (self->port.flags & ASYNC_CLOSING) { - seq_printf(m, "%cASYNC_CLOSING", sep); - sep = '|'; - } if (self->port.flags & ASYNC_NORMAL_ACTIVE) { seq_printf(m, "%cASYNC_NORMAL_ACTIVE", sep); sep = '|'; -- cgit v1.2.3 From 70f340df24518d36eeaefb6652d492f250115c19 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Wed, 27 Jan 2016 17:48:32 +0100 Subject: spi: atmel: fix gpio chip-select in case of non-DT platform The non-DT platform that uses this driver (actually the AVR32) was taking a bad branch for determining if the IP would use gpio for CS. Adding the presence of DT as a condition fixes this issue. Fixes: 4820303480a1 ("spi: atmel: add support for the internal chip-select of the spi controller") Reported-by: Mans Rullgard Signed-off-by: Cyrille Pitchen [nicolas.ferre@atmel.com: extract from ml discussion] Signed-off-by: Nicolas Ferre Tested-by: Mans Rullgard Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/spi/spi-atmel.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index aebad36391c9..8feac599e9ab 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1571,6 +1571,7 @@ static int atmel_spi_probe(struct platform_device *pdev) as->use_cs_gpios = true; if (atmel_spi_is_v2(as) && + pdev->dev.of_node && !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) { as->use_cs_gpios = false; master->num_chipselect = 4; -- cgit v1.2.3 From 4dc236c31733f5d2a3872c88cf12f607d7d36905 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 27 Jan 2016 15:20:16 +0100 Subject: mlxsw: spectrum: Handle port leaving LAG while bridged It is possible for a user to remove a port from a LAG device, while the LAG device or VLAN devices on top of it are bridged. In these cases, bridge's teardown sequence is never issued, so we need to take care of it ourselves. When LAG's unlinking event is received by port netdev: 1) Traverse its vPorts list and make those member in a bridge leave it. They will be deleted later by LAG code. 2) Make the port netdev itself leave its bridge if member in one. Fixes: 0d65fc13042f ("mlxsw: spectrum: Implement LAG port join/leave") Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 30 +++++++++++++++++++--- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 1 + .../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 8 ++++++ 3 files changed, 36 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index ce6845d534a8..637a9d72fd93 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2200,10 +2200,14 @@ err_col_port_enable: return err; } +static int mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport, + struct net_device *br_dev); + static int mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port, struct net_device *lag_dev) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + struct mlxsw_sp_port *mlxsw_sp_vport; struct mlxsw_sp_upper *lag; u16 lag_id = mlxsw_sp_port->lag_id; int err; @@ -2220,6 +2224,29 @@ static int mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port, if (err) return err; + /* In case we leave a LAG device that has bridges built on top, + * then their teardown sequence is never issued and we need to + * invoke the necessary cleanup routines ourselves. + */ + list_for_each_entry(mlxsw_sp_vport, &mlxsw_sp_port->vports_list, + vport.list) { + struct net_device *br_dev; + + if (!mlxsw_sp_vport->bridged) + continue; + + br_dev = mlxsw_sp_vport_br_get(mlxsw_sp_vport); + mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport, br_dev); + } + + if (mlxsw_sp_port->bridged) { + mlxsw_sp_port_active_vlans_del(mlxsw_sp_port); + mlxsw_sp_port_bridge_leave(mlxsw_sp_port); + + if (lag->ref_count == 1) + mlxsw_sp_master_bridge_dec(mlxsw_sp, NULL); + } + if (lag->ref_count == 1) { err = mlxsw_sp_lag_destroy(mlxsw_sp, lag_id); if (err) @@ -2272,9 +2299,6 @@ static int mlxsw_sp_port_lag_changed(struct mlxsw_sp_port *mlxsw_sp_port, return mlxsw_sp_port_lag_tx_en_set(mlxsw_sp_port, info->tx_enabled); } -static int mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport, - struct net_device *br_dev); - static int mlxsw_sp_port_vlan_link(struct mlxsw_sp_port *mlxsw_sp_port, struct net_device *vlan_dev) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index a23dc610d259..df279fc81c2e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -254,5 +254,6 @@ int mlxsw_sp_port_kill_vid(struct net_device *dev, __be16 __always_unused proto, u16 vid); int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 vfid, bool set, bool only_uc); +void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port); #endif diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 45479ef5bcf4..e4a3bd49069f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -936,6 +936,14 @@ static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port, vlan->vid_begin, vlan->vid_end, false); } +void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port) +{ + u16 vid; + + for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) + __mlxsw_sp_port_vlans_del(mlxsw_sp_port, vid, vid, false); +} + static int mlxsw_sp_port_fdb_static_del(struct mlxsw_sp_port *mlxsw_sp_port, const struct switchdev_obj_port_fdb *fdb) -- cgit v1.2.3 From 419332713581f0cbec6414f5e779afb79ddee3dd Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 27 Jan 2016 15:20:17 +0100 Subject: mlxsw: reg: Add the Switch Filtering DB Flush register When removing a net device from a bridge we should flush the FDB entries associated with this net device. Up until now, we relied upon bridge code to do that for us, but it is possible for user to prevent hardware from syncing with the software bridge (learning_sync=0), so we need to flush overselves. Add the Switch Filtering DB Flush (SFDF) register that is used to flush FDB entries according to different parameters (per-port, per-FID etc). Fixes: 56ade8fe3fe1 ("mlxsw: spectrum: Add initial support for Spectrum ASIC") Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 88 +++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 0c5237264e3e..815e5df06d8c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -1044,6 +1044,92 @@ static inline void mlxsw_reg_sftr_pack(char *payload, mlxsw_reg_sftr_port_mask_set(payload, port, 1); } +/* SFDF - Switch Filtering DB Flush + * -------------------------------- + * The switch filtering DB flush register is used to flush the FDB. + * Note that FDB notifications are flushed as well. + */ +#define MLXSW_REG_SFDF_ID 0x2013 +#define MLXSW_REG_SFDF_LEN 0x14 + +static const struct mlxsw_reg_info mlxsw_reg_sfdf = { + .id = MLXSW_REG_SFDF_ID, + .len = MLXSW_REG_SFDF_LEN, +}; + +/* reg_sfdf_swid + * Switch partition ID. + * Access: Index + */ +MLXSW_ITEM32(reg, sfdf, swid, 0x00, 24, 8); + +enum mlxsw_reg_sfdf_flush_type { + MLXSW_REG_SFDF_FLUSH_PER_SWID, + MLXSW_REG_SFDF_FLUSH_PER_FID, + MLXSW_REG_SFDF_FLUSH_PER_PORT, + MLXSW_REG_SFDF_FLUSH_PER_PORT_AND_FID, + MLXSW_REG_SFDF_FLUSH_PER_LAG, + MLXSW_REG_SFDF_FLUSH_PER_LAG_AND_FID, +}; + +/* reg_sfdf_flush_type + * Flush type. + * 0 - All SWID dynamic entries are flushed. + * 1 - All FID dynamic entries are flushed. + * 2 - All dynamic entries pointing to port are flushed. + * 3 - All FID dynamic entries pointing to port are flushed. + * 4 - All dynamic entries pointing to LAG are flushed. + * 5 - All FID dynamic entries pointing to LAG are flushed. + * Access: RW + */ +MLXSW_ITEM32(reg, sfdf, flush_type, 0x04, 28, 4); + +/* reg_sfdf_flush_static + * Static. + * 0 - Flush only dynamic entries. + * 1 - Flush both dynamic and static entries. + * Access: RW + */ +MLXSW_ITEM32(reg, sfdf, flush_static, 0x04, 24, 1); + +static inline void mlxsw_reg_sfdf_pack(char *payload, + enum mlxsw_reg_sfdf_flush_type type) +{ + MLXSW_REG_ZERO(sfdf, payload); + mlxsw_reg_sfdf_flush_type_set(payload, type); + mlxsw_reg_sfdf_flush_static_set(payload, true); +} + +/* reg_sfdf_fid + * FID to flush. + * Access: RW + */ +MLXSW_ITEM32(reg, sfdf, fid, 0x0C, 0, 16); + +/* reg_sfdf_system_port + * Port to flush. + * Access: RW + */ +MLXSW_ITEM32(reg, sfdf, system_port, 0x0C, 0, 16); + +/* reg_sfdf_port_fid_system_port + * Port to flush, pointed to by FID. + * Access: RW + */ +MLXSW_ITEM32(reg, sfdf, port_fid_system_port, 0x08, 0, 16); + +/* reg_sfdf_lag_id + * LAG ID to flush. + * Access: RW + */ +MLXSW_ITEM32(reg, sfdf, lag_id, 0x0C, 0, 10); + +/* reg_sfdf_lag_fid_lag_id + * LAG ID to flush, pointed to by FID. + * Access: RW + */ +MLXSW_ITEM32(reg, sfdf, lag_fid_lag_id, 0x08, 0, 10); + /* SLDR - Switch LAG Descriptor Register * ----------------------------------------- * The switch LAG descriptor register is populated by LAG descriptors. @@ -3121,6 +3207,8 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "SFGC"; case MLXSW_REG_SFTR_ID: return "SFTR"; + case MLXSW_REG_SFDF_ID: + return "SFDF"; case MLXSW_REG_SLDR_ID: return "SLDR"; case MLXSW_REG_SLCR_ID: -- cgit v1.2.3 From 039c49a6e6cf673a2bec572b3360209ec418a152 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 27 Jan 2016 15:20:18 +0100 Subject: mlxsw: spectrum: Flush FDB when leaving bridge As explained in previous commit, we should always take care of flushing the FDB in the driver and not rely on bridge code. We need to distinguish between two cases with regards to LAG: 1) Port is leaving LAG while LAG is bridged (or VLAN devices on top of it). In this case don't flush the FDB entries pointing to the LAG ID, as this will affect other ports still member in the LAG. Only flush the FDB when the last port in the LAG is leaving the bridge. 2) LAG device is leaving the bridge. In this case the CHANGEUPPER event is simply propagated to each member port, so make each port flush the FDB in its turn. Note that emptying a bridged LAG from ports creates an inconsistency between hardware and software. A user who later (< ageing_time) re-populates the LAG won't have any FDB entries pointing to the LAG ID in hardware, but they will be present in the software bridge's FDB. Currently there is no good solution to this problem, but this will be addressed by us in the future. In order to optimize the flushing process, flush by port or LAG ID if there are no VLAN interfaces on top of the port. Otherwise, flush using (Port / LAG ID, FID=VID} for each of the lower 4K FIDs. In the case of VLAN device simply flush using {Port / LAG ID, vFID} with the vFID to which the VLAN device is mapped to. Fixes: 56ade8fe3fe1 ("mlxsw: spectrum: Add initial support for Spectrum ASIC") Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 137 +++++++++++++++++++++++-- 1 file changed, 129 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 637a9d72fd93..217856bdd400 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1979,6 +1979,115 @@ static struct mlxsw_driver mlxsw_sp_driver = { .profile = &mlxsw_sp_config_profile, }; +static int +mlxsw_sp_port_fdb_flush_by_port(const struct mlxsw_sp_port *mlxsw_sp_port) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char sfdf_pl[MLXSW_REG_SFDF_LEN]; + + mlxsw_reg_sfdf_pack(sfdf_pl, MLXSW_REG_SFDF_FLUSH_PER_PORT); + mlxsw_reg_sfdf_system_port_set(sfdf_pl, mlxsw_sp_port->local_port); + + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdf), sfdf_pl); +} + +static int +mlxsw_sp_port_fdb_flush_by_port_fid(const struct mlxsw_sp_port *mlxsw_sp_port, + u16 fid) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char sfdf_pl[MLXSW_REG_SFDF_LEN]; + + mlxsw_reg_sfdf_pack(sfdf_pl, MLXSW_REG_SFDF_FLUSH_PER_PORT_AND_FID); + mlxsw_reg_sfdf_fid_set(sfdf_pl, fid); + mlxsw_reg_sfdf_port_fid_system_port_set(sfdf_pl, + mlxsw_sp_port->local_port); + + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdf), sfdf_pl); +} + +static int +mlxsw_sp_port_fdb_flush_by_lag_id(const struct mlxsw_sp_port *mlxsw_sp_port) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char sfdf_pl[MLXSW_REG_SFDF_LEN]; + + mlxsw_reg_sfdf_pack(sfdf_pl, MLXSW_REG_SFDF_FLUSH_PER_LAG); + mlxsw_reg_sfdf_lag_id_set(sfdf_pl, mlxsw_sp_port->lag_id); + + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdf), sfdf_pl); +} + +static int +mlxsw_sp_port_fdb_flush_by_lag_id_fid(const struct mlxsw_sp_port *mlxsw_sp_port, + u16 fid) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char sfdf_pl[MLXSW_REG_SFDF_LEN]; + + mlxsw_reg_sfdf_pack(sfdf_pl, MLXSW_REG_SFDF_FLUSH_PER_LAG_AND_FID); + mlxsw_reg_sfdf_fid_set(sfdf_pl, fid); + mlxsw_reg_sfdf_lag_fid_lag_id_set(sfdf_pl, mlxsw_sp_port->lag_id); + + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdf), sfdf_pl); +} + +static int +__mlxsw_sp_port_fdb_flush(const struct mlxsw_sp_port *mlxsw_sp_port) +{ + int err, last_err = 0; + u16 vid; + + for (vid = 1; vid < VLAN_N_VID - 1; vid++) { + err = mlxsw_sp_port_fdb_flush_by_port_fid(mlxsw_sp_port, vid); + if (err) + last_err = err; + } + + return last_err; +} + +static int +__mlxsw_sp_port_fdb_flush_lagged(const struct mlxsw_sp_port *mlxsw_sp_port) +{ + int err, last_err = 0; + u16 vid; + + for (vid = 1; vid < VLAN_N_VID - 1; vid++) { + err = mlxsw_sp_port_fdb_flush_by_lag_id_fid(mlxsw_sp_port, vid); + if (err) + last_err = err; + } + + return last_err; +} + +static int mlxsw_sp_port_fdb_flush(struct mlxsw_sp_port *mlxsw_sp_port) +{ + if (!list_empty(&mlxsw_sp_port->vports_list)) + if (mlxsw_sp_port->lagged) + return __mlxsw_sp_port_fdb_flush_lagged(mlxsw_sp_port); + else + return __mlxsw_sp_port_fdb_flush(mlxsw_sp_port); + else + if (mlxsw_sp_port->lagged) + return mlxsw_sp_port_fdb_flush_by_lag_id(mlxsw_sp_port); + else + return mlxsw_sp_port_fdb_flush_by_port(mlxsw_sp_port); +} + +static int mlxsw_sp_vport_fdb_flush(struct mlxsw_sp_port *mlxsw_sp_vport) +{ + u16 vfid = mlxsw_sp_vport_vfid_get(mlxsw_sp_vport); + u16 fid = mlxsw_sp_vfid_to_fid(vfid); + + if (mlxsw_sp_vport->lagged) + return mlxsw_sp_port_fdb_flush_by_lag_id_fid(mlxsw_sp_vport, + fid); + else + return mlxsw_sp_port_fdb_flush_by_port_fid(mlxsw_sp_vport, fid); +} + static bool mlxsw_sp_port_dev_check(const struct net_device *dev) { return dev->netdev_ops == &mlxsw_sp_port_netdev_ops; @@ -2006,10 +2115,14 @@ static int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port) return 0; } -static int mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port) +static int mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port, + bool flush_fdb) { struct net_device *dev = mlxsw_sp_port->dev; + if (flush_fdb && mlxsw_sp_port_fdb_flush(mlxsw_sp_port)) + netdev_err(mlxsw_sp_port->dev, "Failed to flush FDB\n"); + mlxsw_sp_port->learning = 0; mlxsw_sp_port->learning_sync = 0; mlxsw_sp_port->uc_flood = 0; @@ -2201,7 +2314,8 @@ err_col_port_enable: } static int mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport, - struct net_device *br_dev); + struct net_device *br_dev, + bool flush_fdb); static int mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port, struct net_device *lag_dev) @@ -2236,18 +2350,20 @@ static int mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port, continue; br_dev = mlxsw_sp_vport_br_get(mlxsw_sp_vport); - mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport, br_dev); + mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport, br_dev, false); } if (mlxsw_sp_port->bridged) { mlxsw_sp_port_active_vlans_del(mlxsw_sp_port); - mlxsw_sp_port_bridge_leave(mlxsw_sp_port); + mlxsw_sp_port_bridge_leave(mlxsw_sp_port, false); if (lag->ref_count == 1) mlxsw_sp_master_bridge_dec(mlxsw_sp, NULL); } if (lag->ref_count == 1) { + if (mlxsw_sp_port_fdb_flush_by_lag_id(mlxsw_sp_port)) + netdev_err(mlxsw_sp_port->dev, "Failed to flush FDB\n"); err = mlxsw_sp_lag_destroy(mlxsw_sp, lag_id); if (err) return err; @@ -2336,7 +2452,7 @@ static int mlxsw_sp_port_vlan_unlink(struct mlxsw_sp_port *mlxsw_sp_port, struct net_device *br_dev; br_dev = mlxsw_sp_vport_br_get(mlxsw_sp_vport); - mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport, br_dev); + mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport, br_dev, true); } mlxsw_sp_vport->dev = mlxsw_sp_port->dev; @@ -2398,7 +2514,8 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *dev, } mlxsw_sp_master_bridge_inc(mlxsw_sp, upper_dev); } else { - err = mlxsw_sp_port_bridge_leave(mlxsw_sp_port); + err = mlxsw_sp_port_bridge_leave(mlxsw_sp_port, + true); mlxsw_sp_master_bridge_dec(mlxsw_sp, upper_dev); if (err) { netdev_err(dev, "Failed to leave bridge\n"); @@ -2565,7 +2682,8 @@ static void mlxsw_sp_br_vfid_destroy(struct mlxsw_sp *mlxsw_sp, } static int mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport, - struct net_device *br_dev) + struct net_device *br_dev, + bool flush_fdb) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_vport->mlxsw_sp; u16 vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport); @@ -2628,6 +2746,9 @@ static int mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport, goto err_vport_flood_set; } + if (flush_fdb && mlxsw_sp_vport_fdb_flush(mlxsw_sp_vport)) + netdev_err(dev, "Failed to flush FDB\n"); + /* Switch between the vFIDs and destroy the old one if needed. */ new_vfid->nr_vports++; mlxsw_sp_vport->vport.vfid = new_vfid; @@ -2801,7 +2922,7 @@ static int mlxsw_sp_netdevice_vport_event(struct net_device *dev, if (!mlxsw_sp_vport) return NOTIFY_DONE; err = mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport, - upper_dev); + upper_dev, true); if (err) { netdev_err(dev, "Failed to leave bridge\n"); return NOTIFY_BAD; -- cgit v1.2.3 From 9cb026ebb8ab76829a8d8e4bbd057168ac38fb86 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 27 Jan 2016 15:20:19 +0100 Subject: mlxsw: spectrum: Don't forward packets when STP state is DISABLED When STP state is set to DISABLED the port is assumed to be inactive, but currently we forward packets ingressing through it. Instead, set the port's STP state in hardware to DISCARDING, which means it doesn't forward packets or perform any learning, but it does trap control packets. However, these packets will be dropped by bridge code, which results in the expected behavior. Fixes: 56ade8fe3fe1 ("mlxsw: spectrum: Add initial support for Spectrum ASIC") Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index e4a3bd49069f..5087e742dceb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -124,7 +124,6 @@ static int mlxsw_sp_port_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port, int err; switch (state) { - case BR_STATE_DISABLED: /* fall-through */ case BR_STATE_FORWARDING: spms_state = MLXSW_REG_SPMS_STATE_FORWARDING; break; @@ -132,6 +131,7 @@ static int mlxsw_sp_port_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port, case BR_STATE_LEARNING: spms_state = MLXSW_REG_SPMS_STATE_LEARNING; break; + case BR_STATE_DISABLED: /* fall-through */ case BR_STATE_BLOCKING: spms_state = MLXSW_REG_SPMS_STATE_DISCARDING; break; -- cgit v1.2.3 From 454911333b1d86e1d58a557be271bc6b7e9e7f10 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 27 Jan 2016 15:20:20 +0100 Subject: mlxsw: spectrum: Disable learning according to STP state When port is put into LISTENING state it shouldn't populate the FDB, so set the port's STP state in hardware to DISCARDING instead of LEARNING. It will therefore keep listening to BPDU packets, but discard other non-control packets and won't perform any learning. Fixes: 56ade8fe3fe1 ("mlxsw: spectrum: Add initial support for Spectrum ASIC") Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 5087e742dceb..5e6095dd7d97 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -127,10 +127,10 @@ static int mlxsw_sp_port_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port, case BR_STATE_FORWARDING: spms_state = MLXSW_REG_SPMS_STATE_FORWARDING; break; - case BR_STATE_LISTENING: /* fall-through */ case BR_STATE_LEARNING: spms_state = MLXSW_REG_SPMS_STATE_LEARNING; break; + case BR_STATE_LISTENING: /* fall-through */ case BR_STATE_DISABLED: /* fall-through */ case BR_STATE_BLOCKING: spms_state = MLXSW_REG_SPMS_STATE_DISCARDING; -- cgit v1.2.3 From 45827d780aab533a777f965798018118b373cc0b Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 27 Jan 2016 15:20:21 +0100 Subject: mlxsw: spectrum: Notify bridge's FDB only based on learning_sync When we disable learning on bridge port we should still update the software bridge's FDB when entry pointing to this bridge port is aged-out. We can otherwise have an inconsistency between software and hardware tables. Fixes: 8a1ab5d76639 ("mlxsw: spectrum: Implement FDB add/remove/dump for LAG") Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 5e6095dd7d97..e1cbc59fced3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1202,14 +1202,14 @@ static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = { .switchdev_port_obj_dump = mlxsw_sp_port_obj_dump, }; -static void mlxsw_sp_fdb_call_notifiers(bool learning, bool learning_sync, - bool adding, char *mac, u16 vid, +static void mlxsw_sp_fdb_call_notifiers(bool learning_sync, bool adding, + char *mac, u16 vid, struct net_device *dev) { struct switchdev_notifier_fdb_info info; unsigned long notifier_type; - if (learning && learning_sync) { + if (learning_sync) { info.addr = mac; info.vid = vid; notifier_type = adding ? SWITCHDEV_FDB_ADD : SWITCHDEV_FDB_DEL; @@ -1265,8 +1265,7 @@ do_fdb_op: if (!do_notification) return; - mlxsw_sp_fdb_call_notifiers(mlxsw_sp_port->learning, - mlxsw_sp_port->learning_sync, + mlxsw_sp_fdb_call_notifiers(mlxsw_sp_port->learning_sync, adding, mac, vid, mlxsw_sp_port->dev); return; @@ -1327,9 +1326,8 @@ do_fdb_op: if (!do_notification) return; - mlxsw_sp_fdb_call_notifiers(mlxsw_sp_port->learning, - mlxsw_sp_port->learning_sync, - adding, mac, vid, + mlxsw_sp_fdb_call_notifiers(mlxsw_sp_port->learning_sync, adding, mac, + vid, mlxsw_sp_lag_get(mlxsw_sp, lag_id)->dev); return; -- cgit v1.2.3 From 004f85ea8258a2ffecdeecd154bdbe08409c13a4 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 27 Jan 2016 15:20:22 +0100 Subject: mlxsw: spectrum: Don't report VLAN for 802.1D FDB entries When dumping the hardware FDB we should report entries pointing to VLAN devices with VLAN 0, as packets coming into the bridge are untagged. Likewise, pass FDB_{ADD,DEL} notifications with VLAN 0 for these devices. Fixes: 54a732018d8e ("mlxsw: spectrum: Adjust switchdev ops for VLAN devices") Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 31 +++++++++++----------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index e1cbc59fced3..26e85b759e89 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1051,7 +1051,7 @@ static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port, switchdev_obj_dump_cb_t *cb) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - u16 vport_vid = 0, vport_fid = 0; + u16 vport_fid = 0; char *sfd_pl; char mac[ETH_ALEN]; u16 fid; @@ -1072,7 +1072,6 @@ static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port, tmp = mlxsw_sp_vport_vfid_get(mlxsw_sp_port); vport_fid = mlxsw_sp_vfid_to_fid(tmp); - vport_vid = mlxsw_sp_vport_vid_get(mlxsw_sp_port); } mlxsw_reg_sfd_pack(sfd_pl, MLXSW_REG_SFD_OP_QUERY_DUMP, 0); @@ -1096,12 +1095,13 @@ static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port, mlxsw_reg_sfd_uc_unpack(sfd_pl, i, mac, &fid, &local_port); if (local_port == mlxsw_sp_port->local_port) { - if (vport_fid && vport_fid != fid) - continue; - else if (vport_fid) - fdb->vid = vport_vid; - else + if (vport_fid && vport_fid == fid) + fdb->vid = 0; + else if (!vport_fid && + !mlxsw_sp_fid_is_vfid(fid)) fdb->vid = fid; + else + continue; ether_addr_copy(fdb->addr, mac); fdb->ndm_state = NUD_REACHABLE; err = cb(&fdb->obj); @@ -1114,12 +1114,13 @@ static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port, mac, &fid, &lag_id); if (mlxsw_sp_port == mlxsw_sp_lag_rep_port(mlxsw_sp, lag_id)) { - if (vport_fid && vport_fid != fid) - continue; - else if (vport_fid) - fdb->vid = vport_vid; - else + if (vport_fid && vport_fid == fid) + fdb->vid = 0; + else if (!vport_fid && + !mlxsw_sp_fid_is_vfid(fid)) fdb->vid = fid; + else + continue; ether_addr_copy(fdb->addr, mac); fdb->ndm_state = NUD_REACHABLE; err = cb(&fdb->obj); @@ -1245,7 +1246,7 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp, netdev_err(mlxsw_sp_port->dev, "Failed to find a matching vPort following FDB notification\n"); goto just_remove; } - vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport); + vid = 0; /* Override the physical port with the vPort. */ mlxsw_sp_port = mlxsw_sp_vport; } else { @@ -1305,8 +1306,8 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp, goto just_remove; } - vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport); - lag_vid = vid; + lag_vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport); + vid = 0; /* Override the physical port with the vPort. */ mlxsw_sp_port = mlxsw_sp_vport; } else { -- cgit v1.2.3 From e43aca22ed039af235acc2ee0384f943c1fbfe83 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 27 Jan 2016 15:20:23 +0100 Subject: mlxsw: spectrum: Use correct netdev when notifying bridge LAG FDB entries pointing to VLAN devices should be reported to the bridge with the matching VLAN device and not the underlying LAG device. Fixes: aac78a440887 ("mlxsw: spectrum: Adjust FDB notifications for VLAN devices") Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 26e85b759e89..3102c1422262 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1281,6 +1281,7 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp, bool adding) { struct mlxsw_sp_port *mlxsw_sp_port; + struct net_device *dev; char mac[ETH_ALEN]; u16 lag_vid = 0; u16 lag_id; @@ -1307,10 +1308,12 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp, } lag_vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport); + dev = mlxsw_sp_vport->dev; vid = 0; /* Override the physical port with the vPort. */ mlxsw_sp_port = mlxsw_sp_vport; } else { + dev = mlxsw_sp_lag_get(mlxsw_sp, lag_id)->dev; vid = fid; } @@ -1328,8 +1331,7 @@ do_fdb_op: if (!do_notification) return; mlxsw_sp_fdb_call_notifiers(mlxsw_sp_port->learning_sync, adding, mac, - vid, - mlxsw_sp_lag_get(mlxsw_sp, lag_id)->dev); + vid, dev); return; just_remove: -- cgit v1.2.3 From 304f51584f4591789539c0d37fc359bc129a4ff0 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 27 Jan 2016 15:20:24 +0100 Subject: mlxsw: spectrum: Dump LAG FDB records only once LAG FDB records can only point to LAG devices or VLAN devices configured on top of them. Therefore, when dumping the FDB we shouldn't associate these records with the underlying physical ports. Fixes: 8a1ab5d76639 ("mlxsw: spectrum: Implement FDB add/remove/dump for LAG") Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 3102c1422262..2b8b3745eaf0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1048,7 +1048,8 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port, struct switchdev_obj_port_fdb *fdb, - switchdev_obj_dump_cb_t *cb) + switchdev_obj_dump_cb_t *cb, + struct net_device *orig_dev) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; u16 vport_fid = 0; @@ -1114,6 +1115,12 @@ static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port, mac, &fid, &lag_id); if (mlxsw_sp_port == mlxsw_sp_lag_rep_port(mlxsw_sp, lag_id)) { + /* LAG records can only point to LAG + * devices or VLAN devices on top. + */ + if (!netif_is_lag_master(orig_dev) && + !is_vlan_dev(orig_dev)) + continue; if (vport_fid && vport_fid == fid) fdb->vid = 0; else if (!vport_fid && @@ -1185,7 +1192,8 @@ static int mlxsw_sp_port_obj_dump(struct net_device *dev, break; case SWITCHDEV_OBJ_ID_PORT_FDB: err = mlxsw_sp_port_fdb_dump(mlxsw_sp_port, - SWITCHDEV_OBJ_PORT_FDB(obj), cb); + SWITCHDEV_OBJ_PORT_FDB(obj), cb, + obj->orig_dev); break; default: err = -EOPNOTSUPP; -- cgit v1.2.3 From 3f47f867814cdb08cd43d4b82f95bfde4a9ae579 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 27 Jan 2016 15:20:25 +0100 Subject: mlxsw: spectrum: Compare local ports instead of pointers When dumping the FDB we can't compare the actual pointers of the ports structs, as it's possible the struct represents a vPort instead of the underlying physical port. Solve this by comparing the local port number instead, as it's shared between the physical ports and all the vPorts on top of him. Fixes: 54a732018d8e ("mlxsw: spectrum: Adjust switchdev ops for VLAN devices") Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 2b8b3745eaf0..f2ab7cd09cf3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1052,6 +1052,7 @@ static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port, struct net_device *orig_dev) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + struct mlxsw_sp_port *tmp; u16 vport_fid = 0; char *sfd_pl; char mac[ETH_ALEN]; @@ -1113,8 +1114,9 @@ static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port, case MLXSW_REG_SFD_REC_TYPE_UNICAST_LAG: mlxsw_reg_sfd_uc_lag_unpack(sfd_pl, i, mac, &fid, &lag_id); - if (mlxsw_sp_port == - mlxsw_sp_lag_rep_port(mlxsw_sp, lag_id)) { + tmp = mlxsw_sp_lag_rep_port(mlxsw_sp, lag_id); + if (tmp && tmp->local_port == + mlxsw_sp_port->local_port) { /* LAG records can only point to LAG * devices or VLAN devices on top. */ -- cgit v1.2.3 From bbeeda27abc516af51ddd93c555b6324559dbb3b Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 27 Jan 2016 15:20:26 +0100 Subject: mlxsw: reg: Use correct offset in field definiton The rx_lane, tx_lane and module fields in the PMLP register don't have an additional offset besides the base one (0x04), so set it to 0x00. Fixes: 4ec14b7634b2 ("mlxsw: Add interface to access registers and process events") Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 815e5df06d8c..bb77e2207804 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -1787,20 +1787,20 @@ MLXSW_ITEM32(reg, pmlp, width, 0x00, 0, 8); * Module number. * Access: RW */ -MLXSW_ITEM32_INDEXED(reg, pmlp, module, 0x04, 0, 8, 0x04, 0, false); +MLXSW_ITEM32_INDEXED(reg, pmlp, module, 0x04, 0, 8, 0x04, 0x00, false); /* reg_pmlp_tx_lane * Tx Lane. When rxtx field is cleared, this field is used for Rx as well. * Access: RW */ -MLXSW_ITEM32_INDEXED(reg, pmlp, tx_lane, 0x04, 16, 2, 0x04, 16, false); +MLXSW_ITEM32_INDEXED(reg, pmlp, tx_lane, 0x04, 16, 2, 0x04, 0x00, false); /* reg_pmlp_rx_lane * Rx Lane. When rxtx field is cleared, this field is ignored and Rx lane is * equal to Tx lane. * Access: RW */ -MLXSW_ITEM32_INDEXED(reg, pmlp, rx_lane, 0x04, 24, 2, 0x04, 24, false); +MLXSW_ITEM32_INDEXED(reg, pmlp, rx_lane, 0x04, 24, 2, 0x04, 0x00, false); static inline void mlxsw_reg_pmlp_pack(char *payload, u8 local_port) { -- cgit v1.2.3 From c731f0e3493cc9031a0aceea6a50c70beed23e6d Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 25 Jan 2016 23:24:12 +0100 Subject: net: Fix dependencies for !HAS_IOMEM archs Not every arch has io memory. So, unbreak the build by fixing the dependencies. Signed-off-by: Richard Weinberger Signed-off-by: David S. Miller --- drivers/net/ethernet/ezchip/Kconfig | 1 + drivers/net/phy/Kconfig | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/ezchip/Kconfig b/drivers/net/ethernet/ezchip/Kconfig index 48ecbc8aaaea..b423ad380b6a 100644 --- a/drivers/net/ethernet/ezchip/Kconfig +++ b/drivers/net/ethernet/ezchip/Kconfig @@ -18,6 +18,7 @@ if NET_VENDOR_EZCHIP config EZCHIP_NPS_MANAGEMENT_ENET tristate "EZchip NPS management enet support" depends on OF_IRQ && OF_NET + depends on HAS_IOMEM ---help--- Simple LAN device for debug or management purposes. Device supports interrupts for RX and TX(completion). diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 60994a83a0d6..f0a77020037a 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -186,6 +186,7 @@ config MDIO_GPIO config MDIO_OCTEON tristate "Support for MDIO buses on Octeon and ThunderX SOCs" depends on 64BIT + depends on HAS_IOMEM help This module provides a driver for the Octeon and ThunderX MDIO -- cgit v1.2.3 From 96c5d076f0a5e2023ecdb44d8261f87641ee71e0 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 15 Oct 2014 15:00:47 -0400 Subject: drm/vmwgfx: respect 'nomodeset' Signed-off-by: Rob Clark Reviewed-by: Thomas Hellstrom . Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index c49812b80dd0..24fb348a44e1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -25,6 +25,7 @@ * **************************************************************************/ #include +#include #include #include "vmwgfx_drv.h" @@ -1538,6 +1539,12 @@ static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent) static int __init vmwgfx_init(void) { int ret; + +#ifdef CONFIG_VGA_CONSOLE + if (vgacon_text_force()) + return -EINVAL; +#endif + ret = drm_pci_init(&driver, &vmw_pci_driver); if (ret) DRM_ERROR("Failed initializing DRM.\n"); -- cgit v1.2.3 From 6ed742363b9c3d1d038f013591d57a606ae2c261 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Tue, 26 Jan 2016 15:12:30 +0100 Subject: of: of_mdio: Ensure mdio device is a PHY of_phy_find_device() is used to find the phy device associated with a device node. It is expected the node is for a PHY device, but in fact it could of been probed as a generic MDIO device. Ensure the device is a PHY before returning it. Fixes: a9049e0c513c ("mdio: Add support for mdio drivers.") Reported-by: Aaro Koskinen Reported-by: Olof Johansson Signed-off-by: Andrew Lunn Tested-by: Aaro Koskinen Signed-off-by: David S. Miller --- drivers/of/of_mdio.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 86829f8064a6..b5aa004a24b6 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -256,11 +256,19 @@ static int of_phy_match(struct device *dev, void *phy_np) struct phy_device *of_phy_find_device(struct device_node *phy_np) { struct device *d; + struct mdio_device *mdiodev; + if (!phy_np) return NULL; d = bus_find_device(&mdio_bus_type, NULL, phy_np, of_phy_match); - return d ? to_phy_device(d) : NULL; + if (d) { + mdiodev = to_mdio_device(d); + if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY) + return to_phy_device(d); + } + + return NULL; } EXPORT_SYMBOL(of_phy_find_device); -- cgit v1.2.3 From 3b89624ab54b9dc2d92fc08ce2670e5f19ad8ec8 Mon Sep 17 00:00:00 2001 From: Nicolas Schichan Date: Tue, 26 Jan 2016 16:12:35 +0100 Subject: net: mv643xx_eth: fix packet corruption with TSO and tiny unaligned packets. The code in txq_put_data() would use txq->tx_curr_desc to index the tso_hdrs/tso_hdrs_dma buffers, for less than 8 bytes unaligned fragments, which is already moved to the next descriptor at the beginning of the function. If that fragment was the last of the the skb, the next skb would use that same space to place the ip headers, overwritting that small fragment data. Fixes: 91986fd3d335 (net: mv643xx_eth: Ensure proper data alignment in TSO TX path) Signed-off-by: Nicolas Schichan Reviewed-by: Philipp Kirchhofer Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index a0c03834a2f7..55831188bc32 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -762,10 +762,10 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq, if (length <= 8 && (uintptr_t)data & 0x7) { /* Copy unaligned small data fragment to TSO header data area */ - memcpy(txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE, + memcpy(txq->tso_hdrs + tx_index * TSO_HEADER_SIZE, data, length); desc->buf_ptr = txq->tso_hdrs_dma - + txq->tx_curr_desc * TSO_HEADER_SIZE; + + tx_index * TSO_HEADER_SIZE; } else { /* Alignment is okay, map buffer and hand off to hardware */ txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE; -- cgit v1.2.3 From 7d0105b5334b9722b7d33acad613096dfcf3330e Mon Sep 17 00:00:00 2001 From: Malcolm Crossley Date: Tue, 26 Jan 2016 17:12:44 +0000 Subject: xen-netfront: request Tx response events more often Trying to batch Tx response events results in poor performance because this delays freeing the transmitted skbs. Instead use the standard RING_FINAL_CHECK_FOR_RESPONSES() macro to be notified once the next Tx response is placed on the ring. Signed-off-by: Malcolm Crossley Signed-off-by: David Vrabel Signed-off-by: David S. Miller --- drivers/net/xen-netfront.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index d6abf191122a..96ccd4e943db 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -364,6 +364,7 @@ static void xennet_tx_buf_gc(struct netfront_queue *queue) RING_IDX cons, prod; unsigned short id; struct sk_buff *skb; + bool more_to_do; BUG_ON(!netif_carrier_ok(queue->info->netdev)); @@ -398,18 +399,8 @@ static void xennet_tx_buf_gc(struct netfront_queue *queue) queue->tx.rsp_cons = prod; - /* - * Set a new event, then check for race with update of tx_cons. - * Note that it is essential to schedule a callback, no matter - * how few buffers are pending. Even if there is space in the - * transmit ring, higher layers may be blocked because too much - * data is outstanding: in such cases notification from Xen is - * likely to be the only kick that we'll get. - */ - queue->tx.sring->rsp_event = - prod + ((queue->tx.sring->req_prod - prod) >> 1) + 1; - mb(); /* update shared area */ - } while ((cons == prod) && (prod != queue->tx.sring->rsp_prod)); + RING_FINAL_CHECK_FOR_RESPONSES(&queue->tx, more_to_do); + } while (more_to_do); xennet_maybe_wake_tx(queue); } -- cgit v1.2.3 From 4f2c6ae5c64c353fb1b0425e4747e5603feadba1 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 27 Jan 2016 15:16:43 +0100 Subject: switchdev: Require RTNL mutex to be held when sending FDB notifications When switchdev drivers process FDB notifications from the underlying device they resolve the netdev to which the entry points to and notify the bridge using the switchdev notifier. However, since the RTNL mutex is not held there is nothing preventing the netdev from disappearing in the middle, which will cause br_switchdev_event() to dereference a non-existing netdev. Make switchdev drivers hold the lock at the beginning of the notification processing session and release it once it ends, after notifying the bridge. Also, remove switchdev_mutex and fdb_lock, as they are no longer needed when RTNL mutex is held. Fixes: 03bf0c281234 ("switchdev: introduce switchdev notifier") Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 1 - drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 8 +++----- drivers/net/ethernet/rocker/rocker.c | 2 ++ net/bridge/br.c | 3 +-- net/switchdev/switchdev.c | 15 ++++++++------- 5 files changed, 14 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index df279fc81c2e..7f42eb1c320e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -120,7 +120,6 @@ struct mlxsw_sp { } fdb_notify; #define MLXSW_SP_DEFAULT_AGEING_TIME 300 u32 ageing_time; - struct mutex fdb_lock; /* Make sure FDB sessions are atomic. */ struct mlxsw_sp_upper master_bridge; struct mlxsw_sp_upper lags[MLXSW_SP_LAG_MAX]; }; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index f2ab7cd09cf3..e492ca2cdecd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include "spectrum.h" @@ -1068,7 +1069,6 @@ static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port, if (!sfd_pl) return -ENOMEM; - mutex_lock(&mlxsw_sp_port->mlxsw_sp->fdb_lock); if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) { u16 tmp; @@ -1142,7 +1142,6 @@ static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port, } while (num_rec == MLXSW_REG_SFD_REC_MAX_COUNT); out: - mutex_unlock(&mlxsw_sp_port->mlxsw_sp->fdb_lock); kfree(sfd_pl); return stored_err ? stored_err : err; } @@ -1393,7 +1392,7 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work) mlxsw_sp = container_of(work, struct mlxsw_sp, fdb_notify.dw.work); - mutex_lock(&mlxsw_sp->fdb_lock); + rtnl_lock(); do { mlxsw_reg_sfn_pack(sfn_pl); err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl); @@ -1406,7 +1405,7 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work) mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i); } while (num_rec); - mutex_unlock(&mlxsw_sp->fdb_lock); + rtnl_unlock(); kfree(sfn_pl); mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp); @@ -1421,7 +1420,6 @@ static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp) dev_err(mlxsw_sp->bus_info->dev, "Failed to set default ageing time\n"); return err; } - mutex_init(&mlxsw_sp->fdb_lock); INIT_DELAYED_WORK(&mlxsw_sp->fdb_notify.dw, mlxsw_sp_fdb_notify_work); mlxsw_sp->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL; mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp); diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index a4ab71d43e4e..166a7fc87e2f 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -3531,12 +3531,14 @@ static void rocker_port_fdb_learn_work(struct work_struct *work) info.addr = lw->addr; info.vid = lw->vid; + rtnl_lock(); if (learned && removing) call_switchdev_notifiers(SWITCHDEV_FDB_DEL, lw->rocker_port->dev, &info.info); else if (learned && !removing) call_switchdev_notifiers(SWITCHDEV_FDB_ADD, lw->rocker_port->dev, &info.info); + rtnl_unlock(); rocker_port_kfree(lw->trans, work); } diff --git a/net/bridge/br.c b/net/bridge/br.c index a1abe4936fe1..3addc05b9a16 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -121,6 +121,7 @@ static struct notifier_block br_device_notifier = { .notifier_call = br_device_event }; +/* called with RTNL */ static int br_switchdev_event(struct notifier_block *unused, unsigned long event, void *ptr) { @@ -130,7 +131,6 @@ static int br_switchdev_event(struct notifier_block *unused, struct switchdev_notifier_fdb_info *fdb_info; int err = NOTIFY_DONE; - rtnl_lock(); p = br_port_get_rtnl(dev); if (!p) goto out; @@ -155,7 +155,6 @@ static int br_switchdev_event(struct notifier_block *unused, } out: - rtnl_unlock(); return err; } diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index ebc661d3b6e3..47f7da58a7f0 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -567,7 +568,6 @@ int switchdev_port_obj_dump(struct net_device *dev, struct switchdev_obj *obj, } EXPORT_SYMBOL_GPL(switchdev_port_obj_dump); -static DEFINE_MUTEX(switchdev_mutex); static RAW_NOTIFIER_HEAD(switchdev_notif_chain); /** @@ -582,9 +582,9 @@ int register_switchdev_notifier(struct notifier_block *nb) { int err; - mutex_lock(&switchdev_mutex); + rtnl_lock(); err = raw_notifier_chain_register(&switchdev_notif_chain, nb); - mutex_unlock(&switchdev_mutex); + rtnl_unlock(); return err; } EXPORT_SYMBOL_GPL(register_switchdev_notifier); @@ -600,9 +600,9 @@ int unregister_switchdev_notifier(struct notifier_block *nb) { int err; - mutex_lock(&switchdev_mutex); + rtnl_lock(); err = raw_notifier_chain_unregister(&switchdev_notif_chain, nb); - mutex_unlock(&switchdev_mutex); + rtnl_unlock(); return err; } EXPORT_SYMBOL_GPL(unregister_switchdev_notifier); @@ -616,16 +616,17 @@ EXPORT_SYMBOL_GPL(unregister_switchdev_notifier); * Call all network notifier blocks. This should be called by driver * when it needs to propagate hardware event. * Return values are same as for atomic_notifier_call_chain(). + * rtnl_lock must be held. */ int call_switchdev_notifiers(unsigned long val, struct net_device *dev, struct switchdev_notifier_info *info) { int err; + ASSERT_RTNL(); + info->dev = dev; - mutex_lock(&switchdev_mutex); err = raw_notifier_call_chain(&switchdev_notif_chain, val, info); - mutex_unlock(&switchdev_mutex); return err; } EXPORT_SYMBOL_GPL(call_switchdev_notifiers); -- cgit v1.2.3 From d791a8c60e9cbd1c4fecbc5c86ff59c7ffe137e8 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Wed, 27 Jan 2016 18:22:44 -0800 Subject: storvsc: Install the storvsc specific timeout handler for FC devices The default timeout routine used for FC transport is not suitable for FC devices managed by storvsc since FC devices managed by storvsc driver do not have an rport associated with them. Use the time out handler used for SCSI devices for FC devices as well. Signed-off-by: K. Y. Srinivasan Reviewed-by: Alex Ng Tested-by: Vivek Yadav Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/storvsc_drv.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 41c115c230d9..622f64a98a9e 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -42,6 +42,7 @@ #include #include #include +#include /* * All wire protocol details (storage protocol between the guest and the host) @@ -1770,6 +1771,11 @@ static int __init storvsc_drv_init(void) fc_transport_template = fc_attach_transport(&fc_transport_functions); if (!fc_transport_template) return -ENODEV; + + /* + * Install Hyper-V specific timeout handler. + */ + fc_transport_template->eh_timed_out = storvsc_eh_timed_out; #endif ret = vmbus_driver_register(&storvsc_drv); -- cgit v1.2.3 From 98441221708a092eb6d3d05142cf842a95aba152 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Wed, 27 Jan 2016 18:22:45 -0800 Subject: storvsc: Use the specified target ID in device lookup The current code assumes that there is only one target in device lookup. Fix this bug. This will alow us to correctly handle hot reomoval of LUNs. Signed-off-by: K. Y. Srinivasan Reviewed-by: Alex Ng Tested-by: Vivek Yadav Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/storvsc_drv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 622f64a98a9e..132b16861954 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -478,19 +478,18 @@ struct hv_host_device { struct storvsc_scan_work { struct work_struct work; struct Scsi_Host *host; - uint lun; + u8 lun; + u8 tgt_id; }; static void storvsc_device_scan(struct work_struct *work) { struct storvsc_scan_work *wrk; - uint lun; struct scsi_device *sdev; wrk = container_of(work, struct storvsc_scan_work, work); - lun = wrk->lun; - sdev = scsi_device_lookup(wrk->host, 0, 0, lun); + sdev = scsi_device_lookup(wrk->host, 0, wrk->tgt_id, wrk->lun); if (!sdev) goto done; scsi_rescan_device(&sdev->sdev_gendev); @@ -541,7 +540,7 @@ static void storvsc_remove_lun(struct work_struct *work) if (!scsi_host_get(wrk->host)) goto done; - sdev = scsi_device_lookup(wrk->host, 0, 0, wrk->lun); + sdev = scsi_device_lookup(wrk->host, 0, wrk->tgt_id, wrk->lun); if (sdev) { scsi_remove_device(sdev); @@ -941,6 +940,7 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, wrk->host = host; wrk->lun = vm_srb->lun; + wrk->tgt_id = vm_srb->target_id; INIT_WORK(&wrk->work, process_err_fn); schedule_work(&wrk->work); } -- cgit v1.2.3 From 76e9521fc9a400c62585b5fc2465d1103f6ce836 Mon Sep 17 00:00:00 2001 From: "Daniel H. Hemmingsen" Date: Tue, 10 Nov 2015 19:35:30 +0100 Subject: Staging: panel: Fixed a spacing after cast coding style issue Fixed a spacing after cast coding style issue. Signed-off-by: Daniel H. Hemmingsen Acked-by: Willy Tarreau Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 79ac19246548..96920efa8fc7 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -1788,7 +1788,7 @@ static void phys_scan_contacts(void) gndmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i; /* grounded inputs are signals 40-44 */ - phys_read |= (pmask_t) gndmask << 40; + phys_read |= (pmask_t)gndmask << 40; if (bitmask != gndmask) { /* -- cgit v1.2.3 From df44f1504b4d04e523ccc6469a53d37380c9bfbd Mon Sep 17 00:00:00 2001 From: Ricardo Ruedas Date: Tue, 8 Dec 2015 22:30:40 +0100 Subject: staging: panel: remove warnings line over 80 characters This patch removes the warnings reported by checkpatch.pl for line over 80 characters. Signed-off-by: Ricardo Ruedas Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 96920efa8fc7..1e67e26a9e0c 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -947,7 +947,8 @@ static void lcd_clear_fast_s(void) lcd_send_serial(0x5F); /* R/W=W, RS=1 */ lcd_send_serial(' ' & 0x0F); lcd_send_serial((' ' >> 4) & 0x0F); - usleep_range(40, 100); /* the shortest data takes at least 40 us */ + /* the shortest data takes at least 40 us */ + usleep_range(40, 100); } spin_unlock_irq(&pprt_lock); -- cgit v1.2.3 From 05c153fa1990a9450d99b2f1a858873a912694d2 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 18 Dec 2015 14:06:14 +0100 Subject: staging: update panel driver's author address I'm realizing that I sometimes miss e-mails sent to my old address, so better update it. Since I only have the relevant hardware at my work place, let's use this address so that I can test code if needed. Signed-off-by: Willy Tarreau Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 2 +- drivers/staging/panel/TODO | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 30aca4aa5467..48d09cca8505 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10401,7 +10401,7 @@ S: Maintained F: drivers/staging/olpc_dcon/ STAGING - PARALLEL LCD/KEYPAD PANEL DRIVER -M: Willy Tarreau +M: Willy Tarreau S: Odd Fixes F: drivers/staging/panel/ diff --git a/drivers/staging/panel/TODO b/drivers/staging/panel/TODO index 2db3f994b632..3a6405ab91e0 100644 --- a/drivers/staging/panel/TODO +++ b/drivers/staging/panel/TODO @@ -5,4 +5,4 @@ TODO: - see if all of this could be easier done in userspace instead. Please send patches to Greg Kroah-Hartman and -Willy Tarreau +Willy Tarreau -- cgit v1.2.3 From 7a725972e212c165c7991d06ede952d4c3b6387a Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Sun, 3 Jan 2016 20:32:03 +0100 Subject: Staging: panel: Remove space No space is necessary after a cast, therefore remove it. Found by checkpatch.pl Signed-off-by: Ksenija Stanojevic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 1e67e26a9e0c..04d86f3d8e12 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -1805,7 +1805,7 @@ static void phys_scan_contacts(void) w_dtr(pprt, oldval & ~bitval); /* enable this output */ bitmask = PNL_PINPUT(r_str(pprt)) & ~gndmask; - phys_read |= (pmask_t) bitmask << (5 * bit); + phys_read |= (pmask_t)bitmask << (5 * bit); } w_dtr(pprt, oldval); /* disable all outputs */ } -- cgit v1.2.3 From d938e1eb2fa9c23ea643e03b1834b6ad5b03805f Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Sun, 3 Jan 2016 20:39:49 +0100 Subject: Staging: panel: Use u8 type Declare om, im, omask and imask as u8 to remove any confusion if that describes the 8 bits of the data bus on the parallel port. Also change return type of lcd_write_data() to u8. Signed-off-by: Ksenija Stanojevic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 04d86f3d8e12..8bc604d83541 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -2042,11 +2042,11 @@ static void init_scan_timer(void) * corresponding to out and in bits respectively. * returns 1 if ok, 0 if error (in which case, nothing is written). */ -static int input_name2mask(const char *name, pmask_t *mask, pmask_t *value, - char *imask, char *omask) +static u8 input_name2mask(const char *name, pmask_t *mask, pmask_t *value, + u8 *imask, u8 *omask) { static char sigtab[10] = "EeSsPpAaBb"; - char im, om; + u8 im, om; pmask_t m, v; om = 0ULL; -- cgit v1.2.3 From 35fe0872846efa50b85900542a27694c69c82405 Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Sun, 3 Jan 2016 20:40:58 +0100 Subject: Staging: panel: Remove typedef pmask_t Use __u64 instead of pmask_t and remove pmask_t since is useless. Signed-off-by: Ksenija Stanojevic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 8bc604d83541..7138ee7d217a 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -172,8 +172,6 @@ static __u8 scan_mask_o; /* logical or of the input bits involved in the scan matrix */ static __u8 scan_mask_i; -typedef __u64 pmask_t; - enum input_type { INPUT_TYPE_STD, INPUT_TYPE_KBD, @@ -188,8 +186,8 @@ enum input_state { struct logical_input { struct list_head list; - pmask_t mask; - pmask_t value; + __u64 mask; + __u64 value; enum input_type type; enum input_state state; __u8 rise_time, fall_time; @@ -219,19 +217,19 @@ static LIST_HEAD(logical_inputs); /* list of all defined logical inputs */ * corresponds to the ground. * Within each group, bits are stored in the same order as read on the port : * BAPSE (busy=4, ack=3, paper empty=2, select=1, error=0). - * So, each __u64 (or pmask_t) is represented like this : + * So, each __u64 is represented like this : * 0000000000000000000BAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSE * <-----unused------> */ /* what has just been read from the I/O ports */ -static pmask_t phys_read; +static __u64 phys_read; /* previous phys_read */ -static pmask_t phys_read_prev; +static __u64 phys_read_prev; /* stabilized phys_read (phys_read|phys_read_prev) */ -static pmask_t phys_curr; +static __u64 phys_curr; /* previous phys_curr */ -static pmask_t phys_prev; +static __u64 phys_prev; /* 0 means that at least one logical signal needs be computed */ static char inputs_stable; @@ -1789,7 +1787,7 @@ static void phys_scan_contacts(void) gndmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i; /* grounded inputs are signals 40-44 */ - phys_read |= (pmask_t)gndmask << 40; + phys_read |= (__u64)gndmask << 40; if (bitmask != gndmask) { /* @@ -1805,7 +1803,7 @@ static void phys_scan_contacts(void) w_dtr(pprt, oldval & ~bitval); /* enable this output */ bitmask = PNL_PINPUT(r_str(pprt)) & ~gndmask; - phys_read |= (pmask_t)bitmask << (5 * bit); + phys_read |= (__u64)bitmask << (5 * bit); } w_dtr(pprt, oldval); /* disable all outputs */ } @@ -2042,12 +2040,12 @@ static void init_scan_timer(void) * corresponding to out and in bits respectively. * returns 1 if ok, 0 if error (in which case, nothing is written). */ -static u8 input_name2mask(const char *name, pmask_t *mask, pmask_t *value, +static u8 input_name2mask(const char *name, __u64 *mask, __u64 *value, u8 *imask, u8 *omask) { static char sigtab[10] = "EeSsPpAaBb"; u8 im, om; - pmask_t m, v; + __u64 m, v; om = 0ULL; im = 0ULL; -- cgit v1.2.3 From d12f27e8b2abc1efe9156ff403f4fa6eae4268df Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Sun, 3 Jan 2016 20:42:26 +0100 Subject: Staging: panel: Remove ULL Remove ULL on om and im, since it's useless. Signed-off-by: Ksenija Stanojevic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 7138ee7d217a..e9641ea7e477 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -2047,8 +2047,8 @@ static u8 input_name2mask(const char *name, __u64 *mask, __u64 *value, u8 im, om; __u64 m, v; - om = 0ULL; - im = 0ULL; + om = 0; + im = 0; m = 0ULL; v = 0ULL; while (*name) { -- cgit v1.2.3 From 52ebf93f367f3b749a696dc77ac2e42c186eb924 Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Sun, 3 Jan 2016 20:43:27 +0100 Subject: Staging: panel: Reduce value range for *name out is 0-9 so it's too much for om, therefore reduce value range for *name from '0'-'9' to '0'-'7'. Signed-off-by: Ksenija Stanojevic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index e9641ea7e477..fcfcda7ff1f4 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -2065,7 +2065,7 @@ static u8 input_name2mask(const char *name, __u64 *mask, __u64 *value, im |= BIT(in); name++; - if (isdigit(*name)) { + if (*name >= '0' && *name <= '7') { out = *name - '0'; om |= BIT(out); } else if (*name == '-') { -- cgit v1.2.3 From 8aa7307b7802cb765fcc11305db3fdeee0920658 Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Sun, 3 Jan 2016 20:44:44 +0100 Subject: Staging: panel: Make code more readable Repace 'for' statement by strchr() function to make code more readable. Signed-off-by: Ksenija Stanojevic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index fcfcda7ff1f4..1219ff7884f8 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -2043,7 +2043,7 @@ static void init_scan_timer(void) static u8 input_name2mask(const char *name, __u64 *mask, __u64 *value, u8 *imask, u8 *omask) { - static char sigtab[10] = "EeSsPpAaBb"; + const char sigtab[] = "EeSsPpAaBb"; u8 im, om; __u64 m, v; @@ -2053,13 +2053,13 @@ static u8 input_name2mask(const char *name, __u64 *mask, __u64 *value, v = 0ULL; while (*name) { int in, out, bit, neg; + const char *idx; - for (in = 0; (in < sizeof(sigtab)) && (sigtab[in] != *name); - in++) - ; - - if (in >= sizeof(sigtab)) + idx = strchr(sigtab, *name); + if (!idx) return 0; /* input name not found */ + + in = idx - sigtab; neg = (in & 1); /* odd (lower) names are negated */ in >>= 1; im |= BIT(in); -- cgit v1.2.3 From b64a1cbef6df47c986ad622b5b2e4d3d1940070c Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Sat, 23 Jan 2016 14:49:20 +0530 Subject: Revert "Staging: panel: usleep_range is preferred over udelay" This reverts commit ebd43516d3879f882a403836bba8bc5791f26a28. We should not be sleeping inside spin_lock. Fixes: ebd43516d387 ("Staging: panel: usleep_range is preferred over udelay") Cc: Sirnam Swetha Signed-off-by: Sudip Mukherjee Reported-by: Huang, Ying Tested-by: Huang, Ying Cc: stable # 4.4 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 79ac19246548..70b8f4fabfad 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -825,8 +825,7 @@ static void lcd_write_cmd_s(int cmd) lcd_send_serial(0x1F); /* R/W=W, RS=0 */ lcd_send_serial(cmd & 0x0F); lcd_send_serial((cmd >> 4) & 0x0F); - /* the shortest command takes at least 40 us */ - usleep_range(40, 100); + udelay(40); /* the shortest command takes at least 40 us */ spin_unlock_irq(&pprt_lock); } @@ -837,8 +836,7 @@ static void lcd_write_data_s(int data) lcd_send_serial(0x5F); /* R/W=W, RS=1 */ lcd_send_serial(data & 0x0F); lcd_send_serial((data >> 4) & 0x0F); - /* the shortest data takes at least 40 us */ - usleep_range(40, 100); + udelay(40); /* the shortest data takes at least 40 us */ spin_unlock_irq(&pprt_lock); } @@ -848,20 +846,19 @@ static void lcd_write_cmd_p8(int cmd) spin_lock_irq(&pprt_lock); /* present the data to the data port */ w_dtr(pprt, cmd); - /* maintain the data during 20 us before the strobe */ - usleep_range(20, 100); + udelay(20); /* maintain the data during 20 us before the strobe */ bits.e = BIT_SET; bits.rs = BIT_CLR; bits.rw = BIT_CLR; set_ctrl_bits(); - usleep_range(40, 100); /* maintain the strobe during 40 us */ + udelay(40); /* maintain the strobe during 40 us */ bits.e = BIT_CLR; set_ctrl_bits(); - usleep_range(120, 500); /* the shortest command takes at least 120 us */ + udelay(120); /* the shortest command takes at least 120 us */ spin_unlock_irq(&pprt_lock); } @@ -871,20 +868,19 @@ static void lcd_write_data_p8(int data) spin_lock_irq(&pprt_lock); /* present the data to the data port */ w_dtr(pprt, data); - /* maintain the data during 20 us before the strobe */ - usleep_range(20, 100); + udelay(20); /* maintain the data during 20 us before the strobe */ bits.e = BIT_SET; bits.rs = BIT_SET; bits.rw = BIT_CLR; set_ctrl_bits(); - usleep_range(40, 100); /* maintain the strobe during 40 us */ + udelay(40); /* maintain the strobe during 40 us */ bits.e = BIT_CLR; set_ctrl_bits(); - usleep_range(45, 100); /* the shortest data takes at least 45 us */ + udelay(45); /* the shortest data takes at least 45 us */ spin_unlock_irq(&pprt_lock); } @@ -894,7 +890,7 @@ static void lcd_write_cmd_tilcd(int cmd) spin_lock_irq(&pprt_lock); /* present the data to the control port */ w_ctr(pprt, cmd); - usleep_range(60, 120); + udelay(60); spin_unlock_irq(&pprt_lock); } @@ -904,7 +900,7 @@ static void lcd_write_data_tilcd(int data) spin_lock_irq(&pprt_lock); /* present the data to the data port */ w_dtr(pprt, data); - usleep_range(60, 120); + udelay(60); spin_unlock_irq(&pprt_lock); } @@ -947,7 +943,7 @@ static void lcd_clear_fast_s(void) lcd_send_serial(0x5F); /* R/W=W, RS=1 */ lcd_send_serial(' ' & 0x0F); lcd_send_serial((' ' >> 4) & 0x0F); - usleep_range(40, 100); /* the shortest data takes at least 40 us */ + udelay(40); /* the shortest data takes at least 40 us */ } spin_unlock_irq(&pprt_lock); @@ -971,7 +967,7 @@ static void lcd_clear_fast_p8(void) w_dtr(pprt, ' '); /* maintain the data during 20 us before the strobe */ - usleep_range(20, 100); + udelay(20); bits.e = BIT_SET; bits.rs = BIT_SET; @@ -979,13 +975,13 @@ static void lcd_clear_fast_p8(void) set_ctrl_bits(); /* maintain the strobe during 40 us */ - usleep_range(40, 100); + udelay(40); bits.e = BIT_CLR; set_ctrl_bits(); /* the shortest data takes at least 45 us */ - usleep_range(45, 100); + udelay(45); } spin_unlock_irq(&pprt_lock); @@ -1007,7 +1003,7 @@ static void lcd_clear_fast_tilcd(void) for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { /* present the data to the data port */ w_dtr(pprt, ' '); - usleep_range(60, 120); + udelay(60); } spin_unlock_irq(&pprt_lock); -- cgit v1.2.3 From a4efe6fd5dead8d82b73a7ab726aa18cfa11b734 Mon Sep 17 00:00:00 2001 From: Christian Colic Date: Thu, 19 Nov 2015 14:40:59 +0100 Subject: staging: speakup: (coding style) Add spaces around operands (checkpatch checks) Fix checkpatch check: CHECK: spaces preferred around that '-' (ctx:VxV) Add spaces around operands to fix these warnings. Signed-off-by: Christian Colic Reviewed-by: Luis de Bethencourt Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/keyhelp.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/speakup/keyhelp.c b/drivers/staging/speakup/keyhelp.c index 02d5c706aee7..d14089a8dbd9 100644 --- a/drivers/staging/speakup/keyhelp.c +++ b/drivers/staging/speakup/keyhelp.c @@ -74,7 +74,7 @@ static void build_key_data(void) for (i = 0; i < nstates; i++, kp++) { if (!*kp) continue; - if ((state_tbl[i]&16) != 0 && *kp == SPK_KEY) + if ((state_tbl[i] & 16) != 0 && *kp == SPK_KEY) continue; counters[*kp]++; } @@ -83,7 +83,7 @@ static void build_key_data(void) if (counters[i] == 0) continue; key_offsets[i] = offset; - offset += (counters[i]+1); + offset += (counters[i] + 1); if (offset >= MAXKEYS) break; } @@ -97,7 +97,7 @@ static void build_key_data(void) ch1 = *kp++; if (!ch1) continue; - if ((state_tbl[i]&16) != 0 && ch1 == SPK_KEY) + if ((state_tbl[i] & 16) != 0 && ch1 == SPK_KEY) continue; key = (state_tbl[i] << 8) + ch; counters[ch1]--; @@ -130,14 +130,14 @@ static int help_init(void) int i; int num_funcs = MSG_FUNCNAMES_END - MSG_FUNCNAMES_START + 1; - state_tbl = spk_our_keys[0]+SHIFT_TBL_SIZE+2; + state_tbl = spk_our_keys[0] + SHIFT_TBL_SIZE + 2; for (i = 0; i < num_funcs; i++) { char *cur_funcname = spk_msg_get(MSG_FUNCNAMES_START + i); if (start == *cur_funcname) continue; start = *cur_funcname; - letter_offsets[(start&31)-1] = i; + letter_offsets[(start & 31) - 1] = i; } return 0; } @@ -160,12 +160,12 @@ int spk_handle_help(struct vc_data *vc, u_char type, u_char ch, u_short key) ch |= 32; /* lower case */ if (ch < 'a' || ch > 'z') return -1; - if (letter_offsets[ch-'a'] == -1) { + if (letter_offsets[ch - 'a'] == -1) { synth_printf(spk_msg_get(MSG_NO_COMMAND), ch); synth_printf("\n"); return 1; } - cur_item = letter_offsets[ch-'a']; + cur_item = letter_offsets[ch - 'a']; } else if (type == KT_CUR) { if (ch == 0 && (MSG_FUNCNAMES_START + cur_item + 1) <= @@ -186,7 +186,7 @@ int spk_handle_help(struct vc_data *vc, u_char type, u_char ch, u_short key) name = NULL; if ((type != KT_SPKUP) && (key > 0) && (key <= num_key_names)) { synth_printf("%s\n", - spk_msg_get(MSG_KEYNAMES_START + key-1)); + spk_msg_get(MSG_KEYNAMES_START + key - 1)); return 1; } for (i = 0; funcvals[i] != 0 && !name; i++) { @@ -195,7 +195,7 @@ int spk_handle_help(struct vc_data *vc, u_char type, u_char ch, u_short key) } if (!name) return -1; - kp = spk_our_keys[key]+1; + kp = spk_our_keys[key] + 1; for (i = 0; i < nstates; i++) { if (ch == kp[i]) break; -- cgit v1.2.3 From 1fd16a31256cc867a7212e3399bd493a92cbd177 Mon Sep 17 00:00:00 2001 From: Christian Colic Date: Thu, 19 Nov 2015 17:08:06 +0100 Subject: staging: speakup: (coding style) Add braces around all arms of if-statement Fix checkpatch error: "braces {} should be used on all arms of this statement" by adding the necessary braces around the "if". Signed-off-by: Christian Colic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/devsynth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/speakup/devsynth.c b/drivers/staging/speakup/devsynth.c index d1ffdf4c0c4b..84989711ae67 100644 --- a/drivers/staging/speakup/devsynth.c +++ b/drivers/staging/speakup/devsynth.c @@ -76,9 +76,9 @@ void speakup_register_devsynth(void) if (misc_registered != 0) return; /* zero it so if register fails, deregister will not ref invalid ptrs */ - if (misc_register(&synth_device)) + if (misc_register(&synth_device)) { pr_warn("Couldn't initialize miscdevice /dev/synth.\n"); - else { + } else { pr_info("initialized device: /dev/synth, node (MAJOR %d, MINOR %d)\n", MISC_MAJOR, SYNTH_MINOR); misc_registered = 1; -- cgit v1.2.3 From d3da1cbaef8d92b1bb4103feee03b888f5bead24 Mon Sep 17 00:00:00 2001 From: Christian Colic Date: Thu, 19 Nov 2015 17:18:43 +0100 Subject: staging: speakup: (coding style) Rewrite comparisons to NULL Rewrite comparisons to NULL so they dont show any checkpatch errors anymore. "vc_cons[i].d != NULL" => "vc_cons[i].d" Signed-off-by: Christian Colic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/buffers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/speakup/buffers.c b/drivers/staging/speakup/buffers.c index 8565c2343968..723d5df44221 100644 --- a/drivers/staging/speakup/buffers.c +++ b/drivers/staging/speakup/buffers.c @@ -27,7 +27,7 @@ void speakup_start_ttys(void) for (i = 0; i < MAX_NR_CONSOLES; i++) { if (speakup_console[i] && speakup_console[i]->tty_stopped) continue; - if ((vc_cons[i].d != NULL) && (vc_cons[i].d->port.tty != NULL)) + if ((vc_cons[i].d) && (vc_cons[i].d->port.tty)) start_tty(vc_cons[i].d->port.tty); } } @@ -38,7 +38,7 @@ static void speakup_stop_ttys(void) int i; for (i = 0; i < MAX_NR_CONSOLES; i++) - if ((vc_cons[i].d != NULL) && (vc_cons[i].d->port.tty != NULL)) + if ((vc_cons[i].d && (vc_cons[i].d->port.tty))) stop_tty(vc_cons[i].d->port.tty); } -- cgit v1.2.3 From d86b4a71ca579914c971ae949335b4e971eec213 Mon Sep 17 00:00:00 2001 From: Saurabh Sengar Date: Mon, 7 Dec 2015 18:35:11 +0530 Subject: Staging: speakup: varhandlers: cleanup of function spk_get_punc_var This patch does the following: * changed the complicated if statements to simple case statements * in case of E_DEFAULT, no need to return error as ERESTART, because this is the user asked for. Hence function should return success. * ret variable is 0 always, hence removed it. * removed one ternary operator, as it was always returning the status value only, and hence removed the status variable too Signed-off-by: Saurabh Sengar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/varhandlers.c | 50 +++++++++++++++++------------------ 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/speakup/varhandlers.c b/drivers/staging/speakup/varhandlers.c index ab4fe8de415f..e1393d2a2b0f 100644 --- a/drivers/staging/speakup/varhandlers.c +++ b/drivers/staging/speakup/varhandlers.c @@ -176,7 +176,6 @@ struct punc_var_t *spk_get_punc_var(enum var_id_t var_id) int spk_set_num_var(int input, struct st_var_header *var, int how) { int val; - short ret = 0; int *p_val = var->p_val; int l; char buf[32]; @@ -186,50 +185,51 @@ int spk_set_num_var(int input, struct st_var_header *var, int how) if (!var_data) return -ENODATA; - if (how == E_NEW_DEFAULT) { + val = var_data->u.n.value; + switch (how) { + case E_NEW_DEFAULT: if (input < var_data->u.n.low || input > var_data->u.n.high) return -ERANGE; var_data->u.n.default_val = input; return 0; - } - if (how == E_DEFAULT) { + case E_DEFAULT: val = var_data->u.n.default_val; - ret = -ERESTART; - } else { - if (how == E_SET) - val = input; - else - val = var_data->u.n.value; - if (how == E_INC) - val += input; - else if (how == E_DEC) - val -= input; - if (val < var_data->u.n.low || val > var_data->u.n.high) - return -ERANGE; + break; + case E_SET: + val = input; + break; + case E_INC: + val += input; + break; + case E_DEC: + val -= input; + break; } + + if (val < var_data->u.n.low || val > var_data->u.n.high) + return -ERANGE; + var_data->u.n.value = val; if (var->var_type == VAR_TIME && p_val != NULL) { *p_val = msecs_to_jiffies(val); - return ret; + return 0; } if (p_val != NULL) *p_val = val; if (var->var_id == PUNC_LEVEL) { spk_punc_mask = spk_punc_masks[val]; - return ret; + return 0; } if (var_data->u.n.multiplier != 0) val *= var_data->u.n.multiplier; val += var_data->u.n.offset; if (var->var_id < FIRST_SYNTH_VAR || !synth) - return ret; - if (synth->synth_adjust) { - int status = synth->synth_adjust(var); + return 0; + if (synth->synth_adjust) + return synth->synth_adjust(var); - return (status != 0) ? status : ret; - } if (!var_data->u.n.synth_fmt) - return ret; + return 0; if (var->var_id == PITCH) cp = spk_pitch_buff; else @@ -240,7 +240,7 @@ int spk_set_num_var(int input, struct st_var_header *var, int how) l = sprintf(cp, var_data->u.n.synth_fmt, var_data->u.n.out_str[val]); synth_printf("%s", cp); - return ret; + return 0; } int spk_set_string_var(const char *page, struct st_var_header *var, int len) -- cgit v1.2.3 From 911b04d61d28667f2841319939121678198bf1db Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 18 Dec 2015 12:42:51 -0800 Subject: STAGING/SPEAKUP: Fix "expression using sizeof bool" warnings Fix "warning: expression using sizeof bool" messages caught by sparse. Resending directly to SPEAKUP maintainers. Signed-off-by: Jeff Becker Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/fakekey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/speakup/fakekey.c b/drivers/staging/speakup/fakekey.c index 5e1f16c36b49..092dbe2c636a 100644 --- a/drivers/staging/speakup/fakekey.c +++ b/drivers/staging/speakup/fakekey.c @@ -28,7 +28,7 @@ #define PRESSED 1 #define RELEASED 0 -static DEFINE_PER_CPU(bool, reporting_keystroke); +static DEFINE_PER_CPU(int, reporting_keystroke); static struct input_dev *virt_keyboard; -- cgit v1.2.3 From 5cb10d42de412c69dbf3f5670b3099037c35cc78 Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Sun, 27 Dec 2015 20:10:38 +0530 Subject: Staging: speakup: Remove FSF mailing address FSF mailing address is no longer required to be specified. Hence removed. Detected using checkpatch Signed-off-by: Shraddha Barke Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/fakekey.c | 4 ---- drivers/staging/speakup/keyhelp.c | 4 ---- drivers/staging/speakup/main.c | 4 ---- drivers/staging/speakup/speakup_acntpc.c | 5 ----- drivers/staging/speakup/speakup_acntsa.c | 4 ---- drivers/staging/speakup/speakup_apollo.c | 4 ---- drivers/staging/speakup/speakup_audptr.c | 4 ---- drivers/staging/speakup/speakup_bns.c | 4 ---- drivers/staging/speakup/speakup_decext.c | 4 ---- drivers/staging/speakup/speakup_decpc.c | 4 ---- drivers/staging/speakup/speakup_dectlk.c | 4 ---- drivers/staging/speakup/speakup_dtlk.c | 4 ---- drivers/staging/speakup/speakup_dummy.c | 4 ---- drivers/staging/speakup/speakup_keypc.c | 4 ---- drivers/staging/speakup/speakup_ltlk.c | 4 ---- drivers/staging/speakup/speakup_soft.c | 3 --- drivers/staging/speakup/speakup_spkout.c | 4 ---- drivers/staging/speakup/speakup_txprt.c | 4 ---- drivers/staging/speakup/spk_priv.h | 4 ---- drivers/staging/speakup/spk_priv_keyinfo.h | 4 ---- drivers/staging/speakup/spkguide.txt | 1 - 21 files changed, 81 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/speakup/fakekey.c b/drivers/staging/speakup/fakekey.c index 092dbe2c636a..8f058b42f68d 100644 --- a/drivers/staging/speakup/fakekey.c +++ b/drivers/staging/speakup/fakekey.c @@ -12,10 +12,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include diff --git a/drivers/staging/speakup/keyhelp.c b/drivers/staging/speakup/keyhelp.c index d14089a8dbd9..ce94cb13e256 100644 --- a/drivers/staging/speakup/keyhelp.c +++ b/drivers/staging/speakup/keyhelp.c @@ -14,10 +14,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c index 63c59bc89b04..456f65043355 100644 --- a/drivers/staging/speakup/main.c +++ b/drivers/staging/speakup/main.c @@ -16,10 +16,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include diff --git a/drivers/staging/speakup/speakup_acntpc.c b/drivers/staging/speakup/speakup_acntpc.c index f418893928ec..efb791bb642b 100644 --- a/drivers/staging/speakup/speakup_acntpc.c +++ b/drivers/staging/speakup/speakup_acntpc.c @@ -14,11 +14,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * this code is specificly written as a driver for the speakup screenreview * package and is not a general device driver. * This driver is for the Aicom Acent PC internal synthesizer. diff --git a/drivers/staging/speakup/speakup_acntsa.c b/drivers/staging/speakup/speakup_acntsa.c index af2690f38950..34f45d3549b2 100644 --- a/drivers/staging/speakup/speakup_acntsa.c +++ b/drivers/staging/speakup/speakup_acntsa.c @@ -15,10 +15,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * this code is specificly written as a driver for the speakup screenreview * package and is not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_apollo.c b/drivers/staging/speakup/speakup_apollo.c index 51788f7d4480..3cbc8a7ad1ef 100644 --- a/drivers/staging/speakup/speakup_apollo.c +++ b/drivers/staging/speakup/speakup_apollo.c @@ -15,10 +15,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * this code is specificly written as a driver for the speakup screenreview * package and is not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_audptr.c b/drivers/staging/speakup/speakup_audptr.c index a9a687232955..7a12b8408b67 100644 --- a/drivers/staging/speakup/speakup_audptr.c +++ b/drivers/staging/speakup/speakup_audptr.c @@ -15,10 +15,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * specificly written as a driver for the speakup screenreview * s not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_bns.c b/drivers/staging/speakup/speakup_bns.c index 80f8358d4199..570f0c21745e 100644 --- a/drivers/staging/speakup/speakup_bns.c +++ b/drivers/staging/speakup/speakup_bns.c @@ -15,10 +15,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * this code is specificly written as a driver for the speakup screenreview * package and is not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_decext.c b/drivers/staging/speakup/speakup_decext.c index e0b5db9bb46e..fdd7488f554c 100644 --- a/drivers/staging/speakup/speakup_decext.c +++ b/drivers/staging/speakup/speakup_decext.c @@ -15,10 +15,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * specificly written as a driver for the speakup screenreview * s not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_decpc.c b/drivers/staging/speakup/speakup_decpc.c index 4893fef3f894..d6479bd2163b 100644 --- a/drivers/staging/speakup/speakup_decpc.c +++ b/drivers/staging/speakup/speakup_decpc.c @@ -24,10 +24,6 @@ * 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 diff --git a/drivers/staging/speakup/speakup_dectlk.c b/drivers/staging/speakup/speakup_dectlk.c index 09063b82326f..764656759fbf 100644 --- a/drivers/staging/speakup/speakup_dectlk.c +++ b/drivers/staging/speakup/speakup_dectlk.c @@ -15,10 +15,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * specificly written as a driver for the speakup screenreview * s not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_dtlk.c b/drivers/staging/speakup/speakup_dtlk.c index 345efd3344b0..38aa4013bf62 100644 --- a/drivers/staging/speakup/speakup_dtlk.c +++ b/drivers/staging/speakup/speakup_dtlk.c @@ -15,10 +15,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * specificly written as a driver for the speakup screenreview * package it's not a general device driver. * This driver is for the RC Systems DoubleTalk PC internal synthesizer. diff --git a/drivers/staging/speakup/speakup_dummy.c b/drivers/staging/speakup/speakup_dummy.c index f66811269475..87d2a8002b47 100644 --- a/drivers/staging/speakup/speakup_dummy.c +++ b/drivers/staging/speakup/speakup_dummy.c @@ -17,10 +17,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * specificly written as a driver for the speakup screenreview * s not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_keypc.c b/drivers/staging/speakup/speakup_keypc.c index 6ea027365664..5e2170bf4a8b 100644 --- a/drivers/staging/speakup/speakup_keypc.c +++ b/drivers/staging/speakup/speakup_keypc.c @@ -13,10 +13,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * specificly written as a driver for the speakup screenreview * package it's not a general device driver. * This driver is for the Keynote Gold internal synthesizer. diff --git a/drivers/staging/speakup/speakup_ltlk.c b/drivers/staging/speakup/speakup_ltlk.c index cc4806be806b..b474e8b65f9a 100644 --- a/drivers/staging/speakup/speakup_ltlk.c +++ b/drivers/staging/speakup/speakup_ltlk.c @@ -15,10 +15,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * specificly written as a driver for the speakup screenreview * s not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/staging/speakup/speakup_soft.c index b2eb5b133a5d..6b1d0f538bbd 100644 --- a/drivers/staging/speakup/speakup_soft.c +++ b/drivers/staging/speakup/speakup_soft.c @@ -14,9 +14,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * this code is specificly written as a driver for the speakup screenreview * package and is not a general device driver. diff --git a/drivers/staging/speakup/speakup_spkout.c b/drivers/staging/speakup/speakup_spkout.c index 1007a6168c3c..e449f2770c1f 100644 --- a/drivers/staging/speakup/speakup_spkout.c +++ b/drivers/staging/speakup/speakup_spkout.c @@ -15,10 +15,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * specificly written as a driver for the speakup screenreview * s not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_txprt.c b/drivers/staging/speakup/speakup_txprt.c index 6c21e7112210..fd98d4ffcb3e 100644 --- a/drivers/staging/speakup/speakup_txprt.c +++ b/drivers/staging/speakup/speakup_txprt.c @@ -15,10 +15,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * specificly written as a driver for the speakup screenreview * s not a general device driver. */ diff --git a/drivers/staging/speakup/spk_priv.h b/drivers/staging/speakup/spk_priv.h index 9bb281d36556..98c4b6f0344a 100644 --- a/drivers/staging/speakup/spk_priv.h +++ b/drivers/staging/speakup/spk_priv.h @@ -16,10 +16,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _SPEAKUP_PRIVATE_H #define _SPEAKUP_PRIVATE_H diff --git a/drivers/staging/speakup/spk_priv_keyinfo.h b/drivers/staging/speakup/spk_priv_keyinfo.h index 3116ef78c196..130e9cb0118b 100644 --- a/drivers/staging/speakup/spk_priv_keyinfo.h +++ b/drivers/staging/speakup/spk_priv_keyinfo.h @@ -16,10 +16,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _SPEAKUP_KEYINFO_H diff --git a/drivers/staging/speakup/spkguide.txt b/drivers/staging/speakup/spkguide.txt index b699de3c649f..c23549c54c3c 100644 --- a/drivers/staging/speakup/spkguide.txt +++ b/drivers/staging/speakup/spkguide.txt @@ -1179,7 +1179,6 @@ if desired. Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. -- cgit v1.2.3 From e4953910aee0c1a8f7f0fff598354948c2702900 Mon Sep 17 00:00:00 2001 From: "Woojung.Huh@microchip.com" Date: Wed, 27 Jan 2016 22:57:52 +0000 Subject: lan78xx: change to use updated phy-ignore-interrupts Update lan78xx to use patch of commit 4f2aaf7dd95b ("Merge branch 'fix-phy-ignore-interrupts'"). Signed-off-by: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/usb/lan78xx.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 2ed53331bfb2..027ee373860e 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -36,7 +36,7 @@ #define DRIVER_AUTHOR "WOOJUNG HUH " #define DRIVER_DESC "LAN78XX USB 3.0 Gigabit Ethernet Devices" #define DRIVER_NAME "lan78xx" -#define DRIVER_VERSION "1.0.1" +#define DRIVER_VERSION "1.0.2" #define TX_TIMEOUT_JIFFIES (5 * HZ) #define THROTTLE_JIFFIES (HZ / 8) @@ -904,7 +904,6 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) if (!phydev->link && dev->link_on) { dev->link_on = false; - netif_carrier_off(dev->net); /* reset MAC */ ret = lan78xx_read_reg(dev, MAC_CR, &buf); @@ -914,6 +913,8 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) ret = lan78xx_write_reg(dev, MAC_CR, buf); if (unlikely(ret < 0)) return -EIO; + + phy_mac_interrupt(phydev, 0); } else if (phydev->link && !dev->link_on) { dev->link_on = true; @@ -953,7 +954,7 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) ethtool_cmd_speed(&ecmd), ecmd.duplex, ladv, radv); ret = lan78xx_update_flowcontrol(dev, ecmd.duplex, ladv, radv); - netif_carrier_on(dev->net); + phy_mac_interrupt(phydev, 1); } return ret; @@ -1495,7 +1496,6 @@ done: static int lan78xx_mdio_init(struct lan78xx_net *dev) { int ret; - int i; dev->mdiobus = mdiobus_alloc(); if (!dev->mdiobus) { @@ -1511,10 +1511,6 @@ static int lan78xx_mdio_init(struct lan78xx_net *dev) snprintf(dev->mdiobus->id, MII_BUS_ID_SIZE, "usb-%03d:%03d", dev->udev->bus->busnum, dev->udev->devnum); - /* handle our own interrupt */ - for (i = 0; i < PHY_MAX_ADDR; i++) - dev->mdiobus->irq[i] = PHY_IGNORE_INTERRUPT; - switch (dev->devid & ID_REV_CHIP_ID_MASK_) { case 0x78000000: case 0x78500000: @@ -1558,6 +1554,16 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) return -EIO; } + /* Enable PHY interrupts. + * We handle our own interrupt + */ + ret = phy_read(phydev, LAN88XX_INT_STS); + ret = phy_write(phydev, LAN88XX_INT_MASK, + LAN88XX_INT_MASK_MDINTPIN_EN_ | + LAN88XX_INT_MASK_LINK_CHANGE_); + + phydev->irq = PHY_IGNORE_INTERRUPT; + ret = phy_connect_direct(dev->net, phydev, lan78xx_link_status_change, PHY_INTERFACE_MODE_GMII); @@ -1580,14 +1586,6 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) SUPPORTED_Pause | SUPPORTED_Asym_Pause); genphy_config_aneg(phydev); - /* Workaround to enable PHY interrupt. - * phy_start_interrupts() is API for requesting and enabling - * PHY interrupt. However, USB-to-Ethernet device can't use - * request_irq() called in phy_start_interrupts(). - * Set PHY to PHY_HALTED and call phy_start() - * to make a call to phy_enable_interrupts() - */ - phy_stop(phydev); phy_start(phydev); netif_dbg(dev, ifup, dev->net, "phy initialised successfully"); -- cgit v1.2.3 From a0db7d10b76e98df0cb5d4ee1ec5b8e5fbe2038c Mon Sep 17 00:00:00 2001 From: "Woojung.Huh@microchip.com" Date: Wed, 27 Jan 2016 22:57:53 +0000 Subject: lan78xx: Add to handle mux control per chip id Depends on chip, some EEPROM pins are muxed with LED function. Disable & restore LED function to access EEPROM. Signed-off-by: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/usb/lan78xx.c | 98 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 027ee373860e..650e71604d86 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -462,32 +462,53 @@ static int lan78xx_read_raw_eeprom(struct lan78xx_net *dev, u32 offset, u32 length, u8 *data) { u32 val; + u32 saved; int i, ret; + int retval; - ret = lan78xx_eeprom_confirm_not_busy(dev); - if (ret) - return ret; + /* depends on chip, some EEPROM pins are muxed with LED function. + * disable & restore LED function to access EEPROM. + */ + ret = lan78xx_read_reg(dev, HW_CFG, &val); + saved = val; + if ((dev->devid & ID_REV_CHIP_ID_MASK_) == 0x78000000) { + val &= ~(HW_CFG_LED1_EN_ | HW_CFG_LED0_EN_); + ret = lan78xx_write_reg(dev, HW_CFG, val); + } + + retval = lan78xx_eeprom_confirm_not_busy(dev); + if (retval) + return retval; for (i = 0; i < length; i++) { val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_READ_; val |= (offset & E2P_CMD_EPC_ADDR_MASK_); ret = lan78xx_write_reg(dev, E2P_CMD, val); - if (unlikely(ret < 0)) - return -EIO; + if (unlikely(ret < 0)) { + retval = -EIO; + goto exit; + } - ret = lan78xx_wait_eeprom(dev); - if (ret < 0) - return ret; + retval = lan78xx_wait_eeprom(dev); + if (retval < 0) + goto exit; ret = lan78xx_read_reg(dev, E2P_DATA, &val); - if (unlikely(ret < 0)) - return -EIO; + if (unlikely(ret < 0)) { + retval = -EIO; + goto exit; + } data[i] = val & 0xFF; offset++; } - return 0; + retval = 0; +exit: + if ((dev->devid & ID_REV_CHIP_ID_MASK_) == 0x78000000) + ret = lan78xx_write_reg(dev, HW_CFG, saved); + + return retval; } static int lan78xx_read_eeprom(struct lan78xx_net *dev, u32 offset, @@ -509,44 +530,67 @@ static int lan78xx_write_raw_eeprom(struct lan78xx_net *dev, u32 offset, u32 length, u8 *data) { u32 val; + u32 saved; int i, ret; + int retval; - ret = lan78xx_eeprom_confirm_not_busy(dev); - if (ret) - return ret; + /* depends on chip, some EEPROM pins are muxed with LED function. + * disable & restore LED function to access EEPROM. + */ + ret = lan78xx_read_reg(dev, HW_CFG, &val); + saved = val; + if ((dev->devid & ID_REV_CHIP_ID_MASK_) == 0x78000000) { + val &= ~(HW_CFG_LED1_EN_ | HW_CFG_LED0_EN_); + ret = lan78xx_write_reg(dev, HW_CFG, val); + } + + retval = lan78xx_eeprom_confirm_not_busy(dev); + if (retval) + goto exit; /* Issue write/erase enable command */ val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_EWEN_; ret = lan78xx_write_reg(dev, E2P_CMD, val); - if (unlikely(ret < 0)) - return -EIO; + if (unlikely(ret < 0)) { + retval = -EIO; + goto exit; + } - ret = lan78xx_wait_eeprom(dev); - if (ret < 0) - return ret; + retval = lan78xx_wait_eeprom(dev); + if (retval < 0) + goto exit; for (i = 0; i < length; i++) { /* Fill data register */ val = data[i]; ret = lan78xx_write_reg(dev, E2P_DATA, val); - if (ret < 0) - return ret; + if (ret < 0) { + retval = -EIO; + goto exit; + } /* Send "write" command */ val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_WRITE_; val |= (offset & E2P_CMD_EPC_ADDR_MASK_); ret = lan78xx_write_reg(dev, E2P_CMD, val); - if (ret < 0) - return ret; + if (ret < 0) { + retval = -EIO; + goto exit; + } - ret = lan78xx_wait_eeprom(dev); - if (ret < 0) - return ret; + retval = lan78xx_wait_eeprom(dev); + if (retval < 0) + goto exit; offset++; } - return 0; + retval = 0; +exit: + if ((dev->devid & ID_REV_CHIP_ID_MASK_) == 0x78000000) + ret = lan78xx_write_reg(dev, HW_CFG, saved); + + return retval; } static int lan78xx_read_raw_otp(struct lan78xx_net *dev, u32 offset, -- cgit v1.2.3 From 4b2a4a965331a8ce7303b43039ce43651ef80fb0 Mon Sep 17 00:00:00 2001 From: "Woojung.Huh@microchip.com" Date: Wed, 27 Jan 2016 22:57:54 +0000 Subject: lan78xx: throttle TX path at slower than SuperSpeed USB Throttle TX path only at slower than SuperSpeed USB. SuperSpeed USB has enough bandwidth to maintain GigE. Signed-off-by: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/usb/lan78xx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 650e71604d86..1c299b8a162d 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -2263,7 +2263,9 @@ netdev_tx_t lan78xx_start_xmit(struct sk_buff *skb, struct net_device *net) if (skb2) { skb_queue_tail(&dev->txq_pend, skb2); - if (skb_queue_len(&dev->txq_pend) > 10) + /* throttle TX patch at slower than SUPER SPEED USB */ + if ((dev->udev->speed < USB_SPEED_SUPER) && + (skb_queue_len(&dev->txq_pend) > 10)) netif_stop_queue(net); } else { netif_dbg(dev, tx_err, dev->net, -- cgit v1.2.3 From ae461131960b27d4be158d62a89d40977388d7a1 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Thu, 28 Jan 2016 02:30:29 +0100 Subject: of: of_mdio: Add a whitelist of PHY compatibilities. Some phy nodes list a compatible value indicating the PHY make/model. This is never used to match the device to the driver. However it does confuse the code to separate a PHY from a generic MDIO device like a switch. Generic MDIO devices must have a compatible value, PHYs can list clause 22 or 45, but nothing else. Issue a warning if we find a compatible value known on the whitelist, and say it is a PHY. Fixes: a9049e0c513c ("mdio: Add support for mdio drivers.") Reported-by: Aaro Koskinen Reported-by: Olof Johansson Tested-by: Aaro Koskinen Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/of/of_mdio.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers') diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index b5aa004a24b6..5648317d355f 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -143,11 +143,31 @@ int of_mdio_parse_addr(struct device *dev, const struct device_node *np) } EXPORT_SYMBOL(of_mdio_parse_addr); +/* The following is a list of PHY compatible strings which appear in + * some DTBs. The compatible string is never matched against a PHY + * driver, so is pointless. We only expect devices which are not PHYs + * to have a compatible string, so they can be matched to an MDIO + * driver. Encourage users to upgrade their DT blobs to remove these. + */ +static const struct of_device_id whitelist_phys[] = { + { .compatible = "brcm,40nm-ephy" }, + { .compatible = "marvell,88E1111", }, + { .compatible = "marvell,88e1116", }, + { .compatible = "marvell,88e1118", }, + { .compatible = "marvell,88e1149r", }, + { .compatible = "marvell,88e1310", }, + { .compatible = "marvell,88E1510", }, + { .compatible = "marvell,88E1514", }, + { .compatible = "moxa,moxart-rtl8201cp", }, + {} +}; + /* * Return true if the child node is for a phy. It must either: * o Compatible string of "ethernet-phy-idX.X" * o Compatible string of "ethernet-phy-ieee802.3-c45" * o Compatible string of "ethernet-phy-ieee802.3-c22" + * o In the white list above (and issue a warning) * o No compatibility string * * A device which is not a phy is expected to have a compatible string @@ -166,6 +186,13 @@ static bool of_mdiobus_child_is_phy(struct device_node *child) if (of_device_is_compatible(child, "ethernet-phy-ieee802.3-c22")) return true; + if (of_match_node(whitelist_phys, child)) { + pr_warn(FW_WARN + "%s: Whitelisted compatible string. Please remove\n", + child->full_name); + return true; + } + if (!of_find_property(child, "compatible", NULL)) return true; -- cgit v1.2.3 From 327b882d3bcc1fba82dbd39b5cf5a838c81218e2 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Fri, 15 Jan 2016 00:47:41 +0100 Subject: Staging: speakup: Fix getting port information Commit f79b0d9c223c ("staging: speakup: Fixed warning instead of ") broke the port information in the speakup driver: SERIAL_PORT_DFNS only gets defined if asm/serial.h is included, and no other header includes asm/serial.h. We here make sure serialio.c does get the arch-specific definition of SERIAL_PORT_DFNS from asm/serial.h, if any. Along the way, this makes sure that we do have information for the requested serial port number (index) Fixes: f79b0d9c223c ("staging: speakup: Fixed warning instead of ") Signed-off-by: Samuel Thibault Cc: stable # 3.18 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/serialio.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/speakup/serialio.c b/drivers/staging/speakup/serialio.c index 3b5835b28128..a5bbb338f275 100644 --- a/drivers/staging/speakup/serialio.c +++ b/drivers/staging/speakup/serialio.c @@ -6,6 +6,11 @@ #include "spk_priv.h" #include "serialio.h" +#include +/* WARNING: Do not change this to without testing that + * SERIAL_PORT_DFNS does get defined to the appropriate value. */ +#include + #ifndef SERIAL_PORT_DFNS #define SERIAL_PORT_DFNS #endif @@ -23,9 +28,15 @@ const struct old_serial_port *spk_serial_init(int index) int baud = 9600, quot = 0; unsigned int cval = 0; int cflag = CREAD | HUPCL | CLOCAL | B9600 | CS8; - const struct old_serial_port *ser = rs_table + index; + const struct old_serial_port *ser; int err; + if (index >= ARRAY_SIZE(rs_table)) { + pr_info("no port info for ttyS%d\n", index); + return NULL; + } + ser = rs_table + index; + /* Divisor, bytesize and parity */ quot = ser->baud_base / baud; cval = cflag & (CSIZE | CSTOPB); -- cgit v1.2.3 From 88867e3d0b7eea256c1cd432b0a3c7a21e8edf07 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Mon, 25 Jan 2016 01:32:08 +0100 Subject: Staging: speakup: fix read scrolled-back VT Previously, speakup would always read the non-scrolled part of the VT, even when the VT is scrolled back with shift-page. This patch makes vt.c export screen_pos so that speakup can use it to properly access the content of the scrolled-back VT. This was tested with both vgacon and fbcon. Signed-off-by: Samuel Thibault Reviewed-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/main.c | 21 +++++++++++++-------- drivers/tty/vt/vt.c | 1 + 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c index 63c59bc89b04..30cf973f326d 100644 --- a/drivers/staging/speakup/main.c +++ b/drivers/staging/speakup/main.c @@ -264,8 +264,9 @@ static struct notifier_block vt_notifier_block = { .notifier_call = vt_notifier_call, }; -static unsigned char get_attributes(u16 *pos) +static unsigned char get_attributes(struct vc_data *vc, u16 *pos) { + pos = screen_pos(vc, pos - (u16 *)vc->vc_origin, 1); return (u_char) (scr_readw(pos) >> 8); } @@ -275,7 +276,7 @@ static void speakup_date(struct vc_data *vc) spk_y = spk_cy = vc->vc_y; spk_pos = spk_cp = vc->vc_pos; spk_old_attr = spk_attr; - spk_attr = get_attributes((u_short *) spk_pos); + spk_attr = get_attributes(vc, (u_short *)spk_pos); } static void bleep(u_short val) @@ -469,8 +470,12 @@ static u16 get_char(struct vc_data *vc, u16 *pos, u_char *attribs) u16 ch = ' '; if (vc && pos) { - u16 w = scr_readw(pos); - u16 c = w & 0xff; + u16 w; + u16 c; + + pos = screen_pos(vc, pos - (u16 *)vc->vc_origin, 1); + w = scr_readw(pos); + c = w & 0xff; if (w & vc->vc_hi_font_mask) c |= 0x100; @@ -746,7 +751,7 @@ static int get_line(struct vc_data *vc) u_char tmp2; spk_old_attr = spk_attr; - spk_attr = get_attributes((u_short *) spk_pos); + spk_attr = get_attributes(vc, (u_short *)spk_pos); for (i = 0; i < vc->vc_cols; i++) { buf[i] = (u_char) get_char(vc, (u_short *) tmp, &tmp2); tmp += 2; @@ -811,7 +816,7 @@ static int say_from_to(struct vc_data *vc, u_long from, u_long to, u_short saved_punc_mask = spk_punc_mask; spk_old_attr = spk_attr; - spk_attr = get_attributes((u_short *) from); + spk_attr = get_attributes(vc, (u_short *)from); while (from < to) { buf[i++] = (char)get_char(vc, (u_short *) from, &tmp); from += 2; @@ -886,7 +891,7 @@ static int get_sentence_buf(struct vc_data *vc, int read_punc) sentmarks[bn][0] = &sentbuf[bn][0]; i = 0; spk_old_attr = spk_attr; - spk_attr = get_attributes((u_short *) start); + spk_attr = get_attributes(vc, (u_short *)start); while (start < end) { sentbuf[bn][i] = (char)get_char(vc, (u_short *) start, &tmp); @@ -1585,7 +1590,7 @@ static int count_highlight_color(struct vc_data *vc) u16 *ptr; for (ptr = start; ptr < end; ptr++) { - ch = get_attributes(ptr); + ch = get_attributes(vc, ptr); bg = (ch & 0x70) >> 4; speakup_console[vc_num]->ht.bgcount[bg]++; } diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 4462d167900c..12210dab9ab1 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -4250,6 +4250,7 @@ unsigned short *screen_pos(struct vc_data *vc, int w_offset, int viewed) { return screenpos(vc, 2 * w_offset, viewed); } +EXPORT_SYMBOL_GPL(screen_pos); void getconsxy(struct vc_data *vc, unsigned char *p) { -- cgit v1.2.3 From 1e859111c128265f8d62b39ff322e42b1ddb5a20 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 25 Jan 2016 12:02:28 +0100 Subject: drm/i915: refine qemu south bridge detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test for the qemu q35 south bridge added by commit "39bfcd52 drm/i915: more virtual south bridge detection" also matches on real hardware. Having the check for virtual systems last in the list is not enough to avoid that ... Refine the check by additionally verifying the pci subsystem id to see whenever it *really* is qemu. [ v2: fix subvendor tyops ] Reported-and-tested-by: Bjørn Mork Signed-off-by: Gerd Hoffmann Tested-by: Bruno Wolff III Cc: drm-intel-fixes@lists.freedesktop.org Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1453719748-10944-1-git-send-email-kraxel@redhat.com --- drivers/gpu/drm/i915/i915_drv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 706b8eabfaf4..11d8414edbbe 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -501,7 +501,9 @@ void intel_detect_pch(struct drm_device *dev) WARN_ON(!IS_SKYLAKE(dev) && !IS_KABYLAKE(dev)); } else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) || - (id == INTEL_PCH_QEMU_DEVICE_ID_TYPE)) { + ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) && + pch->subsystem_vendor == 0x1af4 && + pch->subsystem_device == 0x1100)) { dev_priv->pch_type = intel_virt_detect_pch(dev); } else continue; -- cgit v1.2.3 From 935a0ff0e1ea62a116848c0a187b13838f7b9cee Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 13 Jan 2016 18:59:39 -0800 Subject: drm/i915: Make sure DC writes are coherent on flush. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to set the DC FLUSH PIPE_CONTROL bit on Gen7+ to guarantee that writes performed via the HDC are visible in memory. Fixes an intermittent failure in a Piglit test that writes to a BO from a shader using GL atomic counters (implemented as HDC untyped atomics) and then expects the memory to read back the same value after mapping it on the CPU. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=91298 Tested-by: Mark Janes Cc: Rodrigo Vivi Cc: stable@vger.kernel.org Signed-off-by: Francisco Jerez Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1452740379-3194-1-git-send-email-currojerez@riseup.net (cherry picked from commit 965fd602a6436f689f4f2fe40a6789582778ccd5) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_lrc.c | 1 + drivers/gpu/drm/i915/intel_ringbuffer.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 3aa614731d7e..f1fa756c5d5d 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1707,6 +1707,7 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request, if (flush_domains) { flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; + flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; flags |= PIPE_CONTROL_FLUSH_ENABLE; } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 339701d7a9a5..40c6aff57256 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -331,6 +331,7 @@ gen7_render_ring_flush(struct drm_i915_gem_request *req, if (flush_domains) { flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; + flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; flags |= PIPE_CONTROL_FLUSH_ENABLE; } if (invalidate_domains) { @@ -403,6 +404,7 @@ gen8_render_ring_flush(struct drm_i915_gem_request *req, if (flush_domains) { flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; + flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; flags |= PIPE_CONTROL_FLUSH_ENABLE; } if (invalidate_domains) { -- cgit v1.2.3 From 5efd407674068dede403551bea3b0b134c32513a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 13 Jan 2016 16:35:20 +0200 Subject: drm/i915/dp: fall back to 18 bpp when sink capability is unknown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per DP spec, the source device should fall back to 18 bpp, VESA range RGB when the sink capability is unknown. Fix the color depth clamping. 18 bpp color depth should ensure full color range in automatic mode. The clamping has been HDMI specific since its introduction in commit 996a2239f93b03c5972923f04b097f65565c5bed Author: Daniel Vetter Date: Fri Apr 19 11:24:34 2013 +0200 drm/i915: Disable high-bpc on pre-1.4 EDID screens Cc: stable@vger.kernel.org Reported-and-tested-by: Dihan Wickremasuriya Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=105331 Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1452695720-7076-1-git-send-email-jani.nikula@intel.com (cherry picked from commit 013dd9e038723bbd2aa67be51847384b75be8253) --- drivers/gpu/drm/i915/intel_display.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2f00828ccc6e..002ce89de412 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12075,11 +12075,21 @@ connected_sink_compute_bpp(struct intel_connector *connector, pipe_config->pipe_bpp = connector->base.display_info.bpc*3; } - /* Clamp bpp to 8 on screens without EDID 1.4 */ - if (connector->base.display_info.bpc == 0 && bpp > 24) { - DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of 24\n", - bpp); - pipe_config->pipe_bpp = 24; + /* Clamp bpp to default limit on screens without EDID 1.4 */ + if (connector->base.display_info.bpc == 0) { + int type = connector->base.connector_type; + int clamp_bpp = 24; + + /* Fall back to 18 bpp when DP sink capability is unknown. */ + if (type == DRM_MODE_CONNECTOR_DisplayPort || + type == DRM_MODE_CONNECTOR_eDP) + clamp_bpp = 18; + + if (bpp > clamp_bpp) { + DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of %d\n", + bpp, clamp_bpp); + pipe_config->pipe_bpp = clamp_bpp; + } } } -- cgit v1.2.3 From 6f94b6dd006909a5ef6435cc0af557e945240f48 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 15 Jan 2016 20:46:53 +0200 Subject: drm/i915: Don't reject primary plane windowing with color keying enabled on SKL+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On SKL+ plane scaling is mutually exclusive with color keying. The code check for this, but during some refactoring the code got changed to also reject primary plane windowing when color keying is used. There is no such restriction in the hardware, so restore the original logic. Cc: Maarten Lankhorst Fixes: 061e4b8d650a ("drm/i915: clean up atomic plane check functions, v2.") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1452883613-28549-1-git-send-email-ville.syrjala@linux.intel.com Cc: stable@vger.kernel.org Reviewed-by: Matt Roper Reviewed-by: Maarten Lankhorst (cherry picked from commit 693bdc28a733dba68b86af295e7509812fec35d9) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_display.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 002ce89de412..354f44793218 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13893,11 +13893,12 @@ intel_check_primary_plane(struct drm_plane *plane, int max_scale = DRM_PLANE_HELPER_NO_SCALING; bool can_position = false; - /* use scaler when colorkey is not required */ - if (INTEL_INFO(plane->dev)->gen >= 9 && - state->ckey.flags == I915_SET_COLORKEY_NONE) { - min_scale = 1; - max_scale = skl_max_scale(to_intel_crtc(crtc), crtc_state); + if (INTEL_INFO(plane->dev)->gen >= 9) { + /* use scaler when colorkey is not required */ + if (state->ckey.flags == I915_SET_COLORKEY_NONE) { + min_scale = 1; + max_scale = skl_max_scale(to_intel_crtc(crtc), crtc_state); + } can_position = true; } -- cgit v1.2.3 From 2850cfddfb052a552dfa19b75836a873e0ca1f50 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 19 Jan 2016 18:23:17 +0200 Subject: drm/i915: Fix NULL plane->fb oops on SKL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In this atomic age, we can't trust the plane->fb pointer anymore. It might get update too late. Instead we are supposed to use the plane_state->fb pointer instead. Let's do that in intel_plane_obj_offset() and avoid problems from dereferencing the potentially stale plane->fb pointer. Paulo found this with 'kms_frontbuffer_tracking --show-hidden --run-subtest nop-1p-rte' but it can be reproduced with just plain old kms_setplane. I was too lazy to bisect this, so not sure exactly when it broke. The most obvious candidate commit ce7f17285639 ("drm/i915: Fix i915_ggtt_view_equal to handle rotation correctly") was actually still fine, so it must have broken some time after that. Here's the resulting fireworks: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] intel_fill_fb_ggtt_view+0x1b/0x15a [i915] PGD 8a5f6067 PUD 8a5f5067 PMD 0 Oops: 0000 [#1] PREEMPT SMP Modules linked in: i915 i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm intel_gtt agpgart netconsole mousedev hid_generic psmouse usbhid atkbd libps2 coretemp hwmon efi_pstore intel_rapl iosf_mbi x86_pkg_temp_thermal efivars pcspkr e1000e sdhci_pci ptp pps_core sdhci i2c_i801 mmc_core i2c_hid hid i8042 serio evdev sch_fq_codel ip_tables x_tables ipv6 autofs4 CPU: 1 PID: 260 Comm: kms_plane Not tainted 4.4.0-skl+ #171 Hardware name: Intel Corporation Skylake Client platform/Skylake Y LPDDR3 RVP3, BIOS SKLSE2R1.R00.B104.B00.1511030553 11/03/2015 task: ffff88008bde2d80 ti: ffff88008a6ec000 task.ti: ffff88008a6ec000 RIP: 0010:[] [] intel_fill_fb_ggtt_view+0x1b/0x15a [i915] RSP: 0018:ffff88008a6efa10 EFLAGS: 00010086 RAX: 0000000000000001 RBX: ffff8801674f4240 RCX: 0000000000000014 RDX: ffff88008a7440c0 RSI: 0000000000000000 RDI: ffff88008a6efa40 RBP: ffff88008a6efa30 R08: ffff88008bde3598 R09: 0000000000000001 R10: ffff88008b782000 R11: 0000000000000000 R12: 0000000000000000 R13: ffff88008a7440c0 R14: 0000000000000000 R15: ffff88008a7449c0 FS: 00007fa0c07a28c0(0000) GS:ffff88016ec40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 000000008a6ff000 CR4: 00000000003406e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Stack: ffff8801674f4240 0000000000000000 ffff88008a7440c0 0000000000000000 ffff88008a6efaa0 ffffffffa02daf25 ffffffff814ec80e 0000000000070298 ffff8800850d0000 ffff88008a6efaa0 ffffffffa02c49c2 0000000000000002 Call Trace: [] intel_plane_obj_offset+0x2d/0xa9 [i915] [] ? _raw_spin_unlock_irqrestore+0x4b/0x60 [] ? gen9_write32+0x2e8/0x3b8 [i915] [] skl_update_plane+0x203/0x4c5 [i915] [] intel_plane_atomic_update+0x53/0x6a [i915] [] drm_atomic_helper_commit_planes_on_crtc+0x142/0x1d5 [drm_kms_helper] [] intel_atomic_commit+0x1262/0x1350 [i915] [] ? __drm_atomic_helper_crtc_duplicate_state+0x2f/0x41 [drm_kms_helper] [] ? drm_atomic_check_only+0x3e3/0x552 [drm] [] drm_atomic_commit+0x4d/0x52 [drm] [] drm_atomic_helper_update_plane+0xcb/0x118 [drm_kms_helper] [] __setplane_internal+0x1c8/0x224 [drm] [] drm_mode_setplane+0x14e/0x172 [drm] [] drm_ioctl+0x265/0x3ad [drm] [] ? drm_mode_cursor_common+0x158/0x158 [drm] [] ? current_kernel_time64+0x5e/0x98 [] ? trace_hardirqs_on_caller+0x17a/0x196 [] do_vfs_ioctl+0x42b/0x4ea [] ? __fget_light+0x4d/0x71 [] SyS_ioctl+0x43/0x61 [] entry_SYSCALL_64_fastpath+0x12/0x6f Cc: drm-intel-fixes@lists.freedesktop.org Cc: Paulo Zanoni Testcase: igt/kms_plane Reported-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1453220597-28973-1-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter (cherry picked from commit e794129444aba459e9bedf5080bfb4605f933c32) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 354f44793218..5feb65725c04 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2946,7 +2946,7 @@ u32 intel_plane_obj_offset(struct intel_plane *intel_plane, struct i915_vma *vma; u64 offset; - intel_fill_fb_ggtt_view(&view, intel_plane->base.fb, + intel_fill_fb_ggtt_view(&view, intel_plane->base.state->fb, intel_plane->base.state); vma = i915_gem_obj_to_ggtt_view(obj, &view); -- cgit v1.2.3 From 3fe9f21ae88e9b8f17fb2ab48745f926b5eb54b7 Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Sat, 7 Nov 2015 09:22:55 +0530 Subject: Staging: fwserial: Declare fwtty_port_get as static Declare the function fwtty_port_get as static since it is used only in this particular file. Also remove the corresponding declaration from header file. Signed-off-by: Shraddha Barke Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fwserial/fwserial.c | 3 +-- drivers/staging/fwserial/fwserial.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index b676c486cb18..e481d3230f86 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c @@ -828,7 +828,7 @@ static void fwtty_write_xchar(struct fwtty_port *port, char ch) rcu_read_unlock(); } -struct fwtty_port *fwtty_port_get(unsigned index) +static struct fwtty_port *fwtty_port_get(unsigned index) { struct fwtty_port *port; @@ -842,7 +842,6 @@ struct fwtty_port *fwtty_port_get(unsigned index) mutex_unlock(&port_table_lock); return port; } -EXPORT_SYMBOL(fwtty_port_get); static int fwtty_ports_add(struct fw_serial *serial) { diff --git a/drivers/staging/fwserial/fwserial.h b/drivers/staging/fwserial/fwserial.h index e13fe33a6897..6fa936501b3f 100644 --- a/drivers/staging/fwserial/fwserial.h +++ b/drivers/staging/fwserial/fwserial.h @@ -341,7 +341,6 @@ static const char loop_dev_name[] = "fwloop"; extern struct tty_driver *fwtty_driver; -struct fwtty_port *fwtty_port_get(unsigned index); /* * Returns the max send async payload size in bytes based on the unit device * link speed. Self-limiting asynchronous bandwidth (via reducing the payload) -- cgit v1.2.3 From 82ef33af9dd30075adbd9f3dd161b606b8ba88ac Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Sat, 26 Dec 2015 16:44:34 +0530 Subject: Staging: olpc_dcon: Remove obsolete driver Remove support for One Laptop Per Child organization since it is dead. http://www.olpcnews.com/about_olpc_news/goodbye_one_laptop_per_child.html Signed-off-by: Shraddha Barke Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 8 - drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/olpc_dcon/Kconfig | 35 -- drivers/staging/olpc_dcon/Makefile | 6 - drivers/staging/olpc_dcon/TODO | 9 - drivers/staging/olpc_dcon/olpc_dcon.c | 813 --------------------------- drivers/staging/olpc_dcon/olpc_dcon.h | 111 ---- drivers/staging/olpc_dcon/olpc_dcon_xo_1.c | 205 ------- drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c | 161 ------ 10 files changed, 1351 deletions(-) delete mode 100644 drivers/staging/olpc_dcon/Kconfig delete mode 100644 drivers/staging/olpc_dcon/Makefile delete mode 100644 drivers/staging/olpc_dcon/TODO delete mode 100644 drivers/staging/olpc_dcon/olpc_dcon.c delete mode 100644 drivers/staging/olpc_dcon/olpc_dcon.h delete mode 100644 drivers/staging/olpc_dcon/olpc_dcon_xo_1.c delete mode 100644 drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 48d09cca8505..0d85f01e7deb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10392,14 +10392,6 @@ L: linux-tegra@vger.kernel.org S: Maintained F: drivers/staging/nvec/ -STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON) -M: Jens Frederich -M: Daniel Drake -M: Jon Nettleton -W: http://wiki.laptop.org/go/DCON -S: Maintained -F: drivers/staging/olpc_dcon/ - STAGING - PARALLEL LCD/KEYPAD PANEL DRIVER M: Willy Tarreau S: Odd Fixes diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 5d3b86a33857..6c12a4871f19 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -30,8 +30,6 @@ source "drivers/staging/wlan-ng/Kconfig" source "drivers/staging/comedi/Kconfig" -source "drivers/staging/olpc_dcon/Kconfig" - source "drivers/staging/panel/Kconfig" source "drivers/staging/rtl8192u/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 30918edef5e3..af207f0492d6 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -7,7 +7,6 @@ obj-y += media/ obj-$(CONFIG_SLICOSS) += slicoss/ obj-$(CONFIG_PRISM2_USB) += wlan-ng/ obj-$(CONFIG_COMEDI) += comedi/ -obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/ obj-$(CONFIG_PANEL) += panel/ obj-$(CONFIG_RTL8192U) += rtl8192u/ obj-$(CONFIG_RTL8192E) += rtl8192e/ diff --git a/drivers/staging/olpc_dcon/Kconfig b/drivers/staging/olpc_dcon/Kconfig deleted file mode 100644 index d277f048789e..000000000000 --- a/drivers/staging/olpc_dcon/Kconfig +++ /dev/null @@ -1,35 +0,0 @@ -config FB_OLPC_DCON - tristate "One Laptop Per Child Display CONtroller support" - depends on OLPC && FB - depends on I2C - depends on (GPIO_CS5535 || GPIO_CS5535=n) - select BACKLIGHT_CLASS_DEVICE - ---help--- - In order to support very low power operation, the XO laptop uses a - secondary Display CONtroller, or DCON. This secondary controller - is present in the video pipeline between the primary display - controller (integrate into the processor or chipset) and the LCD - panel. It allows the main processor/display controller to be - completely powered off while still retaining an image on the display. - This controller is only available on OLPC platforms. Unless you have - one of these platforms, you will want to say 'N'. - -config FB_OLPC_DCON_1 - bool "OLPC XO-1 DCON support" - depends on FB_OLPC_DCON && GPIO_CS5535 - default y - ---help--- - Enable support for the DCON in XO-1 model laptops. The kernel - communicates with the DCON using model-specific code. If you - have an XO-1 (or if you're unsure what model you have), you should - say 'Y'. - -config FB_OLPC_DCON_1_5 - bool "OLPC XO-1.5 DCON support" - depends on FB_OLPC_DCON && ACPI - default y - ---help--- - Enable support for the DCON in XO-1.5 model laptops. The kernel - communicates with the DCON using model-specific code. If you - have an XO-1.5 (or if you're unsure what model you have), you - should say 'Y'. diff --git a/drivers/staging/olpc_dcon/Makefile b/drivers/staging/olpc_dcon/Makefile deleted file mode 100644 index 36c7e67fec20..000000000000 --- a/drivers/staging/olpc_dcon/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -olpc-dcon-objs += olpc_dcon.o -olpc-dcon-$(CONFIG_FB_OLPC_DCON_1) += olpc_dcon_xo_1.o -olpc-dcon-$(CONFIG_FB_OLPC_DCON_1_5) += olpc_dcon_xo_1_5.o -obj-$(CONFIG_FB_OLPC_DCON) += olpc-dcon.o - - diff --git a/drivers/staging/olpc_dcon/TODO b/drivers/staging/olpc_dcon/TODO deleted file mode 100644 index 61c2e65ac354..000000000000 --- a/drivers/staging/olpc_dcon/TODO +++ /dev/null @@ -1,9 +0,0 @@ -TODO: - - see if vx855 gpio API can be made similar enough to cs5535 so we can - share more code - - allow simultaneous XO-1 and XO-1.5 support - -Please send patches to Greg Kroah-Hartman and -copy: - Daniel Drake - Jens Frederich diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c deleted file mode 100644 index f45b2ef05f48..000000000000 --- a/drivers/staging/olpc_dcon/olpc_dcon.c +++ /dev/null @@ -1,813 +0,0 @@ -/* - * Mainly by David Woodhouse, somewhat modified by Jordan Crouse - * - * Copyright © 2006-2007 Red Hat, Inc. - * Copyright © 2006-2007 Advanced Micro Devices, Inc. - * Copyright © 2009 VIA Technology, Inc. - * Copyright (c) 2010-2011 Andres Salomon - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "olpc_dcon.h" - -/* Module definitions */ - -static ushort resumeline = 898; -module_param(resumeline, ushort, 0444); - -static struct dcon_platform_data *pdata; - -/* I2C structures */ - -/* Platform devices */ -static struct platform_device *dcon_device; - -static unsigned short normal_i2c[] = { 0x0d, I2C_CLIENT_END }; - -static s32 dcon_write(struct dcon_priv *dcon, u8 reg, u16 val) -{ - return i2c_smbus_write_word_data(dcon->client, reg, val); -} - -static s32 dcon_read(struct dcon_priv *dcon, u8 reg) -{ - return i2c_smbus_read_word_data(dcon->client, reg); -} - -/* ===== API functions - these are called by a variety of users ==== */ - -static int dcon_hw_init(struct dcon_priv *dcon, int is_init) -{ - u16 ver; - int rc = 0; - - ver = dcon_read(dcon, DCON_REG_ID); - if ((ver >> 8) != 0xDC) { - pr_err("DCON ID not 0xDCxx: 0x%04x instead.\n", ver); - rc = -ENXIO; - goto err; - } - - if (is_init) { - pr_info("Discovered DCON version %x\n", ver & 0xFF); - rc = pdata->init(dcon); - if (rc != 0) { - pr_err("Unable to init.\n"); - goto err; - } - } - - if (ver < 0xdc02) { - dev_err(&dcon->client->dev, - "DCON v1 is unsupported, giving up..\n"); - rc = -ENODEV; - goto err; - } - - /* SDRAM setup/hold time */ - dcon_write(dcon, 0x3a, 0xc040); - dcon_write(dcon, DCON_REG_MEM_OPT_A, 0x0000); /* clear option bits */ - dcon_write(dcon, DCON_REG_MEM_OPT_A, - MEM_DLL_CLOCK_DELAY | MEM_POWER_DOWN); - dcon_write(dcon, DCON_REG_MEM_OPT_B, MEM_SOFT_RESET); - - /* Colour swizzle, AA, no passthrough, backlight */ - if (is_init) { - dcon->disp_mode = MODE_PASSTHRU | MODE_BL_ENABLE | - MODE_CSWIZZLE | MODE_COL_AA; - } - dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode); - - /* Set the scanline to interrupt on during resume */ - dcon_write(dcon, DCON_REG_SCAN_INT, resumeline); - -err: - return rc; -} - -/* - * The smbus doesn't always come back due to what is believed to be - * hardware (power rail) bugs. For older models where this is known to - * occur, our solution is to attempt to wait for the bus to stabilize; - * if it doesn't happen, cut power to the dcon, repower it, and wait - * for the bus to stabilize. Rinse, repeat until we have a working - * smbus. For newer models, we simply BUG(); we want to know if this - * still happens despite the power fixes that have been made! - */ -static int dcon_bus_stabilize(struct dcon_priv *dcon, int is_powered_down) -{ - unsigned long timeout; - u8 pm; - int x; - -power_up: - if (is_powered_down) { - pm = 1; - x = olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0); - if (x) { - pr_warn("unable to force dcon to power up: %d!\n", x); - return x; - } - usleep_range(10000, 11000); /* we'll be conservative */ - } - - pdata->bus_stabilize_wiggle(); - - for (x = -1, timeout = 50; timeout && x < 0; timeout--) { - usleep_range(1000, 1100); - x = dcon_read(dcon, DCON_REG_ID); - } - if (x < 0) { - pr_err("unable to stabilize dcon's smbus, reasserting power and praying.\n"); - BUG_ON(olpc_board_at_least(olpc_board(0xc2))); - pm = 0; - olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0); - msleep(100); - is_powered_down = 1; - goto power_up; /* argh, stupid hardware.. */ - } - - if (is_powered_down) - return dcon_hw_init(dcon, 0); - return 0; -} - -static void dcon_set_backlight(struct dcon_priv *dcon, u8 level) -{ - dcon->bl_val = level; - dcon_write(dcon, DCON_REG_BRIGHT, dcon->bl_val); - - /* Purposely turn off the backlight when we go to level 0 */ - if (dcon->bl_val == 0) { - dcon->disp_mode &= ~MODE_BL_ENABLE; - dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode); - } else if (!(dcon->disp_mode & MODE_BL_ENABLE)) { - dcon->disp_mode |= MODE_BL_ENABLE; - dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode); - } -} - -/* Set the output type to either color or mono */ -static int dcon_set_mono_mode(struct dcon_priv *dcon, bool enable_mono) -{ - if (dcon->mono == enable_mono) - return 0; - - dcon->mono = enable_mono; - - if (enable_mono) { - dcon->disp_mode &= ~(MODE_CSWIZZLE | MODE_COL_AA); - dcon->disp_mode |= MODE_MONO_LUMA; - } else { - dcon->disp_mode &= ~(MODE_MONO_LUMA); - dcon->disp_mode |= MODE_CSWIZZLE | MODE_COL_AA; - } - - dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode); - return 0; -} - -/* For now, this will be really stupid - we need to address how - * DCONLOAD works in a sleep and account for it accordingly - */ - -static void dcon_sleep(struct dcon_priv *dcon, bool sleep) -{ - int x; - - /* Turn off the backlight and put the DCON to sleep */ - - if (dcon->asleep == sleep) - return; - - if (!olpc_board_at_least(olpc_board(0xc2))) - return; - - if (sleep) { - u8 pm = 0; - - x = olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0); - if (x) - pr_warn("unable to force dcon to power down: %d!\n", x); - else - dcon->asleep = sleep; - } else { - /* Only re-enable the backlight if the backlight value is set */ - if (dcon->bl_val != 0) - dcon->disp_mode |= MODE_BL_ENABLE; - x = dcon_bus_stabilize(dcon, 1); - if (x) - pr_warn("unable to reinit dcon hardware: %d!\n", x); - else - dcon->asleep = sleep; - - /* Restore backlight */ - dcon_set_backlight(dcon, dcon->bl_val); - } - - /* We should turn off some stuff in the framebuffer - but what? */ -} - -/* the DCON seems to get confused if we change DCONLOAD too - * frequently -- i.e., approximately faster than frame time. - * normally we don't change it this fast, so in general we won't - * delay here. - */ -static void dcon_load_holdoff(struct dcon_priv *dcon) -{ - ktime_t delta_t, now; - - while (1) { - now = ktime_get(); - delta_t = ktime_sub(now, dcon->load_time); - if (ktime_to_ns(delta_t) > NSEC_PER_MSEC * 20) - break; - mdelay(4); - } -} - -static bool dcon_blank_fb(struct dcon_priv *dcon, bool blank) -{ - int err; - - console_lock(); - if (!lock_fb_info(dcon->fbinfo)) { - console_unlock(); - dev_err(&dcon->client->dev, "unable to lock framebuffer\n"); - return false; - } - - dcon->ignore_fb_events = true; - err = fb_blank(dcon->fbinfo, - blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK); - dcon->ignore_fb_events = false; - unlock_fb_info(dcon->fbinfo); - console_unlock(); - - if (err) { - dev_err(&dcon->client->dev, "couldn't %sblank framebuffer\n", - blank ? "" : "un"); - return false; - } - return true; -} - -/* Set the source of the display (CPU or DCON) */ -static void dcon_source_switch(struct work_struct *work) -{ - struct dcon_priv *dcon = container_of(work, struct dcon_priv, - switch_source); - int source = dcon->pending_src; - - if (dcon->curr_src == source) - return; - - dcon_load_holdoff(dcon); - - dcon->switched = false; - - switch (source) { - case DCON_SOURCE_CPU: - pr_info("dcon_source_switch to CPU\n"); - /* Enable the scanline interrupt bit */ - if (dcon_write(dcon, DCON_REG_MODE, - dcon->disp_mode | MODE_SCAN_INT)) - pr_err("couldn't enable scanline interrupt!\n"); - else - /* Wait up to one second for the scanline interrupt */ - wait_event_timeout(dcon->waitq, dcon->switched, HZ); - - if (!dcon->switched) - pr_err("Timeout entering CPU mode; expect a screen glitch.\n"); - - /* Turn off the scanline interrupt */ - if (dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode)) - pr_err("couldn't disable scanline interrupt!\n"); - - /* - * Ideally we'd like to disable interrupts here so that the - * fb unblanking and DCON turn on happen at a known time value; - * however, we can't do that right now with fb_blank - * messing with semaphores. - * - * For now, we just hope.. - */ - if (!dcon_blank_fb(dcon, false)) { - pr_err("Failed to enter CPU mode\n"); - dcon->pending_src = DCON_SOURCE_DCON; - return; - } - - /* And turn off the DCON */ - pdata->set_dconload(1); - dcon->load_time = ktime_get(); - - pr_info("The CPU has control\n"); - break; - case DCON_SOURCE_DCON: - { - ktime_t delta_t; - - pr_info("dcon_source_switch to DCON\n"); - - /* Clear DCONLOAD - this implies that the DCON is in control */ - pdata->set_dconload(0); - dcon->load_time = ktime_get(); - - wait_event_timeout(dcon->waitq, dcon->switched, HZ/2); - - if (!dcon->switched) { - pr_err("Timeout entering DCON mode; expect a screen glitch.\n"); - } else { - /* sometimes the DCON doesn't follow its own rules, - * and doesn't wait for two vsync pulses before - * ack'ing the frame load with an IRQ. the result - * is that the display shows the *previously* - * loaded frame. we can detect this by looking at - * the time between asserting DCONLOAD and the IRQ -- - * if it's less than 20msec, then the DCON couldn't - * have seen two VSYNC pulses. in that case we - * deassert and reassert, and hope for the best. - * see http://dev.laptop.org/ticket/9664 - */ - delta_t = ktime_sub(dcon->irq_time, dcon->load_time); - if (dcon->switched && ktime_to_ns(delta_t) - < NSEC_PER_MSEC * 20) { - pr_err("missed loading, retrying\n"); - pdata->set_dconload(1); - mdelay(41); - pdata->set_dconload(0); - dcon->load_time = ktime_get(); - mdelay(41); - } - } - - dcon_blank_fb(dcon, true); - pr_info("The DCON has control\n"); - break; - } - default: - BUG(); - } - - dcon->curr_src = source; -} - -static void dcon_set_source(struct dcon_priv *dcon, int arg) -{ - if (dcon->pending_src == arg) - return; - - dcon->pending_src = arg; - - if (dcon->curr_src != arg) - schedule_work(&dcon->switch_source); -} - -static void dcon_set_source_sync(struct dcon_priv *dcon, int arg) -{ - dcon_set_source(dcon, arg); - flush_scheduled_work(); -} - -static ssize_t dcon_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct dcon_priv *dcon = dev_get_drvdata(dev); - - return sprintf(buf, "%4.4X\n", dcon->disp_mode); -} - -static ssize_t dcon_sleep_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct dcon_priv *dcon = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", dcon->asleep); -} - -static ssize_t dcon_freeze_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct dcon_priv *dcon = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", dcon->curr_src == DCON_SOURCE_DCON ? 1 : 0); -} - -static ssize_t dcon_mono_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct dcon_priv *dcon = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", dcon->mono); -} - -static ssize_t dcon_resumeline_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", resumeline); -} - -static ssize_t dcon_mono_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - unsigned long enable_mono; - int rc; - - rc = kstrtoul(buf, 10, &enable_mono); - if (rc) - return rc; - - dcon_set_mono_mode(dev_get_drvdata(dev), enable_mono ? true : false); - - return count; -} - -static ssize_t dcon_freeze_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct dcon_priv *dcon = dev_get_drvdata(dev); - unsigned long output; - int ret; - - ret = kstrtoul(buf, 10, &output); - if (ret) - return ret; - - pr_info("dcon_freeze_store: %lu\n", output); - - switch (output) { - case 0: - dcon_set_source(dcon, DCON_SOURCE_CPU); - break; - case 1: - dcon_set_source_sync(dcon, DCON_SOURCE_DCON); - break; - case 2: /* normally unused */ - dcon_set_source(dcon, DCON_SOURCE_DCON); - break; - default: - return -EINVAL; - } - - return count; -} - -static ssize_t dcon_resumeline_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - unsigned short rl; - int rc; - - rc = kstrtou16(buf, 10, &rl); - if (rc) - return rc; - - resumeline = rl; - dcon_write(dev_get_drvdata(dev), DCON_REG_SCAN_INT, resumeline); - - return count; -} - -static ssize_t dcon_sleep_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - unsigned long output; - int ret; - - ret = kstrtoul(buf, 10, &output); - if (ret) - return ret; - - dcon_sleep(dev_get_drvdata(dev), output ? true : false); - return count; -} - -static struct device_attribute dcon_device_files[] = { - __ATTR(mode, 0444, dcon_mode_show, NULL), - __ATTR(sleep, 0644, dcon_sleep_show, dcon_sleep_store), - __ATTR(freeze, 0644, dcon_freeze_show, dcon_freeze_store), - __ATTR(monochrome, 0644, dcon_mono_show, dcon_mono_store), - __ATTR(resumeline, 0644, dcon_resumeline_show, dcon_resumeline_store), -}; - -static int dcon_bl_update(struct backlight_device *dev) -{ - struct dcon_priv *dcon = bl_get_data(dev); - u8 level = dev->props.brightness & 0x0F; - - if (dev->props.power != FB_BLANK_UNBLANK) - level = 0; - - if (level != dcon->bl_val) - dcon_set_backlight(dcon, level); - - /* power down the DCON when the screen is blanked */ - if (!dcon->ignore_fb_events) - dcon_sleep(dcon, !!(dev->props.state & BL_CORE_FBBLANK)); - - return 0; -} - -static int dcon_bl_get(struct backlight_device *dev) -{ - struct dcon_priv *dcon = bl_get_data(dev); - - return dcon->bl_val; -} - -static const struct backlight_ops dcon_bl_ops = { - .update_status = dcon_bl_update, - .get_brightness = dcon_bl_get, -}; - -static struct backlight_properties dcon_bl_props = { - .max_brightness = 15, - .type = BACKLIGHT_RAW, - .power = FB_BLANK_UNBLANK, -}; - -static int dcon_reboot_notify(struct notifier_block *nb, - unsigned long foo, void *bar) -{ - struct dcon_priv *dcon = container_of(nb, struct dcon_priv, reboot_nb); - - if (!dcon || !dcon->client) - return NOTIFY_DONE; - - /* Turn off the DCON. Entirely. */ - dcon_write(dcon, DCON_REG_MODE, 0x39); - dcon_write(dcon, DCON_REG_MODE, 0x32); - return NOTIFY_DONE; -} - -static int unfreeze_on_panic(struct notifier_block *nb, - unsigned long e, void *p) -{ - pdata->set_dconload(1); - return NOTIFY_DONE; -} - -static struct notifier_block dcon_panic_nb = { - .notifier_call = unfreeze_on_panic, -}; - -static int dcon_detect(struct i2c_client *client, struct i2c_board_info *info) -{ - strlcpy(info->type, "olpc_dcon", I2C_NAME_SIZE); - - return 0; -} - -static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct dcon_priv *dcon; - int rc, i, j; - - if (!pdata) - return -ENXIO; - - dcon = kzalloc(sizeof(*dcon), GFP_KERNEL); - if (!dcon) - return -ENOMEM; - - dcon->client = client; - init_waitqueue_head(&dcon->waitq); - INIT_WORK(&dcon->switch_source, dcon_source_switch); - dcon->reboot_nb.notifier_call = dcon_reboot_notify; - dcon->reboot_nb.priority = -1; - - i2c_set_clientdata(client, dcon); - - if (num_registered_fb < 1) { - dev_err(&client->dev, "DCON driver requires a registered fb\n"); - rc = -EIO; - goto einit; - } - dcon->fbinfo = registered_fb[0]; - - rc = dcon_hw_init(dcon, 1); - if (rc) - goto einit; - - /* Add the DCON device */ - - dcon_device = platform_device_alloc("dcon", -1); - - if (!dcon_device) { - pr_err("Unable to create the DCON device\n"); - rc = -ENOMEM; - goto eirq; - } - rc = platform_device_add(dcon_device); - platform_set_drvdata(dcon_device, dcon); - - if (rc) { - pr_err("Unable to add the DCON device\n"); - goto edev; - } - - for (i = 0; i < ARRAY_SIZE(dcon_device_files); i++) { - rc = device_create_file(&dcon_device->dev, - &dcon_device_files[i]); - if (rc) { - dev_err(&dcon_device->dev, "Cannot create sysfs file\n"); - goto ecreate; - } - } - - dcon->bl_val = dcon_read(dcon, DCON_REG_BRIGHT) & 0x0F; - - /* Add the backlight device for the DCON */ - dcon_bl_props.brightness = dcon->bl_val; - dcon->bl_dev = backlight_device_register("dcon-bl", &dcon_device->dev, - dcon, &dcon_bl_ops, &dcon_bl_props); - if (IS_ERR(dcon->bl_dev)) { - dev_err(&client->dev, "cannot register backlight dev (%ld)\n", - PTR_ERR(dcon->bl_dev)); - dcon->bl_dev = NULL; - } - - register_reboot_notifier(&dcon->reboot_nb); - atomic_notifier_chain_register(&panic_notifier_list, &dcon_panic_nb); - - return 0; - - ecreate: - for (j = 0; j < i; j++) - device_remove_file(&dcon_device->dev, &dcon_device_files[j]); - edev: - platform_device_unregister(dcon_device); - dcon_device = NULL; - eirq: - free_irq(DCON_IRQ, dcon); - einit: - kfree(dcon); - return rc; -} - -static int dcon_remove(struct i2c_client *client) -{ - struct dcon_priv *dcon = i2c_get_clientdata(client); - - unregister_reboot_notifier(&dcon->reboot_nb); - atomic_notifier_chain_unregister(&panic_notifier_list, &dcon_panic_nb); - - free_irq(DCON_IRQ, dcon); - - backlight_device_unregister(dcon->bl_dev); - - if (dcon_device) - platform_device_unregister(dcon_device); - cancel_work_sync(&dcon->switch_source); - - kfree(dcon); - - return 0; -} - -#ifdef CONFIG_PM -static int dcon_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct dcon_priv *dcon = i2c_get_clientdata(client); - - if (!dcon->asleep) { - /* Set up the DCON to have the source */ - dcon_set_source_sync(dcon, DCON_SOURCE_DCON); - } - - return 0; -} - -static int dcon_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct dcon_priv *dcon = i2c_get_clientdata(client); - - if (!dcon->asleep) { - dcon_bus_stabilize(dcon, 0); - dcon_set_source(dcon, DCON_SOURCE_CPU); - } - - return 0; -} - -#else - -#define dcon_suspend NULL -#define dcon_resume NULL - -#endif /* CONFIG_PM */ - -irqreturn_t dcon_interrupt(int irq, void *id) -{ - struct dcon_priv *dcon = id; - u8 status; - - if (pdata->read_status(&status)) - return IRQ_NONE; - - switch (status & 3) { - case 3: - pr_debug("DCONLOAD_MISSED interrupt\n"); - break; - - case 2: /* switch to DCON mode */ - case 1: /* switch to CPU mode */ - dcon->switched = true; - dcon->irq_time = ktime_get(); - wake_up(&dcon->waitq); - break; - - case 0: - /* workaround resume case: the DCON (on 1.5) doesn't - * ever assert status 0x01 when switching to CPU mode - * during resume. this is because DCONLOAD is de-asserted - * _immediately_ upon exiting S3, so the actual release - * of the DCON happened long before this point. - * see http://dev.laptop.org/ticket/9869 - */ - if (dcon->curr_src != dcon->pending_src && !dcon->switched) { - dcon->switched = true; - dcon->irq_time = ktime_get(); - wake_up(&dcon->waitq); - pr_debug("switching w/ status 0/0\n"); - } else { - pr_debug("scanline interrupt w/CPU\n"); - } - } - - return IRQ_HANDLED; -} - -static const struct dev_pm_ops dcon_pm_ops = { - .suspend = dcon_suspend, - .resume = dcon_resume, -}; - -static const struct i2c_device_id dcon_idtable[] = { - { "olpc_dcon", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, dcon_idtable); - -static struct i2c_driver dcon_driver = { - .driver = { - .name = "olpc_dcon", - .pm = &dcon_pm_ops, - }, - .class = I2C_CLASS_DDC | I2C_CLASS_HWMON, - .id_table = dcon_idtable, - .probe = dcon_probe, - .remove = dcon_remove, - .detect = dcon_detect, - .address_list = normal_i2c, -}; - -static int __init olpc_dcon_init(void) -{ -#ifdef CONFIG_FB_OLPC_DCON_1_5 - /* XO-1.5 */ - if (olpc_board_at_least(olpc_board(0xd0))) - pdata = &dcon_pdata_xo_1_5; -#endif -#ifdef CONFIG_FB_OLPC_DCON_1 - if (!pdata) - pdata = &dcon_pdata_xo_1; -#endif - - return i2c_add_driver(&dcon_driver); -} - -static void __exit olpc_dcon_exit(void) -{ - i2c_del_driver(&dcon_driver); -} - -module_init(olpc_dcon_init); -module_exit(olpc_dcon_exit); - -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/olpc_dcon/olpc_dcon.h b/drivers/staging/olpc_dcon/olpc_dcon.h deleted file mode 100644 index 215e7ec4dea2..000000000000 --- a/drivers/staging/olpc_dcon/olpc_dcon.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef OLPC_DCON_H_ -#define OLPC_DCON_H_ - -#include -#include - -/* DCON registers */ - -#define DCON_REG_ID 0 -#define DCON_REG_MODE 1 - -#define MODE_PASSTHRU (1<<0) -#define MODE_SLEEP (1<<1) -#define MODE_SLEEP_AUTO (1<<2) -#define MODE_BL_ENABLE (1<<3) -#define MODE_BLANK (1<<4) -#define MODE_CSWIZZLE (1<<5) -#define MODE_COL_AA (1<<6) -#define MODE_MONO_LUMA (1<<7) -#define MODE_SCAN_INT (1<<8) -#define MODE_CLOCKDIV (1<<9) -#define MODE_DEBUG (1<<14) -#define MODE_SELFTEST (1<<15) - -#define DCON_REG_HRES 0x2 -#define DCON_REG_HTOTAL 0x3 -#define DCON_REG_HSYNC_WIDTH 0x4 -#define DCON_REG_VRES 0x5 -#define DCON_REG_VTOTAL 0x6 -#define DCON_REG_VSYNC_WIDTH 0x7 -#define DCON_REG_TIMEOUT 0x8 -#define DCON_REG_SCAN_INT 0x9 -#define DCON_REG_BRIGHT 0xa -#define DCON_REG_MEM_OPT_A 0x41 -#define DCON_REG_MEM_OPT_B 0x42 - -/* Load Delay Locked Loop (DLL) settings for clock delay */ -#define MEM_DLL_CLOCK_DELAY (1<<0) -/* Memory controller power down function */ -#define MEM_POWER_DOWN (1<<8) -/* Memory controller software reset */ -#define MEM_SOFT_RESET (1<<0) - -/* Status values */ - -#define DCONSTAT_SCANINT 0 -#define DCONSTAT_SCANINT_DCON 1 -#define DCONSTAT_DISPLAYLOAD 2 -#define DCONSTAT_MISSED 3 - -/* Source values */ - -#define DCON_SOURCE_DCON 0 -#define DCON_SOURCE_CPU 1 - -/* Interrupt */ -#define DCON_IRQ 6 - -struct dcon_priv { - struct i2c_client *client; - struct fb_info *fbinfo; - struct backlight_device *bl_dev; - - wait_queue_head_t waitq; - struct work_struct switch_source; - struct notifier_block reboot_nb; - - /* Shadow register for the DCON_REG_MODE register */ - u8 disp_mode; - - /* The current backlight value - this saves us some smbus traffic */ - u8 bl_val; - - /* Current source, initialized at probe time */ - int curr_src; - - /* Desired source */ - int pending_src; - - /* Variables used during switches */ - bool switched; - ktime_t irq_time; - ktime_t load_time; - - /* Current output type; true == mono, false == color */ - bool mono; - bool asleep; - /* This get set while controlling fb blank state from the driver */ - bool ignore_fb_events; -}; - -struct dcon_platform_data { - int (*init)(struct dcon_priv *); - void (*bus_stabilize_wiggle)(void); - void (*set_dconload)(int); - int (*read_status)(u8 *); -}; - -#include - -irqreturn_t dcon_interrupt(int irq, void *id); - -#ifdef CONFIG_FB_OLPC_DCON_1 -extern struct dcon_platform_data dcon_pdata_xo_1; -#endif - -#ifdef CONFIG_FB_OLPC_DCON_1_5 -extern struct dcon_platform_data dcon_pdata_xo_1_5; -#endif - -#endif diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c deleted file mode 100644 index 0c5a10c69401..000000000000 --- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Mainly by David Woodhouse, somewhat modified by Jordan Crouse - * - * Copyright © 2006-2007 Red Hat, Inc. - * Copyright © 2006-2007 Advanced Micro Devices, Inc. - * Copyright © 2009 VIA Technology, Inc. - * Copyright (c) 2010 Andres Salomon - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include - -#include "olpc_dcon.h" - -static int dcon_init_xo_1(struct dcon_priv *dcon) -{ - unsigned char lob; - - if (gpio_request(OLPC_GPIO_DCON_STAT0, "OLPC-DCON")) { - pr_err("failed to request STAT0 GPIO\n"); - return -EIO; - } - if (gpio_request(OLPC_GPIO_DCON_STAT1, "OLPC-DCON")) { - pr_err("failed to request STAT1 GPIO\n"); - goto err_gp_stat1; - } - if (gpio_request(OLPC_GPIO_DCON_IRQ, "OLPC-DCON")) { - pr_err("failed to request IRQ GPIO\n"); - goto err_gp_irq; - } - if (gpio_request(OLPC_GPIO_DCON_LOAD, "OLPC-DCON")) { - pr_err("failed to request LOAD GPIO\n"); - goto err_gp_load; - } - if (gpio_request(OLPC_GPIO_DCON_BLANK, "OLPC-DCON")) { - pr_err("failed to request BLANK GPIO\n"); - goto err_gp_blank; - } - - /* Turn off the event enable for GPIO7 just to be safe */ - cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_EVENTS_ENABLE); - - /* - * Determine the current state by reading the GPIO bit; earlier - * stages of the boot process have established the state. - * - * Note that we read GPIO_OUTPUT_VAL rather than GPIO_READ_BACK here; - * this is because OFW will disable input for the pin and set a value.. - * READ_BACK will only contain a valid value if input is enabled and - * then a value is set. So, future readings of the pin can use - * READ_BACK, but the first one cannot. Awesome, huh? - */ - dcon->curr_src = cs5535_gpio_isset(OLPC_GPIO_DCON_LOAD, GPIO_OUTPUT_VAL) - ? DCON_SOURCE_CPU - : DCON_SOURCE_DCON; - dcon->pending_src = dcon->curr_src; - - /* Set the directions for the GPIO pins */ - gpio_direction_input(OLPC_GPIO_DCON_STAT0); - gpio_direction_input(OLPC_GPIO_DCON_STAT1); - gpio_direction_input(OLPC_GPIO_DCON_IRQ); - gpio_direction_input(OLPC_GPIO_DCON_BLANK); - gpio_direction_output(OLPC_GPIO_DCON_LOAD, - dcon->curr_src == DCON_SOURCE_CPU); - - /* Set up the interrupt mappings */ - - /* Set the IRQ to pair 2 */ - cs5535_gpio_setup_event(OLPC_GPIO_DCON_IRQ, 2, 0); - - /* Enable group 2 to trigger the DCON interrupt */ - cs5535_gpio_set_irq(2, DCON_IRQ); - - /* Select edge level for interrupt (in PIC) */ - lob = inb(0x4d0); - lob &= ~(1 << DCON_IRQ); - outb(lob, 0x4d0); - - /* Register the interrupt handler */ - if (request_irq(DCON_IRQ, &dcon_interrupt, 0, "DCON", dcon)) { - pr_err("failed to request DCON's irq\n"); - goto err_req_irq; - } - - /* Clear INV_EN for GPIO7 (DCONIRQ) */ - cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_INVERT); - - /* Enable filter for GPIO12 (DCONBLANK) */ - cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_INPUT_FILTER); - - /* Disable filter for GPIO7 */ - cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_FILTER); - - /* Disable event counter for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */ - cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_EVENT_COUNT); - cs5535_gpio_clear(OLPC_GPIO_DCON_BLANK, GPIO_INPUT_EVENT_COUNT); - - /* Add GPIO12 to the Filter Event Pair #7 */ - cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_FE7_SEL); - - /* Turn off negative Edge Enable for GPIO12 */ - cs5535_gpio_clear(OLPC_GPIO_DCON_BLANK, GPIO_NEGATIVE_EDGE_EN); - - /* Enable negative Edge Enable for GPIO7 */ - cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_EN); - - /* Zero the filter amount for Filter Event Pair #7 */ - cs5535_gpio_set(0, GPIO_FLTR7_AMOUNT); - - /* Clear the negative edge status for GPIO7 and GPIO12 */ - cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_STS); - cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_NEGATIVE_EDGE_STS); - - /* FIXME: Clear the positive status as well, just to be sure */ - cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_POSITIVE_EDGE_STS); - cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_POSITIVE_EDGE_STS); - - /* Enable events for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */ - cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_EVENTS_ENABLE); - cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_EVENTS_ENABLE); - - return 0; - -err_req_irq: - gpio_free(OLPC_GPIO_DCON_BLANK); -err_gp_blank: - gpio_free(OLPC_GPIO_DCON_LOAD); -err_gp_load: - gpio_free(OLPC_GPIO_DCON_IRQ); -err_gp_irq: - gpio_free(OLPC_GPIO_DCON_STAT1); -err_gp_stat1: - gpio_free(OLPC_GPIO_DCON_STAT0); - return -EIO; -} - -static void dcon_wiggle_xo_1(void) -{ - int x; - - /* - * According to HiMax, when powering the DCON up we should hold - * SMB_DATA high for 8 SMB_CLK cycles. This will force the DCON - * state machine to reset to a (sane) initial state. Mitch Bradley - * did some testing and discovered that holding for 16 SMB_CLK cycles - * worked a lot more reliably, so that's what we do here. - * - * According to the cs5536 spec, to set GPIO14 to SMB_CLK we must - * simultaneously set AUX1 IN/OUT to GPIO14; ditto for SMB_DATA and - * GPIO15. - */ - cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL); - cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_VAL); - cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_ENABLE); - cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_ENABLE); - cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX1); - cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX1); - cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX2); - cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX2); - cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_INPUT_AUX1); - cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_INPUT_AUX1); - - for (x = 0; x < 16; x++) { - udelay(5); - cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL); - udelay(5); - cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL); - } - udelay(5); - cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX1); - cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX1); - cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_INPUT_AUX1); - cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_INPUT_AUX1); -} - -static void dcon_set_dconload_1(int val) -{ - gpio_set_value(OLPC_GPIO_DCON_LOAD, val); -} - -static int dcon_read_status_xo_1(u8 *status) -{ - *status = gpio_get_value(OLPC_GPIO_DCON_STAT0); - *status |= gpio_get_value(OLPC_GPIO_DCON_STAT1) << 1; - - /* Clear the negative edge status for GPIO7 */ - cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_STS); - - return 0; -} - -struct dcon_platform_data dcon_pdata_xo_1 = { - .init = dcon_init_xo_1, - .bus_stabilize_wiggle = dcon_wiggle_xo_1, - .set_dconload = dcon_set_dconload_1, - .read_status = dcon_read_status_xo_1, -}; diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c deleted file mode 100644 index 6a4d379c16a3..000000000000 --- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2009,2010 One Laptop per Child - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include - -/* TODO: this eventually belongs in linux/vx855.h */ -#define NR_VX855_GPI 14 -#define NR_VX855_GPO 13 -#define NR_VX855_GPIO 15 - -#define VX855_GPI(n) (n) -#define VX855_GPO(n) (NR_VX855_GPI + (n)) -#define VX855_GPIO(n) (NR_VX855_GPI + NR_VX855_GPO + (n)) - -#include "olpc_dcon.h" - -/* Hardware setup on the XO 1.5: - * DCONLOAD connects to VX855_GPIO1 (not SMBCK2) - * DCONBLANK connects to VX855_GPIO8 (not SSPICLK) unused in driver - * DCONSTAT0 connects to VX855_GPI10 (not SSPISDI) - * DCONSTAT1 connects to VX855_GPI11 (not nSSPISS) - * DCONIRQ connects to VX855_GPIO12 - * DCONSMBDATA connects to VX855 graphics CRTSPD - * DCONSMBCLK connects to VX855 graphics CRTSPCLK - */ - -#define VX855_GENL_PURPOSE_OUTPUT 0x44c /* PMIO_Rx4c-4f */ -#define VX855_GPI_STATUS_CHG 0x450 /* PMIO_Rx50 */ -#define VX855_GPI_SCI_SMI 0x452 /* PMIO_Rx52 */ -#define BIT_GPIO12 0x40 - -#define PREFIX "OLPC DCON:" - -static void dcon_clear_irq(void) -{ - /* irq status will appear in PMIO_Rx50[6] (RW1C) on gpio12 */ - outb(BIT_GPIO12, VX855_GPI_STATUS_CHG); -} - -static int dcon_was_irq(void) -{ - u_int8_t tmp; - - /* irq status will appear in PMIO_Rx50[6] on gpio12 */ - tmp = inb(VX855_GPI_STATUS_CHG); - return !!(tmp & BIT_GPIO12); - - return 0; -} - -static int dcon_init_xo_1_5(struct dcon_priv *dcon) -{ - unsigned int irq; - - dcon_clear_irq(); - - /* set PMIO_Rx52[6] to enable SCI/SMI on gpio12 */ - outb(inb(VX855_GPI_SCI_SMI)|BIT_GPIO12, VX855_GPI_SCI_SMI); - - /* Determine the current state of DCONLOAD, likely set by firmware */ - /* GPIO1 */ - dcon->curr_src = (inl(VX855_GENL_PURPOSE_OUTPUT) & 0x1000) ? - DCON_SOURCE_CPU : DCON_SOURCE_DCON; - dcon->pending_src = dcon->curr_src; - - /* we're sharing the IRQ with ACPI */ - irq = acpi_gbl_FADT.sci_interrupt; - if (request_irq(irq, &dcon_interrupt, IRQF_SHARED, "DCON", dcon)) { - pr_err("DCON (IRQ%d) allocation failed\n", irq); - return 1; - } - - return 0; -} - -static void set_i2c_line(int sda, int scl) -{ - unsigned char tmp; - unsigned int port = 0x26; - - /* FIXME: This directly accesses the CRT GPIO controller !!! */ - outb(port, 0x3c4); - tmp = inb(0x3c5); - - if (scl) - tmp |= 0x20; - else - tmp &= ~0x20; - - if (sda) - tmp |= 0x10; - else - tmp &= ~0x10; - - tmp |= 0x01; - - outb(port, 0x3c4); - outb(tmp, 0x3c5); -} - - -static void dcon_wiggle_xo_1_5(void) -{ - int x; - - /* - * According to HiMax, when powering the DCON up we should hold - * SMB_DATA high for 8 SMB_CLK cycles. This will force the DCON - * state machine to reset to a (sane) initial state. Mitch Bradley - * did some testing and discovered that holding for 16 SMB_CLK cycles - * worked a lot more reliably, so that's what we do here. - */ - set_i2c_line(1, 1); - - for (x = 0; x < 16; x++) { - udelay(5); - set_i2c_line(1, 0); - udelay(5); - set_i2c_line(1, 1); - } - udelay(5); - - /* set PMIO_Rx52[6] to enable SCI/SMI on gpio12 */ - outb(inb(VX855_GPI_SCI_SMI)|BIT_GPIO12, VX855_GPI_SCI_SMI); -} - -static void dcon_set_dconload_xo_1_5(int val) -{ - gpio_set_value(VX855_GPIO(1), val); -} - -static int dcon_read_status_xo_1_5(u8 *status) -{ - if (!dcon_was_irq()) - return -1; - - /* i believe this is the same as "inb(0x44b) & 3" */ - *status = gpio_get_value(VX855_GPI(10)); - *status |= gpio_get_value(VX855_GPI(11)) << 1; - - dcon_clear_irq(); - - return 0; -} - -struct dcon_platform_data dcon_pdata_xo_1_5 = { - .init = dcon_init_xo_1_5, - .bus_stabilize_wiggle = dcon_wiggle_xo_1_5, - .set_dconload = dcon_set_dconload_xo_1_5, - .read_status = dcon_read_status_xo_1_5, -}; -- cgit v1.2.3 From 7e3933df9874b70745548ce9177295d11c58fc21 Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Sat, 26 Dec 2015 17:36:07 +0530 Subject: Staging: dgap: Remove obsolete driver Remove support for dgap driver since there is no way to get the firmware files required by the dgap driver into the linux- firmware tree. The dgap driver is rendered useless without this firmware and hence this product is considered obsolete by DIGI. Signed-off-by: Shraddha Barke Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 7 - drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/dgap/Kconfig | 6 - drivers/staging/dgap/Makefile | 1 - drivers/staging/dgap/dgap.c | 7079 ----------------------------------------- drivers/staging/dgap/dgap.h | 1229 ------- 7 files changed, 8325 deletions(-) delete mode 100644 drivers/staging/dgap/Kconfig delete mode 100644 drivers/staging/dgap/Makefile delete mode 100644 drivers/staging/dgap/dgap.c delete mode 100644 drivers/staging/dgap/dgap.h (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 0d85f01e7deb..79f7eb25ecd8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3538,13 +3538,6 @@ L: driverdev-devel@linuxdriverproject.org S: Maintained F: drivers/staging/dgnc/ -DIGI EPCA PCI PRODUCTS -M: Lidza Louina -M: Daeseok Youn -L: driverdev-devel@linuxdriverproject.org -S: Maintained -F: drivers/staging/dgap/ - DIOLAN U2C-12 I2C DRIVER M: Guenter Roeck L: linux-i2c@vger.kernel.org diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 6c12a4871f19..e80268ae8c9d 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -90,8 +90,6 @@ source "drivers/staging/lustre/Kconfig" source "drivers/staging/dgnc/Kconfig" -source "drivers/staging/dgap/Kconfig" - source "drivers/staging/gs_fpgaboot/Kconfig" source "drivers/staging/skein/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index af207f0492d6..ba160f1ec02d 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -36,7 +36,6 @@ obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/ obj-$(CONFIG_GOLDFISH) += goldfish/ obj-$(CONFIG_LUSTRE_FS) += lustre/ obj-$(CONFIG_DGNC) += dgnc/ -obj-$(CONFIG_DGAP) += dgap/ obj-$(CONFIG_MTD_SPINAND_MT29F) += mt29f_spinand/ obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/ obj-$(CONFIG_CRYPTO_SKEIN) += skein/ diff --git a/drivers/staging/dgap/Kconfig b/drivers/staging/dgap/Kconfig deleted file mode 100644 index 3bbe9e122365..000000000000 --- a/drivers/staging/dgap/Kconfig +++ /dev/null @@ -1,6 +0,0 @@ -config DGAP - tristate "Digi EPCA PCI products" - default n - depends on TTY && HAS_IOMEM - ---help--- - Driver for the Digi International EPCA PCI based product line diff --git a/drivers/staging/dgap/Makefile b/drivers/staging/dgap/Makefile deleted file mode 100644 index 0063d044ca71..000000000000 --- a/drivers/staging/dgap/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_DGAP) += dgap.o diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c deleted file mode 100644 index bad355100825..000000000000 --- a/drivers/staging/dgap/dgap.c +++ /dev/null @@ -1,7079 +0,0 @@ -/* - * Copyright 2003 Digi International (www.digi.com) - * Scott H Kilau - * - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - */ - -/* - * In the original out of kernel Digi dgap driver, firmware - * loading was done via user land to driver handshaking. - * - * For cards that support a concentrator (port expander), - * I believe the concentrator its self told the card which - * concentrator is actually attached and then that info - * was used to tell user land which concentrator firmware - * image was to be downloaded. I think even the BIOS or - * FEP images required could change with the connection - * of a particular concentrator. - * - * Since I have no access to any of these cards or - * concentrators, I cannot put the correct concentrator - * firmware file names into the firmware_info structure - * as is now done for the BIOS and FEP images. - * - * I think, but am not certain, that the cards supporting - * concentrators will function without them. So support - * of these cards has been left in this driver. - * - * In order to fully support those cards, they would - * either have to be acquired for dissection or maybe - * Digi International could provide some assistance. - */ -#undef DIGI_CONCENTRATORS_SUPPORTED - -#define pr_fmt(fmt) "dgap: " fmt - -#include -#include -#include -#include /* For udelay */ -#include -#include -#include - -#include /* For tasklet and interrupt structs/defines */ -#include -#include -#include -#include -#include /* For read[bwl]/write[bwl] */ - -#include -#include -#include -#include - -#include "dgap.h" - -/* - * File operations permitted on Control/Management major. - */ -static const struct file_operations dgap_board_fops = { - .owner = THIS_MODULE, -}; - -static uint dgap_numboards; -static struct board_t *dgap_board[MAXBOARDS]; -static ulong dgap_poll_counter; -static int dgap_driver_state = DRIVER_INITIALIZED; -static int dgap_poll_tick = 20; /* Poll interval - 20 ms */ - -static struct class *dgap_class; - -static uint dgap_count = 500; - -/* - * Poller stuff - */ -static DEFINE_SPINLOCK(dgap_poll_lock); /* Poll scheduling lock */ -static ulong dgap_poll_time; /* Time of next poll */ -static uint dgap_poll_stop; /* Used to tell poller to stop */ -static struct timer_list dgap_poll_timer; - -/* - SUPPORTED PRODUCTS - - Card Model Number of Ports Interface - ---------------------------------------------------------------- - Acceleport Xem 4 - 64 (EIA232 & EIA422) - Acceleport Xr 4 & 8 (EIA232) - Acceleport Xr 920 4 & 8 (EIA232) - Acceleport C/X 8 - 128 (EIA232) - Acceleport EPC/X 8 - 224 (EIA232) - Acceleport Xr/422 4 & 8 (EIA422) - Acceleport 2r/920 2 (EIA232) - Acceleport 4r/920 4 (EIA232) - Acceleport 8r/920 8 (EIA232) - - IBM 8-Port Asynchronous PCI Adapter (EIA232) - IBM 128-Port Asynchronous PCI Adapter (EIA232 & EIA422) -*/ - -static struct pci_device_id dgap_pci_tbl[] = { - { DIGI_VID, PCI_DEV_XEM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { DIGI_VID, PCI_DEV_CX_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, - { DIGI_VID, PCI_DEV_CX_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, - { DIGI_VID, PCI_DEV_EPCJ_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, - { DIGI_VID, PCI_DEV_920_2_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, - { DIGI_VID, PCI_DEV_920_4_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, - { DIGI_VID, PCI_DEV_920_8_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 }, - { DIGI_VID, PCI_DEV_XR_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 }, - { DIGI_VID, PCI_DEV_XRJ_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, - { DIGI_VID, PCI_DEV_XR_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 }, - { DIGI_VID, PCI_DEV_XR_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 }, - { DIGI_VID, PCI_DEV_XR_SAIP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 }, - { DIGI_VID, PCI_DEV_XR_BULL_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 }, - { DIGI_VID, PCI_DEV_920_8_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 }, - { DIGI_VID, PCI_DEV_XEM_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 }, - {0,} /* 0 terminated list. */ -}; -MODULE_DEVICE_TABLE(pci, dgap_pci_tbl); - -/* - * A generic list of Product names, PCI Vendor ID, and PCI Device ID. - */ -struct board_id { - uint config_type; - u8 *name; - uint maxports; - uint dpatype; -}; - -static struct board_id dgap_ids[] = { - {PPCM, PCI_DEV_XEM_NAME, 64, (T_PCXM | T_PCLITE | T_PCIBUS)}, - {PCX, PCI_DEV_CX_NAME, 128, (T_CX | T_PCIBUS) }, - {PCX, PCI_DEV_CX_IBM_NAME, 128, (T_CX | T_PCIBUS) }, - {PEPC, PCI_DEV_EPCJ_NAME, 224, (T_EPC | T_PCIBUS) }, - {APORT2_920P, PCI_DEV_920_2_NAME, 2, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {APORT4_920P, PCI_DEV_920_4_NAME, 4, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {APORT8_920P, PCI_DEV_920_8_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {PAPORT8, PCI_DEV_XR_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {PAPORT8, PCI_DEV_XRJ_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {PAPORT8, PCI_DEV_XR_422_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {PAPORT8, PCI_DEV_XR_IBM_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {PAPORT8, PCI_DEV_XR_SAIP_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {PAPORT8, PCI_DEV_XR_BULL_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {APORT8_920P, PCI_DEV_920_8_HP_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {PPCM, PCI_DEV_XEM_HP_NAME, 64, (T_PCXM | T_PCLITE | T_PCIBUS)}, - {0,} /* 0 terminated list. */ -}; - -struct firmware_info { - u8 *conf_name; /* dgap.conf */ - u8 *bios_name; /* BIOS filename */ - u8 *fep_name; /* FEP filename */ - u8 *con_name; /* Concentrator filename FIXME*/ - int num; /* sequence number */ -}; - -/* - * Firmware - BIOS, FEP, and CONC filenames - */ -static struct firmware_info fw_info[] = { - { "dgap/dgap.conf", "dgap/sxbios.bin", "dgap/sxfep.bin", NULL, 0 }, - { "dgap/dgap.conf", "dgap/cxpbios.bin", "dgap/cxpfep.bin", NULL, 1 }, - { "dgap/dgap.conf", "dgap/cxpbios.bin", "dgap/cxpfep.bin", NULL, 2 }, - { "dgap/dgap.conf", "dgap/pcibios.bin", "dgap/pcifep.bin", NULL, 3 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 4 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 5 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 6 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 7 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 8 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 9 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 10 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 11 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 12 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 13 }, - { "dgap/dgap.conf", "dgap/sxbios.bin", "dgap/sxfep.bin", NULL, 14 }, - {NULL,} -}; - -/* - * Default transparent print information. - */ -static struct digi_t dgap_digi_init = { - .digi_flags = DIGI_COOK, /* Flags */ - .digi_maxcps = 100, /* Max CPS */ - .digi_maxchar = 50, /* Max chars in print queue */ - .digi_bufsize = 100, /* Printer buffer size */ - .digi_onlen = 4, /* size of printer on string */ - .digi_offlen = 4, /* size of printer off string */ - .digi_onstr = "\033[5i", /* ANSI printer on string ] */ - .digi_offstr = "\033[4i", /* ANSI printer off string ] */ - .digi_term = "ansi" /* default terminal type */ -}; - -/* - * Define a local default termios struct. All ports will be created - * with this termios initially. - * - * This defines a raw port at 9600 baud, 8 data bits, no parity, - * 1 stop bit. - */ - -static struct ktermios dgap_default_termios = { - .c_iflag = (DEFAULT_IFLAGS), /* iflags */ - .c_oflag = (DEFAULT_OFLAGS), /* oflags */ - .c_cflag = (DEFAULT_CFLAGS), /* cflags */ - .c_lflag = (DEFAULT_LFLAGS), /* lflags */ - .c_cc = INIT_C_CC, - .c_line = 0, -}; - -/* - * Our needed internal static variables from dgap_parse.c - */ -static struct cnode dgap_head; -#define MAXCWORD 200 -static char dgap_cword[MAXCWORD]; - -struct toklist { - int token; - char *string; -}; - -static struct toklist dgap_brdtype[] = { - { PCX, "Digi_AccelePort_C/X_PCI" }, - { PEPC, "Digi_AccelePort_EPC/X_PCI" }, - { PPCM, "Digi_AccelePort_Xem_PCI" }, - { APORT2_920P, "Digi_AccelePort_2r_920_PCI" }, - { APORT4_920P, "Digi_AccelePort_4r_920_PCI" }, - { APORT8_920P, "Digi_AccelePort_8r_920_PCI" }, - { PAPORT4, "Digi_AccelePort_4r_PCI(EIA-232/RS-422)" }, - { PAPORT8, "Digi_AccelePort_8r_PCI(EIA-232/RS-422)" }, - { 0, NULL } -}; - -static struct toklist dgap_tlist[] = { - { BEGIN, "config_begin" }, - { END, "config_end" }, - { BOARD, "board" }, - { PCIINFO, "pciinfo" }, - { LINE, "line" }, - { CONC, "conc" }, - { CONC, "concentrator" }, - { CX, "cx" }, - { CX, "ccon" }, - { EPC, "epccon" }, - { EPC, "epc" }, - { MOD, "module" }, - { ID, "id" }, - { STARTO, "start" }, - { SPEED, "speed" }, - { CABLE, "cable" }, - { CONNECT, "connect" }, - { METHOD, "method" }, - { STATUS, "status" }, - { CUSTOM, "Custom" }, - { BASIC, "Basic" }, - { MEM, "mem" }, - { MEM, "memory" }, - { PORTS, "ports" }, - { MODEM, "modem" }, - { NPORTS, "nports" }, - { TTYN, "ttyname" }, - { CU, "cuname" }, - { PRINT, "prname" }, - { CMAJOR, "major" }, - { ALTPIN, "altpin" }, - { USEINTR, "useintr" }, - { TTSIZ, "ttysize" }, - { CHSIZ, "chsize" }, - { BSSIZ, "boardsize" }, - { UNTSIZ, "schedsize" }, - { F2SIZ, "f2200size" }, - { VPSIZ, "vpixsize" }, - { 0, NULL } -}; - -/* - * get a word from the input stream, also keep track of current line number. - * words are separated by whitespace. - */ -static char *dgap_getword(char **in) -{ - char *ret_ptr = *in; - - char *ptr = strpbrk(*in, " \t\n"); - - /* If no word found, return null */ - if (!ptr) - return NULL; - - /* Mark new location for our buffer */ - *ptr = '\0'; - *in = ptr + 1; - - /* Eat any extra spaces/tabs/newlines that might be present */ - while (*in && **in && ((**in == ' ') || - (**in == '\t') || - (**in == '\n'))) { - **in = '\0'; - *in = *in + 1; - } - - return ret_ptr; -} - - -/* - * Get a token from the input file; return 0 if end of file is reached - */ -static int dgap_gettok(char **in) -{ - char *w; - struct toklist *t; - - if (strstr(dgap_cword, "board")) { - w = dgap_getword(in); - if (!w) - return 0; - snprintf(dgap_cword, MAXCWORD, "%s", w); - for (t = dgap_brdtype; t->token != 0; t++) { - if (!strcmp(w, t->string)) - return t->token; - } - } else { - while ((w = dgap_getword(in))) { - snprintf(dgap_cword, MAXCWORD, "%s", w); - for (t = dgap_tlist; t->token != 0; t++) { - if (!strcmp(w, t->string)) - return t->token; - } - } - } - - return 0; -} - -/* - * dgap_checknode: see if all the necessary info has been supplied for a node - * before creating the next node. - */ -static int dgap_checknode(struct cnode *p) -{ - switch (p->type) { - case LNODE: - if (p->u.line.v_speed == 0) { - pr_err("line speed not specified"); - return 1; - } - return 0; - - case CNODE: - if (p->u.conc.v_speed == 0) { - pr_err("concentrator line speed not specified"); - return 1; - } - if (p->u.conc.v_nport == 0) { - pr_err("number of ports on concentrator not specified"); - return 1; - } - if (p->u.conc.v_id == 0) { - pr_err("concentrator id letter not specified"); - return 1; - } - return 0; - - case MNODE: - if (p->u.module.v_nport == 0) { - pr_err("number of ports on EBI module not specified"); - return 1; - } - if (p->u.module.v_id == 0) { - pr_err("EBI module id letter not specified"); - return 1; - } - return 0; - } - return 0; -} - -/* - * Given a board pointer, returns whether we should use interrupts or not. - */ -static uint dgap_config_get_useintr(struct board_t *bd) -{ - struct cnode *p; - - if (!bd) - return 0; - - for (p = bd->bd_config; p; p = p->next) { - if (p->type == INTRNODE) { - /* - * check for pcxr types. - */ - return p->u.useintr; - } - } - - /* If not found, then don't turn on interrupts. */ - return 0; -} - -/* - * Given a board pointer, returns whether we turn on altpin or not. - */ -static uint dgap_config_get_altpin(struct board_t *bd) -{ - struct cnode *p; - - if (!bd) - return 0; - - for (p = bd->bd_config; p; p = p->next) { - if (p->type == ANODE) { - /* - * check for pcxr types. - */ - return p->u.altpin; - } - } - - /* If not found, then don't turn on interrupts. */ - return 0; -} - -/* - * Given a specific type of board, if found, detached link and - * returns the first occurrence in the list. - */ -static struct cnode *dgap_find_config(int type, int bus, int slot) -{ - struct cnode *p, *prev, *prev2, *found; - - p = &dgap_head; - - while (p->next) { - prev = p; - p = p->next; - - if (p->type != BNODE) - continue; - - if (p->u.board.type != type) - continue; - - if (p->u.board.v_pcibus && - p->u.board.pcibus != bus) - continue; - - if (p->u.board.v_pcislot && - p->u.board.pcislot != slot) - continue; - - found = p; - /* - * Keep walking thru the list till we - * find the next board. - */ - while (p->next) { - prev2 = p; - p = p->next; - - if (p->type != BNODE) - continue; - - /* - * Mark the end of our 1 board - * chain of configs. - */ - prev2->next = NULL; - - /* - * Link the "next" board to the - * previous board, effectively - * "unlinking" our board from - * the main config. - */ - prev->next = p; - - return found; - } - /* - * It must be the last board in the list. - */ - prev->next = NULL; - return found; - } - return NULL; -} - -/* - * Given a board pointer, walks the config link, counting up - * all ports user specified should be on the board. - * (This does NOT mean they are all actually present right now tho) - */ -static uint dgap_config_get_num_prts(struct board_t *bd) -{ - int count = 0; - struct cnode *p; - - if (!bd) - return 0; - - for (p = bd->bd_config; p; p = p->next) { - switch (p->type) { - case BNODE: - /* - * check for pcxr types. - */ - if (p->u.board.type > EPCFE) - count += p->u.board.nport; - break; - case CNODE: - count += p->u.conc.nport; - break; - case MNODE: - count += p->u.module.nport; - break; - } - } - return count; -} - -static char *dgap_create_config_string(struct board_t *bd, char *string) -{ - char *ptr = string; - struct cnode *p; - struct cnode *q; - int speed; - - if (!bd) { - *ptr = 0xff; - return string; - } - - for (p = bd->bd_config; p; p = p->next) { - switch (p->type) { - case LNODE: - *ptr = '\0'; - ptr++; - *ptr = p->u.line.speed; - ptr++; - break; - case CNODE: - /* - * Because the EPC/con concentrators can have EM modules - * hanging off of them, we have to walk ahead in the - * list and keep adding the number of ports on each EM - * to the config. UGH! - */ - speed = p->u.conc.speed; - q = p->next; - if (q && (q->type == MNODE)) { - *ptr = (p->u.conc.nport + 0x80); - ptr++; - p = q; - while (q->next && (q->next->type) == MNODE) { - *ptr = (q->u.module.nport + 0x80); - ptr++; - p = q; - q = q->next; - } - *ptr = q->u.module.nport; - ptr++; - } else { - *ptr = p->u.conc.nport; - ptr++; - } - - *ptr = speed; - ptr++; - break; - } - } - - *ptr = 0xff; - return string; -} - -/* - * Parse a configuration file read into memory as a string. - */ -static int dgap_parsefile(char **in) -{ - struct cnode *p, *brd, *line, *conc; - int rc; - char *s; - int linecnt = 0; - - p = &dgap_head; - brd = line = conc = NULL; - - /* perhaps we are adding to an existing list? */ - while (p->next) - p = p->next; - - /* file must start with a BEGIN */ - while ((rc = dgap_gettok(in)) != BEGIN) { - if (rc == 0) { - pr_err("unexpected EOF"); - return -1; - } - } - - for (; ;) { - int board_type = 0; - int conc_type = 0; - int module_type = 0; - - rc = dgap_gettok(in); - if (rc == 0) { - pr_err("unexpected EOF"); - return -1; - } - - switch (rc) { - case BEGIN: /* should only be 1 begin */ - pr_err("unexpected config_begin\n"); - return -1; - - case END: - return 0; - - case BOARD: /* board info */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - - p->type = BNODE; - p->u.board.status = kstrdup("No", GFP_KERNEL); - line = conc = NULL; - brd = p; - linecnt = -1; - - board_type = dgap_gettok(in); - if (board_type == 0) { - pr_err("board !!type not specified"); - return -1; - } - - p->u.board.type = board_type; - - break; - - case MEM: /* memory address */ - if (p->type != BNODE) { - pr_err("memory address only valid for boards"); - return -1; - } - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - kfree(p->u.board.addrstr); - p->u.board.addrstr = kstrdup(s, GFP_KERNEL); - if (kstrtoul(s, 0, &p->u.board.addr)) { - pr_err("bad number for memory address"); - return -1; - } - p->u.board.v_addr = 1; - break; - - case PCIINFO: /* pci information */ - if (p->type != BNODE) { - pr_err("memory address only valid for boards"); - return -1; - } - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - kfree(p->u.board.pcibusstr); - p->u.board.pcibusstr = kstrdup(s, GFP_KERNEL); - if (kstrtoul(s, 0, &p->u.board.pcibus)) { - pr_err("bad number for pci bus"); - return -1; - } - p->u.board.v_pcibus = 1; - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - kfree(p->u.board.pcislotstr); - p->u.board.pcislotstr = kstrdup(s, GFP_KERNEL); - if (kstrtoul(s, 0, &p->u.board.pcislot)) { - pr_err("bad number for pci slot"); - return -1; - } - p->u.board.v_pcislot = 1; - break; - - case METHOD: - if (p->type != BNODE) { - pr_err("install method only valid for boards"); - return -1; - } - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - kfree(p->u.board.method); - p->u.board.method = kstrdup(s, GFP_KERNEL); - p->u.board.v_method = 1; - break; - - case STATUS: - if (p->type != BNODE) { - pr_err("config status only valid for boards"); - return -1; - } - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - kfree(p->u.board.status); - p->u.board.status = kstrdup(s, GFP_KERNEL); - break; - - case NPORTS: /* number of ports */ - if (p->type == BNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.board.nport)) { - pr_err("bad number for number of ports"); - return -1; - } - p->u.board.v_nport = 1; - } else if (p->type == CNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.conc.nport)) { - pr_err("bad number for number of ports"); - return -1; - } - p->u.conc.v_nport = 1; - } else if (p->type == MNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.module.nport)) { - pr_err("bad number for number of ports"); - return -1; - } - p->u.module.v_nport = 1; - } else { - pr_err("nports only valid for concentrators or modules"); - return -1; - } - break; - - case ID: /* letter ID used in tty name */ - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - kfree(p->u.board.status); - p->u.board.status = kstrdup(s, GFP_KERNEL); - - if (p->type == CNODE) { - kfree(p->u.conc.id); - p->u.conc.id = kstrdup(s, GFP_KERNEL); - p->u.conc.v_id = 1; - } else if (p->type == MNODE) { - kfree(p->u.module.id); - p->u.module.id = kstrdup(s, GFP_KERNEL); - p->u.module.v_id = 1; - } else { - pr_err("id only valid for concentrators or modules"); - return -1; - } - break; - - case STARTO: /* start offset of ID */ - if (p->type == BNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.board.start)) { - pr_err("bad number for start of tty count"); - return -1; - } - p->u.board.v_start = 1; - } else if (p->type == CNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.conc.start)) { - pr_err("bad number for start of tty count"); - return -1; - } - p->u.conc.v_start = 1; - } else if (p->type == MNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.module.start)) { - pr_err("bad number for start of tty count"); - return -1; - } - p->u.module.v_start = 1; - } else { - pr_err("start only valid for concentrators or modules"); - return -1; - } - break; - - case TTYN: /* tty name prefix */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = TNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpeced end of file"); - return -1; - } - p->u.ttyname = kstrdup(s, GFP_KERNEL); - if (!p->u.ttyname) - return -1; - - break; - - case CU: /* cu name prefix */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = CUNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpeced end of file"); - return -1; - } - p->u.cuname = kstrdup(s, GFP_KERNEL); - if (!p->u.cuname) - return -1; - - break; - - case LINE: /* line information */ - if (dgap_checknode(p)) - return -1; - if (!brd) { - pr_err("must specify board before line info"); - return -1; - } - switch (brd->u.board.type) { - case PPCM: - pr_err("line not valid for PC/em"); - return -1; - } - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = LNODE; - conc = NULL; - line = p; - linecnt++; - break; - - case CONC: /* concentrator information */ - if (dgap_checknode(p)) - return -1; - if (!line) { - pr_err("must specify line info before concentrator"); - return -1; - } - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = CNODE; - conc = p; - - if (linecnt) - brd->u.board.conc2++; - else - brd->u.board.conc1++; - - conc_type = dgap_gettok(in); - if (conc_type == 0 || - (conc_type != CX && conc_type != EPC)) { - pr_err("failed to set a type of concentratros"); - return -1; - } - - p->u.conc.type = conc_type; - - break; - - case MOD: /* EBI module */ - if (dgap_checknode(p)) - return -1; - if (!brd) { - pr_err("must specify board info before EBI modules"); - return -1; - } - switch (brd->u.board.type) { - case PPCM: - linecnt = 0; - break; - default: - if (!conc) { - pr_err("must specify concentrator info before EBI module"); - return -1; - } - } - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = MNODE; - - if (linecnt) - brd->u.board.module2++; - else - brd->u.board.module1++; - - module_type = dgap_gettok(in); - if (module_type == 0 || - (module_type != PORTS && module_type != MODEM)) { - pr_err("failed to set a type of module"); - return -1; - } - - p->u.module.type = module_type; - - break; - - case CABLE: - if (p->type == LNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - kfree(p->u.line.cable); - p->u.line.cable = kstrdup(s, GFP_KERNEL); - p->u.line.v_cable = 1; - } - break; - - case SPEED: /* sync line speed indication */ - if (p->type == LNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.line.speed)) { - pr_err("bad number for line speed"); - return -1; - } - p->u.line.v_speed = 1; - } else if (p->type == CNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.conc.speed)) { - pr_err("bad number for line speed"); - return -1; - } - p->u.conc.v_speed = 1; - } else { - pr_err("speed valid only for lines or concentrators."); - return -1; - } - break; - - case CONNECT: - if (p->type == CNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - kfree(p->u.conc.connect); - p->u.conc.connect = kstrdup(s, GFP_KERNEL); - p->u.conc.v_connect = 1; - } - break; - case PRINT: /* transparent print name prefix */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = PNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpeced end of file"); - return -1; - } - p->u.printname = kstrdup(s, GFP_KERNEL); - if (!p->u.printname) - return -1; - - break; - - case CMAJOR: /* major number */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = JNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.majornumber)) { - pr_err("bad number for major number"); - return -1; - } - break; - - case ALTPIN: /* altpin setting */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = ANODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.altpin)) { - pr_err("bad number for altpin"); - return -1; - } - break; - - case USEINTR: /* enable interrupt setting */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = INTRNODE; - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.useintr)) { - pr_err("bad number for useintr"); - return -1; - } - break; - - case TTSIZ: /* size of tty structure */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = TSNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.ttysize)) { - pr_err("bad number for ttysize"); - return -1; - } - break; - - case CHSIZ: /* channel structure size */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = CSNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.chsize)) { - pr_err("bad number for chsize"); - return -1; - } - break; - - case BSSIZ: /* board structure size */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = BSNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.bssize)) { - pr_err("bad number for bssize"); - return -1; - } - break; - - case UNTSIZ: /* sched structure size */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = USNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.unsize)) { - pr_err("bad number for schedsize"); - return -1; - } - break; - - case F2SIZ: /* f2200 structure size */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = FSNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.f2size)) { - pr_err("bad number for f2200size"); - return -1; - } - break; - - case VPSIZ: /* vpix structure size */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = VSNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.vpixsize)) { - pr_err("bad number for vpixsize"); - return -1; - } - break; - } - } -} - -static void dgap_cleanup_nodes(void) -{ - struct cnode *p; - - p = &dgap_head; - - while (p) { - struct cnode *tmp = p->next; - - if (p->type == NULLNODE) { - p = tmp; - continue; - } - - switch (p->type) { - case BNODE: - kfree(p->u.board.addrstr); - kfree(p->u.board.pcibusstr); - kfree(p->u.board.pcislotstr); - kfree(p->u.board.method); - break; - case CNODE: - kfree(p->u.conc.id); - kfree(p->u.conc.connect); - break; - case MNODE: - kfree(p->u.module.id); - break; - case TNODE: - kfree(p->u.ttyname); - break; - case CUNODE: - kfree(p->u.cuname); - break; - case LNODE: - kfree(p->u.line.cable); - break; - case PNODE: - kfree(p->u.printname); - break; - } - - kfree(p->u.board.status); - kfree(p); - p = tmp; - } -} - -/* - * Retrives the current custom baud rate from FEP memory, - * and returns it back to the user. - * Returns 0 on error. - */ -static uint dgap_get_custom_baud(struct channel_t *ch) -{ - u8 __iomem *vaddr; - ulong offset; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - - if (!ch->ch_bd || ch->ch_bd->magic != DGAP_BOARD_MAGIC) - return 0; - - if (!(ch->ch_bd->bd_flags & BD_FEP5PLUS)) - return 0; - - vaddr = ch->ch_bd->re_map_membase; - - if (!vaddr) - return 0; - - /* - * Go get from fep mem, what the fep - * believes the custom baud rate is. - */ - offset = (ioread16(vaddr + ECS_SEG) << 4) + (ch->ch_portnum * 0x28) - + LINE_SPEED; - - return readw(vaddr + offset); -} - -/* - * Remap PCI memory. - */ -static int dgap_remap(struct board_t *brd) -{ - if (!brd || brd->magic != DGAP_BOARD_MAGIC) - return -EIO; - - if (!request_mem_region(brd->membase, 0x200000, "dgap")) - return -ENOMEM; - - if (!request_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000, "dgap")) - goto err_req_mem; - - brd->re_map_membase = ioremap(brd->membase, 0x200000); - if (!brd->re_map_membase) - goto err_remap_mem; - - brd->re_map_port = ioremap((brd->membase + PCI_IO_OFFSET), 0x200000); - if (!brd->re_map_port) - goto err_remap_port; - - return 0; - -err_remap_port: - iounmap(brd->re_map_membase); -err_remap_mem: - release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000); -err_req_mem: - release_mem_region(brd->membase, 0x200000); - - return -ENOMEM; -} - -static void dgap_unmap(struct board_t *brd) -{ - iounmap(brd->re_map_port); - iounmap(brd->re_map_membase); - release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000); - release_mem_region(brd->membase, 0x200000); -} - -/* - * dgap_parity_scan() - * - * Convert the FEP5 way of reporting parity errors and breaks into - * the Linux line discipline way. - */ -static void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf, - unsigned char *fbuf, int *len) -{ - int l = *len; - int count = 0; - unsigned char *in, *cout, *fout; - unsigned char c; - - in = cbuf; - cout = cbuf; - fout = fbuf; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - while (l--) { - c = *in++; - switch (ch->pscan_state) { - default: - /* reset to sanity and fall through */ - ch->pscan_state = 0; - - case 0: - /* No FF seen yet */ - if (c == (unsigned char)'\377') - /* delete this character from stream */ - ch->pscan_state = 1; - else { - *cout++ = c; - *fout++ = TTY_NORMAL; - count += 1; - } - break; - - case 1: - /* first FF seen */ - if (c == (unsigned char)'\377') { - /* doubled ff, transform to single ff */ - *cout++ = c; - *fout++ = TTY_NORMAL; - count += 1; - ch->pscan_state = 0; - } else { - /* save value examination in next state */ - ch->pscan_savechar = c; - ch->pscan_state = 2; - } - break; - - case 2: - /* third character of ff sequence */ - - *cout++ = c; - - if (ch->pscan_savechar == 0x0) { - if (c == 0x0) { - ch->ch_err_break++; - *fout++ = TTY_BREAK; - } else { - ch->ch_err_parity++; - *fout++ = TTY_PARITY; - } - } - - count += 1; - ch->pscan_state = 0; - } - } - *len = count; -} - -/*======================================================================= - * - * dgap_input - Process received data. - * - * ch - Pointer to channel structure. - * - *=======================================================================*/ - -static void dgap_input(struct channel_t *ch) -{ - struct board_t *bd; - struct bs_t __iomem *bs; - struct tty_struct *tp; - struct tty_ldisc *ld; - uint rmask; - uint head; - uint tail; - int data_len; - ulong lock_flags; - ulong lock_flags2; - int flip_len; - int len; - int n; - u8 *buf; - u8 tmpchar; - int s; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - tp = ch->ch_tun.un_tty; - - bs = ch->ch_bs; - if (!bs) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - /* - * Figure the number of characters in the buffer. - * Exit immediately if none. - */ - - rmask = ch->ch_rsize - 1; - - head = readw(&bs->rx_head); - head &= rmask; - tail = readw(&bs->rx_tail); - tail &= rmask; - - data_len = (head - tail) & rmask; - - if (data_len == 0) { - writeb(1, &bs->idata); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return; - } - - /* - * If the device is not open, or CREAD is off, flush - * input data and return immediately. - */ - if ((bd->state != BOARD_READY) || !tp || - (tp->magic != TTY_MAGIC) || - !(ch->ch_tun.un_flags & UN_ISOPEN) || - !(tp->termios.c_cflag & CREAD) || - (ch->ch_tun.un_flags & UN_CLOSING)) { - writew(head, &bs->rx_tail); - writeb(1, &bs->idata); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return; - } - - /* - * If we are throttled, simply don't read any data. - */ - if (ch->ch_flags & CH_RXBLOCK) { - writeb(1, &bs->idata); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return; - } - - /* - * Ignore oruns. - */ - tmpchar = readb(&bs->orun); - if (tmpchar) { - ch->ch_err_overrun++; - writeb(0, &bs->orun); - } - - /* Decide how much data we can send into the tty layer */ - flip_len = TTY_FLIPBUF_SIZE; - - /* Chop down the length, if needed */ - len = min(data_len, flip_len); - len = min(len, (N_TTY_BUF_SIZE - 1)); - - ld = tty_ldisc_ref(tp); - -#ifdef TTY_DONT_FLIP - /* - * If the DONT_FLIP flag is on, don't flush our buffer, and act - * like the ld doesn't have any space to put the data right now. - */ - if (test_bit(TTY_DONT_FLIP, &tp->flags)) - len = 0; -#endif - - /* - * If we were unable to get a reference to the ld, - * don't flush our buffer, and act like the ld doesn't - * have any space to put the data right now. - */ - if (!ld) { - len = 0; - } else { - /* - * If ld doesn't have a pointer to a receive_buf function, - * flush the data, then act like the ld doesn't have any - * space to put the data right now. - */ - if (!ld->ops->receive_buf) { - writew(head, &bs->rx_tail); - len = 0; - } - } - - if (len <= 0) { - writeb(1, &bs->idata); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - if (ld) - tty_ldisc_deref(ld); - return; - } - - buf = ch->ch_bd->flipbuf; - n = len; - - /* - * n now contains the most amount of data we can copy, - * bounded either by our buffer size or the amount - * of data the card actually has pending... - */ - while (n) { - s = ((head >= tail) ? head : ch->ch_rsize) - tail; - s = min(s, n); - - if (s <= 0) - break; - - memcpy_fromio(buf, ch->ch_raddr + tail, s); - - tail += s; - buf += s; - - n -= s; - /* Flip queue if needed */ - tail &= rmask; - } - - writew(tail, &bs->rx_tail); - writeb(1, &bs->idata); - ch->ch_rxcount += len; - - /* - * If we are completely raw, we don't need to go through a lot - * of the tty layers that exist. - * In this case, we take the shortest and fastest route we - * can to relay the data to the user. - * - * On the other hand, if we are not raw, we need to go through - * the tty layer, which has its API more well defined. - */ - if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { - dgap_parity_scan(ch, ch->ch_bd->flipbuf, - ch->ch_bd->flipflagbuf, &len); - - len = tty_buffer_request_room(tp->port, len); - tty_insert_flip_string_flags(tp->port, ch->ch_bd->flipbuf, - ch->ch_bd->flipflagbuf, len); - } else { - len = tty_buffer_request_room(tp->port, len); - tty_insert_flip_string(tp->port, ch->ch_bd->flipbuf, len); - } - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - /* Tell the tty layer its okay to "eat" the data now */ - tty_flip_buffer_push(tp->port); - - if (ld) - tty_ldisc_deref(ld); -} - -static void dgap_write_wakeup(struct board_t *bd, struct channel_t *ch, - struct un_t *un, u32 mask, - unsigned long *irq_flags1, - unsigned long *irq_flags2) -{ - if (!(un->un_flags & mask)) - return; - - un->un_flags &= ~mask; - - if (!(un->un_flags & UN_ISOPEN)) - return; - - if ((un->un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - un->un_tty->ldisc->ops->write_wakeup) { - spin_unlock_irqrestore(&ch->ch_lock, *irq_flags2); - spin_unlock_irqrestore(&bd->bd_lock, *irq_flags1); - - (un->un_tty->ldisc->ops->write_wakeup)(un->un_tty); - - spin_lock_irqsave(&bd->bd_lock, *irq_flags1); - spin_lock_irqsave(&ch->ch_lock, *irq_flags2); - } - wake_up_interruptible(&un->un_tty->write_wait); - wake_up_interruptible(&un->un_flags_wait); -} - -/************************************************************************ - * Determines when CARRIER changes state and takes appropriate - * action. - ************************************************************************/ -static void dgap_carrier(struct channel_t *ch) -{ - struct board_t *bd; - - int virt_carrier = 0; - int phys_carrier = 0; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - /* Make sure altpin is always set correctly */ - if (ch->ch_digi.digi_flags & DIGI_ALTPIN) { - ch->ch_dsr = DM_CD; - ch->ch_cd = DM_DSR; - } else { - ch->ch_dsr = DM_DSR; - ch->ch_cd = DM_CD; - } - - if (ch->ch_mistat & D_CD(ch)) - phys_carrier = 1; - - if (ch->ch_digi.digi_flags & DIGI_FORCEDCD) - virt_carrier = 1; - - if (ch->ch_c_cflag & CLOCAL) - virt_carrier = 1; - - /* - * Test for a VIRTUAL carrier transition to HIGH. - */ - if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) { - /* - * When carrier rises, wake any threads waiting - * for carrier in the open routine. - */ - - if (waitqueue_active(&(ch->ch_flags_wait))) - wake_up_interruptible(&ch->ch_flags_wait); - } - - /* - * Test for a PHYSICAL carrier transition to HIGH. - */ - if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) { - /* - * When carrier rises, wake any threads waiting - * for carrier in the open routine. - */ - - if (waitqueue_active(&(ch->ch_flags_wait))) - wake_up_interruptible(&ch->ch_flags_wait); - } - - /* - * Test for a PHYSICAL transition to low, so long as we aren't - * currently ignoring physical transitions (which is what "virtual - * carrier" indicates). - * - * The transition of the virtual carrier to low really doesn't - * matter... it really only means "ignore carrier state", not - * "make pretend that carrier is there". - */ - if ((virt_carrier == 0) && - ((ch->ch_flags & CH_CD) != 0) && - (phys_carrier == 0)) { - /* - * When carrier drops: - * - * Drop carrier on all open units. - * - * Flush queues, waking up any task waiting in the - * line discipline. - * - * Send a hangup to the control terminal. - * - * Enable all select calls. - */ - if (waitqueue_active(&(ch->ch_flags_wait))) - wake_up_interruptible(&ch->ch_flags_wait); - - if (ch->ch_tun.un_open_count > 0) - tty_hangup(ch->ch_tun.un_tty); - - if (ch->ch_pun.un_open_count > 0) - tty_hangup(ch->ch_pun.un_tty); - } - - /* - * Make sure that our cached values reflect the current reality. - */ - if (virt_carrier == 1) - ch->ch_flags |= CH_FCAR; - else - ch->ch_flags &= ~CH_FCAR; - - if (phys_carrier == 1) - ch->ch_flags |= CH_CD; - else - ch->ch_flags &= ~CH_CD; -} - -/*======================================================================= - * - * dgap_event - FEP to host event processing routine. - * - * bd - Board of current event. - * - *=======================================================================*/ -static int dgap_event(struct board_t *bd) -{ - struct channel_t *ch; - ulong lock_flags; - ulong lock_flags2; - struct bs_t __iomem *bs; - u8 __iomem *event; - u8 __iomem *vaddr; - struct ev_t __iomem *eaddr; - uint head; - uint tail; - int port; - int reason; - int modem; - - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return -EIO; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - - vaddr = bd->re_map_membase; - - if (!vaddr) { - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return -EIO; - } - - eaddr = (struct ev_t __iomem *)(vaddr + EVBUF); - - /* Get our head and tail */ - head = readw(&eaddr->ev_head); - tail = readw(&eaddr->ev_tail); - - /* - * Forget it if pointers out of range. - */ - - if (head >= EVMAX - EVSTART || tail >= EVMAX - EVSTART || - (head | tail) & 03) { - /* Let go of board lock */ - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return -EIO; - } - - /* - * Loop to process all the events in the buffer. - */ - while (tail != head) { - /* - * Get interrupt information. - */ - - event = bd->re_map_membase + tail + EVSTART; - - port = ioread8(event); - reason = ioread8(event + 1); - modem = ioread8(event + 2); - ioread8(event + 3); - - /* - * Make sure the interrupt is valid. - */ - if (port >= bd->nasync) - goto next; - - if (!(reason & (IFMODEM | IFBREAK | IFTLW | IFTEM | IFDATA))) - goto next; - - ch = bd->channels[port]; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - goto next; - - /* - * If we have made it here, the event was valid. - * Lock down the channel. - */ - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - bs = ch->ch_bs; - - if (!bs) { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - goto next; - } - - /* - * Process received data. - */ - if (reason & IFDATA) { - /* - * ALL LOCKS *MUST* BE DROPPED BEFORE CALLING INPUT! - * input could send some data to ld, which in turn - * could do a callback to one of our other functions. - */ - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - dgap_input(ch); - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - if (ch->ch_flags & CH_RACTIVE) - ch->ch_flags |= CH_RENABLE; - else - writeb(1, &bs->idata); - - if (ch->ch_flags & CH_RWAIT) { - ch->ch_flags &= ~CH_RWAIT; - - wake_up_interruptible - (&ch->ch_tun.un_flags_wait); - } - } - - /* - * Process Modem change signals. - */ - if (reason & IFMODEM) { - ch->ch_mistat = modem; - dgap_carrier(ch); - } - - /* - * Process break. - */ - if (reason & IFBREAK) { - if (ch->ch_tun.un_tty) { - /* A break has been indicated */ - ch->ch_err_break++; - tty_buffer_request_room - (ch->ch_tun.un_tty->port, 1); - tty_insert_flip_char(ch->ch_tun.un_tty->port, - 0, TTY_BREAK); - tty_flip_buffer_push(ch->ch_tun.un_tty->port); - } - } - - /* - * Process Transmit low. - */ - if (reason & IFTLW) { - dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_LOW, - &lock_flags, &lock_flags2); - dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_LOW, - &lock_flags, &lock_flags2); - if (ch->ch_flags & CH_WLOW) { - ch->ch_flags &= ~CH_WLOW; - wake_up_interruptible(&ch->ch_flags_wait); - } - } - - /* - * Process Transmit empty. - */ - if (reason & IFTEM) { - dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_EMPTY, - &lock_flags, &lock_flags2); - dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_EMPTY, - &lock_flags, &lock_flags2); - if (ch->ch_flags & CH_WEMPTY) { - ch->ch_flags &= ~CH_WEMPTY; - wake_up_interruptible(&ch->ch_flags_wait); - } - } - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - -next: - tail = (tail + 4) & (EVMAX - EVSTART - 4); - } - - writew(tail, &eaddr->ev_tail); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; -} - -/* - * Our board poller function. - */ -static void dgap_poll_tasklet(unsigned long data) -{ - struct board_t *bd = (struct board_t *)data; - ulong lock_flags; - char __iomem *vaddr; - u16 head, tail; - - if (!bd || (bd->magic != DGAP_BOARD_MAGIC)) - return; - - if (bd->inhibit_poller) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - - vaddr = bd->re_map_membase; - - /* - * If board is ready, parse deeper to see if there is anything to do. - */ - if (bd->state == BOARD_READY) { - struct ev_t __iomem *eaddr; - - if (!bd->re_map_membase) { - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return; - } - if (!bd->re_map_port) { - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return; - } - - if (!bd->nasync) - goto out; - - eaddr = (struct ev_t __iomem *)(vaddr + EVBUF); - - /* Get our head and tail */ - head = readw(&eaddr->ev_head); - tail = readw(&eaddr->ev_tail); - - /* - * If there is an event pending. Go service it. - */ - if (head != tail) { - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - dgap_event(bd); - spin_lock_irqsave(&bd->bd_lock, lock_flags); - } - -out: - /* - * If board is doing interrupts, ACK the interrupt. - */ - if (bd->intr_running) - readb(bd->re_map_port + 2); - - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return; - } - - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); -} - -/* - * dgap_found_board() - * - * A board has been found, init it. - */ -static struct board_t *dgap_found_board(struct pci_dev *pdev, int id, - int boardnum) -{ - struct board_t *brd; - unsigned int pci_irq; - int i; - int ret; - - /* get the board structure and prep it */ - brd = kzalloc(sizeof(struct board_t), GFP_KERNEL); - if (!brd) - return ERR_PTR(-ENOMEM); - - /* store the info for the board we've found */ - brd->magic = DGAP_BOARD_MAGIC; - brd->boardnum = boardnum; - brd->vendor = dgap_pci_tbl[id].vendor; - brd->device = dgap_pci_tbl[id].device; - brd->pdev = pdev; - brd->pci_bus = pdev->bus->number; - brd->pci_slot = PCI_SLOT(pdev->devfn); - brd->name = dgap_ids[id].name; - brd->maxports = dgap_ids[id].maxports; - brd->type = dgap_ids[id].config_type; - brd->dpatype = dgap_ids[id].dpatype; - brd->dpastatus = BD_NOFEP; - init_waitqueue_head(&brd->state_wait); - - spin_lock_init(&brd->bd_lock); - - brd->inhibit_poller = FALSE; - brd->wait_for_bios = 0; - brd->wait_for_fep = 0; - - for (i = 0; i < MAXPORTS; i++) - brd->channels[i] = NULL; - - /* store which card & revision we have */ - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &brd->subdevice); - pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev); - - pci_irq = pdev->irq; - brd->irq = pci_irq; - - /* get the PCI Base Address Registers */ - - /* Xr Jupiter and EPC use BAR 2 */ - if (brd->device == PCI_DEV_XRJ_DID || brd->device == PCI_DEV_EPCJ_DID) { - brd->membase = pci_resource_start(pdev, 2); - brd->membase_end = pci_resource_end(pdev, 2); - } - /* Everyone else uses BAR 0 */ - else { - brd->membase = pci_resource_start(pdev, 0); - brd->membase_end = pci_resource_end(pdev, 0); - } - - if (!brd->membase) { - ret = -ENODEV; - goto free_brd; - } - - if (brd->membase & 1) - brd->membase &= ~3; - else - brd->membase &= ~15; - - /* - * On the PCI boards, there is no IO space allocated - * The I/O registers will be in the first 3 bytes of the - * upper 2MB of the 4MB memory space. The board memory - * will be mapped into the low 2MB of the 4MB memory space - */ - brd->port = brd->membase + PCI_IO_OFFSET; - brd->port_end = brd->port + PCI_IO_SIZE_DGAP; - - /* - * Special initialization for non-PLX boards - */ - if (brd->device != PCI_DEV_XRJ_DID && brd->device != PCI_DEV_EPCJ_DID) { - unsigned short cmd; - - pci_write_config_byte(pdev, 0x40, 0); - pci_write_config_byte(pdev, 0x46, 0); - - /* Limit burst length to 2 doubleword transactions */ - pci_write_config_byte(pdev, 0x42, 1); - - /* - * Enable IO and mem if not already done. - * This was needed for support on Itanium. - */ - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY); - pci_write_config_word(pdev, PCI_COMMAND, cmd); - } - - /* init our poll helper tasklet */ - tasklet_init(&brd->helper_tasklet, dgap_poll_tasklet, - (unsigned long)brd); - - ret = dgap_remap(brd); - if (ret) - goto free_brd; - - pr_info("dgap: board %d: %s (rev %d), irq %ld\n", - boardnum, brd->name, brd->rev, brd->irq); - - return brd; - -free_brd: - kfree(brd); - - return ERR_PTR(ret); -} - -/* - * dgap_intr() - * - * Driver interrupt handler. - */ -static irqreturn_t dgap_intr(int irq, void *voidbrd) -{ - struct board_t *brd = voidbrd; - - if (!brd) - return IRQ_NONE; - - /* - * Check to make sure its for us. - */ - if (brd->magic != DGAP_BOARD_MAGIC) - return IRQ_NONE; - - brd->intr_count++; - - /* - * Schedule tasklet to run at a better time. - */ - tasklet_schedule(&brd->helper_tasklet); - return IRQ_HANDLED; -} - -/***************************************************************************** -* -* Function: -* -* dgap_poll_handler -* -* Author: -* -* Scott H Kilau -* -* Parameters: -* -* dummy -- ignored -* -* Return Values: -* -* none -* -* Description: -* -* As each timer expires, it determines (a) whether the "transmit" -* waiter needs to be woken up, and (b) whether the poller needs to -* be rescheduled. -* -******************************************************************************/ - -static void dgap_poll_handler(ulong dummy) -{ - unsigned int i; - struct board_t *brd; - unsigned long lock_flags; - ulong new_time; - - dgap_poll_counter++; - - /* - * Do not start the board state machine until - * driver tells us its up and running, and has - * everything it needs. - */ - if (dgap_driver_state != DRIVER_READY) - goto schedule_poller; - - /* - * If we have just 1 board, or the system is not SMP, - * then use the typical old style poller. - * Otherwise, use our new tasklet based poller, which should - * speed things up for multiple boards. - */ - if ((dgap_numboards == 1) || (num_online_cpus() <= 1)) { - for (i = 0; i < dgap_numboards; i++) { - brd = dgap_board[i]; - - if (brd->state == BOARD_FAILED) - continue; - if (!brd->intr_running) - /* Call the real board poller directly */ - dgap_poll_tasklet((unsigned long)brd); - } - } else { - /* - * Go thru each board, kicking off a - * tasklet for each if needed - */ - for (i = 0; i < dgap_numboards; i++) { - brd = dgap_board[i]; - - /* - * Attempt to grab the board lock. - * - * If we can't get it, no big deal, the next poll - * will get it. Basically, I just really don't want - * to spin in here, because I want to kick off my - * tasklets as fast as I can, and then get out the - * poller. - */ - if (!spin_trylock(&brd->bd_lock)) - continue; - - /* - * If board is in a failed state, don't bother - * scheduling a tasklet - */ - if (brd->state == BOARD_FAILED) { - spin_unlock(&brd->bd_lock); - continue; - } - - /* Schedule a poll helper task */ - if (!brd->intr_running) - tasklet_schedule(&brd->helper_tasklet); - - /* - * Can't do DGAP_UNLOCK here, as we don't have - * lock_flags because we did a trylock above. - */ - spin_unlock(&brd->bd_lock); - } - } - -schedule_poller: - - /* - * Schedule ourself back at the nominal wakeup interval. - */ - spin_lock_irqsave(&dgap_poll_lock, lock_flags); - dgap_poll_time += dgap_jiffies_from_ms(dgap_poll_tick); - - new_time = dgap_poll_time - jiffies; - - if ((ulong)new_time >= 2 * dgap_poll_tick) { - dgap_poll_time = - jiffies + dgap_jiffies_from_ms(dgap_poll_tick); - } - - dgap_poll_timer.function = dgap_poll_handler; - dgap_poll_timer.data = 0; - dgap_poll_timer.expires = dgap_poll_time; - spin_unlock_irqrestore(&dgap_poll_lock, lock_flags); - - if (!dgap_poll_stop) - add_timer(&dgap_poll_timer); -} - -/*======================================================================= - * - * dgap_cmdb - Sends a 2 byte command to the FEP. - * - * ch - Pointer to channel structure. - * cmd - Command to be sent. - * byte1 - Integer containing first byte to be sent. - * byte2 - Integer containing second byte to be sent. - * ncmds - Wait until ncmds or fewer cmds are left - * in the cmd buffer before returning. - * - *=======================================================================*/ -static void dgap_cmdb(struct channel_t *ch, u8 cmd, u8 byte1, - u8 byte2, uint ncmds) -{ - char __iomem *vaddr; - struct __iomem cm_t *cm_addr; - uint count; - uint n; - u16 head; - u16 tail; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - /* - * Check if board is still alive. - */ - if (ch->ch_bd->state == BOARD_FAILED) - return; - - /* - * Make sure the pointers are in range before - * writing to the FEP memory. - */ - vaddr = ch->ch_bd->re_map_membase; - - if (!vaddr) - return; - - cm_addr = (struct cm_t __iomem *)(vaddr + CMDBUF); - head = readw(&cm_addr->cm_head); - - /* - * Forget it if pointers out of range. - */ - if (head >= (CMDMAX - CMDSTART) || (head & 03)) { - ch->ch_bd->state = BOARD_FAILED; - return; - } - - /* - * Put the data in the circular command buffer. - */ - writeb(cmd, (vaddr + head + CMDSTART + 0)); - writeb((u8)ch->ch_portnum, (vaddr + head + CMDSTART + 1)); - writeb(byte1, (vaddr + head + CMDSTART + 2)); - writeb(byte2, (vaddr + head + CMDSTART + 3)); - - head = (head + 4) & (CMDMAX - CMDSTART - 4); - - writew(head, &cm_addr->cm_head); - - /* - * Wait if necessary before updating the head - * pointer to limit the number of outstanding - * commands to the FEP. If the time spent waiting - * is outlandish, declare the FEP dead. - */ - for (count = dgap_count ;;) { - head = readw(&cm_addr->cm_head); - tail = readw(&cm_addr->cm_tail); - - n = (head - tail) & (CMDMAX - CMDSTART - 4); - - if (n <= ncmds * sizeof(struct cm_t)) - break; - - if (--count == 0) { - ch->ch_bd->state = BOARD_FAILED; - return; - } - udelay(10); - } -} - -/*======================================================================= - * - * dgap_cmdw - Sends a 1 word command to the FEP. - * - * ch - Pointer to channel structure. - * cmd - Command to be sent. - * word - Integer containing word to be sent. - * ncmds - Wait until ncmds or fewer cmds are left - * in the cmd buffer before returning. - * - *=======================================================================*/ -static void dgap_cmdw(struct channel_t *ch, u8 cmd, u16 word, uint ncmds) -{ - char __iomem *vaddr; - struct __iomem cm_t *cm_addr; - uint count; - uint n; - u16 head; - u16 tail; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - /* - * Check if board is still alive. - */ - if (ch->ch_bd->state == BOARD_FAILED) - return; - - /* - * Make sure the pointers are in range before - * writing to the FEP memory. - */ - vaddr = ch->ch_bd->re_map_membase; - if (!vaddr) - return; - - cm_addr = (struct cm_t __iomem *)(vaddr + CMDBUF); - head = readw(&cm_addr->cm_head); - - /* - * Forget it if pointers out of range. - */ - if (head >= (CMDMAX - CMDSTART) || (head & 03)) { - ch->ch_bd->state = BOARD_FAILED; - return; - } - - /* - * Put the data in the circular command buffer. - */ - writeb(cmd, (vaddr + head + CMDSTART + 0)); - writeb((u8)ch->ch_portnum, (vaddr + head + CMDSTART + 1)); - writew((u16)word, (vaddr + head + CMDSTART + 2)); - - head = (head + 4) & (CMDMAX - CMDSTART - 4); - - writew(head, &cm_addr->cm_head); - - /* - * Wait if necessary before updating the head - * pointer to limit the number of outstanding - * commands to the FEP. If the time spent waiting - * is outlandish, declare the FEP dead. - */ - for (count = dgap_count ;;) { - head = readw(&cm_addr->cm_head); - tail = readw(&cm_addr->cm_tail); - - n = (head - tail) & (CMDMAX - CMDSTART - 4); - - if (n <= ncmds * sizeof(struct cm_t)) - break; - - if (--count == 0) { - ch->ch_bd->state = BOARD_FAILED; - return; - } - udelay(10); - } -} - -/*======================================================================= - * - * dgap_cmdw_ext - Sends a extended word command to the FEP. - * - * ch - Pointer to channel structure. - * cmd - Command to be sent. - * word - Integer containing word to be sent. - * ncmds - Wait until ncmds or fewer cmds are left - * in the cmd buffer before returning. - * - *=======================================================================*/ -static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds) -{ - char __iomem *vaddr; - struct __iomem cm_t *cm_addr; - uint count; - uint n; - u16 head; - u16 tail; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - /* - * Check if board is still alive. - */ - if (ch->ch_bd->state == BOARD_FAILED) - return; - - /* - * Make sure the pointers are in range before - * writing to the FEP memory. - */ - vaddr = ch->ch_bd->re_map_membase; - if (!vaddr) - return; - - cm_addr = (struct cm_t __iomem *)(vaddr + CMDBUF); - head = readw(&cm_addr->cm_head); - - /* - * Forget it if pointers out of range. - */ - if (head >= (CMDMAX - CMDSTART) || (head & 03)) { - ch->ch_bd->state = BOARD_FAILED; - return; - } - - /* - * Put the data in the circular command buffer. - */ - - /* Write an FF to tell the FEP that we want an extended command */ - writeb((u8)0xff, (vaddr + head + CMDSTART + 0)); - - writeb((u8)ch->ch_portnum, (vaddr + head + CMDSTART + 1)); - writew((u16)cmd, (vaddr + head + CMDSTART + 2)); - - /* - * If the second part of the command won't fit, - * put it at the beginning of the circular buffer. - */ - if (((head + 4) >= ((CMDMAX - CMDSTART)) || (head & 03))) - writew((u16)word, (vaddr + CMDSTART)); - else - writew((u16)word, (vaddr + head + CMDSTART + 4)); - - head = (head + 8) & (CMDMAX - CMDSTART - 4); - - writew(head, &cm_addr->cm_head); - - /* - * Wait if necessary before updating the head - * pointer to limit the number of outstanding - * commands to the FEP. If the time spent waiting - * is outlandish, declare the FEP dead. - */ - for (count = dgap_count ;;) { - head = readw(&cm_addr->cm_head); - tail = readw(&cm_addr->cm_tail); - - n = (head - tail) & (CMDMAX - CMDSTART - 4); - - if (n <= ncmds * sizeof(struct cm_t)) - break; - - if (--count == 0) { - ch->ch_bd->state = BOARD_FAILED; - return; - } - udelay(10); - } -} - -/*======================================================================= - * - * dgap_wmove - Write data to FEP buffer. - * - * ch - Pointer to channel structure. - * buf - Pointer to characters to be moved. - * cnt - Number of characters to move. - * - *=======================================================================*/ -static void dgap_wmove(struct channel_t *ch, char *buf, uint cnt) -{ - int n; - char __iomem *taddr; - struct bs_t __iomem *bs; - u16 head; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - /* - * Check parameters. - */ - bs = ch->ch_bs; - head = readw(&bs->tx_head); - - /* - * If pointers are out of range, just return. - */ - if ((cnt > ch->ch_tsize) || - (unsigned)(head - ch->ch_tstart) >= ch->ch_tsize) - return; - - /* - * If the write wraps over the top of the circular buffer, - * move the portion up to the wrap point, and reset the - * pointers to the bottom. - */ - n = ch->ch_tstart + ch->ch_tsize - head; - - if (cnt >= n) { - cnt -= n; - taddr = ch->ch_taddr + head; - memcpy_toio(taddr, buf, n); - head = ch->ch_tstart; - buf += n; - } - - /* - * Move rest of data. - */ - taddr = ch->ch_taddr + head; - n = cnt; - memcpy_toio(taddr, buf, n); - head += cnt; - - writew(head, &bs->tx_head); -} - -/* - * Calls the firmware to reset this channel. - */ -static void dgap_firmware_reset_port(struct channel_t *ch) -{ - dgap_cmdb(ch, CHRESET, 0, 0, 0); - - /* - * Now that the channel is reset, we need to make sure - * all the current settings get reapplied to the port - * in the firmware. - * - * So we will set the driver's cache of firmware - * settings all to 0, and then call param. - */ - ch->ch_fepiflag = 0; - ch->ch_fepcflag = 0; - ch->ch_fepoflag = 0; - ch->ch_fepstartc = 0; - ch->ch_fepstopc = 0; - ch->ch_fepastartc = 0; - ch->ch_fepastopc = 0; - ch->ch_mostat = 0; - ch->ch_hflow = 0; -} - -/*======================================================================= - * - * dgap_param - Set Digi parameters. - * - * struct tty_struct * - TTY for port. - * - *=======================================================================*/ -static int dgap_param(struct channel_t *ch, struct board_t *bd, u32 un_type) -{ - u16 head; - u16 cflag; - u16 iflag; - u8 mval; - u8 hflow; - - /* - * If baud rate is zero, flush queues, and set mval to drop DTR. - */ - if ((ch->ch_c_cflag & (CBAUD)) == 0) { - /* flush rx */ - head = readw(&ch->ch_bs->rx_head); - writew(head, &ch->ch_bs->rx_tail); - - /* flush tx */ - head = readw(&ch->ch_bs->tx_head); - writew(head, &ch->ch_bs->tx_tail); - - ch->ch_flags |= (CH_BAUD0); - - /* Drop RTS and DTR */ - ch->ch_mval &= ~(D_RTS(ch) | D_DTR(ch)); - mval = D_DTR(ch) | D_RTS(ch); - ch->ch_baud_info = 0; - - } else if (ch->ch_custom_speed && (bd->bd_flags & BD_FEP5PLUS)) { - /* - * Tell the fep to do the command - */ - - dgap_cmdw_ext(ch, 0xff01, ch->ch_custom_speed, 0); - - /* - * Now go get from fep mem, what the fep - * believes the custom baud rate is. - */ - ch->ch_custom_speed = dgap_get_custom_baud(ch); - ch->ch_baud_info = ch->ch_custom_speed; - - /* Handle transition from B0 */ - if (ch->ch_flags & CH_BAUD0) { - ch->ch_flags &= ~(CH_BAUD0); - ch->ch_mval |= (D_RTS(ch) | D_DTR(ch)); - } - mval = D_DTR(ch) | D_RTS(ch); - - } else { - /* - * Set baud rate, character size, and parity. - */ - - - int iindex = 0; - int jindex = 0; - int baud = 0; - - ulong bauds[4][16] = { - { /* slowbaud */ - 0, 50, 75, 110, - 134, 150, 200, 300, - 600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 }, - { /* slowbaud & CBAUDEX */ - 0, 57600, 115200, 230400, - 460800, 150, 200, 921600, - 600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 }, - { /* fastbaud */ - 0, 57600, 76800, 115200, - 14400, 57600, 230400, 76800, - 115200, 230400, 28800, 460800, - 921600, 9600, 19200, 38400 }, - { /* fastbaud & CBAUDEX */ - 0, 57600, 115200, 230400, - 460800, 150, 200, 921600, - 600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 } - }; - - /* - * Only use the TXPrint baud rate if the - * terminal unit is NOT open - */ - if (!(ch->ch_tun.un_flags & UN_ISOPEN) && - un_type == DGAP_PRINT) - baud = C_BAUD(ch->ch_pun.un_tty) & 0xff; - else - baud = C_BAUD(ch->ch_tun.un_tty) & 0xff; - - if (ch->ch_c_cflag & CBAUDEX) - iindex = 1; - - if (ch->ch_digi.digi_flags & DIGI_FAST) - iindex += 2; - - jindex = baud; - - if ((iindex >= 0) && (iindex < 4) && - (jindex >= 0) && (jindex < 16)) - baud = bauds[iindex][jindex]; - else - baud = 0; - - if (baud == 0) - baud = 9600; - - ch->ch_baud_info = baud; - - /* - * CBAUD has bit position 0x1000 set these days to - * indicate Linux baud rate remap. - * We use a different bit assignment for high speed. - * Clear this bit out while grabbing the parts of - * "cflag" we want. - */ - cflag = ch->ch_c_cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | - CSTOPB | CSIZE); - - /* - * HUPCL bit is used by FEP to indicate fast baud - * table is to be used. - */ - if ((ch->ch_digi.digi_flags & DIGI_FAST) || - (ch->ch_c_cflag & CBAUDEX)) - cflag |= HUPCL; - - if ((ch->ch_c_cflag & CBAUDEX) && - !(ch->ch_digi.digi_flags & DIGI_FAST)) { - /* - * The below code is trying to guarantee that only - * baud rates 115200, 230400, 460800, 921600 are - * remapped. We use exclusive or because the various - * baud rates share common bit positions and therefore - * can't be tested for easily. - */ - tcflag_t tcflag = (ch->ch_c_cflag & CBAUD) | CBAUDEX; - int baudpart = 0; - - /* - * Map high speed requests to index - * into FEP's baud table - */ - switch (tcflag) { - case B57600: - baudpart = 1; - break; -#ifdef B76800 - case B76800: - baudpart = 2; - break; -#endif - case B115200: - baudpart = 3; - break; - case B230400: - baudpart = 9; - break; - case B460800: - baudpart = 11; - break; -#ifdef B921600 - case B921600: - baudpart = 12; - break; -#endif - default: - baudpart = 0; - } - - if (baudpart) - cflag = (cflag & ~(CBAUD | CBAUDEX)) | baudpart; - } - - cflag &= 0xffff; - - if (cflag != ch->ch_fepcflag) { - ch->ch_fepcflag = (u16)(cflag & 0xffff); - - /* - * Okay to have channel and board - * locks held calling this - */ - dgap_cmdw(ch, SCFLAG, (u16)cflag, 0); - } - - /* Handle transition from B0 */ - if (ch->ch_flags & CH_BAUD0) { - ch->ch_flags &= ~(CH_BAUD0); - ch->ch_mval |= (D_RTS(ch) | D_DTR(ch)); - } - mval = D_DTR(ch) | D_RTS(ch); - } - - /* - * Get input flags. - */ - iflag = ch->ch_c_iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | - INPCK | ISTRIP | IXON | IXANY | IXOFF); - - if ((ch->ch_startc == _POSIX_VDISABLE) || - (ch->ch_stopc == _POSIX_VDISABLE)) { - iflag &= ~(IXON | IXOFF); - ch->ch_c_iflag &= ~(IXON | IXOFF); - } - - /* - * Only the IBM Xr card can switch between - * 232 and 422 modes on the fly - */ - if (bd->device == PCI_DEV_XR_IBM_DID) { - if (ch->ch_digi.digi_flags & DIGI_422) - dgap_cmdb(ch, SCOMMODE, MODE_422, 0, 0); - else - dgap_cmdb(ch, SCOMMODE, MODE_232, 0, 0); - } - - if (ch->ch_digi.digi_flags & DIGI_ALTPIN) - iflag |= IALTPIN; - - if (iflag != ch->ch_fepiflag) { - ch->ch_fepiflag = iflag; - - /* Okay to have channel and board locks held calling this */ - dgap_cmdw(ch, SIFLAG, (u16)ch->ch_fepiflag, 0); - } - - /* - * Select hardware handshaking. - */ - hflow = 0; - - if (ch->ch_c_cflag & CRTSCTS) - hflow |= (D_RTS(ch) | D_CTS(ch)); - if (ch->ch_digi.digi_flags & RTSPACE) - hflow |= D_RTS(ch); - if (ch->ch_digi.digi_flags & DTRPACE) - hflow |= D_DTR(ch); - if (ch->ch_digi.digi_flags & CTSPACE) - hflow |= D_CTS(ch); - if (ch->ch_digi.digi_flags & DSRPACE) - hflow |= D_DSR(ch); - if (ch->ch_digi.digi_flags & DCDPACE) - hflow |= D_CD(ch); - - if (hflow != ch->ch_hflow) { - ch->ch_hflow = hflow; - - /* Okay to have channel and board locks held calling this */ - dgap_cmdb(ch, SHFLOW, (u8)hflow, 0xff, 0); - } - - /* - * Set RTS and/or DTR Toggle if needed, - * but only if product is FEP5+ based. - */ - if (bd->bd_flags & BD_FEP5PLUS) { - u16 hflow2 = 0; - - if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) - hflow2 |= (D_RTS(ch)); - if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) - hflow2 |= (D_DTR(ch)); - - dgap_cmdw_ext(ch, 0xff03, hflow2, 0); - } - - /* - * Set modem control lines. - */ - - mval ^= ch->ch_mforce & (mval ^ ch->ch_mval); - - if (ch->ch_mostat ^ mval) { - ch->ch_mostat = mval; - - /* Okay to have channel and board locks held calling this */ - dgap_cmdb(ch, SMODEM, (u8)mval, D_RTS(ch) | D_DTR(ch), 0); - } - - /* - * Read modem signals, and then call carrier function. - */ - ch->ch_mistat = readb(&ch->ch_bs->m_stat); - dgap_carrier(ch); - - /* - * Set the start and stop characters. - */ - if (ch->ch_startc != ch->ch_fepstartc || - ch->ch_stopc != ch->ch_fepstopc) { - ch->ch_fepstartc = ch->ch_startc; - ch->ch_fepstopc = ch->ch_stopc; - - /* Okay to have channel and board locks held calling this */ - dgap_cmdb(ch, SFLOWC, ch->ch_fepstartc, ch->ch_fepstopc, 0); - } - - /* - * Set the Auxiliary start and stop characters. - */ - if (ch->ch_astartc != ch->ch_fepastartc || - ch->ch_astopc != ch->ch_fepastopc) { - ch->ch_fepastartc = ch->ch_astartc; - ch->ch_fepastopc = ch->ch_astopc; - - /* Okay to have channel and board locks held calling this */ - dgap_cmdb(ch, SAFLOWC, ch->ch_fepastartc, ch->ch_fepastopc, 0); - } - - return 0; -} - -/* - * dgap_block_til_ready() - * - * Wait for DCD, if needed. - */ -static int dgap_block_til_ready(struct tty_struct *tty, struct file *file, - struct channel_t *ch) -{ - int retval = 0; - struct un_t *un; - ulong lock_flags; - uint old_flags; - int sleep_on_un_flags; - - if (!tty || tty->magic != TTY_MAGIC || !file || !ch || - ch->magic != DGAP_CHANNEL_MAGIC) - return -EIO; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EIO; - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - - ch->ch_wopen++; - - /* Loop forever */ - while (1) { - sleep_on_un_flags = 0; - - /* - * If board has failed somehow during our sleep, - * bail with error. - */ - if (ch->ch_bd->state == BOARD_FAILED) { - retval = -EIO; - break; - } - - /* If tty was hung up, break out of loop and set error. */ - if (tty_hung_up_p(file)) { - retval = -EAGAIN; - break; - } - - /* - * If either unit is in the middle of the fragile part of close, - * we just cannot touch the channel safely. - * Go back to sleep, knowing that when the channel can be - * touched safely, the close routine will signal the - * ch_wait_flags to wake us back up. - */ - if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & - UN_CLOSING)) { - /* - * Our conditions to leave cleanly and happily: - * 1) NONBLOCKING on the tty is set. - * 2) CLOCAL is set. - * 3) DCD (fake or real) is active. - */ - - if (file->f_flags & O_NONBLOCK) - break; - - if (tty->flags & (1 << TTY_IO_ERROR)) - break; - - if (ch->ch_flags & CH_CD) - break; - - if (ch->ch_flags & CH_FCAR) - break; - } else { - sleep_on_un_flags = 1; - } - - /* - * If there is a signal pending, the user probably - * interrupted (ctrl-c) us. - * Leave loop with error set. - */ - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - - /* - * Store the flags before we let go of channel lock - */ - if (sleep_on_un_flags) - old_flags = ch->ch_tun.un_flags | ch->ch_pun.un_flags; - else - old_flags = ch->ch_flags; - - /* - * Let go of channel lock before calling schedule. - * Our poller will get any FEP events and wake us up when DCD - * eventually goes active. - */ - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - /* - * Wait for something in the flags to change - * from the current value. - */ - if (sleep_on_un_flags) { - retval = wait_event_interruptible(un->un_flags_wait, - (old_flags != (ch->ch_tun.un_flags | - ch->ch_pun.un_flags))); - } else { - retval = wait_event_interruptible(ch->ch_flags_wait, - (old_flags != ch->ch_flags)); - } - - /* - * We got woken up for some reason. - * Before looping around, grab our channel lock. - */ - spin_lock_irqsave(&ch->ch_lock, lock_flags); - } - - ch->ch_wopen--; - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - return retval; -} - -/* - * dgap_tty_flush_buffer() - * - * Flush Tx buffer (make in == out) - */ -static void dgap_tty_flush_buffer(struct tty_struct *tty) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - u16 head; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - ch->ch_flags &= ~CH_STOP; - head = readw(&ch->ch_bs->tx_head); - dgap_cmdw(ch, FLUSHTX, (u16)head, 0); - dgap_cmdw(ch, RESUMETX, 0, 0); - if (ch->ch_tun.un_flags & (UN_LOW | UN_EMPTY)) { - ch->ch_tun.un_flags &= ~(UN_LOW | UN_EMPTY); - wake_up_interruptible(&ch->ch_tun.un_flags_wait); - } - if (ch->ch_pun.un_flags & (UN_LOW | UN_EMPTY)) { - ch->ch_pun.un_flags &= ~(UN_LOW | UN_EMPTY); - wake_up_interruptible(&ch->ch_pun.un_flags_wait); - } - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - if (waitqueue_active(&tty->write_wait)) - wake_up_interruptible(&tty->write_wait); - tty_wakeup(tty); -} - -/* - * dgap_tty_hangup() - * - * Hangup the port. Like a close, but don't wait for output to drain. - */ -static void dgap_tty_hangup(struct tty_struct *tty) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - /* flush the transmit queues */ - dgap_tty_flush_buffer(tty); -} - -/* - * dgap_tty_chars_in_buffer() - * - * Return number of characters that have not been transmitted yet. - * - * This routine is used by the line discipline to determine if there - * is data waiting to be transmitted/drained/flushed or not. - */ -static int dgap_tty_chars_in_buffer(struct tty_struct *tty) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - struct bs_t __iomem *bs; - u8 tbusy; - uint chars; - u16 thead, ttail, tmask, chead, ctail; - ulong lock_flags = 0; - ulong lock_flags2 = 0; - - if (!tty) - return 0; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - - bs = ch->ch_bs; - if (!bs) - return 0; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - tmask = (ch->ch_tsize - 1); - - /* Get Transmit queue pointers */ - thead = readw(&bs->tx_head) & tmask; - ttail = readw(&bs->tx_tail) & tmask; - - /* Get tbusy flag */ - tbusy = readb(&bs->tbusy); - - /* Get Command queue pointers */ - chead = readw(&ch->ch_cm->cm_head); - ctail = readw(&ch->ch_cm->cm_tail); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - /* - * The only way we know for sure if there is no pending - * data left to be transferred, is if: - * 1) Transmit head and tail are equal (empty). - * 2) Command queue head and tail are equal (empty). - * 3) The "TBUSY" flag is 0. (Transmitter not busy). - */ - - if ((ttail == thead) && (tbusy == 0) && (chead == ctail)) { - chars = 0; - } else { - if (thead >= ttail) - chars = thead - ttail; - else - chars = thead - ttail + ch->ch_tsize; - /* - * Fudge factor here. - * If chars is zero, we know that the command queue had - * something in it or tbusy was set. Because we cannot - * be sure if there is still some data to be transmitted, - * lets lie, and tell ld we have 1 byte left. - */ - if (chars == 0) { - /* - * If TBUSY is still set, and our tx buffers are empty, - * force the firmware to send me another wakeup after - * TBUSY has been cleared. - */ - if (tbusy != 0) { - spin_lock_irqsave(&ch->ch_lock, lock_flags); - un->un_flags |= UN_EMPTY; - writeb(1, &bs->iempty); - spin_unlock_irqrestore(&ch->ch_lock, - lock_flags); - } - chars = 1; - } - } - - return chars; -} - -static int dgap_wait_for_drain(struct tty_struct *tty) -{ - struct channel_t *ch; - struct un_t *un; - struct bs_t __iomem *bs; - int ret = 0; - uint count = 1; - ulong lock_flags = 0; - - if (!tty || tty->magic != TTY_MAGIC) - return -EIO; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EIO; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EIO; - - bs = ch->ch_bs; - if (!bs) - return -EIO; - - /* Loop until data is drained */ - while (count != 0) { - count = dgap_tty_chars_in_buffer(tty); - - if (count == 0) - break; - - /* Set flag waiting for drain */ - spin_lock_irqsave(&ch->ch_lock, lock_flags); - un->un_flags |= UN_EMPTY; - writeb(1, &bs->iempty); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - /* Go to sleep till we get woken up */ - ret = wait_event_interruptible(un->un_flags_wait, - ((un->un_flags & UN_EMPTY) == 0)); - /* If ret is non-zero, user ctrl-c'ed us */ - if (ret) - break; - } - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - un->un_flags &= ~(UN_EMPTY); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - return ret; -} - -/* - * dgap_maxcps_room - * - * Reduces bytes_available to the max number of characters - * that can be sent currently given the maxcps value, and - * returns the new bytes_available. This only affects printer - * output. - */ -static int dgap_maxcps_room(struct channel_t *ch, struct un_t *un, - int bytes_available) -{ - /* - * If its not the Transparent print device, return - * the full data amount. - */ - if (un->un_type != DGAP_PRINT) - return bytes_available; - - if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0) { - int cps_limit = 0; - unsigned long current_time = jiffies; - unsigned long buffer_time = current_time + - (HZ * ch->ch_digi.digi_bufsize) / - ch->ch_digi.digi_maxcps; - - if (ch->ch_cpstime < current_time) { - /* buffer is empty */ - ch->ch_cpstime = current_time; /* reset ch_cpstime */ - cps_limit = ch->ch_digi.digi_bufsize; - } else if (ch->ch_cpstime < buffer_time) { - /* still room in the buffer */ - cps_limit = ((buffer_time - ch->ch_cpstime) * - ch->ch_digi.digi_maxcps) / HZ; - } else { - /* no room in the buffer */ - cps_limit = 0; - } - - bytes_available = min(cps_limit, bytes_available); - } - - return bytes_available; -} - -static inline void dgap_set_firmware_event(struct un_t *un, unsigned int event) -{ - struct channel_t *ch; - struct bs_t __iomem *bs; - - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - bs = ch->ch_bs; - if (!bs) - return; - - if ((event & UN_LOW) != 0) { - if ((un->un_flags & UN_LOW) == 0) { - un->un_flags |= UN_LOW; - writeb(1, &bs->ilow); - } - } - if ((event & UN_LOW) != 0) { - if ((un->un_flags & UN_EMPTY) == 0) { - un->un_flags |= UN_EMPTY; - writeb(1, &bs->iempty); - } - } -} - -/* - * dgap_tty_write_room() - * - * Return space available in Tx buffer - */ -static int dgap_tty_write_room(struct tty_struct *tty) -{ - struct channel_t *ch; - struct un_t *un; - struct bs_t __iomem *bs; - u16 head, tail, tmask; - int ret; - ulong lock_flags = 0; - - if (!tty) - return 0; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - - bs = ch->ch_bs; - if (!bs) - return 0; - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - - tmask = ch->ch_tsize - 1; - head = readw(&bs->tx_head) & tmask; - tail = readw(&bs->tx_tail) & tmask; - - ret = tail - head - 1; - if (ret < 0) - ret += ch->ch_tsize; - - /* Limit printer to maxcps */ - ret = dgap_maxcps_room(ch, un, ret); - - /* - * If we are printer device, leave space for - * possibly both the on and off strings. - */ - if (un->un_type == DGAP_PRINT) { - if (!(ch->ch_flags & CH_PRON)) - ret -= ch->ch_digi.digi_onlen; - ret -= ch->ch_digi.digi_offlen; - } else { - if (ch->ch_flags & CH_PRON) - ret -= ch->ch_digi.digi_offlen; - } - - if (ret < 0) - ret = 0; - - /* - * Schedule FEP to wake us up if needed. - * - * TODO: This might be overkill... - * Do we really need to schedule callbacks from the FEP - * in every case? Can we get smarter based on ret? - */ - dgap_set_firmware_event(un, UN_LOW | UN_EMPTY); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - return ret; -} - -/* - * dgap_tty_write() - * - * Take data from the user or kernel and send it out to the FEP. - * In here exists all the Transparent Print magic as well. - */ -static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf, - int count) -{ - struct channel_t *ch; - struct un_t *un; - struct bs_t __iomem *bs; - char __iomem *vaddr; - u16 head, tail, tmask, remain; - int bufcount, n; - ulong lock_flags; - - if (!tty) - return 0; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - - bs = ch->ch_bs; - if (!bs) - return 0; - - if (!count) - return 0; - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - - /* Get our space available for the channel from the board */ - tmask = ch->ch_tsize - 1; - head = readw(&(bs->tx_head)) & tmask; - tail = readw(&(bs->tx_tail)) & tmask; - - bufcount = tail - head - 1; - if (bufcount < 0) - bufcount += ch->ch_tsize; - - /* - * Limit printer output to maxcps overall, with bursts allowed - * up to bufsize characters. - */ - bufcount = dgap_maxcps_room(ch, un, bufcount); - - /* - * Take minimum of what the user wants to send, and the - * space available in the FEP buffer. - */ - count = min(count, bufcount); - - /* - * Bail if no space left. - */ - if (count <= 0) { - dgap_set_firmware_event(un, UN_LOW | UN_EMPTY); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - return 0; - } - - /* - * Output the printer ON string, if we are in terminal mode, but - * need to be in printer mode. - */ - if ((un->un_type == DGAP_PRINT) && !(ch->ch_flags & CH_PRON)) { - dgap_wmove(ch, ch->ch_digi.digi_onstr, - (int)ch->ch_digi.digi_onlen); - head = readw(&bs->tx_head) & tmask; - ch->ch_flags |= CH_PRON; - } - - /* - * On the other hand, output the printer OFF string, if we are - * currently in printer mode, but need to output to the terminal. - */ - if ((un->un_type != DGAP_PRINT) && (ch->ch_flags & CH_PRON)) { - dgap_wmove(ch, ch->ch_digi.digi_offstr, - (int)ch->ch_digi.digi_offlen); - head = readw(&bs->tx_head) & tmask; - ch->ch_flags &= ~CH_PRON; - } - - n = count; - - /* - * If the write wraps over the top of the circular buffer, - * move the portion up to the wrap point, and reset the - * pointers to the bottom. - */ - remain = ch->ch_tstart + ch->ch_tsize - head; - - if (n >= remain) { - n -= remain; - vaddr = ch->ch_taddr + head; - - memcpy_toio(vaddr, (u8 *)buf, remain); - - head = ch->ch_tstart; - buf += remain; - } - - if (n > 0) { - /* - * Move rest of data. - */ - vaddr = ch->ch_taddr + head; - remain = n; - - memcpy_toio(vaddr, (u8 *)buf, remain); - head += remain; - } - - if (count) { - ch->ch_txcount += count; - head &= tmask; - writew(head, &bs->tx_head); - } - - dgap_set_firmware_event(un, UN_LOW | UN_EMPTY); - - /* - * If this is the print device, and the - * printer is still on, we need to turn it - * off before going idle. If the buffer is - * non-empty, wait until it goes empty. - * Otherwise turn it off right now. - */ - if ((un->un_type == DGAP_PRINT) && (ch->ch_flags & CH_PRON)) { - tail = readw(&bs->tx_tail) & tmask; - - if (tail != head) { - un->un_flags |= UN_EMPTY; - writeb(1, &bs->iempty); - } else { - dgap_wmove(ch, ch->ch_digi.digi_offstr, - (int)ch->ch_digi.digi_offlen); - head = readw(&bs->tx_head) & tmask; - ch->ch_flags &= ~CH_PRON; - } - } - - /* Update printer buffer empty time. */ - if ((un->un_type == DGAP_PRINT) && (ch->ch_digi.digi_maxcps > 0) - && (ch->ch_digi.digi_bufsize > 0)) { - ch->ch_cpstime += (HZ * count) / ch->ch_digi.digi_maxcps; - } - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - return count; -} - -/* - * dgap_tty_put_char() - * - * Put a character into ch->ch_buf - * - * - used by the line discipline for OPOST processing - */ -static int dgap_tty_put_char(struct tty_struct *tty, unsigned char c) -{ - /* - * Simply call tty_write. - */ - dgap_tty_write(tty, &c, 1); - return 1; -} - -/* - * Return modem signals to ld. - */ -static int dgap_tty_tiocmget(struct tty_struct *tty) -{ - struct channel_t *ch; - struct un_t *un; - int result; - u8 mstat; - ulong lock_flags; - - if (!tty || tty->magic != TTY_MAGIC) - return -EIO; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EIO; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EIO; - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - - mstat = readb(&ch->ch_bs->m_stat); - /* Append any outbound signals that might be pending... */ - mstat |= ch->ch_mostat; - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - result = 0; - - if (mstat & D_DTR(ch)) - result |= TIOCM_DTR; - if (mstat & D_RTS(ch)) - result |= TIOCM_RTS; - if (mstat & D_CTS(ch)) - result |= TIOCM_CTS; - if (mstat & D_DSR(ch)) - result |= TIOCM_DSR; - if (mstat & D_RI(ch)) - result |= TIOCM_RI; - if (mstat & D_CD(ch)) - result |= TIOCM_CD; - - return result; -} - -/* - * dgap_tty_tiocmset() - * - * Set modem signals, called by ld. - */ -static int dgap_tty_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return -EIO; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EIO; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EIO; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return -EIO; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - if (set & TIOCM_RTS) { - ch->ch_mforce |= D_RTS(ch); - ch->ch_mval |= D_RTS(ch); - } - - if (set & TIOCM_DTR) { - ch->ch_mforce |= D_DTR(ch); - ch->ch_mval |= D_DTR(ch); - } - - if (clear & TIOCM_RTS) { - ch->ch_mforce |= D_RTS(ch); - ch->ch_mval &= ~(D_RTS(ch)); - } - - if (clear & TIOCM_DTR) { - ch->ch_mforce |= D_DTR(ch); - ch->ch_mval &= ~(D_DTR(ch)); - } - - dgap_param(ch, bd, un->un_type); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; -} - -/* - * dgap_tty_send_break() - * - * Send a Break, called by ld. - */ -static int dgap_tty_send_break(struct tty_struct *tty, int msec) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return -EIO; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EIO; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EIO; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return -EIO; - - switch (msec) { - case -1: - msec = 0xFFFF; - break; - case 0: - msec = 1; - break; - default: - msec /= 10; - break; - } - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); -#if 0 - dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0); -#endif - dgap_cmdw(ch, SBREAK, (u16)msec, 0); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; -} - -/* - * dgap_tty_wait_until_sent() - * - * wait until data has been transmitted, called by ld. - */ -static void dgap_tty_wait_until_sent(struct tty_struct *tty, int timeout) -{ - dgap_wait_for_drain(tty); -} - -/* - * dgap_send_xchar() - * - * send a high priority character, called by ld. - */ -static void dgap_tty_send_xchar(struct tty_struct *tty, char c) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - /* - * This is technically what we should do. - * However, the NIST tests specifically want - * to see each XON or XOFF character that it - * sends, so lets just send each character - * by hand... - */ -#if 0 - if (c == STOP_CHAR(tty)) - dgap_cmdw(ch, RPAUSE, 0, 0); - else if (c == START_CHAR(tty)) - dgap_cmdw(ch, RRESUME, 0, 0); - else - dgap_wmove(ch, &c, 1); -#else - dgap_wmove(ch, &c, 1); -#endif - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); -} - -/* - * Return modem signals to ld. - */ -static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value) -{ - int result; - u8 mstat; - ulong lock_flags; - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - - mstat = readb(&ch->ch_bs->m_stat); - /* Append any outbound signals that might be pending... */ - mstat |= ch->ch_mostat; - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - result = 0; - - if (mstat & D_DTR(ch)) - result |= TIOCM_DTR; - if (mstat & D_RTS(ch)) - result |= TIOCM_RTS; - if (mstat & D_CTS(ch)) - result |= TIOCM_CTS; - if (mstat & D_DSR(ch)) - result |= TIOCM_DSR; - if (mstat & D_RI(ch)) - result |= TIOCM_RI; - if (mstat & D_CD(ch)) - result |= TIOCM_CD; - - return put_user(result, value); -} - -/* - * dgap_set_modem_info() - * - * Set modem signals, called by ld. - */ -static int dgap_set_modem_info(struct channel_t *ch, struct board_t *bd, - struct un_t *un, unsigned int command, - unsigned int __user *value) -{ - int ret; - unsigned int arg; - ulong lock_flags; - ulong lock_flags2; - - ret = get_user(arg, value); - if (ret) - return ret; - - switch (command) { - case TIOCMBIS: - if (arg & TIOCM_RTS) { - ch->ch_mforce |= D_RTS(ch); - ch->ch_mval |= D_RTS(ch); - } - - if (arg & TIOCM_DTR) { - ch->ch_mforce |= D_DTR(ch); - ch->ch_mval |= D_DTR(ch); - } - - break; - - case TIOCMBIC: - if (arg & TIOCM_RTS) { - ch->ch_mforce |= D_RTS(ch); - ch->ch_mval &= ~(D_RTS(ch)); - } - - if (arg & TIOCM_DTR) { - ch->ch_mforce |= D_DTR(ch); - ch->ch_mval &= ~(D_DTR(ch)); - } - - break; - - case TIOCMSET: - ch->ch_mforce = D_DTR(ch) | D_RTS(ch); - - if (arg & TIOCM_RTS) - ch->ch_mval |= D_RTS(ch); - else - ch->ch_mval &= ~(D_RTS(ch)); - - if (arg & TIOCM_DTR) - ch->ch_mval |= (D_DTR(ch)); - else - ch->ch_mval &= ~(D_DTR(ch)); - - break; - - default: - return -EINVAL; - } - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - dgap_param(ch, bd, un->un_type); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; -} - -/* - * dgap_tty_digigeta() - * - * Ioctl to get the information for ditty. - * - * - * - */ -static int dgap_tty_digigeta(struct channel_t *ch, - struct digi_t __user *retinfo) -{ - struct digi_t tmp; - ulong lock_flags; - - if (!retinfo) - return -EFAULT; - - memset(&tmp, 0, sizeof(tmp)); - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - memcpy(&tmp, &ch->ch_digi, sizeof(tmp)); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - - return 0; -} - -/* - * dgap_tty_digiseta() - * - * Ioctl to set the information for ditty. - * - * - * - */ -static int dgap_tty_digiseta(struct channel_t *ch, struct board_t *bd, - struct un_t *un, struct digi_t __user *new_info) -{ - struct digi_t new_digi; - ulong lock_flags = 0; - unsigned long lock_flags2; - - if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t))) - return -EFAULT; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - memcpy(&ch->ch_digi, &new_digi, sizeof(struct digi_t)); - - if (ch->ch_digi.digi_maxcps < 1) - ch->ch_digi.digi_maxcps = 1; - - if (ch->ch_digi.digi_maxcps > 10000) - ch->ch_digi.digi_maxcps = 10000; - - if (ch->ch_digi.digi_bufsize < 10) - ch->ch_digi.digi_bufsize = 10; - - if (ch->ch_digi.digi_maxchar < 1) - ch->ch_digi.digi_maxchar = 1; - - if (ch->ch_digi.digi_maxchar > ch->ch_digi.digi_bufsize) - ch->ch_digi.digi_maxchar = ch->ch_digi.digi_bufsize; - - if (ch->ch_digi.digi_onlen > DIGI_PLEN) - ch->ch_digi.digi_onlen = DIGI_PLEN; - - if (ch->ch_digi.digi_offlen > DIGI_PLEN) - ch->ch_digi.digi_offlen = DIGI_PLEN; - - dgap_param(ch, bd, un->un_type); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; -} - -/* - * dgap_tty_digigetedelay() - * - * Ioctl to get the current edelay setting. - * - * - * - */ -static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo) -{ - struct channel_t *ch; - struct un_t *un; - int tmp; - ulong lock_flags; - - if (!retinfo) - return -EFAULT; - - if (!tty || tty->magic != TTY_MAGIC) - return -EFAULT; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EFAULT; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EFAULT; - - memset(&tmp, 0, sizeof(tmp)); - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - tmp = readw(&ch->ch_bs->edelay); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - - return 0; -} - -/* - * dgap_tty_digisetedelay() - * - * Ioctl to set the EDELAY setting - * - */ -static int dgap_tty_digisetedelay(struct channel_t *ch, struct board_t *bd, - struct un_t *un, int __user *new_info) -{ - int new_digi; - ulong lock_flags; - ulong lock_flags2; - - if (copy_from_user(&new_digi, new_info, sizeof(int))) - return -EFAULT; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - writew((u16)new_digi, &ch->ch_bs->edelay); - - dgap_param(ch, bd, un->un_type); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; -} - -/* - * dgap_tty_digigetcustombaud() - * - * Ioctl to get the current custom baud rate setting. - */ -static int dgap_tty_digigetcustombaud(struct channel_t *ch, struct un_t *un, - int __user *retinfo) -{ - int tmp; - ulong lock_flags; - - if (!retinfo) - return -EFAULT; - - memset(&tmp, 0, sizeof(tmp)); - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - tmp = dgap_get_custom_baud(ch); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - - return 0; -} - -/* - * dgap_tty_digisetcustombaud() - * - * Ioctl to set the custom baud rate setting - */ -static int dgap_tty_digisetcustombaud(struct channel_t *ch, struct board_t *bd, - struct un_t *un, int __user *new_info) -{ - uint new_rate; - ulong lock_flags; - ulong lock_flags2; - - if (copy_from_user(&new_rate, new_info, sizeof(unsigned int))) - return -EFAULT; - - if (bd->bd_flags & BD_FEP5PLUS) { - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - ch->ch_custom_speed = new_rate; - - dgap_param(ch, bd, un->un_type); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - } - - return 0; -} - -/* - * dgap_set_termios() - */ -static void dgap_tty_set_termios(struct tty_struct *tty, - struct ktermios *old_termios) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - unsigned long lock_flags; - unsigned long lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - ch->ch_c_cflag = tty->termios.c_cflag; - ch->ch_c_iflag = tty->termios.c_iflag; - ch->ch_c_oflag = tty->termios.c_oflag; - ch->ch_c_lflag = tty->termios.c_lflag; - ch->ch_startc = tty->termios.c_cc[VSTART]; - ch->ch_stopc = tty->termios.c_cc[VSTOP]; - - dgap_carrier(ch); - dgap_param(ch, bd, un->un_type); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); -} - -static void dgap_tty_throttle(struct tty_struct *tty) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - ch->ch_flags |= (CH_RXBLOCK); -#if 1 - dgap_cmdw(ch, RPAUSE, 0, 0); -#endif - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); -} - -static void dgap_tty_unthrottle(struct tty_struct *tty) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - ch->ch_flags &= ~(CH_RXBLOCK); - -#if 1 - dgap_cmdw(ch, RRESUME, 0, 0); -#endif - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); -} - -static struct board_t *find_board_by_major(unsigned int major) -{ - unsigned int i; - - for (i = 0; i < MAXBOARDS; i++) { - struct board_t *brd = dgap_board[i]; - - if (!brd) - return NULL; - if (major == brd->serial_driver->major || - major == brd->print_driver->major) - return brd; - } - - return NULL; -} - -/************************************************************************ - * - * TTY Entry points and helper functions - * - ************************************************************************/ - -/* - * dgap_tty_open() - * - */ -static int dgap_tty_open(struct tty_struct *tty, struct file *file) -{ - struct board_t *brd; - struct channel_t *ch; - struct un_t *un; - struct bs_t __iomem *bs; - uint major; - uint minor; - int rc; - ulong lock_flags; - ulong lock_flags2; - u16 head; - - major = MAJOR(tty_devnum(tty)); - minor = MINOR(tty_devnum(tty)); - - brd = find_board_by_major(major); - if (!brd) - return -EIO; - - /* - * If board is not yet up to a state of READY, go to - * sleep waiting for it to happen or they cancel the open. - */ - rc = wait_event_interruptible(brd->state_wait, - (brd->state & BOARD_READY)); - - if (rc) - return rc; - - spin_lock_irqsave(&brd->bd_lock, lock_flags); - - /* The wait above should guarantee this cannot happen */ - if (brd->state != BOARD_READY) { - spin_unlock_irqrestore(&brd->bd_lock, lock_flags); - return -EIO; - } - - /* If opened device is greater than our number of ports, bail. */ - if (MINOR(tty_devnum(tty)) > brd->nasync) { - spin_unlock_irqrestore(&brd->bd_lock, lock_flags); - return -EIO; - } - - ch = brd->channels[minor]; - if (!ch) { - spin_unlock_irqrestore(&brd->bd_lock, lock_flags); - return -EIO; - } - - /* Grab channel lock */ - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - /* Figure out our type */ - if (major == brd->serial_driver->major) { - un = &brd->channels[minor]->ch_tun; - un->un_type = DGAP_SERIAL; - } else if (major == brd->print_driver->major) { - un = &brd->channels[minor]->ch_pun; - un->un_type = DGAP_PRINT; - } else { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&brd->bd_lock, lock_flags); - return -EIO; - } - - /* Store our unit into driver_data, so we always have it available. */ - tty->driver_data = un; - - /* - * Error if channel info pointer is NULL. - */ - bs = ch->ch_bs; - if (!bs) { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&brd->bd_lock, lock_flags); - return -EIO; - } - - /* - * Initialize tty's - */ - if (!(un->un_flags & UN_ISOPEN)) { - /* Store important variables. */ - un->un_tty = tty; - - /* Maybe do something here to the TTY struct as well? */ - } - - /* - * Initialize if neither terminal or printer is open. - */ - if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_ISOPEN)) { - ch->ch_mforce = 0; - ch->ch_mval = 0; - - /* - * Flush input queue. - */ - head = readw(&bs->rx_head); - writew(head, &bs->rx_tail); - - ch->ch_flags = 0; - ch->pscan_state = 0; - ch->pscan_savechar = 0; - - ch->ch_c_cflag = tty->termios.c_cflag; - ch->ch_c_iflag = tty->termios.c_iflag; - ch->ch_c_oflag = tty->termios.c_oflag; - ch->ch_c_lflag = tty->termios.c_lflag; - ch->ch_startc = tty->termios.c_cc[VSTART]; - ch->ch_stopc = tty->termios.c_cc[VSTOP]; - - /* TODO: flush our TTY struct here? */ - } - - dgap_carrier(ch); - /* - * Run param in case we changed anything - */ - dgap_param(ch, brd, un->un_type); - - /* - * follow protocol for opening port - */ - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&brd->bd_lock, lock_flags); - - rc = dgap_block_til_ready(tty, file, ch); - - if (!un->un_tty) - return -ENODEV; - - /* No going back now, increment our unit and channel counters */ - spin_lock_irqsave(&ch->ch_lock, lock_flags); - ch->ch_open_count++; - un->un_open_count++; - un->un_flags |= (UN_ISOPEN); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - return rc; -} - -/* - * dgap_tty_close() - * - */ -static void dgap_tty_close(struct tty_struct *tty, struct file *file) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - - /* - * Determine if this is the last close or not - and if we agree about - * which type of close it is with the Line Discipline - */ - if ((tty->count == 1) && (un->un_open_count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. un_open_count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - un->un_open_count = 1; - } - - if (--un->un_open_count < 0) - un->un_open_count = 0; - - ch->ch_open_count--; - - if (ch->ch_open_count && un->un_open_count) { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - return; - } - - /* OK, its the last close on the unit */ - - un->un_flags |= UN_CLOSING; - - tty->closing = 1; - - /* - * Only officially close channel if count is 0 and - * DIGI_PRINTER bit is not set. - */ - if ((ch->ch_open_count == 0) && - !(ch->ch_digi.digi_flags & DIGI_PRINTER)) { - ch->ch_flags &= ~(CH_RXBLOCK); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - /* wait for output to drain */ - /* This will also return if we take an interrupt */ - - dgap_wait_for_drain(tty); - - dgap_tty_flush_buffer(tty); - tty_ldisc_flush(tty); - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - - tty->closing = 0; - - /* - * If we have HUPCL set, lower DTR and RTS - */ - if (ch->ch_c_cflag & HUPCL) { - ch->ch_mostat &= ~(D_RTS(ch) | D_DTR(ch)); - dgap_cmdb(ch, SMODEM, 0, D_DTR(ch) | D_RTS(ch), 0); - - /* - * Go to sleep to ensure RTS/DTR - * have been dropped for modems to see it. - */ - spin_unlock_irqrestore(&ch->ch_lock, - lock_flags); - - /* .25 second delay for dropping RTS/DTR */ - schedule_timeout_interruptible(msecs_to_jiffies(250)); - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - } - - ch->pscan_state = 0; - ch->pscan_savechar = 0; - ch->ch_baud_info = 0; - } - - /* - * turn off print device when closing print device. - */ - if ((un->un_type == DGAP_PRINT) && (ch->ch_flags & CH_PRON)) { - dgap_wmove(ch, ch->ch_digi.digi_offstr, - (int)ch->ch_digi.digi_offlen); - ch->ch_flags &= ~CH_PRON; - } - - un->un_tty = NULL; - un->un_flags &= ~(UN_ISOPEN | UN_CLOSING); - tty->driver_data = NULL; - - wake_up_interruptible(&ch->ch_flags_wait); - wake_up_interruptible(&un->un_flags_wait); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); -} - -static void dgap_tty_start(struct tty_struct *tty) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - dgap_cmdw(ch, RESUMETX, 0, 0); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); -} - -static void dgap_tty_stop(struct tty_struct *tty) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - dgap_cmdw(ch, PAUSETX, 0, 0); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); -} - -/* - * dgap_tty_flush_chars() - * - * Flush the cook buffer - * - * Note to self, and any other poor souls who venture here: - * - * flush in this case DOES NOT mean dispose of the data. - * instead, it means "stop buffering and send it if you - * haven't already." Just guess how I figured that out... SRW 2-Jun-98 - * - * It is also always called in interrupt context - JAR 8-Sept-99 - */ -static void dgap_tty_flush_chars(struct tty_struct *tty) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - /* TODO: Do something here */ - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); -} - -/***************************************************************************** - * - * The IOCTL function and all of its helpers - * - *****************************************************************************/ - -/* - * dgap_tty_ioctl() - * - * The usual assortment of ioctl's - */ -static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, - unsigned long arg) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - int rc; - u16 head; - ulong lock_flags = 0; - ulong lock_flags2 = 0; - void __user *uarg = (void __user *)arg; - - if (!tty || tty->magic != TTY_MAGIC) - return -ENODEV; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -ENODEV; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -ENODEV; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return -ENODEV; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - if (un->un_open_count <= 0) { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return -EIO; - } - - switch (cmd) { - /* Here are all the standard ioctl's that we MUST implement */ - case TCSBRK: - /* - * TCSBRK is SVID version: non-zero arg --> no break - * this behaviour is exploited by tcdrain(). - * - * According to POSIX.1 spec (7.2.2.1.2) breaks should be - * between 0.25 and 0.5 seconds so we'll ask for something - * in the middle: 0.375 seconds. - */ - rc = tty_check_change(tty); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - if (rc) - return rc; - - rc = dgap_wait_for_drain(tty); - - if (rc) - return -EINTR; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - if (((cmd == TCSBRK) && (!arg)) || (cmd == TCSBRKP)) - dgap_cmdw(ch, SBREAK, (u16)SBREAK_TIME, 0); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; - - case TCSBRKP: - /* support for POSIX tcsendbreak() - - * According to POSIX.1 spec (7.2.2.1.2) breaks should be - * between 0.25 and 0.5 seconds so we'll ask for something - * in the middle: 0.375 seconds. - */ - rc = tty_check_change(tty); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - if (rc) - return rc; - - rc = dgap_wait_for_drain(tty); - if (rc) - return -EINTR; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - dgap_cmdw(ch, SBREAK, (u16)SBREAK_TIME, 0); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; - - case TIOCSBRK: - /* - * FEP5 doesn't support turning on a break unconditionally. - * The FEP5 device will stop sending a break automatically - * after the specified time value that was sent when turning on - * the break. - */ - rc = tty_check_change(tty); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - if (rc) - return rc; - - rc = dgap_wait_for_drain(tty); - if (rc) - return -EINTR; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - dgap_cmdw(ch, SBREAK, (u16)SBREAK_TIME, 0); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; - - case TIOCCBRK: - /* - * FEP5 doesn't support turning off a break unconditionally. - * The FEP5 device will stop sending a break automatically - * after the specified time value that was sent when turning on - * the break. - */ - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return 0; - - case TIOCGSOFTCAR: - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return put_user(C_CLOCAL(tty) ? 1 : 0, - (unsigned long __user *)arg); - - case TIOCSSOFTCAR: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - rc = get_user(arg, (unsigned long __user *)arg); - if (rc) - return rc; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - tty->termios.c_cflag = ((tty->termios.c_cflag & ~CLOCAL) | - (arg ? CLOCAL : 0)); - dgap_param(ch, bd, un->un_type); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; - - case TIOCMGET: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_get_modem_info(ch, uarg); - - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_set_modem_info(ch, bd, un, cmd, uarg); - - /* - * Here are any additional ioctl's that we want to implement - */ - - case TCFLSH: - /* - * The linux tty driver doesn't have a flush - * input routine for the driver, assuming all backed - * up data is in the line disc. buffers. However, - * we all know that's not the case. Here, we - * act on the ioctl, but then lie and say we didn't - * so the line discipline will process the flush - * also. - */ - rc = tty_check_change(tty); - if (rc) { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return rc; - } - - if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) { - if (!(un->un_type == DGAP_PRINT)) { - head = readw(&ch->ch_bs->rx_head); - writew(head, &ch->ch_bs->rx_tail); - writeb(0, &ch->ch_bs->orun); - } - } - - if ((arg != TCOFLUSH) && (arg != TCIOFLUSH)) { - /* pretend we didn't recognize this IOCTL */ - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return -ENOIOCTLCMD; - } - - ch->ch_flags &= ~CH_STOP; - head = readw(&ch->ch_bs->tx_head); - dgap_cmdw(ch, FLUSHTX, (u16)head, 0); - dgap_cmdw(ch, RESUMETX, 0, 0); - if (ch->ch_tun.un_flags & (UN_LOW | UN_EMPTY)) { - ch->ch_tun.un_flags &= ~(UN_LOW | UN_EMPTY); - wake_up_interruptible(&ch->ch_tun.un_flags_wait); - } - if (ch->ch_pun.un_flags & (UN_LOW | UN_EMPTY)) { - ch->ch_pun.un_flags &= ~(UN_LOW | UN_EMPTY); - wake_up_interruptible(&ch->ch_pun.un_flags_wait); - } - if (waitqueue_active(&tty->write_wait)) - wake_up_interruptible(&tty->write_wait); - - /* Can't hold any locks when calling tty_wakeup! */ - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - tty_wakeup(tty); - - /* pretend we didn't recognize this IOCTL */ - return -ENOIOCTLCMD; - - case TCSETSF: - case TCSETSW: - /* - * The linux tty driver doesn't have a flush - * input routine for the driver, assuming all backed - * up data is in the line disc. buffers. However, - * we all know that's not the case. Here, we - * act on the ioctl, but then lie and say we didn't - * so the line discipline will process the flush - * also. - */ - if (cmd == TCSETSF) { - /* flush rx */ - ch->ch_flags &= ~CH_STOP; - head = readw(&ch->ch_bs->rx_head); - writew(head, &ch->ch_bs->rx_tail); - } - - /* now wait for all the output to drain */ - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - rc = dgap_wait_for_drain(tty); - if (rc) - return -EINTR; - - /* pretend we didn't recognize this */ - return -ENOIOCTLCMD; - - case TCSETAW: - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - rc = dgap_wait_for_drain(tty); - if (rc) - return -EINTR; - - /* pretend we didn't recognize this */ - return -ENOIOCTLCMD; - - case TCXONC: - /* - * The Linux Line Discipline (LD) would do this for us if we - * let it, but we have the special firmware options to do this - * the "right way" regardless of hardware or software flow - * control so we'll do it outselves instead of letting the LD - * do it. - */ - rc = tty_check_change(tty); - if (rc) { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return rc; - } - - switch (arg) { - case TCOON: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - dgap_tty_start(tty); - return 0; - case TCOOFF: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - dgap_tty_stop(tty); - return 0; - case TCION: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - /* Make the ld do it */ - return -ENOIOCTLCMD; - case TCIOFF: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - /* Make the ld do it */ - return -ENOIOCTLCMD; - default: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return -EINVAL; - } - - case DIGI_GETA: - /* get information for ditty */ - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digigeta(ch, uarg); - - case DIGI_SETAW: - case DIGI_SETAF: - - /* set information for ditty */ - if (cmd == (DIGI_SETAW)) { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - rc = dgap_wait_for_drain(tty); - if (rc) - return -EINTR; - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - } else - tty_ldisc_flush(tty); - /* fall thru */ - - case DIGI_SETA: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digiseta(ch, bd, un, uarg); - - case DIGI_GEDELAY: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digigetedelay(tty, uarg); - - case DIGI_SEDELAY: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digisetedelay(ch, bd, un, uarg); - - case DIGI_GETCUSTOMBAUD: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digigetcustombaud(ch, un, uarg); - - case DIGI_SETCUSTOMBAUD: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digisetcustombaud(ch, bd, un, uarg); - - case DIGI_RESET_PORT: - dgap_firmware_reset_port(ch); - dgap_param(ch, bd, un->un_type); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return 0; - - default: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return -ENOIOCTLCMD; - } -} - -static const struct tty_operations dgap_tty_ops = { - .open = dgap_tty_open, - .close = dgap_tty_close, - .write = dgap_tty_write, - .write_room = dgap_tty_write_room, - .flush_buffer = dgap_tty_flush_buffer, - .chars_in_buffer = dgap_tty_chars_in_buffer, - .flush_chars = dgap_tty_flush_chars, - .ioctl = dgap_tty_ioctl, - .set_termios = dgap_tty_set_termios, - .stop = dgap_tty_stop, - .start = dgap_tty_start, - .throttle = dgap_tty_throttle, - .unthrottle = dgap_tty_unthrottle, - .hangup = dgap_tty_hangup, - .put_char = dgap_tty_put_char, - .tiocmget = dgap_tty_tiocmget, - .tiocmset = dgap_tty_tiocmset, - .break_ctl = dgap_tty_send_break, - .wait_until_sent = dgap_tty_wait_until_sent, - .send_xchar = dgap_tty_send_xchar -}; - -/************************************************************************ - * - * TTY Initialization/Cleanup Functions - * - ************************************************************************/ - -/* - * dgap_tty_register() - * - * Init the tty subsystem for this board. - */ -static int dgap_tty_register(struct board_t *brd) -{ - int rc; - - brd->serial_driver = tty_alloc_driver(MAXPORTS, - TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_DEV | - TTY_DRIVER_HARDWARE_BREAK); - if (IS_ERR(brd->serial_driver)) - return PTR_ERR(brd->serial_driver); - - snprintf(brd->serial_name, MAXTTYNAMELEN, "tty_dgap_%d_", - brd->boardnum); - brd->serial_driver->name = brd->serial_name; - brd->serial_driver->name_base = 0; - brd->serial_driver->major = 0; - brd->serial_driver->minor_start = 0; - brd->serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - brd->serial_driver->subtype = SERIAL_TYPE_NORMAL; - brd->serial_driver->init_termios = dgap_default_termios; - brd->serial_driver->driver_name = DRVSTR; - - /* - * Entry points for driver. Called by the kernel from - * tty_io.c and n_tty.c. - */ - tty_set_operations(brd->serial_driver, &dgap_tty_ops); - - /* - * If we're doing transparent print, we have to do all of the above - * again, separately so we don't get the LD confused about what major - * we are when we get into the dgap_tty_open() routine. - */ - brd->print_driver = tty_alloc_driver(MAXPORTS, - TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_DEV | - TTY_DRIVER_HARDWARE_BREAK); - if (IS_ERR(brd->print_driver)) { - rc = PTR_ERR(brd->print_driver); - goto free_serial_drv; - } - - snprintf(brd->print_name, MAXTTYNAMELEN, "pr_dgap_%d_", - brd->boardnum); - brd->print_driver->name = brd->print_name; - brd->print_driver->name_base = 0; - brd->print_driver->major = 0; - brd->print_driver->minor_start = 0; - brd->print_driver->type = TTY_DRIVER_TYPE_SERIAL; - brd->print_driver->subtype = SERIAL_TYPE_NORMAL; - brd->print_driver->init_termios = dgap_default_termios; - brd->print_driver->driver_name = DRVSTR; - - /* - * Entry points for driver. Called by the kernel from - * tty_io.c and n_tty.c. - */ - tty_set_operations(brd->print_driver, &dgap_tty_ops); - - /* Register tty devices */ - rc = tty_register_driver(brd->serial_driver); - if (rc < 0) - goto free_print_drv; - - /* Register Transparent Print devices */ - rc = tty_register_driver(brd->print_driver); - if (rc < 0) - goto unregister_serial_drv; - - return 0; - -unregister_serial_drv: - tty_unregister_driver(brd->serial_driver); -free_print_drv: - put_tty_driver(brd->print_driver); -free_serial_drv: - put_tty_driver(brd->serial_driver); - - return rc; -} - -static void dgap_tty_unregister(struct board_t *brd) -{ - tty_unregister_driver(brd->print_driver); - tty_unregister_driver(brd->serial_driver); - put_tty_driver(brd->print_driver); - put_tty_driver(brd->serial_driver); -} - -static int dgap_alloc_flipbuf(struct board_t *brd) -{ - /* - * allocate flip buffer for board. - */ - brd->flipbuf = kmalloc(MYFLIPLEN, GFP_KERNEL); - if (!brd->flipbuf) - return -ENOMEM; - - brd->flipflagbuf = kmalloc(MYFLIPLEN, GFP_KERNEL); - if (!brd->flipflagbuf) { - kfree(brd->flipbuf); - return -ENOMEM; - } - - return 0; -} - -static void dgap_free_flipbuf(struct board_t *brd) -{ - kfree(brd->flipbuf); - kfree(brd->flipflagbuf); -} - -static struct board_t *dgap_verify_board(struct device *p) -{ - struct board_t *bd; - - if (!p) - return NULL; - - bd = dev_get_drvdata(p); - if (!bd || bd->magic != DGAP_BOARD_MAGIC || bd->state != BOARD_READY) - return NULL; - - return bd; -} - -static ssize_t dgap_ports_state_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) { - count += snprintf(buf + count, PAGE_SIZE - count, - "%d %s\n", bd->channels[i]->ch_portnum, - bd->channels[i]->ch_open_count ? "Open" : "Closed"); - } - return count; -} -static DEVICE_ATTR(ports_state, S_IRUSR, dgap_ports_state_show, NULL); - -static ssize_t dgap_ports_baud_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) { - count += snprintf(buf + count, PAGE_SIZE - count, "%d %d\n", - bd->channels[i]->ch_portnum, - bd->channels[i]->ch_baud_info); - } - return count; -} -static DEVICE_ATTR(ports_baud, S_IRUSR, dgap_ports_baud_show, NULL); - -static ssize_t dgap_ports_msignals_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) { - if (bd->channels[i]->ch_open_count) - count += snprintf(buf + count, PAGE_SIZE - count, - "%d %s %s %s %s %s %s\n", - bd->channels[i]->ch_portnum, - (bd->channels[i]->ch_mostat & - UART_MCR_RTS) ? "RTS" : "", - (bd->channels[i]->ch_mistat & - UART_MSR_CTS) ? "CTS" : "", - (bd->channels[i]->ch_mostat & - UART_MCR_DTR) ? "DTR" : "", - (bd->channels[i]->ch_mistat & - UART_MSR_DSR) ? "DSR" : "", - (bd->channels[i]->ch_mistat & - UART_MSR_DCD) ? "DCD" : "", - (bd->channels[i]->ch_mistat & - UART_MSR_RI) ? "RI" : ""); - else - count += snprintf(buf + count, PAGE_SIZE - count, - "%d\n", bd->channels[i]->ch_portnum); - } - return count; -} -static DEVICE_ATTR(ports_msignals, S_IRUSR, dgap_ports_msignals_show, NULL); - -static ssize_t dgap_ports_iflag_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) - count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n", - bd->channels[i]->ch_portnum, - bd->channels[i]->ch_c_iflag); - return count; -} -static DEVICE_ATTR(ports_iflag, S_IRUSR, dgap_ports_iflag_show, NULL); - -static ssize_t dgap_ports_cflag_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) - count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n", - bd->channels[i]->ch_portnum, - bd->channels[i]->ch_c_cflag); - return count; -} -static DEVICE_ATTR(ports_cflag, S_IRUSR, dgap_ports_cflag_show, NULL); - -static ssize_t dgap_ports_oflag_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) - count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n", - bd->channels[i]->ch_portnum, - bd->channels[i]->ch_c_oflag); - return count; -} -static DEVICE_ATTR(ports_oflag, S_IRUSR, dgap_ports_oflag_show, NULL); - -static ssize_t dgap_ports_lflag_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) - count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n", - bd->channels[i]->ch_portnum, - bd->channels[i]->ch_c_lflag); - return count; -} -static DEVICE_ATTR(ports_lflag, S_IRUSR, dgap_ports_lflag_show, NULL); - -static ssize_t dgap_ports_digi_flag_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) - count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n", - bd->channels[i]->ch_portnum, - bd->channels[i]->ch_digi.digi_flags); - return count; -} -static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgap_ports_digi_flag_show, NULL); - -static ssize_t dgap_ports_rxcount_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) - count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n", - bd->channels[i]->ch_portnum, - bd->channels[i]->ch_rxcount); - return count; -} -static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgap_ports_rxcount_show, NULL); - -static ssize_t dgap_ports_txcount_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) - count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n", - bd->channels[i]->ch_portnum, - bd->channels[i]->ch_txcount); - return count; -} -static DEVICE_ATTR(ports_txcount, S_IRUSR, dgap_ports_txcount_show, NULL); - -static ssize_t dgap_tty_state_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? - "Open" : "Closed"); -} -static DEVICE_ATTR(state, S_IRUSR, dgap_tty_state_show, NULL); - -static ssize_t dgap_tty_baud_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_baud_info); -} -static DEVICE_ATTR(baud, S_IRUSR, dgap_tty_baud_show, NULL); - -static ssize_t dgap_tty_msignals_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - if (ch->ch_open_count) { - return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n", - (ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "", - (ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "", - (ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "", - (ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "", - (ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "", - (ch->ch_mistat & UART_MSR_RI) ? "RI" : ""); - } - return 0; -} -static DEVICE_ATTR(msignals, S_IRUSR, dgap_tty_msignals_show, NULL); - -static ssize_t dgap_tty_iflag_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag); -} -static DEVICE_ATTR(iflag, S_IRUSR, dgap_tty_iflag_show, NULL); - -static ssize_t dgap_tty_cflag_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag); -} -static DEVICE_ATTR(cflag, S_IRUSR, dgap_tty_cflag_show, NULL); - -static ssize_t dgap_tty_oflag_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag); -} -static DEVICE_ATTR(oflag, S_IRUSR, dgap_tty_oflag_show, NULL); - -static ssize_t dgap_tty_lflag_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag); -} -static DEVICE_ATTR(lflag, S_IRUSR, dgap_tty_lflag_show, NULL); - -static ssize_t dgap_tty_digi_flag_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags); -} -static DEVICE_ATTR(digi_flag, S_IRUSR, dgap_tty_digi_flag_show, NULL); - -static ssize_t dgap_tty_rxcount_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount); -} -static DEVICE_ATTR(rxcount, S_IRUSR, dgap_tty_rxcount_show, NULL); - -static ssize_t dgap_tty_txcount_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount); -} -static DEVICE_ATTR(txcount, S_IRUSR, dgap_tty_txcount_show, NULL); - -static ssize_t dgap_tty_name_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - int cn; - int bn; - struct cnode *cptr; - int found = FALSE; - int ncount = 0; - int starto = 0; - int i; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - bn = bd->boardnum; - cn = ch->ch_portnum; - - for (cptr = bd->bd_config; cptr; cptr = cptr->next) { - if ((cptr->type == BNODE) && - ((cptr->u.board.type == APORT2_920P) || - (cptr->u.board.type == APORT4_920P) || - (cptr->u.board.type == APORT8_920P) || - (cptr->u.board.type == PAPORT4) || - (cptr->u.board.type == PAPORT8))) { - found = TRUE; - if (cptr->u.board.v_start) - starto = cptr->u.board.start; - else - starto = 1; - } - - if (cptr->type == TNODE && found == TRUE) { - char *ptr1; - - if (strstr(cptr->u.ttyname, "tty")) { - ptr1 = cptr->u.ttyname; - ptr1 += 3; - } else - ptr1 = cptr->u.ttyname; - - for (i = 0; i < dgap_config_get_num_prts(bd); i++) { - if (cn != i) - continue; - - return snprintf(buf, PAGE_SIZE, "%s%s%02d\n", - (un->un_type == DGAP_PRINT) ? - "pr" : "tty", - ptr1, i + starto); - } - } - - if (cptr->type == CNODE) { - for (i = 0; i < cptr->u.conc.nport; i++) { - if (cn != (i + ncount)) - continue; - - return snprintf(buf, PAGE_SIZE, "%s%s%02ld\n", - (un->un_type == DGAP_PRINT) ? - "pr" : "tty", - cptr->u.conc.id, - i + (cptr->u.conc.v_start ? - cptr->u.conc.start : 1)); - } - - ncount += cptr->u.conc.nport; - } - - if (cptr->type == MNODE) { - for (i = 0; i < cptr->u.module.nport; i++) { - if (cn != (i + ncount)) - continue; - - return snprintf(buf, PAGE_SIZE, "%s%s%02ld\n", - (un->un_type == DGAP_PRINT) ? - "pr" : "tty", - cptr->u.module.id, - i + (cptr->u.module.v_start ? - cptr->u.module.start : 1)); - } - - ncount += cptr->u.module.nport; - } - } - - return snprintf(buf, PAGE_SIZE, "%s_dgap_%d_%d\n", - (un->un_type == DGAP_PRINT) ? "pr" : "tty", bn, cn); -} -static DEVICE_ATTR(custom_name, S_IRUSR, dgap_tty_name_show, NULL); - -static struct attribute *dgap_sysfs_tty_entries[] = { - &dev_attr_state.attr, - &dev_attr_baud.attr, - &dev_attr_msignals.attr, - &dev_attr_iflag.attr, - &dev_attr_cflag.attr, - &dev_attr_oflag.attr, - &dev_attr_lflag.attr, - &dev_attr_digi_flag.attr, - &dev_attr_rxcount.attr, - &dev_attr_txcount.attr, - &dev_attr_custom_name.attr, - NULL -}; - - -/* this function creates the sys files that will export each signal status - * to sysfs each value will be put in a separate filename - */ -static void dgap_create_ports_sysfiles(struct board_t *bd) -{ - dev_set_drvdata(&bd->pdev->dev, bd); - device_create_file(&bd->pdev->dev, &dev_attr_ports_state); - device_create_file(&bd->pdev->dev, &dev_attr_ports_baud); - device_create_file(&bd->pdev->dev, &dev_attr_ports_msignals); - device_create_file(&bd->pdev->dev, &dev_attr_ports_iflag); - device_create_file(&bd->pdev->dev, &dev_attr_ports_cflag); - device_create_file(&bd->pdev->dev, &dev_attr_ports_oflag); - device_create_file(&bd->pdev->dev, &dev_attr_ports_lflag); - device_create_file(&bd->pdev->dev, &dev_attr_ports_digi_flag); - device_create_file(&bd->pdev->dev, &dev_attr_ports_rxcount); - device_create_file(&bd->pdev->dev, &dev_attr_ports_txcount); -} - -/* removes all the sys files created for that port */ -static void dgap_remove_ports_sysfiles(struct board_t *bd) -{ - device_remove_file(&bd->pdev->dev, &dev_attr_ports_state); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_baud); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_msignals); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_iflag); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_cflag); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_oflag); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_lflag); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_digi_flag); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_rxcount); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_txcount); -} - -/* - * Copies the BIOS code from the user to the board, - * and starts the BIOS running. - */ -static void dgap_do_bios_load(struct board_t *brd, const u8 *ubios, int len) -{ - u8 __iomem *addr; - uint offset; - unsigned int i; - - if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase) - return; - - addr = brd->re_map_membase; - - /* - * clear POST area - */ - for (i = 0; i < 16; i++) - writeb(0, addr + POSTAREA + i); - - /* - * Download bios - */ - offset = 0x1000; - memcpy_toio(addr + offset, ubios, len); - - writel(0x0bf00401, addr); - writel(0, (addr + 4)); - - /* Clear the reset, and change states. */ - writeb(FEPCLR, brd->re_map_port); -} - -/* - * Checks to see if the BIOS completed running on the card. - */ -static int dgap_test_bios(struct board_t *brd) -{ - u8 __iomem *addr; - u16 word; - u16 err1; - u16 err2; - - if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase) - return -EINVAL; - - addr = brd->re_map_membase; - word = readw(addr + POSTAREA); - - /* - * It can take 5-6 seconds for a board to - * pass the bios self test and post results. - * Give it 10 seconds. - */ - brd->wait_for_bios = 0; - while (brd->wait_for_bios < 1000) { - /* Check to see if BIOS thinks board is good. (GD). */ - if (word == *(u16 *)"GD") - return 0; - msleep_interruptible(10); - brd->wait_for_bios++; - word = readw(addr + POSTAREA); - } - - /* Gave up on board after too long of time taken */ - err1 = readw(addr + SEQUENCE); - err2 = readw(addr + ERROR); - dev_warn(&brd->pdev->dev, "%s failed diagnostics. Error #(%x,%x).\n", - brd->name, err1, err2); - brd->state = BOARD_FAILED; - brd->dpastatus = BD_NOBIOS; - - return -EIO; -} - -/* - * Copies the FEP code from the user to the board, - * and starts the FEP running. - */ -static void dgap_do_fep_load(struct board_t *brd, const u8 *ufep, int len) -{ - u8 __iomem *addr; - uint offset; - - if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase) - return; - - addr = brd->re_map_membase; - - /* - * Download FEP - */ - offset = 0x1000; - memcpy_toio(addr + offset, ufep, len); - - /* - * If board is a concentrator product, we need to give - * it its config string describing how the concentrators look. - */ - if ((brd->type == PCX) || (brd->type == PEPC)) { - u8 string[100]; - u8 __iomem *config; - u8 *xconfig; - unsigned int i = 0; - - xconfig = dgap_create_config_string(brd, string); - - /* Write string to board memory */ - config = addr + CONFIG; - for (; i < CONFIGSIZE; i++, config++, xconfig++) { - writeb(*xconfig, config); - if ((*xconfig & 0xff) == 0xff) - break; - } - } - - writel(0xbfc01004, (addr + 0xc34)); - writel(0x3, (addr + 0xc30)); -} - -/* - * Waits for the FEP to report thats its ready for us to use. - */ -static int dgap_test_fep(struct board_t *brd) -{ - u8 __iomem *addr; - u16 word; - u16 err1; - u16 err2; - - if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase) - return -EINVAL; - - addr = brd->re_map_membase; - word = readw(addr + FEPSTAT); - - /* - * It can take 2-3 seconds for the FEP to - * be up and running. Give it 5 secs. - */ - brd->wait_for_fep = 0; - while (brd->wait_for_fep < 500) { - /* Check to see if FEP is up and running now. */ - if (word == *(u16 *)"OS") { - /* - * Check to see if the board can support FEP5+ commands. - */ - word = readw(addr + FEP5_PLUS); - if (word == *(u16 *)"5A") - brd->bd_flags |= BD_FEP5PLUS; - - return 0; - } - msleep_interruptible(10); - brd->wait_for_fep++; - word = readw(addr + FEPSTAT); - } - - /* Gave up on board after too long of time taken */ - err1 = readw(addr + SEQUENCE); - err2 = readw(addr + ERROR); - dev_warn(&brd->pdev->dev, - "FEPOS for %s not functioning. Error #(%x,%x).\n", - brd->name, err1, err2); - brd->state = BOARD_FAILED; - brd->dpastatus = BD_NOFEP; - - return -EIO; -} - -/* - * Physically forces the FEP5 card to reset itself. - */ -static void dgap_do_reset_board(struct board_t *brd) -{ - u8 check; - u32 check1; - u32 check2; - unsigned int i; - - if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || - !brd->re_map_membase || !brd->re_map_port) - return; - - /* FEPRST does not vary among supported boards */ - writeb(FEPRST, brd->re_map_port); - - for (i = 0; i <= 1000; i++) { - check = readb(brd->re_map_port) & 0xe; - if (check == FEPRST) - break; - udelay(10); - } - if (i > 1000) { - dev_warn(&brd->pdev->dev, - "dgap: Board not resetting... Failing board.\n"); - brd->state = BOARD_FAILED; - brd->dpastatus = BD_NOFEP; - return; - } - - /* - * Make sure there really is memory out there. - */ - writel(0xa55a3cc3, (brd->re_map_membase + LOWMEM)); - writel(0x5aa5c33c, (brd->re_map_membase + HIGHMEM)); - check1 = readl(brd->re_map_membase + LOWMEM); - check2 = readl(brd->re_map_membase + HIGHMEM); - - if ((check1 != 0xa55a3cc3) || (check2 != 0x5aa5c33c)) { - dev_warn(&brd->pdev->dev, - "No memory at %p for board.\n", - brd->re_map_membase); - brd->state = BOARD_FAILED; - brd->dpastatus = BD_NOFEP; - return; - } -} - -#ifdef DIGI_CONCENTRATORS_SUPPORTED -/* - * Sends a concentrator image into the FEP5 board. - */ -static void dgap_do_conc_load(struct board_t *brd, u8 *uaddr, int len) -{ - char __iomem *vaddr; - u16 offset; - struct downld_t *to_dp; - - if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase) - return; - - vaddr = brd->re_map_membase; - - offset = readw((u16 *)(vaddr + DOWNREQ)); - to_dp = (struct downld_t *)(vaddr + (int)offset); - memcpy_toio(to_dp, uaddr, len); - - /* Tell card we have data for it */ - writew(0, vaddr + (DOWNREQ)); - - brd->conc_dl_status = NO_PENDING_CONCENTRATOR_REQUESTS; -} -#endif - -#define EXPANSION_ROM_SIZE (64 * 1024) -#define FEP5_ROM_MAGIC (0xFEFFFFFF) - -static void dgap_get_vpd(struct board_t *brd) -{ - u32 magic; - u32 base_offset; - u16 rom_offset; - u16 vpd_offset; - u16 image_length; - u16 i; - u8 byte1; - u8 byte2; - - /* - * Poke the magic number at the PCI Rom Address location. - * If VPD is supported, the value read from that address - * will be non-zero. - */ - magic = FEP5_ROM_MAGIC; - pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic); - pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic); - - /* VPD not supported, bail */ - if (!magic) - return; - - /* - * To get to the OTPROM memory, we have to send the boards base - * address or'ed with 1 into the PCI Rom Address location. - */ - magic = brd->membase | 0x01; - pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic); - pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic); - - byte1 = readb(brd->re_map_membase); - byte2 = readb(brd->re_map_membase + 1); - - /* - * If the board correctly swapped to the OTPROM memory, - * the first 2 bytes (header) should be 0x55, 0xAA - */ - if (byte1 == 0x55 && byte2 == 0xAA) { - base_offset = 0; - - /* - * We have to run through all the OTPROM memory looking - * for the VPD offset. - */ - while (base_offset <= EXPANSION_ROM_SIZE) { - /* - * Lots of magic numbers here. - * - * The VPD offset is located inside the ROM Data - * Structure. - * - * We also have to remember the length of each - * ROM Data Structure, so we can "hop" to the next - * entry if the VPD isn't in the current - * ROM Data Structure. - */ - rom_offset = readw(brd->re_map_membase + - base_offset + 0x18); - image_length = readw(brd->re_map_membase + - rom_offset + 0x10) * 512; - vpd_offset = readw(brd->re_map_membase + - rom_offset + 0x08); - - /* Found the VPD entry */ - if (vpd_offset) - break; - - /* We didn't find a VPD entry, go to next ROM entry. */ - base_offset += image_length; - - byte1 = readb(brd->re_map_membase + base_offset); - byte2 = readb(brd->re_map_membase + base_offset + 1); - - /* - * If the new ROM offset doesn't have 0x55, 0xAA - * as its header, we have run out of ROM. - */ - if (byte1 != 0x55 || byte2 != 0xAA) - break; - } - - /* - * If we have a VPD offset, then mark the board - * as having a valid VPD, and copy VPDSIZE (512) bytes of - * that VPD to the buffer we have in our board structure. - */ - if (vpd_offset) { - brd->bd_flags |= BD_HAS_VPD; - for (i = 0; i < VPDSIZE; i++) { - brd->vpd[i] = readb(brd->re_map_membase + - vpd_offset + i); - } - } - } - - /* - * We MUST poke the magic number at the PCI Rom Address location again. - * This makes the card report the regular board memory back to us, - * rather than the OTPROM memory. - */ - magic = FEP5_ROM_MAGIC; - pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic); -} - - -static ssize_t dgap_driver_version_show(struct device_driver *ddp, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART); -} -static DRIVER_ATTR(version, S_IRUSR, dgap_driver_version_show, NULL); - - -static ssize_t dgap_driver_boards_show(struct device_driver *ddp, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", dgap_numboards); -} -static DRIVER_ATTR(boards, S_IRUSR, dgap_driver_boards_show, NULL); - - -static ssize_t dgap_driver_maxboards_show(struct device_driver *ddp, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS); -} -static DRIVER_ATTR(maxboards, S_IRUSR, dgap_driver_maxboards_show, NULL); - - -static ssize_t dgap_driver_pollcounter_show(struct device_driver *ddp, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%ld\n", dgap_poll_counter); -} -static DRIVER_ATTR(pollcounter, S_IRUSR, dgap_driver_pollcounter_show, NULL); - -static ssize_t dgap_driver_pollrate_show(struct device_driver *ddp, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%dms\n", dgap_poll_tick); -} - -static ssize_t dgap_driver_pollrate_store(struct device_driver *ddp, - const char *buf, size_t count) -{ - if (sscanf(buf, "%d\n", &dgap_poll_tick) != 1) - return -EINVAL; - return count; -} -static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgap_driver_pollrate_show, - dgap_driver_pollrate_store); - - -static int dgap_create_driver_sysfiles(struct pci_driver *dgap_driver) -{ - int rc = 0; - struct device_driver *driverfs = &dgap_driver->driver; - - rc |= driver_create_file(driverfs, &driver_attr_version); - rc |= driver_create_file(driverfs, &driver_attr_boards); - rc |= driver_create_file(driverfs, &driver_attr_maxboards); - rc |= driver_create_file(driverfs, &driver_attr_pollrate); - rc |= driver_create_file(driverfs, &driver_attr_pollcounter); - - return rc; -} - -static void dgap_remove_driver_sysfiles(struct pci_driver *dgap_driver) -{ - struct device_driver *driverfs = &dgap_driver->driver; - - driver_remove_file(driverfs, &driver_attr_version); - driver_remove_file(driverfs, &driver_attr_boards); - driver_remove_file(driverfs, &driver_attr_maxboards); - driver_remove_file(driverfs, &driver_attr_pollrate); - driver_remove_file(driverfs, &driver_attr_pollcounter); -} - -static struct attribute_group dgap_tty_attribute_group = { - .name = NULL, - .attrs = dgap_sysfs_tty_entries, -}; - -static void dgap_create_tty_sysfs(struct un_t *un, struct device *c) -{ - int ret; - - ret = sysfs_create_group(&c->kobj, &dgap_tty_attribute_group); - if (ret) - return; - - dev_set_drvdata(c, un); -} - -static void dgap_remove_tty_sysfs(struct device *c) -{ - sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group); -} - -/* - * Create pr and tty device entries - */ -static int dgap_tty_register_ports(struct board_t *brd) -{ - struct channel_t *ch; - int i; - int ret; - - brd->serial_ports = kcalloc(brd->nasync, sizeof(*brd->serial_ports), - GFP_KERNEL); - if (!brd->serial_ports) - return -ENOMEM; - - brd->printer_ports = kcalloc(brd->nasync, sizeof(*brd->printer_ports), - GFP_KERNEL); - if (!brd->printer_ports) { - ret = -ENOMEM; - goto free_serial_ports; - } - - for (i = 0; i < brd->nasync; i++) { - tty_port_init(&brd->serial_ports[i]); - tty_port_init(&brd->printer_ports[i]); - } - - ch = brd->channels[0]; - for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) { - struct device *classp; - - classp = tty_port_register_device(&brd->serial_ports[i], - brd->serial_driver, - i, NULL); - - if (IS_ERR(classp)) { - ret = PTR_ERR(classp); - goto unregister_ttys; - } - - dgap_create_tty_sysfs(&ch->ch_tun, classp); - ch->ch_tun.un_sysfs = classp; - - classp = tty_port_register_device(&brd->printer_ports[i], - brd->print_driver, - i, NULL); - - if (IS_ERR(classp)) { - ret = PTR_ERR(classp); - goto unregister_ttys; - } - - dgap_create_tty_sysfs(&ch->ch_pun, classp); - ch->ch_pun.un_sysfs = classp; - } - dgap_create_ports_sysfiles(brd); - - return 0; - -unregister_ttys: - while (i >= 0) { - ch = brd->channels[i]; - if (ch->ch_tun.un_sysfs) { - dgap_remove_tty_sysfs(ch->ch_tun.un_sysfs); - tty_unregister_device(brd->serial_driver, i); - } - - if (ch->ch_pun.un_sysfs) { - dgap_remove_tty_sysfs(ch->ch_pun.un_sysfs); - tty_unregister_device(brd->print_driver, i); - } - i--; - } - - for (i = 0; i < brd->nasync; i++) { - tty_port_destroy(&brd->serial_ports[i]); - tty_port_destroy(&brd->printer_ports[i]); - } - - kfree(brd->printer_ports); - brd->printer_ports = NULL; - -free_serial_ports: - kfree(brd->serial_ports); - brd->serial_ports = NULL; - - return ret; -} - -/* - * dgap_cleanup_tty() - * - * Uninitialize the TTY portion of this driver. Free all memory and - * resources. - */ -static void dgap_cleanup_tty(struct board_t *brd) -{ - struct device *dev; - unsigned int i; - - for (i = 0; i < brd->nasync; i++) { - tty_port_destroy(&brd->serial_ports[i]); - dev = brd->channels[i]->ch_tun.un_sysfs; - dgap_remove_tty_sysfs(dev); - tty_unregister_device(brd->serial_driver, i); - } - tty_unregister_driver(brd->serial_driver); - put_tty_driver(brd->serial_driver); - kfree(brd->serial_ports); - - for (i = 0; i < brd->nasync; i++) { - tty_port_destroy(&brd->printer_ports[i]); - dev = brd->channels[i]->ch_pun.un_sysfs; - dgap_remove_tty_sysfs(dev); - tty_unregister_device(brd->print_driver, i); - } - tty_unregister_driver(brd->print_driver); - put_tty_driver(brd->print_driver); - kfree(brd->printer_ports); -} - -static int dgap_request_irq(struct board_t *brd) -{ - int rc; - - if (!brd || brd->magic != DGAP_BOARD_MAGIC) - return -ENODEV; - - /* - * Set up our interrupt handler if we are set to do interrupts. - */ - if (dgap_config_get_useintr(brd) && brd->irq) { - rc = request_irq(brd->irq, dgap_intr, IRQF_SHARED, "DGAP", brd); - - if (!rc) - brd->intr_used = 1; - } - return 0; -} - -static void dgap_free_irq(struct board_t *brd) -{ - if (brd->intr_used && brd->irq) - free_irq(brd->irq, brd); -} - -static int dgap_firmware_load(struct pci_dev *pdev, int card_type, - struct board_t *brd) -{ - const struct firmware *fw; - char *tmp_ptr; - int ret; - char *dgap_config_buf; - - dgap_get_vpd(brd); - dgap_do_reset_board(brd); - - if (fw_info[card_type].conf_name) { - ret = request_firmware(&fw, fw_info[card_type].conf_name, - &pdev->dev); - if (ret) { - dev_err(&pdev->dev, "config file %s not found\n", - fw_info[card_type].conf_name); - return ret; - } - - dgap_config_buf = kzalloc(fw->size + 1, GFP_KERNEL); - if (!dgap_config_buf) { - release_firmware(fw); - return -ENOMEM; - } - - memcpy(dgap_config_buf, fw->data, fw->size); - release_firmware(fw); - - /* - * preserve dgap_config_buf - * as dgap_parsefile would - * otherwise alter it. - */ - tmp_ptr = dgap_config_buf; - - if (dgap_parsefile(&tmp_ptr) != 0) { - kfree(dgap_config_buf); - return -EINVAL; - } - kfree(dgap_config_buf); - } - - /* - * Match this board to a config the user created for us. - */ - brd->bd_config = - dgap_find_config(brd->type, brd->pci_bus, brd->pci_slot); - - /* - * Because the 4 port Xr products share the same PCI ID - * as the 8 port Xr products, if we receive a NULL config - * back, and this is a PAPORT8 board, retry with a - * PAPORT4 attempt as well. - */ - if (brd->type == PAPORT8 && !brd->bd_config) - brd->bd_config = - dgap_find_config(PAPORT4, brd->pci_bus, brd->pci_slot); - - if (!brd->bd_config) { - dev_err(&pdev->dev, "No valid configuration found\n"); - return -EINVAL; - } - - if (fw_info[card_type].bios_name) { - ret = request_firmware(&fw, fw_info[card_type].bios_name, - &pdev->dev); - if (ret) { - dev_err(&pdev->dev, "bios file %s not found\n", - fw_info[card_type].bios_name); - return ret; - } - dgap_do_bios_load(brd, fw->data, fw->size); - release_firmware(fw); - - /* Wait for BIOS to test board... */ - ret = dgap_test_bios(brd); - if (ret) - return ret; - } - - if (fw_info[card_type].fep_name) { - ret = request_firmware(&fw, fw_info[card_type].fep_name, - &pdev->dev); - if (ret) { - dev_err(&pdev->dev, "dgap: fep file %s not found\n", - fw_info[card_type].fep_name); - return ret; - } - dgap_do_fep_load(brd, fw->data, fw->size); - release_firmware(fw); - - /* Wait for FEP to load on board... */ - ret = dgap_test_fep(brd); - if (ret) - return ret; - } - -#ifdef DIGI_CONCENTRATORS_SUPPORTED - /* - * If this is a CX or EPCX, we need to see if the firmware - * is requesting a concentrator image from us. - */ - if ((bd->type == PCX) || (bd->type == PEPC)) { - chk_addr = (u16 *)(vaddr + DOWNREQ); - /* Nonzero if FEP is requesting concentrator image. */ - check = readw(chk_addr); - vaddr = brd->re_map_membase; - } - - if (fw_info[card_type].con_name && check && vaddr) { - ret = request_firmware(&fw, fw_info[card_type].con_name, - &pdev->dev); - if (ret) { - dev_err(&pdev->dev, "conc file %s not found\n", - fw_info[card_type].con_name); - return ret; - } - /* Put concentrator firmware loading code here */ - offset = readw((u16 *)(vaddr + DOWNREQ)); - memcpy_toio(offset, fw->data, fw->size); - - dgap_do_conc_load(brd, (char *)fw->data, fw->size) - release_firmware(fw); - } -#endif - - return 0; -} - -/* - * dgap_tty_init() - * - * Init the tty subsystem. Called once per board after board has been - * downloaded and init'ed. - */ -static int dgap_tty_init(struct board_t *brd) -{ - int i; - int tlw; - uint true_count; - u8 __iomem *vaddr; - u8 modem; - struct channel_t *ch; - struct bs_t __iomem *bs; - struct cm_t __iomem *cm; - int ret; - - /* - * Initialize board structure elements. - */ - - vaddr = brd->re_map_membase; - true_count = readw((vaddr + NCHAN)); - - brd->nasync = dgap_config_get_num_prts(brd); - - if (!brd->nasync) - brd->nasync = brd->maxports; - - if (brd->nasync > brd->maxports) - brd->nasync = brd->maxports; - - if (true_count != brd->nasync) { - dev_warn(&brd->pdev->dev, - "%s configured for %d ports, has %d ports.\n", - brd->name, brd->nasync, true_count); - - if ((brd->type == PPCM) && - (true_count == 64 || true_count == 0)) { - dev_warn(&brd->pdev->dev, - "Please make SURE the EBI cable running from the card\n"); - dev_warn(&brd->pdev->dev, - "to each EM module is plugged into EBI IN!\n"); - } - - brd->nasync = true_count; - - /* If no ports, don't bother going any further */ - if (!brd->nasync) { - brd->state = BOARD_FAILED; - brd->dpastatus = BD_NOFEP; - return -EIO; - } - } - - /* - * Allocate channel memory that might not have been allocated - * when the driver was first loaded. - */ - for (i = 0; i < brd->nasync; i++) { - brd->channels[i] = - kzalloc(sizeof(struct channel_t), GFP_KERNEL); - if (!brd->channels[i]) { - ret = -ENOMEM; - goto free_chan; - } - } - - ch = brd->channels[0]; - vaddr = brd->re_map_membase; - - bs = (struct bs_t __iomem *)((ulong)vaddr + CHANBUF); - cm = (struct cm_t __iomem *)((ulong)vaddr + CMDBUF); - - brd->bd_bs = bs; - - /* Set up channel variables */ - for (i = 0; i < brd->nasync; i++, ch = brd->channels[i], bs++) { - spin_lock_init(&ch->ch_lock); - - /* Store all our magic numbers */ - ch->magic = DGAP_CHANNEL_MAGIC; - ch->ch_tun.magic = DGAP_UNIT_MAGIC; - ch->ch_tun.un_type = DGAP_SERIAL; - ch->ch_tun.un_ch = ch; - ch->ch_tun.un_dev = i; - - ch->ch_pun.magic = DGAP_UNIT_MAGIC; - ch->ch_pun.un_type = DGAP_PRINT; - ch->ch_pun.un_ch = ch; - ch->ch_pun.un_dev = i; - - ch->ch_vaddr = vaddr; - ch->ch_bs = bs; - ch->ch_cm = cm; - ch->ch_bd = brd; - ch->ch_portnum = i; - ch->ch_digi = dgap_digi_init; - - /* - * Set up digi dsr and dcd bits based on altpin flag. - */ - if (dgap_config_get_altpin(brd)) { - ch->ch_dsr = DM_CD; - ch->ch_cd = DM_DSR; - ch->ch_digi.digi_flags |= DIGI_ALTPIN; - } else { - ch->ch_cd = DM_CD; - ch->ch_dsr = DM_DSR; - } - - ch->ch_taddr = vaddr + (ioread16(&ch->ch_bs->tx_seg) << 4); - ch->ch_raddr = vaddr + (ioread16(&ch->ch_bs->rx_seg) << 4); - ch->ch_tx_win = 0; - ch->ch_rx_win = 0; - ch->ch_tsize = readw(&ch->ch_bs->tx_max) + 1; - ch->ch_rsize = readw(&ch->ch_bs->rx_max) + 1; - ch->ch_tstart = 0; - ch->ch_rstart = 0; - - /* - * Set queue water marks, interrupt mask, - * and general tty parameters. - */ - tlw = ch->ch_tsize >= 2000 ? ((ch->ch_tsize * 5) / 8) : - ch->ch_tsize / 2; - ch->ch_tlw = tlw; - - dgap_cmdw(ch, STLOW, tlw, 0); - - dgap_cmdw(ch, SRLOW, ch->ch_rsize / 2, 0); - - dgap_cmdw(ch, SRHIGH, 7 * ch->ch_rsize / 8, 0); - - ch->ch_mistat = readb(&ch->ch_bs->m_stat); - - init_waitqueue_head(&ch->ch_flags_wait); - init_waitqueue_head(&ch->ch_tun.un_flags_wait); - init_waitqueue_head(&ch->ch_pun.un_flags_wait); - - /* Turn on all modem interrupts for now */ - modem = (DM_CD | DM_DSR | DM_CTS | DM_RI); - writeb(modem, &ch->ch_bs->m_int); - - /* - * Set edelay to 0 if interrupts are turned on, - * otherwise set edelay to the usual 100. - */ - if (brd->intr_used) - writew(0, &ch->ch_bs->edelay); - else - writew(100, &ch->ch_bs->edelay); - - writeb(1, &ch->ch_bs->idata); - } - - return 0; - -free_chan: - while (--i >= 0) { - kfree(brd->channels[i]); - brd->channels[i] = NULL; - } - return ret; -} - -/* - * dgap_tty_free() - * - * Free the channles which are allocated in dgap_tty_init(). - */ -static void dgap_tty_free(struct board_t *brd) -{ - int i; - - for (i = 0; i < brd->nasync; i++) - kfree(brd->channels[i]); -} - -static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int rc; - struct board_t *brd; - - if (dgap_numboards >= MAXBOARDS) - return -EPERM; - - rc = pci_enable_device(pdev); - if (rc) - return -EIO; - - brd = dgap_found_board(pdev, ent->driver_data, dgap_numboards); - if (IS_ERR(brd)) - return PTR_ERR(brd); - - rc = dgap_firmware_load(pdev, ent->driver_data, brd); - if (rc) - goto cleanup_brd; - - rc = dgap_alloc_flipbuf(brd); - if (rc) - goto cleanup_brd; - - rc = dgap_tty_register(brd); - if (rc) - goto free_flipbuf; - - rc = dgap_request_irq(brd); - if (rc) - goto unregister_tty; - - /* - * Do tty device initialization. - */ - rc = dgap_tty_init(brd); - if (rc < 0) - goto free_irq; - - rc = dgap_tty_register_ports(brd); - if (rc) - goto tty_free; - - brd->state = BOARD_READY; - brd->dpastatus = BD_RUNNING; - - dgap_board[dgap_numboards++] = brd; - - return 0; - -tty_free: - dgap_tty_free(brd); -free_irq: - dgap_free_irq(brd); -unregister_tty: - dgap_tty_unregister(brd); -free_flipbuf: - dgap_free_flipbuf(brd); -cleanup_brd: - dgap_cleanup_nodes(); - dgap_unmap(brd); - kfree(brd); - - return rc; -} - -/* - * dgap_cleanup_board() - * - * Free all the memory associated with a board - */ -static void dgap_cleanup_board(struct board_t *brd) -{ - unsigned int i; - - if (!brd || brd->magic != DGAP_BOARD_MAGIC) - return; - - dgap_free_irq(brd); - - tasklet_kill(&brd->helper_tasklet); - - dgap_unmap(brd); - - /* Free all allocated channels structs */ - for (i = 0; i < MAXPORTS ; i++) - kfree(brd->channels[i]); - - kfree(brd->flipbuf); - kfree(brd->flipflagbuf); - - dgap_board[brd->boardnum] = NULL; - - kfree(brd); -} - -static void dgap_stop(bool removesys, struct pci_driver *drv) -{ - unsigned long lock_flags; - - spin_lock_irqsave(&dgap_poll_lock, lock_flags); - dgap_poll_stop = 1; - spin_unlock_irqrestore(&dgap_poll_lock, lock_flags); - - del_timer_sync(&dgap_poll_timer); - if (removesys) - dgap_remove_driver_sysfiles(drv); - - device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0)); - class_destroy(dgap_class); - unregister_chrdev(DIGI_DGAP_MAJOR, "dgap"); -} - -static void dgap_remove_one(struct pci_dev *dev) -{ - unsigned int i; - struct pci_driver *drv = to_pci_driver(dev->dev.driver); - - dgap_stop(true, drv); - for (i = 0; i < dgap_numboards; ++i) { - dgap_remove_ports_sysfiles(dgap_board[i]); - dgap_cleanup_tty(dgap_board[i]); - dgap_cleanup_board(dgap_board[i]); - } - - dgap_cleanup_nodes(); -} - -static struct pci_driver dgap_driver = { - .name = "dgap", - .probe = dgap_init_one, - .id_table = dgap_pci_tbl, - .remove = dgap_remove_one, -}; - -/* - * Start of driver. - */ -static int dgap_start(void) -{ - int rc; - unsigned long flags; - struct device *device; - - dgap_numboards = 0; - - pr_info("For the tools package please visit http://www.digi.com\n"); - - /* - * Register our base character device into the kernel. - */ - - /* - * Register management/dpa devices - */ - rc = register_chrdev(DIGI_DGAP_MAJOR, "dgap", &dgap_board_fops); - if (rc < 0) - return rc; - - dgap_class = class_create(THIS_MODULE, "dgap_mgmt"); - if (IS_ERR(dgap_class)) { - rc = PTR_ERR(dgap_class); - goto failed_class; - } - - device = device_create(dgap_class, NULL, - MKDEV(DIGI_DGAP_MAJOR, 0), - NULL, "dgap_mgmt"); - if (IS_ERR(device)) { - rc = PTR_ERR(device); - goto failed_device; - } - - /* Start the poller */ - spin_lock_irqsave(&dgap_poll_lock, flags); - setup_timer(&dgap_poll_timer, dgap_poll_handler, 0); - dgap_poll_timer.data = 0; - dgap_poll_time = jiffies + dgap_jiffies_from_ms(dgap_poll_tick); - dgap_poll_timer.expires = dgap_poll_time; - spin_unlock_irqrestore(&dgap_poll_lock, flags); - - add_timer(&dgap_poll_timer); - - return rc; - -failed_device: - class_destroy(dgap_class); -failed_class: - unregister_chrdev(DIGI_DGAP_MAJOR, "dgap"); - return rc; -} - -/************************************************************************ - * - * Driver load/unload functions - * - ************************************************************************/ - -/* - * init_module() - * - * Module load. This is where it all starts. - */ -static int dgap_init_module(void) -{ - int rc; - - pr_info("%s, Digi International Part Number %s\n", DG_NAME, DG_PART); - - rc = dgap_start(); - if (rc) - return rc; - - rc = pci_register_driver(&dgap_driver); - if (rc) { - dgap_stop(false, NULL); - return rc; - } - - rc = dgap_create_driver_sysfiles(&dgap_driver); - if (rc) - goto err_unregister; - - dgap_driver_state = DRIVER_READY; - - return 0; - -err_unregister: - pci_unregister_driver(&dgap_driver); - return rc; -} - -/* - * dgap_cleanup_module() - * - * Module unload. This is where it all ends. - */ -static void dgap_cleanup_module(void) -{ - if (dgap_numboards) - pci_unregister_driver(&dgap_driver); -} - -module_init(dgap_init_module); -module_exit(dgap_cleanup_module); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Digi International, http://www.digi.com"); -MODULE_DESCRIPTION("Driver for the Digi International EPCA PCI based product line"); -MODULE_SUPPORTED_DEVICE("dgap"); diff --git a/drivers/staging/dgap/dgap.h b/drivers/staging/dgap/dgap.h deleted file mode 100644 index c84dbf2a0684..000000000000 --- a/drivers/staging/dgap/dgap.h +++ /dev/null @@ -1,1229 +0,0 @@ -/* - * Copyright 2003 Digi International (www.digi.com) - * Scott H Kilau - * - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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. - * - * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!! - * - ************************************************************************* - * - * Driver includes - * - *************************************************************************/ - -#ifndef __DGAP_DRIVER_H -#define __DGAP_DRIVER_H - -#include /* To pick up the varions Linux types */ -#include /* To pick up the various tty structs/defines */ -#include /* For irqreturn_t type */ - -#ifndef TRUE -# define TRUE 1 -#endif - -#ifndef FALSE -# define FALSE 0 -#endif - -#if !defined(TTY_FLIPBUF_SIZE) -# define TTY_FLIPBUF_SIZE 512 -#endif - -/************************************************************************* - * - * Driver defines - * - *************************************************************************/ - -/* - * Driver identification - */ -#define DG_NAME "dgap-1.3-16" -#define DG_PART "40002347_C" -#define DRVSTR "dgap" - -/* - * defines from dgap_pci.h - */ -#define PCIMAX 32 /* maximum number of PCI boards */ - -#define DIGI_VID 0x114F - -#define PCI_DEV_EPC_DID 0x0002 -#define PCI_DEV_XEM_DID 0x0004 -#define PCI_DEV_XR_DID 0x0005 -#define PCI_DEV_CX_DID 0x0006 -#define PCI_DEV_XRJ_DID 0x0009 /* PLX-based Xr adapter */ -#define PCI_DEV_XR_IBM_DID 0x0011 /* IBM 8-port Async Adapter */ -#define PCI_DEV_XR_BULL_DID 0x0013 /* BULL 8-port Async Adapter */ -#define PCI_DEV_XR_SAIP_DID 0x001c /* SAIP card - Xr adapter */ -#define PCI_DEV_XR_422_DID 0x0012 /* Xr-422 */ -#define PCI_DEV_920_2_DID 0x0034 /* XR-Plus 920 K, 2 port */ -#define PCI_DEV_920_4_DID 0x0026 /* XR-Plus 920 K, 4 port */ -#define PCI_DEV_920_8_DID 0x0027 /* XR-Plus 920 K, 8 port */ -#define PCI_DEV_EPCJ_DID 0x000a /* PLX 9060 chip for PCI */ -#define PCI_DEV_CX_IBM_DID 0x001b /* IBM 128-port Async Adapter */ -#define PCI_DEV_920_8_HP_DID 0x0058 /* HP XR-Plus 920 K, 8 port */ -#define PCI_DEV_XEM_HP_DID 0x0059 /* HP Xem PCI */ - -#define PCI_DEV_XEM_NAME "AccelePort XEM" -#define PCI_DEV_CX_NAME "AccelePort CX" -#define PCI_DEV_XR_NAME "AccelePort Xr" -#define PCI_DEV_XRJ_NAME "AccelePort Xr (PLX)" -#define PCI_DEV_XR_SAIP_NAME "AccelePort Xr (SAIP)" -#define PCI_DEV_920_2_NAME "AccelePort Xr920 2 port" -#define PCI_DEV_920_4_NAME "AccelePort Xr920 4 port" -#define PCI_DEV_920_8_NAME "AccelePort Xr920 8 port" -#define PCI_DEV_XR_422_NAME "AccelePort Xr 422" -#define PCI_DEV_EPCJ_NAME "AccelePort EPC (PLX)" -#define PCI_DEV_XR_BULL_NAME "AccelePort Xr (BULL)" -#define PCI_DEV_XR_IBM_NAME "AccelePort Xr (IBM)" -#define PCI_DEV_CX_IBM_NAME "AccelePort CX (IBM)" -#define PCI_DEV_920_8_HP_NAME "AccelePort Xr920 8 port (HP)" -#define PCI_DEV_XEM_HP_NAME "AccelePort XEM (HP)" - -/* - * On the PCI boards, there is no IO space allocated - * The I/O registers will be in the first 3 bytes of the - * upper 2MB of the 4MB memory space. The board memory - * will be mapped into the low 2MB of the 4MB memory space - */ - -/* Potential location of PCI Bios from E0000 to FFFFF*/ -#define PCI_BIOS_SIZE 0x00020000 - -/* Size of Memory and I/O for PCI (4MB) */ -#define PCI_RAM_SIZE 0x00400000 - -/* Size of Memory (2MB) */ -#define PCI_MEM_SIZE 0x00200000 - -/* Max PCI Window Size (2MB) */ -#define PCI_WIN_SIZE 0x00200000 - -#define PCI_WIN_SHIFT 21 /* 21 bits max */ - -/* Offset of I/0 in Memory (2MB) */ -#define PCI_IO_OFFSET 0x00200000 - -/* Size of IO (2MB) */ -#define PCI_IO_SIZE_DGAP 0x00200000 - -/* Number of boards we support at once. */ -#define MAXBOARDS 32 -#define MAXPORTS 224 -#define MAXTTYNAMELEN 200 - -/* Our 3 magic numbers for our board, channel and unit structs */ -#define DGAP_BOARD_MAGIC 0x5c6df104 -#define DGAP_CHANNEL_MAGIC 0x6c6df104 -#define DGAP_UNIT_MAGIC 0x7c6df104 - -/* Serial port types */ -#define DGAP_SERIAL 0 -#define DGAP_PRINT 1 - -#define SERIAL_TYPE_NORMAL 1 - -/* 4 extra for alignment play space */ -#define WRITEBUFLEN ((4096) + 4) -#define MYFLIPLEN N_TTY_BUF_SIZE - -#define SBREAK_TIME 0x25 -#define U2BSIZE 0x400 - -#define dgap_jiffies_from_ms(a) (((a) * HZ) / 1000) - -/* - * Our major for the mgmt devices. - * - * We can use 22, because Digi was allocated 22 and 23 for the epca driver. - * 22 has now become obsolete now that the "cu" devices have - * been removed from 2.6. - * Also, this *IS* the epca driver, just PCI only now. - */ -#ifndef DIGI_DGAP_MAJOR -# define DIGI_DGAP_MAJOR 22 -#endif - -/* - * The parameters we use to define the periods of the moving averages. - */ -#define MA_PERIOD (HZ / 10) -#define SMA_DUR (1 * HZ) -#define EMA_DUR (1 * HZ) -#define SMA_NPERIODS (SMA_DUR / MA_PERIOD) -#define EMA_NPERIODS (EMA_DUR / MA_PERIOD) - -/* - * Define a local default termios struct. All ports will be created - * with this termios initially. This is the same structure that is defined - * as the default in tty_io.c with the same settings overridden as in serial.c - * - * In short, this should match the internal serial ports' defaults. - */ -#define DEFAULT_IFLAGS (ICRNL | IXON) -#define DEFAULT_OFLAGS (OPOST | ONLCR) -#define DEFAULT_CFLAGS (B9600 | CS8 | CREAD | HUPCL | CLOCAL) -#define DEFAULT_LFLAGS (ISIG | ICANON | ECHO | ECHOE | ECHOK | \ - ECHOCTL | ECHOKE | IEXTEN) - -#ifndef _POSIX_VDISABLE -#define _POSIX_VDISABLE ('\0') -#endif - -#define SNIFF_MAX 65536 /* Sniff buffer size (2^n) */ -#define SNIFF_MASK (SNIFF_MAX - 1) /* Sniff wrap mask */ - -#define VPDSIZE (512) - -/************************************************************************ - * FEP memory offsets - ************************************************************************/ -#define START 0x0004L /* Execution start address */ - -#define CMDBUF 0x0d10L /* Command (cm_t) structure offset */ -#define CMDSTART 0x0400L /* Start of command buffer */ -#define CMDMAX 0x0800L /* End of command buffer */ - -#define EVBUF 0x0d18L /* Event (ev_t) structure */ -#define EVSTART 0x0800L /* Start of event buffer */ -#define EVMAX 0x0c00L /* End of event buffer */ -#define FEP5_PLUS 0x0E40 /* ASCII '5' and ASCII 'A' is here */ -#define ECS_SEG 0x0E44 /* Segment of the extended */ - /* channel structure */ -#define LINE_SPEED 0x10 /* Offset into ECS_SEG for line */ - /* speed if the fep has extended */ - /* capabilities */ - -/* BIOS MAGIC SPOTS */ -#define ERROR 0x0C14L /* BIOS error code */ -#define SEQUENCE 0x0C12L /* BIOS sequence indicator */ -#define POSTAREA 0x0C00L /* POST complete message area */ - -/* FEP MAGIC SPOTS */ -#define FEPSTAT POSTAREA /* OS here when FEP comes up */ -#define NCHAN 0x0C02L /* number of ports FEP sees */ -#define PANIC 0x0C10L /* PANIC area for FEP */ -#define KMEMEM 0x0C30L /* Memory for KME use */ -#define CONFIG 0x0CD0L /* Concentrator configuration info */ -#define CONFIGSIZE 0x0030 /* configuration info size */ -#define DOWNREQ 0x0D00 /* Download request buffer pointer */ - -#define CHANBUF 0x1000L /* Async channel (bs_t) structs */ -#define FEPOSSIZE 0x1FFF /* 8K FEPOS */ - -#define XEMPORTS 0xC02 /* - * Offset in board memory where FEP5 stores - * how many ports it has detected. - * NOTE: FEP5 reports 64 ports when the user - * has the cable in EBI OUT instead of EBI IN. - */ - -#define FEPCLR 0x00 -#define FEPMEM 0x02 -#define FEPRST 0x04 -#define FEPINT 0x08 -#define FEPMASK 0x0e -#define FEPWIN 0x80 - -#define LOWMEM 0x0100 -#define HIGHMEM 0x7f00 - -#define FEPTIMEOUT 200000 - -#define ENABLE_INTR 0x0e04 /* Enable interrupts flag */ -#define FEPPOLL_MIN 1 /* minimum of 1 millisecond */ -#define FEPPOLL_MAX 20 /* maximum of 20 milliseconds */ -#define FEPPOLL 0x0c26 /* Fep event poll interval */ - -#define IALTPIN 0x0080 /* Input flag to swap DSR <-> DCD */ - -/************************************************************************ - * FEP supported functions - ************************************************************************/ -#define SRLOW 0xe0 /* Set receive low water */ -#define SRHIGH 0xe1 /* Set receive high water */ -#define FLUSHTX 0xe2 /* Flush transmit buffer */ -#define PAUSETX 0xe3 /* Pause data transmission */ -#define RESUMETX 0xe4 /* Resume data transmission */ -#define SMINT 0xe5 /* Set Modem Interrupt */ -#define SAFLOWC 0xe6 /* Set Aux. flow control chars */ -#define SBREAK 0xe8 /* Send break */ -#define SMODEM 0xe9 /* Set 8530 modem control lines */ -#define SIFLAG 0xea /* Set UNIX iflags */ -#define SFLOWC 0xeb /* Set flow control characters */ -#define STLOW 0xec /* Set transmit low water mark */ -#define RPAUSE 0xee /* Pause receive */ -#define RRESUME 0xef /* Resume receive */ -#define CHRESET 0xf0 /* Reset Channel */ -#define BUFSETALL 0xf2 /* Set Tx & Rx buffer size avail*/ -#define SOFLAG 0xf3 /* Set UNIX oflags */ -#define SHFLOW 0xf4 /* Set hardware handshake */ -#define SCFLAG 0xf5 /* Set UNIX cflags */ -#define SVNEXT 0xf6 /* Set VNEXT character */ -#define SPINTFC 0xfc /* Reserved */ -#define SCOMMODE 0xfd /* Set RS232/422 mode */ - -/************************************************************************ - * Modes for SCOMMODE - ************************************************************************/ -#define MODE_232 0x00 -#define MODE_422 0x01 - -/************************************************************************ - * Event flags. - ************************************************************************/ -#define IFBREAK 0x01 /* Break received */ -#define IFTLW 0x02 /* Transmit low water */ -#define IFTEM 0x04 /* Transmitter empty */ -#define IFDATA 0x08 /* Receive data present */ -#define IFMODEM 0x20 /* Modem status change */ - -/************************************************************************ - * Modem flags - ************************************************************************/ -# define DM_RTS 0x02 /* Request to send */ -# define DM_CD 0x80 /* Carrier detect */ -# define DM_DSR 0x20 /* Data set ready */ -# define DM_CTS 0x10 /* Clear to send */ -# define DM_RI 0x40 /* Ring indicator */ -# define DM_DTR 0x01 /* Data terminal ready */ - -/* - * defines from dgap_conf.h - */ -#define NULLNODE 0 /* header node, not used */ -#define BNODE 1 /* Board node */ -#define LNODE 2 /* Line node */ -#define CNODE 3 /* Concentrator node */ -#define MNODE 4 /* EBI Module node */ -#define TNODE 5 /* tty name prefix node */ -#define CUNODE 6 /* cu name prefix (non-SCO) */ -#define PNODE 7 /* trans. print prefix node */ -#define JNODE 8 /* maJor number node */ -#define ANODE 9 /* altpin */ -#define TSNODE 10 /* tty structure size */ -#define CSNODE 11 /* channel structure size */ -#define BSNODE 12 /* board structure size */ -#define USNODE 13 /* unit schedule structure size */ -#define FSNODE 14 /* f2200 structure size */ -#define VSNODE 15 /* size of VPIX structures */ -#define INTRNODE 16 /* enable interrupt */ - -/* Enumeration of tokens */ -#define BEGIN 1 -#define END 2 -#define BOARD 10 - -#define EPCFS 11 /* start of EPC family definitions */ -#define ICX 11 -#define MCX 13 -#define PCX 14 -#define IEPC 15 -#define EEPC 16 -#define MEPC 17 -#define IPCM 18 -#define EPCM 19 -#define MPCM 20 -#define PEPC 21 -#define PPCM 22 -#ifdef CP -#define ICP 23 -#define ECP 24 -#define MCP 25 -#endif -#define EPCFE 25 /* end of EPC family definitions */ -#define PC2E 26 -#define PC4E 27 -#define PC4E8K 28 -#define PC8E 29 -#define PC8E8K 30 -#define PC16E 31 -#define MC2E8K 34 -#define MC4E8K 35 -#define MC8E8K 36 - -#define AVANFS 42 /* start of Avanstar family definitions */ -#define A8P 42 -#define A16P 43 -#define AVANFE 43 /* end of Avanstar family definitions */ - -#define DA2000FS 44 /* start of AccelePort 2000 family definitions */ -#define DA22 44 /* AccelePort 2002 */ -#define DA24 45 /* AccelePort 2004 */ -#define DA28 46 /* AccelePort 2008 */ -#define DA216 47 /* AccelePort 2016 */ -#define DAR4 48 /* AccelePort RAS 4 port */ -#define DAR8 49 /* AccelePort RAS 8 port */ -#define DDR24 50 /* DataFire RAS 24 port */ -#define DDR30 51 /* DataFire RAS 30 port */ -#define DDR48 52 /* DataFire RAS 48 port */ -#define DDR60 53 /* DataFire RAS 60 port */ -#define DA2000FE 53 /* end of AccelePort 2000/RAS family definitions */ - -#define PCXRFS 106 /* start of PCXR family definitions */ -#define APORT4 106 -#define APORT8 107 -#define PAPORT4 108 -#define PAPORT8 109 -#define APORT4_920I 110 -#define APORT8_920I 111 -#define APORT4_920P 112 -#define APORT8_920P 113 -#define APORT2_920P 114 -#define PCXRFE 117 /* end of PCXR family definitions */ - -#define LINE 82 -#ifdef T1 -#define T1M 83 -#define E1M 84 -#endif -#define CONC 64 -#define CX 65 -#define EPC 66 -#define MOD 67 -#define PORTS 68 -#define METHOD 69 -#define CUSTOM 70 -#define BASIC 71 -#define STATUS 72 -#define MODEM 73 -/* The following tokens can appear in multiple places */ -#define SPEED 74 -#define NPORTS 75 -#define ID 76 -#define CABLE 77 -#define CONNECT 78 -#define MEM 80 -#define DPSZ 81 - -#define TTYN 90 -#define CU 91 -#define PRINT 92 -#define XPRINT 93 -#define CMAJOR 94 -#define ALTPIN 95 -#define STARTO 96 -#define USEINTR 97 -#define PCIINFO 98 - -#define TTSIZ 100 -#define CHSIZ 101 -#define BSSIZ 102 -#define UNTSIZ 103 -#define F2SIZ 104 -#define VPSIZ 105 - -#define TOTAL_BOARD 2 -#define CURRENT_BRD 4 -#define BOARD_TYPE 6 -#define IO_ADDRESS 8 -#define MEM_ADDRESS 10 - -#define FIELDS_PER_PAGE 18 - -#define TB_FIELD 1 -#define CB_FIELD 3 -#define BT_FIELD 5 -#define IO_FIELD 7 -#define ID_FIELD 8 -#define ME_FIELD 9 -#define TTY_FIELD 11 -#define CU_FIELD 13 -#define PR_FIELD 15 -#define MPR_FIELD 17 - -#define MAX_FIELD 512 - -#define INIT 0 -#define NITEMS 128 -#define MAX_ITEM 512 - -#define DSCRINST 1 -#define DSCRNUM 3 -#define ALTPINQ 5 -#define SSAVE 7 - -#define DSCR "32" -#define ONETONINE "123456789" -#define ALL "1234567890" - -/* - * All the possible states the driver can be while being loaded. - */ -enum { - DRIVER_INITIALIZED = 0, - DRIVER_READY -}; - -/* - * All the possible states the board can be while booting up. - */ -enum { - BOARD_FAILED = 0, - BOARD_READY -}; - -/* - * All the possible states that a requested concentrator image can be in. - */ -enum { - NO_PENDING_CONCENTRATOR_REQUESTS = 0, - NEED_CONCENTRATOR, - REQUESTED_CONCENTRATOR -}; - -/* - * Modem line constants are defined as macros because DSR and - * DCD are swapable using the ditty altpin option. - */ -#define D_CD(ch) ch->ch_cd /* Carrier detect */ -#define D_DSR(ch) ch->ch_dsr /* Data set ready */ -#define D_RTS(ch) DM_RTS /* Request to send */ -#define D_CTS(ch) DM_CTS /* Clear to send */ -#define D_RI(ch) DM_RI /* Ring indicator */ -#define D_DTR(ch) DM_DTR /* Data terminal ready */ - -/************************************************************************* - * - * Structures and closely related defines. - * - *************************************************************************/ - -/* - * A structure to hold a statistics counter. We also - * compute moving averages for this counter. - */ -struct macounter { - u32 cnt; /* Total count */ - ulong accum; /* Acuumulator per period */ - ulong sma; /* Simple moving average */ - ulong ema; /* Exponential moving average */ -}; - -/************************************************************************ - * Device flag definitions for bd_flags. - ************************************************************************/ -#define BD_FEP5PLUS 0x0001 /* Supports FEP5 Plus commands */ -#define BD_HAS_VPD 0x0002 /* Board has VPD info available */ - -/* - * Per-board information - */ -struct board_t { - int magic; /* Board Magic number. */ - int boardnum; /* Board number: 0-3 */ - - int type; /* Type of board */ - char *name; /* Product Name */ - struct pci_dev *pdev; /* Pointer to the pci_dev struct */ - u16 vendor; /* PCI vendor ID */ - u16 device; /* PCI device ID */ - u16 subvendor; /* PCI subsystem vendor ID */ - u16 subdevice; /* PCI subsystem device ID */ - u8 rev; /* PCI revision ID */ - uint pci_bus; /* PCI bus value */ - uint pci_slot; /* PCI slot value */ - u16 maxports; /* MAX ports this board can handle */ - u8 vpd[VPDSIZE]; /* VPD of board, if found */ - u32 bd_flags; /* Board flags */ - - spinlock_t bd_lock; /* Used to protect board */ - - u32 state; /* State of card. */ - wait_queue_head_t state_wait; /* Place to sleep on for state change */ - - struct tasklet_struct helper_tasklet; /* Poll helper tasklet */ - - u32 wait_for_bios; - u32 wait_for_fep; - - struct cnode *bd_config; /* Config of board */ - - u16 nasync; /* Number of ports on card */ - - ulong irq; /* Interrupt request number */ - ulong intr_count; /* Count of interrupts */ - u32 intr_used; /* Non-zero if using interrupts */ - u32 intr_running; /* Non-zero if FEP knows its doing */ - /* interrupts */ - - ulong port; /* Start of base io port of the card */ - ulong port_end; /* End of base io port of the card */ - ulong membase; /* Start of base memory of the card */ - ulong membase_end; /* End of base memory of the card */ - - u8 __iomem *re_map_port; /* Remapped io port of the card */ - u8 __iomem *re_map_membase;/* Remapped memory of the card */ - - u8 inhibit_poller; /* Tells the poller to leave us alone */ - - struct channel_t *channels[MAXPORTS]; /* array of pointers to our */ - /* channels. */ - - struct tty_driver *serial_driver; - struct tty_port *serial_ports; - char serial_name[200]; - struct tty_driver *print_driver; - struct tty_port *printer_ports; - char print_name[200]; - - struct bs_t __iomem *bd_bs; /* Base structure pointer */ - - char *flipbuf; /* Our flip buffer, alloced if */ - /* board is found */ - char *flipflagbuf; /* Our flip flag buffer, alloced */ - /* if board is found */ - - u16 dpatype; /* The board "type", as defined */ - /* by DPA */ - u16 dpastatus; /* The board "status", as defined */ - /* by DPA */ - - u32 conc_dl_status; /* Status of any pending conc */ - /* download */ -}; - -/************************************************************************ - * Unit flag definitions for un_flags. - ************************************************************************/ -#define UN_ISOPEN 0x0001 /* Device is open */ -#define UN_CLOSING 0x0002 /* Line is being closed */ -#define UN_IMM 0x0004 /* Service immediately */ -#define UN_BUSY 0x0008 /* Some work this channel */ -#define UN_BREAKI 0x0010 /* Input break received */ -#define UN_PWAIT 0x0020 /* Printer waiting for terminal */ -#define UN_TIME 0x0040 /* Waiting on time */ -#define UN_EMPTY 0x0080 /* Waiting output queue empty */ -#define UN_LOW 0x0100 /* Waiting output low water mark*/ -#define UN_EXCL_OPEN 0x0200 /* Open for exclusive use */ -#define UN_WOPEN 0x0400 /* Device waiting for open */ -#define UN_WIOCTL 0x0800 /* Device waiting for open */ -#define UN_HANGUP 0x8000 /* Carrier lost */ - -struct device; - -/************************************************************************ - * Structure for terminal or printer unit. - ************************************************************************/ -struct un_t { - int magic; /* Unit Magic Number. */ - struct channel_t *un_ch; - u32 un_time; - u32 un_type; - int un_open_count; /* Counter of opens to port */ - struct tty_struct *un_tty;/* Pointer to unit tty structure */ - u32 un_flags; /* Unit flags */ - wait_queue_head_t un_flags_wait; /* Place to sleep to wait on unit */ - u32 un_dev; /* Minor device number */ - tcflag_t un_oflag; /* oflags being done on board */ - tcflag_t un_lflag; /* lflags being done on board */ - struct device *un_sysfs; -}; - -/************************************************************************ - * Device flag definitions for ch_flags. - ************************************************************************/ -#define CH_PRON 0x0001 /* Printer on string */ -#define CH_OUT 0x0002 /* Dial-out device open */ -#define CH_STOP 0x0004 /* Output is stopped */ -#define CH_STOPI 0x0008 /* Input is stopped */ -#define CH_CD 0x0010 /* Carrier is present */ -#define CH_FCAR 0x0020 /* Carrier forced on */ - -#define CH_RXBLOCK 0x0080 /* Enable rx blocked flag */ -#define CH_WLOW 0x0100 /* Term waiting low event */ -#define CH_WEMPTY 0x0200 /* Term waiting empty event */ -#define CH_RENABLE 0x0400 /* Buffer just emptied */ -#define CH_RACTIVE 0x0800 /* Process active in xxread() */ -#define CH_RWAIT 0x1000 /* Process waiting in xxread() */ -#define CH_BAUD0 0x2000 /* Used for checking B0 transitions */ -#define CH_HANGUP 0x8000 /* Hangup received */ - -/* - * Definitions for ch_sniff_flags - */ -#define SNIFF_OPEN 0x1 -#define SNIFF_WAIT_DATA 0x2 -#define SNIFF_WAIT_SPACE 0x4 - -/************************************************************************ - *** Definitions for Digi ditty(1) command. - ************************************************************************/ - -/************************************************************************ - * This module provides application access to special Digi - * serial line enhancements which are not standard UNIX(tm) features. - ************************************************************************/ - -#if !defined(TIOCMODG) - -#define TIOCMODG (('d'<<8) | 250) /* get modem ctrl state */ -#define TIOCMODS (('d'<<8) | 251) /* set modem ctrl state */ - -#ifndef TIOCM_LE -#define TIOCM_LE 0x01 /* line enable */ -#define TIOCM_DTR 0x02 /* data terminal ready */ -#define TIOCM_RTS 0x04 /* request to send */ -#define TIOCM_ST 0x08 /* secondary transmit */ -#define TIOCM_SR 0x10 /* secondary receive */ -#define TIOCM_CTS 0x20 /* clear to send */ -#define TIOCM_CAR 0x40 /* carrier detect */ -#define TIOCM_RNG 0x80 /* ring indicator */ -#define TIOCM_DSR 0x100 /* data set ready */ -#define TIOCM_RI TIOCM_RNG /* ring (alternate) */ -#define TIOCM_CD TIOCM_CAR /* carrier detect (alt) */ -#endif - -#endif - -#if !defined(TIOCMSET) -#define TIOCMSET (('d'<<8) | 252) /* set modem ctrl state */ -#define TIOCMGET (('d'<<8) | 253) /* set modem ctrl state */ -#endif - -#if !defined(TIOCMBIC) -#define TIOCMBIC (('d'<<8) | 254) /* set modem ctrl state */ -#define TIOCMBIS (('d'<<8) | 255) /* set modem ctrl state */ -#endif - -#if !defined(TIOCSDTR) -#define TIOCSDTR (('e'<<8) | 0) /* set DTR */ -#define TIOCCDTR (('e'<<8) | 1) /* clear DTR */ -#endif - -/************************************************************************ - * Ioctl command arguments for DIGI parameters. - ************************************************************************/ -#define DIGI_GETA (('e'<<8) | 94) /* Read params */ - -#define DIGI_SETA (('e'<<8) | 95) /* Set params */ -#define DIGI_SETAW (('e'<<8) | 96) /* Drain & set params */ -#define DIGI_SETAF (('e'<<8) | 97) /* Drain, flush & set params */ - -#define DIGI_KME (('e'<<8) | 98) /* Read/Write Host */ - /* Adapter Memory */ - -#define DIGI_GETFLOW (('e'<<8) | 99) /* Get startc/stopc flow */ - /* control characters */ -#define DIGI_SETFLOW (('e'<<8) | 100) /* Set startc/stopc flow */ - /* control characters */ -#define DIGI_GETAFLOW (('e'<<8) | 101) /* Get Aux. startc/stopc */ - /* flow control chars */ -#define DIGI_SETAFLOW (('e'<<8) | 102) /* Set Aux. startc/stopc */ - /* flow control chars */ - -#define DIGI_GEDELAY (('d'<<8) | 246) /* Get edelay */ -#define DIGI_SEDELAY (('d'<<8) | 247) /* Set edelay */ - -struct digiflow_t { - unsigned char startc; /* flow cntl start char */ - unsigned char stopc; /* flow cntl stop char */ -}; - -#ifdef FLOW_2200 -#define F2200_GETA (('e'<<8) | 104) /* Get 2x36 flow cntl flags */ -#define F2200_SETAW (('e'<<8) | 105) /* Set 2x36 flow cntl flags */ -#define F2200_MASK 0x03 /* 2200 flow cntl bit mask */ -#define FCNTL_2200 0x01 /* 2x36 terminal flow cntl */ -#define PCNTL_2200 0x02 /* 2x36 printer flow cntl */ -#define F2200_XON 0xf8 -#define P2200_XON 0xf9 -#define F2200_XOFF 0xfa -#define P2200_XOFF 0xfb - -#define FXOFF_MASK 0x03 /* 2200 flow status mask */ -#define RCVD_FXOFF 0x01 /* 2x36 Terminal XOFF rcvd */ -#define RCVD_PXOFF 0x02 /* 2x36 Printer XOFF rcvd */ -#endif - -/************************************************************************ - * Values for digi_flags - ************************************************************************/ -#define DIGI_IXON 0x0001 /* Handle IXON in the FEP */ -#define DIGI_FAST 0x0002 /* Fast baud rates */ -#define RTSPACE 0x0004 /* RTS input flow control */ -#define CTSPACE 0x0008 /* CTS output flow control */ -#define DSRPACE 0x0010 /* DSR output flow control */ -#define DCDPACE 0x0020 /* DCD output flow control */ -#define DTRPACE 0x0040 /* DTR input flow control */ -#define DIGI_COOK 0x0080 /* Cooked processing done in FEP */ -#define DIGI_FORCEDCD 0x0100 /* Force carrier */ -#define DIGI_ALTPIN 0x0200 /* Alternate RJ-45 pin config */ -#define DIGI_AIXON 0x0400 /* Aux flow control in fep */ -#define DIGI_PRINTER 0x0800 /* Hold port open for flow cntrl*/ -#define DIGI_PP_INPUT 0x1000 /* Change parallel port to input*/ -#define DIGI_DTR_TOGGLE 0x2000 /* Support DTR Toggle */ -#define DIGI_422 0x4000 /* for 422/232 selectable panel */ -#define DIGI_RTS_TOGGLE 0x8000 /* Support RTS Toggle */ - -/************************************************************************ - * These options are not supported on the comxi. - ************************************************************************/ -#define DIGI_COMXI (DIGI_FAST|DIGI_COOK|DSRPACE|DCDPACE|DTRPACE) - -#define DIGI_PLEN 28 /* String length */ -#define DIGI_TSIZ 10 /* Terminal string len */ - -/************************************************************************ - * Structure used with ioctl commands for DIGI parameters. - ************************************************************************/ -struct digi_t { - unsigned short digi_flags; /* Flags (see above) */ - unsigned short digi_maxcps; /* Max printer CPS */ - unsigned short digi_maxchar; /* Max chars in print queue */ - unsigned short digi_bufsize; /* Buffer size */ - unsigned char digi_onlen; /* Length of ON string */ - unsigned char digi_offlen; /* Length of OFF string */ - char digi_onstr[DIGI_PLEN]; /* Printer on string */ - char digi_offstr[DIGI_PLEN]; /* Printer off string */ - char digi_term[DIGI_TSIZ]; /* terminal string */ -}; - -/************************************************************************ - * KME definitions and structures. - ************************************************************************/ -#define RW_IDLE 0 /* Operation complete */ -#define RW_READ 1 /* Read Concentrator Memory */ -#define RW_WRITE 2 /* Write Concentrator Memory */ - -struct rw_t { - unsigned char rw_req; /* Request type */ - unsigned char rw_board; /* Host Adapter board number */ - unsigned char rw_conc; /* Concentrator number */ - unsigned char rw_reserved; /* Reserved for expansion */ - unsigned long rw_addr; /* Address in concentrator */ - unsigned short rw_size; /* Read/write request length */ - unsigned char rw_data[128]; /* Data to read/write */ -}; - -/************************************************************************ - * Structure to get driver status information - ************************************************************************/ -struct digi_dinfo { - unsigned long dinfo_nboards; /* # boards configured */ - char dinfo_reserved[12]; /* for future expansion */ - char dinfo_version[16]; /* driver version */ -}; - -#define DIGI_GETDD (('d'<<8) | 248) /* get driver info */ - -/************************************************************************ - * Structure used with ioctl commands for per-board information - * - * physsize and memsize differ when board has "windowed" memory - ************************************************************************/ -struct digi_info { - unsigned long info_bdnum; /* Board number (0 based) */ - unsigned long info_ioport; /* io port address */ - unsigned long info_physaddr; /* memory address */ - unsigned long info_physsize; /* Size of host mem window */ - unsigned long info_memsize; /* Amount of dual-port mem */ - /* on board */ - unsigned short info_bdtype; /* Board type */ - unsigned short info_nports; /* number of ports */ - char info_bdstate; /* board state */ - char info_reserved[7]; /* for future expansion */ -}; - -#define DIGI_GETBD (('d'<<8) | 249) /* get board info */ - -struct digi_stat { - unsigned int info_chan; /* Channel number (0 based) */ - unsigned int info_brd; /* Board number (0 based) */ - unsigned long info_cflag; /* cflag for channel */ - unsigned long info_iflag; /* iflag for channel */ - unsigned long info_oflag; /* oflag for channel */ - unsigned long info_mstat; /* mstat for channel */ - unsigned long info_tx_data; /* tx_data for channel */ - unsigned long info_rx_data; /* rx_data for channel */ - unsigned long info_hflow; /* hflow for channel */ - unsigned long info_reserved[8]; /* for future expansion */ -}; - -#define DIGI_GETSTAT (('d'<<8) | 244) /* get board info */ -/************************************************************************ - * - * Structure used with ioctl commands for per-channel information - * - ************************************************************************/ -struct digi_ch { - unsigned long info_bdnum; /* Board number (0 based) */ - unsigned long info_channel; /* Channel index number */ - unsigned long info_ch_cflag; /* Channel cflag */ - unsigned long info_ch_iflag; /* Channel iflag */ - unsigned long info_ch_oflag; /* Channel oflag */ - unsigned long info_chsize; /* Channel structure size */ - unsigned long info_sleep_stat; /* sleep status */ - dev_t info_dev; /* device number */ - unsigned char info_initstate; /* Channel init state */ - unsigned char info_running; /* Channel running state */ - long reserved[8]; /* reserved for future use */ -}; - -/* -* This structure is used with the DIGI_FEPCMD ioctl to -* tell the driver which port to send the command for. -*/ -struct digi_cmd { - int cmd; - int word; - int ncmds; - int chan; /* channel index (zero based) */ - int bdid; /* board index (zero based) */ -}; - -/* -* info_sleep_stat defines -*/ -#define INFO_RUNWAIT 0x0001 -#define INFO_WOPEN 0x0002 -#define INFO_TTIOW 0x0004 -#define INFO_CH_RWAIT 0x0008 -#define INFO_CH_WEMPTY 0x0010 -#define INFO_CH_WLOW 0x0020 -#define INFO_XXBUF_BUSY 0x0040 - -#define DIGI_GETCH (('d'<<8) | 245) /* get board info */ - -/* Board type definitions */ - -#define SUBTYPE 0007 -#define T_PCXI 0000 -#define T_PCXM 0001 -#define T_PCXE 0002 -#define T_PCXR 0003 -#define T_SP 0004 -#define T_SP_PLUS 0005 -# define T_HERC 0000 -# define T_HOU 0001 -# define T_LON 0002 -# define T_CHA 0003 -#define FAMILY 0070 -#define T_COMXI 0000 -#define T_PCXX 0010 -#define T_CX 0020 -#define T_EPC 0030 -#define T_PCLITE 0040 -#define T_SPXX 0050 -#define T_AVXX 0060 -#define T_DXB 0070 -#define T_A2K_4_8 0070 -#define BUSTYPE 0700 -#define T_ISABUS 0000 -#define T_MCBUS 0100 -#define T_EISABUS 0200 -#define T_PCIBUS 0400 - -/* Board State Definitions */ - -#define BD_RUNNING 0x0 -#define BD_REASON 0x7f -#define BD_NOTFOUND 0x1 -#define BD_NOIOPORT 0x2 -#define BD_NOMEM 0x3 -#define BD_NOBIOS 0x4 -#define BD_NOFEP 0x5 -#define BD_FAILED 0x6 -#define BD_ALLOCATED 0x7 -#define BD_TRIBOOT 0x8 -#define BD_BADKME 0x80 - -#define DIGI_LOOPBACK (('d'<<8) | 252) /* Enable/disable UART */ - /* internal loopback */ -#define DIGI_SPOLL (('d'<<8) | 254) /* change poller rate */ - -#define DIGI_SETCUSTOMBAUD _IOW('e', 106, int) /* Set integer baud rate */ -#define DIGI_GETCUSTOMBAUD _IOR('e', 107, int) /* Get integer baud rate */ -#define DIGI_RESET_PORT (('e'<<8) | 93) /* Reset port */ - -/************************************************************************ - * Channel information structure. - ************************************************************************/ -struct channel_t { - int magic; /* Channel Magic Number */ - struct bs_t __iomem *ch_bs; /* Base structure pointer */ - struct cm_t __iomem *ch_cm; /* Command queue pointer */ - struct board_t *ch_bd; /* Board structure pointer */ - u8 __iomem *ch_vaddr; /* FEP memory origin */ - u8 __iomem *ch_taddr; /* Write buffer origin */ - u8 __iomem *ch_raddr; /* Read buffer origin */ - struct digi_t ch_digi; /* Transparent Print structure */ - struct un_t ch_tun; /* Terminal unit info */ - struct un_t ch_pun; /* Printer unit info */ - - spinlock_t ch_lock; /* provide for serialization */ - wait_queue_head_t ch_flags_wait; - - u32 pscan_state; - u8 pscan_savechar; - - u32 ch_portnum; /* Port number, 0 offset. */ - u32 ch_open_count; /* open count */ - u32 ch_flags; /* Channel flags */ - - u32 ch_cpstime; /* Time for CPS calculations */ - - tcflag_t ch_c_iflag; /* channel iflags */ - tcflag_t ch_c_cflag; /* channel cflags */ - tcflag_t ch_c_oflag; /* channel oflags */ - tcflag_t ch_c_lflag; /* channel lflags */ - - u16 ch_fepiflag; /* FEP tty iflags */ - u16 ch_fepcflag; /* FEP tty cflags */ - u16 ch_fepoflag; /* FEP tty oflags */ - u16 ch_wopen; /* Waiting for open process cnt */ - u16 ch_tstart; /* Transmit buffer start */ - u16 ch_tsize; /* Transmit buffer size */ - u16 ch_rstart; /* Receive buffer start */ - u16 ch_rsize; /* Receive buffer size */ - u16 ch_rdelay; /* Receive delay time */ - - u16 ch_tlw; /* Our currently set low water mark */ - - u16 ch_cook; /* Output character mask */ - - u8 ch_card; /* Card channel is on */ - u8 ch_stopc; /* Stop character */ - u8 ch_startc; /* Start character */ - - u8 ch_mostat; /* FEP output modem status */ - u8 ch_mistat; /* FEP input modem status */ - u8 ch_mforce; /* Modem values to be forced */ - u8 ch_mval; /* Force values */ - u8 ch_fepstopc; /* FEP stop character */ - u8 ch_fepstartc; /* FEP start character */ - - u8 ch_astopc; /* Auxiliary Stop character */ - u8 ch_astartc; /* Auxiliary Start character */ - u8 ch_fepastopc; /* Auxiliary FEP stop char */ - u8 ch_fepastartc; /* Auxiliary FEP start char */ - - u8 ch_hflow; /* FEP hardware handshake */ - u8 ch_dsr; /* stores real dsr value */ - u8 ch_cd; /* stores real cd value */ - u8 ch_tx_win; /* channel tx buffer window */ - u8 ch_rx_win; /* channel rx buffer window */ - uint ch_custom_speed; /* Custom baud, if set */ - uint ch_baud_info; /* Current baud info for /proc output */ - ulong ch_rxcount; /* total of data received so far */ - ulong ch_txcount; /* total of data transmitted so far */ - ulong ch_err_parity; /* Count of parity errors on channel */ - ulong ch_err_frame; /* Count of framing errors on channel */ - ulong ch_err_break; /* Count of breaks on channel */ - ulong ch_err_overrun; /* Count of overruns on channel */ -}; - -/************************************************************************ - * Command structure definition. - ************************************************************************/ -struct cm_t { - unsigned short cm_head; /* Command buffer head offset */ - unsigned short cm_tail; /* Command buffer tail offset */ - unsigned short cm_start; /* start offset of buffer */ - unsigned short cm_max; /* last offset of buffer */ -}; - -/************************************************************************ - * Event structure definition. - ************************************************************************/ -struct ev_t { - unsigned short ev_head; /* Command buffer head offset */ - unsigned short ev_tail; /* Command buffer tail offset */ - unsigned short ev_start; /* start offset of buffer */ - unsigned short ev_max; /* last offset of buffer */ -}; - -/************************************************************************ - * Download buffer structure. - ************************************************************************/ -struct downld_t { - u8 dl_type; /* Header */ - u8 dl_seq; /* Download sequence */ - ushort dl_srev; /* Software revision number */ - ushort dl_lrev; /* Low revision number */ - ushort dl_hrev; /* High revision number */ - ushort dl_seg; /* Start segment address */ - ushort dl_size; /* Number of bytes to download */ - u8 dl_data[1024]; /* Download data */ -}; - -/************************************************************************ - * Per channel buffer structure - ************************************************************************ - * Base Structure Entries Usage Meanings to Host * - * * - * W = read write R = read only * - * C = changed by commands only * - * U = unknown (may be changed w/o notice) * - ************************************************************************/ -struct bs_t { - unsigned short tp_jmp; /* Transmit poll jump */ - unsigned short tc_jmp; /* Cooked procedure jump */ - unsigned short ri_jmp; /* Not currently used */ - unsigned short rp_jmp; /* Receive poll jump */ - - unsigned short tx_seg; /* W Tx segment */ - unsigned short tx_head; /* W Tx buffer head offset */ - unsigned short tx_tail; /* R Tx buffer tail offset */ - unsigned short tx_max; /* W Tx buffer size - 1 */ - - unsigned short rx_seg; /* W Rx segment */ - unsigned short rx_head; /* W Rx buffer head offset */ - unsigned short rx_tail; /* R Rx buffer tail offset */ - unsigned short rx_max; /* W Rx buffer size - 1 */ - - unsigned short tx_lw; /* W Tx buffer low water mark */ - unsigned short rx_lw; /* W Rx buffer low water mark */ - unsigned short rx_hw; /* W Rx buffer high water mark*/ - unsigned short incr; /* W Increment to next channel*/ - - unsigned short fepdev; /* U SCC device base address */ - unsigned short edelay; /* W Exception delay */ - unsigned short blen; /* W Break length */ - unsigned short btime; /* U Break complete time */ - - unsigned short iflag; /* C UNIX input flags */ - unsigned short oflag; /* C UNIX output flags */ - unsigned short cflag; /* C UNIX control flags */ - unsigned short wfill[13]; /* U Reserved for expansion */ - - unsigned char num; /* U Channel number */ - unsigned char ract; /* U Receiver active counter */ - unsigned char bstat; /* U Break status bits */ - unsigned char tbusy; /* W Transmit busy */ - unsigned char iempty; /* W Transmit empty event */ - /* enable */ - unsigned char ilow; /* W Transmit low-water event */ - /* enable */ - unsigned char idata; /* W Receive data interrupt */ - /* enable */ - unsigned char eflag; /* U Host event flags */ - - unsigned char tflag; /* U Transmit flags */ - unsigned char rflag; /* U Receive flags */ - unsigned char xmask; /* U Transmit ready flags */ - unsigned char xval; /* U Transmit ready value */ - unsigned char m_stat; /* RC Modem status bits */ - unsigned char m_change; /* U Modem bits which changed */ - unsigned char m_int; /* W Modem interrupt enable */ - /* bits */ - unsigned char m_last; /* U Last modem status */ - - unsigned char mtran; /* C Unreported modem trans */ - unsigned char orun; /* C Buffer overrun occurred */ - unsigned char astartc; /* W Auxiliary Xon char */ - unsigned char astopc; /* W Auxiliary Xoff char */ - unsigned char startc; /* W Xon character */ - unsigned char stopc; /* W Xoff character */ - unsigned char vnextc; /* W Vnext character */ - unsigned char hflow; /* C Software flow control */ - - unsigned char fillc; /* U Delay Fill character */ - unsigned char ochar; /* U Saved output character */ - unsigned char omask; /* U Output character mask */ - - unsigned char bfill[13]; /* U Reserved for expansion */ - - unsigned char scc[16]; /* U SCC registers */ -}; - -struct cnode { - struct cnode *next; - int type; - int numbrd; - - union { - struct { - char type; /* Board Type */ - long addr; /* Memory Address */ - char *addrstr; /* Memory Address in string */ - long pcibus; /* PCI BUS */ - char *pcibusstr; /* PCI BUS in string */ - long pcislot; /* PCI SLOT */ - char *pcislotstr; /* PCI SLOT in string */ - long nport; /* Number of Ports */ - char *id; /* tty id */ - long start; /* start of tty counting */ - char *method; /* Install method */ - char v_addr; - char v_pcibus; - char v_pcislot; - char v_nport; - char v_id; - char v_start; - char v_method; - char line1; - char line2; - char conc1; /* total concs in line1 */ - char conc2; /* total concs in line2 */ - char module1; /* total modules for line1 */ - char module2; /* total modules for line2 */ - char *status; /* config status */ - char *dimstatus; /* Y/N */ - int status_index; /* field pointer */ - } board; - - struct { - char *cable; - char v_cable; - long speed; - char v_speed; - } line; - - struct { - char type; - char *connect; - long speed; - long nport; - char *id; - char *idstr; - long start; - char v_connect; - char v_speed; - char v_nport; - char v_id; - char v_start; - } conc; - - struct { - char type; - long nport; - char *id; - char *idstr; - long start; - char v_nport; - char v_id; - char v_start; - } module; - - char *ttyname; - char *cuname; - char *printname; - long majornumber; - long altpin; - long ttysize; - long chsize; - long bssize; - long unsize; - long f2size; - long vpixsize; - long useintr; - } u; -}; -#endif -- cgit v1.2.3 From 428398e44a2762875c01a4d5c18932f1e84fdc17 Mon Sep 17 00:00:00 2001 From: Andreas Ziegler Date: Mon, 25 Jan 2016 12:41:19 +0100 Subject: drm/i915: Remove select to deleted STOP_MACHINE from Kconfig Commit 5bab6f60cb4d ("drm/i915: Serialise updates to GGTT with access through GGTT on Braswell") depended upon a working stop_machine() and so forced the selection of STOP_MACHINE. However, commit 86fffe4a61dd ("kernel: remove stop_machine() Kconfig dependency") removed the option STOP_MACHINE from init/Kconfig and ensured that stop_machine() universally works. Due to the order in which the patches were applied, removing the select from DRM_I915 got lost during merging. Remove the now obsolete select statement. Signed-off-by: Andreas Ziegler Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1453722079-2604-1-git-send-email-andreas.ziegler@fau.de Cc: drm-intel-fixes@lists.freedesktop.org Signed-off-by: Daniel Vetter (cherry picked from commit 21fabbebff0e17c7698ed399cae23958c214cc82) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index fcd77b27514d..051eab33e4c7 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -10,7 +10,6 @@ config DRM_I915 # the shmem_readpage() which depends upon tmpfs select SHMEM select TMPFS - select STOP_MACHINE select DRM_KMS_HELPER select DRM_PANEL select DRM_MIPI_DSI -- cgit v1.2.3 From f2e305108faba0c85eb4ba4066599decb675117e Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 25 Jan 2016 12:02:28 +0100 Subject: drm/i915: refine qemu south bridge detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test for the qemu q35 south bridge added by commit "39bfcd52 drm/i915: more virtual south bridge detection" also matches on real hardware. Having the check for virtual systems last in the list is not enough to avoid that ... Refine the check by additionally verifying the pci subsystem id to see whenever it *really* is qemu. [ v2: fix subvendor tyops ] Reported-and-tested-by: Bjørn Mork Signed-off-by: Gerd Hoffmann Tested-by: Bruno Wolff III Cc: drm-intel-fixes@lists.freedesktop.org Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1453719748-10944-1-git-send-email-kraxel@redhat.com (cherry picked from commit 1e859111c128265f8d62b39ff322e42b1ddb5a20) --- drivers/gpu/drm/i915/i915_drv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3ac616d7363b..f357058c74d9 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -501,7 +501,9 @@ void intel_detect_pch(struct drm_device *dev) WARN_ON(!IS_SKYLAKE(dev) && !IS_KABYLAKE(dev)); } else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) || - (id == INTEL_PCH_QEMU_DEVICE_ID_TYPE)) { + ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) && + pch->subsystem_vendor == 0x1af4 && + pch->subsystem_device == 0x1100)) { dev_priv->pch_type = intel_virt_detect_pch(dev); } else continue; -- cgit v1.2.3 From bd2f348db5033b88b8b81caf58e7bdabf0b6961d Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Wed, 6 Jan 2016 14:04:13 +0000 Subject: goldfish: refactor goldfish platform configs On new virtual devices, the goldfish virtual bus can be replaced with autoprobing infrastructure like Device Tree. Refactor the goldfish kernel configs to better accommodate this. Move the goldfish platform into a menuconfig in the style of the chrome platform, and separate the goldfish bus into its own config option. Signed-off-by: Greg Hackmann Signed-off-by: Jin Qian [Corrected a tristate to bool] Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/Kconfig | 3 +-- drivers/platform/goldfish/Kconfig | 18 ++++++++++++++++++ drivers/platform/goldfish/Makefile | 2 +- 3 files changed, 20 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig index 0adccbf5c83f..c11db8bceea1 100644 --- a/drivers/platform/Kconfig +++ b/drivers/platform/Kconfig @@ -4,8 +4,7 @@ endif if MIPS source "drivers/platform/mips/Kconfig" endif -if GOLDFISH + source "drivers/platform/goldfish/Kconfig" -endif source "drivers/platform/chrome/Kconfig" diff --git a/drivers/platform/goldfish/Kconfig b/drivers/platform/goldfish/Kconfig index 635ef25cc722..2be762743592 100644 --- a/drivers/platform/goldfish/Kconfig +++ b/drivers/platform/goldfish/Kconfig @@ -1,5 +1,23 @@ +menuconfig GOLDFISH + bool "Platform support for Goldfish virtual devices" + depends on X86_32 || X86_64 || ARM || ARM64 + ---help--- + Say Y here to get to see options for the Goldfish virtual platform. + This option alone does not add any kernel code. + + Unless you are building for the Android Goldfish emulator say N here. + +if GOLDFISH + +config GOLDFISH_BUS + bool "Goldfish platform bus" + ---help--- + This is a virtual bus to host Goldfish Android Virtual Devices. + config GOLDFISH_PIPE tristate "Goldfish virtual device for QEMU pipes" ---help--- This is a virtual device to drive the QEMU pipe interface used by the Goldfish Android Virtual Device. + +endif # GOLDFISH diff --git a/drivers/platform/goldfish/Makefile b/drivers/platform/goldfish/Makefile index a0022395eee9..d3487125838c 100644 --- a/drivers/platform/goldfish/Makefile +++ b/drivers/platform/goldfish/Makefile @@ -1,5 +1,5 @@ # # Makefile for Goldfish platform specific drivers # -obj-$(CONFIG_GOLDFISH) += pdev_bus.o +obj-$(CONFIG_GOLDFISH_BUS) += pdev_bus.o obj-$(CONFIG_GOLDFISH_PIPE) += goldfish_pipe.o -- cgit v1.2.3 From 23c5ee21c46ba694681e2378e64a475b5c68f02c Mon Sep 17 00:00:00 2001 From: Alex Bennée Date: Wed, 6 Jan 2016 14:04:31 +0000 Subject: goldfish_pipe: don't be clever with #define offsets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It just makes it harder to figure out which commands are being used. Signed-off-by: Alex Bennée Signed-off-by: Jin Qian Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index e7a29e2750c6..0fb3a34f5991 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -90,12 +90,6 @@ #define CMD_WRITE_BUFFER 4 /* send a user buffer to the emulator */ #define CMD_WAKE_ON_WRITE 5 /* tell the emulator to wake us when writing is possible */ - -/* The following commands are related to read operations, they must be - * listed in the same order than the corresponding write ones, since we - * will use (CMD_READ_BUFFER - CMD_WRITE_BUFFER) as a special offset - * in goldfish_pipe_read_write() below. - */ #define CMD_READ_BUFFER 6 /* receive a user buffer from the emulator */ #define CMD_WAKE_ON_READ 7 /* tell the emulator to wake us when reading * is possible */ @@ -272,8 +266,6 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, unsigned long irq_flags; struct goldfish_pipe *pipe = filp->private_data; struct goldfish_pipe_dev *dev = pipe->dev; - const int cmd_offset = is_write ? 0 - : (CMD_READ_BUFFER - CMD_WRITE_BUFFER); unsigned long address, address_end; int ret = 0; @@ -325,7 +317,8 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, /* Now, try to transfer the bytes in the current page */ spin_lock_irqsave(&dev->lock, irq_flags); - if (access_with_param(dev, CMD_WRITE_BUFFER + cmd_offset, + if (access_with_param(dev, + is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER, address, avail, pipe, &status)) { gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, dev->base + PIPE_REG_CHANNEL_HIGH); @@ -333,7 +326,7 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, gf_write_ptr((void *)address, dev->base + PIPE_REG_ADDRESS, dev->base + PIPE_REG_ADDRESS_HIGH); - writel(CMD_WRITE_BUFFER + cmd_offset, + writel(is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER, dev->base + PIPE_REG_COMMAND); status = readl(dev->base + PIPE_REG_STATUS); } @@ -370,7 +363,8 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, set_bit(wakeBit, &pipe->flags); /* Tell the emulator we're going to wait for a wake event */ - goldfish_cmd(pipe, CMD_WAKE_ON_WRITE + cmd_offset); + goldfish_cmd(pipe, + is_write ? CMD_WAKE_ON_WRITE : CMD_WAKE_ON_READ); /* Unlock the pipe, then wait for the wake signal */ mutex_unlock(&pipe->lock); -- cgit v1.2.3 From 2f3be88237a301ab83b8ba4a0fdf0381bbb3f6ac Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Wed, 6 Jan 2016 14:05:15 +0000 Subject: goldfish_pipe: Pin pages to memory while copying and other cleanups The existing code had a troubling TODO statement concerning the fact that it just did a check if the page that the QEMU backend was going to read from / write to was there before the call to the QEMU backend and then relying on the fact that the page stayed around, even in a preemptible SMP kernel. Obviously the page could go away or be reassigned, and strange things may happen. Further, writes were not tracked, so any use of COW or KSM-like features would break completely. Probably that was never used by adbd (the only current active user of the pipe), but could prove much more dangerous for the GPU passthrough mechanism. Instead, use get_user_pages() as the comment suggested and cleanup the error path and add the set_page_dirt() call on a successful read operation. Also clarify the count used to return from successful read/write calls and use Linux style commentary in various places of the file. Note: The "just ignore error and return whatever we read so far" error handling is really quite horrific. I cannot change it without a more careful study of all user space ABIs reliance on this 'feature'. Signed-off-by: Christoffer Dall Signed-off-by: Jin Qian Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 129 +++++++++++++++++------------- 1 file changed, 72 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 0fb3a34f5991..20a933726ac1 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -2,6 +2,7 @@ * Copyright (C) 2011 Google, Inc. * Copyright (C) 2012 Intel, Inc. * Copyright (C) 2013 Intel, Inc. + * Copyright (C) 2014 Linaro Limited * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -57,6 +58,7 @@ #include #include #include +#include /* * IMPORTANT: The following constants must match the ones used and defined @@ -257,17 +259,14 @@ static int access_with_param(struct goldfish_pipe_dev *dev, const int cmd, return 0; } -/* This function is used for both reading from and writing to a given - * pipe. - */ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, - size_t bufflen, int is_write) + size_t bufflen, int is_write) { unsigned long irq_flags; struct goldfish_pipe *pipe = filp->private_data; struct goldfish_pipe_dev *dev = pipe->dev; unsigned long address, address_end; - int ret = 0; + int count = 0, ret = -EINVAL; /* If the emulator already closed the pipe, no need to go further */ if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) @@ -290,30 +289,23 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, address_end = address + bufflen; while (address < address_end) { - unsigned long page_end = (address & PAGE_MASK) + PAGE_SIZE; - unsigned long next = page_end < address_end ? page_end - : address_end; - unsigned long avail = next - address; + unsigned long page_end = (address & PAGE_MASK) + PAGE_SIZE; + unsigned long next = page_end < address_end ? page_end + : address_end; + unsigned long avail = next - address; int status, wakeBit; - - /* Ensure that the corresponding page is properly mapped */ - /* FIXME: this isn't safe or sufficient - use get_user_pages */ - if (is_write) { - char c; - /* Ensure that the page is mapped and readable */ - if (__get_user(c, (char __user *)address)) { - if (!ret) - ret = -EFAULT; - break; - } - } else { - /* Ensure that the page is mapped and writable */ - if (__put_user(0, (char __user *)address)) { - if (!ret) - ret = -EFAULT; - break; - } - } + struct page *page; + + /* + * We grab the pages on a page-by-page basis in case user + * space gives us a potentially huge buffer but the read only + * returns a small amount, then there's no need to pin that + * much memory to the process. + */ + ret = get_user_pages(current, current->mm, address, 1, + !is_write, 0, &page, NULL); + if (ret < 0) + return ret; /* Now, try to transfer the bytes in the current page */ spin_lock_irqsave(&dev->lock, irq_flags); @@ -332,33 +324,48 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, } spin_unlock_irqrestore(&dev->lock, irq_flags); + if (status > 0 && !is_write) + set_page_dirty(page); + put_page(page); + if (status > 0) { /* Correct transfer */ - ret += status; + count += status; address += status; continue; - } - - if (status == 0) /* EOF */ + } else if (status == 0) { /* EOF */ + ret = 0; break; - - /* An error occured. If we already transfered stuff, just - * return with its count. We expect the next call to return - * an error code */ - if (ret > 0) + } else if (status < 0 && count > 0) { + /* + * An error occurred and we already transferred + * something on one of the previous pages. + * Just return what we already copied and log this + * err. + * + * Note: This seems like an incorrect approach but + * cannot change it until we check if any user space + * ABI relies on this behavior. + */ + pr_info_ratelimited("android_pipe: backend returned error %d on %s\n", + status, is_write ? "write" : "read"); + ret = 0; break; + } - /* If the error is not PIPE_ERROR_AGAIN, or if we are not in - * non-blocking mode, just return the error code. - */ + /* + * If the error is not PIPE_ERROR_AGAIN, or if we are not in + * non-blocking mode, just return the error code. + */ if (status != PIPE_ERROR_AGAIN || (filp->f_flags & O_NONBLOCK) != 0) { ret = goldfish_pipe_error_convert(status); break; } - /* We will have to wait until more data/space is available. - * First, mark the pipe as waiting for a specific wake signal. - */ + /* + * The backend blocked the read/write, wait until the backend + * tells us it's ready to process more data. + */ wakeBit = is_write ? BIT_WAKE_ON_WRITE : BIT_WAKE_ON_READ; set_bit(wakeBit, &pipe->flags); @@ -372,22 +379,29 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, while (test_bit(wakeBit, &pipe->flags)) { if (wait_event_interruptible( pipe->wake_queue, - !test_bit(wakeBit, &pipe->flags))) - return -ERESTARTSYS; + !test_bit(wakeBit, &pipe->flags))) { + ret = -ERESTARTSYS; + break; + } - if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) - return -EIO; + if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) { + ret = -EIO; + break; + } } /* Try to re-acquire the lock */ - if (mutex_lock_interruptible(&pipe->lock)) - return -ERESTARTSYS; - - /* Try the transfer again */ - continue; + if (mutex_lock_interruptible(&pipe->lock)) { + ret = -ERESTARTSYS; + break; + } } mutex_unlock(&pipe->lock); - return ret; + + if (ret < 0) + return ret; + else + return count; } static ssize_t goldfish_pipe_read(struct file *filp, char __user *buffer, @@ -440,10 +454,11 @@ static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id) unsigned long irq_flags; int count = 0; - /* We're going to read from the emulator a list of (channel,flags) - * pairs corresponding to the wake events that occured on each - * blocked pipe (i.e. channel). - */ + /* + * We're going to read from the emulator a list of (channel,flags) + * pairs corresponding to the wake events that occurred on each + * blocked pipe (i.e. channel). + */ spin_lock_irqsave(&dev->lock, irq_flags); for (;;) { /* First read the channel, 0 means the end of the list */ -- cgit v1.2.3 From 91a18a414185a2b937e2cc8bf0cc32de1863d11a Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Wed, 6 Jan 2016 14:05:36 +0000 Subject: platform: goldfish: pipe: add devicetree bindings Add bindings so we don't need to rely on goldfish virtual bus for probing any more, which means we don't need ARM and MIPS goldfish board code for instantiating the bus. In the long term we would like to move towards replacing the Android pipe with virtio-vsock that is currently under development. Signed-off-by: Greg Hackmann Signed-off-by: Jin Qian Acked-by: Rob Herring Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/goldfish/pipe.txt | 17 +++++++++++++++++ drivers/platform/goldfish/goldfish_pipe.c | 10 +++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/goldfish/pipe.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/goldfish/pipe.txt b/Documentation/devicetree/bindings/goldfish/pipe.txt new file mode 100644 index 000000000000..e417a31a1ee3 --- /dev/null +++ b/Documentation/devicetree/bindings/goldfish/pipe.txt @@ -0,0 +1,17 @@ +Android Goldfish QEMU Pipe + +Andorid pipe virtual device generated by android emulator. + +Required properties: + +- compatible : should contain "google,android-pipe" to match emulator +- reg : +- interrupts : + +Example: + + android_pipe@a010000 { + compatible = "google,android-pipe"; + reg = ; + interrupts = <0x12>; + }; diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 20a933726ac1..0b187ff7a35b 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -624,11 +624,19 @@ static int goldfish_pipe_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id goldfish_pipe_of_match[] = { + { .compatible = "google,android-pipe", }, + {}, +}; +MODULE_DEVICE_TABLE(of, goldfish_pipe_of_match); + static struct platform_driver goldfish_pipe = { .probe = goldfish_pipe_probe, .remove = goldfish_pipe_remove, .driver = { - .name = "goldfish_pipe" + .name = "goldfish_pipe", + .owner = THIS_MODULE, + .of_match_table = goldfish_pipe_of_match, } }; -- cgit v1.2.3 From 25dd0f407307c54de5025250ca1dfbd4bdbb2fba Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Wed, 6 Jan 2016 14:05:55 +0000 Subject: platform: goldfish: pipe: don't log when dropping PIPE_ERROR_AGAIN On PIPE_ERROR_AGAIN, just stopping in the middle of a transfer and returning the number of bytes actually handled is the right behavior. Other errors should be returned on the next read() or write() call. Continue logging those until we confirm nothing actually relies on the existing (wrong) behavior of dropping errors on the floor. Signed-off-by: Greg Hackmann Signed-off-by: Jin Qian Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 0b187ff7a35b..7a56be9c9432 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -346,7 +346,8 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, * cannot change it until we check if any user space * ABI relies on this behavior. */ - pr_info_ratelimited("android_pipe: backend returned error %d on %s\n", + if (status != PIPE_ERROR_AGAIN) + pr_info_ratelimited("goldfish_pipe: backend returned error %d on %s\n", status, is_write ? "write" : "read"); ret = 0; break; -- cgit v1.2.3 From 2e5fc89ac5a0b1460316f19b21c38284949daf38 Mon Sep 17 00:00:00 2001 From: Miodrag Dinic Date: Wed, 6 Jan 2016 14:06:08 +0000 Subject: Enable platform support for Goldfish virtual devices Enable CONFIG_GOLDFISH for MIPS platforms. Signed-off-by: Miodrag Dinic Signed-off-by: Jin Qian Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/goldfish/Kconfig b/drivers/platform/goldfish/Kconfig index 2be762743592..50331e3e54f3 100644 --- a/drivers/platform/goldfish/Kconfig +++ b/drivers/platform/goldfish/Kconfig @@ -1,6 +1,6 @@ menuconfig GOLDFISH bool "Platform support for Goldfish virtual devices" - depends on X86_32 || X86_64 || ARM || ARM64 + depends on X86_32 || X86_64 || ARM || ARM64 || MIPS ---help--- Say Y here to get to see options for the Goldfish virtual platform. This option alone does not add any kernel code. -- cgit v1.2.3 From 4f42071c943977e91e7fda8230e4f85bc3ba117a Mon Sep 17 00:00:00 2001 From: Yu Ning Date: Wed, 6 Jan 2016 14:06:40 +0000 Subject: goldfish_pipe: Pass physical addresses to the device if supported For reading and writing guest user space buffers, currently the kernel sends the guest virtual address of the buffer to the pipe device. This virtual address has to be first converted to a guest physical address. Doing this translation on the QEMU side is inefficient and requires additional handling when KVM is enabled, whose implementation would either incur intrusive changes to QEMU's KVM support code or suffer from poor performance, see commit 08c7228c50f8 ("x86-kvm: only sync SREGS when doing address translation") of $AOSP/external/qemu for details, and thus should be avoided if possible. There is a TODO comment in hw/misc/android_pipe.c in the new Android emulator source tree ($AOSP/external/qemu-android) which requests that the translation be done on the kernel side and that physical addresses be passed to the device instead of virtual ones. Once the QEMU-side implementation is done, the kernel will need to support both the new paddr-based pipe device and the old vaddr-based one (which will continue to be used by the classic emulator). This patch achieves that by leveraging the device version register available in the new device. See https://android-review.googlesource.com/128280 for the QEMU-side patch. In addition, use the mmap semaphore (in read mode) to safeguard the call to get_user_pages(). Signed-off-by: Yu Ning Signed-off-by: Jin Qian Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 7a56be9c9432..c214434e8811 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -77,6 +77,7 @@ #define PIPE_REG_PARAMS_ADDR_LOW 0x18 /* read/write: batch data address */ #define PIPE_REG_PARAMS_ADDR_HIGH 0x1c /* read/write: batch data address */ #define PIPE_REG_ACCESS_PARAMS 0x20 /* write: batch access */ +#define PIPE_REG_VERSION 0x24 /* read: device version */ /* list of commands for PIPE_REG_COMMAND */ #define CMD_OPEN 1 /* open new channel */ @@ -126,6 +127,7 @@ struct goldfish_pipe_dev { unsigned char __iomem *base; struct access_params *aps; int irq; + u32 version; }; static struct goldfish_pipe_dev pipe_dev[1]; @@ -296,26 +298,43 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, int status, wakeBit; struct page *page; + /* Either vaddr or paddr depending on the device version */ + unsigned long xaddr; + /* * We grab the pages on a page-by-page basis in case user * space gives us a potentially huge buffer but the read only * returns a small amount, then there's no need to pin that * much memory to the process. */ + down_read(¤t->mm->mmap_sem); ret = get_user_pages(current, current->mm, address, 1, !is_write, 0, &page, NULL); + up_read(¤t->mm->mmap_sem); if (ret < 0) return ret; + if (dev->version) { + /* Device version 1 or newer (qemu-android) expects the + * physical address. + */ + xaddr = page_to_phys(page) | (address & ~PAGE_MASK); + } else { + /* Device version 0 (classic emulator) expects the + * virtual address. + */ + xaddr = address; + } + /* Now, try to transfer the bytes in the current page */ spin_lock_irqsave(&dev->lock, irq_flags); if (access_with_param(dev, is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER, - address, avail, pipe, &status)) { + xaddr, avail, pipe, &status)) { gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, dev->base + PIPE_REG_CHANNEL_HIGH); writel(avail, dev->base + PIPE_REG_SIZE); - gf_write_ptr((void *)address, + gf_write_ptr((void *)xaddr, dev->base + PIPE_REG_ADDRESS, dev->base + PIPE_REG_ADDRESS_HIGH); writel(is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER, @@ -610,6 +629,12 @@ static int goldfish_pipe_probe(struct platform_device *pdev) goto error; } setup_access_params_addr(pdev, dev); + + /* Although the pipe device in the classic Android emulator does not + * recognize the 'version' register, it won't treat this as an error + * either and will simply return 0, which is fine. + */ + dev->version = readl(dev->base + PIPE_REG_VERSION); return 0; error: -- cgit v1.2.3 From d62f324b0ac80c3923ebbf897735c7c24ba887b8 Mon Sep 17 00:00:00 2001 From: Jason Hu Date: Wed, 6 Jan 2016 14:06:55 +0000 Subject: goldfish: Enable ACPI-based enumeration for android pipe Add ACPI binding to the android pipe driver Signed-off-by: Jason Hu Signed-off-by: Jin Qian Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index c214434e8811..e3fab9a1d9f7 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -59,6 +59,7 @@ #include #include #include +#include /* * IMPORTANT: The following constants must match the ones used and defined @@ -650,6 +651,12 @@ static int goldfish_pipe_remove(struct platform_device *pdev) return 0; } +static const struct acpi_device_id goldfish_pipe_acpi_match[] = { + { "GFSH0003", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, goldfish_pipe_acpi_match); + static const struct of_device_id goldfish_pipe_of_match[] = { { .compatible = "google,android-pipe", }, {}, @@ -663,6 +670,7 @@ static struct platform_driver goldfish_pipe = { .name = "goldfish_pipe", .owner = THIS_MODULE, .of_match_table = goldfish_pipe_of_match, + .acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match), } }; -- cgit v1.2.3 From 3e2fbc7feec4426feba609b94aa89a147e02c67e Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Thu, 21 Jan 2016 02:38:53 +0530 Subject: Staging: goldfish: goldfish_nand: Add DMA Support using dmam_alloc_coherent Function nand_setup_cmd_params has 2 goals- -Initialize the cmd_params field so that it can be used to send and read commands from the device. -Get a bus address for the allocated memory to transfer to the device. Replace the combination of devm_kzalloc and _pa() with dmam_alloc_coherent. Coherent mapping guarantees that the device and CPU are in sync. Signed-off-by: Shraddha Barke Signed-off-by: Greg Kroah-Hartman --- drivers/staging/goldfish/goldfish_nand.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/goldfish/goldfish_nand.c b/drivers/staging/goldfish/goldfish_nand.c index 623353db5a08..f223b3a5a428 100644 --- a/drivers/staging/goldfish/goldfish_nand.c +++ b/drivers/staging/goldfish/goldfish_nand.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "goldfish_nand_reg.h" @@ -284,17 +285,18 @@ invalid_arg: static int nand_setup_cmd_params(struct platform_device *pdev, struct goldfish_nand *nand) { - u64 paddr; + dma_addr_t dma_handle; unsigned char __iomem *base = nand->base; - nand->cmd_params = devm_kzalloc(&pdev->dev, - sizeof(struct cmd_params), GFP_KERNEL); - if (!nand->cmd_params) - return -1; - - paddr = __pa(nand->cmd_params); - writel((u32)(paddr >> 32), base + NAND_CMD_PARAMS_ADDR_HIGH); - writel((u32)paddr, base + NAND_CMD_PARAMS_ADDR_LOW); + nand->cmd_params = dmam_alloc_coherent(&pdev->dev, + sizeof(struct cmd_params), + &dma_handle, GFP_KERNEL); + if (!nand->cmd_params) { + dev_err(&pdev->dev, "allocate buffer failed\n"); + return -ENOMEM; + } + writel((u32)((u64)dma_handle >> 32), base + NAND_CMD_PARAMS_ADDR_HIGH); + writel((u32)dma_handle, base + NAND_CMD_PARAMS_ADDR_LOW); return 0; } -- cgit v1.2.3 From bbc396993a97246403f5979036f1b4637a56ef72 Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Thu, 28 Jan 2016 15:22:05 -0800 Subject: drm/i915: Fix file permissions No functional change Signed-off-by: Mat Martineau Fixes: f8d03ea0053b ("drm/i915: increase the tries for HDMI hotplug live status checking") Link: http://patchwork.freedesktop.org/patch/msgid/1454023325-26265-1-git-send-email-mathew.j.martineau@linux.intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_hdmi.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 drivers/gpu/drm/i915/intel_hdmi.c (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c old mode 100755 new mode 100644 -- cgit v1.2.3 From 4c1ce07bcf62536ed42a4ba43e5fb580be61ac48 Mon Sep 17 00:00:00 2001 From: Uri Mashiach Date: Wed, 30 Dec 2015 15:35:31 +0200 Subject: wlcore/wl12xx: spi: add power operation function The power function uses a consumer regulator access to update the WiFi enable GPIO value. Signed-off-by: Uri Mashiach Tested-By: Sebastian Reichel Reviewed-by: Grygorii Strashko Acked-by: Igor Grinberg Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wlcore/spi.c | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 44f059f7f34e..dec151247d0d 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "wlcore.h" #include "wl12xx_80211.h" @@ -81,6 +82,7 @@ struct wl12xx_spi_glue { struct device *dev; struct platform_device *core; + struct regulator *reg; /* Power regulator */ }; static void wl12xx_spi_reset(struct device *child) @@ -318,11 +320,40 @@ static int __must_check wl12xx_spi_raw_write(struct device *child, int addr, return 0; } +/** + * wl12xx_spi_set_power - power on/off the wl12xx unit + * @child: wl12xx device handle. + * @enable: true/false to power on/off the unit. + * + * use the WiFi enable regulator to enable/disable the WiFi unit. + */ +static int wl12xx_spi_set_power(struct device *child, bool enable) +{ + int ret = 0; + struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); + + WARN_ON(!glue->reg); + + /* Update regulator state */ + if (enable) { + ret = regulator_enable(glue->reg); + if (ret) + dev_err(child, "Power enable failure\n"); + } else { + ret = regulator_disable(glue->reg); + if (ret) + dev_err(child, "Power disable failure\n"); + } + + return ret; +} + static struct wl1271_if_operations spi_ops = { .read = wl12xx_spi_raw_read, .write = wl12xx_spi_raw_write, .reset = wl12xx_spi_reset, .init = wl12xx_spi_init, + .power = wl12xx_spi_set_power, .set_block_size = NULL, }; @@ -353,6 +384,14 @@ static int wl1271_probe(struct spi_device *spi) * comes from the board-peripherals file */ spi->bits_per_word = 32; + glue->reg = devm_regulator_get(&spi->dev, "vwlan"); + if (PTR_ERR(glue->reg) == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (IS_ERR(glue->reg)) { + dev_err(glue->dev, "can't get regulator\n"); + return PTR_ERR(glue->reg); + } + ret = spi_setup(spi); if (ret < 0) { dev_err(glue->dev, "spi_setup failed\n"); -- cgit v1.2.3 From 04654c386145239c8bcb35878b0b0537ce916766 Mon Sep 17 00:00:00 2001 From: Uri Mashiach Date: Wed, 30 Dec 2015 15:35:32 +0200 Subject: wlcore/wl12xx: spi: add device tree support Add DT support for the wl1271 SPI WiFi. Add documentation file for the wl1271 SPI WiFi. Signed-off-by: Uri Mashiach Acked-by: Rob Herring Tested-By: Sebastian Reichel Reviewed-by: Grygorii Strashko Acked-by: Igor Grinberg Signed-off-by: Kalle Valo --- .../bindings/net/wireless/ti,wlcore,spi.txt | 36 +++++++++++++++++ drivers/net/wireless/ti/wlcore/Kconfig | 2 +- drivers/net/wireless/ti/wlcore/spi.c | 47 ++++++++++++++++++++-- 3 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/wireless/ti,wlcore,spi.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/net/wireless/ti,wlcore,spi.txt b/Documentation/devicetree/bindings/net/wireless/ti,wlcore,spi.txt new file mode 100644 index 000000000000..9180724e182c --- /dev/null +++ b/Documentation/devicetree/bindings/net/wireless/ti,wlcore,spi.txt @@ -0,0 +1,36 @@ +* Texas Instruments wl1271 wireless lan controller + +The wl1271 chip can be connected via SPI or via SDIO. This +document describes the binding for the SPI connected chip. + +Required properties: +- compatible : Should be "ti,wl1271" +- reg : Chip select address of device +- spi-max-frequency : Maximum SPI clocking speed of device in Hz +- ref-clock-frequency : Reference clock frequency +- interrupt-parent, interrupts : + Should contain parameters for 1 interrupt line. + Interrupt parameters: parent, line number, type. +- vwlan-supply : Point the node of the regulator that powers/enable the wl1271 chip + +Optional properties: +- clock-xtal : boolean, clock is generated from XTAL + +- Please consult Documentation/devicetree/bindings/spi/spi-bus.txt + for optional SPI connection related properties, + +Examples: + +&spi1 { + wl1271@1 { + compatible = "ti,wl1271"; + + reg = <1>; + spi-max-frequency = <48000000>; + clock-xtal; + ref-clock-frequency = <38400000>; + interrupt-parent = <&gpio3>; + interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; + vwlan-supply = <&vwlan_fixed>; + }; +}; diff --git a/drivers/net/wireless/ti/wlcore/Kconfig b/drivers/net/wireless/ti/wlcore/Kconfig index 969c9d79bfc8..8a8f1e711384 100644 --- a/drivers/net/wireless/ti/wlcore/Kconfig +++ b/drivers/net/wireless/ti/wlcore/Kconfig @@ -13,7 +13,7 @@ config WLCORE config WLCORE_SPI tristate "TI wlcore SPI support" - depends on WLCORE && SPI_MASTER + depends on WLCORE && SPI_MASTER && OF select CRC7 ---help--- This module adds support for the SPI interface of adapters using diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index dec151247d0d..020ac1a4b408 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "wlcore.h" @@ -357,6 +358,39 @@ static struct wl1271_if_operations spi_ops = { .set_block_size = NULL, }; +static const struct of_device_id wlcore_spi_of_match_table[] = { + { .compatible = "ti,wl1271" }, + { } +}; +MODULE_DEVICE_TABLE(of, wlcore_spi_of_match_table); + +/** + * wlcore_probe_of - DT node parsing. + * @spi: SPI slave device parameters. + * @res: resource parameters. + * @glue: wl12xx SPI bus to slave device glue parameters. + * @pdev_data: wlcore device parameters + */ +static int wlcore_probe_of(struct spi_device *spi, struct wl12xx_spi_glue *glue, + struct wlcore_platdev_data *pdev_data) +{ + struct device_node *dt_node = spi->dev.of_node; + int ret; + + if (of_find_property(dt_node, "clock-xtal", NULL)) + pdev_data->ref_clock_xtal = true; + + ret = of_property_read_u32(dt_node, "ref-clock-frequency", + &pdev_data->ref_clock_freq); + if (IS_ERR_VALUE(ret)) { + dev_err(glue->dev, + "can't get reference clock frequency (%d)\n", ret); + return ret; + } + + return 0; +} + static int wl1271_probe(struct spi_device *spi) { struct wl12xx_spi_glue *glue; @@ -366,8 +400,6 @@ static int wl1271_probe(struct spi_device *spi) memset(&pdev_data, 0x00, sizeof(pdev_data)); - /* TODO: add DT parsing when needed */ - pdev_data.if_ops = &spi_ops; glue = devm_kzalloc(&spi->dev, sizeof(*glue), GFP_KERNEL); @@ -392,6 +424,13 @@ static int wl1271_probe(struct spi_device *spi) return PTR_ERR(glue->reg); } + ret = wlcore_probe_of(spi, glue, &pdev_data); + if (IS_ERR_VALUE(ret)) { + dev_err(glue->dev, + "can't get device tree parameters (%d)\n", ret); + return ret; + } + ret = spi_setup(spi); if (ret < 0) { dev_err(glue->dev, "spi_setup failed\n"); @@ -409,7 +448,7 @@ static int wl1271_probe(struct spi_device *spi) memset(res, 0x00, sizeof(res)); res[0].start = spi->irq; - res[0].flags = IORESOURCE_IRQ; + res[0].flags = IORESOURCE_IRQ | irq_get_trigger_type(spi->irq); res[0].name = "irq"; ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res)); @@ -447,10 +486,10 @@ static int wl1271_remove(struct spi_device *spi) return 0; } - static struct spi_driver wl1271_spi_driver = { .driver = { .name = "wl1271_spi", + .of_match_table = of_match_ptr(wlcore_spi_of_match_table), }, .probe = wl1271_probe, -- cgit v1.2.3 From 2fd5c6ed0b4fbf3c2d9314a24c82862ce5254d42 Mon Sep 17 00:00:00 2001 From: chunfan chen Date: Wed, 6 Jan 2016 23:40:47 -0800 Subject: mwifiex: firmware download enhancements Same chip is being used by WLAN as well as bluetooth drivers. Each driver needs to check during initialisation if firmware is already active or it needs to be freshly downloaded. If one driver has started downloading the firmware, other finds the winner flag as false. mwifiex_check_fw_status() checks firmware status and also check if WLAN is the winner for firmware downloading. Once we detect that other interface is downloading the firmware, we call this routine again with max poll count to wait until firmware is ready. This patch splits the routine to avoid checking winner status unnecessarily multiple times and ensures that correct messages are displayed to user. Firmware status poll count is also increased to 150. Signed-off-by: Chunfan Chen Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/fw.h | 2 +- drivers/net/wireless/marvell/mwifiex/init.c | 16 +++++++++--- drivers/net/wireless/marvell/mwifiex/main.h | 1 + drivers/net/wireless/marvell/mwifiex/pcie.c | 40 +++++++++++++++++------------ drivers/net/wireless/marvell/mwifiex/sdio.c | 33 ++++++++++++++---------- 5 files changed, 57 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index ced7af2be29a..426e76ade30c 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -96,7 +96,7 @@ enum KEY_TYPE_ID { #define WAPI_KEY_LEN (WLAN_KEY_LEN_SMS4 + PN_LEN + 2) #define MAX_POLL_TRIES 100 -#define MAX_FIRMWARE_POLL_TRIES 100 +#define MAX_FIRMWARE_POLL_TRIES 150 #define FIRMWARE_READY_SDIO 0xfedc #define FIRMWARE_READY_PCIE 0xfedcba00 diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c index 6f7876ec31b7..517653b3adab 100644 --- a/drivers/net/wireless/marvell/mwifiex/init.c +++ b/drivers/net/wireless/marvell/mwifiex/init.c @@ -741,8 +741,6 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, u32 poll_num = 1; if (adapter->if_ops.check_fw_status) { - adapter->winner = 0; - /* check if firmware is already running */ ret = adapter->if_ops.check_fw_status(adapter, poll_num); if (!ret) { @@ -750,13 +748,23 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, "WLAN FW already running! Skip FW dnld\n"); return 0; } + } + + /* check if we are the winner for downloading FW */ + if (adapter->if_ops.check_winner_status) { + adapter->winner = 0; + ret = adapter->if_ops.check_winner_status(adapter); poll_num = MAX_FIRMWARE_POLL_TRIES; + if (ret) { + mwifiex_dbg(adapter, MSG, + "WLAN read winner status failed!\n"); + return ret; + } - /* check if we are the winner for downloading FW */ if (!adapter->winner) { mwifiex_dbg(adapter, MSG, - "FW already running! Skip FW dnld\n"); + "WLAN is not the winner! Skip FW dnld\n"); goto poll_fw; } } diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 2f7f478ce04b..c08be798905f 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -791,6 +791,7 @@ struct mwifiex_if_ops { int (*init_if) (struct mwifiex_adapter *); void (*cleanup_if) (struct mwifiex_adapter *); int (*check_fw_status) (struct mwifiex_adapter *, u32); + int (*check_winner_status)(struct mwifiex_adapter *); int (*prog_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *); int (*register_dev) (struct mwifiex_adapter *); void (*unregister_dev) (struct mwifiex_adapter *); diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 6d0dc40e20e5..f448d7ca4e7c 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2007,14 +2007,12 @@ done: /* * This function checks the firmware status in card. - * - * The winner interface is also determined by this function. */ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num) { int ret = 0; - u32 firmware_stat, winner_status; + u32 firmware_stat; struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; u32 tries; @@ -2054,19 +2052,28 @@ mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num) } } - if (ret) { - if (mwifiex_read_reg(adapter, reg->fw_status, - &winner_status)) - ret = -1; - else if (!winner_status) { - mwifiex_dbg(adapter, INFO, - "PCI-E is the winner\n"); - adapter->winner = 1; - } else { - mwifiex_dbg(adapter, ERROR, - "PCI-E is not the winner <%#x,%d>, exit dnld\n", - ret, adapter->winner); - } + return ret; +} + +/* This function checks if WLAN is the winner. + */ +static int +mwifiex_check_winner_status(struct mwifiex_adapter *adapter) +{ + u32 winner = 0; + int ret = 0; + struct pcie_service_card *card = adapter->card; + const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; + + if (mwifiex_read_reg(adapter, reg->fw_status, &winner)) { + ret = -1; + } else if (!winner) { + mwifiex_dbg(adapter, INFO, "PCI-E is the winner\n"); + adapter->winner = 1; + } else { + mwifiex_dbg(adapter, ERROR, + "PCI-E is not the winner <%#x,%d>, exit dnld\n", + ret, adapter->winner); } return ret; @@ -2675,6 +2682,7 @@ static struct mwifiex_if_ops pcie_ops = { .init_if = mwifiex_pcie_init, .cleanup_if = mwifiex_pcie_cleanup, .check_fw_status = mwifiex_check_fw_status, + .check_winner_status = mwifiex_check_winner_status, .prog_fw = mwifiex_prog_fw_w_helper, .register_dev = mwifiex_register_dev, .unregister_dev = mwifiex_unregister_dev, diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index 4c8cae682c89..33771d3fd843 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -1039,19 +1039,14 @@ done: /* * This function checks the firmware status in card. - * - * The winner interface is also determined by this function. */ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num) { - struct sdio_mmc_card *card = adapter->card; int ret = 0; u16 firmware_stat; u32 tries; - u8 winner_status; - /* Wait for firmware initialization event */ for (tries = 0; tries < poll_num; tries++) { ret = mwifiex_sdio_read_fw_status(adapter, &firmware_stat); if (ret) @@ -1065,16 +1060,25 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, } } - if (ret) { - if (mwifiex_read_reg - (adapter, card->reg->status_reg_0, &winner_status)) - winner_status = 0; + return ret; +} + +/* This function checks if WLAN is the winner. + */ +static int mwifiex_check_winner_status(struct mwifiex_adapter *adapter) +{ + int ret = 0; + u8 winner = 0; + struct sdio_mmc_card *card = adapter->card; + + if (mwifiex_read_reg(adapter, card->reg->status_reg_0, &winner)) + return -1; + + if (winner) + adapter->winner = 0; + else + adapter->winner = 1; - if (winner_status) - adapter->winner = 0; - else - adapter->winner = 1; - } return ret; } @@ -2620,6 +2624,7 @@ static struct mwifiex_if_ops sdio_ops = { .init_if = mwifiex_init_sdio, .cleanup_if = mwifiex_cleanup_sdio, .check_fw_status = mwifiex_check_fw_status, + .check_winner_status = mwifiex_check_winner_status, .prog_fw = mwifiex_prog_fw_w_helper, .register_dev = mwifiex_register_dev, .unregister_dev = mwifiex_unregister_dev, -- cgit v1.2.3 From dc386ce76dedaeeaaf006fceb6ed8cf2e20ff026 Mon Sep 17 00:00:00 2001 From: chunfan chen Date: Wed, 6 Jan 2016 23:40:48 -0800 Subject: mwifiex: fix IBSS data path issue. The port_open flag is not applicable for IBSS mode. IBSS data path was broken when port_open flag was introduced. This patch fixes the problem by correcting the checks. Fixes: 5c8946330abfa4c ("mwifiex: enable traffic only when port is open") Signed-off-by: chunfan chen Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/sta_event.c | 10 ++++++---- drivers/net/wireless/marvell/mwifiex/wmm.c | 6 ++++-- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c index ff3ee9dfbbd5..23bae87d4d3d 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c @@ -607,11 +607,13 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) case EVENT_PS_AWAKE: mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n"); - if (!adapter->pps_uapsd_mode && priv->port_open && + if (!adapter->pps_uapsd_mode && + (priv->port_open || + (priv->bss_mode == NL80211_IFTYPE_ADHOC)) && priv->media_connected && adapter->sleep_period.period) { - adapter->pps_uapsd_mode = true; - mwifiex_dbg(adapter, EVENT, - "event: PPS/UAPSD mode activated\n"); + adapter->pps_uapsd_mode = true; + mwifiex_dbg(adapter, EVENT, + "event: PPS/UAPSD mode activated\n"); } adapter->tx_lock_flag = false; if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.c b/drivers/net/wireless/marvell/mwifiex/wmm.c index acccd6734e3b..499e5a741c62 100644 --- a/drivers/net/wireless/marvell/mwifiex/wmm.c +++ b/drivers/net/wireless/marvell/mwifiex/wmm.c @@ -475,7 +475,8 @@ mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) priv = adapter->priv[i]; if (!priv) continue; - if (!priv->port_open) + if (!priv->port_open && + (priv->bss_mode != NL80211_IFTYPE_ADHOC)) continue; if (adapter->if_ops.is_port_ready && !adapter->if_ops.is_port_ready(priv)) @@ -1099,7 +1100,8 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, priv_tmp = adapter->bss_prio_tbl[j].bss_prio_cur->priv; - if (!priv_tmp->port_open || + if (((priv_tmp->bss_mode != NL80211_IFTYPE_ADHOC) && + !priv_tmp->port_open) || (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0)) continue; -- cgit v1.2.3 From 17934b6a32b2fdfcc0a9e83d17c780f15627aa30 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Wed, 6 Jan 2016 23:40:49 -0800 Subject: mwifiex: add debugfs file to read chip information This patch add 'verext' debugfs item, which can be used to get detailed chip specific information from our firmware. Examples: echo "1" > /sys/kernel/debug/mwifiex/mlan0/verext cat /sys/kernel/debug/mwifiex/mlan0/verext Signed-off-by: Shengzhen Li Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/README | 10 +++++ drivers/net/wireless/marvell/mwifiex/debugfs.c | 51 +++++++++++++++++++++++- drivers/net/wireless/marvell/mwifiex/main.h | 3 +- drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 3 +- 4 files changed, 63 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/README b/drivers/net/wireless/marvell/mwifiex/README index 2f0f9b5609d0..24e649b1eb24 100644 --- a/drivers/net/wireless/marvell/mwifiex/README +++ b/drivers/net/wireless/marvell/mwifiex/README @@ -237,4 +237,14 @@ device_dump cat fw_dump +verext + This command is used to get extended firmware version string using + different configuration parameters. + + Usage: + echo "[version_str_sel]" > verext + cat verext + + [version_str_sel]: firmware support several extend version + string cases, include 0/1/10/20/21/99 =============================================================================== diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c index 0b9c580af988..df28836a1d11 100644 --- a/drivers/net/wireless/marvell/mwifiex/debugfs.c +++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c @@ -95,8 +95,7 @@ mwifiex_info_read(struct file *file, char __user *ubuf, mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1); - if (!priv->version_str[0]) - mwifiex_get_ver_ext(priv); + mwifiex_get_ver_ext(priv, 0); p += sprintf(p, "driver_name = " "\"mwifiex\"\n"); p += sprintf(p, "driver_version = %s", fmt); @@ -583,6 +582,52 @@ done: return ret; } +/* debugfs verext file write handler. + * This function is called when the 'verext' file is opened for write + */ +static ssize_t +mwifiex_verext_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + int ret; + u32 versionstrsel; + struct mwifiex_private *priv = (void *)file->private_data; + char buf[16]; + + memset(buf, 0, sizeof(buf)); + + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) + return -EFAULT; + + ret = kstrtou32(buf, 10, &versionstrsel); + if (ret) + return ret; + + priv->versionstrsel = versionstrsel; + + return count; +} + +/* Proc verext file read handler. + * This function is called when the 'verext' file is opened for reading + * This function can be used read driver exteneed verion string. + */ +static ssize_t +mwifiex_verext_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct mwifiex_private *priv = + (struct mwifiex_private *)file->private_data; + char buf[256]; + int ret; + + mwifiex_get_ver_ext(priv, priv->versionstrsel); + ret = snprintf(buf, sizeof(buf), "version string: %s\n", + priv->version_str); + + return simple_read_from_buffer(ubuf, count, ppos, buf, ret); +} + /* Proc memrw file write handler. * This function is called when the 'memrw' file is opened for writing * This function can be used to write to a memory location. @@ -940,6 +985,7 @@ MWIFIEX_DFS_FILE_OPS(histogram); MWIFIEX_DFS_FILE_OPS(debug_mask); MWIFIEX_DFS_FILE_OPS(timeshare_coex); MWIFIEX_DFS_FILE_WRITE_OPS(reset); +MWIFIEX_DFS_FILE_OPS(verext); /* * This function creates the debug FS directory structure and the files. @@ -968,6 +1014,7 @@ mwifiex_dev_debugfs_init(struct mwifiex_private *priv) MWIFIEX_DFS_ADD_FILE(debug_mask); MWIFIEX_DFS_ADD_FILE(timeshare_coex); MWIFIEX_DFS_ADD_FILE(reset); + MWIFIEX_DFS_ADD_FILE(verext); } /* diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index c08be798905f..35ab052c8a36 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -616,6 +616,7 @@ struct mwifiex_private { spinlock_t curr_bcn_buf_lock; struct wireless_dev wdev; struct mwifiex_chan_freq_power cfp; + u32 versionstrsel; char version_str[128]; #ifdef CONFIG_DEBUG_FS struct dentry *dfs_dev_dir; @@ -1418,7 +1419,7 @@ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp, int mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len); -int mwifiex_get_ver_ext(struct mwifiex_private *priv); +int mwifiex_get_ver_ext(struct mwifiex_private *priv, u32 version_str_sel); int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, struct ieee80211_channel *chan, diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index 6a4fc5d183cf..210b257aad6b 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -1114,11 +1114,12 @@ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp, * with requisite parameters and calls the IOCTL handler. */ int -mwifiex_get_ver_ext(struct mwifiex_private *priv) +mwifiex_get_ver_ext(struct mwifiex_private *priv, u32 version_str_sel) { struct mwifiex_ver_ext ver_ext; memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext)); + ver_ext.version_str_sel = version_str_sel; if (mwifiex_send_cmd(priv, HostCmd_CMD_VERSION_EXT, HostCmd_ACT_GEN_GET, 0, &ver_ext, true)) return -1; -- cgit v1.2.3 From 68f37e5d7a2e00306adab033fba6c3042b33e8e1 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Thu, 7 Jan 2016 14:28:50 +0100 Subject: wlcore: fix error handling in wlcore_event_fw_logger wlcore_read/wlcore_write can return negative values so it should be assigned to signed variable. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2120705 Fixes: 3719c17e1816 ("wlcore/wl18xx: fw logger over sdio") Signed-off-by: Andrzej Hajda Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wlcore/event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index c96405498bf4..4b59f67724de 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c @@ -38,7 +38,7 @@ int wlcore_event_fw_logger(struct wl1271 *wl) { - u32 ret; + int ret; struct fw_logger_information fw_log; u8 *buffer; u32 internal_fw_addrbase = WL18XX_DATA_RAM_BASE_ADDRESS; -- cgit v1.2.3 From 99074fc1e67b374b5c72406a23ac01fed806d634 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Mon, 11 Jan 2016 02:16:40 -0800 Subject: mwifiex: enable pcie MSIx interrupt mode support Newer pcie chipsets (8997 onwards) support MSIx. This patch enables it. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 187 +++++++++++++++++++++++----- drivers/net/wireless/marvell/mwifiex/pcie.h | 17 +++ 2 files changed, 176 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index f448d7ca4e7c..5e154649c6a2 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2082,20 +2082,28 @@ mwifiex_check_winner_status(struct mwifiex_adapter *adapter) /* * This function reads the interrupt status from card. */ -static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) +static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter, + int msg_id) { u32 pcie_ireg; unsigned long flags; + struct pcie_service_card *card = adapter->card; if (!mwifiex_pcie_ok_to_access_hw(adapter)) return; - if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS, &pcie_ireg)) { - mwifiex_dbg(adapter, ERROR, "Read register failed\n"); - return; - } + if (card->msix_enable && msg_id >= 0) { + pcie_ireg = BIT(msg_id); + } else { + if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS, + &pcie_ireg)) { + mwifiex_dbg(adapter, ERROR, "Read register failed\n"); + return; + } + + if ((pcie_ireg == 0xFFFFFFFF) || !pcie_ireg) + return; - if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) { mwifiex_pcie_disable_host_int(adapter); @@ -2106,20 +2114,23 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) "Write register failed\n"); return; } - spin_lock_irqsave(&adapter->int_lock, flags); - adapter->int_status |= pcie_ireg; - spin_unlock_irqrestore(&adapter->int_lock, flags); - - if (!adapter->pps_uapsd_mode && - adapter->ps_state == PS_STATE_SLEEP && - mwifiex_pcie_ok_to_access_hw(adapter)) { - /* Potentially for PCIe we could get other - * interrupts like shared. Don't change power - * state until cookie is set */ - adapter->ps_state = PS_STATE_AWAKE; - adapter->pm_wakeup_fw_try = false; - del_timer(&adapter->wakeup_timer); - } + } + + spin_lock_irqsave(&adapter->int_lock, flags); + adapter->int_status |= pcie_ireg; + spin_unlock_irqrestore(&adapter->int_lock, flags); + mwifiex_dbg(adapter, INTR, "ireg: 0x%08x\n", pcie_ireg); + + if (!adapter->pps_uapsd_mode && + adapter->ps_state == PS_STATE_SLEEP && + mwifiex_pcie_ok_to_access_hw(adapter)) { + /* Potentially for PCIe we could get other + * interrupts like shared. Don't change power + * state until cookie is set + */ + adapter->ps_state = PS_STATE_AWAKE; + adapter->pm_wakeup_fw_try = false; + del_timer(&adapter->wakeup_timer); } } @@ -2131,7 +2142,8 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) */ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context) { - struct pci_dev *pdev = (struct pci_dev *)context; + struct mwifiex_msix_context *ctx = context; + struct pci_dev *pdev = ctx->dev; struct pcie_service_card *card; struct mwifiex_adapter *adapter; @@ -2151,7 +2163,11 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context) if (adapter->surprise_removed) goto exit; - mwifiex_interrupt_status(adapter); + if (card->msix_enable) + mwifiex_interrupt_status(adapter, ctx->msg_id); + else + mwifiex_interrupt_status(adapter, -1); + mwifiex_queue_main_work(adapter); exit: @@ -2171,7 +2187,7 @@ exit: * In case of Rx packets received, the packets are uploaded from card to * host and processed accordingly. */ -static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) +static int mwifiex_process_pcie_int(struct mwifiex_adapter *adapter) { int ret; u32 pcie_ireg; @@ -2251,6 +2267,69 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) return 0; } +static int mwifiex_process_msix_int(struct mwifiex_adapter *adapter) +{ + int ret; + u32 pcie_ireg; + unsigned long flags; + + spin_lock_irqsave(&adapter->int_lock, flags); + /* Clear out unused interrupts */ + pcie_ireg = adapter->int_status; + adapter->int_status = 0; + spin_unlock_irqrestore(&adapter->int_lock, flags); + + if (pcie_ireg & HOST_INTR_DNLD_DONE) { + mwifiex_dbg(adapter, INTR, + "info: TX DNLD Done\n"); + ret = mwifiex_pcie_send_data_complete(adapter); + if (ret) + return ret; + } + if (pcie_ireg & HOST_INTR_UPLD_RDY) { + mwifiex_dbg(adapter, INTR, + "info: Rx DATA\n"); + ret = mwifiex_pcie_process_recv_data(adapter); + if (ret) + return ret; + } + if (pcie_ireg & HOST_INTR_EVENT_RDY) { + mwifiex_dbg(adapter, INTR, + "info: Rx EVENT\n"); + ret = mwifiex_pcie_process_event_ready(adapter); + if (ret) + return ret; + } + + if (pcie_ireg & HOST_INTR_CMD_DONE) { + if (adapter->cmd_sent) { + mwifiex_dbg(adapter, INTR, + "info: CMD sent Interrupt\n"); + adapter->cmd_sent = false; + } + /* Handle command response */ + ret = mwifiex_pcie_process_cmd_complete(adapter); + if (ret) + return ret; + } + + mwifiex_dbg(adapter, INTR, + "info: cmd_sent=%d data_sent=%d\n", + adapter->cmd_sent, adapter->data_sent); + + return 0; +} + +static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) +{ + struct pcie_service_card *card = adapter->card; + + if (card->msix_enable) + return mwifiex_process_msix_int(adapter); + else + return mwifiex_process_pcie_int(adapter); +} + /* * This function downloads data from driver to card. * @@ -2602,10 +2681,43 @@ static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter) static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter) { - int ret; + int ret, i, j; struct pcie_service_card *card = adapter->card; struct pci_dev *pdev = card->dev; + if (card->pcie.reg->msix_support) { + for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++) + card->msix_entries[i].entry = i; + ret = pci_enable_msix_exact(pdev, card->msix_entries, + MWIFIEX_NUM_MSIX_VECTORS); + if (!ret) { + for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++) { + card->msix_ctx[i].dev = pdev; + card->msix_ctx[i].msg_id = i; + + ret = request_irq(card->msix_entries[i].vector, + mwifiex_pcie_interrupt, 0, + "MWIFIEX_PCIE_MSIX", + &card->msix_ctx[i]); + if (ret) + break; + } + + if (ret) { + mwifiex_dbg(adapter, INFO, "request_irq fail: %d\n", + ret); + for (j = 0; j < i; j++) + free_irq(card->msix_entries[j].vector, + &card->msix_ctx[i]); + pci_disable_msix(pdev); + } else { + mwifiex_dbg(adapter, MSG, "MSIx enabled!"); + card->msix_enable = 1; + return 0; + } + } + } + if (pci_enable_msi(pdev) != 0) pci_disable_msi(pdev); else @@ -2613,8 +2725,10 @@ static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter) mwifiex_dbg(adapter, INFO, "msi_enable = %d\n", card->msi_enable); + card->share_irq_ctx.dev = pdev; + card->share_irq_ctx.msg_id = -1; ret = request_irq(pdev->irq, mwifiex_pcie_interrupt, IRQF_SHARED, - "MRVL_PCIE", pdev); + "MRVL_PCIE", &card->share_irq_ctx); if (ret) { pr_err("request_irq failed: ret=%d\n", ret); adapter->card = NULL; @@ -2660,11 +2774,28 @@ static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *reg; + struct pci_dev *pdev = card->dev; + int i; if (card) { - mwifiex_dbg(adapter, INFO, - "%s(): calling free_irq()\n", __func__); - free_irq(card->dev->irq, card->dev); + if (card->msix_enable) { + for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++) + synchronize_irq(card->msix_entries[i].vector); + + for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++) + free_irq(card->msix_entries[i].vector, + &card->msix_ctx[i]); + + card->msix_enable = 0; + pci_disable_msix(pdev); + } else { + mwifiex_dbg(adapter, INFO, + "%s(): calling free_irq()\n", __func__); + free_irq(card->dev->irq, &card->share_irq_ctx); + + if (card->msi_enable) + pci_disable_msi(pdev); + } reg = card->pcie.reg; if (reg->sleep_cookie) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index 6fc28737b576..9700ac355e55 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -135,6 +135,7 @@ struct mwifiex_pcie_card_reg { u16 fw_dump_ctrl; u16 fw_dump_start; u16 fw_dump_end; + u8 msix_support; }; static const struct mwifiex_pcie_card_reg mwifiex_reg_8766 = { @@ -166,6 +167,7 @@ static const struct mwifiex_pcie_card_reg mwifiex_reg_8766 = { .ring_tx_start_ptr = 0, .pfu_enabled = 0, .sleep_cookie = 1, + .msix_support = 0, }; static const struct mwifiex_pcie_card_reg mwifiex_reg_8897 = { @@ -200,6 +202,7 @@ static const struct mwifiex_pcie_card_reg mwifiex_reg_8897 = { .fw_dump_ctrl = 0xcf4, .fw_dump_start = 0xcf8, .fw_dump_end = 0xcff, + .msix_support = 0, }; static const struct mwifiex_pcie_card_reg mwifiex_reg_8997 = { @@ -231,6 +234,7 @@ static const struct mwifiex_pcie_card_reg mwifiex_reg_8997 = { .ring_tx_start_ptr = MWIFIEX_BD_FLAG_TX_START_PTR, .pfu_enabled = 1, .sleep_cookie = 0, + .msix_support = 1, }; struct mwifiex_pcie_device { @@ -290,6 +294,13 @@ struct mwifiex_pfu_buf_desc { u32 reserved; } __packed; +#define MWIFIEX_NUM_MSIX_VECTORS 4 + +struct mwifiex_msix_context { + struct pci_dev *dev; + u16 msg_id; +}; + struct pcie_service_card { struct pci_dev *dev; struct mwifiex_adapter *adapter; @@ -327,6 +338,12 @@ struct pcie_service_card { void __iomem *pci_mmap; void __iomem *pci_mmap1; int msi_enable; + int msix_enable; +#ifdef CONFIG_PCI + struct msix_entry msix_entries[MWIFIEX_NUM_MSIX_VECTORS]; +#endif + struct mwifiex_msix_context msix_ctx[MWIFIEX_NUM_MSIX_VECTORS]; + struct mwifiex_msix_context share_irq_ctx; }; static inline int -- cgit v1.2.3 From dc896b15fe94345912ff13fa8eb581b5c6acccde Mon Sep 17 00:00:00 2001 From: Shengzhen Li Date: Tue, 12 Jan 2016 05:43:16 -0800 Subject: mwifiex: fix power state out of sync problem It's been observed that driver's power state goes out of sync with firmware in some corner cases. When this happens, driver tries to download the data to firmware assuming it's awake which causes Tx data timeout. Main thread will process interrupt as soon as interrupt handler fills 'int_status' variable. This patch fixes the race issue by updating 'int_status' at the end of mwifiex_interrupt_status(). Signed-off-by: Shengzhen Li Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 5e154649c6a2..918e04954afe 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2116,11 +2116,6 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter, } } - spin_lock_irqsave(&adapter->int_lock, flags); - adapter->int_status |= pcie_ireg; - spin_unlock_irqrestore(&adapter->int_lock, flags); - mwifiex_dbg(adapter, INTR, "ireg: 0x%08x\n", pcie_ireg); - if (!adapter->pps_uapsd_mode && adapter->ps_state == PS_STATE_SLEEP && mwifiex_pcie_ok_to_access_hw(adapter)) { @@ -2132,6 +2127,11 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter, adapter->pm_wakeup_fw_try = false; del_timer(&adapter->wakeup_timer); } + + spin_lock_irqsave(&adapter->int_lock, flags); + adapter->int_status |= pcie_ireg; + spin_unlock_irqrestore(&adapter->int_lock, flags); + mwifiex_dbg(adapter, INTR, "ireg: 0x%08x\n", pcie_ireg); } /* -- cgit v1.2.3 From 89aa027e6019d6e631a6c18c877e01f890a1800f Mon Sep 17 00:00:00 2001 From: Alexander Kochetkov Date: Fri, 29 Jan 2016 10:58:02 +0300 Subject: clk: rockchip: Allow sclk_i2s0 and i2s0_frac to change their parents rate on rk3188 Allow sclk_i2s0 and i2s0_frac to change their parents rate as that the upstream dividers are purely there to feed sclk_i2s0 Tested on radxarock-lite. Signed-off-by: Alexander Kochetkov Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3188.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index cc1d09d77edd..629c65df1f2d 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -666,7 +666,7 @@ PNAME(mux_hsicphy_p) = { "sclk_otgphy0_480m", "sclk_otgphy1_480m", "gpll", "cpll" }; static struct rockchip_clk_branch rk3188_i2s0_fracmux __initdata = - MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0, + MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(3), 8, 2, MFLAGS); static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = { @@ -722,7 +722,7 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = { COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0, RK2928_CLKSEL_CON(3), 0, 7, DFLAGS, RK2928_CLKGATE_CON(0), 9, GFLAGS), - COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", 0, + COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(7), 0, RK2928_CLKGATE_CON(0), 10, GFLAGS, &rk3188_i2s0_fracmux), -- cgit v1.2.3 From 0c9b7f22e8e1f3aa5b88d7530db8b3a7d647adb6 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Wed, 13 Jan 2016 01:26:52 -0800 Subject: mwifiex: add schedule scan support This patch add sched scan support for mwifiex, include cfg80211 sched_scan_start/sched_scan_stop handler, corresponding bgscan command path and event handler. Signed-off-by: Xinming Hu Signed-off-by: chunfan chen Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 134 +++++++++++ drivers/net/wireless/marvell/mwifiex/fw.h | 59 +++++ drivers/net/wireless/marvell/mwifiex/ioctl.h | 1 + drivers/net/wireless/marvell/mwifiex/main.c | 7 + drivers/net/wireless/marvell/mwifiex/main.h | 10 + drivers/net/wireless/marvell/mwifiex/scan.c | 261 +++++++++++++++++++++ drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 4 + drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c | 3 + drivers/net/wireless/marvell/mwifiex/sta_event.c | 7 + drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 7 + 10 files changed, 493 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index e7adef72c05f..c27c6cc5f93e 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -1962,6 +1962,9 @@ mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + if (!mwifiex_stop_bg_scan(priv)) + cfg80211_sched_scan_stopped_rtnl(priv->wdev.wiphy); + if (mwifiex_deauthenticate(priv, NULL)) return -EFAULT; @@ -2217,6 +2220,9 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, "info: Trying to associate to %s and bssid %pM\n", (char *)sme->ssid, sme->bssid); + if (!mwifiex_stop_bg_scan(priv)) + cfg80211_sched_scan_stopped_rtnl(priv->wdev.wiphy); + ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, priv->bss_mode, sme->channel, sme, 0); if (!ret) { @@ -2420,6 +2426,9 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, return -EBUSY; } + if (!mwifiex_stop_bg_scan(priv)) + cfg80211_sched_scan_stopped_rtnl(priv->wdev.wiphy); + user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL); if (!user_scan_cfg) return -ENOMEM; @@ -2487,6 +2496,121 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, return 0; } +/* CFG802.11 operation handler for sched_scan_start. + * + * This function issues a bgscan config request to the firmware based upon + * the user specified sched_scan configuration. On successful completion, + * firmware will generate BGSCAN_REPORT event, driver should issue bgscan + * query command to get sched_scan results from firmware. + */ +static int +mwifiex_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_sched_scan_request *request) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + int i, offset; + struct ieee80211_channel *chan; + struct mwifiex_bg_scan_cfg *bgscan_cfg; + struct ieee_types_header *ie; + + if (!request || (!request->n_ssids && !request->n_match_sets)) { + wiphy_err(wiphy, "%s : Invalid Sched_scan parameters", + __func__); + return -EINVAL; + } + + wiphy_info(wiphy, "sched_scan start : n_ssids=%d n_match_sets=%d ", + request->n_ssids, request->n_match_sets); + wiphy_info(wiphy, "n_channels=%d interval=%d ie_len=%d\n", + request->n_channels, request->scan_plans->interval, + (int)request->ie_len); + + bgscan_cfg = kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL); + if (!bgscan_cfg) + return -ENOMEM; + + if (priv->scan_request || priv->scan_aborting) + bgscan_cfg->start_later = true; + + bgscan_cfg->num_ssids = request->n_match_sets; + bgscan_cfg->ssid_list = request->match_sets; + + if (request->ie && request->ie_len) { + offset = 0; + for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) { + if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR) + continue; + priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_BGSCAN; + ie = (struct ieee_types_header *)(request->ie + offset); + memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len); + offset += sizeof(*ie) + ie->len; + + if (offset >= request->ie_len) + break; + } + } + + for (i = 0; i < min_t(u32, request->n_channels, + MWIFIEX_BG_SCAN_CHAN_MAX); i++) { + chan = request->channels[i]; + bgscan_cfg->chan_list[i].chan_number = chan->hw_value; + bgscan_cfg->chan_list[i].radio_type = chan->band; + + if ((chan->flags & IEEE80211_CHAN_NO_IR) || !request->n_ssids) + bgscan_cfg->chan_list[i].scan_type = + MWIFIEX_SCAN_TYPE_PASSIVE; + else + bgscan_cfg->chan_list[i].scan_type = + MWIFIEX_SCAN_TYPE_ACTIVE; + + bgscan_cfg->chan_list[i].scan_time = 0; + } + + bgscan_cfg->chan_per_scan = min_t(u32, request->n_channels, + MWIFIEX_BG_SCAN_CHAN_MAX); + + /* Use at least 15 second for per scan cycle */ + bgscan_cfg->scan_interval = (request->scan_plans->interval > + MWIFIEX_BGSCAN_INTERVAL) ? + request->scan_plans->interval : + MWIFIEX_BGSCAN_INTERVAL; + + bgscan_cfg->repeat_count = MWIFIEX_BGSCAN_REPEAT_COUNT; + bgscan_cfg->report_condition = MWIFIEX_BGSCAN_SSID_MATCH | + MWIFIEX_BGSCAN_WAIT_ALL_CHAN_DONE; + bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA; + bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET; + bgscan_cfg->enable = true; + + if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG, + HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) { + kfree(bgscan_cfg); + return -EFAULT; + } + + priv->sched_scanning = true; + + kfree(bgscan_cfg); + return 0; +} + +/* CFG802.11 operation handler for sched_scan_stop. + * + * This function issues a bgscan config command to disable + * previous bgscan configuration in the firmware + */ +static int mwifiex_cfg80211_sched_scan_stop(struct wiphy *wiphy, + struct net_device *dev) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + + wiphy_info(wiphy, "sched scan stop!"); + mwifiex_stop_bg_scan(priv); + + return 0; +} + static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info, struct mwifiex_private *priv) { @@ -2848,6 +2972,9 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) mwifiex_dev_debugfs_remove(priv); #endif + if (priv->sched_scanning) + priv->sched_scanning = false; + mwifiex_stop_net_dev_queue(priv->netdev, adapter); skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) @@ -3701,6 +3828,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, .set_antenna = mwifiex_cfg80211_set_antenna, .del_station = mwifiex_cfg80211_del_station, + .sched_scan_start = mwifiex_cfg80211_sched_scan_start, + .sched_scan_stop = mwifiex_cfg80211_sched_scan_stop, #ifdef CONFIG_PM .suspend = mwifiex_cfg80211_suspend, .resume = mwifiex_cfg80211_resume, @@ -3829,6 +3958,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | WIPHY_FLAG_AP_UAPSD | + WIPHY_FLAG_SUPPORTS_SCHED_SCAN | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_HAS_CHANNEL_SWITCH | WIPHY_FLAG_PS_ON_BY_DEFAULT; @@ -3847,6 +3977,10 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; + wiphy->max_sched_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH; + wiphy->max_sched_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; + wiphy->max_match_sets = MWIFIEX_MAX_SSID_LIST_LENGTH; + wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1; wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1; diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 426e76ade30c..07bdc2a96b8a 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -144,6 +144,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18) #define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) #define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) +#define TLV_TYPE_BGSCAN_START_LATER (PROPRIETARY_TLV_BASE_ID + 30) #define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) #define TLV_TYPE_STA_MAC_ADDR (PROPRIETARY_TLV_BASE_ID + 32) #define TLV_TYPE_BSSID (PROPRIETARY_TLV_BASE_ID + 35) @@ -177,6 +178,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define TLV_TYPE_TX_PAUSE (PROPRIETARY_TLV_BASE_ID + 148) #define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 154) #define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 156) +#define TLV_TYPE_REPEAT_COUNT (PROPRIETARY_TLV_BASE_ID + 176) #define TLV_TYPE_MULTI_CHAN_INFO (PROPRIETARY_TLV_BASE_ID + 183) #define TLV_TYPE_MC_GROUP_INFO (PROPRIETARY_TLV_BASE_ID + 184) #define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194) @@ -331,6 +333,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define HostCmd_CMD_802_11_MAC_ADDRESS 0x004D #define HostCmd_CMD_802_11D_DOMAIN_INFO 0x005b #define HostCmd_CMD_802_11_KEY_MATERIAL 0x005e +#define HostCmd_CMD_802_11_BG_SCAN_CONFIG 0x006b #define HostCmd_CMD_802_11_BG_SCAN_QUERY 0x006c #define HostCmd_CMD_WMM_GET_STATUS 0x0071 #define HostCmd_CMD_802_11_SUBSCRIBE_EVENT 0x0075 @@ -523,6 +526,7 @@ enum P2P_MODES { #define EVENT_CHANNEL_REPORT_RDY 0x00000054 #define EVENT_TX_DATA_PAUSE 0x00000055 #define EVENT_EXT_SCAN_REPORT 0x00000058 +#define EVENT_BG_SCAN_STOPPED 0x00000065 #define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f #define EVENT_MULTI_CHAN_INFO 0x0000006a #define EVENT_TX_STATUS_REPORT 0x00000074 @@ -733,6 +737,16 @@ struct mwifiex_ie_types_num_probes { __le16 num_probes; } __packed; +struct mwifiex_ie_types_repeat_count { + struct mwifiex_ie_types_header header; + __le16 repeat_count; +} __packed; + +struct mwifiex_ie_types_bgscan_start_later { + struct mwifiex_ie_types_header header; + __le16 start_later; +} __packed; + struct mwifiex_ie_types_scan_chan_gap { struct mwifiex_ie_types_header header; /* time gap in TUs to be used between two consecutive channels scan */ @@ -1425,6 +1439,36 @@ struct mwifiex_user_scan_cfg { u16 scan_chan_gap; } __packed; +#define MWIFIEX_BG_SCAN_CHAN_MAX 38 +#define MWIFIEX_BSS_MODE_INFRA 1 +#define MWIFIEX_BGSCAN_ACT_GET 0x0000 +#define MWIFIEX_BGSCAN_ACT_SET 0x0001 +#define MWIFIEX_BGSCAN_ACT_SET_ALL 0xff01 +/** ssid match */ +#define MWIFIEX_BGSCAN_SSID_MATCH 0x0001 +/** ssid match and RSSI exceeded */ +#define MWIFIEX_BGSCAN_SSID_RSSI_MATCH 0x0004 +/**wait for all channel scan to complete to report scan result*/ +#define MWIFIEX_BGSCAN_WAIT_ALL_CHAN_DONE 0x80000000 + +struct mwifiex_bg_scan_cfg { + u16 action; + u8 enable; + u8 bss_type; + u8 chan_per_scan; + u32 scan_interval; + u32 report_condition; + u8 num_probes; + u8 rssi_threshold; + u8 snr_threshold; + u16 repeat_count; + u16 start_later; + struct cfg80211_match_set *ssid_list; + u8 num_ssids; + struct mwifiex_user_scan_chan chan_list[MWIFIEX_BG_SCAN_CHAN_MAX]; + u16 scan_chan_gap; +} __packed; + struct ie_body { u8 grp_key_oui[4]; u8 ptk_cnt[2]; @@ -1470,6 +1514,20 @@ struct mwifiex_ie_types_bss_scan_info { __le64 tsf; } __packed; +struct host_cmd_ds_802_11_bg_scan_config { + __le16 action; + u8 enable; + u8 bss_type; + u8 chan_per_scan; + u8 reserved; + __le16 reserved1; + __le32 scan_interval; + __le32 reserved2; + __le32 report_condition; + __le16 reserved3; + u8 tlv[0]; +} __packed; + struct host_cmd_ds_802_11_bg_scan_query { u8 flush; } __packed; @@ -2124,6 +2182,7 @@ struct host_cmd_ds_command { struct host_cmd_ds_802_11_scan scan; struct host_cmd_ds_802_11_scan_ext ext_scan; struct host_cmd_ds_802_11_scan_rsp scan_resp; + struct host_cmd_ds_802_11_bg_scan_config bg_scan_config; struct host_cmd_ds_802_11_bg_scan_query bg_scan_query; struct host_cmd_ds_802_11_bg_scan_query_rsp bg_scan_query_resp; struct host_cmd_ds_802_11_associate associate; diff --git a/drivers/net/wireless/marvell/mwifiex/ioctl.h b/drivers/net/wireless/marvell/mwifiex/ioctl.h index 4f0174c64946..6333b163acef 100644 --- a/drivers/net/wireless/marvell/mwifiex/ioctl.h +++ b/drivers/net/wireless/marvell/mwifiex/ioctl.h @@ -414,6 +414,7 @@ struct mwifiex_ds_mef_cfg { #define MWIFIEX_VSIE_MASK_SCAN 0x01 #define MWIFIEX_VSIE_MASK_ASSOC 0x02 #define MWIFIEX_VSIE_MASK_ADHOC 0x04 +#define MWIFIEX_VSIE_MASK_BGSCAN 0x08 enum { MWIFIEX_FUNC_INIT = 1, diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index 79c16de8743e..a99b72bbde51 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -746,6 +746,13 @@ int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb) mwifiex_queue_main_work(priv->adapter); + if (priv->sched_scanning) { + mwifiex_dbg(priv->adapter, INFO, + "aborting bgscan on ndo_stop\n"); + mwifiex_stop_bg_scan(priv); + cfg80211_sched_scan_stopped(priv->wdev.wiphy); + } + return 0; } diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 35ab052c8a36..5f5bcf8b9fc9 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -198,6 +198,11 @@ do { \ buf, len, false); \ } while (0) +/** Min BGSCAN interval 15 second */ +#define MWIFIEX_BGSCAN_INTERVAL 15000 +/** default repeat count */ +#define MWIFIEX_BGSCAN_REPEAT_COUNT 6 + struct mwifiex_dbg { u32 num_cmd_host_to_card_failure; u32 num_cmd_sleep_cfm_host_to_card_failure; @@ -641,6 +646,7 @@ struct mwifiex_private { u32 mgmt_frame_mask; struct mwifiex_roc_cfg roc_cfg; bool scan_aborting; + u8 sched_scanning; u8 csa_chan; unsigned long csa_expire_time; u8 del_list_idx; @@ -1198,6 +1204,10 @@ int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv, struct host_cmd_ds_command *resp); int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv, void *buf); +int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf); +int mwifiex_stop_bg_scan(struct mwifiex_private *priv); /* * This function checks if the queuing is RA based or not. diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index c20017ced566..d4e214385f54 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -547,6 +547,61 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv, return chan_idx; } +/* This function creates a channel list tlv for bgscan config, based + * on region/band information. + */ +static int +mwifiex_bgscan_create_channel_list(struct mwifiex_private *priv, + const struct mwifiex_bg_scan_cfg + *bgscan_cfg_in, + struct mwifiex_chan_scan_param_set + *scan_chan_list) +{ + enum ieee80211_band band; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + struct mwifiex_adapter *adapter = priv->adapter; + int chan_idx = 0, i; + + for (band = 0; (band < IEEE80211_NUM_BANDS); band++) { + if (!priv->wdev.wiphy->bands[band]) + continue; + + sband = priv->wdev.wiphy->bands[band]; + + for (i = 0; (i < sband->n_channels) ; i++) { + ch = &sband->channels[i]; + if (ch->flags & IEEE80211_CHAN_DISABLED) + continue; + scan_chan_list[chan_idx].radio_type = band; + + if (bgscan_cfg_in->chan_list[0].scan_time) + scan_chan_list[chan_idx].max_scan_time = + cpu_to_le16((u16)bgscan_cfg_in-> + chan_list[0].scan_time); + else if (ch->flags & IEEE80211_CHAN_NO_IR) + scan_chan_list[chan_idx].max_scan_time = + cpu_to_le16(adapter->passive_scan_time); + else + scan_chan_list[chan_idx].max_scan_time = + cpu_to_le16(adapter-> + specific_scan_time); + + if (ch->flags & IEEE80211_CHAN_NO_IR) + scan_chan_list[chan_idx].chan_scan_mode_bitmap + |= MWIFIEX_PASSIVE_SCAN; + else + scan_chan_list[chan_idx].chan_scan_mode_bitmap + &= ~MWIFIEX_PASSIVE_SCAN; + + scan_chan_list[chan_idx].chan_number = + (u32)ch->hw_value; + chan_idx++; + } + } + return chan_idx; +} + /* This function appends rate TLV to scan config command. */ static int mwifiex_append_rate_tlv(struct mwifiex_private *priv, @@ -2155,6 +2210,212 @@ int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, return 0; } +/* This function prepares an background scan config command to be sent + * to the firmware + */ +int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf) +{ + struct host_cmd_ds_802_11_bg_scan_config *bgscan_config = + &cmd->params.bg_scan_config; + struct mwifiex_bg_scan_cfg *bgscan_cfg_in = data_buf; + u8 *tlv_pos = bgscan_config->tlv; + u8 num_probes; + u32 ssid_len, chan_idx, scan_type, scan_dur, chan_num; + int i; + struct mwifiex_ie_types_num_probes *num_probes_tlv; + struct mwifiex_ie_types_repeat_count *repeat_count_tlv; + struct mwifiex_ie_types_bgscan_start_later *start_later_tlv; + struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; + struct mwifiex_ie_types_chan_list_param_set *chan_list_tlv; + struct mwifiex_chan_scan_param_set *temp_chan; + + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG); + cmd->size = cpu_to_le16(sizeof(*bgscan_config) + S_DS_GEN); + + bgscan_config->action = cpu_to_le16(bgscan_cfg_in->action); + bgscan_config->enable = bgscan_cfg_in->enable; + bgscan_config->bss_type = bgscan_cfg_in->bss_type; + bgscan_config->scan_interval = + cpu_to_le32(bgscan_cfg_in->scan_interval); + bgscan_config->report_condition = + cpu_to_le32(bgscan_cfg_in->report_condition); + + /* stop sched scan */ + if (!bgscan_config->enable) + return 0; + + bgscan_config->chan_per_scan = bgscan_cfg_in->chan_per_scan; + + num_probes = (bgscan_cfg_in->num_probes ? bgscan_cfg_in-> + num_probes : priv->adapter->scan_probes); + + if (num_probes) { + num_probes_tlv = (struct mwifiex_ie_types_num_probes *)tlv_pos; + num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES); + num_probes_tlv->header.len = + cpu_to_le16(sizeof(num_probes_tlv->num_probes)); + num_probes_tlv->num_probes = cpu_to_le16((u16)num_probes); + + tlv_pos += sizeof(num_probes_tlv->header) + + le16_to_cpu(num_probes_tlv->header.len); + } + + if (bgscan_cfg_in->repeat_count) { + repeat_count_tlv = + (struct mwifiex_ie_types_repeat_count *)tlv_pos; + repeat_count_tlv->header.type = + cpu_to_le16(TLV_TYPE_REPEAT_COUNT); + repeat_count_tlv->header.len = + cpu_to_le16(sizeof(repeat_count_tlv->repeat_count)); + repeat_count_tlv->repeat_count = + cpu_to_le16(bgscan_cfg_in->repeat_count); + + tlv_pos += sizeof(repeat_count_tlv->header) + + le16_to_cpu(repeat_count_tlv->header.len); + } + + for (i = 0; i < bgscan_cfg_in->num_ssids; i++) { + ssid_len = bgscan_cfg_in->ssid_list[i].ssid.ssid_len; + + wildcard_ssid_tlv = + (struct mwifiex_ie_types_wildcard_ssid_params *)tlv_pos; + wildcard_ssid_tlv->header.type = + cpu_to_le16(TLV_TYPE_WILDCARDSSID); + wildcard_ssid_tlv->header.len = cpu_to_le16( + (u16)(ssid_len + sizeof(wildcard_ssid_tlv-> + max_ssid_length))); + + /* max_ssid_length = 0 tells firmware to perform + * specific scan for the SSID filled, whereas + * max_ssid_length = IEEE80211_MAX_SSID_LEN is for + * wildcard scan. + */ + if (ssid_len) + wildcard_ssid_tlv->max_ssid_length = 0; + else + wildcard_ssid_tlv->max_ssid_length = + IEEE80211_MAX_SSID_LEN; + + memcpy(wildcard_ssid_tlv->ssid, + bgscan_cfg_in->ssid_list[i].ssid.ssid, ssid_len); + + tlv_pos += (sizeof(wildcard_ssid_tlv->header) + + le16_to_cpu(wildcard_ssid_tlv->header.len)); + } + + chan_list_tlv = (struct mwifiex_ie_types_chan_list_param_set *)tlv_pos; + + if (bgscan_cfg_in->chan_list[0].chan_number) { + dev_dbg(priv->adapter->dev, "info: bgscan: Using supplied channel list\n"); + + chan_list_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); + + for (chan_idx = 0; + chan_idx < MWIFIEX_BG_SCAN_CHAN_MAX && + bgscan_cfg_in->chan_list[chan_idx].chan_number; + chan_idx++) { + temp_chan = chan_list_tlv->chan_scan_param + chan_idx; + + /* Increment the TLV header length by size appended */ + le16_add_cpu(&chan_list_tlv->header.len, + sizeof(chan_list_tlv->chan_scan_param)); + + temp_chan->chan_number = + bgscan_cfg_in->chan_list[chan_idx].chan_number; + temp_chan->radio_type = + bgscan_cfg_in->chan_list[chan_idx].radio_type; + + scan_type = + bgscan_cfg_in->chan_list[chan_idx].scan_type; + + if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) + temp_chan->chan_scan_mode_bitmap + |= MWIFIEX_PASSIVE_SCAN; + else + temp_chan->chan_scan_mode_bitmap + &= ~MWIFIEX_PASSIVE_SCAN; + + if (bgscan_cfg_in->chan_list[chan_idx].scan_time) { + scan_dur = (u16)bgscan_cfg_in-> + chan_list[chan_idx].scan_time; + } else { + scan_dur = (scan_type == + MWIFIEX_SCAN_TYPE_PASSIVE) ? + priv->adapter->passive_scan_time : + priv->adapter->specific_scan_time; + } + + temp_chan->min_scan_time = cpu_to_le16(scan_dur); + temp_chan->max_scan_time = cpu_to_le16(scan_dur); + } + } else { + dev_dbg(priv->adapter->dev, + "info: bgscan: Creating full region channel list\n"); + chan_num = + mwifiex_bgscan_create_channel_list(priv, bgscan_cfg_in, + chan_list_tlv-> + chan_scan_param); + le16_add_cpu(&chan_list_tlv->header.len, + chan_num * + sizeof(chan_list_tlv->chan_scan_param[0])); + } + + tlv_pos += (sizeof(chan_list_tlv->header) + + le16_to_cpu(chan_list_tlv->header.len)); + + if (bgscan_cfg_in->start_later) { + start_later_tlv = + (struct mwifiex_ie_types_bgscan_start_later *)tlv_pos; + start_later_tlv->header.type = + cpu_to_le16(TLV_TYPE_BGSCAN_START_LATER); + start_later_tlv->header.len = + cpu_to_le16(sizeof(start_later_tlv->start_later)); + start_later_tlv->start_later = + cpu_to_le16(bgscan_cfg_in->start_later); + + tlv_pos += sizeof(start_later_tlv->header) + + le16_to_cpu(start_later_tlv->header.len); + } + + /* Append vendor specific IE TLV */ + mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_BGSCAN, &tlv_pos); + + le16_add_cpu(&cmd->size, tlv_pos - bgscan_config->tlv); + + return 0; +} + +int mwifiex_stop_bg_scan(struct mwifiex_private *priv) +{ + struct mwifiex_bg_scan_cfg *bgscan_cfg; + + if (!priv->sched_scanning) { + dev_dbg(priv->adapter->dev, "bgscan already stopped!\n"); + return 0; + } + + bgscan_cfg = kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL); + if (!bgscan_cfg) + return -ENOMEM; + + bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA; + bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET; + bgscan_cfg->enable = false; + + if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG, + HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) { + kfree(bgscan_cfg); + return -EFAULT; + } + + kfree(bgscan_cfg); + priv->sched_scanning = false; + + return 0; +} + static void mwifiex_update_chan_statistics(struct mwifiex_private *priv, struct mwifiex_ietypes_chanstats *tlv_stat) diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c index e486867a4c67..60f3ded747c9 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c @@ -1873,6 +1873,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, case HostCmd_CMD_802_11_SCAN: ret = mwifiex_cmd_802_11_scan(cmd_ptr, data_buf); break; + case HostCmd_CMD_802_11_BG_SCAN_CONFIG: + ret = mwifiex_cmd_802_11_bg_scan_config(priv, cmd_ptr, + data_buf); + break; case HostCmd_CMD_802_11_BG_SCAN_QUERY: ret = mwifiex_cmd_802_11_bg_scan_query(cmd_ptr); break; diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c index 9ac7aa2431b4..4b23d3b95a20 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c @@ -1076,9 +1076,12 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, break; case HostCmd_CMD_802_11_BG_SCAN_QUERY: ret = mwifiex_ret_802_11_scan(priv, resp); + cfg80211_sched_scan_results(priv->wdev.wiphy); mwifiex_dbg(adapter, CMD, "info: CMD_RESP: BG_SCAN result is ready!\n"); break; + case HostCmd_CMD_802_11_BG_SCAN_CONFIG: + break; case HostCmd_CMD_TXPWR_CFG: ret = mwifiex_ret_tx_power_cfg(priv, resp); break; diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c index 23bae87d4d3d..fd8061c73091 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c @@ -688,6 +688,13 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) HostCmd_ACT_GEN_GET, 0, NULL, false); break; + case EVENT_BG_SCAN_STOPPED: + dev_dbg(adapter->dev, "event: BGS_STOPPED\n"); + cfg80211_sched_scan_stopped(priv->wdev.wiphy); + if (priv->sched_scanning) + priv->sched_scanning = false; + break; + case EVENT_PORT_RELEASE: mwifiex_dbg(adapter, EVENT, "event: PORT RELEASE\n"); priv->port_open = true; diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index 210b257aad6b..2cc1a32691bd 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -504,6 +504,13 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) } } + priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); + if (priv && priv->sched_scanning) { + dev_dbg(adapter->dev, "aborting bgscan!\n"); + mwifiex_stop_bg_scan(priv); + cfg80211_sched_scan_stopped(priv->wdev.wiphy); + } + if (adapter->hs_activated) { mwifiex_dbg(adapter, CMD, "cmd: HS Already activated\n"); -- cgit v1.2.3 From 5323b53d80fc17604b2c60b725af116827330b2c Mon Sep 17 00:00:00 2001 From: chunfan chen Date: Wed, 13 Jan 2016 01:26:53 -0800 Subject: mwifiex: add wowlan info messages This patch adds informative messages in wake up on magic packet, disconnect, pattern configuration paths. Signed-off-by: chunfan chen Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index c27c6cc5f93e..6d36d081e953 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3171,10 +3171,12 @@ static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv, sizeof(byte_seq)); mef_entry->filter[filt_num].filt_type = TYPE_EQ; - if (first_pat) + if (first_pat) { first_pat = false; - else + mwifiex_dbg(priv->adapter, INFO, "Wake on patterns\n"); + } else { mef_entry->filter[filt_num].filt_action = TYPE_AND; + } filt_num++; } @@ -3200,6 +3202,7 @@ static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv, mef_entry->filter[filt_num].offset = 56; mef_entry->filter[filt_num].filt_type = TYPE_EQ; mef_entry->filter[filt_num].filt_action = TYPE_OR; + mwifiex_dbg(priv->adapter, INFO, "Wake on magic packet\n"); } return ret; } @@ -3295,6 +3298,7 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, "Failed to set HS params\n"); return ret; } + mwifiex_dbg(priv->adapter, INFO, "Wake on device disconnect\n"); } return ret; -- cgit v1.2.3 From 7d7f07d8c5d35ebfb207650b0dbcf437dad76bab Mon Sep 17 00:00:00 2001 From: chunfan chen Date: Wed, 13 Jan 2016 01:26:54 -0800 Subject: mwifiex: add wowlan net-detect support This patch adds support for wakeup when configured network is detected. Signed-off-by: chunfan chen Signed-off-by: Amitkumar Karwar Signed-off-by: Xinming Hu Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 40 +++++++++++++++--------- drivers/net/wireless/marvell/mwifiex/fw.h | 2 ++ drivers/net/wireless/marvell/mwifiex/main.c | 7 +++++ drivers/net/wireless/marvell/mwifiex/main.h | 1 + drivers/net/wireless/marvell/mwifiex/scan.c | 34 ++++++++++++++++++++ drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 13 ++++++-- 6 files changed, 80 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 6d36d081e953..a1b8d89d399f 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3273,7 +3273,7 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); - if (!priv->media_connected) { + if (!priv->media_connected && !wowlan->nd_config) { mwifiex_dbg(adapter, ERROR, "Can not configure WOWLAN in disconnected state\n"); return 0; @@ -3285,22 +3285,32 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, return ret; } + memset(&hs_cfg, 0, sizeof(hs_cfg)); + hs_cfg.conditions = le32_to_cpu(adapter->hs_cfg.conditions); + + if (wowlan->nd_config) { + mwifiex_dbg(adapter, INFO, "Wake on net detect\n"); + hs_cfg.conditions |= HS_CFG_COND_MAC_EVENT; + mwifiex_cfg80211_sched_scan_start(wiphy, priv->netdev, + wowlan->nd_config); + } + if (wowlan->disconnect) { - memset(&hs_cfg, 0, sizeof(hs_cfg)); - hs_cfg.is_invoke_hostcmd = false; - hs_cfg.conditions = HS_CFG_COND_MAC_EVENT; - hs_cfg.gpio = adapter->hs_cfg.gpio; - hs_cfg.gap = adapter->hs_cfg.gap; - ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, - MWIFIEX_SYNC_CMD, &hs_cfg); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "Failed to set HS params\n"); - return ret; - } + hs_cfg.conditions |= HS_CFG_COND_MAC_EVENT; mwifiex_dbg(priv->adapter, INFO, "Wake on device disconnect\n"); } + hs_cfg.is_invoke_hostcmd = false; + hs_cfg.gpio = adapter->hs_cfg.gpio; + hs_cfg.gap = adapter->hs_cfg.gap; + ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, + MWIFIEX_SYNC_CMD, &hs_cfg); + if (ret) { + mwifiex_dbg(adapter, ERROR, + "Failed to set HS params\n"); + return ret; + } + return ret; } @@ -3853,11 +3863,13 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { #ifdef CONFIG_PM static const struct wiphy_wowlan_support mwifiex_wowlan_support = { - .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, + .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_NET_DETECT, .n_patterns = MWIFIEX_MEF_MAX_FILTERS, .pattern_min_len = 1, .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN, .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN, + .max_nd_match_sets = MWIFIEX_MAX_ND_MATCH_SETS, }; #endif diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 07bdc2a96b8a..81b491aac343 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -543,6 +543,8 @@ enum P2P_MODES { #define MWIFIEX_MAX_PATTERN_LEN 40 #define MWIFIEX_MAX_OFFSET_LEN 100 +#define MWIFIEX_MAX_ND_MATCH_SETS 10 + #define STACK_NBYTES 100 #define TYPE_DNUM 1 #define TYPE_BYTESEQ 2 diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index a99b72bbde51..3cfa94677a8e 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -132,6 +132,13 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter) } } + if (adapter->nd_info) { + for (i = 0 ; i < adapter->nd_info->n_matches ; i++) + kfree(adapter->nd_info->matches[i]); + kfree(adapter->nd_info); + adapter->nd_info = NULL; + } + vfree(adapter->chan_stats); kfree(adapter); return 0; diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 5f5bcf8b9fc9..bf9b24ae46fc 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -1002,6 +1002,7 @@ struct mwifiex_adapter { u8 active_scan_triggered; bool usb_mc_status; bool usb_mc_setup; + struct cfg80211_wowlan_nd_info *nd_info; }; void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter); diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index d4e214385f54..2702bd93f74d 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -2092,6 +2092,8 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, u8 is_bgscan_resp; __le64 fw_tsf = 0; u8 *radio_type; + struct cfg80211_wowlan_nd_match *pmatch; + struct cfg80211_sched_scan_request *nd_config = NULL; is_bgscan_resp = (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_BG_SCAN_QUERY); @@ -2154,6 +2156,21 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, (struct mwifiex_ie_types_data **) &chan_band_tlv); +#ifdef CONFIG_PM + if (priv->wdev.wiphy->wowlan_config) + nd_config = priv->wdev.wiphy->wowlan_config->nd_config; +#endif + + if (nd_config) { + adapter->nd_info = + kzalloc(sizeof(struct cfg80211_wowlan_nd_match) + + sizeof(struct cfg80211_wowlan_nd_match *) * + scan_rsp->number_of_sets, GFP_ATOMIC); + + if (adapter->nd_info) + adapter->nd_info->n_matches = scan_rsp->number_of_sets; + } + for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { /* * If the TSF TLV was appended to the scan results, save this @@ -2172,6 +2189,23 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, radio_type = NULL; } + if (chan_band_tlv && adapter->nd_info) { + adapter->nd_info->matches[idx] = + kzalloc(sizeof(*pmatch) + + sizeof(u32), GFP_ATOMIC); + + pmatch = adapter->nd_info->matches[idx]; + + if (!pmatch) { + memset(pmatch, 0, sizeof(*pmatch)); + if (chan_band_tlv) { + pmatch->n_channels = 1; + pmatch->channels[0] = + chan_band->chan_number; + } + } + } + ret = mwifiex_parse_single_response_buf(priv, &bss_info, &bytes_left, le64_to_cpu(fw_tsf), diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index 2cc1a32691bd..7277c24ee9aa 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -505,10 +505,17 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) } priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); + if (priv && priv->sched_scanning) { - dev_dbg(adapter->dev, "aborting bgscan!\n"); - mwifiex_stop_bg_scan(priv); - cfg80211_sched_scan_stopped(priv->wdev.wiphy); +#ifdef CONFIG_PM + if (!priv->wdev.wiphy->wowlan_config->nd_config) { +#endif + mwifiex_dbg(adapter, CMD, "aborting bgscan!\n"); + mwifiex_stop_bg_scan(priv); + cfg80211_sched_scan_stopped(priv->wdev.wiphy); +#ifdef CONFIG_PM + } +#endif } if (adapter->hs_activated) { -- cgit v1.2.3 From 8de00f1b1c7f37e523430efba8e4257b2761df7c Mon Sep 17 00:00:00 2001 From: chunfan chen Date: Wed, 13 Jan 2016 01:26:55 -0800 Subject: mwifiex: report wakeup reason to cfg80211 This patch adds code to report wakeup reason to cfg80211 when system is resumed. Signed-off-by: chunfan chen Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 58 ++++++++++++++++++++++ drivers/net/wireless/marvell/mwifiex/cmdevt.c | 13 +++++ drivers/net/wireless/marvell/mwifiex/fw.h | 20 ++++++++ drivers/net/wireless/marvell/mwifiex/ioctl.h | 4 ++ drivers/net/wireless/marvell/mwifiex/main.h | 6 +++ drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 19 +++++++ drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c | 3 ++ drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 16 ++++++ 8 files changed, 139 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index a1b8d89d399f..c80d9e2daa16 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3316,6 +3316,64 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, static int mwifiex_cfg80211_resume(struct wiphy *wiphy) { + struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); + struct mwifiex_private *priv = + mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); + struct mwifiex_ds_wakeup_reason wakeup_reason; + struct cfg80211_wowlan_wakeup wakeup_report; + int i; + + mwifiex_get_wakeup_reason(priv, HostCmd_ACT_GEN_GET, MWIFIEX_SYNC_CMD, + &wakeup_reason); + memset(&wakeup_report, 0, sizeof(struct cfg80211_wowlan_wakeup)); + + wakeup_report.pattern_idx = -1; + + switch (wakeup_reason.hs_wakeup_reason) { + case NO_HSWAKEUP_REASON: + break; + case BCAST_DATA_MATCHED: + break; + case MCAST_DATA_MATCHED: + break; + case UCAST_DATA_MATCHED: + break; + case MASKTABLE_EVENT_MATCHED: + break; + case NON_MASKABLE_EVENT_MATCHED: + if (wiphy->wowlan_config->disconnect) + wakeup_report.disconnect = true; + if (wiphy->wowlan_config->nd_config) + wakeup_report.net_detect = adapter->nd_info; + break; + case NON_MASKABLE_CONDITION_MATCHED: + break; + case MAGIC_PATTERN_MATCHED: + if (wiphy->wowlan_config->magic_pkt) + wakeup_report.magic_pkt = true; + if (wiphy->wowlan_config->n_patterns) + wakeup_report.pattern_idx = 1; + break; + case CONTROL_FRAME_MATCHED: + break; + case MANAGEMENT_FRAME_MATCHED: + break; + default: + break; + } + + if ((wakeup_reason.hs_wakeup_reason > 0) && + (wakeup_reason.hs_wakeup_reason <= 7)) + cfg80211_report_wowlan_wakeup(&priv->wdev, &wakeup_report, + GFP_KERNEL); + + if (adapter->nd_info) { + for (i = 0 ; i < adapter->nd_info->n_matches ; i++) + kfree(adapter->nd_info->matches[i]); + kfree(adapter->nd_info); + adapter->nd_info = NULL; + } + return 0; } diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c index cb25aa7e90db..a12adee776c6 100644 --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c @@ -1657,3 +1657,16 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, return 0; } + +/* This function handles the command response of hs wakeup reason + * command. + */ +int mwifiex_ret_wakeup_reason(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + struct host_cmd_ds_wakeup_reason *wakeup_reason) +{ + wakeup_reason->wakeup_reason = + resp->params.hs_wakeup_reason.wakeup_reason; + + return 0; +} diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 81b491aac343..d293e485189b 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -373,6 +373,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define HostCmd_CMD_MGMT_FRAME_REG 0x010c #define HostCmd_CMD_REMAIN_ON_CHAN 0x010d #define HostCmd_CMD_11AC_CFG 0x0112 +#define HostCmd_CMD_HS_WAKEUP_REASON 0x0116 #define HostCmd_CMD_TDLS_CONFIG 0x0100 #define HostCmd_CMD_MC_POLICY 0x0121 #define HostCmd_CMD_TDLS_OPER 0x0122 @@ -607,6 +608,20 @@ struct mwifiex_ie_types_data { #define MWIFIEX_RXPD_FLAGS_TDLS_PACKET 0x01 #define MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS 0x20 +enum HS_WAKEUP_REASON { + NO_HSWAKEUP_REASON = 0, + BCAST_DATA_MATCHED, + MCAST_DATA_MATCHED, + UCAST_DATA_MATCHED, + MASKTABLE_EVENT_MATCHED, + NON_MASKABLE_EVENT_MATCHED, + NON_MASKABLE_CONDITION_MATCHED, + MAGIC_PATTERN_MATCHED, + CONTROL_FRAME_MATCHED, + MANAGEMENT_FRAME_MATCHED, + RESERVED +}; + struct txpd { u8 bss_type; u8 bss_num; @@ -2159,6 +2174,10 @@ struct host_cmd_ds_robust_coex { __le16 reserved; } __packed; +struct host_cmd_ds_wakeup_reason { + u16 wakeup_reason; +} __packed; + struct host_cmd_ds_command { __le16 command; __le16 size; @@ -2231,6 +2250,7 @@ struct host_cmd_ds_command { struct host_cmd_sdio_sp_rx_aggr_cfg sdio_rx_aggr_cfg; struct host_cmd_ds_multi_chan_policy mc_policy; struct host_cmd_ds_robust_coex coex; + struct host_cmd_ds_wakeup_reason hs_wakeup_reason; } params; } __packed; diff --git a/drivers/net/wireless/marvell/mwifiex/ioctl.h b/drivers/net/wireless/marvell/mwifiex/ioctl.h index 6333b163acef..14cfa37deb00 100644 --- a/drivers/net/wireless/marvell/mwifiex/ioctl.h +++ b/drivers/net/wireless/marvell/mwifiex/ioctl.h @@ -271,6 +271,10 @@ struct mwifiex_ds_hs_cfg { u32 gap; }; +struct mwifiex_ds_wakeup_reason { + u16 hs_wakeup_reason; +}; + #define DEEP_SLEEP_ON 1 #define DEEP_SLEEP_OFF 0 #define DEEP_SLEEP_IDLE_TIME 100 diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index bf9b24ae46fc..c755be54cc83 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -1599,6 +1599,12 @@ void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter); void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter); void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags); void mwifiex_queue_main_work(struct mwifiex_adapter *adapter); +int mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action, + int cmd_type, + struct mwifiex_ds_wakeup_reason *wakeup_reason); +int mwifiex_ret_wakeup_reason(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + struct host_cmd_ds_wakeup_reason *wakeup_reason); void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter); void mwifiex_11n_delba(struct mwifiex_private *priv, int tid); int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy); diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c index 60f3ded747c9..30f152601c57 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c @@ -1813,6 +1813,22 @@ static int mwifiex_cmd_sdio_rx_aggr_cfg(struct host_cmd_ds_command *cmd, return 0; } +/* This function prepares command to get HS wakeup reason. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Ensuring correct endian-ness + */ +static int mwifiex_cmd_get_wakeup_reason(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd) +{ + cmd->command = cpu_to_le16(HostCmd_CMD_HS_WAKEUP_REASON); + cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_wakeup_reason) + + S_DS_GEN); + + return 0; +} + /* * This function prepares the commands before sending them to the firmware. * @@ -2067,6 +2083,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, ret = mwifiex_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action, data_buf); break; + case HostCmd_CMD_HS_WAKEUP_REASON: + ret = mwifiex_cmd_get_wakeup_reason(priv, cmd_ptr); + break; case HostCmd_CMD_MC_POLICY: ret = mwifiex_cmd_set_mc_policy(priv, cmd_ptr, cmd_action, data_buf); diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c index 4b23d3b95a20..d96523e10eb4 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c @@ -1236,6 +1236,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG: ret = mwifiex_ret_sdio_rx_aggr_cfg(priv, resp); break; + case HostCmd_CMD_HS_WAKEUP_REASON: + ret = mwifiex_ret_wakeup_reason(priv, resp, data_buf); + break; case HostCmd_CMD_TDLS_CONFIG: break; case HostCmd_CMD_ROBUST_COEX: diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index 7277c24ee9aa..5cbee58f8781 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -1465,3 +1465,19 @@ mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len) return 0; } + +/* This function get Host Sleep wake up reason. + * + */ +int mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action, + int cmd_type, + struct mwifiex_ds_wakeup_reason *wakeup_reason) +{ + int status = 0; + + status = mwifiex_send_cmd(priv, HostCmd_CMD_HS_WAKEUP_REASON, + HostCmd_ACT_GEN_GET, 0, wakeup_reason, + cmd_type == MWIFIEX_SYNC_CMD); + + return status; +} -- cgit v1.2.3 From fdcab083055d759325c8e0f8999d9e192417fc20 Mon Sep 17 00:00:00 2001 From: Ganapathi Bhat Date: Wed, 13 Jan 2016 01:26:56 -0800 Subject: mwifiex: add RSSI support for net-detect This patch adds support for waking up the device on finding better RSSI. Threshold RSSI value will be configured by application. Signed-off-by: Ganapathi Bhat Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 4 ++++ drivers/net/wireless/marvell/mwifiex/fw.h | 5 +++++ drivers/net/wireless/marvell/mwifiex/scan.c | 15 +++++++++++++++ 3 files changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index c80d9e2daa16..84615533986c 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -2582,6 +2582,10 @@ mwifiex_cfg80211_sched_scan_start(struct wiphy *wiphy, bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA; bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET; bgscan_cfg->enable = true; + if (request->min_rssi_thold != NL80211_SCAN_RSSI_THOLD_OFF) { + bgscan_cfg->report_condition |= MWIFIEX_BGSCAN_SSID_RSSI_MATCH; + bgscan_cfg->rssi_threshold = request->min_rssi_thold; + } if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG, HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) { diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index d293e485189b..4af916817bcd 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -759,6 +759,11 @@ struct mwifiex_ie_types_repeat_count { __le16 repeat_count; } __packed; +struct mwifiex_ie_types_min_rssi_threshold { + struct mwifiex_ie_types_header header; + __le16 rssi_threshold; +} __packed; + struct mwifiex_ie_types_bgscan_start_later { struct mwifiex_ie_types_header header; __le16 start_later; diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 2702bd93f74d..fc8d8ca67453 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -2260,6 +2260,7 @@ int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv, int i; struct mwifiex_ie_types_num_probes *num_probes_tlv; struct mwifiex_ie_types_repeat_count *repeat_count_tlv; + struct mwifiex_ie_types_min_rssi_threshold *rssi_threshold_tlv; struct mwifiex_ie_types_bgscan_start_later *start_later_tlv; struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; struct mwifiex_ie_types_chan_list_param_set *chan_list_tlv; @@ -2310,6 +2311,20 @@ int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv, le16_to_cpu(repeat_count_tlv->header.len); } + if (bgscan_cfg_in->rssi_threshold) { + rssi_threshold_tlv = + (struct mwifiex_ie_types_min_rssi_threshold *)tlv_pos; + rssi_threshold_tlv->header.type = + cpu_to_le16(TLV_TYPE_RSSI_LOW); + rssi_threshold_tlv->header.len = + cpu_to_le16(sizeof(rssi_threshold_tlv->rssi_threshold)); + rssi_threshold_tlv->rssi_threshold = + cpu_to_le16(bgscan_cfg_in->rssi_threshold); + + tlv_pos += sizeof(rssi_threshold_tlv->header) + + le16_to_cpu(rssi_threshold_tlv->header.len); + } + for (i = 0; i < bgscan_cfg_in->num_ssids; i++) { ssid_len = bgscan_cfg_in->ssid_list[i].ssid.ssid_len; -- cgit v1.2.3 From a92277bc3bfe7c41cac13ca4a7d5070033543732 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Wed, 13 Jan 2016 01:26:57 -0800 Subject: mwifiex: use SYNC flag for canceling host sleep Host sleep is cancelled in sdio resume() handler. Cfg80211's resume handler is immediately called after this. SYNC flag here ensures that host sleep handshake gets completed and we have valid "adapter->nd_config" before we report host wakeup reason in cfg80211's resume handler. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index 33771d3fd843..abf15dbdfe08 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -181,7 +181,7 @@ static int mwifiex_sdio_resume(struct device *dev) /* Disable Host Sleep */ mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), - MWIFIEX_ASYNC_CMD); + MWIFIEX_SYNC_CMD); return 0; } -- cgit v1.2.3 From 52795f6fdeb8a2b98373108ac2838c674bb2cbc4 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 27 Jan 2016 14:40:33 +0100 Subject: i2c: piix4: don't regress on bus names The I2C bus names are supposed to be stable as they can be used by userspace to uniquely identify a specific I2C bus. So restore the original names for all legacy (pre-SB800) devices. For SB800 devices and later, improve the names. "SDA" refers to the serial data pin of each SMBus port, it's an implementation detail the user doesn't need to know. Use "port" instead, which is easier to understand. Signed-off-by: Jean Delvare Reviewed-by: Mika Westerberg Tested-by: Christian Fetzer Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-piix4.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index f79a84ef1aa4..93f2895383ee 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -139,9 +139,9 @@ static const struct dmi_system_id piix4_dmi_ibm[] = { /* SB800 globals */ static DEFINE_MUTEX(piix4_mutex_sb800); static const char *piix4_main_port_names_sb800[PIIX4_MAX_ADAPTERS] = { - "SDA0", "SDA2", "SDA3", "SDA4" + " port 0", " port 2", " port 3", " port 4" }; -static const char *piix4_aux_port_name_sb800 = "SDA1"; +static const char *piix4_aux_port_name_sb800 = " port 1"; struct i2c_piix4_adapdata { unsigned short smba; @@ -660,7 +660,7 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, adap->dev.parent = &dev->dev; snprintf(adap->name, sizeof(adap->name), - "SMBus PIIX4 adapter %s at %04x", name, smba); + "SMBus PIIX4 adapter%s at %04x", name, smba); i2c_set_adapdata(adap, adapdata); @@ -712,11 +712,14 @@ error: static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) { int retval; + bool is_sb800 = false; if ((dev->vendor == PCI_VENDOR_ID_ATI && dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && dev->revision >= 0x40) || dev->vendor == PCI_VENDOR_ID_AMD) { + is_sb800 = true; + if (!request_region(SB800_PIIX4_SMB_IDX, 2, "smba_idx")) { dev_err(&dev->dev, "SMBus base address index region 0x%x already in use!\n", @@ -746,7 +749,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) return retval; /* Try to register main SMBus adapter, give up if we can't */ - retval = piix4_add_adapter(dev, retval, false, 0, "main", + retval = piix4_add_adapter(dev, retval, false, 0, "", &piix4_main_adapters[0]); if (retval < 0) return retval; @@ -774,7 +777,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) /* Try to add the aux adapter if it exists, * piix4_add_adapter will clean up if this fails */ piix4_add_adapter(dev, retval, false, 0, - piix4_aux_port_name_sb800, + is_sb800 ? piix4_aux_port_name_sb800 : "", &piix4_aux_adapter); } -- cgit v1.2.3 From 435b7be1d812cdbbad997f5279293770dff21abb Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 25 Jan 2016 21:15:43 +0800 Subject: clk: sunxi: factors: Support custom formulas Some clocks cannot be modelled using the standard factors clk formula, such as clocks with special pre-dividers on one parent, or clocks with all power-of-two dividers. Add support for a custom .recalc callback for factors clk. Also pass the current parent index to the .get_factor and .recalc callbacks. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-factors.c | 31 +++++++++++++++++++++++++++++-- drivers/clk/sunxi/clk-factors.h | 3 +++ 2 files changed, 32 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index 4a8e36a53287..2927b09d5e0d 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c @@ -63,6 +63,26 @@ static unsigned long clk_factors_recalc_rate(struct clk_hw *hw, if (config->pwidth != SUNXI_FACTORS_NOT_APPLICABLE) p = FACTOR_GET(config->pshift, config->pwidth, reg); + if (factors->recalc) { + struct factors_request factors_req = { + .parent_rate = parent_rate, + .n = n, + .k = k, + .m = m, + .p = p, + }; + + /* get mux details from mux clk structure */ + if (factors->mux) + factors_req.parent_index = + (reg >> factors->mux->shift) & + factors->mux->mask; + + factors->recalc(&factors_req); + + return factors_req.rate; + } + /* Calculate the rate */ rate = (parent_rate * (n + config->n_start) * (k + 1) >> p) / (m + 1); @@ -87,6 +107,7 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate, static int clk_factors_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { + struct clk_factors *factors = to_clk_factors(hw); struct clk_hw *parent, *best_parent = NULL; int i, num_parents; unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0; @@ -94,6 +115,10 @@ static int clk_factors_determine_rate(struct clk_hw *hw, /* find the parent that can help provide the fastest rate <= rate */ num_parents = clk_hw_get_num_parents(hw); for (i = 0; i < num_parents; i++) { + struct factors_request factors_req = { + .rate = req->rate, + .parent_index = i, + }; parent = clk_hw_get_parent_by_index(hw, i); if (!parent) continue; @@ -102,8 +127,9 @@ static int clk_factors_determine_rate(struct clk_hw *hw, else parent_rate = clk_hw_get_rate(parent); - child_rate = clk_factors_round_rate(hw, req->rate, - &parent_rate); + factors_req.parent_rate = parent_rate; + factors->get_factors(&factors_req); + child_rate = factors_req.rate; if (child_rate <= req->rate && child_rate > best_child_rate) { best_parent = parent; @@ -202,6 +228,7 @@ struct clk *sunxi_factors_register(struct device_node *node, factors->reg = reg; factors->config = data->table; factors->get_factors = data->getter; + factors->recalc = data->recalc; factors->lock = lock; /* Add a gate if this factor clock can be gated */ diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h index f09d7c214533..a44a865a6b9e 100644 --- a/drivers/clk/sunxi/clk-factors.h +++ b/drivers/clk/sunxi/clk-factors.h @@ -22,6 +22,7 @@ struct clk_factors_config { struct factors_request { unsigned long rate; unsigned long parent_rate; + u8 parent_index; u8 n; u8 k; u8 m; @@ -34,6 +35,7 @@ struct factors_data { int muxmask; const struct clk_factors_config *table; void (*getter)(struct factors_request *req); + void (*recalc)(struct factors_request *req); const char *name; }; @@ -42,6 +44,7 @@ struct clk_factors { void __iomem *reg; const struct clk_factors_config *config; void (*get_factors)(struct factors_request *req); + void (*recalc)(struct factors_request *req); spinlock_t *lock; /* for cleanup */ struct clk_mux *mux; -- cgit v1.2.3 From 50d6ea47bab46645f28c439d9d8fb4840e10b486 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 25 Jan 2016 21:15:44 +0800 Subject: clk: sunxi: factors: Drop round_rate from clk ops The common clock framework requires either determine_rate or round_rate to be implemented. We use determine_rate so we can pass the parent index to the get_factors callback. This cannot be done easily with round_rate, so just drop it. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-factors.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index 2927b09d5e0d..6e97f46c0c37 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c @@ -89,21 +89,6 @@ static unsigned long clk_factors_recalc_rate(struct clk_hw *hw, return rate; } -static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - struct clk_factors *factors = to_clk_factors(hw); - struct factors_request req = { - .rate = rate, - .parent_rate = *parent_rate, - }; - - factors->get_factors(&req); - - - return rate; -} - static int clk_factors_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { @@ -189,7 +174,6 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, static const struct clk_ops clk_factors_ops = { .determine_rate = clk_factors_determine_rate, .recalc_rate = clk_factors_recalc_rate, - .round_rate = clk_factors_round_rate, .set_rate = clk_factors_set_rate, }; -- cgit v1.2.3 From a78bb35552a800949b2bf68f372d3d6ccabdd790 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 25 Jan 2016 21:15:45 +0800 Subject: clk: sunxi: rewrite sun6i-a31-ahb1-clk using factors clk with custom recalc The factors clk implementation has been extended to support custom recalc callbacks to support clocks that use one factor for certain parents only, like a pre-divider. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-sunxi.c | 291 ++++++++++++------------------------------ 1 file changed, 83 insertions(+), 208 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index a57c36c104dc..da15f2b12ab2 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -28,214 +28,6 @@ static DEFINE_SPINLOCK(clk_lock); -/** - * sun6i_a31_ahb1_clk_setup() - Setup function for a31 ahb1 composite clk - */ - -#define SUN6I_AHB1_MAX_PARENTS 4 -#define SUN6I_AHB1_MUX_PARENT_PLL6 3 -#define SUN6I_AHB1_MUX_SHIFT 12 -/* un-shifted mask is what mux_clk expects */ -#define SUN6I_AHB1_MUX_MASK 0x3 -#define SUN6I_AHB1_MUX_GET_PARENT(reg) ((reg >> SUN6I_AHB1_MUX_SHIFT) & \ - SUN6I_AHB1_MUX_MASK) - -#define SUN6I_AHB1_DIV_SHIFT 4 -#define SUN6I_AHB1_DIV_MASK (0x3 << SUN6I_AHB1_DIV_SHIFT) -#define SUN6I_AHB1_DIV_GET(reg) ((reg & SUN6I_AHB1_DIV_MASK) >> \ - SUN6I_AHB1_DIV_SHIFT) -#define SUN6I_AHB1_DIV_SET(reg, div) ((reg & ~SUN6I_AHB1_DIV_MASK) | \ - (div << SUN6I_AHB1_DIV_SHIFT)) -#define SUN6I_AHB1_PLL6_DIV_SHIFT 6 -#define SUN6I_AHB1_PLL6_DIV_MASK (0x3 << SUN6I_AHB1_PLL6_DIV_SHIFT) -#define SUN6I_AHB1_PLL6_DIV_GET(reg) ((reg & SUN6I_AHB1_PLL6_DIV_MASK) >> \ - SUN6I_AHB1_PLL6_DIV_SHIFT) -#define SUN6I_AHB1_PLL6_DIV_SET(reg, div) ((reg & ~SUN6I_AHB1_PLL6_DIV_MASK) | \ - (div << SUN6I_AHB1_PLL6_DIV_SHIFT)) - -struct sun6i_ahb1_clk { - struct clk_hw hw; - void __iomem *reg; -}; - -#define to_sun6i_ahb1_clk(_hw) container_of(_hw, struct sun6i_ahb1_clk, hw) - -static unsigned long sun6i_ahb1_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct sun6i_ahb1_clk *ahb1 = to_sun6i_ahb1_clk(hw); - unsigned long rate; - u32 reg; - - /* Fetch the register value */ - reg = readl(ahb1->reg); - - /* apply pre-divider first if parent is pll6 */ - if (SUN6I_AHB1_MUX_GET_PARENT(reg) == SUN6I_AHB1_MUX_PARENT_PLL6) - parent_rate /= SUN6I_AHB1_PLL6_DIV_GET(reg) + 1; - - /* clk divider */ - rate = parent_rate >> SUN6I_AHB1_DIV_GET(reg); - - return rate; -} - -static long sun6i_ahb1_clk_round(unsigned long rate, u8 *divp, u8 *pre_divp, - u8 parent, unsigned long parent_rate) -{ - u8 div, calcp, calcm = 1; - - /* - * clock can only divide, so we will never be able to achieve - * frequencies higher than the parent frequency - */ - if (parent_rate && rate > parent_rate) - rate = parent_rate; - - div = DIV_ROUND_UP(parent_rate, rate); - - /* calculate pre-divider if parent is pll6 */ - if (parent == SUN6I_AHB1_MUX_PARENT_PLL6) { - if (div < 4) - calcp = 0; - else if (div / 2 < 4) - calcp = 1; - else if (div / 4 < 4) - calcp = 2; - else - calcp = 3; - - calcm = DIV_ROUND_UP(div, 1 << calcp); - } else { - calcp = __roundup_pow_of_two(div); - calcp = calcp > 3 ? 3 : calcp; - } - - /* we were asked to pass back divider values */ - if (divp) { - *divp = calcp; - *pre_divp = calcm - 1; - } - - return (parent_rate / calcm) >> calcp; -} - -static int sun6i_ahb1_clk_determine_rate(struct clk_hw *hw, - struct clk_rate_request *req) -{ - struct clk_hw *parent, *best_parent = NULL; - int i, num_parents; - unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0; - - /* find the parent that can help provide the fastest rate <= rate */ - num_parents = clk_hw_get_num_parents(hw); - for (i = 0; i < num_parents; i++) { - parent = clk_hw_get_parent_by_index(hw, i); - if (!parent) - continue; - if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) - parent_rate = clk_hw_round_rate(parent, req->rate); - else - parent_rate = clk_hw_get_rate(parent); - - child_rate = sun6i_ahb1_clk_round(req->rate, NULL, NULL, i, - parent_rate); - - if (child_rate <= req->rate && child_rate > best_child_rate) { - best_parent = parent; - best = parent_rate; - best_child_rate = child_rate; - } - } - - if (!best_parent) - return -EINVAL; - - req->best_parent_hw = best_parent; - req->best_parent_rate = best; - req->rate = best_child_rate; - - return 0; -} - -static int sun6i_ahb1_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct sun6i_ahb1_clk *ahb1 = to_sun6i_ahb1_clk(hw); - unsigned long flags; - u8 div, pre_div, parent; - u32 reg; - - spin_lock_irqsave(&clk_lock, flags); - - reg = readl(ahb1->reg); - - /* need to know which parent is used to apply pre-divider */ - parent = SUN6I_AHB1_MUX_GET_PARENT(reg); - sun6i_ahb1_clk_round(rate, &div, &pre_div, parent, parent_rate); - - reg = SUN6I_AHB1_DIV_SET(reg, div); - reg = SUN6I_AHB1_PLL6_DIV_SET(reg, pre_div); - writel(reg, ahb1->reg); - - spin_unlock_irqrestore(&clk_lock, flags); - - return 0; -} - -static const struct clk_ops sun6i_ahb1_clk_ops = { - .determine_rate = sun6i_ahb1_clk_determine_rate, - .recalc_rate = sun6i_ahb1_clk_recalc_rate, - .set_rate = sun6i_ahb1_clk_set_rate, -}; - -static void __init sun6i_ahb1_clk_setup(struct device_node *node) -{ - struct clk *clk; - struct sun6i_ahb1_clk *ahb1; - struct clk_mux *mux; - const char *clk_name = node->name; - const char *parents[SUN6I_AHB1_MAX_PARENTS]; - void __iomem *reg; - int i; - - reg = of_io_request_and_map(node, 0, of_node_full_name(node)); - if (IS_ERR(reg)) - return; - - /* we have a mux, we will have >1 parents */ - i = of_clk_parent_fill(node, parents, SUN6I_AHB1_MAX_PARENTS); - of_property_read_string(node, "clock-output-names", &clk_name); - - ahb1 = kzalloc(sizeof(struct sun6i_ahb1_clk), GFP_KERNEL); - if (!ahb1) - return; - - mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); - if (!mux) { - kfree(ahb1); - return; - } - - /* set up clock properties */ - mux->reg = reg; - mux->shift = SUN6I_AHB1_MUX_SHIFT; - mux->mask = SUN6I_AHB1_MUX_MASK; - mux->lock = &clk_lock; - ahb1->reg = reg; - - clk = clk_register_composite(NULL, clk_name, parents, i, - &mux->hw, &clk_mux_ops, - &ahb1->hw, &sun6i_ahb1_clk_ops, - NULL, NULL, 0); - - if (!IS_ERR(clk)) { - of_clk_add_provider(node, of_clk_src_simple_get, clk); - clk_register_clkdev(clk, clk_name, NULL); - } -} -CLK_OF_DECLARE(sun6i_a31_ahb1, "allwinner,sun6i-a31-ahb1-clk", sun6i_ahb1_clk_setup); - /* Maximum number of parents our clocks have */ #define SUNXI_MAX_PARENTS 5 @@ -490,6 +282,68 @@ static void sun5i_a13_get_ahb_factors(struct factors_request *req) req->p = div; } +#define SUN6I_AHB1_PARENT_PLL6 3 + +/** + * sun6i_a31_get_ahb_factors() - calculates m, p factors for AHB + * AHB rate is calculated as follows + * rate = parent_rate >> p + * + * if parent is pll6, then + * parent_rate = pll6 rate / (m + 1) + */ + +static void sun6i_get_ahb1_factors(struct factors_request *req) +{ + u8 div, calcp, calcm = 1; + + /* + * clock can only divide, so we will never be able to achieve + * frequencies higher than the parent frequency + */ + if (req->parent_rate && req->rate > req->parent_rate) + req->rate = req->parent_rate; + + div = DIV_ROUND_UP(req->parent_rate, req->rate); + + /* calculate pre-divider if parent is pll6 */ + if (req->parent_index == SUN6I_AHB1_PARENT_PLL6) { + if (div < 4) + calcp = 0; + else if (div / 2 < 4) + calcp = 1; + else if (div / 4 < 4) + calcp = 2; + else + calcp = 3; + + calcm = DIV_ROUND_UP(div, 1 << calcp); + } else { + calcp = __roundup_pow_of_two(div); + calcp = calcp > 3 ? 3 : calcp; + } + + req->rate = (req->parent_rate / calcm) >> calcp; + req->p = calcp; + req->m = calcm - 1; +} + +/** + * sun6i_ahb1_recalc() - calculates AHB clock rate from m, p factors and + * parent index + */ +static void sun6i_ahb1_recalc(struct factors_request *req) +{ + req->rate = req->parent_rate; + + /* apply pre-divider first if parent is pll6 */ + if (req->parent_index == SUN6I_AHB1_PARENT_PLL6) + req->rate /= req->m + 1; + + /* clk divider */ + req->rate >>= req->p; +} + /** * sun4i_get_apb1_factors() - calculates m, p factors for APB1 * APB1 rate is calculated as follows @@ -619,6 +473,13 @@ static const struct clk_factors_config sun5i_a13_ahb_config = { .pwidth = 2, }; +static const struct clk_factors_config sun6i_ahb1_config = { + .mshift = 6, + .mwidth = 2, + .pshift = 4, + .pwidth = 2, +}; + static const struct clk_factors_config sun4i_apb1_config = { .mshift = 0, .mwidth = 5, @@ -686,6 +547,14 @@ static const struct factors_data sun5i_a13_ahb_data __initconst = { .getter = sun5i_a13_get_ahb_factors, }; +static const struct factors_data sun6i_ahb1_data __initconst = { + .mux = 12, + .muxmask = BIT(1) | BIT(0), + .table = &sun6i_ahb1_config, + .getter = sun6i_get_ahb1_factors, + .recalc = sun6i_ahb1_recalc, +}; + static const struct factors_data sun4i_apb1_data __initconst = { .mux = 24, .muxmask = BIT(1) | BIT(0), @@ -716,6 +585,12 @@ static struct clk * __init sunxi_factors_clk_setup(struct device_node *node, return sunxi_factors_register(node, data, &clk_lock, reg); } +static void __init sun6i_ahb1_clk_setup(struct device_node *node) +{ + sunxi_factors_clk_setup(node, &sun6i_ahb1_data); +} +CLK_OF_DECLARE(sun6i_a31_ahb1, "allwinner,sun6i-a31-ahb1-clk", + sun6i_ahb1_clk_setup); /** -- cgit v1.2.3 From 3ca2377b6fed7c3db0c064ea73327cc6895e175d Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 25 Jan 2016 21:15:46 +0800 Subject: clk: sunxi: rewrite sun6i-ar100 using factors clk sun6i's AR100 clock is a classic factors clk case: AR100 = ((parent mux) >> p) / (m + 1) Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-sun6i-ar100.c | 235 ++++++++++-------------------------- 1 file changed, 61 insertions(+), 174 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c index 20887686bdbe..a7f5777834eb 100644 --- a/drivers/clk/sunxi/clk-sun6i-ar100.c +++ b/drivers/clk/sunxi/clk-sun6i-ar100.c @@ -8,211 +8,97 @@ * */ +#include #include #include #include #include +#include -#define SUN6I_AR100_MAX_PARENTS 4 -#define SUN6I_AR100_SHIFT_MASK 0x3 -#define SUN6I_AR100_SHIFT_MAX SUN6I_AR100_SHIFT_MASK -#define SUN6I_AR100_SHIFT_SHIFT 4 -#define SUN6I_AR100_DIV_MASK 0x1f -#define SUN6I_AR100_DIV_MAX (SUN6I_AR100_DIV_MASK + 1) -#define SUN6I_AR100_DIV_SHIFT 8 -#define SUN6I_AR100_MUX_MASK 0x3 -#define SUN6I_AR100_MUX_SHIFT 16 - -struct ar100_clk { - struct clk_hw hw; - void __iomem *reg; -}; - -static inline struct ar100_clk *to_ar100_clk(struct clk_hw *hw) -{ - return container_of(hw, struct ar100_clk, hw); -} - -static unsigned long ar100_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct ar100_clk *clk = to_ar100_clk(hw); - u32 val = readl(clk->reg); - int shift = (val >> SUN6I_AR100_SHIFT_SHIFT) & SUN6I_AR100_SHIFT_MASK; - int div = (val >> SUN6I_AR100_DIV_SHIFT) & SUN6I_AR100_DIV_MASK; - - return (parent_rate >> shift) / (div + 1); -} - -static int ar100_determine_rate(struct clk_hw *hw, - struct clk_rate_request *req) -{ - int nparents = clk_hw_get_num_parents(hw); - long best_rate = -EINVAL; - int i; - - req->best_parent_hw = NULL; - - for (i = 0; i < nparents; i++) { - unsigned long parent_rate; - unsigned long tmp_rate; - struct clk_hw *parent; - unsigned long div; - int shift; - - parent = clk_hw_get_parent_by_index(hw, i); - parent_rate = clk_hw_get_rate(parent); - div = DIV_ROUND_UP(parent_rate, req->rate); - - /* - * The AR100 clk contains 2 divisors: - * - one power of 2 divisor - * - one regular divisor - * - * First check if we can safely shift (or divide by a power - * of 2) without losing precision on the requested rate. - */ - shift = ffs(div) - 1; - if (shift > SUN6I_AR100_SHIFT_MAX) - shift = SUN6I_AR100_SHIFT_MAX; - - div >>= shift; - - /* - * Then if the divisor is still bigger than what the HW - * actually supports, use a bigger shift (or power of 2 - * divider) value and accept to lose some precision. - */ - while (div > SUN6I_AR100_DIV_MAX) { - shift++; - div >>= 1; - if (shift > SUN6I_AR100_SHIFT_MAX) - break; - } - - /* - * If the shift value (or power of 2 divider) is bigger - * than what the HW actually support, skip this parent. - */ - if (shift > SUN6I_AR100_SHIFT_MAX) - continue; - - tmp_rate = (parent_rate >> shift) / div; - if (!req->best_parent_hw || tmp_rate > best_rate) { - req->best_parent_hw = parent; - req->best_parent_rate = parent_rate; - best_rate = tmp_rate; - } - } - - if (best_rate < 0) - return best_rate; - - req->rate = best_rate; - - return 0; -} - -static int ar100_set_parent(struct clk_hw *hw, u8 index) -{ - struct ar100_clk *clk = to_ar100_clk(hw); - u32 val = readl(clk->reg); - - if (index >= SUN6I_AR100_MAX_PARENTS) - return -EINVAL; - - val &= ~(SUN6I_AR100_MUX_MASK << SUN6I_AR100_MUX_SHIFT); - val |= (index << SUN6I_AR100_MUX_SHIFT); - writel(val, clk->reg); - - return 0; -} +#include "clk-factors.h" -static u8 ar100_get_parent(struct clk_hw *hw) -{ - struct ar100_clk *clk = to_ar100_clk(hw); - return (readl(clk->reg) >> SUN6I_AR100_MUX_SHIFT) & - SUN6I_AR100_MUX_MASK; -} - -static int ar100_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) +/** + * sun6i_get_ar100_factors - Calculates factors p, m for AR100 + * + * AR100 rate is calculated as follows + * rate = (parent_rate >> p) / (m + 1); + */ +static void sun6i_get_ar100_factors(struct factors_request *req) { - unsigned long div = parent_rate / rate; - struct ar100_clk *clk = to_ar100_clk(hw); - u32 val = readl(clk->reg); + unsigned long div; int shift; - if (parent_rate % rate) - return -EINVAL; + /* clock only divides */ + if (req->rate > req->parent_rate) + req->rate = req->parent_rate; - shift = ffs(div) - 1; - if (shift > SUN6I_AR100_SHIFT_MAX) - shift = SUN6I_AR100_SHIFT_MAX; + div = DIV_ROUND_UP(req->parent_rate, req->rate); - div >>= shift; + if (div < 32) + shift = 0; + else if (div >> 1 < 32) + shift = 1; + else if (div >> 2 < 32) + shift = 2; + else + shift = 3; - if (div > SUN6I_AR100_DIV_MAX) - return -EINVAL; + div >>= shift; - val &= ~((SUN6I_AR100_SHIFT_MASK << SUN6I_AR100_SHIFT_SHIFT) | - (SUN6I_AR100_DIV_MASK << SUN6I_AR100_DIV_SHIFT)); - val |= (shift << SUN6I_AR100_SHIFT_SHIFT) | - (div << SUN6I_AR100_DIV_SHIFT); - writel(val, clk->reg); + if (div > 32) + div = 32; - return 0; + req->rate = (req->parent_rate >> shift) / div; + req->m = div - 1; + req->p = shift; } -static struct clk_ops ar100_ops = { - .recalc_rate = ar100_recalc_rate, - .determine_rate = ar100_determine_rate, - .set_parent = ar100_set_parent, - .get_parent = ar100_get_parent, - .set_rate = ar100_set_rate, +static const struct clk_factors_config sun6i_ar100_config = { + .mwidth = 5, + .mshift = 8, + .pwidth = 2, + .pshift = 4, }; +static const struct factors_data sun6i_ar100_data __initconst = { + .mux = 16, + .muxmask = GENMASK(1, 0), + .table = &sun6i_ar100_config, + .getter = sun6i_get_ar100_factors, +}; + +static DEFINE_SPINLOCK(sun6i_ar100_lock); + static int sun6i_a31_ar100_clk_probe(struct platform_device *pdev) { - const char *parents[SUN6I_AR100_MAX_PARENTS]; struct device_node *np = pdev->dev.of_node; - const char *clk_name = np->name; - struct clk_init_data init; - struct ar100_clk *ar100; struct resource *r; + void __iomem *reg; struct clk *clk; - int nparents; - - ar100 = devm_kzalloc(&pdev->dev, sizeof(*ar100), GFP_KERNEL); - if (!ar100) - return -ENOMEM; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ar100->reg = devm_ioremap_resource(&pdev->dev, r); - if (IS_ERR(ar100->reg)) - return PTR_ERR(ar100->reg); + reg = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(reg)) + return PTR_ERR(reg); - nparents = of_clk_get_parent_count(np); - if (nparents > SUN6I_AR100_MAX_PARENTS) - nparents = SUN6I_AR100_MAX_PARENTS; - - of_clk_parent_fill(np, parents, nparents); + clk = sunxi_factors_register(np, &sun6i_ar100_data, &sun6i_ar100_lock, + reg); + if (!clk) + return -ENOMEM; - of_property_read_string(np, "clock-output-names", &clk_name); + platform_set_drvdata(pdev, clk); - init.name = clk_name; - init.ops = &ar100_ops; - init.parent_names = parents; - init.num_parents = nparents; - init.flags = 0; + return 0; +} - ar100->hw.init = &init; +static int sun6i_a31_ar100_clk_remove(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct clk *clk = platform_get_drvdata(pdev); - clk = clk_register(&pdev->dev, &ar100->hw); - if (IS_ERR(clk)) - return PTR_ERR(clk); + sunxi_factors_unregister(np, clk); - return of_clk_add_provider(np, of_clk_src_simple_get, clk); + return 0; } static const struct of_device_id sun6i_a31_ar100_clk_dt_ids[] = { @@ -227,6 +113,7 @@ static struct platform_driver sun6i_a31_ar100_clk_driver = { .of_match_table = sun6i_a31_ar100_clk_dt_ids, }, .probe = sun6i_a31_ar100_clk_probe, + .remove = sun6i_a31_ar100_clk_remove, }; module_platform_driver(sun6i_a31_ar100_clk_driver); -- cgit v1.2.3 From 8f2bf2ad9673e187b5c2956497003f60e0885e5d Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 25 Jan 2016 21:15:47 +0800 Subject: clk: sunxi: rewrite sun8i-a23-mbus-clk using the simpler composite clk sun8i-a23-mbus-clk used sunxi's factors clk, which is nice for very complicated clocks, but is not really needed here. Convert sun8i-a23-mbus-clk to use clk_composite, as it is a gate + mux + divider. This makes the code easier to understand. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-sun8i-mbus.c | 121 +++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-sun8i-mbus.c b/drivers/clk/sunxi/clk-sun8i-mbus.c index 78683f02a37d..3aaa9cbef791 100644 --- a/drivers/clk/sunxi/clk-sun8i-mbus.c +++ b/drivers/clk/sunxi/clk-sun8i-mbus.c @@ -15,68 +15,99 @@ */ #include +#include #include +#include +#include #include -#include "clk-factors.h" +#define SUN8I_MBUS_ENABLE 31 +#define SUN8I_MBUS_MUX_SHIFT 24 +#define SUN8I_MBUS_MUX_MASK 0x3 +#define SUN8I_MBUS_DIV_SHIFT 0 +#define SUN8I_MBUS_DIV_WIDTH 3 +#define SUN8I_MBUS_MAX_PARENTS 4 -/** - * sun8i_a23_get_mbus_factors() - calculates m factor for MBUS clocks - * MBUS rate is calculated as follows - * rate = parent_rate / (m + 1); - */ +static DEFINE_SPINLOCK(sun8i_a23_mbus_lock); -static void sun8i_a23_get_mbus_factors(struct factors_request *req) +static void __init sun8i_a23_mbus_setup(struct device_node *node) { - u8 div; + int num_parents = of_clk_get_parent_count(node); + const char *parents[num_parents]; + const char *clk_name = node->name; + struct resource res; + struct clk_divider *div; + struct clk_gate *gate; + struct clk_mux *mux; + struct clk *clk; + void __iomem *reg; + int err; - /* - * These clocks can only divide, so we will never be able to - * achieve frequencies higher than the parent frequency - */ - if (req->rate > req->parent_rate) - req->rate = req->parent_rate; + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); + if (!reg) { + pr_err("Could not get registers for sun8i-mbus-clk\n"); + return; + } - div = DIV_ROUND_UP(req->parent_rate, req->rate); + div = kzalloc(sizeof(*div), GFP_KERNEL); + if (!div) + goto err_unmap; - if (div > 8) - div = 8; + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) + goto err_free_div; - req->rate = req->parent_rate / div; - req->m = div - 1; -} + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + goto err_free_mux; -static struct clk_factors_config sun8i_a23_mbus_config = { - .mshift = 0, - .mwidth = 3, -}; + of_property_read_string(node, "clock-output-names", &clk_name); + of_clk_parent_fill(node, parents, num_parents); -static const struct factors_data sun8i_a23_mbus_data __initconst = { - .enable = 31, - .mux = 24, - .muxmask = BIT(1) | BIT(0), - .table = &sun8i_a23_mbus_config, - .getter = sun8i_a23_get_mbus_factors, -}; + gate->reg = reg; + gate->bit_idx = SUN8I_MBUS_ENABLE; + gate->lock = &sun8i_a23_mbus_lock; -static DEFINE_SPINLOCK(sun8i_a23_mbus_lock); + div->reg = reg; + div->shift = SUN8I_MBUS_DIV_SHIFT; + div->width = SUN8I_MBUS_DIV_WIDTH; + div->lock = &sun8i_a23_mbus_lock; -static void __init sun8i_a23_mbus_setup(struct device_node *node) -{ - struct clk *mbus; - void __iomem *reg; + mux->reg = reg; + mux->shift = SUN8I_MBUS_MUX_SHIFT; + mux->mask = SUN8I_MBUS_MUX_MASK; + mux->lock = &sun8i_a23_mbus_lock; - reg = of_iomap(node, 0); - if (!reg) { - pr_err("Could not get registers for a23-mbus-clk\n"); - return; - } + clk = clk_register_composite(NULL, clk_name, parents, num_parents, + &mux->hw, &clk_mux_ops, + &div->hw, &clk_divider_ops, + &gate->hw, &clk_gate_ops, + 0); + if (IS_ERR(clk)) + goto err_free_gate; - mbus = sunxi_factors_register(node, &sun8i_a23_mbus_data, - &sun8i_a23_mbus_lock, reg); + err = of_clk_add_provider(node, of_clk_src_simple_get, clk); + if (err) + goto err_unregister_clk; /* The MBUS clocks needs to be always enabled */ - __clk_get(mbus); - clk_prepare_enable(mbus); + __clk_get(clk); + clk_prepare_enable(clk); + + return; + +err_unregister_clk: + /* TODO: The composite clock stuff will leak a bit here. */ + clk_unregister(clk); +err_free_gate: + kfree(gate); +err_free_mux: + kfree(mux); +err_free_div: + kfree(div); +err_unmap: + iounmap(reg); + of_address_to_resource(node, 0, &res); + release_mem_region(res.start, resource_size(&res)); } CLK_OF_DECLARE(sun8i_a23_mbus, "allwinner,sun8i-a23-mbus-clk", sun8i_a23_mbus_setup); -- cgit v1.2.3 From 8f6aff9858c45525345b92b2a88c2af776c64340 Mon Sep 17 00:00:00 2001 From: Lada Trimasova Date: Wed, 27 Jan 2016 11:10:32 +0000 Subject: iommu/io-pgtable-arm: Fix io-pgtable-arm build failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trying to build a kernel for ARC with both options CONFIG_COMPILE_TEST and CONFIG_IOMMU_IO_PGTABLE_LPAE enabled (e.g. as a result of "make allyesconfig") results in the following build failure: | CC drivers/iommu/io-pgtable-arm.o | linux/drivers/iommu/io-pgtable-arm.c: In | function ‘__arm_lpae_alloc_pages’: | linux/drivers/iommu/io-pgtable-arm.c:221:3: | error: implicit declaration of function ‘dma_map_single’ | [-Werror=implicit-function-declaration] | dma = dma_map_single(dev, pages, size, DMA_TO_DEVICE); | ^ | linux/drivers/iommu/io-pgtable-arm.c:221:42: | error: ‘DMA_TO_DEVICE’ undeclared (first use in this function) | dma = dma_map_single(dev, pages, size, DMA_TO_DEVICE); | ^ Since IOMMU_IO_PGTABLE_LPAE depends on DMA API, io-pgtable-arm.c should include linux/dma-mapping.h. This fixes the reported failure. Cc: Alexey Brodkin Cc: Vineet Gupta Cc: Joerg Roedel Signed-off-by: Lada Trimasova Signed-off-by: Will Deacon Signed-off-by: Joerg Roedel --- drivers/iommu/io-pgtable-arm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 8bbcbfe7695c..381ca5a37a7b 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -25,6 +25,7 @@ #include #include #include +#include #include -- cgit v1.2.3 From c5b635203032462603c503ecce91a7021c1ad44a Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Fri, 29 Jan 2016 10:57:53 +0100 Subject: irqchip/mxs: Add missing set_handle_irq() The rework of the driver missed to move the call to set_handle_irq() into asm9260_of_init(). As a consequence no interrupt entry point is installed and no interrupts are delivered Solution is simple: Install the interrupt entry handler. Fixes: 7e4ac676ee ("irqchip/mxs: Add Alphascale ASM9260 support") Signed-off-by: Oleksij Rempel Cc: kernel@pengutronix.de Cc: jason@lakedaemon.net Cc: marc.zyngier@arm.com Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1454061473-24957-1-git-send-email-linux@rempel-privat.de Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-mxs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c index c22e2d40cb30..efe50845939d 100644 --- a/drivers/irqchip/irq-mxs.c +++ b/drivers/irqchip/irq-mxs.c @@ -241,6 +241,7 @@ static int __init asm9260_of_init(struct device_node *np, writel(0, icoll_priv.intr + i); icoll_add_domain(np, ASM9260_NUM_IRQS); + set_handle_irq(icoll_handle_irq); return 0; } -- cgit v1.2.3 From da972fb13bc5a1baad450c11f9182e4cd0a091f6 Mon Sep 17 00:00:00 2001 From: Jeremy McNicoll Date: Thu, 14 Jan 2016 21:33:06 -0800 Subject: iommu/vt-d: Don't skip PCI devices when disabling IOTLB Fix a simple typo when disabling IOTLB on PCI(e) devices. Fixes: b16d0cb9e2fc ("iommu/vt-d: Always enable PASID/PRI PCI capabilities before ATS") Cc: stable@vger.kernel.org # v4.4 Signed-off-by: Jeremy McNicoll Reviewed-by: Alex Williamson Signed-off-by: Joerg Roedel --- drivers/iommu/intel-iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index ac7387686ddc..986a53e3eb96 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1489,7 +1489,7 @@ static void iommu_disable_dev_iotlb(struct device_domain_info *info) { struct pci_dev *pdev; - if (dev_is_pci(info->dev)) + if (!dev_is_pci(info->dev)) return; pdev = to_pci_dev(info->dev); -- cgit v1.2.3 From cd6438c5f8446691afa4829fe1a9d7b656204f11 Mon Sep 17 00:00:00 2001 From: ZhengShunQian Date: Tue, 19 Jan 2016 15:03:00 +0800 Subject: iommu/rockchip: Reconstruct to support multi slaves There are some IPs, such as video encoder/decoder, contains 2 slave iommus, one for reading and the other for writing. They share the same irq and clock with master. This patch reconstructs to support this case by making them share the same Page Directory, Page Tables and even the register operations. That means every instruction to the reading MMU registers would be duplicated to the writing MMU and vice versa. Signed-off-by: ZhengShunQian Signed-off-by: Joerg Roedel --- drivers/iommu/rockchip-iommu.c | 214 ++++++++++++++++++++++++++--------------- 1 file changed, 135 insertions(+), 79 deletions(-) (limited to 'drivers') diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index ebf0adb8e7ea..a6f593a0a29e 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -86,7 +86,8 @@ struct rk_iommu_domain { struct rk_iommu { struct device *dev; - void __iomem *base; + void __iomem **bases; + int num_mmu; int irq; struct list_head node; /* entry in rk_iommu_domain.iommus */ struct iommu_domain *domain; /* domain to which iommu is attached */ @@ -271,47 +272,70 @@ static u32 rk_iova_page_offset(dma_addr_t iova) return (u32)(iova & RK_IOVA_PAGE_MASK) >> RK_IOVA_PAGE_SHIFT; } -static u32 rk_iommu_read(struct rk_iommu *iommu, u32 offset) +static u32 rk_iommu_read(void __iomem *base, u32 offset) { - return readl(iommu->base + offset); + return readl(base + offset); } -static void rk_iommu_write(struct rk_iommu *iommu, u32 offset, u32 value) +static void rk_iommu_write(void __iomem *base, u32 offset, u32 value) { - writel(value, iommu->base + offset); + writel(value, base + offset); } static void rk_iommu_command(struct rk_iommu *iommu, u32 command) { - writel(command, iommu->base + RK_MMU_COMMAND); + int i; + + for (i = 0; i < iommu->num_mmu; i++) + writel(command, iommu->bases[i] + RK_MMU_COMMAND); } +static void rk_iommu_base_command(void __iomem *base, u32 command) +{ + writel(command, base + RK_MMU_COMMAND); +} static void rk_iommu_zap_lines(struct rk_iommu *iommu, dma_addr_t iova, size_t size) { + int i; + dma_addr_t iova_end = iova + size; /* * TODO(djkurtz): Figure out when it is more efficient to shootdown the * entire iotlb rather than iterate over individual iovas. */ - for (; iova < iova_end; iova += SPAGE_SIZE) - rk_iommu_write(iommu, RK_MMU_ZAP_ONE_LINE, iova); + for (i = 0; i < iommu->num_mmu; i++) + for (; iova < iova_end; iova += SPAGE_SIZE) + rk_iommu_write(iommu->bases[i], RK_MMU_ZAP_ONE_LINE, iova); } static bool rk_iommu_is_stall_active(struct rk_iommu *iommu) { - return rk_iommu_read(iommu, RK_MMU_STATUS) & RK_MMU_STATUS_STALL_ACTIVE; + bool active = true; + int i; + + for (i = 0; i < iommu->num_mmu; i++) + active &= rk_iommu_read(iommu->bases[i], RK_MMU_STATUS) & + RK_MMU_STATUS_STALL_ACTIVE; + + return active; } static bool rk_iommu_is_paging_enabled(struct rk_iommu *iommu) { - return rk_iommu_read(iommu, RK_MMU_STATUS) & - RK_MMU_STATUS_PAGING_ENABLED; + bool enable = true; + int i; + + for (i = 0; i < iommu->num_mmu; i++) + enable &= rk_iommu_read(iommu->bases[i], RK_MMU_STATUS) & + RK_MMU_STATUS_PAGING_ENABLED; + + return enable; } static int rk_iommu_enable_stall(struct rk_iommu *iommu) { - int ret; + int ret, i; if (rk_iommu_is_stall_active(iommu)) return 0; @@ -324,15 +348,16 @@ static int rk_iommu_enable_stall(struct rk_iommu *iommu) ret = rk_wait_for(rk_iommu_is_stall_active(iommu), 1); if (ret) - dev_err(iommu->dev, "Enable stall request timed out, status: %#08x\n", - rk_iommu_read(iommu, RK_MMU_STATUS)); + for (i = 0; i < iommu->num_mmu; i++) + dev_err(iommu->dev, "Enable stall request timed out, status: %#08x\n", + rk_iommu_read(iommu->bases[i], RK_MMU_STATUS)); return ret; } static int rk_iommu_disable_stall(struct rk_iommu *iommu) { - int ret; + int ret, i; if (!rk_iommu_is_stall_active(iommu)) return 0; @@ -341,15 +366,16 @@ static int rk_iommu_disable_stall(struct rk_iommu *iommu) ret = rk_wait_for(!rk_iommu_is_stall_active(iommu), 1); if (ret) - dev_err(iommu->dev, "Disable stall request timed out, status: %#08x\n", - rk_iommu_read(iommu, RK_MMU_STATUS)); + for (i = 0; i < iommu->num_mmu; i++) + dev_err(iommu->dev, "Disable stall request timed out, status: %#08x\n", + rk_iommu_read(iommu->bases[i], RK_MMU_STATUS)); return ret; } static int rk_iommu_enable_paging(struct rk_iommu *iommu) { - int ret; + int ret, i; if (rk_iommu_is_paging_enabled(iommu)) return 0; @@ -358,15 +384,16 @@ static int rk_iommu_enable_paging(struct rk_iommu *iommu) ret = rk_wait_for(rk_iommu_is_paging_enabled(iommu), 1); if (ret) - dev_err(iommu->dev, "Enable paging request timed out, status: %#08x\n", - rk_iommu_read(iommu, RK_MMU_STATUS)); + for (i = 0; i < iommu->num_mmu; i++) + dev_err(iommu->dev, "Enable paging request timed out, status: %#08x\n", + rk_iommu_read(iommu->bases[i], RK_MMU_STATUS)); return ret; } static int rk_iommu_disable_paging(struct rk_iommu *iommu) { - int ret; + int ret, i; if (!rk_iommu_is_paging_enabled(iommu)) return 0; @@ -375,41 +402,49 @@ static int rk_iommu_disable_paging(struct rk_iommu *iommu) ret = rk_wait_for(!rk_iommu_is_paging_enabled(iommu), 1); if (ret) - dev_err(iommu->dev, "Disable paging request timed out, status: %#08x\n", - rk_iommu_read(iommu, RK_MMU_STATUS)); + for (i = 0; i < iommu->num_mmu; i++) + dev_err(iommu->dev, "Disable paging request timed out, status: %#08x\n", + rk_iommu_read(iommu->bases[i], RK_MMU_STATUS)); return ret; } static int rk_iommu_force_reset(struct rk_iommu *iommu) { - int ret; + int ret, i; u32 dte_addr; /* * Check if register DTE_ADDR is working by writing DTE_ADDR_DUMMY * and verifying that upper 5 nybbles are read back. */ - rk_iommu_write(iommu, RK_MMU_DTE_ADDR, DTE_ADDR_DUMMY); + for (i = 0; i < iommu->num_mmu; i++) { + rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR, DTE_ADDR_DUMMY); - dte_addr = rk_iommu_read(iommu, RK_MMU_DTE_ADDR); - if (dte_addr != (DTE_ADDR_DUMMY & RK_DTE_PT_ADDRESS_MASK)) { - dev_err(iommu->dev, "Error during raw reset. MMU_DTE_ADDR is not functioning\n"); - return -EFAULT; + dte_addr = rk_iommu_read(iommu->bases[i], RK_MMU_DTE_ADDR); + if (dte_addr != (DTE_ADDR_DUMMY & RK_DTE_PT_ADDRESS_MASK)) { + dev_err(iommu->dev, "Error during raw reset. MMU_DTE_ADDR is not functioning\n"); + return -EFAULT; + } } rk_iommu_command(iommu, RK_MMU_CMD_FORCE_RESET); - ret = rk_wait_for(rk_iommu_read(iommu, RK_MMU_DTE_ADDR) == 0x00000000, - FORCE_RESET_TIMEOUT); - if (ret) - dev_err(iommu->dev, "FORCE_RESET command timed out\n"); + for (i = 0; i < iommu->num_mmu; i++) { + ret = rk_wait_for(rk_iommu_read(iommu->bases[i], RK_MMU_DTE_ADDR) == 0x00000000, + FORCE_RESET_TIMEOUT); + if (ret) { + dev_err(iommu->dev, "FORCE_RESET command timed out\n"); + return ret; + } + } - return ret; + return 0; } -static void log_iova(struct rk_iommu *iommu, dma_addr_t iova) +static void log_iova(struct rk_iommu *iommu, int index, dma_addr_t iova) { + void __iomem *base = iommu->bases[index]; u32 dte_index, pte_index, page_offset; u32 mmu_dte_addr; phys_addr_t mmu_dte_addr_phys, dte_addr_phys; @@ -425,7 +460,7 @@ static void log_iova(struct rk_iommu *iommu, dma_addr_t iova) pte_index = rk_iova_pte_index(iova); page_offset = rk_iova_page_offset(iova); - mmu_dte_addr = rk_iommu_read(iommu, RK_MMU_DTE_ADDR); + mmu_dte_addr = rk_iommu_read(base, RK_MMU_DTE_ADDR); mmu_dte_addr_phys = (phys_addr_t)mmu_dte_addr; dte_addr_phys = mmu_dte_addr_phys + (4 * dte_index); @@ -460,51 +495,56 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id) u32 status; u32 int_status; dma_addr_t iova; + irqreturn_t ret = IRQ_NONE; + int i; - int_status = rk_iommu_read(iommu, RK_MMU_INT_STATUS); - if (int_status == 0) - return IRQ_NONE; + for (i = 0; i < iommu->num_mmu; i++) { + int_status = rk_iommu_read(iommu->bases[i], RK_MMU_INT_STATUS); + if (int_status == 0) + continue; - iova = rk_iommu_read(iommu, RK_MMU_PAGE_FAULT_ADDR); + ret = IRQ_HANDLED; + iova = rk_iommu_read(iommu->bases[i], RK_MMU_PAGE_FAULT_ADDR); - if (int_status & RK_MMU_IRQ_PAGE_FAULT) { - int flags; + if (int_status & RK_MMU_IRQ_PAGE_FAULT) { + int flags; - status = rk_iommu_read(iommu, RK_MMU_STATUS); - flags = (status & RK_MMU_STATUS_PAGE_FAULT_IS_WRITE) ? - IOMMU_FAULT_WRITE : IOMMU_FAULT_READ; + status = rk_iommu_read(iommu->bases[i], RK_MMU_STATUS); + flags = (status & RK_MMU_STATUS_PAGE_FAULT_IS_WRITE) ? + IOMMU_FAULT_WRITE : IOMMU_FAULT_READ; - dev_err(iommu->dev, "Page fault at %pad of type %s\n", - &iova, - (flags == IOMMU_FAULT_WRITE) ? "write" : "read"); + dev_err(iommu->dev, "Page fault at %pad of type %s\n", + &iova, + (flags == IOMMU_FAULT_WRITE) ? "write" : "read"); - log_iova(iommu, iova); + log_iova(iommu, i, iova); - /* - * Report page fault to any installed handlers. - * Ignore the return code, though, since we always zap cache - * and clear the page fault anyway. - */ - if (iommu->domain) - report_iommu_fault(iommu->domain, iommu->dev, iova, - flags); - else - dev_err(iommu->dev, "Page fault while iommu not attached to domain?\n"); + /* + * Report page fault to any installed handlers. + * Ignore the return code, though, since we always zap cache + * and clear the page fault anyway. + */ + if (iommu->domain) + report_iommu_fault(iommu->domain, iommu->dev, iova, + flags); + else + dev_err(iommu->dev, "Page fault while iommu not attached to domain?\n"); - rk_iommu_command(iommu, RK_MMU_CMD_ZAP_CACHE); - rk_iommu_command(iommu, RK_MMU_CMD_PAGE_FAULT_DONE); - } + rk_iommu_base_command(iommu->bases[i], RK_MMU_CMD_ZAP_CACHE); + rk_iommu_base_command(iommu->bases[i], RK_MMU_CMD_PAGE_FAULT_DONE); + } - if (int_status & RK_MMU_IRQ_BUS_ERROR) - dev_err(iommu->dev, "BUS_ERROR occurred at %pad\n", &iova); + if (int_status & RK_MMU_IRQ_BUS_ERROR) + dev_err(iommu->dev, "BUS_ERROR occurred at %pad\n", &iova); - if (int_status & ~RK_MMU_IRQ_MASK) - dev_err(iommu->dev, "unexpected int_status: %#08x\n", - int_status); + if (int_status & ~RK_MMU_IRQ_MASK) + dev_err(iommu->dev, "unexpected int_status: %#08x\n", + int_status); - rk_iommu_write(iommu, RK_MMU_INT_CLEAR, int_status); + rk_iommu_write(iommu->bases[i], RK_MMU_INT_CLEAR, int_status); + } - return IRQ_HANDLED; + return ret; } static phys_addr_t rk_iommu_iova_to_phys(struct iommu_domain *domain, @@ -746,7 +786,7 @@ static int rk_iommu_attach_device(struct iommu_domain *domain, struct rk_iommu *iommu; struct rk_iommu_domain *rk_domain = to_rk_domain(domain); unsigned long flags; - int ret; + int ret, i; phys_addr_t dte_addr; /* @@ -773,9 +813,11 @@ static int rk_iommu_attach_device(struct iommu_domain *domain, return ret; dte_addr = virt_to_phys(rk_domain->dt); - rk_iommu_write(iommu, RK_MMU_DTE_ADDR, dte_addr); - rk_iommu_command(iommu, RK_MMU_CMD_ZAP_CACHE); - rk_iommu_write(iommu, RK_MMU_INT_MASK, RK_MMU_IRQ_MASK); + for (i = 0; i < iommu->num_mmu; i++) { + rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR, dte_addr); + rk_iommu_command(iommu->bases[i], RK_MMU_CMD_ZAP_CACHE); + rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, RK_MMU_IRQ_MASK); + } ret = rk_iommu_enable_paging(iommu); if (ret) @@ -798,6 +840,7 @@ static void rk_iommu_detach_device(struct iommu_domain *domain, struct rk_iommu *iommu; struct rk_iommu_domain *rk_domain = to_rk_domain(domain); unsigned long flags; + int i; /* Allow 'virtual devices' (eg drm) to detach from domain */ iommu = rk_iommu_from_dev(dev); @@ -811,8 +854,10 @@ static void rk_iommu_detach_device(struct iommu_domain *domain, /* Ignore error while disabling, just keep going */ rk_iommu_enable_stall(iommu); rk_iommu_disable_paging(iommu); - rk_iommu_write(iommu, RK_MMU_INT_MASK, 0); - rk_iommu_write(iommu, RK_MMU_DTE_ADDR, 0); + for (i = 0; i < iommu->num_mmu; i++) { + rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, 0); + rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR, 0); + } rk_iommu_disable_stall(iommu); devm_free_irq(dev, iommu->irq, iommu); @@ -988,6 +1033,7 @@ static int rk_iommu_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct rk_iommu *iommu; struct resource *res; + int i; iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL); if (!iommu) @@ -995,11 +1041,21 @@ static int rk_iommu_probe(struct platform_device *pdev) platform_set_drvdata(pdev, iommu); iommu->dev = dev; + iommu->num_mmu = 0; + iommu->bases = devm_kzalloc(dev, sizeof(*iommu->bases) * iommu->num_mmu, + GFP_KERNEL); + if (!iommu->bases) + return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - iommu->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(iommu->base)) - return PTR_ERR(iommu->base); + for (i = 0; i < pdev->num_resources; i++) { + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + iommu->bases[i] = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(iommu->bases[i])) + continue; + iommu->num_mmu++; + } + if (iommu->num_mmu == 0) + return PTR_ERR(iommu->bases[0]); iommu->irq = platform_get_irq(pdev, 0); if (iommu->irq < 0) { -- cgit v1.2.3 From 9b1a12d29109234d2b9718d04d4d404b7da4e794 Mon Sep 17 00:00:00 2001 From: Baoquan He Date: Wed, 20 Jan 2016 22:01:19 +0800 Subject: iommu/amd: Correct the wrong setting of alias DTE in do_attach In below commit alias DTE is set when its peripheral is setting DTE. However there's a code bug here to wrongly set the alias DTE, correct it in this patch. commit e25bfb56ea7f046b71414e02f80f620deb5c6362 Author: Joerg Roedel Date: Tue Oct 20 17:33:38 2015 +0200 iommu/amd: Set alias DTE in do_attach/do_detach Signed-off-by: Baoquan He Tested-by: Mark Hounschell Cc: stable@vger.kernel.org # v4.4 Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 539b0dea8034..e5e223938eec 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -2049,7 +2049,7 @@ static void do_attach(struct iommu_dev_data *dev_data, /* Update device table */ set_dte_entry(dev_data->devid, domain, ats); if (alias != dev_data->devid) - set_dte_entry(dev_data->devid, domain, ats); + set_dte_entry(alias, domain, ats); device_flush_dte(dev_data); } -- cgit v1.2.3 From 4f57d27be2a5a10ad042fcfd97c5ea9f4d5215f7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 26 Jan 2016 10:46:23 -0200 Subject: [media] tvp5150: fix tvp5150_fill_fmt() The tvp5150 output video is interlaced so mark the format field as alternate and reduce the height to the half. [javier: split patch and write commit message] Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas --- drivers/media/i2c/tvp5150.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 437f1a7ecb96..c277caaad8be 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -852,10 +852,10 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd, tvp5150_reset(sd, 0); f->width = decoder->rect.width; - f->height = decoder->rect.height; + f->height = decoder->rect.height / 2; f->code = MEDIA_BUS_FMT_UYVY8_2X8; - f->field = V4L2_FIELD_SEQ_TB; + f->field = V4L2_FIELD_ALTERNATE; f->colorspace = V4L2_COLORSPACE_SMPTE170M; v4l2_dbg(1, debug, sd, "width = %d, height = %d\n", f->width, -- cgit v1.2.3 From e545ac872ff884801a48beb7e6e0fc7513555fd9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 26 Jan 2016 10:46:24 -0200 Subject: [media] tvp5150: Add pad-level subdev operations This patch enables the tvp5150 decoder driver to be used with the media controller framework by adding pad-level subdev operations and init the media entity pad. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas --- drivers/media/i2c/tvp5150.c | 53 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index c277caaad8be..0ad122fcd632 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -37,6 +37,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); struct tvp5150 { struct v4l2_subdev sd; + struct media_pad pad; struct v4l2_ctrl_handler hdl; struct v4l2_rect rect; @@ -826,17 +827,6 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd) } } -static int tvp5150_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) -{ - if (code->pad || code->index) - return -EINVAL; - - code->code = MEDIA_BUS_FMT_UYVY8_2X8; - return 0; -} - static int tvp5150_fill_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *format) @@ -968,6 +958,38 @@ static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, return 0; } +/**************************************************************************** + V4L2 subdev pad ops + ****************************************************************************/ +static int tvp5150_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->pad || code->index) + return -EINVAL; + + code->code = MEDIA_BUS_FMT_UYVY8_2X8; + return 0; +} + +static int tvp5150_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct tvp5150 *decoder = to_tvp5150(sd); + + if (fse->index >= 8 || fse->code != MEDIA_BUS_FMT_UYVY8_2X8) + return -EINVAL; + + fse->code = MEDIA_BUS_FMT_UYVY8_2X8; + fse->min_width = decoder->rect.width; + fse->max_width = decoder->rect.width; + fse->min_height = decoder->rect.height / 2; + fse->max_height = decoder->rect.height / 2; + + return 0; +} + /**************************************************************************** I2C Command ****************************************************************************/ @@ -1132,6 +1154,7 @@ static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { static const struct v4l2_subdev_pad_ops tvp5150_pad_ops = { .enum_mbus_code = tvp5150_enum_mbus_code, + .enum_frame_size = tvp5150_enum_frame_size, .set_fmt = tvp5150_fill_fmt, .get_fmt = tvp5150_fill_fmt, }; @@ -1287,6 +1310,14 @@ static int tvp5150_probe(struct i2c_client *c, } v4l2_i2c_subdev_init(sd, c, &tvp5150_ops); + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + +#if defined(CONFIG_MEDIA_CONTROLLER) + core->pad.flags = MEDIA_PAD_FL_SOURCE; + res = media_entity_pads_init(&sd->entity, 1, &core->pad); + if (res < 0) + return res; +#endif res = tvp5150_detect_version(core); if (res < 0) -- cgit v1.2.3 From 87df1b2a2103b9019433da99be43a472c16647ab Mon Sep 17 00:00:00 2001 From: Andrea Merello Date: Tue, 26 Jan 2016 15:48:04 +0100 Subject: ocfb: fix tgdel and tvdel timing parameters According to the ocfb documentation: Fix tgdel HW param should be left margin, not right. Fix tvdel HW param should upper margin, not lower. This seems to fix lock issues on certain monitors (tested on a slightly customized IP, but the FPGA guy said that it should be the same wrt this changes). Signed-off-by: Andrea Merello Acked-by: Stefan Kristiansson Signed-off-by: Tomi Valkeinen --- drivers/video/fbdev/ocfb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/fbdev/ocfb.c b/drivers/video/fbdev/ocfb.c index c9293aea8ec3..a970edc2a6f8 100644 --- a/drivers/video/fbdev/ocfb.c +++ b/drivers/video/fbdev/ocfb.c @@ -123,11 +123,11 @@ static int ocfb_setupfb(struct ocfb_dev *fbdev) /* Horizontal timings */ ocfb_writereg(fbdev, OCFB_HTIM, (var->hsync_len - 1) << 24 | - (var->right_margin - 1) << 16 | (var->xres - 1)); + (var->left_margin - 1) << 16 | (var->xres - 1)); /* Vertical timings */ ocfb_writereg(fbdev, OCFB_VTIM, (var->vsync_len - 1) << 24 | - (var->lower_margin - 1) << 16 | (var->yres - 1)); + (var->upper_margin - 1) << 16 | (var->yres - 1)); /* Total length of frame */ hlen = var->left_margin + var->right_margin + var->hsync_len + -- cgit v1.2.3 From b54729b6cea7d1f46b1ed70cb7065c6bdefaa780 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 16:04:03 +0100 Subject: fbdev: s6e8ax0: avoid unused function warnings The s6e8ax0 suspend/resume functions are hidden inside of an #ifdef when CONFIG_PM is set to avoid unused function warnings, but they call some other functions that nothing else calls, and we get warnings about those: drivers/video/fbdev/exynos/s6e8ax0.c:449:13: error: 's6e8ax0_sleep_in' defined but not used [-Werror=unused-function] drivers/video/fbdev/exynos/s6e8ax0.c:485:13: error: 's6e8ax0_display_off' defined but not used [-Werror=unused-function] This marks the PM functions as __maybe_unused so the compiler can silently drop them when they are not referenced. Signed-off-by: Arnd Bergmann Reviewed-by: Krzysztof Kozlowski Signed-off-by: Tomi Valkeinen --- drivers/video/fbdev/exynos/s6e8ax0.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/video/fbdev/exynos/s6e8ax0.c b/drivers/video/fbdev/exynos/s6e8ax0.c index 95873f26e39c..de2f3e793786 100644 --- a/drivers/video/fbdev/exynos/s6e8ax0.c +++ b/drivers/video/fbdev/exynos/s6e8ax0.c @@ -829,8 +829,7 @@ static int s6e8ax0_probe(struct mipi_dsim_lcd_device *dsim_dev) return 0; } -#ifdef CONFIG_PM -static int s6e8ax0_suspend(struct mipi_dsim_lcd_device *dsim_dev) +static int __maybe_unused s6e8ax0_suspend(struct mipi_dsim_lcd_device *dsim_dev) { struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev); @@ -843,7 +842,7 @@ static int s6e8ax0_suspend(struct mipi_dsim_lcd_device *dsim_dev) return 0; } -static int s6e8ax0_resume(struct mipi_dsim_lcd_device *dsim_dev) +static int __maybe_unused s6e8ax0_resume(struct mipi_dsim_lcd_device *dsim_dev) { struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev); @@ -855,10 +854,6 @@ static int s6e8ax0_resume(struct mipi_dsim_lcd_device *dsim_dev) return 0; } -#else -#define s6e8ax0_suspend NULL -#define s6e8ax0_resume NULL -#endif static struct mipi_dsim_lcd_driver s6e8ax0_dsim_ddi_driver = { .name = "s6e8ax0", @@ -867,8 +862,8 @@ static struct mipi_dsim_lcd_driver s6e8ax0_dsim_ddi_driver = { .power_on = s6e8ax0_power_on, .set_sequence = s6e8ax0_set_sequence, .probe = s6e8ax0_probe, - .suspend = s6e8ax0_suspend, - .resume = s6e8ax0_resume, + .suspend = IS_ENABLED(CONFIG_PM) ? s6e8ax0_suspend : NULL, + .resume = IS_ENABLED(CONFIG_PM) ? s6e8ax0_resume : NULL, }; static int s6e8ax0_init(void) -- cgit v1.2.3 From ef88ee4e2c98c11dab56b2845ade9270acb8e68b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 16:05:18 +0100 Subject: fbdev: da8xx-fb: remove incorrect type cast The probe function correct passes a dma_addr_t pointer into dma_alloc_coherent(), but has a cast to resource_size_t, which might be different from dma_addr_t: drivers/video/fbdev/da8xx-fb.c: In function 'fb_probe': drivers/video/fbdev/da8xx-fb.c:1431:10: error: passing argument 3 of 'dma_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] This removes the cast, which avoids the warning. Signed-off-by: Arnd Bergmann Signed-off-by: Tomi Valkeinen --- drivers/video/fbdev/da8xx-fb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/video/fbdev/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c index 0081725c6b5b..6b2a06d09f2b 100644 --- a/drivers/video/fbdev/da8xx-fb.c +++ b/drivers/video/fbdev/da8xx-fb.c @@ -152,7 +152,7 @@ static void lcdc_write(unsigned int val, unsigned int addr) struct da8xx_fb_par { struct device *dev; - resource_size_t p_palette_base; + dma_addr_t p_palette_base; unsigned char *v_palette_base; dma_addr_t vram_phys; unsigned long vram_size; @@ -1428,7 +1428,7 @@ static int fb_probe(struct platform_device *device) par->vram_virt = dma_alloc_coherent(NULL, par->vram_size, - (resource_size_t *) &par->vram_phys, + &par->vram_phys, GFP_KERNEL | GFP_DMA); if (!par->vram_virt) { dev_err(&device->dev, @@ -1448,7 +1448,7 @@ static int fb_probe(struct platform_device *device) /* allocate palette buffer */ par->v_palette_base = dma_zalloc_coherent(NULL, PALETTE_SIZE, - (resource_size_t *)&par->p_palette_base, + &par->p_palette_base, GFP_KERNEL | GFP_DMA); if (!par->v_palette_base) { dev_err(&device->dev, -- cgit v1.2.3 From c3a2da26e6216033456c1d5375cd1d2629d1fd09 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 16:03:01 +0100 Subject: fbdev: mmp: print IRQ resource using %pR format string resource_size_t cannot be printed using the %x format string when we it is defined as u64: drivers/video/fbdev/mmp/hw/mmp_ctrl.c: In function 'mmphw_probe': drivers/video/fbdev/mmp/hw/mmp_ctrl.c:506:22: error: format '%x' expects argument of type 'unsigned int', but argument 4 has type 'resource_size_t {aka long long unsigned int}' [-Werror=format=] dev_err(ctrl->dev, "%s: res %x - %x map failed\n", __func__, ^ drivers/video/fbdev/mmp/hw/mmp_ctrl.c:506:22: error: format '%x' expects argument of type 'unsigned int', but argument 5 has type 'resource_size_t {aka long long unsigned int}' [-Werror=format=] This changes the format string to %pR, which is interpreted by the printk implementation to pretty-print a resource structure. Signed-off-by: Arnd Bergmann Signed-off-by: Tomi Valkeinen --- drivers/video/fbdev/mmp/hw/mmp_ctrl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/fbdev/mmp/hw/mmp_ctrl.c b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c index de54a4748065..b6f83d5df9fd 100644 --- a/drivers/video/fbdev/mmp/hw/mmp_ctrl.c +++ b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c @@ -503,8 +503,7 @@ static int mmphw_probe(struct platform_device *pdev) ctrl->reg_base = devm_ioremap_nocache(ctrl->dev, res->start, resource_size(res)); if (ctrl->reg_base == NULL) { - dev_err(ctrl->dev, "%s: res %x - %x map failed\n", __func__, - res->start, res->end); + dev_err(ctrl->dev, "%s: res %pR map failed\n", __func__, res); ret = -ENOMEM; goto failed; } -- cgit v1.2.3 From a588afc920bc50e894f6ae2874c4281c795e0979 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 29 Jan 2016 07:06:53 -0500 Subject: libata-sff: use WARN instead of BUG on illegal host state machine state ata_sff_hsm_move() triggers BUG if it sees a host state machine state that it dind't expect. The risk for data corruption when the condition occurs is low as it's highly unlikely that it would lead to spurious completion of commands. The BUG occasionally triggered for subtle race conditions in the driver. Let's downgrade it to WARN so that it doesn't kill the machine unnecessarily. Signed-off-by: Tejun Heo Cc: Dmitry Vyukov --- drivers/ata/libata-sff.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index cdf6215a9a22..608677df4f49 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -1296,7 +1296,8 @@ fsm_start: break; default: poll_next = 0; - BUG(); + WARN(true, "ata%d: SFF host state machine in invalid state %d", + ap->print_id, ap->hsm_task_state); } return poll_next; -- cgit v1.2.3 From b82fe6ddd782f847332aeabf8cab980852f61629 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 19 Jan 2016 11:10:57 -0200 Subject: video: fbdev: imxfb: Provide a reset mechanism Currently when we boot the kernel on a mx25pdk the LCDC controller does not show the Linux logo on boot. This problem is well explained by Sascha Hauer: "Unfortunately this LCD controller does not have an enable bit. The controller starts directly when the clocks are enabled. If the clocks are enabled when the controller is not yet programmed with proper register values then it just goes into some undefined state. What I suspect is that the clocks already were enabled before driver probe, presumably by the bootloader, so the controller is already in undefined state when entering Linux. Now by dis/enabling the ipg clock you effectively reset the controller. Since you have programmed it with valid register values in the mean time it starts working after this reset." So do as suggested and force a reset of the LCDC hardware by enabling and disabling the IPG clock. With this change the Linux logo can be seen on boot on a mx25pdk. Signed-off-by: Fabio Estevam Signed-off-by: Tomi Valkeinen --- drivers/video/fbdev/imxfb.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c index cee88603efc9..bb2f1e866020 100644 --- a/drivers/video/fbdev/imxfb.c +++ b/drivers/video/fbdev/imxfb.c @@ -902,6 +902,21 @@ static int imxfb_probe(struct platform_device *pdev) goto failed_getclock; } + /* + * The LCDC controller does not have an enable bit. The + * controller starts directly when the clocks are enabled. + * If the clocks are enabled when the controller is not yet + * programmed with proper register values (enabled at the + * bootloader, for example) then it just goes into some undefined + * state. + * To avoid this issue, let's enable and disable LCDC IPG clock + * so that we force some kind of 'reset' to the LCDC block. + */ + ret = clk_prepare_enable(fbi->clk_ipg); + if (ret) + goto failed_getclock; + clk_disable_unprepare(fbi->clk_ipg); + fbi->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); if (IS_ERR(fbi->clk_ahb)) { ret = PTR_ERR(fbi->clk_ahb); -- cgit v1.2.3 From a382c30c662a31dd8f51cc4b6dad82d39205d50c Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Fri, 29 Jan 2016 22:38:07 +0900 Subject: HID: quirks: Add no_init_reports for AKAI midi controller The midi controller times-out while initializing reports, this causes boot to take an extra 10 seconds. The device descriptor advertises that it has an internal HID device but seems to not actually do anything useful. Signed-off-by: Stafford Horne Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 3 +++ drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index bfd2c9d834d0..953257b390c3 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -61,6 +61,9 @@ #define USB_VENDOR_ID_AIREN 0x1a2c #define USB_DEVICE_ID_AIREN_SLIMPLUS 0x0002 +#define USB_VENDOR_ID_AKAI 0x2011 +#define USB_DEVICE_ID_AKAI_MPKMINI2 0x0715 + #define USB_VENDOR_ID_ALCOR 0x058f #define USB_DEVICE_ID_ALCOR_USBRS232 0x9720 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 6f0db54c4a9f..cb8cbdd07c4e 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -55,6 +55,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, -- cgit v1.2.3 From ad32152eb26043d165eed9406cb9e2f7011f6b10 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 28 Jan 2016 16:27:41 -0500 Subject: drm/amdgpu: no need to load MC firmware on fiji Vbios does this for us on asic_init. Reviewed-by: Ken Wang >Qingqing.Wang@amd.com> Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index c0c9a0101eb4..875a5e988cb1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -44,7 +44,6 @@ static void gmc_v8_0_set_irq_funcs(struct amdgpu_device *adev); MODULE_FIRMWARE("amdgpu/topaz_mc.bin"); MODULE_FIRMWARE("amdgpu/tonga_mc.bin"); -MODULE_FIRMWARE("amdgpu/fiji_mc.bin"); static const u32 golden_settings_tonga_a11[] = { @@ -236,8 +235,6 @@ static int gmc_v8_0_init_microcode(struct amdgpu_device *adev) chip_name = "tonga"; break; case CHIP_FIJI: - chip_name = "fiji"; - break; case CHIP_CARRIZO: case CHIP_STONEY: return 0; @@ -1007,7 +1004,8 @@ static int gmc_v8_0_hw_init(void *handle) gmc_v8_0_mc_program(adev); - if (!(adev->flags & AMD_IS_APU)) { + if ((adev->asic_type == CHIP_TOPAZ) || + (adev->asic_type == CHIP_TONGA)) { r = gmc_v8_0_mc_load_microcode(adev); if (r) { DRM_ERROR("Failed to load MC firmware!\n"); -- cgit v1.2.3 From 313726cad3b68039c8e4dcad5a2840a0d375678c Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Thu, 28 Jan 2016 18:23:41 +0100 Subject: HID: dragonrise: fix a typo in descriptors comments s/Joystik/Joystick/ Signed-off-by: Antonio Ospite Signed-off-by: Jiri Kosina --- drivers/hid/hid-dr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c index 1d78ba3b799e..8fd4bf77f264 100644 --- a/drivers/hid/hid-dr.c +++ b/drivers/hid/hid-dr.c @@ -151,7 +151,7 @@ static inline int drff_init(struct hid_device *hid) * descriptor. In any case, it's a wonder it works on Windows. * * Usage Page (Desktop), ; Generic desktop controls (01h) - * Usage (Joystik), ; Joystik (04h, application collection) + * Usage (Joystick), ; Joystick (04h, application collection) * Collection (Application), * Collection (Logical), * Report Size (8), @@ -207,7 +207,7 @@ static inline int drff_init(struct hid_device *hid) /* Fixed report descriptor for PID 0x011 joystick */ static __u8 pid0011_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ - 0x09, 0x04, /* Usage (Joystik), */ + 0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x02, /* Collection (Logical), */ 0x14, /* Logical Minimum (0), */ -- cgit v1.2.3 From d542176f94c790016cc340dff74ba00d57410728 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Thu, 28 Jan 2016 18:23:43 +0100 Subject: HID: sony: fix a typo in descriptors comments s/Joystik/Joystick/ Signed-off-by: Antonio Ospite Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 9b8db0e0ef1c..0b5015fd864a 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -251,7 +251,7 @@ static __u8 motion_rdesc[] = { /* PS/3 Navigation controller */ static __u8 navigation_rdesc[] = { 0x05, 0x01, /* Usage Page (Desktop), */ - 0x09, 0x04, /* Usage (Joystik), */ + 0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x02, /* Collection (Logical), */ 0x85, 0x01, /* Report ID (1), */ -- cgit v1.2.3 From 6c55d9b98335f7f6bd5f061866ff1633401f3a44 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Fri, 29 Jan 2016 16:49:47 +0200 Subject: serial: 8250_pci: Add Intel Broadwell ports Some recent (early 2015) macbooks have Intel Broadwell where LPSS UARTs are PCI enumerated instead of ACPI. The LPSS UART block is pretty much same as used on Intel Baytrail so we can reuse the existing Baytrail setup code. Add both Broadwell LPSS UART ports to the list of supported devices. Signed-off-by: Leif Liddy Signed-off-by: Mika Westerberg Reviewed-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 4097f3f65b3b..e71ec78fc11e 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1379,6 +1379,9 @@ ce4100_serial_setup(struct serial_private *priv, #define PCI_DEVICE_ID_INTEL_BSW_UART1 0x228a #define PCI_DEVICE_ID_INTEL_BSW_UART2 0x228c +#define PCI_DEVICE_ID_INTEL_BDW_UART1 0x9ce3 +#define PCI_DEVICE_ID_INTEL_BDW_UART2 0x9ce4 + #define BYT_PRV_CLK 0x800 #define BYT_PRV_CLK_EN (1 << 0) #define BYT_PRV_CLK_M_VAL_SHIFT 1 @@ -1461,11 +1464,13 @@ byt_serial_setup(struct serial_private *priv, switch (pdev->device) { case PCI_DEVICE_ID_INTEL_BYT_UART1: case PCI_DEVICE_ID_INTEL_BSW_UART1: + case PCI_DEVICE_ID_INTEL_BDW_UART1: rx_param->src_id = 3; tx_param->dst_id = 2; break; case PCI_DEVICE_ID_INTEL_BYT_UART2: case PCI_DEVICE_ID_INTEL_BSW_UART2: + case PCI_DEVICE_ID_INTEL_BDW_UART2: rx_param->src_id = 5; tx_param->dst_id = 4; break; @@ -2062,6 +2067,20 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .subdevice = PCI_ANY_ID, .setup = byt_serial_setup, }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_BDW_UART1, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = byt_serial_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_BDW_UART2, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = byt_serial_setup, + }, /* * ITE */ @@ -5506,6 +5525,16 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000, pbn_byt }, + /* Intel Broadwell */ + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BDW_UART1, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000, + pbn_byt }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BDW_UART2, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000, + pbn_byt }, + /* * Intel Quark x1000 */ -- cgit v1.2.3 From 1ce133ec89027dc2dff6d0784564da27f1c21fdc Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 8 Jan 2016 09:35:58 -0800 Subject: clk: mvebu: Mark ioremapped memory as __iomem Silence the following sparse warning drivers/clk/mvebu/dove-divider.c:252:14: warning: incorrect type in assignment (different address spaces) drivers/clk/mvebu/dove-divider.c:252:14: expected void *base drivers/clk/mvebu/dove-divider.c:252:14: got void [noderef] * drivers/clk/mvebu/dove-divider.c:256:13: warning: incorrect type in argument 2 (different address spaces) drivers/clk/mvebu/dove-divider.c:256:13: expected void [noderef] *base drivers/clk/mvebu/dove-divider.c:256:13: got void *base drivers/clk/mvebu/dove-divider.c:257:25: warning: incorrect type in argument 1 (different address spaces) drivers/clk/mvebu/dove-divider.c:257:25: expected void volatile [noderef] *iomem_cookie drivers/clk/mvebu/dove-divider.c:257:25: got void *base Cc: Russell King Signed-off-by: Stephen Boyd --- drivers/clk/mvebu/dove-divider.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/mvebu/dove-divider.c b/drivers/clk/mvebu/dove-divider.c index d5c5bfa35a5a..3e0b52daa35f 100644 --- a/drivers/clk/mvebu/dove-divider.c +++ b/drivers/clk/mvebu/dove-divider.c @@ -247,7 +247,7 @@ static struct clk_onecell_data dove_divider_data = { void __init dove_divider_clk_init(struct device_node *np) { - void *base; + void __iomem *base; base = of_iomap(np, 0); if (WARN_ON(!base)) -- cgit v1.2.3 From ca18d51d77eba6120f56761e5a0e541dbb07fa50 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 21 Jan 2016 18:03:05 -0200 Subject: drm/i915/fbc: wait for a vblank instead of 50ms when enabling Instead of waiting for 50ms, just wait until the next vblank, since it's the minimum requirement. The whole infrastructure of FBC is based on vblanks, so waiting for X vblanks instead of X milliseconds sounds like the correct way to go. Besides, 50ms may be less than a vblank on super slow modes that may or may not exist. There are some small improvements in PC state residency (due to the fact that we're now using 16ms for the common modes instead of 50ms), but the biggest advantage is still the correctness of being vblank-based instead of time-based. v2: - Rebase after changing the patch order. - Update the commit message. v3: - Fix bogus vblank_get() instead of vblank_count() (Ville). - Don't forget to call drm_crtc_vblank_{get,put} (Chris, Ville) - Adjust the performance details on the commit message. v4: - Don't grab the FBC mutex just to grab the vblank (Maarten) Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1453406585-10233-1-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_fbc.c | 39 +++++++++++++++++++++++++++++---------- 2 files changed, 30 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 905e90f25957..83b629b30c61 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -921,9 +921,9 @@ struct i915_fbc { struct intel_fbc_work { bool scheduled; + u32 scheduled_vblank; struct work_struct work; struct drm_framebuffer *fb; - unsigned long enable_jiffies; } work; const char *no_fbc_reason; diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index a1988a486b92..3993b431b02a 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -381,7 +381,17 @@ static void intel_fbc_work_fn(struct work_struct *__work) container_of(__work, struct drm_i915_private, fbc.work.work); struct intel_fbc_work *work = &dev_priv->fbc.work; struct intel_crtc *crtc = dev_priv->fbc.crtc; - int delay_ms = 50; + struct drm_vblank_crtc *vblank = &dev_priv->dev->vblank[crtc->pipe]; + + if (drm_crtc_vblank_get(&crtc->base)) { + DRM_ERROR("vblank not available for FBC on pipe %c\n", + pipe_name(crtc->pipe)); + + mutex_lock(&dev_priv->fbc.lock); + work->scheduled = false; + mutex_unlock(&dev_priv->fbc.lock); + return; + } retry: /* Delay the actual enabling to let pageflipping cease and the @@ -390,14 +400,16 @@ retry: * vblank to pass after disabling the FBC before we attempt * to modify the control registers. * - * A more complicated solution would involve tracking vblanks - * following the termination of the page-flipping sequence - * and indeed performing the enable as a co-routine and not - * waiting synchronously upon the vblank. - * * WaFbcWaitForVBlankBeforeEnable:ilk,snb + * + * It is also worth mentioning that since work->scheduled_vblank can be + * updated multiple times by the other threads, hitting the timeout is + * not an error condition. We'll just end up hitting the "goto retry" + * case below. */ - wait_remaining_ms_from_jiffies(work->enable_jiffies, delay_ms); + wait_event_timeout(vblank->queue, + drm_crtc_vblank_count(&crtc->base) != work->scheduled_vblank, + msecs_to_jiffies(50)); mutex_lock(&dev_priv->fbc.lock); @@ -406,8 +418,7 @@ retry: goto out; /* Were we delayed again while this function was sleeping? */ - if (time_after(work->enable_jiffies + msecs_to_jiffies(delay_ms), - jiffies)) { + if (drm_crtc_vblank_count(&crtc->base) == work->scheduled_vblank) { mutex_unlock(&dev_priv->fbc.lock); goto retry; } @@ -419,6 +430,7 @@ retry: out: mutex_unlock(&dev_priv->fbc.lock); + drm_crtc_vblank_put(&crtc->base); } static void intel_fbc_cancel_work(struct drm_i915_private *dev_priv) @@ -434,13 +446,20 @@ static void intel_fbc_schedule_activation(struct intel_crtc *crtc) WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock)); + if (drm_crtc_vblank_get(&crtc->base)) { + DRM_ERROR("vblank not available for FBC on pipe %c\n", + pipe_name(crtc->pipe)); + return; + } + /* It is useless to call intel_fbc_cancel_work() in this function since * we're not releasing fbc.lock, so it won't have an opportunity to grab * it to discover that it was cancelled. So we just update the expected * jiffy count. */ work->fb = crtc->base.primary->fb; work->scheduled = true; - work->enable_jiffies = jiffies; + work->scheduled_vblank = drm_crtc_vblank_count(&crtc->base); + drm_crtc_vblank_put(&crtc->base); schedule_work(&work->work); } -- cgit v1.2.3 From 615b40d7e441ee10b859ccc5a3e456c823f42cfa Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:35 -0200 Subject: drm/i915/fbc: extract intel_fbc_can_activate() Extract all the code that checks if the FBC configuration is valid to its own function, making __intel_fbc_update() much simpler. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-3-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_fbc.c | 92 ++++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 3993b431b02a..1440bb32b912 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -516,17 +516,6 @@ static bool crtc_can_fbc(struct intel_crtc *crtc) return true; } -static bool crtc_is_valid(struct intel_crtc *crtc) -{ - if (!intel_crtc_active(&crtc->base)) - return false; - - if (!to_intel_plane_state(crtc->base.primary->state)->visible) - return false; - - return true; -} - static bool multiple_pipes_ok(struct drm_i915_private *dev_priv) { enum pipe pipe; @@ -752,48 +741,40 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc) return effective_w <= max_w && effective_h <= max_h; } -/** - * __intel_fbc_update - activate/deactivate FBC as needed, unlocked - * @crtc: the CRTC that triggered the update - * - * This function completely reevaluates the status of FBC, then activates, - * deactivates or maintains it on the same state. - */ -static void __intel_fbc_update(struct intel_crtc *crtc) +static bool intel_fbc_can_activate(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct drm_plane *primary; struct drm_framebuffer *fb; + struct intel_plane_state *plane_state; struct drm_i915_gem_object *obj; const struct drm_display_mode *adjusted_mode; - WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock)); - - if (!multiple_pipes_ok(dev_priv)) { - set_no_fbc_reason(dev_priv, "more than one pipe active"); - goto out_disable; - } - - if (!dev_priv->fbc.enabled || dev_priv->fbc.crtc != crtc) - return; - - if (!crtc_is_valid(crtc)) { - set_no_fbc_reason(dev_priv, "no output"); - goto out_disable; + if (!intel_crtc_active(&crtc->base)) { + set_no_fbc_reason(dev_priv, "CRTC not active"); + return false; } - fb = crtc->base.primary->fb; + primary = crtc->base.primary; + fb = primary->fb; obj = intel_fb_obj(fb); adjusted_mode = &crtc->config->base.adjusted_mode; + plane_state = to_intel_plane_state(primary->state); + + if (!plane_state->visible) { + set_no_fbc_reason(dev_priv, "primary plane not visible"); + return false; + } if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) || (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) { set_no_fbc_reason(dev_priv, "incompatible mode"); - goto out_disable; + return false; } if (!intel_fbc_hw_tracking_covers_screen(crtc)) { set_no_fbc_reason(dev_priv, "mode too large for compression"); - goto out_disable; + return false; } /* The use of a CPU fence is mandatory in order to detect writes @@ -802,22 +783,22 @@ static void __intel_fbc_update(struct intel_crtc *crtc) if (obj->tiling_mode != I915_TILING_X || obj->fence_reg == I915_FENCE_REG_NONE) { set_no_fbc_reason(dev_priv, "framebuffer not tiled or fenced"); - goto out_disable; + return false; } if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_G4X(dev_priv) && - crtc->base.primary->state->rotation != BIT(DRM_ROTATE_0)) { + plane_state->base.rotation != BIT(DRM_ROTATE_0)) { set_no_fbc_reason(dev_priv, "rotation unsupported"); - goto out_disable; + return false; } if (!stride_is_valid(dev_priv, fb->pitches[0])) { set_no_fbc_reason(dev_priv, "framebuffer stride not supported"); - goto out_disable; + return false; } if (!pixel_format_is_valid(fb)) { set_no_fbc_reason(dev_priv, "pixel format is invalid"); - goto out_disable; + return false; } /* WaFbcExceedCdClockThreshold:hsw,bdw */ @@ -825,7 +806,7 @@ static void __intel_fbc_update(struct intel_crtc *crtc) ilk_pipe_pixel_rate(crtc->config) >= dev_priv->cdclk_freq * 95 / 100) { set_no_fbc_reason(dev_priv, "pixel rate is too big"); - goto out_disable; + return false; } /* It is possible for the required CFB size change without a @@ -841,16 +822,43 @@ static void __intel_fbc_update(struct intel_crtc *crtc) if (intel_fbc_calculate_cfb_size(crtc, fb) > dev_priv->fbc.compressed_fb.size * dev_priv->fbc.threshold) { set_no_fbc_reason(dev_priv, "CFB requirements changed"); + return false; + } + + return true; +} + +/** + * __intel_fbc_update - activate/deactivate FBC as needed, unlocked + * @crtc: the CRTC that triggered the update + * + * This function completely reevaluates the status of FBC, then activates, + * deactivates or maintains it on the same state. + */ +static void __intel_fbc_update(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + + WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock)); + + if (!multiple_pipes_ok(dev_priv)) { + set_no_fbc_reason(dev_priv, "more than one pipe active"); goto out_disable; } + if (!dev_priv->fbc.enabled || dev_priv->fbc.crtc != crtc) + return; + + if (!intel_fbc_can_activate(crtc)) + goto out_disable; + /* If the scanout has not changed, don't modify the FBC settings. * Note that we make the fundamental assumption that the fb->obj * cannot be unpinned (and have its GTT offset and fence revoked) * without first being decoupled from the scanout and FBC disabled. */ if (dev_priv->fbc.crtc == crtc && - dev_priv->fbc.fb_id == fb->base.id && + dev_priv->fbc.fb_id == crtc->base.primary->fb->base.id && dev_priv->fbc.y == crtc->base.y && dev_priv->fbc.active) return; -- cgit v1.2.3 From d22eb66b3cc3d7d486bc9fa8c6fdbce197eede5f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 4 Dec 2015 14:51:36 +0800 Subject: clk: scpi: Fix checking return value of platform_device_register_simple() platform_device_register_simple() returns ERR_PTR on error. Signed-off-by: Axel Lin Signed-off-by: Stephen Boyd --- drivers/clk/clk-scpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/clk-scpi.c b/drivers/clk/clk-scpi.c index cd0f2726f5e0..89e9ca78bb94 100644 --- a/drivers/clk/clk-scpi.c +++ b/drivers/clk/clk-scpi.c @@ -299,7 +299,7 @@ static int scpi_clocks_probe(struct platform_device *pdev) /* Add the virtual cpufreq device */ cpufreq_dev = platform_device_register_simple("scpi-cpufreq", -1, NULL, 0); - if (!cpufreq_dev) + if (IS_ERR(cpufreq_dev)) pr_warn("unable to register cpufreq device"); return 0; -- cgit v1.2.3 From eac2d86d60449bc9852f94853cc156897fe9e893 Mon Sep 17 00:00:00 2001 From: Marc Gonzalez Date: Fri, 29 Jan 2016 15:07:22 +0100 Subject: clk: tango4: rename ARCH_TANGOX to ARCH_TANGO Requested by arm-soc maintainer Kevin Hilman in v9 review. http://article.gmane.org/gmane.linux.ports.arm.kernel/456331 Signed-off-by: Marc Gonzalez Signed-off-by: Stephen Boyd --- drivers/clk/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index b038e3666058..bae4be6501df 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -43,7 +43,7 @@ obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o obj-$(CONFIG_ARCH_STM32) += clk-stm32f4.o -obj-$(CONFIG_ARCH_TANGOX) += clk-tango4.o +obj-$(CONFIG_ARCH_TANGO) += clk-tango4.o obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o obj-$(CONFIG_ARCH_U300) += clk-u300.o obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o -- cgit v1.2.3 From 44a8a257087bf5deb8c77bbb640cf0a15643b017 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:36 -0200 Subject: drm/i915/fbc: extract intel_fbc_can_enable() Make our enable/activate checking model more explicit, especially since we now have intel_fbc_can_activate(). Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-4-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_fbc.c | 46 ++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 1440bb32b912..f76b158e248f 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -828,6 +828,33 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) return true; } +static bool intel_fbc_can_enable(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + + if (intel_vgpu_active(dev_priv->dev)) { + set_no_fbc_reason(dev_priv, "VGPU is active"); + return false; + } + + if (i915.enable_fbc < 0) { + set_no_fbc_reason(dev_priv, "disabled per chip default"); + return false; + } + + if (!i915.enable_fbc) { + set_no_fbc_reason(dev_priv, "disabled per module param"); + return false; + } + + if (!crtc_can_fbc(crtc)) { + set_no_fbc_reason(dev_priv, "no enabled pipes can have FBC"); + return false; + } + + return true; +} + /** * __intel_fbc_update - activate/deactivate FBC as needed, unlocked * @crtc: the CRTC that triggered the update @@ -997,25 +1024,8 @@ void intel_fbc_enable(struct intel_crtc *crtc) WARN_ON(dev_priv->fbc.active); WARN_ON(dev_priv->fbc.crtc != NULL); - if (intel_vgpu_active(dev_priv->dev)) { - set_no_fbc_reason(dev_priv, "VGPU is active"); - goto out; - } - - if (i915.enable_fbc < 0) { - set_no_fbc_reason(dev_priv, "disabled per chip default"); - goto out; - } - - if (!i915.enable_fbc) { - set_no_fbc_reason(dev_priv, "disabled per module param"); + if (!intel_fbc_can_enable(crtc)) goto out; - } - - if (!crtc_can_fbc(crtc)) { - set_no_fbc_reason(dev_priv, "no enabled pipes can have FBC"); - goto out; - } if (intel_fbc_alloc_cfb(crtc)) { set_no_fbc_reason(dev_priv, "not enough stolen memory"); -- cgit v1.2.3 From b183b3f143959b8eea5d0970fd4ffe78df3a0210 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Wed, 23 Dec 2015 18:28:11 -0200 Subject: drm/i915/fbc: introduce struct intel_fbc_reg_params The early return inside __intel_fbc_update does not completely check all the parameters that affect the FBC register values. For example, we currently lack looking at crtc->adjusted_y (for the fence Y offset) and all the parameters that affect the CFB size (for i8xx). Instead of just adding the missing parameters to the check and hoping that any changes to the fbc_activate functions also come with a matching change to the __intel_fbc_update check, introduce a new structure where we store these parameters and use the structure at the fbc_activate function. Of course, it's still possible to access everything from dev_priv in those functions, but IMHO the new code will be harder to break. v2: Rebase. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-5-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 22 ++++++- drivers/gpu/drm/i915/intel_fbc.c | 131 ++++++++++++++++++++++----------------- 2 files changed, 93 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 83b629b30c61..99bac7e0121e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -905,11 +905,9 @@ struct i915_fbc { * it's the outer lock when overlapping with stolen_lock. */ struct mutex lock; unsigned threshold; - unsigned int fb_id; unsigned int possible_framebuffer_bits; unsigned int busy_bits; struct intel_crtc *crtc; - int y; struct drm_mm_node compressed_fb; struct drm_mm_node *compressed_llb; @@ -919,6 +917,24 @@ struct i915_fbc { bool enabled; bool active; + struct intel_fbc_reg_params { + struct { + enum pipe pipe; + enum plane plane; + unsigned int fence_y_offset; + } crtc; + + struct { + u64 ggtt_offset; + uint32_t id; + uint32_t pixel_format; + unsigned int stride; + int fence_reg; + } fb; + + int cfb_size; + } params; + struct intel_fbc_work { bool scheduled; u32 scheduled_vblank; @@ -929,7 +945,7 @@ struct i915_fbc { const char *no_fbc_reason; bool (*is_active)(struct drm_i915_private *dev_priv); - void (*activate)(struct intel_crtc *crtc); + void (*activate)(struct drm_i915_private *dev_priv); void (*deactivate)(struct drm_i915_private *dev_priv); }; diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index f76b158e248f..14200d29383b 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -130,11 +130,9 @@ static void i8xx_fbc_deactivate(struct drm_i915_private *dev_priv) } } -static void i8xx_fbc_activate(struct intel_crtc *crtc) +static void i8xx_fbc_activate(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - struct drm_framebuffer *fb = crtc->base.primary->fb; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct intel_fbc_reg_params *params = &dev_priv->fbc.params; int cfb_pitch; int i; u32 fbc_ctl; @@ -142,9 +140,9 @@ static void i8xx_fbc_activate(struct intel_crtc *crtc) dev_priv->fbc.active = true; /* Note: fbc.threshold == 1 for i8xx */ - cfb_pitch = intel_fbc_calculate_cfb_size(crtc, fb) / FBC_LL_SIZE; - if (fb->pitches[0] < cfb_pitch) - cfb_pitch = fb->pitches[0]; + cfb_pitch = params->cfb_size / FBC_LL_SIZE; + if (params->fb.stride < cfb_pitch) + cfb_pitch = params->fb.stride; /* FBC_CTL wants 32B or 64B units */ if (IS_GEN2(dev_priv)) @@ -161,9 +159,9 @@ static void i8xx_fbc_activate(struct intel_crtc *crtc) /* Set it up... */ fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE; - fbc_ctl2 |= FBC_CTL_PLANE(crtc->plane); + fbc_ctl2 |= FBC_CTL_PLANE(params->crtc.plane); I915_WRITE(FBC_CONTROL2, fbc_ctl2); - I915_WRITE(FBC_FENCE_OFF, get_crtc_fence_y_offset(crtc)); + I915_WRITE(FBC_FENCE_OFF, params->crtc.fence_y_offset); } /* enable it... */ @@ -173,7 +171,7 @@ static void i8xx_fbc_activate(struct intel_crtc *crtc) if (IS_I945GM(dev_priv)) fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; - fbc_ctl |= obj->fence_reg; + fbc_ctl |= params->fb.fence_reg; I915_WRITE(FBC_CONTROL, fbc_ctl); } @@ -182,23 +180,21 @@ static bool i8xx_fbc_is_active(struct drm_i915_private *dev_priv) return I915_READ(FBC_CONTROL) & FBC_CTL_EN; } -static void g4x_fbc_activate(struct intel_crtc *crtc) +static void g4x_fbc_activate(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - struct drm_framebuffer *fb = crtc->base.primary->fb; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct intel_fbc_reg_params *params = &dev_priv->fbc.params; u32 dpfc_ctl; dev_priv->fbc.active = true; - dpfc_ctl = DPFC_CTL_PLANE(crtc->plane) | DPFC_SR_EN; - if (drm_format_plane_cpp(fb->pixel_format, 0) == 2) + dpfc_ctl = DPFC_CTL_PLANE(params->crtc.plane) | DPFC_SR_EN; + if (drm_format_plane_cpp(params->fb.pixel_format, 0) == 2) dpfc_ctl |= DPFC_CTL_LIMIT_2X; else dpfc_ctl |= DPFC_CTL_LIMIT_1X; - dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg; + dpfc_ctl |= DPFC_CTL_FENCE_EN | params->fb.fence_reg; - I915_WRITE(DPFC_FENCE_YOFF, get_crtc_fence_y_offset(crtc)); + I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset); /* enable it... */ I915_WRITE(DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); @@ -230,19 +226,16 @@ static void intel_fbc_recompress(struct drm_i915_private *dev_priv) POSTING_READ(MSG_FBC_REND_STATE); } -static void ilk_fbc_activate(struct intel_crtc *crtc) +static void ilk_fbc_activate(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - struct drm_framebuffer *fb = crtc->base.primary->fb; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct intel_fbc_reg_params *params = &dev_priv->fbc.params; u32 dpfc_ctl; int threshold = dev_priv->fbc.threshold; - unsigned int y_offset; dev_priv->fbc.active = true; - dpfc_ctl = DPFC_CTL_PLANE(crtc->plane); - if (drm_format_plane_cpp(fb->pixel_format, 0) == 2) + dpfc_ctl = DPFC_CTL_PLANE(params->crtc.plane); + if (drm_format_plane_cpp(params->fb.pixel_format, 0) == 2) threshold++; switch (threshold) { @@ -259,18 +252,17 @@ static void ilk_fbc_activate(struct intel_crtc *crtc) } dpfc_ctl |= DPFC_CTL_FENCE_EN; if (IS_GEN5(dev_priv)) - dpfc_ctl |= obj->fence_reg; + dpfc_ctl |= params->fb.fence_reg; - y_offset = get_crtc_fence_y_offset(crtc); - I915_WRITE(ILK_DPFC_FENCE_YOFF, y_offset); - I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID); + I915_WRITE(ILK_DPFC_FENCE_YOFF, params->crtc.fence_y_offset); + I915_WRITE(ILK_FBC_RT_BASE, params->fb.ggtt_offset | ILK_FBC_RT_VALID); /* enable it... */ I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); if (IS_GEN6(dev_priv)) { I915_WRITE(SNB_DPFC_CTL_SA, - SNB_CPU_FENCE_ENABLE | obj->fence_reg); - I915_WRITE(DPFC_CPU_FENCE_OFFSET, y_offset); + SNB_CPU_FENCE_ENABLE | params->fb.fence_reg); + I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset); } intel_fbc_recompress(dev_priv); @@ -295,11 +287,9 @@ static bool ilk_fbc_is_active(struct drm_i915_private *dev_priv) return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN; } -static void gen7_fbc_activate(struct intel_crtc *crtc) +static void gen7_fbc_activate(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - struct drm_framebuffer *fb = crtc->base.primary->fb; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct intel_fbc_reg_params *params = &dev_priv->fbc.params; u32 dpfc_ctl; int threshold = dev_priv->fbc.threshold; @@ -307,9 +297,9 @@ static void gen7_fbc_activate(struct intel_crtc *crtc) dpfc_ctl = 0; if (IS_IVYBRIDGE(dev_priv)) - dpfc_ctl |= IVB_DPFC_CTL_PLANE(crtc->plane); + dpfc_ctl |= IVB_DPFC_CTL_PLANE(params->crtc.plane); - if (drm_format_plane_cpp(fb->pixel_format, 0) == 2) + if (drm_format_plane_cpp(params->fb.pixel_format, 0) == 2) threshold++; switch (threshold) { @@ -337,16 +327,16 @@ static void gen7_fbc_activate(struct intel_crtc *crtc) ILK_FBCQ_DIS); } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */ - I915_WRITE(CHICKEN_PIPESL_1(crtc->pipe), - I915_READ(CHICKEN_PIPESL_1(crtc->pipe)) | + I915_WRITE(CHICKEN_PIPESL_1(params->crtc.pipe), + I915_READ(CHICKEN_PIPESL_1(params->crtc.pipe)) | HSW_FBCQ_DIS); } I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); I915_WRITE(SNB_DPFC_CTL_SA, - SNB_CPU_FENCE_ENABLE | obj->fence_reg); - I915_WRITE(DPFC_CPU_FENCE_OFFSET, get_crtc_fence_y_offset(crtc)); + SNB_CPU_FENCE_ENABLE | params->fb.fence_reg); + I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset); intel_fbc_recompress(dev_priv); } @@ -364,17 +354,6 @@ bool intel_fbc_is_active(struct drm_i915_private *dev_priv) return dev_priv->fbc.active; } -static void intel_fbc_activate(const struct drm_framebuffer *fb) -{ - struct drm_i915_private *dev_priv = fb->dev->dev_private; - struct intel_crtc *crtc = dev_priv->fbc.crtc; - - dev_priv->fbc.activate(crtc); - - dev_priv->fbc.fb_id = fb->base.id; - dev_priv->fbc.y = crtc->base.y; -} - static void intel_fbc_work_fn(struct work_struct *__work) { struct drm_i915_private *dev_priv = @@ -424,7 +403,7 @@ retry: } if (crtc->base.primary->fb == work->fb) - intel_fbc_activate(work->fb); + dev_priv->fbc.activate(dev_priv); work->scheduled = false; @@ -855,6 +834,42 @@ static bool intel_fbc_can_enable(struct intel_crtc *crtc) return true; } +static void intel_fbc_get_reg_params(struct intel_crtc *crtc, + struct intel_fbc_reg_params *params) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct drm_framebuffer *fb = crtc->base.primary->fb; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); + + /* Since all our fields are integer types, use memset here so the + * comparison function can rely on memcmp because the padding will be + * zero. */ + memset(params, 0, sizeof(*params)); + + params->crtc.pipe = crtc->pipe; + params->crtc.plane = crtc->plane; + params->crtc.fence_y_offset = get_crtc_fence_y_offset(crtc); + + params->fb.id = fb->base.id; + params->fb.pixel_format = fb->pixel_format; + params->fb.stride = fb->pitches[0]; + params->fb.fence_reg = obj->fence_reg; + + params->cfb_size = intel_fbc_calculate_cfb_size(crtc, fb); + + /* FIXME: We lack the proper locking here, so only run this on the + * platforms that need. */ + if (dev_priv->fbc.activate == ilk_fbc_activate) + params->fb.ggtt_offset = i915_gem_obj_ggtt_offset(obj); +} + +static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1, + struct intel_fbc_reg_params *params2) +{ + /* We can use this since intel_fbc_get_reg_params() does a memset. */ + return memcmp(params1, params2, sizeof(*params1)) == 0; +} + /** * __intel_fbc_update - activate/deactivate FBC as needed, unlocked * @crtc: the CRTC that triggered the update @@ -865,6 +880,7 @@ static bool intel_fbc_can_enable(struct intel_crtc *crtc) static void __intel_fbc_update(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_fbc_reg_params old_params; WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock)); @@ -879,15 +895,16 @@ static void __intel_fbc_update(struct intel_crtc *crtc) if (!intel_fbc_can_activate(crtc)) goto out_disable; + old_params = dev_priv->fbc.params; + intel_fbc_get_reg_params(crtc, &dev_priv->fbc.params); + /* If the scanout has not changed, don't modify the FBC settings. * Note that we make the fundamental assumption that the fb->obj * cannot be unpinned (and have its GTT offset and fence revoked) * without first being decoupled from the scanout and FBC disabled. */ - if (dev_priv->fbc.crtc == crtc && - dev_priv->fbc.fb_id == crtc->base.primary->fb->base.id && - dev_priv->fbc.y == crtc->base.y && - dev_priv->fbc.active) + if (dev_priv->fbc.active && + intel_fbc_reg_params_equal(&old_params, &dev_priv->fbc.params)) return; if (intel_fbc_is_active(dev_priv)) { -- cgit v1.2.3 From ab34a7e8b55a1cbe3f0ad1bb2d7d24568ce4d018 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 11 Jan 2016 17:44:36 -0200 Subject: drm/i915/fbc: replace frequent dev_priv->fbc.x with fbc->x We say "dev_priv->fbc.something" way too many times in our code while we could be saying just "fbc->something" with a previous declaration of fbc. This has been bothering me for a while but I didn't want to patch it since I wanted to fix the real problems first. But as I add more code I keep thinking about it, especially since it makes the code easier to read and it can make us fit 80 columns easier, so let's just do the change now. While at it, also rename from i915_fbc to intel_fbc because the whole FBC code uses intel_fbc. v2: Rebase after the work_fn changes. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453406763-10400-1-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 4 +- drivers/gpu/drm/i915/intel_fbc.c | 237 +++++++++++++++++++++------------------ 2 files changed, 132 insertions(+), 109 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 99bac7e0121e..7b44e988fb4e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -900,7 +900,7 @@ enum fb_op_origin { ORIGIN_DIRTYFB, }; -struct i915_fbc { +struct intel_fbc { /* This is always the inner lock when overlapping with struct_mutex and * it's the outer lock when overlapping with stolen_lock. */ struct mutex lock; @@ -1781,7 +1781,7 @@ struct drm_i915_private { u32 pipestat_irq_mask[I915_MAX_PIPES]; struct i915_hotplug hotplug; - struct i915_fbc fbc; + struct intel_fbc fbc; struct i915_drrs drrs; struct intel_opregion opregion; struct intel_vbt_data vbt; diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 14200d29383b..a0bdcef6bf27 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -358,17 +358,18 @@ static void intel_fbc_work_fn(struct work_struct *__work) { struct drm_i915_private *dev_priv = container_of(__work, struct drm_i915_private, fbc.work.work); - struct intel_fbc_work *work = &dev_priv->fbc.work; - struct intel_crtc *crtc = dev_priv->fbc.crtc; + struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc_work *work = &fbc->work; + struct intel_crtc *crtc = fbc->crtc; struct drm_vblank_crtc *vblank = &dev_priv->dev->vblank[crtc->pipe]; if (drm_crtc_vblank_get(&crtc->base)) { DRM_ERROR("vblank not available for FBC on pipe %c\n", pipe_name(crtc->pipe)); - mutex_lock(&dev_priv->fbc.lock); + mutex_lock(&fbc->lock); work->scheduled = false; - mutex_unlock(&dev_priv->fbc.lock); + mutex_unlock(&fbc->lock); return; } @@ -390,7 +391,7 @@ retry: drm_crtc_vblank_count(&crtc->base) != work->scheduled_vblank, msecs_to_jiffies(50)); - mutex_lock(&dev_priv->fbc.lock); + mutex_lock(&fbc->lock); /* Were we cancelled? */ if (!work->scheduled) @@ -398,32 +399,35 @@ retry: /* Were we delayed again while this function was sleeping? */ if (drm_crtc_vblank_count(&crtc->base) == work->scheduled_vblank) { - mutex_unlock(&dev_priv->fbc.lock); + mutex_unlock(&fbc->lock); goto retry; } if (crtc->base.primary->fb == work->fb) - dev_priv->fbc.activate(dev_priv); + fbc->activate(dev_priv); work->scheduled = false; out: - mutex_unlock(&dev_priv->fbc.lock); + mutex_unlock(&fbc->lock); drm_crtc_vblank_put(&crtc->base); } static void intel_fbc_cancel_work(struct drm_i915_private *dev_priv) { - WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock)); - dev_priv->fbc.work.scheduled = false; + struct intel_fbc *fbc = &dev_priv->fbc; + + WARN_ON(!mutex_is_locked(&fbc->lock)); + fbc->work.scheduled = false; } static void intel_fbc_schedule_activation(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - struct intel_fbc_work *work = &dev_priv->fbc.work; + struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc_work *work = &fbc->work; - WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock)); + WARN_ON(!mutex_is_locked(&fbc->lock)); if (drm_crtc_vblank_get(&crtc->base)) { DRM_ERROR("vblank not available for FBC on pipe %c\n", @@ -445,12 +449,14 @@ static void intel_fbc_schedule_activation(struct intel_crtc *crtc) static void __intel_fbc_deactivate(struct drm_i915_private *dev_priv) { - WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock)); + struct intel_fbc *fbc = &dev_priv->fbc; + + WARN_ON(!mutex_is_locked(&fbc->lock)); intel_fbc_cancel_work(dev_priv); - if (dev_priv->fbc.active) - dev_priv->fbc.deactivate(dev_priv); + if (fbc->active) + fbc->deactivate(dev_priv); } /* @@ -462,23 +468,26 @@ static void __intel_fbc_deactivate(struct drm_i915_private *dev_priv) void intel_fbc_deactivate(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_fbc *fbc = &dev_priv->fbc; if (!fbc_supported(dev_priv)) return; - mutex_lock(&dev_priv->fbc.lock); - if (dev_priv->fbc.crtc == crtc) + mutex_lock(&fbc->lock); + if (fbc->crtc == crtc) __intel_fbc_deactivate(dev_priv); - mutex_unlock(&dev_priv->fbc.lock); + mutex_unlock(&fbc->lock); } static void set_no_fbc_reason(struct drm_i915_private *dev_priv, const char *reason) { - if (dev_priv->fbc.no_fbc_reason == reason) + struct intel_fbc *fbc = &dev_priv->fbc; + + if (fbc->no_fbc_reason == reason) return; - dev_priv->fbc.no_fbc_reason = reason; + fbc->no_fbc_reason = reason; DRM_DEBUG_KMS("Disabling FBC: %s\n", reason); } @@ -568,16 +577,17 @@ again: static int intel_fbc_alloc_cfb(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_fbc *fbc = &dev_priv->fbc; struct drm_framebuffer *fb = crtc->base.primary->state->fb; struct drm_mm_node *uninitialized_var(compressed_llb); int size, fb_cpp, ret; - WARN_ON(drm_mm_node_allocated(&dev_priv->fbc.compressed_fb)); + WARN_ON(drm_mm_node_allocated(&fbc->compressed_fb)); size = intel_fbc_calculate_cfb_size(crtc, fb); fb_cpp = drm_format_plane_cpp(fb->pixel_format, 0); - ret = find_compression_threshold(dev_priv, &dev_priv->fbc.compressed_fb, + ret = find_compression_threshold(dev_priv, &fbc->compressed_fb, size, fb_cpp); if (!ret) goto err_llb; @@ -586,12 +596,12 @@ static int intel_fbc_alloc_cfb(struct intel_crtc *crtc) } - dev_priv->fbc.threshold = ret; + fbc->threshold = ret; if (INTEL_INFO(dev_priv)->gen >= 5) - I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->fbc.compressed_fb.start); + I915_WRITE(ILK_DPFC_CB_BASE, fbc->compressed_fb.start); else if (IS_GM45(dev_priv)) { - I915_WRITE(DPFC_CB_BASE, dev_priv->fbc.compressed_fb.start); + I915_WRITE(DPFC_CB_BASE, fbc->compressed_fb.start); } else { compressed_llb = kzalloc(sizeof(*compressed_llb), GFP_KERNEL); if (!compressed_llb) @@ -602,23 +612,22 @@ static int intel_fbc_alloc_cfb(struct intel_crtc *crtc) if (ret) goto err_fb; - dev_priv->fbc.compressed_llb = compressed_llb; + fbc->compressed_llb = compressed_llb; I915_WRITE(FBC_CFB_BASE, - dev_priv->mm.stolen_base + dev_priv->fbc.compressed_fb.start); + dev_priv->mm.stolen_base + fbc->compressed_fb.start); I915_WRITE(FBC_LL_BASE, dev_priv->mm.stolen_base + compressed_llb->start); } DRM_DEBUG_KMS("reserved %llu bytes of contiguous stolen space for FBC, threshold: %d\n", - dev_priv->fbc.compressed_fb.size, - dev_priv->fbc.threshold); + fbc->compressed_fb.size, fbc->threshold); return 0; err_fb: kfree(compressed_llb); - i915_gem_stolen_remove_node(dev_priv, &dev_priv->fbc.compressed_fb); + i915_gem_stolen_remove_node(dev_priv, &fbc->compressed_fb); err_llb: pr_info_once("drm: not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size); return -ENOSPC; @@ -626,25 +635,27 @@ err_llb: static void __intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv) { - if (drm_mm_node_allocated(&dev_priv->fbc.compressed_fb)) - i915_gem_stolen_remove_node(dev_priv, - &dev_priv->fbc.compressed_fb); - - if (dev_priv->fbc.compressed_llb) { - i915_gem_stolen_remove_node(dev_priv, - dev_priv->fbc.compressed_llb); - kfree(dev_priv->fbc.compressed_llb); + struct intel_fbc *fbc = &dev_priv->fbc; + + if (drm_mm_node_allocated(&fbc->compressed_fb)) + i915_gem_stolen_remove_node(dev_priv, &fbc->compressed_fb); + + if (fbc->compressed_llb) { + i915_gem_stolen_remove_node(dev_priv, fbc->compressed_llb); + kfree(fbc->compressed_llb); } } void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv) { + struct intel_fbc *fbc = &dev_priv->fbc; + if (!fbc_supported(dev_priv)) return; - mutex_lock(&dev_priv->fbc.lock); + mutex_lock(&fbc->lock); __intel_fbc_cleanup_cfb(dev_priv); - mutex_unlock(&dev_priv->fbc.lock); + mutex_unlock(&fbc->lock); } static bool stride_is_valid(struct drm_i915_private *dev_priv, @@ -723,6 +734,7 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc) static bool intel_fbc_can_activate(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_fbc *fbc = &dev_priv->fbc; struct drm_plane *primary; struct drm_framebuffer *fb; struct intel_plane_state *plane_state; @@ -799,7 +811,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) * a lot of tracking just for a specific case. If we conclude it's an * important case, we can implement it later. */ if (intel_fbc_calculate_cfb_size(crtc, fb) > - dev_priv->fbc.compressed_fb.size * dev_priv->fbc.threshold) { + fbc->compressed_fb.size * fbc->threshold) { set_no_fbc_reason(dev_priv, "CFB requirements changed"); return false; } @@ -880,31 +892,32 @@ static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1, static void __intel_fbc_update(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_fbc *fbc = &dev_priv->fbc; struct intel_fbc_reg_params old_params; - WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock)); + WARN_ON(!mutex_is_locked(&fbc->lock)); if (!multiple_pipes_ok(dev_priv)) { set_no_fbc_reason(dev_priv, "more than one pipe active"); goto out_disable; } - if (!dev_priv->fbc.enabled || dev_priv->fbc.crtc != crtc) + if (!fbc->enabled || fbc->crtc != crtc) return; if (!intel_fbc_can_activate(crtc)) goto out_disable; - old_params = dev_priv->fbc.params; - intel_fbc_get_reg_params(crtc, &dev_priv->fbc.params); + old_params = fbc->params; + intel_fbc_get_reg_params(crtc, &fbc->params); /* If the scanout has not changed, don't modify the FBC settings. * Note that we make the fundamental assumption that the fb->obj * cannot be unpinned (and have its GTT offset and fence revoked) * without first being decoupled from the scanout and FBC disabled. */ - if (dev_priv->fbc.active && - intel_fbc_reg_params_equal(&old_params, &dev_priv->fbc.params)) + if (fbc->active && + intel_fbc_reg_params_equal(&old_params, &fbc->params)) return; if (intel_fbc_is_active(dev_priv)) { @@ -936,7 +949,7 @@ static void __intel_fbc_update(struct intel_crtc *crtc) } intel_fbc_schedule_activation(crtc); - dev_priv->fbc.no_fbc_reason = "FBC enabled (not necessarily active)"; + fbc->no_fbc_reason = "FBC enabled (not necessarily active)"; return; out_disable: @@ -956,19 +969,21 @@ out_disable: void intel_fbc_update(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_fbc *fbc = &dev_priv->fbc; if (!fbc_supported(dev_priv)) return; - mutex_lock(&dev_priv->fbc.lock); + mutex_lock(&fbc->lock); __intel_fbc_update(crtc); - mutex_unlock(&dev_priv->fbc.lock); + mutex_unlock(&fbc->lock); } void intel_fbc_invalidate(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits, enum fb_op_origin origin) { + struct intel_fbc *fbc = &dev_priv->fbc; unsigned int fbc_bits; if (!fbc_supported(dev_priv)) @@ -977,44 +992,46 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv, if (origin == ORIGIN_GTT) return; - mutex_lock(&dev_priv->fbc.lock); + mutex_lock(&fbc->lock); - if (dev_priv->fbc.enabled) - fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv->fbc.crtc->pipe); + if (fbc->enabled) + fbc_bits = INTEL_FRONTBUFFER_PRIMARY(fbc->crtc->pipe); else - fbc_bits = dev_priv->fbc.possible_framebuffer_bits; + fbc_bits = fbc->possible_framebuffer_bits; - dev_priv->fbc.busy_bits |= (fbc_bits & frontbuffer_bits); + fbc->busy_bits |= (fbc_bits & frontbuffer_bits); - if (dev_priv->fbc.busy_bits) + if (fbc->busy_bits) __intel_fbc_deactivate(dev_priv); - mutex_unlock(&dev_priv->fbc.lock); + mutex_unlock(&fbc->lock); } void intel_fbc_flush(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits, enum fb_op_origin origin) { + struct intel_fbc *fbc = &dev_priv->fbc; + if (!fbc_supported(dev_priv)) return; if (origin == ORIGIN_GTT) return; - mutex_lock(&dev_priv->fbc.lock); + mutex_lock(&fbc->lock); - dev_priv->fbc.busy_bits &= ~frontbuffer_bits; + fbc->busy_bits &= ~frontbuffer_bits; - if (!dev_priv->fbc.busy_bits && dev_priv->fbc.enabled) { - if (origin != ORIGIN_FLIP && dev_priv->fbc.active) { + if (!fbc->busy_bits && fbc->enabled) { + if (origin != ORIGIN_FLIP && fbc->active) { intel_fbc_recompress(dev_priv); } else { __intel_fbc_deactivate(dev_priv); - __intel_fbc_update(dev_priv->fbc.crtc); + __intel_fbc_update(fbc->crtc); } } - mutex_unlock(&dev_priv->fbc.lock); + mutex_unlock(&fbc->lock); } /** @@ -1027,19 +1044,20 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, void intel_fbc_enable(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_fbc *fbc = &dev_priv->fbc; if (!fbc_supported(dev_priv)) return; - mutex_lock(&dev_priv->fbc.lock); + mutex_lock(&fbc->lock); - if (dev_priv->fbc.enabled) { - WARN_ON(dev_priv->fbc.crtc == crtc); + if (fbc->enabled) { + WARN_ON(fbc->crtc == crtc); goto out; } - WARN_ON(dev_priv->fbc.active); - WARN_ON(dev_priv->fbc.crtc != NULL); + WARN_ON(fbc->active); + WARN_ON(fbc->crtc != NULL); if (!intel_fbc_can_enable(crtc)) goto out; @@ -1050,12 +1068,12 @@ void intel_fbc_enable(struct intel_crtc *crtc) } DRM_DEBUG_KMS("Enabling FBC on pipe %c\n", pipe_name(crtc->pipe)); - dev_priv->fbc.no_fbc_reason = "FBC enabled but not active yet\n"; + fbc->no_fbc_reason = "FBC enabled but not active yet\n"; - dev_priv->fbc.enabled = true; - dev_priv->fbc.crtc = crtc; + fbc->enabled = true; + fbc->crtc = crtc; out: - mutex_unlock(&dev_priv->fbc.lock); + mutex_unlock(&fbc->lock); } /** @@ -1067,19 +1085,20 @@ out: */ static void __intel_fbc_disable(struct drm_i915_private *dev_priv) { - struct intel_crtc *crtc = dev_priv->fbc.crtc; + struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_crtc *crtc = fbc->crtc; - WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock)); - WARN_ON(!dev_priv->fbc.enabled); - WARN_ON(dev_priv->fbc.active); + WARN_ON(!mutex_is_locked(&fbc->lock)); + WARN_ON(!fbc->enabled); + WARN_ON(fbc->active); assert_pipe_disabled(dev_priv, crtc->pipe); DRM_DEBUG_KMS("Disabling FBC on pipe %c\n", pipe_name(crtc->pipe)); __intel_fbc_cleanup_cfb(dev_priv); - dev_priv->fbc.enabled = false; - dev_priv->fbc.crtc = NULL; + fbc->enabled = false; + fbc->crtc = NULL; } /** @@ -1091,17 +1110,18 @@ static void __intel_fbc_disable(struct drm_i915_private *dev_priv) void intel_fbc_disable_crtc(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_fbc *fbc = &dev_priv->fbc; if (!fbc_supported(dev_priv)) return; - mutex_lock(&dev_priv->fbc.lock); - if (dev_priv->fbc.crtc == crtc) { - WARN_ON(!dev_priv->fbc.enabled); - WARN_ON(dev_priv->fbc.active); + mutex_lock(&fbc->lock); + if (fbc->crtc == crtc) { + WARN_ON(!fbc->enabled); + WARN_ON(fbc->active); __intel_fbc_disable(dev_priv); } - mutex_unlock(&dev_priv->fbc.lock); + mutex_unlock(&fbc->lock); } /** @@ -1112,13 +1132,15 @@ void intel_fbc_disable_crtc(struct intel_crtc *crtc) */ void intel_fbc_disable(struct drm_i915_private *dev_priv) { + struct intel_fbc *fbc = &dev_priv->fbc; + if (!fbc_supported(dev_priv)) return; - mutex_lock(&dev_priv->fbc.lock); - if (dev_priv->fbc.enabled) + mutex_lock(&fbc->lock); + if (fbc->enabled) __intel_fbc_disable(dev_priv); - mutex_unlock(&dev_priv->fbc.lock); + mutex_unlock(&fbc->lock); } /** @@ -1129,21 +1151,22 @@ void intel_fbc_disable(struct drm_i915_private *dev_priv) */ void intel_fbc_init(struct drm_i915_private *dev_priv) { + struct intel_fbc *fbc = &dev_priv->fbc; enum pipe pipe; - INIT_WORK(&dev_priv->fbc.work.work, intel_fbc_work_fn); - mutex_init(&dev_priv->fbc.lock); - dev_priv->fbc.enabled = false; - dev_priv->fbc.active = false; - dev_priv->fbc.work.scheduled = false; + INIT_WORK(&fbc->work.work, intel_fbc_work_fn); + mutex_init(&fbc->lock); + fbc->enabled = false; + fbc->active = false; + fbc->work.scheduled = false; if (!HAS_FBC(dev_priv)) { - dev_priv->fbc.no_fbc_reason = "unsupported by this chipset"; + fbc->no_fbc_reason = "unsupported by this chipset"; return; } for_each_pipe(dev_priv, pipe) { - dev_priv->fbc.possible_framebuffer_bits |= + fbc->possible_framebuffer_bits |= INTEL_FRONTBUFFER_PRIMARY(pipe); if (fbc_on_pipe_a_only(dev_priv)) @@ -1151,21 +1174,21 @@ void intel_fbc_init(struct drm_i915_private *dev_priv) } if (INTEL_INFO(dev_priv)->gen >= 7) { - dev_priv->fbc.is_active = ilk_fbc_is_active; - dev_priv->fbc.activate = gen7_fbc_activate; - dev_priv->fbc.deactivate = ilk_fbc_deactivate; + fbc->is_active = ilk_fbc_is_active; + fbc->activate = gen7_fbc_activate; + fbc->deactivate = ilk_fbc_deactivate; } else if (INTEL_INFO(dev_priv)->gen >= 5) { - dev_priv->fbc.is_active = ilk_fbc_is_active; - dev_priv->fbc.activate = ilk_fbc_activate; - dev_priv->fbc.deactivate = ilk_fbc_deactivate; + fbc->is_active = ilk_fbc_is_active; + fbc->activate = ilk_fbc_activate; + fbc->deactivate = ilk_fbc_deactivate; } else if (IS_GM45(dev_priv)) { - dev_priv->fbc.is_active = g4x_fbc_is_active; - dev_priv->fbc.activate = g4x_fbc_activate; - dev_priv->fbc.deactivate = g4x_fbc_deactivate; + fbc->is_active = g4x_fbc_is_active; + fbc->activate = g4x_fbc_activate; + fbc->deactivate = g4x_fbc_deactivate; } else { - dev_priv->fbc.is_active = i8xx_fbc_is_active; - dev_priv->fbc.activate = i8xx_fbc_activate; - dev_priv->fbc.deactivate = i8xx_fbc_deactivate; + fbc->is_active = i8xx_fbc_is_active; + fbc->activate = i8xx_fbc_activate; + fbc->deactivate = i8xx_fbc_deactivate; /* This value was pulled out of someone's hat */ I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT); @@ -1174,6 +1197,6 @@ void intel_fbc_init(struct drm_i915_private *dev_priv) /* We still don't have any sort of hardware state readout for FBC, so * deactivate it in case the BIOS activated it to make sure software * matches the hardware state. */ - if (dev_priv->fbc.is_active(dev_priv)) - dev_priv->fbc.deactivate(dev_priv); + if (fbc->is_active(dev_priv)) + fbc->deactivate(dev_priv); } -- cgit v1.2.3 From 0dd81544c9dd1ba867e7cd2e18d719437b3c97c1 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:39 -0200 Subject: drm/i915/fbc: don't use the frontbuffer tracking subsystem for flips Before this patch, page flips would call intel_frontbuffer_flip() and intel_frontbuffer_flip_complete(), which would call intel_fbc_flush(), which would call intel_fbc_update(). The problem is that drawing operations also trigger intel_fbc_flush() calls, so it's not guaranteed that we have the CRTC and FB locks grabbed when intel_fbc_flush() happens, since the call trace may come from the rendering path. We're trying to make the FBC code grab the appropriate CRTC/FB locks, so split the drawing and the flipping logic in order to achieve that in later patches. So now the frontbuffer tracking code is just going to be used for frontbuffer drawing, and intel_fbc_update() is going to be used directly for actual page flips. As a note, we don't need to call intel_fbc_flip() during the two places where we call intel_frontbuffer_flip() since in one of them we already have an intel_fbc_update() call, and in the other we have the planes disabled. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-7-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_display.c | 1 + drivers/gpu/drm/i915/intel_fbc.c | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 304fc9637026..d56b9347543b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10912,6 +10912,7 @@ static void intel_unpin_work_fn(struct work_struct *__work) mutex_unlock(&dev->struct_mutex); intel_frontbuffer_flip_complete(dev, to_intel_plane(primary)->frontbuffer_bit); + intel_fbc_update(crtc); drm_framebuffer_unreference(work->old_fb); BUG_ON(atomic_read(&crtc->unpin_work_count) == 0); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index a0bdcef6bf27..8c765f699061 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -989,7 +989,7 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv, if (!fbc_supported(dev_priv)) return; - if (origin == ORIGIN_GTT) + if (origin == ORIGIN_GTT || origin == ORIGIN_FLIP) return; mutex_lock(&fbc->lock); @@ -1015,7 +1015,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, if (!fbc_supported(dev_priv)) return; - if (origin == ORIGIN_GTT) + if (origin == ORIGIN_GTT || origin == ORIGIN_FLIP) return; mutex_lock(&fbc->lock); @@ -1023,12 +1023,10 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, fbc->busy_bits &= ~frontbuffer_bits; if (!fbc->busy_bits && fbc->enabled) { - if (origin != ORIGIN_FLIP && fbc->active) { + if (fbc->active) intel_fbc_recompress(dev_priv); - } else { - __intel_fbc_deactivate(dev_priv); + else __intel_fbc_update(fbc->crtc); - } } mutex_unlock(&fbc->lock); -- cgit v1.2.3 From 261fe99ac26bde82f44163b0d7f67b9ccf562359 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:40 -0200 Subject: drm/i915/fbc: don't flush for operations on the wrong frontbuffer If frontbuffer_bits doesn't match the current frontbuffer, there's no reason to recompress or update FBC. There was a plan to make the FBC test suite catch this type of problem, but it never got implemented due to being low priority. While at it, also implement Ville's suggestion and use plane->frontbuffer_bit instead of INTEL_FRONTBUFFER_PRIMARY. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-8-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_fbc.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 8c765f699061..a24cb8dc74e2 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -979,12 +979,19 @@ void intel_fbc_update(struct intel_crtc *crtc) mutex_unlock(&fbc->lock); } +static unsigned int intel_fbc_get_frontbuffer_bit(struct intel_fbc *fbc) +{ + if (fbc->enabled) + return to_intel_plane(fbc->crtc->base.primary)->frontbuffer_bit; + else + return fbc->possible_framebuffer_bits; +} + void intel_fbc_invalidate(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits, enum fb_op_origin origin) { struct intel_fbc *fbc = &dev_priv->fbc; - unsigned int fbc_bits; if (!fbc_supported(dev_priv)) return; @@ -994,12 +1001,7 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv, mutex_lock(&fbc->lock); - if (fbc->enabled) - fbc_bits = INTEL_FRONTBUFFER_PRIMARY(fbc->crtc->pipe); - else - fbc_bits = fbc->possible_framebuffer_bits; - - fbc->busy_bits |= (fbc_bits & frontbuffer_bits); + fbc->busy_bits |= intel_fbc_get_frontbuffer_bit(fbc) & frontbuffer_bits; if (fbc->busy_bits) __intel_fbc_deactivate(dev_priv); @@ -1022,7 +1024,8 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, fbc->busy_bits &= ~frontbuffer_bits; - if (!fbc->busy_bits && fbc->enabled) { + if (!fbc->busy_bits && fbc->enabled && + (frontbuffer_bits & intel_fbc_get_frontbuffer_bit(fbc))) { if (fbc->active) intel_fbc_recompress(dev_priv); else -- cgit v1.2.3 From fcf38d134983c1dbc3f426f6e562d93514fde1f1 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 21 Jan 2016 18:07:17 -0200 Subject: drm/i915/fbc: unconditionally update FBC during atomic commits We unconditionally disable/update FBC even during the page flip IOCTLs, and an unconditional disable/update at every atomic commit touching the primary plane shouldn't impact PC state residency noticeably. Besides, the code that checks for rotation is a good hint that we may be forgetting something else, so let's leave all the decisions to intel_fbc.c, making the code much safer. Once we have the code to properly make FBC enable/update decisions based on atomic states, with proper locking, then we'll be able to evaluate whether it will be worth trying to optimize the cases where a disable isn't needed. v2: Upstream moved and now our patch needs to remove dev_priv. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453406837-10511-1-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_display.c | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d56b9347543b..25af60605e8f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11834,7 +11834,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_plane *plane = plane_state->plane; struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct intel_plane_state *old_plane_state = to_intel_plane_state(plane->state); int idx = intel_crtc->base.base.id, ret; @@ -11902,6 +11901,8 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, case DRM_PLANE_TYPE_PRIMARY: intel_crtc->atomic.pre_disable_primary = turn_off; intel_crtc->atomic.post_enable_primary = turn_on; + intel_crtc->atomic.disable_fbc = true; + intel_crtc->atomic.update_fbc = true; if (turn_off) { /* @@ -11913,27 +11914,8 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, * disable. */ intel_crtc->atomic.disable_ips = true; - - intel_crtc->atomic.disable_fbc = true; } - /* - * FBC does not work on some platforms for rotated - * planes, so disable it when rotation is not 0 and - * update it when rotation is set back to 0. - * - * FIXME: This is redundant with the fbc update done in - * the primary plane enable function except that that - * one is done too late. We eventually need to unify - * this. - */ - - if (visible && - INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) && - dev_priv->fbc.crtc == intel_crtc && - plane_state->rotation != BIT(DRM_ROTATE_0)) - intel_crtc->atomic.disable_fbc = true; - /* * BDW signals flip done immediately if the plane * is disabled, even if the plane enable is already @@ -11942,7 +11924,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, if (turn_on && IS_BROADWELL(dev)) intel_crtc->atomic.wait_vblank = true; - intel_crtc->atomic.update_fbc |= visible || mode_changed; break; case DRM_PLANE_TYPE_CURSOR: break; -- cgit v1.2.3 From aaf78d276ba00ad0ab9e51283b3e3e8db8433ead Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:42 -0200 Subject: drm/i915/fbc: introduce struct intel_fbc_state_cache Per the new atomic locking rules, we need to cache the CRTC, plane and FB state structures we use so we can access them later without needing more locks. So do this. Notice that there are some pieces of the FBC code that look at things that are only computed during the modeset, so we can't just can't precompute whether FBC can be activated during the update_state_cache stage. We may be able to do this later. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-10-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 23 +++++++ drivers/gpu/drm/i915/intel_fbc.c | 133 ++++++++++++++++++++++----------------- 2 files changed, 98 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7b44e988fb4e..0df991371001 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -917,6 +917,29 @@ struct intel_fbc { bool enabled; bool active; + struct intel_fbc_state_cache { + struct { + unsigned int mode_flags; + uint32_t hsw_bdw_pixel_rate; + } crtc; + + struct { + unsigned int rotation; + int src_w; + int src_h; + bool visible; + } plane; + + struct { + u64 ilk_ggtt_offset; + uint32_t id; + uint32_t pixel_format; + unsigned int stride; + int fence_reg; + unsigned int tiling_mode; + } fb; + } state_cache; + struct intel_fbc_reg_params { struct { enum pipe pipe; diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index a24cb8dc74e2..49d445a1854e 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -74,19 +74,17 @@ static unsigned int get_crtc_fence_y_offset(struct intel_crtc *crtc) * write to the PLANE_SIZE register. For BDW-, the hardware looks at the value * we wrote to PIPESRC. */ -static void intel_fbc_get_plane_source_size(struct intel_crtc *crtc, +static void intel_fbc_get_plane_source_size(struct intel_fbc_state_cache *cache, int *width, int *height) { - struct intel_plane_state *plane_state = - to_intel_plane_state(crtc->base.primary->state); int w, h; - if (intel_rotation_90_or_270(plane_state->base.rotation)) { - w = drm_rect_height(&plane_state->src) >> 16; - h = drm_rect_width(&plane_state->src) >> 16; + if (intel_rotation_90_or_270(cache->plane.rotation)) { + w = cache->plane.src_h; + h = cache->plane.src_w; } else { - w = drm_rect_width(&plane_state->src) >> 16; - h = drm_rect_height(&plane_state->src) >> 16; + w = cache->plane.src_w; + h = cache->plane.src_h; } if (width) @@ -95,18 +93,17 @@ static void intel_fbc_get_plane_source_size(struct intel_crtc *crtc, *height = h; } -static int intel_fbc_calculate_cfb_size(struct intel_crtc *crtc, - struct drm_framebuffer *fb) +static int intel_fbc_calculate_cfb_size(struct drm_i915_private *dev_priv, + struct intel_fbc_state_cache *cache) { - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; int lines; - intel_fbc_get_plane_source_size(crtc, NULL, &lines); + intel_fbc_get_plane_source_size(cache, NULL, &lines); if (INTEL_INFO(dev_priv)->gen >= 7) lines = min(lines, 2048); /* Hardware needs the full buffer stride, not just the active area. */ - return lines * fb->pitches[0]; + return lines * cache->fb.stride; } static void i8xx_fbc_deactivate(struct drm_i915_private *dev_priv) @@ -578,14 +575,13 @@ static int intel_fbc_alloc_cfb(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_fbc *fbc = &dev_priv->fbc; - struct drm_framebuffer *fb = crtc->base.primary->state->fb; struct drm_mm_node *uninitialized_var(compressed_llb); int size, fb_cpp, ret; WARN_ON(drm_mm_node_allocated(&fbc->compressed_fb)); - size = intel_fbc_calculate_cfb_size(crtc, fb); - fb_cpp = drm_format_plane_cpp(fb->pixel_format, 0); + size = intel_fbc_calculate_cfb_size(dev_priv, &fbc->state_cache); + fb_cpp = drm_format_plane_cpp(fbc->state_cache.fb.pixel_format, 0); ret = find_compression_threshold(dev_priv, &fbc->compressed_fb, size, fb_cpp); @@ -679,19 +675,17 @@ static bool stride_is_valid(struct drm_i915_private *dev_priv, return true; } -static bool pixel_format_is_valid(struct drm_framebuffer *fb) +static bool pixel_format_is_valid(struct drm_i915_private *dev_priv, + uint32_t pixel_format) { - struct drm_device *dev = fb->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - - switch (fb->pixel_format) { + switch (pixel_format) { case DRM_FORMAT_XRGB8888: case DRM_FORMAT_XBGR8888: return true; case DRM_FORMAT_XRGB1555: case DRM_FORMAT_RGB565: /* 16bpp not supported on gen2 */ - if (IS_GEN2(dev)) + if (IS_GEN2(dev_priv)) return false; /* WaFbcOnly1to1Ratio:ctg */ if (IS_G4X(dev_priv)) @@ -711,6 +705,7 @@ static bool pixel_format_is_valid(struct drm_framebuffer *fb) static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_fbc *fbc = &dev_priv->fbc; unsigned int effective_w, effective_h, max_w, max_h; if (INTEL_INFO(dev_priv)->gen >= 8 || IS_HASWELL(dev_priv)) { @@ -724,41 +719,64 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc) max_h = 1536; } - intel_fbc_get_plane_source_size(crtc, &effective_w, &effective_h); + intel_fbc_get_plane_source_size(&fbc->state_cache, &effective_w, + &effective_h); effective_w += crtc->adjusted_x; effective_h += crtc->adjusted_y; return effective_w <= max_w && effective_h <= max_h; } -static bool intel_fbc_can_activate(struct intel_crtc *crtc) +static void intel_fbc_update_state_cache(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_fbc *fbc = &dev_priv->fbc; - struct drm_plane *primary; - struct drm_framebuffer *fb; - struct intel_plane_state *plane_state; + struct intel_fbc_state_cache *cache = &fbc->state_cache; + struct intel_crtc_state *crtc_state = crtc->config; + struct intel_plane_state *plane_state = + to_intel_plane_state(crtc->base.primary->state); + struct drm_framebuffer *fb = plane_state->base.fb; struct drm_i915_gem_object *obj; - const struct drm_display_mode *adjusted_mode; - if (!intel_crtc_active(&crtc->base)) { - set_no_fbc_reason(dev_priv, "CRTC not active"); - return false; - } + cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags; + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) + cache->crtc.hsw_bdw_pixel_rate = + ilk_pipe_pixel_rate(crtc_state); + + cache->plane.rotation = plane_state->base.rotation; + cache->plane.src_w = drm_rect_width(&plane_state->src) >> 16; + cache->plane.src_h = drm_rect_height(&plane_state->src) >> 16; + cache->plane.visible = plane_state->visible; + + if (!cache->plane.visible) + return; - primary = crtc->base.primary; - fb = primary->fb; obj = intel_fb_obj(fb); - adjusted_mode = &crtc->config->base.adjusted_mode; - plane_state = to_intel_plane_state(primary->state); - if (!plane_state->visible) { + /* FIXME: We lack the proper locking here, so only run this on the + * platforms that need. */ + if (dev_priv->fbc.activate == ilk_fbc_activate) + cache->fb.ilk_ggtt_offset = i915_gem_obj_ggtt_offset(obj); + cache->fb.id = fb->base.id; + cache->fb.pixel_format = fb->pixel_format; + cache->fb.stride = fb->pitches[0]; + cache->fb.fence_reg = obj->fence_reg; + cache->fb.tiling_mode = obj->tiling_mode; +} + +static bool intel_fbc_can_activate(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc_state_cache *cache = &fbc->state_cache; + + if (!cache->plane.visible) { set_no_fbc_reason(dev_priv, "primary plane not visible"); return false; } - if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) || - (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) { + if ((cache->crtc.mode_flags & DRM_MODE_FLAG_INTERLACE) || + (cache->crtc.mode_flags & DRM_MODE_FLAG_DBLSCAN)) { set_no_fbc_reason(dev_priv, "incompatible mode"); return false; } @@ -771,31 +789,30 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) /* The use of a CPU fence is mandatory in order to detect writes * by the CPU to the scanout and trigger updates to the FBC. */ - if (obj->tiling_mode != I915_TILING_X || - obj->fence_reg == I915_FENCE_REG_NONE) { + if (cache->fb.tiling_mode != I915_TILING_X || + cache->fb.fence_reg == I915_FENCE_REG_NONE) { set_no_fbc_reason(dev_priv, "framebuffer not tiled or fenced"); return false; } if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_G4X(dev_priv) && - plane_state->base.rotation != BIT(DRM_ROTATE_0)) { + cache->plane.rotation != BIT(DRM_ROTATE_0)) { set_no_fbc_reason(dev_priv, "rotation unsupported"); return false; } - if (!stride_is_valid(dev_priv, fb->pitches[0])) { + if (!stride_is_valid(dev_priv, cache->fb.stride)) { set_no_fbc_reason(dev_priv, "framebuffer stride not supported"); return false; } - if (!pixel_format_is_valid(fb)) { + if (!pixel_format_is_valid(dev_priv, cache->fb.pixel_format)) { set_no_fbc_reason(dev_priv, "pixel format is invalid"); return false; } /* WaFbcExceedCdClockThreshold:hsw,bdw */ if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) && - ilk_pipe_pixel_rate(crtc->config) >= - dev_priv->cdclk_freq * 95 / 100) { + cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk_freq * 95 / 100) { set_no_fbc_reason(dev_priv, "pixel rate is too big"); return false; } @@ -810,7 +827,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) * we didn't get any invalidate/deactivate calls, but this would require * a lot of tracking just for a specific case. If we conclude it's an * important case, we can implement it later. */ - if (intel_fbc_calculate_cfb_size(crtc, fb) > + if (intel_fbc_calculate_cfb_size(dev_priv, &fbc->state_cache) > fbc->compressed_fb.size * fbc->threshold) { set_no_fbc_reason(dev_priv, "CFB requirements changed"); return false; @@ -850,8 +867,8 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, struct intel_fbc_reg_params *params) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - struct drm_framebuffer *fb = crtc->base.primary->fb; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc_state_cache *cache = &fbc->state_cache; /* Since all our fields are integer types, use memset here so the * comparison function can rely on memcmp because the padding will be @@ -862,17 +879,14 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, params->crtc.plane = crtc->plane; params->crtc.fence_y_offset = get_crtc_fence_y_offset(crtc); - params->fb.id = fb->base.id; - params->fb.pixel_format = fb->pixel_format; - params->fb.stride = fb->pitches[0]; - params->fb.fence_reg = obj->fence_reg; + params->fb.id = cache->fb.id; + params->fb.pixel_format = cache->fb.pixel_format; + params->fb.stride = cache->fb.stride; + params->fb.fence_reg = cache->fb.fence_reg; - params->cfb_size = intel_fbc_calculate_cfb_size(crtc, fb); + params->cfb_size = intel_fbc_calculate_cfb_size(dev_priv, cache); - /* FIXME: We lack the proper locking here, so only run this on the - * platforms that need. */ - if (dev_priv->fbc.activate == ilk_fbc_activate) - params->fb.ggtt_offset = i915_gem_obj_ggtt_offset(obj); + params->fb.ggtt_offset = cache->fb.ilk_ggtt_offset; } static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1, @@ -905,6 +919,8 @@ static void __intel_fbc_update(struct intel_crtc *crtc) if (!fbc->enabled || fbc->crtc != crtc) return; + intel_fbc_update_state_cache(crtc); + if (!intel_fbc_can_activate(crtc)) goto out_disable; @@ -1063,6 +1079,7 @@ void intel_fbc_enable(struct intel_crtc *crtc) if (!intel_fbc_can_enable(crtc)) goto out; + intel_fbc_update_state_cache(crtc); if (intel_fbc_alloc_cfb(crtc)) { set_no_fbc_reason(dev_priv, "not enough stolen memory"); goto out; -- cgit v1.2.3 From 212890cfcd25b148665585ac3b2ecb65bad0d538 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:43 -0200 Subject: drm/i915/fbc: split intel_fbc_update into pre and post update So now pre_update will be responsible for unconditionally deactivating FBC and updating the state cache, while post_update will be responsible for checking if it can be enabled, then enabling it. This is one more step into proper locking. Notice that intel_fbc_flush now calls post_update directly. The FBC flush can only happen for drawing operations - since we explicitly ignore the flips -, so the FBC state is not expected to have changed at this point. With this we can just run post_update, which will make sure we won't deactivate+reactivate FBC as would be the case now if we called pre_update + post_update. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-11-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_fbc.c | 77 ++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 49d445a1854e..61523cd95ac1 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -896,24 +896,16 @@ static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1, return memcmp(params1, params2, sizeof(*params1)) == 0; } -/** - * __intel_fbc_update - activate/deactivate FBC as needed, unlocked - * @crtc: the CRTC that triggered the update - * - * This function completely reevaluates the status of FBC, then activates, - * deactivates or maintains it on the same state. - */ -static void __intel_fbc_update(struct intel_crtc *crtc) +static void intel_fbc_pre_update(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_fbc *fbc = &dev_priv->fbc; - struct intel_fbc_reg_params old_params; WARN_ON(!mutex_is_locked(&fbc->lock)); if (!multiple_pipes_ok(dev_priv)) { set_no_fbc_reason(dev_priv, "more than one pipe active"); - goto out_disable; + goto deactivate; } if (!fbc->enabled || fbc->crtc != crtc) @@ -921,8 +913,25 @@ static void __intel_fbc_update(struct intel_crtc *crtc) intel_fbc_update_state_cache(crtc); - if (!intel_fbc_can_activate(crtc)) - goto out_disable; +deactivate: + __intel_fbc_deactivate(dev_priv); +} + +static void intel_fbc_post_update(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc_reg_params old_params; + + WARN_ON(!mutex_is_locked(&fbc->lock)); + + if (!fbc->enabled || fbc->crtc != crtc) + return; + + if (!intel_fbc_can_activate(crtc)) { + WARN_ON(fbc->active); + return; + } old_params = fbc->params; intel_fbc_get_reg_params(crtc, &fbc->params); @@ -936,44 +945,9 @@ static void __intel_fbc_update(struct intel_crtc *crtc) intel_fbc_reg_params_equal(&old_params, &fbc->params)) return; - if (intel_fbc_is_active(dev_priv)) { - /* We update FBC along two paths, after changing fb/crtc - * configuration (modeswitching) and after page-flipping - * finishes. For the latter, we know that not only did - * we disable the FBC at the start of the page-flip - * sequence, but also more than one vblank has passed. - * - * For the former case of modeswitching, it is possible - * to switch between two FBC valid configurations - * instantaneously so we do need to disable the FBC - * before we can modify its control registers. We also - * have to wait for the next vblank for that to take - * effect. However, since we delay enabling FBC we can - * assume that a vblank has passed since disabling and - * that we can safely alter the registers in the deferred - * callback. - * - * In the scenario that we go from a valid to invalid - * and then back to valid FBC configuration we have - * no strict enforcement that a vblank occurred since - * disabling the FBC. However, along all current pipe - * disabling paths we do need to wait for a vblank at - * some point. And we wait before enabling FBC anyway. - */ - DRM_DEBUG_KMS("deactivating FBC for update\n"); - __intel_fbc_deactivate(dev_priv); - } - + __intel_fbc_deactivate(dev_priv); intel_fbc_schedule_activation(crtc); - fbc->no_fbc_reason = "FBC enabled (not necessarily active)"; - return; - -out_disable: - /* Multiple disables should be harmless */ - if (intel_fbc_is_active(dev_priv)) { - DRM_DEBUG_KMS("unsupported config, deactivating FBC\n"); - __intel_fbc_deactivate(dev_priv); - } + fbc->no_fbc_reason = "FBC enabled (active or scheduled)"; } /* @@ -991,7 +965,8 @@ void intel_fbc_update(struct intel_crtc *crtc) return; mutex_lock(&fbc->lock); - __intel_fbc_update(crtc); + intel_fbc_pre_update(crtc); + intel_fbc_post_update(crtc); mutex_unlock(&fbc->lock); } @@ -1045,7 +1020,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, if (fbc->active) intel_fbc_recompress(dev_priv); else - __intel_fbc_update(fbc->crtc); + intel_fbc_post_update(fbc->crtc); } mutex_unlock(&fbc->lock); -- cgit v1.2.3 From 1eb52238a5f5b6a3f497b47e6da39ccfebe6b878 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:44 -0200 Subject: drm/i915/fbc: fix the FBC state checking code We'll now call intel_fbc_pre_update instead of intel_fbc_deactivate during atomic commits. This will continue to guarantee that we deactivate FBC and it will also update the state checking structures at the correct time. Then, later, at the point where we were calling intel_fbc_update, we'll only need to call intel_fbc_post_update. Also add the proper warnings in case we don't have the appropriate locks. Daniel mentioned the warnings will have to be removed for async commits, but let's keep them here while we can. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-12-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_display.c | 11 +++++------ drivers/gpu/drm/i915/intel_drv.h | 8 +++++--- drivers/gpu/drm/i915/intel_fbc.c | 33 ++++++++++++++++++--------------- 3 files changed, 28 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 25af60605e8f..edd0999f61b4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4799,7 +4799,7 @@ static void intel_post_plane_update(struct intel_crtc *crtc) intel_update_watermarks(&crtc->base); if (atomic->update_fbc) - intel_fbc_update(crtc); + intel_fbc_post_update(crtc); if (atomic->post_enable_primary) intel_post_enable_primary(&crtc->base); @@ -4815,8 +4815,8 @@ static void intel_pre_plane_update(struct intel_crtc *crtc) struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc->base.state); - if (atomic->disable_fbc) - intel_fbc_deactivate(crtc); + if (atomic->update_fbc) + intel_fbc_pre_update(crtc); if (crtc->atomic.disable_ips) hsw_disable_ips(crtc); @@ -10912,7 +10912,7 @@ static void intel_unpin_work_fn(struct work_struct *__work) mutex_unlock(&dev->struct_mutex); intel_frontbuffer_flip_complete(dev, to_intel_plane(primary)->frontbuffer_bit); - intel_fbc_update(crtc); + intel_fbc_post_update(crtc); drm_framebuffer_unreference(work->old_fb); BUG_ON(atomic_read(&crtc->unpin_work_count) == 0); @@ -11712,7 +11712,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, to_intel_plane(primary)->frontbuffer_bit); mutex_unlock(&dev->struct_mutex); - intel_fbc_deactivate(intel_crtc); + intel_fbc_pre_update(intel_crtc); intel_frontbuffer_flip_prepare(dev, to_intel_plane(primary)->frontbuffer_bit); @@ -11901,7 +11901,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, case DRM_PLANE_TYPE_PRIMARY: intel_crtc->atomic.pre_disable_primary = turn_off; intel_crtc->atomic.post_enable_primary = turn_on; - intel_crtc->atomic.disable_fbc = true; intel_crtc->atomic.update_fbc = true; if (turn_off) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f620023ed134..b461d7307541 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -542,16 +542,17 @@ struct intel_mmio_flip { */ struct intel_crtc_atomic_commit { /* Sleepable operations to perform before commit */ - bool disable_fbc; bool disable_ips; bool pre_disable_primary; /* Sleepable operations to perform after commit */ unsigned fb_bits; bool wait_vblank; - bool update_fbc; bool post_enable_primary; unsigned update_sprite_watermarks; + + /* Sleepable operations to perform before and after commit */ + bool update_fbc; }; struct intel_crtc { @@ -1330,7 +1331,8 @@ static inline void intel_fbdev_restore_mode(struct drm_device *dev) /* intel_fbc.c */ bool intel_fbc_is_active(struct drm_i915_private *dev_priv); void intel_fbc_deactivate(struct intel_crtc *crtc); -void intel_fbc_update(struct intel_crtc *crtc); +void intel_fbc_pre_update(struct intel_crtc *crtc); +void intel_fbc_post_update(struct intel_crtc *crtc); void intel_fbc_init(struct drm_i915_private *dev_priv); void intel_fbc_enable(struct intel_crtc *crtc); void intel_fbc_disable(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 61523cd95ac1..1c26d65cdd33 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -510,6 +510,7 @@ static bool multiple_pipes_ok(struct drm_i915_private *dev_priv) if (INTEL_INFO(dev_priv)->gen > 4) return true; + /* FIXME: we don't have the appropriate state locks to do this here. */ for_each_pipe(dev_priv, pipe) { crtc = dev_priv->pipe_to_crtc_mapping[pipe]; @@ -732,12 +733,16 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc) struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_fbc *fbc = &dev_priv->fbc; struct intel_fbc_state_cache *cache = &fbc->state_cache; - struct intel_crtc_state *crtc_state = crtc->config; + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); struct intel_plane_state *plane_state = to_intel_plane_state(crtc->base.primary->state); struct drm_framebuffer *fb = plane_state->base.fb; struct drm_i915_gem_object *obj; + WARN_ON(!drm_modeset_is_locked(&crtc->base.mutex)); + WARN_ON(!drm_modeset_is_locked(&crtc->base.primary->mutex)); + cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags; if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) cache->crtc.hsw_bdw_pixel_rate = @@ -896,12 +901,15 @@ static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1, return memcmp(params1, params2, sizeof(*params1)) == 0; } -static void intel_fbc_pre_update(struct intel_crtc *crtc) +void intel_fbc_pre_update(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_fbc *fbc = &dev_priv->fbc; - WARN_ON(!mutex_is_locked(&fbc->lock)); + if (!fbc_supported(dev_priv)) + return; + + mutex_lock(&fbc->lock); if (!multiple_pipes_ok(dev_priv)) { set_no_fbc_reason(dev_priv, "more than one pipe active"); @@ -909,15 +917,17 @@ static void intel_fbc_pre_update(struct intel_crtc *crtc) } if (!fbc->enabled || fbc->crtc != crtc) - return; + goto unlock; intel_fbc_update_state_cache(crtc); deactivate: __intel_fbc_deactivate(dev_priv); +unlock: + mutex_unlock(&fbc->lock); } -static void intel_fbc_post_update(struct intel_crtc *crtc) +static void __intel_fbc_post_update(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_fbc *fbc = &dev_priv->fbc; @@ -950,13 +960,7 @@ static void intel_fbc_post_update(struct intel_crtc *crtc) fbc->no_fbc_reason = "FBC enabled (active or scheduled)"; } -/* - * intel_fbc_update - activate/deactivate FBC as needed - * @crtc: the CRTC that triggered the update - * - * This function reevaluates the overall state and activates or deactivates FBC. - */ -void intel_fbc_update(struct intel_crtc *crtc) +void intel_fbc_post_update(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_fbc *fbc = &dev_priv->fbc; @@ -965,8 +969,7 @@ void intel_fbc_update(struct intel_crtc *crtc) return; mutex_lock(&fbc->lock); - intel_fbc_pre_update(crtc); - intel_fbc_post_update(crtc); + __intel_fbc_post_update(crtc); mutex_unlock(&fbc->lock); } @@ -1020,7 +1023,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, if (fbc->active) intel_fbc_recompress(dev_priv); else - intel_fbc_post_update(fbc->crtc); + __intel_fbc_post_update(fbc->crtc); } mutex_unlock(&fbc->lock); -- cgit v1.2.3 From 60eb2cc71c7b581bcd499739f021750c2eb1c8b5 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:45 -0200 Subject: drm/i915/fbc: unexport intel_fbc_deactivate With the addition and usage of intel_fbc_pre_update, intel_fbc_deactivate is not used anymore outside intel_fbc.c, so kill the exported function and rename __intel_fbc_deactivate. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-13-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_drv.h | 1 - drivers/gpu/drm/i915/intel_fbc.c | 28 ++++------------------------ 2 files changed, 4 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index b461d7307541..ee07bf9209fa 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1330,7 +1330,6 @@ static inline void intel_fbdev_restore_mode(struct drm_device *dev) /* intel_fbc.c */ bool intel_fbc_is_active(struct drm_i915_private *dev_priv); -void intel_fbc_deactivate(struct intel_crtc *crtc); void intel_fbc_pre_update(struct intel_crtc *crtc); void intel_fbc_post_update(struct intel_crtc *crtc); void intel_fbc_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 1c26d65cdd33..74e6bcdc62b4 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -444,7 +444,7 @@ static void intel_fbc_schedule_activation(struct intel_crtc *crtc) schedule_work(&work->work); } -static void __intel_fbc_deactivate(struct drm_i915_private *dev_priv) +static void intel_fbc_deactivate(struct drm_i915_private *dev_priv) { struct intel_fbc *fbc = &dev_priv->fbc; @@ -456,26 +456,6 @@ static void __intel_fbc_deactivate(struct drm_i915_private *dev_priv) fbc->deactivate(dev_priv); } -/* - * intel_fbc_deactivate - deactivate FBC if it's associated with crtc - * @crtc: the CRTC - * - * This function deactivates FBC if it's associated with the provided CRTC. - */ -void intel_fbc_deactivate(struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - struct intel_fbc *fbc = &dev_priv->fbc; - - if (!fbc_supported(dev_priv)) - return; - - mutex_lock(&fbc->lock); - if (fbc->crtc == crtc) - __intel_fbc_deactivate(dev_priv); - mutex_unlock(&fbc->lock); -} - static void set_no_fbc_reason(struct drm_i915_private *dev_priv, const char *reason) { @@ -922,7 +902,7 @@ void intel_fbc_pre_update(struct intel_crtc *crtc) intel_fbc_update_state_cache(crtc); deactivate: - __intel_fbc_deactivate(dev_priv); + intel_fbc_deactivate(dev_priv); unlock: mutex_unlock(&fbc->lock); } @@ -955,7 +935,7 @@ static void __intel_fbc_post_update(struct intel_crtc *crtc) intel_fbc_reg_params_equal(&old_params, &fbc->params)) return; - __intel_fbc_deactivate(dev_priv); + intel_fbc_deactivate(dev_priv); intel_fbc_schedule_activation(crtc); fbc->no_fbc_reason = "FBC enabled (active or scheduled)"; } @@ -998,7 +978,7 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv, fbc->busy_bits |= intel_fbc_get_frontbuffer_bit(fbc) & frontbuffer_bits; if (fbc->busy_bits) - __intel_fbc_deactivate(dev_priv); + intel_fbc_deactivate(dev_priv); mutex_unlock(&fbc->lock); } -- cgit v1.2.3 From c937ab3e584ea66433ce743a42c752e31f3acdbe Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:46 -0200 Subject: drm/i915/fbc: rename the FBC disable functions Instead of: - intel_fbc_disable_crtc(crtc) - intel_fbc_disable(dev_priv) we now have: - intel_fbc_disable(crtc) - intel_fbc_global_disable(dev_priv) This is because all the other functions that take a CRTC are called - intel_fbc_something(crtc) Instead of: - intel_fbc_something_crtc(crtc) And I also hope that the word "global" is going to help make it more explicit that "global" is the unusual case, not the opposite. Reported-by: Daniel Vetter Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-14-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_suspend.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 8 ++++---- drivers/gpu/drm/i915/intel_drv.h | 4 ++-- drivers/gpu/drm/i915/intel_fbc.c | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index a2aa09ce3202..6c6bedf3eb37 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -92,7 +92,7 @@ static void i915_restore_display(struct drm_device *dev) } /* only restore FBC info on the platform that supports FBC*/ - intel_fbc_disable(dev_priv); + intel_fbc_global_disable(dev_priv); /* restore FBC interval */ if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev)) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index edd0999f61b4..60108e69982e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5124,7 +5124,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true); - intel_fbc_disable_crtc(intel_crtc); + intel_fbc_disable(intel_crtc); } static void haswell_crtc_disable(struct drm_crtc *crtc) @@ -5176,7 +5176,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) true); } - intel_fbc_disable_crtc(intel_crtc); + intel_fbc_disable(intel_crtc); } static void i9xx_pfit_enable(struct intel_crtc *crtc) @@ -6352,7 +6352,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) if (!IS_GEN2(dev)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); - intel_fbc_disable_crtc(intel_crtc); + intel_fbc_disable(intel_crtc); } static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) @@ -16041,7 +16041,7 @@ void intel_modeset_cleanup(struct drm_device *dev) intel_unregister_dsm_handler(); - intel_fbc_disable(dev_priv); + intel_fbc_global_disable(dev_priv); /* flush any delayed tasks or pending work */ flush_scheduled_work(); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ee07bf9209fa..06b04acba3b3 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1334,8 +1334,8 @@ void intel_fbc_pre_update(struct intel_crtc *crtc); void intel_fbc_post_update(struct intel_crtc *crtc); void intel_fbc_init(struct drm_i915_private *dev_priv); void intel_fbc_enable(struct intel_crtc *crtc); -void intel_fbc_disable(struct drm_i915_private *dev_priv); -void intel_fbc_disable_crtc(struct intel_crtc *crtc); +void intel_fbc_disable(struct intel_crtc *crtc); +void intel_fbc_global_disable(struct drm_i915_private *dev_priv); void intel_fbc_invalidate(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits, enum fb_op_origin origin); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 74e6bcdc62b4..04783432d6f7 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -1078,12 +1078,12 @@ static void __intel_fbc_disable(struct drm_i915_private *dev_priv) } /** - * intel_fbc_disable_crtc - disable FBC if it's associated with crtc + * intel_fbc_disable - disable FBC if it's associated with crtc * @crtc: the CRTC * * This function disables FBC if it's associated with the provided CRTC. */ -void intel_fbc_disable_crtc(struct intel_crtc *crtc) +void intel_fbc_disable(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_fbc *fbc = &dev_priv->fbc; @@ -1101,12 +1101,12 @@ void intel_fbc_disable_crtc(struct intel_crtc *crtc) } /** - * intel_fbc_disable - globally disable FBC + * intel_fbc_global_disable - globally disable FBC * @dev_priv: i915 device instance * * This function disables FBC regardless of which CRTC is associated with it. */ -void intel_fbc_disable(struct drm_i915_private *dev_priv) +void intel_fbc_global_disable(struct drm_i915_private *dev_priv) { struct intel_fbc *fbc = &dev_priv->fbc; -- cgit v1.2.3 From 286af315d3f153595ce718fb1e442891f14ed5c0 Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Wed, 27 Jan 2016 17:34:37 +0800 Subject: net: cavium: liquidio: use helpers ns_to_timespec64() Convert the driver to use ns_to_timespec64() to keep consistency with timespec64_to_ns() instead of open coding the same logic. Signed-off-by: Kefeng Wang Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/liquidio/lio_main.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index b89504405b72..872765527081 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -1526,7 +1526,6 @@ static int liquidio_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) { u64 ns; - u32 remainder; unsigned long flags; struct lio *lio = container_of(ptp, struct lio, ptp_info); struct octeon_device *oct = (struct octeon_device *)lio->oct_dev; @@ -1536,8 +1535,7 @@ static int liquidio_ptp_gettime(struct ptp_clock_info *ptp, ns += lio->ptp_adjust; spin_unlock_irqrestore(&lio->ptp_lock, flags); - ts->tv_sec = div_u64_rem(ns, 1000000000ULL, &remainder); - ts->tv_nsec = remainder; + *ts = ns_to_timespec64(ns); return 0; } -- cgit v1.2.3 From 65c7600f07d4eb372c078dcd7138a9276f5705eb Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:47 -0200 Subject: drm/i915/fbc: make sure we cancel the work function at fbc_disable Just to be sure nothing will survive a module unload. We need to do this after the unlock in order to make sure the function won't get stuck trying to grab the lock we already own while we wait for it to finish. Reported-by: Reported-by: Daniel Vetter Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-15-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_fbc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 04783432d6f7..35d265092bc1 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -1098,6 +1098,8 @@ void intel_fbc_disable(struct intel_crtc *crtc) __intel_fbc_disable(dev_priv); } mutex_unlock(&fbc->lock); + + cancel_work_sync(&fbc->work.work); } /** @@ -1117,6 +1119,8 @@ void intel_fbc_global_disable(struct drm_i915_private *dev_priv) if (fbc->enabled) __intel_fbc_disable(dev_priv); mutex_unlock(&fbc->lock); + + cancel_work_sync(&fbc->work.work); } /** -- cgit v1.2.3 From de7d244d0a351f27cfef5f51088ea9a64054c948 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Wed, 27 Jan 2016 17:50:43 +0100 Subject: macvlan: make operstate and carrier more accurate Currently when a macvlan is being initialized and the lower device is netif_carrier_ok(), the macvlan device doesn't run through rfc2863_policy() and is left with UNKNOWN operstate. Fix it by adding an unconditional linkwatch event for the new macvlan device. Similar fix is already used by the 8021q device (see register_vlan_dev()). Also fix the inconsistent state when the lower device has been down and its carrier was changed (when a device is down NETDEV_CHANGE doesn't get generated). The second issue can be seen f.e. when we have a macvlan on top of a 8021q device which has been down and its real device has been changing carrier states, after setting the 8021q device up, the macvlan device will have the same carrier state as it was before even though the 8021q can now have a different state. Example for case 1: 4: eth2: mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000 $ ip l add l eth2 macvl0 type macvlan $ ip l set macvl0 up $ ip l sh macvl0 72: macvl0@eth2: mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default link/ether f6:0b:54:0a:9d:a3 brd ff:ff:ff:ff:ff:ff Example for case 2 (order is important): Prestate: eth2 UP/CARRIER, vlan1 down, vlan1-macvlan down $ ip l set vlan1-macvlan up $ ip l sh vlan1-macvlan 71: vlan1-macvlan@vlan1: mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default link/ether 4a:b8:44:56:b9:b9 brd ff:ff:ff:ff:ff:ff [ eth2 loses CARRIER before vlan1 has been UP-ed ] $ ip l sh eth2 4: eth2: mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000 link/ether 52:54:00:bf:57:16 brd ff:ff:ff:ff:ff:ff $ ip l sh vlan1-macvlan 71: vlan1-macvlan@vlan1: mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default link/ether 4a:b8:44:56:b9:b9 brd ff:ff:ff:ff:ff:ff $ ip l set vlan1 up $ ip l sh vlan1 70: vlan1@eth2: mtu 1500 qdisc noqueue state LOWERLAYERDOWN mode DEFAULT group default qlen 1000 link/ether 52:54:00:bf:57:16 brd ff:ff:ff:ff:ff:ff $ ip l sh vlan1-macvlan 71: vlan1-macvlan@vlan1: mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default link/ether 4a:b8:44:56:b9:b9 brd ff:ff:ff:ff:ff:ff vlan1-macvlan is still UP, still has carrier and is still in the same operstate as before. After the patch in case 1 macvl0 has state UP as it should and in case 2 vlan1-macvlan has state LOWERLAYERDOWN again as it should. Note that while the lower macvlan device is down their carrier and thus operstate can go out of sync but that will be fixed once the lower device goes up again. This behaviour seems to have been present since beginning of git history. Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 6a57a005e0ca..94e688805dd2 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -1323,6 +1323,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, list_add_tail_rcu(&vlan->list, &port->vlans); netif_stacked_transfer_operstate(lowerdev, dev); + linkwatch_fire_event(dev); return 0; @@ -1522,6 +1523,7 @@ static int macvlan_device_event(struct notifier_block *unused, port = macvlan_port_get_rtnl(dev); switch (event) { + case NETDEV_UP: case NETDEV_CHANGE: list_for_each_entry(vlan, &port->vlans, list) netif_stacked_transfer_operstate(vlan->lowerdev, -- cgit v1.2.3 From 010cf73d4648df35585c0c326123b04ab79e4573 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:48 -0200 Subject: drm/i915/fbc: rewrite the multiple_pipes_ok() code for locking Older FBC platforms have this restriction where FBC can't be enabled if multiple pipes are enabled. In the current code, we disable FBC before the second pipe becomes visible. One of the problems with this code is that the current multiple_pipes_ok() implementation just iterates through all CRTCs looking at their states, but it doesn't make sure that the state locks are grabbed. It also can't just grab the locks for every CRTC since this would kill one of the biggest advantages of atomic modesetting. After the recent FBC changes, we now have the appropriate locks for the given CRTC, so we can just try to maintain the state of each CRTC and update it once intel_fbc_pre_update is called. As a last note, I don't have gen 2/3 machines to test this code. My current plan is to enable FBC on just the newer platforms, so this patch is just an attempt to get the gen 2/3 code at least looking sane, so if one day someone decide to fix FBC on these platforms, they may have less work to do. Not-tested-by: Paulo Zanoni (only on HSW+) Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-16-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_display.c | 2 ++ drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_fbc.c | 55 +++++++++++++++++++++++++++--------- 4 files changed, 45 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0df991371001..e4da97c6ff9c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -907,6 +907,7 @@ struct intel_fbc { unsigned threshold; unsigned int possible_framebuffer_bits; unsigned int busy_bits; + unsigned int visible_pipes_mask; struct intel_crtc *crtc; struct drm_mm_node compressed_fb; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 60108e69982e..136668a4e684 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15912,6 +15912,8 @@ intel_modeset_setup_hw_state(struct drm_device *dev) modeset_put_power_domains(dev_priv, put_domains); } intel_display_set_init_power(dev_priv, false); + + intel_fbc_init_pipe_state(dev_priv); } void intel_display_resume(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 06b04acba3b3..00a835990bdb 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1333,6 +1333,7 @@ bool intel_fbc_is_active(struct drm_i915_private *dev_priv); void intel_fbc_pre_update(struct intel_crtc *crtc); void intel_fbc_post_update(struct intel_crtc *crtc); void intel_fbc_init(struct drm_i915_private *dev_priv); +void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv); void intel_fbc_enable(struct intel_crtc *crtc); void intel_fbc_disable(struct intel_crtc *crtc); void intel_fbc_global_disable(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 35d265092bc1..c2ef400a9599 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -56,6 +56,11 @@ static inline bool fbc_on_plane_a_only(struct drm_i915_private *dev_priv) return INTEL_INFO(dev_priv)->gen < 4; } +static inline bool no_fbc_on_multiple_pipes(struct drm_i915_private *dev_priv) +{ + return INTEL_INFO(dev_priv)->gen <= 3; +} + /* * In some platforms where the CRTC's x:0/y:0 coordinates doesn't match the * frontbuffer's x:0/y:0 coordinates we lie to the hardware about the plane's @@ -481,25 +486,25 @@ static bool crtc_can_fbc(struct intel_crtc *crtc) return true; } -static bool multiple_pipes_ok(struct drm_i915_private *dev_priv) +static bool multiple_pipes_ok(struct intel_crtc *crtc) { - enum pipe pipe; - int n_pipes = 0; - struct drm_crtc *crtc; + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct drm_plane *primary = crtc->base.primary; + struct intel_fbc *fbc = &dev_priv->fbc; + enum pipe pipe = crtc->pipe; - if (INTEL_INFO(dev_priv)->gen > 4) + /* Don't even bother tracking anything we don't need. */ + if (!no_fbc_on_multiple_pipes(dev_priv)) return true; - /* FIXME: we don't have the appropriate state locks to do this here. */ - for_each_pipe(dev_priv, pipe) { - crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + WARN_ON(!drm_modeset_is_locked(&primary->mutex)); - if (intel_crtc_active(crtc) && - to_intel_plane_state(crtc->primary->state)->visible) - n_pipes++; - } + if (to_intel_plane_state(primary->state)->visible) + fbc->visible_pipes_mask |= (1 << pipe); + else + fbc->visible_pipes_mask &= ~(1 << pipe); - return (n_pipes < 2); + return (fbc->visible_pipes_mask & ~(1 << pipe)) != 0; } static int find_compression_threshold(struct drm_i915_private *dev_priv, @@ -891,7 +896,7 @@ void intel_fbc_pre_update(struct intel_crtc *crtc) mutex_lock(&fbc->lock); - if (!multiple_pipes_ok(dev_priv)) { + if (!multiple_pipes_ok(crtc)) { set_no_fbc_reason(dev_priv, "more than one pipe active"); goto deactivate; } @@ -1123,6 +1128,28 @@ void intel_fbc_global_disable(struct drm_i915_private *dev_priv) cancel_work_sync(&fbc->work.work); } +/** + * intel_fbc_init_pipe_state - initialize FBC's CRTC visibility tracking + * @dev_priv: i915 device instance + * + * The FBC code needs to track CRTC visibility since the older platforms can't + * have FBC enabled while multiple pipes are used. This function does the + * initial setup at driver load to make sure FBC is matching the real hardware. + */ +void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv) +{ + struct intel_crtc *crtc; + + /* Don't even bother tracking anything if we don't need. */ + if (!no_fbc_on_multiple_pipes(dev_priv)) + return; + + for_each_intel_crtc(dev_priv->dev, crtc) + if (intel_crtc_active(&crtc->base) && + to_intel_plane_state(crtc->base.primary->state)->visible) + dev_priv->fbc.visible_pipes_mask |= (1 << crtc->pipe); +} + /** * intel_fbc_init - Initialize FBC * @dev_priv: the i915 device -- cgit v1.2.3 From dd8b3bdbdb748e1ae6a7025bf113ab08b09952bb Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:49 -0200 Subject: drm/i915: simplify struct drm_device access at intel_atomic_check() We already have a dev variable, there's no need to access state->dev. Also, I plan to add another dev_priv user here, so declare one for the current user. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-17-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_display.c | 7 ++++--- 1 file changed, 4 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 136668a4e684..189367cea993 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13327,6 +13327,7 @@ static void calc_watermark_data(struct drm_atomic_state *state) static int intel_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { + struct drm_i915_private *dev_priv = to_i915(dev); struct intel_atomic_state *intel_state = to_intel_atomic_state(state); struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; @@ -13369,7 +13370,7 @@ static int intel_atomic_check(struct drm_device *dev, return ret; if (i915.fastboot && - intel_pipe_config_compare(state->dev, + intel_pipe_config_compare(dev, to_intel_crtc_state(crtc->state), pipe_config, true)) { crtc_state->mode_changed = false; @@ -13395,9 +13396,9 @@ static int intel_atomic_check(struct drm_device *dev, if (ret) return ret; } else - intel_state->cdclk = to_i915(state->dev)->cdclk_freq; + intel_state->cdclk = dev_priv->cdclk_freq; - ret = drm_atomic_helper_check_planes(state->dev, state); + ret = drm_atomic_helper_check_planes(dev, state); if (ret) return ret; -- cgit v1.2.3 From f51be2e0e3c54b7146152b39c1b5f569a005ab79 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:50 -0200 Subject: drm/i915/fbc: choose the new FBC CRTC during atomic check This opens the possibility of implementing nicer schemes to choose the CRTC, such as checking the amount of stolen memory available, or choosing the best pipe on platforms that don't die FBC to pipe or plane A. This code was written for another refactor that I ended up discarding, so I don't actually need it, but I figured this patch would be an improvement on its own so I kept it on the series. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-18-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_display.c | 1 + drivers/gpu/drm/i915/intel_drv.h | 4 ++ drivers/gpu/drm/i915/intel_fbc.c | 77 +++++++++++++++++++++++++++++++++--- 3 files changed, 76 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 189367cea993..cd57613176fc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13402,6 +13402,7 @@ static int intel_atomic_check(struct drm_device *dev, if (ret) return ret; + intel_fbc_choose_crtc(dev_priv, state); calc_watermark_data(state); return 0; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 00a835990bdb..93ba14a3bb76 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -492,6 +492,8 @@ struct intel_crtc_state { bool ips_enabled; + bool enable_fbc; + bool double_wide; bool dp_encoder_is_mst; @@ -1329,6 +1331,8 @@ static inline void intel_fbdev_restore_mode(struct drm_device *dev) #endif /* intel_fbc.c */ +void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, + struct drm_atomic_state *state); bool intel_fbc_is_active(struct drm_i915_private *dev_priv); void intel_fbc_pre_update(struct intel_crtc *crtc); void intel_fbc_post_update(struct intel_crtc *crtc); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index c2ef400a9599..5bf7f844d827 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -826,7 +826,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) return true; } -static bool intel_fbc_can_enable(struct intel_crtc *crtc) +static bool intel_fbc_can_choose(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; @@ -1014,12 +1014,77 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, mutex_unlock(&fbc->lock); } +/** + * intel_fbc_choose_crtc - select a CRTC to enable FBC on + * @dev_priv: i915 device instance + * @state: the atomic state structure + * + * This function looks at the proposed state for CRTCs and planes, then chooses + * which pipe is going to have FBC by setting intel_crtc_state->enable_fbc to + * true. + * + * Later, intel_fbc_enable is going to look for state->enable_fbc and then maybe + * enable FBC for the chosen CRTC. If it does, it will set dev_priv->fbc.crtc. + */ +void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, + struct drm_atomic_state *state) +{ + struct intel_fbc *fbc = &dev_priv->fbc; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + struct drm_plane *plane; + struct drm_plane_state *plane_state; + bool fbc_crtc_present = false; + int i, j; + + mutex_lock(&fbc->lock); + + for_each_crtc_in_state(state, crtc, crtc_state, i) { + if (fbc->crtc == to_intel_crtc(crtc)) { + fbc_crtc_present = true; + break; + } + } + /* This atomic commit doesn't involve the CRTC currently tied to FBC. */ + if (!fbc_crtc_present && fbc->crtc != NULL) + goto out; + + /* Simply choose the first CRTC that is compatible and has a visible + * plane. We could go for fancier schemes such as checking the plane + * size, but this would just affect the few platforms that don't tie FBC + * to pipe or plane A. */ + for_each_plane_in_state(state, plane, plane_state, i) { + struct intel_plane_state *intel_plane_state = + to_intel_plane_state(plane_state); + + if (!intel_plane_state->visible) + continue; + + for_each_crtc_in_state(state, crtc, crtc_state, j) { + struct intel_crtc_state *intel_crtc_state = + to_intel_crtc_state(crtc_state); + + if (plane_state->crtc != crtc) + continue; + + if (!intel_fbc_can_choose(to_intel_crtc(crtc))) + break; + + intel_crtc_state->enable_fbc = true; + goto out; + } + } + +out: + mutex_unlock(&fbc->lock); +} + /** * intel_fbc_enable: tries to enable FBC on the CRTC * @crtc: the CRTC * - * This function checks if it's possible to enable FBC on the following CRTC, - * then enables it. Notice that it doesn't activate FBC. + * This function checks if the given CRTC was chosen for FBC, then enables it if + * possible. Notice that it doesn't activate FBC. */ void intel_fbc_enable(struct intel_crtc *crtc) { @@ -1036,12 +1101,12 @@ void intel_fbc_enable(struct intel_crtc *crtc) goto out; } + if (!crtc->config->enable_fbc) + goto out; + WARN_ON(fbc->active); WARN_ON(fbc->crtc != NULL); - if (!intel_fbc_can_enable(crtc)) - goto out; - intel_fbc_update_state_cache(crtc); if (intel_fbc_alloc_cfb(crtc)) { set_no_fbc_reason(dev_priv, "not enough stolen memory"); -- cgit v1.2.3 From 58f9c0bc557588fbe3f54c521dd8c6f20598e64e Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:51 -0200 Subject: drm/i915/fbc: move intel_fbc_{enable, disable} call one level up Instead of duplicating the calls for every platform, let's just put them in the correct places inside intel_atomic_commit. This will also make it easier for us to move the enable call in order to support fasbtoot. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-19-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_display.c | 15 +++------------ drivers/gpu/drm/i915/intel_fbc.c | 2 +- 2 files changed, 4 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index cd57613176fc..69ab07758c7e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4927,8 +4927,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) if (intel_crtc->config->has_pch_encoder) intel_wait_for_vblank(dev, pipe); intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true); - - intel_fbc_enable(intel_crtc); } /* IPS only exists on ULT machines and is tied to pipe A. */ @@ -5041,8 +5039,6 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) intel_wait_for_vblank(dev, hsw_workaround_pipe); intel_wait_for_vblank(dev, hsw_workaround_pipe); } - - intel_fbc_enable(intel_crtc); } static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force) @@ -5123,8 +5119,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) } intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true); - - intel_fbc_disable(intel_crtc); } static void haswell_crtc_disable(struct drm_crtc *crtc) @@ -5175,8 +5169,6 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, true); } - - intel_fbc_disable(intel_crtc); } static void i9xx_pfit_enable(struct intel_crtc *crtc) @@ -6287,8 +6279,6 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) for_each_encoder_on_crtc(dev, crtc, encoder) encoder->enable(encoder); - - intel_fbc_enable(intel_crtc); } static void i9xx_pfit_disable(struct intel_crtc *crtc) @@ -6351,8 +6341,6 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) if (!IS_GEN2(dev)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); - - intel_fbc_disable(intel_crtc); } static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) @@ -6376,6 +6364,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) dev_priv->display.crtc_disable(crtc); intel_crtc->active = false; + intel_fbc_disable(intel_crtc); intel_update_watermarks(crtc); intel_disable_shared_dpll(intel_crtc); @@ -13529,6 +13518,7 @@ static int intel_atomic_commit(struct drm_device *dev, intel_crtc_disable_planes(crtc, crtc_state->plane_mask); dev_priv->display.crtc_disable(crtc); intel_crtc->active = false; + intel_fbc_disable(intel_crtc); intel_disable_shared_dpll(intel_crtc); /* @@ -13568,6 +13558,7 @@ static int intel_atomic_commit(struct drm_device *dev, if (modeset && crtc->state->active) { update_scanline_offset(to_intel_crtc(crtc)); dev_priv->display.crtc_enable(crtc); + intel_fbc_enable(intel_crtc); } if (update_pipe) { diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 5bf7f844d827..60644dd49581 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -1137,7 +1137,7 @@ static void __intel_fbc_disable(struct drm_i915_private *dev_priv) WARN_ON(!mutex_is_locked(&fbc->lock)); WARN_ON(!fbc->enabled); WARN_ON(fbc->active); - assert_pipe_disabled(dev_priv, crtc->pipe); + WARN_ON(crtc->active); DRM_DEBUG_KMS("Disabling FBC on pipe %c\n", pipe_name(crtc->pipe)); -- cgit v1.2.3 From 49227c4ae3d2c8ccb6c71bfb5dfac80ad8c73021 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:52 -0200 Subject: drm/i915/fbc: make FBC work with fastboot Move intel_fbc_enable to a place where it is called regardless of the "modeset" variable, and make sure intel_fbc_enable can be called multiple times without intel_fbc_disable being called. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-20-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_display.c | 4 +++- drivers/gpu/drm/i915/intel_fbc.c | 10 ++++++++-- 2 files changed, 11 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 69ab07758c7e..a832ff1c8e32 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13558,7 +13558,6 @@ static int intel_atomic_commit(struct drm_device *dev, if (modeset && crtc->state->active) { update_scanline_offset(to_intel_crtc(crtc)); dev_priv->display.crtc_enable(crtc); - intel_fbc_enable(intel_crtc); } if (update_pipe) { @@ -13571,6 +13570,9 @@ static int intel_atomic_commit(struct drm_device *dev, if (!modeset) intel_pre_plane_update(intel_crtc); + if (crtc->state->active && intel_crtc->atomic.update_fbc) + intel_fbc_enable(intel_crtc); + if (crtc->state->active && (crtc->state->planes_changed || update_pipe)) drm_atomic_helper_commit_planes_on_crtc(crtc_state); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 60644dd49581..912b953ceb50 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -1084,7 +1084,9 @@ out: * @crtc: the CRTC * * This function checks if the given CRTC was chosen for FBC, then enables it if - * possible. Notice that it doesn't activate FBC. + * possible. Notice that it doesn't activate FBC. It is valid to call + * intel_fbc_enable multiple times for the same pipe without an + * intel_fbc_disable in the middle, as long as it is deactivated. */ void intel_fbc_enable(struct intel_crtc *crtc) { @@ -1097,7 +1099,11 @@ void intel_fbc_enable(struct intel_crtc *crtc) mutex_lock(&fbc->lock); if (fbc->enabled) { - WARN_ON(fbc->crtc == crtc); + WARN_ON(fbc->crtc == NULL); + if (fbc->crtc == crtc) { + WARN_ON(!crtc->config->enable_fbc); + WARN_ON(fbc->active); + } goto out; } -- cgit v1.2.3 From 5bc40472dea771260dc6d6946fd09c1ac3c9cd93 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:53 -0200 Subject: drm/i915/fbc: don't try to deactivate FBC if it's not enabled During FBC invalidation, don't call intel_fbc_deactivate if it's not enabled. This doesn't fix any bug, but helps making the interface saner. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-21-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_fbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 912b953ceb50..2ed9be2f9f23 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -982,7 +982,7 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv, fbc->busy_bits |= intel_fbc_get_frontbuffer_bit(fbc) & frontbuffer_bits; - if (fbc->busy_bits) + if (fbc->enabled && fbc->busy_bits) intel_fbc_deactivate(dev_priv); mutex_unlock(&fbc->lock); -- cgit v1.2.3 From 913a3a6acae3c90e07f96c849c2a071b27a0fc1d Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:54 -0200 Subject: drm/i915/fbc: don't print no_fbc_reason to dmesg Our dmesg messages started being misleading after we converted to the enable+activate model: we always print "Disabling FBC", even when we're just deactivating it. So, for example, when I boot my machine and do "dmesg | grep -i fbc", I see: [drm:intel_fbc_enable] Enabling FBC on pipe A [drm:set_no_fbc_reason] Disabling FBC: framebuffer not tiled or fenced but then, if I read the debugfs file, I will see: $ sudo cat i915_fbc_status FBC enabled Compressing: yes so we can conclude that dmesg is misleading, since FBC is actually enabled. What happened is that we deactivated FBC due to fbcon not being tiled, but when we silently reactivated it when the display manager started. We don't print activation messages since there may be way too many of these operations per second during normal desktop usage. One possible solution would be to change set_no_fbc_reason to correctly differentiate between disable and deactivation, but we removed support from printing activation/deactivation messages in the past because they were too frequent. So instead of doing this, let's just not print anything on dmesg, and leave the debugfs file if the user needs to investigate something. We already print when we enable and disable FBC anyway on a given pipe, so this should already help triaging bugs. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-22-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_fbc.c | 43 +++++++++++++++------------------------- 1 file changed, 16 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 2ed9be2f9f23..cdd99cfe211e 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -461,18 +461,6 @@ static void intel_fbc_deactivate(struct drm_i915_private *dev_priv) fbc->deactivate(dev_priv); } -static void set_no_fbc_reason(struct drm_i915_private *dev_priv, - const char *reason) -{ - struct intel_fbc *fbc = &dev_priv->fbc; - - if (fbc->no_fbc_reason == reason) - return; - - fbc->no_fbc_reason = reason; - DRM_DEBUG_KMS("Disabling FBC: %s\n", reason); -} - static bool crtc_can_fbc(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; @@ -761,18 +749,18 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) struct intel_fbc_state_cache *cache = &fbc->state_cache; if (!cache->plane.visible) { - set_no_fbc_reason(dev_priv, "primary plane not visible"); + fbc->no_fbc_reason = "primary plane not visible"; return false; } if ((cache->crtc.mode_flags & DRM_MODE_FLAG_INTERLACE) || (cache->crtc.mode_flags & DRM_MODE_FLAG_DBLSCAN)) { - set_no_fbc_reason(dev_priv, "incompatible mode"); + fbc->no_fbc_reason = "incompatible mode"; return false; } if (!intel_fbc_hw_tracking_covers_screen(crtc)) { - set_no_fbc_reason(dev_priv, "mode too large for compression"); + fbc->no_fbc_reason = "mode too large for compression"; return false; } @@ -781,29 +769,29 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) */ if (cache->fb.tiling_mode != I915_TILING_X || cache->fb.fence_reg == I915_FENCE_REG_NONE) { - set_no_fbc_reason(dev_priv, "framebuffer not tiled or fenced"); + fbc->no_fbc_reason = "framebuffer not tiled or fenced"; return false; } if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_G4X(dev_priv) && cache->plane.rotation != BIT(DRM_ROTATE_0)) { - set_no_fbc_reason(dev_priv, "rotation unsupported"); + fbc->no_fbc_reason = "rotation unsupported"; return false; } if (!stride_is_valid(dev_priv, cache->fb.stride)) { - set_no_fbc_reason(dev_priv, "framebuffer stride not supported"); + fbc->no_fbc_reason = "framebuffer stride not supported"; return false; } if (!pixel_format_is_valid(dev_priv, cache->fb.pixel_format)) { - set_no_fbc_reason(dev_priv, "pixel format is invalid"); + fbc->no_fbc_reason = "pixel format is invalid"; return false; } /* WaFbcExceedCdClockThreshold:hsw,bdw */ if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) && cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk_freq * 95 / 100) { - set_no_fbc_reason(dev_priv, "pixel rate is too big"); + fbc->no_fbc_reason = "pixel rate is too big"; return false; } @@ -819,7 +807,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) * important case, we can implement it later. */ if (intel_fbc_calculate_cfb_size(dev_priv, &fbc->state_cache) > fbc->compressed_fb.size * fbc->threshold) { - set_no_fbc_reason(dev_priv, "CFB requirements changed"); + fbc->no_fbc_reason = "CFB requirements changed"; return false; } @@ -829,24 +817,25 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) static bool intel_fbc_can_choose(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_fbc *fbc = &dev_priv->fbc; if (intel_vgpu_active(dev_priv->dev)) { - set_no_fbc_reason(dev_priv, "VGPU is active"); + fbc->no_fbc_reason = "VGPU is active"; return false; } if (i915.enable_fbc < 0) { - set_no_fbc_reason(dev_priv, "disabled per chip default"); + fbc->no_fbc_reason = "disabled per chip default"; return false; } if (!i915.enable_fbc) { - set_no_fbc_reason(dev_priv, "disabled per module param"); + fbc->no_fbc_reason = "disabled per module param"; return false; } if (!crtc_can_fbc(crtc)) { - set_no_fbc_reason(dev_priv, "no enabled pipes can have FBC"); + fbc->no_fbc_reason = "no enabled pipes can have FBC"; return false; } @@ -897,7 +886,7 @@ void intel_fbc_pre_update(struct intel_crtc *crtc) mutex_lock(&fbc->lock); if (!multiple_pipes_ok(crtc)) { - set_no_fbc_reason(dev_priv, "more than one pipe active"); + fbc->no_fbc_reason = "more than one pipe active"; goto deactivate; } @@ -1115,7 +1104,7 @@ void intel_fbc_enable(struct intel_crtc *crtc) intel_fbc_update_state_cache(crtc); if (intel_fbc_alloc_cfb(crtc)) { - set_no_fbc_reason(dev_priv, "not enough stolen memory"); + fbc->no_fbc_reason = "not enough stolen memory"; goto out; } -- cgit v1.2.3 From b20d27526cb0e8dd2b7db3b45ec96aecfc02d610 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:55 -0200 Subject: drm/i915/fbc: don't store the fb_id on reg_params We don't actually use fb_id anywhere. We already compare all parameters that matter to the hardware: pixel format, stride, fence_reg and ggtt_offset. The ID shouldn't make a difference. Besides, we already update the FBC data at every modeset/flip, so this can't change behind our backs. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-23-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/intel_fbc.c | 2 -- 2 files changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e4da97c6ff9c..52cd35230f45 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -933,7 +933,6 @@ struct intel_fbc { struct { u64 ilk_ggtt_offset; - uint32_t id; uint32_t pixel_format; unsigned int stride; int fence_reg; @@ -950,7 +949,6 @@ struct intel_fbc { struct { u64 ggtt_offset; - uint32_t id; uint32_t pixel_format; unsigned int stride; int fence_reg; diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index cdd99cfe211e..35e92bc6b9cf 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -735,7 +735,6 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc) * platforms that need. */ if (dev_priv->fbc.activate == ilk_fbc_activate) cache->fb.ilk_ggtt_offset = i915_gem_obj_ggtt_offset(obj); - cache->fb.id = fb->base.id; cache->fb.pixel_format = fb->pixel_format; cache->fb.stride = fb->pitches[0]; cache->fb.fence_reg = obj->fence_reg; @@ -858,7 +857,6 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, params->crtc.plane = crtc->plane; params->crtc.fence_y_offset = get_crtc_fence_y_offset(crtc); - params->fb.id = cache->fb.id; params->fb.pixel_format = cache->fb.pixel_format; params->fb.stride = cache->fb.stride; params->fb.fence_reg = cache->fb.fence_reg; -- cgit v1.2.3 From e8216e502acaad129210c3c8b30cb4ab41e70239 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 19 Jan 2016 11:35:56 -0200 Subject: drm/i915/fbc: call intel_fbc_pre_update earlier during page flips Make sure we do the pre_update - which also deactivates FBC - before we actually schedule the page flip, just to make sure we don't flip to the new FB with FBC still activated for the previous FB. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-24-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a832ff1c8e32..a66220ad2e4a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11617,6 +11617,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, crtc->primary->fb = fb; update_state_fb(crtc->primary); + intel_fbc_pre_update(intel_crtc); work->pending_flip_obj = obj; @@ -11701,7 +11702,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, to_intel_plane(primary)->frontbuffer_bit); mutex_unlock(&dev->struct_mutex); - intel_fbc_pre_update(intel_crtc); intel_frontbuffer_flip_prepare(dev, to_intel_plane(primary)->frontbuffer_bit); -- cgit v1.2.3 From 9b42281f9ddafe459e0b0d91ddf1939fbf84d832 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 18 Jan 2016 15:45:56 -0200 Subject: drm/i915/fbc: don't store/check a pointer to the FB We already make sure we run intel_fbc_update_update during modesets and page flips, and this function takes care of deactivating FBC, so it shouldn't be possible for us to reach the condition we check at intel_fbc_work_fn. So instead of grabbing framebuffer references and adding a lot of code to track when we need to free them, just don't track anything at all since we shouldn't need to. v2: Rebase. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-25-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_fbc.c | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 52cd35230f45..c921ad8e15a7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -961,7 +961,6 @@ struct intel_fbc { bool scheduled; u32 scheduled_vblank; struct work_struct work; - struct drm_framebuffer *fb; } work; const char *no_fbc_reason; diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 35e92bc6b9cf..2c896f95d2c3 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -405,8 +405,7 @@ retry: goto retry; } - if (crtc->base.primary->fb == work->fb) - fbc->activate(dev_priv); + fbc->activate(dev_priv); work->scheduled = false; @@ -441,7 +440,6 @@ static void intel_fbc_schedule_activation(struct intel_crtc *crtc) * we're not releasing fbc.lock, so it won't have an opportunity to grab * it to discover that it was cancelled. So we just update the expected * jiffy count. */ - work->fb = crtc->base.primary->fb; work->scheduled = true; work->scheduled_vblank = drm_crtc_vblank_count(&crtc->base); drm_crtc_vblank_put(&crtc->base); -- cgit v1.2.3 From e35be23f31c9bd42c342aca519bcedbc34b35da4 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 18 Jan 2016 15:56:58 -0200 Subject: drm/i915/fbc: refactor some small functions called only once The FBC fixes we've been doing in the last months required a lot of refactor, so functions that were once big and called from different spots are now small and called only once. IMHO now it's better to just move the contents of these functions to their only callers since this reduces the number of indirections while reading the code. While at it, also improve the related comments a little bit. Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-26-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_fbc.c | 41 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 2c896f95d2c3..5adf6d7620ad 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -414,14 +414,6 @@ out: drm_crtc_vblank_put(&crtc->base); } -static void intel_fbc_cancel_work(struct drm_i915_private *dev_priv) -{ - struct intel_fbc *fbc = &dev_priv->fbc; - - WARN_ON(!mutex_is_locked(&fbc->lock)); - fbc->work.scheduled = false; -} - static void intel_fbc_schedule_activation(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; @@ -436,10 +428,10 @@ static void intel_fbc_schedule_activation(struct intel_crtc *crtc) return; } - /* It is useless to call intel_fbc_cancel_work() in this function since - * we're not releasing fbc.lock, so it won't have an opportunity to grab - * it to discover that it was cancelled. So we just update the expected - * jiffy count. */ + /* It is useless to call intel_fbc_cancel_work() or cancel_work() in + * this function since we're not releasing fbc.lock, so it won't have an + * opportunity to grab it to discover that it was cancelled. So we just + * update the expected jiffy count. */ work->scheduled = true; work->scheduled_vblank = drm_crtc_vblank_count(&crtc->base); drm_crtc_vblank_put(&crtc->base); @@ -453,25 +445,15 @@ static void intel_fbc_deactivate(struct drm_i915_private *dev_priv) WARN_ON(!mutex_is_locked(&fbc->lock)); - intel_fbc_cancel_work(dev_priv); + /* Calling cancel_work() here won't help due to the fact that the work + * function grabs fbc->lock. Just set scheduled to false so the work + * function can know it was cancelled. */ + fbc->work.scheduled = false; if (fbc->active) fbc->deactivate(dev_priv); } -static bool crtc_can_fbc(struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - - if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) - return false; - - if (fbc_on_plane_a_only(dev_priv) && crtc->plane != PLANE_A) - return false; - - return true; -} - static bool multiple_pipes_ok(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; @@ -831,11 +813,16 @@ static bool intel_fbc_can_choose(struct intel_crtc *crtc) return false; } - if (!crtc_can_fbc(crtc)) { + if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) { fbc->no_fbc_reason = "no enabled pipes can have FBC"; return false; } + if (fbc_on_plane_a_only(dev_priv) && crtc->plane != PLANE_A) { + fbc->no_fbc_reason = "no enabled planes can have FBC"; + return false; + } + return true; } -- cgit v1.2.3 From b83ef507d9e2bc25cea40b1fb13ebd1ca7c4969a Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Thu, 28 Jan 2016 10:27:19 +0800 Subject: ptp: ixp46x: use helpers for converting ns to timespec Convert the driver to use ns_to_timespec64() and timespec64_to_ns() instead of open coding the same logic. Signed-off-by: Kefeng Wang Acked-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/ptp/ptp_ixp46x.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ptp/ptp_ixp46x.c b/drivers/ptp/ptp_ixp46x.c index 934c139916c6..ee4f183ef9ee 100644 --- a/drivers/ptp/ptp_ixp46x.c +++ b/drivers/ptp/ptp_ixp46x.c @@ -178,7 +178,6 @@ static int ptp_ixp_adjtime(struct ptp_clock_info *ptp, s64 delta) static int ptp_ixp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) { u64 ns; - u32 remainder; unsigned long flags; struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps); struct ixp46x_ts_regs *regs = ixp_clock->regs; @@ -189,8 +188,7 @@ static int ptp_ixp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) spin_unlock_irqrestore(®ister_lock, flags); - ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder); - ts->tv_nsec = remainder; + *ts = ns_to_timespec64(ns); return 0; } @@ -202,8 +200,7 @@ static int ptp_ixp_settime(struct ptp_clock_info *ptp, struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps); struct ixp46x_ts_regs *regs = ixp_clock->regs; - ns = ts->tv_sec * 1000000000ULL; - ns += ts->tv_nsec; + ns = timespec64_to_ns(ts); spin_lock_irqsave(®ister_lock, flags); -- cgit v1.2.3 From 50359819794b4a16ae35051cd80f2dab025f6019 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 21 Jan 2016 21:53:09 +0100 Subject: clk-divider: make sure read-only dividers do not write to their register Commit e6d5e7d90be9 ("clk-divider: Fix READ_ONLY when divider > 1") removed the special ops struct for read-only clocks and instead opted to handle them inside the regular ops. On the rk3368 this results in breakage as aclkm now gets set a value. While it is the same divider value, the A53 core still doesn't like it, which can result in the cpu ending up in a hang. The reason being that "ACLKENMasserts one clock cycle before the rising edge of ACLKM" and the clock should only be touched when STANDBYWFIL2 is asserted. To fix this, reintroduce the read-only ops but do include the round_rate callback. That way no writes that may be unsafe are done to the divider register in any case. The Rockchip use of the clk_divider_ops is adapted to this split again, as is the nxp, lpc18xx-ccu driver that was included since the original commit. On lpc18xx-ccu the divider seems to always be read-only so only uses the new ops now. Fixes: e6d5e7d90be9 ("clk-divider: Fix READ_ONLY when divider > 1") Reported-by: Zhang Qing Signed-off-by: Heiko Stuebner Signed-off-by: Stephen Boyd --- drivers/clk/clk-divider.c | 11 ++++++++++- drivers/clk/nxp/clk-lpc18xx-ccu.c | 2 +- drivers/clk/rockchip/clk.c | 4 +++- include/linux/clk-provider.h | 1 + 4 files changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index ded3ff4b91b9..aa1dacdaa39d 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -423,6 +423,12 @@ const struct clk_ops clk_divider_ops = { }; EXPORT_SYMBOL_GPL(clk_divider_ops); +const struct clk_ops clk_divider_ro_ops = { + .recalc_rate = clk_divider_recalc_rate, + .round_rate = clk_divider_round_rate, +}; +EXPORT_SYMBOL_GPL(clk_divider_ro_ops); + static struct clk *_register_divider(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, @@ -446,7 +452,10 @@ static struct clk *_register_divider(struct device *dev, const char *name, return ERR_PTR(-ENOMEM); init.name = name; - init.ops = &clk_divider_ops; + if (clk_divider_flags & CLK_DIVIDER_READ_ONLY) + init.ops = &clk_divider_ro_ops; + else + init.ops = &clk_divider_ops; init.flags = flags | CLK_IS_BASIC; init.parent_names = (parent_name ? &parent_name: NULL); init.num_parents = (parent_name ? 1 : 0); diff --git a/drivers/clk/nxp/clk-lpc18xx-ccu.c b/drivers/clk/nxp/clk-lpc18xx-ccu.c index 13aabbb3acbe..558da89555af 100644 --- a/drivers/clk/nxp/clk-lpc18xx-ccu.c +++ b/drivers/clk/nxp/clk-lpc18xx-ccu.c @@ -222,7 +222,7 @@ static void lpc18xx_ccu_register_branch_gate_div(struct lpc18xx_clk_branch *bran div->width = 1; div_hw = &div->hw; - div_ops = &clk_divider_ops; + div_ops = &clk_divider_ro_ops; } branch->gate.reg = branch->offset + reg_base; diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index d9a0b5d4d47f..f7e8693ad28b 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -90,7 +90,9 @@ static struct clk *rockchip_clk_register_branch(const char *name, div->width = div_width; div->lock = lock; div->table = div_table; - div_ops = &clk_divider_ops; + div_ops = (div_flags & CLK_DIVIDER_READ_ONLY) + ? &clk_divider_ro_ops + : &clk_divider_ops; } clk = clk_register_composite(NULL, name, parent_names, num_parents, diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 1143e38555a4..408a60dca353 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -385,6 +385,7 @@ struct clk_divider { #define CLK_DIVIDER_MAX_AT_ZERO BIT(6) extern const struct clk_ops clk_divider_ops; +extern const struct clk_ops clk_divider_ro_ops; unsigned long divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate, unsigned int val, const struct clk_div_table *table, -- cgit v1.2.3 From 26adc5fa276f7cfafda47d27849e6c1c3bff5aba Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Wed, 20 Jan 2016 19:14:21 +0900 Subject: clk: s2mps11: merge two for loops in one The driver already loops once, there is no reason to loop again for a different purpose. Merge the second loop into the first. Signed-off-by: Andi Shyti Reviewed-by: Krzysztof Kozlowski Signed-off-by: Stephen Boyd --- drivers/clk/clk-s2mps11.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c index d266299dfdb1..e7b97f4f53d3 100644 --- a/drivers/clk/clk-s2mps11.c +++ b/drivers/clk/clk-s2mps11.c @@ -244,12 +244,6 @@ static int s2mps11_clk_probe(struct platform_device *pdev) ret = -ENOMEM; goto err_reg; } - } - - for (i = 0; i < S2MPS11_CLKS_NUM; i++) { - /* Skip clocks not present on S2MPS14 */ - if (!clks_init[i].name) - continue; clk_table[i] = s2mps11_clks[i].clk; } -- cgit v1.2.3 From 31ad0e2a9ab0667b40a654e5ba412987587229ea Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Wed, 20 Jan 2016 19:14:22 +0900 Subject: clk: s2mps11: allocate only one structure for clock init The driver allocates three structures, s2mpsxx_clk_init, for three different clock types (s2mps11, s2mps13 and s2mps14). They are quite similar but they differ only by the name. Only one of these structures is used, while the others lie unused in the memory. The clock's name, though, is not such a meaningful information and by assigning the same name to the initial data we can avoid over allocation. The common name chosen will be s2mps11, coherently with the device driver name, instead of the clock device. Therefore, remove the structures associated to s2mps13 and s2mps14 and use only the one referred to s2mps11 for all kind of clocks. Signed-off-by: Andi Shyti Suggested-by: Krzysztof Kozlowski Reviewed-by: Krzysztof Kozlowski Signed-off-by: Stephen Boyd --- drivers/clk/clk-s2mps11.c | 51 +++++++---------------------------------------- 1 file changed, 7 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c index e7b97f4f53d3..3ff2162b36ff 100644 --- a/drivers/clk/clk-s2mps11.c +++ b/drivers/clk/clk-s2mps11.c @@ -99,6 +99,7 @@ static struct clk_ops s2mps11_clk_ops = { .recalc_rate = s2mps11_clk_recalc_rate, }; +/* This s2mps11_clks_init tructure is common to s2mps11, s2mps13 and s2mps14 */ static struct clk_init_data s2mps11_clks_init[S2MPS11_CLKS_NUM] = { [S2MPS11_CLK_AP] = { .name = "s2mps11_ap", @@ -117,37 +118,6 @@ static struct clk_init_data s2mps11_clks_init[S2MPS11_CLKS_NUM] = { }, }; -static struct clk_init_data s2mps13_clks_init[S2MPS11_CLKS_NUM] = { - [S2MPS11_CLK_AP] = { - .name = "s2mps13_ap", - .ops = &s2mps11_clk_ops, - .flags = CLK_IS_ROOT, - }, - [S2MPS11_CLK_CP] = { - .name = "s2mps13_cp", - .ops = &s2mps11_clk_ops, - .flags = CLK_IS_ROOT, - }, - [S2MPS11_CLK_BT] = { - .name = "s2mps13_bt", - .ops = &s2mps11_clk_ops, - .flags = CLK_IS_ROOT, - }, -}; - -static struct clk_init_data s2mps14_clks_init[S2MPS11_CLKS_NUM] = { - [S2MPS11_CLK_AP] = { - .name = "s2mps14_ap", - .ops = &s2mps11_clk_ops, - .flags = CLK_IS_ROOT, - }, - [S2MPS11_CLK_BT] = { - .name = "s2mps14_bt", - .ops = &s2mps11_clk_ops, - .flags = CLK_IS_ROOT, - }, -}; - static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev, struct clk_init_data *clks_init) { @@ -164,12 +134,9 @@ static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev, return ERR_PTR(-EINVAL); } - for (i = 0; i < S2MPS11_CLKS_NUM; i++) { - if (!clks_init[i].name) - continue; /* Skip clocks not present in some devices */ + for (i = 0; i < S2MPS11_CLKS_NUM; i++) of_property_read_string_index(clk_np, "clock-output-names", i, &clks_init[i].name); - } return clk_np; } @@ -179,8 +146,8 @@ static int s2mps11_clk_probe(struct platform_device *pdev) struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct s2mps11_clk *s2mps11_clks, *s2mps11_clk; unsigned int s2mps11_reg; - struct clk_init_data *clks_init; int i, ret = 0; + enum sec_device_type hwid = platform_get_device_id(pdev)->driver_data; s2mps11_clks = devm_kcalloc(&pdev->dev, S2MPS11_CLKS_NUM, sizeof(*s2mps11_clk), GFP_KERNEL); @@ -194,22 +161,18 @@ static int s2mps11_clk_probe(struct platform_device *pdev) if (!clk_table) return -ENOMEM; - switch(platform_get_device_id(pdev)->driver_data) { + switch (hwid) { case S2MPS11X: s2mps11_reg = S2MPS11_REG_RTC_CTRL; - clks_init = s2mps11_clks_init; break; case S2MPS13X: s2mps11_reg = S2MPS13_REG_RTCCTRL; - clks_init = s2mps13_clks_init; break; case S2MPS14X: s2mps11_reg = S2MPS14_REG_RTCCTRL; - clks_init = s2mps14_clks_init; break; case S5M8767X: s2mps11_reg = S5M8767_REG_CTRL1; - clks_init = s2mps11_clks_init; break; default: dev_err(&pdev->dev, "Invalid device type\n"); @@ -217,15 +180,15 @@ static int s2mps11_clk_probe(struct platform_device *pdev) } /* Store clocks of_node in first element of s2mps11_clks array */ - s2mps11_clks->clk_np = s2mps11_clk_parse_dt(pdev, clks_init); + s2mps11_clks->clk_np = s2mps11_clk_parse_dt(pdev, s2mps11_clks_init); if (IS_ERR(s2mps11_clks->clk_np)) return PTR_ERR(s2mps11_clks->clk_np); for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) { - if (!clks_init[i].name) + if (i == S2MPS11_CLK_CP && hwid == S2MPS14X) continue; /* Skip clocks not present in some devices */ s2mps11_clk->iodev = iodev; - s2mps11_clk->hw.init = &clks_init[i]; + s2mps11_clk->hw.init = &s2mps11_clks_init[i]; s2mps11_clk->mask = 1 << i; s2mps11_clk->reg = s2mps11_reg; -- cgit v1.2.3 From 36da4def1ea7a5f698d3096d10316f911e819621 Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Wed, 20 Jan 2016 19:14:23 +0900 Subject: clk: s2mps11: remove redundant static variables declaration The clk_table and clk_data are declared static. The clk_table contains the three clock data structures belonging to the s2mps11 driver. In the probe function it gets stored into clk_data. Remove clk_table and refer directly to clk_data. clk_data, itself, is also declared static. Declare locally it and allocate it inside the probe function, as it is not used anywhere else. Signed-off-by: Andi Shyti Reviewed-by: Krzysztof Kozlowski Signed-off-by: Stephen Boyd --- drivers/clk/clk-s2mps11.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c index 3ff2162b36ff..fac0e2029adc 100644 --- a/drivers/clk/clk-s2mps11.c +++ b/drivers/clk/clk-s2mps11.c @@ -30,9 +30,6 @@ #define s2mps11_name(a) (a->hw.init->name) -static struct clk **clk_table; -static struct clk_onecell_data clk_data; - enum { S2MPS11_CLK_AP = 0, S2MPS11_CLK_CP, @@ -145,6 +142,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev) { struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct s2mps11_clk *s2mps11_clks, *s2mps11_clk; + struct clk_onecell_data *clk_data; unsigned int s2mps11_reg; int i, ret = 0; enum sec_device_type hwid = platform_get_device_id(pdev)->driver_data; @@ -156,9 +154,13 @@ static int s2mps11_clk_probe(struct platform_device *pdev) s2mps11_clk = s2mps11_clks; - clk_table = devm_kcalloc(&pdev->dev, S2MPS11_CLKS_NUM, + clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->clks = devm_kcalloc(&pdev->dev, S2MPS11_CLKS_NUM, sizeof(struct clk *), GFP_KERNEL); - if (!clk_table) + if (!clk_data->clks) return -ENOMEM; switch (hwid) { @@ -207,13 +209,12 @@ static int s2mps11_clk_probe(struct platform_device *pdev) ret = -ENOMEM; goto err_reg; } - clk_table[i] = s2mps11_clks[i].clk; + clk_data->clks[i] = s2mps11_clks[i].clk; } - clk_data.clks = clk_table; - clk_data.clk_num = S2MPS11_CLKS_NUM; + clk_data->clk_num = S2MPS11_CLKS_NUM; of_clk_add_provider(s2mps11_clks->clk_np, of_clk_src_onecell_get, - &clk_data); + clk_data); platform_set_drvdata(pdev, s2mps11_clks); -- cgit v1.2.3 From dedbb2724dca5de4073c261c52fa76bf348f6a0d Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Wed, 20 Jan 2016 19:14:24 +0900 Subject: clk: s2mps11: remove redundant code The definition of s2mps11_name is meant to resolve the name of a given clock. Remove it because the clocks have the same name we can get it directly from the s2mps11_clks_init structure. While in the probe function the s2mps11_clks is used only to iterate through the s2mps11_clks. The naming itself brings confusion and the readability does not improve much. Signed-off-by: Andi Shyti Reviewed-by: Krzysztof Kozlowski Signed-off-by: Stephen Boyd --- drivers/clk/clk-s2mps11.c | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c index fac0e2029adc..371150aabd15 100644 --- a/drivers/clk/clk-s2mps11.c +++ b/drivers/clk/clk-s2mps11.c @@ -28,8 +28,6 @@ #include #include -#define s2mps11_name(a) (a->hw.init->name) - enum { S2MPS11_CLK_AP = 0, S2MPS11_CLK_CP, @@ -141,19 +139,17 @@ static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev, static int s2mps11_clk_probe(struct platform_device *pdev) { struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); - struct s2mps11_clk *s2mps11_clks, *s2mps11_clk; + struct s2mps11_clk *s2mps11_clks; struct clk_onecell_data *clk_data; unsigned int s2mps11_reg; int i, ret = 0; enum sec_device_type hwid = platform_get_device_id(pdev)->driver_data; s2mps11_clks = devm_kcalloc(&pdev->dev, S2MPS11_CLKS_NUM, - sizeof(*s2mps11_clk), GFP_KERNEL); + sizeof(*s2mps11_clks), GFP_KERNEL); if (!s2mps11_clks) return -ENOMEM; - s2mps11_clk = s2mps11_clks; - clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL); if (!clk_data) return -ENOMEM; @@ -186,26 +182,26 @@ static int s2mps11_clk_probe(struct platform_device *pdev) if (IS_ERR(s2mps11_clks->clk_np)) return PTR_ERR(s2mps11_clks->clk_np); - for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) { + for (i = 0; i < S2MPS11_CLKS_NUM; i++) { if (i == S2MPS11_CLK_CP && hwid == S2MPS14X) continue; /* Skip clocks not present in some devices */ - s2mps11_clk->iodev = iodev; - s2mps11_clk->hw.init = &s2mps11_clks_init[i]; - s2mps11_clk->mask = 1 << i; - s2mps11_clk->reg = s2mps11_reg; - - s2mps11_clk->clk = devm_clk_register(&pdev->dev, - &s2mps11_clk->hw); - if (IS_ERR(s2mps11_clk->clk)) { + s2mps11_clks[i].iodev = iodev; + s2mps11_clks[i].hw.init = &s2mps11_clks_init[i]; + s2mps11_clks[i].mask = 1 << i; + s2mps11_clks[i].reg = s2mps11_reg; + + s2mps11_clks[i].clk = devm_clk_register(&pdev->dev, + &s2mps11_clks[i].hw); + if (IS_ERR(s2mps11_clks[i].clk)) { dev_err(&pdev->dev, "Fail to register : %s\n", - s2mps11_name(s2mps11_clk)); - ret = PTR_ERR(s2mps11_clk->clk); + s2mps11_clks_init[i].name); + ret = PTR_ERR(s2mps11_clks[i].clk); goto err_reg; } - s2mps11_clk->lookup = clkdev_create(s2mps11_clk->clk, - s2mps11_name(s2mps11_clk), NULL); - if (!s2mps11_clk->lookup) { + s2mps11_clks[i].lookup = clkdev_create(s2mps11_clks[i].clk, + s2mps11_clks_init[i].name, NULL); + if (!s2mps11_clks[i].lookup) { ret = -ENOMEM; goto err_reg; } -- cgit v1.2.3 From 47727beb26569725f6c200cde2c38bd1e9f6f1b0 Mon Sep 17 00:00:00 2001 From: Loc Ho Date: Tue, 19 Jan 2016 19:27:42 -0700 Subject: clk: xgene: Add SoC and PMD PLL clocks with v2 hardware Add X-Gene SoC and PMD PLL clocks support for v2 hardware. X-Gene SoC v2 and above use an slightly different SoC and PMD PLL hardware logic. Signed-off-by: Loc Ho Signed-off-by: Stephen Boyd --- drivers/clk/clk-xgene.c | 103 +++++++++++++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c index 10224b01b97c..266d573b9134 100644 --- a/drivers/clk/clk-xgene.c +++ b/drivers/clk/clk-xgene.c @@ -29,7 +29,9 @@ #include /* Register SCU_PCPPLL bit fields */ -#define N_DIV_RD(src) (((src) & 0x000001ff)) +#define N_DIV_RD(src) ((src) & 0x000001ff) +#define SC_N_DIV_RD(src) ((src) & 0x0000007f) +#define SC_OUTDIV2(src) (((src) & 0x00000100) >> 8) /* Register SCU_SOCPLL bit fields */ #define CLKR_RD(src) (((src) & 0x07000000)>>24) @@ -63,6 +65,7 @@ struct xgene_clk_pll { spinlock_t *lock; u32 pll_offset; enum xgene_pll_type type; + int version; }; #define to_xgene_clk_pll(_hw) container_of(_hw, struct xgene_clk_pll, hw) @@ -92,27 +95,37 @@ static unsigned long xgene_clk_pll_recalc_rate(struct clk_hw *hw, pll = xgene_clk_read(pllclk->reg + pllclk->pll_offset); - if (pllclk->type == PLL_TYPE_PCP) { - /* - * PLL VCO = Reference clock * NF - * PCP PLL = PLL_VCO / 2 - */ - nout = 2; - fvco = parent_rate * (N_DIV_RD(pll) + 4); + if (pllclk->version <= 1) { + if (pllclk->type == PLL_TYPE_PCP) { + /* + * PLL VCO = Reference clock * NF + * PCP PLL = PLL_VCO / 2 + */ + nout = 2; + fvco = parent_rate * (N_DIV_RD(pll) + 4); + } else { + /* + * Fref = Reference Clock / NREF; + * Fvco = Fref * NFB; + * Fout = Fvco / NOUT; + */ + nref = CLKR_RD(pll) + 1; + nout = CLKOD_RD(pll) + 1; + nfb = CLKF_RD(pll); + fref = parent_rate / nref; + fvco = fref * nfb; + } } else { /* - * Fref = Reference Clock / NREF; - * Fvco = Fref * NFB; - * Fout = Fvco / NOUT; + * fvco = Reference clock * FBDIVC + * PLL freq = fvco / NOUT */ - nref = CLKR_RD(pll) + 1; - nout = CLKOD_RD(pll) + 1; - nfb = CLKF_RD(pll); - fref = parent_rate / nref; - fvco = fref * nfb; + nout = SC_OUTDIV2(pll) ? 2 : 3; + fvco = parent_rate * SC_N_DIV_RD(pll); } - pr_debug("%s pll recalc rate %ld parent %ld\n", clk_hw_get_name(hw), - fvco / nout, parent_rate); + pr_debug("%s pll recalc rate %ld parent %ld version %d\n", + clk_hw_get_name(hw), fvco / nout, parent_rate, + pllclk->version); return fvco / nout; } @@ -125,7 +138,7 @@ static const struct clk_ops xgene_clk_pll_ops = { static struct clk *xgene_register_clk_pll(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u32 pll_offset, - u32 type, spinlock_t *lock) + u32 type, spinlock_t *lock, int version) { struct xgene_clk_pll *apmclk; struct clk *clk; @@ -144,6 +157,7 @@ static struct clk *xgene_register_clk_pll(struct device *dev, init.parent_names = parent_name ? &parent_name : NULL; init.num_parents = parent_name ? 1 : 0; + apmclk->version = version; apmclk->reg = reg; apmclk->lock = lock; apmclk->pll_offset = pll_offset; @@ -160,26 +174,37 @@ static struct clk *xgene_register_clk_pll(struct device *dev, return clk; } +static int xgene_pllclk_version(struct device_node *np) +{ + if (of_device_is_compatible(np, "apm,xgene-socpll-clock")) + return 1; + if (of_device_is_compatible(np, "apm,xgene-pcppll-clock")) + return 1; + return 2; +} + static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_type) { - const char *clk_name = np->full_name; - struct clk *clk; - void __iomem *reg; + const char *clk_name = np->full_name; + struct clk *clk; + void __iomem *reg; + int version = xgene_pllclk_version(np); - reg = of_iomap(np, 0); - if (reg == NULL) { - pr_err("Unable to map CSR register for %s\n", np->full_name); - return; - } - of_property_read_string(np, "clock-output-names", &clk_name); - clk = xgene_register_clk_pll(NULL, - clk_name, of_clk_get_parent_name(np, 0), - CLK_IS_ROOT, reg, 0, pll_type, &clk_lock); - if (!IS_ERR(clk)) { - of_clk_add_provider(np, of_clk_src_simple_get, clk); - clk_register_clkdev(clk, clk_name, NULL); - pr_debug("Add %s clock PLL\n", clk_name); - } + reg = of_iomap(np, 0); + if (reg == NULL) { + pr_err("Unable to map CSR register for %s\n", np->full_name); + return; + } + of_property_read_string(np, "clock-output-names", &clk_name); + clk = xgene_register_clk_pll(NULL, + clk_name, of_clk_get_parent_name(np, 0), + CLK_IS_ROOT, reg, 0, pll_type, &clk_lock, + version); + if (!IS_ERR(clk)) { + of_clk_add_provider(np, of_clk_src_simple_get, clk); + clk_register_clkdev(clk, clk_name, NULL); + pr_debug("Add %s clock PLL\n", clk_name); + } } static void xgene_socpllclk_init(struct device_node *np) @@ -460,7 +485,7 @@ static void __init xgene_devclk_init(struct device_node *np) rc = of_address_to_resource(np, i, &res); if (rc != 0) { if (i == 0) { - pr_err("no DTS register for %s\n", + pr_err("no DTS register for %s\n", np->full_name); return; } @@ -518,4 +543,8 @@ err: CLK_OF_DECLARE(xgene_socpll_clock, "apm,xgene-socpll-clock", xgene_socpllclk_init); CLK_OF_DECLARE(xgene_pcppll_clock, "apm,xgene-pcppll-clock", xgene_pcppllclk_init); +CLK_OF_DECLARE(xgene_socpll_v2_clock, "apm,xgene-socpll-v2-clock", + xgene_socpllclk_init); +CLK_OF_DECLARE(xgene_pcppll_v2_clock, "apm,xgene-pcppll-v2-clock", + xgene_pcppllclk_init); CLK_OF_DECLARE(xgene_dev_clock, "apm,xgene-device-clock", xgene_devclk_init); -- cgit v1.2.3 From f9285b54d657f433746df9232068c32ef138ebc4 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 29 Jan 2016 12:57:15 -0800 Subject: clk: xgene: Remove return from void function This function doesn't return anything because it's void. Drop the return statement. Cc: Loc Ho Signed-off-by: Stephen Boyd --- drivers/clk/clk-xgene.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c index 266d573b9134..bd7156baa08b 100644 --- a/drivers/clk/clk-xgene.c +++ b/drivers/clk/clk-xgene.c @@ -50,7 +50,7 @@ static inline u32 xgene_clk_read(void __iomem *csr) static inline void xgene_clk_write(u32 data, void __iomem *csr) { - return writel_relaxed(data, csr); + writel_relaxed(data, csr); } /* PLL Clock */ -- cgit v1.2.3 From 5fd9c05c846db98319e75496612da24435cee208 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Fri, 8 Jan 2016 23:51:46 +0800 Subject: clk: move the common clock's to_clk_*(_hw) macros to clk-provider.h to_clk_*(_hw) macros have been repeatedly defined in many places. This patch moves all the to_clk_*(_hw) definitions in the common clock framework to public header clk-provider.h, and drop the local definitions. Signed-off-by: Geliang Tang Signed-off-by: Stephen Boyd --- drivers/clk/clk-composite.c | 2 -- drivers/clk/clk-divider.c | 2 -- drivers/clk/clk-fixed-factor.c | 2 -- drivers/clk/clk-fixed-rate.c | 2 -- drivers/clk/clk-fractional-divider.c | 2 -- drivers/clk/clk-gate.c | 2 -- drivers/clk/clk-gpio.c | 2 -- drivers/clk/clk-multiplier.c | 2 -- drivers/clk/clk-mux.c | 2 -- drivers/clk/imx/clk-busy.c | 4 ++-- drivers/clk/imx/clk-fixup-div.c | 5 ++--- drivers/clk/imx/clk-fixup-mux.c | 2 -- drivers/clk/imx/clk-gate-exclusive.c | 2 +- drivers/clk/mediatek/clk-gate.c | 8 ++++---- drivers/clk/mediatek/clk-gate.h | 2 +- drivers/clk/mvebu/common.c | 2 -- drivers/clk/mvebu/kirkwood.c | 2 -- drivers/clk/mxs/clk-div.c | 2 +- drivers/clk/nxp/clk-lpc18xx-ccu.c | 2 -- drivers/clk/st/clkgen-mux.c | 9 ++++----- drivers/clk/ti/composite.c | 2 -- drivers/clk/ti/divider.c | 2 -- drivers/clk/ti/gate.c | 2 -- drivers/clk/ti/mux.c | 2 -- include/linux/clk-provider.h | 18 ++++++++++++++++++ 25 files changed, 33 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index 4735de0660cc..1f903e1f86a2 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -19,8 +19,6 @@ #include #include -#define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw) - static u8 clk_composite_get_parent(struct clk_hw *hw) { struct clk_composite *composite = to_clk_composite(hw); diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index aa1dacdaa39d..7d62dc30e969 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -28,8 +28,6 @@ * parent - fixed parent. No clk_set_parent support */ -#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) - #define div_mask(width) ((1 << (width)) - 1) static unsigned int _get_table_maxdiv(const struct clk_div_table *table, diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index 83de57aeceea..f0ddf37d5e15 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -23,8 +23,6 @@ * parent - fixed parent. No clk_set_parent support */ -#define to_clk_fixed_factor(_hw) container_of(_hw, struct clk_fixed_factor, hw) - static unsigned long clk_factor_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index f85ec8d1711f..e156beb871f0 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c @@ -26,8 +26,6 @@ * parent - fixed parent. No clk_set_parent support */ -#define to_clk_fixed_rate(_hw) container_of(_hw, struct clk_fixed_rate, hw) - static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c index 5c4955e33f7a..1abcd76b4993 100644 --- a/drivers/clk/clk-fractional-divider.c +++ b/drivers/clk/clk-fractional-divider.c @@ -16,8 +16,6 @@ #include #include -#define to_clk_fd(_hw) container_of(_hw, struct clk_fractional_divider, hw) - static unsigned long clk_fd_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index de0b322f5f58..d0d8ec8e1f1b 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -26,8 +26,6 @@ * parent - fixed parent. No clk_set_parent support */ -#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw) - /* * It works on following logic: * diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c index 19fed65587e8..cbbea2985cc9 100644 --- a/drivers/clk/clk-gpio.c +++ b/drivers/clk/clk-gpio.c @@ -31,8 +31,6 @@ * parent - fixed parent. No clk_set_parent support */ -#define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw) - static int clk_gpio_gate_enable(struct clk_hw *hw) { struct clk_gpio *clk = to_clk_gpio(hw); diff --git a/drivers/clk/clk-multiplier.c b/drivers/clk/clk-multiplier.c index fe7806506bf3..9e449c7b751c 100644 --- a/drivers/clk/clk-multiplier.c +++ b/drivers/clk/clk-multiplier.c @@ -14,8 +14,6 @@ #include #include -#define to_clk_multiplier(_hw) container_of(_hw, struct clk_multiplier, hw) - static unsigned long __get_mult(struct clk_multiplier *mult, unsigned long rate, unsigned long parent_rate) diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 5ed03c8a8df9..252188fd8bcd 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -26,8 +26,6 @@ * parent - parent is adjustable through clk_set_parent */ -#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw) - static u8 clk_mux_get_parent(struct clk_hw *hw) { struct clk_mux *mux = to_clk_mux(hw); diff --git a/drivers/clk/imx/clk-busy.c b/drivers/clk/imx/clk-busy.c index 4bb1bc419b79..5cc99590f9a3 100644 --- a/drivers/clk/imx/clk-busy.c +++ b/drivers/clk/imx/clk-busy.c @@ -38,7 +38,7 @@ struct clk_busy_divider { static inline struct clk_busy_divider *to_clk_busy_divider(struct clk_hw *hw) { - struct clk_divider *div = container_of(hw, struct clk_divider, hw); + struct clk_divider *div = to_clk_divider(hw); return container_of(div, struct clk_busy_divider, div); } @@ -123,7 +123,7 @@ struct clk_busy_mux { static inline struct clk_busy_mux *to_clk_busy_mux(struct clk_hw *hw) { - struct clk_mux *mux = container_of(hw, struct clk_mux, hw); + struct clk_mux *mux = to_clk_mux(hw); return container_of(mux, struct clk_busy_mux, mux); } diff --git a/drivers/clk/imx/clk-fixup-div.c b/drivers/clk/imx/clk-fixup-div.c index 21db020b1f2d..ce5722732715 100644 --- a/drivers/clk/imx/clk-fixup-div.c +++ b/drivers/clk/imx/clk-fixup-div.c @@ -15,7 +15,6 @@ #include #include "clk.h" -#define to_clk_div(_hw) container_of(_hw, struct clk_divider, hw) #define div_mask(d) ((1 << (d->width)) - 1) /** @@ -35,7 +34,7 @@ struct clk_fixup_div { static inline struct clk_fixup_div *to_clk_fixup_div(struct clk_hw *hw) { - struct clk_divider *divider = to_clk_div(hw); + struct clk_divider *divider = to_clk_divider(hw); return container_of(divider, struct clk_fixup_div, divider); } @@ -60,7 +59,7 @@ static int clk_fixup_div_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_fixup_div *fixup_div = to_clk_fixup_div(hw); - struct clk_divider *div = to_clk_div(hw); + struct clk_divider *div = to_clk_divider(hw); unsigned int divider, value; unsigned long flags = 0; u32 val; diff --git a/drivers/clk/imx/clk-fixup-mux.c b/drivers/clk/imx/clk-fixup-mux.c index 0d40b35c557c..c9b327e0a8dd 100644 --- a/drivers/clk/imx/clk-fixup-mux.c +++ b/drivers/clk/imx/clk-fixup-mux.c @@ -15,8 +15,6 @@ #include #include "clk.h" -#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw) - /** * struct clk_fixup_mux - imx integer fixup multiplexer clock * @mux: the parent class diff --git a/drivers/clk/imx/clk-gate-exclusive.c b/drivers/clk/imx/clk-gate-exclusive.c index c12f5f2e04dc..3bd9dee618b2 100644 --- a/drivers/clk/imx/clk-gate-exclusive.c +++ b/drivers/clk/imx/clk-gate-exclusive.c @@ -31,7 +31,7 @@ struct clk_gate_exclusive { static int clk_gate_exclusive_enable(struct clk_hw *hw) { - struct clk_gate *gate = container_of(hw, struct clk_gate, hw); + struct clk_gate *gate = to_clk_gate(hw); struct clk_gate_exclusive *exgate = container_of(gate, struct clk_gate_exclusive, gate); u32 val = readl(gate->reg); diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c index 576bdb7c98b8..2a76901bf04b 100644 --- a/drivers/clk/mediatek/clk-gate.c +++ b/drivers/clk/mediatek/clk-gate.c @@ -25,7 +25,7 @@ static int mtk_cg_bit_is_cleared(struct clk_hw *hw) { - struct mtk_clk_gate *cg = to_clk_gate(hw); + struct mtk_clk_gate *cg = to_mtk_clk_gate(hw); u32 val; regmap_read(cg->regmap, cg->sta_ofs, &val); @@ -37,7 +37,7 @@ static int mtk_cg_bit_is_cleared(struct clk_hw *hw) static int mtk_cg_bit_is_set(struct clk_hw *hw) { - struct mtk_clk_gate *cg = to_clk_gate(hw); + struct mtk_clk_gate *cg = to_mtk_clk_gate(hw); u32 val; regmap_read(cg->regmap, cg->sta_ofs, &val); @@ -49,14 +49,14 @@ static int mtk_cg_bit_is_set(struct clk_hw *hw) static void mtk_cg_set_bit(struct clk_hw *hw) { - struct mtk_clk_gate *cg = to_clk_gate(hw); + struct mtk_clk_gate *cg = to_mtk_clk_gate(hw); regmap_write(cg->regmap, cg->set_ofs, BIT(cg->bit)); } static void mtk_cg_clr_bit(struct clk_hw *hw) { - struct mtk_clk_gate *cg = to_clk_gate(hw); + struct mtk_clk_gate *cg = to_mtk_clk_gate(hw); regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit)); } diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h index 11e25c992948..b1821603b887 100644 --- a/drivers/clk/mediatek/clk-gate.h +++ b/drivers/clk/mediatek/clk-gate.h @@ -29,7 +29,7 @@ struct mtk_clk_gate { u8 bit; }; -static inline struct mtk_clk_gate *to_clk_gate(struct clk_hw *hw) +static inline struct mtk_clk_gate *to_mtk_clk_gate(struct clk_hw *hw) { return container_of(hw, struct mtk_clk_gate, hw); } diff --git a/drivers/clk/mvebu/common.c b/drivers/clk/mvebu/common.c index 28aac67e7b92..daa6ebdac131 100644 --- a/drivers/clk/mvebu/common.c +++ b/drivers/clk/mvebu/common.c @@ -199,8 +199,6 @@ struct clk_gating_ctrl { u32 saved_reg; }; -#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw) - static struct clk_gating_ctrl *ctrl; static struct clk *clk_gating_get_src( diff --git a/drivers/clk/mvebu/kirkwood.c b/drivers/clk/mvebu/kirkwood.c index 99550f25975e..a2a8d614039d 100644 --- a/drivers/clk/mvebu/kirkwood.c +++ b/drivers/clk/mvebu/kirkwood.c @@ -256,8 +256,6 @@ static const struct clk_muxing_soc_desc kirkwood_mux_desc[] __initconst = { 11, 1, 0 }, }; -#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw) - static struct clk *clk_muxing_get_src( struct of_phandle_args *clkspec, void *data) { diff --git a/drivers/clk/mxs/clk-div.c b/drivers/clk/mxs/clk-div.c index 049ee27d5a22..f75e989c578f 100644 --- a/drivers/clk/mxs/clk-div.c +++ b/drivers/clk/mxs/clk-div.c @@ -33,7 +33,7 @@ struct clk_div { static inline struct clk_div *to_clk_div(struct clk_hw *hw) { - struct clk_divider *divider = container_of(hw, struct clk_divider, hw); + struct clk_divider *divider = to_clk_divider(hw); return container_of(divider, struct clk_div, divider); } diff --git a/drivers/clk/nxp/clk-lpc18xx-ccu.c b/drivers/clk/nxp/clk-lpc18xx-ccu.c index 558da89555af..f7136b94fd0e 100644 --- a/drivers/clk/nxp/clk-lpc18xx-ccu.c +++ b/drivers/clk/nxp/clk-lpc18xx-ccu.c @@ -28,8 +28,6 @@ #define CCU_BRANCH_IS_BUS BIT(0) #define CCU_BRANCH_HAVE_DIV2 BIT(1) -#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw) - struct lpc18xx_branch_clk_data { const char **name; int num; diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c index 5dc5ce217960..0d9a74b66ea3 100644 --- a/drivers/clk/st/clkgen-mux.c +++ b/drivers/clk/st/clkgen-mux.c @@ -822,11 +822,10 @@ err: if (!clk_data->clks[i]) continue; - composite = container_of(__clk_get_hw(clk_data->clks[i]), - struct clk_composite, hw); - kfree(container_of(composite->gate_hw, struct clk_gate, hw)); - kfree(container_of(composite->rate_hw, struct clk_divider, hw)); - kfree(container_of(composite->mux_hw, struct clk_mux, hw)); + composite = to_clk_composite(__clk_get_hw(clk_data->clks[i])); + kfree(to_clk_gate(composite->gate_hw)); + kfree(to_clk_divider(composite->rate_hw)); + kfree(to_clk_mux(composite->mux_hw)); } kfree(clk_data->clks); diff --git a/drivers/clk/ti/composite.c b/drivers/clk/ti/composite.c index dbef218fe5ec..43345c417815 100644 --- a/drivers/clk/ti/composite.c +++ b/drivers/clk/ti/composite.c @@ -28,8 +28,6 @@ #undef pr_fmt #define pr_fmt(fmt) "%s: " fmt, __func__ -#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) - static unsigned long ti_composite_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index df2558350fc1..b4e5de16e561 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c @@ -26,8 +26,6 @@ #undef pr_fmt #define pr_fmt(fmt) "%s: " fmt, __func__ -#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) - #define div_mask(d) ((1 << ((d)->width)) - 1) static unsigned int _get_table_maxdiv(const struct clk_div_table *table) diff --git a/drivers/clk/ti/gate.c b/drivers/clk/ti/gate.c index 5429d3534363..bc05f276f32b 100644 --- a/drivers/clk/ti/gate.c +++ b/drivers/clk/ti/gate.c @@ -24,8 +24,6 @@ #include "clock.h" -#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) - #undef pr_fmt #define pr_fmt(fmt) "%s: " fmt, __func__ diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c index dab9ba88b9d6..618ded96ace3 100644 --- a/drivers/clk/ti/mux.c +++ b/drivers/clk/ti/mux.c @@ -26,8 +26,6 @@ #undef pr_fmt #define pr_fmt(fmt) "%s: " fmt, __func__ -#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw) - static u8 ti_clk_mux_get_parent(struct clk_hw *hw) { struct clk_mux *mux = to_clk_mux(hw); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 408a60dca353..33dc814d0f43 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -276,6 +276,8 @@ struct clk_fixed_rate { u8 flags; }; +#define to_clk_fixed_rate(_hw) container_of(_hw, struct clk_fixed_rate, hw) + extern const struct clk_ops clk_fixed_rate_ops; struct clk *clk_register_fixed_rate(struct device *dev, const char *name, const char *parent_name, unsigned long flags, @@ -314,6 +316,8 @@ struct clk_gate { spinlock_t *lock; }; +#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw) + #define CLK_GATE_SET_TO_DISABLE BIT(0) #define CLK_GATE_HIWORD_MASK BIT(1) @@ -376,6 +380,8 @@ struct clk_divider { spinlock_t *lock; }; +#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) + #define CLK_DIVIDER_ONE_BASED BIT(0) #define CLK_DIVIDER_POWER_OF_TWO BIT(1) #define CLK_DIVIDER_ALLOW_ZERO BIT(2) @@ -441,6 +447,8 @@ struct clk_mux { spinlock_t *lock; }; +#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw) + #define CLK_MUX_INDEX_ONE BIT(0) #define CLK_MUX_INDEX_BIT BIT(1) #define CLK_MUX_HIWORD_MASK BIT(2) @@ -484,6 +492,8 @@ struct clk_fixed_factor { unsigned int div; }; +#define to_clk_fixed_factor(_hw) container_of(_hw, struct clk_fixed_factor, hw) + extern const struct clk_ops clk_fixed_factor_ops; struct clk *clk_register_fixed_factor(struct device *dev, const char *name, const char *parent_name, unsigned long flags, @@ -515,6 +525,8 @@ struct clk_fractional_divider { spinlock_t *lock; }; +#define to_clk_fd(_hw) container_of(_hw, struct clk_fractional_divider, hw) + extern const struct clk_ops clk_fractional_divider_ops; struct clk *clk_register_fractional_divider(struct device *dev, const char *name, const char *parent_name, unsigned long flags, @@ -551,6 +563,8 @@ struct clk_multiplier { spinlock_t *lock; }; +#define to_clk_multiplier(_hw) container_of(_hw, struct clk_multiplier, hw) + #define CLK_MULTIPLIER_ZERO_BYPASS BIT(0) #define CLK_MULTIPLIER_ROUND_CLOSEST BIT(1) @@ -580,6 +594,8 @@ struct clk_composite { const struct clk_ops *gate_ops; }; +#define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw) + struct clk *clk_register_composite(struct device *dev, const char *name, const char * const *parent_names, int num_parents, struct clk_hw *mux_hw, const struct clk_ops *mux_ops, @@ -602,6 +618,8 @@ struct clk_gpio { struct gpio_desc *gpiod; }; +#define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw) + extern const struct clk_ops clk_gpio_gate_ops; struct clk *clk_register_gpio_gate(struct device *dev, const char *name, const char *parent_name, unsigned gpio, bool active_low, -- cgit v1.2.3 From 4974259e18f1fd519d4329babbfefa24852375bb Mon Sep 17 00:00:00 2001 From: James Liao Date: Fri, 8 Jan 2016 16:15:33 +0800 Subject: clk: mediatek: Fix memory leak on clock init fail mtk_clk_register_composite() may leak memory due to some error handling path don't free all allocated memory. This patch free all pointers that may allocate memory before error return. And it's safe because kfree() can handle NULL pointers. Signed-off-by: James Liao Reviewed-by: Daniel Kurtz Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-mtk.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index cf08db6c130c..352830369e0e 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -209,12 +209,14 @@ struct clk * __init mtk_clk_register_composite(const struct mtk_composite *mc, mc->flags); if (IS_ERR(clk)) { - kfree(gate); - kfree(mux); + ret = PTR_ERR(clk); + goto err_out; } return clk; err_out: + kfree(div); + kfree(gate); kfree(mux); return ERR_PTR(ret); -- cgit v1.2.3 From dc5a9037141924c0867eb4a6e5220479dcda84f9 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 29 Jan 2016 14:44:59 -0800 Subject: drm/i915: Sink CRC: tune down error message at stop to debug_kms. When we stop the sink CRC calculation we wait a while until the counter is reset to zero and return -ETIMEDOUT. However the sink crc was calculated already by this point so we just ignore this return at the main function. So, let's also ignore the message and put it as a debug message instead of an error one. The message might still be useful when debuging test failures so we could be able to know something was not going so well with sink crc stop. v2: Improve log message. Reference: https://bugs.freedesktop.org/show_bug.cgi?id=93694 Cc: Daniel Vetter Cc: Paulo Zanoni Signed-off-by: Rodrigo Vivi Reviewed-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1454107499-29678-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index e2bea710614f..f44aba1019b8 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4008,7 +4008,7 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp) } while (--attempts && count); if (attempts == 0) { - DRM_ERROR("TIMEOUT: Sink CRC counter is not zeroed\n"); + DRM_DEBUG_KMS("TIMEOUT: Sink CRC counter is not zeroed after calculation is stopped\n"); ret = -ETIMEDOUT; } -- cgit v1.2.3 From b9e65ebc654dffeb77d8ef878bd6b2da30c55a94 Mon Sep 17 00:00:00 2001 From: James Liao Date: Thu, 28 Jan 2016 16:58:57 +0800 Subject: clk: Move vendor's Kconfig into CCF menu section Move all vendor's Kconfig into CCF menu section to prevent new drivers putting their Kconfig files in a wrong place. Some Kconfigs need to be modified at the same time to avoid build warnings. Signed-off-by: James Liao Acked-by: Sylwester Nawrocki [sboyd@codeaurora.org: Fix typos in commit message] Acked-by: Arnd Bergmann Signed-off-by: Stephen Boyd --- arch/arm/mach-s3c24xx/Kconfig | 1 + drivers/clk/Kconfig | 8 +++----- drivers/clk/samsung/Kconfig | 1 - 3 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index ef68ecb27396..f02495f5ca1f 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -15,6 +15,7 @@ config PLAT_S3C24XX select NO_IOPORT_MAP select S3C_DEV_NAND select IRQ_DOMAIN + select COMMON_CLK help Base platform code for any Samsung S3C24XX device diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index eca8e019e005..de707b2bfb73 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -202,11 +202,9 @@ config COMMON_CLK_CDCE706 source "drivers/clk/bcm/Kconfig" source "drivers/clk/hisilicon/Kconfig" -source "drivers/clk/qcom/Kconfig" - -endmenu - source "drivers/clk/mvebu/Kconfig" - +source "drivers/clk/qcom/Kconfig" source "drivers/clk/samsung/Kconfig" source "drivers/clk/tegra/Kconfig" + +endmenu diff --git a/drivers/clk/samsung/Kconfig b/drivers/clk/samsung/Kconfig index 84196ecdaa12..b3fe5cb01afe 100644 --- a/drivers/clk/samsung/Kconfig +++ b/drivers/clk/samsung/Kconfig @@ -1,6 +1,5 @@ config COMMON_CLK_SAMSUNG bool - select COMMON_CLK config S3C2410_COMMON_CLK bool -- cgit v1.2.3 From bcd8be139803f51834347840349c150bf0e4eb96 Mon Sep 17 00:00:00 2001 From: Simran Rai Date: Tue, 26 Jan 2016 17:18:39 -0800 Subject: clk: iproc: Add support for Cygnus audio clocks This patch adds support for Broadcom Cygnus audio PLL and leaf clocks Signed-off-by: Simran Rai Reviewed-by: Scott Branden Signed-off-by: Ray Jui Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-cygnus.c | 59 ++++++++++++++++++++++++++++++++++ drivers/clk/bcm/clk-iproc-pll.c | 41 ++++++++++++++++++++--- drivers/clk/bcm/clk-iproc.h | 21 ++++++++++++ include/dt-bindings/clock/bcm-cygnus.h | 6 ++++ 4 files changed, 122 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/bcm/clk-cygnus.c b/drivers/clk/bcm/clk-cygnus.c index 3a228b6d4fee..464fdc4bc66b 100644 --- a/drivers/clk/bcm/clk-cygnus.c +++ b/drivers/clk/bcm/clk-cygnus.c @@ -268,3 +268,62 @@ static void __init cygnus_asiu_init(struct device_node *node) iproc_asiu_setup(node, asiu_div, asiu_gate, ARRAY_SIZE(asiu_div)); } CLK_OF_DECLARE(cygnus_asiu_clk, "brcm,cygnus-asiu-clk", cygnus_asiu_init); + +/* + * AUDIO PLL VCO frequency parameter table + * + * PLL output frequency = ((ndiv_int + ndiv_frac / 2^20) * + * (parent clock rate / pdiv) + * + * On Cygnus, parent is the 25MHz oscillator + */ +static const struct iproc_pll_vco_param audiopll_vco_params[] = { + /* rate (Hz) ndiv_int ndiv_frac pdiv */ + { 1354750204UL, 54, 199238, 1 }, + { 1769470191UL, 70, 816639, 1 }, +}; + +static const struct iproc_pll_ctrl audiopll = { + .flags = IPROC_CLK_PLL_NEEDS_SW_CFG | IPROC_CLK_PLL_HAS_NDIV_FRAC | + IPROC_CLK_PLL_USER_MODE_ON | IPROC_CLK_PLL_RESET_ACTIVE_LOW, + .reset = RESET_VAL(0x5c, 0, 1), + .dig_filter = DF_VAL(0x48, 0, 3, 6, 4, 3, 3), + .sw_ctrl = SW_CTRL_VAL(0x4, 0), + .ndiv_int = REG_VAL(0x8, 0, 10), + .ndiv_frac = REG_VAL(0x8, 10, 20), + .pdiv = REG_VAL(0x44, 0, 4), + .vco_ctrl = VCO_CTRL_VAL(0x0c, 0x10), + .status = REG_VAL(0x54, 0, 1), + .macro_mode = REG_VAL(0x0, 0, 3), +}; + +static const struct iproc_clk_ctrl audiopll_clk[] = { + [BCM_CYGNUS_AUDIOPLL_CH0] = { + .channel = BCM_CYGNUS_AUDIOPLL_CH0, + .flags = IPROC_CLK_AON | + IPROC_CLK_MCLK_DIV_BY_2, + .enable = ENABLE_VAL(0x14, 8, 10, 9), + .mdiv = REG_VAL(0x14, 0, 8), + }, + [BCM_CYGNUS_AUDIOPLL_CH1] = { + .channel = BCM_CYGNUS_AUDIOPLL_CH1, + .flags = IPROC_CLK_AON, + .enable = ENABLE_VAL(0x18, 8, 10, 9), + .mdiv = REG_VAL(0x18, 0, 8), + }, + [BCM_CYGNUS_AUDIOPLL_CH2] = { + .channel = BCM_CYGNUS_AUDIOPLL_CH2, + .flags = IPROC_CLK_AON, + .enable = ENABLE_VAL(0x1c, 8, 10, 9), + .mdiv = REG_VAL(0x1c, 0, 8), + }, +}; + +static void __init cygnus_audiopll_clk_init(struct device_node *node) +{ + iproc_pll_clk_setup(node, &audiopll, audiopll_vco_params, + ARRAY_SIZE(audiopll_vco_params), audiopll_clk, + ARRAY_SIZE(audiopll_clk)); +} +CLK_OF_DECLARE(cygnus_audiopll, "brcm,cygnus-audiopll", + cygnus_audiopll_clk_init); diff --git a/drivers/clk/bcm/clk-iproc-pll.c b/drivers/clk/bcm/clk-iproc-pll.c index afd5891ac9e6..fd492a5dad12 100644 --- a/drivers/clk/bcm/clk-iproc-pll.c +++ b/drivers/clk/bcm/clk-iproc-pll.c @@ -25,6 +25,12 @@ #define PLL_VCO_HIGH_SHIFT 19 #define PLL_VCO_LOW_SHIFT 30 +/* + * PLL MACRO_SELECT modes 0 to 5 choose pre-calculated PLL output frequencies + * from a look-up table. Mode 7 allows user to manipulate PLL clock dividers + */ +#define PLL_USER_MODE 7 + /* number of delay loops waiting for PLL to lock */ #define LOCK_DELAY 100 @@ -215,7 +221,10 @@ static void __pll_put_in_reset(struct iproc_pll *pll) const struct iproc_pll_reset_ctrl *reset = &ctrl->reset; val = readl(pll->control_base + reset->offset); - val &= ~(1 << reset->reset_shift | 1 << reset->p_reset_shift); + if (ctrl->flags & IPROC_CLK_PLL_RESET_ACTIVE_LOW) + val |= BIT(reset->reset_shift) | BIT(reset->p_reset_shift); + else + val &= ~(BIT(reset->reset_shift) | BIT(reset->p_reset_shift)); iproc_pll_write(pll, pll->control_base, reset->offset, val); } @@ -236,7 +245,10 @@ static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp, iproc_pll_write(pll, pll->control_base, dig_filter->offset, val); val = readl(pll->control_base + reset->offset); - val |= 1 << reset->reset_shift | 1 << reset->p_reset_shift; + if (ctrl->flags & IPROC_CLK_PLL_RESET_ACTIVE_LOW) + val &= ~(BIT(reset->reset_shift) | BIT(reset->p_reset_shift)); + else + val |= BIT(reset->reset_shift) | BIT(reset->p_reset_shift); iproc_pll_write(pll, pll->control_base, reset->offset, val); } @@ -292,6 +304,16 @@ static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index, /* put PLL in reset */ __pll_put_in_reset(pll); + /* set PLL in user mode before modifying PLL controls */ + if (ctrl->flags & IPROC_CLK_PLL_USER_MODE_ON) { + val = readl(pll->control_base + ctrl->macro_mode.offset); + val &= ~(bit_mask(ctrl->macro_mode.width) << + ctrl->macro_mode.shift); + val |= PLL_USER_MODE << ctrl->macro_mode.shift; + iproc_pll_write(pll, pll->control_base, + ctrl->macro_mode.offset, val); + } + iproc_pll_write(pll, pll->control_base, ctrl->vco_ctrl.u_offset, 0); val = readl(pll->control_base + ctrl->vco_ctrl.l_offset); @@ -505,7 +527,10 @@ static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw, if (mdiv == 0) mdiv = 256; - clk->rate = parent_rate / mdiv; + if (ctrl->flags & IPROC_CLK_MCLK_DIV_BY_2) + clk->rate = parent_rate / (mdiv * 2); + else + clk->rate = parent_rate / mdiv; return clk->rate; } @@ -543,7 +568,10 @@ static int iproc_clk_set_rate(struct clk_hw *hw, unsigned long rate, if (rate == 0 || parent_rate == 0) return -EINVAL; - div = DIV_ROUND_UP(parent_rate, rate); + if (ctrl->flags & IPROC_CLK_MCLK_DIV_BY_2) + div = DIV_ROUND_UP(parent_rate, rate * 2); + else + div = DIV_ROUND_UP(parent_rate, rate); if (div > 256) return -EINVAL; @@ -555,7 +583,10 @@ static int iproc_clk_set_rate(struct clk_hw *hw, unsigned long rate, val |= div << ctrl->mdiv.shift; } iproc_pll_write(pll, pll->control_base, ctrl->mdiv.offset, val); - clk->rate = parent_rate / div; + if (ctrl->flags & IPROC_CLK_MCLK_DIV_BY_2) + clk->rate = parent_rate / (div * 2); + else + clk->rate = parent_rate / div; return 0; } diff --git a/drivers/clk/bcm/clk-iproc.h b/drivers/clk/bcm/clk-iproc.h index 8988de70a98c..febae119f9ef 100644 --- a/drivers/clk/bcm/clk-iproc.h +++ b/drivers/clk/bcm/clk-iproc.h @@ -60,6 +60,26 @@ */ #define IPROC_CLK_PLL_SPLIT_STAT_CTRL BIT(6) +/* + * Some PLLs have an additional divide by 2 in master clock calculation; + * MCLK = VCO_freq / (Mdiv * 2). Identify this to let the driver know + * of modified calculations + */ +#define IPROC_CLK_MCLK_DIV_BY_2 BIT(7) + +/* + * Some PLLs provide a look up table for the leaf clock frequencies and + * auto calculates VCO frequency parameters based on the provided leaf + * clock frequencies. They have a user mode that allows the divider + * controls to be determined by the user + */ +#define IPROC_CLK_PLL_USER_MODE_ON BIT(8) + +/* + * Some PLLs have an active low reset + */ +#define IPROC_CLK_PLL_RESET_ACTIVE_LOW BIT(9) + /* * Parameters for VCO frequency configuration * @@ -149,6 +169,7 @@ struct iproc_pll_ctrl { struct iproc_clk_reg_op pdiv; struct iproc_pll_vco_ctrl vco_ctrl; struct iproc_clk_reg_op status; + struct iproc_clk_reg_op macro_mode; }; /* diff --git a/include/dt-bindings/clock/bcm-cygnus.h b/include/dt-bindings/clock/bcm-cygnus.h index 32fbc475087a..62ac5d782a00 100644 --- a/include/dt-bindings/clock/bcm-cygnus.h +++ b/include/dt-bindings/clock/bcm-cygnus.h @@ -65,4 +65,10 @@ #define BCM_CYGNUS_ASIU_ADC_CLK 1 #define BCM_CYGNUS_ASIU_PWM_CLK 2 +/* AUDIO clock ID */ +#define BCM_CYGNUS_AUDIOPLL 0 +#define BCM_CYGNUS_AUDIOPLL_CH0 1 +#define BCM_CYGNUS_AUDIOPLL_CH1 2 +#define BCM_CYGNUS_AUDIOPLL_CH2 3 + #endif /* _CLOCK_BCM_CYGNUS_H */ -- cgit v1.2.3 From df416e565d6e1d18cfa3b5e016a667bf51ce6aac Mon Sep 17 00:00:00 2001 From: Ray Jui Date: Tue, 26 Jan 2016 17:18:40 -0800 Subject: clk: iproc: Remove __init from header Remove __init macro from all function prototypes in clk-iproc.h Signed-off-by: Ray Jui Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-iproc.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/bcm/clk-iproc.h b/drivers/clk/bcm/clk-iproc.h index febae119f9ef..2148b4ea9f28 100644 --- a/drivers/clk/bcm/clk-iproc.h +++ b/drivers/clk/bcm/clk-iproc.h @@ -204,16 +204,16 @@ struct iproc_asiu_div { unsigned int low_width; }; -void __init iproc_armpll_setup(struct device_node *node); -void __init iproc_pll_clk_setup(struct device_node *node, - const struct iproc_pll_ctrl *pll_ctrl, - const struct iproc_pll_vco_param *vco, - unsigned int num_vco_entries, - const struct iproc_clk_ctrl *clk_ctrl, - unsigned int num_clks); -void __init iproc_asiu_setup(struct device_node *node, - const struct iproc_asiu_div *div, - const struct iproc_asiu_gate *gate, - unsigned int num_clks); +void iproc_armpll_setup(struct device_node *node); +void iproc_pll_clk_setup(struct device_node *node, + const struct iproc_pll_ctrl *pll_ctrl, + const struct iproc_pll_vco_param *vco, + unsigned int num_vco_entries, + const struct iproc_clk_ctrl *clk_ctrl, + unsigned int num_clks); +void iproc_asiu_setup(struct device_node *node, + const struct iproc_asiu_div *div, + const struct iproc_asiu_gate *gate, + unsigned int num_clks); #endif /* _CLK_IPROC_H */ -- cgit v1.2.3 From 5540ac8da18789e567f6d16582f76de7ab196eab Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 4 Jan 2016 11:01:53 +0000 Subject: clk:gcc-msm8916: add missing mss_q6_bimc_axi clock This clock is required for loading the qdsp firmware. Signed-off-by: Srinivas Kandagatla Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-msm8916.c | 18 ++++++++++++++++++ include/dt-bindings/clock/qcom,gcc-msm8916.h | 1 + 2 files changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c index e3bf09d7d0ef..899349b5aa07 100644 --- a/drivers/clk/qcom/gcc-msm8916.c +++ b/drivers/clk/qcom/gcc-msm8916.c @@ -2590,6 +2590,23 @@ static struct clk_branch gcc_mss_cfg_ahb_clk = { }, }; +static struct clk_branch gcc_mss_q6_bimc_axi_clk = { + .halt_reg = 0x49004, + .clkr = { + .enable_reg = 0x49004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_q6_bimc_axi_clk", + .parent_names = (const char *[]){ + "bimc_ddr_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_oxili_ahb_clk = { .halt_reg = 0x59028, .clkr = { @@ -3227,6 +3244,7 @@ static struct clk_regmap *gcc_msm8916_clocks[] = { [GCC_ULTAUDIO_LPAIF_SEC_I2S_CLK] = &gcc_ultaudio_lpaif_sec_i2s_clk.clkr, [GCC_ULTAUDIO_LPAIF_AUX_I2S_CLK] = &gcc_ultaudio_lpaif_aux_i2s_clk.clkr, [GCC_CODEC_DIGCODEC_CLK] = &gcc_codec_digcodec_clk.clkr, + [GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr, }; static struct gdsc *gcc_msm8916_gdscs[] = { diff --git a/include/dt-bindings/clock/qcom,gcc-msm8916.h b/include/dt-bindings/clock/qcom,gcc-msm8916.h index 257e2fbedd94..28a27a4ed3c3 100644 --- a/include/dt-bindings/clock/qcom,gcc-msm8916.h +++ b/include/dt-bindings/clock/qcom,gcc-msm8916.h @@ -174,6 +174,7 @@ #define GCC_ULTAUDIO_LPAIF_SEC_I2S_CLK 157 #define GCC_ULTAUDIO_LPAIF_AUX_I2S_CLK 158 #define GCC_CODEC_DIGCODEC_CLK 159 +#define GCC_MSS_Q6_BIMC_AXI_CLK 160 /* Indexes for GDSCs */ #define BIMC_GDSC 0 -- cgit v1.2.3 From cbf9591f665d44f40795afe2eee4fcbcd32575d6 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 6 Jan 2016 13:25:09 +0900 Subject: clk: add clk_unregister_fixed_factor() Allow to unregister fixed factor clock. Signed-off-by: Masahiro Yamada Signed-off-by: Stephen Boyd --- drivers/clk/clk-fixed-factor.c | 13 +++++++++++++ include/linux/clk-provider.h | 1 + 2 files changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index f0ddf37d5e15..053448e2453d 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -100,6 +100,19 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name, } EXPORT_SYMBOL_GPL(clk_register_fixed_factor); +void clk_unregister_fixed_factor(struct clk *clk) +{ + struct clk_hw *hw; + + hw = __clk_get_hw(clk); + if (!hw) + return; + + clk_unregister(clk); + kfree(to_clk_fixed_factor(hw)); +} +EXPORT_SYMBOL_GPL(clk_unregister_fixed_factor); + #ifdef CONFIG_OF /** * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 33dc814d0f43..3641eecf462a 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -498,6 +498,7 @@ extern const struct clk_ops clk_fixed_factor_ops; struct clk *clk_register_fixed_factor(struct device *dev, const char *name, const char *parent_name, unsigned long flags, unsigned int mult, unsigned int div); +void clk_unregister_fixed_factor(struct clk *clk); /** * struct clk_fractional_divider - adjustable fractional divider clock -- cgit v1.2.3 From 0b225e41e369a7e03411bb67988513302a10382f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 6 Jan 2016 13:25:10 +0900 Subject: clk: add clk_unregister_fixed_rate() Allow to unregister fixed rate clock. Signed-off-by: Masahiro Yamada Signed-off-by: Stephen Boyd --- drivers/clk/clk-fixed-rate.c | 13 +++++++++++++ include/linux/clk-provider.h | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index e156beb871f0..6858bfc548a9 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c @@ -104,6 +104,19 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name, } EXPORT_SYMBOL_GPL(clk_register_fixed_rate); +void clk_unregister_fixed_rate(struct clk *clk) +{ + struct clk_hw *hw; + + hw = __clk_get_hw(clk); + if (!hw) + return; + + clk_unregister(clk); + kfree(to_clk_fixed_rate(hw)); +} +EXPORT_SYMBOL_GPL(clk_unregister_fixed_rate); + #ifdef CONFIG_OF /** * of_fixed_clk_setup() - Setup function for simple fixed rate clock diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 3641eecf462a..fabe5bedbba6 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -285,7 +285,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name, struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev, const char *name, const char *parent_name, unsigned long flags, unsigned long fixed_rate, unsigned long fixed_accuracy); - +void clk_unregister_fixed_rate(struct clk *clk); void of_fixed_clk_setup(struct device_node *np); /** -- cgit v1.2.3 From 090341b0a95d1f6d762915a75c13b393366f4ab3 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Fri, 2 Oct 2015 06:49:53 +0200 Subject: clk: vt8500: fix sign of possible PLL values With unsigned values underflow in loops can occur resulting in theoretically infinite loops. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2038576 Signed-off-by: Andrzej Hajda Signed-off-by: Stephen Boyd --- drivers/clk/clk-vt8500.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c index 37e928846ec5..98c4492d2c0d 100644 --- a/drivers/clk/clk-vt8500.c +++ b/drivers/clk/clk-vt8500.c @@ -384,7 +384,8 @@ static void vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate, static void wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate, u32 *multiplier, u32 *divisor1, u32 *divisor2) { - u32 mul, div1, div2; + u32 mul, div1; + int div2; u32 best_mul, best_div1, best_div2; unsigned long tclk, rate_err, best_err; @@ -452,7 +453,8 @@ static u32 wm8750_get_filter(u32 parent_rate, u32 divisor1) static void wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate, u32 *filter, u32 *multiplier, u32 *divisor1, u32 *divisor2) { - u32 mul, div1, div2; + u32 mul; + int div1, div2; u32 best_mul, best_div1, best_div2; unsigned long tclk, rate_err, best_err; @@ -496,7 +498,8 @@ static void wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate, static void wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate, u32 *multiplier, u32 *divisor1, u32 *divisor2) { - u32 mul, div1, div2; + u32 mul; + int div1, div2; u32 best_mul, best_div1, best_div2; unsigned long tclk, rate_err, best_err; -- cgit v1.2.3 From 653d1452b452207999b67ab943c27cd80b7bd430 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 5 Jan 2016 12:43:41 +0900 Subject: clk: optimize the divider walk in clk_divider_bestdiv() Because _next_div() returns a valid divider, there is no need to consult _is_valid_div() for the validity of the divider in every iteration. Signed-off-by: Masahiro Yamada Signed-off-by: Stephen Boyd --- drivers/clk/clk-divider.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 7d62dc30e969..00e035b51c69 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -303,9 +303,8 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, */ maxdiv = min(ULONG_MAX / rate, maxdiv); - for (i = 1; i <= maxdiv; i = _next_div(table, i, flags)) { - if (!_is_valid_div(table, i, flags)) - continue; + for (i = _next_div(table, 0, flags); i <= maxdiv; + i = _next_div(table, i, flags)) { if (rate * i == parent_rate_saved) { /* * It's the most ideal case if the requested rate can be -- cgit v1.2.3 From 93fffbbee11af1ff9658c2822cfd355b4f16243d Mon Sep 17 00:00:00 2001 From: LABBE Corentin Date: Wed, 25 Nov 2015 13:52:01 +0100 Subject: clk: palmas: constify the palmas_clks_of_match_data structure The palmas_clks_of_match_data structures are never modified. This patch constify them. Signed-off-by: LABBE Corentin Signed-off-by: Stephen Boyd --- drivers/clk/clk-palmas.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-palmas.c b/drivers/clk/clk-palmas.c index 8e3039f0c3f9..c55e7745c9f8 100644 --- a/drivers/clk/clk-palmas.c +++ b/drivers/clk/clk-palmas.c @@ -44,7 +44,7 @@ struct palmas_clock_info { struct clk *clk; struct clk_hw hw; struct palmas *palmas; - struct palmas_clk32k_desc *clk_desc; + const struct palmas_clk32k_desc *clk_desc; int ext_control_pin; }; @@ -125,10 +125,10 @@ static struct clk_ops palmas_clks_ops = { struct palmas_clks_of_match_data { struct clk_init_data init; - struct palmas_clk32k_desc desc; + const struct palmas_clk32k_desc desc; }; -static struct palmas_clks_of_match_data palmas_of_clk32kg = { +static const struct palmas_clks_of_match_data palmas_of_clk32kg = { .init = { .name = "clk32kg", .ops = &palmas_clks_ops, @@ -144,7 +144,7 @@ static struct palmas_clks_of_match_data palmas_of_clk32kg = { }, }; -static struct palmas_clks_of_match_data palmas_of_clk32kgaudio = { +static const struct palmas_clks_of_match_data palmas_of_clk32kgaudio = { .init = { .name = "clk32kgaudio", .ops = &palmas_clks_ops, @@ -240,14 +240,14 @@ static int palmas_clks_probe(struct platform_device *pdev) { struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); struct device_node *node = pdev->dev.of_node; - struct palmas_clks_of_match_data *match_data; + const struct palmas_clks_of_match_data *match_data; const struct of_device_id *match; struct palmas_clock_info *cinfo; struct clk *clk; int ret; match = of_match_device(palmas_clks_of_match, &pdev->dev); - match_data = (struct palmas_clks_of_match_data *)match->data; + match_data = match->data; cinfo = devm_kzalloc(&pdev->dev, sizeof(*cinfo), GFP_KERNEL); if (!cinfo) -- cgit v1.2.3 From 8d0a69d735318cbd99c1376d16ed7ff82a7a678e Mon Sep 17 00:00:00 2001 From: LABBE Corentin Date: Wed, 25 Nov 2015 13:52:02 +0100 Subject: clk: palmas: fix a possible NULL dereference of_match_device could return NULL, and so cause a NULL pointer dereference later. Even if the probability of this case is very low, fixing it made static analyzers happy. Solving this with of_device_get_match_data made also code simplier. Reported-by: coverity (CID 1324137) Signed-off-by: LABBE Corentin Signed-off-by: Stephen Boyd --- drivers/clk/clk-palmas.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-palmas.c b/drivers/clk/clk-palmas.c index c55e7745c9f8..9c0b8e6b1ab3 100644 --- a/drivers/clk/clk-palmas.c +++ b/drivers/clk/clk-palmas.c @@ -241,13 +241,13 @@ static int palmas_clks_probe(struct platform_device *pdev) struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); struct device_node *node = pdev->dev.of_node; const struct palmas_clks_of_match_data *match_data; - const struct of_device_id *match; struct palmas_clock_info *cinfo; struct clk *clk; int ret; - match = of_match_device(palmas_clks_of_match, &pdev->dev); - match_data = match->data; + match_data = of_device_get_match_data(&pdev->dev); + if (!match_data) + return 1; cinfo = devm_kzalloc(&pdev->dev, sizeof(*cinfo), GFP_KERNEL); if (!cinfo) -- cgit v1.2.3 From d95b599c0395c0aa831c6199f2e7b404d33841a2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 30 Nov 2015 17:54:55 +0100 Subject: clk: axi-clkgen: Remove version 1 support Version 1 of the axi-clkgen core has not been used in new designs for over two years now. This is a soft peripheral used in FPGAs and anybody who has updated their kernel to the latest version will also have updated the bitstream containing the clock generator. So it should be safe to drop support for this now. Signed-off-by: Lars-Peter Clausen Signed-off-by: Stephen Boyd --- drivers/clk/clk-axi-clkgen.c | 125 ++----------------------------------------- 1 file changed, 4 insertions(+), 121 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c index 3bcd42fbb55e..8dedc600e711 100644 --- a/drivers/clk/clk-axi-clkgen.c +++ b/drivers/clk/clk-axi-clkgen.c @@ -16,18 +16,6 @@ #include #include -#define AXI_CLKGEN_V1_REG_UPDATE_ENABLE 0x04 -#define AXI_CLKGEN_V1_REG_CLK_OUT1 0x08 -#define AXI_CLKGEN_V1_REG_CLK_OUT2 0x0c -#define AXI_CLKGEN_V1_REG_CLK_DIV 0x10 -#define AXI_CLKGEN_V1_REG_CLK_FB1 0x14 -#define AXI_CLKGEN_V1_REG_CLK_FB2 0x18 -#define AXI_CLKGEN_V1_REG_LOCK1 0x1c -#define AXI_CLKGEN_V1_REG_LOCK2 0x20 -#define AXI_CLKGEN_V1_REG_LOCK3 0x24 -#define AXI_CLKGEN_V1_REG_FILTER1 0x28 -#define AXI_CLKGEN_V1_REG_FILTER2 0x2c - #define AXI_CLKGEN_V2_REG_RESET 0x40 #define AXI_CLKGEN_V2_REG_DRP_CNTRL 0x70 #define AXI_CLKGEN_V2_REG_DRP_STATUS 0x74 @@ -51,40 +39,11 @@ #define MMCM_REG_FILTER1 0x4e #define MMCM_REG_FILTER2 0x4f -struct axi_clkgen; - -struct axi_clkgen_mmcm_ops { - void (*enable)(struct axi_clkgen *axi_clkgen, bool enable); - int (*write)(struct axi_clkgen *axi_clkgen, unsigned int reg, - unsigned int val, unsigned int mask); - int (*read)(struct axi_clkgen *axi_clkgen, unsigned int reg, - unsigned int *val); -}; - struct axi_clkgen { void __iomem *base; - const struct axi_clkgen_mmcm_ops *mmcm_ops; struct clk_hw clk_hw; }; -static void axi_clkgen_mmcm_enable(struct axi_clkgen *axi_clkgen, - bool enable) -{ - axi_clkgen->mmcm_ops->enable(axi_clkgen, enable); -} - -static int axi_clkgen_mmcm_write(struct axi_clkgen *axi_clkgen, - unsigned int reg, unsigned int val, unsigned int mask) -{ - return axi_clkgen->mmcm_ops->write(axi_clkgen, reg, val, mask); -} - -static int axi_clkgen_mmcm_read(struct axi_clkgen *axi_clkgen, - unsigned int reg, unsigned int *val) -{ - return axi_clkgen->mmcm_ops->read(axi_clkgen, reg, val); -} - static uint32_t axi_clkgen_lookup_filter(unsigned int m) { switch (m) { @@ -207,70 +166,6 @@ static void axi_clkgen_read(struct axi_clkgen *axi_clkgen, *val = readl(axi_clkgen->base + reg); } -static unsigned int axi_clkgen_v1_map_mmcm_reg(unsigned int reg) -{ - switch (reg) { - case MMCM_REG_CLKOUT0_1: - return AXI_CLKGEN_V1_REG_CLK_OUT1; - case MMCM_REG_CLKOUT0_2: - return AXI_CLKGEN_V1_REG_CLK_OUT2; - case MMCM_REG_CLK_FB1: - return AXI_CLKGEN_V1_REG_CLK_FB1; - case MMCM_REG_CLK_FB2: - return AXI_CLKGEN_V1_REG_CLK_FB2; - case MMCM_REG_CLK_DIV: - return AXI_CLKGEN_V1_REG_CLK_DIV; - case MMCM_REG_LOCK1: - return AXI_CLKGEN_V1_REG_LOCK1; - case MMCM_REG_LOCK2: - return AXI_CLKGEN_V1_REG_LOCK2; - case MMCM_REG_LOCK3: - return AXI_CLKGEN_V1_REG_LOCK3; - case MMCM_REG_FILTER1: - return AXI_CLKGEN_V1_REG_FILTER1; - case MMCM_REG_FILTER2: - return AXI_CLKGEN_V1_REG_FILTER2; - default: - return 0; - } -} - -static int axi_clkgen_v1_mmcm_write(struct axi_clkgen *axi_clkgen, - unsigned int reg, unsigned int val, unsigned int mask) -{ - reg = axi_clkgen_v1_map_mmcm_reg(reg); - if (reg == 0) - return -EINVAL; - - axi_clkgen_write(axi_clkgen, reg, val); - - return 0; -} - -static int axi_clkgen_v1_mmcm_read(struct axi_clkgen *axi_clkgen, - unsigned int reg, unsigned int *val) -{ - reg = axi_clkgen_v1_map_mmcm_reg(reg); - if (reg == 0) - return -EINVAL; - - axi_clkgen_read(axi_clkgen, reg, val); - - return 0; -} - -static void axi_clkgen_v1_mmcm_enable(struct axi_clkgen *axi_clkgen, - bool enable) -{ - axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V1_REG_UPDATE_ENABLE, enable); -} - -static const struct axi_clkgen_mmcm_ops axi_clkgen_v1_mmcm_ops = { - .write = axi_clkgen_v1_mmcm_write, - .read = axi_clkgen_v1_mmcm_read, - .enable = axi_clkgen_v1_mmcm_enable, -}; - static int axi_clkgen_wait_non_busy(struct axi_clkgen *axi_clkgen) { unsigned int timeout = 10000; @@ -286,7 +181,7 @@ static int axi_clkgen_wait_non_busy(struct axi_clkgen *axi_clkgen) return val & 0xffff; } -static int axi_clkgen_v2_mmcm_read(struct axi_clkgen *axi_clkgen, +static int axi_clkgen_mmcm_read(struct axi_clkgen *axi_clkgen, unsigned int reg, unsigned int *val) { unsigned int reg_val; @@ -310,7 +205,7 @@ static int axi_clkgen_v2_mmcm_read(struct axi_clkgen *axi_clkgen, return 0; } -static int axi_clkgen_v2_mmcm_write(struct axi_clkgen *axi_clkgen, +static int axi_clkgen_mmcm_write(struct axi_clkgen *axi_clkgen, unsigned int reg, unsigned int val, unsigned int mask) { unsigned int reg_val = 0; @@ -321,7 +216,7 @@ static int axi_clkgen_v2_mmcm_write(struct axi_clkgen *axi_clkgen, return ret; if (mask != 0xffff) { - axi_clkgen_v2_mmcm_read(axi_clkgen, reg, ®_val); + axi_clkgen_mmcm_read(axi_clkgen, reg, ®_val); reg_val &= ~mask; } @@ -332,7 +227,7 @@ static int axi_clkgen_v2_mmcm_write(struct axi_clkgen *axi_clkgen, return 0; } -static void axi_clkgen_v2_mmcm_enable(struct axi_clkgen *axi_clkgen, +static void axi_clkgen_mmcm_enable(struct axi_clkgen *axi_clkgen, bool enable) { unsigned int val = AXI_CLKGEN_V2_RESET_ENABLE; @@ -343,12 +238,6 @@ static void axi_clkgen_v2_mmcm_enable(struct axi_clkgen *axi_clkgen, axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_RESET, val); } -static const struct axi_clkgen_mmcm_ops axi_clkgen_v2_mmcm_ops = { - .write = axi_clkgen_v2_mmcm_write, - .read = axi_clkgen_v2_mmcm_read, - .enable = axi_clkgen_v2_mmcm_enable, -}; - static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw) { return container_of(clk_hw, struct axi_clkgen, clk_hw); @@ -470,11 +359,7 @@ static const struct clk_ops axi_clkgen_ops = { static const struct of_device_id axi_clkgen_ids[] = { { - .compatible = "adi,axi-clkgen-1.00.a", - .data = &axi_clkgen_v1_mmcm_ops - }, { .compatible = "adi,axi-clkgen-2.00.a", - .data = &axi_clkgen_v2_mmcm_ops, }, { }, }; @@ -501,8 +386,6 @@ static int axi_clkgen_probe(struct platform_device *pdev) if (!axi_clkgen) return -ENOMEM; - axi_clkgen->mmcm_ops = id->data; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(axi_clkgen->base)) -- cgit v1.2.3 From 62d1e7823d9c3b454dcbffd58f35c5fa96172644 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 30 Nov 2015 17:54:56 +0100 Subject: clk: axi-clkgen: Add multi-parent support The clock generator has two clock inputs that can be used as the reference clock. Add support for switching between them at runtime. Signed-off-by: Lars-Peter Clausen Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/axi-clkgen.txt | 5 ++- drivers/clk/clk-axi-clkgen.c | 40 ++++++++++++++++++---- 2 files changed, 38 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/clock/axi-clkgen.txt b/Documentation/devicetree/bindings/clock/axi-clkgen.txt index 20e1704e7df2..fb40da303d25 100644 --- a/Documentation/devicetree/bindings/clock/axi-clkgen.txt +++ b/Documentation/devicetree/bindings/clock/axi-clkgen.txt @@ -8,7 +8,10 @@ Required properties: - compatible : shall be "adi,axi-clkgen-1.00.a" or "adi,axi-clkgen-2.00.a". - #clock-cells : from common clock binding; Should always be set to 0. - reg : Address and length of the axi-clkgen register set. -- clocks : Phandle and clock specifier for the parent clock. +- clocks : Phandle and clock specifier for the parent clock(s). This must + either reference one clock if only the first clock input is connected or two + if both clock inputs are connected. For the later case the clock connected + to the first input must be specified first. Optional properties: - clock-output-names : From common clock binding. diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c index 8dedc600e711..9a0744c9947c 100644 --- a/drivers/clk/clk-axi-clkgen.c +++ b/drivers/clk/clk-axi-clkgen.c @@ -17,6 +17,7 @@ #include #define AXI_CLKGEN_V2_REG_RESET 0x40 +#define AXI_CLKGEN_V2_REG_CLKSEL 0x44 #define AXI_CLKGEN_V2_REG_DRP_CNTRL 0x70 #define AXI_CLKGEN_V2_REG_DRP_STATUS 0x74 @@ -349,12 +350,33 @@ static void axi_clkgen_disable(struct clk_hw *clk_hw) axi_clkgen_mmcm_enable(axi_clkgen, false); } +static int axi_clkgen_set_parent(struct clk_hw *clk_hw, u8 index) +{ + struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); + + axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_CLKSEL, index); + + return 0; +} + +static u8 axi_clkgen_get_parent(struct clk_hw *clk_hw) +{ + struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); + unsigned int parent; + + axi_clkgen_read(axi_clkgen, AXI_CLKGEN_V2_REG_CLKSEL, &parent); + + return parent; +} + static const struct clk_ops axi_clkgen_ops = { .recalc_rate = axi_clkgen_recalc_rate, .round_rate = axi_clkgen_round_rate, .set_rate = axi_clkgen_set_rate, .enable = axi_clkgen_enable, .disable = axi_clkgen_disable, + .set_parent = axi_clkgen_set_parent, + .get_parent = axi_clkgen_get_parent, }; static const struct of_device_id axi_clkgen_ids[] = { @@ -370,10 +392,11 @@ static int axi_clkgen_probe(struct platform_device *pdev) const struct of_device_id *id; struct axi_clkgen *axi_clkgen; struct clk_init_data init; - const char *parent_name; + const char *parent_names[2]; const char *clk_name; struct resource *mem; struct clk *clk; + unsigned int i; if (!pdev->dev.of_node) return -ENODEV; @@ -391,19 +414,24 @@ static int axi_clkgen_probe(struct platform_device *pdev) if (IS_ERR(axi_clkgen->base)) return PTR_ERR(axi_clkgen->base); - parent_name = of_clk_get_parent_name(pdev->dev.of_node, 0); - if (!parent_name) + init.num_parents = of_clk_get_parent_count(pdev->dev.of_node); + if (init.num_parents < 1 || init.num_parents > 2) return -EINVAL; + for (i = 0; i < init.num_parents; i++) { + parent_names[i] = of_clk_get_parent_name(pdev->dev.of_node, i); + if (!parent_names[i]) + return -EINVAL; + } + clk_name = pdev->dev.of_node->name; of_property_read_string(pdev->dev.of_node, "clock-output-names", &clk_name); init.name = clk_name; init.ops = &axi_clkgen_ops; - init.flags = CLK_SET_RATE_GATE; - init.parent_names = &parent_name; - init.num_parents = 1; + init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; + init.parent_names = parent_names; axi_clkgen_mmcm_enable(axi_clkgen, false); -- cgit v1.2.3 From 3d6f1c7212d0823cbc056b1c184c7fe0cfef553a Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 29 Jan 2016 17:09:01 -0800 Subject: clk: axi-clkgen: Remove sometimes impossible check The size of unsigned long on 64-bit architectures is equal to the size of u64, so this check is impossible there. This throws off static checkers: drivers/clk/clk-axi-clkgen.c:331 axi_clkgen_recalc_rate() warn: impossible condition '(tmp > (~0)) => (0-u64max > u64max)' Let's change this code to use min_t() instead so that we get the same effect on architectures where sizeof(unsigned long) doesn't equal sizeof(u64). Cc: Lars-Peter Clausen Signed-off-by: Stephen Boyd --- drivers/clk/clk-axi-clkgen.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c index 9a0744c9947c..3294db3b4e4e 100644 --- a/drivers/clk/clk-axi-clkgen.c +++ b/drivers/clk/clk-axi-clkgen.c @@ -328,10 +328,7 @@ static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw, tmp = (unsigned long long)(parent_rate / d) * m; do_div(tmp, dout); - if (tmp > ULONG_MAX) - return ULONG_MAX; - - return tmp; + return min_t(unsigned long long, tmp, ULONG_MAX); } static int axi_clkgen_enable(struct clk_hw *clk_hw) -- cgit v1.2.3 From 9849fadfc07eeb2a3699f1ccb7b61f59d2c3c6b8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 16:54:04 +0100 Subject: clk: st: avoid uninitialized variable use My previous patch fixed some warnings about printing a couple of variables that are always uninitialized in quadfs_pll_fs660c32_set_rate(), but I now got a warning that only shows up in some configurations (i.e. without gcc -Os) about the params.ndiv being used uninitialized in the error case: drivers/clk/st/clkgen-fsyn.c: In function 'quadfs_pll_fs660c32_set_rate': drivers/clk/st/clkgen-fsyn.c:584:75: warning: 'params.ndiv' may be used uninitialized in this function [-Wmaybe-uninitialized] drivers/clk/st/clkgen-fsyn.c:574:16: note: 'params.ndiv' was declared here This changes the error handling so we bail for invalid arguments rather than continuing with uninitialized data. Signed-off-by: Arnd Bergmann Signed-off-by: Stephen Boyd --- drivers/clk/st/clkgen-fsyn.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c index ccb324d97160..dec4eaaecc00 100644 --- a/drivers/clk/st/clkgen-fsyn.c +++ b/drivers/clk/st/clkgen-fsyn.c @@ -574,12 +574,16 @@ static int quadfs_pll_fs660c32_set_rate(struct clk_hw *hw, unsigned long rate, struct stm_fs params; long hwrate = 0; unsigned long flags = 0; + int ret; if (!rate || !parent_rate) return -EINVAL; - if (!clk_fs660c32_vco_get_params(parent_rate, rate, ¶ms)) - clk_fs660c32_vco_get_rate(parent_rate, ¶ms, &hwrate); + ret = clk_fs660c32_vco_get_params(parent_rate, rate, ¶ms); + if (ret) + return ret; + + clk_fs660c32_vco_get_rate(parent_rate, ¶ms, &hwrate); pr_debug("%s: %s new rate %ld [ndiv=0x%x]\n", __func__, clk_hw_get_name(hw), -- cgit v1.2.3 From a66a5114b34bb23396568bf485e05a311b3ee22f Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 28 Aug 2015 18:08:19 -0700 Subject: remoteproc: report error if resource table doesn't exist Currently, if the resource table is completely missing in the firmware, powering up the remoteproc fails silently. Add a message indicating that the resource table is missing in the firmware. Signed-off-by: Stefan Agner Acked-by: Suman Anna Signed-off-by: Ohad Ben-Cohen --- drivers/remoteproc/remoteproc_core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 9e03d158f411..3d7d58a109d8 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -823,8 +823,10 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) /* look for the resource table */ table = rproc_find_rsc_table(rproc, fw, &tablesz); - if (!table) + if (!table) { + dev_err(dev, "Failed to find resource table\n"); goto clean_up; + } /* Verify that resource table in loaded fw is unchanged */ if (rproc->table_csum != crc32(0, table, tablesz)) { -- cgit v1.2.3 From 99c429cb4e628e8b6b8131910952436ad10b21f5 Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Wed, 16 Sep 2015 07:32:54 -0500 Subject: remoteproc/wkup_m3: Use MODULE_DEVICE_TABLE to export alias Use MODULE_DEVICE_TABLE with wkup_m3_rproc_of_match so the module alias is exported and the wkup_m3_rproc driver can automatically probe. Signed-off-by: Dave Gerlach Signed-off-by: Ohad Ben-Cohen --- drivers/remoteproc/wkup_m3_rproc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/remoteproc/wkup_m3_rproc.c b/drivers/remoteproc/wkup_m3_rproc.c index edf81819cce1..02d271d101b4 100644 --- a/drivers/remoteproc/wkup_m3_rproc.c +++ b/drivers/remoteproc/wkup_m3_rproc.c @@ -122,6 +122,7 @@ static const struct of_device_id wkup_m3_rproc_of_match[] = { { .compatible = "ti,am4372-wkup-m3", }, {}, }; +MODULE_DEVICE_TABLE(of, wkup_m3_rproc_of_match); static int wkup_m3_rproc_probe(struct platform_device *pdev) { -- cgit v1.2.3 From 47fff9fd8a7848c44c83b34ad7825d2185b9b319 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 12 Jan 2016 12:46:15 +0000 Subject: remoteproc: debugfs: Return error on invalid 'count' value If 'count' value is invalid, return -EINVAL. Signed-off-by: Lee Jones [bjorn: changed commit message] Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c index 916af5096f57..6fdfa688281a 100644 --- a/drivers/remoteproc/remoteproc_debugfs.c +++ b/drivers/remoteproc/remoteproc_debugfs.c @@ -157,7 +157,7 @@ rproc_recovery_write(struct file *filp, const char __user *user_buf, int ret; if (count < 1 || count > sizeof(buf)) - return count; + return -EINVAL; ret = copy_from_user(buf, user_buf, count); if (ret) -- cgit v1.2.3 From 69e50479bd6b99a377223104be46f7b894ca4208 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 12 Jan 2016 12:46:17 +0000 Subject: remoteproc: debugfs: Add ability to boot remote processor using debugfs This functionality is especially useful during the testing phase. When used in conjunction with Mailbox's Test Framework we can trivially conduct end-to-end testing i.e. boot co-processor, send and receive messages to the co-processor, then shut it down again (repeat as required). Signed-off-by: Ludovic Barre Signed-off-by: Lee Jones Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_debugfs.c | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'drivers') diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c index 6fdfa688281a..74a120b6e206 100644 --- a/drivers/remoteproc/remoteproc_debugfs.c +++ b/drivers/remoteproc/remoteproc_debugfs.c @@ -88,8 +88,42 @@ static ssize_t rproc_state_read(struct file *filp, char __user *userbuf, return simple_read_from_buffer(userbuf, count, ppos, buf, i); } +static ssize_t rproc_state_write(struct file *filp, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct rproc *rproc = filp->private_data; + char buf[10]; + int ret; + + if (count > sizeof(buf) || count <= 0) + return -EINVAL; + + ret = copy_from_user(buf, userbuf, count); + if (ret) + return -EFAULT; + + if (buf[count - 1] == '\n') + buf[count - 1] = '\0'; + + if (!strncmp(buf, "start", count)) { + ret = rproc_boot(rproc); + if (ret) { + dev_err(&rproc->dev, "Boot failed: %d\n", ret); + return ret; + } + } else if (!strncmp(buf, "stop", count)) { + rproc_shutdown(rproc); + } else { + dev_err(&rproc->dev, "Unrecognised option: %s\n", buf); + return -EINVAL; + } + + return count; +} + static const struct file_operations rproc_state_ops = { .read = rproc_state_read, + .write = rproc_state_write, .open = simple_open, .llseek = generic_file_llseek, }; -- cgit v1.2.3 From 63edb0310a5ca736c81aaba661b365cd4887cd3b Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 12 Jan 2016 12:46:18 +0000 Subject: remoteproc: Supply controller driver for ST's Remote Processors Signed-off-by: Ludovic Barre Signed-off-by: Lee Jones Signed-off-by: Bjorn Andersson --- drivers/remoteproc/Kconfig | 9 ++ drivers/remoteproc/Makefile | 1 + drivers/remoteproc/st_remoteproc.c | 297 +++++++++++++++++++++++++++++++++++++ 3 files changed, 307 insertions(+) create mode 100644 drivers/remoteproc/st_remoteproc.c (limited to 'drivers') diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 28c711f0ac6b..72e97d7a5209 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -77,4 +77,13 @@ config DA8XX_REMOTEPROC It's safe to say n here if you're not interested in multimedia offloading. +config ST_REMOTEPROC + tristate "ST remoteproc support" + depends on ARCH_STI + select REMOTEPROC + help + Say y here to support ST's adjunct processors via the remote + processor framework. + This can be either built-in or a loadable module. + endmenu diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index 81b04d1e2e58..279cb2edc880 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o obj-$(CONFIG_STE_MODEM_RPROC) += ste_modem_rproc.o obj-$(CONFIG_WKUP_M3_RPROC) += wkup_m3_rproc.o obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o +obj-$(CONFIG_ST_REMOTEPROC) += st_remoteproc.o diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c new file mode 100644 index 000000000000..6bb04d453247 --- /dev/null +++ b/drivers/remoteproc/st_remoteproc.c @@ -0,0 +1,297 @@ +/* + * ST's Remote Processor Control Driver + * + * Copyright (C) 2015 STMicroelectronics - All Rights Reserved + * + * Author: Ludovic Barre + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct st_rproc_config { + bool sw_reset; + bool pwr_reset; + unsigned long bootaddr_mask; +}; + +struct st_rproc { + struct st_rproc_config *config; + struct reset_control *sw_reset; + struct reset_control *pwr_reset; + struct clk *clk; + u32 clk_rate; + struct regmap *boot_base; + u32 boot_offset; +}; + +static int st_rproc_start(struct rproc *rproc) +{ + struct st_rproc *ddata = rproc->priv; + int err; + + regmap_update_bits(ddata->boot_base, ddata->boot_offset, + ddata->config->bootaddr_mask, rproc->bootaddr); + + err = clk_enable(ddata->clk); + if (err) { + dev_err(&rproc->dev, "Failed to enable clock\n"); + return err; + } + + if (ddata->config->sw_reset) { + err = reset_control_deassert(ddata->sw_reset); + if (err) { + dev_err(&rproc->dev, "Failed to deassert S/W Reset\n"); + goto sw_reset_fail; + } + } + + if (ddata->config->pwr_reset) { + err = reset_control_deassert(ddata->pwr_reset); + if (err) { + dev_err(&rproc->dev, "Failed to deassert Power Reset\n"); + goto pwr_reset_fail; + } + } + + dev_info(&rproc->dev, "Started from 0x%x\n", rproc->bootaddr); + + return 0; + + +pwr_reset_fail: + if (ddata->config->pwr_reset) + reset_control_assert(ddata->sw_reset); +sw_reset_fail: + clk_disable(ddata->clk); + + return err; +} + +static int st_rproc_stop(struct rproc *rproc) +{ + struct st_rproc *ddata = rproc->priv; + int sw_err = 0, pwr_err = 0; + + if (ddata->config->sw_reset) { + sw_err = reset_control_assert(ddata->sw_reset); + if (sw_err) + dev_err(&rproc->dev, "Failed to assert S/W Reset\n"); + } + + if (ddata->config->pwr_reset) { + pwr_err = reset_control_assert(ddata->pwr_reset); + if (pwr_err) + dev_err(&rproc->dev, "Failed to assert Power Reset\n"); + } + + clk_disable(ddata->clk); + + return sw_err ?: pwr_err; +} + +static struct rproc_ops st_rproc_ops = { + .start = st_rproc_start, + .stop = st_rproc_stop, +}; + +/* + * Fetch state of the processor: 0 is off, 1 is on. + */ +static int st_rproc_state(struct platform_device *pdev) +{ + struct rproc *rproc = platform_get_drvdata(pdev); + struct st_rproc *ddata = rproc->priv; + int reset_sw = 0, reset_pwr = 0; + + if (ddata->config->sw_reset) + reset_sw = reset_control_status(ddata->sw_reset); + + if (ddata->config->pwr_reset) + reset_pwr = reset_control_status(ddata->pwr_reset); + + if (reset_sw < 0 || reset_pwr < 0) + return -EINVAL; + + return !reset_sw && !reset_pwr; +} + +static const struct st_rproc_config st40_rproc_cfg = { + .sw_reset = true, + .pwr_reset = true, + .bootaddr_mask = GENMASK(28, 1), +}; + +static const struct st_rproc_config st231_rproc_cfg = { + .sw_reset = true, + .pwr_reset = false, + .bootaddr_mask = GENMASK(31, 6), +}; + +static const struct of_device_id st_rproc_match[] = { + { .compatible = "st,st40-rproc", .data = &st40_rproc_cfg }, + { .compatible = "st,st231-rproc", .data = &st231_rproc_cfg }, + {}, +}; +MODULE_DEVICE_TABLE(of, st_rproc_match); + +static int st_rproc_parse_dt(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct rproc *rproc = platform_get_drvdata(pdev); + struct st_rproc *ddata = rproc->priv; + struct device_node *np = dev->of_node; + int err; + + if (ddata->config->sw_reset) { + ddata->sw_reset = devm_reset_control_get(dev, "sw_reset"); + if (IS_ERR(ddata->sw_reset)) { + dev_err(dev, "Failed to get S/W Reset\n"); + return PTR_ERR(ddata->sw_reset); + } + } + + if (ddata->config->pwr_reset) { + ddata->pwr_reset = devm_reset_control_get(dev, "pwr_reset"); + if (IS_ERR(ddata->pwr_reset)) { + dev_err(dev, "Failed to get Power Reset\n"); + return PTR_ERR(ddata->pwr_reset); + } + } + + ddata->clk = devm_clk_get(dev, NULL); + if (IS_ERR(ddata->clk)) { + dev_err(dev, "Failed to get clock\n"); + return PTR_ERR(ddata->clk); + } + + err = of_property_read_u32(np, "clock-frequency", &ddata->clk_rate); + if (err) { + dev_err(dev, "failed to get clock frequency\n"); + return err; + } + + ddata->boot_base = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); + if (!ddata->boot_base) { + dev_err(dev, "Boot base not found\n"); + return -EINVAL; + } + + err = of_property_read_u32_index(np, "st,syscfg", 1, + &ddata->boot_offset); + if (err) { + dev_err(dev, "Boot offset not found\n"); + return -EINVAL; + } + + err = of_reserved_mem_device_init(dev); + if (err) { + dev_err(dev, "Failed to obtain shared memory\n"); + return err; + } + + err = clk_prepare(ddata->clk); + if (err) + dev_err(dev, "failed to get clock\n"); + + return err; +} + +static int st_rproc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const struct of_device_id *match; + struct st_rproc *ddata; + struct device_node *np = dev->of_node; + struct rproc *rproc; + int enabled; + int ret; + + match = of_match_device(st_rproc_match, dev); + if (!match || !match->data) { + dev_err(dev, "No device match found\n"); + return -ENODEV; + } + + rproc = rproc_alloc(dev, np->name, &st_rproc_ops, NULL, sizeof(*ddata)); + if (!rproc) + return -ENOMEM; + + rproc->has_iommu = false; + ddata = rproc->priv; + ddata->config = (struct st_rproc_config *)match->data; + + platform_set_drvdata(pdev, rproc); + + ret = st_rproc_parse_dt(pdev); + if (ret) + goto free_rproc; + + enabled = st_rproc_state(pdev); + if (enabled < 0) + goto free_rproc; + + if (enabled) { + atomic_inc(&rproc->power); + rproc->state = RPROC_RUNNING; + } else { + clk_set_rate(ddata->clk, ddata->clk_rate); + } + + ret = rproc_add(rproc); + if (ret) + goto free_rproc; + + return 0; + +free_rproc: + rproc_put(rproc); + return ret; +} + +static int st_rproc_remove(struct platform_device *pdev) +{ + struct rproc *rproc = platform_get_drvdata(pdev); + struct st_rproc *ddata = rproc->priv; + + rproc_del(rproc); + + clk_disable_unprepare(ddata->clk); + + of_reserved_mem_device_release(&pdev->dev); + + rproc_put(rproc); + + return 0; +} + +static struct platform_driver st_rproc_driver = { + .probe = st_rproc_probe, + .remove = st_rproc_remove, + .driver = { + .name = "st-rproc", + .of_match_table = of_match_ptr(st_rproc_match), + }, +}; +module_platform_driver(st_rproc_driver); + +MODULE_DESCRIPTION("ST Remote Processor Control Driver"); +MODULE_AUTHOR("Ludovic Barre "); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 74608fc98d2856fa7201a498b61c9dd9455b504a Mon Sep 17 00:00:00 2001 From: Prashant Sreedharan Date: Thu, 28 Jan 2016 03:11:20 -0500 Subject: bnxt_en: Ring free response from close path should use completion ring Use completion ring for ring free response from firmware. The response will be the last entry in the ring and we can free the ring after getting the response. This will guarantee no spurious DMA to freed memory. Signed-off-by: Prashant Sreedharan Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index df835f5e46d8..17dcacd3ad43 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -3406,7 +3406,7 @@ static int hwrm_ring_free_send_msg(struct bnxt *bp, struct hwrm_ring_free_output *resp = bp->hwrm_cmd_resp_addr; u16 error_code; - bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_FREE, -1, -1); + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_FREE, cmpl_ring_id, -1); req.ring_type = ring_type; req.ring_id = cpu_to_le16(ring->fw_ring_id); -- cgit v1.2.3 From 8a4d4c8dde7a4119bce3fd8287dca193ff6356da Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 28 Jan 2016 03:11:21 -0500 Subject: bnxt_en: Exclude rx_drop_pkts hw counter from the stack's rx_dropped counter. This hardware counter is misleading as it counts dropped packets that don't match the hardware filters for unicast/broadcast/multicast. We will still report this counter in ethtool -S for diagnostics purposes. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 17dcacd3ad43..ebc541340ea1 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -4819,8 +4819,6 @@ bnxt_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) stats->multicast += le64_to_cpu(hw_stats->rx_mcast_pkts); - stats->rx_dropped += le64_to_cpu(hw_stats->rx_drop_pkts); - stats->tx_dropped += le64_to_cpu(hw_stats->tx_drop_pkts); } -- cgit v1.2.3 From d612a579771385e08f7b665063b36bfa52c03ea3 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 28 Jan 2016 03:11:22 -0500 Subject: bnxt_en: Fix crash in bnxt_free_tx_skbs() during tx timeout. The ring index j is not wrapped properly at the end of the ring, causing it to reference pointers past the end of the ring. For proper loop termination and to access the ring properly, we need to increment j and mask it before referencing the ring entry. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index ebc541340ea1..5dc89e527e7d 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -1490,10 +1490,11 @@ static void bnxt_free_tx_skbs(struct bnxt *bp) last = tx_buf->nr_frags; j += 2; - for (k = 0; k < last; k++, j = NEXT_TX(j)) { + for (k = 0; k < last; k++, j++) { + int ring_idx = j & bp->tx_ring_mask; skb_frag_t *frag = &skb_shinfo(skb)->frags[k]; - tx_buf = &txr->tx_buf_ring[j]; + tx_buf = &txr->tx_buf_ring[ring_idx]; dma_unmap_page( &pdev->dev, dma_unmap_addr(tx_buf, mapping), -- cgit v1.2.3 From 45eb570a0db3391c88cba04510a20fe7e4125497 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 29 Jan 2016 17:42:51 -0800 Subject: libnvdimm, pfn: fix restoring memmap location This path was missed when turning on the memmap in pmem support. Permit 'pmem' as a valid location for the map. Reported-by: Jeff Moyer Signed-off-by: Dan Williams --- drivers/nvdimm/pfn_devs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c index 0cc9048b86e2..ae81a2f1da50 100644 --- a/drivers/nvdimm/pfn_devs.c +++ b/drivers/nvdimm/pfn_devs.c @@ -301,10 +301,8 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn) switch (le32_to_cpu(pfn_sb->mode)) { case PFN_MODE_RAM: - break; case PFN_MODE_PMEM: - /* TODO: allocate from PMEM support */ - return -ENOTTY; + break; default: return -ENXIO; } -- cgit v1.2.3 From 3db70a853202c252a8ebefa71ccb088ad149cdd2 Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Wed, 25 Nov 2015 17:52:55 -0500 Subject: xen/blkfront: realloc ring info in blkif_resume Need to reallocate ring info in the resume path, because info->rinfo was freed in blkif_free(). And 'multi-queue-max-queues' backend reports may have been changed. Signed-off-by: Bob Liu Reported-and-Tested-by: Konrad Rzeszutek Wilk Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkfront.c | 74 +++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 8a8dc91c39f7..83eb9e6bf8b0 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -1873,6 +1873,43 @@ again: return err; } +static int negotiate_mq(struct blkfront_info *info) +{ + unsigned int backend_max_queues = 0; + int err; + unsigned int i; + + BUG_ON(info->nr_rings); + + /* Check if backend supports multiple queues. */ + err = xenbus_scanf(XBT_NIL, info->xbdev->otherend, + "multi-queue-max-queues", "%u", &backend_max_queues); + if (err < 0) + backend_max_queues = 1; + + info->nr_rings = min(backend_max_queues, xen_blkif_max_queues); + /* We need at least one ring. */ + if (!info->nr_rings) + info->nr_rings = 1; + + info->rinfo = kzalloc(sizeof(struct blkfront_ring_info) * info->nr_rings, GFP_KERNEL); + if (!info->rinfo) { + xenbus_dev_fatal(info->xbdev, -ENOMEM, "allocating ring_info structure"); + return -ENOMEM; + } + + for (i = 0; i < info->nr_rings; i++) { + struct blkfront_ring_info *rinfo; + + rinfo = &info->rinfo[i]; + INIT_LIST_HEAD(&rinfo->indirect_pages); + INIT_LIST_HEAD(&rinfo->grants); + rinfo->dev_info = info; + INIT_WORK(&rinfo->work, blkif_restart_queue); + spin_lock_init(&rinfo->ring_lock); + } + return 0; +} /** * Entry point to this code when a new device is created. Allocate the basic * structures and the ring buffer for communication with the backend, and @@ -1883,9 +1920,7 @@ static int blkfront_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int err, vdevice; - unsigned int r_index; struct blkfront_info *info; - unsigned int backend_max_queues = 0; /* FIXME: Use dynamic device id if this is not set. */ err = xenbus_scanf(XBT_NIL, dev->nodename, @@ -1936,33 +1971,10 @@ static int blkfront_probe(struct xenbus_device *dev, } info->xbdev = dev; - /* Check if backend supports multiple queues. */ - err = xenbus_scanf(XBT_NIL, info->xbdev->otherend, - "multi-queue-max-queues", "%u", &backend_max_queues); - if (err < 0) - backend_max_queues = 1; - - info->nr_rings = min(backend_max_queues, xen_blkif_max_queues); - /* We need at least one ring. */ - if (!info->nr_rings) - info->nr_rings = 1; - - info->rinfo = kzalloc(sizeof(struct blkfront_ring_info) * info->nr_rings, GFP_KERNEL); - if (!info->rinfo) { - xenbus_dev_fatal(dev, -ENOMEM, "allocating ring_info structure"); + err = negotiate_mq(info); + if (err) { kfree(info); - return -ENOMEM; - } - - for (r_index = 0; r_index < info->nr_rings; r_index++) { - struct blkfront_ring_info *rinfo; - - rinfo = &info->rinfo[r_index]; - INIT_LIST_HEAD(&rinfo->indirect_pages); - INIT_LIST_HEAD(&rinfo->grants); - rinfo->dev_info = info; - INIT_WORK(&rinfo->work, blkif_restart_queue); - spin_lock_init(&rinfo->ring_lock); + return err; } mutex_init(&info->mutex); @@ -2123,12 +2135,16 @@ static int blkif_recover(struct blkfront_info *info) static int blkfront_resume(struct xenbus_device *dev) { struct blkfront_info *info = dev_get_drvdata(&dev->dev); - int err; + int err = 0; dev_dbg(&dev->dev, "blkfront_resume: %s\n", dev->nodename); blkif_free(info, info->connected == BLKIF_STATE_CONNECTED); + err = negotiate_mq(info); + if (err) + return err; + err = talk_to_blkback(dev, info); /* -- cgit v1.2.3 From 8a9ebe717a133ba7bc90b06047f43cc6b8bcb8b3 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 18 Jan 2016 14:09:27 -0600 Subject: target: Fix WRITE_SAME/DISCARD conversion to linux 512b sectors In a couple places we are not converting to/from the Linux block layer 512 bytes sectors. 1. The request queue values and what we do are a mismatch of things: max_discard_sectors - This is in linux block layer 512 byte sectors. We are just copying this to max_unmap_lba_count. discard_granularity - This is in bytes. We are converting it to Linux block layer 512 byte sectors. discard_alignment - This is in bytes. We are just copying this over. The problem is that the core LIO code exports these values in spc_emulate_evpd_b0 and we use them to test request arguments in sbc_execute_unmap, but we never convert to the block size we export to the initiator. If we are not using 512 byte sectors then we are exporting the wrong values or are checks are off. And, for the discard_alignment/bytes case we are just plain messed up. 2. blkdev_issue_discard's start and number of sector arguments are supposed to be in linux block layer 512 byte sectors. We are currently passing in the values we get from the initiator which might be based on some other sector size. There is a similar problem in iblock_execute_write_same where the bio functions want values in 512 byte sectors but we are passing in what we got from the initiator. Signed-off-by: Mike Christie Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 44 +++++++++++++++++++++++++++ drivers/target/target_core_file.c | 29 ++++++------------ drivers/target/target_core_iblock.c | 58 +++++++++--------------------------- include/target/target_core_backend.h | 3 ++ 4 files changed, 70 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index cacd97a8cbd0..da457e25717a 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -828,6 +828,50 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) return dev; } +/* + * Check if the underlying struct block_device request_queue supports + * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM + * in ATA and we need to set TPE=1 + */ +bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, + struct request_queue *q, int block_size) +{ + if (!blk_queue_discard(q)) + return false; + + attrib->max_unmap_lba_count = (q->limits.max_discard_sectors << 9) / + block_size; + /* + * Currently hardcoded to 1 in Linux/SCSI code.. + */ + attrib->max_unmap_block_desc_count = 1; + attrib->unmap_granularity = q->limits.discard_granularity / block_size; + attrib->unmap_granularity_alignment = q->limits.discard_alignment / + block_size; + attrib->unmap_zeroes_data = q->limits.discard_zeroes_data; + return true; +} +EXPORT_SYMBOL(target_configure_unmap_from_queue); + +/* + * Convert from blocksize advertised to the initiator to the 512 byte + * units unconditionally used by the Linux block layer. + */ +sector_t target_to_linux_sector(struct se_device *dev, sector_t lb) +{ + switch (dev->dev_attrib.block_size) { + case 4096: + return lb << 3; + case 2048: + return lb << 2; + case 1024: + return lb << 1; + default: + return lb; + } +} +EXPORT_SYMBOL(target_to_linux_sector); + int target_configure_device(struct se_device *dev) { struct se_hba *hba = dev->se_hba; diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index e3195700211a..75f0f08b2a34 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -160,25 +160,11 @@ static int fd_configure_device(struct se_device *dev) " block_device blocks: %llu logical_block_size: %d\n", dev_size, div_u64(dev_size, fd_dev->fd_block_size), fd_dev->fd_block_size); - /* - * Check if the underlying struct block_device request_queue supports - * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM - * in ATA and we need to set TPE=1 - */ - if (blk_queue_discard(q)) { - dev->dev_attrib.max_unmap_lba_count = - q->limits.max_discard_sectors; - /* - * Currently hardcoded to 1 in Linux/SCSI code.. - */ - dev->dev_attrib.max_unmap_block_desc_count = 1; - dev->dev_attrib.unmap_granularity = - q->limits.discard_granularity >> 9; - dev->dev_attrib.unmap_granularity_alignment = - q->limits.discard_alignment; + + if (target_configure_unmap_from_queue(&dev->dev_attrib, q, + fd_dev->fd_block_size)) pr_debug("IFILE: BLOCK Discard support available," - " disabled by default\n"); - } + " disabled by default\n"); /* * Enable write same emulation for IBLOCK and use 0xFFFF as * the smaller WRITE_SAME(10) only has a two-byte block count. @@ -490,9 +476,12 @@ fd_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb) if (S_ISBLK(inode->i_mode)) { /* The backend is block device, use discard */ struct block_device *bdev = inode->i_bdev; + struct se_device *dev = cmd->se_dev; - ret = blkdev_issue_discard(bdev, lba, - nolb, GFP_KERNEL, 0); + ret = blkdev_issue_discard(bdev, + target_to_linux_sector(dev, lba), + target_to_linux_sector(dev, nolb), + GFP_KERNEL, 0); if (ret < 0) { pr_warn("FILEIO: blkdev_issue_discard() failed: %d\n", ret); diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 5a2899f9f50b..abe4eb997a84 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -121,29 +121,11 @@ static int iblock_configure_device(struct se_device *dev) dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q); dev->dev_attrib.hw_queue_depth = q->nr_requests; - /* - * Check if the underlying struct block_device request_queue supports - * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM - * in ATA and we need to set TPE=1 - */ - if (blk_queue_discard(q)) { - dev->dev_attrib.max_unmap_lba_count = - q->limits.max_discard_sectors; - - /* - * Currently hardcoded to 1 in Linux/SCSI code.. - */ - dev->dev_attrib.max_unmap_block_desc_count = 1; - dev->dev_attrib.unmap_granularity = - q->limits.discard_granularity >> 9; - dev->dev_attrib.unmap_granularity_alignment = - q->limits.discard_alignment; - dev->dev_attrib.unmap_zeroes_data = - q->limits.discard_zeroes_data; - + if (target_configure_unmap_from_queue(&dev->dev_attrib, q, + dev->dev_attrib.hw_block_size)) pr_debug("IBLOCK: BLOCK Discard support available," - " disabled by default\n"); - } + " disabled by default\n"); + /* * Enable write same emulation for IBLOCK and use 0xFFFF as * the smaller WRITE_SAME(10) only has a two-byte block count. @@ -415,9 +397,13 @@ static sense_reason_t iblock_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb) { struct block_device *bdev = IBLOCK_DEV(cmd->se_dev)->ibd_bd; + struct se_device *dev = cmd->se_dev; int ret; - ret = blkdev_issue_discard(bdev, lba, nolb, GFP_KERNEL, 0); + ret = blkdev_issue_discard(bdev, + target_to_linux_sector(dev, lba), + target_to_linux_sector(dev, nolb), + GFP_KERNEL, 0); if (ret < 0) { pr_err("blkdev_issue_discard() failed: %d\n", ret); return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; @@ -433,8 +419,10 @@ iblock_execute_write_same(struct se_cmd *cmd) struct scatterlist *sg; struct bio *bio; struct bio_list list; - sector_t block_lba = cmd->t_task_lba; - sector_t sectors = sbc_get_write_same_sectors(cmd); + struct se_device *dev = cmd->se_dev; + sector_t block_lba = target_to_linux_sector(dev, cmd->t_task_lba); + sector_t sectors = target_to_linux_sector(dev, + sbc_get_write_same_sectors(cmd)); if (cmd->prot_op) { pr_err("WRITE_SAME: Protection information with IBLOCK" @@ -648,12 +636,12 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, enum dma_data_direction data_direction) { struct se_device *dev = cmd->se_dev; + sector_t block_lba = target_to_linux_sector(dev, cmd->t_task_lba); struct iblock_req *ibr; struct bio *bio, *bio_start; struct bio_list list; struct scatterlist *sg; u32 sg_num = sgl_nents; - sector_t block_lba; unsigned bio_cnt; int rw = 0; int i; @@ -679,24 +667,6 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, rw = READ; } - /* - * Convert the blocksize advertised to the initiator to the 512 byte - * units unconditionally used by the Linux block layer. - */ - if (dev->dev_attrib.block_size == 4096) - block_lba = (cmd->t_task_lba << 3); - else if (dev->dev_attrib.block_size == 2048) - block_lba = (cmd->t_task_lba << 2); - else if (dev->dev_attrib.block_size == 1024) - block_lba = (cmd->t_task_lba << 1); - else if (dev->dev_attrib.block_size == 512) - block_lba = cmd->t_task_lba; - else { - pr_err("Unsupported SCSI -> BLOCK LBA conversion:" - " %u\n", dev->dev_attrib.block_size); - return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - } - ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL); if (!ibr) goto fail; diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 56cf8e485ef2..28ee5c2e6bcd 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -94,5 +94,8 @@ sense_reason_t passthrough_parse_cdb(struct se_cmd *cmd, sense_reason_t (*exec_cmd)(struct se_cmd *cmd)); bool target_sense_desc_format(struct se_device *dev); +sector_t target_to_linux_sector(struct se_device *dev, sector_t lb); +bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, + struct request_queue *q, int block_size); #endif /* TARGET_CORE_BACKEND_H */ -- cgit v1.2.3 From dacb58221805bb72ec46a73826c9e59a587d7d68 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Wed, 20 Jan 2016 15:42:58 -0800 Subject: qla2xxx: Fix warning reported by static checker This patch fixes following warning drivers/scsi/qla2xxx/qla_target.c:3587 qlt_do_ctio_completion() warn: impossible condition '(logged_out == 41) => (0-1 == 41)' drivers/scsi/qla2xxx/qla_target.c 3580 case CTIO_PORT_LOGGED_OUT: 3581 case CTIO_PORT_UNAVAILABLE: 3582 { 3583 bool logged_out = (status & 0xFFFF); 3584 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf059, 3585 "qla_target(%d): CTIO with %s status %x " 3586 "received (state %x, se_cmd %p)\n", vha->vp_idx, 3587 (logged_out == CTIO_PORT_LOGGED_OUT) ? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Bool cannot equal 0x26. 3588 "PORT LOGGED OUT" : "PORT UNAVAILABLE", Reported-by: Dan Carpenter Signed-off-by: Himanshu Madhani Signed-off-by: Giridhar Malavali Signed-off-by: Nicholas Bellinger --- drivers/scsi/qla2xxx/qla_target.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 8075a4cdb45c..2c71305d2563 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -3580,12 +3580,13 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle, case CTIO_PORT_LOGGED_OUT: case CTIO_PORT_UNAVAILABLE: { - int logged_out = (status & 0xFFFF); + int logged_out = + (status & 0xFFFF) == CTIO_PORT_LOGGED_OUT; + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf059, "qla_target(%d): CTIO with %s status %x " "received (state %x, se_cmd %p)\n", vha->vp_idx, - (logged_out == CTIO_PORT_LOGGED_OUT) ? - "PORT LOGGED OUT" : "PORT UNAVAILABLE", + logged_out ? "PORT LOGGED OUT" : "PORT UNAVAILABLE", status, cmd->state, se_cmd); if (logged_out && cmd->sess) { -- cgit v1.2.3 From a07100e00ac42a4474530ce17b4978c9e06bde55 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Mon, 7 Dec 2015 19:48:57 -0500 Subject: qla2xxx: Fix TMR ABORT interaction issue between qla2xxx and TCM During lun reset, TMR thread from TCM would issue abort to qla driver. At abort time, each command is in different state. Depending on the state, qla will use the TMR thread to trigger a command free(cmd_kref--) if command is not down at firmware. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/scsi/qla2xxx/qla_target.c | 55 +++++++++++++++++++--------- drivers/scsi/qla2xxx/qla_target.h | 59 +++++++++++++++++------------- drivers/scsi/qla2xxx/tcm_qla2xxx.c | 73 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 142 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 2c71305d2563..74eb776d2faa 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -105,7 +105,7 @@ static void qlt_response_pkt(struct scsi_qla_host *ha, response_t *pkt); static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun, int fn, void *iocb, int flags); static void qlt_send_term_exchange(struct scsi_qla_host *ha, struct qla_tgt_cmd - *cmd, struct atio_from_isp *atio, int ha_locked); + *cmd, struct atio_from_isp *atio, int ha_locked, int ul_abort); static void qlt_reject_free_srr_imm(struct scsi_qla_host *ha, struct qla_tgt_srr_imm *imm, int ha_lock); static void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, @@ -2665,7 +2665,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, /* no need to terminate. FW already freed exchange. */ qlt_abort_cmd_on_host_reset(cmd->vha, cmd); else - qlt_send_term_exchange(vha, cmd, &cmd->atio, 1); + qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0); spin_unlock_irqrestore(&ha->hardware_lock, flags); return 0; } @@ -3173,7 +3173,8 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha, } static void qlt_send_term_exchange(struct scsi_qla_host *vha, - struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked) + struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked, + int ul_abort) { unsigned long flags = 0; int rc; @@ -3193,8 +3194,7 @@ static void qlt_send_term_exchange(struct scsi_qla_host *vha, qlt_alloc_qfull_cmd(vha, atio, 0, 0); done: - if (cmd && (!cmd->aborted || - !cmd->cmd_sent_to_fw)) { + if (cmd && !ul_abort && !cmd->aborted) { if (cmd->sg_mapped) qlt_unmap_sg(vha, cmd); vha->hw->tgt.tgt_ops->free_cmd(cmd); @@ -3253,21 +3253,38 @@ static void qlt_chk_exch_leak_thresh_hold(struct scsi_qla_host *vha) } -void qlt_abort_cmd(struct qla_tgt_cmd *cmd) +int qlt_abort_cmd(struct qla_tgt_cmd *cmd) { struct qla_tgt *tgt = cmd->tgt; struct scsi_qla_host *vha = tgt->vha; struct se_cmd *se_cmd = &cmd->se_cmd; + unsigned long flags; ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014, "qla_target(%d): terminating exchange for aborted cmd=%p " "(se_cmd=%p, tag=%llu)", vha->vp_idx, cmd, &cmd->se_cmd, se_cmd->tag); + spin_lock_irqsave(&cmd->cmd_lock, flags); + if (cmd->aborted) { + spin_unlock_irqrestore(&cmd->cmd_lock, flags); + /* + * It's normal to see 2 calls in this path: + * 1) XFER Rdy completion + CMD_T_ABORT + * 2) TCM TMR - drain_state_list + */ + ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff, + "multiple abort. %p transport_state %x, t_state %x," + " se_cmd_flags %x \n", cmd, cmd->se_cmd.transport_state, + cmd->se_cmd.t_state,cmd->se_cmd.se_cmd_flags); + return EIO; + } cmd->aborted = 1; cmd->cmd_flags |= BIT_6; + spin_unlock_irqrestore(&cmd->cmd_lock, flags); - qlt_send_term_exchange(vha, cmd, &cmd->atio, 0); + qlt_send_term_exchange(vha, cmd, &cmd->atio, 0, 1); + return 0; } EXPORT_SYMBOL(qlt_abort_cmd); @@ -3282,6 +3299,9 @@ void qlt_free_cmd(struct qla_tgt_cmd *cmd) BUG_ON(cmd->cmd_in_wq); + if (cmd->sg_mapped) + qlt_unmap_sg(cmd->vha, cmd); + if (!cmd->q_full) qlt_decr_num_pend_cmds(cmd->vha); @@ -3399,7 +3419,7 @@ static int qlt_term_ctio_exchange(struct scsi_qla_host *vha, void *ctio, term = 1; if (term) - qlt_send_term_exchange(vha, cmd, &cmd->atio, 1); + qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0); return term; } @@ -3755,6 +3775,7 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) goto out_term; } + spin_lock_init(&cmd->cmd_lock); cdb = &atio->u.isp24.fcp_cmnd.cdb[0]; cmd->se_cmd.tag = atio->u.isp24.exchange_addr; cmd->unpacked_lun = scsilun_to_int( @@ -3797,7 +3818,7 @@ out_term: */ cmd->cmd_flags |= BIT_2; spin_lock_irqsave(&ha->hardware_lock, flags); - qlt_send_term_exchange(vha, NULL, &cmd->atio, 1); + qlt_send_term_exchange(vha, NULL, &cmd->atio, 1, 0); qlt_decr_num_pend_cmds(vha); percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag); @@ -3919,7 +3940,7 @@ static void qlt_create_sess_from_atio(struct work_struct *work) out_term: spin_lock_irqsave(&ha->hardware_lock, flags); - qlt_send_term_exchange(vha, NULL, &op->atio, 1); + qlt_send_term_exchange(vha, NULL, &op->atio, 1, 0); spin_unlock_irqrestore(&ha->hardware_lock, flags); kfree(op); @@ -4772,7 +4793,7 @@ out_reject: dump_stack(); } else { cmd->cmd_flags |= BIT_9; - qlt_send_term_exchange(vha, cmd, &cmd->atio, 1); + qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0); } spin_unlock_irqrestore(&ha->hardware_lock, flags); } @@ -4951,7 +4972,7 @@ static void qlt_prepare_srr_imm(struct scsi_qla_host *vha, sctio, sctio->srr_id); list_del(&sctio->srr_list_entry); qlt_send_term_exchange(vha, sctio->cmd, - &sctio->cmd->atio, 1); + &sctio->cmd->atio, 1, 0); kfree(sctio); } } @@ -5124,7 +5145,7 @@ static int __qlt_send_busy(struct scsi_qla_host *vha, atio->u.isp24.fcp_hdr.s_id); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); if (!sess) { - qlt_send_term_exchange(vha, NULL, atio, 1); + qlt_send_term_exchange(vha, NULL, atio, 1, 0); return 0; } /* Sending marker isn't necessary, since we called from ISR */ @@ -5407,7 +5428,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, #if 1 /* With TERM EXCHANGE some FC cards refuse to boot */ qlt_send_busy(vha, atio, SAM_STAT_BUSY); #else - qlt_send_term_exchange(vha, NULL, atio, 1); + qlt_send_term_exchange(vha, NULL, atio, 1, 0); #endif if (!ha_locked) @@ -5524,7 +5545,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) #if 1 /* With TERM EXCHANGE some FC cards refuse to boot */ qlt_send_busy(vha, atio, 0); #else - qlt_send_term_exchange(vha, NULL, atio, 1); + qlt_send_term_exchange(vha, NULL, atio, 1, 0); #endif } else { if (tgt->tgt_stop) { @@ -5533,7 +5554,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) "command to target, sending TERM " "EXCHANGE for rsp\n"); qlt_send_term_exchange(vha, NULL, - atio, 1); + atio, 1, 0); } else { ql_dbg(ql_dbg_tgt, vha, 0xe060, "qla_target(%d): Unable to send " @@ -5961,7 +5982,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt, return; out_term: - qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 0); + qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 1, 0); if (sess) ha->tgt.tgt_ops->put_sess(sess); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 71b2865ba3c8..22a6a767fe07 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -943,6 +943,36 @@ struct qla_tgt_sess { qlt_plogi_ack_t *plogi_link[QLT_PLOGI_LINK_MAX]; }; +typedef enum { + /* + * BIT_0 - Atio Arrival / schedule to work + * BIT_1 - qlt_do_work + * BIT_2 - qlt_do work failed + * BIT_3 - xfer rdy/tcm_qla2xxx_write_pending + * BIT_4 - read respond/tcm_qla2xx_queue_data_in + * BIT_5 - status respond / tcm_qla2xx_queue_status + * BIT_6 - tcm request to abort/Term exchange. + * pre_xmit_response->qlt_send_term_exchange + * BIT_7 - SRR received (qlt_handle_srr->qlt_xmit_response) + * BIT_8 - SRR received (qlt_handle_srr->qlt_rdy_to_xfer) + * BIT_9 - SRR received (qla_handle_srr->qlt_send_term_exchange) + * BIT_10 - Data in - hanlde_data->tcm_qla2xxx_handle_data + + * BIT_12 - good completion - qlt_ctio_do_completion -->free_cmd + * BIT_13 - Bad completion - + * qlt_ctio_do_completion --> qlt_term_ctio_exchange + * BIT_14 - Back end data received/sent. + * BIT_15 - SRR prepare ctio + * BIT_16 - complete free + * BIT_17 - flush - qlt_abort_cmd_on_host_reset + * BIT_18 - completion w/abort status + * BIT_19 - completion w/unknown status + * BIT_20 - tcm_qla2xxx_free_cmd + */ + CMD_FLAG_DATA_WORK = BIT_11, + CMD_FLAG_DATA_WORK_FREE = BIT_21, +} cmd_flags_t; + struct qla_tgt_cmd { struct se_cmd se_cmd; struct qla_tgt_sess *sess; @@ -952,6 +982,7 @@ struct qla_tgt_cmd { /* Sense buffer that will be mapped into outgoing status */ unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER]; + spinlock_t cmd_lock; /* to save extra sess dereferences */ unsigned int conf_compl_supported:1; unsigned int sg_mapped:1; @@ -986,30 +1017,8 @@ struct qla_tgt_cmd { uint64_t jiffies_at_alloc; uint64_t jiffies_at_free; - /* BIT_0 - Atio Arrival / schedule to work - * BIT_1 - qlt_do_work - * BIT_2 - qlt_do work failed - * BIT_3 - xfer rdy/tcm_qla2xxx_write_pending - * BIT_4 - read respond/tcm_qla2xx_queue_data_in - * BIT_5 - status respond / tcm_qla2xx_queue_status - * BIT_6 - tcm request to abort/Term exchange. - * pre_xmit_response->qlt_send_term_exchange - * BIT_7 - SRR received (qlt_handle_srr->qlt_xmit_response) - * BIT_8 - SRR received (qlt_handle_srr->qlt_rdy_to_xfer) - * BIT_9 - SRR received (qla_handle_srr->qlt_send_term_exchange) - * BIT_10 - Data in - hanlde_data->tcm_qla2xxx_handle_data - * BIT_11 - Data actually going to TCM : tcm_qla2xx_handle_data_work - * BIT_12 - good completion - qlt_ctio_do_completion -->free_cmd - * BIT_13 - Bad completion - - * qlt_ctio_do_completion --> qlt_term_ctio_exchange - * BIT_14 - Back end data received/sent. - * BIT_15 - SRR prepare ctio - * BIT_16 - complete free - * BIT_17 - flush - qlt_abort_cmd_on_host_reset - * BIT_18 - completion w/abort status - * BIT_19 - completion w/unknown status - */ - uint32_t cmd_flags; + + cmd_flags_t cmd_flags; }; struct qla_tgt_sess_work_param { @@ -1148,7 +1157,7 @@ static inline void sid_to_portid(const uint8_t *s_id, port_id_t *p) extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *); extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *); extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t); -extern void qlt_abort_cmd(struct qla_tgt_cmd *); +extern int qlt_abort_cmd(struct qla_tgt_cmd *); extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *); extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *); extern void qlt_free_cmd(struct qla_tgt_cmd *cmd); diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index faf0a126627f..3eecdd1bc6fb 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -298,6 +298,10 @@ static void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *cmd) { cmd->vha->tgt_counters.core_qla_free_cmd++; cmd->cmd_in_wq = 1; + + BUG_ON(cmd->cmd_flags & BIT_20); + cmd->cmd_flags |= BIT_20; + INIT_WORK(&cmd->work, tcm_qla2xxx_complete_free); queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work); } @@ -374,6 +378,20 @@ static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd) { struct qla_tgt_cmd *cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); + + if (cmd->aborted) { + /* Cmd can loop during Q-full. tcm_qla2xxx_aborted_task + * can get ahead of this cmd. tcm_qla2xxx_aborted_task + * already kick start the free. + */ + pr_debug("write_pending aborted cmd[%p] refcount %d " + "transport_state %x, t_state %x, se_cmd_flags %x\n", + cmd,cmd->se_cmd.cmd_kref.refcount.counter, + cmd->se_cmd.transport_state, + cmd->se_cmd.t_state, + cmd->se_cmd.se_cmd_flags); + return 0; + } cmd->cmd_flags |= BIT_3; cmd->bufflen = se_cmd->data_length; cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); @@ -405,7 +423,7 @@ static int tcm_qla2xxx_write_pending_status(struct se_cmd *se_cmd) se_cmd->t_state == TRANSPORT_COMPLETE_QF_WP) { spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); wait_for_completion_timeout(&se_cmd->t_transport_stop_comp, - 3 * HZ); + 50); return 0; } spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); @@ -465,13 +483,25 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd, static void tcm_qla2xxx_handle_data_work(struct work_struct *work) { struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); + unsigned long flags; /* * Ensure that the complete FCP WRITE payload has been received. * Otherwise return an exception via CHECK_CONDITION status. */ cmd->cmd_in_wq = 0; - cmd->cmd_flags |= BIT_11; + + spin_lock_irqsave(&cmd->cmd_lock, flags); + cmd->cmd_flags |= CMD_FLAG_DATA_WORK; + if (cmd->aborted) { + cmd->cmd_flags |= CMD_FLAG_DATA_WORK_FREE; + spin_unlock_irqrestore(&cmd->cmd_lock, flags); + + tcm_qla2xxx_free_cmd(cmd); + return; + } + spin_unlock_irqrestore(&cmd->cmd_lock, flags); + cmd->vha->tgt_counters.qla_core_ret_ctio++; if (!cmd->write_data_transferred) { /* @@ -546,6 +576,20 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd) struct qla_tgt_cmd *cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); + if (cmd->aborted) { + /* Cmd can loop during Q-full. tcm_qla2xxx_aborted_task + * can get ahead of this cmd. tcm_qla2xxx_aborted_task + * already kick start the free. + */ + pr_debug("queue_data_in aborted cmd[%p] refcount %d " + "transport_state %x, t_state %x, se_cmd_flags %x\n", + cmd,cmd->se_cmd.cmd_kref.refcount.counter, + cmd->se_cmd.transport_state, + cmd->se_cmd.t_state, + cmd->se_cmd.se_cmd_flags); + return 0; + } + cmd->cmd_flags |= BIT_4; cmd->bufflen = se_cmd->data_length; cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); @@ -637,11 +681,34 @@ static void tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd) qlt_xmit_tm_rsp(mcmd); } + +#define DATA_WORK_NOT_FREE(_flags) \ + (( _flags & (CMD_FLAG_DATA_WORK|CMD_FLAG_DATA_WORK_FREE)) == \ + CMD_FLAG_DATA_WORK) static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd) { struct qla_tgt_cmd *cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); - qlt_abort_cmd(cmd); + unsigned long flags; + + if (qlt_abort_cmd(cmd)) + return; + + spin_lock_irqsave(&cmd->cmd_lock, flags); + if ((cmd->state == QLA_TGT_STATE_NEW)|| + ((cmd->state == QLA_TGT_STATE_DATA_IN) && + DATA_WORK_NOT_FREE(cmd->cmd_flags)) ) { + + cmd->cmd_flags |= CMD_FLAG_DATA_WORK_FREE; + spin_unlock_irqrestore(&cmd->cmd_lock, flags); + /* Cmd have not reached firmware. + * Use this trigger to free it. */ + tcm_qla2xxx_free_cmd(cmd); + return; + } + spin_unlock_irqrestore(&cmd->cmd_lock, flags); + return; + } static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *, -- cgit v1.2.3 From 59a557be385b66c1da20e9cfc6ff6c2e676c6804 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 28 Jan 2016 17:54:33 +0100 Subject: net: moxart: use correct accessors for DMA memory The moxart ethernet driver confuses coherent DMA buffers with MMIO registers. moxart_ether.c: In function 'moxart_mac_setup_desc_ring': moxart_ether.c:146:428: error: passing argument 1 of '__fswab32' makes integer from pointer without a cast [-Werror=int-conversion] moxart_ether.c:74:39: warning: incorrect type in argument 3 (different address spaces) moxart_ether.c:74:39: expected void *cpu_addr moxart_ether.c:74:39: got void [noderef] *tx_desc_base This leaves the basic logic alone and uses normal pointers for the virtual address of the descriptor. As we cannot use readl/writel to access them, we also introduce our own moxart_desc_read moxart_desc_write helpers that perform the same endianess swap as the original code, but without the address space conversion. The barriers are made explicit here where needed: Even in the worst-case scenario, we just have to use a rmb() after checking ownership so we don't read any input data before we are sure it is value, and we use wmb() before transferring ownership back to the device. Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/ethernet/moxa/moxart_ether.c | 46 +++++++++++++++++++++----------- drivers/net/ethernet/moxa/moxart_ether.h | 4 +-- 2 files changed, 32 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c index a10c928bbd6b..00cfd95ca59d 100644 --- a/drivers/net/ethernet/moxa/moxart_ether.c +++ b/drivers/net/ethernet/moxa/moxart_ether.c @@ -28,6 +28,16 @@ #include "moxart_ether.h" +static inline void moxart_desc_write(u32 data, u32 *desc) +{ + *desc = cpu_to_le32(data); +} + +static inline u32 moxart_desc_read(u32 *desc) +{ + return le32_to_cpu(*desc); +} + static inline void moxart_emac_write(struct net_device *ndev, unsigned int reg, unsigned long value) { @@ -112,7 +122,7 @@ static void moxart_mac_enable(struct net_device *ndev) static void moxart_mac_setup_desc_ring(struct net_device *ndev) { struct moxart_mac_priv_t *priv = netdev_priv(ndev); - void __iomem *desc; + void *desc; int i; for (i = 0; i < TX_DESC_NUM; i++) { @@ -121,7 +131,7 @@ static void moxart_mac_setup_desc_ring(struct net_device *ndev) priv->tx_buf[i] = priv->tx_buf_base + priv->tx_buf_size * i; } - writel(TX_DESC1_END, desc + TX_REG_OFFSET_DESC1); + moxart_desc_write(TX_DESC1_END, desc + TX_REG_OFFSET_DESC1); priv->tx_head = 0; priv->tx_tail = 0; @@ -129,8 +139,8 @@ static void moxart_mac_setup_desc_ring(struct net_device *ndev) for (i = 0; i < RX_DESC_NUM; i++) { desc = priv->rx_desc_base + i * RX_REG_DESC_SIZE; memset(desc, 0, RX_REG_DESC_SIZE); - writel(RX_DESC0_DMA_OWN, desc + RX_REG_OFFSET_DESC0); - writel(RX_BUF_SIZE & RX_DESC1_BUF_SIZE_MASK, + moxart_desc_write(RX_DESC0_DMA_OWN, desc + RX_REG_OFFSET_DESC0); + moxart_desc_write(RX_BUF_SIZE & RX_DESC1_BUF_SIZE_MASK, desc + RX_REG_OFFSET_DESC1); priv->rx_buf[i] = priv->rx_buf_base + priv->rx_buf_size * i; @@ -141,12 +151,12 @@ static void moxart_mac_setup_desc_ring(struct net_device *ndev) if (dma_mapping_error(&ndev->dev, priv->rx_mapping[i])) netdev_err(ndev, "DMA mapping error\n"); - writel(priv->rx_mapping[i], + moxart_desc_write(priv->rx_mapping[i], desc + RX_REG_OFFSET_DESC2 + RX_DESC2_ADDRESS_PHYS); - writel(priv->rx_buf[i], + moxart_desc_write((uintptr_t)priv->rx_buf[i], desc + RX_REG_OFFSET_DESC2 + RX_DESC2_ADDRESS_VIRT); } - writel(RX_DESC1_END, desc + RX_REG_OFFSET_DESC1); + moxart_desc_write(RX_DESC1_END, desc + RX_REG_OFFSET_DESC1); priv->rx_head = 0; @@ -201,14 +211,15 @@ static int moxart_rx_poll(struct napi_struct *napi, int budget) napi); struct net_device *ndev = priv->ndev; struct sk_buff *skb; - void __iomem *desc; + void *desc; unsigned int desc0, len; int rx_head = priv->rx_head; int rx = 0; while (rx < budget) { desc = priv->rx_desc_base + (RX_REG_DESC_SIZE * rx_head); - desc0 = readl(desc + RX_REG_OFFSET_DESC0); + desc0 = moxart_desc_read(desc + RX_REG_OFFSET_DESC0); + rmb(); /* ensure desc0 is up to date */ if (desc0 & RX_DESC0_DMA_OWN) break; @@ -250,7 +261,8 @@ static int moxart_rx_poll(struct napi_struct *napi, int budget) priv->stats.multicast++; rx_next: - writel(RX_DESC0_DMA_OWN, desc + RX_REG_OFFSET_DESC0); + wmb(); /* prevent setting ownership back too early */ + moxart_desc_write(RX_DESC0_DMA_OWN, desc + RX_REG_OFFSET_DESC0); rx_head = RX_NEXT(rx_head); priv->rx_head = rx_head; @@ -310,7 +322,7 @@ static irqreturn_t moxart_mac_interrupt(int irq, void *dev_id) static int moxart_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev) { struct moxart_mac_priv_t *priv = netdev_priv(ndev); - void __iomem *desc; + void *desc; unsigned int len; unsigned int tx_head = priv->tx_head; u32 txdes1; @@ -319,11 +331,12 @@ static int moxart_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev) desc = priv->tx_desc_base + (TX_REG_DESC_SIZE * tx_head); spin_lock_irq(&priv->txlock); - if (readl(desc + TX_REG_OFFSET_DESC0) & TX_DESC0_DMA_OWN) { + if (moxart_desc_read(desc + TX_REG_OFFSET_DESC0) & TX_DESC0_DMA_OWN) { net_dbg_ratelimited("no TX space for packet\n"); priv->stats.tx_dropped++; goto out_unlock; } + rmb(); /* ensure data is only read that had TX_DESC0_DMA_OWN cleared */ len = skb->len > TX_BUF_SIZE ? TX_BUF_SIZE : skb->len; @@ -337,9 +350,9 @@ static int moxart_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev) priv->tx_len[tx_head] = len; priv->tx_skb[tx_head] = skb; - writel(priv->tx_mapping[tx_head], + moxart_desc_write(priv->tx_mapping[tx_head], desc + TX_REG_OFFSET_DESC2 + TX_DESC2_ADDRESS_PHYS); - writel(skb->data, + moxart_desc_write((uintptr_t)skb->data, desc + TX_REG_OFFSET_DESC2 + TX_DESC2_ADDRESS_VIRT); if (skb->len < ETH_ZLEN) { @@ -354,8 +367,9 @@ static int moxart_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev) txdes1 = TX_DESC1_LTS | TX_DESC1_FTS | (len & TX_DESC1_BUF_SIZE_MASK); if (tx_head == TX_DESC_NUM_MASK) txdes1 |= TX_DESC1_END; - writel(txdes1, desc + TX_REG_OFFSET_DESC1); - writel(TX_DESC0_DMA_OWN, desc + TX_REG_OFFSET_DESC0); + moxart_desc_write(txdes1, desc + TX_REG_OFFSET_DESC1); + wmb(); /* flush descriptor before transferring ownership */ + moxart_desc_write(TX_DESC0_DMA_OWN, desc + TX_REG_OFFSET_DESC0); /* start to send packet */ writel(0xffffffff, priv->base + REG_TX_POLL_DEMAND); diff --git a/drivers/net/ethernet/moxa/moxart_ether.h b/drivers/net/ethernet/moxa/moxart_ether.h index 2be9280d608c..93a9563ac7c6 100644 --- a/drivers/net/ethernet/moxa/moxart_ether.h +++ b/drivers/net/ethernet/moxa/moxart_ether.h @@ -300,7 +300,7 @@ struct moxart_mac_priv_t { dma_addr_t rx_base; dma_addr_t rx_mapping[RX_DESC_NUM]; - void __iomem *rx_desc_base; + void *rx_desc_base; unsigned char *rx_buf_base; unsigned char *rx_buf[RX_DESC_NUM]; unsigned int rx_head; @@ -308,7 +308,7 @@ struct moxart_mac_priv_t { dma_addr_t tx_base; dma_addr_t tx_mapping[TX_DESC_NUM]; - void __iomem *tx_desc_base; + void *tx_desc_base; unsigned char *tx_buf_base; unsigned char *tx_buf[RX_DESC_NUM]; unsigned int tx_head; -- cgit v1.2.3 From be1faa92e83b1252d9200c59d8c98aab44463f1e Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 28 Jan 2016 16:54:37 -0500 Subject: net: dsa: mv88e6xxx: fix port VLAN maps Currently the port based VLAN maps should be configured to allow every port to egress frames on all other ports, except themselves. The debugfs interface shows that they are misconfigured. For instance, a 7-port switch has the following content in the related register 0x06: GLOBAL GLOBAL2 SERDES 0 1 2 3 4 5 6 ... 6: 1fa4 1f0f 4 7f 7e 7d 7c 7b 7a 79 ... This means that port 3 is allowed to talk to port 2-6, but cannot talk to ports 0 and 1. With this fix, port 3 can correctly talk to all ports except 3 itself: GLOBAL GLOBAL2 SERDES 0 1 2 3 4 5 6 ... 6: 1fa4 1f0f 4 7e 7d 7b 77 6f 5f 3f ... Fixes: ede8098d0fef ("net: dsa: mv88e6xxx: bridges do not need an FID") Reported-by: Kevin Smith Signed-off-by: Vivien Didelot Reviewed-by: Andrew Lunn Tested-by: Kevin Smith Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 9cc73bf0a081..cf34681af4f6 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -2163,7 +2163,8 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) * database, and allow every port to egress frames on all other ports. */ reg = BIT(ps->num_ports) - 1; /* all ports */ - ret = _mv88e6xxx_port_vlan_map_set(ds, port, reg & ~port); + reg &= ~BIT(port); /* except itself */ + ret = _mv88e6xxx_port_vlan_map_set(ds, port, reg); if (ret) goto abort; -- cgit v1.2.3 From 7256eac13b0e6884355cf40f75db05785d18f5da Mon Sep 17 00:00:00 2001 From: Li RongQing Date: Fri, 29 Jan 2016 09:43:47 +0800 Subject: vxlan: fix a out of bounds access in __vxlan_find_mac The size of all_zeros_mac is 6 byte, but eth_hash() will access the 8 byte, and KASan reported the below bug: [ 8596.479031] BUG: KASan: out of bounds access in __vxlan_find_mac+0x24/0x100 at addr ffffffff841514c0 [ 8596.487647] Read of size 8 by task ip/52820 [ 8596.490818] Address belongs to variable all_zeros_mac+0x0/0x40 [ 8596.496051] CPU: 0 PID: 52820 Comm: ip Tainted: G WC 4.1.15 #1 [ 8596.503520] Hardware name: HP ProLiant DL380p Gen8, BIOS P70 02/10/2014 [ 8596.509365] ffffffff841514c0 ffff88007450f0b8 ffffffff822fa5e1 0000000000000032 [ 8596.516112] ffff88007450f150 ffff88007450f138 ffffffff812dd58c ffff88007450f1d8 [ 8596.522856] ffffffff81113b80 0000000000000282 0000000000000001 ffffffff8101ee4d [ 8596.529599] Call Trace: [ 8596.530858] [] dump_stack+0x4f/0x7b [ 8596.535080] [] kasan_report_error+0x3bc/0x3f0 [ 8596.540258] [] ? __lock_acquire+0x90/0x2140 [ 8596.545245] [] ? save_stack_trace+0x2d/0x80 [ 8596.550234] [] kasan_report+0x40/0x50 [ 8596.554647] [] ? __vxlan_find_mac+0x24/0x100 [ 8596.559729] [] __asan_load8+0x69/0xa0 [ 8596.564141] [] __vxlan_find_mac+0x24/0x100 [ 8596.569033] [] vxlan_fdb_create+0x9d/0x570 it can be fixed by enlarging the all_zeros_mac to 8 byte, although it is harmless; eth_hash() will be called in other place with the memory which is larger and equal to 8 byte. Signed-off-by: Li RongQing Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index a85b1fcb3130..65439188c582 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -73,7 +73,7 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); static int vxlan_net_id; static struct rtnl_link_ops vxlan_link_ops; -static const u8 all_zeros_mac[ETH_ALEN]; +static const u8 all_zeros_mac[ETH_ALEN + 2]; static int vxlan_sock_add(struct vxlan_dev *vxlan); -- cgit v1.2.3 From 84092996673211f16ef3b942a191d7952e9dfea9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 29 Jan 2016 12:39:10 +0100 Subject: net: davinci_cpdma: use dma_addr_t for DMA address The davinci_cpdma mixes up physical addresses as seen from the CPU and DMA addresses as seen from a DMA master, since it can operate on both normal memory or an on-chip buffer. If dma_addr_t is different from phys_addr_t, this means we get a compile-time warning about the type mismatch: ethernet/ti/davinci_cpdma.c: In function 'cpdma_desc_pool_create': ethernet/ti/davinci_cpdma.c:182:48: error: passing argument 3 of 'dma_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys, In file included from ethernet/ti/davinci_cpdma.c:21:0: dma-mapping.h:398:21: note: expected 'dma_addr_t * {aka long long unsigned int *}' but argument is of type 'phys_addr_t * {aka unsigned int *}' static inline void *dma_alloc_coherent(struct device *dev, size_t size, This slightly restructures the code so the address we use for mapping RAM into a DMA address is always a dma_addr_t, avoiding the warning. The code is correct even if both types are 32-bit because the DMA master in this device only supports 32-bit addressing anyway, independent of the types that are used. We still assign this value to pool->phys, and that is wrong if the driver is ever used with an IOMMU, but that value appears to be never used, so there is no problem really. I've added a couple of comments about where we do things that are slightly violating the API. Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/davinci_cpdma.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c index 657b65bf5cac..18bf3a8fdc50 100644 --- a/drivers/net/ethernet/ti/davinci_cpdma.c +++ b/drivers/net/ethernet/ti/davinci_cpdma.c @@ -82,7 +82,7 @@ struct cpdma_desc { struct cpdma_desc_pool { phys_addr_t phys; - u32 hw_addr; + dma_addr_t hw_addr; void __iomem *iomap; /* ioremap map */ void *cpumap; /* dma_alloc map */ int desc_size, mem_size; @@ -152,7 +152,7 @@ struct cpdma_chan { * abstract out these details */ static struct cpdma_desc_pool * -cpdma_desc_pool_create(struct device *dev, u32 phys, u32 hw_addr, +cpdma_desc_pool_create(struct device *dev, u32 phys, dma_addr_t hw_addr, int size, int align) { int bitmap_size; @@ -176,13 +176,13 @@ cpdma_desc_pool_create(struct device *dev, u32 phys, u32 hw_addr, if (phys) { pool->phys = phys; - pool->iomap = ioremap(phys, size); + pool->iomap = ioremap(phys, size); /* should be memremap? */ pool->hw_addr = hw_addr; } else { - pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys, + pool->cpumap = dma_alloc_coherent(dev, size, &pool->hw_addr, GFP_KERNEL); - pool->iomap = pool->cpumap; - pool->hw_addr = pool->phys; + pool->iomap = (void __iomem __force *)pool->cpumap; + pool->phys = pool->hw_addr; /* assumes no IOMMU, don't use this value */ } if (pool->iomap) -- cgit v1.2.3 From 747a11279a442b913a57bf38934879babab3b58b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 29 Jan 2016 12:39:11 +0100 Subject: net: hp100: remove unnecessary #ifdefs Building the hp100 ethernet driver causes warnings when both the PCI and EISA drivers are disabled: ethernet/hp/hp100.c: In function 'hp100_module_init': ethernet/hp/hp100.c:3047:2: warning: label 'out3' defined but not used [-Wunused-label] ethernet/hp/hp100.c: At top level: ethernet/hp/hp100.c:2828:13: warning: 'cleanup_dev' defined but not used [-Wunused-function] We can easily avoid the warnings and make the driver look slightly nicer by removing the #ifdefs that check for the CONFIG_PCI and CONFIG_EISA, as all the registration functions are designed to have no effect when the buses are disabled. Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/ethernet/hp/hp100.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hp/hp100.c b/drivers/net/ethernet/hp/hp100.c index 1d5c3e16d8f4..3daf2d4a7ca0 100644 --- a/drivers/net/ethernet/hp/hp100.c +++ b/drivers/net/ethernet/hp/hp100.c @@ -194,7 +194,6 @@ static const char *hp100_isa_tbl[] = { }; #endif -#ifdef CONFIG_EISA static struct eisa_device_id hp100_eisa_tbl[] = { { "HWPF180" }, /* HP J2577 rev A */ { "HWP1920" }, /* HP 27248B */ @@ -205,9 +204,7 @@ static struct eisa_device_id hp100_eisa_tbl[] = { { "" } /* Mandatory final entry ! */ }; MODULE_DEVICE_TABLE(eisa, hp100_eisa_tbl); -#endif -#ifdef CONFIG_PCI static const struct pci_device_id hp100_pci_tbl[] = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A, PCI_ANY_ID, PCI_ANY_ID,}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B, PCI_ANY_ID, PCI_ANY_ID,}, @@ -219,7 +216,6 @@ static const struct pci_device_id hp100_pci_tbl[] = { {} /* Terminating entry */ }; MODULE_DEVICE_TABLE(pci, hp100_pci_tbl); -#endif static int hp100_rx_ratio = HP100_DEFAULT_RX_RATIO; static int hp100_priority_tx = HP100_DEFAULT_PRIORITY_TX; @@ -2842,7 +2838,6 @@ static void cleanup_dev(struct net_device *d) free_netdev(d); } -#ifdef CONFIG_EISA static int hp100_eisa_probe(struct device *gendev) { struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private)); @@ -2884,9 +2879,7 @@ static struct eisa_driver hp100_eisa_driver = { .remove = hp100_eisa_remove, } }; -#endif -#ifdef CONFIG_PCI static int hp100_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -2955,7 +2948,6 @@ static struct pci_driver hp100_pci_driver = { .probe = hp100_pci_probe, .remove = hp100_pci_remove, }; -#endif /* * module section @@ -3032,23 +3024,17 @@ static int __init hp100_module_init(void) err = hp100_isa_init(); if (err && err != -ENODEV) goto out; -#ifdef CONFIG_EISA err = eisa_driver_register(&hp100_eisa_driver); if (err && err != -ENODEV) goto out2; -#endif -#ifdef CONFIG_PCI err = pci_register_driver(&hp100_pci_driver); if (err && err != -ENODEV) goto out3; -#endif out: return err; out3: -#ifdef CONFIG_EISA eisa_driver_unregister (&hp100_eisa_driver); out2: -#endif hp100_isa_cleanup(); goto out; } @@ -3057,12 +3043,8 @@ static int __init hp100_module_init(void) static void __exit hp100_module_exit(void) { hp100_isa_cleanup(); -#ifdef CONFIG_EISA eisa_driver_unregister (&hp100_eisa_driver); -#endif -#ifdef CONFIG_PCI pci_unregister_driver (&hp100_pci_driver); -#endif } module_init(hp100_module_init) -- cgit v1.2.3 From 1f820f538f7396db7fd40684b9c3620816acc5a3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 29 Jan 2016 12:39:12 +0100 Subject: net: bgmac: clarify CONFIG_BCMA dependency The bgmac driver depends on BCMA_HOST_SOC, which is only used when CONFIG_BCMA is enabled. However, it is a bool option and can be set when CONFIG_BCMA=m, and then bgmac can be built-in, leading to an obvious link error: drivers/built-in.o: In function `bgmac_init': :(.init.text+0x7f2c): undefined reference to `__bcma_driver_register' drivers/built-in.o: In function `bgmac_exit': :(.exit.text+0x110a): undefined reference to `bcma_driver_unregister' To avoid this case, we need to depend on both BCMA and BCMA_SOC, as this patch does. I'm also trying to make the dependency more readable by splitting it into three lines, and adding a COMPILE_TEST alternative so we can test-build it in all configurations that support BCMA. The added dependency on FIXED_PHY addresses a related issue where we cannot call fixed_phy_register() when CONFIG_FIXED_PHY=m and CONFIG_BGMAC=y. Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index 8550df189ceb..19f7cd02e085 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig @@ -151,8 +151,11 @@ config BNX2X_VXLAN config BGMAC tristate "BCMA bus GBit core support" - depends on BCMA_HOST_SOC && HAS_DMA && (BCM47XX || ARCH_BCM_5301X) + depends on BCMA && BCMA_HOST_SOC + depends on HAS_DMA + depends on BCM47XX || ARCH_BCM_5301X || COMPILE_TEST select PHYLIB + select FIXED_PHY ---help--- This driver supports GBit MAC and BCM4706 GBit MAC cores on BCMA bus. They can be found on BCM47xx SoCs and provide gigabit ethernet. -- cgit v1.2.3 From 57e7c8cef224af166b8ec932b5e383641418c005 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 29 Jan 2016 12:39:13 +0100 Subject: net: vxge: avoid unused function warnings When CONFIG_PCI_MSI is disabled, we get warnings about unused functions in the vxge driver: drivers/net/ethernet/neterion/vxge/vxge-main.c:2121:13: warning: 'adaptive_coalesce_tx_interrupts' defined but not used [-Wunused-function] drivers/net/ethernet/neterion/vxge/vxge-main.c:2149:13: warning: 'adaptive_coalesce_rx_interrupts' defined but not used [-Wunused-function] We could add another #ifdef here, but it's nicer to avoid those warnings for good by converting the existing #ifdef to if(IS_ENABLED()), which has the same effect but provides better compile-time coverage in general, and lets the compiler understand better when the function is intentionally unused. Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/ethernet/neterion/vxge/vxge-main.c | 31 ++++++++++---------------- 1 file changed, 12 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c index 50d5604833ed..e0993eba5df3 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-main.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c @@ -2223,8 +2223,6 @@ static irqreturn_t vxge_isr_napi(int irq, void *dev_id) return IRQ_NONE; } -#ifdef CONFIG_PCI_MSI - static irqreturn_t vxge_tx_msix_handle(int irq, void *dev_id) { struct vxge_fifo *fifo = (struct vxge_fifo *)dev_id; @@ -2442,16 +2440,13 @@ static void vxge_rem_msix_isr(struct vxgedev *vdev) if (vdev->config.intr_type == MSI_X) pci_disable_msix(vdev->pdev); } -#endif static void vxge_rem_isr(struct vxgedev *vdev) { -#ifdef CONFIG_PCI_MSI - if (vdev->config.intr_type == MSI_X) { + if (IS_ENABLED(CONFIG_PCI_MSI) && + vdev->config.intr_type == MSI_X) { vxge_rem_msix_isr(vdev); - } else -#endif - if (vdev->config.intr_type == INTA) { + } else if (vdev->config.intr_type == INTA) { synchronize_irq(vdev->pdev->irq); free_irq(vdev->pdev->irq, vdev); } @@ -2460,11 +2455,10 @@ static void vxge_rem_isr(struct vxgedev *vdev) static int vxge_add_isr(struct vxgedev *vdev) { int ret = 0; -#ifdef CONFIG_PCI_MSI int vp_idx = 0, intr_idx = 0, intr_cnt = 0, msix_idx = 0, irq_req = 0; int pci_fun = PCI_FUNC(vdev->pdev->devfn); - if (vdev->config.intr_type == MSI_X) + if (IS_ENABLED(CONFIG_PCI_MSI) && vdev->config.intr_type == MSI_X) ret = vxge_enable_msix(vdev); if (ret) { @@ -2475,7 +2469,7 @@ static int vxge_add_isr(struct vxgedev *vdev) vdev->config.intr_type = INTA; } - if (vdev->config.intr_type == MSI_X) { + if (IS_ENABLED(CONFIG_PCI_MSI) && vdev->config.intr_type == MSI_X) { for (intr_idx = 0; intr_idx < (vdev->no_of_vpath * VXGE_HW_VPATH_MSIX_ACTIVE); intr_idx++) { @@ -2576,9 +2570,8 @@ static int vxge_add_isr(struct vxgedev *vdev) vdev->vxge_entries[intr_cnt].in_use = 1; vdev->vxge_entries[intr_cnt].arg = &vdev->vpaths[0]; } -INTA_MODE: -#endif +INTA_MODE: if (vdev->config.intr_type == INTA) { snprintf(vdev->desc[0], VXGE_INTR_STRLEN, "%s:vxge:INTA", vdev->ndev->name); @@ -3889,12 +3882,12 @@ static void vxge_device_config_init(struct vxge_hw_device_config *device_config, if (max_mac_vpath > VXGE_MAX_MAC_ADDR_COUNT) max_mac_vpath = VXGE_MAX_MAC_ADDR_COUNT; -#ifndef CONFIG_PCI_MSI - vxge_debug_init(VXGE_ERR, - "%s: This Kernel does not support " - "MSI-X. Defaulting to INTA", VXGE_DRIVER_NAME); - *intr_type = INTA; -#endif + if (!IS_ENABLED(CONFIG_PCI_MSI)) { + vxge_debug_init(VXGE_ERR, + "%s: This Kernel does not support " + "MSI-X. Defaulting to INTA", VXGE_DRIVER_NAME); + *intr_type = INTA; + } /* Configure whether MSI-X or IRQL. */ switch (*intr_type) { -- cgit v1.2.3 From 8bdb290896d2ff22942c9c9f5bf19909329f3664 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 29 Jan 2016 12:39:14 +0100 Subject: net: nb8800: avoid uninitialized variable warning The nb8800_poll() function initializes the 'next' variable in the loop looking for new input data. We know this will be called at least once because 'budget' is a guaranteed to be a positive number when we enter the function, but the compiler doesn't know that and warns when the variable is used later: drivers/net/ethernet/aurora/nb8800.c: In function 'nb8800_poll': drivers/net/ethernet/aurora/nb8800.c:350:21: warning: 'next' may be used uninitialized in this function [-Wmaybe-uninitialized] Changing the 'while() {}' loop to 'do {} while()' makes it obvious to the compiler what is going on so it no longer warns. Signed-off-by: Arnd Bergmann Acked-by: Mans Rullgard Signed-off-by: David S. Miller --- drivers/net/ethernet/aurora/nb8800.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/aurora/nb8800.c b/drivers/net/ethernet/aurora/nb8800.c index ecc4a334c507..f71ab2647a3b 100644 --- a/drivers/net/ethernet/aurora/nb8800.c +++ b/drivers/net/ethernet/aurora/nb8800.c @@ -302,7 +302,7 @@ static int nb8800_poll(struct napi_struct *napi, int budget) nb8800_tx_done(dev); again: - while (work < budget) { + do { struct nb8800_rx_buf *rxb; unsigned int len; @@ -330,7 +330,7 @@ again: rxd->report = 0; last = next; work++; - } + } while (work < budget); if (work) { priv->rx_descs[last].desc.config |= DESC_EOC; -- cgit v1.2.3 From e434e04110704eb91acfecbd0fb8ca8e2da9c29b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 29 Jan 2016 12:39:15 +0100 Subject: net: tg3: avoid uninitialized variable warning The tg3_set_eeprom() function correctly initializes the 'start' variable, but gcc generates a false warning: drivers/net/ethernet/broadcom/tg3.c: In function 'tg3_set_eeprom': drivers/net/ethernet/broadcom/tg3.c:12057:4: warning: 'start' may be used uninitialized in this function [-Wmaybe-uninitialized] I have not come up with a way to restructure the code in a way that avoids the warning without making it less readable, so this adds an initialization for the declaration to shut up that warning. Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 9293675df7ba..49eea8981332 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -12016,7 +12016,7 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, int ret; u32 offset, len, b_offset, odd_len; u8 *buf; - __be32 start, end; + __be32 start = 0, end; if (tg3_flag(tp, NO_NVRAM) || eeprom->magic != TG3_EEPROM_MAGIC) -- cgit v1.2.3 From 782b86641e5d471e9eb1cf0072c012d2f758e568 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:24 +0100 Subject: xen, mm: Set IORESOURCE_SYSTEM_RAM to System RAM Set IORESOURCE_SYSTEM_RAM in struct resource.flags of "System RAM" entries. Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Acked-by: David Vrabel # xen Cc: Andrew Banman Cc: Andrew Morton Cc: Andy Lutomirski Cc: Boris Ostrovsky Cc: Borislav Petkov Cc: Brian Gerst Cc: Dan Williams Cc: David Rientjes Cc: Denys Vlasenko Cc: Gu Zheng Cc: H. Peter Anvin Cc: Konrad Rzeszutek Wilk Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Mel Gorman Cc: Naoya Horiguchi Cc: Peter Zijlstra Cc: Tang Chen Cc: Thomas Gleixner Cc: Toshi Kani Cc: linux-arch@vger.kernel.org Cc: linux-mm Cc: xen-devel@lists.xenproject.org Link: http://lkml.kernel.org/r/1453841853-11383-9-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- drivers/xen/balloon.c | 2 +- mm/memory_hotplug.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 12eab503efd1..dc4305b407bf 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -257,7 +257,7 @@ static struct resource *additional_memory_resource(phys_addr_t size) return NULL; res->name = "System RAM"; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; ret = allocate_resource(&iomem_resource, res, size, 0, -1, diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 4af58a3a8ffa..979b18cbd343 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -138,7 +138,7 @@ static struct resource *register_memory_resource(u64 start, u64 size) res->name = "System RAM"; res->start = start; res->end = start + size - 1; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; if (request_resource(&iomem_resource, res) < 0) { pr_debug("System RAM resource %pR cannot be added\n", res); kfree(res); -- cgit v1.2.3 From 9a975bee4b3945b271bcff18a520d4863c210f8b Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:25 +0100 Subject: drivers: Initialize resource entry to zero I/O resource descriptor, 'desc' in struct resource, needs to be initialized to zero by default. Some drivers call kmalloc() to allocate a resource entry, but do not initialize it to zero by memset(). Change these drivers to call kzalloc(), instead. Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Acked-by: Alexandre Bounine Acked-by: Helge Deller Acked-by: Rafael J. Wysocki Acked-by: Simon Horman Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Toshi Kani Cc: linux-acpi@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-mm Cc: linux-parisc@vger.kernel.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-sh@vger.kernel.org Link: http://lkml.kernel.org/r/1453841853-11383-10-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- drivers/acpi/acpi_platform.c | 2 +- drivers/parisc/eisa_enumerator.c | 4 ++-- drivers/rapidio/rio.c | 8 ++++---- drivers/sh/superhyway/superhyway.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 296b7a14893a..b6f7fa3a1d40 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -62,7 +62,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev) if (count < 0) { return NULL; } else if (count > 0) { - resources = kmalloc(count * sizeof(struct resource), + resources = kzalloc(count * sizeof(struct resource), GFP_KERNEL); if (!resources) { dev_err(&adev->dev, "No memory for resources\n"); diff --git a/drivers/parisc/eisa_enumerator.c b/drivers/parisc/eisa_enumerator.c index a656d9e83343..21905fef2cbf 100644 --- a/drivers/parisc/eisa_enumerator.c +++ b/drivers/parisc/eisa_enumerator.c @@ -91,7 +91,7 @@ static int configure_memory(const unsigned char *buf, for (i=0;iname = name; @@ -183,7 +183,7 @@ static int configure_port(const unsigned char *buf, struct resource *io_parent, for (i=0;iname = board; res->start = get_16(buf+len+1); res->end = get_16(buf+len+1)+(c&HPEE_PORT_SIZE_MASK)+1; diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index d7b87c64b7cd..e220edc85c68 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -117,7 +117,7 @@ int rio_request_inb_mbox(struct rio_mport *mport, if (mport->ops->open_inb_mbox == NULL) goto out; - res = kmalloc(sizeof(struct resource), GFP_KERNEL); + res = kzalloc(sizeof(struct resource), GFP_KERNEL); if (res) { rio_init_mbox_res(res, mbox, mbox); @@ -185,7 +185,7 @@ int rio_request_outb_mbox(struct rio_mport *mport, if (mport->ops->open_outb_mbox == NULL) goto out; - res = kmalloc(sizeof(struct resource), GFP_KERNEL); + res = kzalloc(sizeof(struct resource), GFP_KERNEL); if (res) { rio_init_mbox_res(res, mbox, mbox); @@ -285,7 +285,7 @@ int rio_request_inb_dbell(struct rio_mport *mport, { int rc = 0; - struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); + struct resource *res = kzalloc(sizeof(struct resource), GFP_KERNEL); if (res) { rio_init_dbell_res(res, start, end); @@ -360,7 +360,7 @@ int rio_release_inb_dbell(struct rio_mport *mport, u16 start, u16 end) struct resource *rio_request_outb_dbell(struct rio_dev *rdev, u16 start, u16 end) { - struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); + struct resource *res = kzalloc(sizeof(struct resource), GFP_KERNEL); if (res) { rio_init_dbell_res(res, start, end); diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c index 2d9e7f3d5611..bb1fb7712134 100644 --- a/drivers/sh/superhyway/superhyway.c +++ b/drivers/sh/superhyway/superhyway.c @@ -66,7 +66,7 @@ int superhyway_add_device(unsigned long base, struct superhyway_device *sdev, superhyway_read_vcr(dev, base, &dev->vcr); if (!dev->resource) { - dev->resource = kmalloc(sizeof(struct resource), GFP_KERNEL); + dev->resource = kzalloc(sizeof(struct resource), GFP_KERNEL); if (!dev->resource) { kfree(dev); return -ENOMEM; -- cgit v1.2.3 From f0f4711aa16b82016c0b6e59871934bbd71258da Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:30 +0100 Subject: x86, kexec, nvdimm: Use walk_iomem_res_desc() for iomem search Change the callers of walk_iomem_res() scanning for the following resources by name to use walk_iomem_res_desc() instead. "ACPI Tables" "ACPI Non-volatile Storage" "Persistent Memory (legacy)" "Crash kernel" Note, the caller of walk_iomem_res() with "GART" will be removed in a later patch. Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Reviewed-by: Dave Young Cc: Andrew Morton Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Chun-Yi Cc: Dan Williams Cc: Denys Vlasenko Cc: Don Zickus Cc: H. Peter Anvin Cc: Lee, Chun-Yi Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Minfei Huang Cc: Peter Zijlstra (Intel) Cc: Ross Zwisler Cc: Stephen Rothwell Cc: Takao Indoh Cc: Thomas Gleixner Cc: Toshi Kani Cc: kexec@lists.infradead.org Cc: linux-arch@vger.kernel.org Cc: linux-mm Cc: linux-nvdimm@lists.01.org Link: http://lkml.kernel.org/r/1453841853-11383-15-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/crash.c | 4 ++-- arch/x86/kernel/pmem.c | 4 ++-- drivers/nvdimm/e820.c | 2 +- kernel/kexec_file.c | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 58f34319b29a..35e152eeb6e0 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -599,12 +599,12 @@ int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params) /* Add ACPI tables */ cmd.type = E820_ACPI; flags = IORESOURCE_MEM | IORESOURCE_BUSY; - walk_iomem_res("ACPI Tables", flags, 0, -1, &cmd, + walk_iomem_res_desc(IORES_DESC_ACPI_TABLES, flags, 0, -1, &cmd, memmap_entry_callback); /* Add ACPI Non-volatile Storage */ cmd.type = E820_NVS; - walk_iomem_res("ACPI Non-volatile Storage", flags, 0, -1, &cmd, + walk_iomem_res_desc(IORES_DESC_ACPI_NV_STORAGE, flags, 0, -1, &cmd, memmap_entry_callback); /* Add crashk_low_res region */ diff --git a/arch/x86/kernel/pmem.c b/arch/x86/kernel/pmem.c index 14415aff1813..92f70147a9a6 100644 --- a/arch/x86/kernel/pmem.c +++ b/arch/x86/kernel/pmem.c @@ -13,11 +13,11 @@ static int found(u64 start, u64 end, void *data) static __init int register_e820_pmem(void) { - char *pmem = "Persistent Memory (legacy)"; struct platform_device *pdev; int rc; - rc = walk_iomem_res(pmem, IORESOURCE_MEM, 0, -1, NULL, found); + rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY, + IORESOURCE_MEM, 0, -1, NULL, found); if (rc <= 0) return 0; diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c index b0045a505dc8..95825b38559a 100644 --- a/drivers/nvdimm/e820.c +++ b/drivers/nvdimm/e820.c @@ -55,7 +55,7 @@ static int e820_pmem_probe(struct platform_device *pdev) for (p = iomem_resource.child; p ; p = p->sibling) { struct nd_region_desc ndr_desc; - if (strncmp(p->name, "Persistent Memory (legacy)", 26) != 0) + if (p->desc != IORES_DESC_PERSISTENT_MEMORY_LEGACY) continue; memset(&ndr_desc, 0, sizeof(ndr_desc)); diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 2bfcdc064116..56b18eb1f001 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -524,10 +524,10 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz, /* Walk the RAM ranges and allocate a suitable range for the buffer */ if (image->type == KEXEC_TYPE_CRASH) - ret = walk_iomem_res("Crash kernel", - IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY, - crashk_res.start, crashk_res.end, kbuf, - locate_mem_hole_callback); + ret = walk_iomem_res_desc(crashk_res.desc, + IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY, + crashk_res.start, crashk_res.end, kbuf, + locate_mem_hole_callback); else ret = walk_system_ram_res(0, -1, kbuf, locate_mem_hole_callback); -- cgit v1.2.3 From 4650bac1fc45d64aef62ab99aa4db93d41dedbd9 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:33 +0100 Subject: ACPI/EINJ: Allow memory error injection to NVDIMM In the case of memory error injection, einj_error_inject() checks if a target address is System RAM. Change this check to allow injecting a memory error into NVDIMM memory by calling region_intersects() with IORES_DESC_PERSISTENT_MEMORY. This enables memory error testing on both System RAM and NVDIMM. In addition, page_is_ram() is replaced with region_intersects() with IORESOURCE_SYSTEM_RAM, so that it can verify a target address range with the requested size. Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Reviewed-by: Dan Williams Acked-by: Tony Luck Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Jarkko Nikula Cc: Len Brown Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Rafael J. Wysocki Cc: Thomas Gleixner Cc: Toshi Kani Cc: Vishal Verma Cc: linux-acpi@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-mm Cc: linux-nvdimm@lists.01.org Link: http://lkml.kernel.org/r/1453841853-11383-18-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- drivers/acpi/apei/einj.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index 0431883653be..559c1173de1c 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c @@ -519,7 +519,7 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, u64 param3, u64 param4) { int rc; - unsigned long pfn; + u64 base_addr, size; /* If user manually set "flags", make sure it is legal */ if (flags && (flags & @@ -545,10 +545,17 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, /* * Disallow crazy address masks that give BIOS leeway to pick * injection address almost anywhere. Insist on page or - * better granularity and that target address is normal RAM. + * better granularity and that target address is normal RAM or + * NVDIMM. */ - pfn = PFN_DOWN(param1 & param2); - if (!page_is_ram(pfn) || ((param2 & PAGE_MASK) != PAGE_MASK)) + base_addr = param1 & param2; + size = ~param2 + 1; + + if (((param2 & PAGE_MASK) != PAGE_MASK) || + ((region_intersects(base_addr, size, IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE) + != REGION_INTERSECTS) && + (region_intersects(base_addr, size, IORESOURCE_MEM, IORES_DESC_PERSISTENT_MEMORY) + != REGION_INTERSECTS))) return -EINVAL; inject: -- cgit v1.2.3 From bc696ca05f5a8927329ec276a892341e006b00ba Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 26 Jan 2016 22:12:05 +0100 Subject: x86/cpufeature: Replace the old static_cpu_has() with safe variant So the old one didn't work properly before alternatives had run. And it was supposed to provide an optimized JMP because the assumption was that the offset it is jumping to is within a signed byte and thus a two-byte JMP. So I did an x86_64 allyesconfig build and dumped all possible sites where static_cpu_has() was used. The optimization amounted to all in all 12(!) places where static_cpu_has() had generated a 2-byte JMP. Which has saved us a whopping 36 bytes! This clearly is not worth the trouble so we can remove it. The only place where the optimization might count - in __switch_to() - we will handle differently. But that's not subject of this patch. Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1453842730-28463-6-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/Kconfig.debug | 10 ---- arch/x86/include/asm/cpufeature.h | 100 +++-------------------------------- arch/x86/include/asm/fpu/internal.h | 14 ++--- arch/x86/kernel/apic/apic_numachip.c | 4 +- arch/x86/kernel/cpu/common.c | 12 +---- arch/x86/kernel/vm86_32.c | 2 +- drivers/cpufreq/intel_pstate.c | 2 +- fs/btrfs/disk-io.c | 2 +- 8 files changed, 21 insertions(+), 125 deletions(-) (limited to 'drivers') diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 9b18ed97a8a2..68a2d1f0a683 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -350,16 +350,6 @@ config DEBUG_IMR_SELFTEST If unsure say N here. -config X86_DEBUG_STATIC_CPU_HAS - bool "Debug alternatives" - depends on DEBUG_KERNEL - ---help--- - This option causes additional code to be generated which - fails if static_cpu_has() is used before alternatives have - run. - - If unsure, say N. - config X86_DEBUG_FPU bool "Debug the x86 FPU code" depends on DEBUG_KERNEL diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 3cce9f3c5cb1..a261cf2e7907 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -125,103 +125,19 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define cpu_has_osxsave boot_cpu_has(X86_FEATURE_OSXSAVE) #define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR) /* - * Do not add any more of those clumsy macros - use static_cpu_has_safe() for + * Do not add any more of those clumsy macros - use static_cpu_has() for * fast paths and boot_cpu_has() otherwise! */ #if __GNUC__ >= 4 && defined(CONFIG_X86_FAST_FEATURE_TESTS) -extern void warn_pre_alternatives(void); -extern bool __static_cpu_has_safe(u16 bit); +extern bool __static_cpu_has(u16 bit); /* * Static testing of CPU features. Used the same as boot_cpu_has(). * These are only valid after alternatives have run, but will statically * patch the target code for additional performance. */ -static __always_inline __pure bool __static_cpu_has(u16 bit) -{ -#ifdef CC_HAVE_ASM_GOTO - -#ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS - - /* - * Catch too early usage of this before alternatives - * have run. - */ - asm_volatile_goto("1: jmp %l[t_warn]\n" - "2:\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" - " .long 0\n" /* no replacement */ - " .word %P0\n" /* 1: do replace */ - " .byte 2b - 1b\n" /* source len */ - " .byte 0\n" /* replacement len */ - " .byte 0\n" /* pad len */ - ".previous\n" - /* skipping size check since replacement size = 0 */ - : : "i" (X86_FEATURE_ALWAYS) : : t_warn); - -#endif - - asm_volatile_goto("1: jmp %l[t_no]\n" - "2:\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" - " .long 0\n" /* no replacement */ - " .word %P0\n" /* feature bit */ - " .byte 2b - 1b\n" /* source len */ - " .byte 0\n" /* replacement len */ - " .byte 0\n" /* pad len */ - ".previous\n" - /* skipping size check since replacement size = 0 */ - : : "i" (bit) : : t_no); - return true; - t_no: - return false; - -#ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS - t_warn: - warn_pre_alternatives(); - return false; -#endif - -#else /* CC_HAVE_ASM_GOTO */ - - u8 flag; - /* Open-coded due to __stringify() in ALTERNATIVE() */ - asm volatile("1: movb $0,%0\n" - "2:\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" - " .long 3f - .\n" - " .word %P1\n" /* feature bit */ - " .byte 2b - 1b\n" /* source len */ - " .byte 4f - 3f\n" /* replacement len */ - " .byte 0\n" /* pad len */ - ".previous\n" - ".section .discard,\"aw\",@progbits\n" - " .byte 0xff + (4f-3f) - (2b-1b)\n" /* size check */ - ".previous\n" - ".section .altinstr_replacement,\"ax\"\n" - "3: movb $1,%0\n" - "4:\n" - ".previous\n" - : "=qm" (flag) : "i" (bit)); - return flag; - -#endif /* CC_HAVE_ASM_GOTO */ -} - -#define static_cpu_has(bit) \ -( \ - __builtin_constant_p(boot_cpu_has(bit)) ? \ - boot_cpu_has(bit) : \ - __builtin_constant_p(bit) ? \ - __static_cpu_has(bit) : \ - boot_cpu_has(bit) \ -) - -static __always_inline __pure bool _static_cpu_has_safe(u16 bit) +static __always_inline __pure bool _static_cpu_has(u16 bit) { #ifdef CC_HAVE_ASM_GOTO asm_volatile_goto("1: jmp %l[t_dynamic]\n" @@ -255,7 +171,7 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) t_no: return false; t_dynamic: - return __static_cpu_has_safe(bit); + return __static_cpu_has(bit); #else u8 flag; /* Open-coded due to __stringify() in ALTERNATIVE() */ @@ -293,22 +209,21 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) ".previous\n" : "=qm" (flag) : "i" (bit), "i" (X86_FEATURE_ALWAYS)); - return (flag == 2 ? __static_cpu_has_safe(bit) : flag); + return (flag == 2 ? __static_cpu_has(bit) : flag); #endif /* CC_HAVE_ASM_GOTO */ } -#define static_cpu_has_safe(bit) \ +#define static_cpu_has(bit) \ ( \ __builtin_constant_p(boot_cpu_has(bit)) ? \ boot_cpu_has(bit) : \ - _static_cpu_has_safe(bit) \ + _static_cpu_has(bit) \ ) #else /* * gcc 3.x is too stupid to do the static test; fall back to dynamic. */ #define static_cpu_has(bit) boot_cpu_has(bit) -#define static_cpu_has_safe(bit) boot_cpu_has(bit) #endif #define cpu_has_bug(c, bit) cpu_has(c, (bit)) @@ -316,7 +231,6 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) #define clear_cpu_bug(c, bit) clear_cpu_cap(c, (bit)) #define static_cpu_has_bug(bit) static_cpu_has((bit)) -#define static_cpu_has_bug_safe(bit) static_cpu_has_safe((bit)) #define boot_cpu_has_bug(bit) cpu_has_bug(&boot_cpu_data, (bit)) #define MAX_CPU_FEATURES (NCAPINTS * 32) diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h index d01199def781..c2e46eb96b6d 100644 --- a/arch/x86/include/asm/fpu/internal.h +++ b/arch/x86/include/asm/fpu/internal.h @@ -59,22 +59,22 @@ extern u64 fpu__get_supported_xfeatures_mask(void); */ static __always_inline __pure bool use_eager_fpu(void) { - return static_cpu_has_safe(X86_FEATURE_EAGER_FPU); + return static_cpu_has(X86_FEATURE_EAGER_FPU); } static __always_inline __pure bool use_xsaveopt(void) { - return static_cpu_has_safe(X86_FEATURE_XSAVEOPT); + return static_cpu_has(X86_FEATURE_XSAVEOPT); } static __always_inline __pure bool use_xsave(void) { - return static_cpu_has_safe(X86_FEATURE_XSAVE); + return static_cpu_has(X86_FEATURE_XSAVE); } static __always_inline __pure bool use_fxsr(void) { - return static_cpu_has_safe(X86_FEATURE_FXSR); + return static_cpu_has(X86_FEATURE_FXSR); } /* @@ -301,7 +301,7 @@ static inline void copy_xregs_to_kernel_booting(struct xregs_state *xstate) WARN_ON(system_state != SYSTEM_BOOTING); - if (static_cpu_has_safe(X86_FEATURE_XSAVES)) + if (static_cpu_has(X86_FEATURE_XSAVES)) XSTATE_OP(XSAVES, xstate, lmask, hmask, err); else XSTATE_OP(XSAVE, xstate, lmask, hmask, err); @@ -323,7 +323,7 @@ static inline void copy_kernel_to_xregs_booting(struct xregs_state *xstate) WARN_ON(system_state != SYSTEM_BOOTING); - if (static_cpu_has_safe(X86_FEATURE_XSAVES)) + if (static_cpu_has(X86_FEATURE_XSAVES)) XSTATE_OP(XRSTORS, xstate, lmask, hmask, err); else XSTATE_OP(XRSTOR, xstate, lmask, hmask, err); @@ -461,7 +461,7 @@ static inline void copy_kernel_to_fpregs(union fpregs_state *fpstate) * pending. Clear the x87 state here by setting it to fixed values. * "m" is a random variable that should be in L1. */ - if (unlikely(static_cpu_has_bug_safe(X86_BUG_FXSAVE_LEAK))) { + if (unlikely(static_cpu_has_bug(X86_BUG_FXSAVE_LEAK))) { asm volatile( "fnclex\n\t" "emms\n\t" diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index c80c02c6ec49..ab5c2c685a3c 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -30,7 +30,7 @@ static unsigned int numachip1_get_apic_id(unsigned long x) unsigned long value; unsigned int id = (x >> 24) & 0xff; - if (static_cpu_has_safe(X86_FEATURE_NODEID_MSR)) { + if (static_cpu_has(X86_FEATURE_NODEID_MSR)) { rdmsrl(MSR_FAM10H_NODE_ID, value); id |= (value << 2) & 0xff00; } @@ -178,7 +178,7 @@ static void fixup_cpu_id(struct cpuinfo_x86 *c, int node) this_cpu_write(cpu_llc_id, node); /* Account for nodes per socket in multi-core-module processors */ - if (static_cpu_has_safe(X86_FEATURE_NODEID_MSR)) { + if (static_cpu_has(X86_FEATURE_NODEID_MSR)) { rdmsrl(MSR_FAM10H_NODE_ID, val); nodes = ((val >> 3) & 7) + 1; } diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 37830de8f60a..ee499817f3f5 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1475,19 +1475,11 @@ void cpu_init(void) } #endif -#ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS -void warn_pre_alternatives(void) -{ - WARN(1, "You're using static_cpu_has before alternatives have run!\n"); -} -EXPORT_SYMBOL_GPL(warn_pre_alternatives); -#endif - -inline bool __static_cpu_has_safe(u16 bit) +inline bool __static_cpu_has(u16 bit) { return boot_cpu_has(bit); } -EXPORT_SYMBOL_GPL(__static_cpu_has_safe); +EXPORT_SYMBOL_GPL(__static_cpu_has); static void bsp_resume(void) { diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index e574b8546518..3dce1ca0a653 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -362,7 +362,7 @@ static long do_sys_vm86(struct vm86plus_struct __user *user_vm86, bool plus) /* make room for real-mode segments */ tsk->thread.sp0 += 16; - if (static_cpu_has_safe(X86_FEATURE_SEP)) + if (static_cpu_has(X86_FEATURE_SEP)) tsk->thread.sysenter_cs = 0; load_sp0(tss, &tsk->thread); diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index cd83d477e32d..3a4b39afc0ab 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -1431,7 +1431,7 @@ static int __init intel_pstate_init(void) if (!all_cpu_data) return -ENOMEM; - if (static_cpu_has_safe(X86_FEATURE_HWP) && !no_hwp) { + if (static_cpu_has(X86_FEATURE_HWP) && !no_hwp) { pr_info("intel_pstate: HWP enabled\n"); hwp_active++; } diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index dd08e29f5117..d9286497924f 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -930,7 +930,7 @@ static int check_async_write(struct inode *inode, unsigned long bio_flags) if (bio_flags & EXTENT_BIO_TREE_LOG) return 0; #ifdef CONFIG_X86 - if (static_cpu_has_safe(X86_FEATURE_XMM4_2)) + if (static_cpu_has(X86_FEATURE_XMM4_2)) return 0; #endif return 1; -- cgit v1.2.3 From 49a20454e0eb907093ec564d4e8f3832bcbf9d53 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Fri, 29 Jan 2016 17:53:33 +0100 Subject: crypto: atmel-aes - remove calls of clk_prepare() from atomic contexts clk_prepare()/clk_unprepare() must not be called within atomic context. This patch calls clk_prepare() once for all from atmel_aes_probe() and clk_unprepare() from atmel_aes_remove(). Then calls of clk_prepare_enable()/clk_disable_unprepare() were replaced by calls of clk_enable()/clk_disable(). Cc: stable@vger.kernel.org Signed-off-by: Cyrille Pitchen Reported-by: Matthias Mayr Signed-off-by: Herbert Xu --- drivers/crypto/atmel-aes.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index 6dd3317ca365..3eb3f1279fb7 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -400,7 +400,7 @@ static int atmel_aes_hw_init(struct atmel_aes_dev *dd) { int err; - err = clk_prepare_enable(dd->iclk); + err = clk_enable(dd->iclk); if (err) return err; @@ -430,7 +430,7 @@ static int atmel_aes_hw_version_init(struct atmel_aes_dev *dd) dev_info(dd->dev, "version: 0x%x\n", dd->hw_version); - clk_disable_unprepare(dd->iclk); + clk_disable(dd->iclk); return 0; } @@ -448,7 +448,7 @@ static inline bool atmel_aes_is_encrypt(const struct atmel_aes_dev *dd) static inline int atmel_aes_complete(struct atmel_aes_dev *dd, int err) { - clk_disable_unprepare(dd->iclk); + clk_disable(dd->iclk); dd->flags &= ~AES_FLAGS_BUSY; if (dd->is_async) @@ -2091,10 +2091,14 @@ static int atmel_aes_probe(struct platform_device *pdev) goto res_err; } - err = atmel_aes_hw_version_init(aes_dd); + err = clk_prepare(aes_dd->iclk); if (err) goto res_err; + err = atmel_aes_hw_version_init(aes_dd); + if (err) + goto iclk_unprepare; + atmel_aes_get_cap(aes_dd); err = atmel_aes_buff_init(aes_dd); @@ -2127,6 +2131,8 @@ err_algs: err_aes_dma: atmel_aes_buff_cleanup(aes_dd); err_aes_buff: +iclk_unprepare: + clk_unprepare(aes_dd->iclk); res_err: tasklet_kill(&aes_dd->done_task); tasklet_kill(&aes_dd->queue_task); @@ -2155,6 +2161,8 @@ static int atmel_aes_remove(struct platform_device *pdev) atmel_aes_dma_cleanup(aes_dd); atmel_aes_buff_cleanup(aes_dd); + clk_unprepare(aes_dd->iclk); + return 0; } -- cgit v1.2.3 From cc831d32d7b1bd45c5d74c44d8e39d354049c369 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Fri, 29 Jan 2016 17:04:02 +0100 Subject: crypto: atmel-sha - fix algorihtm registration This patch implements the missing .import() and .export() mandatory hooks for asynchronous hash algorithms. It also sets the relevant, non zero, value for the .statesize field when declaring the supported SHA algorithms. Indeed a zero value of .statesize prevents the algorithm from being registered. Signed-off-by: Cyrille Pitchen Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha.c | 61 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index da4c3055784f..63b09e01075c 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -66,7 +66,7 @@ #define SHA_OP_UPDATE 1 #define SHA_OP_FINAL 2 -#define SHA_BUFFER_LEN PAGE_SIZE +#define SHA_BUFFER_LEN (PAGE_SIZE / 16) #define ATMEL_SHA_DMA_THRESHOLD 56 @@ -80,6 +80,17 @@ struct atmel_sha_caps { struct atmel_sha_dev; +/* + * .statesize = sizeof(struct atmel_sha_state) must be <= PAGE_SIZE / 8 as + * tested by the ahash_prepare_alg() function. + */ +struct atmel_sha_state { + u8 digest[SHA512_DIGEST_SIZE]; + u8 buffer[SHA_BUFFER_LEN]; + u64 digcnt[2]; + size_t bufcnt; +}; + struct atmel_sha_reqctx { struct atmel_sha_dev *dd; unsigned long flags; @@ -1033,6 +1044,39 @@ static int atmel_sha_digest(struct ahash_request *req) return atmel_sha_init(req) ?: atmel_sha_finup(req); } + +static int atmel_sha_export(struct ahash_request *req, void *out) +{ + const struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); + struct atmel_sha_state state; + + memcpy(state.digest, ctx->digest, SHA512_DIGEST_SIZE); + memcpy(state.buffer, ctx->buffer, ctx->bufcnt); + state.bufcnt = ctx->bufcnt; + state.digcnt[0] = ctx->digcnt[0]; + state.digcnt[1] = ctx->digcnt[1]; + + /* out might be unaligned. */ + memcpy(out, &state, sizeof(state)); + return 0; +} + +static int atmel_sha_import(struct ahash_request *req, const void *in) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); + struct atmel_sha_state state; + + /* in might be unaligned. */ + memcpy(&state, in, sizeof(state)); + + memcpy(ctx->digest, state.digest, SHA512_DIGEST_SIZE); + memcpy(ctx->buffer, state.buffer, state.bufcnt); + ctx->bufcnt = state.bufcnt; + ctx->digcnt[0] = state.digcnt[0]; + ctx->digcnt[1] = state.digcnt[1]; + return 0; +} + static int atmel_sha_cra_init(struct crypto_tfm *tfm) { crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), @@ -1049,8 +1093,11 @@ static struct ahash_alg sha_1_256_algs[] = { .final = atmel_sha_final, .finup = atmel_sha_finup, .digest = atmel_sha_digest, + .export = atmel_sha_export, + .import = atmel_sha_import, .halg = { .digestsize = SHA1_DIGEST_SIZE, + .statesize = sizeof(struct atmel_sha_state), .base = { .cra_name = "sha1", .cra_driver_name = "atmel-sha1", @@ -1070,8 +1117,11 @@ static struct ahash_alg sha_1_256_algs[] = { .final = atmel_sha_final, .finup = atmel_sha_finup, .digest = atmel_sha_digest, + .export = atmel_sha_export, + .import = atmel_sha_import, .halg = { .digestsize = SHA256_DIGEST_SIZE, + .statesize = sizeof(struct atmel_sha_state), .base = { .cra_name = "sha256", .cra_driver_name = "atmel-sha256", @@ -1093,8 +1143,11 @@ static struct ahash_alg sha_224_alg = { .final = atmel_sha_final, .finup = atmel_sha_finup, .digest = atmel_sha_digest, + .export = atmel_sha_export, + .import = atmel_sha_import, .halg = { .digestsize = SHA224_DIGEST_SIZE, + .statesize = sizeof(struct atmel_sha_state), .base = { .cra_name = "sha224", .cra_driver_name = "atmel-sha224", @@ -1116,8 +1169,11 @@ static struct ahash_alg sha_384_512_algs[] = { .final = atmel_sha_final, .finup = atmel_sha_finup, .digest = atmel_sha_digest, + .export = atmel_sha_export, + .import = atmel_sha_import, .halg = { .digestsize = SHA384_DIGEST_SIZE, + .statesize = sizeof(struct atmel_sha_state), .base = { .cra_name = "sha384", .cra_driver_name = "atmel-sha384", @@ -1137,8 +1193,11 @@ static struct ahash_alg sha_384_512_algs[] = { .final = atmel_sha_final, .finup = atmel_sha_finup, .digest = atmel_sha_digest, + .export = atmel_sha_export, + .import = atmel_sha_import, .halg = { .digestsize = SHA512_DIGEST_SIZE, + .statesize = sizeof(struct atmel_sha_state), .base = { .cra_name = "sha512", .cra_driver_name = "atmel-sha512", -- cgit v1.2.3 From d81dac3c1c5295c61b15293074ac2bd3254e1875 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 26 Jan 2016 12:25:21 +0300 Subject: iio: inkern: fix a NULL dereference on error In twl4030_bci_probe() there are some failure paths where we call iio_channel_release() with a NULL pointer. (Apparently, that driver can opperate without a valid channel pointer). Let's fix it by adding a NULL check in iio_channel_release(). Fixes: 2202e1fc5a29 ('drivers: power: twl4030_charger: fix link problems when building as module') Signed-off-by: Dan Carpenter Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/inkern.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index c8bad3cf891d..217e9306aa0f 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -351,6 +351,8 @@ EXPORT_SYMBOL_GPL(iio_channel_get); void iio_channel_release(struct iio_channel *channel) { + if (!channel) + return; iio_device_put(channel->indio_dev); kfree(channel); } -- cgit v1.2.3 From 0165c3005fd64f850b1bbfe2fd24b916a161b696 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 25 Jan 2016 23:24:05 +0100 Subject: iio: adc: Fix dependencies for !HAS_IOMEM archs Not every arch has io memory. So, unbreak the build by fixing the dependencies. Signed-off-by: Richard Weinberger Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 605ff42c4631..283ded7747a9 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -175,6 +175,7 @@ config DA9150_GPADC config EXYNOS_ADC tristate "Exynos ADC driver support" depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST) + depends on HAS_IOMEM help Core support for the ADC block found in the Samsung EXYNOS series of SoCs for drivers such as the touchscreen and hwmon to use to share @@ -207,6 +208,7 @@ config INA2XX_ADC config IMX7D_ADC tristate "IMX7D ADC driver" depends on ARCH_MXC || COMPILE_TEST + depends on HAS_IOMEM help Say yes here to build support for IMX7D ADC. @@ -409,6 +411,7 @@ config TWL6030_GPADC config VF610_ADC tristate "Freescale vf610 ADC driver" depends on OF + depends on HAS_IOMEM select IIO_BUFFER select IIO_TRIGGERED_BUFFER help -- cgit v1.2.3 From e884cebf9ea34f559bc78a474f3fccbc285dcb71 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 25 Jan 2016 23:24:03 +0100 Subject: staging: iio: Fix dependencies for !HAS_IOMEM archs Not every arch has io memory. So, unbreak the build by fixing the dependencies. Signed-off-by: Richard Weinberger Acked-by: Geert Uytterhoeven Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index 94ae4232ee77..c0a977d82657 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -6,6 +6,7 @@ menu "Analog to digital converters" config AD7606 tristate "Analog Devices AD7606 ADC driver" depends on GPIOLIB || COMPILE_TEST + depends on HAS_IOMEM select IIO_BUFFER select IIO_TRIGGERED_BUFFER help -- cgit v1.2.3 From ddeb35cbd6221751f0197ffaa9500da31e8337f4 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 25 Jan 2016 23:24:15 +0100 Subject: iio: imu: Fix dependencies for !HAS_IOMEM archs Not every arch has io memory. While the driver has correct dependencies the select statement will bypass the HAS_IOMEM dependency. So, unbreak the build by rendering it into a real dependency. Signed-off-by: Richard Weinberger Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig index 48fbc0bc7e2a..8f8d1370ed8b 100644 --- a/drivers/iio/imu/inv_mpu6050/Kconfig +++ b/drivers/iio/imu/inv_mpu6050/Kconfig @@ -5,9 +5,9 @@ config INV_MPU6050_IIO tristate "Invensense MPU6050 devices" depends on I2C && SYSFS + depends on I2C_MUX select IIO_BUFFER select IIO_TRIGGERED_BUFFER - select I2C_MUX help This driver supports the Invensense MPU6050 devices. This driver can also support MPU6500 in MPU6050 compatibility mode -- cgit v1.2.3 From 431386e783a3a6c8b7707bee32d18c353b8688b2 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Thu, 21 Jan 2016 01:07:31 +0900 Subject: iio: pressure: mpl115: fix temperature offset sign According to the datasheet, the resolusion of temperature sensor is -5.35 counts/C. Temperature ADC is 472 counts at 25C. (https://www.sparkfun.com/datasheets/Sensors/Pressure/MPL115A1.pdf NOTE: This is older revision, but this information is removed from the latest datasheet from nxp somehow) Temp [C] = (Tadc - 472) / -5.35 + 25 = (Tadc - 605.750000) * -0.186915888 So the correct offset is -605.750000. Signed-off-by: Akinobu Mita Acked-by: Peter Meerwald-Stadler Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/mpl115.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/pressure/mpl115.c b/drivers/iio/pressure/mpl115.c index f5ecd6e19f5d..a0d7deeac62f 100644 --- a/drivers/iio/pressure/mpl115.c +++ b/drivers/iio/pressure/mpl115.c @@ -117,7 +117,7 @@ static int mpl115_read_raw(struct iio_dev *indio_dev, *val = ret >> 6; return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET: - *val = 605; + *val = -605; *val2 = 750000; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_SCALE: -- cgit v1.2.3 From 7e1da86339f29e445e40d41132c30741df8c19ad Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 16:52:40 +0100 Subject: iio: ade7753: avoid uninitialized data The ade7753_spi_read_reg_16() will either successfully read a value from SPI, or return a failure code without delivering data. However, the ade7753_stop_device() and ade7753_reset() functions use the returned data without checking for an error condition first. Gcc detects this as a possible bug and warns about it: drivers/staging/iio/meter/ade7753.c: In function 'ade7753_remove': drivers/staging/iio/meter/ade7753.c:348:6: error: 'val' may be used uninitialized in this function [-Werror=maybe-uninitialized] val |= BIT(4); /* AD converters can be turned off */ ^ drivers/staging/iio/meter/ade7753.c:345:6: note: 'val' was declared here u16 val; ^ drivers/staging/iio/meter/ade7753.c: In function 'ade7753_probe': drivers/staging/iio/meter/ade7753.c:222:6: error: 'val' may be used uninitialized in this function [-Werror=maybe-uninitialized] In both cases, we can avoids the warning by checking the return code before using the data. Signed-off-by: Arnd Bergmann Signed-off-by: Jonathan Cameron --- drivers/staging/iio/meter/ade7753.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c index f129039bece3..69287108f793 100644 --- a/drivers/staging/iio/meter/ade7753.c +++ b/drivers/staging/iio/meter/ade7753.c @@ -217,8 +217,12 @@ error_ret: static int ade7753_reset(struct device *dev) { u16 val; + int ret; + + ret = ade7753_spi_read_reg_16(dev, ADE7753_MODE, &val); + if (ret) + return ret; - ade7753_spi_read_reg_16(dev, ADE7753_MODE, &val); val |= BIT(6); /* Software Chip Reset */ return ade7753_spi_write_reg_16(dev, ADE7753_MODE, val); @@ -343,8 +347,12 @@ error_ret: static int ade7753_stop_device(struct device *dev) { u16 val; + int ret; + + ret = ade7753_spi_read_reg_16(dev, ADE7753_MODE, &val); + if (ret) + return ret; - ade7753_spi_read_reg_16(dev, ADE7753_MODE, &val); val |= BIT(4); /* AD converters can be turned off */ return ade7753_spi_write_reg_16(dev, ADE7753_MODE, val); -- cgit v1.2.3 From 564cff826fd14b8a2f71e663dec8e53b2243a836 Mon Sep 17 00:00:00 2001 From: Alexander Koch Date: Sat, 16 Jan 2016 17:14:36 +0100 Subject: iio: light: opt3001: extract int. time constants Extract integration times as #define constants. This prepares using them for delay/timeout length determination. Signed-off-by: Alexander Koch Signed-off-by: Michael Hornung Tested-by: Andreas Dannenberg Signed-off-by: Jonathan Cameron --- drivers/iio/light/opt3001.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index 01e111e72d4b..aefbd7989bda 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -65,6 +65,9 @@ #define OPT3001_REG_EXPONENT(n) ((n) >> 12) #define OPT3001_REG_MANTISSA(n) ((n) & 0xfff) +#define OPT3001_INT_TIME_LONG 800000 +#define OPT3001_INT_TIME_SHORT 100000 + /* * Time to wait for conversion result to be ready. The device datasheet * worst-case max value is 880ms. Add some slack to be on the safe side. @@ -325,13 +328,13 @@ static int opt3001_set_int_time(struct opt3001 *opt, int time) reg = ret; switch (time) { - case 100000: + case OPT3001_INT_TIME_SHORT: reg &= ~OPT3001_CONFIGURATION_CT; - opt->int_time = 100000; + opt->int_time = OPT3001_INT_TIME_SHORT; break; - case 800000: + case OPT3001_INT_TIME_LONG: reg |= OPT3001_CONFIGURATION_CT; - opt->int_time = 800000; + opt->int_time = OPT3001_INT_TIME_LONG; break; default: return -EINVAL; @@ -597,9 +600,9 @@ static int opt3001_configure(struct opt3001 *opt) /* Reflect status of the device's integration time setting */ if (reg & OPT3001_CONFIGURATION_CT) - opt->int_time = 800000; + opt->int_time = OPT3001_INT_TIME_LONG; else - opt->int_time = 100000; + opt->int_time = OPT3001_INT_TIME_SHORT; /* Ensure device is in shutdown initially */ opt3001_set_mode(opt, ®, OPT3001_CONFIGURATION_M_SHUTDOWN); -- cgit v1.2.3 From 84e8d090c57522c5f8ae59f5b922bedb929165c7 Mon Sep 17 00:00:00 2001 From: Alexander Koch Date: Sat, 16 Jan 2016 17:14:37 +0100 Subject: iio: light: opt3001: trivial type refactoring Change variable type of struct opt3001 members 'ok_to_ignore_lock' and 'result_ready' uint16-bitfield of length one to bool. They are used as bool, let the compiler do the optimization. Signed-off-by: Alexander Koch Signed-off-by: Michael Hornung Tested-by: Andreas Dannenberg Signed-off-by: Jonathan Cameron --- drivers/iio/light/opt3001.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index aefbd7989bda..b05c484a1646 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -79,8 +79,8 @@ struct opt3001 { struct device *dev; struct mutex lock; - u16 ok_to_ignore_lock:1; - u16 result_ready:1; + bool ok_to_ignore_lock; + bool result_ready; wait_queue_head_t result_ready_queue; u16 result; -- cgit v1.2.3 From ac663db3678a62f69a2a73126e51a9a302b27ff2 Mon Sep 17 00:00:00 2001 From: Alexander Koch Date: Sat, 16 Jan 2016 17:14:38 +0100 Subject: iio: light: opt3001: enable operation w/o IRQ Enable operation of the TI OPT3001 light sensor without having an interrupt line available to connect the INT pin to. In this operation mode, we issue a conversion request and simply wait for the conversion time available as timeout value, determined from integration time configuration and the worst-case time given in the data sheet (sect. 6.5, table on p. 5): short integration time (100ms): 110ms + 3ms = 113ms long integration time (800ms): 880ms + 3ms = 883ms This change is transparent as behaviour defaults to using the interrupt method if an interrupt no. is configured via device tree. Interrupt-less operation mode is performed when no valid interrupt no. is given. Signed-off-by: Alexander Koch Signed-off-by: Michael Hornung Tested-by: Andreas Dannenberg Signed-off-by: Jonathan Cameron --- drivers/iio/light/opt3001.c | 137 ++++++++++++++++++++++++++++++-------------- 1 file changed, 95 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index b05c484a1646..b776c8ed4387 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -70,9 +70,12 @@ /* * Time to wait for conversion result to be ready. The device datasheet - * worst-case max value is 880ms. Add some slack to be on the safe side. + * sect. 6.5 states results are ready after total integration time plus 3ms. + * This results in worst-case max values of 113ms or 883ms, respectively. + * Add some slack to be on the safe side. */ -#define OPT3001_RESULT_READY_TIMEOUT msecs_to_jiffies(1000) +#define OPT3001_RESULT_READY_SHORT 150 +#define OPT3001_RESULT_READY_LONG 1000 struct opt3001 { struct i2c_client *client; @@ -92,6 +95,8 @@ struct opt3001 { u8 high_thresh_exp; u8 low_thresh_exp; + + bool use_irq; }; struct opt3001_scale { @@ -230,26 +235,30 @@ static int opt3001_get_lux(struct opt3001 *opt, int *val, int *val2) u16 reg; u8 exponent; u16 value; + long timeout; - /* - * Enable the end-of-conversion interrupt mechanism. Note that doing - * so will overwrite the low-level limit value however we will restore - * this value later on. - */ - ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_LOW_LIMIT, - OPT3001_LOW_LIMIT_EOC_ENABLE); - if (ret < 0) { - dev_err(opt->dev, "failed to write register %02x\n", - OPT3001_LOW_LIMIT); - return ret; + if (opt->use_irq) { + /* + * Enable the end-of-conversion interrupt mechanism. Note that + * doing so will overwrite the low-level limit value however we + * will restore this value later on. + */ + ret = i2c_smbus_write_word_swapped(opt->client, + OPT3001_LOW_LIMIT, + OPT3001_LOW_LIMIT_EOC_ENABLE); + if (ret < 0) { + dev_err(opt->dev, "failed to write register %02x\n", + OPT3001_LOW_LIMIT); + return ret; + } + + /* Allow IRQ to access the device despite lock being set */ + opt->ok_to_ignore_lock = true; } - /* Reset data-ready indicator flag (will be set in the IRQ routine) */ + /* Reset data-ready indicator flag */ opt->result_ready = false; - /* Allow IRQ to access the device despite lock being set */ - opt->ok_to_ignore_lock = true; - /* Configure for single-conversion mode and start a new conversion */ ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION); if (ret < 0) { @@ -269,32 +278,69 @@ static int opt3001_get_lux(struct opt3001 *opt, int *val, int *val2) goto err; } - /* Wait for the IRQ to indicate the conversion is complete */ - ret = wait_event_timeout(opt->result_ready_queue, opt->result_ready, - OPT3001_RESULT_READY_TIMEOUT); + if (opt->use_irq) { + /* Wait for the IRQ to indicate the conversion is complete */ + ret = wait_event_timeout(opt->result_ready_queue, + opt->result_ready, + msecs_to_jiffies(OPT3001_RESULT_READY_LONG)); + } else { + /* Sleep for result ready time */ + timeout = (opt->int_time == OPT3001_INT_TIME_SHORT) ? + OPT3001_RESULT_READY_SHORT : OPT3001_RESULT_READY_LONG; + msleep(timeout); + + /* Check result ready flag */ + ret = i2c_smbus_read_word_swapped(opt->client, + OPT3001_CONFIGURATION); + if (ret < 0) { + dev_err(opt->dev, "failed to read register %02x\n", + OPT3001_CONFIGURATION); + goto err; + } + + if (!(ret & OPT3001_CONFIGURATION_CRF)) { + ret = -ETIMEDOUT; + goto err; + } + + /* Obtain value */ + ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_RESULT); + if (ret < 0) { + dev_err(opt->dev, "failed to read register %02x\n", + OPT3001_RESULT); + goto err; + } + opt->result = ret; + opt->result_ready = true; + } err: - /* Disallow IRQ to access the device while lock is active */ - opt->ok_to_ignore_lock = false; + if (opt->use_irq) + /* Disallow IRQ to access the device while lock is active */ + opt->ok_to_ignore_lock = false; if (ret == 0) return -ETIMEDOUT; else if (ret < 0) return ret; - /* - * Disable the end-of-conversion interrupt mechanism by restoring the - * low-level limit value (clearing OPT3001_LOW_LIMIT_EOC_ENABLE). Note - * that selectively clearing those enable bits would affect the actual - * limit value due to bit-overlap and therefore can't be done. - */ - value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa; - ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_LOW_LIMIT, - value); - if (ret < 0) { - dev_err(opt->dev, "failed to write register %02x\n", - OPT3001_LOW_LIMIT); - return ret; + if (opt->use_irq) { + /* + * Disable the end-of-conversion interrupt mechanism by + * restoring the low-level limit value (clearing + * OPT3001_LOW_LIMIT_EOC_ENABLE). Note that selectively clearing + * those enable bits would affect the actual limit value due to + * bit-overlap and therefore can't be done. + */ + value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa; + ret = i2c_smbus_write_word_swapped(opt->client, + OPT3001_LOW_LIMIT, + value); + if (ret < 0) { + dev_err(opt->dev, "failed to write register %02x\n", + OPT3001_LOW_LIMIT); + return ret; + } } exponent = OPT3001_REG_EXPONENT(opt->result); @@ -736,12 +782,18 @@ static int opt3001_probe(struct i2c_client *client, return ret; } - ret = request_threaded_irq(irq, NULL, opt3001_irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "opt3001", iio); - if (ret) { - dev_err(dev, "failed to request IRQ #%d\n", irq); - return ret; + /* Make use of INT pin only if valid IRQ no. is given */ + if (irq > 0) { + ret = request_threaded_irq(irq, NULL, opt3001_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "opt3001", iio); + if (ret) { + dev_err(dev, "failed to request IRQ #%d\n", irq); + return ret; + } + opt->use_irq = true; + } else { + dev_dbg(opt->dev, "enabling interrupt-less operation\n"); } return 0; @@ -754,7 +806,8 @@ static int opt3001_remove(struct i2c_client *client) int ret; u16 reg; - free_irq(client->irq, iio); + if (opt->use_irq) + free_irq(client->irq, iio); ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION); if (ret < 0) { -- cgit v1.2.3 From 255ec44451f07334e4c4d54826fc9f2d21025b9e Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Thu, 21 Jan 2016 12:22:59 +0530 Subject: Staging: iio: Documentation: Remove unused sysfs attributes This patch removes the unused sysfs attributes range, range_available, adc_resolution and adc_resolution_available. Signed-off-by: Shraddha Barke Signed-off-by: Jonathan Cameron --- .../staging/iio/Documentation/sysfs-bus-iio-light | 28 ---------------------- 1 file changed, 28 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-light b/drivers/staging/iio/Documentation/sysfs-bus-iio-light index 17e5c9c515d4..7c7cd8456060 100644 --- a/drivers/staging/iio/Documentation/sysfs-bus-iio-light +++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-light @@ -1,31 +1,3 @@ - -What: /sys/bus/iio/devices/device[n]/range -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - Hardware dependent ADC Full Scale Range used for some ambient - light sensors in calculating lux. - -What: /sys/bus/iio/devices/device[n]/range_available -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - Hardware dependent supported vales for ADC Full Scale Range. - -What: /sys/bus/iio/devices/device[n]/adc_resolution -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - Hardware dependent ADC resolution of the ambient light sensor - used in calculating the lux. - -What: /sys/bus/iio/devices/device[n]/adc_resolution_available -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - Hardware dependent list of possible values supported for the - adc_resolution of the given sensor. - What: /sys/bus/iio/devices/device[n]/in_illuminance0[_input|_raw] KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org -- cgit v1.2.3 From 0b767b31889539fbc31383469317264ebee3cf08 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 16 Jan 2016 01:00:02 +0900 Subject: iio: pressure: mpl115: don't set unused i2c clientdata mpl115 sets i2c clientdata, but it is not used anywhere. So remove it. Signed-off-by: Akinobu Mita Cc: Jonathan Cameron Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald Cc: linux-iio@vger.kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/mpl115.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/pressure/mpl115.c b/drivers/iio/pressure/mpl115.c index f5ecd6e19f5d..3e1e33535fe1 100644 --- a/drivers/iio/pressure/mpl115.c +++ b/drivers/iio/pressure/mpl115.c @@ -163,7 +163,6 @@ static int mpl115_probe(struct i2c_client *client, data->client = client; mutex_init(&data->lock); - i2c_set_clientdata(client, indio_dev); indio_dev->info = &mpl115_info; indio_dev->name = id->name; indio_dev->dev.parent = &client->dev; -- cgit v1.2.3 From c984b9cbbd17d3eb602de3802e25d975182474fa Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 16 Jan 2016 01:00:03 +0900 Subject: iio: pressure: mpl115: support MPL115A1 mpl115 driver currently supports i2c interface (MPL115A2). There is also SPI version (MPL115A1). The difference between them is only physical transport so we can easily support both while sharing most of the code. Split the driver into a core support module and one module each for I2C and SPI support. Signed-off-by: Akinobu Mita Cc: Jonathan Cameron Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald Cc: linux-iio@vger.kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/Kconfig | 17 +++++- drivers/iio/pressure/Makefile | 2 + drivers/iio/pressure/mpl115.c | 65 ++++++++++------------- drivers/iio/pressure/mpl115.h | 24 +++++++++ drivers/iio/pressure/mpl115_i2c.c | 67 ++++++++++++++++++++++++ drivers/iio/pressure/mpl115_spi.c | 106 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 242 insertions(+), 39 deletions(-) create mode 100644 drivers/iio/pressure/mpl115.h create mode 100644 drivers/iio/pressure/mpl115_i2c.c create mode 100644 drivers/iio/pressure/mpl115_spi.c (limited to 'drivers') diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index 6f2e7c9ac23e..e8f60dbf646e 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -31,14 +31,29 @@ config HID_SENSOR_PRESS will be called hid-sensor-press. config MPL115 + tristate + +config MPL115_I2C tristate "Freescale MPL115A2 pressure sensor driver" depends on I2C + select MPL115 help Say yes here to build support for the Freescale MPL115A2 pressure sensor connected via I2C. To compile this driver as a module, choose M here: the module - will be called mpl115. + will be called mpl115_i2c. + +config MPL115_SPI + tristate "Freescale MPL115A1 pressure sensor driver" + depends on SPI_MASTER + select MPL115 + help + Say yes here to build support for the Freescale MPL115A1 + pressure sensor connected via SPI. + + To compile this driver as a module, choose M here: the module + will be called mpl115_spi. config MPL3115 tristate "Freescale MPL3115A2 pressure sensor driver" diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index 46571c96823f..d336af14f3fe 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile @@ -6,6 +6,8 @@ obj-$(CONFIG_BMP280) += bmp280.o obj-$(CONFIG_HID_SENSOR_PRESS) += hid-sensor-press.o obj-$(CONFIG_MPL115) += mpl115.o +obj-$(CONFIG_MPL115_I2C) += mpl115_i2c.o +obj-$(CONFIG_MPL115_SPI) += mpl115_spi.o obj-$(CONFIG_MPL3115) += mpl3115.o obj-$(CONFIG_MS5611) += ms5611_core.o obj-$(CONFIG_MS5611_I2C) += ms5611_i2c.o diff --git a/drivers/iio/pressure/mpl115.c b/drivers/iio/pressure/mpl115.c index 3e1e33535fe1..138344ca3ffd 100644 --- a/drivers/iio/pressure/mpl115.c +++ b/drivers/iio/pressure/mpl115.c @@ -1,5 +1,5 @@ /* - * mpl115.c - Support for Freescale MPL115A2 pressure/temperature sensor + * mpl115.c - Support for Freescale MPL115A pressure/temperature sensor * * Copyright (c) 2014 Peter Meerwald * @@ -7,17 +7,16 @@ * the GNU General Public License. See the file COPYING in the main * directory of this archive for more details. * - * (7-bit I2C slave address 0x60) - * * TODO: shutdown pin * */ #include -#include #include #include +#include "mpl115.h" + #define MPL115_PADC 0x00 /* pressure ADC output value, MSB first, 10 bit */ #define MPL115_TADC 0x02 /* temperature ADC output value, MSB first, 10 bit */ #define MPL115_A0 0x04 /* 12 bit integer, 3 bit fraction */ @@ -27,16 +26,18 @@ #define MPL115_CONVERT 0x12 /* convert temperature and pressure */ struct mpl115_data { - struct i2c_client *client; + struct device *dev; struct mutex lock; s16 a0; s16 b1, b2; s16 c12; + const struct mpl115_ops *ops; }; static int mpl115_request(struct mpl115_data *data) { - int ret = i2c_smbus_write_byte_data(data->client, MPL115_CONVERT, 0); + int ret = data->ops->write(data->dev, MPL115_CONVERT, 0); + if (ret < 0) return ret; @@ -57,12 +58,12 @@ static int mpl115_comp_pressure(struct mpl115_data *data, int *val, int *val2) if (ret < 0) goto done; - ret = i2c_smbus_read_word_swapped(data->client, MPL115_PADC); + ret = data->ops->read(data->dev, MPL115_PADC); if (ret < 0) goto done; padc = ret >> 6; - ret = i2c_smbus_read_word_swapped(data->client, MPL115_TADC); + ret = data->ops->read(data->dev, MPL115_TADC); if (ret < 0) goto done; tadc = ret >> 6; @@ -90,7 +91,7 @@ static int mpl115_read_temp(struct mpl115_data *data) ret = mpl115_request(data); if (ret < 0) goto done; - ret = i2c_smbus_read_word_swapped(data->client, MPL115_TADC); + ret = data->ops->read(data->dev, MPL115_TADC); done: mutex_unlock(&data->lock); return ret; @@ -145,65 +146,53 @@ static const struct iio_info mpl115_info = { .driver_module = THIS_MODULE, }; -static int mpl115_probe(struct i2c_client *client, - const struct i2c_device_id *id) +int mpl115_probe(struct device *dev, const char *name, + const struct mpl115_ops *ops) { struct mpl115_data *data; struct iio_dev *indio_dev; int ret; - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) - return -ENODEV; - - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; data = iio_priv(indio_dev); - data->client = client; + data->dev = dev; + data->ops = ops; mutex_init(&data->lock); indio_dev->info = &mpl115_info; - indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; + indio_dev->name = name; + indio_dev->dev.parent = dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = mpl115_channels; indio_dev->num_channels = ARRAY_SIZE(mpl115_channels); - ret = i2c_smbus_read_word_swapped(data->client, MPL115_A0); + ret = data->ops->init(data->dev); + if (ret) + return ret; + + ret = data->ops->read(data->dev, MPL115_A0); if (ret < 0) return ret; data->a0 = ret; - ret = i2c_smbus_read_word_swapped(data->client, MPL115_B1); + ret = data->ops->read(data->dev, MPL115_B1); if (ret < 0) return ret; data->b1 = ret; - ret = i2c_smbus_read_word_swapped(data->client, MPL115_B2); + ret = data->ops->read(data->dev, MPL115_B2); if (ret < 0) return ret; data->b2 = ret; - ret = i2c_smbus_read_word_swapped(data->client, MPL115_C12); + ret = data->ops->read(data->dev, MPL115_C12); if (ret < 0) return ret; data->c12 = ret; - return devm_iio_device_register(&client->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } - -static const struct i2c_device_id mpl115_id[] = { - { "mpl115", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, mpl115_id); - -static struct i2c_driver mpl115_driver = { - .driver = { - .name = "mpl115", - }, - .probe = mpl115_probe, - .id_table = mpl115_id, -}; -module_i2c_driver(mpl115_driver); +EXPORT_SYMBOL_GPL(mpl115_probe); MODULE_AUTHOR("Peter Meerwald "); MODULE_DESCRIPTION("Freescale MPL115 pressure/temperature driver"); diff --git a/drivers/iio/pressure/mpl115.h b/drivers/iio/pressure/mpl115.h new file mode 100644 index 000000000000..01b652774dc3 --- /dev/null +++ b/drivers/iio/pressure/mpl115.h @@ -0,0 +1,24 @@ +/* + * Freescale MPL115A pressure/temperature sensor + * + * Copyright (c) 2014 Peter Meerwald + * Copyright (c) 2016 Akinobu Mita + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + */ + +#ifndef _MPL115_H_ +#define _MPL115_H_ + +struct mpl115_ops { + int (*init)(struct device *); + int (*read)(struct device *, u8); + int (*write)(struct device *, u8, u8); +}; + +int mpl115_probe(struct device *dev, const char *name, + const struct mpl115_ops *ops); + +#endif diff --git a/drivers/iio/pressure/mpl115_i2c.c b/drivers/iio/pressure/mpl115_i2c.c new file mode 100644 index 000000000000..9ea055c3f89e --- /dev/null +++ b/drivers/iio/pressure/mpl115_i2c.c @@ -0,0 +1,67 @@ +/* + * Freescale MPL115A2 pressure/temperature sensor + * + * Copyright (c) 2014 Peter Meerwald + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * (7-bit I2C slave address 0x60) + * + * Datasheet: http://www.nxp.com/files/sensors/doc/data_sheet/MPL115A2.pdf + */ + +#include +#include + +#include "mpl115.h" + +static int mpl115_i2c_init(struct device *dev) +{ + return 0; +} + +static int mpl115_i2c_read(struct device *dev, u8 address) +{ + return i2c_smbus_read_word_swapped(to_i2c_client(dev), address); +} + +static int mpl115_i2c_write(struct device *dev, u8 address, u8 value) +{ + return i2c_smbus_write_byte_data(to_i2c_client(dev), address, value); +} + +static const struct mpl115_ops mpl115_i2c_ops = { + .init = mpl115_i2c_init, + .read = mpl115_i2c_read, + .write = mpl115_i2c_write, +}; + +static int mpl115_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + + return mpl115_probe(&client->dev, id->name, &mpl115_i2c_ops); +} + +static const struct i2c_device_id mpl115_i2c_id[] = { + { "mpl115", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mpl115_i2c_id); + +static struct i2c_driver mpl115_i2c_driver = { + .driver = { + .name = "mpl115", + }, + .probe = mpl115_i2c_probe, + .id_table = mpl115_i2c_id, +}; +module_i2c_driver(mpl115_i2c_driver); + +MODULE_AUTHOR("Peter Meerwald "); +MODULE_DESCRIPTION("Freescale MPL115A2 pressure/temperature driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/pressure/mpl115_spi.c b/drivers/iio/pressure/mpl115_spi.c new file mode 100644 index 000000000000..9ebf55f5b3aa --- /dev/null +++ b/drivers/iio/pressure/mpl115_spi.c @@ -0,0 +1,106 @@ +/* + * Freescale MPL115A1 pressure/temperature sensor + * + * Copyright (c) 2016 Akinobu Mita + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * Datasheet: http://www.nxp.com/files/sensors/doc/data_sheet/MPL115A1.pdf + */ + +#include +#include + +#include "mpl115.h" + +#define MPL115_SPI_WRITE(address) ((address) << 1) +#define MPL115_SPI_READ(address) (0x80 | (address) << 1) + +struct mpl115_spi_buf { + u8 tx[4]; + u8 rx[4]; +}; + +static int mpl115_spi_init(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + struct mpl115_spi_buf *buf; + + buf = devm_kzalloc(dev, sizeof(*buf), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + spi_set_drvdata(spi, buf); + + return 0; +} + +static int mpl115_spi_read(struct device *dev, u8 address) +{ + struct spi_device *spi = to_spi_device(dev); + struct mpl115_spi_buf *buf = spi_get_drvdata(spi); + struct spi_transfer xfer = { + .tx_buf = buf->tx, + .rx_buf = buf->rx, + .len = 4, + }; + int ret; + + buf->tx[0] = MPL115_SPI_READ(address); + buf->tx[2] = MPL115_SPI_READ(address + 1); + + ret = spi_sync_transfer(spi, &xfer, 1); + if (ret) + return ret; + + return (buf->rx[1] << 8) | buf->rx[3]; +} + +static int mpl115_spi_write(struct device *dev, u8 address, u8 value) +{ + struct spi_device *spi = to_spi_device(dev); + struct mpl115_spi_buf *buf = spi_get_drvdata(spi); + struct spi_transfer xfer = { + .tx_buf = buf->tx, + .len = 2, + }; + + buf->tx[0] = MPL115_SPI_WRITE(address); + buf->tx[1] = value; + + return spi_sync_transfer(spi, &xfer, 1); +} + +static const struct mpl115_ops mpl115_spi_ops = { + .init = mpl115_spi_init, + .read = mpl115_spi_read, + .write = mpl115_spi_write, +}; + +static int mpl115_spi_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + + return mpl115_probe(&spi->dev, id->name, &mpl115_spi_ops); +} + +static const struct spi_device_id mpl115_spi_ids[] = { + { "mpl115", 0 }, + {} +}; +MODULE_DEVICE_TABLE(spi, mpl115_spi_ids); + +static struct spi_driver mpl115_spi_driver = { + .driver = { + .name = "mpl115", + }, + .probe = mpl115_spi_probe, + .id_table = mpl115_spi_ids, +}; +module_spi_driver(mpl115_spi_driver); + +MODULE_AUTHOR("Akinobu Mita "); +MODULE_DESCRIPTION("Freescale MPL115A1 pressure/temperature driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 22acc120a141ce0a3b6e98799d15970ef687bc70 Mon Sep 17 00:00:00 2001 From: Harald Geyer Date: Sun, 17 Jan 2016 16:13:29 +0000 Subject: iio: dht11: Improve reliability - be more tolerant about missing start bits Instead of guessing where the data starts, we now just try to decode from every possible start position. This causes no additional overhead if we properly received the full preamble and only costs a few extra CPU cycles in the case where the preamble is corrupted. This is much more efficient than to return an error to userspace and start over again. Signed-off-by: Harald Geyer Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/dht11.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/humidity/dht11.c b/drivers/iio/humidity/dht11.c index 1165b1c4f9d6..1ca284aaacfc 100644 --- a/drivers/iio/humidity/dht11.c +++ b/drivers/iio/humidity/dht11.c @@ -161,7 +161,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev, int *val, int *val2, long m) { struct dht11 *dht11 = iio_priv(iio_dev); - int ret, timeres; + int ret, timeres, offset; mutex_lock(&dht11->lock); if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_real_ns()) { @@ -208,11 +208,14 @@ static int dht11_read_raw(struct iio_dev *iio_dev, if (ret < 0) goto err; - ret = dht11_decode(dht11, - dht11->num_edges == DHT11_EDGES_PER_READ ? - DHT11_EDGES_PREAMBLE : - DHT11_EDGES_PREAMBLE - 2, - timeres); + offset = DHT11_EDGES_PREAMBLE + + dht11->num_edges - DHT11_EDGES_PER_READ; + for (; offset >= 0; --offset) { + ret = dht11_decode(dht11, offset, timeres); + if (!ret) + break; + } + if (ret) goto err; } -- cgit v1.2.3 From 155a57593d38cf7153c01cc037373462aa1e1cc1 Mon Sep 17 00:00:00 2001 From: Harald Geyer Date: Sun, 17 Jan 2016 16:13:30 +0000 Subject: iio: dht11: Simplify decoding algorithm The new algorithm uses a 'one size fits em all' threshold, which should be easier to understand and debug. I believe there are no regressions compared to the old adaptive threshold algorithm. I don't remember why I chose the old algorithm when I initially wrote the driver. Signed-off-by: Harald Geyer Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/dht11.c | 64 +++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/humidity/dht11.c b/drivers/iio/humidity/dht11.c index 1ca284aaacfc..96185f8fad88 100644 --- a/drivers/iio/humidity/dht11.c +++ b/drivers/iio/humidity/dht11.c @@ -50,12 +50,32 @@ #define DHT11_EDGES_PER_READ (2 * DHT11_BITS_PER_READ + \ DHT11_EDGES_PREAMBLE + 1) -/* Data transmission timing (nano seconds) */ +/* + * Data transmission timing: + * Data bits are encoded as pulse length (high time) on the data line. + * 0-bit: 22-30uS -- typically 26uS (AM2302) + * 1-bit: 68-75uS -- typically 70uS (AM2302) + * The acutal timings also depend on the properties of the cable, with + * longer cables typically making pulses shorter. + * + * Our decoding depends on the time resolution of the system: + * timeres > 34uS ... don't know what a 1-tick pulse is + * 34uS > timeres > 30uS ... no problem (30kHz and 32kHz clocks) + * 30uS > timeres > 23uS ... don't know what a 2-tick pulse is + * timeres < 23uS ... no problem + * + * Luckily clocks in the 33-44kHz range are quite uncommon, so we can + * support most systems if the threshold for decoding a pulse as 1-bit + * is chosen carefully. If somebody really wants to support clocks around + * 40kHz, where this driver is most unreliable, there are two options. + * a) select an implementation using busy loop polling on those systems + * b) use the checksum to do some probabilistic decoding + */ #define DHT11_START_TRANSMISSION 18 /* ms */ -#define DHT11_SENSOR_RESPONSE 80000 -#define DHT11_START_BIT 50000 -#define DHT11_DATA_BIT_LOW 27000 -#define DHT11_DATA_BIT_HIGH 70000 +#define DHT11_MIN_TIMERES 34000 /* ns */ +#define DHT11_THRESHOLD 49000 /* ns */ +#define DHT11_AMBIG_LOW 23000 /* ns */ +#define DHT11_AMBIG_HIGH 30000 /* ns */ struct dht11 { struct device *dev; @@ -76,43 +96,39 @@ struct dht11 { struct {s64 ts; int value; } edges[DHT11_EDGES_PER_READ]; }; -static unsigned char dht11_decode_byte(int *timing, int threshold) +static unsigned char dht11_decode_byte(char *bits) { unsigned char ret = 0; int i; for (i = 0; i < 8; ++i) { ret <<= 1; - if (timing[i] >= threshold) + if (bits[i]) ++ret; } return ret; } -static int dht11_decode(struct dht11 *dht11, int offset, int timeres) +static int dht11_decode(struct dht11 *dht11, int offset) { - int i, t, timing[DHT11_BITS_PER_READ], threshold; + int i, t; + char bits[DHT11_BITS_PER_READ]; unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum; - threshold = DHT11_DATA_BIT_HIGH / timeres; - if (DHT11_DATA_BIT_LOW / timeres + 1 >= threshold) - pr_err("dht11: WARNING: decoding ambiguous\n"); - - /* scale down with timeres and check validity */ for (i = 0; i < DHT11_BITS_PER_READ; ++i) { t = dht11->edges[offset + 2 * i + 2].ts - dht11->edges[offset + 2 * i + 1].ts; if (!dht11->edges[offset + 2 * i + 1].value) return -EIO; /* lost synchronisation */ - timing[i] = t / timeres; + bits[i] = t > DHT11_THRESHOLD; } - hum_int = dht11_decode_byte(timing, threshold); - hum_dec = dht11_decode_byte(&timing[8], threshold); - temp_int = dht11_decode_byte(&timing[16], threshold); - temp_dec = dht11_decode_byte(&timing[24], threshold); - checksum = dht11_decode_byte(&timing[32], threshold); + hum_int = dht11_decode_byte(bits); + hum_dec = dht11_decode_byte(&bits[8]); + temp_int = dht11_decode_byte(&bits[16]); + temp_dec = dht11_decode_byte(&bits[24]); + checksum = dht11_decode_byte(&bits[32]); if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum) return -EIO; @@ -166,7 +182,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev, mutex_lock(&dht11->lock); if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_real_ns()) { timeres = ktime_get_resolution_ns(); - if (DHT11_DATA_BIT_HIGH < 2 * timeres) { + if (timeres > DHT11_MIN_TIMERES) { dev_err(dht11->dev, "timeresolution %dns too low\n", timeres); /* In theory a better clock could become available @@ -176,6 +192,10 @@ static int dht11_read_raw(struct iio_dev *iio_dev, ret = -EAGAIN; goto err; } + if (timeres > DHT11_AMBIG_LOW && timeres < DHT11_AMBIG_HIGH) + dev_warn(dht11->dev, + "timeresolution: %dns - decoding ambiguous\n", + timeres); reinit_completion(&dht11->completion); @@ -211,7 +231,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev, offset = DHT11_EDGES_PREAMBLE + dht11->num_edges - DHT11_EDGES_PER_READ; for (; offset >= 0; --offset) { - ret = dht11_decode(dht11, offset, timeres); + ret = dht11_decode(dht11, offset); if (!ret) break; } -- cgit v1.2.3 From 21cb454dc7c065d213efe8d578d67b65ecec8e02 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 24 Jan 2016 17:06:50 +0000 Subject: iio:pressure:Kconfig white space cleanup. Clearly a high degree of cut and paste has gone on in this file, propogating a particularly random combination of tabs and spaces. This patch at least should make it all consistent going forward. Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/Kconfig | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index e8f60dbf646e..cf03a43545a1 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -10,11 +10,11 @@ config BMP280 depends on I2C select REGMAP_I2C help - Say yes here to build support for Bosch Sensortec BMP280 - pressure and temperature sensor. + Say yes here to build support for Bosch Sensortec BMP280 + pressure and temperature sensor. - To compile this driver as a module, choose M here: the module - will be called bmp280. + To compile this driver as a module, choose M here: the module + will be called bmp280. config HID_SENSOR_PRESS depends on HID_SENSOR_HUB @@ -27,8 +27,8 @@ config HID_SENSOR_PRESS Say yes here to build support for the HID SENSOR Pressure driver - To compile this driver as a module, choose M here: the module - will be called hid-sensor-press. + To compile this driver as a module, choose M here: the module + will be called hid-sensor-press. config MPL115 tristate @@ -41,8 +41,8 @@ config MPL115_I2C Say yes here to build support for the Freescale MPL115A2 pressure sensor connected via I2C. - To compile this driver as a module, choose M here: the module - will be called mpl115_i2c. + To compile this driver as a module, choose M here: the module + will be called mpl115_i2c. config MPL115_SPI tristate "Freescale MPL115A1 pressure sensor driver" @@ -52,8 +52,8 @@ config MPL115_SPI Say yes here to build support for the Freescale MPL115A1 pressure sensor connected via SPI. - To compile this driver as a module, choose M here: the module - will be called mpl115_spi. + To compile this driver as a module, choose M here: the module + will be called mpl115_spi. config MPL3115 tristate "Freescale MPL3115A2 pressure sensor driver" @@ -64,8 +64,8 @@ config MPL3115 Say yes here to build support for the Freescale MPL3115A2 pressure sensor / altimeter. - To compile this driver as a module, choose M here: the module - will be called mpl3115. + To compile this driver as a module, choose M here: the module + will be called mpl3115. config MS5611 tristate "Measurement Specialties MS5611 pressure sensor driver" @@ -97,7 +97,7 @@ config MS5611_SPI config MS5637 tristate "Measurement Specialties MS5637 pressure & temperature sensor" depends on I2C - select IIO_MS_SENSORS_I2C + select IIO_MS_SENSORS_I2C help If you say yes here you get support for the Measurement Specialties MS5637 pressure and temperature sensor. @@ -143,7 +143,7 @@ config T5403 Say yes here to build support for the EPCOS T5403 pressure sensor connected via I2C. - To compile this driver as a module, choose M here: the module - will be called t5403. + To compile this driver as a module, choose M here: the module + will be called t5403. endmenu -- cgit v1.2.3 From 3f4202652ea742a79294bd7b8a945ff96696b966 Mon Sep 17 00:00:00 2001 From: Cristina Moraru Date: Tue, 26 Jan 2016 22:21:07 +0200 Subject: iio: si7005: add support for Hoperf th02 This patch adds support for Hoperf th02 humidity and temperature sensor as it uses same register definitions as si7005 th02 Datasheet: http://www.anglia-live.com/netalogue/pdfs/hrf/datasheets/TH02_V1.1.pdf Signed-off-by: Cristina Moraru Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/Kconfig | 3 ++- drivers/iio/humidity/si7005.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig index 6a23698d347c..63823379830b 100644 --- a/drivers/iio/humidity/Kconfig +++ b/drivers/iio/humidity/Kconfig @@ -43,7 +43,8 @@ config SI7005 humidity and temperature sensor. To compile this driver as a module, choose M here: the module - will be called si7005. + will be called si7005. This driver also + supports Hoperf TH02 Humidity and Temperature Sensor. config SI7020 tristate "Si7013/20/21 Relative Humidity and Temperature Sensors" diff --git a/drivers/iio/humidity/si7005.c b/drivers/iio/humidity/si7005.c index 91972ccd8aaf..98a022fa26ad 100644 --- a/drivers/iio/humidity/si7005.c +++ b/drivers/iio/humidity/si7005.c @@ -170,6 +170,7 @@ static int si7005_probe(struct i2c_client *client, static const struct i2c_device_id si7005_id[] = { { "si7005", 0 }, + { "th02", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, si7005_id); -- cgit v1.2.3 From 920dad0ce3f8893fa41a630435da44b4b719bdcb Mon Sep 17 00:00:00 2001 From: Cristina Moraru Date: Tue, 26 Jan 2016 22:17:49 +0200 Subject: iio: si7020: add support for Hoperf th06 This patch adds support for Hoperf th06 humidity and temperature sensor as it uses same register definitions as si7020 th06 Datasheet: http://www.hoperf.com/upload/sensor/TH06.pdf Signed-off-by: Cristina Moraru Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/Kconfig | 3 ++- drivers/iio/humidity/si7020.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig index 63823379830b..866dda133336 100644 --- a/drivers/iio/humidity/Kconfig +++ b/drivers/iio/humidity/Kconfig @@ -51,7 +51,8 @@ config SI7020 depends on I2C help Say yes here to build support for the Silicon Labs Si7013/20/21 - Relative Humidity and Temperature Sensors. + Relative Humidity and Temperature Sensors. This driver also + supports Hoperf TH06 Humidity and Temperature Sensor. To compile this driver as a module, choose M here: the module will be called si7020. diff --git a/drivers/iio/humidity/si7020.c b/drivers/iio/humidity/si7020.c index 71991b5c0658..5ab4e06fb544 100644 --- a/drivers/iio/humidity/si7020.c +++ b/drivers/iio/humidity/si7020.c @@ -149,6 +149,7 @@ static int si7020_probe(struct i2c_client *client, static const struct i2c_device_id si7020_id[] = { { "si7020", 0 }, + { "th06", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, si7020_id); -- cgit v1.2.3 From ecb3a7ccc653fc8007edd0591d32d839386673f1 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Tue, 26 Jan 2016 18:34:30 -0800 Subject: iio: ph: add IIO_PH channel type Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 7 +++++++ drivers/iio/industrialio-core.c | 1 + include/uapi/linux/iio/types.h | 1 + 3 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 8fadd272ad8a..80c6fce9935b 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1493,3 +1493,10 @@ Description: This ABI is especially applicable for humidity sensors to heatup the device and get rid of any condensation in some humidity environment + +What: /sys/bus/iio/devices/iio:deviceX/in_ph_raw +KernelVersion: 4.5 +Contact: linux-iio@vger.kernel.org +Description: + Raw (unscaled no offset etc.) pH reading of a substance as a negative + base-10 logarithm of hydrodium ions in a litre of water. diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index fd01f3493fc7..eb01a83a5b7c 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -77,6 +77,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_VELOCITY] = "velocity", [IIO_CONCENTRATION] = "concentration", [IIO_RESISTANCE] = "resistance", + [IIO_PH] = "ph", }; static const char * const iio_modifier_names[] = { diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h index 7c63bd67c36e..c077617f3304 100644 --- a/include/uapi/linux/iio/types.h +++ b/include/uapi/linux/iio/types.h @@ -37,6 +37,7 @@ enum iio_chan_type { IIO_VELOCITY, IIO_CONCENTRATION, IIO_RESISTANCE, + IIO_PH, }; enum iio_modifier { -- cgit v1.2.3 From 27dec00ecf2dfc830c6a407a9870776ea8efabcb Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Tue, 26 Jan 2016 18:34:31 -0800 Subject: iio: chemical: add Atlas pH-SM sensor support Add support for the Atlas Scientific pH-SM chemical sensor that can detect pH levels of solutions in the range of 0-14. Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- .../bindings/iio/chemical/atlas,ph-sm.txt | 22 + drivers/iio/chemical/Kconfig | 13 + drivers/iio/chemical/Makefile | 1 + drivers/iio/chemical/atlas-ph-sensor.c | 511 +++++++++++++++++++++ 4 files changed, 547 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/chemical/atlas,ph-sm.txt create mode 100644 drivers/iio/chemical/atlas-ph-sensor.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/iio/chemical/atlas,ph-sm.txt b/Documentation/devicetree/bindings/iio/chemical/atlas,ph-sm.txt new file mode 100644 index 000000000000..cffa1907463a --- /dev/null +++ b/Documentation/devicetree/bindings/iio/chemical/atlas,ph-sm.txt @@ -0,0 +1,22 @@ +* Atlas Scientific pH-SM OEM sensor + +http://www.atlas-scientific.com/_files/_datasheets/_oem/pH_oem_datasheet.pdf + +Required properties: + + - compatible: must be "atlas,ph-sm" + - reg: the I2C address of the sensor + - interrupt-parent: should be the phandle for the interrupt controller + - interrupts: the sole interrupt generated by the device + + Refer to interrupt-controller/interrupts.txt for generic interrupt client + node bindings. + +Example: + +atlas@65 { + compatible = "atlas,ph-sm"; + reg = <0x65>; + interrupt-parent = <&gpio1>; + interrupts = <16 2>; +}; diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig index f16de61be46d..ce7cd1370f74 100644 --- a/drivers/iio/chemical/Kconfig +++ b/drivers/iio/chemical/Kconfig @@ -4,6 +4,19 @@ menu "Chemical Sensors" +config ATLAS_PH_SENSOR + tristate "Atlas Scientific OEM pH-SM sensor" + depends on I2C + select REGMAP_I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say Y here to build I2C interface support for the Atlas + Scientific OEM pH-SM sensor. + + To compile this driver as module, choose M here: the + module will be called atlas-ph-sensor. + config IAQCORE tristate "AMS iAQ-Core VOC sensors" depends on I2C diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile index 167861fadfab..b02202b41289 100644 --- a/drivers/iio/chemical/Makefile +++ b/drivers/iio/chemical/Makefile @@ -3,5 +3,6 @@ # # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_ATLAS_PH_SENSOR) += atlas-ph-sensor.o obj-$(CONFIG_IAQCORE) += ams-iaq-core.o obj-$(CONFIG_VZ89X) += vz89x.o diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c new file mode 100644 index 000000000000..06cd49cbfae1 --- /dev/null +++ b/drivers/iio/chemical/atlas-ph-sensor.c @@ -0,0 +1,511 @@ +/* + * atlas-ph-sensor.c - Support for Atlas Scientific OEM pH-SM sensor + * + * Copyright (C) 2015 Matt Ranostay + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ATLAS_REGMAP_NAME "atlas_ph_regmap" +#define ATLAS_DRV_NAME "atlas_ph" + +#define ATLAS_REG_DEV_TYPE 0x00 +#define ATLAS_REG_DEV_VERSION 0x01 + +#define ATLAS_REG_INT_CONTROL 0x04 +#define ATLAS_REG_INT_CONTROL_EN BIT(3) + +#define ATLAS_REG_PWR_CONTROL 0x06 + +#define ATLAS_REG_CALIB_STATUS 0x0d +#define ATLAS_REG_CALIB_STATUS_MASK 0x07 +#define ATLAS_REG_CALIB_STATUS_LOW BIT(0) +#define ATLAS_REG_CALIB_STATUS_MID BIT(1) +#define ATLAS_REG_CALIB_STATUS_HIGH BIT(2) + +#define ATLAS_REG_TEMP_DATA 0x0e +#define ATLAS_REG_PH_DATA 0x16 + +#define ATLAS_PH_INT_TIME_IN_US 450000 + +struct atlas_data { + struct i2c_client *client; + struct iio_trigger *trig; + struct regmap *regmap; + struct irq_work work; + + __be32 buffer[4]; /* 32-bit pH data + 32-bit pad + 64-bit timestamp */ +}; + +static const struct regmap_range atlas_volatile_ranges[] = { + regmap_reg_range(ATLAS_REG_INT_CONTROL, ATLAS_REG_INT_CONTROL), + regmap_reg_range(ATLAS_REG_CALIB_STATUS, ATLAS_REG_CALIB_STATUS), + regmap_reg_range(ATLAS_REG_TEMP_DATA, ATLAS_REG_TEMP_DATA + 4), + regmap_reg_range(ATLAS_REG_PH_DATA, ATLAS_REG_PH_DATA + 4), +}; + +static const struct regmap_access_table atlas_volatile_table = { + .yes_ranges = atlas_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(atlas_volatile_ranges), +}; + +static const struct regmap_config atlas_regmap_config = { + .name = ATLAS_REGMAP_NAME, + + .reg_bits = 8, + .val_bits = 8, + + .volatile_table = &atlas_volatile_table, + .max_register = ATLAS_REG_PH_DATA + 4, + .cache_type = REGCACHE_FLAT, +}; + +static const struct iio_chan_spec atlas_channels[] = { + { + .type = IIO_PH, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 'u', + .realbits = 32, + .storagebits = 32, + .endianness = IIO_BE, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(1), + { + .type = IIO_TEMP, + .address = ATLAS_REG_TEMP_DATA, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .output = 1, + .scan_index = -1 + }, +}; + +static int atlas_set_powermode(struct atlas_data *data, int on) +{ + return regmap_write(data->regmap, ATLAS_REG_PWR_CONTROL, on); +} + +static int atlas_set_interrupt(struct atlas_data *data, bool state) +{ + return regmap_update_bits(data->regmap, ATLAS_REG_INT_CONTROL, + ATLAS_REG_INT_CONTROL_EN, + state ? ATLAS_REG_INT_CONTROL_EN : 0); +} + +static int atlas_buffer_postenable(struct iio_dev *indio_dev) +{ + struct atlas_data *data = iio_priv(indio_dev); + int ret; + + ret = iio_triggered_buffer_postenable(indio_dev); + if (ret) + return ret; + + ret = pm_runtime_get_sync(&data->client->dev); + if (ret < 0) { + pm_runtime_put_noidle(&data->client->dev); + return ret; + } + + return atlas_set_interrupt(data, true); +} + +static int atlas_buffer_predisable(struct iio_dev *indio_dev) +{ + struct atlas_data *data = iio_priv(indio_dev); + int ret; + + ret = iio_triggered_buffer_predisable(indio_dev); + if (ret) + return ret; + + ret = atlas_set_interrupt(data, false); + if (ret) + return ret; + + pm_runtime_mark_last_busy(&data->client->dev); + return pm_runtime_put_autosuspend(&data->client->dev); +} + +static const struct iio_trigger_ops atlas_interrupt_trigger_ops = { + .owner = THIS_MODULE, +}; + +static const struct iio_buffer_setup_ops atlas_buffer_setup_ops = { + .postenable = atlas_buffer_postenable, + .predisable = atlas_buffer_predisable, +}; + +static void atlas_work_handler(struct irq_work *work) +{ + struct atlas_data *data = container_of(work, struct atlas_data, work); + + iio_trigger_poll(data->trig); +} + +static irqreturn_t atlas_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct atlas_data *data = iio_priv(indio_dev); + int ret; + + ret = i2c_smbus_read_i2c_block_data(data->client, ATLAS_REG_PH_DATA, + sizeof(data->buffer[0]), (u8 *) &data->buffer); + + if (ret > 0) + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_get_time_ns()); + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static irqreturn_t atlas_interrupt_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct atlas_data *data = iio_priv(indio_dev); + + irq_work_queue(&data->work); + + return IRQ_HANDLED; +} + +static int atlas_read_ph_measurement(struct atlas_data *data, __be32 *val) +{ + struct device *dev = &data->client->dev; + int suspended = pm_runtime_suspended(dev); + int ret; + + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + pm_runtime_put_noidle(dev); + return ret; + } + + if (suspended) + usleep_range(ATLAS_PH_INT_TIME_IN_US, + ATLAS_PH_INT_TIME_IN_US + 100000); + + ret = regmap_bulk_read(data->regmap, ATLAS_REG_PH_DATA, + (u8 *) val, sizeof(*val)); + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +static int atlas_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct atlas_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: { + int ret; + __be32 reg; + + switch (chan->type) { + case IIO_TEMP: + ret = regmap_bulk_read(data->regmap, chan->address, + (u8 *) ®, sizeof(reg)); + break; + case IIO_PH: + mutex_lock(&indio_dev->mlock); + + if (iio_buffer_enabled(indio_dev)) + ret = -EBUSY; + else + ret = atlas_read_ph_measurement(data, ®); + + mutex_unlock(&indio_dev->mlock); + break; + default: + ret = -EINVAL; + } + + if (!ret) { + *val = be32_to_cpu(reg); + ret = IIO_VAL_INT; + } + return ret; + } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_TEMP: + *val = 1; /* 0.01 */ + *val2 = 100; + break; + case IIO_PH: + *val = 1; /* 0.001 */ + *val2 = 1000; + break; + default: + return -EINVAL; + } + return IIO_VAL_FRACTIONAL; + } + + return -EINVAL; +} + +static int atlas_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct atlas_data *data = iio_priv(indio_dev); + __be32 reg = cpu_to_be32(val); + + if (val2 != 0 || val < 0 || val > 20000) + return -EINVAL; + + if (mask != IIO_CHAN_INFO_RAW || chan->type != IIO_TEMP) + return -EINVAL; + + return regmap_bulk_write(data->regmap, chan->address, + ®, sizeof(reg)); +} + +static const struct iio_info atlas_info = { + .driver_module = THIS_MODULE, + .read_raw = atlas_read_raw, + .write_raw = atlas_write_raw, +}; + +static int atlas_check_calibration(struct atlas_data *data) +{ + struct device *dev = &data->client->dev; + int ret; + unsigned int val; + + ret = regmap_read(data->regmap, ATLAS_REG_CALIB_STATUS, &val); + if (ret) + return ret; + + if (!(val & ATLAS_REG_CALIB_STATUS_MASK)) { + dev_warn(dev, "device has not been calibrated\n"); + return 0; + } + + if (!(val & ATLAS_REG_CALIB_STATUS_LOW)) + dev_warn(dev, "device missing low point calibration\n"); + + if (!(val & ATLAS_REG_CALIB_STATUS_MID)) + dev_warn(dev, "device missing mid point calibration\n"); + + if (!(val & ATLAS_REG_CALIB_STATUS_HIGH)) + dev_warn(dev, "device missing high point calibration\n"); + + return 0; +}; + +static int atlas_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct atlas_data *data; + struct iio_trigger *trig; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + indio_dev->info = &atlas_info; + indio_dev->name = ATLAS_DRV_NAME; + indio_dev->channels = atlas_channels; + indio_dev->num_channels = ARRAY_SIZE(atlas_channels); + indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE; + indio_dev->dev.parent = &client->dev; + + trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", + indio_dev->name, indio_dev->id); + + if (!trig) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + data->trig = trig; + trig->dev.parent = indio_dev->dev.parent; + trig->ops = &atlas_interrupt_trigger_ops; + iio_trigger_set_drvdata(trig, indio_dev); + + i2c_set_clientdata(client, indio_dev); + + data->regmap = devm_regmap_init_i2c(client, &atlas_regmap_config); + if (IS_ERR(data->regmap)) { + dev_err(&client->dev, "regmap initialization failed\n"); + return PTR_ERR(data->regmap); + } + + ret = pm_runtime_set_active(&client->dev); + if (ret) + return ret; + + if (client->irq <= 0) { + dev_err(&client->dev, "no valid irq defined\n"); + return -EINVAL; + } + + ret = atlas_check_calibration(data); + if (ret) + return ret; + + ret = iio_trigger_register(trig); + if (ret) { + dev_err(&client->dev, "failed to register trigger\n"); + return ret; + } + + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + &atlas_trigger_handler, &atlas_buffer_setup_ops); + if (ret) { + dev_err(&client->dev, "cannot setup iio trigger\n"); + goto unregister_trigger; + } + + init_irq_work(&data->work, atlas_work_handler); + + /* interrupt pin toggles on new conversion */ + ret = devm_request_threaded_irq(&client->dev, client->irq, + NULL, atlas_interrupt_handler, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "atlas_irq", + indio_dev); + if (ret) { + dev_err(&client->dev, "request irq (%d) failed\n", client->irq); + goto unregister_buffer; + } + + ret = atlas_set_powermode(data, 1); + if (ret) { + dev_err(&client->dev, "cannot power device on"); + goto unregister_buffer; + } + + pm_runtime_enable(&client->dev); + pm_runtime_set_autosuspend_delay(&client->dev, 2500); + pm_runtime_use_autosuspend(&client->dev); + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&client->dev, "unable to register device\n"); + goto unregister_pm; + } + + return 0; + +unregister_pm: + pm_runtime_disable(&client->dev); + atlas_set_powermode(data, 0); + +unregister_buffer: + iio_triggered_buffer_cleanup(indio_dev); + +unregister_trigger: + iio_trigger_unregister(data->trig); + + return ret; +} + +static int atlas_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct atlas_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + iio_trigger_unregister(data->trig); + + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + pm_runtime_put_noidle(&client->dev); + + return atlas_set_powermode(data, 0); +} + +#ifdef CONFIG_PM +static int atlas_runtime_suspend(struct device *dev) +{ + struct atlas_data *data = + iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + + return atlas_set_powermode(data, 0); +} + +static int atlas_runtime_resume(struct device *dev) +{ + struct atlas_data *data = + iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + + return atlas_set_powermode(data, 1); +} +#endif + +static const struct dev_pm_ops atlas_pm_ops = { + SET_RUNTIME_PM_OPS(atlas_runtime_suspend, + atlas_runtime_resume, NULL) +}; + +static const struct i2c_device_id atlas_id[] = { + { "atlas-ph-sm", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, atlas_id); + +static const struct of_device_id atlas_dt_ids[] = { + { .compatible = "atlas,ph-sm" }, + { } +}; +MODULE_DEVICE_TABLE(of, atlas_dt_ids); + +static struct i2c_driver atlas_driver = { + .driver = { + .name = ATLAS_DRV_NAME, + .of_match_table = of_match_ptr(atlas_dt_ids), + .pm = &atlas_pm_ops, + }, + .probe = atlas_probe, + .remove = atlas_remove, + .id_table = atlas_id, +}; +module_i2c_driver(atlas_driver); + +MODULE_AUTHOR("Matt Ranostay "); +MODULE_DESCRIPTION("Atlas Scientific pH-SM sensor"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 8a695db01dc2b07959628626bc3810c4c6ff2681 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Tue, 19 Jan 2016 08:57:48 -0700 Subject: dmaengine: IOATDMA: fix timer code that continues to restart channels during idle The timer_event() function seems to have a bug where it ends up marking the last entry as non-responding and eventually attempts to restart the channel. This also continuously happen when idle. What needs to happen is for us to make sure there are no descriptors active and then handle that case properly. We should only hit the "cleanup" stage if there are still active descriptors. Signed-off-by: Dave Jiang Signed-off-by: Vinod Koul --- drivers/dma/ioat/dma.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index 1d5df2ef148b..21539d5c54c3 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -861,32 +861,42 @@ void ioat_timer_event(unsigned long data) return; } + spin_lock_bh(&ioat_chan->cleanup_lock); + + /* handle the no-actives case */ + if (!ioat_ring_active(ioat_chan)) { + spin_lock_bh(&ioat_chan->prep_lock); + check_active(ioat_chan); + spin_unlock_bh(&ioat_chan->prep_lock); + spin_unlock_bh(&ioat_chan->cleanup_lock); + return; + } + /* if we haven't made progress and we have already * acknowledged a pending completion once, then be more * forceful with a restart */ - spin_lock_bh(&ioat_chan->cleanup_lock); if (ioat_cleanup_preamble(ioat_chan, &phys_complete)) __cleanup(ioat_chan, phys_complete); else if (test_bit(IOAT_COMPLETION_ACK, &ioat_chan->state)) { + u32 chanerr; + + chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET); + dev_warn(to_dev(ioat_chan), "Restarting channel...\n"); + dev_warn(to_dev(ioat_chan), "CHANSTS: %#Lx CHANERR: %#x\n", + status, chanerr); + dev_warn(to_dev(ioat_chan), "Active descriptors: %d\n", + ioat_ring_active(ioat_chan)); + spin_lock_bh(&ioat_chan->prep_lock); ioat_restart_channel(ioat_chan); spin_unlock_bh(&ioat_chan->prep_lock); spin_unlock_bh(&ioat_chan->cleanup_lock); return; - } else { + } else set_bit(IOAT_COMPLETION_ACK, &ioat_chan->state); - mod_timer(&ioat_chan->timer, jiffies + COMPLETION_TIMEOUT); - } - - if (ioat_ring_active(ioat_chan)) - mod_timer(&ioat_chan->timer, jiffies + COMPLETION_TIMEOUT); - else { - spin_lock_bh(&ioat_chan->prep_lock); - check_active(ioat_chan); - spin_unlock_bh(&ioat_chan->prep_lock); - } + mod_timer(&ioat_chan->timer, jiffies + COMPLETION_TIMEOUT); spin_unlock_bh(&ioat_chan->cleanup_lock); } -- cgit v1.2.3 From 1c319e781e0ecc48228081558f38044a11c7a76e Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Wed, 27 Jan 2016 21:35:00 +0800 Subject: intel-hid: fix incorrect entries in intel_hid_keymap intel_hid_keymap contains a duplicate entry for KEY_HOME and an incorrect HID index for KEY_PAGEDOWN Reported-by: Pavel Bludov Signed-off-by: Alex Hung --- drivers/platform/x86/intel-hid.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index 20f0ad9bb9f3..e20f23e04c24 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -41,8 +41,7 @@ static const struct key_entry intel_hid_keymap[] = { { KE_KEY, 4, { KEY_HOME } }, { KE_KEY, 5, { KEY_END } }, { KE_KEY, 6, { KEY_PAGEUP } }, - { KE_KEY, 4, { KEY_PAGEDOWN } }, - { KE_KEY, 4, { KEY_HOME } }, + { KE_KEY, 7, { KEY_PAGEDOWN } }, { KE_KEY, 8, { KEY_RFKILL } }, { KE_KEY, 9, { KEY_POWER } }, { KE_KEY, 11, { KEY_SLEEP } }, -- cgit v1.2.3 From c2472d0bbcec8920ac9ce4393894bf7844275e81 Mon Sep 17 00:00:00 2001 From: Adriana Reus Date: Sat, 30 Jan 2016 11:43:45 +0200 Subject: iio: inv_mpu6050: Remove unused parameter The inv_check_and_setup_chip function does not use the i2c_device_id parameter. Therefore remove it. Signed-off-by: Adriana Reus Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index f0e06093b5e8..0852b7fa777e 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -727,8 +727,7 @@ static const struct iio_info mpu_info = { /** * inv_check_and_setup_chip() - check and setup chip. */ -static int inv_check_and_setup_chip(struct inv_mpu6050_state *st, - const struct i2c_device_id *id) +static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) { int result; @@ -795,7 +794,7 @@ static int inv_mpu_probe(struct i2c_client *client, if (pdata) st->plat_data = *pdata; /* power is turned on inside check chip type*/ - result = inv_check_and_setup_chip(st, id); + result = inv_check_and_setup_chip(st); if (result) return result; -- cgit v1.2.3 From b1d353ad3d5835b16724653b33c05124e1b5acf1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 26 Jan 2016 12:24:25 +0300 Subject: intel_scu_ipcutil: underflow in scu_reg_access() "count" is controlled by the user and it can be negative. Let's prevent that by making it unsigned. You have to have CAP_SYS_RAWIO to call this function so the bug is not as serious as it could be. Fixes: 5369c02d951a ('intel_scu_ipc: Utility driver for intel scu ipc') Signed-off-by: Dan Carpenter Cc: stable@vger.kernel.org Signed-off-by: Darren Hart --- drivers/platform/x86/intel_scu_ipcutil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/intel_scu_ipcutil.c b/drivers/platform/x86/intel_scu_ipcutil.c index 02bc5a6343c3..aa454241489c 100644 --- a/drivers/platform/x86/intel_scu_ipcutil.c +++ b/drivers/platform/x86/intel_scu_ipcutil.c @@ -49,7 +49,7 @@ struct scu_ipc_data { static int scu_reg_access(u32 cmd, struct scu_ipc_data *data) { - int count = data->count; + unsigned int count = data->count; if (count == 0 || count == 3 || count > 4) return -EINVAL; -- cgit v1.2.3 From 3955525d5d17118ed8900e9e79753057120eb02a Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 14 Jan 2016 09:39:21 +0200 Subject: iwlwifi: pcie: buffer packets to avoid overflowing Tx queues When the Tx queues are full above a threshold, we immediately stop the mac80211's queue to stop getting new packets. This worked until TSO was enabled. With TSO, one single packet from mac80211 can use many descriptors since a large send needs to be split into several segments. This means that stopping mac80211's queues is not enough and we also need to ensure that we don't overflow the Tx queues with one single packet from mac80211. Add code to transport layer to do just that. Stop mac80211's queue as soon as the queue is full above the same threshold as before, and keep pushing the current packet along with its segments on the queue, but check that we don't overflow. If that would happen, buffer the segments, and send them when there is room in the Tx queue again. Of course, we first need to send the buffered segments and only then, wake up mac80211's queues. Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 1 + drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 69 +++++++++++++++++++--- 2 files changed, 62 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index cc3888e2700d..2d8b415fa55e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -280,6 +280,7 @@ struct iwl_txq { bool ampdu; bool block; unsigned long wd_timeout; + struct sk_buff_head overflow_q; }; static inline dma_addr_t diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 5262028b5505..b0b0fd9e2eff 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -571,6 +571,7 @@ static int iwl_pcie_txq_init(struct iwl_trans *trans, struct iwl_txq *txq, return ret; spin_lock_init(&txq->lock); + __skb_queue_head_init(&txq->overflow_q); /* * Tell nic where to find circular buffer of Tx Frame Descriptors for @@ -621,6 +622,13 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) q->read_ptr = iwl_queue_inc_wrap(q->read_ptr); } txq->active = false; + + while (!skb_queue_empty(&txq->overflow_q)) { + struct sk_buff *skb = __skb_dequeue(&txq->overflow_q); + + iwl_op_mode_free_skb(trans->op_mode, skb); + } + spin_unlock_bh(&txq->lock); /* just in case - this queue may have been stopped */ @@ -1052,8 +1060,41 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, iwl_pcie_txq_progress(txq); - if (iwl_queue_space(&txq->q) > txq->q.low_mark) - iwl_wake_queue(trans, txq); + if (iwl_queue_space(&txq->q) > txq->q.low_mark && + test_bit(txq_id, trans_pcie->queue_stopped)) { + struct sk_buff_head skbs; + + __skb_queue_head_init(&skbs); + skb_queue_splice_init(&txq->overflow_q, &skbs); + + /* + * This is tricky: we are in reclaim path which is non + * re-entrant, so noone will try to take the access the + * txq data from that path. We stopped tx, so we can't + * have tx as well. Bottom line, we can unlock and re-lock + * later. + */ + spin_unlock_bh(&txq->lock); + + while (!skb_queue_empty(&skbs)) { + struct sk_buff *skb = __skb_dequeue(&skbs); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + u8 dev_cmd_idx = IWL_TRANS_FIRST_DRIVER_DATA + 1; + struct iwl_device_cmd *dev_cmd = + info->driver_data[dev_cmd_idx]; + + /* + * Note that we can very well be overflowing again. + * In that case, iwl_queue_space will be small again + * and we won't wake mac80211's queue. + */ + iwl_trans_pcie_tx(trans, skb, dev_cmd, txq_id); + } + spin_lock_bh(&txq->lock); + + if (iwl_queue_space(&txq->q) > txq->q.low_mark) + iwl_wake_queue(trans, txq); + } if (q->read_ptr == q->write_ptr) { IWL_DEBUG_RPM(trans, "Q %d - last tx reclaimed\n", q->id); @@ -2161,6 +2202,8 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, csum = skb_checksum(skb, offs, skb->len - offs, 0); *(__sum16 *)(skb->data + csum_offs) = csum_fold(csum); + + skb->ip_summed = CHECKSUM_UNNECESSARY; } if (skb_is_nonlinear(skb) && @@ -2177,6 +2220,22 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, spin_lock(&txq->lock); + if (iwl_queue_space(q) < q->high_mark) { + iwl_stop_queue(trans, txq); + + /* don't put the packet on the ring, if there is no room */ + if (unlikely(iwl_queue_space(q) < 3)) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + + info->driver_data[IWL_TRANS_FIRST_DRIVER_DATA + 1] = + dev_cmd; + __skb_queue_tail(&txq->overflow_q, skb); + + spin_unlock(&txq->lock); + return 0; + } + } + /* In AGG mode, the index in the ring must correspond to the WiFi * sequence number. This is a HW requirements to help the SCD to parse * the BA. @@ -2281,12 +2340,6 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, * At this point the frame is "transmitted" successfully * and we will get a TX status notification eventually. */ - if (iwl_queue_space(q) < q->high_mark) { - if (wait_write_ptr) - iwl_pcie_txq_inc_wr_ptr(trans, txq); - else - iwl_stop_queue(trans, txq); - } spin_unlock(&txq->lock); return 0; out_err: -- cgit v1.2.3 From 7848505416be4e96af14c3387775622d26a13146 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Mon, 14 Dec 2015 17:44:11 +0200 Subject: iwlwifi: pcie: add infrastructure for multi-queue rx The 9000 series devices will support multi rx queues. Current code has one static rx queue - change it to allocate a number of queues per the device capability (pre-9000 devices have the number of rx queues set to one). Subsequent generalizations are: Change the code to access an explicit numbered rx queue only when the queue number is known - when handling interrupt, when accessing the default queue and when iterating the queues. The rest of the functions will receive the rx queue as a pointer. Generalize the warning in allocation failure to consider the allocator status instead of a single rx queue status. Move the rx initial pool of memory buffers to be shared among all the queues and allocated to the default queue on init. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 8 +- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 264 +++++++++++---------- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 73 ++++-- 3 files changed, 191 insertions(+), 154 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 2d8b415fa55e..11ad87fca67a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -57,7 +57,7 @@ #define RX_POST_REQ_ALLOC 2 #define RX_CLAIM_REQ_ALLOC 8 #define RX_POOL_SIZE ((RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC) * RX_NUM_QUEUES) -#define RX_LOW_WATERMARK 8 +#define RX_PENDING_WATERMARK 16 struct iwl_host_cmd; @@ -103,7 +103,6 @@ struct isr_statistics { * @rb_stts: driver's pointer to receive buffer status * @rb_stts_dma: bus address of receive buffer status * @lock: - * @pool: initial pool of iwl_rx_mem_buffer for the queue * @queue: actual rx queue * * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers @@ -122,7 +121,6 @@ struct iwl_rxq { struct iwl_rb_status *rb_stts; dma_addr_t rb_stts_dma; spinlock_t lock; - struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE]; struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; }; @@ -298,6 +296,7 @@ struct iwl_tso_hdr_page { /** * struct iwl_trans_pcie - PCIe transport specific data * @rxq: all the RX queue data + * @rx_pool: initial pool of iwl_rx_mem_buffer for all the queues * @rba: allocator for RX replenishing * @drv - pointer to iwl_drv * @trans: pointer to the generic transport area @@ -324,7 +323,8 @@ struct iwl_tso_hdr_page { * @fw_mon_size: size of the buffer for the firmware monitor */ struct iwl_trans_pcie { - struct iwl_rxq rxq; + struct iwl_rxq *rxq; + struct iwl_rx_mem_buffer rx_pool[RX_QUEUE_SIZE]; struct iwl_rb_allocator rba; struct iwl_trans *trans; struct iwl_drv *drv; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index ccafbd8cf4b3..f557f3dc4db8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -173,10 +173,9 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans) /* * iwl_pcie_rxq_inc_wr_ptr - Update the write pointer for the RX queue */ -static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans) +static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, + struct iwl_rxq *rxq) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; u32 reg; lockdep_assert_held(&rxq->lock); @@ -207,18 +206,18 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans) static void iwl_pcie_rxq_check_wrptr(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; - - spin_lock(&rxq->lock); - - if (!rxq->need_update) - goto exit_unlock; + int i; - iwl_pcie_rxq_inc_wr_ptr(trans); - rxq->need_update = false; + for (i = 0; i < trans->num_rx_queues; i++) { + struct iwl_rxq *rxq = &trans_pcie->rxq[i]; - exit_unlock: - spin_unlock(&rxq->lock); + if (!rxq->need_update) + continue; + spin_lock(&rxq->lock); + iwl_pcie_rxq_inc_wr_ptr(trans, rxq); + rxq->need_update = false; + spin_unlock(&rxq->lock); + } } /* @@ -232,10 +231,8 @@ static void iwl_pcie_rxq_check_wrptr(struct iwl_trans *trans) * also updates the memory address in the firmware to reference the new * target buffer. */ -static void iwl_pcie_rxq_restock(struct iwl_trans *trans) +static void iwl_pcie_rxq_restock(struct iwl_trans *trans, struct iwl_rxq *rxq) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; struct iwl_rx_mem_buffer *rxb; /* @@ -272,7 +269,7 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans) * Increment device's write pointer in multiples of 8. */ if (rxq->write_actual != (rxq->write & ~0x7)) { spin_lock(&rxq->lock); - iwl_pcie_rxq_inc_wr_ptr(trans); + iwl_pcie_rxq_inc_wr_ptr(trans, rxq); spin_unlock(&rxq->lock); } } @@ -285,13 +282,9 @@ static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans, gfp_t priority) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; struct page *page; gfp_t gfp_mask = priority; - if (rxq->free_count > RX_LOW_WATERMARK) - gfp_mask |= __GFP_NOWARN; - if (trans_pcie->rx_page_order > 0) gfp_mask |= __GFP_COMP; @@ -301,16 +294,13 @@ static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans, if (net_ratelimit()) IWL_DEBUG_INFO(trans, "alloc_pages failed, order: %d\n", trans_pcie->rx_page_order); - /* Issue an error if the hardware has consumed more than half - * of its free buffer list and we don't have enough - * pre-allocated buffers. + /* + * Issue an error if we don't have enough pre-allocated + * buffers. ` */ - if (rxq->free_count <= RX_LOW_WATERMARK && - iwl_rxq_space(rxq) > (RX_QUEUE_SIZE / 2) && - net_ratelimit()) + if (!(gfp_mask & __GFP_NOWARN) && net_ratelimit()) IWL_CRIT(trans, - "Failed to alloc_pages with GFP_KERNEL. Only %u free buffers remaining.\n", - rxq->free_count); + "Failed to alloc_pages\n"); return NULL; } return page; @@ -325,10 +315,10 @@ static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans, * iwl_pcie_rxq_restock. The latter function will update the HW to use the newly * allocated buffers. */ -static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority) +static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority, + struct iwl_rxq *rxq) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; struct iwl_rx_mem_buffer *rxb; struct page *page; @@ -386,40 +376,23 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority) } } -static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans) +static void iwl_pcie_free_rbs_pool(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; int i; - lockdep_assert_held(&rxq->lock); - for (i = 0; i < RX_QUEUE_SIZE; i++) { - if (!rxq->pool[i].page) + if (!trans_pcie->rx_pool[i].page) continue; - dma_unmap_page(trans->dev, rxq->pool[i].page_dma, + dma_unmap_page(trans->dev, trans_pcie->rx_pool[i].page_dma, PAGE_SIZE << trans_pcie->rx_page_order, DMA_FROM_DEVICE); - __free_pages(rxq->pool[i].page, trans_pcie->rx_page_order); - rxq->pool[i].page = NULL; + __free_pages(trans_pcie->rx_pool[i].page, + trans_pcie->rx_page_order); + trans_pcie->rx_pool[i].page = NULL; } } -/* - * iwl_pcie_rx_replenish - Move all used buffers from rx_used to rx_free - * - * When moving to rx_free an page is allocated for the slot. - * - * Also restock the Rx queue via iwl_pcie_rxq_restock. - * This is called only during initialization - */ -static void iwl_pcie_rx_replenish(struct iwl_trans *trans) -{ - iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL); - - iwl_pcie_rxq_restock(trans); -} - /* * iwl_pcie_rx_allocator - Allocates pages in the background for RX queues * @@ -444,6 +417,11 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) while (pending) { int i; struct list_head local_allocated; + gfp_t gfp_mask = GFP_KERNEL; + + /* Do not post a warning if there are only a few requests */ + if (pending < RX_PENDING_WATERMARK) + gfp_mask |= __GFP_NOWARN; INIT_LIST_HEAD(&local_allocated); @@ -463,7 +441,7 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) BUG_ON(rxb->page); /* Alloc a new receive buffer */ - page = iwl_pcie_rx_alloc_page(trans, GFP_KERNEL); + page = iwl_pcie_rx_alloc_page(trans, gfp_mask); if (!page) continue; rxb->page = page; @@ -561,38 +539,60 @@ static void iwl_pcie_rx_allocator_work(struct work_struct *data) static int iwl_pcie_rx_alloc(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; struct iwl_rb_allocator *rba = &trans_pcie->rba; struct device *dev = trans->dev; + int i; + + if (WARN_ON(trans_pcie->rxq)) + return -EINVAL; - memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq)); + trans_pcie->rxq = kcalloc(trans->num_rx_queues, sizeof(struct iwl_rxq), + GFP_KERNEL); + if (!trans_pcie->rxq) + return -EINVAL; - spin_lock_init(&rxq->lock); spin_lock_init(&rba->lock); - if (WARN_ON(rxq->bd || rxq->rb_stts)) - return -EINVAL; + for (i = 0; i < trans->num_rx_queues; i++) { + struct iwl_rxq *rxq = &trans_pcie->rxq[i]; - /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */ - rxq->bd = dma_zalloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, + spin_lock_init(&rxq->lock); + /* + * Allocate the circular buffer of Read Buffer Descriptors + * (RBDs) + */ + rxq->bd = dma_zalloc_coherent(dev, + sizeof(__le32) * RX_QUEUE_SIZE, &rxq->bd_dma, GFP_KERNEL); - if (!rxq->bd) - goto err_bd; + if (!rxq->bd) + goto err; - /*Allocate the driver's pointer to receive buffer status */ - rxq->rb_stts = dma_zalloc_coherent(dev, sizeof(*rxq->rb_stts), - &rxq->rb_stts_dma, GFP_KERNEL); - if (!rxq->rb_stts) - goto err_rb_stts; + /*Allocate the driver's pointer to receive buffer status */ + rxq->rb_stts = dma_zalloc_coherent(dev, sizeof(*rxq->rb_stts), + &rxq->rb_stts_dma, + GFP_KERNEL); + if (!rxq->rb_stts) + goto err; + } return 0; -err_rb_stts: - dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, - rxq->bd, rxq->bd_dma); - rxq->bd_dma = 0; - rxq->bd = NULL; -err_bd: +err: + for (i = 0; i < trans->num_rx_queues; i++) { + struct iwl_rxq *rxq = &trans_pcie->rxq[i]; + + if (rxq->bd) + dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, + rxq->bd, rxq->bd_dma); + rxq->bd_dma = 0; + rxq->bd = NULL; + + if (rxq->rb_stts) + dma_free_coherent(trans->dev, + sizeof(struct iwl_rb_status), + rxq->rb_stts, rxq->rb_stts_dma); + } + kfree(trans_pcie->rxq); return -ENOMEM; } @@ -661,17 +661,12 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq) { - int i; - lockdep_assert_held(&rxq->lock); INIT_LIST_HEAD(&rxq->rx_free); INIT_LIST_HEAD(&rxq->rx_used); rxq->free_count = 0; rxq->used_count = 0; - - for (i = 0; i < RX_QUEUE_SIZE; i++) - list_add(&rxq->pool[i].list, &rxq->rx_used); } static void iwl_pcie_rx_init_rba(struct iwl_rb_allocator *rba) @@ -709,15 +704,16 @@ static void iwl_pcie_rx_free_rba(struct iwl_trans *trans) int iwl_pcie_rx_init(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; + struct iwl_rxq *def_rxq; struct iwl_rb_allocator *rba = &trans_pcie->rba; int i, err; - if (!rxq->bd) { + if (!trans_pcie->rxq) { err = iwl_pcie_rx_alloc(trans); if (err) return err; } + def_rxq = trans_pcie->rxq; if (!rba->alloc_wq) rba->alloc_wq = alloc_workqueue("rb_allocator", WQ_HIGHPRI | WQ_UNBOUND, 1); @@ -731,29 +727,42 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) iwl_pcie_rx_init_rba(rba); spin_unlock(&rba->lock); - spin_lock(&rxq->lock); - /* free all first - we might be reconfigured for a different size */ - iwl_pcie_rxq_free_rbs(trans); - iwl_pcie_rx_init_rxb_lists(rxq); + iwl_pcie_free_rbs_pool(trans); for (i = 0; i < RX_QUEUE_SIZE; i++) - rxq->queue[i] = NULL; + def_rxq->queue[i] = NULL; - /* Set us so that we have processed and used all buffers, but have - * not restocked the Rx queue with fresh buffers */ - rxq->read = rxq->write = 0; - rxq->write_actual = 0; - memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); - spin_unlock(&rxq->lock); + for (i = 0; i < trans->num_rx_queues; i++) { + struct iwl_rxq *rxq = &trans_pcie->rxq[i]; - iwl_pcie_rx_replenish(trans); + spin_lock(&rxq->lock); + /* + * Set read write pointer to reflect that we have processed + * and used all buffers, but have not restocked the Rx queue + * with fresh buffers + */ + rxq->read = 0; + rxq->write = 0; + rxq->write_actual = 0; + memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); - iwl_pcie_rx_hw_init(trans, rxq); + iwl_pcie_rx_init_rxb_lists(rxq); - spin_lock(&rxq->lock); - iwl_pcie_rxq_inc_wr_ptr(trans); - spin_unlock(&rxq->lock); + spin_unlock(&rxq->lock); + } + + /* move the entire pool to the default queue ownership */ + for (i = 0; i < RX_QUEUE_SIZE; i++) + list_add(&trans_pcie->rx_pool[i].list, &def_rxq->rx_used); + + iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL, def_rxq); + iwl_pcie_rxq_restock(trans, def_rxq); + iwl_pcie_rx_hw_init(trans, def_rxq); + + spin_lock(&def_rxq->lock); + iwl_pcie_rxq_inc_wr_ptr(trans, def_rxq); + spin_unlock(&def_rxq->lock); return 0; } @@ -761,12 +770,14 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) void iwl_pcie_rx_free(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; struct iwl_rb_allocator *rba = &trans_pcie->rba; + int i; - /*if rxq->bd is NULL, it means that nothing has been allocated, - * exit now */ - if (!rxq->bd) { + /* + * if rxq is NULL, it means that nothing has been allocated, + * exit now + */ + if (!trans_pcie->rxq) { IWL_DEBUG_INFO(trans, "Free NULL rx context\n"); return; } @@ -781,23 +792,28 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) iwl_pcie_rx_free_rba(trans); spin_unlock(&rba->lock); - spin_lock(&rxq->lock); - iwl_pcie_rxq_free_rbs(trans); - spin_unlock(&rxq->lock); - - dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE, - rxq->bd, rxq->bd_dma); - rxq->bd_dma = 0; - rxq->bd = NULL; + iwl_pcie_free_rbs_pool(trans); + + for (i = 0; i < trans->num_rx_queues; i++) { + struct iwl_rxq *rxq = &trans_pcie->rxq[i]; + + if (rxq->bd) + dma_free_coherent(trans->dev, + sizeof(__le32) * RX_QUEUE_SIZE, + rxq->bd, rxq->bd_dma); + rxq->bd_dma = 0; + rxq->bd = NULL; + + if (rxq->rb_stts) + dma_free_coherent(trans->dev, + sizeof(struct iwl_rb_status), + rxq->rb_stts, rxq->rb_stts_dma); + else + IWL_DEBUG_INFO(trans, + "Free rxq->rb_stts which is NULL\n"); + } - if (rxq->rb_stts) - dma_free_coherent(trans->dev, - sizeof(struct iwl_rb_status), - rxq->rb_stts, rxq->rb_stts_dma); - else - IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n"); - rxq->rb_stts_dma = 0; - rxq->rb_stts = NULL; + kfree(trans_pcie->rxq); } /* @@ -841,11 +857,11 @@ static void iwl_pcie_rx_reuse_rbd(struct iwl_trans *trans, } static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, + struct iwl_rxq *rxq, struct iwl_rx_mem_buffer *rxb, bool emergency) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; bool page_stolen = false; int max_len = PAGE_SIZE << trans_pcie->rx_page_order; @@ -975,7 +991,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, static void iwl_pcie_rx_handle(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; + struct iwl_rxq *rxq = &trans_pcie->rxq[0]; u32 r, i, j, count = 0; bool emergency = false; @@ -1000,7 +1016,7 @@ restart: rxq->queue[i] = NULL; IWL_DEBUG_RX(trans, "rxbuf: HW = %d, SW = %d\n", r, i); - iwl_pcie_rx_handle_rb(trans, rxb, emergency); + iwl_pcie_rx_handle_rb(trans, rxq, rxb, emergency); i = (i + 1) & RX_QUEUE_MASK; @@ -1043,7 +1059,7 @@ restart: if (rxq->used_count < RX_QUEUE_SIZE / 3) emergency = false; spin_unlock(&rxq->lock); - iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC); + iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC, rxq); spin_lock(&rxq->lock); } } @@ -1055,7 +1071,7 @@ restart: if (rxq->free_count >= RX_CLAIM_REQ_ALLOC) { rxq->read = i; spin_unlock(&rxq->lock); - iwl_pcie_rxq_restock(trans); + iwl_pcie_rxq_restock(trans, rxq); goto restart; } } @@ -1077,7 +1093,7 @@ restart: * will be restocked by the next call of iwl_pcie_rxq_restock. */ if (unlikely(emergency && count)) - iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC); + iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC, rxq); if (trans_pcie->napi.poll) napi_gro_flush(&trans_pcie->napi, false); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index d60a467a983c..0302aede4fdf 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2001,29 +2001,48 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, { struct iwl_trans *trans = file->private_data; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; - char buf[256]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", - rxq->read); - pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", - rxq->write); - pos += scnprintf(buf + pos, bufsz - pos, "write_actual: %u\n", - rxq->write_actual); - pos += scnprintf(buf + pos, bufsz - pos, "need_update: %d\n", - rxq->need_update); - pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", - rxq->free_count); - if (rxq->rb_stts) { - pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", - le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); - } else { - pos += scnprintf(buf + pos, bufsz - pos, - "closed_rb_num: Not Allocated\n"); + char *buf; + int pos = 0, i, ret; + size_t bufsz = sizeof(buf); + + bufsz = sizeof(char) * 121 * trans->num_rx_queues; + + if (!trans_pcie->rxq) + return -EAGAIN; + + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + for (i = 0; i < trans->num_rx_queues && pos < bufsz; i++) { + struct iwl_rxq *rxq = &trans_pcie->rxq[i]; + + pos += scnprintf(buf + pos, bufsz - pos, "queue#: %2d\n", + i); + pos += scnprintf(buf + pos, bufsz - pos, "\tread: %u\n", + rxq->read); + pos += scnprintf(buf + pos, bufsz - pos, "\twrite: %u\n", + rxq->write); + pos += scnprintf(buf + pos, bufsz - pos, "\twrite_actual: %u\n", + rxq->write_actual); + pos += scnprintf(buf + pos, bufsz - pos, "\tneed_update: %2d\n", + rxq->need_update); + pos += scnprintf(buf + pos, bufsz - pos, "\tfree_count: %u\n", + rxq->free_count); + if (rxq->rb_stts) { + pos += scnprintf(buf + pos, bufsz - pos, + "\tclosed_rb_num: %u\n", + le16_to_cpu(rxq->rb_stts->closed_rb_num) & + 0x0FFF); + } else { + pos += scnprintf(buf + pos, bufsz - pos, + "\tclosed_rb_num: Not Allocated\n"); + } } - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + + return ret; } static ssize_t iwl_dbgfs_interrupt_read(struct file *file, @@ -2188,7 +2207,8 @@ static u32 iwl_trans_pcie_dump_rbs(struct iwl_trans *trans, { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int max_len = PAGE_SIZE << trans_pcie->rx_page_order; - struct iwl_rxq *rxq = &trans_pcie->rxq; + /* Dump RBs is supported only for pre-9000 devices (1 queue) */ + struct iwl_rxq *rxq = &trans_pcie->rxq[0]; u32 i, r, j, rb_len = 0; spin_lock(&rxq->lock); @@ -2438,11 +2458,12 @@ static struct iwl_trans_dump_data len += sizeof(*data) + (FH_MEM_UPPER_BOUND - FH_MEM_LOWER_BOUND); if (dump_rbs) { + /* Dump RBs is supported only for pre-9000 devices (1 queue) */ + struct iwl_rxq *rxq = &trans_pcie->rxq[0]; /* RBs */ - num_rbs = le16_to_cpu(ACCESS_ONCE( - trans_pcie->rxq.rb_stts->closed_rb_num)) + num_rbs = le16_to_cpu(ACCESS_ONCE(rxq->rb_stts->closed_rb_num)) & 0x0FFF; - num_rbs = (num_rbs - trans_pcie->rxq.read) & RX_QUEUE_MASK; + num_rbs = (num_rbs - rxq->read) & RX_QUEUE_MASK; len += num_rbs * (sizeof(*data) + sizeof(struct iwl_fw_error_dump_rb) + (PAGE_SIZE << trans_pcie->rx_page_order)); -- cgit v1.2.3 From 7e502e5bc546a8d8be188fa019fe6fcdf02e3c87 Mon Sep 17 00:00:00 2001 From: Oren Givon Date: Mon, 25 Jan 2016 12:00:42 +0200 Subject: iwlwifi: fix name of ucode loaded for 8265 series Fix the name of the ucode being loaded for 8265 series to be: iwlwifi-8265-XX.ucode Signed-off-by: Oren Givon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-8000.c | 42 +++++++++++++++++++++------ drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 6 ++-- 2 files changed, 37 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c index c84a0299d43e..bce9b3420a13 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c @@ -7,6 +7,7 @@ * * Copyright(c) 2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * 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 @@ -70,12 +71,15 @@ /* Highest firmware API version supported */ #define IWL8000_UCODE_API_MAX 20 +#define IWL8265_UCODE_API_MAX 20 /* Oldest version we won't warn about */ #define IWL8000_UCODE_API_OK 13 +#define IWL8265_UCODE_API_OK 20 /* Lowest firmware API version supported */ #define IWL8000_UCODE_API_MIN 13 +#define IWL8265_UCODE_API_MIN 20 /* NVM versions */ #define IWL8000_NVM_VERSION 0x0a1d @@ -93,6 +97,10 @@ #define IWL8000_MODULE_FIRMWARE(api) \ IWL8000_FW_PRE "-" __stringify(api) ".ucode" +#define IWL8265_FW_PRE "iwlwifi-8265-" +#define IWL8265_MODULE_FIRMWARE(api) \ + IWL8265_FW_PRE __stringify(api) ".ucode" + #define NVM_HW_SECTION_NUM_FAMILY_8000 10 #define DEFAULT_NVM_FILE_FAMILY_8000B "nvmData-8000B" #define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C" @@ -144,10 +152,7 @@ static const struct iwl_tt_params iwl8000_tt_params = { .support_tx_backoff = true, }; -#define IWL_DEVICE_8000 \ - .ucode_api_max = IWL8000_UCODE_API_MAX, \ - .ucode_api_ok = IWL8000_UCODE_API_OK, \ - .ucode_api_min = IWL8000_UCODE_API_MIN, \ +#define IWL_DEVICE_8000_COMMON \ .device_family = IWL_DEVICE_FAMILY_8000, \ .max_inst_size = IWL60_RTC_INST_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \ @@ -167,10 +172,28 @@ static const struct iwl_tt_params iwl8000_tt_params = { .thermal_params = &iwl8000_tt_params, \ .apmg_not_supported = true +#define IWL_DEVICE_8000 \ + IWL_DEVICE_8000_COMMON, \ + .ucode_api_max = IWL8000_UCODE_API_MAX, \ + .ucode_api_ok = IWL8000_UCODE_API_OK, \ + .ucode_api_min = IWL8000_UCODE_API_MIN \ + +#define IWL_DEVICE_8260 \ + IWL_DEVICE_8000_COMMON, \ + .ucode_api_max = IWL8000_UCODE_API_MAX, \ + .ucode_api_ok = IWL8000_UCODE_API_OK, \ + .ucode_api_min = IWL8000_UCODE_API_MIN \ + +#define IWL_DEVICE_8265 \ + IWL_DEVICE_8000_COMMON, \ + .ucode_api_max = IWL8265_UCODE_API_MAX, \ + .ucode_api_ok = IWL8265_UCODE_API_OK, \ + .ucode_api_min = IWL8265_UCODE_API_MIN \ + const struct iwl_cfg iwl8260_2n_cfg = { .name = "Intel(R) Dual Band Wireless N 8260", .fw_name_pre = IWL8000_FW_PRE, - IWL_DEVICE_8000, + IWL_DEVICE_8260, .ht_params = &iwl8000_ht_params, .nvm_ver = IWL8000_NVM_VERSION, .nvm_calib_ver = IWL8000_TX_POWER_VERSION, @@ -179,7 +202,7 @@ const struct iwl_cfg iwl8260_2n_cfg = { const struct iwl_cfg iwl8260_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 8260", .fw_name_pre = IWL8000_FW_PRE, - IWL_DEVICE_8000, + IWL_DEVICE_8260, .ht_params = &iwl8000_ht_params, .nvm_ver = IWL8000_NVM_VERSION, .nvm_calib_ver = IWL8000_TX_POWER_VERSION, @@ -188,8 +211,8 @@ const struct iwl_cfg iwl8260_2ac_cfg = { const struct iwl_cfg iwl8265_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 8265", - .fw_name_pre = IWL8000_FW_PRE, - IWL_DEVICE_8000, + .fw_name_pre = IWL8265_FW_PRE, + IWL_DEVICE_8265, .ht_params = &iwl8000_ht_params, .nvm_ver = IWL8000_NVM_VERSION, .nvm_calib_ver = IWL8000_TX_POWER_VERSION, @@ -209,7 +232,7 @@ const struct iwl_cfg iwl4165_2ac_cfg = { const struct iwl_cfg iwl8260_2ac_sdio_cfg = { .name = "Intel(R) Dual Band Wireless-AC 8260", .fw_name_pre = IWL8000_FW_PRE, - IWL_DEVICE_8000, + IWL_DEVICE_8260, .ht_params = &iwl8000_ht_params, .nvm_ver = IWL8000_NVM_VERSION, .nvm_calib_ver = IWL8000_TX_POWER_VERSION, @@ -236,3 +259,4 @@ const struct iwl_cfg iwl4165_2ac_sdio_cfg = { }; MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK)); +MODULE_FIRMWARE(IWL8265_MODULE_FIRMWARE(IWL8265_UCODE_API_OK)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 7acb49075683..ab4c2a0470b2 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -243,8 +243,10 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) { char rev_step = 'A' + CSR_HW_REV_STEP(drv->trans->hw_rev); - snprintf(drv->firmware_name, sizeof(drv->firmware_name), - "%s%c-%s.ucode", name_pre, rev_step, tag); + if (rev_step != 'A') + snprintf(drv->firmware_name, + sizeof(drv->firmware_name), "%s%c-%s.ucode", + name_pre, rev_step, tag); } IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n", -- cgit v1.2.3 From 96a6497bc3ed1c19d877e5f4f95f2cfa27448abe Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 23 Dec 2015 15:10:03 +0200 Subject: iwlwifi: pcie: add 9000 series multi queue rx DMA support The 9000 series introduces several changes in the device DMA operation. As the device now supports multi-queue rx, several DMA channels should be configured. The flows of providing the device with the allocated RBDs now changes as well - the device maintains a separate table of used and free table. The hardware may use the free table to feed RBDs to any queue. This requires maintaing a shared table to map returned RBDs to the original RXB - for that purpose the VID is introduced - an internal identifier of the RB placed in the lower 12 bits and returned by HW in the used data. Another change is the support of 64 bit DMA address. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-9000.c | 3 +- drivers/net/wireless/intel/iwlwifi/iwl-config.h | 2 + drivers/net/wireless/intel/iwlwifi/iwl-fh.h | 77 ++++++ drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 28 ++- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 277 ++++++++++++++++----- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 15 +- 6 files changed, 322 insertions(+), 80 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c index ecbf4822cd69..4b93404f46a7 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c @@ -138,7 +138,8 @@ static const struct iwl_tt_params iwl9000_tt_params = { .smem_offset = IWL9000_SMEM_OFFSET, \ .smem_len = IWL9000_SMEM_LEN, \ .thermal_params = &iwl9000_tt_params, \ - .apmg_not_supported = true + .apmg_not_supported = true, \ + .mq_rx_supported = true const struct iwl_cfg iwl9260_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 9260", diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index f99048135fb9..dad5570d6cc8 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -311,6 +311,7 @@ struct iwl_pwr_tx_backoff { * @dccm2_len: length of the second DCCM * @smem_offset: offset from which the SMEM begins * @smem_len: the length of SMEM + * @mq_rx_supported: multi-queue rx support * * We enable the driver to be backward compatible wrt. hardware features. * API differences in uCode shouldn't be handled here but through TLVs @@ -362,6 +363,7 @@ struct iwl_cfg { const u32 smem_len; const struct iwl_tt_params *thermal_params; bool apmg_not_supported; + bool mq_rx_supported; }; /* diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h index 5cc6be927eab..4ab6682ea53e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h @@ -6,6 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2015 Intel Deutschland GmbH * * 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 @@ -31,6 +32,7 @@ * BSD LICENSE * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2015 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -312,6 +314,77 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl) #define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT 28 #define FH_MEM_TB_MAX_LENGTH (0x00020000) +/* 9000 rx series registers */ + +#define RFH_Q0_FRBDCB_BA_LSB 0xA08000 /* 64 bit address */ +#define RFH_Q_FRBDCB_BA_LSB(q) (RFH_Q0_FRBDCB_BA_LSB + (q) * 8) +/* Write index table */ +#define RFH_Q0_FRBDCB_WIDX 0xA08080 +#define RFH_Q_FRBDCB_WIDX(q) (RFH_Q0_FRBDCB_WIDX + (q) * 4) +/* Read index table */ +#define RFH_Q0_FRBDCB_RIDX 0xA080C0 +#define RFH_Q_FRBDCB_RIDX(q) (RFH_Q0_FRBDCB_RIDX + (q) * 4) +/* Used list table */ +#define RFH_Q0_URBDCB_BA_LSB 0xA08100 /* 64 bit address */ +#define RFH_Q_URBDCB_BA_LSB(q) (RFH_Q0_URBDCB_BA_LSB + (q) * 8) +/* Write index table */ +#define RFH_Q0_URBDCB_WIDX 0xA08180 +#define RFH_Q_URBDCB_WIDX(q) (RFH_Q0_URBDCB_WIDX + (q) * 4) +#define RFH_Q0_URBDCB_VAID 0xA081C0 +#define RFH_Q_URBDCB_VAID(q) (RFH_Q0_URBDCB_VAID + (q) * 4) +/* stts */ +#define RFH_Q0_URBD_STTS_WPTR_LSB 0xA08200 /*64 bits address */ +#define RFH_Q_URBD_STTS_WPTR_LSB(q) (RFH_Q0_URBD_STTS_WPTR_LSB + (q) * 8) + +#define RFH_Q0_ORB_WPTR_LSB 0xA08280 +#define RFH_Q_ORB_WPTR_LSB(q) (RFH_Q0_ORB_WPTR_LSB + (q) * 8) +#define RFH_RBDBUF_RBD0_LSB 0xA08300 +#define RFH_RBDBUF_RBD_LSB(q) (RFH_RBDBUF_RBD0_LSB + (q) * 8) + +/* DMA configuration */ +#define RFH_RXF_DMA_CFG 0xA09820 +/* RB size */ +#define RFH_RXF_DMA_RB_SIZE_MASK (0x000F0000) /* bits 16-19 */ +#define RFH_RXF_DMA_RB_SIZE_POS 16 +#define RFH_RXF_DMA_RB_SIZE_1K (0x1 << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_2K (0x2 << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_4K (0x4 << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_8K (0x8 << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_12K (0x9 << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_16K (0xA << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_20K (0xB << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_24K (0xC << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_28K (0xD << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_32K (0xE << RFH_RXF_DMA_RB_SIZE_POS) +/* RB Circular Buffer size:defines the table sizes in RBD units */ +#define RFH_RXF_DMA_RBDCB_SIZE_MASK (0x00F00000) /* bits 20-23 */ +#define RFH_RXF_DMA_RBDCB_SIZE_POS 20 +#define RFH_RXF_DMA_RBDCB_SIZE_8 (0x3 << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_RBDCB_SIZE_16 (0x4 << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_RBDCB_SIZE_32 (0x5 << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_RBDCB_SIZE_64 (0x7 << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_RBDCB_SIZE_128 (0x7 << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_RBDCB_SIZE_256 (0x8 << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_RBDCB_SIZE_512 (0x9 << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_RBDCB_SIZE_1024 (0xA << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_RBDCB_SIZE_2048 (0xB << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_MIN_RB_SIZE_MASK (0x03000000) /* bit 24-25 */ +#define RFH_RXF_DMA_MIN_RB_SIZE_POS 24 +#define RFH_RXF_DMA_MIN_RB_4_8 (3 << RFH_RXF_DMA_MIN_RB_SIZE_POS) +#define RFH_RXF_DMA_SINGLE_FRAME_MASK (0x20000000) /* bit 29 */ +#define RFH_DMA_EN_MASK (0xC0000000) /* bits 30-31*/ +#define RFH_DMA_EN_ENABLE_VAL BIT(31) + +#define RFH_RXF_RXQ_ACTIVE 0xA0980C + +#define RFH_GEN_CFG 0xA09800 +#define RFH_GEN_CFG_DEFAULT_RXQ_NUM_MASK 0xF00 +#define RFH_GEN_CFG_SERVICE_DMA_SNOOP BIT(0) +#define RFH_GEN_CFG_RFH_DMA_SNOOP BIT(1) +#define DEFAULT_RXQ_NUM 8 + +/* end of 9000 rx series registers */ + /* TFDB Area - TFDs buffer table */ #define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK (0xFFFFFFFF) #define FH_TFDIB_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x900) @@ -434,6 +507,10 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl) */ #define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN (0x00000002) +#define MQ_RX_TABLE_SIZE 512 +#define MQ_RX_TABLE_MASK (MQ_RX_TABLE_SIZE - 1) +#define MQ_RX_POOL_SIZE MQ_RX_TABLE_MASK + #define RX_QUEUE_SIZE 256 #define RX_QUEUE_MASK 255 #define RX_QUEUE_SIZE_LOG 8 diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 11ad87fca67a..bdda7028c393 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -56,7 +56,6 @@ #define RX_NUM_QUEUES 1 #define RX_POST_REQ_ALLOC 2 #define RX_CLAIM_REQ_ALLOC 8 -#define RX_POOL_SIZE ((RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC) * RX_NUM_QUEUES) #define RX_PENDING_WATERMARK 16 struct iwl_host_cmd; @@ -64,9 +63,16 @@ struct iwl_host_cmd; /*This file includes the declaration that are internal to the * trans_pcie layer */ +/** + * struct iwl_rx_mem_buffer + * @page_dma: bus address of rxb page + * @page: driver's pointer to the rxb page + * @vid: index of this rxb in the global table + */ struct iwl_rx_mem_buffer { dma_addr_t page_dma; struct page *page; + u16 vid; struct list_head list; }; @@ -90,8 +96,12 @@ struct isr_statistics { /** * struct iwl_rxq - Rx queue - * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) + * @id: queue index + * @bd: driver's pointer to buffer of receive buffer descriptors (rbd). + * Address size is 32 bit in pre-9000 devices and 64 bit in 9000 devices. * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) + * @ubd: driver's pointer to buffer of used receive buffer descriptors (rbd) + * @ubd_dma: physical address of buffer of used receive buffer descriptors (rbd) * @read: Shared index to newest available Rx buffer * @write: Shared index to oldest written Rx packet * @free_count: Number of pre-allocated buffers in rx_free @@ -103,18 +113,22 @@ struct isr_statistics { * @rb_stts: driver's pointer to receive buffer status * @rb_stts_dma: bus address of receive buffer status * @lock: - * @queue: actual rx queue + * @queue: actual rx queue. Not used for multi-rx queue. * * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers */ struct iwl_rxq { - __le32 *bd; + int id; + void *bd; dma_addr_t bd_dma; + __le32 *used_bd; + dma_addr_t used_bd_dma; u32 read; u32 write; u32 free_count; u32 used_count; u32 write_actual; + u32 queue_size; struct list_head rx_free; struct list_head rx_used; bool need_update; @@ -126,7 +140,6 @@ struct iwl_rxq { /** * struct iwl_rb_allocator - Rx allocator - * @pool: initial pool of allocator * @req_pending: number of requests the allcator had not processed yet * @req_ready: number of requests honored and ready for claiming * @rbd_allocated: RBDs with pages allocated and ready to be handled to @@ -138,7 +151,6 @@ struct iwl_rxq { * @rx_alloc: work struct for background calls */ struct iwl_rb_allocator { - struct iwl_rx_mem_buffer pool[RX_POOL_SIZE]; atomic_t req_pending; atomic_t req_ready; struct list_head rbd_allocated; @@ -297,6 +309,7 @@ struct iwl_tso_hdr_page { * struct iwl_trans_pcie - PCIe transport specific data * @rxq: all the RX queue data * @rx_pool: initial pool of iwl_rx_mem_buffer for all the queues + * @global_table: table mapping received VID from hw to rxb * @rba: allocator for RX replenishing * @drv - pointer to iwl_drv * @trans: pointer to the generic transport area @@ -324,7 +337,8 @@ struct iwl_tso_hdr_page { */ struct iwl_trans_pcie { struct iwl_rxq *rxq; - struct iwl_rx_mem_buffer rx_pool[RX_QUEUE_SIZE]; + struct iwl_rx_mem_buffer rx_pool[MQ_RX_POOL_SIZE]; + struct iwl_rx_mem_buffer *global_table[MQ_RX_TABLE_SIZE]; struct iwl_rb_allocator rba; struct iwl_trans *trans; struct iwl_drv *drv; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index f557f3dc4db8..a385f3cddb5d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -140,8 +140,8 @@ */ static int iwl_rxq_space(const struct iwl_rxq *rxq) { - /* Make sure RX_QUEUE_SIZE is a power of 2 */ - BUILD_BUG_ON(RX_QUEUE_SIZE & (RX_QUEUE_SIZE - 1)); + /* Make sure rx queue size is a power of 2 */ + WARN_ON(rxq->queue_size & (rxq->queue_size - 1)); /* * There can be up to (RX_QUEUE_SIZE - 1) free slots, to avoid ambiguity @@ -149,7 +149,7 @@ static int iwl_rxq_space(const struct iwl_rxq *rxq) * The following is equivalent to modulo by RX_QUEUE_SIZE and is well * defined for negative dividends. */ - return (rxq->read - rxq->write - 1) & (RX_QUEUE_SIZE - 1); + return (rxq->read - rxq->write - 1) & (rxq->queue_size - 1); } /* @@ -160,6 +160,12 @@ static inline __le32 iwl_pcie_dma_addr2rbd_ptr(dma_addr_t dma_addr) return cpu_to_le32((u32)(dma_addr >> 8)); } +static void iwl_pcie_write_prph_64(struct iwl_trans *trans, u64 ofs, u64 val) +{ + iwl_write_prph(trans, ofs, val & 0xffffffff); + iwl_write_prph(trans, ofs + 4, val >> 32); +} + /* * iwl_pcie_rx_stop - stops the Rx DMA */ @@ -200,7 +206,11 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, } rxq->write_actual = round_down(rxq->write, 8); - iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual); + if (trans->cfg->mq_rx_supported) + iwl_write_prph(trans, RFH_Q_FRBDCB_WIDX(rxq->id), + rxq->write_actual); + else + iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual); } static void iwl_pcie_rxq_check_wrptr(struct iwl_trans *trans) @@ -220,6 +230,51 @@ static void iwl_pcie_rxq_check_wrptr(struct iwl_trans *trans) } } +static void iwl_pcie_rxq_mq_restock(struct iwl_trans *trans, + struct iwl_rxq *rxq) +{ + struct iwl_rx_mem_buffer *rxb; + + /* + * If the device isn't enabled - no need to try to add buffers... + * This can happen when we stop the device and still have an interrupt + * pending. We stop the APM before we sync the interrupts because we + * have to (see comment there). On the other hand, since the APM is + * stopped, we cannot access the HW (in particular not prph). + * So don't try to restock if the APM has been already stopped. + */ + if (!test_bit(STATUS_DEVICE_ENABLED, &trans->status)) + return; + + spin_lock(&rxq->lock); + while (rxq->free_count) { + __le64 *bd = (__le64 *)rxq->bd; + + /* Get next free Rx buffer, remove from free list */ + rxb = list_first_entry(&rxq->rx_free, struct iwl_rx_mem_buffer, + list); + list_del(&rxb->list); + + /* 12 first bits are expected to be empty */ + WARN_ON(rxb->page_dma & DMA_BIT_MASK(12)); + /* Point to Rx buffer via next RBD in circular buffer */ + bd[rxq->write] = cpu_to_le64(rxb->page_dma | rxb->vid); + rxq->write = (rxq->write + 1) & MQ_RX_TABLE_MASK; + rxq->free_count--; + } + spin_unlock(&rxq->lock); + + /* + * If we've added more space for the firmware to place data, tell it. + * Increment device's write pointer in multiples of 8. + */ + if (rxq->write_actual != (rxq->write & ~0x7)) { + spin_lock(&rxq->lock); + iwl_pcie_rxq_inc_wr_ptr(trans, rxq); + spin_unlock(&rxq->lock); + } +} + /* * iwl_pcie_rxq_restock - refill RX queue from pre-allocated pool * @@ -248,6 +303,7 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans, struct iwl_rxq *rxq) spin_lock(&rxq->lock); while ((iwl_rxq_space(rxq) > 0) && (rxq->free_count)) { + __le32 *bd = (__le32 *)rxq->bd; /* The overwritten rxb must be a used one */ rxb = rxq->queue[rxq->write]; BUG_ON(rxb && rxb->page); @@ -258,7 +314,7 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans, struct iwl_rxq *rxq) list_del(&rxb->list); /* Point to Rx buffer via next RBD in circular buffer */ - rxq->bd[rxq->write] = iwl_pcie_dma_addr2rbd_ptr(rxb->page_dma); + bd[rxq->write] = iwl_pcie_dma_addr2rbd_ptr(rxb->page_dma); rxq->queue[rxq->write] = rxb; rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; rxq->free_count--; @@ -362,10 +418,6 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority, __free_pages(page, trans_pcie->rx_page_order); return; } - /* dma address must be no more than 36 bits */ - BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); - /* and also 256 byte aligned! */ - BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); spin_lock(&rxq->lock); @@ -381,7 +433,7 @@ static void iwl_pcie_free_rbs_pool(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int i; - for (i = 0; i < RX_QUEUE_SIZE; i++) { + for (i = 0; i < MQ_RX_POOL_SIZE; i++) { if (!trans_pcie->rx_pool[i].page) continue; dma_unmap_page(trans->dev, trans_pcie->rx_pool[i].page_dma, @@ -455,10 +507,6 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) __free_pages(page, trans_pcie->rx_page_order); continue; } - /* dma address must be no more than 36 bits */ - BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); - /* and also 256 byte aligned! */ - BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); /* move the allocated entry to the out list */ list_move(&rxb->list, &local_allocated); @@ -542,6 +590,8 @@ static int iwl_pcie_rx_alloc(struct iwl_trans *trans) struct iwl_rb_allocator *rba = &trans_pcie->rba; struct device *dev = trans->dev; int i; + int free_size = trans->cfg->mq_rx_supported ? sizeof(__le64) : + sizeof(__le32); if (WARN_ON(trans_pcie->rxq)) return -EINVAL; @@ -557,16 +607,30 @@ static int iwl_pcie_rx_alloc(struct iwl_trans *trans) struct iwl_rxq *rxq = &trans_pcie->rxq[i]; spin_lock_init(&rxq->lock); + if (trans->cfg->mq_rx_supported) + rxq->queue_size = MQ_RX_TABLE_SIZE; + else + rxq->queue_size = RX_QUEUE_SIZE; + /* * Allocate the circular buffer of Read Buffer Descriptors * (RBDs) */ rxq->bd = dma_zalloc_coherent(dev, - sizeof(__le32) * RX_QUEUE_SIZE, - &rxq->bd_dma, GFP_KERNEL); + free_size * rxq->queue_size, + &rxq->bd_dma, GFP_KERNEL); if (!rxq->bd) goto err; + if (trans->cfg->mq_rx_supported) { + rxq->used_bd = dma_zalloc_coherent(dev, + sizeof(__le32) * + rxq->queue_size, + &rxq->used_bd_dma, + GFP_KERNEL); + if (!rxq->used_bd) + goto err; + } /*Allocate the driver's pointer to receive buffer status */ rxq->rb_stts = dma_zalloc_coherent(dev, sizeof(*rxq->rb_stts), @@ -582,7 +646,7 @@ err: struct iwl_rxq *rxq = &trans_pcie->rxq[i]; if (rxq->bd) - dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, + dma_free_coherent(dev, free_size * rxq->queue_size, rxq->bd, rxq->bd_dma); rxq->bd_dma = 0; rxq->bd = NULL; @@ -591,8 +655,15 @@ err: dma_free_coherent(trans->dev, sizeof(struct iwl_rb_status), rxq->rb_stts, rxq->rb_stts_dma); + + if (rxq->used_bd) + dma_free_coherent(dev, sizeof(__le32) * rxq->queue_size, + rxq->used_bd, rxq->used_bd_dma); + rxq->used_bd_dma = 0; + rxq->used_bd = NULL; } kfree(trans_pcie->rxq); + return -ENOMEM; } @@ -659,46 +730,82 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) iwl_set_bit(trans, CSR_INT_COALESCING, IWL_HOST_INT_OPER_MODE); } -static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq) +static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) { - lockdep_assert_held(&rxq->lock); + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + u32 rb_size, enabled = 0; + int i; - INIT_LIST_HEAD(&rxq->rx_free); - INIT_LIST_HEAD(&rxq->rx_used); - rxq->free_count = 0; - rxq->used_count = 0; -} + switch (trans_pcie->rx_buf_size) { + case IWL_AMSDU_4K: + rb_size = RFH_RXF_DMA_RB_SIZE_4K; + break; + case IWL_AMSDU_8K: + rb_size = RFH_RXF_DMA_RB_SIZE_8K; + break; + case IWL_AMSDU_12K: + rb_size = RFH_RXF_DMA_RB_SIZE_12K; + break; + default: + WARN_ON(1); + rb_size = RFH_RXF_DMA_RB_SIZE_4K; + } -static void iwl_pcie_rx_init_rba(struct iwl_rb_allocator *rba) -{ - int i; + /* Stop Rx DMA */ + iwl_write_prph(trans, RFH_RXF_DMA_CFG, 0); + /* disable free amd used rx queue operation */ + iwl_write_prph(trans, RFH_RXF_RXQ_ACTIVE, 0); - lockdep_assert_held(&rba->lock); + for (i = 0; i < trans->num_rx_queues; i++) { + /* Tell device where to find RBD free table in DRAM */ + iwl_pcie_write_prph_64(trans, RFH_Q_FRBDCB_BA_LSB(i), + (u64)(rxq->bd_dma)); + /* Tell device where to find RBD used table in DRAM */ + iwl_pcie_write_prph_64(trans, RFH_Q_URBDCB_BA_LSB(i), + (u64)(rxq->used_bd_dma)); + /* Tell device where in DRAM to update its Rx status */ + iwl_pcie_write_prph_64(trans, RFH_Q_URBD_STTS_WPTR_LSB(i), + rxq->rb_stts_dma); + /* Reset device indice tables */ + iwl_write_prph(trans, RFH_Q_FRBDCB_WIDX(i), 0); + iwl_write_prph(trans, RFH_Q_FRBDCB_RIDX(i), 0); + iwl_write_prph(trans, RFH_Q_URBDCB_WIDX(i), 0); + + enabled |= BIT(i) | BIT(i + 16); + } - INIT_LIST_HEAD(&rba->rbd_allocated); - INIT_LIST_HEAD(&rba->rbd_empty); + /* restock default queue */ + iwl_pcie_rxq_mq_restock(trans, &trans_pcie->rxq[0]); - for (i = 0; i < RX_POOL_SIZE; i++) - list_add(&rba->pool[i].list, &rba->rbd_empty); + /* + * Enable Rx DMA + * Single frame mode + * Rx buffer size 4 or 8k or 12k + * Min RB size 4 or 8 + * 512 RBDs + */ + iwl_write_prph(trans, RFH_RXF_DMA_CFG, + RFH_DMA_EN_ENABLE_VAL | + rb_size | RFH_RXF_DMA_SINGLE_FRAME_MASK | + RFH_RXF_DMA_MIN_RB_4_8 | + RFH_RXF_DMA_RBDCB_SIZE_512); + + iwl_write_prph(trans, RFH_GEN_CFG, RFH_GEN_CFG_RFH_DMA_SNOOP | + RFH_GEN_CFG_SERVICE_DMA_SNOOP); + iwl_write_prph(trans, RFH_RXF_RXQ_ACTIVE, enabled); + + /* Set interrupt coalescing timer to default (2048 usecs) */ + iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); } -static void iwl_pcie_rx_free_rba(struct iwl_trans *trans) +static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rb_allocator *rba = &trans_pcie->rba; - int i; - - lockdep_assert_held(&rba->lock); + lockdep_assert_held(&rxq->lock); - for (i = 0; i < RX_POOL_SIZE; i++) { - if (!rba->pool[i].page) - continue; - dma_unmap_page(trans->dev, rba->pool[i].page_dma, - PAGE_SIZE << trans_pcie->rx_page_order, - DMA_FROM_DEVICE); - __free_pages(rba->pool[i].page, trans_pcie->rx_page_order); - rba->pool[i].page = NULL; - } + INIT_LIST_HEAD(&rxq->rx_free); + INIT_LIST_HEAD(&rxq->rx_used); + rxq->free_count = 0; + rxq->used_count = 0; } int iwl_pcie_rx_init(struct iwl_trans *trans) @@ -706,7 +813,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rxq *def_rxq; struct iwl_rb_allocator *rba = &trans_pcie->rba; - int i, err; + int i, err, num_rbds, allocator_pool_size; if (!trans_pcie->rxq) { err = iwl_pcie_rx_alloc(trans); @@ -722,9 +829,8 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) spin_lock(&rba->lock); atomic_set(&rba->req_pending, 0); atomic_set(&rba->req_ready, 0); - /* free all first - we might be reconfigured for a different size */ - iwl_pcie_rx_free_rba(trans); - iwl_pcie_rx_init_rba(rba); + INIT_LIST_HEAD(&rba->rbd_allocated); + INIT_LIST_HEAD(&rba->rbd_empty); spin_unlock(&rba->lock); /* free all first - we might be reconfigured for a different size */ @@ -736,6 +842,8 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) for (i = 0; i < trans->num_rx_queues; i++) { struct iwl_rxq *rxq = &trans_pcie->rxq[i]; + rxq->id = i; + spin_lock(&rxq->lock); /* * Set read write pointer to reflect that we have processed @@ -752,13 +860,29 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) spin_unlock(&rxq->lock); } - /* move the entire pool to the default queue ownership */ - for (i = 0; i < RX_QUEUE_SIZE; i++) - list_add(&trans_pcie->rx_pool[i].list, &def_rxq->rx_used); + /* move the pool to the default queue and allocator ownerships */ + num_rbds = trans->cfg->mq_rx_supported ? + MQ_RX_POOL_SIZE : RX_QUEUE_SIZE; + allocator_pool_size = trans->num_rx_queues * + (RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC); + for (i = 0; i < num_rbds; i++) { + struct iwl_rx_mem_buffer *rxb = &trans_pcie->rx_pool[i]; + + if (i < allocator_pool_size) + list_add(&rxb->list, &rba->rbd_empty); + else + list_add(&rxb->list, &def_rxq->rx_used); + trans_pcie->global_table[i] = rxb; + rxb->vid = (u16)i; + } iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL, def_rxq); - iwl_pcie_rxq_restock(trans, def_rxq); - iwl_pcie_rx_hw_init(trans, def_rxq); + if (trans->cfg->mq_rx_supported) { + iwl_pcie_rx_mq_hw_init(trans, def_rxq); + } else { + iwl_pcie_rxq_restock(trans, def_rxq); + iwl_pcie_rx_hw_init(trans, def_rxq); + } spin_lock(&def_rxq->lock); iwl_pcie_rxq_inc_wr_ptr(trans, def_rxq); @@ -771,6 +895,8 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rb_allocator *rba = &trans_pcie->rba; + int free_size = trans->cfg->mq_rx_supported ? sizeof(__le64) : + sizeof(__le32); int i; /* @@ -788,10 +914,6 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) rba->alloc_wq = NULL; } - spin_lock(&rba->lock); - iwl_pcie_rx_free_rba(trans); - spin_unlock(&rba->lock); - iwl_pcie_free_rbs_pool(trans); for (i = 0; i < trans->num_rx_queues; i++) { @@ -799,7 +921,7 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) if (rxq->bd) dma_free_coherent(trans->dev, - sizeof(__le32) * RX_QUEUE_SIZE, + free_size * rxq->queue_size, rxq->bd, rxq->bd_dma); rxq->bd_dma = 0; rxq->bd = NULL; @@ -811,8 +933,14 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) else IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n"); - } + if (rxq->used_bd) + dma_free_coherent(trans->dev, + sizeof(__le32) * rxq->queue_size, + rxq->used_bd, rxq->used_bd_dma); + rxq->used_bd_dma = 0; + rxq->used_bd = NULL; + } kfree(trans_pcie->rxq); } @@ -1009,16 +1137,26 @@ restart: while (i != r) { struct iwl_rx_mem_buffer *rxb; - if (unlikely(rxq->used_count == RX_QUEUE_SIZE / 2)) + if (unlikely(rxq->used_count == rxq->queue_size / 2)) emergency = true; - rxb = rxq->queue[i]; - rxq->queue[i] = NULL; + if (trans->cfg->mq_rx_supported) { + /* + * used_bd is a 32 bit but only 12 are used to retrieve + * the vid + */ + u16 vid = (u16)le32_to_cpu(rxq->used_bd[i]); + + rxb = trans_pcie->global_table[vid]; + } else { + rxb = rxq->queue[i]; + rxq->queue[i] = NULL; + } IWL_DEBUG_RX(trans, "rxbuf: HW = %d, SW = %d\n", r, i); iwl_pcie_rx_handle_rb(trans, rxq, rxb, emergency); - i = (i + 1) & RX_QUEUE_MASK; + i = (i + 1) & (rxq->queue_size - 1); /* If we have RX_CLAIM_REQ_ALLOC released rx buffers - * try to claim the pre-allocated buffers from the allocator */ @@ -1056,7 +1194,7 @@ restart: count++; if (count == 8) { count = 0; - if (rxq->used_count < RX_QUEUE_SIZE / 3) + if (rxq->used_count < rxq->queue_size / 3) emergency = false; spin_unlock(&rxq->lock); iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC, rxq); @@ -1071,7 +1209,10 @@ restart: if (rxq->free_count >= RX_CLAIM_REQ_ALLOC) { rxq->read = i; spin_unlock(&rxq->lock); - iwl_pcie_rxq_restock(trans, rxq); + if (trans->cfg->mq_rx_supported) + iwl_pcie_rxq_mq_restock(trans, rxq); + else + iwl_pcie_rxq_restock(trans, rxq); goto restart; } } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 0302aede4fdf..35810965221c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2403,7 +2403,8 @@ static struct iwl_trans_dump_data u32 len, num_rbs; u32 monitor_len; int i, ptr; - bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status); + bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status) && + !trans->cfg->mq_rx_supported; /* transport dump header */ len = sizeof(*dump_data); @@ -2562,7 +2563,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, struct iwl_trans_pcie *trans_pcie; struct iwl_trans *trans; u16 pci_cmd; - int ret; + int ret, addr_size; trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), &pdev->dev, cfg, &trans_ops_pcie, 0); @@ -2600,11 +2601,17 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, PCIE_LINK_STATE_CLKPM); } + if (cfg->mq_rx_supported) + addr_size = 64; + else + addr_size = 36; + pci_set_master(pdev); - ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(addr_size)); if (!ret) - ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); + ret = pci_set_consistent_dma_mask(pdev, + DMA_BIT_MASK(addr_size)); if (ret) { ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (!ret) -- cgit v1.2.3 From 29efefb9091dc7b58a2ac9d054c92295101e6bb2 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 15 Jan 2016 18:35:34 +0100 Subject: watchdog: max63xx: make module's license marker match the header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The header specifies GPL version 2 only, so make the MODULE_LICENSE string use the respective string for that. Signed-off-by: Uwe Kleine-König Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/max63xx_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c index f36ca4be0720..ac5840d9689a 100644 --- a/drivers/watchdog/max63xx_wdt.c +++ b/drivers/watchdog/max63xx_wdt.c @@ -292,4 +292,4 @@ MODULE_PARM_DESC(nodelay, "Force selection of a timeout setting without initial delay " "(max6373/74 only, default=0)"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 55e071779c79890f43b75d4472243280e91581de Mon Sep 17 00:00:00 2001 From: Sandeep Tripathy Date: Tue, 19 Jan 2016 14:44:49 +0530 Subject: watchdog: sp805: ping fails to abort wdt reset sp805 wdt asserts interrupt for the first expiry and reloads the counter. If wdt interrupt is set and count reaches zero then wdt reset event is generated. To get wdt reset at 't' timeout the driver loads wdt counter with 't/2'. A ping before time 't' *should* prevent wdt reset. Currently if ping is done after 't/2' then wdt interrupt condition gets set. On the next countdown of loadval wdt reset event occurs eventhough wdt was reloaded before the set timeout 't'. This patch clears the interrupt condition on ping. Signed-off-by: Sandeep Tripathy Acked-by: Viresh Kumar Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sp805_wdt.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index 01d816251302..e7a715e82021 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -139,12 +139,11 @@ static int wdt_config(struct watchdog_device *wdd, bool ping) writel_relaxed(UNLOCK, wdt->base + WDTLOCK); writel_relaxed(wdt->load_val, wdt->base + WDTLOAD); + writel_relaxed(INT_MASK, wdt->base + WDTINTCLR); - if (!ping) { - writel_relaxed(INT_MASK, wdt->base + WDTINTCLR); + if (!ping) writel_relaxed(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL); - } writel_relaxed(LOCK, wdt->base + WDTLOCK); -- cgit v1.2.3 From 99f08ca84156f08b8545f7a5bfedfdd2452c4556 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 19 Jan 2016 15:51:04 +0200 Subject: watchdog: pcwd_usb: fix compilation warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In function ‘usb_pcwd_probe’: drivers/watchdog/pcwd_usb.c:611:12: warning: variable ‘maxp’ set but not used [-Wunused-but-set-variable] int pipe, maxp; Signed-off-by: Tomas Winkler Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/pcwd_usb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c index 1a11aedc4fe8..68952d9ccf83 100644 --- a/drivers/watchdog/pcwd_usb.c +++ b/drivers/watchdog/pcwd_usb.c @@ -608,7 +608,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; struct usb_pcwd_private *usb_pcwd = NULL; - int pipe, maxp; + int pipe; int retval = -ENOMEM; int got_fw_rev; unsigned char fw_rev_major, fw_rev_minor; @@ -641,7 +641,6 @@ static int usb_pcwd_probe(struct usb_interface *interface, /* get a handle to the interrupt data pipe */ pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); /* allocate memory for our device and initialize it */ usb_pcwd = kzalloc(sizeof(struct usb_pcwd_private), GFP_KERNEL); -- cgit v1.2.3 From c75f6c5ac0877e8d9728f680aa324e9adeff91e1 Mon Sep 17 00:00:00 2001 From: Marc Gonzalez Date: Thu, 21 Jan 2016 15:27:07 +0100 Subject: watchdog: tango: rename ARCH_TANGOX to ARCH_TANGO This change was requested by arm-soc maintainer Kevin Hilman because the X in TANGOX is a wildcard. Signed-off-by: Marc Gonzalez Acked-by: Mans Rullgard Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 4f0e7be0da34..e723e0169f88 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -145,7 +145,7 @@ config MENF21BMC_WATCHDOG config TANGOX_WATCHDOG tristate "Sigma Designs SMP86xx/SMP87xx watchdog" select WATCHDOG_CORE - depends on ARCH_TANGOX || COMPILE_TEST + depends on ARCH_TANGO || COMPILE_TEST help Support for the watchdog in Sigma Designs SMP86xx (tango3) and SMP87xx (tango4) family chips. -- cgit v1.2.3 From df1a3e64f79b3e277a22b2e789896f86c63eec1f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 17:06:27 +0100 Subject: watchdog: imgdpc: select WATCHDOG_CORE The imgpdc_wdt driver can be built on all architectures with CONFIG_COMPILE_TEST, but fails if no other watchdog driver is enabled: drivers/watchdog/built-in.o: In function `pdc_wdt_remove': imgpdc_wdt.c:(.text+0x74): undefined reference to `watchdog_unregister_device' This adds the normal 'select WATCHDOG_CORE' that is needed to ensure the driver always builds cleanly. Signed-off-by: Arnd Bergmann Reviewed-by: James Hogan Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index e723e0169f88..0847f2e22e55 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1383,6 +1383,7 @@ config IMGPDC_WDT tristate "Imagination Technologies PDC Watchdog Timer" depends on HAS_IOMEM depends on METAG || MIPS || COMPILE_TEST + select WATCHDOG_CORE help Driver for Imagination Technologies PowerDown Controller Watchdog Timer. -- cgit v1.2.3 From d42d6108711b142804b4710d4215efbf5f9b6e21 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 25 Jan 2016 23:24:14 +0100 Subject: watchdog: Fix dependencies for !HAS_IOMEM archs Not every arch has io memory. So, unbreak the build by fixing the dependencies. Signed-off-by: Richard Weinberger Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 0847f2e22e55..0f6d8515ba4f 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -146,6 +146,7 @@ config TANGOX_WATCHDOG tristate "Sigma Designs SMP86xx/SMP87xx watchdog" select WATCHDOG_CORE depends on ARCH_TANGO || COMPILE_TEST + depends on HAS_IOMEM help Support for the watchdog in Sigma Designs SMP86xx (tango3) and SMP87xx (tango4) family chips. @@ -618,6 +619,7 @@ config DIGICOLOR_WATCHDOG config LPC18XX_WATCHDOG tristate "LPC18xx/43xx Watchdog" depends on ARCH_LPC18XX || COMPILE_TEST + depends on HAS_IOMEM select WATCHDOG_CORE help Say Y here if to include support for the watchdog timer @@ -1374,6 +1376,7 @@ config BCM_KONA_WDT_DEBUG config BCM7038_WDT tristate "BCM7038 Watchdog" select WATCHDOG_CORE + depends on HAS_IOMEM help Watchdog driver for the built-in hardware in Broadcom 7038 SoCs. -- cgit v1.2.3 From ca0bb0798022732773752fee97bb633c6f3623d2 Mon Sep 17 00:00:00 2001 From: "wim.coekaerts@oracle.com" Date: Fri, 29 Jan 2016 09:39:38 -0800 Subject: Add sun4v_wdt watchdog driver This driver adds sparc hypervisor watchdog support. The default timeout is 60 seconds and the range is between 1 and 31536000 seconds. Both watchdog-resolution and watchdog-max-timeout MD properties settings are supported. Signed-off-by: Wim Coekaerts Reviewed-by: Julian Calaby Reviewed-by: Guenter Roeck Signed-off-by: David S. Miller --- Documentation/watchdog/watchdog-parameters.txt | 4 + arch/sparc/kernel/hvcalls.S | 3 +- arch/sparc/kernel/sparc_ksyms_64.c | 1 + drivers/watchdog/Kconfig | 11 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/sun4v_wdt.c | 191 +++++++++++++++++++++++++ 6 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 drivers/watchdog/sun4v_wdt.c (limited to 'drivers') diff --git a/Documentation/watchdog/watchdog-parameters.txt b/Documentation/watchdog/watchdog-parameters.txt index 9f9ec9f76039..4e4b6f10d841 100644 --- a/Documentation/watchdog/watchdog-parameters.txt +++ b/Documentation/watchdog/watchdog-parameters.txt @@ -400,3 +400,7 @@ wm8350_wdt: nowayout: Watchdog cannot be stopped once started (default=kernel config parameter) ------------------------------------------------- +sun4v_wdt: +timeout_ms: Watchdog timeout in milliseconds 1..180000, default=60000) +nowayout: Watchdog cannot be stopped once started +------------------------------------------------- diff --git a/arch/sparc/kernel/hvcalls.S b/arch/sparc/kernel/hvcalls.S index afbaba52d2f1..d127130bf424 100644 --- a/arch/sparc/kernel/hvcalls.S +++ b/arch/sparc/kernel/hvcalls.S @@ -338,8 +338,9 @@ ENTRY(sun4v_mach_set_watchdog) mov %o1, %o4 mov HV_FAST_MACH_SET_WATCHDOG, %o5 ta HV_FAST_TRAP + brnz,a,pn %o4, 0f stx %o1, [%o4] - retl +0: retl nop ENDPROC(sun4v_mach_set_watchdog) diff --git a/arch/sparc/kernel/sparc_ksyms_64.c b/arch/sparc/kernel/sparc_ksyms_64.c index a92d5d2c46a3..9e034f29dcc5 100644 --- a/arch/sparc/kernel/sparc_ksyms_64.c +++ b/arch/sparc/kernel/sparc_ksyms_64.c @@ -37,6 +37,7 @@ EXPORT_SYMBOL(sun4v_niagara_getperf); EXPORT_SYMBOL(sun4v_niagara_setperf); EXPORT_SYMBOL(sun4v_niagara2_getperf); EXPORT_SYMBOL(sun4v_niagara2_setperf); +EXPORT_SYMBOL(sun4v_mach_set_watchdog); /* from hweight.S */ EXPORT_SYMBOL(__arch_hweight8); diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 4f0e7be0da34..30d38ae685f6 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1565,6 +1565,17 @@ config WATCHDOG_RIO machines. The watchdog timeout period is normally one minute but can be changed with a boot-time parameter. +config WATCHDOG_SUN4V + tristate "Sun4v Watchdog support" + select WATCHDOG_CORE + depends on SPARC64 + help + Say Y here to support the hypervisor watchdog capability embedded + in the SPARC sun4v architecture. + + To compile this driver as a module, choose M here. The module will + be called sun4v_wdt. + # XTENSA Architecture # Xen Architecture diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index f566753256ab..f6a6a387c6c7 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -179,6 +179,7 @@ obj-$(CONFIG_SH_WDT) += shwdt.o obj-$(CONFIG_WATCHDOG_RIO) += riowd.o obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o +obj-$(CONFIG_WATCHDOG_SUN4V) += sun4v_wdt.o # XTENSA Architecture diff --git a/drivers/watchdog/sun4v_wdt.c b/drivers/watchdog/sun4v_wdt.c new file mode 100644 index 000000000000..1467fe50a76f --- /dev/null +++ b/drivers/watchdog/sun4v_wdt.c @@ -0,0 +1,191 @@ +/* + * sun4v watchdog timer + * (c) Copyright 2016 Oracle Corporation + * + * Implement a simple watchdog driver using the built-in sun4v hypervisor + * watchdog support. If time expires, the hypervisor stops or bounces + * the guest domain. + * + * 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. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#define WDT_TIMEOUT 60 +#define WDT_MAX_TIMEOUT 31536000 +#define WDT_MIN_TIMEOUT 1 +#define WDT_DEFAULT_RESOLUTION_MS 1000 /* 1 second */ + +static unsigned int timeout; +module_param(timeout, uint, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=" + __MODULE_STRING(WDT_TIMEOUT) ")"); + +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, S_IRUGO); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +static int sun4v_wdt_stop(struct watchdog_device *wdd) +{ + sun4v_mach_set_watchdog(0, NULL); + + return 0; +} + +static int sun4v_wdt_ping(struct watchdog_device *wdd) +{ + int hverr; + + /* + * HV watchdog timer will round up the timeout + * passed in to the nearest multiple of the + * watchdog resolution in milliseconds. + */ + hverr = sun4v_mach_set_watchdog(wdd->timeout * 1000, NULL); + if (hverr == HV_EINVAL) + return -EINVAL; + + return 0; +} + +static int sun4v_wdt_set_timeout(struct watchdog_device *wdd, + unsigned int timeout) +{ + wdd->timeout = timeout; + + return 0; +} + +static const struct watchdog_info sun4v_wdt_ident = { + .options = WDIOF_SETTIMEOUT | + WDIOF_MAGICCLOSE | + WDIOF_KEEPALIVEPING, + .identity = "sun4v hypervisor watchdog", + .firmware_version = 0, +}; + +static struct watchdog_ops sun4v_wdt_ops = { + .owner = THIS_MODULE, + .start = sun4v_wdt_ping, + .stop = sun4v_wdt_stop, + .ping = sun4v_wdt_ping, + .set_timeout = sun4v_wdt_set_timeout, +}; + +static struct watchdog_device wdd = { + .info = &sun4v_wdt_ident, + .ops = &sun4v_wdt_ops, + .min_timeout = WDT_MIN_TIMEOUT, + .max_timeout = WDT_MAX_TIMEOUT, + .timeout = WDT_TIMEOUT, +}; + +static int __init sun4v_wdt_init(void) +{ + struct mdesc_handle *handle; + u64 node; + const u64 *value; + int err = 0; + unsigned long major = 1, minor = 1; + + /* + * There are 2 properties that can be set from the control + * domain for the watchdog. + * watchdog-resolution + * watchdog-max-timeout + * + * We can expect a handle to be returned otherwise something + * serious is wrong. Correct to return -ENODEV here. + */ + + handle = mdesc_grab(); + if (!handle) + return -ENODEV; + + node = mdesc_node_by_name(handle, MDESC_NODE_NULL, "platform"); + err = -ENODEV; + if (node == MDESC_NODE_NULL) + goto out_release; + + /* + * This is a safe way to validate if we are on the right + * platform. + */ + if (sun4v_hvapi_register(HV_GRP_CORE, major, &minor)) + goto out_hv_unreg; + + /* Allow value of watchdog-resolution up to 1s (default) */ + value = mdesc_get_property(handle, node, "watchdog-resolution", NULL); + err = -EINVAL; + if (value) { + if (*value == 0 || + *value > WDT_DEFAULT_RESOLUTION_MS) + goto out_hv_unreg; + } + + value = mdesc_get_property(handle, node, "watchdog-max-timeout", NULL); + if (value) { + /* + * If the property value (in ms) is smaller than + * min_timeout, return -EINVAL. + */ + if (*value < wdd.min_timeout * 1000) + goto out_hv_unreg; + + /* + * If the property value is smaller than + * default max_timeout then set watchdog max_timeout to + * the value of the property in seconds. + */ + if (*value < wdd.max_timeout * 1000) + wdd.max_timeout = *value / 1000; + } + + watchdog_init_timeout(&wdd, timeout, NULL); + + watchdog_set_nowayout(&wdd, nowayout); + + err = watchdog_register_device(&wdd); + if (err) + goto out_hv_unreg; + + pr_info("initialized (timeout=%ds, nowayout=%d)\n", + wdd.timeout, nowayout); + + mdesc_release(handle); + + return 0; + +out_hv_unreg: + sun4v_hvapi_unregister(HV_GRP_CORE); + +out_release: + mdesc_release(handle); + return err; +} + +static void __exit sun4v_wdt_exit(void) +{ + sun4v_hvapi_unregister(HV_GRP_CORE); + watchdog_unregister_device(&wdd); +} + +module_init(sun4v_wdt_init); +module_exit(sun4v_wdt_exit); + +MODULE_AUTHOR("Wim Coekaerts "); +MODULE_DESCRIPTION("sun4v watchdog driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From e0fea7e7b63108b31c043df0d5754bbd666d05c6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 17 Nov 2015 16:08:36 +0100 Subject: drm/exynos: fix building without CONFIG_PM_SLEEP The runtime PM operations use the suspend/resume functions even when CONFIG_PM_SLEEP is not set, but this now fails for the exynos DRM driver: exynos_mixer.c:1289:61: error: 'exynos_mixer_resume' undeclared here (not in a function) SET_RUNTIME_PM_OPS(exynos_mixer_suspend, exynos_mixer_resume, NULL) This removes the #ifdef and instead marks the functions as __maybe_unused, which does the right thing in all cases and also looks nicer. Signed-off-by: Arnd Bergmann Reviewed-by: Krzysztof Kozlowski Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_mixer.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index b5fbc1cbf024..0a5a60005f7e 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1289,8 +1289,7 @@ static int mixer_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP -static int exynos_mixer_suspend(struct device *dev) +static int __maybe_unused exynos_mixer_suspend(struct device *dev) { struct mixer_context *ctx = dev_get_drvdata(dev); struct mixer_resources *res = &ctx->mixer_res; @@ -1306,7 +1305,7 @@ static int exynos_mixer_suspend(struct device *dev) return 0; } -static int exynos_mixer_resume(struct device *dev) +static int __maybe_unused exynos_mixer_resume(struct device *dev) { struct mixer_context *ctx = dev_get_drvdata(dev); struct mixer_resources *res = &ctx->mixer_res; @@ -1342,7 +1341,6 @@ static int exynos_mixer_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops exynos_mixer_pm_ops = { SET_RUNTIME_PM_OPS(exynos_mixer_suspend, exynos_mixer_resume, NULL) -- cgit v1.2.3 From 010848a73fd87a481f263f7322e733f129ac398b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 20 Jan 2016 11:33:37 +0100 Subject: drm: exynos: make PM functions as __maybe_unused The newly added runtime-pm support for exynos-drm encloses the pm functions in an #ifdef, but not the functions that are called from them and nowhere else, which produces warnings: drm/exynos/exynos_drm_dsi.c:733:13: warning: 'exynos_dsi_disable_clock' defined but not used [-Wunused-function] static void exynos_dsi_disable_clock(struct exynos_dsi *dsi) ^ drm/exynos/exynos_drm_dsi.c:1291:13: warning: 'exynos_dsi_disable_irq' defined but not used [-Wunused-function] static void exynos_dsi_disable_irq(struct exynos_dsi *dsi) ^ This removes the #ifdef and instead marks the functions as __maybe_unused, so gcc can silently discard them and all called functions when CONFIG_PM is disabled. Signed-off-by: Arnd Bergmann Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index d84a498ef099..e977a81af2e6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1906,8 +1906,7 @@ static int exynos_dsi_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int exynos_dsi_suspend(struct device *dev) +static int __maybe_unused exynos_dsi_suspend(struct device *dev) { struct drm_encoder *encoder = dev_get_drvdata(dev); struct exynos_dsi *dsi = encoder_to_dsi(encoder); @@ -1938,7 +1937,7 @@ static int exynos_dsi_suspend(struct device *dev) return 0; } -static int exynos_dsi_resume(struct device *dev) +static int __maybe_unused exynos_dsi_resume(struct device *dev) { struct drm_encoder *encoder = dev_get_drvdata(dev); struct exynos_dsi *dsi = encoder_to_dsi(encoder); @@ -1972,7 +1971,6 @@ err_clk: return ret; } -#endif static const struct dev_pm_ops exynos_dsi_pm_ops = { SET_RUNTIME_PM_OPS(exynos_dsi_suspend, exynos_dsi_resume, NULL) -- cgit v1.2.3 From 37e110625eeeaba83e8cb763ab7645f0678c6f8e Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 29 Jan 2016 12:09:31 -0300 Subject: drm/exynos: dp: Fix panel and bridge lookup logic Commit a9fa852886fd ("drm/exynos: dp: add of_graph dt binding support for panel") made the Exynos DP DT binding more consistent since the OF graph could be used to lookup either a panel or a bridge device node. Before that commit, a panel would be looked up using a phandle and a bridge using the OF graph which made the DT binding not consistent. But the patch broke the later case since not finding a panel dev node would cause the driver's to do a probe deferral instead of attempting to lookup a bridge device node associated with the remote endpoint. So instead of returning a -EPROBE_DEFER if a panel is not found, check if there's a bridge and only do a probe deferral if both aren't found. Signed-off-by: Javier Martinez Canillas Tested-by: Michal Suchanek Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_dp_core.c | 55 +++++++++++++++------------------ 1 file changed, 25 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index b79c316c2ad2..673164b331c8 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -1392,7 +1392,7 @@ static const struct component_ops exynos_dp_ops = { static int exynos_dp_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *panel_node = NULL, *bridge_node, *endpoint = NULL; + struct device_node *np = NULL, *endpoint = NULL; struct exynos_dp_device *dp; int ret; @@ -1404,41 +1404,36 @@ static int exynos_dp_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dp); /* This is for the backward compatibility. */ - panel_node = of_parse_phandle(dev->of_node, "panel", 0); - if (panel_node) { - dp->panel = of_drm_find_panel(panel_node); - of_node_put(panel_node); + np = of_parse_phandle(dev->of_node, "panel", 0); + if (np) { + dp->panel = of_drm_find_panel(np); + of_node_put(np); if (!dp->panel) return -EPROBE_DEFER; - } else { - endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); - if (endpoint) { - panel_node = of_graph_get_remote_port_parent(endpoint); - if (panel_node) { - dp->panel = of_drm_find_panel(panel_node); - of_node_put(panel_node); - if (!dp->panel) - return -EPROBE_DEFER; - } else { - DRM_ERROR("no port node for panel device.\n"); - return -EINVAL; - } - } - } - - if (endpoint) goto out; + } endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); if (endpoint) { - bridge_node = of_graph_get_remote_port_parent(endpoint); - if (bridge_node) { - dp->ptn_bridge = of_drm_find_bridge(bridge_node); - of_node_put(bridge_node); - if (!dp->ptn_bridge) - return -EPROBE_DEFER; - } else - return -EPROBE_DEFER; + np = of_graph_get_remote_port_parent(endpoint); + if (np) { + /* The remote port can be either a panel or a bridge */ + dp->panel = of_drm_find_panel(np); + if (!dp->panel) { + dp->ptn_bridge = of_drm_find_bridge(np); + if (!dp->ptn_bridge) { + of_node_put(np); + return -EPROBE_DEFER; + } + } + of_node_put(np); + } else { + DRM_ERROR("no remote endpoint device node found.\n"); + return -EINVAL; + } + } else { + DRM_ERROR("no port endpoint subnode found.\n"); + return -EINVAL; } out: -- cgit v1.2.3 From d83a96a53dd2c36948be37b64a85a761b942ddfd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 Jan 2016 09:24:29 -0200 Subject: [media] em28xx: remove unused input types The em28xx driver have lots of different input types but only 4 of such types are actually used. The others are bogus. Remove them, in order to cleanup the driver. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 134 ++++++++++++++++---------------- drivers/media/usb/em28xx/em28xx-video.c | 16 ++-- drivers/media/usb/em28xx/em28xx.h | 8 +- 3 files changed, 73 insertions(+), 85 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index a1b6ef5894a6..ab0fe0319991 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -570,7 +570,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, .gpio = silvercrest_reg_seq, @@ -583,7 +583,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .tuner_type = TUNER_ABSENT, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -605,7 +605,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, } }, @@ -616,7 +616,7 @@ struct em28xx_board em28xx_boards[] = { .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -635,7 +635,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_LINE_IN, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -655,7 +655,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -675,7 +675,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -715,7 +715,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_LINE_IN, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -735,7 +735,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_LINE_IN, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -755,7 +755,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -775,7 +775,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -800,7 +800,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE4, .amux = EM28XX_AMUX_AUX, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE5, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -819,7 +819,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, } }, @@ -829,7 +829,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, .gpio = silvercrest_reg_seq, @@ -848,7 +848,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_LINE_IN, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { @@ -863,7 +863,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, /* Capture only device */ .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -879,7 +879,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, } }, @@ -889,7 +889,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .tuner_type = TUNER_ABSENT, /* Capture only device */ .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -909,7 +909,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -930,7 +930,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -952,7 +952,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -974,7 +974,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -992,7 +992,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1006,7 +1006,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, /* Capture only device */ .decoder = EM28XX_TVP5150, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1029,7 +1029,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, .gpio = pinnacle_hybrid_pro_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = pinnacle_hybrid_pro_analog, @@ -1100,7 +1100,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = terratec_cinergy_USB_XS_FR_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = terratec_cinergy_USB_XS_FR_analog, @@ -1186,7 +1186,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1213,7 +1213,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1239,7 +1239,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1265,7 +1265,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1291,7 +1291,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1317,7 +1317,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1343,7 +1343,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = default_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = default_analog, @@ -1368,7 +1368,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1392,7 +1392,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE4, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1413,7 +1413,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1428,7 +1428,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .tuner_type = TUNER_ABSENT, /* capture only board */ .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1443,7 +1443,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, /* Capture-only board */ .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, .gpio = vc211a_enable, @@ -1465,7 +1465,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1485,7 +1485,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1500,7 +1500,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, /* capture only board */ .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1520,7 +1520,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1541,7 +1541,7 @@ struct em28xx_board em28xx_boards[] = { .aout = EM28XX_AOUT_MONO | /* I2S */ EM28XX_AOUT_MASTER, /* Line out pin */ }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1563,7 +1563,7 @@ struct em28xx_board em28xx_boards[] = { .aout = EM28XX_AOUT_MONO | /* I2S */ EM28XX_AOUT_MASTER, /* Line out pin */ }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1581,7 +1581,7 @@ struct em28xx_board em28xx_boards[] = { .type = EM28XX_VMUX_SVIDEO, .vmux = SAA7115_SVIDEO3, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, } }, }, @@ -1610,7 +1610,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = em2880_msi_digivox_ad_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = em2880_msi_digivox_ad_analog, @@ -1633,7 +1633,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = em2880_msi_digivox_ad_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = em2880_msi_digivox_ad_analog, @@ -1654,7 +1654,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1677,7 +1677,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = default_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = default_analog, @@ -1708,7 +1708,7 @@ struct em28xx_board em28xx_boards[] = { .gpio = em2882_kworld_315u_analog, .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, .gpio = em2882_kworld_315u_analog1, @@ -1735,7 +1735,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = default_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = default_analog, @@ -1758,7 +1758,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = default_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = default_analog, @@ -1782,7 +1782,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = pinnacle_hybrid_pro_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = pinnacle_hybrid_pro_analog, @@ -1808,7 +1808,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1834,7 +1834,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1859,7 +1859,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1904,7 +1904,7 @@ struct em28xx_board em28xx_boards[] = { .gpio = kworld_330u_analog, .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = kworld_330u_analog, @@ -1951,7 +1951,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1970,7 +1970,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1990,7 +1990,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { /* Composite has not been tested yet */ - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_VIDEO, }, { /* S-video has not been tested yet */ @@ -2006,7 +2006,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -2023,7 +2023,7 @@ struct em28xx_board em28xx_boards[] = { .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, .mute_gpio = terratec_av350_mute_gpio, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AUDIO_SRC_LINE, .gpio = terratec_av350_unmute_gpio, @@ -2041,7 +2041,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .tuner_type = TUNER_ABSENT, /* Capture only device */ .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -2067,7 +2067,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = evga_indtube_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = evga_indtube_analog, @@ -2125,7 +2125,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -2238,7 +2238,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .amux = EM28XX_AMUX_VIDEO, .gpio = speedlink_vad_laplace_reg_seq, } }, @@ -2272,7 +2272,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, /* Capture only device */ .decoder = EM28XX_TVP5150, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 6a015e8e8655..52428b4cce5f 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1442,16 +1442,11 @@ static int vidioc_s_parm(struct file *file, void *priv, 0, video, s_parm, p); } -static const char *iname[] = { - [EM28XX_VMUX_COMPOSITE1] = "Composite1", - [EM28XX_VMUX_COMPOSITE2] = "Composite2", - [EM28XX_VMUX_COMPOSITE3] = "Composite3", - [EM28XX_VMUX_COMPOSITE4] = "Composite4", - [EM28XX_VMUX_SVIDEO] = "S-Video", +static const char * const iname[] = { + [EM28XX_VMUX_COMPOSITE] = "Composite", + [EM28XX_VMUX_SVIDEO] = "S-Video", [EM28XX_VMUX_TELEVISION] = "Television", - [EM28XX_VMUX_CABLE] = "Cable TV", - [EM28XX_VMUX_DVB] = "DVB", - [EM28XX_VMUX_DEBUG] = "for debug only", + [EM28XX_RADIO] = "Radio", }; static int vidioc_enum_input(struct file *file, void *priv, @@ -1471,8 +1466,7 @@ static int vidioc_enum_input(struct file *file, void *priv, strcpy(i->name, iname[INPUT(n)->type]); - if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) || - (EM28XX_VMUX_CABLE == INPUT(n)->type)) + if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type)) i->type = V4L2_INPUT_TYPE_TUNER; i->std = dev->v4l2->vdev.tvnorms; diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 8ff066c977d9..b23bf6a64011 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -291,15 +291,9 @@ struct em28xx_dmaqueue { #define MAX_EM28XX_INPUT 4 enum enum28xx_itype { - EM28XX_VMUX_COMPOSITE1 = 1, - EM28XX_VMUX_COMPOSITE2, - EM28XX_VMUX_COMPOSITE3, - EM28XX_VMUX_COMPOSITE4, + EM28XX_VMUX_COMPOSITE = 1, EM28XX_VMUX_SVIDEO, EM28XX_VMUX_TELEVISION, - EM28XX_VMUX_CABLE, - EM28XX_VMUX_DVB, - EM28XX_VMUX_DEBUG, EM28XX_RADIO, }; -- cgit v1.2.3 From 8dfbcc4351a0b6d2f2d77f367552f48ffefafe18 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 28 Jan 2016 09:22:44 -0200 Subject: [media] xc2028: avoid use after free If struct xc2028_config is passed without a firmware name, the following trouble may happen: [11009.907205] xc2028 5-0061: type set to XCeive xc2028/xc3028 tuner [11009.907491] ================================================================== [11009.907750] BUG: KASAN: use-after-free in strcmp+0x96/0xb0 at addr ffff8803bd78ab40 [11009.907992] Read of size 1 by task modprobe/28992 [11009.907994] ============================================================================= [11009.907997] BUG kmalloc-16 (Tainted: G W ): kasan: bad access detected [11009.907999] ----------------------------------------------------------------------------- [11009.908008] INFO: Allocated in xhci_urb_enqueue+0x214/0x14c0 [xhci_hcd] age=0 cpu=3 pid=28992 [11009.908012] ___slab_alloc+0x581/0x5b0 [11009.908014] __slab_alloc+0x51/0x90 [11009.908017] __kmalloc+0x27b/0x350 [11009.908022] xhci_urb_enqueue+0x214/0x14c0 [xhci_hcd] [11009.908026] usb_hcd_submit_urb+0x1e8/0x1c60 [11009.908029] usb_submit_urb+0xb0e/0x1200 [11009.908032] usb_serial_generic_write_start+0xb6/0x4c0 [11009.908035] usb_serial_generic_write+0x92/0xc0 [11009.908039] usb_console_write+0x38a/0x560 [11009.908045] call_console_drivers.constprop.14+0x1ee/0x2c0 [11009.908051] console_unlock+0x40d/0x900 [11009.908056] vprintk_emit+0x4b4/0x830 [11009.908061] vprintk_default+0x1f/0x30 [11009.908064] printk+0x99/0xb5 [11009.908067] kasan_report_error+0x10a/0x550 [11009.908070] __asan_report_load1_noabort+0x43/0x50 [11009.908074] INFO: Freed in xc2028_set_config+0x90/0x630 [tuner_xc2028] age=1 cpu=3 pid=28992 [11009.908077] __slab_free+0x2ec/0x460 [11009.908080] kfree+0x266/0x280 [11009.908083] xc2028_set_config+0x90/0x630 [tuner_xc2028] [11009.908086] xc2028_attach+0x310/0x8a0 [tuner_xc2028] [11009.908090] em28xx_attach_xc3028.constprop.7+0x1f9/0x30d [em28xx_dvb] [11009.908094] em28xx_dvb_init.part.3+0x8e4/0x5cf4 [em28xx_dvb] [11009.908098] em28xx_dvb_init+0x81/0x8a [em28xx_dvb] [11009.908101] em28xx_register_extension+0xd9/0x190 [em28xx] [11009.908105] em28xx_dvb_register+0x10/0x1000 [em28xx_dvb] [11009.908108] do_one_initcall+0x141/0x300 [11009.908111] do_init_module+0x1d0/0x5ad [11009.908114] load_module+0x6666/0x9ba0 [11009.908117] SyS_finit_module+0x108/0x130 [11009.908120] entry_SYSCALL_64_fastpath+0x16/0x76 [11009.908123] INFO: Slab 0xffffea000ef5e280 objects=25 used=25 fp=0x (null) flags=0x2ffff8000004080 [11009.908126] INFO: Object 0xffff8803bd78ab40 @offset=2880 fp=0x0000000000000001 [11009.908130] Bytes b4 ffff8803bd78ab30: 01 00 00 00 2a 07 00 00 9d 28 00 00 01 00 00 00 ....*....(...... [11009.908133] Object ffff8803bd78ab40: 01 00 00 00 00 00 00 00 b0 1d c3 6a 00 88 ff ff ...........j.... [11009.908137] CPU: 3 PID: 28992 Comm: modprobe Tainted: G B W 4.5.0-rc1+ #43 [11009.908140] Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015 [11009.908142] ffff8803bd78a000 ffff8802c273f1b8 ffffffff81932007 ffff8803c6407a80 [11009.908148] ffff8802c273f1e8 ffffffff81556759 ffff8803c6407a80 ffffea000ef5e280 [11009.908153] ffff8803bd78ab40 dffffc0000000000 ffff8802c273f210 ffffffff8155ccb4 [11009.908158] Call Trace: [11009.908162] [] dump_stack+0x4b/0x64 [11009.908165] [] print_trailer+0xf9/0x150 [11009.908168] [] object_err+0x34/0x40 [11009.908171] [] kasan_report_error+0x230/0x550 [11009.908175] [] ? trace_hardirqs_off_caller+0x21/0x290 [11009.908179] [] ? kasan_unpoison_shadow+0x36/0x50 [11009.908182] [] __asan_report_load1_noabort+0x43/0x50 [11009.908185] [] ? __asan_register_globals+0x50/0xa0 [11009.908189] [] ? strcmp+0x96/0xb0 [11009.908192] [] strcmp+0x96/0xb0 [11009.908196] [] xc2028_set_config+0x15c/0x630 [tuner_xc2028] [11009.908200] [] xc2028_attach+0x310/0x8a0 [tuner_xc2028] [11009.908203] [] ? memset+0x28/0x30 [11009.908206] [] ? xc2028_set_config+0x630/0x630 [tuner_xc2028] [11009.908211] [] em28xx_attach_xc3028.constprop.7+0x1f9/0x30d [em28xx_dvb] [11009.908215] [] ? em28xx_dvb_init.part.3+0x37c/0x5cf4 [em28xx_dvb] [11009.908219] [] ? hauppauge_hvr930c_init+0x487/0x487 [em28xx_dvb] [11009.908222] [] ? lgdt330x_attach+0x1cc/0x370 [lgdt330x] [11009.908226] [] ? i2c_read_demod_bytes.isra.2+0x210/0x210 [lgdt330x] [11009.908230] [] ? ref_module.part.15+0x10/0x10 [11009.908233] [] ? module_assert_mutex_or_preempt+0x80/0x80 [11009.908238] [] em28xx_dvb_init.part.3+0x8e4/0x5cf4 [em28xx_dvb] [11009.908242] [] ? em28xx_attach_xc3028.constprop.7+0x30d/0x30d [em28xx_dvb] [11009.908245] [] ? string+0x14d/0x1f0 [11009.908249] [] ? symbol_string+0xff/0x1a0 [11009.908253] [] ? uuid_string+0x6f0/0x6f0 [11009.908257] [] ? __kernel_text_address+0x7e/0xa0 [11009.908260] [] ? print_context_stack+0x7f/0xf0 [11009.908264] [] ? __module_address+0xb6/0x360 [11009.908268] [] ? is_ftrace_trampoline+0x99/0xe0 [11009.908271] [] ? __kernel_text_address+0x7e/0xa0 [11009.908275] [] ? debug_check_no_locks_freed+0x290/0x290 [11009.908278] [] ? dump_trace+0x11b/0x300 [11009.908282] [] ? em28xx_register_extension+0x23/0x190 [em28xx] [11009.908285] [] ? trace_hardirqs_off_caller+0x21/0x290 [11009.908289] [] ? trace_hardirqs_on_caller+0x16/0x590 [11009.908292] [] ? trace_hardirqs_on+0xd/0x10 [11009.908296] [] ? em28xx_register_extension+0x23/0x190 [em28xx] [11009.908299] [] ? mutex_trylock+0x400/0x400 [11009.908302] [] ? do_one_initcall+0x131/0x300 [11009.908306] [] ? call_rcu_sched+0x17/0x20 [11009.908309] [] ? put_object+0x48/0x70 [11009.908314] [] em28xx_dvb_init+0x81/0x8a [em28xx_dvb] [11009.908317] [] em28xx_register_extension+0xd9/0x190 [em28xx] [11009.908320] [] ? 0xffffffffa0150000 [11009.908324] [] em28xx_dvb_register+0x10/0x1000 [em28xx_dvb] [11009.908327] [] do_one_initcall+0x141/0x300 [11009.908330] [] ? try_to_run_init_process+0x40/0x40 [11009.908333] [] ? trace_hardirqs_on_caller+0x16/0x590 [11009.908337] [] ? kasan_unpoison_shadow+0x36/0x50 [11009.908340] [] ? kasan_unpoison_shadow+0x36/0x50 [11009.908343] [] ? kasan_unpoison_shadow+0x36/0x50 [11009.908346] [] ? __asan_register_globals+0x87/0xa0 [11009.908350] [] do_init_module+0x1d0/0x5ad [11009.908353] [] load_module+0x6666/0x9ba0 [11009.908356] [] ? symbol_put_addr+0x50/0x50 [11009.908361] [] ? em28xx_dvb_init.part.3+0x5989/0x5cf4 [em28xx_dvb] [11009.908366] [] ? module_frob_arch_sections+0x20/0x20 [11009.908369] [] ? open_exec+0x50/0x50 [11009.908374] [] ? ns_capable+0x5b/0xd0 [11009.908377] [] SyS_finit_module+0x108/0x130 [11009.908379] [] ? SyS_init_module+0x1f0/0x1f0 [11009.908383] [] ? lockdep_sys_exit_thunk+0x12/0x14 [11009.908394] [] entry_SYSCALL_64_fastpath+0x16/0x76 [11009.908396] Memory state around the buggy address: [11009.908398] ffff8803bd78aa00: 00 00 fc fc fc fc fc fc fc fc fc fc fc fc fc fc [11009.908401] ffff8803bd78aa80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [11009.908403] >ffff8803bd78ab00: fc fc fc fc fc fc fc fc 00 00 fc fc fc fc fc fc [11009.908405] ^ [11009.908407] ffff8803bd78ab80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [11009.908409] ffff8803bd78ac00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [11009.908411] ================================================================== In order to avoid it, let's set the cached value of the firmware name to NULL after freeing it. While here, return an error if the memory allocation fails. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/tuner-xc2028.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c index 4e941f00b600..082ff5608455 100644 --- a/drivers/media/tuners/tuner-xc2028.c +++ b/drivers/media/tuners/tuner-xc2028.c @@ -1403,11 +1403,12 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) * in order to avoid troubles during device release. */ kfree(priv->ctrl.fname); + priv->ctrl.fname = NULL; memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); if (p->fname) { priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); if (priv->ctrl.fname == NULL) - rc = -ENOMEM; + return -ENOMEM; } /* -- cgit v1.2.3 From 163c9bca101caf000691b56fb3834905e62cbba3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 Jan 2016 08:39:33 -0200 Subject: [media] tuner.h: rename TUNER_PAD_IF_OUTPUT to TUNER_PAD_OUTPUT The output of a tuner is not only IF frequencies. They may also output audio on some of its pins, and may even be a zero-IF tuner, with outputs a baseband. So, rename the PAD name to make it clearer and add a proper documentation about that at tuner.h. No functional changes. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 2 +- drivers/media/usb/au0828/au0828-core.c | 2 +- drivers/media/usb/cx231xx/cx231xx-cards.c | 2 +- drivers/media/usb/dvb-usb-v2/mxl111sf.c | 2 +- drivers/media/v4l2-core/tuner-core.c | 2 +- include/media/tuner.h | 21 ++++++++++++++++++--- 6 files changed, 23 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 560450a0b32a..a7de62ebc415 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -661,7 +661,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap, if (ntuner && ndemod) { ret = media_create_pad_links(mdev, MEDIA_ENT_F_TUNER, - tuner, TUNER_PAD_IF_OUTPUT, + tuner, TUNER_PAD_OUTPUT, MEDIA_ENT_F_DTV_DEMOD, demod, 0, MEDIA_LNK_FL_ENABLED, false); diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index 9e29e70a78d7..df2bc3f732b6 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -276,7 +276,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev) return -EINVAL; if (tuner) { - ret = media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT, + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, decoder, 0, MEDIA_LNK_FL_ENABLED); if (ret) diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 620b83d03f75..54e43fe13e6d 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1259,7 +1259,7 @@ static int cx231xx_create_media_graph(struct cx231xx *dev) return 0; if (tuner) { - ret = media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT, decoder, 0, + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, decoder, 0, MEDIA_LNK_FL_ENABLED); if (ret < 0) return ret; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index b669deccc34c..e7978e4e40ea 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -888,7 +888,7 @@ static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap) state->tuner.function = MEDIA_ENT_F_TUNER; state->tuner.name = "mxl111sf tuner"; state->tuner_pads[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; - state->tuner_pads[TUNER_PAD_IF_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + state->tuner_pads[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&state->tuner, TUNER_NUM_PADS, state->tuner_pads); diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index 76496fd282aa..a1f858b34187 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -697,7 +697,7 @@ static int tuner_probe(struct i2c_client *client, register_client: #if defined(CONFIG_MEDIA_CONTROLLER) t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; - t->pad[TUNER_PAD_IF_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; t->sd.entity.function = MEDIA_ENT_F_TUNER; t->sd.entity.name = t->name; diff --git a/include/media/tuner.h b/include/media/tuner.h index e5321fda5489..c5994fe865a0 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -21,11 +21,26 @@ #include -/* Tuner PADs */ -/* FIXME: is this the right place for it? */ +/** + * enum tuner_pad_index - tuner pad index + * + * @TUNER_PAD_RF_INPUT: Radiofrequency (RF) sink pad, usually linked to a + * RF connector entity. + * @TUNER_PAD_OUTPUT: Tuner output pad. This is actually more complex than + * a single pad output, as, in addition to luminance and + * chrominance IF a tuner may have internally an + * audio decoder (like xc3028) or it may produce an audio + * IF that will be used by an audio decoder like msp34xx. + * It may also have an IF-PLL demodulator on it, like + * tuners with tda9887. Yet, currently, we don't need to + * represent all the dirty details, as this is transparent + * for the V4L2 API usage. So, let's represent all kinds + * of different outputs as a single source pad. + * @TUNER_NUM_PADS: Number of pads of the tuner. + */ enum tuner_pad_index { TUNER_PAD_RF_INPUT, - TUNER_PAD_IF_OUTPUT, + TUNER_PAD_OUTPUT, TUNER_NUM_PADS }; -- cgit v1.2.3 From 5c9077eabc9a0ffbd4c8b0724ddcd69ef2b1a7ed Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 07:00:08 -0200 Subject: [media] v4l2-mc.h: Split audio from baseband output Analog TV tuners have a separate output pad for the audio IF or audio sampled data. This pad is connected to a different chipset. Add an extra pad for it and improve the documentation. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/tuner-core.c | 1 + include/media/v4l2-mc.h | 28 +++++++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index a1f858b34187..d6bd9ce1101d 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -698,6 +698,7 @@ register_client: #if defined(CONFIG_MEDIA_CONTROLLER) t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + t->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; t->sd.entity.function = MEDIA_ENT_F_TUNER; t->sd.entity.name = t->name; diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index f6fcd70f3548..c174e5b4f188 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -19,20 +19,26 @@ * * @TUNER_PAD_RF_INPUT: Radiofrequency (RF) sink pad, usually linked to a * RF connector entity. - * @TUNER_PAD_OUTPUT: Tuner output pad. This is actually more complex than - * a single pad output, as, in addition to luminance and - * chrominance IF a tuner may have internally an - * audio decoder (like xc3028) or it may produce an audio - * IF that will be used by an audio decoder like msp34xx. - * It may also have an IF-PLL demodulator on it, like - * tuners with tda9887. Yet, currently, we don't need to - * represent all the dirty details, as this is transparent - * for the V4L2 API usage. So, let's represent all kinds - * of different outputs as a single source pad. + * @TUNER_PAD_OUTPUT: Tuner video output source pad. Contains the video + * chrominance and luminance or the hole bandwidth + * of the signal converted to an Intermediate Frequency + * (IF) or to baseband (on zero-IF tuners). + * @TUNER_PAD_AUD_OUT: Tuner audio output source pad. Tuners used to decode + * analog TV signals have an extra pad for audio output. + * Old tuners use an analog stage with a saw filter for + * the audio IF frequency. The output of the pad is, in + * this case, the audio IF, with should be decoded either + * by the bridge chipset (that's the case of cx2388x + * chipsets) or may require an external IF sound + * processor, like msp34xx. On modern silicon tuners, + * the audio IF decoder is usually incorporated at the + * tuner. On such case, the output of this pad is an + * audio sampled data. * @TUNER_NUM_PADS: Number of pads of the tuner. */ enum tuner_pad_index { TUNER_PAD_RF_INPUT, TUNER_PAD_OUTPUT, + TUNER_PAD_AUD_OUT, TUNER_NUM_PADS -}; \ No newline at end of file +}; -- cgit v1.2.3 From 953a457e50958494cfa90b41a13c26e9fb04195c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 07:00:37 -0200 Subject: [media] v4l2-mc.h Add pads for audio and video IF-PLL decoders The audio and video IF-PLL decoders have one sink and one source PAD. Add macro names for those pads and describe what kind of signals are represented at such pads. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/tuner-core.c | 27 +++++++++++++++++++++------ include/media/v4l2-mc.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index d6bd9ce1101d..731487be5baa 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -696,17 +696,32 @@ static int tuner_probe(struct i2c_client *client, /* Should be just before return */ register_client: #if defined(CONFIG_MEDIA_CONTROLLER) - t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; - t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; - t->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; - t->sd.entity.function = MEDIA_ENT_F_TUNER; t->sd.entity.name = t->name; + /* + * Handle the special case where the tuner has actually + * two stages: the PLL to tune into a frequency and the + * IF-PLL demodulator (tda988x). + */ + if (t->type == TUNER_TDA9887) { + t->pad[IF_VID_DEC_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + t->pad[IF_VID_DEC_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&t->sd.entity, + IF_VID_DEC_PAD_NUM_PADS, + &t->pad[0]); + t->sd.entity.function = MEDIA_ENT_F_IF_VID_DECODER; + } else { + t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; + t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + t->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&t->sd.entity, TUNER_NUM_PADS, + &t->pad[0]); + t->sd.entity.function = MEDIA_ENT_F_TUNER; + } - ret = media_entity_pads_init(&t->sd.entity, TUNER_NUM_PADS, &t->pad[0]); if (ret < 0) { tuner_err("failed to initialize media entity!\n"); kfree(t); - return -ENODEV; + return ret; } #endif /* Sets a default mode */ diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index c174e5b4f188..6a6ef5bc767e 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -42,3 +42,35 @@ enum tuner_pad_index { TUNER_PAD_AUD_OUT, TUNER_NUM_PADS }; + +/** + * enum if_vid_dec_index - video IF-PLL pad index for + * MEDIA_ENT_F_IF_VID_DECODER + * + * @IF_VID_DEC_PAD_IF_INPUT: video Intermediate Frequency (IF) sink pad + * @IF_VID_DEC_PAD_OUT: IF-PLL video output source pad. Contains the + * video chrominance and luminance IF signals. + * @IF_VID_DEC_PAD_NUM_PADS: Number of pads of the video IF-PLL. + */ +enum if_vid_dec_pad_index { + IF_VID_DEC_PAD_IF_INPUT, + IF_VID_DEC_PAD_OUT, + IF_VID_DEC_PAD_NUM_PADS +}; + +/** + * enum if_aud_dec_index - audio/sound IF-PLL pad index for + * MEDIA_ENT_F_IF_AUD_DECODER + * + * @IF_AUD_DEC_PAD_IF_INPUT: audio Intermediate Frequency (IF) sink pad + * @IF_AUD_DEC_PAD_OUT: IF-PLL audio output source pad. Contains the + * audio sampled stream data, usually connected + * to the bridge bus via an Inter-IC Sound (I2S) + * bus. + * @IF_AUD_DEC_PAD_NUM_PADS: Number of pads of the audio IF-PLL. + */ +enum if_aud_dec_pad_index { + IF_AUD_DEC_PAD_IF_INPUT, + IF_AUD_DEC_PAD_OUT, + IF_AUD_DEC_PAD_NUM_PADS +}; -- cgit v1.2.3 From 55606310e77f5099d01b59ea9a25401f521c5713 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 Jan 2016 12:08:13 -0200 Subject: [media] tvp5150: create the expected number of pads The tvp5150 doesn't have just one pad. It has 3 ones: - IF input - Video output - VBI output Fix it and use the macros for the pad indexes. Reviewed-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 0ad122fcd632..20428f052506 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "tvp5150_reg.h" @@ -37,7 +38,9 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); struct tvp5150 { struct v4l2_subdev sd; - struct media_pad pad; +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_pad pads[DEMOD_NUM_PADS]; +#endif struct v4l2_ctrl_handler hdl; struct v4l2_rect rect; @@ -1313,8 +1316,10 @@ static int tvp5150_probe(struct i2c_client *c, sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; #if defined(CONFIG_MEDIA_CONTROLLER) - core->pad.flags = MEDIA_PAD_FL_SOURCE; - res = media_entity_pads_init(&sd->entity, 1, &core->pad); + core->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + core->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; + core->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; + res = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, core->pads); if (res < 0) return res; #endif -- cgit v1.2.3 From fb4932821731f58353d23f6673b55a9612a1cb57 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 28 Jan 2016 08:51:01 -0200 Subject: [media] msp3400: initialize MC data Add pads and set the device type when used with the media controller. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/msp3400-driver.c | 14 ++++++++++++++ drivers/media/i2c/msp3400-driver.h | 5 +++++ 2 files changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c index a84561d0d4a8..e016626ebf89 100644 --- a/drivers/media/i2c/msp3400-driver.c +++ b/drivers/media/i2c/msp3400-driver.c @@ -688,6 +688,9 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) int msp_revision; int msp_product, msp_prod_hi, msp_prod_lo; int msp_rom; +#if defined(CONFIG_MEDIA_CONTROLLER) + int ret; +#endif if (!id) strlcpy(client->name, "msp3400", sizeof(client->name)); @@ -704,6 +707,17 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &msp_ops); +#if defined(CONFIG_MEDIA_CONTROLLER) + state->pads[IF_AUD_DEC_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + state->pads[IF_AUD_DEC_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE; + + sd->entity.function = MEDIA_ENT_F_IF_AUD_DECODER; + + ret = media_entity_pads_init(&sd->entity, 2, state->pads); + if (ret < 0) + return ret; +#endif + state->v4l2_std = V4L2_STD_NTSC; state->detected_std = V4L2_STD_ALL; state->audmode = V4L2_TUNER_MODE_STEREO; diff --git a/drivers/media/i2c/msp3400-driver.h b/drivers/media/i2c/msp3400-driver.h index 6cae21366ed5..f0bb37dc9013 100644 --- a/drivers/media/i2c/msp3400-driver.h +++ b/drivers/media/i2c/msp3400-driver.h @@ -7,6 +7,7 @@ #include #include #include +#include /* ---------------------------------------------------------------------- */ @@ -102,6 +103,10 @@ struct msp_state { wait_queue_head_t wq; unsigned int restart:1; unsigned int watch_stereo:1; + +#if CONFIG_MEDIA_CONTROLLER + struct media_pad pads[IF_AUD_DEC_PAD_NUM_PADS]; +#endif }; static inline struct msp_state *to_state(struct v4l2_subdev *sd) -- cgit v1.2.3 From f92c70ad28341b6430c64332521428768058dd17 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 Jan 2016 15:09:15 -0200 Subject: [media] tvp5150: identify it as a MEDIA_ENT_F_ATV_DECODER The tvp5150 is an analog TV decoder. Identify as such at the media graph, or otherwise devices using it would fail. That avoids the following warning: [ 1546.669139] usb 2-3.3: Entity type for entity tvp5150 5-005c was not initialized! Reviewed-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 20428f052506..19b52736b24e 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1319,6 +1319,9 @@ static int tvp5150_probe(struct i2c_client *c, core->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; core->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; core->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; + + sd->entity.function = MEDIA_ENT_F_ATV_DECODER; + res = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, core->pads); if (res < 0) return res; -- cgit v1.2.3 From af7d374a4cf715d7b7f535bcc30d814faf6a5cf6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 08:44:28 -0200 Subject: [media] saa7115: initialize demod type and add the needed pads The saa7115 driver is used on several em28xx-based devices. Now that we're about to add MC support to em28xx, we need to be sure that the saa711x demod will be properly mapped at MC. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/saa7115.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index 24d2b76dbe97..d2a1ce2bc7f5 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -74,6 +75,9 @@ enum saa711x_model { struct saa711x_state { struct v4l2_subdev sd; +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_pad pads[DEMOD_NUM_PADS]; +#endif struct v4l2_ctrl_handler hdl; struct { @@ -1809,6 +1813,9 @@ static int saa711x_probe(struct i2c_client *client, struct saa7115_platform_data *pdata; int ident; char name[CHIP_VER_SIZE + 1]; +#if defined(CONFIG_MEDIA_CONTROLLER) + int ret; +#endif /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -1832,6 +1839,18 @@ static int saa711x_probe(struct i2c_client *client, sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &saa711x_ops); +#if defined(CONFIG_MEDIA_CONTROLLER) + state->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + state->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; + state->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; + + sd->entity.function = MEDIA_ENT_F_ATV_DECODER; + + ret = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, state->pads); + if (ret < 0) + return ret; +#endif + v4l_info(client, "%s found @ 0x%x (%s)\n", name, client->addr << 1, client->adapter->name); hdl = &state->hdl; -- cgit v1.2.3 From 56a7f51554b22729cee87042ea697a0d59b13d6b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 13:08:19 -0200 Subject: [media] em28xx: unregister devices in case of failure If something bad happens during device registration, unregister the already registered devices. Without that, it will have lots of KASAN errors when udev would try to open the devices. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 52428b4cce5f..8c87f3fbd0cf 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -2579,6 +2579,22 @@ static int em28xx_v4l2_init(struct em28xx *dev) return 0; unregister_dev: + if (video_is_registered(&v4l2->radio_dev)) { + em28xx_info("V4L2 device %s deregistered\n", + video_device_node_name(&v4l2->radio_dev)); + video_unregister_device(&v4l2->radio_dev); + } + if (video_is_registered(&v4l2->vbi_dev)) { + em28xx_info("V4L2 device %s deregistered\n", + video_device_node_name(&v4l2->vbi_dev)); + video_unregister_device(&v4l2->vbi_dev); + } + if (video_is_registered(&v4l2->vdev)) { + em28xx_info("V4L2 device %s deregistered\n", + video_device_node_name(&v4l2->vdev)); + video_unregister_device(&v4l2->vdev); + } + v4l2_ctrl_handler_free(&v4l2->ctrl_handler); v4l2_device_unregister(&v4l2->v4l2_dev); err: -- cgit v1.2.3 From 41a5e7ea7d25f207e5d1c71c9cfe5c07aa5fd055 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 10:11:57 -0200 Subject: [media] em28xx: fix tuner detection for Pixelview Prolink PlayTV USB 2.0 The tuner is at address 0x60. This address is not probed by default by tuner anymore, so we need to explicitly add it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index ab0fe0319991..2001c9c14784 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -1555,6 +1555,7 @@ struct em28xx_board em28xx_boards[] = { .buttons = std_snapshot_button, .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_YMEC_TVF_5533MF, + .tuner_addr = 0x60, .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, -- cgit v1.2.3 From 22580f7cb9dfc11db233f48a5e257566f508f5c3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 12:53:56 -0200 Subject: [media] em28xx: make sure that the device has video There are some devices, like Terratec Cinergy HTC, where while the device supports analog TV, the driver is not capable yet of handling it, because the analog TV driver was not written. So, don't bind the em28xx-v4l drivers on such devices. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 2001c9c14784..ec4e95119877 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -3468,7 +3468,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, /* save our data pointer in this interface device */ usb_set_intfdata(interface, dev); - /* allocate device struct */ + /* allocate device struct and check if the device is a webcam */ mutex_init(&dev->lock); retval = em28xx_init_dev(dev, udev, interface, nr); if (retval) { @@ -3484,6 +3484,15 @@ static int em28xx_usb_probe(struct usb_interface *interface, try_bulk = usb_xfer_mode > 0; } + /* Disable V4L2 if the device doesn't have a decoder */ + if (has_video && + dev->board.decoder == EM28XX_NODECODER && !dev->board.is_webcam) { + printk(DRIVER_NAME + ": Currently, V4L2 is not supported on this model\n"); + has_video = false; + dev->has_video = false; + } + /* Select USB transfer types to use */ if (has_video) { if (!dev->analog_ep_isoc || (try_bulk && dev->analog_ep_bulk)) -- cgit v1.2.3 From 0962a763327bd33fd18c3a4d0a613cad0976a930 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 14:05:11 -0200 Subject: [media] em28xx: avoid divide by zero error [ 1841.243670] divide error: 0000 [#1] SMP KASAN [ 1841.243994] Modules linked in: em28xx_rc rc_core tda18271 drxk em28xx_dvb dvb_core em28xx_alsa mt9v011 em28xx_v4l videobuf2_vmalloc videobuf2_memops videobuf2_v4l2 videobuf2_core em28xx tveeprom v4l2_common videodev media cpufreq_powersave cpufreq_conservative cpufreq_userspace cpufreq_stats parport_pc ppdev lp parport snd_hda_codec_hdmi intel_rapl x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm iTCO_wdt iTCO_vendor_support irqbypass crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel sha256_ssse3 sha256_generic hmac drbg i915 snd_hda_codec_realtek snd_hda_codec_generic aesni_intel aes_x86_64 lrw gf128mul glue_helper ablk_helper cryptd btusb i2c_algo_bit snd_hda_intel btrtl drm_kms_helper btbcm evdev snd_hda_codec btintel psmouse bluetooth pcspkr snd_hwdep sg drm serio_raw [ 1841.244845] snd_hda_core snd_pcm mei_me rfkill snd_timer mei snd lpc_ich soundcore shpchp i2c_i801 mfd_core battery dw_dmac i2c_designware_platform i2c_designware_core dw_dmac_core video acpi_pad button tpm_tis tpm ext4 crc16 mbcache jbd2 dm_mod hid_generic usbhid sd_mod ahci libahci libata ehci_pci e1000e xhci_pci ptp scsi_mod ehci_hcd xhci_hcd pps_core fan thermal sdhci_acpi sdhci mmc_core i2c_hid hid [last unloaded: tveeprom] [ 1841.245342] CPU: 2 PID: 38 Comm: kworker/2:1 Tainted: G W 4.5.0-rc1+ #43 [ 1841.245413] Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015 [ 1841.245503] Workqueue: events request_module_async [em28xx] [ 1841.245557] task: ffff88009df10000 ti: ffff88009df18000 task.ti: ffff88009df18000 [ 1841.245626] RIP: 0010:[] [] size_to_scale+0xed/0x2c0 [em28xx_v4l] [ 1841.245714] RSP: 0018:ffff88009df1faa8 EFLAGS: 00010246 [ 1841.245756] RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff8803bb933b38 [ 1841.245815] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff8803bb933b00 [ 1841.245879] RBP: ffff88009df1fad8 R08: ffff8803bb933b3c R09: 1ffff10077726760 [ 1841.245944] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 [ 1841.246006] R13: 0000000000000000 R14: dffffc0000000000 R15: ffff8803b391a130 [ 1841.246071] FS: 0000000000000000(0000) GS:ffff8803c6900000(0000) knlGS:0000000000000000 [ 1841.246141] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1841.246194] CR2: 0000000001d97008 CR3: 00000003bdd85000 CR4: 00000000003406e0 [ 1841.246256] Stack: [ 1841.246278] 0000000000000246 ffff8803bb9321f0 ffff8803bb932270 ffffffffa136f7a0 [ 1841.246359] 0000000000000000 ffff8803bb932130 ffff88009df1fb20 ffffffffa13646a0 [ 1841.246439] ffffffffa127f206 ffff8803bb932130 ffff8803bb932130 ffff8803b391a130 [ 1841.246517] Call Trace: [ 1841.246548] [] em28xx_set_video_format+0x140/0x1e0 [em28xx_v4l] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 8c87f3fbd0cf..86db1e1f8ab5 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1232,6 +1232,12 @@ static void scale_to_size(struct em28xx *dev, *width = (((unsigned long)maxw) << 12) / (hscale + 4096L); *height = (((unsigned long)maxh) << 12) / (vscale + 4096L); + + /* Don't let width or height to be zero */ + if (*width < 1) + *width = 1; + if (*height < 1) + *height = 1; } /* ------------------------------------------------------------------ @@ -1307,6 +1313,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0); } + /* Avoid division by zero at size_to_scale */ + if (width < 1) + width = 1; + if (height < 1) + height = 1; size_to_scale(dev, width, height, &hscale, &vscale); scale_to_size(dev, hscale, vscale, &width, &height); -- cgit v1.2.3 From ac88fce987bd3433706b1082e8a85408de63512c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 14:33:12 -0200 Subject: [media] mt9v011: add media controller support Create a source pad and set the media controller type to the sensor. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/mt9v011.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c index b9fea11d6b0b..9ed1b26b6549 100644 --- a/drivers/media/i2c/mt9v011.c +++ b/drivers/media/i2c/mt9v011.c @@ -50,6 +50,9 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); struct mt9v011 { struct v4l2_subdev sd; +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_pad pad; +#endif struct v4l2_ctrl_handler ctrls; unsigned width, height; unsigned xtal; @@ -493,6 +496,9 @@ static int mt9v011_probe(struct i2c_client *c, u16 version; struct mt9v011 *core; struct v4l2_subdev *sd; +#ifdef CONFIG_MEDIA_CONTROLLER + int ret; +#endif /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(c->adapter, @@ -506,6 +512,15 @@ static int mt9v011_probe(struct i2c_client *c, sd = &core->sd; v4l2_i2c_subdev_init(sd, c, &mt9v011_ops); +#ifdef CONFIG_MEDIA_CONTROLLER + core->pad.flags = MEDIA_PAD_FL_SOURCE; + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; + + ret = media_entity_pads_init(&sd->entity, 1, &core->pad); + if (ret < 0) + return ret; +#endif + /* Check if the sensor is really a MT9V011 */ version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); if ((version != MT9V011_VERSION) && -- cgit v1.2.3 From 37ecc7b1278f4184a6869504f7074b4a54f112c5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 Jan 2016 07:07:24 -0200 Subject: [media] em28xx: add media controller support Add the needed bits to make em28xx to create a media controller graph. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-camera.c | 4 + drivers/media/usb/em28xx/em28xx-cards.c | 55 +++++- drivers/media/usb/em28xx/em28xx-dvb.c | 10 ++ drivers/media/usb/em28xx/em28xx-video.c | 294 ++++++++++++++++++++++++++++++- drivers/media/usb/em28xx/em28xx.h | 13 +- 5 files changed, 366 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c index b58acd3fcd99..72f3f4d50253 100644 --- a/drivers/media/usb/em28xx/em28xx-camera.c +++ b/drivers/media/usb/em28xx/em28xx-camera.c @@ -64,6 +64,8 @@ static int em28xx_initialize_mt9m111(struct em28xx *dev) i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], ®s[i][0], 3); + /* FIXME: This won't be creating a sensor at the media graph */ + return 0; } @@ -91,6 +93,8 @@ static int em28xx_initialize_mt9m001(struct em28xx *dev) i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], ®s[i][0], 3); + /* FIXME: This won't be creating a sensor at the media graph */ + return 0; } diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index ec4e95119877..ba442c967415 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -3013,6 +3013,48 @@ static void flush_request_modules(struct em28xx *dev) flush_work(&dev->request_module_wk); } +static int em28xx_media_device_init(struct em28xx *dev, + struct usb_device *udev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *mdev; + + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return -ENOMEM; + + mdev->dev = &udev->dev; + + if (!dev->name) + strlcpy(mdev->model, "unknown em28xx", sizeof(mdev->model)); + else + strlcpy(mdev->model, dev->name, sizeof(mdev->model)); + if (udev->serial) + strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); + strcpy(mdev->bus_info, udev->devpath); + mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); + mdev->driver_version = LINUX_VERSION_CODE; + + media_device_init(mdev); + + dev->media_dev = mdev; +#endif + return 0; +} + +static void em28xx_unregister_media_device(struct em28xx *dev) +{ + +#ifdef CONFIG_MEDIA_CONTROLLER + if (dev->media_dev) { + media_device_unregister(dev->media_dev); + media_device_cleanup(dev->media_dev); + kfree(dev->media_dev); + dev->media_dev = NULL; + } +#endif +} + /* * em28xx_release_resources() * unregisters the v4l2,i2c and usb devices @@ -3024,6 +3066,8 @@ static void em28xx_release_resources(struct em28xx *dev) mutex_lock(&dev->lock); + em28xx_unregister_media_device(dev); + if (dev->def_i2c_bus) em28xx_i2c_unregister(dev, 1); em28xx_i2c_unregister(dev, 0); @@ -3168,6 +3212,8 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, */ snprintf(dev->name, sizeof(dev->name), "%s #%d", chip_name, dev->devno); + em28xx_media_device_init(dev, udev); + if (dev->is_audio_only) { retval = em28xx_audio_setup(dev); if (retval) @@ -3511,9 +3557,14 @@ static int em28xx_usb_probe(struct usb_interface *interface, request_modules(dev); - /* Should be the last thing to do, to avoid newer udev's to - open the device before fully initializing it + /* + * Do it at the end, to reduce dynamic configuration changes during + * the device init. Yet, as request_modules() can be async, the + * topology will likely change after the load of the em28xx subdrivers. */ +#ifdef CONFIG_MEDIA_CONTROLLER + retval = media_device_register(dev->media_dev); +#endif return 0; diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index bf5c24467c65..ea80541d58f0 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -916,6 +916,9 @@ static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module, dev->name, result); goto fail_adapter; } +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + dvb->adapter.mdev = dev->media_dev; +#endif /* Ensure all frontends negotiate bus access */ dvb->fe[0]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; @@ -994,8 +997,15 @@ static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module, /* register network adapter */ dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); + + result = dvb_create_media_graph(&dvb->adapter, false); + if (result < 0) + goto fail_create_graph; + return 0; +fail_create_graph: + dvb_net_release(&dvb->net); fail_fe_conn: dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); fail_fe_mem: diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 86db1e1f8ab5..16a2d4039330 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -866,6 +866,275 @@ static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type) em28xx_videodbg("res: put %d\n", res_type); } +static void em28xx_v4l2_media_release(struct em28xx *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + int i; + + for (i = 0; i < MAX_EM28XX_INPUT; i++) { + if (!INPUT(i)->type) + return; + media_device_unregister_entity(&dev->input_ent[i]); + } +#endif +} + +/* + * Media Controller helper functions + */ + +static int em28xx_v4l2_create_media_graph(struct em28xx *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct em28xx_v4l2 *v4l2 = dev->v4l2; + struct media_device *mdev = dev->media_dev; + struct media_entity *entity; + struct media_entity *if_vid = NULL, *if_aud = NULL; + struct media_entity *tuner = NULL, *decoder = NULL; + int i, ret; + + if (!mdev) + return 0; + + /* Webcams are really simple */ + if (dev->board.is_webcam) { + media_device_for_each_entity(entity, mdev) { + if (entity->function != MEDIA_ENT_F_CAM_SENSOR) + continue; + ret = media_create_pad_link(entity, 0, + &v4l2->vdev.entity, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + return 0; + } + + /* Non-webcams have analog TV decoder and other complexities */ + + media_device_for_each_entity(entity, mdev) { + switch (entity->function) { + case MEDIA_ENT_F_IF_VID_DECODER: + if_vid = entity; + break; + case MEDIA_ENT_F_IF_AUD_DECODER: + if_aud = entity; + break; + case MEDIA_ENT_F_TUNER: + tuner = entity; + break; + case MEDIA_ENT_F_ATV_DECODER: + decoder = entity; + break; + } + } + + /* Analog setup, using tuner as a link */ + + /* Something bad happened! */ + if (!decoder) + return -EINVAL; + + if (tuner) { + if (if_vid) { + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, + if_vid, + IF_VID_DEC_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT, + decoder, DEMOD_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } else { + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, + decoder, DEMOD_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + if (if_aud) { + ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT, + if_aud, + IF_AUD_DEC_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } else { + if_aud = tuner; + } + + } + ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT, + &v4l2->vdev.entity, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + + if (em28xx_vbi_supported(dev)) { + ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT, + &v4l2->vbi_dev.entity, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + for (i = 0; i < MAX_EM28XX_INPUT; i++) { + struct media_entity *ent = &dev->input_ent[i]; + + if (!INPUT(i)->type) + break; + + switch (INPUT(i)->type) { + case EM28XX_VMUX_COMPOSITE: + case EM28XX_VMUX_SVIDEO: + ret = media_create_pad_link(ent, 0, decoder, + DEMOD_PAD_IF_INPUT, 0); + if (ret) + return ret; + break; + default: /* EM28XX_VMUX_TELEVISION or EM28XX_RADIO */ + if (!tuner) + break; + + ret = media_create_pad_link(ent, 0, tuner, + TUNER_PAD_RF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + break; + } + } +#endif + return 0; +} + +static int em28xx_enable_analog_tuner(struct em28xx *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *mdev = dev->media_dev; + struct em28xx_v4l2 *v4l2 = dev->v4l2; + struct media_entity *source; + struct media_link *link, *found_link = NULL; + int ret, active_links = 0; + + if (!mdev || !v4l2->decoder) + return 0; + + /* + * This will find the tuner that is connected into the decoder. + * Technically, this is not 100% correct, as the device may be + * using an analog input instead of the tuner. However, as we can't + * do DVB streaming while the DMA engine is being used for V4L2, + * this should be enough for the actual needs. + */ + list_for_each_entry(link, &v4l2->decoder->links, list) { + if (link->sink->entity == v4l2->decoder) { + found_link = link; + if (link->flags & MEDIA_LNK_FL_ENABLED) + active_links++; + break; + } + } + + if (active_links == 1 || !found_link) + return 0; + + source = found_link->source->entity; + list_for_each_entry(link, &source->links, list) { + struct media_entity *sink; + int flags = 0; + + sink = link->sink->entity; + + if (sink == v4l2->decoder) + flags = MEDIA_LNK_FL_ENABLED; + + ret = media_entity_setup_link(link, flags); + if (ret) { + pr_err("Couldn't change link %s->%s to %s. Error %d\n", + source->name, sink->name, + flags ? "enabled" : "disabled", + ret); + return ret; + } else + em28xx_videodbg("link %s->%s was %s\n", + source->name, sink->name, + flags ? "ENABLED" : "disabled"); + } +#endif + return 0; +} + +static const char * const iname[] = { + [EM28XX_VMUX_COMPOSITE] = "Composite", + [EM28XX_VMUX_SVIDEO] = "S-Video", + [EM28XX_VMUX_TELEVISION] = "Television", + [EM28XX_RADIO] = "Radio", +}; + +static void em28xx_v4l2_create_entities(struct em28xx *dev) +{ +#if defined(CONFIG_MEDIA_CONTROLLER) + struct em28xx_v4l2 *v4l2 = dev->v4l2; + int ret, i; + + /* Initialize Video, VBI and Radio pads */ + v4l2->video_pad.flags = MEDIA_PAD_FL_SINK; + ret = media_entity_pads_init(&v4l2->vdev.entity, 1, &v4l2->video_pad); + if (ret < 0) + pr_err("failed to initialize video media entity!\n"); + + if (em28xx_vbi_supported(dev)) { + v4l2->vbi_pad.flags = MEDIA_PAD_FL_SINK; + ret = media_entity_pads_init(&v4l2->vbi_dev.entity, 1, + &v4l2->vbi_pad); + if (ret < 0) + pr_err("failed to initialize vbi media entity!\n"); + } + + /* Webcams don't have input connectors */ + if (dev->board.is_webcam) + return; + + /* Create entities for each input connector */ + for (i = 0; i < MAX_EM28XX_INPUT; i++) { + struct media_entity *ent = &dev->input_ent[i]; + + if (!INPUT(i)->type) + break; + + ent->name = iname[INPUT(i)->type]; + ent->flags = MEDIA_ENT_FL_CONNECTOR; + dev->input_pad[i].flags = MEDIA_PAD_FL_SOURCE; + + switch (INPUT(i)->type) { + case EM28XX_VMUX_COMPOSITE: + ent->function = MEDIA_ENT_F_CONN_COMPOSITE; + break; + case EM28XX_VMUX_SVIDEO: + ent->function = MEDIA_ENT_F_CONN_SVIDEO; + break; + default: /* EM28XX_VMUX_TELEVISION or EM28XX_RADIO */ + ent->function = MEDIA_ENT_F_CONN_RF; + break; + } + + ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]); + if (ret < 0) + pr_err("failed to initialize input pad[%d]!\n", i); + + ret = media_device_register_entity(dev->media_dev, ent); + if (ret < 0) + pr_err("failed to register input entity %d!\n", i); + } +#endif +} + + /* ------------------------------------------------------------------ Videobuf2 operations ------------------------------------------------------------------*/ @@ -883,6 +1152,9 @@ static int queue_setup(struct vb2_queue *vq, return sizes[0] < size ? -EINVAL : 0; *nplanes = 1; sizes[0] = size; + + em28xx_enable_analog_tuner(dev); + return 0; } @@ -1453,13 +1725,6 @@ static int vidioc_s_parm(struct file *file, void *priv, 0, video, s_parm, p); } -static const char * const iname[] = { - [EM28XX_VMUX_COMPOSITE] = "Composite", - [EM28XX_VMUX_SVIDEO] = "S-Video", - [EM28XX_VMUX_TELEVISION] = "Television", - [EM28XX_RADIO] = "Radio", -}; - static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) { @@ -1974,6 +2239,8 @@ static int em28xx_v4l2_fini(struct em28xx *dev) em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE); + em28xx_v4l2_media_release(dev); + if (video_is_registered(&v4l2->radio_dev)) { em28xx_info("V4L2 device %s deregistered\n", video_device_node_name(&v4l2->radio_dev)); @@ -2297,6 +2564,9 @@ static int em28xx_v4l2_init(struct em28xx *dev) v4l2->dev = dev; dev->v4l2 = v4l2; +#ifdef CONFIG_MEDIA_CONTROLLER + v4l2->v4l2_dev.mdev = dev->media_dev; +#endif ret = v4l2_device_register(&dev->udev->dev, &v4l2->v4l2_dev); if (ret < 0) { em28xx_errdev("Call to v4l2_device_register() failed!\n"); @@ -2569,6 +2839,16 @@ static int em28xx_v4l2_init(struct em28xx *dev) video_device_node_name(&v4l2->radio_dev)); } + /* Init entities at the Media Controller */ + em28xx_v4l2_create_entities(dev); + + ret = em28xx_v4l2_create_media_graph(dev); + if (ret) { + em28xx_errdev("failed to create media graph\n"); + em28xx_v4l2_media_release(dev); + goto unregister_dev; + } + em28xx_info("V4L2 video device registered as %s\n", video_device_node_name(&v4l2->vdev)); diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index b23bf6a64011..267444961775 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -26,7 +26,7 @@ #ifndef _EM28XX_H #define _EM28XX_H -#define EM28XX_VERSION "0.2.1" +#define EM28XX_VERSION "0.2.2" #define DRIVER_DESC "Empia em28xx device driver" #include @@ -552,6 +552,11 @@ struct em28xx_v4l2 { bool top_field; int vbi_read; unsigned int field_count; + +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_pad video_pad, vbi_pad; + struct media_entity *decoder; +#endif }; struct em28xx_audio { @@ -712,6 +717,12 @@ struct em28xx { /* Snapshot button input device */ char snapshot_button_path[30]; /* path of the input dev */ struct input_dev *sbutton_input_dev; + +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *media_dev; + struct media_entity input_ent[MAX_EM28XX_INPUT]; + struct media_pad input_pad[MAX_EM28XX_INPUT]; +#endif }; #define kref_to_dev(d) container_of(d, struct em28xx, ref) -- cgit v1.2.3 From 242c5033508991221d787043b734740770c850be Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 6 Dec 2015 13:34:26 -0200 Subject: [media] constify stv6110x_devctl structure The stv6110x_devctl structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stv6110x.c | 4 ++-- drivers/media/dvb-frontends/stv6110x.h | 4 ++-- drivers/media/dvb-frontends/stv6110x_priv.h | 2 +- drivers/media/pci/ddbridge/ddbridge-core.c | 2 +- drivers/media/pci/ngene/ngene-cards.c | 2 +- drivers/media/pci/ttpci/budget.c | 4 ++-- drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c | 2 +- drivers/media/usb/dvb-usb/technisat-usb2.c | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/stv6110x.c b/drivers/media/dvb-frontends/stv6110x.c index e66154e5c1d7..a62c01e454f5 100644 --- a/drivers/media/dvb-frontends/stv6110x.c +++ b/drivers/media/dvb-frontends/stv6110x.c @@ -355,7 +355,7 @@ static struct dvb_tuner_ops stv6110x_ops = { .release = stv6110x_release }; -static struct stv6110x_devctl stv6110x_ctl = { +static const struct stv6110x_devctl stv6110x_ctl = { .tuner_init = stv6110x_init, .tuner_sleep = stv6110x_sleep, .tuner_set_mode = stv6110x_set_mode, @@ -369,7 +369,7 @@ static struct stv6110x_devctl stv6110x_ctl = { .tuner_get_status = stv6110x_get_status, }; -struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, +const struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, const struct stv6110x_config *config, struct i2c_adapter *i2c) { diff --git a/drivers/media/dvb-frontends/stv6110x.h b/drivers/media/dvb-frontends/stv6110x.h index 9f7eb251aec3..696b6e5b9e7b 100644 --- a/drivers/media/dvb-frontends/stv6110x.h +++ b/drivers/media/dvb-frontends/stv6110x.h @@ -55,12 +55,12 @@ struct stv6110x_devctl { #if IS_REACHABLE(CONFIG_DVB_STV6110x) -extern struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, +extern const struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, const struct stv6110x_config *config, struct i2c_adapter *i2c); #else -static inline struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, +static inline const struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, const struct stv6110x_config *config, struct i2c_adapter *i2c) { diff --git a/drivers/media/dvb-frontends/stv6110x_priv.h b/drivers/media/dvb-frontends/stv6110x_priv.h index 0ec936a660a7..a993aba27b7e 100644 --- a/drivers/media/dvb-frontends/stv6110x_priv.h +++ b/drivers/media/dvb-frontends/stv6110x_priv.h @@ -70,7 +70,7 @@ struct stv6110x_state { const struct stv6110x_config *config; u8 regs[8]; - struct stv6110x_devctl *devctl; + const struct stv6110x_devctl *devctl; }; #endif /* __STV6110x_PRIV_H */ diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c index 9d5b314142f1..6e995ef8c37e 100644 --- a/drivers/media/pci/ddbridge/ddbridge-core.c +++ b/drivers/media/pci/ddbridge/ddbridge-core.c @@ -690,7 +690,7 @@ static int tuner_attach_stv6110(struct ddb_input *input, int type) struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900; struct stv6110x_config *tunerconf = (input->nr & 1) ? &stv6110b : &stv6110a; - struct stv6110x_devctl *ctl; + const struct stv6110x_devctl *ctl; ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c); if (!ctl) { diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c index 039bed3cc919..4e783a68bf4a 100644 --- a/drivers/media/pci/ngene/ngene-cards.c +++ b/drivers/media/pci/ngene/ngene-cards.c @@ -57,7 +57,7 @@ static int tuner_attach_stv6110(struct ngene_channel *chan) chan->dev->card_info->fe_config[chan->number]; struct stv6110x_config *tunerconf = (struct stv6110x_config *) chan->dev->card_info->tuner_config[chan->number]; - struct stv6110x_devctl *ctl; + const struct stv6110x_devctl *ctl; /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */ if (chan->number < 2) diff --git a/drivers/media/pci/ttpci/budget.c b/drivers/media/pci/ttpci/budget.c index de54310a2660..9f48100227f1 100644 --- a/drivers/media/pci/ttpci/budget.c +++ b/drivers/media/pci/ttpci/budget.c @@ -644,7 +644,7 @@ static void frontend_init(struct budget *budget) } case 0x101c: { /* TT S2-1600 */ - struct stv6110x_devctl *ctl; + const struct stv6110x_devctl *ctl; saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO); msleep(50); saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI); @@ -697,7 +697,7 @@ static void frontend_init(struct budget *budget) break; case 0x1020: { /* Omicom S2 */ - struct stv6110x_devctl *ctl; + const struct stv6110x_devctl *ctl; saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO); msleep(50); saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI); diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c index 69d7fe4471c2..2c0015b1264d 100644 --- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c +++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c @@ -118,7 +118,7 @@ int c8sectpfe_frontend_attach(struct dvb_frontend **fe, struct channel_info *tsin, int chan_num) { struct tda18212_config *tda18212; - struct stv6110x_devctl *fe2; + const struct stv6110x_devctl *fe2; struct i2c_client *client; struct i2c_board_info tda18212_info = { .type = "tda18212", diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c index 6c3c47722955..51487d2f7764 100644 --- a/drivers/media/usb/dvb-usb/technisat-usb2.c +++ b/drivers/media/usb/dvb-usb/technisat-usb2.c @@ -512,7 +512,7 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a) &a->dev->i2c_adap, STV090x_DEMODULATOR_0); if (a->fe_adap[0].fe) { - struct stv6110x_devctl *ctl; + const struct stv6110x_devctl *ctl; ctl = dvb_attach(stv6110x_attach, a->fe_adap[0].fe, -- cgit v1.2.3 From f691ba9864ad0ed1bd67ad27ed95ed2dce6e15e2 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 6 Dec 2015 13:51:38 -0200 Subject: [media] drivers/media/usb/as102: constify as102_priv_ops_t structure The as102_priv_ops_t structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/as102/as102_drv.h | 2 +- drivers/media/usb/as102/as102_usb_drv.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/as102/as102_drv.h b/drivers/media/usb/as102/as102_drv.h index aee2d76e8dfc..8def19d9ab92 100644 --- a/drivers/media/usb/as102/as102_drv.h +++ b/drivers/media/usb/as102/as102_drv.h @@ -52,7 +52,7 @@ struct as10x_bus_adapter_t { struct as10x_cmd_t *cmd, *rsp; /* bus adapter private ops callback */ - struct as102_priv_ops_t *ops; + const struct as102_priv_ops_t *ops; }; struct as102_dev_t { diff --git a/drivers/media/usb/as102/as102_usb_drv.c b/drivers/media/usb/as102/as102_usb_drv.c index 3f669066ccf6..0e8030c071b8 100644 --- a/drivers/media/usb/as102/as102_usb_drv.c +++ b/drivers/media/usb/as102/as102_usb_drv.c @@ -189,7 +189,7 @@ static int as102_read_ep2(struct as10x_bus_adapter_t *bus_adap, return actual_len; } -static struct as102_priv_ops_t as102_priv_ops = { +static const struct as102_priv_ops_t as102_priv_ops = { .upload_fw_pkt = as102_send_ep1, .xfer_cmd = as102_usb_xfer_cmd, .as102_read_ep2 = as102_read_ep2, -- cgit v1.2.3 From 9637b03251dea31d99c0742932b9fcbfa015e5f0 Mon Sep 17 00:00:00 2001 From: "Wu, Xia" Date: Wed, 9 Dec 2015 05:26:26 -0200 Subject: [media] media: videobuf2-core: Fix one __qbuf_dmabuf() error path Add dma_buf_put() to decrease refcount of the dmabuf in error path if DMABUF size is smaller than the requirement. Signed-off-by: wu xia Acked-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index c5d49d7a0d76..ec5b78ee6e72 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1220,6 +1220,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb) if (planes[plane].length < vb->planes[plane].min_length) { dprintk(1, "invalid dmabuf length for plane %d\n", plane); + dma_buf_put(dbuf); ret = -EINVAL; goto err; } -- cgit v1.2.3 From 2874bf3ec453f50cfe1f7bf000efdadeb6f30db6 Mon Sep 17 00:00:00 2001 From: Mats Randgaard Date: Thu, 10 Dec 2015 12:00:31 -0200 Subject: [media] tc358743: Print timings only when debug level is set Prevent unnecessary kernel log spamming. Signed-off-by: Mats Randgaard Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tc358743.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 3397eb99c67b..0325f7ed45d9 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -859,15 +859,16 @@ static void tc358743_format_change(struct v4l2_subdev *sd) if (tc358743_get_detected_timings(sd, &timings)) { enable_stream(sd, false); - v4l2_dbg(1, debug, sd, "%s: Format changed. No signal\n", + v4l2_dbg(1, debug, sd, "%s: No signal\n", __func__); } else { if (!v4l2_match_dv_timings(&state->timings, &timings, 0, false)) enable_stream(sd, false); - v4l2_print_dv_timings(sd->name, - "tc358743_format_change: Format changed. New format: ", - &timings, false); + if (debug) + v4l2_print_dv_timings(sd->name, + "tc358743_format_change: New format: ", + &timings, false); } if (sd->devnode) -- cgit v1.2.3 From ff880348e74e0fd1196ab39ec765f5fd330ed3c6 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 11 Dec 2015 14:16:48 -0200 Subject: [media] go7007: constify go7007_hpi_ops structures The go7007_hpi_ops structures are never modified, so declare them as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-go7007.c | 2 +- drivers/media/usb/go7007/go7007-priv.h | 2 +- drivers/media/usb/go7007/go7007-usb.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/saa7134/saa7134-go7007.c b/drivers/media/pci/saa7134/saa7134-go7007.c index 8a2abb34186b..2799538e2d7e 100644 --- a/drivers/media/pci/saa7134/saa7134-go7007.c +++ b/drivers/media/pci/saa7134/saa7134-go7007.c @@ -378,7 +378,7 @@ static int saa7134_go7007_send_firmware(struct go7007 *go, u8 *data, int len) return 0; } -static struct go7007_hpi_ops saa7134_go7007_hpi_ops = { +static const struct go7007_hpi_ops saa7134_go7007_hpi_ops = { .interface_reset = saa7134_go7007_interface_reset, .write_interrupt = saa7134_go7007_write_interrupt, .read_interrupt = saa7134_go7007_read_interrupt, diff --git a/drivers/media/usb/go7007/go7007-priv.h b/drivers/media/usb/go7007/go7007-priv.h index 745185eb060b..bebee8ca9981 100644 --- a/drivers/media/usb/go7007/go7007-priv.h +++ b/drivers/media/usb/go7007/go7007-priv.h @@ -250,7 +250,7 @@ struct go7007 { struct i2c_adapter i2c_adapter; /* HPI driver */ - struct go7007_hpi_ops *hpi_ops; + const struct go7007_hpi_ops *hpi_ops; void *hpi_context; int interrupt_available; wait_queue_head_t interrupt_waitq; diff --git a/drivers/media/usb/go7007/go7007-usb.c b/drivers/media/usb/go7007/go7007-usb.c index 3dbf14c85c5c..14d3f8c1ce4a 100644 --- a/drivers/media/usb/go7007/go7007-usb.c +++ b/drivers/media/usb/go7007/go7007-usb.c @@ -932,7 +932,7 @@ static void go7007_usb_release(struct go7007 *go) kfree(go->hpi_context); } -static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = { +static const struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = { .interface_reset = go7007_usb_interface_reset, .write_interrupt = go7007_usb_ezusb_write_interrupt, .read_interrupt = go7007_usb_read_interrupt, @@ -942,7 +942,7 @@ static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = { .release = go7007_usb_release, }; -static struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = { +static const struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = { .interface_reset = go7007_usb_interface_reset, .write_interrupt = go7007_usb_onboard_write_interrupt, .read_interrupt = go7007_usb_read_interrupt, -- cgit v1.2.3 From 9f1830206d5e2c6fc85185de4d22c5188ff00232 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 14 Dec 2015 08:17:00 -0200 Subject: [media] saa7134: add DMABUF support Since saa7134 is now using vb2, there is no reason why we can't support dmabuf for this driver. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-empress.c | 3 ++- drivers/media/pci/saa7134/saa7134-video.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c index 56b932c97196..ca417a454d67 100644 --- a/drivers/media/pci/saa7134/saa7134-empress.c +++ b/drivers/media/pci/saa7134/saa7134-empress.c @@ -189,6 +189,7 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = { .vidioc_querybuf = vb2_ioctl_querybuf, .vidioc_qbuf = vb2_ioctl_qbuf, .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, .vidioc_streamon = vb2_ioctl_streamon, .vidioc_streamoff = vb2_ioctl_streamoff, .vidioc_g_frequency = saa7134_g_frequency, @@ -286,7 +287,7 @@ static int empress_init(struct saa7134_dev *dev) * transfers that do not start at the beginning of a page. A USERPTR * can start anywhere in a page, so USERPTR support is a no-go. */ - q->io_modes = VB2_MMAP | VB2_READ; + q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; q->drv_priv = &dev->ts_q; q->ops = &saa7134_empress_qops; q->gfp_flags = GFP_DMA32; diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index a63c1366a64e..7a42d3ae3ac9 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1906,6 +1906,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_querybuf = vb2_ioctl_querybuf, .vidioc_qbuf = vb2_ioctl_qbuf, .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, .vidioc_s_std = saa7134_s_std, .vidioc_g_std = saa7134_g_std, .vidioc_querystd = saa7134_querystd, @@ -2089,7 +2090,7 @@ int saa7134_video_init1(struct saa7134_dev *dev) * USERPTR support is a no-go unless the application knows about these * limitations and has special support for this. */ - q->io_modes = VB2_MMAP | VB2_READ; + q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; if (saa7134_userptr) q->io_modes |= VB2_USERPTR; q->drv_priv = &dev->video_q; -- cgit v1.2.3 From 80fa4f07fd6d33500b26275a5405d5b49cf2ff6a Mon Sep 17 00:00:00 2001 From: Nikola Forró Date: Sun, 20 Dec 2015 09:57:17 -0200 Subject: [media] usbtv: discard redundant video fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are many dropped fields with some sources, leading to many redundant fields without counterparts. When this redundant field is odd, a new frame is pushed containing this odd field interleaved with whatever was left in the buffer, causing video artifacts. Do not push a new frame after processing every odd field, but do it only after those which come after an even field. Signed-off-by: Nikola Forró Acked-by: Lubomir Rintel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbtv/usbtv-video.c | 33 +++++++++++++++++++-------------- drivers/media/usb/usbtv/usbtv.h | 1 + 2 files changed, 20 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 4ebb33943f9a..4ecb27b2d619 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -312,20 +312,24 @@ static void usbtv_image_chunk(struct usbtv *usbtv, __be32 *chunk) usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd); usbtv->chunks_done++; - /* Last chunk in a frame, signalling an end */ - if (odd && chunk_no == usbtv->n_chunks-1) { - int size = vb2_plane_size(&buf->vb.vb2_buf, 0); - enum vb2_buffer_state state = usbtv->chunks_done == - usbtv->n_chunks ? - VB2_BUF_STATE_DONE : - VB2_BUF_STATE_ERROR; - - buf->vb.field = V4L2_FIELD_INTERLACED; - buf->vb.sequence = usbtv->sequence++; - buf->vb.vb2_buf.timestamp = ktime_get_ns(); - vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); - vb2_buffer_done(&buf->vb.vb2_buf, state); - list_del(&buf->list); + /* Last chunk in a field */ + if (chunk_no == usbtv->n_chunks-1) { + /* Last chunk in a frame, signalling an end */ + if (odd && !usbtv->last_odd) { + int size = vb2_plane_size(&buf->vb.vb2_buf, 0); + enum vb2_buffer_state state = usbtv->chunks_done == + usbtv->n_chunks ? + VB2_BUF_STATE_DONE : + VB2_BUF_STATE_ERROR; + + buf->vb.field = V4L2_FIELD_INTERLACED; + buf->vb.sequence = usbtv->sequence++; + buf->vb.vb2_buf.timestamp = ktime_get_ns(); + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); + vb2_buffer_done(&buf->vb.vb2_buf, state); + list_del(&buf->list); + } + usbtv->last_odd = odd; } spin_unlock_irqrestore(&usbtv->buflock, flags); @@ -639,6 +643,7 @@ static int usbtv_start_streaming(struct vb2_queue *vq, unsigned int count) if (usbtv->udev == NULL) return -ENODEV; + usbtv->last_odd = 1; usbtv->sequence = 0; return usbtv_start(usbtv); } diff --git a/drivers/media/usb/usbtv/usbtv.h b/drivers/media/usb/usbtv/usbtv.h index 19cb8bf7c4e9..161b38d5cfa0 100644 --- a/drivers/media/usb/usbtv/usbtv.h +++ b/drivers/media/usb/usbtv/usbtv.h @@ -95,6 +95,7 @@ struct usbtv { int width, height; int n_chunks; int iso_size; + int last_odd; unsigned int sequence; struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; -- cgit v1.2.3 From 03c6bdfc65f157f2de4cc98926fc26778b28b0d1 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Tue, 22 Dec 2015 13:38:04 -0200 Subject: [media] bttv-driver, usbvision-video: use to_video_device() Use to_video_device() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/bttv-driver.c | 2 +- drivers/media/usb/usbvision/usbvision-video.c | 27 +++++++++------------------ 2 files changed, 10 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 9400e996087b..a04329adc0e5 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -186,7 +186,7 @@ MODULE_VERSION(BTTV_VERSION); static ssize_t show_card(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vfd = container_of(cd, struct video_device, dev); + struct video_device *vfd = to_video_device(cd); struct bttv *btv = video_get_drvdata(vfd); return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET); } diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index de9ff3bb8edd..7f5d6f15a49f 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -162,8 +162,7 @@ MODULE_ALIAS(DRIVER_ALIAS); static inline struct usb_usbvision *cd_to_usbvision(struct device *cd) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); return video_get_drvdata(vdev); } @@ -177,8 +176,7 @@ static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); static ssize_t show_model(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", usbvision_device_data[usbvision->dev_model].model_string); @@ -188,8 +186,7 @@ static DEVICE_ATTR(model, S_IRUGO, show_model, NULL); static ssize_t show_hue(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_HUE; @@ -203,8 +200,7 @@ static DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); static ssize_t show_contrast(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_CONTRAST; @@ -218,8 +214,7 @@ static DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); static ssize_t show_brightness(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_BRIGHTNESS; @@ -233,8 +228,7 @@ static DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); static ssize_t show_saturation(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_SATURATION; @@ -248,8 +242,7 @@ static DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); static ssize_t show_streaming(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", YES_NO(usbvision->streaming == stream_on ? 1 : 0)); @@ -259,8 +252,7 @@ static DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); static ssize_t show_compression(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", YES_NO(usbvision->isoc_mode == ISOC_MODE_COMPRESS)); @@ -270,8 +262,7 @@ static DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL); static ssize_t show_device_bridge(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%d\n", usbvision->bridge_type); } -- cgit v1.2.3 From faccb05ca8fb56c140fdeb70ae599e559c01c815 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 24 Dec 2015 18:06:45 -0200 Subject: [media] stk1160: Remove redundant vb2_buf payload set Calling vb2_set_plane_payload is enough, there's no need to set the planes[] bytesused field. Remove it. Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/stk1160/stk1160-video.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c index 46191d5262eb..6ecb0b48423f 100644 --- a/drivers/media/usb/stk1160/stk1160-video.c +++ b/drivers/media/usb/stk1160/stk1160-video.c @@ -98,7 +98,6 @@ void stk1160_buffer_done(struct stk1160 *dev) buf->vb.sequence = dev->sequence++; buf->vb.field = V4L2_FIELD_INTERLACED; - buf->vb.vb2_buf.planes[0].bytesused = buf->bytesused; buf->vb.vb2_buf.timestamp = ktime_get_ns(); vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->bytesused); -- cgit v1.2.3 From b20b51f090f81418b4f74232a0f414b886e8ba8c Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Fri, 25 Dec 2015 15:25:16 -0200 Subject: [media] vim2m: return error if driver registration fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't hide the error code. Signed-off-by: Niklas Söderlund Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vim2m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index 418113c99801..c4b5fab83666 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -1074,7 +1074,7 @@ static int __init vim2m_init(void) if (ret) platform_device_unregister(&vim2m_pdev); - return 0; + return ret; } module_init(vim2m_init); -- cgit v1.2.3 From 490ba9c29d5b82df2bed59d6007314c03d597716 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sun, 27 Dec 2015 19:02:21 -0200 Subject: [media] bttv: Returning only value constants in two functions Return constant integer values without storing them in the local variable "err" or "rc". Signed-off-by: Markus Elfring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/bttv-driver.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index a04329adc0e5..2c412377507b 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -1726,22 +1726,15 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id id) struct bttv_fh *fh = priv; struct bttv *btv = fh->btv; unsigned int i; - int err = 0; for (i = 0; i < BTTV_TVNORMS; i++) if (id & bttv_tvnorms[i].v4l2_id) break; - if (i == BTTV_TVNORMS) { - err = -EINVAL; - goto err; - } - + if (i == BTTV_TVNORMS) + return -EINVAL; btv->std = id; set_tvnorm(btv, i); - -err: - - return err; + return 0; } static int bttv_g_std(struct file *file, void *priv, v4l2_std_id *id) @@ -1770,12 +1763,9 @@ static int bttv_enum_input(struct file *file, void *priv, { struct bttv_fh *fh = priv; struct bttv *btv = fh->btv; - int rc = 0; - if (i->index >= bttv_tvcards[btv->c.type].video_inputs) { - rc = -EINVAL; - goto err; - } + if (i->index >= bttv_tvcards[btv->c.type].video_inputs) + return -EINVAL; i->type = V4L2_INPUT_TYPE_CAMERA; i->audioset = 0; @@ -1799,10 +1789,7 @@ static int bttv_enum_input(struct file *file, void *priv, } i->std = BTTV_NORMS; - -err: - - return rc; + return 0; } static int bttv_g_input(struct file *file, void *priv, unsigned int *i) -- cgit v1.2.3 From 80c1bce9aa315ac70738f79afb4f7c93ae27d9fa Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 28 Dec 2015 19:52:48 -0200 Subject: [media] au0828: Refactoring for start_urb_transfer() This issue was detected by using the Coccinelle software. 1. Let us return directly if a buffer allocation failed. 2. Delete the jump label "err" then. 3. Drop the explicit initialisation for the variable "ret" at the beginning. 4. Return zero as a constant at the end. Signed-off-by: Markus Elfring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-dvb.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c index 94363a3ba400..0e174e860614 100644 --- a/drivers/media/usb/au0828/au0828-dvb.c +++ b/drivers/media/usb/au0828/au0828-dvb.c @@ -181,7 +181,7 @@ static int stop_urb_transfer(struct au0828_dev *dev) static int start_urb_transfer(struct au0828_dev *dev) { struct urb *purb; - int i, ret = -ENOMEM; + int i, ret; dprintk(2, "%s()\n", __func__); @@ -194,7 +194,7 @@ static int start_urb_transfer(struct au0828_dev *dev) dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL); if (!dev->urbs[i]) - goto err; + return -ENOMEM; purb = dev->urbs[i]; @@ -207,9 +207,10 @@ static int start_urb_transfer(struct au0828_dev *dev) if (!purb->transfer_buffer) { usb_free_urb(purb); dev->urbs[i] = NULL; + ret = -ENOMEM; pr_err("%s: failed big buffer allocation, err = %d\n", __func__, ret); - goto err; + return ret; } purb->status = -EINPROGRESS; @@ -235,10 +236,7 @@ static int start_urb_transfer(struct au0828_dev *dev) } dev->urb_streaming = true; - ret = 0; - -err: - return ret; + return 0; } static void au0828_start_transport(struct au0828_dev *dev) -- cgit v1.2.3 From b68554cd76bfed57a3aac2fc4ac4c60478d90050 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 29 Dec 2015 08:02:43 -0200 Subject: [media] hdpvr: Refactoring for hdpvr_read() Let us return directly if the element "status" of the variable "buf" indicates "BUFSTAT_READY". A check repetition can be excluded for the variable "ret" at the end then. Signed-off-by: Markus Elfring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/hdpvr/hdpvr-video.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index 7dee22deebf3..ba7f02270c83 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -462,10 +462,8 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, } if (wait_event_interruptible(dev->wait_data, - buf->status == BUFSTAT_READY)) { - ret = -ERESTARTSYS; - goto err; - } + buf->status == BUFSTAT_READY)) + return -ERESTARTSYS; } if (buf->status != BUFSTAT_READY) -- cgit v1.2.3 From f8433226d1b3eb035693724dca786c4445221368 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Tue, 29 Dec 2015 16:53:35 -0200 Subject: [media] cx231xx: correctly handling failed allocation Since kmalloc can be failed in memory pressure, if not properly handled, NULL dereference can be happend Signed-off-by: Insu Yun Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-417.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index 48643b94e694..c9320d6c6131 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1382,6 +1382,8 @@ static int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb) buffer_size = urb->actual_length; buffer = kmalloc(buffer_size, GFP_ATOMIC); + if (!buffer) + return -ENOMEM; memcpy(buffer, dma_q->ps_head, 3); memcpy(buffer+3, p_buffer, buffer_size-3); -- cgit v1.2.3 From e22a3b34a1f2ee53f89aef86b15d6f677de6bdc5 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Tue, 29 Dec 2015 19:48:29 -0200 Subject: [media] usbtv: correctly handling failed allocation Since kzalloc can be failed, if not properly handled, NULL dereference could be happened. Signed-off-by: Insu Yun Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbtv/usbtv-video.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 4ecb27b2d619..f6cfad46547e 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -393,6 +393,10 @@ static struct urb *usbtv_setup_iso_transfer(struct usbtv *usbtv) ip->transfer_flags = URB_ISO_ASAP; ip->transfer_buffer = kzalloc(size * USBTV_ISOC_PACKETS, GFP_KERNEL); + if (!ip->transfer_buffer) { + usb_free_urb(ip); + return NULL; + } ip->complete = usbtv_iso_cb; ip->number_of_packets = USBTV_ISOC_PACKETS; ip->transfer_buffer_length = size * USBTV_ISOC_PACKETS; -- cgit v1.2.3 From 3defe84a76d5055b24e2e04b5171892fa9455566 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 3 Jan 2016 09:58:14 -0200 Subject: [media] av7110: constify sp8870_config structure This sp8870_config structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/ttpci/av7110.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c index a69dc6a0752b..18d229fa65cf 100644 --- a/drivers/media/pci/ttpci/av7110.c +++ b/drivers/media/pci/ttpci/av7110.c @@ -1739,7 +1739,7 @@ static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct fir #endif } -static struct sp8870_config alps_tdlb7_config = { +static const struct sp8870_config alps_tdlb7_config = { .demod_address = 0x71, .request_firmware = alps_tdlb7_request_firmware, -- cgit v1.2.3 From 40205163ff84277747347ad0e522a7e2152a7677 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 3 Jan 2016 10:11:06 -0200 Subject: [media] drivers/media/usb/dvb-usb-v2: constify mxl111sf_tuner_config structure This mxl111sf_tuner_config structure is never modified, so declare it as const. There are some indentation changes to remain within 80 columns. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Reviewed-by: Michael Ira Krufky Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c | 6 +++--- drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h | 8 ++++---- drivers/media/usb/dvb-usb-v2/mxl111sf.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c index 444579be0b77..7d16252dbb71 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c @@ -36,7 +36,7 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); struct mxl111sf_tuner_state { struct mxl111sf_state *mxl_state; - struct mxl111sf_tuner_config *cfg; + const struct mxl111sf_tuner_config *cfg; enum mxl_if_freq if_freq; @@ -489,8 +489,8 @@ static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = { }; struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, - struct mxl111sf_state *mxl_state, - struct mxl111sf_tuner_config *cfg) + struct mxl111sf_state *mxl_state, + const struct mxl111sf_tuner_config *cfg) { struct mxl111sf_tuner_state *state = NULL; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h index e6caab21a197..509b55071218 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h @@ -63,13 +63,13 @@ struct mxl111sf_tuner_config { #if IS_ENABLED(CONFIG_DVB_USB_MXL111SF) extern struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, - struct mxl111sf_state *mxl_state, - struct mxl111sf_tuner_config *cfg); + struct mxl111sf_state *mxl_state, + const struct mxl111sf_tuner_config *cfg); #else static inline struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, - struct mxl111sf_state *mxl_state, - struct mxl111sf_tuner_config *cfg) + struct mxl111sf_state *mxl_state, + const struct mxl111sf_tuner_config *cfg) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index e7978e4e40ea..5d676b533a3a 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -856,7 +856,7 @@ static int mxl111sf_ant_hunt(struct dvb_frontend *fe) return 0; } -static struct mxl111sf_tuner_config mxl_tuner_config = { +static const struct mxl111sf_tuner_config mxl_tuner_config = { .if_freq = MXL_IF_6_0, /* applies to external IF output, only */ .invert_spectrum = 0, .read_reg = mxl111sf_read_reg, -- cgit v1.2.3 From 4a40c73e5b27910edafe000fcc50a905de13447f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 3 Jan 2016 10:19:52 -0200 Subject: [media] media: bt8xx: constify or51211_config structure The or51211_config structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/dvb-bt8xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c index d407244fd1bc..8aeb14cfb89c 100644 --- a/drivers/media/pci/bt8xx/dvb-bt8xx.c +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c @@ -458,7 +458,7 @@ static void or51211_sleep(struct dvb_frontend * fe) bttv_write_gpio(bt->bttv_nr, 0x0001, 0x0000); } -static struct or51211_config or51211_config = { +static const struct or51211_config or51211_config = { .demod_address = 0x15, .request_firmware = or51211_request_firmware, .setmode = or51211_setmode, -- cgit v1.2.3 From 64e423d4fb7d561131a2dcc91930c401ab6bc217 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 3 Jan 2016 10:27:53 -0200 Subject: [media] media: bt8xx: constify sp887x_config structure This sp887x_config structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/dvb-bt8xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c index 8aeb14cfb89c..e69d338ab9be 100644 --- a/drivers/media/pci/bt8xx/dvb-bt8xx.c +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c @@ -318,7 +318,7 @@ static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const s return request_firmware(fw, name, &bt->bt->dev->dev); } -static struct sp887x_config microtune_mt7202dtf_config = { +static const struct sp887x_config microtune_mt7202dtf_config = { .demod_address = 0x70, .request_firmware = microtune_mt7202dtf_request_firmware, }; -- cgit v1.2.3 From 74dc385cb450089b28c28be2c8a0baca296b95f9 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 4 Jan 2016 17:30:09 -0200 Subject: [media] coda: fix first encoded frame payload During the recent vb2_buffer restructuring, the calculation of the buffer payload reported to userspace was accidentally broken for the first encoded frame, counting only the length of the headers. This patch re-adds the length of the actual frame data. Fixes: 2d7007153f0c ("[media] media: videobuf2: Restructure vb2_buffer") Reported-by: Michael Olbrich Signed-off-by: Philipp Zabel Tested-by: Jan Luebbe Cc: # for v4.4 and up Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-bit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index 7d28899f89ce..6efe9d002961 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -1342,7 +1342,7 @@ static void coda_finish_encode(struct coda_ctx *ctx) /* Calculate bytesused field */ if (dst_buf->sequence == 0) { - vb2_set_plane_payload(&dst_buf->vb2_buf, 0, + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr + ctx->vpu_header_size[0] + ctx->vpu_header_size[1] + ctx->vpu_header_size[2]); -- cgit v1.2.3 From 39de7d95f88d95a07f64b047c985fff31c006b5c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 6 Jan 2016 08:05:52 -0200 Subject: [media] vpx3220: signedness bug in vpx3220_fp_read() The intent was to return -1 on error and that's what the callers expect but the current code returns USHRT_MAX instead. Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/vpx3220.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/i2c/vpx3220.c b/drivers/media/i2c/vpx3220.c index 4b564f17f618..90b693f4e2ab 100644 --- a/drivers/media/i2c/vpx3220.c +++ b/drivers/media/i2c/vpx3220.c @@ -124,7 +124,7 @@ static int vpx3220_fp_write(struct v4l2_subdev *sd, u8 fpaddr, u16 data) return 0; } -static u16 vpx3220_fp_read(struct v4l2_subdev *sd, u16 fpaddr) +static int vpx3220_fp_read(struct v4l2_subdev *sd, u16 fpaddr) { struct i2c_client *client = v4l2_get_subdevdata(sd); s16 data; -- cgit v1.2.3 From d99875eebfebec5432981273fac0547f3e34f2d7 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Fri, 22 Jan 2016 23:38:38 +0530 Subject: bus: vexpress-config: Add missing of_node_put for_each_compatible_node performs an of_node_get on each iteration, so to break out of the loop an of_node_put is required. Found using Coccinelle. The semantic patch used for this is as follows: // @@ expression e; local idexpression n; @@ for_each_compatible_node(n, ...) { ... when != of_node_put(n) when != e = n ( return n; + of_node_put(n); ? return ...; ) ... } // Acked-by: Liviu Dudau Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Sudeep Holla --- drivers/bus/vexpress-config.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/bus/vexpress-config.c b/drivers/bus/vexpress-config.c index 6575c0fe6a4e..c3cb76b363c6 100644 --- a/drivers/bus/vexpress-config.c +++ b/drivers/bus/vexpress-config.c @@ -192,8 +192,10 @@ static int __init vexpress_config_init(void) /* Need the config devices early, before the "normal" devices... */ for_each_compatible_node(node, NULL, "arm,vexpress,config-bus") { err = vexpress_config_populate(node); - if (err) + if (err) { + of_node_put(node); break; + } } return err; -- cgit v1.2.3 From 199964b1d080d82cc8d39a7df1ece8671ef07753 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Jan 2016 08:57:58 -0200 Subject: [media] staging: media: lirc: fix MODULE_PARM_DESC typo It "tx_mask" was intended instead of "tx_maxk". Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_parallel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c index 6e2edb24d9d5..68ede6c56e6d 100644 --- a/drivers/staging/media/lirc/lirc_parallel.c +++ b/drivers/staging/media/lirc/lirc_parallel.c @@ -730,7 +730,7 @@ module_param(irq, int, S_IRUGO); MODULE_PARM_DESC(irq, "Interrupt (7 or 5)"); module_param(tx_mask, int, S_IRUGO); -MODULE_PARM_DESC(tx_maxk, "Transmitter mask (default: 0x01)"); +MODULE_PARM_DESC(tx_mask, "Transmitter mask (default: 0x01)"); module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Enable debugging messages"); -- cgit v1.2.3 From aeae69daa312246e8f03ed2f6bc792d25a531118 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Jan 2016 09:02:56 -0200 Subject: [media] wl128x: fix typo in MODULE_PARM_DESC The module_param() is "default_rds_buf" and the MODULE_PARM_DESC() should match. Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/wl128x/fmdrv_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index ebc73b034249..3f9e6df7d837 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -68,7 +68,7 @@ MODULE_PARM_DESC(default_radio_region, "Region: 0=Europe/US, 1=Japan"); /* RDS buffer blocks */ static u32 default_rds_buf = 300; module_param(default_rds_buf, uint, 0444); -MODULE_PARM_DESC(rds_buf, "RDS buffer entries"); +MODULE_PARM_DESC(default_rds_buf, "RDS buffer entries"); /* Radio Nr */ static u32 radio_nr = -1; -- cgit v1.2.3 From 9dd73448c6a98b1971e626627e4b020b8898a3f6 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Theou Date: Fri, 8 Jan 2016 20:02:03 -0200 Subject: [media] cx231xx: Fix memory leak dma_area needs to be freed when the device is closed. Based on em23xx-audio.c Signed-off-by: Jean-Baptiste Theou Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-audio.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c index de4ae5eb4830..a6a9508418f8 100644 --- a/drivers/media/usb/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c @@ -499,6 +499,11 @@ static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream) } dev->adev.users--; + if (substream->runtime->dma_area) { + dev_dbg(dev->dev, "freeing\n"); + vfree(substream->runtime->dma_area); + substream->runtime->dma_area = NULL; + } mutex_unlock(&dev->lock); if (dev->adev.users == 0 && dev->adev.shutdown == 1) { -- cgit v1.2.3 From 949cf70636bfe12c160c36608d18c5f8d89d2940 Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Mon, 11 Jan 2016 05:13:35 -0200 Subject: [media] radio-si476x: add return value check to avoid dead code Dead code found on below code: si476x_radio_add_new_custom(radio, SI476X_IDX_DIVERSITY_MODE); if (rval < 0) goto exit; si476x_radio_add_new_custom(radio, SI476X_IDX_INTERCHIP_LINK); if (rval < 0) ====> Dead code !!! goto exit; The piece of code miss return value check after calling .si476x_radio_add_new_custom(), the patch fix it. Signed-off-by: Fugang Duan Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-si476x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index 859f0c08ee05..271f725b17e8 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -1530,11 +1530,11 @@ static int si476x_radio_probe(struct platform_device *pdev) if (si476x_core_has_diversity(radio->core)) { si476x_ctrls[SI476X_IDX_DIVERSITY_MODE].def = si476x_phase_diversity_mode_to_idx(radio->core->diversity_mode); - si476x_radio_add_new_custom(radio, SI476X_IDX_DIVERSITY_MODE); + rval = si476x_radio_add_new_custom(radio, SI476X_IDX_DIVERSITY_MODE); if (rval < 0) goto exit; - si476x_radio_add_new_custom(radio, SI476X_IDX_INTERCHIP_LINK); + rval = si476x_radio_add_new_custom(radio, SI476X_IDX_INTERCHIP_LINK); if (rval < 0) goto exit; } -- cgit v1.2.3 From 8e20b80344148dd8b7ec23d546e931d54810a1b7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 13 Jan 2016 11:44:41 -0200 Subject: [media] v4l2-dv-timings: skip standards check for V4L2_DV_BT_CAP_CUSTOM Skip validating the standards field in v4l2_valid_dv_timings() if the V4L2_DV_BT_CAP_CUSTOM capability is set, since that implies that non-standard timings are allowed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-dv-timings.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c index ec258b73001a..889de0a32152 100644 --- a/drivers/media/v4l2-core/v4l2-dv-timings.c +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c @@ -165,7 +165,8 @@ bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t, bt->width > cap->max_width || bt->pixelclock < cap->min_pixelclock || bt->pixelclock > cap->max_pixelclock || - (cap->standards && bt->standards && + (!(caps & V4L2_DV_BT_CAP_CUSTOM) && + cap->standards && bt->standards && !(bt->standards & cap->standards)) || (bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) || (!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE))) -- cgit v1.2.3 From fcae73fac1b45053766c92f08fb3afee6d30dbbc Mon Sep 17 00:00:00 2001 From: Mats Randgaard Date: Thu, 10 Dec 2015 11:38:07 -0200 Subject: [media] tc358743: Use local array with fixed size in i2c write i2c_wr() is called from ops and the interrupt service routine, while state->wr_data is shared and unprotected, and could be overwritten. This shared buffer is therefore replaced with a local array with fixed size. The array has the size of one EDID block (128 bytes) + 2 bytes i2c address, and the EDID is written block by block (up to 8 blocks). Signed-off-by: Mats Randgaard Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tc358743.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 0325f7ed45d9..da7469bc6e56 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -59,8 +59,7 @@ MODULE_LICENSE("GPL"); #define EDID_NUM_BLOCKS_MAX 8 #define EDID_BLOCK_SIZE 128 -/* Max transfer size done by I2C transfer functions */ -#define MAX_XFER_SIZE (EDID_NUM_BLOCKS_MAX * EDID_BLOCK_SIZE + 2) +#define I2C_MAX_XFER_SIZE (EDID_BLOCK_SIZE + 2) static const struct v4l2_dv_timings_cap tc358743_timings_cap = { .type = V4L2_DV_BT_656_1120, @@ -97,9 +96,6 @@ struct tc358743_state { /* edid */ u8 edid_blocks_written; - /* used by i2c_wr() */ - u8 wr_data[MAX_XFER_SIZE]; - struct v4l2_dv_timings timings; u32 mbus_fmt_code; @@ -149,13 +145,15 @@ static void i2c_wr(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) { struct tc358743_state *state = to_state(sd); struct i2c_client *client = state->i2c_client; - u8 *data = state->wr_data; int err, i; struct i2c_msg msg; + u8 data[I2C_MAX_XFER_SIZE]; - if ((2 + n) > sizeof(state->wr_data)) + if ((2 + n) > I2C_MAX_XFER_SIZE) { + n = I2C_MAX_XFER_SIZE - 2; v4l2_warn(sd, "i2c wr reg=%04x: len=%d is too big!\n", reg, 2 + n); + } msg.addr = client->addr; msg.buf = data; @@ -1582,6 +1580,7 @@ static int tc358743_s_edid(struct v4l2_subdev *sd, { struct tc358743_state *state = to_state(sd); u16 edid_len = edid->blocks * EDID_BLOCK_SIZE; + int i; v4l2_dbg(2, debug, sd, "%s, pad %d, start block %d, blocks %d\n", __func__, edid->pad, edid->start_block, edid->blocks); @@ -1607,7 +1606,8 @@ static int tc358743_s_edid(struct v4l2_subdev *sd, return 0; } - i2c_wr(sd, EDID_RAM, edid->edid, edid_len); + for (i = 0; i < edid_len; i += EDID_BLOCK_SIZE) + i2c_wr(sd, EDID_RAM + i, edid->edid + i, EDID_BLOCK_SIZE); state->edid_blocks_written = edid->blocks; -- cgit v1.2.3 From b7d4d2f8d8517e1b3759568ef20a88d1022598ff Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Tue, 22 Dec 2015 12:22:01 -0200 Subject: [media] media: adv7604: implement get_selection The rcar_vin driver relies on this. Signed-off-by: Ulrich Hecht Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index f8dd7505b529..5d4dbd05f9d6 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -1884,6 +1884,26 @@ static int adv76xx_get_format(struct v4l2_subdev *sd, return 0; } +static int adv76xx_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) +{ + struct adv76xx_state *state = to_state(sd); + + if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + /* Only CROP, CROP_DEFAULT and CROP_BOUNDS are supported */ + if (sel->target > V4L2_SEL_TGT_CROP_BOUNDS) + return -EINVAL; + + sel->r.left = 0; + sel->r.top = 0; + sel->r.width = state->timings.bt.width; + sel->r.height = state->timings.bt.height; + + return 0; +} + static int adv76xx_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *format) @@ -2404,6 +2424,7 @@ static const struct v4l2_subdev_video_ops adv76xx_video_ops = { static const struct v4l2_subdev_pad_ops adv76xx_pad_ops = { .enum_mbus_code = adv76xx_enum_mbus_code, + .get_selection = adv76xx_get_selection, .get_fmt = adv76xx_get_format, .set_fmt = adv76xx_set_format, .get_edid = adv76xx_get_edid, -- cgit v1.2.3 From 7df5ab8774aa383c6d2bff00688d004585d96dfd Mon Sep 17 00:00:00 2001 From: Tiffany Lin Date: Tue, 19 Jan 2016 05:56:50 -0200 Subject: [media] media: v4l2-compat-ioctl32: fix missing length copy in put_v4l2_buffer32 In v4l2-compliance utility, test QUERYBUF required correct length value to go through each planar to check planar's length in multi-planar buffer type Signed-off-by: Tiffany Lin Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil Cc: # for v3.7 and up Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 8fd84a67478a..019644ff627d 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -415,7 +415,8 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user get_user(kp->index, &up->index) || get_user(kp->type, &up->type) || get_user(kp->flags, &up->flags) || - get_user(kp->memory, &up->memory)) + get_user(kp->memory, &up->memory) || + get_user(kp->length, &up->length)) return -EFAULT; if (V4L2_TYPE_IS_OUTPUT(kp->type)) @@ -427,9 +428,6 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user return -EFAULT; if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { - if (get_user(kp->length, &up->length)) - return -EFAULT; - num_planes = kp->length; if (num_planes == 0) { kp->m.planes = NULL; @@ -462,16 +460,14 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user } else { switch (kp->memory) { case V4L2_MEMORY_MMAP: - if (get_user(kp->length, &up->length) || - get_user(kp->m.offset, &up->m.offset)) + if (get_user(kp->m.offset, &up->m.offset)) return -EFAULT; break; case V4L2_MEMORY_USERPTR: { compat_long_t tmp; - if (get_user(kp->length, &up->length) || - get_user(tmp, &up->m.userptr)) + if (get_user(tmp, &up->m.userptr)) return -EFAULT; kp->m.userptr = (unsigned long)compat_ptr(tmp); @@ -513,7 +509,8 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || put_user(kp->sequence, &up->sequence) || put_user(kp->reserved2, &up->reserved2) || - put_user(kp->reserved, &up->reserved)) + put_user(kp->reserved, &up->reserved) || + put_user(kp->length, &up->length)) return -EFAULT; if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { @@ -536,13 +533,11 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user } else { switch (kp->memory) { case V4L2_MEMORY_MMAP: - if (put_user(kp->length, &up->length) || - put_user(kp->m.offset, &up->m.offset)) + if (put_user(kp->m.offset, &up->m.offset)) return -EFAULT; break; case V4L2_MEMORY_USERPTR: - if (put_user(kp->length, &up->length) || - put_user(kp->m.userptr, &up->m.userptr)) + if (put_user(kp->m.userptr, &up->m.userptr)) return -EFAULT; break; case V4L2_MEMORY_OVERLAY: -- cgit v1.2.3 From 3541e349e18eeacbe8e5e97ed984f018be4cfdaf Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jan 2016 13:13:25 -0200 Subject: [media] vivid: fix broken Bayer text rendering Sometimes when a Bayer pixelformat is selected the rendering of the OSD text by vivid was all wrong: every other line of the text was shifted by half the width or more. It turned out that to render Bayer formats the interleaved boolean is set to true in the tpg. This mode indicates a semi-biplanar mode where two interleaved planes are used to render the frame. From outside the tpg it looks like a single plane, but internally it is two planes. However, in the tpg_s_bytesperline() function the interleaved bool wasn't checked and only the bytesperline value for plane 0 was updated. But for the interleaved mode the same value has to be copied to bytesperline[1] as well. The effect was that whatever old value was left in bytesperline[1] was used, which caused all sorts of weird and seemingly unpredictable shifts. Reported-by: Ove Brynestad Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-tpg.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/drivers/media/platform/vivid/vivid-tpg.h index 9baed6a10334..93fbaee69675 100644 --- a/drivers/media/platform/vivid/vivid-tpg.h +++ b/drivers/media/platform/vivid/vivid-tpg.h @@ -418,6 +418,8 @@ static inline void tpg_s_bytesperline(struct tpg_data *tpg, unsigned plane, unsi tpg->bytesperline[p] = plane_w / tpg->hdownsampling[p]; } + if (tpg_g_interleaved(tpg)) + tpg->bytesperline[1] = tpg->bytesperline[0]; } -- cgit v1.2.3 From a0c80efe5956ccce9fe7ae5c78542578c07bc20a Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Mon, 1 Feb 2016 11:19:17 +0100 Subject: floppy: fix lock_fdc() signal handling floppy_revalidate() doesn't perform any error handling on lock_fdc() result. lock_fdc() might actually be interrupted by a signal (it waits for fdc becoming non-busy interruptibly). In such case, floppy_revalidate() proceeds as if it had claimed the lock, but it fact it doesn't. In case of multiple threads trying to open("/dev/fdX"), this leads to serious corruptions all over the place, because all of a sudden there is no critical section protection (that'd otherwise be guaranteed by locked fd) whatsoever. While at this, fix the fact that the 'interruptible' parameter to lock_fdc() doesn't make any sense whatsoever, because we always wait interruptibly anyway. Most of the lock_fdc() callsites do properly handle error (and propagate EINTR), but floppy_revalidate() and floppy_check_events() don't. Fix this. Spotted by 'syzkaller' tool. Reported-by: Dmitry Vyukov Tested-by: Dmitry Vyukov Signed-off-by: Jiri Kosina --- drivers/block/floppy.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index fa9bb742df6e..c1aacca88c8f 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -866,7 +866,7 @@ static void set_fdc(int drive) } /* locks the driver */ -static int lock_fdc(int drive, bool interruptible) +static int lock_fdc(int drive) { if (WARN(atomic_read(&usage_count) == 0, "Trying to lock fdc while usage count=0\n")) @@ -2173,7 +2173,7 @@ static int do_format(int drive, struct format_descr *tmp_format_req) { int ret; - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; set_floppy(drive); @@ -2960,7 +2960,7 @@ static int user_reset_fdc(int drive, int arg, bool interruptible) { int ret; - if (lock_fdc(drive, interruptible)) + if (lock_fdc(drive)) return -EINTR; if (arg == FD_RESET_ALWAYS) @@ -3243,7 +3243,7 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g, if (!capable(CAP_SYS_ADMIN)) return -EPERM; mutex_lock(&open_lock); - if (lock_fdc(drive, true)) { + if (lock_fdc(drive)) { mutex_unlock(&open_lock); return -EINTR; } @@ -3263,7 +3263,7 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g, } else { int oldStretch; - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; if (cmd != FDDEFPRM) { /* notice a disk change immediately, else @@ -3349,7 +3349,7 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g) if (type) *g = &floppy_type[type]; else { - if (lock_fdc(drive, false)) + if (lock_fdc(drive)) return -EINTR; if (poll_drive(false, 0) == -EINTR) return -EINTR; @@ -3433,7 +3433,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int if (UDRS->fd_ref != 1) /* somebody else has this drive open */ return -EBUSY; - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; /* do the actual eject. Fails on @@ -3445,7 +3445,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int process_fd_request(); return ret; case FDCLRPRM: - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; current_type[drive] = NULL; floppy_sizes[drive] = MAX_DISK_SIZE << 1; @@ -3467,7 +3467,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int UDP->flags &= ~FTD_MSG; return 0; case FDFMTBEG: - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) return -EINTR; @@ -3484,7 +3484,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int return do_format(drive, &inparam.f); case FDFMTEND: case FDFLUSH: - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; return invalidate_drive(bdev); case FDSETEMSGTRESH: @@ -3507,7 +3507,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int outparam = UDP; break; case FDPOLLDRVSTAT: - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) return -EINTR; @@ -3530,7 +3530,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int case FDRAWCMD: if (type) return -EINVAL; - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; set_floppy(drive); i = raw_cmd_ioctl(cmd, (void __user *)param); @@ -3539,7 +3539,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int process_fd_request(); return i; case FDTWADDLE: - if (lock_fdc(drive, true)) + if (lock_fdc(drive)) return -EINTR; twaddle(); process_fd_request(); @@ -3747,7 +3747,8 @@ static unsigned int floppy_check_events(struct gendisk *disk, return DISK_EVENT_MEDIA_CHANGE; if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) { - lock_fdc(drive, false); + if (lock_fdc(drive)) + return -EINTR; poll_drive(false, 0); process_fd_request(); } @@ -3845,7 +3846,9 @@ static int floppy_revalidate(struct gendisk *disk) "VFS: revalidate called on non-open device.\n")) return -EFAULT; - lock_fdc(drive, false); + res = lock_fdc(drive); + if (res) + return res; cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || test_bit(FD_VERIFY_BIT, &UDRS->flags)); if (!(cf || test_bit(drive, &fake_change) || drive_no_geom(drive))) { -- cgit v1.2.3 From cc8ed76938b5cf6a54ab3d60edabaf808dc960d1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 22 Jan 2016 13:39:25 +0100 Subject: soc: mediatek: SCPSYS: Fix double enabling of regulators With CONFIG_PM enabled do not call genpd->power_on manually as this will cause the regulators being turned on once in SCPSYS probe and then again when the genpd core turns on the domains. Instead, call genpd->power_on only with CONFIG_PM disabled and tell the genpd core that the domains are disabled when registered. Signed-off-by: Sascha Hauer Tested-by: Daniel Kurtz Reviewed-by: Daniel Kurtz Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-scpsys.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c index 837effe19907..57e781c71e67 100644 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ b/drivers/soc/mediatek/mtk-scpsys.c @@ -491,14 +491,13 @@ static int scpsys_probe(struct platform_device *pdev) genpd->dev_ops.active_wakeup = scpsys_active_wakeup; /* - * Initially turn on all domains to make the domains usable - * with !CONFIG_PM and to get the hardware in sync with the - * software. The unused domains will be switched off during - * late_init time. + * With CONFIG_PM disabled turn on all domains to make the + * hardware usable. */ - genpd->power_on(genpd); + if (!IS_ENABLED(CONFIG_PM)) + genpd->power_on(genpd); - pm_genpd_init(genpd, NULL, false); + pm_genpd_init(genpd, NULL, true); } /* -- cgit v1.2.3 From 343e89a792a571b28b9c02850db7af2ef25ffb20 Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Wed, 6 Jan 2016 21:37:26 -0200 Subject: [media] media: ti-vpe: Add CAL v4l2 camera capture driver The Camera Adaptation Layer (CAL) is a block which consists of a dual port CSI2/MIPI camera capture engine. Port #0 can handle CSI2 camera connected to up to 4 data lanes. Port #1 can handle CSI2 camera connected to up to 2 data lanes. The driver implements the required API/ioctls to be V4L2 compliant. Driver supports the following: - V4L2 API using DMABUF/MMAP buffer access based on videobuf2 api - Asynchronous sensor sub device registration - DT support Signed-off-by: Benoit Parrot Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 12 + drivers/media/platform/Makefile | 2 + drivers/media/platform/ti-vpe/Makefile | 4 + drivers/media/platform/ti-vpe/cal.c | 1970 ++++++++++++++++++++++++++++++ drivers/media/platform/ti-vpe/cal_regs.h | 479 ++++++++ 5 files changed, 2467 insertions(+) create mode 100644 drivers/media/platform/ti-vpe/cal.c create mode 100644 drivers/media/platform/ti-vpe/cal_regs.h (limited to 'drivers') diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 526359447ff9..6f0f28fc4e2f 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -120,6 +120,18 @@ source "drivers/media/platform/s5p-tv/Kconfig" source "drivers/media/platform/am437x/Kconfig" source "drivers/media/platform/xilinx/Kconfig" +config VIDEO_TI_CAL + tristate "TI CAL (Camera Adaptation Layer) driver" + depends on VIDEO_DEV && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on SOC_DRA7XX || COMPILE_TEST + select VIDEOBUF2_DMA_CONTIG + default n + ---help--- + Support for the TI CAL (Camera Adaptation Layer) block + found on DRA72X SoC. + In TI Technical Reference Manual this module is referred as + Camera Interface Subsystem (CAMSS). + endif # V4L_PLATFORM_DRIVERS menuconfig V4L_MEM2MEM_DRIVERS diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index efa0295af87b..028a7233096b 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -18,6 +18,8 @@ obj-$(CONFIG_VIDEO_VIM2M) += vim2m.o obj-$(CONFIG_VIDEO_TI_VPE) += ti-vpe/ +obj-$(CONFIG_VIDEO_TI_CAL) += ti-vpe/ + obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o obj-$(CONFIG_VIDEO_CODA) += coda/ diff --git a/drivers/media/platform/ti-vpe/Makefile b/drivers/media/platform/ti-vpe/Makefile index be680f839e77..e236059a60ad 100644 --- a/drivers/media/platform/ti-vpe/Makefile +++ b/drivers/media/platform/ti-vpe/Makefile @@ -3,3 +3,7 @@ obj-$(CONFIG_VIDEO_TI_VPE) += ti-vpe.o ti-vpe-y := vpe.o sc.o csc.o vpdma.o ccflags-$(CONFIG_VIDEO_TI_VPE_DEBUG) += -DDEBUG + +obj-$(CONFIG_VIDEO_TI_CAL) += ti-cal.o + +ti-cal-y := cal.o diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c new file mode 100644 index 000000000000..69ec79ba49ee --- /dev/null +++ b/drivers/media/platform/ti-vpe/cal.c @@ -0,0 +1,1970 @@ +/* + * TI CAL camera interface driver + * + * Copyright (c) 2015 Texas Instruments Inc. + * Benoit Parrot, + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cal_regs.h" + +#define CAL_MODULE_NAME "cal" + +#define MAX_WIDTH 1920 +#define MAX_HEIGHT 1200 + +#define CAL_VERSION "0.1.0" + +MODULE_DESCRIPTION("TI CAL driver"); +MODULE_AUTHOR("Benoit Parrot, "); +MODULE_LICENSE("GPL v2"); +MODULE_VERSION(CAL_VERSION); + +static unsigned video_nr = -1; +module_param(video_nr, uint, 0644); +MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect"); + +static unsigned debug; +module_param(debug, uint, 0644); +MODULE_PARM_DESC(debug, "activates debug info"); + +/* timeperframe: min/max and default */ +static const struct v4l2_fract + tpf_default = {.numerator = 1001, .denominator = 30000}; + +#define cal_dbg(level, caldev, fmt, arg...) \ + v4l2_dbg(level, debug, &caldev->v4l2_dev, fmt, ##arg) +#define cal_info(caldev, fmt, arg...) \ + v4l2_info(&caldev->v4l2_dev, fmt, ##arg) +#define cal_err(caldev, fmt, arg...) \ + v4l2_err(&caldev->v4l2_dev, fmt, ##arg) + +#define ctx_dbg(level, ctx, fmt, arg...) \ + v4l2_dbg(level, debug, &ctx->v4l2_dev, fmt, ##arg) +#define ctx_info(ctx, fmt, arg...) \ + v4l2_info(&ctx->v4l2_dev, fmt, ##arg) +#define ctx_err(ctx, fmt, arg...) \ + v4l2_err(&ctx->v4l2_dev, fmt, ##arg) + +#define CAL_NUM_INPUT 1 +#define CAL_NUM_CONTEXT 2 + +#define bytes_per_line(pixel, bpp) (ALIGN(pixel * bpp, 16)) + +#define reg_read(dev, offset) ioread32(dev->base + offset) +#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset) + +#define reg_read_field(dev, offset, mask) get_field(reg_read(dev, offset), \ + mask) +#define reg_write_field(dev, offset, field, mask) { \ + u32 val = reg_read(dev, offset); \ + set_field(&val, field, mask); \ + reg_write(dev, offset, val); } + +/* ------------------------------------------------------------------ + * Basic structures + * ------------------------------------------------------------------ + */ + +struct cal_fmt { + u32 fourcc; + u32 code; + u8 depth; +}; + +static struct cal_fmt cal_formats[] = { + { + .fourcc = V4L2_PIX_FMT_YUYV, + .code = MEDIA_BUS_FMT_YUYV8_2X8, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_UYVY, + .code = MEDIA_BUS_FMT_UYVY8_2X8, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_YVYU, + .code = MEDIA_BUS_FMT_YVYU8_2X8, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_VYUY, + .code = MEDIA_BUS_FMT_VYUY8_2X8, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */ + .code = MEDIA_BUS_FMT_RGB565_2X8_LE, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */ + .code = MEDIA_BUS_FMT_RGB565_2X8_BE, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */ + .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */ + .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */ + .code = MEDIA_BUS_FMT_RGB888_2X12_LE, + .depth = 24, + }, { + .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */ + .code = MEDIA_BUS_FMT_RGB888_2X12_BE, + .depth = 24, + }, { + .fourcc = V4L2_PIX_FMT_RGB32, /* argb */ + .code = MEDIA_BUS_FMT_ARGB8888_1X32, + .depth = 32, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR8, + .code = MEDIA_BUS_FMT_SBGGR8_1X8, + .depth = 8, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG8, + .code = MEDIA_BUS_FMT_SGBRG8_1X8, + .depth = 8, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG8, + .code = MEDIA_BUS_FMT_SGRBG8_1X8, + .depth = 8, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB8, + .code = MEDIA_BUS_FMT_SRGGB8_1X8, + .depth = 8, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR10, + .code = MEDIA_BUS_FMT_SBGGR10_1X10, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG10, + .code = MEDIA_BUS_FMT_SGBRG10_1X10, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG10, + .code = MEDIA_BUS_FMT_SGRBG10_1X10, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB10, + .code = MEDIA_BUS_FMT_SRGGB10_1X10, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR12, + .code = MEDIA_BUS_FMT_SBGGR12_1X12, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG12, + .code = MEDIA_BUS_FMT_SGBRG12_1X12, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG12, + .code = MEDIA_BUS_FMT_SGRBG12_1X12, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB12, + .code = MEDIA_BUS_FMT_SRGGB12_1X12, + .depth = 16, + }, +}; + +/* Print Four-character-code (FOURCC) */ +static char *fourcc_to_str(u32 fmt) +{ + static char code[5]; + + code[0] = (unsigned char)(fmt & 0xff); + code[1] = (unsigned char)((fmt >> 8) & 0xff); + code[2] = (unsigned char)((fmt >> 16) & 0xff); + code[3] = (unsigned char)((fmt >> 24) & 0xff); + code[4] = '\0'; + + return code; +} + +/* buffer for one video frame */ +struct cal_buffer { + /* common v4l buffer stuff -- must be first */ + struct vb2_v4l2_buffer vb; + struct list_head list; + const struct cal_fmt *fmt; +}; + +struct cal_dmaqueue { + struct list_head active; + + /* Counters to control fps rate */ + int frame; + int ini_jiffies; +}; + +struct cm_data { + void __iomem *base; + struct resource *res; + + unsigned int camerrx_control; + + struct platform_device *pdev; +}; + +struct cc_data { + void __iomem *base; + struct resource *res; + + struct platform_device *pdev; +}; + +/* + * there is one cal_dev structure in the driver, it is shared by + * all instances. + */ +struct cal_dev { + int irq; + void __iomem *base; + struct resource *res; + struct platform_device *pdev; + struct v4l2_device v4l2_dev; + + /* Control Module handle */ + struct cm_data *cm; + /* Camera Core Module handle */ + struct cc_data *cc[CAL_NUM_CSI2_PORTS]; + + struct cal_ctx *ctx[CAL_NUM_CONTEXT]; +}; + +/* + * There is one cal_ctx structure for each camera core context. + */ +struct cal_ctx { + struct v4l2_device v4l2_dev; + struct v4l2_ctrl_handler ctrl_handler; + struct video_device vdev; + struct v4l2_async_notifier notifier; + struct v4l2_subdev *sensor; + struct v4l2_of_endpoint endpoint; + + struct v4l2_async_subdev asd; + struct v4l2_async_subdev *asd_list[1]; + + struct v4l2_fh fh; + struct cal_dev *dev; + struct cc_data *cc; + + /* v4l2_ioctl mutex */ + struct mutex mutex; + /* v4l2 buffers lock */ + spinlock_t slock; + + /* Several counters */ + unsigned long jiffies; + + struct vb2_alloc_ctx *alloc_ctx; + struct cal_dmaqueue vidq; + + /* Input Number */ + int input; + + /* video capture */ + const struct cal_fmt *fmt; + /* Used to store current pixel format */ + struct v4l2_format v_fmt; + /* Used to store current mbus frame format */ + struct v4l2_mbus_framefmt m_fmt; + + /* Current subdev enumerated format */ + struct cal_fmt *active_fmt[ARRAY_SIZE(cal_formats)]; + int num_active_fmt; + + struct v4l2_fract timeperframe; + unsigned int sequence; + unsigned int external_rate; + struct vb2_queue vb_vidq; + unsigned int seq_count; + unsigned int csi2_port; + unsigned int virtual_channel; + + /* Pointer pointing to current v4l2_buffer */ + struct cal_buffer *cur_frm; + /* Pointer pointing to next v4l2_buffer */ + struct cal_buffer *next_frm; +}; + +static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx, + u32 pixelformat) +{ + const struct cal_fmt *fmt; + unsigned int k; + + for (k = 0; k < ctx->num_active_fmt; k++) { + fmt = ctx->active_fmt[k]; + if (fmt->fourcc == pixelformat) + return fmt; + } + + return NULL; +} + +static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx, + u32 code) +{ + const struct cal_fmt *fmt; + unsigned int k; + + for (k = 0; k < ctx->num_active_fmt; k++) { + fmt = ctx->active_fmt[k]; + if (fmt->code == code) + return fmt; + } + + return NULL; +} + +static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n) +{ + return container_of(n, struct cal_ctx, notifier); +} + +static inline int get_field(u32 value, u32 mask) +{ + return (value & mask) >> __ffs(mask); +} + +static inline void set_field(u32 *valp, u32 field, u32 mask) +{ + u32 val = *valp; + + val &= ~mask; + val |= (field << __ffs(mask)) & mask; + *valp = val; +} + +/* + * Control Module block access + */ +static struct cm_data *cm_create(struct cal_dev *dev) +{ + struct platform_device *pdev = dev->pdev; + struct cm_data *cm; + + cm = devm_kzalloc(&pdev->dev, sizeof(*cm), GFP_KERNEL); + if (!cm) + return ERR_PTR(-ENOMEM); + + cm->res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "camerrx_control"); + cm->base = devm_ioremap_resource(&pdev->dev, cm->res); + if (IS_ERR(cm->base)) { + cal_err(dev, "failed to ioremap\n"); + return cm->base; + } + + cal_dbg(1, dev, "ioresource %s at %pa - %pa\n", + cm->res->name, &cm->res->start, &cm->res->end); + + return cm; +} + +static void camerarx_phy_enable(struct cal_ctx *ctx) +{ + u32 val; + + if (!ctx->dev->cm->base) { + ctx_err(ctx, "cm not mapped\n"); + return; + } + + val = reg_read(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL); + if (ctx->csi2_port == 1) { + set_field(&val, 1, CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_MASK); + set_field(&val, 0, CM_CAMERRX_CTRL_CSI0_CAMMODE_MASK); + /* enable all lanes by default */ + set_field(&val, 0xf, CM_CAMERRX_CTRL_CSI0_LANEENABLE_MASK); + set_field(&val, 1, CM_CAMERRX_CTRL_CSI0_MODE_MASK); + } else if (ctx->csi2_port == 2) { + set_field(&val, 1, CM_CAMERRX_CTRL_CSI1_CTRLCLKEN_MASK); + set_field(&val, 0, CM_CAMERRX_CTRL_CSI1_CAMMODE_MASK); + /* enable all lanes by default */ + set_field(&val, 0x3, CM_CAMERRX_CTRL_CSI1_LANEENABLE_MASK); + set_field(&val, 1, CM_CAMERRX_CTRL_CSI1_MODE_MASK); + } + reg_write(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL, val); +} + +static void camerarx_phy_disable(struct cal_ctx *ctx) +{ + u32 val; + + if (!ctx->dev->cm->base) { + ctx_err(ctx, "cm not mapped\n"); + return; + } + + val = reg_read(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL); + if (ctx->csi2_port == 1) + set_field(&val, 0x0, CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_MASK); + else if (ctx->csi2_port == 2) + set_field(&val, 0x0, CM_CAMERRX_CTRL_CSI1_CTRLCLKEN_MASK); + reg_write(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL, val); +} + +/* + * Camera Instance access block + */ +static struct cc_data *cc_create(struct cal_dev *dev, unsigned int core) +{ + struct platform_device *pdev = dev->pdev; + struct cc_data *cc; + + cc = devm_kzalloc(&pdev->dev, sizeof(*cc), GFP_KERNEL); + if (!cc) + return ERR_PTR(-ENOMEM); + + cc->res = platform_get_resource_byname(pdev, + IORESOURCE_MEM, + (core == 0) ? + "cal_rx_core0" : + "cal_rx_core1"); + cc->base = devm_ioremap_resource(&pdev->dev, cc->res); + if (IS_ERR(cc->base)) { + cal_err(dev, "failed to ioremap\n"); + return cc->base; + } + + cal_dbg(1, dev, "ioresource %s at %pa - %pa\n", + cc->res->name, &cc->res->start, &cc->res->end); + + return cc; +} + +/* + * Get Revision and HW info + */ +static void cal_get_hwinfo(struct cal_dev *dev) +{ + u32 revision = 0; + u32 hwinfo = 0; + + revision = reg_read(dev, CAL_HL_REVISION); + cal_dbg(3, dev, "CAL_HL_REVISION = 0x%08x (expecting 0x40000200)\n", + revision); + + hwinfo = reg_read(dev, CAL_HL_HWINFO); + cal_dbg(3, dev, "CAL_HL_HWINFO = 0x%08x (expecting 0xA3C90469)\n", + hwinfo); +} + +static inline int cal_runtime_get(struct cal_dev *dev) +{ + int r; + + r = pm_runtime_get_sync(&dev->pdev->dev); + + return r; +} + +static inline void cal_runtime_put(struct cal_dev *dev) +{ + pm_runtime_put_sync(&dev->pdev->dev); +} + +static void cal_quickdump_regs(struct cal_dev *dev) +{ + cal_info(dev, "CAL Registers @ 0x%pa:\n", &dev->res->start); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4, + dev->base, resource_size(dev->res), false); + + if (dev->ctx[0]) { + cal_info(dev, "CSI2 Core 0 Registers @ %pa:\n", + &dev->ctx[0]->cc->res->start); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4, + dev->ctx[0]->cc->base, + resource_size(dev->ctx[0]->cc->res), + false); + } + + if (dev->ctx[1]) { + cal_info(dev, "CSI2 Core 1 Registers @ %pa:\n", + &dev->ctx[1]->cc->res->start); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4, + dev->ctx[1]->cc->base, + resource_size(dev->ctx[1]->cc->res), + false); + } + + cal_info(dev, "CAMERRX_Control Registers @ %pa:\n", + &dev->cm->res->start); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4, + dev->cm->base, + resource_size(dev->cm->res), false); +} + +/* + * Enable the expected IRQ sources + */ +static void enable_irqs(struct cal_ctx *ctx) +{ + /* Enable IRQ_WDMA_END 0/1 */ + reg_write_field(ctx->dev, + CAL_HL_IRQENABLE_SET(2), + CAL_HL_IRQ_ENABLE, + CAL_HL_IRQ_MASK(ctx->csi2_port)); + /* Enable IRQ_WDMA_START 0/1 */ + reg_write_field(ctx->dev, + CAL_HL_IRQENABLE_SET(3), + CAL_HL_IRQ_ENABLE, + CAL_HL_IRQ_MASK(ctx->csi2_port)); + /* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */ + reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(1), 0xFF000000); +} + +static void disable_irqs(struct cal_ctx *ctx) +{ + /* Disable IRQ_WDMA_END 0/1 */ + reg_write_field(ctx->dev, + CAL_HL_IRQENABLE_CLR(2), + CAL_HL_IRQ_CLEAR, + CAL_HL_IRQ_MASK(ctx->csi2_port)); + /* Disable IRQ_WDMA_START 0/1 */ + reg_write_field(ctx->dev, + CAL_HL_IRQENABLE_CLR(3), + CAL_HL_IRQ_CLEAR, + CAL_HL_IRQ_MASK(ctx->csi2_port)); + /* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */ + reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(1), 0); +} + +static void csi2_init(struct cal_ctx *ctx) +{ + int i; + u32 val; + + val = reg_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port)); + set_field(&val, CAL_GEN_ENABLE, + CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK); + set_field(&val, CAL_GEN_ENABLE, + CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK); + set_field(&val, CAL_GEN_DISABLE, + CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK); + set_field(&val, 407, CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK); + reg_write(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_CSI2_TIMING(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port))); + + val = reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)); + set_field(&val, CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL, + CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK); + set_field(&val, CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON, + CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK); + reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val); + for (i = 0; i < 10; i++) { + if (reg_read_field(ctx->dev, + CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), + CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK) == + CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_ON) + break; + usleep_range(1000, 1100); + } + ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port))); + + val = reg_read(ctx->dev, CAL_CTRL); + set_field(&val, CAL_CTRL_BURSTSIZE_BURST128, CAL_CTRL_BURSTSIZE_MASK); + set_field(&val, 0xF, CAL_CTRL_TAGCNT_MASK); + set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED, + CAL_CTRL_POSTED_WRITES_MASK); + set_field(&val, 0xFF, CAL_CTRL_MFLAGL_MASK); + set_field(&val, 0xFF, CAL_CTRL_MFLAGH_MASK); + reg_write(ctx->dev, CAL_CTRL, val); + ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", reg_read(ctx->dev, CAL_CTRL)); +} + +static void csi2_lane_config(struct cal_ctx *ctx) +{ + u32 val = reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)); + u32 lane_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK; + u32 polarity_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK; + struct v4l2_of_bus_mipi_csi2 *mipi_csi2 = &ctx->endpoint.bus.mipi_csi2; + int lane; + + set_field(&val, mipi_csi2->clock_lane + 1, lane_mask); + set_field(&val, mipi_csi2->lane_polarities[0], polarity_mask); + for (lane = 0; lane < mipi_csi2->num_data_lanes; lane++) { + /* + * Every lane are one nibble apart starting with the + * clock followed by the data lanes so shift masks by 4. + */ + lane_mask <<= 4; + polarity_mask <<= 4; + set_field(&val, mipi_csi2->data_lanes[lane] + 1, lane_mask); + set_field(&val, mipi_csi2->lane_polarities[lane + 1], + polarity_mask); + } + + reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n", + ctx->csi2_port, val); +} + +static void csi2_ppi_enable(struct cal_ctx *ctx) +{ + reg_write_field(ctx->dev, CAL_CSI2_PPI_CTRL(ctx->csi2_port), + CAL_GEN_ENABLE, CAL_CSI2_PPI_CTRL_IF_EN_MASK); +} + +static void csi2_ppi_disable(struct cal_ctx *ctx) +{ + reg_write_field(ctx->dev, CAL_CSI2_PPI_CTRL(ctx->csi2_port), + CAL_GEN_DISABLE, CAL_CSI2_PPI_CTRL_IF_EN_MASK); +} + +static void csi2_ctx_config(struct cal_ctx *ctx) +{ + u32 val; + + val = reg_read(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port)); + set_field(&val, ctx->csi2_port, CAL_CSI2_CTX_CPORT_MASK); + /* + * DT type: MIPI CSI-2 Specs + * 0x1: All - DT filter is disabled + * 0x24: RGB888 1 pixel = 3 bytes + * 0x2B: RAW10 4 pixels = 5 bytes + * 0x2A: RAW8 1 pixel = 1 byte + * 0x1E: YUV422 2 pixels = 4 bytes + */ + set_field(&val, 0x1, CAL_CSI2_CTX_DT_MASK); + /* Virtual Channel from the CSI2 sensor usually 0! */ + set_field(&val, ctx->virtual_channel, CAL_CSI2_CTX_VC_MASK); + /* NUM_LINES_PER_FRAME => 0 means auto detect */ + set_field(&val, 0, CAL_CSI2_CTX_LINES_MASK); + set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK); + set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE, + CAL_CSI2_CTX_PACK_MODE_MASK); + reg_write(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_CSI2_CTX0(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port))); +} + +static void pix_proc_config(struct cal_ctx *ctx) +{ + u32 val; + + val = reg_read(ctx->dev, CAL_PIX_PROC(ctx->csi2_port)); + set_field(&val, CAL_PIX_PROC_EXTRACT_B8, CAL_PIX_PROC_EXTRACT_MASK); + set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK); + set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK); + set_field(&val, CAL_PIX_PROC_PACK_B8, CAL_PIX_PROC_PACK_MASK); + set_field(&val, ctx->csi2_port, CAL_PIX_PROC_CPORT_MASK); + set_field(&val, CAL_GEN_ENABLE, CAL_PIX_PROC_EN_MASK); + reg_write(ctx->dev, CAL_PIX_PROC(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_PIX_PROC(ctx->csi2_port))); +} + +static void cal_wr_dma_config(struct cal_ctx *ctx, + unsigned int width) +{ + u32 val; + + val = reg_read(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port)); + set_field(&val, ctx->csi2_port, CAL_WR_DMA_CTRL_CPORT_MASK); + set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT, + CAL_WR_DMA_CTRL_DTAG_MASK); + set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST, + CAL_WR_DMA_CTRL_MODE_MASK); + set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR, + CAL_WR_DMA_CTRL_PATTERN_MASK); + set_field(&val, CAL_GEN_ENABLE, CAL_WR_DMA_CTRL_STALL_RD_MASK); + reg_write(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port))); + + /* + * width/16 not sure but giving it a whirl. + * zero does not work right + */ + reg_write_field(ctx->dev, + CAL_WR_DMA_OFST(ctx->csi2_port), + (width / 16), + CAL_WR_DMA_OFST_MASK); + ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_WR_DMA_OFST(ctx->csi2_port))); + + val = reg_read(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port)); + /* 64 bit word means no skipping */ + set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK); + /* + * (width*8)/64 this should be size of an entire line + * in 64bit word but 0 means all data until the end + * is detected automagically + */ + set_field(&val, (width / 8), CAL_WR_DMA_XSIZE_MASK); + reg_write(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port))); +} + +static void cal_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr) +{ + reg_write(ctx->dev, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr); +} + +/* + * TCLK values are OK at their reset values + */ +#define TCLK_TERM 0 +#define TCLK_MISS 1 +#define TCLK_SETTLE 14 +#define THS_SETTLE 15 + +static void csi2_phy_config(struct cal_ctx *ctx) +{ + unsigned int reg0, reg1; + unsigned int ths_term, ths_settle; + unsigned int ddrclkperiod_us; + + /* + * THS_TERM: Programmed value = floor(20 ns/DDRClk period) - 2. + */ + ddrclkperiod_us = ctx->external_rate / 2000000; + ddrclkperiod_us = 1000000 / ddrclkperiod_us; + ctx_dbg(1, ctx, "ddrclkperiod_us: %d\n", ddrclkperiod_us); + + ths_term = 20000 / ddrclkperiod_us; + ths_term = (ths_term >= 2) ? ths_term - 2 : ths_term; + ctx_dbg(1, ctx, "ths_term: %d (0x%02x)\n", ths_term, ths_term); + + /* + * THS_SETTLE: Programmed value = floor(176.3 ns/CtrlClk period) - 1. + * Since CtrlClk is fixed at 96Mhz then we get + * ths_settle = floor(176.3 / 10.416) - 1 = 15 + * If we ever switch to a dynamic clock then this code might be useful + * + * unsigned int ctrlclkperiod_us; + * ctrlclkperiod_us = 96000000 / 1000000; + * ctrlclkperiod_us = 1000000 / ctrlclkperiod_us; + * ctx_dbg(1, ctx, "ctrlclkperiod_us: %d\n", ctrlclkperiod_us); + + * ths_settle = 176300 / ctrlclkperiod_us; + * ths_settle = (ths_settle > 1) ? ths_settle - 1 : ths_settle; + */ + + ths_settle = THS_SETTLE; + ctx_dbg(1, ctx, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle); + + reg0 = reg_read(ctx->cc, CAL_CSI2_PHY_REG0); + set_field(®0, CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE, + CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK); + set_field(®0, ths_term, CAL_CSI2_PHY_REG0_THS_TERM_MASK); + set_field(®0, ths_settle, CAL_CSI2_PHY_REG0_THS_SETTLE_MASK); + + ctx_dbg(1, ctx, "CSI2_%d_REG0 = 0x%08x\n", (ctx->csi2_port - 1), reg0); + reg_write(ctx->cc, CAL_CSI2_PHY_REG0, reg0); + + reg1 = reg_read(ctx->cc, CAL_CSI2_PHY_REG1); + set_field(®1, TCLK_TERM, CAL_CSI2_PHY_REG1_TCLK_TERM_MASK); + set_field(®1, 0xb8, CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK); + set_field(®1, TCLK_MISS, CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK); + set_field(®1, TCLK_SETTLE, CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK); + + ctx_dbg(1, ctx, "CSI2_%d_REG1 = 0x%08x\n", (ctx->csi2_port - 1), reg1); + reg_write(ctx->cc, CAL_CSI2_PHY_REG1, reg1); +} + +static int cal_get_external_info(struct cal_ctx *ctx) +{ + struct v4l2_ctrl *ctrl; + + ctrl = v4l2_ctrl_find(ctx->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE); + if (!ctrl) { + ctx_err(ctx, "no pixel rate control in subdev: %s\n", + ctx->sensor->name); + return -EPIPE; + } + + ctx->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl); + ctx_dbg(3, ctx, "sensor Pixel Rate: %d\n", ctx->external_rate); + + return 0; +} + +static inline void cal_schedule_next_buffer(struct cal_ctx *ctx) +{ + struct cal_dmaqueue *dma_q = &ctx->vidq; + struct cal_buffer *buf; + unsigned long addr; + + buf = list_entry(dma_q->active.next, struct cal_buffer, list); + ctx->next_frm = buf; + list_del(&buf->list); + + addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); + cal_wr_dma_addr(ctx, addr); +} + +static inline void cal_process_buffer_complete(struct cal_ctx *ctx) +{ + ctx->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns(); + ctx->cur_frm->vb.field = ctx->m_fmt.field; + ctx->cur_frm->vb.sequence = ctx->sequence++; + + vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); + ctx->cur_frm = ctx->next_frm; +} + +#define isvcirqset(irq, vc, ff) (irq & \ + (CAL_CSI2_VC_IRQENABLE_ ##ff ##_IRQ_##vc ##_MASK)) + +#define isportirqset(irq, port) (irq & CAL_HL_IRQ_MASK(port)) + +static irqreturn_t cal_irq(int irq_cal, void *data) +{ + struct cal_dev *dev = (struct cal_dev *)data; + struct cal_ctx *ctx; + struct cal_dmaqueue *dma_q; + u32 irqst2, irqst3; + + /* Check which DMA just finished */ + irqst2 = reg_read(dev, CAL_HL_IRQSTATUS(2)); + if (irqst2) { + /* Clear Interrupt status */ + reg_write(dev, CAL_HL_IRQSTATUS(2), irqst2); + + /* Need to check both port */ + if (isportirqset(irqst2, 1)) { + ctx = dev->ctx[0]; + + if (ctx->cur_frm != ctx->next_frm) + cal_process_buffer_complete(ctx); + } + + if (isportirqset(irqst2, 2)) { + ctx = dev->ctx[1]; + + if (ctx->cur_frm != ctx->next_frm) + cal_process_buffer_complete(ctx); + } + } + + /* Check which DMA just started */ + irqst3 = reg_read(dev, CAL_HL_IRQSTATUS(3)); + if (irqst3) { + /* Clear Interrupt status */ + reg_write(dev, CAL_HL_IRQSTATUS(3), irqst3); + + /* Need to check both port */ + if (isportirqset(irqst3, 1)) { + ctx = dev->ctx[0]; + dma_q = &ctx->vidq; + + spin_lock(&ctx->slock); + if (!list_empty(&dma_q->active) && + ctx->cur_frm == ctx->next_frm) + cal_schedule_next_buffer(ctx); + spin_unlock(&ctx->slock); + } + + if (isportirqset(irqst3, 2)) { + ctx = dev->ctx[1]; + dma_q = &ctx->vidq; + + spin_lock(&ctx->slock); + if (!list_empty(&dma_q->active) && + ctx->cur_frm == ctx->next_frm) + cal_schedule_next_buffer(ctx); + spin_unlock(&ctx->slock); + } + } + + return IRQ_HANDLED; +} + +/* + * video ioctls + */ +static int cal_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct cal_ctx *ctx = video_drvdata(file); + + strlcpy(cap->driver, CAL_MODULE_NAME, sizeof(cap->driver)); + strlcpy(cap->card, CAL_MODULE_NAME, sizeof(cap->card)); + + snprintf(cap->bus_info, sizeof(cap->bus_info), + "platform:%s", ctx->v4l2_dev.name); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; +} + +static int cal_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct cal_ctx *ctx = video_drvdata(file); + const struct cal_fmt *fmt = NULL; + + if (f->index >= ctx->num_active_fmt) + return -EINVAL; + + fmt = ctx->active_fmt[f->index]; + + f->pixelformat = fmt->fourcc; + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + return 0; +} + +static int __subdev_get_format(struct cal_ctx *ctx, + struct v4l2_mbus_framefmt *fmt) +{ + struct v4l2_subdev_format sd_fmt; + struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format; + int ret; + + if (!ctx->sensor) + return -EINVAL; + + sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sd_fmt.pad = 0; + + ret = v4l2_subdev_call(ctx->sensor, pad, get_fmt, NULL, &sd_fmt); + if (ret) + return ret; + + *fmt = *mbus_fmt; + + ctx_dbg(1, ctx, "%s %dx%d code:%04X\n", __func__, + fmt->width, fmt->height, fmt->code); + + return 0; +} + +static int __subdev_set_format(struct cal_ctx *ctx, + struct v4l2_mbus_framefmt *fmt) +{ + struct v4l2_subdev_format sd_fmt; + struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format; + int ret; + + if (!ctx->sensor) + return -EINVAL; + + sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sd_fmt.pad = 0; + *mbus_fmt = *fmt; + + ret = v4l2_subdev_call(ctx->sensor, pad, set_fmt, NULL, &sd_fmt); + if (ret) + return ret; + + ctx_dbg(1, ctx, "%s %dx%d code:%04X\n", __func__, + fmt->width, fmt->height, fmt->code); + + return 0; +} + +static int cal_calc_format_size(struct cal_ctx *ctx, + const struct cal_fmt *fmt, + struct v4l2_format *f) +{ + if (!fmt) { + ctx_dbg(3, ctx, "No cal_fmt provided!\n"); + return -EINVAL; + } + + v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2, + &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0); + f->fmt.pix.bytesperline = bytes_per_line(f->fmt.pix.width, + fmt->depth >> 3); + f->fmt.pix.sizeimage = f->fmt.pix.height * + f->fmt.pix.bytesperline; + + ctx_dbg(3, ctx, "%s: fourcc: %s size: %dx%d bpl:%d img_size:%d\n", + __func__, fourcc_to_str(f->fmt.pix.pixelformat), + f->fmt.pix.width, f->fmt.pix.height, + f->fmt.pix.bytesperline, f->fmt.pix.sizeimage); + + return 0; +} + +static int cal_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cal_ctx *ctx = video_drvdata(file); + + *f = ctx->v_fmt; + + return 0; +} + +static int cal_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cal_ctx *ctx = video_drvdata(file); + const struct cal_fmt *fmt; + struct v4l2_subdev_frame_size_enum fse; + int ret, found; + + fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat); + if (!fmt) { + ctx_dbg(3, ctx, "Fourcc format (0x%08x) not found.\n", + f->fmt.pix.pixelformat); + + /* Just get the first one enumerated */ + fmt = ctx->active_fmt[0]; + f->fmt.pix.pixelformat = fmt->fourcc; + } + + f->fmt.pix.field = ctx->v_fmt.fmt.pix.field; + + /* check for/find a valid width/height */ + ret = 0; + found = false; + fse.pad = 0; + fse.code = fmt->code; + fse.which = V4L2_SUBDEV_FORMAT_ACTIVE; + for (fse.index = 0; ; fse.index++) { + ret = v4l2_subdev_call(ctx->sensor, pad, enum_frame_size, + NULL, &fse); + if (ret) + break; + + if ((f->fmt.pix.width == fse.max_width) && + (f->fmt.pix.height == fse.max_height)) { + found = true; + break; + } else if ((f->fmt.pix.width >= fse.min_width) && + (f->fmt.pix.width <= fse.max_width) && + (f->fmt.pix.height >= fse.min_height) && + (f->fmt.pix.height <= fse.max_height)) { + found = true; + break; + } + } + + if (!found) { + /* use existing values as default */ + f->fmt.pix.width = ctx->v_fmt.fmt.pix.width; + f->fmt.pix.height = ctx->v_fmt.fmt.pix.height; + } + + /* + * Use current colorspace for now, it will get + * updated properly during s_fmt + */ + f->fmt.pix.colorspace = ctx->v_fmt.fmt.pix.colorspace; + return cal_calc_format_size(ctx, fmt, f); +} + +static int cal_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cal_ctx *ctx = video_drvdata(file); + struct vb2_queue *q = &ctx->vb_vidq; + const struct cal_fmt *fmt; + struct v4l2_mbus_framefmt mbus_fmt; + int ret; + + if (vb2_is_busy(q)) { + ctx_dbg(3, ctx, "%s device busy\n", __func__); + return -EBUSY; + } + + ret = cal_try_fmt_vid_cap(file, priv, f); + if (ret < 0) + return ret; + + fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat); + + v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, fmt->code); + + ret = __subdev_set_format(ctx, &mbus_fmt); + if (ret) + return ret; + + /* Just double check nothing has gone wrong */ + if (mbus_fmt.code != fmt->code) { + ctx_dbg(3, ctx, + "%s subdev changed format on us, this should not happen\n", + __func__); + return -EINVAL; + } + + v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt); + ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + ctx->v_fmt.fmt.pix.pixelformat = fmt->fourcc; + cal_calc_format_size(ctx, fmt, &ctx->v_fmt); + ctx->fmt = fmt; + ctx->m_fmt = mbus_fmt; + *f = ctx->v_fmt; + + return 0; +} + +static int cal_enum_framesizes(struct file *file, void *fh, + struct v4l2_frmsizeenum *fsize) +{ + struct cal_ctx *ctx = video_drvdata(file); + const struct cal_fmt *fmt; + struct v4l2_subdev_frame_size_enum fse; + int ret; + + /* check for valid format */ + fmt = find_format_by_pix(ctx, fsize->pixel_format); + if (!fmt) { + ctx_dbg(3, ctx, "Invalid pixel code: %x\n", + fsize->pixel_format); + return -EINVAL; + } + + fse.index = fsize->index; + fse.pad = 0; + fse.code = fmt->code; + + ret = v4l2_subdev_call(ctx->sensor, pad, enum_frame_size, NULL, &fse); + if (ret) + return -EINVAL; + + ctx_dbg(1, ctx, "%s: index: %d code: %x W:[%d,%d] H:[%d,%d]\n", + __func__, fse.index, fse.code, fse.min_width, fse.max_width, + fse.min_height, fse.max_height); + + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = fse.max_width; + fsize->discrete.height = fse.max_height; + + return 0; +} + +static int cal_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) +{ + if (inp->index >= CAL_NUM_INPUT) + return -EINVAL; + + inp->type = V4L2_INPUT_TYPE_CAMERA; + sprintf(inp->name, "Camera %u", inp->index); + return 0; +} + +static int cal_g_input(struct file *file, void *priv, unsigned int *i) +{ + struct cal_ctx *ctx = video_drvdata(file); + + *i = ctx->input; + return 0; +} + +static int cal_s_input(struct file *file, void *priv, unsigned int i) +{ + struct cal_ctx *ctx = video_drvdata(file); + + if (i >= CAL_NUM_INPUT) + return -EINVAL; + + ctx->input = i; + return 0; +} + +/* timeperframe is arbitrary and continuous */ +static int cal_enum_frameintervals(struct file *file, void *priv, + struct v4l2_frmivalenum *fival) +{ + struct cal_ctx *ctx = video_drvdata(file); + const struct cal_fmt *fmt; + struct v4l2_subdev_frame_size_enum fse; + int ret; + + if (fival->index) + return -EINVAL; + + fmt = find_format_by_pix(ctx, fival->pixel_format); + if (!fmt) + return -EINVAL; + + /* check for valid width/height */ + ret = 0; + fse.pad = 0; + fse.code = fmt->code; + fse.which = V4L2_SUBDEV_FORMAT_ACTIVE; + for (fse.index = 0; ; fse.index++) { + ret = v4l2_subdev_call(ctx->sensor, pad, enum_frame_size, + NULL, &fse); + if (ret) + return -EINVAL; + + if ((fival->width == fse.max_width) && + (fival->height == fse.max_height)) + break; + else if ((fival->width >= fse.min_width) && + (fival->width <= fse.max_width) && + (fival->height >= fse.min_height) && + (fival->height <= fse.max_height)) + break; + + return -EINVAL; + } + + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; + fival->discrete.numerator = 1; + fival->discrete.denominator = 30; + + return 0; +} + +/* + * Videobuf operations + */ +static int cal_queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct cal_ctx *ctx = vb2_get_drv_priv(vq); + unsigned size = ctx->v_fmt.fmt.pix.sizeimage; + + if (vq->num_buffers + *nbuffers < 3) + *nbuffers = 3 - vq->num_buffers; + alloc_ctxs[0] = ctx->alloc_ctx; + + if (*nplanes) { + if (sizes[0] < size) + return -EINVAL; + size = sizes[0]; + } + + *nplanes = 1; + sizes[0] = size; + + ctx_dbg(3, ctx, "nbuffers=%d, size=%d\n", *nbuffers, sizes[0]); + + return 0; +} + +static int cal_buffer_prepare(struct vb2_buffer *vb) +{ + struct cal_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct cal_buffer *buf = container_of(vb, struct cal_buffer, + vb.vb2_buf); + unsigned long size; + + if (WARN_ON(!ctx->fmt)) + return -EINVAL; + + size = ctx->v_fmt.fmt.pix.sizeimage; + if (vb2_plane_size(vb, 0) < size) { + ctx_err(ctx, + "data will not fit into plane (%lu < %lu)\n", + vb2_plane_size(vb, 0), size); + return -EINVAL; + } + + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); + return 0; +} + +static void cal_buffer_queue(struct vb2_buffer *vb) +{ + struct cal_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct cal_buffer *buf = container_of(vb, struct cal_buffer, + vb.vb2_buf); + struct cal_dmaqueue *vidq = &ctx->vidq; + unsigned long flags = 0; + + /* recheck locking */ + spin_lock_irqsave(&ctx->slock, flags); + list_add_tail(&buf->list, &vidq->active); + spin_unlock_irqrestore(&ctx->slock, flags); +} + +static int cal_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct cal_ctx *ctx = vb2_get_drv_priv(vq); + struct cal_dmaqueue *dma_q = &ctx->vidq; + struct cal_buffer *buf, *tmp; + unsigned long addr = 0; + unsigned long flags; + int ret; + + spin_lock_irqsave(&ctx->slock, flags); + if (list_empty(&dma_q->active)) { + spin_unlock_irqrestore(&ctx->slock, flags); + ctx_dbg(3, ctx, "buffer queue is empty\n"); + return -EIO; + } + + buf = list_entry(dma_q->active.next, struct cal_buffer, list); + ctx->cur_frm = buf; + ctx->next_frm = buf; + list_del(&buf->list); + spin_unlock_irqrestore(&ctx->slock, flags); + + addr = vb2_dma_contig_plane_dma_addr(&ctx->cur_frm->vb.vb2_buf, 0); + ctx->sequence = 0; + + ret = cal_get_external_info(ctx); + if (ret < 0) + goto err; + + cal_runtime_get(ctx->dev); + + enable_irqs(ctx); + camerarx_phy_enable(ctx); + csi2_init(ctx); + csi2_phy_config(ctx); + csi2_lane_config(ctx); + csi2_ctx_config(ctx); + pix_proc_config(ctx); + cal_wr_dma_config(ctx, ctx->v_fmt.fmt.pix.bytesperline); + cal_wr_dma_addr(ctx, addr); + csi2_ppi_enable(ctx); + + if (ctx->sensor) { + if (v4l2_subdev_call(ctx->sensor, video, s_stream, 1)) { + ctx_err(ctx, "stream on failed in subdev\n"); + cal_runtime_put(ctx->dev); + ret = -EINVAL; + goto err; + } + } + + if (debug >= 4) + cal_quickdump_regs(ctx->dev); + + return 0; + +err: + list_for_each_entry_safe(buf, tmp, &dma_q->active, list) { + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); + } + return ret; +} + +static void cal_stop_streaming(struct vb2_queue *vq) +{ + struct cal_ctx *ctx = vb2_get_drv_priv(vq); + struct cal_dmaqueue *dma_q = &ctx->vidq; + struct cal_buffer *buf, *tmp; + unsigned long flags; + + if (ctx->sensor) { + if (v4l2_subdev_call(ctx->sensor, video, s_stream, 0)) + ctx_err(ctx, "stream off failed in subdev\n"); + } + + csi2_ppi_disable(ctx); + disable_irqs(ctx); + + /* Release all active buffers */ + spin_lock_irqsave(&ctx->slock, flags); + list_for_each_entry_safe(buf, tmp, &dma_q->active, list) { + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + } + + if (ctx->cur_frm == ctx->next_frm) { + vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); + } else { + vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&ctx->next_frm->vb.vb2_buf, + VB2_BUF_STATE_ERROR); + } + ctx->cur_frm = NULL; + ctx->next_frm = NULL; + spin_unlock_irqrestore(&ctx->slock, flags); + + cal_runtime_put(ctx->dev); +} + +static struct vb2_ops cal_video_qops = { + .queue_setup = cal_queue_setup, + .buf_prepare = cal_buffer_prepare, + .buf_queue = cal_buffer_queue, + .start_streaming = cal_start_streaming, + .stop_streaming = cal_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, +}; + +static const struct v4l2_file_operations cal_fops = { + .owner = THIS_MODULE, + .open = v4l2_fh_open, + .release = vb2_fop_release, + .read = vb2_fop_read, + .poll = vb2_fop_poll, + .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ + .mmap = vb2_fop_mmap, +}; + +static const struct v4l2_ioctl_ops cal_ioctl_ops = { + .vidioc_querycap = cal_querycap, + .vidioc_enum_fmt_vid_cap = cal_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = cal_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = cal_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = cal_s_fmt_vid_cap, + .vidioc_enum_framesizes = cal_enum_framesizes, + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_enum_input = cal_enum_input, + .vidioc_g_input = cal_g_input, + .vidioc_s_input = cal_s_input, + .vidioc_enum_frameintervals = cal_enum_frameintervals, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static struct video_device cal_videodev = { + .name = CAL_MODULE_NAME, + .fops = &cal_fops, + .ioctl_ops = &cal_ioctl_ops, + .minor = -1, + .release = video_device_release_empty, +}; + +/* ----------------------------------------------------------------- + * Initialization and module stuff + * ------------------------------------------------------------------ + */ +static int cal_complete_ctx(struct cal_ctx *ctx); + +static int cal_async_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *subdev, + struct v4l2_async_subdev *asd) +{ + struct cal_ctx *ctx = notifier_to_ctx(notifier); + struct v4l2_subdev_mbus_code_enum mbus_code; + int ret = 0; + int i, j, k; + + if (ctx->sensor) { + ctx_info(ctx, "Rejecting subdev %s (Already set!!)", + subdev->name); + return 0; + } + + ctx->sensor = subdev; + ctx_dbg(1, ctx, "Using sensor %s for capture\n", subdev->name); + + /* Enumerate sub device formats and enable all matching local formats */ + ctx->num_active_fmt = 0; + for (j = 0, i = 0; ret != -EINVAL; ++j) { + struct cal_fmt *fmt; + + memset(&mbus_code, 0, sizeof(mbus_code)); + mbus_code.index = j; + ret = v4l2_subdev_call(subdev, pad, enum_mbus_code, + NULL, &mbus_code); + if (ret) + continue; + + ctx_dbg(2, ctx, + "subdev %s: code: %04x idx: %d\n", + subdev->name, mbus_code.code, j); + + for (k = 0; k < ARRAY_SIZE(cal_formats); k++) { + fmt = &cal_formats[k]; + + if (mbus_code.code == fmt->code) { + ctx->active_fmt[i] = fmt; + ctx_dbg(2, ctx, + "matched fourcc: %s: code: %04x idx: %d\n", + fourcc_to_str(fmt->fourcc), + fmt->code, i); + ctx->num_active_fmt = ++i; + } + } + } + + if (i == 0) { + ctx_err(ctx, "No suitable format reported by subdev %s\n", + subdev->name); + return -EINVAL; + } + + cal_complete_ctx(ctx); + + return 0; +} + +static int cal_async_complete(struct v4l2_async_notifier *notifier) +{ + struct cal_ctx *ctx = notifier_to_ctx(notifier); + const struct cal_fmt *fmt; + struct v4l2_mbus_framefmt mbus_fmt; + int ret; + + ret = __subdev_get_format(ctx, &mbus_fmt); + if (ret) + return ret; + + fmt = find_format_by_code(ctx, mbus_fmt.code); + if (!fmt) { + ctx_dbg(3, ctx, "mbus code format (0x%08x) not found.\n", + mbus_fmt.code); + return -EINVAL; + } + + /* Save current subdev format */ + v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt); + ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + ctx->v_fmt.fmt.pix.pixelformat = fmt->fourcc; + cal_calc_format_size(ctx, fmt, &ctx->v_fmt); + ctx->fmt = fmt; + ctx->m_fmt = mbus_fmt; + + return 0; +} + +static int cal_complete_ctx(struct cal_ctx *ctx) +{ + struct video_device *vfd; + struct vb2_queue *q; + int ret; + + ctx->timeperframe = tpf_default; + ctx->external_rate = 192000000; + + /* initialize locks */ + spin_lock_init(&ctx->slock); + mutex_init(&ctx->mutex); + + /* initialize queue */ + q = &ctx->vb_vidq; + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; + q->drv_priv = ctx; + q->buf_struct_size = sizeof(struct cal_buffer); + q->ops = &cal_video_qops; + q->mem_ops = &vb2_dma_contig_memops; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &ctx->mutex; + q->min_buffers_needed = 3; + + ret = vb2_queue_init(q); + if (ret) + return ret; + + /* init video dma queues */ + INIT_LIST_HEAD(&ctx->vidq.active); + + vfd = &ctx->vdev; + *vfd = cal_videodev; + vfd->v4l2_dev = &ctx->v4l2_dev; + vfd->queue = q; + + /* + * Provide a mutex to v4l2 core. It will be used to protect + * all fops and v4l2 ioctls. + */ + vfd->lock = &ctx->mutex; + video_set_drvdata(vfd, ctx); + + ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); + if (ret < 0) + return ret; + + v4l2_info(&ctx->v4l2_dev, "V4L2 device registered as %s\n", + video_device_node_name(vfd)); + + ctx->alloc_ctx = vb2_dma_contig_init_ctx(vfd->v4l2_dev->dev); + if (IS_ERR(ctx->alloc_ctx)) { + ctx_err(ctx, "Failed to alloc vb2 context\n"); + ret = PTR_ERR(ctx->alloc_ctx); + goto vdev_unreg; + } + + return 0; + +vdev_unreg: + video_unregister_device(vfd); + return ret; +} + +static struct device_node * +of_get_next_port(const struct device_node *parent, + struct device_node *prev) +{ + struct device_node *port = NULL; + + if (!parent) + return NULL; + + if (!prev) { + struct device_node *ports; + /* + * It's the first call, we have to find a port subnode + * within this node or within an optional 'ports' node. + */ + ports = of_get_child_by_name(parent, "ports"); + if (ports) + parent = ports; + + port = of_get_child_by_name(parent, "port"); + + /* release the 'ports' node */ + of_node_put(ports); + } else { + struct device_node *ports; + + ports = of_get_parent(prev); + if (!ports) + return NULL; + + do { + port = of_get_next_child(ports, prev); + if (!port) { + of_node_put(ports); + return NULL; + } + prev = port; + } while (of_node_cmp(port->name, "port") != 0); + } + + return port; +} + +static struct device_node * +of_get_next_endpoint(const struct device_node *parent, + struct device_node *prev) +{ + struct device_node *ep = NULL; + + if (!parent) + return NULL; + + do { + ep = of_get_next_child(parent, prev); + if (!ep) + return NULL; + prev = ep; + } while (of_node_cmp(ep->name, "endpoint") != 0); + + return ep; +} + +static int of_cal_create_instance(struct cal_ctx *ctx, int inst) +{ + struct platform_device *pdev = ctx->dev->pdev; + struct device_node *ep_node, *port, *remote_ep, + *sensor_node, *parent; + struct v4l2_of_endpoint *endpoint; + struct v4l2_async_subdev *asd; + u32 regval = 0; + int ret, index, found_port = 0, lane; + + parent = pdev->dev.of_node; + + asd = &ctx->asd; + endpoint = &ctx->endpoint; + + ep_node = NULL; + port = NULL; + remote_ep = NULL; + sensor_node = NULL; + ret = -EINVAL; + + ctx_dbg(3, ctx, "Scanning Port node for csi2 port: %d\n", inst); + for (index = 0; index < CAL_NUM_CSI2_PORTS; index++) { + port = of_get_next_port(parent, port); + if (!port) { + ctx_dbg(1, ctx, "No port node found for csi2 port:%d\n", + index); + goto cleanup_exit; + } + + /* Match the slice number with */ + of_property_read_u32(port, "reg", ®val); + ctx_dbg(3, ctx, "port:%d inst:%d :%d\n", + index, inst, regval); + if ((regval == inst) && (index == inst)) { + found_port = 1; + break; + } + } + + if (!found_port) { + ctx_dbg(1, ctx, "No port node matches csi2 port:%d\n", + inst); + goto cleanup_exit; + } + + ctx_dbg(3, ctx, "Scanning sub-device for csi2 port: %d\n", + inst); + + ep_node = of_get_next_endpoint(port, ep_node); + if (!ep_node) { + ctx_dbg(3, ctx, "can't get next endpoint\n"); + goto cleanup_exit; + } + + sensor_node = of_graph_get_remote_port_parent(ep_node); + if (!sensor_node) { + ctx_dbg(3, ctx, "can't get remote parent\n"); + goto cleanup_exit; + } + asd->match_type = V4L2_ASYNC_MATCH_OF; + asd->match.of.node = sensor_node; + + remote_ep = of_parse_phandle(ep_node, "remote-endpoint", 0); + if (!remote_ep) { + ctx_dbg(3, ctx, "can't get remote-endpoint\n"); + goto cleanup_exit; + } + v4l2_of_parse_endpoint(remote_ep, endpoint); + + if (endpoint->bus_type != V4L2_MBUS_CSI2) { + ctx_err(ctx, "Port:%d sub-device %s is not a CSI2 device\n", + inst, sensor_node->name); + goto cleanup_exit; + } + + /* Store Virtual Channel number */ + ctx->virtual_channel = endpoint->base.id; + + ctx_dbg(3, ctx, "Port:%d v4l2-endpoint: CSI2\n", inst); + ctx_dbg(3, ctx, "Virtual Channel=%d\n", ctx->virtual_channel); + ctx_dbg(3, ctx, "flags=0x%08x\n", endpoint->bus.mipi_csi2.flags); + ctx_dbg(3, ctx, "clock_lane=%d\n", endpoint->bus.mipi_csi2.clock_lane); + ctx_dbg(3, ctx, "num_data_lanes=%d\n", + endpoint->bus.mipi_csi2.num_data_lanes); + ctx_dbg(3, ctx, "data_lanes= <\n"); + for (lane = 0; lane < endpoint->bus.mipi_csi2.num_data_lanes; lane++) + ctx_dbg(3, ctx, "\t%d\n", + endpoint->bus.mipi_csi2.data_lanes[lane]); + ctx_dbg(3, ctx, "\t>\n"); + + ctx_dbg(1, ctx, "Port: %d found sub-device %s\n", + inst, sensor_node->name); + + ctx->asd_list[0] = asd; + ctx->notifier.subdevs = ctx->asd_list; + ctx->notifier.num_subdevs = 1; + ctx->notifier.bound = cal_async_bound; + ctx->notifier.complete = cal_async_complete; + ret = v4l2_async_notifier_register(&ctx->v4l2_dev, + &ctx->notifier); + if (ret) { + ctx_err(ctx, "Error registering async notifier\n"); + ret = -EINVAL; + } + +cleanup_exit: + if (!remote_ep) + of_node_put(remote_ep); + if (!sensor_node) + of_node_put(sensor_node); + if (!ep_node) + of_node_put(ep_node); + if (!port) + of_node_put(port); + + return ret; +} + +static struct cal_ctx *cal_create_instance(struct cal_dev *dev, int inst) +{ + struct cal_ctx *ctx; + struct v4l2_ctrl_handler *hdl; + int ret; + + ctx = devm_kzalloc(&dev->pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return 0; + + /* save the cal_dev * for future ref */ + ctx->dev = dev; + + snprintf(ctx->v4l2_dev.name, sizeof(ctx->v4l2_dev.name), + "%s-%03d", CAL_MODULE_NAME, inst); + ret = v4l2_device_register(&dev->pdev->dev, &ctx->v4l2_dev); + if (ret) + goto err_exit; + + hdl = &ctx->ctrl_handler; + ret = v4l2_ctrl_handler_init(hdl, 11); + if (ret) { + ctx_err(ctx, "Failed to init ctrl handler\n"); + goto unreg_dev; + } + ctx->v4l2_dev.ctrl_handler = hdl; + + /* Make sure Camera Core H/W register area is available */ + ctx->cc = dev->cc[inst]; + + /* Store the instance id */ + ctx->csi2_port = inst + 1; + + ret = of_cal_create_instance(ctx, inst); + if (ret) { + ret = -EINVAL; + goto free_hdl; + } + return ctx; + +free_hdl: + v4l2_ctrl_handler_free(hdl); +unreg_dev: + v4l2_device_unregister(&ctx->v4l2_dev); +err_exit: + return 0; +} + +static int cal_probe(struct platform_device *pdev) +{ + struct cal_dev *dev; + int ret; + int irq; + + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + /* set pseudo v4l2 device name so we can use v4l2_printk */ + strlcpy(dev->v4l2_dev.name, CAL_MODULE_NAME, + sizeof(dev->v4l2_dev.name)); + + /* save pdev pointer */ + dev->pdev = pdev; + + dev->res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "cal_top"); + dev->base = devm_ioremap_resource(&pdev->dev, dev->res); + if (IS_ERR(dev->base)) + return PTR_ERR(dev->base); + + cal_dbg(1, dev, "ioresource %s at %pa - %pa\n", + dev->res->name, &dev->res->start, &dev->res->end); + + irq = platform_get_irq(pdev, 0); + cal_dbg(1, dev, "got irq# %d\n", irq); + ret = devm_request_irq(&pdev->dev, irq, cal_irq, 0, CAL_MODULE_NAME, + dev); + if (ret) + return ret; + + platform_set_drvdata(pdev, dev); + + dev->cm = cm_create(dev); + if (IS_ERR(dev->cm)) + return PTR_ERR(dev->cm); + + dev->cc[0] = cc_create(dev, 0); + if (IS_ERR(dev->cc[0])) + return PTR_ERR(dev->cc[0]); + + dev->cc[1] = cc_create(dev, 1); + if (IS_ERR(dev->cc[1])) + return PTR_ERR(dev->cc[1]); + + dev->ctx[0] = NULL; + dev->ctx[1] = NULL; + + dev->ctx[0] = cal_create_instance(dev, 0); + dev->ctx[1] = cal_create_instance(dev, 1); + if (!dev->ctx[0] && !dev->ctx[1]) { + cal_err(dev, "Neither port is configured, no point in staying up\n"); + return -ENODEV; + } + + pm_runtime_enable(&pdev->dev); + + ret = cal_runtime_get(dev); + if (ret) + goto runtime_disable; + + /* Just check we can actually access the module */ + cal_get_hwinfo(dev); + + cal_runtime_put(dev); + + return 0; + +runtime_disable: + pm_runtime_disable(&pdev->dev); + return ret; +} + +static int cal_remove(struct platform_device *pdev) +{ + struct cal_dev *dev = + (struct cal_dev *)platform_get_drvdata(pdev); + struct cal_ctx *ctx; + int i; + + cal_dbg(1, dev, "Removing %s\n", CAL_MODULE_NAME); + + cal_runtime_get(dev); + + for (i = 0; i < CAL_NUM_CONTEXT; i++) { + ctx = dev->ctx[i]; + if (ctx) { + ctx_dbg(1, ctx, "unregistering %s\n", + video_device_node_name(&ctx->vdev)); + camerarx_phy_disable(ctx); + v4l2_async_notifier_unregister(&ctx->notifier); + vb2_dma_contig_cleanup_ctx(ctx->alloc_ctx); + v4l2_ctrl_handler_free(&ctx->ctrl_handler); + v4l2_device_unregister(&ctx->v4l2_dev); + video_unregister_device(&ctx->vdev); + } + } + + cal_runtime_put(dev); + pm_runtime_disable(&pdev->dev); + + return 0; +} + +#if defined(CONFIG_OF) +static const struct of_device_id cal_of_match[] = { + { .compatible = "ti,dra72-cal", }, + {}, +}; +MODULE_DEVICE_TABLE(of, cal_of_match); +#endif + +static struct platform_driver cal_pdrv = { + .probe = cal_probe, + .remove = cal_remove, + .driver = { + .name = CAL_MODULE_NAME, + .of_match_table = of_match_ptr(cal_of_match), + }, +}; + +module_platform_driver(cal_pdrv); diff --git a/drivers/media/platform/ti-vpe/cal_regs.h b/drivers/media/platform/ti-vpe/cal_regs.h new file mode 100644 index 000000000000..82b3dcf87128 --- /dev/null +++ b/drivers/media/platform/ti-vpe/cal_regs.h @@ -0,0 +1,479 @@ +/* + * TI CAL camera interface driver + * + * Copyright (c) 2015 Texas Instruments Inc. + * + * Benoit Parrot, + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#ifndef __TI_CAL_REGS_H +#define __TI_CAL_REGS_H + +#define CAL_NUM_CSI2_PORTS 2 + +/* CAL register offsets */ + +#define CAL_HL_REVISION 0x0000 +#define CAL_HL_HWINFO 0x0004 +#define CAL_HL_SYSCONFIG 0x0010 +#define CAL_HL_IRQ_EOI 0x001c +#define CAL_HL_IRQSTATUS_RAW(m) (0x20U + ((m-1) * 0x10U)) +#define CAL_HL_IRQSTATUS(m) (0x24U + ((m-1) * 0x10U)) +#define CAL_HL_IRQENABLE_SET(m) (0x28U + ((m-1) * 0x10U)) +#define CAL_HL_IRQENABLE_CLR(m) (0x2cU + ((m-1) * 0x10U)) +#define CAL_PIX_PROC(m) (0xc0U + ((m-1) * 0x4U)) +#define CAL_CTRL 0x100 +#define CAL_CTRL1 0x104 +#define CAL_LINE_NUMBER_EVT 0x108 +#define CAL_VPORT_CTRL1 0x120 +#define CAL_VPORT_CTRL2 0x124 +#define CAL_BYS_CTRL1 0x130 +#define CAL_BYS_CTRL2 0x134 +#define CAL_RD_DMA_CTRL 0x140 +#define CAL_RD_DMA_PIX_ADDR 0x144 +#define CAL_RD_DMA_PIX_OFST 0x148 +#define CAL_RD_DMA_XSIZE 0x14c +#define CAL_RD_DMA_YSIZE 0x150 +#define CAL_RD_DMA_INIT_ADDR 0x154 +#define CAL_RD_DMA_INIT_OFST 0x168 +#define CAL_RD_DMA_CTRL2 0x16c +#define CAL_WR_DMA_CTRL(m) (0x200U + ((m-1) * 0x10U)) +#define CAL_WR_DMA_ADDR(m) (0x204U + ((m-1) * 0x10U)) +#define CAL_WR_DMA_OFST(m) (0x208U + ((m-1) * 0x10U)) +#define CAL_WR_DMA_XSIZE(m) (0x20cU + ((m-1) * 0x10U)) +#define CAL_CSI2_PPI_CTRL(m) (0x300U + ((m-1) * 0x80U)) +#define CAL_CSI2_COMPLEXIO_CFG(m) (0x304U + ((m-1) * 0x80U)) +#define CAL_CSI2_COMPLEXIO_IRQSTATUS(m) (0x308U + ((m-1) * 0x80U)) +#define CAL_CSI2_SHORT_PACKET(m) (0x30cU + ((m-1) * 0x80U)) +#define CAL_CSI2_COMPLEXIO_IRQENABLE(m) (0x310U + ((m-1) * 0x80U)) +#define CAL_CSI2_TIMING(m) (0x314U + ((m-1) * 0x80U)) +#define CAL_CSI2_VC_IRQENABLE(m) (0x318U + ((m-1) * 0x80U)) +#define CAL_CSI2_VC_IRQSTATUS(m) (0x328U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX0(m) (0x330U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX1(m) (0x334U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX2(m) (0x338U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX3(m) (0x33cU + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX4(m) (0x340U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX5(m) (0x344U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX6(m) (0x348U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX7(m) (0x34cU + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS0(m) (0x350U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS1(m) (0x354U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS2(m) (0x358U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS3(m) (0x35cU + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS4(m) (0x360U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS5(m) (0x364U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS6(m) (0x368U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS7(m) (0x36cU + ((m-1) * 0x80U)) + +/* CAL CSI2 PHY register offsets */ +#define CAL_CSI2_PHY_REG0 0x000 +#define CAL_CSI2_PHY_REG1 0x004 +#define CAL_CSI2_PHY_REG2 0x008 + +/* CAL Control Module Core Camerrx Control register offsets */ +#define CM_CTRL_CORE_CAMERRX_CONTROL 0x000 + +/********************************************************************* +* Generic value used in various field below +*********************************************************************/ + +#define CAL_GEN_DISABLE 0 +#define CAL_GEN_ENABLE 1 +#define CAL_GEN_FALSE 0 +#define CAL_GEN_TRUE 1 + +/********************************************************************* +* Field Definition Macros +*********************************************************************/ + +#define CAL_HL_REVISION_MINOR_MASK GENMASK(5, 0) +#define CAL_HL_REVISION_CUSTOM_MASK GENMASK(7, 6) +#define CAL_HL_REVISION_MAJOR_MASK GENMASK(10, 8) +#define CAL_HL_REVISION_RTL_MASK GENMASK(15, 11) +#define CAL_HL_REVISION_FUNC_MASK GENMASK(27, 16) +#define CAL_HL_REVISION_SCHEME_MASK GENMASK(31, 30) +#define CAL_HL_REVISION_SCHEME_H08 1 +#define CAL_HL_REVISION_SCHEME_LEGACY 0 + +#define CAL_HL_HWINFO_WFIFO_MASK GENMASK(3, 0) +#define CAL_HL_HWINFO_RFIFO_MASK GENMASK(7, 4) +#define CAL_HL_HWINFO_PCTX_MASK GENMASK(12, 8) +#define CAL_HL_HWINFO_WCTX_MASK GENMASK(18, 13) +#define CAL_HL_HWINFO_VFIFO_MASK GENMASK(22, 19) +#define CAL_HL_HWINFO_NCPORT_MASK GENMASK(27, 23) +#define CAL_HL_HWINFO_NPPI_CTXS0_MASK GENMASK(29, 28) +#define CAL_HL_HWINFO_NPPI_CTXS1_MASK GENMASK(31, 30) +#define CAL_HL_HWINFO_NPPI_CONTEXTS_ZERO 0 +#define CAL_HL_HWINFO_NPPI_CONTEXTS_FOUR 1 +#define CAL_HL_HWINFO_NPPI_CONTEXTS_EIGHT 2 +#define CAL_HL_HWINFO_NPPI_CONTEXTS_RESERVED 3 + +#define CAL_HL_SYSCONFIG_SOFTRESET_MASK BIT_MASK(0) +#define CAL_HL_SYSCONFIG_SOFTRESET_DONE 0x0 +#define CAL_HL_SYSCONFIG_SOFTRESET_PENDING 0x1 +#define CAL_HL_SYSCONFIG_SOFTRESET_NOACTION 0x0 +#define CAL_HL_SYSCONFIG_SOFTRESET_RESET 0x1 +#define CAL_HL_SYSCONFIG_IDLE_MASK GENMASK(3, 2) +#define CAL_HL_SYSCONFIG_IDLEMODE_FORCE 0 +#define CAL_HL_SYSCONFIG_IDLEMODE_NO 1 +#define CAL_HL_SYSCONFIG_IDLEMODE_SMART1 2 +#define CAL_HL_SYSCONFIG_IDLEMODE_SMART2 3 + +#define CAL_HL_IRQ_EOI_LINE_NUMBER_MASK BIT_MASK(0) +#define CAL_HL_IRQ_EOI_LINE_NUMBER_READ0 0 +#define CAL_HL_IRQ_EOI_LINE_NUMBER_EOI0 0 + +#define CAL_HL_IRQ_MASK(m) BIT_MASK(m-1) +#define CAL_HL_IRQ_NOACTION 0x0 +#define CAL_HL_IRQ_ENABLE 0x1 +#define CAL_HL_IRQ_CLEAR 0x1 +#define CAL_HL_IRQ_DISABLED 0x0 +#define CAL_HL_IRQ_ENABLED 0x1 +#define CAL_HL_IRQ_PENDING 0x1 + +#define CAL_PIX_PROC_EN_MASK BIT_MASK(0) +#define CAL_PIX_PROC_EXTRACT_MASK GENMASK(4, 1) +#define CAL_PIX_PROC_EXTRACT_B6 0x0 +#define CAL_PIX_PROC_EXTRACT_B7 0x1 +#define CAL_PIX_PROC_EXTRACT_B8 0x2 +#define CAL_PIX_PROC_EXTRACT_B10 0x3 +#define CAL_PIX_PROC_EXTRACT_B10_MIPI 0x4 +#define CAL_PIX_PROC_EXTRACT_B12 0x5 +#define CAL_PIX_PROC_EXTRACT_B12_MIPI 0x6 +#define CAL_PIX_PROC_EXTRACT_B14 0x7 +#define CAL_PIX_PROC_EXTRACT_B14_MIPI 0x8 +#define CAL_PIX_PROC_EXTRACT_B16_BE 0x9 +#define CAL_PIX_PROC_EXTRACT_B16_LE 0xa +#define CAL_PIX_PROC_DPCMD_MASK GENMASK(9, 5) +#define CAL_PIX_PROC_DPCMD_BYPASS 0x0 +#define CAL_PIX_PROC_DPCMD_DPCM_10_8_1 0x2 +#define CAL_PIX_PROC_DPCMD_DPCM_12_8_1 0x8 +#define CAL_PIX_PROC_DPCMD_DPCM_10_7_1 0x4 +#define CAL_PIX_PROC_DPCMD_DPCM_10_7_2 0x5 +#define CAL_PIX_PROC_DPCMD_DPCM_10_6_1 0x6 +#define CAL_PIX_PROC_DPCMD_DPCM_10_6_2 0x7 +#define CAL_PIX_PROC_DPCMD_DPCM_12_7_1 0xa +#define CAL_PIX_PROC_DPCMD_DPCM_12_6_1 0xc +#define CAL_PIX_PROC_DPCMD_DPCM_14_10 0xe +#define CAL_PIX_PROC_DPCMD_DPCM_14_8_1 0x10 +#define CAL_PIX_PROC_DPCMD_DPCM_16_12_1 0x12 +#define CAL_PIX_PROC_DPCMD_DPCM_16_10_1 0x14 +#define CAL_PIX_PROC_DPCMD_DPCM_16_8_1 0x16 +#define CAL_PIX_PROC_DPCME_MASK GENMASK(15, 11) +#define CAL_PIX_PROC_DPCME_BYPASS 0x0 +#define CAL_PIX_PROC_DPCME_DPCM_10_8_1 0x2 +#define CAL_PIX_PROC_DPCME_DPCM_12_8_1 0x8 +#define CAL_PIX_PROC_DPCME_DPCM_14_10 0xe +#define CAL_PIX_PROC_DPCME_DPCM_14_8_1 0x10 +#define CAL_PIX_PROC_DPCME_DPCM_16_12_1 0x12 +#define CAL_PIX_PROC_DPCME_DPCM_16_10_1 0x14 +#define CAL_PIX_PROC_DPCME_DPCM_16_8_1 0x16 +#define CAL_PIX_PROC_PACK_MASK GENMASK(18, 16) +#define CAL_PIX_PROC_PACK_B8 0x0 +#define CAL_PIX_PROC_PACK_B10_MIPI 0x2 +#define CAL_PIX_PROC_PACK_B12 0x3 +#define CAL_PIX_PROC_PACK_B12_MIPI 0x4 +#define CAL_PIX_PROC_PACK_B16 0x5 +#define CAL_PIX_PROC_PACK_ARGB 0x6 +#define CAL_PIX_PROC_CPORT_MASK GENMASK(23, 19) + +#define CAL_CTRL_POSTED_WRITES_MASK BIT_MASK(0) +#define CAL_CTRL_POSTED_WRITES_NONPOSTED 0 +#define CAL_CTRL_POSTED_WRITES 1 +#define CAL_CTRL_TAGCNT_MASK GENMASK(4, 1) +#define CAL_CTRL_BURSTSIZE_MASK GENMASK(6, 5) +#define CAL_CTRL_BURSTSIZE_BURST16 0x0 +#define CAL_CTRL_BURSTSIZE_BURST32 0x1 +#define CAL_CTRL_BURSTSIZE_BURST64 0x2 +#define CAL_CTRL_BURSTSIZE_BURST128 0x3 +#define CAL_CTRL_LL_FORCE_STATE_MASK GENMASK(12, 7) +#define CAL_CTRL_MFLAGL_MASK GENMASK(20, 13) +#define CAL_CTRL_PWRSCPCLK_MASK BIT_MASK(21) +#define CAL_CTRL_PWRSCPCLK_AUTO 0 +#define CAL_CTRL_PWRSCPCLK_FORCE 1 +#define CAL_CTRL_RD_DMA_STALL_MASK BIT_MASK(22) +#define CAL_CTRL_MFLAGH_MASK GENMASK(31, 24) + +#define CAL_CTRL1_PPI_GROUPING_MASK GENMASK(1, 0) +#define CAL_CTRL1_PPI_GROUPING_DISABLED 0 +#define CAL_CTRL1_PPI_GROUPING_RESERVED 1 +#define CAL_CTRL1_PPI_GROUPING_0 2 +#define CAL_CTRL1_PPI_GROUPING_1 3 +#define CAL_CTRL1_INTERLEAVE01_MASK GENMASK(3, 2) +#define CAL_CTRL1_INTERLEAVE01_DISABLED 0 +#define CAL_CTRL1_INTERLEAVE01_PIX1 1 +#define CAL_CTRL1_INTERLEAVE01_PIX4 2 +#define CAL_CTRL1_INTERLEAVE01_RESERVED 3 +#define CAL_CTRL1_INTERLEAVE23_MASK GENMASK(5, 4) +#define CAL_CTRL1_INTERLEAVE23_DISABLED 0 +#define CAL_CTRL1_INTERLEAVE23_PIX1 1 +#define CAL_CTRL1_INTERLEAVE23_PIX4 2 +#define CAL_CTRL1_INTERLEAVE23_RESERVED 3 + +#define CAL_LINE_NUMBER_EVT_CPORT_MASK GENMASK(4, 0) +#define CAL_LINE_NUMBER_EVT_MASK GENMASK(29, 16) + +#define CAL_VPORT_CTRL1_PCLK_MASK GENMASK(16, 0) +#define CAL_VPORT_CTRL1_XBLK_MASK GENMASK(24, 17) +#define CAL_VPORT_CTRL1_YBLK_MASK GENMASK(30, 25) +#define CAL_VPORT_CTRL1_WIDTH_MASK BIT_MASK(31) +#define CAL_VPORT_CTRL1_WIDTH_ONE 0 +#define CAL_VPORT_CTRL1_WIDTH_TWO 1 + +#define CAL_VPORT_CTRL2_CPORT_MASK GENMASK(4, 0) +#define CAL_VPORT_CTRL2_FREERUNNING_MASK BIT_MASK(15) +#define CAL_VPORT_CTRL2_FREERUNNING_GATED 0 +#define CAL_VPORT_CTRL2_FREERUNNING_FREE 1 +#define CAL_VPORT_CTRL2_FS_RESETS_MASK BIT_MASK(16) +#define CAL_VPORT_CTRL2_FS_RESETS_NO 0 +#define CAL_VPORT_CTRL2_FS_RESETS_YES 1 +#define CAL_VPORT_CTRL2_FSM_RESET_MASK BIT_MASK(17) +#define CAL_VPORT_CTRL2_FSM_RESET_NOEFFECT 0 +#define CAL_VPORT_CTRL2_FSM_RESET 1 +#define CAL_VPORT_CTRL2_RDY_THR_MASK GENMASK(31, 18) + +#define CAL_BYS_CTRL1_PCLK_MASK GENMASK(16, 0) +#define CAL_BYS_CTRL1_XBLK_MASK GENMASK(24, 17) +#define CAL_BYS_CTRL1_YBLK_MASK GENMASK(30, 25) +#define CAL_BYS_CTRL1_BYSINEN_MASK BIT_MASK(31) + +#define CAL_BYS_CTRL2_CPORTIN_MASK GENMASK(4, 0) +#define CAL_BYS_CTRL2_CPORTOUT_MASK GENMASK(9, 5) +#define CAL_BYS_CTRL2_DUPLICATEDDATA_MASK BIT_MASK(10) +#define CAL_BYS_CTRL2_DUPLICATEDDATA_NO 0 +#define CAL_BYS_CTRL2_DUPLICATEDDATA_YES 1 +#define CAL_BYS_CTRL2_FREERUNNING_MASK BIT_MASK(11) +#define CAL_BYS_CTRL2_FREERUNNING_NO 0 +#define CAL_BYS_CTRL2_FREERUNNING_YES 1 + +#define CAL_RD_DMA_CTRL_GO_MASK BIT_MASK(0) +#define CAL_RD_DMA_CTRL_GO_DIS 0 +#define CAL_RD_DMA_CTRL_GO_EN 1 +#define CAL_RD_DMA_CTRL_GO_IDLE 0 +#define CAL_RD_DMA_CTRL_GO_BUSY 1 +#define CAL_RD_DMA_CTRL_INIT_MASK BIT_MASK(1) +#define CAL_RD_DMA_CTRL_BW_LIMITER_MASK GENMASK(10, 2) +#define CAL_RD_DMA_CTRL_OCP_TAG_CNT_MASK GENMASK(14, 11) +#define CAL_RD_DMA_CTRL_PCLK_MASK GENMASK(31, 15) + +#define CAL_RD_DMA_PIX_ADDR_MASK GENMASK(31, 3) + +#define CAL_RD_DMA_PIX_OFST_MASK GENMASK(31, 4) + +#define CAL_RD_DMA_XSIZE_MASK GENMASK(31, 19) + +#define CAL_RD_DMA_YSIZE_MASK GENMASK(29, 16) + +#define CAL_RD_DMA_INIT_ADDR_MASK GENMASK(31, 3) + +#define CAL_RD_DMA_INIT_OFST_MASK GENMASK(31, 3) + +#define CAL_RD_DMA_CTRL2_CIRC_MODE_MASK GENMASK(2, 0) +#define CAL_RD_DMA_CTRL2_CIRC_MODE_DIS 0 +#define CAL_RD_DMA_CTRL2_CIRC_MODE_ONE 1 +#define CAL_RD_DMA_CTRL2_CIRC_MODE_FOUR 2 +#define CAL_RD_DMA_CTRL2_CIRC_MODE_SIXTEEN 3 +#define CAL_RD_DMA_CTRL2_CIRC_MODE_SIXTYFOUR 4 +#define CAL_RD_DMA_CTRL2_CIRC_MODE_RESERVED 5 +#define CAL_RD_DMA_CTRL2_ICM_CSTART_MASK BIT_MASK(3) +#define CAL_RD_DMA_CTRL2_PATTERN_MASK GENMASK(5, 4) +#define CAL_RD_DMA_CTRL2_PATTERN_LINEAR 0 +#define CAL_RD_DMA_CTRL2_PATTERN_YUV420 1 +#define CAL_RD_DMA_CTRL2_PATTERN_RD2SKIP2 2 +#define CAL_RD_DMA_CTRL2_PATTERN_RD2SKIP4 3 +#define CAL_RD_DMA_CTRL2_BYSOUT_LE_WAIT_MASK BIT_MASK(6) +#define CAL_RD_DMA_CTRL2_BYSOUT_LE_WAIT_FREERUNNING 0 +#define CAL_RD_DMA_CTRL2_BYSOUT_LE_WAIT_WAITFORBYSOUT 1 +#define CAL_RD_DMA_CTRL2_CIRC_SIZE_MASK GENMASK(29, 16) + +#define CAL_WR_DMA_CTRL_MODE_MASK GENMASK(2, 0) +#define CAL_WR_DMA_CTRL_MODE_DIS 0 +#define CAL_WR_DMA_CTRL_MODE_SHD 1 +#define CAL_WR_DMA_CTRL_MODE_CNT 2 +#define CAL_WR_DMA_CTRL_MODE_CNT_INIT 3 +#define CAL_WR_DMA_CTRL_MODE_CONST 4 +#define CAL_WR_DMA_CTRL_MODE_RESERVED 5 +#define CAL_WR_DMA_CTRL_PATTERN_MASK GENMASK(4, 3) +#define CAL_WR_DMA_CTRL_PATTERN_LINEAR 0 +#define CAL_WR_DMA_CTRL_PATTERN_WR2SKIP2 2 +#define CAL_WR_DMA_CTRL_PATTERN_WR2SKIP4 3 +#define CAL_WR_DMA_CTRL_PATTERN_RESERVED 1 +#define CAL_WR_DMA_CTRL_ICM_PSTART_MASK BIT_MASK(5) +#define CAL_WR_DMA_CTRL_DTAG_MASK GENMASK(8, 6) +#define CAL_WR_DMA_CTRL_DTAG_ATT_HDR 0 +#define CAL_WR_DMA_CTRL_DTAG_ATT_DAT 1 +#define CAL_WR_DMA_CTRL_DTAG 2 +#define CAL_WR_DMA_CTRL_DTAG_PIX_HDR 3 +#define CAL_WR_DMA_CTRL_DTAG_PIX_DAT 4 +#define CAL_WR_DMA_CTRL_DTAG_D5 5 +#define CAL_WR_DMA_CTRL_DTAG_D6 6 +#define CAL_WR_DMA_CTRL_DTAG_D7 7 +#define CAL_WR_DMA_CTRL_CPORT_MASK GENMASK(13, 9) +#define CAL_WR_DMA_CTRL_STALL_RD_MASK BIT_MASK(14) +#define CAL_WR_DMA_CTRL_YSIZE_MASK GENMASK(31, 18) + +#define CAL_WR_DMA_ADDR_MASK GENMASK(31, 4) + +#define CAL_WR_DMA_OFST_MASK GENMASK(18, 4) +#define CAL_WR_DMA_OFST_CIRC_MODE_MASK GENMASK(23, 22) +#define CAL_WR_DMA_OFST_CIRC_MODE_ONE 1 +#define CAL_WR_DMA_OFST_CIRC_MODE_FOUR 2 +#define CAL_WR_DMA_OFST_CIRC_MODE_SIXTYFOUR 3 +#define CAL_WR_DMA_OFST_CIRC_MODE_DISABLED 0 +#define CAL_WR_DMA_OFST_CIRC_SIZE_MASK GENMASK(31, 24) + +#define CAL_WR_DMA_XSIZE_XSKIP_MASK GENMASK(15, 3) +#define CAL_WR_DMA_XSIZE_MASK GENMASK(31, 19) + +#define CAL_CSI2_PPI_CTRL_IF_EN_MASK BIT_MASK(0) +#define CAL_CSI2_PPI_CTRL_ECC_EN_MASK BIT_MASK(2) +#define CAL_CSI2_PPI_CTRL_FRAME_MASK BIT_MASK(3) +#define CAL_CSI2_PPI_CTRL_FRAME_IMMEDIATE 0 +#define CAL_CSI2_PPI_CTRL_FRAME 1 + +#define CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK GENMASK(2, 0) +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_5 5 +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_4 4 +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_3 3 +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_2 2 +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_1 1 +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_NOT_USED 0 +#define CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK BIT_MASK(3) +#define CAL_CSI2_COMPLEXIO_CFG_POL_PLUSMINUS 0 +#define CAL_CSI2_COMPLEXIO_CFG_POL_MINUSPLUS 1 +#define CAL_CSI2_COMPLEXIO_CFG_DATA1_POSITION_MASK GENMASK(6, 4) +#define CAL_CSI2_COMPLEXIO_CFG_DATA1_POL_MASK BIT_MASK(7) +#define CAL_CSI2_COMPLEXIO_CFG_DATA2_POSITION_MASK GENMASK(10, 8) +#define CAL_CSI2_COMPLEXIO_CFG_DATA2_POL_MASK BIT_MASK(11) +#define CAL_CSI2_COMPLEXIO_CFG_DATA3_POSITION_MASK GENMASK(14, 12) +#define CAL_CSI2_COMPLEXIO_CFG_DATA3_POL_MASK BIT_MASK(15) +#define CAL_CSI2_COMPLEXIO_CFG_DATA4_POSITION_MASK GENMASK(18, 16) +#define CAL_CSI2_COMPLEXIO_CFG_DATA4_POL_MASK BIT_MASK(19) +#define CAL_CSI2_COMPLEXIO_CFG_PWR_AUTO_MASK BIT_MASK(24) +#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK GENMASK(26, 25) +#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_OFF 0 +#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_ON 1 +#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_ULP 2 +#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK GENMASK(28, 27) +#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_OFF 0 +#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON 1 +#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ULP 2 +#define CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK BIT_MASK(29) +#define CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED 1 +#define CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETONGOING 0 +#define CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK BIT_MASK(30) +#define CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL 0 +#define CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL 1 + +#define CAL_CSI2_SHORT_PACKET_MASK GENMASK(23, 0) + +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTHS1_MASK BIT_MASK(0) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTHS2_MASK BIT_MASK(1) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTHS3_MASK BIT_MASK(2) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTHS4_MASK BIT_MASK(3) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTHS5_MASK BIT_MASK(4) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS1_MASK BIT_MASK(5) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS2_MASK BIT_MASK(6) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS3_MASK BIT_MASK(7) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS4_MASK BIT_MASK(8) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS5_MASK BIT_MASK(9) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRESC1_MASK BIT_MASK(10) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRESC2_MASK BIT_MASK(11) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRESC3_MASK BIT_MASK(12) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRESC4_MASK BIT_MASK(13) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRESC5_MASK BIT_MASK(14) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL1_MASK BIT_MASK(15) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL2_MASK BIT_MASK(16) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL3_MASK BIT_MASK(17) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL4_MASK BIT_MASK(18) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL5_MASK BIT_MASK(19) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM1_MASK BIT_MASK(20) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM2_MASK BIT_MASK(21) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM3_MASK BIT_MASK(22) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM4_MASK BIT_MASK(23) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM5_MASK BIT_MASK(24) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEALLULPMENTER_MASK BIT_MASK(25) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEALLULPMEXIT_MASK BIT_MASK(26) +#define CAL_CSI2_COMPLEXIO_IRQ_FIFO_OVR_MASK BIT_MASK(27) +#define CAL_CSI2_COMPLEXIO_IRQ_SHORT_PACKET_MASK BIT_MASK(28) +#define CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK BIT_MASK(30) + +#define CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK GENMASK(12, 0) +#define CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK BIT_MASK(13) +#define CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK BIT_MASK(14) +#define CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK BIT_MASK(15) + +#define CAL_CSI2_VC_IRQ_FS_IRQ_0_MASK BIT_MASK(0) +#define CAL_CSI2_VC_IRQ_FE_IRQ_0_MASK BIT_MASK(1) +#define CAL_CSI2_VC_IRQ_LS_IRQ_0_MASK BIT_MASK(2) +#define CAL_CSI2_VC_IRQ_LE_IRQ_0_MASK BIT_MASK(3) +#define CAL_CSI2_VC_IRQ_CS_IRQ_0_MASK BIT_MASK(4) +#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_0_MASK BIT_MASK(5) +#define CAL_CSI2_VC_IRQ_FS_IRQ_1_MASK BIT_MASK(8) +#define CAL_CSI2_VC_IRQ_FE_IRQ_1_MASK BIT_MASK(9) +#define CAL_CSI2_VC_IRQ_LS_IRQ_1_MASK BIT_MASK(10) +#define CAL_CSI2_VC_IRQ_LE_IRQ_1_MASK BIT_MASK(11) +#define CAL_CSI2_VC_IRQ_CS_IRQ_1_MASK BIT_MASK(12) +#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_1_MASK BIT_MASK(13) +#define CAL_CSI2_VC_IRQ_FS_IRQ_2_MASK BIT_MASK(16) +#define CAL_CSI2_VC_IRQ_FE_IRQ_2_MASK BIT_MASK(17) +#define CAL_CSI2_VC_IRQ_LS_IRQ_2_MASK BIT_MASK(18) +#define CAL_CSI2_VC_IRQ_LE_IRQ_2_MASK BIT_MASK(19) +#define CAL_CSI2_VC_IRQ_CS_IRQ_2_MASK BIT_MASK(20) +#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_2_MASK BIT_MASK(21) +#define CAL_CSI2_VC_IRQ_FS_IRQ_3_MASK BIT_MASK(24) +#define CAL_CSI2_VC_IRQ_FE_IRQ_3_MASK BIT_MASK(25) +#define CAL_CSI2_VC_IRQ_LS_IRQ_3_MASK BIT_MASK(26) +#define CAL_CSI2_VC_IRQ_LE_IRQ_3_MASK BIT_MASK(27) +#define CAL_CSI2_VC_IRQ_CS_IRQ_3_MASK BIT_MASK(28) +#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_3_MASK BIT_MASK(29) + +#define CAL_CSI2_CTX_DT_MASK GENMASK(5, 0) +#define CAL_CSI2_CTX_VC_MASK GENMASK(7, 6) +#define CAL_CSI2_CTX_CPORT_MASK GENMASK(12, 8) +#define CAL_CSI2_CTX_ATT_MASK BIT_MASK(13) +#define CAL_CSI2_CTX_ATT_PIX 0 +#define CAL_CSI2_CTX_ATT 1 +#define CAL_CSI2_CTX_PACK_MODE_MASK BIT_MASK(14) +#define CAL_CSI2_CTX_PACK_MODE_LINE 0 +#define CAL_CSI2_CTX_PACK_MODE_FRAME 1 +#define CAL_CSI2_CTX_LINES_MASK GENMASK(29, 16) + +#define CAL_CSI2_STATUS_FRAME_MASK GENMASK(15, 0) + +#define CAL_CSI2_PHY_REG0_THS_SETTLE_MASK GENMASK(7, 0) +#define CAL_CSI2_PHY_REG0_THS_TERM_MASK GENMASK(15, 8) +#define CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK BIT_MASK(24) +#define CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE 1 +#define CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_ENABLE 0 + +#define CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK GENMASK(7, 0) +#define CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK GENMASK(9, 8) +#define CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK GENMASK(17, 10) +#define CAL_CSI2_PHY_REG1_TCLK_TERM_MASK GENMASK(24, 18) +#define CAL_CSI2_PHY_REG1_CLOCK_MISS_DETECTOR_STATUS_MASK BIT_MASK(25) +#define CAL_CSI2_PHY_REG1_CLOCK_MISS_DETECTOR_STATUS_ERROR 1 +#define CAL_CSI2_PHY_REG1_CLOCK_MISS_DETECTOR_STATUS_SUCCESS 0 +#define CAL_CSI2_PHY_REG1_RESET_DONE_STATUS_MASK GENMASK(29, 28) + +#define CAL_CSI2_PHY_REG2_CCP2_SYNC_PATTERN_MASK GENMASK(23, 0) +#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC3_MASK GENMASK(25, 24) +#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC2_MASK GENMASK(27, 26) +#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC1_MASK GENMASK(29, 28) +#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC0_MASK GENMASK(31, 30) + +#define CM_CAMERRX_CTRL_CSI1_CTRLCLKEN_MASK BIT_MASK(0) +#define CM_CAMERRX_CTRL_CSI1_CAMMODE_MASK GENMASK(2, 1) +#define CM_CAMERRX_CTRL_CSI1_LANEENABLE_MASK GENMASK(4, 3) +#define CM_CAMERRX_CTRL_CSI1_MODE_MASK BIT_MASK(5) +#define CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_MASK BIT_MASK(10) +#define CM_CAMERRX_CTRL_CSI0_CAMMODE_MASK GENMASK(12, 11) +#define CM_CAMERRX_CTRL_CSI0_LANEENABLE_MASK GENMASK(16, 13) +#define CM_CAMERRX_CTRL_CSI0_MODE_MASK BIT_MASK(17) + +#endif -- cgit v1.2.3 From 3f1321cbaa1f2221be7444b7fab0905a31bdfd9f Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:43:29 -0200 Subject: [media] media: rc: nuvoton-cir: improve nvt_hw_detect Check for the case that no Nuvoton chip is found on either EFM port. Also move the position of nvt_efm_disable to reduce the time the EFM ports are locked. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 17 +++++++++++++---- drivers/media/rc/nuvoton-cir.h | 3 ++- 2 files changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 5790ee46a38d..f587a727df2e 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -291,7 +291,7 @@ static inline const char *nvt_find_chip(struct nvt_dev *nvt, int id) /* detect hardware features */ -static void nvt_hw_detect(struct nvt_dev *nvt) +static int nvt_hw_detect(struct nvt_dev *nvt) { const char *chip_name; int chip_id; @@ -306,10 +306,17 @@ static void nvt_hw_detect(struct nvt_dev *nvt) nvt_efm_enable(nvt); nvt->chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); } - nvt->chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); + nvt_efm_disable(nvt); + chip_id = nvt->chip_major << 8 | nvt->chip_minor; + if (chip_id == NVT_INVALID) { + dev_err(&nvt->pdev->dev, + "No device found on either EFM port\n"); + return -ENODEV; + } + chip_name = nvt_find_chip(nvt, chip_id); /* warn, but still let the driver load, if we don't know this chip */ @@ -322,7 +329,7 @@ static void nvt_hw_detect(struct nvt_dev *nvt) "found %s or compatible: chip id: 0x%02x 0x%02x", chip_name, nvt->chip_major, nvt->chip_minor); - nvt_efm_disable(nvt); + return 0; } static void nvt_cir_ldev_init(struct nvt_dev *nvt) @@ -1057,7 +1064,9 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) init_waitqueue_head(&nvt->tx.queue); - nvt_hw_detect(nvt); + ret = nvt_hw_detect(nvt); + if (ret) + goto exit_free_dev_rdev; /* Initialize CIR & CIR Wake Logical Devices */ nvt_efm_enable(nvt); diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h index 6a3de08a17c0..48c09c7a101c 100644 --- a/drivers/media/rc/nuvoton-cir.h +++ b/drivers/media/rc/nuvoton-cir.h @@ -68,7 +68,8 @@ enum nvt_chip_ver { NVT_W83667HG = 0xa510, NVT_6775F = 0xb470, NVT_6776F = 0xc330, - NVT_6779D = 0xc560 + NVT_6779D = 0xc560, + NVT_INVALID = 0xffff, }; struct nvt_chip { -- cgit v1.2.3 From fb2b0065756a5ed6b6852e663574f9331d47fdec Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:44:36 -0200 Subject: [media] media: rc: nuvoton-cir: add locking to calls of nvt_enable_wake Add locking to nvt_enable_wake calls. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index f587a727df2e..3097ff0eb176 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -1174,16 +1174,16 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) nvt_dbg("%s called", __func__); - /* zero out misc state tracking */ - spin_lock_irqsave(&nvt->nvt_lock, flags); - nvt->study_state = ST_STUDY_NONE; - nvt->wake_state = ST_WAKE_NONE; - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - spin_lock_irqsave(&nvt->tx.lock, flags); nvt->tx.tx_state = ST_TX_NONE; spin_unlock_irqrestore(&nvt->tx.lock, flags); + spin_lock_irqsave(&nvt->nvt_lock, flags); + + /* zero out misc state tracking */ + nvt->study_state = ST_STUDY_NONE; + nvt->wake_state = ST_WAKE_NONE; + /* disable all CIR interrupts */ nvt_cir_reg_write(nvt, 0, CIR_IREN); @@ -1193,6 +1193,8 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) /* make sure wake is enabled */ nvt_enable_wake(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + return 0; } @@ -1211,7 +1213,11 @@ static int nvt_resume(struct pnp_dev *pdev) static void nvt_shutdown(struct pnp_dev *pdev) { struct nvt_dev *nvt = pnp_get_drvdata(pdev); + unsigned long flags; + + spin_lock_irqsave(&nvt->nvt_lock, flags); nvt_enable_wake(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); } static const struct pnp_device_id nvt_ids[] = { -- cgit v1.2.3 From 88205f01fe30590d04c81f09f003af8c2cf6aeaf Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:45:00 -0200 Subject: [media] media: rc: nuvoton-cir: fix wakeup interrupt bits Most likely a copy & paste error. The wakeup interrupt supports less triggering events. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h index 48c09c7a101c..4a5650dffa29 100644 --- a/drivers/media/rc/nuvoton-cir.h +++ b/drivers/media/rc/nuvoton-cir.h @@ -293,10 +293,7 @@ struct nvt_dev { #define CIR_WAKE_IREN_RTR 0x40 #define CIR_WAKE_IREN_PE 0x20 #define CIR_WAKE_IREN_RFO 0x10 -#define CIR_WAKE_IREN_TE 0x08 -#define CIR_WAKE_IREN_TTR 0x04 -#define CIR_WAKE_IREN_TFU 0x02 -#define CIR_WAKE_IREN_GH 0x01 +#define CIR_WAKE_IREN_GH 0x08 /* CIR WAKE FIFOCON settings */ #define CIR_WAKE_FIFOCON_RXFIFOCLR 0x08 -- cgit v1.2.3 From d42fd29769f52c056032bbf1b9b2d1d914fd145a Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:45:51 -0200 Subject: [media] media: rc: nuvoton-cir: fix interrupt handling Only handle an interrupt if at least one combination of event bit and related interrupt bit is set. Previously it was just checked that at least one event bit and at least one interrupt bit are set. This fixes issues like the following which was caused by interrupt sharing: An interrupt intended for nvt_cir_isr was handled by nvt_cir_wake_isr first and because status bit CIR_WAKE_IRSTS_IR_PENDING was set the wake fifo was accidently cleared. This patch also fixes the bug that nvt_cir_wake_isr returned IRQ_HANDLED even if it detected that the (shared) interrupt was meant for another handler. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 3097ff0eb176..291d870e618f 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -825,9 +825,13 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) * 0: CIR_IRSTS_GH - Min Length Detected */ status = nvt_cir_reg_read(nvt, CIR_IRSTS); - if (!status) { + iren = nvt_cir_reg_read(nvt, CIR_IREN); + + /* IRQ may be shared with CIR WAKE, therefore check for each + * status bit whether the related interrupt source is enabled + */ + if (!(status & iren)) { nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__); - nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); return IRQ_NONE; } @@ -835,13 +839,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) nvt_cir_reg_write(nvt, status, CIR_IRSTS); nvt_cir_reg_write(nvt, 0, CIR_IRSTS); - /* Interrupt may be shared with CIR Wake, bail if CIR not enabled */ - iren = nvt_cir_reg_read(nvt, CIR_IREN); - if (!iren) { - nvt_dbg_verbose("%s exiting, CIR not enabled", __func__); - return IRQ_NONE; - } - nvt_cir_log_irqs(status, iren); if (status & CIR_IRSTS_RTR) { @@ -914,7 +911,12 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) nvt_dbg_wake("%s firing", __func__); status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS); - if (!status) + iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); + + /* IRQ may be shared with CIR, therefore check for each + * status bit whether the related interrupt source is enabled + */ + if (!(status & iren)) return IRQ_NONE; if (status & CIR_WAKE_IRSTS_IR_PENDING) @@ -923,13 +925,6 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) nvt_cir_wake_reg_write(nvt, status, CIR_WAKE_IRSTS); nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IRSTS); - /* Interrupt may be shared with CIR, bail if Wake not enabled */ - iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); - if (!iren) { - nvt_dbg_wake("%s exiting, wake not enabled", __func__); - return IRQ_HANDLED; - } - if ((status & CIR_WAKE_IRSTS_PE) && (nvt->wake_state == ST_WAKE_START)) { while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)) { -- cgit v1.2.3 From e60c1e87c76068c3756369048cd63ed6e55b0155 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:46:29 -0200 Subject: [media] media: rc: nuvoton-cir: improve locking in both interrupt handlers Extend the locking to protect more critical actions like register accesses in the interrupt handlers. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 291d870e618f..d428b4e6e26f 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -727,7 +727,6 @@ static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt) /* copy data from hardware rx fifo into driver buffer */ static void nvt_get_rx_ir_data(struct nvt_dev *nvt) { - unsigned long flags; u8 fifocount, val; unsigned int b_idx; bool overrun = false; @@ -746,8 +745,6 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt) nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount); - spin_lock_irqsave(&nvt->nvt_lock, flags); - b_idx = nvt->pkts; /* This should never happen, but lets check anyway... */ @@ -769,8 +766,6 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt) if (overrun) nvt_handle_rx_fifo_overrun(nvt); - - spin_unlock_irqrestore(&nvt->nvt_lock, flags); } static void nvt_cir_log_irqs(u8 status, u8 iren) @@ -811,6 +806,8 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) nvt_dbg_verbose("%s firing", __func__); + spin_lock_irqsave(&nvt->nvt_lock, flags); + /* * Get IR Status register contents. Write 1 to ack/clear * @@ -831,6 +828,7 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) * status bit whether the related interrupt source is enabled */ if (!(status & iren)) { + spin_unlock_irqrestore(&nvt->nvt_lock, flags); nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__); return IRQ_NONE; } @@ -852,16 +850,14 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) if (nvt_cir_tx_inactive(nvt)) nvt_get_rx_ir_data(nvt); - spin_lock_irqsave(&nvt->nvt_lock, flags); - cur_state = nvt->study_state; - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - if (cur_state == ST_STUDY_NONE) nvt_clear_cir_fifo(nvt); } + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + if (status & CIR_IRSTS_TE) nvt_clear_tx_fifo(nvt); @@ -910,14 +906,18 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) nvt_dbg_wake("%s firing", __func__); + spin_lock_irqsave(&nvt->nvt_lock, flags); + status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS); iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); /* IRQ may be shared with CIR, therefore check for each * status bit whether the related interrupt source is enabled */ - if (!(status & iren)) + if (!(status & iren)) { + spin_unlock_irqrestore(&nvt->nvt_lock, flags); return IRQ_NONE; + } if (status & CIR_WAKE_IRSTS_IR_PENDING) nvt_clear_cir_wake_fifo(nvt); @@ -933,11 +933,11 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) } nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); - spin_lock_irqsave(&nvt->nvt_lock, flags); nvt->wake_state = ST_WAKE_FINISH; - spin_unlock_irqrestore(&nvt->nvt_lock, flags); } + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + nvt_dbg_wake("%s done", __func__); return IRQ_HANDLED; } -- cgit v1.2.3 From 9398ddfe4ef38f26b8e25f510c5f6ffe01698e8b Mon Sep 17 00:00:00 2001 From: Andrei Koshkosh Date: Sun, 3 Jan 2016 23:31:26 -0200 Subject: [media] si2157.c: fix frequency range According with: https://www.silabs.com/Support%20Documents/TechnicalDocs/Si2157-short.pdf The RF input frequency range of this demod is from 42MHz to 870 MHz. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 0e1ca2b00e61..5da5b421d310 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -364,8 +364,8 @@ static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) static const struct dvb_tuner_ops si2157_ops = { .info = { .name = "Silicon Labs Si2146/2147/2148/2157/2158", - .frequency_min = 55000000, - .frequency_max = 862000000, + .frequency_min = 42000000, + .frequency_max = 870000000, }, .init = si2157_init, -- cgit v1.2.3 From 93b66420a4eb846ed8859d25c0a2056486f2929d Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 4 Jan 2016 17:32:51 -0200 Subject: [media] dw2102: Add support for Terratec Cinergy S2 USB BOX The Terratec Cinergy S2 USB BOX uses a Montage M88TS2022 tuner and a M88DS3103 demodulator, same as Technotrend TT-connect S2-4600. This patch adds the missing USB Product ID to make it work. Signed-off-by: Philipp Zabel Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/dw2102.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index bc19da5ad3b7..dd46d6c78c4e 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -1688,6 +1688,7 @@ enum dw2102_table_entry { TECHNOTREND_S2_4600, TEVII_S482_1, TEVII_S482_2, + TERRATEC_CINERGY_S2_BOX, }; static struct usb_device_id dw2102_table[] = { @@ -1715,6 +1716,7 @@ static struct usb_device_id dw2102_table[] = { USB_PID_TECHNOTREND_CONNECT_S2_4600)}, [TEVII_S482_1] = {USB_DEVICE(0x9022, 0xd483)}, [TEVII_S482_2] = {USB_DEVICE(0x9022, 0xd484)}, + [TERRATEC_CINERGY_S2_BOX] = {USB_DEVICE(USB_VID_TERRATEC, 0x0105)}, { } }; @@ -2232,7 +2234,7 @@ static struct dvb_usb_device_properties tt_s2_4600_properties = { } }, } }, - .num_device_descs = 3, + .num_device_descs = 4, .devices = { { "TechnoTrend TT-connect S2-4600", { &dw2102_table[TECHNOTREND_S2_4600], NULL }, @@ -2246,6 +2248,10 @@ static struct dvb_usb_device_properties tt_s2_4600_properties = { { &dw2102_table[TEVII_S482_2], NULL }, { NULL }, }, + { "Terratec Cinergy S2 USB BOX", + { &dw2102_table[TERRATEC_CINERGY_S2_BOX], NULL }, + { NULL }, + }, } }; -- cgit v1.2.3 From b8278f8b961a6a65a4939f646483866fb5bef112 Mon Sep 17 00:00:00 2001 From: Stefan Pöschel Date: Mon, 4 Jan 2016 19:16:55 -0200 Subject: [media] af9035: add support for 2nd tuner of MSI DigiVox Diversity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PIP tested with VLC. Diversity tested with the Windows driver. Signed-off-by: Stefan Pöschel Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/af9035.c | 4 ++-- drivers/media/usb/dvb-usb-v2/af9035.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index 6e02a15d39ce..b3c09fe54d9b 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -684,7 +684,7 @@ static int af9035_download_firmware(struct dvb_usb_device *d, if (ret < 0) goto err; - if (tmp == 1 || tmp == 3) { + if (tmp == 1 || tmp == 3 || tmp == 5) { /* configure gpioh1, reset & power slave demod */ ret = af9035_wr_reg_mask(d, 0x00d8b0, 0x01, 0x01); if (ret < 0) @@ -823,7 +823,7 @@ static int af9035_read_config(struct dvb_usb_device *d) if (ret < 0) goto err; - if (tmp == 1 || tmp == 3) + if (tmp == 1 || tmp == 3 || tmp == 5) state->dual_mode = true; dev_dbg(&d->udev->dev, "%s: ts mode=%d dual mode=%d\n", __func__, diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h index 416a97f05ec8..df22001f9e41 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.h +++ b/drivers/media/usb/dvb-usb-v2/af9035.h @@ -112,9 +112,10 @@ static const u32 clock_lut_it9135[] = { * 0 TS * 1 DCA + PIP * 3 PIP + * 5 DCA + PIP * n DCA * - * Values 0 and 3 are seen to this day. 0 for single TS and 3 for dual TS. + * Values 0, 3 and 5 are seen to this day. 0 for single TS and 3/5 for dual TS. */ #define EEPROM_BASE_AF9035 0x42fd -- cgit v1.2.3 From d309c8bb70beef4128a78d5208e692800c68b8f0 Mon Sep 17 00:00:00 2001 From: Torbjörn Jansson Date: Wed, 6 Jan 2016 14:26:31 -0200 Subject: [media] dvb-usb-dvbsky: add new product id for TT CT2-4650 CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new product id to dvb-usb-dvbsky for new version of TechnoTrend CT2-4650 CI Signed-off-by: Torbjörn Jansson Reviewed-by: Olli Salonen Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb-usb-ids.h | 1 + drivers/media/usb/dvb-usb-v2/dvbsky.c | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 750d23f9928d..dbdbb84294c5 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h @@ -248,6 +248,7 @@ #define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d #define USB_PID_TECHNOTREND_CONNECT_S2_4600 0x3011 #define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI 0x3012 +#define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI_2 0x3015 #define USB_PID_TECHNOTREND_TVSTICK_CT2_4400 0x3014 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c index 2d922b96ed83..02dbc6c45423 100644 --- a/drivers/media/usb/dvb-usb-v2/dvbsky.c +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c @@ -847,6 +847,10 @@ static const struct usb_device_id dvbsky_id_table[] = { USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI, &dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI", RC_MAP_TT_1500) }, + { DVB_USB_DEVICE(USB_VID_TECHNOTREND, + USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI_2, + &dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI v1.1", + RC_MAP_TT_1500) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_3, &dvbsky_t680c_props, "Terratec H7 Rev.4", -- cgit v1.2.3 From 4c7cad4bbf718e73a49e236e2b79489f1ee83810 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 7 Jan 2016 06:35:21 -0200 Subject: [media] rtl28xxu: retry failed i2c messages Sometimes i2c transfer fails. That happens especially when large amount of data is written sequentially eg. firmware download. Problem arises with both integrated rtl2832 demod and external mn88472 demod, which is clear indicator it is busy i2c bus issue. Use i2c core retry logic in order fix the issue by repeating failed message. Another solution which also works is to add ~100us delay between i2c messages - but repeating sounds more elegant and does not cause any extra delay for success cases. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index eb5787a3191e..c4c6e92e8643 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -259,6 +259,10 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], ret = -EOPNOTSUPP; } + /* Retry failed I2C messages */ + if (ret == -EPIPE) + ret = -EAGAIN; + err_mutex_unlock: mutex_unlock(&d->i2c_mutex); @@ -619,6 +623,10 @@ static int rtl28xxu_identify_state(struct dvb_usb_device *d, const char **name) } dev_dbg(&d->intf->dev, "chip_id=%u\n", dev->chip_id); + /* Retry failed I2C messages */ + d->i2c_adap.retries = 1; + d->i2c_adap.timeout = msecs_to_jiffies(10); + return WARM; err: dev_dbg(&d->intf->dev, "failed=%d\n", ret); -- cgit v1.2.3 From 631c694f7d7e17147bcf6c7c3669c8f4dc84cc09 Mon Sep 17 00:00:00 2001 From: Ernst Martin Witte Date: Sat, 9 Jan 2016 18:18:45 -0200 Subject: [media] af9013: cancel_delayed_work_sync before device removal / kfree af9013_remove was calling kfree(state) with possibly still active schedule_delayed_work(&state->statistics_work). A similar bug in si2157 caused kernel panics in call_timer_fn e.g. after rmmod cx23885. Signed-off-by: Ernst Martin Witte Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/af9013.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c index e23197da84af..41ab5defb798 100644 --- a/drivers/media/dvb-frontends/af9013.c +++ b/drivers/media/dvb-frontends/af9013.c @@ -1344,6 +1344,10 @@ err: static void af9013_release(struct dvb_frontend *fe) { struct af9013_state *state = fe->demodulator_priv; + + /* stop statistics polling */ + cancel_delayed_work_sync(&state->statistics_work); + kfree(state); } -- cgit v1.2.3 From 4bdcaa054e1c73697b390c32c434d96836121306 Mon Sep 17 00:00:00 2001 From: Ernst Martin Witte Date: Sat, 9 Jan 2016 18:18:46 -0200 Subject: [media] af9033: cancel_delayed_work_sync before device removal / kfree af9033_remove was calling kfree(dev) with possibly still active schedule_delayed_work(&dev->stat_work). A similar bug in si2157 caused kernel panics in call_timer_fn e.g. after rmmod cx23885. Signed-off-by: Ernst Martin Witte Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/af9033.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c index bc35206a0821..8b328d1ca8d3 100644 --- a/drivers/media/dvb-frontends/af9033.c +++ b/drivers/media/dvb-frontends/af9033.c @@ -1372,6 +1372,9 @@ static int af9033_remove(struct i2c_client *client) dev_dbg(&dev->client->dev, "\n"); + /* stop statistics polling */ + cancel_delayed_work_sync(&dev->stat_work); + dev->fe.ops.release = NULL; dev->fe.demodulator_priv = NULL; kfree(dev); -- cgit v1.2.3 From 01d1d714e26624bc50ba95c49cf6e15bb215c150 Mon Sep 17 00:00:00 2001 From: Ernst Martin Witte Date: Sat, 9 Jan 2016 18:18:43 -0200 Subject: [media] si2157: cancel_delayed_work_sync before device removal / kfree si2157_remove was calling kfree(dev) with possibly still active schedule_delayed_work(dev->stat_work). This caused kernel panics in call_timer_fn e.g. after rmmod cx23885. Signed-off-by: Ernst Martin Witte Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 5da5b421d310..3450dfb7c427 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -458,6 +458,9 @@ static int si2157_remove(struct i2c_client *client) dev_dbg(&client->dev, "\n"); + /* stop statistics polling */ + cancel_delayed_work_sync(&dev->stat_work); + memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops)); fe->tuner_priv = NULL; kfree(dev); -- cgit v1.2.3 From 4fd57ed61564bd4706e71cfd8c5a259079ddabf3 Mon Sep 17 00:00:00 2001 From: Ernst Martin Witte Date: Sat, 9 Jan 2016 18:18:47 -0200 Subject: [media] rtl2830: cancel_delayed_work_sync before device removal / kfree rtl2830_remove was calling kfree(dev) with possibly still active schedule_delayed_work(&dev->stat_work). A similar bug in si2157 caused kernel panics in call_timer_fn e.g. after rmmod cx23885. Signed-off-by: Ernst Martin Witte Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index b792f305cf15..74b771218033 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -900,6 +900,9 @@ static int rtl2830_remove(struct i2c_client *client) dev_dbg(&client->dev, "\n"); + /* stop statistics polling */ + cancel_delayed_work_sync(&dev->stat_work); + i2c_del_mux_adapter(dev->adapter); regmap_exit(dev->regmap); kfree(dev); -- cgit v1.2.3 From 41ff9142df375ac319b1d9fe50d88e4247da6f1a Mon Sep 17 00:00:00 2001 From: Ernst Martin Witte Date: Sat, 9 Jan 2016 18:18:44 -0200 Subject: [media] ts2020: cancel_delayed_work_sync before device removal / kfree ts2020_remove was calling kfree(dev) with possibly still active schedule_delayed_work(dev->stat_work). A similar bug in si2157 caused kernel panics in call_timer_fn e.g. after rmmod cx23885. Signed-off-by: Ernst Martin Witte Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/ts2020.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c index 7979e5d6498b..14b410ffe612 100644 --- a/drivers/media/dvb-frontends/ts2020.c +++ b/drivers/media/dvb-frontends/ts2020.c @@ -712,6 +712,10 @@ static int ts2020_remove(struct i2c_client *client) dev_dbg(&client->dev, "\n"); + /* stop statistics polling */ + if (!dev->dont_poll) + cancel_delayed_work_sync(&dev->stat_work); + regmap_exit(dev->regmap); kfree(dev); return 0; -- cgit v1.2.3 From df47512d59c0db59a6785f0208001a4b7dd90aaf Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 10 Jan 2016 05:20:16 -0200 Subject: [media] netup_unidvb: Remove a useless memset This memory is allocated using kzalloc so there is no need to call memset(..., 0, ...) [mchehab@osg.samsung.com: as suggested by Joe Perches, It's unusual to not see the alloc above the if, removed a blank line between kzalloc/if and added a blank line after if] Signed-off-by: Christophe JAILLET Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/netup_unidvb/netup_unidvb_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c index 525ebfefeee8..c94cecd2aa40 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c @@ -771,10 +771,9 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev, /* allocate device context */ ndev = kzalloc(sizeof(*ndev), GFP_KERNEL); - if (!ndev) goto dev_alloc_err; - memset(ndev, 0, sizeof(*ndev)); + ndev->old_fw = old_firmware; ndev->wq = create_singlethread_workqueue(NETUP_UNIDVB_NAME); if (!ndev->wq) { -- cgit v1.2.3 From 417b552331df8181e8033503c1cb2749290073e7 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 11 Jan 2016 00:13:20 -0200 Subject: [media] rcar_jpu: Add R-Car Gen2 Fallback Compatibility String Add fallback compatibility string. This is in keeping with the fallback scheme being adopted wherever appropriate for drivers for Renesas SoCs. Signed-off-by: Simon Horman Acked-by: Rob Herring Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/renesas,jpu.txt | 13 +++++++------ drivers/media/platform/rcar_jpu.c | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/media/renesas,jpu.txt b/Documentation/devicetree/bindings/media/renesas,jpu.txt index 0cb94201bf92..d3436e5190f9 100644 --- a/Documentation/devicetree/bindings/media/renesas,jpu.txt +++ b/Documentation/devicetree/bindings/media/renesas,jpu.txt @@ -5,11 +5,12 @@ and decoding function conforming to the JPEG baseline process, so that the JPU can encode image data and decode JPEG data quickly. Required properties: - - compatible: should containg one of the following: - - "renesas,jpu-r8a7790" for R-Car H2 - - "renesas,jpu-r8a7791" for R-Car M2-W - - "renesas,jpu-r8a7792" for R-Car V2H - - "renesas,jpu-r8a7793" for R-Car M2-N +- compatible: "renesas,jpu-", "renesas,rcar-gen2-jpu" as fallback. + Examples with soctypes are: + - "renesas,jpu-r8a7790" for R-Car H2 + - "renesas,jpu-r8a7791" for R-Car M2-W + - "renesas,jpu-r8a7792" for R-Car V2H + - "renesas,jpu-r8a7793" for R-Car M2-N - reg: Base address and length of the registers block for the JPU. - interrupts: JPU interrupt specifier. @@ -17,7 +18,7 @@ Required properties: Example: R8A7790 (R-Car H2) JPU node jpeg-codec@fe980000 { - compatible = "renesas,jpu-r8a7790"; + compatible = "renesas,jpu-r8a7790", "renesas,rcar-gen2-jpu"; reg = <0 0xfe980000 0 0x10300>; interrupts = <0 272 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp1_clks R8A7790_CLK_JPU>; diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c index 485f5259acb0..552789a69c86 100644 --- a/drivers/media/platform/rcar_jpu.c +++ b/drivers/media/platform/rcar_jpu.c @@ -1613,6 +1613,7 @@ static const struct of_device_id jpu_dt_ids[] = { { .compatible = "renesas,jpu-r8a7791" }, /* M2-W */ { .compatible = "renesas,jpu-r8a7792" }, /* V2H */ { .compatible = "renesas,jpu-r8a7793" }, /* M2-N */ + { .compatible = "renesas,rcar-gen2-jpu" }, { }, }; MODULE_DEVICE_TABLE(of, jpu_dt_ids); -- cgit v1.2.3 From f7842cfd3cab4566b28ede860344fcf8a7b409f6 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:09 -0200 Subject: [media] v4l: of: Correct v4l2_of_parse_endpoint() kernel-doc The v4l2_of_parse_endpoint function kernel-doc says that the return value is always 0. But that is not true since the function can fail and a error negative code is returned on failure. So correct the kernel-doc to match. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/v4l2-of.c b/drivers/media/v4l2-core/v4l2-of.c index b27cbb1f5afe..93b33681776c 100644 --- a/drivers/media/v4l2-core/v4l2-of.c +++ b/drivers/media/v4l2-core/v4l2-of.c @@ -146,7 +146,7 @@ static void v4l2_of_parse_parallel_bus(const struct device_node *node, * variable without a low fixed limit. Please use * v4l2_of_alloc_parse_endpoint() in new drivers instead. * - * Return: 0. + * Return: 0 on success or a negative error code on failure. */ int v4l2_of_parse_endpoint(const struct device_node *node, struct v4l2_of_endpoint *endpoint) -- cgit v1.2.3 From 7f6cd6c40d7bf3c640294359a8a835d03c94d634 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:10 -0200 Subject: [media] adv7604: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 5d4dbd05f9d6..801a9b09d5e5 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -2820,6 +2820,7 @@ static int adv76xx_parse_dt(struct adv76xx_state *state) struct device_node *endpoint; struct device_node *np; unsigned int flags; + int ret; u32 v; np = state->i2c_clients[ADV76XX_PAGE_IO]->dev.of_node; @@ -2829,7 +2830,11 @@ static int adv76xx_parse_dt(struct adv76xx_state *state) if (!endpoint) return -EINVAL; - v4l2_of_parse_endpoint(endpoint, &bus_cfg); + ret = v4l2_of_parse_endpoint(endpoint, &bus_cfg); + if (ret) { + of_node_put(endpoint); + return ret; + } if (!of_property_read_u32(endpoint, "default-input", &v)) state->pdata.default_input = v; -- cgit v1.2.3 From fda8b13ddce96335de2c6ae46bd3b14829318afe Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:11 -0200 Subject: [media] s5c73m3: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5c73m3/s5c73m3-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 57b3d27993a4..08af58fb8e7d 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1639,8 +1639,10 @@ static int s5c73m3_get_platform_data(struct s5c73m3 *state) return 0; } - v4l2_of_parse_endpoint(node_ep, &ep); + ret = v4l2_of_parse_endpoint(node_ep, &ep); of_node_put(node_ep); + if (ret) + return ret; if (ep.bus_type != V4L2_MBUS_CSI2) { dev_err(dev, "unsupported bus type\n"); -- cgit v1.2.3 From 2388309c7480550e64e20221640f6a5c717be662 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:12 -0200 Subject: [media] s5k5baf: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5k5baf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index fc3a5a8e6c9c..db82ed05792e 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -1868,8 +1868,11 @@ static int s5k5baf_parse_device_node(struct s5k5baf *state, struct device *dev) return -EINVAL; } - v4l2_of_parse_endpoint(node_ep, &ep); + ret = v4l2_of_parse_endpoint(node_ep, &ep); of_node_put(node_ep); + if (ret) + return ret; + state->bus_type = ep.bus_type; switch (state->bus_type) { -- cgit v1.2.3 From fe1e6ac6145b82f17c19653fc6bde626dfd8d861 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:13 -0200 Subject: [media] tvp514x: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp514x.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index 7fa5f1e4fe37..7cdd94842938 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -1001,7 +1001,7 @@ static struct tvp514x_decoder tvp514x_dev = { static struct tvp514x_platform_data * tvp514x_get_pdata(struct i2c_client *client) { - struct tvp514x_platform_data *pdata; + struct tvp514x_platform_data *pdata = NULL; struct v4l2_of_endpoint bus_cfg; struct device_node *endpoint; unsigned int flags; @@ -1013,11 +1013,13 @@ tvp514x_get_pdata(struct i2c_client *client) if (!endpoint) return NULL; + if (v4l2_of_parse_endpoint(endpoint, &bus_cfg)) + goto done; + pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) goto done; - v4l2_of_parse_endpoint(endpoint, &bus_cfg); flags = bus_cfg.bus.parallel.flags; if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) -- cgit v1.2.3 From baf40b5f79e0d8579cef5beaa18a91980dc77bfd Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:14 -0200 Subject: [media] tvp7002: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp7002.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 83c79fa5f61d..4df640c3aa40 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -894,7 +894,7 @@ static struct tvp7002_config * tvp7002_get_pdata(struct i2c_client *client) { struct v4l2_of_endpoint bus_cfg; - struct tvp7002_config *pdata; + struct tvp7002_config *pdata = NULL; struct device_node *endpoint; unsigned int flags; @@ -905,11 +905,13 @@ tvp7002_get_pdata(struct i2c_client *client) if (!endpoint) return NULL; + if (v4l2_of_parse_endpoint(endpoint, &bus_cfg)) + goto done; + pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) goto done; - v4l2_of_parse_endpoint(endpoint, &bus_cfg); flags = bus_cfg.bus.parallel.flags; if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) -- cgit v1.2.3 From 234eab8407afbedb4428012f8292357db75e24cd Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:15 -0200 Subject: [media] exynos4-is: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/media-dev.c | 8 +++++++- drivers/media/platform/exynos4-is/mipi-csis.c | 10 +++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index f3b2dd30ec77..662d4a5c584e 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -332,13 +332,19 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, struct fimc_source_info *pd = &fmd->sensor[index].pdata; struct device_node *rem, *ep, *np; struct v4l2_of_endpoint endpoint; + int ret; /* Assume here a port node can have only one endpoint node. */ ep = of_get_next_child(port, NULL); if (!ep) return 0; - v4l2_of_parse_endpoint(ep, &endpoint); + ret = v4l2_of_parse_endpoint(ep, &endpoint); + if (ret) { + of_node_put(ep); + return ret; + } + if (WARN_ON(endpoint.base.port == 0) || index >= FIMC_MAX_SENSORS) return -EINVAL; diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index ac5e50e595be..bd5c46c3d4b7 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -736,6 +736,7 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, { struct device_node *node = pdev->dev.of_node; struct v4l2_of_endpoint endpoint; + int ret; if (of_property_read_u32(node, "clock-frequency", &state->clk_frequency)) @@ -751,7 +752,9 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, return -EINVAL; } /* Get port node and validate MIPI-CSI channel id. */ - v4l2_of_parse_endpoint(node, &endpoint); + ret = v4l2_of_parse_endpoint(node, &endpoint); + if (ret) + goto err; state->index = endpoint.base.port - FIMC_INPUT_MIPI_CSI2_0; if (state->index >= CSIS_MAX_ENTITIES) @@ -764,9 +767,10 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, "samsung,csis-wclk"); state->num_lanes = endpoint.bus.mipi_csi2.num_data_lanes; - of_node_put(node); - return 0; +err: + of_node_put(node); + return ret; } static int s5pcsis_pm_resume(struct device *dev, bool runtime); -- cgit v1.2.3 From c517b35211aed34cb7c78d508a0b9fb209fd60c9 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:16 -0200 Subject: [media] omap3isp: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 67efa9ea551e..f9e5245f26ac 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2235,8 +2235,11 @@ static int isp_of_parse_node(struct device *dev, struct device_node *node, struct isp_bus_cfg *buscfg = &isd->bus; struct v4l2_of_endpoint vep; unsigned int i; + int ret; - v4l2_of_parse_endpoint(node, &vep); + ret = v4l2_of_parse_endpoint(node, &vep); + if (ret) + return ret; dev_dbg(dev, "parsing endpoint %s, interface %u\n", node->full_name, vep.base.port); -- cgit v1.2.3 From c89f8d47a171243fcac56b136e8526189035f8ee Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 13 Jan 2016 12:23:51 -0200 Subject: [media] s5c73m3: remove duplicate module device table Clang complains about an extraneous definition of the module device table after the patch to add it was accidentally merged twice: ../drivers/media/i2c/s5c73m3/s5c73m3-spi.c:40:1: error: redefinition of '__mod_of__s5c73m3_spi_ids_device_table' MODULE_DEVICE_TABLE(of, s5c73m3_spi_ids); ^ ../include/linux/module.h:223:27: note: expanded from macro 'MODULE_DEVICE_TABLE' extern const typeof(name) __mod_##type##__##name##_device_table \ ^ :99:1: note: expanded from here __mod_of__s5c73m3_spi_ids_device_table This removes the second definition. Fixes: f934a94bb566 ("[media] s5c73m3: Export OF module alias information") Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5c73m3/s5c73m3-spi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c index 7d65b36434b1..72ef9f936e6c 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c @@ -37,7 +37,6 @@ enum spi_direction { SPI_DIR_RX, SPI_DIR_TX }; -MODULE_DEVICE_TABLE(of, s5c73m3_spi_ids); static int spi_xmit(struct spi_device *spi_dev, void *addr, const int len, enum spi_direction dir) -- cgit v1.2.3 From 7445e45d19a09e5269dc85f17f9635be29d2f76c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 22 Jan 2016 08:53:55 -0200 Subject: [media] pwc: Add USB id for Philips Spc880nc webcam SPC 880NC PC camera discussions: http://www.pclinuxos.com/forum/index.php/topic,135688.0.html Cc: stable@vger.kernel.org Reported-by: Kikim Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pwc/pwc-if.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c index 086cf1c7bd7d..18aed5dd325e 100644 --- a/drivers/media/usb/pwc/pwc-if.c +++ b/drivers/media/usb/pwc/pwc-if.c @@ -91,6 +91,7 @@ static const struct usb_device_id pwc_device_table [] = { { USB_DEVICE(0x0471, 0x0312) }, { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */ { USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC PC Camera */ + { USB_DEVICE(0x0471, 0x032C) }, /* Philips SPC 880NC PC Camera */ { USB_DEVICE(0x069A, 0x0001) }, /* Askey */ { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */ { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */ @@ -810,6 +811,11 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id name = "Philips SPC 900NC webcam"; type_id = 740; break; + case 0x032C: + PWC_INFO("Philips SPC 880NC USB webcam detected.\n"); + name = "Philips SPC 880NC webcam"; + type_id = 740; + break; default: return -ENODEV; break; -- cgit v1.2.3 From eac287adb305820661f528e35a50bd54d7c515f1 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 15 Jan 2016 03:15:00 -0200 Subject: [media] dvbdev: remove useless parentheses after return The parentheses are not required after return, and just remove it. Signed-off-by: Xiubo Li Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index a7de62ebc415..a48421e96b5e 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -352,7 +352,7 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev, ret = media_device_register_entity(dvbdev->adapter->mdev, dvbdev->entity); if (ret) - return (ret); + return ret; printk(KERN_DEBUG "%s: media entity '%s' registered.\n", __func__, dvbdev->entity->name); -- cgit v1.2.3 From 5c3fbc5e033ae2e089883c7294304a9a5bf404b2 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 15 Jan 2016 03:14:58 -0200 Subject: [media] dvbdev: replace kcalloc with kzalloc Since the number of elements equals to 1, so just use kzalloc to simplify the code and make it more readable. Signed-off-by: Xiubo Li Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index a48421e96b5e..9fd687a1f593 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -620,8 +620,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap, return -ENOMEM; adap->conn = conn; - adap->conn_pads = kcalloc(1, sizeof(*adap->conn_pads), - GFP_KERNEL); + adap->conn_pads = kzalloc(sizeof(*adap->conn_pads), GFP_KERNEL); if (!adap->conn_pads) return -ENOMEM; -- cgit v1.2.3 From 0ede1876f7eb43ee6a47f5081d8902db6dd8b4ab Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 15 Jan 2016 03:14:59 -0200 Subject: [media] dvbdev: the space is required after ',' The space is missing after ',', and this will be introduce much noise when checking new patch around them. Signed-off-by: Xiubo Li Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 9fd687a1f593..1b9732ee0a4f 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -58,7 +58,7 @@ static const char * const dnames[] = { #define DVB_MAX_IDS MAX_DVB_MINORS #else #define DVB_MAX_IDS 4 -#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type) +#define nums2minor(num, type, id) ((num << 6) | (id << 4) | type) #define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64) #endif @@ -85,7 +85,7 @@ static int dvb_device_open(struct inode *inode, struct file *file) file->private_data = dvbdev; replace_fops(file, new_fops); if (file->f_op->open) - err = file->f_op->open(inode,file); + err = file->f_op->open(inode, file); up_read(&minor_rwsem); mutex_unlock(&dvbdev_mutex); return err; @@ -867,7 +867,7 @@ int dvb_usercopy(struct file *file, parg = sbuf; } else { /* too big to allocate from stack */ - mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); + mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); if (NULL == mbuf) return -ENOMEM; parg = mbuf; -- cgit v1.2.3 From 458a39523542c4479a69b98743436fb761f03796 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Mon, 25 Jan 2016 13:21:37 -0200 Subject: [media] media: platform: exynos4-is: media-dev: Add missing of_node_put for_each_available_child_of_node and for_each_child_of_node perform an of_node_get on each iteration, so to break out of the loop an of_node_put is required. Found using Coccinelle. The simplified version of the semantic patch that is used for this is as follows: // @@ local idexpression n; expression e,r; @@ for_each_available_child_of_node(r,n) { ... ( of_node_put(n); | e = n | + of_node_put(n); ? break; ) ... } ... when != n // Signed-off-by: Amitoj Kaur Chawla Reviewed-by: Krzysztof Kozlowski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/media-dev.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 662d4a5c584e..26a4e5c7b47a 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -435,8 +435,10 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) continue; ret = fimc_md_parse_port_node(fmd, port, index); - if (ret < 0) + if (ret < 0) { + of_node_put(node); goto rpm_put; + } index++; } @@ -447,8 +449,10 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) for_each_child_of_node(ports, node) { ret = fimc_md_parse_port_node(fmd, node, index); - if (ret < 0) + if (ret < 0) { + of_node_put(node); break; + } index++; } rpm_put: @@ -656,8 +660,10 @@ static int fimc_md_register_platform_entities(struct fimc_md *fmd, ret = fimc_md_register_platform_entity(fmd, pdev, plat_entity); put_device(&pdev->dev); - if (ret < 0) + if (ret < 0) { + of_node_put(node); break; + } } return ret; -- cgit v1.2.3 From 0529900a01cb840feb7f7e2f64ed88f7a9ed0031 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Tue, 26 Jan 2016 20:25:40 +0800 Subject: crypto: omap-aes - Support crypto engine framework Integrate with the newly added crypto engine to make the crypto hardware engine underutilized as each block needs to be processed before the crypto hardware can start working on the next block. The requests from dm-crypt will be listed into engine queue and processed by engine automatically, so remove the 'queue' and 'queue_task' things in omap aes driver. Signed-off-by: Baolin Wang Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 1 + drivers/crypto/omap-aes.c | 97 +++++++++++++++++++++-------------------------- 2 files changed, 45 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 07d494276aad..0a6e0b72284b 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -296,6 +296,7 @@ config CRYPTO_DEV_OMAP_AES depends on ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP2PLUS select CRYPTO_AES select CRYPTO_BLKCIPHER + select CRYPTO_ENGINE help OMAP processors have AES module accelerator. Select this if you want to use the OMAP module for AES algorithms. diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c index dd355bd19474..d420ec751c7c 100644 --- a/drivers/crypto/omap-aes.c +++ b/drivers/crypto/omap-aes.c @@ -36,6 +36,7 @@ #include #include #include +#include #define DST_MAXBURST 4 #define DMA_MIN (DST_MAXBURST * sizeof(u32)) @@ -152,13 +153,10 @@ struct omap_aes_dev { unsigned long flags; int err; - spinlock_t lock; - struct crypto_queue queue; - struct tasklet_struct done_task; - struct tasklet_struct queue_task; struct ablkcipher_request *req; + struct crypto_engine *engine; /* * total is used by PIO mode for book keeping so introduce @@ -532,9 +530,7 @@ static void omap_aes_finish_req(struct omap_aes_dev *dd, int err) pr_debug("err: %d\n", err); - dd->flags &= ~FLAGS_BUSY; - - req->base.complete(&req->base, err); + crypto_finalize_request(dd->engine, req, err); } static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd) @@ -604,34 +600,25 @@ static int omap_aes_copy_sgs(struct omap_aes_dev *dd) } static int omap_aes_handle_queue(struct omap_aes_dev *dd, - struct ablkcipher_request *req) + struct ablkcipher_request *req) { - struct crypto_async_request *async_req, *backlog; - struct omap_aes_ctx *ctx; - struct omap_aes_reqctx *rctx; - unsigned long flags; - int err, ret = 0, len; - - spin_lock_irqsave(&dd->lock, flags); if (req) - ret = ablkcipher_enqueue_request(&dd->queue, req); - if (dd->flags & FLAGS_BUSY) { - spin_unlock_irqrestore(&dd->lock, flags); - return ret; - } - backlog = crypto_get_backlog(&dd->queue); - async_req = crypto_dequeue_request(&dd->queue); - if (async_req) - dd->flags |= FLAGS_BUSY; - spin_unlock_irqrestore(&dd->lock, flags); + return crypto_transfer_request_to_engine(dd->engine, req); - if (!async_req) - return ret; + return 0; +} - if (backlog) - backlog->complete(backlog, -EINPROGRESS); +static int omap_aes_prepare_req(struct crypto_engine *engine, + struct ablkcipher_request *req) +{ + struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx( + crypto_ablkcipher_reqtfm(req)); + struct omap_aes_dev *dd = omap_aes_find_dev(ctx); + struct omap_aes_reqctx *rctx; + int len; - req = ablkcipher_request_cast(async_req); + if (!dd) + return -ENODEV; /* assign new request to device */ dd->req = req; @@ -662,16 +649,20 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd, dd->ctx = ctx; ctx->dd = dd; - err = omap_aes_write_ctrl(dd); - if (!err) - err = omap_aes_crypt_dma_start(dd); - if (err) { - /* aes_task will not finish it, so do it here */ - omap_aes_finish_req(dd, err); - tasklet_schedule(&dd->queue_task); - } + return omap_aes_write_ctrl(dd); +} - return ret; /* return ret, which is enqueue return value */ +static int omap_aes_crypt_req(struct crypto_engine *engine, + struct ablkcipher_request *req) +{ + struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx( + crypto_ablkcipher_reqtfm(req)); + struct omap_aes_dev *dd = omap_aes_find_dev(ctx); + + if (!dd) + return -ENODEV; + + return omap_aes_crypt_dma_start(dd); } static void omap_aes_done_task(unsigned long data) @@ -704,18 +695,10 @@ static void omap_aes_done_task(unsigned long data) } omap_aes_finish_req(dd, 0); - omap_aes_handle_queue(dd, NULL); pr_debug("exit\n"); } -static void omap_aes_queue_task(unsigned long data) -{ - struct omap_aes_dev *dd = (struct omap_aes_dev *)data; - - omap_aes_handle_queue(dd, NULL); -} - static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode) { struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx( @@ -1175,9 +1158,6 @@ static int omap_aes_probe(struct platform_device *pdev) dd->dev = dev; platform_set_drvdata(pdev, dd); - spin_lock_init(&dd->lock); - crypto_init_queue(&dd->queue, OMAP_AES_QUEUE_LENGTH); - err = (dev->of_node) ? omap_aes_get_res_of(dd, dev, &res) : omap_aes_get_res_pdev(dd, pdev, &res); if (err) @@ -1209,7 +1189,6 @@ static int omap_aes_probe(struct platform_device *pdev) (reg & dd->pdata->minor_mask) >> dd->pdata->minor_shift); tasklet_init(&dd->done_task, omap_aes_done_task, (unsigned long)dd); - tasklet_init(&dd->queue_task, omap_aes_queue_task, (unsigned long)dd); err = omap_aes_dma_init(dd); if (err && AES_REG_IRQ_STATUS(dd) && AES_REG_IRQ_ENABLE(dd)) { @@ -1250,7 +1229,20 @@ static int omap_aes_probe(struct platform_device *pdev) } } + /* Initialize crypto engine */ + dd->engine = crypto_engine_alloc_init(dev, 1); + if (!dd->engine) + goto err_algs; + + dd->engine->prepare_request = omap_aes_prepare_req; + dd->engine->crypt_one_request = omap_aes_crypt_req; + err = crypto_engine_start(dd->engine); + if (err) + goto err_engine; + return 0; +err_engine: + crypto_engine_exit(dd->engine); err_algs: for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) @@ -1260,7 +1252,6 @@ err_algs: omap_aes_dma_cleanup(dd); err_irq: tasklet_kill(&dd->done_task); - tasklet_kill(&dd->queue_task); pm_runtime_disable(dev); err_res: dd = NULL; @@ -1286,8 +1277,8 @@ static int omap_aes_remove(struct platform_device *pdev) crypto_unregister_alg( &dd->pdata->algs_info[i].algs_list[j]); + crypto_engine_exit(dd->engine); tasklet_kill(&dd->done_task); - tasklet_kill(&dd->queue_task); omap_aes_dma_cleanup(dd); pm_runtime_disable(dd->dev); dd = NULL; -- cgit v1.2.3 From d1662165ae612ec8b5f94a6b07e65ea58b6dce34 Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Fri, 29 Jan 2016 12:45:14 -0600 Subject: crypto: ccp - Limit the amount of information exported Since the exported information can be exposed to user-space, instead of exporting the entire request context only export the minimum information needed. Cc: # 3.14.x- Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto-aes-cmac.c | 16 +++++++++++----- drivers/crypto/ccp/ccp-crypto-sha.c | 20 +++++++++++++++----- drivers/crypto/ccp/ccp-crypto.h | 22 ++++++++++++++++++++++ 3 files changed, 48 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c index 00207cf5c79b..6a2d836eb2d9 100644 --- a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c +++ b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c @@ -223,9 +223,12 @@ static int ccp_aes_cmac_digest(struct ahash_request *req) static int ccp_aes_cmac_export(struct ahash_request *req, void *out) { struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); - struct ccp_aes_cmac_req_ctx *state = out; + struct ccp_aes_cmac_exp_ctx *state = out; - *state = *rctx; + state->null_msg = rctx->null_msg; + memcpy(state->iv, rctx->iv, sizeof(state->iv)); + state->buf_count = rctx->buf_count; + memcpy(state->buf, rctx->buf, sizeof(state->buf)); return 0; } @@ -233,9 +236,12 @@ static int ccp_aes_cmac_export(struct ahash_request *req, void *out) static int ccp_aes_cmac_import(struct ahash_request *req, const void *in) { struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); - const struct ccp_aes_cmac_req_ctx *state = in; + const struct ccp_aes_cmac_exp_ctx *state = in; - *rctx = *state; + rctx->null_msg = state->null_msg; + memcpy(rctx->iv, state->iv, sizeof(rctx->iv)); + rctx->buf_count = state->buf_count; + memcpy(rctx->buf, state->buf, sizeof(rctx->buf)); return 0; } @@ -378,7 +384,7 @@ int ccp_register_aes_cmac_algs(struct list_head *head) halg = &alg->halg; halg->digestsize = AES_BLOCK_SIZE; - halg->statesize = sizeof(struct ccp_aes_cmac_req_ctx); + halg->statesize = sizeof(struct ccp_aes_cmac_exp_ctx); base = &halg->base; snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "cmac(aes)"); diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c index 3aae58def106..a67128a7af23 100644 --- a/drivers/crypto/ccp/ccp-crypto-sha.c +++ b/drivers/crypto/ccp/ccp-crypto-sha.c @@ -210,9 +210,14 @@ static int ccp_sha_digest(struct ahash_request *req) static int ccp_sha_export(struct ahash_request *req, void *out) { struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); - struct ccp_sha_req_ctx *state = out; + struct ccp_sha_exp_ctx *state = out; - *state = *rctx; + state->type = rctx->type; + state->msg_bits = rctx->msg_bits; + state->first = rctx->first; + memcpy(state->ctx, rctx->ctx, sizeof(state->ctx)); + state->buf_count = rctx->buf_count; + memcpy(state->buf, rctx->buf, sizeof(state->buf)); return 0; } @@ -220,9 +225,14 @@ static int ccp_sha_export(struct ahash_request *req, void *out) static int ccp_sha_import(struct ahash_request *req, const void *in) { struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); - const struct ccp_sha_req_ctx *state = in; + const struct ccp_sha_exp_ctx *state = in; - *rctx = *state; + rctx->type = state->type; + rctx->msg_bits = state->msg_bits; + rctx->first = state->first; + memcpy(rctx->ctx, state->ctx, sizeof(rctx->ctx)); + rctx->buf_count = state->buf_count; + memcpy(rctx->buf, state->buf, sizeof(rctx->buf)); return 0; } @@ -428,7 +438,7 @@ static int ccp_register_sha_alg(struct list_head *head, halg = &alg->halg; halg->digestsize = def->digest_size; - halg->statesize = sizeof(struct ccp_sha_req_ctx); + halg->statesize = sizeof(struct ccp_sha_exp_ctx); base = &halg->base; snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); diff --git a/drivers/crypto/ccp/ccp-crypto.h b/drivers/crypto/ccp/ccp-crypto.h index 76a96f0f44c6..a326ec20bfa8 100644 --- a/drivers/crypto/ccp/ccp-crypto.h +++ b/drivers/crypto/ccp/ccp-crypto.h @@ -129,6 +129,15 @@ struct ccp_aes_cmac_req_ctx { struct ccp_cmd cmd; }; +struct ccp_aes_cmac_exp_ctx { + unsigned int null_msg; + + u8 iv[AES_BLOCK_SIZE]; + + unsigned int buf_count; + u8 buf[AES_BLOCK_SIZE]; +}; + /***** SHA related defines *****/ #define MAX_SHA_CONTEXT_SIZE SHA256_DIGEST_SIZE #define MAX_SHA_BLOCK_SIZE SHA256_BLOCK_SIZE @@ -171,6 +180,19 @@ struct ccp_sha_req_ctx { struct ccp_cmd cmd; }; +struct ccp_sha_exp_ctx { + enum ccp_sha_type type; + + u64 msg_bits; + + unsigned int first; + + u8 ctx[MAX_SHA_CONTEXT_SIZE]; + + unsigned int buf_count; + u8 buf[MAX_SHA_BLOCK_SIZE]; +}; + /***** Common Context Structure *****/ struct ccp_ctx { int (*complete)(struct crypto_async_request *req, int ret); -- cgit v1.2.3 From b3ff1270566d41eb8ab2d67844bf17b7fa9fee78 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Wed, 6 Jan 2016 18:40:38 -0200 Subject: iwlwifi: pcie: add initial RTPM support for PCI Add an initial implementation of runtime power management (RTPM) for PCI devices. With this patch, RTPM is only used when wifi is off (i.e. the wifi interface is down). This implementation is behind a new Kconfig flag, IWLWIFI_PCIE_RTPM. Signed-off-by: Luca Coelho Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/Kconfig | 12 +++++ drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 60 +++++++++++++++++++++++-- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 27 +++++++++++ 3 files changed, 96 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/Kconfig b/drivers/net/wireless/intel/iwlwifi/Kconfig index 866067789330..11932d53ea24 100644 --- a/drivers/net/wireless/intel/iwlwifi/Kconfig +++ b/drivers/net/wireless/intel/iwlwifi/Kconfig @@ -99,6 +99,18 @@ config IWLWIFI_UAPSD If unsure, say N. +config IWLWIFI_PCIE_RTPM + bool "Enable runtime power management mode for PCIe devices" + depends on IWLMVM && PM + default false + help + Say Y here to enable runtime power management for PCIe + devices. If enabled, the device will go into low power mode + when idle for a short period of time, allowing for improved + power saving during runtime. + + If unsure, say N. + menu "Debugging Options" config IWLWIFI_DEBUG diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 6261a68cae90..676d2391eb66 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -7,6 +7,7 @@ * * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * 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 @@ -66,6 +67,9 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#ifdef CONFIG_IWLWIFI_PCIE_RTPM +#include +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ #include #include #include @@ -623,6 +627,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) goto out_free_drv; +#ifdef CONFIG_IWLWIFI_PCIE_RTPM + pm_runtime_set_active(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, + iwlwifi_mod_params.d0i3_entry_delay); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_allow(&pdev->dev); +#endif return 0; out_free_drv: @@ -689,15 +700,58 @@ static int iwl_pci_resume(struct device *device) return 0; } -static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume); +#ifdef CONFIG_IWLWIFI_PCIE_RTPM +static int iwl_pci_runtime_suspend(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct iwl_trans *trans = pci_get_drvdata(pdev); + + IWL_DEBUG_RPM(trans, "entering runtime suspend\n"); + + /* For now we only allow D0I3 if the device is off */ + if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) + return -EBUSY; + + trans->system_pm_mode = IWL_PLAT_PM_MODE_D0I3; + + iwl_trans_d3_suspend(trans, false); + + return 0; +} + +static int iwl_pci_runtime_resume(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct iwl_trans *trans = pci_get_drvdata(pdev); + enum iwl_d3_status d3_status; + + IWL_DEBUG_RPM(trans, "exiting runtime suspend (resume)\n"); + + iwl_trans_d3_resume(trans, &d3_status, false); + + trans->system_pm_mode = IWL_PLAT_PM_MODE_D3; + + return 0; +} +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ + +static const struct dev_pm_ops iwl_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(iwl_pci_suspend, + iwl_pci_resume) +#ifdef CONFIG_IWLWIFI_PCIE_RTPM + SET_RUNTIME_PM_OPS(iwl_pci_runtime_suspend, + iwl_pci_runtime_resume, + NULL) +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ +}; #define IWL_PM_OPS (&iwl_dev_pm_ops) -#else +#else /* CONFIG_PM_SLEEP */ #define IWL_PM_OPS NULL -#endif +#endif /* CONFIG_PM_SLEEP */ static struct pci_driver iwl_pci_driver = { .name = DRV_NAME, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 35810965221c..db94fe1e1bc6 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -72,6 +72,9 @@ #include #include #include +#ifdef CONFIG_IWLWIFI_PCIE_RTPM +#include +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ #include "iwl-drv.h" #include "iwl-trans.h" @@ -1194,6 +1197,9 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) if (hw_rfkill != was_hw_rfkill) iwl_trans_pcie_rf_kill(trans, hw_rfkill); +#ifdef CONFIG_IWLWIFI_PCIE_RTPM + pm_runtime_put_sync(trans->dev); +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ /* re-take ownership to prevent other users from stealing the deivce */ iwl_pcie_prepare_card_hw(trans); } @@ -1353,6 +1359,9 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power) /* ... rfkill can call stop_device and set it false if needed */ iwl_trans_pcie_rf_kill(trans, hw_rfkill); +#ifdef CONFIG_IWLWIFI_PCIE_RTPM + pm_runtime_get_sync(trans->dev); +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ return 0; } @@ -1476,6 +1485,10 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int i; +#ifdef CONFIG_IWLWIFI_PCIE_RTPM + /* TODO: check if this is really needed */ + pm_runtime_disable(trans->dev); +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ synchronize_irq(trans_pcie->pci_dev->irq); iwl_pcie_tx_free(trans); @@ -1831,6 +1844,9 @@ void iwl_trans_pcie_ref(struct iwl_trans *trans) spin_lock_irqsave(&trans_pcie->ref_lock, flags); IWL_DEBUG_RPM(trans, "ref_counter: %d\n", trans_pcie->ref_count); trans_pcie->ref_count++; +#ifdef CONFIG_IWLWIFI_PCIE_RTPM + pm_runtime_get(&trans_pcie->pci_dev->dev); +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ spin_unlock_irqrestore(&trans_pcie->ref_lock, flags); } @@ -1849,6 +1865,11 @@ void iwl_trans_pcie_unref(struct iwl_trans *trans) return; } trans_pcie->ref_count--; +#ifdef CONFIG_IWLWIFI_PCIE_RTPM + pm_runtime_mark_last_busy(&trans_pcie->pci_dev->dev); + pm_runtime_put_autosuspend(&trans_pcie->pci_dev->dev); +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ + spin_unlock_irqrestore(&trans_pcie->ref_lock, flags); } @@ -2728,6 +2749,12 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, trans_pcie->inta_mask = CSR_INI_SET_MASK; +#ifdef CONFIG_IWLWIFI_PCIE_RTPM + trans->runtime_pm_mode = IWL_PLAT_PM_MODE_D0I3; +#else + trans->runtime_pm_mode = IWL_PLAT_PM_MODE_DISABLED; +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ + return trans; out_free_ict: -- cgit v1.2.3 From 4cbb8e50338a2f2453ba399ce52562e0a111fc1f Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Tue, 18 Aug 2015 16:02:38 +0300 Subject: iwlwifi: pcie: add RTPM support when wifi is enabled Enable runtime power management (RTPM) for PCIe devices and implement the corresponding functions to enable D0i3 mode when the device is idle. Additionally, remove some unnecessary #ifdef's because the RTPM code will not be called if runtime PM is not configured. Signed-off-by: Luca Coelho Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 5 ++ drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 98 +++++++++++++++++++--- drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 5 ++ drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 43 ++++++---- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 17 +++- 5 files changed, 141 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 82fb3a97a46d..fe170a3fb1a6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -736,6 +736,11 @@ enum iwl_plat_pm_mode { IWL_PLAT_PM_MODE_D0I3, }; +/* Max time to wait for trans to become idle/non-idle on d0i3 + * enter/exit (in msecs). + */ +#define IWL_TRANS_IDLE_TIMEOUT 2000 + /** * struct iwl_trans - transport common data * diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 676d2391eb66..16b579a5aa6b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -67,9 +67,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#ifdef CONFIG_IWLWIFI_PCIE_RTPM #include -#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ #include #include #include @@ -627,13 +625,15 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) goto out_free_drv; -#ifdef CONFIG_IWLWIFI_PCIE_RTPM - pm_runtime_set_active(&pdev->dev); - pm_runtime_set_autosuspend_delay(&pdev->dev, + /* if RTPM is in use, enable it in our device */ + if (iwl_trans->runtime_pm_mode != IWL_PLAT_PM_MODE_DISABLED) { + pm_runtime_set_active(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, iwlwifi_mod_params.d0i3_entry_delay); - pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_allow(&pdev->dev); -#endif + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_allow(&pdev->dev); + } + return 0; out_free_drv: @@ -700,17 +700,90 @@ static int iwl_pci_resume(struct device *device) return 0; } +int iwl_pci_fw_enter_d0i3(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + int ret; + + if (test_bit(STATUS_FW_ERROR, &trans->status)) + return 0; + + set_bit(STATUS_TRANS_GOING_IDLE, &trans->status); + + /* config the fw */ + ret = iwl_op_mode_enter_d0i3(trans->op_mode); + if (ret == 1) { + IWL_DEBUG_RPM(trans, "aborting d0i3 entrance\n"); + clear_bit(STATUS_TRANS_GOING_IDLE, &trans->status); + return -EBUSY; + } + if (ret) + goto err; + + ret = wait_event_timeout(trans_pcie->d0i3_waitq, + test_bit(STATUS_TRANS_IDLE, &trans->status), + msecs_to_jiffies(IWL_TRANS_IDLE_TIMEOUT)); + if (!ret) { + IWL_ERR(trans, "Timeout entering D0i3\n"); + ret = -ETIMEDOUT; + goto err; + } + + clear_bit(STATUS_TRANS_GOING_IDLE, &trans->status); + + return 0; +err: + clear_bit(STATUS_TRANS_GOING_IDLE, &trans->status); + iwl_trans_fw_error(trans); + return ret; +} + +int iwl_pci_fw_exit_d0i3(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + int ret; + + /* sometimes a D0i3 entry is not followed through */ + if (!test_bit(STATUS_TRANS_IDLE, &trans->status)) + return 0; + + /* config the fw */ + ret = iwl_op_mode_exit_d0i3(trans->op_mode); + if (ret) + goto err; + + /* we clear STATUS_TRANS_IDLE only when D0I3_END command is completed */ + + ret = wait_event_timeout(trans_pcie->d0i3_waitq, + !test_bit(STATUS_TRANS_IDLE, &trans->status), + msecs_to_jiffies(IWL_TRANS_IDLE_TIMEOUT)); + if (!ret) { + IWL_ERR(trans, "Timeout exiting D0i3\n"); + ret = -ETIMEDOUT; + goto err; + } + + return 0; +err: + clear_bit(STATUS_TRANS_IDLE, &trans->status); + iwl_trans_fw_error(trans); + return ret; +} + #ifdef CONFIG_IWLWIFI_PCIE_RTPM static int iwl_pci_runtime_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct iwl_trans *trans = pci_get_drvdata(pdev); + int ret; IWL_DEBUG_RPM(trans, "entering runtime suspend\n"); - /* For now we only allow D0I3 if the device is off */ - if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) - return -EBUSY; + if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) { + ret = iwl_pci_fw_enter_d0i3(trans); + if (ret < 0) + return ret; + } trans->system_pm_mode = IWL_PLAT_PM_MODE_D0I3; @@ -729,7 +802,8 @@ static int iwl_pci_runtime_resume(struct device *device) iwl_trans_d3_resume(trans, &d3_status, false); - trans->system_pm_mode = IWL_PLAT_PM_MODE_D3; + if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) + return iwl_pci_fw_exit_d0i3(trans); return 0; } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index bdda7028c393..7bc02e0cdd93 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -2,6 +2,7 @@ * * Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -374,6 +375,7 @@ struct iwl_trans_pcie { bool ucode_write_complete; wait_queue_head_t ucode_write_waitq; wait_queue_head_t wait_command_queue; + wait_queue_head_t d0i3_waitq; u8 cmd_queue; u8 cmd_fifo; @@ -594,4 +596,7 @@ static inline int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) } #endif +int iwl_pci_fw_exit_d0i3(struct iwl_trans *trans); +int iwl_pci_fw_enter_d0i3(struct iwl_trans *trans); + #endif /* __iwl_trans_int_pcie_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index db94fe1e1bc6..cfdc7f6e554a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -72,9 +72,7 @@ #include #include #include -#ifdef CONFIG_IWLWIFI_PCIE_RTPM #include -#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ #include "iwl-drv.h" #include "iwl-trans.h" @@ -1197,9 +1195,6 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) if (hw_rfkill != was_hw_rfkill) iwl_trans_pcie_rf_kill(trans, hw_rfkill); -#ifdef CONFIG_IWLWIFI_PCIE_RTPM - pm_runtime_put_sync(trans->dev); -#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ /* re-take ownership to prevent other users from stealing the deivce */ iwl_pcie_prepare_card_hw(trans); } @@ -1359,9 +1354,10 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power) /* ... rfkill can call stop_device and set it false if needed */ iwl_trans_pcie_rf_kill(trans, hw_rfkill); -#ifdef CONFIG_IWLWIFI_PCIE_RTPM - pm_runtime_get_sync(trans->dev); -#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ + /* Make sure we sync here, because we'll need full access later */ + if (low_power) + pm_runtime_resume(trans->dev); + return 0; } @@ -1485,10 +1481,9 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int i; -#ifdef CONFIG_IWLWIFI_PCIE_RTPM /* TODO: check if this is really needed */ pm_runtime_disable(trans->dev); -#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ + synchronize_irq(trans_pcie->pci_dev->irq); iwl_pcie_tx_free(trans); @@ -1844,9 +1839,7 @@ void iwl_trans_pcie_ref(struct iwl_trans *trans) spin_lock_irqsave(&trans_pcie->ref_lock, flags); IWL_DEBUG_RPM(trans, "ref_counter: %d\n", trans_pcie->ref_count); trans_pcie->ref_count++; -#ifdef CONFIG_IWLWIFI_PCIE_RTPM pm_runtime_get(&trans_pcie->pci_dev->dev); -#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ spin_unlock_irqrestore(&trans_pcie->ref_lock, flags); } @@ -1865,10 +1858,9 @@ void iwl_trans_pcie_unref(struct iwl_trans *trans) return; } trans_pcie->ref_count--; -#ifdef CONFIG_IWLWIFI_PCIE_RTPM + pm_runtime_mark_last_busy(&trans_pcie->pci_dev->dev); pm_runtime_put_autosuspend(&trans_pcie->pci_dev->dev); -#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ spin_unlock_irqrestore(&trans_pcie->ref_lock, flags); } @@ -2536,6 +2528,22 @@ static struct iwl_trans_dump_data return dump_data; } +#ifdef CONFIG_PM_SLEEP +static int iwl_trans_pcie_suspend(struct iwl_trans *trans) +{ + if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3) + return iwl_pci_fw_enter_d0i3(trans); + + return 0; +} + +static void iwl_trans_pcie_resume(struct iwl_trans *trans) +{ + if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3) + iwl_pci_fw_exit_d0i3(trans); +} +#endif /* CONFIG_PM_SLEEP */ + static const struct iwl_trans_ops trans_ops_pcie = { .start_hw = iwl_trans_pcie_start_hw, .op_mode_leave = iwl_trans_pcie_op_mode_leave, @@ -2546,6 +2554,11 @@ static const struct iwl_trans_ops trans_ops_pcie = { .d3_suspend = iwl_trans_pcie_d3_suspend, .d3_resume = iwl_trans_pcie_d3_resume, +#ifdef CONFIG_PM_SLEEP + .suspend = iwl_trans_pcie_suspend, + .resume = iwl_trans_pcie_resume, +#endif /* CONFIG_PM_SLEEP */ + .send_cmd = iwl_trans_pcie_send_hcmd, .tx = iwl_trans_pcie_tx, @@ -2735,6 +2748,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, /* Initialize the wait queue for commands */ init_waitqueue_head(&trans_pcie->wait_command_queue); + init_waitqueue_head(&trans_pcie->d0i3_waitq); + ret = iwl_pcie_alloc_ict(trans); if (ret) goto out_pci_disable_msi; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index b0b0fd9e2eff..c499345ba526 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -1,7 +1,8 @@ /****************************************************************************** * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -1727,6 +1728,20 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, wake_up(&trans_pcie->wait_command_queue); } + if (meta->flags & CMD_MAKE_TRANS_IDLE) { + IWL_DEBUG_INFO(trans, "complete %s - mark trans as idle\n", + iwl_get_cmd_string(trans, cmd->hdr.cmd)); + set_bit(STATUS_TRANS_IDLE, &trans->status); + wake_up(&trans_pcie->d0i3_waitq); + } + + if (meta->flags & CMD_WAKE_UP_TRANS) { + IWL_DEBUG_INFO(trans, "complete %s - clear trans idle flag\n", + iwl_get_cmd_string(trans, cmd->hdr.cmd)); + clear_bit(STATUS_TRANS_IDLE, &trans->status); + wake_up(&trans_pcie->d0i3_waitq); + } + meta->flags = 0; spin_unlock_bh(&txq->lock); -- cgit v1.2.3 From 23ae61282b88873bec2d56c78fea531f8485146c Mon Sep 17 00:00:00 2001 From: Matti Gottlieb Date: Thu, 31 Dec 2015 18:18:02 +0200 Subject: iwlwifi: mvm: Do not switch to D3 image on suspend Currently when the driver is configured with wowlan parameters, and enters D3 mode, the driver switches the FW image to D3, and when it exists suspend, it reloads the D0 image. If the firmware supports the consolidation of the D0 & D3 images there is no need to load the D3 image on suspend, and no need to reload the D0 image on resume. Do not switch images on suspend / resume, for firmwares that support consolidated images. Signed-off-by: Matti Gottlieb Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c | 4 +- drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 2 + drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 13 +++-- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 70 ++++++++++++++++------- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 4 +- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 4 +- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 11 ++-- 7 files changed, 70 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c index 29ea1c6705b4..4db4cb7aa73a 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c @@ -396,7 +396,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); - iwl_trans_d3_suspend(priv->trans, false); + iwl_trans_d3_suspend(priv->trans, false, true); goto out; @@ -469,7 +469,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) /* we'll clear ctx->vif during iwlagn_prepare_restart() */ vif = ctx->vif; - ret = iwl_trans_d3_resume(priv->trans, &d3_status, false); + ret = iwl_trans_d3_resume(priv->trans, &d3_status, false, true); if (ret) goto out_unlock; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index 84f8aeb926c8..2273908ad83a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -297,6 +297,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; * @IWL_UCODE_TLV_CAPA_DQA_SUPPORT: supports dynamic queue allocation (DQA), * which also implies support for the scheduler configuration command * @IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH: supports TDLS channel switching + * @IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG: Consolidated D3-D0 image * @IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT: supports Hot Spot Command * @IWL_UCODE_TLV_CAPA_DC2DC_SUPPORT: supports DC2DC Command * @IWL_UCODE_TLV_CAPA_CSUM_SUPPORT: supports TCP Checksum Offload @@ -330,6 +331,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT = (__force iwl_ucode_tlv_capa_t)11, IWL_UCODE_TLV_CAPA_DQA_SUPPORT = (__force iwl_ucode_tlv_capa_t)12, IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH = (__force iwl_ucode_tlv_capa_t)13, + IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG = (__force iwl_ucode_tlv_capa_t)17, IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT = (__force iwl_ucode_tlv_capa_t)18, IWL_UCODE_TLV_CAPA_DC2DC_CONFIG_SUPPORT = (__force iwl_ucode_tlv_capa_t)19, IWL_UCODE_TLV_CAPA_CSUM_SUPPORT = (__force iwl_ucode_tlv_capa_t)21, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index fe170a3fb1a6..e6a5e99f95e0 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -618,9 +618,9 @@ struct iwl_trans_ops { void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); void (*stop_device)(struct iwl_trans *trans, bool low_power); - void (*d3_suspend)(struct iwl_trans *trans, bool test); + void (*d3_suspend)(struct iwl_trans *trans, bool test, bool reset); int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status, - bool test); + bool test, bool reset); int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); @@ -925,22 +925,23 @@ static inline void iwl_trans_stop_device(struct iwl_trans *trans) _iwl_trans_stop_device(trans, true); } -static inline void iwl_trans_d3_suspend(struct iwl_trans *trans, bool test) +static inline void iwl_trans_d3_suspend(struct iwl_trans *trans, bool test, + bool reset) { might_sleep(); if (trans->ops->d3_suspend) - trans->ops->d3_suspend(trans, test); + trans->ops->d3_suspend(trans, test, reset); } static inline int iwl_trans_d3_resume(struct iwl_trans *trans, enum iwl_d3_status *status, - bool test) + bool test, bool reset) { might_sleep(); if (!trans->ops->d3_resume) return 0; - return trans->ops->d3_resume(trans, status, test); + return trans->ops->d3_resume(trans, status, test, reset); } static inline void iwl_trans_ref(struct iwl_trans *trans) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index d3e21d95cece..78572ef89b26 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * 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 @@ -33,6 +34,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1023,14 +1025,18 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm, struct ieee80211_sta *ap_sta) { int ret; + bool unified_image = fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); - ret = iwl_mvm_switch_to_d3(mvm); - if (ret) - return ret; + if (!unified_image) { + ret = iwl_mvm_switch_to_d3(mvm); + if (ret) + return ret; - ret = iwl_mvm_d3_reprogram(mvm, vif, ap_sta); - if (ret) - return ret; + ret = iwl_mvm_d3_reprogram(mvm, vif, ap_sta); + if (ret) + return ret; + } if (!iwlwifi_mod_params.sw_crypto) { /* @@ -1072,10 +1078,14 @@ iwl_mvm_netdetect_config(struct iwl_mvm *mvm, { struct iwl_wowlan_config_cmd wowlan_config_cmd = {}; int ret; + bool unified_image = fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); - ret = iwl_mvm_switch_to_d3(mvm); - if (ret) - return ret; + if (!unified_image) { + ret = iwl_mvm_switch_to_d3(mvm); + if (ret) + return ret; + } /* rfkill release can be either for wowlan or netdetect */ if (wowlan->rfkill_release) @@ -1151,6 +1161,8 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, }; int ret; int len __maybe_unused; + bool unified_image = fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); if (!wowlan) { /* @@ -1236,7 +1248,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); - iwl_trans_d3_suspend(mvm->trans, test); + iwl_trans_d3_suspend(mvm->trans, test, !unified_image); out: if (ret < 0) { iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); @@ -1299,7 +1311,7 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) __set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags); mutex_unlock(&mvm->d0i3_suspend_mutex); - iwl_trans_d3_suspend(trans, false); + iwl_trans_d3_suspend(trans, false, false); return 0; } @@ -2041,9 +2053,14 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac, static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) { struct ieee80211_vif *vif = NULL; - int ret; + int ret = 1; enum iwl_d3_status d3_status; bool keep = false; + bool unified_image = fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); + + u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE | + CMD_WAKE_UP_TRANS; mutex_lock(&mvm->mutex); @@ -2052,7 +2069,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) if (IS_ERR_OR_NULL(vif)) goto err; - ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test); + ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test, !unified_image); if (ret) goto err; @@ -2095,17 +2112,28 @@ out_iterate: iwl_mvm_d3_disconnect_iter, keep ? vif : NULL); out: - /* return 1 to reconfigure the device */ + if (unified_image && !ret) { + ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, flags, 0, NULL); + if (!ret) /* D3 ended successfully - no need to reset device */ + return 0; + } + + /* + * Reconfigure the device in one of the following cases: + * 1. We are not using a unified image + * 2. We are using a unified image but had an error while exiting D3 + */ set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); set_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status); - - /* We always return 1, which causes mac80211 to do a reconfig - * with IEEE80211_RECONFIG_TYPE_RESTART. This type of - * reconfig calls iwl_mvm_restart_complete(), where we unref - * the IWL_MVM_REF_UCODE_DOWN, so we need to take the - * reference here. + /* + * When switching images we return 1, which causes mac80211 + * to do a reconfig with IEEE80211_RECONFIG_TYPE_RESTART. + * This type of reconfig calls iwl_mvm_restart_complete(), + * where we unref the IWL_MVM_REF_UCODE_DOWN, so we need + * to take the reference here. */ iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); + return 1; } @@ -2122,7 +2150,7 @@ static int iwl_mvm_resume_d0i3(struct iwl_mvm *mvm) enum iwl_d3_status d3_status; struct iwl_trans *trans = mvm->trans; - iwl_trans_d3_resume(trans, &d3_status, false); + iwl_trans_d3_resume(trans, &d3_status, false, false); /* * make sure to clear D0I3_DEFER_WAKEUP before diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 9a15642f80dd..0476e7688e9b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -1109,7 +1109,7 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, cmd->general_flags = cpu_to_le32(iwl_mvm_scan_umac_flags(mvm, params, vif)); - if (type == IWL_MVM_SCAN_SCHED) + if (type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT) cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE); if (iwl_mvm_scan_use_ebs(mvm, vif)) @@ -1351,7 +1351,7 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) { hcmd.id = iwl_cmd_id(SCAN_REQ_UMAC, IWL_ALWAYS_LONG_GROUP, 0); - ret = iwl_mvm_scan_umac(mvm, vif, ¶ms, IWL_MVM_SCAN_SCHED); + ret = iwl_mvm_scan_umac(mvm, vif, ¶ms, type); } else { hcmd.id = SCAN_OFFLOAD_REQUEST_CMD; ret = iwl_mvm_scan_lmac(mvm, vif, ¶ms); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 16b579a5aa6b..762e7c4d96b6 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -787,7 +787,7 @@ static int iwl_pci_runtime_suspend(struct device *device) trans->system_pm_mode = IWL_PLAT_PM_MODE_D0I3; - iwl_trans_d3_suspend(trans, false); + iwl_trans_d3_suspend(trans, false, false); return 0; } @@ -800,7 +800,7 @@ static int iwl_pci_runtime_resume(struct device *device) IWL_DEBUG_RPM(trans, "exiting runtime suspend (resume)\n"); - iwl_trans_d3_resume(trans, &d3_status, false); + iwl_trans_d3_resume(trans, &d3_status, false, false); if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) return iwl_pci_fw_exit_d0i3(trans); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index cfdc7f6e554a..abe091698471 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1219,11 +1219,12 @@ void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state) _iwl_trans_pcie_stop_device(trans, true); } -static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test) +static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test, + bool reset) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - if (trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3) { + if (!reset) { /* Enable persistence mode to avoid reset */ iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_PERSIST_MODE); @@ -1247,7 +1248,7 @@ static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test) iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - if (trans->system_pm_mode == IWL_PLAT_PM_MODE_D3) { + if (reset) { /* * reset TX queues -- some of their registers reset during S3 * so if we don't reset everything here the D3 image would try @@ -1261,7 +1262,7 @@ static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test) static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, enum iwl_d3_status *status, - bool test) + bool test, bool reset) { u32 val; int ret; @@ -1296,7 +1297,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, iwl_pcie_set_pwr(trans, false); - if (trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3) { + if (!reset) { iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); } else { -- cgit v1.2.3 From 15ffd075e4088d3fc83ce8db914e7d3b6f31bc1c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 24 Jan 2016 23:04:22 +0200 Subject: iwlwifi: various comments and code cleanups No need to include net/ip6_checksum.h twice. Remove TODOs. Remove trailing space. Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h | 3 --- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 1 - drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 1 - 4 files changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index e6a5e99f95e0..0ca0f13b69b0 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -506,7 +506,7 @@ struct iwl_trans_config { bool sw_csum_tx; const struct iwl_hcmd_arr *command_groups; int command_groups_size; - + u32 sdio_adma_addr; }; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h index fb6d341d6f3d..ab467cb9b97c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h @@ -287,16 +287,13 @@ enum iwl_rx_mpdu_status { IWL_RX_MPDU_STATUS_KEY_ERROR = BIT(4), IWL_RX_MPDU_STATUS_ICV_OK = BIT(5), IWL_RX_MPDU_STATUS_MIC_OK = BIT(6), - /* TODO - verify this is the correct value */ IWL_RX_MPDU_RES_STATUS_TTAK_OK = BIT(7), IWL_RX_MPDU_STATUS_SEC_MASK = 0x7 << 8, IWL_RX_MPDU_STATUS_SEC_NONE = 0x0 << 8, IWL_RX_MPDU_STATUS_SEC_WEP = 0x1 << 8, IWL_RX_MPDU_STATUS_SEC_CCM = 0x2 << 8, IWL_RX_MPDU_STATUS_SEC_TKIP = 0x3 << 8, - /* TODO - define IWL_RX_MPDU_STATUS_SEC_EXT_ENC - this is a stub */ IWL_RX_MPDU_STATUS_SEC_EXT_ENC = 0x4 << 8, - /* TODO - define IWL_RX_MPDU_STATUS_SEC_GCM - this is a stub */ IWL_RX_MPDU_STATUS_SEC_GCM = 0x5 << 8, IWL_RX_MPDU_STATUS_DECRYPTED = BIT(11), IWL_RX_MPDU_STATUS_WEP_MATCH = BIT(12), diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 89ea70deeb84..6bf2bde239a0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -392,7 +392,6 @@ static const struct iwl_hcmd_arr iwl_mvm_groups[] = { [PHY_OPS_GROUP] = HCMD_ARR(iwl_mvm_phy_names), }; - /* this forward declaration can avoid to export the function */ static void iwl_mvm_async_handlers_wk(struct work_struct *wk); static void iwl_mvm_d0i3_exit_work(struct work_struct *wk); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index c499345ba526..837a7d536874 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -34,7 +34,6 @@ #include #include #include -#include #include "iwl-debug.h" #include "iwl-csr.h" -- cgit v1.2.3 From bdf408eca877a2ae310e3df9f05e865ffe10e4de Mon Sep 17 00:00:00 2001 From: Hubert Tarasiuk Date: Sun, 24 Jan 2016 13:35:06 +0100 Subject: iwlwifi: dvm: handle zero brightness for wifi LED In order to have the LED being OFF constantly when the brightness is set to 0, we need to pass IWL_LED_SOLID to iwl_led_cmd as the off parameter, otherwise the led will stay on constantly. This fixes https://bugzilla.kernel.org/show_bug.cgi?id=110551 Signed-off-by: Hubert Tarasiuk [reworked the commit message] Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/dvm/led.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/led.c b/drivers/net/wireless/intel/iwlwifi/dvm/led.c index 1aabb5ec096f..1bbd17ada974 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/led.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/led.c @@ -152,11 +152,14 @@ static void iwl_led_brightness_set(struct led_classdev *led_cdev, { struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv, led); unsigned long on = 0; + unsigned long off = 0; if (brightness > 0) on = IWL_LED_SOLID; + else + off = IWL_LED_SOLID; - iwl_led_cmd(priv, on, 0); + iwl_led_cmd(priv, on, off); } static int iwl_led_blink_set(struct led_classdev *led_cdev, -- cgit v1.2.3 From d1cae0fd22e9d0c55c97da29dcdfe28d99d96ea6 Mon Sep 17 00:00:00 2001 From: Rodrigo Freire Date: Wed, 6 Jan 2016 20:24:01 -0200 Subject: iwlwifi: Document missing module options This patch documents two missing module options in the internal code comment block. Signed-off-by: Rodrigo Freire Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-modparams.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h index fd42f63f5e84..b88ecc7892a9 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h @@ -108,6 +108,8 @@ enum iwl_amsdu_size { * @power_level: power level, default = 1 * @debug_level: levels are IWL_DL_* * @ant_coupling: antenna coupling in dB, default = 0 + * @nvm_file: specifies a external NVM file + * @uapsd_disable: disable U-APSD, default = 1 * @d0i3_disable: disable d0i3, default = 1, * @d0i3_entry_delay: time to wait after no refs are taken before * entering D0i3 (in msecs) -- cgit v1.2.3 From 25657fec94f87308da19bb3d5063feef04d5ba20 Mon Sep 17 00:00:00 2001 From: Golan Ben-Ami Date: Wed, 2 Sep 2015 12:34:23 +0300 Subject: iwlwifi: mvm: add trigger for firmware dump upon TX response status This will allow to collect the data when the firmware sends a specific tx response status. Signed-off-by: Golan Ben-Ami Signed-off-by: Emmanuel Grumbach --- .../net/wireless/intel/iwlwifi/iwl-fw-error-dump.h | 3 ++ drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 13 +++++++++ drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 33 ++++++++++++++++++++++ 3 files changed, 49 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h index a5aaf6853704..8425e1a587d9 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h @@ -293,6 +293,8 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data) * @FW_DBG_TX_LATENCY: trigger log collection when the tx latency goes above a * threshold. * @FW_DBG_TDLS: trigger log collection upon TDLS related events. + * @FW_DBG_TRIGGER_TX_STATUS: trigger log collection upon tx status when + * the firmware sends a tx reply. */ enum iwl_fw_dbg_trigger { FW_DBG_TRIGGER_INVALID = 0, @@ -309,6 +311,7 @@ enum iwl_fw_dbg_trigger { FW_DBG_TRIGGER_BA, FW_DBG_TRIGGER_TX_LATENCY, FW_DBG_TRIGGER_TDLS, + FW_DBG_TRIGGER_TX_STATUS, /* must be last */ FW_DBG_TRIGGER_MAX, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index 2273908ad83a..4050b4af7e45 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -749,6 +749,19 @@ struct iwl_fw_dbg_trigger_tdls { u8 reserved[4]; } __packed; +/** + * struct iwl_fw_dbg_trigger_tx_status - configures trigger for tx response + * status. + * @statuses: the list of statuses to trigger the collection on + */ +struct iwl_fw_dbg_trigger_tx_status { + struct tx_status { + u8 status; + u8 reserved[3]; + } __packed statuses[16]; + __le32 reserved[2]; +} __packed; + /** * struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration. * @id: conf id diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 8bf48a7d0f4e..5d73db2534a0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -736,6 +736,37 @@ static void iwl_mvm_hwrate_to_tx_status(u32 rate_n_flags, iwl_mvm_hwrate_to_tx_rate(rate_n_flags, info->band, r); } +static void iwl_mvm_tx_status_check_trigger(struct iwl_mvm *mvm, + u32 status) +{ + struct iwl_fw_dbg_trigger_tlv *trig; + struct iwl_fw_dbg_trigger_tx_status *status_trig; + int i; + + if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TX_STATUS)) + return; + + trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TX_STATUS); + status_trig = (void *)trig->data; + + if (!iwl_fw_dbg_trigger_check_stop(mvm, NULL, trig)) + return; + + for (i = 0; i < ARRAY_SIZE(status_trig->statuses); i++) { + /* don't collect on status 0 */ + if (!status_trig->statuses[i].status) + break; + + if (status_trig->statuses[i].status != (status & TX_STATUS_MSK)) + continue; + + iwl_mvm_fw_dbg_collect_trig(mvm, trig, + "Tx status %d was received", + status & TX_STATUS_MSK); + break; + } +} + static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt) { @@ -784,6 +815,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, break; } + iwl_mvm_tx_status_check_trigger(mvm, status); + info->status.rates[0].count = tx_resp->failure_frame + 1; iwl_mvm_hwrate_to_tx_status(le32_to_cpu(tx_resp->initial_rate), info); -- cgit v1.2.3 From ee95ed3728cb3ed70b76fb770fff66133ff8b1fa Mon Sep 17 00:00:00 2001 From: Avri Altman Date: Wed, 25 Nov 2015 13:17:10 +0200 Subject: iwlwifi: mvm: Add P2P client snoozing Enable snoozing and U-APSD on P2P client. The firwmare will support this only if the BSS vif is not associated. Make this configurable by a constant variable and disable it by default. Signed-off-by: Avri Altman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 2 ++ drivers/net/wireless/intel/iwlwifi/mvm/constants.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 8 +++++ drivers/net/wireless/intel/iwlwifi/mvm/power.c | 39 ++++++++++++++++++++-- 4 files changed, 47 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index 4050b4af7e45..dbf08c493654 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -302,6 +302,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; * @IWL_UCODE_TLV_CAPA_DC2DC_SUPPORT: supports DC2DC Command * @IWL_UCODE_TLV_CAPA_CSUM_SUPPORT: supports TCP Checksum Offload * @IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS: support radio and beacon statistics + * @IWL_UCODE_TLV_CAPA_P2P_STANDALONE_UAPSD: support p2p standalone U-APSD * @IWL_UCODE_TLV_CAPA_BT_COEX_PLCR: enabled BT Coex packet level co-running * @IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC: ucode supports LAR updates with different * sources for the MCC. This TLV bit is a future replacement to @@ -336,6 +337,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_DC2DC_CONFIG_SUPPORT = (__force iwl_ucode_tlv_capa_t)19, IWL_UCODE_TLV_CAPA_CSUM_SUPPORT = (__force iwl_ucode_tlv_capa_t)21, IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS = (__force iwl_ucode_tlv_capa_t)22, + IWL_UCODE_TLV_CAPA_P2P_STANDALONE_UAPSD = (__force iwl_ucode_tlv_capa_t)26, IWL_UCODE_TLV_CAPA_BT_COEX_PLCR = (__force iwl_ucode_tlv_capa_t)28, IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29, IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h index b00c03fcd447..959fc4d33d16 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h @@ -73,6 +73,7 @@ #define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC) #define IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT (2 * 1024) /* defined in TU */ #define IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT (40 * 1024) /* defined in TU */ +#define IWL_MVM_P2P_UAPSD_STANDALONE 0 #define IWL_MVM_P2P_LOWLATENCY_PS_ENABLE 0 #define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC) #define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 5f3ac8cccf49..5a92ab1b3787 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1005,6 +1005,14 @@ static inline bool iwl_mvm_is_mplut_supported(struct iwl_mvm *mvm) IWL_MVM_BT_COEX_MPLUT; } +static inline +bool iwl_mvm_is_p2p_standalone_uapsd_supported(struct iwl_mvm *mvm) +{ + return fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_P2P_STANDALONE_UAPSD) && + IWL_MVM_P2P_UAPSD_STANDALONE; +} + static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm) { /* firmware flag isn't defined yet */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index 9de159f1ef2d..16b3e36fb1ba 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c @@ -259,6 +259,26 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm, IWL_MVM_PS_HEAVY_RX_THLD_PERCENT; } +static void iwl_mvm_p2p_standalone_iterator(void *_data, u8 *mac, + struct ieee80211_vif *vif) +{ + bool *is_p2p_standalone = _data; + + switch (ieee80211_vif_type_p2p(vif)) { + case NL80211_IFTYPE_P2P_GO: + case NL80211_IFTYPE_AP: + *is_p2p_standalone = false; + break; + case NL80211_IFTYPE_STATION: + if (vif->bss_conf.assoc) + *is_p2p_standalone = false; + break; + + default: + break; + } +} + static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { @@ -268,9 +288,6 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, ETH_ALEN)) return false; - if (vif->p2p && - !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD)) - return false; /* * Avoid using uAPSD if P2P client is associated to GO that uses * opportunistic power save. This is due to current FW limitation. @@ -287,6 +304,22 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, if (iwl_mvm_phy_ctx_count(mvm) >= 2) return false; + if (vif->p2p) { + /* Allow U-APSD only if p2p is stand alone */ + bool is_p2p_standalone = true; + + if (!iwl_mvm_is_p2p_standalone_uapsd_supported(mvm)) + return false; + + ieee80211_iterate_active_interfaces_atomic(mvm->hw, + IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_p2p_standalone_iterator, + &is_p2p_standalone); + + if (!is_p2p_standalone) + return false; + } + return true; } -- cgit v1.2.3 From 33efe947e797c0f26b81bfe1b1eaf53501a6cd8e Mon Sep 17 00:00:00 2001 From: Golan Ben-Ami Date: Wed, 23 Dec 2015 17:53:27 +0200 Subject: iwlwifi: mvm: make collecting fw debug data optional Slow platforms may have issues with dumping data upon firmware assert. Make it easier to disable it for those platform. Signed-off-by: Golan Ben-Ami Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/constants.h | 7 +++++-- drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h index 959fc4d33d16..4b560e4417ee 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h @@ -6,7 +6,8 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2015 Intel Deutschland GmbH * * 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 @@ -32,7 +33,8 @@ * BSD LICENSE * * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2015 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,6 +110,7 @@ #define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1 #define IWL_MVM_TOF_IS_RESPONDER 0 #define IWL_MVM_SW_TX_CSUM_OFFLOAD 0 +#define IWL_MVM_COLLECT_FW_ERR_DUMP 1 #define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2 #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE_TW 1 diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c index 0813f8184e10..94ec3f0c15cf 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c @@ -435,6 +435,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) bool monitor_dump_only = false; int i; + if (!IWL_MVM_COLLECT_FW_ERR_DUMP && + !mvm->trans->dbg_dest_tlv) + return; + lockdep_assert_held(&mvm->mutex); /* there's no point in fw dump if the bus is dead */ -- cgit v1.2.3 From d8f7c5115d09e4b6b72b5b33414853aaa39bf837 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 14 Jan 2016 10:46:38 +0100 Subject: iwlwifi: mvm: remove shadowing variable The outer scope has a perfectly suitable 'i' variable, use it instead of adding a shadowing one in the inner scope. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c index 94ec3f0c15cf..4856eac120f6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c @@ -644,8 +644,6 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) /* Dump fw's virtual image */ if (mvm->fw->img[mvm->cur_ucode].paging_mem_size) { - u32 i; - for (i = 1; i < mvm->num_of_paging_blk + 1; i++) { struct iwl_fw_error_dump_paging *paging; struct page *pages = -- cgit v1.2.3 From 27e070d3d3c2f6ab925ffd7c54814cabd95db51c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 14 Jan 2016 10:55:22 +0100 Subject: iwlwifi: mvm: fix debugfs signedness warning Using kstrtouint() with a signed int isn't really right, use kstrotoint() instead. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 90500e2d107b..8059efafcb80 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -983,7 +983,7 @@ static ssize_t iwl_dbgfs_cont_recording_write(struct iwl_mvm *mvm, trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) return -EOPNOTSUPP; - ret = kstrtouint(buf, 0, &rec_mode); + ret = kstrtoint(buf, 0, &rec_mode); if (ret) return ret; -- cgit v1.2.3 From 7869318e4296e27d4cb97505e8739d62b48b2d58 Mon Sep 17 00:00:00 2001 From: Chaya Rachel Ivgi Date: Sun, 27 Dec 2015 13:45:42 +0200 Subject: iwlwifi: mvm: add support for negative temperatures The driver should support also negative temperatures. So there is a need to separate between the return value and temperature in order to be able to distinguish between a negative temperature and error value. Signed-off-by: Chaya Rachel Ivgi Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 9 +++++---- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/tt.c | 17 ++++++++--------- 3 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 8059efafcb80..5c0f93997b7b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -261,17 +261,18 @@ static ssize_t iwl_dbgfs_nic_temp_read(struct file *file, { struct iwl_mvm *mvm = file->private_data; char buf[16]; - int pos, temp; + int pos, ret; + s32 temp; if (!mvm->ucode_loaded) return -EIO; mutex_lock(&mvm->mutex); - temp = iwl_mvm_get_temp(mvm); + ret = iwl_mvm_get_temp(mvm, &temp); mutex_unlock(&mvm->mutex); - if (temp < 0) - return temp; + if (ret) + return -EIO; pos = scnprintf(buf , sizeof(buf), "%d\n", temp); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 5a92ab1b3787..216c8d6275a1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1489,7 +1489,7 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm); void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff); void iwl_mvm_tt_exit(struct iwl_mvm *mvm); void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state); -int iwl_mvm_get_temp(struct iwl_mvm *mvm); +int iwl_mvm_get_temp(struct iwl_mvm *mvm, s32 *temp); /* Location Aware Regulatory */ struct iwl_mcc_update_resp * diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c index fb76004eede4..758d05a8c6aa 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c @@ -194,12 +194,12 @@ static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm) return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(extcmd), &extcmd); } -int iwl_mvm_get_temp(struct iwl_mvm *mvm) +int iwl_mvm_get_temp(struct iwl_mvm *mvm, s32 *temp) { struct iwl_notification_wait wait_temp_notif; static u16 temp_notif[] = { WIDE_ID(PHY_OPS_GROUP, DTS_MEASUREMENT_NOTIF_WIDE) }; - int ret, temp; + int ret; if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_WIDE_CMD_HDR)) temp_notif[0] = DTS_MEASUREMENT_NOTIFICATION; @@ -208,7 +208,7 @@ int iwl_mvm_get_temp(struct iwl_mvm *mvm) iwl_init_notification_wait(&mvm->notif_wait, &wait_temp_notif, temp_notif, ARRAY_SIZE(temp_notif), - iwl_mvm_temp_notif_wait, &temp); + iwl_mvm_temp_notif_wait, temp); ret = iwl_mvm_get_temp_cmd(mvm); if (ret) { @@ -219,12 +219,10 @@ int iwl_mvm_get_temp(struct iwl_mvm *mvm) ret = iwl_wait_notification(&mvm->notif_wait, &wait_temp_notif, IWL_MVM_TEMP_NOTIF_WAIT_TIMEOUT); - if (ret) { + if (ret) IWL_ERR(mvm, "Getting the temperature timed out\n"); - return ret; - } - return temp; + return ret; } static void check_exit_ctkill(struct work_struct *work) @@ -233,6 +231,7 @@ static void check_exit_ctkill(struct work_struct *work) struct iwl_mvm *mvm; u32 duration; s32 temp; + int ret; tt = container_of(work, struct iwl_mvm_tt_mgmt, ct_kill_exit.work); mvm = container_of(tt, struct iwl_mvm, thermal_throttle); @@ -250,13 +249,13 @@ static void check_exit_ctkill(struct work_struct *work) goto reschedule; } - temp = iwl_mvm_get_temp(mvm); + ret = iwl_mvm_get_temp(mvm, &temp); iwl_mvm_unref(mvm, IWL_MVM_REF_CHECK_CTKILL); __iwl_mvm_mac_stop(mvm); - if (temp < 0) + if (ret) goto reschedule; IWL_DEBUG_TEMP(mvm, "NIC temperature: %d\n", temp); -- cgit v1.2.3 From 0db056d32490181be48efc2ca7cfa7494b13e6b5 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 29 Dec 2015 11:07:15 +0200 Subject: iwlwifi: mvm: support beacon storing Currently firmware is configured to filter out beacons. In case a beacon was changed - it is waking the host. However, some vendors change their IEs frequently without any significant change, and redundant wakeups are triggered as a result. As a solution disable beacon filtering when entering d0i3. Instead, firmware will store the latest beacon and upon exiting d0i3 it will send it up to the host, so the host can act upon changes (if there were any). This beacon will arrive as a dedicated notification - support it as well. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 3 ++ drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 3 +- drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h | 29 +++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 41 ++++++++++++++++++++-- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 ++ drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 22 ++++++++++-- drivers/net/wireless/intel/iwlwifi/mvm/power.c | 33 ++++++++++++----- 8 files changed, 120 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index dbf08c493654..5152987c8b8d 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -315,6 +315,8 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; * @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT * @IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION: firmware will decide on what * antenna the beacon should be transmitted + * @IWL_UCODE_TLV_CAPA_BEACON_STORING: firmware will store the latest beacon + * from AP and will send it upon d0i3 exit. * @IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2: support LAR API V2 * * @NUM_IWL_UCODE_TLV_CAPA: number of bits used @@ -346,6 +348,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65, IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67, IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION = (__force iwl_ucode_tlv_capa_t)71, + IWL_UCODE_TLV_CAPA_BEACON_STORING = (__force iwl_ucode_tlv_capa_t)72, IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2 = (__force iwl_ucode_tlv_capa_t)73, NUM_IWL_UCODE_TLV_CAPA diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 78572ef89b26..346376187ef8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -853,7 +853,8 @@ iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm, wowlan_config_cmd->is_11n_connection = ap_sta->ht_cap.ht_supported; wowlan_config_cmd->flags = ENABLE_L3_FILTERING | - ENABLE_NBNS_FILTERING | ENABLE_DHCP_FILTERING; + ENABLE_NBNS_FILTERING | ENABLE_DHCP_FILTERING | + ENABLE_STORE_BEACON; /* Query the last used seqno and set it */ ret = iwl_mvm_get_last_nonqos_seq(mvm, vif); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h index 62b9a0a96700..eec52c57f718 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h @@ -251,6 +251,7 @@ enum iwl_wowlan_flags { ENABLE_L3_FILTERING = BIT(1), ENABLE_NBNS_FILTERING = BIT(2), ENABLE_DHCP_FILTERING = BIT(3), + ENABLE_STORE_BEACON = BIT(4), }; struct iwl_wowlan_config_cmd { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h index 82049bb139c2..b6b57273b8ba 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h @@ -280,11 +280,16 @@ enum iwl_phy_ops_subcmd_ids { DTS_MEASUREMENT_NOTIF_WIDE = 0xFF, }; +enum iwl_prot_offload_subcmd_ids { + STORED_BEACON_NTF = 0xFF, +}; + /* command groups */ enum { LEGACY_GROUP = 0x0, LONG_GROUP = 0x1, PHY_OPS_GROUP = 0x4, + PROT_OFFLOAD_GROUP = 0xb, }; /** @@ -1851,4 +1856,28 @@ struct iwl_shared_mem_cfg { __le32 page_buff_size; } __packed; /* SHARED_MEM_ALLOC_API_S_VER_1 */ +#define MAX_STORED_BEACON_SIZE 600 + +/** + * Stored beacon notification + * + * @system_time: system time on air rise + * @tsf: TSF on air rise + * @beacon_timestamp: beacon on air rise + * @phy_flags: general phy flags: band, modulation, etc. + * @channel: channel this beacon was received on + * @rates: rate in ucode internal format + * @byte_count: frame's byte count + */ +struct iwl_stored_beacon_notif { + __le32 system_time; + __le64 tsf; + __le32 beacon_timestamp; + __le16 phy_flags; + __le16 channel; + __le32 rates; + __le32 byte_count; + u8 data[MAX_STORED_BEACON_SIZE]; +} __packed; /* WOWLAN_STROED_BEACON_INFO_S_VER_1 */ + #endif /* __fw_api_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index bf1e5eb5dbdb..62927f567afc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -7,7 +7,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH - * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2015 - 2016 Intel Deutschland GmbH * * 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 @@ -34,7 +34,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH - * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2015 - 2016 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1462,3 +1462,40 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, iwl_mvm_beacon_loss_iterator, mb); } + +void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_stored_beacon_notif *sb = (void *)pkt->data; + struct ieee80211_rx_status rx_status; + struct sk_buff *skb; + u32 size = le32_to_cpu(sb->byte_count); + + if (size == 0) + return; + + skb = alloc_skb(size, GFP_ATOMIC); + if (!skb) { + IWL_ERR(mvm, "alloc_skb failed\n"); + return; + } + + /* update rx_status according to the notification's metadata */ + memset(&rx_status, 0, sizeof(rx_status)); + rx_status.mactime = le64_to_cpu(sb->tsf); + rx_status.device_timestamp = le32_to_cpu(sb->system_time); + rx_status.band = + (sb->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ? + IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; + rx_status.freq = + ieee80211_channel_to_frequency(le16_to_cpu(sb->channel), + rx_status.band); + + /* copy the data */ + memcpy(skb_put(skb, size), sb->data, size); + memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); + + /* pass it as regular rx to mac80211 */ + ieee80211_rx_napi(mvm->hw, skb, NULL); +} diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 216c8d6275a1..b45cf4f63781 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1192,6 +1192,8 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); +void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif); unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 6bf2bde239a0..3c869ad6aaec 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -33,6 +33,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -267,6 +268,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { true), RX_HANDLER(MFUART_LOAD_NOTIFICATION, iwl_mvm_rx_mfuart_notif, false), RX_HANDLER(TOF_NOTIFICATION, iwl_mvm_tof_resp_handler, true), + RX_HANDLER_GRP(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF, + iwl_mvm_rx_stored_beacon_notif, false), }; #undef RX_HANDLER @@ -386,10 +389,18 @@ static const struct iwl_hcmd_names iwl_mvm_phy_names[] = { HCMD_NAME(DTS_MEASUREMENT_NOTIF_WIDE), }; +/* Please keep this array *SORTED* by hex value. + * Access is done through binary search + */ +static const struct iwl_hcmd_names iwl_mvm_prot_offload_names[] = { + HCMD_NAME(STORED_BEACON_NTF), +}; + static const struct iwl_hcmd_arr iwl_mvm_groups[] = { [LEGACY_GROUP] = HCMD_ARR(iwl_mvm_legacy_names), [LONG_GROUP] = HCMD_ARR(iwl_mvm_legacy_names), [PHY_OPS_GROUP] = HCMD_ARR(iwl_mvm_phy_names), + [PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mvm_prot_offload_names), }; /* this forward declaration can avoid to export the function */ @@ -1195,7 +1206,7 @@ static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm, cmd->is_11n_connection = ap_sta->ht_cap.ht_supported; cmd->offloading_tid = iter_data->offloading_tid; cmd->flags = ENABLE_L3_FILTERING | ENABLE_NBNS_FILTERING | - ENABLE_DHCP_FILTERING; + ENABLE_DHCP_FILTERING | ENABLE_STORE_BEACON; /* * The d0i3 uCode takes care of the nonqos counters, * so configure only the qos seq ones. @@ -1216,8 +1227,7 @@ int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode) struct iwl_wowlan_config_cmd wowlan_config_cmd = { .wakeup_filter = cpu_to_le32(IWL_WOWLAN_WAKEUP_RX_FRAME | IWL_WOWLAN_WAKEUP_BEACON_MISS | - IWL_WOWLAN_WAKEUP_LINK_CHANGE | - IWL_WOWLAN_WAKEUP_BCN_FILTERING), + IWL_WOWLAN_WAKEUP_LINK_CHANGE), }; struct iwl_d3_manager_config d3_cfg_cmd = { .min_sleep_time = cpu_to_le32(1000), @@ -1267,6 +1277,12 @@ int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode) /* configure wowlan configuration only if needed */ if (mvm->d0i3_ap_sta_id != IWL_MVM_STATION_COUNT) { + /* wake on beacons only if beacon storing isn't supported */ + if (!fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_BEACON_STORING)) + wowlan_config_cmd.wakeup_filter |= + cpu_to_le32(IWL_WOWLAN_WAKEUP_BCN_FILTERING); + iwl_mvm_wowlan_config_key_params(mvm, d0i3_iter_data.connected_vif, true, flags); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index 16b3e36fb1ba..0d03b3e3cf4e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c @@ -7,7 +7,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH - * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2015 - 2016 Intel Deutschland GmbH * * 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 @@ -34,7 +34,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH - * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2015 - 2016 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -903,9 +903,9 @@ static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false); } -int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - u32 flags) +static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + u32 flags, bool d0i3) { struct iwl_beacon_filter_cmd cmd = {}; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); @@ -916,12 +916,20 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags); - if (!ret) + /* don't change bf_enabled in case of temporary d0i3 configuration */ + if (!ret && !d0i3) mvmvif->bf_data.bf_enabled = false; return ret; } +int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + u32 flags) +{ + return _iwl_mvm_disable_beacon_filter(mvm, vif, flags, false); +} + static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm) { bool disable_ps; @@ -1058,8 +1066,17 @@ int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm, IWL_BF_CMD_CONFIG_D0I3, .bf_enable_beacon_filter = cpu_to_le32(1), }; - ret = _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd_bf, - flags, true); + /* + * When beacon storing is supported - disable beacon filtering + * altogether - the latest beacon will be sent when exiting d0i3 + */ + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_BEACON_STORING)) + ret = _iwl_mvm_disable_beacon_filter(mvm, vif, flags, + true); + else + ret = _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd_bf, + flags, true); } else { if (mvmvif->bf_data.bf_enabled) ret = iwl_mvm_enable_beacon_filter(mvm, vif, flags); -- cgit v1.2.3 From b525d08125e61e262be63ea250e3e13e93b6a92a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 6 Jan 2016 10:01:41 +0100 Subject: iwlwifi: mvm: track low-latency sources separately To be able to test low-latency behaviour properly, split the different low-latency sources so that setting any one of them, for example from debugfs, is sufficient; this avoids getting the debug setting overwritten by other sources. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c | 19 ++++++++++++++----- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 12 +++++++----- drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 6 ++---- 3 files changed, 23 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c index 9e0d46368cdd..c286a5f8d8bd 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * 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 @@ -33,6 +34,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1255,6 +1257,7 @@ static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm *mvm = mvmvif->mvm; + bool prev; u8 value; int ret; @@ -1265,7 +1268,9 @@ static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf, return -EINVAL; mutex_lock(&mvm->mutex); - iwl_mvm_update_low_latency(mvm, vif, value); + prev = iwl_mvm_vif_low_latency(mvmvif); + mvmvif->low_latency_dbgfs = value; + iwl_mvm_update_low_latency(mvm, vif, prev); mutex_unlock(&mvm->mutex); return count; @@ -1277,11 +1282,15 @@ static ssize_t iwl_dbgfs_low_latency_read(struct file *file, { struct ieee80211_vif *vif = file->private_data; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - char buf[2]; + char buf[30] = {}; + int len; - buf[0] = mvmvif->low_latency ? '1' : '0'; - buf[1] = '\n'; - return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf)); + len = snprintf(buf, sizeof(buf) - 1, + "traffic=%d\ndbgfs=%d\nvcmd=%d\n", + mvmvif->low_latency_traffic, + mvmvif->low_latency_dbgfs, + mvmvif->low_latency_vcmd); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); } static ssize_t iwl_dbgfs_uapsd_misbehaving_read(struct file *file, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index b45cf4f63781..418aeffd9bab 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -346,8 +346,9 @@ struct iwl_mvm_vif_bf_data { * @pm_enabled - Indicate if MAC power management is allowed * @monitor_active: indicates that monitor context is configured, and that the * interface should get quota etc. - * @low_latency: indicates that this interface is in low-latency mode - * (VMACLowLatencyMode) + * @low_latency_traffic: indicates low latency traffic was detected + * @low_latency_dbgfs: low latency mode set from debugfs + * @low_latency_vcmd: low latency mode set from vendor command * @ps_disabled: indicates that this interface requires PS to be disabled * @queue_params: QoS params for this MAC * @bcast_sta: station used for broadcast packets. Used by the following @@ -375,7 +376,7 @@ struct iwl_mvm_vif { bool ap_ibss_active; bool pm_enabled; bool monitor_active; - bool low_latency; + bool low_latency_traffic, low_latency_dbgfs, low_latency_vcmd; bool ps_disabled; struct iwl_mvm_vif_bf_data bf_data; @@ -1427,8 +1428,9 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif) * binding, so this has no real impact. For now, just return * the current desired low-latency state. */ - - return mvmvif->low_latency; + return mvmvif->low_latency_dbgfs || + mvmvif->low_latency_traffic || + mvmvif->low_latency_vcmd; } /* hw scheduler queue config */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 3a989f5c20db..59453c176580 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -937,18 +937,16 @@ bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm) } int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - bool value) + bool prev) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); int res; lockdep_assert_held(&mvm->mutex); - if (mvmvif->low_latency == value) + if (iwl_mvm_vif_low_latency(mvmvif) == prev) return 0; - mvmvif->low_latency = value; - res = iwl_mvm_update_quotas(mvm, false, NULL); if (res) return res; -- cgit v1.2.3 From a80c1cf9b4b2937cfe782aba7b54a5144fe7eec2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Jan 2016 15:01:00 +0100 Subject: iwlwifi: mvm: support setting minimum quota from debugfs For debug purposes, allow setting minimum quota (for a single virtual interface) from debugfs. This is an absolute minimum, so it can only be set up to 95%. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- .../net/wireless/intel/iwlwifi/mvm/debugfs-vif.c | 56 ++++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/quota.c | 16 +++++++ 3 files changed, 73 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c index c286a5f8d8bd..14004456bf55 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c @@ -1372,6 +1372,59 @@ static ssize_t iwl_dbgfs_rx_phyinfo_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf)); } +static void iwl_dbgfs_quota_check(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + int *ret = data; + + if (mvmvif->dbgfs_quota_min) + *ret = -EINVAL; +} + +static ssize_t iwl_dbgfs_quota_min_write(struct ieee80211_vif *vif, char *buf, + size_t count, loff_t *ppos) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_mvm *mvm = mvmvif->mvm; + u16 value; + int ret; + + ret = kstrtou16(buf, 0, &value); + if (ret) + return ret; + + if (value > 95) + return -EINVAL; + + mutex_lock(&mvm->mutex); + + mvmvif->dbgfs_quota_min = 0; + ieee80211_iterate_interfaces(mvm->hw, IEEE80211_IFACE_ITER_NORMAL, + iwl_dbgfs_quota_check, &ret); + if (ret == 0) { + mvmvif->dbgfs_quota_min = value; + iwl_mvm_update_quotas(mvm, false, NULL); + } + mutex_unlock(&mvm->mutex); + + return ret ?: count; +} + +static ssize_t iwl_dbgfs_quota_min_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_vif *vif = file->private_data; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + char buf[10]; + int len; + + len = snprintf(buf, sizeof(buf), "%d\n", mvmvif->dbgfs_quota_min); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \ _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif) #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ @@ -1395,6 +1448,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_req_ext, 32); MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_abort, 32); MVM_DEBUGFS_READ_FILE_OPS(tof_range_response); MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_responder_params, 32); +MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32); void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { @@ -1432,6 +1486,8 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) S_IRUSR | S_IWUSR); MVM_DEBUGFS_ADD_FILE_VIF(rx_phyinfo, mvmvif->dbgfs_dir, S_IRUSR | S_IWUSR); + MVM_DEBUGFS_ADD_FILE_VIF(quota_min, mvmvif->dbgfs_dir, + S_IRUSR | S_IWUSR); if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p && mvmvif == mvm->bf_allowed_vif) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 418aeffd9bab..5a34808fdeed 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -433,6 +433,7 @@ struct iwl_mvm_vif { struct iwl_dbgfs_pm dbgfs_pm; struct iwl_dbgfs_bf dbgfs_bf; struct iwl_mac_power_cmd mac_pwr_cmd; + int dbgfs_quota_min; #endif enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ]; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/quota.c b/drivers/net/wireless/intel/iwlwifi/mvm/quota.c index 0b762b4f8fad..2141db5bff82 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/quota.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/quota.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * 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 @@ -33,6 +34,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -74,6 +76,9 @@ struct iwl_mvm_quota_iterator_data { int n_interfaces[MAX_BINDINGS]; int colors[MAX_BINDINGS]; int low_latency[MAX_BINDINGS]; +#ifdef CONFIG_IWLWIFI_DEBUGFS + int dbgfs_min[MAX_BINDINGS]; +#endif int n_low_latency_bindings; struct ieee80211_vif *disabled_vif; }; @@ -129,6 +134,12 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac, data->n_interfaces[id]++; +#ifdef CONFIG_IWLWIFI_DEBUGFS + if (mvmvif->dbgfs_quota_min) + data->dbgfs_min[id] = max(data->dbgfs_min[id], + mvmvif->dbgfs_quota_min); +#endif + if (iwl_mvm_vif_low_latency(mvmvif) && !data->low_latency[id]) { data->n_low_latency_bindings++; data->low_latency[id] = true; @@ -259,6 +270,11 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, if (data.n_interfaces[i] <= 0) cmd.quotas[idx].quota = cpu_to_le32(0); +#ifdef CONFIG_IWLWIFI_DEBUGFS + else if (data.dbgfs_min[i]) + cmd.quotas[idx].quota = + cpu_to_le32(data.dbgfs_min[i] * QUOTA_100 / 100); +#endif else if (data.n_low_latency_bindings == 1 && n_non_lowlat && data.low_latency[i]) /* -- cgit v1.2.3 From 0c1c6e37137fc2333ef9898c24ea0cb9efbd8df0 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 16 Dec 2015 21:17:06 +0200 Subject: iwlwifi: mvm: change access to ieee80211_hdr Make the code clearer. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 0c073e02fd4c..4cce37238a08 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -294,7 +294,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, struct ieee80211_rx_status *rx_status; struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_mpdu_desc *desc = (void *)pkt->data; - struct ieee80211_hdr *hdr = (void *)(desc + 1); + struct ieee80211_hdr *hdr = (void *)(pkt->data + sizeof(*desc)); u32 len = le16_to_cpu(desc->mpdu_len); u32 rate_n_flags = le32_to_cpu(desc->rate_n_flags); struct ieee80211_sta *sta = NULL; -- cgit v1.2.3 From 1c4e15a23d27e2efd56d2b9b7436bff060f126ef Mon Sep 17 00:00:00 2001 From: Max Stepanov Date: Mon, 4 Jan 2016 11:09:14 +0200 Subject: iwlwifi: mvm: add debug print if scan config is ignored Print a debug message in iwl_mvm_config_scan() if a scan configuration data is decided not to be sent to FW. Signed-off-by: Max Stepanov Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 0476e7688e9b..1e1ab9daaec9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -930,8 +930,11 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) if (WARN_ON(num_channels > mvm->fw->ucode_capa.n_scan_channels)) return -ENOBUFS; - if (type == mvm->scan_type) + if (type == mvm->scan_type) { + IWL_DEBUG_SCAN(mvm, + "Ignoring UMAC scan config of the same type\n"); return 0; + } cmd_size = sizeof(*scan_config) + mvm->fw->ucode_capa.n_scan_channels; -- cgit v1.2.3 From 837c4da98481d4e504b2aba077c8528fee1b6d13 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Thu, 7 Jan 2016 16:50:45 +0200 Subject: iwlwifi: mvm: change the check for ADD_STA status The firmware will return the baid for BA session in the ADD_STA command response. This requires masking the check of the status, which is actually only 8 bits, and not the whole 32 bits. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h | 3 +++ drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h index 6fca4fb1d306..1eb3983decc3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h @@ -253,6 +253,9 @@ struct iwl_mvm_keyinfo { __le64 hw_tkip_mic_tx_key; } __packed; +#define IWL_ADD_STA_STATUS_MASK 0xFF +#define IWL_ADD_STA_BAID_MASK 0xFF00 + /** * struct iwl_mvm_add_sta_cmd - Add/modify a station in the fw's sta table. * ( REPLY_ADD_STA = 0x18 ) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index b556e33658d7..84b7fd1c4c70 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -192,7 +192,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, if (ret) return ret; - switch (status) { + switch (status & IWL_ADD_STA_STATUS_MASK) { case ADD_STA_SUCCESS: IWL_DEBUG_ASSOC(mvm, "ADD_STA PASSED\n"); break; @@ -362,7 +362,7 @@ int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, if (ret) return ret; - switch (status) { + switch (status & IWL_ADD_STA_STATUS_MASK) { case ADD_STA_SUCCESS: IWL_DEBUG_INFO(mvm, "Frames for staid %d will drained in fw\n", mvmsta->sta_id); @@ -628,7 +628,7 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm, if (ret) return ret; - switch (status) { + switch (status & IWL_ADD_STA_STATUS_MASK) { case ADD_STA_SUCCESS: IWL_DEBUG_INFO(mvm, "Internal station added.\n"); return 0; @@ -851,7 +851,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, if (ret) return ret; - switch (status) { + switch (status & IWL_ADD_STA_STATUS_MASK) { case ADD_STA_SUCCESS: IWL_DEBUG_INFO(mvm, "RX BA Session %sed in fw\n", start ? "start" : "stopp"); @@ -909,7 +909,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, if (ret) return ret; - switch (status) { + switch (status & IWL_ADD_STA_STATUS_MASK) { case ADD_STA_SUCCESS: break; default: -- cgit v1.2.3 From 81f02ba3dbe0c9133dc4490f0a7d3acd99a89aad Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 30 Dec 2015 23:58:29 +0200 Subject: iwlwifi: mvm: add tlv for multi queue rx support Previous patches enabled the multi-queue rx path based on iwl_mvm_has_new_rx_api() which returned false by default. Change it to return the actual value based on the firmware TLV which is now defined. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index 5152987c8b8d..e2dbc67a367b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -347,6 +347,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65, IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67, + IWL_UCODE_TLV_CAPA_MULTI_QUEUE_RX_SUPPORT = (__force iwl_ucode_tlv_capa_t)68, IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION = (__force iwl_ucode_tlv_capa_t)71, IWL_UCODE_TLV_CAPA_BEACON_STORING = (__force iwl_ucode_tlv_capa_t)72, IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2 = (__force iwl_ucode_tlv_capa_t)73, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 5a34808fdeed..f87aa972fdce 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1017,8 +1017,8 @@ bool iwl_mvm_is_p2p_standalone_uapsd_supported(struct iwl_mvm *mvm) static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm) { - /* firmware flag isn't defined yet */ - return false; + return fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_MULTI_QUEUE_RX_SUPPORT); } extern const u8 iwl_mvm_ac_to_tx_fifo[]; -- cgit v1.2.3 From c257d5fb52872213f33016c0750bc2334a781700 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 24 Jan 2016 15:28:43 +0100 Subject: iwlwifi: treat iwl_parse_nvm_data() MAC addr as little endian The MAC address parameters passed to iwl_parse_nvm_data() are passed on to iwl_set_hw_address_family_8000() which treats them as little endian. Annotate them as such, and add the missing byte-swapping in mvm. While at it, add the MAC address to the error to make debugging issues with it easier. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 7 ++++--- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/nvm.c | 8 +++++--- 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 7b89bfc8c8ac..50f4cc60cf3e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -539,7 +539,7 @@ static void iwl_set_hw_address_family_8000(struct device *dev, struct iwl_nvm_data *data, const __le16 *mac_override, const __le16 *nvm_hw, - u32 mac_addr0, u32 mac_addr1) + __le32 mac_addr0, __le32 mac_addr1) { const u8 *hw_addr; @@ -583,7 +583,8 @@ static void iwl_set_hw_address_family_8000(struct device *dev, if (!is_valid_ether_addr(data->hw_addr)) IWL_ERR_DEV(dev, - "mac address from hw section is not valid\n"); + "mac address (%pM) from hw section is not valid\n", + data->hw_addr); return; } @@ -597,7 +598,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, const __le16 *nvm_calib, const __le16 *regulatory, const __le16 *mac_override, const __le16 *phy_sku, u8 tx_chains, u8 rx_chains, bool lar_fw_supported, - u32 mac_addr0, u32 mac_addr1) + __le32 mac_addr0, __le32 mac_addr1) { struct iwl_nvm_data *data; u32 sku; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h index 92466ee72806..4e8e0dc474d4 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h @@ -79,7 +79,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, const __le16 *nvm_calib, const __le16 *regulatory, const __le16 *mac_override, const __le16 *phy_sku, u8 tx_chains, u8 rx_chains, bool lar_fw_supported, - u32 mac_addr0, u32 mac_addr1); + __le32 mac_addr0, __le32 mac_addr1); /** * iwl_parse_mcc_info - parse MCC (mobile country code) info coming from FW diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c index 7a3da2da6fd0..c446e0da9789 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c @@ -300,7 +300,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) struct iwl_nvm_section *sections = mvm->nvm_sections; const __le16 *hw, *sw, *calib, *regulatory, *mac_override, *phy_sku; bool lar_enabled; - u32 mac_addr0, mac_addr1; + __le32 mac_addr0, mac_addr1; /* Checking for required sections */ if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) { @@ -337,8 +337,10 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) return NULL; /* read the mac address from WFMP registers */ - mac_addr0 = iwl_trans_read_prph(mvm->trans, WFMP_MAC_ADDR_0); - mac_addr1 = iwl_trans_read_prph(mvm->trans, WFMP_MAC_ADDR_1); + mac_addr0 = cpu_to_le32(iwl_trans_read_prph(mvm->trans, + WFMP_MAC_ADDR_0)); + mac_addr1 = cpu_to_le32(iwl_trans_read_prph(mvm->trans, + WFMP_MAC_ADDR_1)); hw = (const __le16 *)sections[mvm->cfg->nvm_hw_section_num].data; sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data; -- cgit v1.2.3 From 8812182e5df31e49cd888bafa36bcccf87787940 Mon Sep 17 00:00:00 2001 From: Avri Altman Date: Sun, 24 Jan 2016 15:18:59 +0200 Subject: iwlwifi: mvm: Remove bf_vif from iwl_power_vifs This member is actually not needed as beacon abort is only allowed for a bss station. Signed-off-by: Avri Altman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/power.c | 28 ++++++++++++-------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index 0d03b3e3cf4e..83e686dd86ee 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c @@ -577,7 +577,6 @@ void iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm, struct iwl_power_vifs { struct iwl_mvm *mvm; - struct ieee80211_vif *bf_vif; struct ieee80211_vif *bss_vif; struct ieee80211_vif *p2p_vif; struct ieee80211_vif *ap_vif; @@ -650,11 +649,6 @@ static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac, if (mvmvif->phy_ctxt) if (mvmvif->phy_ctxt->id < MAX_PHYS) power_iterator->bss_active = true; - - if (mvmvif->bf_data.bf_enabled && - !WARN_ON(power_iterator->bf_vif)) - power_iterator->bf_vif = vif; - break; default: @@ -959,21 +953,19 @@ static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm) } static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm, - struct iwl_power_vifs *vifs) + struct ieee80211_vif *vif) { - struct iwl_mvm_vif *mvmvif; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); bool ba_enable; - if (!vifs->bf_vif) + if (!mvmvif->bf_data.bf_enabled) return 0; - mvmvif = iwl_mvm_vif_from_mac80211(vifs->bf_vif); - ba_enable = !(!mvmvif->pm_enabled || mvm->ps_disabled || - !vifs->bf_vif->bss_conf.ps || + !vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif)); - return iwl_mvm_update_beacon_abort(mvm, vifs->bf_vif, ba_enable); + return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable); } int iwl_mvm_power_update_ps(struct iwl_mvm *mvm) @@ -994,7 +986,10 @@ int iwl_mvm_power_update_ps(struct iwl_mvm *mvm) if (ret) return ret; - return iwl_mvm_power_set_ba(mvm, &vifs); + if (vifs.bss_vif) + return iwl_mvm_power_set_ba(mvm, vifs.bss_vif); + + return 0; } int iwl_mvm_power_update_mac(struct iwl_mvm *mvm) @@ -1029,7 +1024,10 @@ int iwl_mvm_power_update_mac(struct iwl_mvm *mvm) return ret; } - return iwl_mvm_power_set_ba(mvm, &vifs); + if (vifs.bss_vif) + return iwl_mvm_power_set_ba(mvm, vifs.bss_vif); + + return 0; } int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm, -- cgit v1.2.3 From 416ec4f3928544fcedba5a4d98866e74ce44f369 Mon Sep 17 00:00:00 2001 From: Avri Altman Date: Sun, 24 Jan 2016 15:56:11 +0200 Subject: iwlwifi: mvm: Remove iwl_mvm_update_beacon_abort It is only called from iwl_mvm_power_set_ba() so simplify things by removing it. Signed-off-by: Avri Altman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/power.c | 37 +++++++++----------------- 1 file changed, 12 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index 83e686dd86ee..f313910cd026 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c @@ -877,26 +877,6 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags, false); } -static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - bool enable) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_beacon_filter_cmd cmd = { - IWL_BF_CMD_CONFIG_DEFAULTS, - .bf_enable_beacon_filter = cpu_to_le32(1), - }; - - if (!mvmvif->bf_data.bf_enabled) - return 0; - - if (mvm->cur_ucode == IWL_UCODE_WOWLAN) - cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3); - - mvmvif->bf_data.ba_enabled = enable; - return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false); -} - static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, struct ieee80211_vif *vif, u32 flags, bool d0i3) @@ -956,16 +936,23 @@ static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - bool ba_enable; + struct iwl_beacon_filter_cmd cmd = { + IWL_BF_CMD_CONFIG_DEFAULTS, + .bf_enable_beacon_filter = cpu_to_le32(1), + }; if (!mvmvif->bf_data.bf_enabled) return 0; - ba_enable = !(!mvmvif->pm_enabled || mvm->ps_disabled || - !vif->bss_conf.ps || - iwl_mvm_vif_low_latency(mvmvif)); + if (mvm->cur_ucode == IWL_UCODE_WOWLAN) + cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3); + + mvmvif->bf_data.ba_enabled = !(!mvmvif->pm_enabled || + mvm->ps_disabled || + !vif->bss_conf.ps || + iwl_mvm_vif_low_latency(mvmvif)); - return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable); + return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false); } int iwl_mvm_power_update_ps(struct iwl_mvm *mvm) -- cgit v1.2.3 From 854c57057390e45041a56c3d3228eb805e980c99 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 26 Jan 2016 13:17:47 +0200 Subject: iwlwifi: mvm: add new ADD_STA command version The 9000 hardware introduces the frame releaser, which keeps track of the aggregation window and notifies host of the window status. This requires in turn updating the hardware with the RX BA session window size. Firmware API was changed to enable that, update the driver accordingly. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- .../net/wireless/intel/iwlwifi/mvm/fw-api-sta.h | 66 +++++++++++++++++++++- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 4 +- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 40 ++++++++++--- drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 2 +- 4 files changed, 99 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h index 1eb3983decc3..90d911394836 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * 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 @@ -33,6 +34,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -256,6 +258,65 @@ struct iwl_mvm_keyinfo { #define IWL_ADD_STA_STATUS_MASK 0xFF #define IWL_ADD_STA_BAID_MASK 0xFF00 +/** + * struct iwl_mvm_add_sta_cmd_v7 - Add/modify a station in the fw's sta table. + * ( REPLY_ADD_STA = 0x18 ) + * @add_modify: 1: modify existing, 0: add new station + * @awake_acs: + * @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable + * AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field. + * @mac_id_n_color: the Mac context this station belongs to + * @addr[ETH_ALEN]: station's MAC address + * @sta_id: index of station in uCode's station table + * @modify_mask: STA_MODIFY_*, selects which parameters to modify vs. leave + * alone. 1 - modify, 0 - don't change. + * @station_flags: look at %iwl_sta_flags + * @station_flags_msk: what of %station_flags have changed + * @add_immediate_ba_tid: tid for which to add block-ack support (Rx) + * Set %STA_MODIFY_ADD_BA_TID to use this field, and also set + * add_immediate_ba_ssn. + * @remove_immediate_ba_tid: tid for which to remove block-ack support (Rx) + * Set %STA_MODIFY_REMOVE_BA_TID to use this field + * @add_immediate_ba_ssn: ssn for the Rx block-ack session. Used together with + * add_immediate_ba_tid. + * @sleep_tx_count: number of packets to transmit to station even though it is + * asleep. Used to synchronise PS-poll and u-APSD responses while ucode + * keeps track of STA sleep state. + * @sleep_state_flags: Look at %iwl_sta_sleep_flag. + * @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP + * mac-addr. + * @beamform_flags: beam forming controls + * @tfd_queue_msk: tfd queues used by this station + * + * The device contains an internal table of per-station information, with info + * on security keys, aggregation parameters, and Tx rates for initial Tx + * attempt and any retries (set by REPLY_TX_LINK_QUALITY_CMD). + * + * ADD_STA sets up the table entry for one station, either creating a new + * entry, or modifying a pre-existing one. + */ +struct iwl_mvm_add_sta_cmd_v7 { + u8 add_modify; + u8 awake_acs; + __le16 tid_disable_tx; + __le32 mac_id_n_color; + u8 addr[ETH_ALEN]; /* _STA_ID_MODIFY_INFO_API_S_VER_1 */ + __le16 reserved2; + u8 sta_id; + u8 modify_mask; + __le16 reserved3; + __le32 station_flags; + __le32 station_flags_msk; + u8 add_immediate_ba_tid; + u8 remove_immediate_ba_tid; + __le16 add_immediate_ba_ssn; + __le16 sleep_tx_count; + __le16 sleep_state_flags; + __le16 assoc_id; + __le16 beamform_flags; + __le32 tfd_queue_msk; +} __packed; /* ADD_STA_CMD_API_S_VER_7 */ + /** * struct iwl_mvm_add_sta_cmd - Add/modify a station in the fw's sta table. * ( REPLY_ADD_STA = 0x18 ) @@ -285,6 +346,7 @@ struct iwl_mvm_keyinfo { * mac-addr. * @beamform_flags: beam forming controls * @tfd_queue_msk: tfd queues used by this station + * @rx_ba_window: aggregation window size * * The device contains an internal table of per-station information, with info * on security keys, aggregation parameters, and Tx rates for initial Tx @@ -313,7 +375,9 @@ struct iwl_mvm_add_sta_cmd { __le16 assoc_id; __le16 beamform_flags; __le32 tfd_queue_msk; -} __packed; /* ADD_STA_CMD_API_S_VER_7 */ + __le16 rx_ba_window; + __le16 reserved; +} __packed; /* ADD_STA_CMD_API_S_VER_8 */ /** * struct iwl_mvm_add_sta_key_cmd - add/modify sta key diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index d70a1716f3e0..01476f545695 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -884,10 +884,10 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, ret = -EINVAL; break; } - ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, *ssn, true); + ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, *ssn, true, buf_size); break; case IEEE80211_AMPDU_RX_STOP: - ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false); + ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false, buf_size); break; case IEEE80211_AMPDU_TX_START: if (!iwl_enable_tx_ampdu(mvm->cfg)) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 84b7fd1c4c70..4854e79cbda8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 2015 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * 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 @@ -33,6 +34,7 @@ * * Copyright(c) 2012 - 2015 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -68,6 +70,18 @@ #include "sta.h" #include "rs.h" +/* + * New version of ADD_STA_sta command added new fields at the end of the + * structure, so sending the size of the relevant API's structure is enough to + * support both API versions. + */ +static inline int iwl_mvm_add_sta_cmd_size(struct iwl_mvm *mvm) +{ + return iwl_mvm_has_new_rx_api(mvm) ? + sizeof(struct iwl_mvm_add_sta_cmd) : + sizeof(struct iwl_mvm_add_sta_cmd_v7); +} + static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, enum nl80211_iftype iftype) { @@ -187,7 +201,8 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT); status = ADD_STA_SUCCESS; - ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(add_sta_cmd), + ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, + iwl_mvm_add_sta_cmd_size(mvm), &add_sta_cmd, &status); if (ret) return ret; @@ -357,7 +372,8 @@ int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, cmd.station_flags_msk = cpu_to_le32(STA_FLG_DRAIN_FLOW); status = ADD_STA_SUCCESS; - ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), + ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, + iwl_mvm_add_sta_cmd_size(mvm), &cmd, &status); if (ret) return ret; @@ -623,7 +639,8 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm, if (addr) memcpy(cmd.addr, addr, ETH_ALEN); - ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), + ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, + iwl_mvm_add_sta_cmd_size(mvm), &cmd, &status); if (ret) return ret; @@ -819,7 +836,7 @@ int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) #define IWL_MAX_RX_BA_SESSIONS 16 int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, - int tid, u16 ssn, bool start) + int tid, u16 ssn, bool start, u8 buf_size) { struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_add_sta_cmd cmd = {}; @@ -839,6 +856,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, if (start) { cmd.add_immediate_ba_tid = (u8) tid; cmd.add_immediate_ba_ssn = cpu_to_le16(ssn); + cmd.rx_ba_window = cpu_to_le16((u16)buf_size); } else { cmd.remove_immediate_ba_tid = (u8) tid; } @@ -846,7 +864,8 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, STA_MODIFY_REMOVE_BA_TID; status = ADD_STA_SUCCESS; - ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), + ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, + iwl_mvm_add_sta_cmd_size(mvm), &cmd, &status); if (ret) return ret; @@ -904,7 +923,8 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, cmd.tid_disable_tx = cpu_to_le16(mvm_sta->tid_disable_agg); status = ADD_STA_SUCCESS; - ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), + ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, + iwl_mvm_add_sta_cmd_size(mvm), &cmd, &status); if (ret) return ret; @@ -1640,7 +1660,8 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, }; int ret; - ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd); + ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, + iwl_mvm_add_sta_cmd_size(mvm), &cmd); if (ret) IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); } @@ -1731,7 +1752,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC | CMD_WANT_ASYNC_CALLBACK, - sizeof(cmd), &cmd); + iwl_mvm_add_sta_cmd_size(mvm), &cmd); if (ret) IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); } @@ -1766,7 +1787,8 @@ void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm, }; int ret; - ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd); + ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, + iwl_mvm_add_sta_cmd_size(mvm), &cmd); if (ret) IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index 39fdf5224e81..e3b9446ee995 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h @@ -401,7 +401,7 @@ void iwl_mvm_rx_eosp_notif(struct iwl_mvm *mvm, /* AMPDU */ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, - int tid, u16 ssn, bool start); + int tid, u16 ssn, bool start, u8 buf_size); int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn); int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, -- cgit v1.2.3 From 6ad6c01fa74f649722eeca7308dc1fc4e43235cd Mon Sep 17 00:00:00 2001 From: Gregory Greenman Date: Wed, 27 Jan 2016 00:10:15 +0200 Subject: iwlwifi: mvm: rs: fix TPC action decision algorithm Decreasing Tx power is allowed only when success ratio is above the threshold defined in the algorithm. Add this condition. Signed-off-by: Gregory Greenman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 7bb6fd0e4391..986e12ab9dc2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -2040,7 +2040,8 @@ static enum tpc_action rs_get_tpc_action(struct iwl_mvm *mvm, } /* try decreasing first if applicable */ - if (weak != TPC_INVALID) { + if (sr >= RS_PERCENT(IWL_MVM_RS_TPC_SR_NO_INCREASE) && + weak != TPC_INVALID) { if (weak_tpt == IWL_INVALID_VALUE && (strong_tpt == IWL_INVALID_VALUE || current_tpt >= strong_tpt)) { -- cgit v1.2.3 From 43413a975d06e5e34016751fac27e29ec3d4d10f Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Thu, 31 Dec 2015 11:49:18 +0200 Subject: iwlwifi: mvm: support rss queues configuration command 9000 series supports multi-queue rx. The hardware needs to be configured with the hash functions to perform and indirection table that maps hash results to the relevant CPUs\queues. Support this configuration. Add debugfs hook to configure the indirection table in order to enable performance analysis. The configuration is stateless, receives a partial or full pattern and sends the command to the firmware. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 44 ++++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h | 33 +++++++++++++++- drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h | 2 + drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 29 ++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 4 ++ 6 files changed, 111 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 5c0f93997b7b..005cc09757d2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * 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 @@ -943,6 +944,47 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf, return count; } +static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm, + char *buf, size_t count, + loff_t *ppos) +{ + struct iwl_rss_config_cmd cmd = { + .flags = cpu_to_le32(IWL_RSS_ENABLE), + .hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP | + IWL_RSS_HASH_TYPE_IPV4_PAYLOAD | + IWL_RSS_HASH_TYPE_IPV6_TCP | + IWL_RSS_HASH_TYPE_IPV6_PAYLOAD, + }; + int ret, i, num_repeats, nbytes = count / 2; + + ret = hex2bin(cmd.indirection_table, buf, nbytes); + if (ret) + return ret; + + /* + * The input is the redirection table, partial or full. + * Repeat the pattern if needed. + * For example, input of 01020F will be repeated 42 times, + * indirecting RSS hash results to queues 1, 2, 15 (skipping + * queues 3 - 14). + */ + num_repeats = ARRAY_SIZE(cmd.indirection_table) / nbytes; + for (i = 1; i < num_repeats; i++) + memcpy(&cmd.indirection_table[i * nbytes], + cmd.indirection_table, nbytes); + /* handle cut in the middle pattern for the last places */ + memcpy(&cmd.indirection_table[i * nbytes], cmd.indirection_table, + ARRAY_SIZE(cmd.indirection_table) % nbytes); + + memcpy(cmd.secret_key, mvm->secret_key, ARRAY_SIZE(cmd.secret_key)); + + mutex_lock(&mvm->mutex); + ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd); + mutex_unlock(&mvm->mutex); + + return ret ?: count; +} + static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -1455,6 +1497,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8); MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64); MVM_DEBUGFS_WRITE_FILE_OPS(cont_recording, 8); +MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl, 16); #ifdef CONFIG_IWLWIFI_BCAST_FILTERING MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); @@ -1499,6 +1542,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR); MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, S_IWUSR); MVM_DEBUGFS_ADD_FILE(cont_recording, mvm->debugfs_dir, S_IWUSR); + MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, S_IWUSR); if (!debugfs_create_bool("enable_scan_iteration_notif", S_IRUSR | S_IWUSR, mvm->debugfs_dir, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h index ab467cb9b97c..b45c61e1f45c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h @@ -7,7 +7,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH - * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2015 - 2016 Intel Deutschland GmbH * * 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 @@ -34,7 +34,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH - * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2015 - 2016 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -362,4 +362,33 @@ struct iwl_frame_release { __le16 nssn; }; +enum iwl_rss_hash_func_en { + IWL_RSS_HASH_TYPE_IPV4_TCP, + IWL_RSS_HASH_TYPE_IPV4_UDP, + IWL_RSS_HASH_TYPE_IPV4_PAYLOAD, + IWL_RSS_HASH_TYPE_IPV6_TCP, + IWL_RSS_HASH_TYPE_IPV6_UDP, + IWL_RSS_HASH_TYPE_IPV6_PAYLOAD, +}; + +#define IWL_RSS_HASH_KEY_CNT 10 +#define IWL_RSS_INDIRECTION_TABLE_SIZE 128 +#define IWL_RSS_ENABLE 1 + +/** + * struct iwl_rss_config_cmd - RSS (Receive Side Scaling) configuration + * + * @flags: 1 - enable, 0 - disable + * @hash_mask: Type of RSS to use. Values are from %iwl_rss_hash_func_en + * @secret_key: 320 bit input of random key configuration from driver + * @indirection_table: indirection table + */ +struct iwl_rss_config_cmd { + __le32 flags; + u8 hash_mask; + u8 reserved[3]; + __le32 secret_key[IWL_RSS_HASH_KEY_CNT]; + u8 indirection_table[IWL_RSS_INDIRECTION_TABLE_SIZE]; +} __packed; /* RSS_CONFIG_CMD_API_S_VER_1 */ + #endif /* __fw_api_rx_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h index b6b57273b8ba..f332497e29d1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h @@ -213,6 +213,8 @@ enum { MFUART_LOAD_NOTIFICATION = 0xb1, + RSS_CONFIG_CMD = 0xb3, + REPLY_RX_PHY_CMD = 0xc0, REPLY_RX_MPDU_CMD = 0xc1, FRAME_RELEASE = 0xc3, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 4ed5180c547b..070e2af05ca2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * 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 @@ -107,6 +108,24 @@ static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant) sizeof(tx_ant_cmd), &tx_ant_cmd); } +static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm) +{ + int i; + struct iwl_rss_config_cmd cmd = { + .flags = cpu_to_le32(IWL_RSS_ENABLE), + .hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP | + IWL_RSS_HASH_TYPE_IPV4_PAYLOAD | + IWL_RSS_HASH_TYPE_IPV6_TCP | + IWL_RSS_HASH_TYPE_IPV6_PAYLOAD, + }; + + for (i = 0; i < ARRAY_SIZE(cmd.indirection_table); i++) + cmd.indirection_table[i] = i % mvm->trans->num_rx_queues; + memcpy(cmd.secret_key, mvm->secret_key, ARRAY_SIZE(cmd.secret_key)); + + return iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd); +} + static void iwl_free_fw_paging(struct iwl_mvm *mvm) { int i; @@ -894,6 +913,16 @@ int iwl_mvm_up(struct iwl_mvm *mvm) if (ret) goto error; + /* Init RSS configuration */ + if (iwl_mvm_has_new_rx_api(mvm)) { + ret = iwl_send_rss_cfg_cmd(mvm); + if (ret) { + IWL_ERR(mvm, "Failed to configure RSS queues: %d\n", + ret); + goto error; + } + } + /* init the fw <-> mac80211 STA mapping */ for (i = 0; i < IWL_MVM_STATION_COUNT; i++) RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index f87aa972fdce..747f7eb80f47 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -647,6 +647,7 @@ struct iwl_mvm { atomic_t pending_frames[IWL_MVM_STATION_COUNT]; u32 tfd_drained[IWL_MVM_STATION_COUNT]; u8 rx_ba_sessions; + u32 secret_key[IWL_RSS_HASH_KEY_CNT]; /* configured by mac80211 */ u32 rts_threshold; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 3c869ad6aaec..325ff8aa33f5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -347,6 +347,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = { HCMD_NAME(MAC_PM_POWER_TABLE), HCMD_NAME(TDLS_CHANNEL_SWITCH_NOTIFICATION), HCMD_NAME(MFUART_LOAD_NOTIFICATION), + HCMD_NAME(RSS_CONFIG_CMD), HCMD_NAME(SCAN_ITERATION_COMPLETE_UMAC), HCMD_NAME(REPLY_RX_PHY_CMD), HCMD_NAME(REPLY_RX_MPDU_CMD), @@ -651,6 +652,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, iwl_mvm_tof_init(mvm); + /* init RSS hash key */ + get_random_bytes(mvm->secret_key, ARRAY_SIZE(mvm->secret_key)); + return op_mode; out_unregister: -- cgit v1.2.3 From bce977310416a2b6c9ad774dfe2071eaacd3d90b Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Mon, 25 Jan 2016 18:14:49 +0200 Subject: iwlwifi: pcie: enable multi-queue rx path Previous patches enabled new 9000 hardware DMA for one queue only. Enable the actual multi-queue path and configuration now. This requires also per-queue NAPI struct. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 35 +++++++++++++++++----- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 14 +-------- 3 files changed, 29 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 7bc02e0cdd93..2f959162d045 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -136,6 +136,7 @@ struct iwl_rxq { struct iwl_rb_status *rb_stts; dma_addr_t rb_stts_dma; spinlock_t lock; + struct napi_struct napi; struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; }; @@ -345,7 +346,6 @@ struct iwl_trans_pcie { struct iwl_drv *drv; struct net_device napi_dev; - struct napi_struct napi; struct __percpu iwl_tso_hdr_page *tso_hdr_page; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index a385f3cddb5d..51314e56209d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -2,6 +2,7 @@ * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -730,7 +731,7 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) iwl_set_bit(trans, CSR_INT_COALESCING, IWL_HOST_INT_OPER_MODE); } -static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) +static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); u32 rb_size, enabled = 0; @@ -759,13 +760,13 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) for (i = 0; i < trans->num_rx_queues; i++) { /* Tell device where to find RBD free table in DRAM */ iwl_pcie_write_prph_64(trans, RFH_Q_FRBDCB_BA_LSB(i), - (u64)(rxq->bd_dma)); + (u64)(trans_pcie->rxq[i].bd_dma)); /* Tell device where to find RBD used table in DRAM */ iwl_pcie_write_prph_64(trans, RFH_Q_URBDCB_BA_LSB(i), - (u64)(rxq->used_bd_dma)); + (u64)(trans_pcie->rxq[i].used_bd_dma)); /* Tell device where in DRAM to update its Rx status */ iwl_pcie_write_prph_64(trans, RFH_Q_URBD_STTS_WPTR_LSB(i), - rxq->rb_stts_dma); + trans_pcie->rxq[i].rb_stts_dma); /* Reset device indice tables */ iwl_write_prph(trans, RFH_Q_FRBDCB_WIDX(i), 0); iwl_write_prph(trans, RFH_Q_FRBDCB_RIDX(i), 0); @@ -808,6 +809,12 @@ static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq) rxq->used_count = 0; } +static int iwl_pcie_dummy_napi_poll(struct napi_struct *napi, int budget) +{ + WARN_ON(1); + return 0; +} + int iwl_pcie_rx_init(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -857,6 +864,10 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) iwl_pcie_rx_init_rxb_lists(rxq); + if (!rxq->napi.poll) + netif_napi_add(&trans_pcie->napi_dev, &rxq->napi, + iwl_pcie_dummy_napi_poll, 64); + spin_unlock(&rxq->lock); } @@ -878,7 +889,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL, def_rxq); if (trans->cfg->mq_rx_supported) { - iwl_pcie_rx_mq_hw_init(trans, def_rxq); + iwl_pcie_rx_mq_hw_init(trans); } else { iwl_pcie_rxq_restock(trans, def_rxq); iwl_pcie_rx_hw_init(trans, def_rxq); @@ -940,6 +951,9 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) rxq->used_bd, rxq->used_bd_dma); rxq->used_bd_dma = 0; rxq->used_bd = NULL; + + if (rxq->napi.poll) + netif_napi_del(&rxq->napi); } kfree(trans_pcie->rxq); } @@ -1055,7 +1069,12 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, index = SEQ_TO_INDEX(sequence); cmd_index = get_cmd_index(&txq->q, index); - iwl_op_mode_rx(trans->op_mode, &trans_pcie->napi, &rxcb); + if (rxq->id == 0) + iwl_op_mode_rx(trans->op_mode, &rxq->napi, + &rxcb); + else + iwl_op_mode_rx_rss(trans->op_mode, &rxq->napi, + &rxcb, rxq->id); if (reclaim) { kzfree(txq->entries[cmd_index].free_buf); @@ -1236,8 +1255,8 @@ restart: if (unlikely(emergency && count)) iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC, rxq); - if (trans_pcie->napi.poll) - napi_gro_flush(&trans_pcie->napi, false); + if (rxq->napi.poll) + napi_gro_flush(&rxq->napi, false); } /* diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index abe091698471..b796952da644 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1428,12 +1428,6 @@ static void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr, iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val); } -static int iwl_pcie_dummy_napi_poll(struct napi_struct *napi, int budget) -{ - WARN_ON(1); - return 0; -} - static void iwl_trans_pcie_configure(struct iwl_trans *trans, const struct iwl_trans_config *trans_cfg) { @@ -1470,11 +1464,8 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, * As this function may be called again in some corner cases don't * do anything if NAPI was already initialized. */ - if (!trans_pcie->napi.poll) { + if (trans_pcie->napi_dev.reg_state != NETREG_DUMMY) init_dummy_netdev(&trans_pcie->napi_dev); - netif_napi_add(&trans_pcie->napi_dev, &trans_pcie->napi, - iwl_pcie_dummy_napi_poll, 64); - } } void iwl_trans_pcie_free(struct iwl_trans *trans) @@ -1498,9 +1489,6 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) pci_release_regions(trans_pcie->pci_dev); pci_disable_device(trans_pcie->pci_dev); - if (trans_pcie->napi.poll) - netif_napi_del(&trans_pcie->napi); - iwl_pcie_free_fw_monitor(trans); for_each_possible_cpu(i) { -- cgit v1.2.3 From d56a7801b544d63b0d32bc8bca0c12a259b1d8e9 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 26 Jan 2016 12:35:13 +0200 Subject: iwlwifi: pcie: update iwl_mpdu_desc fields Final API of iwl_mpdu_desc has a change in the order of the fields and does not include energy from the third antenna (which is perfectly fine, since we don't have one). Update the structure accordingly. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h | 6 +++--- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 11 ++++------- 2 files changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h index b45c61e1f45c..df939f51d9b9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h @@ -347,11 +347,11 @@ struct iwl_rx_mpdu_desc { /* DW8 */ __le32 filter_match; /* DW9 */ - __le32 gp2_on_air_rise; - /* DW10 */ __le32 rate_n_flags; + /* DW10 */ + u8 energy_a, energy_b, channel, reserved; /* DW11 */ - u8 energy_a, energy_b, energy_c, channel; + __le32 gp2_on_air_rise; /* DW12 & DW13 */ __le64 tsf_on_air_rise; } __packed; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 4cce37238a08..615dea143d4e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -201,25 +201,22 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, struct iwl_rx_mpdu_desc *desc, struct ieee80211_rx_status *rx_status) { - int energy_a, energy_b, energy_c, max_energy; + int energy_a, energy_b, max_energy; energy_a = desc->energy_a; energy_a = energy_a ? -energy_a : S8_MIN; energy_b = desc->energy_b; energy_b = energy_b ? -energy_b : S8_MIN; - energy_c = desc->energy_c; - energy_c = energy_c ? -energy_c : S8_MIN; max_energy = max(energy_a, energy_b); - max_energy = max(max_energy, energy_c); - IWL_DEBUG_STATS(mvm, "energy In A %d B %d C %d , and max %d\n", - energy_a, energy_b, energy_c, max_energy); + IWL_DEBUG_STATS(mvm, "energy In A %d B %d, and max %d\n", + energy_a, energy_b, max_energy); rx_status->signal = max_energy; rx_status->chains = 0; /* TODO: phy info */ rx_status->chain_signal[0] = energy_a; rx_status->chain_signal[1] = energy_b; - rx_status->chain_signal[2] = energy_c; + rx_status->chain_signal[2] = S8_MIN; } static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, -- cgit v1.2.3 From c89e333d5e4a27f736c960b29040b261c21563a5 Mon Sep 17 00:00:00 2001 From: Andrei Otcheretianski Date: Tue, 26 Jan 2016 18:12:28 +0200 Subject: iwlwifi: mvm: allow to disable beacon filtering for AP/GO interface When in AP mode we need to filter in beacons from other APs to update HT operation mode. As a power optimization the beacons are filtered out when there are no associated stations. As a result, when there are no associated stations, we will not update the HT operation mode until a station connects. Add a debugfs parameter that allows to disable this optimization. Signed-off-by: Andrei Otcheretianski Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 3 +++ drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 6 ++++++ drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 1 + 4 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 005cc09757d2..c529e5355803 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1548,6 +1548,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) mvm->debugfs_dir, &mvm->scan_iter_notif_enabled)) goto err; + if (!debugfs_create_bool("drop_bcn_ap_mode", S_IRUSR | S_IWUSR, + mvm->debugfs_dir, &mvm->drop_bcn_ap_mode)) + goto err; #ifdef CONFIG_IWLWIFI_BCAST_FILTERING if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 62927f567afc..535134d639e0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -744,7 +744,7 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm, * wake-ups. */ cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); - if (mvmvif->ap_assoc_sta_count) { + if (mvmvif->ap_assoc_sta_count || !mvm->drop_bcn_ap_mode) { cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON); IWL_DEBUG_HC(mvm, "Asking FW to pass beacons\n"); } else { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 747f7eb80f47..ebe37bb0ce4c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -859,6 +859,12 @@ struct iwl_mvm { u32 ciphers[6]; struct iwl_mvm_tof_data tof_data; + + /* + * Drop beacons from other APs in AP mode when there are no connected + * clients. + */ + bool drop_bcn_ap_mode; }; /* Extract MVM priv from op_mode and _hw */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 325ff8aa33f5..09a94a5efb61 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -492,6 +492,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, } mvm->sf_state = SF_UNINIT; mvm->cur_ucode = IWL_UCODE_INIT; + mvm->drop_bcn_ap_mode = true; mutex_init(&mvm->mutex); mutex_init(&mvm->d0i3_suspend_mutex); -- cgit v1.2.3 From b97baa3e22e18dac42001e665cf27ad1211bf878 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 Jan 2016 12:09:56 -0200 Subject: [media] hdpvr: hide unused variable The i2c client pointer is only used when CONFIG_I2C is set, and otherwise produces a compile-time warning: drivers/media/usb/hdpvr/hdpvr-core.c: In function 'hdpvr_probe': drivers/media/usb/hdpvr/hdpvr-core.c:276:21: error: unused variable 'client' [-Werror=unused-variable] This uses the same #ifdef to hide the variable when the code using it is hidden. Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/hdpvr/hdpvr-core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c index 3fc64197b4e6..08f0ca7aa012 100644 --- a/drivers/media/usb/hdpvr/hdpvr-core.c +++ b/drivers/media/usb/hdpvr/hdpvr-core.c @@ -273,7 +273,9 @@ static int hdpvr_probe(struct usb_interface *interface, struct hdpvr_device *dev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; +#if IS_ENABLED(CONFIG_I2C) struct i2c_client *client; +#endif size_t buffer_size; int i; int retval = -ENOMEM; -- cgit v1.2.3 From 733d0def3ebdd1d088330d904149af21fa4b9ae2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 Jan 2016 12:09:58 -0200 Subject: [media] b2c2: flexcop: avoid unused function warnings The flexcop driver has two functions that are normally used, except when multiple frontend drivers are disabled: drivers/media/common/b2c2/flexcop-fe-tuner.c:42:12: warning: 'flexcop_set_voltage' defined but not used [-Wunused-function] drivers/media/common/b2c2/flexcop-fe-tuner.c:71:12: warning: 'flexcop_sleep' defined but not used [-Wunused-function] This avoids the build warning by updating the #ifdef for flexcop_set_voltage to the exact condition under which it is used. For flexcop_sleep, the condition is rather complex, so I resort to marking it as __maybe_unused, so the compiler can silently drop it. Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/b2c2/flexcop-fe-tuner.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/common/b2c2/flexcop-fe-tuner.c b/drivers/media/common/b2c2/flexcop-fe-tuner.c index 9c59f4306883..f5956402fc69 100644 --- a/drivers/media/common/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/common/b2c2/flexcop-fe-tuner.c @@ -38,7 +38,7 @@ static int flexcop_fe_request_firmware(struct dvb_frontend *fe, #endif /* lnb control */ -#if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299) +#if (FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299)) && FE_SUPPORTED(PLL) static int flexcop_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) { @@ -68,7 +68,7 @@ static int flexcop_set_voltage(struct dvb_frontend *fe, #endif #if FE_SUPPORTED(S5H1420) || FE_SUPPORTED(STV0299) || FE_SUPPORTED(MT312) -static int flexcop_sleep(struct dvb_frontend* fe) +static int __maybe_unused flexcop_sleep(struct dvb_frontend* fe) { struct flexcop_device *fc = fe->dvb->priv; if (fc->fe_sleep) -- cgit v1.2.3 From 7c8fe516bd81d991feb73ccd969ec29850af3013 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 Jan 2016 19:46:02 -0200 Subject: [media] v4l: remove MEDIA_TUNER dependency for VIDEO_TUNER em28xx selects VIDEO_TUNER, which has a dependency on MEDIA_TUNER, so we get a Kconfig warning if that is disabled: warning: (VIDEO_PVRUSB2 && VIDEO_USBVISION && VIDEO_GO7007 && VIDEO_AU0828_V4L2 && VIDEO_CX231XX && VIDEO_TM6000 && VIDEO_EM28XX && VIDEO_IVTV && VIDEO_MXB && VIDEO_CX18 && VIDEO_CX23885 && VIDEO_CX88 && VIDEO_BT848 && VIDEO_SAA7134 && VIDEO_SAA7164) selects VIDEO_TUNER which has unmet direct dependencies (MEDIA_SUPPORT && MEDIA_TUNER) VIDEO_TUNER does not actually depend on MEDIA_TUNER, and the dependency does nothing except cause the above warning, so let's remove it. Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig index 9beece00869b..29b3436d0910 100644 --- a/drivers/media/v4l2-core/Kconfig +++ b/drivers/media/v4l2-core/Kconfig @@ -37,7 +37,6 @@ config VIDEO_PCI_SKELETON # Used by drivers that need tuner.ko config VIDEO_TUNER tristate - depends on MEDIA_TUNER # Used by drivers that need v4l2-mem2mem.ko config V4L2_MEM2MEM_DEV -- cgit v1.2.3 From 329d88da4df9a96da43018aceabd3a06e6a7e7ae Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 12:03:23 -0200 Subject: [media] media: i2c: Don't export ir-kbd-i2c module alias This is a partial revert of commit ed8d1cf07cb16d ("[media] Export I2C module alias information in missing drivers") that exported the module aliases for the I2C drivers that were missing to make autoload to work. But there is a bug report [0] that auto load of the ir-kbd-i2c driver cause the Hauppauge HD-PVR driver to not behave correctly. This is a hdpvr latent bug that was just exposed by ir-kbd-i2c module autoloading working and will also happen if the I2C driver is built-in or a user calls modprobe to load the module and register the driver. But there is a regression experimented by users so until the real bug is fixed, let's not export the module alias for the ir-kbd-i2c driver even when this just masks the actual issue. [0]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=810726 Fixes: ed8d1cf07cb1 ("[media] Export I2C module alias information in missing drivers") Cc: # 4.3+ Signed-off-by: Javier Martinez Canillas --- drivers/media/i2c/ir-kbd-i2c.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index 830491960add..bf82726fd3f4 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c @@ -478,7 +478,6 @@ static const struct i2c_device_id ir_kbd_id[] = { { "ir_rx_z8f0811_hdpvr", 0 }, { } }; -MODULE_DEVICE_TABLE(i2c, ir_kbd_id); static struct i2c_driver ir_kbd_driver = { .driver = { -- cgit v1.2.3 From d40ec6fdb0b03b7be4c7923a3da0e46bf943740a Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 27 Jan 2016 21:49:33 -0200 Subject: [media] media: Fix media_open() to clear filp->private_data in error leg Fix media_open() to clear filp->private_data when file open fails. Signed-off-by: Shuah Khan Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-devnode.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c index cea35bf20011..29409f440f1c 100644 --- a/drivers/media/media-devnode.c +++ b/drivers/media/media-devnode.c @@ -181,6 +181,7 @@ static int media_open(struct inode *inode, struct file *filp) ret = mdev->fops->open(filp); if (ret) { put_device(&mdev->dev); + filp->private_data = NULL; return ret; } } -- cgit v1.2.3 From 3801bc7d1b8dd70d47a92e58d6fb5653c10b7c95 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Sat, 30 Jan 2016 18:10:52 -0200 Subject: [media] media: Media Controller fix to not let stream_count go negative Change media_entity_pipeline_stop() to not decrement stream_count of an inactive media pipeline. Doing so, results in preventing starting the pipeline. Signed-off-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-entity.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index e89d85a7d31b..f2e43603d6d2 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -452,9 +452,12 @@ error: media_entity_graph_walk_start(graph, entity_err); while ((entity_err = media_entity_graph_walk_next(graph))) { - entity_err->stream_count--; - if (entity_err->stream_count == 0) - entity_err->pipe = NULL; + /* don't let the stream_count go negative */ + if (entity->stream_count > 0) { + entity_err->stream_count--; + if (entity_err->stream_count == 0) + entity_err->pipe = NULL; + } /* * We haven't increased stream_count further than this @@ -486,9 +489,12 @@ void media_entity_pipeline_stop(struct media_entity *entity) media_entity_graph_walk_start(graph, entity); while ((entity = media_entity_graph_walk_next(graph))) { - entity->stream_count--; - if (entity->stream_count == 0) - entity->pipe = NULL; + /* don't let the stream_count go negative */ + if (entity->stream_count > 0) { + entity->stream_count--; + if (entity->stream_count == 0) + entity->pipe = NULL; + } } if (!--pipe->streaming_count) -- cgit v1.2.3 From 6b3f99989eb73e5250bba9dfeaa852939acfbf70 Mon Sep 17 00:00:00 2001 From: Abhilash Jindal Date: Sun, 31 Jan 2016 03:47:31 -0200 Subject: [media] dvb-frontend: Use boottime Wall time obtained from ktime_get_real is susceptible to sudden jumps due to user setting the time or due to NTP. Boot time is constantly increasing time better suited for comparing two timestamps. [mchehab@osg.samsung.com: fix trivial merge conflicts] Signed-off-by: Abhilash Jindal Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 8 ++++---- drivers/media/dvb-frontends/stv0299.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 40080645341e..03cc508b8c42 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -899,10 +899,10 @@ void dvb_frontend_sleep_until(ktime_t *waketime, u32 add_usec) s32 delta; *waketime = ktime_add_us(*waketime, add_usec); - delta = ktime_us_delta(ktime_get_real(), *waketime); + delta = ktime_us_delta(ktime_get_boottime(), *waketime); if (delta > 2500) { msleep((delta - 1500) / 1000); - delta = ktime_us_delta(ktime_get_real(), *waketime); + delta = ktime_us_delta(ktime_get_boottime(), *waketime); } if (delta > 0) udelay(delta); @@ -2451,7 +2451,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file, u8 last = 1; if (dvb_frontend_debug) printk("%s switch command: 0x%04lx\n", __func__, swcmd); - nexttime = ktime_get_real(); + nexttime = ktime_get_boottime(); if (dvb_frontend_debug) tv[0] = nexttime; /* before sending a command, initialize by sending @@ -2462,7 +2462,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file, for (i = 0; i < 9; i++) { if (dvb_frontend_debug) - tv[i+1] = ktime_get_real(); + tv[i+1] = ktime_get_boottime(); if ((swcmd & 0x01) != last) { /* set voltage to (last ? 13V : 18V) */ fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18); diff --git a/drivers/media/dvb-frontends/stv0299.c b/drivers/media/dvb-frontends/stv0299.c index a8177807fb65..c43f36d32340 100644 --- a/drivers/media/dvb-frontends/stv0299.c +++ b/drivers/media/dvb-frontends/stv0299.c @@ -422,7 +422,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long if (debug_legacy_dish_switch) printk ("%s switch command: 0x%04lx\n",__func__, cmd); - nexttime = ktime_get_real(); + nexttime = ktime_get_boottime(); if (debug_legacy_dish_switch) tv[0] = nexttime; stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */ @@ -431,7 +431,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long for (i=0; i<9; i++) { if (debug_legacy_dish_switch) - tv[i+1] = ktime_get_real(); + tv[i+1] = ktime_get_boottime(); if((cmd & 0x01) != last) { /* set voltage to (last ? 13V : 18V) */ stv0299_writeregI (state, 0x0c, reg0x0c | (last ? lv_mask : 0x50)); -- cgit v1.2.3 From 8eee1d3ed5b6fc8e14389567c9a6f53f82bb7224 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 1 Feb 2016 11:33:21 -0500 Subject: libata: fix sff host state machine locking while polling The bulk of ATA host state machine is implemented by ata_sff_hsm_move(). The function is called from either the interrupt handler or, if polling, a work item. Unlike from the interrupt path, the polling path calls the function without holding the host lock and ata_sff_hsm_move() selectively grabs the lock. This is completely broken. If an IRQ triggers while polling is in progress, the two can easily race and end up accessing the hardware and updating state machine state at the same time. This can put the state machine in an illegal state and lead to a crash like the following. kernel BUG at drivers/ata/libata-sff.c:1302! invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN Modules linked in: CPU: 1 PID: 10679 Comm: syz-executor Not tainted 4.5.0-rc1+ #300 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 task: ffff88002bd00000 ti: ffff88002e048000 task.ti: ffff88002e048000 RIP: 0010:[] [] ata_sff_hsm_move+0x619/0x1c60 ... Call Trace: [] __ata_sff_port_intr+0x1e1/0x3a0 drivers/ata/libata-sff.c:1584 [] ata_bmdma_port_intr+0x71/0x400 drivers/ata/libata-sff.c:2877 [< inline >] __ata_sff_interrupt drivers/ata/libata-sff.c:1629 [] ata_bmdma_interrupt+0x253/0x580 drivers/ata/libata-sff.c:2902 [] handle_irq_event_percpu+0x108/0x7e0 kernel/irq/handle.c:157 [] handle_irq_event+0xa7/0x140 kernel/irq/handle.c:205 [] handle_edge_irq+0x1e3/0x8d0 kernel/irq/chip.c:623 [< inline >] generic_handle_irq_desc include/linux/irqdesc.h:146 [] handle_irq+0x10c/0x2a0 arch/x86/kernel/irq_64.c:78 [] do_IRQ+0x7d/0x1a0 arch/x86/kernel/irq.c:240 [] common_interrupt+0x8c/0x8c arch/x86/entry/entry_64.S:520 [< inline >] rcu_lock_acquire include/linux/rcupdate.h:490 [< inline >] rcu_read_lock include/linux/rcupdate.h:874 [] filemap_map_pages+0x131/0xba0 mm/filemap.c:2145 [< inline >] do_fault_around mm/memory.c:2943 [< inline >] do_read_fault mm/memory.c:2962 [< inline >] do_fault mm/memory.c:3133 [< inline >] handle_pte_fault mm/memory.c:3308 [< inline >] __handle_mm_fault mm/memory.c:3418 [] handle_mm_fault+0x2516/0x49a0 mm/memory.c:3447 [] __do_page_fault+0x376/0x960 arch/x86/mm/fault.c:1238 [] trace_do_page_fault+0xe8/0x420 arch/x86/mm/fault.c:1331 [] do_async_page_fault+0x14/0xd0 arch/x86/kernel/kvm.c:264 [] async_page_fault+0x28/0x30 arch/x86/entry/entry_64.S:986 Fix it by ensuring that the polling path is holding the host lock before entering ata_sff_hsm_move() so that all hardware accesses and state updates are performed under the host lock. Signed-off-by: Tejun Heo Reported-and-tested-by: Dmitry Vyukov Link: http://lkml.kernel.org/g/CACT4Y+b_JsOxJu2EZyEf+mOXORc_zid5V1-pLZSroJVxyWdSpw@mail.gmail.com Cc: stable@vger.kernel.org --- drivers/ata/libata-sff.c | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 608677df4f49..051b6158d1b7 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -997,12 +997,9 @@ static inline int ata_hsm_ok_in_wq(struct ata_port *ap, static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) { struct ata_port *ap = qc->ap; - unsigned long flags; if (ap->ops->error_handler) { if (in_wq) { - spin_lock_irqsave(ap->lock, flags); - /* EH might have kicked in while host lock is * released. */ @@ -1014,8 +1011,6 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) } else ata_port_freeze(ap); } - - spin_unlock_irqrestore(ap->lock, flags); } else { if (likely(!(qc->err_mask & AC_ERR_HSM))) ata_qc_complete(qc); @@ -1024,10 +1019,8 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) } } else { if (in_wq) { - spin_lock_irqsave(ap->lock, flags); ata_sff_irq_on(ap); ata_qc_complete(qc); - spin_unlock_irqrestore(ap->lock, flags); } else ata_qc_complete(qc); } @@ -1048,9 +1041,10 @@ int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, { struct ata_link *link = qc->dev->link; struct ata_eh_info *ehi = &link->eh_info; - unsigned long flags = 0; int poll_next; + lockdep_assert_held(ap->lock); + WARN_ON_ONCE((qc->flags & ATA_QCFLAG_ACTIVE) == 0); /* Make sure ata_sff_qc_issue() does not throw things @@ -1112,14 +1106,6 @@ fsm_start: } } - /* Send the CDB (atapi) or the first data block (ata pio out). - * During the state transition, interrupt handler shouldn't - * be invoked before the data transfer is complete and - * hsm_task_state is changed. Hence, the following locking. - */ - if (in_wq) - spin_lock_irqsave(ap->lock, flags); - if (qc->tf.protocol == ATA_PROT_PIO) { /* PIO data out protocol. * send first data block. @@ -1135,9 +1121,6 @@ fsm_start: /* send CDB */ atapi_send_cdb(ap, qc); - if (in_wq) - spin_unlock_irqrestore(ap->lock, flags); - /* if polling, ata_sff_pio_task() handles the rest. * otherwise, interrupt handler takes over from here. */ @@ -1362,12 +1345,14 @@ static void ata_sff_pio_task(struct work_struct *work) u8 status; int poll_next; + spin_lock_irq(ap->lock); + BUG_ON(ap->sff_pio_task_link == NULL); /* qc can be NULL if timeout occurred */ qc = ata_qc_from_tag(ap, link->active_tag); if (!qc) { ap->sff_pio_task_link = NULL; - return; + goto out_unlock; } fsm_start: @@ -1382,11 +1367,14 @@ fsm_start: */ status = ata_sff_busy_wait(ap, ATA_BUSY, 5); if (status & ATA_BUSY) { + spin_unlock_irq(ap->lock); ata_msleep(ap, 2); + spin_lock_irq(ap->lock); + status = ata_sff_busy_wait(ap, ATA_BUSY, 10); if (status & ATA_BUSY) { ata_sff_queue_pio_task(link, ATA_SHORT_PAUSE); - return; + goto out_unlock; } } @@ -1403,6 +1391,8 @@ fsm_start: */ if (poll_next) goto fsm_start; +out_unlock: + spin_unlock_irq(ap->lock); } /** -- cgit v1.2.3 From a41c8882592fb80458959b10e37632ce030b68ca Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Thu, 28 Jan 2016 15:19:23 -0800 Subject: drm/i915/skl: Fix DMC load on Skylake J0 and K0 The driver does not load firmware for unknown steppings, so these new steppings must be added to the list. Cc: Rodrigo Vivi Signed-off-by: Mat Martineau Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1454023163-25469-1-git-send-email-mathew.j.martineau@linux.intel.com --- drivers/gpu/drm/i915/intel_csr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 5c2f9a40c81b..2a7ec3141c8d 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -179,7 +179,8 @@ static const struct stepping_info kbl_stepping_info[] = { static const struct stepping_info skl_stepping_info[] = { {'A', '0'}, {'B', '0'}, {'C', '0'}, {'D', '0'}, {'E', '0'}, {'F', '0'}, - {'G', '0'}, {'H', '0'}, {'I', '0'} + {'G', '0'}, {'H', '0'}, {'I', '0'}, + {'J', '0'}, {'K', '0'} }; static const struct stepping_info bxt_stepping_info[] = { -- cgit v1.2.3 From 02c3b0bd69a537557484e46a5937874a2d2ad454 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 25 Jan 2016 23:24:20 +0100 Subject: mtd: cs553x: Fix dependencies for !HAS_IOMEM archs Not every arch has io memory nor can this driver ever work on UML/i386. So, unbreak the build by fixing the dependencies. Signed-off-by: Richard Weinberger Signed-off-by: Brian Norris --- drivers/mtd/nand/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 545d82b100b6..b253654140d0 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -311,6 +311,7 @@ config MTD_NAND_CAFE config MTD_NAND_CS553X tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)" depends on X86_32 + depends on !UML && HAS_IOMEM help The CS553x companion chips for the AMD Geode processor include NAND flash controllers with built-in hardware ECC -- cgit v1.2.3 From 26d072e36c732e6fe7eebdceb5e0497ddf256ded Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Mon, 25 Jan 2016 21:29:45 +0100 Subject: mtd: nand: pxa3xx_nand: add register access debug Add verbose debug for register accesses. This enables easier debugging by following where and how hardware is stimulated, and how it answers. Signed-off-by: Robert Jarzmik Acked-by: Ezequiel Garcia Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 86fc245dc71a..e42496adda8d 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -131,11 +131,23 @@ #define READ_ID_BYTES 7 /* macros for registers read/write */ -#define nand_writel(info, off, val) \ - writel_relaxed((val), (info)->mmio_base + (off)) - -#define nand_readl(info, off) \ - readl_relaxed((info)->mmio_base + (off)) +#define nand_writel(info, off, val) \ + do { \ + dev_vdbg(&info->pdev->dev, \ + "%s():%d nand_writel(0x%x, 0x%04x)\n", \ + __func__, __LINE__, (val), (off)); \ + writel_relaxed((val), (info)->mmio_base + (off)); \ + } while (0) + +#define nand_readl(info, off) \ + ({ \ + unsigned int _v; \ + _v = readl_relaxed((info)->mmio_base + (off)); \ + dev_vdbg(&info->pdev->dev, \ + "%s():%d nand_readl(0x%04x) = 0x%x\n", \ + __func__, __LINE__, (off), _v); \ + _v; \ + }) /* error code and state */ enum { -- cgit v1.2.3 From ed4eeba7338bb123090f1c8b208f64d8184a896d Mon Sep 17 00:00:00 2001 From: Raghav Dogra Date: Wed, 16 Dec 2015 16:11:31 +0530 Subject: driver/memory: Removal of deprecated NO_IRQ Replacing the NO_IRQ macro with 0. If there is no interrupt, returned value will be 0 regardless of what NO_IRQ is defined. Signed-off-by: Raghav Dogra Signed-off-by: Brian Norris --- drivers/memory/fsl_ifc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c index acd1460cf787..2a691da8c1c7 100644 --- a/drivers/memory/fsl_ifc.c +++ b/drivers/memory/fsl_ifc.c @@ -260,7 +260,7 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) /* get the Controller level irq */ fsl_ifc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0); - if (fsl_ifc_ctrl_dev->irq == NO_IRQ) { + if (fsl_ifc_ctrl_dev->irq == 0) { dev_err(&dev->dev, "failed to get irq resource " "for IFC\n"); ret = -ENODEV; -- cgit v1.2.3 From dc9b5a0c631115118267255837ac9df682fb79d1 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Mon, 1 Feb 2016 12:02:06 -0800 Subject: drm/i915: PSR simplify port and link standby checks. Current code not just block link_standby for non DDI platforms but also block PSR from work on other ports B/C/D/E. So, besides change any behaviour let's just fix the mess a bit here and reuse HSW check to block the other ports and reduce the second if only to link stadnby request. Cc: Paulo Zanoni Signed-off-by: Rodrigo Vivi Reviewed-by: Paulo Zanoni --- drivers/gpu/drm/i915/intel_psr.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 9ccff3011523..3c80b86e45f8 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -304,8 +304,15 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) dev_priv->psr.source_ok = false; - if (IS_HASWELL(dev) && dig_port->port != PORT_A) { - DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n"); + /* + * HSW spec explicitly says PSR is tied to port A. + * BDW+ platforms with DDI implementation of PSR have different + * PSR registers per transcoder and we only implement transcoder EDP + * ones. Since by Display design transcoder EDP is tied to port A + * we can safely escape based on the port A. + */ + if (HAS_DDI(dev) && dig_port->port != PORT_A) { + DRM_DEBUG_KMS("PSR condition failed: Port not supported\n"); return false; } @@ -328,7 +335,7 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) } if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && - ((dev_priv->vbt.psr.full_link) || (dig_port->port != PORT_A))) { + dev_priv->vbt.psr.full_link) { DRM_DEBUG_KMS("PSR condition failed: Link Standby requested/needed but not supported on this platform\n"); return false; } -- cgit v1.2.3 From 60e5ffe329b090155ec860e2f31dc8d505ec7acd Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Mon, 1 Feb 2016 12:02:07 -0800 Subject: drm/i915: Add PSR main link standby support back Link standby support has been deprecated with 'commit 89251b177 ("drm/i915: PSR: deprecate link_standby support for core platforms.")' The reason for that is that main link in full off offers more power savings and on HSW and BDW implementations on source side had known bugs with link standby. However that same HSD report only mentions BDW and HSW and tells that a fix was going to new platforms. Since on Skylake link standby didn't cause the bad blank flickering screens seen on HSW and BDW let's respect VBT again for this and future platforms. Cc: Paulo Zanoni Signed-off-by: Rodrigo Vivi Reviewed-by: Paulo Zanoni --- drivers/gpu/drm/i915/i915_debugfs.c | 4 ++++ drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_psr.c | 26 +++++++++++++++++++------- 3 files changed, 24 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 863012a2602e..ec0c2a05eed6 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2583,6 +2583,10 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) enabled = true; } } + + seq_printf(m, "Main link in standby mode: %s\n", + yesno(dev_priv->psr.link_standby)); + seq_printf(m, "HW Enabled & Active bit: %s", yesno(enabled)); if (!HAS_DDI(dev)) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c921ad8e15a7..65a2cd04bc8f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1007,6 +1007,7 @@ struct i915_psr { unsigned busy_frontbuffer_bits; bool psr2_support; bool aux_frame_sync; + bool link_standby; }; enum intel_pch { diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 3c80b86e45f8..b99a105ae58b 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -225,7 +225,12 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT)); } - drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, DP_PSR_ENABLE); + if (dev_priv->psr.link_standby) + drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, + DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE); + else + drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, + DP_PSR_ENABLE); } static void vlv_psr_enable_source(struct intel_dp *intel_dp) @@ -280,6 +285,9 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) if (IS_HASWELL(dev)) val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES; + if (dev_priv->psr.link_standby) + val |= EDP_PSR_LINK_STANDBY; + I915_WRITE(EDP_PSR_CTL, val | max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT | idle_frames << EDP_PSR_IDLE_FRAME_SHIFT | @@ -334,12 +342,6 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) return false; } - if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && - dev_priv->vbt.psr.full_link) { - DRM_DEBUG_KMS("PSR condition failed: Link Standby requested/needed but not supported on this platform\n"); - return false; - } - dev_priv->psr.source_ok = true; return true; } @@ -770,6 +772,16 @@ void intel_psr_init(struct drm_device *dev) dev_priv->psr_mmio_base = IS_HASWELL(dev_priv) ? HSW_EDP_PSR_BASE : BDW_EDP_PSR_BASE; + if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + /* HSW and BDW require workarounds that we don't implement. */ + dev_priv->psr.link_standby = false; + else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + /* On VLV and CHV only standby mode is supported. */ + dev_priv->psr.link_standby = true; + else + /* For new platforms let's respect VBT back again */ + dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link; + INIT_DELAYED_WORK(&dev_priv->psr.work, intel_psr_work); mutex_init(&dev_priv->psr.lock); } -- cgit v1.2.3 From 65f61b426ddba160699fd64bf94f14eff339616c Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Mon, 1 Feb 2016 12:02:08 -0800 Subject: drm/i915: Instrument PSR parameter for debuging with link standby x link off. Unfortunately we don't know all panels and platforms out there and we found internal prototypes without VBT proper set but where only link in standby worked well. So, before enable PSR by default let's instrument the PSR parameter in a way that we can identify different panels out there that might require or work better with link standby mode. It is also useful to say that for backward compatibility I'm not changing the meaning of this flag. So "0" still means disabled and "1" means enabled with full support and maximum power savings. v2: Use positive value instead of negative for different operation mode as suggested by Daniel. v3: As Paulo suggested use 2 to force link standby and 3 to force link fully on. Also split the link_standby introduction in a separated patch. v4: Use DRM_ERROR for link off request on platforms that don't support and Remove the quirk promise. Cc: Jani Nikula Cc: Paulo Zanoni Cc: Daniel Vetter Signed-off-by: Rodrigo Vivi Reviewed-by: Paulo Zanoni Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1454356928-19779-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_params.c | 3 ++- drivers/gpu/drm/i915/intel_psr.c | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 8d90c256520a..8b9f36814165 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -127,7 +127,8 @@ MODULE_PARM_DESC(enable_execlists, "(-1=auto [default], 0=disabled, 1=enabled)"); module_param_named_unsafe(enable_psr, i915.enable_psr, int, 0600); -MODULE_PARM_DESC(enable_psr, "Enable PSR (default: false)"); +MODULE_PARM_DESC(enable_psr, "Enable PSR " + "(0=disabled [default], 1=enabled - link mode chosen per-platform, 2=force link-standby mode, 3=force link-off mode)"); module_param_named_unsafe(preliminary_hw_support, i915.preliminary_hw_support, int, 0600); MODULE_PARM_DESC(preliminary_hw_support, diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index b99a105ae58b..4ab757947f15 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -329,6 +329,12 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) return false; } + if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && + !dev_priv->psr.link_standby) { + DRM_ERROR("PSR condition failed: Link off requested but not supported on this platform\n"); + return false; + } + if (IS_HASWELL(dev) && I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config->cpu_transcoder)) & S3D_ENABLE) { @@ -772,6 +778,7 @@ void intel_psr_init(struct drm_device *dev) dev_priv->psr_mmio_base = IS_HASWELL(dev_priv) ? HSW_EDP_PSR_BASE : BDW_EDP_PSR_BASE; + /* Set link_standby x link_off defaults */ if (IS_HASWELL(dev) || IS_BROADWELL(dev)) /* HSW and BDW require workarounds that we don't implement. */ dev_priv->psr.link_standby = false; @@ -782,6 +789,16 @@ void intel_psr_init(struct drm_device *dev) /* For new platforms let's respect VBT back again */ dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link; + /* Override link_standby x link_off defaults */ + if (i915.enable_psr == 2 && !dev_priv->psr.link_standby) { + DRM_DEBUG_KMS("PSR: Forcing link standby\n"); + dev_priv->psr.link_standby = true; + } + if (i915.enable_psr == 3 && dev_priv->psr.link_standby) { + DRM_DEBUG_KMS("PSR: Forcing main link off\n"); + dev_priv->psr.link_standby = false; + } + INIT_DELAYED_WORK(&dev_priv->psr.work, intel_psr_work); mutex_init(&dev_priv->psr.lock); } -- cgit v1.2.3 From 17a2f46c3d8877fe2a0b6ff391d1df30e67892a6 Mon Sep 17 00:00:00 2001 From: Abhilash Jindal Date: Wed, 27 Jan 2016 17:46:02 -0500 Subject: iio: dht11: Use boottime Wall time obtained from ktime_get_real_ns is susceptible to sudden jumps due to user setting the time or due to NTP. Boot time is constantly increasing time better suited for comparing two timestamps. Signed-off-by: Abhilash Jindal Reviewed-by: Harald Geyer Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/dht11.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/humidity/dht11.c b/drivers/iio/humidity/dht11.c index 1165b1c4f9d6..cfc5a051ab9f 100644 --- a/drivers/iio/humidity/dht11.c +++ b/drivers/iio/humidity/dht11.c @@ -117,7 +117,7 @@ static int dht11_decode(struct dht11 *dht11, int offset, int timeres) if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum) return -EIO; - dht11->timestamp = ktime_get_real_ns(); + dht11->timestamp = ktime_get_boot_ns(); if (hum_int < 20) { /* DHT22 */ dht11->temperature = (((temp_int & 0x7f) << 8) + temp_dec) * ((temp_int & 0x80) ? -100 : 100); @@ -145,7 +145,7 @@ static irqreturn_t dht11_handle_irq(int irq, void *data) /* TODO: Consider making the handler safe for IRQ sharing */ if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) { - dht11->edges[dht11->num_edges].ts = ktime_get_real_ns(); + dht11->edges[dht11->num_edges].ts = ktime_get_boot_ns(); dht11->edges[dht11->num_edges++].value = gpio_get_value(dht11->gpio); @@ -164,7 +164,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev, int ret, timeres; mutex_lock(&dht11->lock); - if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_real_ns()) { + if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_boot_ns()) { timeres = ktime_get_resolution_ns(); if (DHT11_DATA_BIT_HIGH < 2 * timeres) { dev_err(dht11->dev, "timeresolution %dns too low\n", @@ -279,7 +279,7 @@ static int dht11_probe(struct platform_device *pdev) return -EINVAL; } - dht11->timestamp = ktime_get_real_ns() - DHT11_DATA_VALID_TIME - 1; + dht11->timestamp = ktime_get_boot_ns() - DHT11_DATA_VALID_TIME - 1; dht11->num_edges = -1; platform_set_drvdata(pdev, iio); -- cgit v1.2.3 From 047a555f95fec4bcb8adfc37eb6fb1026fb3026a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 23 Jan 2016 23:06:28 +0900 Subject: bus: uniphier-system-bus: revive tristate prompt At first, commit 4b7f48d395a7 ("bus: uniphier-system-bus: add UniPhier System Bus driver") introduced this driver as a tristate one. Then, commit 326ea45aa827 ("bus: uniphier: allow only built-in driver") temporarily made it boolean in order to fix a link error in case it is compiled as a module. The root cause was fixed by commit b80443c2211c ("of/platform: export of_default_bus_match_table"). Now this driver can really be a module. Signed-off-by: Masahiro Yamada Signed-off-by: Olof Johansson --- drivers/bus/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 129d47bcc5fc..9a92c072a485 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -132,7 +132,7 @@ config SUNXI_RSB and AC100/AC200 ICs. config UNIPHIER_SYSTEM_BUS - bool "UniPhier System Bus driver" + tristate "UniPhier System Bus driver" depends on ARCH_UNIPHIER && OF default y help -- cgit v1.2.3 From ea7743e2719d34eacb4cb206ae227120029d06c6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 29 Jan 2016 15:06:25 +0100 Subject: ARM: pxa: define clock registers as __iomem We should not dereference registers as pointers, so use readl/writel instead for these registers. The clock registers are accessed in multiple files, so we have to change them all at once. I stumbled over these registers while looking at something unrelated. There are in fact other registers with the same problem, but I did not try to address those at this point. Signed-off-by: Arnd Bergmann Acked-by: Stephen Boyd Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/gumstix.c | 6 ++--- arch/arm/mach-pxa/include/mach/pxa2xx-regs.h | 8 +++---- arch/arm/mach-pxa/include/mach/pxa3xx-regs.h | 2 +- arch/arm/mach-pxa/zeus.c | 2 +- drivers/clk/pxa/clk-pxa25x.c | 12 +++++----- drivers/clk/pxa/clk-pxa27x.c | 34 ++++++++++++++-------------- drivers/clk/pxa/clk-pxa3xx.c | 3 +-- drivers/cpufreq/pxa2xx-cpufreq.c | 2 +- 8 files changed, 34 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c index 6815a9357774..9c5b2fb054f9 100644 --- a/arch/arm/mach-pxa/gumstix.c +++ b/arch/arm/mach-pxa/gumstix.c @@ -139,14 +139,14 @@ static void gumstix_setup_bt_clock(void) { int timeout = 500; - if (!(OSCC & OSCC_OOK)) + if (!(readl(OSCC) & OSCC_OOK)) pr_warn("32kHz clock was not on. Bootloader may need to be updated\n"); else return; - OSCC |= OSCC_OON; + writel(readl(OSCC) | OSCC_OON, OSCC); do { - if (OSCC & OSCC_OOK) + if (readl(OSCC) & OSCC_OOK) break; udelay(1); } while (--timeout); diff --git a/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h b/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h index f1dd62946b36..5537d5601d70 100644 --- a/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h +++ b/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h @@ -134,10 +134,10 @@ /* * PXA2xx specific Core clock definitions */ -#define CCCR __REG(0x41300000) /* Core Clock Configuration Register */ -#define CCSR __REG(0x4130000C) /* Core Clock Status Register */ -#define CKEN __REG(0x41300004) /* Clock Enable Register */ -#define OSCC __REG(0x41300008) /* Oscillator Configuration Register */ +#define CCCR io_p2v(0x41300000) /* Core Clock Configuration Register */ +#define CCSR io_p2v(0x4130000C) /* Core Clock Status Register */ +#define CKEN io_p2v(0x41300004) /* Clock Enable Register */ +#define OSCC io_p2v(0x41300008) /* Oscillator Configuration Register */ #define CCCR_N_MASK 0x0380 /* Run Mode Frequency to Turbo Mode Frequency Multiplier */ #define CCCR_M_MASK 0x0060 /* Memory Frequency to Run Mode Frequency Multiplier */ diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h b/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h index f4d48d20754e..888bf7ade15a 100644 --- a/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h +++ b/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h @@ -18,7 +18,7 @@ /* * Oscillator Configuration Register (OSCC) */ -#define OSCC __REG(0x41350000) /* Oscillator Configuration Register */ +#define OSCC io_p2v(0x41350000) /* Oscillator Configuration Register */ #define OSCC_PEN (1 << 11) /* 13MHz POUT */ diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c index 515b7ddda8aa..3b94ecfb9426 100644 --- a/arch/arm/mach-pxa/zeus.c +++ b/arch/arm/mach-pxa/zeus.c @@ -910,7 +910,7 @@ static void __init zeus_map_io(void) PMCR = PSPR = 0; /* enable internal 32.768Khz oscillator (ignore OSCC_OOK) */ - OSCC |= OSCC_OON; + writel(readl(OSCC) | OSCC_OON, OSCC); /* Some clock cycles later (from OSCC_ON), programme PCFR (OPDE...). * float chip selects and PCMCIA */ diff --git a/drivers/clk/pxa/clk-pxa25x.c b/drivers/clk/pxa/clk-pxa25x.c index b7747229db9a..a9353cd4ce17 100644 --- a/drivers/clk/pxa/clk-pxa25x.c +++ b/drivers/clk/pxa/clk-pxa25x.c @@ -84,7 +84,7 @@ unsigned int pxa25x_get_clk_frequency_khz(int info) static unsigned long clk_pxa25x_memory_get_rate(struct clk_hw *hw, unsigned long parent_rate) { - unsigned long cccr = CCCR; + unsigned long cccr = readl(CCCR); unsigned int m = M_clk_mult[(cccr >> 5) & 0x03]; return parent_rate / m; @@ -99,7 +99,7 @@ PARENTS(pxa25x_osc3) = { "osc_3_6864mhz", "osc_3_6864mhz" }; #define PXA25X_CKEN(dev_id, con_id, parents, mult, div, \ bit, is_lp, flags) \ PXA_CKEN(dev_id, con_id, bit, parents, mult, div, mult, div, \ - is_lp, &CKEN, CKEN_ ## bit, flags) + is_lp, CKEN, CKEN_ ## bit, flags) #define PXA25X_PBUS95_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay) \ PXA25X_CKEN(dev_id, con_id, pxa25x_pbus95_parents, mult_hp, \ div_hp, bit, NULL, 0) @@ -112,10 +112,10 @@ PARENTS(pxa25x_osc3) = { "osc_3_6864mhz", "osc_3_6864mhz" }; #define PXA25X_CKEN_1RATE(dev_id, con_id, bit, parents, delay) \ PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \ - &CKEN, CKEN_ ## bit, 0) + CKEN, CKEN_ ## bit, 0) #define PXA25X_CKEN_1RATE_AO(dev_id, con_id, bit, parents, delay) \ PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \ - &CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED) + CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED) static struct desc_clk_cken pxa25x_clocks[] __initdata = { PXA25X_PBUS95_CKEN("pxa2xx-mci.0", NULL, MMC, 1, 5, 0), @@ -162,7 +162,7 @@ MUX_RO_RATE_RO_OPS(clk_pxa25x_core, "core"); static unsigned long clk_pxa25x_run_get_rate(struct clk_hw *hw, unsigned long parent_rate) { - unsigned long cccr = CCCR; + unsigned long cccr = readl(CCCR); unsigned int n2 = N2_clk_mult[(cccr >> 7) & 0x07]; return (parent_rate / n2) * 2; @@ -173,7 +173,7 @@ RATE_RO_OPS(clk_pxa25x_run, "run"); static unsigned long clk_pxa25x_cpll_get_rate(struct clk_hw *hw, unsigned long parent_rate) { - unsigned long clkcfg, cccr = CCCR; + unsigned long clkcfg, cccr = readl(CCCR); unsigned int l, m, n2, t; asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg)); diff --git a/drivers/clk/pxa/clk-pxa27x.c b/drivers/clk/pxa/clk-pxa27x.c index 5b82d30baf9f..fc2abf97edd7 100644 --- a/drivers/clk/pxa/clk-pxa27x.c +++ b/drivers/clk/pxa/clk-pxa27x.c @@ -85,7 +85,7 @@ unsigned int pxa27x_get_clk_frequency_khz(int info) bool pxa27x_is_ppll_disabled(void) { - unsigned long ccsr = CCSR; + unsigned long ccsr = readl(CCSR); return ccsr & (1 << CCCR_PPDIS_BIT); } @@ -93,7 +93,7 @@ bool pxa27x_is_ppll_disabled(void) #define PXA27X_CKEN(dev_id, con_id, parents, mult_hp, div_hp, \ bit, is_lp, flags) \ PXA_CKEN(dev_id, con_id, bit, parents, 1, 1, mult_hp, div_hp, \ - is_lp, &CKEN, CKEN_ ## bit, flags) + is_lp, CKEN, CKEN_ ## bit, flags) #define PXA27X_PBUS_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay) \ PXA27X_CKEN(dev_id, con_id, pxa27x_pbus_parents, mult_hp, \ div_hp, bit, pxa27x_is_ppll_disabled, 0) @@ -106,10 +106,10 @@ PARENTS(pxa27x_membus) = { "lcd_base", "lcd_base" }; #define PXA27X_CKEN_1RATE(dev_id, con_id, bit, parents, delay) \ PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \ - &CKEN, CKEN_ ## bit, 0) + CKEN, CKEN_ ## bit, 0) #define PXA27X_CKEN_1RATE_AO(dev_id, con_id, bit, parents, delay) \ PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \ - &CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED) + CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED) static struct desc_clk_cken pxa27x_clocks[] __initdata = { PXA27X_PBUS_CKEN("pxa2xx-uart.0", NULL, FFUART, 2, 42, 1), @@ -151,7 +151,7 @@ static unsigned long clk_pxa27x_cpll_get_rate(struct clk_hw *hw, unsigned long clkcfg; unsigned int t, ht; unsigned int l, L, n2, N; - unsigned long ccsr = CCSR; + unsigned long ccsr = readl(CCSR); asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg)); t = clkcfg & (1 << 0); @@ -171,8 +171,8 @@ static unsigned long clk_pxa27x_lcd_base_get_rate(struct clk_hw *hw, unsigned long parent_rate) { unsigned int l, osc_forced; - unsigned long ccsr = CCSR; - unsigned long cccr = CCCR; + unsigned long ccsr = readl(CCSR); + unsigned long cccr = readl(CCCR); l = ccsr & CCSR_L_MASK; osc_forced = ccsr & (1 << CCCR_CPDIS_BIT); @@ -193,7 +193,7 @@ static unsigned long clk_pxa27x_lcd_base_get_rate(struct clk_hw *hw, static u8 clk_pxa27x_lcd_base_get_parent(struct clk_hw *hw) { unsigned int osc_forced; - unsigned long ccsr = CCSR; + unsigned long ccsr = readl(CCSR); osc_forced = ccsr & (1 << CCCR_CPDIS_BIT); if (osc_forced) @@ -222,7 +222,7 @@ static unsigned long clk_pxa27x_core_get_rate(struct clk_hw *hw, { unsigned long clkcfg; unsigned int t, ht, b, osc_forced; - unsigned long ccsr = CCSR; + unsigned long ccsr = readl(CCSR); osc_forced = ccsr & (1 << CCCR_CPDIS_BIT); asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg)); @@ -242,7 +242,7 @@ static u8 clk_pxa27x_core_get_parent(struct clk_hw *hw) { unsigned long clkcfg; unsigned int t, ht, b, osc_forced; - unsigned long ccsr = CCSR; + unsigned long ccsr = readl(CCSR); osc_forced = ccsr & (1 << CCCR_CPDIS_BIT); if (osc_forced) @@ -263,7 +263,7 @@ MUX_RO_RATE_RO_OPS(clk_pxa27x_core, "core"); static unsigned long clk_pxa27x_run_get_rate(struct clk_hw *hw, unsigned long parent_rate) { - unsigned long ccsr = CCSR; + unsigned long ccsr = readl(CCSR); unsigned int n2 = (ccsr & CCSR_N2_MASK) >> CCSR_N2_SHIFT; return (parent_rate / n2) * 2; @@ -285,7 +285,7 @@ static unsigned long clk_pxa27x_system_bus_get_rate(struct clk_hw *hw, { unsigned long clkcfg; unsigned int b, osc_forced; - unsigned long ccsr = CCSR; + unsigned long ccsr = readl(CCSR); osc_forced = ccsr & (1 << CCCR_CPDIS_BIT); asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg)); @@ -302,7 +302,7 @@ static unsigned long clk_pxa27x_system_bus_get_rate(struct clk_hw *hw, static u8 clk_pxa27x_system_bus_get_parent(struct clk_hw *hw) { unsigned int osc_forced; - unsigned long ccsr = CCSR; + unsigned long ccsr = readl(CCSR); osc_forced = ccsr & (1 << CCCR_CPDIS_BIT); if (osc_forced) @@ -318,8 +318,8 @@ static unsigned long clk_pxa27x_memory_get_rate(struct clk_hw *hw, unsigned long parent_rate) { unsigned int a, l, osc_forced; - unsigned long cccr = CCCR; - unsigned long ccsr = CCSR; + unsigned long cccr = readl(CCCR); + unsigned long ccsr = readl(CCSR); osc_forced = ccsr & (1 << CCCR_CPDIS_BIT); a = cccr & (1 << CCCR_A_BIT); @@ -337,8 +337,8 @@ static unsigned long clk_pxa27x_memory_get_rate(struct clk_hw *hw, static u8 clk_pxa27x_memory_get_parent(struct clk_hw *hw) { unsigned int osc_forced, a; - unsigned long cccr = CCCR; - unsigned long ccsr = CCSR; + unsigned long cccr = readl(CCCR); + unsigned long ccsr = readl(CCSR); osc_forced = ccsr & (1 << CCCR_CPDIS_BIT); a = cccr & (1 << CCCR_A_BIT); diff --git a/drivers/clk/pxa/clk-pxa3xx.c b/drivers/clk/pxa/clk-pxa3xx.c index 4af4eed5f89f..ea679718601c 100644 --- a/drivers/clk/pxa/clk-pxa3xx.c +++ b/drivers/clk/pxa/clk-pxa3xx.c @@ -334,8 +334,7 @@ static void __init pxa3xx_base_clocks_init(void) clk_register_clk_pxa3xx_system_bus(); clk_register_clk_pxa3xx_ac97(); clk_register_clk_pxa3xx_smemc(); - clk_register_gate(NULL, "CLK_POUT", "osc_13mhz", 0, - (void __iomem *)&OSCC, 11, 0, NULL); + clk_register_gate(NULL, "CLK_POUT", "osc_13mhz", 0, OSCC, 11, 0, NULL); clkdev_pxa_register(CLK_OSTIMER, "OSTIMER0", NULL, clk_register_fixed_factor(NULL, "os-timer0", "osc_13mhz", 0, 1, 4)); diff --git a/drivers/cpufreq/pxa2xx-cpufreq.c b/drivers/cpufreq/pxa2xx-cpufreq.c index 1d99c97defa9..efe3b215fd34 100644 --- a/drivers/cpufreq/pxa2xx-cpufreq.c +++ b/drivers/cpufreq/pxa2xx-cpufreq.c @@ -319,7 +319,7 @@ static int pxa_set_target(struct cpufreq_policy *policy, unsigned int idx) local_irq_save(flags); /* Set new the CCCR and prepare CCLKCFG */ - CCCR = pxa_freq_settings[idx].cccr; + writel(pxa_freq_settings[idx].cccr, CCCR); cclkcfg = pxa_freq_settings[idx].cclkcfg; asm volatile(" \n\ -- cgit v1.2.3 From 8d9b39c6499b113ef9218c80682de114beffe7bb Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Mon, 1 Feb 2016 09:06:03 +0100 Subject: Staging: speakup: Fix allyesconfig build on mn10300 mn10300 uses an mmio-driven uart. This is not supported by speakup, so prevent from enabling it. Signed-off-by: Samuel Thibault Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/speakup/Kconfig b/drivers/staging/speakup/Kconfig index efd6f4560d3e..7e8037e230b8 100644 --- a/drivers/staging/speakup/Kconfig +++ b/drivers/staging/speakup/Kconfig @@ -1,7 +1,7 @@ menu "Speakup console speech" config SPEAKUP - depends on VT + depends on VT && !MN10300 tristate "Speakup core" ---help--- This is the Speakup screen reader. Think of it as a -- cgit v1.2.3 From bb2bb45d1be28987e6cb50f50e4819795537ab83 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 1 Feb 2016 21:09:14 +0000 Subject: regmap: Return an error if a caller attempts to do an unsupported raw read regmaps without raw I/O access can't implement raw I/O operations, return an error if someone tries to do that rather than crashing. Signed-off-by: Mark Brown --- drivers/base/regmap/regmap.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 343263449aff..e2f68807d970 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -2255,6 +2255,9 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, WARN_ON(!map->bus); + if (!map->bus || !map->bus->read) + return -EINVAL; + range = _regmap_range_lookup(map, reg); if (range) { ret = _regmap_select_page(map, ®, range, -- cgit v1.2.3 From d9e743408ecd468974cd233623ed19253fa2a7b0 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 Dec 2015 19:22:55 +0900 Subject: clk: remove unused first argument of __clk_init() The "struct device *dev" is not used at all in this function. Signed-off-by: Masahiro Yamada Reviewed-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index b4db67a446c8..4bb7d09dfcf2 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2304,13 +2304,12 @@ static inline void clk_debug_unregister(struct clk_core *core) /** * __clk_init - initialize the data structures in a struct clk - * @dev: device initializing this clk, placeholder for now * @clk: clk being initialized * * Initializes the lists in struct clk_core, queries the hardware for the * parent and rate and sets them both. */ -static int __clk_init(struct device *dev, struct clk *clk_user) +static int __clk_init(struct clk *clk_user) { int i, ret = 0; struct clk_core *orphan; @@ -2593,7 +2592,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) goto fail_parent_names_copy; } - ret = __clk_init(dev, hw->clk); + ret = __clk_init(hw->clk); if (!ret) return hw->clk; -- cgit v1.2.3 From d35c80c248c7a97458b075225b1bf3e41c8a6d50 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 Dec 2015 19:22:56 +0900 Subject: clk: change the argument of __clk_init() into pointer to clk_core The argument clk_user is used only for the clk_user->core. The rest of this function only takes care of clk_core. Signed-off-by: Masahiro Yamada Reviewed-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 4bb7d09dfcf2..b8cd6bbdbbc0 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2303,25 +2303,22 @@ static inline void clk_debug_unregister(struct clk_core *core) #endif /** - * __clk_init - initialize the data structures in a struct clk - * @clk: clk being initialized + * __clk_init - initialize the data structures in a struct clk_core + * @core: clk_core being initialized * * Initializes the lists in struct clk_core, queries the hardware for the * parent and rate and sets them both. */ -static int __clk_init(struct clk *clk_user) +static int __clk_init(struct clk_core *core) { int i, ret = 0; struct clk_core *orphan; struct hlist_node *tmp2; - struct clk_core *core; unsigned long rate; - if (!clk_user) + if (!core) return -EINVAL; - core = clk_user->core; - clk_prepare_lock(); /* check to see if a clock with this name is already registered */ @@ -2592,7 +2589,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) goto fail_parent_names_copy; } - ret = __clk_init(hw->clk); + ret = __clk_init(core); if (!ret) return hw->clk; -- cgit v1.2.3 From be45ebf25fc8866675f4822c74c9d0eb3dd96103 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 Dec 2015 19:22:57 +0900 Subject: clk: rename __clk_init() into __clk_core_init() Now this function takes clk_core as its argument. __clk_core_init() would be more suitable for the name of this function. Signed-off-by: Masahiro Yamada Reviewed-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index b8cd6bbdbbc0..e7701d6029b3 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2303,13 +2303,13 @@ static inline void clk_debug_unregister(struct clk_core *core) #endif /** - * __clk_init - initialize the data structures in a struct clk_core + * __clk_core_init - initialize the data structures in a struct clk_core * @core: clk_core being initialized * * Initializes the lists in struct clk_core, queries the hardware for the * parent and rate and sets them both. */ -static int __clk_init(struct clk_core *core) +static int __clk_core_init(struct clk_core *core) { int i, ret = 0; struct clk_core *orphan; @@ -2589,7 +2589,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) goto fail_parent_names_copy; } - ret = __clk_init(core); + ret = __clk_core_init(core); if (!ret) return hw->clk; -- cgit v1.2.3 From 027f942ce44131bc3a11aaae6dbb227f461845b6 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 Dec 2015 19:22:58 +0900 Subject: clk: remove unnecessary !core->parents conditional This if-block has been here since the introduction of the common clock framework. Now no clock drivers are statically initialized. core->parent is always NULL at this point. Drop the redundant check and the confusing comment. Signed-off-by: Masahiro Yamada Reviewed-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index e7701d6029b3..735828d55c00 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2366,11 +2366,8 @@ static int __clk_core_init(struct clk_core *core) * in to clk_init during early boot; thus any access to core->parents[] * must always check for a NULL pointer and try to populate it if * necessary. - * - * If core->parents is not NULL we skip this entire block. This allows - * for clock drivers to statically initialize core->parents. */ - if (core->num_parents > 1 && !core->parents) { + if (core->num_parents > 1) { core->parents = kcalloc(core->num_parents, sizeof(struct clk *), GFP_KERNEL); /* -- cgit v1.2.3 From 3a6e84545129913613dc1a97bbe8e4f2378696ee Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 Dec 2015 19:22:59 +0900 Subject: clk: change sizeof(struct clk *) to sizeof(*core->parents) Now, the clock parent is not "struct clk *", but "struct clk_core *". Of course, the size of a pointer is always same, but strictly speaking, sizeof(struct clk *) should be sizeof(struct clk_core *) here. This mismatch happened when we split the structure into struct clk and struct clk_core. For the potential possibility of future renaming, sizeof(*core->parents) would be better. Signed-off-by: Masahiro Yamada Reviewed-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 735828d55c00..f9cab0919bb4 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1069,7 +1069,7 @@ static int clk_fetch_parent_index(struct clk_core *core, if (!core->parents) { core->parents = kcalloc(core->num_parents, - sizeof(struct clk *), GFP_KERNEL); + sizeof(*core->parents), GFP_KERNEL); if (!core->parents) return -ENOMEM; } @@ -1720,7 +1720,7 @@ static struct clk_core *__clk_init_parent(struct clk_core *core) if (!core->parents) core->parents = - kcalloc(core->num_parents, sizeof(struct clk *), + kcalloc(core->num_parents, sizeof(*core->parents), GFP_KERNEL); ret = clk_core_get_parent_by_index(core, index); @@ -2368,8 +2368,8 @@ static int __clk_core_init(struct clk_core *core) * necessary. */ if (core->num_parents > 1) { - core->parents = kcalloc(core->num_parents, sizeof(struct clk *), - GFP_KERNEL); + core->parents = kcalloc(core->num_parents, + sizeof(*core->parents), GFP_KERNEL); /* * clk_core_lookup returns NULL for parents that have not been * clk_init'd; thus any access to clk->parents[] must check -- cgit v1.2.3 From 176d11690ba2c8ad59f99734d692f19f451c408b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 Dec 2015 19:23:00 +0900 Subject: clk: move core->parents allocation to clk_register() Currently, __clk_core_init() allows failure of the kcalloc() for the core->parents. So, clk_fetch_parent_index() and __clk_init_parent() also try to allocate core->parents in case it has not been allocated yet. Scattering memory allocation here and there makes things complicated. Like other clk_core members, allocate core->parents in clk_register() and let it fail in case of memory shortage. If we cannot allocate such a small piece of memory, the system is already insane. There is no point to postpone the memory allocation. Also, allocate core->parents regardless of core->num_parents. We want it even if core->num_parents == 1 because clk_fetch_parent_index() might be called against the clk_core with a single parent. If core->num_parents == 0, core->parents is set to ZERO_SIZE_PTR. It is harmless because no access happens to core->parents in such a case. Signed-off-by: Masahiro Yamada Reviewed-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 51 +++++++++++++++++++-------------------------------- 1 file changed, 19 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f9cab0919bb4..a92feedda592 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1067,13 +1067,6 @@ static int clk_fetch_parent_index(struct clk_core *core, { int i; - if (!core->parents) { - core->parents = kcalloc(core->num_parents, - sizeof(*core->parents), GFP_KERNEL); - if (!core->parents) - return -ENOMEM; - } - /* * find index of new parent clock using cached parent ptrs, * or if not yet cached, use string name comparison and cache @@ -1718,11 +1711,6 @@ static struct clk_core *__clk_init_parent(struct clk_core *core) index = core->ops->get_parent(core->hw); - if (!core->parents) - core->parents = - kcalloc(core->num_parents, sizeof(*core->parents), - GFP_KERNEL); - ret = clk_core_get_parent_by_index(core, index); out: @@ -2361,26 +2349,15 @@ static int __clk_core_init(struct clk_core *core) __func__, core->name); /* - * Allocate an array of struct clk *'s to avoid unnecessary string - * look-ups of clk's possible parents. This can fail for clocks passed - * in to clk_init during early boot; thus any access to core->parents[] - * must always check for a NULL pointer and try to populate it if - * necessary. + * clk_core_lookup returns NULL for parents that have not been + * clk_init'd; thus any access to clk->parents[] must check + * for a NULL pointer. We can always perform lazy lookups for + * missing parents later on. */ - if (core->num_parents > 1) { - core->parents = kcalloc(core->num_parents, - sizeof(*core->parents), GFP_KERNEL); - /* - * clk_core_lookup returns NULL for parents that have not been - * clk_init'd; thus any access to clk->parents[] must check - * for a NULL pointer. We can always perform lazy lookups for - * missing parents later on. - */ - if (core->parents) - for (i = 0; i < core->num_parents; i++) - core->parents[i] = - clk_core_lookup(core->parent_names[i]); - } + if (core->parents) + for (i = 0; i < core->num_parents; i++) + core->parents[i] = + clk_core_lookup(core->parent_names[i]); core->parent = __clk_init_parent(core); @@ -2578,12 +2555,20 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) } } + /* avoid unnecessary string look-ups of clk_core's possible parents. */ + core->parents = kcalloc(core->num_parents, sizeof(*core->parents), + GFP_KERNEL); + if (!core->parents) { + ret = -ENOMEM; + goto fail_parents; + }; + INIT_HLIST_HEAD(&core->clks); hw->clk = __clk_create_clk(hw, NULL, NULL); if (IS_ERR(hw->clk)) { ret = PTR_ERR(hw->clk); - goto fail_parent_names_copy; + goto fail_parents; } ret = __clk_core_init(core); @@ -2593,6 +2578,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) __clk_free_clk(hw->clk); hw->clk = NULL; +fail_parents: + kfree(core->parents); fail_parent_names_copy: while (--i >= 0) kfree_const(core->parent_names[i]); -- cgit v1.2.3 From 88cfbef2acd38443c3eed780263b5f5e95a8dc1f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 Dec 2015 19:23:01 +0900 Subject: clk: simplify clk_core_get_parent_by_index() Drop the "if (!core->parents)" case and refactor the function a bit because core->parents is always allocated. (Strictly speaking, it is ZERO_SIZE_PTR if core->num_parents == 0, but such a case is omitted by the if-conditional above.) Signed-off-by: Masahiro Yamada Reviewed-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index a92feedda592..c2e993db0cfd 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -350,13 +350,12 @@ static struct clk_core *clk_core_get_parent_by_index(struct clk_core *core, { if (!core || index >= core->num_parents) return NULL; - else if (!core->parents) - return clk_core_lookup(core->parent_names[index]); - else if (!core->parents[index]) - return core->parents[index] = - clk_core_lookup(core->parent_names[index]); - else - return core->parents[index]; + + if (!core->parents[index]) + core->parents[index] = + clk_core_lookup(core->parent_names[index]); + + return core->parents[index]; } struct clk_hw * -- cgit v1.2.3 From 3c436bf95a1df22fa501be7134bccd29f8387dfe Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 Dec 2015 19:23:02 +0900 Subject: clk: drop the initial core->parents look-ups from __clk_core_init() The core->parents is a cache to save expensive clock parent look-ups. It will be filled as needed later. We do not have to do it here. Signed-off-by: Masahiro Yamada Reviewed-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index c2e993db0cfd..98c68e99d5f6 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2347,17 +2347,6 @@ static int __clk_core_init(struct clk_core *core) "%s: invalid NULL in %s's .parent_names\n", __func__, core->name); - /* - * clk_core_lookup returns NULL for parents that have not been - * clk_init'd; thus any access to clk->parents[] must check - * for a NULL pointer. We can always perform lazy lookups for - * missing parents later on. - */ - if (core->parents) - for (i = 0; i < core->num_parents; i++) - core->parents[i] = - clk_core_lookup(core->parent_names[i]); - core->parent = __clk_init_parent(core); /* -- cgit v1.2.3 From c44fccb5f7b071d36cac3962799ba5a571429c28 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 Dec 2015 19:23:03 +0900 Subject: clk: replace pr_warn() with pr_err() for fatal cases These three cases let clk_register() fail. They should be considered as error messages. Signed-off-by: Masahiro Yamada Reviewed-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 98c68e99d5f6..09d84453ea3a 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2320,22 +2320,22 @@ static int __clk_core_init(struct clk_core *core) if (core->ops->set_rate && !((core->ops->round_rate || core->ops->determine_rate) && core->ops->recalc_rate)) { - pr_warning("%s: %s must implement .round_rate or .determine_rate in addition to .recalc_rate\n", - __func__, core->name); + pr_err("%s: %s must implement .round_rate or .determine_rate in addition to .recalc_rate\n", + __func__, core->name); ret = -EINVAL; goto out; } if (core->ops->set_parent && !core->ops->get_parent) { - pr_warning("%s: %s must implement .get_parent & .set_parent\n", - __func__, core->name); + pr_err("%s: %s must implement .get_parent & .set_parent\n", + __func__, core->name); ret = -EINVAL; goto out; } if (core->ops->set_rate_and_parent && !(core->ops->set_parent && core->ops->set_rate)) { - pr_warn("%s: %s must implement .set_parent & .set_rate\n", + pr_err("%s: %s must implement .set_parent & .set_rate\n", __func__, core->name); ret = -EINVAL; goto out; -- cgit v1.2.3 From 096676061987c613bdacddbae838cb63a815db94 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 2 Feb 2016 10:59:53 +0100 Subject: EDAC: Balance workqueue setup and teardown We use the ->edac_check function pointers to determine whether we need to setup a polling workqueue. However, the destroy path is not balanced and we might try to teardown an unitialized workqueue. Balance init and destroy paths by looking at ->edac_check in both cases. Set op_state to OP_OFFLINE *before* destroying anything. Reported-by: Zhiqiang Hou Cc: Varun Sethi Signed-off-by: Borislav Petkov --- drivers/edac/edac_mc.c | 15 +++++++-------- drivers/edac/edac_pci.c | 8 +++----- 2 files changed, 10 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 8adfc167c2e3..50802c154915 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -583,8 +583,6 @@ static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec) */ static void edac_mc_workq_teardown(struct mem_ctl_info *mci) { - mci->op_state = OP_OFFLINE; - edac_stop_work(&mci->work); } @@ -772,7 +770,7 @@ int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci, } /* If there IS a check routine, then we are running POLLED */ - if (mci->edac_check != NULL) { + if (mci->edac_check) { /* This instance is NOW RUNNING */ mci->op_state = OP_RUNNING_POLL; @@ -823,15 +821,16 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev) return NULL; } + /* mark MCI offline: */ + mci->op_state = OP_OFFLINE; + if (!del_mc_from_global_list(mci)) edac_mc_owner = NULL; - mutex_unlock(&mem_ctls_mutex); - /* flush workq processes */ - edac_mc_workq_teardown(mci); + mutex_unlock(&mem_ctls_mutex); - /* marking MCI offline */ - mci->op_state = OP_OFFLINE; + if (mci->edac_check) + edac_mc_workq_teardown(mci); /* remove from sysfs */ edac_remove_sysfs_mci_device(mci); diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index 99685388d3fb..f0e8c3d01ed5 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c @@ -241,8 +241,6 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) { edac_dbg(0, "\n"); - pci->op_state = OP_OFFLINE; - edac_stop_work(&pci->work); } @@ -289,7 +287,7 @@ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx) goto fail1; } - if (pci->edac_check != NULL) { + if (pci->edac_check) { pci->op_state = OP_RUNNING_POLL; edac_pci_workq_setup(pci, 1000); @@ -350,8 +348,8 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev) mutex_unlock(&edac_pci_ctls_mutex); - /* stop the workq timer */ - edac_pci_workq_teardown(pci); + if (pci->edac_check) + edac_pci_workq_teardown(pci); edac_printk(KERN_INFO, EDAC_PCI, "Removed device %d for %s %s: DEV %s\n", -- cgit v1.2.3 From 626a7a4dba2ad672b66b675f961de214f0ad0c74 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 2 Feb 2016 11:06:41 +0100 Subject: EDAC: Kill workqueue setup/teardown functions We have the generic wrappers now, use those. edac_pci_workq_setup() had an unused argument anyway. Signed-off-by: Borislav Petkov --- drivers/edac/edac_mc.c | 43 ++++--------------------------------------- drivers/edac/edac_pci.c | 35 ++++------------------------------- 2 files changed, 8 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 50802c154915..050493edb505 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -551,41 +551,6 @@ static void edac_mc_workq_function(struct work_struct *work_req) edac_queue_work(&mci->work, msecs_to_jiffies(edac_mc_get_poll_msec())); } -/* - * edac_mc_workq_setup - * initialize a workq item for this mci - * passing in the new delay period in msec - * - * locking model: - * - * called with the mem_ctls_mutex held - */ -static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec) -{ - edac_dbg(0, "\n"); - - /* if this instance is not in the POLL state, then simply return */ - if (mci->op_state != OP_RUNNING_POLL) - return; - - INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function); - - edac_queue_work(&mci->work, msecs_to_jiffies(msec)); -} - -/* - * edac_mc_workq_teardown - * stop the workq processing on this mci - * - * locking model: - * - * called WITHOUT lock held - */ -static void edac_mc_workq_teardown(struct mem_ctl_info *mci) -{ - edac_stop_work(&mci->work); -} - /* * edac_mc_reset_delay_period(unsigned long value) * @@ -769,12 +734,12 @@ int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci, goto fail1; } - /* If there IS a check routine, then we are running POLLED */ if (mci->edac_check) { - /* This instance is NOW RUNNING */ mci->op_state = OP_RUNNING_POLL; - edac_mc_workq_setup(mci, edac_mc_get_poll_msec()); + INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function); + edac_queue_work(&mci->work, msecs_to_jiffies(edac_mc_get_poll_msec())); + } else { mci->op_state = OP_RUNNING_INTERRUPT; } @@ -830,7 +795,7 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev) mutex_unlock(&mem_ctls_mutex); if (mci->edac_check) - edac_mc_workq_teardown(mci); + edac_stop_work(&mci->work); /* remove from sysfs */ edac_remove_sysfs_mci_device(mci); diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index f0e8c3d01ed5..79945e0df0dc 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c @@ -215,35 +215,6 @@ static void edac_pci_workq_function(struct work_struct *work_req) mutex_unlock(&edac_pci_ctls_mutex); } -/* - * edac_pci_workq_setup() - * initialize a workq item for this edac_pci instance - * passing in the new delay period in msec - * - * locking model: - * called when 'edac_pci_ctls_mutex' is locked - */ -static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci, - unsigned int msec) -{ - edac_dbg(0, "\n"); - - INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function); - - edac_queue_work(&pci->work, msecs_to_jiffies(edac_pci_get_poll_msec())); -} - -/* - * edac_pci_workq_teardown() - * stop the workq processing on this edac_pci instance - */ -static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) -{ - edac_dbg(0, "\n"); - - edac_stop_work(&pci->work); -} - /* * edac_pci_alloc_index: Allocate a unique PCI index number * @@ -290,7 +261,9 @@ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx) if (pci->edac_check) { pci->op_state = OP_RUNNING_POLL; - edac_pci_workq_setup(pci, 1000); + INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function); + edac_queue_work(&pci->work, msecs_to_jiffies(edac_pci_get_poll_msec())); + } else { pci->op_state = OP_RUNNING_INTERRUPT; } @@ -349,7 +322,7 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev) mutex_unlock(&edac_pci_ctls_mutex); if (pci->edac_check) - edac_pci_workq_teardown(pci); + edac_stop_work(&pci->work); edac_printk(KERN_INFO, EDAC_PCI, "Removed device %d for %s %s: DEV %s\n", -- cgit v1.2.3 From 06e912d4d4c2624c169997e26b3d7b5746735a14 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 2 Feb 2016 11:36:11 +0100 Subject: EDAC: Cleanup/sync workqueue functions They're both running only when ->edac_check is initialized so remove that check from the workqueue function itself. Synchronize/generalize the ->op_state check between the two. Kill useless comments, while at it. Signed-off-by: Borislav Petkov --- drivers/edac/edac_mc.c | 8 +++----- drivers/edac/edac_pci.c | 30 +++++++++++++++--------------- 2 files changed, 18 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 050493edb505..1472f48c8ac6 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -535,19 +535,17 @@ static void edac_mc_workq_function(struct work_struct *work_req) mutex_lock(&mem_ctls_mutex); - /* if this control struct has movd to offline state, we are done */ - if (mci->op_state == OP_OFFLINE) { + if (mci->op_state != OP_RUNNING_POLL) { mutex_unlock(&mem_ctls_mutex); return; } - /* Only poll controllers that are running polled and have a check */ - if (edac_mc_assert_error_check_and_clear() && (mci->edac_check != NULL)) + if (edac_mc_assert_error_check_and_clear()) mci->edac_check(mci); mutex_unlock(&mem_ctls_mutex); - /* Reschedule */ + /* Queue ourselves again. */ edac_queue_work(&mci->work, msecs_to_jiffies(edac_mc_get_poll_msec())); } diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index 79945e0df0dc..8f2f2899a7a2 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c @@ -195,23 +195,23 @@ static void edac_pci_workq_function(struct work_struct *work_req) mutex_lock(&edac_pci_ctls_mutex); - if (pci->op_state == OP_RUNNING_POLL) { - /* we might be in POLL mode, but there may NOT be a poll func - */ - if ((pci->edac_check != NULL) && edac_pci_get_check_errors()) - pci->edac_check(pci); - - /* if we are on a one second period, then use round */ - msec = edac_pci_get_poll_msec(); - if (msec == 1000) - delay = round_jiffies_relative(msecs_to_jiffies(msec)); - else - delay = msecs_to_jiffies(msec); - - /* Reschedule only if we are in POLL mode */ - edac_queue_work(&pci->work, delay); + if (pci->op_state != OP_RUNNING_POLL) { + mutex_unlock(&edac_pci_ctls_mutex); + return; } + if (edac_pci_get_check_errors()) + pci->edac_check(pci); + + /* if we are on a one second period, then use round */ + msec = edac_pci_get_poll_msec(); + if (msec == 1000) + delay = round_jiffies_relative(msecs_to_jiffies(msec)); + else + delay = msecs_to_jiffies(msec); + + edac_queue_work(&pci->work, delay); + mutex_unlock(&edac_pci_ctls_mutex); } -- cgit v1.2.3 From e9c8dc8ba96b165ae72daad3b1f27823c3aee628 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Thu, 10 Dec 2015 17:28:37 +0000 Subject: mailbox: pcc: fix channel calculation in get_pcc_channel() This patch fixes the calculation of pcc_chan for non-zero id. After the compiler ignores the (unsigned long) cast the pcc_mbox_channels pointer is type-cast and then the type-cast offset is added which results in address outside of the range leading to the kernel crashing. We might add braces and make it: pcc_chan = (struct mbox_chan *) ((unsigned long) pcc_mbox_channels + (id * sizeof(*pcc_chan))); but let's go with array approach here and use id as index. Tested on Juno board. Signed-off-by: Alexey Klimov Acked-by: Sudeep Holla Acked-by: Ashwin Chaugule Signed-off-by: Jassi Brar --- drivers/mailbox/pcc.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index 45d85aea9955..8f779a1ec99c 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -81,16 +81,10 @@ static struct mbox_controller pcc_mbox_ctrl = {}; */ static struct mbox_chan *get_pcc_channel(int id) { - struct mbox_chan *pcc_chan; - if (id < 0 || id > pcc_mbox_ctrl.num_chans) return ERR_PTR(-ENOENT); - pcc_chan = (struct mbox_chan *) - (unsigned long) pcc_mbox_channels + - (id * sizeof(*pcc_chan)); - - return pcc_chan; + return &pcc_mbox_channels[id]; } /** -- cgit v1.2.3 From 65d3b04a814679a31fe4d5edd19d89dd5b94fd40 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 25 Jan 2016 23:24:09 +0100 Subject: mailbox: Fix dependencies for !HAS_IOMEM archs Not every arch has io memory. So, unbreak the build by fixing the dependencies. Signed-off-by: Richard Weinberger Signed-off-by: Jassi Brar --- drivers/mailbox/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 546d05f4358a..b2bbe8659bed 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -81,6 +81,7 @@ config STI_MBOX config MAILBOX_TEST tristate "Mailbox Test Client" depends on OF + depends on HAS_IOMEM help Test client to help with testing new Controller driver implementations. -- cgit v1.2.3 From 41c89159a6ae5472d39ed8bded5b3b4e07a37944 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Fri, 29 Jan 2016 00:21:26 +0100 Subject: mmc: pxamci: fix again read-only gpio detection polarity The commit fixing the conversion of pxamci to slot-gpio API fixed the inverted the logic of the read-only gpio. Unfortunately, the commit was tested on a non-inverted gpio, and not on the inverted one. And the fix did work partially, by luck. This is the remaining missing part of the fix, trivial but still necessary. Fixes: Fixes: 26d49fe71953 ("mmc: pxamci: fix read-only gpio detection polarity") Reported-by: Andrea Adami Tested-by: Andrea Adami Signed-off-by: Robert Jarzmik Cc: stable@vger.kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/pxamci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index ce08896b9d69..28a057fae0a1 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -804,7 +804,7 @@ static int pxamci_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed requesting gpio_ro %d\n", gpio_ro); goto out; } else { - mmc->caps |= host->pdata->gpio_card_ro_invert ? + mmc->caps2 |= host->pdata->gpio_card_ro_invert ? 0 : MMC_CAP2_RO_ACTIVE_HIGH; } -- cgit v1.2.3 From 875e94392ad2be9776c8325d3573160eb1455a2b Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Thu, 28 Jan 2016 19:24:02 +0200 Subject: wil6210: prevent access to vring_tx_data lock during its init wil_tx_vring locks the vring_tx_data lock before accessing the TX vring to check if it is enabled and valid for use. In case of quick disconnect / connect events for the same station, spin_lock(&txdata->lock) can be called during the lock initialization in the vring init function. To prevent such a race, the TX vrings spin lock should be initialized once during wil6210 driver initialization. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/main.c | 3 +++ drivers/net/wireless/ath/wil6210/txrx.c | 26 +++++++++++++++++++++----- 2 files changed, 24 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 0652efed6b5d..712ebbfbdeb8 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -438,6 +438,9 @@ int wil_priv_init(struct wil6210_priv *wil) for (i = 0; i < WIL6210_MAX_CID; i++) spin_lock_init(&wil->sta[i].tid_rx_lock); + for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) + spin_lock_init(&wil->vring_tx_data[i].lock); + mutex_init(&wil->mutex); mutex_init(&wil->wmi_mutex); mutex_init(&wil->back_rx_mutex); diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 9680b970b863..6af20903cf89 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -717,6 +717,21 @@ void wil_rx_fini(struct wil6210_priv *wil) wil_vring_free(wil, vring, 0); } +static inline void wil_tx_data_init(struct vring_tx_data *txdata) +{ + spin_lock_bh(&txdata->lock); + txdata->dot1x_open = 0; + txdata->enabled = 0; + txdata->idle = 0; + txdata->last_idle = 0; + txdata->begin = 0; + txdata->agg_wsize = 0; + txdata->agg_timeout = 0; + txdata->agg_amsdu = 0; + txdata->addba_in_progress = false; + spin_unlock_bh(&txdata->lock); +} + int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, int cid, int tid) { @@ -758,8 +773,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, goto out; } - memset(txdata, 0, sizeof(*txdata)); - spin_lock_init(&txdata->lock); + wil_tx_data_init(txdata); vring->size = size; rc = wil_vring_alloc(wil, vring); if (rc) @@ -791,8 +805,10 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, return 0; out_free: + spin_lock_bh(&txdata->lock); txdata->dot1x_open = false; txdata->enabled = 0; + spin_unlock_bh(&txdata->lock); wil_vring_free(wil, vring, 1); wil->vring2cid_tid[id][0] = WIL6210_MAX_CID; wil->vring2cid_tid[id][1] = 0; @@ -834,8 +850,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) goto out; } - memset(txdata, 0, sizeof(*txdata)); - spin_lock_init(&txdata->lock); + wil_tx_data_init(txdata); vring->size = size; rc = wil_vring_alloc(wil, vring); if (rc) @@ -865,8 +880,10 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) return 0; out_free: + spin_lock_bh(&txdata->lock); txdata->enabled = 0; txdata->dot1x_open = false; + spin_unlock_bh(&txdata->lock); wil_vring_free(wil, vring, 1); out: @@ -894,7 +911,6 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) napi_synchronize(&wil->napi_tx); wil_vring_free(wil, vring, 1); - memset(txdata, 0, sizeof(*txdata)); } static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, -- cgit v1.2.3 From 78771d76f826202012201d700028a2d866d03fb3 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Thu, 28 Jan 2016 19:24:03 +0200 Subject: wil6210: wait for disconnect completion cfg80211_ops.disconnect() should wait for disconnect flow to complete. If it does not, internal state becomes out of sync with one in cfg80211. If one does stress test connect/disconnect sequence, cfg80211 will issue next connect before disconnect completed internally. Signed-off-by: Vladimir Kondratiev Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 13 ++++++++++++- drivers/net/wireless/ath/wil6210/main.c | 28 +++++++++------------------- drivers/net/wireless/ath/wil6210/wil6210.h | 1 + 3 files changed, 22 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 774352f9e256..97ad91eef4a6 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -535,7 +535,18 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy, wil_dbg_misc(wil, "%s(reason=%d)\n", __func__, reason_code); - rc = wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0); + if (!(test_bit(wil_status_fwconnecting, wil->status) || + test_bit(wil_status_fwconnected, wil->status))) { + wil_err(wil, "%s: Disconnect was called while disconnected\n", + __func__); + return 0; + } + + rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0, + WMI_DISCONNECT_EVENTID, NULL, 0, + WIL6210_DISCONNECT_TO_MS); + if (rc) + wil_err(wil, "%s: disconnect error %d\n", __func__, rc); return rc; } diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 712ebbfbdeb8..78ba6e04c944 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -23,9 +23,6 @@ #include "wmi.h" #include "boot_loader.h" -#define WAIT_FOR_DISCONNECT_TIMEOUT_MS 2000 -#define WAIT_FOR_DISCONNECT_INTERVAL_MS 10 - bool debug_fw; /* = false; */ module_param(debug_fw, bool, S_IRUGO); MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug"); @@ -942,8 +939,7 @@ int wil_up(struct wil6210_priv *wil) int __wil_down(struct wil6210_priv *wil) { - int iter = WAIT_FOR_DISCONNECT_TIMEOUT_MS / - WAIT_FOR_DISCONNECT_INTERVAL_MS; + int rc; WARN_ON(!mutex_is_locked(&wil->mutex)); @@ -967,22 +963,16 @@ int __wil_down(struct wil6210_priv *wil) } if (test_bit(wil_status_fwconnected, wil->status) || - test_bit(wil_status_fwconnecting, wil->status)) - wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0); + test_bit(wil_status_fwconnecting, wil->status)) { - /* make sure wil is idle (not connected) */ - mutex_unlock(&wil->mutex); - while (iter--) { - int idle = !test_bit(wil_status_fwconnected, wil->status) && - !test_bit(wil_status_fwconnecting, wil->status); - if (idle) - break; - msleep(WAIT_FOR_DISCONNECT_INTERVAL_MS); + mutex_unlock(&wil->mutex); + rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0, + WMI_DISCONNECT_EVENTID, NULL, 0, + WIL6210_DISCONNECT_TO_MS); + mutex_lock(&wil->mutex); + if (rc) + wil_err(wil, "timeout waiting for disconnect\n"); } - mutex_lock(&wil->mutex); - - if (iter < 0) - wil_err(wil, "timeout waiting for idle FW/HW\n"); wil_reset(wil, false); diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 1b8fa1d2bae9..950296507dd1 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -92,6 +92,7 @@ static inline u32 wil_mtu2macbuf(u32 mtu) #define WIL6210_FW_RECOVERY_RETRIES (5) /* try to recover this many times */ #define WIL6210_FW_RECOVERY_TO msecs_to_jiffies(5000) #define WIL6210_SCAN_TO msecs_to_jiffies(10000) +#define WIL6210_DISCONNECT_TO_MS (2000) #define WIL6210_RX_HIGH_TRSH_INIT (0) #define WIL6210_RX_HIGH_TRSH_DEFAULT \ (1 << (WIL_RX_RING_SIZE_ORDER_DEFAULT - 3)) -- cgit v1.2.3 From fe5c271e2878fb080f1b32fec5b4e3f7a6070152 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Thu, 28 Jan 2016 19:24:04 +0200 Subject: wil6210: protect synchronous wmi commands handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case there are multiple WMI commands with the same reply_id, the following scenario can occur: - Driver sends the first command to the device - The reply didn’t get on time and there is timeout - Reply_id, reply_buf and reply_size are set to 0 - Driver sends second wmi command with the same reply_id as the first - Driver sets wil->reply_id - Reply for the first wmi command arrives and handled by wmi_recv_cmd - As its ID fits the reply_id but the reply_buf is not set yet it is handled as a reply with event handler, and WARN_ON is printed This patch guarantee atomic setting of all the reply variables and prevents the above scenario. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/wmi.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index e1a6cb8840ed..493e721c4fa7 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -838,6 +838,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) struct wil6210_mbox_hdr_wmi *wmi = &evt->event.wmi; u16 id = le16_to_cpu(wmi->id); u32 tstamp = le32_to_cpu(wmi->timestamp); + spin_lock_irqsave(&wil->wmi_ev_lock, flags); if (wil->reply_id && wil->reply_id == id) { if (wil->reply_buf) { memcpy(wil->reply_buf, wmi, @@ -845,6 +846,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) immed_reply = true; } } + spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); wil_dbg_wmi(wil, "WMI event 0x%04x MID %d @%d msec\n", id, wmi->mid, tstamp); @@ -888,13 +890,16 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, mutex_lock(&wil->wmi_mutex); + spin_lock(&wil->wmi_ev_lock); + wil->reply_id = reply_id; + wil->reply_buf = reply; + wil->reply_size = reply_size; + spin_unlock(&wil->wmi_ev_lock); + rc = __wmi_send(wil, cmdid, buf, len); if (rc) goto out; - wil->reply_id = reply_id; - wil->reply_buf = reply; - wil->reply_size = reply_size; remain = wait_for_completion_timeout(&wil->wmi_call, msecs_to_jiffies(to_msec)); if (0 == remain) { @@ -907,10 +912,14 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, cmdid, reply_id, to_msec - jiffies_to_msecs(remain)); } + +out: + spin_lock(&wil->wmi_ev_lock); wil->reply_id = 0; wil->reply_buf = NULL; wil->reply_size = 0; - out: + spin_unlock(&wil->wmi_ev_lock); + mutex_unlock(&wil->wmi_mutex); return rc; -- cgit v1.2.3 From ee5dfe0d240e21afe63bdd77bf1d4a386203aa6e Mon Sep 17 00:00:00 2001 From: Hamad Kadmany Date: Thu, 28 Jan 2016 19:24:05 +0200 Subject: wil6210: TX vring optimization Tx vring needs to be enlarged to get better performance for traffic over 2Gbps. Signed-off-by: Hamad Kadmany Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/debugfs.c | 6 +++--- drivers/net/wireless/ath/wil6210/wil6210.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 97bc186f9728..98c9148a3450 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -68,13 +68,13 @@ static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, seq_puts(s, "???\n"); } - if (vring->va && (vring->size < 1025)) { + if (vring->va && (vring->size <= (1 << WIL_RING_SIZE_ORDER_MAX))) { uint i; for (i = 0; i < vring->size; i++) { volatile struct vring_tx_desc *d = &vring->va[i].tx; - if ((i % 64) == 0 && (i != 0)) + if ((i % 128) == 0 && (i != 0)) seq_puts(s, "\n"); seq_printf(s, "%c", (d->dma.status & BIT(0)) ? _s : (vring->ctx[i].skb ? _h : 'h')); diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 950296507dd1..8427d68b6fa8 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -51,7 +51,7 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) #define WIL_TX_Q_LEN_DEFAULT (4000) #define WIL_RX_RING_SIZE_ORDER_DEFAULT (10) -#define WIL_TX_RING_SIZE_ORDER_DEFAULT (10) +#define WIL_TX_RING_SIZE_ORDER_DEFAULT (12) #define WIL_BCAST_RING_SIZE_ORDER_DEFAULT (7) #define WIL_BCAST_MCS0_LIMIT (1024) /* limit for MCS0 frame size */ /* limit ring size in range [32..32k] */ -- cgit v1.2.3 From 0b3d76e9f8b4a2b67358b454843ede30555f93a5 Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Thu, 28 Jan 2016 13:54:07 -0800 Subject: ath10k: rename Mesh related service names WMI_10_4_SERVICE_MESH bit is for non IEEE802.11s Mesh. Hence rename it to WMI_10_4_SERVICE_MESH_NON_11S. Also add _11S as post-fix to each of WMI_SERVICE_MESH and WMI_VDEV_SUBTYPE_MESH specifying the service is for 11s Mesh. This will help users to distinguish 11s Mesh from non 11s Mesh. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 4 ++-- drivers/net/wireless/ath/ath10k/wmi.h | 16 +++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index ef0438d2cc8f..1406b0f1d883 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4380,8 +4380,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, arvif->vdev_type = WMI_VDEV_TYPE_IBSS; break; case NL80211_IFTYPE_MESH_POINT: - if (test_bit(WMI_SERVICE_MESH, ar->wmi.svc_map)) { - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH; + if (test_bit(WMI_SERVICE_MESH_11S, ar->wmi.svc_map)) { + arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S; } else if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { ret = -EINVAL; ath10k_warn(ar, "must load driver with rawmode=1 to add mesh interfaces\n"); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 806d4bb6e7d6..0458bf6bcdfc 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -176,7 +176,8 @@ enum wmi_service { WMI_SERVICE_AUX_CHAN_LOAD_INTF, WMI_SERVICE_BSS_CHANNEL_INFO_64, WMI_SERVICE_EXT_RES_CFG_SUPPORT, - WMI_SERVICE_MESH, + WMI_SERVICE_MESH_11S, + WMI_SERVICE_MESH_NON_11S, WMI_SERVICE_PEER_STATS, /* keep last */ @@ -296,7 +297,7 @@ enum wmi_10_4_service { WMI_10_4_SERVICE_AUX_CHAN_LOAD_INTF, WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64, WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT, - WMI_10_4_SERVICE_MESH, + WMI_10_4_SERVICE_MESH_NON_11S, }; static inline char *wmi_service_name(int service_id) @@ -387,7 +388,8 @@ static inline char *wmi_service_name(int service_id) SVCSTR(WMI_SERVICE_AUX_CHAN_LOAD_INTF); SVCSTR(WMI_SERVICE_BSS_CHANNEL_INFO_64); SVCSTR(WMI_SERVICE_EXT_RES_CFG_SUPPORT); - SVCSTR(WMI_SERVICE_MESH); + SVCSTR(WMI_SERVICE_MESH_11S); + SVCSTR(WMI_SERVICE_MESH_NON_11S); SVCSTR(WMI_SERVICE_PEER_STATS); default: return NULL; @@ -463,7 +465,7 @@ static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out, SVCMAP(WMI_10X_SERVICE_BSS_CHANNEL_INFO_64, WMI_SERVICE_BSS_CHANNEL_INFO_64, len); SVCMAP(WMI_10X_SERVICE_MESH, - WMI_SERVICE_MESH, len); + WMI_SERVICE_MESH_11S, len); SVCMAP(WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT, WMI_SERVICE_EXT_RES_CFG_SUPPORT, len); SVCMAP(WMI_10X_SERVICE_PEER_STATS, @@ -628,8 +630,8 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out, WMI_SERVICE_BSS_CHANNEL_INFO_64, len); SVCMAP(WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT, WMI_SERVICE_EXT_RES_CFG_SUPPORT, len); - SVCMAP(WMI_10_4_SERVICE_MESH, - WMI_SERVICE_MESH, len); + SVCMAP(WMI_10_4_SERVICE_MESH_NON_11S, + WMI_SERVICE_MESH_NON_11S, len); } #undef SVCMAP @@ -4287,7 +4289,7 @@ enum wmi_vdev_subtype { WMI_VDEV_SUBTYPE_P2P_CLIENT = 2, WMI_VDEV_SUBTYPE_P2P_GO = 3, WMI_VDEV_SUBTYPE_PROXY_STA = 4, - WMI_VDEV_SUBTYPE_MESH = 5, + WMI_VDEV_SUBTYPE_MESH_11S = 5, }; /* values for vdev_subtype */ -- cgit v1.2.3 From e70e9ba9df8609908c34d042cf980c1a59c56900 Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Thu, 28 Jan 2016 13:54:08 -0800 Subject: ath10k: update 10.4 WMI service map Update 10.4 WMI service map to sync to the latest 10.4 firmware as of 1/20/2016. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 0458bf6bcdfc..031018a07231 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -179,6 +179,7 @@ enum wmi_service { WMI_SERVICE_MESH_11S, WMI_SERVICE_MESH_NON_11S, WMI_SERVICE_PEER_STATS, + WMI_SERVICE_RESTRT_CHNL_SUPPORT, /* keep last */ WMI_SERVICE_MAX, @@ -298,6 +299,9 @@ enum wmi_10_4_service { WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64, WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT, WMI_10_4_SERVICE_MESH_NON_11S, + WMI_10_4_SERVICE_RESTRT_CHNL_SUPPORT, + WMI_10_4_SERVICE_PEER_STATS, + WMI_10_4_SERVICE_MESH_11S, }; static inline char *wmi_service_name(int service_id) @@ -391,6 +395,7 @@ static inline char *wmi_service_name(int service_id) SVCSTR(WMI_SERVICE_MESH_11S); SVCSTR(WMI_SERVICE_MESH_NON_11S); SVCSTR(WMI_SERVICE_PEER_STATS); + SVCSTR(WMI_SERVICE_RESTRT_CHNL_SUPPORT); default: return NULL; } @@ -632,6 +637,12 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out, WMI_SERVICE_EXT_RES_CFG_SUPPORT, len); SVCMAP(WMI_10_4_SERVICE_MESH_NON_11S, WMI_SERVICE_MESH_NON_11S, len); + SVCMAP(WMI_10_4_SERVICE_RESTRT_CHNL_SUPPORT, + WMI_SERVICE_RESTRT_CHNL_SUPPORT, len); + SVCMAP(WMI_10_4_SERVICE_PEER_STATS, + WMI_SERVICE_PEER_STATS, len); + SVCMAP(WMI_10_4_SERVICE_MESH_11S, + WMI_SERVICE_MESH_11S, len); } #undef SVCMAP -- cgit v1.2.3 From 08c27be1db84dcdad14e86ec76d9c9915deb14eb Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Thu, 28 Jan 2016 13:54:09 -0800 Subject: ath10k: use vif->type and vif->p2p for P2P_GO check Interface type P2P_GO can be checked by either arvif->vdev_type and arvif->vdev_subtype or vif->type and vif->p2p. Use later one to avoid more cpu consumption that could happen when subtype abstraction layer change is introduced. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 8 ++------ drivers/net/wireless/ath/ath10k/wmi.c | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 1406b0f1d883..addf3cb3aeb1 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1358,10 +1358,7 @@ static int ath10k_mac_setup_bcn_p2p_ie(struct ath10k_vif *arvif, const u8 *p2p_ie; int ret; - if (arvif->vdev_type != WMI_VDEV_TYPE_AP) - return 0; - - if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) + if (arvif->vif->type != NL80211_IFTYPE_AP || !arvif->vif->p2p) return 0; mgmt = (void *)bcn->data; @@ -3259,8 +3256,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); /* This is case only for P2P_GO */ - if (arvif->vdev_type != WMI_VDEV_TYPE_AP || - arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) + if (vif->type != NL80211_IFTYPE_AP || !vif->p2p) return; if (unlikely(ieee80211_is_probe_resp(hdr->frame_control))) { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 0f01a8d99604..5158716d6dff 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -3196,7 +3196,7 @@ static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif, struct sk_buff *bcn, const struct wmi_p2p_noa_info *noa) { - if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) + if (!arvif->vif->p2p) return; ath10k_dbg(ar, ATH10K_DBG_MGMT, "noa changed: %d\n", noa->changed); -- cgit v1.2.3 From 6e4de1a49aa3254f46f66db5aac530707c193cde Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Thu, 28 Jan 2016 13:54:10 -0800 Subject: ath10k: add abstraction layer for vdev subtype Abstraction layer for vdev subtype is added to solve subtype mismatch and to give flexible compatibility among different firmware revisions. For instance, 10.2 and 10.4 firmware has different definition of their vdev subtypes for Mesh. 10.4 defined subtype 6 for 802.11s Mesh while 10.2 uses 5. Hence use the abstraction API to get right subtype to use. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 15 ++++--- drivers/net/wireless/ath/ath10k/wmi-ops.h | 11 +++++ drivers/net/wireless/ath/ath10k/wmi-tlv.c | 1 + drivers/net/wireless/ath/ath10k/wmi.c | 70 +++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.h | 42 ++++++++++++++++--- 5 files changed, 128 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index addf3cb3aeb1..96e2f8ad22fc 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4359,25 +4359,29 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, bit, ar->free_vdev_map); arvif->vdev_id = bit; - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; + arvif->vdev_subtype = + ath10k_wmi_get_vdev_subtype(ar, WMI_VDEV_SUBTYPE_NONE); switch (vif->type) { case NL80211_IFTYPE_P2P_DEVICE: arvif->vdev_type = WMI_VDEV_TYPE_STA; - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE; + arvif->vdev_subtype = ath10k_wmi_get_vdev_subtype + (ar, WMI_VDEV_SUBTYPE_P2P_DEVICE); break; case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_STATION: arvif->vdev_type = WMI_VDEV_TYPE_STA; if (vif->p2p) - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_CLIENT; + arvif->vdev_subtype = ath10k_wmi_get_vdev_subtype + (ar, WMI_VDEV_SUBTYPE_P2P_CLIENT); break; case NL80211_IFTYPE_ADHOC: arvif->vdev_type = WMI_VDEV_TYPE_IBSS; break; case NL80211_IFTYPE_MESH_POINT: if (test_bit(WMI_SERVICE_MESH_11S, ar->wmi.svc_map)) { - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S; + arvif->vdev_subtype = ath10k_wmi_get_vdev_subtype + (ar, WMI_VDEV_SUBTYPE_MESH_11S); } else if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { ret = -EINVAL; ath10k_warn(ar, "must load driver with rawmode=1 to add mesh interfaces\n"); @@ -4389,7 +4393,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, arvif->vdev_type = WMI_VDEV_TYPE_AP; if (vif->p2p) - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_GO; + arvif->vdev_subtype = ath10k_wmi_get_vdev_subtype + (ar, WMI_VDEV_SUBTYPE_P2P_GO); break; case NL80211_IFTYPE_MONITOR: arvif->vdev_type = WMI_VDEV_TYPE_MONITOR; diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index 8f4f6a892581..32ab34edceb5 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h @@ -186,6 +186,8 @@ struct wmi_ops { u8 enable, u32 detect_level, u32 detect_margin); + int (*get_vdev_subtype)(struct ath10k *ar, + enum wmi_vdev_subtype subtype); }; int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); @@ -1327,4 +1329,13 @@ ath10k_wmi_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable, ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid); } +static inline int +ath10k_wmi_get_vdev_subtype(struct ath10k *ar, enum wmi_vdev_subtype subtype) +{ + if (!ar->wmi.ops->get_vdev_subtype) + return -EOPNOTSUPP; + + return ar->wmi.ops->get_vdev_subtype(ar, subtype); +} + #endif diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 3b3a27b859f3..108593202052 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -3483,6 +3483,7 @@ static const struct wmi_ops wmi_tlv_ops = { .gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update, .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs, .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, + .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, }; static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 5158716d6dff..04799c73ebc8 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -7413,6 +7413,71 @@ unlock: buf[len] = 0; } +int ath10k_wmi_op_get_vdev_subtype(struct ath10k *ar, + enum wmi_vdev_subtype subtype) +{ + switch (subtype) { + case WMI_VDEV_SUBTYPE_NONE: + return WMI_VDEV_SUBTYPE_LEGACY_NONE; + case WMI_VDEV_SUBTYPE_P2P_DEVICE: + return WMI_VDEV_SUBTYPE_LEGACY_P2P_DEV; + case WMI_VDEV_SUBTYPE_P2P_CLIENT: + return WMI_VDEV_SUBTYPE_LEGACY_P2P_CLI; + case WMI_VDEV_SUBTYPE_P2P_GO: + return WMI_VDEV_SUBTYPE_LEGACY_P2P_GO; + case WMI_VDEV_SUBTYPE_PROXY_STA: + return WMI_VDEV_SUBTYPE_LEGACY_PROXY_STA; + case WMI_VDEV_SUBTYPE_MESH_11S: + case WMI_VDEV_SUBTYPE_MESH_NON_11S: + return -ENOTSUPP; + } + return -ENOTSUPP; +} + +static int ath10k_wmi_10_2_4_op_get_vdev_subtype(struct ath10k *ar, + enum wmi_vdev_subtype subtype) +{ + switch (subtype) { + case WMI_VDEV_SUBTYPE_NONE: + return WMI_VDEV_SUBTYPE_10_2_4_NONE; + case WMI_VDEV_SUBTYPE_P2P_DEVICE: + return WMI_VDEV_SUBTYPE_10_2_4_P2P_DEV; + case WMI_VDEV_SUBTYPE_P2P_CLIENT: + return WMI_VDEV_SUBTYPE_10_2_4_P2P_CLI; + case WMI_VDEV_SUBTYPE_P2P_GO: + return WMI_VDEV_SUBTYPE_10_2_4_P2P_GO; + case WMI_VDEV_SUBTYPE_PROXY_STA: + return WMI_VDEV_SUBTYPE_10_2_4_PROXY_STA; + case WMI_VDEV_SUBTYPE_MESH_11S: + return WMI_VDEV_SUBTYPE_10_2_4_MESH_11S; + case WMI_VDEV_SUBTYPE_MESH_NON_11S: + return -ENOTSUPP; + } + return -ENOTSUPP; +} + +static int ath10k_wmi_10_4_op_get_vdev_subtype(struct ath10k *ar, + enum wmi_vdev_subtype subtype) +{ + switch (subtype) { + case WMI_VDEV_SUBTYPE_NONE: + return WMI_VDEV_SUBTYPE_10_4_NONE; + case WMI_VDEV_SUBTYPE_P2P_DEVICE: + return WMI_VDEV_SUBTYPE_10_4_P2P_DEV; + case WMI_VDEV_SUBTYPE_P2P_CLIENT: + return WMI_VDEV_SUBTYPE_10_4_P2P_CLI; + case WMI_VDEV_SUBTYPE_P2P_GO: + return WMI_VDEV_SUBTYPE_10_4_P2P_GO; + case WMI_VDEV_SUBTYPE_PROXY_STA: + return WMI_VDEV_SUBTYPE_10_4_PROXY_STA; + case WMI_VDEV_SUBTYPE_MESH_11S: + return WMI_VDEV_SUBTYPE_10_4_MESH_11S; + case WMI_VDEV_SUBTYPE_MESH_NON_11S: + return WMI_VDEV_SUBTYPE_10_4_MESH_NON_11S; + } + return -ENOTSUPP; +} + static const struct wmi_ops wmi_ops = { .rx = ath10k_wmi_op_rx, .map_svc = wmi_main_svc_map, @@ -7472,6 +7537,7 @@ static const struct wmi_ops wmi_ops = { .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_delba_send = ath10k_wmi_op_gen_delba_send, .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, + .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ @@ -7539,6 +7605,7 @@ static const struct wmi_ops wmi_10_1_ops = { .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_delba_send = ath10k_wmi_op_gen_delba_send, .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, + .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ @@ -7607,6 +7674,7 @@ static const struct wmi_ops wmi_10_2_ops = { .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_delba_send = ath10k_wmi_op_gen_delba_send, .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, + .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, /* .gen_pdev_enable_adaptive_cca not implemented */ }; @@ -7673,6 +7741,7 @@ static const struct wmi_ops wmi_10_2_4_ops = { .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, .gen_pdev_enable_adaptive_cca = ath10k_wmi_op_gen_pdev_enable_adaptive_cca, + .get_vdev_subtype = ath10k_wmi_10_2_4_op_get_vdev_subtype, /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ @@ -7739,6 +7808,7 @@ static const struct wmi_ops wmi_10_4_ops = { /* shared with 10.2 */ .gen_request_stats = ath10k_wmi_op_gen_request_stats, .gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature, + .get_vdev_subtype = ath10k_wmi_10_4_op_get_vdev_subtype, }; int ath10k_wmi_attach(struct ath10k *ar) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 031018a07231..049c61820765 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4295,12 +4295,40 @@ enum wmi_vdev_type { }; enum wmi_vdev_subtype { - WMI_VDEV_SUBTYPE_NONE = 0, - WMI_VDEV_SUBTYPE_P2P_DEVICE = 1, - WMI_VDEV_SUBTYPE_P2P_CLIENT = 2, - WMI_VDEV_SUBTYPE_P2P_GO = 3, - WMI_VDEV_SUBTYPE_PROXY_STA = 4, - WMI_VDEV_SUBTYPE_MESH_11S = 5, + WMI_VDEV_SUBTYPE_NONE, + WMI_VDEV_SUBTYPE_P2P_DEVICE, + WMI_VDEV_SUBTYPE_P2P_CLIENT, + WMI_VDEV_SUBTYPE_P2P_GO, + WMI_VDEV_SUBTYPE_PROXY_STA, + WMI_VDEV_SUBTYPE_MESH_11S, + WMI_VDEV_SUBTYPE_MESH_NON_11S, +}; + +enum wmi_vdev_subtype_legacy { + WMI_VDEV_SUBTYPE_LEGACY_NONE = 0, + WMI_VDEV_SUBTYPE_LEGACY_P2P_DEV = 1, + WMI_VDEV_SUBTYPE_LEGACY_P2P_CLI = 2, + WMI_VDEV_SUBTYPE_LEGACY_P2P_GO = 3, + WMI_VDEV_SUBTYPE_LEGACY_PROXY_STA = 4, +}; + +enum wmi_vdev_subtype_10_2_4 { + WMI_VDEV_SUBTYPE_10_2_4_NONE = 0, + WMI_VDEV_SUBTYPE_10_2_4_P2P_DEV = 1, + WMI_VDEV_SUBTYPE_10_2_4_P2P_CLI = 2, + WMI_VDEV_SUBTYPE_10_2_4_P2P_GO = 3, + WMI_VDEV_SUBTYPE_10_2_4_PROXY_STA = 4, + WMI_VDEV_SUBTYPE_10_2_4_MESH_11S = 5, +}; + +enum wmi_vdev_subtype_10_4 { + WMI_VDEV_SUBTYPE_10_4_NONE = 0, + WMI_VDEV_SUBTYPE_10_4_P2P_DEV = 1, + WMI_VDEV_SUBTYPE_10_4_P2P_CLI = 2, + WMI_VDEV_SUBTYPE_10_4_P2P_GO = 3, + WMI_VDEV_SUBTYPE_10_4_PROXY_STA = 4, + WMI_VDEV_SUBTYPE_10_4_MESH_NON_11S = 5, + WMI_VDEV_SUBTYPE_10_4_MESH_11S = 6, }; /* values for vdev_subtype */ @@ -6471,5 +6499,7 @@ size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head); void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, struct ath10k_fw_stats *fw_stats, char *buf); +int ath10k_wmi_op_get_vdev_subtype(struct ath10k *ar, + enum wmi_vdev_subtype subtype); #endif /* _WMI_H_ */ -- cgit v1.2.3 From b1a958c933c5b0f967844ec05e76ec2985450782 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Fri, 29 Jan 2016 16:35:11 +0530 Subject: ath10k: add qca4019 hw params Add a new entry in hw_params_list for qca4019 with list of it's own details. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 20 ++++++++++++++++++++ drivers/net/wireless/ath/ath10k/hw.h | 8 ++++++++ drivers/net/wireless/ath/ath10k/targaddrs.h | 3 +++ 3 files changed, 31 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 1f4a27881936..79043872e7ac 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -201,6 +201,26 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, }, }, + { + .id = QCA4019_HW_1_0_DEV_VERSION, + .dev_id = 0, + .name = "qca4019 hw1.0", + .patch_load_addr = QCA4019_HW_1_0_PATCH_LOAD_ADDR, + .uart_pin = 7, + .otp_exe_param = 0x0010000, + .continuous_frag_desc = true, + .channel_counters_freq_hz = 125000, + .max_probe_resp_desc_thres = 24, + .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, + .fw = { + .dir = QCA4019_HW_1_0_FW_DIR, + .fw = QCA4019_HW_1_0_FW_FILE, + .otp = QCA4019_HW_1_0_OTP_FILE, + .board = QCA4019_HW_1_0_BOARD_DATA_FILE, + .board_size = QCA4019_BOARD_DATA_SZ, + .board_ext_size = QCA4019_BOARD_EXT_DATA_SZ, + }, + }, }; static const char *const ath10k_core_fw_feature_str[] = { diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 4217bdbe9f01..291ca1f798e3 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -106,6 +106,14 @@ enum qca9377_chip_id_rev { #define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin" #define QCA9377_HW_1_0_PATCH_LOAD_ADDR 0x1234 +/* QCA4019 1.0 definitions */ +#define QCA4019_HW_1_0_DEV_VERSION 0x01000000 +#define QCA4019_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA4019/hw1.0" +#define QCA4019_HW_1_0_FW_FILE "firmware.bin" +#define QCA4019_HW_1_0_OTP_FILE "otp.bin" +#define QCA4019_HW_1_0_BOARD_DATA_FILE "board.bin" +#define QCA4019_HW_1_0_PATCH_LOAD_ADDR 0x1234 + #define ATH10K_FW_API2_FILE "firmware-2.bin" #define ATH10K_FW_API3_FILE "firmware-3.bin" diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h index 05a421bc322a..361f143b019c 100644 --- a/drivers/net/wireless/ath/ath10k/targaddrs.h +++ b/drivers/net/wireless/ath/ath10k/targaddrs.h @@ -456,4 +456,7 @@ Fw Mode/SubMode Mask #define QCA99X0_BOARD_DATA_SZ 12288 #define QCA99X0_BOARD_EXT_DATA_SZ 0 +#define QCA4019_BOARD_DATA_SZ 12064 +#define QCA4019_BOARD_EXT_DATA_SZ 0 + #endif /* __TARGADDRS_H__ */ -- cgit v1.2.3 From 5699a6f238ebfc8a6be3963a30d86d6f1e8aaaf9 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Fri, 29 Jan 2016 16:35:12 +0530 Subject: ath10k: populate qca4019 fw specific wmi init params Some of the parameter like tx/rx chain mask, number of htt tx desc, qcache active peer count, etc goes via wmi init cmd to qca4019 firmware are different. To make use of 10.4 gen_init function for qca4019, change wmi service ready handler and 10.4 wmi init functions to adapt qca4019 specific init values. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 14 ++++++++++++-- drivers/net/wireless/ath/ath10k/core.h | 6 ++++++ drivers/net/wireless/ath/ath10k/hw.h | 6 ------ drivers/net/wireless/ath/ath10k/wmi.c | 12 ++++++------ drivers/net/wireless/ath/ath10k/wmi.h | 1 - 5 files changed, 24 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 79043872e7ac..4d3176492ae7 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -156,6 +156,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .channel_counters_freq_hz = 150000, .max_probe_resp_desc_thres = 24, .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, + .num_msdu_desc = 1424, + .qcache_active_peers = 50, + .tx_chain_mask = 0xf, + .rx_chain_mask = 0xf, + .max_spatial_stream = 4, .fw = { .dir = QCA99X0_HW_2_0_FW_DIR, .fw = QCA99X0_HW_2_0_FW_FILE, @@ -212,6 +217,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .channel_counters_freq_hz = 125000, .max_probe_resp_desc_thres = 24, .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, + .num_msdu_desc = 2500, + .qcache_active_peers = 35, + .tx_chain_mask = 0x3, + .rx_chain_mask = 0x3, + .max_spatial_stream = 2, .fw = { .dir = QCA4019_HW_1_0_FW_DIR, .fw = QCA4019_HW_1_0_FW_FILE, @@ -1523,9 +1533,9 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS; ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS; ar->num_tids = TARGET_10_4_TGT_NUM_TIDS; - ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC; + ar->htt.max_num_pending_tx = ar->hw_params.num_msdu_desc; ar->fw_stats_req_mask = WMI_STAT_PEER; - ar->max_spatial_stream = WMI_10_4_MAX_SPATIAL_STREAM; + ar->max_spatial_stream = ar->hw_params.max_spatial_stream; break; case ATH10K_FW_WMI_OP_VERSION_UNSET: case ATH10K_FW_WMI_OP_VERSION_MAX: diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 2e411b5258c2..a62b62a62266 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -680,6 +680,12 @@ struct ath10k { /* The padding bytes's location is different on various chips */ enum ath10k_hw_4addr_pad hw_4addr_pad; + u32 num_msdu_desc; + u32 qcache_active_peers; + u32 tx_chain_mask; + u32 rx_chain_mask; + u32 max_spatial_stream; + struct ath10k_hw_params_fw { const char *dir; const char *fw; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 291ca1f798e3..2dece8db83f8 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -426,16 +426,11 @@ enum ath10k_hw_4addr_pad { #define TARGET_10_4_ACTIVE_PEERS 0 #define TARGET_10_4_NUM_QCACHE_PEERS_MAX 512 -#define TARGET_10_4_QCACHE_ACTIVE_PEERS 50 #define TARGET_10_4_NUM_OFFLOAD_PEERS 0 #define TARGET_10_4_NUM_OFFLOAD_REORDER_BUFFS 0 #define TARGET_10_4_NUM_PEER_KEYS 2 #define TARGET_10_4_TGT_NUM_TIDS ((TARGET_10_4_NUM_PEERS) * 2) #define TARGET_10_4_AST_SKID_LIMIT 32 -#define TARGET_10_4_TX_CHAIN_MASK (BIT(0) | BIT(1) | \ - BIT(2) | BIT(3)) -#define TARGET_10_4_RX_CHAIN_MASK (BIT(0) | BIT(1) | \ - BIT(2) | BIT(3)) /* 100 ms for video, best-effort, and background */ #define TARGET_10_4_RX_TIMEOUT_LO_PRI 100 @@ -461,7 +456,6 @@ enum ath10k_hw_4addr_pad { #define TARGET_10_4_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1 #define TARGET_10_4_VOW_CONFIG 0 #define TARGET_10_4_GTK_OFFLOAD_MAX_VDEV 3 -#define TARGET_10_4_NUM_MSDU_DESC (1024 + 400) #define TARGET_10_4_11AC_TX_MAX_FRAGS 2 #define TARGET_10_4_MAX_PEER_EXT_STATS 16 #define TARGET_10_4_SMART_ANT_CAP 0 diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 04799c73ebc8..1ce67423224a 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -4618,9 +4618,9 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) if (test_bit(WMI_SERVICE_PEER_CACHING, ar->wmi.svc_map)) { ar->max_num_peers = TARGET_10_4_NUM_QCACHE_PEERS_MAX + - TARGET_10_4_NUM_VDEVS; - ar->num_active_peers = TARGET_10_4_QCACHE_ACTIVE_PEERS + - TARGET_10_4_NUM_VDEVS; + ar->max_num_vdevs; + ar->num_active_peers = ar->hw_params.qcache_active_peers + + ar->max_num_vdevs; ar->num_tids = ar->num_active_peers * 2; ar->max_num_stations = TARGET_10_4_NUM_QCACHE_PEERS_MAX; } @@ -5602,8 +5602,8 @@ static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar) __cpu_to_le32(TARGET_10_4_NUM_OFFLOAD_REORDER_BUFFS); config.num_peer_keys = __cpu_to_le32(TARGET_10_4_NUM_PEER_KEYS); config.ast_skid_limit = __cpu_to_le32(TARGET_10_4_AST_SKID_LIMIT); - config.tx_chain_mask = __cpu_to_le32(TARGET_10_4_TX_CHAIN_MASK); - config.rx_chain_mask = __cpu_to_le32(TARGET_10_4_RX_CHAIN_MASK); + config.tx_chain_mask = __cpu_to_le32(ar->hw_params.tx_chain_mask); + config.rx_chain_mask = __cpu_to_le32(ar->hw_params.rx_chain_mask); config.rx_timeout_pri[0] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_LO_PRI); config.rx_timeout_pri[1] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_LO_PRI); @@ -5634,7 +5634,7 @@ static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar) config.vow_config = __cpu_to_le32(TARGET_10_4_VOW_CONFIG); config.gtk_offload_max_vdev = __cpu_to_le32(TARGET_10_4_GTK_OFFLOAD_MAX_VDEV); - config.num_msdu_desc = __cpu_to_le32(TARGET_10_4_NUM_MSDU_DESC); + config.num_msdu_desc = __cpu_to_le32(ar->htt.max_num_pending_tx); config.max_frag_entries = __cpu_to_le32(TARGET_10_4_11AC_TX_MAX_FRAGS); config.max_peer_ext_stats = __cpu_to_le32(TARGET_10_4_MAX_PEER_EXT_STATS); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 049c61820765..4d3cbc44fcd2 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -1818,7 +1818,6 @@ enum wmi_channel_change_cause { #define WMI_CHANNEL_CHANGE_CAUSE_CSA (1 << 13) #define WMI_MAX_SPATIAL_STREAM 3 /* default max ss */ -#define WMI_10_4_MAX_SPATIAL_STREAM 4 /* HT Capabilities*/ #define WMI_HT_CAP_ENABLED 0x0001 /* HT Enabled/ disabled */ -- cgit v1.2.3 From 2df9d58fcc0f20d812f390e0b97df69d70d3152f Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 2 Feb 2016 19:55:06 +0800 Subject: mmc: sdhci-of-at91: fix pm runtime unbalanced issue in error path The device power usage counter is increased by pm_runtime_get_noresume but isn't decreased in err_add_host error path. Fix this issue by calling pm_runtime_put_noidle() in the error path to restore the device's power usage counter. Signed-off-by: Jisheng Zhang Acked-by: Ludovic Desroches Fixes: f5f17813ae9b ("mmc: sdhci-of-at91: add PM support) Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-at91.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c index 7e7d8f0c9438..9cb86fb25976 100644 --- a/drivers/mmc/host/sdhci-of-at91.c +++ b/drivers/mmc/host/sdhci-of-at91.c @@ -217,6 +217,7 @@ static int sdhci_at91_probe(struct platform_device *pdev) pm_runtime_disable: pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); clocks_disable_unprepare: clk_disable_unprepare(priv->gck); clk_disable_unprepare(priv->mainck); -- cgit v1.2.3 From 2d6f5f0cf6bfb17b8f0102cabe0665098ce0a865 Mon Sep 17 00:00:00 2001 From: Vishnu Patekar Date: Sun, 31 Jan 2016 09:20:54 +0800 Subject: clk: sunxi: Add apb0 gates for A83T APB0 is part of PRCM, and is compatible with earlier SOCs. apb0 gates controls R_PIO, R_UART, R_RSB, etc clocks. This patch adds support for APB0 gates for A83T. Signed-off-by: Vishnu Patekar Acked-by: Rob Herring Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/clock/sunxi.txt | 1 + drivers/clk/sunxi/clk-simple-gates.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index e59f57b24777..7f19ef55d61f 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -39,6 +39,7 @@ Required properties: "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31 "allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23 "allwinner,sun9i-a80-apb0-clk" - for the APB0 bus clock on A80 + "allwinner,sun8i-a83t-apb0-gates-clk" - for the APB0 gates on A83T "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10 "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s diff --git a/drivers/clk/sunxi/clk-simple-gates.c b/drivers/clk/sunxi/clk-simple-gates.c index f4da52b5ca0e..2cfc5a8a5534 100644 --- a/drivers/clk/sunxi/clk-simple-gates.c +++ b/drivers/clk/sunxi/clk-simple-gates.c @@ -130,6 +130,8 @@ CLK_OF_DECLARE(sun8i_a23_apb2, "allwinner,sun8i-a23-apb2-gates-clk", sunxi_simple_gates_init); CLK_OF_DECLARE(sun8i_a33_ahb1, "allwinner,sun8i-a33-ahb1-gates-clk", sunxi_simple_gates_init); +CLK_OF_DECLARE(sun8i_a83t_apb0, "allwinner,sun8i-a83t-apb0-gates-clk", + sunxi_simple_gates_init); CLK_OF_DECLARE(sun9i_a80_ahb0, "allwinner,sun9i-a80-ahb0-gates-clk", sunxi_simple_gates_init); CLK_OF_DECLARE(sun9i_a80_ahb1, "allwinner,sun9i-a80-ahb1-gates-clk", -- cgit v1.2.3 From be338e4c589935a95f09022566ec6c511c07bb8c Mon Sep 17 00:00:00 2001 From: Vishnu Patekar Date: Sun, 31 Jan 2016 09:20:55 +0800 Subject: clk: sunxi: add bus gates for A83T A83T has similar bus gates that of H3, including single gating register has different clock parent. As per H3 and A83T datasheet, usbhost is under AHB2. However,below shows allwinner source code assignment: bits: 26 (ehci0), 27 (ehci1), 29 (ohci0) => AHB1 for A83T. bits: 26 (ehci0), 27 (ehci1) => AHB1 for H3 bits 29, 30, 31(ohci0,1,2) => AHB2 for H3. until, this confusion is cleared keep it H3 way. Signed-off-by: Vishnu Patekar Acked-by: Rob Herring Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/clock/sunxi.txt | 1 + drivers/clk/sunxi/clk-sun8i-bus-gates.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index 7f19ef55d61f..c09f59b1747c 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -58,6 +58,7 @@ Required properties: "allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80 "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 "allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23 + "allwinner,sun8i-a83t-bus-gates-clk" - for the bus gates on A83T "allwinner,sun8i-h3-bus-gates-clk" - for the bus gates on H3 "allwinner,sun9i-a80-apbs-gates-clk" - for the APBS gates on A80 "allwinner,sun4i-a10-dram-gates-clk" - for the DRAM gates on A10 diff --git a/drivers/clk/sunxi/clk-sun8i-bus-gates.c b/drivers/clk/sunxi/clk-sun8i-bus-gates.c index 1113eb98c9b4..63fdb790df29 100644 --- a/drivers/clk/sunxi/clk-sun8i-bus-gates.c +++ b/drivers/clk/sunxi/clk-sun8i-bus-gates.c @@ -109,3 +109,5 @@ err_unmap: CLK_OF_DECLARE(sun8i_h3_bus_gates, "allwinner,sun8i-h3-bus-gates-clk", sun8i_h3_bus_gates_init); +CLK_OF_DECLARE(sun8i_a83t_bus_gates, "allwinner,sun8i-a83t-bus-gates-clk", + sun8i_h3_bus_gates_init); -- cgit v1.2.3 From d0be8584b01160eb6f49e77f8e9c1da286bb4ffb Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 4 Jan 2016 03:33:45 +0100 Subject: drm: adv7511: really enable interrupts for EDID detection The interrupts for EDID_READY or DDC_ERROR were never enabled in this driver, so reading EDID always timed out when chip was powered down and interrupts were used. Fix this and also remove clearing the interrupt flags, they are cleared in POWER_DOWN mode anyhow (unlike the interrupt enable flags) according to docs and my tests. Signed-off-by: Wolfram Sang Tested-by: Archit Taneja --- drivers/gpu/drm/i2c/adv7511.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c index 533d1e3d4a99..db7435a4517f 100644 --- a/drivers/gpu/drm/i2c/adv7511.c +++ b/drivers/gpu/drm/i2c/adv7511.c @@ -362,12 +362,19 @@ static void adv7511_power_on(struct adv7511 *adv7511) { adv7511->current_edid_segment = -1; - regmap_write(adv7511->regmap, ADV7511_REG_INT(0), - ADV7511_INT0_EDID_READY); - regmap_write(adv7511->regmap, ADV7511_REG_INT(1), - ADV7511_INT1_DDC_ERROR); regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, ADV7511_POWER_POWER_DOWN, 0); + if (adv7511->i2c_main->irq) { + /* + * Documentation says the INT_ENABLE registers are reset in + * POWER_DOWN mode. My 7511w preserved the bits, however. + * Still, let's be safe and stick to the documentation. + */ + regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0), + ADV7511_INT0_EDID_READY); + regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1), + ADV7511_INT1_DDC_ERROR); + } /* * Per spec it is allowed to pulse the HDP signal to indicate that the @@ -567,12 +574,14 @@ static int adv7511_get_modes(struct drm_encoder *encoder, /* Reading the EDID only works if the device is powered */ if (!adv7511->powered) { - regmap_write(adv7511->regmap, ADV7511_REG_INT(0), - ADV7511_INT0_EDID_READY); - regmap_write(adv7511->regmap, ADV7511_REG_INT(1), - ADV7511_INT1_DDC_ERROR); regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, ADV7511_POWER_POWER_DOWN, 0); + if (adv7511->i2c_main->irq) { + regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0), + ADV7511_INT0_EDID_READY); + regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1), + ADV7511_INT1_DDC_ERROR); + } adv7511->current_edid_segment = -1; } -- cgit v1.2.3 From cd38a33750ace4300ef91b9ad668baf07c3bfd2b Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 4 Jan 2016 03:33:46 +0100 Subject: drm: adv7511: mark ADV7511_REG_EDID_READ_CTRL volatile This register includes a counter which is decremented by the chip on I2C failures. Also, it is reset when powering down. Signed-off-by: Wolfram Sang Reviewed-by: Laurent Pinchart Tested-by: Archit Taneja --- drivers/gpu/drm/i2c/adv7511.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c index db7435a4517f..e1756a452d69 100644 --- a/drivers/gpu/drm/i2c/adv7511.c +++ b/drivers/gpu/drm/i2c/adv7511.c @@ -136,6 +136,7 @@ static bool adv7511_register_volatile(struct device *dev, unsigned int reg) case ADV7511_REG_BKSV(3): case ADV7511_REG_BKSV(4): case ADV7511_REG_DDC_STATUS: + case ADV7511_REG_EDID_READ_CTRL: case ADV7511_REG_BSTATUS(0): case ADV7511_REG_BSTATUS(1): case ADV7511_REG_CHIP_ID_HIGH: -- cgit v1.2.3 From 29ce4ed441d04a8931150f291c0f7d961690ab81 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 4 Jan 2016 03:33:47 +0100 Subject: drm: adv7511: it's HPD, not HDP Fix this typo, consequently used over both files :) Signed-off-by: Wolfram Sang Acked-by: Lars-Peter Clausen Reviewed-by: Laurent Pinchart Tested-by: Archit Taneja --- drivers/gpu/drm/i2c/adv7511.c | 22 +++++++++++----------- drivers/gpu/drm/i2c/adv7511.h | 12 ++++++------ 2 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c index e1756a452d69..a02112ba1c3d 100644 --- a/drivers/gpu/drm/i2c/adv7511.c +++ b/drivers/gpu/drm/i2c/adv7511.c @@ -378,16 +378,16 @@ static void adv7511_power_on(struct adv7511 *adv7511) } /* - * Per spec it is allowed to pulse the HDP signal to indicate that the + * Per spec it is allowed to pulse the HPD signal to indicate that the * EDID information has changed. Some monitors do this when they wakeup - * from standby or are enabled. When the HDP goes low the adv7511 is + * from standby or are enabled. When the HPD goes low the adv7511 is * reset and the outputs are disabled which might cause the monitor to - * go to standby again. To avoid this we ignore the HDP pin for the + * go to standby again. To avoid this we ignore the HPD pin for the * first few seconds after enabling the output. */ regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2, - ADV7511_REG_POWER2_HDP_SRC_MASK, - ADV7511_REG_POWER2_HDP_SRC_NONE); + ADV7511_REG_POWER2_HPD_SRC_MASK, + ADV7511_REG_POWER2_HPD_SRC_NONE); /* * Most of the registers are reset during power down or when HPD is low. @@ -421,9 +421,9 @@ static bool adv7511_hpd(struct adv7511 *adv7511) if (ret < 0) return false; - if (irq0 & ADV7511_INT0_HDP) { + if (irq0 & ADV7511_INT0_HPD) { regmap_write(adv7511->regmap, ADV7511_REG_INT(0), - ADV7511_INT0_HDP); + ADV7511_INT0_HPD); return true; } @@ -446,7 +446,7 @@ static int adv7511_irq_process(struct adv7511 *adv7511) regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0); regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1); - if (irq0 & ADV7511_INT0_HDP && adv7511->encoder) + if (irq0 & ADV7511_INT0_HPD && adv7511->encoder) drm_helper_hpd_irq_event(adv7511->encoder->dev); if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) { @@ -648,10 +648,10 @@ adv7511_encoder_detect(struct drm_encoder *encoder, if (adv7511->status == connector_status_connected) status = connector_status_disconnected; } else { - /* Renable HDP sensing */ + /* Renable HPD sensing */ regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2, - ADV7511_REG_POWER2_HDP_SRC_MASK, - ADV7511_REG_POWER2_HDP_SRC_BOTH); + ADV7511_REG_POWER2_HPD_SRC_MASK, + ADV7511_REG_POWER2_HPD_SRC_BOTH); } adv7511->status = status; diff --git a/drivers/gpu/drm/i2c/adv7511.h b/drivers/gpu/drm/i2c/adv7511.h index 6599ed538426..38515b30cedf 100644 --- a/drivers/gpu/drm/i2c/adv7511.h +++ b/drivers/gpu/drm/i2c/adv7511.h @@ -90,7 +90,7 @@ #define ADV7511_CSC_ENABLE BIT(7) #define ADV7511_CSC_UPDATE_MODE BIT(5) -#define ADV7511_INT0_HDP BIT(7) +#define ADV7511_INT0_HPD BIT(7) #define ADV7511_INT0_VSYNC BIT(5) #define ADV7511_INT0_AUDIO_FIFO_FULL BIT(4) #define ADV7511_INT0_EDID_READY BIT(2) @@ -157,11 +157,11 @@ #define ADV7511_PACKET_ENABLE_SPARE2 BIT(1) #define ADV7511_PACKET_ENABLE_SPARE1 BIT(0) -#define ADV7511_REG_POWER2_HDP_SRC_MASK 0xc0 -#define ADV7511_REG_POWER2_HDP_SRC_BOTH 0x00 -#define ADV7511_REG_POWER2_HDP_SRC_HDP 0x40 -#define ADV7511_REG_POWER2_HDP_SRC_CEC 0x80 -#define ADV7511_REG_POWER2_HDP_SRC_NONE 0xc0 +#define ADV7511_REG_POWER2_HPD_SRC_MASK 0xc0 +#define ADV7511_REG_POWER2_HPD_SRC_BOTH 0x00 +#define ADV7511_REG_POWER2_HPD_SRC_HPD 0x40 +#define ADV7511_REG_POWER2_HPD_SRC_CEC 0x80 +#define ADV7511_REG_POWER2_HPD_SRC_NONE 0xc0 #define ADV7511_REG_POWER2_TDMS_ENABLE BIT(4) #define ADV7511_REG_POWER2_GATE_INPUT_CLK BIT(0) -- cgit v1.2.3 From 6235f0ecc4ed799169b80f7317c7f974f7415320 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 1 Feb 2016 17:39:20 +0000 Subject: irqchip/sun4i: Fix compilation outside of arch/arm The Allwinner sunxi specific interrupt controller cannot be compiled for any architecture except arm: drivers/irqchip/irq-sun4i.c:25:26: fatal error: asm/mach/irq.h: No such file or directory compilation terminated. It turns out that this header is actually not needed for the driver, so remove it and allow compilation for other architectures like arm64. Signed-off-by: Andre Przywara Acked-by: Arnd Bergmann Cc: linux-arm-kernel@lists.infradead.org Cc: Jason Cooper Cc: Marc Zyngier Cc: Maxime Ripard Cc: Chen-Yu Tsai Cc: linux-sunxi@googlegroups.com Link: http://lkml.kernel.org/r/1454348370-3816-2-git-send-email-andre.przywara@arm.com Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-sun4i.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c index 0704362f4c82..376b28074e0d 100644 --- a/drivers/irqchip/irq-sun4i.c +++ b/drivers/irqchip/irq-sun4i.c @@ -22,7 +22,6 @@ #include #include -#include #define SUN4I_IRQ_VECTOR_REG 0x00 #define SUN4I_IRQ_PROTECTION_REG 0x08 -- cgit v1.2.3 From 474f2ba268f220e75ed7b9bfa7b977ade740d30c Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Thu, 14 Jan 2016 14:24:32 -0500 Subject: clk: tegra: Fix naming of MISC registers Some register for PLLM and PLLMB were named MISC0 but according to the TRM, they have different names. Sync up the names to make it easier to understand which register they are really referring to. Signed-off-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra210.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index f45c9adf7fb2..caae0dcc9cb5 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -59,8 +59,8 @@ #define PLLC3_MISC3 0x50c #define PLLM_BASE 0x90 -#define PLLM_MISC0 0x9c #define PLLM_MISC1 0x98 +#define PLLM_MISC2 0x9c #define PLLP_BASE 0xa0 #define PLLP_MISC0 0xac #define PLLP_MISC1 0x680 @@ -99,7 +99,7 @@ #define PLLC4_MISC0 0x5a8 #define PLLC4_OUT 0x5e4 #define PLLMB_BASE 0x5e8 -#define PLLMB_MISC0 0x5ec +#define PLLMB_MISC1 0x5ec #define PLLA1_BASE 0x6a4 #define PLLA1_MISC0 0x6a8 #define PLLA1_MISC1 0x6ac @@ -367,12 +367,12 @@ static const char *mux_pllmcp_clkm[] = { /* PLLMB */ #define PLLMB_BASE_LOCK (1 << 27) -#define PLLMB_MISC0_LOCK_OVERRIDE (1 << 18) -#define PLLMB_MISC0_IDDQ (1 << 17) -#define PLLMB_MISC0_LOCK_ENABLE (1 << 16) +#define PLLMB_MISC1_LOCK_OVERRIDE (1 << 18) +#define PLLMB_MISC1_IDDQ (1 << 17) +#define PLLMB_MISC1_LOCK_ENABLE (1 << 16) -#define PLLMB_MISC0_DEFAULT_VALUE 0x00030000 -#define PLLMB_MISC0_WRITE_MASK 0x0007ffff +#define PLLMB_MISC1_DEFAULT_VALUE 0x00030000 +#define PLLMB_MISC1_WRITE_MASK 0x0007ffff /* PLLP */ #define PLLP_BASE_OVERRIDE (1 << 28) @@ -914,15 +914,15 @@ void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb) * PLL is ON: check if defaults already set, then set those * that can be updated in flight. */ - val = PLLMB_MISC0_DEFAULT_VALUE & (~PLLMB_MISC0_IDDQ); - mask = PLLMB_MISC0_LOCK_ENABLE | PLLMB_MISC0_LOCK_OVERRIDE; + val = PLLMB_MISC1_DEFAULT_VALUE & (~PLLMB_MISC1_IDDQ); + mask = PLLMB_MISC1_LOCK_ENABLE | PLLMB_MISC1_LOCK_OVERRIDE; _pll_misc_chk_default(clk_base, pllmb->params, 0, val, - ~mask & PLLMB_MISC0_WRITE_MASK); + ~mask & PLLMB_MISC1_WRITE_MASK); /* Enable lock detect */ val = readl_relaxed(clk_base + pllmb->params->ext_misc_reg[0]); val &= ~mask; - val |= PLLMB_MISC0_DEFAULT_VALUE & mask; + val |= PLLMB_MISC1_DEFAULT_VALUE & mask; writel_relaxed(val, clk_base + pllmb->params->ext_misc_reg[0]); udelay(1); @@ -930,7 +930,7 @@ void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb) } /* set IDDQ, enable lock detect */ - writel_relaxed(PLLMB_MISC0_DEFAULT_VALUE, + writel_relaxed(PLLMB_MISC1_DEFAULT_VALUE, clk_base + pllmb->params->ext_misc_reg[0]); udelay(1); } @@ -1557,14 +1557,14 @@ static struct tegra_clk_pll_params pll_m_params = { .vco_min = 800000000, .vco_max = 1866000000, .base_reg = PLLM_BASE, - .misc_reg = PLLM_MISC0, + .misc_reg = PLLM_MISC2, .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLLM_MISC_LOCK_ENABLE, .lock_delay = 300, - .iddq_reg = PLLM_MISC0, + .iddq_reg = PLLM_MISC2, .iddq_bit_idx = PLLM_IDDQ_BIT, .max_p = PLL_QLIN_PDIV_MAX, - .ext_misc_reg[0] = PLLM_MISC0, + .ext_misc_reg[0] = PLLM_MISC2, .ext_misc_reg[0] = PLLM_MISC1, .round_p_to_pdiv = pll_qlin_p_to_pdiv, .pdiv_tohw = pll_qlin_pdiv_to_hw, @@ -1584,13 +1584,13 @@ static struct tegra_clk_pll_params pll_mb_params = { .vco_min = 800000000, .vco_max = 1866000000, .base_reg = PLLMB_BASE, - .misc_reg = PLLMB_MISC0, + .misc_reg = PLLMB_MISC1, .lock_mask = PLL_BASE_LOCK, .lock_delay = 300, - .iddq_reg = PLLMB_MISC0, + .iddq_reg = PLLMB_MISC1, .iddq_bit_idx = PLLMB_IDDQ_BIT, .max_p = PLL_QLIN_PDIV_MAX, - .ext_misc_reg[0] = PLLMB_MISC0, + .ext_misc_reg[0] = PLLMB_MISC1, .round_p_to_pdiv = pll_qlin_p_to_pdiv, .pdiv_tohw = pll_qlin_pdiv_to_hw, .div_nmp = &pllm_nmp, -- cgit v1.2.3 From 736971bed20de137db9b418cc641c7d11336fffb Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Thu, 14 Jan 2016 14:24:33 -0500 Subject: clk: tegra: Fix the misnaming of nvenc from msenc When adding the nvenc clock, it was partially named msenc in the code. Since the msenc clock isn't present in Tegra210 and has been replaced by the nvenc clock, its misleading to see it present. Therefore, properly rename it. Signed-off-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra-periph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 105405ca85ab..1860df1862dd 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -773,7 +773,7 @@ static struct tegra_periph_init_data periph_clks[] = { XUSB("xusb_dev_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src), XUSB("xusb_dev_src", mux_clkm_pllp_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src_8), MUX8("dbgapb", mux_pllp_clkm_2, CLK_SOURCE_DBGAPB, 185, TEGRA_PERIPH_NO_RESET, tegra_clk_dbgapb), - MUX8("msenc", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVENC, 219, 0, tegra_clk_nvenc), + MUX8("nvenc", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVENC, 219, 0, tegra_clk_nvenc), MUX8("nvdec", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVDEC, 194, 0, tegra_clk_nvdec), MUX8("nvjpg", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVJPG, 195, 0, tegra_clk_nvjpg), MUX8("ape", mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm, CLK_SOURCE_APE, 198, TEGRA_PERIPH_ON_APB, tegra_clk_ape), -- cgit v1.2.3 From 3eb61566a6efc5a56ebe1e6b86519bc5e0b39003 Mon Sep 17 00:00:00 2001 From: Andrew Bresticker Date: Thu, 14 Jan 2016 14:24:34 -0500 Subject: clk: tegra: pll: Fix potential sleeping-while-atomic Since the ->enable() callback is called with a spinlock held, we cannot call potentially blocking functions such as clk_get_rate() or clk_get_parent(), so use the unlocked versions instead. Signed-off-by: Andrew Bresticker [rklein: Adapted from ChromeOS patch, removing pllu_enable cleanup as it isn't present upstream] Signed-off-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-pll.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index a534bfab30b3..65156486889a 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -880,7 +880,7 @@ static int clk_plle_training(struct tegra_clk_pll *pll) static int clk_plle_enable(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); - unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk)); + unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); struct tegra_clk_pll_freq_table sel; u32 val; int err; @@ -1378,7 +1378,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw) u32 val; int ret; unsigned long flags = 0; - unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk)); + unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate)) return -EINVAL; @@ -2014,7 +2014,7 @@ static int clk_plle_tegra210_enable(struct clk_hw *hw) u32 val; int ret; unsigned long flags = 0; - unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk)); + unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate)) return -EINVAL; -- cgit v1.2.3 From 3dad5c5fa1d24c3bbb3e9e8ac0c52f35e045b807 Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Thu, 14 Jan 2016 14:24:35 -0500 Subject: clk: tegra: Fix pllx dyn step calculation The logic for calculating the input rate used when figuring out the proper dynamic steps for pllx was incorrect. It is supposed to be calculated using parent_rate / m but it was just using the parent rate directly, therefore using the wrong step values. Signed-off-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra210.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index caae0dcc9cb5..ffcb86a667d9 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -780,13 +780,13 @@ static void pllx_get_dyn_steps(struct clk_hw *hw, u32 *step_a, u32 *step_b) { unsigned long input_rate; - if (!IS_ERR_OR_NULL(hw->clk)) { + /* cf rate */ + if (!IS_ERR_OR_NULL(hw->clk)) input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); - /* cf rate */ - input_rate /= tegra_pll_get_fixed_mdiv(hw, input_rate); - } else { + else input_rate = 38400000; - } + + input_rate /= tegra_pll_get_fixed_mdiv(hw, input_rate); switch (input_rate) { case 12000000: -- cgit v1.2.3 From f59b0168d3f3257f9bf0734563290acc3c9d972b Mon Sep 17 00:00:00 2001 From: Mark Kuo Date: Thu, 14 Jan 2016 14:24:36 -0500 Subject: clk: tegra: Do not disable PLLE when under hardware control Software should not disable PLLE if PLLE is already put under hardware control. Signed-off-by: Mark Kuo Signed-off-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-pll.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 65156486889a..d9c3109b75bd 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -2012,7 +2012,7 @@ static int clk_plle_tegra210_enable(struct clk_hw *hw) struct tegra_clk_pll *pll = to_clk_pll(hw); struct tegra_clk_pll_freq_table sel; u32 val; - int ret; + int ret = 0; unsigned long flags = 0; unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); @@ -2022,16 +2022,14 @@ static int clk_plle_tegra210_enable(struct clk_hw *hw) if (pll->lock) spin_lock_irqsave(pll->lock, flags); + val = pll_readl(pll->params->aux_reg, pll); + if (val & PLLE_AUX_SEQ_ENABLE) + goto out; + val = pll_readl_base(pll); val &= ~BIT(30); /* Disable lock override */ pll_writel_base(val, pll); - val = pll_readl(pll->params->aux_reg, pll); - val |= PLLE_AUX_ENABLE_SWCTL; - val &= ~PLLE_AUX_SEQ_ENABLE; - pll_writel(val, pll->params->aux_reg, pll); - udelay(1); - val = pll_readl_misc(pll); val |= PLLE_MISC_LOCK_ENABLE; val |= PLLE_MISC_IDDQ_SW_CTRL; @@ -2104,15 +2102,25 @@ static void clk_plle_tegra210_disable(struct clk_hw *hw) if (pll->lock) spin_lock_irqsave(pll->lock, flags); + /* If PLLE HW sequencer is enabled, SW should not disable PLLE */ + val = pll_readl(pll->params->aux_reg, pll); + if (val & PLLE_AUX_SEQ_ENABLE) + goto out; + val = pll_readl_base(pll); val &= ~PLLE_BASE_ENABLE; pll_writel_base(val, pll); + val = pll_readl(pll->params->aux_reg, pll); + val |= PLLE_AUX_ENABLE_SWCTL | PLLE_AUX_SS_SWCTL; + pll_writel(val, pll->params->aux_reg, pll); + val = pll_readl_misc(pll); val |= PLLE_MISC_IDDQ_SW_CTRL | PLLE_MISC_IDDQ_SW_VALUE; pll_writel_misc(val, pll); udelay(1); +out: if (pll->lock) spin_unlock_irqrestore(pll->lock, flags); } -- cgit v1.2.3 From fd2963b071c1346572285a274a6ae8f26a970c4d Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Thu, 14 Jan 2016 14:24:37 -0500 Subject: clk: tegra: Fix typos around clearing PLLE bits during enable While enabling PLLE on both Tegra114 and Tegra210, we should be clearing PLLE_MISC_VREG_BG_CTRL_MASK and PLLE_MISC_VREG_CTRL_MASK not setting them. This patch fixes both places where we incorrectly set instead of cleared those bits. Signed-off-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-pll.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index d9c3109b75bd..cb28130e6c0a 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -1401,7 +1401,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw) val |= PLLE_MISC_IDDQ_SW_CTRL; val &= ~PLLE_MISC_IDDQ_SW_VALUE; val |= PLLE_MISC_PLLE_PTS; - val |= PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK; + val &= ~(PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK); pll_writel_misc(val, pll); udelay(5); @@ -2035,7 +2035,7 @@ static int clk_plle_tegra210_enable(struct clk_hw *hw) val |= PLLE_MISC_IDDQ_SW_CTRL; val &= ~PLLE_MISC_IDDQ_SW_VALUE; val |= PLLE_MISC_PLLE_PTS; - val |= PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK; + val &= ~(PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK); pll_writel_misc(val, pll); udelay(5); -- cgit v1.2.3 From 442f53fb1be44c00263ebb8e7c2eff19dd019037 Mon Sep 17 00:00:00 2001 From: Mark Kuo Date: Thu, 14 Jan 2016 14:26:42 -0500 Subject: clk: tegra: Fix PLLE SS coefficients The PLLE SS coefficients are different between Tegra210 and Tegra114. Add SoC generation specific versions for Tegra114 and Tegra210 and use them in their respective ->enable() callbacks. Signed-off-by: Mark Kuo Signed-off-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-pll.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index cb28130e6c0a..6ac3f843e7ca 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -86,15 +86,21 @@ #define PLLE_SS_DISABLE (PLLE_SS_CNTL_BYPASS_SS | PLLE_SS_CNTL_INTERP_RESET |\ PLLE_SS_CNTL_SSC_BYP) #define PLLE_SS_MAX_MASK 0x1ff -#define PLLE_SS_MAX_VAL 0x25 +#define PLLE_SS_MAX_VAL_TEGRA114 0x25 +#define PLLE_SS_MAX_VAL_TEGRA210 0x21 #define PLLE_SS_INC_MASK (0xff << 16) #define PLLE_SS_INC_VAL (0x1 << 16) #define PLLE_SS_INCINTRV_MASK (0x3f << 24) -#define PLLE_SS_INCINTRV_VAL (0x20 << 24) +#define PLLE_SS_INCINTRV_VAL_TEGRA114 (0x20 << 24) +#define PLLE_SS_INCINTRV_VAL_TEGRA210 (0x23 << 24) #define PLLE_SS_COEFFICIENTS_MASK \ (PLLE_SS_MAX_MASK | PLLE_SS_INC_MASK | PLLE_SS_INCINTRV_MASK) -#define PLLE_SS_COEFFICIENTS_VAL \ - (PLLE_SS_MAX_VAL | PLLE_SS_INC_VAL | PLLE_SS_INCINTRV_VAL) +#define PLLE_SS_COEFFICIENTS_VAL_TEGRA114 \ + (PLLE_SS_MAX_VAL_TEGRA114 | PLLE_SS_INC_VAL |\ + PLLE_SS_INCINTRV_VAL_TEGRA114) +#define PLLE_SS_COEFFICIENTS_VAL_TEGRA210 \ + (PLLE_SS_MAX_VAL_TEGRA210 | PLLE_SS_INC_VAL |\ + PLLE_SS_INCINTRV_VAL_TEGRA210) #define PLLE_AUX_PLLP_SEL BIT(2) #define PLLE_AUX_USE_LOCKDET BIT(3) @@ -1428,7 +1434,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw) val = pll_readl(PLLE_SS_CTRL, pll); val &= ~(PLLE_SS_CNTL_CENTER | PLLE_SS_CNTL_INVERT); val &= ~PLLE_SS_COEFFICIENTS_MASK; - val |= PLLE_SS_COEFFICIENTS_VAL; + val |= PLLE_SS_COEFFICIENTS_VAL_TEGRA114; pll_writel(val, PLLE_SS_CTRL, pll); val &= ~(PLLE_SS_CNTL_SSC_BYP | PLLE_SS_CNTL_BYPASS_SS); pll_writel(val, PLLE_SS_CTRL, pll); @@ -2065,7 +2071,7 @@ static int clk_plle_tegra210_enable(struct clk_hw *hw) val = pll_readl(PLLE_SS_CTRL, pll); val &= ~(PLLE_SS_CNTL_CENTER | PLLE_SS_CNTL_INVERT); val &= ~PLLE_SS_COEFFICIENTS_MASK; - val |= PLLE_SS_COEFFICIENTS_VAL; + val |= PLLE_SS_COEFFICIENTS_VAL_TEGRA210; pll_writel(val, PLLE_SS_CTRL, pll); val &= ~(PLLE_SS_CNTL_SSC_BYP | PLLE_SS_CNTL_BYPASS_SS); pll_writel(val, PLLE_SS_CTRL, pll); -- cgit v1.2.3 From 047d6d8401c2d8f59ae5f478486096c13147ddf7 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Sun, 24 Jan 2016 20:45:20 +0530 Subject: clk: tegra: Add missing of_node_put() for_each_child_of_node() performs an of_node_get() on each iteration, so before breaking out of the loop an of_node_put() is required. Found using Coccinelle. The semantic patch used for this is as follows: // @@ expression e; local idexpression child; @@ for_each_child_of_node(root, child) { ... when != of_node_put(child) when != e = child ( return child; | + of_node_put(child); ? return ...; ) ... } // Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-emc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-emc.c b/drivers/clk/tegra/clk-emc.c index e1fe8f35d45c..74e7544f861b 100644 --- a/drivers/clk/tegra/clk-emc.c +++ b/drivers/clk/tegra/clk-emc.c @@ -450,8 +450,10 @@ static int load_timings_from_dt(struct tegra_clk_emc *tegra, struct emc_timing *timing = tegra->timings + (i++); err = load_one_timing_from_dt(tegra, timing, child); - if (err) + if (err) { + of_node_put(child); return err; + } timing->ram_code = ram_code; } @@ -499,9 +501,9 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np, * fuses until the apbmisc driver is loaded. */ err = load_timings_from_dt(tegra, node, node_ram_code); + of_node_put(node); if (err) return ERR_PTR(err); - of_node_put(node); break; } -- cgit v1.2.3 From 29569941688cdf647f953b2eb073aa6ec9dd3fc1 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 28 Jan 2016 16:33:50 +0000 Subject: clk: tegra: Add the APB2APE audio clock on Tegra210 The APB2APE clock for the audio subsystem is required for powering up the audio power domain and accessing the various modules in this subsystem on Tegra210 devices. Add this clock for Tegra210. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-id.h | 1 + drivers/clk/tegra/clk-tegra-periph.c | 1 + drivers/clk/tegra/clk-tegra210.c | 1 + include/dt-bindings/clock/tegra210-car.h | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h index 19ce0738ee76..62ea38187b71 100644 --- a/drivers/clk/tegra/clk-id.h +++ b/drivers/clk/tegra/clk-id.h @@ -11,6 +11,7 @@ enum clk_id { tegra_clk_afi, tegra_clk_amx, tegra_clk_amx1, + tegra_clk_apb2ape, tegra_clk_apbdma, tegra_clk_apbif, tegra_clk_ape, diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 1860df1862dd..ea2b9cbf9e70 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -829,6 +829,7 @@ static struct tegra_periph_init_data gate_clks[] = { GATE("xusb_gate", "osc", 143, 0, tegra_clk_xusb_gate, 0), GATE("pll_p_out_cpu", "pll_p", 223, 0, tegra_clk_pll_p_out_cpu, 0), GATE("pll_p_out_adsp", "pll_p", 187, 0, tegra_clk_pll_p_out_adsp, 0), + GATE("apb2ape", "clk_m", 107, 0, tegra_clk_apb2ape, 0), }; static struct tegra_periph_init_data div_clks[] = { diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index ffcb86a667d9..14c1841eb29b 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -2204,6 +2204,7 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = { [tegra_clk_pll_c4_out1] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT1, .present = true }, [tegra_clk_pll_c4_out2] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT2, .present = true }, [tegra_clk_pll_c4_out3] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT3, .present = true }, + [tegra_clk_apb2ape] = { .dt_id = TEGRA210_CLK_APB2APE, .present = true }, }; static struct tegra_devclk devclks[] __initdata = { diff --git a/include/dt-bindings/clock/tegra210-car.h b/include/dt-bindings/clock/tegra210-car.h index 6f45aea49e4f..0a05b0d36ae7 100644 --- a/include/dt-bindings/clock/tegra210-car.h +++ b/include/dt-bindings/clock/tegra210-car.h @@ -126,7 +126,7 @@ /* 104 */ /* 105 */ #define TEGRA210_CLK_D_AUDIO 106 -/* 107 ( affects abp -> ape) */ +#define TEGRA210_CLK_APB2APE 107 /* 108 */ /* 109 */ /* 110 */ -- cgit v1.2.3 From 4f8d44403079991a29e69f6aa25bb718ead418cb Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 18 Dec 2015 13:45:28 +0000 Subject: clk: tegra: Fix clock sources for Tegra210 EMC The EMC clock sources for Tegra210 currently incorrectly include pll_c2 and pll_c3. However, both of these should have been pll_mb as shown in the TRM. If Tegra210 happens to be configured such that the pll_mb is the default clock for the EMC, as configured by the bootloader, then this will cause a system hang on boot. This is because the kernel will disable the pll_mb when disabling unused clock as it appears to be unused when it is not. Also add the additional pll_p clock source for the EMC. Signed-off-by: Jon Hunter Acked-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra210.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 14c1841eb29b..429eec96696e 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -243,7 +243,8 @@ static unsigned long tegra210_input_freq[] = { }; static const char *mux_pllmcp_clkm[] = { - "pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_c2", "pll_c3", + "pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_mb", "pll_mb", + "pll_p", }; #define mux_pllmcp_clkm_idx NULL -- cgit v1.2.3 From 0649c3232be5b647dba50e2f6d31fe1306913ab2 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Mon, 21 Dec 2015 12:56:31 +0000 Subject: clk: tegra: Fix warning caused by pll_u failing to lock If the pll_u is not configured by the bootloader, then on kernel boot the following warning is seen: clk_pll_wait_for_lock: Timed out waiting for pll pll_u_vco lock tegra_init_from_table: Failed to enable pll_u_out1 ------------[ cut here ]------------ WARNING: at drivers/clk/tegra/clk.c:269 Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.4.0-rc4-next-20151214+ #1 Hardware name: NVIDIA Tegra210 P2371 reference board (E.1) (DT) task: ffffffc0bc0a0000 ti: ffffffc0bc0a8000 task.ti: ffffffc0bc0a8000 PC is at tegra_init_from_table+0x140/0x164 LR is at tegra_init_from_table+0x140/0x164 pc : [] lr : [] pstate: 80000045 sp : ffffffc0bc0abd50 x29: ffffffc0bc0abd50 x28: ffffffc00090b8a8 x27: ffffffc000a06000 x26: ffffffc0bc019780 x25: ffffffc00086a708 x24: ffffffc00086a790 x23: ffffffc0006d7188 x22: ffffffc0bc010000 x21: 000000000000016e x20: ffffffc0bc00d100 x19: ffffffc000944178 x18: 0000000000000007 x17: 000000000000000e x16: 0000000000000001 x15: 0000000000000007 x14: 000000000000000e x13: 0000000000000013 x12: 000000000000001a x11: 000000000000004d x10: 0000000000000750 x9 : ffffffc0bc0a8000 x8 : ffffffc0bc0a07b0 x7 : 0000000000000001 x6 : 0000000002d5f0f8 x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000002 x2 : ffffffc000996724 x1 : 0000000000000000 x0 : 0000000000000032 ---[ end trace cbd20ae519e92ced ]--- Call trace: [] tegra_init_from_table+0x140/0x164 [] tegra210_clock_apply_init_table+0x20/0x28 [] tegra_clocks_apply_init_table+0x18/0x24 [] do_one_initcall+0x90/0x194 [] kernel_init_freeable+0x148/0x1e8 [] kernel_init+0x10/0xdc [] ret_from_fork+0x10/0x40 clk_pll_wait_for_lock: Timed out waiting for pll pll_u_vco lock tegra_init_from_table: Failed to enable pll_u_out2 ------------[ cut here ]------------ pll_u can be either controlled by software or hardware and this is selected via the OVERRIDE bit in the pll_u base register. In the function tegra210_pll_init(), the OVERRIDE bit for pll_u is cleared, which selects hardware control of the pll. However, at the same time the pll_u clocks are populated in the init_table for tegra210 and so software will try to configure the pll_u if it is not already configured and hence, the above warning is seen when the pll fails to lock. Remove the pll_u clocks from the init_table so that software does not try to configure this pll on boot. Signed-off-by: Jon Hunter Acked-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra210.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 429eec96696e..1948ea4f77ff 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -2726,8 +2726,6 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA210_CLK_DFLL_REF, TEGRA210_CLK_PLL_P, 51000000, 1 }, { TEGRA210_CLK_SBC4, TEGRA210_CLK_PLL_P, 12000000, 1 }, { TEGRA210_CLK_PLL_RE_VCO, TEGRA210_CLK_CLK_MAX, 672000000, 1 }, - { TEGRA210_CLK_PLL_U_OUT1, TEGRA210_CLK_CLK_MAX, 48000000, 1 }, - { TEGRA210_CLK_PLL_U_OUT2, TEGRA210_CLK_CLK_MAX, 60000000, 1 }, { TEGRA210_CLK_XUSB_GATE, TEGRA210_CLK_CLK_MAX, 0, 1 }, { TEGRA210_CLK_XUSB_SS_SRC, TEGRA210_CLK_PLL_U_480M, 120000000, 0 }, { TEGRA210_CLK_XUSB_FS_SRC, TEGRA210_CLK_PLL_U_48M, 48000000, 0 }, -- cgit v1.2.3 From 2d5b6cf84a1764aa9837128bc1e6fd53cb0bb9c1 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Mon, 21 Dec 2015 12:56:32 +0000 Subject: clk: tegra: Use definition for pll_u override bit The definition, PLLU_BASE_OVERRIDE, for the pll_u OVERRIDE bit is defined but not used and when the OVERRIDE bit is cleared in tegra210_pll_init() the code directly uses the bit number. Therefore, use the definition, PLLU_BASE_OVERRIDE when clearing the OVERRIDE bit. Signed-off-by: Jon Hunter Acked-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra210.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 1948ea4f77ff..ca04c2d85e2b 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -2507,7 +2507,7 @@ static void __init tegra210_pll_init(void __iomem *clk_base, /* PLLU_VCO */ val = readl(clk_base + pll_u_vco_params.base_reg); - val &= ~BIT(24); /* disable PLLU_OVERRIDE */ + val &= ~PLLU_BASE_OVERRIDE; /* disable PLLU_OVERRIDE */ writel(val, clk_base + pll_u_vco_params.base_reg); clk = tegra_clk_register_pllre("pll_u_vco", "pll_ref", clk_base, pmc, -- cgit v1.2.3 From d9e657919afe0794713b5ffb069f9f66c37bfe17 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 4 Dec 2015 17:04:23 +0000 Subject: clk: tegra: Fix sparse warning for pll_m Sparse generates the following warning for the pll_m params structure: drivers/clk/tegra/clk-tegra210.c:1569:10: warning: Initializer entry defined twice drivers/clk/tegra/clk-tegra210.c:1570:10: also defined here Fix this by correcting the index for the MISC1 register. Fixes: b31eba5ff3f7 ("clk: tegra: Add support for Tegra210 clocks") Signed-off-by: Jon Hunter Acked-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra210.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index ca04c2d85e2b..271ea1580d91 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -1566,7 +1566,7 @@ static struct tegra_clk_pll_params pll_m_params = { .iddq_bit_idx = PLLM_IDDQ_BIT, .max_p = PLL_QLIN_PDIV_MAX, .ext_misc_reg[0] = PLLM_MISC2, - .ext_misc_reg[0] = PLLM_MISC1, + .ext_misc_reg[1] = PLLM_MISC1, .round_p_to_pdiv = pll_qlin_p_to_pdiv, .pdiv_tohw = pll_qlin_pdiv_to_hw, .div_nmp = &pllm_nmp, -- cgit v1.2.3 From fd360e20844aa8d1081eb28c72128abb7a5d3598 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 4 Dec 2015 17:04:24 +0000 Subject: clk: tegra: Fix sparse warnings for functions not declared as static Sparse reports the following warnings for functions in clk-tegra210.c that should be declared as static: drivers/clk/tegra/clk-tegra210.c:460:6: warning: symbol 'tegra210_pllcx_set_defaults' was not declared. Should it be static? drivers/clk/tegra/clk-tegra210.c:485:6: warning: symbol '_pllc_set_defaults' was not declared. Should it be static? drivers/clk/tegra/clk-tegra210.c:490:6: warning: symbol '_pllc2_set_defaults' was not declared. Should it be static? drivers/clk/tegra/clk-tegra210.c:495:6: warning: symbol '_pllc3_set_defaults' was not declared. Should it be static? drivers/clk/tegra/clk-tegra210.c:500:6: warning: symbol '_plla1_set_defaults' was not declared. Should it be static? drivers/clk/tegra/clk-tegra210.c:510:6: warning: symbol 'tegra210_plla_set_defaults' was not declared. Should it be static? drivers/clk/tegra/clk-tegra210.c:562:6: warning: symbol 'tegra210_plld_set_defaults' was not declared. Should it be static? drivers/clk/tegra/clk-tegra210.c:701:6: warning: symbol 'tegra210_plld2_set_defaults' was not declared. Should it be static? drivers/clk/tegra/clk-tegra210.c:709:6: warning: symbol 'tegra210_plldp_set_defaults' was not declared. Should it be static? drivers/clk/tegra/clk-tegra210.c:722:6: warning: symbol 'tegra210_pllc4_set_defaults' was not declared. Should it be static? drivers/clk/tegra/clk-tegra210.c:731:6: warning: symbol 'tegra210_pllre_set_defaults' was not declared. Should it be static? drivers/clk/tegra/clk-tegra210.c:844:6: warning: symbol 'tegra210_pllx_set_defaults' was not declared. Should it be static? drivers/clk/tegra/clk-tegra210.c:904:6: warning: symbol 'tegra210_pllmb_set_defaults' was not declared. Should it be static? drivers/clk/tegra/clk-tegra210.c:963:6: warning: symbol 'tegra210_pllp_set_defaults' was not declared. Should it be static? drivers/clk/tegra/clk-tegra210.c:1025:6: warning: symbol 'tegra210_pllu_set_defaults' was not declared. Should it be static? drivers/clk/tegra/clk-tegra210.c:1215:15: warning: symbol 'tegra210_clk_adjust_vco_min' was not declared. Should it be static? Fix this by declaring the above as static. Signed-off-by: Jon Hunter Acked-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra210.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 271ea1580d91..637041fd53ad 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -458,7 +458,8 @@ static void pllcx_check_defaults(struct tegra_clk_pll_params *params) PLLCX_MISC3_WRITE_MASK); } -void tegra210_pllcx_set_defaults(const char *name, struct tegra_clk_pll *pllcx) +static void tegra210_pllcx_set_defaults(const char *name, + struct tegra_clk_pll *pllcx) { pllcx->params->defaults_set = true; @@ -483,22 +484,22 @@ void tegra210_pllcx_set_defaults(const char *name, struct tegra_clk_pll *pllcx) udelay(1); } -void _pllc_set_defaults(struct tegra_clk_pll *pllcx) +static void _pllc_set_defaults(struct tegra_clk_pll *pllcx) { tegra210_pllcx_set_defaults("PLL_C", pllcx); } -void _pllc2_set_defaults(struct tegra_clk_pll *pllcx) +static void _pllc2_set_defaults(struct tegra_clk_pll *pllcx) { tegra210_pllcx_set_defaults("PLL_C2", pllcx); } -void _pllc3_set_defaults(struct tegra_clk_pll *pllcx) +static void _pllc3_set_defaults(struct tegra_clk_pll *pllcx) { tegra210_pllcx_set_defaults("PLL_C3", pllcx); } -void _plla1_set_defaults(struct tegra_clk_pll *pllcx) +static void _plla1_set_defaults(struct tegra_clk_pll *pllcx) { tegra210_pllcx_set_defaults("PLL_A1", pllcx); } @@ -508,7 +509,7 @@ void _plla1_set_defaults(struct tegra_clk_pll *pllcx) * PLL with dynamic ramp and fractional SDM. Dynamic ramp is not used. * Fractional SDM is allowed to provide exact audio rates. */ -void tegra210_plla_set_defaults(struct tegra_clk_pll *plla) +static void tegra210_plla_set_defaults(struct tegra_clk_pll *plla) { u32 mask; u32 val = readl_relaxed(clk_base + plla->params->base_reg); @@ -560,7 +561,7 @@ void tegra210_plla_set_defaults(struct tegra_clk_pll *plla) * PLLD * PLL with fractional SDM. */ -void tegra210_plld_set_defaults(struct tegra_clk_pll *plld) +static void tegra210_plld_set_defaults(struct tegra_clk_pll *plld) { u32 val; u32 mask = 0xffff; @@ -699,7 +700,7 @@ static void plldss_defaults(const char *pll_name, struct tegra_clk_pll *plldss, udelay(1); } -void tegra210_plld2_set_defaults(struct tegra_clk_pll *plld2) +static void tegra210_plld2_set_defaults(struct tegra_clk_pll *plld2) { plldss_defaults("PLL_D2", plld2, PLLD2_MISC0_DEFAULT_VALUE, PLLD2_MISC1_CFG_DEFAULT_VALUE, @@ -707,7 +708,7 @@ void tegra210_plld2_set_defaults(struct tegra_clk_pll *plld2) PLLD2_MISC3_CTRL2_DEFAULT_VALUE); } -void tegra210_plldp_set_defaults(struct tegra_clk_pll *plldp) +static void tegra210_plldp_set_defaults(struct tegra_clk_pll *plldp) { plldss_defaults("PLL_DP", plldp, PLLDP_MISC0_DEFAULT_VALUE, PLLDP_MISC1_CFG_DEFAULT_VALUE, @@ -720,7 +721,7 @@ void tegra210_plldp_set_defaults(struct tegra_clk_pll *plldp) * Base and misc0 layout is the same as PLLD2/PLLDP, but no SDM/SSC support. * VCO is exposed to the clock tree via fixed 1/3 and 1/5 dividers. */ -void tegra210_pllc4_set_defaults(struct tegra_clk_pll *pllc4) +static void tegra210_pllc4_set_defaults(struct tegra_clk_pll *pllc4) { plldss_defaults("PLL_C4", pllc4, PLLC4_MISC0_DEFAULT_VALUE, 0, 0, 0); } @@ -729,7 +730,7 @@ void tegra210_pllc4_set_defaults(struct tegra_clk_pll *pllc4) * PLLRE * VCO is exposed to the clock tree directly along with post-divider output */ -void tegra210_pllre_set_defaults(struct tegra_clk_pll *pllre) +static void tegra210_pllre_set_defaults(struct tegra_clk_pll *pllre) { u32 mask; u32 val = readl_relaxed(clk_base + pllre->params->base_reg); @@ -842,7 +843,7 @@ static void pllx_check_defaults(struct tegra_clk_pll *pll) PLLX_MISC5_WRITE_MASK); } -void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx) +static void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx) { u32 val; u32 step_a, step_b; @@ -902,7 +903,7 @@ void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx) } /* PLLMB */ -void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb) +static void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb) { u32 mask, val = readl_relaxed(clk_base + pllmb->params->base_reg); @@ -961,7 +962,7 @@ static void pllp_check_defaults(struct tegra_clk_pll *pll, bool enabled) ~mask & PLLP_MISC1_WRITE_MASK); } -void tegra210_pllp_set_defaults(struct tegra_clk_pll *pllp) +static void tegra210_pllp_set_defaults(struct tegra_clk_pll *pllp) { u32 mask; u32 val = readl_relaxed(clk_base + pllp->params->base_reg); @@ -1023,7 +1024,7 @@ static void pllu_check_defaults(struct tegra_clk_pll *pll, bool hw_control) ~mask & PLLU_MISC1_WRITE_MASK); } -void tegra210_pllu_set_defaults(struct tegra_clk_pll *pllu) +static void tegra210_pllu_set_defaults(struct tegra_clk_pll *pllu) { u32 val = readl_relaxed(clk_base + pllu->params->base_reg); @@ -1213,8 +1214,9 @@ static void tegra210_clk_pll_set_gain(struct tegra_clk_pll_freq_table *cfg) cfg->m *= PLL_SDM_COEFF; } -unsigned long tegra210_clk_adjust_vco_min(struct tegra_clk_pll_params *params, - unsigned long parent_rate) +static unsigned long +tegra210_clk_adjust_vco_min(struct tegra_clk_pll_params *params, + unsigned long parent_rate) { unsigned long vco_min = params->vco_min; -- cgit v1.2.3 From 5a1d5eff3ede4de4482015a9999336051054283f Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 4 Dec 2015 17:04:25 +0000 Subject: clk: tegra: super: Fix sparse warnings for functions not declared as static Sparse reports the following warnings for structures and functions that should be declared static: drivers/clk/tegra/clk-tegra-super-gen4.c:70:35: warning: symbol 'tegra_super_gen_info_gen4' was not declared. Should it be static? drivers/clk/tegra/clk-tegra-super-gen4.c:96:35: warning: symbol 'tegra_super_gen_info_gen5' was not declared. Should it be static? drivers/clk/tegra/clk-tegra-super-gen4.c:174:13: warning: symbol 'tegra_super_clk_init' was not declared. Should it be static? Fix this by making the above static. Signed-off-by: Jon Hunter Acked-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra-super-gen4.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c b/drivers/clk/tegra/clk-tegra-super-gen4.c index 4559a20e3af6..474de0f0c26d 100644 --- a/drivers/clk/tegra/clk-tegra-super-gen4.c +++ b/drivers/clk/tegra/clk-tegra-super-gen4.c @@ -67,7 +67,7 @@ static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", "pll_p", "pll_p_out4", "unused", "unused", "pll_x", "pll_x_out0" }; -const struct tegra_super_gen_info tegra_super_gen_info_gen4 = { +static const struct tegra_super_gen_info tegra_super_gen_info_gen4 = { .gen = gen4, .sclk_parents = sclk_parents, .cclk_g_parents = cclk_g_parents, @@ -93,7 +93,7 @@ static const char *cclk_lp_parents_gen5[] = { "clk_m", "unused", "clk_32k", "unu "unused", "unused", "unused", "unused", "dfllCPU_out" }; -const struct tegra_super_gen_info tegra_super_gen_info_gen5 = { +static const struct tegra_super_gen_info tegra_super_gen_info_gen5 = { .gen = gen5, .sclk_parents = sclk_parents_gen5, .cclk_g_parents = cclk_g_parents_gen5, @@ -171,7 +171,7 @@ static void __init tegra_sclk_init(void __iomem *clk_base, *dt_clk = clk; } -void __init tegra_super_clk_init(void __iomem *clk_base, +static void __init tegra_super_clk_init(void __iomem *clk_base, void __iomem *pmc_base, struct tegra_clk *tegra_clks, struct tegra_clk_pll_params *params, -- cgit v1.2.3 From bf4f2fb05f89ac50de024b1a5dd0cd0db4a8f845 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Wed, 20 Jan 2016 15:31:20 +0100 Subject: drm/i915/skl/kbl: Add support for pipe fusing On SKL and KBL we can have pipe A/B/C disabled by fuse settings. The pipes must be fused in descending order (e.g. C, B+C, A+B+C). We simply decrease info->num_pipes if we find a valid fused out config. v2: Don't store the pipe disabled mask in device info (Damien) v3: Don't check FUSE_STRAP register for pipe c disabled Cc: Damien Lespiau Signed-off-by: Patrik Jakobsson Reviewed-by: Damien Lespiau [Jani: fixed some checkpatch indentation complaints] Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1453300280-10661-1-git-send-email-patrik.jakobsson@linux.intel.com --- drivers/gpu/drm/i915/i915_dma.c | 31 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_reg.h | 3 +++ 2 files changed, 34 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index db9b0c6840a0..4e3c7418729f 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -809,6 +809,37 @@ static void intel_device_info_runtime_init(struct drm_device *dev) DRM_INFO("Display fused off, disabling\n"); info->num_pipes = 0; } + } else if (info->num_pipes > 0 && INTEL_INFO(dev)->gen == 9) { + u32 dfsm = I915_READ(SKL_DFSM); + u8 disabled_mask = 0; + bool invalid; + int num_bits; + + if (dfsm & SKL_DFSM_PIPE_A_DISABLE) + disabled_mask |= BIT(PIPE_A); + if (dfsm & SKL_DFSM_PIPE_B_DISABLE) + disabled_mask |= BIT(PIPE_B); + if (dfsm & SKL_DFSM_PIPE_C_DISABLE) + disabled_mask |= BIT(PIPE_C); + + num_bits = hweight8(disabled_mask); + + switch (disabled_mask) { + case BIT(PIPE_A): + case BIT(PIPE_B): + case BIT(PIPE_A) | BIT(PIPE_B): + case BIT(PIPE_A) | BIT(PIPE_C): + invalid = true; + break; + default: + invalid = false; + } + + if (num_bits > info->num_pipes || invalid) + DRM_ERROR("invalid pipe fuse configuration: 0x%x\n", + disabled_mask); + else + info->num_pipes -= num_bits; } /* Initialize slice/subslice/EU info */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 65e32a317d63..c0bd691b41f8 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5994,6 +5994,9 @@ enum skl_disp_power_wells { #define SKL_DFSM_CDCLK_LIMIT_540 (1 << 23) #define SKL_DFSM_CDCLK_LIMIT_450 (2 << 23) #define SKL_DFSM_CDCLK_LIMIT_337_5 (3 << 23) +#define SKL_DFSM_PIPE_A_DISABLE (1 << 30) +#define SKL_DFSM_PIPE_B_DISABLE (1 << 21) +#define SKL_DFSM_PIPE_C_DISABLE (1 << 28) #define GEN7_FF_SLICE_CS_CHICKEN1 _MMIO(0x20e0) #define GEN9_FFSC_PERCTX_PREEMPT_CTRL (1<<14) -- cgit v1.2.3 From c5244987394648913ae1a03879c58058a2fc2cee Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Sat, 30 Jan 2016 07:59:33 +0200 Subject: drm/radeon: mask out WC from BO on unsupported arches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Reviewed-by: Michel Dänzer Signed-off-by: Oded Gabbay Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_object.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 84d45633d28c..fb6ad143873f 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "radeon.h" #include "radeon_trace.h" @@ -245,6 +246,12 @@ int radeon_bo_create(struct radeon_device *rdev, DRM_INFO_ONCE("Please enable CONFIG_MTRR and CONFIG_X86_PAT for " "better performance thanks to write-combining\n"); bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC); +#else + /* For architectures that don't support WC memory, + * mask out the WC flag from the BO + */ + if (!drm_arch_can_wc_memory()) + bo->flags &= ~RADEON_GEM_GTT_WC; #endif radeon_ttm_placement_from_domain(bo, domain); -- cgit v1.2.3 From a187f17f0e15a046aa5d7263b35df55230d92779 Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Sat, 30 Jan 2016 07:59:34 +0200 Subject: drm/amdgpu: mask out WC from BO on unsupported arches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Reviewed-by: Michel Dänzer Signed-off-by: Oded Gabbay Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index a2a16acee34d..b8fbbd7699e4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "amdgpu.h" #include "amdgpu_trace.h" @@ -261,6 +262,13 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, AMDGPU_GEM_DOMAIN_OA); bo->flags = flags; + + /* For architectures that don't support WC memory, + * mask out the WC flag from the BO + */ + if (!drm_arch_can_wc_memory()) + bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC; + amdgpu_fill_placement_to_bo(bo, placement); /* Kernel allocation are uninterruptible */ r = ttm_bo_init(&adev->mman.bdev, &bo->tbo, size, type, -- cgit v1.2.3 From d81a67cc1bfdc3efed8590ee4e07a40b198908ba Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 29 Jan 2016 14:52:26 +0200 Subject: drm/i915: Sanity check DP AUX message buffer and size While we are calling intel_dp_aux_transfer() with msg->size=0 whenever msg->buffer is NULL, passing NULL to memcpy() is undefined according to the ISO C standard. I haven't found any notes about this in the GNU C's or the kernel's documentation of the function and can't imagine what it would do with the NULL ptr. To better document this use of the parameters it still make sense to add an explicit check for this to the code. Signed-off-by: Imre Deak Reviewed-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/1454071949-24677-1-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index f44aba1019b8..a073f04a5330 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -979,7 +979,10 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) if (WARN_ON(txsize > 20)) return -E2BIG; - memcpy(txbuf + HEADER_SIZE, msg->buffer, msg->size); + if (msg->buffer) + memcpy(txbuf + HEADER_SIZE, msg->buffer, msg->size); + else + WARN_ON(msg->size); ret = intel_dp_aux_ch(intel_dp, txbuf, txsize, rxbuf, rxsize); if (ret > 0) { -- cgit v1.2.3 From 9c06f6744d663205395f88d98aef87edcd3ce5bd Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 29 Jan 2016 14:52:27 +0200 Subject: drm/i915/chv: Fix error path in GPU freq helpers Atm we wouldn't catch these errors or on the error path we would end up with a division-by-zero, fix this up. Signed-off-by: Imre Deak Reviewed-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/1454071949-24677-2-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 31bc4ea395ac..a47b8f219357 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -7185,9 +7185,10 @@ static int chv_gpu_freq(struct drm_i915_private *dev_priv, int val) { int div, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000); - div = vlv_gpu_freq_div(czclk_freq) / 2; + div = vlv_gpu_freq_div(czclk_freq); if (div < 0) return div; + div /= 2; return DIV_ROUND_CLOSEST(czclk_freq * val, 2 * div) / 2; } @@ -7196,9 +7197,10 @@ static int chv_freq_opcode(struct drm_i915_private *dev_priv, int val) { int mul, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000); - mul = vlv_gpu_freq_div(czclk_freq) / 2; + mul = vlv_gpu_freq_div(czclk_freq); if (mul < 0) return mul; + mul /= 2; /* CHV needs even values */ return DIV_ROUND_CLOSEST(val * 2 * mul, czclk_freq) * 2; -- cgit v1.2.3 From b074eae12f1e9f8eb1aafa3d7b922427f9b8e68a Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 29 Jan 2016 14:52:28 +0200 Subject: drm/i915: Add debug info for failed MSI enabling While not being able to enable MSI interrupts may be a normal circumstance, for debugging it may still be a useful information, so emit an info about this. Signed-off-by: Imre Deak Reviewed-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/1454071949-24677-3-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_dma.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 4e3c7418729f..a42eb58f7c41 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1109,8 +1109,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) * be lost or delayed, but we use them anyways to avoid * stuck interrupts on some machines. */ - if (!IS_I945G(dev) && !IS_I945GM(dev)) - pci_enable_msi(dev->pdev); + if (!IS_I945G(dev) && !IS_I945GM(dev)) { + if (pci_enable_msi(dev->pdev) < 0) + DRM_DEBUG_DRIVER("can't enable MSI"); + } intel_device_info_runtime_init(dev); -- cgit v1.2.3 From 05d25214c4d1cab99d1056f99b7e7d95e9e31ed0 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 29 Jan 2016 14:52:29 +0200 Subject: drm/i915: Properly terminate KMS mode name string during tv init Signed-off-by: Imre Deak Reviewed-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/1454071949-24677-4-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_tv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 948cbff6c62e..5034b0055169 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1420,6 +1420,7 @@ intel_tv_get_modes(struct drm_connector *connector) if (!mode_ptr) continue; strncpy(mode_ptr->name, input->name, DRM_DISPLAY_MODE_LEN); + mode_ptr->name[DRM_DISPLAY_MODE_LEN - 1] = '\0'; mode_ptr->hdisplay = hactive_s; mode_ptr->hsync_start = hactive_s + 1; -- cgit v1.2.3 From 842096fc40519e85bd4c0751e65a07cc3e23bd66 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 1 Feb 2016 18:49:32 -0200 Subject: [media] rc/nuvoton_cir: fix locking issue with nvt_enable_cir nvt_enable_cir calls nvt_enable_logical_dev (that may sleep) while holding a spinlock. This patch fixes this and moves the content of nvt_enable_cir to nvt_open as this is the only caller. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index d428b4e6e26f..46a9ece66f75 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -942,23 +942,6 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) return IRQ_HANDLED; } -static void nvt_enable_cir(struct nvt_dev *nvt) -{ - /* set function enable flags */ - nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | - CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, - CIR_IRCON); - - /* enable the CIR logical device */ - nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); - - /* clear all pending interrupts */ - nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); - - /* enable interrupts */ - nvt_set_cir_iren(nvt); -} - static void nvt_disable_cir(struct nvt_dev *nvt) { /* disable CIR interrupts */ @@ -984,9 +967,23 @@ static int nvt_open(struct rc_dev *dev) unsigned long flags; spin_lock_irqsave(&nvt->nvt_lock, flags); - nvt_enable_cir(nvt); + + /* set function enable flags */ + nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | + CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, + CIR_IRCON); + + /* clear all pending interrupts */ + nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); + + /* enable interrupts */ + nvt_set_cir_iren(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + /* enable the CIR logical device */ + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); + return 0; } -- cgit v1.2.3 From b883af30bcd1f37ed39948be529a13f5ac4ec6a2 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 1 Feb 2016 18:50:26 -0200 Subject: [media] rc/nuvoton_cir: fix locking issue when calling nvt_enable_wake nvt_enable_wake calls nvt_select_logical_dev (that may sleep) and is called from contexts holding a spinlock. Fix this. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 46a9ece66f75..efff08a37d4d 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -503,6 +503,8 @@ static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) static void nvt_enable_wake(struct nvt_dev *nvt) { + unsigned long flags; + nvt_efm_enable(nvt); nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); @@ -514,12 +516,16 @@ static void nvt_enable_wake(struct nvt_dev *nvt) nvt_efm_disable(nvt); + spin_lock_irqsave(&nvt->nvt_lock, flags); + nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, CIR_WAKE_IRCON); nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); + + spin_unlock_irqrestore(&nvt->nvt_lock, flags); } #if 0 /* Currently unused */ @@ -1152,9 +1158,10 @@ static void nvt_remove(struct pnp_dev *pdev) /* disable CIR */ nvt_cir_reg_write(nvt, 0, CIR_IREN); nvt_disable_cir(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + /* enable CIR Wake (for IR power-on) */ nvt_enable_wake(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); rc_unregister_device(nvt->rdev); } @@ -1179,14 +1186,14 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) /* disable all CIR interrupts */ nvt_cir_reg_write(nvt, 0, CIR_IREN); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + /* disable cir logical dev */ nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR); /* make sure wake is enabled */ nvt_enable_wake(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - return 0; } @@ -1205,11 +1212,8 @@ static int nvt_resume(struct pnp_dev *pdev) static void nvt_shutdown(struct pnp_dev *pdev) { struct nvt_dev *nvt = pnp_get_drvdata(pdev); - unsigned long flags; - spin_lock_irqsave(&nvt->nvt_lock, flags); nvt_enable_wake(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); } static const struct pnp_device_id nvt_ids[] = { -- cgit v1.2.3 From 137aa3617b3e7e780800855cdc5d3258aa0ea8d9 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 1 Feb 2016 18:50:55 -0200 Subject: [media] rc/nuvoton_cir: fix locking issue when calling nvt_disable_cir nvt_disable_cir calls nvt_disable_logical_dev (that may sleep) and is called from contexts holding a spinlock. Fix this and remove the unneeded clearing of CIR_IREN as this is done in nvt_cir_disable already. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index efff08a37d4d..c96da3aaf00b 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -950,6 +950,10 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) static void nvt_disable_cir(struct nvt_dev *nvt) { + unsigned long flags; + + spin_lock_irqsave(&nvt->nvt_lock, flags); + /* disable CIR interrupts */ nvt_cir_reg_write(nvt, 0, CIR_IREN); @@ -963,6 +967,8 @@ static void nvt_disable_cir(struct nvt_dev *nvt) nvt_clear_cir_fifo(nvt); nvt_clear_tx_fifo(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + /* disable the CIR logical device */ nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR); } @@ -996,11 +1002,8 @@ static int nvt_open(struct rc_dev *dev) static void nvt_close(struct rc_dev *dev) { struct nvt_dev *nvt = dev->priv; - unsigned long flags; - spin_lock_irqsave(&nvt->nvt_lock, flags); nvt_disable_cir(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); } /* Allocate memory, probe hardware, and initialize everything */ @@ -1152,13 +1155,8 @@ exit_free_dev_rdev: static void nvt_remove(struct pnp_dev *pdev) { struct nvt_dev *nvt = pnp_get_drvdata(pdev); - unsigned long flags; - spin_lock_irqsave(&nvt->nvt_lock, flags); - /* disable CIR */ - nvt_cir_reg_write(nvt, 0, CIR_IREN); nvt_disable_cir(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); /* enable CIR Wake (for IR power-on) */ nvt_enable_wake(nvt); -- cgit v1.2.3 From 5ce625a42d6206d5a18222c6475f6b866ef68569 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Mon, 1 Feb 2016 13:59:30 -0200 Subject: [media] usbvision: fix locking error When remove_pending is non-zero, v4l2_lock is never unlocked. Signed-off-by: Insu Yun Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbvision/usbvision-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index 7f5d6f15a49f..12f5ebbd0436 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -1147,6 +1147,7 @@ static int usbvision_radio_close(struct file *file) usbvision_audio_off(usbvision); usbvision->radio = 0; usbvision->user--; + mutex_unlock(&usbvision->v4l2_lock); if (usbvision->remove_pending) { printk(KERN_INFO "%s: Final disconnect\n", __func__); @@ -1155,7 +1156,6 @@ static int usbvision_radio_close(struct file *file) return 0; } - mutex_unlock(&usbvision->v4l2_lock); PDEBUG(DBG_IO, "success"); return v4l2_fh_release(file); } -- cgit v1.2.3 From 24095e766037018e7a4b636834a383f86a9b30f2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 2 Feb 2016 13:47:58 -0200 Subject: [media] msp3400: use IS_ENABLED check instead of #if A recent patch broke the msp3400 driver when CONFIG_MEDIA_CONTROLLER is not set: drivers/media/i2c/msp3400-driver.h:107:5: error: "CONFIG_MEDIA_CONTROLLER" is not defined [-Werror=undef] It was clearly a typo, and this patch changes the "#if CONFIG_MEDIA_CONTROLLER" to a working IS_ENABLED() check. Fixes: fb4932821731 ("[media] msp3400: initialize MC data") Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/msp3400-driver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/i2c/msp3400-driver.h b/drivers/media/i2c/msp3400-driver.h index f0bb37dc9013..a8702aca187a 100644 --- a/drivers/media/i2c/msp3400-driver.h +++ b/drivers/media/i2c/msp3400-driver.h @@ -104,7 +104,7 @@ struct msp_state { unsigned int restart:1; unsigned int watch_stereo:1; -#if CONFIG_MEDIA_CONTROLLER +#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER) struct media_pad pads[IF_AUD_DEC_PAD_NUM_PADS]; #endif }; -- cgit v1.2.3 From 14b5a4bf7acd3c803c9bde857ae054ba19c4a04c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 2 Feb 2016 16:55:30 +0100 Subject: clk: sunxi: don't mark sun6i_ar100_data __initconst The clk-sun6i-ar100 clk driver is a platform driver that may use deferred probing, so its probe function must not access __init symbols. Kbuild warns about this: WARNING: drivers/clk/sunxi/built-in.o(.text+0x15f0): Section mismatch in reference from the function sun6i_a31_ar100_clk_probe() to the (unknown reference) .init.rodata:(unknown) The function sun6i_a31_ar100_clk_probe() references the (unknown reference) __initconst (unknown). This is often because sun6i_a31_ar100_clk_probe lacks a __initconst annotation or the annotation of (unknown) is wrong. Removing the __initconst annotation avoids the warning and makes deferred probing work. Signed-off-by: Arnd Bergmann Fixes: 3ca2377b6fed ("clk: sunxi: rewrite sun6i-ar100 using factors clk") Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-sun6i-ar100.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c index a7f5777834eb..84a187e55360 100644 --- a/drivers/clk/sunxi/clk-sun6i-ar100.c +++ b/drivers/clk/sunxi/clk-sun6i-ar100.c @@ -60,7 +60,7 @@ static const struct clk_factors_config sun6i_ar100_config = { .pshift = 4, }; -static const struct factors_data sun6i_ar100_data __initconst = { +static const struct factors_data sun6i_ar100_data = { .mux = 16, .muxmask = GENMASK(1, 0), .table = &sun6i_ar100_config, -- cgit v1.2.3 From f2b59ac66f980e7636c15e2ebbd09f0ef46881ab Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Tue, 2 Feb 2016 21:09:33 +0530 Subject: EDAC, mpc85xx: Silence unused variable warning We were getting this build warning: drivers/edac/mpc85xx_edac.c:1247:6: warning: unused variable 'pvr' pvr is only used if CONFIG_FSL_SOC_BOOKE is defined. Declare it __maybe_unused. Suggested-by: Guenter Roeck Signed-off-by: Sudip Mukherjee Reviewed-by: Johannes Thumshirn Cc: linux-edac Link: http://lkml.kernel.org/r/1454427573-7994-1-git-send-email-sudipm.mukherjee@gmail.com Signed-off-by: Borislav Petkov --- drivers/edac/mpc85xx_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index b7139c160baf..ca63d0da8889 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -1244,7 +1244,7 @@ static struct platform_driver * const drivers[] = { static int __init mpc85xx_mc_init(void) { int res = 0; - u32 pvr = 0; + u32 __maybe_unused pvr = 0; printk(KERN_INFO "Freescale(R) MPC85xx EDAC driver, " "(C) 2006 Montavista Software\n"); -- cgit v1.2.3 From 3245d460a1eb55b5c3ca31dde7b5c5ac71546edf Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 2 Feb 2016 10:16:51 -0200 Subject: regmap: cache: Fall back to register by register read for cache defaults If we are unable to read the cache defaults for a regmap then fall back on attempting to read them word by word. This is going to be painfully slow for large regmaps but might be adequate for smaller ones. Signed-off-by: Mark Brown [maciej: Use cache_bypass around read and skipping of unreadable regs] Signed-off-by: Maciej S. Szmigiero Signed-off-by: Fabio Estevam Tested-by: Fabio Estevam Signed-off-by: Mark Brown --- drivers/base/regmap/regcache.c | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 348be3a35410..cccceb599b02 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -30,7 +30,7 @@ static int regcache_hw_init(struct regmap *map) int i, j; int ret; int count; - unsigned int val; + unsigned int reg, val; void *tmp_buf; if (!map->num_reg_defaults_raw) @@ -67,27 +67,46 @@ static int regcache_hw_init(struct regmap *map) ret = regmap_raw_read(map, 0, tmp_buf, map->num_reg_defaults_raw); map->cache_bypass = cache_bypass; - if (ret < 0) - goto err_cache_free; - - map->reg_defaults_raw = tmp_buf; - map->cache_free = 1; + if (ret == 0) { + map->reg_defaults_raw = tmp_buf; + map->cache_free = 1; + } else { + kfree(tmp_buf); + } } /* fill the reg_defaults */ for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) { - if (regmap_volatile(map, i * map->reg_stride)) + reg = i * map->reg_stride; + + if (!regmap_readable(map, reg)) continue; - val = regcache_get_val(map, map->reg_defaults_raw, i); - map->reg_defaults[j].reg = i * map->reg_stride; + + if (regmap_volatile(map, reg)) + continue; + + if (map->reg_defaults_raw) { + val = regcache_get_val(map, map->reg_defaults_raw, i); + } else { + bool cache_bypass = map->cache_bypass; + + map->cache_bypass = true; + ret = regmap_read(map, reg, &val); + map->cache_bypass = cache_bypass; + if (ret != 0) { + dev_err(map->dev, "Failed to read %d: %d\n", + reg, ret); + goto err_free; + } + } + + map->reg_defaults[j].reg = reg; map->reg_defaults[j].def = val; j++; } return 0; -err_cache_free: - kfree(tmp_buf); err_free: kfree(map->reg_defaults); -- cgit v1.2.3 From d221b7a8781ce594249cb44644ec9fecd893957d Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 1 Feb 2016 17:39:27 +0000 Subject: clk: sunxi: improve error reporting for the mux clock clk_register_mux returns a pointer wrapped error value in case of failure, so a simple NULL check is not sufficient to catch errors. Fix that and elaborate on the failure reason on the way. The whole function does not return any error value, so silently failing may leave users scratching their heads because the kernel does not provide any clues on what's wrong. Signed-off-by: Andre Przywara Signed-off-by: Maxime Ripard --- drivers/clk/sunxi/clk-sunxi.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index da15f2b12ab2..2524d6f41b3b 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -627,17 +627,29 @@ static void __init sunxi_mux_clk_setup(struct device_node *node, reg = of_iomap(node, 0); i = of_clk_parent_fill(node, parents, SUNXI_MAX_PARENTS); - of_property_read_string(node, "clock-output-names", &clk_name); + if (of_property_read_string(node, "clock-output-names", &clk_name)) { + pr_warn("%s: could not read clock-output-names for \"%s\"\n", + __func__, clk_name); + goto out_unmap; + } clk = clk_register_mux(NULL, clk_name, parents, i, CLK_SET_RATE_PARENT, reg, data->shift, SUNXI_MUX_GATE_WIDTH, 0, &clk_lock); - if (clk) { - of_clk_add_provider(node, of_clk_src_simple_get, clk); - clk_register_clkdev(clk, clk_name, NULL); + if (IS_ERR(clk)) { + pr_warn("%s: failed to register mux clock %s: %ld\n", __func__, + clk_name, PTR_ERR(clk)); + goto out_unmap; } + + of_clk_add_provider(node, of_clk_src_simple_get, clk); + clk_register_clkdev(clk, clk_name, NULL); + return; + +out_unmap: + iounmap(reg); } -- cgit v1.2.3 From e1ea07542352be468e901173c7a1beeee404d696 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Wed, 6 Jan 2016 09:53:41 -0800 Subject: drm/i915/bxt: Don't save/restore eDP panel power during suspend (v3) Our attempts save/restore panel power state in i915_suspend.c are causing unclaimed register warnings on BXT since the registers for this platform differ from older platforms. The big hammer suspend/resume shouldn't be necessary for PP since the connector/encoder hooks should already handle this. In theory we could remove this for all platforms, but in practice it's likely that would cause some regressions since older platforms with LVDS may have incomplete PP handling. For now we'll leave the PCH save/restore alone and change the non-PCH branch to only operate on gen <= 4 so that BXT and future platforms aren't included. v2: Typo fix: s/||/&&/ v3: Change non-PCH condition to a gen <= 4 test rather than listing VLV/CHV/BXT as specific platforms to exclude; should be more future-proof as we add new platforms. (Daniel) Cc: Vandana Kannan Cc: Jani Nikula Cc: Daniel Vetter Cc: drm-intel-fixes@lists.freedesktop.org Signed-off-by: Matt Roper Reviewed-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1452102821-17190-1-git-send-email-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/i915_suspend.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 6c6bedf3eb37..34e061a9ef06 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -49,7 +49,7 @@ static void i915_save_display(struct drm_device *dev) dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS); dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS); dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR); - } else if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) { + } else if (INTEL_INFO(dev)->gen <= 4) { dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL); dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS); dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS); @@ -84,7 +84,7 @@ static void i915_restore_display(struct drm_device *dev) I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS); I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR); I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL); - } else if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) { + } else if (INTEL_INFO(dev)->gen <= 4) { I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS); I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS); I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR); -- cgit v1.2.3 From 3c8e77dd20ab733f855e66bb6197ce84eb33e480 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 Dec 2015 19:23:04 +0900 Subject: clk: move checking .get_parent to __clk_core_init() The .get_parent is mandatory for multi-parent clocks. Move the check to __clk_core_init(), like other callback checkings. Signed-off-by: Masahiro Yamada Reviewed-by: Vladimir Zapolskiy [sboyd@codeaurora.org: Squashed in error path handling, fix typos in commit message] Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 09d84453ea3a..7fe94a5c6b4a 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1695,13 +1695,6 @@ static struct clk_core *__clk_init_parent(struct clk_core *core) goto out; } - if (!core->ops->get_parent) { - WARN(!core->ops->get_parent, - "%s: multi-parent clocks must implement .get_parent\n", - __func__); - goto out; - } - /* * Do our best to cache parent clocks in core->parents. This prevents * unnecessary and expensive lookups. We don't set core->parent here; @@ -2333,6 +2326,13 @@ static int __clk_core_init(struct clk_core *core) goto out; } + if (core->num_parents > 1 && !core->ops->get_parent) { + pr_err("%s: %s must implement .get_parent as it has multi parents\n", + __func__, core->name); + ret = -EINVAL; + goto out; + } + if (core->ops->set_rate_and_parent && !(core->ops->set_parent && core->ops->set_rate)) { pr_err("%s: %s must implement .set_parent & .set_rate\n", -- cgit v1.2.3 From 5146e0b05963f75347c9f4e18996da245f859e32 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 Dec 2015 19:23:04 +0900 Subject: clk: simplify __clk_init_parent() The translation from the index into clk_core is done by clk_core_get_parent_by_index(). The if-block for num_parents == 1 case is duplicating the code in the clk_core_get_parent_by_index(). Drop the "if (num_parents == 1)" from the special case. Instead, set the index to zero if .get_parent() is missing. Signed-off-by: Masahiro Yamada Reviewed-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 38 ++++---------------------------------- 1 file changed, 4 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 7fe94a5c6b4a..dee9c528ea83 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1669,44 +1669,14 @@ struct clk *clk_get_parent(struct clk *clk) } EXPORT_SYMBOL_GPL(clk_get_parent); -/* - * .get_parent is mandatory for clocks with multiple possible parents. It is - * optional for single-parent clocks. Always call .get_parent if it is - * available and WARN if it is missing for multi-parent clocks. - * - * For single-parent clocks without .get_parent, first check to see if the - * .parents array exists, and if so use it to avoid an expensive tree - * traversal. If .parents does not exist then walk the tree. - */ static struct clk_core *__clk_init_parent(struct clk_core *core) { - struct clk_core *ret = NULL; - u8 index; - - /* handle the trivial cases */ + u8 index = 0; - if (!core->num_parents) - goto out; - - if (core->num_parents == 1) { - if (IS_ERR_OR_NULL(core->parent)) - core->parent = clk_core_lookup(core->parent_names[0]); - ret = core->parent; - goto out; - } + if (core->ops->get_parent) + index = core->ops->get_parent(core->hw); - /* - * Do our best to cache parent clocks in core->parents. This prevents - * unnecessary and expensive lookups. We don't set core->parent here; - * that is done by the calling function. - */ - - index = core->ops->get_parent(core->hw); - - ret = clk_core_get_parent_by_index(core, index); - -out: - return ret; + return clk_core_get_parent_by_index(core, index); } static void clk_core_reparent(struct clk_core *core, -- cgit v1.2.3 From 858d5881564026cbc4e6f5e25ae878a27df5d4c9 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 Dec 2015 19:23:06 +0900 Subject: clk: avoid circular clock topology Currently, clk_register() never checks a circular parent looping, but clock providers could register such an insane clock topology. For example, "clk_a" could have "clk_b" as a parent, and vice versa. In this case, clk_core_reparent() creates a circular parent list and __clk_recalc_accuracies() calls itself recursively forever. The core infrastructure should be kind enough to bail out, showing an appropriate error message in such a case. This helps to easily find a bug in clock providers. (uh, I made such a silly mistake when I was implementing my clock providers first. I was upset because the kernel did not respond, without any error message.) This commit adds a new helper function, __clk_is_ancestor(). It returns true if the second argument is a possible ancestor of the first one. If a clock core is a possible ancestor of itself, it would make a loop when it were registered. That should be detected as an error. Signed-off-by: Masahiro Yamada Reviewed-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index dee9c528ea83..5a1507498e05 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2252,6 +2252,38 @@ static inline void clk_debug_unregister(struct clk_core *core) } #endif +/** + * __clk_is_ancestor - check if a clk_core is a possible ancestor of another + * @core: clock core + * @ancestor: ancestor clock core + * + * Returns true if there is a possibility that @ancestor can be an ancestor + * of @core, false otherwise. + * + * This function can be used against @core or @ancestor that has not been + * registered yet. + */ +static bool __clk_is_ancestor(struct clk_core *core, struct clk_core *ancestor) +{ + struct clk_core *parent; + int i; + + for (i = 0; i < core->num_parents; i++) { + parent = clk_core_get_parent_by_index(core, i); + /* + * If ancestor has not been added to clk_{root,orphan}_list + * yet, clk_core_lookup() cannot find it. If parent is NULL, + * compare the name strings, too. + */ + if ((parent && (parent == ancestor || + __clk_is_ancestor(parent, ancestor))) || + (!parent && !strcmp(core->parent_names[i], ancestor->name))) + return true; + } + + return false; +} + /** * __clk_core_init - initialize the data structures in a struct clk_core * @core: clk_core being initialized @@ -2317,6 +2349,14 @@ static int __clk_core_init(struct clk_core *core) "%s: invalid NULL in %s's .parent_names\n", __func__, core->name); + /* If core is an ancestor of itself, it would make a loop. */ + if (__clk_is_ancestor(core, core)) { + pr_err("%s: %s would create circular parent\n", __func__, + core->name); + ret = -EINVAL; + goto out; + } + core->parent = __clk_init_parent(core); /* -- cgit v1.2.3 From 0e8f6e499ebfd3617c81a89778f55fa6c54623e8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 Dec 2015 19:23:07 +0900 Subject: clk: walk the orphan clock list more simply This loop can be much simpler. If a new parent is available for orphan clocks, __clk_init_parent(orphan) can detect it. Signed-off-by: Masahiro Yamada Reviewed-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 5a1507498e05..03820467fbba 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2422,24 +2422,15 @@ static int __clk_core_init(struct clk_core *core) core->rate = core->req_rate = rate; /* - * walk the list of orphan clocks and reparent any that are children of - * this clock + * walk the list of orphan clocks and reparent any that newly finds a + * parent. */ hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) { - if (orphan->num_parents && orphan->ops->get_parent) { - i = orphan->ops->get_parent(orphan->hw); - if (i >= 0 && i < orphan->num_parents && - !strcmp(core->name, orphan->parent_names[i])) - clk_core_reparent(orphan, core); - continue; - } + struct clk_core *parent = __clk_init_parent(orphan); - for (i = 0; i < orphan->num_parents; i++) - if (!strcmp(core->name, orphan->parent_names[i])) { - clk_core_reparent(orphan, core); - break; - } - } + if (parent) + clk_core_reparent(orphan, parent); + } /* * optional platform-specific magic -- cgit v1.2.3 From 508f884a66abb61f22fcc2b36ab1e68492f1d295 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 Dec 2015 19:23:08 +0900 Subject: clk: make sure parent is not NULL in clk_fetch_parent_index() If parent is given with NULL, clk_fetch_parent_index() could return a positive index value. Currently, parent is checked by the callers of this function, but it would be safer to do it in this function. Signed-off-by: Masahiro Yamada Reviewed-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 03820467fbba..da7c9a523f02 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1066,6 +1066,9 @@ static int clk_fetch_parent_index(struct clk_core *core, { int i; + if (!parent) + return -EINVAL; + /* * find index of new parent clock using cached parent ptrs, * or if not yet cached, use string name comparison and cache -- cgit v1.2.3 From 470b5e2f97cf8fb6a8375cc59e86314c9dd354c2 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 Dec 2015 19:23:09 +0900 Subject: clk: simplify clk_fetch_parent_index() function The clk_core_get_parent_by_index can be used as a helper function to simplify the implementation of clk_fetch_parent_index(). Signed-off-by: Masahiro Yamada Reviewed-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index da7c9a523f02..82b79a6ec0ec 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1069,23 +1069,9 @@ static int clk_fetch_parent_index(struct clk_core *core, if (!parent) return -EINVAL; - /* - * find index of new parent clock using cached parent ptrs, - * or if not yet cached, use string name comparison and cache - * them now to avoid future calls to clk_core_lookup. - */ - for (i = 0; i < core->num_parents; i++) { - if (core->parents[i] == parent) - return i; - - if (core->parents[i]) - continue; - - if (!strcmp(core->parent_names[i], parent->name)) { - core->parents[i] = clk_core_lookup(parent->name); + for (i = 0; i < core->num_parents; i++) + if (clk_core_get_parent_by_index(core, i) == parent) return i; - } - } return -EINVAL; } -- cgit v1.2.3 From e8f0e68ec0802dc840e29e0fabdcfdc39aa2a8fb Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 Dec 2015 19:23:10 +0900 Subject: clk: slightly optimize clk_core_set_parent() If clk_fetch_parent_index() fails, p_rate is unused. Move the assignment after the error checking. Signed-off-by: Masahiro Yamada Reviewed-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 82b79a6ec0ec..d31ed95d27a4 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1748,13 +1748,13 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent) /* try finding the new parent index */ if (parent) { p_index = clk_fetch_parent_index(core, parent); - p_rate = parent->rate; if (p_index < 0) { pr_debug("%s: clk %s can not be parent of clk %s\n", __func__, parent->name, core->name); ret = p_index; goto out; } + p_rate = parent->rate; } /* propagate PRE_RATE_CHANGE notifications */ -- cgit v1.2.3 From 7001ec560a82d1cc2ba5c0c9ac1f7fcca820b27e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 1 Feb 2016 11:19:10 +0100 Subject: clk: vt8500: don't return possibly uninitialized data The clk-vt8500.c driver would previously enter an endless loop when invalid settings got requested, this was now fixed. However, the driver will now return uninitialized data for a subset of those cases instead, as the gcc correctly warns: clk/clk-vt8500.c: In function 'wm8650_find_pll_bits': clk/clk-vt8500.c:423:12: error: 'best_div2' may be used uninitialized in this function [-Werror=maybe-uninitialized] *divisor2 = best_div2; ^ clk/clk-vt8500.c:422:12: error: 'best_div1' may be used uninitialized in this function [-Werror=maybe-uninitialized] *divisor1 = best_div1; ^ clk/clk-vt8500.c:421:14: error: 'best_mul' may be used uninitialized in this function [-Werror=maybe-uninitialized] *multiplier = best_mul; This reworks the error handling in the driver so we now return -EINVAL from clk_round_rate() and clk_set_rate() when we get impossible inputs. Signed-off-by: Arnd Bergmann Fixes: 090341b0a95d ("clk: vt8500: fix sign of possible PLL values") Signed-off-by: Stephen Boyd --- drivers/clk/clk-vt8500.c | 91 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c index 98c4492d2c0d..b0f76a84f1e9 100644 --- a/drivers/clk/clk-vt8500.c +++ b/drivers/clk/clk-vt8500.c @@ -355,7 +355,7 @@ CLK_OF_DECLARE(vt8500_device, "via,vt8500-device-clock", vtwm_device_clk_init); #define WM8850_BITS_TO_VAL(m, d1, d2) \ ((((m / 2) - 1) << 16) | ((d1 - 1) << 8) | d2) -static void vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate, +static int vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate, u32 *multiplier, u32 *prediv) { unsigned long tclk; @@ -365,7 +365,7 @@ static void vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate, pr_err("%s: requested rate out of range\n", __func__); *multiplier = 0; *prediv = 1; - return; + return -EINVAL; } if (rate <= parent_rate * 31) /* use the prediv to double the resolution */ @@ -379,9 +379,11 @@ static void vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate, if (tclk != rate) pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate, tclk); + + return 0; } -static void wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate, +static int wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate, u32 *multiplier, u32 *divisor1, u32 *divisor2) { u32 mul, div1; @@ -404,7 +406,7 @@ static void wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate, *multiplier = mul; *divisor1 = div1; *divisor2 = div2; - return; + return 0; } if (rate_err < best_err) { @@ -415,12 +417,19 @@ static void wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate, } } + if (best_err == (unsigned long)-1) { + pr_warn("%s: impossible rate %lu\n", __func__, rate); + return -EINVAL; + } + /* if we got here, it wasn't an exact match */ pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate, rate - best_err); *multiplier = best_mul; *divisor1 = best_div1; *divisor2 = best_div2; + + return 0; } static u32 wm8750_get_filter(u32 parent_rate, u32 divisor1) @@ -450,7 +459,7 @@ static u32 wm8750_get_filter(u32 parent_rate, u32 divisor1) return 0; } -static void wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate, +static int wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate, u32 *filter, u32 *multiplier, u32 *divisor1, u32 *divisor2) { u32 mul; @@ -474,7 +483,7 @@ static void wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate, *multiplier = mul; *divisor1 = div1; *divisor2 = div2; - return; + return 0; } if (rate_err < best_err) { @@ -485,6 +494,11 @@ static void wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate, } } + if (best_err == (unsigned long)-1) { + pr_warn("%s: impossible rate %lu\n", __func__, rate); + return -EINVAL; + } + /* if we got here, it wasn't an exact match */ pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate, rate - best_err); @@ -493,9 +507,11 @@ static void wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate, *multiplier = best_mul; *divisor1 = best_div1; *divisor2 = best_div2; + + return 0; } -static void wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate, +static int wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate, u32 *multiplier, u32 *divisor1, u32 *divisor2) { u32 mul; @@ -519,7 +535,7 @@ static void wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate, *multiplier = mul; *divisor1 = div1; *divisor2 = div2; - return; + return 0; } if (rate_err < best_err) { @@ -530,6 +546,11 @@ static void wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate, } } + if (best_err == (unsigned long)-1) { + pr_warn("%s: impossible rate %lu\n", __func__, rate); + return -EINVAL; + } + /* if we got here, it wasn't an exact match */ pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate, rate - best_err); @@ -537,6 +558,8 @@ static void wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate, *multiplier = best_mul; *divisor1 = best_div1; *divisor2 = best_div2; + + return 0; } static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate, @@ -546,31 +569,39 @@ static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate, u32 filter, mul, div1, div2; u32 pll_val; unsigned long flags = 0; + int ret; /* sanity check */ switch (pll->type) { case PLL_TYPE_VT8500: - vt8500_find_pll_bits(rate, parent_rate, &mul, &div1); - pll_val = VT8500_BITS_TO_VAL(mul, div1); + ret = vt8500_find_pll_bits(rate, parent_rate, &mul, &div1); + if (!ret) + pll_val = VT8500_BITS_TO_VAL(mul, div1); break; case PLL_TYPE_WM8650: - wm8650_find_pll_bits(rate, parent_rate, &mul, &div1, &div2); - pll_val = WM8650_BITS_TO_VAL(mul, div1, div2); + ret = wm8650_find_pll_bits(rate, parent_rate, &mul, &div1, &div2); + if (!ret) + pll_val = WM8650_BITS_TO_VAL(mul, div1, div2); break; case PLL_TYPE_WM8750: - wm8750_find_pll_bits(rate, parent_rate, &filter, &mul, &div1, &div2); - pll_val = WM8750_BITS_TO_VAL(filter, mul, div1, div2); + ret = wm8750_find_pll_bits(rate, parent_rate, &filter, &mul, &div1, &div2); + if (!ret) + pll_val = WM8750_BITS_TO_VAL(filter, mul, div1, div2); break; case PLL_TYPE_WM8850: - wm8850_find_pll_bits(rate, parent_rate, &mul, &div1, &div2); - pll_val = WM8850_BITS_TO_VAL(mul, div1, div2); + ret = wm8850_find_pll_bits(rate, parent_rate, &mul, &div1, &div2); + if (!ret) + pll_val = WM8850_BITS_TO_VAL(mul, div1, div2); break; default: pr_err("%s: invalid pll type\n", __func__); - return 0; + ret = -EINVAL; } + if (ret) + return ret; + spin_lock_irqsave(pll->lock, flags); vt8500_pmc_wait_busy(); @@ -588,28 +619,36 @@ static long vtwm_pll_round_rate(struct clk_hw *hw, unsigned long rate, struct clk_pll *pll = to_clk_pll(hw); u32 filter, mul, div1, div2; long round_rate; + int ret; switch (pll->type) { case PLL_TYPE_VT8500: - vt8500_find_pll_bits(rate, *prate, &mul, &div1); - round_rate = VT8500_BITS_TO_FREQ(*prate, mul, div1); + ret = vt8500_find_pll_bits(rate, *prate, &mul, &div1); + if (!ret) + round_rate = VT8500_BITS_TO_FREQ(*prate, mul, div1); break; case PLL_TYPE_WM8650: - wm8650_find_pll_bits(rate, *prate, &mul, &div1, &div2); - round_rate = WM8650_BITS_TO_FREQ(*prate, mul, div1, div2); + ret = wm8650_find_pll_bits(rate, *prate, &mul, &div1, &div2); + if (!ret) + round_rate = WM8650_BITS_TO_FREQ(*prate, mul, div1, div2); break; case PLL_TYPE_WM8750: - wm8750_find_pll_bits(rate, *prate, &filter, &mul, &div1, &div2); - round_rate = WM8750_BITS_TO_FREQ(*prate, mul, div1, div2); + ret = wm8750_find_pll_bits(rate, *prate, &filter, &mul, &div1, &div2); + if (!ret) + round_rate = WM8750_BITS_TO_FREQ(*prate, mul, div1, div2); break; case PLL_TYPE_WM8850: - wm8850_find_pll_bits(rate, *prate, &mul, &div1, &div2); - round_rate = WM8850_BITS_TO_FREQ(*prate, mul, div1, div2); + ret = wm8850_find_pll_bits(rate, *prate, &mul, &div1, &div2); + if (!ret) + round_rate = WM8850_BITS_TO_FREQ(*prate, mul, div1, div2); break; default: - round_rate = 0; + ret = -EINVAL; } + if (ret) + return ret; + return round_rate; } -- cgit v1.2.3 From 4106a3d9ebb9839a8e93b0116c0f94dc4f10e4b2 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Sat, 30 Jan 2016 10:12:04 -0500 Subject: clk: unlock for handling unregistered clock If clock is already unregistered, it returns with holding lock. It needs to be unlocked. Signed-off-by: Insu Yun [sboyd@codeaurora.org: Use goto instead] Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index d31ed95d27a4..bb01ed6cc63e 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2641,7 +2641,7 @@ void clk_unregister(struct clk *clk) if (clk->core->ops == &clk_nodrv_ops) { pr_err("%s: unregistered clock: %s\n", __func__, clk->core->name); - return; + goto unlock; } /* * Assign empty clock ops for consumers that might still hold @@ -2667,7 +2667,7 @@ void clk_unregister(struct clk *clk) pr_warn("%s: unregistering prepared clock: %s\n", __func__, clk->core->name); kref_put(&clk->core->ref, __clk_release); - +unlock: clk_prepare_unlock(); } EXPORT_SYMBOL_GPL(clk_unregister); -- cgit v1.2.3 From 2467b6745e0ae9c6cdccff24c4cceeb14b1cce3f Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Tue, 2 Feb 2016 11:37:50 +0800 Subject: clk: rockchip: free memory in error cases when registering clock branches Add free memeory if rockchip_clk_register_branch fails. Fixes: a245fecbb806 ("clk: rockchip: add basic infrastructure...") Signed-off-by: Shawn Lin Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index d9a0b5d4d47f..62fbe2c6eaaf 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -70,7 +70,7 @@ static struct clk *rockchip_clk_register_branch(const char *name, if (gate_offset >= 0) { gate = kzalloc(sizeof(*gate), GFP_KERNEL); if (!gate) - return ERR_PTR(-ENOMEM); + goto err_gate; gate->flags = gate_flags; gate->reg = base + gate_offset; @@ -82,7 +82,7 @@ static struct clk *rockchip_clk_register_branch(const char *name, if (div_width > 0) { div = kzalloc(sizeof(*div), GFP_KERNEL); if (!div) - return ERR_PTR(-ENOMEM); + goto err_div; div->flags = div_flags; div->reg = base + muxdiv_offset; @@ -100,6 +100,11 @@ static struct clk *rockchip_clk_register_branch(const char *name, flags); return clk; +err_div: + kfree(gate); +err_gate: + kfree(mux); + return ERR_PTR(-ENOMEM); } struct rockchip_clk_frac { -- cgit v1.2.3 From 1d961f11a108af9f7fbe89cc950a8d16ddbdbb28 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Mon, 1 Feb 2016 16:18:40 +0800 Subject: soc: rockchip: power-domain: fix err handle while probing If we fail to probe the driver, we should not directly break from the for_each_available_child_of_node since it calls of_node_get while iterating. This patch add of_node_put to fix the unbalanced call pair. Fixes: 7c696693a4f5 ("soc: rockchip: power-domain: Add power domain driver") Signed-off-by: Shawn Lin Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/pm_domains.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 6cdffb13c862..43155e1f97b9 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -423,6 +423,7 @@ static int rockchip_pm_domain_probe(struct platform_device *pdev) if (error) { dev_err(dev, "failed to handle node %s: %d\n", node->name, error); + of_node_put(node); goto err_out; } } -- cgit v1.2.3 From 1d22a454ecda91c8b8c67ff2b07cdbdf7d26ede1 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 2 Feb 2016 14:42:28 -0500 Subject: drm/amdgpu/gfx8: enable cp inst/reg error interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable CP register/instruction error interrupts. Useful for debugging command stream problems. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 95c0cdfbd1b3..39fa41bcae10 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -3901,6 +3901,8 @@ static int gfx_v8_0_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0); + amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0); gfx_v8_0_cp_enable(adev, false); gfx_v8_0_rlc_stop(adev); gfx_v8_0_cp_compute_fini(adev); @@ -4329,6 +4331,14 @@ static int gfx_v8_0_late_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; int r; + r = amdgpu_irq_get(adev, &adev->gfx.priv_reg_irq, 0); + if (r) + return r; + + r = amdgpu_irq_get(adev, &adev->gfx.priv_inst_irq, 0); + if (r) + return r; + /* requires IBs so do in late init after IB pool is initialized */ r = gfx_v8_0_do_edc_gpr_workarounds(adev); if (r) -- cgit v1.2.3 From ef720532ecc22a76fea4450bcc91ee054cde9bdb Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 2 Feb 2016 14:46:48 -0500 Subject: drm/amdgpu/gfx7: enable cp inst/reg error interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable CP register/instruction error interrupts. Useful for debugging command stream problems. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 72793f93e2fc..6c76139de1c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -4738,6 +4738,22 @@ static int gfx_v7_0_early_init(void *handle) return 0; } +static int gfx_v7_0_late_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int r; + + r = amdgpu_irq_get(adev, &adev->gfx.priv_reg_irq, 0); + if (r) + return r; + + r = amdgpu_irq_get(adev, &adev->gfx.priv_inst_irq, 0); + if (r) + return r; + + return 0; +} + static int gfx_v7_0_sw_init(void *handle) { struct amdgpu_ring *ring; @@ -4890,6 +4906,8 @@ static int gfx_v7_0_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0); + amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0); gfx_v7_0_cp_enable(adev, false); gfx_v7_0_rlc_stop(adev); gfx_v7_0_fini_pg(adev); @@ -5527,7 +5545,7 @@ static int gfx_v7_0_set_powergating_state(void *handle, const struct amd_ip_funcs gfx_v7_0_ip_funcs = { .early_init = gfx_v7_0_early_init, - .late_init = NULL, + .late_init = gfx_v7_0_late_init, .sw_init = gfx_v7_0_sw_init, .sw_fini = gfx_v7_0_sw_fini, .hw_init = gfx_v7_0_hw_init, -- cgit v1.2.3 From d4584ddfc97518a575ed538307e81e73456b8175 Mon Sep 17 00:00:00 2001 From: Matan Barak Date: Thu, 28 Jan 2016 17:51:46 +0200 Subject: IB/mlx5: Add CREATE_CQ and CREATE_QP to uverbs_ex_cmd_mask The mlx5_ib driver supports the extended create_cq and create_qp user verbs. In the current mechanism, a vendor supporting an extended uverb should set the appropriate bit in the uverbs_ex_cmd_mask field. Adding the actual support by setting the required bits in order to support features like completion time-stamping and cross-channel. Fixes: 972ecb821379 ('IB/mlx5: Add create_cq extended command') Fixes: ddf9529be19c ('IB/core: Allow setting create flags in QP init attribute') Signed-off-by: Matan Barak Signed-off-by: Doug Ledford --- drivers/infiniband/hw/mlx5/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index ec737e2287fe..6f67412c1296 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -2214,7 +2214,9 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev) (1ull << IB_USER_VERBS_CMD_CREATE_XSRQ) | (1ull << IB_USER_VERBS_CMD_OPEN_QP); dev->ib_dev.uverbs_ex_cmd_mask = - (1ull << IB_USER_VERBS_EX_CMD_QUERY_DEVICE); + (1ull << IB_USER_VERBS_EX_CMD_QUERY_DEVICE) | + (1ull << IB_USER_VERBS_EX_CMD_CREATE_CQ) | + (1ull << IB_USER_VERBS_EX_CMD_CREATE_QP); dev->ib_dev.query_device = mlx5_ib_query_device; dev->ib_dev.query_port = mlx5_ib_query_port; -- cgit v1.2.3 From a168a41c8147fe644f1144031a6ec27a1a13fe37 Mon Sep 17 00:00:00 2001 From: Majd Dibbiny Date: Thu, 28 Jan 2016 17:51:47 +0200 Subject: IB/mlx5: Fix reqlen validation in mlx5_ib_alloc_ucontext Older libraries that don't have all the new req_v2 fields should be able to work as well. Today, if the library uses v2, it will fail to allocate context since the size of reqlen is smaller than the req_v2 size. Fix the validation to be with the original req_v2 size and not the current. Fixes: f72300c56c3b ('IB/mlx5: Expose CQE version to user-space') Signed-off-by: Majd Dibbiny Signed-off-by: Doug Ledford --- drivers/infiniband/hw/mlx5/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 6f67412c1296..03c418ccbc98 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -844,6 +844,8 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev, int err; int i; size_t reqlen; + size_t min_req_v2 = offsetof(struct mlx5_ib_alloc_ucontext_req_v2, + max_cqe_version); if (!dev->ib_active) return ERR_PTR(-EAGAIN); @@ -854,7 +856,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev, reqlen = udata->inlen - sizeof(struct ib_uverbs_cmd_hdr); if (reqlen == sizeof(struct mlx5_ib_alloc_ucontext_req)) ver = 0; - else if (reqlen >= sizeof(struct mlx5_ib_alloc_ucontext_req_v2)) + else if (reqlen >= min_req_v2) ver = 2; else return ERR_PTR(-EINVAL); -- cgit v1.2.3 From 09f16cf59fbf825130c216c3af189253505dc9d9 Mon Sep 17 00:00:00 2001 From: Majd Dibbiny Date: Thu, 28 Jan 2016 17:51:48 +0200 Subject: IB/mlx5: Fix use of null pointer PD When a Raw Ethernet QP is created, a NULL pointer PD could be used. Fixing that by only using the PD after validating it's valid. smatch also reported this error: drivers/infiniband/hw/mlx5/qp.c:1629 mlx5_ib_create_qp() error: we previously assumed 'pd' could be null (see line 1616) Fixes: 0fb2ed66a14c ('IB/mlx5: Add create and destroy functionality for Raw Packet QP') Signed-off-by: Majd Dibbiny Reported-by: Dan Carpenter Signed-off-by: Doug Ledford --- drivers/infiniband/hw/mlx5/qp.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 8fb9c27485e1..40bbe962a1ce 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -1615,15 +1615,6 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, if (pd) { dev = to_mdev(pd->device); - } else { - /* being cautious here */ - if (init_attr->qp_type != IB_QPT_XRC_TGT && - init_attr->qp_type != MLX5_IB_QPT_REG_UMR) { - pr_warn("%s: no PD for transport %s\n", __func__, - ib_qp_type_str(init_attr->qp_type)); - return ERR_PTR(-EINVAL); - } - dev = to_mdev(to_mxrcd(init_attr->xrcd)->ibxrcd.device); if (init_attr->qp_type == IB_QPT_RAW_PACKET) { if (!pd->uobject) { @@ -1634,6 +1625,15 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, return ERR_PTR(-EINVAL); } } + } else { + /* being cautious here */ + if (init_attr->qp_type != IB_QPT_XRC_TGT && + init_attr->qp_type != MLX5_IB_QPT_REG_UMR) { + pr_warn("%s: no PD for transport %s\n", __func__, + ib_qp_type_str(init_attr->qp_type)); + return ERR_PTR(-EINVAL); + } + dev = to_mdev(to_mxrcd(init_attr->xrcd)->ibxrcd.device); } switch (init_attr->qp_type) { -- cgit v1.2.3 From 01581fb89e5a6d41d06132aefe105a506f04ce1e Mon Sep 17 00:00:00 2001 From: Maor Gottlieb Date: Thu, 28 Jan 2016 17:51:49 +0200 Subject: IB/mlx5: Use MLX5_GET to correctly get end of padding mode MLX5_GET64 was used on end_padding_mode, which is a 2-bit field. This is wrong as the calculated offset is incorrect. Using MLX5_GET instead of MLX5_GET64 to fix that. Fixes: 0fb2ed66a14c ('IB/mlx5: Add create and destroy functionality for Raw Packet QP') Signed-off-by: Maor Gottlieb Signed-off-by: Doug Ledford --- drivers/infiniband/hw/mlx5/qp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 40bbe962a1ce..9116bc3988a6 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -1036,7 +1036,7 @@ static int create_raw_packet_qp_rq(struct mlx5_ib_dev *dev, wq = MLX5_ADDR_OF(rqc, rqc, wq); MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_CYCLIC); MLX5_SET(wq, wq, end_padding_mode, - MLX5_GET64(qpc, qpc, end_padding_mode)); + MLX5_GET(qpc, qpc, end_padding_mode)); MLX5_SET(wq, wq, page_offset, MLX5_GET(qpc, qpc, page_offset)); MLX5_SET(wq, wq, pd, MLX5_GET(qpc, qpc, pd)); MLX5_SET64(wq, wq, dbr_addr, MLX5_GET64(qpc, qpc, dbr_addr)); -- cgit v1.2.3 From 1c5e08099022942cd530c99f5f292c735acc288f Mon Sep 17 00:00:00 2001 From: Moni Shoua Date: Thu, 28 Jan 2016 17:51:50 +0200 Subject: IB/core: Set correct payload length for RoCEv2 over IPv6 For GSI QP traffic, the count of the udp header bytes was missing from the IPv6 header, fix that. Fixes: 25f40220e56b ('IB/core: Initialize UD header structure with IP and UDP headers') Signed-off-by: Moni Shoua Signed-off-by: Doug Ledford --- drivers/infiniband/core/ud_header.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/ud_header.c b/drivers/infiniband/core/ud_header.c index 19837d270278..2116132568e7 100644 --- a/drivers/infiniband/core/ud_header.c +++ b/drivers/infiniband/core/ud_header.c @@ -322,6 +322,8 @@ int ib_ud_header_init(int payload_bytes, int immediate_present, struct ib_ud_header *header) { + size_t udp_bytes = udp_present ? IB_UDP_BYTES : 0; + grh_present = grh_present && !ip_version; memset(header, 0, sizeof *header); @@ -353,7 +355,8 @@ int ib_ud_header_init(int payload_bytes, if (ip_version == 6 || grh_present) { header->grh.ip_version = 6; header->grh.payload_length = - cpu_to_be16((IB_BTH_BYTES + + cpu_to_be16((udp_bytes + + IB_BTH_BYTES + IB_DETH_BYTES + payload_bytes + 4 + /* ICRC */ @@ -362,8 +365,6 @@ int ib_ud_header_init(int payload_bytes, } if (ip_version == 4) { - int udp_bytes = udp_present ? IB_UDP_BYTES : 0; - header->ip4.ver = 4; /* version 4 */ header->ip4.hdr_len = 5; /* 5 words */ header->ip4.tot_len = -- cgit v1.2.3 From ed1f0eeebaeeb7f790e9e7642116a208581e5bfc Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 3 Feb 2016 01:00:29 +0100 Subject: PNP: Add Haswell-ULT to Intel MCH size workaround Add device ID 0x0a04 for Haswell-ULT to the list of devices with MCH problems. From a Lenovo ThinkPad T440S: [ 0.188604] pnp: PnP ACPI init [ 0.189044] system 00:00: [mem 0x00000000-0x0009ffff] could not be reserved [ 0.189048] system 00:00: [mem 0x000c0000-0x000c3fff] could not be reserved [ 0.189050] system 00:00: [mem 0x000c4000-0x000c7fff] could not be reserved [ 0.189052] system 00:00: [mem 0x000c8000-0x000cbfff] could not be reserved [ 0.189054] system 00:00: [mem 0x000cc000-0x000cffff] could not be reserved [ 0.189056] system 00:00: [mem 0x000d0000-0x000d3fff] has been reserved [ 0.189058] system 00:00: [mem 0x000d4000-0x000d7fff] has been reserved [ 0.189060] system 00:00: [mem 0x000d8000-0x000dbfff] has been reserved [ 0.189061] system 00:00: [mem 0x000dc000-0x000dffff] has been reserved [ 0.189063] system 00:00: [mem 0x000e0000-0x000e3fff] could not be reserved [ 0.189065] system 00:00: [mem 0x000e4000-0x000e7fff] could not be reserved [ 0.189067] system 00:00: [mem 0x000e8000-0x000ebfff] could not be reserved [ 0.189069] system 00:00: [mem 0x000ec000-0x000effff] could not be reserved [ 0.189071] system 00:00: [mem 0x000f0000-0x000fffff] could not be reserved [ 0.189073] system 00:00: [mem 0x00100000-0xdf9fffff] could not be reserved [ 0.189075] system 00:00: [mem 0xfec00000-0xfed3ffff] could not be reserved [ 0.189078] system 00:00: [mem 0xfed4c000-0xffffffff] could not be reserved [ 0.189082] system 00:00: Plug and Play ACPI device, IDs PNP0c01 (active) [ 0.189216] system 00:01: [io 0x1800-0x189f] could not be reserved [ 0.189220] system 00:01: [io 0x0800-0x087f] has been reserved [ 0.189222] system 00:01: [io 0x0880-0x08ff] has been reserved [ 0.189224] system 00:01: [io 0x0900-0x097f] has been reserved [ 0.189226] system 00:01: [io 0x0980-0x09ff] has been reserved [ 0.189229] system 00:01: [io 0x0a00-0x0a7f] has been reserved [ 0.189231] system 00:01: [io 0x0a80-0x0aff] has been reserved [ 0.189233] system 00:01: [io 0x0b00-0x0b7f] has been reserved [ 0.189235] system 00:01: [io 0x0b80-0x0bff] has been reserved [ 0.189238] system 00:01: [io 0x15e0-0x15ef] has been reserved [ 0.189240] system 00:01: [io 0x1600-0x167f] has been reserved [ 0.189242] system 00:01: [io 0x1640-0x165f] has been reserved [ 0.189246] system 00:01: [mem 0xf8000000-0xfbffffff] could not be reserved [ 0.189249] system 00:01: [mem 0x00000000-0x00000fff] could not be reserved [ 0.189251] system 00:01: [mem 0xfed1c000-0xfed1ffff] has been reserved [ 0.189254] system 00:01: [mem 0xfed10000-0xfed13fff] has been reserved [ 0.189256] system 00:01: [mem 0xfed18000-0xfed18fff] has been reserved [ 0.189258] system 00:01: [mem 0xfed19000-0xfed19fff] has been reserved [ 0.189261] system 00:01: [mem 0xfed45000-0xfed4bfff] has been reserved [ 0.189264] system 00:01: Plug and Play ACPI device, IDs PNP0c02 (active) [....] [ 0.583653] resource sanity check: requesting [mem 0xfed10000-0xfed15fff], which spans more than pnp 00:01 [mem 0xfed10000-0xfed13fff] [ 0.583654] ------------[ cut here ]------------ [ 0.583660] WARNING: CPU: 0 PID: 1 at arch/x86/mm/ioremap.c:198 __ioremap_caller+0x2c5/0x380() [ 0.583661] Info: mapping multiple BARs. Your kernel is fine. [ 0.583662] Modules linked in: [ 0.583666] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.3.3-303.fc23.x86_64 #1 [ 0.583668] Hardware name: LENOVO 20AR001GXS/20AR001GXS, BIOS GJET86WW (2.36 ) 12/04/2015 [ 0.583670] 0000000000000000 0000000014cf7e59 ffff880214a1baf8 ffffffff813a625f [ 0.583673] ffff880214a1bb40 ffff880214a1bb30 ffffffff810a07c2 00000000fed10000 [ 0.583675] ffffc90000cb8000 0000000000006000 0000000000000000 ffff8800d6381040 [ 0.583678] Call Trace: [ 0.583683] [] dump_stack+0x44/0x55 [ 0.583686] [] warn_slowpath_common+0x82/0xc0 [ 0.583688] [] warn_slowpath_fmt+0x5c/0x80 [ 0.583692] [] ? iomem_map_sanity_check+0xba/0xd0 [ 0.583695] [] __ioremap_caller+0x2c5/0x380 [ 0.583698] [] ioremap_nocache+0x17/0x20 [ 0.583701] [] snb_uncore_imc_init_box+0x79/0xb0 [ 0.583705] [] uncore_pci_probe+0xd0/0x1b0 [ 0.583707] [] local_pci_probe+0x45/0xa0 [ 0.583710] [] pci_device_probe+0xfd/0x140 [ 0.583713] [] driver_probe_device+0x222/0x480 [ 0.583715] [] __driver_attach+0x84/0x90 [ 0.583717] [] ? driver_probe_device+0x480/0x480 [ 0.583720] [] bus_for_each_dev+0x6c/0xc0 [ 0.583722] [] driver_attach+0x1e/0x20 [ 0.583724] [] bus_add_driver+0x1eb/0x280 [ 0.583727] [] ? uncore_cpu_setup+0x12/0x12 [ 0.583729] [] driver_register+0x60/0xe0 [ 0.583733] [] __pci_register_driver+0x4c/0x50 [ 0.583736] [] intel_uncore_init+0xe2/0x2e6 [ 0.583738] [] ? uncore_cpu_setup+0x12/0x12 [ 0.583741] [] do_one_initcall+0xb3/0x200 [ 0.583745] [] ? parse_args+0x1a0/0x4a0 [ 0.583749] [] kernel_init_freeable+0x189/0x223 [ 0.583752] [] ? rest_init+0x80/0x80 [ 0.583754] [] kernel_init+0xe/0xe0 [ 0.583758] [] ret_from_fork+0x3f/0x70 [ 0.583760] [] ? rest_init+0x80/0x80 [ 0.583765] ---[ end trace 077c426a39e018aa ]--- 00:00.0 Host bridge [0600]: Intel Corporation Haswell-ULT DRAM Controller [8086:0a04] (rev 0b) Subsystem: Lenovo Device [17aa:220c] Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=fast >TAbort- SERR- Kernel driver in use: hsw_uncore Link: https://bugzilla.redhat.com/show_bug.cgi?id=1300955 Tested-by: Signed-off-by: Josh Boyer Signed-off-by: Rafael J. Wysocki --- drivers/pnp/quirks.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index f700723ca5d6..d28e3ab9479c 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c @@ -342,6 +342,7 @@ static void quirk_amd_mmconfig_area(struct pnp_dev *dev) /* Device IDs of parts that have 32KB MCH space */ static const unsigned int mch_quirk_devices[] = { 0x0154, /* Ivy Bridge */ + 0x0a04, /* Haswell-ULT */ 0x0c00, /* Haswell */ 0x1604, /* Broadwell */ }; -- cgit v1.2.3 From 5be6ada39f3f11a14fae9c6c328bcc78cf476e2e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 1 Feb 2016 16:17:38 +0200 Subject: ACPI / LPSS: set PM domain via helper setter The commit 989561de9b51 ("PM / Domains: add setter for dev.pm_domain") changed acpi_lpss.c module to use PM domain setter, though it missed one assignment. Add it here. Fixes: 989561de9b51 (PM / Domains: add setter for dev.pm_domain) Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_lpss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index c570b1d9f094..0872d5fecb82 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -880,7 +880,7 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, break; case BUS_NOTIFY_DRIVER_NOT_BOUND: case BUS_NOTIFY_UNBOUND_DRIVER: - pdev->dev.pm_domain = NULL; + dev_pm_domain_set(&pdev->dev, NULL); break; case BUS_NOTIFY_ADD_DEVICE: dev_pm_domain_set(&pdev->dev, &acpi_lpss_pm_domain); -- cgit v1.2.3 From 53af16f79fbc3f06df76f6d82adcd4ed03b3d752 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 1 Feb 2016 14:52:41 +0100 Subject: PM / Domains: Silence compiler warning for an unused function The only remaining caller of genpd_poweron() is conditionally compiled based on CONFIG_PM_GENERIC_DOMAINS_OF, so we get a warning when that is unset. By moving the locking/unlocking of the genpd outside genpd_poweron(), thus to the caller, genpd_poweron() becomes redundant. Within this context let's then rename the wrapper function, __genpd_poweron(), to genpd_poweron() as it will then be consistent with its friend genpd_poweroff(). This change silence the warning about the unused function. Reported-by: Arnd Bergmann Fixes: ea823c7cbffa "PM / Domains: Remove pm_genpd_poweron() API" Signed-off-by: Ulf Hansson Acked-by: Arnd Bergmann Cc: 4.4+ # 4.4+ Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 784dbe897a5e..301b785f9f56 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -173,14 +173,14 @@ static void genpd_queue_power_off_work(struct generic_pm_domain *genpd) } /** - * __genpd_poweron - Restore power to a given PM domain and its masters. + * genpd_poweron - Restore power to a given PM domain and its masters. * @genpd: PM domain to power up. * @depth: nesting count for lockdep. * * Restore power to @genpd and all of its masters so that it is possible to * resume a device belonging to it. */ -static int __genpd_poweron(struct generic_pm_domain *genpd, unsigned int depth) +static int genpd_poweron(struct generic_pm_domain *genpd, unsigned int depth) { struct gpd_link *link; int ret = 0; @@ -200,7 +200,7 @@ static int __genpd_poweron(struct generic_pm_domain *genpd, unsigned int depth) genpd_sd_counter_inc(master); mutex_lock_nested(&master->lock, depth + 1); - ret = __genpd_poweron(master, depth + 1); + ret = genpd_poweron(master, depth + 1); mutex_unlock(&master->lock); if (ret) { @@ -227,21 +227,6 @@ static int __genpd_poweron(struct generic_pm_domain *genpd, unsigned int depth) return ret; } -/** - * genpd_poweron - Restore power to a given PM domain and its masters. - * @genpd: PM domain to power up. - */ -static int genpd_poweron(struct generic_pm_domain *genpd) -{ - int ret; - - mutex_lock(&genpd->lock); - ret = __genpd_poweron(genpd, 0); - mutex_unlock(&genpd->lock); - return ret; -} - - static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev) { return GENPD_DEV_CALLBACK(genpd, int, save_state, dev); @@ -489,7 +474,7 @@ static int pm_genpd_runtime_resume(struct device *dev) } mutex_lock(&genpd->lock); - ret = __genpd_poweron(genpd, 0); + ret = genpd_poweron(genpd, 0); mutex_unlock(&genpd->lock); if (ret) @@ -1821,8 +1806,10 @@ int genpd_dev_pm_attach(struct device *dev) dev->pm_domain->detach = genpd_dev_pm_detach; dev->pm_domain->sync = genpd_dev_pm_sync; - ret = genpd_poweron(pd); + mutex_lock(&pd->lock); + ret = genpd_poweron(pd, 0); + mutex_unlock(&pd->lock); out: return ret ? -EPROBE_DEFER : 0; } -- cgit v1.2.3 From ed8d60f450d3db4c4dbb25eddc8f106cbab4bd1c Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 28 Jan 2016 15:09:37 -0800 Subject: drm/i915: Check DDI max lanes after applying BXT workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit bfb9faab8 we added a workaround for some BXT BIOS that fail to properly initialize the DDI_A_4_LANES bit of the control register (4 lanes is the only valid configuration on BXT since there is no DDI E to share with). A recent patch added some additional checks on this register bit before the workaround gets applied; this breaks eDP on BXT in some settings. Some minor code shuffling is all we need to restore the workaround. Cc: Ville Syrjälä Fixes: 7cd87cb80 ("drm/i915: Check max number of lanes when registering DDI ports") Signed-off-by: Matt Roper Link: http://patchwork.freedesktop.org/patch/msgid/1454022577-834-1-git-send-email-matthew.d.roper@intel.com Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_ddi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 1f9a3687b540..6d5b09f2a8a6 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -3281,7 +3281,6 @@ void intel_ddi_init(struct drm_device *dev, enum port port) intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) & (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES); - intel_dig_port->max_lanes = max_lanes; /* * Bspec says that DDI_A_4_LANES is the only supported configuration @@ -3294,9 +3293,12 @@ void intel_ddi_init(struct drm_device *dev, enum port port) if (!(intel_dig_port->saved_port_bits & DDI_A_4_LANES)) { DRM_DEBUG_KMS("BXT BIOS forgot to set DDI_A_4_LANES for port A; fixing\n"); intel_dig_port->saved_port_bits |= DDI_A_4_LANES; + max_lanes = 4; } } + intel_dig_port->max_lanes = max_lanes; + intel_encoder->type = INTEL_OUTPUT_UNKNOWN; intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->cloneable = 0; -- cgit v1.2.3 From e42d85261680edfc350a6c2a86b7fbb44a85014b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 2 Feb 2016 10:59:53 -0500 Subject: drm/amdgpu: move gmc7 support out of CIK dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's used by iceland which is VI. Reviewed-by: Ken Wang Reviewed-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 66f729eaf00b..20c9539abc36 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -25,7 +25,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o # add asic specific block -amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o gmc_v7_0.o cik_ih.o kv_smc.o kv_dpm.o \ +amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \ ci_smc.o ci_dpm.o dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o \ amdgpu_amdkfd_gfx_v7.o @@ -34,6 +34,7 @@ amdgpu-y += \ # add GMC block amdgpu-y += \ + gmc_v7_0.o \ gmc_v8_0.o # add IH block -- cgit v1.2.3 From 429c45deae6e57f1bb91bfb05b671063fb0cef60 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Wed, 3 Feb 2016 19:16:54 +0800 Subject: drm/amdgpu: iceland use CI based MC IP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Ken Wang Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 10 +++++++++- drivers/gpu/drm/amd/amdgpu/vi.c | 7 ++++--- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 3f956065d069..069abc8ea31d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -42,6 +42,7 @@ static void gmc_v7_0_set_irq_funcs(struct amdgpu_device *adev); MODULE_FIRMWARE("radeon/bonaire_mc.bin"); MODULE_FIRMWARE("radeon/hawaii_mc.bin"); +MODULE_FIRMWARE("amdgpu/topaz_mc.bin"); /** * gmc8_mc_wait_for_idle - wait for MC idle callback. @@ -132,13 +133,20 @@ static int gmc_v7_0_init_microcode(struct amdgpu_device *adev) case CHIP_HAWAII: chip_name = "hawaii"; break; + case CHIP_TOPAZ: + chip_name = "topaz"; + break; case CHIP_KAVERI: case CHIP_KABINI: return 0; default: BUG(); } - snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); + if(adev->asic_type == CHIP_TOPAZ) + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mc.bin", chip_name); + else + snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); + err = request_firmware(&adev->mc.fw, fw_name, adev->dev); if (err) goto out; diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 652e76644c31..d94c625575b9 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -61,6 +61,7 @@ #include "vi.h" #include "vi_dpm.h" #include "gmc_v8_0.h" +#include "gmc_v7_0.h" #include "gfx_v8_0.h" #include "sdma_v2_4.h" #include "sdma_v3_0.h" @@ -1109,10 +1110,10 @@ static const struct amdgpu_ip_block_version topaz_ip_blocks[] = }, { .type = AMD_IP_BLOCK_TYPE_GMC, - .major = 8, - .minor = 0, + .major = 7, + .minor = 4, .rev = 0, - .funcs = &gmc_v8_0_ip_funcs, + .funcs = &gmc_v7_0_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_IH, -- cgit v1.2.3 From 8f3c162961fc2d92ec73a66496aab69eb2e19c36 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Wed, 3 Feb 2016 19:17:53 +0800 Subject: drm/amdgpu: The VI specific EXE bit should only apply to GMC v8.0 above MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Ken Wang Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 8a1752ff3d8e..55cf05e1c81c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -808,7 +808,7 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, flags |= AMDGPU_PTE_SNOOPED; } - if (adev->asic_type >= CHIP_TOPAZ) + if (adev->asic_type >= CHIP_TONGA) flags |= AMDGPU_PTE_EXECUTABLE; flags |= AMDGPU_PTE_READABLE; -- cgit v1.2.3 From 72b459c8f716ef03a8a0c78078547ce64d8d29a2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 2 Feb 2016 10:56:15 -0500 Subject: drm/amdgpu: pull topaz gmc bits into gmc_v7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the topaz golden settings into the gmc7 module. Reviewed-by: Ken Wang Reviewed-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 069abc8ea31d..8aa2991ab379 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -44,8 +44,37 @@ MODULE_FIRMWARE("radeon/bonaire_mc.bin"); MODULE_FIRMWARE("radeon/hawaii_mc.bin"); MODULE_FIRMWARE("amdgpu/topaz_mc.bin"); +static const u32 golden_settings_iceland_a11[] = +{ + mmVM_PRT_APERTURE0_LOW_ADDR, 0x0fffffff, 0x0fffffff, + mmVM_PRT_APERTURE1_LOW_ADDR, 0x0fffffff, 0x0fffffff, + mmVM_PRT_APERTURE2_LOW_ADDR, 0x0fffffff, 0x0fffffff, + mmVM_PRT_APERTURE3_LOW_ADDR, 0x0fffffff, 0x0fffffff +}; + +static const u32 iceland_mgcg_cgcg_init[] = +{ + mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104 +}; + +static void gmc_v7_0_init_golden_registers(struct amdgpu_device *adev) +{ + switch (adev->asic_type) { + case CHIP_TOPAZ: + amdgpu_program_register_sequence(adev, + iceland_mgcg_cgcg_init, + (const u32)ARRAY_SIZE(iceland_mgcg_cgcg_init)); + amdgpu_program_register_sequence(adev, + golden_settings_iceland_a11, + (const u32)ARRAY_SIZE(golden_settings_iceland_a11)); + break; + default: + break; + } +} + /** - * gmc8_mc_wait_for_idle - wait for MC idle callback. + * gmc7_mc_wait_for_idle - wait for MC idle callback. * * @adev: amdgpu_device pointer * @@ -142,7 +171,7 @@ static int gmc_v7_0_init_microcode(struct amdgpu_device *adev) default: BUG(); } - if(adev->asic_type == CHIP_TOPAZ) + if (adev->asic_type == CHIP_TOPAZ) snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mc.bin", chip_name); else snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); @@ -992,6 +1021,8 @@ static int gmc_v7_0_hw_init(void *handle) int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; + gmc_v7_0_init_golden_registers(adev); + gmc_v7_0_mc_program(adev); if (!(adev->flags & AMD_IS_APU)) { -- cgit v1.2.3 From 8878d8548ac7fae43cd6d82579f966eb8825e282 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 2 Feb 2016 10:57:30 -0500 Subject: drm/amdgpu: drop topaz support from gmc8 module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit topaz is actually gmc7. Reviewed-by: Ken Wang Reviewed-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 875a5e988cb1..3efd45546241 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -42,7 +42,6 @@ static void gmc_v8_0_set_gart_funcs(struct amdgpu_device *adev); static void gmc_v8_0_set_irq_funcs(struct amdgpu_device *adev); -MODULE_FIRMWARE("amdgpu/topaz_mc.bin"); MODULE_FIRMWARE("amdgpu/tonga_mc.bin"); static const u32 golden_settings_tonga_a11[] = @@ -74,19 +73,6 @@ static const u32 fiji_mgcg_cgcg_init[] = mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104 }; -static const u32 golden_settings_iceland_a11[] = -{ - mmVM_PRT_APERTURE0_LOW_ADDR, 0x0fffffff, 0x0fffffff, - mmVM_PRT_APERTURE1_LOW_ADDR, 0x0fffffff, 0x0fffffff, - mmVM_PRT_APERTURE2_LOW_ADDR, 0x0fffffff, 0x0fffffff, - mmVM_PRT_APERTURE3_LOW_ADDR, 0x0fffffff, 0x0fffffff -}; - -static const u32 iceland_mgcg_cgcg_init[] = -{ - mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104 -}; - static const u32 cz_mgcg_cgcg_init[] = { mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104 @@ -101,14 +87,6 @@ static const u32 stoney_mgcg_cgcg_init[] = static void gmc_v8_0_init_golden_registers(struct amdgpu_device *adev) { switch (adev->asic_type) { - case CHIP_TOPAZ: - amdgpu_program_register_sequence(adev, - iceland_mgcg_cgcg_init, - (const u32)ARRAY_SIZE(iceland_mgcg_cgcg_init)); - amdgpu_program_register_sequence(adev, - golden_settings_iceland_a11, - (const u32)ARRAY_SIZE(golden_settings_iceland_a11)); - break; case CHIP_FIJI: amdgpu_program_register_sequence(adev, fiji_mgcg_cgcg_init, @@ -228,9 +206,6 @@ static int gmc_v8_0_init_microcode(struct amdgpu_device *adev) DRM_DEBUG("\n"); switch (adev->asic_type) { - case CHIP_TOPAZ: - chip_name = "topaz"; - break; case CHIP_TONGA: chip_name = "tonga"; break; @@ -1004,8 +979,7 @@ static int gmc_v8_0_hw_init(void *handle) gmc_v8_0_mc_program(adev); - if ((adev->asic_type == CHIP_TOPAZ) || - (adev->asic_type == CHIP_TONGA)) { + if (adev->asic_type == CHIP_TONGA) { r = gmc_v8_0_mc_load_microcode(adev); if (r) { DRM_ERROR("Failed to load MC firmware!\n"); -- cgit v1.2.3 From 97dde76a30c2e67fa5fb9cb6a4072c0178c9df26 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 2 Feb 2016 11:15:41 -0500 Subject: drm/amdgpu: don't load MEC2 on topaz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not validated. Reviewed-by: Ken Wang Reviewed-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/iceland_smc.c | 12 +++--------- 2 files changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 39fa41bcae10..87c3332f45e3 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -111,7 +111,6 @@ MODULE_FIRMWARE("amdgpu/topaz_ce.bin"); MODULE_FIRMWARE("amdgpu/topaz_pfp.bin"); MODULE_FIRMWARE("amdgpu/topaz_me.bin"); MODULE_FIRMWARE("amdgpu/topaz_mec.bin"); -MODULE_FIRMWARE("amdgpu/topaz_mec2.bin"); MODULE_FIRMWARE("amdgpu/topaz_rlc.bin"); MODULE_FIRMWARE("amdgpu/fiji_ce.bin"); @@ -828,7 +827,8 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev) adev->gfx.mec_fw_version = le32_to_cpu(cp_hdr->header.ucode_version); adev->gfx.mec_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version); - if (adev->asic_type != CHIP_STONEY) { + if ((adev->asic_type != CHIP_STONEY) && + (adev->asic_type != CHIP_TOPAZ)) { snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name); err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev); if (!err) { diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_smc.c b/drivers/gpu/drm/amd/amdgpu/iceland_smc.c index 966d4b2ed9da..090486c18249 100644 --- a/drivers/gpu/drm/amd/amdgpu/iceland_smc.c +++ b/drivers/gpu/drm/amd/amdgpu/iceland_smc.c @@ -432,7 +432,7 @@ static uint32_t iceland_smu_get_mask_for_fw_type(uint32_t fw_type) case AMDGPU_UCODE_ID_CP_ME: return UCODE_ID_CP_ME_MASK; case AMDGPU_UCODE_ID_CP_MEC1: - return UCODE_ID_CP_MEC_MASK | UCODE_ID_CP_MEC_JT1_MASK | UCODE_ID_CP_MEC_JT2_MASK; + return UCODE_ID_CP_MEC_MASK | UCODE_ID_CP_MEC_JT1_MASK; case AMDGPU_UCODE_ID_CP_MEC2: return UCODE_ID_CP_MEC_MASK; case AMDGPU_UCODE_ID_RLC_G: @@ -522,12 +522,6 @@ static int iceland_smu_request_load_fw(struct amdgpu_device *adev) return -EINVAL; } - if (iceland_smu_populate_single_firmware_entry(adev, UCODE_ID_CP_MEC_JT2, - &toc->entry[toc->num_entries++])) { - DRM_ERROR("Failed to get firmware entry for MEC_JT2\n"); - return -EINVAL; - } - if (iceland_smu_populate_single_firmware_entry(adev, UCODE_ID_SDMA0, &toc->entry[toc->num_entries++])) { DRM_ERROR("Failed to get firmware entry for SDMA0\n"); @@ -550,8 +544,8 @@ static int iceland_smu_request_load_fw(struct amdgpu_device *adev) UCODE_ID_CP_ME_MASK | UCODE_ID_CP_PFP_MASK | UCODE_ID_CP_MEC_MASK | - UCODE_ID_CP_MEC_JT1_MASK | - UCODE_ID_CP_MEC_JT2_MASK; + UCODE_ID_CP_MEC_JT1_MASK; + if (iceland_send_msg_to_smc_with_parameter_without_waiting(adev, PPSMC_MSG_LoadUcodes, fw_to_load)) { DRM_ERROR("Fail to request SMU load ucode\n"); -- cgit v1.2.3 From 951e09624a9f417f0b64c872f71feb6738905086 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 2 Feb 2016 16:22:15 -0500 Subject: drm/amdgpu: load MEC ucode manually on iceland MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The smc doesn't handle it. Reviewed-by: Ken Wang Reviewed-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 87c3332f45e3..8f8ec37ecd88 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -3851,10 +3851,16 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev) if (r) return -EINVAL; - r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, - AMDGPU_UCODE_ID_CP_MEC1); - if (r) - return -EINVAL; + if (adev->asic_type == CHIP_TOPAZ) { + r = gfx_v8_0_cp_compute_load_microcode(adev); + if (r) + return r; + } else { + r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, + AMDGPU_UCODE_ID_CP_MEC1); + if (r) + return -EINVAL; + } } } -- cgit v1.2.3 From dba280b20bfd1c2bed8a07ce3f75a6da8ba7d247 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 2 Feb 2016 16:24:20 -0500 Subject: drm/amdgpu: remove exp hardware support from iceland MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's working now. bug: https://bugs.freedesktop.org/show_bug.cgi?id=92270 Reviewed-by: Ken Wang Reviewed-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index b5dbbb573491..9c1af8976bef 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -256,11 +256,11 @@ static struct pci_device_id pciidlist[] = { {0x1002, 0x985F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU}, #endif /* topaz */ - {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT}, + {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, + {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, + {0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, + {0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, + {0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, /* tonga */ {0x1002, 0x6920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA}, {0x1002, 0x6921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA}, -- cgit v1.2.3 From d896910f381737a139686eb3fa9e1c7ce8f59e52 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 15 Jan 2016 14:40:24 +0100 Subject: phy: Restrict phy-hi6220-usb to HiSilicon arm64 The HiSilicon Hi6220 USB PHY is available in HiSilicon Hi6220 SoCs only. Restrict it to HiSilicon arm64, unless compile-testing. Signed-off-by: Geert Uytterhoeven Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index e7e117d5dbbe..0124d17bd9fe 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -224,6 +224,7 @@ config PHY_MT65XX_USB3 config PHY_HI6220_USB tristate "hi6220 USB PHY support" + depends on (ARCH_HISI && ARM64) || COMPILE_TEST select GENERIC_PHY select MFD_SYSCON help -- cgit v1.2.3 From 27ea43fe2a32f63bb6f442dafc2133232b8af4a6 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Sat, 24 Oct 2015 21:15:34 +0200 Subject: nbd: Fix debugfs error handling Static checker complains about the implemented error handling. It is indeed wrong. We don't care about the return values of created debugfs files. We only have to check the return values of created dirs for NULL pointer. If we use a null pointer as parent directory for files, this may lead to debugfs files in wrong places. Signed-off-by: Markus Pargmann --- drivers/block/nbd.c | 55 ++++++++++++++--------------------------------------- 1 file changed, 14 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index e4c5cc107934..d61a04155d99 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -892,50 +892,23 @@ static const struct file_operations nbd_dbg_flags_ops = { static int nbd_dev_dbg_init(struct nbd_device *nbd) { struct dentry *dir; - struct dentry *f; + + if (!nbd_dbg_dir) + return -EIO; dir = debugfs_create_dir(nbd_name(nbd), nbd_dbg_dir); - if (IS_ERR_OR_NULL(dir)) { - dev_err(nbd_to_dev(nbd), "Failed to create debugfs dir for '%s' (%ld)\n", - nbd_name(nbd), PTR_ERR(dir)); - return PTR_ERR(dir); + if (!dir) { + dev_err(nbd_to_dev(nbd), "Failed to create debugfs dir for '%s'\n", + nbd_name(nbd)); + return -EIO; } nbd->dbg_dir = dir; - f = debugfs_create_file("tasks", 0444, dir, nbd, &nbd_dbg_tasks_ops); - if (IS_ERR_OR_NULL(f)) { - dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'tasks', %ld\n", - PTR_ERR(f)); - return PTR_ERR(f); - } - - f = debugfs_create_u64("size_bytes", 0444, dir, &nbd->bytesize); - if (IS_ERR_OR_NULL(f)) { - dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'size_bytes', %ld\n", - PTR_ERR(f)); - return PTR_ERR(f); - } - - f = debugfs_create_u32("timeout", 0444, dir, &nbd->xmit_timeout); - if (IS_ERR_OR_NULL(f)) { - dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'timeout', %ld\n", - PTR_ERR(f)); - return PTR_ERR(f); - } - - f = debugfs_create_u32("blocksize", 0444, dir, &nbd->blksize); - if (IS_ERR_OR_NULL(f)) { - dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'blocksize', %ld\n", - PTR_ERR(f)); - return PTR_ERR(f); - } - - f = debugfs_create_file("flags", 0444, dir, &nbd, &nbd_dbg_flags_ops); - if (IS_ERR_OR_NULL(f)) { - dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'flags', %ld\n", - PTR_ERR(f)); - return PTR_ERR(f); - } + debugfs_create_file("tasks", 0444, dir, nbd, &nbd_dbg_tasks_ops); + debugfs_create_u64("size_bytes", 0444, dir, &nbd->bytesize); + debugfs_create_u32("timeout", 0444, dir, &nbd->xmit_timeout); + debugfs_create_u32("blocksize", 0444, dir, &nbd->blksize); + debugfs_create_file("flags", 0444, dir, &nbd, &nbd_dbg_flags_ops); return 0; } @@ -950,8 +923,8 @@ static int nbd_dbg_init(void) struct dentry *dbg_dir; dbg_dir = debugfs_create_dir("nbd", NULL); - if (IS_ERR(dbg_dir)) - return PTR_ERR(dbg_dir); + if (!dbg_dir) + return -EIO; nbd_dbg_dir = dbg_dir; -- cgit v1.2.3 From 68b2206a57c22d5b7c5bb16308a4afafe04d416d Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Tue, 20 Oct 2015 11:22:32 +0200 Subject: clk/samsung: exynos5433: add definitions of HDMI-PHY output clocks HDMI driver must re-parent respective muxes during HDMI-PHY on/off to HDMI-PHY output clocks. To reference those clocks their definitions should be added. Signed-off-by: Andrzej Hajda Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5433.c | 6 ++++-- include/dt-bindings/clock/exynos5433.h | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index cee062c588de..55300142188b 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -2614,8 +2614,10 @@ static struct samsung_fixed_rate_clock disp_fixed_clks[] __initdata = { FRATE(0, "phyclk_mipidphy0_rxclkesc0_phy", NULL, CLK_IS_ROOT, 100000000), /* PHY clocks from HDMI_PHY */ - FRATE(0, "phyclk_hdmiphy_tmds_clko_phy", NULL, CLK_IS_ROOT, 300000000), - FRATE(0, "phyclk_hdmiphy_pixel_clko_phy", NULL, CLK_IS_ROOT, 166000000), + FRATE(CLK_PHYCLK_HDMIPHY_TMDS_CLKO_PHY, "phyclk_hdmiphy_tmds_clko_phy", + NULL, CLK_IS_ROOT, 300000000), + FRATE(CLK_PHYCLK_HDMIPHY_PIXEL_CLKO_PHY, "phyclk_hdmiphy_pixel_clko_phy", + NULL, CLK_IS_ROOT, 166000000), }; static struct samsung_mux_clock disp_mux_clks[] __initdata = { diff --git a/include/dt-bindings/clock/exynos5433.h b/include/dt-bindings/clock/exynos5433.h index 5bd80d5ecd0f..4f0d5667ee9d 100644 --- a/include/dt-bindings/clock/exynos5433.h +++ b/include/dt-bindings/clock/exynos5433.h @@ -765,7 +765,10 @@ #define CLK_SCLK_RGB_VCLK 109 #define CLK_SCLK_RGB_TV_VCLK 110 -#define DISP_NR_CLK 111 +#define CLK_PHYCLK_HDMIPHY_PIXEL_CLKO_PHY 111 +#define CLK_PHYCLK_HDMIPHY_TMDS_CLKO_PHY 112 + +#define DISP_NR_CLK 113 /* CMU_AUD */ #define CLK_MOUT_AUD_PLL_USER 1 -- cgit v1.2.3 From 02ed910cb4e1c3d03ef70efa94c08f5f580c7ff8 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Tue, 20 Oct 2015 11:22:33 +0200 Subject: clk/samsung: exynos5433: add pclk_decon clock This undocumented gate clock is used by DECON IP. Signed-off-by: Andrzej Hajda Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5433.c | 2 ++ include/dt-bindings/clock/exynos5433.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index 55300142188b..b7f1fb702e05 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -2822,6 +2822,8 @@ static struct samsung_gate_clock disp_gate_clks[] __initdata = { ENABLE_PCLK_DISP, 2, 0, 0), GATE(CLK_PCLK_DECON_TV, "pclk_decon_tv", "div_pclk_disp", ENABLE_PCLK_DISP, 1, 0, 0), + GATE(CLK_PCLK_DECON, "pclk_decon", "div_pclk_disp", + ENABLE_PCLK_DISP, 0, 0, 0), /* ENABLE_SCLK_DISP */ GATE(CLK_PHYCLK_MIPIDPHY1_BITCLKDIV8, "phyclk_mipidphy1_bitclkdiv8", diff --git a/include/dt-bindings/clock/exynos5433.h b/include/dt-bindings/clock/exynos5433.h index 4f0d5667ee9d..5c2636cb9576 100644 --- a/include/dt-bindings/clock/exynos5433.h +++ b/include/dt-bindings/clock/exynos5433.h @@ -768,7 +768,9 @@ #define CLK_PHYCLK_HDMIPHY_PIXEL_CLKO_PHY 111 #define CLK_PHYCLK_HDMIPHY_TMDS_CLKO_PHY 112 -#define DISP_NR_CLK 113 +#define CLK_PCLK_DECON 113 + +#define DISP_NR_CLK 114 /* CMU_AUD */ #define CLK_MOUT_AUD_PLL_USER 1 -- cgit v1.2.3 From e32bb8709fce66ff7f392a33d7689402d3e2ba2e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 2 Feb 2016 11:27:42 +0000 Subject: spi: Fix sorting in Kconfig Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 64 ++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 77064160dd76..7caf18cb3e5e 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -75,6 +75,14 @@ config SPI_ATMEL This selects a driver for the Atmel SPI Controller, present on many AT32 (AVR32) and AT91 (ARM) chips. +config SPI_AU1550 + tristate "Au1550/Au1200/Au1300 SPI Controller" + depends on MIPS_ALCHEMY + select SPI_BITBANG + help + If you say yes to this option, support will be included for the + PSC SPI controller found on Au1550, Au1200 and Au1300 series. + config SPI_BCM2835 tristate "BCM2835 SPI controller" depends on GPIOLIB @@ -118,14 +126,6 @@ config SPI_BFIN_SPORT help Enable support for a SPI bus via the Blackfin SPORT peripheral. -config SPI_AU1550 - tristate "Au1550/Au1200/Au1300 SPI Controller" - depends on MIPS_ALCHEMY - select SPI_BITBANG - help - If you say yes to this option, support will be included for the - PSC SPI controller found on Au1550, Au1200 and Au1300 series. - config SPI_BCM53XX tristate "Broadcom BCM53xx SPI controller" depends on ARCH_BCM_5301X @@ -197,6 +197,23 @@ config SPI_DAVINCI help SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules. +config SPI_DESIGNWARE + tristate "DesignWare SPI controller core support" + help + general driver for SPI controller core from DesignWare + +config SPI_DW_PCI + tristate "PCI interface driver for DW SPI core" + depends on SPI_DESIGNWARE && PCI + +config SPI_DW_MID_DMA + bool "DMA support for DW SPI controller on Intel MID platform" + depends on SPI_DW_PCI && DW_DMAC_PCI + +config SPI_DW_MMIO + tristate "Memory-mapped io interface driver for DW SPI core" + depends on SPI_DESIGNWARE + config SPI_DLN2 tristate "Diolan DLN-2 USB SPI adapter" depends on MFD_DLN2 @@ -346,6 +363,13 @@ config SPI_MT65XX say Y or M here.If you are not sure, say N. SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs. +config SPI_NUC900 + tristate "Nuvoton NUC900 series SPI" + depends on ARCH_W90X900 + select SPI_BITBANG + help + SPI driver for Nuvoton NUC900 series ARM SoCs + config SPI_OC_TINY tristate "OpenCores tiny SPI" depends on GPIOLIB || COMPILE_TEST @@ -647,34 +671,10 @@ config SPI_ZYNQMP_GQSPI help Enables Xilinx GQSPI controller driver for Zynq UltraScale+ MPSoC. -config SPI_NUC900 - tristate "Nuvoton NUC900 series SPI" - depends on ARCH_W90X900 - select SPI_BITBANG - help - SPI driver for Nuvoton NUC900 series ARM SoCs - # # Add new SPI master controllers in alphabetical order above this line # -config SPI_DESIGNWARE - tristate "DesignWare SPI controller core support" - help - general driver for SPI controller core from DesignWare - -config SPI_DW_PCI - tristate "PCI interface driver for DW SPI core" - depends on SPI_DESIGNWARE && PCI - -config SPI_DW_MID_DMA - bool "DMA support for DW SPI controller on Intel MID platform" - depends on SPI_DW_PCI && DW_DMAC_PCI - -config SPI_DW_MMIO - tristate "Memory-mapped io interface driver for DW SPI core" - depends on SPI_DESIGNWARE - # # There are lots of SPI device types, with sensors and memory # being probably the most widely used ones. -- cgit v1.2.3 From 9c6672ac9c91f7eb1ec436be1442b8c26d098e55 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 1 Feb 2016 22:06:55 +0000 Subject: efi: Expose non-blocking set_variable() wrapper to efivars Commit 6d80dba1c9fe ("efi: Provide a non-blocking SetVariable() operation") implemented a non-blocking alternative for the UEFI SetVariable() invocation performed by efivars, since it may occur in atomic context. However, this version of the function was never exposed via the efivars struct, so the non-blocking versions was not actually callable. Fix that. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Fixes: 6d80dba1c9fe ("efi: Provide a non-blocking SetVariable() operation") Link: http://lkml.kernel.org/r/1454364428-494-2-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/efi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 9b815c813687..20451c290233 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -182,6 +182,7 @@ static int generic_ops_register(void) { generic_ops.get_variable = efi.get_variable; generic_ops.set_variable = efi.set_variable; + generic_ops.set_variable_nonblocking = efi.set_variable_nonblocking; generic_ops.get_next_variable = efi.get_next_variable; generic_ops.query_variable_store = efi_query_variable_store; -- cgit v1.2.3 From d3cac1f83c631b9fe5edaebcba49f6989bfff089 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 1 Feb 2016 22:06:57 +0000 Subject: efi/runtime-wrappers: Add a nonblocking version of QueryVariableInfo() This introduces a new runtime wrapper for the QueryVariableInfo() UEFI Runtime Service, which gives up immediately rather than spins on failure to grab the efi_runtime spinlock. This is required in the non-blocking path of the efi-pstore code. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1454364428-494-4-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/runtime-wrappers.c | 22 ++++++++++++++++++++++ include/linux/efi.h | 1 + 2 files changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index 228bbf910461..e9f2867f0d91 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c @@ -230,6 +230,27 @@ static efi_status_t virt_efi_query_variable_info(u32 attr, return status; } +static efi_status_t +virt_efi_query_variable_info_nonblocking(u32 attr, + u64 *storage_space, + u64 *remaining_space, + u64 *max_variable_size) +{ + unsigned long flags; + efi_status_t status; + + if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) + return EFI_UNSUPPORTED; + + if (!spin_trylock_irqsave(&efi_runtime_lock, flags)) + return EFI_NOT_READY; + + status = efi_call_virt(query_variable_info, attr, storage_space, + remaining_space, max_variable_size); + spin_unlock_irqrestore(&efi_runtime_lock, flags); + return status; +} + static efi_status_t virt_efi_get_next_high_mono_count(u32 *count) { unsigned long flags; @@ -300,6 +321,7 @@ void efi_native_runtime_setup(void) efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; efi.reset_system = virt_efi_reset_system; efi.query_variable_info = virt_efi_query_variable_info; + efi.query_variable_info_nonblocking = virt_efi_query_variable_info_nonblocking; efi.update_capsule = virt_efi_update_capsule; efi.query_capsule_caps = virt_efi_query_capsule_caps; } diff --git a/include/linux/efi.h b/include/linux/efi.h index 8706e0aabedc..ad1e177ba48e 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -849,6 +849,7 @@ extern struct efi { efi_set_variable_t *set_variable; efi_set_variable_t *set_variable_nonblocking; efi_query_variable_info_t *query_variable_info; + efi_query_variable_info_t *query_variable_info_nonblocking; efi_update_capsule_t *update_capsule; efi_query_capsule_caps_t *query_capsule_caps; efi_get_next_high_mono_count_t *get_next_high_mono_count; -- cgit v1.2.3 From ca0e30dcaa53a3fcb2dfdf74252d30bc40603eea Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 1 Feb 2016 22:06:58 +0000 Subject: efi: Add nonblocking option to efi_query_variable_store() The function efi_query_variable_store() may be invoked by efivar_entry_set_nonblocking(), which itself takes care to only call a non-blocking version of the SetVariable() runtime wrapper. However, efi_query_variable_store() may call the SetVariable() wrapper directly, as well as the wrapper for QueryVariableInfo(), both of which could deadlock in the same way we are trying to prevent by calling efivar_entry_set_nonblocking() in the first place. So instead, modify efi_query_variable_store() to use the non-blocking variants of QueryVariableInfo() (and give up rather than free up space if the available space is below EFI_MIN_RESERVE) if invoked with the 'nonblocking' argument set to true. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1454364428-494-5-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- arch/x86/platform/efi/quirks.c | 33 ++++++++++++++++++++++++++++++++- drivers/firmware/efi/vars.c | 16 ++++++++++++++-- include/linux/efi.h | 12 +++++++++--- 3 files changed, 55 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index 453504662a33..2326bf51978f 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c @@ -56,6 +56,33 @@ void efi_delete_dummy_variable(void) 0, NULL); } +/* + * In the nonblocking case we do not attempt to perform garbage + * collection if we do not have enough free space. Rather, we do the + * bare minimum check and give up immediately if the available space + * is below EFI_MIN_RESERVE. + * + * This function is intended to be small and simple because it is + * invoked from crash handler paths. + */ +static efi_status_t +query_variable_store_nonblocking(u32 attributes, unsigned long size) +{ + efi_status_t status; + u64 storage_size, remaining_size, max_size; + + status = efi.query_variable_info_nonblocking(attributes, &storage_size, + &remaining_size, + &max_size); + if (status != EFI_SUCCESS) + return status; + + if (remaining_size - size < EFI_MIN_RESERVE) + return EFI_OUT_OF_RESOURCES; + + return EFI_SUCCESS; +} + /* * Some firmware implementations refuse to boot if there's insufficient space * in the variable store. Ensure that we never use more than a safe limit. @@ -63,7 +90,8 @@ void efi_delete_dummy_variable(void) * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable * store. */ -efi_status_t efi_query_variable_store(u32 attributes, unsigned long size) +efi_status_t efi_query_variable_store(u32 attributes, unsigned long size, + bool nonblocking) { efi_status_t status; u64 storage_size, remaining_size, max_size; @@ -71,6 +99,9 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size) if (!(attributes & EFI_VARIABLE_NON_VOLATILE)) return 0; + if (nonblocking) + return query_variable_store_nonblocking(attributes, size); + status = efi.query_variable_info(attributes, &storage_size, &remaining_size, &max_size); if (status != EFI_SUCCESS) diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c index 70a0fb10517f..d2a49626a335 100644 --- a/drivers/firmware/efi/vars.c +++ b/drivers/firmware/efi/vars.c @@ -234,7 +234,18 @@ check_var_size(u32 attributes, unsigned long size) if (!fops->query_variable_store) return EFI_UNSUPPORTED; - return fops->query_variable_store(attributes, size); + return fops->query_variable_store(attributes, size, false); +} + +static efi_status_t +check_var_size_nonblocking(u32 attributes, unsigned long size) +{ + const struct efivar_operations *fops = __efivars->ops; + + if (!fops->query_variable_store) + return EFI_UNSUPPORTED; + + return fops->query_variable_store(attributes, size, true); } static int efi_status_to_err(efi_status_t status) @@ -615,7 +626,8 @@ efivar_entry_set_nonblocking(efi_char16_t *name, efi_guid_t vendor, if (!spin_trylock_irqsave(&__efivars->lock, flags)) return -EBUSY; - status = check_var_size(attributes, size + ucs2_strsize(name, 1024)); + status = check_var_size_nonblocking(attributes, + size + ucs2_strsize(name, 1024)); if (status != EFI_SUCCESS) { spin_unlock_irqrestore(&__efivars->lock, flags); return -ENOSPC; diff --git a/include/linux/efi.h b/include/linux/efi.h index ad1e177ba48e..09f1559e7525 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -525,7 +525,9 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, unsigned long count, u64 *max_size, int *reset_type); -typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long size); +typedef efi_status_t efi_query_variable_store_t(u32 attributes, + unsigned long size, + bool nonblocking); void efi_native_runtime_setup(void); @@ -881,13 +883,17 @@ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if pos #ifdef CONFIG_X86 extern void efi_late_init(void); extern void efi_free_boot_services(void); -extern efi_status_t efi_query_variable_store(u32 attributes, unsigned long size); +extern efi_status_t efi_query_variable_store(u32 attributes, + unsigned long size, + bool nonblocking); extern void efi_find_mirror(void); #else static inline void efi_late_init(void) {} static inline void efi_free_boot_services(void) {} -static inline efi_status_t efi_query_variable_store(u32 attributes, unsigned long size) +static inline efi_status_t efi_query_variable_store(u32 attributes, + unsigned long size, + bool nonblocking) { return EFI_SUCCESS; } -- cgit v1.2.3 From 774846defceb16dcab2f0215cfc467f7c93f1c26 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 1 Feb 2016 22:06:59 +0000 Subject: efi/runtime-wrappers: Remove out of date comment regarding in_nmi() This code is long gone, so remove the comment as well. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1454364428-494-6-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/runtime-wrappers.c | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index e9f2867f0d91..311f415bff51 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c @@ -61,32 +61,6 @@ */ static DEFINE_SPINLOCK(efi_runtime_lock); -/* - * Some runtime services calls can be reentrant under NMI, even if the table - * above says they are not. (source: UEFI Specification v2.4A) - * - * Table 32. Functions that may be called after Machine Check, INIT and NMI - * +----------------------------+------------------------------------------+ - * | Function | Called after Machine Check, INIT and NMI | - * +----------------------------+------------------------------------------+ - * | GetTime() | Yes, even if previously busy. | - * | GetVariable() | Yes, even if previously busy | - * | GetNextVariableName() | Yes, even if previously busy | - * | QueryVariableInfo() | Yes, even if previously busy | - * | SetVariable() | Yes, even if previously busy | - * | UpdateCapsule() | Yes, even if previously busy | - * | QueryCapsuleCapabilities() | Yes, even if previously busy | - * | ResetSystem() | Yes, even if previously busy | - * +----------------------------+------------------------------------------+ - * - * In order to prevent deadlocks under NMI, the wrappers for these functions - * may only grab the efi_runtime_lock or rtc_lock spinlocks if !efi_in_nmi(). - * However, not all of the services listed are reachable through NMI code paths, - * so the the special handling as suggested by the UEFI spec is only implemented - * for QueryVariableInfo() and SetVariable(), as these can be reached in NMI - * context through efi_pstore_write(). - */ - /* * As per commit ef68c8f87ed1 ("x86: Serialize EFI time accesses on rtc_lock"), * the EFI specification requires that callers of the time related runtime -- cgit v1.2.3 From 1bb6936473c07b5a7c8daced1000893b7145bb14 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 1 Feb 2016 22:07:00 +0000 Subject: efi: Runtime-wrapper: Get rid of the rtc_lock spinlock The rtc_lock spinlock aims to serialize access to the CMOS RTC between the UEFI firmware and the kernel drivers that use it directly. However, x86 is the only arch that performs such direct accesses, and that never uses the time related UEFI runtime services. Since no other UEFI enlightened architectures have a legcay CMOS RTC anyway, we can remove the rtc_lock spinlock entirely. Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1454364428-494-7-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/runtime-wrappers.c | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index 311f415bff51..7b8b2f2702ca 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c @@ -61,24 +61,14 @@ */ static DEFINE_SPINLOCK(efi_runtime_lock); -/* - * As per commit ef68c8f87ed1 ("x86: Serialize EFI time accesses on rtc_lock"), - * the EFI specification requires that callers of the time related runtime - * functions serialize with other CMOS accesses in the kernel, as the EFI time - * functions may choose to also use the legacy CMOS RTC. - */ -__weak DEFINE_SPINLOCK(rtc_lock); - static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) { unsigned long flags; efi_status_t status; - spin_lock_irqsave(&rtc_lock, flags); - spin_lock(&efi_runtime_lock); + spin_lock_irqsave(&efi_runtime_lock, flags); status = efi_call_virt(get_time, tm, tc); - spin_unlock(&efi_runtime_lock); - spin_unlock_irqrestore(&rtc_lock, flags); + spin_unlock_irqrestore(&efi_runtime_lock, flags); return status; } @@ -87,11 +77,9 @@ static efi_status_t virt_efi_set_time(efi_time_t *tm) unsigned long flags; efi_status_t status; - spin_lock_irqsave(&rtc_lock, flags); - spin_lock(&efi_runtime_lock); + spin_lock_irqsave(&efi_runtime_lock, flags); status = efi_call_virt(set_time, tm); - spin_unlock(&efi_runtime_lock); - spin_unlock_irqrestore(&rtc_lock, flags); + spin_unlock_irqrestore(&efi_runtime_lock, flags); return status; } @@ -102,11 +90,9 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled, unsigned long flags; efi_status_t status; - spin_lock_irqsave(&rtc_lock, flags); - spin_lock(&efi_runtime_lock); + spin_lock_irqsave(&efi_runtime_lock, flags); status = efi_call_virt(get_wakeup_time, enabled, pending, tm); - spin_unlock(&efi_runtime_lock); - spin_unlock_irqrestore(&rtc_lock, flags); + spin_unlock_irqrestore(&efi_runtime_lock, flags); return status; } @@ -115,11 +101,9 @@ static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) unsigned long flags; efi_status_t status; - spin_lock_irqsave(&rtc_lock, flags); - spin_lock(&efi_runtime_lock); + spin_lock_irqsave(&efi_runtime_lock, flags); status = efi_call_virt(set_wakeup_time, enabled, tm); - spin_unlock(&efi_runtime_lock); - spin_unlock_irqrestore(&rtc_lock, flags); + spin_unlock_irqrestore(&efi_runtime_lock, flags); return status; } -- cgit v1.2.3 From 9c09a342eb27902955ca939bd6ba29d875bd8b6b Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Mon, 1 Feb 2016 22:07:02 +0000 Subject: efivars: Use to_efivar_entry Use to_efivar_entry() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Matt Fleming Link: http://lkml.kernel.org/r/1454364428-494-9-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/efivars.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c index 756eca8c4cf8..c5b0d2bc1111 100644 --- a/drivers/firmware/efi/efivars.c +++ b/drivers/firmware/efi/efivars.c @@ -386,7 +386,7 @@ static const struct sysfs_ops efivar_attr_ops = { static void efivar_release(struct kobject *kobj) { - struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj); + struct efivar_entry *var = to_efivar_entry(kobj); kfree(var); } -- cgit v1.2.3 From c016ca08f89c6c78ed815f025262bdb87aba3f4c Mon Sep 17 00:00:00 2001 From: Robert Elliott Date: Mon, 1 Feb 2016 22:07:06 +0000 Subject: efi: Add NV memory attribute Add the NV memory attribute introduced in UEFI 2.5 and add a column for it in the types and attributes string used when printing the UEFI memory map. old: efi: mem61: [type=14 | | | | | | | |WB|WT|WC|UC] range=[0x0000000880000000-0x0000000c7fffffff) (16384MB) new: efi: mem61: [type=14 | | |NV| | | | | |WB|WT|WC|UC] range=[0x0000000880000000-0x0000000c7fffffff) (16384MB) Signed-off-by: Robert Elliott Signed-off-by: Matt Fleming Reviewed-by: Laszlo Ersek Cc: Andy Lutomirski Cc: Ard Biesheuvel Cc: Borislav Petkov Cc: Brian Gerst Cc: Dan Williams Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Ross Zwisler Cc: Taku Izumi Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1454364428-494-13-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/efi.c | 5 ++++- include/linux/efi.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 20451c290233..f4370485c26a 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -582,13 +582,16 @@ char * __init efi_md_typeattr_format(char *buf, size_t size, if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO | EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP | + EFI_MEMORY_NV | EFI_MEMORY_RUNTIME | EFI_MEMORY_MORE_RELIABLE)) snprintf(pos, size, "|attr=0x%016llx]", (unsigned long long)attr); else - snprintf(pos, size, "|%3s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]", + snprintf(pos, size, + "|%3s|%2s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]", attr & EFI_MEMORY_RUNTIME ? "RUN" : "", attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "", + attr & EFI_MEMORY_NV ? "NV" : "", attr & EFI_MEMORY_XP ? "XP" : "", attr & EFI_MEMORY_RP ? "RP" : "", attr & EFI_MEMORY_WP ? "WP" : "", diff --git a/include/linux/efi.h b/include/linux/efi.h index 09f1559e7525..3c6cbbdae4aa 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -97,6 +97,7 @@ typedef struct { #define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */ #define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */ #define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */ +#define EFI_MEMORY_NV ((u64)0x0000000000008000ULL) /* non-volatile */ #define EFI_MEMORY_MORE_RELIABLE \ ((u64)0x0000000000010000ULL) /* higher reliability */ #define EFI_MEMORY_RO ((u64)0x0000000000020000ULL) /* read-only */ -- cgit v1.2.3 From 35575e0e8ba633fc8276509a21f89b599b4f9006 Mon Sep 17 00:00:00 2001 From: Robert Elliott Date: Mon, 1 Feb 2016 22:07:07 +0000 Subject: efi: Add Persistent Memory type name Add the "Persistent Memory" string for type 14 introduced in UEFI 2.5. This is used when printing the UEFI memory map. old: efi: mem61: [type=14 | | | | | | | |WB|WT|WC|UC] range=[0x0000000880000000-0x0000000c7fffffff) (16384MB) new: efi: mem61: [Persistent Memory | | | | | | | |WB|WT|WC|UC] range=[0x0000000880000000-0x0000000c7fffffff) (16384MB) Signed-off-by: Robert Elliott Signed-off-by: Matt Fleming Reviewed-by: Laszlo Ersek Cc: Andy Lutomirski Cc: Ard Biesheuvel Cc: Borislav Petkov Cc: Brian Gerst Cc: Dan Williams Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Ross Zwisler Cc: Taku Izumi Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1454364428-494-14-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/efi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index f4370485c26a..3a69ed5ecfcb 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -555,7 +555,8 @@ static __initdata char memory_type_name[][20] = { "ACPI Memory NVS", "Memory Mapped I/O", "MMIO Port Space", - "PAL Code" + "PAL Code", + "Persistent Memory", }; char * __init efi_md_typeattr_format(char *buf, size_t size, -- cgit v1.2.3 From b2435692dbb709d4c8ff3b2f2815c9b8423b72bb Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 2 Feb 2016 22:06:51 -0800 Subject: drm/i915: Pretend cursor is always on for ILK-style WM calculations (v2) Due to our lack of two-step watermark programming, our driver has historically pretended that the cursor plane is always on for the purpose of watermark calculations; this helps avoid serious flickering when the cursor turns off/on (e.g., when the user moves the mouse pointer to a different screen). That workaround was accidentally dropped as we started working toward atomic watermark updates. Since we still aren't quite there yet with two-stage updates, we need to resurrect the workaround and treat the cursor as always active. v2: Tweak cursor width calculations slightly to more closely match the logic we used before the atomic overhaul began. (Ville) Cc: simdev11@outlook.com Cc: manfred.kitzbichler@gmail.com Cc: drm-intel-fixes@lists.freedesktop.org Reported-by: simdev11@outlook.com Reported-by: manfred.kitzbichler@gmail.com Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93892 Fixes: 43d59eda1 ("drm/i915: Eliminate usage of plane_wm_parameters from ILK-style WM code (v2)") Signed-off-by: Matt Roper Link: http://patchwork.freedesktop.org/patch/msgid/1454479611-6804-1-git-send-email-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a47b8f219357..3da7935c1665 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1799,16 +1799,20 @@ static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate, const struct intel_plane_state *pstate, uint32_t mem_value) { - int cpp = pstate->base.fb ? - drm_format_plane_cpp(pstate->base.fb->pixel_format, 0) : 0; + /* + * We treat the cursor plane as always-on for the purposes of watermark + * calculation. Until we have two-stage watermark programming merged, + * this is necessary to avoid flickering. + */ + int cpp = 4; + int width = pstate->visible ? pstate->base.crtc_w : 64; - if (!cstate->base.active || !pstate->visible) + if (!cstate->base.active) return 0; return ilk_wm_method2(ilk_pipe_pixel_rate(cstate), cstate->base.adjusted_mode.crtc_htotal, - drm_rect_width(&pstate->dst), - cpp, mem_value); + width, cpp, mem_value); } /* Only for WM_LP. */ -- cgit v1.2.3 From f5e741b7c7dddefa318b7f91af134f8ae2a342c1 Mon Sep 17 00:00:00 2001 From: Doug Ledford Date: Wed, 3 Feb 2016 11:06:23 -0500 Subject: staging/rdma: remove deprecated amso1100 driver Driver was placed in staging for eventual removal, it is time to complete that task. Signed-off-by: Doug Ledford --- MAINTAINERS | 7 - drivers/staging/rdma/Kconfig | 2 - drivers/staging/rdma/Makefile | 1 - drivers/staging/rdma/amso1100/Kbuild | 6 - drivers/staging/rdma/amso1100/Kconfig | 15 - drivers/staging/rdma/amso1100/TODO | 4 - drivers/staging/rdma/amso1100/c2.c | 1240 ---------------------- drivers/staging/rdma/amso1100/c2.h | 547 ---------- drivers/staging/rdma/amso1100/c2_ae.c | 327 ------ drivers/staging/rdma/amso1100/c2_ae.h | 108 -- drivers/staging/rdma/amso1100/c2_alloc.c | 142 --- drivers/staging/rdma/amso1100/c2_cm.c | 458 -------- drivers/staging/rdma/amso1100/c2_cq.c | 437 -------- drivers/staging/rdma/amso1100/c2_intr.c | 219 ---- drivers/staging/rdma/amso1100/c2_mm.c | 377 ------- drivers/staging/rdma/amso1100/c2_mq.c | 175 --- drivers/staging/rdma/amso1100/c2_mq.h | 106 -- drivers/staging/rdma/amso1100/c2_pd.c | 90 -- drivers/staging/rdma/amso1100/c2_provider.c | 862 --------------- drivers/staging/rdma/amso1100/c2_provider.h | 182 ---- drivers/staging/rdma/amso1100/c2_qp.c | 1024 ------------------ drivers/staging/rdma/amso1100/c2_rnic.c | 652 ------------ drivers/staging/rdma/amso1100/c2_status.h | 158 --- drivers/staging/rdma/amso1100/c2_user.h | 82 -- drivers/staging/rdma/amso1100/c2_vq.c | 260 ----- drivers/staging/rdma/amso1100/c2_vq.h | 63 -- drivers/staging/rdma/amso1100/c2_wr.h | 1520 --------------------------- 27 files changed, 9064 deletions(-) delete mode 100644 drivers/staging/rdma/amso1100/Kbuild delete mode 100644 drivers/staging/rdma/amso1100/Kconfig delete mode 100644 drivers/staging/rdma/amso1100/TODO delete mode 100644 drivers/staging/rdma/amso1100/c2.c delete mode 100644 drivers/staging/rdma/amso1100/c2.h delete mode 100644 drivers/staging/rdma/amso1100/c2_ae.c delete mode 100644 drivers/staging/rdma/amso1100/c2_ae.h delete mode 100644 drivers/staging/rdma/amso1100/c2_alloc.c delete mode 100644 drivers/staging/rdma/amso1100/c2_cm.c delete mode 100644 drivers/staging/rdma/amso1100/c2_cq.c delete mode 100644 drivers/staging/rdma/amso1100/c2_intr.c delete mode 100644 drivers/staging/rdma/amso1100/c2_mm.c delete mode 100644 drivers/staging/rdma/amso1100/c2_mq.c delete mode 100644 drivers/staging/rdma/amso1100/c2_mq.h delete mode 100644 drivers/staging/rdma/amso1100/c2_pd.c delete mode 100644 drivers/staging/rdma/amso1100/c2_provider.c delete mode 100644 drivers/staging/rdma/amso1100/c2_provider.h delete mode 100644 drivers/staging/rdma/amso1100/c2_qp.c delete mode 100644 drivers/staging/rdma/amso1100/c2_rnic.c delete mode 100644 drivers/staging/rdma/amso1100/c2_status.h delete mode 100644 drivers/staging/rdma/amso1100/c2_user.h delete mode 100644 drivers/staging/rdma/amso1100/c2_vq.c delete mode 100644 drivers/staging/rdma/amso1100/c2_vq.h delete mode 100644 drivers/staging/rdma/amso1100/c2_wr.h (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 30aca4aa5467..e76048d11e45 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -686,13 +686,6 @@ M: Michael Hanselmann S: Supported F: drivers/macintosh/ams/ -AMSO1100 RNIC DRIVER -M: Tom Tucker -M: Steve Wise -L: linux-rdma@vger.kernel.org -S: Maintained -F: drivers/infiniband/hw/amso1100/ - ANALOG DEVICES INC AD9389B DRIVER M: Hans Verkuil L: linux-media@vger.kernel.org diff --git a/drivers/staging/rdma/Kconfig b/drivers/staging/rdma/Kconfig index ba8765063174..1624bc43e304 100644 --- a/drivers/staging/rdma/Kconfig +++ b/drivers/staging/rdma/Kconfig @@ -22,8 +22,6 @@ menuconfig STAGING_RDMA # Please keep entries in alphabetic order if STAGING_RDMA -source "drivers/staging/rdma/amso1100/Kconfig" - source "drivers/staging/rdma/ehca/Kconfig" source "drivers/staging/rdma/hfi1/Kconfig" diff --git a/drivers/staging/rdma/Makefile b/drivers/staging/rdma/Makefile index 139d78ef2c24..2217d6778669 100644 --- a/drivers/staging/rdma/Makefile +++ b/drivers/staging/rdma/Makefile @@ -1,5 +1,4 @@ # Entries for RDMA_STAGING tree -obj-$(CONFIG_INFINIBAND_AMSO1100) += amso1100/ obj-$(CONFIG_INFINIBAND_EHCA) += ehca/ obj-$(CONFIG_INFINIBAND_HFI1) += hfi1/ obj-$(CONFIG_INFINIBAND_IPATH) += ipath/ diff --git a/drivers/staging/rdma/amso1100/Kbuild b/drivers/staging/rdma/amso1100/Kbuild deleted file mode 100644 index 950dfabcd89d..000000000000 --- a/drivers/staging/rdma/amso1100/Kbuild +++ /dev/null @@ -1,6 +0,0 @@ -ccflags-$(CONFIG_INFINIBAND_AMSO1100_DEBUG) := -DDEBUG - -obj-$(CONFIG_INFINIBAND_AMSO1100) += iw_c2.o - -iw_c2-y := c2.o c2_provider.o c2_rnic.o c2_alloc.o c2_mq.o c2_ae.o c2_vq.o \ - c2_intr.o c2_cq.o c2_qp.o c2_cm.o c2_mm.o c2_pd.o diff --git a/drivers/staging/rdma/amso1100/Kconfig b/drivers/staging/rdma/amso1100/Kconfig deleted file mode 100644 index e6ce5f209e47..000000000000 --- a/drivers/staging/rdma/amso1100/Kconfig +++ /dev/null @@ -1,15 +0,0 @@ -config INFINIBAND_AMSO1100 - tristate "Ammasso 1100 HCA support" - depends on PCI && INET - ---help--- - This is a low-level driver for the Ammasso 1100 host - channel adapter (HCA). - -config INFINIBAND_AMSO1100_DEBUG - bool "Verbose debugging output" - depends on INFINIBAND_AMSO1100 - default n - ---help--- - This option causes the amso1100 driver to produce a bunch of - debug messages. Select this if you are developing the driver - or trying to diagnose a problem. diff --git a/drivers/staging/rdma/amso1100/TODO b/drivers/staging/rdma/amso1100/TODO deleted file mode 100644 index 18b00a5cb549..000000000000 --- a/drivers/staging/rdma/amso1100/TODO +++ /dev/null @@ -1,4 +0,0 @@ -7/2015 - -The amso1100 driver has been deprecated and moved to drivers/staging. -It will be removed in the 4.6 merge window. diff --git a/drivers/staging/rdma/amso1100/c2.c b/drivers/staging/rdma/amso1100/c2.c deleted file mode 100644 index b46ebd1ae15a..000000000000 --- a/drivers/staging/rdma/amso1100/c2.c +++ /dev/null @@ -1,1240 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include "c2.h" -#include "c2_provider.h" - -MODULE_AUTHOR("Tom Tucker "); -MODULE_DESCRIPTION("Ammasso AMSO1100 Low-level iWARP Driver"); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_VERSION(DRV_VERSION); - -static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK - | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN; - -static int debug = -1; /* defaults above */ -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); - -static int c2_up(struct net_device *netdev); -static int c2_down(struct net_device *netdev); -static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev); -static void c2_tx_interrupt(struct net_device *netdev); -static void c2_rx_interrupt(struct net_device *netdev); -static irqreturn_t c2_interrupt(int irq, void *dev_id); -static void c2_tx_timeout(struct net_device *netdev); -static int c2_change_mtu(struct net_device *netdev, int new_mtu); -static void c2_reset(struct c2_port *c2_port); - -static struct pci_device_id c2_pci_table[] = { - { PCI_DEVICE(0x18b8, 0xb001) }, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, c2_pci_table); - -static void c2_set_rxbufsize(struct c2_port *c2_port) -{ - struct net_device *netdev = c2_port->netdev; - - if (netdev->mtu > RX_BUF_SIZE) - c2_port->rx_buf_size = - netdev->mtu + ETH_HLEN + sizeof(struct c2_rxp_hdr) + - NET_IP_ALIGN; - else - c2_port->rx_buf_size = sizeof(struct c2_rxp_hdr) + RX_BUF_SIZE; -} - -/* - * Allocate TX ring elements and chain them together. - * One-to-one association of adapter descriptors with ring elements. - */ -static int c2_tx_ring_alloc(struct c2_ring *tx_ring, void *vaddr, - dma_addr_t base, void __iomem * mmio_txp_ring) -{ - struct c2_tx_desc *tx_desc; - struct c2_txp_desc __iomem *txp_desc; - struct c2_element *elem; - int i; - - tx_ring->start = kmalloc_array(tx_ring->count, sizeof(*elem), - GFP_KERNEL); - if (!tx_ring->start) - return -ENOMEM; - - elem = tx_ring->start; - tx_desc = vaddr; - txp_desc = mmio_txp_ring; - for (i = 0; i < tx_ring->count; i++, elem++, tx_desc++, txp_desc++) { - tx_desc->len = 0; - tx_desc->status = 0; - - /* Set TXP_HTXD_UNINIT */ - __raw_writeq((__force u64) cpu_to_be64(0x1122334455667788ULL), - (void __iomem *) txp_desc + C2_TXP_ADDR); - __raw_writew(0, (void __iomem *) txp_desc + C2_TXP_LEN); - __raw_writew((__force u16) cpu_to_be16(TXP_HTXD_UNINIT), - (void __iomem *) txp_desc + C2_TXP_FLAGS); - - elem->skb = NULL; - elem->ht_desc = tx_desc; - elem->hw_desc = txp_desc; - - if (i == tx_ring->count - 1) { - elem->next = tx_ring->start; - tx_desc->next_offset = base; - } else { - elem->next = elem + 1; - tx_desc->next_offset = - base + (i + 1) * sizeof(*tx_desc); - } - } - - tx_ring->to_use = tx_ring->to_clean = tx_ring->start; - - return 0; -} - -/* - * Allocate RX ring elements and chain them together. - * One-to-one association of adapter descriptors with ring elements. - */ -static int c2_rx_ring_alloc(struct c2_ring *rx_ring, void *vaddr, - dma_addr_t base, void __iomem * mmio_rxp_ring) -{ - struct c2_rx_desc *rx_desc; - struct c2_rxp_desc __iomem *rxp_desc; - struct c2_element *elem; - int i; - - rx_ring->start = kmalloc_array(rx_ring->count, sizeof(*elem), - GFP_KERNEL); - if (!rx_ring->start) - return -ENOMEM; - - elem = rx_ring->start; - rx_desc = vaddr; - rxp_desc = mmio_rxp_ring; - for (i = 0; i < rx_ring->count; i++, elem++, rx_desc++, rxp_desc++) { - rx_desc->len = 0; - rx_desc->status = 0; - - /* Set RXP_HRXD_UNINIT */ - __raw_writew((__force u16) cpu_to_be16(RXP_HRXD_OK), - (void __iomem *) rxp_desc + C2_RXP_STATUS); - __raw_writew(0, (void __iomem *) rxp_desc + C2_RXP_COUNT); - __raw_writew(0, (void __iomem *) rxp_desc + C2_RXP_LEN); - __raw_writeq((__force u64) cpu_to_be64(0x99aabbccddeeffULL), - (void __iomem *) rxp_desc + C2_RXP_ADDR); - __raw_writew((__force u16) cpu_to_be16(RXP_HRXD_UNINIT), - (void __iomem *) rxp_desc + C2_RXP_FLAGS); - - elem->skb = NULL; - elem->ht_desc = rx_desc; - elem->hw_desc = rxp_desc; - - if (i == rx_ring->count - 1) { - elem->next = rx_ring->start; - rx_desc->next_offset = base; - } else { - elem->next = elem + 1; - rx_desc->next_offset = - base + (i + 1) * sizeof(*rx_desc); - } - } - - rx_ring->to_use = rx_ring->to_clean = rx_ring->start; - - return 0; -} - -/* Setup buffer for receiving */ -static inline int c2_rx_alloc(struct c2_port *c2_port, struct c2_element *elem) -{ - struct c2_dev *c2dev = c2_port->c2dev; - struct c2_rx_desc *rx_desc = elem->ht_desc; - struct sk_buff *skb; - dma_addr_t mapaddr; - u32 maplen; - struct c2_rxp_hdr *rxp_hdr; - - skb = dev_alloc_skb(c2_port->rx_buf_size); - if (unlikely(!skb)) { - pr_debug("%s: out of memory for receive\n", - c2_port->netdev->name); - return -ENOMEM; - } - - /* Zero out the rxp hdr in the sk_buff */ - memset(skb->data, 0, sizeof(*rxp_hdr)); - - skb->dev = c2_port->netdev; - - maplen = c2_port->rx_buf_size; - mapaddr = - pci_map_single(c2dev->pcidev, skb->data, maplen, - PCI_DMA_FROMDEVICE); - - /* Set the sk_buff RXP_header to RXP_HRXD_READY */ - rxp_hdr = (struct c2_rxp_hdr *) skb->data; - rxp_hdr->flags = RXP_HRXD_READY; - - __raw_writew(0, elem->hw_desc + C2_RXP_STATUS); - __raw_writew((__force u16) cpu_to_be16((u16) maplen - sizeof(*rxp_hdr)), - elem->hw_desc + C2_RXP_LEN); - __raw_writeq((__force u64) cpu_to_be64(mapaddr), elem->hw_desc + C2_RXP_ADDR); - __raw_writew((__force u16) cpu_to_be16(RXP_HRXD_READY), - elem->hw_desc + C2_RXP_FLAGS); - - elem->skb = skb; - elem->mapaddr = mapaddr; - elem->maplen = maplen; - rx_desc->len = maplen; - - return 0; -} - -/* - * Allocate buffers for the Rx ring - * For receive: rx_ring.to_clean is next received frame - */ -static int c2_rx_fill(struct c2_port *c2_port) -{ - struct c2_ring *rx_ring = &c2_port->rx_ring; - struct c2_element *elem; - int ret = 0; - - elem = rx_ring->start; - do { - if (c2_rx_alloc(c2_port, elem)) { - ret = 1; - break; - } - } while ((elem = elem->next) != rx_ring->start); - - rx_ring->to_clean = rx_ring->start; - return ret; -} - -/* Free all buffers in RX ring, assumes receiver stopped */ -static void c2_rx_clean(struct c2_port *c2_port) -{ - struct c2_dev *c2dev = c2_port->c2dev; - struct c2_ring *rx_ring = &c2_port->rx_ring; - struct c2_element *elem; - struct c2_rx_desc *rx_desc; - - elem = rx_ring->start; - do { - rx_desc = elem->ht_desc; - rx_desc->len = 0; - - __raw_writew(0, elem->hw_desc + C2_RXP_STATUS); - __raw_writew(0, elem->hw_desc + C2_RXP_COUNT); - __raw_writew(0, elem->hw_desc + C2_RXP_LEN); - __raw_writeq((__force u64) cpu_to_be64(0x99aabbccddeeffULL), - elem->hw_desc + C2_RXP_ADDR); - __raw_writew((__force u16) cpu_to_be16(RXP_HRXD_UNINIT), - elem->hw_desc + C2_RXP_FLAGS); - - if (elem->skb) { - pci_unmap_single(c2dev->pcidev, elem->mapaddr, - elem->maplen, PCI_DMA_FROMDEVICE); - dev_kfree_skb(elem->skb); - elem->skb = NULL; - } - } while ((elem = elem->next) != rx_ring->start); -} - -static inline int c2_tx_free(struct c2_dev *c2dev, struct c2_element *elem) -{ - struct c2_tx_desc *tx_desc = elem->ht_desc; - - tx_desc->len = 0; - - pci_unmap_single(c2dev->pcidev, elem->mapaddr, elem->maplen, - PCI_DMA_TODEVICE); - - if (elem->skb) { - dev_kfree_skb_any(elem->skb); - elem->skb = NULL; - } - - return 0; -} - -/* Free all buffers in TX ring, assumes transmitter stopped */ -static void c2_tx_clean(struct c2_port *c2_port) -{ - struct c2_ring *tx_ring = &c2_port->tx_ring; - struct c2_element *elem; - struct c2_txp_desc txp_htxd; - int retry; - unsigned long flags; - - spin_lock_irqsave(&c2_port->tx_lock, flags); - - elem = tx_ring->start; - - do { - retry = 0; - do { - txp_htxd.flags = - readw(elem->hw_desc + C2_TXP_FLAGS); - - if (txp_htxd.flags == TXP_HTXD_READY) { - retry = 1; - __raw_writew(0, - elem->hw_desc + C2_TXP_LEN); - __raw_writeq(0, - elem->hw_desc + C2_TXP_ADDR); - __raw_writew((__force u16) cpu_to_be16(TXP_HTXD_DONE), - elem->hw_desc + C2_TXP_FLAGS); - c2_port->netdev->stats.tx_dropped++; - break; - } else { - __raw_writew(0, - elem->hw_desc + C2_TXP_LEN); - __raw_writeq((__force u64) cpu_to_be64(0x1122334455667788ULL), - elem->hw_desc + C2_TXP_ADDR); - __raw_writew((__force u16) cpu_to_be16(TXP_HTXD_UNINIT), - elem->hw_desc + C2_TXP_FLAGS); - } - - c2_tx_free(c2_port->c2dev, elem); - - } while ((elem = elem->next) != tx_ring->start); - } while (retry); - - c2_port->tx_avail = c2_port->tx_ring.count - 1; - c2_port->c2dev->cur_tx = tx_ring->to_use - tx_ring->start; - - if (c2_port->tx_avail > MAX_SKB_FRAGS + 1) - netif_wake_queue(c2_port->netdev); - - spin_unlock_irqrestore(&c2_port->tx_lock, flags); -} - -/* - * Process transmit descriptors marked 'DONE' by the firmware, - * freeing up their unneeded sk_buffs. - */ -static void c2_tx_interrupt(struct net_device *netdev) -{ - struct c2_port *c2_port = netdev_priv(netdev); - struct c2_dev *c2dev = c2_port->c2dev; - struct c2_ring *tx_ring = &c2_port->tx_ring; - struct c2_element *elem; - struct c2_txp_desc txp_htxd; - - spin_lock(&c2_port->tx_lock); - - for (elem = tx_ring->to_clean; elem != tx_ring->to_use; - elem = elem->next) { - txp_htxd.flags = - be16_to_cpu((__force __be16) readw(elem->hw_desc + C2_TXP_FLAGS)); - - if (txp_htxd.flags != TXP_HTXD_DONE) - break; - - if (netif_msg_tx_done(c2_port)) { - /* PCI reads are expensive in fast path */ - txp_htxd.len = - be16_to_cpu((__force __be16) readw(elem->hw_desc + C2_TXP_LEN)); - pr_debug("%s: tx done slot %3Zu status 0x%x len " - "%5u bytes\n", - netdev->name, elem - tx_ring->start, - txp_htxd.flags, txp_htxd.len); - } - - c2_tx_free(c2dev, elem); - ++(c2_port->tx_avail); - } - - tx_ring->to_clean = elem; - - if (netif_queue_stopped(netdev) - && c2_port->tx_avail > MAX_SKB_FRAGS + 1) - netif_wake_queue(netdev); - - spin_unlock(&c2_port->tx_lock); -} - -static void c2_rx_error(struct c2_port *c2_port, struct c2_element *elem) -{ - struct c2_rx_desc *rx_desc = elem->ht_desc; - struct c2_rxp_hdr *rxp_hdr = (struct c2_rxp_hdr *) elem->skb->data; - - if (rxp_hdr->status != RXP_HRXD_OK || - rxp_hdr->len > (rx_desc->len - sizeof(*rxp_hdr))) { - pr_debug("BAD RXP_HRXD\n"); - pr_debug(" rx_desc : %p\n", rx_desc); - pr_debug(" index : %Zu\n", - elem - c2_port->rx_ring.start); - pr_debug(" len : %u\n", rx_desc->len); - pr_debug(" rxp_hdr : %p [PA %p]\n", rxp_hdr, - (void *) __pa((unsigned long) rxp_hdr)); - pr_debug(" flags : 0x%x\n", rxp_hdr->flags); - pr_debug(" status: 0x%x\n", rxp_hdr->status); - pr_debug(" len : %u\n", rxp_hdr->len); - pr_debug(" rsvd : 0x%x\n", rxp_hdr->rsvd); - } - - /* Setup the skb for reuse since we're dropping this pkt */ - elem->skb->data = elem->skb->head; - skb_reset_tail_pointer(elem->skb); - - /* Zero out the rxp hdr in the sk_buff */ - memset(elem->skb->data, 0, sizeof(*rxp_hdr)); - - /* Write the descriptor to the adapter's rx ring */ - __raw_writew(0, elem->hw_desc + C2_RXP_STATUS); - __raw_writew(0, elem->hw_desc + C2_RXP_COUNT); - __raw_writew((__force u16) cpu_to_be16((u16) elem->maplen - sizeof(*rxp_hdr)), - elem->hw_desc + C2_RXP_LEN); - __raw_writeq((__force u64) cpu_to_be64(elem->mapaddr), - elem->hw_desc + C2_RXP_ADDR); - __raw_writew((__force u16) cpu_to_be16(RXP_HRXD_READY), - elem->hw_desc + C2_RXP_FLAGS); - - pr_debug("packet dropped\n"); - c2_port->netdev->stats.rx_dropped++; -} - -static void c2_rx_interrupt(struct net_device *netdev) -{ - struct c2_port *c2_port = netdev_priv(netdev); - struct c2_dev *c2dev = c2_port->c2dev; - struct c2_ring *rx_ring = &c2_port->rx_ring; - struct c2_element *elem; - struct c2_rx_desc *rx_desc; - struct c2_rxp_hdr *rxp_hdr; - struct sk_buff *skb; - dma_addr_t mapaddr; - u32 maplen, buflen; - unsigned long flags; - - spin_lock_irqsave(&c2dev->lock, flags); - - /* Begin where we left off */ - rx_ring->to_clean = rx_ring->start + c2dev->cur_rx; - - for (elem = rx_ring->to_clean; elem->next != rx_ring->to_clean; - elem = elem->next) { - rx_desc = elem->ht_desc; - mapaddr = elem->mapaddr; - maplen = elem->maplen; - skb = elem->skb; - rxp_hdr = (struct c2_rxp_hdr *) skb->data; - - if (rxp_hdr->flags != RXP_HRXD_DONE) - break; - buflen = rxp_hdr->len; - - /* Sanity check the RXP header */ - if (rxp_hdr->status != RXP_HRXD_OK || - buflen > (rx_desc->len - sizeof(*rxp_hdr))) { - c2_rx_error(c2_port, elem); - continue; - } - - /* - * Allocate and map a new skb for replenishing the host - * RX desc - */ - if (c2_rx_alloc(c2_port, elem)) { - c2_rx_error(c2_port, elem); - continue; - } - - /* Unmap the old skb */ - pci_unmap_single(c2dev->pcidev, mapaddr, maplen, - PCI_DMA_FROMDEVICE); - - prefetch(skb->data); - - /* - * Skip past the leading 8 bytes comprising of the - * "struct c2_rxp_hdr", prepended by the adapter - * to the usual Ethernet header ("struct ethhdr"), - * to the start of the raw Ethernet packet. - * - * Fix up the various fields in the sk_buff before - * passing it up to netif_rx(). The transfer size - * (in bytes) specified by the adapter len field of - * the "struct rxp_hdr_t" does NOT include the - * "sizeof(struct c2_rxp_hdr)". - */ - skb->data += sizeof(*rxp_hdr); - skb_set_tail_pointer(skb, buflen); - skb->len = buflen; - skb->protocol = eth_type_trans(skb, netdev); - - netif_rx(skb); - - netdev->stats.rx_packets++; - netdev->stats.rx_bytes += buflen; - } - - /* Save where we left off */ - rx_ring->to_clean = elem; - c2dev->cur_rx = elem - rx_ring->start; - C2_SET_CUR_RX(c2dev, c2dev->cur_rx); - - spin_unlock_irqrestore(&c2dev->lock, flags); -} - -/* - * Handle netisr0 TX & RX interrupts. - */ -static irqreturn_t c2_interrupt(int irq, void *dev_id) -{ - unsigned int netisr0, dmaisr; - int handled = 0; - struct c2_dev *c2dev = dev_id; - - /* Process CCILNET interrupts */ - netisr0 = readl(c2dev->regs + C2_NISR0); - if (netisr0) { - - /* - * There is an issue with the firmware that always - * provides the status of RX for both TX & RX - * interrupts. So process both queues here. - */ - c2_rx_interrupt(c2dev->netdev); - c2_tx_interrupt(c2dev->netdev); - - /* Clear the interrupt */ - writel(netisr0, c2dev->regs + C2_NISR0); - handled++; - } - - /* Process RNIC interrupts */ - dmaisr = readl(c2dev->regs + C2_DISR); - if (dmaisr) { - writel(dmaisr, c2dev->regs + C2_DISR); - c2_rnic_interrupt(c2dev); - handled++; - } - - if (handled) { - return IRQ_HANDLED; - } else { - return IRQ_NONE; - } -} - -static int c2_up(struct net_device *netdev) -{ - struct c2_port *c2_port = netdev_priv(netdev); - struct c2_dev *c2dev = c2_port->c2dev; - struct c2_element *elem; - struct c2_rxp_hdr *rxp_hdr; - struct in_device *in_dev; - size_t rx_size, tx_size; - int ret, i; - unsigned int netimr0; - - if (netif_msg_ifup(c2_port)) - pr_debug("%s: enabling interface\n", netdev->name); - - /* Set the Rx buffer size based on MTU */ - c2_set_rxbufsize(c2_port); - - /* Allocate DMA'able memory for Tx/Rx host descriptor rings */ - rx_size = c2_port->rx_ring.count * sizeof(struct c2_rx_desc); - tx_size = c2_port->tx_ring.count * sizeof(struct c2_tx_desc); - - c2_port->mem_size = tx_size + rx_size; - c2_port->mem = pci_zalloc_consistent(c2dev->pcidev, c2_port->mem_size, - &c2_port->dma); - if (c2_port->mem == NULL) { - pr_debug("Unable to allocate memory for " - "host descriptor rings\n"); - return -ENOMEM; - } - - /* Create the Rx host descriptor ring */ - if ((ret = - c2_rx_ring_alloc(&c2_port->rx_ring, c2_port->mem, c2_port->dma, - c2dev->mmio_rxp_ring))) { - pr_debug("Unable to create RX ring\n"); - goto bail0; - } - - /* Allocate Rx buffers for the host descriptor ring */ - if (c2_rx_fill(c2_port)) { - pr_debug("Unable to fill RX ring\n"); - goto bail1; - } - - /* Create the Tx host descriptor ring */ - if ((ret = c2_tx_ring_alloc(&c2_port->tx_ring, c2_port->mem + rx_size, - c2_port->dma + rx_size, - c2dev->mmio_txp_ring))) { - pr_debug("Unable to create TX ring\n"); - goto bail1; - } - - /* Set the TX pointer to where we left off */ - c2_port->tx_avail = c2_port->tx_ring.count - 1; - c2_port->tx_ring.to_use = c2_port->tx_ring.to_clean = - c2_port->tx_ring.start + c2dev->cur_tx; - - /* missing: Initialize MAC */ - - BUG_ON(c2_port->tx_ring.to_use != c2_port->tx_ring.to_clean); - - /* Reset the adapter, ensures the driver is in sync with the RXP */ - c2_reset(c2_port); - - /* Reset the READY bit in the sk_buff RXP headers & adapter HRXDQ */ - for (i = 0, elem = c2_port->rx_ring.start; i < c2_port->rx_ring.count; - i++, elem++) { - rxp_hdr = (struct c2_rxp_hdr *) elem->skb->data; - rxp_hdr->flags = 0; - __raw_writew((__force u16) cpu_to_be16(RXP_HRXD_READY), - elem->hw_desc + C2_RXP_FLAGS); - } - - /* Enable network packets */ - netif_start_queue(netdev); - - /* Enable IRQ */ - writel(0, c2dev->regs + C2_IDIS); - netimr0 = readl(c2dev->regs + C2_NIMR0); - netimr0 &= ~(C2_PCI_HTX_INT | C2_PCI_HRX_INT); - writel(netimr0, c2dev->regs + C2_NIMR0); - - /* Tell the stack to ignore arp requests for ipaddrs bound to - * other interfaces. This is needed to prevent the host stack - * from responding to arp requests to the ipaddr bound on the - * rdma interface. - */ - in_dev = in_dev_get(netdev); - IN_DEV_CONF_SET(in_dev, ARP_IGNORE, 1); - in_dev_put(in_dev); - - return 0; - -bail1: - c2_rx_clean(c2_port); - kfree(c2_port->rx_ring.start); - -bail0: - pci_free_consistent(c2dev->pcidev, c2_port->mem_size, c2_port->mem, - c2_port->dma); - - return ret; -} - -static int c2_down(struct net_device *netdev) -{ - struct c2_port *c2_port = netdev_priv(netdev); - struct c2_dev *c2dev = c2_port->c2dev; - - if (netif_msg_ifdown(c2_port)) - pr_debug("%s: disabling interface\n", - netdev->name); - - /* Wait for all the queued packets to get sent */ - c2_tx_interrupt(netdev); - - /* Disable network packets */ - netif_stop_queue(netdev); - - /* Disable IRQs by clearing the interrupt mask */ - writel(1, c2dev->regs + C2_IDIS); - writel(0, c2dev->regs + C2_NIMR0); - - /* missing: Stop transmitter */ - - /* missing: Stop receiver */ - - /* Reset the adapter, ensures the driver is in sync with the RXP */ - c2_reset(c2_port); - - /* missing: Turn off LEDs here */ - - /* Free all buffers in the host descriptor rings */ - c2_tx_clean(c2_port); - c2_rx_clean(c2_port); - - /* Free the host descriptor rings */ - kfree(c2_port->rx_ring.start); - kfree(c2_port->tx_ring.start); - pci_free_consistent(c2dev->pcidev, c2_port->mem_size, c2_port->mem, - c2_port->dma); - - return 0; -} - -static void c2_reset(struct c2_port *c2_port) -{ - struct c2_dev *c2dev = c2_port->c2dev; - unsigned int cur_rx = c2dev->cur_rx; - - /* Tell the hardware to quiesce */ - C2_SET_CUR_RX(c2dev, cur_rx | C2_PCI_HRX_QUI); - - /* - * The hardware will reset the C2_PCI_HRX_QUI bit once - * the RXP is quiesced. Wait 2 seconds for this. - */ - ssleep(2); - - cur_rx = C2_GET_CUR_RX(c2dev); - - if (cur_rx & C2_PCI_HRX_QUI) - pr_debug("c2_reset: failed to quiesce the hardware!\n"); - - cur_rx &= ~C2_PCI_HRX_QUI; - - c2dev->cur_rx = cur_rx; - - pr_debug("Current RX: %u\n", c2dev->cur_rx); -} - -static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct c2_port *c2_port = netdev_priv(netdev); - struct c2_dev *c2dev = c2_port->c2dev; - struct c2_ring *tx_ring = &c2_port->tx_ring; - struct c2_element *elem; - dma_addr_t mapaddr; - u32 maplen; - unsigned long flags; - unsigned int i; - - spin_lock_irqsave(&c2_port->tx_lock, flags); - - if (unlikely(c2_port->tx_avail < (skb_shinfo(skb)->nr_frags + 1))) { - netif_stop_queue(netdev); - spin_unlock_irqrestore(&c2_port->tx_lock, flags); - - pr_debug("%s: Tx ring full when queue awake!\n", - netdev->name); - return NETDEV_TX_BUSY; - } - - maplen = skb_headlen(skb); - mapaddr = - pci_map_single(c2dev->pcidev, skb->data, maplen, PCI_DMA_TODEVICE); - - elem = tx_ring->to_use; - elem->skb = skb; - elem->mapaddr = mapaddr; - elem->maplen = maplen; - - /* Tell HW to xmit */ - __raw_writeq((__force u64) cpu_to_be64(mapaddr), - elem->hw_desc + C2_TXP_ADDR); - __raw_writew((__force u16) cpu_to_be16(maplen), - elem->hw_desc + C2_TXP_LEN); - __raw_writew((__force u16) cpu_to_be16(TXP_HTXD_READY), - elem->hw_desc + C2_TXP_FLAGS); - - netdev->stats.tx_packets++; - netdev->stats.tx_bytes += maplen; - - /* Loop thru additional data fragments and queue them */ - if (skb_shinfo(skb)->nr_frags) { - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - maplen = skb_frag_size(frag); - mapaddr = skb_frag_dma_map(&c2dev->pcidev->dev, frag, - 0, maplen, DMA_TO_DEVICE); - elem = elem->next; - elem->skb = NULL; - elem->mapaddr = mapaddr; - elem->maplen = maplen; - - /* Tell HW to xmit */ - __raw_writeq((__force u64) cpu_to_be64(mapaddr), - elem->hw_desc + C2_TXP_ADDR); - __raw_writew((__force u16) cpu_to_be16(maplen), - elem->hw_desc + C2_TXP_LEN); - __raw_writew((__force u16) cpu_to_be16(TXP_HTXD_READY), - elem->hw_desc + C2_TXP_FLAGS); - - netdev->stats.tx_packets++; - netdev->stats.tx_bytes += maplen; - } - } - - tx_ring->to_use = elem->next; - c2_port->tx_avail -= (skb_shinfo(skb)->nr_frags + 1); - - if (c2_port->tx_avail <= MAX_SKB_FRAGS + 1) { - netif_stop_queue(netdev); - if (netif_msg_tx_queued(c2_port)) - pr_debug("%s: transmit queue full\n", - netdev->name); - } - - spin_unlock_irqrestore(&c2_port->tx_lock, flags); - - netdev->trans_start = jiffies; - - return NETDEV_TX_OK; -} - -static void c2_tx_timeout(struct net_device *netdev) -{ - struct c2_port *c2_port = netdev_priv(netdev); - - if (netif_msg_timer(c2_port)) - pr_debug("%s: tx timeout\n", netdev->name); - - c2_tx_clean(c2_port); -} - -static int c2_change_mtu(struct net_device *netdev, int new_mtu) -{ - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) - return -EINVAL; - - netdev->mtu = new_mtu; - - if (netif_running(netdev)) { - c2_down(netdev); - - c2_up(netdev); - } - - return ret; -} - -static const struct net_device_ops c2_netdev = { - .ndo_open = c2_up, - .ndo_stop = c2_down, - .ndo_start_xmit = c2_xmit_frame, - .ndo_tx_timeout = c2_tx_timeout, - .ndo_change_mtu = c2_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -/* Initialize network device */ -static struct net_device *c2_devinit(struct c2_dev *c2dev, - void __iomem * mmio_addr) -{ - struct c2_port *c2_port = NULL; - struct net_device *netdev = alloc_etherdev(sizeof(*c2_port)); - - if (!netdev) { - pr_debug("c2_port etherdev alloc failed"); - return NULL; - } - - SET_NETDEV_DEV(netdev, &c2dev->pcidev->dev); - - netdev->netdev_ops = &c2_netdev; - netdev->watchdog_timeo = C2_TX_TIMEOUT; - netdev->irq = c2dev->pcidev->irq; - - c2_port = netdev_priv(netdev); - c2_port->netdev = netdev; - c2_port->c2dev = c2dev; - c2_port->msg_enable = netif_msg_init(debug, default_msg); - c2_port->tx_ring.count = C2_NUM_TX_DESC; - c2_port->rx_ring.count = C2_NUM_RX_DESC; - - spin_lock_init(&c2_port->tx_lock); - - /* Copy our 48-bit ethernet hardware address */ - memcpy_fromio(netdev->dev_addr, mmio_addr + C2_REGS_ENADDR, 6); - - /* Validate the MAC address */ - if (!is_valid_ether_addr(netdev->dev_addr)) { - pr_debug("Invalid MAC Address\n"); - pr_debug("%s: MAC %pM, IRQ %u\n", netdev->name, - netdev->dev_addr, netdev->irq); - free_netdev(netdev); - return NULL; - } - - c2dev->netdev = netdev; - - return netdev; -} - -static int c2_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) -{ - int ret = 0, i; - unsigned long reg0_start, reg0_flags, reg0_len; - unsigned long reg2_start, reg2_flags, reg2_len; - unsigned long reg4_start, reg4_flags, reg4_len; - unsigned kva_map_size; - struct net_device *netdev = NULL; - struct c2_dev *c2dev = NULL; - void __iomem *mmio_regs = NULL; - - printk(KERN_INFO PFX "AMSO1100 Gigabit Ethernet driver v%s loaded\n", - DRV_VERSION); - - /* Enable PCI device */ - ret = pci_enable_device(pcidev); - if (ret) { - printk(KERN_ERR PFX "%s: Unable to enable PCI device\n", - pci_name(pcidev)); - goto bail0; - } - - reg0_start = pci_resource_start(pcidev, BAR_0); - reg0_len = pci_resource_len(pcidev, BAR_0); - reg0_flags = pci_resource_flags(pcidev, BAR_0); - - reg2_start = pci_resource_start(pcidev, BAR_2); - reg2_len = pci_resource_len(pcidev, BAR_2); - reg2_flags = pci_resource_flags(pcidev, BAR_2); - - reg4_start = pci_resource_start(pcidev, BAR_4); - reg4_len = pci_resource_len(pcidev, BAR_4); - reg4_flags = pci_resource_flags(pcidev, BAR_4); - - pr_debug("BAR0 size = 0x%lX bytes\n", reg0_len); - pr_debug("BAR2 size = 0x%lX bytes\n", reg2_len); - pr_debug("BAR4 size = 0x%lX bytes\n", reg4_len); - - /* Make sure PCI base addr are MMIO */ - if (!(reg0_flags & IORESOURCE_MEM) || - !(reg2_flags & IORESOURCE_MEM) || !(reg4_flags & IORESOURCE_MEM)) { - printk(KERN_ERR PFX "PCI regions not an MMIO resource\n"); - ret = -ENODEV; - goto bail1; - } - - /* Check for weird/broken PCI region reporting */ - if ((reg0_len < C2_REG0_SIZE) || - (reg2_len < C2_REG2_SIZE) || (reg4_len < C2_REG4_SIZE)) { - printk(KERN_ERR PFX "Invalid PCI region sizes\n"); - ret = -ENODEV; - goto bail1; - } - - /* Reserve PCI I/O and memory resources */ - ret = pci_request_regions(pcidev, DRV_NAME); - if (ret) { - printk(KERN_ERR PFX "%s: Unable to request regions\n", - pci_name(pcidev)); - goto bail1; - } - - if ((sizeof(dma_addr_t) > 4)) { - ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(64)); - if (ret < 0) { - printk(KERN_ERR PFX "64b DMA configuration failed\n"); - goto bail2; - } - } else { - ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(32)); - if (ret < 0) { - printk(KERN_ERR PFX "32b DMA configuration failed\n"); - goto bail2; - } - } - - /* Enables bus-mastering on the device */ - pci_set_master(pcidev); - - /* Remap the adapter PCI registers in BAR4 */ - mmio_regs = ioremap_nocache(reg4_start + C2_PCI_REGS_OFFSET, - sizeof(struct c2_adapter_pci_regs)); - if (!mmio_regs) { - printk(KERN_ERR PFX - "Unable to remap adapter PCI registers in BAR4\n"); - ret = -EIO; - goto bail2; - } - - /* Validate PCI regs magic */ - for (i = 0; i < sizeof(c2_magic); i++) { - if (c2_magic[i] != readb(mmio_regs + C2_REGS_MAGIC + i)) { - printk(KERN_ERR PFX "Downlevel Firmware boot loader " - "[%d/%Zd: got 0x%x, exp 0x%x]. Use the cc_flash " - "utility to update your boot loader\n", - i + 1, sizeof(c2_magic), - readb(mmio_regs + C2_REGS_MAGIC + i), - c2_magic[i]); - printk(KERN_ERR PFX "Adapter not claimed\n"); - iounmap(mmio_regs); - ret = -EIO; - goto bail2; - } - } - - /* Validate the adapter version */ - if (be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_VERS)) != C2_VERSION) { - printk(KERN_ERR PFX "Version mismatch " - "[fw=%u, c2=%u], Adapter not claimed\n", - be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_VERS)), - C2_VERSION); - ret = -EINVAL; - iounmap(mmio_regs); - goto bail2; - } - - /* Validate the adapter IVN */ - if (be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_IVN)) != C2_IVN) { - printk(KERN_ERR PFX "Downlevel FIrmware level. You should be using " - "the OpenIB device support kit. " - "[fw=0x%x, c2=0x%x], Adapter not claimed\n", - be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_IVN)), - C2_IVN); - ret = -EINVAL; - iounmap(mmio_regs); - goto bail2; - } - - /* Allocate hardware structure */ - c2dev = (struct c2_dev *) ib_alloc_device(sizeof(*c2dev)); - if (!c2dev) { - printk(KERN_ERR PFX "%s: Unable to alloc hardware struct\n", - pci_name(pcidev)); - ret = -ENOMEM; - iounmap(mmio_regs); - goto bail2; - } - - memset(c2dev, 0, sizeof(*c2dev)); - spin_lock_init(&c2dev->lock); - c2dev->pcidev = pcidev; - c2dev->cur_tx = 0; - - /* Get the last RX index */ - c2dev->cur_rx = - (be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_HRX_CUR)) - - 0xffffc000) / sizeof(struct c2_rxp_desc); - - /* Request an interrupt line for the driver */ - ret = request_irq(pcidev->irq, c2_interrupt, IRQF_SHARED, DRV_NAME, c2dev); - if (ret) { - printk(KERN_ERR PFX "%s: requested IRQ %u is busy\n", - pci_name(pcidev), pcidev->irq); - iounmap(mmio_regs); - goto bail3; - } - - /* Set driver specific data */ - pci_set_drvdata(pcidev, c2dev); - - /* Initialize network device */ - if ((netdev = c2_devinit(c2dev, mmio_regs)) == NULL) { - ret = -ENOMEM; - iounmap(mmio_regs); - goto bail4; - } - - /* Save off the actual size prior to unmapping mmio_regs */ - kva_map_size = be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_PCI_WINSIZE)); - - /* Unmap the adapter PCI registers in BAR4 */ - iounmap(mmio_regs); - - /* Register network device */ - ret = register_netdev(netdev); - if (ret) { - printk(KERN_ERR PFX "Unable to register netdev, ret = %d\n", - ret); - goto bail5; - } - - /* Disable network packets */ - netif_stop_queue(netdev); - - /* Remap the adapter HRXDQ PA space to kernel VA space */ - c2dev->mmio_rxp_ring = ioremap_nocache(reg4_start + C2_RXP_HRXDQ_OFFSET, - C2_RXP_HRXDQ_SIZE); - if (!c2dev->mmio_rxp_ring) { - printk(KERN_ERR PFX "Unable to remap MMIO HRXDQ region\n"); - ret = -EIO; - goto bail6; - } - - /* Remap the adapter HTXDQ PA space to kernel VA space */ - c2dev->mmio_txp_ring = ioremap_nocache(reg4_start + C2_TXP_HTXDQ_OFFSET, - C2_TXP_HTXDQ_SIZE); - if (!c2dev->mmio_txp_ring) { - printk(KERN_ERR PFX "Unable to remap MMIO HTXDQ region\n"); - ret = -EIO; - goto bail7; - } - - /* Save off the current RX index in the last 4 bytes of the TXP Ring */ - C2_SET_CUR_RX(c2dev, c2dev->cur_rx); - - /* Remap the PCI registers in adapter BAR0 to kernel VA space */ - c2dev->regs = ioremap_nocache(reg0_start, reg0_len); - if (!c2dev->regs) { - printk(KERN_ERR PFX "Unable to remap BAR0\n"); - ret = -EIO; - goto bail8; - } - - /* Remap the PCI registers in adapter BAR4 to kernel VA space */ - c2dev->pa = reg4_start + C2_PCI_REGS_OFFSET; - c2dev->kva = ioremap_nocache(reg4_start + C2_PCI_REGS_OFFSET, - kva_map_size); - if (!c2dev->kva) { - printk(KERN_ERR PFX "Unable to remap BAR4\n"); - ret = -EIO; - goto bail9; - } - - /* Print out the MAC address */ - pr_debug("%s: MAC %pM, IRQ %u\n", netdev->name, netdev->dev_addr, - netdev->irq); - - ret = c2_rnic_init(c2dev); - if (ret) { - printk(KERN_ERR PFX "c2_rnic_init failed: %d\n", ret); - goto bail10; - } - - ret = c2_register_device(c2dev); - if (ret) - goto bail10; - - return 0; - - bail10: - iounmap(c2dev->kva); - - bail9: - iounmap(c2dev->regs); - - bail8: - iounmap(c2dev->mmio_txp_ring); - - bail7: - iounmap(c2dev->mmio_rxp_ring); - - bail6: - unregister_netdev(netdev); - - bail5: - free_netdev(netdev); - - bail4: - free_irq(pcidev->irq, c2dev); - - bail3: - ib_dealloc_device(&c2dev->ibdev); - - bail2: - pci_release_regions(pcidev); - - bail1: - pci_disable_device(pcidev); - - bail0: - return ret; -} - -static void c2_remove(struct pci_dev *pcidev) -{ - struct c2_dev *c2dev = pci_get_drvdata(pcidev); - struct net_device *netdev = c2dev->netdev; - - /* Unregister with OpenIB */ - c2_unregister_device(c2dev); - - /* Clean up the RNIC resources */ - c2_rnic_term(c2dev); - - /* Remove network device from the kernel */ - unregister_netdev(netdev); - - /* Free network device */ - free_netdev(netdev); - - /* Free the interrupt line */ - free_irq(pcidev->irq, c2dev); - - /* missing: Turn LEDs off here */ - - /* Unmap adapter PA space */ - iounmap(c2dev->kva); - iounmap(c2dev->regs); - iounmap(c2dev->mmio_txp_ring); - iounmap(c2dev->mmio_rxp_ring); - - /* Free the hardware structure */ - ib_dealloc_device(&c2dev->ibdev); - - /* Release reserved PCI I/O and memory resources */ - pci_release_regions(pcidev); - - /* Disable PCI device */ - pci_disable_device(pcidev); - - /* Clear driver specific data */ - pci_set_drvdata(pcidev, NULL); -} - -static struct pci_driver c2_pci_driver = { - .name = DRV_NAME, - .id_table = c2_pci_table, - .probe = c2_probe, - .remove = c2_remove, -}; - -module_pci_driver(c2_pci_driver); diff --git a/drivers/staging/rdma/amso1100/c2.h b/drivers/staging/rdma/amso1100/c2.h deleted file mode 100644 index 21b565a91fd6..000000000000 --- a/drivers/staging/rdma/amso1100/c2.h +++ /dev/null @@ -1,547 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef __C2_H -#define __C2_H - -#include -#include -#include -#include -#include -#include - -#include "c2_provider.h" -#include "c2_mq.h" -#include "c2_status.h" - -#define DRV_NAME "c2" -#define DRV_VERSION "1.1" -#define PFX DRV_NAME ": " - -#define BAR_0 0 -#define BAR_2 2 -#define BAR_4 4 - -#define RX_BUF_SIZE (1536 + 8) -#define ETH_JUMBO_MTU 9000 -#define C2_MAGIC "CEPHEUS" -#define C2_VERSION 4 -#define C2_IVN (18 & 0x7fffffff) - -#define C2_REG0_SIZE (16 * 1024) -#define C2_REG2_SIZE (2 * 1024 * 1024) -#define C2_REG4_SIZE (256 * 1024 * 1024) -#define C2_NUM_TX_DESC 341 -#define C2_NUM_RX_DESC 256 -#define C2_PCI_REGS_OFFSET (0x10000) -#define C2_RXP_HRXDQ_OFFSET (((C2_REG4_SIZE)/2)) -#define C2_RXP_HRXDQ_SIZE (4096) -#define C2_TXP_HTXDQ_OFFSET (((C2_REG4_SIZE)/2) + C2_RXP_HRXDQ_SIZE) -#define C2_TXP_HTXDQ_SIZE (4096) -#define C2_TX_TIMEOUT (6*HZ) - -/* CEPHEUS */ -static const u8 c2_magic[] = { - 0x43, 0x45, 0x50, 0x48, 0x45, 0x55, 0x53 -}; - -enum adapter_pci_regs { - C2_REGS_MAGIC = 0x0000, - C2_REGS_VERS = 0x0008, - C2_REGS_IVN = 0x000C, - C2_REGS_PCI_WINSIZE = 0x0010, - C2_REGS_Q0_QSIZE = 0x0014, - C2_REGS_Q0_MSGSIZE = 0x0018, - C2_REGS_Q0_POOLSTART = 0x001C, - C2_REGS_Q0_SHARED = 0x0020, - C2_REGS_Q1_QSIZE = 0x0024, - C2_REGS_Q1_MSGSIZE = 0x0028, - C2_REGS_Q1_SHARED = 0x0030, - C2_REGS_Q2_QSIZE = 0x0034, - C2_REGS_Q2_MSGSIZE = 0x0038, - C2_REGS_Q2_SHARED = 0x0040, - C2_REGS_ENADDR = 0x004C, - C2_REGS_RDMA_ENADDR = 0x0054, - C2_REGS_HRX_CUR = 0x006C, -}; - -struct c2_adapter_pci_regs { - char reg_magic[8]; - u32 version; - u32 ivn; - u32 pci_window_size; - u32 q0_q_size; - u32 q0_msg_size; - u32 q0_pool_start; - u32 q0_shared; - u32 q1_q_size; - u32 q1_msg_size; - u32 q1_pool_start; - u32 q1_shared; - u32 q2_q_size; - u32 q2_msg_size; - u32 q2_pool_start; - u32 q2_shared; - u32 log_start; - u32 log_size; - u8 host_enaddr[8]; - u8 rdma_enaddr[8]; - u32 crash_entry; - u32 crash_ready[2]; - u32 fw_txd_cur; - u32 fw_hrxd_cur; - u32 fw_rxd_cur; -}; - -enum pci_regs { - C2_HISR = 0x0000, - C2_DISR = 0x0004, - C2_HIMR = 0x0008, - C2_DIMR = 0x000C, - C2_NISR0 = 0x0010, - C2_NISR1 = 0x0014, - C2_NIMR0 = 0x0018, - C2_NIMR1 = 0x001C, - C2_IDIS = 0x0020, -}; - -enum { - C2_PCI_HRX_INT = 1 << 8, - C2_PCI_HTX_INT = 1 << 17, - C2_PCI_HRX_QUI = 1 << 31, -}; - -/* - * Cepheus registers in BAR0. - */ -struct c2_pci_regs { - u32 hostisr; - u32 dmaisr; - u32 hostimr; - u32 dmaimr; - u32 netisr0; - u32 netisr1; - u32 netimr0; - u32 netimr1; - u32 int_disable; -}; - -/* TXP flags */ -enum c2_txp_flags { - TXP_HTXD_DONE = 0, - TXP_HTXD_READY = 1 << 0, - TXP_HTXD_UNINIT = 1 << 1, -}; - -/* RXP flags */ -enum c2_rxp_flags { - RXP_HRXD_UNINIT = 0, - RXP_HRXD_READY = 1 << 0, - RXP_HRXD_DONE = 1 << 1, -}; - -/* RXP status */ -enum c2_rxp_status { - RXP_HRXD_ZERO = 0, - RXP_HRXD_OK = 1 << 0, - RXP_HRXD_BUF_OV = 1 << 1, -}; - -/* TXP descriptor fields */ -enum txp_desc { - C2_TXP_FLAGS = 0x0000, - C2_TXP_LEN = 0x0002, - C2_TXP_ADDR = 0x0004, -}; - -/* RXP descriptor fields */ -enum rxp_desc { - C2_RXP_FLAGS = 0x0000, - C2_RXP_STATUS = 0x0002, - C2_RXP_COUNT = 0x0004, - C2_RXP_LEN = 0x0006, - C2_RXP_ADDR = 0x0008, -}; - -struct c2_txp_desc { - u16 flags; - u16 len; - u64 addr; -} __attribute__ ((packed)); - -struct c2_rxp_desc { - u16 flags; - u16 status; - u16 count; - u16 len; - u64 addr; -} __attribute__ ((packed)); - -struct c2_rxp_hdr { - u16 flags; - u16 status; - u16 len; - u16 rsvd; -} __attribute__ ((packed)); - -struct c2_tx_desc { - u32 len; - u32 status; - dma_addr_t next_offset; -}; - -struct c2_rx_desc { - u32 len; - u32 status; - dma_addr_t next_offset; -}; - -struct c2_alloc { - u32 last; - u32 max; - spinlock_t lock; - unsigned long *table; -}; - -struct c2_array { - struct { - void **page; - int used; - } *page_list; -}; - -/* - * The MQ shared pointer pool is organized as a linked list of - * chunks. Each chunk contains a linked list of free shared pointers - * that can be allocated to a given user mode client. - * - */ -struct sp_chunk { - struct sp_chunk *next; - dma_addr_t dma_addr; - DEFINE_DMA_UNMAP_ADDR(mapping); - u16 head; - u16 shared_ptr[0]; -}; - -struct c2_pd_table { - u32 last; - u32 max; - spinlock_t lock; - unsigned long *table; -}; - -struct c2_qp_table { - struct idr idr; - spinlock_t lock; -}; - -struct c2_element { - struct c2_element *next; - void *ht_desc; /* host descriptor */ - void __iomem *hw_desc; /* hardware descriptor */ - struct sk_buff *skb; - dma_addr_t mapaddr; - u32 maplen; -}; - -struct c2_ring { - struct c2_element *to_clean; - struct c2_element *to_use; - struct c2_element *start; - unsigned long count; -}; - -struct c2_dev { - struct ib_device ibdev; - void __iomem *regs; - void __iomem *mmio_txp_ring; /* remapped adapter memory for hw rings */ - void __iomem *mmio_rxp_ring; - spinlock_t lock; - struct pci_dev *pcidev; - struct net_device *netdev; - struct net_device *pseudo_netdev; - unsigned int cur_tx; - unsigned int cur_rx; - u32 adapter_handle; - int device_cap_flags; - void __iomem *kva; /* KVA device memory */ - unsigned long pa; /* PA device memory */ - void **qptr_array; - - struct kmem_cache *host_msg_cache; - - struct list_head cca_link; /* adapter list */ - struct list_head eh_wakeup_list; /* event wakeup list */ - wait_queue_head_t req_vq_wo; - - /* Cached RNIC properties */ - struct ib_device_attr props; - - struct c2_pd_table pd_table; - struct c2_qp_table qp_table; - int ports; /* num of GigE ports */ - int devnum; - spinlock_t vqlock; /* sync vbs req MQ */ - - /* Verbs Queues */ - struct c2_mq req_vq; /* Verbs Request MQ */ - struct c2_mq rep_vq; /* Verbs Reply MQ */ - struct c2_mq aeq; /* Async Events MQ */ - - /* Kernel client MQs */ - struct sp_chunk *kern_mqsp_pool; - - /* Device updates these values when posting messages to a host - * target queue */ - u16 req_vq_shared; - u16 rep_vq_shared; - u16 aeq_shared; - u16 irq_claimed; - - /* - * Shared host target pages for user-accessible MQs. - */ - int hthead; /* index of first free entry */ - void *htpages; /* kernel vaddr */ - int htlen; /* length of htpages memory */ - void *htuva; /* user mapped vaddr */ - spinlock_t htlock; /* serialize allocation */ - - u64 adapter_hint_uva; /* access to the activity FIFO */ - - // spinlock_t aeq_lock; - // spinlock_t rnic_lock; - - __be16 *hint_count; - dma_addr_t hint_count_dma; - u16 hints_read; - - int init; /* TRUE if it's ready */ - char ae_cache_name[16]; - char vq_cache_name[16]; -}; - -struct c2_port { - u32 msg_enable; - struct c2_dev *c2dev; - struct net_device *netdev; - - spinlock_t tx_lock; - u32 tx_avail; - struct c2_ring tx_ring; - struct c2_ring rx_ring; - - void *mem; /* PCI memory for host rings */ - dma_addr_t dma; - unsigned long mem_size; - - u32 rx_buf_size; -}; - -/* - * Activity FIFO registers in BAR0. - */ -#define PCI_BAR0_HOST_HINT 0x100 -#define PCI_BAR0_ADAPTER_HINT 0x2000 - -/* - * Ammasso PCI vendor id and Cepheus PCI device id. - */ -#define CQ_ARMED 0x01 -#define CQ_WAIT_FOR_DMA 0x80 - -/* - * The format of a hint is as follows: - * Lower 16 bits are the count of hints for the queue. - * Next 15 bits are the qp_index - * Upper most bit depends on who reads it: - * If read by producer, then it means Full (1) or Not-Full (0) - * If read by consumer, then it means Empty (1) or Not-Empty (0) - */ -#define C2_HINT_MAKE(q_index, hint_count) (((q_index) << 16) | hint_count) -#define C2_HINT_GET_INDEX(hint) (((hint) & 0x7FFF0000) >> 16) -#define C2_HINT_GET_COUNT(hint) ((hint) & 0x0000FFFF) - - -/* - * The following defines the offset in SDRAM for the c2_adapter_pci_regs_t - * struct. - */ -#define C2_ADAPTER_PCI_REGS_OFFSET 0x10000 - -#ifndef readq -static inline u64 readq(const void __iomem * addr) -{ - u64 ret = readl(addr + 4); - ret <<= 32; - ret |= readl(addr); - - return ret; -} -#endif - -#ifndef writeq -static inline void __raw_writeq(u64 val, void __iomem * addr) -{ - __raw_writel((u32) (val), addr); - __raw_writel((u32) (val >> 32), (addr + 4)); -} -#endif - -#define C2_SET_CUR_RX(c2dev, cur_rx) \ - __raw_writel((__force u32) cpu_to_be32(cur_rx), c2dev->mmio_txp_ring + 4092) - -#define C2_GET_CUR_RX(c2dev) \ - be32_to_cpu((__force __be32) readl(c2dev->mmio_txp_ring + 4092)) - -static inline struct c2_dev *to_c2dev(struct ib_device *ibdev) -{ - return container_of(ibdev, struct c2_dev, ibdev); -} - -static inline int c2_errno(void *reply) -{ - switch (c2_wr_get_result(reply)) { - case C2_OK: - return 0; - case CCERR_NO_BUFS: - case CCERR_INSUFFICIENT_RESOURCES: - case CCERR_ZERO_RDMA_READ_RESOURCES: - return -ENOMEM; - case CCERR_MR_IN_USE: - case CCERR_QP_IN_USE: - return -EBUSY; - case CCERR_ADDR_IN_USE: - return -EADDRINUSE; - case CCERR_ADDR_NOT_AVAIL: - return -EADDRNOTAVAIL; - case CCERR_CONN_RESET: - return -ECONNRESET; - case CCERR_NOT_IMPLEMENTED: - case CCERR_INVALID_WQE: - return -ENOSYS; - case CCERR_QP_NOT_PRIVILEGED: - return -EPERM; - case CCERR_STACK_ERROR: - return -EPROTO; - case CCERR_ACCESS_VIOLATION: - case CCERR_BASE_AND_BOUNDS_VIOLATION: - return -EFAULT; - case CCERR_STAG_STATE_NOT_INVALID: - case CCERR_INVALID_ADDRESS: - case CCERR_INVALID_CQ: - case CCERR_INVALID_EP: - case CCERR_INVALID_MODIFIER: - case CCERR_INVALID_MTU: - case CCERR_INVALID_PD_ID: - case CCERR_INVALID_QP: - case CCERR_INVALID_RNIC: - case CCERR_INVALID_STAG: - return -EINVAL; - default: - return -EAGAIN; - } -} - -/* Device */ -int c2_register_device(struct c2_dev *c2dev); -void c2_unregister_device(struct c2_dev *c2dev); -int c2_rnic_init(struct c2_dev *c2dev); -void c2_rnic_term(struct c2_dev *c2dev); -void c2_rnic_interrupt(struct c2_dev *c2dev); -int c2_del_addr(struct c2_dev *c2dev, __be32 inaddr, __be32 inmask); -int c2_add_addr(struct c2_dev *c2dev, __be32 inaddr, __be32 inmask); - -/* QPs */ -int c2_alloc_qp(struct c2_dev *c2dev, struct c2_pd *pd, - struct ib_qp_init_attr *qp_attrs, struct c2_qp *qp); -void c2_free_qp(struct c2_dev *c2dev, struct c2_qp *qp); -struct ib_qp *c2_get_qp(struct ib_device *device, int qpn); -int c2_qp_modify(struct c2_dev *c2dev, struct c2_qp *qp, - struct ib_qp_attr *attr, int attr_mask); -int c2_qp_set_read_limits(struct c2_dev *c2dev, struct c2_qp *qp, - int ord, int ird); -int c2_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, - struct ib_send_wr **bad_wr); -int c2_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr, - struct ib_recv_wr **bad_wr); -void c2_init_qp_table(struct c2_dev *c2dev); -void c2_cleanup_qp_table(struct c2_dev *c2dev); -void c2_set_qp_state(struct c2_qp *, int); -struct c2_qp *c2_find_qpn(struct c2_dev *c2dev, int qpn); - -/* PDs */ -int c2_pd_alloc(struct c2_dev *c2dev, int privileged, struct c2_pd *pd); -void c2_pd_free(struct c2_dev *c2dev, struct c2_pd *pd); -int c2_init_pd_table(struct c2_dev *c2dev); -void c2_cleanup_pd_table(struct c2_dev *c2dev); - -/* CQs */ -int c2_init_cq(struct c2_dev *c2dev, int entries, - struct c2_ucontext *ctx, struct c2_cq *cq); -void c2_free_cq(struct c2_dev *c2dev, struct c2_cq *cq); -void c2_cq_event(struct c2_dev *c2dev, u32 mq_index); -void c2_cq_clean(struct c2_dev *c2dev, struct c2_qp *qp, u32 mq_index); -int c2_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry); -int c2_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags); - -/* CM */ -int c2_llp_connect(struct iw_cm_id *cm_id, - struct iw_cm_conn_param *iw_param); -int c2_llp_accept(struct iw_cm_id *cm_id, - struct iw_cm_conn_param *iw_param); -int c2_llp_reject(struct iw_cm_id *cm_id, const void *pdata, - u8 pdata_len); -int c2_llp_service_create(struct iw_cm_id *cm_id, int backlog); -int c2_llp_service_destroy(struct iw_cm_id *cm_id); - -/* MM */ -int c2_nsmr_register_phys_kern(struct c2_dev *c2dev, u64 *addr_list, - int page_size, int pbl_depth, u32 length, - u32 off, u64 *va, enum c2_acf acf, - struct c2_mr *mr); -int c2_stag_dealloc(struct c2_dev *c2dev, u32 stag_index); - -/* AE */ -void c2_ae_event(struct c2_dev *c2dev, u32 mq_index); - -/* MQSP Allocator */ -int c2_init_mqsp_pool(struct c2_dev *c2dev, gfp_t gfp_mask, - struct sp_chunk **root); -void c2_free_mqsp_pool(struct c2_dev *c2dev, struct sp_chunk *root); -__be16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head, - dma_addr_t *dma_addr, gfp_t gfp_mask); -void c2_free_mqsp(__be16* mqsp); -#endif diff --git a/drivers/staging/rdma/amso1100/c2_ae.c b/drivers/staging/rdma/amso1100/c2_ae.c deleted file mode 100644 index eb7a92b2692f..000000000000 --- a/drivers/staging/rdma/amso1100/c2_ae.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "c2.h" -#include -#include "c2_status.h" -#include "c2_ae.h" - -static int c2_convert_cm_status(u32 c2_status) -{ - switch (c2_status) { - case C2_CONN_STATUS_SUCCESS: - return 0; - case C2_CONN_STATUS_REJECTED: - return -ENETRESET; - case C2_CONN_STATUS_REFUSED: - return -ECONNREFUSED; - case C2_CONN_STATUS_TIMEDOUT: - return -ETIMEDOUT; - case C2_CONN_STATUS_NETUNREACH: - return -ENETUNREACH; - case C2_CONN_STATUS_HOSTUNREACH: - return -EHOSTUNREACH; - case C2_CONN_STATUS_INVALID_RNIC: - return -EINVAL; - case C2_CONN_STATUS_INVALID_QP: - return -EINVAL; - case C2_CONN_STATUS_INVALID_QP_STATE: - return -EINVAL; - case C2_CONN_STATUS_ADDR_NOT_AVAIL: - return -EADDRNOTAVAIL; - default: - printk(KERN_ERR PFX - "%s - Unable to convert CM status: %d\n", - __func__, c2_status); - return -EIO; - } -} - -static const char* to_event_str(int event) -{ - static const char* event_str[] = { - "CCAE_REMOTE_SHUTDOWN", - "CCAE_ACTIVE_CONNECT_RESULTS", - "CCAE_CONNECTION_REQUEST", - "CCAE_LLP_CLOSE_COMPLETE", - "CCAE_TERMINATE_MESSAGE_RECEIVED", - "CCAE_LLP_CONNECTION_RESET", - "CCAE_LLP_CONNECTION_LOST", - "CCAE_LLP_SEGMENT_SIZE_INVALID", - "CCAE_LLP_INVALID_CRC", - "CCAE_LLP_BAD_FPDU", - "CCAE_INVALID_DDP_VERSION", - "CCAE_INVALID_RDMA_VERSION", - "CCAE_UNEXPECTED_OPCODE", - "CCAE_INVALID_DDP_QUEUE_NUMBER", - "CCAE_RDMA_READ_NOT_ENABLED", - "CCAE_RDMA_WRITE_NOT_ENABLED", - "CCAE_RDMA_READ_TOO_SMALL", - "CCAE_NO_L_BIT", - "CCAE_TAGGED_INVALID_STAG", - "CCAE_TAGGED_BASE_BOUNDS_VIOLATION", - "CCAE_TAGGED_ACCESS_RIGHTS_VIOLATION", - "CCAE_TAGGED_INVALID_PD", - "CCAE_WRAP_ERROR", - "CCAE_BAD_CLOSE", - "CCAE_BAD_LLP_CLOSE", - "CCAE_INVALID_MSN_RANGE", - "CCAE_INVALID_MSN_GAP", - "CCAE_IRRQ_OVERFLOW", - "CCAE_IRRQ_MSN_GAP", - "CCAE_IRRQ_MSN_RANGE", - "CCAE_IRRQ_INVALID_STAG", - "CCAE_IRRQ_BASE_BOUNDS_VIOLATION", - "CCAE_IRRQ_ACCESS_RIGHTS_VIOLATION", - "CCAE_IRRQ_INVALID_PD", - "CCAE_IRRQ_WRAP_ERROR", - "CCAE_CQ_SQ_COMPLETION_OVERFLOW", - "CCAE_CQ_RQ_COMPLETION_ERROR", - "CCAE_QP_SRQ_WQE_ERROR", - "CCAE_QP_LOCAL_CATASTROPHIC_ERROR", - "CCAE_CQ_OVERFLOW", - "CCAE_CQ_OPERATION_ERROR", - "CCAE_SRQ_LIMIT_REACHED", - "CCAE_QP_RQ_LIMIT_REACHED", - "CCAE_SRQ_CATASTROPHIC_ERROR", - "CCAE_RNIC_CATASTROPHIC_ERROR" - }; - - if (event < CCAE_REMOTE_SHUTDOWN || - event > CCAE_RNIC_CATASTROPHIC_ERROR) - return ""; - - event -= CCAE_REMOTE_SHUTDOWN; - return event_str[event]; -} - -static const char *to_qp_state_str(int state) -{ - switch (state) { - case C2_QP_STATE_IDLE: - return "C2_QP_STATE_IDLE"; - case C2_QP_STATE_CONNECTING: - return "C2_QP_STATE_CONNECTING"; - case C2_QP_STATE_RTS: - return "C2_QP_STATE_RTS"; - case C2_QP_STATE_CLOSING: - return "C2_QP_STATE_CLOSING"; - case C2_QP_STATE_TERMINATE: - return "C2_QP_STATE_TERMINATE"; - case C2_QP_STATE_ERROR: - return "C2_QP_STATE_ERROR"; - default: - return ""; - } -} - -void c2_ae_event(struct c2_dev *c2dev, u32 mq_index) -{ - struct c2_mq *mq = c2dev->qptr_array[mq_index]; - union c2wr *wr; - void *resource_user_context; - struct iw_cm_event cm_event; - struct ib_event ib_event; - enum c2_resource_indicator resource_indicator; - enum c2_event_id event_id; - unsigned long flags; - int status; - struct sockaddr_in *laddr = (struct sockaddr_in *)&cm_event.local_addr; - struct sockaddr_in *raddr = (struct sockaddr_in *)&cm_event.remote_addr; - - /* - * retrieve the message - */ - wr = c2_mq_consume(mq); - if (!wr) - return; - - memset(&ib_event, 0, sizeof(ib_event)); - memset(&cm_event, 0, sizeof(cm_event)); - - event_id = c2_wr_get_id(wr); - resource_indicator = be32_to_cpu(wr->ae.ae_generic.resource_type); - resource_user_context = - (void *) (unsigned long) wr->ae.ae_generic.user_context; - - status = cm_event.status = c2_convert_cm_status(c2_wr_get_result(wr)); - - pr_debug("event received c2_dev=%p, event_id=%d, " - "resource_indicator=%d, user_context=%p, status = %d\n", - c2dev, event_id, resource_indicator, resource_user_context, - status); - - switch (resource_indicator) { - case C2_RES_IND_QP:{ - - struct c2_qp *qp = resource_user_context; - struct iw_cm_id *cm_id = qp->cm_id; - struct c2wr_ae_active_connect_results *res; - - if (!cm_id) { - pr_debug("event received, but cm_id is , qp=%p!\n", - qp); - goto ignore_it; - } - pr_debug("%s: event = %s, user_context=%llx, " - "resource_type=%x, " - "resource=%x, qp_state=%s\n", - __func__, - to_event_str(event_id), - (unsigned long long) wr->ae.ae_generic.user_context, - be32_to_cpu(wr->ae.ae_generic.resource_type), - be32_to_cpu(wr->ae.ae_generic.resource), - to_qp_state_str(be32_to_cpu(wr->ae.ae_generic.qp_state))); - - c2_set_qp_state(qp, be32_to_cpu(wr->ae.ae_generic.qp_state)); - - switch (event_id) { - case CCAE_ACTIVE_CONNECT_RESULTS: - res = &wr->ae.ae_active_connect_results; - cm_event.event = IW_CM_EVENT_CONNECT_REPLY; - laddr->sin_addr.s_addr = res->laddr; - raddr->sin_addr.s_addr = res->raddr; - laddr->sin_port = res->lport; - raddr->sin_port = res->rport; - if (status == 0) { - cm_event.private_data_len = - be32_to_cpu(res->private_data_length); - cm_event.private_data = res->private_data; - } else { - spin_lock_irqsave(&qp->lock, flags); - if (qp->cm_id) { - qp->cm_id->rem_ref(qp->cm_id); - qp->cm_id = NULL; - } - spin_unlock_irqrestore(&qp->lock, flags); - cm_event.private_data_len = 0; - cm_event.private_data = NULL; - } - if (cm_id->event_handler) - cm_id->event_handler(cm_id, &cm_event); - break; - case CCAE_TERMINATE_MESSAGE_RECEIVED: - case CCAE_CQ_SQ_COMPLETION_OVERFLOW: - ib_event.device = &c2dev->ibdev; - ib_event.element.qp = &qp->ibqp; - ib_event.event = IB_EVENT_QP_REQ_ERR; - - if (qp->ibqp.event_handler) - qp->ibqp.event_handler(&ib_event, - qp->ibqp. - qp_context); - break; - case CCAE_BAD_CLOSE: - case CCAE_LLP_CLOSE_COMPLETE: - case CCAE_LLP_CONNECTION_RESET: - case CCAE_LLP_CONNECTION_LOST: - BUG_ON(cm_id->event_handler==(void*)0x6b6b6b6b); - - spin_lock_irqsave(&qp->lock, flags); - if (qp->cm_id) { - qp->cm_id->rem_ref(qp->cm_id); - qp->cm_id = NULL; - } - spin_unlock_irqrestore(&qp->lock, flags); - cm_event.event = IW_CM_EVENT_CLOSE; - cm_event.status = 0; - if (cm_id->event_handler) - cm_id->event_handler(cm_id, &cm_event); - break; - default: - BUG_ON(1); - pr_debug("%s:%d Unexpected event_id=%d on QP=%p, " - "CM_ID=%p\n", - __func__, __LINE__, - event_id, qp, cm_id); - break; - } - break; - } - - case C2_RES_IND_EP:{ - - struct c2wr_ae_connection_request *req = - &wr->ae.ae_connection_request; - struct iw_cm_id *cm_id = - resource_user_context; - - pr_debug("C2_RES_IND_EP event_id=%d\n", event_id); - if (event_id != CCAE_CONNECTION_REQUEST) { - pr_debug("%s: Invalid event_id: %d\n", - __func__, event_id); - break; - } - cm_event.event = IW_CM_EVENT_CONNECT_REQUEST; - cm_event.provider_data = (void*)(unsigned long)req->cr_handle; - laddr->sin_addr.s_addr = req->laddr; - raddr->sin_addr.s_addr = req->raddr; - laddr->sin_port = req->lport; - raddr->sin_port = req->rport; - cm_event.private_data_len = - be32_to_cpu(req->private_data_length); - cm_event.private_data = req->private_data; - /* - * Until ird/ord negotiation via MPAv2 support is added, send - * max supported values - */ - cm_event.ird = cm_event.ord = 128; - - if (cm_id->event_handler) - cm_id->event_handler(cm_id, &cm_event); - break; - } - - case C2_RES_IND_CQ:{ - struct c2_cq *cq = - resource_user_context; - - pr_debug("IB_EVENT_CQ_ERR\n"); - ib_event.device = &c2dev->ibdev; - ib_event.element.cq = &cq->ibcq; - ib_event.event = IB_EVENT_CQ_ERR; - - if (cq->ibcq.event_handler) - cq->ibcq.event_handler(&ib_event, - cq->ibcq.cq_context); - break; - } - - default: - printk("Bad resource indicator = %d\n", - resource_indicator); - break; - } - - ignore_it: - c2_mq_free(mq); -} diff --git a/drivers/staging/rdma/amso1100/c2_ae.h b/drivers/staging/rdma/amso1100/c2_ae.h deleted file mode 100644 index 3a065c33b83b..000000000000 --- a/drivers/staging/rdma/amso1100/c2_ae.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef _C2_AE_H_ -#define _C2_AE_H_ - -/* - * WARNING: If you change this file, also bump C2_IVN_BASE - * in common/include/clustercore/c2_ivn.h. - */ - -/* - * Asynchronous Event Identifiers - * - * These start at 0x80 only so it's obvious from inspection that - * they are not work-request statuses. This isn't critical. - * - * NOTE: these event id's must fit in eight bits. - */ -enum c2_event_id { - CCAE_REMOTE_SHUTDOWN = 0x80, - CCAE_ACTIVE_CONNECT_RESULTS, - CCAE_CONNECTION_REQUEST, - CCAE_LLP_CLOSE_COMPLETE, - CCAE_TERMINATE_MESSAGE_RECEIVED, - CCAE_LLP_CONNECTION_RESET, - CCAE_LLP_CONNECTION_LOST, - CCAE_LLP_SEGMENT_SIZE_INVALID, - CCAE_LLP_INVALID_CRC, - CCAE_LLP_BAD_FPDU, - CCAE_INVALID_DDP_VERSION, - CCAE_INVALID_RDMA_VERSION, - CCAE_UNEXPECTED_OPCODE, - CCAE_INVALID_DDP_QUEUE_NUMBER, - CCAE_RDMA_READ_NOT_ENABLED, - CCAE_RDMA_WRITE_NOT_ENABLED, - CCAE_RDMA_READ_TOO_SMALL, - CCAE_NO_L_BIT, - CCAE_TAGGED_INVALID_STAG, - CCAE_TAGGED_BASE_BOUNDS_VIOLATION, - CCAE_TAGGED_ACCESS_RIGHTS_VIOLATION, - CCAE_TAGGED_INVALID_PD, - CCAE_WRAP_ERROR, - CCAE_BAD_CLOSE, - CCAE_BAD_LLP_CLOSE, - CCAE_INVALID_MSN_RANGE, - CCAE_INVALID_MSN_GAP, - CCAE_IRRQ_OVERFLOW, - CCAE_IRRQ_MSN_GAP, - CCAE_IRRQ_MSN_RANGE, - CCAE_IRRQ_INVALID_STAG, - CCAE_IRRQ_BASE_BOUNDS_VIOLATION, - CCAE_IRRQ_ACCESS_RIGHTS_VIOLATION, - CCAE_IRRQ_INVALID_PD, - CCAE_IRRQ_WRAP_ERROR, - CCAE_CQ_SQ_COMPLETION_OVERFLOW, - CCAE_CQ_RQ_COMPLETION_ERROR, - CCAE_QP_SRQ_WQE_ERROR, - CCAE_QP_LOCAL_CATASTROPHIC_ERROR, - CCAE_CQ_OVERFLOW, - CCAE_CQ_OPERATION_ERROR, - CCAE_SRQ_LIMIT_REACHED, - CCAE_QP_RQ_LIMIT_REACHED, - CCAE_SRQ_CATASTROPHIC_ERROR, - CCAE_RNIC_CATASTROPHIC_ERROR -/* WARNING If you add more id's, make sure their values fit in eight bits. */ -}; - -/* - * Resource Indicators and Identifiers - */ -enum c2_resource_indicator { - C2_RES_IND_QP = 1, - C2_RES_IND_EP, - C2_RES_IND_CQ, - C2_RES_IND_SRQ, -}; - -#endif /* _C2_AE_H_ */ diff --git a/drivers/staging/rdma/amso1100/c2_alloc.c b/drivers/staging/rdma/amso1100/c2_alloc.c deleted file mode 100644 index 039872dfabbc..000000000000 --- a/drivers/staging/rdma/amso1100/c2_alloc.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2004 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include "c2.h" - -static int c2_alloc_mqsp_chunk(struct c2_dev *c2dev, gfp_t gfp_mask, - struct sp_chunk **head) -{ - int i; - struct sp_chunk *new_head; - dma_addr_t dma_addr; - - new_head = dma_alloc_coherent(&c2dev->pcidev->dev, PAGE_SIZE, - &dma_addr, gfp_mask); - if (new_head == NULL) - return -ENOMEM; - - new_head->dma_addr = dma_addr; - dma_unmap_addr_set(new_head, mapping, new_head->dma_addr); - - new_head->next = NULL; - new_head->head = 0; - - /* build list where each index is the next free slot */ - for (i = 0; - i < (PAGE_SIZE - sizeof(struct sp_chunk) - - sizeof(u16)) / sizeof(u16) - 1; - i++) { - new_head->shared_ptr[i] = i + 1; - } - /* terminate list */ - new_head->shared_ptr[i] = 0xFFFF; - - *head = new_head; - return 0; -} - -int c2_init_mqsp_pool(struct c2_dev *c2dev, gfp_t gfp_mask, - struct sp_chunk **root) -{ - return c2_alloc_mqsp_chunk(c2dev, gfp_mask, root); -} - -void c2_free_mqsp_pool(struct c2_dev *c2dev, struct sp_chunk *root) -{ - struct sp_chunk *next; - - while (root) { - next = root->next; - dma_free_coherent(&c2dev->pcidev->dev, PAGE_SIZE, root, - dma_unmap_addr(root, mapping)); - root = next; - } -} - -__be16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head, - dma_addr_t *dma_addr, gfp_t gfp_mask) -{ - u16 mqsp; - - while (head) { - mqsp = head->head; - if (mqsp != 0xFFFF) { - head->head = head->shared_ptr[mqsp]; - break; - } else if (head->next == NULL) { - if (c2_alloc_mqsp_chunk(c2dev, gfp_mask, &head->next) == - 0) { - head = head->next; - mqsp = head->head; - head->head = head->shared_ptr[mqsp]; - break; - } else - return NULL; - } else - head = head->next; - } - if (head) { - *dma_addr = head->dma_addr + - ((unsigned long) &(head->shared_ptr[mqsp]) - - (unsigned long) head); - pr_debug("%s addr %p dma_addr %llx\n", __func__, - &(head->shared_ptr[mqsp]), (unsigned long long) *dma_addr); - return (__force __be16 *) &(head->shared_ptr[mqsp]); - } - return NULL; -} - -void c2_free_mqsp(__be16 *mqsp) -{ - struct sp_chunk *head; - u16 idx; - - /* The chunk containing this ptr begins at the page boundary */ - head = (struct sp_chunk *) ((unsigned long) mqsp & PAGE_MASK); - - /* Link head to new mqsp */ - *mqsp = (__force __be16) head->head; - - /* Compute the shared_ptr index */ - idx = (offset_in_page(mqsp)) >> 1; - idx -= (unsigned long) &(((struct sp_chunk *) 0)->shared_ptr[0]) >> 1; - - /* Point this index at the head */ - head->shared_ptr[idx] = head->head; - - /* Point head at this index */ - head->head = idx; -} diff --git a/drivers/staging/rdma/amso1100/c2_cm.c b/drivers/staging/rdma/amso1100/c2_cm.c deleted file mode 100644 index f8dbdb9e0f66..000000000000 --- a/drivers/staging/rdma/amso1100/c2_cm.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ -#include - -#include "c2.h" -#include "c2_wr.h" -#include "c2_vq.h" -#include - -int c2_llp_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param) -{ - struct c2_dev *c2dev = to_c2dev(cm_id->device); - struct ib_qp *ibqp; - struct c2_qp *qp; - struct c2wr_qp_connect_req *wr; /* variable size needs a malloc. */ - struct c2_vq_req *vq_req; - int err; - struct sockaddr_in *raddr = (struct sockaddr_in *)&cm_id->remote_addr; - - if (cm_id->remote_addr.ss_family != AF_INET) - return -ENOSYS; - - ibqp = c2_get_qp(cm_id->device, iw_param->qpn); - if (!ibqp) - return -EINVAL; - qp = to_c2qp(ibqp); - - /* Associate QP <--> CM_ID */ - cm_id->provider_data = qp; - cm_id->add_ref(cm_id); - qp->cm_id = cm_id; - - /* - * only support the max private_data length - */ - if (iw_param->private_data_len > C2_MAX_PRIVATE_DATA_SIZE) { - err = -EINVAL; - goto bail0; - } - /* - * Set the rdma read limits - */ - err = c2_qp_set_read_limits(c2dev, qp, iw_param->ord, iw_param->ird); - if (err) - goto bail0; - - /* - * Create and send a WR_QP_CONNECT... - */ - wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL); - if (!wr) { - err = -ENOMEM; - goto bail0; - } - - vq_req = vq_req_alloc(c2dev); - if (!vq_req) { - err = -ENOMEM; - goto bail1; - } - - c2_wr_set_id(wr, CCWR_QP_CONNECT); - wr->hdr.context = 0; - wr->rnic_handle = c2dev->adapter_handle; - wr->qp_handle = qp->adapter_handle; - - wr->remote_addr = raddr->sin_addr.s_addr; - wr->remote_port = raddr->sin_port; - - /* - * Move any private data from the callers's buf into - * the WR. - */ - if (iw_param->private_data) { - wr->private_data_length = - cpu_to_be32(iw_param->private_data_len); - memcpy(&wr->private_data[0], iw_param->private_data, - iw_param->private_data_len); - } else - wr->private_data_length = 0; - - /* - * Send WR to adapter. NOTE: There is no synch reply from - * the adapter. - */ - err = vq_send_wr(c2dev, (union c2wr *) wr); - vq_req_free(c2dev, vq_req); - - bail1: - kfree(wr); - bail0: - if (err) { - /* - * If we fail, release reference on QP and - * disassociate QP from CM_ID - */ - cm_id->provider_data = NULL; - qp->cm_id = NULL; - cm_id->rem_ref(cm_id); - } - return err; -} - -int c2_llp_service_create(struct iw_cm_id *cm_id, int backlog) -{ - struct c2_dev *c2dev; - struct c2wr_ep_listen_create_req wr; - struct c2wr_ep_listen_create_rep *reply; - struct c2_vq_req *vq_req; - int err; - struct sockaddr_in *laddr = (struct sockaddr_in *)&cm_id->local_addr; - - if (cm_id->local_addr.ss_family != AF_INET) - return -ENOSYS; - - c2dev = to_c2dev(cm_id->device); - if (c2dev == NULL) - return -EINVAL; - - /* - * Allocate verbs request. - */ - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - /* - * Build the WR - */ - c2_wr_set_id(&wr, CCWR_EP_LISTEN_CREATE); - wr.hdr.context = (u64) (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.local_addr = laddr->sin_addr.s_addr; - wr.local_port = laddr->sin_port; - wr.backlog = cpu_to_be32(backlog); - wr.user_context = (u64) (unsigned long) cm_id; - - /* - * Reference the request struct. Dereferenced in the int handler. - */ - vq_req_get(c2dev, vq_req); - - /* - * Send WR to adapter - */ - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - /* - * Wait for reply from adapter - */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail0; - - /* - * Process reply - */ - reply = - (struct c2wr_ep_listen_create_rep *) (unsigned long) vq_req->reply_msg; - if (!reply) { - err = -ENOMEM; - goto bail1; - } - - if ((err = c2_errno(reply)) != 0) - goto bail1; - - /* - * Keep the adapter handle. Used in subsequent destroy - */ - cm_id->provider_data = (void*)(unsigned long) reply->ep_handle; - - /* - * free vq stuff - */ - vq_repbuf_free(c2dev, reply); - vq_req_free(c2dev, vq_req); - - return 0; - - bail1: - vq_repbuf_free(c2dev, reply); - bail0: - vq_req_free(c2dev, vq_req); - return err; -} - - -int c2_llp_service_destroy(struct iw_cm_id *cm_id) -{ - - struct c2_dev *c2dev; - struct c2wr_ep_listen_destroy_req wr; - struct c2wr_ep_listen_destroy_rep *reply; - struct c2_vq_req *vq_req; - int err; - - c2dev = to_c2dev(cm_id->device); - if (c2dev == NULL) - return -EINVAL; - - /* - * Allocate verbs request. - */ - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - /* - * Build the WR - */ - c2_wr_set_id(&wr, CCWR_EP_LISTEN_DESTROY); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.ep_handle = (u32)(unsigned long)cm_id->provider_data; - - /* - * reference the request struct. dereferenced in the int handler. - */ - vq_req_get(c2dev, vq_req); - - /* - * Send WR to adapter - */ - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - /* - * Wait for reply from adapter - */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail0; - - /* - * Process reply - */ - reply=(struct c2wr_ep_listen_destroy_rep *)(unsigned long)vq_req->reply_msg; - if (!reply) { - err = -ENOMEM; - goto bail0; - } - - vq_repbuf_free(c2dev, reply); - bail0: - vq_req_free(c2dev, vq_req); - return err; -} - -int c2_llp_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param) -{ - struct c2_dev *c2dev = to_c2dev(cm_id->device); - struct c2_qp *qp; - struct ib_qp *ibqp; - struct c2wr_cr_accept_req *wr; /* variable length WR */ - struct c2_vq_req *vq_req; - struct c2wr_cr_accept_rep *reply; /* VQ Reply msg ptr. */ - int err; - - ibqp = c2_get_qp(cm_id->device, iw_param->qpn); - if (!ibqp) - return -EINVAL; - qp = to_c2qp(ibqp); - - /* Set the RDMA read limits */ - err = c2_qp_set_read_limits(c2dev, qp, iw_param->ord, iw_param->ird); - if (err) - goto bail0; - - /* Allocate verbs request. */ - vq_req = vq_req_alloc(c2dev); - if (!vq_req) { - err = -ENOMEM; - goto bail0; - } - vq_req->qp = qp; - vq_req->cm_id = cm_id; - vq_req->event = IW_CM_EVENT_ESTABLISHED; - - wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL); - if (!wr) { - err = -ENOMEM; - goto bail1; - } - - /* Build the WR */ - c2_wr_set_id(wr, CCWR_CR_ACCEPT); - wr->hdr.context = (unsigned long) vq_req; - wr->rnic_handle = c2dev->adapter_handle; - wr->ep_handle = (u32) (unsigned long) cm_id->provider_data; - wr->qp_handle = qp->adapter_handle; - - /* Replace the cr_handle with the QP after accept */ - cm_id->provider_data = qp; - cm_id->add_ref(cm_id); - qp->cm_id = cm_id; - - cm_id->provider_data = qp; - - /* Validate private_data length */ - if (iw_param->private_data_len > C2_MAX_PRIVATE_DATA_SIZE) { - err = -EINVAL; - goto bail1; - } - - if (iw_param->private_data) { - wr->private_data_length = cpu_to_be32(iw_param->private_data_len); - memcpy(&wr->private_data[0], - iw_param->private_data, iw_param->private_data_len); - } else - wr->private_data_length = 0; - - /* Reference the request struct. Dereferenced in the int handler. */ - vq_req_get(c2dev, vq_req); - - /* Send WR to adapter */ - err = vq_send_wr(c2dev, (union c2wr *) wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail1; - } - - /* Wait for reply from adapter */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail1; - - /* Check that reply is present */ - reply = (struct c2wr_cr_accept_rep *) (unsigned long) vq_req->reply_msg; - if (!reply) { - err = -ENOMEM; - goto bail1; - } - - err = c2_errno(reply); - vq_repbuf_free(c2dev, reply); - - if (!err) - c2_set_qp_state(qp, C2_QP_STATE_RTS); - bail1: - kfree(wr); - vq_req_free(c2dev, vq_req); - bail0: - if (err) { - /* - * If we fail, release reference on QP and - * disassociate QP from CM_ID - */ - cm_id->provider_data = NULL; - qp->cm_id = NULL; - cm_id->rem_ref(cm_id); - } - return err; -} - -int c2_llp_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) -{ - struct c2_dev *c2dev; - struct c2wr_cr_reject_req wr; - struct c2_vq_req *vq_req; - struct c2wr_cr_reject_rep *reply; - int err; - - c2dev = to_c2dev(cm_id->device); - - /* - * Allocate verbs request. - */ - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - /* - * Build the WR - */ - c2_wr_set_id(&wr, CCWR_CR_REJECT); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.ep_handle = (u32) (unsigned long) cm_id->provider_data; - - /* - * reference the request struct. dereferenced in the int handler. - */ - vq_req_get(c2dev, vq_req); - - /* - * Send WR to adapter - */ - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - /* - * Wait for reply from adapter - */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail0; - - /* - * Process reply - */ - reply = (struct c2wr_cr_reject_rep *) (unsigned long) - vq_req->reply_msg; - if (!reply) { - err = -ENOMEM; - goto bail0; - } - err = c2_errno(reply); - /* - * free vq stuff - */ - vq_repbuf_free(c2dev, reply); - - bail0: - vq_req_free(c2dev, vq_req); - return err; -} diff --git a/drivers/staging/rdma/amso1100/c2_cq.c b/drivers/staging/rdma/amso1100/c2_cq.c deleted file mode 100644 index 7ad0c082485a..000000000000 --- a/drivers/staging/rdma/amso1100/c2_cq.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2005 Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2004 Voltaire, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ -#include - -#include "c2.h" -#include "c2_vq.h" -#include "c2_status.h" - -#define C2_CQ_MSG_SIZE ((sizeof(struct c2wr_ce) + 32-1) & ~(32-1)) - -static struct c2_cq *c2_cq_get(struct c2_dev *c2dev, int cqn) -{ - struct c2_cq *cq; - unsigned long flags; - - spin_lock_irqsave(&c2dev->lock, flags); - cq = c2dev->qptr_array[cqn]; - if (!cq) { - spin_unlock_irqrestore(&c2dev->lock, flags); - return NULL; - } - atomic_inc(&cq->refcount); - spin_unlock_irqrestore(&c2dev->lock, flags); - return cq; -} - -static void c2_cq_put(struct c2_cq *cq) -{ - if (atomic_dec_and_test(&cq->refcount)) - wake_up(&cq->wait); -} - -void c2_cq_event(struct c2_dev *c2dev, u32 mq_index) -{ - struct c2_cq *cq; - - cq = c2_cq_get(c2dev, mq_index); - if (!cq) { - printk("discarding events on destroyed CQN=%d\n", mq_index); - return; - } - - (*cq->ibcq.comp_handler) (&cq->ibcq, cq->ibcq.cq_context); - c2_cq_put(cq); -} - -void c2_cq_clean(struct c2_dev *c2dev, struct c2_qp *qp, u32 mq_index) -{ - struct c2_cq *cq; - struct c2_mq *q; - - cq = c2_cq_get(c2dev, mq_index); - if (!cq) - return; - - spin_lock_irq(&cq->lock); - q = &cq->mq; - if (q && !c2_mq_empty(q)) { - u16 priv = q->priv; - struct c2wr_ce *msg; - - while (priv != be16_to_cpu(*q->shared)) { - msg = (struct c2wr_ce *) - (q->msg_pool.host + priv * q->msg_size); - if (msg->qp_user_context == (u64) (unsigned long) qp) { - msg->qp_user_context = (u64) 0; - } - priv = (priv + 1) % q->q_size; - } - } - spin_unlock_irq(&cq->lock); - c2_cq_put(cq); -} - -static inline enum ib_wc_status c2_cqe_status_to_openib(u8 status) -{ - switch (status) { - case C2_OK: - return IB_WC_SUCCESS; - case CCERR_FLUSHED: - return IB_WC_WR_FLUSH_ERR; - case CCERR_BASE_AND_BOUNDS_VIOLATION: - return IB_WC_LOC_PROT_ERR; - case CCERR_ACCESS_VIOLATION: - return IB_WC_LOC_ACCESS_ERR; - case CCERR_TOTAL_LENGTH_TOO_BIG: - return IB_WC_LOC_LEN_ERR; - case CCERR_INVALID_WINDOW: - return IB_WC_MW_BIND_ERR; - default: - return IB_WC_GENERAL_ERR; - } -} - - -static inline int c2_poll_one(struct c2_dev *c2dev, - struct c2_cq *cq, struct ib_wc *entry) -{ - struct c2wr_ce *ce; - struct c2_qp *qp; - int is_recv = 0; - - ce = c2_mq_consume(&cq->mq); - if (!ce) { - return -EAGAIN; - } - - /* - * if the qp returned is null then this qp has already - * been freed and we are unable process the completion. - * try pulling the next message - */ - while ((qp = - (struct c2_qp *) (unsigned long) ce->qp_user_context) == NULL) { - c2_mq_free(&cq->mq); - ce = c2_mq_consume(&cq->mq); - if (!ce) - return -EAGAIN; - } - - entry->status = c2_cqe_status_to_openib(c2_wr_get_result(ce)); - entry->wr_id = ce->hdr.context; - entry->qp = &qp->ibqp; - entry->wc_flags = 0; - entry->slid = 0; - entry->sl = 0; - entry->src_qp = 0; - entry->dlid_path_bits = 0; - entry->pkey_index = 0; - - switch (c2_wr_get_id(ce)) { - case C2_WR_TYPE_SEND: - entry->opcode = IB_WC_SEND; - break; - case C2_WR_TYPE_RDMA_WRITE: - entry->opcode = IB_WC_RDMA_WRITE; - break; - case C2_WR_TYPE_RDMA_READ: - entry->opcode = IB_WC_RDMA_READ; - break; - case C2_WR_TYPE_RECV: - entry->byte_len = be32_to_cpu(ce->bytes_rcvd); - entry->opcode = IB_WC_RECV; - is_recv = 1; - break; - default: - break; - } - - /* consume the WQEs */ - if (is_recv) - c2_mq_lconsume(&qp->rq_mq, 1); - else - c2_mq_lconsume(&qp->sq_mq, - be32_to_cpu(c2_wr_get_wqe_count(ce)) + 1); - - /* free the message */ - c2_mq_free(&cq->mq); - - return 0; -} - -int c2_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) -{ - struct c2_dev *c2dev = to_c2dev(ibcq->device); - struct c2_cq *cq = to_c2cq(ibcq); - unsigned long flags; - int npolled, err; - - spin_lock_irqsave(&cq->lock, flags); - - for (npolled = 0; npolled < num_entries; ++npolled) { - - err = c2_poll_one(c2dev, cq, entry + npolled); - if (err) - break; - } - - spin_unlock_irqrestore(&cq->lock, flags); - - return npolled; -} - -int c2_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags notify_flags) -{ - struct c2_mq_shared __iomem *shared; - struct c2_cq *cq; - unsigned long flags; - int ret = 0; - - cq = to_c2cq(ibcq); - shared = cq->mq.peer; - - if ((notify_flags & IB_CQ_SOLICITED_MASK) == IB_CQ_NEXT_COMP) - writeb(C2_CQ_NOTIFICATION_TYPE_NEXT, &shared->notification_type); - else if ((notify_flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED) - writeb(C2_CQ_NOTIFICATION_TYPE_NEXT_SE, &shared->notification_type); - else - return -EINVAL; - - writeb(CQ_WAIT_FOR_DMA | CQ_ARMED, &shared->armed); - - /* - * Now read back shared->armed to make the PCI - * write synchronous. This is necessary for - * correct cq notification semantics. - */ - readb(&shared->armed); - - if (notify_flags & IB_CQ_REPORT_MISSED_EVENTS) { - spin_lock_irqsave(&cq->lock, flags); - ret = !c2_mq_empty(&cq->mq); - spin_unlock_irqrestore(&cq->lock, flags); - } - - return ret; -} - -static void c2_free_cq_buf(struct c2_dev *c2dev, struct c2_mq *mq) -{ - dma_free_coherent(&c2dev->pcidev->dev, mq->q_size * mq->msg_size, - mq->msg_pool.host, dma_unmap_addr(mq, mapping)); -} - -static int c2_alloc_cq_buf(struct c2_dev *c2dev, struct c2_mq *mq, - size_t q_size, size_t msg_size) -{ - u8 *pool_start; - - if (q_size > SIZE_MAX / msg_size) - return -EINVAL; - - pool_start = dma_alloc_coherent(&c2dev->pcidev->dev, q_size * msg_size, - &mq->host_dma, GFP_KERNEL); - if (!pool_start) - return -ENOMEM; - - c2_mq_rep_init(mq, - 0, /* index (currently unknown) */ - q_size, - msg_size, - pool_start, - NULL, /* peer (currently unknown) */ - C2_MQ_HOST_TARGET); - - dma_unmap_addr_set(mq, mapping, mq->host_dma); - - return 0; -} - -int c2_init_cq(struct c2_dev *c2dev, int entries, - struct c2_ucontext *ctx, struct c2_cq *cq) -{ - struct c2wr_cq_create_req wr; - struct c2wr_cq_create_rep *reply; - unsigned long peer_pa; - struct c2_vq_req *vq_req; - int err; - - might_sleep(); - - cq->ibcq.cqe = entries - 1; - cq->is_kernel = !ctx; - - /* Allocate a shared pointer */ - cq->mq.shared = c2_alloc_mqsp(c2dev, c2dev->kern_mqsp_pool, - &cq->mq.shared_dma, GFP_KERNEL); - if (!cq->mq.shared) - return -ENOMEM; - - /* Allocate pages for the message pool */ - err = c2_alloc_cq_buf(c2dev, &cq->mq, entries + 1, C2_CQ_MSG_SIZE); - if (err) - goto bail0; - - vq_req = vq_req_alloc(c2dev); - if (!vq_req) { - err = -ENOMEM; - goto bail1; - } - - memset(&wr, 0, sizeof(wr)); - c2_wr_set_id(&wr, CCWR_CQ_CREATE); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.msg_size = cpu_to_be32(cq->mq.msg_size); - wr.depth = cpu_to_be32(cq->mq.q_size); - wr.shared_ht = cpu_to_be64(cq->mq.shared_dma); - wr.msg_pool = cpu_to_be64(cq->mq.host_dma); - wr.user_context = (u64) (unsigned long) (cq); - - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail2; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail2; - - reply = (struct c2wr_cq_create_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) { - err = -ENOMEM; - goto bail2; - } - - if ((err = c2_errno(reply)) != 0) - goto bail3; - - cq->adapter_handle = reply->cq_handle; - cq->mq.index = be32_to_cpu(reply->mq_index); - - peer_pa = c2dev->pa + be32_to_cpu(reply->adapter_shared); - cq->mq.peer = ioremap_nocache(peer_pa, PAGE_SIZE); - if (!cq->mq.peer) { - err = -ENOMEM; - goto bail3; - } - - vq_repbuf_free(c2dev, reply); - vq_req_free(c2dev, vq_req); - - spin_lock_init(&cq->lock); - atomic_set(&cq->refcount, 1); - init_waitqueue_head(&cq->wait); - - /* - * Use the MQ index allocated by the adapter to - * store the CQ in the qptr_array - */ - cq->cqn = cq->mq.index; - c2dev->qptr_array[cq->cqn] = cq; - - return 0; - -bail3: - vq_repbuf_free(c2dev, reply); -bail2: - vq_req_free(c2dev, vq_req); -bail1: - c2_free_cq_buf(c2dev, &cq->mq); -bail0: - c2_free_mqsp(cq->mq.shared); - - return err; -} - -void c2_free_cq(struct c2_dev *c2dev, struct c2_cq *cq) -{ - int err; - struct c2_vq_req *vq_req; - struct c2wr_cq_destroy_req wr; - struct c2wr_cq_destroy_rep *reply; - - might_sleep(); - - /* Clear CQ from the qptr array */ - spin_lock_irq(&c2dev->lock); - c2dev->qptr_array[cq->mq.index] = NULL; - atomic_dec(&cq->refcount); - spin_unlock_irq(&c2dev->lock); - - wait_event(cq->wait, !atomic_read(&cq->refcount)); - - vq_req = vq_req_alloc(c2dev); - if (!vq_req) { - goto bail0; - } - - memset(&wr, 0, sizeof(wr)); - c2_wr_set_id(&wr, CCWR_CQ_DESTROY); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.cq_handle = cq->adapter_handle; - - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail1; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail1; - - reply = (struct c2wr_cq_destroy_rep *) (unsigned long) (vq_req->reply_msg); - if (reply) - vq_repbuf_free(c2dev, reply); -bail1: - vq_req_free(c2dev, vq_req); -bail0: - if (cq->is_kernel) { - c2_free_cq_buf(c2dev, &cq->mq); - } - - return; -} diff --git a/drivers/staging/rdma/amso1100/c2_intr.c b/drivers/staging/rdma/amso1100/c2_intr.c deleted file mode 100644 index 74b32a971124..000000000000 --- a/drivers/staging/rdma/amso1100/c2_intr.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "c2.h" -#include -#include "c2_vq.h" - -static void handle_mq(struct c2_dev *c2dev, u32 index); -static void handle_vq(struct c2_dev *c2dev, u32 mq_index); - -/* - * Handle RNIC interrupts - */ -void c2_rnic_interrupt(struct c2_dev *c2dev) -{ - unsigned int mq_index; - - while (c2dev->hints_read != be16_to_cpu(*c2dev->hint_count)) { - mq_index = readl(c2dev->regs + PCI_BAR0_HOST_HINT); - if (mq_index & 0x80000000) { - break; - } - - c2dev->hints_read++; - handle_mq(c2dev, mq_index); - } - -} - -/* - * Top level MQ handler - */ -static void handle_mq(struct c2_dev *c2dev, u32 mq_index) -{ - if (c2dev->qptr_array[mq_index] == NULL) { - pr_debug("handle_mq: stray activity for mq_index=%d\n", - mq_index); - return; - } - - switch (mq_index) { - case (0): - /* - * An index of 0 in the activity queue - * indicates the req vq now has messages - * available... - * - * Wake up any waiters waiting on req VQ - * message availability. - */ - wake_up(&c2dev->req_vq_wo); - break; - case (1): - handle_vq(c2dev, mq_index); - break; - case (2): - /* We have to purge the VQ in case there are pending - * accept reply requests that would result in the - * generation of an ESTABLISHED event. If we don't - * generate these first, a CLOSE event could end up - * being delivered before the ESTABLISHED event. - */ - handle_vq(c2dev, 1); - - c2_ae_event(c2dev, mq_index); - break; - default: - /* There is no event synchronization between CQ events - * and AE or CM events. In fact, CQE could be - * delivered for all of the I/O up to and including the - * FLUSH for a peer disconenct prior to the ESTABLISHED - * event being delivered to the app. The reason for this - * is that CM events are delivered on a thread, while AE - * and CM events are delivered on interrupt context. - */ - c2_cq_event(c2dev, mq_index); - break; - } - - return; -} - -/* - * Handles verbs WR replies. - */ -static void handle_vq(struct c2_dev *c2dev, u32 mq_index) -{ - void *adapter_msg, *reply_msg; - struct c2wr_hdr *host_msg; - struct c2wr_hdr tmp; - struct c2_mq *reply_vq; - struct c2_vq_req *req; - struct iw_cm_event cm_event; - int err; - - reply_vq = c2dev->qptr_array[mq_index]; - - /* - * get next msg from mq_index into adapter_msg. - * don't free it yet. - */ - adapter_msg = c2_mq_consume(reply_vq); - if (adapter_msg == NULL) { - return; - } - - host_msg = vq_repbuf_alloc(c2dev); - - /* - * If we can't get a host buffer, then we'll still - * wakeup the waiter, we just won't give him the msg. - * It is assumed the waiter will deal with this... - */ - if (!host_msg) { - pr_debug("handle_vq: no repbufs!\n"); - - /* - * just copy the WR header into a local variable. - * this allows us to still demux on the context - */ - host_msg = &tmp; - memcpy(host_msg, adapter_msg, sizeof(tmp)); - reply_msg = NULL; - } else { - memcpy(host_msg, adapter_msg, reply_vq->msg_size); - reply_msg = host_msg; - } - - /* - * consume the msg from the MQ - */ - c2_mq_free(reply_vq); - - /* - * wakeup the waiter. - */ - req = (struct c2_vq_req *) (unsigned long) host_msg->context; - if (req == NULL) { - /* - * We should never get here, as the adapter should - * never send us a reply that we're not expecting. - */ - if (reply_msg != NULL) - vq_repbuf_free(c2dev, host_msg); - pr_debug("handle_vq: UNEXPECTEDLY got NULL req\n"); - return; - } - - if (reply_msg) - err = c2_errno(reply_msg); - else - err = -ENOMEM; - - if (!err) switch (req->event) { - case IW_CM_EVENT_ESTABLISHED: - c2_set_qp_state(req->qp, - C2_QP_STATE_RTS); - /* - * Until ird/ord negotiation via MPAv2 support is added, send - * max supported values - */ - cm_event.ird = cm_event.ord = 128; - case IW_CM_EVENT_CLOSE: - - /* - * Move the QP to RTS if this is - * the established event - */ - cm_event.event = req->event; - cm_event.status = 0; - cm_event.local_addr = req->cm_id->local_addr; - cm_event.remote_addr = req->cm_id->remote_addr; - cm_event.private_data = NULL; - cm_event.private_data_len = 0; - req->cm_id->event_handler(req->cm_id, &cm_event); - break; - default: - break; - } - - req->reply_msg = (u64) (unsigned long) (reply_msg); - atomic_set(&req->reply_ready, 1); - wake_up(&req->wait_object); - - /* - * If the request was cancelled, then this put will - * free the vq_req memory...and reply_msg!!! - */ - vq_req_put(c2dev, req); -} diff --git a/drivers/staging/rdma/amso1100/c2_mm.c b/drivers/staging/rdma/amso1100/c2_mm.c deleted file mode 100644 index 25081e2913de..000000000000 --- a/drivers/staging/rdma/amso1100/c2_mm.c +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include - -#include "c2.h" -#include "c2_vq.h" - -#define PBL_VIRT 1 -#define PBL_PHYS 2 - -/* - * Send all the PBL messages to convey the remainder of the PBL - * Wait for the adapter's reply on the last one. - * This is indicated by setting the MEM_PBL_COMPLETE in the flags. - * - * NOTE: vq_req is _not_ freed by this function. The VQ Host - * Reply buffer _is_ freed by this function. - */ -static int -send_pbl_messages(struct c2_dev *c2dev, __be32 stag_index, - unsigned long va, u32 pbl_depth, - struct c2_vq_req *vq_req, int pbl_type) -{ - u32 pbe_count; /* amt that fits in a PBL msg */ - u32 count; /* amt in this PBL MSG. */ - struct c2wr_nsmr_pbl_req *wr; /* PBL WR ptr */ - struct c2wr_nsmr_pbl_rep *reply; /* reply ptr */ - int err, pbl_virt, pbl_index, i; - - switch (pbl_type) { - case PBL_VIRT: - pbl_virt = 1; - break; - case PBL_PHYS: - pbl_virt = 0; - break; - default: - return -EINVAL; - break; - } - - pbe_count = (c2dev->req_vq.msg_size - - sizeof(struct c2wr_nsmr_pbl_req)) / sizeof(u64); - wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL); - if (!wr) { - return -ENOMEM; - } - c2_wr_set_id(wr, CCWR_NSMR_PBL); - - /* - * Only the last PBL message will generate a reply from the verbs, - * so we set the context to 0 indicating there is no kernel verbs - * handler blocked awaiting this reply. - */ - wr->hdr.context = 0; - wr->rnic_handle = c2dev->adapter_handle; - wr->stag_index = stag_index; /* already swapped */ - wr->flags = 0; - pbl_index = 0; - while (pbl_depth) { - count = min(pbe_count, pbl_depth); - wr->addrs_length = cpu_to_be32(count); - - /* - * If this is the last message, then reference the - * vq request struct cuz we're gonna wait for a reply. - * also make this PBL msg as the last one. - */ - if (count == pbl_depth) { - /* - * reference the request struct. dereferenced in the - * int handler. - */ - vq_req_get(c2dev, vq_req); - wr->flags = cpu_to_be32(MEM_PBL_COMPLETE); - - /* - * This is the last PBL message. - * Set the context to our VQ Request Object so we can - * wait for the reply. - */ - wr->hdr.context = (unsigned long) vq_req; - } - - /* - * If pbl_virt is set then va is a virtual address - * that describes a virtually contiguous memory - * allocation. The wr needs the start of each virtual page - * to be converted to the corresponding physical address - * of the page. If pbl_virt is not set then va is an array - * of physical addresses and there is no conversion to do. - * Just fill in the wr with what is in the array. - */ - for (i = 0; i < count; i++) { - if (pbl_virt) { - va += PAGE_SIZE; - } else { - wr->paddrs[i] = - cpu_to_be64(((u64 *)va)[pbl_index + i]); - } - } - - /* - * Send WR to adapter - */ - err = vq_send_wr(c2dev, (union c2wr *) wr); - if (err) { - if (count <= pbe_count) { - vq_req_put(c2dev, vq_req); - } - goto bail0; - } - pbl_depth -= count; - pbl_index += count; - } - - /* - * Now wait for the reply... - */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) { - goto bail0; - } - - /* - * Process reply - */ - reply = (struct c2wr_nsmr_pbl_rep *) (unsigned long) vq_req->reply_msg; - if (!reply) { - err = -ENOMEM; - goto bail0; - } - - err = c2_errno(reply); - - vq_repbuf_free(c2dev, reply); -bail0: - kfree(wr); - return err; -} - -#define C2_PBL_MAX_DEPTH 131072 -int -c2_nsmr_register_phys_kern(struct c2_dev *c2dev, u64 *addr_list, - int page_size, int pbl_depth, u32 length, - u32 offset, u64 *va, enum c2_acf acf, - struct c2_mr *mr) -{ - struct c2_vq_req *vq_req; - struct c2wr_nsmr_register_req *wr; - struct c2wr_nsmr_register_rep *reply; - u16 flags; - int i, pbe_count, count; - int err; - - if (!va || !length || !addr_list || !pbl_depth) - return -EINTR; - - /* - * Verify PBL depth is within rnic max - */ - if (pbl_depth > C2_PBL_MAX_DEPTH) { - return -EINTR; - } - - /* - * allocate verbs request object - */ - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL); - if (!wr) { - err = -ENOMEM; - goto bail0; - } - - /* - * build the WR - */ - c2_wr_set_id(wr, CCWR_NSMR_REGISTER); - wr->hdr.context = (unsigned long) vq_req; - wr->rnic_handle = c2dev->adapter_handle; - - flags = (acf | MEM_VA_BASED | MEM_REMOTE); - - /* - * compute how many pbes can fit in the message - */ - pbe_count = (c2dev->req_vq.msg_size - - sizeof(struct c2wr_nsmr_register_req)) / sizeof(u64); - - if (pbl_depth <= pbe_count) { - flags |= MEM_PBL_COMPLETE; - } - wr->flags = cpu_to_be16(flags); - wr->stag_key = 0; //stag_key; - wr->va = cpu_to_be64(*va); - wr->pd_id = mr->pd->pd_id; - wr->pbe_size = cpu_to_be32(page_size); - wr->length = cpu_to_be32(length); - wr->pbl_depth = cpu_to_be32(pbl_depth); - wr->fbo = cpu_to_be32(offset); - count = min(pbl_depth, pbe_count); - wr->addrs_length = cpu_to_be32(count); - - /* - * fill out the PBL for this message - */ - for (i = 0; i < count; i++) { - wr->paddrs[i] = cpu_to_be64(addr_list[i]); - } - - /* - * regerence the request struct - */ - vq_req_get(c2dev, vq_req); - - /* - * send the WR to the adapter - */ - err = vq_send_wr(c2dev, (union c2wr *) wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail1; - } - - /* - * wait for reply from adapter - */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) { - goto bail1; - } - - /* - * process reply - */ - reply = - (struct c2wr_nsmr_register_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) { - err = -ENOMEM; - goto bail1; - } - if ((err = c2_errno(reply))) { - goto bail2; - } - //*p_pb_entries = be32_to_cpu(reply->pbl_depth); - mr->ibmr.lkey = mr->ibmr.rkey = be32_to_cpu(reply->stag_index); - vq_repbuf_free(c2dev, reply); - - /* - * if there are still more PBEs we need to send them to - * the adapter and wait for a reply on the final one. - * reuse vq_req for this purpose. - */ - pbl_depth -= count; - if (pbl_depth) { - - vq_req->reply_msg = (unsigned long) NULL; - atomic_set(&vq_req->reply_ready, 0); - err = send_pbl_messages(c2dev, - cpu_to_be32(mr->ibmr.lkey), - (unsigned long) &addr_list[i], - pbl_depth, vq_req, PBL_PHYS); - if (err) { - goto bail1; - } - } - - vq_req_free(c2dev, vq_req); - kfree(wr); - - return err; - -bail2: - vq_repbuf_free(c2dev, reply); -bail1: - kfree(wr); -bail0: - vq_req_free(c2dev, vq_req); - return err; -} - -int c2_stag_dealloc(struct c2_dev *c2dev, u32 stag_index) -{ - struct c2_vq_req *vq_req; /* verbs request object */ - struct c2wr_stag_dealloc_req wr; /* work request */ - struct c2wr_stag_dealloc_rep *reply; /* WR reply */ - int err; - - - /* - * allocate verbs request object - */ - vq_req = vq_req_alloc(c2dev); - if (!vq_req) { - return -ENOMEM; - } - - /* - * Build the WR - */ - c2_wr_set_id(&wr, CCWR_STAG_DEALLOC); - wr.hdr.context = (u64) (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.stag_index = cpu_to_be32(stag_index); - - /* - * reference the request struct. dereferenced in the int handler. - */ - vq_req_get(c2dev, vq_req); - - /* - * Send WR to adapter - */ - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - /* - * Wait for reply from adapter - */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) { - goto bail0; - } - - /* - * Process reply - */ - reply = (struct c2wr_stag_dealloc_rep *) (unsigned long) vq_req->reply_msg; - if (!reply) { - err = -ENOMEM; - goto bail0; - } - - err = c2_errno(reply); - - vq_repbuf_free(c2dev, reply); -bail0: - vq_req_free(c2dev, vq_req); - return err; -} diff --git a/drivers/staging/rdma/amso1100/c2_mq.c b/drivers/staging/rdma/amso1100/c2_mq.c deleted file mode 100644 index 7827fb8bdb10..000000000000 --- a/drivers/staging/rdma/amso1100/c2_mq.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "c2.h" -#include "c2_mq.h" - -void *c2_mq_alloc(struct c2_mq *q) -{ - BUG_ON(q->magic != C2_MQ_MAGIC); - BUG_ON(q->type != C2_MQ_ADAPTER_TARGET); - - if (c2_mq_full(q)) { - return NULL; - } else { -#ifdef DEBUG - struct c2wr_hdr *m = - (struct c2wr_hdr *) (q->msg_pool.host + q->priv * q->msg_size); -#ifdef CCMSGMAGIC - BUG_ON(m->magic != be32_to_cpu(~CCWR_MAGIC)); - m->magic = cpu_to_be32(CCWR_MAGIC); -#endif - return m; -#else - return q->msg_pool.host + q->priv * q->msg_size; -#endif - } -} - -void c2_mq_produce(struct c2_mq *q) -{ - BUG_ON(q->magic != C2_MQ_MAGIC); - BUG_ON(q->type != C2_MQ_ADAPTER_TARGET); - - if (!c2_mq_full(q)) { - q->priv = (q->priv + 1) % q->q_size; - q->hint_count++; - /* Update peer's offset. */ - __raw_writew((__force u16) cpu_to_be16(q->priv), &q->peer->shared); - } -} - -void *c2_mq_consume(struct c2_mq *q) -{ - BUG_ON(q->magic != C2_MQ_MAGIC); - BUG_ON(q->type != C2_MQ_HOST_TARGET); - - if (c2_mq_empty(q)) { - return NULL; - } else { -#ifdef DEBUG - struct c2wr_hdr *m = (struct c2wr_hdr *) - (q->msg_pool.host + q->priv * q->msg_size); -#ifdef CCMSGMAGIC - BUG_ON(m->magic != be32_to_cpu(CCWR_MAGIC)); -#endif - return m; -#else - return q->msg_pool.host + q->priv * q->msg_size; -#endif - } -} - -void c2_mq_free(struct c2_mq *q) -{ - BUG_ON(q->magic != C2_MQ_MAGIC); - BUG_ON(q->type != C2_MQ_HOST_TARGET); - - if (!c2_mq_empty(q)) { - -#ifdef CCMSGMAGIC - { - struct c2wr_hdr __iomem *m = (struct c2wr_hdr __iomem *) - (q->msg_pool.adapter + q->priv * q->msg_size); - __raw_writel(cpu_to_be32(~CCWR_MAGIC), &m->magic); - } -#endif - q->priv = (q->priv + 1) % q->q_size; - /* Update peer's offset. */ - __raw_writew((__force u16) cpu_to_be16(q->priv), &q->peer->shared); - } -} - - -void c2_mq_lconsume(struct c2_mq *q, u32 wqe_count) -{ - BUG_ON(q->magic != C2_MQ_MAGIC); - BUG_ON(q->type != C2_MQ_ADAPTER_TARGET); - - while (wqe_count--) { - BUG_ON(c2_mq_empty(q)); - *q->shared = cpu_to_be16((be16_to_cpu(*q->shared)+1) % q->q_size); - } -} - -#if 0 -u32 c2_mq_count(struct c2_mq *q) -{ - s32 count; - - if (q->type == C2_MQ_HOST_TARGET) - count = be16_to_cpu(*q->shared) - q->priv; - else - count = q->priv - be16_to_cpu(*q->shared); - - if (count < 0) - count += q->q_size; - - return (u32) count; -} -#endif /* 0 */ - -void c2_mq_req_init(struct c2_mq *q, u32 index, u32 q_size, u32 msg_size, - u8 __iomem *pool_start, u16 __iomem *peer, u32 type) -{ - BUG_ON(!q->shared); - - /* This code assumes the byte swapping has already been done! */ - q->index = index; - q->q_size = q_size; - q->msg_size = msg_size; - q->msg_pool.adapter = pool_start; - q->peer = (struct c2_mq_shared __iomem *) peer; - q->magic = C2_MQ_MAGIC; - q->type = type; - q->priv = 0; - q->hint_count = 0; - return; -} - -void c2_mq_rep_init(struct c2_mq *q, u32 index, u32 q_size, u32 msg_size, - u8 *pool_start, u16 __iomem *peer, u32 type) -{ - BUG_ON(!q->shared); - - /* This code assumes the byte swapping has already been done! */ - q->index = index; - q->q_size = q_size; - q->msg_size = msg_size; - q->msg_pool.host = pool_start; - q->peer = (struct c2_mq_shared __iomem *) peer; - q->magic = C2_MQ_MAGIC; - q->type = type; - q->priv = 0; - q->hint_count = 0; - return; -} diff --git a/drivers/staging/rdma/amso1100/c2_mq.h b/drivers/staging/rdma/amso1100/c2_mq.h deleted file mode 100644 index 8e1b4d13409e..000000000000 --- a/drivers/staging/rdma/amso1100/c2_mq.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _C2_MQ_H_ -#define _C2_MQ_H_ -#include -#include -#include "c2_wr.h" - -enum c2_shared_regs { - - C2_SHARED_ARMED = 0x10, - C2_SHARED_NOTIFY = 0x18, - C2_SHARED_SHARED = 0x40, -}; - -struct c2_mq_shared { - u16 unused1; - u8 armed; - u8 notification_type; - u32 unused2; - u16 shared; - /* Pad to 64 bytes. */ - u8 pad[64 - sizeof(u16) - 2 * sizeof(u8) - sizeof(u32) - sizeof(u16)]; -}; - -enum c2_mq_type { - C2_MQ_HOST_TARGET = 1, - C2_MQ_ADAPTER_TARGET = 2, -}; - -/* - * c2_mq_t is for kernel-mode MQs like the VQs Cand the AEQ. - * c2_user_mq_t (which is the same format) is for user-mode MQs... - */ -#define C2_MQ_MAGIC 0x4d512020 /* 'MQ ' */ -struct c2_mq { - u32 magic; - union { - u8 *host; - u8 __iomem *adapter; - } msg_pool; - dma_addr_t host_dma; - DEFINE_DMA_UNMAP_ADDR(mapping); - u16 hint_count; - u16 priv; - struct c2_mq_shared __iomem *peer; - __be16 *shared; - dma_addr_t shared_dma; - u32 q_size; - u32 msg_size; - u32 index; - enum c2_mq_type type; -}; - -static __inline__ int c2_mq_empty(struct c2_mq *q) -{ - return q->priv == be16_to_cpu(*q->shared); -} - -static __inline__ int c2_mq_full(struct c2_mq *q) -{ - return q->priv == (be16_to_cpu(*q->shared) + q->q_size - 1) % q->q_size; -} - -void c2_mq_lconsume(struct c2_mq *q, u32 wqe_count); -void *c2_mq_alloc(struct c2_mq *q); -void c2_mq_produce(struct c2_mq *q); -void *c2_mq_consume(struct c2_mq *q); -void c2_mq_free(struct c2_mq *q); -void c2_mq_req_init(struct c2_mq *q, u32 index, u32 q_size, u32 msg_size, - u8 __iomem *pool_start, u16 __iomem *peer, u32 type); -void c2_mq_rep_init(struct c2_mq *q, u32 index, u32 q_size, u32 msg_size, - u8 *pool_start, u16 __iomem *peer, u32 type); - -#endif /* _C2_MQ_H_ */ diff --git a/drivers/staging/rdma/amso1100/c2_pd.c b/drivers/staging/rdma/amso1100/c2_pd.c deleted file mode 100644 index f3e81dc357bb..000000000000 --- a/drivers/staging/rdma/amso1100/c2_pd.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2004 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include - -#include "c2.h" -#include "c2_provider.h" - -int c2_pd_alloc(struct c2_dev *c2dev, int privileged, struct c2_pd *pd) -{ - u32 obj; - int ret = 0; - - spin_lock(&c2dev->pd_table.lock); - obj = find_next_zero_bit(c2dev->pd_table.table, c2dev->pd_table.max, - c2dev->pd_table.last); - if (obj >= c2dev->pd_table.max) - obj = find_first_zero_bit(c2dev->pd_table.table, - c2dev->pd_table.max); - if (obj < c2dev->pd_table.max) { - pd->pd_id = obj; - __set_bit(obj, c2dev->pd_table.table); - c2dev->pd_table.last = obj+1; - if (c2dev->pd_table.last >= c2dev->pd_table.max) - c2dev->pd_table.last = 0; - } else - ret = -ENOMEM; - spin_unlock(&c2dev->pd_table.lock); - return ret; -} - -void c2_pd_free(struct c2_dev *c2dev, struct c2_pd *pd) -{ - spin_lock(&c2dev->pd_table.lock); - __clear_bit(pd->pd_id, c2dev->pd_table.table); - spin_unlock(&c2dev->pd_table.lock); -} - -int c2_init_pd_table(struct c2_dev *c2dev) -{ - - c2dev->pd_table.last = 0; - c2dev->pd_table.max = c2dev->props.max_pd; - spin_lock_init(&c2dev->pd_table.lock); - c2dev->pd_table.table = kmalloc(BITS_TO_LONGS(c2dev->props.max_pd) * - sizeof(long), GFP_KERNEL); - if (!c2dev->pd_table.table) - return -ENOMEM; - bitmap_zero(c2dev->pd_table.table, c2dev->props.max_pd); - return 0; -} - -void c2_cleanup_pd_table(struct c2_dev *c2dev) -{ - kfree(c2dev->pd_table.table); -} diff --git a/drivers/staging/rdma/amso1100/c2_provider.c b/drivers/staging/rdma/amso1100/c2_provider.c deleted file mode 100644 index de8d10e1bde3..000000000000 --- a/drivers/staging/rdma/amso1100/c2_provider.c +++ /dev/null @@ -1,862 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include "c2.h" -#include "c2_provider.h" -#include "c2_user.h" - -static int c2_query_device(struct ib_device *ibdev, struct ib_device_attr *props, - struct ib_udata *uhw) -{ - struct c2_dev *c2dev = to_c2dev(ibdev); - - pr_debug("%s:%u\n", __func__, __LINE__); - - if (uhw->inlen || uhw->outlen) - return -EINVAL; - - *props = c2dev->props; - return 0; -} - -static int c2_query_port(struct ib_device *ibdev, - u8 port, struct ib_port_attr *props) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - - props->max_mtu = IB_MTU_4096; - props->lid = 0; - props->lmc = 0; - props->sm_lid = 0; - props->sm_sl = 0; - props->state = IB_PORT_ACTIVE; - props->phys_state = 0; - props->port_cap_flags = - IB_PORT_CM_SUP | - IB_PORT_REINIT_SUP | - IB_PORT_VENDOR_CLASS_SUP | IB_PORT_BOOT_MGMT_SUP; - props->gid_tbl_len = 1; - props->pkey_tbl_len = 1; - props->qkey_viol_cntr = 0; - props->active_width = 1; - props->active_speed = IB_SPEED_SDR; - - return 0; -} - -static int c2_query_pkey(struct ib_device *ibdev, - u8 port, u16 index, u16 * pkey) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - *pkey = 0; - return 0; -} - -static int c2_query_gid(struct ib_device *ibdev, u8 port, - int index, union ib_gid *gid) -{ - struct c2_dev *c2dev = to_c2dev(ibdev); - - pr_debug("%s:%u\n", __func__, __LINE__); - memset(&(gid->raw[0]), 0, sizeof(gid->raw)); - memcpy(&(gid->raw[0]), c2dev->pseudo_netdev->dev_addr, 6); - - return 0; -} - -/* Allocate the user context data structure. This keeps track - * of all objects associated with a particular user-mode client. - */ -static struct ib_ucontext *c2_alloc_ucontext(struct ib_device *ibdev, - struct ib_udata *udata) -{ - struct c2_ucontext *context; - - pr_debug("%s:%u\n", __func__, __LINE__); - context = kmalloc(sizeof(*context), GFP_KERNEL); - if (!context) - return ERR_PTR(-ENOMEM); - - return &context->ibucontext; -} - -static int c2_dealloc_ucontext(struct ib_ucontext *context) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - kfree(context); - return 0; -} - -static int c2_mmap_uar(struct ib_ucontext *context, struct vm_area_struct *vma) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - return -ENOSYS; -} - -static struct ib_pd *c2_alloc_pd(struct ib_device *ibdev, - struct ib_ucontext *context, - struct ib_udata *udata) -{ - struct c2_pd *pd; - int err; - - pr_debug("%s:%u\n", __func__, __LINE__); - - pd = kmalloc(sizeof(*pd), GFP_KERNEL); - if (!pd) - return ERR_PTR(-ENOMEM); - - err = c2_pd_alloc(to_c2dev(ibdev), !context, pd); - if (err) { - kfree(pd); - return ERR_PTR(err); - } - - if (context) { - if (ib_copy_to_udata(udata, &pd->pd_id, sizeof(__u32))) { - c2_pd_free(to_c2dev(ibdev), pd); - kfree(pd); - return ERR_PTR(-EFAULT); - } - } - - return &pd->ibpd; -} - -static int c2_dealloc_pd(struct ib_pd *pd) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - c2_pd_free(to_c2dev(pd->device), to_c2pd(pd)); - kfree(pd); - - return 0; -} - -static struct ib_ah *c2_ah_create(struct ib_pd *pd, struct ib_ah_attr *ah_attr) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - return ERR_PTR(-ENOSYS); -} - -static int c2_ah_destroy(struct ib_ah *ah) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - return -ENOSYS; -} - -static void c2_add_ref(struct ib_qp *ibqp) -{ - struct c2_qp *qp; - BUG_ON(!ibqp); - qp = to_c2qp(ibqp); - atomic_inc(&qp->refcount); -} - -static void c2_rem_ref(struct ib_qp *ibqp) -{ - struct c2_qp *qp; - BUG_ON(!ibqp); - qp = to_c2qp(ibqp); - if (atomic_dec_and_test(&qp->refcount)) - wake_up(&qp->wait); -} - -struct ib_qp *c2_get_qp(struct ib_device *device, int qpn) -{ - struct c2_dev* c2dev = to_c2dev(device); - struct c2_qp *qp; - - qp = c2_find_qpn(c2dev, qpn); - pr_debug("%s Returning QP=%p for QPN=%d, device=%p, refcount=%d\n", - __func__, qp, qpn, device, - (qp?atomic_read(&qp->refcount):0)); - - return (qp?&qp->ibqp:NULL); -} - -static struct ib_qp *c2_create_qp(struct ib_pd *pd, - struct ib_qp_init_attr *init_attr, - struct ib_udata *udata) -{ - struct c2_qp *qp; - int err; - - pr_debug("%s:%u\n", __func__, __LINE__); - - if (init_attr->create_flags) - return ERR_PTR(-EINVAL); - - switch (init_attr->qp_type) { - case IB_QPT_RC: - qp = kzalloc(sizeof(*qp), GFP_KERNEL); - if (!qp) { - pr_debug("%s: Unable to allocate QP\n", __func__); - return ERR_PTR(-ENOMEM); - } - spin_lock_init(&qp->lock); - if (pd->uobject) { - /* userspace specific */ - } - - err = c2_alloc_qp(to_c2dev(pd->device), - to_c2pd(pd), init_attr, qp); - - if (err && pd->uobject) { - /* userspace specific */ - } - - break; - default: - pr_debug("%s: Invalid QP type: %d\n", __func__, - init_attr->qp_type); - return ERR_PTR(-EINVAL); - } - - if (err) { - kfree(qp); - return ERR_PTR(err); - } - - return &qp->ibqp; -} - -static int c2_destroy_qp(struct ib_qp *ib_qp) -{ - struct c2_qp *qp = to_c2qp(ib_qp); - - pr_debug("%s:%u qp=%p,qp->state=%d\n", - __func__, __LINE__, ib_qp, qp->state); - c2_free_qp(to_c2dev(ib_qp->device), qp); - kfree(qp); - return 0; -} - -static struct ib_cq *c2_create_cq(struct ib_device *ibdev, - const struct ib_cq_init_attr *attr, - struct ib_ucontext *context, - struct ib_udata *udata) -{ - int entries = attr->cqe; - struct c2_cq *cq; - int err; - - if (attr->flags) - return ERR_PTR(-EINVAL); - - cq = kmalloc(sizeof(*cq), GFP_KERNEL); - if (!cq) { - pr_debug("%s: Unable to allocate CQ\n", __func__); - return ERR_PTR(-ENOMEM); - } - - err = c2_init_cq(to_c2dev(ibdev), entries, NULL, cq); - if (err) { - pr_debug("%s: error initializing CQ\n", __func__); - kfree(cq); - return ERR_PTR(err); - } - - return &cq->ibcq; -} - -static int c2_destroy_cq(struct ib_cq *ib_cq) -{ - struct c2_cq *cq = to_c2cq(ib_cq); - - pr_debug("%s:%u\n", __func__, __LINE__); - - c2_free_cq(to_c2dev(ib_cq->device), cq); - kfree(cq); - - return 0; -} - -static inline u32 c2_convert_access(int acc) -{ - return (acc & IB_ACCESS_REMOTE_WRITE ? C2_ACF_REMOTE_WRITE : 0) | - (acc & IB_ACCESS_REMOTE_READ ? C2_ACF_REMOTE_READ : 0) | - (acc & IB_ACCESS_LOCAL_WRITE ? C2_ACF_LOCAL_WRITE : 0) | - C2_ACF_LOCAL_READ | C2_ACF_WINDOW_BIND; -} - -static struct ib_mr *c2_get_dma_mr(struct ib_pd *pd, int acc) -{ - struct c2_mr *mr; - u64 *page_list; - const u32 total_len = 0xffffffff; /* AMSO1100 limit */ - int err, page_shift, pbl_depth, i; - u64 kva = 0; - - pr_debug("%s:%u\n", __func__, __LINE__); - - /* - * This is a map of all phy mem...use a 32k page_shift. - */ - page_shift = PAGE_SHIFT + 3; - pbl_depth = ALIGN(total_len, BIT(page_shift)) >> page_shift; - - page_list = vmalloc(sizeof(u64) * pbl_depth); - if (!page_list) { - pr_debug("couldn't vmalloc page_list of size %zd\n", - (sizeof(u64) * pbl_depth)); - return ERR_PTR(-ENOMEM); - } - - for (i = 0; i < pbl_depth; i++) - page_list[i] = (i << page_shift); - - mr = kmalloc(sizeof(*mr), GFP_KERNEL); - if (!mr) { - vfree(page_list); - return ERR_PTR(-ENOMEM); - } - - mr->pd = to_c2pd(pd); - mr->umem = NULL; - pr_debug("%s - page shift %d, pbl_depth %d, total_len %u, " - "*iova_start %llx, first pa %llx, last pa %llx\n", - __func__, page_shift, pbl_depth, total_len, - (unsigned long long) kva, - (unsigned long long) page_list[0], - (unsigned long long) page_list[pbl_depth-1]); - err = c2_nsmr_register_phys_kern(to_c2dev(pd->device), page_list, - BIT(page_shift), pbl_depth, - total_len, 0, &kva, - c2_convert_access(acc), mr); - vfree(page_list); - if (err) { - kfree(mr); - return ERR_PTR(err); - } - - return &mr->ibmr; -} - -static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt, int acc, struct ib_udata *udata) -{ - u64 *pages; - u64 kva = 0; - int shift, n, len; - int i, k, entry; - int err = 0; - struct scatterlist *sg; - struct c2_pd *c2pd = to_c2pd(pd); - struct c2_mr *c2mr; - - pr_debug("%s:%u\n", __func__, __LINE__); - - c2mr = kmalloc(sizeof(*c2mr), GFP_KERNEL); - if (!c2mr) - return ERR_PTR(-ENOMEM); - c2mr->pd = c2pd; - - c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0); - if (IS_ERR(c2mr->umem)) { - err = PTR_ERR(c2mr->umem); - kfree(c2mr); - return ERR_PTR(err); - } - - shift = ffs(c2mr->umem->page_size) - 1; - n = c2mr->umem->nmap; - - pages = kmalloc_array(n, sizeof(u64), GFP_KERNEL); - if (!pages) { - err = -ENOMEM; - goto err; - } - - i = 0; - for_each_sg(c2mr->umem->sg_head.sgl, sg, c2mr->umem->nmap, entry) { - len = sg_dma_len(sg) >> shift; - for (k = 0; k < len; ++k) { - pages[i++] = - sg_dma_address(sg) + - (c2mr->umem->page_size * k); - } - } - - kva = virt; - err = c2_nsmr_register_phys_kern(to_c2dev(pd->device), - pages, - c2mr->umem->page_size, - i, - length, - ib_umem_offset(c2mr->umem), - &kva, - c2_convert_access(acc), - c2mr); - kfree(pages); - if (err) - goto err; - return &c2mr->ibmr; - -err: - ib_umem_release(c2mr->umem); - kfree(c2mr); - return ERR_PTR(err); -} - -static int c2_dereg_mr(struct ib_mr *ib_mr) -{ - struct c2_mr *mr = to_c2mr(ib_mr); - int err; - - pr_debug("%s:%u\n", __func__, __LINE__); - - err = c2_stag_dealloc(to_c2dev(ib_mr->device), ib_mr->lkey); - if (err) - pr_debug("c2_stag_dealloc failed: %d\n", err); - else { - if (mr->umem) - ib_umem_release(mr->umem); - kfree(mr); - } - - return err; -} - -static ssize_t show_rev(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct c2_dev *c2dev = container_of(dev, struct c2_dev, ibdev.dev); - pr_debug("%s:%u\n", __func__, __LINE__); - return sprintf(buf, "%x\n", c2dev->props.hw_ver); -} - -static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct c2_dev *c2dev = container_of(dev, struct c2_dev, ibdev.dev); - pr_debug("%s:%u\n", __func__, __LINE__); - return sprintf(buf, "%x.%x.%x\n", - (int) (c2dev->props.fw_ver >> 32), - (int) (c2dev->props.fw_ver >> 16) & 0xffff, - (int) (c2dev->props.fw_ver & 0xffff)); -} - -static ssize_t show_hca(struct device *dev, struct device_attribute *attr, - char *buf) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - return sprintf(buf, "AMSO1100\n"); -} - -static ssize_t show_board(struct device *dev, struct device_attribute *attr, - char *buf) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - return sprintf(buf, "%.*s\n", 32, "AMSO1100 Board ID"); -} - -static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL); -static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL); -static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL); -static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL); - -static struct device_attribute *c2_dev_attributes[] = { - &dev_attr_hw_rev, - &dev_attr_fw_ver, - &dev_attr_hca_type, - &dev_attr_board_id -}; - -static int c2_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, - int attr_mask, struct ib_udata *udata) -{ - int err; - - err = - c2_qp_modify(to_c2dev(ibqp->device), to_c2qp(ibqp), attr, - attr_mask); - - return err; -} - -static int c2_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - return -ENOSYS; -} - -static int c2_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - return -ENOSYS; -} - -static int c2_process_mad(struct ib_device *ibdev, - int mad_flags, - u8 port_num, - const struct ib_wc *in_wc, - const struct ib_grh *in_grh, - const struct ib_mad_hdr *in_mad, - size_t in_mad_size, - struct ib_mad_hdr *out_mad, - size_t *out_mad_size, - u16 *out_mad_pkey_index) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - return -ENOSYS; -} - -static int c2_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - - /* Request a connection */ - return c2_llp_connect(cm_id, iw_param); -} - -static int c2_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - - /* Accept the new connection */ - return c2_llp_accept(cm_id, iw_param); -} - -static int c2_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - - return c2_llp_reject(cm_id, pdata, pdata_len); -} - -static int c2_service_create(struct iw_cm_id *cm_id, int backlog) -{ - int err; - - pr_debug("%s:%u\n", __func__, __LINE__); - err = c2_llp_service_create(cm_id, backlog); - pr_debug("%s:%u err=%d\n", - __func__, __LINE__, - err); - return err; -} - -static int c2_service_destroy(struct iw_cm_id *cm_id) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - - return c2_llp_service_destroy(cm_id); -} - -static int c2_pseudo_up(struct net_device *netdev) -{ - struct in_device *ind; - struct c2_dev *c2dev = netdev->ml_priv; - - ind = in_dev_get(netdev); - if (!ind) - return 0; - - pr_debug("adding...\n"); - for_ifa(ind) { -#ifdef DEBUG - u8 *ip = (u8 *) & ifa->ifa_address; - - pr_debug("%s: %d.%d.%d.%d\n", - ifa->ifa_label, ip[0], ip[1], ip[2], ip[3]); -#endif - c2_add_addr(c2dev, ifa->ifa_address, ifa->ifa_mask); - } - endfor_ifa(ind); - in_dev_put(ind); - - return 0; -} - -static int c2_pseudo_down(struct net_device *netdev) -{ - struct in_device *ind; - struct c2_dev *c2dev = netdev->ml_priv; - - ind = in_dev_get(netdev); - if (!ind) - return 0; - - pr_debug("deleting...\n"); - for_ifa(ind) { -#ifdef DEBUG - u8 *ip = (u8 *) & ifa->ifa_address; - - pr_debug("%s: %d.%d.%d.%d\n", - ifa->ifa_label, ip[0], ip[1], ip[2], ip[3]); -#endif - c2_del_addr(c2dev, ifa->ifa_address, ifa->ifa_mask); - } - endfor_ifa(ind); - in_dev_put(ind); - - return 0; -} - -static int c2_pseudo_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - kfree_skb(skb); - return NETDEV_TX_OK; -} - -static int c2_pseudo_change_mtu(struct net_device *netdev, int new_mtu) -{ - if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) - return -EINVAL; - - netdev->mtu = new_mtu; - - /* TODO: Tell rnic about new rmda interface mtu */ - return 0; -} - -static const struct net_device_ops c2_pseudo_netdev_ops = { - .ndo_open = c2_pseudo_up, - .ndo_stop = c2_pseudo_down, - .ndo_start_xmit = c2_pseudo_xmit_frame, - .ndo_change_mtu = c2_pseudo_change_mtu, - .ndo_validate_addr = eth_validate_addr, -}; - -static void setup(struct net_device *netdev) -{ - netdev->netdev_ops = &c2_pseudo_netdev_ops; - - netdev->watchdog_timeo = 0; - netdev->type = ARPHRD_ETHER; - netdev->mtu = 1500; - netdev->hard_header_len = ETH_HLEN; - netdev->addr_len = ETH_ALEN; - netdev->tx_queue_len = 0; - netdev->flags |= IFF_NOARP; -} - -static struct net_device *c2_pseudo_netdev_init(struct c2_dev *c2dev) -{ - char name[IFNAMSIZ]; - struct net_device *netdev; - - /* change ethxxx to iwxxx */ - strcpy(name, "iw"); - strcat(name, &c2dev->netdev->name[3]); - netdev = alloc_netdev(0, name, NET_NAME_UNKNOWN, setup); - if (!netdev) { - printk(KERN_ERR PFX "%s - etherdev alloc failed", - __func__); - return NULL; - } - - netdev->ml_priv = c2dev; - - SET_NETDEV_DEV(netdev, &c2dev->pcidev->dev); - - memcpy_fromio(netdev->dev_addr, c2dev->kva + C2_REGS_RDMA_ENADDR, 6); - - /* Print out the MAC address */ - pr_debug("%s: MAC %pM\n", netdev->name, netdev->dev_addr); - -#if 0 - /* Disable network packets */ - netif_stop_queue(netdev); -#endif - return netdev; -} - -static int c2_port_immutable(struct ib_device *ibdev, u8 port_num, - struct ib_port_immutable *immutable) -{ - struct ib_port_attr attr; - int err; - - err = c2_query_port(ibdev, port_num, &attr); - if (err) - return err; - - immutable->pkey_tbl_len = attr.pkey_tbl_len; - immutable->gid_tbl_len = attr.gid_tbl_len; - immutable->core_cap_flags = RDMA_CORE_PORT_IWARP; - - return 0; -} - -int c2_register_device(struct c2_dev *dev) -{ - int ret = -ENOMEM; - int i; - - /* Register pseudo network device */ - dev->pseudo_netdev = c2_pseudo_netdev_init(dev); - if (!dev->pseudo_netdev) - goto out; - - ret = register_netdev(dev->pseudo_netdev); - if (ret) - goto out_free_netdev; - - pr_debug("%s:%u\n", __func__, __LINE__); - strlcpy(dev->ibdev.name, "amso%d", IB_DEVICE_NAME_MAX); - dev->ibdev.owner = THIS_MODULE; - dev->ibdev.uverbs_cmd_mask = - (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | - (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | - (1ull << IB_USER_VERBS_CMD_QUERY_PORT) | - (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | - (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | - (1ull << IB_USER_VERBS_CMD_REG_MR) | - (1ull << IB_USER_VERBS_CMD_DEREG_MR) | - (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | - (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | - (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) | - (1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ) | - (1ull << IB_USER_VERBS_CMD_CREATE_QP) | - (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | - (1ull << IB_USER_VERBS_CMD_POLL_CQ) | - (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | - (1ull << IB_USER_VERBS_CMD_POST_SEND) | - (1ull << IB_USER_VERBS_CMD_POST_RECV); - - dev->ibdev.node_type = RDMA_NODE_RNIC; - memset(&dev->ibdev.node_guid, 0, sizeof(dev->ibdev.node_guid)); - memcpy(&dev->ibdev.node_guid, dev->pseudo_netdev->dev_addr, 6); - dev->ibdev.phys_port_cnt = 1; - dev->ibdev.num_comp_vectors = 1; - dev->ibdev.dma_device = &dev->pcidev->dev; - dev->ibdev.query_device = c2_query_device; - dev->ibdev.query_port = c2_query_port; - dev->ibdev.query_pkey = c2_query_pkey; - dev->ibdev.query_gid = c2_query_gid; - dev->ibdev.alloc_ucontext = c2_alloc_ucontext; - dev->ibdev.dealloc_ucontext = c2_dealloc_ucontext; - dev->ibdev.mmap = c2_mmap_uar; - dev->ibdev.alloc_pd = c2_alloc_pd; - dev->ibdev.dealloc_pd = c2_dealloc_pd; - dev->ibdev.create_ah = c2_ah_create; - dev->ibdev.destroy_ah = c2_ah_destroy; - dev->ibdev.create_qp = c2_create_qp; - dev->ibdev.modify_qp = c2_modify_qp; - dev->ibdev.destroy_qp = c2_destroy_qp; - dev->ibdev.create_cq = c2_create_cq; - dev->ibdev.destroy_cq = c2_destroy_cq; - dev->ibdev.poll_cq = c2_poll_cq; - dev->ibdev.get_dma_mr = c2_get_dma_mr; - dev->ibdev.reg_user_mr = c2_reg_user_mr; - dev->ibdev.dereg_mr = c2_dereg_mr; - dev->ibdev.get_port_immutable = c2_port_immutable; - - dev->ibdev.alloc_fmr = NULL; - dev->ibdev.unmap_fmr = NULL; - dev->ibdev.dealloc_fmr = NULL; - dev->ibdev.map_phys_fmr = NULL; - - dev->ibdev.attach_mcast = c2_multicast_attach; - dev->ibdev.detach_mcast = c2_multicast_detach; - dev->ibdev.process_mad = c2_process_mad; - - dev->ibdev.req_notify_cq = c2_arm_cq; - dev->ibdev.post_send = c2_post_send; - dev->ibdev.post_recv = c2_post_receive; - - dev->ibdev.iwcm = kmalloc(sizeof(*dev->ibdev.iwcm), GFP_KERNEL); - if (dev->ibdev.iwcm == NULL) { - ret = -ENOMEM; - goto out_unregister_netdev; - } - dev->ibdev.iwcm->add_ref = c2_add_ref; - dev->ibdev.iwcm->rem_ref = c2_rem_ref; - dev->ibdev.iwcm->get_qp = c2_get_qp; - dev->ibdev.iwcm->connect = c2_connect; - dev->ibdev.iwcm->accept = c2_accept; - dev->ibdev.iwcm->reject = c2_reject; - dev->ibdev.iwcm->create_listen = c2_service_create; - dev->ibdev.iwcm->destroy_listen = c2_service_destroy; - - ret = ib_register_device(&dev->ibdev, NULL); - if (ret) - goto out_free_iwcm; - - for (i = 0; i < ARRAY_SIZE(c2_dev_attributes); ++i) { - ret = device_create_file(&dev->ibdev.dev, - c2_dev_attributes[i]); - if (ret) - goto out_unregister_ibdev; - } - goto out; - -out_unregister_ibdev: - ib_unregister_device(&dev->ibdev); -out_free_iwcm: - kfree(dev->ibdev.iwcm); -out_unregister_netdev: - unregister_netdev(dev->pseudo_netdev); -out_free_netdev: - free_netdev(dev->pseudo_netdev); -out: - pr_debug("%s:%u ret=%d\n", __func__, __LINE__, ret); - return ret; -} - -void c2_unregister_device(struct c2_dev *dev) -{ - pr_debug("%s:%u\n", __func__, __LINE__); - unregister_netdev(dev->pseudo_netdev); - free_netdev(dev->pseudo_netdev); - ib_unregister_device(&dev->ibdev); -} diff --git a/drivers/staging/rdma/amso1100/c2_provider.h b/drivers/staging/rdma/amso1100/c2_provider.h deleted file mode 100644 index bf189987711f..000000000000 --- a/drivers/staging/rdma/amso1100/c2_provider.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifndef C2_PROVIDER_H -#define C2_PROVIDER_H -#include - -#include -#include - -#include "c2_mq.h" -#include - -#define C2_MPT_FLAG_ATOMIC (1 << 14) -#define C2_MPT_FLAG_REMOTE_WRITE (1 << 13) -#define C2_MPT_FLAG_REMOTE_READ (1 << 12) -#define C2_MPT_FLAG_LOCAL_WRITE (1 << 11) -#define C2_MPT_FLAG_LOCAL_READ (1 << 10) - -struct c2_buf_list { - void *buf; - DEFINE_DMA_UNMAP_ADDR(mapping); -}; - - -/* The user context keeps track of objects allocated for a - * particular user-mode client. */ -struct c2_ucontext { - struct ib_ucontext ibucontext; -}; - -struct c2_mtt; - -/* All objects associated with a PD are kept in the - * associated user context if present. - */ -struct c2_pd { - struct ib_pd ibpd; - u32 pd_id; -}; - -struct c2_mr { - struct ib_mr ibmr; - struct c2_pd *pd; - struct ib_umem *umem; -}; - -struct c2_av; - -enum c2_ah_type { - C2_AH_ON_HCA, - C2_AH_PCI_POOL, - C2_AH_KMALLOC -}; - -struct c2_ah { - struct ib_ah ibah; -}; - -struct c2_cq { - struct ib_cq ibcq; - spinlock_t lock; - atomic_t refcount; - int cqn; - int is_kernel; - wait_queue_head_t wait; - - u32 adapter_handle; - struct c2_mq mq; -}; - -struct c2_wq { - spinlock_t lock; -}; -struct iw_cm_id; -struct c2_qp { - struct ib_qp ibqp; - struct iw_cm_id *cm_id; - spinlock_t lock; - atomic_t refcount; - wait_queue_head_t wait; - int qpn; - - u32 adapter_handle; - u32 send_sgl_depth; - u32 recv_sgl_depth; - u32 rdma_write_sgl_depth; - u8 state; - - struct c2_mq sq_mq; - struct c2_mq rq_mq; -}; - -struct c2_cr_query_attrs { - u32 local_addr; - u32 remote_addr; - u16 local_port; - u16 remote_port; -}; - -static inline struct c2_pd *to_c2pd(struct ib_pd *ibpd) -{ - return container_of(ibpd, struct c2_pd, ibpd); -} - -static inline struct c2_ucontext *to_c2ucontext(struct ib_ucontext *ibucontext) -{ - return container_of(ibucontext, struct c2_ucontext, ibucontext); -} - -static inline struct c2_mr *to_c2mr(struct ib_mr *ibmr) -{ - return container_of(ibmr, struct c2_mr, ibmr); -} - - -static inline struct c2_ah *to_c2ah(struct ib_ah *ibah) -{ - return container_of(ibah, struct c2_ah, ibah); -} - -static inline struct c2_cq *to_c2cq(struct ib_cq *ibcq) -{ - return container_of(ibcq, struct c2_cq, ibcq); -} - -static inline struct c2_qp *to_c2qp(struct ib_qp *ibqp) -{ - return container_of(ibqp, struct c2_qp, ibqp); -} - -static inline int is_rnic_addr(struct net_device *netdev, u32 addr) -{ - struct in_device *ind; - int ret = 0; - - ind = in_dev_get(netdev); - if (!ind) - return 0; - - for_ifa(ind) { - if (ifa->ifa_address == addr) { - ret = 1; - break; - } - } - endfor_ifa(ind); - in_dev_put(ind); - return ret; -} -#endif /* C2_PROVIDER_H */ diff --git a/drivers/staging/rdma/amso1100/c2_qp.c b/drivers/staging/rdma/amso1100/c2_qp.c deleted file mode 100644 index ca364dbe369c..000000000000 --- a/drivers/staging/rdma/amso1100/c2_qp.c +++ /dev/null @@ -1,1024 +0,0 @@ -/* - * Copyright (c) 2004 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2004 Voltaire, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#include -#include - -#include "c2.h" -#include "c2_vq.h" -#include "c2_status.h" - -#define C2_MAX_ORD_PER_QP 128 -#define C2_MAX_IRD_PER_QP 128 - -#define C2_HINT_MAKE(q_index, hint_count) (((q_index) << 16) | hint_count) -#define C2_HINT_GET_INDEX(hint) (((hint) & 0x7FFF0000) >> 16) -#define C2_HINT_GET_COUNT(hint) ((hint) & 0x0000FFFF) - -#define NO_SUPPORT -1 -static const u8 c2_opcode[] = { - [IB_WR_SEND] = C2_WR_TYPE_SEND, - [IB_WR_SEND_WITH_IMM] = NO_SUPPORT, - [IB_WR_RDMA_WRITE] = C2_WR_TYPE_RDMA_WRITE, - [IB_WR_RDMA_WRITE_WITH_IMM] = NO_SUPPORT, - [IB_WR_RDMA_READ] = C2_WR_TYPE_RDMA_READ, - [IB_WR_ATOMIC_CMP_AND_SWP] = NO_SUPPORT, - [IB_WR_ATOMIC_FETCH_AND_ADD] = NO_SUPPORT, -}; - -static int to_c2_state(enum ib_qp_state ib_state) -{ - switch (ib_state) { - case IB_QPS_RESET: - return C2_QP_STATE_IDLE; - case IB_QPS_RTS: - return C2_QP_STATE_RTS; - case IB_QPS_SQD: - return C2_QP_STATE_CLOSING; - case IB_QPS_SQE: - return C2_QP_STATE_CLOSING; - case IB_QPS_ERR: - return C2_QP_STATE_ERROR; - default: - return -1; - } -} - -static int to_ib_state(enum c2_qp_state c2_state) -{ - switch (c2_state) { - case C2_QP_STATE_IDLE: - return IB_QPS_RESET; - case C2_QP_STATE_CONNECTING: - return IB_QPS_RTR; - case C2_QP_STATE_RTS: - return IB_QPS_RTS; - case C2_QP_STATE_CLOSING: - return IB_QPS_SQD; - case C2_QP_STATE_ERROR: - return IB_QPS_ERR; - case C2_QP_STATE_TERMINATE: - return IB_QPS_SQE; - default: - return -1; - } -} - -static const char *to_ib_state_str(int ib_state) -{ - static const char *state_str[] = { - "IB_QPS_RESET", - "IB_QPS_INIT", - "IB_QPS_RTR", - "IB_QPS_RTS", - "IB_QPS_SQD", - "IB_QPS_SQE", - "IB_QPS_ERR" - }; - if (ib_state < IB_QPS_RESET || - ib_state > IB_QPS_ERR) - return ""; - - ib_state -= IB_QPS_RESET; - return state_str[ib_state]; -} - -void c2_set_qp_state(struct c2_qp *qp, int c2_state) -{ - int new_state = to_ib_state(c2_state); - - pr_debug("%s: qp[%p] state modify %s --> %s\n", - __func__, - qp, - to_ib_state_str(qp->state), - to_ib_state_str(new_state)); - qp->state = new_state; -} - -#define C2_QP_NO_ATTR_CHANGE 0xFFFFFFFF - -int c2_qp_modify(struct c2_dev *c2dev, struct c2_qp *qp, - struct ib_qp_attr *attr, int attr_mask) -{ - struct c2wr_qp_modify_req wr; - struct c2wr_qp_modify_rep *reply; - struct c2_vq_req *vq_req; - unsigned long flags; - u8 next_state; - int err; - - pr_debug("%s:%d qp=%p, %s --> %s\n", - __func__, __LINE__, - qp, - to_ib_state_str(qp->state), - to_ib_state_str(attr->qp_state)); - - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - c2_wr_set_id(&wr, CCWR_QP_MODIFY); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.qp_handle = qp->adapter_handle; - wr.ord = cpu_to_be32(C2_QP_NO_ATTR_CHANGE); - wr.ird = cpu_to_be32(C2_QP_NO_ATTR_CHANGE); - wr.sq_depth = cpu_to_be32(C2_QP_NO_ATTR_CHANGE); - wr.rq_depth = cpu_to_be32(C2_QP_NO_ATTR_CHANGE); - - if (attr_mask & IB_QP_STATE) { - /* Ensure the state is valid */ - if (attr->qp_state < 0 || attr->qp_state > IB_QPS_ERR) { - err = -EINVAL; - goto bail0; - } - - wr.next_qp_state = cpu_to_be32(to_c2_state(attr->qp_state)); - - if (attr->qp_state == IB_QPS_ERR) { - spin_lock_irqsave(&qp->lock, flags); - if (qp->cm_id && qp->state == IB_QPS_RTS) { - pr_debug("Generating CLOSE event for QP-->ERR, " - "qp=%p, cm_id=%p\n",qp,qp->cm_id); - /* Generate an CLOSE event */ - vq_req->cm_id = qp->cm_id; - vq_req->event = IW_CM_EVENT_CLOSE; - } - spin_unlock_irqrestore(&qp->lock, flags); - } - next_state = attr->qp_state; - - } else if (attr_mask & IB_QP_CUR_STATE) { - - if (attr->cur_qp_state != IB_QPS_RTR && - attr->cur_qp_state != IB_QPS_RTS && - attr->cur_qp_state != IB_QPS_SQD && - attr->cur_qp_state != IB_QPS_SQE) { - err = -EINVAL; - goto bail0; - } else - wr.next_qp_state = - cpu_to_be32(to_c2_state(attr->cur_qp_state)); - - next_state = attr->cur_qp_state; - - } else { - err = 0; - goto bail0; - } - - /* reference the request struct */ - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail0; - - reply = (struct c2wr_qp_modify_rep *) (unsigned long) vq_req->reply_msg; - if (!reply) { - err = -ENOMEM; - goto bail0; - } - - err = c2_errno(reply); - if (!err) - qp->state = next_state; -#ifdef DEBUG - else - pr_debug("%s: c2_errno=%d\n", __func__, err); -#endif - /* - * If we're going to error and generating the event here, then - * we need to remove the reference because there will be no - * close event generated by the adapter - */ - spin_lock_irqsave(&qp->lock, flags); - if (vq_req->event==IW_CM_EVENT_CLOSE && qp->cm_id) { - qp->cm_id->rem_ref(qp->cm_id); - qp->cm_id = NULL; - } - spin_unlock_irqrestore(&qp->lock, flags); - - vq_repbuf_free(c2dev, reply); -bail0: - vq_req_free(c2dev, vq_req); - - pr_debug("%s:%d qp=%p, cur_state=%s\n", - __func__, __LINE__, - qp, - to_ib_state_str(qp->state)); - return err; -} - -int c2_qp_set_read_limits(struct c2_dev *c2dev, struct c2_qp *qp, - int ord, int ird) -{ - struct c2wr_qp_modify_req wr; - struct c2wr_qp_modify_rep *reply; - struct c2_vq_req *vq_req; - int err; - - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - c2_wr_set_id(&wr, CCWR_QP_MODIFY); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.qp_handle = qp->adapter_handle; - wr.ord = cpu_to_be32(ord); - wr.ird = cpu_to_be32(ird); - wr.sq_depth = cpu_to_be32(C2_QP_NO_ATTR_CHANGE); - wr.rq_depth = cpu_to_be32(C2_QP_NO_ATTR_CHANGE); - wr.next_qp_state = cpu_to_be32(C2_QP_NO_ATTR_CHANGE); - - /* reference the request struct */ - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail0; - - reply = (struct c2wr_qp_modify_rep *) (unsigned long) - vq_req->reply_msg; - if (!reply) { - err = -ENOMEM; - goto bail0; - } - - err = c2_errno(reply); - vq_repbuf_free(c2dev, reply); -bail0: - vq_req_free(c2dev, vq_req); - return err; -} - -static int destroy_qp(struct c2_dev *c2dev, struct c2_qp *qp) -{ - struct c2_vq_req *vq_req; - struct c2wr_qp_destroy_req wr; - struct c2wr_qp_destroy_rep *reply; - unsigned long flags; - int err; - - /* - * Allocate a verb request message - */ - vq_req = vq_req_alloc(c2dev); - if (!vq_req) { - return -ENOMEM; - } - - /* - * Initialize the WR - */ - c2_wr_set_id(&wr, CCWR_QP_DESTROY); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.qp_handle = qp->adapter_handle; - - /* - * reference the request struct. dereferenced in the int handler. - */ - vq_req_get(c2dev, vq_req); - - spin_lock_irqsave(&qp->lock, flags); - if (qp->cm_id && qp->state == IB_QPS_RTS) { - pr_debug("destroy_qp: generating CLOSE event for QP-->ERR, " - "qp=%p, cm_id=%p\n",qp,qp->cm_id); - /* Generate an CLOSE event */ - vq_req->qp = qp; - vq_req->cm_id = qp->cm_id; - vq_req->event = IW_CM_EVENT_CLOSE; - } - spin_unlock_irqrestore(&qp->lock, flags); - - /* - * Send WR to adapter - */ - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - /* - * Wait for reply from adapter - */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) { - goto bail0; - } - - /* - * Process reply - */ - reply = (struct c2wr_qp_destroy_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) { - err = -ENOMEM; - goto bail0; - } - - spin_lock_irqsave(&qp->lock, flags); - if (qp->cm_id) { - qp->cm_id->rem_ref(qp->cm_id); - qp->cm_id = NULL; - } - spin_unlock_irqrestore(&qp->lock, flags); - - vq_repbuf_free(c2dev, reply); -bail0: - vq_req_free(c2dev, vq_req); - return err; -} - -static int c2_alloc_qpn(struct c2_dev *c2dev, struct c2_qp *qp) -{ - int ret; - - idr_preload(GFP_KERNEL); - spin_lock_irq(&c2dev->qp_table.lock); - - ret = idr_alloc_cyclic(&c2dev->qp_table.idr, qp, 0, 0, GFP_NOWAIT); - if (ret >= 0) - qp->qpn = ret; - - spin_unlock_irq(&c2dev->qp_table.lock); - idr_preload_end(); - return ret < 0 ? ret : 0; -} - -static void c2_free_qpn(struct c2_dev *c2dev, int qpn) -{ - spin_lock_irq(&c2dev->qp_table.lock); - idr_remove(&c2dev->qp_table.idr, qpn); - spin_unlock_irq(&c2dev->qp_table.lock); -} - -struct c2_qp *c2_find_qpn(struct c2_dev *c2dev, int qpn) -{ - unsigned long flags; - struct c2_qp *qp; - - spin_lock_irqsave(&c2dev->qp_table.lock, flags); - qp = idr_find(&c2dev->qp_table.idr, qpn); - spin_unlock_irqrestore(&c2dev->qp_table.lock, flags); - return qp; -} - -int c2_alloc_qp(struct c2_dev *c2dev, - struct c2_pd *pd, - struct ib_qp_init_attr *qp_attrs, struct c2_qp *qp) -{ - struct c2wr_qp_create_req wr; - struct c2wr_qp_create_rep *reply; - struct c2_vq_req *vq_req; - struct c2_cq *send_cq = to_c2cq(qp_attrs->send_cq); - struct c2_cq *recv_cq = to_c2cq(qp_attrs->recv_cq); - unsigned long peer_pa; - u32 q_size, msg_size, mmap_size; - void __iomem *mmap; - int err; - - err = c2_alloc_qpn(c2dev, qp); - if (err) - return err; - qp->ibqp.qp_num = qp->qpn; - qp->ibqp.qp_type = IB_QPT_RC; - - /* Allocate the SQ and RQ shared pointers */ - qp->sq_mq.shared = c2_alloc_mqsp(c2dev, c2dev->kern_mqsp_pool, - &qp->sq_mq.shared_dma, GFP_KERNEL); - if (!qp->sq_mq.shared) { - err = -ENOMEM; - goto bail0; - } - - qp->rq_mq.shared = c2_alloc_mqsp(c2dev, c2dev->kern_mqsp_pool, - &qp->rq_mq.shared_dma, GFP_KERNEL); - if (!qp->rq_mq.shared) { - err = -ENOMEM; - goto bail1; - } - - /* Allocate the verbs request */ - vq_req = vq_req_alloc(c2dev); - if (vq_req == NULL) { - err = -ENOMEM; - goto bail2; - } - - /* Initialize the work request */ - memset(&wr, 0, sizeof(wr)); - c2_wr_set_id(&wr, CCWR_QP_CREATE); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.sq_cq_handle = send_cq->adapter_handle; - wr.rq_cq_handle = recv_cq->adapter_handle; - wr.sq_depth = cpu_to_be32(qp_attrs->cap.max_send_wr + 1); - wr.rq_depth = cpu_to_be32(qp_attrs->cap.max_recv_wr + 1); - wr.srq_handle = 0; - wr.flags = cpu_to_be32(QP_RDMA_READ | QP_RDMA_WRITE | QP_MW_BIND | - QP_ZERO_STAG | QP_RDMA_READ_RESPONSE); - wr.send_sgl_depth = cpu_to_be32(qp_attrs->cap.max_send_sge); - wr.recv_sgl_depth = cpu_to_be32(qp_attrs->cap.max_recv_sge); - wr.rdma_write_sgl_depth = cpu_to_be32(qp_attrs->cap.max_send_sge); - wr.shared_sq_ht = cpu_to_be64(qp->sq_mq.shared_dma); - wr.shared_rq_ht = cpu_to_be64(qp->rq_mq.shared_dma); - wr.ord = cpu_to_be32(C2_MAX_ORD_PER_QP); - wr.ird = cpu_to_be32(C2_MAX_IRD_PER_QP); - wr.pd_id = pd->pd_id; - wr.user_context = (unsigned long) qp; - - vq_req_get(c2dev, vq_req); - - /* Send the WR to the adapter */ - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail3; - } - - /* Wait for the verb reply */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) { - goto bail3; - } - - /* Process the reply */ - reply = (struct c2wr_qp_create_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) { - err = -ENOMEM; - goto bail3; - } - - if ((err = c2_wr_get_result(reply)) != 0) { - goto bail4; - } - - /* Fill in the kernel QP struct */ - atomic_set(&qp->refcount, 1); - qp->adapter_handle = reply->qp_handle; - qp->state = IB_QPS_RESET; - qp->send_sgl_depth = qp_attrs->cap.max_send_sge; - qp->rdma_write_sgl_depth = qp_attrs->cap.max_send_sge; - qp->recv_sgl_depth = qp_attrs->cap.max_recv_sge; - init_waitqueue_head(&qp->wait); - - /* Initialize the SQ MQ */ - q_size = be32_to_cpu(reply->sq_depth); - msg_size = be32_to_cpu(reply->sq_msg_size); - peer_pa = c2dev->pa + be32_to_cpu(reply->sq_mq_start); - mmap_size = PAGE_ALIGN(sizeof(struct c2_mq_shared) + msg_size * q_size); - mmap = ioremap_nocache(peer_pa, mmap_size); - if (!mmap) { - err = -ENOMEM; - goto bail5; - } - - c2_mq_req_init(&qp->sq_mq, - be32_to_cpu(reply->sq_mq_index), - q_size, - msg_size, - mmap + sizeof(struct c2_mq_shared), /* pool start */ - mmap, /* peer */ - C2_MQ_ADAPTER_TARGET); - - /* Initialize the RQ mq */ - q_size = be32_to_cpu(reply->rq_depth); - msg_size = be32_to_cpu(reply->rq_msg_size); - peer_pa = c2dev->pa + be32_to_cpu(reply->rq_mq_start); - mmap_size = PAGE_ALIGN(sizeof(struct c2_mq_shared) + msg_size * q_size); - mmap = ioremap_nocache(peer_pa, mmap_size); - if (!mmap) { - err = -ENOMEM; - goto bail6; - } - - c2_mq_req_init(&qp->rq_mq, - be32_to_cpu(reply->rq_mq_index), - q_size, - msg_size, - mmap + sizeof(struct c2_mq_shared), /* pool start */ - mmap, /* peer */ - C2_MQ_ADAPTER_TARGET); - - vq_repbuf_free(c2dev, reply); - vq_req_free(c2dev, vq_req); - - return 0; - -bail6: - iounmap(qp->sq_mq.peer); -bail5: - destroy_qp(c2dev, qp); -bail4: - vq_repbuf_free(c2dev, reply); -bail3: - vq_req_free(c2dev, vq_req); -bail2: - c2_free_mqsp(qp->rq_mq.shared); -bail1: - c2_free_mqsp(qp->sq_mq.shared); -bail0: - c2_free_qpn(c2dev, qp->qpn); - return err; -} - -static inline void c2_lock_cqs(struct c2_cq *send_cq, struct c2_cq *recv_cq) -{ - if (send_cq == recv_cq) - spin_lock_irq(&send_cq->lock); - else if (send_cq > recv_cq) { - spin_lock_irq(&send_cq->lock); - spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING); - } else { - spin_lock_irq(&recv_cq->lock); - spin_lock_nested(&send_cq->lock, SINGLE_DEPTH_NESTING); - } -} - -static inline void c2_unlock_cqs(struct c2_cq *send_cq, struct c2_cq *recv_cq) -{ - if (send_cq == recv_cq) - spin_unlock_irq(&send_cq->lock); - else if (send_cq > recv_cq) { - spin_unlock(&recv_cq->lock); - spin_unlock_irq(&send_cq->lock); - } else { - spin_unlock(&send_cq->lock); - spin_unlock_irq(&recv_cq->lock); - } -} - -void c2_free_qp(struct c2_dev *c2dev, struct c2_qp *qp) -{ - struct c2_cq *send_cq; - struct c2_cq *recv_cq; - - send_cq = to_c2cq(qp->ibqp.send_cq); - recv_cq = to_c2cq(qp->ibqp.recv_cq); - - /* - * Lock CQs here, so that CQ polling code can do QP lookup - * without taking a lock. - */ - c2_lock_cqs(send_cq, recv_cq); - c2_free_qpn(c2dev, qp->qpn); - c2_unlock_cqs(send_cq, recv_cq); - - /* - * Destroy qp in the rnic... - */ - destroy_qp(c2dev, qp); - - /* - * Mark any unreaped CQEs as null and void. - */ - c2_cq_clean(c2dev, qp, send_cq->cqn); - if (send_cq != recv_cq) - c2_cq_clean(c2dev, qp, recv_cq->cqn); - /* - * Unmap the MQs and return the shared pointers - * to the message pool. - */ - iounmap(qp->sq_mq.peer); - iounmap(qp->rq_mq.peer); - c2_free_mqsp(qp->sq_mq.shared); - c2_free_mqsp(qp->rq_mq.shared); - - atomic_dec(&qp->refcount); - wait_event(qp->wait, !atomic_read(&qp->refcount)); -} - -/* - * Function: move_sgl - * - * Description: - * Move an SGL from the user's work request struct into a CCIL Work Request - * message, swapping to WR byte order and ensure the total length doesn't - * overflow. - * - * IN: - * dst - ptr to CCIL Work Request message SGL memory. - * src - ptr to the consumers SGL memory. - * - * OUT: none - * - * Return: - * CCIL status codes. - */ -static int -move_sgl(struct c2_data_addr * dst, struct ib_sge *src, int count, u32 * p_len, - u8 * actual_count) -{ - u32 tot = 0; /* running total */ - u8 acount = 0; /* running total non-0 len sge's */ - - while (count > 0) { - /* - * If the addition of this SGE causes the - * total SGL length to exceed 2^32-1, then - * fail-n-bail. - * - * If the current total plus the next element length - * wraps, then it will go negative and be less than the - * current total... - */ - if ((tot + src->length) < tot) { - return -EINVAL; - } - /* - * Bug: 1456 (as well as 1498 & 1643) - * Skip over any sge's supplied with len=0 - */ - if (src->length) { - tot += src->length; - dst->stag = cpu_to_be32(src->lkey); - dst->to = cpu_to_be64(src->addr); - dst->length = cpu_to_be32(src->length); - dst++; - acount++; - } - src++; - count--; - } - - if (acount == 0) { - /* - * Bug: 1476 (as well as 1498, 1456 and 1643) - * Setup the SGL in the WR to make it easier for the RNIC. - * This way, the FW doesn't have to deal with special cases. - * Setting length=0 should be sufficient. - */ - dst->stag = 0; - dst->to = 0; - dst->length = 0; - } - - *p_len = tot; - *actual_count = acount; - return 0; -} - -/* - * Function: c2_activity (private function) - * - * Description: - * Post an mq index to the host->adapter activity fifo. - * - * IN: - * c2dev - ptr to c2dev structure - * mq_index - mq index to post - * shared - value most recently written to shared - * - * OUT: - * - * Return: - * none - */ -static inline void c2_activity(struct c2_dev *c2dev, u32 mq_index, u16 shared) -{ - /* - * First read the register to see if the FIFO is full, and if so, - * spin until it's not. This isn't perfect -- there is no - * synchronization among the clients of the register, but in - * practice it prevents multiple CPU from hammering the bus - * with PCI RETRY. Note that when this does happen, the card - * cannot get on the bus and the card and system hang in a - * deadlock -- thus the need for this code. [TOT] - */ - while (readl(c2dev->regs + PCI_BAR0_ADAPTER_HINT) & 0x80000000) - udelay(10); - - __raw_writel(C2_HINT_MAKE(mq_index, shared), - c2dev->regs + PCI_BAR0_ADAPTER_HINT); -} - -/* - * Function: qp_wr_post - * - * Description: - * This in-line function allocates a MQ msg, then moves the host-copy of - * the completed WR into msg. Then it posts the message. - * - * IN: - * q - ptr to user MQ. - * wr - ptr to host-copy of the WR. - * qp - ptr to user qp - * size - Number of bytes to post. Assumed to be divisible by 4. - * - * OUT: none - * - * Return: - * CCIL status codes. - */ -static int qp_wr_post(struct c2_mq *q, union c2wr * wr, struct c2_qp *qp, u32 size) -{ - union c2wr *msg; - - msg = c2_mq_alloc(q); - if (msg == NULL) { - return -EINVAL; - } -#ifdef CCMSGMAGIC - ((c2wr_hdr_t *) wr)->magic = cpu_to_be32(CCWR_MAGIC); -#endif - - /* - * Since all header fields in the WR are the same as the - * CQE, set the following so the adapter need not. - */ - c2_wr_set_result(wr, CCERR_PENDING); - - /* - * Copy the wr down to the adapter - */ - memcpy((void *) msg, (void *) wr, size); - - c2_mq_produce(q); - return 0; -} - - -int c2_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, - struct ib_send_wr **bad_wr) -{ - struct c2_dev *c2dev = to_c2dev(ibqp->device); - struct c2_qp *qp = to_c2qp(ibqp); - union c2wr wr; - unsigned long lock_flags; - int err = 0; - - u32 flags; - u32 tot_len; - u8 actual_sge_count; - u32 msg_size; - - if (qp->state > IB_QPS_RTS) { - err = -EINVAL; - goto out; - } - - while (ib_wr) { - - flags = 0; - wr.sqwr.sq_hdr.user_hdr.hdr.context = ib_wr->wr_id; - if (ib_wr->send_flags & IB_SEND_SIGNALED) { - flags |= SQ_SIGNALED; - } - - switch (ib_wr->opcode) { - case IB_WR_SEND: - case IB_WR_SEND_WITH_INV: - if (ib_wr->opcode == IB_WR_SEND) { - if (ib_wr->send_flags & IB_SEND_SOLICITED) - c2_wr_set_id(&wr, C2_WR_TYPE_SEND_SE); - else - c2_wr_set_id(&wr, C2_WR_TYPE_SEND); - wr.sqwr.send.remote_stag = 0; - } else { - if (ib_wr->send_flags & IB_SEND_SOLICITED) - c2_wr_set_id(&wr, C2_WR_TYPE_SEND_SE_INV); - else - c2_wr_set_id(&wr, C2_WR_TYPE_SEND_INV); - wr.sqwr.send.remote_stag = - cpu_to_be32(ib_wr->ex.invalidate_rkey); - } - - msg_size = sizeof(struct c2wr_send_req) + - sizeof(struct c2_data_addr) * ib_wr->num_sge; - if (ib_wr->num_sge > qp->send_sgl_depth) { - err = -EINVAL; - break; - } - if (ib_wr->send_flags & IB_SEND_FENCE) { - flags |= SQ_READ_FENCE; - } - err = move_sgl((struct c2_data_addr *) & (wr.sqwr.send.data), - ib_wr->sg_list, - ib_wr->num_sge, - &tot_len, &actual_sge_count); - wr.sqwr.send.sge_len = cpu_to_be32(tot_len); - c2_wr_set_sge_count(&wr, actual_sge_count); - break; - case IB_WR_RDMA_WRITE: - c2_wr_set_id(&wr, C2_WR_TYPE_RDMA_WRITE); - msg_size = sizeof(struct c2wr_rdma_write_req) + - (sizeof(struct c2_data_addr) * ib_wr->num_sge); - if (ib_wr->num_sge > qp->rdma_write_sgl_depth) { - err = -EINVAL; - break; - } - if (ib_wr->send_flags & IB_SEND_FENCE) { - flags |= SQ_READ_FENCE; - } - wr.sqwr.rdma_write.remote_stag = - cpu_to_be32(rdma_wr(ib_wr)->rkey); - wr.sqwr.rdma_write.remote_to = - cpu_to_be64(rdma_wr(ib_wr)->remote_addr); - err = move_sgl((struct c2_data_addr *) - & (wr.sqwr.rdma_write.data), - ib_wr->sg_list, - ib_wr->num_sge, - &tot_len, &actual_sge_count); - wr.sqwr.rdma_write.sge_len = cpu_to_be32(tot_len); - c2_wr_set_sge_count(&wr, actual_sge_count); - break; - case IB_WR_RDMA_READ: - c2_wr_set_id(&wr, C2_WR_TYPE_RDMA_READ); - msg_size = sizeof(struct c2wr_rdma_read_req); - - /* IWarp only suppots 1 sge for RDMA reads */ - if (ib_wr->num_sge > 1) { - err = -EINVAL; - break; - } - - /* - * Move the local and remote stag/to/len into the WR. - */ - wr.sqwr.rdma_read.local_stag = - cpu_to_be32(ib_wr->sg_list->lkey); - wr.sqwr.rdma_read.local_to = - cpu_to_be64(ib_wr->sg_list->addr); - wr.sqwr.rdma_read.remote_stag = - cpu_to_be32(rdma_wr(ib_wr)->rkey); - wr.sqwr.rdma_read.remote_to = - cpu_to_be64(rdma_wr(ib_wr)->remote_addr); - wr.sqwr.rdma_read.length = - cpu_to_be32(ib_wr->sg_list->length); - break; - default: - /* error */ - msg_size = 0; - err = -EINVAL; - break; - } - - /* - * If we had an error on the last wr build, then - * break out. Possible errors include bogus WR - * type, and a bogus SGL length... - */ - if (err) { - break; - } - - /* - * Store flags - */ - c2_wr_set_flags(&wr, flags); - - /* - * Post the puppy! - */ - spin_lock_irqsave(&qp->lock, lock_flags); - err = qp_wr_post(&qp->sq_mq, &wr, qp, msg_size); - if (err) { - spin_unlock_irqrestore(&qp->lock, lock_flags); - break; - } - - /* - * Enqueue mq index to activity FIFO. - */ - c2_activity(c2dev, qp->sq_mq.index, qp->sq_mq.hint_count); - spin_unlock_irqrestore(&qp->lock, lock_flags); - - ib_wr = ib_wr->next; - } - -out: - if (err) - *bad_wr = ib_wr; - return err; -} - -int c2_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr, - struct ib_recv_wr **bad_wr) -{ - struct c2_dev *c2dev = to_c2dev(ibqp->device); - struct c2_qp *qp = to_c2qp(ibqp); - union c2wr wr; - unsigned long lock_flags; - int err = 0; - - if (qp->state > IB_QPS_RTS) { - err = -EINVAL; - goto out; - } - - /* - * Try and post each work request - */ - while (ib_wr) { - u32 tot_len; - u8 actual_sge_count; - - if (ib_wr->num_sge > qp->recv_sgl_depth) { - err = -EINVAL; - break; - } - - /* - * Create local host-copy of the WR - */ - wr.rqwr.rq_hdr.user_hdr.hdr.context = ib_wr->wr_id; - c2_wr_set_id(&wr, CCWR_RECV); - c2_wr_set_flags(&wr, 0); - - /* sge_count is limited to eight bits. */ - BUG_ON(ib_wr->num_sge >= 256); - err = move_sgl((struct c2_data_addr *) & (wr.rqwr.data), - ib_wr->sg_list, - ib_wr->num_sge, &tot_len, &actual_sge_count); - c2_wr_set_sge_count(&wr, actual_sge_count); - - /* - * If we had an error on the last wr build, then - * break out. Possible errors include bogus WR - * type, and a bogus SGL length... - */ - if (err) { - break; - } - - spin_lock_irqsave(&qp->lock, lock_flags); - err = qp_wr_post(&qp->rq_mq, &wr, qp, qp->rq_mq.msg_size); - if (err) { - spin_unlock_irqrestore(&qp->lock, lock_flags); - break; - } - - /* - * Enqueue mq index to activity FIFO - */ - c2_activity(c2dev, qp->rq_mq.index, qp->rq_mq.hint_count); - spin_unlock_irqrestore(&qp->lock, lock_flags); - - ib_wr = ib_wr->next; - } - -out: - if (err) - *bad_wr = ib_wr; - return err; -} - -void c2_init_qp_table(struct c2_dev *c2dev) -{ - spin_lock_init(&c2dev->qp_table.lock); - idr_init(&c2dev->qp_table.idr); -} - -void c2_cleanup_qp_table(struct c2_dev *c2dev) -{ - idr_destroy(&c2dev->qp_table.idr); -} diff --git a/drivers/staging/rdma/amso1100/c2_rnic.c b/drivers/staging/rdma/amso1100/c2_rnic.c deleted file mode 100644 index 5e65c6d07ca4..000000000000 --- a/drivers/staging/rdma/amso1100/c2_rnic.c +++ /dev/null @@ -1,652 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include "c2.h" -#include "c2_vq.h" - -/* Device capabilities */ -#define C2_MIN_PAGESIZE 1024 - -#define C2_MAX_MRS 32768 -#define C2_MAX_QPS 16000 -#define C2_MAX_WQE_SZ 256 -#define C2_MAX_QP_WR ((128*1024)/C2_MAX_WQE_SZ) -#define C2_MAX_SGES 4 -#define C2_MAX_SGE_RD 1 -#define C2_MAX_CQS 32768 -#define C2_MAX_CQES 4096 -#define C2_MAX_PDS 16384 - -/* - * Send the adapter INIT message to the amso1100 - */ -static int c2_adapter_init(struct c2_dev *c2dev) -{ - struct c2wr_init_req wr; - - memset(&wr, 0, sizeof(wr)); - c2_wr_set_id(&wr, CCWR_INIT); - wr.hdr.context = 0; - wr.hint_count = cpu_to_be64(c2dev->hint_count_dma); - wr.q0_host_shared = cpu_to_be64(c2dev->req_vq.shared_dma); - wr.q1_host_shared = cpu_to_be64(c2dev->rep_vq.shared_dma); - wr.q1_host_msg_pool = cpu_to_be64(c2dev->rep_vq.host_dma); - wr.q2_host_shared = cpu_to_be64(c2dev->aeq.shared_dma); - wr.q2_host_msg_pool = cpu_to_be64(c2dev->aeq.host_dma); - - /* Post the init message */ - return vq_send_wr(c2dev, (union c2wr *) & wr); -} - -/* - * Send the adapter TERM message to the amso1100 - */ -static void c2_adapter_term(struct c2_dev *c2dev) -{ - struct c2wr_init_req wr; - - memset(&wr, 0, sizeof(wr)); - c2_wr_set_id(&wr, CCWR_TERM); - wr.hdr.context = 0; - - /* Post the init message */ - vq_send_wr(c2dev, (union c2wr *) & wr); - c2dev->init = 0; - - return; -} - -/* - * Query the adapter - */ -static int c2_rnic_query(struct c2_dev *c2dev, struct ib_device_attr *props) -{ - struct c2_vq_req *vq_req; - struct c2wr_rnic_query_req wr; - struct c2wr_rnic_query_rep *reply; - int err; - - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - c2_wr_set_id(&wr, CCWR_RNIC_QUERY); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, (union c2wr *) &wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail1; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail1; - - reply = - (struct c2wr_rnic_query_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) - err = -ENOMEM; - else - err = c2_errno(reply); - if (err) - goto bail2; - - props->fw_ver = - ((u64)be32_to_cpu(reply->fw_ver_major) << 32) | - ((be32_to_cpu(reply->fw_ver_minor) & 0xFFFF) << 16) | - (be32_to_cpu(reply->fw_ver_patch) & 0xFFFF); - memcpy(&props->sys_image_guid, c2dev->netdev->dev_addr, 6); - props->max_mr_size = 0xFFFFFFFF; - props->page_size_cap = ~(C2_MIN_PAGESIZE-1); - props->vendor_id = be32_to_cpu(reply->vendor_id); - props->vendor_part_id = be32_to_cpu(reply->part_number); - props->hw_ver = be32_to_cpu(reply->hw_version); - props->max_qp = be32_to_cpu(reply->max_qps); - props->max_qp_wr = be32_to_cpu(reply->max_qp_depth); - props->device_cap_flags = c2dev->device_cap_flags; - props->max_sge = C2_MAX_SGES; - props->max_sge_rd = C2_MAX_SGE_RD; - props->max_cq = be32_to_cpu(reply->max_cqs); - props->max_cqe = be32_to_cpu(reply->max_cq_depth); - props->max_mr = be32_to_cpu(reply->max_mrs); - props->max_pd = be32_to_cpu(reply->max_pds); - props->max_qp_rd_atom = be32_to_cpu(reply->max_qp_ird); - props->max_ee_rd_atom = 0; - props->max_res_rd_atom = be32_to_cpu(reply->max_global_ird); - props->max_qp_init_rd_atom = be32_to_cpu(reply->max_qp_ord); - props->max_ee_init_rd_atom = 0; - props->atomic_cap = IB_ATOMIC_NONE; - props->max_ee = 0; - props->max_rdd = 0; - props->max_mw = be32_to_cpu(reply->max_mws); - props->max_raw_ipv6_qp = 0; - props->max_raw_ethy_qp = 0; - props->max_mcast_grp = 0; - props->max_mcast_qp_attach = 0; - props->max_total_mcast_qp_attach = 0; - props->max_ah = 0; - props->max_fmr = 0; - props->max_map_per_fmr = 0; - props->max_srq = 0; - props->max_srq_wr = 0; - props->max_srq_sge = 0; - props->max_pkeys = 0; - props->local_ca_ack_delay = 0; - - bail2: - vq_repbuf_free(c2dev, reply); - - bail1: - vq_req_free(c2dev, vq_req); - return err; -} - -/* - * Add an IP address to the RNIC interface - */ -int c2_add_addr(struct c2_dev *c2dev, __be32 inaddr, __be32 inmask) -{ - struct c2_vq_req *vq_req; - struct c2wr_rnic_setconfig_req *wr; - struct c2wr_rnic_setconfig_rep *reply; - struct c2_netaddr netaddr; - int err, len; - - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - len = sizeof(struct c2_netaddr); - wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL); - if (!wr) { - err = -ENOMEM; - goto bail0; - } - - c2_wr_set_id(wr, CCWR_RNIC_SETCONFIG); - wr->hdr.context = (unsigned long) vq_req; - wr->rnic_handle = c2dev->adapter_handle; - wr->option = cpu_to_be32(C2_CFG_ADD_ADDR); - - netaddr.ip_addr = inaddr; - netaddr.netmask = inmask; - netaddr.mtu = 0; - - memcpy(wr->data, &netaddr, len); - - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, (union c2wr *) wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail1; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail1; - - reply = - (struct c2wr_rnic_setconfig_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) { - err = -ENOMEM; - goto bail1; - } - - err = c2_errno(reply); - vq_repbuf_free(c2dev, reply); - -bail1: - kfree(wr); -bail0: - vq_req_free(c2dev, vq_req); - return err; -} - -/* - * Delete an IP address from the RNIC interface - */ -int c2_del_addr(struct c2_dev *c2dev, __be32 inaddr, __be32 inmask) -{ - struct c2_vq_req *vq_req; - struct c2wr_rnic_setconfig_req *wr; - struct c2wr_rnic_setconfig_rep *reply; - struct c2_netaddr netaddr; - int err, len; - - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - len = sizeof(struct c2_netaddr); - wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL); - if (!wr) { - err = -ENOMEM; - goto bail0; - } - - c2_wr_set_id(wr, CCWR_RNIC_SETCONFIG); - wr->hdr.context = (unsigned long) vq_req; - wr->rnic_handle = c2dev->adapter_handle; - wr->option = cpu_to_be32(C2_CFG_DEL_ADDR); - - netaddr.ip_addr = inaddr; - netaddr.netmask = inmask; - netaddr.mtu = 0; - - memcpy(wr->data, &netaddr, len); - - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, (union c2wr *) wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail1; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail1; - - reply = - (struct c2wr_rnic_setconfig_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) { - err = -ENOMEM; - goto bail1; - } - - err = c2_errno(reply); - vq_repbuf_free(c2dev, reply); - -bail1: - kfree(wr); -bail0: - vq_req_free(c2dev, vq_req); - return err; -} - -/* - * Open a single RNIC instance to use with all - * low level openib calls - */ -static int c2_rnic_open(struct c2_dev *c2dev) -{ - struct c2_vq_req *vq_req; - union c2wr wr; - struct c2wr_rnic_open_rep *reply; - int err; - - vq_req = vq_req_alloc(c2dev); - if (vq_req == NULL) { - return -ENOMEM; - } - - memset(&wr, 0, sizeof(wr)); - c2_wr_set_id(&wr, CCWR_RNIC_OPEN); - wr.rnic_open.req.hdr.context = (unsigned long) (vq_req); - wr.rnic_open.req.flags = cpu_to_be16(RNIC_PRIV_MODE); - wr.rnic_open.req.port_num = cpu_to_be16(0); - wr.rnic_open.req.user_context = (unsigned long) c2dev; - - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, &wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) { - goto bail0; - } - - reply = (struct c2wr_rnic_open_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) { - err = -ENOMEM; - goto bail0; - } - - if ((err = c2_errno(reply)) != 0) { - goto bail1; - } - - c2dev->adapter_handle = reply->rnic_handle; - -bail1: - vq_repbuf_free(c2dev, reply); -bail0: - vq_req_free(c2dev, vq_req); - return err; -} - -/* - * Close the RNIC instance - */ -static int c2_rnic_close(struct c2_dev *c2dev) -{ - struct c2_vq_req *vq_req; - union c2wr wr; - struct c2wr_rnic_close_rep *reply; - int err; - - vq_req = vq_req_alloc(c2dev); - if (vq_req == NULL) { - return -ENOMEM; - } - - memset(&wr, 0, sizeof(wr)); - c2_wr_set_id(&wr, CCWR_RNIC_CLOSE); - wr.rnic_close.req.hdr.context = (unsigned long) vq_req; - wr.rnic_close.req.rnic_handle = c2dev->adapter_handle; - - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, &wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) { - goto bail0; - } - - reply = (struct c2wr_rnic_close_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) { - err = -ENOMEM; - goto bail0; - } - - if ((err = c2_errno(reply)) != 0) { - goto bail1; - } - - c2dev->adapter_handle = 0; - -bail1: - vq_repbuf_free(c2dev, reply); -bail0: - vq_req_free(c2dev, vq_req); - return err; -} - -/* - * Called by c2_probe to initialize the RNIC. This principally - * involves initializing the various limits and resource pools that - * comprise the RNIC instance. - */ -int c2_rnic_init(struct c2_dev *c2dev) -{ - int err; - u32 qsize, msgsize; - void *q1_pages; - void *q2_pages; - void __iomem *mmio_regs; - - /* Device capabilities */ - c2dev->device_cap_flags = - (IB_DEVICE_RESIZE_MAX_WR | - IB_DEVICE_CURR_QP_STATE_MOD | - IB_DEVICE_SYS_IMAGE_GUID | - IB_DEVICE_LOCAL_DMA_LKEY | - IB_DEVICE_MEM_WINDOW); - - /* Allocate the qptr_array */ - c2dev->qptr_array = vzalloc(C2_MAX_CQS * sizeof(void *)); - if (!c2dev->qptr_array) { - return -ENOMEM; - } - - /* Initialize the qptr_array */ - c2dev->qptr_array[0] = (void *) &c2dev->req_vq; - c2dev->qptr_array[1] = (void *) &c2dev->rep_vq; - c2dev->qptr_array[2] = (void *) &c2dev->aeq; - - /* Initialize data structures */ - init_waitqueue_head(&c2dev->req_vq_wo); - spin_lock_init(&c2dev->vqlock); - spin_lock_init(&c2dev->lock); - - /* Allocate MQ shared pointer pool for kernel clients. User - * mode client pools are hung off the user context - */ - err = c2_init_mqsp_pool(c2dev, GFP_KERNEL, &c2dev->kern_mqsp_pool); - if (err) { - goto bail0; - } - - /* Allocate shared pointers for Q0, Q1, and Q2 from - * the shared pointer pool. - */ - - c2dev->hint_count = c2_alloc_mqsp(c2dev, c2dev->kern_mqsp_pool, - &c2dev->hint_count_dma, - GFP_KERNEL); - c2dev->req_vq.shared = c2_alloc_mqsp(c2dev, c2dev->kern_mqsp_pool, - &c2dev->req_vq.shared_dma, - GFP_KERNEL); - c2dev->rep_vq.shared = c2_alloc_mqsp(c2dev, c2dev->kern_mqsp_pool, - &c2dev->rep_vq.shared_dma, - GFP_KERNEL); - c2dev->aeq.shared = c2_alloc_mqsp(c2dev, c2dev->kern_mqsp_pool, - &c2dev->aeq.shared_dma, GFP_KERNEL); - if (!c2dev->hint_count || !c2dev->req_vq.shared || - !c2dev->rep_vq.shared || !c2dev->aeq.shared) { - err = -ENOMEM; - goto bail1; - } - - mmio_regs = c2dev->kva; - /* Initialize the Verbs Request Queue */ - c2_mq_req_init(&c2dev->req_vq, 0, - be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q0_QSIZE)), - be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q0_MSGSIZE)), - mmio_regs + - be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q0_POOLSTART)), - mmio_regs + - be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q0_SHARED)), - C2_MQ_ADAPTER_TARGET); - - /* Initialize the Verbs Reply Queue */ - qsize = be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q1_QSIZE)); - msgsize = be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q1_MSGSIZE)); - q1_pages = dma_alloc_coherent(&c2dev->pcidev->dev, qsize * msgsize, - &c2dev->rep_vq.host_dma, GFP_KERNEL); - if (!q1_pages) { - err = -ENOMEM; - goto bail1; - } - dma_unmap_addr_set(&c2dev->rep_vq, mapping, c2dev->rep_vq.host_dma); - pr_debug("%s rep_vq va %p dma %llx\n", __func__, q1_pages, - (unsigned long long) c2dev->rep_vq.host_dma); - c2_mq_rep_init(&c2dev->rep_vq, - 1, - qsize, - msgsize, - q1_pages, - mmio_regs + - be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q1_SHARED)), - C2_MQ_HOST_TARGET); - - /* Initialize the Asynchronus Event Queue */ - qsize = be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q2_QSIZE)); - msgsize = be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q2_MSGSIZE)); - q2_pages = dma_alloc_coherent(&c2dev->pcidev->dev, qsize * msgsize, - &c2dev->aeq.host_dma, GFP_KERNEL); - if (!q2_pages) { - err = -ENOMEM; - goto bail2; - } - dma_unmap_addr_set(&c2dev->aeq, mapping, c2dev->aeq.host_dma); - pr_debug("%s aeq va %p dma %llx\n", __func__, q2_pages, - (unsigned long long) c2dev->aeq.host_dma); - c2_mq_rep_init(&c2dev->aeq, - 2, - qsize, - msgsize, - q2_pages, - mmio_regs + - be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q2_SHARED)), - C2_MQ_HOST_TARGET); - - /* Initialize the verbs request allocator */ - err = vq_init(c2dev); - if (err) - goto bail3; - - /* Enable interrupts on the adapter */ - writel(0, c2dev->regs + C2_IDIS); - - /* create the WR init message */ - err = c2_adapter_init(c2dev); - if (err) - goto bail4; - c2dev->init++; - - /* open an adapter instance */ - err = c2_rnic_open(c2dev); - if (err) - goto bail4; - - /* Initialize cached the adapter limits */ - err = c2_rnic_query(c2dev, &c2dev->props); - if (err) - goto bail5; - - /* Initialize the PD pool */ - err = c2_init_pd_table(c2dev); - if (err) - goto bail5; - - /* Initialize the QP pool */ - c2_init_qp_table(c2dev); - return 0; - -bail5: - c2_rnic_close(c2dev); -bail4: - vq_term(c2dev); -bail3: - dma_free_coherent(&c2dev->pcidev->dev, - c2dev->aeq.q_size * c2dev->aeq.msg_size, - q2_pages, dma_unmap_addr(&c2dev->aeq, mapping)); -bail2: - dma_free_coherent(&c2dev->pcidev->dev, - c2dev->rep_vq.q_size * c2dev->rep_vq.msg_size, - q1_pages, dma_unmap_addr(&c2dev->rep_vq, mapping)); -bail1: - c2_free_mqsp_pool(c2dev, c2dev->kern_mqsp_pool); -bail0: - vfree(c2dev->qptr_array); - - return err; -} - -/* - * Called by c2_remove to cleanup the RNIC resources. - */ -void c2_rnic_term(struct c2_dev *c2dev) -{ - - /* Close the open adapter instance */ - c2_rnic_close(c2dev); - - /* Send the TERM message to the adapter */ - c2_adapter_term(c2dev); - - /* Disable interrupts on the adapter */ - writel(1, c2dev->regs + C2_IDIS); - - /* Free the QP pool */ - c2_cleanup_qp_table(c2dev); - - /* Free the PD pool */ - c2_cleanup_pd_table(c2dev); - - /* Free the verbs request allocator */ - vq_term(c2dev); - - /* Free the asynchronus event queue */ - dma_free_coherent(&c2dev->pcidev->dev, - c2dev->aeq.q_size * c2dev->aeq.msg_size, - c2dev->aeq.msg_pool.host, - dma_unmap_addr(&c2dev->aeq, mapping)); - - /* Free the verbs reply queue */ - dma_free_coherent(&c2dev->pcidev->dev, - c2dev->rep_vq.q_size * c2dev->rep_vq.msg_size, - c2dev->rep_vq.msg_pool.host, - dma_unmap_addr(&c2dev->rep_vq, mapping)); - - /* Free the MQ shared pointer pool */ - c2_free_mqsp_pool(c2dev, c2dev->kern_mqsp_pool); - - /* Free the qptr_array */ - vfree(c2dev->qptr_array); - - return; -} diff --git a/drivers/staging/rdma/amso1100/c2_status.h b/drivers/staging/rdma/amso1100/c2_status.h deleted file mode 100644 index 6ee4aa92d875..000000000000 --- a/drivers/staging/rdma/amso1100/c2_status.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef _C2_STATUS_H_ -#define _C2_STATUS_H_ - -/* - * Verbs Status Codes - */ -enum c2_status { - C2_OK = 0, /* This must be zero */ - CCERR_INSUFFICIENT_RESOURCES = 1, - CCERR_INVALID_MODIFIER = 2, - CCERR_INVALID_MODE = 3, - CCERR_IN_USE = 4, - CCERR_INVALID_RNIC = 5, - CCERR_INTERRUPTED_OPERATION = 6, - CCERR_INVALID_EH = 7, - CCERR_INVALID_CQ = 8, - CCERR_CQ_EMPTY = 9, - CCERR_NOT_IMPLEMENTED = 10, - CCERR_CQ_DEPTH_TOO_SMALL = 11, - CCERR_PD_IN_USE = 12, - CCERR_INVALID_PD = 13, - CCERR_INVALID_SRQ = 14, - CCERR_INVALID_ADDRESS = 15, - CCERR_INVALID_NETMASK = 16, - CCERR_INVALID_QP = 17, - CCERR_INVALID_QP_STATE = 18, - CCERR_TOO_MANY_WRS_POSTED = 19, - CCERR_INVALID_WR_TYPE = 20, - CCERR_INVALID_SGL_LENGTH = 21, - CCERR_INVALID_SQ_DEPTH = 22, - CCERR_INVALID_RQ_DEPTH = 23, - CCERR_INVALID_ORD = 24, - CCERR_INVALID_IRD = 25, - CCERR_QP_ATTR_CANNOT_CHANGE = 26, - CCERR_INVALID_STAG = 27, - CCERR_QP_IN_USE = 28, - CCERR_OUTSTANDING_WRS = 29, - CCERR_STAG_IN_USE = 30, - CCERR_INVALID_STAG_INDEX = 31, - CCERR_INVALID_SGL_FORMAT = 32, - CCERR_ADAPTER_TIMEOUT = 33, - CCERR_INVALID_CQ_DEPTH = 34, - CCERR_INVALID_PRIVATE_DATA_LENGTH = 35, - CCERR_INVALID_EP = 36, - CCERR_MR_IN_USE = CCERR_STAG_IN_USE, - CCERR_FLUSHED = 38, - CCERR_INVALID_WQE = 39, - CCERR_LOCAL_QP_CATASTROPHIC_ERROR = 40, - CCERR_REMOTE_TERMINATION_ERROR = 41, - CCERR_BASE_AND_BOUNDS_VIOLATION = 42, - CCERR_ACCESS_VIOLATION = 43, - CCERR_INVALID_PD_ID = 44, - CCERR_WRAP_ERROR = 45, - CCERR_INV_STAG_ACCESS_ERROR = 46, - CCERR_ZERO_RDMA_READ_RESOURCES = 47, - CCERR_QP_NOT_PRIVILEGED = 48, - CCERR_STAG_STATE_NOT_INVALID = 49, - CCERR_INVALID_PAGE_SIZE = 50, - CCERR_INVALID_BUFFER_SIZE = 51, - CCERR_INVALID_PBE = 52, - CCERR_INVALID_FBO = 53, - CCERR_INVALID_LENGTH = 54, - CCERR_INVALID_ACCESS_RIGHTS = 55, - CCERR_PBL_TOO_BIG = 56, - CCERR_INVALID_VA = 57, - CCERR_INVALID_REGION = 58, - CCERR_INVALID_WINDOW = 59, - CCERR_TOTAL_LENGTH_TOO_BIG = 60, - CCERR_INVALID_QP_ID = 61, - CCERR_ADDR_IN_USE = 62, - CCERR_ADDR_NOT_AVAIL = 63, - CCERR_NET_DOWN = 64, - CCERR_NET_UNREACHABLE = 65, - CCERR_CONN_ABORTED = 66, - CCERR_CONN_RESET = 67, - CCERR_NO_BUFS = 68, - CCERR_CONN_TIMEDOUT = 69, - CCERR_CONN_REFUSED = 70, - CCERR_HOST_UNREACHABLE = 71, - CCERR_INVALID_SEND_SGL_DEPTH = 72, - CCERR_INVALID_RECV_SGL_DEPTH = 73, - CCERR_INVALID_RDMA_WRITE_SGL_DEPTH = 74, - CCERR_INSUFFICIENT_PRIVILEGES = 75, - CCERR_STACK_ERROR = 76, - CCERR_INVALID_VERSION = 77, - CCERR_INVALID_MTU = 78, - CCERR_INVALID_IMAGE = 79, - CCERR_PENDING = 98, /* not an error; user internally by adapter */ - CCERR_DEFER = 99, /* not an error; used internally by adapter */ - CCERR_FAILED_WRITE = 100, - CCERR_FAILED_ERASE = 101, - CCERR_FAILED_VERIFICATION = 102, - CCERR_NOT_FOUND = 103, - -}; - -/* - * CCAE_ACTIVE_CONNECT_RESULTS status result codes. - */ -enum c2_connect_status { - C2_CONN_STATUS_SUCCESS = C2_OK, - C2_CONN_STATUS_NO_MEM = CCERR_INSUFFICIENT_RESOURCES, - C2_CONN_STATUS_TIMEDOUT = CCERR_CONN_TIMEDOUT, - C2_CONN_STATUS_REFUSED = CCERR_CONN_REFUSED, - C2_CONN_STATUS_NETUNREACH = CCERR_NET_UNREACHABLE, - C2_CONN_STATUS_HOSTUNREACH = CCERR_HOST_UNREACHABLE, - C2_CONN_STATUS_INVALID_RNIC = CCERR_INVALID_RNIC, - C2_CONN_STATUS_INVALID_QP = CCERR_INVALID_QP, - C2_CONN_STATUS_INVALID_QP_STATE = CCERR_INVALID_QP_STATE, - C2_CONN_STATUS_REJECTED = CCERR_CONN_RESET, - C2_CONN_STATUS_ADDR_NOT_AVAIL = CCERR_ADDR_NOT_AVAIL, -}; - -/* - * Flash programming status codes. - */ -enum c2_flash_status { - C2_FLASH_STATUS_SUCCESS = 0x0000, - C2_FLASH_STATUS_VERIFY_ERR = 0x0002, - C2_FLASH_STATUS_IMAGE_ERR = 0x0004, - C2_FLASH_STATUS_ECLBS = 0x0400, - C2_FLASH_STATUS_PSLBS = 0x0800, - C2_FLASH_STATUS_VPENS = 0x1000, -}; - -#endif /* _C2_STATUS_H_ */ diff --git a/drivers/staging/rdma/amso1100/c2_user.h b/drivers/staging/rdma/amso1100/c2_user.h deleted file mode 100644 index 7e9e7ad65467..000000000000 --- a/drivers/staging/rdma/amso1100/c2_user.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifndef C2_USER_H -#define C2_USER_H - -#include - -/* - * Make sure that all structs defined in this file remain laid out so - * that they pack the same way on 32-bit and 64-bit architectures (to - * avoid incompatibility between 32-bit userspace and 64-bit kernels). - * In particular do not use pointer types -- pass pointers in __u64 - * instead. - */ - -struct c2_alloc_ucontext_resp { - __u32 qp_tab_size; - __u32 uarc_size; -}; - -struct c2_alloc_pd_resp { - __u32 pdn; - __u32 reserved; -}; - -struct c2_create_cq { - __u32 lkey; - __u32 pdn; - __u64 arm_db_page; - __u64 set_db_page; - __u32 arm_db_index; - __u32 set_db_index; -}; - -struct c2_create_cq_resp { - __u32 cqn; - __u32 reserved; -}; - -struct c2_create_qp { - __u32 lkey; - __u32 reserved; - __u64 sq_db_page; - __u64 rq_db_page; - __u32 sq_db_index; - __u32 rq_db_index; -}; - -#endif /* C2_USER_H */ diff --git a/drivers/staging/rdma/amso1100/c2_vq.c b/drivers/staging/rdma/amso1100/c2_vq.c deleted file mode 100644 index 2ec716fb2edb..000000000000 --- a/drivers/staging/rdma/amso1100/c2_vq.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include -#include - -#include "c2_vq.h" -#include "c2_provider.h" - -/* - * Verbs Request Objects: - * - * VQ Request Objects are allocated by the kernel verbs handlers. - * They contain a wait object, a refcnt, an atomic bool indicating that the - * adapter has replied, and a copy of the verb reply work request. - * A pointer to the VQ Request Object is passed down in the context - * field of the work request message, and reflected back by the adapter - * in the verbs reply message. The function handle_vq() in the interrupt - * path will use this pointer to: - * 1) append a copy of the verbs reply message - * 2) mark that the reply is ready - * 3) wake up the kernel verbs handler blocked awaiting the reply. - * - * - * The kernel verbs handlers do a "get" to put a 2nd reference on the - * VQ Request object. If the kernel verbs handler exits before the adapter - * can respond, this extra reference will keep the VQ Request object around - * until the adapter's reply can be processed. The reason we need this is - * because a pointer to this object is stuffed into the context field of - * the verbs work request message, and reflected back in the reply message. - * It is used in the interrupt handler (handle_vq()) to wake up the appropriate - * kernel verb handler that is blocked awaiting the verb reply. - * So handle_vq() will do a "put" on the object when it's done accessing it. - * NOTE: If we guarantee that the kernel verb handler will never bail before - * getting the reply, then we don't need these refcnts. - * - * - * VQ Request objects are freed by the kernel verbs handlers only - * after the verb has been processed, or when the adapter fails and - * does not reply. - * - * - * Verbs Reply Buffers: - * - * VQ Reply bufs are local host memory copies of a - * outstanding Verb Request reply - * message. The are always allocated by the kernel verbs handlers, and _may_ be - * freed by either the kernel verbs handler -or- the interrupt handler. The - * kernel verbs handler _must_ free the repbuf, then free the vq request object - * in that order. - */ - -int vq_init(struct c2_dev *c2dev) -{ - sprintf(c2dev->vq_cache_name, "c2-vq:dev%c", - (char) ('0' + c2dev->devnum)); - c2dev->host_msg_cache = - kmem_cache_create(c2dev->vq_cache_name, c2dev->rep_vq.msg_size, 0, - SLAB_HWCACHE_ALIGN, NULL); - if (c2dev->host_msg_cache == NULL) { - return -ENOMEM; - } - return 0; -} - -void vq_term(struct c2_dev *c2dev) -{ - kmem_cache_destroy(c2dev->host_msg_cache); -} - -/* vq_req_alloc - allocate a VQ Request Object and initialize it. - * The refcnt is set to 1. - */ -struct c2_vq_req *vq_req_alloc(struct c2_dev *c2dev) -{ - struct c2_vq_req *r; - - r = kmalloc(sizeof(struct c2_vq_req), GFP_KERNEL); - if (r) { - init_waitqueue_head(&r->wait_object); - r->reply_msg = 0; - r->event = 0; - r->cm_id = NULL; - r->qp = NULL; - atomic_set(&r->refcnt, 1); - atomic_set(&r->reply_ready, 0); - } - return r; -} - - -/* vq_req_free - free the VQ Request Object. It is assumed the verbs handler - * has already free the VQ Reply Buffer if it existed. - */ -void vq_req_free(struct c2_dev *c2dev, struct c2_vq_req *r) -{ - r->reply_msg = 0; - if (atomic_dec_and_test(&r->refcnt)) { - kfree(r); - } -} - -/* vq_req_get - reference a VQ Request Object. Done - * only in the kernel verbs handlers. - */ -void vq_req_get(struct c2_dev *c2dev, struct c2_vq_req *r) -{ - atomic_inc(&r->refcnt); -} - - -/* vq_req_put - dereference and potentially free a VQ Request Object. - * - * This is only called by handle_vq() on the - * interrupt when it is done processing - * a verb reply message. If the associated - * kernel verbs handler has already bailed, - * then this put will actually free the VQ - * Request object _and_ the VQ Reply Buffer - * if it exists. - */ -void vq_req_put(struct c2_dev *c2dev, struct c2_vq_req *r) -{ - if (atomic_dec_and_test(&r->refcnt)) { - if (r->reply_msg != 0) - vq_repbuf_free(c2dev, - (void *) (unsigned long) r->reply_msg); - kfree(r); - } -} - - -/* - * vq_repbuf_alloc - allocate a VQ Reply Buffer. - */ -void *vq_repbuf_alloc(struct c2_dev *c2dev) -{ - return kmem_cache_alloc(c2dev->host_msg_cache, GFP_ATOMIC); -} - -/* - * vq_send_wr - post a verbs request message to the Verbs Request Queue. - * If a message is not available in the MQ, then block until one is available. - * NOTE: handle_mq() on the interrupt context will wake up threads blocked here. - * When the adapter drains the Verbs Request Queue, - * it inserts MQ index 0 in to the - * adapter->host activity fifo and interrupts the host. - */ -int vq_send_wr(struct c2_dev *c2dev, union c2wr *wr) -{ - void *msg; - wait_queue_t __wait; - - /* - * grab adapter vq lock - */ - spin_lock(&c2dev->vqlock); - - /* - * allocate msg - */ - msg = c2_mq_alloc(&c2dev->req_vq); - - /* - * If we cannot get a msg, then we'll wait - * When a messages are available, the int handler will wake_up() - * any waiters. - */ - while (msg == NULL) { - pr_debug("%s:%d no available msg in VQ, waiting...\n", - __func__, __LINE__); - init_waitqueue_entry(&__wait, current); - add_wait_queue(&c2dev->req_vq_wo, &__wait); - spin_unlock(&c2dev->vqlock); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (!c2_mq_full(&c2dev->req_vq)) { - break; - } - if (!signal_pending(current)) { - schedule_timeout(1 * HZ); /* 1 second... */ - continue; - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&c2dev->req_vq_wo, &__wait); - return -EINTR; - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&c2dev->req_vq_wo, &__wait); - spin_lock(&c2dev->vqlock); - msg = c2_mq_alloc(&c2dev->req_vq); - } - - /* - * copy wr into adapter msg - */ - memcpy(msg, wr, c2dev->req_vq.msg_size); - - /* - * post msg - */ - c2_mq_produce(&c2dev->req_vq); - - /* - * release adapter vq lock - */ - spin_unlock(&c2dev->vqlock); - return 0; -} - - -/* - * vq_wait_for_reply - block until the adapter posts a Verb Reply Message. - */ -int vq_wait_for_reply(struct c2_dev *c2dev, struct c2_vq_req *req) -{ - if (!wait_event_timeout(req->wait_object, - atomic_read(&req->reply_ready), - 60*HZ)) - return -ETIMEDOUT; - - return 0; -} - -/* - * vq_repbuf_free - Free a Verbs Reply Buffer. - */ -void vq_repbuf_free(struct c2_dev *c2dev, void *reply) -{ - kmem_cache_free(c2dev->host_msg_cache, reply); -} diff --git a/drivers/staging/rdma/amso1100/c2_vq.h b/drivers/staging/rdma/amso1100/c2_vq.h deleted file mode 100644 index c1f6cef60213..000000000000 --- a/drivers/staging/rdma/amso1100/c2_vq.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef _C2_VQ_H_ -#define _C2_VQ_H_ -#include -#include "c2.h" -#include "c2_wr.h" -#include "c2_provider.h" - -struct c2_vq_req { - u64 reply_msg; /* ptr to reply msg */ - wait_queue_head_t wait_object; /* wait object for vq reqs */ - atomic_t reply_ready; /* set when reply is ready */ - atomic_t refcnt; /* used to cancel WRs... */ - int event; - struct iw_cm_id *cm_id; - struct c2_qp *qp; -}; - -int vq_init(struct c2_dev *c2dev); -void vq_term(struct c2_dev *c2dev); - -struct c2_vq_req *vq_req_alloc(struct c2_dev *c2dev); -void vq_req_free(struct c2_dev *c2dev, struct c2_vq_req *req); -void vq_req_get(struct c2_dev *c2dev, struct c2_vq_req *req); -void vq_req_put(struct c2_dev *c2dev, struct c2_vq_req *req); -int vq_send_wr(struct c2_dev *c2dev, union c2wr * wr); - -void *vq_repbuf_alloc(struct c2_dev *c2dev); -void vq_repbuf_free(struct c2_dev *c2dev, void *reply); - -int vq_wait_for_reply(struct c2_dev *c2dev, struct c2_vq_req *req); -#endif /* _C2_VQ_H_ */ diff --git a/drivers/staging/rdma/amso1100/c2_wr.h b/drivers/staging/rdma/amso1100/c2_wr.h deleted file mode 100644 index 8d4b4ca463ca..000000000000 --- a/drivers/staging/rdma/amso1100/c2_wr.h +++ /dev/null @@ -1,1520 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef _C2_WR_H_ -#define _C2_WR_H_ - -#ifdef CCDEBUG -#define CCWR_MAGIC 0xb07700b0 -#endif - -#define C2_QP_NO_ATTR_CHANGE 0xFFFFFFFF - -/* Maximum allowed size in bytes of private_data exchange - * on connect. - */ -#define C2_MAX_PRIVATE_DATA_SIZE 200 - -/* - * These types are shared among the adapter, host, and CCIL consumer. - */ -enum c2_cq_notification_type { - C2_CQ_NOTIFICATION_TYPE_NONE = 1, - C2_CQ_NOTIFICATION_TYPE_NEXT, - C2_CQ_NOTIFICATION_TYPE_NEXT_SE -}; - -enum c2_setconfig_cmd { - C2_CFG_ADD_ADDR = 1, - C2_CFG_DEL_ADDR = 2, - C2_CFG_ADD_ROUTE = 3, - C2_CFG_DEL_ROUTE = 4 -}; - -enum c2_getconfig_cmd { - C2_GETCONFIG_ROUTES = 1, - C2_GETCONFIG_ADDRS -}; - -/* - * CCIL Work Request Identifiers - */ -enum c2wr_ids { - CCWR_RNIC_OPEN = 1, - CCWR_RNIC_QUERY, - CCWR_RNIC_SETCONFIG, - CCWR_RNIC_GETCONFIG, - CCWR_RNIC_CLOSE, - CCWR_CQ_CREATE, - CCWR_CQ_QUERY, - CCWR_CQ_MODIFY, - CCWR_CQ_DESTROY, - CCWR_QP_CONNECT, - CCWR_PD_ALLOC, - CCWR_PD_DEALLOC, - CCWR_SRQ_CREATE, - CCWR_SRQ_QUERY, - CCWR_SRQ_MODIFY, - CCWR_SRQ_DESTROY, - CCWR_QP_CREATE, - CCWR_QP_QUERY, - CCWR_QP_MODIFY, - CCWR_QP_DESTROY, - CCWR_NSMR_STAG_ALLOC, - CCWR_NSMR_REGISTER, - CCWR_NSMR_PBL, - CCWR_STAG_DEALLOC, - CCWR_NSMR_REREGISTER, - CCWR_SMR_REGISTER, - CCWR_MR_QUERY, - CCWR_MW_ALLOC, - CCWR_MW_QUERY, - CCWR_EP_CREATE, - CCWR_EP_GETOPT, - CCWR_EP_SETOPT, - CCWR_EP_DESTROY, - CCWR_EP_BIND, - CCWR_EP_CONNECT, - CCWR_EP_LISTEN, - CCWR_EP_SHUTDOWN, - CCWR_EP_LISTEN_CREATE, - CCWR_EP_LISTEN_DESTROY, - CCWR_EP_QUERY, - CCWR_CR_ACCEPT, - CCWR_CR_REJECT, - CCWR_CONSOLE, - CCWR_TERM, - CCWR_FLASH_INIT, - CCWR_FLASH, - CCWR_BUF_ALLOC, - CCWR_BUF_FREE, - CCWR_FLASH_WRITE, - CCWR_INIT, /* WARNING: Don't move this ever again! */ - - - - /* Add new IDs here */ - - - - /* - * WARNING: CCWR_LAST must always be the last verbs id defined! - * All the preceding IDs are fixed, and must not change. - * You can add new IDs, but must not remove or reorder - * any IDs. If you do, YOU will ruin any hope of - * compatibility between versions. - */ - CCWR_LAST, - - /* - * Start over at 1 so that arrays indexed by user wr id's - * begin at 1. This is OK since the verbs and user wr id's - * are always used on disjoint sets of queues. - */ - /* - * The order of the CCWR_SEND_XX verbs must - * match the order of the RDMA_OPs - */ - CCWR_SEND = 1, - CCWR_SEND_INV, - CCWR_SEND_SE, - CCWR_SEND_SE_INV, - CCWR_RDMA_WRITE, - CCWR_RDMA_READ, - CCWR_RDMA_READ_INV, - CCWR_MW_BIND, - CCWR_NSMR_FASTREG, - CCWR_STAG_INVALIDATE, - CCWR_RECV, - CCWR_NOP, - CCWR_UNIMPL, -/* WARNING: This must always be the last user wr id defined! */ -}; -#define RDMA_SEND_OPCODE_FROM_WR_ID(x) (x+2) - -/* - * SQ/RQ Work Request Types - */ -enum c2_wr_type { - C2_WR_TYPE_SEND = CCWR_SEND, - C2_WR_TYPE_SEND_SE = CCWR_SEND_SE, - C2_WR_TYPE_SEND_INV = CCWR_SEND_INV, - C2_WR_TYPE_SEND_SE_INV = CCWR_SEND_SE_INV, - C2_WR_TYPE_RDMA_WRITE = CCWR_RDMA_WRITE, - C2_WR_TYPE_RDMA_READ = CCWR_RDMA_READ, - C2_WR_TYPE_RDMA_READ_INV_STAG = CCWR_RDMA_READ_INV, - C2_WR_TYPE_BIND_MW = CCWR_MW_BIND, - C2_WR_TYPE_FASTREG_NSMR = CCWR_NSMR_FASTREG, - C2_WR_TYPE_INV_STAG = CCWR_STAG_INVALIDATE, - C2_WR_TYPE_RECV = CCWR_RECV, - C2_WR_TYPE_NOP = CCWR_NOP, -}; - -struct c2_netaddr { - __be32 ip_addr; - __be32 netmask; - u32 mtu; -}; - -struct c2_route { - u32 ip_addr; /* 0 indicates the default route */ - u32 netmask; /* netmask associated with dst */ - u32 flags; - union { - u32 ipaddr; /* address of the nexthop interface */ - u8 enaddr[6]; - } nexthop; -}; - -/* - * A Scatter Gather Entry. - */ -struct c2_data_addr { - __be32 stag; - __be32 length; - __be64 to; -}; - -/* - * MR and MW flags used by the consumer, RI, and RNIC. - */ -enum c2_mm_flags { - MEM_REMOTE = 0x0001, /* allow mw binds with remote access. */ - MEM_VA_BASED = 0x0002, /* Not Zero-based */ - MEM_PBL_COMPLETE = 0x0004, /* PBL array is complete in this msg */ - MEM_LOCAL_READ = 0x0008, /* allow local reads */ - MEM_LOCAL_WRITE = 0x0010, /* allow local writes */ - MEM_REMOTE_READ = 0x0020, /* allow remote reads */ - MEM_REMOTE_WRITE = 0x0040, /* allow remote writes */ - MEM_WINDOW_BIND = 0x0080, /* binds allowed */ - MEM_SHARED = 0x0100, /* set if MR is shared */ - MEM_STAG_VALID = 0x0200 /* set if STAG is in valid state */ -}; - -/* - * CCIL API ACF flags defined in terms of the low level mem flags. - * This minimizes translation needed in the user API - */ -enum c2_acf { - C2_ACF_LOCAL_READ = MEM_LOCAL_READ, - C2_ACF_LOCAL_WRITE = MEM_LOCAL_WRITE, - C2_ACF_REMOTE_READ = MEM_REMOTE_READ, - C2_ACF_REMOTE_WRITE = MEM_REMOTE_WRITE, - C2_ACF_WINDOW_BIND = MEM_WINDOW_BIND -}; - -/* - * Image types of objects written to flash - */ -#define C2_FLASH_IMG_BITFILE 1 -#define C2_FLASH_IMG_OPTION_ROM 2 -#define C2_FLASH_IMG_VPD 3 - -/* - * to fix bug 1815 we define the max size allowable of the - * terminate message (per the IETF spec).Refer to the IETF - * protocol specification, section 12.1.6, page 64) - * The message is prefixed by 20 types of DDP info. - * - * Then the message has 6 bytes for the terminate control - * and DDP segment length info plus a DDP header (either - * 14 or 18 byts) plus 28 bytes for the RDMA header. - * Thus the max size in: - * 20 + (6 + 18 + 28) = 72 - */ -#define C2_MAX_TERMINATE_MESSAGE_SIZE (72) - -/* - * Build String Length. It must be the same as C2_BUILD_STR_LEN in ccil_api.h - */ -#define WR_BUILD_STR_LEN 64 - -/* - * WARNING: All of these structs need to align any 64bit types on - * 64 bit boundaries! 64bit types include u64 and u64. - */ - -/* - * Clustercore Work Request Header. Be sensitive to field layout - * and alignment. - */ -struct c2wr_hdr { - /* wqe_count is part of the cqe. It is put here so the - * adapter can write to it while the wr is pending without - * clobbering part of the wr. This word need not be dma'd - * from the host to adapter by libccil, but we copy it anyway - * to make the memcpy to the adapter better aligned. - */ - __be32 wqe_count; - - /* Put these fields next so that later 32- and 64-bit - * quantities are naturally aligned. - */ - u8 id; - u8 result; /* adapter -> host */ - u8 sge_count; /* host -> adapter */ - u8 flags; /* host -> adapter */ - - u64 context; -#ifdef CCMSGMAGIC - u32 magic; - u32 pad; -#endif -} __attribute__((packed)); - -/* - *------------------------ RNIC ------------------------ - */ - -/* - * WR_RNIC_OPEN - */ - -/* - * Flags for the RNIC WRs - */ -enum c2_rnic_flags { - RNIC_IRD_STATIC = 0x0001, - RNIC_ORD_STATIC = 0x0002, - RNIC_QP_STATIC = 0x0004, - RNIC_SRQ_SUPPORTED = 0x0008, - RNIC_PBL_BLOCK_MODE = 0x0010, - RNIC_SRQ_MODEL_ARRIVAL = 0x0020, - RNIC_CQ_OVF_DETECTED = 0x0040, - RNIC_PRIV_MODE = 0x0080 -}; - -struct c2wr_rnic_open_req { - struct c2wr_hdr hdr; - u64 user_context; - __be16 flags; /* See enum c2_rnic_flags */ - __be16 port_num; -} __attribute__((packed)); - -struct c2wr_rnic_open_rep { - struct c2wr_hdr hdr; - u32 rnic_handle; -} __attribute__((packed)); - -union c2wr_rnic_open { - struct c2wr_rnic_open_req req; - struct c2wr_rnic_open_rep rep; -} __attribute__((packed)); - -struct c2wr_rnic_query_req { - struct c2wr_hdr hdr; - u32 rnic_handle; -} __attribute__((packed)); - -/* - * WR_RNIC_QUERY - */ -struct c2wr_rnic_query_rep { - struct c2wr_hdr hdr; - u64 user_context; - __be32 vendor_id; - __be32 part_number; - __be32 hw_version; - __be32 fw_ver_major; - __be32 fw_ver_minor; - __be32 fw_ver_patch; - char fw_ver_build_str[WR_BUILD_STR_LEN]; - __be32 max_qps; - __be32 max_qp_depth; - u32 max_srq_depth; - u32 max_send_sgl_depth; - u32 max_rdma_sgl_depth; - __be32 max_cqs; - __be32 max_cq_depth; - u32 max_cq_event_handlers; - __be32 max_mrs; - u32 max_pbl_depth; - __be32 max_pds; - __be32 max_global_ird; - u32 max_global_ord; - __be32 max_qp_ird; - __be32 max_qp_ord; - u32 flags; - __be32 max_mws; - u32 pbe_range_low; - u32 pbe_range_high; - u32 max_srqs; - u32 page_size; -} __attribute__((packed)); - -union c2wr_rnic_query { - struct c2wr_rnic_query_req req; - struct c2wr_rnic_query_rep rep; -} __attribute__((packed)); - -/* - * WR_RNIC_GETCONFIG - */ - -struct c2wr_rnic_getconfig_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 option; /* see c2_getconfig_cmd_t */ - u64 reply_buf; - u32 reply_buf_len; -} __attribute__((packed)) ; - -struct c2wr_rnic_getconfig_rep { - struct c2wr_hdr hdr; - u32 option; /* see c2_getconfig_cmd_t */ - u32 count_len; /* length of the number of addresses configured */ -} __attribute__((packed)) ; - -union c2wr_rnic_getconfig { - struct c2wr_rnic_getconfig_req req; - struct c2wr_rnic_getconfig_rep rep; -} __attribute__((packed)) ; - -/* - * WR_RNIC_SETCONFIG - */ -struct c2wr_rnic_setconfig_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - __be32 option; /* See c2_setconfig_cmd_t */ - /* variable data and pad. See c2_netaddr and c2_route */ - u8 data[0]; -} __attribute__((packed)) ; - -struct c2wr_rnic_setconfig_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_rnic_setconfig { - struct c2wr_rnic_setconfig_req req; - struct c2wr_rnic_setconfig_rep rep; -} __attribute__((packed)) ; - -/* - * WR_RNIC_CLOSE - */ -struct c2wr_rnic_close_req { - struct c2wr_hdr hdr; - u32 rnic_handle; -} __attribute__((packed)) ; - -struct c2wr_rnic_close_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_rnic_close { - struct c2wr_rnic_close_req req; - struct c2wr_rnic_close_rep rep; -} __attribute__((packed)) ; - -/* - *------------------------ CQ ------------------------ - */ -struct c2wr_cq_create_req { - struct c2wr_hdr hdr; - __be64 shared_ht; - u64 user_context; - __be64 msg_pool; - u32 rnic_handle; - __be32 msg_size; - __be32 depth; -} __attribute__((packed)) ; - -struct c2wr_cq_create_rep { - struct c2wr_hdr hdr; - __be32 mq_index; - __be32 adapter_shared; - u32 cq_handle; -} __attribute__((packed)) ; - -union c2wr_cq_create { - struct c2wr_cq_create_req req; - struct c2wr_cq_create_rep rep; -} __attribute__((packed)) ; - -struct c2wr_cq_modify_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 cq_handle; - u32 new_depth; - u64 new_msg_pool; -} __attribute__((packed)) ; - -struct c2wr_cq_modify_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_cq_modify { - struct c2wr_cq_modify_req req; - struct c2wr_cq_modify_rep rep; -} __attribute__((packed)) ; - -struct c2wr_cq_destroy_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 cq_handle; -} __attribute__((packed)) ; - -struct c2wr_cq_destroy_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_cq_destroy { - struct c2wr_cq_destroy_req req; - struct c2wr_cq_destroy_rep rep; -} __attribute__((packed)) ; - -/* - *------------------------ PD ------------------------ - */ -struct c2wr_pd_alloc_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 pd_id; -} __attribute__((packed)) ; - -struct c2wr_pd_alloc_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_pd_alloc { - struct c2wr_pd_alloc_req req; - struct c2wr_pd_alloc_rep rep; -} __attribute__((packed)) ; - -struct c2wr_pd_dealloc_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 pd_id; -} __attribute__((packed)) ; - -struct c2wr_pd_dealloc_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_pd_dealloc { - struct c2wr_pd_dealloc_req req; - struct c2wr_pd_dealloc_rep rep; -} __attribute__((packed)) ; - -/* - *------------------------ SRQ ------------------------ - */ -struct c2wr_srq_create_req { - struct c2wr_hdr hdr; - u64 shared_ht; - u64 user_context; - u32 rnic_handle; - u32 srq_depth; - u32 srq_limit; - u32 sgl_depth; - u32 pd_id; -} __attribute__((packed)) ; - -struct c2wr_srq_create_rep { - struct c2wr_hdr hdr; - u32 srq_depth; - u32 sgl_depth; - u32 msg_size; - u32 mq_index; - u32 mq_start; - u32 srq_handle; -} __attribute__((packed)) ; - -union c2wr_srq_create { - struct c2wr_srq_create_req req; - struct c2wr_srq_create_rep rep; -} __attribute__((packed)) ; - -struct c2wr_srq_destroy_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 srq_handle; -} __attribute__((packed)) ; - -struct c2wr_srq_destroy_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_srq_destroy { - struct c2wr_srq_destroy_req req; - struct c2wr_srq_destroy_rep rep; -} __attribute__((packed)) ; - -/* - *------------------------ QP ------------------------ - */ -enum c2wr_qp_flags { - QP_RDMA_READ = 0x00000001, /* RDMA read enabled? */ - QP_RDMA_WRITE = 0x00000002, /* RDMA write enabled? */ - QP_MW_BIND = 0x00000004, /* MWs enabled */ - QP_ZERO_STAG = 0x00000008, /* enabled? */ - QP_REMOTE_TERMINATION = 0x00000010, /* remote end terminated */ - QP_RDMA_READ_RESPONSE = 0x00000020 /* Remote RDMA read */ - /* enabled? */ -}; - -struct c2wr_qp_create_req { - struct c2wr_hdr hdr; - __be64 shared_sq_ht; - __be64 shared_rq_ht; - u64 user_context; - u32 rnic_handle; - u32 sq_cq_handle; - u32 rq_cq_handle; - __be32 sq_depth; - __be32 rq_depth; - u32 srq_handle; - u32 srq_limit; - __be32 flags; /* see enum c2wr_qp_flags */ - __be32 send_sgl_depth; - __be32 recv_sgl_depth; - __be32 rdma_write_sgl_depth; - __be32 ord; - __be32 ird; - u32 pd_id; -} __attribute__((packed)) ; - -struct c2wr_qp_create_rep { - struct c2wr_hdr hdr; - __be32 sq_depth; - __be32 rq_depth; - u32 send_sgl_depth; - u32 recv_sgl_depth; - u32 rdma_write_sgl_depth; - u32 ord; - u32 ird; - __be32 sq_msg_size; - __be32 sq_mq_index; - __be32 sq_mq_start; - __be32 rq_msg_size; - __be32 rq_mq_index; - __be32 rq_mq_start; - u32 qp_handle; -} __attribute__((packed)) ; - -union c2wr_qp_create { - struct c2wr_qp_create_req req; - struct c2wr_qp_create_rep rep; -} __attribute__((packed)) ; - -struct c2wr_qp_query_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 qp_handle; -} __attribute__((packed)) ; - -struct c2wr_qp_query_rep { - struct c2wr_hdr hdr; - u64 user_context; - u32 rnic_handle; - u32 sq_depth; - u32 rq_depth; - u32 send_sgl_depth; - u32 rdma_write_sgl_depth; - u32 recv_sgl_depth; - u32 ord; - u32 ird; - u16 qp_state; - u16 flags; /* see c2wr_qp_flags_t */ - u32 qp_id; - u32 local_addr; - u32 remote_addr; - u16 local_port; - u16 remote_port; - u32 terminate_msg_length; /* 0 if not present */ - u8 data[0]; - /* Terminate Message in-line here. */ -} __attribute__((packed)) ; - -union c2wr_qp_query { - struct c2wr_qp_query_req req; - struct c2wr_qp_query_rep rep; -} __attribute__((packed)) ; - -struct c2wr_qp_modify_req { - struct c2wr_hdr hdr; - u64 stream_msg; - u32 stream_msg_length; - u32 rnic_handle; - u32 qp_handle; - __be32 next_qp_state; - __be32 ord; - __be32 ird; - __be32 sq_depth; - __be32 rq_depth; - u32 llp_ep_handle; -} __attribute__((packed)) ; - -struct c2wr_qp_modify_rep { - struct c2wr_hdr hdr; - u32 ord; - u32 ird; - u32 sq_depth; - u32 rq_depth; - u32 sq_msg_size; - u32 sq_mq_index; - u32 sq_mq_start; - u32 rq_msg_size; - u32 rq_mq_index; - u32 rq_mq_start; -} __attribute__((packed)) ; - -union c2wr_qp_modify { - struct c2wr_qp_modify_req req; - struct c2wr_qp_modify_rep rep; -} __attribute__((packed)) ; - -struct c2wr_qp_destroy_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 qp_handle; -} __attribute__((packed)) ; - -struct c2wr_qp_destroy_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_qp_destroy { - struct c2wr_qp_destroy_req req; - struct c2wr_qp_destroy_rep rep; -} __attribute__((packed)) ; - -/* - * The CCWR_QP_CONNECT msg is posted on the verbs request queue. It can - * only be posted when a QP is in IDLE state. After the connect request is - * submitted to the LLP, the adapter moves the QP to CONNECT_PENDING state. - * No synchronous reply from adapter to this WR. The results of - * connection are passed back in an async event CCAE_ACTIVE_CONNECT_RESULTS - * See c2wr_ae_active_connect_results_t - */ -struct c2wr_qp_connect_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 qp_handle; - __be32 remote_addr; - __be16 remote_port; - u16 pad; - __be32 private_data_length; - u8 private_data[0]; /* Private data in-line. */ -} __attribute__((packed)) ; - -struct c2wr_qp_connect { - struct c2wr_qp_connect_req req; - /* no synchronous reply. */ -} __attribute__((packed)) ; - - -/* - *------------------------ MM ------------------------ - */ - -struct c2wr_nsmr_stag_alloc_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 pbl_depth; - u32 pd_id; - u32 flags; -} __attribute__((packed)) ; - -struct c2wr_nsmr_stag_alloc_rep { - struct c2wr_hdr hdr; - u32 pbl_depth; - u32 stag_index; -} __attribute__((packed)) ; - -union c2wr_nsmr_stag_alloc { - struct c2wr_nsmr_stag_alloc_req req; - struct c2wr_nsmr_stag_alloc_rep rep; -} __attribute__((packed)) ; - -struct c2wr_nsmr_register_req { - struct c2wr_hdr hdr; - __be64 va; - u32 rnic_handle; - __be16 flags; - u8 stag_key; - u8 pad; - u32 pd_id; - __be32 pbl_depth; - __be32 pbe_size; - __be32 fbo; - __be32 length; - __be32 addrs_length; - /* array of paddrs (must be aligned on a 64bit boundary) */ - __be64 paddrs[0]; -} __attribute__((packed)) ; - -struct c2wr_nsmr_register_rep { - struct c2wr_hdr hdr; - u32 pbl_depth; - __be32 stag_index; -} __attribute__((packed)) ; - -union c2wr_nsmr_register { - struct c2wr_nsmr_register_req req; - struct c2wr_nsmr_register_rep rep; -} __attribute__((packed)) ; - -struct c2wr_nsmr_pbl_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - __be32 flags; - __be32 stag_index; - __be32 addrs_length; - /* array of paddrs (must be aligned on a 64bit boundary) */ - __be64 paddrs[0]; -} __attribute__((packed)) ; - -struct c2wr_nsmr_pbl_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_nsmr_pbl { - struct c2wr_nsmr_pbl_req req; - struct c2wr_nsmr_pbl_rep rep; -} __attribute__((packed)) ; - -struct c2wr_mr_query_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 stag_index; -} __attribute__((packed)) ; - -struct c2wr_mr_query_rep { - struct c2wr_hdr hdr; - u8 stag_key; - u8 pad[3]; - u32 pd_id; - u32 flags; - u32 pbl_depth; -} __attribute__((packed)) ; - -union c2wr_mr_query { - struct c2wr_mr_query_req req; - struct c2wr_mr_query_rep rep; -} __attribute__((packed)) ; - -struct c2wr_mw_query_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 stag_index; -} __attribute__((packed)) ; - -struct c2wr_mw_query_rep { - struct c2wr_hdr hdr; - u8 stag_key; - u8 pad[3]; - u32 pd_id; - u32 flags; -} __attribute__((packed)) ; - -union c2wr_mw_query { - struct c2wr_mw_query_req req; - struct c2wr_mw_query_rep rep; -} __attribute__((packed)) ; - - -struct c2wr_stag_dealloc_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - __be32 stag_index; -} __attribute__((packed)) ; - -struct c2wr_stag_dealloc_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_stag_dealloc { - struct c2wr_stag_dealloc_req req; - struct c2wr_stag_dealloc_rep rep; -} __attribute__((packed)) ; - -struct c2wr_nsmr_reregister_req { - struct c2wr_hdr hdr; - u64 va; - u32 rnic_handle; - u16 flags; - u8 stag_key; - u8 pad; - u32 stag_index; - u32 pd_id; - u32 pbl_depth; - u32 pbe_size; - u32 fbo; - u32 length; - u32 addrs_length; - u32 pad1; - /* array of paddrs (must be aligned on a 64bit boundary) */ - u64 paddrs[0]; -} __attribute__((packed)) ; - -struct c2wr_nsmr_reregister_rep { - struct c2wr_hdr hdr; - u32 pbl_depth; - u32 stag_index; -} __attribute__((packed)) ; - -union c2wr_nsmr_reregister { - struct c2wr_nsmr_reregister_req req; - struct c2wr_nsmr_reregister_rep rep; -} __attribute__((packed)) ; - -struct c2wr_smr_register_req { - struct c2wr_hdr hdr; - u64 va; - u32 rnic_handle; - u16 flags; - u8 stag_key; - u8 pad; - u32 stag_index; - u32 pd_id; -} __attribute__((packed)) ; - -struct c2wr_smr_register_rep { - struct c2wr_hdr hdr; - u32 stag_index; -} __attribute__((packed)) ; - -union c2wr_smr_register { - struct c2wr_smr_register_req req; - struct c2wr_smr_register_rep rep; -} __attribute__((packed)) ; - -struct c2wr_mw_alloc_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 pd_id; -} __attribute__((packed)) ; - -struct c2wr_mw_alloc_rep { - struct c2wr_hdr hdr; - u32 stag_index; -} __attribute__((packed)) ; - -union c2wr_mw_alloc { - struct c2wr_mw_alloc_req req; - struct c2wr_mw_alloc_rep rep; -} __attribute__((packed)) ; - -/* - *------------------------ WRs ----------------------- - */ - -struct c2wr_user_hdr { - struct c2wr_hdr hdr; /* Has status and WR Type */ -} __attribute__((packed)) ; - -enum c2_qp_state { - C2_QP_STATE_IDLE = 0x01, - C2_QP_STATE_CONNECTING = 0x02, - C2_QP_STATE_RTS = 0x04, - C2_QP_STATE_CLOSING = 0x08, - C2_QP_STATE_TERMINATE = 0x10, - C2_QP_STATE_ERROR = 0x20, -}; - -/* Completion queue entry. */ -struct c2wr_ce { - struct c2wr_hdr hdr; /* Has status and WR Type */ - u64 qp_user_context; /* c2_user_qp_t * */ - u32 qp_state; /* Current QP State */ - u32 handle; /* QPID or EP Handle */ - __be32 bytes_rcvd; /* valid for RECV WCs */ - u32 stag; -} __attribute__((packed)) ; - - -/* - * Flags used for all post-sq WRs. These must fit in the flags - * field of the struct c2wr_hdr (eight bits). - */ -enum { - SQ_SIGNALED = 0x01, - SQ_READ_FENCE = 0x02, - SQ_FENCE = 0x04, -}; - -/* - * Common fields for all post-sq WRs. Namely the standard header and a - * secondary header with fields common to all post-sq WRs. - */ -struct c2_sq_hdr { - struct c2wr_user_hdr user_hdr; -} __attribute__((packed)); - -/* - * Same as above but for post-rq WRs. - */ -struct c2_rq_hdr { - struct c2wr_user_hdr user_hdr; -} __attribute__((packed)); - -/* - * use the same struct for all sends. - */ -struct c2wr_send_req { - struct c2_sq_hdr sq_hdr; - __be32 sge_len; - __be32 remote_stag; - u8 data[0]; /* SGE array */ -} __attribute__((packed)); - -union c2wr_send { - struct c2wr_send_req req; - struct c2wr_ce rep; -} __attribute__((packed)); - -struct c2wr_rdma_write_req { - struct c2_sq_hdr sq_hdr; - __be64 remote_to; - __be32 remote_stag; - __be32 sge_len; - u8 data[0]; /* SGE array */ -} __attribute__((packed)); - -union c2wr_rdma_write { - struct c2wr_rdma_write_req req; - struct c2wr_ce rep; -} __attribute__((packed)); - -struct c2wr_rdma_read_req { - struct c2_sq_hdr sq_hdr; - __be64 local_to; - __be64 remote_to; - __be32 local_stag; - __be32 remote_stag; - __be32 length; -} __attribute__((packed)); - -union c2wr_rdma_read { - struct c2wr_rdma_read_req req; - struct c2wr_ce rep; -} __attribute__((packed)); - -struct c2wr_mw_bind_req { - struct c2_sq_hdr sq_hdr; - u64 va; - u8 stag_key; - u8 pad[3]; - u32 mw_stag_index; - u32 mr_stag_index; - u32 length; - u32 flags; -} __attribute__((packed)); - -union c2wr_mw_bind { - struct c2wr_mw_bind_req req; - struct c2wr_ce rep; -} __attribute__((packed)); - -struct c2wr_nsmr_fastreg_req { - struct c2_sq_hdr sq_hdr; - u64 va; - u8 stag_key; - u8 pad[3]; - u32 stag_index; - u32 pbe_size; - u32 fbo; - u32 length; - u32 addrs_length; - /* array of paddrs (must be aligned on a 64bit boundary) */ - u64 paddrs[0]; -} __attribute__((packed)); - -union c2wr_nsmr_fastreg { - struct c2wr_nsmr_fastreg_req req; - struct c2wr_ce rep; -} __attribute__((packed)); - -struct c2wr_stag_invalidate_req { - struct c2_sq_hdr sq_hdr; - u8 stag_key; - u8 pad[3]; - u32 stag_index; -} __attribute__((packed)); - -union c2wr_stag_invalidate { - struct c2wr_stag_invalidate_req req; - struct c2wr_ce rep; -} __attribute__((packed)); - -union c2wr_sqwr { - struct c2_sq_hdr sq_hdr; - struct c2wr_send_req send; - struct c2wr_send_req send_se; - struct c2wr_send_req send_inv; - struct c2wr_send_req send_se_inv; - struct c2wr_rdma_write_req rdma_write; - struct c2wr_rdma_read_req rdma_read; - struct c2wr_mw_bind_req mw_bind; - struct c2wr_nsmr_fastreg_req nsmr_fastreg; - struct c2wr_stag_invalidate_req stag_inv; -} __attribute__((packed)); - - -/* - * RQ WRs - */ -struct c2wr_rqwr { - struct c2_rq_hdr rq_hdr; - u8 data[0]; /* array of SGEs */ -} __attribute__((packed)); - -union c2wr_recv { - struct c2wr_rqwr req; - struct c2wr_ce rep; -} __attribute__((packed)); - -/* - * All AEs start with this header. Most AEs only need to convey the - * information in the header. Some, like LLP connection events, need - * more info. The union typdef c2wr_ae_t has all the possible AEs. - * - * hdr.context is the user_context from the rnic_open WR. NULL If this - * is not affiliated with an rnic - * - * hdr.id is the AE identifier (eg; CCAE_REMOTE_SHUTDOWN, - * CCAE_LLP_CLOSE_COMPLETE) - * - * resource_type is one of: C2_RES_IND_QP, C2_RES_IND_CQ, C2_RES_IND_SRQ - * - * user_context is the context passed down when the host created the resource. - */ -struct c2wr_ae_hdr { - struct c2wr_hdr hdr; - u64 user_context; /* user context for this res. */ - __be32 resource_type; /* see enum c2_resource_indicator */ - __be32 resource; /* handle for resource */ - __be32 qp_state; /* current QP State */ -} __attribute__((packed)); - -/* - * After submitting the CCAE_ACTIVE_CONNECT_RESULTS message on the AEQ, - * the adapter moves the QP into RTS state - */ -struct c2wr_ae_active_connect_results { - struct c2wr_ae_hdr ae_hdr; - __be32 laddr; - __be32 raddr; - __be16 lport; - __be16 rport; - __be32 private_data_length; - u8 private_data[0]; /* data is in-line in the msg. */ -} __attribute__((packed)); - -/* - * When connections are established by the stack (and the private data - * MPA frame is received), the adapter will generate an event to the host. - * The details of the connection, any private data, and the new connection - * request handle is passed up via the CCAE_CONNECTION_REQUEST msg on the - * AE queue: - */ -struct c2wr_ae_connection_request { - struct c2wr_ae_hdr ae_hdr; - u32 cr_handle; /* connreq handle (sock ptr) */ - __be32 laddr; - __be32 raddr; - __be16 lport; - __be16 rport; - __be32 private_data_length; - u8 private_data[0]; /* data is in-line in the msg. */ -} __attribute__((packed)); - -union c2wr_ae { - struct c2wr_ae_hdr ae_generic; - struct c2wr_ae_active_connect_results ae_active_connect_results; - struct c2wr_ae_connection_request ae_connection_request; -} __attribute__((packed)); - -struct c2wr_init_req { - struct c2wr_hdr hdr; - __be64 hint_count; - __be64 q0_host_shared; - __be64 q1_host_shared; - __be64 q1_host_msg_pool; - __be64 q2_host_shared; - __be64 q2_host_msg_pool; -} __attribute__((packed)); - -struct c2wr_init_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)); - -union c2wr_init { - struct c2wr_init_req req; - struct c2wr_init_rep rep; -} __attribute__((packed)); - -/* - * For upgrading flash. - */ - -struct c2wr_flash_init_req { - struct c2wr_hdr hdr; - u32 rnic_handle; -} __attribute__((packed)); - -struct c2wr_flash_init_rep { - struct c2wr_hdr hdr; - u32 adapter_flash_buf_offset; - u32 adapter_flash_len; -} __attribute__((packed)); - -union c2wr_flash_init { - struct c2wr_flash_init_req req; - struct c2wr_flash_init_rep rep; -} __attribute__((packed)); - -struct c2wr_flash_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 len; -} __attribute__((packed)); - -struct c2wr_flash_rep { - struct c2wr_hdr hdr; - u32 status; -} __attribute__((packed)); - -union c2wr_flash { - struct c2wr_flash_req req; - struct c2wr_flash_rep rep; -} __attribute__((packed)); - -struct c2wr_buf_alloc_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 size; -} __attribute__((packed)); - -struct c2wr_buf_alloc_rep { - struct c2wr_hdr hdr; - u32 offset; /* 0 if mem not available */ - u32 size; /* 0 if mem not available */ -} __attribute__((packed)); - -union c2wr_buf_alloc { - struct c2wr_buf_alloc_req req; - struct c2wr_buf_alloc_rep rep; -} __attribute__((packed)); - -struct c2wr_buf_free_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 offset; /* Must match value from alloc */ - u32 size; /* Must match value from alloc */ -} __attribute__((packed)); - -struct c2wr_buf_free_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)); - -union c2wr_buf_free { - struct c2wr_buf_free_req req; - struct c2wr_ce rep; -} __attribute__((packed)); - -struct c2wr_flash_write_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 offset; - u32 size; - u32 type; - u32 flags; -} __attribute__((packed)); - -struct c2wr_flash_write_rep { - struct c2wr_hdr hdr; - u32 status; -} __attribute__((packed)); - -union c2wr_flash_write { - struct c2wr_flash_write_req req; - struct c2wr_flash_write_rep rep; -} __attribute__((packed)); - -/* - * Messages for LLP connection setup. - */ - -/* - * Listen Request. This allocates a listening endpoint to allow passive - * connection setup. Newly established LLP connections are passed up - * via an AE. See c2wr_ae_connection_request_t - */ -struct c2wr_ep_listen_create_req { - struct c2wr_hdr hdr; - u64 user_context; /* returned in AEs. */ - u32 rnic_handle; - __be32 local_addr; /* local addr, or 0 */ - __be16 local_port; /* 0 means "pick one" */ - u16 pad; - __be32 backlog; /* tradional tcp listen bl */ -} __attribute__((packed)); - -struct c2wr_ep_listen_create_rep { - struct c2wr_hdr hdr; - u32 ep_handle; /* handle to new listening ep */ - u16 local_port; /* resulting port... */ - u16 pad; -} __attribute__((packed)); - -union c2wr_ep_listen_create { - struct c2wr_ep_listen_create_req req; - struct c2wr_ep_listen_create_rep rep; -} __attribute__((packed)); - -struct c2wr_ep_listen_destroy_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 ep_handle; -} __attribute__((packed)); - -struct c2wr_ep_listen_destroy_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)); - -union c2wr_ep_listen_destroy { - struct c2wr_ep_listen_destroy_req req; - struct c2wr_ep_listen_destroy_rep rep; -} __attribute__((packed)); - -struct c2wr_ep_query_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 ep_handle; -} __attribute__((packed)); - -struct c2wr_ep_query_rep { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 local_addr; - u32 remote_addr; - u16 local_port; - u16 remote_port; -} __attribute__((packed)); - -union c2wr_ep_query { - struct c2wr_ep_query_req req; - struct c2wr_ep_query_rep rep; -} __attribute__((packed)); - - -/* - * The host passes this down to indicate acceptance of a pending iWARP - * connection. The cr_handle was obtained from the CONNECTION_REQUEST - * AE passed up by the adapter. See c2wr_ae_connection_request_t. - */ -struct c2wr_cr_accept_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 qp_handle; /* QP to bind to this LLP conn */ - u32 ep_handle; /* LLP handle to accept */ - __be32 private_data_length; - u8 private_data[0]; /* data in-line in msg. */ -} __attribute__((packed)); - -/* - * adapter sends reply when private data is successfully submitted to - * the LLP. - */ -struct c2wr_cr_accept_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)); - -union c2wr_cr_accept { - struct c2wr_cr_accept_req req; - struct c2wr_cr_accept_rep rep; -} __attribute__((packed)); - -/* - * The host sends this down if a given iWARP connection request was - * rejected by the consumer. The cr_handle was obtained from a - * previous c2wr_ae_connection_request_t AE sent by the adapter. - */ -struct c2wr_cr_reject_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 ep_handle; /* LLP handle to reject */ -} __attribute__((packed)); - -/* - * Dunno if this is needed, but we'll add it for now. The adapter will - * send the reject_reply after the LLP endpoint has been destroyed. - */ -struct c2wr_cr_reject_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)); - -union c2wr_cr_reject { - struct c2wr_cr_reject_req req; - struct c2wr_cr_reject_rep rep; -} __attribute__((packed)); - -/* - * console command. Used to implement a debug console over the verbs - * request and reply queues. - */ - -/* - * Console request message. It contains: - * - message hdr with id = CCWR_CONSOLE - * - the physaddr/len of host memory to be used for the reply. - * - the command string. eg: "netstat -s" or "zoneinfo" - */ -struct c2wr_console_req { - struct c2wr_hdr hdr; /* id = CCWR_CONSOLE */ - u64 reply_buf; /* pinned host buf for reply */ - u32 reply_buf_len; /* length of reply buffer */ - u8 command[0]; /* NUL terminated ascii string */ - /* containing the command req */ -} __attribute__((packed)); - -/* - * flags used in the console reply. - */ -enum c2_console_flags { - CONS_REPLY_TRUNCATED = 0x00000001 /* reply was truncated */ -} __attribute__((packed)); - -/* - * Console reply message. - * hdr.result contains the c2_status_t error if the reply was _not_ generated, - * or C2_OK if the reply was generated. - */ -struct c2wr_console_rep { - struct c2wr_hdr hdr; /* id = CCWR_CONSOLE */ - u32 flags; -} __attribute__((packed)); - -union c2wr_console { - struct c2wr_console_req req; - struct c2wr_console_rep rep; -} __attribute__((packed)); - - -/* - * Giant union with all WRs. Makes life easier... - */ -union c2wr { - struct c2wr_hdr hdr; - struct c2wr_user_hdr user_hdr; - union c2wr_rnic_open rnic_open; - union c2wr_rnic_query rnic_query; - union c2wr_rnic_getconfig rnic_getconfig; - union c2wr_rnic_setconfig rnic_setconfig; - union c2wr_rnic_close rnic_close; - union c2wr_cq_create cq_create; - union c2wr_cq_modify cq_modify; - union c2wr_cq_destroy cq_destroy; - union c2wr_pd_alloc pd_alloc; - union c2wr_pd_dealloc pd_dealloc; - union c2wr_srq_create srq_create; - union c2wr_srq_destroy srq_destroy; - union c2wr_qp_create qp_create; - union c2wr_qp_query qp_query; - union c2wr_qp_modify qp_modify; - union c2wr_qp_destroy qp_destroy; - struct c2wr_qp_connect qp_connect; - union c2wr_nsmr_stag_alloc nsmr_stag_alloc; - union c2wr_nsmr_register nsmr_register; - union c2wr_nsmr_pbl nsmr_pbl; - union c2wr_mr_query mr_query; - union c2wr_mw_query mw_query; - union c2wr_stag_dealloc stag_dealloc; - union c2wr_sqwr sqwr; - struct c2wr_rqwr rqwr; - struct c2wr_ce ce; - union c2wr_ae ae; - union c2wr_init init; - union c2wr_ep_listen_create ep_listen_create; - union c2wr_ep_listen_destroy ep_listen_destroy; - union c2wr_cr_accept cr_accept; - union c2wr_cr_reject cr_reject; - union c2wr_console console; - union c2wr_flash_init flash_init; - union c2wr_flash flash; - union c2wr_buf_alloc buf_alloc; - union c2wr_buf_free buf_free; - union c2wr_flash_write flash_write; -} __attribute__((packed)); - - -/* - * Accessors for the wr fields that are packed together tightly to - * reduce the wr message size. The wr arguments are void* so that - * either a struct c2wr*, a struct c2wr_hdr*, or a pointer to any of the types - * in the struct c2wr union can be passed in. - */ -static __inline__ u8 c2_wr_get_id(void *wr) -{ - return ((struct c2wr_hdr *) wr)->id; -} -static __inline__ void c2_wr_set_id(void *wr, u8 id) -{ - ((struct c2wr_hdr *) wr)->id = id; -} -static __inline__ u8 c2_wr_get_result(void *wr) -{ - return ((struct c2wr_hdr *) wr)->result; -} -static __inline__ void c2_wr_set_result(void *wr, u8 result) -{ - ((struct c2wr_hdr *) wr)->result = result; -} -static __inline__ u8 c2_wr_get_flags(void *wr) -{ - return ((struct c2wr_hdr *) wr)->flags; -} -static __inline__ void c2_wr_set_flags(void *wr, u8 flags) -{ - ((struct c2wr_hdr *) wr)->flags = flags; -} -static __inline__ u8 c2_wr_get_sge_count(void *wr) -{ - return ((struct c2wr_hdr *) wr)->sge_count; -} -static __inline__ void c2_wr_set_sge_count(void *wr, u8 sge_count) -{ - ((struct c2wr_hdr *) wr)->sge_count = sge_count; -} -static __inline__ __be32 c2_wr_get_wqe_count(void *wr) -{ - return ((struct c2wr_hdr *) wr)->wqe_count; -} -static __inline__ void c2_wr_set_wqe_count(void *wr, u32 wqe_count) -{ - ((struct c2wr_hdr *) wr)->wqe_count = wqe_count; -} - -#endif /* _C2_WR_H_ */ -- cgit v1.2.3 From e581d111dad3781266ae1abe1d2848e69406deb5 Mon Sep 17 00:00:00 2001 From: Doug Ledford Date: Wed, 3 Feb 2016 11:08:53 -0500 Subject: staging/rdma: remove deprecated ehca driver This driver was moved to staging for eventual deletion. Time to complete that task. Signed-off-by: Doug Ledford --- MAINTAINERS | 7 - drivers/staging/rdma/Kconfig | 2 - drivers/staging/rdma/Makefile | 1 - drivers/staging/rdma/ehca/Kconfig | 10 - drivers/staging/rdma/ehca/Makefile | 16 - drivers/staging/rdma/ehca/TODO | 4 - drivers/staging/rdma/ehca/ehca_av.c | 279 --- drivers/staging/rdma/ehca/ehca_classes.h | 481 ----- drivers/staging/rdma/ehca/ehca_classes_pSeries.h | 208 -- drivers/staging/rdma/ehca/ehca_cq.c | 397 ---- drivers/staging/rdma/ehca/ehca_eq.c | 189 -- drivers/staging/rdma/ehca/ehca_hca.c | 414 ---- drivers/staging/rdma/ehca/ehca_irq.c | 870 --------- drivers/staging/rdma/ehca/ehca_irq.h | 77 - drivers/staging/rdma/ehca/ehca_iverbs.h | 202 -- drivers/staging/rdma/ehca/ehca_main.c | 1118 ----------- drivers/staging/rdma/ehca/ehca_mcast.c | 131 -- drivers/staging/rdma/ehca/ehca_mrmw.c | 2202 --------------------- drivers/staging/rdma/ehca/ehca_mrmw.h | 127 -- drivers/staging/rdma/ehca/ehca_pd.c | 123 -- drivers/staging/rdma/ehca/ehca_qes.h | 260 --- drivers/staging/rdma/ehca/ehca_qp.c | 2256 ---------------------- drivers/staging/rdma/ehca/ehca_reqs.c | 953 --------- drivers/staging/rdma/ehca/ehca_sqp.c | 245 --- drivers/staging/rdma/ehca/ehca_tools.h | 155 -- drivers/staging/rdma/ehca/ehca_uverbs.c | 309 --- drivers/staging/rdma/ehca/hcp_if.c | 949 --------- drivers/staging/rdma/ehca/hcp_if.h | 265 --- drivers/staging/rdma/ehca/hcp_phyp.c | 82 - drivers/staging/rdma/ehca/hcp_phyp.h | 90 - drivers/staging/rdma/ehca/hipz_fns.h | 68 - drivers/staging/rdma/ehca/hipz_fns_core.h | 100 - drivers/staging/rdma/ehca/hipz_hw.h | 414 ---- drivers/staging/rdma/ehca/ipz_pt_fn.c | 289 --- drivers/staging/rdma/ehca/ipz_pt_fn.h | 289 --- 35 files changed, 13582 deletions(-) delete mode 100644 drivers/staging/rdma/ehca/Kconfig delete mode 100644 drivers/staging/rdma/ehca/Makefile delete mode 100644 drivers/staging/rdma/ehca/TODO delete mode 100644 drivers/staging/rdma/ehca/ehca_av.c delete mode 100644 drivers/staging/rdma/ehca/ehca_classes.h delete mode 100644 drivers/staging/rdma/ehca/ehca_classes_pSeries.h delete mode 100644 drivers/staging/rdma/ehca/ehca_cq.c delete mode 100644 drivers/staging/rdma/ehca/ehca_eq.c delete mode 100644 drivers/staging/rdma/ehca/ehca_hca.c delete mode 100644 drivers/staging/rdma/ehca/ehca_irq.c delete mode 100644 drivers/staging/rdma/ehca/ehca_irq.h delete mode 100644 drivers/staging/rdma/ehca/ehca_iverbs.h delete mode 100644 drivers/staging/rdma/ehca/ehca_main.c delete mode 100644 drivers/staging/rdma/ehca/ehca_mcast.c delete mode 100644 drivers/staging/rdma/ehca/ehca_mrmw.c delete mode 100644 drivers/staging/rdma/ehca/ehca_mrmw.h delete mode 100644 drivers/staging/rdma/ehca/ehca_pd.c delete mode 100644 drivers/staging/rdma/ehca/ehca_qes.h delete mode 100644 drivers/staging/rdma/ehca/ehca_qp.c delete mode 100644 drivers/staging/rdma/ehca/ehca_reqs.c delete mode 100644 drivers/staging/rdma/ehca/ehca_sqp.c delete mode 100644 drivers/staging/rdma/ehca/ehca_tools.h delete mode 100644 drivers/staging/rdma/ehca/ehca_uverbs.c delete mode 100644 drivers/staging/rdma/ehca/hcp_if.c delete mode 100644 drivers/staging/rdma/ehca/hcp_if.h delete mode 100644 drivers/staging/rdma/ehca/hcp_phyp.c delete mode 100644 drivers/staging/rdma/ehca/hcp_phyp.h delete mode 100644 drivers/staging/rdma/ehca/hipz_fns.h delete mode 100644 drivers/staging/rdma/ehca/hipz_fns_core.h delete mode 100644 drivers/staging/rdma/ehca/hipz_hw.h delete mode 100644 drivers/staging/rdma/ehca/ipz_pt_fn.c delete mode 100644 drivers/staging/rdma/ehca/ipz_pt_fn.h (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index e76048d11e45..d1aeb1d5add5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4177,13 +4177,6 @@ W: http://aeschi.ch.eu.org/efs/ S: Orphan F: fs/efs/ -EHCA (IBM GX bus InfiniBand adapter) DRIVER -M: Hoang-Nam Nguyen -M: Christoph Raisch -L: linux-rdma@vger.kernel.org -S: Supported -F: drivers/infiniband/hw/ehca/ - EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER M: Thadeu Lima de Souza Cascardo L: netdev@vger.kernel.org diff --git a/drivers/staging/rdma/Kconfig b/drivers/staging/rdma/Kconfig index 1624bc43e304..8a0be6961d7a 100644 --- a/drivers/staging/rdma/Kconfig +++ b/drivers/staging/rdma/Kconfig @@ -22,8 +22,6 @@ menuconfig STAGING_RDMA # Please keep entries in alphabetic order if STAGING_RDMA -source "drivers/staging/rdma/ehca/Kconfig" - source "drivers/staging/rdma/hfi1/Kconfig" source "drivers/staging/rdma/ipath/Kconfig" diff --git a/drivers/staging/rdma/Makefile b/drivers/staging/rdma/Makefile index 2217d6778669..08e1919c819e 100644 --- a/drivers/staging/rdma/Makefile +++ b/drivers/staging/rdma/Makefile @@ -1,4 +1,3 @@ # Entries for RDMA_STAGING tree -obj-$(CONFIG_INFINIBAND_EHCA) += ehca/ obj-$(CONFIG_INFINIBAND_HFI1) += hfi1/ obj-$(CONFIG_INFINIBAND_IPATH) += ipath/ diff --git a/drivers/staging/rdma/ehca/Kconfig b/drivers/staging/rdma/ehca/Kconfig deleted file mode 100644 index 3fadd2ad6426..000000000000 --- a/drivers/staging/rdma/ehca/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -config INFINIBAND_EHCA - tristate "eHCA support" - depends on IBMEBUS - ---help--- - This driver supports the deprecated IBM pSeries eHCA InfiniBand - adapter. - - To compile the driver as a module, choose M here. The module - will be called ib_ehca. - diff --git a/drivers/staging/rdma/ehca/Makefile b/drivers/staging/rdma/ehca/Makefile deleted file mode 100644 index 74d284e46a40..000000000000 --- a/drivers/staging/rdma/ehca/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# Authors: Heiko J Schick -# Christoph Raisch -# Joachim Fenkes -# -# Copyright (c) 2005 IBM Corporation -# -# All rights reserved. -# -# This source code is distributed under a dual license of GPL v2.0 and OpenIB BSD. - -obj-$(CONFIG_INFINIBAND_EHCA) += ib_ehca.o - -ib_ehca-objs = ehca_main.o ehca_hca.o ehca_mcast.o ehca_pd.o ehca_av.o ehca_eq.o \ - ehca_cq.o ehca_qp.o ehca_sqp.o ehca_mrmw.o ehca_reqs.o ehca_irq.o \ - ehca_uverbs.o ipz_pt_fn.o hcp_if.o hcp_phyp.o - diff --git a/drivers/staging/rdma/ehca/TODO b/drivers/staging/rdma/ehca/TODO deleted file mode 100644 index 199a4a600142..000000000000 --- a/drivers/staging/rdma/ehca/TODO +++ /dev/null @@ -1,4 +0,0 @@ -9/2015 - -The ehca driver has been deprecated and moved to drivers/staging/rdma. -It will be removed in the 4.6 merge window. diff --git a/drivers/staging/rdma/ehca/ehca_av.c b/drivers/staging/rdma/ehca/ehca_av.c deleted file mode 100644 index 94e088c2d989..000000000000 --- a/drivers/staging/rdma/ehca/ehca_av.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * address vector functions - * - * Authors: Hoang-Nam Nguyen - * Khadija Souissi - * Reinhard Ernst - * Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "ehca_tools.h" -#include "ehca_iverbs.h" -#include "hcp_if.h" - -static struct kmem_cache *av_cache; - -int ehca_calc_ipd(struct ehca_shca *shca, int port, - enum ib_rate path_rate, u32 *ipd) -{ - int path = ib_rate_to_mult(path_rate); - int link, ret; - struct ib_port_attr pa; - - if (path_rate == IB_RATE_PORT_CURRENT) { - *ipd = 0; - return 0; - } - - if (unlikely(path < 0)) { - ehca_err(&shca->ib_device, "Invalid static rate! path_rate=%x", - path_rate); - return -EINVAL; - } - - ret = ehca_query_port(&shca->ib_device, port, &pa); - if (unlikely(ret < 0)) { - ehca_err(&shca->ib_device, "Failed to query port ret=%i", ret); - return ret; - } - - link = ib_width_enum_to_int(pa.active_width) * pa.active_speed; - - if (path >= link) - /* no need to throttle if path faster than link */ - *ipd = 0; - else - /* IPD = round((link / path) - 1) */ - *ipd = ((link + (path >> 1)) / path) - 1; - - return 0; -} - -struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) -{ - int ret; - struct ehca_av *av; - struct ehca_shca *shca = container_of(pd->device, struct ehca_shca, - ib_device); - - av = kmem_cache_alloc(av_cache, GFP_KERNEL); - if (!av) { - ehca_err(pd->device, "Out of memory pd=%p ah_attr=%p", - pd, ah_attr); - return ERR_PTR(-ENOMEM); - } - - av->av.sl = ah_attr->sl; - av->av.dlid = ah_attr->dlid; - av->av.slid_path_bits = ah_attr->src_path_bits; - - if (ehca_static_rate < 0) { - u32 ipd; - - if (ehca_calc_ipd(shca, ah_attr->port_num, - ah_attr->static_rate, &ipd)) { - ret = -EINVAL; - goto create_ah_exit1; - } - av->av.ipd = ipd; - } else - av->av.ipd = ehca_static_rate; - - av->av.lnh = ah_attr->ah_flags; - av->av.grh.word_0 = EHCA_BMASK_SET(GRH_IPVERSION_MASK, 6); - av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_TCLASS_MASK, - ah_attr->grh.traffic_class); - av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_FLOWLABEL_MASK, - ah_attr->grh.flow_label); - av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_HOPLIMIT_MASK, - ah_attr->grh.hop_limit); - av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_NEXTHEADER_MASK, 0x1B); - /* set sgid in grh.word_1 */ - if (ah_attr->ah_flags & IB_AH_GRH) { - int rc; - struct ib_port_attr port_attr; - union ib_gid gid; - - memset(&port_attr, 0, sizeof(port_attr)); - rc = ehca_query_port(pd->device, ah_attr->port_num, - &port_attr); - if (rc) { /* invalid port number */ - ret = -EINVAL; - ehca_err(pd->device, "Invalid port number " - "ehca_query_port() returned %x " - "pd=%p ah_attr=%p", rc, pd, ah_attr); - goto create_ah_exit1; - } - memset(&gid, 0, sizeof(gid)); - rc = ehca_query_gid(pd->device, - ah_attr->port_num, - ah_attr->grh.sgid_index, &gid); - if (rc) { - ret = -EINVAL; - ehca_err(pd->device, "Failed to retrieve sgid " - "ehca_query_gid() returned %x " - "pd=%p ah_attr=%p", rc, pd, ah_attr); - goto create_ah_exit1; - } - memcpy(&av->av.grh.word_1, &gid, sizeof(gid)); - } - av->av.pmtu = shca->max_mtu; - - /* dgid comes in grh.word_3 */ - memcpy(&av->av.grh.word_3, &ah_attr->grh.dgid, - sizeof(ah_attr->grh.dgid)); - - return &av->ib_ah; - -create_ah_exit1: - kmem_cache_free(av_cache, av); - - return ERR_PTR(ret); -} - -int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) -{ - struct ehca_av *av; - struct ehca_ud_av new_ehca_av; - struct ehca_shca *shca = container_of(ah->pd->device, struct ehca_shca, - ib_device); - - memset(&new_ehca_av, 0, sizeof(new_ehca_av)); - new_ehca_av.sl = ah_attr->sl; - new_ehca_av.dlid = ah_attr->dlid; - new_ehca_av.slid_path_bits = ah_attr->src_path_bits; - new_ehca_av.ipd = ah_attr->static_rate; - new_ehca_av.lnh = EHCA_BMASK_SET(GRH_FLAG_MASK, - (ah_attr->ah_flags & IB_AH_GRH) > 0); - new_ehca_av.grh.word_0 = EHCA_BMASK_SET(GRH_TCLASS_MASK, - ah_attr->grh.traffic_class); - new_ehca_av.grh.word_0 |= EHCA_BMASK_SET(GRH_FLOWLABEL_MASK, - ah_attr->grh.flow_label); - new_ehca_av.grh.word_0 |= EHCA_BMASK_SET(GRH_HOPLIMIT_MASK, - ah_attr->grh.hop_limit); - new_ehca_av.grh.word_0 |= EHCA_BMASK_SET(GRH_NEXTHEADER_MASK, 0x1b); - - /* set sgid in grh.word_1 */ - if (ah_attr->ah_flags & IB_AH_GRH) { - int rc; - struct ib_port_attr port_attr; - union ib_gid gid; - - memset(&port_attr, 0, sizeof(port_attr)); - rc = ehca_query_port(ah->device, ah_attr->port_num, - &port_attr); - if (rc) { /* invalid port number */ - ehca_err(ah->device, "Invalid port number " - "ehca_query_port() returned %x " - "ah=%p ah_attr=%p port_num=%x", - rc, ah, ah_attr, ah_attr->port_num); - return -EINVAL; - } - memset(&gid, 0, sizeof(gid)); - rc = ehca_query_gid(ah->device, - ah_attr->port_num, - ah_attr->grh.sgid_index, &gid); - if (rc) { - ehca_err(ah->device, "Failed to retrieve sgid " - "ehca_query_gid() returned %x " - "ah=%p ah_attr=%p port_num=%x " - "sgid_index=%x", - rc, ah, ah_attr, ah_attr->port_num, - ah_attr->grh.sgid_index); - return -EINVAL; - } - memcpy(&new_ehca_av.grh.word_1, &gid, sizeof(gid)); - } - - new_ehca_av.pmtu = shca->max_mtu; - - memcpy(&new_ehca_av.grh.word_3, &ah_attr->grh.dgid, - sizeof(ah_attr->grh.dgid)); - - av = container_of(ah, struct ehca_av, ib_ah); - av->av = new_ehca_av; - - return 0; -} - -int ehca_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) -{ - struct ehca_av *av = container_of(ah, struct ehca_av, ib_ah); - - memcpy(&ah_attr->grh.dgid, &av->av.grh.word_3, - sizeof(ah_attr->grh.dgid)); - ah_attr->sl = av->av.sl; - - ah_attr->dlid = av->av.dlid; - - ah_attr->src_path_bits = av->av.slid_path_bits; - ah_attr->static_rate = av->av.ipd; - ah_attr->ah_flags = EHCA_BMASK_GET(GRH_FLAG_MASK, av->av.lnh); - ah_attr->grh.traffic_class = EHCA_BMASK_GET(GRH_TCLASS_MASK, - av->av.grh.word_0); - ah_attr->grh.hop_limit = EHCA_BMASK_GET(GRH_HOPLIMIT_MASK, - av->av.grh.word_0); - ah_attr->grh.flow_label = EHCA_BMASK_GET(GRH_FLOWLABEL_MASK, - av->av.grh.word_0); - - return 0; -} - -int ehca_destroy_ah(struct ib_ah *ah) -{ - kmem_cache_free(av_cache, container_of(ah, struct ehca_av, ib_ah)); - - return 0; -} - -int ehca_init_av_cache(void) -{ - av_cache = kmem_cache_create("ehca_cache_av", - sizeof(struct ehca_av), 0, - SLAB_HWCACHE_ALIGN, - NULL); - if (!av_cache) - return -ENOMEM; - return 0; -} - -void ehca_cleanup_av_cache(void) -{ - kmem_cache_destroy(av_cache); -} diff --git a/drivers/staging/rdma/ehca/ehca_classes.h b/drivers/staging/rdma/ehca/ehca_classes.h deleted file mode 100644 index e8c3387d7aaa..000000000000 --- a/drivers/staging/rdma/ehca/ehca_classes.h +++ /dev/null @@ -1,481 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Struct definition for eHCA internal structures - * - * Authors: Heiko J Schick - * Christoph Raisch - * Joachim Fenkes - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __EHCA_CLASSES_H__ -#define __EHCA_CLASSES_H__ - -struct ehca_module; -struct ehca_qp; -struct ehca_cq; -struct ehca_eq; -struct ehca_mr; -struct ehca_mw; -struct ehca_pd; -struct ehca_av; - -#include -#include - -#include -#include - -#ifdef CONFIG_PPC64 -#include "ehca_classes_pSeries.h" -#endif -#include "ipz_pt_fn.h" -#include "ehca_qes.h" -#include "ehca_irq.h" - -#define EHCA_EQE_CACHE_SIZE 20 -#define EHCA_MAX_NUM_QUEUES 0xffff - -struct ehca_eqe_cache_entry { - struct ehca_eqe *eqe; - struct ehca_cq *cq; -}; - -struct ehca_eq { - u32 length; - struct ipz_queue ipz_queue; - struct ipz_eq_handle ipz_eq_handle; - struct work_struct work; - struct h_galpas galpas; - int is_initialized; - struct ehca_pfeq pf; - spinlock_t spinlock; - struct tasklet_struct interrupt_task; - u32 ist; - spinlock_t irq_spinlock; - struct ehca_eqe_cache_entry eqe_cache[EHCA_EQE_CACHE_SIZE]; -}; - -struct ehca_sma_attr { - u16 lid, lmc, sm_sl, sm_lid; - u16 pkey_tbl_len, pkeys[16]; -}; - -struct ehca_sport { - struct ib_cq *ibcq_aqp1; - struct ib_qp *ibqp_sqp[2]; - /* lock to serialze modify_qp() calls for sqp in normal - * and irq path (when event PORT_ACTIVE is received first time) - */ - spinlock_t mod_sqp_lock; - enum ib_port_state port_state; - struct ehca_sma_attr saved_attr; - u32 pma_qp_nr; -}; - -#define HCA_CAP_MR_PGSIZE_4K 0x80000000 -#define HCA_CAP_MR_PGSIZE_64K 0x40000000 -#define HCA_CAP_MR_PGSIZE_1M 0x20000000 -#define HCA_CAP_MR_PGSIZE_16M 0x10000000 - -struct ehca_shca { - struct ib_device ib_device; - struct platform_device *ofdev; - u8 num_ports; - int hw_level; - struct list_head shca_list; - struct ipz_adapter_handle ipz_hca_handle; - struct ehca_sport sport[2]; - struct ehca_eq eq; - struct ehca_eq neq; - struct ehca_mr *maxmr; - struct ehca_pd *pd; - struct h_galpas galpas; - struct mutex modify_mutex; - u64 hca_cap; - /* MR pgsize: bit 0-3 means 4K, 64K, 1M, 16M respectively */ - u32 hca_cap_mr_pgsize; - int max_mtu; - int max_num_qps; - int max_num_cqs; - atomic_t num_cqs; - atomic_t num_qps; -}; - -struct ehca_pd { - struct ib_pd ib_pd; - struct ipz_pd fw_pd; - /* small queue mgmt */ - struct mutex lock; - struct list_head free[2]; - struct list_head full[2]; -}; - -enum ehca_ext_qp_type { - EQPT_NORMAL = 0, - EQPT_LLQP = 1, - EQPT_SRQBASE = 2, - EQPT_SRQ = 3, -}; - -/* struct to cache modify_qp()'s parms for GSI/SMI qp */ -struct ehca_mod_qp_parm { - int mask; - struct ib_qp_attr attr; -}; - -#define EHCA_MOD_QP_PARM_MAX 4 - -#define QMAP_IDX_MASK 0xFFFFULL - -/* struct for tracking if cqes have been reported to the application */ -struct ehca_qmap_entry { - u16 app_wr_id; - u8 reported; - u8 cqe_req; -}; - -struct ehca_queue_map { - struct ehca_qmap_entry *map; - unsigned int entries; - unsigned int tail; - unsigned int left_to_poll; - unsigned int next_wqe_idx; /* Idx to first wqe to be flushed */ -}; - -/* function to calculate the next index for the qmap */ -static inline unsigned int next_index(unsigned int cur_index, unsigned int limit) -{ - unsigned int temp = cur_index + 1; - return (temp == limit) ? 0 : temp; -} - -struct ehca_qp { - union { - struct ib_qp ib_qp; - struct ib_srq ib_srq; - }; - u32 qp_type; - enum ehca_ext_qp_type ext_type; - enum ib_qp_state state; - struct ipz_queue ipz_squeue; - struct ehca_queue_map sq_map; - struct ipz_queue ipz_rqueue; - struct ehca_queue_map rq_map; - struct h_galpas galpas; - u32 qkey; - u32 real_qp_num; - u32 token; - spinlock_t spinlock_s; - spinlock_t spinlock_r; - u32 sq_max_inline_data_size; - struct ipz_qp_handle ipz_qp_handle; - struct ehca_pfqp pf; - struct ib_qp_init_attr init_attr; - struct ehca_cq *send_cq; - struct ehca_cq *recv_cq; - unsigned int sqerr_purgeflag; - struct hlist_node list_entries; - /* array to cache modify_qp()'s parms for GSI/SMI qp */ - struct ehca_mod_qp_parm *mod_qp_parm; - int mod_qp_parm_idx; - /* mmap counter for resources mapped into user space */ - u32 mm_count_squeue; - u32 mm_count_rqueue; - u32 mm_count_galpa; - /* unsolicited ack circumvention */ - int unsol_ack_circ; - int mtu_shift; - u32 message_count; - u32 packet_count; - atomic_t nr_events; /* events seen */ - wait_queue_head_t wait_completion; - int mig_armed; - struct list_head sq_err_node; - struct list_head rq_err_node; -}; - -#define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ) -#define HAS_SQ(qp) (qp->ext_type != EQPT_SRQ) -#define HAS_RQ(qp) (qp->ext_type != EQPT_SRQBASE) - -/* must be power of 2 */ -#define QP_HASHTAB_LEN 8 - -struct ehca_cq { - struct ib_cq ib_cq; - struct ipz_queue ipz_queue; - struct h_galpas galpas; - spinlock_t spinlock; - u32 cq_number; - u32 token; - u32 nr_of_entries; - struct ipz_cq_handle ipz_cq_handle; - struct ehca_pfcq pf; - spinlock_t cb_lock; - struct hlist_head qp_hashtab[QP_HASHTAB_LEN]; - struct list_head entry; - u32 nr_callbacks; /* #events assigned to cpu by scaling code */ - atomic_t nr_events; /* #events seen */ - wait_queue_head_t wait_completion; - spinlock_t task_lock; - /* mmap counter for resources mapped into user space */ - u32 mm_count_queue; - u32 mm_count_galpa; - struct list_head sqp_err_list; - struct list_head rqp_err_list; -}; - -enum ehca_mr_flag { - EHCA_MR_FLAG_FMR = 0x80000000, /* FMR, created with ehca_alloc_fmr */ - EHCA_MR_FLAG_MAXMR = 0x40000000, /* max-MR */ -}; - -struct ehca_mr { - union { - struct ib_mr ib_mr; /* must always be first in ehca_mr */ - struct ib_fmr ib_fmr; /* must always be first in ehca_mr */ - } ib; - struct ib_umem *umem; - spinlock_t mrlock; - - enum ehca_mr_flag flags; - u32 num_kpages; /* number of kernel pages */ - u32 num_hwpages; /* number of hw pages to form MR */ - u64 hwpage_size; /* hw page size used for this MR */ - int acl; /* ACL (stored here for usage in reregister) */ - u64 *start; /* virtual start address (stored here for */ - /* usage in reregister) */ - u64 size; /* size (stored here for usage in reregister) */ - u32 fmr_page_size; /* page size for FMR */ - u32 fmr_max_pages; /* max pages for FMR */ - u32 fmr_max_maps; /* max outstanding maps for FMR */ - u32 fmr_map_cnt; /* map counter for FMR */ - /* fw specific data */ - struct ipz_mrmw_handle ipz_mr_handle; /* MR handle for h-calls */ - struct h_galpas galpas; -}; - -struct ehca_mw { - struct ib_mw ib_mw; /* gen2 mw, must always be first in ehca_mw */ - spinlock_t mwlock; - - u8 never_bound; /* indication MW was never bound */ - struct ipz_mrmw_handle ipz_mw_handle; /* MW handle for h-calls */ - struct h_galpas galpas; -}; - -enum ehca_mr_pgi_type { - EHCA_MR_PGI_PHYS = 1, /* type of ehca_reg_phys_mr, - * ehca_rereg_phys_mr, - * ehca_reg_internal_maxmr */ - EHCA_MR_PGI_USER = 2, /* type of ehca_reg_user_mr */ - EHCA_MR_PGI_FMR = 3 /* type of ehca_map_phys_fmr */ -}; - -struct ehca_mr_pginfo { - enum ehca_mr_pgi_type type; - u64 num_kpages; - u64 kpage_cnt; - u64 hwpage_size; /* hw page size used for this MR */ - u64 num_hwpages; /* number of hw pages */ - u64 hwpage_cnt; /* counter for hw pages */ - u64 next_hwpage; /* next hw page in buffer/chunk/listelem */ - - union { - struct { /* type EHCA_MR_PGI_PHYS section */ - u64 addr; - u16 size; - } phy; - struct { /* type EHCA_MR_PGI_USER section */ - struct ib_umem *region; - struct scatterlist *next_sg; - u64 next_nmap; - } usr; - struct { /* type EHCA_MR_PGI_FMR section */ - u64 fmr_pgsize; - u64 *page_list; - u64 next_listelem; - } fmr; - } u; -}; - -/* output parameters for MR/FMR hipz calls */ -struct ehca_mr_hipzout_parms { - struct ipz_mrmw_handle handle; - u32 lkey; - u32 rkey; - u64 len; - u64 vaddr; - u32 acl; -}; - -/* output parameters for MW hipz calls */ -struct ehca_mw_hipzout_parms { - struct ipz_mrmw_handle handle; - u32 rkey; -}; - -struct ehca_av { - struct ib_ah ib_ah; - struct ehca_ud_av av; -}; - -struct ehca_ucontext { - struct ib_ucontext ib_ucontext; -}; - -int ehca_init_pd_cache(void); -void ehca_cleanup_pd_cache(void); -int ehca_init_cq_cache(void); -void ehca_cleanup_cq_cache(void); -int ehca_init_qp_cache(void); -void ehca_cleanup_qp_cache(void); -int ehca_init_av_cache(void); -void ehca_cleanup_av_cache(void); -int ehca_init_mrmw_cache(void); -void ehca_cleanup_mrmw_cache(void); -int ehca_init_small_qp_cache(void); -void ehca_cleanup_small_qp_cache(void); - -extern rwlock_t ehca_qp_idr_lock; -extern rwlock_t ehca_cq_idr_lock; -extern struct idr ehca_qp_idr; -extern struct idr ehca_cq_idr; -extern spinlock_t shca_list_lock; - -extern int ehca_static_rate; -extern int ehca_port_act_time; -extern bool ehca_use_hp_mr; -extern bool ehca_scaling_code; -extern int ehca_lock_hcalls; -extern int ehca_nr_ports; -extern int ehca_max_cq; -extern int ehca_max_qp; - -struct ipzu_queue_resp { - u32 qe_size; /* queue entry size */ - u32 act_nr_of_sg; - u32 queue_length; /* queue length allocated in bytes */ - u32 pagesize; - u32 toggle_state; - u32 offset; /* save offset within a page for small_qp */ -}; - -struct ehca_create_cq_resp { - u32 cq_number; - u32 token; - struct ipzu_queue_resp ipz_queue; - u32 fw_handle_ofs; - u32 dummy; -}; - -struct ehca_create_qp_resp { - u32 qp_num; - u32 token; - u32 qp_type; - u32 ext_type; - u32 qkey; - /* qp_num assigned by ehca: sqp0/1 may have got different numbers */ - u32 real_qp_num; - u32 fw_handle_ofs; - u32 dummy; - struct ipzu_queue_resp ipz_squeue; - struct ipzu_queue_resp ipz_rqueue; -}; - -struct ehca_alloc_cq_parms { - u32 nr_cqe; - u32 act_nr_of_entries; - u32 act_pages; - struct ipz_eq_handle eq_handle; -}; - -enum ehca_service_type { - ST_RC = 0, - ST_UC = 1, - ST_RD = 2, - ST_UD = 3, -}; - -enum ehca_ll_comp_flags { - LLQP_SEND_COMP = 0x20, - LLQP_RECV_COMP = 0x40, - LLQP_COMP_MASK = 0x60, -}; - -struct ehca_alloc_queue_parms { - /* input parameters */ - int max_wr; - int max_sge; - int page_size; - int is_small; - - /* output parameters */ - u16 act_nr_wqes; - u8 act_nr_sges; - u32 queue_size; /* bytes for small queues, pages otherwise */ -}; - -struct ehca_alloc_qp_parms { - struct ehca_alloc_queue_parms squeue; - struct ehca_alloc_queue_parms rqueue; - - /* input parameters */ - enum ehca_service_type servicetype; - int qp_storage; - int sigtype; - enum ehca_ext_qp_type ext_type; - enum ehca_ll_comp_flags ll_comp_flags; - int ud_av_l_key_ctl; - - u32 token; - struct ipz_eq_handle eq_handle; - struct ipz_pd pd; - struct ipz_cq_handle send_cq_handle, recv_cq_handle; - - u32 srq_qpn, srq_token, srq_limit; - - /* output parameters */ - u32 real_qp_num; - struct ipz_qp_handle qp_handle; - struct h_galpas galpas; -}; - -int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp); -int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int qp_num); -struct ehca_qp *ehca_cq_get_qp(struct ehca_cq *cq, int qp_num); - -#endif diff --git a/drivers/staging/rdma/ehca/ehca_classes_pSeries.h b/drivers/staging/rdma/ehca/ehca_classes_pSeries.h deleted file mode 100644 index 689c35786dd2..000000000000 --- a/drivers/staging/rdma/ehca/ehca_classes_pSeries.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * pSeries interface definitions - * - * Authors: Waleri Fomin - * Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __EHCA_CLASSES_PSERIES_H__ -#define __EHCA_CLASSES_PSERIES_H__ - -#include "hcp_phyp.h" -#include "ipz_pt_fn.h" - - -struct ehca_pfqp { - struct ipz_qpt sqpt; - struct ipz_qpt rqpt; -}; - -struct ehca_pfcq { - struct ipz_qpt qpt; - u32 cqnr; -}; - -struct ehca_pfeq { - struct ipz_qpt qpt; - struct h_galpa galpa; - u32 eqnr; -}; - -struct ipz_adapter_handle { - u64 handle; -}; - -struct ipz_cq_handle { - u64 handle; -}; - -struct ipz_eq_handle { - u64 handle; -}; - -struct ipz_qp_handle { - u64 handle; -}; -struct ipz_mrmw_handle { - u64 handle; -}; - -struct ipz_pd { - u32 value; -}; - -struct hcp_modify_qp_control_block { - u32 qkey; /* 00 */ - u32 rdd; /* reliable datagram domain */ - u32 send_psn; /* 02 */ - u32 receive_psn; /* 03 */ - u32 prim_phys_port; /* 04 */ - u32 alt_phys_port; /* 05 */ - u32 prim_p_key_idx; /* 06 */ - u32 alt_p_key_idx; /* 07 */ - u32 rdma_atomic_ctrl; /* 08 */ - u32 qp_state; /* 09 */ - u32 reserved_10; /* 10 */ - u32 rdma_nr_atomic_resp_res; /* 11 */ - u32 path_migration_state; /* 12 */ - u32 rdma_atomic_outst_dest_qp; /* 13 */ - u32 dest_qp_nr; /* 14 */ - u32 min_rnr_nak_timer_field; /* 15 */ - u32 service_level; /* 16 */ - u32 send_grh_flag; /* 17 */ - u32 retry_count; /* 18 */ - u32 timeout; /* 19 */ - u32 path_mtu; /* 20 */ - u32 max_static_rate; /* 21 */ - u32 dlid; /* 22 */ - u32 rnr_retry_count; /* 23 */ - u32 source_path_bits; /* 24 */ - u32 traffic_class; /* 25 */ - u32 hop_limit; /* 26 */ - u32 source_gid_idx; /* 27 */ - u32 flow_label; /* 28 */ - u32 reserved_29; /* 29 */ - union { /* 30 */ - u64 dw[2]; - u8 byte[16]; - } dest_gid; - u32 service_level_al; /* 34 */ - u32 send_grh_flag_al; /* 35 */ - u32 retry_count_al; /* 36 */ - u32 timeout_al; /* 37 */ - u32 max_static_rate_al; /* 38 */ - u32 dlid_al; /* 39 */ - u32 rnr_retry_count_al; /* 40 */ - u32 source_path_bits_al; /* 41 */ - u32 traffic_class_al; /* 42 */ - u32 hop_limit_al; /* 43 */ - u32 source_gid_idx_al; /* 44 */ - u32 flow_label_al; /* 45 */ - u32 reserved_46; /* 46 */ - u32 reserved_47; /* 47 */ - union { /* 48 */ - u64 dw[2]; - u8 byte[16]; - } dest_gid_al; - u32 max_nr_outst_send_wr; /* 52 */ - u32 max_nr_outst_recv_wr; /* 53 */ - u32 disable_ete_credit_check; /* 54 */ - u32 qp_number; /* 55 */ - u64 send_queue_handle; /* 56 */ - u64 recv_queue_handle; /* 58 */ - u32 actual_nr_sges_in_sq_wqe; /* 60 */ - u32 actual_nr_sges_in_rq_wqe; /* 61 */ - u32 qp_enable; /* 62 */ - u32 curr_srq_limit; /* 63 */ - u64 qp_aff_asyn_ev_log_reg; /* 64 */ - u64 shared_rq_hndl; /* 66 */ - u64 trigg_doorbell_qp_hndl; /* 68 */ - u32 reserved_70_127[58]; /* 70 */ -}; - -#define MQPCB_MASK_QKEY EHCA_BMASK_IBM( 0, 0) -#define MQPCB_MASK_SEND_PSN EHCA_BMASK_IBM( 2, 2) -#define MQPCB_MASK_RECEIVE_PSN EHCA_BMASK_IBM( 3, 3) -#define MQPCB_MASK_PRIM_PHYS_PORT EHCA_BMASK_IBM( 4, 4) -#define MQPCB_PRIM_PHYS_PORT EHCA_BMASK_IBM(24, 31) -#define MQPCB_MASK_ALT_PHYS_PORT EHCA_BMASK_IBM( 5, 5) -#define MQPCB_MASK_PRIM_P_KEY_IDX EHCA_BMASK_IBM( 6, 6) -#define MQPCB_PRIM_P_KEY_IDX EHCA_BMASK_IBM(24, 31) -#define MQPCB_MASK_ALT_P_KEY_IDX EHCA_BMASK_IBM( 7, 7) -#define MQPCB_MASK_RDMA_ATOMIC_CTRL EHCA_BMASK_IBM( 8, 8) -#define MQPCB_MASK_QP_STATE EHCA_BMASK_IBM( 9, 9) -#define MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES EHCA_BMASK_IBM(11, 11) -#define MQPCB_MASK_PATH_MIGRATION_STATE EHCA_BMASK_IBM(12, 12) -#define MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP EHCA_BMASK_IBM(13, 13) -#define MQPCB_MASK_DEST_QP_NR EHCA_BMASK_IBM(14, 14) -#define MQPCB_MASK_MIN_RNR_NAK_TIMER_FIELD EHCA_BMASK_IBM(15, 15) -#define MQPCB_MASK_SERVICE_LEVEL EHCA_BMASK_IBM(16, 16) -#define MQPCB_MASK_SEND_GRH_FLAG EHCA_BMASK_IBM(17, 17) -#define MQPCB_MASK_RETRY_COUNT EHCA_BMASK_IBM(18, 18) -#define MQPCB_MASK_TIMEOUT EHCA_BMASK_IBM(19, 19) -#define MQPCB_MASK_PATH_MTU EHCA_BMASK_IBM(20, 20) -#define MQPCB_MASK_MAX_STATIC_RATE EHCA_BMASK_IBM(21, 21) -#define MQPCB_MASK_DLID EHCA_BMASK_IBM(22, 22) -#define MQPCB_MASK_RNR_RETRY_COUNT EHCA_BMASK_IBM(23, 23) -#define MQPCB_MASK_SOURCE_PATH_BITS EHCA_BMASK_IBM(24, 24) -#define MQPCB_MASK_TRAFFIC_CLASS EHCA_BMASK_IBM(25, 25) -#define MQPCB_MASK_HOP_LIMIT EHCA_BMASK_IBM(26, 26) -#define MQPCB_MASK_SOURCE_GID_IDX EHCA_BMASK_IBM(27, 27) -#define MQPCB_MASK_FLOW_LABEL EHCA_BMASK_IBM(28, 28) -#define MQPCB_MASK_DEST_GID EHCA_BMASK_IBM(30, 30) -#define MQPCB_MASK_SERVICE_LEVEL_AL EHCA_BMASK_IBM(31, 31) -#define MQPCB_MASK_SEND_GRH_FLAG_AL EHCA_BMASK_IBM(32, 32) -#define MQPCB_MASK_RETRY_COUNT_AL EHCA_BMASK_IBM(33, 33) -#define MQPCB_MASK_TIMEOUT_AL EHCA_BMASK_IBM(34, 34) -#define MQPCB_MASK_MAX_STATIC_RATE_AL EHCA_BMASK_IBM(35, 35) -#define MQPCB_MASK_DLID_AL EHCA_BMASK_IBM(36, 36) -#define MQPCB_MASK_RNR_RETRY_COUNT_AL EHCA_BMASK_IBM(37, 37) -#define MQPCB_MASK_SOURCE_PATH_BITS_AL EHCA_BMASK_IBM(38, 38) -#define MQPCB_MASK_TRAFFIC_CLASS_AL EHCA_BMASK_IBM(39, 39) -#define MQPCB_MASK_HOP_LIMIT_AL EHCA_BMASK_IBM(40, 40) -#define MQPCB_MASK_SOURCE_GID_IDX_AL EHCA_BMASK_IBM(41, 41) -#define MQPCB_MASK_FLOW_LABEL_AL EHCA_BMASK_IBM(42, 42) -#define MQPCB_MASK_DEST_GID_AL EHCA_BMASK_IBM(44, 44) -#define MQPCB_MASK_MAX_NR_OUTST_SEND_WR EHCA_BMASK_IBM(45, 45) -#define MQPCB_MASK_MAX_NR_OUTST_RECV_WR EHCA_BMASK_IBM(46, 46) -#define MQPCB_MASK_DISABLE_ETE_CREDIT_CHECK EHCA_BMASK_IBM(47, 47) -#define MQPCB_MASK_QP_ENABLE EHCA_BMASK_IBM(48, 48) -#define MQPCB_MASK_CURR_SRQ_LIMIT EHCA_BMASK_IBM(49, 49) -#define MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG EHCA_BMASK_IBM(50, 50) -#define MQPCB_MASK_SHARED_RQ_HNDL EHCA_BMASK_IBM(51, 51) - -#endif /* __EHCA_CLASSES_PSERIES_H__ */ diff --git a/drivers/staging/rdma/ehca/ehca_cq.c b/drivers/staging/rdma/ehca/ehca_cq.c deleted file mode 100644 index 1aa7931fe860..000000000000 --- a/drivers/staging/rdma/ehca/ehca_cq.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Completion queue handling - * - * Authors: Waleri Fomin - * Khadija Souissi - * Reinhard Ernst - * Heiko J Schick - * Hoang-Nam Nguyen - * - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "ehca_iverbs.h" -#include "ehca_classes.h" -#include "ehca_irq.h" -#include "hcp_if.h" - -static struct kmem_cache *cq_cache; - -int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp) -{ - unsigned int qp_num = qp->real_qp_num; - unsigned int key = qp_num & (QP_HASHTAB_LEN-1); - unsigned long flags; - - spin_lock_irqsave(&cq->spinlock, flags); - hlist_add_head(&qp->list_entries, &cq->qp_hashtab[key]); - spin_unlock_irqrestore(&cq->spinlock, flags); - - ehca_dbg(cq->ib_cq.device, "cq_num=%x real_qp_num=%x", - cq->cq_number, qp_num); - - return 0; -} - -int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int real_qp_num) -{ - int ret = -EINVAL; - unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1); - struct hlist_node *iter; - struct ehca_qp *qp; - unsigned long flags; - - spin_lock_irqsave(&cq->spinlock, flags); - hlist_for_each(iter, &cq->qp_hashtab[key]) { - qp = hlist_entry(iter, struct ehca_qp, list_entries); - if (qp->real_qp_num == real_qp_num) { - hlist_del(iter); - ehca_dbg(cq->ib_cq.device, - "removed qp from cq .cq_num=%x real_qp_num=%x", - cq->cq_number, real_qp_num); - ret = 0; - break; - } - } - spin_unlock_irqrestore(&cq->spinlock, flags); - if (ret) - ehca_err(cq->ib_cq.device, - "qp not found cq_num=%x real_qp_num=%x", - cq->cq_number, real_qp_num); - - return ret; -} - -struct ehca_qp *ehca_cq_get_qp(struct ehca_cq *cq, int real_qp_num) -{ - struct ehca_qp *ret = NULL; - unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1); - struct hlist_node *iter; - struct ehca_qp *qp; - hlist_for_each(iter, &cq->qp_hashtab[key]) { - qp = hlist_entry(iter, struct ehca_qp, list_entries); - if (qp->real_qp_num == real_qp_num) { - ret = qp; - break; - } - } - return ret; -} - -struct ib_cq *ehca_create_cq(struct ib_device *device, - const struct ib_cq_init_attr *attr, - struct ib_ucontext *context, - struct ib_udata *udata) -{ - int cqe = attr->cqe; - static const u32 additional_cqe = 20; - struct ib_cq *cq; - struct ehca_cq *my_cq; - struct ehca_shca *shca = - container_of(device, struct ehca_shca, ib_device); - struct ipz_adapter_handle adapter_handle; - struct ehca_alloc_cq_parms param; /* h_call's out parameters */ - struct h_galpa gal; - void *vpage; - u32 counter; - u64 rpage, cqx_fec, h_ret; - int rc, i; - unsigned long flags; - - if (attr->flags) - return ERR_PTR(-EINVAL); - - if (cqe >= 0xFFFFFFFF - 64 - additional_cqe) - return ERR_PTR(-EINVAL); - - if (!atomic_add_unless(&shca->num_cqs, 1, shca->max_num_cqs)) { - ehca_err(device, "Unable to create CQ, max number of %i " - "CQs reached.", shca->max_num_cqs); - ehca_err(device, "To increase the maximum number of CQs " - "use the number_of_cqs module parameter.\n"); - return ERR_PTR(-ENOSPC); - } - - my_cq = kmem_cache_zalloc(cq_cache, GFP_KERNEL); - if (!my_cq) { - ehca_err(device, "Out of memory for ehca_cq struct device=%p", - device); - atomic_dec(&shca->num_cqs); - return ERR_PTR(-ENOMEM); - } - - memset(¶m, 0, sizeof(struct ehca_alloc_cq_parms)); - - spin_lock_init(&my_cq->spinlock); - spin_lock_init(&my_cq->cb_lock); - spin_lock_init(&my_cq->task_lock); - atomic_set(&my_cq->nr_events, 0); - init_waitqueue_head(&my_cq->wait_completion); - - cq = &my_cq->ib_cq; - - adapter_handle = shca->ipz_hca_handle; - param.eq_handle = shca->eq.ipz_eq_handle; - - idr_preload(GFP_KERNEL); - write_lock_irqsave(&ehca_cq_idr_lock, flags); - rc = idr_alloc(&ehca_cq_idr, my_cq, 0, 0x2000000, GFP_NOWAIT); - write_unlock_irqrestore(&ehca_cq_idr_lock, flags); - idr_preload_end(); - - if (rc < 0) { - cq = ERR_PTR(-ENOMEM); - ehca_err(device, "Can't allocate new idr entry. device=%p", - device); - goto create_cq_exit1; - } - my_cq->token = rc; - - /* - * CQs maximum depth is 4GB-64, but we need additional 20 as buffer - * for receiving errors CQEs. - */ - param.nr_cqe = cqe + additional_cqe; - h_ret = hipz_h_alloc_resource_cq(adapter_handle, my_cq, ¶m); - - if (h_ret != H_SUCCESS) { - ehca_err(device, "hipz_h_alloc_resource_cq() failed " - "h_ret=%lli device=%p", h_ret, device); - cq = ERR_PTR(ehca2ib_return_code(h_ret)); - goto create_cq_exit2; - } - - rc = ipz_queue_ctor(NULL, &my_cq->ipz_queue, param.act_pages, - EHCA_PAGESIZE, sizeof(struct ehca_cqe), 0, 0); - if (!rc) { - ehca_err(device, "ipz_queue_ctor() failed ipz_rc=%i device=%p", - rc, device); - cq = ERR_PTR(-EINVAL); - goto create_cq_exit3; - } - - for (counter = 0; counter < param.act_pages; counter++) { - vpage = ipz_qpageit_get_inc(&my_cq->ipz_queue); - if (!vpage) { - ehca_err(device, "ipz_qpageit_get_inc() " - "returns NULL device=%p", device); - cq = ERR_PTR(-EAGAIN); - goto create_cq_exit4; - } - rpage = __pa(vpage); - - h_ret = hipz_h_register_rpage_cq(adapter_handle, - my_cq->ipz_cq_handle, - &my_cq->pf, - 0, - 0, - rpage, - 1, - my_cq->galpas. - kernel); - - if (h_ret < H_SUCCESS) { - ehca_err(device, "hipz_h_register_rpage_cq() failed " - "ehca_cq=%p cq_num=%x h_ret=%lli counter=%i " - "act_pages=%i", my_cq, my_cq->cq_number, - h_ret, counter, param.act_pages); - cq = ERR_PTR(-EINVAL); - goto create_cq_exit4; - } - - if (counter == (param.act_pages - 1)) { - vpage = ipz_qpageit_get_inc(&my_cq->ipz_queue); - if ((h_ret != H_SUCCESS) || vpage) { - ehca_err(device, "Registration of pages not " - "complete ehca_cq=%p cq_num=%x " - "h_ret=%lli", my_cq, my_cq->cq_number, - h_ret); - cq = ERR_PTR(-EAGAIN); - goto create_cq_exit4; - } - } else { - if (h_ret != H_PAGE_REGISTERED) { - ehca_err(device, "Registration of page failed " - "ehca_cq=%p cq_num=%x h_ret=%lli " - "counter=%i act_pages=%i", - my_cq, my_cq->cq_number, - h_ret, counter, param.act_pages); - cq = ERR_PTR(-ENOMEM); - goto create_cq_exit4; - } - } - } - - ipz_qeit_reset(&my_cq->ipz_queue); - - gal = my_cq->galpas.kernel; - cqx_fec = hipz_galpa_load(gal, CQTEMM_OFFSET(cqx_fec)); - ehca_dbg(device, "ehca_cq=%p cq_num=%x CQX_FEC=%llx", - my_cq, my_cq->cq_number, cqx_fec); - - my_cq->ib_cq.cqe = my_cq->nr_of_entries = - param.act_nr_of_entries - additional_cqe; - my_cq->cq_number = (my_cq->ipz_cq_handle.handle) & 0xffff; - - for (i = 0; i < QP_HASHTAB_LEN; i++) - INIT_HLIST_HEAD(&my_cq->qp_hashtab[i]); - - INIT_LIST_HEAD(&my_cq->sqp_err_list); - INIT_LIST_HEAD(&my_cq->rqp_err_list); - - if (context) { - struct ipz_queue *ipz_queue = &my_cq->ipz_queue; - struct ehca_create_cq_resp resp; - memset(&resp, 0, sizeof(resp)); - resp.cq_number = my_cq->cq_number; - resp.token = my_cq->token; - resp.ipz_queue.qe_size = ipz_queue->qe_size; - resp.ipz_queue.act_nr_of_sg = ipz_queue->act_nr_of_sg; - resp.ipz_queue.queue_length = ipz_queue->queue_length; - resp.ipz_queue.pagesize = ipz_queue->pagesize; - resp.ipz_queue.toggle_state = ipz_queue->toggle_state; - resp.fw_handle_ofs = (u32) - (my_cq->galpas.user.fw_handle & (PAGE_SIZE - 1)); - if (ib_copy_to_udata(udata, &resp, sizeof(resp))) { - ehca_err(device, "Copy to udata failed."); - cq = ERR_PTR(-EFAULT); - goto create_cq_exit4; - } - } - - return cq; - -create_cq_exit4: - ipz_queue_dtor(NULL, &my_cq->ipz_queue); - -create_cq_exit3: - h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 1); - if (h_ret != H_SUCCESS) - ehca_err(device, "hipz_h_destroy_cq() failed ehca_cq=%p " - "cq_num=%x h_ret=%lli", my_cq, my_cq->cq_number, h_ret); - -create_cq_exit2: - write_lock_irqsave(&ehca_cq_idr_lock, flags); - idr_remove(&ehca_cq_idr, my_cq->token); - write_unlock_irqrestore(&ehca_cq_idr_lock, flags); - -create_cq_exit1: - kmem_cache_free(cq_cache, my_cq); - - atomic_dec(&shca->num_cqs); - return cq; -} - -int ehca_destroy_cq(struct ib_cq *cq) -{ - u64 h_ret; - struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); - int cq_num = my_cq->cq_number; - struct ib_device *device = cq->device; - struct ehca_shca *shca = container_of(device, struct ehca_shca, - ib_device); - struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle; - unsigned long flags; - - if (cq->uobject) { - if (my_cq->mm_count_galpa || my_cq->mm_count_queue) { - ehca_err(device, "Resources still referenced in " - "user space cq_num=%x", my_cq->cq_number); - return -EINVAL; - } - } - - /* - * remove the CQ from the idr first to make sure - * no more interrupt tasklets will touch this CQ - */ - write_lock_irqsave(&ehca_cq_idr_lock, flags); - idr_remove(&ehca_cq_idr, my_cq->token); - write_unlock_irqrestore(&ehca_cq_idr_lock, flags); - - /* now wait until all pending events have completed */ - wait_event(my_cq->wait_completion, !atomic_read(&my_cq->nr_events)); - - /* nobody's using our CQ any longer -- we can destroy it */ - h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0); - if (h_ret == H_R_STATE) { - /* cq in err: read err data and destroy it forcibly */ - ehca_dbg(device, "ehca_cq=%p cq_num=%x resource=%llx in err " - "state. Try to delete it forcibly.", - my_cq, cq_num, my_cq->ipz_cq_handle.handle); - ehca_error_data(shca, my_cq, my_cq->ipz_cq_handle.handle); - h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 1); - if (h_ret == H_SUCCESS) - ehca_dbg(device, "cq_num=%x deleted successfully.", - cq_num); - } - if (h_ret != H_SUCCESS) { - ehca_err(device, "hipz_h_destroy_cq() failed h_ret=%lli " - "ehca_cq=%p cq_num=%x", h_ret, my_cq, cq_num); - return ehca2ib_return_code(h_ret); - } - ipz_queue_dtor(NULL, &my_cq->ipz_queue); - kmem_cache_free(cq_cache, my_cq); - - atomic_dec(&shca->num_cqs); - return 0; -} - -int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata) -{ - /* TODO: proper resize needs to be done */ - ehca_err(cq->device, "not implemented yet"); - - return -EFAULT; -} - -int ehca_init_cq_cache(void) -{ - cq_cache = kmem_cache_create("ehca_cache_cq", - sizeof(struct ehca_cq), 0, - SLAB_HWCACHE_ALIGN, - NULL); - if (!cq_cache) - return -ENOMEM; - return 0; -} - -void ehca_cleanup_cq_cache(void) -{ - kmem_cache_destroy(cq_cache); -} diff --git a/drivers/staging/rdma/ehca/ehca_eq.c b/drivers/staging/rdma/ehca/ehca_eq.c deleted file mode 100644 index 90da6747d395..000000000000 --- a/drivers/staging/rdma/ehca/ehca_eq.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Event queue handling - * - * Authors: Waleri Fomin - * Khadija Souissi - * Reinhard Ernst - * Heiko J Schick - * Hoang-Nam Nguyen - * - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ehca_classes.h" -#include "ehca_irq.h" -#include "ehca_iverbs.h" -#include "ehca_qes.h" -#include "hcp_if.h" -#include "ipz_pt_fn.h" - -int ehca_create_eq(struct ehca_shca *shca, - struct ehca_eq *eq, - const enum ehca_eq_type type, const u32 length) -{ - int ret; - u64 h_ret; - u32 nr_pages; - u32 i; - void *vpage; - struct ib_device *ib_dev = &shca->ib_device; - - spin_lock_init(&eq->spinlock); - spin_lock_init(&eq->irq_spinlock); - eq->is_initialized = 0; - - if (type != EHCA_EQ && type != EHCA_NEQ) { - ehca_err(ib_dev, "Invalid EQ type %x. eq=%p", type, eq); - return -EINVAL; - } - if (!length) { - ehca_err(ib_dev, "EQ length must not be zero. eq=%p", eq); - return -EINVAL; - } - - h_ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle, - &eq->pf, - type, - length, - &eq->ipz_eq_handle, - &eq->length, - &nr_pages, &eq->ist); - - if (h_ret != H_SUCCESS) { - ehca_err(ib_dev, "Can't allocate EQ/NEQ. eq=%p", eq); - return -EINVAL; - } - - ret = ipz_queue_ctor(NULL, &eq->ipz_queue, nr_pages, - EHCA_PAGESIZE, sizeof(struct ehca_eqe), 0, 0); - if (!ret) { - ehca_err(ib_dev, "Can't allocate EQ pages eq=%p", eq); - goto create_eq_exit1; - } - - for (i = 0; i < nr_pages; i++) { - u64 rpage; - - vpage = ipz_qpageit_get_inc(&eq->ipz_queue); - if (!vpage) - goto create_eq_exit2; - - rpage = __pa(vpage); - h_ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle, - eq->ipz_eq_handle, - &eq->pf, - 0, 0, rpage, 1); - - if (i == (nr_pages - 1)) { - /* last page */ - vpage = ipz_qpageit_get_inc(&eq->ipz_queue); - if (h_ret != H_SUCCESS || vpage) - goto create_eq_exit2; - } else { - if (h_ret != H_PAGE_REGISTERED) - goto create_eq_exit2; - } - } - - ipz_qeit_reset(&eq->ipz_queue); - - /* register interrupt handlers and initialize work queues */ - if (type == EHCA_EQ) { - tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca); - - ret = ibmebus_request_irq(eq->ist, ehca_interrupt_eq, - 0, "ehca_eq", - (void *)shca); - if (ret < 0) - ehca_err(ib_dev, "Can't map interrupt handler."); - } else if (type == EHCA_NEQ) { - tasklet_init(&eq->interrupt_task, ehca_tasklet_neq, (long)shca); - - ret = ibmebus_request_irq(eq->ist, ehca_interrupt_neq, - 0, "ehca_neq", - (void *)shca); - if (ret < 0) - ehca_err(ib_dev, "Can't map interrupt handler."); - } - - eq->is_initialized = 1; - - return 0; - -create_eq_exit2: - ipz_queue_dtor(NULL, &eq->ipz_queue); - -create_eq_exit1: - hipz_h_destroy_eq(shca->ipz_hca_handle, eq); - - return -EINVAL; -} - -void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq) -{ - unsigned long flags; - void *eqe; - - spin_lock_irqsave(&eq->spinlock, flags); - eqe = ipz_eqit_eq_get_inc_valid(&eq->ipz_queue); - spin_unlock_irqrestore(&eq->spinlock, flags); - - return eqe; -} - -int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq) -{ - unsigned long flags; - u64 h_ret; - - ibmebus_free_irq(eq->ist, (void *)shca); - - spin_lock_irqsave(&shca_list_lock, flags); - eq->is_initialized = 0; - spin_unlock_irqrestore(&shca_list_lock, flags); - - tasklet_kill(&eq->interrupt_task); - - h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq); - - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "Can't free EQ resources."); - return -EINVAL; - } - ipz_queue_dtor(NULL, &eq->ipz_queue); - - return 0; -} diff --git a/drivers/staging/rdma/ehca/ehca_hca.c b/drivers/staging/rdma/ehca/ehca_hca.c deleted file mode 100644 index e8b1bb65797a..000000000000 --- a/drivers/staging/rdma/ehca/ehca_hca.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * HCA query functions - * - * Authors: Heiko J Schick - * Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "ehca_tools.h" -#include "ehca_iverbs.h" -#include "hcp_if.h" - -static unsigned int limit_uint(unsigned int value) -{ - return min_t(unsigned int, value, INT_MAX); -} - -int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props, - struct ib_udata *uhw) -{ - int i, ret = 0; - struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, - ib_device); - struct hipz_query_hca *rblock; - - static const u32 cap_mapping[] = { - IB_DEVICE_RESIZE_MAX_WR, HCA_CAP_WQE_RESIZE, - IB_DEVICE_BAD_PKEY_CNTR, HCA_CAP_BAD_P_KEY_CTR, - IB_DEVICE_BAD_QKEY_CNTR, HCA_CAP_Q_KEY_VIOL_CTR, - IB_DEVICE_RAW_MULTI, HCA_CAP_RAW_PACKET_MCAST, - IB_DEVICE_AUTO_PATH_MIG, HCA_CAP_AUTO_PATH_MIG, - IB_DEVICE_CHANGE_PHY_PORT, HCA_CAP_SQD_RTS_PORT_CHANGE, - IB_DEVICE_UD_AV_PORT_ENFORCE, HCA_CAP_AH_PORT_NR_CHECK, - IB_DEVICE_CURR_QP_STATE_MOD, HCA_CAP_CUR_QP_STATE_MOD, - IB_DEVICE_SHUTDOWN_PORT, HCA_CAP_SHUTDOWN_PORT, - IB_DEVICE_INIT_TYPE, HCA_CAP_INIT_TYPE, - IB_DEVICE_PORT_ACTIVE_EVENT, HCA_CAP_PORT_ACTIVE_EVENT, - }; - - if (uhw->inlen || uhw->outlen) - return -EINVAL; - - rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); - if (!rblock) { - ehca_err(&shca->ib_device, "Can't allocate rblock memory."); - return -ENOMEM; - } - - if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { - ehca_err(&shca->ib_device, "Can't query device properties"); - ret = -EINVAL; - goto query_device1; - } - - memset(props, 0, sizeof(struct ib_device_attr)); - props->page_size_cap = shca->hca_cap_mr_pgsize; - props->fw_ver = rblock->hw_ver; - props->max_mr_size = rblock->max_mr_size; - props->vendor_id = rblock->vendor_id >> 8; - props->vendor_part_id = rblock->vendor_part_id >> 16; - props->hw_ver = rblock->hw_ver; - props->max_qp = limit_uint(rblock->max_qp); - props->max_qp_wr = limit_uint(rblock->max_wqes_wq); - props->max_sge = limit_uint(rblock->max_sge); - props->max_sge_rd = limit_uint(rblock->max_sge_rd); - props->max_cq = limit_uint(rblock->max_cq); - props->max_cqe = limit_uint(rblock->max_cqe); - props->max_mr = limit_uint(rblock->max_mr); - props->max_mw = limit_uint(rblock->max_mw); - props->max_pd = limit_uint(rblock->max_pd); - props->max_ah = limit_uint(rblock->max_ah); - props->max_ee = limit_uint(rblock->max_rd_ee_context); - props->max_rdd = limit_uint(rblock->max_rd_domain); - props->max_fmr = limit_uint(rblock->max_mr); - props->max_qp_rd_atom = limit_uint(rblock->max_rr_qp); - props->max_ee_rd_atom = limit_uint(rblock->max_rr_ee_context); - props->max_res_rd_atom = limit_uint(rblock->max_rr_hca); - props->max_qp_init_rd_atom = limit_uint(rblock->max_act_wqs_qp); - props->max_ee_init_rd_atom = limit_uint(rblock->max_act_wqs_ee_context); - - if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) { - props->max_srq = limit_uint(props->max_qp); - props->max_srq_wr = limit_uint(props->max_qp_wr); - props->max_srq_sge = 3; - } - - props->max_pkeys = 16; - /* Some FW versions say 0 here; insert sensible value in that case */ - props->local_ca_ack_delay = rblock->local_ca_ack_delay ? - min_t(u8, rblock->local_ca_ack_delay, 255) : 12; - props->max_raw_ipv6_qp = limit_uint(rblock->max_raw_ipv6_qp); - props->max_raw_ethy_qp = limit_uint(rblock->max_raw_ethy_qp); - props->max_mcast_grp = limit_uint(rblock->max_mcast_grp); - props->max_mcast_qp_attach = limit_uint(rblock->max_mcast_qp_attach); - props->max_total_mcast_qp_attach - = limit_uint(rblock->max_total_mcast_qp_attach); - - /* translate device capabilities */ - props->device_cap_flags = IB_DEVICE_SYS_IMAGE_GUID | - IB_DEVICE_RC_RNR_NAK_GEN | IB_DEVICE_N_NOTIFY_CQ; - for (i = 0; i < ARRAY_SIZE(cap_mapping); i += 2) - if (rblock->hca_cap_indicators & cap_mapping[i + 1]) - props->device_cap_flags |= cap_mapping[i]; - -query_device1: - ehca_free_fw_ctrlblock(rblock); - - return ret; -} - -static enum ib_mtu map_mtu(struct ehca_shca *shca, u32 fw_mtu) -{ - switch (fw_mtu) { - case 0x1: - return IB_MTU_256; - case 0x2: - return IB_MTU_512; - case 0x3: - return IB_MTU_1024; - case 0x4: - return IB_MTU_2048; - case 0x5: - return IB_MTU_4096; - default: - ehca_err(&shca->ib_device, "Unknown MTU size: %x.", - fw_mtu); - return 0; - } -} - -static u8 map_number_of_vls(struct ehca_shca *shca, u32 vl_cap) -{ - switch (vl_cap) { - case 0x1: - return 1; - case 0x2: - return 2; - case 0x3: - return 4; - case 0x4: - return 8; - case 0x5: - return 15; - default: - ehca_err(&shca->ib_device, "invalid Vl Capability: %x.", - vl_cap); - return 0; - } -} - -int ehca_query_port(struct ib_device *ibdev, - u8 port, struct ib_port_attr *props) -{ - int ret = 0; - u64 h_ret; - struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, - ib_device); - struct hipz_query_port *rblock; - - rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); - if (!rblock) { - ehca_err(&shca->ib_device, "Can't allocate rblock memory."); - return -ENOMEM; - } - - h_ret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "Can't query port properties"); - ret = -EINVAL; - goto query_port1; - } - - memset(props, 0, sizeof(struct ib_port_attr)); - - props->active_mtu = props->max_mtu = map_mtu(shca, rblock->max_mtu); - props->port_cap_flags = rblock->capability_mask; - props->gid_tbl_len = rblock->gid_tbl_len; - if (rblock->max_msg_sz) - props->max_msg_sz = rblock->max_msg_sz; - else - props->max_msg_sz = 0x1 << 31; - props->bad_pkey_cntr = rblock->bad_pkey_cntr; - props->qkey_viol_cntr = rblock->qkey_viol_cntr; - props->pkey_tbl_len = rblock->pkey_tbl_len; - props->lid = rblock->lid; - props->sm_lid = rblock->sm_lid; - props->lmc = rblock->lmc; - props->sm_sl = rblock->sm_sl; - props->subnet_timeout = rblock->subnet_timeout; - props->init_type_reply = rblock->init_type_reply; - props->max_vl_num = map_number_of_vls(shca, rblock->vl_cap); - - if (rblock->state && rblock->phys_width) { - props->phys_state = rblock->phys_pstate; - props->state = rblock->phys_state; - props->active_width = rblock->phys_width; - props->active_speed = rblock->phys_speed; - } else { - /* old firmware releases don't report physical - * port info, so use default values - */ - props->phys_state = 5; - props->state = rblock->state; - props->active_width = IB_WIDTH_12X; - props->active_speed = IB_SPEED_SDR; - } - -query_port1: - ehca_free_fw_ctrlblock(rblock); - - return ret; -} - -int ehca_query_sma_attr(struct ehca_shca *shca, - u8 port, struct ehca_sma_attr *attr) -{ - int ret = 0; - u64 h_ret; - struct hipz_query_port *rblock; - - rblock = ehca_alloc_fw_ctrlblock(GFP_ATOMIC); - if (!rblock) { - ehca_err(&shca->ib_device, "Can't allocate rblock memory."); - return -ENOMEM; - } - - h_ret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "Can't query port properties"); - ret = -EINVAL; - goto query_sma_attr1; - } - - memset(attr, 0, sizeof(struct ehca_sma_attr)); - - attr->lid = rblock->lid; - attr->lmc = rblock->lmc; - attr->sm_sl = rblock->sm_sl; - attr->sm_lid = rblock->sm_lid; - - attr->pkey_tbl_len = rblock->pkey_tbl_len; - memcpy(attr->pkeys, rblock->pkey_entries, sizeof(attr->pkeys)); - -query_sma_attr1: - ehca_free_fw_ctrlblock(rblock); - - return ret; -} - -int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey) -{ - int ret = 0; - u64 h_ret; - struct ehca_shca *shca; - struct hipz_query_port *rblock; - - shca = container_of(ibdev, struct ehca_shca, ib_device); - if (index > 16) { - ehca_err(&shca->ib_device, "Invalid index: %x.", index); - return -EINVAL; - } - - rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); - if (!rblock) { - ehca_err(&shca->ib_device, "Can't allocate rblock memory."); - return -ENOMEM; - } - - h_ret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "Can't query port properties"); - ret = -EINVAL; - goto query_pkey1; - } - - memcpy(pkey, &rblock->pkey_entries + index, sizeof(u16)); - -query_pkey1: - ehca_free_fw_ctrlblock(rblock); - - return ret; -} - -int ehca_query_gid(struct ib_device *ibdev, u8 port, - int index, union ib_gid *gid) -{ - int ret = 0; - u64 h_ret; - struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, - ib_device); - struct hipz_query_port *rblock; - - if (index < 0 || index > 255) { - ehca_err(&shca->ib_device, "Invalid index: %x.", index); - return -EINVAL; - } - - rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); - if (!rblock) { - ehca_err(&shca->ib_device, "Can't allocate rblock memory."); - return -ENOMEM; - } - - h_ret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "Can't query port properties"); - ret = -EINVAL; - goto query_gid1; - } - - memcpy(&gid->raw[0], &rblock->gid_prefix, sizeof(u64)); - memcpy(&gid->raw[8], &rblock->guid_entries[index], sizeof(u64)); - -query_gid1: - ehca_free_fw_ctrlblock(rblock); - - return ret; -} - -static const u32 allowed_port_caps = ( - IB_PORT_SM | IB_PORT_LED_INFO_SUP | IB_PORT_CM_SUP | - IB_PORT_SNMP_TUNNEL_SUP | IB_PORT_DEVICE_MGMT_SUP | - IB_PORT_VENDOR_CLASS_SUP); - -int ehca_modify_port(struct ib_device *ibdev, - u8 port, int port_modify_mask, - struct ib_port_modify *props) -{ - int ret = 0; - struct ehca_shca *shca; - struct hipz_query_port *rblock; - u32 cap; - u64 hret; - - shca = container_of(ibdev, struct ehca_shca, ib_device); - if ((props->set_port_cap_mask | props->clr_port_cap_mask) - & ~allowed_port_caps) { - ehca_err(&shca->ib_device, "Non-changeable bits set in masks " - "set=%x clr=%x allowed=%x", props->set_port_cap_mask, - props->clr_port_cap_mask, allowed_port_caps); - return -EINVAL; - } - - if (mutex_lock_interruptible(&shca->modify_mutex)) - return -ERESTARTSYS; - - rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); - if (!rblock) { - ehca_err(&shca->ib_device, "Can't allocate rblock memory."); - ret = -ENOMEM; - goto modify_port1; - } - - hret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock); - if (hret != H_SUCCESS) { - ehca_err(&shca->ib_device, "Can't query port properties"); - ret = -EINVAL; - goto modify_port2; - } - - cap = (rblock->capability_mask | props->set_port_cap_mask) - & ~props->clr_port_cap_mask; - - hret = hipz_h_modify_port(shca->ipz_hca_handle, port, - cap, props->init_type, port_modify_mask); - if (hret != H_SUCCESS) { - ehca_err(&shca->ib_device, "Modify port failed h_ret=%lli", - hret); - ret = -EINVAL; - } - -modify_port2: - ehca_free_fw_ctrlblock(rblock); - -modify_port1: - mutex_unlock(&shca->modify_mutex); - - return ret; -} diff --git a/drivers/staging/rdma/ehca/ehca_irq.c b/drivers/staging/rdma/ehca/ehca_irq.c deleted file mode 100644 index 8615d7cf7e01..000000000000 --- a/drivers/staging/rdma/ehca/ehca_irq.c +++ /dev/null @@ -1,870 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Functions for EQs, NEQs and interrupts - * - * Authors: Heiko J Schick - * Khadija Souissi - * Hoang-Nam Nguyen - * Joachim Fenkes - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -#include "ehca_classes.h" -#include "ehca_irq.h" -#include "ehca_iverbs.h" -#include "ehca_tools.h" -#include "hcp_if.h" -#include "hipz_fns.h" -#include "ipz_pt_fn.h" - -#define EQE_COMPLETION_EVENT EHCA_BMASK_IBM( 1, 1) -#define EQE_CQ_QP_NUMBER EHCA_BMASK_IBM( 8, 31) -#define EQE_EE_IDENTIFIER EHCA_BMASK_IBM( 2, 7) -#define EQE_CQ_NUMBER EHCA_BMASK_IBM( 8, 31) -#define EQE_QP_NUMBER EHCA_BMASK_IBM( 8, 31) -#define EQE_QP_TOKEN EHCA_BMASK_IBM(32, 63) -#define EQE_CQ_TOKEN EHCA_BMASK_IBM(32, 63) - -#define NEQE_COMPLETION_EVENT EHCA_BMASK_IBM( 1, 1) -#define NEQE_EVENT_CODE EHCA_BMASK_IBM( 2, 7) -#define NEQE_PORT_NUMBER EHCA_BMASK_IBM( 8, 15) -#define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16, 16) -#define NEQE_DISRUPTIVE EHCA_BMASK_IBM(16, 16) -#define NEQE_SPECIFIC_EVENT EHCA_BMASK_IBM(16, 23) - -#define ERROR_DATA_LENGTH EHCA_BMASK_IBM(52, 63) -#define ERROR_DATA_TYPE EHCA_BMASK_IBM( 0, 7) - -static void queue_comp_task(struct ehca_cq *__cq); - -static struct ehca_comp_pool *pool; - -static inline void comp_event_callback(struct ehca_cq *cq) -{ - if (!cq->ib_cq.comp_handler) - return; - - spin_lock(&cq->cb_lock); - cq->ib_cq.comp_handler(&cq->ib_cq, cq->ib_cq.cq_context); - spin_unlock(&cq->cb_lock); - - return; -} - -static void print_error_data(struct ehca_shca *shca, void *data, - u64 *rblock, int length) -{ - u64 type = EHCA_BMASK_GET(ERROR_DATA_TYPE, rblock[2]); - u64 resource = rblock[1]; - - switch (type) { - case 0x1: /* Queue Pair */ - { - struct ehca_qp *qp = (struct ehca_qp *)data; - - /* only print error data if AER is set */ - if (rblock[6] == 0) - return; - - ehca_err(&shca->ib_device, - "QP 0x%x (resource=%llx) has errors.", - qp->ib_qp.qp_num, resource); - break; - } - case 0x4: /* Completion Queue */ - { - struct ehca_cq *cq = (struct ehca_cq *)data; - - ehca_err(&shca->ib_device, - "CQ 0x%x (resource=%llx) has errors.", - cq->cq_number, resource); - break; - } - default: - ehca_err(&shca->ib_device, - "Unknown error type: %llx on %s.", - type, shca->ib_device.name); - break; - } - - ehca_err(&shca->ib_device, "Error data is available: %llx.", resource); - ehca_err(&shca->ib_device, "EHCA ----- error data begin " - "---------------------------------------------------"); - ehca_dmp(rblock, length, "resource=%llx", resource); - ehca_err(&shca->ib_device, "EHCA ----- error data end " - "----------------------------------------------------"); - - return; -} - -int ehca_error_data(struct ehca_shca *shca, void *data, - u64 resource) -{ - - unsigned long ret; - u64 *rblock; - unsigned long block_count; - - rblock = ehca_alloc_fw_ctrlblock(GFP_ATOMIC); - if (!rblock) { - ehca_err(&shca->ib_device, "Cannot allocate rblock memory."); - ret = -ENOMEM; - goto error_data1; - } - - /* rblock must be 4K aligned and should be 4K large */ - ret = hipz_h_error_data(shca->ipz_hca_handle, - resource, - rblock, - &block_count); - - if (ret == H_R_STATE) - ehca_err(&shca->ib_device, - "No error data is available: %llx.", resource); - else if (ret == H_SUCCESS) { - int length; - - length = EHCA_BMASK_GET(ERROR_DATA_LENGTH, rblock[0]); - - if (length > EHCA_PAGESIZE) - length = EHCA_PAGESIZE; - - print_error_data(shca, data, rblock, length); - } else - ehca_err(&shca->ib_device, - "Error data could not be fetched: %llx", resource); - - ehca_free_fw_ctrlblock(rblock); - -error_data1: - return ret; - -} - -static void dispatch_qp_event(struct ehca_shca *shca, struct ehca_qp *qp, - enum ib_event_type event_type) -{ - struct ib_event event; - - /* PATH_MIG without the QP ever having been armed is false alarm */ - if (event_type == IB_EVENT_PATH_MIG && !qp->mig_armed) - return; - - event.device = &shca->ib_device; - event.event = event_type; - - if (qp->ext_type == EQPT_SRQ) { - if (!qp->ib_srq.event_handler) - return; - - event.element.srq = &qp->ib_srq; - qp->ib_srq.event_handler(&event, qp->ib_srq.srq_context); - } else { - if (!qp->ib_qp.event_handler) - return; - - event.element.qp = &qp->ib_qp; - qp->ib_qp.event_handler(&event, qp->ib_qp.qp_context); - } -} - -static void qp_event_callback(struct ehca_shca *shca, u64 eqe, - enum ib_event_type event_type, int fatal) -{ - struct ehca_qp *qp; - u32 token = EHCA_BMASK_GET(EQE_QP_TOKEN, eqe); - - read_lock(&ehca_qp_idr_lock); - qp = idr_find(&ehca_qp_idr, token); - if (qp) - atomic_inc(&qp->nr_events); - read_unlock(&ehca_qp_idr_lock); - - if (!qp) - return; - - if (fatal) - ehca_error_data(shca, qp, qp->ipz_qp_handle.handle); - - dispatch_qp_event(shca, qp, fatal && qp->ext_type == EQPT_SRQ ? - IB_EVENT_SRQ_ERR : event_type); - - /* - * eHCA only processes one WQE at a time for SRQ base QPs, - * so the last WQE has been processed as soon as the QP enters - * error state. - */ - if (fatal && qp->ext_type == EQPT_SRQBASE) - dispatch_qp_event(shca, qp, IB_EVENT_QP_LAST_WQE_REACHED); - - if (atomic_dec_and_test(&qp->nr_events)) - wake_up(&qp->wait_completion); - return; -} - -static void cq_event_callback(struct ehca_shca *shca, - u64 eqe) -{ - struct ehca_cq *cq; - u32 token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe); - - read_lock(&ehca_cq_idr_lock); - cq = idr_find(&ehca_cq_idr, token); - if (cq) - atomic_inc(&cq->nr_events); - read_unlock(&ehca_cq_idr_lock); - - if (!cq) - return; - - ehca_error_data(shca, cq, cq->ipz_cq_handle.handle); - - if (atomic_dec_and_test(&cq->nr_events)) - wake_up(&cq->wait_completion); - - return; -} - -static void parse_identifier(struct ehca_shca *shca, u64 eqe) -{ - u8 identifier = EHCA_BMASK_GET(EQE_EE_IDENTIFIER, eqe); - - switch (identifier) { - case 0x02: /* path migrated */ - qp_event_callback(shca, eqe, IB_EVENT_PATH_MIG, 0); - break; - case 0x03: /* communication established */ - qp_event_callback(shca, eqe, IB_EVENT_COMM_EST, 0); - break; - case 0x04: /* send queue drained */ - qp_event_callback(shca, eqe, IB_EVENT_SQ_DRAINED, 0); - break; - case 0x05: /* QP error */ - case 0x06: /* QP error */ - qp_event_callback(shca, eqe, IB_EVENT_QP_FATAL, 1); - break; - case 0x07: /* CQ error */ - case 0x08: /* CQ error */ - cq_event_callback(shca, eqe); - break; - case 0x09: /* MRMWPTE error */ - ehca_err(&shca->ib_device, "MRMWPTE error."); - break; - case 0x0A: /* port event */ - ehca_err(&shca->ib_device, "Port event."); - break; - case 0x0B: /* MR access error */ - ehca_err(&shca->ib_device, "MR access error."); - break; - case 0x0C: /* EQ error */ - ehca_err(&shca->ib_device, "EQ error."); - break; - case 0x0D: /* P/Q_Key mismatch */ - ehca_err(&shca->ib_device, "P/Q_Key mismatch."); - break; - case 0x10: /* sampling complete */ - ehca_err(&shca->ib_device, "Sampling complete."); - break; - case 0x11: /* unaffiliated access error */ - ehca_err(&shca->ib_device, "Unaffiliated access error."); - break; - case 0x12: /* path migrating */ - ehca_err(&shca->ib_device, "Path migrating."); - break; - case 0x13: /* interface trace stopped */ - ehca_err(&shca->ib_device, "Interface trace stopped."); - break; - case 0x14: /* first error capture info available */ - ehca_info(&shca->ib_device, "First error capture available"); - break; - case 0x15: /* SRQ limit reached */ - qp_event_callback(shca, eqe, IB_EVENT_SRQ_LIMIT_REACHED, 0); - break; - default: - ehca_err(&shca->ib_device, "Unknown identifier: %x on %s.", - identifier, shca->ib_device.name); - break; - } - - return; -} - -static void dispatch_port_event(struct ehca_shca *shca, int port_num, - enum ib_event_type type, const char *msg) -{ - struct ib_event event; - - ehca_info(&shca->ib_device, "port %d %s.", port_num, msg); - event.device = &shca->ib_device; - event.event = type; - event.element.port_num = port_num; - ib_dispatch_event(&event); -} - -static void notify_port_conf_change(struct ehca_shca *shca, int port_num) -{ - struct ehca_sma_attr new_attr; - struct ehca_sma_attr *old_attr = &shca->sport[port_num - 1].saved_attr; - - ehca_query_sma_attr(shca, port_num, &new_attr); - - if (new_attr.sm_sl != old_attr->sm_sl || - new_attr.sm_lid != old_attr->sm_lid) - dispatch_port_event(shca, port_num, IB_EVENT_SM_CHANGE, - "SM changed"); - - if (new_attr.lid != old_attr->lid || - new_attr.lmc != old_attr->lmc) - dispatch_port_event(shca, port_num, IB_EVENT_LID_CHANGE, - "LID changed"); - - if (new_attr.pkey_tbl_len != old_attr->pkey_tbl_len || - memcmp(new_attr.pkeys, old_attr->pkeys, - sizeof(u16) * new_attr.pkey_tbl_len)) - dispatch_port_event(shca, port_num, IB_EVENT_PKEY_CHANGE, - "P_Key changed"); - - *old_attr = new_attr; -} - -/* replay modify_qp for sqps -- return 0 if all is well, 1 if AQP1 destroyed */ -static int replay_modify_qp(struct ehca_sport *sport) -{ - int aqp1_destroyed; - unsigned long flags; - - spin_lock_irqsave(&sport->mod_sqp_lock, flags); - - aqp1_destroyed = !sport->ibqp_sqp[IB_QPT_GSI]; - - if (sport->ibqp_sqp[IB_QPT_SMI]) - ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]); - if (!aqp1_destroyed) - ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]); - - spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); - - return aqp1_destroyed; -} - -static void parse_ec(struct ehca_shca *shca, u64 eqe) -{ - u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); - u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); - u8 spec_event; - struct ehca_sport *sport = &shca->sport[port - 1]; - - switch (ec) { - case 0x30: /* port availability change */ - if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { - /* only replay modify_qp calls in autodetect mode; - * if AQP1 was destroyed, the port is already down - * again and we can drop the event. - */ - if (ehca_nr_ports < 0) - if (replay_modify_qp(sport)) - break; - - sport->port_state = IB_PORT_ACTIVE; - dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, - "is active"); - ehca_query_sma_attr(shca, port, &sport->saved_attr); - } else { - sport->port_state = IB_PORT_DOWN; - dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, - "is inactive"); - } - break; - case 0x31: - /* port configuration change - * disruptive change is caused by - * LID, PKEY or SM change - */ - if (EHCA_BMASK_GET(NEQE_DISRUPTIVE, eqe)) { - ehca_warn(&shca->ib_device, "disruptive port " - "%d configuration change", port); - - sport->port_state = IB_PORT_DOWN; - dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, - "is inactive"); - - sport->port_state = IB_PORT_ACTIVE; - dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, - "is active"); - ehca_query_sma_attr(shca, port, - &sport->saved_attr); - } else - notify_port_conf_change(shca, port); - break; - case 0x32: /* adapter malfunction */ - ehca_err(&shca->ib_device, "Adapter malfunction."); - break; - case 0x33: /* trace stopped */ - ehca_err(&shca->ib_device, "Traced stopped."); - break; - case 0x34: /* util async event */ - spec_event = EHCA_BMASK_GET(NEQE_SPECIFIC_EVENT, eqe); - if (spec_event == 0x80) /* client reregister required */ - dispatch_port_event(shca, port, - IB_EVENT_CLIENT_REREGISTER, - "client reregister req."); - else - ehca_warn(&shca->ib_device, "Unknown util async " - "event %x on port %x", spec_event, port); - break; - default: - ehca_err(&shca->ib_device, "Unknown event code: %x on %s.", - ec, shca->ib_device.name); - break; - } - - return; -} - -static inline void reset_eq_pending(struct ehca_cq *cq) -{ - u64 CQx_EP; - struct h_galpa gal = cq->galpas.kernel; - - hipz_galpa_store_cq(gal, cqx_ep, 0x0); - CQx_EP = hipz_galpa_load(gal, CQTEMM_OFFSET(cqx_ep)); - - return; -} - -irqreturn_t ehca_interrupt_neq(int irq, void *dev_id) -{ - struct ehca_shca *shca = (struct ehca_shca*)dev_id; - - tasklet_hi_schedule(&shca->neq.interrupt_task); - - return IRQ_HANDLED; -} - -void ehca_tasklet_neq(unsigned long data) -{ - struct ehca_shca *shca = (struct ehca_shca*)data; - struct ehca_eqe *eqe; - u64 ret; - - eqe = ehca_poll_eq(shca, &shca->neq); - - while (eqe) { - if (!EHCA_BMASK_GET(NEQE_COMPLETION_EVENT, eqe->entry)) - parse_ec(shca, eqe->entry); - - eqe = ehca_poll_eq(shca, &shca->neq); - } - - ret = hipz_h_reset_event(shca->ipz_hca_handle, - shca->neq.ipz_eq_handle, 0xFFFFFFFFFFFFFFFFL); - - if (ret != H_SUCCESS) - ehca_err(&shca->ib_device, "Can't clear notification events."); - - return; -} - -irqreturn_t ehca_interrupt_eq(int irq, void *dev_id) -{ - struct ehca_shca *shca = (struct ehca_shca*)dev_id; - - tasklet_hi_schedule(&shca->eq.interrupt_task); - - return IRQ_HANDLED; -} - - -static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe) -{ - u64 eqe_value; - u32 token; - struct ehca_cq *cq; - - eqe_value = eqe->entry; - ehca_dbg(&shca->ib_device, "eqe_value=%llx", eqe_value); - if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) { - ehca_dbg(&shca->ib_device, "Got completion event"); - token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value); - read_lock(&ehca_cq_idr_lock); - cq = idr_find(&ehca_cq_idr, token); - if (cq) - atomic_inc(&cq->nr_events); - read_unlock(&ehca_cq_idr_lock); - if (cq == NULL) { - ehca_err(&shca->ib_device, - "Invalid eqe for non-existing cq token=%x", - token); - return; - } - reset_eq_pending(cq); - if (ehca_scaling_code) - queue_comp_task(cq); - else { - comp_event_callback(cq); - if (atomic_dec_and_test(&cq->nr_events)) - wake_up(&cq->wait_completion); - } - } else { - ehca_dbg(&shca->ib_device, "Got non completion event"); - parse_identifier(shca, eqe_value); - } -} - -void ehca_process_eq(struct ehca_shca *shca, int is_irq) -{ - struct ehca_eq *eq = &shca->eq; - struct ehca_eqe_cache_entry *eqe_cache = eq->eqe_cache; - u64 eqe_value, ret; - int eqe_cnt, i; - int eq_empty = 0; - - spin_lock(&eq->irq_spinlock); - if (is_irq) { - const int max_query_cnt = 100; - int query_cnt = 0; - int int_state = 1; - do { - int_state = hipz_h_query_int_state( - shca->ipz_hca_handle, eq->ist); - query_cnt++; - iosync(); - } while (int_state && query_cnt < max_query_cnt); - if (unlikely((query_cnt == max_query_cnt))) - ehca_dbg(&shca->ib_device, "int_state=%x query_cnt=%x", - int_state, query_cnt); - } - - /* read out all eqes */ - eqe_cnt = 0; - do { - u32 token; - eqe_cache[eqe_cnt].eqe = ehca_poll_eq(shca, eq); - if (!eqe_cache[eqe_cnt].eqe) - break; - eqe_value = eqe_cache[eqe_cnt].eqe->entry; - if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) { - token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value); - read_lock(&ehca_cq_idr_lock); - eqe_cache[eqe_cnt].cq = idr_find(&ehca_cq_idr, token); - if (eqe_cache[eqe_cnt].cq) - atomic_inc(&eqe_cache[eqe_cnt].cq->nr_events); - read_unlock(&ehca_cq_idr_lock); - if (!eqe_cache[eqe_cnt].cq) { - ehca_err(&shca->ib_device, - "Invalid eqe for non-existing cq " - "token=%x", token); - continue; - } - } else - eqe_cache[eqe_cnt].cq = NULL; - eqe_cnt++; - } while (eqe_cnt < EHCA_EQE_CACHE_SIZE); - if (!eqe_cnt) { - if (is_irq) - ehca_dbg(&shca->ib_device, - "No eqe found for irq event"); - goto unlock_irq_spinlock; - } else if (!is_irq) { - ret = hipz_h_eoi(eq->ist); - if (ret != H_SUCCESS) - ehca_err(&shca->ib_device, - "bad return code EOI -rc = %lld\n", ret); - ehca_dbg(&shca->ib_device, "deadman found %x eqe", eqe_cnt); - } - if (unlikely(eqe_cnt == EHCA_EQE_CACHE_SIZE)) - ehca_dbg(&shca->ib_device, "too many eqes for one irq event"); - /* enable irq for new packets */ - for (i = 0; i < eqe_cnt; i++) { - if (eq->eqe_cache[i].cq) - reset_eq_pending(eq->eqe_cache[i].cq); - } - /* check eq */ - spin_lock(&eq->spinlock); - eq_empty = (!ipz_eqit_eq_peek_valid(&shca->eq.ipz_queue)); - spin_unlock(&eq->spinlock); - /* call completion handler for cached eqes */ - for (i = 0; i < eqe_cnt; i++) - if (eq->eqe_cache[i].cq) { - if (ehca_scaling_code) - queue_comp_task(eq->eqe_cache[i].cq); - else { - struct ehca_cq *cq = eq->eqe_cache[i].cq; - comp_event_callback(cq); - if (atomic_dec_and_test(&cq->nr_events)) - wake_up(&cq->wait_completion); - } - } else { - ehca_dbg(&shca->ib_device, "Got non completion event"); - parse_identifier(shca, eq->eqe_cache[i].eqe->entry); - } - /* poll eq if not empty */ - if (eq_empty) - goto unlock_irq_spinlock; - do { - struct ehca_eqe *eqe; - eqe = ehca_poll_eq(shca, &shca->eq); - if (!eqe) - break; - process_eqe(shca, eqe); - } while (1); - -unlock_irq_spinlock: - spin_unlock(&eq->irq_spinlock); -} - -void ehca_tasklet_eq(unsigned long data) -{ - ehca_process_eq((struct ehca_shca*)data, 1); -} - -static int find_next_online_cpu(struct ehca_comp_pool *pool) -{ - int cpu; - unsigned long flags; - - WARN_ON_ONCE(!in_interrupt()); - if (ehca_debug_level >= 3) - ehca_dmp(cpu_online_mask, cpumask_size(), ""); - - spin_lock_irqsave(&pool->last_cpu_lock, flags); - do { - cpu = cpumask_next(pool->last_cpu, cpu_online_mask); - if (cpu >= nr_cpu_ids) - cpu = cpumask_first(cpu_online_mask); - pool->last_cpu = cpu; - } while (!per_cpu_ptr(pool->cpu_comp_tasks, cpu)->active); - spin_unlock_irqrestore(&pool->last_cpu_lock, flags); - - return cpu; -} - -static void __queue_comp_task(struct ehca_cq *__cq, - struct ehca_cpu_comp_task *cct, - struct task_struct *thread) -{ - unsigned long flags; - - spin_lock_irqsave(&cct->task_lock, flags); - spin_lock(&__cq->task_lock); - - if (__cq->nr_callbacks == 0) { - __cq->nr_callbacks++; - list_add_tail(&__cq->entry, &cct->cq_list); - cct->cq_jobs++; - wake_up_process(thread); - } else - __cq->nr_callbacks++; - - spin_unlock(&__cq->task_lock); - spin_unlock_irqrestore(&cct->task_lock, flags); -} - -static void queue_comp_task(struct ehca_cq *__cq) -{ - int cpu_id; - struct ehca_cpu_comp_task *cct; - struct task_struct *thread; - int cq_jobs; - unsigned long flags; - - cpu_id = find_next_online_cpu(pool); - BUG_ON(!cpu_online(cpu_id)); - - cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id); - thread = *per_cpu_ptr(pool->cpu_comp_threads, cpu_id); - BUG_ON(!cct || !thread); - - spin_lock_irqsave(&cct->task_lock, flags); - cq_jobs = cct->cq_jobs; - spin_unlock_irqrestore(&cct->task_lock, flags); - if (cq_jobs > 0) { - cpu_id = find_next_online_cpu(pool); - cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id); - thread = *per_cpu_ptr(pool->cpu_comp_threads, cpu_id); - BUG_ON(!cct || !thread); - } - __queue_comp_task(__cq, cct, thread); -} - -static void run_comp_task(struct ehca_cpu_comp_task *cct) -{ - struct ehca_cq *cq; - - while (!list_empty(&cct->cq_list)) { - cq = list_entry(cct->cq_list.next, struct ehca_cq, entry); - spin_unlock_irq(&cct->task_lock); - - comp_event_callback(cq); - if (atomic_dec_and_test(&cq->nr_events)) - wake_up(&cq->wait_completion); - - spin_lock_irq(&cct->task_lock); - spin_lock(&cq->task_lock); - cq->nr_callbacks--; - if (!cq->nr_callbacks) { - list_del_init(cct->cq_list.next); - cct->cq_jobs--; - } - spin_unlock(&cq->task_lock); - } -} - -static void comp_task_park(unsigned int cpu) -{ - struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); - struct ehca_cpu_comp_task *target; - struct task_struct *thread; - struct ehca_cq *cq, *tmp; - LIST_HEAD(list); - - spin_lock_irq(&cct->task_lock); - cct->cq_jobs = 0; - cct->active = 0; - list_splice_init(&cct->cq_list, &list); - spin_unlock_irq(&cct->task_lock); - - cpu = find_next_online_cpu(pool); - target = per_cpu_ptr(pool->cpu_comp_tasks, cpu); - thread = *per_cpu_ptr(pool->cpu_comp_threads, cpu); - spin_lock_irq(&target->task_lock); - list_for_each_entry_safe(cq, tmp, &list, entry) { - list_del(&cq->entry); - __queue_comp_task(cq, target, thread); - } - spin_unlock_irq(&target->task_lock); -} - -static void comp_task_stop(unsigned int cpu, bool online) -{ - struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); - - spin_lock_irq(&cct->task_lock); - cct->cq_jobs = 0; - cct->active = 0; - WARN_ON(!list_empty(&cct->cq_list)); - spin_unlock_irq(&cct->task_lock); -} - -static int comp_task_should_run(unsigned int cpu) -{ - struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); - - return cct->cq_jobs; -} - -static void comp_task(unsigned int cpu) -{ - struct ehca_cpu_comp_task *cct = this_cpu_ptr(pool->cpu_comp_tasks); - int cql_empty; - - spin_lock_irq(&cct->task_lock); - cql_empty = list_empty(&cct->cq_list); - if (!cql_empty) { - __set_current_state(TASK_RUNNING); - run_comp_task(cct); - } - spin_unlock_irq(&cct->task_lock); -} - -static struct smp_hotplug_thread comp_pool_threads = { - .thread_should_run = comp_task_should_run, - .thread_fn = comp_task, - .thread_comm = "ehca_comp/%u", - .cleanup = comp_task_stop, - .park = comp_task_park, -}; - -int ehca_create_comp_pool(void) -{ - int cpu, ret = -ENOMEM; - - if (!ehca_scaling_code) - return 0; - - pool = kzalloc(sizeof(struct ehca_comp_pool), GFP_KERNEL); - if (pool == NULL) - return -ENOMEM; - - spin_lock_init(&pool->last_cpu_lock); - pool->last_cpu = cpumask_any(cpu_online_mask); - - pool->cpu_comp_tasks = alloc_percpu(struct ehca_cpu_comp_task); - if (!pool->cpu_comp_tasks) - goto out_pool; - - pool->cpu_comp_threads = alloc_percpu(struct task_struct *); - if (!pool->cpu_comp_threads) - goto out_tasks; - - for_each_present_cpu(cpu) { - struct ehca_cpu_comp_task *cct; - - cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); - spin_lock_init(&cct->task_lock); - INIT_LIST_HEAD(&cct->cq_list); - } - - comp_pool_threads.store = pool->cpu_comp_threads; - ret = smpboot_register_percpu_thread(&comp_pool_threads); - if (ret) - goto out_threads; - - pr_info("eHCA scaling code enabled\n"); - return ret; - -out_threads: - free_percpu(pool->cpu_comp_threads); -out_tasks: - free_percpu(pool->cpu_comp_tasks); -out_pool: - kfree(pool); - return ret; -} - -void ehca_destroy_comp_pool(void) -{ - if (!ehca_scaling_code) - return; - - smpboot_unregister_percpu_thread(&comp_pool_threads); - - free_percpu(pool->cpu_comp_threads); - free_percpu(pool->cpu_comp_tasks); - kfree(pool); -} diff --git a/drivers/staging/rdma/ehca/ehca_irq.h b/drivers/staging/rdma/ehca/ehca_irq.h deleted file mode 100644 index 5370199f08c7..000000000000 --- a/drivers/staging/rdma/ehca/ehca_irq.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Function definitions and structs for EQs, NEQs and interrupts - * - * Authors: Heiko J Schick - * Khadija Souissi - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __EHCA_IRQ_H -#define __EHCA_IRQ_H - - -struct ehca_shca; - -#include -#include - -int ehca_error_data(struct ehca_shca *shca, void *data, u64 resource); - -irqreturn_t ehca_interrupt_neq(int irq, void *dev_id); -void ehca_tasklet_neq(unsigned long data); - -irqreturn_t ehca_interrupt_eq(int irq, void *dev_id); -void ehca_tasklet_eq(unsigned long data); -void ehca_process_eq(struct ehca_shca *shca, int is_irq); - -struct ehca_cpu_comp_task { - struct list_head cq_list; - spinlock_t task_lock; - int cq_jobs; - int active; -}; - -struct ehca_comp_pool { - struct ehca_cpu_comp_task __percpu *cpu_comp_tasks; - struct task_struct * __percpu *cpu_comp_threads; - int last_cpu; - spinlock_t last_cpu_lock; -}; - -int ehca_create_comp_pool(void); -void ehca_destroy_comp_pool(void); - -#endif diff --git a/drivers/staging/rdma/ehca/ehca_iverbs.h b/drivers/staging/rdma/ehca/ehca_iverbs.h deleted file mode 100644 index cca5933fcda6..000000000000 --- a/drivers/staging/rdma/ehca/ehca_iverbs.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Function definitions for internal functions - * - * Authors: Heiko J Schick - * Dietmar Decker - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __EHCA_IVERBS_H__ -#define __EHCA_IVERBS_H__ - -#include "ehca_classes.h" - -int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props, - struct ib_udata *uhw); - -int ehca_query_port(struct ib_device *ibdev, u8 port, - struct ib_port_attr *props); - -enum rdma_protocol_type -ehca_query_protocol(struct ib_device *device, u8 port_num); - -int ehca_query_sma_attr(struct ehca_shca *shca, u8 port, - struct ehca_sma_attr *attr); - -int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 * pkey); - -int ehca_query_gid(struct ib_device *ibdev, u8 port, int index, - union ib_gid *gid); - -int ehca_modify_port(struct ib_device *ibdev, u8 port, int port_modify_mask, - struct ib_port_modify *props); - -struct ib_pd *ehca_alloc_pd(struct ib_device *device, - struct ib_ucontext *context, - struct ib_udata *udata); - -int ehca_dealloc_pd(struct ib_pd *pd); - -struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr); - -int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr); - -int ehca_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr); - -int ehca_destroy_ah(struct ib_ah *ah); - -struct ib_mr *ehca_get_dma_mr(struct ib_pd *pd, int mr_access_flags); - -struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt, int mr_access_flags, - struct ib_udata *udata); - -int ehca_dereg_mr(struct ib_mr *mr); - -struct ib_mw *ehca_alloc_mw(struct ib_pd *pd, enum ib_mw_type type); - -int ehca_dealloc_mw(struct ib_mw *mw); - -struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd, - int mr_access_flags, - struct ib_fmr_attr *fmr_attr); - -int ehca_map_phys_fmr(struct ib_fmr *fmr, - u64 *page_list, int list_len, u64 iova); - -int ehca_unmap_fmr(struct list_head *fmr_list); - -int ehca_dealloc_fmr(struct ib_fmr *fmr); - -enum ehca_eq_type { - EHCA_EQ = 0, /* Event Queue */ - EHCA_NEQ /* Notification Event Queue */ -}; - -int ehca_create_eq(struct ehca_shca *shca, struct ehca_eq *eq, - enum ehca_eq_type type, const u32 length); - -int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq); - -void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq); - - -struct ib_cq *ehca_create_cq(struct ib_device *device, - const struct ib_cq_init_attr *attr, - struct ib_ucontext *context, - struct ib_udata *udata); - -int ehca_destroy_cq(struct ib_cq *cq); - -int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata); - -int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc); - -int ehca_peek_cq(struct ib_cq *cq, int wc_cnt); - -int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags notify_flags); - -struct ib_qp *ehca_create_qp(struct ib_pd *pd, - struct ib_qp_init_attr *init_attr, - struct ib_udata *udata); - -int ehca_destroy_qp(struct ib_qp *qp); - -int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, - struct ib_udata *udata); - -int ehca_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr, - int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr); - -int ehca_post_send(struct ib_qp *qp, struct ib_send_wr *send_wr, - struct ib_send_wr **bad_send_wr); - -int ehca_post_recv(struct ib_qp *qp, struct ib_recv_wr *recv_wr, - struct ib_recv_wr **bad_recv_wr); - -int ehca_post_srq_recv(struct ib_srq *srq, - struct ib_recv_wr *recv_wr, - struct ib_recv_wr **bad_recv_wr); - -struct ib_srq *ehca_create_srq(struct ib_pd *pd, - struct ib_srq_init_attr *init_attr, - struct ib_udata *udata); - -int ehca_modify_srq(struct ib_srq *srq, struct ib_srq_attr *attr, - enum ib_srq_attr_mask attr_mask, struct ib_udata *udata); - -int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr); - -int ehca_destroy_srq(struct ib_srq *srq); - -u64 ehca_define_sqp(struct ehca_shca *shca, struct ehca_qp *ibqp, - struct ib_qp_init_attr *qp_init_attr); - -int ehca_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid); - -int ehca_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid); - -struct ib_ucontext *ehca_alloc_ucontext(struct ib_device *device, - struct ib_udata *udata); - -int ehca_dealloc_ucontext(struct ib_ucontext *context); - -int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); - -int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, - const struct ib_wc *in_wc, const struct ib_grh *in_grh, - const struct ib_mad_hdr *in, size_t in_mad_size, - struct ib_mad_hdr *out, size_t *out_mad_size, - u16 *out_mad_pkey_index); - -void ehca_poll_eqs(unsigned long data); - -int ehca_calc_ipd(struct ehca_shca *shca, int port, - enum ib_rate path_rate, u32 *ipd); - -void ehca_add_to_err_list(struct ehca_qp *qp, int on_sq); - -#ifdef CONFIG_PPC_64K_PAGES -void *ehca_alloc_fw_ctrlblock(gfp_t flags); -void ehca_free_fw_ctrlblock(void *ptr); -#else -#define ehca_alloc_fw_ctrlblock(flags) ((void *)get_zeroed_page(flags)) -#define ehca_free_fw_ctrlblock(ptr) free_page((unsigned long)(ptr)) -#endif - -void ehca_recover_sqp(struct ib_qp *sqp); - -#endif diff --git a/drivers/staging/rdma/ehca/ehca_main.c b/drivers/staging/rdma/ehca/ehca_main.c deleted file mode 100644 index 832f22f40862..000000000000 --- a/drivers/staging/rdma/ehca/ehca_main.c +++ /dev/null @@ -1,1118 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * module start stop, hca detection - * - * Authors: Heiko J Schick - * Hoang-Nam Nguyen - * Joachim Fenkes - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef CONFIG_PPC_64K_PAGES -#include -#endif - -#include -#include -#include -#include "ehca_classes.h" -#include "ehca_iverbs.h" -#include "ehca_mrmw.h" -#include "ehca_tools.h" -#include "hcp_if.h" - -#define HCAD_VERSION "0029" - -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_AUTHOR("Christoph Raisch "); -MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver"); -MODULE_VERSION(HCAD_VERSION); - -static bool ehca_open_aqp1 = 0; -static int ehca_hw_level = 0; -static bool ehca_poll_all_eqs = 1; - -int ehca_debug_level = 0; -int ehca_nr_ports = -1; -bool ehca_use_hp_mr = 0; -int ehca_port_act_time = 30; -int ehca_static_rate = -1; -bool ehca_scaling_code = 0; -int ehca_lock_hcalls = -1; -int ehca_max_cq = -1; -int ehca_max_qp = -1; - -module_param_named(open_aqp1, ehca_open_aqp1, bool, S_IRUGO); -module_param_named(debug_level, ehca_debug_level, int, S_IRUGO); -module_param_named(hw_level, ehca_hw_level, int, S_IRUGO); -module_param_named(nr_ports, ehca_nr_ports, int, S_IRUGO); -module_param_named(use_hp_mr, ehca_use_hp_mr, bool, S_IRUGO); -module_param_named(port_act_time, ehca_port_act_time, int, S_IRUGO); -module_param_named(poll_all_eqs, ehca_poll_all_eqs, bool, S_IRUGO); -module_param_named(static_rate, ehca_static_rate, int, S_IRUGO); -module_param_named(scaling_code, ehca_scaling_code, bool, S_IRUGO); -module_param_named(lock_hcalls, ehca_lock_hcalls, bint, S_IRUGO); -module_param_named(number_of_cqs, ehca_max_cq, int, S_IRUGO); -module_param_named(number_of_qps, ehca_max_qp, int, S_IRUGO); - -MODULE_PARM_DESC(open_aqp1, - "Open AQP1 on startup (default: no)"); -MODULE_PARM_DESC(debug_level, - "Amount of debug output (0: none (default), 1: traces, " - "2: some dumps, 3: lots)"); -MODULE_PARM_DESC(hw_level, - "Hardware level (0: autosensing (default), " - "0x10..0x14: eHCA, 0x20..0x23: eHCA2)"); -MODULE_PARM_DESC(nr_ports, - "number of connected ports (-1: autodetect (default), " - "1: port one only, 2: two ports)"); -MODULE_PARM_DESC(use_hp_mr, - "Use high performance MRs (default: no)"); -MODULE_PARM_DESC(port_act_time, - "Time to wait for port activation (default: 30 sec)"); -MODULE_PARM_DESC(poll_all_eqs, - "Poll all event queues periodically (default: yes)"); -MODULE_PARM_DESC(static_rate, - "Set permanent static rate (default: no static rate)"); -MODULE_PARM_DESC(scaling_code, - "Enable scaling code (default: no)"); -MODULE_PARM_DESC(lock_hcalls, - "Serialize all hCalls made by the driver " - "(default: autodetect)"); -MODULE_PARM_DESC(number_of_cqs, - "Max number of CQs which can be allocated " - "(default: autodetect)"); -MODULE_PARM_DESC(number_of_qps, - "Max number of QPs which can be allocated " - "(default: autodetect)"); - -DEFINE_RWLOCK(ehca_qp_idr_lock); -DEFINE_RWLOCK(ehca_cq_idr_lock); -DEFINE_IDR(ehca_qp_idr); -DEFINE_IDR(ehca_cq_idr); - -static LIST_HEAD(shca_list); /* list of all registered ehcas */ -DEFINE_SPINLOCK(shca_list_lock); - -static struct timer_list poll_eqs_timer; - -#ifdef CONFIG_PPC_64K_PAGES -static struct kmem_cache *ctblk_cache; - -void *ehca_alloc_fw_ctrlblock(gfp_t flags) -{ - void *ret = kmem_cache_zalloc(ctblk_cache, flags); - if (!ret) - ehca_gen_err("Out of memory for ctblk"); - return ret; -} - -void ehca_free_fw_ctrlblock(void *ptr) -{ - if (ptr) - kmem_cache_free(ctblk_cache, ptr); - -} -#endif - -int ehca2ib_return_code(u64 ehca_rc) -{ - switch (ehca_rc) { - case H_SUCCESS: - return 0; - case H_RESOURCE: /* Resource in use */ - case H_BUSY: - return -EBUSY; - case H_NOT_ENOUGH_RESOURCES: /* insufficient resources */ - case H_CONSTRAINED: /* resource constraint */ - case H_NO_MEM: - return -ENOMEM; - default: - return -EINVAL; - } -} - -static int ehca_create_slab_caches(void) -{ - int ret; - - ret = ehca_init_pd_cache(); - if (ret) { - ehca_gen_err("Cannot create PD SLAB cache."); - return ret; - } - - ret = ehca_init_cq_cache(); - if (ret) { - ehca_gen_err("Cannot create CQ SLAB cache."); - goto create_slab_caches2; - } - - ret = ehca_init_qp_cache(); - if (ret) { - ehca_gen_err("Cannot create QP SLAB cache."); - goto create_slab_caches3; - } - - ret = ehca_init_av_cache(); - if (ret) { - ehca_gen_err("Cannot create AV SLAB cache."); - goto create_slab_caches4; - } - - ret = ehca_init_mrmw_cache(); - if (ret) { - ehca_gen_err("Cannot create MR&MW SLAB cache."); - goto create_slab_caches5; - } - - ret = ehca_init_small_qp_cache(); - if (ret) { - ehca_gen_err("Cannot create small queue SLAB cache."); - goto create_slab_caches6; - } - -#ifdef CONFIG_PPC_64K_PAGES - ctblk_cache = kmem_cache_create("ehca_cache_ctblk", - EHCA_PAGESIZE, H_CB_ALIGNMENT, - SLAB_HWCACHE_ALIGN, - NULL); - if (!ctblk_cache) { - ehca_gen_err("Cannot create ctblk SLAB cache."); - ehca_cleanup_small_qp_cache(); - ret = -ENOMEM; - goto create_slab_caches6; - } -#endif - return 0; - -create_slab_caches6: - ehca_cleanup_mrmw_cache(); - -create_slab_caches5: - ehca_cleanup_av_cache(); - -create_slab_caches4: - ehca_cleanup_qp_cache(); - -create_slab_caches3: - ehca_cleanup_cq_cache(); - -create_slab_caches2: - ehca_cleanup_pd_cache(); - - return ret; -} - -static void ehca_destroy_slab_caches(void) -{ - ehca_cleanup_small_qp_cache(); - ehca_cleanup_mrmw_cache(); - ehca_cleanup_av_cache(); - ehca_cleanup_qp_cache(); - ehca_cleanup_cq_cache(); - ehca_cleanup_pd_cache(); -#ifdef CONFIG_PPC_64K_PAGES - kmem_cache_destroy(ctblk_cache); -#endif -} - -#define EHCA_HCAAVER EHCA_BMASK_IBM(32, 39) -#define EHCA_REVID EHCA_BMASK_IBM(40, 63) - -static struct cap_descr { - u64 mask; - char *descr; -} hca_cap_descr[] = { - { HCA_CAP_AH_PORT_NR_CHECK, "HCA_CAP_AH_PORT_NR_CHECK" }, - { HCA_CAP_ATOMIC, "HCA_CAP_ATOMIC" }, - { HCA_CAP_AUTO_PATH_MIG, "HCA_CAP_AUTO_PATH_MIG" }, - { HCA_CAP_BAD_P_KEY_CTR, "HCA_CAP_BAD_P_KEY_CTR" }, - { HCA_CAP_SQD_RTS_PORT_CHANGE, "HCA_CAP_SQD_RTS_PORT_CHANGE" }, - { HCA_CAP_CUR_QP_STATE_MOD, "HCA_CAP_CUR_QP_STATE_MOD" }, - { HCA_CAP_INIT_TYPE, "HCA_CAP_INIT_TYPE" }, - { HCA_CAP_PORT_ACTIVE_EVENT, "HCA_CAP_PORT_ACTIVE_EVENT" }, - { HCA_CAP_Q_KEY_VIOL_CTR, "HCA_CAP_Q_KEY_VIOL_CTR" }, - { HCA_CAP_WQE_RESIZE, "HCA_CAP_WQE_RESIZE" }, - { HCA_CAP_RAW_PACKET_MCAST, "HCA_CAP_RAW_PACKET_MCAST" }, - { HCA_CAP_SHUTDOWN_PORT, "HCA_CAP_SHUTDOWN_PORT" }, - { HCA_CAP_RC_LL_QP, "HCA_CAP_RC_LL_QP" }, - { HCA_CAP_SRQ, "HCA_CAP_SRQ" }, - { HCA_CAP_UD_LL_QP, "HCA_CAP_UD_LL_QP" }, - { HCA_CAP_RESIZE_MR, "HCA_CAP_RESIZE_MR" }, - { HCA_CAP_MINI_QP, "HCA_CAP_MINI_QP" }, - { HCA_CAP_H_ALLOC_RES_SYNC, "HCA_CAP_H_ALLOC_RES_SYNC" }, -}; - -static int ehca_sense_attributes(struct ehca_shca *shca) -{ - int i, ret = 0; - u64 h_ret; - struct hipz_query_hca *rblock; - struct hipz_query_port *port; - const char *loc_code; - - static const u32 pgsize_map[] = { - HCA_CAP_MR_PGSIZE_4K, 0x1000, - HCA_CAP_MR_PGSIZE_64K, 0x10000, - HCA_CAP_MR_PGSIZE_1M, 0x100000, - HCA_CAP_MR_PGSIZE_16M, 0x1000000, - }; - - ehca_gen_dbg("Probing adapter %s...", - shca->ofdev->dev.of_node->full_name); - loc_code = of_get_property(shca->ofdev->dev.of_node, "ibm,loc-code", - NULL); - if (loc_code) - ehca_gen_dbg(" ... location lode=%s", loc_code); - - rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); - if (!rblock) { - ehca_gen_err("Cannot allocate rblock memory."); - return -ENOMEM; - } - - h_ret = hipz_h_query_hca(shca->ipz_hca_handle, rblock); - if (h_ret != H_SUCCESS) { - ehca_gen_err("Cannot query device properties. h_ret=%lli", - h_ret); - ret = -EPERM; - goto sense_attributes1; - } - - if (ehca_nr_ports == 1) - shca->num_ports = 1; - else - shca->num_ports = (u8)rblock->num_ports; - - ehca_gen_dbg(" ... found %x ports", rblock->num_ports); - - if (ehca_hw_level == 0) { - u32 hcaaver; - u32 revid; - - hcaaver = EHCA_BMASK_GET(EHCA_HCAAVER, rblock->hw_ver); - revid = EHCA_BMASK_GET(EHCA_REVID, rblock->hw_ver); - - ehca_gen_dbg(" ... hardware version=%x:%x", hcaaver, revid); - - if (hcaaver == 1) { - if (revid <= 3) - shca->hw_level = 0x10 | (revid + 1); - else - shca->hw_level = 0x14; - } else if (hcaaver == 2) { - if (revid == 0) - shca->hw_level = 0x21; - else if (revid == 0x10) - shca->hw_level = 0x22; - else if (revid == 0x20 || revid == 0x21) - shca->hw_level = 0x23; - } - - if (!shca->hw_level) { - ehca_gen_warn("unknown hardware version" - " - assuming default level"); - shca->hw_level = 0x22; - } - } else - shca->hw_level = ehca_hw_level; - ehca_gen_dbg(" ... hardware level=%x", shca->hw_level); - - shca->hca_cap = rblock->hca_cap_indicators; - ehca_gen_dbg(" ... HCA capabilities:"); - for (i = 0; i < ARRAY_SIZE(hca_cap_descr); i++) - if (EHCA_BMASK_GET(hca_cap_descr[i].mask, shca->hca_cap)) - ehca_gen_dbg(" %s", hca_cap_descr[i].descr); - - /* Autodetect hCall locking -- the "H_ALLOC_RESOURCE synced" flag is - * a firmware property, so it's valid across all adapters - */ - if (ehca_lock_hcalls == -1) - ehca_lock_hcalls = !EHCA_BMASK_GET(HCA_CAP_H_ALLOC_RES_SYNC, - shca->hca_cap); - - /* translate supported MR page sizes; always support 4K */ - shca->hca_cap_mr_pgsize = EHCA_PAGESIZE; - for (i = 0; i < ARRAY_SIZE(pgsize_map); i += 2) - if (rblock->memory_page_size_supported & pgsize_map[i]) - shca->hca_cap_mr_pgsize |= pgsize_map[i + 1]; - - /* Set maximum number of CQs and QPs to calculate EQ size */ - if (shca->max_num_qps == -1) - shca->max_num_qps = min_t(int, rblock->max_qp, - EHCA_MAX_NUM_QUEUES); - else if (shca->max_num_qps < 1 || shca->max_num_qps > rblock->max_qp) { - ehca_gen_warn("The requested number of QPs is out of range " - "(1 - %i) specified by HW. Value is set to %i", - rblock->max_qp, rblock->max_qp); - shca->max_num_qps = rblock->max_qp; - } - - if (shca->max_num_cqs == -1) - shca->max_num_cqs = min_t(int, rblock->max_cq, - EHCA_MAX_NUM_QUEUES); - else if (shca->max_num_cqs < 1 || shca->max_num_cqs > rblock->max_cq) { - ehca_gen_warn("The requested number of CQs is out of range " - "(1 - %i) specified by HW. Value is set to %i", - rblock->max_cq, rblock->max_cq); - } - - /* query max MTU from first port -- it's the same for all ports */ - port = (struct hipz_query_port *)rblock; - h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port); - if (h_ret != H_SUCCESS) { - ehca_gen_err("Cannot query port properties. h_ret=%lli", - h_ret); - ret = -EPERM; - goto sense_attributes1; - } - - shca->max_mtu = port->max_mtu; - -sense_attributes1: - ehca_free_fw_ctrlblock(rblock); - return ret; -} - -static int init_node_guid(struct ehca_shca *shca) -{ - int ret = 0; - struct hipz_query_hca *rblock; - - rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); - if (!rblock) { - ehca_err(&shca->ib_device, "Can't allocate rblock memory."); - return -ENOMEM; - } - - if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { - ehca_err(&shca->ib_device, "Can't query device properties"); - ret = -EINVAL; - goto init_node_guid1; - } - - memcpy(&shca->ib_device.node_guid, &rblock->node_guid, sizeof(u64)); - -init_node_guid1: - ehca_free_fw_ctrlblock(rblock); - return ret; -} - -static int ehca_port_immutable(struct ib_device *ibdev, u8 port_num, - struct ib_port_immutable *immutable) -{ - struct ib_port_attr attr; - int err; - - err = ehca_query_port(ibdev, port_num, &attr); - if (err) - return err; - - immutable->pkey_tbl_len = attr.pkey_tbl_len; - immutable->gid_tbl_len = attr.gid_tbl_len; - immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB; - immutable->max_mad_size = IB_MGMT_MAD_SIZE; - - return 0; -} - -static int ehca_init_device(struct ehca_shca *shca) -{ - int ret; - - ret = init_node_guid(shca); - if (ret) - return ret; - - strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX); - shca->ib_device.owner = THIS_MODULE; - - shca->ib_device.uverbs_abi_ver = 8; - shca->ib_device.uverbs_cmd_mask = - (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | - (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | - (1ull << IB_USER_VERBS_CMD_QUERY_PORT) | - (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | - (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | - (1ull << IB_USER_VERBS_CMD_REG_MR) | - (1ull << IB_USER_VERBS_CMD_DEREG_MR) | - (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | - (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | - (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) | - (1ull << IB_USER_VERBS_CMD_CREATE_QP) | - (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | - (1ull << IB_USER_VERBS_CMD_QUERY_QP) | - (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | - (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) | - (1ull << IB_USER_VERBS_CMD_DETACH_MCAST); - - shca->ib_device.node_type = RDMA_NODE_IB_CA; - shca->ib_device.phys_port_cnt = shca->num_ports; - shca->ib_device.num_comp_vectors = 1; - shca->ib_device.dma_device = &shca->ofdev->dev; - shca->ib_device.query_device = ehca_query_device; - shca->ib_device.query_port = ehca_query_port; - shca->ib_device.query_gid = ehca_query_gid; - shca->ib_device.query_pkey = ehca_query_pkey; - /* shca->in_device.modify_device = ehca_modify_device */ - shca->ib_device.modify_port = ehca_modify_port; - shca->ib_device.alloc_ucontext = ehca_alloc_ucontext; - shca->ib_device.dealloc_ucontext = ehca_dealloc_ucontext; - shca->ib_device.alloc_pd = ehca_alloc_pd; - shca->ib_device.dealloc_pd = ehca_dealloc_pd; - shca->ib_device.create_ah = ehca_create_ah; - /* shca->ib_device.modify_ah = ehca_modify_ah; */ - shca->ib_device.query_ah = ehca_query_ah; - shca->ib_device.destroy_ah = ehca_destroy_ah; - shca->ib_device.create_qp = ehca_create_qp; - shca->ib_device.modify_qp = ehca_modify_qp; - shca->ib_device.query_qp = ehca_query_qp; - shca->ib_device.destroy_qp = ehca_destroy_qp; - shca->ib_device.post_send = ehca_post_send; - shca->ib_device.post_recv = ehca_post_recv; - shca->ib_device.create_cq = ehca_create_cq; - shca->ib_device.destroy_cq = ehca_destroy_cq; - shca->ib_device.resize_cq = ehca_resize_cq; - shca->ib_device.poll_cq = ehca_poll_cq; - /* shca->ib_device.peek_cq = ehca_peek_cq; */ - shca->ib_device.req_notify_cq = ehca_req_notify_cq; - /* shca->ib_device.req_ncomp_notif = ehca_req_ncomp_notif; */ - shca->ib_device.get_dma_mr = ehca_get_dma_mr; - shca->ib_device.reg_user_mr = ehca_reg_user_mr; - shca->ib_device.dereg_mr = ehca_dereg_mr; - shca->ib_device.alloc_mw = ehca_alloc_mw; - shca->ib_device.dealloc_mw = ehca_dealloc_mw; - shca->ib_device.alloc_fmr = ehca_alloc_fmr; - shca->ib_device.map_phys_fmr = ehca_map_phys_fmr; - shca->ib_device.unmap_fmr = ehca_unmap_fmr; - shca->ib_device.dealloc_fmr = ehca_dealloc_fmr; - shca->ib_device.attach_mcast = ehca_attach_mcast; - shca->ib_device.detach_mcast = ehca_detach_mcast; - shca->ib_device.process_mad = ehca_process_mad; - shca->ib_device.mmap = ehca_mmap; - shca->ib_device.dma_ops = &ehca_dma_mapping_ops; - shca->ib_device.get_port_immutable = ehca_port_immutable; - - if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) { - shca->ib_device.uverbs_cmd_mask |= - (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) | - (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) | - (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) | - (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ); - - shca->ib_device.create_srq = ehca_create_srq; - shca->ib_device.modify_srq = ehca_modify_srq; - shca->ib_device.query_srq = ehca_query_srq; - shca->ib_device.destroy_srq = ehca_destroy_srq; - shca->ib_device.post_srq_recv = ehca_post_srq_recv; - } - - return ret; -} - -static int ehca_create_aqp1(struct ehca_shca *shca, u32 port) -{ - struct ehca_sport *sport = &shca->sport[port - 1]; - struct ib_cq *ibcq; - struct ib_qp *ibqp; - struct ib_qp_init_attr qp_init_attr; - struct ib_cq_init_attr cq_attr = {}; - int ret; - - if (sport->ibcq_aqp1) { - ehca_err(&shca->ib_device, "AQP1 CQ is already created."); - return -EPERM; - } - - cq_attr.cqe = 10; - ibcq = ib_create_cq(&shca->ib_device, NULL, NULL, (void *)(-1), - &cq_attr); - if (IS_ERR(ibcq)) { - ehca_err(&shca->ib_device, "Cannot create AQP1 CQ."); - return PTR_ERR(ibcq); - } - sport->ibcq_aqp1 = ibcq; - - if (sport->ibqp_sqp[IB_QPT_GSI]) { - ehca_err(&shca->ib_device, "AQP1 QP is already created."); - ret = -EPERM; - goto create_aqp1; - } - - memset(&qp_init_attr, 0, sizeof(struct ib_qp_init_attr)); - qp_init_attr.send_cq = ibcq; - qp_init_attr.recv_cq = ibcq; - qp_init_attr.sq_sig_type = IB_SIGNAL_ALL_WR; - qp_init_attr.cap.max_send_wr = 100; - qp_init_attr.cap.max_recv_wr = 100; - qp_init_attr.cap.max_send_sge = 2; - qp_init_attr.cap.max_recv_sge = 1; - qp_init_attr.qp_type = IB_QPT_GSI; - qp_init_attr.port_num = port; - qp_init_attr.qp_context = NULL; - qp_init_attr.event_handler = NULL; - qp_init_attr.srq = NULL; - - ibqp = ib_create_qp(&shca->pd->ib_pd, &qp_init_attr); - if (IS_ERR(ibqp)) { - ehca_err(&shca->ib_device, "Cannot create AQP1 QP."); - ret = PTR_ERR(ibqp); - goto create_aqp1; - } - sport->ibqp_sqp[IB_QPT_GSI] = ibqp; - - return 0; - -create_aqp1: - ib_destroy_cq(sport->ibcq_aqp1); - return ret; -} - -static int ehca_destroy_aqp1(struct ehca_sport *sport) -{ - int ret; - - ret = ib_destroy_qp(sport->ibqp_sqp[IB_QPT_GSI]); - if (ret) { - ehca_gen_err("Cannot destroy AQP1 QP. ret=%i", ret); - return ret; - } - - ret = ib_destroy_cq(sport->ibcq_aqp1); - if (ret) - ehca_gen_err("Cannot destroy AQP1 CQ. ret=%i", ret); - - return ret; -} - -static ssize_t ehca_show_debug_level(struct device_driver *ddp, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", ehca_debug_level); -} - -static ssize_t ehca_store_debug_level(struct device_driver *ddp, - const char *buf, size_t count) -{ - int value = (*buf) - '0'; - if (value >= 0 && value <= 9) - ehca_debug_level = value; - return 1; -} - -static DRIVER_ATTR(debug_level, S_IRUSR | S_IWUSR, - ehca_show_debug_level, ehca_store_debug_level); - -static struct attribute *ehca_drv_attrs[] = { - &driver_attr_debug_level.attr, - NULL -}; - -static struct attribute_group ehca_drv_attr_grp = { - .attrs = ehca_drv_attrs -}; - -static const struct attribute_group *ehca_drv_attr_groups[] = { - &ehca_drv_attr_grp, - NULL, -}; - -#define EHCA_RESOURCE_ATTR(name) \ -static ssize_t ehca_show_##name(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct ehca_shca *shca; \ - struct hipz_query_hca *rblock; \ - int data; \ - \ - shca = dev_get_drvdata(dev); \ - \ - rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); \ - if (!rblock) { \ - dev_err(dev, "Can't allocate rblock memory.\n"); \ - return 0; \ - } \ - \ - if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { \ - dev_err(dev, "Can't query device properties\n"); \ - ehca_free_fw_ctrlblock(rblock); \ - return 0; \ - } \ - \ - data = rblock->name; \ - ehca_free_fw_ctrlblock(rblock); \ - \ - if ((strcmp(#name, "num_ports") == 0) && (ehca_nr_ports == 1)) \ - return snprintf(buf, 256, "1\n"); \ - else \ - return snprintf(buf, 256, "%d\n", data); \ - \ -} \ -static DEVICE_ATTR(name, S_IRUGO, ehca_show_##name, NULL); - -EHCA_RESOURCE_ATTR(num_ports); -EHCA_RESOURCE_ATTR(hw_ver); -EHCA_RESOURCE_ATTR(max_eq); -EHCA_RESOURCE_ATTR(cur_eq); -EHCA_RESOURCE_ATTR(max_cq); -EHCA_RESOURCE_ATTR(cur_cq); -EHCA_RESOURCE_ATTR(max_qp); -EHCA_RESOURCE_ATTR(cur_qp); -EHCA_RESOURCE_ATTR(max_mr); -EHCA_RESOURCE_ATTR(cur_mr); -EHCA_RESOURCE_ATTR(max_mw); -EHCA_RESOURCE_ATTR(cur_mw); -EHCA_RESOURCE_ATTR(max_pd); -EHCA_RESOURCE_ATTR(max_ah); - -static ssize_t ehca_show_adapter_handle(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ehca_shca *shca = dev_get_drvdata(dev); - - return sprintf(buf, "%llx\n", shca->ipz_hca_handle.handle); - -} -static DEVICE_ATTR(adapter_handle, S_IRUGO, ehca_show_adapter_handle, NULL); - -static struct attribute *ehca_dev_attrs[] = { - &dev_attr_adapter_handle.attr, - &dev_attr_num_ports.attr, - &dev_attr_hw_ver.attr, - &dev_attr_max_eq.attr, - &dev_attr_cur_eq.attr, - &dev_attr_max_cq.attr, - &dev_attr_cur_cq.attr, - &dev_attr_max_qp.attr, - &dev_attr_cur_qp.attr, - &dev_attr_max_mr.attr, - &dev_attr_cur_mr.attr, - &dev_attr_max_mw.attr, - &dev_attr_cur_mw.attr, - &dev_attr_max_pd.attr, - &dev_attr_max_ah.attr, - NULL -}; - -static struct attribute_group ehca_dev_attr_grp = { - .attrs = ehca_dev_attrs -}; - -static int ehca_probe(struct platform_device *dev) -{ - struct ehca_shca *shca; - const u64 *handle; - struct ib_pd *ibpd; - int ret, i, eq_size; - unsigned long flags; - - handle = of_get_property(dev->dev.of_node, "ibm,hca-handle", NULL); - if (!handle) { - ehca_gen_err("Cannot get eHCA handle for adapter: %s.", - dev->dev.of_node->full_name); - return -ENODEV; - } - - if (!(*handle)) { - ehca_gen_err("Wrong eHCA handle for adapter: %s.", - dev->dev.of_node->full_name); - return -ENODEV; - } - - shca = (struct ehca_shca *)ib_alloc_device(sizeof(*shca)); - if (!shca) { - ehca_gen_err("Cannot allocate shca memory."); - return -ENOMEM; - } - - mutex_init(&shca->modify_mutex); - atomic_set(&shca->num_cqs, 0); - atomic_set(&shca->num_qps, 0); - shca->max_num_qps = ehca_max_qp; - shca->max_num_cqs = ehca_max_cq; - - for (i = 0; i < ARRAY_SIZE(shca->sport); i++) - spin_lock_init(&shca->sport[i].mod_sqp_lock); - - shca->ofdev = dev; - shca->ipz_hca_handle.handle = *handle; - dev_set_drvdata(&dev->dev, shca); - - ret = ehca_sense_attributes(shca); - if (ret < 0) { - ehca_gen_err("Cannot sense eHCA attributes."); - goto probe1; - } - - ret = ehca_init_device(shca); - if (ret) { - ehca_gen_err("Cannot init ehca device struct"); - goto probe1; - } - - eq_size = 2 * shca->max_num_cqs + 4 * shca->max_num_qps; - /* create event queues */ - ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, eq_size); - if (ret) { - ehca_err(&shca->ib_device, "Cannot create EQ."); - goto probe1; - } - - ret = ehca_create_eq(shca, &shca->neq, EHCA_NEQ, 513); - if (ret) { - ehca_err(&shca->ib_device, "Cannot create NEQ."); - goto probe3; - } - - /* create internal protection domain */ - ibpd = ehca_alloc_pd(&shca->ib_device, (void *)(-1), NULL); - if (IS_ERR(ibpd)) { - ehca_err(&shca->ib_device, "Cannot create internal PD."); - ret = PTR_ERR(ibpd); - goto probe4; - } - - shca->pd = container_of(ibpd, struct ehca_pd, ib_pd); - shca->pd->ib_pd.device = &shca->ib_device; - - /* create internal max MR */ - ret = ehca_reg_internal_maxmr(shca, shca->pd, &shca->maxmr); - - if (ret) { - ehca_err(&shca->ib_device, "Cannot create internal MR ret=%i", - ret); - goto probe5; - } - - ret = ib_register_device(&shca->ib_device, NULL); - if (ret) { - ehca_err(&shca->ib_device, - "ib_register_device() failed ret=%i", ret); - goto probe6; - } - - /* create AQP1 for port 1 */ - if (ehca_open_aqp1 == 1) { - shca->sport[0].port_state = IB_PORT_DOWN; - ret = ehca_create_aqp1(shca, 1); - if (ret) { - ehca_err(&shca->ib_device, - "Cannot create AQP1 for port 1."); - goto probe7; - } - } - - /* create AQP1 for port 2 */ - if ((ehca_open_aqp1 == 1) && (shca->num_ports == 2)) { - shca->sport[1].port_state = IB_PORT_DOWN; - ret = ehca_create_aqp1(shca, 2); - if (ret) { - ehca_err(&shca->ib_device, - "Cannot create AQP1 for port 2."); - goto probe8; - } - } - - ret = sysfs_create_group(&dev->dev.kobj, &ehca_dev_attr_grp); - if (ret) /* only complain; we can live without attributes */ - ehca_err(&shca->ib_device, - "Cannot create device attributes ret=%d", ret); - - spin_lock_irqsave(&shca_list_lock, flags); - list_add(&shca->shca_list, &shca_list); - spin_unlock_irqrestore(&shca_list_lock, flags); - - return 0; - -probe8: - ret = ehca_destroy_aqp1(&shca->sport[0]); - if (ret) - ehca_err(&shca->ib_device, - "Cannot destroy AQP1 for port 1. ret=%i", ret); - -probe7: - ib_unregister_device(&shca->ib_device); - -probe6: - ret = ehca_dereg_internal_maxmr(shca); - if (ret) - ehca_err(&shca->ib_device, - "Cannot destroy internal MR. ret=%x", ret); - -probe5: - ret = ehca_dealloc_pd(&shca->pd->ib_pd); - if (ret) - ehca_err(&shca->ib_device, - "Cannot destroy internal PD. ret=%x", ret); - -probe4: - ret = ehca_destroy_eq(shca, &shca->neq); - if (ret) - ehca_err(&shca->ib_device, - "Cannot destroy NEQ. ret=%x", ret); - -probe3: - ret = ehca_destroy_eq(shca, &shca->eq); - if (ret) - ehca_err(&shca->ib_device, - "Cannot destroy EQ. ret=%x", ret); - -probe1: - ib_dealloc_device(&shca->ib_device); - - return -EINVAL; -} - -static int ehca_remove(struct platform_device *dev) -{ - struct ehca_shca *shca = dev_get_drvdata(&dev->dev); - unsigned long flags; - int ret; - - sysfs_remove_group(&dev->dev.kobj, &ehca_dev_attr_grp); - - if (ehca_open_aqp1 == 1) { - int i; - for (i = 0; i < shca->num_ports; i++) { - ret = ehca_destroy_aqp1(&shca->sport[i]); - if (ret) - ehca_err(&shca->ib_device, - "Cannot destroy AQP1 for port %x " - "ret=%i", ret, i); - } - } - - ib_unregister_device(&shca->ib_device); - - ret = ehca_dereg_internal_maxmr(shca); - if (ret) - ehca_err(&shca->ib_device, - "Cannot destroy internal MR. ret=%i", ret); - - ret = ehca_dealloc_pd(&shca->pd->ib_pd); - if (ret) - ehca_err(&shca->ib_device, - "Cannot destroy internal PD. ret=%i", ret); - - ret = ehca_destroy_eq(shca, &shca->eq); - if (ret) - ehca_err(&shca->ib_device, "Cannot destroy EQ. ret=%i", ret); - - ret = ehca_destroy_eq(shca, &shca->neq); - if (ret) - ehca_err(&shca->ib_device, "Canot destroy NEQ. ret=%i", ret); - - ib_dealloc_device(&shca->ib_device); - - spin_lock_irqsave(&shca_list_lock, flags); - list_del(&shca->shca_list); - spin_unlock_irqrestore(&shca_list_lock, flags); - - return ret; -} - -static struct of_device_id ehca_device_table[] = -{ - { - .name = "lhca", - .compatible = "IBM,lhca", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, ehca_device_table); - -static struct platform_driver ehca_driver = { - .probe = ehca_probe, - .remove = ehca_remove, - .driver = { - .name = "ehca", - .owner = THIS_MODULE, - .groups = ehca_drv_attr_groups, - .of_match_table = ehca_device_table, - }, -}; - -void ehca_poll_eqs(unsigned long data) -{ - struct ehca_shca *shca; - - spin_lock(&shca_list_lock); - list_for_each_entry(shca, &shca_list, shca_list) { - if (shca->eq.is_initialized) { - /* call deadman proc only if eq ptr does not change */ - struct ehca_eq *eq = &shca->eq; - int max = 3; - volatile u64 q_ofs, q_ofs2; - unsigned long flags; - spin_lock_irqsave(&eq->spinlock, flags); - q_ofs = eq->ipz_queue.current_q_offset; - spin_unlock_irqrestore(&eq->spinlock, flags); - do { - spin_lock_irqsave(&eq->spinlock, flags); - q_ofs2 = eq->ipz_queue.current_q_offset; - spin_unlock_irqrestore(&eq->spinlock, flags); - max--; - } while (q_ofs == q_ofs2 && max > 0); - if (q_ofs == q_ofs2) - ehca_process_eq(shca, 0); - } - } - mod_timer(&poll_eqs_timer, round_jiffies(jiffies + HZ)); - spin_unlock(&shca_list_lock); -} - -static int ehca_mem_notifier(struct notifier_block *nb, - unsigned long action, void *data) -{ - static unsigned long ehca_dmem_warn_time; - unsigned long flags; - - switch (action) { - case MEM_CANCEL_OFFLINE: - case MEM_CANCEL_ONLINE: - case MEM_ONLINE: - case MEM_OFFLINE: - return NOTIFY_OK; - case MEM_GOING_ONLINE: - case MEM_GOING_OFFLINE: - /* only ok if no hca is attached to the lpar */ - spin_lock_irqsave(&shca_list_lock, flags); - if (list_empty(&shca_list)) { - spin_unlock_irqrestore(&shca_list_lock, flags); - return NOTIFY_OK; - } else { - spin_unlock_irqrestore(&shca_list_lock, flags); - if (printk_timed_ratelimit(&ehca_dmem_warn_time, - 30 * 1000)) - ehca_gen_err("DMEM operations are not allowed" - "in conjunction with eHCA"); - return NOTIFY_BAD; - } - } - return NOTIFY_OK; -} - -static struct notifier_block ehca_mem_nb = { - .notifier_call = ehca_mem_notifier, -}; - -static int __init ehca_module_init(void) -{ - int ret; - - printk(KERN_INFO "eHCA Infiniband Device Driver " - "(Version " HCAD_VERSION ")\n"); - - ret = ehca_create_comp_pool(); - if (ret) { - ehca_gen_err("Cannot create comp pool."); - return ret; - } - - ret = ehca_create_slab_caches(); - if (ret) { - ehca_gen_err("Cannot create SLAB caches"); - ret = -ENOMEM; - goto module_init1; - } - - ret = ehca_create_busmap(); - if (ret) { - ehca_gen_err("Cannot create busmap."); - goto module_init2; - } - - ret = ibmebus_register_driver(&ehca_driver); - if (ret) { - ehca_gen_err("Cannot register eHCA device driver"); - ret = -EINVAL; - goto module_init3; - } - - ret = register_memory_notifier(&ehca_mem_nb); - if (ret) { - ehca_gen_err("Failed registering memory add/remove notifier"); - goto module_init4; - } - - if (ehca_poll_all_eqs != 1) { - ehca_gen_err("WARNING!!!"); - ehca_gen_err("It is possible to lose interrupts."); - } else { - init_timer(&poll_eqs_timer); - poll_eqs_timer.function = ehca_poll_eqs; - poll_eqs_timer.expires = jiffies + HZ; - add_timer(&poll_eqs_timer); - } - - return 0; - -module_init4: - ibmebus_unregister_driver(&ehca_driver); - -module_init3: - ehca_destroy_busmap(); - -module_init2: - ehca_destroy_slab_caches(); - -module_init1: - ehca_destroy_comp_pool(); - return ret; -}; - -static void __exit ehca_module_exit(void) -{ - if (ehca_poll_all_eqs == 1) - del_timer_sync(&poll_eqs_timer); - - ibmebus_unregister_driver(&ehca_driver); - - unregister_memory_notifier(&ehca_mem_nb); - - ehca_destroy_busmap(); - - ehca_destroy_slab_caches(); - - ehca_destroy_comp_pool(); - - idr_destroy(&ehca_cq_idr); - idr_destroy(&ehca_qp_idr); -}; - -module_init(ehca_module_init); -module_exit(ehca_module_exit); diff --git a/drivers/staging/rdma/ehca/ehca_mcast.c b/drivers/staging/rdma/ehca/ehca_mcast.c deleted file mode 100644 index cec181532924..000000000000 --- a/drivers/staging/rdma/ehca/ehca_mcast.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * mcast functions - * - * Authors: Khadija Souissi - * Waleri Fomin - * Reinhard Ernst - * Hoang-Nam Nguyen - * Heiko J Schick - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include "ehca_classes.h" -#include "ehca_tools.h" -#include "ehca_qes.h" -#include "ehca_iverbs.h" -#include "hcp_if.h" - -#define MAX_MC_LID 0xFFFE -#define MIN_MC_LID 0xC000 /* Multicast limits */ -#define EHCA_VALID_MULTICAST_GID(gid) ((gid)[0] == 0xFF) -#define EHCA_VALID_MULTICAST_LID(lid) \ - (((lid) >= MIN_MC_LID) && ((lid) <= MAX_MC_LID)) - -int ehca_attach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) -{ - struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); - struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca, - ib_device); - union ib_gid my_gid; - u64 subnet_prefix, interface_id, h_ret; - - if (ibqp->qp_type != IB_QPT_UD) { - ehca_err(ibqp->device, "invalid qp_type=%x", ibqp->qp_type); - return -EINVAL; - } - - if (!(EHCA_VALID_MULTICAST_GID(gid->raw))) { - ehca_err(ibqp->device, "invalid mulitcast gid"); - return -EINVAL; - } else if ((lid < MIN_MC_LID) || (lid > MAX_MC_LID)) { - ehca_err(ibqp->device, "invalid mulitcast lid=%x", lid); - return -EINVAL; - } - - memcpy(&my_gid, gid->raw, sizeof(union ib_gid)); - - subnet_prefix = be64_to_cpu(my_gid.global.subnet_prefix); - interface_id = be64_to_cpu(my_gid.global.interface_id); - h_ret = hipz_h_attach_mcqp(shca->ipz_hca_handle, - my_qp->ipz_qp_handle, - my_qp->galpas.kernel, - lid, subnet_prefix, interface_id); - if (h_ret != H_SUCCESS) - ehca_err(ibqp->device, - "ehca_qp=%p qp_num=%x hipz_h_attach_mcqp() failed " - "h_ret=%lli", my_qp, ibqp->qp_num, h_ret); - - return ehca2ib_return_code(h_ret); -} - -int ehca_detach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) -{ - struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); - struct ehca_shca *shca = container_of(ibqp->pd->device, - struct ehca_shca, ib_device); - union ib_gid my_gid; - u64 subnet_prefix, interface_id, h_ret; - - if (ibqp->qp_type != IB_QPT_UD) { - ehca_err(ibqp->device, "invalid qp_type %x", ibqp->qp_type); - return -EINVAL; - } - - if (!(EHCA_VALID_MULTICAST_GID(gid->raw))) { - ehca_err(ibqp->device, "invalid mulitcast gid"); - return -EINVAL; - } else if ((lid < MIN_MC_LID) || (lid > MAX_MC_LID)) { - ehca_err(ibqp->device, "invalid mulitcast lid=%x", lid); - return -EINVAL; - } - - memcpy(&my_gid, gid->raw, sizeof(union ib_gid)); - - subnet_prefix = be64_to_cpu(my_gid.global.subnet_prefix); - interface_id = be64_to_cpu(my_gid.global.interface_id); - h_ret = hipz_h_detach_mcqp(shca->ipz_hca_handle, - my_qp->ipz_qp_handle, - my_qp->galpas.kernel, - lid, subnet_prefix, interface_id); - if (h_ret != H_SUCCESS) - ehca_err(ibqp->device, - "ehca_qp=%p qp_num=%x hipz_h_detach_mcqp() failed " - "h_ret=%lli", my_qp, ibqp->qp_num, h_ret); - - return ehca2ib_return_code(h_ret); -} diff --git a/drivers/staging/rdma/ehca/ehca_mrmw.c b/drivers/staging/rdma/ehca/ehca_mrmw.c deleted file mode 100644 index 3367205e3160..000000000000 --- a/drivers/staging/rdma/ehca/ehca_mrmw.c +++ /dev/null @@ -1,2202 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * MR/MW functions - * - * Authors: Dietmar Decker - * Christoph Raisch - * Hoang-Nam Nguyen - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -#include "ehca_iverbs.h" -#include "ehca_mrmw.h" -#include "hcp_if.h" -#include "hipz_hw.h" - -#define NUM_CHUNKS(length, chunk_size) \ - (((length) + (chunk_size - 1)) / (chunk_size)) - -/* max number of rpages (per hcall register_rpages) */ -#define MAX_RPAGES 512 - -/* DMEM toleration management */ -#define EHCA_SECTSHIFT SECTION_SIZE_BITS -#define EHCA_SECTSIZE (1UL << EHCA_SECTSHIFT) -#define EHCA_HUGEPAGESHIFT 34 -#define EHCA_HUGEPAGE_SIZE (1UL << EHCA_HUGEPAGESHIFT) -#define EHCA_HUGEPAGE_PFN_MASK ((EHCA_HUGEPAGE_SIZE - 1) >> PAGE_SHIFT) -#define EHCA_INVAL_ADDR 0xFFFFFFFFFFFFFFFFULL -#define EHCA_DIR_INDEX_SHIFT 13 /* 8k Entries in 64k block */ -#define EHCA_TOP_INDEX_SHIFT (EHCA_DIR_INDEX_SHIFT * 2) -#define EHCA_MAP_ENTRIES (1 << EHCA_DIR_INDEX_SHIFT) -#define EHCA_TOP_MAP_SIZE (0x10000) /* currently fixed map size */ -#define EHCA_DIR_MAP_SIZE (0x10000) -#define EHCA_ENT_MAP_SIZE (0x10000) -#define EHCA_INDEX_MASK (EHCA_MAP_ENTRIES - 1) - -static unsigned long ehca_mr_len; - -/* - * Memory map data structures - */ -struct ehca_dir_bmap { - u64 ent[EHCA_MAP_ENTRIES]; -}; -struct ehca_top_bmap { - struct ehca_dir_bmap *dir[EHCA_MAP_ENTRIES]; -}; -struct ehca_bmap { - struct ehca_top_bmap *top[EHCA_MAP_ENTRIES]; -}; - -static struct ehca_bmap *ehca_bmap; - -static struct kmem_cache *mr_cache; -static struct kmem_cache *mw_cache; - -enum ehca_mr_pgsize { - EHCA_MR_PGSIZE4K = 0x1000L, - EHCA_MR_PGSIZE64K = 0x10000L, - EHCA_MR_PGSIZE1M = 0x100000L, - EHCA_MR_PGSIZE16M = 0x1000000L -}; - -#define EHCA_MR_PGSHIFT4K 12 -#define EHCA_MR_PGSHIFT64K 16 -#define EHCA_MR_PGSHIFT1M 20 -#define EHCA_MR_PGSHIFT16M 24 - -static u64 ehca_map_vaddr(void *caddr); - -static u32 ehca_encode_hwpage_size(u32 pgsize) -{ - int log = ilog2(pgsize); - WARN_ON(log < 12 || log > 24 || log & 3); - return (log - 12) / 4; -} - -static u64 ehca_get_max_hwpage_size(struct ehca_shca *shca) -{ - return rounddown_pow_of_two(shca->hca_cap_mr_pgsize); -} - -static struct ehca_mr *ehca_mr_new(void) -{ - struct ehca_mr *me; - - me = kmem_cache_zalloc(mr_cache, GFP_KERNEL); - if (me) - spin_lock_init(&me->mrlock); - else - ehca_gen_err("alloc failed"); - - return me; -} - -static void ehca_mr_delete(struct ehca_mr *me) -{ - kmem_cache_free(mr_cache, me); -} - -static struct ehca_mw *ehca_mw_new(void) -{ - struct ehca_mw *me; - - me = kmem_cache_zalloc(mw_cache, GFP_KERNEL); - if (me) - spin_lock_init(&me->mwlock); - else - ehca_gen_err("alloc failed"); - - return me; -} - -static void ehca_mw_delete(struct ehca_mw *me) -{ - kmem_cache_free(mw_cache, me); -} - -/*----------------------------------------------------------------------*/ - -struct ib_mr *ehca_get_dma_mr(struct ib_pd *pd, int mr_access_flags) -{ - struct ib_mr *ib_mr; - int ret; - struct ehca_mr *e_maxmr; - struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd); - struct ehca_shca *shca = - container_of(pd->device, struct ehca_shca, ib_device); - - if (shca->maxmr) { - e_maxmr = ehca_mr_new(); - if (!e_maxmr) { - ehca_err(&shca->ib_device, "out of memory"); - ib_mr = ERR_PTR(-ENOMEM); - goto get_dma_mr_exit0; - } - - ret = ehca_reg_maxmr(shca, e_maxmr, - (void *)ehca_map_vaddr((void *)(KERNELBASE + PHYSICAL_START)), - mr_access_flags, e_pd, - &e_maxmr->ib.ib_mr.lkey, - &e_maxmr->ib.ib_mr.rkey); - if (ret) { - ehca_mr_delete(e_maxmr); - ib_mr = ERR_PTR(ret); - goto get_dma_mr_exit0; - } - ib_mr = &e_maxmr->ib.ib_mr; - } else { - ehca_err(&shca->ib_device, "no internal max-MR exist!"); - ib_mr = ERR_PTR(-EINVAL); - goto get_dma_mr_exit0; - } - -get_dma_mr_exit0: - if (IS_ERR(ib_mr)) - ehca_err(&shca->ib_device, "h_ret=%li pd=%p mr_access_flags=%x", - PTR_ERR(ib_mr), pd, mr_access_flags); - return ib_mr; -} /* end ehca_get_dma_mr() */ - -/*----------------------------------------------------------------------*/ - -struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt, int mr_access_flags, - struct ib_udata *udata) -{ - struct ib_mr *ib_mr; - struct ehca_mr *e_mr; - struct ehca_shca *shca = - container_of(pd->device, struct ehca_shca, ib_device); - struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd); - struct ehca_mr_pginfo pginfo; - int ret, page_shift; - u32 num_kpages; - u32 num_hwpages; - u64 hwpage_size; - - if (!pd) { - ehca_gen_err("bad pd=%p", pd); - return ERR_PTR(-EFAULT); - } - - if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) && - !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) || - ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) && - !(mr_access_flags & IB_ACCESS_LOCAL_WRITE))) { - /* - * Remote Write Access requires Local Write Access - * Remote Atomic Access requires Local Write Access - */ - ehca_err(pd->device, "bad input values: mr_access_flags=%x", - mr_access_flags); - ib_mr = ERR_PTR(-EINVAL); - goto reg_user_mr_exit0; - } - - if (length == 0 || virt + length < virt) { - ehca_err(pd->device, "bad input values: length=%llx " - "virt_base=%llx", length, virt); - ib_mr = ERR_PTR(-EINVAL); - goto reg_user_mr_exit0; - } - - e_mr = ehca_mr_new(); - if (!e_mr) { - ehca_err(pd->device, "out of memory"); - ib_mr = ERR_PTR(-ENOMEM); - goto reg_user_mr_exit0; - } - - e_mr->umem = ib_umem_get(pd->uobject->context, start, length, - mr_access_flags, 0); - if (IS_ERR(e_mr->umem)) { - ib_mr = (void *)e_mr->umem; - goto reg_user_mr_exit1; - } - - if (e_mr->umem->page_size != PAGE_SIZE) { - ehca_err(pd->device, "page size not supported, " - "e_mr->umem->page_size=%x", e_mr->umem->page_size); - ib_mr = ERR_PTR(-EINVAL); - goto reg_user_mr_exit2; - } - - /* determine number of MR pages */ - num_kpages = NUM_CHUNKS((virt % PAGE_SIZE) + length, PAGE_SIZE); - /* select proper hw_pgsize */ - page_shift = PAGE_SHIFT; - if (e_mr->umem->hugetlb) { - /* determine page_shift, clamp between 4K and 16M */ - page_shift = (fls64(length - 1) + 3) & ~3; - page_shift = min(max(page_shift, EHCA_MR_PGSHIFT4K), - EHCA_MR_PGSHIFT16M); - } - hwpage_size = 1UL << page_shift; - - /* now that we have the desired page size, shift until it's - * supported, too. 4K is always supported, so this terminates. - */ - while (!(hwpage_size & shca->hca_cap_mr_pgsize)) - hwpage_size >>= 4; - -reg_user_mr_fallback: - num_hwpages = NUM_CHUNKS((virt % hwpage_size) + length, hwpage_size); - /* register MR on HCA */ - memset(&pginfo, 0, sizeof(pginfo)); - pginfo.type = EHCA_MR_PGI_USER; - pginfo.hwpage_size = hwpage_size; - pginfo.num_kpages = num_kpages; - pginfo.num_hwpages = num_hwpages; - pginfo.u.usr.region = e_mr->umem; - pginfo.next_hwpage = ib_umem_offset(e_mr->umem) / hwpage_size; - pginfo.u.usr.next_sg = pginfo.u.usr.region->sg_head.sgl; - ret = ehca_reg_mr(shca, e_mr, (u64 *)virt, length, mr_access_flags, - e_pd, &pginfo, &e_mr->ib.ib_mr.lkey, - &e_mr->ib.ib_mr.rkey, EHCA_REG_MR); - if (ret == -EINVAL && pginfo.hwpage_size > PAGE_SIZE) { - ehca_warn(pd->device, "failed to register mr " - "with hwpage_size=%llx", hwpage_size); - ehca_info(pd->device, "try to register mr with " - "kpage_size=%lx", PAGE_SIZE); - /* - * this means kpages are not contiguous for a hw page - * try kernel page size as fallback solution - */ - hwpage_size = PAGE_SIZE; - goto reg_user_mr_fallback; - } - if (ret) { - ib_mr = ERR_PTR(ret); - goto reg_user_mr_exit2; - } - - /* successful registration of all pages */ - return &e_mr->ib.ib_mr; - -reg_user_mr_exit2: - ib_umem_release(e_mr->umem); -reg_user_mr_exit1: - ehca_mr_delete(e_mr); -reg_user_mr_exit0: - if (IS_ERR(ib_mr)) - ehca_err(pd->device, "rc=%li pd=%p mr_access_flags=%x udata=%p", - PTR_ERR(ib_mr), pd, mr_access_flags, udata); - return ib_mr; -} /* end ehca_reg_user_mr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_dereg_mr(struct ib_mr *mr) -{ - int ret = 0; - u64 h_ret; - struct ehca_shca *shca = - container_of(mr->device, struct ehca_shca, ib_device); - struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr); - - if ((e_mr->flags & EHCA_MR_FLAG_FMR)) { - ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p " - "e_mr->flags=%x", mr, e_mr, e_mr->flags); - ret = -EINVAL; - goto dereg_mr_exit0; - } else if (e_mr == shca->maxmr) { - /* should be impossible, however reject to be sure */ - ehca_err(mr->device, "dereg internal max-MR impossible, mr=%p " - "shca->maxmr=%p mr->lkey=%x", - mr, shca->maxmr, mr->lkey); - ret = -EINVAL; - goto dereg_mr_exit0; - } - - /* TODO: BUSY: MR still has bound window(s) */ - h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr); - if (h_ret != H_SUCCESS) { - ehca_err(mr->device, "hipz_free_mr failed, h_ret=%lli shca=%p " - "e_mr=%p hca_hndl=%llx mr_hndl=%llx mr->lkey=%x", - h_ret, shca, e_mr, shca->ipz_hca_handle.handle, - e_mr->ipz_mr_handle.handle, mr->lkey); - ret = ehca2ib_return_code(h_ret); - goto dereg_mr_exit0; - } - - if (e_mr->umem) - ib_umem_release(e_mr->umem); - - /* successful deregistration */ - ehca_mr_delete(e_mr); - -dereg_mr_exit0: - if (ret) - ehca_err(mr->device, "ret=%i mr=%p", ret, mr); - return ret; -} /* end ehca_dereg_mr() */ - -/*----------------------------------------------------------------------*/ - -struct ib_mw *ehca_alloc_mw(struct ib_pd *pd, enum ib_mw_type type) -{ - struct ib_mw *ib_mw; - u64 h_ret; - struct ehca_mw *e_mw; - struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd); - struct ehca_shca *shca = - container_of(pd->device, struct ehca_shca, ib_device); - struct ehca_mw_hipzout_parms hipzout; - - if (type != IB_MW_TYPE_1) - return ERR_PTR(-EINVAL); - - e_mw = ehca_mw_new(); - if (!e_mw) { - ib_mw = ERR_PTR(-ENOMEM); - goto alloc_mw_exit0; - } - - h_ret = hipz_h_alloc_resource_mw(shca->ipz_hca_handle, e_mw, - e_pd->fw_pd, &hipzout); - if (h_ret != H_SUCCESS) { - ehca_err(pd->device, "hipz_mw_allocate failed, h_ret=%lli " - "shca=%p hca_hndl=%llx mw=%p", - h_ret, shca, shca->ipz_hca_handle.handle, e_mw); - ib_mw = ERR_PTR(ehca2ib_return_code(h_ret)); - goto alloc_mw_exit1; - } - /* successful MW allocation */ - e_mw->ipz_mw_handle = hipzout.handle; - e_mw->ib_mw.rkey = hipzout.rkey; - return &e_mw->ib_mw; - -alloc_mw_exit1: - ehca_mw_delete(e_mw); -alloc_mw_exit0: - if (IS_ERR(ib_mw)) - ehca_err(pd->device, "h_ret=%li pd=%p", PTR_ERR(ib_mw), pd); - return ib_mw; -} /* end ehca_alloc_mw() */ - -/*----------------------------------------------------------------------*/ - -int ehca_dealloc_mw(struct ib_mw *mw) -{ - u64 h_ret; - struct ehca_shca *shca = - container_of(mw->device, struct ehca_shca, ib_device); - struct ehca_mw *e_mw = container_of(mw, struct ehca_mw, ib_mw); - - h_ret = hipz_h_free_resource_mw(shca->ipz_hca_handle, e_mw); - if (h_ret != H_SUCCESS) { - ehca_err(mw->device, "hipz_free_mw failed, h_ret=%lli shca=%p " - "mw=%p rkey=%x hca_hndl=%llx mw_hndl=%llx", - h_ret, shca, mw, mw->rkey, shca->ipz_hca_handle.handle, - e_mw->ipz_mw_handle.handle); - return ehca2ib_return_code(h_ret); - } - /* successful deallocation */ - ehca_mw_delete(e_mw); - return 0; -} /* end ehca_dealloc_mw() */ - -/*----------------------------------------------------------------------*/ - -struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd, - int mr_access_flags, - struct ib_fmr_attr *fmr_attr) -{ - struct ib_fmr *ib_fmr; - struct ehca_shca *shca = - container_of(pd->device, struct ehca_shca, ib_device); - struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd); - struct ehca_mr *e_fmr; - int ret; - u32 tmp_lkey, tmp_rkey; - struct ehca_mr_pginfo pginfo; - u64 hw_pgsize; - - /* check other parameters */ - if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) && - !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) || - ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) && - !(mr_access_flags & IB_ACCESS_LOCAL_WRITE))) { - /* - * Remote Write Access requires Local Write Access - * Remote Atomic Access requires Local Write Access - */ - ehca_err(pd->device, "bad input values: mr_access_flags=%x", - mr_access_flags); - ib_fmr = ERR_PTR(-EINVAL); - goto alloc_fmr_exit0; - } - if (mr_access_flags & IB_ACCESS_MW_BIND) { - ehca_err(pd->device, "bad input values: mr_access_flags=%x", - mr_access_flags); - ib_fmr = ERR_PTR(-EINVAL); - goto alloc_fmr_exit0; - } - if ((fmr_attr->max_pages == 0) || (fmr_attr->max_maps == 0)) { - ehca_err(pd->device, "bad input values: fmr_attr->max_pages=%x " - "fmr_attr->max_maps=%x fmr_attr->page_shift=%x", - fmr_attr->max_pages, fmr_attr->max_maps, - fmr_attr->page_shift); - ib_fmr = ERR_PTR(-EINVAL); - goto alloc_fmr_exit0; - } - - hw_pgsize = 1 << fmr_attr->page_shift; - if (!(hw_pgsize & shca->hca_cap_mr_pgsize)) { - ehca_err(pd->device, "unsupported fmr_attr->page_shift=%x", - fmr_attr->page_shift); - ib_fmr = ERR_PTR(-EINVAL); - goto alloc_fmr_exit0; - } - - e_fmr = ehca_mr_new(); - if (!e_fmr) { - ib_fmr = ERR_PTR(-ENOMEM); - goto alloc_fmr_exit0; - } - e_fmr->flags |= EHCA_MR_FLAG_FMR; - - /* register MR on HCA */ - memset(&pginfo, 0, sizeof(pginfo)); - pginfo.hwpage_size = hw_pgsize; - /* - * pginfo.num_hwpages==0, ie register_rpages() will not be called - * but deferred to map_phys_fmr() - */ - ret = ehca_reg_mr(shca, e_fmr, NULL, - fmr_attr->max_pages * (1 << fmr_attr->page_shift), - mr_access_flags, e_pd, &pginfo, - &tmp_lkey, &tmp_rkey, EHCA_REG_MR); - if (ret) { - ib_fmr = ERR_PTR(ret); - goto alloc_fmr_exit1; - } - - /* successful */ - e_fmr->hwpage_size = hw_pgsize; - e_fmr->fmr_page_size = 1 << fmr_attr->page_shift; - e_fmr->fmr_max_pages = fmr_attr->max_pages; - e_fmr->fmr_max_maps = fmr_attr->max_maps; - e_fmr->fmr_map_cnt = 0; - return &e_fmr->ib.ib_fmr; - -alloc_fmr_exit1: - ehca_mr_delete(e_fmr); -alloc_fmr_exit0: - return ib_fmr; -} /* end ehca_alloc_fmr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_map_phys_fmr(struct ib_fmr *fmr, - u64 *page_list, - int list_len, - u64 iova) -{ - int ret; - struct ehca_shca *shca = - container_of(fmr->device, struct ehca_shca, ib_device); - struct ehca_mr *e_fmr = container_of(fmr, struct ehca_mr, ib.ib_fmr); - struct ehca_pd *e_pd = container_of(fmr->pd, struct ehca_pd, ib_pd); - struct ehca_mr_pginfo pginfo; - u32 tmp_lkey, tmp_rkey; - - if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) { - ehca_err(fmr->device, "not a FMR, e_fmr=%p e_fmr->flags=%x", - e_fmr, e_fmr->flags); - ret = -EINVAL; - goto map_phys_fmr_exit0; - } - ret = ehca_fmr_check_page_list(e_fmr, page_list, list_len); - if (ret) - goto map_phys_fmr_exit0; - if (iova % e_fmr->fmr_page_size) { - /* only whole-numbered pages */ - ehca_err(fmr->device, "bad iova, iova=%llx fmr_page_size=%x", - iova, e_fmr->fmr_page_size); - ret = -EINVAL; - goto map_phys_fmr_exit0; - } - if (e_fmr->fmr_map_cnt >= e_fmr->fmr_max_maps) { - /* HCAD does not limit the maps, however trace this anyway */ - ehca_info(fmr->device, "map limit exceeded, fmr=%p " - "e_fmr->fmr_map_cnt=%x e_fmr->fmr_max_maps=%x", - fmr, e_fmr->fmr_map_cnt, e_fmr->fmr_max_maps); - } - - memset(&pginfo, 0, sizeof(pginfo)); - pginfo.type = EHCA_MR_PGI_FMR; - pginfo.num_kpages = list_len; - pginfo.hwpage_size = e_fmr->hwpage_size; - pginfo.num_hwpages = - list_len * e_fmr->fmr_page_size / pginfo.hwpage_size; - pginfo.u.fmr.page_list = page_list; - pginfo.next_hwpage = - (iova & (e_fmr->fmr_page_size-1)) / pginfo.hwpage_size; - pginfo.u.fmr.fmr_pgsize = e_fmr->fmr_page_size; - - ret = ehca_rereg_mr(shca, e_fmr, (u64 *)iova, - list_len * e_fmr->fmr_page_size, - e_fmr->acl, e_pd, &pginfo, &tmp_lkey, &tmp_rkey); - if (ret) - goto map_phys_fmr_exit0; - - /* successful reregistration */ - e_fmr->fmr_map_cnt++; - e_fmr->ib.ib_fmr.lkey = tmp_lkey; - e_fmr->ib.ib_fmr.rkey = tmp_rkey; - return 0; - -map_phys_fmr_exit0: - if (ret) - ehca_err(fmr->device, "ret=%i fmr=%p page_list=%p list_len=%x " - "iova=%llx", ret, fmr, page_list, list_len, iova); - return ret; -} /* end ehca_map_phys_fmr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_unmap_fmr(struct list_head *fmr_list) -{ - int ret = 0; - struct ib_fmr *ib_fmr; - struct ehca_shca *shca = NULL; - struct ehca_shca *prev_shca; - struct ehca_mr *e_fmr; - u32 num_fmr = 0; - u32 unmap_fmr_cnt = 0; - - /* check all FMR belong to same SHCA, and check internal flag */ - list_for_each_entry(ib_fmr, fmr_list, list) { - prev_shca = shca; - shca = container_of(ib_fmr->device, struct ehca_shca, - ib_device); - e_fmr = container_of(ib_fmr, struct ehca_mr, ib.ib_fmr); - if ((shca != prev_shca) && prev_shca) { - ehca_err(&shca->ib_device, "SHCA mismatch, shca=%p " - "prev_shca=%p e_fmr=%p", - shca, prev_shca, e_fmr); - ret = -EINVAL; - goto unmap_fmr_exit0; - } - if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) { - ehca_err(&shca->ib_device, "not a FMR, e_fmr=%p " - "e_fmr->flags=%x", e_fmr, e_fmr->flags); - ret = -EINVAL; - goto unmap_fmr_exit0; - } - num_fmr++; - } - - /* loop over all FMRs to unmap */ - list_for_each_entry(ib_fmr, fmr_list, list) { - unmap_fmr_cnt++; - e_fmr = container_of(ib_fmr, struct ehca_mr, ib.ib_fmr); - shca = container_of(ib_fmr->device, struct ehca_shca, - ib_device); - ret = ehca_unmap_one_fmr(shca, e_fmr); - if (ret) { - /* unmap failed, stop unmapping of rest of FMRs */ - ehca_err(&shca->ib_device, "unmap of one FMR failed, " - "stop rest, e_fmr=%p num_fmr=%x " - "unmap_fmr_cnt=%x lkey=%x", e_fmr, num_fmr, - unmap_fmr_cnt, e_fmr->ib.ib_fmr.lkey); - goto unmap_fmr_exit0; - } - } - -unmap_fmr_exit0: - if (ret) - ehca_gen_err("ret=%i fmr_list=%p num_fmr=%x unmap_fmr_cnt=%x", - ret, fmr_list, num_fmr, unmap_fmr_cnt); - return ret; -} /* end ehca_unmap_fmr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_dealloc_fmr(struct ib_fmr *fmr) -{ - int ret; - u64 h_ret; - struct ehca_shca *shca = - container_of(fmr->device, struct ehca_shca, ib_device); - struct ehca_mr *e_fmr = container_of(fmr, struct ehca_mr, ib.ib_fmr); - - if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) { - ehca_err(fmr->device, "not a FMR, e_fmr=%p e_fmr->flags=%x", - e_fmr, e_fmr->flags); - ret = -EINVAL; - goto free_fmr_exit0; - } - - h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr); - if (h_ret != H_SUCCESS) { - ehca_err(fmr->device, "hipz_free_mr failed, h_ret=%lli e_fmr=%p " - "hca_hndl=%llx fmr_hndl=%llx fmr->lkey=%x", - h_ret, e_fmr, shca->ipz_hca_handle.handle, - e_fmr->ipz_mr_handle.handle, fmr->lkey); - ret = ehca2ib_return_code(h_ret); - goto free_fmr_exit0; - } - /* successful deregistration */ - ehca_mr_delete(e_fmr); - return 0; - -free_fmr_exit0: - if (ret) - ehca_err(&shca->ib_device, "ret=%i fmr=%p", ret, fmr); - return ret; -} /* end ehca_dealloc_fmr() */ - -/*----------------------------------------------------------------------*/ - -static int ehca_reg_bmap_mr_rpages(struct ehca_shca *shca, - struct ehca_mr *e_mr, - struct ehca_mr_pginfo *pginfo); - -int ehca_reg_mr(struct ehca_shca *shca, - struct ehca_mr *e_mr, - u64 *iova_start, - u64 size, - int acl, - struct ehca_pd *e_pd, - struct ehca_mr_pginfo *pginfo, - u32 *lkey, /*OUT*/ - u32 *rkey, /*OUT*/ - enum ehca_reg_type reg_type) -{ - int ret; - u64 h_ret; - u32 hipz_acl; - struct ehca_mr_hipzout_parms hipzout; - - ehca_mrmw_map_acl(acl, &hipz_acl); - ehca_mrmw_set_pgsize_hipz_acl(pginfo->hwpage_size, &hipz_acl); - if (ehca_use_hp_mr == 1) - hipz_acl |= 0x00000001; - - h_ret = hipz_h_alloc_resource_mr(shca->ipz_hca_handle, e_mr, - (u64)iova_start, size, hipz_acl, - e_pd->fw_pd, &hipzout); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "hipz_alloc_mr failed, h_ret=%lli " - "hca_hndl=%llx", h_ret, shca->ipz_hca_handle.handle); - ret = ehca2ib_return_code(h_ret); - goto ehca_reg_mr_exit0; - } - - e_mr->ipz_mr_handle = hipzout.handle; - - if (reg_type == EHCA_REG_BUSMAP_MR) - ret = ehca_reg_bmap_mr_rpages(shca, e_mr, pginfo); - else if (reg_type == EHCA_REG_MR) - ret = ehca_reg_mr_rpages(shca, e_mr, pginfo); - else - ret = -EINVAL; - - if (ret) - goto ehca_reg_mr_exit1; - - /* successful registration */ - e_mr->num_kpages = pginfo->num_kpages; - e_mr->num_hwpages = pginfo->num_hwpages; - e_mr->hwpage_size = pginfo->hwpage_size; - e_mr->start = iova_start; - e_mr->size = size; - e_mr->acl = acl; - *lkey = hipzout.lkey; - *rkey = hipzout.rkey; - return 0; - -ehca_reg_mr_exit1: - h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "h_ret=%lli shca=%p e_mr=%p " - "iova_start=%p size=%llx acl=%x e_pd=%p lkey=%x " - "pginfo=%p num_kpages=%llx num_hwpages=%llx ret=%i", - h_ret, shca, e_mr, iova_start, size, acl, e_pd, - hipzout.lkey, pginfo, pginfo->num_kpages, - pginfo->num_hwpages, ret); - ehca_err(&shca->ib_device, "internal error in ehca_reg_mr, " - "not recoverable"); - } -ehca_reg_mr_exit0: - if (ret) - ehca_err(&shca->ib_device, "ret=%i shca=%p e_mr=%p " - "iova_start=%p size=%llx acl=%x e_pd=%p pginfo=%p " - "num_kpages=%llx num_hwpages=%llx", - ret, shca, e_mr, iova_start, size, acl, e_pd, pginfo, - pginfo->num_kpages, pginfo->num_hwpages); - return ret; -} /* end ehca_reg_mr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_reg_mr_rpages(struct ehca_shca *shca, - struct ehca_mr *e_mr, - struct ehca_mr_pginfo *pginfo) -{ - int ret = 0; - u64 h_ret; - u32 rnum; - u64 rpage; - u32 i; - u64 *kpage; - - if (!pginfo->num_hwpages) /* in case of fmr */ - return 0; - - kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL); - if (!kpage) { - ehca_err(&shca->ib_device, "kpage alloc failed"); - ret = -ENOMEM; - goto ehca_reg_mr_rpages_exit0; - } - - /* max MAX_RPAGES ehca mr pages per register call */ - for (i = 0; i < NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES); i++) { - - if (i == NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES) - 1) { - rnum = pginfo->num_hwpages % MAX_RPAGES; /* last shot */ - if (rnum == 0) - rnum = MAX_RPAGES; /* last shot is full */ - } else - rnum = MAX_RPAGES; - - ret = ehca_set_pagebuf(pginfo, rnum, kpage); - if (ret) { - ehca_err(&shca->ib_device, "ehca_set_pagebuf " - "bad rc, ret=%i rnum=%x kpage=%p", - ret, rnum, kpage); - goto ehca_reg_mr_rpages_exit1; - } - - if (rnum > 1) { - rpage = __pa(kpage); - if (!rpage) { - ehca_err(&shca->ib_device, "kpage=%p i=%x", - kpage, i); - ret = -EFAULT; - goto ehca_reg_mr_rpages_exit1; - } - } else - rpage = *kpage; - - h_ret = hipz_h_register_rpage_mr( - shca->ipz_hca_handle, e_mr, - ehca_encode_hwpage_size(pginfo->hwpage_size), - 0, rpage, rnum); - - if (i == NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES) - 1) { - /* - * check for 'registration complete'==H_SUCCESS - * and for 'page registered'==H_PAGE_REGISTERED - */ - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "last " - "hipz_reg_rpage_mr failed, h_ret=%lli " - "e_mr=%p i=%x hca_hndl=%llx mr_hndl=%llx" - " lkey=%x", h_ret, e_mr, i, - shca->ipz_hca_handle.handle, - e_mr->ipz_mr_handle.handle, - e_mr->ib.ib_mr.lkey); - ret = ehca2ib_return_code(h_ret); - break; - } else - ret = 0; - } else if (h_ret != H_PAGE_REGISTERED) { - ehca_err(&shca->ib_device, "hipz_reg_rpage_mr failed, " - "h_ret=%lli e_mr=%p i=%x lkey=%x hca_hndl=%llx " - "mr_hndl=%llx", h_ret, e_mr, i, - e_mr->ib.ib_mr.lkey, - shca->ipz_hca_handle.handle, - e_mr->ipz_mr_handle.handle); - ret = ehca2ib_return_code(h_ret); - break; - } else - ret = 0; - } /* end for(i) */ - - -ehca_reg_mr_rpages_exit1: - ehca_free_fw_ctrlblock(kpage); -ehca_reg_mr_rpages_exit0: - if (ret) - ehca_err(&shca->ib_device, "ret=%i shca=%p e_mr=%p pginfo=%p " - "num_kpages=%llx num_hwpages=%llx", ret, shca, e_mr, - pginfo, pginfo->num_kpages, pginfo->num_hwpages); - return ret; -} /* end ehca_reg_mr_rpages() */ - -/*----------------------------------------------------------------------*/ - -inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca, - struct ehca_mr *e_mr, - u64 *iova_start, - u64 size, - u32 acl, - struct ehca_pd *e_pd, - struct ehca_mr_pginfo *pginfo, - u32 *lkey, /*OUT*/ - u32 *rkey) /*OUT*/ -{ - int ret; - u64 h_ret; - u32 hipz_acl; - u64 *kpage; - u64 rpage; - struct ehca_mr_pginfo pginfo_save; - struct ehca_mr_hipzout_parms hipzout; - - ehca_mrmw_map_acl(acl, &hipz_acl); - ehca_mrmw_set_pgsize_hipz_acl(pginfo->hwpage_size, &hipz_acl); - - kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL); - if (!kpage) { - ehca_err(&shca->ib_device, "kpage alloc failed"); - ret = -ENOMEM; - goto ehca_rereg_mr_rereg1_exit0; - } - - pginfo_save = *pginfo; - ret = ehca_set_pagebuf(pginfo, pginfo->num_hwpages, kpage); - if (ret) { - ehca_err(&shca->ib_device, "set pagebuf failed, e_mr=%p " - "pginfo=%p type=%x num_kpages=%llx num_hwpages=%llx " - "kpage=%p", e_mr, pginfo, pginfo->type, - pginfo->num_kpages, pginfo->num_hwpages, kpage); - goto ehca_rereg_mr_rereg1_exit1; - } - rpage = __pa(kpage); - if (!rpage) { - ehca_err(&shca->ib_device, "kpage=%p", kpage); - ret = -EFAULT; - goto ehca_rereg_mr_rereg1_exit1; - } - h_ret = hipz_h_reregister_pmr(shca->ipz_hca_handle, e_mr, - (u64)iova_start, size, hipz_acl, - e_pd->fw_pd, rpage, &hipzout); - if (h_ret != H_SUCCESS) { - /* - * reregistration unsuccessful, try it again with the 3 hCalls, - * e.g. this is required in case H_MR_CONDITION - * (MW bound or MR is shared) - */ - ehca_warn(&shca->ib_device, "hipz_h_reregister_pmr failed " - "(Rereg1), h_ret=%lli e_mr=%p", h_ret, e_mr); - *pginfo = pginfo_save; - ret = -EAGAIN; - } else if ((u64 *)hipzout.vaddr != iova_start) { - ehca_err(&shca->ib_device, "PHYP changed iova_start in " - "rereg_pmr, iova_start=%p iova_start_out=%llx e_mr=%p " - "mr_handle=%llx lkey=%x lkey_out=%x", iova_start, - hipzout.vaddr, e_mr, e_mr->ipz_mr_handle.handle, - e_mr->ib.ib_mr.lkey, hipzout.lkey); - ret = -EFAULT; - } else { - /* - * successful reregistration - * note: start and start_out are identical for eServer HCAs - */ - e_mr->num_kpages = pginfo->num_kpages; - e_mr->num_hwpages = pginfo->num_hwpages; - e_mr->hwpage_size = pginfo->hwpage_size; - e_mr->start = iova_start; - e_mr->size = size; - e_mr->acl = acl; - *lkey = hipzout.lkey; - *rkey = hipzout.rkey; - } - -ehca_rereg_mr_rereg1_exit1: - ehca_free_fw_ctrlblock(kpage); -ehca_rereg_mr_rereg1_exit0: - if ( ret && (ret != -EAGAIN) ) - ehca_err(&shca->ib_device, "ret=%i lkey=%x rkey=%x " - "pginfo=%p num_kpages=%llx num_hwpages=%llx", - ret, *lkey, *rkey, pginfo, pginfo->num_kpages, - pginfo->num_hwpages); - return ret; -} /* end ehca_rereg_mr_rereg1() */ - -/*----------------------------------------------------------------------*/ - -int ehca_rereg_mr(struct ehca_shca *shca, - struct ehca_mr *e_mr, - u64 *iova_start, - u64 size, - int acl, - struct ehca_pd *e_pd, - struct ehca_mr_pginfo *pginfo, - u32 *lkey, - u32 *rkey) -{ - int ret = 0; - u64 h_ret; - int rereg_1_hcall = 1; /* 1: use hipz_h_reregister_pmr directly */ - int rereg_3_hcall = 0; /* 1: use 3 hipz calls for reregistration */ - - /* first determine reregistration hCall(s) */ - if ((pginfo->num_hwpages > MAX_RPAGES) || - (e_mr->num_hwpages > MAX_RPAGES) || - (pginfo->num_hwpages > e_mr->num_hwpages)) { - ehca_dbg(&shca->ib_device, "Rereg3 case, " - "pginfo->num_hwpages=%llx e_mr->num_hwpages=%x", - pginfo->num_hwpages, e_mr->num_hwpages); - rereg_1_hcall = 0; - rereg_3_hcall = 1; - } - - if (e_mr->flags & EHCA_MR_FLAG_MAXMR) { /* check for max-MR */ - rereg_1_hcall = 0; - rereg_3_hcall = 1; - e_mr->flags &= ~EHCA_MR_FLAG_MAXMR; - ehca_err(&shca->ib_device, "Rereg MR for max-MR! e_mr=%p", - e_mr); - } - - if (rereg_1_hcall) { - ret = ehca_rereg_mr_rereg1(shca, e_mr, iova_start, size, - acl, e_pd, pginfo, lkey, rkey); - if (ret) { - if (ret == -EAGAIN) - rereg_3_hcall = 1; - else - goto ehca_rereg_mr_exit0; - } - } - - if (rereg_3_hcall) { - struct ehca_mr save_mr; - - /* first deregister old MR */ - h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "hipz_free_mr failed, " - "h_ret=%lli e_mr=%p hca_hndl=%llx mr_hndl=%llx " - "mr->lkey=%x", - h_ret, e_mr, shca->ipz_hca_handle.handle, - e_mr->ipz_mr_handle.handle, - e_mr->ib.ib_mr.lkey); - ret = ehca2ib_return_code(h_ret); - goto ehca_rereg_mr_exit0; - } - /* clean ehca_mr_t, without changing struct ib_mr and lock */ - save_mr = *e_mr; - ehca_mr_deletenew(e_mr); - - /* set some MR values */ - e_mr->flags = save_mr.flags; - e_mr->hwpage_size = save_mr.hwpage_size; - e_mr->fmr_page_size = save_mr.fmr_page_size; - e_mr->fmr_max_pages = save_mr.fmr_max_pages; - e_mr->fmr_max_maps = save_mr.fmr_max_maps; - e_mr->fmr_map_cnt = save_mr.fmr_map_cnt; - - ret = ehca_reg_mr(shca, e_mr, iova_start, size, acl, - e_pd, pginfo, lkey, rkey, EHCA_REG_MR); - if (ret) { - u32 offset = (u64)(&e_mr->flags) - (u64)e_mr; - memcpy(&e_mr->flags, &(save_mr.flags), - sizeof(struct ehca_mr) - offset); - goto ehca_rereg_mr_exit0; - } - } - -ehca_rereg_mr_exit0: - if (ret) - ehca_err(&shca->ib_device, "ret=%i shca=%p e_mr=%p " - "iova_start=%p size=%llx acl=%x e_pd=%p pginfo=%p " - "num_kpages=%llx lkey=%x rkey=%x rereg_1_hcall=%x " - "rereg_3_hcall=%x", ret, shca, e_mr, iova_start, size, - acl, e_pd, pginfo, pginfo->num_kpages, *lkey, *rkey, - rereg_1_hcall, rereg_3_hcall); - return ret; -} /* end ehca_rereg_mr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_unmap_one_fmr(struct ehca_shca *shca, - struct ehca_mr *e_fmr) -{ - int ret = 0; - u64 h_ret; - struct ehca_pd *e_pd = - container_of(e_fmr->ib.ib_fmr.pd, struct ehca_pd, ib_pd); - struct ehca_mr save_fmr; - u32 tmp_lkey, tmp_rkey; - struct ehca_mr_pginfo pginfo; - struct ehca_mr_hipzout_parms hipzout; - struct ehca_mr save_mr; - - if (e_fmr->fmr_max_pages <= MAX_RPAGES) { - /* - * note: after using rereg hcall with len=0, - * rereg hcall must be used again for registering pages - */ - h_ret = hipz_h_reregister_pmr(shca->ipz_hca_handle, e_fmr, 0, - 0, 0, e_pd->fw_pd, 0, &hipzout); - if (h_ret == H_SUCCESS) { - /* successful reregistration */ - e_fmr->start = NULL; - e_fmr->size = 0; - tmp_lkey = hipzout.lkey; - tmp_rkey = hipzout.rkey; - return 0; - } - /* - * should not happen, because length checked above, - * FMRs are not shared and no MW bound to FMRs - */ - ehca_err(&shca->ib_device, "hipz_reregister_pmr failed " - "(Rereg1), h_ret=%lli e_fmr=%p hca_hndl=%llx " - "mr_hndl=%llx lkey=%x lkey_out=%x", - h_ret, e_fmr, shca->ipz_hca_handle.handle, - e_fmr->ipz_mr_handle.handle, - e_fmr->ib.ib_fmr.lkey, hipzout.lkey); - /* try free and rereg */ - } - - /* first free old FMR */ - h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "hipz_free_mr failed, " - "h_ret=%lli e_fmr=%p hca_hndl=%llx mr_hndl=%llx " - "lkey=%x", - h_ret, e_fmr, shca->ipz_hca_handle.handle, - e_fmr->ipz_mr_handle.handle, - e_fmr->ib.ib_fmr.lkey); - ret = ehca2ib_return_code(h_ret); - goto ehca_unmap_one_fmr_exit0; - } - /* clean ehca_mr_t, without changing lock */ - save_fmr = *e_fmr; - ehca_mr_deletenew(e_fmr); - - /* set some MR values */ - e_fmr->flags = save_fmr.flags; - e_fmr->hwpage_size = save_fmr.hwpage_size; - e_fmr->fmr_page_size = save_fmr.fmr_page_size; - e_fmr->fmr_max_pages = save_fmr.fmr_max_pages; - e_fmr->fmr_max_maps = save_fmr.fmr_max_maps; - e_fmr->fmr_map_cnt = save_fmr.fmr_map_cnt; - e_fmr->acl = save_fmr.acl; - - memset(&pginfo, 0, sizeof(pginfo)); - pginfo.type = EHCA_MR_PGI_FMR; - ret = ehca_reg_mr(shca, e_fmr, NULL, - (e_fmr->fmr_max_pages * e_fmr->fmr_page_size), - e_fmr->acl, e_pd, &pginfo, &tmp_lkey, - &tmp_rkey, EHCA_REG_MR); - if (ret) { - u32 offset = (u64)(&e_fmr->flags) - (u64)e_fmr; - memcpy(&e_fmr->flags, &(save_mr.flags), - sizeof(struct ehca_mr) - offset); - } - -ehca_unmap_one_fmr_exit0: - if (ret) - ehca_err(&shca->ib_device, "ret=%i tmp_lkey=%x tmp_rkey=%x " - "fmr_max_pages=%x", - ret, tmp_lkey, tmp_rkey, e_fmr->fmr_max_pages); - return ret; -} /* end ehca_unmap_one_fmr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_reg_smr(struct ehca_shca *shca, - struct ehca_mr *e_origmr, - struct ehca_mr *e_newmr, - u64 *iova_start, - int acl, - struct ehca_pd *e_pd, - u32 *lkey, /*OUT*/ - u32 *rkey) /*OUT*/ -{ - int ret = 0; - u64 h_ret; - u32 hipz_acl; - struct ehca_mr_hipzout_parms hipzout; - - ehca_mrmw_map_acl(acl, &hipz_acl); - ehca_mrmw_set_pgsize_hipz_acl(e_origmr->hwpage_size, &hipz_acl); - - h_ret = hipz_h_register_smr(shca->ipz_hca_handle, e_newmr, e_origmr, - (u64)iova_start, hipz_acl, e_pd->fw_pd, - &hipzout); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "hipz_reg_smr failed, h_ret=%lli " - "shca=%p e_origmr=%p e_newmr=%p iova_start=%p acl=%x " - "e_pd=%p hca_hndl=%llx mr_hndl=%llx lkey=%x", - h_ret, shca, e_origmr, e_newmr, iova_start, acl, e_pd, - shca->ipz_hca_handle.handle, - e_origmr->ipz_mr_handle.handle, - e_origmr->ib.ib_mr.lkey); - ret = ehca2ib_return_code(h_ret); - goto ehca_reg_smr_exit0; - } - /* successful registration */ - e_newmr->num_kpages = e_origmr->num_kpages; - e_newmr->num_hwpages = e_origmr->num_hwpages; - e_newmr->hwpage_size = e_origmr->hwpage_size; - e_newmr->start = iova_start; - e_newmr->size = e_origmr->size; - e_newmr->acl = acl; - e_newmr->ipz_mr_handle = hipzout.handle; - *lkey = hipzout.lkey; - *rkey = hipzout.rkey; - return 0; - -ehca_reg_smr_exit0: - if (ret) - ehca_err(&shca->ib_device, "ret=%i shca=%p e_origmr=%p " - "e_newmr=%p iova_start=%p acl=%x e_pd=%p", - ret, shca, e_origmr, e_newmr, iova_start, acl, e_pd); - return ret; -} /* end ehca_reg_smr() */ - -/*----------------------------------------------------------------------*/ -static inline void *ehca_calc_sectbase(int top, int dir, int idx) -{ - unsigned long ret = idx; - ret |= dir << EHCA_DIR_INDEX_SHIFT; - ret |= top << EHCA_TOP_INDEX_SHIFT; - return __va(ret << SECTION_SIZE_BITS); -} - -#define ehca_bmap_valid(entry) \ - ((u64)entry != (u64)EHCA_INVAL_ADDR) - -static u64 ehca_reg_mr_section(int top, int dir, int idx, u64 *kpage, - struct ehca_shca *shca, struct ehca_mr *mr, - struct ehca_mr_pginfo *pginfo) -{ - u64 h_ret = 0; - unsigned long page = 0; - u64 rpage = __pa(kpage); - int page_count; - - void *sectbase = ehca_calc_sectbase(top, dir, idx); - if ((unsigned long)sectbase & (pginfo->hwpage_size - 1)) { - ehca_err(&shca->ib_device, "reg_mr_section will probably fail:" - "hwpage_size does not fit to " - "section start address"); - } - page_count = EHCA_SECTSIZE / pginfo->hwpage_size; - - while (page < page_count) { - u64 rnum; - for (rnum = 0; (rnum < MAX_RPAGES) && (page < page_count); - rnum++) { - void *pg = sectbase + ((page++) * pginfo->hwpage_size); - kpage[rnum] = __pa(pg); - } - - h_ret = hipz_h_register_rpage_mr(shca->ipz_hca_handle, mr, - ehca_encode_hwpage_size(pginfo->hwpage_size), - 0, rpage, rnum); - - if ((h_ret != H_SUCCESS) && (h_ret != H_PAGE_REGISTERED)) { - ehca_err(&shca->ib_device, "register_rpage_mr failed"); - return h_ret; - } - } - return h_ret; -} - -static u64 ehca_reg_mr_sections(int top, int dir, u64 *kpage, - struct ehca_shca *shca, struct ehca_mr *mr, - struct ehca_mr_pginfo *pginfo) -{ - u64 hret = H_SUCCESS; - int idx; - - for (idx = 0; idx < EHCA_MAP_ENTRIES; idx++) { - if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]->ent[idx])) - continue; - - hret = ehca_reg_mr_section(top, dir, idx, kpage, shca, mr, - pginfo); - if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED)) - return hret; - } - return hret; -} - -static u64 ehca_reg_mr_dir_sections(int top, u64 *kpage, struct ehca_shca *shca, - struct ehca_mr *mr, - struct ehca_mr_pginfo *pginfo) -{ - u64 hret = H_SUCCESS; - int dir; - - for (dir = 0; dir < EHCA_MAP_ENTRIES; dir++) { - if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir])) - continue; - - hret = ehca_reg_mr_sections(top, dir, kpage, shca, mr, pginfo); - if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED)) - return hret; - } - return hret; -} - -/* register internal max-MR to internal SHCA */ -int ehca_reg_internal_maxmr( - struct ehca_shca *shca, - struct ehca_pd *e_pd, - struct ehca_mr **e_maxmr) /*OUT*/ -{ - int ret; - struct ehca_mr *e_mr; - u64 *iova_start; - u64 size_maxmr; - struct ehca_mr_pginfo pginfo; - u32 num_kpages; - u32 num_hwpages; - u64 hw_pgsize; - - if (!ehca_bmap) { - ret = -EFAULT; - goto ehca_reg_internal_maxmr_exit0; - } - - e_mr = ehca_mr_new(); - if (!e_mr) { - ehca_err(&shca->ib_device, "out of memory"); - ret = -ENOMEM; - goto ehca_reg_internal_maxmr_exit0; - } - e_mr->flags |= EHCA_MR_FLAG_MAXMR; - - /* register internal max-MR on HCA */ - size_maxmr = ehca_mr_len; - iova_start = (u64 *)ehca_map_vaddr((void *)(KERNELBASE + PHYSICAL_START)); - num_kpages = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size_maxmr, - PAGE_SIZE); - hw_pgsize = ehca_get_max_hwpage_size(shca); - num_hwpages = NUM_CHUNKS(((u64)iova_start % hw_pgsize) + size_maxmr, - hw_pgsize); - - memset(&pginfo, 0, sizeof(pginfo)); - pginfo.type = EHCA_MR_PGI_PHYS; - pginfo.num_kpages = num_kpages; - pginfo.num_hwpages = num_hwpages; - pginfo.hwpage_size = hw_pgsize; - pginfo.u.phy.addr = 0; - pginfo.u.phy.size = size_maxmr; - - ret = ehca_reg_mr(shca, e_mr, iova_start, size_maxmr, 0, e_pd, - &pginfo, &e_mr->ib.ib_mr.lkey, - &e_mr->ib.ib_mr.rkey, EHCA_REG_BUSMAP_MR); - if (ret) { - ehca_err(&shca->ib_device, "reg of internal max MR failed, " - "e_mr=%p iova_start=%p size_maxmr=%llx num_kpages=%x " - "num_hwpages=%x", e_mr, iova_start, size_maxmr, - num_kpages, num_hwpages); - goto ehca_reg_internal_maxmr_exit1; - } - - /* successful registration of all pages */ - e_mr->ib.ib_mr.device = e_pd->ib_pd.device; - e_mr->ib.ib_mr.pd = &e_pd->ib_pd; - e_mr->ib.ib_mr.uobject = NULL; - atomic_inc(&(e_pd->ib_pd.usecnt)); - *e_maxmr = e_mr; - return 0; - -ehca_reg_internal_maxmr_exit1: - ehca_mr_delete(e_mr); -ehca_reg_internal_maxmr_exit0: - if (ret) - ehca_err(&shca->ib_device, "ret=%i shca=%p e_pd=%p e_maxmr=%p", - ret, shca, e_pd, e_maxmr); - return ret; -} /* end ehca_reg_internal_maxmr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_reg_maxmr(struct ehca_shca *shca, - struct ehca_mr *e_newmr, - u64 *iova_start, - int acl, - struct ehca_pd *e_pd, - u32 *lkey, - u32 *rkey) -{ - u64 h_ret; - struct ehca_mr *e_origmr = shca->maxmr; - u32 hipz_acl; - struct ehca_mr_hipzout_parms hipzout; - - ehca_mrmw_map_acl(acl, &hipz_acl); - ehca_mrmw_set_pgsize_hipz_acl(e_origmr->hwpage_size, &hipz_acl); - - h_ret = hipz_h_register_smr(shca->ipz_hca_handle, e_newmr, e_origmr, - (u64)iova_start, hipz_acl, e_pd->fw_pd, - &hipzout); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "hipz_reg_smr failed, h_ret=%lli " - "e_origmr=%p hca_hndl=%llx mr_hndl=%llx lkey=%x", - h_ret, e_origmr, shca->ipz_hca_handle.handle, - e_origmr->ipz_mr_handle.handle, - e_origmr->ib.ib_mr.lkey); - return ehca2ib_return_code(h_ret); - } - /* successful registration */ - e_newmr->num_kpages = e_origmr->num_kpages; - e_newmr->num_hwpages = e_origmr->num_hwpages; - e_newmr->hwpage_size = e_origmr->hwpage_size; - e_newmr->start = iova_start; - e_newmr->size = e_origmr->size; - e_newmr->acl = acl; - e_newmr->ipz_mr_handle = hipzout.handle; - *lkey = hipzout.lkey; - *rkey = hipzout.rkey; - return 0; -} /* end ehca_reg_maxmr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_dereg_internal_maxmr(struct ehca_shca *shca) -{ - int ret; - struct ehca_mr *e_maxmr; - struct ib_pd *ib_pd; - - if (!shca->maxmr) { - ehca_err(&shca->ib_device, "bad call, shca=%p", shca); - ret = -EINVAL; - goto ehca_dereg_internal_maxmr_exit0; - } - - e_maxmr = shca->maxmr; - ib_pd = e_maxmr->ib.ib_mr.pd; - shca->maxmr = NULL; /* remove internal max-MR indication from SHCA */ - - ret = ehca_dereg_mr(&e_maxmr->ib.ib_mr); - if (ret) { - ehca_err(&shca->ib_device, "dereg internal max-MR failed, " - "ret=%i e_maxmr=%p shca=%p lkey=%x", - ret, e_maxmr, shca, e_maxmr->ib.ib_mr.lkey); - shca->maxmr = e_maxmr; - goto ehca_dereg_internal_maxmr_exit0; - } - - atomic_dec(&ib_pd->usecnt); - -ehca_dereg_internal_maxmr_exit0: - if (ret) - ehca_err(&shca->ib_device, "ret=%i shca=%p shca->maxmr=%p", - ret, shca, shca->maxmr); - return ret; -} /* end ehca_dereg_internal_maxmr() */ - -/*----------------------------------------------------------------------*/ - -/* check page list of map FMR verb for validness */ -int ehca_fmr_check_page_list(struct ehca_mr *e_fmr, - u64 *page_list, - int list_len) -{ - u32 i; - u64 *page; - - if ((list_len == 0) || (list_len > e_fmr->fmr_max_pages)) { - ehca_gen_err("bad list_len, list_len=%x " - "e_fmr->fmr_max_pages=%x fmr=%p", - list_len, e_fmr->fmr_max_pages, e_fmr); - return -EINVAL; - } - - /* each page must be aligned */ - page = page_list; - for (i = 0; i < list_len; i++) { - if (*page % e_fmr->fmr_page_size) { - ehca_gen_err("bad page, i=%x *page=%llx page=%p fmr=%p " - "fmr_page_size=%x", i, *page, page, e_fmr, - e_fmr->fmr_page_size); - return -EINVAL; - } - page++; - } - - return 0; -} /* end ehca_fmr_check_page_list() */ - -/*----------------------------------------------------------------------*/ - -/* PAGE_SIZE >= pginfo->hwpage_size */ -static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo, - u32 number, - u64 *kpage) -{ - int ret = 0; - u64 pgaddr; - u32 j = 0; - int hwpages_per_kpage = PAGE_SIZE / pginfo->hwpage_size; - struct scatterlist **sg = &pginfo->u.usr.next_sg; - - while (*sg != NULL) { - pgaddr = page_to_pfn(sg_page(*sg)) - << PAGE_SHIFT; - *kpage = pgaddr + (pginfo->next_hwpage * - pginfo->hwpage_size); - if (!(*kpage)) { - ehca_gen_err("pgaddr=%llx " - "sg_dma_address=%llx " - "entry=%llx next_hwpage=%llx", - pgaddr, (u64)sg_dma_address(*sg), - pginfo->u.usr.next_nmap, - pginfo->next_hwpage); - return -EFAULT; - } - (pginfo->hwpage_cnt)++; - (pginfo->next_hwpage)++; - kpage++; - if (pginfo->next_hwpage % hwpages_per_kpage == 0) { - (pginfo->kpage_cnt)++; - (pginfo->u.usr.next_nmap)++; - pginfo->next_hwpage = 0; - *sg = sg_next(*sg); - } - j++; - if (j >= number) - break; - } - - return ret; -} - -/* - * check given pages for contiguous layout - * last page addr is returned in prev_pgaddr for further check - */ -static int ehca_check_kpages_per_ate(struct scatterlist **sg, - int num_pages, - u64 *prev_pgaddr) -{ - for (; *sg && num_pages > 0; *sg = sg_next(*sg), num_pages--) { - u64 pgaddr = page_to_pfn(sg_page(*sg)) << PAGE_SHIFT; - if (ehca_debug_level >= 3) - ehca_gen_dbg("chunk_page=%llx value=%016llx", pgaddr, - *(u64 *)__va(pgaddr)); - if (pgaddr - PAGE_SIZE != *prev_pgaddr) { - ehca_gen_err("uncontiguous page found pgaddr=%llx " - "prev_pgaddr=%llx entries_left_in_hwpage=%x", - pgaddr, *prev_pgaddr, num_pages); - return -EINVAL; - } - *prev_pgaddr = pgaddr; - } - return 0; -} - -/* PAGE_SIZE < pginfo->hwpage_size */ -static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo, - u32 number, - u64 *kpage) -{ - int ret = 0; - u64 pgaddr, prev_pgaddr; - u32 j = 0; - int kpages_per_hwpage = pginfo->hwpage_size / PAGE_SIZE; - int nr_kpages = kpages_per_hwpage; - struct scatterlist **sg = &pginfo->u.usr.next_sg; - - while (*sg != NULL) { - - if (nr_kpages == kpages_per_hwpage) { - pgaddr = (page_to_pfn(sg_page(*sg)) - << PAGE_SHIFT); - *kpage = pgaddr; - if (!(*kpage)) { - ehca_gen_err("pgaddr=%llx entry=%llx", - pgaddr, pginfo->u.usr.next_nmap); - ret = -EFAULT; - return ret; - } - /* - * The first page in a hwpage must be aligned; - * the first MR page is exempt from this rule. - */ - if (pgaddr & (pginfo->hwpage_size - 1)) { - if (pginfo->hwpage_cnt) { - ehca_gen_err( - "invalid alignment " - "pgaddr=%llx entry=%llx " - "mr_pgsize=%llx", - pgaddr, pginfo->u.usr.next_nmap, - pginfo->hwpage_size); - ret = -EFAULT; - return ret; - } - /* first MR page */ - pginfo->kpage_cnt = - (pgaddr & - (pginfo->hwpage_size - 1)) >> - PAGE_SHIFT; - nr_kpages -= pginfo->kpage_cnt; - *kpage = pgaddr & - ~(pginfo->hwpage_size - 1); - } - if (ehca_debug_level >= 3) { - u64 val = *(u64 *)__va(pgaddr); - ehca_gen_dbg("kpage=%llx page=%llx " - "value=%016llx", - *kpage, pgaddr, val); - } - prev_pgaddr = pgaddr; - *sg = sg_next(*sg); - pginfo->kpage_cnt++; - pginfo->u.usr.next_nmap++; - nr_kpages--; - if (!nr_kpages) - goto next_kpage; - continue; - } - - ret = ehca_check_kpages_per_ate(sg, nr_kpages, - &prev_pgaddr); - if (ret) - return ret; - pginfo->kpage_cnt += nr_kpages; - pginfo->u.usr.next_nmap += nr_kpages; - -next_kpage: - nr_kpages = kpages_per_hwpage; - (pginfo->hwpage_cnt)++; - kpage++; - j++; - if (j >= number) - break; - } - - return ret; -} - -static int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo, - u32 number, u64 *kpage) -{ - int ret = 0; - u64 addr = pginfo->u.phy.addr; - u64 size = pginfo->u.phy.size; - u64 num_hw, offs_hw; - u32 i = 0; - - num_hw = NUM_CHUNKS((addr % pginfo->hwpage_size) + size, - pginfo->hwpage_size); - offs_hw = (addr & ~(pginfo->hwpage_size - 1)) / pginfo->hwpage_size; - - while (pginfo->next_hwpage < offs_hw + num_hw) { - /* sanity check */ - if ((pginfo->kpage_cnt >= pginfo->num_kpages) || - (pginfo->hwpage_cnt >= pginfo->num_hwpages)) { - ehca_gen_err("kpage_cnt >= num_kpages, " - "kpage_cnt=%llx num_kpages=%llx " - "hwpage_cnt=%llx " - "num_hwpages=%llx i=%x", - pginfo->kpage_cnt, - pginfo->num_kpages, - pginfo->hwpage_cnt, - pginfo->num_hwpages, i); - return -EFAULT; - } - *kpage = (addr & ~(pginfo->hwpage_size - 1)) + - (pginfo->next_hwpage * pginfo->hwpage_size); - if ( !(*kpage) && addr ) { - ehca_gen_err("addr=%llx size=%llx " - "next_hwpage=%llx", addr, - size, pginfo->next_hwpage); - return -EFAULT; - } - (pginfo->hwpage_cnt)++; - (pginfo->next_hwpage)++; - if (PAGE_SIZE >= pginfo->hwpage_size) { - if (pginfo->next_hwpage % - (PAGE_SIZE / pginfo->hwpage_size) == 0) - (pginfo->kpage_cnt)++; - } else - pginfo->kpage_cnt += pginfo->hwpage_size / - PAGE_SIZE; - kpage++; - i++; - if (i >= number) break; - } - if (pginfo->next_hwpage >= offs_hw + num_hw) { - pginfo->next_hwpage = 0; - } - - return ret; -} - -static int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo, - u32 number, u64 *kpage) -{ - int ret = 0; - u64 *fmrlist; - u32 i; - - /* loop over desired page_list entries */ - fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem; - for (i = 0; i < number; i++) { - *kpage = (*fmrlist & ~(pginfo->hwpage_size - 1)) + - pginfo->next_hwpage * pginfo->hwpage_size; - if ( !(*kpage) ) { - ehca_gen_err("*fmrlist=%llx fmrlist=%p " - "next_listelem=%llx next_hwpage=%llx", - *fmrlist, fmrlist, - pginfo->u.fmr.next_listelem, - pginfo->next_hwpage); - return -EFAULT; - } - (pginfo->hwpage_cnt)++; - if (pginfo->u.fmr.fmr_pgsize >= pginfo->hwpage_size) { - if (pginfo->next_hwpage % - (pginfo->u.fmr.fmr_pgsize / - pginfo->hwpage_size) == 0) { - (pginfo->kpage_cnt)++; - (pginfo->u.fmr.next_listelem)++; - fmrlist++; - pginfo->next_hwpage = 0; - } else - (pginfo->next_hwpage)++; - } else { - unsigned int cnt_per_hwpage = pginfo->hwpage_size / - pginfo->u.fmr.fmr_pgsize; - unsigned int j; - u64 prev = *kpage; - /* check if adrs are contiguous */ - for (j = 1; j < cnt_per_hwpage; j++) { - u64 p = fmrlist[j] & ~(pginfo->hwpage_size - 1); - if (prev + pginfo->u.fmr.fmr_pgsize != p) { - ehca_gen_err("uncontiguous fmr pages " - "found prev=%llx p=%llx " - "idx=%x", prev, p, i + j); - return -EINVAL; - } - prev = p; - } - pginfo->kpage_cnt += cnt_per_hwpage; - pginfo->u.fmr.next_listelem += cnt_per_hwpage; - fmrlist += cnt_per_hwpage; - } - kpage++; - } - return ret; -} - -/* setup page buffer from page info */ -int ehca_set_pagebuf(struct ehca_mr_pginfo *pginfo, - u32 number, - u64 *kpage) -{ - int ret; - - switch (pginfo->type) { - case EHCA_MR_PGI_PHYS: - ret = ehca_set_pagebuf_phys(pginfo, number, kpage); - break; - case EHCA_MR_PGI_USER: - ret = PAGE_SIZE >= pginfo->hwpage_size ? - ehca_set_pagebuf_user1(pginfo, number, kpage) : - ehca_set_pagebuf_user2(pginfo, number, kpage); - break; - case EHCA_MR_PGI_FMR: - ret = ehca_set_pagebuf_fmr(pginfo, number, kpage); - break; - default: - ehca_gen_err("bad pginfo->type=%x", pginfo->type); - ret = -EFAULT; - break; - } - return ret; -} /* end ehca_set_pagebuf() */ - -/*----------------------------------------------------------------------*/ - -/* - * check MR if it is a max-MR, i.e. uses whole memory - * in case it's a max-MR 1 is returned, else 0 - */ -int ehca_mr_is_maxmr(u64 size, - u64 *iova_start) -{ - /* a MR is treated as max-MR only if it fits following: */ - if ((size == ehca_mr_len) && - (iova_start == (void *)ehca_map_vaddr((void *)(KERNELBASE + PHYSICAL_START)))) { - ehca_gen_dbg("this is a max-MR"); - return 1; - } else - return 0; -} /* end ehca_mr_is_maxmr() */ - -/*----------------------------------------------------------------------*/ - -/* map access control for MR/MW. This routine is used for MR and MW. */ -void ehca_mrmw_map_acl(int ib_acl, - u32 *hipz_acl) -{ - *hipz_acl = 0; - if (ib_acl & IB_ACCESS_REMOTE_READ) - *hipz_acl |= HIPZ_ACCESSCTRL_R_READ; - if (ib_acl & IB_ACCESS_REMOTE_WRITE) - *hipz_acl |= HIPZ_ACCESSCTRL_R_WRITE; - if (ib_acl & IB_ACCESS_REMOTE_ATOMIC) - *hipz_acl |= HIPZ_ACCESSCTRL_R_ATOMIC; - if (ib_acl & IB_ACCESS_LOCAL_WRITE) - *hipz_acl |= HIPZ_ACCESSCTRL_L_WRITE; - if (ib_acl & IB_ACCESS_MW_BIND) - *hipz_acl |= HIPZ_ACCESSCTRL_MW_BIND; -} /* end ehca_mrmw_map_acl() */ - -/*----------------------------------------------------------------------*/ - -/* sets page size in hipz access control for MR/MW. */ -void ehca_mrmw_set_pgsize_hipz_acl(u32 pgsize, u32 *hipz_acl) /*INOUT*/ -{ - *hipz_acl |= (ehca_encode_hwpage_size(pgsize) << 24); -} /* end ehca_mrmw_set_pgsize_hipz_acl() */ - -/*----------------------------------------------------------------------*/ - -/* - * reverse map access control for MR/MW. - * This routine is used for MR and MW. - */ -void ehca_mrmw_reverse_map_acl(const u32 *hipz_acl, - int *ib_acl) /*OUT*/ -{ - *ib_acl = 0; - if (*hipz_acl & HIPZ_ACCESSCTRL_R_READ) - *ib_acl |= IB_ACCESS_REMOTE_READ; - if (*hipz_acl & HIPZ_ACCESSCTRL_R_WRITE) - *ib_acl |= IB_ACCESS_REMOTE_WRITE; - if (*hipz_acl & HIPZ_ACCESSCTRL_R_ATOMIC) - *ib_acl |= IB_ACCESS_REMOTE_ATOMIC; - if (*hipz_acl & HIPZ_ACCESSCTRL_L_WRITE) - *ib_acl |= IB_ACCESS_LOCAL_WRITE; - if (*hipz_acl & HIPZ_ACCESSCTRL_MW_BIND) - *ib_acl |= IB_ACCESS_MW_BIND; -} /* end ehca_mrmw_reverse_map_acl() */ - - -/*----------------------------------------------------------------------*/ - -/* - * MR destructor and constructor - * used in Reregister MR verb, sets all fields in ehca_mr_t to 0, - * except struct ib_mr and spinlock - */ -void ehca_mr_deletenew(struct ehca_mr *mr) -{ - mr->flags = 0; - mr->num_kpages = 0; - mr->num_hwpages = 0; - mr->acl = 0; - mr->start = NULL; - mr->fmr_page_size = 0; - mr->fmr_max_pages = 0; - mr->fmr_max_maps = 0; - mr->fmr_map_cnt = 0; - memset(&mr->ipz_mr_handle, 0, sizeof(mr->ipz_mr_handle)); - memset(&mr->galpas, 0, sizeof(mr->galpas)); -} /* end ehca_mr_deletenew() */ - -int ehca_init_mrmw_cache(void) -{ - mr_cache = kmem_cache_create("ehca_cache_mr", - sizeof(struct ehca_mr), 0, - SLAB_HWCACHE_ALIGN, - NULL); - if (!mr_cache) - return -ENOMEM; - mw_cache = kmem_cache_create("ehca_cache_mw", - sizeof(struct ehca_mw), 0, - SLAB_HWCACHE_ALIGN, - NULL); - if (!mw_cache) { - kmem_cache_destroy(mr_cache); - mr_cache = NULL; - return -ENOMEM; - } - return 0; -} - -void ehca_cleanup_mrmw_cache(void) -{ - kmem_cache_destroy(mr_cache); - kmem_cache_destroy(mw_cache); -} - -static inline int ehca_init_top_bmap(struct ehca_top_bmap *ehca_top_bmap, - int dir) -{ - if (!ehca_bmap_valid(ehca_top_bmap->dir[dir])) { - ehca_top_bmap->dir[dir] = - kmalloc(sizeof(struct ehca_dir_bmap), GFP_KERNEL); - if (!ehca_top_bmap->dir[dir]) - return -ENOMEM; - /* Set map block to 0xFF according to EHCA_INVAL_ADDR */ - memset(ehca_top_bmap->dir[dir], 0xFF, EHCA_ENT_MAP_SIZE); - } - return 0; -} - -static inline int ehca_init_bmap(struct ehca_bmap *ehca_bmap, int top, int dir) -{ - if (!ehca_bmap_valid(ehca_bmap->top[top])) { - ehca_bmap->top[top] = - kmalloc(sizeof(struct ehca_top_bmap), GFP_KERNEL); - if (!ehca_bmap->top[top]) - return -ENOMEM; - /* Set map block to 0xFF according to EHCA_INVAL_ADDR */ - memset(ehca_bmap->top[top], 0xFF, EHCA_DIR_MAP_SIZE); - } - return ehca_init_top_bmap(ehca_bmap->top[top], dir); -} - -static inline int ehca_calc_index(unsigned long i, unsigned long s) -{ - return (i >> s) & EHCA_INDEX_MASK; -} - -void ehca_destroy_busmap(void) -{ - int top, dir; - - if (!ehca_bmap) - return; - - for (top = 0; top < EHCA_MAP_ENTRIES; top++) { - if (!ehca_bmap_valid(ehca_bmap->top[top])) - continue; - for (dir = 0; dir < EHCA_MAP_ENTRIES; dir++) { - if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir])) - continue; - - kfree(ehca_bmap->top[top]->dir[dir]); - } - - kfree(ehca_bmap->top[top]); - } - - kfree(ehca_bmap); - ehca_bmap = NULL; -} - -static int ehca_update_busmap(unsigned long pfn, unsigned long nr_pages) -{ - unsigned long i, start_section, end_section; - int top, dir, idx; - - if (!nr_pages) - return 0; - - if (!ehca_bmap) { - ehca_bmap = kmalloc(sizeof(struct ehca_bmap), GFP_KERNEL); - if (!ehca_bmap) - return -ENOMEM; - /* Set map block to 0xFF according to EHCA_INVAL_ADDR */ - memset(ehca_bmap, 0xFF, EHCA_TOP_MAP_SIZE); - } - - start_section = (pfn * PAGE_SIZE) / EHCA_SECTSIZE; - end_section = ((pfn + nr_pages) * PAGE_SIZE) / EHCA_SECTSIZE; - for (i = start_section; i < end_section; i++) { - int ret; - top = ehca_calc_index(i, EHCA_TOP_INDEX_SHIFT); - dir = ehca_calc_index(i, EHCA_DIR_INDEX_SHIFT); - idx = i & EHCA_INDEX_MASK; - - ret = ehca_init_bmap(ehca_bmap, top, dir); - if (ret) { - ehca_destroy_busmap(); - return ret; - } - ehca_bmap->top[top]->dir[dir]->ent[idx] = ehca_mr_len; - ehca_mr_len += EHCA_SECTSIZE; - } - return 0; -} - -static int ehca_is_hugepage(unsigned long pfn) -{ - int page_order; - - if (pfn & EHCA_HUGEPAGE_PFN_MASK) - return 0; - - page_order = compound_order(pfn_to_page(pfn)); - if (page_order + PAGE_SHIFT != EHCA_HUGEPAGESHIFT) - return 0; - - return 1; -} - -static int ehca_create_busmap_callback(unsigned long initial_pfn, - unsigned long total_nr_pages, void *arg) -{ - int ret; - unsigned long pfn, start_pfn, end_pfn, nr_pages; - - if ((total_nr_pages * PAGE_SIZE) < EHCA_HUGEPAGE_SIZE) - return ehca_update_busmap(initial_pfn, total_nr_pages); - - /* Given chunk is >= 16GB -> check for hugepages */ - start_pfn = initial_pfn; - end_pfn = initial_pfn + total_nr_pages; - pfn = start_pfn; - - while (pfn < end_pfn) { - if (ehca_is_hugepage(pfn)) { - /* Add mem found in front of the hugepage */ - nr_pages = pfn - start_pfn; - ret = ehca_update_busmap(start_pfn, nr_pages); - if (ret) - return ret; - /* Skip the hugepage */ - pfn += (EHCA_HUGEPAGE_SIZE / PAGE_SIZE); - start_pfn = pfn; - } else - pfn += (EHCA_SECTSIZE / PAGE_SIZE); - } - - /* Add mem found behind the hugepage(s) */ - nr_pages = pfn - start_pfn; - return ehca_update_busmap(start_pfn, nr_pages); -} - -int ehca_create_busmap(void) -{ - int ret; - - ehca_mr_len = 0; - ret = walk_system_ram_range(0, 1ULL << MAX_PHYSMEM_BITS, NULL, - ehca_create_busmap_callback); - return ret; -} - -static int ehca_reg_bmap_mr_rpages(struct ehca_shca *shca, - struct ehca_mr *e_mr, - struct ehca_mr_pginfo *pginfo) -{ - int top; - u64 hret, *kpage; - - kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL); - if (!kpage) { - ehca_err(&shca->ib_device, "kpage alloc failed"); - return -ENOMEM; - } - for (top = 0; top < EHCA_MAP_ENTRIES; top++) { - if (!ehca_bmap_valid(ehca_bmap->top[top])) - continue; - hret = ehca_reg_mr_dir_sections(top, kpage, shca, e_mr, pginfo); - if ((hret != H_PAGE_REGISTERED) && (hret != H_SUCCESS)) - break; - } - - ehca_free_fw_ctrlblock(kpage); - - if (hret == H_SUCCESS) - return 0; /* Everything is fine */ - else { - ehca_err(&shca->ib_device, "ehca_reg_bmap_mr_rpages failed, " - "h_ret=%lli e_mr=%p top=%x lkey=%x " - "hca_hndl=%llx mr_hndl=%llx", hret, e_mr, top, - e_mr->ib.ib_mr.lkey, - shca->ipz_hca_handle.handle, - e_mr->ipz_mr_handle.handle); - return ehca2ib_return_code(hret); - } -} - -static u64 ehca_map_vaddr(void *caddr) -{ - int top, dir, idx; - unsigned long abs_addr, offset; - u64 entry; - - if (!ehca_bmap) - return EHCA_INVAL_ADDR; - - abs_addr = __pa(caddr); - top = ehca_calc_index(abs_addr, EHCA_TOP_INDEX_SHIFT + EHCA_SECTSHIFT); - if (!ehca_bmap_valid(ehca_bmap->top[top])) - return EHCA_INVAL_ADDR; - - dir = ehca_calc_index(abs_addr, EHCA_DIR_INDEX_SHIFT + EHCA_SECTSHIFT); - if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir])) - return EHCA_INVAL_ADDR; - - idx = ehca_calc_index(abs_addr, EHCA_SECTSHIFT); - - entry = ehca_bmap->top[top]->dir[dir]->ent[idx]; - if (ehca_bmap_valid(entry)) { - offset = (unsigned long)caddr & (EHCA_SECTSIZE - 1); - return entry | offset; - } else - return EHCA_INVAL_ADDR; -} - -static int ehca_dma_mapping_error(struct ib_device *dev, u64 dma_addr) -{ - return dma_addr == EHCA_INVAL_ADDR; -} - -static u64 ehca_dma_map_single(struct ib_device *dev, void *cpu_addr, - size_t size, enum dma_data_direction direction) -{ - if (cpu_addr) - return ehca_map_vaddr(cpu_addr); - else - return EHCA_INVAL_ADDR; -} - -static void ehca_dma_unmap_single(struct ib_device *dev, u64 addr, size_t size, - enum dma_data_direction direction) -{ - /* This is only a stub; nothing to be done here */ -} - -static u64 ehca_dma_map_page(struct ib_device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction direction) -{ - u64 addr; - - if (offset + size > PAGE_SIZE) - return EHCA_INVAL_ADDR; - - addr = ehca_map_vaddr(page_address(page)); - if (!ehca_dma_mapping_error(dev, addr)) - addr += offset; - - return addr; -} - -static void ehca_dma_unmap_page(struct ib_device *dev, u64 addr, size_t size, - enum dma_data_direction direction) -{ - /* This is only a stub; nothing to be done here */ -} - -static int ehca_dma_map_sg(struct ib_device *dev, struct scatterlist *sgl, - int nents, enum dma_data_direction direction) -{ - struct scatterlist *sg; - int i; - - for_each_sg(sgl, sg, nents, i) { - u64 addr; - addr = ehca_map_vaddr(sg_virt(sg)); - if (ehca_dma_mapping_error(dev, addr)) - return 0; - - sg->dma_address = addr; - sg->dma_length = sg->length; - } - return nents; -} - -static void ehca_dma_unmap_sg(struct ib_device *dev, struct scatterlist *sg, - int nents, enum dma_data_direction direction) -{ - /* This is only a stub; nothing to be done here */ -} - -static void ehca_dma_sync_single_for_cpu(struct ib_device *dev, u64 addr, - size_t size, - enum dma_data_direction dir) -{ - dma_sync_single_for_cpu(dev->dma_device, addr, size, dir); -} - -static void ehca_dma_sync_single_for_device(struct ib_device *dev, u64 addr, - size_t size, - enum dma_data_direction dir) -{ - dma_sync_single_for_device(dev->dma_device, addr, size, dir); -} - -static void *ehca_dma_alloc_coherent(struct ib_device *dev, size_t size, - u64 *dma_handle, gfp_t flag) -{ - struct page *p; - void *addr = NULL; - u64 dma_addr; - - p = alloc_pages(flag, get_order(size)); - if (p) { - addr = page_address(p); - dma_addr = ehca_map_vaddr(addr); - if (ehca_dma_mapping_error(dev, dma_addr)) { - free_pages((unsigned long)addr, get_order(size)); - return NULL; - } - if (dma_handle) - *dma_handle = dma_addr; - return addr; - } - return NULL; -} - -static void ehca_dma_free_coherent(struct ib_device *dev, size_t size, - void *cpu_addr, u64 dma_handle) -{ - if (cpu_addr && size) - free_pages((unsigned long)cpu_addr, get_order(size)); -} - - -struct ib_dma_mapping_ops ehca_dma_mapping_ops = { - .mapping_error = ehca_dma_mapping_error, - .map_single = ehca_dma_map_single, - .unmap_single = ehca_dma_unmap_single, - .map_page = ehca_dma_map_page, - .unmap_page = ehca_dma_unmap_page, - .map_sg = ehca_dma_map_sg, - .unmap_sg = ehca_dma_unmap_sg, - .sync_single_for_cpu = ehca_dma_sync_single_for_cpu, - .sync_single_for_device = ehca_dma_sync_single_for_device, - .alloc_coherent = ehca_dma_alloc_coherent, - .free_coherent = ehca_dma_free_coherent, -}; diff --git a/drivers/staging/rdma/ehca/ehca_mrmw.h b/drivers/staging/rdma/ehca/ehca_mrmw.h deleted file mode 100644 index 52bfa95697f7..000000000000 --- a/drivers/staging/rdma/ehca/ehca_mrmw.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * MR/MW declarations and inline functions - * - * Authors: Dietmar Decker - * Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _EHCA_MRMW_H_ -#define _EHCA_MRMW_H_ - -enum ehca_reg_type { - EHCA_REG_MR, - EHCA_REG_BUSMAP_MR -}; - -int ehca_reg_mr(struct ehca_shca *shca, - struct ehca_mr *e_mr, - u64 *iova_start, - u64 size, - int acl, - struct ehca_pd *e_pd, - struct ehca_mr_pginfo *pginfo, - u32 *lkey, - u32 *rkey, - enum ehca_reg_type reg_type); - -int ehca_reg_mr_rpages(struct ehca_shca *shca, - struct ehca_mr *e_mr, - struct ehca_mr_pginfo *pginfo); - -int ehca_rereg_mr(struct ehca_shca *shca, - struct ehca_mr *e_mr, - u64 *iova_start, - u64 size, - int mr_access_flags, - struct ehca_pd *e_pd, - struct ehca_mr_pginfo *pginfo, - u32 *lkey, - u32 *rkey); - -int ehca_unmap_one_fmr(struct ehca_shca *shca, - struct ehca_mr *e_fmr); - -int ehca_reg_smr(struct ehca_shca *shca, - struct ehca_mr *e_origmr, - struct ehca_mr *e_newmr, - u64 *iova_start, - int acl, - struct ehca_pd *e_pd, - u32 *lkey, - u32 *rkey); - -int ehca_reg_internal_maxmr(struct ehca_shca *shca, - struct ehca_pd *e_pd, - struct ehca_mr **maxmr); - -int ehca_reg_maxmr(struct ehca_shca *shca, - struct ehca_mr *e_newmr, - u64 *iova_start, - int acl, - struct ehca_pd *e_pd, - u32 *lkey, - u32 *rkey); - -int ehca_dereg_internal_maxmr(struct ehca_shca *shca); - -int ehca_fmr_check_page_list(struct ehca_mr *e_fmr, - u64 *page_list, - int list_len); - -int ehca_set_pagebuf(struct ehca_mr_pginfo *pginfo, - u32 number, - u64 *kpage); - -int ehca_mr_is_maxmr(u64 size, - u64 *iova_start); - -void ehca_mrmw_map_acl(int ib_acl, - u32 *hipz_acl); - -void ehca_mrmw_set_pgsize_hipz_acl(u32 pgsize, u32 *hipz_acl); - -void ehca_mrmw_reverse_map_acl(const u32 *hipz_acl, - int *ib_acl); - -void ehca_mr_deletenew(struct ehca_mr *mr); - -int ehca_create_busmap(void); - -void ehca_destroy_busmap(void); - -extern struct ib_dma_mapping_ops ehca_dma_mapping_ops; -#endif /*_EHCA_MRMW_H_*/ diff --git a/drivers/staging/rdma/ehca/ehca_pd.c b/drivers/staging/rdma/ehca/ehca_pd.c deleted file mode 100644 index 2a8aae411941..000000000000 --- a/drivers/staging/rdma/ehca/ehca_pd.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * PD functions - * - * Authors: Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "ehca_tools.h" -#include "ehca_iverbs.h" - -static struct kmem_cache *pd_cache; - -struct ib_pd *ehca_alloc_pd(struct ib_device *device, - struct ib_ucontext *context, struct ib_udata *udata) -{ - struct ehca_pd *pd; - int i; - - pd = kmem_cache_zalloc(pd_cache, GFP_KERNEL); - if (!pd) { - ehca_err(device, "device=%p context=%p out of memory", - device, context); - return ERR_PTR(-ENOMEM); - } - - for (i = 0; i < 2; i++) { - INIT_LIST_HEAD(&pd->free[i]); - INIT_LIST_HEAD(&pd->full[i]); - } - mutex_init(&pd->lock); - - /* - * Kernel PD: when device = -1, 0 - * User PD: when context != -1 - */ - if (!context) { - /* - * Kernel PDs after init reuses always - * the one created in ehca_shca_reopen() - */ - struct ehca_shca *shca = container_of(device, struct ehca_shca, - ib_device); - pd->fw_pd.value = shca->pd->fw_pd.value; - } else - pd->fw_pd.value = (u64)pd; - - return &pd->ib_pd; -} - -int ehca_dealloc_pd(struct ib_pd *pd) -{ - struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd); - int i, leftovers = 0; - struct ipz_small_queue_page *page, *tmp; - - for (i = 0; i < 2; i++) { - list_splice(&my_pd->full[i], &my_pd->free[i]); - list_for_each_entry_safe(page, tmp, &my_pd->free[i], list) { - leftovers = 1; - free_page(page->page); - kmem_cache_free(small_qp_cache, page); - } - } - - if (leftovers) - ehca_warn(pd->device, - "Some small queue pages were not freed"); - - kmem_cache_free(pd_cache, my_pd); - - return 0; -} - -int ehca_init_pd_cache(void) -{ - pd_cache = kmem_cache_create("ehca_cache_pd", - sizeof(struct ehca_pd), 0, - SLAB_HWCACHE_ALIGN, - NULL); - if (!pd_cache) - return -ENOMEM; - return 0; -} - -void ehca_cleanup_pd_cache(void) -{ - kmem_cache_destroy(pd_cache); -} diff --git a/drivers/staging/rdma/ehca/ehca_qes.h b/drivers/staging/rdma/ehca/ehca_qes.h deleted file mode 100644 index 90c4efa67586..000000000000 --- a/drivers/staging/rdma/ehca/ehca_qes.h +++ /dev/null @@ -1,260 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Hardware request structures - * - * Authors: Waleri Fomin - * Reinhard Ernst - * Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef _EHCA_QES_H_ -#define _EHCA_QES_H_ - -#include "ehca_tools.h" - -/* virtual scatter gather entry to specify remote addresses with length */ -struct ehca_vsgentry { - u64 vaddr; - u32 lkey; - u32 length; -}; - -#define GRH_FLAG_MASK EHCA_BMASK_IBM( 7, 7) -#define GRH_IPVERSION_MASK EHCA_BMASK_IBM( 0, 3) -#define GRH_TCLASS_MASK EHCA_BMASK_IBM( 4, 12) -#define GRH_FLOWLABEL_MASK EHCA_BMASK_IBM(13, 31) -#define GRH_PAYLEN_MASK EHCA_BMASK_IBM(32, 47) -#define GRH_NEXTHEADER_MASK EHCA_BMASK_IBM(48, 55) -#define GRH_HOPLIMIT_MASK EHCA_BMASK_IBM(56, 63) - -/* - * Unreliable Datagram Address Vector Format - * see IBTA Vol1 chapter 8.3 Global Routing Header - */ -struct ehca_ud_av { - u8 sl; - u8 lnh; - u16 dlid; - u8 reserved1; - u8 reserved2; - u8 reserved3; - u8 slid_path_bits; - u8 reserved4; - u8 ipd; - u8 reserved5; - u8 pmtu; - u32 reserved6; - u64 reserved7; - union { - struct { - u64 word_0; /* always set to 6 */ - /*should be 0x1B for IB transport */ - u64 word_1; - u64 word_2; - u64 word_3; - u64 word_4; - } grh; - struct { - u32 wd_0; - u32 wd_1; - /* DWord_1 --> SGID */ - - u32 sgid_wd3; - u32 sgid_wd2; - - u32 sgid_wd1; - u32 sgid_wd0; - /* DWord_3 --> DGID */ - - u32 dgid_wd3; - u32 dgid_wd2; - - u32 dgid_wd1; - u32 dgid_wd0; - } grh_l; - }; -}; - -/* maximum number of sg entries allowed in a WQE */ -#define MAX_WQE_SG_ENTRIES 252 - -#define WQE_OPTYPE_SEND 0x80 -#define WQE_OPTYPE_RDMAREAD 0x40 -#define WQE_OPTYPE_RDMAWRITE 0x20 -#define WQE_OPTYPE_CMPSWAP 0x10 -#define WQE_OPTYPE_FETCHADD 0x08 -#define WQE_OPTYPE_BIND 0x04 - -#define WQE_WRFLAG_REQ_SIGNAL_COM 0x80 -#define WQE_WRFLAG_FENCE 0x40 -#define WQE_WRFLAG_IMM_DATA_PRESENT 0x20 -#define WQE_WRFLAG_SOLIC_EVENT 0x10 - -#define WQEF_CACHE_HINT 0x80 -#define WQEF_CACHE_HINT_RD_WR 0x40 -#define WQEF_TIMED_WQE 0x20 -#define WQEF_PURGE 0x08 -#define WQEF_HIGH_NIBBLE 0xF0 - -#define MW_BIND_ACCESSCTRL_R_WRITE 0x40 -#define MW_BIND_ACCESSCTRL_R_READ 0x20 -#define MW_BIND_ACCESSCTRL_R_ATOMIC 0x10 - -struct ehca_wqe { - u64 work_request_id; - u8 optype; - u8 wr_flag; - u16 pkeyi; - u8 wqef; - u8 nr_of_data_seg; - u16 wqe_provided_slid; - u32 destination_qp_number; - u32 resync_psn_sqp; - u32 local_ee_context_qkey; - u32 immediate_data; - union { - struct { - u64 remote_virtual_address; - u32 rkey; - u32 reserved; - u64 atomic_1st_op_dma_len; - u64 atomic_2nd_op; - struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES]; - - } nud; - struct { - u64 ehca_ud_av_ptr; - u64 reserved1; - u64 reserved2; - u64 reserved3; - struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES]; - } ud_avp; - struct { - struct ehca_ud_av ud_av; - struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES - - 2]; - } ud_av; - struct { - u64 reserved0; - u64 reserved1; - u64 reserved2; - u64 reserved3; - struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES]; - } all_rcv; - - struct { - u64 reserved; - u32 rkey; - u32 old_rkey; - u64 reserved1; - u64 reserved2; - u64 virtual_address; - u32 reserved3; - u32 length; - u32 reserved4; - u16 reserved5; - u8 reserved6; - u8 lr_ctl; - u32 lkey; - u32 reserved7; - u64 reserved8; - u64 reserved9; - u64 reserved10; - u64 reserved11; - } bind; - struct { - u64 reserved12; - u64 reserved13; - u32 size; - u32 start; - } inline_data; - } u; - -}; - -#define WC_SEND_RECEIVE EHCA_BMASK_IBM(0, 0) -#define WC_IMM_DATA EHCA_BMASK_IBM(1, 1) -#define WC_GRH_PRESENT EHCA_BMASK_IBM(2, 2) -#define WC_SE_BIT EHCA_BMASK_IBM(3, 3) -#define WC_STATUS_ERROR_BIT 0x80000000 -#define WC_STATUS_REMOTE_ERROR_FLAGS 0x0000F800 -#define WC_STATUS_PURGE_BIT 0x10 -#define WC_SEND_RECEIVE_BIT 0x80 - -struct ehca_cqe { - u64 work_request_id; - u8 optype; - u8 w_completion_flags; - u16 reserved1; - u32 nr_bytes_transferred; - u32 immediate_data; - u32 local_qp_number; - u8 freed_resource_count; - u8 service_level; - u16 wqe_count; - u32 qp_token; - u32 qkey_ee_token; - u32 remote_qp_number; - u16 dlid; - u16 rlid; - u16 reserved2; - u16 pkey_index; - u32 cqe_timestamp; - u32 wqe_timestamp; - u8 wqe_timestamp_valid; - u8 reserved3; - u8 reserved4; - u8 cqe_flags; - u32 status; -}; - -struct ehca_eqe { - u64 entry; -}; - -struct ehca_mrte { - u64 starting_va; - u64 length; /* length of memory region in bytes*/ - u32 pd; - u8 key_instance; - u8 pagesize; - u8 mr_control; - u8 local_remote_access_ctrl; - u8 reserved[0x20 - 0x18]; - u64 at_pointer[4]; -}; -#endif /*_EHCA_QES_H_*/ diff --git a/drivers/staging/rdma/ehca/ehca_qp.c b/drivers/staging/rdma/ehca/ehca_qp.c deleted file mode 100644 index 896c01f810f6..000000000000 --- a/drivers/staging/rdma/ehca/ehca_qp.c +++ /dev/null @@ -1,2256 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * QP functions - * - * Authors: Joachim Fenkes - * Stefan Roscher - * Waleri Fomin - * Hoang-Nam Nguyen - * Reinhard Ernst - * Heiko J Schick - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "ehca_classes.h" -#include "ehca_tools.h" -#include "ehca_qes.h" -#include "ehca_iverbs.h" -#include "hcp_if.h" -#include "hipz_fns.h" - -static struct kmem_cache *qp_cache; - -/* - * attributes not supported by query qp - */ -#define QP_ATTR_QUERY_NOT_SUPPORTED (IB_QP_ACCESS_FLAGS | \ - IB_QP_EN_SQD_ASYNC_NOTIFY) - -/* - * ehca (internal) qp state values - */ -enum ehca_qp_state { - EHCA_QPS_RESET = 1, - EHCA_QPS_INIT = 2, - EHCA_QPS_RTR = 3, - EHCA_QPS_RTS = 5, - EHCA_QPS_SQD = 6, - EHCA_QPS_SQE = 8, - EHCA_QPS_ERR = 128 -}; - -/* - * qp state transitions as defined by IB Arch Rel 1.1 page 431 - */ -enum ib_qp_statetrans { - IB_QPST_ANY2RESET, - IB_QPST_ANY2ERR, - IB_QPST_RESET2INIT, - IB_QPST_INIT2RTR, - IB_QPST_INIT2INIT, - IB_QPST_RTR2RTS, - IB_QPST_RTS2SQD, - IB_QPST_RTS2RTS, - IB_QPST_SQD2RTS, - IB_QPST_SQE2RTS, - IB_QPST_SQD2SQD, - IB_QPST_MAX /* nr of transitions, this must be last!!! */ -}; - -/* - * ib2ehca_qp_state maps IB to ehca qp_state - * returns ehca qp state corresponding to given ib qp state - */ -static inline enum ehca_qp_state ib2ehca_qp_state(enum ib_qp_state ib_qp_state) -{ - switch (ib_qp_state) { - case IB_QPS_RESET: - return EHCA_QPS_RESET; - case IB_QPS_INIT: - return EHCA_QPS_INIT; - case IB_QPS_RTR: - return EHCA_QPS_RTR; - case IB_QPS_RTS: - return EHCA_QPS_RTS; - case IB_QPS_SQD: - return EHCA_QPS_SQD; - case IB_QPS_SQE: - return EHCA_QPS_SQE; - case IB_QPS_ERR: - return EHCA_QPS_ERR; - default: - ehca_gen_err("invalid ib_qp_state=%x", ib_qp_state); - return -EINVAL; - } -} - -/* - * ehca2ib_qp_state maps ehca to IB qp_state - * returns ib qp state corresponding to given ehca qp state - */ -static inline enum ib_qp_state ehca2ib_qp_state(enum ehca_qp_state - ehca_qp_state) -{ - switch (ehca_qp_state) { - case EHCA_QPS_RESET: - return IB_QPS_RESET; - case EHCA_QPS_INIT: - return IB_QPS_INIT; - case EHCA_QPS_RTR: - return IB_QPS_RTR; - case EHCA_QPS_RTS: - return IB_QPS_RTS; - case EHCA_QPS_SQD: - return IB_QPS_SQD; - case EHCA_QPS_SQE: - return IB_QPS_SQE; - case EHCA_QPS_ERR: - return IB_QPS_ERR; - default: - ehca_gen_err("invalid ehca_qp_state=%x", ehca_qp_state); - return -EINVAL; - } -} - -/* - * ehca_qp_type used as index for req_attr and opt_attr of - * struct ehca_modqp_statetrans - */ -enum ehca_qp_type { - QPT_RC = 0, - QPT_UC = 1, - QPT_UD = 2, - QPT_SQP = 3, - QPT_MAX -}; - -/* - * ib2ehcaqptype maps Ib to ehca qp_type - * returns ehca qp type corresponding to ib qp type - */ -static inline enum ehca_qp_type ib2ehcaqptype(enum ib_qp_type ibqptype) -{ - switch (ibqptype) { - case IB_QPT_SMI: - case IB_QPT_GSI: - return QPT_SQP; - case IB_QPT_RC: - return QPT_RC; - case IB_QPT_UC: - return QPT_UC; - case IB_QPT_UD: - return QPT_UD; - default: - ehca_gen_err("Invalid ibqptype=%x", ibqptype); - return -EINVAL; - } -} - -static inline enum ib_qp_statetrans get_modqp_statetrans(int ib_fromstate, - int ib_tostate) -{ - int index = -EINVAL; - switch (ib_tostate) { - case IB_QPS_RESET: - index = IB_QPST_ANY2RESET; - break; - case IB_QPS_INIT: - switch (ib_fromstate) { - case IB_QPS_RESET: - index = IB_QPST_RESET2INIT; - break; - case IB_QPS_INIT: - index = IB_QPST_INIT2INIT; - break; - } - break; - case IB_QPS_RTR: - if (ib_fromstate == IB_QPS_INIT) - index = IB_QPST_INIT2RTR; - break; - case IB_QPS_RTS: - switch (ib_fromstate) { - case IB_QPS_RTR: - index = IB_QPST_RTR2RTS; - break; - case IB_QPS_RTS: - index = IB_QPST_RTS2RTS; - break; - case IB_QPS_SQD: - index = IB_QPST_SQD2RTS; - break; - case IB_QPS_SQE: - index = IB_QPST_SQE2RTS; - break; - } - break; - case IB_QPS_SQD: - if (ib_fromstate == IB_QPS_RTS) - index = IB_QPST_RTS2SQD; - break; - case IB_QPS_SQE: - break; - case IB_QPS_ERR: - index = IB_QPST_ANY2ERR; - break; - default: - break; - } - return index; -} - -/* - * ibqptype2servicetype returns hcp service type corresponding to given - * ib qp type used by create_qp() - */ -static inline int ibqptype2servicetype(enum ib_qp_type ibqptype) -{ - switch (ibqptype) { - case IB_QPT_SMI: - case IB_QPT_GSI: - return ST_UD; - case IB_QPT_RC: - return ST_RC; - case IB_QPT_UC: - return ST_UC; - case IB_QPT_UD: - return ST_UD; - case IB_QPT_RAW_IPV6: - return -EINVAL; - case IB_QPT_RAW_ETHERTYPE: - return -EINVAL; - default: - ehca_gen_err("Invalid ibqptype=%x", ibqptype); - return -EINVAL; - } -} - -/* - * init userspace queue info from ipz_queue data - */ -static inline void queue2resp(struct ipzu_queue_resp *resp, - struct ipz_queue *queue) -{ - resp->qe_size = queue->qe_size; - resp->act_nr_of_sg = queue->act_nr_of_sg; - resp->queue_length = queue->queue_length; - resp->pagesize = queue->pagesize; - resp->toggle_state = queue->toggle_state; - resp->offset = queue->offset; -} - -/* - * init_qp_queue initializes/constructs r/squeue and registers queue pages. - */ -static inline int init_qp_queue(struct ehca_shca *shca, - struct ehca_pd *pd, - struct ehca_qp *my_qp, - struct ipz_queue *queue, - int q_type, - u64 expected_hret, - struct ehca_alloc_queue_parms *parms, - int wqe_size) -{ - int ret, cnt, ipz_rc, nr_q_pages; - void *vpage; - u64 rpage, h_ret; - struct ib_device *ib_dev = &shca->ib_device; - struct ipz_adapter_handle ipz_hca_handle = shca->ipz_hca_handle; - - if (!parms->queue_size) - return 0; - - if (parms->is_small) { - nr_q_pages = 1; - ipz_rc = ipz_queue_ctor(pd, queue, nr_q_pages, - 128 << parms->page_size, - wqe_size, parms->act_nr_sges, 1); - } else { - nr_q_pages = parms->queue_size; - ipz_rc = ipz_queue_ctor(pd, queue, nr_q_pages, - EHCA_PAGESIZE, wqe_size, - parms->act_nr_sges, 0); - } - - if (!ipz_rc) { - ehca_err(ib_dev, "Cannot allocate page for queue. ipz_rc=%i", - ipz_rc); - return -EBUSY; - } - - /* register queue pages */ - for (cnt = 0; cnt < nr_q_pages; cnt++) { - vpage = ipz_qpageit_get_inc(queue); - if (!vpage) { - ehca_err(ib_dev, "ipz_qpageit_get_inc() " - "failed p_vpage= %p", vpage); - ret = -EINVAL; - goto init_qp_queue1; - } - rpage = __pa(vpage); - - h_ret = hipz_h_register_rpage_qp(ipz_hca_handle, - my_qp->ipz_qp_handle, - NULL, 0, q_type, - rpage, parms->is_small ? 0 : 1, - my_qp->galpas.kernel); - if (cnt == (nr_q_pages - 1)) { /* last page! */ - if (h_ret != expected_hret) { - ehca_err(ib_dev, "hipz_qp_register_rpage() " - "h_ret=%lli", h_ret); - ret = ehca2ib_return_code(h_ret); - goto init_qp_queue1; - } - vpage = ipz_qpageit_get_inc(&my_qp->ipz_rqueue); - if (vpage) { - ehca_err(ib_dev, "ipz_qpageit_get_inc() " - "should not succeed vpage=%p", vpage); - ret = -EINVAL; - goto init_qp_queue1; - } - } else { - if (h_ret != H_PAGE_REGISTERED) { - ehca_err(ib_dev, "hipz_qp_register_rpage() " - "h_ret=%lli", h_ret); - ret = ehca2ib_return_code(h_ret); - goto init_qp_queue1; - } - } - } - - ipz_qeit_reset(queue); - - return 0; - -init_qp_queue1: - ipz_queue_dtor(pd, queue); - return ret; -} - -static inline int ehca_calc_wqe_size(int act_nr_sge, int is_llqp) -{ - if (is_llqp) - return 128 << act_nr_sge; - else - return offsetof(struct ehca_wqe, - u.nud.sg_list[act_nr_sge]); -} - -static void ehca_determine_small_queue(struct ehca_alloc_queue_parms *queue, - int req_nr_sge, int is_llqp) -{ - u32 wqe_size, q_size; - int act_nr_sge = req_nr_sge; - - if (!is_llqp) - /* round up #SGEs so WQE size is a power of 2 */ - for (act_nr_sge = 4; act_nr_sge <= 252; - act_nr_sge = 4 + 2 * act_nr_sge) - if (act_nr_sge >= req_nr_sge) - break; - - wqe_size = ehca_calc_wqe_size(act_nr_sge, is_llqp); - q_size = wqe_size * (queue->max_wr + 1); - - if (q_size <= 512) - queue->page_size = 2; - else if (q_size <= 1024) - queue->page_size = 3; - else - queue->page_size = 0; - - queue->is_small = (queue->page_size != 0); -} - -/* needs to be called with cq->spinlock held */ -void ehca_add_to_err_list(struct ehca_qp *qp, int on_sq) -{ - struct list_head *list, *node; - - /* TODO: support low latency QPs */ - if (qp->ext_type == EQPT_LLQP) - return; - - if (on_sq) { - list = &qp->send_cq->sqp_err_list; - node = &qp->sq_err_node; - } else { - list = &qp->recv_cq->rqp_err_list; - node = &qp->rq_err_node; - } - - if (list_empty(node)) - list_add_tail(node, list); - - return; -} - -static void del_from_err_list(struct ehca_cq *cq, struct list_head *node) -{ - unsigned long flags; - - spin_lock_irqsave(&cq->spinlock, flags); - - if (!list_empty(node)) - list_del_init(node); - - spin_unlock_irqrestore(&cq->spinlock, flags); -} - -static void reset_queue_map(struct ehca_queue_map *qmap) -{ - int i; - - qmap->tail = qmap->entries - 1; - qmap->left_to_poll = 0; - qmap->next_wqe_idx = 0; - for (i = 0; i < qmap->entries; i++) { - qmap->map[i].reported = 1; - qmap->map[i].cqe_req = 0; - } -} - -/* - * Create an ib_qp struct that is either a QP or an SRQ, depending on - * the value of the is_srq parameter. If init_attr and srq_init_attr share - * fields, the field out of init_attr is used. - */ -static struct ehca_qp *internal_create_qp( - struct ib_pd *pd, - struct ib_qp_init_attr *init_attr, - struct ib_srq_init_attr *srq_init_attr, - struct ib_udata *udata, int is_srq) -{ - struct ehca_qp *my_qp, *my_srq = NULL; - struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd); - struct ehca_shca *shca = container_of(pd->device, struct ehca_shca, - ib_device); - struct ib_ucontext *context = NULL; - u64 h_ret; - int is_llqp = 0, has_srq = 0, is_user = 0; - int qp_type, max_send_sge, max_recv_sge, ret; - - /* h_call's out parameters */ - struct ehca_alloc_qp_parms parms; - u32 swqe_size = 0, rwqe_size = 0, ib_qp_num; - unsigned long flags; - - if (!atomic_add_unless(&shca->num_qps, 1, shca->max_num_qps)) { - ehca_err(pd->device, "Unable to create QP, max number of %i " - "QPs reached.", shca->max_num_qps); - ehca_err(pd->device, "To increase the maximum number of QPs " - "use the number_of_qps module parameter.\n"); - return ERR_PTR(-ENOSPC); - } - - if (init_attr->create_flags) { - atomic_dec(&shca->num_qps); - return ERR_PTR(-EINVAL); - } - - memset(&parms, 0, sizeof(parms)); - qp_type = init_attr->qp_type; - - if (init_attr->sq_sig_type != IB_SIGNAL_REQ_WR && - init_attr->sq_sig_type != IB_SIGNAL_ALL_WR) { - ehca_err(pd->device, "init_attr->sg_sig_type=%x not allowed", - init_attr->sq_sig_type); - atomic_dec(&shca->num_qps); - return ERR_PTR(-EINVAL); - } - - /* save LLQP info */ - if (qp_type & 0x80) { - is_llqp = 1; - parms.ext_type = EQPT_LLQP; - parms.ll_comp_flags = qp_type & LLQP_COMP_MASK; - } - qp_type &= 0x1F; - init_attr->qp_type &= 0x1F; - - /* handle SRQ base QPs */ - if (init_attr->srq) { - my_srq = container_of(init_attr->srq, struct ehca_qp, ib_srq); - - if (qp_type == IB_QPT_UC) { - ehca_err(pd->device, "UC with SRQ not supported"); - atomic_dec(&shca->num_qps); - return ERR_PTR(-EINVAL); - } - - has_srq = 1; - parms.ext_type = EQPT_SRQBASE; - parms.srq_qpn = my_srq->real_qp_num; - } - - if (is_llqp && has_srq) { - ehca_err(pd->device, "LLQPs can't have an SRQ"); - atomic_dec(&shca->num_qps); - return ERR_PTR(-EINVAL); - } - - /* handle SRQs */ - if (is_srq) { - parms.ext_type = EQPT_SRQ; - parms.srq_limit = srq_init_attr->attr.srq_limit; - if (init_attr->cap.max_recv_sge > 3) { - ehca_err(pd->device, "no more than three SGEs " - "supported for SRQ pd=%p max_sge=%x", - pd, init_attr->cap.max_recv_sge); - atomic_dec(&shca->num_qps); - return ERR_PTR(-EINVAL); - } - } - - /* check QP type */ - if (qp_type != IB_QPT_UD && - qp_type != IB_QPT_UC && - qp_type != IB_QPT_RC && - qp_type != IB_QPT_SMI && - qp_type != IB_QPT_GSI) { - ehca_err(pd->device, "wrong QP Type=%x", qp_type); - atomic_dec(&shca->num_qps); - return ERR_PTR(-EINVAL); - } - - if (is_llqp) { - switch (qp_type) { - case IB_QPT_RC: - if ((init_attr->cap.max_send_wr > 255) || - (init_attr->cap.max_recv_wr > 255)) { - ehca_err(pd->device, - "Invalid Number of max_sq_wr=%x " - "or max_rq_wr=%x for RC LLQP", - init_attr->cap.max_send_wr, - init_attr->cap.max_recv_wr); - atomic_dec(&shca->num_qps); - return ERR_PTR(-EINVAL); - } - break; - case IB_QPT_UD: - if (!EHCA_BMASK_GET(HCA_CAP_UD_LL_QP, shca->hca_cap)) { - ehca_err(pd->device, "UD LLQP not supported " - "by this adapter"); - atomic_dec(&shca->num_qps); - return ERR_PTR(-ENOSYS); - } - if (!(init_attr->cap.max_send_sge <= 5 - && init_attr->cap.max_send_sge >= 1 - && init_attr->cap.max_recv_sge <= 5 - && init_attr->cap.max_recv_sge >= 1)) { - ehca_err(pd->device, - "Invalid Number of max_send_sge=%x " - "or max_recv_sge=%x for UD LLQP", - init_attr->cap.max_send_sge, - init_attr->cap.max_recv_sge); - atomic_dec(&shca->num_qps); - return ERR_PTR(-EINVAL); - } else if (init_attr->cap.max_send_wr > 255) { - ehca_err(pd->device, - "Invalid Number of " - "max_send_wr=%x for UD QP_TYPE=%x", - init_attr->cap.max_send_wr, qp_type); - atomic_dec(&shca->num_qps); - return ERR_PTR(-EINVAL); - } - break; - default: - ehca_err(pd->device, "unsupported LL QP Type=%x", - qp_type); - atomic_dec(&shca->num_qps); - return ERR_PTR(-EINVAL); - } - } else { - int max_sge = (qp_type == IB_QPT_UD || qp_type == IB_QPT_SMI - || qp_type == IB_QPT_GSI) ? 250 : 252; - - if (init_attr->cap.max_send_sge > max_sge - || init_attr->cap.max_recv_sge > max_sge) { - ehca_err(pd->device, "Invalid number of SGEs requested " - "send_sge=%x recv_sge=%x max_sge=%x", - init_attr->cap.max_send_sge, - init_attr->cap.max_recv_sge, max_sge); - atomic_dec(&shca->num_qps); - return ERR_PTR(-EINVAL); - } - } - - my_qp = kmem_cache_zalloc(qp_cache, GFP_KERNEL); - if (!my_qp) { - ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd); - atomic_dec(&shca->num_qps); - return ERR_PTR(-ENOMEM); - } - - if (pd->uobject && udata) { - is_user = 1; - context = pd->uobject->context; - } - - atomic_set(&my_qp->nr_events, 0); - init_waitqueue_head(&my_qp->wait_completion); - spin_lock_init(&my_qp->spinlock_s); - spin_lock_init(&my_qp->spinlock_r); - my_qp->qp_type = qp_type; - my_qp->ext_type = parms.ext_type; - my_qp->state = IB_QPS_RESET; - - if (init_attr->recv_cq) - my_qp->recv_cq = - container_of(init_attr->recv_cq, struct ehca_cq, ib_cq); - if (init_attr->send_cq) - my_qp->send_cq = - container_of(init_attr->send_cq, struct ehca_cq, ib_cq); - - idr_preload(GFP_KERNEL); - write_lock_irqsave(&ehca_qp_idr_lock, flags); - - ret = idr_alloc(&ehca_qp_idr, my_qp, 0, 0x2000000, GFP_NOWAIT); - if (ret >= 0) - my_qp->token = ret; - - write_unlock_irqrestore(&ehca_qp_idr_lock, flags); - idr_preload_end(); - if (ret < 0) { - if (ret == -ENOSPC) { - ret = -EINVAL; - ehca_err(pd->device, "Invalid number of qp"); - } else { - ret = -ENOMEM; - ehca_err(pd->device, "Can't allocate new idr entry."); - } - goto create_qp_exit0; - } - - if (has_srq) - parms.srq_token = my_qp->token; - - parms.servicetype = ibqptype2servicetype(qp_type); - if (parms.servicetype < 0) { - ret = -EINVAL; - ehca_err(pd->device, "Invalid qp_type=%x", qp_type); - goto create_qp_exit1; - } - - /* Always signal by WQE so we can hide circ. WQEs */ - parms.sigtype = HCALL_SIGT_BY_WQE; - - /* UD_AV CIRCUMVENTION */ - max_send_sge = init_attr->cap.max_send_sge; - max_recv_sge = init_attr->cap.max_recv_sge; - if (parms.servicetype == ST_UD && !is_llqp) { - max_send_sge += 2; - max_recv_sge += 2; - } - - parms.token = my_qp->token; - parms.eq_handle = shca->eq.ipz_eq_handle; - parms.pd = my_pd->fw_pd; - if (my_qp->send_cq) - parms.send_cq_handle = my_qp->send_cq->ipz_cq_handle; - if (my_qp->recv_cq) - parms.recv_cq_handle = my_qp->recv_cq->ipz_cq_handle; - - parms.squeue.max_wr = init_attr->cap.max_send_wr; - parms.rqueue.max_wr = init_attr->cap.max_recv_wr; - parms.squeue.max_sge = max_send_sge; - parms.rqueue.max_sge = max_recv_sge; - - /* RC QPs need one more SWQE for unsolicited ack circumvention */ - if (qp_type == IB_QPT_RC) - parms.squeue.max_wr++; - - if (EHCA_BMASK_GET(HCA_CAP_MINI_QP, shca->hca_cap)) { - if (HAS_SQ(my_qp)) - ehca_determine_small_queue( - &parms.squeue, max_send_sge, is_llqp); - if (HAS_RQ(my_qp)) - ehca_determine_small_queue( - &parms.rqueue, max_recv_sge, is_llqp); - parms.qp_storage = - (parms.squeue.is_small || parms.rqueue.is_small); - } - - h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, &parms, is_user); - if (h_ret != H_SUCCESS) { - ehca_err(pd->device, "h_alloc_resource_qp() failed h_ret=%lli", - h_ret); - ret = ehca2ib_return_code(h_ret); - goto create_qp_exit1; - } - - ib_qp_num = my_qp->real_qp_num = parms.real_qp_num; - my_qp->ipz_qp_handle = parms.qp_handle; - my_qp->galpas = parms.galpas; - - swqe_size = ehca_calc_wqe_size(parms.squeue.act_nr_sges, is_llqp); - rwqe_size = ehca_calc_wqe_size(parms.rqueue.act_nr_sges, is_llqp); - - switch (qp_type) { - case IB_QPT_RC: - if (is_llqp) { - parms.squeue.act_nr_sges = 1; - parms.rqueue.act_nr_sges = 1; - } - /* hide the extra WQE */ - parms.squeue.act_nr_wqes--; - break; - case IB_QPT_UD: - case IB_QPT_GSI: - case IB_QPT_SMI: - /* UD circumvention */ - if (is_llqp) { - parms.squeue.act_nr_sges = 1; - parms.rqueue.act_nr_sges = 1; - } else { - parms.squeue.act_nr_sges -= 2; - parms.rqueue.act_nr_sges -= 2; - } - - if (IB_QPT_GSI == qp_type || IB_QPT_SMI == qp_type) { - parms.squeue.act_nr_wqes = init_attr->cap.max_send_wr; - parms.rqueue.act_nr_wqes = init_attr->cap.max_recv_wr; - parms.squeue.act_nr_sges = init_attr->cap.max_send_sge; - parms.rqueue.act_nr_sges = init_attr->cap.max_recv_sge; - ib_qp_num = (qp_type == IB_QPT_SMI) ? 0 : 1; - } - - break; - - default: - break; - } - - /* initialize r/squeue and register queue pages */ - if (HAS_SQ(my_qp)) { - ret = init_qp_queue( - shca, my_pd, my_qp, &my_qp->ipz_squeue, 0, - HAS_RQ(my_qp) ? H_PAGE_REGISTERED : H_SUCCESS, - &parms.squeue, swqe_size); - if (ret) { - ehca_err(pd->device, "Couldn't initialize squeue " - "and pages ret=%i", ret); - goto create_qp_exit2; - } - - if (!is_user) { - my_qp->sq_map.entries = my_qp->ipz_squeue.queue_length / - my_qp->ipz_squeue.qe_size; - my_qp->sq_map.map = vmalloc(my_qp->sq_map.entries * - sizeof(struct ehca_qmap_entry)); - if (!my_qp->sq_map.map) { - ehca_err(pd->device, "Couldn't allocate squeue " - "map ret=%i", ret); - goto create_qp_exit3; - } - INIT_LIST_HEAD(&my_qp->sq_err_node); - /* to avoid the generation of bogus flush CQEs */ - reset_queue_map(&my_qp->sq_map); - } - } - - if (HAS_RQ(my_qp)) { - ret = init_qp_queue( - shca, my_pd, my_qp, &my_qp->ipz_rqueue, 1, - H_SUCCESS, &parms.rqueue, rwqe_size); - if (ret) { - ehca_err(pd->device, "Couldn't initialize rqueue " - "and pages ret=%i", ret); - goto create_qp_exit4; - } - if (!is_user) { - my_qp->rq_map.entries = my_qp->ipz_rqueue.queue_length / - my_qp->ipz_rqueue.qe_size; - my_qp->rq_map.map = vmalloc(my_qp->rq_map.entries * - sizeof(struct ehca_qmap_entry)); - if (!my_qp->rq_map.map) { - ehca_err(pd->device, "Couldn't allocate squeue " - "map ret=%i", ret); - goto create_qp_exit5; - } - INIT_LIST_HEAD(&my_qp->rq_err_node); - /* to avoid the generation of bogus flush CQEs */ - reset_queue_map(&my_qp->rq_map); - } - } else if (init_attr->srq && !is_user) { - /* this is a base QP, use the queue map of the SRQ */ - my_qp->rq_map = my_srq->rq_map; - INIT_LIST_HEAD(&my_qp->rq_err_node); - - my_qp->ipz_rqueue = my_srq->ipz_rqueue; - } - - if (is_srq) { - my_qp->ib_srq.pd = &my_pd->ib_pd; - my_qp->ib_srq.device = my_pd->ib_pd.device; - - my_qp->ib_srq.srq_context = init_attr->qp_context; - my_qp->ib_srq.event_handler = init_attr->event_handler; - } else { - my_qp->ib_qp.qp_num = ib_qp_num; - my_qp->ib_qp.pd = &my_pd->ib_pd; - my_qp->ib_qp.device = my_pd->ib_pd.device; - - my_qp->ib_qp.recv_cq = init_attr->recv_cq; - my_qp->ib_qp.send_cq = init_attr->send_cq; - - my_qp->ib_qp.qp_type = qp_type; - my_qp->ib_qp.srq = init_attr->srq; - - my_qp->ib_qp.qp_context = init_attr->qp_context; - my_qp->ib_qp.event_handler = init_attr->event_handler; - } - - init_attr->cap.max_inline_data = 0; /* not supported yet */ - init_attr->cap.max_recv_sge = parms.rqueue.act_nr_sges; - init_attr->cap.max_recv_wr = parms.rqueue.act_nr_wqes; - init_attr->cap.max_send_sge = parms.squeue.act_nr_sges; - init_attr->cap.max_send_wr = parms.squeue.act_nr_wqes; - my_qp->init_attr = *init_attr; - - if (qp_type == IB_QPT_SMI || qp_type == IB_QPT_GSI) { - shca->sport[init_attr->port_num - 1].ibqp_sqp[qp_type] = - &my_qp->ib_qp; - if (ehca_nr_ports < 0) { - /* alloc array to cache subsequent modify qp parms - * for autodetect mode - */ - my_qp->mod_qp_parm = - kzalloc(EHCA_MOD_QP_PARM_MAX * - sizeof(*my_qp->mod_qp_parm), - GFP_KERNEL); - if (!my_qp->mod_qp_parm) { - ehca_err(pd->device, - "Could not alloc mod_qp_parm"); - goto create_qp_exit5; - } - } - } - - /* NOTE: define_apq0() not supported yet */ - if (qp_type == IB_QPT_GSI) { - h_ret = ehca_define_sqp(shca, my_qp, init_attr); - if (h_ret != H_SUCCESS) { - kfree(my_qp->mod_qp_parm); - my_qp->mod_qp_parm = NULL; - /* the QP pointer is no longer valid */ - shca->sport[init_attr->port_num - 1].ibqp_sqp[qp_type] = - NULL; - ret = ehca2ib_return_code(h_ret); - goto create_qp_exit6; - } - } - - if (my_qp->send_cq) { - ret = ehca_cq_assign_qp(my_qp->send_cq, my_qp); - if (ret) { - ehca_err(pd->device, - "Couldn't assign qp to send_cq ret=%i", ret); - goto create_qp_exit7; - } - } - - /* copy queues, galpa data to user space */ - if (context && udata) { - struct ehca_create_qp_resp resp; - memset(&resp, 0, sizeof(resp)); - - resp.qp_num = my_qp->real_qp_num; - resp.token = my_qp->token; - resp.qp_type = my_qp->qp_type; - resp.ext_type = my_qp->ext_type; - resp.qkey = my_qp->qkey; - resp.real_qp_num = my_qp->real_qp_num; - - if (HAS_SQ(my_qp)) - queue2resp(&resp.ipz_squeue, &my_qp->ipz_squeue); - if (HAS_RQ(my_qp)) - queue2resp(&resp.ipz_rqueue, &my_qp->ipz_rqueue); - resp.fw_handle_ofs = (u32) - (my_qp->galpas.user.fw_handle & (PAGE_SIZE - 1)); - - if (ib_copy_to_udata(udata, &resp, sizeof resp)) { - ehca_err(pd->device, "Copy to udata failed"); - ret = -EINVAL; - goto create_qp_exit8; - } - } - - return my_qp; - -create_qp_exit8: - ehca_cq_unassign_qp(my_qp->send_cq, my_qp->real_qp_num); - -create_qp_exit7: - kfree(my_qp->mod_qp_parm); - -create_qp_exit6: - if (HAS_RQ(my_qp) && !is_user) - vfree(my_qp->rq_map.map); - -create_qp_exit5: - if (HAS_RQ(my_qp)) - ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue); - -create_qp_exit4: - if (HAS_SQ(my_qp) && !is_user) - vfree(my_qp->sq_map.map); - -create_qp_exit3: - if (HAS_SQ(my_qp)) - ipz_queue_dtor(my_pd, &my_qp->ipz_squeue); - -create_qp_exit2: - hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp); - -create_qp_exit1: - write_lock_irqsave(&ehca_qp_idr_lock, flags); - idr_remove(&ehca_qp_idr, my_qp->token); - write_unlock_irqrestore(&ehca_qp_idr_lock, flags); - -create_qp_exit0: - kmem_cache_free(qp_cache, my_qp); - atomic_dec(&shca->num_qps); - return ERR_PTR(ret); -} - -struct ib_qp *ehca_create_qp(struct ib_pd *pd, - struct ib_qp_init_attr *qp_init_attr, - struct ib_udata *udata) -{ - struct ehca_qp *ret; - - ret = internal_create_qp(pd, qp_init_attr, NULL, udata, 0); - return IS_ERR(ret) ? (struct ib_qp *)ret : &ret->ib_qp; -} - -static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp, - struct ib_uobject *uobject); - -struct ib_srq *ehca_create_srq(struct ib_pd *pd, - struct ib_srq_init_attr *srq_init_attr, - struct ib_udata *udata) -{ - struct ib_qp_init_attr qp_init_attr; - struct ehca_qp *my_qp; - struct ib_srq *ret; - struct ehca_shca *shca = container_of(pd->device, struct ehca_shca, - ib_device); - struct hcp_modify_qp_control_block *mqpcb; - u64 hret, update_mask; - - if (srq_init_attr->srq_type != IB_SRQT_BASIC) - return ERR_PTR(-ENOSYS); - - /* For common attributes, internal_create_qp() takes its info - * out of qp_init_attr, so copy all common attrs there. - */ - memset(&qp_init_attr, 0, sizeof(qp_init_attr)); - qp_init_attr.event_handler = srq_init_attr->event_handler; - qp_init_attr.qp_context = srq_init_attr->srq_context; - qp_init_attr.sq_sig_type = IB_SIGNAL_ALL_WR; - qp_init_attr.qp_type = IB_QPT_RC; - qp_init_attr.cap.max_recv_wr = srq_init_attr->attr.max_wr; - qp_init_attr.cap.max_recv_sge = srq_init_attr->attr.max_sge; - - my_qp = internal_create_qp(pd, &qp_init_attr, srq_init_attr, udata, 1); - if (IS_ERR(my_qp)) - return (struct ib_srq *)my_qp; - - /* copy back return values */ - srq_init_attr->attr.max_wr = qp_init_attr.cap.max_recv_wr; - srq_init_attr->attr.max_sge = 3; - - /* drive SRQ into RTR state */ - mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL); - if (!mqpcb) { - ehca_err(pd->device, "Could not get zeroed page for mqpcb " - "ehca_qp=%p qp_num=%x ", my_qp, my_qp->real_qp_num); - ret = ERR_PTR(-ENOMEM); - goto create_srq1; - } - - mqpcb->qp_state = EHCA_QPS_INIT; - mqpcb->prim_phys_port = 1; - update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1); - hret = hipz_h_modify_qp(shca->ipz_hca_handle, - my_qp->ipz_qp_handle, - &my_qp->pf, - update_mask, - mqpcb, my_qp->galpas.kernel); - if (hret != H_SUCCESS) { - ehca_err(pd->device, "Could not modify SRQ to INIT " - "ehca_qp=%p qp_num=%x h_ret=%lli", - my_qp, my_qp->real_qp_num, hret); - goto create_srq2; - } - - mqpcb->qp_enable = 1; - update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_ENABLE, 1); - hret = hipz_h_modify_qp(shca->ipz_hca_handle, - my_qp->ipz_qp_handle, - &my_qp->pf, - update_mask, - mqpcb, my_qp->galpas.kernel); - if (hret != H_SUCCESS) { - ehca_err(pd->device, "Could not enable SRQ " - "ehca_qp=%p qp_num=%x h_ret=%lli", - my_qp, my_qp->real_qp_num, hret); - goto create_srq2; - } - - mqpcb->qp_state = EHCA_QPS_RTR; - update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1); - hret = hipz_h_modify_qp(shca->ipz_hca_handle, - my_qp->ipz_qp_handle, - &my_qp->pf, - update_mask, - mqpcb, my_qp->galpas.kernel); - if (hret != H_SUCCESS) { - ehca_err(pd->device, "Could not modify SRQ to RTR " - "ehca_qp=%p qp_num=%x h_ret=%lli", - my_qp, my_qp->real_qp_num, hret); - goto create_srq2; - } - - ehca_free_fw_ctrlblock(mqpcb); - - return &my_qp->ib_srq; - -create_srq2: - ret = ERR_PTR(ehca2ib_return_code(hret)); - ehca_free_fw_ctrlblock(mqpcb); - -create_srq1: - internal_destroy_qp(pd->device, my_qp, my_qp->ib_srq.uobject); - - return ret; -} - -/* - * prepare_sqe_rts called by internal_modify_qp() at trans sqe -> rts - * set purge bit of bad wqe and subsequent wqes to avoid reentering sqe - * returns total number of bad wqes in bad_wqe_cnt - */ -static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca, - int *bad_wqe_cnt) -{ - u64 h_ret; - struct ipz_queue *squeue; - void *bad_send_wqe_p, *bad_send_wqe_v; - u64 q_ofs; - struct ehca_wqe *wqe; - int qp_num = my_qp->ib_qp.qp_num; - - /* get send wqe pointer */ - h_ret = hipz_h_disable_and_get_wqe(shca->ipz_hca_handle, - my_qp->ipz_qp_handle, &my_qp->pf, - &bad_send_wqe_p, NULL, 2); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "hipz_h_disable_and_get_wqe() failed" - " ehca_qp=%p qp_num=%x h_ret=%lli", - my_qp, qp_num, h_ret); - return ehca2ib_return_code(h_ret); - } - bad_send_wqe_p = (void *)((u64)bad_send_wqe_p & (~(1L << 63))); - ehca_dbg(&shca->ib_device, "qp_num=%x bad_send_wqe_p=%p", - qp_num, bad_send_wqe_p); - /* convert wqe pointer to vadr */ - bad_send_wqe_v = __va((u64)bad_send_wqe_p); - if (ehca_debug_level >= 2) - ehca_dmp(bad_send_wqe_v, 32, "qp_num=%x bad_wqe", qp_num); - squeue = &my_qp->ipz_squeue; - if (ipz_queue_abs_to_offset(squeue, (u64)bad_send_wqe_p, &q_ofs)) { - ehca_err(&shca->ib_device, "failed to get wqe offset qp_num=%x" - " bad_send_wqe_p=%p", qp_num, bad_send_wqe_p); - return -EFAULT; - } - - /* loop sets wqe's purge bit */ - wqe = (struct ehca_wqe *)ipz_qeit_calc(squeue, q_ofs); - *bad_wqe_cnt = 0; - while (wqe->optype != 0xff && wqe->wqef != 0xff) { - if (ehca_debug_level >= 2) - ehca_dmp(wqe, 32, "qp_num=%x wqe", qp_num); - wqe->nr_of_data_seg = 0; /* suppress data access */ - wqe->wqef = WQEF_PURGE; /* WQE to be purged */ - q_ofs = ipz_queue_advance_offset(squeue, q_ofs); - wqe = (struct ehca_wqe *)ipz_qeit_calc(squeue, q_ofs); - *bad_wqe_cnt = (*bad_wqe_cnt)+1; - } - /* - * bad wqe will be reprocessed and ignored when pol_cq() is called, - * i.e. nr of wqes with flush error status is one less - */ - ehca_dbg(&shca->ib_device, "qp_num=%x flusherr_wqe_cnt=%x", - qp_num, (*bad_wqe_cnt)-1); - wqe->wqef = 0; - - return 0; -} - -static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue, - struct ehca_queue_map *qmap) -{ - void *wqe_v; - u64 q_ofs; - u32 wqe_idx; - unsigned int tail_idx; - - /* convert real to abs address */ - wqe_p = wqe_p & (~(1UL << 63)); - - wqe_v = __va(wqe_p); - - if (ipz_queue_abs_to_offset(ipz_queue, wqe_p, &q_ofs)) { - ehca_gen_err("Invalid offset for calculating left cqes " - "wqe_p=%#llx wqe_v=%p\n", wqe_p, wqe_v); - return -EFAULT; - } - - tail_idx = next_index(qmap->tail, qmap->entries); - wqe_idx = q_ofs / ipz_queue->qe_size; - - /* check all processed wqes, whether a cqe is requested or not */ - while (tail_idx != wqe_idx) { - if (qmap->map[tail_idx].cqe_req) - qmap->left_to_poll++; - tail_idx = next_index(tail_idx, qmap->entries); - } - /* save index in queue, where we have to start flushing */ - qmap->next_wqe_idx = wqe_idx; - return 0; -} - -static int check_for_left_cqes(struct ehca_qp *my_qp, struct ehca_shca *shca) -{ - u64 h_ret; - void *send_wqe_p, *recv_wqe_p; - int ret; - unsigned long flags; - int qp_num = my_qp->ib_qp.qp_num; - - /* this hcall is not supported on base QPs */ - if (my_qp->ext_type != EQPT_SRQBASE) { - /* get send and receive wqe pointer */ - h_ret = hipz_h_disable_and_get_wqe(shca->ipz_hca_handle, - my_qp->ipz_qp_handle, &my_qp->pf, - &send_wqe_p, &recv_wqe_p, 4); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "disable_and_get_wqe() " - "failed ehca_qp=%p qp_num=%x h_ret=%lli", - my_qp, qp_num, h_ret); - return ehca2ib_return_code(h_ret); - } - - /* - * acquire lock to ensure that nobody is polling the cq which - * could mean that the qmap->tail pointer is in an - * inconsistent state. - */ - spin_lock_irqsave(&my_qp->send_cq->spinlock, flags); - ret = calc_left_cqes((u64)send_wqe_p, &my_qp->ipz_squeue, - &my_qp->sq_map); - spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags); - if (ret) - return ret; - - - spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags); - ret = calc_left_cqes((u64)recv_wqe_p, &my_qp->ipz_rqueue, - &my_qp->rq_map); - spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags); - if (ret) - return ret; - } else { - spin_lock_irqsave(&my_qp->send_cq->spinlock, flags); - my_qp->sq_map.left_to_poll = 0; - my_qp->sq_map.next_wqe_idx = next_index(my_qp->sq_map.tail, - my_qp->sq_map.entries); - spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags); - - spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags); - my_qp->rq_map.left_to_poll = 0; - my_qp->rq_map.next_wqe_idx = next_index(my_qp->rq_map.tail, - my_qp->rq_map.entries); - spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags); - } - - /* this assures flush cqes being generated only for pending wqes */ - if ((my_qp->sq_map.left_to_poll == 0) && - (my_qp->rq_map.left_to_poll == 0)) { - spin_lock_irqsave(&my_qp->send_cq->spinlock, flags); - ehca_add_to_err_list(my_qp, 1); - spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags); - - if (HAS_RQ(my_qp)) { - spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags); - ehca_add_to_err_list(my_qp, 0); - spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, - flags); - } - } - - return 0; -} - -/* - * internal_modify_qp with circumvention to handle aqp0 properly - * smi_reset2init indicates if this is an internal reset-to-init-call for - * smi. This flag must always be zero if called from ehca_modify_qp()! - * This internal func was intorduced to avoid recursion of ehca_modify_qp()! - */ -static int internal_modify_qp(struct ib_qp *ibqp, - struct ib_qp_attr *attr, - int attr_mask, int smi_reset2init) -{ - enum ib_qp_state qp_cur_state, qp_new_state; - int cnt, qp_attr_idx, ret = 0; - enum ib_qp_statetrans statetrans; - struct hcp_modify_qp_control_block *mqpcb; - struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); - struct ehca_shca *shca = - container_of(ibqp->pd->device, struct ehca_shca, ib_device); - u64 update_mask; - u64 h_ret; - int bad_wqe_cnt = 0; - int is_user = 0; - int squeue_locked = 0; - unsigned long flags = 0; - - /* do query_qp to obtain current attr values */ - mqpcb = ehca_alloc_fw_ctrlblock(GFP_ATOMIC); - if (!mqpcb) { - ehca_err(ibqp->device, "Could not get zeroed page for mqpcb " - "ehca_qp=%p qp_num=%x ", my_qp, ibqp->qp_num); - return -ENOMEM; - } - - h_ret = hipz_h_query_qp(shca->ipz_hca_handle, - my_qp->ipz_qp_handle, - &my_qp->pf, - mqpcb, my_qp->galpas.kernel); - if (h_ret != H_SUCCESS) { - ehca_err(ibqp->device, "hipz_h_query_qp() failed " - "ehca_qp=%p qp_num=%x h_ret=%lli", - my_qp, ibqp->qp_num, h_ret); - ret = ehca2ib_return_code(h_ret); - goto modify_qp_exit1; - } - if (ibqp->uobject) - is_user = 1; - - qp_cur_state = ehca2ib_qp_state(mqpcb->qp_state); - - if (qp_cur_state == -EINVAL) { /* invalid qp state */ - ret = -EINVAL; - ehca_err(ibqp->device, "Invalid current ehca_qp_state=%x " - "ehca_qp=%p qp_num=%x", - mqpcb->qp_state, my_qp, ibqp->qp_num); - goto modify_qp_exit1; - } - /* - * circumvention to set aqp0 initial state to init - * as expected by IB spec - */ - if (smi_reset2init == 0 && - ibqp->qp_type == IB_QPT_SMI && - qp_cur_state == IB_QPS_RESET && - (attr_mask & IB_QP_STATE) && - attr->qp_state == IB_QPS_INIT) { /* RESET -> INIT */ - struct ib_qp_attr smiqp_attr = { - .qp_state = IB_QPS_INIT, - .port_num = my_qp->init_attr.port_num, - .pkey_index = 0, - .qkey = 0 - }; - int smiqp_attr_mask = IB_QP_STATE | IB_QP_PORT | - IB_QP_PKEY_INDEX | IB_QP_QKEY; - int smirc = internal_modify_qp( - ibqp, &smiqp_attr, smiqp_attr_mask, 1); - if (smirc) { - ehca_err(ibqp->device, "SMI RESET -> INIT failed. " - "ehca_modify_qp() rc=%i", smirc); - ret = H_PARAMETER; - goto modify_qp_exit1; - } - qp_cur_state = IB_QPS_INIT; - ehca_dbg(ibqp->device, "SMI RESET -> INIT succeeded"); - } - /* is transmitted current state equal to "real" current state */ - if ((attr_mask & IB_QP_CUR_STATE) && - qp_cur_state != attr->cur_qp_state) { - ret = -EINVAL; - ehca_err(ibqp->device, - "Invalid IB_QP_CUR_STATE attr->curr_qp_state=%x <>" - " actual cur_qp_state=%x. ehca_qp=%p qp_num=%x", - attr->cur_qp_state, qp_cur_state, my_qp, ibqp->qp_num); - goto modify_qp_exit1; - } - - ehca_dbg(ibqp->device, "ehca_qp=%p qp_num=%x current qp_state=%x " - "new qp_state=%x attribute_mask=%x", - my_qp, ibqp->qp_num, qp_cur_state, attr->qp_state, attr_mask); - - qp_new_state = attr_mask & IB_QP_STATE ? attr->qp_state : qp_cur_state; - if (!smi_reset2init && - !ib_modify_qp_is_ok(qp_cur_state, qp_new_state, ibqp->qp_type, - attr_mask, IB_LINK_LAYER_UNSPECIFIED)) { - ret = -EINVAL; - ehca_err(ibqp->device, - "Invalid qp transition new_state=%x cur_state=%x " - "ehca_qp=%p qp_num=%x attr_mask=%x", qp_new_state, - qp_cur_state, my_qp, ibqp->qp_num, attr_mask); - goto modify_qp_exit1; - } - - mqpcb->qp_state = ib2ehca_qp_state(qp_new_state); - if (mqpcb->qp_state) - update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1); - else { - ret = -EINVAL; - ehca_err(ibqp->device, "Invalid new qp state=%x " - "ehca_qp=%p qp_num=%x", - qp_new_state, my_qp, ibqp->qp_num); - goto modify_qp_exit1; - } - - /* retrieve state transition struct to get req and opt attrs */ - statetrans = get_modqp_statetrans(qp_cur_state, qp_new_state); - if (statetrans < 0) { - ret = -EINVAL; - ehca_err(ibqp->device, " qp_cur_state=%x " - "new_qp_state=%x State_xsition=%x ehca_qp=%p " - "qp_num=%x", qp_cur_state, qp_new_state, - statetrans, my_qp, ibqp->qp_num); - goto modify_qp_exit1; - } - - qp_attr_idx = ib2ehcaqptype(ibqp->qp_type); - - if (qp_attr_idx < 0) { - ret = qp_attr_idx; - ehca_err(ibqp->device, - "Invalid QP type=%x ehca_qp=%p qp_num=%x", - ibqp->qp_type, my_qp, ibqp->qp_num); - goto modify_qp_exit1; - } - - ehca_dbg(ibqp->device, - "ehca_qp=%p qp_num=%x qp_state_xsit=%x", - my_qp, ibqp->qp_num, statetrans); - - /* eHCA2 rev2 and higher require the SEND_GRH_FLAG to be set - * in non-LL UD QPs. - */ - if ((my_qp->qp_type == IB_QPT_UD) && - (my_qp->ext_type != EQPT_LLQP) && - (statetrans == IB_QPST_INIT2RTR) && - (shca->hw_level >= 0x22)) { - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1); - mqpcb->send_grh_flag = 1; - } - - /* sqe -> rts: set purge bit of bad wqe before actual trans */ - if ((my_qp->qp_type == IB_QPT_UD || - my_qp->qp_type == IB_QPT_GSI || - my_qp->qp_type == IB_QPT_SMI) && - statetrans == IB_QPST_SQE2RTS) { - /* mark next free wqe if kernel */ - if (!ibqp->uobject) { - struct ehca_wqe *wqe; - /* lock send queue */ - spin_lock_irqsave(&my_qp->spinlock_s, flags); - squeue_locked = 1; - /* mark next free wqe */ - wqe = (struct ehca_wqe *) - ipz_qeit_get(&my_qp->ipz_squeue); - wqe->optype = wqe->wqef = 0xff; - ehca_dbg(ibqp->device, "qp_num=%x next_free_wqe=%p", - ibqp->qp_num, wqe); - } - ret = prepare_sqe_rts(my_qp, shca, &bad_wqe_cnt); - if (ret) { - ehca_err(ibqp->device, "prepare_sqe_rts() failed " - "ehca_qp=%p qp_num=%x ret=%i", - my_qp, ibqp->qp_num, ret); - goto modify_qp_exit2; - } - } - - /* - * enable RDMA_Atomic_Control if reset->init und reliable con - * this is necessary since gen2 does not provide that flag, - * but pHyp requires it - */ - if (statetrans == IB_QPST_RESET2INIT && - (ibqp->qp_type == IB_QPT_RC || ibqp->qp_type == IB_QPT_UC)) { - mqpcb->rdma_atomic_ctrl = 3; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RDMA_ATOMIC_CTRL, 1); - } - /* circ. pHyp requires #RDMA/Atomic Resp Res for UC INIT -> RTR */ - if (statetrans == IB_QPST_INIT2RTR && - (ibqp->qp_type == IB_QPT_UC) && - !(attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)) { - mqpcb->rdma_nr_atomic_resp_res = 1; /* default to 1 */ - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES, 1); - } - - if (attr_mask & IB_QP_PKEY_INDEX) { - if (attr->pkey_index >= 16) { - ret = -EINVAL; - ehca_err(ibqp->device, "Invalid pkey_index=%x. " - "ehca_qp=%p qp_num=%x max_pkey_index=f", - attr->pkey_index, my_qp, ibqp->qp_num); - goto modify_qp_exit2; - } - mqpcb->prim_p_key_idx = attr->pkey_index; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_P_KEY_IDX, 1); - } - if (attr_mask & IB_QP_PORT) { - struct ehca_sport *sport; - struct ehca_qp *aqp1; - if (attr->port_num < 1 || attr->port_num > shca->num_ports) { - ret = -EINVAL; - ehca_err(ibqp->device, "Invalid port=%x. " - "ehca_qp=%p qp_num=%x num_ports=%x", - attr->port_num, my_qp, ibqp->qp_num, - shca->num_ports); - goto modify_qp_exit2; - } - sport = &shca->sport[attr->port_num - 1]; - if (!sport->ibqp_sqp[IB_QPT_GSI]) { - /* should not occur */ - ret = -EFAULT; - ehca_err(ibqp->device, "AQP1 was not created for " - "port=%x", attr->port_num); - goto modify_qp_exit2; - } - aqp1 = container_of(sport->ibqp_sqp[IB_QPT_GSI], - struct ehca_qp, ib_qp); - if (ibqp->qp_type != IB_QPT_GSI && - ibqp->qp_type != IB_QPT_SMI && - aqp1->mod_qp_parm) { - /* - * firmware will reject this modify_qp() because - * port is not activated/initialized fully - */ - ret = -EFAULT; - ehca_warn(ibqp->device, "Couldn't modify qp port=%x: " - "either port is being activated (try again) " - "or cabling issue", attr->port_num); - goto modify_qp_exit2; - } - mqpcb->prim_phys_port = attr->port_num; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_PHYS_PORT, 1); - } - if (attr_mask & IB_QP_QKEY) { - mqpcb->qkey = attr->qkey; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_QKEY, 1); - } - if (attr_mask & IB_QP_AV) { - mqpcb->dlid = attr->ah_attr.dlid; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DLID, 1); - mqpcb->source_path_bits = attr->ah_attr.src_path_bits; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SOURCE_PATH_BITS, 1); - mqpcb->service_level = attr->ah_attr.sl; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL, 1); - - if (ehca_calc_ipd(shca, mqpcb->prim_phys_port, - attr->ah_attr.static_rate, - &mqpcb->max_static_rate)) { - ret = -EINVAL; - goto modify_qp_exit2; - } - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE, 1); - - /* - * Always supply the GRH flag, even if it's zero, to give the - * hypervisor a clear "yes" or "no" instead of a "perhaps" - */ - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1); - - /* - * only if GRH is TRUE we might consider SOURCE_GID_IDX - * and DEST_GID otherwise phype will return H_ATTR_PARM!!! - */ - if (attr->ah_attr.ah_flags == IB_AH_GRH) { - mqpcb->send_grh_flag = 1; - - mqpcb->source_gid_idx = attr->ah_attr.grh.sgid_index; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_SOURCE_GID_IDX, 1); - - for (cnt = 0; cnt < 16; cnt++) - mqpcb->dest_gid.byte[cnt] = - attr->ah_attr.grh.dgid.raw[cnt]; - - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DEST_GID, 1); - mqpcb->flow_label = attr->ah_attr.grh.flow_label; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_FLOW_LABEL, 1); - mqpcb->hop_limit = attr->ah_attr.grh.hop_limit; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_HOP_LIMIT, 1); - mqpcb->traffic_class = attr->ah_attr.grh.traffic_class; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_TRAFFIC_CLASS, 1); - } - } - - if (attr_mask & IB_QP_PATH_MTU) { - /* store ld(MTU) */ - my_qp->mtu_shift = attr->path_mtu + 7; - mqpcb->path_mtu = attr->path_mtu; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PATH_MTU, 1); - } - if (attr_mask & IB_QP_TIMEOUT) { - mqpcb->timeout = attr->timeout; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_TIMEOUT, 1); - } - if (attr_mask & IB_QP_RETRY_CNT) { - mqpcb->retry_count = attr->retry_cnt; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RETRY_COUNT, 1); - } - if (attr_mask & IB_QP_RNR_RETRY) { - mqpcb->rnr_retry_count = attr->rnr_retry; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RNR_RETRY_COUNT, 1); - } - if (attr_mask & IB_QP_RQ_PSN) { - mqpcb->receive_psn = attr->rq_psn; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RECEIVE_PSN, 1); - } - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) { - mqpcb->rdma_nr_atomic_resp_res = attr->max_dest_rd_atomic < 3 ? - attr->max_dest_rd_atomic : 2; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES, 1); - } - if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) { - mqpcb->rdma_atomic_outst_dest_qp = attr->max_rd_atomic < 3 ? - attr->max_rd_atomic : 2; - update_mask |= - EHCA_BMASK_SET - (MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP, 1); - } - if (attr_mask & IB_QP_ALT_PATH) { - if (attr->alt_port_num < 1 - || attr->alt_port_num > shca->num_ports) { - ret = -EINVAL; - ehca_err(ibqp->device, "Invalid alt_port=%x. " - "ehca_qp=%p qp_num=%x num_ports=%x", - attr->alt_port_num, my_qp, ibqp->qp_num, - shca->num_ports); - goto modify_qp_exit2; - } - mqpcb->alt_phys_port = attr->alt_port_num; - - if (attr->alt_pkey_index >= 16) { - ret = -EINVAL; - ehca_err(ibqp->device, "Invalid alt_pkey_index=%x. " - "ehca_qp=%p qp_num=%x max_pkey_index=f", - attr->pkey_index, my_qp, ibqp->qp_num); - goto modify_qp_exit2; - } - mqpcb->alt_p_key_idx = attr->alt_pkey_index; - - mqpcb->timeout_al = attr->alt_timeout; - mqpcb->dlid_al = attr->alt_ah_attr.dlid; - mqpcb->source_path_bits_al = attr->alt_ah_attr.src_path_bits; - mqpcb->service_level_al = attr->alt_ah_attr.sl; - - if (ehca_calc_ipd(shca, mqpcb->alt_phys_port, - attr->alt_ah_attr.static_rate, - &mqpcb->max_static_rate_al)) { - ret = -EINVAL; - goto modify_qp_exit2; - } - - /* OpenIB doesn't support alternate retry counts - copy them */ - mqpcb->retry_count_al = mqpcb->retry_count; - mqpcb->rnr_retry_count_al = mqpcb->rnr_retry_count; - - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_ALT_PHYS_PORT, 1) - | EHCA_BMASK_SET(MQPCB_MASK_ALT_P_KEY_IDX, 1) - | EHCA_BMASK_SET(MQPCB_MASK_TIMEOUT_AL, 1) - | EHCA_BMASK_SET(MQPCB_MASK_DLID_AL, 1) - | EHCA_BMASK_SET(MQPCB_MASK_SOURCE_PATH_BITS_AL, 1) - | EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL_AL, 1) - | EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE_AL, 1) - | EHCA_BMASK_SET(MQPCB_MASK_RETRY_COUNT_AL, 1) - | EHCA_BMASK_SET(MQPCB_MASK_RNR_RETRY_COUNT_AL, 1); - - /* - * Always supply the GRH flag, even if it's zero, to give the - * hypervisor a clear "yes" or "no" instead of a "perhaps" - */ - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG_AL, 1); - - /* - * only if GRH is TRUE we might consider SOURCE_GID_IDX - * and DEST_GID otherwise phype will return H_ATTR_PARM!!! - */ - if (attr->alt_ah_attr.ah_flags == IB_AH_GRH) { - mqpcb->send_grh_flag_al = 1; - - for (cnt = 0; cnt < 16; cnt++) - mqpcb->dest_gid_al.byte[cnt] = - attr->alt_ah_attr.grh.dgid.raw[cnt]; - mqpcb->source_gid_idx_al = - attr->alt_ah_attr.grh.sgid_index; - mqpcb->flow_label_al = attr->alt_ah_attr.grh.flow_label; - mqpcb->hop_limit_al = attr->alt_ah_attr.grh.hop_limit; - mqpcb->traffic_class_al = - attr->alt_ah_attr.grh.traffic_class; - - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_SOURCE_GID_IDX_AL, 1) - | EHCA_BMASK_SET(MQPCB_MASK_DEST_GID_AL, 1) - | EHCA_BMASK_SET(MQPCB_MASK_FLOW_LABEL_AL, 1) - | EHCA_BMASK_SET(MQPCB_MASK_HOP_LIMIT_AL, 1) | - EHCA_BMASK_SET(MQPCB_MASK_TRAFFIC_CLASS_AL, 1); - } - } - - if (attr_mask & IB_QP_MIN_RNR_TIMER) { - mqpcb->min_rnr_nak_timer_field = attr->min_rnr_timer; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_MIN_RNR_NAK_TIMER_FIELD, 1); - } - - if (attr_mask & IB_QP_SQ_PSN) { - mqpcb->send_psn = attr->sq_psn; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_PSN, 1); - } - - if (attr_mask & IB_QP_DEST_QPN) { - mqpcb->dest_qp_nr = attr->dest_qp_num; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DEST_QP_NR, 1); - } - - if (attr_mask & IB_QP_PATH_MIG_STATE) { - if (attr->path_mig_state != IB_MIG_REARM - && attr->path_mig_state != IB_MIG_MIGRATED) { - ret = -EINVAL; - ehca_err(ibqp->device, "Invalid mig_state=%x", - attr->path_mig_state); - goto modify_qp_exit2; - } - mqpcb->path_migration_state = attr->path_mig_state + 1; - if (attr->path_mig_state == IB_MIG_REARM) - my_qp->mig_armed = 1; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_PATH_MIGRATION_STATE, 1); - } - - if (attr_mask & IB_QP_CAP) { - mqpcb->max_nr_outst_send_wr = attr->cap.max_send_wr+1; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_MAX_NR_OUTST_SEND_WR, 1); - mqpcb->max_nr_outst_recv_wr = attr->cap.max_recv_wr+1; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_MAX_NR_OUTST_RECV_WR, 1); - /* no support for max_send/recv_sge yet */ - } - - if (ehca_debug_level >= 2) - ehca_dmp(mqpcb, 4*70, "qp_num=%x", ibqp->qp_num); - - h_ret = hipz_h_modify_qp(shca->ipz_hca_handle, - my_qp->ipz_qp_handle, - &my_qp->pf, - update_mask, - mqpcb, my_qp->galpas.kernel); - - if (h_ret != H_SUCCESS) { - ret = ehca2ib_return_code(h_ret); - ehca_err(ibqp->device, "hipz_h_modify_qp() failed h_ret=%lli " - "ehca_qp=%p qp_num=%x", h_ret, my_qp, ibqp->qp_num); - goto modify_qp_exit2; - } - - if ((my_qp->qp_type == IB_QPT_UD || - my_qp->qp_type == IB_QPT_GSI || - my_qp->qp_type == IB_QPT_SMI) && - statetrans == IB_QPST_SQE2RTS) { - /* doorbell to reprocessing wqes */ - iosync(); /* serialize GAL register access */ - hipz_update_sqa(my_qp, bad_wqe_cnt-1); - ehca_gen_dbg("doorbell for %x wqes", bad_wqe_cnt); - } - - if (statetrans == IB_QPST_RESET2INIT || - statetrans == IB_QPST_INIT2INIT) { - mqpcb->qp_enable = 1; - mqpcb->qp_state = EHCA_QPS_INIT; - update_mask = 0; - update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_ENABLE, 1); - - h_ret = hipz_h_modify_qp(shca->ipz_hca_handle, - my_qp->ipz_qp_handle, - &my_qp->pf, - update_mask, - mqpcb, - my_qp->galpas.kernel); - - if (h_ret != H_SUCCESS) { - ret = ehca2ib_return_code(h_ret); - ehca_err(ibqp->device, "ENABLE in context of " - "RESET_2_INIT failed! Maybe you didn't get " - "a LID h_ret=%lli ehca_qp=%p qp_num=%x", - h_ret, my_qp, ibqp->qp_num); - goto modify_qp_exit2; - } - } - if ((qp_new_state == IB_QPS_ERR) && (qp_cur_state != IB_QPS_ERR) - && !is_user) { - ret = check_for_left_cqes(my_qp, shca); - if (ret) - goto modify_qp_exit2; - } - - if (statetrans == IB_QPST_ANY2RESET) { - ipz_qeit_reset(&my_qp->ipz_rqueue); - ipz_qeit_reset(&my_qp->ipz_squeue); - - if (qp_cur_state == IB_QPS_ERR && !is_user) { - del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node); - - if (HAS_RQ(my_qp)) - del_from_err_list(my_qp->recv_cq, - &my_qp->rq_err_node); - } - if (!is_user) - reset_queue_map(&my_qp->sq_map); - - if (HAS_RQ(my_qp) && !is_user) - reset_queue_map(&my_qp->rq_map); - } - - if (attr_mask & IB_QP_QKEY) - my_qp->qkey = attr->qkey; - -modify_qp_exit2: - if (squeue_locked) { /* this means: sqe -> rts */ - spin_unlock_irqrestore(&my_qp->spinlock_s, flags); - my_qp->sqerr_purgeflag = 1; - } - -modify_qp_exit1: - ehca_free_fw_ctrlblock(mqpcb); - - return ret; -} - -int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, - struct ib_udata *udata) -{ - int ret = 0; - - struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca, - ib_device); - struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); - - /* The if-block below caches qp_attr to be modified for GSI and SMI - * qps during the initialization by ib_mad. When the respective port - * is activated, ie we got an event PORT_ACTIVE, we'll replay the - * cached modify calls sequence, see ehca_recover_sqs() below. - * Why that is required: - * 1) If one port is connected, older code requires that port one - * to be connected and module option nr_ports=1 to be given by - * user, which is very inconvenient for end user. - * 2) Firmware accepts modify_qp() only if respective port has become - * active. Older code had a wait loop of 30sec create_qp()/ - * define_aqp1(), which is not appropriate in practice. This - * code now removes that wait loop, see define_aqp1(), and always - * reports all ports to ib_mad resp. users. Only activated ports - * will then usable for the users. - */ - if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI) { - int port = my_qp->init_attr.port_num; - struct ehca_sport *sport = &shca->sport[port - 1]; - unsigned long flags; - spin_lock_irqsave(&sport->mod_sqp_lock, flags); - /* cache qp_attr only during init */ - if (my_qp->mod_qp_parm) { - struct ehca_mod_qp_parm *p; - if (my_qp->mod_qp_parm_idx >= EHCA_MOD_QP_PARM_MAX) { - ehca_err(&shca->ib_device, - "mod_qp_parm overflow state=%x port=%x" - " type=%x", attr->qp_state, - my_qp->init_attr.port_num, - ibqp->qp_type); - spin_unlock_irqrestore(&sport->mod_sqp_lock, - flags); - return -EINVAL; - } - p = &my_qp->mod_qp_parm[my_qp->mod_qp_parm_idx]; - p->mask = attr_mask; - p->attr = *attr; - my_qp->mod_qp_parm_idx++; - ehca_dbg(&shca->ib_device, - "Saved qp_attr for state=%x port=%x type=%x", - attr->qp_state, my_qp->init_attr.port_num, - ibqp->qp_type); - spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); - goto out; - } - spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); - } - - ret = internal_modify_qp(ibqp, attr, attr_mask, 0); - -out: - if ((ret == 0) && (attr_mask & IB_QP_STATE)) - my_qp->state = attr->qp_state; - - return ret; -} - -void ehca_recover_sqp(struct ib_qp *sqp) -{ - struct ehca_qp *my_sqp = container_of(sqp, struct ehca_qp, ib_qp); - int port = my_sqp->init_attr.port_num; - struct ib_qp_attr attr; - struct ehca_mod_qp_parm *qp_parm; - int i, qp_parm_idx, ret; - unsigned long flags, wr_cnt; - - if (!my_sqp->mod_qp_parm) - return; - ehca_dbg(sqp->device, "SQP port=%x qp_num=%x", port, sqp->qp_num); - - qp_parm = my_sqp->mod_qp_parm; - qp_parm_idx = my_sqp->mod_qp_parm_idx; - for (i = 0; i < qp_parm_idx; i++) { - attr = qp_parm[i].attr; - ret = internal_modify_qp(sqp, &attr, qp_parm[i].mask, 0); - if (ret) { - ehca_err(sqp->device, "Could not modify SQP port=%x " - "qp_num=%x ret=%x", port, sqp->qp_num, ret); - goto free_qp_parm; - } - ehca_dbg(sqp->device, "SQP port=%x qp_num=%x in state=%x", - port, sqp->qp_num, attr.qp_state); - } - - /* re-trigger posted recv wrs */ - wr_cnt = my_sqp->ipz_rqueue.current_q_offset / - my_sqp->ipz_rqueue.qe_size; - if (wr_cnt) { - spin_lock_irqsave(&my_sqp->spinlock_r, flags); - hipz_update_rqa(my_sqp, wr_cnt); - spin_unlock_irqrestore(&my_sqp->spinlock_r, flags); - ehca_dbg(sqp->device, "doorbell port=%x qp_num=%x wr_cnt=%lx", - port, sqp->qp_num, wr_cnt); - } - -free_qp_parm: - kfree(qp_parm); - /* this prevents subsequent calls to modify_qp() to cache qp_attr */ - my_sqp->mod_qp_parm = NULL; -} - -int ehca_query_qp(struct ib_qp *qp, - struct ib_qp_attr *qp_attr, - int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr) -{ - struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp); - struct ehca_shca *shca = container_of(qp->device, struct ehca_shca, - ib_device); - struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle; - struct hcp_modify_qp_control_block *qpcb; - int cnt, ret = 0; - u64 h_ret; - - if (qp_attr_mask & QP_ATTR_QUERY_NOT_SUPPORTED) { - ehca_err(qp->device, "Invalid attribute mask " - "ehca_qp=%p qp_num=%x qp_attr_mask=%x ", - my_qp, qp->qp_num, qp_attr_mask); - return -EINVAL; - } - - qpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL); - if (!qpcb) { - ehca_err(qp->device, "Out of memory for qpcb " - "ehca_qp=%p qp_num=%x", my_qp, qp->qp_num); - return -ENOMEM; - } - - h_ret = hipz_h_query_qp(adapter_handle, - my_qp->ipz_qp_handle, - &my_qp->pf, - qpcb, my_qp->galpas.kernel); - - if (h_ret != H_SUCCESS) { - ret = ehca2ib_return_code(h_ret); - ehca_err(qp->device, "hipz_h_query_qp() failed " - "ehca_qp=%p qp_num=%x h_ret=%lli", - my_qp, qp->qp_num, h_ret); - goto query_qp_exit1; - } - - qp_attr->cur_qp_state = ehca2ib_qp_state(qpcb->qp_state); - qp_attr->qp_state = qp_attr->cur_qp_state; - - if (qp_attr->cur_qp_state == -EINVAL) { - ret = -EINVAL; - ehca_err(qp->device, "Got invalid ehca_qp_state=%x " - "ehca_qp=%p qp_num=%x", - qpcb->qp_state, my_qp, qp->qp_num); - goto query_qp_exit1; - } - - if (qp_attr->qp_state == IB_QPS_SQD) - qp_attr->sq_draining = 1; - - qp_attr->qkey = qpcb->qkey; - qp_attr->path_mtu = qpcb->path_mtu; - qp_attr->path_mig_state = qpcb->path_migration_state - 1; - qp_attr->rq_psn = qpcb->receive_psn; - qp_attr->sq_psn = qpcb->send_psn; - qp_attr->min_rnr_timer = qpcb->min_rnr_nak_timer_field; - qp_attr->cap.max_send_wr = qpcb->max_nr_outst_send_wr-1; - qp_attr->cap.max_recv_wr = qpcb->max_nr_outst_recv_wr-1; - /* UD_AV CIRCUMVENTION */ - if (my_qp->qp_type == IB_QPT_UD) { - qp_attr->cap.max_send_sge = - qpcb->actual_nr_sges_in_sq_wqe - 2; - qp_attr->cap.max_recv_sge = - qpcb->actual_nr_sges_in_rq_wqe - 2; - } else { - qp_attr->cap.max_send_sge = - qpcb->actual_nr_sges_in_sq_wqe; - qp_attr->cap.max_recv_sge = - qpcb->actual_nr_sges_in_rq_wqe; - } - - qp_attr->cap.max_inline_data = my_qp->sq_max_inline_data_size; - qp_attr->dest_qp_num = qpcb->dest_qp_nr; - - qp_attr->pkey_index = qpcb->prim_p_key_idx; - qp_attr->port_num = qpcb->prim_phys_port; - qp_attr->timeout = qpcb->timeout; - qp_attr->retry_cnt = qpcb->retry_count; - qp_attr->rnr_retry = qpcb->rnr_retry_count; - - qp_attr->alt_pkey_index = qpcb->alt_p_key_idx; - qp_attr->alt_port_num = qpcb->alt_phys_port; - qp_attr->alt_timeout = qpcb->timeout_al; - - qp_attr->max_dest_rd_atomic = qpcb->rdma_nr_atomic_resp_res; - qp_attr->max_rd_atomic = qpcb->rdma_atomic_outst_dest_qp; - - /* primary av */ - qp_attr->ah_attr.sl = qpcb->service_level; - - if (qpcb->send_grh_flag) { - qp_attr->ah_attr.ah_flags = IB_AH_GRH; - } - - qp_attr->ah_attr.static_rate = qpcb->max_static_rate; - qp_attr->ah_attr.dlid = qpcb->dlid; - qp_attr->ah_attr.src_path_bits = qpcb->source_path_bits; - qp_attr->ah_attr.port_num = qp_attr->port_num; - - /* primary GRH */ - qp_attr->ah_attr.grh.traffic_class = qpcb->traffic_class; - qp_attr->ah_attr.grh.hop_limit = qpcb->hop_limit; - qp_attr->ah_attr.grh.sgid_index = qpcb->source_gid_idx; - qp_attr->ah_attr.grh.flow_label = qpcb->flow_label; - - for (cnt = 0; cnt < 16; cnt++) - qp_attr->ah_attr.grh.dgid.raw[cnt] = - qpcb->dest_gid.byte[cnt]; - - /* alternate AV */ - qp_attr->alt_ah_attr.sl = qpcb->service_level_al; - if (qpcb->send_grh_flag_al) { - qp_attr->alt_ah_attr.ah_flags = IB_AH_GRH; - } - - qp_attr->alt_ah_attr.static_rate = qpcb->max_static_rate_al; - qp_attr->alt_ah_attr.dlid = qpcb->dlid_al; - qp_attr->alt_ah_attr.src_path_bits = qpcb->source_path_bits_al; - - /* alternate GRH */ - qp_attr->alt_ah_attr.grh.traffic_class = qpcb->traffic_class_al; - qp_attr->alt_ah_attr.grh.hop_limit = qpcb->hop_limit_al; - qp_attr->alt_ah_attr.grh.sgid_index = qpcb->source_gid_idx_al; - qp_attr->alt_ah_attr.grh.flow_label = qpcb->flow_label_al; - - for (cnt = 0; cnt < 16; cnt++) - qp_attr->alt_ah_attr.grh.dgid.raw[cnt] = - qpcb->dest_gid_al.byte[cnt]; - - /* return init attributes given in ehca_create_qp */ - if (qp_init_attr) - *qp_init_attr = my_qp->init_attr; - - if (ehca_debug_level >= 2) - ehca_dmp(qpcb, 4*70, "qp_num=%x", qp->qp_num); - -query_qp_exit1: - ehca_free_fw_ctrlblock(qpcb); - - return ret; -} - -int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, - enum ib_srq_attr_mask attr_mask, struct ib_udata *udata) -{ - struct ehca_qp *my_qp = - container_of(ibsrq, struct ehca_qp, ib_srq); - struct ehca_shca *shca = - container_of(ibsrq->pd->device, struct ehca_shca, ib_device); - struct hcp_modify_qp_control_block *mqpcb; - u64 update_mask; - u64 h_ret; - int ret = 0; - - mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL); - if (!mqpcb) { - ehca_err(ibsrq->device, "Could not get zeroed page for mqpcb " - "ehca_qp=%p qp_num=%x ", my_qp, my_qp->real_qp_num); - return -ENOMEM; - } - - update_mask = 0; - if (attr_mask & IB_SRQ_LIMIT) { - attr_mask &= ~IB_SRQ_LIMIT; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_CURR_SRQ_LIMIT, 1) - | EHCA_BMASK_SET(MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG, 1); - mqpcb->curr_srq_limit = attr->srq_limit; - mqpcb->qp_aff_asyn_ev_log_reg = - EHCA_BMASK_SET(QPX_AAELOG_RESET_SRQ_LIMIT, 1); - } - - /* by now, all bits in attr_mask should have been cleared */ - if (attr_mask) { - ehca_err(ibsrq->device, "invalid attribute mask bits set " - "attr_mask=%x", attr_mask); - ret = -EINVAL; - goto modify_srq_exit0; - } - - if (ehca_debug_level >= 2) - ehca_dmp(mqpcb, 4*70, "qp_num=%x", my_qp->real_qp_num); - - h_ret = hipz_h_modify_qp(shca->ipz_hca_handle, my_qp->ipz_qp_handle, - NULL, update_mask, mqpcb, - my_qp->galpas.kernel); - - if (h_ret != H_SUCCESS) { - ret = ehca2ib_return_code(h_ret); - ehca_err(ibsrq->device, "hipz_h_modify_qp() failed h_ret=%lli " - "ehca_qp=%p qp_num=%x", - h_ret, my_qp, my_qp->real_qp_num); - } - -modify_srq_exit0: - ehca_free_fw_ctrlblock(mqpcb); - - return ret; -} - -int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr) -{ - struct ehca_qp *my_qp = container_of(srq, struct ehca_qp, ib_srq); - struct ehca_shca *shca = container_of(srq->device, struct ehca_shca, - ib_device); - struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle; - struct hcp_modify_qp_control_block *qpcb; - int ret = 0; - u64 h_ret; - - qpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL); - if (!qpcb) { - ehca_err(srq->device, "Out of memory for qpcb " - "ehca_qp=%p qp_num=%x", my_qp, my_qp->real_qp_num); - return -ENOMEM; - } - - h_ret = hipz_h_query_qp(adapter_handle, my_qp->ipz_qp_handle, - NULL, qpcb, my_qp->galpas.kernel); - - if (h_ret != H_SUCCESS) { - ret = ehca2ib_return_code(h_ret); - ehca_err(srq->device, "hipz_h_query_qp() failed " - "ehca_qp=%p qp_num=%x h_ret=%lli", - my_qp, my_qp->real_qp_num, h_ret); - goto query_srq_exit1; - } - - srq_attr->max_wr = qpcb->max_nr_outst_recv_wr - 1; - srq_attr->max_sge = 3; - srq_attr->srq_limit = qpcb->curr_srq_limit; - - if (ehca_debug_level >= 2) - ehca_dmp(qpcb, 4*70, "qp_num=%x", my_qp->real_qp_num); - -query_srq_exit1: - ehca_free_fw_ctrlblock(qpcb); - - return ret; -} - -static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp, - struct ib_uobject *uobject) -{ - struct ehca_shca *shca = container_of(dev, struct ehca_shca, ib_device); - struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd, - ib_pd); - struct ehca_sport *sport = &shca->sport[my_qp->init_attr.port_num - 1]; - u32 qp_num = my_qp->real_qp_num; - int ret; - u64 h_ret; - u8 port_num; - int is_user = 0; - enum ib_qp_type qp_type; - unsigned long flags; - - if (uobject) { - is_user = 1; - if (my_qp->mm_count_galpa || - my_qp->mm_count_rqueue || my_qp->mm_count_squeue) { - ehca_err(dev, "Resources still referenced in " - "user space qp_num=%x", qp_num); - return -EINVAL; - } - } - - if (my_qp->send_cq) { - ret = ehca_cq_unassign_qp(my_qp->send_cq, qp_num); - if (ret) { - ehca_err(dev, "Couldn't unassign qp from " - "send_cq ret=%i qp_num=%x cq_num=%x", ret, - qp_num, my_qp->send_cq->cq_number); - return ret; - } - } - - write_lock_irqsave(&ehca_qp_idr_lock, flags); - idr_remove(&ehca_qp_idr, my_qp->token); - write_unlock_irqrestore(&ehca_qp_idr_lock, flags); - - /* - * SRQs will never get into an error list and do not have a recv_cq, - * so we need to skip them here. - */ - if (HAS_RQ(my_qp) && !IS_SRQ(my_qp) && !is_user) - del_from_err_list(my_qp->recv_cq, &my_qp->rq_err_node); - - if (HAS_SQ(my_qp) && !is_user) - del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node); - - /* now wait until all pending events have completed */ - wait_event(my_qp->wait_completion, !atomic_read(&my_qp->nr_events)); - - h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp); - if (h_ret != H_SUCCESS) { - ehca_err(dev, "hipz_h_destroy_qp() failed h_ret=%lli " - "ehca_qp=%p qp_num=%x", h_ret, my_qp, qp_num); - return ehca2ib_return_code(h_ret); - } - - port_num = my_qp->init_attr.port_num; - qp_type = my_qp->init_attr.qp_type; - - if (qp_type == IB_QPT_SMI || qp_type == IB_QPT_GSI) { - spin_lock_irqsave(&sport->mod_sqp_lock, flags); - kfree(my_qp->mod_qp_parm); - my_qp->mod_qp_parm = NULL; - shca->sport[port_num - 1].ibqp_sqp[qp_type] = NULL; - spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); - } - - /* no support for IB_QPT_SMI yet */ - if (qp_type == IB_QPT_GSI) { - struct ib_event event; - ehca_info(dev, "device %s: port %x is inactive.", - shca->ib_device.name, port_num); - event.device = &shca->ib_device; - event.event = IB_EVENT_PORT_ERR; - event.element.port_num = port_num; - shca->sport[port_num - 1].port_state = IB_PORT_DOWN; - ib_dispatch_event(&event); - } - - if (HAS_RQ(my_qp)) { - ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue); - if (!is_user) - vfree(my_qp->rq_map.map); - } - if (HAS_SQ(my_qp)) { - ipz_queue_dtor(my_pd, &my_qp->ipz_squeue); - if (!is_user) - vfree(my_qp->sq_map.map); - } - kmem_cache_free(qp_cache, my_qp); - atomic_dec(&shca->num_qps); - return 0; -} - -int ehca_destroy_qp(struct ib_qp *qp) -{ - return internal_destroy_qp(qp->device, - container_of(qp, struct ehca_qp, ib_qp), - qp->uobject); -} - -int ehca_destroy_srq(struct ib_srq *srq) -{ - return internal_destroy_qp(srq->device, - container_of(srq, struct ehca_qp, ib_srq), - srq->uobject); -} - -int ehca_init_qp_cache(void) -{ - qp_cache = kmem_cache_create("ehca_cache_qp", - sizeof(struct ehca_qp), 0, - SLAB_HWCACHE_ALIGN, - NULL); - if (!qp_cache) - return -ENOMEM; - return 0; -} - -void ehca_cleanup_qp_cache(void) -{ - kmem_cache_destroy(qp_cache); -} diff --git a/drivers/staging/rdma/ehca/ehca_reqs.c b/drivers/staging/rdma/ehca/ehca_reqs.c deleted file mode 100644 index 11813b880e16..000000000000 --- a/drivers/staging/rdma/ehca/ehca_reqs.c +++ /dev/null @@ -1,953 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * post_send/recv, poll_cq, req_notify - * - * Authors: Hoang-Nam Nguyen - * Waleri Fomin - * Joachim Fenkes - * Reinhard Ernst - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#include "ehca_classes.h" -#include "ehca_tools.h" -#include "ehca_qes.h" -#include "ehca_iverbs.h" -#include "hcp_if.h" -#include "hipz_fns.h" - -/* in RC traffic, insert an empty RDMA READ every this many packets */ -#define ACK_CIRC_THRESHOLD 2000000 - -static u64 replace_wr_id(u64 wr_id, u16 idx) -{ - u64 ret; - - ret = wr_id & ~QMAP_IDX_MASK; - ret |= idx & QMAP_IDX_MASK; - - return ret; -} - -static u16 get_app_wr_id(u64 wr_id) -{ - return wr_id & QMAP_IDX_MASK; -} - -static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue, - struct ehca_wqe *wqe_p, - struct ib_recv_wr *recv_wr, - u32 rq_map_idx) -{ - u8 cnt_ds; - if (unlikely((recv_wr->num_sge < 0) || - (recv_wr->num_sge > ipz_rqueue->act_nr_of_sg))) { - ehca_gen_err("Invalid number of WQE SGE. " - "num_sqe=%x max_nr_of_sg=%x", - recv_wr->num_sge, ipz_rqueue->act_nr_of_sg); - return -EINVAL; /* invalid SG list length */ - } - - /* clear wqe header until sglist */ - memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list)); - - wqe_p->work_request_id = replace_wr_id(recv_wr->wr_id, rq_map_idx); - wqe_p->nr_of_data_seg = recv_wr->num_sge; - - for (cnt_ds = 0; cnt_ds < recv_wr->num_sge; cnt_ds++) { - wqe_p->u.all_rcv.sg_list[cnt_ds].vaddr = - recv_wr->sg_list[cnt_ds].addr; - wqe_p->u.all_rcv.sg_list[cnt_ds].lkey = - recv_wr->sg_list[cnt_ds].lkey; - wqe_p->u.all_rcv.sg_list[cnt_ds].length = - recv_wr->sg_list[cnt_ds].length; - } - - if (ehca_debug_level >= 3) { - ehca_gen_dbg("RECEIVE WQE written into ipz_rqueue=%p", - ipz_rqueue); - ehca_dmp(wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "recv wqe"); - } - - return 0; -} - -#if defined(DEBUG_GSI_SEND_WR) - -/* need ib_mad struct */ -#include - -static void trace_ud_wr(const struct ib_ud_wr *ud_wr) -{ - int idx; - int j; - while (ud_wr) { - struct ib_mad_hdr *mad_hdr = ud_wrmad_hdr; - struct ib_sge *sge = ud_wr->wr.sg_list; - ehca_gen_dbg("ud_wr#%x wr_id=%lx num_sge=%x " - "send_flags=%x opcode=%x", idx, ud_wr->wr.wr_id, - ud_wr->wr.num_sge, ud_wr->wr.send_flags, - ud_wr->.wr.opcode); - if (mad_hdr) { - ehca_gen_dbg("ud_wr#%x mad_hdr base_version=%x " - "mgmt_class=%x class_version=%x method=%x " - "status=%x class_specific=%x tid=%lx " - "attr_id=%x resv=%x attr_mod=%x", - idx, mad_hdr->base_version, - mad_hdr->mgmt_class, - mad_hdr->class_version, mad_hdr->method, - mad_hdr->status, mad_hdr->class_specific, - mad_hdr->tid, mad_hdr->attr_id, - mad_hdr->resv, - mad_hdr->attr_mod); - } - for (j = 0; j < ud_wr->wr.num_sge; j++) { - u8 *data = __va(sge->addr); - ehca_gen_dbg("ud_wr#%x sge#%x addr=%p length=%x " - "lkey=%x", - idx, j, data, sge->length, sge->lkey); - /* assume length is n*16 */ - ehca_dmp(data, sge->length, "ud_wr#%x sge#%x", - idx, j); - sge++; - } /* eof for j */ - idx++; - ud_wr = ud_wr(ud_wr->wr.next); - } /* eof while ud_wr */ -} - -#endif /* DEBUG_GSI_SEND_WR */ - -static inline int ehca_write_swqe(struct ehca_qp *qp, - struct ehca_wqe *wqe_p, - struct ib_send_wr *send_wr, - u32 sq_map_idx, - int hidden) -{ - u32 idx; - u64 dma_length; - struct ehca_av *my_av; - u32 remote_qkey; - struct ehca_qmap_entry *qmap_entry = &qp->sq_map.map[sq_map_idx]; - - if (unlikely((send_wr->num_sge < 0) || - (send_wr->num_sge > qp->ipz_squeue.act_nr_of_sg))) { - ehca_gen_err("Invalid number of WQE SGE. " - "num_sqe=%x max_nr_of_sg=%x", - send_wr->num_sge, qp->ipz_squeue.act_nr_of_sg); - return -EINVAL; /* invalid SG list length */ - } - - /* clear wqe header until sglist */ - memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list)); - - wqe_p->work_request_id = replace_wr_id(send_wr->wr_id, sq_map_idx); - - qmap_entry->app_wr_id = get_app_wr_id(send_wr->wr_id); - qmap_entry->reported = 0; - qmap_entry->cqe_req = 0; - - switch (send_wr->opcode) { - case IB_WR_SEND: - case IB_WR_SEND_WITH_IMM: - wqe_p->optype = WQE_OPTYPE_SEND; - break; - case IB_WR_RDMA_WRITE: - case IB_WR_RDMA_WRITE_WITH_IMM: - wqe_p->optype = WQE_OPTYPE_RDMAWRITE; - break; - case IB_WR_RDMA_READ: - wqe_p->optype = WQE_OPTYPE_RDMAREAD; - break; - default: - ehca_gen_err("Invalid opcode=%x", send_wr->opcode); - return -EINVAL; /* invalid opcode */ - } - - wqe_p->wqef = (send_wr->opcode) & WQEF_HIGH_NIBBLE; - - wqe_p->wr_flag = 0; - - if ((send_wr->send_flags & IB_SEND_SIGNALED || - qp->init_attr.sq_sig_type == IB_SIGNAL_ALL_WR) - && !hidden) { - wqe_p->wr_flag |= WQE_WRFLAG_REQ_SIGNAL_COM; - qmap_entry->cqe_req = 1; - } - - if (send_wr->opcode == IB_WR_SEND_WITH_IMM || - send_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) { - /* this might not work as long as HW does not support it */ - wqe_p->immediate_data = be32_to_cpu(send_wr->ex.imm_data); - wqe_p->wr_flag |= WQE_WRFLAG_IMM_DATA_PRESENT; - } - - wqe_p->nr_of_data_seg = send_wr->num_sge; - - switch (qp->qp_type) { - case IB_QPT_SMI: - case IB_QPT_GSI: - /* no break is intential here */ - case IB_QPT_UD: - /* IB 1.2 spec C10-15 compliance */ - remote_qkey = ud_wr(send_wr)->remote_qkey; - if (remote_qkey & 0x80000000) - remote_qkey = qp->qkey; - - wqe_p->destination_qp_number = ud_wr(send_wr)->remote_qpn << 8; - wqe_p->local_ee_context_qkey = remote_qkey; - if (unlikely(!ud_wr(send_wr)->ah)) { - ehca_gen_err("ud_wr(send_wr) is NULL. qp=%p", qp); - return -EINVAL; - } - if (unlikely(ud_wr(send_wr)->remote_qpn == 0)) { - ehca_gen_err("dest QP# is 0. qp=%x", qp->real_qp_num); - return -EINVAL; - } - my_av = container_of(ud_wr(send_wr)->ah, struct ehca_av, ib_ah); - wqe_p->u.ud_av.ud_av = my_av->av; - - /* - * omitted check of IB_SEND_INLINE - * since HW does not support it - */ - for (idx = 0; idx < send_wr->num_sge; idx++) { - wqe_p->u.ud_av.sg_list[idx].vaddr = - send_wr->sg_list[idx].addr; - wqe_p->u.ud_av.sg_list[idx].lkey = - send_wr->sg_list[idx].lkey; - wqe_p->u.ud_av.sg_list[idx].length = - send_wr->sg_list[idx].length; - } /* eof for idx */ - if (qp->qp_type == IB_QPT_SMI || - qp->qp_type == IB_QPT_GSI) - wqe_p->u.ud_av.ud_av.pmtu = 1; - if (qp->qp_type == IB_QPT_GSI) { - wqe_p->pkeyi = ud_wr(send_wr)->pkey_index; -#ifdef DEBUG_GSI_SEND_WR - trace_ud_wr(ud_wr(send_wr)); -#endif /* DEBUG_GSI_SEND_WR */ - } - break; - - case IB_QPT_UC: - if (send_wr->send_flags & IB_SEND_FENCE) - wqe_p->wr_flag |= WQE_WRFLAG_FENCE; - /* no break is intentional here */ - case IB_QPT_RC: - /* TODO: atomic not implemented */ - wqe_p->u.nud.remote_virtual_address = - rdma_wr(send_wr)->remote_addr; - wqe_p->u.nud.rkey = rdma_wr(send_wr)->rkey; - - /* - * omitted checking of IB_SEND_INLINE - * since HW does not support it - */ - dma_length = 0; - for (idx = 0; idx < send_wr->num_sge; idx++) { - wqe_p->u.nud.sg_list[idx].vaddr = - send_wr->sg_list[idx].addr; - wqe_p->u.nud.sg_list[idx].lkey = - send_wr->sg_list[idx].lkey; - wqe_p->u.nud.sg_list[idx].length = - send_wr->sg_list[idx].length; - dma_length += send_wr->sg_list[idx].length; - } /* eof idx */ - wqe_p->u.nud.atomic_1st_op_dma_len = dma_length; - - /* unsolicited ack circumvention */ - if (send_wr->opcode == IB_WR_RDMA_READ) { - /* on RDMA read, switch on and reset counters */ - qp->message_count = qp->packet_count = 0; - qp->unsol_ack_circ = 1; - } else - /* else estimate #packets */ - qp->packet_count += (dma_length >> qp->mtu_shift) + 1; - - break; - - default: - ehca_gen_err("Invalid qptype=%x", qp->qp_type); - return -EINVAL; - } - - if (ehca_debug_level >= 3) { - ehca_gen_dbg("SEND WQE written into queue qp=%p ", qp); - ehca_dmp( wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "send wqe"); - } - return 0; -} - -/* map_ib_wc_status converts raw cqe_status to ib_wc_status */ -static inline void map_ib_wc_status(u32 cqe_status, - enum ib_wc_status *wc_status) -{ - if (unlikely(cqe_status & WC_STATUS_ERROR_BIT)) { - switch (cqe_status & 0x3F) { - case 0x01: - case 0x21: - *wc_status = IB_WC_LOC_LEN_ERR; - break; - case 0x02: - case 0x22: - *wc_status = IB_WC_LOC_QP_OP_ERR; - break; - case 0x03: - case 0x23: - *wc_status = IB_WC_LOC_EEC_OP_ERR; - break; - case 0x04: - case 0x24: - *wc_status = IB_WC_LOC_PROT_ERR; - break; - case 0x05: - case 0x25: - *wc_status = IB_WC_WR_FLUSH_ERR; - break; - case 0x06: - *wc_status = IB_WC_MW_BIND_ERR; - break; - case 0x07: /* remote error - look into bits 20:24 */ - switch ((cqe_status - & WC_STATUS_REMOTE_ERROR_FLAGS) >> 11) { - case 0x0: - /* - * PSN Sequence Error! - * couldn't find a matching status! - */ - *wc_status = IB_WC_GENERAL_ERR; - break; - case 0x1: - *wc_status = IB_WC_REM_INV_REQ_ERR; - break; - case 0x2: - *wc_status = IB_WC_REM_ACCESS_ERR; - break; - case 0x3: - *wc_status = IB_WC_REM_OP_ERR; - break; - case 0x4: - *wc_status = IB_WC_REM_INV_RD_REQ_ERR; - break; - } - break; - case 0x08: - *wc_status = IB_WC_RETRY_EXC_ERR; - break; - case 0x09: - *wc_status = IB_WC_RNR_RETRY_EXC_ERR; - break; - case 0x0A: - case 0x2D: - *wc_status = IB_WC_REM_ABORT_ERR; - break; - case 0x0B: - case 0x2E: - *wc_status = IB_WC_INV_EECN_ERR; - break; - case 0x0C: - case 0x2F: - *wc_status = IB_WC_INV_EEC_STATE_ERR; - break; - case 0x0D: - *wc_status = IB_WC_BAD_RESP_ERR; - break; - case 0x10: - /* WQE purged */ - *wc_status = IB_WC_WR_FLUSH_ERR; - break; - default: - *wc_status = IB_WC_FATAL_ERR; - - } - } else - *wc_status = IB_WC_SUCCESS; -} - -static inline int post_one_send(struct ehca_qp *my_qp, - struct ib_send_wr *cur_send_wr, - int hidden) -{ - struct ehca_wqe *wqe_p; - int ret; - u32 sq_map_idx; - u64 start_offset = my_qp->ipz_squeue.current_q_offset; - - /* get pointer next to free WQE */ - wqe_p = ipz_qeit_get_inc(&my_qp->ipz_squeue); - if (unlikely(!wqe_p)) { - /* too many posted work requests: queue overflow */ - ehca_err(my_qp->ib_qp.device, "Too many posted WQEs " - "qp_num=%x", my_qp->ib_qp.qp_num); - return -ENOMEM; - } - - /* - * Get the index of the WQE in the send queue. The same index is used - * for writing into the sq_map. - */ - sq_map_idx = start_offset / my_qp->ipz_squeue.qe_size; - - /* write a SEND WQE into the QUEUE */ - ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr, sq_map_idx, hidden); - /* - * if something failed, - * reset the free entry pointer to the start value - */ - if (unlikely(ret)) { - my_qp->ipz_squeue.current_q_offset = start_offset; - ehca_err(my_qp->ib_qp.device, "Could not write WQE " - "qp_num=%x", my_qp->ib_qp.qp_num); - return -EINVAL; - } - - return 0; -} - -int ehca_post_send(struct ib_qp *qp, - struct ib_send_wr *send_wr, - struct ib_send_wr **bad_send_wr) -{ - struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp); - int wqe_cnt = 0; - int ret = 0; - unsigned long flags; - - /* Reject WR if QP is in RESET, INIT or RTR state */ - if (unlikely(my_qp->state < IB_QPS_RTS)) { - ehca_err(qp->device, "Invalid QP state qp_state=%d qpn=%x", - my_qp->state, qp->qp_num); - ret = -EINVAL; - goto out; - } - - /* LOCK the QUEUE */ - spin_lock_irqsave(&my_qp->spinlock_s, flags); - - /* Send an empty extra RDMA read if: - * 1) there has been an RDMA read on this connection before - * 2) no RDMA read occurred for ACK_CIRC_THRESHOLD link packets - * 3) we can be sure that any previous extra RDMA read has been - * processed so we don't overflow the SQ - */ - if (unlikely(my_qp->unsol_ack_circ && - my_qp->packet_count > ACK_CIRC_THRESHOLD && - my_qp->message_count > my_qp->init_attr.cap.max_send_wr)) { - /* insert an empty RDMA READ to fix up the remote QP state */ - struct ib_send_wr circ_wr; - memset(&circ_wr, 0, sizeof(circ_wr)); - circ_wr.opcode = IB_WR_RDMA_READ; - post_one_send(my_qp, &circ_wr, 1); /* ignore retcode */ - wqe_cnt++; - ehca_dbg(qp->device, "posted circ wr qp_num=%x", qp->qp_num); - my_qp->message_count = my_qp->packet_count = 0; - } - - /* loop processes list of send reqs */ - while (send_wr) { - ret = post_one_send(my_qp, send_wr, 0); - if (unlikely(ret)) { - goto post_send_exit0; - } - wqe_cnt++; - send_wr = send_wr->next; - } - -post_send_exit0: - iosync(); /* serialize GAL register access */ - hipz_update_sqa(my_qp, wqe_cnt); - if (unlikely(ret || ehca_debug_level >= 2)) - ehca_dbg(qp->device, "ehca_qp=%p qp_num=%x wqe_cnt=%d ret=%i", - my_qp, qp->qp_num, wqe_cnt, ret); - my_qp->message_count += wqe_cnt; - spin_unlock_irqrestore(&my_qp->spinlock_s, flags); - -out: - if (ret) - *bad_send_wr = send_wr; - return ret; -} - -static int internal_post_recv(struct ehca_qp *my_qp, - struct ib_device *dev, - struct ib_recv_wr *recv_wr, - struct ib_recv_wr **bad_recv_wr) -{ - struct ehca_wqe *wqe_p; - int wqe_cnt = 0; - int ret = 0; - u32 rq_map_idx; - unsigned long flags; - struct ehca_qmap_entry *qmap_entry; - - if (unlikely(!HAS_RQ(my_qp))) { - ehca_err(dev, "QP has no RQ ehca_qp=%p qp_num=%x ext_type=%d", - my_qp, my_qp->real_qp_num, my_qp->ext_type); - ret = -ENODEV; - goto out; - } - - /* LOCK the QUEUE */ - spin_lock_irqsave(&my_qp->spinlock_r, flags); - - /* loop processes list of recv reqs */ - while (recv_wr) { - u64 start_offset = my_qp->ipz_rqueue.current_q_offset; - /* get pointer next to free WQE */ - wqe_p = ipz_qeit_get_inc(&my_qp->ipz_rqueue); - if (unlikely(!wqe_p)) { - /* too many posted work requests: queue overflow */ - ret = -ENOMEM; - ehca_err(dev, "Too many posted WQEs " - "qp_num=%x", my_qp->real_qp_num); - goto post_recv_exit0; - } - /* - * Get the index of the WQE in the recv queue. The same index - * is used for writing into the rq_map. - */ - rq_map_idx = start_offset / my_qp->ipz_rqueue.qe_size; - - /* write a RECV WQE into the QUEUE */ - ret = ehca_write_rwqe(&my_qp->ipz_rqueue, wqe_p, recv_wr, - rq_map_idx); - /* - * if something failed, - * reset the free entry pointer to the start value - */ - if (unlikely(ret)) { - my_qp->ipz_rqueue.current_q_offset = start_offset; - ret = -EINVAL; - ehca_err(dev, "Could not write WQE " - "qp_num=%x", my_qp->real_qp_num); - goto post_recv_exit0; - } - - qmap_entry = &my_qp->rq_map.map[rq_map_idx]; - qmap_entry->app_wr_id = get_app_wr_id(recv_wr->wr_id); - qmap_entry->reported = 0; - qmap_entry->cqe_req = 1; - - wqe_cnt++; - recv_wr = recv_wr->next; - } /* eof for recv_wr */ - -post_recv_exit0: - iosync(); /* serialize GAL register access */ - hipz_update_rqa(my_qp, wqe_cnt); - if (unlikely(ret || ehca_debug_level >= 2)) - ehca_dbg(dev, "ehca_qp=%p qp_num=%x wqe_cnt=%d ret=%i", - my_qp, my_qp->real_qp_num, wqe_cnt, ret); - spin_unlock_irqrestore(&my_qp->spinlock_r, flags); - -out: - if (ret) - *bad_recv_wr = recv_wr; - - return ret; -} - -int ehca_post_recv(struct ib_qp *qp, - struct ib_recv_wr *recv_wr, - struct ib_recv_wr **bad_recv_wr) -{ - struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp); - - /* Reject WR if QP is in RESET state */ - if (unlikely(my_qp->state == IB_QPS_RESET)) { - ehca_err(qp->device, "Invalid QP state qp_state=%d qpn=%x", - my_qp->state, qp->qp_num); - *bad_recv_wr = recv_wr; - return -EINVAL; - } - - return internal_post_recv(my_qp, qp->device, recv_wr, bad_recv_wr); -} - -int ehca_post_srq_recv(struct ib_srq *srq, - struct ib_recv_wr *recv_wr, - struct ib_recv_wr **bad_recv_wr) -{ - return internal_post_recv(container_of(srq, struct ehca_qp, ib_srq), - srq->device, recv_wr, bad_recv_wr); -} - -/* - * ib_wc_opcode table converts ehca wc opcode to ib - * Since we use zero to indicate invalid opcode, the actual ib opcode must - * be decremented!!! - */ -static const u8 ib_wc_opcode[255] = { - [0x01] = IB_WC_RECV+1, - [0x02] = IB_WC_RECV_RDMA_WITH_IMM+1, - [0x08] = IB_WC_FETCH_ADD+1, - [0x10] = IB_WC_COMP_SWAP+1, - [0x20] = IB_WC_RDMA_WRITE+1, - [0x40] = IB_WC_RDMA_READ+1, - [0x80] = IB_WC_SEND+1 -}; - -/* internal function to poll one entry of cq */ -static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc) -{ - int ret = 0, qmap_tail_idx; - struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); - struct ehca_cqe *cqe; - struct ehca_qp *my_qp; - struct ehca_qmap_entry *qmap_entry; - struct ehca_queue_map *qmap; - int cqe_count = 0, is_error; - -repoll: - cqe = (struct ehca_cqe *) - ipz_qeit_get_inc_valid(&my_cq->ipz_queue); - if (!cqe) { - ret = -EAGAIN; - if (ehca_debug_level >= 3) - ehca_dbg(cq->device, "Completion queue is empty " - "my_cq=%p cq_num=%x", my_cq, my_cq->cq_number); - goto poll_cq_one_exit0; - } - - /* prevents loads being reordered across this point */ - rmb(); - - cqe_count++; - if (unlikely(cqe->status & WC_STATUS_PURGE_BIT)) { - struct ehca_qp *qp; - int purgeflag; - unsigned long flags; - - qp = ehca_cq_get_qp(my_cq, cqe->local_qp_number); - if (!qp) { - ehca_err(cq->device, "cq_num=%x qp_num=%x " - "could not find qp -> ignore cqe", - my_cq->cq_number, cqe->local_qp_number); - ehca_dmp(cqe, 64, "cq_num=%x qp_num=%x", - my_cq->cq_number, cqe->local_qp_number); - /* ignore this purged cqe */ - goto repoll; - } - spin_lock_irqsave(&qp->spinlock_s, flags); - purgeflag = qp->sqerr_purgeflag; - spin_unlock_irqrestore(&qp->spinlock_s, flags); - - if (purgeflag) { - ehca_dbg(cq->device, - "Got CQE with purged bit qp_num=%x src_qp=%x", - cqe->local_qp_number, cqe->remote_qp_number); - if (ehca_debug_level >= 2) - ehca_dmp(cqe, 64, "qp_num=%x src_qp=%x", - cqe->local_qp_number, - cqe->remote_qp_number); - /* - * ignore this to avoid double cqes of bad wqe - * that caused sqe and turn off purge flag - */ - qp->sqerr_purgeflag = 0; - goto repoll; - } - } - - is_error = cqe->status & WC_STATUS_ERROR_BIT; - - /* trace error CQEs if debug_level >= 1, trace all CQEs if >= 3 */ - if (unlikely(ehca_debug_level >= 3 || (ehca_debug_level && is_error))) { - ehca_dbg(cq->device, - "Received %sCOMPLETION ehca_cq=%p cq_num=%x -----", - is_error ? "ERROR " : "", my_cq, my_cq->cq_number); - ehca_dmp(cqe, 64, "ehca_cq=%p cq_num=%x", - my_cq, my_cq->cq_number); - ehca_dbg(cq->device, - "ehca_cq=%p cq_num=%x -------------------------", - my_cq, my_cq->cq_number); - } - - read_lock(&ehca_qp_idr_lock); - my_qp = idr_find(&ehca_qp_idr, cqe->qp_token); - read_unlock(&ehca_qp_idr_lock); - if (!my_qp) - goto repoll; - wc->qp = &my_qp->ib_qp; - - qmap_tail_idx = get_app_wr_id(cqe->work_request_id); - if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT)) - /* We got a send completion. */ - qmap = &my_qp->sq_map; - else - /* We got a receive completion. */ - qmap = &my_qp->rq_map; - - /* advance the tail pointer */ - qmap->tail = qmap_tail_idx; - - if (is_error) { - /* - * set left_to_poll to 0 because in error state, we will not - * get any additional CQEs - */ - my_qp->sq_map.next_wqe_idx = next_index(my_qp->sq_map.tail, - my_qp->sq_map.entries); - my_qp->sq_map.left_to_poll = 0; - ehca_add_to_err_list(my_qp, 1); - - my_qp->rq_map.next_wqe_idx = next_index(my_qp->rq_map.tail, - my_qp->rq_map.entries); - my_qp->rq_map.left_to_poll = 0; - if (HAS_RQ(my_qp)) - ehca_add_to_err_list(my_qp, 0); - } - - qmap_entry = &qmap->map[qmap_tail_idx]; - if (qmap_entry->reported) { - ehca_warn(cq->device, "Double cqe on qp_num=%#x", - my_qp->real_qp_num); - /* found a double cqe, discard it and read next one */ - goto repoll; - } - - wc->wr_id = replace_wr_id(cqe->work_request_id, qmap_entry->app_wr_id); - qmap_entry->reported = 1; - - /* if left_to_poll is decremented to 0, add the QP to the error list */ - if (qmap->left_to_poll > 0) { - qmap->left_to_poll--; - if ((my_qp->sq_map.left_to_poll == 0) && - (my_qp->rq_map.left_to_poll == 0)) { - ehca_add_to_err_list(my_qp, 1); - if (HAS_RQ(my_qp)) - ehca_add_to_err_list(my_qp, 0); - } - } - - /* eval ib_wc_opcode */ - wc->opcode = ib_wc_opcode[cqe->optype]-1; - if (unlikely(wc->opcode == -1)) { - ehca_err(cq->device, "Invalid cqe->OPType=%x cqe->status=%x " - "ehca_cq=%p cq_num=%x", - cqe->optype, cqe->status, my_cq, my_cq->cq_number); - /* dump cqe for other infos */ - ehca_dmp(cqe, 64, "ehca_cq=%p cq_num=%x", - my_cq, my_cq->cq_number); - /* update also queue adder to throw away this entry!!! */ - goto repoll; - } - - /* eval ib_wc_status */ - if (unlikely(is_error)) { - /* complete with errors */ - map_ib_wc_status(cqe->status, &wc->status); - wc->vendor_err = wc->status; - } else - wc->status = IB_WC_SUCCESS; - - wc->byte_len = cqe->nr_bytes_transferred; - wc->pkey_index = cqe->pkey_index; - wc->slid = cqe->rlid; - wc->dlid_path_bits = cqe->dlid; - wc->src_qp = cqe->remote_qp_number; - /* - * HW has "Immed data present" and "GRH present" in bits 6 and 5. - * SW defines those in bits 1 and 0, so we can just shift and mask. - */ - wc->wc_flags = (cqe->w_completion_flags >> 5) & 3; - wc->ex.imm_data = cpu_to_be32(cqe->immediate_data); - wc->sl = cqe->service_level; - -poll_cq_one_exit0: - if (cqe_count > 0) - hipz_update_feca(my_cq, cqe_count); - - return ret; -} - -static int generate_flush_cqes(struct ehca_qp *my_qp, struct ib_cq *cq, - struct ib_wc *wc, int num_entries, - struct ipz_queue *ipz_queue, int on_sq) -{ - int nr = 0; - struct ehca_wqe *wqe; - u64 offset; - struct ehca_queue_map *qmap; - struct ehca_qmap_entry *qmap_entry; - - if (on_sq) - qmap = &my_qp->sq_map; - else - qmap = &my_qp->rq_map; - - qmap_entry = &qmap->map[qmap->next_wqe_idx]; - - while ((nr < num_entries) && (qmap_entry->reported == 0)) { - /* generate flush CQE */ - - memset(wc, 0, sizeof(*wc)); - - offset = qmap->next_wqe_idx * ipz_queue->qe_size; - wqe = (struct ehca_wqe *)ipz_qeit_calc(ipz_queue, offset); - if (!wqe) { - ehca_err(cq->device, "Invalid wqe offset=%#llx on " - "qp_num=%#x", offset, my_qp->real_qp_num); - return nr; - } - - wc->wr_id = replace_wr_id(wqe->work_request_id, - qmap_entry->app_wr_id); - - if (on_sq) { - switch (wqe->optype) { - case WQE_OPTYPE_SEND: - wc->opcode = IB_WC_SEND; - break; - case WQE_OPTYPE_RDMAWRITE: - wc->opcode = IB_WC_RDMA_WRITE; - break; - case WQE_OPTYPE_RDMAREAD: - wc->opcode = IB_WC_RDMA_READ; - break; - default: - ehca_err(cq->device, "Invalid optype=%x", - wqe->optype); - return nr; - } - } else - wc->opcode = IB_WC_RECV; - - if (wqe->wr_flag & WQE_WRFLAG_IMM_DATA_PRESENT) { - wc->ex.imm_data = wqe->immediate_data; - wc->wc_flags |= IB_WC_WITH_IMM; - } - - wc->status = IB_WC_WR_FLUSH_ERR; - - wc->qp = &my_qp->ib_qp; - - /* mark as reported and advance next_wqe pointer */ - qmap_entry->reported = 1; - qmap->next_wqe_idx = next_index(qmap->next_wqe_idx, - qmap->entries); - qmap_entry = &qmap->map[qmap->next_wqe_idx]; - - wc++; nr++; - } - - return nr; - -} - -int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc) -{ - struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); - int nr; - struct ehca_qp *err_qp; - struct ib_wc *current_wc = wc; - int ret = 0; - unsigned long flags; - int entries_left = num_entries; - - if (num_entries < 1) { - ehca_err(cq->device, "Invalid num_entries=%d ehca_cq=%p " - "cq_num=%x", num_entries, my_cq, my_cq->cq_number); - ret = -EINVAL; - goto poll_cq_exit0; - } - - spin_lock_irqsave(&my_cq->spinlock, flags); - - /* generate flush cqes for send queues */ - list_for_each_entry(err_qp, &my_cq->sqp_err_list, sq_err_node) { - nr = generate_flush_cqes(err_qp, cq, current_wc, entries_left, - &err_qp->ipz_squeue, 1); - entries_left -= nr; - current_wc += nr; - - if (entries_left == 0) - break; - } - - /* generate flush cqes for receive queues */ - list_for_each_entry(err_qp, &my_cq->rqp_err_list, rq_err_node) { - nr = generate_flush_cqes(err_qp, cq, current_wc, entries_left, - &err_qp->ipz_rqueue, 0); - entries_left -= nr; - current_wc += nr; - - if (entries_left == 0) - break; - } - - for (nr = 0; nr < entries_left; nr++) { - ret = ehca_poll_cq_one(cq, current_wc); - if (ret) - break; - current_wc++; - } /* eof for nr */ - entries_left -= nr; - - spin_unlock_irqrestore(&my_cq->spinlock, flags); - if (ret == -EAGAIN || !ret) - ret = num_entries - entries_left; - -poll_cq_exit0: - return ret; -} - -int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags notify_flags) -{ - struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); - int ret = 0; - - switch (notify_flags & IB_CQ_SOLICITED_MASK) { - case IB_CQ_SOLICITED: - hipz_set_cqx_n0(my_cq, 1); - break; - case IB_CQ_NEXT_COMP: - hipz_set_cqx_n1(my_cq, 1); - break; - default: - return -EINVAL; - } - - if (notify_flags & IB_CQ_REPORT_MISSED_EVENTS) { - unsigned long spl_flags; - spin_lock_irqsave(&my_cq->spinlock, spl_flags); - ret = ipz_qeit_is_valid(&my_cq->ipz_queue); - spin_unlock_irqrestore(&my_cq->spinlock, spl_flags); - } - - return ret; -} diff --git a/drivers/staging/rdma/ehca/ehca_sqp.c b/drivers/staging/rdma/ehca/ehca_sqp.c deleted file mode 100644 index 376b031c2c7f..000000000000 --- a/drivers/staging/rdma/ehca/ehca_sqp.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * SQP functions - * - * Authors: Khadija Souissi - * Heiko J Schick - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "ehca_classes.h" -#include "ehca_tools.h" -#include "ehca_iverbs.h" -#include "hcp_if.h" - -#define IB_MAD_STATUS_REDIRECT cpu_to_be16(0x0002) -#define IB_MAD_STATUS_UNSUP_VERSION cpu_to_be16(0x0004) -#define IB_MAD_STATUS_UNSUP_METHOD cpu_to_be16(0x0008) - -#define IB_PMA_CLASS_PORT_INFO cpu_to_be16(0x0001) - -/** - * ehca_define_sqp - Defines special queue pair 1 (GSI QP). When special queue - * pair is created successfully, the corresponding port gets active. - * - * Define Special Queue pair 0 (SMI QP) is still not supported. - * - * @qp_init_attr: Queue pair init attributes with port and queue pair type - */ - -u64 ehca_define_sqp(struct ehca_shca *shca, - struct ehca_qp *ehca_qp, - struct ib_qp_init_attr *qp_init_attr) -{ - u32 pma_qp_nr, bma_qp_nr; - u64 ret; - u8 port = qp_init_attr->port_num; - int counter; - - shca->sport[port - 1].port_state = IB_PORT_DOWN; - - switch (qp_init_attr->qp_type) { - case IB_QPT_SMI: - /* function not supported yet */ - break; - case IB_QPT_GSI: - ret = hipz_h_define_aqp1(shca->ipz_hca_handle, - ehca_qp->ipz_qp_handle, - ehca_qp->galpas.kernel, - (u32) qp_init_attr->port_num, - &pma_qp_nr, &bma_qp_nr); - - if (ret != H_SUCCESS) { - ehca_err(&shca->ib_device, - "Can't define AQP1 for port %x. h_ret=%lli", - port, ret); - return ret; - } - shca->sport[port - 1].pma_qp_nr = pma_qp_nr; - ehca_dbg(&shca->ib_device, "port=%x pma_qp_nr=%x", - port, pma_qp_nr); - break; - default: - ehca_err(&shca->ib_device, "invalid qp_type=%x", - qp_init_attr->qp_type); - return H_PARAMETER; - } - - if (ehca_nr_ports < 0) /* autodetect mode */ - return H_SUCCESS; - - for (counter = 0; - shca->sport[port - 1].port_state != IB_PORT_ACTIVE && - counter < ehca_port_act_time; - counter++) { - ehca_dbg(&shca->ib_device, "... wait until port %x is active", - port); - msleep_interruptible(1000); - } - - if (counter == ehca_port_act_time) { - ehca_err(&shca->ib_device, "Port %x is not active.", port); - return H_HARDWARE; - } - - return H_SUCCESS; -} - -struct ib_perf { - struct ib_mad_hdr mad_hdr; - u8 reserved[40]; - u8 data[192]; -} __attribute__ ((packed)); - -/* TC/SL/FL packed into 32 bits, as in ClassPortInfo */ -struct tcslfl { - u32 tc:8; - u32 sl:4; - u32 fl:20; -} __attribute__ ((packed)); - -/* IP Version/TC/FL packed into 32 bits, as in GRH */ -struct vertcfl { - u32 ver:4; - u32 tc:8; - u32 fl:20; -} __attribute__ ((packed)); - -static int ehca_process_perf(struct ib_device *ibdev, u8 port_num, - const struct ib_wc *in_wc, const struct ib_grh *in_grh, - const struct ib_mad *in_mad, struct ib_mad *out_mad) -{ - const struct ib_perf *in_perf = (const struct ib_perf *)in_mad; - struct ib_perf *out_perf = (struct ib_perf *)out_mad; - struct ib_class_port_info *poi = - (struct ib_class_port_info *)out_perf->data; - struct tcslfl *tcslfl = - (struct tcslfl *)&poi->redirect_tcslfl; - struct ehca_shca *shca = - container_of(ibdev, struct ehca_shca, ib_device); - struct ehca_sport *sport = &shca->sport[port_num - 1]; - - ehca_dbg(ibdev, "method=%x", in_perf->mad_hdr.method); - - *out_mad = *in_mad; - - if (in_perf->mad_hdr.class_version != 1) { - ehca_warn(ibdev, "Unsupported class_version=%x", - in_perf->mad_hdr.class_version); - out_perf->mad_hdr.status = IB_MAD_STATUS_UNSUP_VERSION; - goto perf_reply; - } - - switch (in_perf->mad_hdr.method) { - case IB_MGMT_METHOD_GET: - case IB_MGMT_METHOD_SET: - /* set class port info for redirection */ - out_perf->mad_hdr.attr_id = IB_PMA_CLASS_PORT_INFO; - out_perf->mad_hdr.status = IB_MAD_STATUS_REDIRECT; - memset(poi, 0, sizeof(*poi)); - poi->base_version = 1; - poi->class_version = 1; - poi->resp_time_value = 18; - - /* copy local routing information from WC where applicable */ - tcslfl->sl = in_wc->sl; - poi->redirect_lid = - sport->saved_attr.lid | in_wc->dlid_path_bits; - poi->redirect_qp = sport->pma_qp_nr; - poi->redirect_qkey = IB_QP1_QKEY; - - ehca_query_pkey(ibdev, port_num, in_wc->pkey_index, - &poi->redirect_pkey); - - /* if request was globally routed, copy route info */ - if (in_grh) { - const struct vertcfl *vertcfl = - (const struct vertcfl *)&in_grh->version_tclass_flow; - memcpy(poi->redirect_gid, in_grh->dgid.raw, - sizeof(poi->redirect_gid)); - tcslfl->tc = vertcfl->tc; - tcslfl->fl = vertcfl->fl; - } else - /* else only fill in default GID */ - ehca_query_gid(ibdev, port_num, 0, - (union ib_gid *)&poi->redirect_gid); - - ehca_dbg(ibdev, "ehca_pma_lid=%x ehca_pma_qp=%x", - sport->saved_attr.lid, sport->pma_qp_nr); - break; - - case IB_MGMT_METHOD_GET_RESP: - return IB_MAD_RESULT_FAILURE; - - default: - out_perf->mad_hdr.status = IB_MAD_STATUS_UNSUP_METHOD; - break; - } - -perf_reply: - out_perf->mad_hdr.method = IB_MGMT_METHOD_GET_RESP; - - return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY; -} - -int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, - const struct ib_wc *in_wc, const struct ib_grh *in_grh, - const struct ib_mad_hdr *in, size_t in_mad_size, - struct ib_mad_hdr *out, size_t *out_mad_size, - u16 *out_mad_pkey_index) -{ - int ret; - const struct ib_mad *in_mad = (const struct ib_mad *)in; - struct ib_mad *out_mad = (struct ib_mad *)out; - - if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || - *out_mad_size != sizeof(*out_mad))) - return IB_MAD_RESULT_FAILURE; - - if (!port_num || port_num > ibdev->phys_port_cnt || !in_wc) - return IB_MAD_RESULT_FAILURE; - - /* accept only pma request */ - if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_PERF_MGMT) - return IB_MAD_RESULT_SUCCESS; - - ehca_dbg(ibdev, "port_num=%x src_qp=%x", port_num, in_wc->src_qp); - ret = ehca_process_perf(ibdev, port_num, in_wc, in_grh, - in_mad, out_mad); - - return ret; -} diff --git a/drivers/staging/rdma/ehca/ehca_tools.h b/drivers/staging/rdma/ehca/ehca_tools.h deleted file mode 100644 index d280b12aae64..000000000000 --- a/drivers/staging/rdma/ehca/ehca_tools.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * auxiliary functions - * - * Authors: Christoph Raisch - * Hoang-Nam Nguyen - * Khadija Souissi - * Waleri Fomin - * Heiko J Schick - * - * Copyright (c) 2005 IBM Corporation - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef EHCA_TOOLS_H -#define EHCA_TOOLS_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -extern int ehca_debug_level; - -#define ehca_dbg(ib_dev, format, arg...) \ - do { \ - if (unlikely(ehca_debug_level)) \ - dev_printk(KERN_DEBUG, (ib_dev)->dma_device, \ - "PU%04x EHCA_DBG:%s " format "\n", \ - raw_smp_processor_id(), __func__, \ - ## arg); \ - } while (0) - -#define ehca_info(ib_dev, format, arg...) \ - dev_info((ib_dev)->dma_device, "PU%04x EHCA_INFO:%s " format "\n", \ - raw_smp_processor_id(), __func__, ## arg) - -#define ehca_warn(ib_dev, format, arg...) \ - dev_warn((ib_dev)->dma_device, "PU%04x EHCA_WARN:%s " format "\n", \ - raw_smp_processor_id(), __func__, ## arg) - -#define ehca_err(ib_dev, format, arg...) \ - dev_err((ib_dev)->dma_device, "PU%04x EHCA_ERR:%s " format "\n", \ - raw_smp_processor_id(), __func__, ## arg) - -/* use this one only if no ib_dev available */ -#define ehca_gen_dbg(format, arg...) \ - do { \ - if (unlikely(ehca_debug_level)) \ - printk(KERN_DEBUG "PU%04x EHCA_DBG:%s " format "\n", \ - raw_smp_processor_id(), __func__, ## arg); \ - } while (0) - -#define ehca_gen_warn(format, arg...) \ - printk(KERN_INFO "PU%04x EHCA_WARN:%s " format "\n", \ - raw_smp_processor_id(), __func__, ## arg) - -#define ehca_gen_err(format, arg...) \ - printk(KERN_ERR "PU%04x EHCA_ERR:%s " format "\n", \ - raw_smp_processor_id(), __func__, ## arg) - -/** - * ehca_dmp - printk a memory block, whose length is n*8 bytes. - * Each line has the following layout: - * adr=X ofs=Y <8 bytes hex> <8 bytes hex> - */ -#define ehca_dmp(adr, len, format, args...) \ - do { \ - unsigned int x; \ - unsigned int l = (unsigned int)(len); \ - unsigned char *deb = (unsigned char *)(adr); \ - for (x = 0; x < l; x += 16) { \ - printk(KERN_INFO "EHCA_DMP:%s " format \ - " adr=%p ofs=%04x %016llx %016llx\n", \ - __func__, ##args, deb, x, \ - *((u64 *)&deb[0]), *((u64 *)&deb[8])); \ - deb += 16; \ - } \ - } while (0) - -/* define a bitmask, little endian version */ -#define EHCA_BMASK(pos, length) (((pos) << 16) + (length)) - -/* define a bitmask, the ibm way... */ -#define EHCA_BMASK_IBM(from, to) (((63 - to) << 16) + ((to) - (from) + 1)) - -/* internal function, don't use */ -#define EHCA_BMASK_SHIFTPOS(mask) (((mask) >> 16) & 0xffff) - -/* internal function, don't use */ -#define EHCA_BMASK_MASK(mask) (~0ULL >> ((64 - (mask)) & 0xffff)) - -/** - * EHCA_BMASK_SET - return value shifted and masked by mask - * variable|=EHCA_BMASK_SET(MY_MASK,0x4711) ORs the bits in variable - * variable&=~EHCA_BMASK_SET(MY_MASK,-1) clears the bits from the mask - * in variable - */ -#define EHCA_BMASK_SET(mask, value) \ - ((EHCA_BMASK_MASK(mask) & ((u64)(value))) << EHCA_BMASK_SHIFTPOS(mask)) - -/** - * EHCA_BMASK_GET - extract a parameter from value by mask - */ -#define EHCA_BMASK_GET(mask, value) \ - (EHCA_BMASK_MASK(mask) & (((u64)(value)) >> EHCA_BMASK_SHIFTPOS(mask))) - -/* Converts ehca to ib return code */ -int ehca2ib_return_code(u64 ehca_rc); - -#endif /* EHCA_TOOLS_H */ diff --git a/drivers/staging/rdma/ehca/ehca_uverbs.c b/drivers/staging/rdma/ehca/ehca_uverbs.c deleted file mode 100644 index 1a1d5d99fcf9..000000000000 --- a/drivers/staging/rdma/ehca/ehca_uverbs.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * userspace support verbs - * - * Authors: Christoph Raisch - * Hoang-Nam Nguyen - * Heiko J Schick - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "ehca_classes.h" -#include "ehca_iverbs.h" -#include "ehca_mrmw.h" -#include "ehca_tools.h" -#include "hcp_if.h" - -struct ib_ucontext *ehca_alloc_ucontext(struct ib_device *device, - struct ib_udata *udata) -{ - struct ehca_ucontext *my_context; - - my_context = kzalloc(sizeof *my_context, GFP_KERNEL); - if (!my_context) { - ehca_err(device, "Out of memory device=%p", device); - return ERR_PTR(-ENOMEM); - } - - return &my_context->ib_ucontext; -} - -int ehca_dealloc_ucontext(struct ib_ucontext *context) -{ - kfree(container_of(context, struct ehca_ucontext, ib_ucontext)); - return 0; -} - -static void ehca_mm_open(struct vm_area_struct *vma) -{ - u32 *count = (u32 *)vma->vm_private_data; - if (!count) { - ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx", - vma->vm_start, vma->vm_end); - return; - } - (*count)++; - if (!(*count)) - ehca_gen_err("Use count overflow vm_start=%lx vm_end=%lx", - vma->vm_start, vma->vm_end); - ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x", - vma->vm_start, vma->vm_end, *count); -} - -static void ehca_mm_close(struct vm_area_struct *vma) -{ - u32 *count = (u32 *)vma->vm_private_data; - if (!count) { - ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx", - vma->vm_start, vma->vm_end); - return; - } - (*count)--; - ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x", - vma->vm_start, vma->vm_end, *count); -} - -static const struct vm_operations_struct vm_ops = { - .open = ehca_mm_open, - .close = ehca_mm_close, -}; - -static int ehca_mmap_fw(struct vm_area_struct *vma, struct h_galpas *galpas, - u32 *mm_count) -{ - int ret; - u64 vsize, physical; - - vsize = vma->vm_end - vma->vm_start; - if (vsize < EHCA_PAGESIZE) { - ehca_gen_err("invalid vsize=%lx", vma->vm_end - vma->vm_start); - return -EINVAL; - } - - physical = galpas->user.fw_handle; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - ehca_gen_dbg("vsize=%llx physical=%llx", vsize, physical); - /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */ - ret = remap_4k_pfn(vma, vma->vm_start, physical >> EHCA_PAGESHIFT, - vma->vm_page_prot); - if (unlikely(ret)) { - ehca_gen_err("remap_pfn_range() failed ret=%i", ret); - return -ENOMEM; - } - - vma->vm_private_data = mm_count; - (*mm_count)++; - vma->vm_ops = &vm_ops; - - return 0; -} - -static int ehca_mmap_queue(struct vm_area_struct *vma, struct ipz_queue *queue, - u32 *mm_count) -{ - int ret; - u64 start, ofs; - struct page *page; - - vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; - start = vma->vm_start; - for (ofs = 0; ofs < queue->queue_length; ofs += PAGE_SIZE) { - u64 virt_addr = (u64)ipz_qeit_calc(queue, ofs); - page = virt_to_page(virt_addr); - ret = vm_insert_page(vma, start, page); - if (unlikely(ret)) { - ehca_gen_err("vm_insert_page() failed rc=%i", ret); - return ret; - } - start += PAGE_SIZE; - } - vma->vm_private_data = mm_count; - (*mm_count)++; - vma->vm_ops = &vm_ops; - - return 0; -} - -static int ehca_mmap_cq(struct vm_area_struct *vma, struct ehca_cq *cq, - u32 rsrc_type) -{ - int ret; - - switch (rsrc_type) { - case 0: /* galpa fw handle */ - ehca_dbg(cq->ib_cq.device, "cq_num=%x fw", cq->cq_number); - ret = ehca_mmap_fw(vma, &cq->galpas, &cq->mm_count_galpa); - if (unlikely(ret)) { - ehca_err(cq->ib_cq.device, - "ehca_mmap_fw() failed rc=%i cq_num=%x", - ret, cq->cq_number); - return ret; - } - break; - - case 1: /* cq queue_addr */ - ehca_dbg(cq->ib_cq.device, "cq_num=%x queue", cq->cq_number); - ret = ehca_mmap_queue(vma, &cq->ipz_queue, &cq->mm_count_queue); - if (unlikely(ret)) { - ehca_err(cq->ib_cq.device, - "ehca_mmap_queue() failed rc=%i cq_num=%x", - ret, cq->cq_number); - return ret; - } - break; - - default: - ehca_err(cq->ib_cq.device, "bad resource type=%x cq_num=%x", - rsrc_type, cq->cq_number); - return -EINVAL; - } - - return 0; -} - -static int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp, - u32 rsrc_type) -{ - int ret; - - switch (rsrc_type) { - case 0: /* galpa fw handle */ - ehca_dbg(qp->ib_qp.device, "qp_num=%x fw", qp->ib_qp.qp_num); - ret = ehca_mmap_fw(vma, &qp->galpas, &qp->mm_count_galpa); - if (unlikely(ret)) { - ehca_err(qp->ib_qp.device, - "remap_pfn_range() failed ret=%i qp_num=%x", - ret, qp->ib_qp.qp_num); - return -ENOMEM; - } - break; - - case 1: /* qp rqueue_addr */ - ehca_dbg(qp->ib_qp.device, "qp_num=%x rq", qp->ib_qp.qp_num); - ret = ehca_mmap_queue(vma, &qp->ipz_rqueue, - &qp->mm_count_rqueue); - if (unlikely(ret)) { - ehca_err(qp->ib_qp.device, - "ehca_mmap_queue(rq) failed rc=%i qp_num=%x", - ret, qp->ib_qp.qp_num); - return ret; - } - break; - - case 2: /* qp squeue_addr */ - ehca_dbg(qp->ib_qp.device, "qp_num=%x sq", qp->ib_qp.qp_num); - ret = ehca_mmap_queue(vma, &qp->ipz_squeue, - &qp->mm_count_squeue); - if (unlikely(ret)) { - ehca_err(qp->ib_qp.device, - "ehca_mmap_queue(sq) failed rc=%i qp_num=%x", - ret, qp->ib_qp.qp_num); - return ret; - } - break; - - default: - ehca_err(qp->ib_qp.device, "bad resource type=%x qp=num=%x", - rsrc_type, qp->ib_qp.qp_num); - return -EINVAL; - } - - return 0; -} - -int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) -{ - u64 fileoffset = vma->vm_pgoff; - u32 idr_handle = fileoffset & 0x1FFFFFF; - u32 q_type = (fileoffset >> 27) & 0x1; /* CQ, QP,... */ - u32 rsrc_type = (fileoffset >> 25) & 0x3; /* sq,rq,cmnd_window */ - u32 ret; - struct ehca_cq *cq; - struct ehca_qp *qp; - struct ib_uobject *uobject; - - switch (q_type) { - case 0: /* CQ */ - read_lock(&ehca_cq_idr_lock); - cq = idr_find(&ehca_cq_idr, idr_handle); - read_unlock(&ehca_cq_idr_lock); - - /* make sure this mmap really belongs to the authorized user */ - if (!cq) - return -EINVAL; - - if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context) - return -EINVAL; - - ret = ehca_mmap_cq(vma, cq, rsrc_type); - if (unlikely(ret)) { - ehca_err(cq->ib_cq.device, - "ehca_mmap_cq() failed rc=%i cq_num=%x", - ret, cq->cq_number); - return ret; - } - break; - - case 1: /* QP */ - read_lock(&ehca_qp_idr_lock); - qp = idr_find(&ehca_qp_idr, idr_handle); - read_unlock(&ehca_qp_idr_lock); - - /* make sure this mmap really belongs to the authorized user */ - if (!qp) - return -EINVAL; - - uobject = IS_SRQ(qp) ? qp->ib_srq.uobject : qp->ib_qp.uobject; - if (!uobject || uobject->context != context) - return -EINVAL; - - ret = ehca_mmap_qp(vma, qp, rsrc_type); - if (unlikely(ret)) { - ehca_err(qp->ib_qp.device, - "ehca_mmap_qp() failed rc=%i qp_num=%x", - ret, qp->ib_qp.qp_num); - return ret; - } - break; - - default: - ehca_gen_err("bad queue type %x", q_type); - return -EINVAL; - } - - return 0; -} diff --git a/drivers/staging/rdma/ehca/hcp_if.c b/drivers/staging/rdma/ehca/hcp_if.c deleted file mode 100644 index 89517ffb4389..000000000000 --- a/drivers/staging/rdma/ehca/hcp_if.c +++ /dev/null @@ -1,949 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Firmware Infiniband Interface code for POWER - * - * Authors: Christoph Raisch - * Hoang-Nam Nguyen - * Joachim Fenkes - * Gerd Bayer - * Waleri Fomin - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "ehca_tools.h" -#include "hcp_if.h" -#include "hcp_phyp.h" -#include "hipz_fns.h" -#include "ipz_pt_fn.h" - -#define H_ALL_RES_QP_ENHANCED_OPS EHCA_BMASK_IBM(9, 11) -#define H_ALL_RES_QP_PTE_PIN EHCA_BMASK_IBM(12, 12) -#define H_ALL_RES_QP_SERVICE_TYPE EHCA_BMASK_IBM(13, 15) -#define H_ALL_RES_QP_STORAGE EHCA_BMASK_IBM(16, 17) -#define H_ALL_RES_QP_LL_RQ_CQE_POSTING EHCA_BMASK_IBM(18, 18) -#define H_ALL_RES_QP_LL_SQ_CQE_POSTING EHCA_BMASK_IBM(19, 21) -#define H_ALL_RES_QP_SIGNALING_TYPE EHCA_BMASK_IBM(22, 23) -#define H_ALL_RES_QP_UD_AV_LKEY_CTRL EHCA_BMASK_IBM(31, 31) -#define H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE EHCA_BMASK_IBM(32, 35) -#define H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE EHCA_BMASK_IBM(36, 39) -#define H_ALL_RES_QP_RESOURCE_TYPE EHCA_BMASK_IBM(56, 63) - -#define H_ALL_RES_QP_MAX_OUTST_SEND_WR EHCA_BMASK_IBM(0, 15) -#define H_ALL_RES_QP_MAX_OUTST_RECV_WR EHCA_BMASK_IBM(16, 31) -#define H_ALL_RES_QP_MAX_SEND_SGE EHCA_BMASK_IBM(32, 39) -#define H_ALL_RES_QP_MAX_RECV_SGE EHCA_BMASK_IBM(40, 47) - -#define H_ALL_RES_QP_UD_AV_LKEY EHCA_BMASK_IBM(32, 63) -#define H_ALL_RES_QP_SRQ_QP_TOKEN EHCA_BMASK_IBM(0, 31) -#define H_ALL_RES_QP_SRQ_QP_HANDLE EHCA_BMASK_IBM(0, 64) -#define H_ALL_RES_QP_SRQ_LIMIT EHCA_BMASK_IBM(48, 63) -#define H_ALL_RES_QP_SRQ_QPN EHCA_BMASK_IBM(40, 63) - -#define H_ALL_RES_QP_ACT_OUTST_SEND_WR EHCA_BMASK_IBM(16, 31) -#define H_ALL_RES_QP_ACT_OUTST_RECV_WR EHCA_BMASK_IBM(48, 63) -#define H_ALL_RES_QP_ACT_SEND_SGE EHCA_BMASK_IBM(8, 15) -#define H_ALL_RES_QP_ACT_RECV_SGE EHCA_BMASK_IBM(24, 31) - -#define H_ALL_RES_QP_SQUEUE_SIZE_PAGES EHCA_BMASK_IBM(0, 31) -#define H_ALL_RES_QP_RQUEUE_SIZE_PAGES EHCA_BMASK_IBM(32, 63) - -#define H_MP_INIT_TYPE EHCA_BMASK_IBM(44, 47) -#define H_MP_SHUTDOWN EHCA_BMASK_IBM(48, 48) -#define H_MP_RESET_QKEY_CTR EHCA_BMASK_IBM(49, 49) - -#define HCALL4_REGS_FORMAT "r4=%lx r5=%lx r6=%lx r7=%lx" -#define HCALL7_REGS_FORMAT HCALL4_REGS_FORMAT " r8=%lx r9=%lx r10=%lx" -#define HCALL9_REGS_FORMAT HCALL7_REGS_FORMAT " r11=%lx r12=%lx" - -static DEFINE_SPINLOCK(hcall_lock); - -static long ehca_plpar_hcall_norets(unsigned long opcode, - unsigned long arg1, - unsigned long arg2, - unsigned long arg3, - unsigned long arg4, - unsigned long arg5, - unsigned long arg6, - unsigned long arg7) -{ - long ret; - int i, sleep_msecs; - unsigned long flags = 0; - - if (unlikely(ehca_debug_level >= 2)) - ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT, - opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7); - - for (i = 0; i < 5; i++) { - /* serialize hCalls to work around firmware issue */ - if (ehca_lock_hcalls) - spin_lock_irqsave(&hcall_lock, flags); - - ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4, - arg5, arg6, arg7); - - if (ehca_lock_hcalls) - spin_unlock_irqrestore(&hcall_lock, flags); - - if (H_IS_LONG_BUSY(ret)) { - sleep_msecs = get_longbusy_msecs(ret); - msleep_interruptible(sleep_msecs); - continue; - } - - if (ret < H_SUCCESS) - ehca_gen_err("opcode=%lx ret=%li " HCALL7_REGS_FORMAT, - opcode, ret, arg1, arg2, arg3, - arg4, arg5, arg6, arg7); - else - if (unlikely(ehca_debug_level >= 2)) - ehca_gen_dbg("opcode=%lx ret=%li", opcode, ret); - - return ret; - } - - return H_BUSY; -} - -static long ehca_plpar_hcall9(unsigned long opcode, - unsigned long *outs, /* array of 9 outputs */ - unsigned long arg1, - unsigned long arg2, - unsigned long arg3, - unsigned long arg4, - unsigned long arg5, - unsigned long arg6, - unsigned long arg7, - unsigned long arg8, - unsigned long arg9) -{ - long ret; - int i, sleep_msecs; - unsigned long flags = 0; - - if (unlikely(ehca_debug_level >= 2)) - ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode, - arg1, arg2, arg3, arg4, arg5, - arg6, arg7, arg8, arg9); - - for (i = 0; i < 5; i++) { - /* serialize hCalls to work around firmware issue */ - if (ehca_lock_hcalls) - spin_lock_irqsave(&hcall_lock, flags); - - ret = plpar_hcall9(opcode, outs, - arg1, arg2, arg3, arg4, arg5, - arg6, arg7, arg8, arg9); - - if (ehca_lock_hcalls) - spin_unlock_irqrestore(&hcall_lock, flags); - - if (H_IS_LONG_BUSY(ret)) { - sleep_msecs = get_longbusy_msecs(ret); - msleep_interruptible(sleep_msecs); - continue; - } - - if (ret < H_SUCCESS) { - ehca_gen_err("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, - opcode, arg1, arg2, arg3, arg4, arg5, - arg6, arg7, arg8, arg9); - ehca_gen_err("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT, - ret, outs[0], outs[1], outs[2], outs[3], - outs[4], outs[5], outs[6], outs[7], - outs[8]); - } else if (unlikely(ehca_debug_level >= 2)) - ehca_gen_dbg("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT, - ret, outs[0], outs[1], outs[2], outs[3], - outs[4], outs[5], outs[6], outs[7], - outs[8]); - return ret; - } - - return H_BUSY; -} - -u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle, - struct ehca_pfeq *pfeq, - const u32 neq_control, - const u32 number_of_entries, - struct ipz_eq_handle *eq_handle, - u32 *act_nr_of_entries, - u32 *act_pages, - u32 *eq_ist) -{ - u64 ret; - unsigned long outs[PLPAR_HCALL9_BUFSIZE]; - u64 allocate_controls; - - /* resource type */ - allocate_controls = 3ULL; - - /* ISN is associated */ - if (neq_control != 1) - allocate_controls = (1ULL << (63 - 7)) | allocate_controls; - else /* notification event queue */ - allocate_controls = (1ULL << 63) | allocate_controls; - - ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, - adapter_handle.handle, /* r4 */ - allocate_controls, /* r5 */ - number_of_entries, /* r6 */ - 0, 0, 0, 0, 0, 0); - eq_handle->handle = outs[0]; - *act_nr_of_entries = (u32)outs[3]; - *act_pages = (u32)outs[4]; - *eq_ist = (u32)outs[5]; - - if (ret == H_NOT_ENOUGH_RESOURCES) - ehca_gen_err("Not enough resource - ret=%lli ", ret); - - return ret; -} - -u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle, - struct ipz_eq_handle eq_handle, - const u64 event_mask) -{ - return ehca_plpar_hcall_norets(H_RESET_EVENTS, - adapter_handle.handle, /* r4 */ - eq_handle.handle, /* r5 */ - event_mask, /* r6 */ - 0, 0, 0, 0); -} - -u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle, - struct ehca_cq *cq, - struct ehca_alloc_cq_parms *param) -{ - int rc; - u64 ret; - unsigned long outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, - adapter_handle.handle, /* r4 */ - 2, /* r5 */ - param->eq_handle.handle, /* r6 */ - cq->token, /* r7 */ - param->nr_cqe, /* r8 */ - 0, 0, 0, 0); - cq->ipz_cq_handle.handle = outs[0]; - param->act_nr_of_entries = (u32)outs[3]; - param->act_pages = (u32)outs[4]; - - if (ret == H_SUCCESS) { - rc = hcp_galpas_ctor(&cq->galpas, 0, outs[5], outs[6]); - if (rc) { - ehca_gen_err("Could not establish HW access. rc=%d paddr=%#lx", - rc, outs[5]); - - ehca_plpar_hcall_norets(H_FREE_RESOURCE, - adapter_handle.handle, /* r4 */ - cq->ipz_cq_handle.handle, /* r5 */ - 0, 0, 0, 0, 0); - ret = H_NO_MEM; - } - } - - if (ret == H_NOT_ENOUGH_RESOURCES) - ehca_gen_err("Not enough resources. ret=%lli", ret); - - return ret; -} - -u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle, - struct ehca_alloc_qp_parms *parms, int is_user) -{ - int rc; - u64 ret; - u64 allocate_controls, max_r10_reg, r11, r12; - unsigned long outs[PLPAR_HCALL9_BUFSIZE]; - - allocate_controls = - EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type) - | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0) - | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype) - | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype) - | EHCA_BMASK_SET(H_ALL_RES_QP_STORAGE, parms->qp_storage) - | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE, - parms->squeue.page_size) - | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE, - parms->rqueue.page_size) - | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING, - !!(parms->ll_comp_flags & LLQP_RECV_COMP)) - | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING, - !!(parms->ll_comp_flags & LLQP_SEND_COMP)) - | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL, - parms->ud_av_l_key_ctl) - | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1); - - max_r10_reg = - EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR, - parms->squeue.max_wr + 1) - | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR, - parms->rqueue.max_wr + 1) - | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE, - parms->squeue.max_sge) - | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE, - parms->rqueue.max_sge); - - r11 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QP_TOKEN, parms->srq_token); - - if (parms->ext_type == EQPT_SRQ) - r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_LIMIT, parms->srq_limit); - else - r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QPN, parms->srq_qpn); - - ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, - adapter_handle.handle, /* r4 */ - allocate_controls, /* r5 */ - parms->send_cq_handle.handle, - parms->recv_cq_handle.handle, - parms->eq_handle.handle, - ((u64)parms->token << 32) | parms->pd.value, - max_r10_reg, r11, r12); - - parms->qp_handle.handle = outs[0]; - parms->real_qp_num = (u32)outs[1]; - parms->squeue.act_nr_wqes = - (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]); - parms->rqueue.act_nr_wqes = - (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]); - parms->squeue.act_nr_sges = - (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]); - parms->rqueue.act_nr_sges = - (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]); - parms->squeue.queue_size = - (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]); - parms->rqueue.queue_size = - (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]); - - if (ret == H_SUCCESS) { - rc = hcp_galpas_ctor(&parms->galpas, is_user, outs[6], outs[6]); - if (rc) { - ehca_gen_err("Could not establish HW access. rc=%d paddr=%#lx", - rc, outs[6]); - - ehca_plpar_hcall_norets(H_FREE_RESOURCE, - adapter_handle.handle, /* r4 */ - parms->qp_handle.handle, /* r5 */ - 0, 0, 0, 0, 0); - ret = H_NO_MEM; - } - } - - if (ret == H_NOT_ENOUGH_RESOURCES) - ehca_gen_err("Not enough resources. ret=%lli", ret); - - return ret; -} - -u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle, - const u8 port_id, - struct hipz_query_port *query_port_response_block) -{ - u64 ret; - u64 r_cb = __pa(query_port_response_block); - - if (r_cb & (EHCA_PAGESIZE-1)) { - ehca_gen_err("response block not page aligned"); - return H_PARAMETER; - } - - ret = ehca_plpar_hcall_norets(H_QUERY_PORT, - adapter_handle.handle, /* r4 */ - port_id, /* r5 */ - r_cb, /* r6 */ - 0, 0, 0, 0); - - if (ehca_debug_level >= 2) - ehca_dmp(query_port_response_block, 64, "response_block"); - - return ret; -} - -u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle, - const u8 port_id, const u32 port_cap, - const u8 init_type, const int modify_mask) -{ - u64 port_attributes = port_cap; - - if (modify_mask & IB_PORT_SHUTDOWN) - port_attributes |= EHCA_BMASK_SET(H_MP_SHUTDOWN, 1); - if (modify_mask & IB_PORT_INIT_TYPE) - port_attributes |= EHCA_BMASK_SET(H_MP_INIT_TYPE, init_type); - if (modify_mask & IB_PORT_RESET_QKEY_CNTR) - port_attributes |= EHCA_BMASK_SET(H_MP_RESET_QKEY_CTR, 1); - - return ehca_plpar_hcall_norets(H_MODIFY_PORT, - adapter_handle.handle, /* r4 */ - port_id, /* r5 */ - port_attributes, /* r6 */ - 0, 0, 0, 0); -} - -u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle, - struct hipz_query_hca *query_hca_rblock) -{ - u64 r_cb = __pa(query_hca_rblock); - - if (r_cb & (EHCA_PAGESIZE-1)) { - ehca_gen_err("response_block=%p not page aligned", - query_hca_rblock); - return H_PARAMETER; - } - - return ehca_plpar_hcall_norets(H_QUERY_HCA, - adapter_handle.handle, /* r4 */ - r_cb, /* r5 */ - 0, 0, 0, 0, 0); -} - -u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle, - const u8 pagesize, - const u8 queue_type, - const u64 resource_handle, - const u64 logical_address_of_page, - u64 count) -{ - return ehca_plpar_hcall_norets(H_REGISTER_RPAGES, - adapter_handle.handle, /* r4 */ - (u64)queue_type | ((u64)pagesize) << 8, - /* r5 */ - resource_handle, /* r6 */ - logical_address_of_page, /* r7 */ - count, /* r8 */ - 0, 0); -} - -u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle, - const struct ipz_eq_handle eq_handle, - struct ehca_pfeq *pfeq, - const u8 pagesize, - const u8 queue_type, - const u64 logical_address_of_page, - const u64 count) -{ - if (count != 1) { - ehca_gen_err("Ppage counter=%llx", count); - return H_PARAMETER; - } - return hipz_h_register_rpage(adapter_handle, - pagesize, - queue_type, - eq_handle.handle, - logical_address_of_page, count); -} - -u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle, - u32 ist) -{ - u64 ret; - ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE, - adapter_handle.handle, /* r4 */ - ist, /* r5 */ - 0, 0, 0, 0, 0); - - if (ret != H_SUCCESS && ret != H_BUSY) - ehca_gen_err("Could not query interrupt state."); - - return ret; -} - -u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle, - const struct ipz_cq_handle cq_handle, - struct ehca_pfcq *pfcq, - const u8 pagesize, - const u8 queue_type, - const u64 logical_address_of_page, - const u64 count, - const struct h_galpa gal) -{ - if (count != 1) { - ehca_gen_err("Page counter=%llx", count); - return H_PARAMETER; - } - - return hipz_h_register_rpage(adapter_handle, pagesize, queue_type, - cq_handle.handle, logical_address_of_page, - count); -} - -u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct ehca_pfqp *pfqp, - const u8 pagesize, - const u8 queue_type, - const u64 logical_address_of_page, - const u64 count, - const struct h_galpa galpa) -{ - if (count > 1) { - ehca_gen_err("Page counter=%llx", count); - return H_PARAMETER; - } - - return hipz_h_register_rpage(adapter_handle, pagesize, queue_type, - qp_handle.handle, logical_address_of_page, - count); -} - -u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct ehca_pfqp *pfqp, - void **log_addr_next_sq_wqe2processed, - void **log_addr_next_rq_wqe2processed, - int dis_and_get_function_code) -{ - u64 ret; - unsigned long outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs, - adapter_handle.handle, /* r4 */ - dis_and_get_function_code, /* r5 */ - qp_handle.handle, /* r6 */ - 0, 0, 0, 0, 0, 0); - if (log_addr_next_sq_wqe2processed) - *log_addr_next_sq_wqe2processed = (void *)outs[0]; - if (log_addr_next_rq_wqe2processed) - *log_addr_next_rq_wqe2processed = (void *)outs[1]; - - return ret; -} - -u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct ehca_pfqp *pfqp, - const u64 update_mask, - struct hcp_modify_qp_control_block *mqpcb, - struct h_galpa gal) -{ - u64 ret; - unsigned long outs[PLPAR_HCALL9_BUFSIZE]; - ret = ehca_plpar_hcall9(H_MODIFY_QP, outs, - adapter_handle.handle, /* r4 */ - qp_handle.handle, /* r5 */ - update_mask, /* r6 */ - __pa(mqpcb), /* r7 */ - 0, 0, 0, 0, 0); - - if (ret == H_NOT_ENOUGH_RESOURCES) - ehca_gen_err("Insufficient resources ret=%lli", ret); - - return ret; -} - -u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct ehca_pfqp *pfqp, - struct hcp_modify_qp_control_block *qqpcb, - struct h_galpa gal) -{ - return ehca_plpar_hcall_norets(H_QUERY_QP, - adapter_handle.handle, /* r4 */ - qp_handle.handle, /* r5 */ - __pa(qqpcb), /* r6 */ - 0, 0, 0, 0); -} - -u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle, - struct ehca_qp *qp) -{ - u64 ret; - unsigned long outs[PLPAR_HCALL9_BUFSIZE]; - - ret = hcp_galpas_dtor(&qp->galpas); - if (ret) { - ehca_gen_err("Could not destruct qp->galpas"); - return H_RESOURCE; - } - ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs, - adapter_handle.handle, /* r4 */ - /* function code */ - 1, /* r5 */ - qp->ipz_qp_handle.handle, /* r6 */ - 0, 0, 0, 0, 0, 0); - if (ret == H_HARDWARE) - ehca_gen_err("HCA not operational. ret=%lli", ret); - - ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE, - adapter_handle.handle, /* r4 */ - qp->ipz_qp_handle.handle, /* r5 */ - 0, 0, 0, 0, 0); - - if (ret == H_RESOURCE) - ehca_gen_err("Resource still in use. ret=%lli", ret); - - return ret; -} - -u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct h_galpa gal, - u32 port) -{ - return ehca_plpar_hcall_norets(H_DEFINE_AQP0, - adapter_handle.handle, /* r4 */ - qp_handle.handle, /* r5 */ - port, /* r6 */ - 0, 0, 0, 0); -} - -u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct h_galpa gal, - u32 port, u32 * pma_qp_nr, - u32 * bma_qp_nr) -{ - u64 ret; - unsigned long outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs, - adapter_handle.handle, /* r4 */ - qp_handle.handle, /* r5 */ - port, /* r6 */ - 0, 0, 0, 0, 0, 0); - *pma_qp_nr = (u32)outs[0]; - *bma_qp_nr = (u32)outs[1]; - - if (ret == H_ALIAS_EXIST) - ehca_gen_err("AQP1 already exists. ret=%lli", ret); - - return ret; -} - -u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct h_galpa gal, - u16 mcg_dlid, - u64 subnet_prefix, u64 interface_id) -{ - u64 ret; - - ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP, - adapter_handle.handle, /* r4 */ - qp_handle.handle, /* r5 */ - mcg_dlid, /* r6 */ - interface_id, /* r7 */ - subnet_prefix, /* r8 */ - 0, 0); - - if (ret == H_NOT_ENOUGH_RESOURCES) - ehca_gen_err("Not enough resources. ret=%lli", ret); - - return ret; -} - -u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct h_galpa gal, - u16 mcg_dlid, - u64 subnet_prefix, u64 interface_id) -{ - return ehca_plpar_hcall_norets(H_DETACH_MCQP, - adapter_handle.handle, /* r4 */ - qp_handle.handle, /* r5 */ - mcg_dlid, /* r6 */ - interface_id, /* r7 */ - subnet_prefix, /* r8 */ - 0, 0); -} - -u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle, - struct ehca_cq *cq, - u8 force_flag) -{ - u64 ret; - - ret = hcp_galpas_dtor(&cq->galpas); - if (ret) { - ehca_gen_err("Could not destruct cp->galpas"); - return H_RESOURCE; - } - - ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE, - adapter_handle.handle, /* r4 */ - cq->ipz_cq_handle.handle, /* r5 */ - force_flag != 0 ? 1L : 0L, /* r6 */ - 0, 0, 0, 0); - - if (ret == H_RESOURCE) - ehca_gen_err("H_FREE_RESOURCE failed ret=%lli ", ret); - - return ret; -} - -u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle, - struct ehca_eq *eq) -{ - u64 ret; - - ret = hcp_galpas_dtor(&eq->galpas); - if (ret) { - ehca_gen_err("Could not destruct eq->galpas"); - return H_RESOURCE; - } - - ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE, - adapter_handle.handle, /* r4 */ - eq->ipz_eq_handle.handle, /* r5 */ - 0, 0, 0, 0, 0); - - if (ret == H_RESOURCE) - ehca_gen_err("Resource in use. ret=%lli ", ret); - - return ret; -} - -u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - const u64 vaddr, - const u64 length, - const u32 access_ctrl, - const struct ipz_pd pd, - struct ehca_mr_hipzout_parms *outparms) -{ - u64 ret; - unsigned long outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, - adapter_handle.handle, /* r4 */ - 5, /* r5 */ - vaddr, /* r6 */ - length, /* r7 */ - (((u64)access_ctrl) << 32ULL), /* r8 */ - pd.value, /* r9 */ - 0, 0, 0); - outparms->handle.handle = outs[0]; - outparms->lkey = (u32)outs[2]; - outparms->rkey = (u32)outs[3]; - - return ret; -} - -u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - const u8 pagesize, - const u8 queue_type, - const u64 logical_address_of_page, - const u64 count) -{ - u64 ret; - - if (unlikely(ehca_debug_level >= 3)) { - if (count > 1) { - u64 *kpage; - int i; - kpage = __va(logical_address_of_page); - for (i = 0; i < count; i++) - ehca_gen_dbg("kpage[%d]=%p", - i, (void *)kpage[i]); - } else - ehca_gen_dbg("kpage=%p", - (void *)logical_address_of_page); - } - - if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) { - ehca_gen_err("logical_address_of_page not on a 4k boundary " - "adapter_handle=%llx mr=%p mr_handle=%llx " - "pagesize=%x queue_type=%x " - "logical_address_of_page=%llx count=%llx", - adapter_handle.handle, mr, - mr->ipz_mr_handle.handle, pagesize, queue_type, - logical_address_of_page, count); - ret = H_PARAMETER; - } else - ret = hipz_h_register_rpage(adapter_handle, pagesize, - queue_type, - mr->ipz_mr_handle.handle, - logical_address_of_page, count); - return ret; -} - -u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - struct ehca_mr_hipzout_parms *outparms) -{ - u64 ret; - unsigned long outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_QUERY_MR, outs, - adapter_handle.handle, /* r4 */ - mr->ipz_mr_handle.handle, /* r5 */ - 0, 0, 0, 0, 0, 0, 0); - outparms->len = outs[0]; - outparms->vaddr = outs[1]; - outparms->acl = outs[4] >> 32; - outparms->lkey = (u32)(outs[5] >> 32); - outparms->rkey = (u32)(outs[5] & (0xffffffff)); - - return ret; -} - -u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr) -{ - return ehca_plpar_hcall_norets(H_FREE_RESOURCE, - adapter_handle.handle, /* r4 */ - mr->ipz_mr_handle.handle, /* r5 */ - 0, 0, 0, 0, 0); -} - -u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - const u64 vaddr_in, - const u64 length, - const u32 access_ctrl, - const struct ipz_pd pd, - const u64 mr_addr_cb, - struct ehca_mr_hipzout_parms *outparms) -{ - u64 ret; - unsigned long outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs, - adapter_handle.handle, /* r4 */ - mr->ipz_mr_handle.handle, /* r5 */ - vaddr_in, /* r6 */ - length, /* r7 */ - /* r8 */ - ((((u64)access_ctrl) << 32ULL) | pd.value), - mr_addr_cb, /* r9 */ - 0, 0, 0); - outparms->vaddr = outs[1]; - outparms->lkey = (u32)outs[2]; - outparms->rkey = (u32)outs[3]; - - return ret; -} - -u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - const struct ehca_mr *orig_mr, - const u64 vaddr_in, - const u32 access_ctrl, - const struct ipz_pd pd, - struct ehca_mr_hipzout_parms *outparms) -{ - u64 ret; - unsigned long outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs, - adapter_handle.handle, /* r4 */ - orig_mr->ipz_mr_handle.handle, /* r5 */ - vaddr_in, /* r6 */ - (((u64)access_ctrl) << 32ULL), /* r7 */ - pd.value, /* r8 */ - 0, 0, 0, 0); - outparms->handle.handle = outs[0]; - outparms->lkey = (u32)outs[2]; - outparms->rkey = (u32)outs[3]; - - return ret; -} - -u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mw *mw, - const struct ipz_pd pd, - struct ehca_mw_hipzout_parms *outparms) -{ - u64 ret; - unsigned long outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, - adapter_handle.handle, /* r4 */ - 6, /* r5 */ - pd.value, /* r6 */ - 0, 0, 0, 0, 0, 0); - outparms->handle.handle = outs[0]; - outparms->rkey = (u32)outs[3]; - - return ret; -} - -u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mw *mw, - struct ehca_mw_hipzout_parms *outparms) -{ - u64 ret; - unsigned long outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_QUERY_MW, outs, - adapter_handle.handle, /* r4 */ - mw->ipz_mw_handle.handle, /* r5 */ - 0, 0, 0, 0, 0, 0, 0); - outparms->rkey = (u32)outs[3]; - - return ret; -} - -u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mw *mw) -{ - return ehca_plpar_hcall_norets(H_FREE_RESOURCE, - adapter_handle.handle, /* r4 */ - mw->ipz_mw_handle.handle, /* r5 */ - 0, 0, 0, 0, 0); -} - -u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle, - const u64 ressource_handle, - void *rblock, - unsigned long *byte_count) -{ - u64 r_cb = __pa(rblock); - - if (r_cb & (EHCA_PAGESIZE-1)) { - ehca_gen_err("rblock not page aligned."); - return H_PARAMETER; - } - - return ehca_plpar_hcall_norets(H_ERROR_DATA, - adapter_handle.handle, - ressource_handle, - r_cb, - 0, 0, 0, 0); -} - -u64 hipz_h_eoi(int irq) -{ - unsigned long xirr; - - iosync(); - xirr = (0xffULL << 24) | irq; - - return plpar_hcall_norets(H_EOI, xirr); -} diff --git a/drivers/staging/rdma/ehca/hcp_if.h b/drivers/staging/rdma/ehca/hcp_if.h deleted file mode 100644 index a46e514c367b..000000000000 --- a/drivers/staging/rdma/ehca/hcp_if.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Firmware Infiniband Interface code for POWER - * - * Authors: Christoph Raisch - * Hoang-Nam Nguyen - * Gerd Bayer - * Waleri Fomin - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HCP_IF_H__ -#define __HCP_IF_H__ - -#include "ehca_classes.h" -#include "ehca_tools.h" -#include "hipz_hw.h" - -/* - * hipz_h_alloc_resource_eq allocates EQ resources in HW and FW, initialize - * resources, create the empty EQPT (ring). - */ -u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle, - struct ehca_pfeq *pfeq, - const u32 neq_control, - const u32 number_of_entries, - struct ipz_eq_handle *eq_handle, - u32 * act_nr_of_entries, - u32 * act_pages, - u32 * eq_ist); - -u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle, - struct ipz_eq_handle eq_handle, - const u64 event_mask); -/* - * hipz_h_allocate_resource_cq allocates CQ resources in HW and FW, initialize - * resources, create the empty CQPT (ring). - */ -u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle, - struct ehca_cq *cq, - struct ehca_alloc_cq_parms *param); - - -/* - * hipz_h_alloc_resource_qp allocates QP resources in HW and FW, - * initialize resources, create empty QPPTs (2 rings). - */ -u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle, - struct ehca_alloc_qp_parms *parms, int is_user); - -u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle, - const u8 port_id, - struct hipz_query_port *query_port_response_block); - -u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle, - const u8 port_id, const u32 port_cap, - const u8 init_type, const int modify_mask); - -u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle, - struct hipz_query_hca *query_hca_rblock); - -/* - * hipz_h_register_rpage internal function in hcp_if.h for all - * hcp_H_REGISTER_RPAGE calls. - */ -u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle, - const u8 pagesize, - const u8 queue_type, - const u64 resource_handle, - const u64 logical_address_of_page, - u64 count); - -u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle, - const struct ipz_eq_handle eq_handle, - struct ehca_pfeq *pfeq, - const u8 pagesize, - const u8 queue_type, - const u64 logical_address_of_page, - const u64 count); - -u64 hipz_h_query_int_state(const struct ipz_adapter_handle - hcp_adapter_handle, - u32 ist); - -u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle, - const struct ipz_cq_handle cq_handle, - struct ehca_pfcq *pfcq, - const u8 pagesize, - const u8 queue_type, - const u64 logical_address_of_page, - const u64 count, - const struct h_galpa gal); - -u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct ehca_pfqp *pfqp, - const u8 pagesize, - const u8 queue_type, - const u64 logical_address_of_page, - const u64 count, - const struct h_galpa galpa); - -u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct ehca_pfqp *pfqp, - void **log_addr_next_sq_wqe_tb_processed, - void **log_addr_next_rq_wqe_tb_processed, - int dis_and_get_function_code); -enum hcall_sigt { - HCALL_SIGT_NO_CQE = 0, - HCALL_SIGT_BY_WQE = 1, - HCALL_SIGT_EVERY = 2 -}; - -u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct ehca_pfqp *pfqp, - const u64 update_mask, - struct hcp_modify_qp_control_block *mqpcb, - struct h_galpa gal); - -u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct ehca_pfqp *pfqp, - struct hcp_modify_qp_control_block *qqpcb, - struct h_galpa gal); - -u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle, - struct ehca_qp *qp); - -u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct h_galpa gal, - u32 port); - -u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct h_galpa gal, - u32 port, u32 * pma_qp_nr, - u32 * bma_qp_nr); - -u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct h_galpa gal, - u16 mcg_dlid, - u64 subnet_prefix, u64 interface_id); - -u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct h_galpa gal, - u16 mcg_dlid, - u64 subnet_prefix, u64 interface_id); - -u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle, - struct ehca_cq *cq, - u8 force_flag); - -u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle, - struct ehca_eq *eq); - -/* - * hipz_h_alloc_resource_mr allocates MR resources in HW and FW, initialize - * resources. - */ -u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - const u64 vaddr, - const u64 length, - const u32 access_ctrl, - const struct ipz_pd pd, - struct ehca_mr_hipzout_parms *outparms); - -/* hipz_h_register_rpage_mr registers MR resource pages in HW and FW */ -u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - const u8 pagesize, - const u8 queue_type, - const u64 logical_address_of_page, - const u64 count); - -/* hipz_h_query_mr queries MR in HW and FW */ -u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - struct ehca_mr_hipzout_parms *outparms); - -/* hipz_h_free_resource_mr frees MR resources in HW and FW */ -u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr); - -/* hipz_h_reregister_pmr reregisters MR in HW and FW */ -u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - const u64 vaddr_in, - const u64 length, - const u32 access_ctrl, - const struct ipz_pd pd, - const u64 mr_addr_cb, - struct ehca_mr_hipzout_parms *outparms); - -/* hipz_h_register_smr register shared MR in HW and FW */ -u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - const struct ehca_mr *orig_mr, - const u64 vaddr_in, - const u32 access_ctrl, - const struct ipz_pd pd, - struct ehca_mr_hipzout_parms *outparms); - -/* - * hipz_h_alloc_resource_mw allocates MW resources in HW and FW, initialize - * resources. - */ -u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mw *mw, - const struct ipz_pd pd, - struct ehca_mw_hipzout_parms *outparms); - -/* hipz_h_query_mw queries MW in HW and FW */ -u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mw *mw, - struct ehca_mw_hipzout_parms *outparms); - -/* hipz_h_free_resource_mw frees MW resources in HW and FW */ -u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mw *mw); - -u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle, - const u64 ressource_handle, - void *rblock, - unsigned long *byte_count); -u64 hipz_h_eoi(int irq); - -#endif /* __HCP_IF_H__ */ diff --git a/drivers/staging/rdma/ehca/hcp_phyp.c b/drivers/staging/rdma/ehca/hcp_phyp.c deleted file mode 100644 index 077376ff3d28..000000000000 --- a/drivers/staging/rdma/ehca/hcp_phyp.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * load store abstraction for ehca register access with tracing - * - * Authors: Christoph Raisch - * Hoang-Nam Nguyen - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ehca_classes.h" -#include "hipz_hw.h" - -u64 hcall_map_page(u64 physaddr) -{ - return (u64)ioremap(physaddr, EHCA_PAGESIZE); -} - -int hcall_unmap_page(u64 mapaddr) -{ - iounmap((volatile void __iomem *) mapaddr); - return 0; -} - -int hcp_galpas_ctor(struct h_galpas *galpas, int is_user, - u64 paddr_kernel, u64 paddr_user) -{ - if (!is_user) { - galpas->kernel.fw_handle = hcall_map_page(paddr_kernel); - if (!galpas->kernel.fw_handle) - return -ENOMEM; - } else - galpas->kernel.fw_handle = 0; - - galpas->user.fw_handle = paddr_user; - - return 0; -} - -int hcp_galpas_dtor(struct h_galpas *galpas) -{ - if (galpas->kernel.fw_handle) { - int ret = hcall_unmap_page(galpas->kernel.fw_handle); - if (ret) - return ret; - } - - galpas->user.fw_handle = galpas->kernel.fw_handle = 0; - - return 0; -} diff --git a/drivers/staging/rdma/ehca/hcp_phyp.h b/drivers/staging/rdma/ehca/hcp_phyp.h deleted file mode 100644 index d1b029910249..000000000000 --- a/drivers/staging/rdma/ehca/hcp_phyp.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Firmware calls - * - * Authors: Christoph Raisch - * Hoang-Nam Nguyen - * Waleri Fomin - * Gerd Bayer - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HCP_PHYP_H__ -#define __HCP_PHYP_H__ - - -/* - * eHCA page (mapped into memory) - * resource to access eHCA register pages in CPU address space -*/ -struct h_galpa { - u64 fw_handle; - /* for pSeries this is a 64bit memory address where - I/O memory is mapped into CPU address space (kv) */ -}; - -/* - * resource to access eHCA address space registers, all types - */ -struct h_galpas { - u32 pid; /*PID of userspace galpa checking */ - struct h_galpa user; /* user space accessible resource, - set to 0 if unused */ - struct h_galpa kernel; /* kernel space accessible resource, - set to 0 if unused */ -}; - -static inline u64 hipz_galpa_load(struct h_galpa galpa, u32 offset) -{ - u64 addr = galpa.fw_handle + offset; - return *(volatile u64 __force *)addr; -} - -static inline void hipz_galpa_store(struct h_galpa galpa, u32 offset, u64 value) -{ - u64 addr = galpa.fw_handle + offset; - *(volatile u64 __force *)addr = value; -} - -int hcp_galpas_ctor(struct h_galpas *galpas, int is_user, - u64 paddr_kernel, u64 paddr_user); - -int hcp_galpas_dtor(struct h_galpas *galpas); - -u64 hcall_map_page(u64 physaddr); - -int hcall_unmap_page(u64 mapaddr); - -#endif diff --git a/drivers/staging/rdma/ehca/hipz_fns.h b/drivers/staging/rdma/ehca/hipz_fns.h deleted file mode 100644 index 9dac93d02140..000000000000 --- a/drivers/staging/rdma/ehca/hipz_fns.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * HW abstraction register functions - * - * Authors: Christoph Raisch - * Reinhard Ernst - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIPZ_FNS_H__ -#define __HIPZ_FNS_H__ - -#include "ehca_classes.h" -#include "hipz_hw.h" - -#include "hipz_fns_core.h" - -#define hipz_galpa_store_eq(gal, offset, value) \ - hipz_galpa_store(gal, EQTEMM_OFFSET(offset), value) - -#define hipz_galpa_load_eq(gal, offset) \ - hipz_galpa_load(gal, EQTEMM_OFFSET(offset)) - -#define hipz_galpa_store_qped(gal, offset, value) \ - hipz_galpa_store(gal, QPEDMM_OFFSET(offset), value) - -#define hipz_galpa_load_qped(gal, offset) \ - hipz_galpa_load(gal, QPEDMM_OFFSET(offset)) - -#define hipz_galpa_store_mrmw(gal, offset, value) \ - hipz_galpa_store(gal, MRMWMM_OFFSET(offset), value) - -#define hipz_galpa_load_mrmw(gal, offset) \ - hipz_galpa_load(gal, MRMWMM_OFFSET(offset)) - -#endif diff --git a/drivers/staging/rdma/ehca/hipz_fns_core.h b/drivers/staging/rdma/ehca/hipz_fns_core.h deleted file mode 100644 index 868735fd3187..000000000000 --- a/drivers/staging/rdma/ehca/hipz_fns_core.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * HW abstraction register functions - * - * Authors: Christoph Raisch - * Heiko J Schick - * Hoang-Nam Nguyen - * Reinhard Ernst - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIPZ_FNS_CORE_H__ -#define __HIPZ_FNS_CORE_H__ - -#include "hcp_phyp.h" -#include "hipz_hw.h" - -#define hipz_galpa_store_cq(gal, offset, value) \ - hipz_galpa_store(gal, CQTEMM_OFFSET(offset), value) - -#define hipz_galpa_load_cq(gal, offset) \ - hipz_galpa_load(gal, CQTEMM_OFFSET(offset)) - -#define hipz_galpa_store_qp(gal, offset, value) \ - hipz_galpa_store(gal, QPTEMM_OFFSET(offset), value) -#define hipz_galpa_load_qp(gal, offset) \ - hipz_galpa_load(gal, QPTEMM_OFFSET(offset)) - -static inline void hipz_update_sqa(struct ehca_qp *qp, u16 nr_wqes) -{ - /* ringing doorbell :-) */ - hipz_galpa_store_qp(qp->galpas.kernel, qpx_sqa, - EHCA_BMASK_SET(QPX_SQADDER, nr_wqes)); -} - -static inline void hipz_update_rqa(struct ehca_qp *qp, u16 nr_wqes) -{ - /* ringing doorbell :-) */ - hipz_galpa_store_qp(qp->galpas.kernel, qpx_rqa, - EHCA_BMASK_SET(QPX_RQADDER, nr_wqes)); -} - -static inline void hipz_update_feca(struct ehca_cq *cq, u32 nr_cqes) -{ - hipz_galpa_store_cq(cq->galpas.kernel, cqx_feca, - EHCA_BMASK_SET(CQX_FECADDER, nr_cqes)); -} - -static inline void hipz_set_cqx_n0(struct ehca_cq *cq, u32 value) -{ - u64 cqx_n0_reg; - - hipz_galpa_store_cq(cq->galpas.kernel, cqx_n0, - EHCA_BMASK_SET(CQX_N0_GENERATE_SOLICITED_COMP_EVENT, - value)); - cqx_n0_reg = hipz_galpa_load_cq(cq->galpas.kernel, cqx_n0); -} - -static inline void hipz_set_cqx_n1(struct ehca_cq *cq, u32 value) -{ - u64 cqx_n1_reg; - - hipz_galpa_store_cq(cq->galpas.kernel, cqx_n1, - EHCA_BMASK_SET(CQX_N1_GENERATE_COMP_EVENT, value)); - cqx_n1_reg = hipz_galpa_load_cq(cq->galpas.kernel, cqx_n1); -} - -#endif /* __HIPZ_FNC_CORE_H__ */ diff --git a/drivers/staging/rdma/ehca/hipz_hw.h b/drivers/staging/rdma/ehca/hipz_hw.h deleted file mode 100644 index bf996c7acc42..000000000000 --- a/drivers/staging/rdma/ehca/hipz_hw.h +++ /dev/null @@ -1,414 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * eHCA register definitions - * - * Authors: Waleri Fomin - * Christoph Raisch - * Reinhard Ernst - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIPZ_HW_H__ -#define __HIPZ_HW_H__ - -#include "ehca_tools.h" - -#define EHCA_MAX_MTU 4 - -/* QP Table Entry Memory Map */ -struct hipz_qptemm { - u64 qpx_hcr; - u64 qpx_c; - u64 qpx_herr; - u64 qpx_aer; -/* 0x20*/ - u64 qpx_sqa; - u64 qpx_sqc; - u64 qpx_rqa; - u64 qpx_rqc; -/* 0x40*/ - u64 qpx_st; - u64 qpx_pmstate; - u64 qpx_pmfa; - u64 qpx_pkey; -/* 0x60*/ - u64 qpx_pkeya; - u64 qpx_pkeyb; - u64 qpx_pkeyc; - u64 qpx_pkeyd; -/* 0x80*/ - u64 qpx_qkey; - u64 qpx_dqp; - u64 qpx_dlidp; - u64 qpx_portp; -/* 0xa0*/ - u64 qpx_slidp; - u64 qpx_slidpp; - u64 qpx_dlida; - u64 qpx_porta; -/* 0xc0*/ - u64 qpx_slida; - u64 qpx_slidpa; - u64 qpx_slvl; - u64 qpx_ipd; -/* 0xe0*/ - u64 qpx_mtu; - u64 qpx_lato; - u64 qpx_rlimit; - u64 qpx_rnrlimit; -/* 0x100*/ - u64 qpx_t; - u64 qpx_sqhp; - u64 qpx_sqptp; - u64 qpx_nspsn; -/* 0x120*/ - u64 qpx_nspsnhwm; - u64 reserved1; - u64 qpx_sdsi; - u64 qpx_sdsbc; -/* 0x140*/ - u64 qpx_sqwsize; - u64 qpx_sqwts; - u64 qpx_lsn; - u64 qpx_nssn; -/* 0x160 */ - u64 qpx_mor; - u64 qpx_cor; - u64 qpx_sqsize; - u64 qpx_erc; -/* 0x180*/ - u64 qpx_rnrrc; - u64 qpx_ernrwt; - u64 qpx_rnrresp; - u64 qpx_lmsna; -/* 0x1a0 */ - u64 qpx_sqhpc; - u64 qpx_sqcptp; - u64 qpx_sigt; - u64 qpx_wqecnt; -/* 0x1c0*/ - u64 qpx_rqhp; - u64 qpx_rqptp; - u64 qpx_rqsize; - u64 qpx_nrr; -/* 0x1e0*/ - u64 qpx_rdmac; - u64 qpx_nrpsn; - u64 qpx_lapsn; - u64 qpx_lcr; -/* 0x200*/ - u64 qpx_rwc; - u64 qpx_rwva; - u64 qpx_rdsi; - u64 qpx_rdsbc; -/* 0x220*/ - u64 qpx_rqwsize; - u64 qpx_crmsn; - u64 qpx_rdd; - u64 qpx_larpsn; -/* 0x240*/ - u64 qpx_pd; - u64 qpx_scqn; - u64 qpx_rcqn; - u64 qpx_aeqn; -/* 0x260*/ - u64 qpx_aaelog; - u64 qpx_ram; - u64 qpx_rdmaqe0; - u64 qpx_rdmaqe1; -/* 0x280*/ - u64 qpx_rdmaqe2; - u64 qpx_rdmaqe3; - u64 qpx_nrpsnhwm; -/* 0x298*/ - u64 reserved[(0x400 - 0x298) / 8]; -/* 0x400 extended data */ - u64 reserved_ext[(0x500 - 0x400) / 8]; -/* 0x500 */ - u64 reserved2[(0x1000 - 0x500) / 8]; -/* 0x1000 */ -}; - -#define QPX_SQADDER EHCA_BMASK_IBM(48, 63) -#define QPX_RQADDER EHCA_BMASK_IBM(48, 63) -#define QPX_AAELOG_RESET_SRQ_LIMIT EHCA_BMASK_IBM(3, 3) - -#define QPTEMM_OFFSET(x) offsetof(struct hipz_qptemm, x) - -/* MRMWPT Entry Memory Map */ -struct hipz_mrmwmm { - /* 0x00 */ - u64 mrx_hcr; - - u64 mrx_c; - u64 mrx_herr; - u64 mrx_aer; - /* 0x20 */ - u64 mrx_pp; - u64 reserved1; - u64 reserved2; - u64 reserved3; - /* 0x40 */ - u64 reserved4[(0x200 - 0x40) / 8]; - /* 0x200 */ - u64 mrx_ctl[64]; - -}; - -#define MRMWMM_OFFSET(x) offsetof(struct hipz_mrmwmm, x) - -struct hipz_qpedmm { - /* 0x00 */ - u64 reserved0[(0x400) / 8]; - /* 0x400 */ - u64 qpedx_phh; - u64 qpedx_ppsgp; - /* 0x410 */ - u64 qpedx_ppsgu; - u64 qpedx_ppdgp; - /* 0x420 */ - u64 qpedx_ppdgu; - u64 qpedx_aph; - /* 0x430 */ - u64 qpedx_apsgp; - u64 qpedx_apsgu; - /* 0x440 */ - u64 qpedx_apdgp; - u64 qpedx_apdgu; - /* 0x450 */ - u64 qpedx_apav; - u64 qpedx_apsav; - /* 0x460 */ - u64 qpedx_hcr; - u64 reserved1[4]; - /* 0x488 */ - u64 qpedx_rrl0; - /* 0x490 */ - u64 qpedx_rrrkey0; - u64 qpedx_rrva0; - /* 0x4a0 */ - u64 reserved2; - u64 qpedx_rrl1; - /* 0x4b0 */ - u64 qpedx_rrrkey1; - u64 qpedx_rrva1; - /* 0x4c0 */ - u64 reserved3; - u64 qpedx_rrl2; - /* 0x4d0 */ - u64 qpedx_rrrkey2; - u64 qpedx_rrva2; - /* 0x4e0 */ - u64 reserved4; - u64 qpedx_rrl3; - /* 0x4f0 */ - u64 qpedx_rrrkey3; - u64 qpedx_rrva3; -}; - -#define QPEDMM_OFFSET(x) offsetof(struct hipz_qpedmm, x) - -/* CQ Table Entry Memory Map */ -struct hipz_cqtemm { - u64 cqx_hcr; - u64 cqx_c; - u64 cqx_herr; - u64 cqx_aer; -/* 0x20 */ - u64 cqx_ptp; - u64 cqx_tp; - u64 cqx_fec; - u64 cqx_feca; -/* 0x40 */ - u64 cqx_ep; - u64 cqx_eq; -/* 0x50 */ - u64 reserved1; - u64 cqx_n0; -/* 0x60 */ - u64 cqx_n1; - u64 reserved2[(0x1000 - 0x60) / 8]; -/* 0x1000 */ -}; - -#define CQX_FEC_CQE_CNT EHCA_BMASK_IBM(32, 63) -#define CQX_FECADDER EHCA_BMASK_IBM(32, 63) -#define CQX_N0_GENERATE_SOLICITED_COMP_EVENT EHCA_BMASK_IBM(0, 0) -#define CQX_N1_GENERATE_COMP_EVENT EHCA_BMASK_IBM(0, 0) - -#define CQTEMM_OFFSET(x) offsetof(struct hipz_cqtemm, x) - -/* EQ Table Entry Memory Map */ -struct hipz_eqtemm { - u64 eqx_hcr; - u64 eqx_c; - - u64 eqx_herr; - u64 eqx_aer; -/* 0x20 */ - u64 eqx_ptp; - u64 eqx_tp; - u64 eqx_ssba; - u64 eqx_psba; - -/* 0x40 */ - u64 eqx_cec; - u64 eqx_meql; - u64 eqx_xisbi; - u64 eqx_xisc; -/* 0x60 */ - u64 eqx_it; - -}; - -#define EQTEMM_OFFSET(x) offsetof(struct hipz_eqtemm, x) - -/* access control defines for MR/MW */ -#define HIPZ_ACCESSCTRL_L_WRITE 0x00800000 -#define HIPZ_ACCESSCTRL_R_WRITE 0x00400000 -#define HIPZ_ACCESSCTRL_R_READ 0x00200000 -#define HIPZ_ACCESSCTRL_R_ATOMIC 0x00100000 -#define HIPZ_ACCESSCTRL_MW_BIND 0x00080000 - -/* query hca response block */ -struct hipz_query_hca { - u32 cur_reliable_dg; - u32 cur_qp; - u32 cur_cq; - u32 cur_eq; - u32 cur_mr; - u32 cur_mw; - u32 cur_ee_context; - u32 cur_mcast_grp; - u32 cur_qp_attached_mcast_grp; - u32 reserved1; - u32 cur_ipv6_qp; - u32 cur_eth_qp; - u32 cur_hp_mr; - u32 reserved2[3]; - u32 max_rd_domain; - u32 max_qp; - u32 max_cq; - u32 max_eq; - u32 max_mr; - u32 max_hp_mr; - u32 max_mw; - u32 max_mrwpte; - u32 max_special_mrwpte; - u32 max_rd_ee_context; - u32 max_mcast_grp; - u32 max_total_mcast_qp_attach; - u32 max_mcast_qp_attach; - u32 max_raw_ipv6_qp; - u32 max_raw_ethy_qp; - u32 internal_clock_frequency; - u32 max_pd; - u32 max_ah; - u32 max_cqe; - u32 max_wqes_wq; - u32 max_partitions; - u32 max_rr_ee_context; - u32 max_rr_qp; - u32 max_rr_hca; - u32 max_act_wqs_ee_context; - u32 max_act_wqs_qp; - u32 max_sge; - u32 max_sge_rd; - u32 memory_page_size_supported; - u64 max_mr_size; - u32 local_ca_ack_delay; - u32 num_ports; - u32 vendor_id; - u32 vendor_part_id; - u32 hw_ver; - u64 node_guid; - u64 hca_cap_indicators; - u32 data_counter_register_size; - u32 max_shared_rq; - u32 max_isns_eq; - u32 max_neq; -} __attribute__ ((packed)); - -#define HCA_CAP_AH_PORT_NR_CHECK EHCA_BMASK_IBM( 0, 0) -#define HCA_CAP_ATOMIC EHCA_BMASK_IBM( 1, 1) -#define HCA_CAP_AUTO_PATH_MIG EHCA_BMASK_IBM( 2, 2) -#define HCA_CAP_BAD_P_KEY_CTR EHCA_BMASK_IBM( 3, 3) -#define HCA_CAP_SQD_RTS_PORT_CHANGE EHCA_BMASK_IBM( 4, 4) -#define HCA_CAP_CUR_QP_STATE_MOD EHCA_BMASK_IBM( 5, 5) -#define HCA_CAP_INIT_TYPE EHCA_BMASK_IBM( 6, 6) -#define HCA_CAP_PORT_ACTIVE_EVENT EHCA_BMASK_IBM( 7, 7) -#define HCA_CAP_Q_KEY_VIOL_CTR EHCA_BMASK_IBM( 8, 8) -#define HCA_CAP_WQE_RESIZE EHCA_BMASK_IBM( 9, 9) -#define HCA_CAP_RAW_PACKET_MCAST EHCA_BMASK_IBM(10, 10) -#define HCA_CAP_SHUTDOWN_PORT EHCA_BMASK_IBM(11, 11) -#define HCA_CAP_RC_LL_QP EHCA_BMASK_IBM(12, 12) -#define HCA_CAP_SRQ EHCA_BMASK_IBM(13, 13) -#define HCA_CAP_UD_LL_QP EHCA_BMASK_IBM(16, 16) -#define HCA_CAP_RESIZE_MR EHCA_BMASK_IBM(17, 17) -#define HCA_CAP_MINI_QP EHCA_BMASK_IBM(18, 18) -#define HCA_CAP_H_ALLOC_RES_SYNC EHCA_BMASK_IBM(19, 19) - -/* query port response block */ -struct hipz_query_port { - u32 state; - u32 bad_pkey_cntr; - u32 lmc; - u32 lid; - u32 subnet_timeout; - u32 qkey_viol_cntr; - u32 sm_sl; - u32 sm_lid; - u32 capability_mask; - u32 init_type_reply; - u32 pkey_tbl_len; - u32 gid_tbl_len; - u64 gid_prefix; - u32 port_nr; - u16 pkey_entries[16]; - u8 reserved1[32]; - u32 trent_size; - u32 trbuf_size; - u64 max_msg_sz; - u32 max_mtu; - u32 vl_cap; - u32 phys_pstate; - u32 phys_state; - u32 phys_speed; - u32 phys_width; - u8 reserved2[1884]; - u64 guid_entries[255]; -} __attribute__ ((packed)); - -#endif diff --git a/drivers/staging/rdma/ehca/ipz_pt_fn.c b/drivers/staging/rdma/ehca/ipz_pt_fn.c deleted file mode 100644 index 7ffc748cb973..000000000000 --- a/drivers/staging/rdma/ehca/ipz_pt_fn.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * internal queue handling - * - * Authors: Waleri Fomin - * Reinhard Ernst - * Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "ehca_tools.h" -#include "ipz_pt_fn.h" -#include "ehca_classes.h" - -#define PAGES_PER_KPAGE (PAGE_SIZE >> EHCA_PAGESHIFT) - -struct kmem_cache *small_qp_cache; - -void *ipz_qpageit_get_inc(struct ipz_queue *queue) -{ - void *ret = ipz_qeit_get(queue); - queue->current_q_offset += queue->pagesize; - if (queue->current_q_offset > queue->queue_length) { - queue->current_q_offset -= queue->pagesize; - ret = NULL; - } - if (((u64)ret) % queue->pagesize) { - ehca_gen_err("ERROR!! not at PAGE-Boundary"); - return NULL; - } - return ret; -} - -void *ipz_qeit_eq_get_inc(struct ipz_queue *queue) -{ - void *ret = ipz_qeit_get(queue); - u64 last_entry_in_q = queue->queue_length - queue->qe_size; - - queue->current_q_offset += queue->qe_size; - if (queue->current_q_offset > last_entry_in_q) { - queue->current_q_offset = 0; - queue->toggle_state = (~queue->toggle_state) & 1; - } - - return ret; -} - -int ipz_queue_abs_to_offset(struct ipz_queue *queue, u64 addr, u64 *q_offset) -{ - int i; - for (i = 0; i < queue->queue_length / queue->pagesize; i++) { - u64 page = __pa(queue->queue_pages[i]); - if (addr >= page && addr < page + queue->pagesize) { - *q_offset = addr - page + i * queue->pagesize; - return 0; - } - } - return -EINVAL; -} - -#if PAGE_SHIFT < EHCA_PAGESHIFT -#error Kernel pages must be at least as large than eHCA pages (4K) ! -#endif - -/* - * allocate pages for queue: - * outer loop allocates whole kernel pages (page aligned) and - * inner loop divides a kernel page into smaller hca queue pages - */ -static int alloc_queue_pages(struct ipz_queue *queue, const u32 nr_of_pages) -{ - int k, f = 0; - u8 *kpage; - - while (f < nr_of_pages) { - kpage = (u8 *)get_zeroed_page(GFP_KERNEL); - if (!kpage) - goto out; - - for (k = 0; k < PAGES_PER_KPAGE && f < nr_of_pages; k++) { - queue->queue_pages[f] = (struct ipz_page *)kpage; - kpage += EHCA_PAGESIZE; - f++; - } - } - return 1; - -out: - for (f = 0; f < nr_of_pages && queue->queue_pages[f]; - f += PAGES_PER_KPAGE) - free_page((unsigned long)(queue->queue_pages)[f]); - return 0; -} - -static int alloc_small_queue_page(struct ipz_queue *queue, struct ehca_pd *pd) -{ - int order = ilog2(queue->pagesize) - 9; - struct ipz_small_queue_page *page; - unsigned long bit; - - mutex_lock(&pd->lock); - - if (!list_empty(&pd->free[order])) - page = list_entry(pd->free[order].next, - struct ipz_small_queue_page, list); - else { - page = kmem_cache_zalloc(small_qp_cache, GFP_KERNEL); - if (!page) - goto out; - - page->page = get_zeroed_page(GFP_KERNEL); - if (!page->page) { - kmem_cache_free(small_qp_cache, page); - goto out; - } - - list_add(&page->list, &pd->free[order]); - } - - bit = find_first_zero_bit(page->bitmap, IPZ_SPAGE_PER_KPAGE >> order); - __set_bit(bit, page->bitmap); - page->fill++; - - if (page->fill == IPZ_SPAGE_PER_KPAGE >> order) - list_move(&page->list, &pd->full[order]); - - mutex_unlock(&pd->lock); - - queue->queue_pages[0] = (void *)(page->page | (bit << (order + 9))); - queue->small_page = page; - queue->offset = bit << (order + 9); - return 1; - -out: - ehca_err(pd->ib_pd.device, "failed to allocate small queue page"); - mutex_unlock(&pd->lock); - return 0; -} - -static void free_small_queue_page(struct ipz_queue *queue, struct ehca_pd *pd) -{ - int order = ilog2(queue->pagesize) - 9; - struct ipz_small_queue_page *page = queue->small_page; - unsigned long bit; - int free_page = 0; - - bit = ((unsigned long)queue->queue_pages[0] & ~PAGE_MASK) - >> (order + 9); - - mutex_lock(&pd->lock); - - __clear_bit(bit, page->bitmap); - page->fill--; - - if (page->fill == 0) { - list_del(&page->list); - free_page = 1; - } - - if (page->fill == (IPZ_SPAGE_PER_KPAGE >> order) - 1) - /* the page was full until we freed the chunk */ - list_move_tail(&page->list, &pd->free[order]); - - mutex_unlock(&pd->lock); - - if (free_page) { - free_page(page->page); - kmem_cache_free(small_qp_cache, page); - } -} - -int ipz_queue_ctor(struct ehca_pd *pd, struct ipz_queue *queue, - const u32 nr_of_pages, const u32 pagesize, - const u32 qe_size, const u32 nr_of_sg, - int is_small) -{ - if (pagesize > PAGE_SIZE) { - ehca_gen_err("FATAL ERROR: pagesize=%x " - "is greater than kernel page size", pagesize); - return 0; - } - - /* init queue fields */ - queue->queue_length = nr_of_pages * pagesize; - queue->pagesize = pagesize; - queue->qe_size = qe_size; - queue->act_nr_of_sg = nr_of_sg; - queue->current_q_offset = 0; - queue->toggle_state = 1; - queue->small_page = NULL; - - /* allocate queue page pointers */ - queue->queue_pages = kzalloc(nr_of_pages * sizeof(void *), - GFP_KERNEL | __GFP_NOWARN); - if (!queue->queue_pages) { - queue->queue_pages = vzalloc(nr_of_pages * sizeof(void *)); - if (!queue->queue_pages) { - ehca_gen_err("Couldn't allocate queue page list"); - return 0; - } - } - - /* allocate actual queue pages */ - if (is_small) { - if (!alloc_small_queue_page(queue, pd)) - goto ipz_queue_ctor_exit0; - } else - if (!alloc_queue_pages(queue, nr_of_pages)) - goto ipz_queue_ctor_exit0; - - return 1; - -ipz_queue_ctor_exit0: - ehca_gen_err("Couldn't alloc pages queue=%p " - "nr_of_pages=%x", queue, nr_of_pages); - kvfree(queue->queue_pages); - - return 0; -} - -int ipz_queue_dtor(struct ehca_pd *pd, struct ipz_queue *queue) -{ - int i, nr_pages; - - if (!queue || !queue->queue_pages) { - ehca_gen_dbg("queue or queue_pages is NULL"); - return 0; - } - - if (queue->small_page) - free_small_queue_page(queue, pd); - else { - nr_pages = queue->queue_length / queue->pagesize; - for (i = 0; i < nr_pages; i += PAGES_PER_KPAGE) - free_page((unsigned long)queue->queue_pages[i]); - } - - kvfree(queue->queue_pages); - - return 1; -} - -int ehca_init_small_qp_cache(void) -{ - small_qp_cache = kmem_cache_create("ehca_cache_small_qp", - sizeof(struct ipz_small_queue_page), - 0, SLAB_HWCACHE_ALIGN, NULL); - if (!small_qp_cache) - return -ENOMEM; - - return 0; -} - -void ehca_cleanup_small_qp_cache(void) -{ - kmem_cache_destroy(small_qp_cache); -} diff --git a/drivers/staging/rdma/ehca/ipz_pt_fn.h b/drivers/staging/rdma/ehca/ipz_pt_fn.h deleted file mode 100644 index a801274ea337..000000000000 --- a/drivers/staging/rdma/ehca/ipz_pt_fn.h +++ /dev/null @@ -1,289 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * internal queue handling - * - * Authors: Waleri Fomin - * Reinhard Ernst - * Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __IPZ_PT_FN_H__ -#define __IPZ_PT_FN_H__ - -#define EHCA_PAGESHIFT 12 -#define EHCA_PAGESIZE 4096UL -#define EHCA_PAGEMASK (~(EHCA_PAGESIZE-1)) -#define EHCA_PT_ENTRIES 512UL - -#include "ehca_tools.h" -#include "ehca_qes.h" - -struct ehca_pd; -struct ipz_small_queue_page; - -extern struct kmem_cache *small_qp_cache; - -/* struct generic ehca page */ -struct ipz_page { - u8 entries[EHCA_PAGESIZE]; -}; - -#define IPZ_SPAGE_PER_KPAGE (PAGE_SIZE / 512) - -struct ipz_small_queue_page { - unsigned long page; - unsigned long bitmap[IPZ_SPAGE_PER_KPAGE / BITS_PER_LONG]; - int fill; - void *mapped_addr; - u32 mmap_count; - struct list_head list; -}; - -/* struct generic queue in linux kernel virtual memory (kv) */ -struct ipz_queue { - u64 current_q_offset; /* current queue entry */ - - struct ipz_page **queue_pages; /* array of pages belonging to queue */ - u32 qe_size; /* queue entry size */ - u32 act_nr_of_sg; - u32 queue_length; /* queue length allocated in bytes */ - u32 pagesize; - u32 toggle_state; /* toggle flag - per page */ - u32 offset; /* save offset within page for small_qp */ - struct ipz_small_queue_page *small_page; -}; - -/* - * return current Queue Entry for a certain q_offset - * returns address (kv) of Queue Entry - */ -static inline void *ipz_qeit_calc(struct ipz_queue *queue, u64 q_offset) -{ - struct ipz_page *current_page; - if (q_offset >= queue->queue_length) - return NULL; - current_page = (queue->queue_pages)[q_offset >> EHCA_PAGESHIFT]; - return ¤t_page->entries[q_offset & (EHCA_PAGESIZE - 1)]; -} - -/* - * return current Queue Entry - * returns address (kv) of Queue Entry - */ -static inline void *ipz_qeit_get(struct ipz_queue *queue) -{ - return ipz_qeit_calc(queue, queue->current_q_offset); -} - -/* - * return current Queue Page , increment Queue Page iterator from - * page to page in struct ipz_queue, last increment will return 0! and - * NOT wrap - * returns address (kv) of Queue Page - * warning don't use in parallel with ipz_QE_get_inc() - */ -void *ipz_qpageit_get_inc(struct ipz_queue *queue); - -/* - * return current Queue Entry, increment Queue Entry iterator by one - * step in struct ipz_queue, will wrap in ringbuffer - * returns address (kv) of Queue Entry BEFORE increment - * warning don't use in parallel with ipz_qpageit_get_inc() - */ -static inline void *ipz_qeit_get_inc(struct ipz_queue *queue) -{ - void *ret = ipz_qeit_get(queue); - queue->current_q_offset += queue->qe_size; - if (queue->current_q_offset >= queue->queue_length) { - queue->current_q_offset = 0; - /* toggle the valid flag */ - queue->toggle_state = (~queue->toggle_state) & 1; - } - - return ret; -} - -/* - * return a bool indicating whether current Queue Entry is valid - */ -static inline int ipz_qeit_is_valid(struct ipz_queue *queue) -{ - struct ehca_cqe *cqe = ipz_qeit_get(queue); - return ((cqe->cqe_flags >> 7) == (queue->toggle_state & 1)); -} - -/* - * return current Queue Entry, increment Queue Entry iterator by one - * step in struct ipz_queue, will wrap in ringbuffer - * returns address (kv) of Queue Entry BEFORE increment - * returns 0 and does not increment, if wrong valid state - * warning don't use in parallel with ipz_qpageit_get_inc() - */ -static inline void *ipz_qeit_get_inc_valid(struct ipz_queue *queue) -{ - return ipz_qeit_is_valid(queue) ? ipz_qeit_get_inc(queue) : NULL; -} - -/* - * returns and resets Queue Entry iterator - * returns address (kv) of first Queue Entry - */ -static inline void *ipz_qeit_reset(struct ipz_queue *queue) -{ - queue->current_q_offset = 0; - return ipz_qeit_get(queue); -} - -/* - * return the q_offset corresponding to an absolute address - */ -int ipz_queue_abs_to_offset(struct ipz_queue *queue, u64 addr, u64 *q_offset); - -/* - * return the next queue offset. don't modify the queue. - */ -static inline u64 ipz_queue_advance_offset(struct ipz_queue *queue, u64 offset) -{ - offset += queue->qe_size; - if (offset >= queue->queue_length) offset = 0; - return offset; -} - -/* struct generic page table */ -struct ipz_pt { - u64 entries[EHCA_PT_ENTRIES]; -}; - -/* struct page table for a queue, only to be used in pf */ -struct ipz_qpt { - /* queue page tables (kv), use u64 because we know the element length */ - u64 *qpts; - u32 n_qpts; - u32 n_ptes; /* number of page table entries */ - u64 *current_pte_addr; -}; - -/* - * constructor for a ipz_queue_t, placement new for ipz_queue_t, - * new for all dependent datastructors - * all QP Tables are the same - * flow: - * allocate+pin queue - * see ipz_qpt_ctor() - * returns true if ok, false if out of memory - */ -int ipz_queue_ctor(struct ehca_pd *pd, struct ipz_queue *queue, - const u32 nr_of_pages, const u32 pagesize, - const u32 qe_size, const u32 nr_of_sg, - int is_small); - -/* - * destructor for a ipz_queue_t - * -# free queue - * see ipz_queue_ctor() - * returns true if ok, false if queue was NULL-ptr of free failed - */ -int ipz_queue_dtor(struct ehca_pd *pd, struct ipz_queue *queue); - -/* - * constructor for a ipz_qpt_t, - * placement new for struct ipz_queue, new for all dependent datastructors - * all QP Tables are the same, - * flow: - * -# allocate+pin queue - * -# initialise ptcb - * -# allocate+pin PTs - * -# link PTs to a ring, according to HCA Arch, set bit62 id needed - * -# the ring must have room for exactly nr_of_PTEs - * see ipz_qpt_ctor() - */ -void ipz_qpt_ctor(struct ipz_qpt *qpt, - const u32 nr_of_qes, - const u32 pagesize, - const u32 qe_size, - const u8 lowbyte, const u8 toggle, - u32 * act_nr_of_QEs, u32 * act_nr_of_pages); - -/* - * return current Queue Entry, increment Queue Entry iterator by one - * step in struct ipz_queue, will wrap in ringbuffer - * returns address (kv) of Queue Entry BEFORE increment - * warning don't use in parallel with ipz_qpageit_get_inc() - * warning unpredictable results may occur if steps>act_nr_of_queue_entries - * fix EQ page problems - */ -void *ipz_qeit_eq_get_inc(struct ipz_queue *queue); - -/* - * return current Event Queue Entry, increment Queue Entry iterator - * by one step in struct ipz_queue if valid, will wrap in ringbuffer - * returns address (kv) of Queue Entry BEFORE increment - * returns 0 and does not increment, if wrong valid state - * warning don't use in parallel with ipz_queue_QPageit_get_inc() - * warning unpredictable results may occur if steps>act_nr_of_queue_entries - */ -static inline void *ipz_eqit_eq_get_inc_valid(struct ipz_queue *queue) -{ - void *ret = ipz_qeit_get(queue); - u32 qe = *(u8 *)ret; - if ((qe >> 7) != (queue->toggle_state & 1)) - return NULL; - ipz_qeit_eq_get_inc(queue); /* this is a good one */ - return ret; -} - -static inline void *ipz_eqit_eq_peek_valid(struct ipz_queue *queue) -{ - void *ret = ipz_qeit_get(queue); - u32 qe = *(u8 *)ret; - if ((qe >> 7) != (queue->toggle_state & 1)) - return NULL; - return ret; -} - -/* returns address (GX) of first queue entry */ -static inline u64 ipz_qpt_get_firstpage(struct ipz_qpt *qpt) -{ - return be64_to_cpu(qpt->qpts[0]); -} - -/* returns address (kv) of first page of queue page table */ -static inline void *ipz_qpt_get_qpt(struct ipz_qpt *qpt) -{ - return qpt->qpts; -} - -#endif /* __IPZ_PT_FN_H__ */ -- cgit v1.2.3 From b85d9905a7ca128f24e3a4e60ff2a1b0cd58ae7c Mon Sep 17 00:00:00 2001 From: Doug Ledford Date: Wed, 3 Feb 2016 11:10:58 -0500 Subject: staging/rdma: remove deprecated ipath driver This driver was moved to staging for eventual deletion. Time to complete that task. Signed-off-by: Doug Ledford --- MAINTAINERS | 6 - drivers/staging/rdma/Kconfig | 2 - drivers/staging/rdma/Makefile | 1 - drivers/staging/rdma/ipath/Kconfig | 16 - drivers/staging/rdma/ipath/Makefile | 37 - drivers/staging/rdma/ipath/TODO | 5 - drivers/staging/rdma/ipath/ipath_common.h | 851 -------- drivers/staging/rdma/ipath/ipath_cq.c | 483 ---- drivers/staging/rdma/ipath/ipath_debug.h | 99 - drivers/staging/rdma/ipath/ipath_diag.c | 551 ----- drivers/staging/rdma/ipath/ipath_dma.c | 179 -- drivers/staging/rdma/ipath/ipath_driver.c | 2784 ------------------------ drivers/staging/rdma/ipath/ipath_eeprom.c | 1183 ---------- drivers/staging/rdma/ipath/ipath_file_ops.c | 2619 ---------------------- drivers/staging/rdma/ipath/ipath_fs.c | 415 ---- drivers/staging/rdma/ipath/ipath_iba6110.c | 1939 ----------------- drivers/staging/rdma/ipath/ipath_init_chip.c | 1062 --------- drivers/staging/rdma/ipath/ipath_intr.c | 1271 ----------- drivers/staging/rdma/ipath/ipath_kernel.h | 1374 ------------ drivers/staging/rdma/ipath/ipath_keys.c | 270 --- drivers/staging/rdma/ipath/ipath_mad.c | 1521 ------------- drivers/staging/rdma/ipath/ipath_mmap.c | 174 -- drivers/staging/rdma/ipath/ipath_mr.c | 370 ---- drivers/staging/rdma/ipath/ipath_qp.c | 1079 --------- drivers/staging/rdma/ipath/ipath_rc.c | 1969 ----------------- drivers/staging/rdma/ipath/ipath_registers.h | 512 ----- drivers/staging/rdma/ipath/ipath_ruc.c | 733 ------- drivers/staging/rdma/ipath/ipath_sdma.c | 818 ------- drivers/staging/rdma/ipath/ipath_srq.c | 380 ---- drivers/staging/rdma/ipath/ipath_stats.c | 347 --- drivers/staging/rdma/ipath/ipath_sysfs.c | 1237 ----------- drivers/staging/rdma/ipath/ipath_uc.c | 547 ----- drivers/staging/rdma/ipath/ipath_ud.c | 579 ----- drivers/staging/rdma/ipath/ipath_user_pages.c | 228 -- drivers/staging/rdma/ipath/ipath_user_sdma.c | 874 -------- drivers/staging/rdma/ipath/ipath_user_sdma.h | 52 - drivers/staging/rdma/ipath/ipath_verbs.c | 2376 -------------------- drivers/staging/rdma/ipath/ipath_verbs.h | 941 -------- drivers/staging/rdma/ipath/ipath_verbs_mcast.c | 363 --- drivers/staging/rdma/ipath/ipath_wc_ppc64.c | 49 - drivers/staging/rdma/ipath/ipath_wc_x86_64.c | 144 -- 41 files changed, 30440 deletions(-) delete mode 100644 drivers/staging/rdma/ipath/Kconfig delete mode 100644 drivers/staging/rdma/ipath/Makefile delete mode 100644 drivers/staging/rdma/ipath/TODO delete mode 100644 drivers/staging/rdma/ipath/ipath_common.h delete mode 100644 drivers/staging/rdma/ipath/ipath_cq.c delete mode 100644 drivers/staging/rdma/ipath/ipath_debug.h delete mode 100644 drivers/staging/rdma/ipath/ipath_diag.c delete mode 100644 drivers/staging/rdma/ipath/ipath_dma.c delete mode 100644 drivers/staging/rdma/ipath/ipath_driver.c delete mode 100644 drivers/staging/rdma/ipath/ipath_eeprom.c delete mode 100644 drivers/staging/rdma/ipath/ipath_file_ops.c delete mode 100644 drivers/staging/rdma/ipath/ipath_fs.c delete mode 100644 drivers/staging/rdma/ipath/ipath_iba6110.c delete mode 100644 drivers/staging/rdma/ipath/ipath_init_chip.c delete mode 100644 drivers/staging/rdma/ipath/ipath_intr.c delete mode 100644 drivers/staging/rdma/ipath/ipath_kernel.h delete mode 100644 drivers/staging/rdma/ipath/ipath_keys.c delete mode 100644 drivers/staging/rdma/ipath/ipath_mad.c delete mode 100644 drivers/staging/rdma/ipath/ipath_mmap.c delete mode 100644 drivers/staging/rdma/ipath/ipath_mr.c delete mode 100644 drivers/staging/rdma/ipath/ipath_qp.c delete mode 100644 drivers/staging/rdma/ipath/ipath_rc.c delete mode 100644 drivers/staging/rdma/ipath/ipath_registers.h delete mode 100644 drivers/staging/rdma/ipath/ipath_ruc.c delete mode 100644 drivers/staging/rdma/ipath/ipath_sdma.c delete mode 100644 drivers/staging/rdma/ipath/ipath_srq.c delete mode 100644 drivers/staging/rdma/ipath/ipath_stats.c delete mode 100644 drivers/staging/rdma/ipath/ipath_sysfs.c delete mode 100644 drivers/staging/rdma/ipath/ipath_uc.c delete mode 100644 drivers/staging/rdma/ipath/ipath_ud.c delete mode 100644 drivers/staging/rdma/ipath/ipath_user_pages.c delete mode 100644 drivers/staging/rdma/ipath/ipath_user_sdma.c delete mode 100644 drivers/staging/rdma/ipath/ipath_user_sdma.h delete mode 100644 drivers/staging/rdma/ipath/ipath_verbs.c delete mode 100644 drivers/staging/rdma/ipath/ipath_verbs.h delete mode 100644 drivers/staging/rdma/ipath/ipath_verbs_mcast.c delete mode 100644 drivers/staging/rdma/ipath/ipath_wc_ppc64.c delete mode 100644 drivers/staging/rdma/ipath/ipath_wc_x86_64.c (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index d1aeb1d5add5..5c889cd754c3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5795,12 +5795,6 @@ M: Juanjo Ciarlante S: Maintained F: net/ipv4/netfilter/ipt_MASQUERADE.c -IPATH DRIVER -M: Mike Marciniszyn -L: linux-rdma@vger.kernel.org -S: Maintained -F: drivers/staging/rdma/ipath/ - IPMI SUBSYSTEM M: Corey Minyard L: openipmi-developer@lists.sourceforge.net (moderated for non-subscribers) diff --git a/drivers/staging/rdma/Kconfig b/drivers/staging/rdma/Kconfig index 8a0be6961d7a..f1f3ecadf0fb 100644 --- a/drivers/staging/rdma/Kconfig +++ b/drivers/staging/rdma/Kconfig @@ -24,6 +24,4 @@ if STAGING_RDMA source "drivers/staging/rdma/hfi1/Kconfig" -source "drivers/staging/rdma/ipath/Kconfig" - endif diff --git a/drivers/staging/rdma/Makefile b/drivers/staging/rdma/Makefile index 08e1919c819e..8c7fc1de48a7 100644 --- a/drivers/staging/rdma/Makefile +++ b/drivers/staging/rdma/Makefile @@ -1,3 +1,2 @@ # Entries for RDMA_STAGING tree obj-$(CONFIG_INFINIBAND_HFI1) += hfi1/ -obj-$(CONFIG_INFINIBAND_IPATH) += ipath/ diff --git a/drivers/staging/rdma/ipath/Kconfig b/drivers/staging/rdma/ipath/Kconfig deleted file mode 100644 index 041ce0634968..000000000000 --- a/drivers/staging/rdma/ipath/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -config INFINIBAND_IPATH - tristate "QLogic HTX HCA support" - depends on 64BIT && NET && HT_IRQ - ---help--- - This is a driver for the deprecated QLogic Hyper-Transport - IB host channel adapter (model QHT7140), - including InfiniBand verbs support. This driver allows these - devices to be used with both kernel upper level protocols such - as IP-over-InfiniBand as well as with userspace applications - (in conjunction with InfiniBand userspace access). - For QLogic PCIe QLE based cards, use the QIB driver instead. - - If you have this hardware you will need to boot with PAT disabled - on your x86-64 systems, use the nopat kernel parameter. - - Note that this driver will soon be removed entirely from the kernel. diff --git a/drivers/staging/rdma/ipath/Makefile b/drivers/staging/rdma/ipath/Makefile deleted file mode 100644 index 4496f2820c92..000000000000 --- a/drivers/staging/rdma/ipath/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -ccflags-y := -DIPATH_IDSTR='"QLogic kernel.org driver"' \ - -DIPATH_KERN_TYPE=0 - -obj-$(CONFIG_INFINIBAND_IPATH) += ib_ipath.o - -ib_ipath-y := \ - ipath_cq.o \ - ipath_diag.o \ - ipath_dma.o \ - ipath_driver.o \ - ipath_eeprom.o \ - ipath_file_ops.o \ - ipath_fs.o \ - ipath_init_chip.o \ - ipath_intr.o \ - ipath_keys.o \ - ipath_mad.o \ - ipath_mmap.o \ - ipath_mr.o \ - ipath_qp.o \ - ipath_rc.o \ - ipath_ruc.o \ - ipath_sdma.o \ - ipath_srq.o \ - ipath_stats.o \ - ipath_sysfs.o \ - ipath_uc.o \ - ipath_ud.o \ - ipath_user_pages.o \ - ipath_user_sdma.o \ - ipath_verbs_mcast.o \ - ipath_verbs.o - -ib_ipath-$(CONFIG_HT_IRQ) += ipath_iba6110.o - -ib_ipath-$(CONFIG_X86_64) += ipath_wc_x86_64.o -ib_ipath-$(CONFIG_PPC64) += ipath_wc_ppc64.o diff --git a/drivers/staging/rdma/ipath/TODO b/drivers/staging/rdma/ipath/TODO deleted file mode 100644 index cb00158d64c8..000000000000 --- a/drivers/staging/rdma/ipath/TODO +++ /dev/null @@ -1,5 +0,0 @@ -The ipath driver has been moved to staging in preparation for its removal in a -few releases. The driver will be deleted during the 4.6 merge window. - -Contact Dennis Dalessandro and -Cc: linux-rdma@vger.kernel.org diff --git a/drivers/staging/rdma/ipath/ipath_common.h b/drivers/staging/rdma/ipath/ipath_common.h deleted file mode 100644 index 28cfe97cf1e9..000000000000 --- a/drivers/staging/rdma/ipath/ipath_common.h +++ /dev/null @@ -1,851 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _IPATH_COMMON_H -#define _IPATH_COMMON_H - -/* - * This file contains defines, structures, etc. that are used - * to communicate between kernel and user code. - */ - - -/* This is the IEEE-assigned OUI for QLogic Inc. InfiniPath */ -#define IPATH_SRC_OUI_1 0x00 -#define IPATH_SRC_OUI_2 0x11 -#define IPATH_SRC_OUI_3 0x75 - -/* version of protocol header (known to chip also). In the long run, - * we should be able to generate and accept a range of version numbers; - * for now we only accept one, and it's compiled in. - */ -#define IPS_PROTO_VERSION 2 - -/* - * These are compile time constants that you may want to enable or disable - * if you are trying to debug problems with code or performance. - * IPATH_VERBOSE_TRACING define as 1 if you want additional tracing in - * fastpath code - * IPATH_TRACE_REGWRITES define as 1 if you want register writes to be - * traced in faspath code - * _IPATH_TRACING define as 0 if you want to remove all tracing in a - * compilation unit - * _IPATH_DEBUGGING define as 0 if you want to remove debug prints - */ - -/* - * The value in the BTH QP field that InfiniPath uses to differentiate - * an infinipath protocol IB packet vs standard IB transport - */ -#define IPATH_KD_QP 0x656b79 - -/* - * valid states passed to ipath_set_linkstate() user call - */ -#define IPATH_IB_LINKDOWN 0 -#define IPATH_IB_LINKARM 1 -#define IPATH_IB_LINKACTIVE 2 -#define IPATH_IB_LINKDOWN_ONLY 3 -#define IPATH_IB_LINKDOWN_SLEEP 4 -#define IPATH_IB_LINKDOWN_DISABLE 5 -#define IPATH_IB_LINK_LOOPBACK 6 /* enable local loopback */ -#define IPATH_IB_LINK_EXTERNAL 7 /* normal, disable local loopback */ -#define IPATH_IB_LINK_NO_HRTBT 8 /* disable Heartbeat, e.g. for loopback */ -#define IPATH_IB_LINK_HRTBT 9 /* enable heartbeat, normal, non-loopback */ - -/* - * These 3 values (SDR and DDR may be ORed for auto-speed - * negotiation) are used for the 3rd argument to path_f_set_ib_cfg - * with cmd IPATH_IB_CFG_SPD_ENB, by direct calls or via sysfs. They - * are also the the possible values for ipath_link_speed_enabled and active - * The values were chosen to match values used within the IB spec. - */ -#define IPATH_IB_SDR 1 -#define IPATH_IB_DDR 2 - -/* - * stats maintained by the driver. For now, at least, this is global - * to all minor devices. - */ -struct infinipath_stats { - /* number of interrupts taken */ - __u64 sps_ints; - /* number of interrupts for errors */ - __u64 sps_errints; - /* number of errors from chip (not incl. packet errors or CRC) */ - __u64 sps_errs; - /* number of packet errors from chip other than CRC */ - __u64 sps_pkterrs; - /* number of packets with CRC errors (ICRC and VCRC) */ - __u64 sps_crcerrs; - /* number of hardware errors reported (parity, etc.) */ - __u64 sps_hwerrs; - /* number of times IB link changed state unexpectedly */ - __u64 sps_iblink; - __u64 sps_unused; /* was fastrcvint, no longer implemented */ - /* number of kernel (port0) packets received */ - __u64 sps_port0pkts; - /* number of "ethernet" packets sent by driver */ - __u64 sps_ether_spkts; - /* number of "ethernet" packets received by driver */ - __u64 sps_ether_rpkts; - /* number of SMA packets sent by driver. Obsolete. */ - __u64 sps_sma_spkts; - /* number of SMA packets received by driver. Obsolete. */ - __u64 sps_sma_rpkts; - /* number of times all ports rcvhdrq was full and packet dropped */ - __u64 sps_hdrqfull; - /* number of times all ports egrtid was full and packet dropped */ - __u64 sps_etidfull; - /* - * number of times we tried to send from driver, but no pio buffers - * avail - */ - __u64 sps_nopiobufs; - /* number of ports currently open */ - __u64 sps_ports; - /* list of pkeys (other than default) accepted (0 means not set) */ - __u16 sps_pkeys[4]; - __u16 sps_unused16[4]; /* available; maintaining compatible layout */ - /* number of user ports per chip (not IB ports) */ - __u32 sps_nports; - /* not our interrupt, or already handled */ - __u32 sps_nullintr; - /* max number of packets handled per receive call */ - __u32 sps_maxpkts_call; - /* avg number of packets handled per receive call */ - __u32 sps_avgpkts_call; - /* total number of pages locked */ - __u64 sps_pagelocks; - /* total number of pages unlocked */ - __u64 sps_pageunlocks; - /* - * Number of packets dropped in kernel other than errors (ether - * packets if ipath not configured, etc.) - */ - __u64 sps_krdrops; - __u64 sps_txeparity; /* PIO buffer parity error, recovered */ - /* pad for future growth */ - __u64 __sps_pad[45]; -}; - -/* - * These are the status bits readable (in ascii form, 64bit value) - * from the "status" sysfs file. - */ -#define IPATH_STATUS_INITTED 0x1 /* basic initialization done */ -#define IPATH_STATUS_DISABLED 0x2 /* hardware disabled */ -/* Device has been disabled via admin request */ -#define IPATH_STATUS_ADMIN_DISABLED 0x4 -/* Chip has been found and initted */ -#define IPATH_STATUS_CHIP_PRESENT 0x20 -/* IB link is at ACTIVE, usable for data traffic */ -#define IPATH_STATUS_IB_READY 0x40 -/* link is configured, LID, MTU, etc. have been set */ -#define IPATH_STATUS_IB_CONF 0x80 -/* no link established, probably no cable */ -#define IPATH_STATUS_IB_NOCABLE 0x100 -/* A Fatal hardware error has occurred. */ -#define IPATH_STATUS_HWERROR 0x200 - -/* - * The list of usermode accessible registers. Also see Reg_* later in file. - */ -typedef enum _ipath_ureg { - /* (RO) DMA RcvHdr to be used next. */ - ur_rcvhdrtail = 0, - /* (RW) RcvHdr entry to be processed next by host. */ - ur_rcvhdrhead = 1, - /* (RO) Index of next Eager index to use. */ - ur_rcvegrindextail = 2, - /* (RW) Eager TID to be processed next */ - ur_rcvegrindexhead = 3, - /* For internal use only; max register number. */ - _IPATH_UregMax -} ipath_ureg; - -/* bit values for spi_runtime_flags */ -#define IPATH_RUNTIME_HT 0x1 -#define IPATH_RUNTIME_PCIE 0x2 -#define IPATH_RUNTIME_FORCE_WC_ORDER 0x4 -#define IPATH_RUNTIME_RCVHDR_COPY 0x8 -#define IPATH_RUNTIME_MASTER 0x10 -#define IPATH_RUNTIME_NODMA_RTAIL 0x80 -#define IPATH_RUNTIME_SDMA 0x200 -#define IPATH_RUNTIME_FORCE_PIOAVAIL 0x400 -#define IPATH_RUNTIME_PIO_REGSWAPPED 0x800 - -/* - * This structure is returned by ipath_userinit() immediately after - * open to get implementation-specific info, and info specific to this - * instance. - * - * This struct must have explict pad fields where type sizes - * may result in different alignments between 32 and 64 bit - * programs, since the 64 bit * bit kernel requires the user code - * to have matching offsets - */ -struct ipath_base_info { - /* version of hardware, for feature checking. */ - __u32 spi_hw_version; - /* version of software, for feature checking. */ - __u32 spi_sw_version; - /* InfiniPath port assigned, goes into sent packets */ - __u16 spi_port; - __u16 spi_subport; - /* - * IB MTU, packets IB data must be less than this. - * The MTU is in bytes, and will be a multiple of 4 bytes. - */ - __u32 spi_mtu; - /* - * Size of a PIO buffer. Any given packet's total size must be less - * than this (in words). Included is the starting control word, so - * if 513 is returned, then total pkt size is 512 words or less. - */ - __u32 spi_piosize; - /* size of the TID cache in infinipath, in entries */ - __u32 spi_tidcnt; - /* size of the TID Eager list in infinipath, in entries */ - __u32 spi_tidegrcnt; - /* size of a single receive header queue entry in words. */ - __u32 spi_rcvhdrent_size; - /* - * Count of receive header queue entries allocated. - * This may be less than the spu_rcvhdrcnt passed in!. - */ - __u32 spi_rcvhdr_cnt; - - /* per-chip and other runtime features bitmap (IPATH_RUNTIME_*) */ - __u32 spi_runtime_flags; - - /* address where receive buffer queue is mapped into */ - __u64 spi_rcvhdr_base; - - /* user program. */ - - /* base address of eager TID receive buffers. */ - __u64 spi_rcv_egrbufs; - - /* Allocated by initialization code, not by protocol. */ - - /* - * Size of each TID buffer in host memory, starting at - * spi_rcv_egrbufs. The buffers are virtually contiguous. - */ - __u32 spi_rcv_egrbufsize; - /* - * The special QP (queue pair) value that identifies an infinipath - * protocol packet from standard IB packets. More, probably much - * more, to be added. - */ - __u32 spi_qpair; - - /* - * User register base for init code, not to be used directly by - * protocol or applications. - */ - __u64 __spi_uregbase; - /* - * Maximum buffer size in bytes that can be used in a single TID - * entry (assuming the buffer is aligned to this boundary). This is - * the minimum of what the hardware and software support Guaranteed - * to be a power of 2. - */ - __u32 spi_tid_maxsize; - /* - * alignment of each pio send buffer (byte count - * to add to spi_piobufbase to get to second buffer) - */ - __u32 spi_pioalign; - /* - * The index of the first pio buffer available to this process; - * needed to do lookup in spi_pioavailaddr; not added to - * spi_piobufbase. - */ - __u32 spi_pioindex; - /* number of buffers mapped for this process */ - __u32 spi_piocnt; - - /* - * Base address of writeonly pio buffers for this process. - * Each buffer has spi_piosize words, and is aligned on spi_pioalign - * boundaries. spi_piocnt buffers are mapped from this address - */ - __u64 spi_piobufbase; - - /* - * Base address of readonly memory copy of the pioavail registers. - * There are 2 bits for each buffer. - */ - __u64 spi_pioavailaddr; - - /* - * Address where driver updates a copy of the interface and driver - * status (IPATH_STATUS_*) as a 64 bit value. It's followed by a - * string indicating hardware error, if there was one. - */ - __u64 spi_status; - - /* number of chip ports available to user processes */ - __u32 spi_nports; - /* unit number of chip we are using */ - __u32 spi_unit; - /* num bufs in each contiguous set */ - __u32 spi_rcv_egrperchunk; - /* size in bytes of each contiguous set */ - __u32 spi_rcv_egrchunksize; - /* total size of mmap to cover full rcvegrbuffers */ - __u32 spi_rcv_egrbuftotlen; - __u32 spi_filler_for_align; - /* address of readonly memory copy of the rcvhdrq tail register. */ - __u64 spi_rcvhdr_tailaddr; - - /* shared memory pages for subports if port is shared */ - __u64 spi_subport_uregbase; - __u64 spi_subport_rcvegrbuf; - __u64 spi_subport_rcvhdr_base; - - /* shared memory page for hardware port if it is shared */ - __u64 spi_port_uregbase; - __u64 spi_port_rcvegrbuf; - __u64 spi_port_rcvhdr_base; - __u64 spi_port_rcvhdr_tailaddr; - -} __attribute__ ((aligned(8))); - - -/* - * This version number is given to the driver by the user code during - * initialization in the spu_userversion field of ipath_user_info, so - * the driver can check for compatibility with user code. - * - * The major version changes when data structures - * change in an incompatible way. The driver must be the same or higher - * for initialization to succeed. In some cases, a higher version - * driver will not interoperate with older software, and initialization - * will return an error. - */ -#define IPATH_USER_SWMAJOR 1 - -/* - * Minor version differences are always compatible - * a within a major version, however if user software is larger - * than driver software, some new features and/or structure fields - * may not be implemented; the user code must deal with this if it - * cares, or it must abort after initialization reports the difference. - */ -#define IPATH_USER_SWMINOR 6 - -#define IPATH_USER_SWVERSION ((IPATH_USER_SWMAJOR<<16) | IPATH_USER_SWMINOR) - -#define IPATH_KERN_TYPE 0 - -/* - * Similarly, this is the kernel version going back to the user. It's - * slightly different, in that we want to tell if the driver was built as - * part of a QLogic release, or from the driver from openfabrics.org, - * kernel.org, or a standard distribution, for support reasons. - * The high bit is 0 for non-QLogic and 1 for QLogic-built/supplied. - * - * It's returned by the driver to the user code during initialization in the - * spi_sw_version field of ipath_base_info, so the user code can in turn - * check for compatibility with the kernel. -*/ -#define IPATH_KERN_SWVERSION ((IPATH_KERN_TYPE<<31) | IPATH_USER_SWVERSION) - -/* - * This structure is passed to ipath_userinit() to tell the driver where - * user code buffers are, sizes, etc. The offsets and sizes of the - * fields must remain unchanged, for binary compatibility. It can - * be extended, if userversion is changed so user code can tell, if needed - */ -struct ipath_user_info { - /* - * version of user software, to detect compatibility issues. - * Should be set to IPATH_USER_SWVERSION. - */ - __u32 spu_userversion; - - /* desired number of receive header queue entries */ - __u32 spu_rcvhdrcnt; - - /* size of struct base_info to write to */ - __u32 spu_base_info_size; - - /* - * number of words in KD protocol header - * This tells InfiniPath how many words to copy to rcvhdrq. If 0, - * kernel uses a default. Once set, attempts to set any other value - * are an error (EAGAIN) until driver is reloaded. - */ - __u32 spu_rcvhdrsize; - - /* - * If two or more processes wish to share a port, each process - * must set the spu_subport_cnt and spu_subport_id to the same - * values. The only restriction on the spu_subport_id is that - * it be unique for a given node. - */ - __u16 spu_subport_cnt; - __u16 spu_subport_id; - - __u32 spu_unused; /* kept for compatible layout */ - - /* - * address of struct base_info to write to - */ - __u64 spu_base_info; - -} __attribute__ ((aligned(8))); - -/* User commands. */ - -#define IPATH_CMD_MIN 16 - -#define __IPATH_CMD_USER_INIT 16 /* old set up userspace (for old user code) */ -#define IPATH_CMD_PORT_INFO 17 /* find out what resources we got */ -#define IPATH_CMD_RECV_CTRL 18 /* control receipt of packets */ -#define IPATH_CMD_TID_UPDATE 19 /* update expected TID entries */ -#define IPATH_CMD_TID_FREE 20 /* free expected TID entries */ -#define IPATH_CMD_SET_PART_KEY 21 /* add partition key */ -#define __IPATH_CMD_SLAVE_INFO 22 /* return info on slave processes (for old user code) */ -#define IPATH_CMD_ASSIGN_PORT 23 /* allocate HCA and port */ -#define IPATH_CMD_USER_INIT 24 /* set up userspace */ -#define IPATH_CMD_UNUSED_1 25 -#define IPATH_CMD_UNUSED_2 26 -#define IPATH_CMD_PIOAVAILUPD 27 /* force an update of PIOAvail reg */ -#define IPATH_CMD_POLL_TYPE 28 /* set the kind of polling we want */ -#define IPATH_CMD_ARMLAUNCH_CTRL 29 /* armlaunch detection control */ -/* 30 is unused */ -#define IPATH_CMD_SDMA_INFLIGHT 31 /* sdma inflight counter request */ -#define IPATH_CMD_SDMA_COMPLETE 32 /* sdma completion counter request */ - -/* - * Poll types - */ -#define IPATH_POLL_TYPE_URGENT 0x01 -#define IPATH_POLL_TYPE_OVERFLOW 0x02 - -struct ipath_port_info { - __u32 num_active; /* number of active units */ - __u32 unit; /* unit (chip) assigned to caller */ - __u16 port; /* port on unit assigned to caller */ - __u16 subport; /* subport on unit assigned to caller */ - __u16 num_ports; /* number of ports available on unit */ - __u16 num_subports; /* number of subports opened on port */ -}; - -struct ipath_tid_info { - __u32 tidcnt; - /* make structure same size in 32 and 64 bit */ - __u32 tid__unused; - /* virtual address of first page in transfer */ - __u64 tidvaddr; - /* pointer (same size 32/64 bit) to __u16 tid array */ - __u64 tidlist; - - /* - * pointer (same size 32/64 bit) to bitmap of TIDs used - * for this call; checked for being large enough at open - */ - __u64 tidmap; -}; - -struct ipath_cmd { - __u32 type; /* command type */ - union { - struct ipath_tid_info tid_info; - struct ipath_user_info user_info; - - /* - * address in userspace where we should put the sdma - * inflight counter - */ - __u64 sdma_inflight; - /* - * address in userspace where we should put the sdma - * completion counter - */ - __u64 sdma_complete; - /* address in userspace of struct ipath_port_info to - write result to */ - __u64 port_info; - /* enable/disable receipt of packets */ - __u32 recv_ctrl; - /* enable/disable armlaunch errors (non-zero to enable) */ - __u32 armlaunch_ctrl; - /* partition key to set */ - __u16 part_key; - /* user address of __u32 bitmask of active slaves */ - __u64 slave_mask_addr; - /* type of polling we want */ - __u16 poll_type; - } cmd; -}; - -struct ipath_iovec { - /* Pointer to data, but same size 32 and 64 bit */ - __u64 iov_base; - - /* - * Length of data; don't need 64 bits, but want - * ipath_sendpkt to remain same size as before 32 bit changes, so... - */ - __u64 iov_len; -}; - -/* - * Describes a single packet for send. Each packet can have one or more - * buffers, but the total length (exclusive of IB headers) must be less - * than the MTU, and if using the PIO method, entire packet length, - * including IB headers, must be less than the ipath_piosize value (words). - * Use of this necessitates including sys/uio.h - */ -struct __ipath_sendpkt { - __u32 sps_flags; /* flags for packet (TBD) */ - __u32 sps_cnt; /* number of entries to use in sps_iov */ - /* array of iov's describing packet. TEMPORARY */ - struct ipath_iovec sps_iov[4]; -}; - -/* - * diagnostics can send a packet by "writing" one of the following - * two structs to diag data special file - * The first is the legacy version for backward compatibility - */ -struct ipath_diag_pkt { - __u32 unit; - __u64 data; - __u32 len; -}; - -/* The second diag_pkt struct is the expanded version that allows - * more control over the packet, specifically, by allowing a custom - * pbc (+ static rate) qword, so that special modes and deliberate - * changes to CRCs can be used. The elements were also re-ordered - * for better alignment and to avoid padding issues. - */ -struct ipath_diag_xpkt { - __u64 data; - __u64 pbc_wd; - __u32 unit; - __u32 len; -}; - -/* - * Data layout in I2C flash (for GUID, etc.) - * All fields are little-endian binary unless otherwise stated - */ -#define IPATH_FLASH_VERSION 2 -struct ipath_flash { - /* flash layout version (IPATH_FLASH_VERSION) */ - __u8 if_fversion; - /* checksum protecting if_length bytes */ - __u8 if_csum; - /* - * valid length (in use, protected by if_csum), including - * if_fversion and if_csum themselves) - */ - __u8 if_length; - /* the GUID, in network order */ - __u8 if_guid[8]; - /* number of GUIDs to use, starting from if_guid */ - __u8 if_numguid; - /* the (last 10 characters of) board serial number, in ASCII */ - char if_serial[12]; - /* board mfg date (YYYYMMDD ASCII) */ - char if_mfgdate[8]; - /* last board rework/test date (YYYYMMDD ASCII) */ - char if_testdate[8]; - /* logging of error counts, TBD */ - __u8 if_errcntp[4]; - /* powered on hours, updated at driver unload */ - __u8 if_powerhour[2]; - /* ASCII free-form comment field */ - char if_comment[32]; - /* Backwards compatible prefix for longer QLogic Serial Numbers */ - char if_sprefix[4]; - /* 82 bytes used, min flash size is 128 bytes */ - __u8 if_future[46]; -}; - -/* - * These are the counters implemented in the chip, and are listed in order. - * The InterCaps naming is taken straight from the chip spec. - */ -struct infinipath_counters { - __u64 LBIntCnt; - __u64 LBFlowStallCnt; - __u64 TxSDmaDescCnt; /* was Reserved1 */ - __u64 TxUnsupVLErrCnt; - __u64 TxDataPktCnt; - __u64 TxFlowPktCnt; - __u64 TxDwordCnt; - __u64 TxLenErrCnt; - __u64 TxMaxMinLenErrCnt; - __u64 TxUnderrunCnt; - __u64 TxFlowStallCnt; - __u64 TxDroppedPktCnt; - __u64 RxDroppedPktCnt; - __u64 RxDataPktCnt; - __u64 RxFlowPktCnt; - __u64 RxDwordCnt; - __u64 RxLenErrCnt; - __u64 RxMaxMinLenErrCnt; - __u64 RxICRCErrCnt; - __u64 RxVCRCErrCnt; - __u64 RxFlowCtrlErrCnt; - __u64 RxBadFormatCnt; - __u64 RxLinkProblemCnt; - __u64 RxEBPCnt; - __u64 RxLPCRCErrCnt; - __u64 RxBufOvflCnt; - __u64 RxTIDFullErrCnt; - __u64 RxTIDValidErrCnt; - __u64 RxPKeyMismatchCnt; - __u64 RxP0HdrEgrOvflCnt; - __u64 RxP1HdrEgrOvflCnt; - __u64 RxP2HdrEgrOvflCnt; - __u64 RxP3HdrEgrOvflCnt; - __u64 RxP4HdrEgrOvflCnt; - __u64 RxP5HdrEgrOvflCnt; - __u64 RxP6HdrEgrOvflCnt; - __u64 RxP7HdrEgrOvflCnt; - __u64 RxP8HdrEgrOvflCnt; - __u64 RxP9HdrEgrOvflCnt; /* was Reserved6 */ - __u64 RxP10HdrEgrOvflCnt; /* was Reserved7 */ - __u64 RxP11HdrEgrOvflCnt; /* new for IBA7220 */ - __u64 RxP12HdrEgrOvflCnt; /* new for IBA7220 */ - __u64 RxP13HdrEgrOvflCnt; /* new for IBA7220 */ - __u64 RxP14HdrEgrOvflCnt; /* new for IBA7220 */ - __u64 RxP15HdrEgrOvflCnt; /* new for IBA7220 */ - __u64 RxP16HdrEgrOvflCnt; /* new for IBA7220 */ - __u64 IBStatusChangeCnt; - __u64 IBLinkErrRecoveryCnt; - __u64 IBLinkDownedCnt; - __u64 IBSymbolErrCnt; - /* The following are new for IBA7220 */ - __u64 RxVL15DroppedPktCnt; - __u64 RxOtherLocalPhyErrCnt; - __u64 PcieRetryBufDiagQwordCnt; - __u64 ExcessBufferOvflCnt; - __u64 LocalLinkIntegrityErrCnt; - __u64 RxVlErrCnt; - __u64 RxDlidFltrCnt; -}; - -/* - * The next set of defines are for packet headers, and chip register - * and memory bits that are visible to and/or used by user-mode software - * The other bits that are used only by the driver or diags are in - * ipath_registers.h - */ - -/* RcvHdrFlags bits */ -#define INFINIPATH_RHF_LENGTH_MASK 0x7FF -#define INFINIPATH_RHF_LENGTH_SHIFT 0 -#define INFINIPATH_RHF_RCVTYPE_MASK 0x7 -#define INFINIPATH_RHF_RCVTYPE_SHIFT 11 -#define INFINIPATH_RHF_EGRINDEX_MASK 0xFFF -#define INFINIPATH_RHF_EGRINDEX_SHIFT 16 -#define INFINIPATH_RHF_SEQ_MASK 0xF -#define INFINIPATH_RHF_SEQ_SHIFT 0 -#define INFINIPATH_RHF_HDRQ_OFFSET_MASK 0x7FF -#define INFINIPATH_RHF_HDRQ_OFFSET_SHIFT 4 -#define INFINIPATH_RHF_H_ICRCERR 0x80000000 -#define INFINIPATH_RHF_H_VCRCERR 0x40000000 -#define INFINIPATH_RHF_H_PARITYERR 0x20000000 -#define INFINIPATH_RHF_H_LENERR 0x10000000 -#define INFINIPATH_RHF_H_MTUERR 0x08000000 -#define INFINIPATH_RHF_H_IHDRERR 0x04000000 -#define INFINIPATH_RHF_H_TIDERR 0x02000000 -#define INFINIPATH_RHF_H_MKERR 0x01000000 -#define INFINIPATH_RHF_H_IBERR 0x00800000 -#define INFINIPATH_RHF_H_ERR_MASK 0xFF800000 -#define INFINIPATH_RHF_L_USE_EGR 0x80000000 -#define INFINIPATH_RHF_L_SWA 0x00008000 -#define INFINIPATH_RHF_L_SWB 0x00004000 - -/* infinipath header fields */ -#define INFINIPATH_I_VERS_MASK 0xF -#define INFINIPATH_I_VERS_SHIFT 28 -#define INFINIPATH_I_PORT_MASK 0xF -#define INFINIPATH_I_PORT_SHIFT 24 -#define INFINIPATH_I_TID_MASK 0x7FF -#define INFINIPATH_I_TID_SHIFT 13 -#define INFINIPATH_I_OFFSET_MASK 0x1FFF -#define INFINIPATH_I_OFFSET_SHIFT 0 - -/* K_PktFlags bits */ -#define INFINIPATH_KPF_INTR 0x1 -#define INFINIPATH_KPF_SUBPORT_MASK 0x3 -#define INFINIPATH_KPF_SUBPORT_SHIFT 1 - -#define INFINIPATH_MAX_SUBPORT 4 - -/* SendPIO per-buffer control */ -#define INFINIPATH_SP_TEST 0x40 -#define INFINIPATH_SP_TESTEBP 0x20 -#define INFINIPATH_SP_TRIGGER_SHIFT 15 - -/* SendPIOAvail bits */ -#define INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT 1 -#define INFINIPATH_SENDPIOAVAIL_CHECK_SHIFT 0 - -/* infinipath header format */ -struct ipath_header { - /* - * Version - 4 bits, Port - 4 bits, TID - 10 bits and Offset - - * 14 bits before ECO change ~28 Dec 03. After that, Vers 4, - * Port 4, TID 11, offset 13. - */ - __le32 ver_port_tid_offset; - __le16 chksum; - __le16 pkt_flags; -}; - -/* infinipath user message header format. - * This structure contains the first 4 fields common to all protocols - * that employ infinipath. - */ -struct ipath_message_header { - __be16 lrh[4]; - __be32 bth[3]; - /* fields below this point are in host byte order */ - struct ipath_header iph; - __u8 sub_opcode; -}; - -/* infinipath ethernet header format */ -struct ether_header { - __be16 lrh[4]; - __be32 bth[3]; - struct ipath_header iph; - __u8 sub_opcode; - __u8 cmd; - __be16 lid; - __u16 mac[3]; - __u8 frag_num; - __u8 seq_num; - __le32 len; - /* MUST be of word size due to PIO write requirements */ - __le32 csum; - __le16 csum_offset; - __le16 flags; - __u16 first_2_bytes; - __u8 unused[2]; /* currently unused */ -}; - - -/* IB - LRH header consts */ -#define IPATH_LRH_GRH 0x0003 /* 1. word of IB LRH - next header: GRH */ -#define IPATH_LRH_BTH 0x0002 /* 1. word of IB LRH - next header: BTH */ - -/* misc. */ -#define SIZE_OF_CRC 1 - -#define IPATH_DEFAULT_P_KEY 0xFFFF -#define IPATH_PERMISSIVE_LID 0xFFFF -#define IPATH_AETH_CREDIT_SHIFT 24 -#define IPATH_AETH_CREDIT_MASK 0x1F -#define IPATH_AETH_CREDIT_INVAL 0x1F -#define IPATH_PSN_MASK 0xFFFFFF -#define IPATH_MSN_MASK 0xFFFFFF -#define IPATH_QPN_MASK 0xFFFFFF -#define IPATH_MULTICAST_LID_BASE 0xC000 -#define IPATH_EAGER_TID_ID INFINIPATH_I_TID_MASK -#define IPATH_MULTICAST_QPN 0xFFFFFF - -/* Receive Header Queue: receive type (from infinipath) */ -#define RCVHQ_RCV_TYPE_EXPECTED 0 -#define RCVHQ_RCV_TYPE_EAGER 1 -#define RCVHQ_RCV_TYPE_NON_KD 2 -#define RCVHQ_RCV_TYPE_ERROR 3 - - -/* sub OpCodes - ith4x */ -#define IPATH_ITH4X_OPCODE_ENCAP 0x81 -#define IPATH_ITH4X_OPCODE_LID_ARP 0x82 - -#define IPATH_HEADER_QUEUE_WORDS 9 - -/* functions for extracting fields from rcvhdrq entries for the driver. - */ -static inline __u32 ipath_hdrget_err_flags(const __le32 * rbuf) -{ - return __le32_to_cpu(rbuf[1]) & INFINIPATH_RHF_H_ERR_MASK; -} - -static inline __u32 ipath_hdrget_rcv_type(const __le32 * rbuf) -{ - return (__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_RCVTYPE_SHIFT) - & INFINIPATH_RHF_RCVTYPE_MASK; -} - -static inline __u32 ipath_hdrget_length_in_bytes(const __le32 * rbuf) -{ - return ((__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_LENGTH_SHIFT) - & INFINIPATH_RHF_LENGTH_MASK) << 2; -} - -static inline __u32 ipath_hdrget_index(const __le32 * rbuf) -{ - return (__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_EGRINDEX_SHIFT) - & INFINIPATH_RHF_EGRINDEX_MASK; -} - -static inline __u32 ipath_hdrget_seq(const __le32 *rbuf) -{ - return (__le32_to_cpu(rbuf[1]) >> INFINIPATH_RHF_SEQ_SHIFT) - & INFINIPATH_RHF_SEQ_MASK; -} - -static inline __u32 ipath_hdrget_offset(const __le32 *rbuf) -{ - return (__le32_to_cpu(rbuf[1]) >> INFINIPATH_RHF_HDRQ_OFFSET_SHIFT) - & INFINIPATH_RHF_HDRQ_OFFSET_MASK; -} - -static inline __u32 ipath_hdrget_use_egr_buf(const __le32 *rbuf) -{ - return __le32_to_cpu(rbuf[0]) & INFINIPATH_RHF_L_USE_EGR; -} - -static inline __u32 ipath_hdrget_ipath_ver(__le32 hdrword) -{ - return (__le32_to_cpu(hdrword) >> INFINIPATH_I_VERS_SHIFT) - & INFINIPATH_I_VERS_MASK; -} - -#endif /* _IPATH_COMMON_H */ diff --git a/drivers/staging/rdma/ipath/ipath_cq.c b/drivers/staging/rdma/ipath/ipath_cq.c deleted file mode 100644 index e9dd9112e718..000000000000 --- a/drivers/staging/rdma/ipath/ipath_cq.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. - * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include - -#include "ipath_verbs.h" - -/** - * ipath_cq_enter - add a new entry to the completion queue - * @cq: completion queue - * @entry: work completion entry to add - * @sig: true if @entry is a solicitated entry - * - * This may be called with qp->s_lock held. - */ -void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int solicited) -{ - struct ipath_cq_wc *wc; - unsigned long flags; - u32 head; - u32 next; - - spin_lock_irqsave(&cq->lock, flags); - - /* - * Note that the head pointer might be writable by user processes. - * Take care to verify it is a sane value. - */ - wc = cq->queue; - head = wc->head; - if (head >= (unsigned) cq->ibcq.cqe) { - head = cq->ibcq.cqe; - next = 0; - } else - next = head + 1; - if (unlikely(next == wc->tail)) { - spin_unlock_irqrestore(&cq->lock, flags); - if (cq->ibcq.event_handler) { - struct ib_event ev; - - ev.device = cq->ibcq.device; - ev.element.cq = &cq->ibcq; - ev.event = IB_EVENT_CQ_ERR; - cq->ibcq.event_handler(&ev, cq->ibcq.cq_context); - } - return; - } - if (cq->ip) { - wc->uqueue[head].wr_id = entry->wr_id; - wc->uqueue[head].status = entry->status; - wc->uqueue[head].opcode = entry->opcode; - wc->uqueue[head].vendor_err = entry->vendor_err; - wc->uqueue[head].byte_len = entry->byte_len; - wc->uqueue[head].ex.imm_data = (__u32 __force) entry->ex.imm_data; - wc->uqueue[head].qp_num = entry->qp->qp_num; - wc->uqueue[head].src_qp = entry->src_qp; - wc->uqueue[head].wc_flags = entry->wc_flags; - wc->uqueue[head].pkey_index = entry->pkey_index; - wc->uqueue[head].slid = entry->slid; - wc->uqueue[head].sl = entry->sl; - wc->uqueue[head].dlid_path_bits = entry->dlid_path_bits; - wc->uqueue[head].port_num = entry->port_num; - /* Make sure entry is written before the head index. */ - smp_wmb(); - } else - wc->kqueue[head] = *entry; - wc->head = next; - - if (cq->notify == IB_CQ_NEXT_COMP || - (cq->notify == IB_CQ_SOLICITED && solicited)) { - cq->notify = IB_CQ_NONE; - cq->triggered++; - /* - * This will cause send_complete() to be called in - * another thread. - */ - tasklet_hi_schedule(&cq->comptask); - } - - spin_unlock_irqrestore(&cq->lock, flags); - - if (entry->status != IB_WC_SUCCESS) - to_idev(cq->ibcq.device)->n_wqe_errs++; -} - -/** - * ipath_poll_cq - poll for work completion entries - * @ibcq: the completion queue to poll - * @num_entries: the maximum number of entries to return - * @entry: pointer to array where work completions are placed - * - * Returns the number of completion entries polled. - * - * This may be called from interrupt context. Also called by ib_poll_cq() - * in the generic verbs code. - */ -int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) -{ - struct ipath_cq *cq = to_icq(ibcq); - struct ipath_cq_wc *wc; - unsigned long flags; - int npolled; - u32 tail; - - /* The kernel can only poll a kernel completion queue */ - if (cq->ip) { - npolled = -EINVAL; - goto bail; - } - - spin_lock_irqsave(&cq->lock, flags); - - wc = cq->queue; - tail = wc->tail; - if (tail > (u32) cq->ibcq.cqe) - tail = (u32) cq->ibcq.cqe; - for (npolled = 0; npolled < num_entries; ++npolled, ++entry) { - if (tail == wc->head) - break; - /* The kernel doesn't need a RMB since it has the lock. */ - *entry = wc->kqueue[tail]; - if (tail >= cq->ibcq.cqe) - tail = 0; - else - tail++; - } - wc->tail = tail; - - spin_unlock_irqrestore(&cq->lock, flags); - -bail: - return npolled; -} - -static void send_complete(unsigned long data) -{ - struct ipath_cq *cq = (struct ipath_cq *)data; - - /* - * The completion handler will most likely rearm the notification - * and poll for all pending entries. If a new completion entry - * is added while we are in this routine, tasklet_hi_schedule() - * won't call us again until we return so we check triggered to - * see if we need to call the handler again. - */ - for (;;) { - u8 triggered = cq->triggered; - - cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context); - - if (cq->triggered == triggered) - return; - } -} - -/** - * ipath_create_cq - create a completion queue - * @ibdev: the device this completion queue is attached to - * @attr: creation attributes - * @context: unused by the InfiniPath driver - * @udata: unused by the InfiniPath driver - * - * Returns a pointer to the completion queue or negative errno values - * for failure. - * - * Called by ib_create_cq() in the generic verbs code. - */ -struct ib_cq *ipath_create_cq(struct ib_device *ibdev, - const struct ib_cq_init_attr *attr, - struct ib_ucontext *context, - struct ib_udata *udata) -{ - int entries = attr->cqe; - struct ipath_ibdev *dev = to_idev(ibdev); - struct ipath_cq *cq; - struct ipath_cq_wc *wc; - struct ib_cq *ret; - u32 sz; - - if (attr->flags) - return ERR_PTR(-EINVAL); - - if (entries < 1 || entries > ib_ipath_max_cqes) { - ret = ERR_PTR(-EINVAL); - goto done; - } - - /* Allocate the completion queue structure. */ - cq = kmalloc(sizeof(*cq), GFP_KERNEL); - if (!cq) { - ret = ERR_PTR(-ENOMEM); - goto done; - } - - /* - * Allocate the completion queue entries and head/tail pointers. - * This is allocated separately so that it can be resized and - * also mapped into user space. - * We need to use vmalloc() in order to support mmap and large - * numbers of entries. - */ - sz = sizeof(*wc); - if (udata && udata->outlen >= sizeof(__u64)) - sz += sizeof(struct ib_uverbs_wc) * (entries + 1); - else - sz += sizeof(struct ib_wc) * (entries + 1); - wc = vmalloc_user(sz); - if (!wc) { - ret = ERR_PTR(-ENOMEM); - goto bail_cq; - } - - /* - * Return the address of the WC as the offset to mmap. - * See ipath_mmap() for details. - */ - if (udata && udata->outlen >= sizeof(__u64)) { - int err; - - cq->ip = ipath_create_mmap_info(dev, sz, context, wc); - if (!cq->ip) { - ret = ERR_PTR(-ENOMEM); - goto bail_wc; - } - - err = ib_copy_to_udata(udata, &cq->ip->offset, - sizeof(cq->ip->offset)); - if (err) { - ret = ERR_PTR(err); - goto bail_ip; - } - } else - cq->ip = NULL; - - spin_lock(&dev->n_cqs_lock); - if (dev->n_cqs_allocated == ib_ipath_max_cqs) { - spin_unlock(&dev->n_cqs_lock); - ret = ERR_PTR(-ENOMEM); - goto bail_ip; - } - - dev->n_cqs_allocated++; - spin_unlock(&dev->n_cqs_lock); - - if (cq->ip) { - spin_lock_irq(&dev->pending_lock); - list_add(&cq->ip->pending_mmaps, &dev->pending_mmaps); - spin_unlock_irq(&dev->pending_lock); - } - - /* - * ib_create_cq() will initialize cq->ibcq except for cq->ibcq.cqe. - * The number of entries should be >= the number requested or return - * an error. - */ - cq->ibcq.cqe = entries; - cq->notify = IB_CQ_NONE; - cq->triggered = 0; - spin_lock_init(&cq->lock); - tasklet_init(&cq->comptask, send_complete, (unsigned long)cq); - wc->head = 0; - wc->tail = 0; - cq->queue = wc; - - ret = &cq->ibcq; - - goto done; - -bail_ip: - kfree(cq->ip); -bail_wc: - vfree(wc); -bail_cq: - kfree(cq); -done: - return ret; -} - -/** - * ipath_destroy_cq - destroy a completion queue - * @ibcq: the completion queue to destroy. - * - * Returns 0 for success. - * - * Called by ib_destroy_cq() in the generic verbs code. - */ -int ipath_destroy_cq(struct ib_cq *ibcq) -{ - struct ipath_ibdev *dev = to_idev(ibcq->device); - struct ipath_cq *cq = to_icq(ibcq); - - tasklet_kill(&cq->comptask); - spin_lock(&dev->n_cqs_lock); - dev->n_cqs_allocated--; - spin_unlock(&dev->n_cqs_lock); - if (cq->ip) - kref_put(&cq->ip->ref, ipath_release_mmap_info); - else - vfree(cq->queue); - kfree(cq); - - return 0; -} - -/** - * ipath_req_notify_cq - change the notification type for a completion queue - * @ibcq: the completion queue - * @notify_flags: the type of notification to request - * - * Returns 0 for success. - * - * This may be called from interrupt context. Also called by - * ib_req_notify_cq() in the generic verbs code. - */ -int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags notify_flags) -{ - struct ipath_cq *cq = to_icq(ibcq); - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&cq->lock, flags); - /* - * Don't change IB_CQ_NEXT_COMP to IB_CQ_SOLICITED but allow - * any other transitions (see C11-31 and C11-32 in ch. 11.4.2.2). - */ - if (cq->notify != IB_CQ_NEXT_COMP) - cq->notify = notify_flags & IB_CQ_SOLICITED_MASK; - - if ((notify_flags & IB_CQ_REPORT_MISSED_EVENTS) && - cq->queue->head != cq->queue->tail) - ret = 1; - - spin_unlock_irqrestore(&cq->lock, flags); - - return ret; -} - -/** - * ipath_resize_cq - change the size of the CQ - * @ibcq: the completion queue - * - * Returns 0 for success. - */ -int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata) -{ - struct ipath_cq *cq = to_icq(ibcq); - struct ipath_cq_wc *old_wc; - struct ipath_cq_wc *wc; - u32 head, tail, n; - int ret; - u32 sz; - - if (cqe < 1 || cqe > ib_ipath_max_cqes) { - ret = -EINVAL; - goto bail; - } - - /* - * Need to use vmalloc() if we want to support large #s of entries. - */ - sz = sizeof(*wc); - if (udata && udata->outlen >= sizeof(__u64)) - sz += sizeof(struct ib_uverbs_wc) * (cqe + 1); - else - sz += sizeof(struct ib_wc) * (cqe + 1); - wc = vmalloc_user(sz); - if (!wc) { - ret = -ENOMEM; - goto bail; - } - - /* Check that we can write the offset to mmap. */ - if (udata && udata->outlen >= sizeof(__u64)) { - __u64 offset = 0; - - ret = ib_copy_to_udata(udata, &offset, sizeof(offset)); - if (ret) - goto bail_free; - } - - spin_lock_irq(&cq->lock); - /* - * Make sure head and tail are sane since they - * might be user writable. - */ - old_wc = cq->queue; - head = old_wc->head; - if (head > (u32) cq->ibcq.cqe) - head = (u32) cq->ibcq.cqe; - tail = old_wc->tail; - if (tail > (u32) cq->ibcq.cqe) - tail = (u32) cq->ibcq.cqe; - if (head < tail) - n = cq->ibcq.cqe + 1 + head - tail; - else - n = head - tail; - if (unlikely((u32)cqe < n)) { - ret = -EINVAL; - goto bail_unlock; - } - for (n = 0; tail != head; n++) { - if (cq->ip) - wc->uqueue[n] = old_wc->uqueue[tail]; - else - wc->kqueue[n] = old_wc->kqueue[tail]; - if (tail == (u32) cq->ibcq.cqe) - tail = 0; - else - tail++; - } - cq->ibcq.cqe = cqe; - wc->head = n; - wc->tail = 0; - cq->queue = wc; - spin_unlock_irq(&cq->lock); - - vfree(old_wc); - - if (cq->ip) { - struct ipath_ibdev *dev = to_idev(ibcq->device); - struct ipath_mmap_info *ip = cq->ip; - - ipath_update_mmap_info(dev, ip, sz, wc); - - /* - * Return the offset to mmap. - * See ipath_mmap() for details. - */ - if (udata && udata->outlen >= sizeof(__u64)) { - ret = ib_copy_to_udata(udata, &ip->offset, - sizeof(ip->offset)); - if (ret) - goto bail; - } - - spin_lock_irq(&dev->pending_lock); - if (list_empty(&ip->pending_mmaps)) - list_add(&ip->pending_mmaps, &dev->pending_mmaps); - spin_unlock_irq(&dev->pending_lock); - } - - ret = 0; - goto bail; - -bail_unlock: - spin_unlock_irq(&cq->lock); -bail_free: - vfree(wc); -bail: - return ret; -} diff --git a/drivers/staging/rdma/ipath/ipath_debug.h b/drivers/staging/rdma/ipath/ipath_debug.h deleted file mode 100644 index 65926cd35759..000000000000 --- a/drivers/staging/rdma/ipath/ipath_debug.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. - * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _IPATH_DEBUG_H -#define _IPATH_DEBUG_H - -#ifndef _IPATH_DEBUGGING /* debugging enabled or not */ -#define _IPATH_DEBUGGING 1 -#endif - -#if _IPATH_DEBUGGING - -/* - * Mask values for debugging. The scheme allows us to compile out any - * of the debug tracing stuff, and if compiled in, to enable or disable - * dynamically. This can be set at modprobe time also: - * modprobe infinipath.ko infinipath_debug=7 - */ - -#define __IPATH_INFO 0x1 /* generic low verbosity stuff */ -#define __IPATH_DBG 0x2 /* generic debug */ -#define __IPATH_TRSAMPLE 0x8 /* generate trace buffer sample entries */ -/* leave some low verbosity spots open */ -#define __IPATH_VERBDBG 0x40 /* very verbose debug */ -#define __IPATH_PKTDBG 0x80 /* print packet data */ -/* print process startup (init)/exit messages */ -#define __IPATH_PROCDBG 0x100 -/* print mmap/fault stuff, not using VDBG any more */ -#define __IPATH_MMDBG 0x200 -#define __IPATH_ERRPKTDBG 0x400 -#define __IPATH_USER_SEND 0x1000 /* use user mode send */ -#define __IPATH_KERNEL_SEND 0x2000 /* use kernel mode send */ -#define __IPATH_EPKTDBG 0x4000 /* print ethernet packet data */ -#define __IPATH_IPATHDBG 0x10000 /* Ethernet (IPATH) gen debug */ -#define __IPATH_IPATHWARN 0x20000 /* Ethernet (IPATH) warnings */ -#define __IPATH_IPATHERR 0x40000 /* Ethernet (IPATH) errors */ -#define __IPATH_IPATHPD 0x80000 /* Ethernet (IPATH) packet dump */ -#define __IPATH_IPATHTABLE 0x100000 /* Ethernet (IPATH) table dump */ -#define __IPATH_LINKVERBDBG 0x200000 /* very verbose linkchange debug */ - -#else /* _IPATH_DEBUGGING */ - -/* - * define all of these even with debugging off, for the few places that do - * if(infinipath_debug & _IPATH_xyzzy), but in a way that will make the - * compiler eliminate the code - */ - -#define __IPATH_INFO 0x0 /* generic low verbosity stuff */ -#define __IPATH_DBG 0x0 /* generic debug */ -#define __IPATH_TRSAMPLE 0x0 /* generate trace buffer sample entries */ -#define __IPATH_VERBDBG 0x0 /* very verbose debug */ -#define __IPATH_PKTDBG 0x0 /* print packet data */ -#define __IPATH_PROCDBG 0x0 /* process startup (init)/exit messages */ -/* print mmap/fault stuff, not using VDBG any more */ -#define __IPATH_MMDBG 0x0 -#define __IPATH_EPKTDBG 0x0 /* print ethernet packet data */ -#define __IPATH_IPATHDBG 0x0 /* Ethernet (IPATH) table dump on */ -#define __IPATH_IPATHWARN 0x0 /* Ethernet (IPATH) warnings on */ -#define __IPATH_IPATHERR 0x0 /* Ethernet (IPATH) errors on */ -#define __IPATH_IPATHPD 0x0 /* Ethernet (IPATH) packet dump on */ -#define __IPATH_IPATHTABLE 0x0 /* Ethernet (IPATH) packet dump on */ -#define __IPATH_LINKVERBDBG 0x0 /* very verbose linkchange debug */ - -#endif /* _IPATH_DEBUGGING */ - -#define __IPATH_VERBOSEDBG __IPATH_VERBDBG - -#endif /* _IPATH_DEBUG_H */ diff --git a/drivers/staging/rdma/ipath/ipath_diag.c b/drivers/staging/rdma/ipath/ipath_diag.c deleted file mode 100644 index 45802e97332e..000000000000 --- a/drivers/staging/rdma/ipath/ipath_diag.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * This file contains support for diagnostic functions. It is accessed by - * opening the ipath_diag device, normally minor number 129. Diagnostic use - * of the InfiniPath chip may render the chip or board unusable until the - * driver is unloaded, or in some cases, until the system is rebooted. - * - * Accesses to the chip through this interface are not similar to going - * through the /sys/bus/pci resource mmap interface. - */ - -#include -#include -#include -#include -#include -#include - -#include "ipath_kernel.h" -#include "ipath_common.h" - -int ipath_diag_inuse; -static int diag_set_link; - -static int ipath_diag_open(struct inode *in, struct file *fp); -static int ipath_diag_release(struct inode *in, struct file *fp); -static ssize_t ipath_diag_read(struct file *fp, char __user *data, - size_t count, loff_t *off); -static ssize_t ipath_diag_write(struct file *fp, const char __user *data, - size_t count, loff_t *off); - -static const struct file_operations diag_file_ops = { - .owner = THIS_MODULE, - .write = ipath_diag_write, - .read = ipath_diag_read, - .open = ipath_diag_open, - .release = ipath_diag_release, - .llseek = default_llseek, -}; - -static ssize_t ipath_diagpkt_write(struct file *fp, - const char __user *data, - size_t count, loff_t *off); - -static const struct file_operations diagpkt_file_ops = { - .owner = THIS_MODULE, - .write = ipath_diagpkt_write, - .llseek = noop_llseek, -}; - -static atomic_t diagpkt_count = ATOMIC_INIT(0); -static struct cdev *diagpkt_cdev; -static struct device *diagpkt_dev; - -int ipath_diag_add(struct ipath_devdata *dd) -{ - char name[16]; - int ret = 0; - - if (atomic_inc_return(&diagpkt_count) == 1) { - ret = ipath_cdev_init(IPATH_DIAGPKT_MINOR, - "ipath_diagpkt", &diagpkt_file_ops, - &diagpkt_cdev, &diagpkt_dev); - - if (ret) { - ipath_dev_err(dd, "Couldn't create ipath_diagpkt " - "device: %d", ret); - goto done; - } - } - - snprintf(name, sizeof(name), "ipath_diag%d", dd->ipath_unit); - - ret = ipath_cdev_init(IPATH_DIAG_MINOR_BASE + dd->ipath_unit, name, - &diag_file_ops, &dd->diag_cdev, - &dd->diag_dev); - if (ret) - ipath_dev_err(dd, "Couldn't create %s device: %d", - name, ret); - -done: - return ret; -} - -void ipath_diag_remove(struct ipath_devdata *dd) -{ - if (atomic_dec_and_test(&diagpkt_count)) - ipath_cdev_cleanup(&diagpkt_cdev, &diagpkt_dev); - - ipath_cdev_cleanup(&dd->diag_cdev, &dd->diag_dev); -} - -/** - * ipath_read_umem64 - read a 64-bit quantity from the chip into user space - * @dd: the infinipath device - * @uaddr: the location to store the data in user memory - * @caddr: the source chip address (full pointer, not offset) - * @count: number of bytes to copy (multiple of 32 bits) - * - * This function also localizes all chip memory accesses. - * The copy should be written such that we read full cacheline packets - * from the chip. This is usually used for a single qword - * - * NOTE: This assumes the chip address is 64-bit aligned. - */ -static int ipath_read_umem64(struct ipath_devdata *dd, void __user *uaddr, - const void __iomem *caddr, size_t count) -{ - const u64 __iomem *reg_addr = caddr; - const u64 __iomem *reg_end = reg_addr + (count / sizeof(u64)); - int ret; - - /* not very efficient, but it works for now */ - if (reg_addr < dd->ipath_kregbase || reg_end > dd->ipath_kregend) { - ret = -EINVAL; - goto bail; - } - while (reg_addr < reg_end) { - u64 data = readq(reg_addr); - if (copy_to_user(uaddr, &data, sizeof(u64))) { - ret = -EFAULT; - goto bail; - } - reg_addr++; - uaddr += sizeof(u64); - } - ret = 0; -bail: - return ret; -} - -/** - * ipath_write_umem64 - write a 64-bit quantity to the chip from user space - * @dd: the infinipath device - * @caddr: the destination chip address (full pointer, not offset) - * @uaddr: the source of the data in user memory - * @count: the number of bytes to copy (multiple of 32 bits) - * - * This is usually used for a single qword - * NOTE: This assumes the chip address is 64-bit aligned. - */ - -static int ipath_write_umem64(struct ipath_devdata *dd, void __iomem *caddr, - const void __user *uaddr, size_t count) -{ - u64 __iomem *reg_addr = caddr; - const u64 __iomem *reg_end = reg_addr + (count / sizeof(u64)); - int ret; - - /* not very efficient, but it works for now */ - if (reg_addr < dd->ipath_kregbase || reg_end > dd->ipath_kregend) { - ret = -EINVAL; - goto bail; - } - while (reg_addr < reg_end) { - u64 data; - if (copy_from_user(&data, uaddr, sizeof(data))) { - ret = -EFAULT; - goto bail; - } - writeq(data, reg_addr); - - reg_addr++; - uaddr += sizeof(u64); - } - ret = 0; -bail: - return ret; -} - -/** - * ipath_read_umem32 - read a 32-bit quantity from the chip into user space - * @dd: the infinipath device - * @uaddr: the location to store the data in user memory - * @caddr: the source chip address (full pointer, not offset) - * @count: number of bytes to copy - * - * read 32 bit values, not 64 bit; for memories that only - * support 32 bit reads; usually a single dword. - */ -static int ipath_read_umem32(struct ipath_devdata *dd, void __user *uaddr, - const void __iomem *caddr, size_t count) -{ - const u32 __iomem *reg_addr = caddr; - const u32 __iomem *reg_end = reg_addr + (count / sizeof(u32)); - int ret; - - if (reg_addr < (u32 __iomem *) dd->ipath_kregbase || - reg_end > (u32 __iomem *) dd->ipath_kregend) { - ret = -EINVAL; - goto bail; - } - /* not very efficient, but it works for now */ - while (reg_addr < reg_end) { - u32 data = readl(reg_addr); - if (copy_to_user(uaddr, &data, sizeof(data))) { - ret = -EFAULT; - goto bail; - } - - reg_addr++; - uaddr += sizeof(u32); - - } - ret = 0; -bail: - return ret; -} - -/** - * ipath_write_umem32 - write a 32-bit quantity to the chip from user space - * @dd: the infinipath device - * @caddr: the destination chip address (full pointer, not offset) - * @uaddr: the source of the data in user memory - * @count: number of bytes to copy - * - * write 32 bit values, not 64 bit; for memories that only - * support 32 bit write; usually a single dword. - */ - -static int ipath_write_umem32(struct ipath_devdata *dd, void __iomem *caddr, - const void __user *uaddr, size_t count) -{ - u32 __iomem *reg_addr = caddr; - const u32 __iomem *reg_end = reg_addr + (count / sizeof(u32)); - int ret; - - if (reg_addr < (u32 __iomem *) dd->ipath_kregbase || - reg_end > (u32 __iomem *) dd->ipath_kregend) { - ret = -EINVAL; - goto bail; - } - while (reg_addr < reg_end) { - u32 data; - if (copy_from_user(&data, uaddr, sizeof(data))) { - ret = -EFAULT; - goto bail; - } - writel(data, reg_addr); - - reg_addr++; - uaddr += sizeof(u32); - } - ret = 0; -bail: - return ret; -} - -static int ipath_diag_open(struct inode *in, struct file *fp) -{ - int unit = iminor(in) - IPATH_DIAG_MINOR_BASE; - struct ipath_devdata *dd; - int ret; - - mutex_lock(&ipath_mutex); - - if (ipath_diag_inuse) { - ret = -EBUSY; - goto bail; - } - - dd = ipath_lookup(unit); - - if (dd == NULL || !(dd->ipath_flags & IPATH_PRESENT) || - !dd->ipath_kregbase) { - ret = -ENODEV; - goto bail; - } - - fp->private_data = dd; - ipath_diag_inuse = -2; - diag_set_link = 0; - ret = 0; - - /* Only expose a way to reset the device if we - make it into diag mode. */ - ipath_expose_reset(&dd->pcidev->dev); - -bail: - mutex_unlock(&ipath_mutex); - - return ret; -} - -/** - * ipath_diagpkt_write - write an IB packet - * @fp: the diag data device file pointer - * @data: ipath_diag_pkt structure saying where to get the packet - * @count: size of data to write - * @off: unused by this code - */ -static ssize_t ipath_diagpkt_write(struct file *fp, - const char __user *data, - size_t count, loff_t *off) -{ - u32 __iomem *piobuf; - u32 plen, pbufn, maxlen_reserve; - struct ipath_diag_pkt odp; - struct ipath_diag_xpkt dp; - u32 *tmpbuf = NULL; - struct ipath_devdata *dd; - ssize_t ret = 0; - u64 val; - u32 l_state, lt_state; /* LinkState, LinkTrainingState */ - - - if (count == sizeof(dp)) { - if (copy_from_user(&dp, data, sizeof(dp))) { - ret = -EFAULT; - goto bail; - } - } else if (count == sizeof(odp)) { - if (copy_from_user(&odp, data, sizeof(odp))) { - ret = -EFAULT; - goto bail; - } - dp.len = odp.len; - dp.unit = odp.unit; - dp.data = odp.data; - dp.pbc_wd = 0; - } else { - ret = -EINVAL; - goto bail; - } - - /* send count must be an exact number of dwords */ - if (dp.len & 3) { - ret = -EINVAL; - goto bail; - } - - plen = dp.len >> 2; - - dd = ipath_lookup(dp.unit); - if (!dd || !(dd->ipath_flags & IPATH_PRESENT) || - !dd->ipath_kregbase) { - ipath_cdbg(VERBOSE, "illegal unit %u for diag data send\n", - dp.unit); - ret = -ENODEV; - goto bail; - } - - if (ipath_diag_inuse && !diag_set_link && - !(dd->ipath_flags & IPATH_LINKACTIVE)) { - diag_set_link = 1; - ipath_cdbg(VERBOSE, "Trying to set to set link active for " - "diag pkt\n"); - ipath_set_linkstate(dd, IPATH_IB_LINKARM); - ipath_set_linkstate(dd, IPATH_IB_LINKACTIVE); - } - - if (!(dd->ipath_flags & IPATH_INITTED)) { - /* no hardware, freeze, etc. */ - ipath_cdbg(VERBOSE, "unit %u not usable\n", dd->ipath_unit); - ret = -ENODEV; - goto bail; - } - /* - * Want to skip check for l_state if using custom PBC, - * because we might be trying to force an SM packet out. - * first-cut, skip _all_ state checking in that case. - */ - val = ipath_ib_state(dd, dd->ipath_lastibcstat); - lt_state = ipath_ib_linktrstate(dd, dd->ipath_lastibcstat); - l_state = ipath_ib_linkstate(dd, dd->ipath_lastibcstat); - if (!dp.pbc_wd && (lt_state != INFINIPATH_IBCS_LT_STATE_LINKUP || - (val != dd->ib_init && val != dd->ib_arm && - val != dd->ib_active))) { - ipath_cdbg(VERBOSE, "unit %u not ready (state %llx)\n", - dd->ipath_unit, (unsigned long long) val); - ret = -EINVAL; - goto bail; - } - - /* - * need total length before first word written, plus 2 Dwords. One Dword - * is for padding so we get the full user data when not aligned on - * a word boundary. The other Dword is to make sure we have room for the - * ICRC which gets tacked on later. - */ - maxlen_reserve = 2 * sizeof(u32); - if (dp.len > dd->ipath_ibmaxlen - maxlen_reserve) { - ipath_dbg("Pkt len 0x%x > ibmaxlen %x\n", - dp.len, dd->ipath_ibmaxlen); - ret = -EINVAL; - goto bail; - } - - plen = sizeof(u32) + dp.len; - - tmpbuf = vmalloc(plen); - if (!tmpbuf) { - dev_info(&dd->pcidev->dev, "Unable to allocate tmp buffer, " - "failing\n"); - ret = -ENOMEM; - goto bail; - } - - if (copy_from_user(tmpbuf, - (const void __user *) (unsigned long) dp.data, - dp.len)) { - ret = -EFAULT; - goto bail; - } - - plen >>= 2; /* in dwords */ - - piobuf = ipath_getpiobuf(dd, plen, &pbufn); - if (!piobuf) { - ipath_cdbg(VERBOSE, "No PIO buffers avail unit for %u\n", - dd->ipath_unit); - ret = -EBUSY; - goto bail; - } - /* disarm it just to be extra sure */ - ipath_disarm_piobufs(dd, pbufn, 1); - - if (ipath_debug & __IPATH_PKTDBG) - ipath_cdbg(VERBOSE, "unit %u 0x%x+1w pio%d\n", - dd->ipath_unit, plen - 1, pbufn); - - if (dp.pbc_wd == 0) - dp.pbc_wd = plen; - writeq(dp.pbc_wd, piobuf); - /* - * Copy all by the trigger word, then flush, so it's written - * to chip before trigger word, then write trigger word, then - * flush again, so packet is sent. - */ - if (dd->ipath_flags & IPATH_PIO_FLUSH_WC) { - ipath_flush_wc(); - __iowrite32_copy(piobuf + 2, tmpbuf, plen - 1); - ipath_flush_wc(); - __raw_writel(tmpbuf[plen - 1], piobuf + plen + 1); - } else - __iowrite32_copy(piobuf + 2, tmpbuf, plen); - - ipath_flush_wc(); - - ret = sizeof(dp); - -bail: - vfree(tmpbuf); - return ret; -} - -static int ipath_diag_release(struct inode *in, struct file *fp) -{ - mutex_lock(&ipath_mutex); - ipath_diag_inuse = 0; - fp->private_data = NULL; - mutex_unlock(&ipath_mutex); - return 0; -} - -static ssize_t ipath_diag_read(struct file *fp, char __user *data, - size_t count, loff_t *off) -{ - struct ipath_devdata *dd = fp->private_data; - void __iomem *kreg_base; - ssize_t ret; - - kreg_base = dd->ipath_kregbase; - - if (count == 0) - ret = 0; - else if ((count % 4) || (*off % 4)) - /* address or length is not 32-bit aligned, hence invalid */ - ret = -EINVAL; - else if (ipath_diag_inuse < 1 && (*off || count != 8)) - ret = -EINVAL; /* prevent cat /dev/ipath_diag* */ - else if ((count % 8) || (*off % 8)) - /* address or length not 64-bit aligned; do 32-bit reads */ - ret = ipath_read_umem32(dd, data, kreg_base + *off, count); - else - ret = ipath_read_umem64(dd, data, kreg_base + *off, count); - - if (ret >= 0) { - *off += count; - ret = count; - if (ipath_diag_inuse == -2) - ipath_diag_inuse++; - } - - return ret; -} - -static ssize_t ipath_diag_write(struct file *fp, const char __user *data, - size_t count, loff_t *off) -{ - struct ipath_devdata *dd = fp->private_data; - void __iomem *kreg_base; - ssize_t ret; - - kreg_base = dd->ipath_kregbase; - - if (count == 0) - ret = 0; - else if ((count % 4) || (*off % 4)) - /* address or length is not 32-bit aligned, hence invalid */ - ret = -EINVAL; - else if ((ipath_diag_inuse == -1 && (*off || count != 8)) || - ipath_diag_inuse == -2) /* read qw off 0, write qw off 0 */ - ret = -EINVAL; /* before any other write allowed */ - else if ((count % 8) || (*off % 8)) - /* address or length not 64-bit aligned; do 32-bit writes */ - ret = ipath_write_umem32(dd, kreg_base + *off, data, count); - else - ret = ipath_write_umem64(dd, kreg_base + *off, data, count); - - if (ret >= 0) { - *off += count; - ret = count; - if (ipath_diag_inuse == -1) - ipath_diag_inuse = 1; /* all read/write OK now */ - } - - return ret; -} diff --git a/drivers/staging/rdma/ipath/ipath_dma.c b/drivers/staging/rdma/ipath/ipath_dma.c deleted file mode 100644 index 123a8c053539..000000000000 --- a/drivers/staging/rdma/ipath/ipath_dma.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2006 QLogic, Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include - -#include "ipath_verbs.h" - -#define BAD_DMA_ADDRESS ((u64) 0) - -/* - * The following functions implement driver specific replacements - * for the ib_dma_*() functions. - * - * These functions return kernel virtual addresses instead of - * device bus addresses since the driver uses the CPU to copy - * data instead of using hardware DMA. - */ - -static int ipath_mapping_error(struct ib_device *dev, u64 dma_addr) -{ - return dma_addr == BAD_DMA_ADDRESS; -} - -static u64 ipath_dma_map_single(struct ib_device *dev, - void *cpu_addr, size_t size, - enum dma_data_direction direction) -{ - BUG_ON(!valid_dma_direction(direction)); - return (u64) cpu_addr; -} - -static void ipath_dma_unmap_single(struct ib_device *dev, - u64 addr, size_t size, - enum dma_data_direction direction) -{ - BUG_ON(!valid_dma_direction(direction)); -} - -static u64 ipath_dma_map_page(struct ib_device *dev, - struct page *page, - unsigned long offset, - size_t size, - enum dma_data_direction direction) -{ - u64 addr; - - BUG_ON(!valid_dma_direction(direction)); - - if (offset + size > PAGE_SIZE) { - addr = BAD_DMA_ADDRESS; - goto done; - } - - addr = (u64) page_address(page); - if (addr) - addr += offset; - /* TODO: handle highmem pages */ - -done: - return addr; -} - -static void ipath_dma_unmap_page(struct ib_device *dev, - u64 addr, size_t size, - enum dma_data_direction direction) -{ - BUG_ON(!valid_dma_direction(direction)); -} - -static int ipath_map_sg(struct ib_device *dev, struct scatterlist *sgl, - int nents, enum dma_data_direction direction) -{ - struct scatterlist *sg; - u64 addr; - int i; - int ret = nents; - - BUG_ON(!valid_dma_direction(direction)); - - for_each_sg(sgl, sg, nents, i) { - addr = (u64) page_address(sg_page(sg)); - /* TODO: handle highmem pages */ - if (!addr) { - ret = 0; - break; - } - sg->dma_address = addr + sg->offset; -#ifdef CONFIG_NEED_SG_DMA_LENGTH - sg->dma_length = sg->length; -#endif - } - return ret; -} - -static void ipath_unmap_sg(struct ib_device *dev, - struct scatterlist *sg, int nents, - enum dma_data_direction direction) -{ - BUG_ON(!valid_dma_direction(direction)); -} - -static void ipath_sync_single_for_cpu(struct ib_device *dev, - u64 addr, - size_t size, - enum dma_data_direction dir) -{ -} - -static void ipath_sync_single_for_device(struct ib_device *dev, - u64 addr, - size_t size, - enum dma_data_direction dir) -{ -} - -static void *ipath_dma_alloc_coherent(struct ib_device *dev, size_t size, - u64 *dma_handle, gfp_t flag) -{ - struct page *p; - void *addr = NULL; - - p = alloc_pages(flag, get_order(size)); - if (p) - addr = page_address(p); - if (dma_handle) - *dma_handle = (u64) addr; - return addr; -} - -static void ipath_dma_free_coherent(struct ib_device *dev, size_t size, - void *cpu_addr, u64 dma_handle) -{ - free_pages((unsigned long) cpu_addr, get_order(size)); -} - -struct ib_dma_mapping_ops ipath_dma_mapping_ops = { - .mapping_error = ipath_mapping_error, - .map_single = ipath_dma_map_single, - .unmap_single = ipath_dma_unmap_single, - .map_page = ipath_dma_map_page, - .unmap_page = ipath_dma_unmap_page, - .map_sg = ipath_map_sg, - .unmap_sg = ipath_unmap_sg, - .sync_single_for_cpu = ipath_sync_single_for_cpu, - .sync_single_for_device = ipath_sync_single_for_device, - .alloc_coherent = ipath_dma_alloc_coherent, - .free_coherent = ipath_dma_free_coherent -}; diff --git a/drivers/staging/rdma/ipath/ipath_driver.c b/drivers/staging/rdma/ipath/ipath_driver.c deleted file mode 100644 index 2ab22f98e3ba..000000000000 --- a/drivers/staging/rdma/ipath/ipath_driver.c +++ /dev/null @@ -1,2784 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_X86_64 -#include -#endif - -#include "ipath_kernel.h" -#include "ipath_verbs.h" - -static void ipath_update_pio_bufs(struct ipath_devdata *); - -const char *ipath_get_unit_name(int unit) -{ - static char iname[16]; - snprintf(iname, sizeof iname, "infinipath%u", unit); - return iname; -} - -#define DRIVER_LOAD_MSG "QLogic " IPATH_DRV_NAME " loaded: " -#define PFX IPATH_DRV_NAME ": " - -/* - * The size has to be longer than this string, so we can append - * board/chip information to it in the init code. - */ -const char ib_ipath_version[] = IPATH_IDSTR "\n"; - -static struct idr unit_table; -DEFINE_SPINLOCK(ipath_devs_lock); -LIST_HEAD(ipath_dev_list); - -wait_queue_head_t ipath_state_wait; - -unsigned ipath_debug = __IPATH_INFO; - -module_param_named(debug, ipath_debug, uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(debug, "mask for debug prints"); -EXPORT_SYMBOL_GPL(ipath_debug); - -unsigned ipath_mtu4096 = 1; /* max 4KB IB mtu by default, if supported */ -module_param_named(mtu4096, ipath_mtu4096, uint, S_IRUGO); -MODULE_PARM_DESC(mtu4096, "enable MTU of 4096 bytes, if supported"); - -static unsigned ipath_hol_timeout_ms = 13000; -module_param_named(hol_timeout_ms, ipath_hol_timeout_ms, uint, S_IRUGO); -MODULE_PARM_DESC(hol_timeout_ms, - "duration of user app suspension after link failure"); - -unsigned ipath_linkrecovery = 1; -module_param_named(linkrecovery, ipath_linkrecovery, uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(linkrecovery, "enable workaround for link recovery issue"); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("QLogic "); -MODULE_DESCRIPTION("QLogic InfiniPath driver"); - -/* - * Table to translate the LINKTRAININGSTATE portion of - * IBCStatus to a human-readable form. - */ -const char *ipath_ibcstatus_str[] = { - "Disabled", - "LinkUp", - "PollActive", - "PollQuiet", - "SleepDelay", - "SleepQuiet", - "LState6", /* unused */ - "LState7", /* unused */ - "CfgDebounce", - "CfgRcvfCfg", - "CfgWaitRmt", - "CfgIdle", - "RecovRetrain", - "CfgTxRevLane", /* unused before IBA7220 */ - "RecovWaitRmt", - "RecovIdle", - /* below were added for IBA7220 */ - "CfgEnhanced", - "CfgTest", - "CfgWaitRmtTest", - "CfgWaitCfgEnhanced", - "SendTS_T", - "SendTstIdles", - "RcvTS_T", - "SendTst_TS1s", - "LTState18", "LTState19", "LTState1A", "LTState1B", - "LTState1C", "LTState1D", "LTState1E", "LTState1F" -}; - -static void ipath_remove_one(struct pci_dev *); -static int ipath_init_one(struct pci_dev *, const struct pci_device_id *); - -/* Only needed for registration, nothing else needs this info */ -#define PCI_VENDOR_ID_PATHSCALE 0x1fc1 -#define PCI_DEVICE_ID_INFINIPATH_HT 0xd - -/* Number of seconds before our card status check... */ -#define STATUS_TIMEOUT 60 - -static const struct pci_device_id ipath_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_HT) }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, ipath_pci_tbl); - -static struct pci_driver ipath_driver = { - .name = IPATH_DRV_NAME, - .probe = ipath_init_one, - .remove = ipath_remove_one, - .id_table = ipath_pci_tbl, - .driver = { - .groups = ipath_driver_attr_groups, - }, -}; - -static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev, - u32 *bar0, u32 *bar1) -{ - int ret; - - ret = pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, bar0); - if (ret) - ipath_dev_err(dd, "failed to read bar0 before enable: " - "error %d\n", -ret); - - ret = pci_read_config_dword(dev, PCI_BASE_ADDRESS_1, bar1); - if (ret) - ipath_dev_err(dd, "failed to read bar1 before enable: " - "error %d\n", -ret); - - ipath_dbg("Read bar0 %x bar1 %x\n", *bar0, *bar1); -} - -static void ipath_free_devdata(struct pci_dev *pdev, - struct ipath_devdata *dd) -{ - unsigned long flags; - - pci_set_drvdata(pdev, NULL); - - if (dd->ipath_unit != -1) { - spin_lock_irqsave(&ipath_devs_lock, flags); - idr_remove(&unit_table, dd->ipath_unit); - list_del(&dd->ipath_list); - spin_unlock_irqrestore(&ipath_devs_lock, flags); - } - vfree(dd); -} - -static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev) -{ - unsigned long flags; - struct ipath_devdata *dd; - int ret; - - dd = vzalloc(sizeof(*dd)); - if (!dd) { - dd = ERR_PTR(-ENOMEM); - goto bail; - } - dd->ipath_unit = -1; - - idr_preload(GFP_KERNEL); - spin_lock_irqsave(&ipath_devs_lock, flags); - - ret = idr_alloc(&unit_table, dd, 0, 0, GFP_NOWAIT); - if (ret < 0) { - printk(KERN_ERR IPATH_DRV_NAME - ": Could not allocate unit ID: error %d\n", -ret); - ipath_free_devdata(pdev, dd); - dd = ERR_PTR(ret); - goto bail_unlock; - } - dd->ipath_unit = ret; - - dd->pcidev = pdev; - pci_set_drvdata(pdev, dd); - - list_add(&dd->ipath_list, &ipath_dev_list); - -bail_unlock: - spin_unlock_irqrestore(&ipath_devs_lock, flags); - idr_preload_end(); -bail: - return dd; -} - -static inline struct ipath_devdata *__ipath_lookup(int unit) -{ - return idr_find(&unit_table, unit); -} - -struct ipath_devdata *ipath_lookup(int unit) -{ - struct ipath_devdata *dd; - unsigned long flags; - - spin_lock_irqsave(&ipath_devs_lock, flags); - dd = __ipath_lookup(unit); - spin_unlock_irqrestore(&ipath_devs_lock, flags); - - return dd; -} - -int ipath_count_units(int *npresentp, int *nupp, int *maxportsp) -{ - int nunits, npresent, nup; - struct ipath_devdata *dd; - unsigned long flags; - int maxports; - - nunits = npresent = nup = maxports = 0; - - spin_lock_irqsave(&ipath_devs_lock, flags); - - list_for_each_entry(dd, &ipath_dev_list, ipath_list) { - nunits++; - if ((dd->ipath_flags & IPATH_PRESENT) && dd->ipath_kregbase) - npresent++; - if (dd->ipath_lid && - !(dd->ipath_flags & (IPATH_DISABLED | IPATH_LINKDOWN - | IPATH_LINKUNK))) - nup++; - if (dd->ipath_cfgports > maxports) - maxports = dd->ipath_cfgports; - } - - spin_unlock_irqrestore(&ipath_devs_lock, flags); - - if (npresentp) - *npresentp = npresent; - if (nupp) - *nupp = nup; - if (maxportsp) - *maxportsp = maxports; - - return nunits; -} - -/* - * These next two routines are placeholders in case we don't have per-arch - * code for controlling write combining. If explicit control of write - * combining is not available, performance will probably be awful. - */ - -int __attribute__((weak)) ipath_enable_wc(struct ipath_devdata *dd) -{ - return -EOPNOTSUPP; -} - -void __attribute__((weak)) ipath_disable_wc(struct ipath_devdata *dd) -{ -} - -/* - * Perform a PIO buffer bandwidth write test, to verify proper system - * configuration. Even when all the setup calls work, occasionally - * BIOS or other issues can prevent write combining from working, or - * can cause other bandwidth problems to the chip. - * - * This test simply writes the same buffer over and over again, and - * measures close to the peak bandwidth to the chip (not testing - * data bandwidth to the wire). On chips that use an address-based - * trigger to send packets to the wire, this is easy. On chips that - * use a count to trigger, we want to make sure that the packet doesn't - * go out on the wire, or trigger flow control checks. - */ -static void ipath_verify_pioperf(struct ipath_devdata *dd) -{ - u32 pbnum, cnt, lcnt; - u32 __iomem *piobuf; - u32 *addr; - u64 msecs, emsecs; - - piobuf = ipath_getpiobuf(dd, 0, &pbnum); - if (!piobuf) { - dev_info(&dd->pcidev->dev, - "No PIObufs for checking perf, skipping\n"); - return; - } - - /* - * Enough to give us a reasonable test, less than piobuf size, and - * likely multiple of store buffer length. - */ - cnt = 1024; - - addr = vmalloc(cnt); - if (!addr) { - dev_info(&dd->pcidev->dev, - "Couldn't get memory for checking PIO perf," - " skipping\n"); - goto done; - } - - preempt_disable(); /* we want reasonably accurate elapsed time */ - msecs = 1 + jiffies_to_msecs(jiffies); - for (lcnt = 0; lcnt < 10000U; lcnt++) { - /* wait until we cross msec boundary */ - if (jiffies_to_msecs(jiffies) >= msecs) - break; - udelay(1); - } - - ipath_disable_armlaunch(dd); - - /* - * length 0, no dwords actually sent, and mark as VL15 - * on chips where that may matter (due to IB flowcontrol) - */ - if ((dd->ipath_flags & IPATH_HAS_PBC_CNT)) - writeq(1UL << 63, piobuf); - else - writeq(0, piobuf); - ipath_flush_wc(); - - /* - * this is only roughly accurate, since even with preempt we - * still take interrupts that could take a while. Running for - * >= 5 msec seems to get us "close enough" to accurate values - */ - msecs = jiffies_to_msecs(jiffies); - for (emsecs = lcnt = 0; emsecs <= 5UL; lcnt++) { - __iowrite32_copy(piobuf + 64, addr, cnt >> 2); - emsecs = jiffies_to_msecs(jiffies) - msecs; - } - - /* 1 GiB/sec, slightly over IB SDR line rate */ - if (lcnt < (emsecs * 1024U)) - ipath_dev_err(dd, - "Performance problem: bandwidth to PIO buffers is " - "only %u MiB/sec\n", - lcnt / (u32) emsecs); - else - ipath_dbg("PIO buffer bandwidth %u MiB/sec is OK\n", - lcnt / (u32) emsecs); - - preempt_enable(); - - vfree(addr); - -done: - /* disarm piobuf, so it's available again */ - ipath_disarm_piobufs(dd, pbnum, 1); - ipath_enable_armlaunch(dd); -} - -static void cleanup_device(struct ipath_devdata *dd); - -static int ipath_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int ret, len, j; - struct ipath_devdata *dd; - unsigned long long addr; - u32 bar0 = 0, bar1 = 0; - -#ifdef CONFIG_X86_64 - if (pat_enabled()) { - pr_warn("ipath needs PAT disabled, boot with nopat kernel parameter\n"); - ret = -ENODEV; - goto bail; - } -#endif - - dd = ipath_alloc_devdata(pdev); - if (IS_ERR(dd)) { - ret = PTR_ERR(dd); - printk(KERN_ERR IPATH_DRV_NAME - ": Could not allocate devdata: error %d\n", -ret); - goto bail; - } - - ipath_cdbg(VERBOSE, "initializing unit #%u\n", dd->ipath_unit); - - ret = pci_enable_device(pdev); - if (ret) { - /* This can happen iff: - * - * We did a chip reset, and then failed to reprogram the - * BAR, or the chip reset due to an internal error. We then - * unloaded the driver and reloaded it. - * - * Both reset cases set the BAR back to initial state. For - * the latter case, the AER sticky error bit at offset 0x718 - * should be set, but the Linux kernel doesn't yet know - * about that, it appears. If the original BAR was retained - * in the kernel data structures, this may be OK. - */ - ipath_dev_err(dd, "enable unit %d failed: error %d\n", - dd->ipath_unit, -ret); - goto bail_devdata; - } - addr = pci_resource_start(pdev, 0); - len = pci_resource_len(pdev, 0); - ipath_cdbg(VERBOSE, "regbase (0) %llx len %d irq %d, vend %x/%x " - "driver_data %lx\n", addr, len, pdev->irq, ent->vendor, - ent->device, ent->driver_data); - - read_bars(dd, pdev, &bar0, &bar1); - - if (!bar1 && !(bar0 & ~0xf)) { - if (addr) { - dev_info(&pdev->dev, "BAR is 0 (probable RESET), " - "rewriting as %llx\n", addr); - ret = pci_write_config_dword( - pdev, PCI_BASE_ADDRESS_0, addr); - if (ret) { - ipath_dev_err(dd, "rewrite of BAR0 " - "failed: err %d\n", -ret); - goto bail_disable; - } - ret = pci_write_config_dword( - pdev, PCI_BASE_ADDRESS_1, addr >> 32); - if (ret) { - ipath_dev_err(dd, "rewrite of BAR1 " - "failed: err %d\n", -ret); - goto bail_disable; - } - } else { - ipath_dev_err(dd, "BAR is 0 (probable RESET), " - "not usable until reboot\n"); - ret = -ENODEV; - goto bail_disable; - } - } - - ret = pci_request_regions(pdev, IPATH_DRV_NAME); - if (ret) { - dev_info(&pdev->dev, "pci_request_regions unit %u fails: " - "err %d\n", dd->ipath_unit, -ret); - goto bail_disable; - } - - ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); - if (ret) { - /* - * if the 64 bit setup fails, try 32 bit. Some systems - * do not setup 64 bit maps on systems with 2GB or less - * memory installed. - */ - ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (ret) { - dev_info(&pdev->dev, - "Unable to set DMA mask for unit %u: %d\n", - dd->ipath_unit, ret); - goto bail_regions; - } else { - ipath_dbg("No 64bit DMA mask, used 32 bit mask\n"); - ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); - if (ret) - dev_info(&pdev->dev, - "Unable to set DMA consistent mask " - "for unit %u: %d\n", - dd->ipath_unit, ret); - - } - } else { - ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); - if (ret) - dev_info(&pdev->dev, - "Unable to set DMA consistent mask " - "for unit %u: %d\n", - dd->ipath_unit, ret); - } - - pci_set_master(pdev); - - /* - * Save BARs to rewrite after device reset. Save all 64 bits of - * BAR, just in case. - */ - dd->ipath_pcibar0 = addr; - dd->ipath_pcibar1 = addr >> 32; - dd->ipath_deviceid = ent->device; /* save for later use */ - dd->ipath_vendorid = ent->vendor; - - /* setup the chip-specific functions, as early as possible. */ - switch (ent->device) { - case PCI_DEVICE_ID_INFINIPATH_HT: - ipath_init_iba6110_funcs(dd); - break; - - default: - ipath_dev_err(dd, "Found unknown QLogic deviceid 0x%x, " - "failing\n", ent->device); - return -ENODEV; - } - - for (j = 0; j < 6; j++) { - if (!pdev->resource[j].start) - continue; - ipath_cdbg(VERBOSE, "BAR %d %pR, len %llx\n", - j, &pdev->resource[j], - (unsigned long long)pci_resource_len(pdev, j)); - } - - if (!addr) { - ipath_dev_err(dd, "No valid address in BAR 0!\n"); - ret = -ENODEV; - goto bail_regions; - } - - dd->ipath_pcirev = pdev->revision; - -#if defined(__powerpc__) - /* There isn't a generic way to specify writethrough mappings */ - dd->ipath_kregbase = __ioremap(addr, len, - (_PAGE_NO_CACHE|_PAGE_WRITETHRU)); -#else - /* XXX: split this properly to enable on PAT */ - dd->ipath_kregbase = ioremap_nocache(addr, len); -#endif - - if (!dd->ipath_kregbase) { - ipath_dbg("Unable to map io addr %llx to kvirt, failing\n", - addr); - ret = -ENOMEM; - goto bail_iounmap; - } - dd->ipath_kregend = (u64 __iomem *) - ((void __iomem *)dd->ipath_kregbase + len); - dd->ipath_physaddr = addr; /* used for io_remap, etc. */ - /* for user mmap */ - ipath_cdbg(VERBOSE, "mapped io addr %llx to kregbase %p\n", - addr, dd->ipath_kregbase); - - if (dd->ipath_f_bus(dd, pdev)) - ipath_dev_err(dd, "Failed to setup config space; " - "continuing anyway\n"); - - /* - * set up our interrupt handler; IRQF_SHARED probably not needed, - * since MSI interrupts shouldn't be shared but won't hurt for now. - * check 0 irq after we return from chip-specific bus setup, since - * that can affect this due to setup - */ - if (!dd->ipath_irq) - ipath_dev_err(dd, "irq is 0, BIOS error? Interrupts won't " - "work\n"); - else { - ret = request_irq(dd->ipath_irq, ipath_intr, IRQF_SHARED, - IPATH_DRV_NAME, dd); - if (ret) { - ipath_dev_err(dd, "Couldn't setup irq handler, " - "irq=%d: %d\n", dd->ipath_irq, ret); - goto bail_iounmap; - } - } - - ret = ipath_init_chip(dd, 0); /* do the chip-specific init */ - if (ret) - goto bail_irqsetup; - - ret = ipath_enable_wc(dd); - - if (ret) - ret = 0; - - ipath_verify_pioperf(dd); - - ipath_device_create_group(&pdev->dev, dd); - ipathfs_add_device(dd); - ipath_user_add(dd); - ipath_diag_add(dd); - ipath_register_ib_device(dd); - - goto bail; - -bail_irqsetup: - cleanup_device(dd); - - if (dd->ipath_irq) - dd->ipath_f_free_irq(dd); - - if (dd->ipath_f_cleanup) - dd->ipath_f_cleanup(dd); - -bail_iounmap: - iounmap((volatile void __iomem *) dd->ipath_kregbase); - -bail_regions: - pci_release_regions(pdev); - -bail_disable: - pci_disable_device(pdev); - -bail_devdata: - ipath_free_devdata(pdev, dd); - -bail: - return ret; -} - -static void cleanup_device(struct ipath_devdata *dd) -{ - int port; - struct ipath_portdata **tmp; - unsigned long flags; - - if (*dd->ipath_statusp & IPATH_STATUS_CHIP_PRESENT) { - /* can't do anything more with chip; needs re-init */ - *dd->ipath_statusp &= ~IPATH_STATUS_CHIP_PRESENT; - if (dd->ipath_kregbase) { - /* - * if we haven't already cleaned up before these are - * to ensure any register reads/writes "fail" until - * re-init - */ - dd->ipath_kregbase = NULL; - dd->ipath_uregbase = 0; - dd->ipath_sregbase = 0; - dd->ipath_cregbase = 0; - dd->ipath_kregsize = 0; - } - ipath_disable_wc(dd); - } - - if (dd->ipath_spectriggerhit) - dev_info(&dd->pcidev->dev, "%lu special trigger hits\n", - dd->ipath_spectriggerhit); - - if (dd->ipath_pioavailregs_dma) { - dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE, - (void *) dd->ipath_pioavailregs_dma, - dd->ipath_pioavailregs_phys); - dd->ipath_pioavailregs_dma = NULL; - } - if (dd->ipath_dummy_hdrq) { - dma_free_coherent(&dd->pcidev->dev, - dd->ipath_pd[0]->port_rcvhdrq_size, - dd->ipath_dummy_hdrq, dd->ipath_dummy_hdrq_phys); - dd->ipath_dummy_hdrq = NULL; - } - - if (dd->ipath_pageshadow) { - struct page **tmpp = dd->ipath_pageshadow; - dma_addr_t *tmpd = dd->ipath_physshadow; - int i, cnt = 0; - - ipath_cdbg(VERBOSE, "Unlocking any expTID pages still " - "locked\n"); - for (port = 0; port < dd->ipath_cfgports; port++) { - int port_tidbase = port * dd->ipath_rcvtidcnt; - int maxtid = port_tidbase + dd->ipath_rcvtidcnt; - for (i = port_tidbase; i < maxtid; i++) { - if (!tmpp[i]) - continue; - pci_unmap_page(dd->pcidev, tmpd[i], - PAGE_SIZE, PCI_DMA_FROMDEVICE); - ipath_release_user_pages(&tmpp[i], 1); - tmpp[i] = NULL; - cnt++; - } - } - if (cnt) { - ipath_stats.sps_pageunlocks += cnt; - ipath_cdbg(VERBOSE, "There were still %u expTID " - "entries locked\n", cnt); - } - if (ipath_stats.sps_pagelocks || - ipath_stats.sps_pageunlocks) - ipath_cdbg(VERBOSE, "%llu pages locked, %llu " - "unlocked via ipath_m{un}lock\n", - (unsigned long long) - ipath_stats.sps_pagelocks, - (unsigned long long) - ipath_stats.sps_pageunlocks); - - ipath_cdbg(VERBOSE, "Free shadow page tid array at %p\n", - dd->ipath_pageshadow); - tmpp = dd->ipath_pageshadow; - dd->ipath_pageshadow = NULL; - vfree(tmpp); - - dd->ipath_egrtidbase = NULL; - } - - /* - * free any resources still in use (usually just kernel ports) - * at unload; we do for portcnt, because that's what we allocate. - * We acquire lock to be really paranoid that ipath_pd isn't being - * accessed from some interrupt-related code (that should not happen, - * but best to be sure). - */ - spin_lock_irqsave(&dd->ipath_uctxt_lock, flags); - tmp = dd->ipath_pd; - dd->ipath_pd = NULL; - spin_unlock_irqrestore(&dd->ipath_uctxt_lock, flags); - for (port = 0; port < dd->ipath_portcnt; port++) { - struct ipath_portdata *pd = tmp[port]; - tmp[port] = NULL; /* debugging paranoia */ - ipath_free_pddata(dd, pd); - } - kfree(tmp); -} - -static void ipath_remove_one(struct pci_dev *pdev) -{ - struct ipath_devdata *dd = pci_get_drvdata(pdev); - - ipath_cdbg(VERBOSE, "removing, pdev=%p, dd=%p\n", pdev, dd); - - /* - * disable the IB link early, to be sure no new packets arrive, which - * complicates the shutdown process - */ - ipath_shutdown_device(dd); - - flush_workqueue(ib_wq); - - if (dd->verbs_dev) - ipath_unregister_ib_device(dd->verbs_dev); - - ipath_diag_remove(dd); - ipath_user_remove(dd); - ipathfs_remove_device(dd); - ipath_device_remove_group(&pdev->dev, dd); - - ipath_cdbg(VERBOSE, "Releasing pci memory regions, dd %p, " - "unit %u\n", dd, (u32) dd->ipath_unit); - - cleanup_device(dd); - - /* - * turn off rcv, send, and interrupts for all ports, all drivers - * should also hard reset the chip here? - * free up port 0 (kernel) rcvhdr, egr bufs, and eventually tid bufs - * for all versions of the driver, if they were allocated - */ - if (dd->ipath_irq) { - ipath_cdbg(VERBOSE, "unit %u free irq %d\n", - dd->ipath_unit, dd->ipath_irq); - dd->ipath_f_free_irq(dd); - } else - ipath_dbg("irq is 0, not doing free_irq " - "for unit %u\n", dd->ipath_unit); - /* - * we check for NULL here, because it's outside - * the kregbase check, and we need to call it - * after the free_irq. Thus it's possible that - * the function pointers were never initialized. - */ - if (dd->ipath_f_cleanup) - /* clean up chip-specific stuff */ - dd->ipath_f_cleanup(dd); - - ipath_cdbg(VERBOSE, "Unmapping kregbase %p\n", dd->ipath_kregbase); - iounmap((volatile void __iomem *) dd->ipath_kregbase); - pci_release_regions(pdev); - ipath_cdbg(VERBOSE, "calling pci_disable_device\n"); - pci_disable_device(pdev); - - ipath_free_devdata(pdev, dd); -} - -/* general driver use */ -DEFINE_MUTEX(ipath_mutex); - -static DEFINE_SPINLOCK(ipath_pioavail_lock); - -/** - * ipath_disarm_piobufs - cancel a range of PIO buffers - * @dd: the infinipath device - * @first: the first PIO buffer to cancel - * @cnt: the number of PIO buffers to cancel - * - * cancel a range of PIO buffers, used when they might be armed, but - * not triggered. Used at init to ensure buffer state, and also user - * process close, in case it died while writing to a PIO buffer - * Also after errors. - */ -void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first, - unsigned cnt) -{ - unsigned i, last = first + cnt; - unsigned long flags; - - ipath_cdbg(PKT, "disarm %u PIObufs first=%u\n", cnt, first); - for (i = first; i < last; i++) { - spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); - /* - * The disarm-related bits are write-only, so it - * is ok to OR them in with our copy of sendctrl - * while we hold the lock. - */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, - dd->ipath_sendctrl | INFINIPATH_S_DISARM | - (i << INFINIPATH_S_DISARMPIOBUF_SHIFT)); - /* can't disarm bufs back-to-back per iba7220 spec */ - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); - } - /* on some older chips, update may not happen after cancel */ - ipath_force_pio_avail_update(dd); -} - -/** - * ipath_wait_linkstate - wait for an IB link state change to occur - * @dd: the infinipath device - * @state: the state to wait for - * @msecs: the number of milliseconds to wait - * - * wait up to msecs milliseconds for IB link state change to occur for - * now, take the easy polling route. Currently used only by - * ipath_set_linkstate. Returns 0 if state reached, otherwise - * -ETIMEDOUT state can have multiple states set, for any of several - * transitions. - */ -int ipath_wait_linkstate(struct ipath_devdata *dd, u32 state, int msecs) -{ - dd->ipath_state_wanted = state; - wait_event_interruptible_timeout(ipath_state_wait, - (dd->ipath_flags & state), - msecs_to_jiffies(msecs)); - dd->ipath_state_wanted = 0; - - if (!(dd->ipath_flags & state)) { - u64 val; - ipath_cdbg(VERBOSE, "Didn't reach linkstate %s within %u" - " ms\n", - /* test INIT ahead of DOWN, both can be set */ - (state & IPATH_LINKINIT) ? "INIT" : - ((state & IPATH_LINKDOWN) ? "DOWN" : - ((state & IPATH_LINKARMED) ? "ARM" : "ACTIVE")), - msecs); - val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus); - ipath_cdbg(VERBOSE, "ibcc=%llx ibcstatus=%llx (%s)\n", - (unsigned long long) ipath_read_kreg64( - dd, dd->ipath_kregs->kr_ibcctrl), - (unsigned long long) val, - ipath_ibcstatus_str[val & dd->ibcs_lts_mask]); - } - return (dd->ipath_flags & state) ? 0 : -ETIMEDOUT; -} - -static void decode_sdma_errs(struct ipath_devdata *dd, ipath_err_t err, - char *buf, size_t blen) -{ - static const struct { - ipath_err_t err; - const char *msg; - } errs[] = { - { INFINIPATH_E_SDMAGENMISMATCH, "SDmaGenMismatch" }, - { INFINIPATH_E_SDMAOUTOFBOUND, "SDmaOutOfBound" }, - { INFINIPATH_E_SDMATAILOUTOFBOUND, "SDmaTailOutOfBound" }, - { INFINIPATH_E_SDMABASE, "SDmaBase" }, - { INFINIPATH_E_SDMA1STDESC, "SDma1stDesc" }, - { INFINIPATH_E_SDMARPYTAG, "SDmaRpyTag" }, - { INFINIPATH_E_SDMADWEN, "SDmaDwEn" }, - { INFINIPATH_E_SDMAMISSINGDW, "SDmaMissingDw" }, - { INFINIPATH_E_SDMAUNEXPDATA, "SDmaUnexpData" }, - { INFINIPATH_E_SDMADESCADDRMISALIGN, "SDmaDescAddrMisalign" }, - { INFINIPATH_E_SENDBUFMISUSE, "SendBufMisuse" }, - { INFINIPATH_E_SDMADISABLED, "SDmaDisabled" }, - }; - int i; - int expected; - size_t bidx = 0; - - for (i = 0; i < ARRAY_SIZE(errs); i++) { - expected = (errs[i].err != INFINIPATH_E_SDMADISABLED) ? 0 : - test_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status); - if ((err & errs[i].err) && !expected) - bidx += snprintf(buf + bidx, blen - bidx, - "%s ", errs[i].msg); - } -} - -/* - * Decode the error status into strings, deciding whether to always - * print * it or not depending on "normal packet errors" vs everything - * else. Return 1 if "real" errors, otherwise 0 if only packet - * errors, so caller can decide what to print with the string. - */ -int ipath_decode_err(struct ipath_devdata *dd, char *buf, size_t blen, - ipath_err_t err) -{ - int iserr = 1; - *buf = '\0'; - if (err & INFINIPATH_E_PKTERRS) { - if (!(err & ~INFINIPATH_E_PKTERRS)) - iserr = 0; // if only packet errors. - if (ipath_debug & __IPATH_ERRPKTDBG) { - if (err & INFINIPATH_E_REBP) - strlcat(buf, "EBP ", blen); - if (err & INFINIPATH_E_RVCRC) - strlcat(buf, "VCRC ", blen); - if (err & INFINIPATH_E_RICRC) { - strlcat(buf, "CRC ", blen); - // clear for check below, so only once - err &= INFINIPATH_E_RICRC; - } - if (err & INFINIPATH_E_RSHORTPKTLEN) - strlcat(buf, "rshortpktlen ", blen); - if (err & INFINIPATH_E_SDROPPEDDATAPKT) - strlcat(buf, "sdroppeddatapkt ", blen); - if (err & INFINIPATH_E_SPKTLEN) - strlcat(buf, "spktlen ", blen); - } - if ((err & INFINIPATH_E_RICRC) && - !(err&(INFINIPATH_E_RVCRC|INFINIPATH_E_REBP))) - strlcat(buf, "CRC ", blen); - if (!iserr) - goto done; - } - if (err & INFINIPATH_E_RHDRLEN) - strlcat(buf, "rhdrlen ", blen); - if (err & INFINIPATH_E_RBADTID) - strlcat(buf, "rbadtid ", blen); - if (err & INFINIPATH_E_RBADVERSION) - strlcat(buf, "rbadversion ", blen); - if (err & INFINIPATH_E_RHDR) - strlcat(buf, "rhdr ", blen); - if (err & INFINIPATH_E_SENDSPECIALTRIGGER) - strlcat(buf, "sendspecialtrigger ", blen); - if (err & INFINIPATH_E_RLONGPKTLEN) - strlcat(buf, "rlongpktlen ", blen); - if (err & INFINIPATH_E_RMAXPKTLEN) - strlcat(buf, "rmaxpktlen ", blen); - if (err & INFINIPATH_E_RMINPKTLEN) - strlcat(buf, "rminpktlen ", blen); - if (err & INFINIPATH_E_SMINPKTLEN) - strlcat(buf, "sminpktlen ", blen); - if (err & INFINIPATH_E_RFORMATERR) - strlcat(buf, "rformaterr ", blen); - if (err & INFINIPATH_E_RUNSUPVL) - strlcat(buf, "runsupvl ", blen); - if (err & INFINIPATH_E_RUNEXPCHAR) - strlcat(buf, "runexpchar ", blen); - if (err & INFINIPATH_E_RIBFLOW) - strlcat(buf, "ribflow ", blen); - if (err & INFINIPATH_E_SUNDERRUN) - strlcat(buf, "sunderrun ", blen); - if (err & INFINIPATH_E_SPIOARMLAUNCH) - strlcat(buf, "spioarmlaunch ", blen); - if (err & INFINIPATH_E_SUNEXPERRPKTNUM) - strlcat(buf, "sunexperrpktnum ", blen); - if (err & INFINIPATH_E_SDROPPEDSMPPKT) - strlcat(buf, "sdroppedsmppkt ", blen); - if (err & INFINIPATH_E_SMAXPKTLEN) - strlcat(buf, "smaxpktlen ", blen); - if (err & INFINIPATH_E_SUNSUPVL) - strlcat(buf, "sunsupVL ", blen); - if (err & INFINIPATH_E_INVALIDADDR) - strlcat(buf, "invalidaddr ", blen); - if (err & INFINIPATH_E_RRCVEGRFULL) - strlcat(buf, "rcvegrfull ", blen); - if (err & INFINIPATH_E_RRCVHDRFULL) - strlcat(buf, "rcvhdrfull ", blen); - if (err & INFINIPATH_E_IBSTATUSCHANGED) - strlcat(buf, "ibcstatuschg ", blen); - if (err & INFINIPATH_E_RIBLOSTLINK) - strlcat(buf, "riblostlink ", blen); - if (err & INFINIPATH_E_HARDWARE) - strlcat(buf, "hardware ", blen); - if (err & INFINIPATH_E_RESET) - strlcat(buf, "reset ", blen); - if (err & INFINIPATH_E_SDMAERRS) - decode_sdma_errs(dd, err, buf, blen); - if (err & INFINIPATH_E_INVALIDEEPCMD) - strlcat(buf, "invalideepromcmd ", blen); -done: - return iserr; -} - -/** - * get_rhf_errstring - decode RHF errors - * @err: the err number - * @msg: the output buffer - * @len: the length of the output buffer - * - * only used one place now, may want more later - */ -static void get_rhf_errstring(u32 err, char *msg, size_t len) -{ - /* if no errors, and so don't need to check what's first */ - *msg = '\0'; - - if (err & INFINIPATH_RHF_H_ICRCERR) - strlcat(msg, "icrcerr ", len); - if (err & INFINIPATH_RHF_H_VCRCERR) - strlcat(msg, "vcrcerr ", len); - if (err & INFINIPATH_RHF_H_PARITYERR) - strlcat(msg, "parityerr ", len); - if (err & INFINIPATH_RHF_H_LENERR) - strlcat(msg, "lenerr ", len); - if (err & INFINIPATH_RHF_H_MTUERR) - strlcat(msg, "mtuerr ", len); - if (err & INFINIPATH_RHF_H_IHDRERR) - /* infinipath hdr checksum error */ - strlcat(msg, "ipathhdrerr ", len); - if (err & INFINIPATH_RHF_H_TIDERR) - strlcat(msg, "tiderr ", len); - if (err & INFINIPATH_RHF_H_MKERR) - /* bad port, offset, etc. */ - strlcat(msg, "invalid ipathhdr ", len); - if (err & INFINIPATH_RHF_H_IBERR) - strlcat(msg, "iberr ", len); - if (err & INFINIPATH_RHF_L_SWA) - strlcat(msg, "swA ", len); - if (err & INFINIPATH_RHF_L_SWB) - strlcat(msg, "swB ", len); -} - -/** - * ipath_get_egrbuf - get an eager buffer - * @dd: the infinipath device - * @bufnum: the eager buffer to get - * - * must only be called if ipath_pd[port] is known to be allocated - */ -static inline void *ipath_get_egrbuf(struct ipath_devdata *dd, u32 bufnum) -{ - return dd->ipath_port0_skbinfo ? - (void *) dd->ipath_port0_skbinfo[bufnum].skb->data : NULL; -} - -/** - * ipath_alloc_skb - allocate an skb and buffer with possible constraints - * @dd: the infinipath device - * @gfp_mask: the sk_buff SFP mask - */ -struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd, - gfp_t gfp_mask) -{ - struct sk_buff *skb; - u32 len; - - /* - * Only fully supported way to handle this is to allocate lots - * extra, align as needed, and then do skb_reserve(). That wastes - * a lot of memory... I'll have to hack this into infinipath_copy - * also. - */ - - /* - * We need 2 extra bytes for ipath_ether data sent in the - * key header. In order to keep everything dword aligned, - * we'll reserve 4 bytes. - */ - len = dd->ipath_ibmaxlen + 4; - - if (dd->ipath_flags & IPATH_4BYTE_TID) { - /* We need a 2KB multiple alignment, and there is no way - * to do it except to allocate extra and then skb_reserve - * enough to bring it up to the right alignment. - */ - len += 2047; - } - - skb = __dev_alloc_skb(len, gfp_mask); - if (!skb) { - ipath_dev_err(dd, "Failed to allocate skbuff, length %u\n", - len); - goto bail; - } - - skb_reserve(skb, 4); - - if (dd->ipath_flags & IPATH_4BYTE_TID) { - u32 una = (unsigned long)skb->data & 2047; - if (una) - skb_reserve(skb, 2048 - una); - } - -bail: - return skb; -} - -static void ipath_rcv_hdrerr(struct ipath_devdata *dd, - u32 eflags, - u32 l, - u32 etail, - __le32 *rhf_addr, - struct ipath_message_header *hdr) -{ - char emsg[128]; - - get_rhf_errstring(eflags, emsg, sizeof emsg); - ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u " - "tlen=%x opcode=%x egridx=%x: %s\n", - eflags, l, - ipath_hdrget_rcv_type(rhf_addr), - ipath_hdrget_length_in_bytes(rhf_addr), - be32_to_cpu(hdr->bth[0]) >> 24, - etail, emsg); - - /* Count local link integrity errors. */ - if (eflags & (INFINIPATH_RHF_H_ICRCERR | INFINIPATH_RHF_H_VCRCERR)) { - u8 n = (dd->ipath_ibcctrl >> - INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) & - INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK; - - if (++dd->ipath_lli_counter > n) { - dd->ipath_lli_counter = 0; - dd->ipath_lli_errors++; - } - } -} - -/* - * ipath_kreceive - receive a packet - * @pd: the infinipath port - * - * called from interrupt handler for errors or receive interrupt - */ -void ipath_kreceive(struct ipath_portdata *pd) -{ - struct ipath_devdata *dd = pd->port_dd; - __le32 *rhf_addr; - void *ebuf; - const u32 rsize = dd->ipath_rcvhdrentsize; /* words */ - const u32 maxcnt = dd->ipath_rcvhdrcnt * rsize; /* words */ - u32 etail = -1, l, hdrqtail; - struct ipath_message_header *hdr; - u32 eflags, i, etype, tlen, pkttot = 0, updegr = 0, reloop = 0; - static u64 totcalls; /* stats, may eventually remove */ - int last; - - l = pd->port_head; - rhf_addr = (__le32 *) pd->port_rcvhdrq + l + dd->ipath_rhf_offset; - if (dd->ipath_flags & IPATH_NODMA_RTAIL) { - u32 seq = ipath_hdrget_seq(rhf_addr); - - if (seq != pd->port_seq_cnt) - goto bail; - hdrqtail = 0; - } else { - hdrqtail = ipath_get_rcvhdrtail(pd); - if (l == hdrqtail) - goto bail; - smp_rmb(); - } - -reloop: - for (last = 0, i = 1; !last; i += !last) { - hdr = dd->ipath_f_get_msgheader(dd, rhf_addr); - eflags = ipath_hdrget_err_flags(rhf_addr); - etype = ipath_hdrget_rcv_type(rhf_addr); - /* total length */ - tlen = ipath_hdrget_length_in_bytes(rhf_addr); - ebuf = NULL; - if ((dd->ipath_flags & IPATH_NODMA_RTAIL) ? - ipath_hdrget_use_egr_buf(rhf_addr) : - (etype != RCVHQ_RCV_TYPE_EXPECTED)) { - /* - * It turns out that the chip uses an eager buffer - * for all non-expected packets, whether it "needs" - * one or not. So always get the index, but don't - * set ebuf (so we try to copy data) unless the - * length requires it. - */ - etail = ipath_hdrget_index(rhf_addr); - updegr = 1; - if (tlen > sizeof(*hdr) || - etype == RCVHQ_RCV_TYPE_NON_KD) - ebuf = ipath_get_egrbuf(dd, etail); - } - - /* - * both tiderr and ipathhdrerr are set for all plain IB - * packets; only ipathhdrerr should be set. - */ - - if (etype != RCVHQ_RCV_TYPE_NON_KD && - etype != RCVHQ_RCV_TYPE_ERROR && - ipath_hdrget_ipath_ver(hdr->iph.ver_port_tid_offset) != - IPS_PROTO_VERSION) - ipath_cdbg(PKT, "Bad InfiniPath protocol version " - "%x\n", etype); - - if (unlikely(eflags)) - ipath_rcv_hdrerr(dd, eflags, l, etail, rhf_addr, hdr); - else if (etype == RCVHQ_RCV_TYPE_NON_KD) { - ipath_ib_rcv(dd->verbs_dev, (u32 *)hdr, ebuf, tlen); - if (dd->ipath_lli_counter) - dd->ipath_lli_counter--; - } else if (etype == RCVHQ_RCV_TYPE_EAGER) { - u8 opcode = be32_to_cpu(hdr->bth[0]) >> 24; - u32 qp = be32_to_cpu(hdr->bth[1]) & 0xffffff; - ipath_cdbg(PKT, "typ %x, opcode %x (eager, " - "qp=%x), len %x; ignored\n", - etype, opcode, qp, tlen); - } else if (etype == RCVHQ_RCV_TYPE_EXPECTED) { - ipath_dbg("Bug: Expected TID, opcode %x; ignored\n", - be32_to_cpu(hdr->bth[0]) >> 24); - } else { - /* - * error packet, type of error unknown. - * Probably type 3, but we don't know, so don't - * even try to print the opcode, etc. - * Usually caused by a "bad packet", that has no - * BTH, when the LRH says it should. - */ - ipath_cdbg(ERRPKT, "Error Pkt, but no eflags! egrbuf" - " %x, len %x hdrq+%x rhf: %Lx\n", - etail, tlen, l, (unsigned long long) - le64_to_cpu(*(__le64 *) rhf_addr)); - if (ipath_debug & __IPATH_ERRPKTDBG) { - u32 j, *d, dw = rsize-2; - if (rsize > (tlen>>2)) - dw = tlen>>2; - d = (u32 *)hdr; - printk(KERN_DEBUG "EPkt rcvhdr(%x dw):\n", - dw); - for (j = 0; j < dw; j++) - printk(KERN_DEBUG "%8x%s", d[j], - (j%8) == 7 ? "\n" : " "); - printk(KERN_DEBUG ".\n"); - } - } - l += rsize; - if (l >= maxcnt) - l = 0; - rhf_addr = (__le32 *) pd->port_rcvhdrq + - l + dd->ipath_rhf_offset; - if (dd->ipath_flags & IPATH_NODMA_RTAIL) { - u32 seq = ipath_hdrget_seq(rhf_addr); - - if (++pd->port_seq_cnt > 13) - pd->port_seq_cnt = 1; - if (seq != pd->port_seq_cnt) - last = 1; - } else if (l == hdrqtail) { - last = 1; - } - /* - * update head regs on last packet, and every 16 packets. - * Reduce bus traffic, while still trying to prevent - * rcvhdrq overflows, for when the queue is nearly full - */ - if (last || !(i & 0xf)) { - u64 lval = l; - - /* request IBA6120 and 7220 interrupt only on last */ - if (last) - lval |= dd->ipath_rhdrhead_intr_off; - ipath_write_ureg(dd, ur_rcvhdrhead, lval, - pd->port_port); - if (updegr) { - ipath_write_ureg(dd, ur_rcvegrindexhead, - etail, pd->port_port); - updegr = 0; - } - } - } - - if (!dd->ipath_rhdrhead_intr_off && !reloop && - !(dd->ipath_flags & IPATH_NODMA_RTAIL)) { - /* IBA6110 workaround; we can have a race clearing chip - * interrupt with another interrupt about to be delivered, - * and can clear it before it is delivered on the GPIO - * workaround. By doing the extra check here for the - * in-memory tail register updating while we were doing - * earlier packets, we "almost" guarantee we have covered - * that case. - */ - u32 hqtail = ipath_get_rcvhdrtail(pd); - if (hqtail != hdrqtail) { - hdrqtail = hqtail; - reloop = 1; /* loop 1 extra time at most */ - goto reloop; - } - } - - pkttot += i; - - pd->port_head = l; - - if (pkttot > ipath_stats.sps_maxpkts_call) - ipath_stats.sps_maxpkts_call = pkttot; - ipath_stats.sps_port0pkts += pkttot; - ipath_stats.sps_avgpkts_call = - ipath_stats.sps_port0pkts / ++totcalls; - -bail:; -} - -/** - * ipath_update_pio_bufs - update shadow copy of the PIO availability map - * @dd: the infinipath device - * - * called whenever our local copy indicates we have run out of send buffers - * NOTE: This can be called from interrupt context by some code - * and from non-interrupt context by ipath_getpiobuf(). - */ - -static void ipath_update_pio_bufs(struct ipath_devdata *dd) -{ - unsigned long flags; - int i; - const unsigned piobregs = (unsigned)dd->ipath_pioavregs; - - /* If the generation (check) bits have changed, then we update the - * busy bit for the corresponding PIO buffer. This algorithm will - * modify positions to the value they already have in some cases - * (i.e., no change), but it's faster than changing only the bits - * that have changed. - * - * We would like to do this atomicly, to avoid spinlocks in the - * critical send path, but that's not really possible, given the - * type of changes, and that this routine could be called on - * multiple cpu's simultaneously, so we lock in this routine only, - * to avoid conflicting updates; all we change is the shadow, and - * it's a single 64 bit memory location, so by definition the update - * is atomic in terms of what other cpu's can see in testing the - * bits. The spin_lock overhead isn't too bad, since it only - * happens when all buffers are in use, so only cpu overhead, not - * latency or bandwidth is affected. - */ - if (!dd->ipath_pioavailregs_dma) { - ipath_dbg("Update shadow pioavail, but regs_dma NULL!\n"); - return; - } - if (ipath_debug & __IPATH_VERBDBG) { - /* only if packet debug and verbose */ - volatile __le64 *dma = dd->ipath_pioavailregs_dma; - unsigned long *shadow = dd->ipath_pioavailshadow; - - ipath_cdbg(PKT, "Refill avail, dma0=%llx shad0=%lx, " - "d1=%llx s1=%lx, d2=%llx s2=%lx, d3=%llx " - "s3=%lx\n", - (unsigned long long) le64_to_cpu(dma[0]), - shadow[0], - (unsigned long long) le64_to_cpu(dma[1]), - shadow[1], - (unsigned long long) le64_to_cpu(dma[2]), - shadow[2], - (unsigned long long) le64_to_cpu(dma[3]), - shadow[3]); - if (piobregs > 4) - ipath_cdbg( - PKT, "2nd group, dma4=%llx shad4=%lx, " - "d5=%llx s5=%lx, d6=%llx s6=%lx, " - "d7=%llx s7=%lx\n", - (unsigned long long) le64_to_cpu(dma[4]), - shadow[4], - (unsigned long long) le64_to_cpu(dma[5]), - shadow[5], - (unsigned long long) le64_to_cpu(dma[6]), - shadow[6], - (unsigned long long) le64_to_cpu(dma[7]), - shadow[7]); - } - spin_lock_irqsave(&ipath_pioavail_lock, flags); - for (i = 0; i < piobregs; i++) { - u64 pchbusy, pchg, piov, pnew; - /* - * Chip Errata: bug 6641; even and odd qwords>3 are swapped - */ - if (i > 3 && (dd->ipath_flags & IPATH_SWAP_PIOBUFS)) - piov = le64_to_cpu(dd->ipath_pioavailregs_dma[i ^ 1]); - else - piov = le64_to_cpu(dd->ipath_pioavailregs_dma[i]); - pchg = dd->ipath_pioavailkernel[i] & - ~(dd->ipath_pioavailshadow[i] ^ piov); - pchbusy = pchg << INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT; - if (pchg && (pchbusy & dd->ipath_pioavailshadow[i])) { - pnew = dd->ipath_pioavailshadow[i] & ~pchbusy; - pnew |= piov & pchbusy; - dd->ipath_pioavailshadow[i] = pnew; - } - } - spin_unlock_irqrestore(&ipath_pioavail_lock, flags); -} - -/* - * used to force update of pioavailshadow if we can't get a pio buffer. - * Needed primarily due to exitting freeze mode after recovering - * from errors. Done lazily, because it's safer (known to not - * be writing pio buffers). - */ -static void ipath_reset_availshadow(struct ipath_devdata *dd) -{ - int i, im; - unsigned long flags; - - spin_lock_irqsave(&ipath_pioavail_lock, flags); - for (i = 0; i < dd->ipath_pioavregs; i++) { - u64 val, oldval; - /* deal with 6110 chip bug on high register #s */ - im = (i > 3 && (dd->ipath_flags & IPATH_SWAP_PIOBUFS)) ? - i ^ 1 : i; - val = le64_to_cpu(dd->ipath_pioavailregs_dma[im]); - /* - * busy out the buffers not in the kernel avail list, - * without changing the generation bits. - */ - oldval = dd->ipath_pioavailshadow[i]; - dd->ipath_pioavailshadow[i] = val | - ((~dd->ipath_pioavailkernel[i] << - INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT) & - 0xaaaaaaaaaaaaaaaaULL); /* All BUSY bits in qword */ - if (oldval != dd->ipath_pioavailshadow[i]) - ipath_dbg("shadow[%d] was %Lx, now %lx\n", - i, (unsigned long long) oldval, - dd->ipath_pioavailshadow[i]); - } - spin_unlock_irqrestore(&ipath_pioavail_lock, flags); -} - -/** - * ipath_setrcvhdrsize - set the receive header size - * @dd: the infinipath device - * @rhdrsize: the receive header size - * - * called from user init code, and also layered driver init - */ -int ipath_setrcvhdrsize(struct ipath_devdata *dd, unsigned rhdrsize) -{ - int ret = 0; - - if (dd->ipath_flags & IPATH_RCVHDRSZ_SET) { - if (dd->ipath_rcvhdrsize != rhdrsize) { - dev_info(&dd->pcidev->dev, - "Error: can't set protocol header " - "size %u, already %u\n", - rhdrsize, dd->ipath_rcvhdrsize); - ret = -EAGAIN; - } else - ipath_cdbg(VERBOSE, "Reuse same protocol header " - "size %u\n", dd->ipath_rcvhdrsize); - } else if (rhdrsize > (dd->ipath_rcvhdrentsize - - (sizeof(u64) / sizeof(u32)))) { - ipath_dbg("Error: can't set protocol header size %u " - "(> max %u)\n", rhdrsize, - dd->ipath_rcvhdrentsize - - (u32) (sizeof(u64) / sizeof(u32))); - ret = -EOVERFLOW; - } else { - dd->ipath_flags |= IPATH_RCVHDRSZ_SET; - dd->ipath_rcvhdrsize = rhdrsize; - ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrsize, - dd->ipath_rcvhdrsize); - ipath_cdbg(VERBOSE, "Set protocol header size to %u\n", - dd->ipath_rcvhdrsize); - } - return ret; -} - -/* - * debugging code and stats updates if no pio buffers available. - */ -static noinline void no_pio_bufs(struct ipath_devdata *dd) -{ - unsigned long *shadow = dd->ipath_pioavailshadow; - __le64 *dma = (__le64 *)dd->ipath_pioavailregs_dma; - - dd->ipath_upd_pio_shadow = 1; - - /* - * not atomic, but if we lose a stat count in a while, that's OK - */ - ipath_stats.sps_nopiobufs++; - if (!(++dd->ipath_consec_nopiobuf % 100000)) { - ipath_force_pio_avail_update(dd); /* at start */ - ipath_dbg("%u tries no piobufavail ts%lx; dmacopy: " - "%llx %llx %llx %llx\n" - "ipath shadow: %lx %lx %lx %lx\n", - dd->ipath_consec_nopiobuf, - (unsigned long)get_cycles(), - (unsigned long long) le64_to_cpu(dma[0]), - (unsigned long long) le64_to_cpu(dma[1]), - (unsigned long long) le64_to_cpu(dma[2]), - (unsigned long long) le64_to_cpu(dma[3]), - shadow[0], shadow[1], shadow[2], shadow[3]); - /* - * 4 buffers per byte, 4 registers above, cover rest - * below - */ - if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) > - (sizeof(shadow[0]) * 4 * 4)) - ipath_dbg("2nd group: dmacopy: " - "%llx %llx %llx %llx\n" - "ipath shadow: %lx %lx %lx %lx\n", - (unsigned long long)le64_to_cpu(dma[4]), - (unsigned long long)le64_to_cpu(dma[5]), - (unsigned long long)le64_to_cpu(dma[6]), - (unsigned long long)le64_to_cpu(dma[7]), - shadow[4], shadow[5], shadow[6], shadow[7]); - - /* at end, so update likely happened */ - ipath_reset_availshadow(dd); - } -} - -/* - * common code for normal driver pio buffer allocation, and reserved - * allocation. - * - * do appropriate marking as busy, etc. - * returns buffer number if one found (>=0), negative number is error. - */ -static u32 __iomem *ipath_getpiobuf_range(struct ipath_devdata *dd, - u32 *pbufnum, u32 first, u32 last, u32 firsti) -{ - int i, j, updated = 0; - unsigned piobcnt; - unsigned long flags; - unsigned long *shadow = dd->ipath_pioavailshadow; - u32 __iomem *buf; - - piobcnt = last - first; - if (dd->ipath_upd_pio_shadow) { - /* - * Minor optimization. If we had no buffers on last call, - * start out by doing the update; continue and do scan even - * if no buffers were updated, to be paranoid - */ - ipath_update_pio_bufs(dd); - updated++; - i = first; - } else - i = firsti; -rescan: - /* - * while test_and_set_bit() is atomic, we do that and then the - * change_bit(), and the pair is not. See if this is the cause - * of the remaining armlaunch errors. - */ - spin_lock_irqsave(&ipath_pioavail_lock, flags); - for (j = 0; j < piobcnt; j++, i++) { - if (i >= last) - i = first; - if (__test_and_set_bit((2 * i) + 1, shadow)) - continue; - /* flip generation bit */ - __change_bit(2 * i, shadow); - break; - } - spin_unlock_irqrestore(&ipath_pioavail_lock, flags); - - if (j == piobcnt) { - if (!updated) { - /* - * first time through; shadow exhausted, but may be - * buffers available, try an update and then rescan. - */ - ipath_update_pio_bufs(dd); - updated++; - i = first; - goto rescan; - } else if (updated == 1 && piobcnt <= - ((dd->ipath_sendctrl - >> INFINIPATH_S_UPDTHRESH_SHIFT) & - INFINIPATH_S_UPDTHRESH_MASK)) { - /* - * for chips supporting and using the update - * threshold we need to force an update of the - * in-memory copy if the count is less than the - * thershold, then check one more time. - */ - ipath_force_pio_avail_update(dd); - ipath_update_pio_bufs(dd); - updated++; - i = first; - goto rescan; - } - - no_pio_bufs(dd); - buf = NULL; - } else { - if (i < dd->ipath_piobcnt2k) - buf = (u32 __iomem *) (dd->ipath_pio2kbase + - i * dd->ipath_palign); - else - buf = (u32 __iomem *) - (dd->ipath_pio4kbase + - (i - dd->ipath_piobcnt2k) * dd->ipath_4kalign); - if (pbufnum) - *pbufnum = i; - } - - return buf; -} - -/** - * ipath_getpiobuf - find an available pio buffer - * @dd: the infinipath device - * @plen: the size of the PIO buffer needed in 32-bit words - * @pbufnum: the buffer number is placed here - */ -u32 __iomem *ipath_getpiobuf(struct ipath_devdata *dd, u32 plen, u32 *pbufnum) -{ - u32 __iomem *buf; - u32 pnum, nbufs; - u32 first, lasti; - - if (plen + 1 >= IPATH_SMALLBUF_DWORDS) { - first = dd->ipath_piobcnt2k; - lasti = dd->ipath_lastpioindexl; - } else { - first = 0; - lasti = dd->ipath_lastpioindex; - } - nbufs = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k; - buf = ipath_getpiobuf_range(dd, &pnum, first, nbufs, lasti); - - if (buf) { - /* - * Set next starting place. It's just an optimization, - * it doesn't matter who wins on this, so no locking - */ - if (plen + 1 >= IPATH_SMALLBUF_DWORDS) - dd->ipath_lastpioindexl = pnum + 1; - else - dd->ipath_lastpioindex = pnum + 1; - if (dd->ipath_upd_pio_shadow) - dd->ipath_upd_pio_shadow = 0; - if (dd->ipath_consec_nopiobuf) - dd->ipath_consec_nopiobuf = 0; - ipath_cdbg(VERBOSE, "Return piobuf%u %uk @ %p\n", - pnum, (pnum < dd->ipath_piobcnt2k) ? 2 : 4, buf); - if (pbufnum) - *pbufnum = pnum; - - } - return buf; -} - -/** - * ipath_chg_pioavailkernel - change which send buffers are available for kernel - * @dd: the infinipath device - * @start: the starting send buffer number - * @len: the number of send buffers - * @avail: true if the buffers are available for kernel use, false otherwise - */ -void ipath_chg_pioavailkernel(struct ipath_devdata *dd, unsigned start, - unsigned len, int avail) -{ - unsigned long flags; - unsigned end, cnt = 0; - - /* There are two bits per send buffer (busy and generation) */ - start *= 2; - end = start + len * 2; - - spin_lock_irqsave(&ipath_pioavail_lock, flags); - /* Set or clear the busy bit in the shadow. */ - while (start < end) { - if (avail) { - unsigned long dma; - int i, im; - /* - * the BUSY bit will never be set, because we disarm - * the user buffers before we hand them back to the - * kernel. We do have to make sure the generation - * bit is set correctly in shadow, since it could - * have changed many times while allocated to user. - * We can't use the bitmap functions on the full - * dma array because it is always little-endian, so - * we have to flip to host-order first. - * BITS_PER_LONG is slightly wrong, since it's - * always 64 bits per register in chip... - * We only work on 64 bit kernels, so that's OK. - */ - /* deal with 6110 chip bug on high register #s */ - i = start / BITS_PER_LONG; - im = (i > 3 && (dd->ipath_flags & IPATH_SWAP_PIOBUFS)) ? - i ^ 1 : i; - __clear_bit(INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT - + start, dd->ipath_pioavailshadow); - dma = (unsigned long) le64_to_cpu( - dd->ipath_pioavailregs_dma[im]); - if (test_bit((INFINIPATH_SENDPIOAVAIL_CHECK_SHIFT - + start) % BITS_PER_LONG, &dma)) - __set_bit(INFINIPATH_SENDPIOAVAIL_CHECK_SHIFT - + start, dd->ipath_pioavailshadow); - else - __clear_bit(INFINIPATH_SENDPIOAVAIL_CHECK_SHIFT - + start, dd->ipath_pioavailshadow); - __set_bit(start, dd->ipath_pioavailkernel); - } else { - __set_bit(start + INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT, - dd->ipath_pioavailshadow); - __clear_bit(start, dd->ipath_pioavailkernel); - } - start += 2; - } - - if (dd->ipath_pioupd_thresh) { - end = 2 * (dd->ipath_piobcnt2k + dd->ipath_piobcnt4k); - cnt = bitmap_weight(dd->ipath_pioavailkernel, end); - } - spin_unlock_irqrestore(&ipath_pioavail_lock, flags); - - /* - * When moving buffers from kernel to user, if number assigned to - * the user is less than the pio update threshold, and threshold - * is supported (cnt was computed > 0), drop the update threshold - * so we update at least once per allocated number of buffers. - * In any case, if the kernel buffers are less than the threshold, - * drop the threshold. We don't bother increasing it, having once - * decreased it, since it would typically just cycle back and forth. - * If we don't decrease below buffers in use, we can wait a long - * time for an update, until some other context uses PIO buffers. - */ - if (!avail && len < cnt) - cnt = len; - if (cnt < dd->ipath_pioupd_thresh) { - dd->ipath_pioupd_thresh = cnt; - ipath_dbg("Decreased pio update threshold to %u\n", - dd->ipath_pioupd_thresh); - spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); - dd->ipath_sendctrl &= ~(INFINIPATH_S_UPDTHRESH_MASK - << INFINIPATH_S_UPDTHRESH_SHIFT); - dd->ipath_sendctrl |= dd->ipath_pioupd_thresh - << INFINIPATH_S_UPDTHRESH_SHIFT; - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, - dd->ipath_sendctrl); - spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); - } -} - -/** - * ipath_create_rcvhdrq - create a receive header queue - * @dd: the infinipath device - * @pd: the port data - * - * this must be contiguous memory (from an i/o perspective), and must be - * DMA'able (which means for some systems, it will go through an IOMMU, - * or be forced into a low address range). - */ -int ipath_create_rcvhdrq(struct ipath_devdata *dd, - struct ipath_portdata *pd) -{ - int ret = 0; - - if (!pd->port_rcvhdrq) { - dma_addr_t phys_hdrqtail; - gfp_t gfp_flags = GFP_USER | __GFP_COMP; - int amt = ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize * - sizeof(u32), PAGE_SIZE); - - pd->port_rcvhdrq = dma_alloc_coherent( - &dd->pcidev->dev, amt, &pd->port_rcvhdrq_phys, - gfp_flags); - - if (!pd->port_rcvhdrq) { - ipath_dev_err(dd, "attempt to allocate %d bytes " - "for port %u rcvhdrq failed\n", - amt, pd->port_port); - ret = -ENOMEM; - goto bail; - } - - if (!(dd->ipath_flags & IPATH_NODMA_RTAIL)) { - pd->port_rcvhdrtail_kvaddr = dma_alloc_coherent( - &dd->pcidev->dev, PAGE_SIZE, &phys_hdrqtail, - GFP_KERNEL); - if (!pd->port_rcvhdrtail_kvaddr) { - ipath_dev_err(dd, "attempt to allocate 1 page " - "for port %u rcvhdrqtailaddr " - "failed\n", pd->port_port); - ret = -ENOMEM; - dma_free_coherent(&dd->pcidev->dev, amt, - pd->port_rcvhdrq, - pd->port_rcvhdrq_phys); - pd->port_rcvhdrq = NULL; - goto bail; - } - pd->port_rcvhdrqtailaddr_phys = phys_hdrqtail; - ipath_cdbg(VERBOSE, "port %d hdrtailaddr, %llx " - "physical\n", pd->port_port, - (unsigned long long) phys_hdrqtail); - } - - pd->port_rcvhdrq_size = amt; - - ipath_cdbg(VERBOSE, "%d pages at %p (phys %lx) size=%lu " - "for port %u rcvhdr Q\n", - amt >> PAGE_SHIFT, pd->port_rcvhdrq, - (unsigned long) pd->port_rcvhdrq_phys, - (unsigned long) pd->port_rcvhdrq_size, - pd->port_port); - } else { - ipath_cdbg(VERBOSE, "reuse port %d rcvhdrq @%p %llx phys; " - "hdrtailaddr@%p %llx physical\n", - pd->port_port, pd->port_rcvhdrq, - (unsigned long long) pd->port_rcvhdrq_phys, - pd->port_rcvhdrtail_kvaddr, (unsigned long long) - pd->port_rcvhdrqtailaddr_phys); - } - /* clear for security and sanity on each use */ - memset(pd->port_rcvhdrq, 0, pd->port_rcvhdrq_size); - if (pd->port_rcvhdrtail_kvaddr) - memset(pd->port_rcvhdrtail_kvaddr, 0, PAGE_SIZE); - - /* - * tell chip each time we init it, even if we are re-using previous - * memory (we zero the register at process close) - */ - ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdrtailaddr, - pd->port_port, pd->port_rcvhdrqtailaddr_phys); - ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdraddr, - pd->port_port, pd->port_rcvhdrq_phys); - -bail: - return ret; -} - - -/* - * Flush all sends that might be in the ready to send state, as well as any - * that are in the process of being sent. Used whenever we need to be - * sure the send side is idle. Cleans up all buffer state by canceling - * all pio buffers, and issuing an abort, which cleans up anything in the - * launch fifo. The cancel is superfluous on some chip versions, but - * it's safer to always do it. - * PIOAvail bits are updated by the chip as if normal send had happened. - */ -void ipath_cancel_sends(struct ipath_devdata *dd, int restore_sendctrl) -{ - unsigned long flags; - - if (dd->ipath_flags & IPATH_IB_AUTONEG_INPROG) { - ipath_cdbg(VERBOSE, "Ignore while in autonegotiation\n"); - goto bail; - } - /* - * If we have SDMA, and it's not disabled, we have to kick off the - * abort state machine, provided we aren't already aborting. - * If we are in the process of aborting SDMA (!DISABLED, but ABORTING), - * we skip the rest of this routine. It is already "in progress" - */ - if (dd->ipath_flags & IPATH_HAS_SEND_DMA) { - int skip_cancel; - unsigned long *statp = &dd->ipath_sdma_status; - - spin_lock_irqsave(&dd->ipath_sdma_lock, flags); - skip_cancel = - test_and_set_bit(IPATH_SDMA_ABORTING, statp) - && !test_bit(IPATH_SDMA_DISABLED, statp); - spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); - if (skip_cancel) - goto bail; - } - - ipath_dbg("Cancelling all in-progress send buffers\n"); - - /* skip armlaunch errs for a while */ - dd->ipath_lastcancel = jiffies + HZ / 2; - - /* - * The abort bit is auto-clearing. We also don't want pioavail - * update happening during this, and we don't want any other - * sends going out, so turn those off for the duration. We read - * the scratch register to be sure that cancels and the abort - * have taken effect in the chip. Otherwise two parts are same - * as ipath_force_pio_avail_update() - */ - spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); - dd->ipath_sendctrl &= ~(INFINIPATH_S_PIOBUFAVAILUPD - | INFINIPATH_S_PIOENABLE); - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, - dd->ipath_sendctrl | INFINIPATH_S_ABORT); - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); - - /* disarm all send buffers */ - ipath_disarm_piobufs(dd, 0, - dd->ipath_piobcnt2k + dd->ipath_piobcnt4k); - - if (dd->ipath_flags & IPATH_HAS_SEND_DMA) - set_bit(IPATH_SDMA_DISARMED, &dd->ipath_sdma_status); - - if (restore_sendctrl) { - /* else done by caller later if needed */ - spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); - dd->ipath_sendctrl |= INFINIPATH_S_PIOBUFAVAILUPD | - INFINIPATH_S_PIOENABLE; - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, - dd->ipath_sendctrl); - /* and again, be sure all have hit the chip */ - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); - } - - if ((dd->ipath_flags & IPATH_HAS_SEND_DMA) && - !test_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status) && - test_bit(IPATH_SDMA_RUNNING, &dd->ipath_sdma_status)) { - spin_lock_irqsave(&dd->ipath_sdma_lock, flags); - /* only wait so long for intr */ - dd->ipath_sdma_abort_intr_timeout = jiffies + HZ; - dd->ipath_sdma_reset_wait = 200; - if (!test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status)) - tasklet_hi_schedule(&dd->ipath_sdma_abort_task); - spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); - } -bail:; -} - -/* - * Force an update of in-memory copy of the pioavail registers, when - * needed for any of a variety of reasons. We read the scratch register - * to make it highly likely that the update will have happened by the - * time we return. If already off (as in cancel_sends above), this - * routine is a nop, on the assumption that the caller will "do the - * right thing". - */ -void ipath_force_pio_avail_update(struct ipath_devdata *dd) -{ - unsigned long flags; - - spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); - if (dd->ipath_sendctrl & INFINIPATH_S_PIOBUFAVAILUPD) { - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, - dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD); - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, - dd->ipath_sendctrl); - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - } - spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); -} - -static void ipath_set_ib_lstate(struct ipath_devdata *dd, int linkcmd, - int linitcmd) -{ - u64 mod_wd; - static const char *what[4] = { - [0] = "NOP", - [INFINIPATH_IBCC_LINKCMD_DOWN] = "DOWN", - [INFINIPATH_IBCC_LINKCMD_ARMED] = "ARMED", - [INFINIPATH_IBCC_LINKCMD_ACTIVE] = "ACTIVE" - }; - - if (linitcmd == INFINIPATH_IBCC_LINKINITCMD_DISABLE) { - /* - * If we are told to disable, note that so link-recovery - * code does not attempt to bring us back up. - */ - preempt_disable(); - dd->ipath_flags |= IPATH_IB_LINK_DISABLED; - preempt_enable(); - } else if (linitcmd) { - /* - * Any other linkinitcmd will lead to LINKDOWN and then - * to INIT (if all is well), so clear flag to let - * link-recovery code attempt to bring us back up. - */ - preempt_disable(); - dd->ipath_flags &= ~IPATH_IB_LINK_DISABLED; - preempt_enable(); - } - - mod_wd = (linkcmd << dd->ibcc_lc_shift) | - (linitcmd << INFINIPATH_IBCC_LINKINITCMD_SHIFT); - ipath_cdbg(VERBOSE, - "Moving unit %u to %s (initcmd=0x%x), current ltstate is %s\n", - dd->ipath_unit, what[linkcmd], linitcmd, - ipath_ibcstatus_str[ipath_ib_linktrstate(dd, - ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus))]); - - ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, - dd->ipath_ibcctrl | mod_wd); - /* read from chip so write is flushed */ - (void) ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus); -} - -int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate) -{ - u32 lstate; - int ret; - - switch (newstate) { - case IPATH_IB_LINKDOWN_ONLY: - ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN, 0); - /* don't wait */ - ret = 0; - goto bail; - - case IPATH_IB_LINKDOWN: - ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN, - INFINIPATH_IBCC_LINKINITCMD_POLL); - /* don't wait */ - ret = 0; - goto bail; - - case IPATH_IB_LINKDOWN_SLEEP: - ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN, - INFINIPATH_IBCC_LINKINITCMD_SLEEP); - /* don't wait */ - ret = 0; - goto bail; - - case IPATH_IB_LINKDOWN_DISABLE: - ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN, - INFINIPATH_IBCC_LINKINITCMD_DISABLE); - /* don't wait */ - ret = 0; - goto bail; - - case IPATH_IB_LINKARM: - if (dd->ipath_flags & IPATH_LINKARMED) { - ret = 0; - goto bail; - } - if (!(dd->ipath_flags & - (IPATH_LINKINIT | IPATH_LINKACTIVE))) { - ret = -EINVAL; - goto bail; - } - ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ARMED, 0); - - /* - * Since the port can transition to ACTIVE by receiving - * a non VL 15 packet, wait for either state. - */ - lstate = IPATH_LINKARMED | IPATH_LINKACTIVE; - break; - - case IPATH_IB_LINKACTIVE: - if (dd->ipath_flags & IPATH_LINKACTIVE) { - ret = 0; - goto bail; - } - if (!(dd->ipath_flags & IPATH_LINKARMED)) { - ret = -EINVAL; - goto bail; - } - ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ACTIVE, 0); - lstate = IPATH_LINKACTIVE; - break; - - case IPATH_IB_LINK_LOOPBACK: - dev_info(&dd->pcidev->dev, "Enabling IB local loopback\n"); - dd->ipath_ibcctrl |= INFINIPATH_IBCC_LOOPBACK; - ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, - dd->ipath_ibcctrl); - - /* turn heartbeat off, as it causes loopback to fail */ - dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT, - IPATH_IB_HRTBT_OFF); - /* don't wait */ - ret = 0; - goto bail; - - case IPATH_IB_LINK_EXTERNAL: - dev_info(&dd->pcidev->dev, - "Disabling IB local loopback (normal)\n"); - dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT, - IPATH_IB_HRTBT_ON); - dd->ipath_ibcctrl &= ~INFINIPATH_IBCC_LOOPBACK; - ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, - dd->ipath_ibcctrl); - /* don't wait */ - ret = 0; - goto bail; - - /* - * Heartbeat can be explicitly enabled by the user via - * "hrtbt_enable" "file", and if disabled, trying to enable here - * will have no effect. Implicit changes (heartbeat off when - * loopback on, and vice versa) are included to ease testing. - */ - case IPATH_IB_LINK_HRTBT: - ret = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT, - IPATH_IB_HRTBT_ON); - goto bail; - - case IPATH_IB_LINK_NO_HRTBT: - ret = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT, - IPATH_IB_HRTBT_OFF); - goto bail; - - default: - ipath_dbg("Invalid linkstate 0x%x requested\n", newstate); - ret = -EINVAL; - goto bail; - } - ret = ipath_wait_linkstate(dd, lstate, 2000); - -bail: - return ret; -} - -/** - * ipath_set_mtu - set the MTU - * @dd: the infinipath device - * @arg: the new MTU - * - * we can handle "any" incoming size, the issue here is whether we - * need to restrict our outgoing size. For now, we don't do any - * sanity checking on this, and we don't deal with what happens to - * programs that are already running when the size changes. - * NOTE: changing the MTU will usually cause the IBC to go back to - * link INIT state... - */ -int ipath_set_mtu(struct ipath_devdata *dd, u16 arg) -{ - u32 piosize; - int changed = 0; - int ret; - - /* - * mtu is IB data payload max. It's the largest power of 2 less - * than piosize (or even larger, since it only really controls the - * largest we can receive; we can send the max of the mtu and - * piosize). We check that it's one of the valid IB sizes. - */ - if (arg != 256 && arg != 512 && arg != 1024 && arg != 2048 && - (arg != 4096 || !ipath_mtu4096)) { - ipath_dbg("Trying to set invalid mtu %u, failing\n", arg); - ret = -EINVAL; - goto bail; - } - if (dd->ipath_ibmtu == arg) { - ret = 0; /* same as current */ - goto bail; - } - - piosize = dd->ipath_ibmaxlen; - dd->ipath_ibmtu = arg; - - if (arg >= (piosize - IPATH_PIO_MAXIBHDR)) { - /* Only if it's not the initial value (or reset to it) */ - if (piosize != dd->ipath_init_ibmaxlen) { - if (arg > piosize && arg <= dd->ipath_init_ibmaxlen) - piosize = dd->ipath_init_ibmaxlen; - dd->ipath_ibmaxlen = piosize; - changed = 1; - } - } else if ((arg + IPATH_PIO_MAXIBHDR) != dd->ipath_ibmaxlen) { - piosize = arg + IPATH_PIO_MAXIBHDR; - ipath_cdbg(VERBOSE, "ibmaxlen was 0x%x, setting to 0x%x " - "(mtu 0x%x)\n", dd->ipath_ibmaxlen, piosize, - arg); - dd->ipath_ibmaxlen = piosize; - changed = 1; - } - - if (changed) { - u64 ibc = dd->ipath_ibcctrl, ibdw; - /* - * update our housekeeping variables, and set IBC max - * size, same as init code; max IBC is max we allow in - * buffer, less the qword pbc, plus 1 for ICRC, in dwords - */ - dd->ipath_ibmaxlen = piosize - 2 * sizeof(u32); - ibdw = (dd->ipath_ibmaxlen >> 2) + 1; - ibc &= ~(INFINIPATH_IBCC_MAXPKTLEN_MASK << - dd->ibcc_mpl_shift); - ibc |= ibdw << dd->ibcc_mpl_shift; - dd->ipath_ibcctrl = ibc; - ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, - dd->ipath_ibcctrl); - dd->ipath_f_tidtemplate(dd); - } - - ret = 0; - -bail: - return ret; -} - -int ipath_set_lid(struct ipath_devdata *dd, u32 lid, u8 lmc) -{ - dd->ipath_lid = lid; - dd->ipath_lmc = lmc; - - dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LIDLMC, lid | - (~((1U << lmc) - 1)) << 16); - - dev_info(&dd->pcidev->dev, "We got a lid: 0x%x\n", lid); - - return 0; -} - - -/** - * ipath_write_kreg_port - write a device's per-port 64-bit kernel register - * @dd: the infinipath device - * @regno: the register number to write - * @port: the port containing the register - * @value: the value to write - * - * Registers that vary with the chip implementation constants (port) - * use this routine. - */ -void ipath_write_kreg_port(const struct ipath_devdata *dd, ipath_kreg regno, - unsigned port, u64 value) -{ - u16 where; - - if (port < dd->ipath_portcnt && - (regno == dd->ipath_kregs->kr_rcvhdraddr || - regno == dd->ipath_kregs->kr_rcvhdrtailaddr)) - where = regno + port; - else - where = -1; - - ipath_write_kreg(dd, where, value); -} - -/* - * Following deal with the "obviously simple" task of overriding the state - * of the LEDS, which normally indicate link physical and logical status. - * The complications arise in dealing with different hardware mappings - * and the board-dependent routine being called from interrupts. - * and then there's the requirement to _flash_ them. - */ -#define LED_OVER_FREQ_SHIFT 8 -#define LED_OVER_FREQ_MASK (0xFF<ipath_flags & IPATH_INITTED)) - return; - - pidx = dd->ipath_led_override_phase++ & 1; - dd->ipath_led_override = dd->ipath_led_override_vals[pidx]; - timeoff = dd->ipath_led_override_timeoff; - - /* - * below potentially restores the LED values per current status, - * should also possibly setup the traffic-blink register, - * but leave that to per-chip functions. - */ - val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus); - ltstate = ipath_ib_linktrstate(dd, val); - lstate = ipath_ib_linkstate(dd, val); - - dd->ipath_f_setextled(dd, lstate, ltstate); - mod_timer(&dd->ipath_led_override_timer, jiffies + timeoff); -} - -void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val) -{ - int timeoff, freq; - - if (!(dd->ipath_flags & IPATH_INITTED)) - return; - - /* First check if we are blinking. If not, use 1HZ polling */ - timeoff = HZ; - freq = (val & LED_OVER_FREQ_MASK) >> LED_OVER_FREQ_SHIFT; - - if (freq) { - /* For blink, set each phase from one nybble of val */ - dd->ipath_led_override_vals[0] = val & 0xF; - dd->ipath_led_override_vals[1] = (val >> 4) & 0xF; - timeoff = (HZ << 4)/freq; - } else { - /* Non-blink set both phases the same. */ - dd->ipath_led_override_vals[0] = val & 0xF; - dd->ipath_led_override_vals[1] = val & 0xF; - } - dd->ipath_led_override_timeoff = timeoff; - - /* - * If the timer has not already been started, do so. Use a "quick" - * timeout so the function will be called soon, to look at our request. - */ - if (atomic_inc_return(&dd->ipath_led_override_timer_active) == 1) { - /* Need to start timer */ - setup_timer(&dd->ipath_led_override_timer, - ipath_run_led_override, (unsigned long)dd); - - dd->ipath_led_override_timer.expires = jiffies + 1; - add_timer(&dd->ipath_led_override_timer); - } else - atomic_dec(&dd->ipath_led_override_timer_active); -} - -/** - * ipath_shutdown_device - shut down a device - * @dd: the infinipath device - * - * This is called to make the device quiet when we are about to - * unload the driver, and also when the device is administratively - * disabled. It does not free any data structures. - * Everything it does has to be setup again by ipath_init_chip(dd,1) - */ -void ipath_shutdown_device(struct ipath_devdata *dd) -{ - unsigned long flags; - - ipath_dbg("Shutting down the device\n"); - - ipath_hol_up(dd); /* make sure user processes aren't suspended */ - - dd->ipath_flags |= IPATH_LINKUNK; - dd->ipath_flags &= ~(IPATH_INITTED | IPATH_LINKDOWN | - IPATH_LINKINIT | IPATH_LINKARMED | - IPATH_LINKACTIVE); - *dd->ipath_statusp &= ~(IPATH_STATUS_IB_CONF | - IPATH_STATUS_IB_READY); - - /* mask interrupts, but not errors */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, 0ULL); - - dd->ipath_rcvctrl = 0; - ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, - dd->ipath_rcvctrl); - - if (dd->ipath_flags & IPATH_HAS_SEND_DMA) - teardown_sdma(dd); - - /* - * gracefully stop all sends allowing any in progress to trickle out - * first. - */ - spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); - dd->ipath_sendctrl = 0; - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl); - /* flush it */ - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); - - /* - * enough for anything that's going to trickle out to have actually - * done so. - */ - udelay(5); - - dd->ipath_f_setextled(dd, 0, 0); /* make sure LEDs are off */ - - ipath_set_ib_lstate(dd, 0, INFINIPATH_IBCC_LINKINITCMD_DISABLE); - ipath_cancel_sends(dd, 0); - - /* - * we are shutting down, so tell components that care. We don't do - * this on just a link state change, much like ethernet, a cable - * unplug, etc. doesn't change driver state - */ - signal_ib_event(dd, IB_EVENT_PORT_ERR); - - /* disable IBC */ - dd->ipath_control &= ~INFINIPATH_C_LINKENABLE; - ipath_write_kreg(dd, dd->ipath_kregs->kr_control, - dd->ipath_control | INFINIPATH_C_FREEZEMODE); - - /* - * clear SerdesEnable and turn the leds off; do this here because - * we are unloading, so don't count on interrupts to move along - * Turn the LEDs off explicitly for the same reason. - */ - dd->ipath_f_quiet_serdes(dd); - - /* stop all the timers that might still be running */ - del_timer_sync(&dd->ipath_hol_timer); - if (dd->ipath_stats_timer_active) { - del_timer_sync(&dd->ipath_stats_timer); - dd->ipath_stats_timer_active = 0; - } - if (dd->ipath_intrchk_timer.data) { - del_timer_sync(&dd->ipath_intrchk_timer); - dd->ipath_intrchk_timer.data = 0; - } - if (atomic_read(&dd->ipath_led_override_timer_active)) { - del_timer_sync(&dd->ipath_led_override_timer); - atomic_set(&dd->ipath_led_override_timer_active, 0); - } - - /* - * clear all interrupts and errors, so that the next time the driver - * is loaded or device is enabled, we know that whatever is set - * happened while we were unloaded - */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, - ~0ULL & ~INFINIPATH_HWE_MEMBISTFAILED); - ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, -1LL); - ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL); - - ipath_cdbg(VERBOSE, "Flush time and errors to EEPROM\n"); - ipath_update_eeprom_log(dd); -} - -/** - * ipath_free_pddata - free a port's allocated data - * @dd: the infinipath device - * @pd: the portdata structure - * - * free up any allocated data for a port - * This should not touch anything that would affect a simultaneous - * re-allocation of port data, because it is called after ipath_mutex - * is released (and can be called from reinit as well). - * It should never change any chip state, or global driver state. - * (The only exception to global state is freeing the port0 port0_skbs.) - */ -void ipath_free_pddata(struct ipath_devdata *dd, struct ipath_portdata *pd) -{ - if (!pd) - return; - - if (pd->port_rcvhdrq) { - ipath_cdbg(VERBOSE, "free closed port %d rcvhdrq @ %p " - "(size=%lu)\n", pd->port_port, pd->port_rcvhdrq, - (unsigned long) pd->port_rcvhdrq_size); - dma_free_coherent(&dd->pcidev->dev, pd->port_rcvhdrq_size, - pd->port_rcvhdrq, pd->port_rcvhdrq_phys); - pd->port_rcvhdrq = NULL; - if (pd->port_rcvhdrtail_kvaddr) { - dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE, - pd->port_rcvhdrtail_kvaddr, - pd->port_rcvhdrqtailaddr_phys); - pd->port_rcvhdrtail_kvaddr = NULL; - } - } - if (pd->port_port && pd->port_rcvegrbuf) { - unsigned e; - - for (e = 0; e < pd->port_rcvegrbuf_chunks; e++) { - void *base = pd->port_rcvegrbuf[e]; - size_t size = pd->port_rcvegrbuf_size; - - ipath_cdbg(VERBOSE, "egrbuf free(%p, %lu), " - "chunk %u/%u\n", base, - (unsigned long) size, - e, pd->port_rcvegrbuf_chunks); - dma_free_coherent(&dd->pcidev->dev, size, - base, pd->port_rcvegrbuf_phys[e]); - } - kfree(pd->port_rcvegrbuf); - pd->port_rcvegrbuf = NULL; - kfree(pd->port_rcvegrbuf_phys); - pd->port_rcvegrbuf_phys = NULL; - pd->port_rcvegrbuf_chunks = 0; - } else if (pd->port_port == 0 && dd->ipath_port0_skbinfo) { - unsigned e; - struct ipath_skbinfo *skbinfo = dd->ipath_port0_skbinfo; - - dd->ipath_port0_skbinfo = NULL; - ipath_cdbg(VERBOSE, "free closed port %d " - "ipath_port0_skbinfo @ %p\n", pd->port_port, - skbinfo); - for (e = 0; e < dd->ipath_p0_rcvegrcnt; e++) - if (skbinfo[e].skb) { - pci_unmap_single(dd->pcidev, skbinfo[e].phys, - dd->ipath_ibmaxlen, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(skbinfo[e].skb); - } - vfree(skbinfo); - } - kfree(pd->port_tid_pg_list); - vfree(pd->subport_uregbase); - vfree(pd->subport_rcvegrbuf); - vfree(pd->subport_rcvhdr_base); - kfree(pd); -} - -static int __init infinipath_init(void) -{ - int ret; - - if (ipath_debug & __IPATH_DBG) - printk(KERN_INFO DRIVER_LOAD_MSG "%s", ib_ipath_version); - - /* - * These must be called before the driver is registered with - * the PCI subsystem. - */ - idr_init(&unit_table); - - ret = pci_register_driver(&ipath_driver); - if (ret < 0) { - printk(KERN_ERR IPATH_DRV_NAME - ": Unable to register driver: error %d\n", -ret); - goto bail_unit; - } - - ret = ipath_init_ipathfs(); - if (ret < 0) { - printk(KERN_ERR IPATH_DRV_NAME ": Unable to create " - "ipathfs: error %d\n", -ret); - goto bail_pci; - } - - goto bail; - -bail_pci: - pci_unregister_driver(&ipath_driver); - -bail_unit: - idr_destroy(&unit_table); - -bail: - return ret; -} - -static void __exit infinipath_cleanup(void) -{ - ipath_exit_ipathfs(); - - ipath_cdbg(VERBOSE, "Unregistering pci driver\n"); - pci_unregister_driver(&ipath_driver); - - idr_destroy(&unit_table); -} - -/** - * ipath_reset_device - reset the chip if possible - * @unit: the device to reset - * - * Whether or not reset is successful, we attempt to re-initialize the chip - * (that is, much like a driver unload/reload). We clear the INITTED flag - * so that the various entry points will fail until we reinitialize. For - * now, we only allow this if no user ports are open that use chip resources - */ -int ipath_reset_device(int unit) -{ - int ret, i; - struct ipath_devdata *dd = ipath_lookup(unit); - unsigned long flags; - - if (!dd) { - ret = -ENODEV; - goto bail; - } - - if (atomic_read(&dd->ipath_led_override_timer_active)) { - /* Need to stop LED timer, _then_ shut off LEDs */ - del_timer_sync(&dd->ipath_led_override_timer); - atomic_set(&dd->ipath_led_override_timer_active, 0); - } - - /* Shut off LEDs after we are sure timer is not running */ - dd->ipath_led_override = LED_OVER_BOTH_OFF; - dd->ipath_f_setextled(dd, 0, 0); - - dev_info(&dd->pcidev->dev, "Reset on unit %u requested\n", unit); - - if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) { - dev_info(&dd->pcidev->dev, "Invalid unit number %u or " - "not initialized or not present\n", unit); - ret = -ENXIO; - goto bail; - } - - spin_lock_irqsave(&dd->ipath_uctxt_lock, flags); - if (dd->ipath_pd) - for (i = 1; i < dd->ipath_cfgports; i++) { - if (!dd->ipath_pd[i] || !dd->ipath_pd[i]->port_cnt) - continue; - spin_unlock_irqrestore(&dd->ipath_uctxt_lock, flags); - ipath_dbg("unit %u port %d is in use " - "(PID %u cmd %s), can't reset\n", - unit, i, - pid_nr(dd->ipath_pd[i]->port_pid), - dd->ipath_pd[i]->port_comm); - ret = -EBUSY; - goto bail; - } - spin_unlock_irqrestore(&dd->ipath_uctxt_lock, flags); - - if (dd->ipath_flags & IPATH_HAS_SEND_DMA) - teardown_sdma(dd); - - dd->ipath_flags &= ~IPATH_INITTED; - ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, 0ULL); - ret = dd->ipath_f_reset(dd); - if (ret == 1) { - ipath_dbg("Reinitializing unit %u after reset attempt\n", - unit); - ret = ipath_init_chip(dd, 1); - } else - ret = -EAGAIN; - if (ret) - ipath_dev_err(dd, "Reinitialize unit %u after " - "reset failed with %d\n", unit, ret); - else - dev_info(&dd->pcidev->dev, "Reinitialized unit %u after " - "resetting\n", unit); - -bail: - return ret; -} - -/* - * send a signal to all the processes that have the driver open - * through the normal interfaces (i.e., everything other than diags - * interface). Returns number of signalled processes. - */ -static int ipath_signal_procs(struct ipath_devdata *dd, int sig) -{ - int i, sub, any = 0; - struct pid *pid; - unsigned long flags; - - if (!dd->ipath_pd) - return 0; - - spin_lock_irqsave(&dd->ipath_uctxt_lock, flags); - for (i = 1; i < dd->ipath_cfgports; i++) { - if (!dd->ipath_pd[i] || !dd->ipath_pd[i]->port_cnt) - continue; - pid = dd->ipath_pd[i]->port_pid; - if (!pid) - continue; - - dev_info(&dd->pcidev->dev, "context %d in use " - "(PID %u), sending signal %d\n", - i, pid_nr(pid), sig); - kill_pid(pid, sig, 1); - any++; - for (sub = 0; sub < INFINIPATH_MAX_SUBPORT; sub++) { - pid = dd->ipath_pd[i]->port_subpid[sub]; - if (!pid) - continue; - dev_info(&dd->pcidev->dev, "sub-context " - "%d:%d in use (PID %u), sending " - "signal %d\n", i, sub, pid_nr(pid), sig); - kill_pid(pid, sig, 1); - any++; - } - } - spin_unlock_irqrestore(&dd->ipath_uctxt_lock, flags); - return any; -} - -static void ipath_hol_signal_down(struct ipath_devdata *dd) -{ - if (ipath_signal_procs(dd, SIGSTOP)) - ipath_dbg("Stopped some processes\n"); - ipath_cancel_sends(dd, 1); -} - - -static void ipath_hol_signal_up(struct ipath_devdata *dd) -{ - if (ipath_signal_procs(dd, SIGCONT)) - ipath_dbg("Continued some processes\n"); -} - -/* - * link is down, stop any users processes, and flush pending sends - * to prevent HoL blocking, then start the HoL timer that - * periodically continues, then stop procs, so they can detect - * link down if they want, and do something about it. - * Timer may already be running, so use mod_timer, not add_timer. - */ -void ipath_hol_down(struct ipath_devdata *dd) -{ - dd->ipath_hol_state = IPATH_HOL_DOWN; - ipath_hol_signal_down(dd); - dd->ipath_hol_next = IPATH_HOL_DOWNCONT; - dd->ipath_hol_timer.expires = jiffies + - msecs_to_jiffies(ipath_hol_timeout_ms); - mod_timer(&dd->ipath_hol_timer, dd->ipath_hol_timer.expires); -} - -/* - * link is up, continue any user processes, and ensure timer - * is a nop, if running. Let timer keep running, if set; it - * will nop when it sees the link is up - */ -void ipath_hol_up(struct ipath_devdata *dd) -{ - ipath_hol_signal_up(dd); - dd->ipath_hol_state = IPATH_HOL_UP; -} - -/* - * toggle the running/not running state of user proceses - * to prevent HoL blocking on chip resources, but still allow - * user processes to do link down special case handling. - * Should only be called via the timer - */ -void ipath_hol_event(unsigned long opaque) -{ - struct ipath_devdata *dd = (struct ipath_devdata *)opaque; - - if (dd->ipath_hol_next == IPATH_HOL_DOWNSTOP - && dd->ipath_hol_state != IPATH_HOL_UP) { - dd->ipath_hol_next = IPATH_HOL_DOWNCONT; - ipath_dbg("Stopping processes\n"); - ipath_hol_signal_down(dd); - } else { /* may do "extra" if also in ipath_hol_up() */ - dd->ipath_hol_next = IPATH_HOL_DOWNSTOP; - ipath_dbg("Continuing processes\n"); - ipath_hol_signal_up(dd); - } - if (dd->ipath_hol_state == IPATH_HOL_UP) - ipath_dbg("link's up, don't resched timer\n"); - else { - dd->ipath_hol_timer.expires = jiffies + - msecs_to_jiffies(ipath_hol_timeout_ms); - mod_timer(&dd->ipath_hol_timer, - dd->ipath_hol_timer.expires); - } -} - -int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv) -{ - u64 val; - - if (new_pol_inv > INFINIPATH_XGXS_RX_POL_MASK) - return -1; - if (dd->ipath_rx_pol_inv != new_pol_inv) { - dd->ipath_rx_pol_inv = new_pol_inv; - val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig); - val &= ~(INFINIPATH_XGXS_RX_POL_MASK << - INFINIPATH_XGXS_RX_POL_SHIFT); - val |= ((u64)dd->ipath_rx_pol_inv) << - INFINIPATH_XGXS_RX_POL_SHIFT; - ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val); - } - return 0; -} - -/* - * Disable and enable the armlaunch error. Used for PIO bandwidth testing on - * the 7220, which is count-based, rather than trigger-based. Safe for the - * driver check, since it's at init. Not completely safe when used for - * user-mode checking, since some error checking can be lost, but not - * particularly risky, and only has problematic side-effects in the face of - * very buggy user code. There is no reference counting, but that's also - * fine, given the intended use. - */ -void ipath_enable_armlaunch(struct ipath_devdata *dd) -{ - dd->ipath_lasterror &= ~INFINIPATH_E_SPIOARMLAUNCH; - ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, - INFINIPATH_E_SPIOARMLAUNCH); - dd->ipath_errormask |= INFINIPATH_E_SPIOARMLAUNCH; - ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, - dd->ipath_errormask); -} - -void ipath_disable_armlaunch(struct ipath_devdata *dd) -{ - /* so don't re-enable if already set */ - dd->ipath_maskederrs &= ~INFINIPATH_E_SPIOARMLAUNCH; - dd->ipath_errormask &= ~INFINIPATH_E_SPIOARMLAUNCH; - ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, - dd->ipath_errormask); -} - -module_init(infinipath_init); -module_exit(infinipath_cleanup); diff --git a/drivers/staging/rdma/ipath/ipath_eeprom.c b/drivers/staging/rdma/ipath/ipath_eeprom.c deleted file mode 100644 index ef84107c7ce0..000000000000 --- a/drivers/staging/rdma/ipath/ipath_eeprom.c +++ /dev/null @@ -1,1183 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include - -#include "ipath_kernel.h" - -/* - * InfiniPath I2C driver for a serial eeprom. This is not a generic - * I2C interface. For a start, the device we're using (Atmel AT24C11) - * doesn't work like a regular I2C device. It looks like one - * electrically, but not logically. Normal I2C devices have a single - * 7-bit or 10-bit I2C address that they respond to. Valid 7-bit - * addresses range from 0x03 to 0x77. Addresses 0x00 to 0x02 and 0x78 - * to 0x7F are special reserved addresses (e.g. 0x00 is the "general - * call" address.) The Atmel device, on the other hand, responds to ALL - * 7-bit addresses. It's designed to be the only device on a given I2C - * bus. A 7-bit address corresponds to the memory address within the - * Atmel device itself. - * - * Also, the timing requirements mean more than simple software - * bitbanging, with readbacks from chip to ensure timing (simple udelay - * is not enough). - * - * This all means that accessing the device is specialized enough - * that using the standard kernel I2C bitbanging interface would be - * impossible. For example, the core I2C eeprom driver expects to find - * a device at one or more of a limited set of addresses only. It doesn't - * allow writing to an eeprom. It also doesn't provide any means of - * accessing eeprom contents from within the kernel, only via sysfs. - */ - -/* Added functionality for IBA7220-based cards */ -#define IPATH_EEPROM_DEV_V1 0xA0 -#define IPATH_EEPROM_DEV_V2 0xA2 -#define IPATH_TEMP_DEV 0x98 -#define IPATH_BAD_DEV (IPATH_EEPROM_DEV_V2+2) -#define IPATH_NO_DEV (0xFF) - -/* - * The number of I2C chains is proliferating. Table below brings - * some order to the madness. The basic principle is that the - * table is scanned from the top, and a "probe" is made to the - * device probe_dev. If that succeeds, the chain is considered - * to be of that type, and dd->i2c_chain_type is set to the index+1 - * of the entry. - * The +1 is so static initialization can mean "unknown, do probe." - */ -static struct i2c_chain_desc { - u8 probe_dev; /* If seen at probe, chain is this type */ - u8 eeprom_dev; /* Dev addr (if any) for EEPROM */ - u8 temp_dev; /* Dev Addr (if any) for Temp-sense */ -} i2c_chains[] = { - { IPATH_BAD_DEV, IPATH_NO_DEV, IPATH_NO_DEV }, /* pre-iba7220 bds */ - { IPATH_EEPROM_DEV_V1, IPATH_EEPROM_DEV_V1, IPATH_TEMP_DEV}, /* V1 */ - { IPATH_EEPROM_DEV_V2, IPATH_EEPROM_DEV_V2, IPATH_TEMP_DEV}, /* V2 */ - { IPATH_NO_DEV } -}; - -enum i2c_type { - i2c_line_scl = 0, - i2c_line_sda -}; - -enum i2c_state { - i2c_line_low = 0, - i2c_line_high -}; - -#define READ_CMD 1 -#define WRITE_CMD 0 - -/** - * i2c_gpio_set - set a GPIO line - * @dd: the infinipath device - * @line: the line to set - * @new_line_state: the state to set - * - * Returns 0 if the line was set to the new state successfully, non-zero - * on error. - */ -static int i2c_gpio_set(struct ipath_devdata *dd, - enum i2c_type line, - enum i2c_state new_line_state) -{ - u64 out_mask, dir_mask, *gpioval; - unsigned long flags = 0; - - gpioval = &dd->ipath_gpio_out; - - if (line == i2c_line_scl) { - dir_mask = dd->ipath_gpio_scl; - out_mask = (1UL << dd->ipath_gpio_scl_num); - } else { - dir_mask = dd->ipath_gpio_sda; - out_mask = (1UL << dd->ipath_gpio_sda_num); - } - - spin_lock_irqsave(&dd->ipath_gpio_lock, flags); - if (new_line_state == i2c_line_high) { - /* tri-state the output rather than force high */ - dd->ipath_extctrl &= ~dir_mask; - } else { - /* config line to be an output */ - dd->ipath_extctrl |= dir_mask; - } - ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, dd->ipath_extctrl); - - /* set output as well (no real verify) */ - if (new_line_state == i2c_line_high) - *gpioval |= out_mask; - else - *gpioval &= ~out_mask; - - ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_out, *gpioval); - spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags); - - return 0; -} - -/** - * i2c_gpio_get - get a GPIO line state - * @dd: the infinipath device - * @line: the line to get - * @curr_statep: where to put the line state - * - * Returns 0 if the line was set to the new state successfully, non-zero - * on error. curr_state is not set on error. - */ -static int i2c_gpio_get(struct ipath_devdata *dd, - enum i2c_type line, - enum i2c_state *curr_statep) -{ - u64 read_val, mask; - int ret; - unsigned long flags = 0; - - /* check args */ - if (curr_statep == NULL) { - ret = 1; - goto bail; - } - - /* config line to be an input */ - if (line == i2c_line_scl) - mask = dd->ipath_gpio_scl; - else - mask = dd->ipath_gpio_sda; - - spin_lock_irqsave(&dd->ipath_gpio_lock, flags); - dd->ipath_extctrl &= ~mask; - ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, dd->ipath_extctrl); - /* - * Below is very unlikely to reflect true input state if Output - * Enable actually changed. - */ - read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus); - spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags); - - if (read_val & mask) - *curr_statep = i2c_line_high; - else - *curr_statep = i2c_line_low; - - ret = 0; - -bail: - return ret; -} - -/** - * i2c_wait_for_writes - wait for a write - * @dd: the infinipath device - * - * We use this instead of udelay directly, so we can make sure - * that previous register writes have been flushed all the way - * to the chip. Since we are delaying anyway, the cost doesn't - * hurt, and makes the bit twiddling more regular - */ -static void i2c_wait_for_writes(struct ipath_devdata *dd) -{ - (void)ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch); - rmb(); -} - -static void scl_out(struct ipath_devdata *dd, u8 bit) -{ - udelay(1); - i2c_gpio_set(dd, i2c_line_scl, bit ? i2c_line_high : i2c_line_low); - - i2c_wait_for_writes(dd); -} - -static void sda_out(struct ipath_devdata *dd, u8 bit) -{ - i2c_gpio_set(dd, i2c_line_sda, bit ? i2c_line_high : i2c_line_low); - - i2c_wait_for_writes(dd); -} - -static u8 sda_in(struct ipath_devdata *dd, int wait) -{ - enum i2c_state bit; - - if (i2c_gpio_get(dd, i2c_line_sda, &bit)) - ipath_dbg("get bit failed!\n"); - - if (wait) - i2c_wait_for_writes(dd); - - return bit == i2c_line_high ? 1U : 0; -} - -/** - * i2c_ackrcv - see if ack following write is true - * @dd: the infinipath device - */ -static int i2c_ackrcv(struct ipath_devdata *dd) -{ - u8 ack_received; - - /* AT ENTRY SCL = LOW */ - /* change direction, ignore data */ - ack_received = sda_in(dd, 1); - scl_out(dd, i2c_line_high); - ack_received = sda_in(dd, 1) == 0; - scl_out(dd, i2c_line_low); - return ack_received; -} - -/** - * rd_byte - read a byte, leaving ACK, STOP, etc up to caller - * @dd: the infinipath device - * - * Returns byte shifted out of device - */ -static int rd_byte(struct ipath_devdata *dd) -{ - int bit_cntr, data; - - data = 0; - - for (bit_cntr = 7; bit_cntr >= 0; --bit_cntr) { - data <<= 1; - scl_out(dd, i2c_line_high); - data |= sda_in(dd, 0); - scl_out(dd, i2c_line_low); - } - return data; -} - -/** - * wr_byte - write a byte, one bit at a time - * @dd: the infinipath device - * @data: the byte to write - * - * Returns 0 if we got the following ack, otherwise 1 - */ -static int wr_byte(struct ipath_devdata *dd, u8 data) -{ - int bit_cntr; - u8 bit; - - for (bit_cntr = 7; bit_cntr >= 0; bit_cntr--) { - bit = (data >> bit_cntr) & 1; - sda_out(dd, bit); - scl_out(dd, i2c_line_high); - scl_out(dd, i2c_line_low); - } - return (!i2c_ackrcv(dd)) ? 1 : 0; -} - -static void send_ack(struct ipath_devdata *dd) -{ - sda_out(dd, i2c_line_low); - scl_out(dd, i2c_line_high); - scl_out(dd, i2c_line_low); - sda_out(dd, i2c_line_high); -} - -/** - * i2c_startcmd - transmit the start condition, followed by address/cmd - * @dd: the infinipath device - * @offset_dir: direction byte - * - * (both clock/data high, clock high, data low while clock is high) - */ -static int i2c_startcmd(struct ipath_devdata *dd, u8 offset_dir) -{ - int res; - - /* issue start sequence */ - sda_out(dd, i2c_line_high); - scl_out(dd, i2c_line_high); - sda_out(dd, i2c_line_low); - scl_out(dd, i2c_line_low); - - /* issue length and direction byte */ - res = wr_byte(dd, offset_dir); - - if (res) - ipath_cdbg(VERBOSE, "No ack to complete start\n"); - - return res; -} - -/** - * stop_cmd - transmit the stop condition - * @dd: the infinipath device - * - * (both clock/data low, clock high, data high while clock is high) - */ -static void stop_cmd(struct ipath_devdata *dd) -{ - scl_out(dd, i2c_line_low); - sda_out(dd, i2c_line_low); - scl_out(dd, i2c_line_high); - sda_out(dd, i2c_line_high); - udelay(2); -} - -/** - * eeprom_reset - reset I2C communication - * @dd: the infinipath device - */ - -static int eeprom_reset(struct ipath_devdata *dd) -{ - int clock_cycles_left = 9; - u64 *gpioval = &dd->ipath_gpio_out; - int ret; - unsigned long flags; - - spin_lock_irqsave(&dd->ipath_gpio_lock, flags); - /* Make sure shadows are consistent */ - dd->ipath_extctrl = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl); - *gpioval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_out); - spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags); - - ipath_cdbg(VERBOSE, "Resetting i2c eeprom; initial gpioout reg " - "is %llx\n", (unsigned long long) *gpioval); - - /* - * This is to get the i2c into a known state, by first going low, - * then tristate sda (and then tristate scl as first thing - * in loop) - */ - scl_out(dd, i2c_line_low); - sda_out(dd, i2c_line_high); - - /* Clock up to 9 cycles looking for SDA hi, then issue START and STOP */ - while (clock_cycles_left--) { - scl_out(dd, i2c_line_high); - - /* SDA seen high, issue START by dropping it while SCL high */ - if (sda_in(dd, 0)) { - sda_out(dd, i2c_line_low); - scl_out(dd, i2c_line_low); - /* ATMEL spec says must be followed by STOP. */ - scl_out(dd, i2c_line_high); - sda_out(dd, i2c_line_high); - ret = 0; - goto bail; - } - - scl_out(dd, i2c_line_low); - } - - ret = 1; - -bail: - return ret; -} - -/* - * Probe for I2C device at specified address. Returns 0 for "success" - * to match rest of this file. - * Leave bus in "reasonable" state for further commands. - */ -static int i2c_probe(struct ipath_devdata *dd, int devaddr) -{ - int ret; - - ret = eeprom_reset(dd); - if (ret) { - ipath_dev_err(dd, "Failed reset probing device 0x%02X\n", - devaddr); - return ret; - } - /* - * Reset no longer leaves bus in start condition, so normal - * i2c_startcmd() will do. - */ - ret = i2c_startcmd(dd, devaddr | READ_CMD); - if (ret) - ipath_cdbg(VERBOSE, "Failed startcmd for device 0x%02X\n", - devaddr); - else { - /* - * Device did respond. Complete a single-byte read, because some - * devices apparently cannot handle STOP immediately after they - * ACK the start-cmd. - */ - int data; - data = rd_byte(dd); - stop_cmd(dd); - ipath_cdbg(VERBOSE, "Response from device 0x%02X\n", devaddr); - } - return ret; -} - -/* - * Returns the "i2c type". This is a pointer to a struct that describes - * the I2C chain on this board. To minimize impact on struct ipath_devdata, - * the (small integer) index into the table is actually memoized, rather - * then the pointer. - * Memoization is because the type is determined on the first call per chip. - * An alternative would be to move type determination to early - * init code. - */ -static struct i2c_chain_desc *ipath_i2c_type(struct ipath_devdata *dd) -{ - int idx; - - /* Get memoized index, from previous successful probes */ - idx = dd->ipath_i2c_chain_type - 1; - if (idx >= 0 && idx < (ARRAY_SIZE(i2c_chains) - 1)) - goto done; - - idx = 0; - while (i2c_chains[idx].probe_dev != IPATH_NO_DEV) { - /* if probe succeeds, this is type */ - if (!i2c_probe(dd, i2c_chains[idx].probe_dev)) - break; - ++idx; - } - - /* - * Old EEPROM (first entry) may require a reset after probe, - * rather than being able to "start" after "stop" - */ - if (idx == 0) - eeprom_reset(dd); - - if (i2c_chains[idx].probe_dev == IPATH_NO_DEV) - idx = -1; - else - dd->ipath_i2c_chain_type = idx + 1; -done: - return (idx >= 0) ? i2c_chains + idx : NULL; -} - -static int ipath_eeprom_internal_read(struct ipath_devdata *dd, - u8 eeprom_offset, void *buffer, int len) -{ - int ret; - struct i2c_chain_desc *icd; - u8 *bp = buffer; - - ret = 1; - icd = ipath_i2c_type(dd); - if (!icd) - goto bail; - - if (icd->eeprom_dev == IPATH_NO_DEV) { - /* legacy not-really-I2C */ - ipath_cdbg(VERBOSE, "Start command only address\n"); - eeprom_offset = (eeprom_offset << 1) | READ_CMD; - ret = i2c_startcmd(dd, eeprom_offset); - } else { - /* Actual I2C */ - ipath_cdbg(VERBOSE, "Start command uses devaddr\n"); - if (i2c_startcmd(dd, icd->eeprom_dev | WRITE_CMD)) { - ipath_dbg("Failed EEPROM startcmd\n"); - stop_cmd(dd); - ret = 1; - goto bail; - } - ret = wr_byte(dd, eeprom_offset); - stop_cmd(dd); - if (ret) { - ipath_dev_err(dd, "Failed to write EEPROM address\n"); - ret = 1; - goto bail; - } - ret = i2c_startcmd(dd, icd->eeprom_dev | READ_CMD); - } - if (ret) { - ipath_dbg("Failed startcmd for dev %02X\n", icd->eeprom_dev); - stop_cmd(dd); - ret = 1; - goto bail; - } - - /* - * eeprom keeps clocking data out as long as we ack, automatically - * incrementing the address. - */ - while (len-- > 0) { - /* get and store data */ - *bp++ = rd_byte(dd); - /* send ack if not the last byte */ - if (len) - send_ack(dd); - } - - stop_cmd(dd); - - ret = 0; - -bail: - return ret; -} - -static int ipath_eeprom_internal_write(struct ipath_devdata *dd, u8 eeprom_offset, - const void *buffer, int len) -{ - int sub_len; - const u8 *bp = buffer; - int max_wait_time, i; - int ret; - struct i2c_chain_desc *icd; - - ret = 1; - icd = ipath_i2c_type(dd); - if (!icd) - goto bail; - - while (len > 0) { - if (icd->eeprom_dev == IPATH_NO_DEV) { - if (i2c_startcmd(dd, - (eeprom_offset << 1) | WRITE_CMD)) { - ipath_dbg("Failed to start cmd offset %u\n", - eeprom_offset); - goto failed_write; - } - } else { - /* Real I2C */ - if (i2c_startcmd(dd, icd->eeprom_dev | WRITE_CMD)) { - ipath_dbg("Failed EEPROM startcmd\n"); - goto failed_write; - } - ret = wr_byte(dd, eeprom_offset); - if (ret) { - ipath_dev_err(dd, "Failed to write EEPROM " - "address\n"); - goto failed_write; - } - } - - sub_len = min(len, 4); - eeprom_offset += sub_len; - len -= sub_len; - - for (i = 0; i < sub_len; i++) { - if (wr_byte(dd, *bp++)) { - ipath_dbg("no ack after byte %u/%u (%u " - "total remain)\n", i, sub_len, - len + sub_len - i); - goto failed_write; - } - } - - stop_cmd(dd); - - /* - * wait for write complete by waiting for a successful - * read (the chip replies with a zero after the write - * cmd completes, and before it writes to the eeprom. - * The startcmd for the read will fail the ack until - * the writes have completed. We do this inline to avoid - * the debug prints that are in the real read routine - * if the startcmd fails. - * We also use the proper device address, so it doesn't matter - * whether we have real eeprom_dev. legacy likes any address. - */ - max_wait_time = 100; - while (i2c_startcmd(dd, icd->eeprom_dev | READ_CMD)) { - stop_cmd(dd); - if (!--max_wait_time) { - ipath_dbg("Did not get successful read to " - "complete write\n"); - goto failed_write; - } - } - /* now read (and ignore) the resulting byte */ - rd_byte(dd); - stop_cmd(dd); - } - - ret = 0; - goto bail; - -failed_write: - stop_cmd(dd); - ret = 1; - -bail: - return ret; -} - -/** - * ipath_eeprom_read - receives bytes from the eeprom via I2C - * @dd: the infinipath device - * @eeprom_offset: address to read from - * @buffer: where to store result - * @len: number of bytes to receive - */ -int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset, - void *buff, int len) -{ - int ret; - - ret = mutex_lock_interruptible(&dd->ipath_eep_lock); - if (!ret) { - ret = ipath_eeprom_internal_read(dd, eeprom_offset, buff, len); - mutex_unlock(&dd->ipath_eep_lock); - } - - return ret; -} - -/** - * ipath_eeprom_write - writes data to the eeprom via I2C - * @dd: the infinipath device - * @eeprom_offset: where to place data - * @buffer: data to write - * @len: number of bytes to write - */ -int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset, - const void *buff, int len) -{ - int ret; - - ret = mutex_lock_interruptible(&dd->ipath_eep_lock); - if (!ret) { - ret = ipath_eeprom_internal_write(dd, eeprom_offset, buff, len); - mutex_unlock(&dd->ipath_eep_lock); - } - - return ret; -} - -static u8 flash_csum(struct ipath_flash *ifp, int adjust) -{ - u8 *ip = (u8 *) ifp; - u8 csum = 0, len; - - /* - * Limit length checksummed to max length of actual data. - * Checksum of erased eeprom will still be bad, but we avoid - * reading past the end of the buffer we were passed. - */ - len = ifp->if_length; - if (len > sizeof(struct ipath_flash)) - len = sizeof(struct ipath_flash); - while (len--) - csum += *ip++; - csum -= ifp->if_csum; - csum = ~csum; - if (adjust) - ifp->if_csum = csum; - - return csum; -} - -/** - * ipath_get_guid - get the GUID from the i2c device - * @dd: the infinipath device - * - * We have the capability to use the ipath_nguid field, and get - * the guid from the first chip's flash, to use for all of them. - */ -void ipath_get_eeprom_info(struct ipath_devdata *dd) -{ - void *buf; - struct ipath_flash *ifp; - __be64 guid; - int len, eep_stat; - u8 csum, *bguid; - int t = dd->ipath_unit; - struct ipath_devdata *dd0 = ipath_lookup(0); - - if (t && dd0->ipath_nguid > 1 && t <= dd0->ipath_nguid) { - u8 oguid; - dd->ipath_guid = dd0->ipath_guid; - bguid = (u8 *) & dd->ipath_guid; - - oguid = bguid[7]; - bguid[7] += t; - if (oguid > bguid[7]) { - if (bguid[6] == 0xff) { - if (bguid[5] == 0xff) { - ipath_dev_err( - dd, - "Can't set %s GUID from " - "base, wraps to OUI!\n", - ipath_get_unit_name(t)); - dd->ipath_guid = 0; - goto bail; - } - bguid[5]++; - } - bguid[6]++; - } - dd->ipath_nguid = 1; - - ipath_dbg("nguid %u, so adding %u to device 0 guid, " - "for %llx\n", - dd0->ipath_nguid, t, - (unsigned long long) be64_to_cpu(dd->ipath_guid)); - goto bail; - } - - /* - * read full flash, not just currently used part, since it may have - * been written with a newer definition - * */ - len = sizeof(struct ipath_flash); - buf = vmalloc(len); - if (!buf) { - ipath_dev_err(dd, "Couldn't allocate memory to read %u " - "bytes from eeprom for GUID\n", len); - goto bail; - } - - mutex_lock(&dd->ipath_eep_lock); - eep_stat = ipath_eeprom_internal_read(dd, 0, buf, len); - mutex_unlock(&dd->ipath_eep_lock); - - if (eep_stat) { - ipath_dev_err(dd, "Failed reading GUID from eeprom\n"); - goto done; - } - ifp = (struct ipath_flash *)buf; - - csum = flash_csum(ifp, 0); - if (csum != ifp->if_csum) { - dev_info(&dd->pcidev->dev, "Bad I2C flash checksum: " - "0x%x, not 0x%x\n", csum, ifp->if_csum); - goto done; - } - if (*(__be64 *) ifp->if_guid == cpu_to_be64(0) || - *(__be64 *) ifp->if_guid == ~cpu_to_be64(0)) { - ipath_dev_err(dd, "Invalid GUID %llx from flash; " - "ignoring\n", - *(unsigned long long *) ifp->if_guid); - /* don't allow GUID if all 0 or all 1's */ - goto done; - } - - /* complain, but allow it */ - if (*(u64 *) ifp->if_guid == 0x100007511000000ULL) - dev_info(&dd->pcidev->dev, "Warning, GUID %llx is " - "default, probably not correct!\n", - *(unsigned long long *) ifp->if_guid); - - bguid = ifp->if_guid; - if (!bguid[0] && !bguid[1] && !bguid[2]) { - /* original incorrect GUID format in flash; fix in - * core copy, by shifting up 2 octets; don't need to - * change top octet, since both it and shifted are - * 0.. */ - bguid[1] = bguid[3]; - bguid[2] = bguid[4]; - bguid[3] = bguid[4] = 0; - guid = *(__be64 *) ifp->if_guid; - ipath_cdbg(VERBOSE, "Old GUID format in flash, top 3 zero, " - "shifting 2 octets\n"); - } else - guid = *(__be64 *) ifp->if_guid; - dd->ipath_guid = guid; - dd->ipath_nguid = ifp->if_numguid; - /* - * Things are slightly complicated by the desire to transparently - * support both the Pathscale 10-digit serial number and the QLogic - * 13-character version. - */ - if ((ifp->if_fversion > 1) && ifp->if_sprefix[0] - && ((u8 *)ifp->if_sprefix)[0] != 0xFF) { - /* This board has a Serial-prefix, which is stored - * elsewhere for backward-compatibility. - */ - char *snp = dd->ipath_serial; - memcpy(snp, ifp->if_sprefix, sizeof ifp->if_sprefix); - snp[sizeof ifp->if_sprefix] = '\0'; - len = strlen(snp); - snp += len; - len = (sizeof dd->ipath_serial) - len; - if (len > sizeof ifp->if_serial) { - len = sizeof ifp->if_serial; - } - memcpy(snp, ifp->if_serial, len); - } else - memcpy(dd->ipath_serial, ifp->if_serial, - sizeof ifp->if_serial); - if (!strstr(ifp->if_comment, "Tested successfully")) - ipath_dev_err(dd, "Board SN %s did not pass functional " - "test: %s\n", dd->ipath_serial, - ifp->if_comment); - - ipath_cdbg(VERBOSE, "Initted GUID to %llx from eeprom\n", - (unsigned long long) be64_to_cpu(dd->ipath_guid)); - - memcpy(&dd->ipath_eep_st_errs, &ifp->if_errcntp, IPATH_EEP_LOG_CNT); - /* - * Power-on (actually "active") hours are kept as little-endian value - * in EEPROM, but as seconds in a (possibly as small as 24-bit) - * atomic_t while running. - */ - atomic_set(&dd->ipath_active_time, 0); - dd->ipath_eep_hrs = ifp->if_powerhour[0] | (ifp->if_powerhour[1] << 8); - -done: - vfree(buf); - -bail:; -} - -/** - * ipath_update_eeprom_log - copy active-time and error counters to eeprom - * @dd: the infinipath device - * - * Although the time is kept as seconds in the ipath_devdata struct, it is - * rounded to hours for re-write, as we have only 16 bits in EEPROM. - * First-cut code reads whole (expected) struct ipath_flash, modifies, - * re-writes. Future direction: read/write only what we need, assuming - * that the EEPROM had to have been "good enough" for driver init, and - * if not, we aren't making it worse. - * - */ - -int ipath_update_eeprom_log(struct ipath_devdata *dd) -{ - void *buf; - struct ipath_flash *ifp; - int len, hi_water; - uint32_t new_time, new_hrs; - u8 csum; - int ret, idx; - unsigned long flags; - - /* first, check if we actually need to do anything. */ - ret = 0; - for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) { - if (dd->ipath_eep_st_new_errs[idx]) { - ret = 1; - break; - } - } - new_time = atomic_read(&dd->ipath_active_time); - - if (ret == 0 && new_time < 3600) - return 0; - - /* - * The quick-check above determined that there is something worthy - * of logging, so get current contents and do a more detailed idea. - * read full flash, not just currently used part, since it may have - * been written with a newer definition - */ - len = sizeof(struct ipath_flash); - buf = vmalloc(len); - ret = 1; - if (!buf) { - ipath_dev_err(dd, "Couldn't allocate memory to read %u " - "bytes from eeprom for logging\n", len); - goto bail; - } - - /* Grab semaphore and read current EEPROM. If we get an - * error, let go, but if not, keep it until we finish write. - */ - ret = mutex_lock_interruptible(&dd->ipath_eep_lock); - if (ret) { - ipath_dev_err(dd, "Unable to acquire EEPROM for logging\n"); - goto free_bail; - } - ret = ipath_eeprom_internal_read(dd, 0, buf, len); - if (ret) { - mutex_unlock(&dd->ipath_eep_lock); - ipath_dev_err(dd, "Unable read EEPROM for logging\n"); - goto free_bail; - } - ifp = (struct ipath_flash *)buf; - - csum = flash_csum(ifp, 0); - if (csum != ifp->if_csum) { - mutex_unlock(&dd->ipath_eep_lock); - ipath_dev_err(dd, "EEPROM cks err (0x%02X, S/B 0x%02X)\n", - csum, ifp->if_csum); - ret = 1; - goto free_bail; - } - hi_water = 0; - spin_lock_irqsave(&dd->ipath_eep_st_lock, flags); - for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) { - int new_val = dd->ipath_eep_st_new_errs[idx]; - if (new_val) { - /* - * If we have seen any errors, add to EEPROM values - * We need to saturate at 0xFF (255) and we also - * would need to adjust the checksum if we were - * trying to minimize EEPROM traffic - * Note that we add to actual current count in EEPROM, - * in case it was altered while we were running. - */ - new_val += ifp->if_errcntp[idx]; - if (new_val > 0xFF) - new_val = 0xFF; - if (ifp->if_errcntp[idx] != new_val) { - ifp->if_errcntp[idx] = new_val; - hi_water = offsetof(struct ipath_flash, - if_errcntp) + idx; - } - /* - * update our shadow (used to minimize EEPROM - * traffic), to match what we are about to write. - */ - dd->ipath_eep_st_errs[idx] = new_val; - dd->ipath_eep_st_new_errs[idx] = 0; - } - } - /* - * now update active-time. We would like to round to the nearest hour - * but unless atomic_t are sure to be proper signed ints we cannot, - * because we need to account for what we "transfer" to EEPROM and - * if we log an hour at 31 minutes, then we would need to set - * active_time to -29 to accurately count the _next_ hour. - */ - if (new_time >= 3600) { - new_hrs = new_time / 3600; - atomic_sub((new_hrs * 3600), &dd->ipath_active_time); - new_hrs += dd->ipath_eep_hrs; - if (new_hrs > 0xFFFF) - new_hrs = 0xFFFF; - dd->ipath_eep_hrs = new_hrs; - if ((new_hrs & 0xFF) != ifp->if_powerhour[0]) { - ifp->if_powerhour[0] = new_hrs & 0xFF; - hi_water = offsetof(struct ipath_flash, if_powerhour); - } - if ((new_hrs >> 8) != ifp->if_powerhour[1]) { - ifp->if_powerhour[1] = new_hrs >> 8; - hi_water = offsetof(struct ipath_flash, if_powerhour) - + 1; - } - } - /* - * There is a tiny possibility that we could somehow fail to write - * the EEPROM after updating our shadows, but problems from holding - * the spinlock too long are a much bigger issue. - */ - spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags); - if (hi_water) { - /* we made some change to the data, uopdate cksum and write */ - csum = flash_csum(ifp, 1); - ret = ipath_eeprom_internal_write(dd, 0, buf, hi_water + 1); - } - mutex_unlock(&dd->ipath_eep_lock); - if (ret) - ipath_dev_err(dd, "Failed updating EEPROM\n"); - -free_bail: - vfree(buf); -bail: - return ret; - -} - -/** - * ipath_inc_eeprom_err - increment one of the four error counters - * that are logged to EEPROM. - * @dd: the infinipath device - * @eidx: 0..3, the counter to increment - * @incr: how much to add - * - * Each counter is 8-bits, and saturates at 255 (0xFF). They - * are copied to the EEPROM (aka flash) whenever ipath_update_eeprom_log() - * is called, but it can only be called in a context that allows sleep. - * This function can be called even at interrupt level. - */ - -void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr) -{ - uint new_val; - unsigned long flags; - - spin_lock_irqsave(&dd->ipath_eep_st_lock, flags); - new_val = dd->ipath_eep_st_new_errs[eidx] + incr; - if (new_val > 255) - new_val = 255; - dd->ipath_eep_st_new_errs[eidx] = new_val; - spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags); - return; -} - -static int ipath_tempsense_internal_read(struct ipath_devdata *dd, u8 regnum) -{ - int ret; - struct i2c_chain_desc *icd; - - ret = -ENOENT; - - icd = ipath_i2c_type(dd); - if (!icd) - goto bail; - - if (icd->temp_dev == IPATH_NO_DEV) { - /* tempsense only exists on new, real-I2C boards */ - ret = -ENXIO; - goto bail; - } - - if (i2c_startcmd(dd, icd->temp_dev | WRITE_CMD)) { - ipath_dbg("Failed tempsense startcmd\n"); - stop_cmd(dd); - ret = -ENXIO; - goto bail; - } - ret = wr_byte(dd, regnum); - stop_cmd(dd); - if (ret) { - ipath_dev_err(dd, "Failed tempsense WR command %02X\n", - regnum); - ret = -ENXIO; - goto bail; - } - if (i2c_startcmd(dd, icd->temp_dev | READ_CMD)) { - ipath_dbg("Failed tempsense RD startcmd\n"); - stop_cmd(dd); - ret = -ENXIO; - goto bail; - } - /* - * We can only clock out one byte per command, sensibly - */ - ret = rd_byte(dd); - stop_cmd(dd); - -bail: - return ret; -} - -#define VALID_TS_RD_REG_MASK 0xBF - -/** - * ipath_tempsense_read - read register of temp sensor via I2C - * @dd: the infinipath device - * @regnum: register to read from - * - * returns reg contents (0..255) or < 0 for error - */ -int ipath_tempsense_read(struct ipath_devdata *dd, u8 regnum) -{ - int ret; - - if (regnum > 7) - return -EINVAL; - - /* return a bogus value for (the one) register we do not have */ - if (!((1 << regnum) & VALID_TS_RD_REG_MASK)) - return 0; - - ret = mutex_lock_interruptible(&dd->ipath_eep_lock); - if (!ret) { - ret = ipath_tempsense_internal_read(dd, regnum); - mutex_unlock(&dd->ipath_eep_lock); - } - - /* - * There are three possibilities here: - * ret is actual value (0..255) - * ret is -ENXIO or -EINVAL from code in this file - * ret is -EINTR from mutex_lock_interruptible. - */ - return ret; -} - -static int ipath_tempsense_internal_write(struct ipath_devdata *dd, - u8 regnum, u8 data) -{ - int ret = -ENOENT; - struct i2c_chain_desc *icd; - - icd = ipath_i2c_type(dd); - if (!icd) - goto bail; - - if (icd->temp_dev == IPATH_NO_DEV) { - /* tempsense only exists on new, real-I2C boards */ - ret = -ENXIO; - goto bail; - } - if (i2c_startcmd(dd, icd->temp_dev | WRITE_CMD)) { - ipath_dbg("Failed tempsense startcmd\n"); - stop_cmd(dd); - ret = -ENXIO; - goto bail; - } - ret = wr_byte(dd, regnum); - if (ret) { - stop_cmd(dd); - ipath_dev_err(dd, "Failed to write tempsense command %02X\n", - regnum); - ret = -ENXIO; - goto bail; - } - ret = wr_byte(dd, data); - stop_cmd(dd); - ret = i2c_startcmd(dd, icd->temp_dev | READ_CMD); - if (ret) { - ipath_dev_err(dd, "Failed tempsense data wrt to %02X\n", - regnum); - ret = -ENXIO; - } - -bail: - return ret; -} - -#define VALID_TS_WR_REG_MASK ((1 << 9) | (1 << 0xB) | (1 << 0xD)) - -/** - * ipath_tempsense_write - write register of temp sensor via I2C - * @dd: the infinipath device - * @regnum: register to write - * @data: data to write - * - * returns 0 for success or < 0 for error - */ -int ipath_tempsense_write(struct ipath_devdata *dd, u8 regnum, u8 data) -{ - int ret; - - if (regnum > 15 || !((1 << regnum) & VALID_TS_WR_REG_MASK)) - return -EINVAL; - - ret = mutex_lock_interruptible(&dd->ipath_eep_lock); - if (!ret) { - ret = ipath_tempsense_internal_write(dd, regnum, data); - mutex_unlock(&dd->ipath_eep_lock); - } - - /* - * There are three possibilities here: - * ret is 0 for success - * ret is -ENXIO or -EINVAL from code in this file - * ret is -EINTR from mutex_lock_interruptible. - */ - return ret; -} diff --git a/drivers/staging/rdma/ipath/ipath_file_ops.c b/drivers/staging/rdma/ipath/ipath_file_ops.c deleted file mode 100644 index 6187b848b3ca..000000000000 --- a/drivers/staging/rdma/ipath/ipath_file_ops.c +++ /dev/null @@ -1,2619 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ipath_kernel.h" -#include "ipath_common.h" -#include "ipath_user_sdma.h" - -static int ipath_open(struct inode *, struct file *); -static int ipath_close(struct inode *, struct file *); -static ssize_t ipath_write(struct file *, const char __user *, size_t, - loff_t *); -static ssize_t ipath_write_iter(struct kiocb *, struct iov_iter *from); -static unsigned int ipath_poll(struct file *, struct poll_table_struct *); -static int ipath_mmap(struct file *, struct vm_area_struct *); - -/* - * This is really, really weird shit - write() and writev() here - * have completely unrelated semantics. Sucky userland ABI, - * film at 11. - */ -static const struct file_operations ipath_file_ops = { - .owner = THIS_MODULE, - .write = ipath_write, - .write_iter = ipath_write_iter, - .open = ipath_open, - .release = ipath_close, - .poll = ipath_poll, - .mmap = ipath_mmap, - .llseek = noop_llseek, -}; - -/* - * Convert kernel virtual addresses to physical addresses so they don't - * potentially conflict with the chip addresses used as mmap offsets. - * It doesn't really matter what mmap offset we use as long as we can - * interpret it correctly. - */ -static u64 cvt_kvaddr(void *p) -{ - struct page *page; - u64 paddr = 0; - - page = vmalloc_to_page(p); - if (page) - paddr = page_to_pfn(page) << PAGE_SHIFT; - - return paddr; -} - -static int ipath_get_base_info(struct file *fp, - void __user *ubase, size_t ubase_size) -{ - struct ipath_portdata *pd = port_fp(fp); - int ret = 0; - struct ipath_base_info *kinfo = NULL; - struct ipath_devdata *dd = pd->port_dd; - unsigned subport_cnt; - int shared, master; - size_t sz; - - subport_cnt = pd->port_subport_cnt; - if (!subport_cnt) { - shared = 0; - master = 0; - subport_cnt = 1; - } else { - shared = 1; - master = !subport_fp(fp); - } - - sz = sizeof(*kinfo); - /* If port sharing is not requested, allow the old size structure */ - if (!shared) - sz -= 7 * sizeof(u64); - if (ubase_size < sz) { - ipath_cdbg(PROC, - "Base size %zu, need %zu (version mismatch?)\n", - ubase_size, sz); - ret = -EINVAL; - goto bail; - } - - kinfo = kzalloc(sizeof(*kinfo), GFP_KERNEL); - if (kinfo == NULL) { - ret = -ENOMEM; - goto bail; - } - - ret = dd->ipath_f_get_base_info(pd, kinfo); - if (ret < 0) - goto bail; - - kinfo->spi_rcvhdr_cnt = dd->ipath_rcvhdrcnt; - kinfo->spi_rcvhdrent_size = dd->ipath_rcvhdrentsize; - kinfo->spi_tidegrcnt = dd->ipath_rcvegrcnt; - kinfo->spi_rcv_egrbufsize = dd->ipath_rcvegrbufsize; - /* - * have to mmap whole thing - */ - kinfo->spi_rcv_egrbuftotlen = - pd->port_rcvegrbuf_chunks * pd->port_rcvegrbuf_size; - kinfo->spi_rcv_egrperchunk = pd->port_rcvegrbufs_perchunk; - kinfo->spi_rcv_egrchunksize = kinfo->spi_rcv_egrbuftotlen / - pd->port_rcvegrbuf_chunks; - kinfo->spi_tidcnt = dd->ipath_rcvtidcnt / subport_cnt; - if (master) - kinfo->spi_tidcnt += dd->ipath_rcvtidcnt % subport_cnt; - /* - * for this use, may be ipath_cfgports summed over all chips that - * are are configured and present - */ - kinfo->spi_nports = dd->ipath_cfgports; - /* unit (chip/board) our port is on */ - kinfo->spi_unit = dd->ipath_unit; - /* for now, only a single page */ - kinfo->spi_tid_maxsize = PAGE_SIZE; - - /* - * Doing this per port, and based on the skip value, etc. This has - * to be the actual buffer size, since the protocol code treats it - * as an array. - * - * These have to be set to user addresses in the user code via mmap. - * These values are used on return to user code for the mmap target - * addresses only. For 32 bit, same 44 bit address problem, so use - * the physical address, not virtual. Before 2.6.11, using the - * page_address() macro worked, but in 2.6.11, even that returns the - * full 64 bit address (upper bits all 1's). So far, using the - * physical addresses (or chip offsets, for chip mapping) works, but - * no doubt some future kernel release will change that, and we'll be - * on to yet another method of dealing with this. - */ - kinfo->spi_rcvhdr_base = (u64) pd->port_rcvhdrq_phys; - kinfo->spi_rcvhdr_tailaddr = (u64) pd->port_rcvhdrqtailaddr_phys; - kinfo->spi_rcv_egrbufs = (u64) pd->port_rcvegr_phys; - kinfo->spi_pioavailaddr = (u64) dd->ipath_pioavailregs_phys; - kinfo->spi_status = (u64) kinfo->spi_pioavailaddr + - (void *) dd->ipath_statusp - - (void *) dd->ipath_pioavailregs_dma; - if (!shared) { - kinfo->spi_piocnt = pd->port_piocnt; - kinfo->spi_piobufbase = (u64) pd->port_piobufs; - kinfo->__spi_uregbase = (u64) dd->ipath_uregbase + - dd->ipath_ureg_align * pd->port_port; - } else if (master) { - kinfo->spi_piocnt = (pd->port_piocnt / subport_cnt) + - (pd->port_piocnt % subport_cnt); - /* Master's PIO buffers are after all the slave's */ - kinfo->spi_piobufbase = (u64) pd->port_piobufs + - dd->ipath_palign * - (pd->port_piocnt - kinfo->spi_piocnt); - } else { - unsigned slave = subport_fp(fp) - 1; - - kinfo->spi_piocnt = pd->port_piocnt / subport_cnt; - kinfo->spi_piobufbase = (u64) pd->port_piobufs + - dd->ipath_palign * kinfo->spi_piocnt * slave; - } - - if (shared) { - kinfo->spi_port_uregbase = (u64) dd->ipath_uregbase + - dd->ipath_ureg_align * pd->port_port; - kinfo->spi_port_rcvegrbuf = kinfo->spi_rcv_egrbufs; - kinfo->spi_port_rcvhdr_base = kinfo->spi_rcvhdr_base; - kinfo->spi_port_rcvhdr_tailaddr = kinfo->spi_rcvhdr_tailaddr; - - kinfo->__spi_uregbase = cvt_kvaddr(pd->subport_uregbase + - PAGE_SIZE * subport_fp(fp)); - - kinfo->spi_rcvhdr_base = cvt_kvaddr(pd->subport_rcvhdr_base + - pd->port_rcvhdrq_size * subport_fp(fp)); - kinfo->spi_rcvhdr_tailaddr = 0; - kinfo->spi_rcv_egrbufs = cvt_kvaddr(pd->subport_rcvegrbuf + - pd->port_rcvegrbuf_chunks * pd->port_rcvegrbuf_size * - subport_fp(fp)); - - kinfo->spi_subport_uregbase = - cvt_kvaddr(pd->subport_uregbase); - kinfo->spi_subport_rcvegrbuf = - cvt_kvaddr(pd->subport_rcvegrbuf); - kinfo->spi_subport_rcvhdr_base = - cvt_kvaddr(pd->subport_rcvhdr_base); - ipath_cdbg(PROC, "port %u flags %x %llx %llx %llx\n", - kinfo->spi_port, kinfo->spi_runtime_flags, - (unsigned long long) kinfo->spi_subport_uregbase, - (unsigned long long) kinfo->spi_subport_rcvegrbuf, - (unsigned long long) kinfo->spi_subport_rcvhdr_base); - } - - /* - * All user buffers are 2KB buffers. If we ever support - * giving 4KB buffers to user processes, this will need some - * work. - */ - kinfo->spi_pioindex = (kinfo->spi_piobufbase - - (dd->ipath_piobufbase & 0xffffffff)) / dd->ipath_palign; - kinfo->spi_pioalign = dd->ipath_palign; - - kinfo->spi_qpair = IPATH_KD_QP; - /* - * user mode PIO buffers are always 2KB, even when 4KB can - * be received, and sent via the kernel; this is ibmaxlen - * for 2K MTU. - */ - kinfo->spi_piosize = dd->ipath_piosize2k - 2 * sizeof(u32); - kinfo->spi_mtu = dd->ipath_ibmaxlen; /* maxlen, not ibmtu */ - kinfo->spi_port = pd->port_port; - kinfo->spi_subport = subport_fp(fp); - kinfo->spi_sw_version = IPATH_KERN_SWVERSION; - kinfo->spi_hw_version = dd->ipath_revision; - - if (master) { - kinfo->spi_runtime_flags |= IPATH_RUNTIME_MASTER; - } - - sz = (ubase_size < sizeof(*kinfo)) ? ubase_size : sizeof(*kinfo); - if (copy_to_user(ubase, kinfo, sz)) - ret = -EFAULT; - -bail: - kfree(kinfo); - return ret; -} - -/** - * ipath_tid_update - update a port TID - * @pd: the port - * @fp: the ipath device file - * @ti: the TID information - * - * The new implementation as of Oct 2004 is that the driver assigns - * the tid and returns it to the caller. To make it easier to - * catch bugs, and to reduce search time, we keep a cursor for - * each port, walking the shadow tid array to find one that's not - * in use. - * - * For now, if we can't allocate the full list, we fail, although - * in the long run, we'll allocate as many as we can, and the - * caller will deal with that by trying the remaining pages later. - * That means that when we fail, we have to mark the tids as not in - * use again, in our shadow copy. - * - * It's up to the caller to free the tids when they are done. - * We'll unlock the pages as they free them. - * - * Also, right now we are locking one page at a time, but since - * the intended use of this routine is for a single group of - * virtually contiguous pages, that should change to improve - * performance. - */ -static int ipath_tid_update(struct ipath_portdata *pd, struct file *fp, - const struct ipath_tid_info *ti) -{ - int ret = 0, ntids; - u32 tid, porttid, cnt, i, tidcnt, tidoff; - u16 *tidlist; - struct ipath_devdata *dd = pd->port_dd; - u64 physaddr; - unsigned long vaddr; - u64 __iomem *tidbase; - unsigned long tidmap[8]; - struct page **pagep = NULL; - unsigned subport = subport_fp(fp); - - if (!dd->ipath_pageshadow) { - ret = -ENOMEM; - goto done; - } - - cnt = ti->tidcnt; - if (!cnt) { - ipath_dbg("After copyin, tidcnt 0, tidlist %llx\n", - (unsigned long long) ti->tidlist); - /* - * Should we treat as success? likely a bug - */ - ret = -EFAULT; - goto done; - } - porttid = pd->port_port * dd->ipath_rcvtidcnt; - if (!pd->port_subport_cnt) { - tidcnt = dd->ipath_rcvtidcnt; - tid = pd->port_tidcursor; - tidoff = 0; - } else if (!subport) { - tidcnt = (dd->ipath_rcvtidcnt / pd->port_subport_cnt) + - (dd->ipath_rcvtidcnt % pd->port_subport_cnt); - tidoff = dd->ipath_rcvtidcnt - tidcnt; - porttid += tidoff; - tid = tidcursor_fp(fp); - } else { - tidcnt = dd->ipath_rcvtidcnt / pd->port_subport_cnt; - tidoff = tidcnt * (subport - 1); - porttid += tidoff; - tid = tidcursor_fp(fp); - } - if (cnt > tidcnt) { - /* make sure it all fits in port_tid_pg_list */ - dev_info(&dd->pcidev->dev, "Process tried to allocate %u " - "TIDs, only trying max (%u)\n", cnt, tidcnt); - cnt = tidcnt; - } - pagep = &((struct page **) pd->port_tid_pg_list)[tidoff]; - tidlist = &((u16 *) &pagep[dd->ipath_rcvtidcnt])[tidoff]; - - memset(tidmap, 0, sizeof(tidmap)); - /* before decrement; chip actual # */ - ntids = tidcnt; - tidbase = (u64 __iomem *) (((char __iomem *) dd->ipath_kregbase) + - dd->ipath_rcvtidbase + - porttid * sizeof(*tidbase)); - - ipath_cdbg(VERBOSE, "Port%u %u tids, cursor %u, tidbase %p\n", - pd->port_port, cnt, tid, tidbase); - - /* virtual address of first page in transfer */ - vaddr = ti->tidvaddr; - if (!access_ok(VERIFY_WRITE, (void __user *) vaddr, - cnt * PAGE_SIZE)) { - ipath_dbg("Fail vaddr %p, %u pages, !access_ok\n", - (void *)vaddr, cnt); - ret = -EFAULT; - goto done; - } - ret = ipath_get_user_pages(vaddr, cnt, pagep); - if (ret) { - if (ret == -EBUSY) { - ipath_dbg("Failed to lock addr %p, %u pages " - "(already locked)\n", - (void *) vaddr, cnt); - /* - * for now, continue, and see what happens but with - * the new implementation, this should never happen, - * unless perhaps the user has mpin'ed the pages - * themselves (something we need to test) - */ - ret = 0; - } else { - dev_info(&dd->pcidev->dev, - "Failed to lock addr %p, %u pages: " - "errno %d\n", (void *) vaddr, cnt, -ret); - goto done; - } - } - for (i = 0; i < cnt; i++, vaddr += PAGE_SIZE) { - for (; ntids--; tid++) { - if (tid == tidcnt) - tid = 0; - if (!dd->ipath_pageshadow[porttid + tid]) - break; - } - if (ntids < 0) { - /* - * oops, wrapped all the way through their TIDs, - * and didn't have enough free; see comments at - * start of routine - */ - ipath_dbg("Not enough free TIDs for %u pages " - "(index %d), failing\n", cnt, i); - i--; /* last tidlist[i] not filled in */ - ret = -ENOMEM; - break; - } - tidlist[i] = tid + tidoff; - ipath_cdbg(VERBOSE, "Updating idx %u to TID %u, " - "vaddr %lx\n", i, tid + tidoff, vaddr); - /* we "know" system pages and TID pages are same size */ - dd->ipath_pageshadow[porttid + tid] = pagep[i]; - dd->ipath_physshadow[porttid + tid] = ipath_map_page( - dd->pcidev, pagep[i], 0, PAGE_SIZE, - PCI_DMA_FROMDEVICE); - /* - * don't need atomic or it's overhead - */ - __set_bit(tid, tidmap); - physaddr = dd->ipath_physshadow[porttid + tid]; - ipath_stats.sps_pagelocks++; - ipath_cdbg(VERBOSE, - "TID %u, vaddr %lx, physaddr %llx pgp %p\n", - tid, vaddr, (unsigned long long) physaddr, - pagep[i]); - dd->ipath_f_put_tid(dd, &tidbase[tid], RCVHQ_RCV_TYPE_EXPECTED, - physaddr); - /* - * don't check this tid in ipath_portshadow, since we - * just filled it in; start with the next one. - */ - tid++; - } - - if (ret) { - u32 limit; - cleanup: - /* jump here if copy out of updated info failed... */ - ipath_dbg("After failure (ret=%d), undo %d of %d entries\n", - -ret, i, cnt); - /* same code that's in ipath_free_tid() */ - limit = sizeof(tidmap) * BITS_PER_BYTE; - if (limit > tidcnt) - /* just in case size changes in future */ - limit = tidcnt; - tid = find_first_bit((const unsigned long *)tidmap, limit); - for (; tid < limit; tid++) { - if (!test_bit(tid, tidmap)) - continue; - if (dd->ipath_pageshadow[porttid + tid]) { - ipath_cdbg(VERBOSE, "Freeing TID %u\n", - tid); - dd->ipath_f_put_tid(dd, &tidbase[tid], - RCVHQ_RCV_TYPE_EXPECTED, - dd->ipath_tidinvalid); - pci_unmap_page(dd->pcidev, - dd->ipath_physshadow[porttid + tid], - PAGE_SIZE, PCI_DMA_FROMDEVICE); - dd->ipath_pageshadow[porttid + tid] = NULL; - ipath_stats.sps_pageunlocks++; - } - } - ipath_release_user_pages(pagep, cnt); - } else { - /* - * Copy the updated array, with ipath_tid's filled in, back - * to user. Since we did the copy in already, this "should - * never fail" If it does, we have to clean up... - */ - if (copy_to_user((void __user *) - (unsigned long) ti->tidlist, - tidlist, cnt * sizeof(*tidlist))) { - ret = -EFAULT; - goto cleanup; - } - if (copy_to_user((void __user *) (unsigned long) ti->tidmap, - tidmap, sizeof tidmap)) { - ret = -EFAULT; - goto cleanup; - } - if (tid == tidcnt) - tid = 0; - if (!pd->port_subport_cnt) - pd->port_tidcursor = tid; - else - tidcursor_fp(fp) = tid; - } - -done: - if (ret) - ipath_dbg("Failed to map %u TID pages, failing with %d\n", - ti->tidcnt, -ret); - return ret; -} - -/** - * ipath_tid_free - free a port TID - * @pd: the port - * @subport: the subport - * @ti: the TID info - * - * right now we are unlocking one page at a time, but since - * the intended use of this routine is for a single group of - * virtually contiguous pages, that should change to improve - * performance. We check that the TID is in range for this port - * but otherwise don't check validity; if user has an error and - * frees the wrong tid, it's only their own data that can thereby - * be corrupted. We do check that the TID was in use, for sanity - * We always use our idea of the saved address, not the address that - * they pass in to us. - */ - -static int ipath_tid_free(struct ipath_portdata *pd, unsigned subport, - const struct ipath_tid_info *ti) -{ - int ret = 0; - u32 tid, porttid, cnt, limit, tidcnt; - struct ipath_devdata *dd = pd->port_dd; - u64 __iomem *tidbase; - unsigned long tidmap[8]; - - if (!dd->ipath_pageshadow) { - ret = -ENOMEM; - goto done; - } - - if (copy_from_user(tidmap, (void __user *)(unsigned long)ti->tidmap, - sizeof tidmap)) { - ret = -EFAULT; - goto done; - } - - porttid = pd->port_port * dd->ipath_rcvtidcnt; - if (!pd->port_subport_cnt) - tidcnt = dd->ipath_rcvtidcnt; - else if (!subport) { - tidcnt = (dd->ipath_rcvtidcnt / pd->port_subport_cnt) + - (dd->ipath_rcvtidcnt % pd->port_subport_cnt); - porttid += dd->ipath_rcvtidcnt - tidcnt; - } else { - tidcnt = dd->ipath_rcvtidcnt / pd->port_subport_cnt; - porttid += tidcnt * (subport - 1); - } - tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) + - dd->ipath_rcvtidbase + - porttid * sizeof(*tidbase)); - - limit = sizeof(tidmap) * BITS_PER_BYTE; - if (limit > tidcnt) - /* just in case size changes in future */ - limit = tidcnt; - tid = find_first_bit(tidmap, limit); - ipath_cdbg(VERBOSE, "Port%u free %u tids; first bit (max=%d) " - "set is %d, porttid %u\n", pd->port_port, ti->tidcnt, - limit, tid, porttid); - for (cnt = 0; tid < limit; tid++) { - /* - * small optimization; if we detect a run of 3 or so without - * any set, use find_first_bit again. That's mainly to - * accelerate the case where we wrapped, so we have some at - * the beginning, and some at the end, and a big gap - * in the middle. - */ - if (!test_bit(tid, tidmap)) - continue; - cnt++; - if (dd->ipath_pageshadow[porttid + tid]) { - struct page *p; - p = dd->ipath_pageshadow[porttid + tid]; - dd->ipath_pageshadow[porttid + tid] = NULL; - ipath_cdbg(VERBOSE, "PID %u freeing TID %u\n", - pid_nr(pd->port_pid), tid); - dd->ipath_f_put_tid(dd, &tidbase[tid], - RCVHQ_RCV_TYPE_EXPECTED, - dd->ipath_tidinvalid); - pci_unmap_page(dd->pcidev, - dd->ipath_physshadow[porttid + tid], - PAGE_SIZE, PCI_DMA_FROMDEVICE); - ipath_release_user_pages(&p, 1); - ipath_stats.sps_pageunlocks++; - } else - ipath_dbg("Unused tid %u, ignoring\n", tid); - } - if (cnt != ti->tidcnt) - ipath_dbg("passed in tidcnt %d, only %d bits set in map\n", - ti->tidcnt, cnt); -done: - if (ret) - ipath_dbg("Failed to unmap %u TID pages, failing with %d\n", - ti->tidcnt, -ret); - return ret; -} - -/** - * ipath_set_part_key - set a partition key - * @pd: the port - * @key: the key - * - * We can have up to 4 active at a time (other than the default, which is - * always allowed). This is somewhat tricky, since multiple ports may set - * the same key, so we reference count them, and clean up at exit. All 4 - * partition keys are packed into a single infinipath register. It's an - * error for a process to set the same pkey multiple times. We provide no - * mechanism to de-allocate a pkey at this time, we may eventually need to - * do that. I've used the atomic operations, and no locking, and only make - * a single pass through what's available. This should be more than - * adequate for some time. I'll think about spinlocks or the like if and as - * it's necessary. - */ -static int ipath_set_part_key(struct ipath_portdata *pd, u16 key) -{ - struct ipath_devdata *dd = pd->port_dd; - int i, any = 0, pidx = -1; - u16 lkey = key & 0x7FFF; - int ret; - - if (lkey == (IPATH_DEFAULT_P_KEY & 0x7FFF)) { - /* nothing to do; this key always valid */ - ret = 0; - goto bail; - } - - ipath_cdbg(VERBOSE, "p%u try to set pkey %hx, current keys " - "%hx:%x %hx:%x %hx:%x %hx:%x\n", - pd->port_port, key, dd->ipath_pkeys[0], - atomic_read(&dd->ipath_pkeyrefs[0]), dd->ipath_pkeys[1], - atomic_read(&dd->ipath_pkeyrefs[1]), dd->ipath_pkeys[2], - atomic_read(&dd->ipath_pkeyrefs[2]), dd->ipath_pkeys[3], - atomic_read(&dd->ipath_pkeyrefs[3])); - - if (!lkey) { - ipath_cdbg(PROC, "p%u tries to set key 0, not allowed\n", - pd->port_port); - ret = -EINVAL; - goto bail; - } - - /* - * Set the full membership bit, because it has to be - * set in the register or the packet, and it seems - * cleaner to set in the register than to force all - * callers to set it. (see bug 4331) - */ - key |= 0x8000; - - for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) { - if (!pd->port_pkeys[i] && pidx == -1) - pidx = i; - if (pd->port_pkeys[i] == key) { - ipath_cdbg(VERBOSE, "p%u tries to set same pkey " - "(%x) more than once\n", - pd->port_port, key); - ret = -EEXIST; - goto bail; - } - } - if (pidx == -1) { - ipath_dbg("All pkeys for port %u already in use, " - "can't set %x\n", pd->port_port, key); - ret = -EBUSY; - goto bail; - } - for (any = i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) { - if (!dd->ipath_pkeys[i]) { - any++; - continue; - } - if (dd->ipath_pkeys[i] == key) { - atomic_t *pkrefs = &dd->ipath_pkeyrefs[i]; - - if (atomic_inc_return(pkrefs) > 1) { - pd->port_pkeys[pidx] = key; - ipath_cdbg(VERBOSE, "p%u set key %x " - "matches #%d, count now %d\n", - pd->port_port, key, i, - atomic_read(pkrefs)); - ret = 0; - goto bail; - } else { - /* - * lost race, decrement count, catch below - */ - atomic_dec(pkrefs); - ipath_cdbg(VERBOSE, "Lost race, count was " - "0, after dec, it's %d\n", - atomic_read(pkrefs)); - any++; - } - } - if ((dd->ipath_pkeys[i] & 0x7FFF) == lkey) { - /* - * It makes no sense to have both the limited and - * full membership PKEY set at the same time since - * the unlimited one will disable the limited one. - */ - ret = -EEXIST; - goto bail; - } - } - if (!any) { - ipath_dbg("port %u, all pkeys already in use, " - "can't set %x\n", pd->port_port, key); - ret = -EBUSY; - goto bail; - } - for (any = i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) { - if (!dd->ipath_pkeys[i] && - atomic_inc_return(&dd->ipath_pkeyrefs[i]) == 1) { - u64 pkey; - - /* for ipathstats, etc. */ - ipath_stats.sps_pkeys[i] = lkey; - pd->port_pkeys[pidx] = dd->ipath_pkeys[i] = key; - pkey = - (u64) dd->ipath_pkeys[0] | - ((u64) dd->ipath_pkeys[1] << 16) | - ((u64) dd->ipath_pkeys[2] << 32) | - ((u64) dd->ipath_pkeys[3] << 48); - ipath_cdbg(PROC, "p%u set key %x in #%d, " - "portidx %d, new pkey reg %llx\n", - pd->port_port, key, i, pidx, - (unsigned long long) pkey); - ipath_write_kreg( - dd, dd->ipath_kregs->kr_partitionkey, pkey); - - ret = 0; - goto bail; - } - } - ipath_dbg("port %u, all pkeys already in use 2nd pass, " - "can't set %x\n", pd->port_port, key); - ret = -EBUSY; - -bail: - return ret; -} - -/** - * ipath_manage_rcvq - manage a port's receive queue - * @pd: the port - * @subport: the subport - * @start_stop: action to carry out - * - * start_stop == 0 disables receive on the port, for use in queue - * overflow conditions. start_stop==1 re-enables, to be used to - * re-init the software copy of the head register - */ -static int ipath_manage_rcvq(struct ipath_portdata *pd, unsigned subport, - int start_stop) -{ - struct ipath_devdata *dd = pd->port_dd; - - ipath_cdbg(PROC, "%sabling rcv for unit %u port %u:%u\n", - start_stop ? "en" : "dis", dd->ipath_unit, - pd->port_port, subport); - if (subport) - goto bail; - /* atomically clear receive enable port. */ - if (start_stop) { - /* - * On enable, force in-memory copy of the tail register to - * 0, so that protocol code doesn't have to worry about - * whether or not the chip has yet updated the in-memory - * copy or not on return from the system call. The chip - * always resets it's tail register back to 0 on a - * transition from disabled to enabled. This could cause a - * problem if software was broken, and did the enable w/o - * the disable, but eventually the in-memory copy will be - * updated and correct itself, even in the face of software - * bugs. - */ - if (pd->port_rcvhdrtail_kvaddr) - ipath_clear_rcvhdrtail(pd); - set_bit(dd->ipath_r_portenable_shift + pd->port_port, - &dd->ipath_rcvctrl); - } else - clear_bit(dd->ipath_r_portenable_shift + pd->port_port, - &dd->ipath_rcvctrl); - ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, - dd->ipath_rcvctrl); - /* now be sure chip saw it before we return */ - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - if (start_stop) { - /* - * And try to be sure that tail reg update has happened too. - * This should in theory interlock with the RXE changes to - * the tail register. Don't assign it to the tail register - * in memory copy, since we could overwrite an update by the - * chip if we did. - */ - ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port); - } - /* always; new head should be equal to new tail; see above */ -bail: - return 0; -} - -static void ipath_clean_part_key(struct ipath_portdata *pd, - struct ipath_devdata *dd) -{ - int i, j, pchanged = 0; - u64 oldpkey; - - /* for debugging only */ - oldpkey = (u64) dd->ipath_pkeys[0] | - ((u64) dd->ipath_pkeys[1] << 16) | - ((u64) dd->ipath_pkeys[2] << 32) | - ((u64) dd->ipath_pkeys[3] << 48); - - for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) { - if (!pd->port_pkeys[i]) - continue; - ipath_cdbg(VERBOSE, "look for key[%d] %hx in pkeys\n", i, - pd->port_pkeys[i]); - for (j = 0; j < ARRAY_SIZE(dd->ipath_pkeys); j++) { - /* check for match independent of the global bit */ - if ((dd->ipath_pkeys[j] & 0x7fff) != - (pd->port_pkeys[i] & 0x7fff)) - continue; - if (atomic_dec_and_test(&dd->ipath_pkeyrefs[j])) { - ipath_cdbg(VERBOSE, "p%u clear key " - "%x matches #%d\n", - pd->port_port, - pd->port_pkeys[i], j); - ipath_stats.sps_pkeys[j] = - dd->ipath_pkeys[j] = 0; - pchanged++; - } else { - ipath_cdbg(VERBOSE, "p%u key %x matches #%d, " - "but ref still %d\n", pd->port_port, - pd->port_pkeys[i], j, - atomic_read(&dd->ipath_pkeyrefs[j])); - break; - } - } - pd->port_pkeys[i] = 0; - } - if (pchanged) { - u64 pkey = (u64) dd->ipath_pkeys[0] | - ((u64) dd->ipath_pkeys[1] << 16) | - ((u64) dd->ipath_pkeys[2] << 32) | - ((u64) dd->ipath_pkeys[3] << 48); - ipath_cdbg(VERBOSE, "p%u old pkey reg %llx, " - "new pkey reg %llx\n", pd->port_port, - (unsigned long long) oldpkey, - (unsigned long long) pkey); - ipath_write_kreg(dd, dd->ipath_kregs->kr_partitionkey, - pkey); - } -} - -/* - * Initialize the port data with the receive buffer sizes - * so this can be done while the master port is locked. - * Otherwise, there is a race with a slave opening the port - * and seeing these fields uninitialized. - */ -static void init_user_egr_sizes(struct ipath_portdata *pd) -{ - struct ipath_devdata *dd = pd->port_dd; - unsigned egrperchunk, egrcnt, size; - - /* - * to avoid wasting a lot of memory, we allocate 32KB chunks of - * physically contiguous memory, advance through it until used up - * and then allocate more. Of course, we need memory to store those - * extra pointers, now. Started out with 256KB, but under heavy - * memory pressure (creating large files and then copying them over - * NFS while doing lots of MPI jobs), we hit some allocation - * failures, even though we can sleep... (2.6.10) Still get - * failures at 64K. 32K is the lowest we can go without wasting - * additional memory. - */ - size = 0x8000; - egrperchunk = size / dd->ipath_rcvegrbufsize; - egrcnt = dd->ipath_rcvegrcnt; - pd->port_rcvegrbuf_chunks = (egrcnt + egrperchunk - 1) / egrperchunk; - pd->port_rcvegrbufs_perchunk = egrperchunk; - pd->port_rcvegrbuf_size = size; -} - -/** - * ipath_create_user_egr - allocate eager TID buffers - * @pd: the port to allocate TID buffers for - * - * This routine is now quite different for user and kernel, because - * the kernel uses skb's, for the accelerated network performance - * This is the user port version - * - * Allocate the eager TID buffers and program them into infinipath - * They are no longer completely contiguous, we do multiple allocation - * calls. - */ -static int ipath_create_user_egr(struct ipath_portdata *pd) -{ - struct ipath_devdata *dd = pd->port_dd; - unsigned e, egrcnt, egrperchunk, chunk, egrsize, egroff; - size_t size; - int ret; - gfp_t gfp_flags; - - /* - * GFP_USER, but without GFP_FS, so buffer cache can be - * coalesced (we hope); otherwise, even at order 4, - * heavy filesystem activity makes these fail, and we can - * use compound pages. - */ - gfp_flags = __GFP_RECLAIM | __GFP_IO | __GFP_COMP; - - egrcnt = dd->ipath_rcvegrcnt; - /* TID number offset for this port */ - egroff = (pd->port_port - 1) * egrcnt + dd->ipath_p0_rcvegrcnt; - egrsize = dd->ipath_rcvegrbufsize; - ipath_cdbg(VERBOSE, "Allocating %d egr buffers, at egrtid " - "offset %x, egrsize %u\n", egrcnt, egroff, egrsize); - - chunk = pd->port_rcvegrbuf_chunks; - egrperchunk = pd->port_rcvegrbufs_perchunk; - size = pd->port_rcvegrbuf_size; - pd->port_rcvegrbuf = kmalloc_array(chunk, sizeof(pd->port_rcvegrbuf[0]), - GFP_KERNEL); - if (!pd->port_rcvegrbuf) { - ret = -ENOMEM; - goto bail; - } - pd->port_rcvegrbuf_phys = - kmalloc_array(chunk, sizeof(pd->port_rcvegrbuf_phys[0]), - GFP_KERNEL); - if (!pd->port_rcvegrbuf_phys) { - ret = -ENOMEM; - goto bail_rcvegrbuf; - } - for (e = 0; e < pd->port_rcvegrbuf_chunks; e++) { - - pd->port_rcvegrbuf[e] = dma_alloc_coherent( - &dd->pcidev->dev, size, &pd->port_rcvegrbuf_phys[e], - gfp_flags); - - if (!pd->port_rcvegrbuf[e]) { - ret = -ENOMEM; - goto bail_rcvegrbuf_phys; - } - } - - pd->port_rcvegr_phys = pd->port_rcvegrbuf_phys[0]; - - for (e = chunk = 0; chunk < pd->port_rcvegrbuf_chunks; chunk++) { - dma_addr_t pa = pd->port_rcvegrbuf_phys[chunk]; - unsigned i; - - for (i = 0; e < egrcnt && i < egrperchunk; e++, i++) { - dd->ipath_f_put_tid(dd, e + egroff + - (u64 __iomem *) - ((char __iomem *) - dd->ipath_kregbase + - dd->ipath_rcvegrbase), - RCVHQ_RCV_TYPE_EAGER, pa); - pa += egrsize; - } - cond_resched(); /* don't hog the cpu */ - } - - ret = 0; - goto bail; - -bail_rcvegrbuf_phys: - for (e = 0; e < pd->port_rcvegrbuf_chunks && - pd->port_rcvegrbuf[e]; e++) { - dma_free_coherent(&dd->pcidev->dev, size, - pd->port_rcvegrbuf[e], - pd->port_rcvegrbuf_phys[e]); - - } - kfree(pd->port_rcvegrbuf_phys); - pd->port_rcvegrbuf_phys = NULL; -bail_rcvegrbuf: - kfree(pd->port_rcvegrbuf); - pd->port_rcvegrbuf = NULL; -bail: - return ret; -} - - -/* common code for the mappings on dma_alloc_coherent mem */ -static int ipath_mmap_mem(struct vm_area_struct *vma, - struct ipath_portdata *pd, unsigned len, int write_ok, - void *kvaddr, char *what) -{ - struct ipath_devdata *dd = pd->port_dd; - unsigned long pfn; - int ret; - - if ((vma->vm_end - vma->vm_start) > len) { - dev_info(&dd->pcidev->dev, - "FAIL on %s: len %lx > %x\n", what, - vma->vm_end - vma->vm_start, len); - ret = -EFAULT; - goto bail; - } - - if (!write_ok) { - if (vma->vm_flags & VM_WRITE) { - dev_info(&dd->pcidev->dev, - "%s must be mapped readonly\n", what); - ret = -EPERM; - goto bail; - } - - /* don't allow them to later change with mprotect */ - vma->vm_flags &= ~VM_MAYWRITE; - } - - pfn = virt_to_phys(kvaddr) >> PAGE_SHIFT; - ret = remap_pfn_range(vma, vma->vm_start, pfn, - len, vma->vm_page_prot); - if (ret) - dev_info(&dd->pcidev->dev, "%s port%u mmap of %lx, %x " - "bytes r%c failed: %d\n", what, pd->port_port, - pfn, len, write_ok?'w':'o', ret); - else - ipath_cdbg(VERBOSE, "%s port%u mmaped %lx, %x bytes " - "r%c\n", what, pd->port_port, pfn, len, - write_ok?'w':'o'); -bail: - return ret; -} - -static int mmap_ureg(struct vm_area_struct *vma, struct ipath_devdata *dd, - u64 ureg) -{ - unsigned long phys; - int ret; - - /* - * This is real hardware, so use io_remap. This is the mechanism - * for the user process to update the head registers for their port - * in the chip. - */ - if ((vma->vm_end - vma->vm_start) > PAGE_SIZE) { - dev_info(&dd->pcidev->dev, "FAIL mmap userreg: reqlen " - "%lx > PAGE\n", vma->vm_end - vma->vm_start); - ret = -EFAULT; - } else { - phys = dd->ipath_physaddr + ureg; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND; - ret = io_remap_pfn_range(vma, vma->vm_start, - phys >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); - } - return ret; -} - -static int mmap_piobufs(struct vm_area_struct *vma, - struct ipath_devdata *dd, - struct ipath_portdata *pd, - unsigned piobufs, unsigned piocnt) -{ - unsigned long phys; - int ret; - - /* - * When we map the PIO buffers in the chip, we want to map them as - * writeonly, no read possible. This prevents access to previous - * process data, and catches users who might try to read the i/o - * space due to a bug. - */ - if ((vma->vm_end - vma->vm_start) > (piocnt * dd->ipath_palign)) { - dev_info(&dd->pcidev->dev, "FAIL mmap piobufs: " - "reqlen %lx > PAGE\n", - vma->vm_end - vma->vm_start); - ret = -EINVAL; - goto bail; - } - - phys = dd->ipath_physaddr + piobufs; - -#if defined(__powerpc__) - /* There isn't a generic way to specify writethrough mappings */ - pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; - pgprot_val(vma->vm_page_prot) |= _PAGE_WRITETHRU; - pgprot_val(vma->vm_page_prot) &= ~_PAGE_GUARDED; -#endif - - /* - * don't allow them to later change to readable with mprotect (for when - * not initially mapped readable, as is normally the case) - */ - vma->vm_flags &= ~VM_MAYREAD; - vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND; - - ret = io_remap_pfn_range(vma, vma->vm_start, phys >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); -bail: - return ret; -} - -static int mmap_rcvegrbufs(struct vm_area_struct *vma, - struct ipath_portdata *pd) -{ - struct ipath_devdata *dd = pd->port_dd; - unsigned long start, size; - size_t total_size, i; - unsigned long pfn; - int ret; - - size = pd->port_rcvegrbuf_size; - total_size = pd->port_rcvegrbuf_chunks * size; - if ((vma->vm_end - vma->vm_start) > total_size) { - dev_info(&dd->pcidev->dev, "FAIL on egr bufs: " - "reqlen %lx > actual %lx\n", - vma->vm_end - vma->vm_start, - (unsigned long) total_size); - ret = -EINVAL; - goto bail; - } - - if (vma->vm_flags & VM_WRITE) { - dev_info(&dd->pcidev->dev, "Can't map eager buffers as " - "writable (flags=%lx)\n", vma->vm_flags); - ret = -EPERM; - goto bail; - } - /* don't allow them to later change to writeable with mprotect */ - vma->vm_flags &= ~VM_MAYWRITE; - - start = vma->vm_start; - - for (i = 0; i < pd->port_rcvegrbuf_chunks; i++, start += size) { - pfn = virt_to_phys(pd->port_rcvegrbuf[i]) >> PAGE_SHIFT; - ret = remap_pfn_range(vma, start, pfn, size, - vma->vm_page_prot); - if (ret < 0) - goto bail; - } - ret = 0; - -bail: - return ret; -} - -/* - * ipath_file_vma_fault - handle a VMA page fault. - */ -static int ipath_file_vma_fault(struct vm_area_struct *vma, - struct vm_fault *vmf) -{ - struct page *page; - - page = vmalloc_to_page((void *)(vmf->pgoff << PAGE_SHIFT)); - if (!page) - return VM_FAULT_SIGBUS; - get_page(page); - vmf->page = page; - - return 0; -} - -static const struct vm_operations_struct ipath_file_vm_ops = { - .fault = ipath_file_vma_fault, -}; - -static int mmap_kvaddr(struct vm_area_struct *vma, u64 pgaddr, - struct ipath_portdata *pd, unsigned subport) -{ - unsigned long len; - struct ipath_devdata *dd; - void *addr; - size_t size; - int ret = 0; - - /* If the port is not shared, all addresses should be physical */ - if (!pd->port_subport_cnt) - goto bail; - - dd = pd->port_dd; - size = pd->port_rcvegrbuf_chunks * pd->port_rcvegrbuf_size; - - /* - * Each process has all the subport uregbase, rcvhdrq, and - * rcvegrbufs mmapped - as an array for all the processes, - * and also separately for this process. - */ - if (pgaddr == cvt_kvaddr(pd->subport_uregbase)) { - addr = pd->subport_uregbase; - size = PAGE_SIZE * pd->port_subport_cnt; - } else if (pgaddr == cvt_kvaddr(pd->subport_rcvhdr_base)) { - addr = pd->subport_rcvhdr_base; - size = pd->port_rcvhdrq_size * pd->port_subport_cnt; - } else if (pgaddr == cvt_kvaddr(pd->subport_rcvegrbuf)) { - addr = pd->subport_rcvegrbuf; - size *= pd->port_subport_cnt; - } else if (pgaddr == cvt_kvaddr(pd->subport_uregbase + - PAGE_SIZE * subport)) { - addr = pd->subport_uregbase + PAGE_SIZE * subport; - size = PAGE_SIZE; - } else if (pgaddr == cvt_kvaddr(pd->subport_rcvhdr_base + - pd->port_rcvhdrq_size * subport)) { - addr = pd->subport_rcvhdr_base + - pd->port_rcvhdrq_size * subport; - size = pd->port_rcvhdrq_size; - } else if (pgaddr == cvt_kvaddr(pd->subport_rcvegrbuf + - size * subport)) { - addr = pd->subport_rcvegrbuf + size * subport; - /* rcvegrbufs are read-only on the slave */ - if (vma->vm_flags & VM_WRITE) { - dev_info(&dd->pcidev->dev, - "Can't map eager buffers as " - "writable (flags=%lx)\n", vma->vm_flags); - ret = -EPERM; - goto bail; - } - /* - * Don't allow permission to later change to writeable - * with mprotect. - */ - vma->vm_flags &= ~VM_MAYWRITE; - } else { - goto bail; - } - len = vma->vm_end - vma->vm_start; - if (len > size) { - ipath_cdbg(MM, "FAIL: reqlen %lx > %zx\n", len, size); - ret = -EINVAL; - goto bail; - } - - vma->vm_pgoff = (unsigned long) addr >> PAGE_SHIFT; - vma->vm_ops = &ipath_file_vm_ops; - vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; - ret = 1; - -bail: - return ret; -} - -/** - * ipath_mmap - mmap various structures into user space - * @fp: the file pointer - * @vma: the VM area - * - * We use this to have a shared buffer between the kernel and the user code - * for the rcvhdr queue, egr buffers, and the per-port user regs and pio - * buffers in the chip. We have the open and close entries so we can bump - * the ref count and keep the driver from being unloaded while still mapped. - */ -static int ipath_mmap(struct file *fp, struct vm_area_struct *vma) -{ - struct ipath_portdata *pd; - struct ipath_devdata *dd; - u64 pgaddr, ureg; - unsigned piobufs, piocnt; - int ret; - - pd = port_fp(fp); - if (!pd) { - ret = -EINVAL; - goto bail; - } - dd = pd->port_dd; - - /* - * This is the ipath_do_user_init() code, mapping the shared buffers - * into the user process. The address referred to by vm_pgoff is the - * file offset passed via mmap(). For shared ports, this is the - * kernel vmalloc() address of the pages to share with the master. - * For non-shared or master ports, this is a physical address. - * We only do one mmap for each space mapped. - */ - pgaddr = vma->vm_pgoff << PAGE_SHIFT; - - /* - * Check for 0 in case one of the allocations failed, but user - * called mmap anyway. - */ - if (!pgaddr) { - ret = -EINVAL; - goto bail; - } - - ipath_cdbg(MM, "pgaddr %llx vm_start=%lx len %lx port %u:%u:%u\n", - (unsigned long long) pgaddr, vma->vm_start, - vma->vm_end - vma->vm_start, dd->ipath_unit, - pd->port_port, subport_fp(fp)); - - /* - * Physical addresses must fit in 40 bits for our hardware. - * Check for kernel virtual addresses first, anything else must - * match a HW or memory address. - */ - ret = mmap_kvaddr(vma, pgaddr, pd, subport_fp(fp)); - if (ret) { - if (ret > 0) - ret = 0; - goto bail; - } - - ureg = dd->ipath_uregbase + dd->ipath_ureg_align * pd->port_port; - if (!pd->port_subport_cnt) { - /* port is not shared */ - piocnt = pd->port_piocnt; - piobufs = pd->port_piobufs; - } else if (!subport_fp(fp)) { - /* caller is the master */ - piocnt = (pd->port_piocnt / pd->port_subport_cnt) + - (pd->port_piocnt % pd->port_subport_cnt); - piobufs = pd->port_piobufs + - dd->ipath_palign * (pd->port_piocnt - piocnt); - } else { - unsigned slave = subport_fp(fp) - 1; - - /* caller is a slave */ - piocnt = pd->port_piocnt / pd->port_subport_cnt; - piobufs = pd->port_piobufs + dd->ipath_palign * piocnt * slave; - } - - if (pgaddr == ureg) - ret = mmap_ureg(vma, dd, ureg); - else if (pgaddr == piobufs) - ret = mmap_piobufs(vma, dd, pd, piobufs, piocnt); - else if (pgaddr == dd->ipath_pioavailregs_phys) - /* in-memory copy of pioavail registers */ - ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0, - (void *) dd->ipath_pioavailregs_dma, - "pioavail registers"); - else if (pgaddr == pd->port_rcvegr_phys) - ret = mmap_rcvegrbufs(vma, pd); - else if (pgaddr == (u64) pd->port_rcvhdrq_phys) - /* - * The rcvhdrq itself; readonly except on HT (so have - * to allow writable mapping), multiple pages, contiguous - * from an i/o perspective. - */ - ret = ipath_mmap_mem(vma, pd, pd->port_rcvhdrq_size, 1, - pd->port_rcvhdrq, - "rcvhdrq"); - else if (pgaddr == (u64) pd->port_rcvhdrqtailaddr_phys) - /* in-memory copy of rcvhdrq tail register */ - ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0, - pd->port_rcvhdrtail_kvaddr, - "rcvhdrq tail"); - else - ret = -EINVAL; - - vma->vm_private_data = NULL; - - if (ret < 0) - dev_info(&dd->pcidev->dev, - "Failure %d on off %llx len %lx\n", - -ret, (unsigned long long)pgaddr, - vma->vm_end - vma->vm_start); -bail: - return ret; -} - -static unsigned ipath_poll_hdrqfull(struct ipath_portdata *pd) -{ - unsigned pollflag = 0; - - if ((pd->poll_type & IPATH_POLL_TYPE_OVERFLOW) && - pd->port_hdrqfull != pd->port_hdrqfull_poll) { - pollflag |= POLLIN | POLLRDNORM; - pd->port_hdrqfull_poll = pd->port_hdrqfull; - } - - return pollflag; -} - -static unsigned int ipath_poll_urgent(struct ipath_portdata *pd, - struct file *fp, - struct poll_table_struct *pt) -{ - unsigned pollflag = 0; - struct ipath_devdata *dd; - - dd = pd->port_dd; - - /* variable access in ipath_poll_hdrqfull() needs this */ - rmb(); - pollflag = ipath_poll_hdrqfull(pd); - - if (pd->port_urgent != pd->port_urgent_poll) { - pollflag |= POLLIN | POLLRDNORM; - pd->port_urgent_poll = pd->port_urgent; - } - - if (!pollflag) { - /* this saves a spin_lock/unlock in interrupt handler... */ - set_bit(IPATH_PORT_WAITING_URG, &pd->port_flag); - /* flush waiting flag so don't miss an event... */ - wmb(); - poll_wait(fp, &pd->port_wait, pt); - } - - return pollflag; -} - -static unsigned int ipath_poll_next(struct ipath_portdata *pd, - struct file *fp, - struct poll_table_struct *pt) -{ - u32 head; - u32 tail; - unsigned pollflag = 0; - struct ipath_devdata *dd; - - dd = pd->port_dd; - - /* variable access in ipath_poll_hdrqfull() needs this */ - rmb(); - pollflag = ipath_poll_hdrqfull(pd); - - head = ipath_read_ureg32(dd, ur_rcvhdrhead, pd->port_port); - if (pd->port_rcvhdrtail_kvaddr) - tail = ipath_get_rcvhdrtail(pd); - else - tail = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port); - - if (head != tail) - pollflag |= POLLIN | POLLRDNORM; - else { - /* this saves a spin_lock/unlock in interrupt handler */ - set_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag); - /* flush waiting flag so we don't miss an event */ - wmb(); - - set_bit(pd->port_port + dd->ipath_r_intravail_shift, - &dd->ipath_rcvctrl); - - ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, - dd->ipath_rcvctrl); - - if (dd->ipath_rhdrhead_intr_off) /* arm rcv interrupt */ - ipath_write_ureg(dd, ur_rcvhdrhead, - dd->ipath_rhdrhead_intr_off | head, - pd->port_port); - - poll_wait(fp, &pd->port_wait, pt); - } - - return pollflag; -} - -static unsigned int ipath_poll(struct file *fp, - struct poll_table_struct *pt) -{ - struct ipath_portdata *pd; - unsigned pollflag; - - pd = port_fp(fp); - if (!pd) - pollflag = 0; - else if (pd->poll_type & IPATH_POLL_TYPE_URGENT) - pollflag = ipath_poll_urgent(pd, fp, pt); - else - pollflag = ipath_poll_next(pd, fp, pt); - - return pollflag; -} - -static int ipath_supports_subports(int user_swmajor, int user_swminor) -{ - /* no subport implementation prior to software version 1.3 */ - return (user_swmajor > 1) || (user_swminor >= 3); -} - -static int ipath_compatible_subports(int user_swmajor, int user_swminor) -{ - /* this code is written long-hand for clarity */ - if (IPATH_USER_SWMAJOR != user_swmajor) { - /* no promise of compatibility if major mismatch */ - return 0; - } - if (IPATH_USER_SWMAJOR == 1) { - switch (IPATH_USER_SWMINOR) { - case 0: - case 1: - case 2: - /* no subport implementation so cannot be compatible */ - return 0; - case 3: - /* 3 is only compatible with itself */ - return user_swminor == 3; - default: - /* >= 4 are compatible (or are expected to be) */ - return user_swminor >= 4; - } - } - /* make no promises yet for future major versions */ - return 0; -} - -static int init_subports(struct ipath_devdata *dd, - struct ipath_portdata *pd, - const struct ipath_user_info *uinfo) -{ - int ret = 0; - unsigned num_subports; - size_t size; - - /* - * If the user is requesting zero subports, - * skip the subport allocation. - */ - if (uinfo->spu_subport_cnt <= 0) - goto bail; - - /* Self-consistency check for ipath_compatible_subports() */ - if (ipath_supports_subports(IPATH_USER_SWMAJOR, IPATH_USER_SWMINOR) && - !ipath_compatible_subports(IPATH_USER_SWMAJOR, - IPATH_USER_SWMINOR)) { - dev_info(&dd->pcidev->dev, - "Inconsistent ipath_compatible_subports()\n"); - goto bail; - } - - /* Check for subport compatibility */ - if (!ipath_compatible_subports(uinfo->spu_userversion >> 16, - uinfo->spu_userversion & 0xffff)) { - dev_info(&dd->pcidev->dev, - "Mismatched user version (%d.%d) and driver " - "version (%d.%d) while port sharing. Ensure " - "that driver and library are from the same " - "release.\n", - (int) (uinfo->spu_userversion >> 16), - (int) (uinfo->spu_userversion & 0xffff), - IPATH_USER_SWMAJOR, - IPATH_USER_SWMINOR); - goto bail; - } - if (uinfo->spu_subport_cnt > INFINIPATH_MAX_SUBPORT) { - ret = -EINVAL; - goto bail; - } - - num_subports = uinfo->spu_subport_cnt; - pd->subport_uregbase = vzalloc(PAGE_SIZE * num_subports); - if (!pd->subport_uregbase) { - ret = -ENOMEM; - goto bail; - } - /* Note: pd->port_rcvhdrq_size isn't initialized yet. */ - size = ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize * - sizeof(u32), PAGE_SIZE) * num_subports; - pd->subport_rcvhdr_base = vzalloc(size); - if (!pd->subport_rcvhdr_base) { - ret = -ENOMEM; - goto bail_ureg; - } - - pd->subport_rcvegrbuf = vzalloc(pd->port_rcvegrbuf_chunks * - pd->port_rcvegrbuf_size * - num_subports); - if (!pd->subport_rcvegrbuf) { - ret = -ENOMEM; - goto bail_rhdr; - } - - pd->port_subport_cnt = uinfo->spu_subport_cnt; - pd->port_subport_id = uinfo->spu_subport_id; - pd->active_slaves = 1; - set_bit(IPATH_PORT_MASTER_UNINIT, &pd->port_flag); - goto bail; - -bail_rhdr: - vfree(pd->subport_rcvhdr_base); -bail_ureg: - vfree(pd->subport_uregbase); - pd->subport_uregbase = NULL; -bail: - return ret; -} - -static int try_alloc_port(struct ipath_devdata *dd, int port, - struct file *fp, - const struct ipath_user_info *uinfo) -{ - struct ipath_portdata *pd; - int ret; - - if (!(pd = dd->ipath_pd[port])) { - void *ptmp; - - pd = kzalloc(sizeof(struct ipath_portdata), GFP_KERNEL); - - /* - * Allocate memory for use in ipath_tid_update() just once - * at open, not per call. Reduces cost of expected send - * setup. - */ - ptmp = kmalloc(dd->ipath_rcvtidcnt * sizeof(u16) + - dd->ipath_rcvtidcnt * sizeof(struct page **), - GFP_KERNEL); - if (!pd || !ptmp) { - ipath_dev_err(dd, "Unable to allocate portdata " - "memory, failing open\n"); - ret = -ENOMEM; - kfree(pd); - kfree(ptmp); - goto bail; - } - dd->ipath_pd[port] = pd; - dd->ipath_pd[port]->port_port = port; - dd->ipath_pd[port]->port_dd = dd; - dd->ipath_pd[port]->port_tid_pg_list = ptmp; - init_waitqueue_head(&dd->ipath_pd[port]->port_wait); - } - if (!pd->port_cnt) { - pd->userversion = uinfo->spu_userversion; - init_user_egr_sizes(pd); - if ((ret = init_subports(dd, pd, uinfo)) != 0) - goto bail; - ipath_cdbg(PROC, "%s[%u] opened unit:port %u:%u\n", - current->comm, current->pid, dd->ipath_unit, - port); - pd->port_cnt = 1; - port_fp(fp) = pd; - pd->port_pid = get_pid(task_pid(current)); - strlcpy(pd->port_comm, current->comm, sizeof(pd->port_comm)); - ipath_stats.sps_ports++; - ret = 0; - } else - ret = -EBUSY; - -bail: - return ret; -} - -static inline int usable(struct ipath_devdata *dd) -{ - return dd && - (dd->ipath_flags & IPATH_PRESENT) && - dd->ipath_kregbase && - dd->ipath_lid && - !(dd->ipath_flags & (IPATH_LINKDOWN | IPATH_DISABLED - | IPATH_LINKUNK)); -} - -static int find_free_port(int unit, struct file *fp, - const struct ipath_user_info *uinfo) -{ - struct ipath_devdata *dd = ipath_lookup(unit); - int ret, i; - - if (!dd) { - ret = -ENODEV; - goto bail; - } - - if (!usable(dd)) { - ret = -ENETDOWN; - goto bail; - } - - for (i = 1; i < dd->ipath_cfgports; i++) { - ret = try_alloc_port(dd, i, fp, uinfo); - if (ret != -EBUSY) - goto bail; - } - ret = -EBUSY; - -bail: - return ret; -} - -static int find_best_unit(struct file *fp, - const struct ipath_user_info *uinfo) -{ - int ret = 0, i, prefunit = -1, devmax; - int maxofallports, npresent, nup; - int ndev; - - devmax = ipath_count_units(&npresent, &nup, &maxofallports); - - /* - * This code is present to allow a knowledgeable person to - * specify the layout of processes to processors before opening - * this driver, and then we'll assign the process to the "closest" - * InfiniPath chip to that processor (we assume reasonable connectivity, - * for now). This code assumes that if affinity has been set - * before this point, that at most one cpu is set; for now this - * is reasonable. I check for both cpumask_empty() and cpumask_full(), - * in case some kernel variant sets none of the bits when no - * affinity is set. 2.6.11 and 12 kernels have all present - * cpus set. Some day we'll have to fix it up further to handle - * a cpu subset. This algorithm fails for two HT chips connected - * in tunnel fashion. Eventually this needs real topology - * information. There may be some issues with dual core numbering - * as well. This needs more work prior to release. - */ - if (!cpumask_empty(tsk_cpus_allowed(current)) && - !cpumask_full(tsk_cpus_allowed(current))) { - int ncpus = num_online_cpus(), curcpu = -1, nset = 0; - get_online_cpus(); - for_each_online_cpu(i) - if (cpumask_test_cpu(i, tsk_cpus_allowed(current))) { - ipath_cdbg(PROC, "%s[%u] affinity set for " - "cpu %d/%d\n", current->comm, - current->pid, i, ncpus); - curcpu = i; - nset++; - } - put_online_cpus(); - if (curcpu != -1 && nset != ncpus) { - if (npresent) { - prefunit = curcpu / (ncpus / npresent); - ipath_cdbg(PROC,"%s[%u] %d chips, %d cpus, " - "%d cpus/chip, select unit %d\n", - current->comm, current->pid, - npresent, ncpus, ncpus / npresent, - prefunit); - } - } - } - - /* - * user ports start at 1, kernel port is 0 - * For now, we do round-robin access across all chips - */ - - if (prefunit != -1) - devmax = prefunit + 1; -recheck: - for (i = 1; i < maxofallports; i++) { - for (ndev = prefunit != -1 ? prefunit : 0; ndev < devmax; - ndev++) { - struct ipath_devdata *dd = ipath_lookup(ndev); - - if (!usable(dd)) - continue; /* can't use this unit */ - if (i >= dd->ipath_cfgports) - /* - * Maxed out on users of this unit. Try - * next. - */ - continue; - ret = try_alloc_port(dd, i, fp, uinfo); - if (!ret) - goto done; - } - } - - if (npresent) { - if (nup == 0) { - ret = -ENETDOWN; - ipath_dbg("No ports available (none initialized " - "and ready)\n"); - } else { - if (prefunit > 0) { - /* if started above 0, retry from 0 */ - ipath_cdbg(PROC, - "%s[%u] no ports on prefunit " - "%d, clear and re-check\n", - current->comm, current->pid, - prefunit); - devmax = ipath_count_units(NULL, NULL, - NULL); - prefunit = -1; - goto recheck; - } - ret = -EBUSY; - ipath_dbg("No ports available\n"); - } - } else { - ret = -ENXIO; - ipath_dbg("No boards found\n"); - } - -done: - return ret; -} - -static int find_shared_port(struct file *fp, - const struct ipath_user_info *uinfo) -{ - int devmax, ndev, i; - int ret = 0; - - devmax = ipath_count_units(NULL, NULL, NULL); - - for (ndev = 0; ndev < devmax; ndev++) { - struct ipath_devdata *dd = ipath_lookup(ndev); - - if (!usable(dd)) - continue; - for (i = 1; i < dd->ipath_cfgports; i++) { - struct ipath_portdata *pd = dd->ipath_pd[i]; - - /* Skip ports which are not yet open */ - if (!pd || !pd->port_cnt) - continue; - /* Skip port if it doesn't match the requested one */ - if (pd->port_subport_id != uinfo->spu_subport_id) - continue; - /* Verify the sharing process matches the master */ - if (pd->port_subport_cnt != uinfo->spu_subport_cnt || - pd->userversion != uinfo->spu_userversion || - pd->port_cnt >= pd->port_subport_cnt) { - ret = -EINVAL; - goto done; - } - port_fp(fp) = pd; - subport_fp(fp) = pd->port_cnt++; - pd->port_subpid[subport_fp(fp)] = - get_pid(task_pid(current)); - tidcursor_fp(fp) = 0; - pd->active_slaves |= 1 << subport_fp(fp); - ipath_cdbg(PROC, - "%s[%u] %u sharing %s[%u] unit:port %u:%u\n", - current->comm, current->pid, - subport_fp(fp), - pd->port_comm, pid_nr(pd->port_pid), - dd->ipath_unit, pd->port_port); - ret = 1; - goto done; - } - } - -done: - return ret; -} - -static int ipath_open(struct inode *in, struct file *fp) -{ - /* The real work is performed later in ipath_assign_port() */ - fp->private_data = kzalloc(sizeof(struct ipath_filedata), GFP_KERNEL); - return fp->private_data ? 0 : -ENOMEM; -} - -/* Get port early, so can set affinity prior to memory allocation */ -static int ipath_assign_port(struct file *fp, - const struct ipath_user_info *uinfo) -{ - int ret; - int i_minor; - unsigned swmajor, swminor; - - /* Check to be sure we haven't already initialized this file */ - if (port_fp(fp)) { - ret = -EINVAL; - goto done; - } - - /* for now, if major version is different, bail */ - swmajor = uinfo->spu_userversion >> 16; - if (swmajor != IPATH_USER_SWMAJOR) { - ipath_dbg("User major version %d not same as driver " - "major %d\n", uinfo->spu_userversion >> 16, - IPATH_USER_SWMAJOR); - ret = -ENODEV; - goto done; - } - - swminor = uinfo->spu_userversion & 0xffff; - if (swminor != IPATH_USER_SWMINOR) - ipath_dbg("User minor version %d not same as driver " - "minor %d\n", swminor, IPATH_USER_SWMINOR); - - mutex_lock(&ipath_mutex); - - if (ipath_compatible_subports(swmajor, swminor) && - uinfo->spu_subport_cnt && - (ret = find_shared_port(fp, uinfo))) { - if (ret > 0) - ret = 0; - goto done_chk_sdma; - } - - i_minor = iminor(file_inode(fp)) - IPATH_USER_MINOR_BASE; - ipath_cdbg(VERBOSE, "open on dev %lx (minor %d)\n", - (long)file_inode(fp)->i_rdev, i_minor); - - if (i_minor) - ret = find_free_port(i_minor - 1, fp, uinfo); - else - ret = find_best_unit(fp, uinfo); - -done_chk_sdma: - if (!ret) { - struct ipath_filedata *fd = fp->private_data; - const struct ipath_portdata *pd = fd->pd; - const struct ipath_devdata *dd = pd->port_dd; - - fd->pq = ipath_user_sdma_queue_create(&dd->pcidev->dev, - dd->ipath_unit, - pd->port_port, - fd->subport); - - if (!fd->pq) - ret = -ENOMEM; - } - - mutex_unlock(&ipath_mutex); - -done: - return ret; -} - - -static int ipath_do_user_init(struct file *fp, - const struct ipath_user_info *uinfo) -{ - int ret; - struct ipath_portdata *pd = port_fp(fp); - struct ipath_devdata *dd; - u32 head32; - - /* Subports don't need to initialize anything since master did it. */ - if (subport_fp(fp)) { - ret = wait_event_interruptible(pd->port_wait, - !test_bit(IPATH_PORT_MASTER_UNINIT, &pd->port_flag)); - goto done; - } - - dd = pd->port_dd; - - if (uinfo->spu_rcvhdrsize) { - ret = ipath_setrcvhdrsize(dd, uinfo->spu_rcvhdrsize); - if (ret) - goto done; - } - - /* for now we do nothing with rcvhdrcnt: uinfo->spu_rcvhdrcnt */ - - /* some ports may get extra buffers, calculate that here */ - if (pd->port_port <= dd->ipath_ports_extrabuf) - pd->port_piocnt = dd->ipath_pbufsport + 1; - else - pd->port_piocnt = dd->ipath_pbufsport; - - /* for right now, kernel piobufs are at end, so port 1 is at 0 */ - if (pd->port_port <= dd->ipath_ports_extrabuf) - pd->port_pio_base = (dd->ipath_pbufsport + 1) - * (pd->port_port - 1); - else - pd->port_pio_base = dd->ipath_ports_extrabuf + - dd->ipath_pbufsport * (pd->port_port - 1); - pd->port_piobufs = dd->ipath_piobufbase + - pd->port_pio_base * dd->ipath_palign; - ipath_cdbg(VERBOSE, "piobuf base for port %u is 0x%x, piocnt %u," - " first pio %u\n", pd->port_port, pd->port_piobufs, - pd->port_piocnt, pd->port_pio_base); - ipath_chg_pioavailkernel(dd, pd->port_pio_base, pd->port_piocnt, 0); - - /* - * Now allocate the rcvhdr Q and eager TIDs; skip the TID - * array for time being. If pd->port_port > chip-supported, - * we need to do extra stuff here to handle by handling overflow - * through port 0, someday - */ - ret = ipath_create_rcvhdrq(dd, pd); - if (!ret) - ret = ipath_create_user_egr(pd); - if (ret) - goto done; - - /* - * set the eager head register for this port to the current values - * of the tail pointers, since we don't know if they were - * updated on last use of the port. - */ - head32 = ipath_read_ureg32(dd, ur_rcvegrindextail, pd->port_port); - ipath_write_ureg(dd, ur_rcvegrindexhead, head32, pd->port_port); - pd->port_lastrcvhdrqtail = -1; - ipath_cdbg(VERBOSE, "Wrote port%d egrhead %x from tail regs\n", - pd->port_port, head32); - pd->port_tidcursor = 0; /* start at beginning after open */ - - /* initialize poll variables... */ - pd->port_urgent = 0; - pd->port_urgent_poll = 0; - pd->port_hdrqfull_poll = pd->port_hdrqfull; - - /* - * Now enable the port for receive. - * For chips that are set to DMA the tail register to memory - * when they change (and when the update bit transitions from - * 0 to 1. So for those chips, we turn it off and then back on. - * This will (very briefly) affect any other open ports, but the - * duration is very short, and therefore isn't an issue. We - * explicitly set the in-memory tail copy to 0 beforehand, so we - * don't have to wait to be sure the DMA update has happened - * (chip resets head/tail to 0 on transition to enable). - */ - set_bit(dd->ipath_r_portenable_shift + pd->port_port, - &dd->ipath_rcvctrl); - if (!(dd->ipath_flags & IPATH_NODMA_RTAIL)) { - if (pd->port_rcvhdrtail_kvaddr) - ipath_clear_rcvhdrtail(pd); - ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, - dd->ipath_rcvctrl & - ~(1ULL << dd->ipath_r_tailupd_shift)); - } - ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, - dd->ipath_rcvctrl); - /* Notify any waiting slaves */ - if (pd->port_subport_cnt) { - clear_bit(IPATH_PORT_MASTER_UNINIT, &pd->port_flag); - wake_up(&pd->port_wait); - } -done: - return ret; -} - -/** - * unlock_exptid - unlock any expected TID entries port still had in use - * @pd: port - * - * We don't actually update the chip here, because we do a bulk update - * below, using ipath_f_clear_tids. - */ -static void unlock_expected_tids(struct ipath_portdata *pd) -{ - struct ipath_devdata *dd = pd->port_dd; - int port_tidbase = pd->port_port * dd->ipath_rcvtidcnt; - int i, cnt = 0, maxtid = port_tidbase + dd->ipath_rcvtidcnt; - - ipath_cdbg(VERBOSE, "Port %u unlocking any locked expTID pages\n", - pd->port_port); - for (i = port_tidbase; i < maxtid; i++) { - struct page *ps = dd->ipath_pageshadow[i]; - - if (!ps) - continue; - - dd->ipath_pageshadow[i] = NULL; - pci_unmap_page(dd->pcidev, dd->ipath_physshadow[i], - PAGE_SIZE, PCI_DMA_FROMDEVICE); - ipath_release_user_pages_on_close(&ps, 1); - cnt++; - ipath_stats.sps_pageunlocks++; - } - if (cnt) - ipath_cdbg(VERBOSE, "Port %u locked %u expTID entries\n", - pd->port_port, cnt); - - if (ipath_stats.sps_pagelocks || ipath_stats.sps_pageunlocks) - ipath_cdbg(VERBOSE, "%llu pages locked, %llu unlocked\n", - (unsigned long long) ipath_stats.sps_pagelocks, - (unsigned long long) - ipath_stats.sps_pageunlocks); -} - -static int ipath_close(struct inode *in, struct file *fp) -{ - struct ipath_filedata *fd; - struct ipath_portdata *pd; - struct ipath_devdata *dd; - unsigned long flags; - unsigned port; - struct pid *pid; - - ipath_cdbg(VERBOSE, "close on dev %lx, private data %p\n", - (long)in->i_rdev, fp->private_data); - - mutex_lock(&ipath_mutex); - - fd = fp->private_data; - fp->private_data = NULL; - pd = fd->pd; - if (!pd) { - mutex_unlock(&ipath_mutex); - goto bail; - } - - dd = pd->port_dd; - - /* drain user sdma queue */ - ipath_user_sdma_queue_drain(dd, fd->pq); - ipath_user_sdma_queue_destroy(fd->pq); - - if (--pd->port_cnt) { - /* - * XXX If the master closes the port before the slave(s), - * revoke the mmap for the eager receive queue so - * the slave(s) don't wait for receive data forever. - */ - pd->active_slaves &= ~(1 << fd->subport); - put_pid(pd->port_subpid[fd->subport]); - pd->port_subpid[fd->subport] = NULL; - mutex_unlock(&ipath_mutex); - goto bail; - } - /* early; no interrupt users after this */ - spin_lock_irqsave(&dd->ipath_uctxt_lock, flags); - port = pd->port_port; - dd->ipath_pd[port] = NULL; - pid = pd->port_pid; - pd->port_pid = NULL; - spin_unlock_irqrestore(&dd->ipath_uctxt_lock, flags); - - if (pd->port_rcvwait_to || pd->port_piowait_to - || pd->port_rcvnowait || pd->port_pionowait) { - ipath_cdbg(VERBOSE, "port%u, %u rcv, %u pio wait timeo; " - "%u rcv %u, pio already\n", - pd->port_port, pd->port_rcvwait_to, - pd->port_piowait_to, pd->port_rcvnowait, - pd->port_pionowait); - pd->port_rcvwait_to = pd->port_piowait_to = - pd->port_rcvnowait = pd->port_pionowait = 0; - } - if (pd->port_flag) { - ipath_cdbg(PROC, "port %u port_flag set: 0x%lx\n", - pd->port_port, pd->port_flag); - pd->port_flag = 0; - } - - if (dd->ipath_kregbase) { - /* atomically clear receive enable port and intr avail. */ - clear_bit(dd->ipath_r_portenable_shift + port, - &dd->ipath_rcvctrl); - clear_bit(pd->port_port + dd->ipath_r_intravail_shift, - &dd->ipath_rcvctrl); - ipath_write_kreg( dd, dd->ipath_kregs->kr_rcvctrl, - dd->ipath_rcvctrl); - /* and read back from chip to be sure that nothing - * else is in flight when we do the rest */ - (void)ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - - /* clean up the pkeys for this port user */ - ipath_clean_part_key(pd, dd); - /* - * be paranoid, and never write 0's to these, just use an - * unused part of the port 0 tail page. Of course, - * rcvhdraddr points to a large chunk of memory, so this - * could still trash things, but at least it won't trash - * page 0, and by disabling the port, it should stop "soon", - * even if a packet or two is in already in flight after we - * disabled the port. - */ - ipath_write_kreg_port(dd, - dd->ipath_kregs->kr_rcvhdrtailaddr, port, - dd->ipath_dummy_hdrq_phys); - ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdraddr, - pd->port_port, dd->ipath_dummy_hdrq_phys); - - ipath_disarm_piobufs(dd, pd->port_pio_base, pd->port_piocnt); - ipath_chg_pioavailkernel(dd, pd->port_pio_base, - pd->port_piocnt, 1); - - dd->ipath_f_clear_tids(dd, pd->port_port); - - if (dd->ipath_pageshadow) - unlock_expected_tids(pd); - ipath_stats.sps_ports--; - ipath_cdbg(PROC, "%s[%u] closed port %u:%u\n", - pd->port_comm, pid_nr(pid), - dd->ipath_unit, port); - } - - put_pid(pid); - mutex_unlock(&ipath_mutex); - ipath_free_pddata(dd, pd); /* after releasing the mutex */ - -bail: - kfree(fd); - return 0; -} - -static int ipath_port_info(struct ipath_portdata *pd, u16 subport, - struct ipath_port_info __user *uinfo) -{ - struct ipath_port_info info; - int nup; - int ret; - size_t sz; - - (void) ipath_count_units(NULL, &nup, NULL); - info.num_active = nup; - info.unit = pd->port_dd->ipath_unit; - info.port = pd->port_port; - info.subport = subport; - /* Don't return new fields if old library opened the port. */ - if (ipath_supports_subports(pd->userversion >> 16, - pd->userversion & 0xffff)) { - /* Number of user ports available for this device. */ - info.num_ports = pd->port_dd->ipath_cfgports - 1; - info.num_subports = pd->port_subport_cnt; - sz = sizeof(info); - } else - sz = sizeof(info) - 2 * sizeof(u16); - - if (copy_to_user(uinfo, &info, sz)) { - ret = -EFAULT; - goto bail; - } - ret = 0; - -bail: - return ret; -} - -static int ipath_get_slave_info(struct ipath_portdata *pd, - void __user *slave_mask_addr) -{ - int ret = 0; - - if (copy_to_user(slave_mask_addr, &pd->active_slaves, sizeof(u32))) - ret = -EFAULT; - return ret; -} - -static int ipath_sdma_get_inflight(struct ipath_user_sdma_queue *pq, - u32 __user *inflightp) -{ - const u32 val = ipath_user_sdma_inflight_counter(pq); - - if (put_user(val, inflightp)) - return -EFAULT; - - return 0; -} - -static int ipath_sdma_get_complete(struct ipath_devdata *dd, - struct ipath_user_sdma_queue *pq, - u32 __user *completep) -{ - u32 val; - int err; - - err = ipath_user_sdma_make_progress(dd, pq); - if (err < 0) - return err; - - val = ipath_user_sdma_complete_counter(pq); - if (put_user(val, completep)) - return -EFAULT; - - return 0; -} - -static ssize_t ipath_write(struct file *fp, const char __user *data, - size_t count, loff_t *off) -{ - const struct ipath_cmd __user *ucmd; - struct ipath_portdata *pd; - const void __user *src; - size_t consumed, copy; - struct ipath_cmd cmd; - ssize_t ret = 0; - void *dest; - - if (count < sizeof(cmd.type)) { - ret = -EINVAL; - goto bail; - } - - ucmd = (const struct ipath_cmd __user *) data; - - if (copy_from_user(&cmd.type, &ucmd->type, sizeof(cmd.type))) { - ret = -EFAULT; - goto bail; - } - - consumed = sizeof(cmd.type); - - switch (cmd.type) { - case IPATH_CMD_ASSIGN_PORT: - case __IPATH_CMD_USER_INIT: - case IPATH_CMD_USER_INIT: - copy = sizeof(cmd.cmd.user_info); - dest = &cmd.cmd.user_info; - src = &ucmd->cmd.user_info; - break; - case IPATH_CMD_RECV_CTRL: - copy = sizeof(cmd.cmd.recv_ctrl); - dest = &cmd.cmd.recv_ctrl; - src = &ucmd->cmd.recv_ctrl; - break; - case IPATH_CMD_PORT_INFO: - copy = sizeof(cmd.cmd.port_info); - dest = &cmd.cmd.port_info; - src = &ucmd->cmd.port_info; - break; - case IPATH_CMD_TID_UPDATE: - case IPATH_CMD_TID_FREE: - copy = sizeof(cmd.cmd.tid_info); - dest = &cmd.cmd.tid_info; - src = &ucmd->cmd.tid_info; - break; - case IPATH_CMD_SET_PART_KEY: - copy = sizeof(cmd.cmd.part_key); - dest = &cmd.cmd.part_key; - src = &ucmd->cmd.part_key; - break; - case __IPATH_CMD_SLAVE_INFO: - copy = sizeof(cmd.cmd.slave_mask_addr); - dest = &cmd.cmd.slave_mask_addr; - src = &ucmd->cmd.slave_mask_addr; - break; - case IPATH_CMD_PIOAVAILUPD: // force an update of PIOAvail reg - copy = 0; - src = NULL; - dest = NULL; - break; - case IPATH_CMD_POLL_TYPE: - copy = sizeof(cmd.cmd.poll_type); - dest = &cmd.cmd.poll_type; - src = &ucmd->cmd.poll_type; - break; - case IPATH_CMD_ARMLAUNCH_CTRL: - copy = sizeof(cmd.cmd.armlaunch_ctrl); - dest = &cmd.cmd.armlaunch_ctrl; - src = &ucmd->cmd.armlaunch_ctrl; - break; - case IPATH_CMD_SDMA_INFLIGHT: - copy = sizeof(cmd.cmd.sdma_inflight); - dest = &cmd.cmd.sdma_inflight; - src = &ucmd->cmd.sdma_inflight; - break; - case IPATH_CMD_SDMA_COMPLETE: - copy = sizeof(cmd.cmd.sdma_complete); - dest = &cmd.cmd.sdma_complete; - src = &ucmd->cmd.sdma_complete; - break; - default: - ret = -EINVAL; - goto bail; - } - - if (copy) { - if ((count - consumed) < copy) { - ret = -EINVAL; - goto bail; - } - - if (copy_from_user(dest, src, copy)) { - ret = -EFAULT; - goto bail; - } - - consumed += copy; - } - - pd = port_fp(fp); - if (!pd && cmd.type != __IPATH_CMD_USER_INIT && - cmd.type != IPATH_CMD_ASSIGN_PORT) { - ret = -EINVAL; - goto bail; - } - - switch (cmd.type) { - case IPATH_CMD_ASSIGN_PORT: - ret = ipath_assign_port(fp, &cmd.cmd.user_info); - if (ret) - goto bail; - break; - case __IPATH_CMD_USER_INIT: - /* backwards compatibility, get port first */ - ret = ipath_assign_port(fp, &cmd.cmd.user_info); - if (ret) - goto bail; - /* and fall through to current version. */ - case IPATH_CMD_USER_INIT: - ret = ipath_do_user_init(fp, &cmd.cmd.user_info); - if (ret) - goto bail; - ret = ipath_get_base_info( - fp, (void __user *) (unsigned long) - cmd.cmd.user_info.spu_base_info, - cmd.cmd.user_info.spu_base_info_size); - break; - case IPATH_CMD_RECV_CTRL: - ret = ipath_manage_rcvq(pd, subport_fp(fp), cmd.cmd.recv_ctrl); - break; - case IPATH_CMD_PORT_INFO: - ret = ipath_port_info(pd, subport_fp(fp), - (struct ipath_port_info __user *) - (unsigned long) cmd.cmd.port_info); - break; - case IPATH_CMD_TID_UPDATE: - ret = ipath_tid_update(pd, fp, &cmd.cmd.tid_info); - break; - case IPATH_CMD_TID_FREE: - ret = ipath_tid_free(pd, subport_fp(fp), &cmd.cmd.tid_info); - break; - case IPATH_CMD_SET_PART_KEY: - ret = ipath_set_part_key(pd, cmd.cmd.part_key); - break; - case __IPATH_CMD_SLAVE_INFO: - ret = ipath_get_slave_info(pd, - (void __user *) (unsigned long) - cmd.cmd.slave_mask_addr); - break; - case IPATH_CMD_PIOAVAILUPD: - ipath_force_pio_avail_update(pd->port_dd); - break; - case IPATH_CMD_POLL_TYPE: - pd->poll_type = cmd.cmd.poll_type; - break; - case IPATH_CMD_ARMLAUNCH_CTRL: - if (cmd.cmd.armlaunch_ctrl) - ipath_enable_armlaunch(pd->port_dd); - else - ipath_disable_armlaunch(pd->port_dd); - break; - case IPATH_CMD_SDMA_INFLIGHT: - ret = ipath_sdma_get_inflight(user_sdma_queue_fp(fp), - (u32 __user *) (unsigned long) - cmd.cmd.sdma_inflight); - break; - case IPATH_CMD_SDMA_COMPLETE: - ret = ipath_sdma_get_complete(pd->port_dd, - user_sdma_queue_fp(fp), - (u32 __user *) (unsigned long) - cmd.cmd.sdma_complete); - break; - } - - if (ret >= 0) - ret = consumed; - -bail: - return ret; -} - -static ssize_t ipath_write_iter(struct kiocb *iocb, struct iov_iter *from) -{ - struct file *filp = iocb->ki_filp; - struct ipath_filedata *fp = filp->private_data; - struct ipath_portdata *pd = port_fp(filp); - struct ipath_user_sdma_queue *pq = fp->pq; - - if (!iter_is_iovec(from) || !from->nr_segs) - return -EINVAL; - - return ipath_user_sdma_writev(pd->port_dd, pq, from->iov, from->nr_segs); -} - -static struct class *ipath_class; - -static int init_cdev(int minor, char *name, const struct file_operations *fops, - struct cdev **cdevp, struct device **devp) -{ - const dev_t dev = MKDEV(IPATH_MAJOR, minor); - struct cdev *cdev = NULL; - struct device *device = NULL; - int ret; - - cdev = cdev_alloc(); - if (!cdev) { - printk(KERN_ERR IPATH_DRV_NAME - ": Could not allocate cdev for minor %d, %s\n", - minor, name); - ret = -ENOMEM; - goto done; - } - - cdev->owner = THIS_MODULE; - cdev->ops = fops; - kobject_set_name(&cdev->kobj, name); - - ret = cdev_add(cdev, dev, 1); - if (ret < 0) { - printk(KERN_ERR IPATH_DRV_NAME - ": Could not add cdev for minor %d, %s (err %d)\n", - minor, name, -ret); - goto err_cdev; - } - - device = device_create(ipath_class, NULL, dev, NULL, name); - - if (IS_ERR(device)) { - ret = PTR_ERR(device); - printk(KERN_ERR IPATH_DRV_NAME ": Could not create " - "device for minor %d, %s (err %d)\n", - minor, name, -ret); - goto err_cdev; - } - - goto done; - -err_cdev: - cdev_del(cdev); - cdev = NULL; - -done: - if (ret >= 0) { - *cdevp = cdev; - *devp = device; - } else { - *cdevp = NULL; - *devp = NULL; - } - - return ret; -} - -int ipath_cdev_init(int minor, char *name, const struct file_operations *fops, - struct cdev **cdevp, struct device **devp) -{ - return init_cdev(minor, name, fops, cdevp, devp); -} - -static void cleanup_cdev(struct cdev **cdevp, - struct device **devp) -{ - struct device *dev = *devp; - - if (dev) { - device_unregister(dev); - *devp = NULL; - } - - if (*cdevp) { - cdev_del(*cdevp); - *cdevp = NULL; - } -} - -void ipath_cdev_cleanup(struct cdev **cdevp, - struct device **devp) -{ - cleanup_cdev(cdevp, devp); -} - -static struct cdev *wildcard_cdev; -static struct device *wildcard_dev; - -static const dev_t dev = MKDEV(IPATH_MAJOR, 0); - -static int user_init(void) -{ - int ret; - - ret = register_chrdev_region(dev, IPATH_NMINORS, IPATH_DRV_NAME); - if (ret < 0) { - printk(KERN_ERR IPATH_DRV_NAME ": Could not register " - "chrdev region (err %d)\n", -ret); - goto done; - } - - ipath_class = class_create(THIS_MODULE, IPATH_DRV_NAME); - - if (IS_ERR(ipath_class)) { - ret = PTR_ERR(ipath_class); - printk(KERN_ERR IPATH_DRV_NAME ": Could not create " - "device class (err %d)\n", -ret); - goto bail; - } - - goto done; -bail: - unregister_chrdev_region(dev, IPATH_NMINORS); -done: - return ret; -} - -static void user_cleanup(void) -{ - if (ipath_class) { - class_destroy(ipath_class); - ipath_class = NULL; - } - - unregister_chrdev_region(dev, IPATH_NMINORS); -} - -static atomic_t user_count = ATOMIC_INIT(0); -static atomic_t user_setup = ATOMIC_INIT(0); - -int ipath_user_add(struct ipath_devdata *dd) -{ - char name[10]; - int ret; - - if (atomic_inc_return(&user_count) == 1) { - ret = user_init(); - if (ret < 0) { - ipath_dev_err(dd, "Unable to set up user support: " - "error %d\n", -ret); - goto bail; - } - ret = init_cdev(0, "ipath", &ipath_file_ops, &wildcard_cdev, - &wildcard_dev); - if (ret < 0) { - ipath_dev_err(dd, "Could not create wildcard " - "minor: error %d\n", -ret); - goto bail_user; - } - - atomic_set(&user_setup, 1); - } - - snprintf(name, sizeof(name), "ipath%d", dd->ipath_unit); - - ret = init_cdev(dd->ipath_unit + 1, name, &ipath_file_ops, - &dd->user_cdev, &dd->user_dev); - if (ret < 0) - ipath_dev_err(dd, "Could not create user minor %d, %s\n", - dd->ipath_unit + 1, name); - - goto bail; - -bail_user: - user_cleanup(); -bail: - return ret; -} - -void ipath_user_remove(struct ipath_devdata *dd) -{ - cleanup_cdev(&dd->user_cdev, &dd->user_dev); - - if (atomic_dec_return(&user_count) == 0) { - if (atomic_read(&user_setup) == 0) - goto bail; - - cleanup_cdev(&wildcard_cdev, &wildcard_dev); - user_cleanup(); - - atomic_set(&user_setup, 0); - } -bail: - return; -} diff --git a/drivers/staging/rdma/ipath/ipath_fs.c b/drivers/staging/rdma/ipath/ipath_fs.c deleted file mode 100644 index 476fcdf05acb..000000000000 --- a/drivers/staging/rdma/ipath/ipath_fs.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. - * Copyright (c) 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "ipath_kernel.h" - -#define IPATHFS_MAGIC 0x726a77 - -static struct super_block *ipath_super; - -static int ipathfs_mknod(struct inode *dir, struct dentry *dentry, - umode_t mode, const struct file_operations *fops, - void *data) -{ - int error; - struct inode *inode = new_inode(dir->i_sb); - - if (!inode) { - error = -EPERM; - goto bail; - } - - inode->i_ino = get_next_ino(); - inode->i_mode = mode; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - inode->i_private = data; - if (S_ISDIR(mode)) { - inode->i_op = &simple_dir_inode_operations; - inc_nlink(inode); - inc_nlink(dir); - } - - inode->i_fop = fops; - - d_instantiate(dentry, inode); - error = 0; - -bail: - return error; -} - -static int create_file(const char *name, umode_t mode, - struct dentry *parent, struct dentry **dentry, - const struct file_operations *fops, void *data) -{ - int error; - - inode_lock(d_inode(parent)); - *dentry = lookup_one_len(name, parent, strlen(name)); - if (!IS_ERR(*dentry)) - error = ipathfs_mknod(d_inode(parent), *dentry, - mode, fops, data); - else - error = PTR_ERR(*dentry); - inode_unlock(d_inode(parent)); - - return error; -} - -static ssize_t atomic_stats_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - return simple_read_from_buffer(buf, count, ppos, &ipath_stats, - sizeof ipath_stats); -} - -static const struct file_operations atomic_stats_ops = { - .read = atomic_stats_read, - .llseek = default_llseek, -}; - -static ssize_t atomic_counters_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct infinipath_counters counters; - struct ipath_devdata *dd; - - dd = file_inode(file)->i_private; - dd->ipath_f_read_counters(dd, &counters); - - return simple_read_from_buffer(buf, count, ppos, &counters, - sizeof counters); -} - -static const struct file_operations atomic_counters_ops = { - .read = atomic_counters_read, - .llseek = default_llseek, -}; - -static ssize_t flash_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct ipath_devdata *dd; - ssize_t ret; - loff_t pos; - char *tmp; - - pos = *ppos; - - if ( pos < 0) { - ret = -EINVAL; - goto bail; - } - - if (pos >= sizeof(struct ipath_flash)) { - ret = 0; - goto bail; - } - - if (count > sizeof(struct ipath_flash) - pos) - count = sizeof(struct ipath_flash) - pos; - - tmp = kmalloc(count, GFP_KERNEL); - if (!tmp) { - ret = -ENOMEM; - goto bail; - } - - dd = file_inode(file)->i_private; - if (ipath_eeprom_read(dd, pos, tmp, count)) { - ipath_dev_err(dd, "failed to read from flash\n"); - ret = -ENXIO; - goto bail_tmp; - } - - if (copy_to_user(buf, tmp, count)) { - ret = -EFAULT; - goto bail_tmp; - } - - *ppos = pos + count; - ret = count; - -bail_tmp: - kfree(tmp); - -bail: - return ret; -} - -static ssize_t flash_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - struct ipath_devdata *dd; - ssize_t ret; - loff_t pos; - char *tmp; - - pos = *ppos; - - if (pos != 0) { - ret = -EINVAL; - goto bail; - } - - if (count != sizeof(struct ipath_flash)) { - ret = -EINVAL; - goto bail; - } - - tmp = memdup_user(buf, count); - if (IS_ERR(tmp)) - return PTR_ERR(tmp); - - dd = file_inode(file)->i_private; - if (ipath_eeprom_write(dd, pos, tmp, count)) { - ret = -ENXIO; - ipath_dev_err(dd, "failed to write to flash\n"); - goto bail_tmp; - } - - *ppos = pos + count; - ret = count; - -bail_tmp: - kfree(tmp); - -bail: - return ret; -} - -static const struct file_operations flash_ops = { - .read = flash_read, - .write = flash_write, - .llseek = default_llseek, -}; - -static int create_device_files(struct super_block *sb, - struct ipath_devdata *dd) -{ - struct dentry *dir, *tmp; - char unit[10]; - int ret; - - snprintf(unit, sizeof unit, "%02d", dd->ipath_unit); - ret = create_file(unit, S_IFDIR|S_IRUGO|S_IXUGO, sb->s_root, &dir, - &simple_dir_operations, dd); - if (ret) { - printk(KERN_ERR "create_file(%s) failed: %d\n", unit, ret); - goto bail; - } - - ret = create_file("atomic_counters", S_IFREG|S_IRUGO, dir, &tmp, - &atomic_counters_ops, dd); - if (ret) { - printk(KERN_ERR "create_file(%s/atomic_counters) " - "failed: %d\n", unit, ret); - goto bail; - } - - ret = create_file("flash", S_IFREG|S_IWUSR|S_IRUGO, dir, &tmp, - &flash_ops, dd); - if (ret) { - printk(KERN_ERR "create_file(%s/flash) " - "failed: %d\n", unit, ret); - goto bail; - } - -bail: - return ret; -} - -static int remove_file(struct dentry *parent, char *name) -{ - struct dentry *tmp; - int ret; - - tmp = lookup_one_len(name, parent, strlen(name)); - - if (IS_ERR(tmp)) { - ret = PTR_ERR(tmp); - goto bail; - } - - spin_lock(&tmp->d_lock); - if (simple_positive(tmp)) { - dget_dlock(tmp); - __d_drop(tmp); - spin_unlock(&tmp->d_lock); - simple_unlink(d_inode(parent), tmp); - } else - spin_unlock(&tmp->d_lock); - - ret = 0; -bail: - /* - * We don't expect clients to care about the return value, but - * it's there if they need it. - */ - return ret; -} - -static int remove_device_files(struct super_block *sb, - struct ipath_devdata *dd) -{ - struct dentry *dir, *root; - char unit[10]; - int ret; - - root = dget(sb->s_root); - inode_lock(d_inode(root)); - snprintf(unit, sizeof unit, "%02d", dd->ipath_unit); - dir = lookup_one_len(unit, root, strlen(unit)); - - if (IS_ERR(dir)) { - ret = PTR_ERR(dir); - printk(KERN_ERR "Lookup of %s failed\n", unit); - goto bail; - } - - remove_file(dir, "flash"); - remove_file(dir, "atomic_counters"); - d_delete(dir); - ret = simple_rmdir(d_inode(root), dir); - -bail: - inode_unlock(d_inode(root)); - dput(root); - return ret; -} - -static int ipathfs_fill_super(struct super_block *sb, void *data, - int silent) -{ - struct ipath_devdata *dd, *tmp; - unsigned long flags; - int ret; - - static struct tree_descr files[] = { - [2] = {"atomic_stats", &atomic_stats_ops, S_IRUGO}, - {""}, - }; - - ret = simple_fill_super(sb, IPATHFS_MAGIC, files); - if (ret) { - printk(KERN_ERR "simple_fill_super failed: %d\n", ret); - goto bail; - } - - spin_lock_irqsave(&ipath_devs_lock, flags); - - list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) { - spin_unlock_irqrestore(&ipath_devs_lock, flags); - ret = create_device_files(sb, dd); - if (ret) - goto bail; - spin_lock_irqsave(&ipath_devs_lock, flags); - } - - spin_unlock_irqrestore(&ipath_devs_lock, flags); - -bail: - return ret; -} - -static struct dentry *ipathfs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) -{ - struct dentry *ret; - ret = mount_single(fs_type, flags, data, ipathfs_fill_super); - if (!IS_ERR(ret)) - ipath_super = ret->d_sb; - return ret; -} - -static void ipathfs_kill_super(struct super_block *s) -{ - kill_litter_super(s); - ipath_super = NULL; -} - -int ipathfs_add_device(struct ipath_devdata *dd) -{ - int ret; - - if (ipath_super == NULL) { - ret = 0; - goto bail; - } - - ret = create_device_files(ipath_super, dd); - -bail: - return ret; -} - -int ipathfs_remove_device(struct ipath_devdata *dd) -{ - int ret; - - if (ipath_super == NULL) { - ret = 0; - goto bail; - } - - ret = remove_device_files(ipath_super, dd); - -bail: - return ret; -} - -static struct file_system_type ipathfs_fs_type = { - .owner = THIS_MODULE, - .name = "ipathfs", - .mount = ipathfs_mount, - .kill_sb = ipathfs_kill_super, -}; -MODULE_ALIAS_FS("ipathfs"); - -int __init ipath_init_ipathfs(void) -{ - return register_filesystem(&ipathfs_fs_type); -} - -void __exit ipath_exit_ipathfs(void) -{ - unregister_filesystem(&ipathfs_fs_type); -} diff --git a/drivers/staging/rdma/ipath/ipath_iba6110.c b/drivers/staging/rdma/ipath/ipath_iba6110.c deleted file mode 100644 index 5f13572a5e24..000000000000 --- a/drivers/staging/rdma/ipath/ipath_iba6110.c +++ /dev/null @@ -1,1939 +0,0 @@ -/* - * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. - * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * This file contains all of the code that is specific to the InfiniPath - * HT chip. - */ - -#include -#include -#include -#include -#include - -#include "ipath_kernel.h" -#include "ipath_registers.h" - -static void ipath_setup_ht_setextled(struct ipath_devdata *, u64, u64); - - -/* - * This lists the InfiniPath registers, in the actual chip layout. - * This structure should never be directly accessed. - * - * The names are in InterCap form because they're taken straight from - * the chip specification. Since they're only used in this file, they - * don't pollute the rest of the source. -*/ - -struct _infinipath_do_not_use_kernel_regs { - unsigned long long Revision; - unsigned long long Control; - unsigned long long PageAlign; - unsigned long long PortCnt; - unsigned long long DebugPortSelect; - unsigned long long DebugPort; - unsigned long long SendRegBase; - unsigned long long UserRegBase; - unsigned long long CounterRegBase; - unsigned long long Scratch; - unsigned long long ReservedMisc1; - unsigned long long InterruptConfig; - unsigned long long IntBlocked; - unsigned long long IntMask; - unsigned long long IntStatus; - unsigned long long IntClear; - unsigned long long ErrorMask; - unsigned long long ErrorStatus; - unsigned long long ErrorClear; - unsigned long long HwErrMask; - unsigned long long HwErrStatus; - unsigned long long HwErrClear; - unsigned long long HwDiagCtrl; - unsigned long long MDIO; - unsigned long long IBCStatus; - unsigned long long IBCCtrl; - unsigned long long ExtStatus; - unsigned long long ExtCtrl; - unsigned long long GPIOOut; - unsigned long long GPIOMask; - unsigned long long GPIOStatus; - unsigned long long GPIOClear; - unsigned long long RcvCtrl; - unsigned long long RcvBTHQP; - unsigned long long RcvHdrSize; - unsigned long long RcvHdrCnt; - unsigned long long RcvHdrEntSize; - unsigned long long RcvTIDBase; - unsigned long long RcvTIDCnt; - unsigned long long RcvEgrBase; - unsigned long long RcvEgrCnt; - unsigned long long RcvBufBase; - unsigned long long RcvBufSize; - unsigned long long RxIntMemBase; - unsigned long long RxIntMemSize; - unsigned long long RcvPartitionKey; - unsigned long long ReservedRcv[10]; - unsigned long long SendCtrl; - unsigned long long SendPIOBufBase; - unsigned long long SendPIOSize; - unsigned long long SendPIOBufCnt; - unsigned long long SendPIOAvailAddr; - unsigned long long TxIntMemBase; - unsigned long long TxIntMemSize; - unsigned long long ReservedSend[9]; - unsigned long long SendBufferError; - unsigned long long SendBufferErrorCONT1; - unsigned long long SendBufferErrorCONT2; - unsigned long long SendBufferErrorCONT3; - unsigned long long ReservedSBE[4]; - unsigned long long RcvHdrAddr0; - unsigned long long RcvHdrAddr1; - unsigned long long RcvHdrAddr2; - unsigned long long RcvHdrAddr3; - unsigned long long RcvHdrAddr4; - unsigned long long RcvHdrAddr5; - unsigned long long RcvHdrAddr6; - unsigned long long RcvHdrAddr7; - unsigned long long RcvHdrAddr8; - unsigned long long ReservedRHA[7]; - unsigned long long RcvHdrTailAddr0; - unsigned long long RcvHdrTailAddr1; - unsigned long long RcvHdrTailAddr2; - unsigned long long RcvHdrTailAddr3; - unsigned long long RcvHdrTailAddr4; - unsigned long long RcvHdrTailAddr5; - unsigned long long RcvHdrTailAddr6; - unsigned long long RcvHdrTailAddr7; - unsigned long long RcvHdrTailAddr8; - unsigned long long ReservedRHTA[7]; - unsigned long long Sync; /* Software only */ - unsigned long long Dump; /* Software only */ - unsigned long long SimVer; /* Software only */ - unsigned long long ReservedSW[5]; - unsigned long long SerdesConfig0; - unsigned long long SerdesConfig1; - unsigned long long SerdesStatus; - unsigned long long XGXSConfig; - unsigned long long ReservedSW2[4]; -}; - -struct _infinipath_do_not_use_counters { - __u64 LBIntCnt; - __u64 LBFlowStallCnt; - __u64 Reserved1; - __u64 TxUnsupVLErrCnt; - __u64 TxDataPktCnt; - __u64 TxFlowPktCnt; - __u64 TxDwordCnt; - __u64 TxLenErrCnt; - __u64 TxMaxMinLenErrCnt; - __u64 TxUnderrunCnt; - __u64 TxFlowStallCnt; - __u64 TxDroppedPktCnt; - __u64 RxDroppedPktCnt; - __u64 RxDataPktCnt; - __u64 RxFlowPktCnt; - __u64 RxDwordCnt; - __u64 RxLenErrCnt; - __u64 RxMaxMinLenErrCnt; - __u64 RxICRCErrCnt; - __u64 RxVCRCErrCnt; - __u64 RxFlowCtrlErrCnt; - __u64 RxBadFormatCnt; - __u64 RxLinkProblemCnt; - __u64 RxEBPCnt; - __u64 RxLPCRCErrCnt; - __u64 RxBufOvflCnt; - __u64 RxTIDFullErrCnt; - __u64 RxTIDValidErrCnt; - __u64 RxPKeyMismatchCnt; - __u64 RxP0HdrEgrOvflCnt; - __u64 RxP1HdrEgrOvflCnt; - __u64 RxP2HdrEgrOvflCnt; - __u64 RxP3HdrEgrOvflCnt; - __u64 RxP4HdrEgrOvflCnt; - __u64 RxP5HdrEgrOvflCnt; - __u64 RxP6HdrEgrOvflCnt; - __u64 RxP7HdrEgrOvflCnt; - __u64 RxP8HdrEgrOvflCnt; - __u64 Reserved6; - __u64 Reserved7; - __u64 IBStatusChangeCnt; - __u64 IBLinkErrRecoveryCnt; - __u64 IBLinkDownedCnt; - __u64 IBSymbolErrCnt; -}; - -#define IPATH_KREG_OFFSET(field) (offsetof( \ - struct _infinipath_do_not_use_kernel_regs, field) / sizeof(u64)) -#define IPATH_CREG_OFFSET(field) (offsetof( \ - struct _infinipath_do_not_use_counters, field) / sizeof(u64)) - -static const struct ipath_kregs ipath_ht_kregs = { - .kr_control = IPATH_KREG_OFFSET(Control), - .kr_counterregbase = IPATH_KREG_OFFSET(CounterRegBase), - .kr_debugport = IPATH_KREG_OFFSET(DebugPort), - .kr_debugportselect = IPATH_KREG_OFFSET(DebugPortSelect), - .kr_errorclear = IPATH_KREG_OFFSET(ErrorClear), - .kr_errormask = IPATH_KREG_OFFSET(ErrorMask), - .kr_errorstatus = IPATH_KREG_OFFSET(ErrorStatus), - .kr_extctrl = IPATH_KREG_OFFSET(ExtCtrl), - .kr_extstatus = IPATH_KREG_OFFSET(ExtStatus), - .kr_gpio_clear = IPATH_KREG_OFFSET(GPIOClear), - .kr_gpio_mask = IPATH_KREG_OFFSET(GPIOMask), - .kr_gpio_out = IPATH_KREG_OFFSET(GPIOOut), - .kr_gpio_status = IPATH_KREG_OFFSET(GPIOStatus), - .kr_hwdiagctrl = IPATH_KREG_OFFSET(HwDiagCtrl), - .kr_hwerrclear = IPATH_KREG_OFFSET(HwErrClear), - .kr_hwerrmask = IPATH_KREG_OFFSET(HwErrMask), - .kr_hwerrstatus = IPATH_KREG_OFFSET(HwErrStatus), - .kr_ibcctrl = IPATH_KREG_OFFSET(IBCCtrl), - .kr_ibcstatus = IPATH_KREG_OFFSET(IBCStatus), - .kr_intblocked = IPATH_KREG_OFFSET(IntBlocked), - .kr_intclear = IPATH_KREG_OFFSET(IntClear), - .kr_interruptconfig = IPATH_KREG_OFFSET(InterruptConfig), - .kr_intmask = IPATH_KREG_OFFSET(IntMask), - .kr_intstatus = IPATH_KREG_OFFSET(IntStatus), - .kr_mdio = IPATH_KREG_OFFSET(MDIO), - .kr_pagealign = IPATH_KREG_OFFSET(PageAlign), - .kr_partitionkey = IPATH_KREG_OFFSET(RcvPartitionKey), - .kr_portcnt = IPATH_KREG_OFFSET(PortCnt), - .kr_rcvbthqp = IPATH_KREG_OFFSET(RcvBTHQP), - .kr_rcvbufbase = IPATH_KREG_OFFSET(RcvBufBase), - .kr_rcvbufsize = IPATH_KREG_OFFSET(RcvBufSize), - .kr_rcvctrl = IPATH_KREG_OFFSET(RcvCtrl), - .kr_rcvegrbase = IPATH_KREG_OFFSET(RcvEgrBase), - .kr_rcvegrcnt = IPATH_KREG_OFFSET(RcvEgrCnt), - .kr_rcvhdrcnt = IPATH_KREG_OFFSET(RcvHdrCnt), - .kr_rcvhdrentsize = IPATH_KREG_OFFSET(RcvHdrEntSize), - .kr_rcvhdrsize = IPATH_KREG_OFFSET(RcvHdrSize), - .kr_rcvintmembase = IPATH_KREG_OFFSET(RxIntMemBase), - .kr_rcvintmemsize = IPATH_KREG_OFFSET(RxIntMemSize), - .kr_rcvtidbase = IPATH_KREG_OFFSET(RcvTIDBase), - .kr_rcvtidcnt = IPATH_KREG_OFFSET(RcvTIDCnt), - .kr_revision = IPATH_KREG_OFFSET(Revision), - .kr_scratch = IPATH_KREG_OFFSET(Scratch), - .kr_sendbuffererror = IPATH_KREG_OFFSET(SendBufferError), - .kr_sendctrl = IPATH_KREG_OFFSET(SendCtrl), - .kr_sendpioavailaddr = IPATH_KREG_OFFSET(SendPIOAvailAddr), - .kr_sendpiobufbase = IPATH_KREG_OFFSET(SendPIOBufBase), - .kr_sendpiobufcnt = IPATH_KREG_OFFSET(SendPIOBufCnt), - .kr_sendpiosize = IPATH_KREG_OFFSET(SendPIOSize), - .kr_sendregbase = IPATH_KREG_OFFSET(SendRegBase), - .kr_txintmembase = IPATH_KREG_OFFSET(TxIntMemBase), - .kr_txintmemsize = IPATH_KREG_OFFSET(TxIntMemSize), - .kr_userregbase = IPATH_KREG_OFFSET(UserRegBase), - .kr_serdesconfig0 = IPATH_KREG_OFFSET(SerdesConfig0), - .kr_serdesconfig1 = IPATH_KREG_OFFSET(SerdesConfig1), - .kr_serdesstatus = IPATH_KREG_OFFSET(SerdesStatus), - .kr_xgxsconfig = IPATH_KREG_OFFSET(XGXSConfig), - /* - * These should not be used directly via ipath_write_kreg64(), - * use them with ipath_write_kreg64_port(), - */ - .kr_rcvhdraddr = IPATH_KREG_OFFSET(RcvHdrAddr0), - .kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0) -}; - -static const struct ipath_cregs ipath_ht_cregs = { - .cr_badformatcnt = IPATH_CREG_OFFSET(RxBadFormatCnt), - .cr_erricrccnt = IPATH_CREG_OFFSET(RxICRCErrCnt), - .cr_errlinkcnt = IPATH_CREG_OFFSET(RxLinkProblemCnt), - .cr_errlpcrccnt = IPATH_CREG_OFFSET(RxLPCRCErrCnt), - .cr_errpkey = IPATH_CREG_OFFSET(RxPKeyMismatchCnt), - .cr_errrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowCtrlErrCnt), - .cr_err_rlencnt = IPATH_CREG_OFFSET(RxLenErrCnt), - .cr_errslencnt = IPATH_CREG_OFFSET(TxLenErrCnt), - .cr_errtidfull = IPATH_CREG_OFFSET(RxTIDFullErrCnt), - .cr_errtidvalid = IPATH_CREG_OFFSET(RxTIDValidErrCnt), - .cr_errvcrccnt = IPATH_CREG_OFFSET(RxVCRCErrCnt), - .cr_ibstatuschange = IPATH_CREG_OFFSET(IBStatusChangeCnt), - /* calc from Reg_CounterRegBase + offset */ - .cr_intcnt = IPATH_CREG_OFFSET(LBIntCnt), - .cr_invalidrlencnt = IPATH_CREG_OFFSET(RxMaxMinLenErrCnt), - .cr_invalidslencnt = IPATH_CREG_OFFSET(TxMaxMinLenErrCnt), - .cr_lbflowstallcnt = IPATH_CREG_OFFSET(LBFlowStallCnt), - .cr_pktrcvcnt = IPATH_CREG_OFFSET(RxDataPktCnt), - .cr_pktrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowPktCnt), - .cr_pktsendcnt = IPATH_CREG_OFFSET(TxDataPktCnt), - .cr_pktsendflowcnt = IPATH_CREG_OFFSET(TxFlowPktCnt), - .cr_portovflcnt = IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt), - .cr_rcvebpcnt = IPATH_CREG_OFFSET(RxEBPCnt), - .cr_rcvovflcnt = IPATH_CREG_OFFSET(RxBufOvflCnt), - .cr_senddropped = IPATH_CREG_OFFSET(TxDroppedPktCnt), - .cr_sendstallcnt = IPATH_CREG_OFFSET(TxFlowStallCnt), - .cr_sendunderruncnt = IPATH_CREG_OFFSET(TxUnderrunCnt), - .cr_wordrcvcnt = IPATH_CREG_OFFSET(RxDwordCnt), - .cr_wordsendcnt = IPATH_CREG_OFFSET(TxDwordCnt), - .cr_unsupvlcnt = IPATH_CREG_OFFSET(TxUnsupVLErrCnt), - .cr_rxdroppktcnt = IPATH_CREG_OFFSET(RxDroppedPktCnt), - .cr_iblinkerrrecovcnt = IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt), - .cr_iblinkdowncnt = IPATH_CREG_OFFSET(IBLinkDownedCnt), - .cr_ibsymbolerrcnt = IPATH_CREG_OFFSET(IBSymbolErrCnt) -}; - -/* kr_intstatus, kr_intclear, kr_intmask bits */ -#define INFINIPATH_I_RCVURG_MASK ((1U<<9)-1) -#define INFINIPATH_I_RCVURG_SHIFT 0 -#define INFINIPATH_I_RCVAVAIL_MASK ((1U<<9)-1) -#define INFINIPATH_I_RCVAVAIL_SHIFT 12 - -/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */ -#define INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT 0 -#define INFINIPATH_HWE_HTCMEMPARITYERR_MASK 0x3FFFFFULL -#define INFINIPATH_HWE_HTCLNKABYTE0CRCERR 0x0000000000800000ULL -#define INFINIPATH_HWE_HTCLNKABYTE1CRCERR 0x0000000001000000ULL -#define INFINIPATH_HWE_HTCLNKBBYTE0CRCERR 0x0000000002000000ULL -#define INFINIPATH_HWE_HTCLNKBBYTE1CRCERR 0x0000000004000000ULL -#define INFINIPATH_HWE_HTCMISCERR4 0x0000000008000000ULL -#define INFINIPATH_HWE_HTCMISCERR5 0x0000000010000000ULL -#define INFINIPATH_HWE_HTCMISCERR6 0x0000000020000000ULL -#define INFINIPATH_HWE_HTCMISCERR7 0x0000000040000000ULL -#define INFINIPATH_HWE_HTCBUSTREQPARITYERR 0x0000000080000000ULL -#define INFINIPATH_HWE_HTCBUSTRESPPARITYERR 0x0000000100000000ULL -#define INFINIPATH_HWE_HTCBUSIREQPARITYERR 0x0000000200000000ULL -#define INFINIPATH_HWE_COREPLL_FBSLIP 0x0080000000000000ULL -#define INFINIPATH_HWE_COREPLL_RFSLIP 0x0100000000000000ULL -#define INFINIPATH_HWE_HTBPLL_FBSLIP 0x0200000000000000ULL -#define INFINIPATH_HWE_HTBPLL_RFSLIP 0x0400000000000000ULL -#define INFINIPATH_HWE_HTAPLL_FBSLIP 0x0800000000000000ULL -#define INFINIPATH_HWE_HTAPLL_RFSLIP 0x1000000000000000ULL -#define INFINIPATH_HWE_SERDESPLLFAILED 0x2000000000000000ULL - -#define IBA6110_IBCS_LINKTRAININGSTATE_MASK 0xf -#define IBA6110_IBCS_LINKSTATE_SHIFT 4 - -/* kr_extstatus bits */ -#define INFINIPATH_EXTS_FREQSEL 0x2 -#define INFINIPATH_EXTS_SERDESSEL 0x4 -#define INFINIPATH_EXTS_MEMBIST_ENDTEST 0x0000000000004000 -#define INFINIPATH_EXTS_MEMBIST_CORRECT 0x0000000000008000 - - -/* TID entries (memory), HT-only */ -#define INFINIPATH_RT_ADDR_MASK 0xFFFFFFFFFFULL /* 40 bits valid */ -#define INFINIPATH_RT_VALID 0x8000000000000000ULL -#define INFINIPATH_RT_ADDR_SHIFT 0 -#define INFINIPATH_RT_BUFSIZE_MASK 0x3FFFULL -#define INFINIPATH_RT_BUFSIZE_SHIFT 48 - -#define INFINIPATH_R_INTRAVAIL_SHIFT 16 -#define INFINIPATH_R_TAILUPD_SHIFT 31 - -/* kr_xgxsconfig bits */ -#define INFINIPATH_XGXS_RESET 0x7ULL - -/* - * masks and bits that are different in different chips, or present only - * in one - */ -static const ipath_err_t infinipath_hwe_htcmemparityerr_mask = - INFINIPATH_HWE_HTCMEMPARITYERR_MASK; -static const ipath_err_t infinipath_hwe_htcmemparityerr_shift = - INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT; - -static const ipath_err_t infinipath_hwe_htclnkabyte0crcerr = - INFINIPATH_HWE_HTCLNKABYTE0CRCERR; -static const ipath_err_t infinipath_hwe_htclnkabyte1crcerr = - INFINIPATH_HWE_HTCLNKABYTE1CRCERR; -static const ipath_err_t infinipath_hwe_htclnkbbyte0crcerr = - INFINIPATH_HWE_HTCLNKBBYTE0CRCERR; -static const ipath_err_t infinipath_hwe_htclnkbbyte1crcerr = - INFINIPATH_HWE_HTCLNKBBYTE1CRCERR; - -#define _IPATH_GPIO_SDA_NUM 1 -#define _IPATH_GPIO_SCL_NUM 0 - -#define IPATH_GPIO_SDA \ - (1ULL << (_IPATH_GPIO_SDA_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT)) -#define IPATH_GPIO_SCL \ - (1ULL << (_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT)) - -/* keep the code below somewhat more readable; not used elsewhere */ -#define _IPATH_HTLINK0_CRCBITS (infinipath_hwe_htclnkabyte0crcerr | \ - infinipath_hwe_htclnkabyte1crcerr) -#define _IPATH_HTLINK1_CRCBITS (infinipath_hwe_htclnkbbyte0crcerr | \ - infinipath_hwe_htclnkbbyte1crcerr) -#define _IPATH_HTLANE0_CRCBITS (infinipath_hwe_htclnkabyte0crcerr | \ - infinipath_hwe_htclnkbbyte0crcerr) -#define _IPATH_HTLANE1_CRCBITS (infinipath_hwe_htclnkabyte1crcerr | \ - infinipath_hwe_htclnkbbyte1crcerr) - -static void hwerr_crcbits(struct ipath_devdata *dd, ipath_err_t hwerrs, - char *msg, size_t msgl) -{ - char bitsmsg[64]; - ipath_err_t crcbits = hwerrs & - (_IPATH_HTLINK0_CRCBITS | _IPATH_HTLINK1_CRCBITS); - /* don't check if 8bit HT */ - if (dd->ipath_flags & IPATH_8BIT_IN_HT0) - crcbits &= ~infinipath_hwe_htclnkabyte1crcerr; - /* don't check if 8bit HT */ - if (dd->ipath_flags & IPATH_8BIT_IN_HT1) - crcbits &= ~infinipath_hwe_htclnkbbyte1crcerr; - /* - * we'll want to ignore link errors on link that is - * not in use, if any. For now, complain about both - */ - if (crcbits) { - u16 ctrl0, ctrl1; - snprintf(bitsmsg, sizeof bitsmsg, - "[HT%s lane %s CRC (%llx); powercycle to completely clear]", - !(crcbits & _IPATH_HTLINK1_CRCBITS) ? - "0 (A)" : (!(crcbits & _IPATH_HTLINK0_CRCBITS) - ? "1 (B)" : "0+1 (A+B)"), - !(crcbits & _IPATH_HTLANE1_CRCBITS) ? "0" - : (!(crcbits & _IPATH_HTLANE0_CRCBITS) ? "1" : - "0+1"), (unsigned long long) crcbits); - strlcat(msg, bitsmsg, msgl); - - /* - * print extra info for debugging. slave/primary - * config word 4, 8 (link control 0, 1) - */ - - if (pci_read_config_word(dd->pcidev, - dd->ipath_ht_slave_off + 0x4, - &ctrl0)) - dev_info(&dd->pcidev->dev, "Couldn't read " - "linkctrl0 of slave/primary " - "config block\n"); - else if (!(ctrl0 & 1 << 6)) - /* not if EOC bit set */ - ipath_dbg("HT linkctrl0 0x%x%s%s\n", ctrl0, - ((ctrl0 >> 8) & 7) ? " CRC" : "", - ((ctrl0 >> 4) & 1) ? "linkfail" : - ""); - if (pci_read_config_word(dd->pcidev, - dd->ipath_ht_slave_off + 0x8, - &ctrl1)) - dev_info(&dd->pcidev->dev, "Couldn't read " - "linkctrl1 of slave/primary " - "config block\n"); - else if (!(ctrl1 & 1 << 6)) - /* not if EOC bit set */ - ipath_dbg("HT linkctrl1 0x%x%s%s\n", ctrl1, - ((ctrl1 >> 8) & 7) ? " CRC" : "", - ((ctrl1 >> 4) & 1) ? "linkfail" : - ""); - - /* disable until driver reloaded */ - dd->ipath_hwerrmask &= ~crcbits; - ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, - dd->ipath_hwerrmask); - ipath_dbg("HT crc errs: %s\n", msg); - } else - ipath_dbg("ignoring HT crc errors 0x%llx, " - "not in use\n", (unsigned long long) - (hwerrs & (_IPATH_HTLINK0_CRCBITS | - _IPATH_HTLINK1_CRCBITS))); -} - -/* 6110 specific hardware errors... */ -static const struct ipath_hwerror_msgs ipath_6110_hwerror_msgs[] = { - INFINIPATH_HWE_MSG(HTCBUSIREQPARITYERR, "HTC Ireq Parity"), - INFINIPATH_HWE_MSG(HTCBUSTREQPARITYERR, "HTC Treq Parity"), - INFINIPATH_HWE_MSG(HTCBUSTRESPPARITYERR, "HTC Tresp Parity"), - INFINIPATH_HWE_MSG(HTCMISCERR5, "HT core Misc5"), - INFINIPATH_HWE_MSG(HTCMISCERR6, "HT core Misc6"), - INFINIPATH_HWE_MSG(HTCMISCERR7, "HT core Misc7"), - INFINIPATH_HWE_MSG(RXDSYNCMEMPARITYERR, "Rx Dsync"), - INFINIPATH_HWE_MSG(SERDESPLLFAILED, "SerDes PLL"), -}; - -#define TXE_PIO_PARITY ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF | \ - INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC) \ - << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) -#define RXE_EAGER_PARITY (INFINIPATH_HWE_RXEMEMPARITYERR_EAGERTID \ - << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) - -static void ipath_ht_txe_recover(struct ipath_devdata *dd) -{ - ++ipath_stats.sps_txeparity; - dev_info(&dd->pcidev->dev, - "Recovering from TXE PIO parity error\n"); -} - - -/** - * ipath_ht_handle_hwerrors - display hardware errors. - * @dd: the infinipath device - * @msg: the output buffer - * @msgl: the size of the output buffer - * - * Use same msg buffer as regular errors to avoid excessive stack - * use. Most hardware errors are catastrophic, but for right now, - * we'll print them and continue. We reuse the same message buffer as - * ipath_handle_errors() to avoid excessive stack usage. - */ -static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg, - size_t msgl) -{ - ipath_err_t hwerrs; - u32 bits, ctrl; - int isfatal = 0; - char bitsmsg[64]; - int log_idx; - - hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus); - - if (!hwerrs) { - ipath_cdbg(VERBOSE, "Called but no hardware errors set\n"); - /* - * better than printing cofusing messages - * This seems to be related to clearing the crc error, or - * the pll error during init. - */ - goto bail; - } else if (hwerrs == -1LL) { - ipath_dev_err(dd, "Read of hardware error status failed " - "(all bits set); ignoring\n"); - goto bail; - } - ipath_stats.sps_hwerrs++; - - /* Always clear the error status register, except MEMBISTFAIL, - * regardless of whether we continue or stop using the chip. - * We want that set so we know it failed, even across driver reload. - * We'll still ignore it in the hwerrmask. We do this partly for - * diagnostics, but also for support */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, - hwerrs&~INFINIPATH_HWE_MEMBISTFAILED); - - hwerrs &= dd->ipath_hwerrmask; - - /* We log some errors to EEPROM, check if we have any of those. */ - for (log_idx = 0; log_idx < IPATH_EEP_LOG_CNT; ++log_idx) - if (hwerrs & dd->ipath_eep_st_masks[log_idx].hwerrs_to_log) - ipath_inc_eeprom_err(dd, log_idx, 1); - - /* - * make sure we get this much out, unless told to be quiet, - * it's a parity error we may recover from, - * or it's occurred within the last 5 seconds - */ - if ((hwerrs & ~(dd->ipath_lasthwerror | TXE_PIO_PARITY | - RXE_EAGER_PARITY)) || - (ipath_debug & __IPATH_VERBDBG)) - dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx " - "(cleared)\n", (unsigned long long) hwerrs); - dd->ipath_lasthwerror |= hwerrs; - - if (hwerrs & ~dd->ipath_hwe_bitsextant) - ipath_dev_err(dd, "hwerror interrupt with unknown errors " - "%llx set\n", (unsigned long long) - (hwerrs & ~dd->ipath_hwe_bitsextant)); - - ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control); - if ((ctrl & INFINIPATH_C_FREEZEMODE) && !ipath_diag_inuse) { - /* - * parity errors in send memory are recoverable, - * just cancel the send (if indicated in * sendbuffererror), - * count the occurrence, unfreeze (if no other handled - * hardware error bits are set), and continue. They can - * occur if a processor speculative read is done to the PIO - * buffer while we are sending a packet, for example. - */ - if (hwerrs & TXE_PIO_PARITY) { - ipath_ht_txe_recover(dd); - hwerrs &= ~TXE_PIO_PARITY; - } - - if (!hwerrs) { - ipath_dbg("Clearing freezemode on ignored or " - "recovered hardware error\n"); - ipath_clear_freeze(dd); - } - } - - *msg = '\0'; - - /* - * may someday want to decode into which bits are which - * functional area for parity errors, etc. - */ - if (hwerrs & (infinipath_hwe_htcmemparityerr_mask - << INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT)) { - bits = (u32) ((hwerrs >> - INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT) & - INFINIPATH_HWE_HTCMEMPARITYERR_MASK); - snprintf(bitsmsg, sizeof bitsmsg, "[HTC Parity Errs %x] ", - bits); - strlcat(msg, bitsmsg, msgl); - } - - ipath_format_hwerrors(hwerrs, - ipath_6110_hwerror_msgs, - ARRAY_SIZE(ipath_6110_hwerror_msgs), - msg, msgl); - - if (hwerrs & (_IPATH_HTLINK0_CRCBITS | _IPATH_HTLINK1_CRCBITS)) - hwerr_crcbits(dd, hwerrs, msg, msgl); - - if (hwerrs & INFINIPATH_HWE_MEMBISTFAILED) { - strlcat(msg, "[Memory BIST test failed, InfiniPath hardware unusable]", - msgl); - /* ignore from now on, so disable until driver reloaded */ - dd->ipath_hwerrmask &= ~INFINIPATH_HWE_MEMBISTFAILED; - ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, - dd->ipath_hwerrmask); - } -#define _IPATH_PLL_FAIL (INFINIPATH_HWE_COREPLL_FBSLIP | \ - INFINIPATH_HWE_COREPLL_RFSLIP | \ - INFINIPATH_HWE_HTBPLL_FBSLIP | \ - INFINIPATH_HWE_HTBPLL_RFSLIP | \ - INFINIPATH_HWE_HTAPLL_FBSLIP | \ - INFINIPATH_HWE_HTAPLL_RFSLIP) - - if (hwerrs & _IPATH_PLL_FAIL) { - snprintf(bitsmsg, sizeof bitsmsg, - "[PLL failed (%llx), InfiniPath hardware unusable]", - (unsigned long long) (hwerrs & _IPATH_PLL_FAIL)); - strlcat(msg, bitsmsg, msgl); - /* ignore from now on, so disable until driver reloaded */ - dd->ipath_hwerrmask &= ~(hwerrs & _IPATH_PLL_FAIL); - ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, - dd->ipath_hwerrmask); - } - - if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED) { - /* - * If it occurs, it is left masked since the eternal - * interface is unused - */ - dd->ipath_hwerrmask &= ~INFINIPATH_HWE_SERDESPLLFAILED; - ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, - dd->ipath_hwerrmask); - } - - if (hwerrs) { - /* - * if any set that we aren't ignoring; only - * make the complaint once, in case it's stuck - * or recurring, and we get here multiple - * times. - * force link down, so switch knows, and - * LEDs are turned off - */ - if (dd->ipath_flags & IPATH_INITTED) { - ipath_set_linkstate(dd, IPATH_IB_LINKDOWN); - ipath_setup_ht_setextled(dd, - INFINIPATH_IBCS_L_STATE_DOWN, - INFINIPATH_IBCS_LT_STATE_DISABLED); - ipath_dev_err(dd, "Fatal Hardware Error (freeze " - "mode), no longer usable, SN %.16s\n", - dd->ipath_serial); - isfatal = 1; - } - *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY; - /* mark as having had error */ - *dd->ipath_statusp |= IPATH_STATUS_HWERROR; - /* - * mark as not usable, at a minimum until driver - * is reloaded, probably until reboot, since no - * other reset is possible. - */ - dd->ipath_flags &= ~IPATH_INITTED; - } else { - *msg = 0; /* recovered from all of them */ - } - if (*msg) - ipath_dev_err(dd, "%s hardware error\n", msg); - if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg) - /* - * for status file; if no trailing brace is copied, - * we'll know it was truncated. - */ - snprintf(dd->ipath_freezemsg, - dd->ipath_freezelen, "{%s}", msg); - -bail:; -} - -/** - * ipath_ht_boardname - fill in the board name - * @dd: the infinipath device - * @name: the output buffer - * @namelen: the size of the output buffer - * - * fill in the board name, based on the board revision register - */ -static int ipath_ht_boardname(struct ipath_devdata *dd, char *name, - size_t namelen) -{ - char *n = NULL; - u8 boardrev = dd->ipath_boardrev; - int ret = 0; - - switch (boardrev) { - case 5: - /* - * original production board; two production levels, with - * different serial number ranges. See ipath_ht_early_init() for - * case where we enable IPATH_GPIO_INTR for later serial # range. - * Original 112* serial number is no longer supported. - */ - n = "InfiniPath_QHT7040"; - break; - case 7: - /* small form factor production board */ - n = "InfiniPath_QHT7140"; - break; - default: /* don't know, just print the number */ - ipath_dev_err(dd, "Don't yet know about board " - "with ID %u\n", boardrev); - snprintf(name, namelen, "Unknown_InfiniPath_QHT7xxx_%u", - boardrev); - break; - } - if (n) - snprintf(name, namelen, "%s", n); - - if (ret) { - ipath_dev_err(dd, "Unsupported InfiniPath board %s!\n", name); - goto bail; - } - if (dd->ipath_majrev != 3 || (dd->ipath_minrev < 2 || - dd->ipath_minrev > 4)) { - /* - * This version of the driver only supports Rev 3.2 - 3.4 - */ - ipath_dev_err(dd, - "Unsupported InfiniPath hardware revision %u.%u!\n", - dd->ipath_majrev, dd->ipath_minrev); - ret = 1; - goto bail; - } - /* - * pkt/word counters are 32 bit, and therefore wrap fast enough - * that we snapshot them from a timer, and maintain 64 bit shadow - * copies - */ - dd->ipath_flags |= IPATH_32BITCOUNTERS; - dd->ipath_flags |= IPATH_GPIO_INTR; - if (dd->ipath_lbus_speed != 800) - ipath_dev_err(dd, - "Incorrectly configured for HT @ %uMHz\n", - dd->ipath_lbus_speed); - - /* - * set here, not in ipath_init_*_funcs because we have to do - * it after we can read chip registers. - */ - dd->ipath_ureg_align = - ipath_read_kreg32(dd, dd->ipath_kregs->kr_pagealign); - -bail: - return ret; -} - -static void ipath_check_htlink(struct ipath_devdata *dd) -{ - u8 linkerr, link_off, i; - - for (i = 0; i < 2; i++) { - link_off = dd->ipath_ht_slave_off + i * 4 + 0xd; - if (pci_read_config_byte(dd->pcidev, link_off, &linkerr)) - dev_info(&dd->pcidev->dev, "Couldn't read " - "linkerror%d of HT slave/primary block\n", - i); - else if (linkerr & 0xf0) { - ipath_cdbg(VERBOSE, "HT linkerr%d bits 0x%x set, " - "clearing\n", linkerr >> 4, i); - /* - * writing the linkerr bits that are set should - * clear them - */ - if (pci_write_config_byte(dd->pcidev, link_off, - linkerr)) - ipath_dbg("Failed write to clear HT " - "linkerror%d\n", i); - if (pci_read_config_byte(dd->pcidev, link_off, - &linkerr)) - dev_info(&dd->pcidev->dev, - "Couldn't reread linkerror%d of " - "HT slave/primary block\n", i); - else if (linkerr & 0xf0) - dev_info(&dd->pcidev->dev, - "HT linkerror%d bits 0x%x " - "couldn't be cleared\n", - i, linkerr >> 4); - } - } -} - -static int ipath_setup_ht_reset(struct ipath_devdata *dd) -{ - ipath_dbg("No reset possible for this InfiniPath hardware\n"); - return 0; -} - -#define HT_INTR_DISC_CONFIG 0x80 /* HT interrupt and discovery cap */ -#define HT_INTR_REG_INDEX 2 /* intconfig requires indirect accesses */ - -/* - * Bits 13-15 of command==0 is slave/primary block. Clear any HT CRC - * errors. We only bother to do this at load time, because it's OK if - * it happened before we were loaded (first time after boot/reset), - * but any time after that, it's fatal anyway. Also need to not check - * for upper byte errors if we are in 8 bit mode, so figure out - * our width. For now, at least, also complain if it's 8 bit. - */ -static void slave_or_pri_blk(struct ipath_devdata *dd, struct pci_dev *pdev, - int pos, u8 cap_type) -{ - u8 linkwidth = 0, linkerr, link_a_b_off, link_off; - u16 linkctrl = 0; - int i; - - dd->ipath_ht_slave_off = pos; - /* command word, master_host bit */ - /* master host || slave */ - if ((cap_type >> 2) & 1) - link_a_b_off = 4; - else - link_a_b_off = 0; - ipath_cdbg(VERBOSE, "HT%u (Link %c) connected to processor\n", - link_a_b_off ? 1 : 0, - link_a_b_off ? 'B' : 'A'); - - link_a_b_off += pos; - - /* - * check both link control registers; clear both HT CRC sets if - * necessary. - */ - for (i = 0; i < 2; i++) { - link_off = pos + i * 4 + 0x4; - if (pci_read_config_word(pdev, link_off, &linkctrl)) - ipath_dev_err(dd, "Couldn't read HT link control%d " - "register\n", i); - else if (linkctrl & (0xf << 8)) { - ipath_cdbg(VERBOSE, "Clear linkctrl%d CRC Error " - "bits %x\n", i, linkctrl & (0xf << 8)); - /* - * now write them back to clear the error. - */ - pci_write_config_word(pdev, link_off, - linkctrl & (0xf << 8)); - } - } - - /* - * As with HT CRC bits, same for protocol errors that might occur - * during boot. - */ - for (i = 0; i < 2; i++) { - link_off = pos + i * 4 + 0xd; - if (pci_read_config_byte(pdev, link_off, &linkerr)) - dev_info(&pdev->dev, "Couldn't read linkerror%d " - "of HT slave/primary block\n", i); - else if (linkerr & 0xf0) { - ipath_cdbg(VERBOSE, "HT linkerr%d bits 0x%x set, " - "clearing\n", linkerr >> 4, i); - /* - * writing the linkerr bits that are set will clear - * them - */ - if (pci_write_config_byte - (pdev, link_off, linkerr)) - ipath_dbg("Failed write to clear HT " - "linkerror%d\n", i); - if (pci_read_config_byte(pdev, link_off, &linkerr)) - dev_info(&pdev->dev, "Couldn't reread " - "linkerror%d of HT slave/primary " - "block\n", i); - else if (linkerr & 0xf0) - dev_info(&pdev->dev, "HT linkerror%d bits " - "0x%x couldn't be cleared\n", - i, linkerr >> 4); - } - } - - /* - * this is just for our link to the host, not devices connected - * through tunnel. - */ - - if (pci_read_config_byte(pdev, link_a_b_off + 7, &linkwidth)) - ipath_dev_err(dd, "Couldn't read HT link width " - "config register\n"); - else { - u32 width; - switch (linkwidth & 7) { - case 5: - width = 4; - break; - case 4: - width = 2; - break; - case 3: - width = 32; - break; - case 1: - width = 16; - break; - case 0: - default: /* if wrong, assume 8 bit */ - width = 8; - break; - } - - dd->ipath_lbus_width = width; - - if (linkwidth != 0x11) { - ipath_dev_err(dd, "Not configured for 16 bit HT " - "(%x)\n", linkwidth); - if (!(linkwidth & 0xf)) { - ipath_dbg("Will ignore HT lane1 errors\n"); - dd->ipath_flags |= IPATH_8BIT_IN_HT0; - } - } - } - - /* - * this is just for our link to the host, not devices connected - * through tunnel. - */ - if (pci_read_config_byte(pdev, link_a_b_off + 0xd, &linkwidth)) - ipath_dev_err(dd, "Couldn't read HT link frequency " - "config register\n"); - else { - u32 speed; - switch (linkwidth & 0xf) { - case 6: - speed = 1000; - break; - case 5: - speed = 800; - break; - case 4: - speed = 600; - break; - case 3: - speed = 500; - break; - case 2: - speed = 400; - break; - case 1: - speed = 300; - break; - default: - /* - * assume reserved and vendor-specific are 200... - */ - case 0: - speed = 200; - break; - } - dd->ipath_lbus_speed = speed; - } - - snprintf(dd->ipath_lbus_info, sizeof(dd->ipath_lbus_info), - "HyperTransport,%uMHz,x%u\n", - dd->ipath_lbus_speed, - dd->ipath_lbus_width); -} - -static int ipath_ht_intconfig(struct ipath_devdata *dd) -{ - int ret; - - if (dd->ipath_intconfig) { - ipath_write_kreg(dd, dd->ipath_kregs->kr_interruptconfig, - dd->ipath_intconfig); /* interrupt address */ - ret = 0; - } else { - ipath_dev_err(dd, "No interrupts enabled, couldn't setup " - "interrupt address\n"); - ret = -EINVAL; - } - - return ret; -} - -static void ipath_ht_irq_update(struct pci_dev *dev, int irq, - struct ht_irq_msg *msg) -{ - struct ipath_devdata *dd = pci_get_drvdata(dev); - u64 prev_intconfig = dd->ipath_intconfig; - - dd->ipath_intconfig = msg->address_lo; - dd->ipath_intconfig |= ((u64) msg->address_hi) << 32; - - /* - * If the previous value of dd->ipath_intconfig is zero, we're - * getting configured for the first time, and must not program the - * intconfig register here (it will be programmed later, when the - * hardware is ready). Otherwise, we should. - */ - if (prev_intconfig) - ipath_ht_intconfig(dd); -} - -/** - * ipath_setup_ht_config - setup the interruptconfig register - * @dd: the infinipath device - * @pdev: the PCI device - * - * setup the interruptconfig register from the HT config info. - * Also clear CRC errors in HT linkcontrol, if necessary. - * This is done only for the real hardware. It is done before - * chip address space is initted, so can't touch infinipath registers - */ -static int ipath_setup_ht_config(struct ipath_devdata *dd, - struct pci_dev *pdev) -{ - int pos, ret; - - ret = __ht_create_irq(pdev, 0, ipath_ht_irq_update); - if (ret < 0) { - ipath_dev_err(dd, "Couldn't create interrupt handler: " - "err %d\n", ret); - goto bail; - } - dd->ipath_irq = ret; - ret = 0; - - /* - * Handle clearing CRC errors in linkctrl register if necessary. We - * do this early, before we ever enable errors or hardware errors, - * mostly to avoid causing the chip to enter freeze mode. - */ - pos = pci_find_capability(pdev, PCI_CAP_ID_HT); - if (!pos) { - ipath_dev_err(dd, "Couldn't find HyperTransport " - "capability; no interrupts\n"); - ret = -ENODEV; - goto bail; - } - do { - u8 cap_type; - - /* - * The HT capability type byte is 3 bytes after the - * capability byte. - */ - if (pci_read_config_byte(pdev, pos + 3, &cap_type)) { - dev_info(&pdev->dev, "Couldn't read config " - "command @ %d\n", pos); - continue; - } - if (!(cap_type & 0xE0)) - slave_or_pri_blk(dd, pdev, pos, cap_type); - } while ((pos = pci_find_next_capability(pdev, pos, - PCI_CAP_ID_HT))); - - dd->ipath_flags |= IPATH_SWAP_PIOBUFS; - -bail: - return ret; -} - -/** - * ipath_setup_ht_cleanup - clean up any per-chip chip-specific stuff - * @dd: the infinipath device - * - * Called during driver unload. - * This is currently a nop for the HT chip, not for all chips - */ -static void ipath_setup_ht_cleanup(struct ipath_devdata *dd) -{ -} - -/** - * ipath_setup_ht_setextled - set the state of the two external LEDs - * @dd: the infinipath device - * @lst: the L state - * @ltst: the LT state - * - * Set the state of the two external LEDs, to indicate physical and - * logical state of IB link. For this chip (at least with recommended - * board pinouts), LED1 is Green (physical state), and LED2 is Yellow - * (logical state) - * - * Note: We try to match the Mellanox HCA LED behavior as best - * we can. Green indicates physical link state is OK (something is - * plugged in, and we can train). - * Amber indicates the link is logically up (ACTIVE). - * Mellanox further blinks the amber LED to indicate data packet - * activity, but we have no hardware support for that, so it would - * require waking up every 10-20 msecs and checking the counters - * on the chip, and then turning the LED off if appropriate. That's - * visible overhead, so not something we will do. - * - */ -static void ipath_setup_ht_setextled(struct ipath_devdata *dd, - u64 lst, u64 ltst) -{ - u64 extctl; - unsigned long flags = 0; - - /* the diags use the LED to indicate diag info, so we leave - * the external LED alone when the diags are running */ - if (ipath_diag_inuse) - return; - - /* Allow override of LED display for, e.g. Locating system in rack */ - if (dd->ipath_led_override) { - ltst = (dd->ipath_led_override & IPATH_LED_PHYS) - ? INFINIPATH_IBCS_LT_STATE_LINKUP - : INFINIPATH_IBCS_LT_STATE_DISABLED; - lst = (dd->ipath_led_override & IPATH_LED_LOG) - ? INFINIPATH_IBCS_L_STATE_ACTIVE - : INFINIPATH_IBCS_L_STATE_DOWN; - } - - spin_lock_irqsave(&dd->ipath_gpio_lock, flags); - /* - * start by setting both LED control bits to off, then turn - * on the appropriate bit(s). - */ - if (dd->ipath_boardrev == 8) { /* LS/X-1 uses different pins */ - /* - * major difference is that INFINIPATH_EXTC_LEDGBLERR_OFF - * is inverted, because it is normally used to indicate - * a hardware fault at reset, if there were errors - */ - extctl = (dd->ipath_extctrl & ~INFINIPATH_EXTC_LEDGBLOK_ON) - | INFINIPATH_EXTC_LEDGBLERR_OFF; - if (ltst == INFINIPATH_IBCS_LT_STATE_LINKUP) - extctl &= ~INFINIPATH_EXTC_LEDGBLERR_OFF; - if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE) - extctl |= INFINIPATH_EXTC_LEDGBLOK_ON; - } else { - extctl = dd->ipath_extctrl & - ~(INFINIPATH_EXTC_LED1PRIPORT_ON | - INFINIPATH_EXTC_LED2PRIPORT_ON); - if (ltst == INFINIPATH_IBCS_LT_STATE_LINKUP) - extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON; - if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE) - extctl |= INFINIPATH_EXTC_LED2PRIPORT_ON; - } - dd->ipath_extctrl = extctl; - ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl); - spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags); -} - -static void ipath_init_ht_variables(struct ipath_devdata *dd) -{ - /* - * setup the register offsets, since they are different for each - * chip - */ - dd->ipath_kregs = &ipath_ht_kregs; - dd->ipath_cregs = &ipath_ht_cregs; - - dd->ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM; - dd->ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM; - dd->ipath_gpio_sda = IPATH_GPIO_SDA; - dd->ipath_gpio_scl = IPATH_GPIO_SCL; - - /* - * Fill in data for field-values that change in newer chips. - * We dynamically specify only the mask for LINKTRAININGSTATE - * and only the shift for LINKSTATE, as they are the only ones - * that change. Also precalculate the 3 link states of interest - * and the combined mask. - */ - dd->ibcs_ls_shift = IBA6110_IBCS_LINKSTATE_SHIFT; - dd->ibcs_lts_mask = IBA6110_IBCS_LINKTRAININGSTATE_MASK; - dd->ibcs_mask = (INFINIPATH_IBCS_LINKSTATE_MASK << - dd->ibcs_ls_shift) | dd->ibcs_lts_mask; - dd->ib_init = (INFINIPATH_IBCS_LT_STATE_LINKUP << - INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) | - (INFINIPATH_IBCS_L_STATE_INIT << dd->ibcs_ls_shift); - dd->ib_arm = (INFINIPATH_IBCS_LT_STATE_LINKUP << - INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) | - (INFINIPATH_IBCS_L_STATE_ARM << dd->ibcs_ls_shift); - dd->ib_active = (INFINIPATH_IBCS_LT_STATE_LINKUP << - INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) | - (INFINIPATH_IBCS_L_STATE_ACTIVE << dd->ibcs_ls_shift); - - /* - * Fill in data for ibcc field-values that change in newer chips. - * We dynamically specify only the mask for LINKINITCMD - * and only the shift for LINKCMD and MAXPKTLEN, as they are - * the only ones that change. - */ - dd->ibcc_lic_mask = INFINIPATH_IBCC_LINKINITCMD_MASK; - dd->ibcc_lc_shift = INFINIPATH_IBCC_LINKCMD_SHIFT; - dd->ibcc_mpl_shift = INFINIPATH_IBCC_MAXPKTLEN_SHIFT; - - /* Fill in shifts for RcvCtrl. */ - dd->ipath_r_portenable_shift = INFINIPATH_R_PORTENABLE_SHIFT; - dd->ipath_r_intravail_shift = INFINIPATH_R_INTRAVAIL_SHIFT; - dd->ipath_r_tailupd_shift = INFINIPATH_R_TAILUPD_SHIFT; - dd->ipath_r_portcfg_shift = 0; /* Not on IBA6110 */ - - dd->ipath_i_bitsextant = - (INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) | - (INFINIPATH_I_RCVAVAIL_MASK << - INFINIPATH_I_RCVAVAIL_SHIFT) | - INFINIPATH_I_ERROR | INFINIPATH_I_SPIOSENT | - INFINIPATH_I_SPIOBUFAVAIL | INFINIPATH_I_GPIO; - - dd->ipath_e_bitsextant = - INFINIPATH_E_RFORMATERR | INFINIPATH_E_RVCRC | - INFINIPATH_E_RICRC | INFINIPATH_E_RMINPKTLEN | - INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RLONGPKTLEN | - INFINIPATH_E_RSHORTPKTLEN | INFINIPATH_E_RUNEXPCHAR | - INFINIPATH_E_RUNSUPVL | INFINIPATH_E_REBP | - INFINIPATH_E_RIBFLOW | INFINIPATH_E_RBADVERSION | - INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL | - INFINIPATH_E_RBADTID | INFINIPATH_E_RHDRLEN | - INFINIPATH_E_RHDR | INFINIPATH_E_RIBLOSTLINK | - INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SMAXPKTLEN | - INFINIPATH_E_SUNDERRUN | INFINIPATH_E_SPKTLEN | - INFINIPATH_E_SDROPPEDSMPPKT | INFINIPATH_E_SDROPPEDDATAPKT | - INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM | - INFINIPATH_E_SUNSUPVL | INFINIPATH_E_IBSTATUSCHANGED | - INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET | - INFINIPATH_E_HARDWARE; - - dd->ipath_hwe_bitsextant = - (INFINIPATH_HWE_HTCMEMPARITYERR_MASK << - INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT) | - (INFINIPATH_HWE_TXEMEMPARITYERR_MASK << - INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) | - (INFINIPATH_HWE_RXEMEMPARITYERR_MASK << - INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) | - INFINIPATH_HWE_HTCLNKABYTE0CRCERR | - INFINIPATH_HWE_HTCLNKABYTE1CRCERR | - INFINIPATH_HWE_HTCLNKBBYTE0CRCERR | - INFINIPATH_HWE_HTCLNKBBYTE1CRCERR | - INFINIPATH_HWE_HTCMISCERR4 | - INFINIPATH_HWE_HTCMISCERR5 | INFINIPATH_HWE_HTCMISCERR6 | - INFINIPATH_HWE_HTCMISCERR7 | - INFINIPATH_HWE_HTCBUSTREQPARITYERR | - INFINIPATH_HWE_HTCBUSTRESPPARITYERR | - INFINIPATH_HWE_HTCBUSIREQPARITYERR | - INFINIPATH_HWE_RXDSYNCMEMPARITYERR | - INFINIPATH_HWE_MEMBISTFAILED | - INFINIPATH_HWE_COREPLL_FBSLIP | - INFINIPATH_HWE_COREPLL_RFSLIP | - INFINIPATH_HWE_HTBPLL_FBSLIP | - INFINIPATH_HWE_HTBPLL_RFSLIP | - INFINIPATH_HWE_HTAPLL_FBSLIP | - INFINIPATH_HWE_HTAPLL_RFSLIP | - INFINIPATH_HWE_SERDESPLLFAILED | - INFINIPATH_HWE_IBCBUSTOSPCPARITYERR | - INFINIPATH_HWE_IBCBUSFRSPCPARITYERR; - - dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK; - dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK; - dd->ipath_i_rcvavail_shift = INFINIPATH_I_RCVAVAIL_SHIFT; - dd->ipath_i_rcvurg_shift = INFINIPATH_I_RCVURG_SHIFT; - - /* - * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity. - * 2 is Some Misc, 3 is reserved for future. - */ - dd->ipath_eep_st_masks[0].hwerrs_to_log = - INFINIPATH_HWE_TXEMEMPARITYERR_MASK << - INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT; - - dd->ipath_eep_st_masks[1].hwerrs_to_log = - INFINIPATH_HWE_RXEMEMPARITYERR_MASK << - INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT; - - dd->ipath_eep_st_masks[2].errs_to_log = INFINIPATH_E_RESET; - - dd->delay_mult = 2; /* SDR, 4X, can't change */ - - dd->ipath_link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X; - dd->ipath_link_speed_supported = IPATH_IB_SDR; - dd->ipath_link_width_enabled = IB_WIDTH_4X; - dd->ipath_link_speed_enabled = dd->ipath_link_speed_supported; - /* these can't change for this chip, so set once */ - dd->ipath_link_width_active = dd->ipath_link_width_enabled; - dd->ipath_link_speed_active = dd->ipath_link_speed_enabled; -} - -/** - * ipath_ht_init_hwerrors - enable hardware errors - * @dd: the infinipath device - * - * now that we have finished initializing everything that might reasonably - * cause a hardware error, and cleared those errors bits as they occur, - * we can enable hardware errors in the mask (potentially enabling - * freeze mode), and enable hardware errors as errors (along with - * everything else) in errormask - */ -static void ipath_ht_init_hwerrors(struct ipath_devdata *dd) -{ - ipath_err_t val; - u64 extsval; - - extsval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus); - - if (!(extsval & INFINIPATH_EXTS_MEMBIST_ENDTEST)) - ipath_dev_err(dd, "MemBIST did not complete!\n"); - if (extsval & INFINIPATH_EXTS_MEMBIST_CORRECT) - ipath_dbg("MemBIST corrected\n"); - - ipath_check_htlink(dd); - - /* barring bugs, all hwerrors become interrupts, which can */ - val = -1LL; - /* don't look at crc lane1 if 8 bit */ - if (dd->ipath_flags & IPATH_8BIT_IN_HT0) - val &= ~infinipath_hwe_htclnkabyte1crcerr; - /* don't look at crc lane1 if 8 bit */ - if (dd->ipath_flags & IPATH_8BIT_IN_HT1) - val &= ~infinipath_hwe_htclnkbbyte1crcerr; - - /* - * disable RXDSYNCMEMPARITY because external serdes is unused, - * and therefore the logic will never be used or initialized, - * and uninitialized state will normally result in this error - * being asserted. Similarly for the external serdess pll - * lock signal. - */ - val &= ~(INFINIPATH_HWE_SERDESPLLFAILED | - INFINIPATH_HWE_RXDSYNCMEMPARITYERR); - - /* - * Disable MISCERR4 because of an inversion in the HT core - * logic checking for errors that cause this bit to be set. - * The errata can also cause the protocol error bit to be set - * in the HT config space linkerror register(s). - */ - val &= ~INFINIPATH_HWE_HTCMISCERR4; - - /* - * PLL ignored because unused MDIO interface has a logic problem - */ - if (dd->ipath_boardrev == 4 || dd->ipath_boardrev == 9) - val &= ~INFINIPATH_HWE_SERDESPLLFAILED; - dd->ipath_hwerrmask = val; -} - - - - -/** - * ipath_ht_bringup_serdes - bring up the serdes - * @dd: the infinipath device - */ -static int ipath_ht_bringup_serdes(struct ipath_devdata *dd) -{ - u64 val, config1; - int ret = 0, change = 0; - - ipath_dbg("Trying to bringup serdes\n"); - - if (ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus) & - INFINIPATH_HWE_SERDESPLLFAILED) - { - ipath_dbg("At start, serdes PLL failed bit set in " - "hwerrstatus, clearing and continuing\n"); - ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, - INFINIPATH_HWE_SERDESPLLFAILED); - } - - val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0); - config1 = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig1); - - ipath_cdbg(VERBOSE, "Initial serdes status is config0=%llx " - "config1=%llx, sstatus=%llx xgxs %llx\n", - (unsigned long long) val, (unsigned long long) config1, - (unsigned long long) - ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesstatus), - (unsigned long long) - ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig)); - - /* force reset on */ - val |= INFINIPATH_SERDC0_RESET_PLL - /* | INFINIPATH_SERDC0_RESET_MASK */ - ; - ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val); - udelay(15); /* need pll reset set at least for a bit */ - - if (val & INFINIPATH_SERDC0_RESET_PLL) { - u64 val2 = val &= ~INFINIPATH_SERDC0_RESET_PLL; - /* set lane resets, and tx idle, during pll reset */ - val2 |= INFINIPATH_SERDC0_RESET_MASK | - INFINIPATH_SERDC0_TXIDLE; - ipath_cdbg(VERBOSE, "Clearing serdes PLL reset (writing " - "%llx)\n", (unsigned long long) val2); - ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, - val2); - /* - * be sure chip saw it - */ - val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - /* - * need pll reset clear at least 11 usec before lane - * resets cleared; give it a few more - */ - udelay(15); - val = val2; /* for check below */ - } - - if (val & (INFINIPATH_SERDC0_RESET_PLL | - INFINIPATH_SERDC0_RESET_MASK | - INFINIPATH_SERDC0_TXIDLE)) { - val &= ~(INFINIPATH_SERDC0_RESET_PLL | - INFINIPATH_SERDC0_RESET_MASK | - INFINIPATH_SERDC0_TXIDLE); - /* clear them */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, - val); - } - - val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig); - if (val & INFINIPATH_XGXS_RESET) { - /* normally true after boot */ - val &= ~INFINIPATH_XGXS_RESET; - change = 1; - } - if (((val >> INFINIPATH_XGXS_RX_POL_SHIFT) & - INFINIPATH_XGXS_RX_POL_MASK) != dd->ipath_rx_pol_inv ) { - /* need to compensate for Tx inversion in partner */ - val &= ~(INFINIPATH_XGXS_RX_POL_MASK << - INFINIPATH_XGXS_RX_POL_SHIFT); - val |= dd->ipath_rx_pol_inv << - INFINIPATH_XGXS_RX_POL_SHIFT; - change = 1; - } - if (change) - ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val); - - val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0); - - /* clear current and de-emphasis bits */ - config1 &= ~0x0ffffffff00ULL; - /* set current to 20ma */ - config1 |= 0x00000000000ULL; - /* set de-emphasis to -5.68dB */ - config1 |= 0x0cccc000000ULL; - ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig1, config1); - - ipath_cdbg(VERBOSE, "After setup: serdes status is config0=%llx " - "config1=%llx, sstatus=%llx xgxs %llx\n", - (unsigned long long) val, (unsigned long long) config1, - (unsigned long long) - ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesstatus), - (unsigned long long) - ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig)); - - return ret; /* for now, say we always succeeded */ -} - -/** - * ipath_ht_quiet_serdes - set serdes to txidle - * @dd: the infinipath device - * driver is being unloaded - */ -static void ipath_ht_quiet_serdes(struct ipath_devdata *dd) -{ - u64 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0); - - val |= INFINIPATH_SERDC0_TXIDLE; - ipath_dbg("Setting TxIdleEn on serdes (config0 = %llx)\n", - (unsigned long long) val); - ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val); -} - -/** - * ipath_pe_put_tid - write a TID in chip - * @dd: the infinipath device - * @tidptr: pointer to the expected TID (in chip) to update - * @tidtype: RCVHQ_RCV_TYPE_EAGER (1) for eager, RCVHQ_RCV_TYPE_EXPECTED (0) for expected - * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing - * - * This exists as a separate routine to allow for special locking etc. - * It's used for both the full cleanup on exit, as well as the normal - * setup and teardown. - */ -static void ipath_ht_put_tid(struct ipath_devdata *dd, - u64 __iomem *tidptr, u32 type, - unsigned long pa) -{ - if (!dd->ipath_kregbase) - return; - - if (pa != dd->ipath_tidinvalid) { - if (unlikely((pa & ~INFINIPATH_RT_ADDR_MASK))) { - dev_info(&dd->pcidev->dev, - "physaddr %lx has more than " - "40 bits, using only 40!!!\n", pa); - pa &= INFINIPATH_RT_ADDR_MASK; - } - if (type == RCVHQ_RCV_TYPE_EAGER) - pa |= dd->ipath_tidtemplate; - else { - /* in words (fixed, full page). */ - u64 lenvalid = PAGE_SIZE >> 2; - lenvalid <<= INFINIPATH_RT_BUFSIZE_SHIFT; - pa |= lenvalid | INFINIPATH_RT_VALID; - } - } - - writeq(pa, tidptr); -} - - -/** - * ipath_ht_clear_tid - clear all TID entries for a port, expected and eager - * @dd: the infinipath device - * @port: the port - * - * Used from ipath_close(), and at chip initialization. - */ -static void ipath_ht_clear_tids(struct ipath_devdata *dd, unsigned port) -{ - u64 __iomem *tidbase; - int i; - - if (!dd->ipath_kregbase) - return; - - ipath_cdbg(VERBOSE, "Invalidate TIDs for port %u\n", port); - - /* - * need to invalidate all of the expected TID entries for this - * port, so we don't have valid entries that might somehow get - * used (early in next use of this port, or through some bug) - */ - tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) + - dd->ipath_rcvtidbase + - port * dd->ipath_rcvtidcnt * - sizeof(*tidbase)); - for (i = 0; i < dd->ipath_rcvtidcnt; i++) - ipath_ht_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EXPECTED, - dd->ipath_tidinvalid); - - tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) + - dd->ipath_rcvegrbase + - port * dd->ipath_rcvegrcnt * - sizeof(*tidbase)); - - for (i = 0; i < dd->ipath_rcvegrcnt; i++) - ipath_ht_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EAGER, - dd->ipath_tidinvalid); -} - -/** - * ipath_ht_tidtemplate - setup constants for TID updates - * @dd: the infinipath device - * - * We setup stuff that we use a lot, to avoid calculating each time - */ -static void ipath_ht_tidtemplate(struct ipath_devdata *dd) -{ - dd->ipath_tidtemplate = dd->ipath_ibmaxlen >> 2; - dd->ipath_tidtemplate <<= INFINIPATH_RT_BUFSIZE_SHIFT; - dd->ipath_tidtemplate |= INFINIPATH_RT_VALID; - - /* - * work around chip errata bug 7358, by marking invalid tids - * as having max length - */ - dd->ipath_tidinvalid = (-1LL & INFINIPATH_RT_BUFSIZE_MASK) << - INFINIPATH_RT_BUFSIZE_SHIFT; -} - -static int ipath_ht_early_init(struct ipath_devdata *dd) -{ - u32 __iomem *piobuf; - u32 pioincr, val32; - int i; - - /* - * one cache line; long IB headers will spill over into received - * buffer - */ - dd->ipath_rcvhdrentsize = 16; - dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE; - - /* - * For HT, we allocate a somewhat overly large eager buffer, - * such that we can guarantee that we can receive the largest - * packet that we can send out. To truly support a 4KB MTU, - * we need to bump this to a large value. To date, other than - * testing, we have never encountered an HCA that can really - * send 4KB MTU packets, so we do not handle that (we'll get - * errors interrupts if we ever see one). - */ - dd->ipath_rcvegrbufsize = dd->ipath_piosize2k; - - /* - * the min() check here is currently a nop, but it may not - * always be, depending on just how we do ipath_rcvegrbufsize - */ - dd->ipath_ibmaxlen = min(dd->ipath_piosize2k, - dd->ipath_rcvegrbufsize); - dd->ipath_init_ibmaxlen = dd->ipath_ibmaxlen; - ipath_ht_tidtemplate(dd); - - /* - * zero all the TID entries at startup. We do this for sanity, - * in case of a previous driver crash of some kind, and also - * because the chip powers up with these memories in an unknown - * state. Use portcnt, not cfgports, since this is for the - * full chip, not for current (possibly different) configuration - * value. - * Chip Errata bug 6447 - */ - for (val32 = 0; val32 < dd->ipath_portcnt; val32++) - ipath_ht_clear_tids(dd, val32); - - /* - * write the pbc of each buffer, to be sure it's initialized, then - * cancel all the buffers, and also abort any packets that might - * have been in flight for some reason (the latter is for driver - * unload/reload, but isn't a bad idea at first init). PIO send - * isn't enabled at this point, so there is no danger of sending - * these out on the wire. - * Chip Errata bug 6610 - */ - piobuf = (u32 __iomem *) (((char __iomem *)(dd->ipath_kregbase)) + - dd->ipath_piobufbase); - pioincr = dd->ipath_palign / sizeof(*piobuf); - for (i = 0; i < dd->ipath_piobcnt2k; i++) { - /* - * reasonable word count, just to init pbc - */ - writel(16, piobuf); - piobuf += pioincr; - } - - ipath_get_eeprom_info(dd); - if (dd->ipath_boardrev == 5) { - /* - * Later production QHT7040 has same changes as QHT7140, so - * can use GPIO interrupts. They have serial #'s starting - * with 128, rather than 112. - */ - if (dd->ipath_serial[0] == '1' && - dd->ipath_serial[1] == '2' && - dd->ipath_serial[2] == '8') - dd->ipath_flags |= IPATH_GPIO_INTR; - else { - ipath_dev_err(dd, "Unsupported InfiniPath board " - "(serial number %.16s)!\n", - dd->ipath_serial); - return 1; - } - } - - if (dd->ipath_minrev >= 4) { - /* Rev4+ reports extra errors via internal GPIO pins */ - dd->ipath_flags |= IPATH_GPIO_ERRINTRS; - dd->ipath_gpio_mask |= IPATH_GPIO_ERRINTR_MASK; - ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask, - dd->ipath_gpio_mask); - } - - return 0; -} - - -/** - * ipath_init_ht_get_base_info - set chip-specific flags for user code - * @dd: the infinipath device - * @kbase: ipath_base_info pointer - * - * We set the PCIE flag because the lower bandwidth on PCIe vs - * HyperTransport can affect some user packet algorithms. - */ -static int ipath_ht_get_base_info(struct ipath_portdata *pd, void *kbase) -{ - struct ipath_base_info *kinfo = kbase; - - kinfo->spi_runtime_flags |= IPATH_RUNTIME_HT | - IPATH_RUNTIME_PIO_REGSWAPPED; - - if (pd->port_dd->ipath_minrev < 4) - kinfo->spi_runtime_flags |= IPATH_RUNTIME_RCVHDR_COPY; - - return 0; -} - -static void ipath_ht_free_irq(struct ipath_devdata *dd) -{ - free_irq(dd->ipath_irq, dd); - ht_destroy_irq(dd->ipath_irq); - dd->ipath_irq = 0; - dd->ipath_intconfig = 0; -} - -static struct ipath_message_header * -ipath_ht_get_msgheader(struct ipath_devdata *dd, __le32 *rhf_addr) -{ - return (struct ipath_message_header *) - &rhf_addr[sizeof(u64) / sizeof(u32)]; -} - -static void ipath_ht_config_ports(struct ipath_devdata *dd, ushort cfgports) -{ - dd->ipath_portcnt = - ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt); - dd->ipath_p0_rcvegrcnt = - ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt); -} - -static void ipath_ht_read_counters(struct ipath_devdata *dd, - struct infinipath_counters *cntrs) -{ - cntrs->LBIntCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(LBIntCnt)); - cntrs->LBFlowStallCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(LBFlowStallCnt)); - cntrs->TxSDmaDescCnt = 0; - cntrs->TxUnsupVLErrCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxUnsupVLErrCnt)); - cntrs->TxDataPktCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDataPktCnt)); - cntrs->TxFlowPktCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxFlowPktCnt)); - cntrs->TxDwordCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDwordCnt)); - cntrs->TxLenErrCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxLenErrCnt)); - cntrs->TxMaxMinLenErrCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxMaxMinLenErrCnt)); - cntrs->TxUnderrunCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxUnderrunCnt)); - cntrs->TxFlowStallCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxFlowStallCnt)); - cntrs->TxDroppedPktCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDroppedPktCnt)); - cntrs->RxDroppedPktCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDroppedPktCnt)); - cntrs->RxDataPktCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDataPktCnt)); - cntrs->RxFlowPktCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxFlowPktCnt)); - cntrs->RxDwordCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDwordCnt)); - cntrs->RxLenErrCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLenErrCnt)); - cntrs->RxMaxMinLenErrCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxMaxMinLenErrCnt)); - cntrs->RxICRCErrCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxICRCErrCnt)); - cntrs->RxVCRCErrCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxVCRCErrCnt)); - cntrs->RxFlowCtrlErrCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxFlowCtrlErrCnt)); - cntrs->RxBadFormatCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxBadFormatCnt)); - cntrs->RxLinkProblemCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLinkProblemCnt)); - cntrs->RxEBPCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxEBPCnt)); - cntrs->RxLPCRCErrCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLPCRCErrCnt)); - cntrs->RxBufOvflCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxBufOvflCnt)); - cntrs->RxTIDFullErrCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxTIDFullErrCnt)); - cntrs->RxTIDValidErrCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxTIDValidErrCnt)); - cntrs->RxPKeyMismatchCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxPKeyMismatchCnt)); - cntrs->RxP0HdrEgrOvflCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt)); - cntrs->RxP1HdrEgrOvflCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP1HdrEgrOvflCnt)); - cntrs->RxP2HdrEgrOvflCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP2HdrEgrOvflCnt)); - cntrs->RxP3HdrEgrOvflCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP3HdrEgrOvflCnt)); - cntrs->RxP4HdrEgrOvflCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP4HdrEgrOvflCnt)); - cntrs->RxP5HdrEgrOvflCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP5HdrEgrOvflCnt)); - cntrs->RxP6HdrEgrOvflCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP6HdrEgrOvflCnt)); - cntrs->RxP7HdrEgrOvflCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP7HdrEgrOvflCnt)); - cntrs->RxP8HdrEgrOvflCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP8HdrEgrOvflCnt)); - cntrs->RxP9HdrEgrOvflCnt = 0; - cntrs->RxP10HdrEgrOvflCnt = 0; - cntrs->RxP11HdrEgrOvflCnt = 0; - cntrs->RxP12HdrEgrOvflCnt = 0; - cntrs->RxP13HdrEgrOvflCnt = 0; - cntrs->RxP14HdrEgrOvflCnt = 0; - cntrs->RxP15HdrEgrOvflCnt = 0; - cntrs->RxP16HdrEgrOvflCnt = 0; - cntrs->IBStatusChangeCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBStatusChangeCnt)); - cntrs->IBLinkErrRecoveryCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt)); - cntrs->IBLinkDownedCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBLinkDownedCnt)); - cntrs->IBSymbolErrCnt = - ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBSymbolErrCnt)); - cntrs->RxVL15DroppedPktCnt = 0; - cntrs->RxOtherLocalPhyErrCnt = 0; - cntrs->PcieRetryBufDiagQwordCnt = 0; - cntrs->ExcessBufferOvflCnt = dd->ipath_overrun_thresh_errs; - cntrs->LocalLinkIntegrityErrCnt = - (dd->ipath_flags & IPATH_GPIO_ERRINTRS) ? - dd->ipath_lli_errs : dd->ipath_lli_errors; - cntrs->RxVlErrCnt = 0; - cntrs->RxDlidFltrCnt = 0; -} - - -/* no interrupt fallback for these chips */ -static int ipath_ht_nointr_fallback(struct ipath_devdata *dd) -{ - return 0; -} - - -/* - * reset the XGXS (between serdes and IBC). Slightly less intrusive - * than resetting the IBC or external link state, and useful in some - * cases to cause some retraining. To do this right, we reset IBC - * as well. - */ -static void ipath_ht_xgxs_reset(struct ipath_devdata *dd) -{ - u64 val, prev_val; - - prev_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig); - val = prev_val | INFINIPATH_XGXS_RESET; - prev_val &= ~INFINIPATH_XGXS_RESET; /* be sure */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_control, - dd->ipath_control & ~INFINIPATH_C_LINKENABLE); - ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val); - ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch); - ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, prev_val); - ipath_write_kreg(dd, dd->ipath_kregs->kr_control, - dd->ipath_control); -} - - -static int ipath_ht_get_ib_cfg(struct ipath_devdata *dd, int which) -{ - int ret; - - switch (which) { - case IPATH_IB_CFG_LWID: - ret = dd->ipath_link_width_active; - break; - case IPATH_IB_CFG_SPD: - ret = dd->ipath_link_speed_active; - break; - case IPATH_IB_CFG_LWID_ENB: - ret = dd->ipath_link_width_enabled; - break; - case IPATH_IB_CFG_SPD_ENB: - ret = dd->ipath_link_speed_enabled; - break; - default: - ret = -ENOTSUPP; - break; - } - return ret; -} - - -/* we assume range checking is already done, if needed */ -static int ipath_ht_set_ib_cfg(struct ipath_devdata *dd, int which, u32 val) -{ - int ret = 0; - - if (which == IPATH_IB_CFG_LWID_ENB) - dd->ipath_link_width_enabled = val; - else if (which == IPATH_IB_CFG_SPD_ENB) - dd->ipath_link_speed_enabled = val; - else - ret = -ENOTSUPP; - return ret; -} - - -static void ipath_ht_config_jint(struct ipath_devdata *dd, u16 a, u16 b) -{ -} - - -static int ipath_ht_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs) -{ - ipath_setup_ht_setextled(dd, ipath_ib_linkstate(dd, ibcs), - ipath_ib_linktrstate(dd, ibcs)); - return 0; -} - - -/** - * ipath_init_iba6110_funcs - set up the chip-specific function pointers - * @dd: the infinipath device - * - * This is global, and is called directly at init to set up the - * chip-specific function pointers for later use. - */ -void ipath_init_iba6110_funcs(struct ipath_devdata *dd) -{ - dd->ipath_f_intrsetup = ipath_ht_intconfig; - dd->ipath_f_bus = ipath_setup_ht_config; - dd->ipath_f_reset = ipath_setup_ht_reset; - dd->ipath_f_get_boardname = ipath_ht_boardname; - dd->ipath_f_init_hwerrors = ipath_ht_init_hwerrors; - dd->ipath_f_early_init = ipath_ht_early_init; - dd->ipath_f_handle_hwerrors = ipath_ht_handle_hwerrors; - dd->ipath_f_quiet_serdes = ipath_ht_quiet_serdes; - dd->ipath_f_bringup_serdes = ipath_ht_bringup_serdes; - dd->ipath_f_clear_tids = ipath_ht_clear_tids; - dd->ipath_f_put_tid = ipath_ht_put_tid; - dd->ipath_f_cleanup = ipath_setup_ht_cleanup; - dd->ipath_f_setextled = ipath_setup_ht_setextled; - dd->ipath_f_get_base_info = ipath_ht_get_base_info; - dd->ipath_f_free_irq = ipath_ht_free_irq; - dd->ipath_f_tidtemplate = ipath_ht_tidtemplate; - dd->ipath_f_intr_fallback = ipath_ht_nointr_fallback; - dd->ipath_f_get_msgheader = ipath_ht_get_msgheader; - dd->ipath_f_config_ports = ipath_ht_config_ports; - dd->ipath_f_read_counters = ipath_ht_read_counters; - dd->ipath_f_xgxs_reset = ipath_ht_xgxs_reset; - dd->ipath_f_get_ib_cfg = ipath_ht_get_ib_cfg; - dd->ipath_f_set_ib_cfg = ipath_ht_set_ib_cfg; - dd->ipath_f_config_jint = ipath_ht_config_jint; - dd->ipath_f_ib_updown = ipath_ht_ib_updown; - - /* - * initialize chip-specific variables - */ - ipath_init_ht_variables(dd); -} diff --git a/drivers/staging/rdma/ipath/ipath_init_chip.c b/drivers/staging/rdma/ipath/ipath_init_chip.c deleted file mode 100644 index a5eea199f733..000000000000 --- a/drivers/staging/rdma/ipath/ipath_init_chip.c +++ /dev/null @@ -1,1062 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -#include "ipath_kernel.h" -#include "ipath_common.h" - -/* - * min buffers we want to have per port, after driver - */ -#define IPATH_MIN_USER_PORT_BUFCNT 7 - -/* - * Number of ports we are configured to use (to allow for more pio - * buffers per port, etc.) Zero means use chip value. - */ -static ushort ipath_cfgports; - -module_param_named(cfgports, ipath_cfgports, ushort, S_IRUGO); -MODULE_PARM_DESC(cfgports, "Set max number of ports to use"); - -/* - * Number of buffers reserved for driver (verbs and layered drivers.) - * Initialized based on number of PIO buffers if not set via module interface. - * The problem with this is that it's global, but we'll use different - * numbers for different chip types. - */ -static ushort ipath_kpiobufs; - -static int ipath_set_kpiobufs(const char *val, struct kernel_param *kp); - -module_param_call(kpiobufs, ipath_set_kpiobufs, param_get_ushort, - &ipath_kpiobufs, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(kpiobufs, "Set number of PIO buffers for driver"); - -/** - * create_port0_egr - allocate the eager TID buffers - * @dd: the infinipath device - * - * This code is now quite different for user and kernel, because - * the kernel uses skb's, for the accelerated network performance. - * This is the kernel (port0) version. - * - * Allocate the eager TID buffers and program them into infinipath. - * We use the network layer alloc_skb() allocator to allocate the - * memory, and either use the buffers as is for things like verbs - * packets, or pass the buffers up to the ipath layered driver and - * thence the network layer, replacing them as we do so (see - * ipath_rcv_layer()). - */ -static int create_port0_egr(struct ipath_devdata *dd) -{ - unsigned e, egrcnt; - struct ipath_skbinfo *skbinfo; - int ret; - - egrcnt = dd->ipath_p0_rcvegrcnt; - - skbinfo = vmalloc(sizeof(*dd->ipath_port0_skbinfo) * egrcnt); - if (skbinfo == NULL) { - ipath_dev_err(dd, "allocation error for eager TID " - "skb array\n"); - ret = -ENOMEM; - goto bail; - } - for (e = 0; e < egrcnt; e++) { - /* - * This is a bit tricky in that we allocate extra - * space for 2 bytes of the 14 byte ethernet header. - * These two bytes are passed in the ipath header so - * the rest of the data is word aligned. We allocate - * 4 bytes so that the data buffer stays word aligned. - * See ipath_kreceive() for more details. - */ - skbinfo[e].skb = ipath_alloc_skb(dd, GFP_KERNEL); - if (!skbinfo[e].skb) { - ipath_dev_err(dd, "SKB allocation error for " - "eager TID %u\n", e); - while (e != 0) - dev_kfree_skb(skbinfo[--e].skb); - vfree(skbinfo); - ret = -ENOMEM; - goto bail; - } - } - /* - * After loop above, so we can test non-NULL to see if ready - * to use at receive, etc. - */ - dd->ipath_port0_skbinfo = skbinfo; - - for (e = 0; e < egrcnt; e++) { - dd->ipath_port0_skbinfo[e].phys = - ipath_map_single(dd->pcidev, - dd->ipath_port0_skbinfo[e].skb->data, - dd->ipath_ibmaxlen, PCI_DMA_FROMDEVICE); - dd->ipath_f_put_tid(dd, e + (u64 __iomem *) - ((char __iomem *) dd->ipath_kregbase + - dd->ipath_rcvegrbase), - RCVHQ_RCV_TYPE_EAGER, - dd->ipath_port0_skbinfo[e].phys); - } - - ret = 0; - -bail: - return ret; -} - -static int bringup_link(struct ipath_devdata *dd) -{ - u64 val, ibc; - int ret = 0; - - /* hold IBC in reset */ - dd->ipath_control &= ~INFINIPATH_C_LINKENABLE; - ipath_write_kreg(dd, dd->ipath_kregs->kr_control, - dd->ipath_control); - - /* - * set initial max size pkt IBC will send, including ICRC; it's the - * PIO buffer size in dwords, less 1; also see ipath_set_mtu() - */ - val = (dd->ipath_ibmaxlen >> 2) + 1; - ibc = val << dd->ibcc_mpl_shift; - - /* flowcontrolwatermark is in units of KBytes */ - ibc |= 0x5ULL << INFINIPATH_IBCC_FLOWCTRLWATERMARK_SHIFT; - /* - * How often flowctrl sent. More or less in usecs; balance against - * watermark value, so that in theory senders always get a flow - * control update in time to not let the IB link go idle. - */ - ibc |= 0x3ULL << INFINIPATH_IBCC_FLOWCTRLPERIOD_SHIFT; - /* max error tolerance */ - ibc |= 0xfULL << INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT; - /* use "real" buffer space for */ - ibc |= 4ULL << INFINIPATH_IBCC_CREDITSCALE_SHIFT; - /* IB credit flow control. */ - ibc |= 0xfULL << INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT; - /* initially come up waiting for TS1, without sending anything. */ - dd->ipath_ibcctrl = ibc; - /* - * Want to start out with both LINKCMD and LINKINITCMD in NOP - * (0 and 0). Don't put linkinitcmd in ipath_ibcctrl, want that - * to stay a NOP. Flag that we are disabled, for the (unlikely) - * case that some recovery path is trying to bring the link up - * before we are ready. - */ - ibc |= INFINIPATH_IBCC_LINKINITCMD_DISABLE << - INFINIPATH_IBCC_LINKINITCMD_SHIFT; - dd->ipath_flags |= IPATH_IB_LINK_DISABLED; - ipath_cdbg(VERBOSE, "Writing 0x%llx to ibcctrl\n", - (unsigned long long) ibc); - ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, ibc); - - // be sure chip saw it - val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - - ret = dd->ipath_f_bringup_serdes(dd); - - if (ret) - dev_info(&dd->pcidev->dev, "Could not initialize SerDes, " - "not usable\n"); - else { - /* enable IBC */ - dd->ipath_control |= INFINIPATH_C_LINKENABLE; - ipath_write_kreg(dd, dd->ipath_kregs->kr_control, - dd->ipath_control); - } - - return ret; -} - -static struct ipath_portdata *create_portdata0(struct ipath_devdata *dd) -{ - struct ipath_portdata *pd; - - pd = kzalloc(sizeof(*pd), GFP_KERNEL); - if (pd) { - pd->port_dd = dd; - pd->port_cnt = 1; - /* The port 0 pkey table is used by the layer interface. */ - pd->port_pkeys[0] = IPATH_DEFAULT_P_KEY; - pd->port_seq_cnt = 1; - } - return pd; -} - -static int init_chip_first(struct ipath_devdata *dd) -{ - struct ipath_portdata *pd; - int ret = 0; - u64 val; - - spin_lock_init(&dd->ipath_kernel_tid_lock); - spin_lock_init(&dd->ipath_user_tid_lock); - spin_lock_init(&dd->ipath_sendctrl_lock); - spin_lock_init(&dd->ipath_uctxt_lock); - spin_lock_init(&dd->ipath_sdma_lock); - spin_lock_init(&dd->ipath_gpio_lock); - spin_lock_init(&dd->ipath_eep_st_lock); - spin_lock_init(&dd->ipath_sdepb_lock); - mutex_init(&dd->ipath_eep_lock); - - /* - * skip cfgports stuff because we are not allocating memory, - * and we don't want problems if the portcnt changed due to - * cfgports. We do still check and report a difference, if - * not same (should be impossible). - */ - dd->ipath_f_config_ports(dd, ipath_cfgports); - if (!ipath_cfgports) - dd->ipath_cfgports = dd->ipath_portcnt; - else if (ipath_cfgports <= dd->ipath_portcnt) { - dd->ipath_cfgports = ipath_cfgports; - ipath_dbg("Configured to use %u ports out of %u in chip\n", - dd->ipath_cfgports, ipath_read_kreg32(dd, - dd->ipath_kregs->kr_portcnt)); - } else { - dd->ipath_cfgports = dd->ipath_portcnt; - ipath_dbg("Tried to configured to use %u ports; chip " - "only supports %u\n", ipath_cfgports, - ipath_read_kreg32(dd, - dd->ipath_kregs->kr_portcnt)); - } - /* - * Allocate full portcnt array, rather than just cfgports, because - * cleanup iterates across all possible ports. - */ - dd->ipath_pd = kcalloc(dd->ipath_portcnt, sizeof(*dd->ipath_pd), - GFP_KERNEL); - - if (!dd->ipath_pd) { - ipath_dev_err(dd, "Unable to allocate portdata array, " - "failing\n"); - ret = -ENOMEM; - goto done; - } - - pd = create_portdata0(dd); - if (!pd) { - ipath_dev_err(dd, "Unable to allocate portdata for port " - "0, failing\n"); - ret = -ENOMEM; - goto done; - } - dd->ipath_pd[0] = pd; - - dd->ipath_rcvtidcnt = - ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt); - dd->ipath_rcvtidbase = - ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidbase); - dd->ipath_rcvegrcnt = - ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt); - dd->ipath_rcvegrbase = - ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrbase); - dd->ipath_palign = - ipath_read_kreg32(dd, dd->ipath_kregs->kr_pagealign); - dd->ipath_piobufbase = - ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiobufbase); - val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiosize); - dd->ipath_piosize2k = val & ~0U; - dd->ipath_piosize4k = val >> 32; - if (dd->ipath_piosize4k == 0 && ipath_mtu4096) - ipath_mtu4096 = 0; /* 4KB not supported by this chip */ - dd->ipath_ibmtu = ipath_mtu4096 ? 4096 : 2048; - val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiobufcnt); - dd->ipath_piobcnt2k = val & ~0U; - dd->ipath_piobcnt4k = val >> 32; - dd->ipath_pio2kbase = - (u32 __iomem *) (((char __iomem *) dd->ipath_kregbase) + - (dd->ipath_piobufbase & 0xffffffff)); - if (dd->ipath_piobcnt4k) { - dd->ipath_pio4kbase = (u32 __iomem *) - (((char __iomem *) dd->ipath_kregbase) + - (dd->ipath_piobufbase >> 32)); - /* - * 4K buffers take 2 pages; we use roundup just to be - * paranoid; we calculate it once here, rather than on - * ever buf allocate - */ - dd->ipath_4kalign = ALIGN(dd->ipath_piosize4k, - dd->ipath_palign); - ipath_dbg("%u 2k(%x) piobufs @ %p, %u 4k(%x) @ %p " - "(%x aligned)\n", - dd->ipath_piobcnt2k, dd->ipath_piosize2k, - dd->ipath_pio2kbase, dd->ipath_piobcnt4k, - dd->ipath_piosize4k, dd->ipath_pio4kbase, - dd->ipath_4kalign); - } else { - ipath_dbg("%u 2k piobufs @ %p\n", - dd->ipath_piobcnt2k, dd->ipath_pio2kbase); - } -done: - return ret; -} - -/** - * init_chip_reset - re-initialize after a reset, or enable - * @dd: the infinipath device - * - * sanity check at least some of the values after reset, and - * ensure no receive or transmit (explicitly, in case reset - * failed - */ -static int init_chip_reset(struct ipath_devdata *dd) -{ - u32 rtmp; - int i; - unsigned long flags; - - /* - * ensure chip does no sends or receives, tail updates, or - * pioavail updates while we re-initialize - */ - dd->ipath_rcvctrl &= ~(1ULL << dd->ipath_r_tailupd_shift); - for (i = 0; i < dd->ipath_portcnt; i++) { - clear_bit(dd->ipath_r_portenable_shift + i, - &dd->ipath_rcvctrl); - clear_bit(dd->ipath_r_intravail_shift + i, - &dd->ipath_rcvctrl); - } - ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, - dd->ipath_rcvctrl); - - spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); - dd->ipath_sendctrl = 0U; /* no sdma, etc */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl); - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); - - ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0ULL); - - rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt); - if (rtmp != dd->ipath_rcvtidcnt) - dev_info(&dd->pcidev->dev, "tidcnt was %u before " - "reset, now %u, using original\n", - dd->ipath_rcvtidcnt, rtmp); - rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidbase); - if (rtmp != dd->ipath_rcvtidbase) - dev_info(&dd->pcidev->dev, "tidbase was %u before " - "reset, now %u, using original\n", - dd->ipath_rcvtidbase, rtmp); - rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt); - if (rtmp != dd->ipath_rcvegrcnt) - dev_info(&dd->pcidev->dev, "egrcnt was %u before " - "reset, now %u, using original\n", - dd->ipath_rcvegrcnt, rtmp); - rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrbase); - if (rtmp != dd->ipath_rcvegrbase) - dev_info(&dd->pcidev->dev, "egrbase was %u before " - "reset, now %u, using original\n", - dd->ipath_rcvegrbase, rtmp); - - return 0; -} - -static int init_pioavailregs(struct ipath_devdata *dd) -{ - int ret; - - dd->ipath_pioavailregs_dma = dma_alloc_coherent( - &dd->pcidev->dev, PAGE_SIZE, &dd->ipath_pioavailregs_phys, - GFP_KERNEL); - if (!dd->ipath_pioavailregs_dma) { - ipath_dev_err(dd, "failed to allocate PIOavail reg area " - "in memory\n"); - ret = -ENOMEM; - goto done; - } - - /* - * we really want L2 cache aligned, but for current CPUs of - * interest, they are the same. - */ - dd->ipath_statusp = (u64 *) - ((char *)dd->ipath_pioavailregs_dma + - ((2 * L1_CACHE_BYTES + - dd->ipath_pioavregs * sizeof(u64)) & ~L1_CACHE_BYTES)); - /* copy the current value now that it's really allocated */ - *dd->ipath_statusp = dd->_ipath_status; - /* - * setup buffer to hold freeze msg, accessible to apps, - * following statusp - */ - dd->ipath_freezemsg = (char *)&dd->ipath_statusp[1]; - /* and its length */ - dd->ipath_freezelen = L1_CACHE_BYTES - sizeof(dd->ipath_statusp[0]); - - ret = 0; - -done: - return ret; -} - -/** - * init_shadow_tids - allocate the shadow TID array - * @dd: the infinipath device - * - * allocate the shadow TID array, so we can ipath_munlock previous - * entries. It may make more sense to move the pageshadow to the - * port data structure, so we only allocate memory for ports actually - * in use, since we at 8k per port, now. - */ -static void init_shadow_tids(struct ipath_devdata *dd) -{ - struct page **pages; - dma_addr_t *addrs; - - pages = vzalloc(dd->ipath_cfgports * dd->ipath_rcvtidcnt * - sizeof(struct page *)); - if (!pages) { - ipath_dev_err(dd, "failed to allocate shadow page * " - "array, no expected sends!\n"); - dd->ipath_pageshadow = NULL; - return; - } - - addrs = vmalloc(dd->ipath_cfgports * dd->ipath_rcvtidcnt * - sizeof(dma_addr_t)); - if (!addrs) { - ipath_dev_err(dd, "failed to allocate shadow dma handle " - "array, no expected sends!\n"); - vfree(pages); - dd->ipath_pageshadow = NULL; - return; - } - - dd->ipath_pageshadow = pages; - dd->ipath_physshadow = addrs; -} - -static void enable_chip(struct ipath_devdata *dd, int reinit) -{ - u32 val; - u64 rcvmask; - unsigned long flags; - int i; - - if (!reinit) - init_waitqueue_head(&ipath_state_wait); - - ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, - dd->ipath_rcvctrl); - - spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); - /* Enable PIO send, and update of PIOavail regs to memory. */ - dd->ipath_sendctrl = INFINIPATH_S_PIOENABLE | - INFINIPATH_S_PIOBUFAVAILUPD; - - /* - * Set the PIO avail update threshold to host memory - * on chips that support it. - */ - if (dd->ipath_pioupd_thresh) - dd->ipath_sendctrl |= dd->ipath_pioupd_thresh - << INFINIPATH_S_UPDTHRESH_SHIFT; - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl); - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); - - /* - * Enable kernel ports' receive and receive interrupt. - * Other ports done as user opens and inits them. - */ - rcvmask = 1ULL; - dd->ipath_rcvctrl |= (rcvmask << dd->ipath_r_portenable_shift) | - (rcvmask << dd->ipath_r_intravail_shift); - if (!(dd->ipath_flags & IPATH_NODMA_RTAIL)) - dd->ipath_rcvctrl |= (1ULL << dd->ipath_r_tailupd_shift); - - ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, - dd->ipath_rcvctrl); - - /* - * now ready for use. this should be cleared whenever we - * detect a reset, or initiate one. - */ - dd->ipath_flags |= IPATH_INITTED; - - /* - * Init our shadow copies of head from tail values, - * and write head values to match. - */ - val = ipath_read_ureg32(dd, ur_rcvegrindextail, 0); - ipath_write_ureg(dd, ur_rcvegrindexhead, val, 0); - - /* Initialize so we interrupt on next packet received */ - ipath_write_ureg(dd, ur_rcvhdrhead, - dd->ipath_rhdrhead_intr_off | - dd->ipath_pd[0]->port_head, 0); - - /* - * by now pioavail updates to memory should have occurred, so - * copy them into our working/shadow registers; this is in - * case something went wrong with abort, but mostly to get the - * initial values of the generation bit correct. - */ - for (i = 0; i < dd->ipath_pioavregs; i++) { - __le64 pioavail; - - /* - * Chip Errata bug 6641; even and odd qwords>3 are swapped. - */ - if (i > 3 && (dd->ipath_flags & IPATH_SWAP_PIOBUFS)) - pioavail = dd->ipath_pioavailregs_dma[i ^ 1]; - else - pioavail = dd->ipath_pioavailregs_dma[i]; - /* - * don't need to worry about ipath_pioavailkernel here - * because we will call ipath_chg_pioavailkernel() later - * in initialization, to busy out buffers as needed - */ - dd->ipath_pioavailshadow[i] = le64_to_cpu(pioavail); - } - /* can get counters, stats, etc. */ - dd->ipath_flags |= IPATH_PRESENT; -} - -static int init_housekeeping(struct ipath_devdata *dd, int reinit) -{ - char boardn[40]; - int ret = 0; - - /* - * have to clear shadow copies of registers at init that are - * not otherwise set here, or all kinds of bizarre things - * happen with driver on chip reset - */ - dd->ipath_rcvhdrsize = 0; - - /* - * Don't clear ipath_flags as 8bit mode was set before - * entering this func. However, we do set the linkstate to - * unknown, so we can watch for a transition. - * PRESENT is set because we want register reads to work, - * and the kernel infrastructure saw it in config space; - * We clear it if we have failures. - */ - dd->ipath_flags |= IPATH_LINKUNK | IPATH_PRESENT; - dd->ipath_flags &= ~(IPATH_LINKACTIVE | IPATH_LINKARMED | - IPATH_LINKDOWN | IPATH_LINKINIT); - - ipath_cdbg(VERBOSE, "Try to read spc chip revision\n"); - dd->ipath_revision = - ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision); - - /* - * set up fundamental info we need to use the chip; we assume - * if the revision reg and these regs are OK, we don't need to - * special case the rest - */ - dd->ipath_sregbase = - ipath_read_kreg32(dd, dd->ipath_kregs->kr_sendregbase); - dd->ipath_cregbase = - ipath_read_kreg32(dd, dd->ipath_kregs->kr_counterregbase); - dd->ipath_uregbase = - ipath_read_kreg32(dd, dd->ipath_kregs->kr_userregbase); - ipath_cdbg(VERBOSE, "ipath_kregbase %p, sendbase %x usrbase %x, " - "cntrbase %x\n", dd->ipath_kregbase, dd->ipath_sregbase, - dd->ipath_uregbase, dd->ipath_cregbase); - if ((dd->ipath_revision & 0xffffffff) == 0xffffffff - || (dd->ipath_sregbase & 0xffffffff) == 0xffffffff - || (dd->ipath_cregbase & 0xffffffff) == 0xffffffff - || (dd->ipath_uregbase & 0xffffffff) == 0xffffffff) { - ipath_dev_err(dd, "Register read failures from chip, " - "giving up initialization\n"); - dd->ipath_flags &= ~IPATH_PRESENT; - ret = -ENODEV; - goto done; - } - - - /* clear diagctrl register, in case diags were running and crashed */ - ipath_write_kreg (dd, dd->ipath_kregs->kr_hwdiagctrl, 0); - - /* clear the initial reset flag, in case first driver load */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, - INFINIPATH_E_RESET); - - ipath_cdbg(VERBOSE, "Revision %llx (PCI %x)\n", - (unsigned long long) dd->ipath_revision, - dd->ipath_pcirev); - - if (((dd->ipath_revision >> INFINIPATH_R_SOFTWARE_SHIFT) & - INFINIPATH_R_SOFTWARE_MASK) != IPATH_CHIP_SWVERSION) { - ipath_dev_err(dd, "Driver only handles version %d, " - "chip swversion is %d (%llx), failng\n", - IPATH_CHIP_SWVERSION, - (int)(dd->ipath_revision >> - INFINIPATH_R_SOFTWARE_SHIFT) & - INFINIPATH_R_SOFTWARE_MASK, - (unsigned long long) dd->ipath_revision); - ret = -ENOSYS; - goto done; - } - dd->ipath_majrev = (u8) ((dd->ipath_revision >> - INFINIPATH_R_CHIPREVMAJOR_SHIFT) & - INFINIPATH_R_CHIPREVMAJOR_MASK); - dd->ipath_minrev = (u8) ((dd->ipath_revision >> - INFINIPATH_R_CHIPREVMINOR_SHIFT) & - INFINIPATH_R_CHIPREVMINOR_MASK); - dd->ipath_boardrev = (u8) ((dd->ipath_revision >> - INFINIPATH_R_BOARDID_SHIFT) & - INFINIPATH_R_BOARDID_MASK); - - ret = dd->ipath_f_get_boardname(dd, boardn, sizeof boardn); - - snprintf(dd->ipath_boardversion, sizeof(dd->ipath_boardversion), - "ChipABI %u.%u, %s, InfiniPath%u %u.%u, PCI %u, " - "SW Compat %u\n", - IPATH_CHIP_VERS_MAJ, IPATH_CHIP_VERS_MIN, boardn, - (unsigned)(dd->ipath_revision >> INFINIPATH_R_ARCH_SHIFT) & - INFINIPATH_R_ARCH_MASK, - dd->ipath_majrev, dd->ipath_minrev, dd->ipath_pcirev, - (unsigned)(dd->ipath_revision >> - INFINIPATH_R_SOFTWARE_SHIFT) & - INFINIPATH_R_SOFTWARE_MASK); - - ipath_dbg("%s", dd->ipath_boardversion); - - if (ret) - goto done; - - if (reinit) - ret = init_chip_reset(dd); - else - ret = init_chip_first(dd); - -done: - return ret; -} - -static void verify_interrupt(unsigned long opaque) -{ - struct ipath_devdata *dd = (struct ipath_devdata *) opaque; - - if (!dd) - return; /* being torn down */ - - /* - * If we don't have any interrupts, let the user know and - * don't bother checking again. - */ - if (dd->ipath_int_counter == 0) { - if (!dd->ipath_f_intr_fallback(dd)) - dev_err(&dd->pcidev->dev, "No interrupts detected, " - "not usable.\n"); - else /* re-arm the timer to see if fallback works */ - mod_timer(&dd->ipath_intrchk_timer, jiffies + HZ/2); - } else - ipath_cdbg(VERBOSE, "%u interrupts at timer check\n", - dd->ipath_int_counter); -} - -/** - * ipath_init_chip - do the actual initialization sequence on the chip - * @dd: the infinipath device - * @reinit: reinitializing, so don't allocate new memory - * - * Do the actual initialization sequence on the chip. This is done - * both from the init routine called from the PCI infrastructure, and - * when we reset the chip, or detect that it was reset internally, - * or it's administratively re-enabled. - * - * Memory allocation here and in called routines is only done in - * the first case (reinit == 0). We have to be careful, because even - * without memory allocation, we need to re-write all the chip registers - * TIDs, etc. after the reset or enable has completed. - */ -int ipath_init_chip(struct ipath_devdata *dd, int reinit) -{ - int ret = 0; - u32 kpiobufs, defkbufs; - u32 piobufs, uports; - u64 val; - struct ipath_portdata *pd; - gfp_t gfp_flags = GFP_USER | __GFP_COMP; - - ret = init_housekeeping(dd, reinit); - if (ret) - goto done; - - /* - * We could bump this to allow for full rcvegrcnt + rcvtidcnt, - * but then it no longer nicely fits power of two, and since - * we now use routines that backend onto __get_free_pages, the - * rest would be wasted. - */ - dd->ipath_rcvhdrcnt = max(dd->ipath_p0_rcvegrcnt, dd->ipath_rcvegrcnt); - ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrcnt, - dd->ipath_rcvhdrcnt); - - /* - * Set up the shadow copies of the piobufavail registers, - * which we compare against the chip registers for now, and - * the in memory DMA'ed copies of the registers. This has to - * be done early, before we calculate lastport, etc. - */ - piobufs = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k; - /* - * calc number of pioavail registers, and save it; we have 2 - * bits per buffer. - */ - dd->ipath_pioavregs = ALIGN(piobufs, sizeof(u64) * BITS_PER_BYTE / 2) - / (sizeof(u64) * BITS_PER_BYTE / 2); - uports = dd->ipath_cfgports ? dd->ipath_cfgports - 1 : 0; - if (piobufs > 144) - defkbufs = 32 + dd->ipath_pioreserved; - else - defkbufs = 16 + dd->ipath_pioreserved; - - if (ipath_kpiobufs && (ipath_kpiobufs + - (uports * IPATH_MIN_USER_PORT_BUFCNT)) > piobufs) { - int i = (int) piobufs - - (int) (uports * IPATH_MIN_USER_PORT_BUFCNT); - if (i < 1) - i = 1; - dev_info(&dd->pcidev->dev, "Allocating %d PIO bufs of " - "%d for kernel leaves too few for %d user ports " - "(%d each); using %u\n", ipath_kpiobufs, - piobufs, uports, IPATH_MIN_USER_PORT_BUFCNT, i); - /* - * shouldn't change ipath_kpiobufs, because could be - * different for different devices... - */ - kpiobufs = i; - } else if (ipath_kpiobufs) - kpiobufs = ipath_kpiobufs; - else - kpiobufs = defkbufs; - dd->ipath_lastport_piobuf = piobufs - kpiobufs; - dd->ipath_pbufsport = - uports ? dd->ipath_lastport_piobuf / uports : 0; - /* if not an even divisor, some user ports get extra buffers */ - dd->ipath_ports_extrabuf = dd->ipath_lastport_piobuf - - (dd->ipath_pbufsport * uports); - if (dd->ipath_ports_extrabuf) - ipath_dbg("%u pbufs/port leaves some unused, add 1 buffer to " - "ports <= %u\n", dd->ipath_pbufsport, - dd->ipath_ports_extrabuf); - dd->ipath_lastpioindex = 0; - dd->ipath_lastpioindexl = dd->ipath_piobcnt2k; - /* ipath_pioavailshadow initialized earlier */ - ipath_cdbg(VERBOSE, "%d PIO bufs for kernel out of %d total %u " - "each for %u user ports\n", kpiobufs, - piobufs, dd->ipath_pbufsport, uports); - ret = dd->ipath_f_early_init(dd); - if (ret) { - ipath_dev_err(dd, "Early initialization failure\n"); - goto done; - } - - /* - * Early_init sets rcvhdrentsize and rcvhdrsize, so this must be - * done after early_init. - */ - dd->ipath_hdrqlast = - dd->ipath_rcvhdrentsize * (dd->ipath_rcvhdrcnt - 1); - ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrentsize, - dd->ipath_rcvhdrentsize); - ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrsize, - dd->ipath_rcvhdrsize); - - if (!reinit) { - ret = init_pioavailregs(dd); - init_shadow_tids(dd); - if (ret) - goto done; - } - - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendpioavailaddr, - dd->ipath_pioavailregs_phys); - - /* - * this is to detect s/w errors, which the h/w works around by - * ignoring the low 6 bits of address, if it wasn't aligned. - */ - val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpioavailaddr); - if (val != dd->ipath_pioavailregs_phys) { - ipath_dev_err(dd, "Catastrophic software error, " - "SendPIOAvailAddr written as %lx, " - "read back as %llx\n", - (unsigned long) dd->ipath_pioavailregs_phys, - (unsigned long long) val); - ret = -EINVAL; - goto done; - } - - ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvbthqp, IPATH_KD_QP); - - /* - * make sure we are not in freeze, and PIO send enabled, so - * writes to pbc happen - */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, 0ULL); - ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, - ~0ULL&~INFINIPATH_HWE_MEMBISTFAILED); - ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0ULL); - - /* - * before error clears, since we expect serdes pll errors during - * this, the first time after reset - */ - if (bringup_link(dd)) { - dev_info(&dd->pcidev->dev, "Failed to bringup IB link\n"); - ret = -ENETDOWN; - goto done; - } - - /* - * clear any "expected" hwerrs from reset and/or initialization - * clear any that aren't enabled (at least this once), and then - * set the enable mask - */ - dd->ipath_f_init_hwerrors(dd); - ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, - ~0ULL&~INFINIPATH_HWE_MEMBISTFAILED); - ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, - dd->ipath_hwerrmask); - - /* clear all */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, -1LL); - /* enable errors that are masked, at least this first time. */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, - ~dd->ipath_maskederrs); - dd->ipath_maskederrs = 0; /* don't re-enable ignored in timer */ - dd->ipath_errormask = - ipath_read_kreg64(dd, dd->ipath_kregs->kr_errormask); - /* clear any interrupts up to this point (ints still not enabled) */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL); - - dd->ipath_f_tidtemplate(dd); - - /* - * Set up the port 0 (kernel) rcvhdr q and egr TIDs. If doing - * re-init, the simplest way to handle this is to free - * existing, and re-allocate. - * Need to re-create rest of port 0 portdata as well. - */ - pd = dd->ipath_pd[0]; - if (reinit) { - struct ipath_portdata *npd; - - /* - * Alloc and init new ipath_portdata for port0, - * Then free old pd. Could lead to fragmentation, but also - * makes later support for hot-swap easier. - */ - npd = create_portdata0(dd); - if (npd) { - ipath_free_pddata(dd, pd); - dd->ipath_pd[0] = npd; - pd = npd; - } else { - ipath_dev_err(dd, "Unable to allocate portdata" - " for port 0, failing\n"); - ret = -ENOMEM; - goto done; - } - } - ret = ipath_create_rcvhdrq(dd, pd); - if (!ret) - ret = create_port0_egr(dd); - if (ret) { - ipath_dev_err(dd, "failed to allocate kernel port's " - "rcvhdrq and/or egr bufs\n"); - goto done; - } else { - enable_chip(dd, reinit); - } - - /* after enable_chip, so pioavailshadow setup */ - ipath_chg_pioavailkernel(dd, 0, piobufs, 1); - - /* - * Cancel any possible active sends from early driver load. - * Follows early_init because some chips have to initialize - * PIO buffers in early_init to avoid false parity errors. - * After enable and ipath_chg_pioavailkernel so we can safely - * enable pioavail updates and PIOENABLE; packets are now - * ready to go out. - */ - ipath_cancel_sends(dd, 1); - - if (!reinit) { - /* - * Used when we close a port, for DMA already in flight - * at close. - */ - dd->ipath_dummy_hdrq = dma_alloc_coherent( - &dd->pcidev->dev, dd->ipath_pd[0]->port_rcvhdrq_size, - &dd->ipath_dummy_hdrq_phys, - gfp_flags); - if (!dd->ipath_dummy_hdrq) { - dev_info(&dd->pcidev->dev, - "Couldn't allocate 0x%lx bytes for dummy hdrq\n", - dd->ipath_pd[0]->port_rcvhdrq_size); - /* fallback to just 0'ing */ - dd->ipath_dummy_hdrq_phys = 0UL; - } - } - - /* - * cause retrigger of pending interrupts ignored during init, - * even if we had errors - */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL); - - if (!dd->ipath_stats_timer_active) { - /* - * first init, or after an admin disable/enable - * set up stats retrieval timer, even if we had errors - * in last portion of setup - */ - setup_timer(&dd->ipath_stats_timer, ipath_get_faststats, - (unsigned long)dd); - /* every 5 seconds; */ - dd->ipath_stats_timer.expires = jiffies + 5 * HZ; - /* takes ~16 seconds to overflow at full IB 4x bandwdith */ - add_timer(&dd->ipath_stats_timer); - dd->ipath_stats_timer_active = 1; - } - - /* Set up SendDMA if chip supports it */ - if (dd->ipath_flags & IPATH_HAS_SEND_DMA) - ret = setup_sdma(dd); - - /* Set up HoL state */ - setup_timer(&dd->ipath_hol_timer, ipath_hol_event, (unsigned long)dd); - - dd->ipath_hol_state = IPATH_HOL_UP; - -done: - if (!ret) { - *dd->ipath_statusp |= IPATH_STATUS_CHIP_PRESENT; - if (!dd->ipath_f_intrsetup(dd)) { - /* now we can enable all interrupts from the chip */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, - -1LL); - /* force re-interrupt of any pending interrupts. */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, - 0ULL); - /* chip is usable; mark it as initialized */ - *dd->ipath_statusp |= IPATH_STATUS_INITTED; - - /* - * setup to verify we get an interrupt, and fallback - * to an alternate if necessary and possible - */ - if (!reinit) { - setup_timer(&dd->ipath_intrchk_timer, - verify_interrupt, - (unsigned long)dd); - } - dd->ipath_intrchk_timer.expires = jiffies + HZ/2; - add_timer(&dd->ipath_intrchk_timer); - } else - ipath_dev_err(dd, "No interrupts enabled, couldn't " - "setup interrupt address\n"); - - if (dd->ipath_cfgports > ipath_stats.sps_nports) - /* - * sps_nports is a global, so, we set it to - * the highest number of ports of any of the - * chips we find; we never decrement it, at - * least for now. Since this might have changed - * over disable/enable or prior to reset, always - * do the check and potentially adjust. - */ - ipath_stats.sps_nports = dd->ipath_cfgports; - } else - ipath_dbg("Failed (%d) to initialize chip\n", ret); - - /* if ret is non-zero, we probably should do some cleanup - here... */ - return ret; -} - -static int ipath_set_kpiobufs(const char *str, struct kernel_param *kp) -{ - struct ipath_devdata *dd; - unsigned long flags; - unsigned short val; - int ret; - - ret = ipath_parse_ushort(str, &val); - - spin_lock_irqsave(&ipath_devs_lock, flags); - - if (ret < 0) - goto bail; - - if (val == 0) { - ret = -EINVAL; - goto bail; - } - - list_for_each_entry(dd, &ipath_dev_list, ipath_list) { - if (dd->ipath_kregbase) - continue; - if (val > (dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - - (dd->ipath_cfgports * - IPATH_MIN_USER_PORT_BUFCNT))) - { - ipath_dev_err( - dd, - "Allocating %d PIO bufs for kernel leaves " - "too few for %d user ports (%d each)\n", - val, dd->ipath_cfgports - 1, - IPATH_MIN_USER_PORT_BUFCNT); - ret = -EINVAL; - goto bail; - } - dd->ipath_lastport_piobuf = - dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - val; - } - - ipath_kpiobufs = val; - ret = 0; -bail: - spin_unlock_irqrestore(&ipath_devs_lock, flags); - - return ret; -} diff --git a/drivers/staging/rdma/ipath/ipath_intr.c b/drivers/staging/rdma/ipath/ipath_intr.c deleted file mode 100644 index 0403fa28ed8d..000000000000 --- a/drivers/staging/rdma/ipath/ipath_intr.c +++ /dev/null @@ -1,1271 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include "ipath_kernel.h" -#include "ipath_verbs.h" -#include "ipath_common.h" - - -/* - * Called when we might have an error that is specific to a particular - * PIO buffer, and may need to cancel that buffer, so it can be re-used. - */ -void ipath_disarm_senderrbufs(struct ipath_devdata *dd) -{ - u32 piobcnt; - unsigned long sbuf[4]; - /* - * it's possible that sendbuffererror could have bits set; might - * have already done this as a result of hardware error handling - */ - piobcnt = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k; - /* read these before writing errorclear */ - sbuf[0] = ipath_read_kreg64( - dd, dd->ipath_kregs->kr_sendbuffererror); - sbuf[1] = ipath_read_kreg64( - dd, dd->ipath_kregs->kr_sendbuffererror + 1); - if (piobcnt > 128) - sbuf[2] = ipath_read_kreg64( - dd, dd->ipath_kregs->kr_sendbuffererror + 2); - if (piobcnt > 192) - sbuf[3] = ipath_read_kreg64( - dd, dd->ipath_kregs->kr_sendbuffererror + 3); - else - sbuf[3] = 0; - - if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) { - int i; - if (ipath_debug & (__IPATH_PKTDBG|__IPATH_DBG) && - time_after(dd->ipath_lastcancel, jiffies)) { - __IPATH_DBG_WHICH(__IPATH_PKTDBG|__IPATH_DBG, - "SendbufErrs %lx %lx", sbuf[0], - sbuf[1]); - if (ipath_debug & __IPATH_PKTDBG && piobcnt > 128) - printk(" %lx %lx ", sbuf[2], sbuf[3]); - printk("\n"); - } - - for (i = 0; i < piobcnt; i++) - if (test_bit(i, sbuf)) - ipath_disarm_piobufs(dd, i, 1); - /* ignore armlaunch errs for a bit */ - dd->ipath_lastcancel = jiffies+3; - } -} - - -/* These are all rcv-related errors which we want to count for stats */ -#define E_SUM_PKTERRS \ - (INFINIPATH_E_RHDRLEN | INFINIPATH_E_RBADTID | \ - INFINIPATH_E_RBADVERSION | INFINIPATH_E_RHDR | \ - INFINIPATH_E_RLONGPKTLEN | INFINIPATH_E_RSHORTPKTLEN | \ - INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RMINPKTLEN | \ - INFINIPATH_E_RFORMATERR | INFINIPATH_E_RUNSUPVL | \ - INFINIPATH_E_RUNEXPCHAR | INFINIPATH_E_REBP) - -/* These are all send-related errors which we want to count for stats */ -#define E_SUM_ERRS \ - (INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM | \ - INFINIPATH_E_SDROPPEDDATAPKT | INFINIPATH_E_SDROPPEDSMPPKT | \ - INFINIPATH_E_SMAXPKTLEN | INFINIPATH_E_SUNSUPVL | \ - INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SPKTLEN | \ - INFINIPATH_E_INVALIDADDR) - -/* - * this is similar to E_SUM_ERRS, but can't ignore armlaunch, don't ignore - * errors not related to freeze and cancelling buffers. Can't ignore - * armlaunch because could get more while still cleaning up, and need - * to cancel those as they happen. - */ -#define E_SPKT_ERRS_IGNORE \ - (INFINIPATH_E_SDROPPEDDATAPKT | INFINIPATH_E_SDROPPEDSMPPKT | \ - INFINIPATH_E_SMAXPKTLEN | INFINIPATH_E_SMINPKTLEN | \ - INFINIPATH_E_SPKTLEN) - -/* - * these are errors that can occur when the link changes state while - * a packet is being sent or received. This doesn't cover things - * like EBP or VCRC that can be the result of a sending having the - * link change state, so we receive a "known bad" packet. - */ -#define E_SUM_LINK_PKTERRS \ - (INFINIPATH_E_SDROPPEDDATAPKT | INFINIPATH_E_SDROPPEDSMPPKT | \ - INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SPKTLEN | \ - INFINIPATH_E_RSHORTPKTLEN | INFINIPATH_E_RMINPKTLEN | \ - INFINIPATH_E_RUNEXPCHAR) - -static u64 handle_e_sum_errs(struct ipath_devdata *dd, ipath_err_t errs) -{ - u64 ignore_this_time = 0; - - ipath_disarm_senderrbufs(dd); - if ((errs & E_SUM_LINK_PKTERRS) && - !(dd->ipath_flags & IPATH_LINKACTIVE)) { - /* - * This can happen when SMA is trying to bring the link - * up, but the IB link changes state at the "wrong" time. - * The IB logic then complains that the packet isn't - * valid. We don't want to confuse people, so we just - * don't print them, except at debug - */ - ipath_dbg("Ignoring packet errors %llx, because link not " - "ACTIVE\n", (unsigned long long) errs); - ignore_this_time = errs & E_SUM_LINK_PKTERRS; - } - - return ignore_this_time; -} - -/* generic hw error messages... */ -#define INFINIPATH_HWE_TXEMEMPARITYERR_MSG(a) \ - { \ - .mask = ( INFINIPATH_HWE_TXEMEMPARITYERR_##a << \ - INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT ), \ - .msg = "TXE " #a " Memory Parity" \ - } -#define INFINIPATH_HWE_RXEMEMPARITYERR_MSG(a) \ - { \ - .mask = ( INFINIPATH_HWE_RXEMEMPARITYERR_##a << \ - INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT ), \ - .msg = "RXE " #a " Memory Parity" \ - } - -static const struct ipath_hwerror_msgs ipath_generic_hwerror_msgs[] = { - INFINIPATH_HWE_MSG(IBCBUSFRSPCPARITYERR, "IPATH2IB Parity"), - INFINIPATH_HWE_MSG(IBCBUSTOSPCPARITYERR, "IB2IPATH Parity"), - - INFINIPATH_HWE_TXEMEMPARITYERR_MSG(PIOBUF), - INFINIPATH_HWE_TXEMEMPARITYERR_MSG(PIOPBC), - INFINIPATH_HWE_TXEMEMPARITYERR_MSG(PIOLAUNCHFIFO), - - INFINIPATH_HWE_RXEMEMPARITYERR_MSG(RCVBUF), - INFINIPATH_HWE_RXEMEMPARITYERR_MSG(LOOKUPQ), - INFINIPATH_HWE_RXEMEMPARITYERR_MSG(EAGERTID), - INFINIPATH_HWE_RXEMEMPARITYERR_MSG(EXPTID), - INFINIPATH_HWE_RXEMEMPARITYERR_MSG(FLAGBUF), - INFINIPATH_HWE_RXEMEMPARITYERR_MSG(DATAINFO), - INFINIPATH_HWE_RXEMEMPARITYERR_MSG(HDRINFO), -}; - -/** - * ipath_format_hwmsg - format a single hwerror message - * @msg message buffer - * @msgl length of message buffer - * @hwmsg message to add to message buffer - */ -static void ipath_format_hwmsg(char *msg, size_t msgl, const char *hwmsg) -{ - strlcat(msg, "[", msgl); - strlcat(msg, hwmsg, msgl); - strlcat(msg, "]", msgl); -} - -/** - * ipath_format_hwerrors - format hardware error messages for display - * @hwerrs hardware errors bit vector - * @hwerrmsgs hardware error descriptions - * @nhwerrmsgs number of hwerrmsgs - * @msg message buffer - * @msgl message buffer length - */ -void ipath_format_hwerrors(u64 hwerrs, - const struct ipath_hwerror_msgs *hwerrmsgs, - size_t nhwerrmsgs, - char *msg, size_t msgl) -{ - int i; - const int glen = - ARRAY_SIZE(ipath_generic_hwerror_msgs); - - for (i=0; iib_init) - ret = "Init"; - else if (state == dd->ib_arm) - ret = "Arm"; - else if (state == dd->ib_active) - ret = "Active"; - else - ret = "Down"; - return ret; -} - -void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev) -{ - struct ib_event event; - - event.device = &dd->verbs_dev->ibdev; - event.element.port_num = 1; - event.event = ev; - ib_dispatch_event(&event); -} - -static void handle_e_ibstatuschanged(struct ipath_devdata *dd, - ipath_err_t errs) -{ - u32 ltstate, lstate, ibstate, lastlstate; - u32 init = dd->ib_init; - u32 arm = dd->ib_arm; - u32 active = dd->ib_active; - const u64 ibcs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus); - - lstate = ipath_ib_linkstate(dd, ibcs); /* linkstate */ - ibstate = ipath_ib_state(dd, ibcs); - /* linkstate at last interrupt */ - lastlstate = ipath_ib_linkstate(dd, dd->ipath_lastibcstat); - ltstate = ipath_ib_linktrstate(dd, ibcs); /* linktrainingtate */ - - /* - * Since going into a recovery state causes the link state to go - * down and since recovery is transitory, it is better if we "miss" - * ever seeing the link training state go into recovery (i.e., - * ignore this transition for link state special handling purposes) - * without even updating ipath_lastibcstat. - */ - if ((ltstate == INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN) || - (ltstate == INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT) || - (ltstate == INFINIPATH_IBCS_LT_STATE_RECOVERIDLE)) - goto done; - - /* - * if linkstate transitions into INIT from any of the various down - * states, or if it transitions from any of the up (INIT or better) - * states into any of the down states (except link recovery), then - * call the chip-specific code to take appropriate actions. - */ - if (lstate >= INFINIPATH_IBCS_L_STATE_INIT && - lastlstate == INFINIPATH_IBCS_L_STATE_DOWN) { - /* transitioned to UP */ - if (dd->ipath_f_ib_updown(dd, 1, ibcs)) { - /* link came up, so we must no longer be disabled */ - dd->ipath_flags &= ~IPATH_IB_LINK_DISABLED; - ipath_cdbg(LINKVERB, "LinkUp handled, skipped\n"); - goto skip_ibchange; /* chip-code handled */ - } - } else if ((lastlstate >= INFINIPATH_IBCS_L_STATE_INIT || - (dd->ipath_flags & IPATH_IB_FORCE_NOTIFY)) && - ltstate <= INFINIPATH_IBCS_LT_STATE_CFGWAITRMT && - ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP) { - int handled; - handled = dd->ipath_f_ib_updown(dd, 0, ibcs); - dd->ipath_flags &= ~IPATH_IB_FORCE_NOTIFY; - if (handled) { - ipath_cdbg(LINKVERB, "LinkDown handled, skipped\n"); - goto skip_ibchange; /* chip-code handled */ - } - } - - /* - * Significant enough to always print and get into logs, if it was - * unexpected. If it was a requested state change, we'll have - * already cleared the flags, so we won't print this warning - */ - if ((ibstate != arm && ibstate != active) && - (dd->ipath_flags & (IPATH_LINKARMED | IPATH_LINKACTIVE))) { - dev_info(&dd->pcidev->dev, "Link state changed from %s " - "to %s\n", (dd->ipath_flags & IPATH_LINKARMED) ? - "ARM" : "ACTIVE", ib_linkstate(dd, ibcs)); - } - - if (ltstate == INFINIPATH_IBCS_LT_STATE_POLLACTIVE || - ltstate == INFINIPATH_IBCS_LT_STATE_POLLQUIET) { - u32 lastlts; - lastlts = ipath_ib_linktrstate(dd, dd->ipath_lastibcstat); - /* - * Ignore cycling back and forth from Polling.Active to - * Polling.Quiet while waiting for the other end of the link - * to come up, except to try and decide if we are connected - * to a live IB device or not. We will cycle back and - * forth between them if no cable is plugged in, the other - * device is powered off or disabled, etc. - */ - if (lastlts == INFINIPATH_IBCS_LT_STATE_POLLACTIVE || - lastlts == INFINIPATH_IBCS_LT_STATE_POLLQUIET) { - if (!(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG) && - (++dd->ipath_ibpollcnt == 40)) { - dd->ipath_flags |= IPATH_NOCABLE; - *dd->ipath_statusp |= - IPATH_STATUS_IB_NOCABLE; - ipath_cdbg(LINKVERB, "Set NOCABLE\n"); - } - ipath_cdbg(LINKVERB, "POLL change to %s (%x)\n", - ipath_ibcstatus_str[ltstate], ibstate); - goto skip_ibchange; - } - } - - dd->ipath_ibpollcnt = 0; /* not poll*, now */ - ipath_stats.sps_iblink++; - - if (ibstate != init && dd->ipath_lastlinkrecov && ipath_linkrecovery) { - u64 linkrecov; - linkrecov = ipath_snap_cntr(dd, - dd->ipath_cregs->cr_iblinkerrrecovcnt); - if (linkrecov != dd->ipath_lastlinkrecov) { - ipath_dbg("IB linkrecov up %Lx (%s %s) recov %Lu\n", - (unsigned long long) ibcs, - ib_linkstate(dd, ibcs), - ipath_ibcstatus_str[ltstate], - (unsigned long long) linkrecov); - /* and no more until active again */ - dd->ipath_lastlinkrecov = 0; - ipath_set_linkstate(dd, IPATH_IB_LINKDOWN); - goto skip_ibchange; - } - } - - if (ibstate == init || ibstate == arm || ibstate == active) { - *dd->ipath_statusp &= ~IPATH_STATUS_IB_NOCABLE; - if (ibstate == init || ibstate == arm) { - *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY; - if (dd->ipath_flags & IPATH_LINKACTIVE) - signal_ib_event(dd, IB_EVENT_PORT_ERR); - } - if (ibstate == arm) { - dd->ipath_flags |= IPATH_LINKARMED; - dd->ipath_flags &= ~(IPATH_LINKUNK | - IPATH_LINKINIT | IPATH_LINKDOWN | - IPATH_LINKACTIVE | IPATH_NOCABLE); - ipath_hol_down(dd); - } else if (ibstate == init) { - /* - * set INIT and DOWN. Down is checked by - * most of the other code, but INIT is - * useful to know in a few places. - */ - dd->ipath_flags |= IPATH_LINKINIT | - IPATH_LINKDOWN; - dd->ipath_flags &= ~(IPATH_LINKUNK | - IPATH_LINKARMED | IPATH_LINKACTIVE | - IPATH_NOCABLE); - ipath_hol_down(dd); - } else { /* active */ - dd->ipath_lastlinkrecov = ipath_snap_cntr(dd, - dd->ipath_cregs->cr_iblinkerrrecovcnt); - *dd->ipath_statusp |= - IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF; - dd->ipath_flags |= IPATH_LINKACTIVE; - dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT - | IPATH_LINKDOWN | IPATH_LINKARMED | - IPATH_NOCABLE); - if (dd->ipath_flags & IPATH_HAS_SEND_DMA) - ipath_restart_sdma(dd); - signal_ib_event(dd, IB_EVENT_PORT_ACTIVE); - /* LED active not handled in chip _f_updown */ - dd->ipath_f_setextled(dd, lstate, ltstate); - ipath_hol_up(dd); - } - - /* - * print after we've already done the work, so as not to - * delay the state changes and notifications, for debugging - */ - if (lstate == lastlstate) - ipath_cdbg(LINKVERB, "Unchanged from last: %s " - "(%x)\n", ib_linkstate(dd, ibcs), ibstate); - else - ipath_cdbg(VERBOSE, "Unit %u: link up to %s %s (%x)\n", - dd->ipath_unit, ib_linkstate(dd, ibcs), - ipath_ibcstatus_str[ltstate], ibstate); - } else { /* down */ - if (dd->ipath_flags & IPATH_LINKACTIVE) - signal_ib_event(dd, IB_EVENT_PORT_ERR); - dd->ipath_flags |= IPATH_LINKDOWN; - dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT - | IPATH_LINKACTIVE | - IPATH_LINKARMED); - *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY; - dd->ipath_lli_counter = 0; - - if (lastlstate != INFINIPATH_IBCS_L_STATE_DOWN) - ipath_cdbg(VERBOSE, "Unit %u link state down " - "(state 0x%x), from %s\n", - dd->ipath_unit, lstate, - ib_linkstate(dd, dd->ipath_lastibcstat)); - else - ipath_cdbg(LINKVERB, "Unit %u link state changed " - "to %s (0x%x) from down (%x)\n", - dd->ipath_unit, - ipath_ibcstatus_str[ltstate], - ibstate, lastlstate); - } - -skip_ibchange: - dd->ipath_lastibcstat = ibcs; -done: - return; -} - -static void handle_supp_msgs(struct ipath_devdata *dd, - unsigned supp_msgs, char *msg, u32 msgsz) -{ - /* - * Print the message unless it's ibc status change only, which - * happens so often we never want to count it. - */ - if (dd->ipath_lasterror & ~INFINIPATH_E_IBSTATUSCHANGED) { - int iserr; - ipath_err_t mask; - iserr = ipath_decode_err(dd, msg, msgsz, - dd->ipath_lasterror & - ~INFINIPATH_E_IBSTATUSCHANGED); - - mask = INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL | - INFINIPATH_E_PKTERRS | INFINIPATH_E_SDMADISABLED; - - /* if we're in debug, then don't mask SDMADISABLED msgs */ - if (ipath_debug & __IPATH_DBG) - mask &= ~INFINIPATH_E_SDMADISABLED; - - if (dd->ipath_lasterror & ~mask) - ipath_dev_err(dd, "Suppressed %u messages for " - "fast-repeating errors (%s) (%llx)\n", - supp_msgs, msg, - (unsigned long long) - dd->ipath_lasterror); - else { - /* - * rcvegrfull and rcvhdrqfull are "normal", for some - * types of processes (mostly benchmarks) that send - * huge numbers of messages, while not processing - * them. So only complain about these at debug - * level. - */ - if (iserr) - ipath_dbg("Suppressed %u messages for %s\n", - supp_msgs, msg); - else - ipath_cdbg(ERRPKT, - "Suppressed %u messages for %s\n", - supp_msgs, msg); - } - } -} - -static unsigned handle_frequent_errors(struct ipath_devdata *dd, - ipath_err_t errs, char *msg, - u32 msgsz, int *noprint) -{ - unsigned long nc; - static unsigned long nextmsg_time; - static unsigned nmsgs, supp_msgs; - - /* - * Throttle back "fast" messages to no more than 10 per 5 seconds. - * This isn't perfect, but it's a reasonable heuristic. If we get - * more than 10, give a 6x longer delay. - */ - nc = jiffies; - if (nmsgs > 10) { - if (time_before(nc, nextmsg_time)) { - *noprint = 1; - if (!supp_msgs++) - nextmsg_time = nc + HZ * 3; - } else if (supp_msgs) { - handle_supp_msgs(dd, supp_msgs, msg, msgsz); - supp_msgs = 0; - nmsgs = 0; - } - } else if (!nmsgs++ || time_after(nc, nextmsg_time)) { - nextmsg_time = nc + HZ / 2; - } - - return supp_msgs; -} - -static void handle_sdma_errors(struct ipath_devdata *dd, ipath_err_t errs) -{ - unsigned long flags; - int expected; - - if (ipath_debug & __IPATH_DBG) { - char msg[128]; - ipath_decode_err(dd, msg, sizeof msg, errs & - INFINIPATH_E_SDMAERRS); - ipath_dbg("errors %lx (%s)\n", (unsigned long)errs, msg); - } - if (ipath_debug & __IPATH_VERBDBG) { - unsigned long tl, hd, status, lengen; - tl = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmatail); - hd = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmahead); - status = ipath_read_kreg64(dd - , dd->ipath_kregs->kr_senddmastatus); - lengen = ipath_read_kreg64(dd, - dd->ipath_kregs->kr_senddmalengen); - ipath_cdbg(VERBOSE, "sdma tl 0x%lx hd 0x%lx status 0x%lx " - "lengen 0x%lx\n", tl, hd, status, lengen); - } - - spin_lock_irqsave(&dd->ipath_sdma_lock, flags); - __set_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status); - expected = test_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status); - spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); - if (!expected) - ipath_cancel_sends(dd, 1); -} - -static void handle_sdma_intr(struct ipath_devdata *dd, u64 istat) -{ - unsigned long flags; - int expected; - - if ((istat & INFINIPATH_I_SDMAINT) && - !test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status)) - ipath_sdma_intr(dd); - - if (istat & INFINIPATH_I_SDMADISABLED) { - expected = test_bit(IPATH_SDMA_ABORTING, - &dd->ipath_sdma_status); - ipath_dbg("%s SDmaDisabled intr\n", - expected ? "expected" : "unexpected"); - spin_lock_irqsave(&dd->ipath_sdma_lock, flags); - __set_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status); - spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); - if (!expected) - ipath_cancel_sends(dd, 1); - if (!test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status)) - tasklet_hi_schedule(&dd->ipath_sdma_abort_task); - } -} - -static int handle_hdrq_full(struct ipath_devdata *dd) -{ - int chkerrpkts = 0; - u32 hd, tl; - u32 i; - - ipath_stats.sps_hdrqfull++; - for (i = 0; i < dd->ipath_cfgports; i++) { - struct ipath_portdata *pd = dd->ipath_pd[i]; - - if (i == 0) { - /* - * For kernel receive queues, we just want to know - * if there are packets in the queue that we can - * process. - */ - if (pd->port_head != ipath_get_hdrqtail(pd)) - chkerrpkts |= 1 << i; - continue; - } - - /* Skip if user context is not open */ - if (!pd || !pd->port_cnt) - continue; - - /* Don't report the same point multiple times. */ - if (dd->ipath_flags & IPATH_NODMA_RTAIL) - tl = ipath_read_ureg32(dd, ur_rcvhdrtail, i); - else - tl = ipath_get_rcvhdrtail(pd); - if (tl == pd->port_lastrcvhdrqtail) - continue; - - hd = ipath_read_ureg32(dd, ur_rcvhdrhead, i); - if (hd == (tl + 1) || (!hd && tl == dd->ipath_hdrqlast)) { - pd->port_lastrcvhdrqtail = tl; - pd->port_hdrqfull++; - /* flush hdrqfull so that poll() sees it */ - wmb(); - wake_up_interruptible(&pd->port_wait); - } - } - - return chkerrpkts; -} - -static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs) -{ - char msg[128]; - u64 ignore_this_time = 0; - u64 iserr = 0; - int chkerrpkts = 0, noprint = 0; - unsigned supp_msgs; - int log_idx; - - /* - * don't report errors that are masked, either at init - * (not set in ipath_errormask), or temporarily (set in - * ipath_maskederrs) - */ - errs &= dd->ipath_errormask & ~dd->ipath_maskederrs; - - supp_msgs = handle_frequent_errors(dd, errs, msg, (u32)sizeof msg, - &noprint); - - /* do these first, they are most important */ - if (errs & INFINIPATH_E_HARDWARE) { - /* reuse same msg buf */ - dd->ipath_f_handle_hwerrors(dd, msg, sizeof msg); - } else { - u64 mask; - for (log_idx = 0; log_idx < IPATH_EEP_LOG_CNT; ++log_idx) { - mask = dd->ipath_eep_st_masks[log_idx].errs_to_log; - if (errs & mask) - ipath_inc_eeprom_err(dd, log_idx, 1); - } - } - - if (errs & INFINIPATH_E_SDMAERRS) - handle_sdma_errors(dd, errs); - - if (!noprint && (errs & ~dd->ipath_e_bitsextant)) - ipath_dev_err(dd, "error interrupt with unknown errors " - "%llx set\n", (unsigned long long) - (errs & ~dd->ipath_e_bitsextant)); - - if (errs & E_SUM_ERRS) - ignore_this_time = handle_e_sum_errs(dd, errs); - else if ((errs & E_SUM_LINK_PKTERRS) && - !(dd->ipath_flags & IPATH_LINKACTIVE)) { - /* - * This can happen when SMA is trying to bring the link - * up, but the IB link changes state at the "wrong" time. - * The IB logic then complains that the packet isn't - * valid. We don't want to confuse people, so we just - * don't print them, except at debug - */ - ipath_dbg("Ignoring packet errors %llx, because link not " - "ACTIVE\n", (unsigned long long) errs); - ignore_this_time = errs & E_SUM_LINK_PKTERRS; - } - - if (supp_msgs == 250000) { - int s_iserr; - /* - * It's not entirely reasonable assuming that the errors set - * in the last clear period are all responsible for the - * problem, but the alternative is to assume it's the only - * ones on this particular interrupt, which also isn't great - */ - dd->ipath_maskederrs |= dd->ipath_lasterror | errs; - - dd->ipath_errormask &= ~dd->ipath_maskederrs; - ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, - dd->ipath_errormask); - s_iserr = ipath_decode_err(dd, msg, sizeof msg, - dd->ipath_maskederrs); - - if (dd->ipath_maskederrs & - ~(INFINIPATH_E_RRCVEGRFULL | - INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS)) - ipath_dev_err(dd, "Temporarily disabling " - "error(s) %llx reporting; too frequent (%s)\n", - (unsigned long long) dd->ipath_maskederrs, - msg); - else { - /* - * rcvegrfull and rcvhdrqfull are "normal", - * for some types of processes (mostly benchmarks) - * that send huge numbers of messages, while not - * processing them. So only complain about - * these at debug level. - */ - if (s_iserr) - ipath_dbg("Temporarily disabling reporting " - "too frequent queue full errors (%s)\n", - msg); - else - ipath_cdbg(ERRPKT, - "Temporarily disabling reporting too" - " frequent packet errors (%s)\n", - msg); - } - - /* - * Re-enable the masked errors after around 3 minutes. in - * ipath_get_faststats(). If we have a series of fast - * repeating but different errors, the interval will keep - * stretching out, but that's OK, as that's pretty - * catastrophic. - */ - dd->ipath_unmasktime = jiffies + HZ * 180; - } - - ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, errs); - if (ignore_this_time) - errs &= ~ignore_this_time; - if (errs & ~dd->ipath_lasterror) { - errs &= ~dd->ipath_lasterror; - /* never suppress duplicate hwerrors or ibstatuschange */ - dd->ipath_lasterror |= errs & - ~(INFINIPATH_E_HARDWARE | - INFINIPATH_E_IBSTATUSCHANGED); - } - - if (errs & INFINIPATH_E_SENDSPECIALTRIGGER) { - dd->ipath_spectriggerhit++; - ipath_dbg("%lu special trigger hits\n", - dd->ipath_spectriggerhit); - } - - /* likely due to cancel; so suppress message unless verbose */ - if ((errs & (INFINIPATH_E_SPKTLEN | INFINIPATH_E_SPIOARMLAUNCH)) && - time_after(dd->ipath_lastcancel, jiffies)) { - /* armlaunch takes precedence; it often causes both. */ - ipath_cdbg(VERBOSE, - "Suppressed %s error (%llx) after sendbuf cancel\n", - (errs & INFINIPATH_E_SPIOARMLAUNCH) ? - "armlaunch" : "sendpktlen", (unsigned long long)errs); - errs &= ~(INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SPKTLEN); - } - - if (!errs) - return 0; - - if (!noprint) { - ipath_err_t mask; - /* - * The ones we mask off are handled specially below - * or above. Also mask SDMADISABLED by default as it - * is too chatty. - */ - mask = INFINIPATH_E_IBSTATUSCHANGED | - INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL | - INFINIPATH_E_HARDWARE | INFINIPATH_E_SDMADISABLED; - - /* if we're in debug, then don't mask SDMADISABLED msgs */ - if (ipath_debug & __IPATH_DBG) - mask &= ~INFINIPATH_E_SDMADISABLED; - - ipath_decode_err(dd, msg, sizeof msg, errs & ~mask); - } else - /* so we don't need if (!noprint) at strlcat's below */ - *msg = 0; - - if (errs & E_SUM_PKTERRS) { - ipath_stats.sps_pkterrs++; - chkerrpkts = 1; - } - if (errs & E_SUM_ERRS) - ipath_stats.sps_errs++; - - if (errs & (INFINIPATH_E_RICRC | INFINIPATH_E_RVCRC)) { - ipath_stats.sps_crcerrs++; - chkerrpkts = 1; - } - iserr = errs & ~(E_SUM_PKTERRS | INFINIPATH_E_PKTERRS); - - - /* - * We don't want to print these two as they happen, or we can make - * the situation even worse, because it takes so long to print - * messages to serial consoles. Kernel ports get printed from - * fast_stats, no more than every 5 seconds, user ports get printed - * on close - */ - if (errs & INFINIPATH_E_RRCVHDRFULL) - chkerrpkts |= handle_hdrq_full(dd); - if (errs & INFINIPATH_E_RRCVEGRFULL) { - struct ipath_portdata *pd = dd->ipath_pd[0]; - - /* - * since this is of less importance and not likely to - * happen without also getting hdrfull, only count - * occurrences; don't check each port (or even the kernel - * vs user) - */ - ipath_stats.sps_etidfull++; - if (pd->port_head != ipath_get_hdrqtail(pd)) - chkerrpkts |= 1; - } - - /* - * do this before IBSTATUSCHANGED, in case both bits set in a single - * interrupt; we want the STATUSCHANGE to "win", so we do our - * internal copy of state machine correctly - */ - if (errs & INFINIPATH_E_RIBLOSTLINK) { - /* - * force through block below - */ - errs |= INFINIPATH_E_IBSTATUSCHANGED; - ipath_stats.sps_iblink++; - dd->ipath_flags |= IPATH_LINKDOWN; - dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT - | IPATH_LINKARMED | IPATH_LINKACTIVE); - *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY; - - ipath_dbg("Lost link, link now down (%s)\n", - ipath_ibcstatus_str[ipath_read_kreg64(dd, - dd->ipath_kregs->kr_ibcstatus) & 0xf]); - } - if (errs & INFINIPATH_E_IBSTATUSCHANGED) - handle_e_ibstatuschanged(dd, errs); - - if (errs & INFINIPATH_E_RESET) { - if (!noprint) - ipath_dev_err(dd, "Got reset, requires re-init " - "(unload and reload driver)\n"); - dd->ipath_flags &= ~IPATH_INITTED; /* needs re-init */ - /* mark as having had error */ - *dd->ipath_statusp |= IPATH_STATUS_HWERROR; - *dd->ipath_statusp &= ~IPATH_STATUS_IB_CONF; - } - - if (!noprint && *msg) { - if (iserr) - ipath_dev_err(dd, "%s error\n", msg); - } - if (dd->ipath_state_wanted & dd->ipath_flags) { - ipath_cdbg(VERBOSE, "driver wanted state %x, iflags now %x, " - "waking\n", dd->ipath_state_wanted, - dd->ipath_flags); - wake_up_interruptible(&ipath_state_wait); - } - - return chkerrpkts; -} - -/* - * try to cleanup as much as possible for anything that might have gone - * wrong while in freeze mode, such as pio buffers being written by user - * processes (causing armlaunch), send errors due to going into freeze mode, - * etc., and try to avoid causing extra interrupts while doing so. - * Forcibly update the in-memory pioavail register copies after cleanup - * because the chip won't do it while in freeze mode (the register values - * themselves are kept correct). - * Make sure that we don't lose any important interrupts by using the chip - * feature that says that writing 0 to a bit in *clear that is set in - * *status will cause an interrupt to be generated again (if allowed by - * the *mask value). - */ -void ipath_clear_freeze(struct ipath_devdata *dd) -{ - /* disable error interrupts, to avoid confusion */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, 0ULL); - - /* also disable interrupts; errormask is sometimes overwriten */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, 0ULL); - - ipath_cancel_sends(dd, 1); - - /* clear the freeze, and be sure chip saw it */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_control, - dd->ipath_control); - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - - /* force in-memory update now we are out of freeze */ - ipath_force_pio_avail_update(dd); - - /* - * force new interrupt if any hwerr, error or interrupt bits are - * still set, and clear "safe" send packet errors related to freeze - * and cancelling sends. Re-enable error interrupts before possible - * force of re-interrupt on pending interrupts. - */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, 0ULL); - ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, - E_SPKT_ERRS_IGNORE); - ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, - dd->ipath_errormask); - ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, -1LL); - ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL); -} - - -/* this is separate to allow for better optimization of ipath_intr() */ - -static noinline void ipath_bad_intr(struct ipath_devdata *dd, u32 *unexpectp) -{ - /* - * sometimes happen during driver init and unload, don't want - * to process any interrupts at that point - */ - - /* this is just a bandaid, not a fix, if something goes badly - * wrong */ - if (++*unexpectp > 100) { - if (++*unexpectp > 105) { - /* - * ok, we must be taking somebody else's interrupts, - * due to a messed up mptable and/or PIRQ table, so - * unregister the interrupt. We've seen this during - * linuxbios development work, and it may happen in - * the future again. - */ - if (dd->pcidev && dd->ipath_irq) { - ipath_dev_err(dd, "Now %u unexpected " - "interrupts, unregistering " - "interrupt handler\n", - *unexpectp); - ipath_dbg("free_irq of irq %d\n", - dd->ipath_irq); - dd->ipath_f_free_irq(dd); - } - } - if (ipath_read_ireg(dd, dd->ipath_kregs->kr_intmask)) { - ipath_dev_err(dd, "%u unexpected interrupts, " - "disabling interrupts completely\n", - *unexpectp); - /* - * disable all interrupts, something is very wrong - */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, - 0ULL); - } - } else if (*unexpectp > 1) - ipath_dbg("Interrupt when not ready, should not happen, " - "ignoring\n"); -} - -static noinline void ipath_bad_regread(struct ipath_devdata *dd) -{ - static int allbits; - - /* separate routine, for better optimization of ipath_intr() */ - - /* - * We print the message and disable interrupts, in hope of - * having a better chance of debugging the problem. - */ - ipath_dev_err(dd, - "Read of interrupt status failed (all bits set)\n"); - if (allbits++) { - /* disable all interrupts, something is very wrong */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, 0ULL); - if (allbits == 2) { - ipath_dev_err(dd, "Still bad interrupt status, " - "unregistering interrupt\n"); - dd->ipath_f_free_irq(dd); - } else if (allbits > 2) { - if ((allbits % 10000) == 0) - printk("."); - } else - ipath_dev_err(dd, "Disabling interrupts, " - "multiple errors\n"); - } -} - -static void handle_layer_pioavail(struct ipath_devdata *dd) -{ - unsigned long flags; - int ret; - - ret = ipath_ib_piobufavail(dd->verbs_dev); - if (ret > 0) - goto set; - - return; -set: - spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); - dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL; - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, - dd->ipath_sendctrl); - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); -} - -/* - * Handle receive interrupts for user ports; this means a user - * process was waiting for a packet to arrive, and didn't want - * to poll - */ -static void handle_urcv(struct ipath_devdata *dd, u64 istat) -{ - u64 portr; - int i; - int rcvdint = 0; - - /* - * test_and_clear_bit(IPATH_PORT_WAITING_RCV) and - * test_and_clear_bit(IPATH_PORT_WAITING_URG) below - * would both like timely updates of the bits so that - * we don't pass them by unnecessarily. the rmb() - * here ensures that we see them promptly -- the - * corresponding wmb()'s are in ipath_poll_urgent() - * and ipath_poll_next()... - */ - rmb(); - portr = ((istat >> dd->ipath_i_rcvavail_shift) & - dd->ipath_i_rcvavail_mask) | - ((istat >> dd->ipath_i_rcvurg_shift) & - dd->ipath_i_rcvurg_mask); - for (i = 1; i < dd->ipath_cfgports; i++) { - struct ipath_portdata *pd = dd->ipath_pd[i]; - - if (portr & (1 << i) && pd && pd->port_cnt) { - if (test_and_clear_bit(IPATH_PORT_WAITING_RCV, - &pd->port_flag)) { - clear_bit(i + dd->ipath_r_intravail_shift, - &dd->ipath_rcvctrl); - wake_up_interruptible(&pd->port_wait); - rcvdint = 1; - } else if (test_and_clear_bit(IPATH_PORT_WAITING_URG, - &pd->port_flag)) { - pd->port_urgent++; - wake_up_interruptible(&pd->port_wait); - } - } - } - if (rcvdint) { - /* only want to take one interrupt, so turn off the rcv - * interrupt for all the ports that we set the rcv_waiting - * (but never for kernel port) - */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, - dd->ipath_rcvctrl); - } -} - -irqreturn_t ipath_intr(int irq, void *data) -{ - struct ipath_devdata *dd = data; - u64 istat, chk0rcv = 0; - ipath_err_t estat = 0; - irqreturn_t ret; - static unsigned unexpected = 0; - u64 kportrbits; - - ipath_stats.sps_ints++; - - if (dd->ipath_int_counter != (u32) -1) - dd->ipath_int_counter++; - - if (!(dd->ipath_flags & IPATH_PRESENT)) { - /* - * This return value is not great, but we do not want the - * interrupt core code to remove our interrupt handler - * because we don't appear to be handling an interrupt - * during a chip reset. - */ - return IRQ_HANDLED; - } - - /* - * this needs to be flags&initted, not statusp, so we keep - * taking interrupts even after link goes down, etc. - * Also, we *must* clear the interrupt at some point, or we won't - * take it again, which can be real bad for errors, etc... - */ - - if (!(dd->ipath_flags & IPATH_INITTED)) { - ipath_bad_intr(dd, &unexpected); - ret = IRQ_NONE; - goto bail; - } - - istat = ipath_read_ireg(dd, dd->ipath_kregs->kr_intstatus); - - if (unlikely(!istat)) { - ipath_stats.sps_nullintr++; - ret = IRQ_NONE; /* not our interrupt, or already handled */ - goto bail; - } - if (unlikely(istat == -1)) { - ipath_bad_regread(dd); - /* don't know if it was our interrupt or not */ - ret = IRQ_NONE; - goto bail; - } - - if (unexpected) - unexpected = 0; - - if (unlikely(istat & ~dd->ipath_i_bitsextant)) - ipath_dev_err(dd, - "interrupt with unknown interrupts %Lx set\n", - (unsigned long long) - istat & ~dd->ipath_i_bitsextant); - else if (istat & ~INFINIPATH_I_ERROR) /* errors do own printing */ - ipath_cdbg(VERBOSE, "intr stat=0x%Lx\n", - (unsigned long long) istat); - - if (istat & INFINIPATH_I_ERROR) { - ipath_stats.sps_errints++; - estat = ipath_read_kreg64(dd, - dd->ipath_kregs->kr_errorstatus); - if (!estat) - dev_info(&dd->pcidev->dev, "error interrupt (%Lx), " - "but no error bits set!\n", - (unsigned long long) istat); - else if (estat == -1LL) - /* - * should we try clearing all, or hope next read - * works? - */ - ipath_dev_err(dd, "Read of error status failed " - "(all bits set); ignoring\n"); - else - chk0rcv |= handle_errors(dd, estat); - } - - if (istat & INFINIPATH_I_GPIO) { - /* - * GPIO interrupts fall in two broad classes: - * GPIO_2 indicates (on some HT4xx boards) that a packet - * has arrived for Port 0. Checking for this - * is controlled by flag IPATH_GPIO_INTR. - * GPIO_3..5 on IBA6120 Rev2 and IBA6110 Rev4 chips indicate - * errors that we need to count. Checking for this - * is controlled by flag IPATH_GPIO_ERRINTRS. - */ - u32 gpiostatus; - u32 to_clear = 0; - - gpiostatus = ipath_read_kreg32( - dd, dd->ipath_kregs->kr_gpio_status); - /* First the error-counter case. */ - if ((gpiostatus & IPATH_GPIO_ERRINTR_MASK) && - (dd->ipath_flags & IPATH_GPIO_ERRINTRS)) { - /* want to clear the bits we see asserted. */ - to_clear |= (gpiostatus & IPATH_GPIO_ERRINTR_MASK); - - /* - * Count appropriately, clear bits out of our copy, - * as they have been "handled". - */ - if (gpiostatus & (1 << IPATH_GPIO_RXUVL_BIT)) { - ipath_dbg("FlowCtl on UnsupVL\n"); - dd->ipath_rxfc_unsupvl_errs++; - } - if (gpiostatus & (1 << IPATH_GPIO_OVRUN_BIT)) { - ipath_dbg("Overrun Threshold exceeded\n"); - dd->ipath_overrun_thresh_errs++; - } - if (gpiostatus & (1 << IPATH_GPIO_LLI_BIT)) { - ipath_dbg("Local Link Integrity error\n"); - dd->ipath_lli_errs++; - } - gpiostatus &= ~IPATH_GPIO_ERRINTR_MASK; - } - /* Now the Port0 Receive case */ - if ((gpiostatus & (1 << IPATH_GPIO_PORT0_BIT)) && - (dd->ipath_flags & IPATH_GPIO_INTR)) { - /* - * GPIO status bit 2 is set, and we expected it. - * clear it and indicate in p0bits. - * This probably only happens if a Port0 pkt - * arrives at _just_ the wrong time, and we - * handle that by seting chk0rcv; - */ - to_clear |= (1 << IPATH_GPIO_PORT0_BIT); - gpiostatus &= ~(1 << IPATH_GPIO_PORT0_BIT); - chk0rcv = 1; - } - if (gpiostatus) { - /* - * Some unexpected bits remain. If they could have - * caused the interrupt, complain and clear. - * To avoid repetition of this condition, also clear - * the mask. It is almost certainly due to error. - */ - const u32 mask = (u32) dd->ipath_gpio_mask; - - if (mask & gpiostatus) { - ipath_dbg("Unexpected GPIO IRQ bits %x\n", - gpiostatus & mask); - to_clear |= (gpiostatus & mask); - dd->ipath_gpio_mask &= ~(gpiostatus & mask); - ipath_write_kreg(dd, - dd->ipath_kregs->kr_gpio_mask, - dd->ipath_gpio_mask); - } - } - if (to_clear) { - ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear, - (u64) to_clear); - } - } - - /* - * Clear the interrupt bits we found set, unless they are receive - * related, in which case we already cleared them above, and don't - * want to clear them again, because we might lose an interrupt. - * Clear it early, so we "know" know the chip will have seen this by - * the time we process the queue, and will re-interrupt if necessary. - * The processor itself won't take the interrupt again until we return. - */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, istat); - - /* - * Handle kernel receive queues before checking for pio buffers - * available since receives can overflow; piobuf waiters can afford - * a few extra cycles, since they were waiting anyway, and user's - * waiting for receive are at the bottom. - */ - kportrbits = (1ULL << dd->ipath_i_rcvavail_shift) | - (1ULL << dd->ipath_i_rcvurg_shift); - if (chk0rcv || (istat & kportrbits)) { - istat &= ~kportrbits; - ipath_kreceive(dd->ipath_pd[0]); - } - - if (istat & ((dd->ipath_i_rcvavail_mask << dd->ipath_i_rcvavail_shift) | - (dd->ipath_i_rcvurg_mask << dd->ipath_i_rcvurg_shift))) - handle_urcv(dd, istat); - - if (istat & (INFINIPATH_I_SDMAINT | INFINIPATH_I_SDMADISABLED)) - handle_sdma_intr(dd, istat); - - if (istat & INFINIPATH_I_SPIOBUFAVAIL) { - unsigned long flags; - - spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); - dd->ipath_sendctrl &= ~INFINIPATH_S_PIOINTBUFAVAIL; - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, - dd->ipath_sendctrl); - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); - - /* always process; sdma verbs uses PIO for acks and VL15 */ - handle_layer_pioavail(dd); - } - - ret = IRQ_HANDLED; - -bail: - return ret; -} diff --git a/drivers/staging/rdma/ipath/ipath_kernel.h b/drivers/staging/rdma/ipath/ipath_kernel.h deleted file mode 100644 index 66c934a5f839..000000000000 --- a/drivers/staging/rdma/ipath/ipath_kernel.h +++ /dev/null @@ -1,1374 +0,0 @@ -#ifndef _IPATH_KERNEL_H -#define _IPATH_KERNEL_H -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * This header file is the base header file for infinipath kernel code - * ipath_user.h serves a similar purpose for user code. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ipath_common.h" -#include "ipath_debug.h" -#include "ipath_registers.h" - -/* only s/w major version of InfiniPath we can handle */ -#define IPATH_CHIP_VERS_MAJ 2U - -/* don't care about this except printing */ -#define IPATH_CHIP_VERS_MIN 0U - -/* temporary, maybe always */ -extern struct infinipath_stats ipath_stats; - -#define IPATH_CHIP_SWVERSION IPATH_CHIP_VERS_MAJ -/* - * First-cut critierion for "device is active" is - * two thousand dwords combined Tx, Rx traffic per - * 5-second interval. SMA packets are 64 dwords, - * and occur "a few per second", presumably each way. - */ -#define IPATH_TRAFFIC_ACTIVE_THRESHOLD (2000) -/* - * Struct used to indicate which errors are logged in each of the - * error-counters that are logged to EEPROM. A counter is incremented - * _once_ (saturating at 255) for each event with any bits set in - * the error or hwerror register masks below. - */ -#define IPATH_EEP_LOG_CNT (4) -struct ipath_eep_log_mask { - u64 errs_to_log; - u64 hwerrs_to_log; -}; - -struct ipath_portdata { - void **port_rcvegrbuf; - dma_addr_t *port_rcvegrbuf_phys; - /* rcvhdrq base, needs mmap before useful */ - void *port_rcvhdrq; - /* kernel virtual address where hdrqtail is updated */ - void *port_rcvhdrtail_kvaddr; - /* - * temp buffer for expected send setup, allocated at open, instead - * of each setup call - */ - void *port_tid_pg_list; - /* when waiting for rcv or pioavail */ - wait_queue_head_t port_wait; - /* - * rcvegr bufs base, physical, must fit - * in 44 bits so 32 bit programs mmap64 44 bit works) - */ - dma_addr_t port_rcvegr_phys; - /* mmap of hdrq, must fit in 44 bits */ - dma_addr_t port_rcvhdrq_phys; - dma_addr_t port_rcvhdrqtailaddr_phys; - /* - * number of opens (including slave subports) on this instance - * (ignoring forks, dup, etc. for now) - */ - int port_cnt; - /* - * how much space to leave at start of eager TID entries for - * protocol use, on each TID - */ - /* instead of calculating it */ - unsigned port_port; - /* non-zero if port is being shared. */ - u16 port_subport_cnt; - /* non-zero if port is being shared. */ - u16 port_subport_id; - /* number of pio bufs for this port (all procs, if shared) */ - u32 port_piocnt; - /* first pio buffer for this port */ - u32 port_pio_base; - /* chip offset of PIO buffers for this port */ - u32 port_piobufs; - /* how many alloc_pages() chunks in port_rcvegrbuf_pages */ - u32 port_rcvegrbuf_chunks; - /* how many egrbufs per chunk */ - u32 port_rcvegrbufs_perchunk; - /* order for port_rcvegrbuf_pages */ - size_t port_rcvegrbuf_size; - /* rcvhdrq size (for freeing) */ - size_t port_rcvhdrq_size; - /* next expected TID to check when looking for free */ - u32 port_tidcursor; - /* next expected TID to check */ - unsigned long port_flag; - /* what happened */ - unsigned long int_flag; - /* WAIT_RCV that timed out, no interrupt */ - u32 port_rcvwait_to; - /* WAIT_PIO that timed out, no interrupt */ - u32 port_piowait_to; - /* WAIT_RCV already happened, no wait */ - u32 port_rcvnowait; - /* WAIT_PIO already happened, no wait */ - u32 port_pionowait; - /* total number of rcvhdrqfull errors */ - u32 port_hdrqfull; - /* - * Used to suppress multiple instances of same - * port staying stuck at same point. - */ - u32 port_lastrcvhdrqtail; - /* saved total number of rcvhdrqfull errors for poll edge trigger */ - u32 port_hdrqfull_poll; - /* total number of polled urgent packets */ - u32 port_urgent; - /* saved total number of polled urgent packets for poll edge trigger */ - u32 port_urgent_poll; - /* pid of process using this port */ - struct pid *port_pid; - struct pid *port_subpid[INFINIPATH_MAX_SUBPORT]; - /* same size as task_struct .comm[] */ - char port_comm[TASK_COMM_LEN]; - /* pkeys set by this use of this port */ - u16 port_pkeys[4]; - /* so file ops can get at unit */ - struct ipath_devdata *port_dd; - /* A page of memory for rcvhdrhead, rcvegrhead, rcvegrtail * N */ - void *subport_uregbase; - /* An array of pages for the eager receive buffers * N */ - void *subport_rcvegrbuf; - /* An array of pages for the eager header queue entries * N */ - void *subport_rcvhdr_base; - /* The version of the library which opened this port */ - u32 userversion; - /* Bitmask of active slaves */ - u32 active_slaves; - /* Type of packets or conditions we want to poll for */ - u16 poll_type; - /* port rcvhdrq head offset */ - u32 port_head; - /* receive packet sequence counter */ - u32 port_seq_cnt; -}; - -struct sk_buff; -struct ipath_sge_state; -struct ipath_verbs_txreq; - -/* - * control information for layered drivers - */ -struct _ipath_layer { - void *l_arg; -}; - -struct ipath_skbinfo { - struct sk_buff *skb; - dma_addr_t phys; -}; - -struct ipath_sdma_txreq { - int flags; - int sg_count; - union { - struct scatterlist *sg; - void *map_addr; - }; - void (*callback)(void *, int); - void *callback_cookie; - int callback_status; - u16 start_idx; /* sdma private */ - u16 next_descq_idx; /* sdma private */ - struct list_head list; /* sdma private */ -}; - -struct ipath_sdma_desc { - __le64 qw[2]; -}; - -#define IPATH_SDMA_TXREQ_F_USELARGEBUF 0x1 -#define IPATH_SDMA_TXREQ_F_HEADTOHOST 0x2 -#define IPATH_SDMA_TXREQ_F_INTREQ 0x4 -#define IPATH_SDMA_TXREQ_F_FREEBUF 0x8 -#define IPATH_SDMA_TXREQ_F_FREEDESC 0x10 -#define IPATH_SDMA_TXREQ_F_VL15 0x20 - -#define IPATH_SDMA_TXREQ_S_OK 0 -#define IPATH_SDMA_TXREQ_S_SENDERROR 1 -#define IPATH_SDMA_TXREQ_S_ABORTED 2 -#define IPATH_SDMA_TXREQ_S_SHUTDOWN 3 - -#define IPATH_SDMA_STATUS_SCORE_BOARD_DRAIN_IN_PROG (1ull << 63) -#define IPATH_SDMA_STATUS_ABORT_IN_PROG (1ull << 62) -#define IPATH_SDMA_STATUS_INTERNAL_SDMA_ENABLE (1ull << 61) -#define IPATH_SDMA_STATUS_SCB_EMPTY (1ull << 30) - -/* max dwords in small buffer packet */ -#define IPATH_SMALLBUF_DWORDS (dd->ipath_piosize2k >> 2) - -/* - * Possible IB config parameters for ipath_f_get/set_ib_cfg() - */ -#define IPATH_IB_CFG_LIDLMC 0 /* Get/set LID (LS16b) and Mask (MS16b) */ -#define IPATH_IB_CFG_HRTBT 1 /* Get/set Heartbeat off/enable/auto */ -#define IPATH_IB_HRTBT_ON 3 /* Heartbeat enabled, sent every 100msec */ -#define IPATH_IB_HRTBT_OFF 0 /* Heartbeat off */ -#define IPATH_IB_CFG_LWID_ENB 2 /* Get/set allowed Link-width */ -#define IPATH_IB_CFG_LWID 3 /* Get currently active Link-width */ -#define IPATH_IB_CFG_SPD_ENB 4 /* Get/set allowed Link speeds */ -#define IPATH_IB_CFG_SPD 5 /* Get current Link spd */ -#define IPATH_IB_CFG_RXPOL_ENB 6 /* Get/set Auto-RX-polarity enable */ -#define IPATH_IB_CFG_LREV_ENB 7 /* Get/set Auto-Lane-reversal enable */ -#define IPATH_IB_CFG_LINKLATENCY 8 /* Get Auto-Lane-reversal enable */ - - -struct ipath_devdata { - struct list_head ipath_list; - - struct ipath_kregs const *ipath_kregs; - struct ipath_cregs const *ipath_cregs; - - /* mem-mapped pointer to base of chip regs */ - u64 __iomem *ipath_kregbase; - /* end of mem-mapped chip space; range checking */ - u64 __iomem *ipath_kregend; - /* physical address of chip for io_remap, etc. */ - unsigned long ipath_physaddr; - /* base of memory alloced for ipath_kregbase, for free */ - u64 *ipath_kregalloc; - /* ipath_cfgports pointers */ - struct ipath_portdata **ipath_pd; - /* sk_buffs used by port 0 eager receive queue */ - struct ipath_skbinfo *ipath_port0_skbinfo; - /* kvirt address of 1st 2k pio buffer */ - void __iomem *ipath_pio2kbase; - /* kvirt address of 1st 4k pio buffer */ - void __iomem *ipath_pio4kbase; - /* - * points to area where PIOavail registers will be DMA'ed. - * Has to be on a page of it's own, because the page will be - * mapped into user program space. This copy is *ONLY* ever - * written by DMA, not by the driver! Need a copy per device - * when we get to multiple devices - */ - volatile __le64 *ipath_pioavailregs_dma; - /* physical address where updates occur */ - dma_addr_t ipath_pioavailregs_phys; - struct _ipath_layer ipath_layer; - /* setup intr */ - int (*ipath_f_intrsetup)(struct ipath_devdata *); - /* fallback to alternate interrupt type if possible */ - int (*ipath_f_intr_fallback)(struct ipath_devdata *); - /* setup on-chip bus config */ - int (*ipath_f_bus)(struct ipath_devdata *, struct pci_dev *); - /* hard reset chip */ - int (*ipath_f_reset)(struct ipath_devdata *); - int (*ipath_f_get_boardname)(struct ipath_devdata *, char *, - size_t); - void (*ipath_f_init_hwerrors)(struct ipath_devdata *); - void (*ipath_f_handle_hwerrors)(struct ipath_devdata *, char *, - size_t); - void (*ipath_f_quiet_serdes)(struct ipath_devdata *); - int (*ipath_f_bringup_serdes)(struct ipath_devdata *); - int (*ipath_f_early_init)(struct ipath_devdata *); - void (*ipath_f_clear_tids)(struct ipath_devdata *, unsigned); - void (*ipath_f_put_tid)(struct ipath_devdata *, u64 __iomem*, - u32, unsigned long); - void (*ipath_f_tidtemplate)(struct ipath_devdata *); - void (*ipath_f_cleanup)(struct ipath_devdata *); - void (*ipath_f_setextled)(struct ipath_devdata *, u64, u64); - /* fill out chip-specific fields */ - int (*ipath_f_get_base_info)(struct ipath_portdata *, void *); - /* free irq */ - void (*ipath_f_free_irq)(struct ipath_devdata *); - struct ipath_message_header *(*ipath_f_get_msgheader) - (struct ipath_devdata *, __le32 *); - void (*ipath_f_config_ports)(struct ipath_devdata *, ushort); - int (*ipath_f_get_ib_cfg)(struct ipath_devdata *, int); - int (*ipath_f_set_ib_cfg)(struct ipath_devdata *, int, u32); - void (*ipath_f_config_jint)(struct ipath_devdata *, u16 , u16); - void (*ipath_f_read_counters)(struct ipath_devdata *, - struct infinipath_counters *); - void (*ipath_f_xgxs_reset)(struct ipath_devdata *); - /* per chip actions needed for IB Link up/down changes */ - int (*ipath_f_ib_updown)(struct ipath_devdata *, int, u64); - - unsigned ipath_lastegr_idx; - struct ipath_ibdev *verbs_dev; - struct timer_list verbs_timer; - /* total dwords sent (summed from counter) */ - u64 ipath_sword; - /* total dwords rcvd (summed from counter) */ - u64 ipath_rword; - /* total packets sent (summed from counter) */ - u64 ipath_spkts; - /* total packets rcvd (summed from counter) */ - u64 ipath_rpkts; - /* ipath_statusp initially points to this. */ - u64 _ipath_status; - /* GUID for this interface, in network order */ - __be64 ipath_guid; - /* - * aggregrate of error bits reported since last cleared, for - * limiting of error reporting - */ - ipath_err_t ipath_lasterror; - /* - * aggregrate of error bits reported since last cleared, for - * limiting of hwerror reporting - */ - ipath_err_t ipath_lasthwerror; - /* errors masked because they occur too fast */ - ipath_err_t ipath_maskederrs; - u64 ipath_lastlinkrecov; /* link recoveries at last ACTIVE */ - /* these 5 fields are used to establish deltas for IB Symbol - * errors and linkrecovery errors. They can be reported on - * some chips during link negotiation prior to INIT, and with - * DDR when faking DDR negotiations with non-IBTA switches. - * The chip counters are adjusted at driver unload if there is - * a non-zero delta. - */ - u64 ibdeltainprog; - u64 ibsymdelta; - u64 ibsymsnap; - u64 iblnkerrdelta; - u64 iblnkerrsnap; - - /* time in jiffies at which to re-enable maskederrs */ - unsigned long ipath_unmasktime; - /* count of egrfull errors, combined for all ports */ - u64 ipath_last_tidfull; - /* for ipath_qcheck() */ - u64 ipath_lastport0rcv_cnt; - /* template for writing TIDs */ - u64 ipath_tidtemplate; - /* value to write to free TIDs */ - u64 ipath_tidinvalid; - /* IBA6120 rcv interrupt setup */ - u64 ipath_rhdrhead_intr_off; - - /* size of memory at ipath_kregbase */ - u32 ipath_kregsize; - /* number of registers used for pioavail */ - u32 ipath_pioavregs; - /* IPATH_POLL, etc. */ - u32 ipath_flags; - /* ipath_flags driver is waiting for */ - u32 ipath_state_wanted; - /* last buffer for user use, first buf for kernel use is this - * index. */ - u32 ipath_lastport_piobuf; - /* is a stats timer active */ - u32 ipath_stats_timer_active; - /* number of interrupts for this device -- saturates... */ - u32 ipath_int_counter; - /* dwords sent read from counter */ - u32 ipath_lastsword; - /* dwords received read from counter */ - u32 ipath_lastrword; - /* sent packets read from counter */ - u32 ipath_lastspkts; - /* received packets read from counter */ - u32 ipath_lastrpkts; - /* pio bufs allocated per port */ - u32 ipath_pbufsport; - /* if remainder on bufs/port, ports < extrabuf get 1 extra */ - u32 ipath_ports_extrabuf; - u32 ipath_pioupd_thresh; /* update threshold, some chips */ - /* - * number of ports configured as max; zero is set to number chip - * supports, less gives more pio bufs/port, etc. - */ - u32 ipath_cfgports; - /* count of port 0 hdrqfull errors */ - u32 ipath_p0_hdrqfull; - /* port 0 number of receive eager buffers */ - u32 ipath_p0_rcvegrcnt; - - /* - * index of last piobuffer we used. Speeds up searching, by - * starting at this point. Doesn't matter if multiple cpu's use and - * update, last updater is only write that matters. Whenever it - * wraps, we update shadow copies. Need a copy per device when we - * get to multiple devices - */ - u32 ipath_lastpioindex; - u32 ipath_lastpioindexl; - /* max length of freezemsg */ - u32 ipath_freezelen; - /* - * consecutive times we wanted a PIO buffer but were unable to - * get one - */ - u32 ipath_consec_nopiobuf; - /* - * hint that we should update ipath_pioavailshadow before - * looking for a PIO buffer - */ - u32 ipath_upd_pio_shadow; - /* so we can rewrite it after a chip reset */ - u32 ipath_pcibar0; - /* so we can rewrite it after a chip reset */ - u32 ipath_pcibar1; - u32 ipath_x1_fix_tries; - u32 ipath_autoneg_tries; - u32 serdes_first_init_done; - - struct ipath_relock { - atomic_t ipath_relock_timer_active; - struct timer_list ipath_relock_timer; - unsigned int ipath_relock_interval; /* in jiffies */ - } ipath_relock_singleton; - - /* interrupt number */ - int ipath_irq; - /* HT/PCI Vendor ID (here for NodeInfo) */ - u16 ipath_vendorid; - /* HT/PCI Device ID (here for NodeInfo) */ - u16 ipath_deviceid; - /* offset in HT config space of slave/primary interface block */ - u8 ipath_ht_slave_off; - /* for write combining settings */ - int wc_cookie; - /* ref count for each pkey */ - atomic_t ipath_pkeyrefs[4]; - /* shadow copy of struct page *'s for exp tid pages */ - struct page **ipath_pageshadow; - /* shadow copy of dma handles for exp tid pages */ - dma_addr_t *ipath_physshadow; - u64 __iomem *ipath_egrtidbase; - /* lock to workaround chip bug 9437 and others */ - spinlock_t ipath_kernel_tid_lock; - spinlock_t ipath_user_tid_lock; - spinlock_t ipath_sendctrl_lock; - /* around ipath_pd and (user ports) port_cnt use (intr vs free) */ - spinlock_t ipath_uctxt_lock; - - /* - * IPATH_STATUS_*, - * this address is mapped readonly into user processes so they can - * get status cheaply, whenever they want. - */ - u64 *ipath_statusp; - /* freeze msg if hw error put chip in freeze */ - char *ipath_freezemsg; - /* pci access data structure */ - struct pci_dev *pcidev; - struct cdev *user_cdev; - struct cdev *diag_cdev; - struct device *user_dev; - struct device *diag_dev; - /* timer used to prevent stats overflow, error throttling, etc. */ - struct timer_list ipath_stats_timer; - /* timer to verify interrupts work, and fallback if possible */ - struct timer_list ipath_intrchk_timer; - void *ipath_dummy_hdrq; /* used after port close */ - dma_addr_t ipath_dummy_hdrq_phys; - - /* SendDMA related entries */ - spinlock_t ipath_sdma_lock; - unsigned long ipath_sdma_status; - unsigned long ipath_sdma_abort_jiffies; - unsigned long ipath_sdma_abort_intr_timeout; - unsigned long ipath_sdma_buf_jiffies; - struct ipath_sdma_desc *ipath_sdma_descq; - u64 ipath_sdma_descq_added; - u64 ipath_sdma_descq_removed; - int ipath_sdma_desc_nreserved; - u16 ipath_sdma_descq_cnt; - u16 ipath_sdma_descq_tail; - u16 ipath_sdma_descq_head; - u16 ipath_sdma_next_intr; - u16 ipath_sdma_reset_wait; - u8 ipath_sdma_generation; - struct tasklet_struct ipath_sdma_abort_task; - struct tasklet_struct ipath_sdma_notify_task; - struct list_head ipath_sdma_activelist; - struct list_head ipath_sdma_notifylist; - atomic_t ipath_sdma_vl15_count; - struct timer_list ipath_sdma_vl15_timer; - - dma_addr_t ipath_sdma_descq_phys; - volatile __le64 *ipath_sdma_head_dma; - dma_addr_t ipath_sdma_head_phys; - - unsigned long ipath_ureg_align; /* user register alignment */ - - struct delayed_work ipath_autoneg_work; - wait_queue_head_t ipath_autoneg_wait; - - /* HoL blocking / user app forward-progress state */ - unsigned ipath_hol_state; - unsigned ipath_hol_next; - struct timer_list ipath_hol_timer; - - /* - * Shadow copies of registers; size indicates read access size. - * Most of them are readonly, but some are write-only register, - * where we manipulate the bits in the shadow copy, and then write - * the shadow copy to infinipath. - * - * We deliberately make most of these 32 bits, since they have - * restricted range. For any that we read, we won't to generate 32 - * bit accesses, since Opteron will generate 2 separate 32 bit HT - * transactions for a 64 bit read, and we want to avoid unnecessary - * HT transactions. - */ - - /* This is the 64 bit group */ - - /* - * shadow of pioavail, check to be sure it's large enough at - * init time. - */ - unsigned long ipath_pioavailshadow[8]; - /* bitmap of send buffers available for the kernel to use with PIO. */ - unsigned long ipath_pioavailkernel[8]; - /* shadow of kr_gpio_out, for rmw ops */ - u64 ipath_gpio_out; - /* shadow the gpio mask register */ - u64 ipath_gpio_mask; - /* shadow the gpio output enable, etc... */ - u64 ipath_extctrl; - /* kr_revision shadow */ - u64 ipath_revision; - /* - * shadow of ibcctrl, for interrupt handling of link changes, - * etc. - */ - u64 ipath_ibcctrl; - /* - * last ibcstatus, to suppress "duplicate" status change messages, - * mostly from 2 to 3 - */ - u64 ipath_lastibcstat; - /* hwerrmask shadow */ - ipath_err_t ipath_hwerrmask; - ipath_err_t ipath_errormask; /* errormask shadow */ - /* interrupt config reg shadow */ - u64 ipath_intconfig; - /* kr_sendpiobufbase value */ - u64 ipath_piobufbase; - /* kr_ibcddrctrl shadow */ - u64 ipath_ibcddrctrl; - - /* these are the "32 bit" regs */ - - /* - * number of GUIDs in the flash for this interface; may need some - * rethinking for setting on other ifaces - */ - u32 ipath_nguid; - /* - * the following two are 32-bit bitmasks, but {test,clear,set}_bit - * all expect bit fields to be "unsigned long" - */ - /* shadow kr_rcvctrl */ - unsigned long ipath_rcvctrl; - /* shadow kr_sendctrl */ - unsigned long ipath_sendctrl; - /* to not count armlaunch after cancel */ - unsigned long ipath_lastcancel; - /* count cases where special trigger was needed (double write) */ - unsigned long ipath_spectriggerhit; - - /* value we put in kr_rcvhdrcnt */ - u32 ipath_rcvhdrcnt; - /* value we put in kr_rcvhdrsize */ - u32 ipath_rcvhdrsize; - /* value we put in kr_rcvhdrentsize */ - u32 ipath_rcvhdrentsize; - /* offset of last entry in rcvhdrq */ - u32 ipath_hdrqlast; - /* kr_portcnt value */ - u32 ipath_portcnt; - /* kr_pagealign value */ - u32 ipath_palign; - /* number of "2KB" PIO buffers */ - u32 ipath_piobcnt2k; - /* size in bytes of "2KB" PIO buffers */ - u32 ipath_piosize2k; - /* number of "4KB" PIO buffers */ - u32 ipath_piobcnt4k; - /* size in bytes of "4KB" PIO buffers */ - u32 ipath_piosize4k; - u32 ipath_pioreserved; /* reserved special-inkernel; */ - /* kr_rcvegrbase value */ - u32 ipath_rcvegrbase; - /* kr_rcvegrcnt value */ - u32 ipath_rcvegrcnt; - /* kr_rcvtidbase value */ - u32 ipath_rcvtidbase; - /* kr_rcvtidcnt value */ - u32 ipath_rcvtidcnt; - /* kr_sendregbase */ - u32 ipath_sregbase; - /* kr_userregbase */ - u32 ipath_uregbase; - /* kr_counterregbase */ - u32 ipath_cregbase; - /* shadow the control register contents */ - u32 ipath_control; - /* PCI revision register (HTC rev on FPGA) */ - u32 ipath_pcirev; - - /* chip address space used by 4k pio buffers */ - u32 ipath_4kalign; - /* The MTU programmed for this unit */ - u32 ipath_ibmtu; - /* - * The max size IB packet, included IB headers that we can send. - * Starts same as ipath_piosize, but is affected when ibmtu is - * changed, or by size of eager buffers - */ - u32 ipath_ibmaxlen; - /* - * ibmaxlen at init time, limited by chip and by receive buffer - * size. Not changed after init. - */ - u32 ipath_init_ibmaxlen; - /* size of each rcvegrbuffer */ - u32 ipath_rcvegrbufsize; - /* localbus width (1, 2,4,8,16,32) from config space */ - u32 ipath_lbus_width; - /* localbus speed (HT: 200,400,800,1000; PCIe 2500) */ - u32 ipath_lbus_speed; - /* - * number of sequential ibcstatus change for polling active/quiet - * (i.e., link not coming up). - */ - u32 ipath_ibpollcnt; - /* low and high portions of MSI capability/vector */ - u32 ipath_msi_lo; - /* saved after PCIe init for restore after reset */ - u32 ipath_msi_hi; - /* MSI data (vector) saved for restore */ - u16 ipath_msi_data; - /* MLID programmed for this instance */ - u16 ipath_mlid; - /* LID programmed for this instance */ - u16 ipath_lid; - /* list of pkeys programmed; 0 if not set */ - u16 ipath_pkeys[4]; - /* - * ASCII serial number, from flash, large enough for original - * all digit strings, and longer QLogic serial number format - */ - u8 ipath_serial[16]; - /* human readable board version */ - u8 ipath_boardversion[96]; - u8 ipath_lbus_info[32]; /* human readable localbus info */ - /* chip major rev, from ipath_revision */ - u8 ipath_majrev; - /* chip minor rev, from ipath_revision */ - u8 ipath_minrev; - /* board rev, from ipath_revision */ - u8 ipath_boardrev; - /* saved for restore after reset */ - u8 ipath_pci_cacheline; - /* LID mask control */ - u8 ipath_lmc; - /* link width supported */ - u8 ipath_link_width_supported; - /* link speed supported */ - u8 ipath_link_speed_supported; - u8 ipath_link_width_enabled; - u8 ipath_link_speed_enabled; - u8 ipath_link_width_active; - u8 ipath_link_speed_active; - /* Rx Polarity inversion (compensate for ~tx on partner) */ - u8 ipath_rx_pol_inv; - - u8 ipath_r_portenable_shift; - u8 ipath_r_intravail_shift; - u8 ipath_r_tailupd_shift; - u8 ipath_r_portcfg_shift; - - /* unit # of this chip, if present */ - int ipath_unit; - - /* local link integrity counter */ - u32 ipath_lli_counter; - /* local link integrity errors */ - u32 ipath_lli_errors; - /* - * Above counts only cases where _successive_ LocalLinkIntegrity - * errors were seen in the receive headers of kern-packets. - * Below are the three (monotonically increasing) counters - * maintained via GPIO interrupts on iba6120-rev2. - */ - u32 ipath_rxfc_unsupvl_errs; - u32 ipath_overrun_thresh_errs; - u32 ipath_lli_errs; - - /* - * Not all devices managed by a driver instance are the same - * type, so these fields must be per-device. - */ - u64 ipath_i_bitsextant; - ipath_err_t ipath_e_bitsextant; - ipath_err_t ipath_hwe_bitsextant; - - /* - * Below should be computable from number of ports, - * since they are never modified. - */ - u64 ipath_i_rcvavail_mask; - u64 ipath_i_rcvurg_mask; - u16 ipath_i_rcvurg_shift; - u16 ipath_i_rcvavail_shift; - - /* - * Register bits for selecting i2c direction and values, used for - * I2C serial flash. - */ - u8 ipath_gpio_sda_num; - u8 ipath_gpio_scl_num; - u8 ipath_i2c_chain_type; - u64 ipath_gpio_sda; - u64 ipath_gpio_scl; - - /* lock for doing RMW of shadows/regs for ExtCtrl and GPIO */ - spinlock_t ipath_gpio_lock; - - /* - * IB link and linktraining states and masks that vary per chip in - * some way. Set at init, to avoid each IB status change interrupt - */ - u8 ibcs_ls_shift; - u8 ibcs_lts_mask; - u32 ibcs_mask; - u32 ib_init; - u32 ib_arm; - u32 ib_active; - - u16 ipath_rhf_offset; /* offset of RHF within receive header entry */ - - /* - * shift/mask for linkcmd, linkinitcmd, maxpktlen in ibccontol - * reg. Changes for IBA7220 - */ - u8 ibcc_lic_mask; /* LinkInitCmd */ - u8 ibcc_lc_shift; /* LinkCmd */ - u8 ibcc_mpl_shift; /* Maxpktlen */ - - u8 delay_mult; - - /* used to override LED behavior */ - u8 ipath_led_override; /* Substituted for normal value, if non-zero */ - u16 ipath_led_override_timeoff; /* delta to next timer event */ - u8 ipath_led_override_vals[2]; /* Alternates per blink-frame */ - u8 ipath_led_override_phase; /* Just counts, LSB picks from vals[] */ - atomic_t ipath_led_override_timer_active; - /* Used to flash LEDs in override mode */ - struct timer_list ipath_led_override_timer; - - /* Support (including locks) for EEPROM logging of errors and time */ - /* control access to actual counters, timer */ - spinlock_t ipath_eep_st_lock; - /* control high-level access to EEPROM */ - struct mutex ipath_eep_lock; - /* Below inc'd by ipath_snap_cntrs(), locked by ipath_eep_st_lock */ - uint64_t ipath_traffic_wds; - /* active time is kept in seconds, but logged in hours */ - atomic_t ipath_active_time; - /* Below are nominal shadow of EEPROM, new since last EEPROM update */ - uint8_t ipath_eep_st_errs[IPATH_EEP_LOG_CNT]; - uint8_t ipath_eep_st_new_errs[IPATH_EEP_LOG_CNT]; - uint16_t ipath_eep_hrs; - /* - * masks for which bits of errs, hwerrs that cause - * each of the counters to increment. - */ - struct ipath_eep_log_mask ipath_eep_st_masks[IPATH_EEP_LOG_CNT]; - - /* interrupt mitigation reload register info */ - u16 ipath_jint_idle_ticks; /* idle clock ticks */ - u16 ipath_jint_max_packets; /* max packets across all ports */ - - /* - * lock for access to SerDes, and flags to sequence preset - * versus steady-state. 7220-only at the moment. - */ - spinlock_t ipath_sdepb_lock; - u8 ipath_presets_needed; /* Set if presets to be restored next DOWN */ -}; - -/* ipath_hol_state values (stopping/starting user proc, send flushing) */ -#define IPATH_HOL_UP 0 -#define IPATH_HOL_DOWN 1 -/* ipath_hol_next toggle values, used when hol_state IPATH_HOL_DOWN */ -#define IPATH_HOL_DOWNSTOP 0 -#define IPATH_HOL_DOWNCONT 1 - -/* bit positions for sdma_status */ -#define IPATH_SDMA_ABORTING 0 -#define IPATH_SDMA_DISARMED 1 -#define IPATH_SDMA_DISABLED 2 -#define IPATH_SDMA_LAYERBUF 3 -#define IPATH_SDMA_RUNNING 30 -#define IPATH_SDMA_SHUTDOWN 31 - -/* bit combinations that correspond to abort states */ -#define IPATH_SDMA_ABORT_NONE 0 -#define IPATH_SDMA_ABORT_ABORTING (1UL << IPATH_SDMA_ABORTING) -#define IPATH_SDMA_ABORT_DISARMED ((1UL << IPATH_SDMA_ABORTING) | \ - (1UL << IPATH_SDMA_DISARMED)) -#define IPATH_SDMA_ABORT_DISABLED ((1UL << IPATH_SDMA_ABORTING) | \ - (1UL << IPATH_SDMA_DISABLED)) -#define IPATH_SDMA_ABORT_ABORTED ((1UL << IPATH_SDMA_ABORTING) | \ - (1UL << IPATH_SDMA_DISARMED) | (1UL << IPATH_SDMA_DISABLED)) -#define IPATH_SDMA_ABORT_MASK ((1UL<private_data)->pd -#define subport_fp(fp) \ - ((struct ipath_filedata *)(fp)->private_data)->subport -#define tidcursor_fp(fp) \ - ((struct ipath_filedata *)(fp)->private_data)->tidcursor -#define user_sdma_queue_fp(fp) \ - ((struct ipath_filedata *)(fp)->private_data)->pq - -/* - * values for ipath_flags - */ - /* chip can report link latency (IB 1.2) */ -#define IPATH_HAS_LINK_LATENCY 0x1 - /* The chip is up and initted */ -#define IPATH_INITTED 0x2 - /* set if any user code has set kr_rcvhdrsize */ -#define IPATH_RCVHDRSZ_SET 0x4 - /* The chip is present and valid for accesses */ -#define IPATH_PRESENT 0x8 - /* HT link0 is only 8 bits wide, ignore upper byte crc - * errors, etc. */ -#define IPATH_8BIT_IN_HT0 0x10 - /* HT link1 is only 8 bits wide, ignore upper byte crc - * errors, etc. */ -#define IPATH_8BIT_IN_HT1 0x20 - /* The link is down */ -#define IPATH_LINKDOWN 0x40 - /* The link level is up (0x11) */ -#define IPATH_LINKINIT 0x80 - /* The link is in the armed (0x21) state */ -#define IPATH_LINKARMED 0x100 - /* The link is in the active (0x31) state */ -#define IPATH_LINKACTIVE 0x200 - /* link current state is unknown */ -#define IPATH_LINKUNK 0x400 - /* Write combining flush needed for PIO */ -#define IPATH_PIO_FLUSH_WC 0x1000 - /* DMA Receive tail pointer */ -#define IPATH_NODMA_RTAIL 0x2000 - /* no IB cable, or no device on IB cable */ -#define IPATH_NOCABLE 0x4000 - /* Supports port zero per packet receive interrupts via - * GPIO */ -#define IPATH_GPIO_INTR 0x8000 - /* uses the coded 4byte TID, not 8 byte */ -#define IPATH_4BYTE_TID 0x10000 - /* packet/word counters are 32 bit, else those 4 counters - * are 64bit */ -#define IPATH_32BITCOUNTERS 0x20000 - /* Interrupt register is 64 bits */ -#define IPATH_INTREG_64 0x40000 - /* can miss port0 rx interrupts */ -#define IPATH_DISABLED 0x80000 /* administratively disabled */ - /* Use GPIO interrupts for new counters */ -#define IPATH_GPIO_ERRINTRS 0x100000 -#define IPATH_SWAP_PIOBUFS 0x200000 - /* Supports Send DMA */ -#define IPATH_HAS_SEND_DMA 0x400000 - /* Supports Send Count (not just word count) in PBC */ -#define IPATH_HAS_PBC_CNT 0x800000 - /* Suppress heartbeat, even if turning off loopback */ -#define IPATH_NO_HRTBT 0x1000000 -#define IPATH_HAS_THRESH_UPDATE 0x4000000 -#define IPATH_HAS_MULT_IB_SPEED 0x8000000 -#define IPATH_IB_AUTONEG_INPROG 0x10000000 -#define IPATH_IB_AUTONEG_FAILED 0x20000000 - /* Linkdown-disable intentionally, Do not attempt to bring up */ -#define IPATH_IB_LINK_DISABLED 0x40000000 -#define IPATH_IB_FORCE_NOTIFY 0x80000000 /* force notify on next ib change */ - -/* Bits in GPIO for the added interrupts */ -#define IPATH_GPIO_PORT0_BIT 2 -#define IPATH_GPIO_RXUVL_BIT 3 -#define IPATH_GPIO_OVRUN_BIT 4 -#define IPATH_GPIO_LLI_BIT 5 -#define IPATH_GPIO_ERRINTR_MASK 0x38 - -/* portdata flag bit offsets */ - /* waiting for a packet to arrive */ -#define IPATH_PORT_WAITING_RCV 2 - /* master has not finished initializing */ -#define IPATH_PORT_MASTER_UNINIT 4 - /* waiting for an urgent packet to arrive */ -#define IPATH_PORT_WAITING_URG 5 - -/* free up any allocated data at closes */ -void ipath_free_data(struct ipath_portdata *dd); -u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32, u32 *); -void ipath_chg_pioavailkernel(struct ipath_devdata *dd, unsigned start, - unsigned len, int avail); -void ipath_init_iba6110_funcs(struct ipath_devdata *); -void ipath_get_eeprom_info(struct ipath_devdata *); -int ipath_update_eeprom_log(struct ipath_devdata *dd); -void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr); -u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg); -void ipath_disarm_senderrbufs(struct ipath_devdata *); -void ipath_force_pio_avail_update(struct ipath_devdata *); -void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev); - -/* - * Set LED override, only the two LSBs have "public" meaning, but - * any non-zero value substitutes them for the Link and LinkTrain - * LED states. - */ -#define IPATH_LED_PHYS 1 /* Physical (linktraining) GREEN LED */ -#define IPATH_LED_LOG 2 /* Logical (link) YELLOW LED */ -void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val); - -/* send dma routines */ -int setup_sdma(struct ipath_devdata *); -void teardown_sdma(struct ipath_devdata *); -void ipath_restart_sdma(struct ipath_devdata *); -void ipath_sdma_intr(struct ipath_devdata *); -int ipath_sdma_verbs_send(struct ipath_devdata *, struct ipath_sge_state *, - u32, struct ipath_verbs_txreq *); -/* ipath_sdma_lock should be locked before calling this. */ -int ipath_sdma_make_progress(struct ipath_devdata *dd); - -/* must be called under ipath_sdma_lock */ -static inline u16 ipath_sdma_descq_freecnt(const struct ipath_devdata *dd) -{ - return dd->ipath_sdma_descq_cnt - - (dd->ipath_sdma_descq_added - dd->ipath_sdma_descq_removed) - - 1 - dd->ipath_sdma_desc_nreserved; -} - -static inline void ipath_sdma_desc_reserve(struct ipath_devdata *dd, u16 cnt) -{ - dd->ipath_sdma_desc_nreserved += cnt; -} - -static inline void ipath_sdma_desc_unreserve(struct ipath_devdata *dd, u16 cnt) -{ - dd->ipath_sdma_desc_nreserved -= cnt; -} - -/* - * number of words used for protocol header if not set by ipath_userinit(); - */ -#define IPATH_DFLT_RCVHDRSIZE 9 - -int ipath_get_user_pages(unsigned long, size_t, struct page **); -void ipath_release_user_pages(struct page **, size_t); -void ipath_release_user_pages_on_close(struct page **, size_t); -int ipath_eeprom_read(struct ipath_devdata *, u8, void *, int); -int ipath_eeprom_write(struct ipath_devdata *, u8, const void *, int); -int ipath_tempsense_read(struct ipath_devdata *, u8 regnum); -int ipath_tempsense_write(struct ipath_devdata *, u8 regnum, u8 data); - -/* these are used for the registers that vary with port */ -void ipath_write_kreg_port(const struct ipath_devdata *, ipath_kreg, - unsigned, u64); - -/* - * We could have a single register get/put routine, that takes a group type, - * but this is somewhat clearer and cleaner. It also gives us some error - * checking. 64 bit register reads should always work, but are inefficient - * on opteron (the northbridge always generates 2 separate HT 32 bit reads), - * so we use kreg32 wherever possible. User register and counter register - * reads are always 32 bit reads, so only one form of those routines. - */ - -/* - * At the moment, none of the s-registers are writable, so no - * ipath_write_sreg(). - */ - -/** - * ipath_read_ureg32 - read 32-bit virtualized per-port register - * @dd: device - * @regno: register number - * @port: port number - * - * Return the contents of a register that is virtualized to be per port. - * Returns -1 on errors (not distinguishable from valid contents at - * runtime; we may add a separate error variable at some point). - */ -static inline u32 ipath_read_ureg32(const struct ipath_devdata *dd, - ipath_ureg regno, int port) -{ - if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) - return 0; - - return readl(regno + (u64 __iomem *) - (dd->ipath_uregbase + - (char __iomem *)dd->ipath_kregbase + - dd->ipath_ureg_align * port)); -} - -/** - * ipath_write_ureg - write 32-bit virtualized per-port register - * @dd: device - * @regno: register number - * @value: value - * @port: port - * - * Write the contents of a register that is virtualized to be per port. - */ -static inline void ipath_write_ureg(const struct ipath_devdata *dd, - ipath_ureg regno, u64 value, int port) -{ - u64 __iomem *ubase = (u64 __iomem *) - (dd->ipath_uregbase + (char __iomem *) dd->ipath_kregbase + - dd->ipath_ureg_align * port); - if (dd->ipath_kregbase) - writeq(value, &ubase[regno]); -} - -static inline u32 ipath_read_kreg32(const struct ipath_devdata *dd, - ipath_kreg regno) -{ - if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) - return -1; - return readl((u32 __iomem *) & dd->ipath_kregbase[regno]); -} - -static inline u64 ipath_read_kreg64(const struct ipath_devdata *dd, - ipath_kreg regno) -{ - if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) - return -1; - - return readq(&dd->ipath_kregbase[regno]); -} - -static inline void ipath_write_kreg(const struct ipath_devdata *dd, - ipath_kreg regno, u64 value) -{ - if (dd->ipath_kregbase) - writeq(value, &dd->ipath_kregbase[regno]); -} - -static inline u64 ipath_read_creg(const struct ipath_devdata *dd, - ipath_sreg regno) -{ - if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) - return 0; - - return readq(regno + (u64 __iomem *) - (dd->ipath_cregbase + - (char __iomem *)dd->ipath_kregbase)); -} - -static inline u32 ipath_read_creg32(const struct ipath_devdata *dd, - ipath_sreg regno) -{ - if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) - return 0; - return readl(regno + (u64 __iomem *) - (dd->ipath_cregbase + - (char __iomem *)dd->ipath_kregbase)); -} - -static inline void ipath_write_creg(const struct ipath_devdata *dd, - ipath_creg regno, u64 value) -{ - if (dd->ipath_kregbase) - writeq(value, regno + (u64 __iomem *) - (dd->ipath_cregbase + - (char __iomem *)dd->ipath_kregbase)); -} - -static inline void ipath_clear_rcvhdrtail(const struct ipath_portdata *pd) -{ - *((u64 *) pd->port_rcvhdrtail_kvaddr) = 0ULL; -} - -static inline u32 ipath_get_rcvhdrtail(const struct ipath_portdata *pd) -{ - return (u32) le64_to_cpu(*((volatile __le64 *) - pd->port_rcvhdrtail_kvaddr)); -} - -static inline u32 ipath_get_hdrqtail(const struct ipath_portdata *pd) -{ - const struct ipath_devdata *dd = pd->port_dd; - u32 hdrqtail; - - if (dd->ipath_flags & IPATH_NODMA_RTAIL) { - __le32 *rhf_addr; - u32 seq; - - rhf_addr = (__le32 *) pd->port_rcvhdrq + - pd->port_head + dd->ipath_rhf_offset; - seq = ipath_hdrget_seq(rhf_addr); - hdrqtail = pd->port_head; - if (seq == pd->port_seq_cnt) - hdrqtail++; - } else - hdrqtail = ipath_get_rcvhdrtail(pd); - - return hdrqtail; -} - -static inline u64 ipath_read_ireg(const struct ipath_devdata *dd, ipath_kreg r) -{ - return (dd->ipath_flags & IPATH_INTREG_64) ? - ipath_read_kreg64(dd, r) : ipath_read_kreg32(dd, r); -} - -/* - * from contents of IBCStatus (or a saved copy), return linkstate - * Report ACTIVE_DEFER as ACTIVE, because we treat them the same - * everywhere, anyway (and should be, for almost all purposes). - */ -static inline u32 ipath_ib_linkstate(struct ipath_devdata *dd, u64 ibcs) -{ - u32 state = (u32)(ibcs >> dd->ibcs_ls_shift) & - INFINIPATH_IBCS_LINKSTATE_MASK; - if (state == INFINIPATH_IBCS_L_STATE_ACT_DEFER) - state = INFINIPATH_IBCS_L_STATE_ACTIVE; - return state; -} - -/* from contents of IBCStatus (or a saved copy), return linktrainingstate */ -static inline u32 ipath_ib_linktrstate(struct ipath_devdata *dd, u64 ibcs) -{ - return (u32)(ibcs >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) & - dd->ibcs_lts_mask; -} - -/* - * from contents of IBCStatus (or a saved copy), return logical link state - * combination of link state and linktraining state (down, active, init, - * arm, etc. - */ -static inline u32 ipath_ib_state(struct ipath_devdata *dd, u64 ibcs) -{ - u32 ibs; - ibs = (u32)(ibcs >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) & - dd->ibcs_lts_mask; - ibs |= (u32)(ibcs & - (INFINIPATH_IBCS_LINKSTATE_MASK << dd->ibcs_ls_shift)); - return ibs; -} - -/* - * sysfs interface. - */ - -struct device_driver; - -extern const char ib_ipath_version[]; - -extern const struct attribute_group *ipath_driver_attr_groups[]; - -int ipath_device_create_group(struct device *, struct ipath_devdata *); -void ipath_device_remove_group(struct device *, struct ipath_devdata *); -int ipath_expose_reset(struct device *); - -int ipath_init_ipathfs(void); -void ipath_exit_ipathfs(void); -int ipathfs_add_device(struct ipath_devdata *); -int ipathfs_remove_device(struct ipath_devdata *); - -/* - * dma_addr wrappers - all 0's invalid for hw - */ -dma_addr_t ipath_map_page(struct pci_dev *, struct page *, unsigned long, - size_t, int); -dma_addr_t ipath_map_single(struct pci_dev *, void *, size_t, int); -const char *ipath_get_unit_name(int unit); - -/* - * Flush write combining store buffers (if present) and perform a write - * barrier. - */ -#if defined(CONFIG_X86_64) -#define ipath_flush_wc() asm volatile("sfence" ::: "memory") -#else -#define ipath_flush_wc() wmb() -#endif - -extern unsigned ipath_debug; /* debugging bit mask */ -extern unsigned ipath_linkrecovery; -extern unsigned ipath_mtu4096; -extern struct mutex ipath_mutex; - -#define IPATH_DRV_NAME "ib_ipath" -#define IPATH_MAJOR 233 -#define IPATH_USER_MINOR_BASE 0 -#define IPATH_DIAGPKT_MINOR 127 -#define IPATH_DIAG_MINOR_BASE 129 -#define IPATH_NMINORS 255 - -#define ipath_dev_err(dd,fmt,...) \ - do { \ - const struct ipath_devdata *__dd = (dd); \ - if (__dd->pcidev) \ - dev_err(&__dd->pcidev->dev, "%s: " fmt, \ - ipath_get_unit_name(__dd->ipath_unit), \ - ##__VA_ARGS__); \ - else \ - printk(KERN_ERR IPATH_DRV_NAME ": %s: " fmt, \ - ipath_get_unit_name(__dd->ipath_unit), \ - ##__VA_ARGS__); \ - } while (0) - -#if _IPATH_DEBUGGING - -# define __IPATH_DBG_WHICH(which,fmt,...) \ - do { \ - if (unlikely(ipath_debug & (which))) \ - printk(KERN_DEBUG IPATH_DRV_NAME ": %s: " fmt, \ - __func__,##__VA_ARGS__); \ - } while(0) - -# define ipath_dbg(fmt,...) \ - __IPATH_DBG_WHICH(__IPATH_DBG,fmt,##__VA_ARGS__) -# define ipath_cdbg(which,fmt,...) \ - __IPATH_DBG_WHICH(__IPATH_##which##DBG,fmt,##__VA_ARGS__) - -#else /* ! _IPATH_DEBUGGING */ - -# define ipath_dbg(fmt,...) -# define ipath_cdbg(which,fmt,...) - -#endif /* _IPATH_DEBUGGING */ - -/* - * this is used for formatting hw error messages... - */ -struct ipath_hwerror_msgs { - u64 mask; - const char *msg; -}; - -#define INFINIPATH_HWE_MSG(a, b) { .mask = INFINIPATH_HWE_##a, .msg = b } - -/* in ipath_intr.c... */ -void ipath_format_hwerrors(u64 hwerrs, - const struct ipath_hwerror_msgs *hwerrmsgs, - size_t nhwerrmsgs, - char *msg, size_t lmsg); - -#endif /* _IPATH_KERNEL_H */ diff --git a/drivers/staging/rdma/ipath/ipath_keys.c b/drivers/staging/rdma/ipath/ipath_keys.c deleted file mode 100644 index c0e933fec218..000000000000 --- a/drivers/staging/rdma/ipath/ipath_keys.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. - * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include "ipath_verbs.h" -#include "ipath_kernel.h" - -/** - * ipath_alloc_lkey - allocate an lkey - * @rkt: lkey table in which to allocate the lkey - * @mr: memory region that this lkey protects - * - * Returns 1 if successful, otherwise returns 0. - */ - -int ipath_alloc_lkey(struct ipath_lkey_table *rkt, struct ipath_mregion *mr) -{ - unsigned long flags; - u32 r; - u32 n; - int ret; - - spin_lock_irqsave(&rkt->lock, flags); - - /* Find the next available LKEY */ - r = n = rkt->next; - for (;;) { - if (rkt->table[r] == NULL) - break; - r = (r + 1) & (rkt->max - 1); - if (r == n) { - spin_unlock_irqrestore(&rkt->lock, flags); - ipath_dbg("LKEY table full\n"); - ret = 0; - goto bail; - } - } - rkt->next = (r + 1) & (rkt->max - 1); - /* - * Make sure lkey is never zero which is reserved to indicate an - * unrestricted LKEY. - */ - rkt->gen++; - mr->lkey = (r << (32 - ib_ipath_lkey_table_size)) | - ((((1 << (24 - ib_ipath_lkey_table_size)) - 1) & rkt->gen) - << 8); - if (mr->lkey == 0) { - mr->lkey |= 1 << 8; - rkt->gen++; - } - rkt->table[r] = mr; - spin_unlock_irqrestore(&rkt->lock, flags); - - ret = 1; - -bail: - return ret; -} - -/** - * ipath_free_lkey - free an lkey - * @rkt: table from which to free the lkey - * @lkey: lkey id to free - */ -void ipath_free_lkey(struct ipath_lkey_table *rkt, u32 lkey) -{ - unsigned long flags; - u32 r; - - if (lkey == 0) - return; - r = lkey >> (32 - ib_ipath_lkey_table_size); - spin_lock_irqsave(&rkt->lock, flags); - rkt->table[r] = NULL; - spin_unlock_irqrestore(&rkt->lock, flags); -} - -/** - * ipath_lkey_ok - check IB SGE for validity and initialize - * @rkt: table containing lkey to check SGE against - * @isge: outgoing internal SGE - * @sge: SGE to check - * @acc: access flags - * - * Return 1 if valid and successful, otherwise returns 0. - * - * Check the IB SGE for validity and initialize our internal version - * of it. - */ -int ipath_lkey_ok(struct ipath_qp *qp, struct ipath_sge *isge, - struct ib_sge *sge, int acc) -{ - struct ipath_lkey_table *rkt = &to_idev(qp->ibqp.device)->lk_table; - struct ipath_mregion *mr; - unsigned n, m; - size_t off; - int ret; - - /* - * We use LKEY == zero for kernel virtual addresses - * (see ipath_get_dma_mr and ipath_dma.c). - */ - if (sge->lkey == 0) { - /* always a kernel port, no locking needed */ - struct ipath_pd *pd = to_ipd(qp->ibqp.pd); - - if (pd->user) { - ret = 0; - goto bail; - } - isge->mr = NULL; - isge->vaddr = (void *) sge->addr; - isge->length = sge->length; - isge->sge_length = sge->length; - ret = 1; - goto bail; - } - mr = rkt->table[(sge->lkey >> (32 - ib_ipath_lkey_table_size))]; - if (unlikely(mr == NULL || mr->lkey != sge->lkey || - qp->ibqp.pd != mr->pd)) { - ret = 0; - goto bail; - } - - off = sge->addr - mr->user_base; - if (unlikely(sge->addr < mr->user_base || - off + sge->length > mr->length || - (mr->access_flags & acc) != acc)) { - ret = 0; - goto bail; - } - - off += mr->offset; - m = 0; - n = 0; - while (off >= mr->map[m]->segs[n].length) { - off -= mr->map[m]->segs[n].length; - n++; - if (n >= IPATH_SEGSZ) { - m++; - n = 0; - } - } - isge->mr = mr; - isge->vaddr = mr->map[m]->segs[n].vaddr + off; - isge->length = mr->map[m]->segs[n].length - off; - isge->sge_length = sge->length; - isge->m = m; - isge->n = n; - - ret = 1; - -bail: - return ret; -} - -/** - * ipath_rkey_ok - check the IB virtual address, length, and RKEY - * @dev: infiniband device - * @ss: SGE state - * @len: length of data - * @vaddr: virtual address to place data - * @rkey: rkey to check - * @acc: access flags - * - * Return 1 if successful, otherwise 0. - */ -int ipath_rkey_ok(struct ipath_qp *qp, struct ipath_sge_state *ss, - u32 len, u64 vaddr, u32 rkey, int acc) -{ - struct ipath_ibdev *dev = to_idev(qp->ibqp.device); - struct ipath_lkey_table *rkt = &dev->lk_table; - struct ipath_sge *sge = &ss->sge; - struct ipath_mregion *mr; - unsigned n, m; - size_t off; - int ret; - - /* - * We use RKEY == zero for kernel virtual addresses - * (see ipath_get_dma_mr and ipath_dma.c). - */ - if (rkey == 0) { - /* always a kernel port, no locking needed */ - struct ipath_pd *pd = to_ipd(qp->ibqp.pd); - - if (pd->user) { - ret = 0; - goto bail; - } - sge->mr = NULL; - sge->vaddr = (void *) vaddr; - sge->length = len; - sge->sge_length = len; - ss->sg_list = NULL; - ss->num_sge = 1; - ret = 1; - goto bail; - } - - mr = rkt->table[(rkey >> (32 - ib_ipath_lkey_table_size))]; - if (unlikely(mr == NULL || mr->lkey != rkey || - qp->ibqp.pd != mr->pd)) { - ret = 0; - goto bail; - } - - off = vaddr - mr->iova; - if (unlikely(vaddr < mr->iova || off + len > mr->length || - (mr->access_flags & acc) == 0)) { - ret = 0; - goto bail; - } - - off += mr->offset; - m = 0; - n = 0; - while (off >= mr->map[m]->segs[n].length) { - off -= mr->map[m]->segs[n].length; - n++; - if (n >= IPATH_SEGSZ) { - m++; - n = 0; - } - } - sge->mr = mr; - sge->vaddr = mr->map[m]->segs[n].vaddr + off; - sge->length = mr->map[m]->segs[n].length - off; - sge->sge_length = len; - sge->m = m; - sge->n = n; - ss->sg_list = NULL; - ss->num_sge = 1; - - ret = 1; - -bail: - return ret; -} diff --git a/drivers/staging/rdma/ipath/ipath_mad.c b/drivers/staging/rdma/ipath/ipath_mad.c deleted file mode 100644 index ad3a926ab3c5..000000000000 --- a/drivers/staging/rdma/ipath/ipath_mad.c +++ /dev/null @@ -1,1521 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include "ipath_kernel.h" -#include "ipath_verbs.h" -#include "ipath_common.h" - -#define IB_SMP_UNSUP_VERSION cpu_to_be16(0x0004) -#define IB_SMP_UNSUP_METHOD cpu_to_be16(0x0008) -#define IB_SMP_UNSUP_METH_ATTR cpu_to_be16(0x000C) -#define IB_SMP_INVALID_FIELD cpu_to_be16(0x001C) - -static int reply(struct ib_smp *smp) -{ - /* - * The verbs framework will handle the directed/LID route - * packet changes. - */ - smp->method = IB_MGMT_METHOD_GET_RESP; - if (smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) - smp->status |= IB_SMP_DIRECTION; - return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY; -} - -static int recv_subn_get_nodedescription(struct ib_smp *smp, - struct ib_device *ibdev) -{ - if (smp->attr_mod) - smp->status |= IB_SMP_INVALID_FIELD; - - memcpy(smp->data, ibdev->node_desc, sizeof(smp->data)); - - return reply(smp); -} - -struct nodeinfo { - u8 base_version; - u8 class_version; - u8 node_type; - u8 num_ports; - __be64 sys_guid; - __be64 node_guid; - __be64 port_guid; - __be16 partition_cap; - __be16 device_id; - __be32 revision; - u8 local_port_num; - u8 vendor_id[3]; -} __attribute__ ((packed)); - -static int recv_subn_get_nodeinfo(struct ib_smp *smp, - struct ib_device *ibdev, u8 port) -{ - struct nodeinfo *nip = (struct nodeinfo *)&smp->data; - struct ipath_devdata *dd = to_idev(ibdev)->dd; - u32 vendor, majrev, minrev; - - /* GUID 0 is illegal */ - if (smp->attr_mod || (dd->ipath_guid == 0)) - smp->status |= IB_SMP_INVALID_FIELD; - - nip->base_version = 1; - nip->class_version = 1; - nip->node_type = 1; /* channel adapter */ - /* - * XXX The num_ports value will need a layer function to get - * the value if we ever have more than one IB port on a chip. - * We will also need to get the GUID for the port. - */ - nip->num_ports = ibdev->phys_port_cnt; - /* This is already in network order */ - nip->sys_guid = to_idev(ibdev)->sys_image_guid; - nip->node_guid = dd->ipath_guid; - nip->port_guid = dd->ipath_guid; - nip->partition_cap = cpu_to_be16(ipath_get_npkeys(dd)); - nip->device_id = cpu_to_be16(dd->ipath_deviceid); - majrev = dd->ipath_majrev; - minrev = dd->ipath_minrev; - nip->revision = cpu_to_be32((majrev << 16) | minrev); - nip->local_port_num = port; - vendor = dd->ipath_vendorid; - nip->vendor_id[0] = IPATH_SRC_OUI_1; - nip->vendor_id[1] = IPATH_SRC_OUI_2; - nip->vendor_id[2] = IPATH_SRC_OUI_3; - - return reply(smp); -} - -static int recv_subn_get_guidinfo(struct ib_smp *smp, - struct ib_device *ibdev) -{ - u32 startgx = 8 * be32_to_cpu(smp->attr_mod); - __be64 *p = (__be64 *) smp->data; - - /* 32 blocks of 8 64-bit GUIDs per block */ - - memset(smp->data, 0, sizeof(smp->data)); - - /* - * We only support one GUID for now. If this changes, the - * portinfo.guid_cap field needs to be updated too. - */ - if (startgx == 0) { - __be64 g = to_idev(ibdev)->dd->ipath_guid; - if (g == 0) - /* GUID 0 is illegal */ - smp->status |= IB_SMP_INVALID_FIELD; - else - /* The first is a copy of the read-only HW GUID. */ - *p = g; - } else - smp->status |= IB_SMP_INVALID_FIELD; - - return reply(smp); -} - -static void set_link_width_enabled(struct ipath_devdata *dd, u32 w) -{ - (void) dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB, w); -} - -static void set_link_speed_enabled(struct ipath_devdata *dd, u32 s) -{ - (void) dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB, s); -} - -static int get_overrunthreshold(struct ipath_devdata *dd) -{ - return (dd->ipath_ibcctrl >> - INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) & - INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK; -} - -/** - * set_overrunthreshold - set the overrun threshold - * @dd: the infinipath device - * @n: the new threshold - * - * Note that this will only take effect when the link state changes. - */ -static int set_overrunthreshold(struct ipath_devdata *dd, unsigned n) -{ - unsigned v; - - v = (dd->ipath_ibcctrl >> INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) & - INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK; - if (v != n) { - dd->ipath_ibcctrl &= - ~(INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK << - INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT); - dd->ipath_ibcctrl |= - (u64) n << INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT; - ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, - dd->ipath_ibcctrl); - } - return 0; -} - -static int get_phyerrthreshold(struct ipath_devdata *dd) -{ - return (dd->ipath_ibcctrl >> - INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) & - INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK; -} - -/** - * set_phyerrthreshold - set the physical error threshold - * @dd: the infinipath device - * @n: the new threshold - * - * Note that this will only take effect when the link state changes. - */ -static int set_phyerrthreshold(struct ipath_devdata *dd, unsigned n) -{ - unsigned v; - - v = (dd->ipath_ibcctrl >> INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) & - INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK; - if (v != n) { - dd->ipath_ibcctrl &= - ~(INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK << - INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT); - dd->ipath_ibcctrl |= - (u64) n << INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT; - ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, - dd->ipath_ibcctrl); - } - return 0; -} - -/** - * get_linkdowndefaultstate - get the default linkdown state - * @dd: the infinipath device - * - * Returns zero if the default is POLL, 1 if the default is SLEEP. - */ -static int get_linkdowndefaultstate(struct ipath_devdata *dd) -{ - return !!(dd->ipath_ibcctrl & INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE); -} - -static int recv_subn_get_portinfo(struct ib_smp *smp, - struct ib_device *ibdev, u8 port) -{ - struct ipath_ibdev *dev; - struct ipath_devdata *dd; - struct ib_port_info *pip = (struct ib_port_info *)smp->data; - u16 lid; - u8 ibcstat; - u8 mtu; - int ret; - - if (be32_to_cpu(smp->attr_mod) > ibdev->phys_port_cnt) { - smp->status |= IB_SMP_INVALID_FIELD; - ret = reply(smp); - goto bail; - } - - dev = to_idev(ibdev); - dd = dev->dd; - - /* Clear all fields. Only set the non-zero fields. */ - memset(smp->data, 0, sizeof(smp->data)); - - /* Only return the mkey if the protection field allows it. */ - if (smp->method == IB_MGMT_METHOD_SET || dev->mkey == smp->mkey || - dev->mkeyprot == 0) - pip->mkey = dev->mkey; - pip->gid_prefix = dev->gid_prefix; - lid = dd->ipath_lid; - pip->lid = lid ? cpu_to_be16(lid) : IB_LID_PERMISSIVE; - pip->sm_lid = cpu_to_be16(dev->sm_lid); - pip->cap_mask = cpu_to_be32(dev->port_cap_flags); - /* pip->diag_code; */ - pip->mkey_lease_period = cpu_to_be16(dev->mkey_lease_period); - pip->local_port_num = port; - pip->link_width_enabled = dd->ipath_link_width_enabled; - pip->link_width_supported = dd->ipath_link_width_supported; - pip->link_width_active = dd->ipath_link_width_active; - pip->linkspeed_portstate = dd->ipath_link_speed_supported << 4; - ibcstat = dd->ipath_lastibcstat; - /* map LinkState to IB portinfo values. */ - pip->linkspeed_portstate |= ipath_ib_linkstate(dd, ibcstat) + 1; - - pip->portphysstate_linkdown = - (ipath_cvt_physportstate[ibcstat & dd->ibcs_lts_mask] << 4) | - (get_linkdowndefaultstate(dd) ? 1 : 2); - pip->mkeyprot_resv_lmc = (dev->mkeyprot << 6) | dd->ipath_lmc; - pip->linkspeedactive_enabled = (dd->ipath_link_speed_active << 4) | - dd->ipath_link_speed_enabled; - switch (dd->ipath_ibmtu) { - case 4096: - mtu = IB_MTU_4096; - break; - case 2048: - mtu = IB_MTU_2048; - break; - case 1024: - mtu = IB_MTU_1024; - break; - case 512: - mtu = IB_MTU_512; - break; - case 256: - mtu = IB_MTU_256; - break; - default: /* oops, something is wrong */ - mtu = IB_MTU_2048; - break; - } - pip->neighbormtu_mastersmsl = (mtu << 4) | dev->sm_sl; - pip->vlcap_inittype = 0x10; /* VLCap = VL0, InitType = 0 */ - pip->vl_high_limit = dev->vl_high_limit; - /* pip->vl_arb_high_cap; // only one VL */ - /* pip->vl_arb_low_cap; // only one VL */ - /* InitTypeReply = 0 */ - /* our mtu cap depends on whether 4K MTU enabled or not */ - pip->inittypereply_mtucap = ipath_mtu4096 ? IB_MTU_4096 : IB_MTU_2048; - /* HCAs ignore VLStallCount and HOQLife */ - /* pip->vlstallcnt_hoqlife; */ - pip->operationalvl_pei_peo_fpi_fpo = 0x10; /* OVLs = 1 */ - pip->mkey_violations = cpu_to_be16(dev->mkey_violations); - /* P_KeyViolations are counted by hardware. */ - pip->pkey_violations = - cpu_to_be16((ipath_get_cr_errpkey(dd) - - dev->z_pkey_violations) & 0xFFFF); - pip->qkey_violations = cpu_to_be16(dev->qkey_violations); - /* Only the hardware GUID is supported for now */ - pip->guid_cap = 1; - pip->clientrereg_resv_subnetto = dev->subnet_timeout; - /* 32.768 usec. response time (guessing) */ - pip->resv_resptimevalue = 3; - pip->localphyerrors_overrunerrors = - (get_phyerrthreshold(dd) << 4) | - get_overrunthreshold(dd); - /* pip->max_credit_hint; */ - if (dev->port_cap_flags & IB_PORT_LINK_LATENCY_SUP) { - u32 v; - - v = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LINKLATENCY); - pip->link_roundtrip_latency[0] = v >> 16; - pip->link_roundtrip_latency[1] = v >> 8; - pip->link_roundtrip_latency[2] = v; - } - - ret = reply(smp); - -bail: - return ret; -} - -/** - * get_pkeys - return the PKEY table for port 0 - * @dd: the infinipath device - * @pkeys: the pkey table is placed here - */ -static int get_pkeys(struct ipath_devdata *dd, u16 * pkeys) -{ - /* always a kernel port, no locking needed */ - struct ipath_portdata *pd = dd->ipath_pd[0]; - - memcpy(pkeys, pd->port_pkeys, sizeof(pd->port_pkeys)); - - return 0; -} - -static int recv_subn_get_pkeytable(struct ib_smp *smp, - struct ib_device *ibdev) -{ - u32 startpx = 32 * (be32_to_cpu(smp->attr_mod) & 0xffff); - u16 *p = (u16 *) smp->data; - __be16 *q = (__be16 *) smp->data; - - /* 64 blocks of 32 16-bit P_Key entries */ - - memset(smp->data, 0, sizeof(smp->data)); - if (startpx == 0) { - struct ipath_ibdev *dev = to_idev(ibdev); - unsigned i, n = ipath_get_npkeys(dev->dd); - - get_pkeys(dev->dd, p); - - for (i = 0; i < n; i++) - q[i] = cpu_to_be16(p[i]); - } else - smp->status |= IB_SMP_INVALID_FIELD; - - return reply(smp); -} - -static int recv_subn_set_guidinfo(struct ib_smp *smp, - struct ib_device *ibdev) -{ - /* The only GUID we support is the first read-only entry. */ - return recv_subn_get_guidinfo(smp, ibdev); -} - -/** - * set_linkdowndefaultstate - set the default linkdown state - * @dd: the infinipath device - * @sleep: the new state - * - * Note that this will only take effect when the link state changes. - */ -static int set_linkdowndefaultstate(struct ipath_devdata *dd, int sleep) -{ - if (sleep) - dd->ipath_ibcctrl |= INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE; - else - dd->ipath_ibcctrl &= ~INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE; - ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, - dd->ipath_ibcctrl); - return 0; -} - -/** - * recv_subn_set_portinfo - set port information - * @smp: the incoming SM packet - * @ibdev: the infiniband device - * @port: the port on the device - * - * Set Portinfo (see ch. 14.2.5.6). - */ -static int recv_subn_set_portinfo(struct ib_smp *smp, - struct ib_device *ibdev, u8 port) -{ - struct ib_port_info *pip = (struct ib_port_info *)smp->data; - struct ib_event event; - struct ipath_ibdev *dev; - struct ipath_devdata *dd; - char clientrereg = 0; - u16 lid, smlid; - u8 lwe; - u8 lse; - u8 state; - u16 lstate; - u32 mtu; - int ret, ore; - - if (be32_to_cpu(smp->attr_mod) > ibdev->phys_port_cnt) - goto err; - - dev = to_idev(ibdev); - dd = dev->dd; - event.device = ibdev; - event.element.port_num = port; - - dev->mkey = pip->mkey; - dev->gid_prefix = pip->gid_prefix; - dev->mkey_lease_period = be16_to_cpu(pip->mkey_lease_period); - - lid = be16_to_cpu(pip->lid); - if (dd->ipath_lid != lid || - dd->ipath_lmc != (pip->mkeyprot_resv_lmc & 7)) { - /* Must be a valid unicast LID address. */ - if (lid == 0 || lid >= IPATH_MULTICAST_LID_BASE) - goto err; - ipath_set_lid(dd, lid, pip->mkeyprot_resv_lmc & 7); - event.event = IB_EVENT_LID_CHANGE; - ib_dispatch_event(&event); - } - - smlid = be16_to_cpu(pip->sm_lid); - if (smlid != dev->sm_lid) { - /* Must be a valid unicast LID address. */ - if (smlid == 0 || smlid >= IPATH_MULTICAST_LID_BASE) - goto err; - dev->sm_lid = smlid; - event.event = IB_EVENT_SM_CHANGE; - ib_dispatch_event(&event); - } - - /* Allow 1x or 4x to be set (see 14.2.6.6). */ - lwe = pip->link_width_enabled; - if (lwe) { - if (lwe == 0xFF) - lwe = dd->ipath_link_width_supported; - else if (lwe >= 16 || (lwe & ~dd->ipath_link_width_supported)) - goto err; - set_link_width_enabled(dd, lwe); - } - - /* Allow 2.5 or 5.0 Gbs. */ - lse = pip->linkspeedactive_enabled & 0xF; - if (lse) { - if (lse == 15) - lse = dd->ipath_link_speed_supported; - else if (lse >= 8 || (lse & ~dd->ipath_link_speed_supported)) - goto err; - set_link_speed_enabled(dd, lse); - } - - /* Set link down default state. */ - switch (pip->portphysstate_linkdown & 0xF) { - case 0: /* NOP */ - break; - case 1: /* SLEEP */ - if (set_linkdowndefaultstate(dd, 1)) - goto err; - break; - case 2: /* POLL */ - if (set_linkdowndefaultstate(dd, 0)) - goto err; - break; - default: - goto err; - } - - dev->mkeyprot = pip->mkeyprot_resv_lmc >> 6; - dev->vl_high_limit = pip->vl_high_limit; - - switch ((pip->neighbormtu_mastersmsl >> 4) & 0xF) { - case IB_MTU_256: - mtu = 256; - break; - case IB_MTU_512: - mtu = 512; - break; - case IB_MTU_1024: - mtu = 1024; - break; - case IB_MTU_2048: - mtu = 2048; - break; - case IB_MTU_4096: - if (!ipath_mtu4096) - goto err; - mtu = 4096; - break; - default: - /* XXX We have already partially updated our state! */ - goto err; - } - ipath_set_mtu(dd, mtu); - - dev->sm_sl = pip->neighbormtu_mastersmsl & 0xF; - - /* We only support VL0 */ - if (((pip->operationalvl_pei_peo_fpi_fpo >> 4) & 0xF) > 1) - goto err; - - if (pip->mkey_violations == 0) - dev->mkey_violations = 0; - - /* - * Hardware counter can't be reset so snapshot and subtract - * later. - */ - if (pip->pkey_violations == 0) - dev->z_pkey_violations = ipath_get_cr_errpkey(dd); - - if (pip->qkey_violations == 0) - dev->qkey_violations = 0; - - ore = pip->localphyerrors_overrunerrors; - if (set_phyerrthreshold(dd, (ore >> 4) & 0xF)) - goto err; - - if (set_overrunthreshold(dd, (ore & 0xF))) - goto err; - - dev->subnet_timeout = pip->clientrereg_resv_subnetto & 0x1F; - - if (pip->clientrereg_resv_subnetto & 0x80) { - clientrereg = 1; - event.event = IB_EVENT_CLIENT_REREGISTER; - ib_dispatch_event(&event); - } - - /* - * Do the port state change now that the other link parameters - * have been set. - * Changing the port physical state only makes sense if the link - * is down or is being set to down. - */ - state = pip->linkspeed_portstate & 0xF; - lstate = (pip->portphysstate_linkdown >> 4) & 0xF; - if (lstate && !(state == IB_PORT_DOWN || state == IB_PORT_NOP)) - goto err; - - /* - * Only state changes of DOWN, ARM, and ACTIVE are valid - * and must be in the correct state to take effect (see 7.2.6). - */ - switch (state) { - case IB_PORT_NOP: - if (lstate == 0) - break; - /* FALLTHROUGH */ - case IB_PORT_DOWN: - if (lstate == 0) - lstate = IPATH_IB_LINKDOWN_ONLY; - else if (lstate == 1) - lstate = IPATH_IB_LINKDOWN_SLEEP; - else if (lstate == 2) - lstate = IPATH_IB_LINKDOWN; - else if (lstate == 3) - lstate = IPATH_IB_LINKDOWN_DISABLE; - else - goto err; - ipath_set_linkstate(dd, lstate); - if (lstate == IPATH_IB_LINKDOWN_DISABLE) { - ret = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED; - goto done; - } - ipath_wait_linkstate(dd, IPATH_LINKINIT | IPATH_LINKARMED | - IPATH_LINKACTIVE, 1000); - break; - case IB_PORT_ARMED: - ipath_set_linkstate(dd, IPATH_IB_LINKARM); - break; - case IB_PORT_ACTIVE: - ipath_set_linkstate(dd, IPATH_IB_LINKACTIVE); - break; - default: - /* XXX We have already partially updated our state! */ - goto err; - } - - ret = recv_subn_get_portinfo(smp, ibdev, port); - - if (clientrereg) - pip->clientrereg_resv_subnetto |= 0x80; - - goto done; - -err: - smp->status |= IB_SMP_INVALID_FIELD; - ret = recv_subn_get_portinfo(smp, ibdev, port); - -done: - return ret; -} - -/** - * rm_pkey - decrecment the reference count for the given PKEY - * @dd: the infinipath device - * @key: the PKEY index - * - * Return true if this was the last reference and the hardware table entry - * needs to be changed. - */ -static int rm_pkey(struct ipath_devdata *dd, u16 key) -{ - int i; - int ret; - - for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) { - if (dd->ipath_pkeys[i] != key) - continue; - if (atomic_dec_and_test(&dd->ipath_pkeyrefs[i])) { - dd->ipath_pkeys[i] = 0; - ret = 1; - goto bail; - } - break; - } - - ret = 0; - -bail: - return ret; -} - -/** - * add_pkey - add the given PKEY to the hardware table - * @dd: the infinipath device - * @key: the PKEY - * - * Return an error code if unable to add the entry, zero if no change, - * or 1 if the hardware PKEY register needs to be updated. - */ -static int add_pkey(struct ipath_devdata *dd, u16 key) -{ - int i; - u16 lkey = key & 0x7FFF; - int any = 0; - int ret; - - if (lkey == 0x7FFF) { - ret = 0; - goto bail; - } - - /* Look for an empty slot or a matching PKEY. */ - for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) { - if (!dd->ipath_pkeys[i]) { - any++; - continue; - } - /* If it matches exactly, try to increment the ref count */ - if (dd->ipath_pkeys[i] == key) { - if (atomic_inc_return(&dd->ipath_pkeyrefs[i]) > 1) { - ret = 0; - goto bail; - } - /* Lost the race. Look for an empty slot below. */ - atomic_dec(&dd->ipath_pkeyrefs[i]); - any++; - } - /* - * It makes no sense to have both the limited and unlimited - * PKEY set at the same time since the unlimited one will - * disable the limited one. - */ - if ((dd->ipath_pkeys[i] & 0x7FFF) == lkey) { - ret = -EEXIST; - goto bail; - } - } - if (!any) { - ret = -EBUSY; - goto bail; - } - for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) { - if (!dd->ipath_pkeys[i] && - atomic_inc_return(&dd->ipath_pkeyrefs[i]) == 1) { - /* for ipathstats, etc. */ - ipath_stats.sps_pkeys[i] = lkey; - dd->ipath_pkeys[i] = key; - ret = 1; - goto bail; - } - } - ret = -EBUSY; - -bail: - return ret; -} - -/** - * set_pkeys - set the PKEY table for port 0 - * @dd: the infinipath device - * @pkeys: the PKEY table - */ -static int set_pkeys(struct ipath_devdata *dd, u16 *pkeys, u8 port) -{ - struct ipath_portdata *pd; - int i; - int changed = 0; - - /* always a kernel port, no locking needed */ - pd = dd->ipath_pd[0]; - - for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) { - u16 key = pkeys[i]; - u16 okey = pd->port_pkeys[i]; - - if (key == okey) - continue; - /* - * The value of this PKEY table entry is changing. - * Remove the old entry in the hardware's array of PKEYs. - */ - if (okey & 0x7FFF) - changed |= rm_pkey(dd, okey); - if (key & 0x7FFF) { - int ret = add_pkey(dd, key); - - if (ret < 0) - key = 0; - else - changed |= ret; - } - pd->port_pkeys[i] = key; - } - if (changed) { - u64 pkey; - struct ib_event event; - - pkey = (u64) dd->ipath_pkeys[0] | - ((u64) dd->ipath_pkeys[1] << 16) | - ((u64) dd->ipath_pkeys[2] << 32) | - ((u64) dd->ipath_pkeys[3] << 48); - ipath_cdbg(VERBOSE, "p0 new pkey reg %llx\n", - (unsigned long long) pkey); - ipath_write_kreg(dd, dd->ipath_kregs->kr_partitionkey, - pkey); - - event.event = IB_EVENT_PKEY_CHANGE; - event.device = &dd->verbs_dev->ibdev; - event.element.port_num = port; - ib_dispatch_event(&event); - } - return 0; -} - -static int recv_subn_set_pkeytable(struct ib_smp *smp, - struct ib_device *ibdev, u8 port) -{ - u32 startpx = 32 * (be32_to_cpu(smp->attr_mod) & 0xffff); - __be16 *p = (__be16 *) smp->data; - u16 *q = (u16 *) smp->data; - struct ipath_ibdev *dev = to_idev(ibdev); - unsigned i, n = ipath_get_npkeys(dev->dd); - - for (i = 0; i < n; i++) - q[i] = be16_to_cpu(p[i]); - - if (startpx != 0 || set_pkeys(dev->dd, q, port) != 0) - smp->status |= IB_SMP_INVALID_FIELD; - - return recv_subn_get_pkeytable(smp, ibdev); -} - -static int recv_pma_get_classportinfo(struct ib_pma_mad *pmp) -{ - struct ib_class_port_info *p = - (struct ib_class_port_info *)pmp->data; - - memset(pmp->data, 0, sizeof(pmp->data)); - - if (pmp->mad_hdr.attr_mod != 0) - pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD; - - /* Indicate AllPortSelect is valid (only one port anyway) */ - p->capability_mask = cpu_to_be16(1 << 8); - p->base_version = 1; - p->class_version = 1; - /* - * Expected response time is 4.096 usec. * 2^18 == 1.073741824 - * sec. - */ - p->resp_time_value = 18; - - return reply((struct ib_smp *) pmp); -} - -/* - * The PortSamplesControl.CounterMasks field is an array of 3 bit fields - * which specify the N'th counter's capabilities. See ch. 16.1.3.2. - * We support 5 counters which only count the mandatory quantities. - */ -#define COUNTER_MASK(q, n) (q << ((9 - n) * 3)) -#define COUNTER_MASK0_9 cpu_to_be32(COUNTER_MASK(1, 0) | \ - COUNTER_MASK(1, 1) | \ - COUNTER_MASK(1, 2) | \ - COUNTER_MASK(1, 3) | \ - COUNTER_MASK(1, 4)) - -static int recv_pma_get_portsamplescontrol(struct ib_pma_mad *pmp, - struct ib_device *ibdev, u8 port) -{ - struct ib_pma_portsamplescontrol *p = - (struct ib_pma_portsamplescontrol *)pmp->data; - struct ipath_ibdev *dev = to_idev(ibdev); - struct ipath_cregs const *crp = dev->dd->ipath_cregs; - unsigned long flags; - u8 port_select = p->port_select; - - memset(pmp->data, 0, sizeof(pmp->data)); - - p->port_select = port_select; - if (pmp->mad_hdr.attr_mod != 0 || - (port_select != port && port_select != 0xFF)) - pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD; - /* - * Ticks are 10x the link transfer period which for 2.5Gbs is 4 - * nsec. 0 == 4 nsec., 1 == 8 nsec., ..., 255 == 1020 nsec. Sample - * intervals are counted in ticks. Since we use Linux timers, that - * count in jiffies, we can't sample for less than 1000 ticks if HZ - * == 1000 (4000 ticks if HZ is 250). link_speed_active returns 2 for - * DDR, 1 for SDR, set the tick to 1 for DDR, 0 for SDR on chips that - * have hardware support for delaying packets. - */ - if (crp->cr_psstat) - p->tick = dev->dd->ipath_link_speed_active - 1; - else - p->tick = 250; /* 1 usec. */ - p->counter_width = 4; /* 32 bit counters */ - p->counter_mask0_9 = COUNTER_MASK0_9; - spin_lock_irqsave(&dev->pending_lock, flags); - if (crp->cr_psstat) - p->sample_status = ipath_read_creg32(dev->dd, crp->cr_psstat); - else - p->sample_status = dev->pma_sample_status; - p->sample_start = cpu_to_be32(dev->pma_sample_start); - p->sample_interval = cpu_to_be32(dev->pma_sample_interval); - p->tag = cpu_to_be16(dev->pma_tag); - p->counter_select[0] = dev->pma_counter_select[0]; - p->counter_select[1] = dev->pma_counter_select[1]; - p->counter_select[2] = dev->pma_counter_select[2]; - p->counter_select[3] = dev->pma_counter_select[3]; - p->counter_select[4] = dev->pma_counter_select[4]; - spin_unlock_irqrestore(&dev->pending_lock, flags); - - return reply((struct ib_smp *) pmp); -} - -static int recv_pma_set_portsamplescontrol(struct ib_pma_mad *pmp, - struct ib_device *ibdev, u8 port) -{ - struct ib_pma_portsamplescontrol *p = - (struct ib_pma_portsamplescontrol *)pmp->data; - struct ipath_ibdev *dev = to_idev(ibdev); - struct ipath_cregs const *crp = dev->dd->ipath_cregs; - unsigned long flags; - u8 status; - int ret; - - if (pmp->mad_hdr.attr_mod != 0 || - (p->port_select != port && p->port_select != 0xFF)) { - pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD; - ret = reply((struct ib_smp *) pmp); - goto bail; - } - - spin_lock_irqsave(&dev->pending_lock, flags); - if (crp->cr_psstat) - status = ipath_read_creg32(dev->dd, crp->cr_psstat); - else - status = dev->pma_sample_status; - if (status == IB_PMA_SAMPLE_STATUS_DONE) { - dev->pma_sample_start = be32_to_cpu(p->sample_start); - dev->pma_sample_interval = be32_to_cpu(p->sample_interval); - dev->pma_tag = be16_to_cpu(p->tag); - dev->pma_counter_select[0] = p->counter_select[0]; - dev->pma_counter_select[1] = p->counter_select[1]; - dev->pma_counter_select[2] = p->counter_select[2]; - dev->pma_counter_select[3] = p->counter_select[3]; - dev->pma_counter_select[4] = p->counter_select[4]; - if (crp->cr_psstat) { - ipath_write_creg(dev->dd, crp->cr_psinterval, - dev->pma_sample_interval); - ipath_write_creg(dev->dd, crp->cr_psstart, - dev->pma_sample_start); - } else - dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_STARTED; - } - spin_unlock_irqrestore(&dev->pending_lock, flags); - - ret = recv_pma_get_portsamplescontrol(pmp, ibdev, port); - -bail: - return ret; -} - -static u64 get_counter(struct ipath_ibdev *dev, - struct ipath_cregs const *crp, - __be16 sel) -{ - u64 ret; - - switch (sel) { - case IB_PMA_PORT_XMIT_DATA: - ret = (crp->cr_psxmitdatacount) ? - ipath_read_creg32(dev->dd, crp->cr_psxmitdatacount) : - dev->ipath_sword; - break; - case IB_PMA_PORT_RCV_DATA: - ret = (crp->cr_psrcvdatacount) ? - ipath_read_creg32(dev->dd, crp->cr_psrcvdatacount) : - dev->ipath_rword; - break; - case IB_PMA_PORT_XMIT_PKTS: - ret = (crp->cr_psxmitpktscount) ? - ipath_read_creg32(dev->dd, crp->cr_psxmitpktscount) : - dev->ipath_spkts; - break; - case IB_PMA_PORT_RCV_PKTS: - ret = (crp->cr_psrcvpktscount) ? - ipath_read_creg32(dev->dd, crp->cr_psrcvpktscount) : - dev->ipath_rpkts; - break; - case IB_PMA_PORT_XMIT_WAIT: - ret = (crp->cr_psxmitwaitcount) ? - ipath_read_creg32(dev->dd, crp->cr_psxmitwaitcount) : - dev->ipath_xmit_wait; - break; - default: - ret = 0; - } - - return ret; -} - -static int recv_pma_get_portsamplesresult(struct ib_pma_mad *pmp, - struct ib_device *ibdev) -{ - struct ib_pma_portsamplesresult *p = - (struct ib_pma_portsamplesresult *)pmp->data; - struct ipath_ibdev *dev = to_idev(ibdev); - struct ipath_cregs const *crp = dev->dd->ipath_cregs; - u8 status; - int i; - - memset(pmp->data, 0, sizeof(pmp->data)); - p->tag = cpu_to_be16(dev->pma_tag); - if (crp->cr_psstat) - status = ipath_read_creg32(dev->dd, crp->cr_psstat); - else - status = dev->pma_sample_status; - p->sample_status = cpu_to_be16(status); - for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++) - p->counter[i] = (status != IB_PMA_SAMPLE_STATUS_DONE) ? 0 : - cpu_to_be32( - get_counter(dev, crp, dev->pma_counter_select[i])); - - return reply((struct ib_smp *) pmp); -} - -static int recv_pma_get_portsamplesresult_ext(struct ib_pma_mad *pmp, - struct ib_device *ibdev) -{ - struct ib_pma_portsamplesresult_ext *p = - (struct ib_pma_portsamplesresult_ext *)pmp->data; - struct ipath_ibdev *dev = to_idev(ibdev); - struct ipath_cregs const *crp = dev->dd->ipath_cregs; - u8 status; - int i; - - memset(pmp->data, 0, sizeof(pmp->data)); - p->tag = cpu_to_be16(dev->pma_tag); - if (crp->cr_psstat) - status = ipath_read_creg32(dev->dd, crp->cr_psstat); - else - status = dev->pma_sample_status; - p->sample_status = cpu_to_be16(status); - /* 64 bits */ - p->extended_width = cpu_to_be32(0x80000000); - for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++) - p->counter[i] = (status != IB_PMA_SAMPLE_STATUS_DONE) ? 0 : - cpu_to_be64( - get_counter(dev, crp, dev->pma_counter_select[i])); - - return reply((struct ib_smp *) pmp); -} - -static int recv_pma_get_portcounters(struct ib_pma_mad *pmp, - struct ib_device *ibdev, u8 port) -{ - struct ib_pma_portcounters *p = (struct ib_pma_portcounters *) - pmp->data; - struct ipath_ibdev *dev = to_idev(ibdev); - struct ipath_verbs_counters cntrs; - u8 port_select = p->port_select; - - ipath_get_counters(dev->dd, &cntrs); - - /* Adjust counters for any resets done. */ - cntrs.symbol_error_counter -= dev->z_symbol_error_counter; - cntrs.link_error_recovery_counter -= - dev->z_link_error_recovery_counter; - cntrs.link_downed_counter -= dev->z_link_downed_counter; - cntrs.port_rcv_errors += dev->rcv_errors; - cntrs.port_rcv_errors -= dev->z_port_rcv_errors; - cntrs.port_rcv_remphys_errors -= dev->z_port_rcv_remphys_errors; - cntrs.port_xmit_discards -= dev->z_port_xmit_discards; - cntrs.port_xmit_data -= dev->z_port_xmit_data; - cntrs.port_rcv_data -= dev->z_port_rcv_data; - cntrs.port_xmit_packets -= dev->z_port_xmit_packets; - cntrs.port_rcv_packets -= dev->z_port_rcv_packets; - cntrs.local_link_integrity_errors -= - dev->z_local_link_integrity_errors; - cntrs.excessive_buffer_overrun_errors -= - dev->z_excessive_buffer_overrun_errors; - cntrs.vl15_dropped -= dev->z_vl15_dropped; - cntrs.vl15_dropped += dev->n_vl15_dropped; - - memset(pmp->data, 0, sizeof(pmp->data)); - - p->port_select = port_select; - if (pmp->mad_hdr.attr_mod != 0 || - (port_select != port && port_select != 0xFF)) - pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD; - - if (cntrs.symbol_error_counter > 0xFFFFUL) - p->symbol_error_counter = cpu_to_be16(0xFFFF); - else - p->symbol_error_counter = - cpu_to_be16((u16)cntrs.symbol_error_counter); - if (cntrs.link_error_recovery_counter > 0xFFUL) - p->link_error_recovery_counter = 0xFF; - else - p->link_error_recovery_counter = - (u8)cntrs.link_error_recovery_counter; - if (cntrs.link_downed_counter > 0xFFUL) - p->link_downed_counter = 0xFF; - else - p->link_downed_counter = (u8)cntrs.link_downed_counter; - if (cntrs.port_rcv_errors > 0xFFFFUL) - p->port_rcv_errors = cpu_to_be16(0xFFFF); - else - p->port_rcv_errors = - cpu_to_be16((u16) cntrs.port_rcv_errors); - if (cntrs.port_rcv_remphys_errors > 0xFFFFUL) - p->port_rcv_remphys_errors = cpu_to_be16(0xFFFF); - else - p->port_rcv_remphys_errors = - cpu_to_be16((u16)cntrs.port_rcv_remphys_errors); - if (cntrs.port_xmit_discards > 0xFFFFUL) - p->port_xmit_discards = cpu_to_be16(0xFFFF); - else - p->port_xmit_discards = - cpu_to_be16((u16)cntrs.port_xmit_discards); - if (cntrs.local_link_integrity_errors > 0xFUL) - cntrs.local_link_integrity_errors = 0xFUL; - if (cntrs.excessive_buffer_overrun_errors > 0xFUL) - cntrs.excessive_buffer_overrun_errors = 0xFUL; - p->link_overrun_errors = (cntrs.local_link_integrity_errors << 4) | - cntrs.excessive_buffer_overrun_errors; - if (cntrs.vl15_dropped > 0xFFFFUL) - p->vl15_dropped = cpu_to_be16(0xFFFF); - else - p->vl15_dropped = cpu_to_be16((u16)cntrs.vl15_dropped); - if (cntrs.port_xmit_data > 0xFFFFFFFFUL) - p->port_xmit_data = cpu_to_be32(0xFFFFFFFF); - else - p->port_xmit_data = cpu_to_be32((u32)cntrs.port_xmit_data); - if (cntrs.port_rcv_data > 0xFFFFFFFFUL) - p->port_rcv_data = cpu_to_be32(0xFFFFFFFF); - else - p->port_rcv_data = cpu_to_be32((u32)cntrs.port_rcv_data); - if (cntrs.port_xmit_packets > 0xFFFFFFFFUL) - p->port_xmit_packets = cpu_to_be32(0xFFFFFFFF); - else - p->port_xmit_packets = - cpu_to_be32((u32)cntrs.port_xmit_packets); - if (cntrs.port_rcv_packets > 0xFFFFFFFFUL) - p->port_rcv_packets = cpu_to_be32(0xFFFFFFFF); - else - p->port_rcv_packets = - cpu_to_be32((u32) cntrs.port_rcv_packets); - - return reply((struct ib_smp *) pmp); -} - -static int recv_pma_get_portcounters_ext(struct ib_pma_mad *pmp, - struct ib_device *ibdev, u8 port) -{ - struct ib_pma_portcounters_ext *p = - (struct ib_pma_portcounters_ext *)pmp->data; - struct ipath_ibdev *dev = to_idev(ibdev); - u64 swords, rwords, spkts, rpkts, xwait; - u8 port_select = p->port_select; - - ipath_snapshot_counters(dev->dd, &swords, &rwords, &spkts, - &rpkts, &xwait); - - /* Adjust counters for any resets done. */ - swords -= dev->z_port_xmit_data; - rwords -= dev->z_port_rcv_data; - spkts -= dev->z_port_xmit_packets; - rpkts -= dev->z_port_rcv_packets; - - memset(pmp->data, 0, sizeof(pmp->data)); - - p->port_select = port_select; - if (pmp->mad_hdr.attr_mod != 0 || - (port_select != port && port_select != 0xFF)) - pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD; - - p->port_xmit_data = cpu_to_be64(swords); - p->port_rcv_data = cpu_to_be64(rwords); - p->port_xmit_packets = cpu_to_be64(spkts); - p->port_rcv_packets = cpu_to_be64(rpkts); - p->port_unicast_xmit_packets = cpu_to_be64(dev->n_unicast_xmit); - p->port_unicast_rcv_packets = cpu_to_be64(dev->n_unicast_rcv); - p->port_multicast_xmit_packets = cpu_to_be64(dev->n_multicast_xmit); - p->port_multicast_rcv_packets = cpu_to_be64(dev->n_multicast_rcv); - - return reply((struct ib_smp *) pmp); -} - -static int recv_pma_set_portcounters(struct ib_pma_mad *pmp, - struct ib_device *ibdev, u8 port) -{ - struct ib_pma_portcounters *p = (struct ib_pma_portcounters *) - pmp->data; - struct ipath_ibdev *dev = to_idev(ibdev); - struct ipath_verbs_counters cntrs; - - /* - * Since the HW doesn't support clearing counters, we save the - * current count and subtract it from future responses. - */ - ipath_get_counters(dev->dd, &cntrs); - - if (p->counter_select & IB_PMA_SEL_SYMBOL_ERROR) - dev->z_symbol_error_counter = cntrs.symbol_error_counter; - - if (p->counter_select & IB_PMA_SEL_LINK_ERROR_RECOVERY) - dev->z_link_error_recovery_counter = - cntrs.link_error_recovery_counter; - - if (p->counter_select & IB_PMA_SEL_LINK_DOWNED) - dev->z_link_downed_counter = cntrs.link_downed_counter; - - if (p->counter_select & IB_PMA_SEL_PORT_RCV_ERRORS) - dev->z_port_rcv_errors = - cntrs.port_rcv_errors + dev->rcv_errors; - - if (p->counter_select & IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS) - dev->z_port_rcv_remphys_errors = - cntrs.port_rcv_remphys_errors; - - if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DISCARDS) - dev->z_port_xmit_discards = cntrs.port_xmit_discards; - - if (p->counter_select & IB_PMA_SEL_LOCAL_LINK_INTEGRITY_ERRORS) - dev->z_local_link_integrity_errors = - cntrs.local_link_integrity_errors; - - if (p->counter_select & IB_PMA_SEL_EXCESSIVE_BUFFER_OVERRUNS) - dev->z_excessive_buffer_overrun_errors = - cntrs.excessive_buffer_overrun_errors; - - if (p->counter_select & IB_PMA_SEL_PORT_VL15_DROPPED) { - dev->n_vl15_dropped = 0; - dev->z_vl15_dropped = cntrs.vl15_dropped; - } - - if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DATA) - dev->z_port_xmit_data = cntrs.port_xmit_data; - - if (p->counter_select & IB_PMA_SEL_PORT_RCV_DATA) - dev->z_port_rcv_data = cntrs.port_rcv_data; - - if (p->counter_select & IB_PMA_SEL_PORT_XMIT_PACKETS) - dev->z_port_xmit_packets = cntrs.port_xmit_packets; - - if (p->counter_select & IB_PMA_SEL_PORT_RCV_PACKETS) - dev->z_port_rcv_packets = cntrs.port_rcv_packets; - - return recv_pma_get_portcounters(pmp, ibdev, port); -} - -static int recv_pma_set_portcounters_ext(struct ib_pma_mad *pmp, - struct ib_device *ibdev, u8 port) -{ - struct ib_pma_portcounters *p = (struct ib_pma_portcounters *) - pmp->data; - struct ipath_ibdev *dev = to_idev(ibdev); - u64 swords, rwords, spkts, rpkts, xwait; - - ipath_snapshot_counters(dev->dd, &swords, &rwords, &spkts, - &rpkts, &xwait); - - if (p->counter_select & IB_PMA_SELX_PORT_XMIT_DATA) - dev->z_port_xmit_data = swords; - - if (p->counter_select & IB_PMA_SELX_PORT_RCV_DATA) - dev->z_port_rcv_data = rwords; - - if (p->counter_select & IB_PMA_SELX_PORT_XMIT_PACKETS) - dev->z_port_xmit_packets = spkts; - - if (p->counter_select & IB_PMA_SELX_PORT_RCV_PACKETS) - dev->z_port_rcv_packets = rpkts; - - if (p->counter_select & IB_PMA_SELX_PORT_UNI_XMIT_PACKETS) - dev->n_unicast_xmit = 0; - - if (p->counter_select & IB_PMA_SELX_PORT_UNI_RCV_PACKETS) - dev->n_unicast_rcv = 0; - - if (p->counter_select & IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS) - dev->n_multicast_xmit = 0; - - if (p->counter_select & IB_PMA_SELX_PORT_MULTI_RCV_PACKETS) - dev->n_multicast_rcv = 0; - - return recv_pma_get_portcounters_ext(pmp, ibdev, port); -} - -static int process_subn(struct ib_device *ibdev, int mad_flags, - u8 port_num, const struct ib_mad *in_mad, - struct ib_mad *out_mad) -{ - struct ib_smp *smp = (struct ib_smp *)out_mad; - struct ipath_ibdev *dev = to_idev(ibdev); - int ret; - - *out_mad = *in_mad; - if (smp->class_version != 1) { - smp->status |= IB_SMP_UNSUP_VERSION; - ret = reply(smp); - goto bail; - } - - /* Is the mkey in the process of expiring? */ - if (dev->mkey_lease_timeout && - time_after_eq(jiffies, dev->mkey_lease_timeout)) { - /* Clear timeout and mkey protection field. */ - dev->mkey_lease_timeout = 0; - dev->mkeyprot = 0; - } - - /* - * M_Key checking depends on - * Portinfo:M_Key_protect_bits - */ - if ((mad_flags & IB_MAD_IGNORE_MKEY) == 0 && dev->mkey != 0 && - dev->mkey != smp->mkey && - (smp->method == IB_MGMT_METHOD_SET || - (smp->method == IB_MGMT_METHOD_GET && - dev->mkeyprot >= 2))) { - if (dev->mkey_violations != 0xFFFF) - ++dev->mkey_violations; - if (dev->mkey_lease_timeout || - dev->mkey_lease_period == 0) { - ret = IB_MAD_RESULT_SUCCESS | - IB_MAD_RESULT_CONSUMED; - goto bail; - } - dev->mkey_lease_timeout = jiffies + - dev->mkey_lease_period * HZ; - /* Future: Generate a trap notice. */ - ret = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED; - goto bail; - } else if (dev->mkey_lease_timeout) - dev->mkey_lease_timeout = 0; - - switch (smp->method) { - case IB_MGMT_METHOD_GET: - switch (smp->attr_id) { - case IB_SMP_ATTR_NODE_DESC: - ret = recv_subn_get_nodedescription(smp, ibdev); - goto bail; - case IB_SMP_ATTR_NODE_INFO: - ret = recv_subn_get_nodeinfo(smp, ibdev, port_num); - goto bail; - case IB_SMP_ATTR_GUID_INFO: - ret = recv_subn_get_guidinfo(smp, ibdev); - goto bail; - case IB_SMP_ATTR_PORT_INFO: - ret = recv_subn_get_portinfo(smp, ibdev, port_num); - goto bail; - case IB_SMP_ATTR_PKEY_TABLE: - ret = recv_subn_get_pkeytable(smp, ibdev); - goto bail; - case IB_SMP_ATTR_SM_INFO: - if (dev->port_cap_flags & IB_PORT_SM_DISABLED) { - ret = IB_MAD_RESULT_SUCCESS | - IB_MAD_RESULT_CONSUMED; - goto bail; - } - if (dev->port_cap_flags & IB_PORT_SM) { - ret = IB_MAD_RESULT_SUCCESS; - goto bail; - } - /* FALLTHROUGH */ - default: - smp->status |= IB_SMP_UNSUP_METH_ATTR; - ret = reply(smp); - goto bail; - } - - case IB_MGMT_METHOD_SET: - switch (smp->attr_id) { - case IB_SMP_ATTR_GUID_INFO: - ret = recv_subn_set_guidinfo(smp, ibdev); - goto bail; - case IB_SMP_ATTR_PORT_INFO: - ret = recv_subn_set_portinfo(smp, ibdev, port_num); - goto bail; - case IB_SMP_ATTR_PKEY_TABLE: - ret = recv_subn_set_pkeytable(smp, ibdev, port_num); - goto bail; - case IB_SMP_ATTR_SM_INFO: - if (dev->port_cap_flags & IB_PORT_SM_DISABLED) { - ret = IB_MAD_RESULT_SUCCESS | - IB_MAD_RESULT_CONSUMED; - goto bail; - } - if (dev->port_cap_flags & IB_PORT_SM) { - ret = IB_MAD_RESULT_SUCCESS; - goto bail; - } - /* FALLTHROUGH */ - default: - smp->status |= IB_SMP_UNSUP_METH_ATTR; - ret = reply(smp); - goto bail; - } - - case IB_MGMT_METHOD_TRAP: - case IB_MGMT_METHOD_REPORT: - case IB_MGMT_METHOD_REPORT_RESP: - case IB_MGMT_METHOD_TRAP_REPRESS: - case IB_MGMT_METHOD_GET_RESP: - /* - * The ib_mad module will call us to process responses - * before checking for other consumers. - * Just tell the caller to process it normally. - */ - ret = IB_MAD_RESULT_SUCCESS; - goto bail; - default: - smp->status |= IB_SMP_UNSUP_METHOD; - ret = reply(smp); - } - -bail: - return ret; -} - -static int process_perf(struct ib_device *ibdev, u8 port_num, - const struct ib_mad *in_mad, - struct ib_mad *out_mad) -{ - struct ib_pma_mad *pmp = (struct ib_pma_mad *)out_mad; - int ret; - - *out_mad = *in_mad; - if (pmp->mad_hdr.class_version != 1) { - pmp->mad_hdr.status |= IB_SMP_UNSUP_VERSION; - ret = reply((struct ib_smp *) pmp); - goto bail; - } - - switch (pmp->mad_hdr.method) { - case IB_MGMT_METHOD_GET: - switch (pmp->mad_hdr.attr_id) { - case IB_PMA_CLASS_PORT_INFO: - ret = recv_pma_get_classportinfo(pmp); - goto bail; - case IB_PMA_PORT_SAMPLES_CONTROL: - ret = recv_pma_get_portsamplescontrol(pmp, ibdev, - port_num); - goto bail; - case IB_PMA_PORT_SAMPLES_RESULT: - ret = recv_pma_get_portsamplesresult(pmp, ibdev); - goto bail; - case IB_PMA_PORT_SAMPLES_RESULT_EXT: - ret = recv_pma_get_portsamplesresult_ext(pmp, - ibdev); - goto bail; - case IB_PMA_PORT_COUNTERS: - ret = recv_pma_get_portcounters(pmp, ibdev, - port_num); - goto bail; - case IB_PMA_PORT_COUNTERS_EXT: - ret = recv_pma_get_portcounters_ext(pmp, ibdev, - port_num); - goto bail; - default: - pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR; - ret = reply((struct ib_smp *) pmp); - goto bail; - } - - case IB_MGMT_METHOD_SET: - switch (pmp->mad_hdr.attr_id) { - case IB_PMA_PORT_SAMPLES_CONTROL: - ret = recv_pma_set_portsamplescontrol(pmp, ibdev, - port_num); - goto bail; - case IB_PMA_PORT_COUNTERS: - ret = recv_pma_set_portcounters(pmp, ibdev, - port_num); - goto bail; - case IB_PMA_PORT_COUNTERS_EXT: - ret = recv_pma_set_portcounters_ext(pmp, ibdev, - port_num); - goto bail; - default: - pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR; - ret = reply((struct ib_smp *) pmp); - goto bail; - } - - case IB_MGMT_METHOD_GET_RESP: - /* - * The ib_mad module will call us to process responses - * before checking for other consumers. - * Just tell the caller to process it normally. - */ - ret = IB_MAD_RESULT_SUCCESS; - goto bail; - default: - pmp->mad_hdr.status |= IB_SMP_UNSUP_METHOD; - ret = reply((struct ib_smp *) pmp); - } - -bail: - return ret; -} - -/** - * ipath_process_mad - process an incoming MAD packet - * @ibdev: the infiniband device this packet came in on - * @mad_flags: MAD flags - * @port_num: the port number this packet came in on - * @in_wc: the work completion entry for this packet - * @in_grh: the global route header for this packet - * @in_mad: the incoming MAD - * @out_mad: any outgoing MAD reply - * - * Returns IB_MAD_RESULT_SUCCESS if this is a MAD that we are not - * interested in processing. - * - * Note that the verbs framework has already done the MAD sanity checks, - * and hop count/pointer updating for IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE - * MADs. - * - * This is called by the ib_mad module. - */ -int ipath_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, - const struct ib_wc *in_wc, const struct ib_grh *in_grh, - const struct ib_mad_hdr *in, size_t in_mad_size, - struct ib_mad_hdr *out, size_t *out_mad_size, - u16 *out_mad_pkey_index) -{ - int ret; - const struct ib_mad *in_mad = (const struct ib_mad *)in; - struct ib_mad *out_mad = (struct ib_mad *)out; - - if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || - *out_mad_size != sizeof(*out_mad))) - return IB_MAD_RESULT_FAILURE; - - switch (in_mad->mad_hdr.mgmt_class) { - case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: - case IB_MGMT_CLASS_SUBN_LID_ROUTED: - ret = process_subn(ibdev, mad_flags, port_num, - in_mad, out_mad); - goto bail; - case IB_MGMT_CLASS_PERF_MGMT: - ret = process_perf(ibdev, port_num, in_mad, out_mad); - goto bail; - default: - ret = IB_MAD_RESULT_SUCCESS; - } - -bail: - return ret; -} diff --git a/drivers/staging/rdma/ipath/ipath_mmap.c b/drivers/staging/rdma/ipath/ipath_mmap.c deleted file mode 100644 index e73274229404..000000000000 --- a/drivers/staging/rdma/ipath/ipath_mmap.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -#include "ipath_verbs.h" - -/** - * ipath_release_mmap_info - free mmap info structure - * @ref: a pointer to the kref within struct ipath_mmap_info - */ -void ipath_release_mmap_info(struct kref *ref) -{ - struct ipath_mmap_info *ip = - container_of(ref, struct ipath_mmap_info, ref); - struct ipath_ibdev *dev = to_idev(ip->context->device); - - spin_lock_irq(&dev->pending_lock); - list_del(&ip->pending_mmaps); - spin_unlock_irq(&dev->pending_lock); - - vfree(ip->obj); - kfree(ip); -} - -/* - * open and close keep track of how many times the CQ is mapped, - * to avoid releasing it. - */ -static void ipath_vma_open(struct vm_area_struct *vma) -{ - struct ipath_mmap_info *ip = vma->vm_private_data; - - kref_get(&ip->ref); -} - -static void ipath_vma_close(struct vm_area_struct *vma) -{ - struct ipath_mmap_info *ip = vma->vm_private_data; - - kref_put(&ip->ref, ipath_release_mmap_info); -} - -static const struct vm_operations_struct ipath_vm_ops = { - .open = ipath_vma_open, - .close = ipath_vma_close, -}; - -/** - * ipath_mmap - create a new mmap region - * @context: the IB user context of the process making the mmap() call - * @vma: the VMA to be initialized - * Return zero if the mmap is OK. Otherwise, return an errno. - */ -int ipath_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) -{ - struct ipath_ibdev *dev = to_idev(context->device); - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - unsigned long size = vma->vm_end - vma->vm_start; - struct ipath_mmap_info *ip, *pp; - int ret = -EINVAL; - - /* - * Search the device's list of objects waiting for a mmap call. - * Normally, this list is very short since a call to create a - * CQ, QP, or SRQ is soon followed by a call to mmap(). - */ - spin_lock_irq(&dev->pending_lock); - list_for_each_entry_safe(ip, pp, &dev->pending_mmaps, - pending_mmaps) { - /* Only the creator is allowed to mmap the object */ - if (context != ip->context || (__u64) offset != ip->offset) - continue; - /* Don't allow a mmap larger than the object. */ - if (size > ip->size) - break; - - list_del_init(&ip->pending_mmaps); - spin_unlock_irq(&dev->pending_lock); - - ret = remap_vmalloc_range(vma, ip->obj, 0); - if (ret) - goto done; - vma->vm_ops = &ipath_vm_ops; - vma->vm_private_data = ip; - ipath_vma_open(vma); - goto done; - } - spin_unlock_irq(&dev->pending_lock); -done: - return ret; -} - -/* - * Allocate information for ipath_mmap - */ -struct ipath_mmap_info *ipath_create_mmap_info(struct ipath_ibdev *dev, - u32 size, - struct ib_ucontext *context, - void *obj) { - struct ipath_mmap_info *ip; - - ip = kmalloc(sizeof *ip, GFP_KERNEL); - if (!ip) - goto bail; - - size = PAGE_ALIGN(size); - - spin_lock_irq(&dev->mmap_offset_lock); - if (dev->mmap_offset == 0) - dev->mmap_offset = PAGE_SIZE; - ip->offset = dev->mmap_offset; - dev->mmap_offset += size; - spin_unlock_irq(&dev->mmap_offset_lock); - - INIT_LIST_HEAD(&ip->pending_mmaps); - ip->size = size; - ip->context = context; - ip->obj = obj; - kref_init(&ip->ref); - -bail: - return ip; -} - -void ipath_update_mmap_info(struct ipath_ibdev *dev, - struct ipath_mmap_info *ip, - u32 size, void *obj) { - size = PAGE_ALIGN(size); - - spin_lock_irq(&dev->mmap_offset_lock); - if (dev->mmap_offset == 0) - dev->mmap_offset = PAGE_SIZE; - ip->offset = dev->mmap_offset; - dev->mmap_offset += size; - spin_unlock_irq(&dev->mmap_offset_lock); - - ip->size = size; - ip->obj = obj; -} diff --git a/drivers/staging/rdma/ipath/ipath_mr.c b/drivers/staging/rdma/ipath/ipath_mr.c deleted file mode 100644 index b76b0ce66709..000000000000 --- a/drivers/staging/rdma/ipath/ipath_mr.c +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. - * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include -#include -#include - -#include "ipath_verbs.h" - -/* Fast memory region */ -struct ipath_fmr { - struct ib_fmr ibfmr; - u8 page_shift; - struct ipath_mregion mr; /* must be last */ -}; - -static inline struct ipath_fmr *to_ifmr(struct ib_fmr *ibfmr) -{ - return container_of(ibfmr, struct ipath_fmr, ibfmr); -} - -/** - * ipath_get_dma_mr - get a DMA memory region - * @pd: protection domain for this memory region - * @acc: access flags - * - * Returns the memory region on success, otherwise returns an errno. - * Note that all DMA addresses should be created via the - * struct ib_dma_mapping_ops functions (see ipath_dma.c). - */ -struct ib_mr *ipath_get_dma_mr(struct ib_pd *pd, int acc) -{ - struct ipath_mr *mr; - struct ib_mr *ret; - - mr = kzalloc(sizeof *mr, GFP_KERNEL); - if (!mr) { - ret = ERR_PTR(-ENOMEM); - goto bail; - } - - mr->mr.access_flags = acc; - ret = &mr->ibmr; - -bail: - return ret; -} - -static struct ipath_mr *alloc_mr(int count, - struct ipath_lkey_table *lk_table) -{ - struct ipath_mr *mr; - int m, i = 0; - - /* Allocate struct plus pointers to first level page tables. */ - m = (count + IPATH_SEGSZ - 1) / IPATH_SEGSZ; - mr = kmalloc(sizeof *mr + m * sizeof mr->mr.map[0], GFP_KERNEL); - if (!mr) - goto done; - - /* Allocate first level page tables. */ - for (; i < m; i++) { - mr->mr.map[i] = kmalloc(sizeof *mr->mr.map[0], GFP_KERNEL); - if (!mr->mr.map[i]) - goto bail; - } - mr->mr.mapsz = m; - - if (!ipath_alloc_lkey(lk_table, &mr->mr)) - goto bail; - mr->ibmr.rkey = mr->ibmr.lkey = mr->mr.lkey; - - goto done; - -bail: - while (i) { - i--; - kfree(mr->mr.map[i]); - } - kfree(mr); - mr = NULL; - -done: - return mr; -} - -/** - * ipath_reg_user_mr - register a userspace memory region - * @pd: protection domain for this memory region - * @start: starting userspace address - * @length: length of region to register - * @virt_addr: virtual address to use (from HCA's point of view) - * @mr_access_flags: access flags for this memory region - * @udata: unused by the InfiniPath driver - * - * Returns the memory region on success, otherwise returns an errno. - */ -struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt_addr, int mr_access_flags, - struct ib_udata *udata) -{ - struct ipath_mr *mr; - struct ib_umem *umem; - int n, m, entry; - struct scatterlist *sg; - struct ib_mr *ret; - - if (length == 0) { - ret = ERR_PTR(-EINVAL); - goto bail; - } - - umem = ib_umem_get(pd->uobject->context, start, length, - mr_access_flags, 0); - if (IS_ERR(umem)) - return (void *) umem; - - n = umem->nmap; - mr = alloc_mr(n, &to_idev(pd->device)->lk_table); - if (!mr) { - ret = ERR_PTR(-ENOMEM); - ib_umem_release(umem); - goto bail; - } - - mr->mr.pd = pd; - mr->mr.user_base = start; - mr->mr.iova = virt_addr; - mr->mr.length = length; - mr->mr.offset = ib_umem_offset(umem); - mr->mr.access_flags = mr_access_flags; - mr->mr.max_segs = n; - mr->umem = umem; - - m = 0; - n = 0; - for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) { - void *vaddr; - - vaddr = page_address(sg_page(sg)); - if (!vaddr) { - ret = ERR_PTR(-EINVAL); - goto bail; - } - mr->mr.map[m]->segs[n].vaddr = vaddr; - mr->mr.map[m]->segs[n].length = umem->page_size; - n++; - if (n == IPATH_SEGSZ) { - m++; - n = 0; - } - } - ret = &mr->ibmr; - -bail: - return ret; -} - -/** - * ipath_dereg_mr - unregister and free a memory region - * @ibmr: the memory region to free - * - * Returns 0 on success. - * - * Note that this is called to free MRs created by ipath_get_dma_mr() - * or ipath_reg_user_mr(). - */ -int ipath_dereg_mr(struct ib_mr *ibmr) -{ - struct ipath_mr *mr = to_imr(ibmr); - int i; - - ipath_free_lkey(&to_idev(ibmr->device)->lk_table, ibmr->lkey); - i = mr->mr.mapsz; - while (i) { - i--; - kfree(mr->mr.map[i]); - } - - if (mr->umem) - ib_umem_release(mr->umem); - - kfree(mr); - return 0; -} - -/** - * ipath_alloc_fmr - allocate a fast memory region - * @pd: the protection domain for this memory region - * @mr_access_flags: access flags for this memory region - * @fmr_attr: fast memory region attributes - * - * Returns the memory region on success, otherwise returns an errno. - */ -struct ib_fmr *ipath_alloc_fmr(struct ib_pd *pd, int mr_access_flags, - struct ib_fmr_attr *fmr_attr) -{ - struct ipath_fmr *fmr; - int m, i = 0; - struct ib_fmr *ret; - - /* Allocate struct plus pointers to first level page tables. */ - m = (fmr_attr->max_pages + IPATH_SEGSZ - 1) / IPATH_SEGSZ; - fmr = kmalloc(sizeof *fmr + m * sizeof fmr->mr.map[0], GFP_KERNEL); - if (!fmr) - goto bail; - - /* Allocate first level page tables. */ - for (; i < m; i++) { - fmr->mr.map[i] = kmalloc(sizeof *fmr->mr.map[0], - GFP_KERNEL); - if (!fmr->mr.map[i]) - goto bail; - } - fmr->mr.mapsz = m; - - /* - * ib_alloc_fmr() will initialize fmr->ibfmr except for lkey & - * rkey. - */ - if (!ipath_alloc_lkey(&to_idev(pd->device)->lk_table, &fmr->mr)) - goto bail; - fmr->ibfmr.rkey = fmr->ibfmr.lkey = fmr->mr.lkey; - /* - * Resources are allocated but no valid mapping (RKEY can't be - * used). - */ - fmr->mr.pd = pd; - fmr->mr.user_base = 0; - fmr->mr.iova = 0; - fmr->mr.length = 0; - fmr->mr.offset = 0; - fmr->mr.access_flags = mr_access_flags; - fmr->mr.max_segs = fmr_attr->max_pages; - fmr->page_shift = fmr_attr->page_shift; - - ret = &fmr->ibfmr; - goto done; - -bail: - while (i) - kfree(fmr->mr.map[--i]); - kfree(fmr); - ret = ERR_PTR(-ENOMEM); - -done: - return ret; -} - -/** - * ipath_map_phys_fmr - set up a fast memory region - * @ibmfr: the fast memory region to set up - * @page_list: the list of pages to associate with the fast memory region - * @list_len: the number of pages to associate with the fast memory region - * @iova: the virtual address of the start of the fast memory region - * - * This may be called from interrupt context. - */ - -int ipath_map_phys_fmr(struct ib_fmr *ibfmr, u64 * page_list, - int list_len, u64 iova) -{ - struct ipath_fmr *fmr = to_ifmr(ibfmr); - struct ipath_lkey_table *rkt; - unsigned long flags; - int m, n, i; - u32 ps; - int ret; - - if (list_len > fmr->mr.max_segs) { - ret = -EINVAL; - goto bail; - } - rkt = &to_idev(ibfmr->device)->lk_table; - spin_lock_irqsave(&rkt->lock, flags); - fmr->mr.user_base = iova; - fmr->mr.iova = iova; - ps = 1 << fmr->page_shift; - fmr->mr.length = list_len * ps; - m = 0; - n = 0; - ps = 1 << fmr->page_shift; - for (i = 0; i < list_len; i++) { - fmr->mr.map[m]->segs[n].vaddr = (void *) page_list[i]; - fmr->mr.map[m]->segs[n].length = ps; - if (++n == IPATH_SEGSZ) { - m++; - n = 0; - } - } - spin_unlock_irqrestore(&rkt->lock, flags); - ret = 0; - -bail: - return ret; -} - -/** - * ipath_unmap_fmr - unmap fast memory regions - * @fmr_list: the list of fast memory regions to unmap - * - * Returns 0 on success. - */ -int ipath_unmap_fmr(struct list_head *fmr_list) -{ - struct ipath_fmr *fmr; - struct ipath_lkey_table *rkt; - unsigned long flags; - - list_for_each_entry(fmr, fmr_list, ibfmr.list) { - rkt = &to_idev(fmr->ibfmr.device)->lk_table; - spin_lock_irqsave(&rkt->lock, flags); - fmr->mr.user_base = 0; - fmr->mr.iova = 0; - fmr->mr.length = 0; - spin_unlock_irqrestore(&rkt->lock, flags); - } - return 0; -} - -/** - * ipath_dealloc_fmr - deallocate a fast memory region - * @ibfmr: the fast memory region to deallocate - * - * Returns 0 on success. - */ -int ipath_dealloc_fmr(struct ib_fmr *ibfmr) -{ - struct ipath_fmr *fmr = to_ifmr(ibfmr); - int i; - - ipath_free_lkey(&to_idev(ibfmr->device)->lk_table, ibfmr->lkey); - i = fmr->mr.mapsz; - while (i) - kfree(fmr->mr.map[--i]); - kfree(fmr); - return 0; -} diff --git a/drivers/staging/rdma/ipath/ipath_qp.c b/drivers/staging/rdma/ipath/ipath_qp.c deleted file mode 100644 index 280cd2d638e4..000000000000 --- a/drivers/staging/rdma/ipath/ipath_qp.c +++ /dev/null @@ -1,1079 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include - -#include "ipath_verbs.h" -#include "ipath_kernel.h" - -#define BITS_PER_PAGE (PAGE_SIZE*BITS_PER_BYTE) -#define BITS_PER_PAGE_MASK (BITS_PER_PAGE-1) -#define mk_qpn(qpt, map, off) (((map) - (qpt)->map) * BITS_PER_PAGE + \ - (off)) -#define find_next_offset(map, off) find_next_zero_bit((map)->page, \ - BITS_PER_PAGE, off) - -/* - * Convert the AETH credit code into the number of credits. - */ -static u32 credit_table[31] = { - 0, /* 0 */ - 1, /* 1 */ - 2, /* 2 */ - 3, /* 3 */ - 4, /* 4 */ - 6, /* 5 */ - 8, /* 6 */ - 12, /* 7 */ - 16, /* 8 */ - 24, /* 9 */ - 32, /* A */ - 48, /* B */ - 64, /* C */ - 96, /* D */ - 128, /* E */ - 192, /* F */ - 256, /* 10 */ - 384, /* 11 */ - 512, /* 12 */ - 768, /* 13 */ - 1024, /* 14 */ - 1536, /* 15 */ - 2048, /* 16 */ - 3072, /* 17 */ - 4096, /* 18 */ - 6144, /* 19 */ - 8192, /* 1A */ - 12288, /* 1B */ - 16384, /* 1C */ - 24576, /* 1D */ - 32768 /* 1E */ -}; - - -static void get_map_page(struct ipath_qp_table *qpt, struct qpn_map *map) -{ - unsigned long page = get_zeroed_page(GFP_KERNEL); - unsigned long flags; - - /* - * Free the page if someone raced with us installing it. - */ - - spin_lock_irqsave(&qpt->lock, flags); - if (map->page) - free_page(page); - else - map->page = (void *)page; - spin_unlock_irqrestore(&qpt->lock, flags); -} - - -static int alloc_qpn(struct ipath_qp_table *qpt, enum ib_qp_type type) -{ - u32 i, offset, max_scan, qpn; - struct qpn_map *map; - u32 ret = -1; - - if (type == IB_QPT_SMI) - ret = 0; - else if (type == IB_QPT_GSI) - ret = 1; - - if (ret != -1) { - map = &qpt->map[0]; - if (unlikely(!map->page)) { - get_map_page(qpt, map); - if (unlikely(!map->page)) { - ret = -ENOMEM; - goto bail; - } - } - if (!test_and_set_bit(ret, map->page)) - atomic_dec(&map->n_free); - else - ret = -EBUSY; - goto bail; - } - - qpn = qpt->last + 1; - if (qpn >= QPN_MAX) - qpn = 2; - offset = qpn & BITS_PER_PAGE_MASK; - map = &qpt->map[qpn / BITS_PER_PAGE]; - max_scan = qpt->nmaps - !offset; - for (i = 0;;) { - if (unlikely(!map->page)) { - get_map_page(qpt, map); - if (unlikely(!map->page)) - break; - } - if (likely(atomic_read(&map->n_free))) { - do { - if (!test_and_set_bit(offset, map->page)) { - atomic_dec(&map->n_free); - qpt->last = qpn; - ret = qpn; - goto bail; - } - offset = find_next_offset(map, offset); - qpn = mk_qpn(qpt, map, offset); - /* - * This test differs from alloc_pidmap(). - * If find_next_offset() does find a zero - * bit, we don't need to check for QPN - * wrapping around past our starting QPN. - * We just need to be sure we don't loop - * forever. - */ - } while (offset < BITS_PER_PAGE && qpn < QPN_MAX); - } - /* - * In order to keep the number of pages allocated to a - * minimum, we scan the all existing pages before increasing - * the size of the bitmap table. - */ - if (++i > max_scan) { - if (qpt->nmaps == QPNMAP_ENTRIES) - break; - map = &qpt->map[qpt->nmaps++]; - offset = 0; - } else if (map < &qpt->map[qpt->nmaps]) { - ++map; - offset = 0; - } else { - map = &qpt->map[0]; - offset = 2; - } - qpn = mk_qpn(qpt, map, offset); - } - - ret = -ENOMEM; - -bail: - return ret; -} - -static void free_qpn(struct ipath_qp_table *qpt, u32 qpn) -{ - struct qpn_map *map; - - map = qpt->map + qpn / BITS_PER_PAGE; - if (map->page) - clear_bit(qpn & BITS_PER_PAGE_MASK, map->page); - atomic_inc(&map->n_free); -} - -/** - * ipath_alloc_qpn - allocate a QP number - * @qpt: the QP table - * @qp: the QP - * @type: the QP type (IB_QPT_SMI and IB_QPT_GSI are special) - * - * Allocate the next available QPN and put the QP into the hash table. - * The hash table holds a reference to the QP. - */ -static int ipath_alloc_qpn(struct ipath_qp_table *qpt, struct ipath_qp *qp, - enum ib_qp_type type) -{ - unsigned long flags; - int ret; - - ret = alloc_qpn(qpt, type); - if (ret < 0) - goto bail; - qp->ibqp.qp_num = ret; - - /* Add the QP to the hash table. */ - spin_lock_irqsave(&qpt->lock, flags); - - ret %= qpt->max; - qp->next = qpt->table[ret]; - qpt->table[ret] = qp; - atomic_inc(&qp->refcount); - - spin_unlock_irqrestore(&qpt->lock, flags); - ret = 0; - -bail: - return ret; -} - -/** - * ipath_free_qp - remove a QP from the QP table - * @qpt: the QP table - * @qp: the QP to remove - * - * Remove the QP from the table so it can't be found asynchronously by - * the receive interrupt routine. - */ -static void ipath_free_qp(struct ipath_qp_table *qpt, struct ipath_qp *qp) -{ - struct ipath_qp *q, **qpp; - unsigned long flags; - - spin_lock_irqsave(&qpt->lock, flags); - - /* Remove QP from the hash table. */ - qpp = &qpt->table[qp->ibqp.qp_num % qpt->max]; - for (; (q = *qpp) != NULL; qpp = &q->next) { - if (q == qp) { - *qpp = qp->next; - qp->next = NULL; - atomic_dec(&qp->refcount); - break; - } - } - - spin_unlock_irqrestore(&qpt->lock, flags); -} - -/** - * ipath_free_all_qps - check for QPs still in use - * @qpt: the QP table to empty - * - * There should not be any QPs still in use. - * Free memory for table. - */ -unsigned ipath_free_all_qps(struct ipath_qp_table *qpt) -{ - unsigned long flags; - struct ipath_qp *qp; - u32 n, qp_inuse = 0; - - spin_lock_irqsave(&qpt->lock, flags); - for (n = 0; n < qpt->max; n++) { - qp = qpt->table[n]; - qpt->table[n] = NULL; - - for (; qp; qp = qp->next) - qp_inuse++; - } - spin_unlock_irqrestore(&qpt->lock, flags); - - for (n = 0; n < ARRAY_SIZE(qpt->map); n++) - if (qpt->map[n].page) - free_page((unsigned long) qpt->map[n].page); - return qp_inuse; -} - -/** - * ipath_lookup_qpn - return the QP with the given QPN - * @qpt: the QP table - * @qpn: the QP number to look up - * - * The caller is responsible for decrementing the QP reference count - * when done. - */ -struct ipath_qp *ipath_lookup_qpn(struct ipath_qp_table *qpt, u32 qpn) -{ - unsigned long flags; - struct ipath_qp *qp; - - spin_lock_irqsave(&qpt->lock, flags); - - for (qp = qpt->table[qpn % qpt->max]; qp; qp = qp->next) { - if (qp->ibqp.qp_num == qpn) { - atomic_inc(&qp->refcount); - break; - } - } - - spin_unlock_irqrestore(&qpt->lock, flags); - return qp; -} - -/** - * ipath_reset_qp - initialize the QP state to the reset state - * @qp: the QP to reset - * @type: the QP type - */ -static void ipath_reset_qp(struct ipath_qp *qp, enum ib_qp_type type) -{ - qp->remote_qpn = 0; - qp->qkey = 0; - qp->qp_access_flags = 0; - atomic_set(&qp->s_dma_busy, 0); - qp->s_flags &= IPATH_S_SIGNAL_REQ_WR; - qp->s_hdrwords = 0; - qp->s_wqe = NULL; - qp->s_pkt_delay = 0; - qp->s_draining = 0; - qp->s_psn = 0; - qp->r_psn = 0; - qp->r_msn = 0; - if (type == IB_QPT_RC) { - qp->s_state = IB_OPCODE_RC_SEND_LAST; - qp->r_state = IB_OPCODE_RC_SEND_LAST; - } else { - qp->s_state = IB_OPCODE_UC_SEND_LAST; - qp->r_state = IB_OPCODE_UC_SEND_LAST; - } - qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE; - qp->r_nak_state = 0; - qp->r_aflags = 0; - qp->r_flags = 0; - qp->s_rnr_timeout = 0; - qp->s_head = 0; - qp->s_tail = 0; - qp->s_cur = 0; - qp->s_last = 0; - qp->s_ssn = 1; - qp->s_lsn = 0; - memset(qp->s_ack_queue, 0, sizeof(qp->s_ack_queue)); - qp->r_head_ack_queue = 0; - qp->s_tail_ack_queue = 0; - qp->s_num_rd_atomic = 0; - if (qp->r_rq.wq) { - qp->r_rq.wq->head = 0; - qp->r_rq.wq->tail = 0; - } -} - -/** - * ipath_error_qp - put a QP into the error state - * @qp: the QP to put into the error state - * @err: the receive completion error to signal if a RWQE is active - * - * Flushes both send and receive work queues. - * Returns true if last WQE event should be generated. - * The QP s_lock should be held and interrupts disabled. - * If we are already in error state, just return. - */ - -int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err) -{ - struct ipath_ibdev *dev = to_idev(qp->ibqp.device); - struct ib_wc wc; - int ret = 0; - - if (qp->state == IB_QPS_ERR) - goto bail; - - qp->state = IB_QPS_ERR; - - spin_lock(&dev->pending_lock); - if (!list_empty(&qp->timerwait)) - list_del_init(&qp->timerwait); - if (!list_empty(&qp->piowait)) - list_del_init(&qp->piowait); - spin_unlock(&dev->pending_lock); - - /* Schedule the sending tasklet to drain the send work queue. */ - if (qp->s_last != qp->s_head) - ipath_schedule_send(qp); - - memset(&wc, 0, sizeof(wc)); - wc.qp = &qp->ibqp; - wc.opcode = IB_WC_RECV; - - if (test_and_clear_bit(IPATH_R_WRID_VALID, &qp->r_aflags)) { - wc.wr_id = qp->r_wr_id; - wc.status = err; - ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1); - } - wc.status = IB_WC_WR_FLUSH_ERR; - - if (qp->r_rq.wq) { - struct ipath_rwq *wq; - u32 head; - u32 tail; - - spin_lock(&qp->r_rq.lock); - - /* sanity check pointers before trusting them */ - wq = qp->r_rq.wq; - head = wq->head; - if (head >= qp->r_rq.size) - head = 0; - tail = wq->tail; - if (tail >= qp->r_rq.size) - tail = 0; - while (tail != head) { - wc.wr_id = get_rwqe_ptr(&qp->r_rq, tail)->wr_id; - if (++tail >= qp->r_rq.size) - tail = 0; - ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1); - } - wq->tail = tail; - - spin_unlock(&qp->r_rq.lock); - } else if (qp->ibqp.event_handler) - ret = 1; - -bail: - return ret; -} - -/** - * ipath_modify_qp - modify the attributes of a queue pair - * @ibqp: the queue pair who's attributes we're modifying - * @attr: the new attributes - * @attr_mask: the mask of attributes to modify - * @udata: user data for ipathverbs.so - * - * Returns 0 on success, otherwise returns an errno. - */ -int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, - int attr_mask, struct ib_udata *udata) -{ - struct ipath_ibdev *dev = to_idev(ibqp->device); - struct ipath_qp *qp = to_iqp(ibqp); - enum ib_qp_state cur_state, new_state; - int lastwqe = 0; - int ret; - - spin_lock_irq(&qp->s_lock); - - cur_state = attr_mask & IB_QP_CUR_STATE ? - attr->cur_qp_state : qp->state; - new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state; - - if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, - attr_mask, IB_LINK_LAYER_UNSPECIFIED)) - goto inval; - - if (attr_mask & IB_QP_AV) { - if (attr->ah_attr.dlid == 0 || - attr->ah_attr.dlid >= IPATH_MULTICAST_LID_BASE) - goto inval; - - if ((attr->ah_attr.ah_flags & IB_AH_GRH) && - (attr->ah_attr.grh.sgid_index > 1)) - goto inval; - } - - if (attr_mask & IB_QP_PKEY_INDEX) - if (attr->pkey_index >= ipath_get_npkeys(dev->dd)) - goto inval; - - if (attr_mask & IB_QP_MIN_RNR_TIMER) - if (attr->min_rnr_timer > 31) - goto inval; - - if (attr_mask & IB_QP_PORT) - if (attr->port_num == 0 || - attr->port_num > ibqp->device->phys_port_cnt) - goto inval; - - /* - * don't allow invalid Path MTU values or greater than 2048 - * unless we are configured for a 4KB MTU - */ - if ((attr_mask & IB_QP_PATH_MTU) && - (ib_mtu_enum_to_int(attr->path_mtu) == -1 || - (attr->path_mtu > IB_MTU_2048 && !ipath_mtu4096))) - goto inval; - - if (attr_mask & IB_QP_PATH_MIG_STATE) - if (attr->path_mig_state != IB_MIG_MIGRATED && - attr->path_mig_state != IB_MIG_REARM) - goto inval; - - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) - if (attr->max_dest_rd_atomic > IPATH_MAX_RDMA_ATOMIC) - goto inval; - - switch (new_state) { - case IB_QPS_RESET: - if (qp->state != IB_QPS_RESET) { - qp->state = IB_QPS_RESET; - spin_lock(&dev->pending_lock); - if (!list_empty(&qp->timerwait)) - list_del_init(&qp->timerwait); - if (!list_empty(&qp->piowait)) - list_del_init(&qp->piowait); - spin_unlock(&dev->pending_lock); - qp->s_flags &= ~IPATH_S_ANY_WAIT; - spin_unlock_irq(&qp->s_lock); - /* Stop the sending tasklet */ - tasklet_kill(&qp->s_task); - wait_event(qp->wait_dma, !atomic_read(&qp->s_dma_busy)); - spin_lock_irq(&qp->s_lock); - } - ipath_reset_qp(qp, ibqp->qp_type); - break; - - case IB_QPS_SQD: - qp->s_draining = qp->s_last != qp->s_cur; - qp->state = new_state; - break; - - case IB_QPS_SQE: - if (qp->ibqp.qp_type == IB_QPT_RC) - goto inval; - qp->state = new_state; - break; - - case IB_QPS_ERR: - lastwqe = ipath_error_qp(qp, IB_WC_WR_FLUSH_ERR); - break; - - default: - qp->state = new_state; - break; - } - - if (attr_mask & IB_QP_PKEY_INDEX) - qp->s_pkey_index = attr->pkey_index; - - if (attr_mask & IB_QP_DEST_QPN) - qp->remote_qpn = attr->dest_qp_num; - - if (attr_mask & IB_QP_SQ_PSN) { - qp->s_psn = qp->s_next_psn = attr->sq_psn; - qp->s_last_psn = qp->s_next_psn - 1; - } - - if (attr_mask & IB_QP_RQ_PSN) - qp->r_psn = attr->rq_psn; - - if (attr_mask & IB_QP_ACCESS_FLAGS) - qp->qp_access_flags = attr->qp_access_flags; - - if (attr_mask & IB_QP_AV) { - qp->remote_ah_attr = attr->ah_attr; - qp->s_dmult = ipath_ib_rate_to_mult(attr->ah_attr.static_rate); - } - - if (attr_mask & IB_QP_PATH_MTU) - qp->path_mtu = attr->path_mtu; - - if (attr_mask & IB_QP_RETRY_CNT) - qp->s_retry = qp->s_retry_cnt = attr->retry_cnt; - - if (attr_mask & IB_QP_RNR_RETRY) { - qp->s_rnr_retry = attr->rnr_retry; - if (qp->s_rnr_retry > 7) - qp->s_rnr_retry = 7; - qp->s_rnr_retry_cnt = qp->s_rnr_retry; - } - - if (attr_mask & IB_QP_MIN_RNR_TIMER) - qp->r_min_rnr_timer = attr->min_rnr_timer; - - if (attr_mask & IB_QP_TIMEOUT) - qp->timeout = attr->timeout; - - if (attr_mask & IB_QP_QKEY) - qp->qkey = attr->qkey; - - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) - qp->r_max_rd_atomic = attr->max_dest_rd_atomic; - - if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) - qp->s_max_rd_atomic = attr->max_rd_atomic; - - spin_unlock_irq(&qp->s_lock); - - if (lastwqe) { - struct ib_event ev; - - ev.device = qp->ibqp.device; - ev.element.qp = &qp->ibqp; - ev.event = IB_EVENT_QP_LAST_WQE_REACHED; - qp->ibqp.event_handler(&ev, qp->ibqp.qp_context); - } - ret = 0; - goto bail; - -inval: - spin_unlock_irq(&qp->s_lock); - ret = -EINVAL; - -bail: - return ret; -} - -int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, - int attr_mask, struct ib_qp_init_attr *init_attr) -{ - struct ipath_qp *qp = to_iqp(ibqp); - - attr->qp_state = qp->state; - attr->cur_qp_state = attr->qp_state; - attr->path_mtu = qp->path_mtu; - attr->path_mig_state = 0; - attr->qkey = qp->qkey; - attr->rq_psn = qp->r_psn; - attr->sq_psn = qp->s_next_psn; - attr->dest_qp_num = qp->remote_qpn; - attr->qp_access_flags = qp->qp_access_flags; - attr->cap.max_send_wr = qp->s_size - 1; - attr->cap.max_recv_wr = qp->ibqp.srq ? 0 : qp->r_rq.size - 1; - attr->cap.max_send_sge = qp->s_max_sge; - attr->cap.max_recv_sge = qp->r_rq.max_sge; - attr->cap.max_inline_data = 0; - attr->ah_attr = qp->remote_ah_attr; - memset(&attr->alt_ah_attr, 0, sizeof(attr->alt_ah_attr)); - attr->pkey_index = qp->s_pkey_index; - attr->alt_pkey_index = 0; - attr->en_sqd_async_notify = 0; - attr->sq_draining = qp->s_draining; - attr->max_rd_atomic = qp->s_max_rd_atomic; - attr->max_dest_rd_atomic = qp->r_max_rd_atomic; - attr->min_rnr_timer = qp->r_min_rnr_timer; - attr->port_num = 1; - attr->timeout = qp->timeout; - attr->retry_cnt = qp->s_retry_cnt; - attr->rnr_retry = qp->s_rnr_retry_cnt; - attr->alt_port_num = 0; - attr->alt_timeout = 0; - - init_attr->event_handler = qp->ibqp.event_handler; - init_attr->qp_context = qp->ibqp.qp_context; - init_attr->send_cq = qp->ibqp.send_cq; - init_attr->recv_cq = qp->ibqp.recv_cq; - init_attr->srq = qp->ibqp.srq; - init_attr->cap = attr->cap; - if (qp->s_flags & IPATH_S_SIGNAL_REQ_WR) - init_attr->sq_sig_type = IB_SIGNAL_REQ_WR; - else - init_attr->sq_sig_type = IB_SIGNAL_ALL_WR; - init_attr->qp_type = qp->ibqp.qp_type; - init_attr->port_num = 1; - return 0; -} - -/** - * ipath_compute_aeth - compute the AETH (syndrome + MSN) - * @qp: the queue pair to compute the AETH for - * - * Returns the AETH. - */ -__be32 ipath_compute_aeth(struct ipath_qp *qp) -{ - u32 aeth = qp->r_msn & IPATH_MSN_MASK; - - if (qp->ibqp.srq) { - /* - * Shared receive queues don't generate credits. - * Set the credit field to the invalid value. - */ - aeth |= IPATH_AETH_CREDIT_INVAL << IPATH_AETH_CREDIT_SHIFT; - } else { - u32 min, max, x; - u32 credits; - struct ipath_rwq *wq = qp->r_rq.wq; - u32 head; - u32 tail; - - /* sanity check pointers before trusting them */ - head = wq->head; - if (head >= qp->r_rq.size) - head = 0; - tail = wq->tail; - if (tail >= qp->r_rq.size) - tail = 0; - /* - * Compute the number of credits available (RWQEs). - * XXX Not holding the r_rq.lock here so there is a small - * chance that the pair of reads are not atomic. - */ - credits = head - tail; - if ((int)credits < 0) - credits += qp->r_rq.size; - /* - * Binary search the credit table to find the code to - * use. - */ - min = 0; - max = 31; - for (;;) { - x = (min + max) / 2; - if (credit_table[x] == credits) - break; - if (credit_table[x] > credits) - max = x; - else if (min == x) - break; - else - min = x; - } - aeth |= x << IPATH_AETH_CREDIT_SHIFT; - } - return cpu_to_be32(aeth); -} - -/** - * ipath_create_qp - create a queue pair for a device - * @ibpd: the protection domain who's device we create the queue pair for - * @init_attr: the attributes of the queue pair - * @udata: unused by InfiniPath - * - * Returns the queue pair on success, otherwise returns an errno. - * - * Called by the ib_create_qp() core verbs function. - */ -struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, - struct ib_qp_init_attr *init_attr, - struct ib_udata *udata) -{ - struct ipath_qp *qp; - int err; - struct ipath_swqe *swq = NULL; - struct ipath_ibdev *dev; - size_t sz; - size_t sg_list_sz; - struct ib_qp *ret; - - if (init_attr->create_flags) { - ret = ERR_PTR(-EINVAL); - goto bail; - } - - if (init_attr->cap.max_send_sge > ib_ipath_max_sges || - init_attr->cap.max_send_wr > ib_ipath_max_qp_wrs) { - ret = ERR_PTR(-EINVAL); - goto bail; - } - - /* Check receive queue parameters if no SRQ is specified. */ - if (!init_attr->srq) { - if (init_attr->cap.max_recv_sge > ib_ipath_max_sges || - init_attr->cap.max_recv_wr > ib_ipath_max_qp_wrs) { - ret = ERR_PTR(-EINVAL); - goto bail; - } - if (init_attr->cap.max_send_sge + - init_attr->cap.max_send_wr + - init_attr->cap.max_recv_sge + - init_attr->cap.max_recv_wr == 0) { - ret = ERR_PTR(-EINVAL); - goto bail; - } - } - - switch (init_attr->qp_type) { - case IB_QPT_UC: - case IB_QPT_RC: - case IB_QPT_UD: - case IB_QPT_SMI: - case IB_QPT_GSI: - sz = sizeof(struct ipath_sge) * - init_attr->cap.max_send_sge + - sizeof(struct ipath_swqe); - swq = vmalloc((init_attr->cap.max_send_wr + 1) * sz); - if (swq == NULL) { - ret = ERR_PTR(-ENOMEM); - goto bail; - } - sz = sizeof(*qp); - sg_list_sz = 0; - if (init_attr->srq) { - struct ipath_srq *srq = to_isrq(init_attr->srq); - - if (srq->rq.max_sge > 1) - sg_list_sz = sizeof(*qp->r_sg_list) * - (srq->rq.max_sge - 1); - } else if (init_attr->cap.max_recv_sge > 1) - sg_list_sz = sizeof(*qp->r_sg_list) * - (init_attr->cap.max_recv_sge - 1); - qp = kmalloc(sz + sg_list_sz, GFP_KERNEL); - if (!qp) { - ret = ERR_PTR(-ENOMEM); - goto bail_swq; - } - if (sg_list_sz && (init_attr->qp_type == IB_QPT_UD || - init_attr->qp_type == IB_QPT_SMI || - init_attr->qp_type == IB_QPT_GSI)) { - qp->r_ud_sg_list = kmalloc(sg_list_sz, GFP_KERNEL); - if (!qp->r_ud_sg_list) { - ret = ERR_PTR(-ENOMEM); - goto bail_qp; - } - } else - qp->r_ud_sg_list = NULL; - if (init_attr->srq) { - sz = 0; - qp->r_rq.size = 0; - qp->r_rq.max_sge = 0; - qp->r_rq.wq = NULL; - init_attr->cap.max_recv_wr = 0; - init_attr->cap.max_recv_sge = 0; - } else { - qp->r_rq.size = init_attr->cap.max_recv_wr + 1; - qp->r_rq.max_sge = init_attr->cap.max_recv_sge; - sz = (sizeof(struct ib_sge) * qp->r_rq.max_sge) + - sizeof(struct ipath_rwqe); - qp->r_rq.wq = vmalloc_user(sizeof(struct ipath_rwq) + - qp->r_rq.size * sz); - if (!qp->r_rq.wq) { - ret = ERR_PTR(-ENOMEM); - goto bail_sg_list; - } - } - - /* - * ib_create_qp() will initialize qp->ibqp - * except for qp->ibqp.qp_num. - */ - spin_lock_init(&qp->s_lock); - spin_lock_init(&qp->r_rq.lock); - atomic_set(&qp->refcount, 0); - init_waitqueue_head(&qp->wait); - init_waitqueue_head(&qp->wait_dma); - tasklet_init(&qp->s_task, ipath_do_send, (unsigned long)qp); - INIT_LIST_HEAD(&qp->piowait); - INIT_LIST_HEAD(&qp->timerwait); - qp->state = IB_QPS_RESET; - qp->s_wq = swq; - qp->s_size = init_attr->cap.max_send_wr + 1; - qp->s_max_sge = init_attr->cap.max_send_sge; - if (init_attr->sq_sig_type == IB_SIGNAL_REQ_WR) - qp->s_flags = IPATH_S_SIGNAL_REQ_WR; - else - qp->s_flags = 0; - dev = to_idev(ibpd->device); - err = ipath_alloc_qpn(&dev->qp_table, qp, - init_attr->qp_type); - if (err) { - ret = ERR_PTR(err); - vfree(qp->r_rq.wq); - goto bail_sg_list; - } - qp->ip = NULL; - qp->s_tx = NULL; - ipath_reset_qp(qp, init_attr->qp_type); - break; - - default: - /* Don't support raw QPs */ - ret = ERR_PTR(-ENOSYS); - goto bail; - } - - init_attr->cap.max_inline_data = 0; - - /* - * Return the address of the RWQ as the offset to mmap. - * See ipath_mmap() for details. - */ - if (udata && udata->outlen >= sizeof(__u64)) { - if (!qp->r_rq.wq) { - __u64 offset = 0; - - err = ib_copy_to_udata(udata, &offset, - sizeof(offset)); - if (err) { - ret = ERR_PTR(err); - goto bail_ip; - } - } else { - u32 s = sizeof(struct ipath_rwq) + - qp->r_rq.size * sz; - - qp->ip = - ipath_create_mmap_info(dev, s, - ibpd->uobject->context, - qp->r_rq.wq); - if (!qp->ip) { - ret = ERR_PTR(-ENOMEM); - goto bail_ip; - } - - err = ib_copy_to_udata(udata, &(qp->ip->offset), - sizeof(qp->ip->offset)); - if (err) { - ret = ERR_PTR(err); - goto bail_ip; - } - } - } - - spin_lock(&dev->n_qps_lock); - if (dev->n_qps_allocated == ib_ipath_max_qps) { - spin_unlock(&dev->n_qps_lock); - ret = ERR_PTR(-ENOMEM); - goto bail_ip; - } - - dev->n_qps_allocated++; - spin_unlock(&dev->n_qps_lock); - - if (qp->ip) { - spin_lock_irq(&dev->pending_lock); - list_add(&qp->ip->pending_mmaps, &dev->pending_mmaps); - spin_unlock_irq(&dev->pending_lock); - } - - ret = &qp->ibqp; - goto bail; - -bail_ip: - if (qp->ip) - kref_put(&qp->ip->ref, ipath_release_mmap_info); - else - vfree(qp->r_rq.wq); - ipath_free_qp(&dev->qp_table, qp); - free_qpn(&dev->qp_table, qp->ibqp.qp_num); -bail_sg_list: - kfree(qp->r_ud_sg_list); -bail_qp: - kfree(qp); -bail_swq: - vfree(swq); -bail: - return ret; -} - -/** - * ipath_destroy_qp - destroy a queue pair - * @ibqp: the queue pair to destroy - * - * Returns 0 on success. - * - * Note that this can be called while the QP is actively sending or - * receiving! - */ -int ipath_destroy_qp(struct ib_qp *ibqp) -{ - struct ipath_qp *qp = to_iqp(ibqp); - struct ipath_ibdev *dev = to_idev(ibqp->device); - - /* Make sure HW and driver activity is stopped. */ - spin_lock_irq(&qp->s_lock); - if (qp->state != IB_QPS_RESET) { - qp->state = IB_QPS_RESET; - spin_lock(&dev->pending_lock); - if (!list_empty(&qp->timerwait)) - list_del_init(&qp->timerwait); - if (!list_empty(&qp->piowait)) - list_del_init(&qp->piowait); - spin_unlock(&dev->pending_lock); - qp->s_flags &= ~IPATH_S_ANY_WAIT; - spin_unlock_irq(&qp->s_lock); - /* Stop the sending tasklet */ - tasklet_kill(&qp->s_task); - wait_event(qp->wait_dma, !atomic_read(&qp->s_dma_busy)); - } else - spin_unlock_irq(&qp->s_lock); - - ipath_free_qp(&dev->qp_table, qp); - - if (qp->s_tx) { - atomic_dec(&qp->refcount); - if (qp->s_tx->txreq.flags & IPATH_SDMA_TXREQ_F_FREEBUF) - kfree(qp->s_tx->txreq.map_addr); - spin_lock_irq(&dev->pending_lock); - list_add(&qp->s_tx->txreq.list, &dev->txreq_free); - spin_unlock_irq(&dev->pending_lock); - qp->s_tx = NULL; - } - - wait_event(qp->wait, !atomic_read(&qp->refcount)); - - /* all user's cleaned up, mark it available */ - free_qpn(&dev->qp_table, qp->ibqp.qp_num); - spin_lock(&dev->n_qps_lock); - dev->n_qps_allocated--; - spin_unlock(&dev->n_qps_lock); - - if (qp->ip) - kref_put(&qp->ip->ref, ipath_release_mmap_info); - else - vfree(qp->r_rq.wq); - kfree(qp->r_ud_sg_list); - vfree(qp->s_wq); - kfree(qp); - return 0; -} - -/** - * ipath_init_qp_table - initialize the QP table for a device - * @idev: the device who's QP table we're initializing - * @size: the size of the QP table - * - * Returns 0 on success, otherwise returns an errno. - */ -int ipath_init_qp_table(struct ipath_ibdev *idev, int size) -{ - int i; - int ret; - - idev->qp_table.last = 1; /* QPN 0 and 1 are special. */ - idev->qp_table.max = size; - idev->qp_table.nmaps = 1; - idev->qp_table.table = kcalloc(size, sizeof(*idev->qp_table.table), - GFP_KERNEL); - if (idev->qp_table.table == NULL) { - ret = -ENOMEM; - goto bail; - } - - for (i = 0; i < ARRAY_SIZE(idev->qp_table.map); i++) { - atomic_set(&idev->qp_table.map[i].n_free, BITS_PER_PAGE); - idev->qp_table.map[i].page = NULL; - } - - ret = 0; - -bail: - return ret; -} - -/** - * ipath_get_credit - flush the send work queue of a QP - * @qp: the qp who's send work queue to flush - * @aeth: the Acknowledge Extended Transport Header - * - * The QP s_lock should be held. - */ -void ipath_get_credit(struct ipath_qp *qp, u32 aeth) -{ - u32 credit = (aeth >> IPATH_AETH_CREDIT_SHIFT) & IPATH_AETH_CREDIT_MASK; - - /* - * If the credit is invalid, we can send - * as many packets as we like. Otherwise, we have to - * honor the credit field. - */ - if (credit == IPATH_AETH_CREDIT_INVAL) - qp->s_lsn = (u32) -1; - else if (qp->s_lsn != (u32) -1) { - /* Compute new LSN (i.e., MSN + credit) */ - credit = (aeth + credit_table[credit]) & IPATH_MSN_MASK; - if (ipath_cmp24(credit, qp->s_lsn) > 0) - qp->s_lsn = credit; - } - - /* Restart sending if it was blocked due to lack of credits. */ - if ((qp->s_flags & IPATH_S_WAIT_SSN_CREDIT) && - qp->s_cur != qp->s_head && - (qp->s_lsn == (u32) -1 || - ipath_cmp24(get_swqe_ptr(qp, qp->s_cur)->ssn, - qp->s_lsn + 1) <= 0)) - ipath_schedule_send(qp); -} diff --git a/drivers/staging/rdma/ipath/ipath_rc.c b/drivers/staging/rdma/ipath/ipath_rc.c deleted file mode 100644 index d4aa53574e57..000000000000 --- a/drivers/staging/rdma/ipath/ipath_rc.c +++ /dev/null @@ -1,1969 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include "ipath_verbs.h" -#include "ipath_kernel.h" - -/* cut down ridiculously long IB macro names */ -#define OP(x) IB_OPCODE_RC_##x - -static u32 restart_sge(struct ipath_sge_state *ss, struct ipath_swqe *wqe, - u32 psn, u32 pmtu) -{ - u32 len; - - len = ((psn - wqe->psn) & IPATH_PSN_MASK) * pmtu; - ss->sge = wqe->sg_list[0]; - ss->sg_list = wqe->sg_list + 1; - ss->num_sge = wqe->wr.num_sge; - ipath_skip_sge(ss, len); - return wqe->length - len; -} - -/** - * ipath_init_restart- initialize the qp->s_sge after a restart - * @qp: the QP who's SGE we're restarting - * @wqe: the work queue to initialize the QP's SGE from - * - * The QP s_lock should be held and interrupts disabled. - */ -static void ipath_init_restart(struct ipath_qp *qp, struct ipath_swqe *wqe) -{ - struct ipath_ibdev *dev; - - qp->s_len = restart_sge(&qp->s_sge, wqe, qp->s_psn, - ib_mtu_enum_to_int(qp->path_mtu)); - dev = to_idev(qp->ibqp.device); - spin_lock(&dev->pending_lock); - if (list_empty(&qp->timerwait)) - list_add_tail(&qp->timerwait, - &dev->pending[dev->pending_index]); - spin_unlock(&dev->pending_lock); -} - -/** - * ipath_make_rc_ack - construct a response packet (ACK, NAK, or RDMA read) - * @qp: a pointer to the QP - * @ohdr: a pointer to the IB header being constructed - * @pmtu: the path MTU - * - * Return 1 if constructed; otherwise, return 0. - * Note that we are in the responder's side of the QP context. - * Note the QP s_lock must be held. - */ -static int ipath_make_rc_ack(struct ipath_ibdev *dev, struct ipath_qp *qp, - struct ipath_other_headers *ohdr, u32 pmtu) -{ - struct ipath_ack_entry *e; - u32 hwords; - u32 len; - u32 bth0; - u32 bth2; - - /* Don't send an ACK if we aren't supposed to. */ - if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) - goto bail; - - /* header size in 32-bit words LRH+BTH = (8+12)/4. */ - hwords = 5; - - switch (qp->s_ack_state) { - case OP(RDMA_READ_RESPONSE_LAST): - case OP(RDMA_READ_RESPONSE_ONLY): - case OP(ATOMIC_ACKNOWLEDGE): - /* - * We can increment the tail pointer now that the last - * response has been sent instead of only being - * constructed. - */ - if (++qp->s_tail_ack_queue > IPATH_MAX_RDMA_ATOMIC) - qp->s_tail_ack_queue = 0; - /* FALLTHROUGH */ - case OP(SEND_ONLY): - case OP(ACKNOWLEDGE): - /* Check for no next entry in the queue. */ - if (qp->r_head_ack_queue == qp->s_tail_ack_queue) { - if (qp->s_flags & IPATH_S_ACK_PENDING) - goto normal; - qp->s_ack_state = OP(ACKNOWLEDGE); - goto bail; - } - - e = &qp->s_ack_queue[qp->s_tail_ack_queue]; - if (e->opcode == OP(RDMA_READ_REQUEST)) { - /* Copy SGE state in case we need to resend */ - qp->s_ack_rdma_sge = e->rdma_sge; - qp->s_cur_sge = &qp->s_ack_rdma_sge; - len = e->rdma_sge.sge.sge_length; - if (len > pmtu) { - len = pmtu; - qp->s_ack_state = OP(RDMA_READ_RESPONSE_FIRST); - } else { - qp->s_ack_state = OP(RDMA_READ_RESPONSE_ONLY); - e->sent = 1; - } - ohdr->u.aeth = ipath_compute_aeth(qp); - hwords++; - qp->s_ack_rdma_psn = e->psn; - bth2 = qp->s_ack_rdma_psn++ & IPATH_PSN_MASK; - } else { - /* COMPARE_SWAP or FETCH_ADD */ - qp->s_cur_sge = NULL; - len = 0; - qp->s_ack_state = OP(ATOMIC_ACKNOWLEDGE); - ohdr->u.at.aeth = ipath_compute_aeth(qp); - ohdr->u.at.atomic_ack_eth[0] = - cpu_to_be32(e->atomic_data >> 32); - ohdr->u.at.atomic_ack_eth[1] = - cpu_to_be32(e->atomic_data); - hwords += sizeof(ohdr->u.at) / sizeof(u32); - bth2 = e->psn; - e->sent = 1; - } - bth0 = qp->s_ack_state << 24; - break; - - case OP(RDMA_READ_RESPONSE_FIRST): - qp->s_ack_state = OP(RDMA_READ_RESPONSE_MIDDLE); - /* FALLTHROUGH */ - case OP(RDMA_READ_RESPONSE_MIDDLE): - len = qp->s_ack_rdma_sge.sge.sge_length; - if (len > pmtu) - len = pmtu; - else { - ohdr->u.aeth = ipath_compute_aeth(qp); - hwords++; - qp->s_ack_state = OP(RDMA_READ_RESPONSE_LAST); - qp->s_ack_queue[qp->s_tail_ack_queue].sent = 1; - } - bth0 = qp->s_ack_state << 24; - bth2 = qp->s_ack_rdma_psn++ & IPATH_PSN_MASK; - break; - - default: - normal: - /* - * Send a regular ACK. - * Set the s_ack_state so we wait until after sending - * the ACK before setting s_ack_state to ACKNOWLEDGE - * (see above). - */ - qp->s_ack_state = OP(SEND_ONLY); - qp->s_flags &= ~IPATH_S_ACK_PENDING; - qp->s_cur_sge = NULL; - if (qp->s_nak_state) - ohdr->u.aeth = - cpu_to_be32((qp->r_msn & IPATH_MSN_MASK) | - (qp->s_nak_state << - IPATH_AETH_CREDIT_SHIFT)); - else - ohdr->u.aeth = ipath_compute_aeth(qp); - hwords++; - len = 0; - bth0 = OP(ACKNOWLEDGE) << 24; - bth2 = qp->s_ack_psn & IPATH_PSN_MASK; - } - qp->s_hdrwords = hwords; - qp->s_cur_size = len; - ipath_make_ruc_header(dev, qp, ohdr, bth0, bth2); - return 1; - -bail: - return 0; -} - -/** - * ipath_make_rc_req - construct a request packet (SEND, RDMA r/w, ATOMIC) - * @qp: a pointer to the QP - * - * Return 1 if constructed; otherwise, return 0. - */ -int ipath_make_rc_req(struct ipath_qp *qp) -{ - struct ipath_ibdev *dev = to_idev(qp->ibqp.device); - struct ipath_other_headers *ohdr; - struct ipath_sge_state *ss; - struct ipath_swqe *wqe; - u32 hwords; - u32 len; - u32 bth0; - u32 bth2; - u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu); - char newreq; - unsigned long flags; - int ret = 0; - - ohdr = &qp->s_hdr.u.oth; - if (qp->remote_ah_attr.ah_flags & IB_AH_GRH) - ohdr = &qp->s_hdr.u.l.oth; - - /* - * The lock is needed to synchronize between the sending tasklet, - * the receive interrupt handler, and timeout resends. - */ - spin_lock_irqsave(&qp->s_lock, flags); - - /* Sending responses has higher priority over sending requests. */ - if ((qp->r_head_ack_queue != qp->s_tail_ack_queue || - (qp->s_flags & IPATH_S_ACK_PENDING) || - qp->s_ack_state != OP(ACKNOWLEDGE)) && - ipath_make_rc_ack(dev, qp, ohdr, pmtu)) - goto done; - - if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK)) { - if (!(ib_ipath_state_ops[qp->state] & IPATH_FLUSH_SEND)) - goto bail; - /* We are in the error state, flush the work request. */ - if (qp->s_last == qp->s_head) - goto bail; - /* If DMAs are in progress, we can't flush immediately. */ - if (atomic_read(&qp->s_dma_busy)) { - qp->s_flags |= IPATH_S_WAIT_DMA; - goto bail; - } - wqe = get_swqe_ptr(qp, qp->s_last); - ipath_send_complete(qp, wqe, IB_WC_WR_FLUSH_ERR); - goto done; - } - - /* Leave BUSY set until RNR timeout. */ - if (qp->s_rnr_timeout) { - qp->s_flags |= IPATH_S_WAITING; - goto bail; - } - - /* header size in 32-bit words LRH+BTH = (8+12)/4. */ - hwords = 5; - bth0 = 1 << 22; /* Set M bit */ - - /* Send a request. */ - wqe = get_swqe_ptr(qp, qp->s_cur); - switch (qp->s_state) { - default: - if (!(ib_ipath_state_ops[qp->state] & - IPATH_PROCESS_NEXT_SEND_OK)) - goto bail; - /* - * Resend an old request or start a new one. - * - * We keep track of the current SWQE so that - * we don't reset the "furthest progress" state - * if we need to back up. - */ - newreq = 0; - if (qp->s_cur == qp->s_tail) { - /* Check if send work queue is empty. */ - if (qp->s_tail == qp->s_head) - goto bail; - /* - * If a fence is requested, wait for previous - * RDMA read and atomic operations to finish. - */ - if ((wqe->wr.send_flags & IB_SEND_FENCE) && - qp->s_num_rd_atomic) { - qp->s_flags |= IPATH_S_FENCE_PENDING; - goto bail; - } - wqe->psn = qp->s_next_psn; - newreq = 1; - } - /* - * Note that we have to be careful not to modify the - * original work request since we may need to resend - * it. - */ - len = wqe->length; - ss = &qp->s_sge; - bth2 = 0; - switch (wqe->wr.opcode) { - case IB_WR_SEND: - case IB_WR_SEND_WITH_IMM: - /* If no credit, return. */ - if (qp->s_lsn != (u32) -1 && - ipath_cmp24(wqe->ssn, qp->s_lsn + 1) > 0) { - qp->s_flags |= IPATH_S_WAIT_SSN_CREDIT; - goto bail; - } - wqe->lpsn = wqe->psn; - if (len > pmtu) { - wqe->lpsn += (len - 1) / pmtu; - qp->s_state = OP(SEND_FIRST); - len = pmtu; - break; - } - if (wqe->wr.opcode == IB_WR_SEND) - qp->s_state = OP(SEND_ONLY); - else { - qp->s_state = OP(SEND_ONLY_WITH_IMMEDIATE); - /* Immediate data comes after the BTH */ - ohdr->u.imm_data = wqe->wr.ex.imm_data; - hwords += 1; - } - if (wqe->wr.send_flags & IB_SEND_SOLICITED) - bth0 |= 1 << 23; - bth2 = 1 << 31; /* Request ACK. */ - if (++qp->s_cur == qp->s_size) - qp->s_cur = 0; - break; - - case IB_WR_RDMA_WRITE: - if (newreq && qp->s_lsn != (u32) -1) - qp->s_lsn++; - /* FALLTHROUGH */ - case IB_WR_RDMA_WRITE_WITH_IMM: - /* If no credit, return. */ - if (qp->s_lsn != (u32) -1 && - ipath_cmp24(wqe->ssn, qp->s_lsn + 1) > 0) { - qp->s_flags |= IPATH_S_WAIT_SSN_CREDIT; - goto bail; - } - ohdr->u.rc.reth.vaddr = - cpu_to_be64(wqe->rdma_wr.remote_addr); - ohdr->u.rc.reth.rkey = - cpu_to_be32(wqe->rdma_wr.rkey); - ohdr->u.rc.reth.length = cpu_to_be32(len); - hwords += sizeof(struct ib_reth) / sizeof(u32); - wqe->lpsn = wqe->psn; - if (len > pmtu) { - wqe->lpsn += (len - 1) / pmtu; - qp->s_state = OP(RDMA_WRITE_FIRST); - len = pmtu; - break; - } - if (wqe->wr.opcode == IB_WR_RDMA_WRITE) - qp->s_state = OP(RDMA_WRITE_ONLY); - else { - qp->s_state = - OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE); - /* Immediate data comes after RETH */ - ohdr->u.rc.imm_data = wqe->wr.ex.imm_data; - hwords += 1; - if (wqe->wr.send_flags & IB_SEND_SOLICITED) - bth0 |= 1 << 23; - } - bth2 = 1 << 31; /* Request ACK. */ - if (++qp->s_cur == qp->s_size) - qp->s_cur = 0; - break; - - case IB_WR_RDMA_READ: - /* - * Don't allow more operations to be started - * than the QP limits allow. - */ - if (newreq) { - if (qp->s_num_rd_atomic >= - qp->s_max_rd_atomic) { - qp->s_flags |= IPATH_S_RDMAR_PENDING; - goto bail; - } - qp->s_num_rd_atomic++; - if (qp->s_lsn != (u32) -1) - qp->s_lsn++; - /* - * Adjust s_next_psn to count the - * expected number of responses. - */ - if (len > pmtu) - qp->s_next_psn += (len - 1) / pmtu; - wqe->lpsn = qp->s_next_psn++; - } - ohdr->u.rc.reth.vaddr = - cpu_to_be64(wqe->rdma_wr.remote_addr); - ohdr->u.rc.reth.rkey = - cpu_to_be32(wqe->rdma_wr.rkey); - ohdr->u.rc.reth.length = cpu_to_be32(len); - qp->s_state = OP(RDMA_READ_REQUEST); - hwords += sizeof(ohdr->u.rc.reth) / sizeof(u32); - ss = NULL; - len = 0; - if (++qp->s_cur == qp->s_size) - qp->s_cur = 0; - break; - - case IB_WR_ATOMIC_CMP_AND_SWP: - case IB_WR_ATOMIC_FETCH_AND_ADD: - /* - * Don't allow more operations to be started - * than the QP limits allow. - */ - if (newreq) { - if (qp->s_num_rd_atomic >= - qp->s_max_rd_atomic) { - qp->s_flags |= IPATH_S_RDMAR_PENDING; - goto bail; - } - qp->s_num_rd_atomic++; - if (qp->s_lsn != (u32) -1) - qp->s_lsn++; - wqe->lpsn = wqe->psn; - } - if (wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP) { - qp->s_state = OP(COMPARE_SWAP); - ohdr->u.atomic_eth.swap_data = cpu_to_be64( - wqe->atomic_wr.swap); - ohdr->u.atomic_eth.compare_data = cpu_to_be64( - wqe->atomic_wr.compare_add); - } else { - qp->s_state = OP(FETCH_ADD); - ohdr->u.atomic_eth.swap_data = cpu_to_be64( - wqe->atomic_wr.compare_add); - ohdr->u.atomic_eth.compare_data = 0; - } - ohdr->u.atomic_eth.vaddr[0] = cpu_to_be32( - wqe->atomic_wr.remote_addr >> 32); - ohdr->u.atomic_eth.vaddr[1] = cpu_to_be32( - wqe->atomic_wr.remote_addr); - ohdr->u.atomic_eth.rkey = cpu_to_be32( - wqe->atomic_wr.rkey); - hwords += sizeof(struct ib_atomic_eth) / sizeof(u32); - ss = NULL; - len = 0; - if (++qp->s_cur == qp->s_size) - qp->s_cur = 0; - break; - - default: - goto bail; - } - qp->s_sge.sge = wqe->sg_list[0]; - qp->s_sge.sg_list = wqe->sg_list + 1; - qp->s_sge.num_sge = wqe->wr.num_sge; - qp->s_len = wqe->length; - if (newreq) { - qp->s_tail++; - if (qp->s_tail >= qp->s_size) - qp->s_tail = 0; - } - bth2 |= qp->s_psn & IPATH_PSN_MASK; - if (wqe->wr.opcode == IB_WR_RDMA_READ) - qp->s_psn = wqe->lpsn + 1; - else { - qp->s_psn++; - if (ipath_cmp24(qp->s_psn, qp->s_next_psn) > 0) - qp->s_next_psn = qp->s_psn; - } - /* - * Put the QP on the pending list so lost ACKs will cause - * a retry. More than one request can be pending so the - * QP may already be on the dev->pending list. - */ - spin_lock(&dev->pending_lock); - if (list_empty(&qp->timerwait)) - list_add_tail(&qp->timerwait, - &dev->pending[dev->pending_index]); - spin_unlock(&dev->pending_lock); - break; - - case OP(RDMA_READ_RESPONSE_FIRST): - /* - * This case can only happen if a send is restarted. - * See ipath_restart_rc(). - */ - ipath_init_restart(qp, wqe); - /* FALLTHROUGH */ - case OP(SEND_FIRST): - qp->s_state = OP(SEND_MIDDLE); - /* FALLTHROUGH */ - case OP(SEND_MIDDLE): - bth2 = qp->s_psn++ & IPATH_PSN_MASK; - if (ipath_cmp24(qp->s_psn, qp->s_next_psn) > 0) - qp->s_next_psn = qp->s_psn; - ss = &qp->s_sge; - len = qp->s_len; - if (len > pmtu) { - len = pmtu; - break; - } - if (wqe->wr.opcode == IB_WR_SEND) - qp->s_state = OP(SEND_LAST); - else { - qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE); - /* Immediate data comes after the BTH */ - ohdr->u.imm_data = wqe->wr.ex.imm_data; - hwords += 1; - } - if (wqe->wr.send_flags & IB_SEND_SOLICITED) - bth0 |= 1 << 23; - bth2 |= 1 << 31; /* Request ACK. */ - qp->s_cur++; - if (qp->s_cur >= qp->s_size) - qp->s_cur = 0; - break; - - case OP(RDMA_READ_RESPONSE_LAST): - /* - * This case can only happen if a RDMA write is restarted. - * See ipath_restart_rc(). - */ - ipath_init_restart(qp, wqe); - /* FALLTHROUGH */ - case OP(RDMA_WRITE_FIRST): - qp->s_state = OP(RDMA_WRITE_MIDDLE); - /* FALLTHROUGH */ - case OP(RDMA_WRITE_MIDDLE): - bth2 = qp->s_psn++ & IPATH_PSN_MASK; - if (ipath_cmp24(qp->s_psn, qp->s_next_psn) > 0) - qp->s_next_psn = qp->s_psn; - ss = &qp->s_sge; - len = qp->s_len; - if (len > pmtu) { - len = pmtu; - break; - } - if (wqe->wr.opcode == IB_WR_RDMA_WRITE) - qp->s_state = OP(RDMA_WRITE_LAST); - else { - qp->s_state = OP(RDMA_WRITE_LAST_WITH_IMMEDIATE); - /* Immediate data comes after the BTH */ - ohdr->u.imm_data = wqe->wr.ex.imm_data; - hwords += 1; - if (wqe->wr.send_flags & IB_SEND_SOLICITED) - bth0 |= 1 << 23; - } - bth2 |= 1 << 31; /* Request ACK. */ - qp->s_cur++; - if (qp->s_cur >= qp->s_size) - qp->s_cur = 0; - break; - - case OP(RDMA_READ_RESPONSE_MIDDLE): - /* - * This case can only happen if a RDMA read is restarted. - * See ipath_restart_rc(). - */ - ipath_init_restart(qp, wqe); - len = ((qp->s_psn - wqe->psn) & IPATH_PSN_MASK) * pmtu; - ohdr->u.rc.reth.vaddr = - cpu_to_be64(wqe->rdma_wr.remote_addr + len); - ohdr->u.rc.reth.rkey = - cpu_to_be32(wqe->rdma_wr.rkey); - ohdr->u.rc.reth.length = cpu_to_be32(qp->s_len); - qp->s_state = OP(RDMA_READ_REQUEST); - hwords += sizeof(ohdr->u.rc.reth) / sizeof(u32); - bth2 = qp->s_psn & IPATH_PSN_MASK; - qp->s_psn = wqe->lpsn + 1; - ss = NULL; - len = 0; - qp->s_cur++; - if (qp->s_cur == qp->s_size) - qp->s_cur = 0; - break; - } - if (ipath_cmp24(qp->s_psn, qp->s_last_psn + IPATH_PSN_CREDIT - 1) >= 0) - bth2 |= 1 << 31; /* Request ACK. */ - qp->s_len -= len; - qp->s_hdrwords = hwords; - qp->s_cur_sge = ss; - qp->s_cur_size = len; - ipath_make_ruc_header(dev, qp, ohdr, bth0 | (qp->s_state << 24), bth2); -done: - ret = 1; - goto unlock; - -bail: - qp->s_flags &= ~IPATH_S_BUSY; -unlock: - spin_unlock_irqrestore(&qp->s_lock, flags); - return ret; -} - -/** - * send_rc_ack - Construct an ACK packet and send it - * @qp: a pointer to the QP - * - * This is called from ipath_rc_rcv() and only uses the receive - * side QP state. - * Note that RDMA reads and atomics are handled in the - * send side QP state and tasklet. - */ -static void send_rc_ack(struct ipath_qp *qp) -{ - struct ipath_ibdev *dev = to_idev(qp->ibqp.device); - struct ipath_devdata *dd; - u16 lrh0; - u32 bth0; - u32 hwords; - u32 __iomem *piobuf; - struct ipath_ib_header hdr; - struct ipath_other_headers *ohdr; - unsigned long flags; - - spin_lock_irqsave(&qp->s_lock, flags); - - /* Don't send ACK or NAK if a RDMA read or atomic is pending. */ - if (qp->r_head_ack_queue != qp->s_tail_ack_queue || - (qp->s_flags & IPATH_S_ACK_PENDING) || - qp->s_ack_state != OP(ACKNOWLEDGE)) - goto queue_ack; - - spin_unlock_irqrestore(&qp->s_lock, flags); - - /* Don't try to send ACKs if the link isn't ACTIVE */ - dd = dev->dd; - if (!(dd->ipath_flags & IPATH_LINKACTIVE)) - goto done; - - piobuf = ipath_getpiobuf(dd, 0, NULL); - if (!piobuf) { - /* - * We are out of PIO buffers at the moment. - * Pass responsibility for sending the ACK to the - * send tasklet so that when a PIO buffer becomes - * available, the ACK is sent ahead of other outgoing - * packets. - */ - spin_lock_irqsave(&qp->s_lock, flags); - goto queue_ack; - } - - /* Construct the header. */ - ohdr = &hdr.u.oth; - lrh0 = IPATH_LRH_BTH; - /* header size in 32-bit words LRH+BTH+AETH = (8+12+4)/4. */ - hwords = 6; - if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) { - hwords += ipath_make_grh(dev, &hdr.u.l.grh, - &qp->remote_ah_attr.grh, - hwords, 0); - ohdr = &hdr.u.l.oth; - lrh0 = IPATH_LRH_GRH; - } - /* read pkey_index w/o lock (its atomic) */ - bth0 = ipath_get_pkey(dd, qp->s_pkey_index) | - (OP(ACKNOWLEDGE) << 24) | (1 << 22); - if (qp->r_nak_state) - ohdr->u.aeth = cpu_to_be32((qp->r_msn & IPATH_MSN_MASK) | - (qp->r_nak_state << - IPATH_AETH_CREDIT_SHIFT)); - else - ohdr->u.aeth = ipath_compute_aeth(qp); - lrh0 |= qp->remote_ah_attr.sl << 4; - hdr.lrh[0] = cpu_to_be16(lrh0); - hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid); - hdr.lrh[2] = cpu_to_be16(hwords + SIZE_OF_CRC); - hdr.lrh[3] = cpu_to_be16(dd->ipath_lid | - qp->remote_ah_attr.src_path_bits); - ohdr->bth[0] = cpu_to_be32(bth0); - ohdr->bth[1] = cpu_to_be32(qp->remote_qpn); - ohdr->bth[2] = cpu_to_be32(qp->r_ack_psn & IPATH_PSN_MASK); - - writeq(hwords + 1, piobuf); - - if (dd->ipath_flags & IPATH_PIO_FLUSH_WC) { - u32 *hdrp = (u32 *) &hdr; - - ipath_flush_wc(); - __iowrite32_copy(piobuf + 2, hdrp, hwords - 1); - ipath_flush_wc(); - __raw_writel(hdrp[hwords - 1], piobuf + hwords + 1); - } else - __iowrite32_copy(piobuf + 2, (u32 *) &hdr, hwords); - - ipath_flush_wc(); - - dev->n_unicast_xmit++; - goto done; - -queue_ack: - if (ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK) { - dev->n_rc_qacks++; - qp->s_flags |= IPATH_S_ACK_PENDING; - qp->s_nak_state = qp->r_nak_state; - qp->s_ack_psn = qp->r_ack_psn; - - /* Schedule the send tasklet. */ - ipath_schedule_send(qp); - } - spin_unlock_irqrestore(&qp->s_lock, flags); -done: - return; -} - -/** - * reset_psn - reset the QP state to send starting from PSN - * @qp: the QP - * @psn: the packet sequence number to restart at - * - * This is called from ipath_rc_rcv() to process an incoming RC ACK - * for the given QP. - * Called at interrupt level with the QP s_lock held. - */ -static void reset_psn(struct ipath_qp *qp, u32 psn) -{ - u32 n = qp->s_last; - struct ipath_swqe *wqe = get_swqe_ptr(qp, n); - u32 opcode; - - qp->s_cur = n; - - /* - * If we are starting the request from the beginning, - * let the normal send code handle initialization. - */ - if (ipath_cmp24(psn, wqe->psn) <= 0) { - qp->s_state = OP(SEND_LAST); - goto done; - } - - /* Find the work request opcode corresponding to the given PSN. */ - opcode = wqe->wr.opcode; - for (;;) { - int diff; - - if (++n == qp->s_size) - n = 0; - if (n == qp->s_tail) - break; - wqe = get_swqe_ptr(qp, n); - diff = ipath_cmp24(psn, wqe->psn); - if (diff < 0) - break; - qp->s_cur = n; - /* - * If we are starting the request from the beginning, - * let the normal send code handle initialization. - */ - if (diff == 0) { - qp->s_state = OP(SEND_LAST); - goto done; - } - opcode = wqe->wr.opcode; - } - - /* - * Set the state to restart in the middle of a request. - * Don't change the s_sge, s_cur_sge, or s_cur_size. - * See ipath_make_rc_req(). - */ - switch (opcode) { - case IB_WR_SEND: - case IB_WR_SEND_WITH_IMM: - qp->s_state = OP(RDMA_READ_RESPONSE_FIRST); - break; - - case IB_WR_RDMA_WRITE: - case IB_WR_RDMA_WRITE_WITH_IMM: - qp->s_state = OP(RDMA_READ_RESPONSE_LAST); - break; - - case IB_WR_RDMA_READ: - qp->s_state = OP(RDMA_READ_RESPONSE_MIDDLE); - break; - - default: - /* - * This case shouldn't happen since its only - * one PSN per req. - */ - qp->s_state = OP(SEND_LAST); - } -done: - qp->s_psn = psn; -} - -/** - * ipath_restart_rc - back up requester to resend the last un-ACKed request - * @qp: the QP to restart - * @psn: packet sequence number for the request - * @wc: the work completion request - * - * The QP s_lock should be held and interrupts disabled. - */ -void ipath_restart_rc(struct ipath_qp *qp, u32 psn) -{ - struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last); - struct ipath_ibdev *dev; - - if (qp->s_retry == 0) { - ipath_send_complete(qp, wqe, IB_WC_RETRY_EXC_ERR); - ipath_error_qp(qp, IB_WC_WR_FLUSH_ERR); - goto bail; - } - qp->s_retry--; - - /* - * Remove the QP from the timeout queue. - * Note: it may already have been removed by ipath_ib_timer(). - */ - dev = to_idev(qp->ibqp.device); - spin_lock(&dev->pending_lock); - if (!list_empty(&qp->timerwait)) - list_del_init(&qp->timerwait); - if (!list_empty(&qp->piowait)) - list_del_init(&qp->piowait); - spin_unlock(&dev->pending_lock); - - if (wqe->wr.opcode == IB_WR_RDMA_READ) - dev->n_rc_resends++; - else - dev->n_rc_resends += (qp->s_psn - psn) & IPATH_PSN_MASK; - - reset_psn(qp, psn); - ipath_schedule_send(qp); - -bail: - return; -} - -static inline void update_last_psn(struct ipath_qp *qp, u32 psn) -{ - qp->s_last_psn = psn; -} - -/** - * do_rc_ack - process an incoming RC ACK - * @qp: the QP the ACK came in on - * @psn: the packet sequence number of the ACK - * @opcode: the opcode of the request that resulted in the ACK - * - * This is called from ipath_rc_rcv_resp() to process an incoming RC ACK - * for the given QP. - * Called at interrupt level with the QP s_lock held and interrupts disabled. - * Returns 1 if OK, 0 if current operation should be aborted (NAK). - */ -static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode, - u64 val) -{ - struct ipath_ibdev *dev = to_idev(qp->ibqp.device); - struct ib_wc wc; - enum ib_wc_status status; - struct ipath_swqe *wqe; - int ret = 0; - u32 ack_psn; - int diff; - - /* - * Remove the QP from the timeout queue (or RNR timeout queue). - * If ipath_ib_timer() has already removed it, - * it's OK since we hold the QP s_lock and ipath_restart_rc() - * just won't find anything to restart if we ACK everything. - */ - spin_lock(&dev->pending_lock); - if (!list_empty(&qp->timerwait)) - list_del_init(&qp->timerwait); - spin_unlock(&dev->pending_lock); - - /* - * Note that NAKs implicitly ACK outstanding SEND and RDMA write - * requests and implicitly NAK RDMA read and atomic requests issued - * before the NAK'ed request. The MSN won't include the NAK'ed - * request but will include an ACK'ed request(s). - */ - ack_psn = psn; - if (aeth >> 29) - ack_psn--; - wqe = get_swqe_ptr(qp, qp->s_last); - - /* - * The MSN might be for a later WQE than the PSN indicates so - * only complete WQEs that the PSN finishes. - */ - while ((diff = ipath_cmp24(ack_psn, wqe->lpsn)) >= 0) { - /* - * RDMA_READ_RESPONSE_ONLY is a special case since - * we want to generate completion events for everything - * before the RDMA read, copy the data, then generate - * the completion for the read. - */ - if (wqe->wr.opcode == IB_WR_RDMA_READ && - opcode == OP(RDMA_READ_RESPONSE_ONLY) && - diff == 0) { - ret = 1; - goto bail; - } - /* - * If this request is a RDMA read or atomic, and the ACK is - * for a later operation, this ACK NAKs the RDMA read or - * atomic. In other words, only a RDMA_READ_LAST or ONLY - * can ACK a RDMA read and likewise for atomic ops. Note - * that the NAK case can only happen if relaxed ordering is - * used and requests are sent after an RDMA read or atomic - * is sent but before the response is received. - */ - if ((wqe->wr.opcode == IB_WR_RDMA_READ && - (opcode != OP(RDMA_READ_RESPONSE_LAST) || diff != 0)) || - ((wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || - wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) && - (opcode != OP(ATOMIC_ACKNOWLEDGE) || diff != 0))) { - /* - * The last valid PSN seen is the previous - * request's. - */ - update_last_psn(qp, wqe->psn - 1); - /* Retry this request. */ - ipath_restart_rc(qp, wqe->psn); - /* - * No need to process the ACK/NAK since we are - * restarting an earlier request. - */ - goto bail; - } - if (wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || - wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) - *(u64 *) wqe->sg_list[0].vaddr = val; - if (qp->s_num_rd_atomic && - (wqe->wr.opcode == IB_WR_RDMA_READ || - wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || - wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD)) { - qp->s_num_rd_atomic--; - /* Restart sending task if fence is complete */ - if (((qp->s_flags & IPATH_S_FENCE_PENDING) && - !qp->s_num_rd_atomic) || - qp->s_flags & IPATH_S_RDMAR_PENDING) - ipath_schedule_send(qp); - } - /* Post a send completion queue entry if requested. */ - if (!(qp->s_flags & IPATH_S_SIGNAL_REQ_WR) || - (wqe->wr.send_flags & IB_SEND_SIGNALED)) { - memset(&wc, 0, sizeof wc); - wc.wr_id = wqe->wr.wr_id; - wc.status = IB_WC_SUCCESS; - wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; - wc.byte_len = wqe->length; - wc.qp = &qp->ibqp; - wc.src_qp = qp->remote_qpn; - wc.slid = qp->remote_ah_attr.dlid; - wc.sl = qp->remote_ah_attr.sl; - ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 0); - } - qp->s_retry = qp->s_retry_cnt; - /* - * If we are completing a request which is in the process of - * being resent, we can stop resending it since we know the - * responder has already seen it. - */ - if (qp->s_last == qp->s_cur) { - if (++qp->s_cur >= qp->s_size) - qp->s_cur = 0; - qp->s_last = qp->s_cur; - if (qp->s_last == qp->s_tail) - break; - wqe = get_swqe_ptr(qp, qp->s_cur); - qp->s_state = OP(SEND_LAST); - qp->s_psn = wqe->psn; - } else { - if (++qp->s_last >= qp->s_size) - qp->s_last = 0; - if (qp->state == IB_QPS_SQD && qp->s_last == qp->s_cur) - qp->s_draining = 0; - if (qp->s_last == qp->s_tail) - break; - wqe = get_swqe_ptr(qp, qp->s_last); - } - } - - switch (aeth >> 29) { - case 0: /* ACK */ - dev->n_rc_acks++; - /* If this is a partial ACK, reset the retransmit timer. */ - if (qp->s_last != qp->s_tail) { - spin_lock(&dev->pending_lock); - if (list_empty(&qp->timerwait)) - list_add_tail(&qp->timerwait, - &dev->pending[dev->pending_index]); - spin_unlock(&dev->pending_lock); - /* - * If we get a partial ACK for a resent operation, - * we can stop resending the earlier packets and - * continue with the next packet the receiver wants. - */ - if (ipath_cmp24(qp->s_psn, psn) <= 0) { - reset_psn(qp, psn + 1); - ipath_schedule_send(qp); - } - } else if (ipath_cmp24(qp->s_psn, psn) <= 0) { - qp->s_state = OP(SEND_LAST); - qp->s_psn = psn + 1; - } - ipath_get_credit(qp, aeth); - qp->s_rnr_retry = qp->s_rnr_retry_cnt; - qp->s_retry = qp->s_retry_cnt; - update_last_psn(qp, psn); - ret = 1; - goto bail; - - case 1: /* RNR NAK */ - dev->n_rnr_naks++; - if (qp->s_last == qp->s_tail) - goto bail; - if (qp->s_rnr_retry == 0) { - status = IB_WC_RNR_RETRY_EXC_ERR; - goto class_b; - } - if (qp->s_rnr_retry_cnt < 7) - qp->s_rnr_retry--; - - /* The last valid PSN is the previous PSN. */ - update_last_psn(qp, psn - 1); - - if (wqe->wr.opcode == IB_WR_RDMA_READ) - dev->n_rc_resends++; - else - dev->n_rc_resends += - (qp->s_psn - psn) & IPATH_PSN_MASK; - - reset_psn(qp, psn); - - qp->s_rnr_timeout = - ib_ipath_rnr_table[(aeth >> IPATH_AETH_CREDIT_SHIFT) & - IPATH_AETH_CREDIT_MASK]; - ipath_insert_rnr_queue(qp); - ipath_schedule_send(qp); - goto bail; - - case 3: /* NAK */ - if (qp->s_last == qp->s_tail) - goto bail; - /* The last valid PSN is the previous PSN. */ - update_last_psn(qp, psn - 1); - switch ((aeth >> IPATH_AETH_CREDIT_SHIFT) & - IPATH_AETH_CREDIT_MASK) { - case 0: /* PSN sequence error */ - dev->n_seq_naks++; - /* - * Back up to the responder's expected PSN. - * Note that we might get a NAK in the middle of an - * RDMA READ response which terminates the RDMA - * READ. - */ - ipath_restart_rc(qp, psn); - break; - - case 1: /* Invalid Request */ - status = IB_WC_REM_INV_REQ_ERR; - dev->n_other_naks++; - goto class_b; - - case 2: /* Remote Access Error */ - status = IB_WC_REM_ACCESS_ERR; - dev->n_other_naks++; - goto class_b; - - case 3: /* Remote Operation Error */ - status = IB_WC_REM_OP_ERR; - dev->n_other_naks++; - class_b: - ipath_send_complete(qp, wqe, status); - ipath_error_qp(qp, IB_WC_WR_FLUSH_ERR); - break; - - default: - /* Ignore other reserved NAK error codes */ - goto reserved; - } - qp->s_rnr_retry = qp->s_rnr_retry_cnt; - goto bail; - - default: /* 2: reserved */ - reserved: - /* Ignore reserved NAK codes. */ - goto bail; - } - -bail: - return ret; -} - -/** - * ipath_rc_rcv_resp - process an incoming RC response packet - * @dev: the device this packet came in on - * @ohdr: the other headers for this packet - * @data: the packet data - * @tlen: the packet length - * @qp: the QP for this packet - * @opcode: the opcode for this packet - * @psn: the packet sequence number for this packet - * @hdrsize: the header length - * @pmtu: the path MTU - * @header_in_data: true if part of the header data is in the data buffer - * - * This is called from ipath_rc_rcv() to process an incoming RC response - * packet for the given QP. - * Called at interrupt level. - */ -static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, - struct ipath_other_headers *ohdr, - void *data, u32 tlen, - struct ipath_qp *qp, - u32 opcode, - u32 psn, u32 hdrsize, u32 pmtu, - int header_in_data) -{ - struct ipath_swqe *wqe; - enum ib_wc_status status; - unsigned long flags; - int diff; - u32 pad; - u32 aeth; - u64 val; - - spin_lock_irqsave(&qp->s_lock, flags); - - /* Double check we can process this now that we hold the s_lock. */ - if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) - goto ack_done; - - /* Ignore invalid responses. */ - if (ipath_cmp24(psn, qp->s_next_psn) >= 0) - goto ack_done; - - /* Ignore duplicate responses. */ - diff = ipath_cmp24(psn, qp->s_last_psn); - if (unlikely(diff <= 0)) { - /* Update credits for "ghost" ACKs */ - if (diff == 0 && opcode == OP(ACKNOWLEDGE)) { - if (!header_in_data) - aeth = be32_to_cpu(ohdr->u.aeth); - else { - aeth = be32_to_cpu(((__be32 *) data)[0]); - data += sizeof(__be32); - } - if ((aeth >> 29) == 0) - ipath_get_credit(qp, aeth); - } - goto ack_done; - } - - if (unlikely(qp->s_last == qp->s_tail)) - goto ack_done; - wqe = get_swqe_ptr(qp, qp->s_last); - status = IB_WC_SUCCESS; - - switch (opcode) { - case OP(ACKNOWLEDGE): - case OP(ATOMIC_ACKNOWLEDGE): - case OP(RDMA_READ_RESPONSE_FIRST): - if (!header_in_data) - aeth = be32_to_cpu(ohdr->u.aeth); - else { - aeth = be32_to_cpu(((__be32 *) data)[0]); - data += sizeof(__be32); - } - if (opcode == OP(ATOMIC_ACKNOWLEDGE)) { - if (!header_in_data) { - __be32 *p = ohdr->u.at.atomic_ack_eth; - - val = ((u64) be32_to_cpu(p[0]) << 32) | - be32_to_cpu(p[1]); - } else - val = be64_to_cpu(((__be64 *) data)[0]); - } else - val = 0; - if (!do_rc_ack(qp, aeth, psn, opcode, val) || - opcode != OP(RDMA_READ_RESPONSE_FIRST)) - goto ack_done; - hdrsize += 4; - wqe = get_swqe_ptr(qp, qp->s_last); - if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ)) - goto ack_op_err; - qp->r_flags &= ~IPATH_R_RDMAR_SEQ; - /* - * If this is a response to a resent RDMA read, we - * have to be careful to copy the data to the right - * location. - */ - qp->s_rdma_read_len = restart_sge(&qp->s_rdma_read_sge, - wqe, psn, pmtu); - goto read_middle; - - case OP(RDMA_READ_RESPONSE_MIDDLE): - /* no AETH, no ACK */ - if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) { - dev->n_rdma_seq++; - if (qp->r_flags & IPATH_R_RDMAR_SEQ) - goto ack_done; - qp->r_flags |= IPATH_R_RDMAR_SEQ; - ipath_restart_rc(qp, qp->s_last_psn + 1); - goto ack_done; - } - if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ)) - goto ack_op_err; - read_middle: - if (unlikely(tlen != (hdrsize + pmtu + 4))) - goto ack_len_err; - if (unlikely(pmtu >= qp->s_rdma_read_len)) - goto ack_len_err; - - /* We got a response so update the timeout. */ - spin_lock(&dev->pending_lock); - if (qp->s_rnr_timeout == 0 && !list_empty(&qp->timerwait)) - list_move_tail(&qp->timerwait, - &dev->pending[dev->pending_index]); - spin_unlock(&dev->pending_lock); - - if (opcode == OP(RDMA_READ_RESPONSE_MIDDLE)) - qp->s_retry = qp->s_retry_cnt; - - /* - * Update the RDMA receive state but do the copy w/o - * holding the locks and blocking interrupts. - */ - qp->s_rdma_read_len -= pmtu; - update_last_psn(qp, psn); - spin_unlock_irqrestore(&qp->s_lock, flags); - ipath_copy_sge(&qp->s_rdma_read_sge, data, pmtu); - goto bail; - - case OP(RDMA_READ_RESPONSE_ONLY): - if (!header_in_data) - aeth = be32_to_cpu(ohdr->u.aeth); - else - aeth = be32_to_cpu(((__be32 *) data)[0]); - if (!do_rc_ack(qp, aeth, psn, opcode, 0)) - goto ack_done; - /* Get the number of bytes the message was padded by. */ - pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3; - /* - * Check that the data size is >= 0 && <= pmtu. - * Remember to account for the AETH header (4) and - * ICRC (4). - */ - if (unlikely(tlen < (hdrsize + pad + 8))) - goto ack_len_err; - /* - * If this is a response to a resent RDMA read, we - * have to be careful to copy the data to the right - * location. - */ - wqe = get_swqe_ptr(qp, qp->s_last); - qp->s_rdma_read_len = restart_sge(&qp->s_rdma_read_sge, - wqe, psn, pmtu); - goto read_last; - - case OP(RDMA_READ_RESPONSE_LAST): - /* ACKs READ req. */ - if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) { - dev->n_rdma_seq++; - if (qp->r_flags & IPATH_R_RDMAR_SEQ) - goto ack_done; - qp->r_flags |= IPATH_R_RDMAR_SEQ; - ipath_restart_rc(qp, qp->s_last_psn + 1); - goto ack_done; - } - if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ)) - goto ack_op_err; - /* Get the number of bytes the message was padded by. */ - pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3; - /* - * Check that the data size is >= 1 && <= pmtu. - * Remember to account for the AETH header (4) and - * ICRC (4). - */ - if (unlikely(tlen <= (hdrsize + pad + 8))) - goto ack_len_err; - read_last: - tlen -= hdrsize + pad + 8; - if (unlikely(tlen != qp->s_rdma_read_len)) - goto ack_len_err; - if (!header_in_data) - aeth = be32_to_cpu(ohdr->u.aeth); - else { - aeth = be32_to_cpu(((__be32 *) data)[0]); - data += sizeof(__be32); - } - ipath_copy_sge(&qp->s_rdma_read_sge, data, tlen); - (void) do_rc_ack(qp, aeth, psn, - OP(RDMA_READ_RESPONSE_LAST), 0); - goto ack_done; - } - -ack_op_err: - status = IB_WC_LOC_QP_OP_ERR; - goto ack_err; - -ack_len_err: - status = IB_WC_LOC_LEN_ERR; -ack_err: - ipath_send_complete(qp, wqe, status); - ipath_error_qp(qp, IB_WC_WR_FLUSH_ERR); -ack_done: - spin_unlock_irqrestore(&qp->s_lock, flags); -bail: - return; -} - -/** - * ipath_rc_rcv_error - process an incoming duplicate or error RC packet - * @dev: the device this packet came in on - * @ohdr: the other headers for this packet - * @data: the packet data - * @qp: the QP for this packet - * @opcode: the opcode for this packet - * @psn: the packet sequence number for this packet - * @diff: the difference between the PSN and the expected PSN - * @header_in_data: true if part of the header data is in the data buffer - * - * This is called from ipath_rc_rcv() to process an unexpected - * incoming RC packet for the given QP. - * Called at interrupt level. - * Return 1 if no more processing is needed; otherwise return 0 to - * schedule a response to be sent. - */ -static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev, - struct ipath_other_headers *ohdr, - void *data, - struct ipath_qp *qp, - u32 opcode, - u32 psn, - int diff, - int header_in_data) -{ - struct ipath_ack_entry *e; - u8 i, prev; - int old_req; - unsigned long flags; - - if (diff > 0) { - /* - * Packet sequence error. - * A NAK will ACK earlier sends and RDMA writes. - * Don't queue the NAK if we already sent one. - */ - if (!qp->r_nak_state) { - qp->r_nak_state = IB_NAK_PSN_ERROR; - /* Use the expected PSN. */ - qp->r_ack_psn = qp->r_psn; - goto send_ack; - } - goto done; - } - - /* - * Handle a duplicate request. Don't re-execute SEND, RDMA - * write or atomic op. Don't NAK errors, just silently drop - * the duplicate request. Note that r_sge, r_len, and - * r_rcv_len may be in use so don't modify them. - * - * We are supposed to ACK the earliest duplicate PSN but we - * can coalesce an outstanding duplicate ACK. We have to - * send the earliest so that RDMA reads can be restarted at - * the requester's expected PSN. - * - * First, find where this duplicate PSN falls within the - * ACKs previously sent. - */ - psn &= IPATH_PSN_MASK; - e = NULL; - old_req = 1; - - spin_lock_irqsave(&qp->s_lock, flags); - /* Double check we can process this now that we hold the s_lock. */ - if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) - goto unlock_done; - - for (i = qp->r_head_ack_queue; ; i = prev) { - if (i == qp->s_tail_ack_queue) - old_req = 0; - if (i) - prev = i - 1; - else - prev = IPATH_MAX_RDMA_ATOMIC; - if (prev == qp->r_head_ack_queue) { - e = NULL; - break; - } - e = &qp->s_ack_queue[prev]; - if (!e->opcode) { - e = NULL; - break; - } - if (ipath_cmp24(psn, e->psn) >= 0) { - if (prev == qp->s_tail_ack_queue) - old_req = 0; - break; - } - } - switch (opcode) { - case OP(RDMA_READ_REQUEST): { - struct ib_reth *reth; - u32 offset; - u32 len; - - /* - * If we didn't find the RDMA read request in the ack queue, - * or the send tasklet is already backed up to send an - * earlier entry, we can ignore this request. - */ - if (!e || e->opcode != OP(RDMA_READ_REQUEST) || old_req) - goto unlock_done; - /* RETH comes after BTH */ - if (!header_in_data) - reth = &ohdr->u.rc.reth; - else { - reth = (struct ib_reth *)data; - data += sizeof(*reth); - } - /* - * Address range must be a subset of the original - * request and start on pmtu boundaries. - * We reuse the old ack_queue slot since the requester - * should not back up and request an earlier PSN for the - * same request. - */ - offset = ((psn - e->psn) & IPATH_PSN_MASK) * - ib_mtu_enum_to_int(qp->path_mtu); - len = be32_to_cpu(reth->length); - if (unlikely(offset + len > e->rdma_sge.sge.sge_length)) - goto unlock_done; - if (len != 0) { - u32 rkey = be32_to_cpu(reth->rkey); - u64 vaddr = be64_to_cpu(reth->vaddr); - int ok; - - ok = ipath_rkey_ok(qp, &e->rdma_sge, - len, vaddr, rkey, - IB_ACCESS_REMOTE_READ); - if (unlikely(!ok)) - goto unlock_done; - } else { - e->rdma_sge.sg_list = NULL; - e->rdma_sge.num_sge = 0; - e->rdma_sge.sge.mr = NULL; - e->rdma_sge.sge.vaddr = NULL; - e->rdma_sge.sge.length = 0; - e->rdma_sge.sge.sge_length = 0; - } - e->psn = psn; - qp->s_ack_state = OP(ACKNOWLEDGE); - qp->s_tail_ack_queue = prev; - break; - } - - case OP(COMPARE_SWAP): - case OP(FETCH_ADD): { - /* - * If we didn't find the atomic request in the ack queue - * or the send tasklet is already backed up to send an - * earlier entry, we can ignore this request. - */ - if (!e || e->opcode != (u8) opcode || old_req) - goto unlock_done; - qp->s_ack_state = OP(ACKNOWLEDGE); - qp->s_tail_ack_queue = prev; - break; - } - - default: - if (old_req) - goto unlock_done; - /* - * Resend the most recent ACK if this request is - * after all the previous RDMA reads and atomics. - */ - if (i == qp->r_head_ack_queue) { - spin_unlock_irqrestore(&qp->s_lock, flags); - qp->r_nak_state = 0; - qp->r_ack_psn = qp->r_psn - 1; - goto send_ack; - } - /* - * Try to send a simple ACK to work around a Mellanox bug - * which doesn't accept a RDMA read response or atomic - * response as an ACK for earlier SENDs or RDMA writes. - */ - if (qp->r_head_ack_queue == qp->s_tail_ack_queue && - !(qp->s_flags & IPATH_S_ACK_PENDING) && - qp->s_ack_state == OP(ACKNOWLEDGE)) { - spin_unlock_irqrestore(&qp->s_lock, flags); - qp->r_nak_state = 0; - qp->r_ack_psn = qp->s_ack_queue[i].psn - 1; - goto send_ack; - } - /* - * Resend the RDMA read or atomic op which - * ACKs this duplicate request. - */ - qp->s_ack_state = OP(ACKNOWLEDGE); - qp->s_tail_ack_queue = i; - break; - } - qp->r_nak_state = 0; - ipath_schedule_send(qp); - -unlock_done: - spin_unlock_irqrestore(&qp->s_lock, flags); -done: - return 1; - -send_ack: - return 0; -} - -void ipath_rc_error(struct ipath_qp *qp, enum ib_wc_status err) -{ - unsigned long flags; - int lastwqe; - - spin_lock_irqsave(&qp->s_lock, flags); - lastwqe = ipath_error_qp(qp, err); - spin_unlock_irqrestore(&qp->s_lock, flags); - - if (lastwqe) { - struct ib_event ev; - - ev.device = qp->ibqp.device; - ev.element.qp = &qp->ibqp; - ev.event = IB_EVENT_QP_LAST_WQE_REACHED; - qp->ibqp.event_handler(&ev, qp->ibqp.qp_context); - } -} - -static inline void ipath_update_ack_queue(struct ipath_qp *qp, unsigned n) -{ - unsigned next; - - next = n + 1; - if (next > IPATH_MAX_RDMA_ATOMIC) - next = 0; - if (n == qp->s_tail_ack_queue) { - qp->s_tail_ack_queue = next; - qp->s_ack_state = OP(ACKNOWLEDGE); - } -} - -/** - * ipath_rc_rcv - process an incoming RC packet - * @dev: the device this packet came in on - * @hdr: the header of this packet - * @has_grh: true if the header has a GRH - * @data: the packet data - * @tlen: the packet length - * @qp: the QP for this packet - * - * This is called from ipath_qp_rcv() to process an incoming RC packet - * for the given QP. - * Called at interrupt level. - */ -void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, - int has_grh, void *data, u32 tlen, struct ipath_qp *qp) -{ - struct ipath_other_headers *ohdr; - u32 opcode; - u32 hdrsize; - u32 psn; - u32 pad; - struct ib_wc wc; - u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu); - int diff; - struct ib_reth *reth; - int header_in_data; - unsigned long flags; - - /* Validate the SLID. See Ch. 9.6.1.5 */ - if (unlikely(be16_to_cpu(hdr->lrh[3]) != qp->remote_ah_attr.dlid)) - goto done; - - /* Check for GRH */ - if (!has_grh) { - ohdr = &hdr->u.oth; - hdrsize = 8 + 12; /* LRH + BTH */ - psn = be32_to_cpu(ohdr->bth[2]); - header_in_data = 0; - } else { - ohdr = &hdr->u.l.oth; - hdrsize = 8 + 40 + 12; /* LRH + GRH + BTH */ - /* - * The header with GRH is 60 bytes and the core driver sets - * the eager header buffer size to 56 bytes so the last 4 - * bytes of the BTH header (PSN) is in the data buffer. - */ - header_in_data = dev->dd->ipath_rcvhdrentsize == 16; - if (header_in_data) { - psn = be32_to_cpu(((__be32 *) data)[0]); - data += sizeof(__be32); - } else - psn = be32_to_cpu(ohdr->bth[2]); - } - - /* - * Process responses (ACKs) before anything else. Note that the - * packet sequence number will be for something in the send work - * queue rather than the expected receive packet sequence number. - * In other words, this QP is the requester. - */ - opcode = be32_to_cpu(ohdr->bth[0]) >> 24; - if (opcode >= OP(RDMA_READ_RESPONSE_FIRST) && - opcode <= OP(ATOMIC_ACKNOWLEDGE)) { - ipath_rc_rcv_resp(dev, ohdr, data, tlen, qp, opcode, psn, - hdrsize, pmtu, header_in_data); - goto done; - } - - /* Compute 24 bits worth of difference. */ - diff = ipath_cmp24(psn, qp->r_psn); - if (unlikely(diff)) { - if (ipath_rc_rcv_error(dev, ohdr, data, qp, opcode, - psn, diff, header_in_data)) - goto done; - goto send_ack; - } - - /* Check for opcode sequence errors. */ - switch (qp->r_state) { - case OP(SEND_FIRST): - case OP(SEND_MIDDLE): - if (opcode == OP(SEND_MIDDLE) || - opcode == OP(SEND_LAST) || - opcode == OP(SEND_LAST_WITH_IMMEDIATE)) - break; - goto nack_inv; - - case OP(RDMA_WRITE_FIRST): - case OP(RDMA_WRITE_MIDDLE): - if (opcode == OP(RDMA_WRITE_MIDDLE) || - opcode == OP(RDMA_WRITE_LAST) || - opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE)) - break; - goto nack_inv; - - default: - if (opcode == OP(SEND_MIDDLE) || - opcode == OP(SEND_LAST) || - opcode == OP(SEND_LAST_WITH_IMMEDIATE) || - opcode == OP(RDMA_WRITE_MIDDLE) || - opcode == OP(RDMA_WRITE_LAST) || - opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE)) - goto nack_inv; - /* - * Note that it is up to the requester to not send a new - * RDMA read or atomic operation before receiving an ACK - * for the previous operation. - */ - break; - } - - memset(&wc, 0, sizeof wc); - - /* OK, process the packet. */ - switch (opcode) { - case OP(SEND_FIRST): - if (!ipath_get_rwqe(qp, 0)) - goto rnr_nak; - qp->r_rcv_len = 0; - /* FALLTHROUGH */ - case OP(SEND_MIDDLE): - case OP(RDMA_WRITE_MIDDLE): - send_middle: - /* Check for invalid length PMTU or posted rwqe len. */ - if (unlikely(tlen != (hdrsize + pmtu + 4))) - goto nack_inv; - qp->r_rcv_len += pmtu; - if (unlikely(qp->r_rcv_len > qp->r_len)) - goto nack_inv; - ipath_copy_sge(&qp->r_sge, data, pmtu); - break; - - case OP(RDMA_WRITE_LAST_WITH_IMMEDIATE): - /* consume RWQE */ - if (!ipath_get_rwqe(qp, 1)) - goto rnr_nak; - goto send_last_imm; - - case OP(SEND_ONLY): - case OP(SEND_ONLY_WITH_IMMEDIATE): - if (!ipath_get_rwqe(qp, 0)) - goto rnr_nak; - qp->r_rcv_len = 0; - if (opcode == OP(SEND_ONLY)) - goto send_last; - /* FALLTHROUGH */ - case OP(SEND_LAST_WITH_IMMEDIATE): - send_last_imm: - if (header_in_data) { - wc.ex.imm_data = *(__be32 *) data; - data += sizeof(__be32); - } else { - /* Immediate data comes after BTH */ - wc.ex.imm_data = ohdr->u.imm_data; - } - hdrsize += 4; - wc.wc_flags = IB_WC_WITH_IMM; - /* FALLTHROUGH */ - case OP(SEND_LAST): - case OP(RDMA_WRITE_LAST): - send_last: - /* Get the number of bytes the message was padded by. */ - pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3; - /* Check for invalid length. */ - /* XXX LAST len should be >= 1 */ - if (unlikely(tlen < (hdrsize + pad + 4))) - goto nack_inv; - /* Don't count the CRC. */ - tlen -= (hdrsize + pad + 4); - wc.byte_len = tlen + qp->r_rcv_len; - if (unlikely(wc.byte_len > qp->r_len)) - goto nack_inv; - ipath_copy_sge(&qp->r_sge, data, tlen); - qp->r_msn++; - if (!test_and_clear_bit(IPATH_R_WRID_VALID, &qp->r_aflags)) - break; - wc.wr_id = qp->r_wr_id; - wc.status = IB_WC_SUCCESS; - if (opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE) || - opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE)) - wc.opcode = IB_WC_RECV_RDMA_WITH_IMM; - else - wc.opcode = IB_WC_RECV; - wc.qp = &qp->ibqp; - wc.src_qp = qp->remote_qpn; - wc.slid = qp->remote_ah_attr.dlid; - wc.sl = qp->remote_ah_attr.sl; - /* Signal completion event if the solicited bit is set. */ - ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, - (ohdr->bth[0] & - cpu_to_be32(1 << 23)) != 0); - break; - - case OP(RDMA_WRITE_FIRST): - case OP(RDMA_WRITE_ONLY): - case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE): - if (unlikely(!(qp->qp_access_flags & - IB_ACCESS_REMOTE_WRITE))) - goto nack_inv; - /* consume RWQE */ - /* RETH comes after BTH */ - if (!header_in_data) - reth = &ohdr->u.rc.reth; - else { - reth = (struct ib_reth *)data; - data += sizeof(*reth); - } - hdrsize += sizeof(*reth); - qp->r_len = be32_to_cpu(reth->length); - qp->r_rcv_len = 0; - if (qp->r_len != 0) { - u32 rkey = be32_to_cpu(reth->rkey); - u64 vaddr = be64_to_cpu(reth->vaddr); - int ok; - - /* Check rkey & NAK */ - ok = ipath_rkey_ok(qp, &qp->r_sge, - qp->r_len, vaddr, rkey, - IB_ACCESS_REMOTE_WRITE); - if (unlikely(!ok)) - goto nack_acc; - } else { - qp->r_sge.sg_list = NULL; - qp->r_sge.sge.mr = NULL; - qp->r_sge.sge.vaddr = NULL; - qp->r_sge.sge.length = 0; - qp->r_sge.sge.sge_length = 0; - } - if (opcode == OP(RDMA_WRITE_FIRST)) - goto send_middle; - else if (opcode == OP(RDMA_WRITE_ONLY)) - goto send_last; - if (!ipath_get_rwqe(qp, 1)) - goto rnr_nak; - goto send_last_imm; - - case OP(RDMA_READ_REQUEST): { - struct ipath_ack_entry *e; - u32 len; - u8 next; - - if (unlikely(!(qp->qp_access_flags & - IB_ACCESS_REMOTE_READ))) - goto nack_inv; - next = qp->r_head_ack_queue + 1; - if (next > IPATH_MAX_RDMA_ATOMIC) - next = 0; - spin_lock_irqsave(&qp->s_lock, flags); - /* Double check we can process this while holding the s_lock. */ - if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) - goto unlock; - if (unlikely(next == qp->s_tail_ack_queue)) { - if (!qp->s_ack_queue[next].sent) - goto nack_inv_unlck; - ipath_update_ack_queue(qp, next); - } - e = &qp->s_ack_queue[qp->r_head_ack_queue]; - /* RETH comes after BTH */ - if (!header_in_data) - reth = &ohdr->u.rc.reth; - else { - reth = (struct ib_reth *)data; - data += sizeof(*reth); - } - len = be32_to_cpu(reth->length); - if (len) { - u32 rkey = be32_to_cpu(reth->rkey); - u64 vaddr = be64_to_cpu(reth->vaddr); - int ok; - - /* Check rkey & NAK */ - ok = ipath_rkey_ok(qp, &e->rdma_sge, len, vaddr, - rkey, IB_ACCESS_REMOTE_READ); - if (unlikely(!ok)) - goto nack_acc_unlck; - /* - * Update the next expected PSN. We add 1 later - * below, so only add the remainder here. - */ - if (len > pmtu) - qp->r_psn += (len - 1) / pmtu; - } else { - e->rdma_sge.sg_list = NULL; - e->rdma_sge.num_sge = 0; - e->rdma_sge.sge.mr = NULL; - e->rdma_sge.sge.vaddr = NULL; - e->rdma_sge.sge.length = 0; - e->rdma_sge.sge.sge_length = 0; - } - e->opcode = opcode; - e->sent = 0; - e->psn = psn; - /* - * We need to increment the MSN here instead of when we - * finish sending the result since a duplicate request would - * increment it more than once. - */ - qp->r_msn++; - qp->r_psn++; - qp->r_state = opcode; - qp->r_nak_state = 0; - qp->r_head_ack_queue = next; - - /* Schedule the send tasklet. */ - ipath_schedule_send(qp); - - goto unlock; - } - - case OP(COMPARE_SWAP): - case OP(FETCH_ADD): { - struct ib_atomic_eth *ateth; - struct ipath_ack_entry *e; - u64 vaddr; - atomic64_t *maddr; - u64 sdata; - u32 rkey; - u8 next; - - if (unlikely(!(qp->qp_access_flags & - IB_ACCESS_REMOTE_ATOMIC))) - goto nack_inv; - next = qp->r_head_ack_queue + 1; - if (next > IPATH_MAX_RDMA_ATOMIC) - next = 0; - spin_lock_irqsave(&qp->s_lock, flags); - /* Double check we can process this while holding the s_lock. */ - if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) - goto unlock; - if (unlikely(next == qp->s_tail_ack_queue)) { - if (!qp->s_ack_queue[next].sent) - goto nack_inv_unlck; - ipath_update_ack_queue(qp, next); - } - if (!header_in_data) - ateth = &ohdr->u.atomic_eth; - else - ateth = (struct ib_atomic_eth *)data; - vaddr = ((u64) be32_to_cpu(ateth->vaddr[0]) << 32) | - be32_to_cpu(ateth->vaddr[1]); - if (unlikely(vaddr & (sizeof(u64) - 1))) - goto nack_inv_unlck; - rkey = be32_to_cpu(ateth->rkey); - /* Check rkey & NAK */ - if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, - sizeof(u64), vaddr, rkey, - IB_ACCESS_REMOTE_ATOMIC))) - goto nack_acc_unlck; - /* Perform atomic OP and save result. */ - maddr = (atomic64_t *) qp->r_sge.sge.vaddr; - sdata = be64_to_cpu(ateth->swap_data); - e = &qp->s_ack_queue[qp->r_head_ack_queue]; - e->atomic_data = (opcode == OP(FETCH_ADD)) ? - (u64) atomic64_add_return(sdata, maddr) - sdata : - (u64) cmpxchg((u64 *) qp->r_sge.sge.vaddr, - be64_to_cpu(ateth->compare_data), - sdata); - e->opcode = opcode; - e->sent = 0; - e->psn = psn & IPATH_PSN_MASK; - qp->r_msn++; - qp->r_psn++; - qp->r_state = opcode; - qp->r_nak_state = 0; - qp->r_head_ack_queue = next; - - /* Schedule the send tasklet. */ - ipath_schedule_send(qp); - - goto unlock; - } - - default: - /* NAK unknown opcodes. */ - goto nack_inv; - } - qp->r_psn++; - qp->r_state = opcode; - qp->r_ack_psn = psn; - qp->r_nak_state = 0; - /* Send an ACK if requested or required. */ - if (psn & (1 << 31)) - goto send_ack; - goto done; - -rnr_nak: - qp->r_nak_state = IB_RNR_NAK | qp->r_min_rnr_timer; - qp->r_ack_psn = qp->r_psn; - goto send_ack; - -nack_inv_unlck: - spin_unlock_irqrestore(&qp->s_lock, flags); -nack_inv: - ipath_rc_error(qp, IB_WC_LOC_QP_OP_ERR); - qp->r_nak_state = IB_NAK_INVALID_REQUEST; - qp->r_ack_psn = qp->r_psn; - goto send_ack; - -nack_acc_unlck: - spin_unlock_irqrestore(&qp->s_lock, flags); -nack_acc: - ipath_rc_error(qp, IB_WC_LOC_PROT_ERR); - qp->r_nak_state = IB_NAK_REMOTE_ACCESS_ERROR; - qp->r_ack_psn = qp->r_psn; -send_ack: - send_rc_ack(qp); - goto done; - -unlock: - spin_unlock_irqrestore(&qp->s_lock, flags); -done: - return; -} diff --git a/drivers/staging/rdma/ipath/ipath_registers.h b/drivers/staging/rdma/ipath/ipath_registers.h deleted file mode 100644 index 8f44d0cf3833..000000000000 --- a/drivers/staging/rdma/ipath/ipath_registers.h +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. - * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _IPATH_REGISTERS_H -#define _IPATH_REGISTERS_H - -/* - * This file should only be included by kernel source, and by the diags. It - * defines the registers, and their contents, for InfiniPath chips. - */ - -/* - * These are the InfiniPath register and buffer bit definitions, - * that are visible to software, and needed only by the kernel - * and diag code. A few, that are visible to protocol and user - * code are in ipath_common.h. Some bits are specific - * to a given chip implementation, and have been moved to the - * chip-specific source file - */ - -/* kr_revision bits */ -#define INFINIPATH_R_CHIPREVMINOR_MASK 0xFF -#define INFINIPATH_R_CHIPREVMINOR_SHIFT 0 -#define INFINIPATH_R_CHIPREVMAJOR_MASK 0xFF -#define INFINIPATH_R_CHIPREVMAJOR_SHIFT 8 -#define INFINIPATH_R_ARCH_MASK 0xFF -#define INFINIPATH_R_ARCH_SHIFT 16 -#define INFINIPATH_R_SOFTWARE_MASK 0xFF -#define INFINIPATH_R_SOFTWARE_SHIFT 24 -#define INFINIPATH_R_BOARDID_MASK 0xFF -#define INFINIPATH_R_BOARDID_SHIFT 32 - -/* kr_control bits */ -#define INFINIPATH_C_FREEZEMODE 0x00000002 -#define INFINIPATH_C_LINKENABLE 0x00000004 - -/* kr_sendctrl bits */ -#define INFINIPATH_S_DISARMPIOBUF_SHIFT 16 -#define INFINIPATH_S_UPDTHRESH_SHIFT 24 -#define INFINIPATH_S_UPDTHRESH_MASK 0x1f - -#define IPATH_S_ABORT 0 -#define IPATH_S_PIOINTBUFAVAIL 1 -#define IPATH_S_PIOBUFAVAILUPD 2 -#define IPATH_S_PIOENABLE 3 -#define IPATH_S_SDMAINTENABLE 9 -#define IPATH_S_SDMASINGLEDESCRIPTOR 10 -#define IPATH_S_SDMAENABLE 11 -#define IPATH_S_SDMAHALT 12 -#define IPATH_S_DISARM 31 - -#define INFINIPATH_S_ABORT (1U << IPATH_S_ABORT) -#define INFINIPATH_S_PIOINTBUFAVAIL (1U << IPATH_S_PIOINTBUFAVAIL) -#define INFINIPATH_S_PIOBUFAVAILUPD (1U << IPATH_S_PIOBUFAVAILUPD) -#define INFINIPATH_S_PIOENABLE (1U << IPATH_S_PIOENABLE) -#define INFINIPATH_S_SDMAINTENABLE (1U << IPATH_S_SDMAINTENABLE) -#define INFINIPATH_S_SDMASINGLEDESCRIPTOR \ - (1U << IPATH_S_SDMASINGLEDESCRIPTOR) -#define INFINIPATH_S_SDMAENABLE (1U << IPATH_S_SDMAENABLE) -#define INFINIPATH_S_SDMAHALT (1U << IPATH_S_SDMAHALT) -#define INFINIPATH_S_DISARM (1U << IPATH_S_DISARM) - -/* kr_rcvctrl bits that are the same on multiple chips */ -#define INFINIPATH_R_PORTENABLE_SHIFT 0 -#define INFINIPATH_R_QPMAP_ENABLE (1ULL << 38) - -/* kr_intstatus, kr_intclear, kr_intmask bits */ -#define INFINIPATH_I_SDMAINT 0x8000000000000000ULL -#define INFINIPATH_I_SDMADISABLED 0x4000000000000000ULL -#define INFINIPATH_I_ERROR 0x0000000080000000ULL -#define INFINIPATH_I_SPIOSENT 0x0000000040000000ULL -#define INFINIPATH_I_SPIOBUFAVAIL 0x0000000020000000ULL -#define INFINIPATH_I_GPIO 0x0000000010000000ULL -#define INFINIPATH_I_JINT 0x0000000004000000ULL - -/* kr_errorstatus, kr_errorclear, kr_errormask bits */ -#define INFINIPATH_E_RFORMATERR 0x0000000000000001ULL -#define INFINIPATH_E_RVCRC 0x0000000000000002ULL -#define INFINIPATH_E_RICRC 0x0000000000000004ULL -#define INFINIPATH_E_RMINPKTLEN 0x0000000000000008ULL -#define INFINIPATH_E_RMAXPKTLEN 0x0000000000000010ULL -#define INFINIPATH_E_RLONGPKTLEN 0x0000000000000020ULL -#define INFINIPATH_E_RSHORTPKTLEN 0x0000000000000040ULL -#define INFINIPATH_E_RUNEXPCHAR 0x0000000000000080ULL -#define INFINIPATH_E_RUNSUPVL 0x0000000000000100ULL -#define INFINIPATH_E_REBP 0x0000000000000200ULL -#define INFINIPATH_E_RIBFLOW 0x0000000000000400ULL -#define INFINIPATH_E_RBADVERSION 0x0000000000000800ULL -#define INFINIPATH_E_RRCVEGRFULL 0x0000000000001000ULL -#define INFINIPATH_E_RRCVHDRFULL 0x0000000000002000ULL -#define INFINIPATH_E_RBADTID 0x0000000000004000ULL -#define INFINIPATH_E_RHDRLEN 0x0000000000008000ULL -#define INFINIPATH_E_RHDR 0x0000000000010000ULL -#define INFINIPATH_E_RIBLOSTLINK 0x0000000000020000ULL -#define INFINIPATH_E_SENDSPECIALTRIGGER 0x0000000008000000ULL -#define INFINIPATH_E_SDMADISABLED 0x0000000010000000ULL -#define INFINIPATH_E_SMINPKTLEN 0x0000000020000000ULL -#define INFINIPATH_E_SMAXPKTLEN 0x0000000040000000ULL -#define INFINIPATH_E_SUNDERRUN 0x0000000080000000ULL -#define INFINIPATH_E_SPKTLEN 0x0000000100000000ULL -#define INFINIPATH_E_SDROPPEDSMPPKT 0x0000000200000000ULL -#define INFINIPATH_E_SDROPPEDDATAPKT 0x0000000400000000ULL -#define INFINIPATH_E_SPIOARMLAUNCH 0x0000000800000000ULL -#define INFINIPATH_E_SUNEXPERRPKTNUM 0x0000001000000000ULL -#define INFINIPATH_E_SUNSUPVL 0x0000002000000000ULL -#define INFINIPATH_E_SENDBUFMISUSE 0x0000004000000000ULL -#define INFINIPATH_E_SDMAGENMISMATCH 0x0000008000000000ULL -#define INFINIPATH_E_SDMAOUTOFBOUND 0x0000010000000000ULL -#define INFINIPATH_E_SDMATAILOUTOFBOUND 0x0000020000000000ULL -#define INFINIPATH_E_SDMABASE 0x0000040000000000ULL -#define INFINIPATH_E_SDMA1STDESC 0x0000080000000000ULL -#define INFINIPATH_E_SDMARPYTAG 0x0000100000000000ULL -#define INFINIPATH_E_SDMADWEN 0x0000200000000000ULL -#define INFINIPATH_E_SDMAMISSINGDW 0x0000400000000000ULL -#define INFINIPATH_E_SDMAUNEXPDATA 0x0000800000000000ULL -#define INFINIPATH_E_IBSTATUSCHANGED 0x0001000000000000ULL -#define INFINIPATH_E_INVALIDADDR 0x0002000000000000ULL -#define INFINIPATH_E_RESET 0x0004000000000000ULL -#define INFINIPATH_E_HARDWARE 0x0008000000000000ULL -#define INFINIPATH_E_SDMADESCADDRMISALIGN 0x0010000000000000ULL -#define INFINIPATH_E_INVALIDEEPCMD 0x0020000000000000ULL - -/* - * this is used to print "common" packet errors only when the - * __IPATH_ERRPKTDBG bit is set in ipath_debug. - */ -#define INFINIPATH_E_PKTERRS ( INFINIPATH_E_SPKTLEN \ - | INFINIPATH_E_SDROPPEDDATAPKT | INFINIPATH_E_RVCRC \ - | INFINIPATH_E_RICRC | INFINIPATH_E_RSHORTPKTLEN \ - | INFINIPATH_E_REBP ) - -/* Convenience for decoding Send DMA errors */ -#define INFINIPATH_E_SDMAERRS ( \ - INFINIPATH_E_SDMAGENMISMATCH | INFINIPATH_E_SDMAOUTOFBOUND | \ - INFINIPATH_E_SDMATAILOUTOFBOUND | INFINIPATH_E_SDMABASE | \ - INFINIPATH_E_SDMA1STDESC | INFINIPATH_E_SDMARPYTAG | \ - INFINIPATH_E_SDMADWEN | INFINIPATH_E_SDMAMISSINGDW | \ - INFINIPATH_E_SDMAUNEXPDATA | \ - INFINIPATH_E_SDMADESCADDRMISALIGN | \ - INFINIPATH_E_SDMADISABLED | \ - INFINIPATH_E_SENDBUFMISUSE) - -/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */ -/* TXEMEMPARITYERR bit 0: PIObuf, 1: PIOpbc, 2: launchfifo - * RXEMEMPARITYERR bit 0: rcvbuf, 1: lookupq, 2: expTID, 3: eagerTID - * bit 4: flag buffer, 5: datainfo, 6: header info */ -#define INFINIPATH_HWE_TXEMEMPARITYERR_MASK 0xFULL -#define INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT 40 -#define INFINIPATH_HWE_RXEMEMPARITYERR_MASK 0x7FULL -#define INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT 44 -#define INFINIPATH_HWE_IBCBUSTOSPCPARITYERR 0x4000000000000000ULL -#define INFINIPATH_HWE_IBCBUSFRSPCPARITYERR 0x8000000000000000ULL -/* txe mem parity errors (shift by INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) */ -#define INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF 0x1ULL -#define INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC 0x2ULL -#define INFINIPATH_HWE_TXEMEMPARITYERR_PIOLAUNCHFIFO 0x4ULL -/* rxe mem parity errors (shift by INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) */ -#define INFINIPATH_HWE_RXEMEMPARITYERR_RCVBUF 0x01ULL -#define INFINIPATH_HWE_RXEMEMPARITYERR_LOOKUPQ 0x02ULL -#define INFINIPATH_HWE_RXEMEMPARITYERR_EXPTID 0x04ULL -#define INFINIPATH_HWE_RXEMEMPARITYERR_EAGERTID 0x08ULL -#define INFINIPATH_HWE_RXEMEMPARITYERR_FLAGBUF 0x10ULL -#define INFINIPATH_HWE_RXEMEMPARITYERR_DATAINFO 0x20ULL -#define INFINIPATH_HWE_RXEMEMPARITYERR_HDRINFO 0x40ULL -/* waldo specific -- find the rest in ipath_6110.c */ -#define INFINIPATH_HWE_RXDSYNCMEMPARITYERR 0x0000000400000000ULL -/* 6120/7220 specific -- find the rest in ipath_6120.c and ipath_7220.c */ -#define INFINIPATH_HWE_MEMBISTFAILED 0x0040000000000000ULL - -/* kr_hwdiagctrl bits */ -#define INFINIPATH_DC_FORCETXEMEMPARITYERR_MASK 0xFULL -#define INFINIPATH_DC_FORCETXEMEMPARITYERR_SHIFT 40 -#define INFINIPATH_DC_FORCERXEMEMPARITYERR_MASK 0x7FULL -#define INFINIPATH_DC_FORCERXEMEMPARITYERR_SHIFT 44 -#define INFINIPATH_DC_FORCERXDSYNCMEMPARITYERR 0x0000000400000000ULL -#define INFINIPATH_DC_COUNTERDISABLE 0x1000000000000000ULL -#define INFINIPATH_DC_COUNTERWREN 0x2000000000000000ULL -#define INFINIPATH_DC_FORCEIBCBUSTOSPCPARITYERR 0x4000000000000000ULL -#define INFINIPATH_DC_FORCEIBCBUSFRSPCPARITYERR 0x8000000000000000ULL - -/* kr_ibcctrl bits */ -#define INFINIPATH_IBCC_FLOWCTRLPERIOD_MASK 0xFFULL -#define INFINIPATH_IBCC_FLOWCTRLPERIOD_SHIFT 0 -#define INFINIPATH_IBCC_FLOWCTRLWATERMARK_MASK 0xFFULL -#define INFINIPATH_IBCC_FLOWCTRLWATERMARK_SHIFT 8 -#define INFINIPATH_IBCC_LINKINITCMD_MASK 0x3ULL -#define INFINIPATH_IBCC_LINKINITCMD_DISABLE 1 -/* cycle through TS1/TS2 till OK */ -#define INFINIPATH_IBCC_LINKINITCMD_POLL 2 -/* wait for TS1, then go on */ -#define INFINIPATH_IBCC_LINKINITCMD_SLEEP 3 -#define INFINIPATH_IBCC_LINKINITCMD_SHIFT 16 -#define INFINIPATH_IBCC_LINKCMD_MASK 0x3ULL -#define INFINIPATH_IBCC_LINKCMD_DOWN 1 /* move to 0x11 */ -#define INFINIPATH_IBCC_LINKCMD_ARMED 2 /* move to 0x21 */ -#define INFINIPATH_IBCC_LINKCMD_ACTIVE 3 /* move to 0x31 */ -#define INFINIPATH_IBCC_LINKCMD_SHIFT 18 -#define INFINIPATH_IBCC_MAXPKTLEN_MASK 0x7FFULL -#define INFINIPATH_IBCC_MAXPKTLEN_SHIFT 20 -#define INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK 0xFULL -#define INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT 32 -#define INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK 0xFULL -#define INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT 36 -#define INFINIPATH_IBCC_CREDITSCALE_MASK 0x7ULL -#define INFINIPATH_IBCC_CREDITSCALE_SHIFT 40 -#define INFINIPATH_IBCC_LOOPBACK 0x8000000000000000ULL -#define INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE 0x4000000000000000ULL - -/* kr_ibcstatus bits */ -#define INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT 0 -#define INFINIPATH_IBCS_LINKSTATE_MASK 0x7 - -#define INFINIPATH_IBCS_TXREADY 0x40000000 -#define INFINIPATH_IBCS_TXCREDITOK 0x80000000 -/* link training states (shift by - INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) */ -#define INFINIPATH_IBCS_LT_STATE_DISABLED 0x00 -#define INFINIPATH_IBCS_LT_STATE_LINKUP 0x01 -#define INFINIPATH_IBCS_LT_STATE_POLLACTIVE 0x02 -#define INFINIPATH_IBCS_LT_STATE_POLLQUIET 0x03 -#define INFINIPATH_IBCS_LT_STATE_SLEEPDELAY 0x04 -#define INFINIPATH_IBCS_LT_STATE_SLEEPQUIET 0x05 -#define INFINIPATH_IBCS_LT_STATE_CFGDEBOUNCE 0x08 -#define INFINIPATH_IBCS_LT_STATE_CFGRCVFCFG 0x09 -#define INFINIPATH_IBCS_LT_STATE_CFGWAITRMT 0x0a -#define INFINIPATH_IBCS_LT_STATE_CFGIDLE 0x0b -#define INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN 0x0c -#define INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT 0x0e -#define INFINIPATH_IBCS_LT_STATE_RECOVERIDLE 0x0f -/* link state machine states (shift by ibcs_ls_shift) */ -#define INFINIPATH_IBCS_L_STATE_DOWN 0x0 -#define INFINIPATH_IBCS_L_STATE_INIT 0x1 -#define INFINIPATH_IBCS_L_STATE_ARM 0x2 -#define INFINIPATH_IBCS_L_STATE_ACTIVE 0x3 -#define INFINIPATH_IBCS_L_STATE_ACT_DEFER 0x4 - - -/* kr_extstatus bits */ -#define INFINIPATH_EXTS_SERDESPLLLOCK 0x1 -#define INFINIPATH_EXTS_GPIOIN_MASK 0xFFFFULL -#define INFINIPATH_EXTS_GPIOIN_SHIFT 48 - -/* kr_extctrl bits */ -#define INFINIPATH_EXTC_GPIOINVERT_MASK 0xFFFFULL -#define INFINIPATH_EXTC_GPIOINVERT_SHIFT 32 -#define INFINIPATH_EXTC_GPIOOE_MASK 0xFFFFULL -#define INFINIPATH_EXTC_GPIOOE_SHIFT 48 -#define INFINIPATH_EXTC_SERDESENABLE 0x80000000ULL -#define INFINIPATH_EXTC_SERDESCONNECT 0x40000000ULL -#define INFINIPATH_EXTC_SERDESENTRUNKING 0x20000000ULL -#define INFINIPATH_EXTC_SERDESDISRXFIFO 0x10000000ULL -#define INFINIPATH_EXTC_SERDESENPLPBK1 0x08000000ULL -#define INFINIPATH_EXTC_SERDESENPLPBK2 0x04000000ULL -#define INFINIPATH_EXTC_SERDESENENCDEC 0x02000000ULL -#define INFINIPATH_EXTC_LED1SECPORT_ON 0x00000020ULL -#define INFINIPATH_EXTC_LED2SECPORT_ON 0x00000010ULL -#define INFINIPATH_EXTC_LED1PRIPORT_ON 0x00000008ULL -#define INFINIPATH_EXTC_LED2PRIPORT_ON 0x00000004ULL -#define INFINIPATH_EXTC_LEDGBLOK_ON 0x00000002ULL -#define INFINIPATH_EXTC_LEDGBLERR_OFF 0x00000001ULL - -/* kr_partitionkey bits */ -#define INFINIPATH_PKEY_SIZE 16 -#define INFINIPATH_PKEY_MASK 0xFFFF -#define INFINIPATH_PKEY_DEFAULT_PKEY 0xFFFF - -/* kr_serdesconfig0 bits */ -#define INFINIPATH_SERDC0_RESET_MASK 0xfULL /* overal reset bits */ -#define INFINIPATH_SERDC0_RESET_PLL 0x10000000ULL /* pll reset */ -/* tx idle enables (per lane) */ -#define INFINIPATH_SERDC0_TXIDLE 0xF000ULL -/* rx detect enables (per lane) */ -#define INFINIPATH_SERDC0_RXDETECT_EN 0xF0000ULL -/* L1 Power down; use with RXDETECT, Otherwise not used on IB side */ -#define INFINIPATH_SERDC0_L1PWR_DN 0xF0ULL - -/* common kr_xgxsconfig bits (or safe in all, even if not implemented) */ -#define INFINIPATH_XGXS_RX_POL_SHIFT 19 -#define INFINIPATH_XGXS_RX_POL_MASK 0xfULL - - -/* - * IPATH_PIO_MAXIBHDR is the max IB header size allowed for in our - * PIO send buffers. This is well beyond anything currently - * defined in the InfiniBand spec. - */ -#define IPATH_PIO_MAXIBHDR 128 - -typedef u64 ipath_err_t; - -/* The following change with the type of device, so - * need to be part of the ipath_devdata struct, or - * we could have problems plugging in devices of - * different types (e.g. one HT, one PCIE) - * in one system, to be managed by one driver. - * On the other hand, this file is may also be included - * by other code, so leave the declarations here - * temporarily. Minor footprint issue if common-model - * linker used, none if C89+ linker used. - */ - -/* mask of defined bits for various registers */ -extern u64 infinipath_i_bitsextant; -extern ipath_err_t infinipath_e_bitsextant, infinipath_hwe_bitsextant; - -/* masks that are different in various chips, or only exist in some chips */ -extern u32 infinipath_i_rcvavail_mask, infinipath_i_rcvurg_mask; - -/* - * These are the infinipath general register numbers (not offsets). - * The kernel registers are used directly, those beyond the kernel - * registers are calculated from one of the base registers. The use of - * an integer type doesn't allow type-checking as thorough as, say, - * an enum but allows for better hiding of chip differences. - */ -typedef const u16 ipath_kreg, /* infinipath general registers */ - ipath_creg, /* infinipath counter registers */ - ipath_sreg; /* kernel-only, infinipath send registers */ - -/* - * These are the chip registers common to all infinipath chips, and - * used both by the kernel and the diagnostics or other user code. - * They are all implemented such that 64 bit accesses work. - * Some implement no more than 32 bits. Because 64 bit reads - * require 2 HT cmds on opteron, we access those with 32 bit - * reads for efficiency (they are written as 64 bits, since - * the extra 32 bits are nearly free on writes, and it slightly reduces - * complexity). The rest are all accessed as 64 bits. - */ -struct ipath_kregs { - /* These are the 32 bit group */ - ipath_kreg kr_control; - ipath_kreg kr_counterregbase; - ipath_kreg kr_intmask; - ipath_kreg kr_intstatus; - ipath_kreg kr_pagealign; - ipath_kreg kr_portcnt; - ipath_kreg kr_rcvtidbase; - ipath_kreg kr_rcvtidcnt; - ipath_kreg kr_rcvegrbase; - ipath_kreg kr_rcvegrcnt; - ipath_kreg kr_scratch; - ipath_kreg kr_sendctrl; - ipath_kreg kr_sendpiobufbase; - ipath_kreg kr_sendpiobufcnt; - ipath_kreg kr_sendpiosize; - ipath_kreg kr_sendregbase; - ipath_kreg kr_userregbase; - /* These are the 64 bit group */ - ipath_kreg kr_debugport; - ipath_kreg kr_debugportselect; - ipath_kreg kr_errorclear; - ipath_kreg kr_errormask; - ipath_kreg kr_errorstatus; - ipath_kreg kr_extctrl; - ipath_kreg kr_extstatus; - ipath_kreg kr_gpio_clear; - ipath_kreg kr_gpio_mask; - ipath_kreg kr_gpio_out; - ipath_kreg kr_gpio_status; - ipath_kreg kr_hwdiagctrl; - ipath_kreg kr_hwerrclear; - ipath_kreg kr_hwerrmask; - ipath_kreg kr_hwerrstatus; - ipath_kreg kr_ibcctrl; - ipath_kreg kr_ibcstatus; - ipath_kreg kr_intblocked; - ipath_kreg kr_intclear; - ipath_kreg kr_interruptconfig; - ipath_kreg kr_mdio; - ipath_kreg kr_partitionkey; - ipath_kreg kr_rcvbthqp; - ipath_kreg kr_rcvbufbase; - ipath_kreg kr_rcvbufsize; - ipath_kreg kr_rcvctrl; - ipath_kreg kr_rcvhdrcnt; - ipath_kreg kr_rcvhdrentsize; - ipath_kreg kr_rcvhdrsize; - ipath_kreg kr_rcvintmembase; - ipath_kreg kr_rcvintmemsize; - ipath_kreg kr_revision; - ipath_kreg kr_sendbuffererror; - ipath_kreg kr_sendpioavailaddr; - ipath_kreg kr_serdesconfig0; - ipath_kreg kr_serdesconfig1; - ipath_kreg kr_serdesstatus; - ipath_kreg kr_txintmembase; - ipath_kreg kr_txintmemsize; - ipath_kreg kr_xgxsconfig; - ipath_kreg kr_ibpllcfg; - /* use these two (and the following N ports) only with - * ipath_k*_kreg64_port(); not *kreg64() */ - ipath_kreg kr_rcvhdraddr; - ipath_kreg kr_rcvhdrtailaddr; - - /* remaining registers are not present on all types of infinipath - chips */ - ipath_kreg kr_rcvpktledcnt; - ipath_kreg kr_pcierbuftestreg0; - ipath_kreg kr_pcierbuftestreg1; - ipath_kreg kr_pcieq0serdesconfig0; - ipath_kreg kr_pcieq0serdesconfig1; - ipath_kreg kr_pcieq0serdesstatus; - ipath_kreg kr_pcieq1serdesconfig0; - ipath_kreg kr_pcieq1serdesconfig1; - ipath_kreg kr_pcieq1serdesstatus; - ipath_kreg kr_hrtbt_guid; - ipath_kreg kr_ibcddrctrl; - ipath_kreg kr_ibcddrstatus; - ipath_kreg kr_jintreload; - - /* send dma related regs */ - ipath_kreg kr_senddmabase; - ipath_kreg kr_senddmalengen; - ipath_kreg kr_senddmatail; - ipath_kreg kr_senddmahead; - ipath_kreg kr_senddmaheadaddr; - ipath_kreg kr_senddmabufmask0; - ipath_kreg kr_senddmabufmask1; - ipath_kreg kr_senddmabufmask2; - ipath_kreg kr_senddmastatus; - - /* SerDes related regs (IBA7220-only) */ - ipath_kreg kr_ibserdesctrl; - ipath_kreg kr_ib_epbacc; - ipath_kreg kr_ib_epbtrans; - ipath_kreg kr_pcie_epbacc; - ipath_kreg kr_pcie_epbtrans; - ipath_kreg kr_ib_ddsrxeq; -}; - -struct ipath_cregs { - ipath_creg cr_badformatcnt; - ipath_creg cr_erricrccnt; - ipath_creg cr_errlinkcnt; - ipath_creg cr_errlpcrccnt; - ipath_creg cr_errpkey; - ipath_creg cr_errrcvflowctrlcnt; - ipath_creg cr_err_rlencnt; - ipath_creg cr_errslencnt; - ipath_creg cr_errtidfull; - ipath_creg cr_errtidvalid; - ipath_creg cr_errvcrccnt; - ipath_creg cr_ibstatuschange; - ipath_creg cr_intcnt; - ipath_creg cr_invalidrlencnt; - ipath_creg cr_invalidslencnt; - ipath_creg cr_lbflowstallcnt; - ipath_creg cr_iblinkdowncnt; - ipath_creg cr_iblinkerrrecovcnt; - ipath_creg cr_ibsymbolerrcnt; - ipath_creg cr_pktrcvcnt; - ipath_creg cr_pktrcvflowctrlcnt; - ipath_creg cr_pktsendcnt; - ipath_creg cr_pktsendflowcnt; - ipath_creg cr_portovflcnt; - ipath_creg cr_rcvebpcnt; - ipath_creg cr_rcvovflcnt; - ipath_creg cr_rxdroppktcnt; - ipath_creg cr_senddropped; - ipath_creg cr_sendstallcnt; - ipath_creg cr_sendunderruncnt; - ipath_creg cr_unsupvlcnt; - ipath_creg cr_wordrcvcnt; - ipath_creg cr_wordsendcnt; - ipath_creg cr_vl15droppedpktcnt; - ipath_creg cr_rxotherlocalphyerrcnt; - ipath_creg cr_excessbufferovflcnt; - ipath_creg cr_locallinkintegrityerrcnt; - ipath_creg cr_rxvlerrcnt; - ipath_creg cr_rxdlidfltrcnt; - ipath_creg cr_psstat; - ipath_creg cr_psstart; - ipath_creg cr_psinterval; - ipath_creg cr_psrcvdatacount; - ipath_creg cr_psrcvpktscount; - ipath_creg cr_psxmitdatacount; - ipath_creg cr_psxmitpktscount; - ipath_creg cr_psxmitwaitcount; -}; - -#endif /* _IPATH_REGISTERS_H */ diff --git a/drivers/staging/rdma/ipath/ipath_ruc.c b/drivers/staging/rdma/ipath/ipath_ruc.c deleted file mode 100644 index e541a01f1f61..000000000000 --- a/drivers/staging/rdma/ipath/ipath_ruc.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include "ipath_verbs.h" -#include "ipath_kernel.h" - -/* - * Convert the AETH RNR timeout code into the number of milliseconds. - */ -const u32 ib_ipath_rnr_table[32] = { - 656, /* 0 */ - 1, /* 1 */ - 1, /* 2 */ - 1, /* 3 */ - 1, /* 4 */ - 1, /* 5 */ - 1, /* 6 */ - 1, /* 7 */ - 1, /* 8 */ - 1, /* 9 */ - 1, /* A */ - 1, /* B */ - 1, /* C */ - 1, /* D */ - 2, /* E */ - 2, /* F */ - 3, /* 10 */ - 4, /* 11 */ - 6, /* 12 */ - 8, /* 13 */ - 11, /* 14 */ - 16, /* 15 */ - 21, /* 16 */ - 31, /* 17 */ - 41, /* 18 */ - 62, /* 19 */ - 82, /* 1A */ - 123, /* 1B */ - 164, /* 1C */ - 246, /* 1D */ - 328, /* 1E */ - 492 /* 1F */ -}; - -/** - * ipath_insert_rnr_queue - put QP on the RNR timeout list for the device - * @qp: the QP - * - * Called with the QP s_lock held and interrupts disabled. - * XXX Use a simple list for now. We might need a priority - * queue if we have lots of QPs waiting for RNR timeouts - * but that should be rare. - */ -void ipath_insert_rnr_queue(struct ipath_qp *qp) -{ - struct ipath_ibdev *dev = to_idev(qp->ibqp.device); - - /* We already did a spin_lock_irqsave(), so just use spin_lock */ - spin_lock(&dev->pending_lock); - if (list_empty(&dev->rnrwait)) - list_add(&qp->timerwait, &dev->rnrwait); - else { - struct list_head *l = &dev->rnrwait; - struct ipath_qp *nqp = list_entry(l->next, struct ipath_qp, - timerwait); - - while (qp->s_rnr_timeout >= nqp->s_rnr_timeout) { - qp->s_rnr_timeout -= nqp->s_rnr_timeout; - l = l->next; - if (l->next == &dev->rnrwait) { - nqp = NULL; - break; - } - nqp = list_entry(l->next, struct ipath_qp, - timerwait); - } - if (nqp) - nqp->s_rnr_timeout -= qp->s_rnr_timeout; - list_add(&qp->timerwait, l); - } - spin_unlock(&dev->pending_lock); -} - -/** - * ipath_init_sge - Validate a RWQE and fill in the SGE state - * @qp: the QP - * - * Return 1 if OK. - */ -int ipath_init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe, - u32 *lengthp, struct ipath_sge_state *ss) -{ - int i, j, ret; - struct ib_wc wc; - - *lengthp = 0; - for (i = j = 0; i < wqe->num_sge; i++) { - if (wqe->sg_list[i].length == 0) - continue; - /* Check LKEY */ - if (!ipath_lkey_ok(qp, j ? &ss->sg_list[j - 1] : &ss->sge, - &wqe->sg_list[i], IB_ACCESS_LOCAL_WRITE)) - goto bad_lkey; - *lengthp += wqe->sg_list[i].length; - j++; - } - ss->num_sge = j; - ret = 1; - goto bail; - -bad_lkey: - memset(&wc, 0, sizeof(wc)); - wc.wr_id = wqe->wr_id; - wc.status = IB_WC_LOC_PROT_ERR; - wc.opcode = IB_WC_RECV; - wc.qp = &qp->ibqp; - /* Signal solicited completion event. */ - ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1); - ret = 0; -bail: - return ret; -} - -/** - * ipath_get_rwqe - copy the next RWQE into the QP's RWQE - * @qp: the QP - * @wr_id_only: update qp->r_wr_id only, not qp->r_sge - * - * Return 0 if no RWQE is available, otherwise return 1. - * - * Can be called from interrupt level. - */ -int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only) -{ - unsigned long flags; - struct ipath_rq *rq; - struct ipath_rwq *wq; - struct ipath_srq *srq; - struct ipath_rwqe *wqe; - void (*handler)(struct ib_event *, void *); - u32 tail; - int ret; - - if (qp->ibqp.srq) { - srq = to_isrq(qp->ibqp.srq); - handler = srq->ibsrq.event_handler; - rq = &srq->rq; - } else { - srq = NULL; - handler = NULL; - rq = &qp->r_rq; - } - - spin_lock_irqsave(&rq->lock, flags); - if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) { - ret = 0; - goto unlock; - } - - wq = rq->wq; - tail = wq->tail; - /* Validate tail before using it since it is user writable. */ - if (tail >= rq->size) - tail = 0; - do { - if (unlikely(tail == wq->head)) { - ret = 0; - goto unlock; - } - /* Make sure entry is read after head index is read. */ - smp_rmb(); - wqe = get_rwqe_ptr(rq, tail); - if (++tail >= rq->size) - tail = 0; - if (wr_id_only) - break; - qp->r_sge.sg_list = qp->r_sg_list; - } while (!ipath_init_sge(qp, wqe, &qp->r_len, &qp->r_sge)); - qp->r_wr_id = wqe->wr_id; - wq->tail = tail; - - ret = 1; - set_bit(IPATH_R_WRID_VALID, &qp->r_aflags); - if (handler) { - u32 n; - - /* - * validate head pointer value and compute - * the number of remaining WQEs. - */ - n = wq->head; - if (n >= rq->size) - n = 0; - if (n < tail) - n += rq->size - tail; - else - n -= tail; - if (n < srq->limit) { - struct ib_event ev; - - srq->limit = 0; - spin_unlock_irqrestore(&rq->lock, flags); - ev.device = qp->ibqp.device; - ev.element.srq = qp->ibqp.srq; - ev.event = IB_EVENT_SRQ_LIMIT_REACHED; - handler(&ev, srq->ibsrq.srq_context); - goto bail; - } - } -unlock: - spin_unlock_irqrestore(&rq->lock, flags); -bail: - return ret; -} - -/** - * ipath_ruc_loopback - handle UC and RC lookback requests - * @sqp: the sending QP - * - * This is called from ipath_do_send() to - * forward a WQE addressed to the same HCA. - * Note that although we are single threaded due to the tasklet, we still - * have to protect against post_send(). We don't have to worry about - * receive interrupts since this is a connected protocol and all packets - * will pass through here. - */ -static void ipath_ruc_loopback(struct ipath_qp *sqp) -{ - struct ipath_ibdev *dev = to_idev(sqp->ibqp.device); - struct ipath_qp *qp; - struct ipath_swqe *wqe; - struct ipath_sge *sge; - unsigned long flags; - struct ib_wc wc; - u64 sdata; - atomic64_t *maddr; - enum ib_wc_status send_status; - - /* - * Note that we check the responder QP state after - * checking the requester's state. - */ - qp = ipath_lookup_qpn(&dev->qp_table, sqp->remote_qpn); - - spin_lock_irqsave(&sqp->s_lock, flags); - - /* Return if we are already busy processing a work request. */ - if ((sqp->s_flags & (IPATH_S_BUSY | IPATH_S_ANY_WAIT)) || - !(ib_ipath_state_ops[sqp->state] & IPATH_PROCESS_OR_FLUSH_SEND)) - goto unlock; - - sqp->s_flags |= IPATH_S_BUSY; - -again: - if (sqp->s_last == sqp->s_head) - goto clr_busy; - wqe = get_swqe_ptr(sqp, sqp->s_last); - - /* Return if it is not OK to start a new work reqeust. */ - if (!(ib_ipath_state_ops[sqp->state] & IPATH_PROCESS_NEXT_SEND_OK)) { - if (!(ib_ipath_state_ops[sqp->state] & IPATH_FLUSH_SEND)) - goto clr_busy; - /* We are in the error state, flush the work request. */ - send_status = IB_WC_WR_FLUSH_ERR; - goto flush_send; - } - - /* - * We can rely on the entry not changing without the s_lock - * being held until we update s_last. - * We increment s_cur to indicate s_last is in progress. - */ - if (sqp->s_last == sqp->s_cur) { - if (++sqp->s_cur >= sqp->s_size) - sqp->s_cur = 0; - } - spin_unlock_irqrestore(&sqp->s_lock, flags); - - if (!qp || !(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) { - dev->n_pkt_drops++; - /* - * For RC, the requester would timeout and retry so - * shortcut the timeouts and just signal too many retries. - */ - if (sqp->ibqp.qp_type == IB_QPT_RC) - send_status = IB_WC_RETRY_EXC_ERR; - else - send_status = IB_WC_SUCCESS; - goto serr; - } - - memset(&wc, 0, sizeof wc); - send_status = IB_WC_SUCCESS; - - sqp->s_sge.sge = wqe->sg_list[0]; - sqp->s_sge.sg_list = wqe->sg_list + 1; - sqp->s_sge.num_sge = wqe->wr.num_sge; - sqp->s_len = wqe->length; - switch (wqe->wr.opcode) { - case IB_WR_SEND_WITH_IMM: - wc.wc_flags = IB_WC_WITH_IMM; - wc.ex.imm_data = wqe->wr.ex.imm_data; - /* FALLTHROUGH */ - case IB_WR_SEND: - if (!ipath_get_rwqe(qp, 0)) - goto rnr_nak; - break; - - case IB_WR_RDMA_WRITE_WITH_IMM: - if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_WRITE))) - goto inv_err; - wc.wc_flags = IB_WC_WITH_IMM; - wc.ex.imm_data = wqe->wr.ex.imm_data; - if (!ipath_get_rwqe(qp, 1)) - goto rnr_nak; - /* FALLTHROUGH */ - case IB_WR_RDMA_WRITE: - if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_WRITE))) - goto inv_err; - if (wqe->length == 0) - break; - if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, wqe->length, - wqe->rdma_wr.remote_addr, - wqe->rdma_wr.rkey, - IB_ACCESS_REMOTE_WRITE))) - goto acc_err; - break; - - case IB_WR_RDMA_READ: - if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_READ))) - goto inv_err; - if (unlikely(!ipath_rkey_ok(qp, &sqp->s_sge, wqe->length, - wqe->rdma_wr.remote_addr, - wqe->rdma_wr.rkey, - IB_ACCESS_REMOTE_READ))) - goto acc_err; - qp->r_sge.sge = wqe->sg_list[0]; - qp->r_sge.sg_list = wqe->sg_list + 1; - qp->r_sge.num_sge = wqe->wr.num_sge; - break; - - case IB_WR_ATOMIC_CMP_AND_SWP: - case IB_WR_ATOMIC_FETCH_AND_ADD: - if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC))) - goto inv_err; - if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, sizeof(u64), - wqe->atomic_wr.remote_addr, - wqe->atomic_wr.rkey, - IB_ACCESS_REMOTE_ATOMIC))) - goto acc_err; - /* Perform atomic OP and save result. */ - maddr = (atomic64_t *) qp->r_sge.sge.vaddr; - sdata = wqe->atomic_wr.compare_add; - *(u64 *) sqp->s_sge.sge.vaddr = - (wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) ? - (u64) atomic64_add_return(sdata, maddr) - sdata : - (u64) cmpxchg((u64 *) qp->r_sge.sge.vaddr, - sdata, wqe->atomic_wr.swap); - goto send_comp; - - default: - send_status = IB_WC_LOC_QP_OP_ERR; - goto serr; - } - - sge = &sqp->s_sge.sge; - while (sqp->s_len) { - u32 len = sqp->s_len; - - if (len > sge->length) - len = sge->length; - if (len > sge->sge_length) - len = sge->sge_length; - BUG_ON(len == 0); - ipath_copy_sge(&qp->r_sge, sge->vaddr, len); - sge->vaddr += len; - sge->length -= len; - sge->sge_length -= len; - if (sge->sge_length == 0) { - if (--sqp->s_sge.num_sge) - *sge = *sqp->s_sge.sg_list++; - } else if (sge->length == 0 && sge->mr != NULL) { - if (++sge->n >= IPATH_SEGSZ) { - if (++sge->m >= sge->mr->mapsz) - break; - sge->n = 0; - } - sge->vaddr = - sge->mr->map[sge->m]->segs[sge->n].vaddr; - sge->length = - sge->mr->map[sge->m]->segs[sge->n].length; - } - sqp->s_len -= len; - } - - if (!test_and_clear_bit(IPATH_R_WRID_VALID, &qp->r_aflags)) - goto send_comp; - - if (wqe->wr.opcode == IB_WR_RDMA_WRITE_WITH_IMM) - wc.opcode = IB_WC_RECV_RDMA_WITH_IMM; - else - wc.opcode = IB_WC_RECV; - wc.wr_id = qp->r_wr_id; - wc.status = IB_WC_SUCCESS; - wc.byte_len = wqe->length; - wc.qp = &qp->ibqp; - wc.src_qp = qp->remote_qpn; - wc.slid = qp->remote_ah_attr.dlid; - wc.sl = qp->remote_ah_attr.sl; - wc.port_num = 1; - /* Signal completion event if the solicited bit is set. */ - ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, - wqe->wr.send_flags & IB_SEND_SOLICITED); - -send_comp: - spin_lock_irqsave(&sqp->s_lock, flags); -flush_send: - sqp->s_rnr_retry = sqp->s_rnr_retry_cnt; - ipath_send_complete(sqp, wqe, send_status); - goto again; - -rnr_nak: - /* Handle RNR NAK */ - if (qp->ibqp.qp_type == IB_QPT_UC) - goto send_comp; - /* - * Note: we don't need the s_lock held since the BUSY flag - * makes this single threaded. - */ - if (sqp->s_rnr_retry == 0) { - send_status = IB_WC_RNR_RETRY_EXC_ERR; - goto serr; - } - if (sqp->s_rnr_retry_cnt < 7) - sqp->s_rnr_retry--; - spin_lock_irqsave(&sqp->s_lock, flags); - if (!(ib_ipath_state_ops[sqp->state] & IPATH_PROCESS_RECV_OK)) - goto clr_busy; - sqp->s_flags |= IPATH_S_WAITING; - dev->n_rnr_naks++; - sqp->s_rnr_timeout = ib_ipath_rnr_table[qp->r_min_rnr_timer]; - ipath_insert_rnr_queue(sqp); - goto clr_busy; - -inv_err: - send_status = IB_WC_REM_INV_REQ_ERR; - wc.status = IB_WC_LOC_QP_OP_ERR; - goto err; - -acc_err: - send_status = IB_WC_REM_ACCESS_ERR; - wc.status = IB_WC_LOC_PROT_ERR; -err: - /* responder goes to error state */ - ipath_rc_error(qp, wc.status); - -serr: - spin_lock_irqsave(&sqp->s_lock, flags); - ipath_send_complete(sqp, wqe, send_status); - if (sqp->ibqp.qp_type == IB_QPT_RC) { - int lastwqe = ipath_error_qp(sqp, IB_WC_WR_FLUSH_ERR); - - sqp->s_flags &= ~IPATH_S_BUSY; - spin_unlock_irqrestore(&sqp->s_lock, flags); - if (lastwqe) { - struct ib_event ev; - - ev.device = sqp->ibqp.device; - ev.element.qp = &sqp->ibqp; - ev.event = IB_EVENT_QP_LAST_WQE_REACHED; - sqp->ibqp.event_handler(&ev, sqp->ibqp.qp_context); - } - goto done; - } -clr_busy: - sqp->s_flags &= ~IPATH_S_BUSY; -unlock: - spin_unlock_irqrestore(&sqp->s_lock, flags); -done: - if (qp && atomic_dec_and_test(&qp->refcount)) - wake_up(&qp->wait); -} - -static void want_buffer(struct ipath_devdata *dd, struct ipath_qp *qp) -{ - if (!(dd->ipath_flags & IPATH_HAS_SEND_DMA) || - qp->ibqp.qp_type == IB_QPT_SMI) { - unsigned long flags; - - spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); - dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL; - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, - dd->ipath_sendctrl); - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); - } -} - -/** - * ipath_no_bufs_available - tell the layer driver we need buffers - * @qp: the QP that caused the problem - * @dev: the device we ran out of buffers on - * - * Called when we run out of PIO buffers. - * If we are now in the error state, return zero to flush the - * send work request. - */ -static int ipath_no_bufs_available(struct ipath_qp *qp, - struct ipath_ibdev *dev) -{ - unsigned long flags; - int ret = 1; - - /* - * Note that as soon as want_buffer() is called and - * possibly before it returns, ipath_ib_piobufavail() - * could be called. Therefore, put QP on the piowait list before - * enabling the PIO avail interrupt. - */ - spin_lock_irqsave(&qp->s_lock, flags); - if (ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK) { - dev->n_piowait++; - qp->s_flags |= IPATH_S_WAITING; - qp->s_flags &= ~IPATH_S_BUSY; - spin_lock(&dev->pending_lock); - if (list_empty(&qp->piowait)) - list_add_tail(&qp->piowait, &dev->piowait); - spin_unlock(&dev->pending_lock); - } else - ret = 0; - spin_unlock_irqrestore(&qp->s_lock, flags); - if (ret) - want_buffer(dev->dd, qp); - return ret; -} - -/** - * ipath_make_grh - construct a GRH header - * @dev: a pointer to the ipath device - * @hdr: a pointer to the GRH header being constructed - * @grh: the global route address to send to - * @hwords: the number of 32 bit words of header being sent - * @nwords: the number of 32 bit words of data being sent - * - * Return the size of the header in 32 bit words. - */ -u32 ipath_make_grh(struct ipath_ibdev *dev, struct ib_grh *hdr, - struct ib_global_route *grh, u32 hwords, u32 nwords) -{ - hdr->version_tclass_flow = - cpu_to_be32((6 << 28) | - (grh->traffic_class << 20) | - grh->flow_label); - hdr->paylen = cpu_to_be16((hwords - 2 + nwords + SIZE_OF_CRC) << 2); - /* next_hdr is defined by C8-7 in ch. 8.4.1 */ - hdr->next_hdr = 0x1B; - hdr->hop_limit = grh->hop_limit; - /* The SGID is 32-bit aligned. */ - hdr->sgid.global.subnet_prefix = dev->gid_prefix; - hdr->sgid.global.interface_id = dev->dd->ipath_guid; - hdr->dgid = grh->dgid; - - /* GRH header size in 32-bit words. */ - return sizeof(struct ib_grh) / sizeof(u32); -} - -void ipath_make_ruc_header(struct ipath_ibdev *dev, struct ipath_qp *qp, - struct ipath_other_headers *ohdr, - u32 bth0, u32 bth2) -{ - u16 lrh0; - u32 nwords; - u32 extra_bytes; - - /* Construct the header. */ - extra_bytes = -qp->s_cur_size & 3; - nwords = (qp->s_cur_size + extra_bytes) >> 2; - lrh0 = IPATH_LRH_BTH; - if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) { - qp->s_hdrwords += ipath_make_grh(dev, &qp->s_hdr.u.l.grh, - &qp->remote_ah_attr.grh, - qp->s_hdrwords, nwords); - lrh0 = IPATH_LRH_GRH; - } - lrh0 |= qp->remote_ah_attr.sl << 4; - qp->s_hdr.lrh[0] = cpu_to_be16(lrh0); - qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid); - qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords + SIZE_OF_CRC); - qp->s_hdr.lrh[3] = cpu_to_be16(dev->dd->ipath_lid | - qp->remote_ah_attr.src_path_bits); - bth0 |= ipath_get_pkey(dev->dd, qp->s_pkey_index); - bth0 |= extra_bytes << 20; - ohdr->bth[0] = cpu_to_be32(bth0 | (1 << 22)); - ohdr->bth[1] = cpu_to_be32(qp->remote_qpn); - ohdr->bth[2] = cpu_to_be32(bth2); -} - -/** - * ipath_do_send - perform a send on a QP - * @data: contains a pointer to the QP - * - * Process entries in the send work queue until credit or queue is - * exhausted. Only allow one CPU to send a packet per QP (tasklet). - * Otherwise, two threads could send packets out of order. - */ -void ipath_do_send(unsigned long data) -{ - struct ipath_qp *qp = (struct ipath_qp *)data; - struct ipath_ibdev *dev = to_idev(qp->ibqp.device); - int (*make_req)(struct ipath_qp *qp); - unsigned long flags; - - if ((qp->ibqp.qp_type == IB_QPT_RC || - qp->ibqp.qp_type == IB_QPT_UC) && - qp->remote_ah_attr.dlid == dev->dd->ipath_lid) { - ipath_ruc_loopback(qp); - goto bail; - } - - if (qp->ibqp.qp_type == IB_QPT_RC) - make_req = ipath_make_rc_req; - else if (qp->ibqp.qp_type == IB_QPT_UC) - make_req = ipath_make_uc_req; - else - make_req = ipath_make_ud_req; - - spin_lock_irqsave(&qp->s_lock, flags); - - /* Return if we are already busy processing a work request. */ - if ((qp->s_flags & (IPATH_S_BUSY | IPATH_S_ANY_WAIT)) || - !(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_OR_FLUSH_SEND)) { - spin_unlock_irqrestore(&qp->s_lock, flags); - goto bail; - } - - qp->s_flags |= IPATH_S_BUSY; - - spin_unlock_irqrestore(&qp->s_lock, flags); - -again: - /* Check for a constructed packet to be sent. */ - if (qp->s_hdrwords != 0) { - /* - * If no PIO bufs are available, return. An interrupt will - * call ipath_ib_piobufavail() when one is available. - */ - if (ipath_verbs_send(qp, &qp->s_hdr, qp->s_hdrwords, - qp->s_cur_sge, qp->s_cur_size)) { - if (ipath_no_bufs_available(qp, dev)) - goto bail; - } - dev->n_unicast_xmit++; - /* Record that we sent the packet and s_hdr is empty. */ - qp->s_hdrwords = 0; - } - - if (make_req(qp)) - goto again; - -bail:; -} - -/* - * This should be called with s_lock held. - */ -void ipath_send_complete(struct ipath_qp *qp, struct ipath_swqe *wqe, - enum ib_wc_status status) -{ - u32 old_last, last; - - if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_OR_FLUSH_SEND)) - return; - - /* See ch. 11.2.4.1 and 10.7.3.1 */ - if (!(qp->s_flags & IPATH_S_SIGNAL_REQ_WR) || - (wqe->wr.send_flags & IB_SEND_SIGNALED) || - status != IB_WC_SUCCESS) { - struct ib_wc wc; - - memset(&wc, 0, sizeof wc); - wc.wr_id = wqe->wr.wr_id; - wc.status = status; - wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; - wc.qp = &qp->ibqp; - if (status == IB_WC_SUCCESS) - wc.byte_len = wqe->length; - ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, - status != IB_WC_SUCCESS); - } - - old_last = last = qp->s_last; - if (++last >= qp->s_size) - last = 0; - qp->s_last = last; - if (qp->s_cur == old_last) - qp->s_cur = last; - if (qp->s_tail == old_last) - qp->s_tail = last; - if (qp->state == IB_QPS_SQD && last == qp->s_cur) - qp->s_draining = 0; -} diff --git a/drivers/staging/rdma/ipath/ipath_sdma.c b/drivers/staging/rdma/ipath/ipath_sdma.c deleted file mode 100644 index 1ffc06abf9da..000000000000 --- a/drivers/staging/rdma/ipath/ipath_sdma.c +++ /dev/null @@ -1,818 +0,0 @@ -/* - * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include "ipath_kernel.h" -#include "ipath_verbs.h" -#include "ipath_common.h" - -#define SDMA_DESCQ_SZ PAGE_SIZE /* 256 entries per 4KB page */ - -static void vl15_watchdog_enq(struct ipath_devdata *dd) -{ - /* ipath_sdma_lock must already be held */ - if (atomic_inc_return(&dd->ipath_sdma_vl15_count) == 1) { - unsigned long interval = (HZ + 19) / 20; - dd->ipath_sdma_vl15_timer.expires = jiffies + interval; - add_timer(&dd->ipath_sdma_vl15_timer); - } -} - -static void vl15_watchdog_deq(struct ipath_devdata *dd) -{ - /* ipath_sdma_lock must already be held */ - if (atomic_dec_return(&dd->ipath_sdma_vl15_count) != 0) { - unsigned long interval = (HZ + 19) / 20; - mod_timer(&dd->ipath_sdma_vl15_timer, jiffies + interval); - } else { - del_timer(&dd->ipath_sdma_vl15_timer); - } -} - -static void vl15_watchdog_timeout(unsigned long opaque) -{ - struct ipath_devdata *dd = (struct ipath_devdata *)opaque; - - if (atomic_read(&dd->ipath_sdma_vl15_count) != 0) { - ipath_dbg("vl15 watchdog timeout - clearing\n"); - ipath_cancel_sends(dd, 1); - ipath_hol_down(dd); - } else { - ipath_dbg("vl15 watchdog timeout - " - "condition already cleared\n"); - } -} - -static void unmap_desc(struct ipath_devdata *dd, unsigned head) -{ - __le64 *descqp = &dd->ipath_sdma_descq[head].qw[0]; - u64 desc[2]; - dma_addr_t addr; - size_t len; - - desc[0] = le64_to_cpu(descqp[0]); - desc[1] = le64_to_cpu(descqp[1]); - - addr = (desc[1] << 32) | (desc[0] >> 32); - len = (desc[0] >> 14) & (0x7ffULL << 2); - dma_unmap_single(&dd->pcidev->dev, addr, len, DMA_TO_DEVICE); -} - -/* - * ipath_sdma_lock should be locked before calling this. - */ -int ipath_sdma_make_progress(struct ipath_devdata *dd) -{ - struct list_head *lp = NULL; - struct ipath_sdma_txreq *txp = NULL; - u16 dmahead; - u16 start_idx = 0; - int progress = 0; - - if (!list_empty(&dd->ipath_sdma_activelist)) { - lp = dd->ipath_sdma_activelist.next; - txp = list_entry(lp, struct ipath_sdma_txreq, list); - start_idx = txp->start_idx; - } - - /* - * Read the SDMA head register in order to know that the - * interrupt clear has been written to the chip. - * Otherwise, we may not get an interrupt for the last - * descriptor in the queue. - */ - dmahead = (u16)ipath_read_kreg32(dd, dd->ipath_kregs->kr_senddmahead); - /* sanity check return value for error handling (chip reset, etc.) */ - if (dmahead >= dd->ipath_sdma_descq_cnt) - goto done; - - while (dd->ipath_sdma_descq_head != dmahead) { - if (txp && txp->flags & IPATH_SDMA_TXREQ_F_FREEDESC && - dd->ipath_sdma_descq_head == start_idx) { - unmap_desc(dd, dd->ipath_sdma_descq_head); - start_idx++; - if (start_idx == dd->ipath_sdma_descq_cnt) - start_idx = 0; - } - - /* increment free count and head */ - dd->ipath_sdma_descq_removed++; - if (++dd->ipath_sdma_descq_head == dd->ipath_sdma_descq_cnt) - dd->ipath_sdma_descq_head = 0; - - if (txp && txp->next_descq_idx == dd->ipath_sdma_descq_head) { - /* move to notify list */ - if (txp->flags & IPATH_SDMA_TXREQ_F_VL15) - vl15_watchdog_deq(dd); - list_move_tail(lp, &dd->ipath_sdma_notifylist); - if (!list_empty(&dd->ipath_sdma_activelist)) { - lp = dd->ipath_sdma_activelist.next; - txp = list_entry(lp, struct ipath_sdma_txreq, - list); - start_idx = txp->start_idx; - } else { - lp = NULL; - txp = NULL; - } - } - progress = 1; - } - - if (progress) - tasklet_hi_schedule(&dd->ipath_sdma_notify_task); - -done: - return progress; -} - -static void ipath_sdma_notify(struct ipath_devdata *dd, struct list_head *list) -{ - struct ipath_sdma_txreq *txp, *txp_next; - - list_for_each_entry_safe(txp, txp_next, list, list) { - list_del_init(&txp->list); - - if (txp->callback) - (*txp->callback)(txp->callback_cookie, - txp->callback_status); - } -} - -static void sdma_notify_taskbody(struct ipath_devdata *dd) -{ - unsigned long flags; - struct list_head list; - - INIT_LIST_HEAD(&list); - - spin_lock_irqsave(&dd->ipath_sdma_lock, flags); - - list_splice_init(&dd->ipath_sdma_notifylist, &list); - - spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); - - ipath_sdma_notify(dd, &list); - - /* - * The IB verbs layer needs to see the callback before getting - * the call to ipath_ib_piobufavail() because the callback - * handles releasing resources the next send will need. - * Otherwise, we could do these calls in - * ipath_sdma_make_progress(). - */ - ipath_ib_piobufavail(dd->verbs_dev); -} - -static void sdma_notify_task(unsigned long opaque) -{ - struct ipath_devdata *dd = (struct ipath_devdata *)opaque; - - if (!test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status)) - sdma_notify_taskbody(dd); -} - -static void dump_sdma_state(struct ipath_devdata *dd) -{ - unsigned long reg; - - reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmastatus); - ipath_cdbg(VERBOSE, "kr_senddmastatus: 0x%016lx\n", reg); - - reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendctrl); - ipath_cdbg(VERBOSE, "kr_sendctrl: 0x%016lx\n", reg); - - reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmabufmask0); - ipath_cdbg(VERBOSE, "kr_senddmabufmask0: 0x%016lx\n", reg); - - reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmabufmask1); - ipath_cdbg(VERBOSE, "kr_senddmabufmask1: 0x%016lx\n", reg); - - reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmabufmask2); - ipath_cdbg(VERBOSE, "kr_senddmabufmask2: 0x%016lx\n", reg); - - reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmatail); - ipath_cdbg(VERBOSE, "kr_senddmatail: 0x%016lx\n", reg); - - reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmahead); - ipath_cdbg(VERBOSE, "kr_senddmahead: 0x%016lx\n", reg); -} - -static void sdma_abort_task(unsigned long opaque) -{ - struct ipath_devdata *dd = (struct ipath_devdata *) opaque; - u64 status; - unsigned long flags; - - if (test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status)) - return; - - spin_lock_irqsave(&dd->ipath_sdma_lock, flags); - - status = dd->ipath_sdma_status & IPATH_SDMA_ABORT_MASK; - - /* nothing to do */ - if (status == IPATH_SDMA_ABORT_NONE) - goto unlock; - - /* ipath_sdma_abort() is done, waiting for interrupt */ - if (status == IPATH_SDMA_ABORT_DISARMED) { - if (time_before(jiffies, dd->ipath_sdma_abort_intr_timeout)) - goto resched_noprint; - /* give up, intr got lost somewhere */ - ipath_dbg("give up waiting for SDMADISABLED intr\n"); - __set_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status); - status = IPATH_SDMA_ABORT_ABORTED; - } - - /* everything is stopped, time to clean up and restart */ - if (status == IPATH_SDMA_ABORT_ABORTED) { - struct ipath_sdma_txreq *txp, *txpnext; - u64 hwstatus; - int notify = 0; - - hwstatus = ipath_read_kreg64(dd, - dd->ipath_kregs->kr_senddmastatus); - - if ((hwstatus & (IPATH_SDMA_STATUS_SCORE_BOARD_DRAIN_IN_PROG | - IPATH_SDMA_STATUS_ABORT_IN_PROG | - IPATH_SDMA_STATUS_INTERNAL_SDMA_ENABLE)) || - !(hwstatus & IPATH_SDMA_STATUS_SCB_EMPTY)) { - if (dd->ipath_sdma_reset_wait > 0) { - /* not done shutting down sdma */ - --dd->ipath_sdma_reset_wait; - goto resched; - } - ipath_cdbg(VERBOSE, "gave up waiting for quiescent " - "status after SDMA reset, continuing\n"); - dump_sdma_state(dd); - } - - /* dequeue all "sent" requests */ - list_for_each_entry_safe(txp, txpnext, - &dd->ipath_sdma_activelist, list) { - txp->callback_status = IPATH_SDMA_TXREQ_S_ABORTED; - if (txp->flags & IPATH_SDMA_TXREQ_F_VL15) - vl15_watchdog_deq(dd); - list_move_tail(&txp->list, &dd->ipath_sdma_notifylist); - notify = 1; - } - if (notify) - tasklet_hi_schedule(&dd->ipath_sdma_notify_task); - - /* reset our notion of head and tail */ - dd->ipath_sdma_descq_tail = 0; - dd->ipath_sdma_descq_head = 0; - dd->ipath_sdma_head_dma[0] = 0; - dd->ipath_sdma_generation = 0; - dd->ipath_sdma_descq_removed = dd->ipath_sdma_descq_added; - - /* Reset SendDmaLenGen */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmalengen, - (u64) dd->ipath_sdma_descq_cnt | (1ULL << 18)); - - /* done with sdma state for a bit */ - spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); - - /* - * Don't restart sdma here (with the exception - * below). Wait until link is up to ACTIVE. VL15 MADs - * used to bring the link up use PIO, and multiple link - * transitions otherwise cause the sdma engine to be - * stopped and started multiple times. - * The disable is done here, including the shadow, - * so the state is kept consistent. - * See ipath_restart_sdma() for the actual starting - * of sdma. - */ - spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); - dd->ipath_sendctrl &= ~INFINIPATH_S_SDMAENABLE; - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, - dd->ipath_sendctrl); - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); - - /* make sure I see next message */ - dd->ipath_sdma_abort_jiffies = 0; - - /* - * Not everything that takes SDMA offline is a link - * status change. If the link was up, restart SDMA. - */ - if (dd->ipath_flags & IPATH_LINKACTIVE) - ipath_restart_sdma(dd); - - goto done; - } - -resched: - /* - * for now, keep spinning - * JAG - this is bad to just have default be a loop without - * state change - */ - if (time_after(jiffies, dd->ipath_sdma_abort_jiffies)) { - ipath_dbg("looping with status 0x%08lx\n", - dd->ipath_sdma_status); - dd->ipath_sdma_abort_jiffies = jiffies + 5 * HZ; - } -resched_noprint: - spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); - if (!test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status)) - tasklet_hi_schedule(&dd->ipath_sdma_abort_task); - return; - -unlock: - spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); -done: - return; -} - -/* - * This is called from interrupt context. - */ -void ipath_sdma_intr(struct ipath_devdata *dd) -{ - unsigned long flags; - - spin_lock_irqsave(&dd->ipath_sdma_lock, flags); - - (void) ipath_sdma_make_progress(dd); - - spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); -} - -static int alloc_sdma(struct ipath_devdata *dd) -{ - int ret = 0; - - /* Allocate memory for SendDMA descriptor FIFO */ - dd->ipath_sdma_descq = dma_alloc_coherent(&dd->pcidev->dev, - SDMA_DESCQ_SZ, &dd->ipath_sdma_descq_phys, GFP_KERNEL); - - if (!dd->ipath_sdma_descq) { - ipath_dev_err(dd, "failed to allocate SendDMA descriptor " - "FIFO memory\n"); - ret = -ENOMEM; - goto done; - } - - dd->ipath_sdma_descq_cnt = - SDMA_DESCQ_SZ / sizeof(struct ipath_sdma_desc); - - /* Allocate memory for DMA of head register to memory */ - dd->ipath_sdma_head_dma = dma_alloc_coherent(&dd->pcidev->dev, - PAGE_SIZE, &dd->ipath_sdma_head_phys, GFP_KERNEL); - if (!dd->ipath_sdma_head_dma) { - ipath_dev_err(dd, "failed to allocate SendDMA head memory\n"); - ret = -ENOMEM; - goto cleanup_descq; - } - dd->ipath_sdma_head_dma[0] = 0; - - setup_timer(&dd->ipath_sdma_vl15_timer, vl15_watchdog_timeout, - (unsigned long)dd); - - atomic_set(&dd->ipath_sdma_vl15_count, 0); - - goto done; - -cleanup_descq: - dma_free_coherent(&dd->pcidev->dev, SDMA_DESCQ_SZ, - (void *)dd->ipath_sdma_descq, dd->ipath_sdma_descq_phys); - dd->ipath_sdma_descq = NULL; - dd->ipath_sdma_descq_phys = 0; -done: - return ret; -} - -int setup_sdma(struct ipath_devdata *dd) -{ - int ret = 0; - unsigned i, n; - u64 tmp64; - u64 senddmabufmask[3] = { 0 }; - unsigned long flags; - - ret = alloc_sdma(dd); - if (ret) - goto done; - - if (!dd->ipath_sdma_descq) { - ipath_dev_err(dd, "SendDMA memory not allocated\n"); - goto done; - } - - /* - * Set initial status as if we had been up, then gone down. - * This lets initial start on transition to ACTIVE be the - * same as restart after link flap. - */ - dd->ipath_sdma_status = IPATH_SDMA_ABORT_ABORTED; - dd->ipath_sdma_abort_jiffies = 0; - dd->ipath_sdma_generation = 0; - dd->ipath_sdma_descq_tail = 0; - dd->ipath_sdma_descq_head = 0; - dd->ipath_sdma_descq_removed = 0; - dd->ipath_sdma_descq_added = 0; - - /* Set SendDmaBase */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabase, - dd->ipath_sdma_descq_phys); - /* Set SendDmaLenGen */ - tmp64 = dd->ipath_sdma_descq_cnt; - tmp64 |= 1<<18; /* enable generation checking */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmalengen, tmp64); - /* Set SendDmaTail */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmatail, - dd->ipath_sdma_descq_tail); - /* Set SendDmaHeadAddr */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmaheadaddr, - dd->ipath_sdma_head_phys); - - /* - * Reserve all the former "kernel" piobufs, using high number range - * so we get as many 4K buffers as possible - */ - n = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k; - i = dd->ipath_lastport_piobuf + dd->ipath_pioreserved; - ipath_chg_pioavailkernel(dd, i, n - i , 0); - for (; i < n; ++i) { - unsigned word = i / 64; - unsigned bit = i & 63; - BUG_ON(word >= 3); - senddmabufmask[word] |= 1ULL << bit; - } - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask0, - senddmabufmask[0]); - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask1, - senddmabufmask[1]); - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask2, - senddmabufmask[2]); - - INIT_LIST_HEAD(&dd->ipath_sdma_activelist); - INIT_LIST_HEAD(&dd->ipath_sdma_notifylist); - - tasklet_init(&dd->ipath_sdma_notify_task, sdma_notify_task, - (unsigned long) dd); - tasklet_init(&dd->ipath_sdma_abort_task, sdma_abort_task, - (unsigned long) dd); - - /* - * No use to turn on SDMA here, as link is probably not ACTIVE - * Just mark it RUNNING and enable the interrupt, and let the - * ipath_restart_sdma() on link transition to ACTIVE actually - * enable it. - */ - spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); - dd->ipath_sendctrl |= INFINIPATH_S_SDMAINTENABLE; - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl); - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - __set_bit(IPATH_SDMA_RUNNING, &dd->ipath_sdma_status); - spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); - -done: - return ret; -} - -void teardown_sdma(struct ipath_devdata *dd) -{ - struct ipath_sdma_txreq *txp, *txpnext; - unsigned long flags; - dma_addr_t sdma_head_phys = 0; - dma_addr_t sdma_descq_phys = 0; - void *sdma_descq = NULL; - void *sdma_head_dma = NULL; - - spin_lock_irqsave(&dd->ipath_sdma_lock, flags); - __clear_bit(IPATH_SDMA_RUNNING, &dd->ipath_sdma_status); - __set_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status); - __set_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status); - spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); - - tasklet_kill(&dd->ipath_sdma_abort_task); - tasklet_kill(&dd->ipath_sdma_notify_task); - - /* turn off sdma */ - spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); - dd->ipath_sendctrl &= ~INFINIPATH_S_SDMAENABLE; - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, - dd->ipath_sendctrl); - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); - - spin_lock_irqsave(&dd->ipath_sdma_lock, flags); - /* dequeue all "sent" requests */ - list_for_each_entry_safe(txp, txpnext, &dd->ipath_sdma_activelist, - list) { - txp->callback_status = IPATH_SDMA_TXREQ_S_SHUTDOWN; - if (txp->flags & IPATH_SDMA_TXREQ_F_VL15) - vl15_watchdog_deq(dd); - list_move_tail(&txp->list, &dd->ipath_sdma_notifylist); - } - spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); - - sdma_notify_taskbody(dd); - - del_timer_sync(&dd->ipath_sdma_vl15_timer); - - spin_lock_irqsave(&dd->ipath_sdma_lock, flags); - - dd->ipath_sdma_abort_jiffies = 0; - - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabase, 0); - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmalengen, 0); - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmatail, 0); - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmaheadaddr, 0); - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask0, 0); - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask1, 0); - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask2, 0); - - if (dd->ipath_sdma_head_dma) { - sdma_head_dma = (void *) dd->ipath_sdma_head_dma; - sdma_head_phys = dd->ipath_sdma_head_phys; - dd->ipath_sdma_head_dma = NULL; - dd->ipath_sdma_head_phys = 0; - } - - if (dd->ipath_sdma_descq) { - sdma_descq = dd->ipath_sdma_descq; - sdma_descq_phys = dd->ipath_sdma_descq_phys; - dd->ipath_sdma_descq = NULL; - dd->ipath_sdma_descq_phys = 0; - } - - spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); - - if (sdma_head_dma) - dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE, - sdma_head_dma, sdma_head_phys); - - if (sdma_descq) - dma_free_coherent(&dd->pcidev->dev, SDMA_DESCQ_SZ, - sdma_descq, sdma_descq_phys); -} - -/* - * [Re]start SDMA, if we use it, and it's not already OK. - * This is called on transition to link ACTIVE, either the first or - * subsequent times. - */ -void ipath_restart_sdma(struct ipath_devdata *dd) -{ - unsigned long flags; - int needed = 1; - - if (!(dd->ipath_flags & IPATH_HAS_SEND_DMA)) - goto bail; - - /* - * First, make sure we should, which is to say, - * check that we are "RUNNING" (not in teardown) - * and not "SHUTDOWN" - */ - spin_lock_irqsave(&dd->ipath_sdma_lock, flags); - if (!test_bit(IPATH_SDMA_RUNNING, &dd->ipath_sdma_status) - || test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status)) - needed = 0; - else { - __clear_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status); - __clear_bit(IPATH_SDMA_DISARMED, &dd->ipath_sdma_status); - __clear_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status); - } - spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); - if (!needed) { - ipath_dbg("invalid attempt to restart SDMA, status 0x%08lx\n", - dd->ipath_sdma_status); - goto bail; - } - spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); - /* - * First clear, just to be safe. Enable is only done - * in chip on 0->1 transition - */ - dd->ipath_sendctrl &= ~INFINIPATH_S_SDMAENABLE; - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl); - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - dd->ipath_sendctrl |= INFINIPATH_S_SDMAENABLE; - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl); - ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); - spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); - - /* notify upper layers */ - ipath_ib_piobufavail(dd->verbs_dev); - -bail: - return; -} - -static inline void make_sdma_desc(struct ipath_devdata *dd, - u64 *sdmadesc, u64 addr, u64 dwlen, u64 dwoffset) -{ - WARN_ON(addr & 3); - /* SDmaPhyAddr[47:32] */ - sdmadesc[1] = addr >> 32; - /* SDmaPhyAddr[31:0] */ - sdmadesc[0] = (addr & 0xfffffffcULL) << 32; - /* SDmaGeneration[1:0] */ - sdmadesc[0] |= (dd->ipath_sdma_generation & 3ULL) << 30; - /* SDmaDwordCount[10:0] */ - sdmadesc[0] |= (dwlen & 0x7ffULL) << 16; - /* SDmaBufOffset[12:2] */ - sdmadesc[0] |= dwoffset & 0x7ffULL; -} - -/* - * This function queues one IB packet onto the send DMA queue per call. - * The caller is responsible for checking: - * 1) The number of send DMA descriptor entries is less than the size of - * the descriptor queue. - * 2) The IB SGE addresses and lengths are 32-bit aligned - * (except possibly the last SGE's length) - * 3) The SGE addresses are suitable for passing to dma_map_single(). - */ -int ipath_sdma_verbs_send(struct ipath_devdata *dd, - struct ipath_sge_state *ss, u32 dwords, - struct ipath_verbs_txreq *tx) -{ - - unsigned long flags; - struct ipath_sge *sge; - int ret = 0; - u16 tail; - __le64 *descqp; - u64 sdmadesc[2]; - u32 dwoffset; - dma_addr_t addr; - - if ((tx->map_len + (dwords<<2)) > dd->ipath_ibmaxlen) { - ipath_dbg("packet size %X > ibmax %X, fail\n", - tx->map_len + (dwords<<2), dd->ipath_ibmaxlen); - ret = -EMSGSIZE; - goto fail; - } - - spin_lock_irqsave(&dd->ipath_sdma_lock, flags); - -retry: - if (unlikely(test_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status))) { - ret = -EBUSY; - goto unlock; - } - - if (tx->txreq.sg_count > ipath_sdma_descq_freecnt(dd)) { - if (ipath_sdma_make_progress(dd)) - goto retry; - ret = -ENOBUFS; - goto unlock; - } - - addr = dma_map_single(&dd->pcidev->dev, tx->txreq.map_addr, - tx->map_len, DMA_TO_DEVICE); - if (dma_mapping_error(&dd->pcidev->dev, addr)) - goto ioerr; - - dwoffset = tx->map_len >> 2; - make_sdma_desc(dd, sdmadesc, (u64) addr, dwoffset, 0); - - /* SDmaFirstDesc */ - sdmadesc[0] |= 1ULL << 12; - if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_USELARGEBUF) - sdmadesc[0] |= 1ULL << 14; /* SDmaUseLargeBuf */ - - /* write to the descq */ - tail = dd->ipath_sdma_descq_tail; - descqp = &dd->ipath_sdma_descq[tail].qw[0]; - *descqp++ = cpu_to_le64(sdmadesc[0]); - *descqp++ = cpu_to_le64(sdmadesc[1]); - - if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_FREEDESC) - tx->txreq.start_idx = tail; - - /* increment the tail */ - if (++tail == dd->ipath_sdma_descq_cnt) { - tail = 0; - descqp = &dd->ipath_sdma_descq[0].qw[0]; - ++dd->ipath_sdma_generation; - } - - sge = &ss->sge; - while (dwords) { - u32 dw; - u32 len; - - len = dwords << 2; - if (len > sge->length) - len = sge->length; - if (len > sge->sge_length) - len = sge->sge_length; - BUG_ON(len == 0); - dw = (len + 3) >> 2; - addr = dma_map_single(&dd->pcidev->dev, sge->vaddr, dw << 2, - DMA_TO_DEVICE); - if (dma_mapping_error(&dd->pcidev->dev, addr)) - goto unmap; - make_sdma_desc(dd, sdmadesc, (u64) addr, dw, dwoffset); - /* SDmaUseLargeBuf has to be set in every descriptor */ - if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_USELARGEBUF) - sdmadesc[0] |= 1ULL << 14; - /* write to the descq */ - *descqp++ = cpu_to_le64(sdmadesc[0]); - *descqp++ = cpu_to_le64(sdmadesc[1]); - - /* increment the tail */ - if (++tail == dd->ipath_sdma_descq_cnt) { - tail = 0; - descqp = &dd->ipath_sdma_descq[0].qw[0]; - ++dd->ipath_sdma_generation; - } - sge->vaddr += len; - sge->length -= len; - sge->sge_length -= len; - if (sge->sge_length == 0) { - if (--ss->num_sge) - *sge = *ss->sg_list++; - } else if (sge->length == 0 && sge->mr != NULL) { - if (++sge->n >= IPATH_SEGSZ) { - if (++sge->m >= sge->mr->mapsz) - break; - sge->n = 0; - } - sge->vaddr = - sge->mr->map[sge->m]->segs[sge->n].vaddr; - sge->length = - sge->mr->map[sge->m]->segs[sge->n].length; - } - - dwoffset += dw; - dwords -= dw; - } - - if (!tail) - descqp = &dd->ipath_sdma_descq[dd->ipath_sdma_descq_cnt].qw[0]; - descqp -= 2; - /* SDmaLastDesc */ - descqp[0] |= cpu_to_le64(1ULL << 11); - if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_INTREQ) { - /* SDmaIntReq */ - descqp[0] |= cpu_to_le64(1ULL << 15); - } - - /* Commit writes to memory and advance the tail on the chip */ - wmb(); - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmatail, tail); - - tx->txreq.next_descq_idx = tail; - tx->txreq.callback_status = IPATH_SDMA_TXREQ_S_OK; - dd->ipath_sdma_descq_tail = tail; - dd->ipath_sdma_descq_added += tx->txreq.sg_count; - list_add_tail(&tx->txreq.list, &dd->ipath_sdma_activelist); - if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_VL15) - vl15_watchdog_enq(dd); - goto unlock; - -unmap: - while (tail != dd->ipath_sdma_descq_tail) { - if (!tail) - tail = dd->ipath_sdma_descq_cnt - 1; - else - tail--; - unmap_desc(dd, tail); - } -ioerr: - ret = -EIO; -unlock: - spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); -fail: - return ret; -} diff --git a/drivers/staging/rdma/ipath/ipath_srq.c b/drivers/staging/rdma/ipath/ipath_srq.c deleted file mode 100644 index 26271984b717..000000000000 --- a/drivers/staging/rdma/ipath/ipath_srq.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include - -#include "ipath_verbs.h" - -/** - * ipath_post_srq_receive - post a receive on a shared receive queue - * @ibsrq: the SRQ to post the receive on - * @wr: the list of work requests to post - * @bad_wr: the first WR to cause a problem is put here - * - * This may be called from interrupt context. - */ -int ipath_post_srq_receive(struct ib_srq *ibsrq, struct ib_recv_wr *wr, - struct ib_recv_wr **bad_wr) -{ - struct ipath_srq *srq = to_isrq(ibsrq); - struct ipath_rwq *wq; - unsigned long flags; - int ret; - - for (; wr; wr = wr->next) { - struct ipath_rwqe *wqe; - u32 next; - int i; - - if ((unsigned) wr->num_sge > srq->rq.max_sge) { - *bad_wr = wr; - ret = -EINVAL; - goto bail; - } - - spin_lock_irqsave(&srq->rq.lock, flags); - wq = srq->rq.wq; - next = wq->head + 1; - if (next >= srq->rq.size) - next = 0; - if (next == wq->tail) { - spin_unlock_irqrestore(&srq->rq.lock, flags); - *bad_wr = wr; - ret = -ENOMEM; - goto bail; - } - - wqe = get_rwqe_ptr(&srq->rq, wq->head); - wqe->wr_id = wr->wr_id; - wqe->num_sge = wr->num_sge; - for (i = 0; i < wr->num_sge; i++) - wqe->sg_list[i] = wr->sg_list[i]; - /* Make sure queue entry is written before the head index. */ - smp_wmb(); - wq->head = next; - spin_unlock_irqrestore(&srq->rq.lock, flags); - } - ret = 0; - -bail: - return ret; -} - -/** - * ipath_create_srq - create a shared receive queue - * @ibpd: the protection domain of the SRQ to create - * @srq_init_attr: the attributes of the SRQ - * @udata: data from libipathverbs when creating a user SRQ - */ -struct ib_srq *ipath_create_srq(struct ib_pd *ibpd, - struct ib_srq_init_attr *srq_init_attr, - struct ib_udata *udata) -{ - struct ipath_ibdev *dev = to_idev(ibpd->device); - struct ipath_srq *srq; - u32 sz; - struct ib_srq *ret; - - if (srq_init_attr->srq_type != IB_SRQT_BASIC) { - ret = ERR_PTR(-ENOSYS); - goto done; - } - - if (srq_init_attr->attr.max_wr == 0) { - ret = ERR_PTR(-EINVAL); - goto done; - } - - if ((srq_init_attr->attr.max_sge > ib_ipath_max_srq_sges) || - (srq_init_attr->attr.max_wr > ib_ipath_max_srq_wrs)) { - ret = ERR_PTR(-EINVAL); - goto done; - } - - srq = kmalloc(sizeof(*srq), GFP_KERNEL); - if (!srq) { - ret = ERR_PTR(-ENOMEM); - goto done; - } - - /* - * Need to use vmalloc() if we want to support large #s of entries. - */ - srq->rq.size = srq_init_attr->attr.max_wr + 1; - srq->rq.max_sge = srq_init_attr->attr.max_sge; - sz = sizeof(struct ib_sge) * srq->rq.max_sge + - sizeof(struct ipath_rwqe); - srq->rq.wq = vmalloc_user(sizeof(struct ipath_rwq) + srq->rq.size * sz); - if (!srq->rq.wq) { - ret = ERR_PTR(-ENOMEM); - goto bail_srq; - } - - /* - * Return the address of the RWQ as the offset to mmap. - * See ipath_mmap() for details. - */ - if (udata && udata->outlen >= sizeof(__u64)) { - int err; - u32 s = sizeof(struct ipath_rwq) + srq->rq.size * sz; - - srq->ip = - ipath_create_mmap_info(dev, s, - ibpd->uobject->context, - srq->rq.wq); - if (!srq->ip) { - ret = ERR_PTR(-ENOMEM); - goto bail_wq; - } - - err = ib_copy_to_udata(udata, &srq->ip->offset, - sizeof(srq->ip->offset)); - if (err) { - ret = ERR_PTR(err); - goto bail_ip; - } - } else - srq->ip = NULL; - - /* - * ib_create_srq() will initialize srq->ibsrq. - */ - spin_lock_init(&srq->rq.lock); - srq->rq.wq->head = 0; - srq->rq.wq->tail = 0; - srq->limit = srq_init_attr->attr.srq_limit; - - spin_lock(&dev->n_srqs_lock); - if (dev->n_srqs_allocated == ib_ipath_max_srqs) { - spin_unlock(&dev->n_srqs_lock); - ret = ERR_PTR(-ENOMEM); - goto bail_ip; - } - - dev->n_srqs_allocated++; - spin_unlock(&dev->n_srqs_lock); - - if (srq->ip) { - spin_lock_irq(&dev->pending_lock); - list_add(&srq->ip->pending_mmaps, &dev->pending_mmaps); - spin_unlock_irq(&dev->pending_lock); - } - - ret = &srq->ibsrq; - goto done; - -bail_ip: - kfree(srq->ip); -bail_wq: - vfree(srq->rq.wq); -bail_srq: - kfree(srq); -done: - return ret; -} - -/** - * ipath_modify_srq - modify a shared receive queue - * @ibsrq: the SRQ to modify - * @attr: the new attributes of the SRQ - * @attr_mask: indicates which attributes to modify - * @udata: user data for ipathverbs.so - */ -int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, - enum ib_srq_attr_mask attr_mask, - struct ib_udata *udata) -{ - struct ipath_srq *srq = to_isrq(ibsrq); - struct ipath_rwq *wq; - int ret = 0; - - if (attr_mask & IB_SRQ_MAX_WR) { - struct ipath_rwq *owq; - struct ipath_rwqe *p; - u32 sz, size, n, head, tail; - - /* Check that the requested sizes are below the limits. */ - if ((attr->max_wr > ib_ipath_max_srq_wrs) || - ((attr_mask & IB_SRQ_LIMIT) ? - attr->srq_limit : srq->limit) > attr->max_wr) { - ret = -EINVAL; - goto bail; - } - - sz = sizeof(struct ipath_rwqe) + - srq->rq.max_sge * sizeof(struct ib_sge); - size = attr->max_wr + 1; - wq = vmalloc_user(sizeof(struct ipath_rwq) + size * sz); - if (!wq) { - ret = -ENOMEM; - goto bail; - } - - /* Check that we can write the offset to mmap. */ - if (udata && udata->inlen >= sizeof(__u64)) { - __u64 offset_addr; - __u64 offset = 0; - - ret = ib_copy_from_udata(&offset_addr, udata, - sizeof(offset_addr)); - if (ret) - goto bail_free; - udata->outbuf = - (void __user *) (unsigned long) offset_addr; - ret = ib_copy_to_udata(udata, &offset, - sizeof(offset)); - if (ret) - goto bail_free; - } - - spin_lock_irq(&srq->rq.lock); - /* - * validate head pointer value and compute - * the number of remaining WQEs. - */ - owq = srq->rq.wq; - head = owq->head; - if (head >= srq->rq.size) - head = 0; - tail = owq->tail; - if (tail >= srq->rq.size) - tail = 0; - n = head; - if (n < tail) - n += srq->rq.size - tail; - else - n -= tail; - if (size <= n) { - ret = -EINVAL; - goto bail_unlock; - } - n = 0; - p = wq->wq; - while (tail != head) { - struct ipath_rwqe *wqe; - int i; - - wqe = get_rwqe_ptr(&srq->rq, tail); - p->wr_id = wqe->wr_id; - p->num_sge = wqe->num_sge; - for (i = 0; i < wqe->num_sge; i++) - p->sg_list[i] = wqe->sg_list[i]; - n++; - p = (struct ipath_rwqe *)((char *) p + sz); - if (++tail >= srq->rq.size) - tail = 0; - } - srq->rq.wq = wq; - srq->rq.size = size; - wq->head = n; - wq->tail = 0; - if (attr_mask & IB_SRQ_LIMIT) - srq->limit = attr->srq_limit; - spin_unlock_irq(&srq->rq.lock); - - vfree(owq); - - if (srq->ip) { - struct ipath_mmap_info *ip = srq->ip; - struct ipath_ibdev *dev = to_idev(srq->ibsrq.device); - u32 s = sizeof(struct ipath_rwq) + size * sz; - - ipath_update_mmap_info(dev, ip, s, wq); - - /* - * Return the offset to mmap. - * See ipath_mmap() for details. - */ - if (udata && udata->inlen >= sizeof(__u64)) { - ret = ib_copy_to_udata(udata, &ip->offset, - sizeof(ip->offset)); - if (ret) - goto bail; - } - - spin_lock_irq(&dev->pending_lock); - if (list_empty(&ip->pending_mmaps)) - list_add(&ip->pending_mmaps, - &dev->pending_mmaps); - spin_unlock_irq(&dev->pending_lock); - } - } else if (attr_mask & IB_SRQ_LIMIT) { - spin_lock_irq(&srq->rq.lock); - if (attr->srq_limit >= srq->rq.size) - ret = -EINVAL; - else - srq->limit = attr->srq_limit; - spin_unlock_irq(&srq->rq.lock); - } - goto bail; - -bail_unlock: - spin_unlock_irq(&srq->rq.lock); -bail_free: - vfree(wq); -bail: - return ret; -} - -int ipath_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr) -{ - struct ipath_srq *srq = to_isrq(ibsrq); - - attr->max_wr = srq->rq.size - 1; - attr->max_sge = srq->rq.max_sge; - attr->srq_limit = srq->limit; - return 0; -} - -/** - * ipath_destroy_srq - destroy a shared receive queue - * @ibsrq: the SRQ to destroy - */ -int ipath_destroy_srq(struct ib_srq *ibsrq) -{ - struct ipath_srq *srq = to_isrq(ibsrq); - struct ipath_ibdev *dev = to_idev(ibsrq->device); - - spin_lock(&dev->n_srqs_lock); - dev->n_srqs_allocated--; - spin_unlock(&dev->n_srqs_lock); - if (srq->ip) - kref_put(&srq->ip->ref, ipath_release_mmap_info); - else - vfree(srq->rq.wq); - kfree(srq); - - return 0; -} diff --git a/drivers/staging/rdma/ipath/ipath_stats.c b/drivers/staging/rdma/ipath/ipath_stats.c deleted file mode 100644 index f63e143e3292..000000000000 --- a/drivers/staging/rdma/ipath/ipath_stats.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "ipath_kernel.h" - -struct infinipath_stats ipath_stats; - -/** - * ipath_snap_cntr - snapshot a chip counter - * @dd: the infinipath device - * @creg: the counter to snapshot - * - * called from add_timer and user counter read calls, to deal with - * counters that wrap in "human time". The words sent and received, and - * the packets sent and received are all that we worry about. For now, - * at least, we don't worry about error counters, because if they wrap - * that quickly, we probably don't care. We may eventually just make this - * handle all the counters. word counters can wrap in about 20 seconds - * of full bandwidth traffic, packet counters in a few hours. - */ - -u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg) -{ - u32 val, reg64 = 0; - u64 val64; - unsigned long t0, t1; - u64 ret; - - t0 = jiffies; - /* If fast increment counters are only 32 bits, snapshot them, - * and maintain them as 64bit values in the driver */ - if (!(dd->ipath_flags & IPATH_32BITCOUNTERS) && - (creg == dd->ipath_cregs->cr_wordsendcnt || - creg == dd->ipath_cregs->cr_wordrcvcnt || - creg == dd->ipath_cregs->cr_pktsendcnt || - creg == dd->ipath_cregs->cr_pktrcvcnt)) { - val64 = ipath_read_creg(dd, creg); - val = val64 == ~0ULL ? ~0U : 0; - reg64 = 1; - } else /* val64 just to keep gcc quiet... */ - val64 = val = ipath_read_creg32(dd, creg); - /* - * See if a second has passed. This is just a way to detect things - * that are quite broken. Normally this should take just a few - * cycles (the check is for long enough that we don't care if we get - * pre-empted.) An Opteron HT O read timeout is 4 seconds with - * normal NB values - */ - t1 = jiffies; - if (time_before(t0 + HZ, t1) && val == -1) { - ipath_dev_err(dd, "Error! Read counter 0x%x timed out\n", - creg); - ret = 0ULL; - goto bail; - } - if (reg64) { - ret = val64; - goto bail; - } - - if (creg == dd->ipath_cregs->cr_wordsendcnt) { - if (val != dd->ipath_lastsword) { - dd->ipath_sword += val - dd->ipath_lastsword; - dd->ipath_lastsword = val; - } - val64 = dd->ipath_sword; - } else if (creg == dd->ipath_cregs->cr_wordrcvcnt) { - if (val != dd->ipath_lastrword) { - dd->ipath_rword += val - dd->ipath_lastrword; - dd->ipath_lastrword = val; - } - val64 = dd->ipath_rword; - } else if (creg == dd->ipath_cregs->cr_pktsendcnt) { - if (val != dd->ipath_lastspkts) { - dd->ipath_spkts += val - dd->ipath_lastspkts; - dd->ipath_lastspkts = val; - } - val64 = dd->ipath_spkts; - } else if (creg == dd->ipath_cregs->cr_pktrcvcnt) { - if (val != dd->ipath_lastrpkts) { - dd->ipath_rpkts += val - dd->ipath_lastrpkts; - dd->ipath_lastrpkts = val; - } - val64 = dd->ipath_rpkts; - } else if (creg == dd->ipath_cregs->cr_ibsymbolerrcnt) { - if (dd->ibdeltainprog) - val64 -= val64 - dd->ibsymsnap; - val64 -= dd->ibsymdelta; - } else if (creg == dd->ipath_cregs->cr_iblinkerrrecovcnt) { - if (dd->ibdeltainprog) - val64 -= val64 - dd->iblnkerrsnap; - val64 -= dd->iblnkerrdelta; - } else - val64 = (u64) val; - - ret = val64; - -bail: - return ret; -} - -/** - * ipath_qcheck - print delta of egrfull/hdrqfull errors for kernel ports - * @dd: the infinipath device - * - * print the delta of egrfull/hdrqfull errors for kernel ports no more than - * every 5 seconds. User processes are printed at close, but kernel doesn't - * close, so... Separate routine so may call from other places someday, and - * so function name when printed by _IPATH_INFO is meaningfull - */ -static void ipath_qcheck(struct ipath_devdata *dd) -{ - static u64 last_tot_hdrqfull; - struct ipath_portdata *pd = dd->ipath_pd[0]; - size_t blen = 0; - char buf[128]; - u32 hdrqtail; - - *buf = 0; - if (pd->port_hdrqfull != dd->ipath_p0_hdrqfull) { - blen = snprintf(buf, sizeof buf, "port 0 hdrqfull %u", - pd->port_hdrqfull - - dd->ipath_p0_hdrqfull); - dd->ipath_p0_hdrqfull = pd->port_hdrqfull; - } - if (ipath_stats.sps_etidfull != dd->ipath_last_tidfull) { - blen += snprintf(buf + blen, sizeof buf - blen, - "%srcvegrfull %llu", - blen ? ", " : "", - (unsigned long long) - (ipath_stats.sps_etidfull - - dd->ipath_last_tidfull)); - dd->ipath_last_tidfull = ipath_stats.sps_etidfull; - } - - /* - * this is actually the number of hdrq full interrupts, not actual - * events, but at the moment that's mostly what I'm interested in. - * Actual count, etc. is in the counters, if needed. For production - * users this won't ordinarily be printed. - */ - - if ((ipath_debug & (__IPATH_PKTDBG | __IPATH_DBG)) && - ipath_stats.sps_hdrqfull != last_tot_hdrqfull) { - blen += snprintf(buf + blen, sizeof buf - blen, - "%shdrqfull %llu (all ports)", - blen ? ", " : "", - (unsigned long long) - (ipath_stats.sps_hdrqfull - - last_tot_hdrqfull)); - last_tot_hdrqfull = ipath_stats.sps_hdrqfull; - } - if (blen) - ipath_dbg("%s\n", buf); - - hdrqtail = ipath_get_hdrqtail(pd); - if (pd->port_head != hdrqtail) { - if (dd->ipath_lastport0rcv_cnt == - ipath_stats.sps_port0pkts) { - ipath_cdbg(PKT, "missing rcv interrupts? " - "port0 hd=%x tl=%x; port0pkts %llx; write" - " hd (w/intr)\n", - pd->port_head, hdrqtail, - (unsigned long long) - ipath_stats.sps_port0pkts); - ipath_write_ureg(dd, ur_rcvhdrhead, hdrqtail | - dd->ipath_rhdrhead_intr_off, pd->port_port); - } - dd->ipath_lastport0rcv_cnt = ipath_stats.sps_port0pkts; - } -} - -static void ipath_chk_errormask(struct ipath_devdata *dd) -{ - static u32 fixed; - u32 ctrl; - unsigned long errormask; - unsigned long hwerrs; - - if (!dd->ipath_errormask || !(dd->ipath_flags & IPATH_INITTED)) - return; - - errormask = ipath_read_kreg64(dd, dd->ipath_kregs->kr_errormask); - - if (errormask == dd->ipath_errormask) - return; - fixed++; - - hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus); - ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control); - - ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, - dd->ipath_errormask); - - if ((hwerrs & dd->ipath_hwerrmask) || - (ctrl & INFINIPATH_C_FREEZEMODE)) { - /* force re-interrupt of pending events, just in case */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, 0ULL); - ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, 0ULL); - ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL); - dev_info(&dd->pcidev->dev, - "errormask fixed(%u) %lx -> %lx, ctrl %x hwerr %lx\n", - fixed, errormask, (unsigned long)dd->ipath_errormask, - ctrl, hwerrs); - } else - ipath_dbg("errormask fixed(%u) %lx -> %lx, no freeze\n", - fixed, errormask, - (unsigned long)dd->ipath_errormask); -} - - -/** - * ipath_get_faststats - get word counters from chip before they overflow - * @opaque - contains a pointer to the infinipath device ipath_devdata - * - * called from add_timer - */ -void ipath_get_faststats(unsigned long opaque) -{ - struct ipath_devdata *dd = (struct ipath_devdata *) opaque; - int i; - static unsigned cnt; - unsigned long flags; - u64 traffic_wds; - - /* - * don't access the chip while running diags, or memory diags can - * fail - */ - if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_INITTED) || - ipath_diag_inuse) - /* but re-arm the timer, for diags case; won't hurt other */ - goto done; - - /* - * We now try to maintain a "active timer", based on traffic - * exceeding a threshold, so we need to check the word-counts - * even if they are 64-bit. - */ - traffic_wds = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt) + - ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt); - spin_lock_irqsave(&dd->ipath_eep_st_lock, flags); - traffic_wds -= dd->ipath_traffic_wds; - dd->ipath_traffic_wds += traffic_wds; - if (traffic_wds >= IPATH_TRAFFIC_ACTIVE_THRESHOLD) - atomic_add(5, &dd->ipath_active_time); /* S/B #define */ - spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags); - - if (dd->ipath_flags & IPATH_32BITCOUNTERS) { - ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt); - ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt); - } - - ipath_qcheck(dd); - - /* - * deal with repeat error suppression. Doesn't really matter if - * last error was almost a full interval ago, or just a few usecs - * ago; still won't get more than 2 per interval. We may want - * longer intervals for this eventually, could do with mod, counter - * or separate timer. Also see code in ipath_handle_errors() and - * ipath_handle_hwerrors(). - */ - - if (dd->ipath_lasterror) - dd->ipath_lasterror = 0; - if (dd->ipath_lasthwerror) - dd->ipath_lasthwerror = 0; - if (dd->ipath_maskederrs - && time_after(jiffies, dd->ipath_unmasktime)) { - char ebuf[256]; - int iserr; - iserr = ipath_decode_err(dd, ebuf, sizeof ebuf, - dd->ipath_maskederrs); - if (dd->ipath_maskederrs & - ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL | - INFINIPATH_E_PKTERRS)) - ipath_dev_err(dd, "Re-enabling masked errors " - "(%s)\n", ebuf); - else { - /* - * rcvegrfull and rcvhdrqfull are "normal", for some - * types of processes (mostly benchmarks) that send - * huge numbers of messages, while not processing - * them. So only complain about these at debug - * level. - */ - if (iserr) - ipath_dbg( - "Re-enabling queue full errors (%s)\n", - ebuf); - else - ipath_cdbg(ERRPKT, "Re-enabling packet" - " problem interrupt (%s)\n", ebuf); - } - - /* re-enable masked errors */ - dd->ipath_errormask |= dd->ipath_maskederrs; - ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, - dd->ipath_errormask); - dd->ipath_maskederrs = 0; - } - - /* limit qfull messages to ~one per minute per port */ - if ((++cnt & 0x10)) { - for (i = (int) dd->ipath_cfgports; --i >= 0; ) { - struct ipath_portdata *pd = dd->ipath_pd[i]; - - if (pd && pd->port_lastrcvhdrqtail != -1) - pd->port_lastrcvhdrqtail = -1; - } - } - - ipath_chk_errormask(dd); -done: - mod_timer(&dd->ipath_stats_timer, jiffies + HZ * 5); -} diff --git a/drivers/staging/rdma/ipath/ipath_sysfs.c b/drivers/staging/rdma/ipath/ipath_sysfs.c deleted file mode 100644 index b12b1f6caf59..000000000000 --- a/drivers/staging/rdma/ipath/ipath_sysfs.c +++ /dev/null @@ -1,1237 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include "ipath_kernel.h" -#include "ipath_verbs.h" -#include "ipath_common.h" - -/** - * ipath_parse_ushort - parse an unsigned short value in an arbitrary base - * @str: the string containing the number - * @valp: where to put the result - * - * returns the number of bytes consumed, or negative value on error - */ -int ipath_parse_ushort(const char *str, unsigned short *valp) -{ - unsigned long val; - char *end; - int ret; - - if (!isdigit(str[0])) { - ret = -EINVAL; - goto bail; - } - - val = simple_strtoul(str, &end, 0); - - if (val > 0xffff) { - ret = -EINVAL; - goto bail; - } - - *valp = val; - - ret = end + 1 - str; - if (ret == 0) - ret = -EINVAL; - -bail: - return ret; -} - -static ssize_t show_version(struct device_driver *dev, char *buf) -{ - /* The string printed here is already newline-terminated. */ - return scnprintf(buf, PAGE_SIZE, "%s", ib_ipath_version); -} - -static ssize_t show_num_units(struct device_driver *dev, char *buf) -{ - return scnprintf(buf, PAGE_SIZE, "%d\n", - ipath_count_units(NULL, NULL, NULL)); -} - -static ssize_t show_status(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - ssize_t ret; - - if (!dd->ipath_statusp) { - ret = -EINVAL; - goto bail; - } - - ret = scnprintf(buf, PAGE_SIZE, "0x%llx\n", - (unsigned long long) *(dd->ipath_statusp)); - -bail: - return ret; -} - -static const char *ipath_status_str[] = { - "Initted", - "Disabled", - "Admin_Disabled", - "", /* This used to be the old "OIB_SMA" status. */ - "", /* This used to be the old "SMA" status. */ - "Present", - "IB_link_up", - "IB_configured", - "NoIBcable", - "Fatal_Hardware_Error", - NULL, -}; - -static ssize_t show_status_str(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int i, any; - u64 s; - ssize_t ret; - - if (!dd->ipath_statusp) { - ret = -EINVAL; - goto bail; - } - - s = *(dd->ipath_statusp); - *buf = '\0'; - for (any = i = 0; s && ipath_status_str[i]; i++) { - if (s & 1) { - if (any && strlcat(buf, " ", PAGE_SIZE) >= - PAGE_SIZE) - /* overflow */ - break; - if (strlcat(buf, ipath_status_str[i], - PAGE_SIZE) >= PAGE_SIZE) - break; - any = 1; - } - s >>= 1; - } - if (any) - strlcat(buf, "\n", PAGE_SIZE); - - ret = strlen(buf); - -bail: - return ret; -} - -static ssize_t show_boardversion(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - /* The string printed here is already newline-terminated. */ - return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_boardversion); -} - -static ssize_t show_localbus_info(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - /* The string printed here is already newline-terminated. */ - return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_lbus_info); -} - -static ssize_t show_lmc(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - - return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_lmc); -} - -static ssize_t store_lmc(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - u16 lmc = 0; - int ret; - - ret = ipath_parse_ushort(buf, &lmc); - if (ret < 0) - goto invalid; - - if (lmc > 7) { - ret = -EINVAL; - goto invalid; - } - - ipath_set_lid(dd, dd->ipath_lid, lmc); - - goto bail; -invalid: - ipath_dev_err(dd, "attempt to set invalid LMC %u\n", lmc); -bail: - return ret; -} - -static ssize_t show_lid(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - - return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_lid); -} - -static ssize_t store_lid(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - u16 lid = 0; - int ret; - - ret = ipath_parse_ushort(buf, &lid); - if (ret < 0) - goto invalid; - - if (lid == 0 || lid >= IPATH_MULTICAST_LID_BASE) { - ret = -EINVAL; - goto invalid; - } - - ipath_set_lid(dd, lid, dd->ipath_lmc); - - goto bail; -invalid: - ipath_dev_err(dd, "attempt to set invalid LID 0x%x\n", lid); -bail: - return ret; -} - -static ssize_t show_mlid(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - - return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_mlid); -} - -static ssize_t store_mlid(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - u16 mlid; - int ret; - - ret = ipath_parse_ushort(buf, &mlid); - if (ret < 0 || mlid < IPATH_MULTICAST_LID_BASE) - goto invalid; - - dd->ipath_mlid = mlid; - - goto bail; -invalid: - ipath_dev_err(dd, "attempt to set invalid MLID\n"); -bail: - return ret; -} - -static ssize_t show_guid(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - u8 *guid; - - guid = (u8 *) & (dd->ipath_guid); - - return scnprintf(buf, PAGE_SIZE, - "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", - guid[0], guid[1], guid[2], guid[3], - guid[4], guid[5], guid[6], guid[7]); -} - -static ssize_t store_guid(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - ssize_t ret; - unsigned short guid[8]; - __be64 new_guid; - u8 *ng; - int i; - - if (sscanf(buf, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx", - &guid[0], &guid[1], &guid[2], &guid[3], - &guid[4], &guid[5], &guid[6], &guid[7]) != 8) - goto invalid; - - ng = (u8 *) &new_guid; - - for (i = 0; i < 8; i++) { - if (guid[i] > 0xff) - goto invalid; - ng[i] = guid[i]; - } - - if (new_guid == 0) - goto invalid; - - dd->ipath_guid = new_guid; - dd->ipath_nguid = 1; - if (dd->verbs_dev) - dd->verbs_dev->ibdev.node_guid = new_guid; - - ret = strlen(buf); - goto bail; - -invalid: - ipath_dev_err(dd, "attempt to set invalid GUID\n"); - ret = -EINVAL; - -bail: - return ret; -} - -static ssize_t show_nguid(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - - return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_nguid); -} - -static ssize_t show_nports(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - - /* Return the number of user ports available. */ - return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_cfgports - 1); -} - -static ssize_t show_serial(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - - buf[sizeof dd->ipath_serial] = '\0'; - memcpy(buf, dd->ipath_serial, sizeof dd->ipath_serial); - strcat(buf, "\n"); - return strlen(buf); -} - -static ssize_t show_unit(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - - return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_unit); -} - -static ssize_t show_jint_max_packets(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - - return scnprintf(buf, PAGE_SIZE, "%hu\n", dd->ipath_jint_max_packets); -} - -static ssize_t store_jint_max_packets(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - u16 v = 0; - int ret; - - ret = ipath_parse_ushort(buf, &v); - if (ret < 0) - ipath_dev_err(dd, "invalid jint_max_packets.\n"); - else - dd->ipath_f_config_jint(dd, dd->ipath_jint_idle_ticks, v); - - return ret; -} - -static ssize_t show_jint_idle_ticks(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - - return scnprintf(buf, PAGE_SIZE, "%hu\n", dd->ipath_jint_idle_ticks); -} - -static ssize_t store_jint_idle_ticks(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - u16 v = 0; - int ret; - - ret = ipath_parse_ushort(buf, &v); - if (ret < 0) - ipath_dev_err(dd, "invalid jint_idle_ticks.\n"); - else - dd->ipath_f_config_jint(dd, v, dd->ipath_jint_max_packets); - - return ret; -} - -#define DEVICE_COUNTER(name, attr) \ - static ssize_t show_counter_##name(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ - { \ - struct ipath_devdata *dd = dev_get_drvdata(dev); \ - return scnprintf(\ - buf, PAGE_SIZE, "%llu\n", (unsigned long long) \ - ipath_snap_cntr( \ - dd, offsetof(struct infinipath_counters, \ - attr) / sizeof(u64))); \ - } \ - static DEVICE_ATTR(name, S_IRUGO, show_counter_##name, NULL); - -DEVICE_COUNTER(ib_link_downeds, IBLinkDownedCnt); -DEVICE_COUNTER(ib_link_err_recoveries, IBLinkErrRecoveryCnt); -DEVICE_COUNTER(ib_status_changes, IBStatusChangeCnt); -DEVICE_COUNTER(ib_symbol_errs, IBSymbolErrCnt); -DEVICE_COUNTER(lb_flow_stalls, LBFlowStallCnt); -DEVICE_COUNTER(lb_ints, LBIntCnt); -DEVICE_COUNTER(rx_bad_formats, RxBadFormatCnt); -DEVICE_COUNTER(rx_buf_ovfls, RxBufOvflCnt); -DEVICE_COUNTER(rx_data_pkts, RxDataPktCnt); -DEVICE_COUNTER(rx_dropped_pkts, RxDroppedPktCnt); -DEVICE_COUNTER(rx_dwords, RxDwordCnt); -DEVICE_COUNTER(rx_ebps, RxEBPCnt); -DEVICE_COUNTER(rx_flow_ctrl_errs, RxFlowCtrlErrCnt); -DEVICE_COUNTER(rx_flow_pkts, RxFlowPktCnt); -DEVICE_COUNTER(rx_icrc_errs, RxICRCErrCnt); -DEVICE_COUNTER(rx_len_errs, RxLenErrCnt); -DEVICE_COUNTER(rx_link_problems, RxLinkProblemCnt); -DEVICE_COUNTER(rx_lpcrc_errs, RxLPCRCErrCnt); -DEVICE_COUNTER(rx_max_min_len_errs, RxMaxMinLenErrCnt); -DEVICE_COUNTER(rx_p0_hdr_egr_ovfls, RxP0HdrEgrOvflCnt); -DEVICE_COUNTER(rx_p1_hdr_egr_ovfls, RxP1HdrEgrOvflCnt); -DEVICE_COUNTER(rx_p2_hdr_egr_ovfls, RxP2HdrEgrOvflCnt); -DEVICE_COUNTER(rx_p3_hdr_egr_ovfls, RxP3HdrEgrOvflCnt); -DEVICE_COUNTER(rx_p4_hdr_egr_ovfls, RxP4HdrEgrOvflCnt); -DEVICE_COUNTER(rx_p5_hdr_egr_ovfls, RxP5HdrEgrOvflCnt); -DEVICE_COUNTER(rx_p6_hdr_egr_ovfls, RxP6HdrEgrOvflCnt); -DEVICE_COUNTER(rx_p7_hdr_egr_ovfls, RxP7HdrEgrOvflCnt); -DEVICE_COUNTER(rx_p8_hdr_egr_ovfls, RxP8HdrEgrOvflCnt); -DEVICE_COUNTER(rx_pkey_mismatches, RxPKeyMismatchCnt); -DEVICE_COUNTER(rx_tid_full_errs, RxTIDFullErrCnt); -DEVICE_COUNTER(rx_tid_valid_errs, RxTIDValidErrCnt); -DEVICE_COUNTER(rx_vcrc_errs, RxVCRCErrCnt); -DEVICE_COUNTER(tx_data_pkts, TxDataPktCnt); -DEVICE_COUNTER(tx_dropped_pkts, TxDroppedPktCnt); -DEVICE_COUNTER(tx_dwords, TxDwordCnt); -DEVICE_COUNTER(tx_flow_pkts, TxFlowPktCnt); -DEVICE_COUNTER(tx_flow_stalls, TxFlowStallCnt); -DEVICE_COUNTER(tx_len_errs, TxLenErrCnt); -DEVICE_COUNTER(tx_max_min_len_errs, TxMaxMinLenErrCnt); -DEVICE_COUNTER(tx_underruns, TxUnderrunCnt); -DEVICE_COUNTER(tx_unsup_vl_errs, TxUnsupVLErrCnt); - -static struct attribute *dev_counter_attributes[] = { - &dev_attr_ib_link_downeds.attr, - &dev_attr_ib_link_err_recoveries.attr, - &dev_attr_ib_status_changes.attr, - &dev_attr_ib_symbol_errs.attr, - &dev_attr_lb_flow_stalls.attr, - &dev_attr_lb_ints.attr, - &dev_attr_rx_bad_formats.attr, - &dev_attr_rx_buf_ovfls.attr, - &dev_attr_rx_data_pkts.attr, - &dev_attr_rx_dropped_pkts.attr, - &dev_attr_rx_dwords.attr, - &dev_attr_rx_ebps.attr, - &dev_attr_rx_flow_ctrl_errs.attr, - &dev_attr_rx_flow_pkts.attr, - &dev_attr_rx_icrc_errs.attr, - &dev_attr_rx_len_errs.attr, - &dev_attr_rx_link_problems.attr, - &dev_attr_rx_lpcrc_errs.attr, - &dev_attr_rx_max_min_len_errs.attr, - &dev_attr_rx_p0_hdr_egr_ovfls.attr, - &dev_attr_rx_p1_hdr_egr_ovfls.attr, - &dev_attr_rx_p2_hdr_egr_ovfls.attr, - &dev_attr_rx_p3_hdr_egr_ovfls.attr, - &dev_attr_rx_p4_hdr_egr_ovfls.attr, - &dev_attr_rx_p5_hdr_egr_ovfls.attr, - &dev_attr_rx_p6_hdr_egr_ovfls.attr, - &dev_attr_rx_p7_hdr_egr_ovfls.attr, - &dev_attr_rx_p8_hdr_egr_ovfls.attr, - &dev_attr_rx_pkey_mismatches.attr, - &dev_attr_rx_tid_full_errs.attr, - &dev_attr_rx_tid_valid_errs.attr, - &dev_attr_rx_vcrc_errs.attr, - &dev_attr_tx_data_pkts.attr, - &dev_attr_tx_dropped_pkts.attr, - &dev_attr_tx_dwords.attr, - &dev_attr_tx_flow_pkts.attr, - &dev_attr_tx_flow_stalls.attr, - &dev_attr_tx_len_errs.attr, - &dev_attr_tx_max_min_len_errs.attr, - &dev_attr_tx_underruns.attr, - &dev_attr_tx_unsup_vl_errs.attr, - NULL -}; - -static struct attribute_group dev_counter_attr_group = { - .name = "counters", - .attrs = dev_counter_attributes -}; - -static ssize_t store_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret; - - if (count < 5 || memcmp(buf, "reset", 5)) { - ret = -EINVAL; - goto bail; - } - - if (dd->ipath_flags & IPATH_DISABLED) { - /* - * post-reset init would re-enable interrupts, etc. - * so don't allow reset on disabled devices. Not - * perfect error, but about the best choice. - */ - dev_info(dev,"Unit %d is disabled, can't reset\n", - dd->ipath_unit); - ret = -EINVAL; - goto bail; - } - ret = ipath_reset_device(dd->ipath_unit); -bail: - return ret<0 ? ret : count; -} - -static ssize_t store_link_state(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret, r; - u16 state; - - ret = ipath_parse_ushort(buf, &state); - if (ret < 0) - goto invalid; - - r = ipath_set_linkstate(dd, state); - if (r < 0) { - ret = r; - goto bail; - } - - goto bail; -invalid: - ipath_dev_err(dd, "attempt to set invalid link state\n"); -bail: - return ret; -} - -static ssize_t show_mtu(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_ibmtu); -} - -static ssize_t store_mtu(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - ssize_t ret; - u16 mtu = 0; - int r; - - ret = ipath_parse_ushort(buf, &mtu); - if (ret < 0) - goto invalid; - - r = ipath_set_mtu(dd, mtu); - if (r < 0) - ret = r; - - goto bail; -invalid: - ipath_dev_err(dd, "attempt to set invalid MTU\n"); -bail: - return ret; -} - -static ssize_t show_enabled(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - return scnprintf(buf, PAGE_SIZE, "%u\n", - (dd->ipath_flags & IPATH_DISABLED) ? 0 : 1); -} - -static ssize_t store_enabled(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - ssize_t ret; - u16 enable = 0; - - ret = ipath_parse_ushort(buf, &enable); - if (ret < 0) { - ipath_dev_err(dd, "attempt to use non-numeric on enable\n"); - goto bail; - } - - if (enable) { - if (!(dd->ipath_flags & IPATH_DISABLED)) - goto bail; - - dev_info(dev, "Enabling unit %d\n", dd->ipath_unit); - /* same as post-reset */ - ret = ipath_init_chip(dd, 1); - if (ret) - ipath_dev_err(dd, "Failed to enable unit %d\n", - dd->ipath_unit); - else { - dd->ipath_flags &= ~IPATH_DISABLED; - *dd->ipath_statusp &= ~IPATH_STATUS_ADMIN_DISABLED; - } - } else if (!(dd->ipath_flags & IPATH_DISABLED)) { - dev_info(dev, "Disabling unit %d\n", dd->ipath_unit); - ipath_shutdown_device(dd); - dd->ipath_flags |= IPATH_DISABLED; - *dd->ipath_statusp |= IPATH_STATUS_ADMIN_DISABLED; - } - -bail: - return ret; -} - -static ssize_t store_rx_pol_inv(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret, r; - u16 val; - - ret = ipath_parse_ushort(buf, &val); - if (ret < 0) - goto invalid; - - r = ipath_set_rx_pol_inv(dd, val); - if (r < 0) { - ret = r; - goto bail; - } - - goto bail; -invalid: - ipath_dev_err(dd, "attempt to set invalid Rx Polarity invert\n"); -bail: - return ret; -} - -static ssize_t store_led_override(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret; - u16 val; - - ret = ipath_parse_ushort(buf, &val); - if (ret > 0) - ipath_set_led_override(dd, val); - else - ipath_dev_err(dd, "attempt to set invalid LED override\n"); - return ret; -} - -static ssize_t show_logged_errs(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int idx, count; - - /* force consistency with actual EEPROM */ - if (ipath_update_eeprom_log(dd) != 0) - return -ENXIO; - - count = 0; - for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) { - count += scnprintf(buf + count, PAGE_SIZE - count, "%d%c", - dd->ipath_eep_st_errs[idx], - idx == (IPATH_EEP_LOG_CNT - 1) ? '\n' : ' '); - } - - return count; -} - -/* - * New sysfs entries to control various IB config. These all turn into - * accesses via ipath_f_get/set_ib_cfg. - * - * Get/Set heartbeat enable. Or of 1=enabled, 2=auto - */ -static ssize_t show_hrtbt_enb(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret; - - ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_HRTBT); - if (ret >= 0) - ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret); - return ret; -} - -static ssize_t store_hrtbt_enb(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret, r; - u16 val; - - ret = ipath_parse_ushort(buf, &val); - if (ret >= 0 && val > 3) - ret = -EINVAL; - if (ret < 0) { - ipath_dev_err(dd, "attempt to set invalid Heartbeat enable\n"); - goto bail; - } - - /* - * Set the "intentional" heartbeat enable per either of - * "Enable" and "Auto", as these are normally set together. - * This bit is consulted when leaving loopback mode, - * because entering loopback mode overrides it and automatically - * disables heartbeat. - */ - r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT, val); - if (r < 0) - ret = r; - else if (val == IPATH_IB_HRTBT_OFF) - dd->ipath_flags |= IPATH_NO_HRTBT; - else - dd->ipath_flags &= ~IPATH_NO_HRTBT; - -bail: - return ret; -} - -/* - * Get/Set Link-widths enabled. Or of 1=1x, 2=4x (this is human/IB centric, - * _not_ the particular encoding of any given chip) - */ -static ssize_t show_lwid_enb(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret; - - ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB); - if (ret >= 0) - ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret); - return ret; -} - -static ssize_t store_lwid_enb(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret, r; - u16 val; - - ret = ipath_parse_ushort(buf, &val); - if (ret >= 0 && (val == 0 || val > 3)) - ret = -EINVAL; - if (ret < 0) { - ipath_dev_err(dd, - "attempt to set invalid Link Width (enable)\n"); - goto bail; - } - - r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB, val); - if (r < 0) - ret = r; - -bail: - return ret; -} - -/* Get current link width */ -static ssize_t show_lwid(struct device *dev, - struct device_attribute *attr, - char *buf) - -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret; - - ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LWID); - if (ret >= 0) - ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret); - return ret; -} - -/* - * Get/Set Link-speeds enabled. Or of 1=SDR 2=DDR. - */ -static ssize_t show_spd_enb(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret; - - ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB); - if (ret >= 0) - ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret); - return ret; -} - -static ssize_t store_spd_enb(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret, r; - u16 val; - - ret = ipath_parse_ushort(buf, &val); - if (ret >= 0 && (val == 0 || val > (IPATH_IB_SDR | IPATH_IB_DDR))) - ret = -EINVAL; - if (ret < 0) { - ipath_dev_err(dd, - "attempt to set invalid Link Speed (enable)\n"); - goto bail; - } - - r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB, val); - if (r < 0) - ret = r; - -bail: - return ret; -} - -/* Get current link speed */ -static ssize_t show_spd(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret; - - ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_SPD); - if (ret >= 0) - ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret); - return ret; -} - -/* - * Get/Set RX polarity-invert enable. 0=no, 1=yes. - */ -static ssize_t show_rx_polinv_enb(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret; - - ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_RXPOL_ENB); - if (ret >= 0) - ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret); - return ret; -} - -static ssize_t store_rx_polinv_enb(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret, r; - u16 val; - - ret = ipath_parse_ushort(buf, &val); - if (ret >= 0 && val > 1) { - ipath_dev_err(dd, - "attempt to set invalid Rx Polarity (enable)\n"); - ret = -EINVAL; - goto bail; - } - - r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_RXPOL_ENB, val); - if (r < 0) - ret = r; - -bail: - return ret; -} - -/* - * Get/Set RX lane-reversal enable. 0=no, 1=yes. - */ -static ssize_t show_lanerev_enb(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret; - - ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LREV_ENB); - if (ret >= 0) - ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret); - return ret; -} - -static ssize_t store_lanerev_enb(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret, r; - u16 val; - - ret = ipath_parse_ushort(buf, &val); - if (ret >= 0 && val > 1) { - ret = -EINVAL; - ipath_dev_err(dd, - "attempt to set invalid Lane reversal (enable)\n"); - goto bail; - } - - r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LREV_ENB, val); - if (r < 0) - ret = r; - -bail: - return ret; -} - -static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL); -static DRIVER_ATTR(version, S_IRUGO, show_version, NULL); - -static struct attribute *driver_attributes[] = { - &driver_attr_num_units.attr, - &driver_attr_version.attr, - NULL -}; - -static struct attribute_group driver_attr_group = { - .attrs = driver_attributes -}; - -static ssize_t store_tempsense(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret, stat; - u16 val; - - ret = ipath_parse_ushort(buf, &val); - if (ret <= 0) { - ipath_dev_err(dd, "attempt to set invalid tempsense config\n"); - goto bail; - } - /* If anything but the highest limit, enable T_CRIT_A "interrupt" */ - stat = ipath_tempsense_write(dd, 9, (val == 0x7f7f) ? 0x80 : 0); - if (stat) { - ipath_dev_err(dd, "Unable to set tempsense config\n"); - ret = -1; - goto bail; - } - stat = ipath_tempsense_write(dd, 0xB, (u8) (val & 0xFF)); - if (stat) { - ipath_dev_err(dd, "Unable to set local Tcrit\n"); - ret = -1; - goto bail; - } - stat = ipath_tempsense_write(dd, 0xD, (u8) (val >> 8)); - if (stat) { - ipath_dev_err(dd, "Unable to set remote Tcrit\n"); - ret = -1; - goto bail; - } - -bail: - return ret; -} - -/* - * dump tempsense regs. in decimal, to ease shell-scripts. - */ -static ssize_t show_tempsense(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret; - int idx; - u8 regvals[8]; - - ret = -ENXIO; - for (idx = 0; idx < 8; ++idx) { - if (idx == 6) - continue; - ret = ipath_tempsense_read(dd, idx); - if (ret < 0) - break; - regvals[idx] = ret; - } - if (idx == 8) - ret = scnprintf(buf, PAGE_SIZE, "%d %d %02X %02X %d %d\n", - *(signed char *)(regvals), - *(signed char *)(regvals + 1), - regvals[2], regvals[3], - *(signed char *)(regvals + 5), - *(signed char *)(regvals + 7)); - return ret; -} - -const struct attribute_group *ipath_driver_attr_groups[] = { - &driver_attr_group, - NULL, -}; - -static DEVICE_ATTR(guid, S_IWUSR | S_IRUGO, show_guid, store_guid); -static DEVICE_ATTR(lmc, S_IWUSR | S_IRUGO, show_lmc, store_lmc); -static DEVICE_ATTR(lid, S_IWUSR | S_IRUGO, show_lid, store_lid); -static DEVICE_ATTR(link_state, S_IWUSR, NULL, store_link_state); -static DEVICE_ATTR(mlid, S_IWUSR | S_IRUGO, show_mlid, store_mlid); -static DEVICE_ATTR(mtu, S_IWUSR | S_IRUGO, show_mtu, store_mtu); -static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO, show_enabled, store_enabled); -static DEVICE_ATTR(nguid, S_IRUGO, show_nguid, NULL); -static DEVICE_ATTR(nports, S_IRUGO, show_nports, NULL); -static DEVICE_ATTR(reset, S_IWUSR, NULL, store_reset); -static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL); -static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); -static DEVICE_ATTR(status_str, S_IRUGO, show_status_str, NULL); -static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL); -static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL); -static DEVICE_ATTR(rx_pol_inv, S_IWUSR, NULL, store_rx_pol_inv); -static DEVICE_ATTR(led_override, S_IWUSR, NULL, store_led_override); -static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL); -static DEVICE_ATTR(localbus_info, S_IRUGO, show_localbus_info, NULL); -static DEVICE_ATTR(jint_max_packets, S_IWUSR | S_IRUGO, - show_jint_max_packets, store_jint_max_packets); -static DEVICE_ATTR(jint_idle_ticks, S_IWUSR | S_IRUGO, - show_jint_idle_ticks, store_jint_idle_ticks); -static DEVICE_ATTR(tempsense, S_IWUSR | S_IRUGO, - show_tempsense, store_tempsense); - -static struct attribute *dev_attributes[] = { - &dev_attr_guid.attr, - &dev_attr_lmc.attr, - &dev_attr_lid.attr, - &dev_attr_link_state.attr, - &dev_attr_mlid.attr, - &dev_attr_mtu.attr, - &dev_attr_nguid.attr, - &dev_attr_nports.attr, - &dev_attr_serial.attr, - &dev_attr_status.attr, - &dev_attr_status_str.attr, - &dev_attr_boardversion.attr, - &dev_attr_unit.attr, - &dev_attr_enabled.attr, - &dev_attr_rx_pol_inv.attr, - &dev_attr_led_override.attr, - &dev_attr_logged_errors.attr, - &dev_attr_tempsense.attr, - &dev_attr_localbus_info.attr, - NULL -}; - -static struct attribute_group dev_attr_group = { - .attrs = dev_attributes -}; - -static DEVICE_ATTR(hrtbt_enable, S_IWUSR | S_IRUGO, show_hrtbt_enb, - store_hrtbt_enb); -static DEVICE_ATTR(link_width_enable, S_IWUSR | S_IRUGO, show_lwid_enb, - store_lwid_enb); -static DEVICE_ATTR(link_width, S_IRUGO, show_lwid, NULL); -static DEVICE_ATTR(link_speed_enable, S_IWUSR | S_IRUGO, show_spd_enb, - store_spd_enb); -static DEVICE_ATTR(link_speed, S_IRUGO, show_spd, NULL); -static DEVICE_ATTR(rx_pol_inv_enable, S_IWUSR | S_IRUGO, show_rx_polinv_enb, - store_rx_polinv_enb); -static DEVICE_ATTR(rx_lane_rev_enable, S_IWUSR | S_IRUGO, show_lanerev_enb, - store_lanerev_enb); - -static struct attribute *dev_ibcfg_attributes[] = { - &dev_attr_hrtbt_enable.attr, - &dev_attr_link_width_enable.attr, - &dev_attr_link_width.attr, - &dev_attr_link_speed_enable.attr, - &dev_attr_link_speed.attr, - &dev_attr_rx_pol_inv_enable.attr, - &dev_attr_rx_lane_rev_enable.attr, - NULL -}; - -static struct attribute_group dev_ibcfg_attr_group = { - .attrs = dev_ibcfg_attributes -}; - -/** - * ipath_expose_reset - create a device reset file - * @dev: the device structure - * - * Only expose a file that lets us reset the device after someone - * enters diag mode. A device reset is quite likely to crash the - * machine entirely, so we don't want to normally make it - * available. - * - * Called with ipath_mutex held. - */ -int ipath_expose_reset(struct device *dev) -{ - static int exposed; - int ret; - - if (!exposed) { - ret = device_create_file(dev, &dev_attr_reset); - exposed = 1; - } else { - ret = 0; - } - - return ret; -} - -int ipath_device_create_group(struct device *dev, struct ipath_devdata *dd) -{ - int ret; - - ret = sysfs_create_group(&dev->kobj, &dev_attr_group); - if (ret) - goto bail; - - ret = sysfs_create_group(&dev->kobj, &dev_counter_attr_group); - if (ret) - goto bail_attrs; - - if (dd->ipath_flags & IPATH_HAS_MULT_IB_SPEED) { - ret = device_create_file(dev, &dev_attr_jint_idle_ticks); - if (ret) - goto bail_counter; - ret = device_create_file(dev, &dev_attr_jint_max_packets); - if (ret) - goto bail_idle; - - ret = sysfs_create_group(&dev->kobj, &dev_ibcfg_attr_group); - if (ret) - goto bail_max; - } - - return 0; - -bail_max: - device_remove_file(dev, &dev_attr_jint_max_packets); -bail_idle: - device_remove_file(dev, &dev_attr_jint_idle_ticks); -bail_counter: - sysfs_remove_group(&dev->kobj, &dev_counter_attr_group); -bail_attrs: - sysfs_remove_group(&dev->kobj, &dev_attr_group); -bail: - return ret; -} - -void ipath_device_remove_group(struct device *dev, struct ipath_devdata *dd) -{ - sysfs_remove_group(&dev->kobj, &dev_counter_attr_group); - - if (dd->ipath_flags & IPATH_HAS_MULT_IB_SPEED) { - sysfs_remove_group(&dev->kobj, &dev_ibcfg_attr_group); - device_remove_file(dev, &dev_attr_jint_idle_ticks); - device_remove_file(dev, &dev_attr_jint_max_packets); - } - - sysfs_remove_group(&dev->kobj, &dev_attr_group); - - device_remove_file(dev, &dev_attr_reset); -} diff --git a/drivers/staging/rdma/ipath/ipath_uc.c b/drivers/staging/rdma/ipath/ipath_uc.c deleted file mode 100644 index 0246b30280b9..000000000000 --- a/drivers/staging/rdma/ipath/ipath_uc.c +++ /dev/null @@ -1,547 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "ipath_verbs.h" -#include "ipath_kernel.h" - -/* cut down ridiculously long IB macro names */ -#define OP(x) IB_OPCODE_UC_##x - -/** - * ipath_make_uc_req - construct a request packet (SEND, RDMA write) - * @qp: a pointer to the QP - * - * Return 1 if constructed; otherwise, return 0. - */ -int ipath_make_uc_req(struct ipath_qp *qp) -{ - struct ipath_other_headers *ohdr; - struct ipath_swqe *wqe; - unsigned long flags; - u32 hwords; - u32 bth0; - u32 len; - u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu); - int ret = 0; - - spin_lock_irqsave(&qp->s_lock, flags); - - if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK)) { - if (!(ib_ipath_state_ops[qp->state] & IPATH_FLUSH_SEND)) - goto bail; - /* We are in the error state, flush the work request. */ - if (qp->s_last == qp->s_head) - goto bail; - /* If DMAs are in progress, we can't flush immediately. */ - if (atomic_read(&qp->s_dma_busy)) { - qp->s_flags |= IPATH_S_WAIT_DMA; - goto bail; - } - wqe = get_swqe_ptr(qp, qp->s_last); - ipath_send_complete(qp, wqe, IB_WC_WR_FLUSH_ERR); - goto done; - } - - ohdr = &qp->s_hdr.u.oth; - if (qp->remote_ah_attr.ah_flags & IB_AH_GRH) - ohdr = &qp->s_hdr.u.l.oth; - - /* header size in 32-bit words LRH+BTH = (8+12)/4. */ - hwords = 5; - bth0 = 1 << 22; /* Set M bit */ - - /* Get the next send request. */ - wqe = get_swqe_ptr(qp, qp->s_cur); - qp->s_wqe = NULL; - switch (qp->s_state) { - default: - if (!(ib_ipath_state_ops[qp->state] & - IPATH_PROCESS_NEXT_SEND_OK)) - goto bail; - /* Check if send work queue is empty. */ - if (qp->s_cur == qp->s_head) - goto bail; - /* - * Start a new request. - */ - qp->s_psn = wqe->psn = qp->s_next_psn; - qp->s_sge.sge = wqe->sg_list[0]; - qp->s_sge.sg_list = wqe->sg_list + 1; - qp->s_sge.num_sge = wqe->wr.num_sge; - qp->s_len = len = wqe->length; - switch (wqe->wr.opcode) { - case IB_WR_SEND: - case IB_WR_SEND_WITH_IMM: - if (len > pmtu) { - qp->s_state = OP(SEND_FIRST); - len = pmtu; - break; - } - if (wqe->wr.opcode == IB_WR_SEND) - qp->s_state = OP(SEND_ONLY); - else { - qp->s_state = - OP(SEND_ONLY_WITH_IMMEDIATE); - /* Immediate data comes after the BTH */ - ohdr->u.imm_data = wqe->wr.ex.imm_data; - hwords += 1; - } - if (wqe->wr.send_flags & IB_SEND_SOLICITED) - bth0 |= 1 << 23; - qp->s_wqe = wqe; - if (++qp->s_cur >= qp->s_size) - qp->s_cur = 0; - break; - - case IB_WR_RDMA_WRITE: - case IB_WR_RDMA_WRITE_WITH_IMM: - ohdr->u.rc.reth.vaddr = - cpu_to_be64(wqe->rdma_wr.remote_addr); - ohdr->u.rc.reth.rkey = - cpu_to_be32(wqe->rdma_wr.rkey); - ohdr->u.rc.reth.length = cpu_to_be32(len); - hwords += sizeof(struct ib_reth) / 4; - if (len > pmtu) { - qp->s_state = OP(RDMA_WRITE_FIRST); - len = pmtu; - break; - } - if (wqe->wr.opcode == IB_WR_RDMA_WRITE) - qp->s_state = OP(RDMA_WRITE_ONLY); - else { - qp->s_state = - OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE); - /* Immediate data comes after the RETH */ - ohdr->u.rc.imm_data = wqe->wr.ex.imm_data; - hwords += 1; - if (wqe->wr.send_flags & IB_SEND_SOLICITED) - bth0 |= 1 << 23; - } - qp->s_wqe = wqe; - if (++qp->s_cur >= qp->s_size) - qp->s_cur = 0; - break; - - default: - goto bail; - } - break; - - case OP(SEND_FIRST): - qp->s_state = OP(SEND_MIDDLE); - /* FALLTHROUGH */ - case OP(SEND_MIDDLE): - len = qp->s_len; - if (len > pmtu) { - len = pmtu; - break; - } - if (wqe->wr.opcode == IB_WR_SEND) - qp->s_state = OP(SEND_LAST); - else { - qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE); - /* Immediate data comes after the BTH */ - ohdr->u.imm_data = wqe->wr.ex.imm_data; - hwords += 1; - } - if (wqe->wr.send_flags & IB_SEND_SOLICITED) - bth0 |= 1 << 23; - qp->s_wqe = wqe; - if (++qp->s_cur >= qp->s_size) - qp->s_cur = 0; - break; - - case OP(RDMA_WRITE_FIRST): - qp->s_state = OP(RDMA_WRITE_MIDDLE); - /* FALLTHROUGH */ - case OP(RDMA_WRITE_MIDDLE): - len = qp->s_len; - if (len > pmtu) { - len = pmtu; - break; - } - if (wqe->wr.opcode == IB_WR_RDMA_WRITE) - qp->s_state = OP(RDMA_WRITE_LAST); - else { - qp->s_state = - OP(RDMA_WRITE_LAST_WITH_IMMEDIATE); - /* Immediate data comes after the BTH */ - ohdr->u.imm_data = wqe->wr.ex.imm_data; - hwords += 1; - if (wqe->wr.send_flags & IB_SEND_SOLICITED) - bth0 |= 1 << 23; - } - qp->s_wqe = wqe; - if (++qp->s_cur >= qp->s_size) - qp->s_cur = 0; - break; - } - qp->s_len -= len; - qp->s_hdrwords = hwords; - qp->s_cur_sge = &qp->s_sge; - qp->s_cur_size = len; - ipath_make_ruc_header(to_idev(qp->ibqp.device), - qp, ohdr, bth0 | (qp->s_state << 24), - qp->s_next_psn++ & IPATH_PSN_MASK); -done: - ret = 1; - goto unlock; - -bail: - qp->s_flags &= ~IPATH_S_BUSY; -unlock: - spin_unlock_irqrestore(&qp->s_lock, flags); - return ret; -} - -/** - * ipath_uc_rcv - handle an incoming UC packet - * @dev: the device the packet came in on - * @hdr: the header of the packet - * @has_grh: true if the packet has a GRH - * @data: the packet data - * @tlen: the length of the packet - * @qp: the QP for this packet. - * - * This is called from ipath_qp_rcv() to process an incoming UC packet - * for the given QP. - * Called at interrupt level. - */ -void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, - int has_grh, void *data, u32 tlen, struct ipath_qp *qp) -{ - struct ipath_other_headers *ohdr; - int opcode; - u32 hdrsize; - u32 psn; - u32 pad; - struct ib_wc wc; - u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu); - struct ib_reth *reth; - int header_in_data; - - /* Validate the SLID. See Ch. 9.6.1.5 */ - if (unlikely(be16_to_cpu(hdr->lrh[3]) != qp->remote_ah_attr.dlid)) - goto done; - - /* Check for GRH */ - if (!has_grh) { - ohdr = &hdr->u.oth; - hdrsize = 8 + 12; /* LRH + BTH */ - psn = be32_to_cpu(ohdr->bth[2]); - header_in_data = 0; - } else { - ohdr = &hdr->u.l.oth; - hdrsize = 8 + 40 + 12; /* LRH + GRH + BTH */ - /* - * The header with GRH is 60 bytes and the - * core driver sets the eager header buffer - * size to 56 bytes so the last 4 bytes of - * the BTH header (PSN) is in the data buffer. - */ - header_in_data = dev->dd->ipath_rcvhdrentsize == 16; - if (header_in_data) { - psn = be32_to_cpu(((__be32 *) data)[0]); - data += sizeof(__be32); - } else - psn = be32_to_cpu(ohdr->bth[2]); - } - /* - * The opcode is in the low byte when its in network order - * (top byte when in host order). - */ - opcode = be32_to_cpu(ohdr->bth[0]) >> 24; - - memset(&wc, 0, sizeof wc); - - /* Compare the PSN verses the expected PSN. */ - if (unlikely(ipath_cmp24(psn, qp->r_psn) != 0)) { - /* - * Handle a sequence error. - * Silently drop any current message. - */ - qp->r_psn = psn; - inv: - qp->r_state = OP(SEND_LAST); - switch (opcode) { - case OP(SEND_FIRST): - case OP(SEND_ONLY): - case OP(SEND_ONLY_WITH_IMMEDIATE): - goto send_first; - - case OP(RDMA_WRITE_FIRST): - case OP(RDMA_WRITE_ONLY): - case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE): - goto rdma_first; - - default: - dev->n_pkt_drops++; - goto done; - } - } - - /* Check for opcode sequence errors. */ - switch (qp->r_state) { - case OP(SEND_FIRST): - case OP(SEND_MIDDLE): - if (opcode == OP(SEND_MIDDLE) || - opcode == OP(SEND_LAST) || - opcode == OP(SEND_LAST_WITH_IMMEDIATE)) - break; - goto inv; - - case OP(RDMA_WRITE_FIRST): - case OP(RDMA_WRITE_MIDDLE): - if (opcode == OP(RDMA_WRITE_MIDDLE) || - opcode == OP(RDMA_WRITE_LAST) || - opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE)) - break; - goto inv; - - default: - if (opcode == OP(SEND_FIRST) || - opcode == OP(SEND_ONLY) || - opcode == OP(SEND_ONLY_WITH_IMMEDIATE) || - opcode == OP(RDMA_WRITE_FIRST) || - opcode == OP(RDMA_WRITE_ONLY) || - opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE)) - break; - goto inv; - } - - /* OK, process the packet. */ - switch (opcode) { - case OP(SEND_FIRST): - case OP(SEND_ONLY): - case OP(SEND_ONLY_WITH_IMMEDIATE): - send_first: - if (qp->r_flags & IPATH_R_REUSE_SGE) { - qp->r_flags &= ~IPATH_R_REUSE_SGE; - qp->r_sge = qp->s_rdma_read_sge; - } else if (!ipath_get_rwqe(qp, 0)) { - dev->n_pkt_drops++; - goto done; - } - /* Save the WQE so we can reuse it in case of an error. */ - qp->s_rdma_read_sge = qp->r_sge; - qp->r_rcv_len = 0; - if (opcode == OP(SEND_ONLY)) - goto send_last; - else if (opcode == OP(SEND_ONLY_WITH_IMMEDIATE)) - goto send_last_imm; - /* FALLTHROUGH */ - case OP(SEND_MIDDLE): - /* Check for invalid length PMTU or posted rwqe len. */ - if (unlikely(tlen != (hdrsize + pmtu + 4))) { - qp->r_flags |= IPATH_R_REUSE_SGE; - dev->n_pkt_drops++; - goto done; - } - qp->r_rcv_len += pmtu; - if (unlikely(qp->r_rcv_len > qp->r_len)) { - qp->r_flags |= IPATH_R_REUSE_SGE; - dev->n_pkt_drops++; - goto done; - } - ipath_copy_sge(&qp->r_sge, data, pmtu); - break; - - case OP(SEND_LAST_WITH_IMMEDIATE): - send_last_imm: - if (header_in_data) { - wc.ex.imm_data = *(__be32 *) data; - data += sizeof(__be32); - } else { - /* Immediate data comes after BTH */ - wc.ex.imm_data = ohdr->u.imm_data; - } - hdrsize += 4; - wc.wc_flags = IB_WC_WITH_IMM; - /* FALLTHROUGH */ - case OP(SEND_LAST): - send_last: - /* Get the number of bytes the message was padded by. */ - pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3; - /* Check for invalid length. */ - /* XXX LAST len should be >= 1 */ - if (unlikely(tlen < (hdrsize + pad + 4))) { - qp->r_flags |= IPATH_R_REUSE_SGE; - dev->n_pkt_drops++; - goto done; - } - /* Don't count the CRC. */ - tlen -= (hdrsize + pad + 4); - wc.byte_len = tlen + qp->r_rcv_len; - if (unlikely(wc.byte_len > qp->r_len)) { - qp->r_flags |= IPATH_R_REUSE_SGE; - dev->n_pkt_drops++; - goto done; - } - wc.opcode = IB_WC_RECV; - last_imm: - ipath_copy_sge(&qp->r_sge, data, tlen); - wc.wr_id = qp->r_wr_id; - wc.status = IB_WC_SUCCESS; - wc.qp = &qp->ibqp; - wc.src_qp = qp->remote_qpn; - wc.slid = qp->remote_ah_attr.dlid; - wc.sl = qp->remote_ah_attr.sl; - /* Signal completion event if the solicited bit is set. */ - ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, - (ohdr->bth[0] & - cpu_to_be32(1 << 23)) != 0); - break; - - case OP(RDMA_WRITE_FIRST): - case OP(RDMA_WRITE_ONLY): - case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE): /* consume RWQE */ - rdma_first: - /* RETH comes after BTH */ - if (!header_in_data) - reth = &ohdr->u.rc.reth; - else { - reth = (struct ib_reth *)data; - data += sizeof(*reth); - } - hdrsize += sizeof(*reth); - qp->r_len = be32_to_cpu(reth->length); - qp->r_rcv_len = 0; - if (qp->r_len != 0) { - u32 rkey = be32_to_cpu(reth->rkey); - u64 vaddr = be64_to_cpu(reth->vaddr); - int ok; - - /* Check rkey */ - ok = ipath_rkey_ok(qp, &qp->r_sge, qp->r_len, - vaddr, rkey, - IB_ACCESS_REMOTE_WRITE); - if (unlikely(!ok)) { - dev->n_pkt_drops++; - goto done; - } - } else { - qp->r_sge.sg_list = NULL; - qp->r_sge.sge.mr = NULL; - qp->r_sge.sge.vaddr = NULL; - qp->r_sge.sge.length = 0; - qp->r_sge.sge.sge_length = 0; - } - if (unlikely(!(qp->qp_access_flags & - IB_ACCESS_REMOTE_WRITE))) { - dev->n_pkt_drops++; - goto done; - } - if (opcode == OP(RDMA_WRITE_ONLY)) - goto rdma_last; - else if (opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE)) - goto rdma_last_imm; - /* FALLTHROUGH */ - case OP(RDMA_WRITE_MIDDLE): - /* Check for invalid length PMTU or posted rwqe len. */ - if (unlikely(tlen != (hdrsize + pmtu + 4))) { - dev->n_pkt_drops++; - goto done; - } - qp->r_rcv_len += pmtu; - if (unlikely(qp->r_rcv_len > qp->r_len)) { - dev->n_pkt_drops++; - goto done; - } - ipath_copy_sge(&qp->r_sge, data, pmtu); - break; - - case OP(RDMA_WRITE_LAST_WITH_IMMEDIATE): - rdma_last_imm: - if (header_in_data) { - wc.ex.imm_data = *(__be32 *) data; - data += sizeof(__be32); - } else { - /* Immediate data comes after BTH */ - wc.ex.imm_data = ohdr->u.imm_data; - } - hdrsize += 4; - wc.wc_flags = IB_WC_WITH_IMM; - - /* Get the number of bytes the message was padded by. */ - pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3; - /* Check for invalid length. */ - /* XXX LAST len should be >= 1 */ - if (unlikely(tlen < (hdrsize + pad + 4))) { - dev->n_pkt_drops++; - goto done; - } - /* Don't count the CRC. */ - tlen -= (hdrsize + pad + 4); - if (unlikely(tlen + qp->r_rcv_len != qp->r_len)) { - dev->n_pkt_drops++; - goto done; - } - if (qp->r_flags & IPATH_R_REUSE_SGE) - qp->r_flags &= ~IPATH_R_REUSE_SGE; - else if (!ipath_get_rwqe(qp, 1)) { - dev->n_pkt_drops++; - goto done; - } - wc.byte_len = qp->r_len; - wc.opcode = IB_WC_RECV_RDMA_WITH_IMM; - goto last_imm; - - case OP(RDMA_WRITE_LAST): - rdma_last: - /* Get the number of bytes the message was padded by. */ - pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3; - /* Check for invalid length. */ - /* XXX LAST len should be >= 1 */ - if (unlikely(tlen < (hdrsize + pad + 4))) { - dev->n_pkt_drops++; - goto done; - } - /* Don't count the CRC. */ - tlen -= (hdrsize + pad + 4); - if (unlikely(tlen + qp->r_rcv_len != qp->r_len)) { - dev->n_pkt_drops++; - goto done; - } - ipath_copy_sge(&qp->r_sge, data, tlen); - break; - - default: - /* Drop packet for unknown opcodes. */ - dev->n_pkt_drops++; - goto done; - } - qp->r_psn++; - qp->r_state = opcode; -done: - return; -} diff --git a/drivers/staging/rdma/ipath/ipath_ud.c b/drivers/staging/rdma/ipath/ipath_ud.c deleted file mode 100644 index 385d9410a51e..000000000000 --- a/drivers/staging/rdma/ipath/ipath_ud.c +++ /dev/null @@ -1,579 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include "ipath_verbs.h" -#include "ipath_kernel.h" - -/** - * ipath_ud_loopback - handle send on loopback QPs - * @sqp: the sending QP - * @swqe: the send work request - * - * This is called from ipath_make_ud_req() to forward a WQE addressed - * to the same HCA. - * Note that the receive interrupt handler may be calling ipath_ud_rcv() - * while this is being called. - */ -static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe) -{ - struct ipath_ibdev *dev = to_idev(sqp->ibqp.device); - struct ipath_qp *qp; - struct ib_ah_attr *ah_attr; - unsigned long flags; - struct ipath_rq *rq; - struct ipath_srq *srq; - struct ipath_sge_state rsge; - struct ipath_sge *sge; - struct ipath_rwq *wq; - struct ipath_rwqe *wqe; - void (*handler)(struct ib_event *, void *); - struct ib_wc wc; - u32 tail; - u32 rlen; - u32 length; - - qp = ipath_lookup_qpn(&dev->qp_table, swqe->ud_wr.remote_qpn); - if (!qp || !(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) { - dev->n_pkt_drops++; - goto done; - } - - /* - * Check that the qkey matches (except for QP0, see 9.6.1.4.1). - * Qkeys with the high order bit set mean use the - * qkey from the QP context instead of the WR (see 10.2.5). - */ - if (unlikely(qp->ibqp.qp_num && - ((int) swqe->ud_wr.remote_qkey < 0 ? - sqp->qkey : swqe->ud_wr.remote_qkey) != qp->qkey)) { - /* XXX OK to lose a count once in a while. */ - dev->qkey_violations++; - dev->n_pkt_drops++; - goto drop; - } - - /* - * A GRH is expected to precede the data even if not - * present on the wire. - */ - length = swqe->length; - memset(&wc, 0, sizeof wc); - wc.byte_len = length + sizeof(struct ib_grh); - - if (swqe->wr.opcode == IB_WR_SEND_WITH_IMM) { - wc.wc_flags = IB_WC_WITH_IMM; - wc.ex.imm_data = swqe->wr.ex.imm_data; - } - - /* - * This would be a lot simpler if we could call ipath_get_rwqe() - * but that uses state that the receive interrupt handler uses - * so we would need to lock out receive interrupts while doing - * local loopback. - */ - if (qp->ibqp.srq) { - srq = to_isrq(qp->ibqp.srq); - handler = srq->ibsrq.event_handler; - rq = &srq->rq; - } else { - srq = NULL; - handler = NULL; - rq = &qp->r_rq; - } - - /* - * Get the next work request entry to find where to put the data. - * Note that it is safe to drop the lock after changing rq->tail - * since ipath_post_receive() won't fill the empty slot. - */ - spin_lock_irqsave(&rq->lock, flags); - wq = rq->wq; - tail = wq->tail; - /* Validate tail before using it since it is user writable. */ - if (tail >= rq->size) - tail = 0; - if (unlikely(tail == wq->head)) { - spin_unlock_irqrestore(&rq->lock, flags); - dev->n_pkt_drops++; - goto drop; - } - wqe = get_rwqe_ptr(rq, tail); - rsge.sg_list = qp->r_ud_sg_list; - if (!ipath_init_sge(qp, wqe, &rlen, &rsge)) { - spin_unlock_irqrestore(&rq->lock, flags); - dev->n_pkt_drops++; - goto drop; - } - /* Silently drop packets which are too big. */ - if (wc.byte_len > rlen) { - spin_unlock_irqrestore(&rq->lock, flags); - dev->n_pkt_drops++; - goto drop; - } - if (++tail >= rq->size) - tail = 0; - wq->tail = tail; - wc.wr_id = wqe->wr_id; - if (handler) { - u32 n; - - /* - * validate head pointer value and compute - * the number of remaining WQEs. - */ - n = wq->head; - if (n >= rq->size) - n = 0; - if (n < tail) - n += rq->size - tail; - else - n -= tail; - if (n < srq->limit) { - struct ib_event ev; - - srq->limit = 0; - spin_unlock_irqrestore(&rq->lock, flags); - ev.device = qp->ibqp.device; - ev.element.srq = qp->ibqp.srq; - ev.event = IB_EVENT_SRQ_LIMIT_REACHED; - handler(&ev, srq->ibsrq.srq_context); - } else - spin_unlock_irqrestore(&rq->lock, flags); - } else - spin_unlock_irqrestore(&rq->lock, flags); - - ah_attr = &to_iah(swqe->ud_wr.ah)->attr; - if (ah_attr->ah_flags & IB_AH_GRH) { - ipath_copy_sge(&rsge, &ah_attr->grh, sizeof(struct ib_grh)); - wc.wc_flags |= IB_WC_GRH; - } else - ipath_skip_sge(&rsge, sizeof(struct ib_grh)); - sge = swqe->sg_list; - while (length) { - u32 len = sge->length; - - if (len > length) - len = length; - if (len > sge->sge_length) - len = sge->sge_length; - BUG_ON(len == 0); - ipath_copy_sge(&rsge, sge->vaddr, len); - sge->vaddr += len; - sge->length -= len; - sge->sge_length -= len; - if (sge->sge_length == 0) { - if (--swqe->wr.num_sge) - sge++; - } else if (sge->length == 0 && sge->mr != NULL) { - if (++sge->n >= IPATH_SEGSZ) { - if (++sge->m >= sge->mr->mapsz) - break; - sge->n = 0; - } - sge->vaddr = - sge->mr->map[sge->m]->segs[sge->n].vaddr; - sge->length = - sge->mr->map[sge->m]->segs[sge->n].length; - } - length -= len; - } - wc.status = IB_WC_SUCCESS; - wc.opcode = IB_WC_RECV; - wc.qp = &qp->ibqp; - wc.src_qp = sqp->ibqp.qp_num; - /* XXX do we know which pkey matched? Only needed for GSI. */ - wc.pkey_index = 0; - wc.slid = dev->dd->ipath_lid | - (ah_attr->src_path_bits & - ((1 << dev->dd->ipath_lmc) - 1)); - wc.sl = ah_attr->sl; - wc.dlid_path_bits = - ah_attr->dlid & ((1 << dev->dd->ipath_lmc) - 1); - wc.port_num = 1; - /* Signal completion event if the solicited bit is set. */ - ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, - swqe->ud_wr.wr.send_flags & IB_SEND_SOLICITED); -drop: - if (atomic_dec_and_test(&qp->refcount)) - wake_up(&qp->wait); -done:; -} - -/** - * ipath_make_ud_req - construct a UD request packet - * @qp: the QP - * - * Return 1 if constructed; otherwise, return 0. - */ -int ipath_make_ud_req(struct ipath_qp *qp) -{ - struct ipath_ibdev *dev = to_idev(qp->ibqp.device); - struct ipath_other_headers *ohdr; - struct ib_ah_attr *ah_attr; - struct ipath_swqe *wqe; - unsigned long flags; - u32 nwords; - u32 extra_bytes; - u32 bth0; - u16 lrh0; - u16 lid; - int ret = 0; - int next_cur; - - spin_lock_irqsave(&qp->s_lock, flags); - - if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_NEXT_SEND_OK)) { - if (!(ib_ipath_state_ops[qp->state] & IPATH_FLUSH_SEND)) - goto bail; - /* We are in the error state, flush the work request. */ - if (qp->s_last == qp->s_head) - goto bail; - /* If DMAs are in progress, we can't flush immediately. */ - if (atomic_read(&qp->s_dma_busy)) { - qp->s_flags |= IPATH_S_WAIT_DMA; - goto bail; - } - wqe = get_swqe_ptr(qp, qp->s_last); - ipath_send_complete(qp, wqe, IB_WC_WR_FLUSH_ERR); - goto done; - } - - if (qp->s_cur == qp->s_head) - goto bail; - - wqe = get_swqe_ptr(qp, qp->s_cur); - next_cur = qp->s_cur + 1; - if (next_cur >= qp->s_size) - next_cur = 0; - - /* Construct the header. */ - ah_attr = &to_iah(wqe->ud_wr.ah)->attr; - if (ah_attr->dlid >= IPATH_MULTICAST_LID_BASE) { - if (ah_attr->dlid != IPATH_PERMISSIVE_LID) - dev->n_multicast_xmit++; - else - dev->n_unicast_xmit++; - } else { - dev->n_unicast_xmit++; - lid = ah_attr->dlid & ~((1 << dev->dd->ipath_lmc) - 1); - if (unlikely(lid == dev->dd->ipath_lid)) { - /* - * If DMAs are in progress, we can't generate - * a completion for the loopback packet since - * it would be out of order. - * XXX Instead of waiting, we could queue a - * zero length descriptor so we get a callback. - */ - if (atomic_read(&qp->s_dma_busy)) { - qp->s_flags |= IPATH_S_WAIT_DMA; - goto bail; - } - qp->s_cur = next_cur; - spin_unlock_irqrestore(&qp->s_lock, flags); - ipath_ud_loopback(qp, wqe); - spin_lock_irqsave(&qp->s_lock, flags); - ipath_send_complete(qp, wqe, IB_WC_SUCCESS); - goto done; - } - } - - qp->s_cur = next_cur; - extra_bytes = -wqe->length & 3; - nwords = (wqe->length + extra_bytes) >> 2; - - /* header size in 32-bit words LRH+BTH+DETH = (8+12+8)/4. */ - qp->s_hdrwords = 7; - qp->s_cur_size = wqe->length; - qp->s_cur_sge = &qp->s_sge; - qp->s_dmult = ah_attr->static_rate; - qp->s_wqe = wqe; - qp->s_sge.sge = wqe->sg_list[0]; - qp->s_sge.sg_list = wqe->sg_list + 1; - qp->s_sge.num_sge = wqe->ud_wr.wr.num_sge; - - if (ah_attr->ah_flags & IB_AH_GRH) { - /* Header size in 32-bit words. */ - qp->s_hdrwords += ipath_make_grh(dev, &qp->s_hdr.u.l.grh, - &ah_attr->grh, - qp->s_hdrwords, nwords); - lrh0 = IPATH_LRH_GRH; - ohdr = &qp->s_hdr.u.l.oth; - /* - * Don't worry about sending to locally attached multicast - * QPs. It is unspecified by the spec. what happens. - */ - } else { - /* Header size in 32-bit words. */ - lrh0 = IPATH_LRH_BTH; - ohdr = &qp->s_hdr.u.oth; - } - if (wqe->ud_wr.wr.opcode == IB_WR_SEND_WITH_IMM) { - qp->s_hdrwords++; - ohdr->u.ud.imm_data = wqe->ud_wr.wr.ex.imm_data; - bth0 = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE << 24; - } else - bth0 = IB_OPCODE_UD_SEND_ONLY << 24; - lrh0 |= ah_attr->sl << 4; - if (qp->ibqp.qp_type == IB_QPT_SMI) - lrh0 |= 0xF000; /* Set VL (see ch. 13.5.3.1) */ - qp->s_hdr.lrh[0] = cpu_to_be16(lrh0); - qp->s_hdr.lrh[1] = cpu_to_be16(ah_attr->dlid); /* DEST LID */ - qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords + - SIZE_OF_CRC); - lid = dev->dd->ipath_lid; - if (lid) { - lid |= ah_attr->src_path_bits & - ((1 << dev->dd->ipath_lmc) - 1); - qp->s_hdr.lrh[3] = cpu_to_be16(lid); - } else - qp->s_hdr.lrh[3] = IB_LID_PERMISSIVE; - if (wqe->ud_wr.wr.send_flags & IB_SEND_SOLICITED) - bth0 |= 1 << 23; - bth0 |= extra_bytes << 20; - bth0 |= qp->ibqp.qp_type == IB_QPT_SMI ? IPATH_DEFAULT_P_KEY : - ipath_get_pkey(dev->dd, qp->s_pkey_index); - ohdr->bth[0] = cpu_to_be32(bth0); - /* - * Use the multicast QP if the destination LID is a multicast LID. - */ - ohdr->bth[1] = ah_attr->dlid >= IPATH_MULTICAST_LID_BASE && - ah_attr->dlid != IPATH_PERMISSIVE_LID ? - cpu_to_be32(IPATH_MULTICAST_QPN) : - cpu_to_be32(wqe->ud_wr.remote_qpn); - ohdr->bth[2] = cpu_to_be32(qp->s_next_psn++ & IPATH_PSN_MASK); - /* - * Qkeys with the high order bit set mean use the - * qkey from the QP context instead of the WR (see 10.2.5). - */ - ohdr->u.ud.deth[0] = cpu_to_be32((int)wqe->ud_wr.remote_qkey < 0 ? - qp->qkey : wqe->ud_wr.remote_qkey); - ohdr->u.ud.deth[1] = cpu_to_be32(qp->ibqp.qp_num); - -done: - ret = 1; - goto unlock; - -bail: - qp->s_flags &= ~IPATH_S_BUSY; -unlock: - spin_unlock_irqrestore(&qp->s_lock, flags); - return ret; -} - -/** - * ipath_ud_rcv - receive an incoming UD packet - * @dev: the device the packet came in on - * @hdr: the packet header - * @has_grh: true if the packet has a GRH - * @data: the packet data - * @tlen: the packet length - * @qp: the QP the packet came on - * - * This is called from ipath_qp_rcv() to process an incoming UD packet - * for the given QP. - * Called at interrupt level. - */ -void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, - int has_grh, void *data, u32 tlen, struct ipath_qp *qp) -{ - struct ipath_other_headers *ohdr; - int opcode; - u32 hdrsize; - u32 pad; - struct ib_wc wc; - u32 qkey; - u32 src_qp; - u16 dlid; - int header_in_data; - - /* Check for GRH */ - if (!has_grh) { - ohdr = &hdr->u.oth; - hdrsize = 8 + 12 + 8; /* LRH + BTH + DETH */ - qkey = be32_to_cpu(ohdr->u.ud.deth[0]); - src_qp = be32_to_cpu(ohdr->u.ud.deth[1]); - header_in_data = 0; - } else { - ohdr = &hdr->u.l.oth; - hdrsize = 8 + 40 + 12 + 8; /* LRH + GRH + BTH + DETH */ - /* - * The header with GRH is 68 bytes and the core driver sets - * the eager header buffer size to 56 bytes so the last 12 - * bytes of the IB header is in the data buffer. - */ - header_in_data = dev->dd->ipath_rcvhdrentsize == 16; - if (header_in_data) { - qkey = be32_to_cpu(((__be32 *) data)[1]); - src_qp = be32_to_cpu(((__be32 *) data)[2]); - data += 12; - } else { - qkey = be32_to_cpu(ohdr->u.ud.deth[0]); - src_qp = be32_to_cpu(ohdr->u.ud.deth[1]); - } - } - src_qp &= IPATH_QPN_MASK; - - /* - * Check that the permissive LID is only used on QP0 - * and the QKEY matches (see 9.6.1.4.1 and 9.6.1.5.1). - */ - if (qp->ibqp.qp_num) { - if (unlikely(hdr->lrh[1] == IB_LID_PERMISSIVE || - hdr->lrh[3] == IB_LID_PERMISSIVE)) { - dev->n_pkt_drops++; - goto bail; - } - if (unlikely(qkey != qp->qkey)) { - /* XXX OK to lose a count once in a while. */ - dev->qkey_violations++; - dev->n_pkt_drops++; - goto bail; - } - } else if (hdr->lrh[1] == IB_LID_PERMISSIVE || - hdr->lrh[3] == IB_LID_PERMISSIVE) { - struct ib_smp *smp = (struct ib_smp *) data; - - if (smp->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) { - dev->n_pkt_drops++; - goto bail; - } - } - - /* - * The opcode is in the low byte when its in network order - * (top byte when in host order). - */ - opcode = be32_to_cpu(ohdr->bth[0]) >> 24; - if (qp->ibqp.qp_num > 1 && - opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) { - if (header_in_data) { - wc.ex.imm_data = *(__be32 *) data; - data += sizeof(__be32); - } else - wc.ex.imm_data = ohdr->u.ud.imm_data; - wc.wc_flags = IB_WC_WITH_IMM; - hdrsize += sizeof(u32); - } else if (opcode == IB_OPCODE_UD_SEND_ONLY) { - wc.ex.imm_data = 0; - wc.wc_flags = 0; - } else { - dev->n_pkt_drops++; - goto bail; - } - - /* Get the number of bytes the message was padded by. */ - pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3; - if (unlikely(tlen < (hdrsize + pad + 4))) { - /* Drop incomplete packets. */ - dev->n_pkt_drops++; - goto bail; - } - tlen -= hdrsize + pad + 4; - - /* Drop invalid MAD packets (see 13.5.3.1). */ - if (unlikely((qp->ibqp.qp_num == 0 && - (tlen != 256 || - (be16_to_cpu(hdr->lrh[0]) >> 12) != 15)) || - (qp->ibqp.qp_num == 1 && - (tlen != 256 || - (be16_to_cpu(hdr->lrh[0]) >> 12) == 15)))) { - dev->n_pkt_drops++; - goto bail; - } - - /* - * A GRH is expected to precede the data even if not - * present on the wire. - */ - wc.byte_len = tlen + sizeof(struct ib_grh); - - /* - * Get the next work request entry to find where to put the data. - */ - if (qp->r_flags & IPATH_R_REUSE_SGE) - qp->r_flags &= ~IPATH_R_REUSE_SGE; - else if (!ipath_get_rwqe(qp, 0)) { - /* - * Count VL15 packets dropped due to no receive buffer. - * Otherwise, count them as buffer overruns since usually, - * the HW will be able to receive packets even if there are - * no QPs with posted receive buffers. - */ - if (qp->ibqp.qp_num == 0) - dev->n_vl15_dropped++; - else - dev->rcv_errors++; - goto bail; - } - /* Silently drop packets which are too big. */ - if (wc.byte_len > qp->r_len) { - qp->r_flags |= IPATH_R_REUSE_SGE; - dev->n_pkt_drops++; - goto bail; - } - if (has_grh) { - ipath_copy_sge(&qp->r_sge, &hdr->u.l.grh, - sizeof(struct ib_grh)); - wc.wc_flags |= IB_WC_GRH; - } else - ipath_skip_sge(&qp->r_sge, sizeof(struct ib_grh)); - ipath_copy_sge(&qp->r_sge, data, - wc.byte_len - sizeof(struct ib_grh)); - if (!test_and_clear_bit(IPATH_R_WRID_VALID, &qp->r_aflags)) - goto bail; - wc.wr_id = qp->r_wr_id; - wc.status = IB_WC_SUCCESS; - wc.opcode = IB_WC_RECV; - wc.vendor_err = 0; - wc.qp = &qp->ibqp; - wc.src_qp = src_qp; - /* XXX do we know which pkey matched? Only needed for GSI. */ - wc.pkey_index = 0; - wc.slid = be16_to_cpu(hdr->lrh[3]); - wc.sl = (be16_to_cpu(hdr->lrh[0]) >> 4) & 0xF; - dlid = be16_to_cpu(hdr->lrh[1]); - /* - * Save the LMC lower bits if the destination LID is a unicast LID. - */ - wc.dlid_path_bits = dlid >= IPATH_MULTICAST_LID_BASE ? 0 : - dlid & ((1 << dev->dd->ipath_lmc) - 1); - wc.port_num = 1; - /* Signal completion event if the solicited bit is set. */ - ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, - (ohdr->bth[0] & - cpu_to_be32(1 << 23)) != 0); - -bail:; -} diff --git a/drivers/staging/rdma/ipath/ipath_user_pages.c b/drivers/staging/rdma/ipath/ipath_user_pages.c deleted file mode 100644 index d29b4daf61f8..000000000000 --- a/drivers/staging/rdma/ipath/ipath_user_pages.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. - * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include - -#include "ipath_kernel.h" - -static void __ipath_release_user_pages(struct page **p, size_t num_pages, - int dirty) -{ - size_t i; - - for (i = 0; i < num_pages; i++) { - ipath_cdbg(MM, "%lu/%lu put_page %p\n", (unsigned long) i, - (unsigned long) num_pages, p[i]); - if (dirty) - set_page_dirty_lock(p[i]); - put_page(p[i]); - } -} - -/* call with current->mm->mmap_sem held */ -static int __ipath_get_user_pages(unsigned long start_page, size_t num_pages, - struct page **p) -{ - unsigned long lock_limit; - size_t got; - int ret; - - lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; - - if (num_pages > lock_limit) { - ret = -ENOMEM; - goto bail; - } - - ipath_cdbg(VERBOSE, "pin %lx pages from vaddr %lx\n", - (unsigned long) num_pages, start_page); - - for (got = 0; got < num_pages; got += ret) { - ret = get_user_pages(current, current->mm, - start_page + got * PAGE_SIZE, - num_pages - got, 1, 1, - p + got, NULL); - if (ret < 0) - goto bail_release; - } - - current->mm->pinned_vm += num_pages; - - ret = 0; - goto bail; - -bail_release: - __ipath_release_user_pages(p, got, 0); -bail: - return ret; -} - -/** - * ipath_map_page - a safety wrapper around pci_map_page() - * - * A dma_addr of all 0's is interpreted by the chip as "disabled". - * Unfortunately, it can also be a valid dma_addr returned on some - * architectures. - * - * The powerpc iommu assigns dma_addrs in ascending order, so we don't - * have to bother with retries or mapping a dummy page to insure we - * don't just get the same mapping again. - * - * I'm sure we won't be so lucky with other iommu's, so FIXME. - */ -dma_addr_t ipath_map_page(struct pci_dev *hwdev, struct page *page, - unsigned long offset, size_t size, int direction) -{ - dma_addr_t phys; - - phys = pci_map_page(hwdev, page, offset, size, direction); - - if (phys == 0) { - pci_unmap_page(hwdev, phys, size, direction); - phys = pci_map_page(hwdev, page, offset, size, direction); - /* - * FIXME: If we get 0 again, we should keep this page, - * map another, then free the 0 page. - */ - } - - return phys; -} - -/** - * ipath_map_single - a safety wrapper around pci_map_single() - * - * Same idea as ipath_map_page(). - */ -dma_addr_t ipath_map_single(struct pci_dev *hwdev, void *ptr, size_t size, - int direction) -{ - dma_addr_t phys; - - phys = pci_map_single(hwdev, ptr, size, direction); - - if (phys == 0) { - pci_unmap_single(hwdev, phys, size, direction); - phys = pci_map_single(hwdev, ptr, size, direction); - /* - * FIXME: If we get 0 again, we should keep this page, - * map another, then free the 0 page. - */ - } - - return phys; -} - -/** - * ipath_get_user_pages - lock user pages into memory - * @start_page: the start page - * @num_pages: the number of pages - * @p: the output page structures - * - * This function takes a given start page (page aligned user virtual - * address) and pins it and the following specified number of pages. For - * now, num_pages is always 1, but that will probably change at some point - * (because caller is doing expected sends on a single virtually contiguous - * buffer, so we can do all pages at once). - */ -int ipath_get_user_pages(unsigned long start_page, size_t num_pages, - struct page **p) -{ - int ret; - - down_write(¤t->mm->mmap_sem); - - ret = __ipath_get_user_pages(start_page, num_pages, p); - - up_write(¤t->mm->mmap_sem); - - return ret; -} - -void ipath_release_user_pages(struct page **p, size_t num_pages) -{ - down_write(¤t->mm->mmap_sem); - - __ipath_release_user_pages(p, num_pages, 1); - - current->mm->pinned_vm -= num_pages; - - up_write(¤t->mm->mmap_sem); -} - -struct ipath_user_pages_work { - struct work_struct work; - struct mm_struct *mm; - unsigned long num_pages; -}; - -static void user_pages_account(struct work_struct *_work) -{ - struct ipath_user_pages_work *work = - container_of(_work, struct ipath_user_pages_work, work); - - down_write(&work->mm->mmap_sem); - work->mm->pinned_vm -= work->num_pages; - up_write(&work->mm->mmap_sem); - mmput(work->mm); - kfree(work); -} - -void ipath_release_user_pages_on_close(struct page **p, size_t num_pages) -{ - struct ipath_user_pages_work *work; - struct mm_struct *mm; - - __ipath_release_user_pages(p, num_pages, 1); - - mm = get_task_mm(current); - if (!mm) - return; - - work = kmalloc(sizeof(*work), GFP_KERNEL); - if (!work) - goto bail_mm; - - INIT_WORK(&work->work, user_pages_account); - work->mm = mm; - work->num_pages = num_pages; - - queue_work(ib_wq, &work->work); - return; - -bail_mm: - mmput(mm); - return; -} diff --git a/drivers/staging/rdma/ipath/ipath_user_sdma.c b/drivers/staging/rdma/ipath/ipath_user_sdma.c deleted file mode 100644 index 8c12e3cccc58..000000000000 --- a/drivers/staging/rdma/ipath/ipath_user_sdma.c +++ /dev/null @@ -1,874 +0,0 @@ -/* - * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ipath_kernel.h" -#include "ipath_user_sdma.h" - -/* minimum size of header */ -#define IPATH_USER_SDMA_MIN_HEADER_LENGTH 64 -/* expected size of headers (for dma_pool) */ -#define IPATH_USER_SDMA_EXP_HEADER_LENGTH 64 -/* length mask in PBC (lower 11 bits) */ -#define IPATH_PBC_LENGTH_MASK ((1 << 11) - 1) - -struct ipath_user_sdma_pkt { - u8 naddr; /* dimension of addr (1..3) ... */ - u32 counter; /* sdma pkts queued counter for this entry */ - u64 added; /* global descq number of entries */ - - struct { - u32 offset; /* offset for kvaddr, addr */ - u32 length; /* length in page */ - u8 put_page; /* should we put_page? */ - u8 dma_mapped; /* is page dma_mapped? */ - struct page *page; /* may be NULL (coherent mem) */ - void *kvaddr; /* FIXME: only for pio hack */ - dma_addr_t addr; - } addr[4]; /* max pages, any more and we coalesce */ - struct list_head list; /* list element */ -}; - -struct ipath_user_sdma_queue { - /* - * pkts sent to dma engine are queued on this - * list head. the type of the elements of this - * list are struct ipath_user_sdma_pkt... - */ - struct list_head sent; - - /* headers with expected length are allocated from here... */ - char header_cache_name[64]; - struct dma_pool *header_cache; - - /* packets are allocated from the slab cache... */ - char pkt_slab_name[64]; - struct kmem_cache *pkt_slab; - - /* as packets go on the queued queue, they are counted... */ - u32 counter; - u32 sent_counter; - - /* dma page table */ - struct rb_root dma_pages_root; - - /* protect everything above... */ - struct mutex lock; -}; - -struct ipath_user_sdma_queue * -ipath_user_sdma_queue_create(struct device *dev, int unit, int port, int sport) -{ - struct ipath_user_sdma_queue *pq = - kmalloc(sizeof(struct ipath_user_sdma_queue), GFP_KERNEL); - - if (!pq) - goto done; - - pq->counter = 0; - pq->sent_counter = 0; - INIT_LIST_HEAD(&pq->sent); - - mutex_init(&pq->lock); - - snprintf(pq->pkt_slab_name, sizeof(pq->pkt_slab_name), - "ipath-user-sdma-pkts-%u-%02u.%02u", unit, port, sport); - pq->pkt_slab = kmem_cache_create(pq->pkt_slab_name, - sizeof(struct ipath_user_sdma_pkt), - 0, 0, NULL); - - if (!pq->pkt_slab) - goto err_kfree; - - snprintf(pq->header_cache_name, sizeof(pq->header_cache_name), - "ipath-user-sdma-headers-%u-%02u.%02u", unit, port, sport); - pq->header_cache = dma_pool_create(pq->header_cache_name, - dev, - IPATH_USER_SDMA_EXP_HEADER_LENGTH, - 4, 0); - if (!pq->header_cache) - goto err_slab; - - pq->dma_pages_root = RB_ROOT; - - goto done; - -err_slab: - kmem_cache_destroy(pq->pkt_slab); -err_kfree: - kfree(pq); - pq = NULL; - -done: - return pq; -} - -static void ipath_user_sdma_init_frag(struct ipath_user_sdma_pkt *pkt, - int i, size_t offset, size_t len, - int put_page, int dma_mapped, - struct page *page, - void *kvaddr, dma_addr_t dma_addr) -{ - pkt->addr[i].offset = offset; - pkt->addr[i].length = len; - pkt->addr[i].put_page = put_page; - pkt->addr[i].dma_mapped = dma_mapped; - pkt->addr[i].page = page; - pkt->addr[i].kvaddr = kvaddr; - pkt->addr[i].addr = dma_addr; -} - -static void ipath_user_sdma_init_header(struct ipath_user_sdma_pkt *pkt, - u32 counter, size_t offset, - size_t len, int dma_mapped, - struct page *page, - void *kvaddr, dma_addr_t dma_addr) -{ - pkt->naddr = 1; - pkt->counter = counter; - ipath_user_sdma_init_frag(pkt, 0, offset, len, 0, dma_mapped, page, - kvaddr, dma_addr); -} - -/* we've too many pages in the iovec, coalesce to a single page */ -static int ipath_user_sdma_coalesce(const struct ipath_devdata *dd, - struct ipath_user_sdma_pkt *pkt, - const struct iovec *iov, - unsigned long niov) { - int ret = 0; - struct page *page = alloc_page(GFP_KERNEL); - void *mpage_save; - char *mpage; - int i; - int len = 0; - dma_addr_t dma_addr; - - if (!page) { - ret = -ENOMEM; - goto done; - } - - mpage = kmap(page); - mpage_save = mpage; - for (i = 0; i < niov; i++) { - int cfur; - - cfur = copy_from_user(mpage, - iov[i].iov_base, iov[i].iov_len); - if (cfur) { - ret = -EFAULT; - goto free_unmap; - } - - mpage += iov[i].iov_len; - len += iov[i].iov_len; - } - - dma_addr = dma_map_page(&dd->pcidev->dev, page, 0, len, - DMA_TO_DEVICE); - if (dma_mapping_error(&dd->pcidev->dev, dma_addr)) { - ret = -ENOMEM; - goto free_unmap; - } - - ipath_user_sdma_init_frag(pkt, 1, 0, len, 0, 1, page, mpage_save, - dma_addr); - pkt->naddr = 2; - - goto done; - -free_unmap: - kunmap(page); - __free_page(page); -done: - return ret; -} - -/* how many pages in this iovec element? */ -static int ipath_user_sdma_num_pages(const struct iovec *iov) -{ - const unsigned long addr = (unsigned long) iov->iov_base; - const unsigned long len = iov->iov_len; - const unsigned long spage = addr & PAGE_MASK; - const unsigned long epage = (addr + len - 1) & PAGE_MASK; - - return 1 + ((epage - spage) >> PAGE_SHIFT); -} - -/* truncate length to page boundary */ -static int ipath_user_sdma_page_length(unsigned long addr, unsigned long len) -{ - const unsigned long offset = offset_in_page(addr); - - return ((offset + len) > PAGE_SIZE) ? (PAGE_SIZE - offset) : len; -} - -static void ipath_user_sdma_free_pkt_frag(struct device *dev, - struct ipath_user_sdma_queue *pq, - struct ipath_user_sdma_pkt *pkt, - int frag) -{ - const int i = frag; - - if (pkt->addr[i].page) { - if (pkt->addr[i].dma_mapped) - dma_unmap_page(dev, - pkt->addr[i].addr, - pkt->addr[i].length, - DMA_TO_DEVICE); - - if (pkt->addr[i].kvaddr) - kunmap(pkt->addr[i].page); - - if (pkt->addr[i].put_page) - put_page(pkt->addr[i].page); - else - __free_page(pkt->addr[i].page); - } else if (pkt->addr[i].kvaddr) - /* free coherent mem from cache... */ - dma_pool_free(pq->header_cache, - pkt->addr[i].kvaddr, pkt->addr[i].addr); -} - -/* return number of pages pinned... */ -static int ipath_user_sdma_pin_pages(const struct ipath_devdata *dd, - struct ipath_user_sdma_pkt *pkt, - unsigned long addr, int tlen, int npages) -{ - struct page *pages[2]; - int j; - int ret; - - ret = get_user_pages_fast(addr, npages, 0, pages); - if (ret != npages) { - int i; - - for (i = 0; i < ret; i++) - put_page(pages[i]); - - ret = -ENOMEM; - goto done; - } - - for (j = 0; j < npages; j++) { - /* map the pages... */ - const int flen = - ipath_user_sdma_page_length(addr, tlen); - dma_addr_t dma_addr = - dma_map_page(&dd->pcidev->dev, - pages[j], 0, flen, DMA_TO_DEVICE); - unsigned long fofs = offset_in_page(addr); - - if (dma_mapping_error(&dd->pcidev->dev, dma_addr)) { - ret = -ENOMEM; - goto done; - } - - ipath_user_sdma_init_frag(pkt, pkt->naddr, fofs, flen, 1, 1, - pages[j], kmap(pages[j]), - dma_addr); - - pkt->naddr++; - addr += flen; - tlen -= flen; - } - -done: - return ret; -} - -static int ipath_user_sdma_pin_pkt(const struct ipath_devdata *dd, - struct ipath_user_sdma_queue *pq, - struct ipath_user_sdma_pkt *pkt, - const struct iovec *iov, - unsigned long niov) -{ - int ret = 0; - unsigned long idx; - - for (idx = 0; idx < niov; idx++) { - const int npages = ipath_user_sdma_num_pages(iov + idx); - const unsigned long addr = (unsigned long) iov[idx].iov_base; - - ret = ipath_user_sdma_pin_pages(dd, pkt, - addr, iov[idx].iov_len, - npages); - if (ret < 0) - goto free_pkt; - } - - goto done; - -free_pkt: - for (idx = 0; idx < pkt->naddr; idx++) - ipath_user_sdma_free_pkt_frag(&dd->pcidev->dev, pq, pkt, idx); - -done: - return ret; -} - -static int ipath_user_sdma_init_payload(const struct ipath_devdata *dd, - struct ipath_user_sdma_queue *pq, - struct ipath_user_sdma_pkt *pkt, - const struct iovec *iov, - unsigned long niov, int npages) -{ - int ret = 0; - - if (npages >= ARRAY_SIZE(pkt->addr)) - ret = ipath_user_sdma_coalesce(dd, pkt, iov, niov); - else - ret = ipath_user_sdma_pin_pkt(dd, pq, pkt, iov, niov); - - return ret; -} - -/* free a packet list -- return counter value of last packet */ -static void ipath_user_sdma_free_pkt_list(struct device *dev, - struct ipath_user_sdma_queue *pq, - struct list_head *list) -{ - struct ipath_user_sdma_pkt *pkt, *pkt_next; - - list_for_each_entry_safe(pkt, pkt_next, list, list) { - int i; - - for (i = 0; i < pkt->naddr; i++) - ipath_user_sdma_free_pkt_frag(dev, pq, pkt, i); - - kmem_cache_free(pq->pkt_slab, pkt); - } -} - -/* - * copy headers, coalesce etc -- pq->lock must be held - * - * we queue all the packets to list, returning the - * number of bytes total. list must be empty initially, - * as, if there is an error we clean it... - */ -static int ipath_user_sdma_queue_pkts(const struct ipath_devdata *dd, - struct ipath_user_sdma_queue *pq, - struct list_head *list, - const struct iovec *iov, - unsigned long niov, - int maxpkts) -{ - unsigned long idx = 0; - int ret = 0; - int npkts = 0; - struct page *page = NULL; - __le32 *pbc; - dma_addr_t dma_addr; - struct ipath_user_sdma_pkt *pkt = NULL; - size_t len; - size_t nw; - u32 counter = pq->counter; - int dma_mapped = 0; - - while (idx < niov && npkts < maxpkts) { - const unsigned long addr = (unsigned long) iov[idx].iov_base; - const unsigned long idx_save = idx; - unsigned pktnw; - unsigned pktnwc; - int nfrags = 0; - int npages = 0; - int cfur; - - dma_mapped = 0; - len = iov[idx].iov_len; - nw = len >> 2; - page = NULL; - - pkt = kmem_cache_alloc(pq->pkt_slab, GFP_KERNEL); - if (!pkt) { - ret = -ENOMEM; - goto free_list; - } - - if (len < IPATH_USER_SDMA_MIN_HEADER_LENGTH || - len > PAGE_SIZE || len & 3 || addr & 3) { - ret = -EINVAL; - goto free_pkt; - } - - if (len == IPATH_USER_SDMA_EXP_HEADER_LENGTH) - pbc = dma_pool_alloc(pq->header_cache, GFP_KERNEL, - &dma_addr); - else - pbc = NULL; - - if (!pbc) { - page = alloc_page(GFP_KERNEL); - if (!page) { - ret = -ENOMEM; - goto free_pkt; - } - pbc = kmap(page); - } - - cfur = copy_from_user(pbc, iov[idx].iov_base, len); - if (cfur) { - ret = -EFAULT; - goto free_pbc; - } - - /* - * this assignment is a bit strange. it's because the - * the pbc counts the number of 32 bit words in the full - * packet _except_ the first word of the pbc itself... - */ - pktnwc = nw - 1; - - /* - * pktnw computation yields the number of 32 bit words - * that the caller has indicated in the PBC. note that - * this is one less than the total number of words that - * goes to the send DMA engine as the first 32 bit word - * of the PBC itself is not counted. Armed with this count, - * we can verify that the packet is consistent with the - * iovec lengths. - */ - pktnw = le32_to_cpu(*pbc) & IPATH_PBC_LENGTH_MASK; - if (pktnw < pktnwc || pktnw > pktnwc + (PAGE_SIZE >> 2)) { - ret = -EINVAL; - goto free_pbc; - } - - - idx++; - while (pktnwc < pktnw && idx < niov) { - const size_t slen = iov[idx].iov_len; - const unsigned long faddr = - (unsigned long) iov[idx].iov_base; - - if (slen & 3 || faddr & 3 || !slen || - slen > PAGE_SIZE) { - ret = -EINVAL; - goto free_pbc; - } - - npages++; - if ((faddr & PAGE_MASK) != - ((faddr + slen - 1) & PAGE_MASK)) - npages++; - - pktnwc += slen >> 2; - idx++; - nfrags++; - } - - if (pktnwc != pktnw) { - ret = -EINVAL; - goto free_pbc; - } - - if (page) { - dma_addr = dma_map_page(&dd->pcidev->dev, - page, 0, len, DMA_TO_DEVICE); - if (dma_mapping_error(&dd->pcidev->dev, dma_addr)) { - ret = -ENOMEM; - goto free_pbc; - } - - dma_mapped = 1; - } - - ipath_user_sdma_init_header(pkt, counter, 0, len, dma_mapped, - page, pbc, dma_addr); - - if (nfrags) { - ret = ipath_user_sdma_init_payload(dd, pq, pkt, - iov + idx_save + 1, - nfrags, npages); - if (ret < 0) - goto free_pbc_dma; - } - - counter++; - npkts++; - - list_add_tail(&pkt->list, list); - } - - ret = idx; - goto done; - -free_pbc_dma: - if (dma_mapped) - dma_unmap_page(&dd->pcidev->dev, dma_addr, len, DMA_TO_DEVICE); -free_pbc: - if (page) { - kunmap(page); - __free_page(page); - } else - dma_pool_free(pq->header_cache, pbc, dma_addr); -free_pkt: - kmem_cache_free(pq->pkt_slab, pkt); -free_list: - ipath_user_sdma_free_pkt_list(&dd->pcidev->dev, pq, list); -done: - return ret; -} - -static void ipath_user_sdma_set_complete_counter(struct ipath_user_sdma_queue *pq, - u32 c) -{ - pq->sent_counter = c; -} - -/* try to clean out queue -- needs pq->lock */ -static int ipath_user_sdma_queue_clean(const struct ipath_devdata *dd, - struct ipath_user_sdma_queue *pq) -{ - struct list_head free_list; - struct ipath_user_sdma_pkt *pkt; - struct ipath_user_sdma_pkt *pkt_prev; - int ret = 0; - - INIT_LIST_HEAD(&free_list); - - list_for_each_entry_safe(pkt, pkt_prev, &pq->sent, list) { - s64 descd = dd->ipath_sdma_descq_removed - pkt->added; - - if (descd < 0) - break; - - list_move_tail(&pkt->list, &free_list); - - /* one more packet cleaned */ - ret++; - } - - if (!list_empty(&free_list)) { - u32 counter; - - pkt = list_entry(free_list.prev, - struct ipath_user_sdma_pkt, list); - counter = pkt->counter; - - ipath_user_sdma_free_pkt_list(&dd->pcidev->dev, pq, &free_list); - ipath_user_sdma_set_complete_counter(pq, counter); - } - - return ret; -} - -void ipath_user_sdma_queue_destroy(struct ipath_user_sdma_queue *pq) -{ - if (!pq) - return; - - kmem_cache_destroy(pq->pkt_slab); - dma_pool_destroy(pq->header_cache); - kfree(pq); -} - -/* clean descriptor queue, returns > 0 if some elements cleaned */ -static int ipath_user_sdma_hwqueue_clean(struct ipath_devdata *dd) -{ - int ret; - unsigned long flags; - - spin_lock_irqsave(&dd->ipath_sdma_lock, flags); - ret = ipath_sdma_make_progress(dd); - spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); - - return ret; -} - -/* we're in close, drain packets so that we can cleanup successfully... */ -void ipath_user_sdma_queue_drain(struct ipath_devdata *dd, - struct ipath_user_sdma_queue *pq) -{ - int i; - - if (!pq) - return; - - for (i = 0; i < 100; i++) { - mutex_lock(&pq->lock); - if (list_empty(&pq->sent)) { - mutex_unlock(&pq->lock); - break; - } - ipath_user_sdma_hwqueue_clean(dd); - ipath_user_sdma_queue_clean(dd, pq); - mutex_unlock(&pq->lock); - msleep(10); - } - - if (!list_empty(&pq->sent)) { - struct list_head free_list; - - printk(KERN_INFO "drain: lists not empty: forcing!\n"); - INIT_LIST_HEAD(&free_list); - mutex_lock(&pq->lock); - list_splice_init(&pq->sent, &free_list); - ipath_user_sdma_free_pkt_list(&dd->pcidev->dev, pq, &free_list); - mutex_unlock(&pq->lock); - } -} - -static inline __le64 ipath_sdma_make_desc0(struct ipath_devdata *dd, - u64 addr, u64 dwlen, u64 dwoffset) -{ - return cpu_to_le64(/* SDmaPhyAddr[31:0] */ - ((addr & 0xfffffffcULL) << 32) | - /* SDmaGeneration[1:0] */ - ((dd->ipath_sdma_generation & 3ULL) << 30) | - /* SDmaDwordCount[10:0] */ - ((dwlen & 0x7ffULL) << 16) | - /* SDmaBufOffset[12:2] */ - (dwoffset & 0x7ffULL)); -} - -static inline __le64 ipath_sdma_make_first_desc0(__le64 descq) -{ - return descq | cpu_to_le64(1ULL << 12); -} - -static inline __le64 ipath_sdma_make_last_desc0(__le64 descq) -{ - /* last */ /* dma head */ - return descq | cpu_to_le64(1ULL << 11 | 1ULL << 13); -} - -static inline __le64 ipath_sdma_make_desc1(u64 addr) -{ - /* SDmaPhyAddr[47:32] */ - return cpu_to_le64(addr >> 32); -} - -static void ipath_user_sdma_send_frag(struct ipath_devdata *dd, - struct ipath_user_sdma_pkt *pkt, int idx, - unsigned ofs, u16 tail) -{ - const u64 addr = (u64) pkt->addr[idx].addr + - (u64) pkt->addr[idx].offset; - const u64 dwlen = (u64) pkt->addr[idx].length / 4; - __le64 *descqp; - __le64 descq0; - - descqp = &dd->ipath_sdma_descq[tail].qw[0]; - - descq0 = ipath_sdma_make_desc0(dd, addr, dwlen, ofs); - if (idx == 0) - descq0 = ipath_sdma_make_first_desc0(descq0); - if (idx == pkt->naddr - 1) - descq0 = ipath_sdma_make_last_desc0(descq0); - - descqp[0] = descq0; - descqp[1] = ipath_sdma_make_desc1(addr); -} - -/* pq->lock must be held, get packets on the wire... */ -static int ipath_user_sdma_push_pkts(struct ipath_devdata *dd, - struct ipath_user_sdma_queue *pq, - struct list_head *pktlist) -{ - int ret = 0; - unsigned long flags; - u16 tail; - - if (list_empty(pktlist)) - return 0; - - if (unlikely(!(dd->ipath_flags & IPATH_LINKACTIVE))) - return -ECOMM; - - spin_lock_irqsave(&dd->ipath_sdma_lock, flags); - - if (unlikely(dd->ipath_sdma_status & IPATH_SDMA_ABORT_MASK)) { - ret = -ECOMM; - goto unlock; - } - - tail = dd->ipath_sdma_descq_tail; - while (!list_empty(pktlist)) { - struct ipath_user_sdma_pkt *pkt = - list_entry(pktlist->next, struct ipath_user_sdma_pkt, - list); - int i; - unsigned ofs = 0; - u16 dtail = tail; - - if (pkt->naddr > ipath_sdma_descq_freecnt(dd)) - goto unlock_check_tail; - - for (i = 0; i < pkt->naddr; i++) { - ipath_user_sdma_send_frag(dd, pkt, i, ofs, tail); - ofs += pkt->addr[i].length >> 2; - - if (++tail == dd->ipath_sdma_descq_cnt) { - tail = 0; - ++dd->ipath_sdma_generation; - } - } - - if ((ofs<<2) > dd->ipath_ibmaxlen) { - ipath_dbg("packet size %X > ibmax %X, fail\n", - ofs<<2, dd->ipath_ibmaxlen); - ret = -EMSGSIZE; - goto unlock; - } - - /* - * if the packet is >= 2KB mtu equivalent, we have to use - * the large buffers, and have to mark each descriptor as - * part of a large buffer packet. - */ - if (ofs >= IPATH_SMALLBUF_DWORDS) { - for (i = 0; i < pkt->naddr; i++) { - dd->ipath_sdma_descq[dtail].qw[0] |= - cpu_to_le64(1ULL << 14); - if (++dtail == dd->ipath_sdma_descq_cnt) - dtail = 0; - } - } - - dd->ipath_sdma_descq_added += pkt->naddr; - pkt->added = dd->ipath_sdma_descq_added; - list_move_tail(&pkt->list, &pq->sent); - ret++; - } - -unlock_check_tail: - /* advance the tail on the chip if necessary */ - if (dd->ipath_sdma_descq_tail != tail) { - wmb(); - ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmatail, tail); - dd->ipath_sdma_descq_tail = tail; - } - -unlock: - spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); - - return ret; -} - -int ipath_user_sdma_writev(struct ipath_devdata *dd, - struct ipath_user_sdma_queue *pq, - const struct iovec *iov, - unsigned long dim) -{ - int ret = 0; - struct list_head list; - int npkts = 0; - - INIT_LIST_HEAD(&list); - - mutex_lock(&pq->lock); - - if (dd->ipath_sdma_descq_added != dd->ipath_sdma_descq_removed) { - ipath_user_sdma_hwqueue_clean(dd); - ipath_user_sdma_queue_clean(dd, pq); - } - - while (dim) { - const int mxp = 8; - - ret = ipath_user_sdma_queue_pkts(dd, pq, &list, iov, dim, mxp); - if (ret <= 0) - goto done_unlock; - else { - dim -= ret; - iov += ret; - } - - /* force packets onto the sdma hw queue... */ - if (!list_empty(&list)) { - /* - * lazily clean hw queue. the 4 is a guess of about - * how many sdma descriptors a packet will take (it - * doesn't have to be perfect). - */ - if (ipath_sdma_descq_freecnt(dd) < ret * 4) { - ipath_user_sdma_hwqueue_clean(dd); - ipath_user_sdma_queue_clean(dd, pq); - } - - ret = ipath_user_sdma_push_pkts(dd, pq, &list); - if (ret < 0) - goto done_unlock; - else { - npkts += ret; - pq->counter += ret; - - if (!list_empty(&list)) - goto done_unlock; - } - } - } - -done_unlock: - if (!list_empty(&list)) - ipath_user_sdma_free_pkt_list(&dd->pcidev->dev, pq, &list); - mutex_unlock(&pq->lock); - - return (ret < 0) ? ret : npkts; -} - -int ipath_user_sdma_make_progress(struct ipath_devdata *dd, - struct ipath_user_sdma_queue *pq) -{ - int ret = 0; - - mutex_lock(&pq->lock); - ipath_user_sdma_hwqueue_clean(dd); - ret = ipath_user_sdma_queue_clean(dd, pq); - mutex_unlock(&pq->lock); - - return ret; -} - -u32 ipath_user_sdma_complete_counter(const struct ipath_user_sdma_queue *pq) -{ - return pq->sent_counter; -} - -u32 ipath_user_sdma_inflight_counter(struct ipath_user_sdma_queue *pq) -{ - return pq->counter; -} - diff --git a/drivers/staging/rdma/ipath/ipath_user_sdma.h b/drivers/staging/rdma/ipath/ipath_user_sdma.h deleted file mode 100644 index fc76316c4a58..000000000000 --- a/drivers/staging/rdma/ipath/ipath_user_sdma.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include - -struct ipath_user_sdma_queue; - -struct ipath_user_sdma_queue * -ipath_user_sdma_queue_create(struct device *dev, int unit, int port, int sport); -void ipath_user_sdma_queue_destroy(struct ipath_user_sdma_queue *pq); - -int ipath_user_sdma_writev(struct ipath_devdata *dd, - struct ipath_user_sdma_queue *pq, - const struct iovec *iov, - unsigned long dim); - -int ipath_user_sdma_make_progress(struct ipath_devdata *dd, - struct ipath_user_sdma_queue *pq); - -void ipath_user_sdma_queue_drain(struct ipath_devdata *dd, - struct ipath_user_sdma_queue *pq); - -u32 ipath_user_sdma_complete_counter(const struct ipath_user_sdma_queue *pq); -u32 ipath_user_sdma_inflight_counter(struct ipath_user_sdma_queue *pq); diff --git a/drivers/staging/rdma/ipath/ipath_verbs.c b/drivers/staging/rdma/ipath/ipath_verbs.c deleted file mode 100644 index 53f9dcab180d..000000000000 --- a/drivers/staging/rdma/ipath/ipath_verbs.c +++ /dev/null @@ -1,2376 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "ipath_kernel.h" -#include "ipath_verbs.h" -#include "ipath_common.h" - -static unsigned int ib_ipath_qp_table_size = 251; -module_param_named(qp_table_size, ib_ipath_qp_table_size, uint, S_IRUGO); -MODULE_PARM_DESC(qp_table_size, "QP table size"); - -unsigned int ib_ipath_lkey_table_size = 12; -module_param_named(lkey_table_size, ib_ipath_lkey_table_size, uint, - S_IRUGO); -MODULE_PARM_DESC(lkey_table_size, - "LKEY table size in bits (2^n, 1 <= n <= 23)"); - -static unsigned int ib_ipath_max_pds = 0xFFFF; -module_param_named(max_pds, ib_ipath_max_pds, uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(max_pds, - "Maximum number of protection domains to support"); - -static unsigned int ib_ipath_max_ahs = 0xFFFF; -module_param_named(max_ahs, ib_ipath_max_ahs, uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(max_ahs, "Maximum number of address handles to support"); - -unsigned int ib_ipath_max_cqes = 0x2FFFF; -module_param_named(max_cqes, ib_ipath_max_cqes, uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(max_cqes, - "Maximum number of completion queue entries to support"); - -unsigned int ib_ipath_max_cqs = 0x1FFFF; -module_param_named(max_cqs, ib_ipath_max_cqs, uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(max_cqs, "Maximum number of completion queues to support"); - -unsigned int ib_ipath_max_qp_wrs = 0x3FFF; -module_param_named(max_qp_wrs, ib_ipath_max_qp_wrs, uint, - S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(max_qp_wrs, "Maximum number of QP WRs to support"); - -unsigned int ib_ipath_max_qps = 16384; -module_param_named(max_qps, ib_ipath_max_qps, uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(max_qps, "Maximum number of QPs to support"); - -unsigned int ib_ipath_max_sges = 0x60; -module_param_named(max_sges, ib_ipath_max_sges, uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(max_sges, "Maximum number of SGEs to support"); - -unsigned int ib_ipath_max_mcast_grps = 16384; -module_param_named(max_mcast_grps, ib_ipath_max_mcast_grps, uint, - S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(max_mcast_grps, - "Maximum number of multicast groups to support"); - -unsigned int ib_ipath_max_mcast_qp_attached = 16; -module_param_named(max_mcast_qp_attached, ib_ipath_max_mcast_qp_attached, - uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(max_mcast_qp_attached, - "Maximum number of attached QPs to support"); - -unsigned int ib_ipath_max_srqs = 1024; -module_param_named(max_srqs, ib_ipath_max_srqs, uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(max_srqs, "Maximum number of SRQs to support"); - -unsigned int ib_ipath_max_srq_sges = 128; -module_param_named(max_srq_sges, ib_ipath_max_srq_sges, - uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(max_srq_sges, "Maximum number of SRQ SGEs to support"); - -unsigned int ib_ipath_max_srq_wrs = 0x1FFFF; -module_param_named(max_srq_wrs, ib_ipath_max_srq_wrs, - uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(max_srq_wrs, "Maximum number of SRQ WRs support"); - -static unsigned int ib_ipath_disable_sma; -module_param_named(disable_sma, ib_ipath_disable_sma, uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(disable_sma, "Disable the SMA"); - -/* - * Note that it is OK to post send work requests in the SQE and ERR - * states; ipath_do_send() will process them and generate error - * completions as per IB 1.2 C10-96. - */ -const int ib_ipath_state_ops[IB_QPS_ERR + 1] = { - [IB_QPS_RESET] = 0, - [IB_QPS_INIT] = IPATH_POST_RECV_OK, - [IB_QPS_RTR] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK, - [IB_QPS_RTS] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK | - IPATH_POST_SEND_OK | IPATH_PROCESS_SEND_OK | - IPATH_PROCESS_NEXT_SEND_OK, - [IB_QPS_SQD] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK | - IPATH_POST_SEND_OK | IPATH_PROCESS_SEND_OK, - [IB_QPS_SQE] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK | - IPATH_POST_SEND_OK | IPATH_FLUSH_SEND, - [IB_QPS_ERR] = IPATH_POST_RECV_OK | IPATH_FLUSH_RECV | - IPATH_POST_SEND_OK | IPATH_FLUSH_SEND, -}; - -struct ipath_ucontext { - struct ib_ucontext ibucontext; -}; - -static inline struct ipath_ucontext *to_iucontext(struct ib_ucontext - *ibucontext) -{ - return container_of(ibucontext, struct ipath_ucontext, ibucontext); -} - -/* - * Translate ib_wr_opcode into ib_wc_opcode. - */ -const enum ib_wc_opcode ib_ipath_wc_opcode[] = { - [IB_WR_RDMA_WRITE] = IB_WC_RDMA_WRITE, - [IB_WR_RDMA_WRITE_WITH_IMM] = IB_WC_RDMA_WRITE, - [IB_WR_SEND] = IB_WC_SEND, - [IB_WR_SEND_WITH_IMM] = IB_WC_SEND, - [IB_WR_RDMA_READ] = IB_WC_RDMA_READ, - [IB_WR_ATOMIC_CMP_AND_SWP] = IB_WC_COMP_SWAP, - [IB_WR_ATOMIC_FETCH_AND_ADD] = IB_WC_FETCH_ADD -}; - -/* - * System image GUID. - */ -static __be64 sys_image_guid; - -/** - * ipath_copy_sge - copy data to SGE memory - * @ss: the SGE state - * @data: the data to copy - * @length: the length of the data - */ -void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length) -{ - struct ipath_sge *sge = &ss->sge; - - while (length) { - u32 len = sge->length; - - if (len > length) - len = length; - if (len > sge->sge_length) - len = sge->sge_length; - BUG_ON(len == 0); - memcpy(sge->vaddr, data, len); - sge->vaddr += len; - sge->length -= len; - sge->sge_length -= len; - if (sge->sge_length == 0) { - if (--ss->num_sge) - *sge = *ss->sg_list++; - } else if (sge->length == 0 && sge->mr != NULL) { - if (++sge->n >= IPATH_SEGSZ) { - if (++sge->m >= sge->mr->mapsz) - break; - sge->n = 0; - } - sge->vaddr = - sge->mr->map[sge->m]->segs[sge->n].vaddr; - sge->length = - sge->mr->map[sge->m]->segs[sge->n].length; - } - data += len; - length -= len; - } -} - -/** - * ipath_skip_sge - skip over SGE memory - XXX almost dup of prev func - * @ss: the SGE state - * @length: the number of bytes to skip - */ -void ipath_skip_sge(struct ipath_sge_state *ss, u32 length) -{ - struct ipath_sge *sge = &ss->sge; - - while (length) { - u32 len = sge->length; - - if (len > length) - len = length; - if (len > sge->sge_length) - len = sge->sge_length; - BUG_ON(len == 0); - sge->vaddr += len; - sge->length -= len; - sge->sge_length -= len; - if (sge->sge_length == 0) { - if (--ss->num_sge) - *sge = *ss->sg_list++; - } else if (sge->length == 0 && sge->mr != NULL) { - if (++sge->n >= IPATH_SEGSZ) { - if (++sge->m >= sge->mr->mapsz) - break; - sge->n = 0; - } - sge->vaddr = - sge->mr->map[sge->m]->segs[sge->n].vaddr; - sge->length = - sge->mr->map[sge->m]->segs[sge->n].length; - } - length -= len; - } -} - -/* - * Count the number of DMA descriptors needed to send length bytes of data. - * Don't modify the ipath_sge_state to get the count. - * Return zero if any of the segments is not aligned. - */ -static u32 ipath_count_sge(struct ipath_sge_state *ss, u32 length) -{ - struct ipath_sge *sg_list = ss->sg_list; - struct ipath_sge sge = ss->sge; - u8 num_sge = ss->num_sge; - u32 ndesc = 1; /* count the header */ - - while (length) { - u32 len = sge.length; - - if (len > length) - len = length; - if (len > sge.sge_length) - len = sge.sge_length; - BUG_ON(len == 0); - if (((long) sge.vaddr & (sizeof(u32) - 1)) || - (len != length && (len & (sizeof(u32) - 1)))) { - ndesc = 0; - break; - } - ndesc++; - sge.vaddr += len; - sge.length -= len; - sge.sge_length -= len; - if (sge.sge_length == 0) { - if (--num_sge) - sge = *sg_list++; - } else if (sge.length == 0 && sge.mr != NULL) { - if (++sge.n >= IPATH_SEGSZ) { - if (++sge.m >= sge.mr->mapsz) - break; - sge.n = 0; - } - sge.vaddr = - sge.mr->map[sge.m]->segs[sge.n].vaddr; - sge.length = - sge.mr->map[sge.m]->segs[sge.n].length; - } - length -= len; - } - return ndesc; -} - -/* - * Copy from the SGEs to the data buffer. - */ -static void ipath_copy_from_sge(void *data, struct ipath_sge_state *ss, - u32 length) -{ - struct ipath_sge *sge = &ss->sge; - - while (length) { - u32 len = sge->length; - - if (len > length) - len = length; - if (len > sge->sge_length) - len = sge->sge_length; - BUG_ON(len == 0); - memcpy(data, sge->vaddr, len); - sge->vaddr += len; - sge->length -= len; - sge->sge_length -= len; - if (sge->sge_length == 0) { - if (--ss->num_sge) - *sge = *ss->sg_list++; - } else if (sge->length == 0 && sge->mr != NULL) { - if (++sge->n >= IPATH_SEGSZ) { - if (++sge->m >= sge->mr->mapsz) - break; - sge->n = 0; - } - sge->vaddr = - sge->mr->map[sge->m]->segs[sge->n].vaddr; - sge->length = - sge->mr->map[sge->m]->segs[sge->n].length; - } - data += len; - length -= len; - } -} - -/** - * ipath_post_one_send - post one RC, UC, or UD send work request - * @qp: the QP to post on - * @wr: the work request to send - */ -static int ipath_post_one_send(struct ipath_qp *qp, struct ib_send_wr *wr) -{ - struct ipath_swqe *wqe; - u32 next; - int i; - int j; - int acc; - int ret; - unsigned long flags; - struct ipath_devdata *dd = to_idev(qp->ibqp.device)->dd; - - spin_lock_irqsave(&qp->s_lock, flags); - - if (qp->ibqp.qp_type != IB_QPT_SMI && - !(dd->ipath_flags & IPATH_LINKACTIVE)) { - ret = -ENETDOWN; - goto bail; - } - - /* Check that state is OK to post send. */ - if (unlikely(!(ib_ipath_state_ops[qp->state] & IPATH_POST_SEND_OK))) - goto bail_inval; - - /* IB spec says that num_sge == 0 is OK. */ - if (wr->num_sge > qp->s_max_sge) - goto bail_inval; - - /* - * Don't allow RDMA reads or atomic operations on UC or - * undefined operations. - * Make sure buffer is large enough to hold the result for atomics. - */ - if (qp->ibqp.qp_type == IB_QPT_UC) { - if ((unsigned) wr->opcode >= IB_WR_RDMA_READ) - goto bail_inval; - } else if (qp->ibqp.qp_type == IB_QPT_UD) { - /* Check UD opcode */ - if (wr->opcode != IB_WR_SEND && - wr->opcode != IB_WR_SEND_WITH_IMM) - goto bail_inval; - /* Check UD destination address PD */ - if (qp->ibqp.pd != ud_wr(wr)->ah->pd) - goto bail_inval; - } else if ((unsigned) wr->opcode > IB_WR_ATOMIC_FETCH_AND_ADD) - goto bail_inval; - else if (wr->opcode >= IB_WR_ATOMIC_CMP_AND_SWP && - (wr->num_sge == 0 || - wr->sg_list[0].length < sizeof(u64) || - wr->sg_list[0].addr & (sizeof(u64) - 1))) - goto bail_inval; - else if (wr->opcode >= IB_WR_RDMA_READ && !qp->s_max_rd_atomic) - goto bail_inval; - - next = qp->s_head + 1; - if (next >= qp->s_size) - next = 0; - if (next == qp->s_last) { - ret = -ENOMEM; - goto bail; - } - - wqe = get_swqe_ptr(qp, qp->s_head); - - if (qp->ibqp.qp_type != IB_QPT_UC && - qp->ibqp.qp_type != IB_QPT_RC) - memcpy(&wqe->ud_wr, ud_wr(wr), sizeof(wqe->ud_wr)); - else if (wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM || - wr->opcode == IB_WR_RDMA_WRITE || - wr->opcode == IB_WR_RDMA_READ) - memcpy(&wqe->rdma_wr, rdma_wr(wr), sizeof(wqe->rdma_wr)); - else if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP || - wr->opcode == IB_WR_ATOMIC_FETCH_AND_ADD) - memcpy(&wqe->atomic_wr, atomic_wr(wr), sizeof(wqe->atomic_wr)); - else - memcpy(&wqe->wr, wr, sizeof(wqe->wr)); - - wqe->length = 0; - if (wr->num_sge) { - acc = wr->opcode >= IB_WR_RDMA_READ ? - IB_ACCESS_LOCAL_WRITE : 0; - for (i = 0, j = 0; i < wr->num_sge; i++) { - u32 length = wr->sg_list[i].length; - int ok; - - if (length == 0) - continue; - ok = ipath_lkey_ok(qp, &wqe->sg_list[j], - &wr->sg_list[i], acc); - if (!ok) - goto bail_inval; - wqe->length += length; - j++; - } - wqe->wr.num_sge = j; - } - if (qp->ibqp.qp_type == IB_QPT_UC || - qp->ibqp.qp_type == IB_QPT_RC) { - if (wqe->length > 0x80000000U) - goto bail_inval; - } else if (wqe->length > to_idev(qp->ibqp.device)->dd->ipath_ibmtu) - goto bail_inval; - wqe->ssn = qp->s_ssn++; - qp->s_head = next; - - ret = 0; - goto bail; - -bail_inval: - ret = -EINVAL; -bail: - spin_unlock_irqrestore(&qp->s_lock, flags); - return ret; -} - -/** - * ipath_post_send - post a send on a QP - * @ibqp: the QP to post the send on - * @wr: the list of work requests to post - * @bad_wr: the first bad WR is put here - * - * This may be called from interrupt context. - */ -static int ipath_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, - struct ib_send_wr **bad_wr) -{ - struct ipath_qp *qp = to_iqp(ibqp); - int err = 0; - - for (; wr; wr = wr->next) { - err = ipath_post_one_send(qp, wr); - if (err) { - *bad_wr = wr; - goto bail; - } - } - - /* Try to do the send work in the caller's context. */ - ipath_do_send((unsigned long) qp); - -bail: - return err; -} - -/** - * ipath_post_receive - post a receive on a QP - * @ibqp: the QP to post the receive on - * @wr: the WR to post - * @bad_wr: the first bad WR is put here - * - * This may be called from interrupt context. - */ -static int ipath_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, - struct ib_recv_wr **bad_wr) -{ - struct ipath_qp *qp = to_iqp(ibqp); - struct ipath_rwq *wq = qp->r_rq.wq; - unsigned long flags; - int ret; - - /* Check that state is OK to post receive. */ - if (!(ib_ipath_state_ops[qp->state] & IPATH_POST_RECV_OK) || !wq) { - *bad_wr = wr; - ret = -EINVAL; - goto bail; - } - - for (; wr; wr = wr->next) { - struct ipath_rwqe *wqe; - u32 next; - int i; - - if ((unsigned) wr->num_sge > qp->r_rq.max_sge) { - *bad_wr = wr; - ret = -EINVAL; - goto bail; - } - - spin_lock_irqsave(&qp->r_rq.lock, flags); - next = wq->head + 1; - if (next >= qp->r_rq.size) - next = 0; - if (next == wq->tail) { - spin_unlock_irqrestore(&qp->r_rq.lock, flags); - *bad_wr = wr; - ret = -ENOMEM; - goto bail; - } - - wqe = get_rwqe_ptr(&qp->r_rq, wq->head); - wqe->wr_id = wr->wr_id; - wqe->num_sge = wr->num_sge; - for (i = 0; i < wr->num_sge; i++) - wqe->sg_list[i] = wr->sg_list[i]; - /* Make sure queue entry is written before the head index. */ - smp_wmb(); - wq->head = next; - spin_unlock_irqrestore(&qp->r_rq.lock, flags); - } - ret = 0; - -bail: - return ret; -} - -/** - * ipath_qp_rcv - processing an incoming packet on a QP - * @dev: the device the packet came on - * @hdr: the packet header - * @has_grh: true if the packet has a GRH - * @data: the packet data - * @tlen: the packet length - * @qp: the QP the packet came on - * - * This is called from ipath_ib_rcv() to process an incoming packet - * for the given QP. - * Called at interrupt level. - */ -static void ipath_qp_rcv(struct ipath_ibdev *dev, - struct ipath_ib_header *hdr, int has_grh, - void *data, u32 tlen, struct ipath_qp *qp) -{ - /* Check for valid receive state. */ - if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) { - dev->n_pkt_drops++; - return; - } - - switch (qp->ibqp.qp_type) { - case IB_QPT_SMI: - case IB_QPT_GSI: - if (ib_ipath_disable_sma) - break; - /* FALLTHROUGH */ - case IB_QPT_UD: - ipath_ud_rcv(dev, hdr, has_grh, data, tlen, qp); - break; - - case IB_QPT_RC: - ipath_rc_rcv(dev, hdr, has_grh, data, tlen, qp); - break; - - case IB_QPT_UC: - ipath_uc_rcv(dev, hdr, has_grh, data, tlen, qp); - break; - - default: - break; - } -} - -/** - * ipath_ib_rcv - process an incoming packet - * @arg: the device pointer - * @rhdr: the header of the packet - * @data: the packet data - * @tlen: the packet length - * - * This is called from ipath_kreceive() to process an incoming packet at - * interrupt level. Tlen is the length of the header + data + CRC in bytes. - */ -void ipath_ib_rcv(struct ipath_ibdev *dev, void *rhdr, void *data, - u32 tlen) -{ - struct ipath_ib_header *hdr = rhdr; - struct ipath_other_headers *ohdr; - struct ipath_qp *qp; - u32 qp_num; - int lnh; - u8 opcode; - u16 lid; - - if (unlikely(dev == NULL)) - goto bail; - - if (unlikely(tlen < 24)) { /* LRH+BTH+CRC */ - dev->rcv_errors++; - goto bail; - } - - /* Check for a valid destination LID (see ch. 7.11.1). */ - lid = be16_to_cpu(hdr->lrh[1]); - if (lid < IPATH_MULTICAST_LID_BASE) { - lid &= ~((1 << dev->dd->ipath_lmc) - 1); - if (unlikely(lid != dev->dd->ipath_lid)) { - dev->rcv_errors++; - goto bail; - } - } - - /* Check for GRH */ - lnh = be16_to_cpu(hdr->lrh[0]) & 3; - if (lnh == IPATH_LRH_BTH) - ohdr = &hdr->u.oth; - else if (lnh == IPATH_LRH_GRH) - ohdr = &hdr->u.l.oth; - else { - dev->rcv_errors++; - goto bail; - } - - opcode = (be32_to_cpu(ohdr->bth[0]) >> 24) & 0x7f; - dev->opstats[opcode].n_bytes += tlen; - dev->opstats[opcode].n_packets++; - - /* Get the destination QP number. */ - qp_num = be32_to_cpu(ohdr->bth[1]) & IPATH_QPN_MASK; - if (qp_num == IPATH_MULTICAST_QPN) { - struct ipath_mcast *mcast; - struct ipath_mcast_qp *p; - - if (lnh != IPATH_LRH_GRH) { - dev->n_pkt_drops++; - goto bail; - } - mcast = ipath_mcast_find(&hdr->u.l.grh.dgid); - if (mcast == NULL) { - dev->n_pkt_drops++; - goto bail; - } - dev->n_multicast_rcv++; - list_for_each_entry_rcu(p, &mcast->qp_list, list) - ipath_qp_rcv(dev, hdr, 1, data, tlen, p->qp); - /* - * Notify ipath_multicast_detach() if it is waiting for us - * to finish. - */ - if (atomic_dec_return(&mcast->refcount) <= 1) - wake_up(&mcast->wait); - } else { - qp = ipath_lookup_qpn(&dev->qp_table, qp_num); - if (qp) { - dev->n_unicast_rcv++; - ipath_qp_rcv(dev, hdr, lnh == IPATH_LRH_GRH, data, - tlen, qp); - /* - * Notify ipath_destroy_qp() if it is waiting - * for us to finish. - */ - if (atomic_dec_and_test(&qp->refcount)) - wake_up(&qp->wait); - } else - dev->n_pkt_drops++; - } - -bail:; -} - -/** - * ipath_ib_timer - verbs timer - * @arg: the device pointer - * - * This is called from ipath_do_rcv_timer() at interrupt level to check for - * QPs which need retransmits and to collect performance numbers. - */ -static void ipath_ib_timer(struct ipath_ibdev *dev) -{ - struct ipath_qp *resend = NULL; - struct ipath_qp *rnr = NULL; - struct list_head *last; - struct ipath_qp *qp; - unsigned long flags; - - if (dev == NULL) - return; - - spin_lock_irqsave(&dev->pending_lock, flags); - /* Start filling the next pending queue. */ - if (++dev->pending_index >= ARRAY_SIZE(dev->pending)) - dev->pending_index = 0; - /* Save any requests still in the new queue, they have timed out. */ - last = &dev->pending[dev->pending_index]; - while (!list_empty(last)) { - qp = list_entry(last->next, struct ipath_qp, timerwait); - list_del_init(&qp->timerwait); - qp->timer_next = resend; - resend = qp; - atomic_inc(&qp->refcount); - } - last = &dev->rnrwait; - if (!list_empty(last)) { - qp = list_entry(last->next, struct ipath_qp, timerwait); - if (--qp->s_rnr_timeout == 0) { - do { - list_del_init(&qp->timerwait); - qp->timer_next = rnr; - rnr = qp; - atomic_inc(&qp->refcount); - if (list_empty(last)) - break; - qp = list_entry(last->next, struct ipath_qp, - timerwait); - } while (qp->s_rnr_timeout == 0); - } - } - /* - * We should only be in the started state if pma_sample_start != 0 - */ - if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_STARTED && - --dev->pma_sample_start == 0) { - dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_RUNNING; - ipath_snapshot_counters(dev->dd, &dev->ipath_sword, - &dev->ipath_rword, - &dev->ipath_spkts, - &dev->ipath_rpkts, - &dev->ipath_xmit_wait); - } - if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_RUNNING) { - if (dev->pma_sample_interval == 0) { - u64 ta, tb, tc, td, te; - - dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_DONE; - ipath_snapshot_counters(dev->dd, &ta, &tb, - &tc, &td, &te); - - dev->ipath_sword = ta - dev->ipath_sword; - dev->ipath_rword = tb - dev->ipath_rword; - dev->ipath_spkts = tc - dev->ipath_spkts; - dev->ipath_rpkts = td - dev->ipath_rpkts; - dev->ipath_xmit_wait = te - dev->ipath_xmit_wait; - } else { - dev->pma_sample_interval--; - } - } - spin_unlock_irqrestore(&dev->pending_lock, flags); - - /* XXX What if timer fires again while this is running? */ - while (resend != NULL) { - qp = resend; - resend = qp->timer_next; - - spin_lock_irqsave(&qp->s_lock, flags); - if (qp->s_last != qp->s_tail && - ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK) { - dev->n_timeouts++; - ipath_restart_rc(qp, qp->s_last_psn + 1); - } - spin_unlock_irqrestore(&qp->s_lock, flags); - - /* Notify ipath_destroy_qp() if it is waiting. */ - if (atomic_dec_and_test(&qp->refcount)) - wake_up(&qp->wait); - } - while (rnr != NULL) { - qp = rnr; - rnr = qp->timer_next; - - spin_lock_irqsave(&qp->s_lock, flags); - if (ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK) - ipath_schedule_send(qp); - spin_unlock_irqrestore(&qp->s_lock, flags); - - /* Notify ipath_destroy_qp() if it is waiting. */ - if (atomic_dec_and_test(&qp->refcount)) - wake_up(&qp->wait); - } -} - -static void update_sge(struct ipath_sge_state *ss, u32 length) -{ - struct ipath_sge *sge = &ss->sge; - - sge->vaddr += length; - sge->length -= length; - sge->sge_length -= length; - if (sge->sge_length == 0) { - if (--ss->num_sge) - *sge = *ss->sg_list++; - } else if (sge->length == 0 && sge->mr != NULL) { - if (++sge->n >= IPATH_SEGSZ) { - if (++sge->m >= sge->mr->mapsz) - return; - sge->n = 0; - } - sge->vaddr = sge->mr->map[sge->m]->segs[sge->n].vaddr; - sge->length = sge->mr->map[sge->m]->segs[sge->n].length; - } -} - -#ifdef __LITTLE_ENDIAN -static inline u32 get_upper_bits(u32 data, u32 shift) -{ - return data >> shift; -} - -static inline u32 set_upper_bits(u32 data, u32 shift) -{ - return data << shift; -} - -static inline u32 clear_upper_bytes(u32 data, u32 n, u32 off) -{ - data <<= ((sizeof(u32) - n) * BITS_PER_BYTE); - data >>= ((sizeof(u32) - n - off) * BITS_PER_BYTE); - return data; -} -#else -static inline u32 get_upper_bits(u32 data, u32 shift) -{ - return data << shift; -} - -static inline u32 set_upper_bits(u32 data, u32 shift) -{ - return data >> shift; -} - -static inline u32 clear_upper_bytes(u32 data, u32 n, u32 off) -{ - data >>= ((sizeof(u32) - n) * BITS_PER_BYTE); - data <<= ((sizeof(u32) - n - off) * BITS_PER_BYTE); - return data; -} -#endif - -static void copy_io(u32 __iomem *piobuf, struct ipath_sge_state *ss, - u32 length, unsigned flush_wc) -{ - u32 extra = 0; - u32 data = 0; - u32 last; - - while (1) { - u32 len = ss->sge.length; - u32 off; - - if (len > length) - len = length; - if (len > ss->sge.sge_length) - len = ss->sge.sge_length; - BUG_ON(len == 0); - /* If the source address is not aligned, try to align it. */ - off = (unsigned long)ss->sge.vaddr & (sizeof(u32) - 1); - if (off) { - u32 *addr = (u32 *)((unsigned long)ss->sge.vaddr & - ~(sizeof(u32) - 1)); - u32 v = get_upper_bits(*addr, off * BITS_PER_BYTE); - u32 y; - - y = sizeof(u32) - off; - if (len > y) - len = y; - if (len + extra >= sizeof(u32)) { - data |= set_upper_bits(v, extra * - BITS_PER_BYTE); - len = sizeof(u32) - extra; - if (len == length) { - last = data; - break; - } - __raw_writel(data, piobuf); - piobuf++; - extra = 0; - data = 0; - } else { - /* Clear unused upper bytes */ - data |= clear_upper_bytes(v, len, extra); - if (len == length) { - last = data; - break; - } - extra += len; - } - } else if (extra) { - /* Source address is aligned. */ - u32 *addr = (u32 *) ss->sge.vaddr; - int shift = extra * BITS_PER_BYTE; - int ushift = 32 - shift; - u32 l = len; - - while (l >= sizeof(u32)) { - u32 v = *addr; - - data |= set_upper_bits(v, shift); - __raw_writel(data, piobuf); - data = get_upper_bits(v, ushift); - piobuf++; - addr++; - l -= sizeof(u32); - } - /* - * We still have 'extra' number of bytes leftover. - */ - if (l) { - u32 v = *addr; - - if (l + extra >= sizeof(u32)) { - data |= set_upper_bits(v, shift); - len -= l + extra - sizeof(u32); - if (len == length) { - last = data; - break; - } - __raw_writel(data, piobuf); - piobuf++; - extra = 0; - data = 0; - } else { - /* Clear unused upper bytes */ - data |= clear_upper_bytes(v, l, - extra); - if (len == length) { - last = data; - break; - } - extra += l; - } - } else if (len == length) { - last = data; - break; - } - } else if (len == length) { - u32 w; - - /* - * Need to round up for the last dword in the - * packet. - */ - w = (len + 3) >> 2; - __iowrite32_copy(piobuf, ss->sge.vaddr, w - 1); - piobuf += w - 1; - last = ((u32 *) ss->sge.vaddr)[w - 1]; - break; - } else { - u32 w = len >> 2; - - __iowrite32_copy(piobuf, ss->sge.vaddr, w); - piobuf += w; - - extra = len & (sizeof(u32) - 1); - if (extra) { - u32 v = ((u32 *) ss->sge.vaddr)[w]; - - /* Clear unused upper bytes */ - data = clear_upper_bytes(v, extra, 0); - } - } - update_sge(ss, len); - length -= len; - } - /* Update address before sending packet. */ - update_sge(ss, length); - if (flush_wc) { - /* must flush early everything before trigger word */ - ipath_flush_wc(); - __raw_writel(last, piobuf); - /* be sure trigger word is written */ - ipath_flush_wc(); - } else - __raw_writel(last, piobuf); -} - -/* - * Convert IB rate to delay multiplier. - */ -unsigned ipath_ib_rate_to_mult(enum ib_rate rate) -{ - switch (rate) { - case IB_RATE_2_5_GBPS: return 8; - case IB_RATE_5_GBPS: return 4; - case IB_RATE_10_GBPS: return 2; - case IB_RATE_20_GBPS: return 1; - default: return 0; - } -} - -/* - * Convert delay multiplier to IB rate - */ -static enum ib_rate ipath_mult_to_ib_rate(unsigned mult) -{ - switch (mult) { - case 8: return IB_RATE_2_5_GBPS; - case 4: return IB_RATE_5_GBPS; - case 2: return IB_RATE_10_GBPS; - case 1: return IB_RATE_20_GBPS; - default: return IB_RATE_PORT_CURRENT; - } -} - -static inline struct ipath_verbs_txreq *get_txreq(struct ipath_ibdev *dev) -{ - struct ipath_verbs_txreq *tx = NULL; - unsigned long flags; - - spin_lock_irqsave(&dev->pending_lock, flags); - if (!list_empty(&dev->txreq_free)) { - struct list_head *l = dev->txreq_free.next; - - list_del(l); - tx = list_entry(l, struct ipath_verbs_txreq, txreq.list); - } - spin_unlock_irqrestore(&dev->pending_lock, flags); - return tx; -} - -static inline void put_txreq(struct ipath_ibdev *dev, - struct ipath_verbs_txreq *tx) -{ - unsigned long flags; - - spin_lock_irqsave(&dev->pending_lock, flags); - list_add(&tx->txreq.list, &dev->txreq_free); - spin_unlock_irqrestore(&dev->pending_lock, flags); -} - -static void sdma_complete(void *cookie, int status) -{ - struct ipath_verbs_txreq *tx = cookie; - struct ipath_qp *qp = tx->qp; - struct ipath_ibdev *dev = to_idev(qp->ibqp.device); - unsigned long flags; - enum ib_wc_status ibs = status == IPATH_SDMA_TXREQ_S_OK ? - IB_WC_SUCCESS : IB_WC_WR_FLUSH_ERR; - - if (atomic_dec_and_test(&qp->s_dma_busy)) { - spin_lock_irqsave(&qp->s_lock, flags); - if (tx->wqe) - ipath_send_complete(qp, tx->wqe, ibs); - if ((ib_ipath_state_ops[qp->state] & IPATH_FLUSH_SEND && - qp->s_last != qp->s_head) || - (qp->s_flags & IPATH_S_WAIT_DMA)) - ipath_schedule_send(qp); - spin_unlock_irqrestore(&qp->s_lock, flags); - wake_up(&qp->wait_dma); - } else if (tx->wqe) { - spin_lock_irqsave(&qp->s_lock, flags); - ipath_send_complete(qp, tx->wqe, ibs); - spin_unlock_irqrestore(&qp->s_lock, flags); - } - - if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_FREEBUF) - kfree(tx->txreq.map_addr); - put_txreq(dev, tx); - - if (atomic_dec_and_test(&qp->refcount)) - wake_up(&qp->wait); -} - -static void decrement_dma_busy(struct ipath_qp *qp) -{ - unsigned long flags; - - if (atomic_dec_and_test(&qp->s_dma_busy)) { - spin_lock_irqsave(&qp->s_lock, flags); - if ((ib_ipath_state_ops[qp->state] & IPATH_FLUSH_SEND && - qp->s_last != qp->s_head) || - (qp->s_flags & IPATH_S_WAIT_DMA)) - ipath_schedule_send(qp); - spin_unlock_irqrestore(&qp->s_lock, flags); - wake_up(&qp->wait_dma); - } -} - -/* - * Compute the number of clock cycles of delay before sending the next packet. - * The multipliers reflect the number of clocks for the fastest rate so - * one tick at 4xDDR is 8 ticks at 1xSDR. - * If the destination port will take longer to receive a packet than - * the outgoing link can send it, we need to delay sending the next packet - * by the difference in time it takes the receiver to receive and the sender - * to send this packet. - * Note that this delay is always correct for UC and RC but not always - * optimal for UD. For UD, the destination HCA can be different for each - * packet, in which case, we could send packets to a different destination - * while "waiting" for the delay. The overhead for doing this without - * HW support is more than just paying the cost of delaying some packets - * unnecessarily. - */ -static inline unsigned ipath_pkt_delay(u32 plen, u8 snd_mult, u8 rcv_mult) -{ - return (rcv_mult > snd_mult) ? - (plen * (rcv_mult - snd_mult) + 1) >> 1 : 0; -} - -static int ipath_verbs_send_dma(struct ipath_qp *qp, - struct ipath_ib_header *hdr, u32 hdrwords, - struct ipath_sge_state *ss, u32 len, - u32 plen, u32 dwords) -{ - struct ipath_ibdev *dev = to_idev(qp->ibqp.device); - struct ipath_devdata *dd = dev->dd; - struct ipath_verbs_txreq *tx; - u32 *piobuf; - u32 control; - u32 ndesc; - int ret; - - tx = qp->s_tx; - if (tx) { - qp->s_tx = NULL; - /* resend previously constructed packet */ - atomic_inc(&qp->s_dma_busy); - ret = ipath_sdma_verbs_send(dd, tx->ss, tx->len, tx); - if (ret) { - qp->s_tx = tx; - decrement_dma_busy(qp); - } - goto bail; - } - - tx = get_txreq(dev); - if (!tx) { - ret = -EBUSY; - goto bail; - } - - /* - * Get the saved delay count we computed for the previous packet - * and save the delay count for this packet to be used next time - * we get here. - */ - control = qp->s_pkt_delay; - qp->s_pkt_delay = ipath_pkt_delay(plen, dd->delay_mult, qp->s_dmult); - - tx->qp = qp; - atomic_inc(&qp->refcount); - tx->wqe = qp->s_wqe; - tx->txreq.callback = sdma_complete; - tx->txreq.callback_cookie = tx; - tx->txreq.flags = IPATH_SDMA_TXREQ_F_HEADTOHOST | - IPATH_SDMA_TXREQ_F_INTREQ | IPATH_SDMA_TXREQ_F_FREEDESC; - if (plen + 1 >= IPATH_SMALLBUF_DWORDS) - tx->txreq.flags |= IPATH_SDMA_TXREQ_F_USELARGEBUF; - - /* VL15 packets bypass credit check */ - if ((be16_to_cpu(hdr->lrh[0]) >> 12) == 15) { - control |= 1ULL << 31; - tx->txreq.flags |= IPATH_SDMA_TXREQ_F_VL15; - } - - if (len) { - /* - * Don't try to DMA if it takes more descriptors than - * the queue holds. - */ - ndesc = ipath_count_sge(ss, len); - if (ndesc >= dd->ipath_sdma_descq_cnt) - ndesc = 0; - } else - ndesc = 1; - if (ndesc) { - tx->hdr.pbc[0] = cpu_to_le32(plen); - tx->hdr.pbc[1] = cpu_to_le32(control); - memcpy(&tx->hdr.hdr, hdr, hdrwords << 2); - tx->txreq.sg_count = ndesc; - tx->map_len = (hdrwords + 2) << 2; - tx->txreq.map_addr = &tx->hdr; - atomic_inc(&qp->s_dma_busy); - ret = ipath_sdma_verbs_send(dd, ss, dwords, tx); - if (ret) { - /* save ss and length in dwords */ - tx->ss = ss; - tx->len = dwords; - qp->s_tx = tx; - decrement_dma_busy(qp); - } - goto bail; - } - - /* Allocate a buffer and copy the header and payload to it. */ - tx->map_len = (plen + 1) << 2; - piobuf = kmalloc(tx->map_len, GFP_ATOMIC); - if (unlikely(piobuf == NULL)) { - ret = -EBUSY; - goto err_tx; - } - tx->txreq.map_addr = piobuf; - tx->txreq.flags |= IPATH_SDMA_TXREQ_F_FREEBUF; - tx->txreq.sg_count = 1; - - *piobuf++ = (__force u32) cpu_to_le32(plen); - *piobuf++ = (__force u32) cpu_to_le32(control); - memcpy(piobuf, hdr, hdrwords << 2); - ipath_copy_from_sge(piobuf + hdrwords, ss, len); - - atomic_inc(&qp->s_dma_busy); - ret = ipath_sdma_verbs_send(dd, NULL, 0, tx); - /* - * If we couldn't queue the DMA request, save the info - * and try again later rather than destroying the - * buffer and undoing the side effects of the copy. - */ - if (ret) { - tx->ss = NULL; - tx->len = 0; - qp->s_tx = tx; - decrement_dma_busy(qp); - } - dev->n_unaligned++; - goto bail; - -err_tx: - if (atomic_dec_and_test(&qp->refcount)) - wake_up(&qp->wait); - put_txreq(dev, tx); -bail: - return ret; -} - -static int ipath_verbs_send_pio(struct ipath_qp *qp, - struct ipath_ib_header *ibhdr, u32 hdrwords, - struct ipath_sge_state *ss, u32 len, - u32 plen, u32 dwords) -{ - struct ipath_devdata *dd = to_idev(qp->ibqp.device)->dd; - u32 *hdr = (u32 *) ibhdr; - u32 __iomem *piobuf; - unsigned flush_wc; - u32 control; - int ret; - unsigned long flags; - - piobuf = ipath_getpiobuf(dd, plen, NULL); - if (unlikely(piobuf == NULL)) { - ret = -EBUSY; - goto bail; - } - - /* - * Get the saved delay count we computed for the previous packet - * and save the delay count for this packet to be used next time - * we get here. - */ - control = qp->s_pkt_delay; - qp->s_pkt_delay = ipath_pkt_delay(plen, dd->delay_mult, qp->s_dmult); - - /* VL15 packets bypass credit check */ - if ((be16_to_cpu(ibhdr->lrh[0]) >> 12) == 15) - control |= 1ULL << 31; - - /* - * Write the length to the control qword plus any needed flags. - * We have to flush after the PBC for correctness on some cpus - * or WC buffer can be written out of order. - */ - writeq(((u64) control << 32) | plen, piobuf); - piobuf += 2; - - flush_wc = dd->ipath_flags & IPATH_PIO_FLUSH_WC; - if (len == 0) { - /* - * If there is just the header portion, must flush before - * writing last word of header for correctness, and after - * the last header word (trigger word). - */ - if (flush_wc) { - ipath_flush_wc(); - __iowrite32_copy(piobuf, hdr, hdrwords - 1); - ipath_flush_wc(); - __raw_writel(hdr[hdrwords - 1], piobuf + hdrwords - 1); - ipath_flush_wc(); - } else - __iowrite32_copy(piobuf, hdr, hdrwords); - goto done; - } - - if (flush_wc) - ipath_flush_wc(); - __iowrite32_copy(piobuf, hdr, hdrwords); - piobuf += hdrwords; - - /* The common case is aligned and contained in one segment. */ - if (likely(ss->num_sge == 1 && len <= ss->sge.length && - !((unsigned long)ss->sge.vaddr & (sizeof(u32) - 1)))) { - u32 *addr = (u32 *) ss->sge.vaddr; - - /* Update address before sending packet. */ - update_sge(ss, len); - if (flush_wc) { - __iowrite32_copy(piobuf, addr, dwords - 1); - /* must flush early everything before trigger word */ - ipath_flush_wc(); - __raw_writel(addr[dwords - 1], piobuf + dwords - 1); - /* be sure trigger word is written */ - ipath_flush_wc(); - } else - __iowrite32_copy(piobuf, addr, dwords); - goto done; - } - copy_io(piobuf, ss, len, flush_wc); -done: - if (qp->s_wqe) { - spin_lock_irqsave(&qp->s_lock, flags); - ipath_send_complete(qp, qp->s_wqe, IB_WC_SUCCESS); - spin_unlock_irqrestore(&qp->s_lock, flags); - } - ret = 0; -bail: - return ret; -} - -/** - * ipath_verbs_send - send a packet - * @qp: the QP to send on - * @hdr: the packet header - * @hdrwords: the number of 32-bit words in the header - * @ss: the SGE to send - * @len: the length of the packet in bytes - */ -int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr, - u32 hdrwords, struct ipath_sge_state *ss, u32 len) -{ - struct ipath_devdata *dd = to_idev(qp->ibqp.device)->dd; - u32 plen; - int ret; - u32 dwords = (len + 3) >> 2; - - /* - * Calculate the send buffer trigger address. - * The +1 counts for the pbc control dword following the pbc length. - */ - plen = hdrwords + dwords + 1; - - /* - * VL15 packets (IB_QPT_SMI) will always use PIO, so we - * can defer SDMA restart until link goes ACTIVE without - * worrying about just how we got there. - */ - if (qp->ibqp.qp_type == IB_QPT_SMI || - !(dd->ipath_flags & IPATH_HAS_SEND_DMA)) - ret = ipath_verbs_send_pio(qp, hdr, hdrwords, ss, len, - plen, dwords); - else - ret = ipath_verbs_send_dma(qp, hdr, hdrwords, ss, len, - plen, dwords); - - return ret; -} - -int ipath_snapshot_counters(struct ipath_devdata *dd, u64 *swords, - u64 *rwords, u64 *spkts, u64 *rpkts, - u64 *xmit_wait) -{ - int ret; - - if (!(dd->ipath_flags & IPATH_INITTED)) { - /* no hardware, freeze, etc. */ - ret = -EINVAL; - goto bail; - } - *swords = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt); - *rwords = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt); - *spkts = ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt); - *rpkts = ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt); - *xmit_wait = ipath_snap_cntr(dd, dd->ipath_cregs->cr_sendstallcnt); - - ret = 0; - -bail: - return ret; -} - -/** - * ipath_get_counters - get various chip counters - * @dd: the infinipath device - * @cntrs: counters are placed here - * - * Return the counters needed by recv_pma_get_portcounters(). - */ -int ipath_get_counters(struct ipath_devdata *dd, - struct ipath_verbs_counters *cntrs) -{ - struct ipath_cregs const *crp = dd->ipath_cregs; - int ret; - - if (!(dd->ipath_flags & IPATH_INITTED)) { - /* no hardware, freeze, etc. */ - ret = -EINVAL; - goto bail; - } - cntrs->symbol_error_counter = - ipath_snap_cntr(dd, crp->cr_ibsymbolerrcnt); - cntrs->link_error_recovery_counter = - ipath_snap_cntr(dd, crp->cr_iblinkerrrecovcnt); - /* - * The link downed counter counts when the other side downs the - * connection. We add in the number of times we downed the link - * due to local link integrity errors to compensate. - */ - cntrs->link_downed_counter = - ipath_snap_cntr(dd, crp->cr_iblinkdowncnt); - cntrs->port_rcv_errors = - ipath_snap_cntr(dd, crp->cr_rxdroppktcnt) + - ipath_snap_cntr(dd, crp->cr_rcvovflcnt) + - ipath_snap_cntr(dd, crp->cr_portovflcnt) + - ipath_snap_cntr(dd, crp->cr_err_rlencnt) + - ipath_snap_cntr(dd, crp->cr_invalidrlencnt) + - ipath_snap_cntr(dd, crp->cr_errlinkcnt) + - ipath_snap_cntr(dd, crp->cr_erricrccnt) + - ipath_snap_cntr(dd, crp->cr_errvcrccnt) + - ipath_snap_cntr(dd, crp->cr_errlpcrccnt) + - ipath_snap_cntr(dd, crp->cr_badformatcnt) + - dd->ipath_rxfc_unsupvl_errs; - if (crp->cr_rxotherlocalphyerrcnt) - cntrs->port_rcv_errors += - ipath_snap_cntr(dd, crp->cr_rxotherlocalphyerrcnt); - if (crp->cr_rxvlerrcnt) - cntrs->port_rcv_errors += - ipath_snap_cntr(dd, crp->cr_rxvlerrcnt); - cntrs->port_rcv_remphys_errors = - ipath_snap_cntr(dd, crp->cr_rcvebpcnt); - cntrs->port_xmit_discards = ipath_snap_cntr(dd, crp->cr_unsupvlcnt); - cntrs->port_xmit_data = ipath_snap_cntr(dd, crp->cr_wordsendcnt); - cntrs->port_rcv_data = ipath_snap_cntr(dd, crp->cr_wordrcvcnt); - cntrs->port_xmit_packets = ipath_snap_cntr(dd, crp->cr_pktsendcnt); - cntrs->port_rcv_packets = ipath_snap_cntr(dd, crp->cr_pktrcvcnt); - cntrs->local_link_integrity_errors = - crp->cr_locallinkintegrityerrcnt ? - ipath_snap_cntr(dd, crp->cr_locallinkintegrityerrcnt) : - ((dd->ipath_flags & IPATH_GPIO_ERRINTRS) ? - dd->ipath_lli_errs : dd->ipath_lli_errors); - cntrs->excessive_buffer_overrun_errors = - crp->cr_excessbufferovflcnt ? - ipath_snap_cntr(dd, crp->cr_excessbufferovflcnt) : - dd->ipath_overrun_thresh_errs; - cntrs->vl15_dropped = crp->cr_vl15droppedpktcnt ? - ipath_snap_cntr(dd, crp->cr_vl15droppedpktcnt) : 0; - - ret = 0; - -bail: - return ret; -} - -/** - * ipath_ib_piobufavail - callback when a PIO buffer is available - * @arg: the device pointer - * - * This is called from ipath_intr() at interrupt level when a PIO buffer is - * available after ipath_verbs_send() returned an error that no buffers were - * available. Return 1 if we consumed all the PIO buffers and we still have - * QPs waiting for buffers (for now, just restart the send tasklet and - * return zero). - */ -int ipath_ib_piobufavail(struct ipath_ibdev *dev) -{ - struct list_head *list; - struct ipath_qp *qplist; - struct ipath_qp *qp; - unsigned long flags; - - if (dev == NULL) - goto bail; - - list = &dev->piowait; - qplist = NULL; - - spin_lock_irqsave(&dev->pending_lock, flags); - while (!list_empty(list)) { - qp = list_entry(list->next, struct ipath_qp, piowait); - list_del_init(&qp->piowait); - qp->pio_next = qplist; - qplist = qp; - atomic_inc(&qp->refcount); - } - spin_unlock_irqrestore(&dev->pending_lock, flags); - - while (qplist != NULL) { - qp = qplist; - qplist = qp->pio_next; - - spin_lock_irqsave(&qp->s_lock, flags); - if (ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK) - ipath_schedule_send(qp); - spin_unlock_irqrestore(&qp->s_lock, flags); - - /* Notify ipath_destroy_qp() if it is waiting. */ - if (atomic_dec_and_test(&qp->refcount)) - wake_up(&qp->wait); - } - -bail: - return 0; -} - -static int ipath_query_device(struct ib_device *ibdev, struct ib_device_attr *props, - struct ib_udata *uhw) -{ - struct ipath_ibdev *dev = to_idev(ibdev); - - if (uhw->inlen || uhw->outlen) - return -EINVAL; - - memset(props, 0, sizeof(*props)); - - props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR | - IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT | - IB_DEVICE_SYS_IMAGE_GUID | IB_DEVICE_RC_RNR_NAK_GEN | - IB_DEVICE_PORT_ACTIVE_EVENT | IB_DEVICE_SRQ_RESIZE; - props->page_size_cap = PAGE_SIZE; - props->vendor_id = - IPATH_SRC_OUI_1 << 16 | IPATH_SRC_OUI_2 << 8 | IPATH_SRC_OUI_3; - props->vendor_part_id = dev->dd->ipath_deviceid; - props->hw_ver = dev->dd->ipath_pcirev; - - props->sys_image_guid = dev->sys_image_guid; - - props->max_mr_size = ~0ull; - props->max_qp = ib_ipath_max_qps; - props->max_qp_wr = ib_ipath_max_qp_wrs; - props->max_sge = ib_ipath_max_sges; - props->max_sge_rd = ib_ipath_max_sges; - props->max_cq = ib_ipath_max_cqs; - props->max_ah = ib_ipath_max_ahs; - props->max_cqe = ib_ipath_max_cqes; - props->max_mr = dev->lk_table.max; - props->max_fmr = dev->lk_table.max; - props->max_map_per_fmr = 32767; - props->max_pd = ib_ipath_max_pds; - props->max_qp_rd_atom = IPATH_MAX_RDMA_ATOMIC; - props->max_qp_init_rd_atom = 255; - /* props->max_res_rd_atom */ - props->max_srq = ib_ipath_max_srqs; - props->max_srq_wr = ib_ipath_max_srq_wrs; - props->max_srq_sge = ib_ipath_max_srq_sges; - /* props->local_ca_ack_delay */ - props->atomic_cap = IB_ATOMIC_GLOB; - props->max_pkeys = ipath_get_npkeys(dev->dd); - props->max_mcast_grp = ib_ipath_max_mcast_grps; - props->max_mcast_qp_attach = ib_ipath_max_mcast_qp_attached; - props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * - props->max_mcast_grp; - - return 0; -} - -const u8 ipath_cvt_physportstate[32] = { - [INFINIPATH_IBCS_LT_STATE_DISABLED] = IB_PHYSPORTSTATE_DISABLED, - [INFINIPATH_IBCS_LT_STATE_LINKUP] = IB_PHYSPORTSTATE_LINKUP, - [INFINIPATH_IBCS_LT_STATE_POLLACTIVE] = IB_PHYSPORTSTATE_POLL, - [INFINIPATH_IBCS_LT_STATE_POLLQUIET] = IB_PHYSPORTSTATE_POLL, - [INFINIPATH_IBCS_LT_STATE_SLEEPDELAY] = IB_PHYSPORTSTATE_SLEEP, - [INFINIPATH_IBCS_LT_STATE_SLEEPQUIET] = IB_PHYSPORTSTATE_SLEEP, - [INFINIPATH_IBCS_LT_STATE_CFGDEBOUNCE] = - IB_PHYSPORTSTATE_CFG_TRAIN, - [INFINIPATH_IBCS_LT_STATE_CFGRCVFCFG] = - IB_PHYSPORTSTATE_CFG_TRAIN, - [INFINIPATH_IBCS_LT_STATE_CFGWAITRMT] = - IB_PHYSPORTSTATE_CFG_TRAIN, - [INFINIPATH_IBCS_LT_STATE_CFGIDLE] = IB_PHYSPORTSTATE_CFG_TRAIN, - [INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN] = - IB_PHYSPORTSTATE_LINK_ERR_RECOVER, - [INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT] = - IB_PHYSPORTSTATE_LINK_ERR_RECOVER, - [INFINIPATH_IBCS_LT_STATE_RECOVERIDLE] = - IB_PHYSPORTSTATE_LINK_ERR_RECOVER, - [0x10] = IB_PHYSPORTSTATE_CFG_TRAIN, - [0x11] = IB_PHYSPORTSTATE_CFG_TRAIN, - [0x12] = IB_PHYSPORTSTATE_CFG_TRAIN, - [0x13] = IB_PHYSPORTSTATE_CFG_TRAIN, - [0x14] = IB_PHYSPORTSTATE_CFG_TRAIN, - [0x15] = IB_PHYSPORTSTATE_CFG_TRAIN, - [0x16] = IB_PHYSPORTSTATE_CFG_TRAIN, - [0x17] = IB_PHYSPORTSTATE_CFG_TRAIN -}; - -u32 ipath_get_cr_errpkey(struct ipath_devdata *dd) -{ - return ipath_read_creg32(dd, dd->ipath_cregs->cr_errpkey); -} - -static int ipath_query_port(struct ib_device *ibdev, - u8 port, struct ib_port_attr *props) -{ - struct ipath_ibdev *dev = to_idev(ibdev); - struct ipath_devdata *dd = dev->dd; - enum ib_mtu mtu; - u16 lid = dd->ipath_lid; - u64 ibcstat; - - memset(props, 0, sizeof(*props)); - props->lid = lid ? lid : be16_to_cpu(IB_LID_PERMISSIVE); - props->lmc = dd->ipath_lmc; - props->sm_lid = dev->sm_lid; - props->sm_sl = dev->sm_sl; - ibcstat = dd->ipath_lastibcstat; - /* map LinkState to IB portinfo values. */ - props->state = ipath_ib_linkstate(dd, ibcstat) + 1; - - /* See phys_state_show() */ - props->phys_state = /* MEA: assumes shift == 0 */ - ipath_cvt_physportstate[dd->ipath_lastibcstat & - dd->ibcs_lts_mask]; - props->port_cap_flags = dev->port_cap_flags; - props->gid_tbl_len = 1; - props->max_msg_sz = 0x80000000; - props->pkey_tbl_len = ipath_get_npkeys(dd); - props->bad_pkey_cntr = ipath_get_cr_errpkey(dd) - - dev->z_pkey_violations; - props->qkey_viol_cntr = dev->qkey_violations; - props->active_width = dd->ipath_link_width_active; - /* See rate_show() */ - props->active_speed = dd->ipath_link_speed_active; - props->max_vl_num = 1; /* VLCap = VL0 */ - props->init_type_reply = 0; - - props->max_mtu = ipath_mtu4096 ? IB_MTU_4096 : IB_MTU_2048; - switch (dd->ipath_ibmtu) { - case 4096: - mtu = IB_MTU_4096; - break; - case 2048: - mtu = IB_MTU_2048; - break; - case 1024: - mtu = IB_MTU_1024; - break; - case 512: - mtu = IB_MTU_512; - break; - case 256: - mtu = IB_MTU_256; - break; - default: - mtu = IB_MTU_2048; - } - props->active_mtu = mtu; - props->subnet_timeout = dev->subnet_timeout; - - return 0; -} - -static int ipath_modify_device(struct ib_device *device, - int device_modify_mask, - struct ib_device_modify *device_modify) -{ - int ret; - - if (device_modify_mask & ~(IB_DEVICE_MODIFY_SYS_IMAGE_GUID | - IB_DEVICE_MODIFY_NODE_DESC)) { - ret = -EOPNOTSUPP; - goto bail; - } - - if (device_modify_mask & IB_DEVICE_MODIFY_NODE_DESC) - memcpy(device->node_desc, device_modify->node_desc, 64); - - if (device_modify_mask & IB_DEVICE_MODIFY_SYS_IMAGE_GUID) - to_idev(device)->sys_image_guid = - cpu_to_be64(device_modify->sys_image_guid); - - ret = 0; - -bail: - return ret; -} - -static int ipath_modify_port(struct ib_device *ibdev, - u8 port, int port_modify_mask, - struct ib_port_modify *props) -{ - struct ipath_ibdev *dev = to_idev(ibdev); - - dev->port_cap_flags |= props->set_port_cap_mask; - dev->port_cap_flags &= ~props->clr_port_cap_mask; - if (port_modify_mask & IB_PORT_SHUTDOWN) - ipath_set_linkstate(dev->dd, IPATH_IB_LINKDOWN); - if (port_modify_mask & IB_PORT_RESET_QKEY_CNTR) - dev->qkey_violations = 0; - return 0; -} - -static int ipath_query_gid(struct ib_device *ibdev, u8 port, - int index, union ib_gid *gid) -{ - struct ipath_ibdev *dev = to_idev(ibdev); - int ret; - - if (index >= 1) { - ret = -EINVAL; - goto bail; - } - gid->global.subnet_prefix = dev->gid_prefix; - gid->global.interface_id = dev->dd->ipath_guid; - - ret = 0; - -bail: - return ret; -} - -static struct ib_pd *ipath_alloc_pd(struct ib_device *ibdev, - struct ib_ucontext *context, - struct ib_udata *udata) -{ - struct ipath_ibdev *dev = to_idev(ibdev); - struct ipath_pd *pd; - struct ib_pd *ret; - - /* - * This is actually totally arbitrary. Some correctness tests - * assume there's a maximum number of PDs that can be allocated. - * We don't actually have this limit, but we fail the test if - * we allow allocations of more than we report for this value. - */ - - pd = kmalloc(sizeof *pd, GFP_KERNEL); - if (!pd) { - ret = ERR_PTR(-ENOMEM); - goto bail; - } - - spin_lock(&dev->n_pds_lock); - if (dev->n_pds_allocated == ib_ipath_max_pds) { - spin_unlock(&dev->n_pds_lock); - kfree(pd); - ret = ERR_PTR(-ENOMEM); - goto bail; - } - - dev->n_pds_allocated++; - spin_unlock(&dev->n_pds_lock); - - /* ib_alloc_pd() will initialize pd->ibpd. */ - pd->user = udata != NULL; - - ret = &pd->ibpd; - -bail: - return ret; -} - -static int ipath_dealloc_pd(struct ib_pd *ibpd) -{ - struct ipath_pd *pd = to_ipd(ibpd); - struct ipath_ibdev *dev = to_idev(ibpd->device); - - spin_lock(&dev->n_pds_lock); - dev->n_pds_allocated--; - spin_unlock(&dev->n_pds_lock); - - kfree(pd); - - return 0; -} - -/** - * ipath_create_ah - create an address handle - * @pd: the protection domain - * @ah_attr: the attributes of the AH - * - * This may be called from interrupt context. - */ -static struct ib_ah *ipath_create_ah(struct ib_pd *pd, - struct ib_ah_attr *ah_attr) -{ - struct ipath_ah *ah; - struct ib_ah *ret; - struct ipath_ibdev *dev = to_idev(pd->device); - unsigned long flags; - - /* A multicast address requires a GRH (see ch. 8.4.1). */ - if (ah_attr->dlid >= IPATH_MULTICAST_LID_BASE && - ah_attr->dlid != IPATH_PERMISSIVE_LID && - !(ah_attr->ah_flags & IB_AH_GRH)) { - ret = ERR_PTR(-EINVAL); - goto bail; - } - - if (ah_attr->dlid == 0) { - ret = ERR_PTR(-EINVAL); - goto bail; - } - - if (ah_attr->port_num < 1 || - ah_attr->port_num > pd->device->phys_port_cnt) { - ret = ERR_PTR(-EINVAL); - goto bail; - } - - ah = kmalloc(sizeof *ah, GFP_ATOMIC); - if (!ah) { - ret = ERR_PTR(-ENOMEM); - goto bail; - } - - spin_lock_irqsave(&dev->n_ahs_lock, flags); - if (dev->n_ahs_allocated == ib_ipath_max_ahs) { - spin_unlock_irqrestore(&dev->n_ahs_lock, flags); - kfree(ah); - ret = ERR_PTR(-ENOMEM); - goto bail; - } - - dev->n_ahs_allocated++; - spin_unlock_irqrestore(&dev->n_ahs_lock, flags); - - /* ib_create_ah() will initialize ah->ibah. */ - ah->attr = *ah_attr; - ah->attr.static_rate = ipath_ib_rate_to_mult(ah_attr->static_rate); - - ret = &ah->ibah; - -bail: - return ret; -} - -/** - * ipath_destroy_ah - destroy an address handle - * @ibah: the AH to destroy - * - * This may be called from interrupt context. - */ -static int ipath_destroy_ah(struct ib_ah *ibah) -{ - struct ipath_ibdev *dev = to_idev(ibah->device); - struct ipath_ah *ah = to_iah(ibah); - unsigned long flags; - - spin_lock_irqsave(&dev->n_ahs_lock, flags); - dev->n_ahs_allocated--; - spin_unlock_irqrestore(&dev->n_ahs_lock, flags); - - kfree(ah); - - return 0; -} - -static int ipath_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr) -{ - struct ipath_ah *ah = to_iah(ibah); - - *ah_attr = ah->attr; - ah_attr->static_rate = ipath_mult_to_ib_rate(ah->attr.static_rate); - - return 0; -} - -/** - * ipath_get_npkeys - return the size of the PKEY table for port 0 - * @dd: the infinipath device - */ -unsigned ipath_get_npkeys(struct ipath_devdata *dd) -{ - return ARRAY_SIZE(dd->ipath_pd[0]->port_pkeys); -} - -/** - * ipath_get_pkey - return the indexed PKEY from the port PKEY table - * @dd: the infinipath device - * @index: the PKEY index - */ -unsigned ipath_get_pkey(struct ipath_devdata *dd, unsigned index) -{ - unsigned ret; - - /* always a kernel port, no locking needed */ - if (index >= ARRAY_SIZE(dd->ipath_pd[0]->port_pkeys)) - ret = 0; - else - ret = dd->ipath_pd[0]->port_pkeys[index]; - - return ret; -} - -static int ipath_query_pkey(struct ib_device *ibdev, u8 port, u16 index, - u16 *pkey) -{ - struct ipath_ibdev *dev = to_idev(ibdev); - int ret; - - if (index >= ipath_get_npkeys(dev->dd)) { - ret = -EINVAL; - goto bail; - } - - *pkey = ipath_get_pkey(dev->dd, index); - ret = 0; - -bail: - return ret; -} - -/** - * ipath_alloc_ucontext - allocate a ucontest - * @ibdev: the infiniband device - * @udata: not used by the InfiniPath driver - */ - -static struct ib_ucontext *ipath_alloc_ucontext(struct ib_device *ibdev, - struct ib_udata *udata) -{ - struct ipath_ucontext *context; - struct ib_ucontext *ret; - - context = kmalloc(sizeof *context, GFP_KERNEL); - if (!context) { - ret = ERR_PTR(-ENOMEM); - goto bail; - } - - ret = &context->ibucontext; - -bail: - return ret; -} - -static int ipath_dealloc_ucontext(struct ib_ucontext *context) -{ - kfree(to_iucontext(context)); - return 0; -} - -static int ipath_verbs_register_sysfs(struct ib_device *dev); - -static void __verbs_timer(unsigned long arg) -{ - struct ipath_devdata *dd = (struct ipath_devdata *) arg; - - /* Handle verbs layer timeouts. */ - ipath_ib_timer(dd->verbs_dev); - - mod_timer(&dd->verbs_timer, jiffies + 1); -} - -static int enable_timer(struct ipath_devdata *dd) -{ - /* - * Early chips had a design flaw where the chip and kernel idea - * of the tail register don't always agree, and therefore we won't - * get an interrupt on the next packet received. - * If the board supports per packet receive interrupts, use it. - * Otherwise, the timer function periodically checks for packets - * to cover this case. - * Either way, the timer is needed for verbs layer related - * processing. - */ - if (dd->ipath_flags & IPATH_GPIO_INTR) { - ipath_write_kreg(dd, dd->ipath_kregs->kr_debugportselect, - 0x2074076542310ULL); - /* Enable GPIO bit 2 interrupt */ - dd->ipath_gpio_mask |= (u64) (1 << IPATH_GPIO_PORT0_BIT); - ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask, - dd->ipath_gpio_mask); - } - - setup_timer(&dd->verbs_timer, __verbs_timer, (unsigned long)dd); - - dd->verbs_timer.expires = jiffies + 1; - add_timer(&dd->verbs_timer); - - return 0; -} - -static int disable_timer(struct ipath_devdata *dd) -{ - /* Disable GPIO bit 2 interrupt */ - if (dd->ipath_flags & IPATH_GPIO_INTR) { - /* Disable GPIO bit 2 interrupt */ - dd->ipath_gpio_mask &= ~((u64) (1 << IPATH_GPIO_PORT0_BIT)); - ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask, - dd->ipath_gpio_mask); - /* - * We might want to undo changes to debugportselect, - * but how? - */ - } - - del_timer_sync(&dd->verbs_timer); - - return 0; -} - -static int ipath_port_immutable(struct ib_device *ibdev, u8 port_num, - struct ib_port_immutable *immutable) -{ - struct ib_port_attr attr; - int err; - - err = ipath_query_port(ibdev, port_num, &attr); - if (err) - return err; - - immutable->pkey_tbl_len = attr.pkey_tbl_len; - immutable->gid_tbl_len = attr.gid_tbl_len; - immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB; - immutable->max_mad_size = IB_MGMT_MAD_SIZE; - - return 0; -} - -/** - * ipath_register_ib_device - register our device with the infiniband core - * @dd: the device data structure - * Return the allocated ipath_ibdev pointer or NULL on error. - */ -int ipath_register_ib_device(struct ipath_devdata *dd) -{ - struct ipath_verbs_counters cntrs; - struct ipath_ibdev *idev; - struct ib_device *dev; - struct ipath_verbs_txreq *tx; - unsigned i; - int ret; - - idev = (struct ipath_ibdev *)ib_alloc_device(sizeof *idev); - if (idev == NULL) { - ret = -ENOMEM; - goto bail; - } - - dev = &idev->ibdev; - - if (dd->ipath_sdma_descq_cnt) { - tx = kmalloc_array(dd->ipath_sdma_descq_cnt, sizeof *tx, - GFP_KERNEL); - if (tx == NULL) { - ret = -ENOMEM; - goto err_tx; - } - } else - tx = NULL; - idev->txreq_bufs = tx; - - /* Only need to initialize non-zero fields. */ - spin_lock_init(&idev->n_pds_lock); - spin_lock_init(&idev->n_ahs_lock); - spin_lock_init(&idev->n_cqs_lock); - spin_lock_init(&idev->n_qps_lock); - spin_lock_init(&idev->n_srqs_lock); - spin_lock_init(&idev->n_mcast_grps_lock); - - spin_lock_init(&idev->qp_table.lock); - spin_lock_init(&idev->lk_table.lock); - idev->sm_lid = be16_to_cpu(IB_LID_PERMISSIVE); - /* Set the prefix to the default value (see ch. 4.1.1) */ - idev->gid_prefix = cpu_to_be64(0xfe80000000000000ULL); - - ret = ipath_init_qp_table(idev, ib_ipath_qp_table_size); - if (ret) - goto err_qp; - - /* - * The top ib_ipath_lkey_table_size bits are used to index the - * table. The lower 8 bits can be owned by the user (copied from - * the LKEY). The remaining bits act as a generation number or tag. - */ - idev->lk_table.max = 1 << ib_ipath_lkey_table_size; - idev->lk_table.table = kcalloc(idev->lk_table.max, - sizeof(*idev->lk_table.table), - GFP_KERNEL); - if (idev->lk_table.table == NULL) { - ret = -ENOMEM; - goto err_lk; - } - INIT_LIST_HEAD(&idev->pending_mmaps); - spin_lock_init(&idev->pending_lock); - idev->mmap_offset = PAGE_SIZE; - spin_lock_init(&idev->mmap_offset_lock); - INIT_LIST_HEAD(&idev->pending[0]); - INIT_LIST_HEAD(&idev->pending[1]); - INIT_LIST_HEAD(&idev->pending[2]); - INIT_LIST_HEAD(&idev->piowait); - INIT_LIST_HEAD(&idev->rnrwait); - INIT_LIST_HEAD(&idev->txreq_free); - idev->pending_index = 0; - idev->port_cap_flags = - IB_PORT_SYS_IMAGE_GUID_SUP | IB_PORT_CLIENT_REG_SUP; - if (dd->ipath_flags & IPATH_HAS_LINK_LATENCY) - idev->port_cap_flags |= IB_PORT_LINK_LATENCY_SUP; - idev->pma_counter_select[0] = IB_PMA_PORT_XMIT_DATA; - idev->pma_counter_select[1] = IB_PMA_PORT_RCV_DATA; - idev->pma_counter_select[2] = IB_PMA_PORT_XMIT_PKTS; - idev->pma_counter_select[3] = IB_PMA_PORT_RCV_PKTS; - idev->pma_counter_select[4] = IB_PMA_PORT_XMIT_WAIT; - - /* Snapshot current HW counters to "clear" them. */ - ipath_get_counters(dd, &cntrs); - idev->z_symbol_error_counter = cntrs.symbol_error_counter; - idev->z_link_error_recovery_counter = - cntrs.link_error_recovery_counter; - idev->z_link_downed_counter = cntrs.link_downed_counter; - idev->z_port_rcv_errors = cntrs.port_rcv_errors; - idev->z_port_rcv_remphys_errors = - cntrs.port_rcv_remphys_errors; - idev->z_port_xmit_discards = cntrs.port_xmit_discards; - idev->z_port_xmit_data = cntrs.port_xmit_data; - idev->z_port_rcv_data = cntrs.port_rcv_data; - idev->z_port_xmit_packets = cntrs.port_xmit_packets; - idev->z_port_rcv_packets = cntrs.port_rcv_packets; - idev->z_local_link_integrity_errors = - cntrs.local_link_integrity_errors; - idev->z_excessive_buffer_overrun_errors = - cntrs.excessive_buffer_overrun_errors; - idev->z_vl15_dropped = cntrs.vl15_dropped; - - for (i = 0; i < dd->ipath_sdma_descq_cnt; i++, tx++) - list_add(&tx->txreq.list, &idev->txreq_free); - - /* - * The system image GUID is supposed to be the same for all - * IB HCAs in a single system but since there can be other - * device types in the system, we can't be sure this is unique. - */ - if (!sys_image_guid) - sys_image_guid = dd->ipath_guid; - idev->sys_image_guid = sys_image_guid; - idev->ib_unit = dd->ipath_unit; - idev->dd = dd; - - strlcpy(dev->name, "ipath%d", IB_DEVICE_NAME_MAX); - dev->owner = THIS_MODULE; - dev->node_guid = dd->ipath_guid; - dev->uverbs_abi_ver = IPATH_UVERBS_ABI_VERSION; - dev->uverbs_cmd_mask = - (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | - (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | - (1ull << IB_USER_VERBS_CMD_QUERY_PORT) | - (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | - (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | - (1ull << IB_USER_VERBS_CMD_CREATE_AH) | - (1ull << IB_USER_VERBS_CMD_DESTROY_AH) | - (1ull << IB_USER_VERBS_CMD_QUERY_AH) | - (1ull << IB_USER_VERBS_CMD_REG_MR) | - (1ull << IB_USER_VERBS_CMD_DEREG_MR) | - (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | - (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | - (1ull << IB_USER_VERBS_CMD_RESIZE_CQ) | - (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) | - (1ull << IB_USER_VERBS_CMD_POLL_CQ) | - (1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ) | - (1ull << IB_USER_VERBS_CMD_CREATE_QP) | - (1ull << IB_USER_VERBS_CMD_QUERY_QP) | - (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | - (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | - (1ull << IB_USER_VERBS_CMD_POST_SEND) | - (1ull << IB_USER_VERBS_CMD_POST_RECV) | - (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) | - (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) | - (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) | - (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) | - (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) | - (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ) | - (1ull << IB_USER_VERBS_CMD_POST_SRQ_RECV); - dev->node_type = RDMA_NODE_IB_CA; - dev->phys_port_cnt = 1; - dev->num_comp_vectors = 1; - dev->dma_device = &dd->pcidev->dev; - dev->query_device = ipath_query_device; - dev->modify_device = ipath_modify_device; - dev->query_port = ipath_query_port; - dev->modify_port = ipath_modify_port; - dev->query_pkey = ipath_query_pkey; - dev->query_gid = ipath_query_gid; - dev->alloc_ucontext = ipath_alloc_ucontext; - dev->dealloc_ucontext = ipath_dealloc_ucontext; - dev->alloc_pd = ipath_alloc_pd; - dev->dealloc_pd = ipath_dealloc_pd; - dev->create_ah = ipath_create_ah; - dev->destroy_ah = ipath_destroy_ah; - dev->query_ah = ipath_query_ah; - dev->create_srq = ipath_create_srq; - dev->modify_srq = ipath_modify_srq; - dev->query_srq = ipath_query_srq; - dev->destroy_srq = ipath_destroy_srq; - dev->create_qp = ipath_create_qp; - dev->modify_qp = ipath_modify_qp; - dev->query_qp = ipath_query_qp; - dev->destroy_qp = ipath_destroy_qp; - dev->post_send = ipath_post_send; - dev->post_recv = ipath_post_receive; - dev->post_srq_recv = ipath_post_srq_receive; - dev->create_cq = ipath_create_cq; - dev->destroy_cq = ipath_destroy_cq; - dev->resize_cq = ipath_resize_cq; - dev->poll_cq = ipath_poll_cq; - dev->req_notify_cq = ipath_req_notify_cq; - dev->get_dma_mr = ipath_get_dma_mr; - dev->reg_user_mr = ipath_reg_user_mr; - dev->dereg_mr = ipath_dereg_mr; - dev->alloc_fmr = ipath_alloc_fmr; - dev->map_phys_fmr = ipath_map_phys_fmr; - dev->unmap_fmr = ipath_unmap_fmr; - dev->dealloc_fmr = ipath_dealloc_fmr; - dev->attach_mcast = ipath_multicast_attach; - dev->detach_mcast = ipath_multicast_detach; - dev->process_mad = ipath_process_mad; - dev->mmap = ipath_mmap; - dev->dma_ops = &ipath_dma_mapping_ops; - dev->get_port_immutable = ipath_port_immutable; - - snprintf(dev->node_desc, sizeof(dev->node_desc), - IPATH_IDSTR " %s", init_utsname()->nodename); - - ret = ib_register_device(dev, NULL); - if (ret) - goto err_reg; - - ret = ipath_verbs_register_sysfs(dev); - if (ret) - goto err_class; - - enable_timer(dd); - - goto bail; - -err_class: - ib_unregister_device(dev); -err_reg: - kfree(idev->lk_table.table); -err_lk: - kfree(idev->qp_table.table); -err_qp: - kfree(idev->txreq_bufs); -err_tx: - ib_dealloc_device(dev); - ipath_dev_err(dd, "cannot register verbs: %d!\n", -ret); - idev = NULL; - -bail: - dd->verbs_dev = idev; - return ret; -} - -void ipath_unregister_ib_device(struct ipath_ibdev *dev) -{ - struct ib_device *ibdev = &dev->ibdev; - u32 qps_inuse; - - ib_unregister_device(ibdev); - - disable_timer(dev->dd); - - if (!list_empty(&dev->pending[0]) || - !list_empty(&dev->pending[1]) || - !list_empty(&dev->pending[2])) - ipath_dev_err(dev->dd, "pending list not empty!\n"); - if (!list_empty(&dev->piowait)) - ipath_dev_err(dev->dd, "piowait list not empty!\n"); - if (!list_empty(&dev->rnrwait)) - ipath_dev_err(dev->dd, "rnrwait list not empty!\n"); - if (!ipath_mcast_tree_empty()) - ipath_dev_err(dev->dd, "multicast table memory leak!\n"); - /* - * Note that ipath_unregister_ib_device() can be called before all - * the QPs are destroyed! - */ - qps_inuse = ipath_free_all_qps(&dev->qp_table); - if (qps_inuse) - ipath_dev_err(dev->dd, "QP memory leak! %u still in use\n", - qps_inuse); - kfree(dev->qp_table.table); - kfree(dev->lk_table.table); - kfree(dev->txreq_bufs); - ib_dealloc_device(ibdev); -} - -static ssize_t show_rev(struct device *device, struct device_attribute *attr, - char *buf) -{ - struct ipath_ibdev *dev = - container_of(device, struct ipath_ibdev, ibdev.dev); - - return sprintf(buf, "%x\n", dev->dd->ipath_pcirev); -} - -static ssize_t show_hca(struct device *device, struct device_attribute *attr, - char *buf) -{ - struct ipath_ibdev *dev = - container_of(device, struct ipath_ibdev, ibdev.dev); - int ret; - - ret = dev->dd->ipath_f_get_boardname(dev->dd, buf, 128); - if (ret < 0) - goto bail; - strcat(buf, "\n"); - ret = strlen(buf); - -bail: - return ret; -} - -static ssize_t show_stats(struct device *device, struct device_attribute *attr, - char *buf) -{ - struct ipath_ibdev *dev = - container_of(device, struct ipath_ibdev, ibdev.dev); - int i; - int len; - - len = sprintf(buf, - "RC resends %d\n" - "RC no QACK %d\n" - "RC ACKs %d\n" - "RC SEQ NAKs %d\n" - "RC RDMA seq %d\n" - "RC RNR NAKs %d\n" - "RC OTH NAKs %d\n" - "RC timeouts %d\n" - "RC RDMA dup %d\n" - "piobuf wait %d\n" - "unaligned %d\n" - "PKT drops %d\n" - "WQE errs %d\n", - dev->n_rc_resends, dev->n_rc_qacks, dev->n_rc_acks, - dev->n_seq_naks, dev->n_rdma_seq, dev->n_rnr_naks, - dev->n_other_naks, dev->n_timeouts, - dev->n_rdma_dup_busy, dev->n_piowait, dev->n_unaligned, - dev->n_pkt_drops, dev->n_wqe_errs); - for (i = 0; i < ARRAY_SIZE(dev->opstats); i++) { - const struct ipath_opcode_stats *si = &dev->opstats[i]; - - if (!si->n_packets && !si->n_bytes) - continue; - len += sprintf(buf + len, "%02x %llu/%llu\n", i, - (unsigned long long) si->n_packets, - (unsigned long long) si->n_bytes); - } - return len; -} - -static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL); -static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL); -static DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL); -static DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL); - -static struct device_attribute *ipath_class_attributes[] = { - &dev_attr_hw_rev, - &dev_attr_hca_type, - &dev_attr_board_id, - &dev_attr_stats -}; - -static int ipath_verbs_register_sysfs(struct ib_device *dev) -{ - int i; - int ret; - - for (i = 0; i < ARRAY_SIZE(ipath_class_attributes); ++i) { - ret = device_create_file(&dev->dev, - ipath_class_attributes[i]); - if (ret) - goto bail; - } - return 0; -bail: - for (i = 0; i < ARRAY_SIZE(ipath_class_attributes); ++i) - device_remove_file(&dev->dev, ipath_class_attributes[i]); - return ret; -} diff --git a/drivers/staging/rdma/ipath/ipath_verbs.h b/drivers/staging/rdma/ipath/ipath_verbs.h deleted file mode 100644 index 6c70a89667a9..000000000000 --- a/drivers/staging/rdma/ipath/ipath_verbs.h +++ /dev/null @@ -1,941 +0,0 @@ -/* - * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. - * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef IPATH_VERBS_H -#define IPATH_VERBS_H - -#include -#include -#include -#include -#include -#include -#include - -#include "ipath_kernel.h" - -#define IPATH_MAX_RDMA_ATOMIC 4 - -#define QPN_MAX (1 << 24) -#define QPNMAP_ENTRIES (QPN_MAX / PAGE_SIZE / BITS_PER_BYTE) - -/* - * Increment this value if any changes that break userspace ABI - * compatibility are made. - */ -#define IPATH_UVERBS_ABI_VERSION 2 - -/* - * Define an ib_cq_notify value that is not valid so we know when CQ - * notifications are armed. - */ -#define IB_CQ_NONE (IB_CQ_NEXT_COMP + 1) - -/* AETH NAK opcode values */ -#define IB_RNR_NAK 0x20 -#define IB_NAK_PSN_ERROR 0x60 -#define IB_NAK_INVALID_REQUEST 0x61 -#define IB_NAK_REMOTE_ACCESS_ERROR 0x62 -#define IB_NAK_REMOTE_OPERATIONAL_ERROR 0x63 -#define IB_NAK_INVALID_RD_REQUEST 0x64 - -/* Flags for checking QP state (see ib_ipath_state_ops[]) */ -#define IPATH_POST_SEND_OK 0x01 -#define IPATH_POST_RECV_OK 0x02 -#define IPATH_PROCESS_RECV_OK 0x04 -#define IPATH_PROCESS_SEND_OK 0x08 -#define IPATH_PROCESS_NEXT_SEND_OK 0x10 -#define IPATH_FLUSH_SEND 0x20 -#define IPATH_FLUSH_RECV 0x40 -#define IPATH_PROCESS_OR_FLUSH_SEND \ - (IPATH_PROCESS_SEND_OK | IPATH_FLUSH_SEND) - -/* IB Performance Manager status values */ -#define IB_PMA_SAMPLE_STATUS_DONE 0x00 -#define IB_PMA_SAMPLE_STATUS_STARTED 0x01 -#define IB_PMA_SAMPLE_STATUS_RUNNING 0x02 - -/* Mandatory IB performance counter select values. */ -#define IB_PMA_PORT_XMIT_DATA cpu_to_be16(0x0001) -#define IB_PMA_PORT_RCV_DATA cpu_to_be16(0x0002) -#define IB_PMA_PORT_XMIT_PKTS cpu_to_be16(0x0003) -#define IB_PMA_PORT_RCV_PKTS cpu_to_be16(0x0004) -#define IB_PMA_PORT_XMIT_WAIT cpu_to_be16(0x0005) - -struct ib_reth { - __be64 vaddr; - __be32 rkey; - __be32 length; -} __attribute__ ((packed)); - -struct ib_atomic_eth { - __be32 vaddr[2]; /* unaligned so access as 2 32-bit words */ - __be32 rkey; - __be64 swap_data; - __be64 compare_data; -} __attribute__ ((packed)); - -struct ipath_other_headers { - __be32 bth[3]; - union { - struct { - __be32 deth[2]; - __be32 imm_data; - } ud; - struct { - struct ib_reth reth; - __be32 imm_data; - } rc; - struct { - __be32 aeth; - __be32 atomic_ack_eth[2]; - } at; - __be32 imm_data; - __be32 aeth; - struct ib_atomic_eth atomic_eth; - } u; -} __attribute__ ((packed)); - -/* - * Note that UD packets with a GRH header are 8+40+12+8 = 68 bytes - * long (72 w/ imm_data). Only the first 56 bytes of the IB header - * will be in the eager header buffer. The remaining 12 or 16 bytes - * are in the data buffer. - */ -struct ipath_ib_header { - __be16 lrh[4]; - union { - struct { - struct ib_grh grh; - struct ipath_other_headers oth; - } l; - struct ipath_other_headers oth; - } u; -} __attribute__ ((packed)); - -struct ipath_pio_header { - __le32 pbc[2]; - struct ipath_ib_header hdr; -} __attribute__ ((packed)); - -/* - * There is one struct ipath_mcast for each multicast GID. - * All attached QPs are then stored as a list of - * struct ipath_mcast_qp. - */ -struct ipath_mcast_qp { - struct list_head list; - struct ipath_qp *qp; -}; - -struct ipath_mcast { - struct rb_node rb_node; - union ib_gid mgid; - struct list_head qp_list; - wait_queue_head_t wait; - atomic_t refcount; - int n_attached; -}; - -/* Protection domain */ -struct ipath_pd { - struct ib_pd ibpd; - int user; /* non-zero if created from user space */ -}; - -/* Address Handle */ -struct ipath_ah { - struct ib_ah ibah; - struct ib_ah_attr attr; -}; - -/* - * This structure is used by ipath_mmap() to validate an offset - * when an mmap() request is made. The vm_area_struct then uses - * this as its vm_private_data. - */ -struct ipath_mmap_info { - struct list_head pending_mmaps; - struct ib_ucontext *context; - void *obj; - __u64 offset; - struct kref ref; - unsigned size; -}; - -/* - * This structure is used to contain the head pointer, tail pointer, - * and completion queue entries as a single memory allocation so - * it can be mmap'ed into user space. - */ -struct ipath_cq_wc { - u32 head; /* index of next entry to fill */ - u32 tail; /* index of next ib_poll_cq() entry */ - union { - /* these are actually size ibcq.cqe + 1 */ - struct ib_uverbs_wc uqueue[0]; - struct ib_wc kqueue[0]; - }; -}; - -/* - * The completion queue structure. - */ -struct ipath_cq { - struct ib_cq ibcq; - struct tasklet_struct comptask; - spinlock_t lock; - u8 notify; - u8 triggered; - struct ipath_cq_wc *queue; - struct ipath_mmap_info *ip; -}; - -/* - * A segment is a linear region of low physical memory. - * XXX Maybe we should use phys addr here and kmap()/kunmap(). - * Used by the verbs layer. - */ -struct ipath_seg { - void *vaddr; - size_t length; -}; - -/* The number of ipath_segs that fit in a page. */ -#define IPATH_SEGSZ (PAGE_SIZE / sizeof (struct ipath_seg)) - -struct ipath_segarray { - struct ipath_seg segs[IPATH_SEGSZ]; -}; - -struct ipath_mregion { - struct ib_pd *pd; /* shares refcnt of ibmr.pd */ - u64 user_base; /* User's address for this region */ - u64 iova; /* IB start address of this region */ - size_t length; - u32 lkey; - u32 offset; /* offset (bytes) to start of region */ - int access_flags; - u32 max_segs; /* number of ipath_segs in all the arrays */ - u32 mapsz; /* size of the map array */ - struct ipath_segarray *map[0]; /* the segments */ -}; - -/* - * These keep track of the copy progress within a memory region. - * Used by the verbs layer. - */ -struct ipath_sge { - struct ipath_mregion *mr; - void *vaddr; /* kernel virtual address of segment */ - u32 sge_length; /* length of the SGE */ - u32 length; /* remaining length of the segment */ - u16 m; /* current index: mr->map[m] */ - u16 n; /* current index: mr->map[m]->segs[n] */ -}; - -/* Memory region */ -struct ipath_mr { - struct ib_mr ibmr; - struct ib_umem *umem; - struct ipath_mregion mr; /* must be last */ -}; - -/* - * Send work request queue entry. - * The size of the sg_list is determined when the QP is created and stored - * in qp->s_max_sge. - */ -struct ipath_swqe { - union { - struct ib_send_wr wr; /* don't use wr.sg_list */ - struct ib_ud_wr ud_wr; - struct ib_rdma_wr rdma_wr; - struct ib_atomic_wr atomic_wr; - }; - - u32 psn; /* first packet sequence number */ - u32 lpsn; /* last packet sequence number */ - u32 ssn; /* send sequence number */ - u32 length; /* total length of data in sg_list */ - struct ipath_sge sg_list[0]; -}; - -/* - * Receive work request queue entry. - * The size of the sg_list is determined when the QP (or SRQ) is created - * and stored in qp->r_rq.max_sge (or srq->rq.max_sge). - */ -struct ipath_rwqe { - u64 wr_id; - u8 num_sge; - struct ib_sge sg_list[0]; -}; - -/* - * This structure is used to contain the head pointer, tail pointer, - * and receive work queue entries as a single memory allocation so - * it can be mmap'ed into user space. - * Note that the wq array elements are variable size so you can't - * just index into the array to get the N'th element; - * use get_rwqe_ptr() instead. - */ -struct ipath_rwq { - u32 head; /* new work requests posted to the head */ - u32 tail; /* receives pull requests from here. */ - struct ipath_rwqe wq[0]; -}; - -struct ipath_rq { - struct ipath_rwq *wq; - spinlock_t lock; - u32 size; /* size of RWQE array */ - u8 max_sge; -}; - -struct ipath_srq { - struct ib_srq ibsrq; - struct ipath_rq rq; - struct ipath_mmap_info *ip; - /* send signal when number of RWQEs < limit */ - u32 limit; -}; - -struct ipath_sge_state { - struct ipath_sge *sg_list; /* next SGE to be used if any */ - struct ipath_sge sge; /* progress state for the current SGE */ - u8 num_sge; - u8 static_rate; -}; - -/* - * This structure holds the information that the send tasklet needs - * to send a RDMA read response or atomic operation. - */ -struct ipath_ack_entry { - u8 opcode; - u8 sent; - u32 psn; - union { - struct ipath_sge_state rdma_sge; - u64 atomic_data; - }; -}; - -/* - * Variables prefixed with s_ are for the requester (sender). - * Variables prefixed with r_ are for the responder (receiver). - * Variables prefixed with ack_ are for responder replies. - * - * Common variables are protected by both r_rq.lock and s_lock in that order - * which only happens in modify_qp() or changing the QP 'state'. - */ -struct ipath_qp { - struct ib_qp ibqp; - struct ipath_qp *next; /* link list for QPN hash table */ - struct ipath_qp *timer_next; /* link list for ipath_ib_timer() */ - struct ipath_qp *pio_next; /* link for ipath_ib_piobufavail() */ - struct list_head piowait; /* link for wait PIO buf */ - struct list_head timerwait; /* link for waiting for timeouts */ - struct ib_ah_attr remote_ah_attr; - struct ipath_ib_header s_hdr; /* next packet header to send */ - atomic_t refcount; - wait_queue_head_t wait; - wait_queue_head_t wait_dma; - struct tasklet_struct s_task; - struct ipath_mmap_info *ip; - struct ipath_sge_state *s_cur_sge; - struct ipath_verbs_txreq *s_tx; - struct ipath_sge_state s_sge; /* current send request data */ - struct ipath_ack_entry s_ack_queue[IPATH_MAX_RDMA_ATOMIC + 1]; - struct ipath_sge_state s_ack_rdma_sge; - struct ipath_sge_state s_rdma_read_sge; - struct ipath_sge_state r_sge; /* current receive data */ - spinlock_t s_lock; - atomic_t s_dma_busy; - u16 s_pkt_delay; - u16 s_hdrwords; /* size of s_hdr in 32 bit words */ - u32 s_cur_size; /* size of send packet in bytes */ - u32 s_len; /* total length of s_sge */ - u32 s_rdma_read_len; /* total length of s_rdma_read_sge */ - u32 s_next_psn; /* PSN for next request */ - u32 s_last_psn; /* last response PSN processed */ - u32 s_psn; /* current packet sequence number */ - u32 s_ack_rdma_psn; /* PSN for sending RDMA read responses */ - u32 s_ack_psn; /* PSN for acking sends and RDMA writes */ - u32 s_rnr_timeout; /* number of milliseconds for RNR timeout */ - u32 r_ack_psn; /* PSN for next ACK or atomic ACK */ - u64 r_wr_id; /* ID for current receive WQE */ - unsigned long r_aflags; - u32 r_len; /* total length of r_sge */ - u32 r_rcv_len; /* receive data len processed */ - u32 r_psn; /* expected rcv packet sequence number */ - u32 r_msn; /* message sequence number */ - u8 state; /* QP state */ - u8 s_state; /* opcode of last packet sent */ - u8 s_ack_state; /* opcode of packet to ACK */ - u8 s_nak_state; /* non-zero if NAK is pending */ - u8 r_state; /* opcode of last packet received */ - u8 r_nak_state; /* non-zero if NAK is pending */ - u8 r_min_rnr_timer; /* retry timeout value for RNR NAKs */ - u8 r_flags; - u8 r_max_rd_atomic; /* max number of RDMA read/atomic to receive */ - u8 r_head_ack_queue; /* index into s_ack_queue[] */ - u8 qp_access_flags; - u8 s_max_sge; /* size of s_wq->sg_list */ - u8 s_retry_cnt; /* number of times to retry */ - u8 s_rnr_retry_cnt; - u8 s_retry; /* requester retry counter */ - u8 s_rnr_retry; /* requester RNR retry counter */ - u8 s_pkey_index; /* PKEY index to use */ - u8 s_max_rd_atomic; /* max number of RDMA read/atomic to send */ - u8 s_num_rd_atomic; /* number of RDMA read/atomic pending */ - u8 s_tail_ack_queue; /* index into s_ack_queue[] */ - u8 s_flags; - u8 s_dmult; - u8 s_draining; - u8 timeout; /* Timeout for this QP */ - enum ib_mtu path_mtu; - u32 remote_qpn; - u32 qkey; /* QKEY for this QP (for UD or RD) */ - u32 s_size; /* send work queue size */ - u32 s_head; /* new entries added here */ - u32 s_tail; /* next entry to process */ - u32 s_cur; /* current work queue entry */ - u32 s_last; /* last un-ACK'ed entry */ - u32 s_ssn; /* SSN of tail entry */ - u32 s_lsn; /* limit sequence number (credit) */ - struct ipath_swqe *s_wq; /* send work queue */ - struct ipath_swqe *s_wqe; - struct ipath_sge *r_ud_sg_list; - struct ipath_rq r_rq; /* receive work queue */ - struct ipath_sge r_sg_list[0]; /* verified SGEs */ -}; - -/* - * Atomic bit definitions for r_aflags. - */ -#define IPATH_R_WRID_VALID 0 - -/* - * Bit definitions for r_flags. - */ -#define IPATH_R_REUSE_SGE 0x01 -#define IPATH_R_RDMAR_SEQ 0x02 - -/* - * Bit definitions for s_flags. - * - * IPATH_S_FENCE_PENDING - waiting for all prior RDMA read or atomic SWQEs - * before processing the next SWQE - * IPATH_S_RDMAR_PENDING - waiting for any RDMA read or atomic SWQEs - * before processing the next SWQE - * IPATH_S_WAITING - waiting for RNR timeout or send buffer available. - * IPATH_S_WAIT_SSN_CREDIT - waiting for RC credits to process next SWQE - * IPATH_S_WAIT_DMA - waiting for send DMA queue to drain before generating - * next send completion entry not via send DMA. - */ -#define IPATH_S_SIGNAL_REQ_WR 0x01 -#define IPATH_S_FENCE_PENDING 0x02 -#define IPATH_S_RDMAR_PENDING 0x04 -#define IPATH_S_ACK_PENDING 0x08 -#define IPATH_S_BUSY 0x10 -#define IPATH_S_WAITING 0x20 -#define IPATH_S_WAIT_SSN_CREDIT 0x40 -#define IPATH_S_WAIT_DMA 0x80 - -#define IPATH_S_ANY_WAIT (IPATH_S_FENCE_PENDING | IPATH_S_RDMAR_PENDING | \ - IPATH_S_WAITING | IPATH_S_WAIT_SSN_CREDIT | IPATH_S_WAIT_DMA) - -#define IPATH_PSN_CREDIT 512 - -/* - * Since struct ipath_swqe is not a fixed size, we can't simply index into - * struct ipath_qp.s_wq. This function does the array index computation. - */ -static inline struct ipath_swqe *get_swqe_ptr(struct ipath_qp *qp, - unsigned n) -{ - return (struct ipath_swqe *)((char *)qp->s_wq + - (sizeof(struct ipath_swqe) + - qp->s_max_sge * - sizeof(struct ipath_sge)) * n); -} - -/* - * Since struct ipath_rwqe is not a fixed size, we can't simply index into - * struct ipath_rwq.wq. This function does the array index computation. - */ -static inline struct ipath_rwqe *get_rwqe_ptr(struct ipath_rq *rq, - unsigned n) -{ - return (struct ipath_rwqe *) - ((char *) rq->wq->wq + - (sizeof(struct ipath_rwqe) + - rq->max_sge * sizeof(struct ib_sge)) * n); -} - -/* - * QPN-map pages start out as NULL, they get allocated upon - * first use and are never deallocated. This way, - * large bitmaps are not allocated unless large numbers of QPs are used. - */ -struct qpn_map { - atomic_t n_free; - void *page; -}; - -struct ipath_qp_table { - spinlock_t lock; - u32 last; /* last QP number allocated */ - u32 max; /* size of the hash table */ - u32 nmaps; /* size of the map table */ - struct ipath_qp **table; - /* bit map of free numbers */ - struct qpn_map map[QPNMAP_ENTRIES]; -}; - -struct ipath_lkey_table { - spinlock_t lock; - u32 next; /* next unused index (speeds search) */ - u32 gen; /* generation count */ - u32 max; /* size of the table */ - struct ipath_mregion **table; -}; - -struct ipath_opcode_stats { - u64 n_packets; /* number of packets */ - u64 n_bytes; /* total number of bytes */ -}; - -struct ipath_ibdev { - struct ib_device ibdev; - struct ipath_devdata *dd; - struct list_head pending_mmaps; - spinlock_t mmap_offset_lock; - u32 mmap_offset; - int ib_unit; /* This is the device number */ - u16 sm_lid; /* in host order */ - u8 sm_sl; - u8 mkeyprot; - /* non-zero when timer is set */ - unsigned long mkey_lease_timeout; - - /* The following fields are really per port. */ - struct ipath_qp_table qp_table; - struct ipath_lkey_table lk_table; - struct list_head pending[3]; /* FIFO of QPs waiting for ACKs */ - struct list_head piowait; /* list for wait PIO buf */ - struct list_head txreq_free; - void *txreq_bufs; - /* list of QPs waiting for RNR timer */ - struct list_head rnrwait; - spinlock_t pending_lock; - __be64 sys_image_guid; /* in network order */ - __be64 gid_prefix; /* in network order */ - __be64 mkey; - - u32 n_pds_allocated; /* number of PDs allocated for device */ - spinlock_t n_pds_lock; - u32 n_ahs_allocated; /* number of AHs allocated for device */ - spinlock_t n_ahs_lock; - u32 n_cqs_allocated; /* number of CQs allocated for device */ - spinlock_t n_cqs_lock; - u32 n_qps_allocated; /* number of QPs allocated for device */ - spinlock_t n_qps_lock; - u32 n_srqs_allocated; /* number of SRQs allocated for device */ - spinlock_t n_srqs_lock; - u32 n_mcast_grps_allocated; /* number of mcast groups allocated */ - spinlock_t n_mcast_grps_lock; - - u64 ipath_sword; /* total dwords sent (sample result) */ - u64 ipath_rword; /* total dwords received (sample result) */ - u64 ipath_spkts; /* total packets sent (sample result) */ - u64 ipath_rpkts; /* total packets received (sample result) */ - /* # of ticks no data sent (sample result) */ - u64 ipath_xmit_wait; - u64 rcv_errors; /* # of packets with SW detected rcv errs */ - u64 n_unicast_xmit; /* total unicast packets sent */ - u64 n_unicast_rcv; /* total unicast packets received */ - u64 n_multicast_xmit; /* total multicast packets sent */ - u64 n_multicast_rcv; /* total multicast packets received */ - u64 z_symbol_error_counter; /* starting count for PMA */ - u64 z_link_error_recovery_counter; /* starting count for PMA */ - u64 z_link_downed_counter; /* starting count for PMA */ - u64 z_port_rcv_errors; /* starting count for PMA */ - u64 z_port_rcv_remphys_errors; /* starting count for PMA */ - u64 z_port_xmit_discards; /* starting count for PMA */ - u64 z_port_xmit_data; /* starting count for PMA */ - u64 z_port_rcv_data; /* starting count for PMA */ - u64 z_port_xmit_packets; /* starting count for PMA */ - u64 z_port_rcv_packets; /* starting count for PMA */ - u32 z_pkey_violations; /* starting count for PMA */ - u32 z_local_link_integrity_errors; /* starting count for PMA */ - u32 z_excessive_buffer_overrun_errors; /* starting count for PMA */ - u32 z_vl15_dropped; /* starting count for PMA */ - u32 n_rc_resends; - u32 n_rc_acks; - u32 n_rc_qacks; - u32 n_seq_naks; - u32 n_rdma_seq; - u32 n_rnr_naks; - u32 n_other_naks; - u32 n_timeouts; - u32 n_pkt_drops; - u32 n_vl15_dropped; - u32 n_wqe_errs; - u32 n_rdma_dup_busy; - u32 n_piowait; - u32 n_unaligned; - u32 port_cap_flags; - u32 pma_sample_start; - u32 pma_sample_interval; - __be16 pma_counter_select[5]; - u16 pma_tag; - u16 qkey_violations; - u16 mkey_violations; - u16 mkey_lease_period; - u16 pending_index; /* which pending queue is active */ - u8 pma_sample_status; - u8 subnet_timeout; - u8 vl_high_limit; - struct ipath_opcode_stats opstats[128]; -}; - -struct ipath_verbs_counters { - u64 symbol_error_counter; - u64 link_error_recovery_counter; - u64 link_downed_counter; - u64 port_rcv_errors; - u64 port_rcv_remphys_errors; - u64 port_xmit_discards; - u64 port_xmit_data; - u64 port_rcv_data; - u64 port_xmit_packets; - u64 port_rcv_packets; - u32 local_link_integrity_errors; - u32 excessive_buffer_overrun_errors; - u32 vl15_dropped; -}; - -struct ipath_verbs_txreq { - struct ipath_qp *qp; - struct ipath_swqe *wqe; - u32 map_len; - u32 len; - struct ipath_sge_state *ss; - struct ipath_pio_header hdr; - struct ipath_sdma_txreq txreq; -}; - -static inline struct ipath_mr *to_imr(struct ib_mr *ibmr) -{ - return container_of(ibmr, struct ipath_mr, ibmr); -} - -static inline struct ipath_pd *to_ipd(struct ib_pd *ibpd) -{ - return container_of(ibpd, struct ipath_pd, ibpd); -} - -static inline struct ipath_ah *to_iah(struct ib_ah *ibah) -{ - return container_of(ibah, struct ipath_ah, ibah); -} - -static inline struct ipath_cq *to_icq(struct ib_cq *ibcq) -{ - return container_of(ibcq, struct ipath_cq, ibcq); -} - -static inline struct ipath_srq *to_isrq(struct ib_srq *ibsrq) -{ - return container_of(ibsrq, struct ipath_srq, ibsrq); -} - -static inline struct ipath_qp *to_iqp(struct ib_qp *ibqp) -{ - return container_of(ibqp, struct ipath_qp, ibqp); -} - -static inline struct ipath_ibdev *to_idev(struct ib_device *ibdev) -{ - return container_of(ibdev, struct ipath_ibdev, ibdev); -} - -/* - * This must be called with s_lock held. - */ -static inline void ipath_schedule_send(struct ipath_qp *qp) -{ - if (qp->s_flags & IPATH_S_ANY_WAIT) - qp->s_flags &= ~IPATH_S_ANY_WAIT; - if (!(qp->s_flags & IPATH_S_BUSY)) - tasklet_hi_schedule(&qp->s_task); -} - -int ipath_process_mad(struct ib_device *ibdev, - int mad_flags, - u8 port_num, - const struct ib_wc *in_wc, - const struct ib_grh *in_grh, - const struct ib_mad_hdr *in, size_t in_mad_size, - struct ib_mad_hdr *out, size_t *out_mad_size, - u16 *out_mad_pkey_index); - -/* - * Compare the lower 24 bits of the two values. - * Returns an integer <, ==, or > than zero. - */ -static inline int ipath_cmp24(u32 a, u32 b) -{ - return (((int) a) - ((int) b)) << 8; -} - -struct ipath_mcast *ipath_mcast_find(union ib_gid *mgid); - -int ipath_snapshot_counters(struct ipath_devdata *dd, u64 *swords, - u64 *rwords, u64 *spkts, u64 *rpkts, - u64 *xmit_wait); - -int ipath_get_counters(struct ipath_devdata *dd, - struct ipath_verbs_counters *cntrs); - -int ipath_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); - -int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); - -int ipath_mcast_tree_empty(void); - -__be32 ipath_compute_aeth(struct ipath_qp *qp); - -struct ipath_qp *ipath_lookup_qpn(struct ipath_qp_table *qpt, u32 qpn); - -struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, - struct ib_qp_init_attr *init_attr, - struct ib_udata *udata); - -int ipath_destroy_qp(struct ib_qp *ibqp); - -int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err); - -int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, - int attr_mask, struct ib_udata *udata); - -int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, - int attr_mask, struct ib_qp_init_attr *init_attr); - -unsigned ipath_free_all_qps(struct ipath_qp_table *qpt); - -int ipath_init_qp_table(struct ipath_ibdev *idev, int size); - -void ipath_get_credit(struct ipath_qp *qp, u32 aeth); - -unsigned ipath_ib_rate_to_mult(enum ib_rate rate); - -int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr, - u32 hdrwords, struct ipath_sge_state *ss, u32 len); - -void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length); - -void ipath_skip_sge(struct ipath_sge_state *ss, u32 length); - -void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, - int has_grh, void *data, u32 tlen, struct ipath_qp *qp); - -void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, - int has_grh, void *data, u32 tlen, struct ipath_qp *qp); - -void ipath_restart_rc(struct ipath_qp *qp, u32 psn); - -void ipath_rc_error(struct ipath_qp *qp, enum ib_wc_status err); - -int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr); - -void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, - int has_grh, void *data, u32 tlen, struct ipath_qp *qp); - -int ipath_alloc_lkey(struct ipath_lkey_table *rkt, - struct ipath_mregion *mr); - -void ipath_free_lkey(struct ipath_lkey_table *rkt, u32 lkey); - -int ipath_lkey_ok(struct ipath_qp *qp, struct ipath_sge *isge, - struct ib_sge *sge, int acc); - -int ipath_rkey_ok(struct ipath_qp *qp, struct ipath_sge_state *ss, - u32 len, u64 vaddr, u32 rkey, int acc); - -int ipath_post_srq_receive(struct ib_srq *ibsrq, struct ib_recv_wr *wr, - struct ib_recv_wr **bad_wr); - -struct ib_srq *ipath_create_srq(struct ib_pd *ibpd, - struct ib_srq_init_attr *srq_init_attr, - struct ib_udata *udata); - -int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, - enum ib_srq_attr_mask attr_mask, - struct ib_udata *udata); - -int ipath_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr); - -int ipath_destroy_srq(struct ib_srq *ibsrq); - -void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int sig); - -int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry); - -struct ib_cq *ipath_create_cq(struct ib_device *ibdev, - const struct ib_cq_init_attr *attr, - struct ib_ucontext *context, - struct ib_udata *udata); - -int ipath_destroy_cq(struct ib_cq *ibcq); - -int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags notify_flags); - -int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata); - -struct ib_mr *ipath_get_dma_mr(struct ib_pd *pd, int acc); - -struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt_addr, int mr_access_flags, - struct ib_udata *udata); - -int ipath_dereg_mr(struct ib_mr *ibmr); - -struct ib_fmr *ipath_alloc_fmr(struct ib_pd *pd, int mr_access_flags, - struct ib_fmr_attr *fmr_attr); - -int ipath_map_phys_fmr(struct ib_fmr *ibfmr, u64 * page_list, - int list_len, u64 iova); - -int ipath_unmap_fmr(struct list_head *fmr_list); - -int ipath_dealloc_fmr(struct ib_fmr *ibfmr); - -void ipath_release_mmap_info(struct kref *ref); - -struct ipath_mmap_info *ipath_create_mmap_info(struct ipath_ibdev *dev, - u32 size, - struct ib_ucontext *context, - void *obj); - -void ipath_update_mmap_info(struct ipath_ibdev *dev, - struct ipath_mmap_info *ip, - u32 size, void *obj); - -int ipath_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); - -void ipath_insert_rnr_queue(struct ipath_qp *qp); - -int ipath_init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe, - u32 *lengthp, struct ipath_sge_state *ss); - -int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only); - -u32 ipath_make_grh(struct ipath_ibdev *dev, struct ib_grh *hdr, - struct ib_global_route *grh, u32 hwords, u32 nwords); - -void ipath_make_ruc_header(struct ipath_ibdev *dev, struct ipath_qp *qp, - struct ipath_other_headers *ohdr, - u32 bth0, u32 bth2); - -void ipath_do_send(unsigned long data); - -void ipath_send_complete(struct ipath_qp *qp, struct ipath_swqe *wqe, - enum ib_wc_status status); - -int ipath_make_rc_req(struct ipath_qp *qp); - -int ipath_make_uc_req(struct ipath_qp *qp); - -int ipath_make_ud_req(struct ipath_qp *qp); - -int ipath_register_ib_device(struct ipath_devdata *); - -void ipath_unregister_ib_device(struct ipath_ibdev *); - -void ipath_ib_rcv(struct ipath_ibdev *, void *, void *, u32); - -int ipath_ib_piobufavail(struct ipath_ibdev *); - -unsigned ipath_get_npkeys(struct ipath_devdata *); - -u32 ipath_get_cr_errpkey(struct ipath_devdata *); - -unsigned ipath_get_pkey(struct ipath_devdata *, unsigned); - -extern const enum ib_wc_opcode ib_ipath_wc_opcode[]; - -/* - * Below converts HCA-specific LinkTrainingState to IB PhysPortState - * values. - */ -extern const u8 ipath_cvt_physportstate[]; -#define IB_PHYSPORTSTATE_SLEEP 1 -#define IB_PHYSPORTSTATE_POLL 2 -#define IB_PHYSPORTSTATE_DISABLED 3 -#define IB_PHYSPORTSTATE_CFG_TRAIN 4 -#define IB_PHYSPORTSTATE_LINKUP 5 -#define IB_PHYSPORTSTATE_LINK_ERR_RECOVER 6 - -extern const int ib_ipath_state_ops[]; - -extern unsigned int ib_ipath_lkey_table_size; - -extern unsigned int ib_ipath_max_cqes; - -extern unsigned int ib_ipath_max_cqs; - -extern unsigned int ib_ipath_max_qp_wrs; - -extern unsigned int ib_ipath_max_qps; - -extern unsigned int ib_ipath_max_sges; - -extern unsigned int ib_ipath_max_mcast_grps; - -extern unsigned int ib_ipath_max_mcast_qp_attached; - -extern unsigned int ib_ipath_max_srqs; - -extern unsigned int ib_ipath_max_srq_sges; - -extern unsigned int ib_ipath_max_srq_wrs; - -extern const u32 ib_ipath_rnr_table[]; - -extern struct ib_dma_mapping_ops ipath_dma_mapping_ops; - -#endif /* IPATH_VERBS_H */ diff --git a/drivers/staging/rdma/ipath/ipath_verbs_mcast.c b/drivers/staging/rdma/ipath/ipath_verbs_mcast.c deleted file mode 100644 index 72d476fa5b8f..000000000000 --- a/drivers/staging/rdma/ipath/ipath_verbs_mcast.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. - * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include "ipath_verbs.h" - -/* - * Global table of GID to attached QPs. - * The table is global to all ipath devices since a send from one QP/device - * needs to be locally routed to any locally attached QPs on the same - * or different device. - */ -static struct rb_root mcast_tree; -static DEFINE_SPINLOCK(mcast_lock); - -/** - * ipath_mcast_qp_alloc - alloc a struct to link a QP to mcast GID struct - * @qp: the QP to link - */ -static struct ipath_mcast_qp *ipath_mcast_qp_alloc(struct ipath_qp *qp) -{ - struct ipath_mcast_qp *mqp; - - mqp = kmalloc(sizeof *mqp, GFP_KERNEL); - if (!mqp) - goto bail; - - mqp->qp = qp; - atomic_inc(&qp->refcount); - -bail: - return mqp; -} - -static void ipath_mcast_qp_free(struct ipath_mcast_qp *mqp) -{ - struct ipath_qp *qp = mqp->qp; - - /* Notify ipath_destroy_qp() if it is waiting. */ - if (atomic_dec_and_test(&qp->refcount)) - wake_up(&qp->wait); - - kfree(mqp); -} - -/** - * ipath_mcast_alloc - allocate the multicast GID structure - * @mgid: the multicast GID - * - * A list of QPs will be attached to this structure. - */ -static struct ipath_mcast *ipath_mcast_alloc(union ib_gid *mgid) -{ - struct ipath_mcast *mcast; - - mcast = kmalloc(sizeof *mcast, GFP_KERNEL); - if (!mcast) - goto bail; - - mcast->mgid = *mgid; - INIT_LIST_HEAD(&mcast->qp_list); - init_waitqueue_head(&mcast->wait); - atomic_set(&mcast->refcount, 0); - mcast->n_attached = 0; - -bail: - return mcast; -} - -static void ipath_mcast_free(struct ipath_mcast *mcast) -{ - struct ipath_mcast_qp *p, *tmp; - - list_for_each_entry_safe(p, tmp, &mcast->qp_list, list) - ipath_mcast_qp_free(p); - - kfree(mcast); -} - -/** - * ipath_mcast_find - search the global table for the given multicast GID - * @mgid: the multicast GID to search for - * - * Returns NULL if not found. - * - * The caller is responsible for decrementing the reference count if found. - */ -struct ipath_mcast *ipath_mcast_find(union ib_gid *mgid) -{ - struct rb_node *n; - unsigned long flags; - struct ipath_mcast *mcast; - - spin_lock_irqsave(&mcast_lock, flags); - n = mcast_tree.rb_node; - while (n) { - int ret; - - mcast = rb_entry(n, struct ipath_mcast, rb_node); - - ret = memcmp(mgid->raw, mcast->mgid.raw, - sizeof(union ib_gid)); - if (ret < 0) - n = n->rb_left; - else if (ret > 0) - n = n->rb_right; - else { - atomic_inc(&mcast->refcount); - spin_unlock_irqrestore(&mcast_lock, flags); - goto bail; - } - } - spin_unlock_irqrestore(&mcast_lock, flags); - - mcast = NULL; - -bail: - return mcast; -} - -/** - * ipath_mcast_add - insert mcast GID into table and attach QP struct - * @mcast: the mcast GID table - * @mqp: the QP to attach - * - * Return zero if both were added. Return EEXIST if the GID was already in - * the table but the QP was added. Return ESRCH if the QP was already - * attached and neither structure was added. - */ -static int ipath_mcast_add(struct ipath_ibdev *dev, - struct ipath_mcast *mcast, - struct ipath_mcast_qp *mqp) -{ - struct rb_node **n = &mcast_tree.rb_node; - struct rb_node *pn = NULL; - int ret; - - spin_lock_irq(&mcast_lock); - - while (*n) { - struct ipath_mcast *tmcast; - struct ipath_mcast_qp *p; - - pn = *n; - tmcast = rb_entry(pn, struct ipath_mcast, rb_node); - - ret = memcmp(mcast->mgid.raw, tmcast->mgid.raw, - sizeof(union ib_gid)); - if (ret < 0) { - n = &pn->rb_left; - continue; - } - if (ret > 0) { - n = &pn->rb_right; - continue; - } - - /* Search the QP list to see if this is already there. */ - list_for_each_entry_rcu(p, &tmcast->qp_list, list) { - if (p->qp == mqp->qp) { - ret = ESRCH; - goto bail; - } - } - if (tmcast->n_attached == ib_ipath_max_mcast_qp_attached) { - ret = ENOMEM; - goto bail; - } - - tmcast->n_attached++; - - list_add_tail_rcu(&mqp->list, &tmcast->qp_list); - ret = EEXIST; - goto bail; - } - - spin_lock(&dev->n_mcast_grps_lock); - if (dev->n_mcast_grps_allocated == ib_ipath_max_mcast_grps) { - spin_unlock(&dev->n_mcast_grps_lock); - ret = ENOMEM; - goto bail; - } - - dev->n_mcast_grps_allocated++; - spin_unlock(&dev->n_mcast_grps_lock); - - mcast->n_attached++; - - list_add_tail_rcu(&mqp->list, &mcast->qp_list); - - atomic_inc(&mcast->refcount); - rb_link_node(&mcast->rb_node, pn, n); - rb_insert_color(&mcast->rb_node, &mcast_tree); - - ret = 0; - -bail: - spin_unlock_irq(&mcast_lock); - - return ret; -} - -int ipath_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) -{ - struct ipath_qp *qp = to_iqp(ibqp); - struct ipath_ibdev *dev = to_idev(ibqp->device); - struct ipath_mcast *mcast; - struct ipath_mcast_qp *mqp; - int ret; - - /* - * Allocate data structures since its better to do this outside of - * spin locks and it will most likely be needed. - */ - mcast = ipath_mcast_alloc(gid); - if (mcast == NULL) { - ret = -ENOMEM; - goto bail; - } - mqp = ipath_mcast_qp_alloc(qp); - if (mqp == NULL) { - ipath_mcast_free(mcast); - ret = -ENOMEM; - goto bail; - } - switch (ipath_mcast_add(dev, mcast, mqp)) { - case ESRCH: - /* Neither was used: can't attach the same QP twice. */ - ipath_mcast_qp_free(mqp); - ipath_mcast_free(mcast); - ret = -EINVAL; - goto bail; - case EEXIST: /* The mcast wasn't used */ - ipath_mcast_free(mcast); - break; - case ENOMEM: - /* Exceeded the maximum number of mcast groups. */ - ipath_mcast_qp_free(mqp); - ipath_mcast_free(mcast); - ret = -ENOMEM; - goto bail; - default: - break; - } - - ret = 0; - -bail: - return ret; -} - -int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) -{ - struct ipath_qp *qp = to_iqp(ibqp); - struct ipath_ibdev *dev = to_idev(ibqp->device); - struct ipath_mcast *mcast = NULL; - struct ipath_mcast_qp *p, *tmp; - struct rb_node *n; - int last = 0; - int ret; - - spin_lock_irq(&mcast_lock); - - /* Find the GID in the mcast table. */ - n = mcast_tree.rb_node; - while (1) { - if (n == NULL) { - spin_unlock_irq(&mcast_lock); - ret = -EINVAL; - goto bail; - } - - mcast = rb_entry(n, struct ipath_mcast, rb_node); - ret = memcmp(gid->raw, mcast->mgid.raw, - sizeof(union ib_gid)); - if (ret < 0) - n = n->rb_left; - else if (ret > 0) - n = n->rb_right; - else - break; - } - - /* Search the QP list. */ - list_for_each_entry_safe(p, tmp, &mcast->qp_list, list) { - if (p->qp != qp) - continue; - /* - * We found it, so remove it, but don't poison the forward - * link until we are sure there are no list walkers. - */ - list_del_rcu(&p->list); - mcast->n_attached--; - - /* If this was the last attached QP, remove the GID too. */ - if (list_empty(&mcast->qp_list)) { - rb_erase(&mcast->rb_node, &mcast_tree); - last = 1; - } - break; - } - - spin_unlock_irq(&mcast_lock); - - if (p) { - /* - * Wait for any list walkers to finish before freeing the - * list element. - */ - wait_event(mcast->wait, atomic_read(&mcast->refcount) <= 1); - ipath_mcast_qp_free(p); - } - if (last) { - atomic_dec(&mcast->refcount); - wait_event(mcast->wait, !atomic_read(&mcast->refcount)); - ipath_mcast_free(mcast); - spin_lock_irq(&dev->n_mcast_grps_lock); - dev->n_mcast_grps_allocated--; - spin_unlock_irq(&dev->n_mcast_grps_lock); - } - - ret = 0; - -bail: - return ret; -} - -int ipath_mcast_tree_empty(void) -{ - return mcast_tree.rb_node == NULL; -} diff --git a/drivers/staging/rdma/ipath/ipath_wc_ppc64.c b/drivers/staging/rdma/ipath/ipath_wc_ppc64.c deleted file mode 100644 index 1a7e20a75149..000000000000 --- a/drivers/staging/rdma/ipath/ipath_wc_ppc64.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * This file is conditionally built on PowerPC only. Otherwise weak symbol - * versions of the functions exported from here are used. - */ - -#include "ipath_kernel.h" - -/** - * ipath_enable_wc - enable write combining for MMIO writes to the device - * @dd: infinipath device - * - * Nothing to do on PowerPC, so just return without error. - */ -int ipath_enable_wc(struct ipath_devdata *dd) -{ - return 0; -} diff --git a/drivers/staging/rdma/ipath/ipath_wc_x86_64.c b/drivers/staging/rdma/ipath/ipath_wc_x86_64.c deleted file mode 100644 index 7b6e4c843e19..000000000000 --- a/drivers/staging/rdma/ipath/ipath_wc_x86_64.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. - * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * This file is conditionally built on x86_64 only. Otherwise weak symbol - * versions of the functions exported from here are used. - */ - -#include -#include - -#include "ipath_kernel.h" - -/** - * ipath_enable_wc - enable write combining for MMIO writes to the device - * @dd: infinipath device - * - * This routine is x86_64-specific; it twiddles the CPU's MTRRs to enable - * write combining. - */ -int ipath_enable_wc(struct ipath_devdata *dd) -{ - int ret = 0; - u64 pioaddr, piolen; - unsigned bits; - const unsigned long addr = pci_resource_start(dd->pcidev, 0); - const size_t len = pci_resource_len(dd->pcidev, 0); - - /* - * Set the PIO buffers to be WCCOMB, so we get HT bursts to the - * chip. Linux (possibly the hardware) requires it to be on a power - * of 2 address matching the length (which has to be a power of 2). - * For rev1, that means the base address, for rev2, it will be just - * the PIO buffers themselves. - * For chips with two sets of buffers, the calculations are - * somewhat more complicated; we need to sum, and the piobufbase - * register has both offsets, 2K in low 32 bits, 4K in high 32 bits. - * The buffers are still packed, so a single range covers both. - */ - if (dd->ipath_piobcnt2k && dd->ipath_piobcnt4k) { /* 2 sizes */ - unsigned long pio2kbase, pio4kbase; - pio2kbase = dd->ipath_piobufbase & 0xffffffffUL; - pio4kbase = (dd->ipath_piobufbase >> 32) & 0xffffffffUL; - if (pio2kbase < pio4kbase) { /* all, for now */ - pioaddr = addr + pio2kbase; - piolen = pio4kbase - pio2kbase + - dd->ipath_piobcnt4k * dd->ipath_4kalign; - } else { - pioaddr = addr + pio4kbase; - piolen = pio2kbase - pio4kbase + - dd->ipath_piobcnt2k * dd->ipath_palign; - } - } else { /* single buffer size (2K, currently) */ - pioaddr = addr + dd->ipath_piobufbase; - piolen = dd->ipath_piobcnt2k * dd->ipath_palign + - dd->ipath_piobcnt4k * dd->ipath_4kalign; - } - - for (bits = 0; !(piolen & (1ULL << bits)); bits++) - /* do nothing */ ; - - if (piolen != (1ULL << bits)) { - piolen >>= bits; - while (piolen >>= 1) - bits++; - piolen = 1ULL << (bits + 1); - } - if (pioaddr & (piolen - 1)) { - u64 atmp; - ipath_dbg("pioaddr %llx not on right boundary for size " - "%llx, fixing\n", - (unsigned long long) pioaddr, - (unsigned long long) piolen); - atmp = pioaddr & ~(piolen - 1); - if (atmp < addr || (atmp + piolen) > (addr + len)) { - ipath_dev_err(dd, "No way to align address/size " - "(%llx/%llx), no WC mtrr\n", - (unsigned long long) atmp, - (unsigned long long) piolen << 1); - ret = -ENODEV; - } else { - ipath_dbg("changing WC base from %llx to %llx, " - "len from %llx to %llx\n", - (unsigned long long) pioaddr, - (unsigned long long) atmp, - (unsigned long long) piolen, - (unsigned long long) piolen << 1); - pioaddr = atmp; - piolen <<= 1; - } - } - - if (!ret) { - dd->wc_cookie = arch_phys_wc_add(pioaddr, piolen); - if (dd->wc_cookie < 0) { - ipath_dev_err(dd, "Seting mtrr failed on PIO buffers\n"); - ret = -ENODEV; - } else if (dd->wc_cookie == 0) - ipath_cdbg(VERBOSE, "Set mtrr for chip to WC not needed\n"); - else - ipath_cdbg(VERBOSE, "Set mtrr for chip to WC\n"); - } - - return ret; -} - -/** - * ipath_disable_wc - disable write combining for MMIO writes to the device - * @dd: infinipath device - */ -void ipath_disable_wc(struct ipath_devdata *dd) -{ - arch_phys_wc_del(dd->wc_cookie); -} -- cgit v1.2.3 From 461c7fa126794157484dca48e88effa4963e3af3 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Tue, 2 Feb 2016 16:57:35 -0800 Subject: drivers/scsi/sg.c: mark VMA as VM_IO to prevent migration Reduced testcase: #include #include #include #include #define SIZE 0x2000 int main() { int fd; void *p; fd = open("/dev/sg0", O_RDWR); p = mmap(NULL, SIZE, PROT_EXEC, MAP_PRIVATE | MAP_LOCKED, fd, 0); mbind(p, SIZE, 0, NULL, 0, MPOL_MF_MOVE); return 0; } We shouldn't try to migrate pages in sg VMA as we don't have a way to update Sg_scatter_hold::pages accordingly from mm core. Let's mark the VMA as VM_IO to indicate to mm core that the VMA is not migratable. Signed-off-by: Kirill A. Shutemov Reported-by: Dmitry Vyukov Acked-by: Vlastimil Babka Cc: Doug Gilbert Cc: David Rientjes Cc: Naoya Horiguchi Cc: "Kirill A. Shutemov" Cc: Shiraz Hashim Cc: Hugh Dickins Cc: Sasha Levin Cc: syzkaller Cc: Kostya Serebryany Cc: Alexander Potapenko Cc: James Bottomley Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/sg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 503ab8b46c0b..5e820674432c 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1261,7 +1261,7 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) } sfp->mmap_called = 1; - vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; + vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; vma->vm_private_data = sfp; vma->vm_ops = &sg_mmap_vm_ops; return 0; -- cgit v1.2.3 From c6400ba7e13a41539342f1b6e1f9e78419cb0148 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 2 Feb 2016 16:57:55 -0800 Subject: drivers/hwspinlock: fix race between radix tree insertion and lookup of_hwspin_lock_get_id() is protected by the RCU lock, which means that insertions can occur simultaneously with the lookup. If the radix tree transitions from a height of 0, we can see a slot with the indirect_ptr bit set, which will cause us to at least read random memory, and could cause other havoc. Fix this by using the newly introduced radix_tree_iter_retry(). Signed-off-by: Matthew Wilcox Cc: Hugh Dickins Cc: Ohad Ben-Cohen Cc: Konstantin Khlebnikov Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwspinlock/hwspinlock_core.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c index 52f708bcf77f..d50c701b19d6 100644 --- a/drivers/hwspinlock/hwspinlock_core.c +++ b/drivers/hwspinlock/hwspinlock_core.c @@ -313,6 +313,10 @@ int of_hwspin_lock_get_id(struct device_node *np, int index) hwlock = radix_tree_deref_slot(slot); if (unlikely(!hwlock)) continue; + if (radix_tree_is_indirect_ptr(hwlock)) { + slot = radix_tree_iter_retry(&iter); + continue; + } if (hwlock->bank->dev->of_node == args.np) { ret = 0; -- cgit v1.2.3 From 58c9d61f86e86ebe1e45ac7a0cd89a2c6299b034 Mon Sep 17 00:00:00 2001 From: Tony Camuso Date: Tue, 2 Feb 2016 13:57:24 -0500 Subject: ipmi: put acpi.h with the other headers Enclosing '#include ' within '#ifdef CONFIG_ACPI' is unnecessary, since it has its own conditional compile for CONFIG_ACPI. Commit 0fbcf4af7c83 ("ipmi: Convert the IPMI SI ACPI handling to a platform device") exposed this as a problem for platforms that do not support ACPI when it introduced a call to ACPI_PTR() macro outside of the CONFIG_ACPI conditional compile. This would have been perfectly acceptable if acpi.h were not conditionally excluded for the non-acpi platform, because the conditional compile within acpi.h defines ACPI_PTR() to return NULL when compiled for non acpi platforms. Signed-off-by: Tony Camuso Fixed commit reference in header to conform to standard. Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_si_intf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 9fda22e3387e..7fddd8696211 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -68,6 +68,7 @@ #include #include #include +#include #ifdef CONFIG_PARISC #include /* for register_parisc_driver() stuff */ @@ -2054,8 +2055,6 @@ static int hardcode_find_bmc(void) #ifdef CONFIG_ACPI -#include - /* * Once we get an ACPI failure, we don't try any more, because we go * through the tables sequentially. Once we don't find a table, there -- cgit v1.2.3 From 94c39041ae0c0e83d10bc1a56974a2eefd9386c8 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 2 Feb 2016 18:27:37 +0800 Subject: regulator: axp20x: Remove voltage readout support for switch regulators Switch-type regulators, such as DC1SW on AXP22X, are a secondary output from DCDC1. They are just an on/off switch, and the driver should not try to read its voltage directly from the DCDC1 control registers. Instead, the core will pass down the voltage from the regulator supply chain. Signed-off-by: Chen-Yu Tsai Signed-off-by: Mark Brown --- drivers/regulator/axp20x-regulator.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index f2e1a39ce0f3..fafaaa8eb8b3 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -78,8 +78,7 @@ .ops = &axp20x_ops, \ } -#define AXP_DESC_SW(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ - _vmask, _ereg, _emask) \ +#define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask) \ [_family##_##_id] = { \ .name = #_id, \ .supply_name = (_supply), \ @@ -87,12 +86,7 @@ .regulators_node = of_match_ptr("regulators"), \ .type = REGULATOR_VOLTAGE, \ .id = _family##_##_id, \ - .n_voltages = (((_max) - (_min)) / (_step) + 1), \ .owner = THIS_MODULE, \ - .min_uV = (_min) * 1000, \ - .uV_step = (_step) * 1000, \ - .vsel_reg = (_vreg), \ - .vsel_mask = (_vmask), \ .enable_reg = (_ereg), \ .enable_mask = (_emask), \ .ops = &axp20x_ops_sw, \ @@ -160,8 +154,6 @@ static struct regulator_ops axp20x_ops = { }; static struct regulator_ops axp20x_ops_sw = { - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .list_voltage = regulator_list_voltage_linear, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -196,8 +188,8 @@ static const struct regulator_desc axp22x_regulators[] = { AXP_DESC(AXP22X, DCDC5, "dcdc5", "vin5", 1000, 2550, 50, AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)), /* secondary switchable output of DCDC1 */ - AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", NULL, 1600, 3400, 100, - AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(7)), + AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2, + BIT(7)), /* LDO regulator internally chained to DCDC5 */ AXP_DESC(AXP22X, DC5LDO, "dc5ldo", NULL, 700, 1400, 100, AXP22X_DC5LDO_V_OUT, 0x7, AXP22X_PWR_OUT_CTRL1, BIT(0)), -- cgit v1.2.3 From 13d57e64352a5d3457d7782bc2f8b576e12b05f3 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 2 Feb 2016 18:27:38 +0800 Subject: regulator: axp20x: Use linear voltage ranges for AXP20X LDO4 AXP20X datasheet lists the possible voltage settings for LDO4, so it was implemented using a voltage table. Upon closer examination, the valid voltages can be mapped into 3 linear ranges. Move AXP20X LDO4 to use linear ranges. The supporting code can be reused with later AXP8xx PMICs, which have a number of regulators that have 2 linear ranges. Signed-off-by: Chen-Yu Tsai Signed-off-by: Mark Brown --- drivers/regulator/axp20x-regulator.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index fafaaa8eb8b3..7d29893f833c 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -106,8 +106,8 @@ .ops = &axp20x_ops_fixed \ } -#define AXP_DESC_TABLE(_family, _id, _match, _supply, _table, _vreg, _vmask, \ - _ereg, _emask) \ +#define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages, \ + _vreg, _vmask, _ereg, _emask) \ [_family##_##_id] = { \ .name = #_id, \ .supply_name = (_supply), \ @@ -115,30 +115,25 @@ .regulators_node = of_match_ptr("regulators"), \ .type = REGULATOR_VOLTAGE, \ .id = _family##_##_id, \ - .n_voltages = ARRAY_SIZE(_table), \ + .n_voltages = (_n_voltages), \ .owner = THIS_MODULE, \ .vsel_reg = (_vreg), \ .vsel_mask = (_vmask), \ .enable_reg = (_ereg), \ .enable_mask = (_emask), \ - .volt_table = (_table), \ - .ops = &axp20x_ops_table, \ + .linear_ranges = (_ranges), \ + .n_linear_ranges = ARRAY_SIZE(_ranges), \ + .ops = &axp20x_ops_range, \ } -static const int axp20x_ldo4_data[] = { 1250000, 1300000, 1400000, 1500000, 1600000, - 1700000, 1800000, 1900000, 2000000, 2500000, - 2700000, 2800000, 3000000, 3100000, 3200000, - 3300000 }; - static struct regulator_ops axp20x_ops_fixed = { .list_voltage = regulator_list_voltage_linear, }; -static struct regulator_ops axp20x_ops_table = { +static struct regulator_ops axp20x_ops_range = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, - .list_voltage = regulator_list_voltage_table, - .map_voltage = regulator_map_voltage_ascend, + .list_voltage = regulator_list_voltage_linear_range, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -159,6 +154,12 @@ static struct regulator_ops axp20x_ops_sw = { .is_enabled = regulator_is_enabled_regmap, }; +static const struct regulator_linear_range axp20x_ldo4_ranges[] = { + REGULATOR_LINEAR_RANGE(1250000, 0x0, 0x0, 0), + REGULATOR_LINEAR_RANGE(1300000, 0x1, 0x8, 100000), + REGULATOR_LINEAR_RANGE(2500000, 0x9, 0xf, 100000), +}; + static const struct regulator_desc axp20x_regulators[] = { AXP_DESC(AXP20X, DCDC2, "dcdc2", "vin2", 700, 2275, 25, AXP20X_DCDC2_V_OUT, 0x3f, AXP20X_PWR_OUT_CTRL, 0x10), @@ -169,8 +170,9 @@ static const struct regulator_desc axp20x_regulators[] = { AXP20X_LDO24_V_OUT, 0xf0, AXP20X_PWR_OUT_CTRL, 0x04), AXP_DESC(AXP20X, LDO3, "ldo3", "ldo3in", 700, 3500, 25, AXP20X_LDO3_V_OUT, 0x7f, AXP20X_PWR_OUT_CTRL, 0x40), - AXP_DESC_TABLE(AXP20X, LDO4, "ldo4", "ldo24in", axp20x_ldo4_data, - AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL, 0x08), + AXP_DESC_RANGES(AXP20X, LDO4, "ldo4", "ldo24in", axp20x_ldo4_ranges, + 16, AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL, + 0x08), AXP_DESC_IO(AXP20X, LDO5, "ldo5", "ldo5in", 1800, 3300, 100, AXP20X_LDO5_V_OUT, 0xf0, AXP20X_GPIO0_CTRL, 0x07, AXP20X_IO_ENABLED, AXP20X_IO_DISABLED), -- cgit v1.2.3 From a38a08dfaaab978dced63aa9cad45f0f62e23a66 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Wed, 13 Jan 2016 09:13:10 +0000 Subject: usb: phy: msm: fix error handling in probe. This driver registers for extcon events as part of its probe, but never unregisters them in case of error in the probe path. There were multiple issues noticed due to this missing error handling. One of them is random crashes if the regulators are not ready yet by the time probe is invoked. Ivan's previous attempt [1] to fix this issue, did not really address all the failure cases like regualtor/get_irq failures. [1] https://lkml.org/lkml/2015/9/7/62 Without this patch the kernel would carsh with log: ... Unable to handle kernel paging request at virtual address 17d78410 pgd = ffffffc001a5c000 [17d78410] *pgd=00000000b6806003, *pud=00000000b6806003, *pmd=0000000000000000 Internal error: Oops: 96000005 [#1] PREEMPT SMP Modules linked in: CPU: 0 PID: 6 Comm: kworker/u8:0 Not tainted 4.4.0+ #48 Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT) Workqueue: deferwq deferred_probe_work_func task: ffffffc03686e900 ti: ffffffc0368b0000 task.ti: ffffffc0368b0000 PC is at raw_notifier_chain_register+0x1c/0x44 LR is at extcon_register_notifier+0x88/0xc8 pc : [] lr : [] pstate: 80000085 sp : ffffffc0368b3a70 x29: ffffffc0368b3a70 x28: ffffffc03680c310 x27: ffffffc035518000 x26: ffffffc035518000 x25: ffffffc03bfa20e0 x24: ffffffc035580a18 x23: 0000000000000000 x22: ffffffc035518458 x21: ffffffc0355e9a60 x20: ffffffc035518000 x19: 0000000000000000 x18: 0000000000000028 x17: 0000000000000003 x16: ffffffc0018153c8 x15: 0000000000000001 x14: ffffffc03686f0f8 x13: ffffffc03686f0f8 x12: 0000000000000003 x11: 0000000000000001 x10: 0000000000000001 x9 : ffffffc03686f0f8 x8 : 0000e3872014c1a1 x7 : 0000000000000028 x6 : 0000000000000000 x5 : 0000000000000001 x4 : 0000000000000000 x3 : 00000000354fb170 x2 : 0000000017d78400 x1 : ffffffc0355e9a60 x0 : ffffffc0354fb268 Fixes: 591fc116f330 ("usb: phy: msm: Use extcon framework for VBUS and ID detection") CC: Stable Signed-off-by: Srinivas Kandagatla Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-msm-usb.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 0d19a6d61a71..970a30e155cb 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -1599,6 +1599,8 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) &motg->id.nb); if (ret < 0) { dev_err(&pdev->dev, "register ID notifier failed\n"); + extcon_unregister_notifier(motg->vbus.extcon, + EXTCON_USB, &motg->vbus.nb); return ret; } @@ -1660,15 +1662,6 @@ static int msm_otg_probe(struct platform_device *pdev) if (!motg) return -ENOMEM; - pdata = dev_get_platdata(&pdev->dev); - if (!pdata) { - if (!np) - return -ENXIO; - ret = msm_otg_read_dt(pdev, motg); - if (ret) - return ret; - } - motg->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg), GFP_KERNEL); if (!motg->phy.otg) @@ -1710,6 +1703,15 @@ static int msm_otg_probe(struct platform_device *pdev) if (!motg->regs) return -ENOMEM; + pdata = dev_get_platdata(&pdev->dev); + if (!pdata) { + if (!np) + return -ENXIO; + ret = msm_otg_read_dt(pdev, motg); + if (ret) + return ret; + } + /* * NOTE: The PHYs can be multiplexed between the chipidea controller * and the dwc3 controller, using a single bit. It is important that @@ -1717,8 +1719,10 @@ static int msm_otg_probe(struct platform_device *pdev) */ if (motg->phy_number) { phy_select = devm_ioremap_nocache(&pdev->dev, USB2_PHY_SEL, 4); - if (!phy_select) - return -ENOMEM; + if (!phy_select) { + ret = -ENOMEM; + goto unregister_extcon; + } /* Enable second PHY with the OTG port */ writel(0x1, phy_select); } @@ -1728,7 +1732,8 @@ static int msm_otg_probe(struct platform_device *pdev) motg->irq = platform_get_irq(pdev, 0); if (motg->irq < 0) { dev_err(&pdev->dev, "platform_get_irq failed\n"); - return motg->irq; + ret = motg->irq; + goto unregister_extcon; } regs[0].supply = "vddcx"; @@ -1737,7 +1742,7 @@ static int msm_otg_probe(struct platform_device *pdev) ret = devm_regulator_bulk_get(motg->phy.dev, ARRAY_SIZE(regs), regs); if (ret) - return ret; + goto unregister_extcon; motg->vddcx = regs[0].consumer; motg->v3p3 = regs[1].consumer; @@ -1834,6 +1839,12 @@ disable_clks: clk_disable_unprepare(motg->clk); if (!IS_ERR(motg->core_clk)) clk_disable_unprepare(motg->core_clk); +unregister_extcon: + extcon_unregister_notifier(motg->id.extcon, + EXTCON_USB_HOST, &motg->id.nb); + extcon_unregister_notifier(motg->vbus.extcon, + EXTCON_USB, &motg->vbus.nb); + return ret; } -- cgit v1.2.3 From 63b121e3a3167df9fdb99633fd1c840c841b07b9 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 21 Jan 2016 15:51:26 +0800 Subject: usb: phy: mxs: declare variable with initialized value Initialize vbus_value to be 0 since it's possible not to assign any value before judgement. Acked-by: Peter Chen Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-mxs-usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index c2936dc48ca7..00bfea01be65 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -220,7 +220,7 @@ static int mxs_phy_hw_init(struct mxs_phy *mxs_phy) /* Return true if the vbus is there */ static bool mxs_phy_get_vbus_status(struct mxs_phy *mxs_phy) { - unsigned int vbus_value; + unsigned int vbus_value = 0; if (!mxs_phy->regmap_anatop) return false; -- cgit v1.2.3 From 79c5623f1cb85f33403eb9f1e45124e9f56181f8 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 25 Jan 2016 13:01:29 +0100 Subject: usb: musb: ux500: Fix NULL pointer dereference at system PM The commit 7d32cdef5356 ("usb: musb: fail with error when no DMA controller set"), caused the core platform driver to correctly return an error code when fail probing. Unfurtante it also caused bug for a NULL pointer dereference, during system suspend for the ux500 driver. The reason is a lacking validation of the corresponding ->driver_data pointer, which won't be set when the musb core driver fails to probe (or haven't yet been probed). Fixes: 7d32cdef5356 ("usb: musb: fail with error when no DMA...") Acked-by: Linus Walleij Signed-off-by: Ulf Hansson Signed-off-by: Felipe Balbi --- drivers/usb/musb/ux500.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index b2685e75a683..3eaa4ba6867d 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -348,7 +348,9 @@ static int ux500_suspend(struct device *dev) struct ux500_glue *glue = dev_get_drvdata(dev); struct musb *musb = glue_to_musb(glue); - usb_phy_set_suspend(musb->xceiv, 1); + if (musb) + usb_phy_set_suspend(musb->xceiv, 1); + clk_disable_unprepare(glue->clk); return 0; @@ -366,7 +368,8 @@ static int ux500_resume(struct device *dev) return ret; } - usb_phy_set_suspend(musb->xceiv, 0); + if (musb) + usb_phy_set_suspend(musb->xceiv, 0); return 0; } -- cgit v1.2.3 From e79aee49bcf9ad005b3f2f4cf68b17dc2c22d9c2 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 30 Jan 2016 12:54:29 +0100 Subject: PM: Avoid false-positive warnings in dev_pm_domain_set() There is a WARN_ON() in dev_pm_domain_set() that triggers on attempts to set the pm_domain pointer for devices with a driver bound. However, that WARN_ON() triggers on attempts to clear the pointer too and the test it uses is based on checking the device's p->knode_driver pointer which still is set when the device bus type's/driver's ->remove callback has been executed. This leads to false-positive warnings when bus type code calls dev_pm_domain_set() to clear the pm_domain pointer after invoking the driver's ->remove() callback. To avoid those false-positives, make dev_pm_domain_set() check if the pointer passed to it is NULL and skip the warning in that case. Fixes: 989561de9b51 (PM / Domains: add setter for dev.pm_domain) Signed-off-by: Rafael J. Wysocki Tested-by: Andy Shevchenko Tested-by: Sinan Kaya Tested-by: Steven Rostedt Acked-by: Ulf Hansson --- drivers/base/power/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c index 93ed14cc2252..f6a9ad52cbbf 100644 --- a/drivers/base/power/common.c +++ b/drivers/base/power/common.c @@ -146,7 +146,7 @@ void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd) if (dev->pm_domain == pd) return; - WARN(device_is_bound(dev), + WARN(pd && device_is_bound(dev), "PM domains can only be changed for unbound devices\n"); dev->pm_domain = pd; device_pm_check_callbacks(dev); -- cgit v1.2.3 From 03b32e4c9bd1b52fcf1e4304e7a704aa0315e398 Mon Sep 17 00:00:00 2001 From: John Youn Date: Mon, 11 Jan 2016 16:32:14 -0800 Subject: Revert "usb: dwc2: Move reset into dwc2_get_hwparams()" This reverts commit 263b7fb557f7 ("usb: dwc2: Move reset into dwc2_get_hwparams()") due to regression found on bcm2835 platform. USB ethernet fails, due to being unable to pick up proper parameters when performing a plain reset before reading hw params. Below shows the results of the gnptxfsiz and hptxfsiz with and before and after reverting this (from Stefan Wahren): So here is the probe result before Patch 1 is applied: [ 1.283148] dwc2 20980000.usb: Configuration mismatch. dr_mode forced to host [ 1.313894] dwc2 20980000.usb: gnptxfsiz=00201000 [ 1.314104] dwc2 20980000.usb: hptxfsiz=00000000 [ 1.353908] dwc2 20980000.usb: 256 invalid for host_nperio_tx_fifo_size. Check HW configuration. [ 1.354262] dwc2 20980000.usb: 512 invalid for host_perio_tx_fifo_size. Check HW configuration. [ 1.394249] dwc2 20980000.usb: DWC OTG Controller [ 1.394561] dwc2 20980000.usb: new USB bus registered, assigned bus number 1 [ 1.394917] dwc2 20980000.usb: irq 33, io mem 0x00000000 And here is the probe result after Patch 1 is applied: [ 1.280107] dwc2 20980000.usb: Configuration mismatch. dr_mode forced to host [ 1.353949] dwc2 20980000.usb: gnptxfsiz=01001000 [ 1.354166] dwc2 20980000.usb: hptxfsiz=02002000 [ 1.434301] dwc2 20980000.usb: DWC OTG Controller [ 1.434616] dwc2 20980000.usb: new USB bus registered, assigned bus number 1 [ 1.434973] dwc2 20980000.usb: irq 33, io mem 0x00000000 Tested-by: Heiko Stuebner Tested-by: Douglas Anderson Signed-off-by: John Youn Reported-by: Stefan Wahren Reported-by: Remi Pommarel Tested-by: Stefan Wahren Tested-by: Remi Pommarel Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/core.c | 8 -------- drivers/usb/dwc2/platform.c | 8 +++++++- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 39a0fa8a4c0a..1489d315f287 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -3278,9 +3278,6 @@ static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg) /** * During device initialization, read various hardware configuration * registers and interpret the contents. - * - * This should be called during driver probe. It will perform a core - * soft reset in order to get the reset values of the parameters. */ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) { @@ -3288,7 +3285,6 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) unsigned width; u32 hwcfg1, hwcfg2, hwcfg3, hwcfg4; u32 grxfsiz; - int retval; /* * Attempt to ensure this device is really a DWC_otg Controller. @@ -3308,10 +3304,6 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) hw->snpsid >> 12 & 0xf, hw->snpsid >> 8 & 0xf, hw->snpsid >> 4 & 0xf, hw->snpsid & 0xf, hw->snpsid); - retval = dwc2_core_reset(hsotg); - if (retval) - return retval; - hwcfg1 = dwc2_readl(hsotg->regs + GHWCFG1); hwcfg2 = dwc2_readl(hsotg->regs + GHWCFG2); hwcfg3 = dwc2_readl(hsotg->regs + GHWCFG3); diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 510f787434b3..690b9fd98b55 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -530,7 +530,13 @@ static int dwc2_driver_probe(struct platform_device *dev) if (retval) return retval; - /* Reset the controller and detect hardware config values */ + /* + * Reset before dwc2_get_hwparams() then it could get power-on real + * reset value form registers. + */ + dwc2_core_reset_and_force_dr_mode(hsotg); + + /* Detect config values from hardware */ retval = dwc2_get_hwparams(hsotg); if (retval) goto error; -- cgit v1.2.3 From 192cb07f7928e8cb09a9851e6c0f7478baa3bc6d Mon Sep 17 00:00:00 2001 From: John Youn Date: Mon, 11 Jan 2016 16:32:28 -0800 Subject: usb: dwc2: Fix probe problem on bcm2835 Fixes an issue found on Raspberry PI platform that prevents probe. Don't skip setting the force mode if it's already set. Fixes: 09c96980dc72 ("usb: dwc2: Add functions to set and clear force mode") Tested-by: Heiko Stuebner Tested-by: Douglas Anderson Signed-off-by: John Youn Reported-by: Stefan Wahren Reported-by: Remi Pommarel Tested-by: Stefan Wahren Tested-by: Remi Pommarel Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/core.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 1489d315f287..e991d55914db 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -572,12 +572,6 @@ static bool dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host) set = host ? GUSBCFG_FORCEHOSTMODE : GUSBCFG_FORCEDEVMODE; clear = host ? GUSBCFG_FORCEDEVMODE : GUSBCFG_FORCEHOSTMODE; - /* - * If the force mode bit is already set, don't set it. - */ - if ((gusbcfg & set) && !(gusbcfg & clear)) - return false; - gusbcfg &= ~clear; gusbcfg |= set; dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG); -- cgit v1.2.3 From de4726649b6b1d7f3f02b2031ee99e067cb71e2d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 22 Jan 2016 18:32:31 +0000 Subject: drm/i915: Allow i915_gem_object_get_page() on userptr as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 033908aed5a596f6202c848c6bbc8a40fb1a8490 Author: Dave Gordon Date: Thu Dec 10 18:51:23 2015 +0000 drm/i915: mark GEM object pages dirty when mapped & written by the CPU introduced a check into i915_gem_object_get_dirty_pages() that returned a NULL pointer when called with a bad object, one that was not backed by shmemfs. This WARN was too strict as we can work on all struct page backed objects, and resulted in a WARN + GPF for existing userspace. In order to differentiate the various types of objects, add a new flags field to the i915_gem_object_ops struct to describe their capabilities, with the first flag being whether the object has struct pages. v2: Drop silly const before an integer in the structure declaration. Testcase: igt/gem_userptr_blits/relocations Reported-and-tested-by: Kristian Høgsberg Kristensen Signed-off-by: Chris Wilson Cc: Dave Gordon Cc: Kristian Høgsberg Kristensen Cc: Daniel Vetter Reviewed-by: Dave Gordon Reviewed-by: Kristian Høgsberg Kristensen Tested-by: Michal Winiarski Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1453487551-16799-1-git-send-email-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 4 ++++ drivers/gpu/drm/i915/i915_gem.c | 3 ++- drivers/gpu/drm/i915/i915_gem_userptr.c | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 65a2cd04bc8f..77227a39f3d5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2038,6 +2038,9 @@ enum hdmi_force_audio { #define I915_GTT_OFFSET_NONE ((u32)-1) struct drm_i915_gem_object_ops { + unsigned int flags; +#define I915_GEM_OBJECT_HAS_STRUCT_PAGE 0x1 + /* Interface between the GEM object and its backing storage. * get_pages() is called once prior to the use of the associated set * of pages before to binding them into the GTT, and put_pages() is @@ -2053,6 +2056,7 @@ struct drm_i915_gem_object_ops { */ int (*get_pages)(struct drm_i915_gem_object *); void (*put_pages)(struct drm_i915_gem_object *); + int (*dmabuf_export)(struct drm_i915_gem_object *); void (*release)(struct drm_i915_gem_object *); }; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a928823507c5..e9b19bca1383 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4465,6 +4465,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj, } static const struct drm_i915_gem_object_ops i915_gem_object_ops = { + .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE, .get_pages = i915_gem_object_get_pages_gtt, .put_pages = i915_gem_object_put_pages_gtt, }; @@ -5309,7 +5310,7 @@ i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n) struct page *page; /* Only default objects have per-page dirty tracking */ - if (WARN_ON(obj->ops != &i915_gem_object_ops)) + if (WARN_ON((obj->ops->flags & I915_GEM_OBJECT_HAS_STRUCT_PAGE) == 0)) return NULL; page = i915_gem_object_get_page(obj, n); diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 74a4d1714879..7107f2fd38f5 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -708,9 +708,10 @@ i915_gem_userptr_dmabuf_export(struct drm_i915_gem_object *obj) } static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = { - .dmabuf_export = i915_gem_userptr_dmabuf_export, + .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE, .get_pages = i915_gem_userptr_get_pages, .put_pages = i915_gem_userptr_put_pages, + .dmabuf_export = i915_gem_userptr_dmabuf_export, .release = i915_gem_userptr_release, }; -- cgit v1.2.3 From 6357b75a5c356a9d8f91c614ab72ac5264a5932c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 2 Feb 2016 18:22:24 -0500 Subject: drm/amdgpu: disable uvd and vce clockgating on Fiji MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Doesn't work properly yet. Reviewed-by: Christian König Reviewed-by: Sonny Jiang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index d94c625575b9..89f5a1ff6f43 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -1443,8 +1443,7 @@ static int vi_common_early_init(void *handle) break; case CHIP_FIJI: adev->has_uvd = true; - adev->cg_flags = AMDGPU_CG_SUPPORT_UVD_MGCG | - AMDGPU_CG_SUPPORT_VCE_MGCG; + adev->cg_flags = 0; adev->pg_flags = 0; adev->external_rev_id = adev->rev_id + 0x3c; break; -- cgit v1.2.3 From fcc5184ec1521c7d85124421e593660c94e9a9fb Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 25 Jan 2016 15:42:04 -0500 Subject: USB: EHCI: store reason for unlinking a QH This patch replaces the "exception" bitflag in the ehci_qh structure with a more explicit "unlink_reason" bitmask. This is for use in the following patch, where we will need to have a good idea of the reason for unlinking a QH, not just "something exceptional happened". Signed-off-by: Alan Stern Tested-by: Michael Reutman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 11 +++++++---- drivers/usb/host/ehci-q.c | 13 +++++++++---- drivers/usb/host/ehci-sched.c | 2 +- drivers/usb/host/ehci-timer.c | 1 + drivers/usb/host/ehci.h | 10 ++++++++-- 5 files changed, 26 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 00e77cc91053..c5465bf9a798 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -911,7 +911,7 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) */ } else { qh = (struct ehci_qh *) urb->hcpriv; - qh->exception = 1; + qh->unlink_reason |= QH_UNLINK_REQUESTED; switch (qh->qh_state) { case QH_STATE_LINKED: if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) @@ -972,10 +972,13 @@ rescan: goto done; } - qh->exception = 1; + qh->unlink_reason |= QH_UNLINK_REQUESTED; switch (qh->qh_state) { case QH_STATE_LINKED: - WARN_ON(!list_empty(&qh->qtd_list)); + if (list_empty(&qh->qtd_list)) + qh->unlink_reason |= QH_UNLINK_QUEUE_EMPTY; + else + WARN_ON(1); if (usb_endpoint_type(&ep->desc) != USB_ENDPOINT_XFER_INT) start_unlink_async(ehci, qh); else @@ -1042,7 +1045,7 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) * re-linking will call qh_refresh(). */ usb_settoggle(qh->ps.udev, epnum, is_out, 0); - qh->exception = 1; + qh->unlink_reason |= QH_UNLINK_REQUESTED; if (eptype == USB_ENDPOINT_XFER_BULK) start_unlink_async(ehci, qh); else diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index aad0777240d3..1b42bcb59743 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -394,6 +394,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) goto retry_xacterr; } stopped = 1; + qh->unlink_reason |= QH_UNLINK_HALTED; /* magic dummy for some short reads; qh won't advance. * that silicon quirk can kick in with this dummy too. @@ -408,6 +409,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) && !(qtd->hw_alt_next & EHCI_LIST_END(ehci))) { stopped = 1; + qh->unlink_reason |= QH_UNLINK_SHORT_READ; } /* stop scanning when we reach qtds the hc is using */ @@ -420,8 +422,10 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) stopped = 1; /* cancel everything if we halt, suspend, etc */ - if (ehci->rh_state < EHCI_RH_RUNNING) + if (ehci->rh_state < EHCI_RH_RUNNING) { last_status = -ESHUTDOWN; + qh->unlink_reason |= QH_UNLINK_SHUTDOWN; + } /* this qtd is active; skip it unless a previous qtd * for its urb faulted, or its urb was canceled. @@ -538,10 +542,10 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) * except maybe high bandwidth ... */ if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) - qh->exception = 1; + qh->unlink_reason |= QH_UNLINK_DUMMY_OVERLAY; /* Let the caller know if the QH needs to be unlinked. */ - return qh->exception; + return qh->unlink_reason; } /*-------------------------------------------------------------------------*/ @@ -1003,7 +1007,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) qh->qh_state = QH_STATE_LINKED; qh->xacterrs = 0; - qh->exception = 0; + qh->unlink_reason = 0; /* qtd completions reported later by interrupt */ enable_async(ehci); @@ -1395,6 +1399,7 @@ static void unlink_empty_async(struct ehci_hcd *ehci) /* If nothing else is being unlinked, unlink the last empty QH */ if (list_empty(&ehci->async_unlink) && qh_to_unlink) { + qh_to_unlink->unlink_reason |= QH_UNLINK_QUEUE_EMPTY; start_unlink_async(ehci, qh_to_unlink); --count; } diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index f9a332775c47..c1704a57e803 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -595,7 +595,7 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) } qh->qh_state = QH_STATE_LINKED; qh->xacterrs = 0; - qh->exception = 0; + qh->unlink_reason = 0; /* update per-qh bandwidth for debugfs */ ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->ps.bw_period diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index 424ac5d83714..37a3e0dece84 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c @@ -237,6 +237,7 @@ static void ehci_handle_start_intr_unlinks(struct ehci_hcd *ehci) ehci->intr_unlink_wait_cycle)) break; list_del_init(&qh->unlink_node); + qh->unlink_reason |= QH_UNLINK_QUEUE_EMPTY; start_unlink_intr(ehci, qh); } diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index ec61aedb0067..f11b9dc53981 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -432,13 +432,19 @@ struct ehci_qh { u8 xacterrs; /* XactErr retry counter */ #define QH_XACTERR_MAX 32 /* XactErr retry limit */ + u8 unlink_reason; +#define QH_UNLINK_HALTED 0x01 /* Halt flag is set */ +#define QH_UNLINK_SHORT_READ 0x02 /* Recover from a short read */ +#define QH_UNLINK_DUMMY_OVERLAY 0x04 /* QH overlayed the dummy TD */ +#define QH_UNLINK_SHUTDOWN 0x08 /* The HC isn't running */ +#define QH_UNLINK_QUEUE_EMPTY 0x10 /* Reached end of the queue */ +#define QH_UNLINK_REQUESTED 0x20 /* Disable, reset, or dequeue */ + u8 gap_uf; /* uframes split/csplit gap */ unsigned is_out:1; /* bulk or intr OUT */ unsigned clearing_tt:1; /* Clear-TT-Buf in progress */ unsigned dequeue_during_giveback:1; - unsigned exception:1; /* got a fault, or an unlink - was requested */ unsigned should_be_inactive:1; }; -- cgit v1.2.3 From f96fba0dbf8f6b0eaa313b4c230f93c9bb0dd759 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 25 Jan 2016 15:44:16 -0500 Subject: USB: EHCI: improve handling of the ehci->iaa_in_progress flag This patch improves the way ehci-hcd handles the iaa_in_progress flag. The current code is somewhat careless in this regard: The flag is meaningless when the root hub isn't running, most particularly after the root hub has been suspended. But in start_iaa_cycle(), the driver checks the flag before checking the root hub's state. They should be checked in the opposite order. That routine also sets the flag too early, before it has definitely committed to starting an IAA cycle. The flag is turned off in end_unlink_async(). Upcoming changes will call that routine at other times, not just at the end of an IAA cycle. The two actions are logically separate (although related), so we separate out a new routine to be called in place of end_unlink_async() whenever an IAA cycle ends: end_iaa_cycle(). iaa_in_progress should be turned off when the root hub is suspended -- we certainly don't want it still to be set when the root hub resumes. Therefore the call to end_unlink_async() in ehci_bus_suspend() should also be replaced with a call to end_iaa_cycle(). Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 3 ++- drivers/usb/host/ehci-hub.c | 3 ++- drivers/usb/host/ehci-q.c | 28 +++++++++++++++------------- drivers/usb/host/ehci-timer.c | 2 +- 4 files changed, 20 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c5465bf9a798..84c41262109c 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -306,6 +306,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci) /*-------------------------------------------------------------------------*/ +static void end_iaa_cycle(struct ehci_hcd *ehci); static void end_unlink_async(struct ehci_hcd *ehci); static void unlink_empty_async(struct ehci_hcd *ehci); static void unlink_empty_async_suspended(struct ehci_hcd *ehci); @@ -758,7 +759,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) ehci_dbg(ehci, "IAA with IAAD still set?\n"); if (ehci->iaa_in_progress) COUNT(ehci->stats.iaa); - end_unlink_async(ehci); + end_iaa_cycle(ehci); } /* remote wakeup [4.3.1] */ diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 086a7115d263..6d84ce2edc27 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -347,7 +347,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) goto done; ehci->rh_state = EHCI_RH_SUSPENDED; - end_unlink_async(ehci); + /* Any IAA cycle that started before the suspend is now invalid */ + end_iaa_cycle(ehci); unlink_empty_async_suspended(ehci); ehci_handle_start_intr_unlinks(ehci); ehci_handle_intr_unlinks(ehci); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 1b42bcb59743..15dcae8f0631 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1283,17 +1283,13 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh) static void start_iaa_cycle(struct ehci_hcd *ehci) { - /* Do nothing if an IAA cycle is already running */ - if (ehci->iaa_in_progress) - return; - ehci->iaa_in_progress = true; - /* If the controller isn't running, we don't have to wait for it */ if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) { end_unlink_async(ehci); - /* Otherwise start a new IAA cycle */ - } else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) { + /* Otherwise start a new IAA cycle if one isn't already running */ + } else if (ehci->rh_state == EHCI_RH_RUNNING && + !ehci->iaa_in_progress) { /* Make sure the unlinks are all visible to the hardware */ wmb(); @@ -1301,17 +1297,13 @@ static void start_iaa_cycle(struct ehci_hcd *ehci) ehci_writel(ehci, ehci->command | CMD_IAAD, &ehci->regs->command); ehci_readl(ehci, &ehci->regs->command); + ehci->iaa_in_progress = true; ehci_enable_event(ehci, EHCI_HRTIMER_IAA_WATCHDOG, true); } } -/* the async qh for the qtds being unlinked are now gone from the HC */ - -static void end_unlink_async(struct ehci_hcd *ehci) +static void end_iaa_cycle(struct ehci_hcd *ehci) { - struct ehci_qh *qh; - bool early_exit; - if (ehci->has_synopsys_hc_bug) ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next); @@ -1319,6 +1311,16 @@ static void end_unlink_async(struct ehci_hcd *ehci) /* The current IAA cycle has ended */ ehci->iaa_in_progress = false; + end_unlink_async(ehci); +} + +/* See if the async qh for the qtds being unlinked are now gone from the HC */ + +static void end_unlink_async(struct ehci_hcd *ehci) +{ + struct ehci_qh *qh; + bool early_exit; + if (list_empty(&ehci->async_unlink)) return; qh = list_first_entry(&ehci->async_unlink, struct ehci_qh, diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index 37a3e0dece84..6bea4d553ec5 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c @@ -361,7 +361,7 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci) } ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd); - end_unlink_async(ehci); + end_iaa_cycle(ehci); } -- cgit v1.2.3 From 87d61912c23a746ee9a8a8d2fe17af217c87f761 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 25 Jan 2016 15:45:25 -0500 Subject: USB: EHCI: add a delay when unlinking an active QH Michael Reutman reports that an AMD/ATI EHCI host controller on one of his computers does not stop transferring data when an active bulk QH is unlinked from the async schedule. Apparently that host controller fails to implement the IAA mechanism correctly when an active QH is unlinked. This leads to data corruption, because the controller continues to update the QH in memory when the driver doesn't expect it. As a result, the next URB submitted for that QH can hang, because the link pointers for the TD queue have been messed up. This misbehavior is observed quite regularly. To be fair, the EHCI spec (section 4.8.2) says that active QHs should not be unlinked. It goes on to recommend a procedure that involves waiting for the QH to go inactive before unlinking it. In the real world this is impractical, not least because the QH may _never_ go inactive. (What were they thinking?) Sometimes we have no choice but to unlink an active QH. In an attempt to avoid the problems that can ensue, this patch changes how the driver decides when the unlink is complete. In addition to waiting through two IAA cycles, in cases where the QH was not known to be inactive beforehand we now wait until a 2-ms period has elapsed with the host controller making no change to the QH data structure (the hw_current and hw_token fields in particular). The intuition here is that after such a long period, the endpoint must be NAKing and hopefully the QH has been dropped from the host controller's internal cache. There's no way to know if this reasoning is really valid -- the spec is no help in this regard -- but at least this approach fixes Michael's problem. The test for whether the QH is already known to be inactive involves the reason for unlinking the QH originally. If it was unlinked because it had halted, or it stopped in response to a short read, or it overlaid a dummy TD (a silicon bug), then it certainly is inactive. If it was unlinked because the TD queue was empty and no TDs have been added to the queue in the meantime, then it must be inactive. Or if the hardware status indicates that the QH is currently halted (even if that wasn't the reason for unlinking it), then it is inactive. Otherwise, if none of those checks apply, we go through the 2-ms delay. Signed-off-by: Alan Stern Reported-by: Michael Reutman Tested-by: Michael Reutman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 3 +++ drivers/usb/host/ehci-q.c | 56 +++++++++++++++++++++++++++++++++++++++---- drivers/usb/host/ehci-timer.c | 2 ++ drivers/usb/host/ehci.h | 3 +++ 4 files changed, 59 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 84c41262109c..a93d445b63a4 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -566,6 +566,9 @@ static int ehci_init(struct usb_hcd *hcd) /* Accept arbitrarily long scatter-gather lists */ if (!(hcd->driver->flags & HCD_LOCAL_MEM)) hcd->self.sg_tablesize = ~0; + + /* Prepare for unlinking active QHs */ + ehci->old_current = ~0; return 0; } diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 15dcae8f0631..a24341ef863d 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1341,14 +1341,60 @@ static void end_unlink_async(struct ehci_hcd *ehci) * after the IAA interrupt occurs. In self-defense, always go * through two IAA cycles for each QH. */ - else if (qh->qh_state == QH_STATE_UNLINK_WAIT) { + else if (qh->qh_state == QH_STATE_UNLINK) { + /* + * Second IAA cycle has finished. Process only the first + * waiting QH (NVIDIA (?) bug). + */ + list_move_tail(&qh->unlink_node, &ehci->async_idle); + } + + /* + * AMD/ATI (?) bug: The HC can continue to use an active QH long + * after the IAA interrupt occurs. To prevent problems, QHs that + * may still be active will wait until 2 ms have passed with no + * change to the hw_current and hw_token fields (this delay occurs + * between the two IAA cycles). + * + * The EHCI spec (4.8.2) says that active QHs must not be removed + * from the async schedule and recommends waiting until the QH + * goes inactive. This is ridiculous because the QH will _never_ + * become inactive if the endpoint NAKs indefinitely. + */ + + /* Some reasons for unlinking guarantee the QH can't be active */ + else if (qh->unlink_reason & (QH_UNLINK_HALTED | + QH_UNLINK_SHORT_READ | QH_UNLINK_DUMMY_OVERLAY)) + goto DelayDone; + + /* The QH can't be active if the queue was and still is empty... */ + else if ((qh->unlink_reason & QH_UNLINK_QUEUE_EMPTY) && + list_empty(&qh->qtd_list)) + goto DelayDone; + + /* ... or if the QH has halted */ + else if (qh->hw->hw_token & cpu_to_hc32(ehci, QTD_STS_HALT)) + goto DelayDone; + + /* Otherwise we have to wait until the QH stops changing */ + else { + __hc32 qh_current, qh_token; + + qh_current = qh->hw->hw_current; + qh_token = qh->hw->hw_token; + if (qh_current != ehci->old_current || + qh_token != ehci->old_token) { + ehci->old_current = qh_current; + ehci->old_token = qh_token; + ehci_enable_event(ehci, + EHCI_HRTIMER_ACTIVE_UNLINK, true); + return; + } + DelayDone: qh->qh_state = QH_STATE_UNLINK; early_exit = true; } - - /* Otherwise process only the first waiting QH (NVIDIA bug?) */ - else - list_move_tail(&qh->unlink_node, &ehci->async_idle); + ehci->old_current = ~0; /* Prepare for next QH */ /* Start a new IAA cycle if any QHs are waiting for it */ if (!list_empty(&ehci->async_unlink)) diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index 6bea4d553ec5..69f50e6533a6 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c @@ -72,6 +72,7 @@ static unsigned event_delays_ns[] = { 1 * NSEC_PER_MSEC, /* EHCI_HRTIMER_POLL_DEAD */ 1125 * NSEC_PER_USEC, /* EHCI_HRTIMER_UNLINK_INTR */ 2 * NSEC_PER_MSEC, /* EHCI_HRTIMER_FREE_ITDS */ + 2 * NSEC_PER_MSEC, /* EHCI_HRTIMER_ACTIVE_UNLINK */ 5 * NSEC_PER_MSEC, /* EHCI_HRTIMER_START_UNLINK_INTR */ 6 * NSEC_PER_MSEC, /* EHCI_HRTIMER_ASYNC_UNLINKS */ 10 * NSEC_PER_MSEC, /* EHCI_HRTIMER_IAA_WATCHDOG */ @@ -395,6 +396,7 @@ static void (*event_handlers[])(struct ehci_hcd *) = { ehci_handle_controller_death, /* EHCI_HRTIMER_POLL_DEAD */ ehci_handle_intr_unlinks, /* EHCI_HRTIMER_UNLINK_INTR */ end_free_itds, /* EHCI_HRTIMER_FREE_ITDS */ + end_unlink_async, /* EHCI_HRTIMER_ACTIVE_UNLINK */ ehci_handle_start_intr_unlinks, /* EHCI_HRTIMER_START_UNLINK_INTR */ unlink_empty_async, /* EHCI_HRTIMER_ASYNC_UNLINKS */ ehci_iaa_watchdog, /* EHCI_HRTIMER_IAA_WATCHDOG */ diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index f11b9dc53981..b13894550139 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -110,6 +110,7 @@ enum ehci_hrtimer_event { EHCI_HRTIMER_POLL_DEAD, /* Wait for dead controller to stop */ EHCI_HRTIMER_UNLINK_INTR, /* Wait for interrupt QH unlink */ EHCI_HRTIMER_FREE_ITDS, /* Wait for unused iTDs and siTDs */ + EHCI_HRTIMER_ACTIVE_UNLINK, /* Wait while unlinking an active QH */ EHCI_HRTIMER_START_UNLINK_INTR, /* Unlink empty interrupt QHs */ EHCI_HRTIMER_ASYNC_UNLINKS, /* Unlink empty async QHs */ EHCI_HRTIMER_IAA_WATCHDOG, /* Handle lost IAA interrupts */ @@ -156,6 +157,8 @@ struct ehci_hcd { /* one per controller */ struct list_head async_idle; unsigned async_unlink_cycle; unsigned async_count; /* async activity count */ + __hc32 old_current; /* Test for QH becoming */ + __hc32 old_token; /* inactive during unlink */ /* periodic schedule support */ #define DEFAULT_I_TDPS 1024 /* some HCs can do less */ -- cgit v1.2.3 From 8df0d77d8ce065ef536676fb4e1f36bfbf1dd809 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 25 Jan 2016 15:45:38 -0500 Subject: USB: EHCI: improvements to unlink_empty_async_suspended() unlink_empty_async_suspended() is marked __maybe_unused. This is because its caller, ehci_bus_suspend(), is protected by "#ifdef CONFIG_PM". We should use the same protection here instead of __maybe_unused. unlink_empty_async_suspended() gets called only when the root hub is suspended. It's silly for it to call start_iaa_cycle() at such a time; the IAA mechanism doesn't work when the root hub isn't running. It should call end_unlink_async() instead. But even this isn't necessary, since there already is a call to end_iaa_cycle() right before the call to unlink_empty_async_suspended(). All we have to do is interchange the two subroutine calls. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hub.c | 3 ++- drivers/usb/host/ehci-q.c | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 6d84ce2edc27..6333d3c2be9c 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -347,9 +347,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) goto done; ehci->rh_state = EHCI_RH_SUSPENDED; + unlink_empty_async_suspended(ehci); + /* Any IAA cycle that started before the suspend is now invalid */ end_iaa_cycle(ehci); - unlink_empty_async_suspended(ehci); ehci_handle_start_intr_unlinks(ehci); ehci_handle_intr_unlinks(ehci); end_free_itds(ehci); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index a24341ef863d..eca3710d8fc4 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1459,8 +1459,10 @@ static void unlink_empty_async(struct ehci_hcd *ehci) } } +#ifdef CONFIG_PM + /* The root hub is suspended; unlink all the async QHs */ -static void __maybe_unused unlink_empty_async_suspended(struct ehci_hcd *ehci) +static void unlink_empty_async_suspended(struct ehci_hcd *ehci) { struct ehci_qh *qh; @@ -1469,9 +1471,10 @@ static void __maybe_unused unlink_empty_async_suspended(struct ehci_hcd *ehci) WARN_ON(!list_empty(&qh->qtd_list)); single_unlink_async(ehci, qh); } - start_iaa_cycle(ehci); } +#endif + /* makes sure the async qh will become idle */ /* caller must own ehci->lock */ -- cgit v1.2.3 From 0caf6b33452112e5a1186c8c964e90310e49e6bd Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Mon, 25 Jan 2016 15:30:44 +0200 Subject: xhci: Make sure xhci handles USB_SPEED_SUPER_PLUS devices. In most cases the devices with the speed set to USB_SPEED_SUPER_PLUS are handled like regular SuperSpeed devices. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 9 ++++++--- drivers/usb/host/xhci-ring.c | 3 ++- drivers/usb/host/xhci.c | 7 +++++-- 3 files changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 5cd080e0a685..9c3da214a515 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1070,7 +1070,7 @@ static u32 xhci_find_real_port_number(struct xhci_hcd *xhci, struct usb_device *top_dev; struct usb_hcd *hcd; - if (udev->speed == USB_SPEED_SUPER) + if (udev->speed >= USB_SPEED_SUPER) hcd = xhci->shared_hcd; else hcd = xhci->main_hcd; @@ -1105,6 +1105,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud /* 3) Only the control endpoint is valid - one endpoint context */ slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | udev->route); switch (udev->speed) { + case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS); max_packets = MAX_PACKET(512); @@ -1292,6 +1293,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev, } /* Fall through - SS and HS isoc/int have same decoding */ + case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: if (usb_endpoint_xfer_int(&ep->desc) || usb_endpoint_xfer_isoc(&ep->desc)) { @@ -1332,7 +1334,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev, static u32 xhci_get_endpoint_mult(struct usb_device *udev, struct usb_host_endpoint *ep) { - if (udev->speed != USB_SPEED_SUPER || + if (udev->speed < USB_SPEED_SUPER || !usb_endpoint_xfer_isoc(&ep->desc)) return 0; return ep->ss_ep_comp.bmAttributes; @@ -1382,7 +1384,7 @@ static u32 xhci_get_max_esit_payload(struct usb_device *udev, usb_endpoint_xfer_bulk(&ep->desc)) return 0; - if (udev->speed == USB_SPEED_SUPER) + if (udev->speed >= USB_SPEED_SUPER) return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval); max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); @@ -1453,6 +1455,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); max_burst = 0; switch (udev->speed) { + case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: /* dig out max burst from ep companion desc */ max_burst = ep->ss_ep_comp.bMaxBurst; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index f1c21c40b4a6..cd336226ad47 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3573,7 +3573,7 @@ static unsigned int xhci_get_burst_count(struct xhci_hcd *xhci, { unsigned int max_burst; - if (xhci->hci_version < 0x100 || udev->speed != USB_SPEED_SUPER) + if (xhci->hci_version < 0x100 || udev->speed < USB_SPEED_SUPER) return 0; max_burst = urb->ep->ss_ep_comp.bMaxBurst; @@ -3599,6 +3599,7 @@ static unsigned int xhci_get_last_burst_packet_count(struct xhci_hcd *xhci, return 0; switch (udev->speed) { + case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: /* bMaxBurst is zero based: 0 means 1 packet per burst */ max_burst = urb->ep->ss_ep_comp.bMaxBurst; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 26a44c0e969e..32d23e1301b8 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2084,6 +2084,7 @@ static unsigned int xhci_get_block_size(struct usb_device *udev) case USB_SPEED_HIGH: return HS_BLOCK; case USB_SPEED_SUPER: + case USB_SPEED_SUPER_PLUS: return SS_BLOCK; case USB_SPEED_UNKNOWN: case USB_SPEED_WIRELESS: @@ -2209,7 +2210,7 @@ static int xhci_check_bw_table(struct xhci_hcd *xhci, unsigned int packets_remaining = 0; unsigned int i; - if (virt_dev->udev->speed == USB_SPEED_SUPER) + if (virt_dev->udev->speed >= USB_SPEED_SUPER) return xhci_check_ss_bw(xhci, virt_dev); if (virt_dev->udev->speed == USB_SPEED_HIGH) { @@ -2410,7 +2411,7 @@ void xhci_drop_ep_from_interval_table(struct xhci_hcd *xhci, if (xhci_is_async_ep(ep_bw->type)) return; - if (udev->speed == USB_SPEED_SUPER) { + if (udev->speed >= USB_SPEED_SUPER) { if (xhci_is_sync_in_ep(ep_bw->type)) xhci->devs[udev->slot_id]->bw_table->ss_bw_in -= xhci_get_ss_bw_consumed(ep_bw); @@ -2448,6 +2449,7 @@ void xhci_drop_ep_from_interval_table(struct xhci_hcd *xhci, interval_bw->overhead[HS_OVERHEAD_TYPE] -= 1; break; case USB_SPEED_SUPER: + case USB_SPEED_SUPER_PLUS: case USB_SPEED_UNKNOWN: case USB_SPEED_WIRELESS: /* Should never happen because only LS/FS/HS endpoints will get @@ -2507,6 +2509,7 @@ static void xhci_add_ep_to_interval_table(struct xhci_hcd *xhci, interval_bw->overhead[HS_OVERHEAD_TYPE] += 1; break; case USB_SPEED_SUPER: + case USB_SPEED_SUPER_PLUS: case USB_SPEED_UNKNOWN: case USB_SPEED_WIRELESS: /* Should never happen because only LS/FS/HS endpoints will get -- cgit v1.2.3 From 2c0e06f8829a542e71b14ffcaa14b8fafa2223c3 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Mon, 25 Jan 2016 15:30:45 +0200 Subject: xhci: set roothub speed to USB_SPEED_SUPER_PLUS for USB3.1 capable controllers Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 32d23e1301b8..503d82fb0dd5 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4898,6 +4898,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) if (xhci->sbrn == 0x31) { xhci_info(xhci, "Host supports USB 3.1 Enhanced SuperSpeed\n"); hcd->speed = HCD_USB31; + hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; } /* xHCI private pointer was set in xhci_pci_probe for the second * registered roothub. -- cgit v1.2.3 From 5da665fcec1a308f5273aacb9da8e87b89da8b4f Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Mon, 25 Jan 2016 15:30:46 +0200 Subject: xhci: USB 3.1 add default Speed Attributes to SuperSpeedPlus device capability If a xhci controller does not provide a protocol speed ID (PSI) table, a default one should be used instead. Add the default values to the SuperSpeedPlus device capability. Overwrite the default ones if a PSI table exists. See xHCI 1.1 sectio 7.2.2.1.1 for more info Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hub.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index b30b4ce294d3..d61fcc48099e 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -50,14 +50,18 @@ static u8 usb_bos_descriptor [] = { 0x00, /* bU1DevExitLat, set later. */ 0x00, 0x00, /* __le16 bU2DevExitLat, set later. */ /* Second device capability, SuperSpeedPlus */ - 0x0c, /* bLength 12, will be adjusted later */ + 0x1c, /* bLength 28, will be adjusted later */ USB_DT_DEVICE_CAPABILITY, /* Device Capability */ USB_SSP_CAP_TYPE, /* bDevCapabilityType SUPERSPEED_PLUS */ 0x00, /* bReserved 0 */ - 0x00, 0x00, 0x00, 0x00, /* bmAttributes, get from xhci psic */ - 0x00, 0x00, /* wFunctionalitySupport */ + 0x23, 0x00, 0x00, 0x00, /* bmAttributes, SSAC=3 SSIC=1 */ + 0x01, 0x00, /* wFunctionalitySupport */ 0x00, 0x00, /* wReserved 0 */ - /* Sublink Speed Attributes are added in xhci_create_usb3_bos_desc() */ + /* Default Sublink Speed Attributes, overwrite if custom PSI exists */ + 0x34, 0x00, 0x05, 0x00, /* 5Gbps, symmetric, rx, ID = 4 */ + 0xb4, 0x00, 0x05, 0x00, /* 5Gbps, symmetric, tx, ID = 4 */ + 0x35, 0x40, 0x0a, 0x00, /* 10Gbps, SSP, symmetric, rx, ID = 5 */ + 0xb5, 0x40, 0x0a, 0x00, /* 10Gbps, SSP, symmetric, tx, ID = 5 */ }; static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf, @@ -72,10 +76,14 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf, ssp_cap_size = sizeof(usb_bos_descriptor) - desc_size; /* does xhci support USB 3.1 Enhanced SuperSpeed */ - if (xhci->usb3_rhub.min_rev >= 0x01 && xhci->usb3_rhub.psi_uid_count) { - /* two SSA entries for each unique PSI ID, one RX and one TX */ - ssa_count = xhci->usb3_rhub.psi_uid_count * 2; - ssa_size = ssa_count * sizeof(u32); + if (xhci->usb3_rhub.min_rev >= 0x01) { + /* does xhci provide a PSI table for SSA speed attributes? */ + if (xhci->usb3_rhub.psi_count) { + /* two SSA entries for each unique PSI ID, RX and TX */ + ssa_count = xhci->usb3_rhub.psi_uid_count * 2; + ssa_size = ssa_count * sizeof(u32); + ssp_cap_size -= 16; /* skip copying the default SSA */ + } desc_size += ssp_cap_size; usb3_1 = true; } @@ -102,7 +110,8 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf, put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]); } - if (usb3_1) { + /* If PSI table exists, add the custom speed attributes from it */ + if (usb3_1 && xhci->usb3_rhub.psi_count) { u32 ssp_cap_base, bm_attrib, psi; int offset; -- cgit v1.2.3 From d78540419866887345cec480016b0f87f6a5aca2 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Mon, 25 Jan 2016 15:30:47 +0200 Subject: xhci: set slot context speed field to SuperSpeedPlus for USB 3.1 SSP devices The speed field of the input slot context should represent the speed the device is working at. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 3 +++ drivers/usb/host/xhci.h | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 9c3da214a515..42f2bec759aa 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1106,6 +1106,9 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | udev->route); switch (udev->speed) { case USB_SPEED_SUPER_PLUS: + slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SSP); + max_packets = MAX_PACKET(512); + break; case USB_SPEED_SUPER: slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS); max_packets = MAX_PACKET(512); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 9be7348872ba..9f28bea65fed 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -343,6 +343,7 @@ struct xhci_op_regs { #define SLOT_SPEED_LS (XDEV_LS << 10) #define SLOT_SPEED_HS (XDEV_HS << 10) #define SLOT_SPEED_SS (XDEV_SS << 10) +#define SLOT_SPEED_SSP (XDEV_SSP << 10) /* Port Indicator Control */ #define PORT_LED_OFF (0 << 14) #define PORT_LED_AMBER (1 << 14) -- cgit v1.2.3 From 5363de75307e333d89df7531f9dd8310d973ecdb Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 25 Jan 2016 20:30:30 +0100 Subject: usb: core: switch bus numbering to using idr USB bus numbering is based on directly dealing with bitmaps and defines a separate list of busses. This can be simplified and unified by using existing idr functionality. Signed-off-by: Heiner Kallweit Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devices.c | 10 ++-------- drivers/usb/core/hcd.c | 21 ++++++--------------- drivers/usb/core/usb.c | 1 + drivers/usb/host/r8a66597-hcd.c | 9 ++------- drivers/usb/mon/mon_main.c | 5 ++--- include/linux/usb.h | 1 - include/linux/usb/hcd.h | 3 ++- 7 files changed, 15 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index b35a6a52210f..6118a04f0b84 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -110,13 +110,6 @@ static const char format_endpt[] = /* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */ "E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%d%cs\n"; - -/* - * Need access to the driver and USB bus lists. - * extern struct list_head usb_bus_list; - * However, these will come from functions that return ptrs to each of them. - */ - /* * Wait for an connect/disconnect event to happen. We initialize * the event counter with an odd number, and each event will increment @@ -618,6 +611,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, struct usb_bus *bus; ssize_t ret, total_written = 0; loff_t skip_bytes = *ppos; + int id; if (*ppos < 0) return -EINVAL; @@ -628,7 +622,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, mutex_lock(&usb_bus_list_lock); /* print devices for all busses */ - list_for_each_entry(bus, &usb_bus_list, bus_list) { + idr_for_each_entry(&usb_bus_idr, bus, id) { /* recurse through all children of the root hub */ if (!bus_to_hcd(bus)->rh_registered) continue; diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 232c8c93dd3a..cf3eb22dbeb4 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -90,12 +90,11 @@ unsigned long usb_hcds_loaded; EXPORT_SYMBOL_GPL(usb_hcds_loaded); /* host controllers we manage */ -LIST_HEAD (usb_bus_list); -EXPORT_SYMBOL_GPL (usb_bus_list); +DEFINE_IDR (usb_bus_idr); +EXPORT_SYMBOL_GPL (usb_bus_idr); /* used when allocating bus numbers */ #define USB_MAXBUS 64 -static DECLARE_BITMAP(busmap, USB_MAXBUS); /* used when updating list of hcds */ DEFINE_MUTEX(usb_bus_list_lock); /* exported only for usbfs */ @@ -996,8 +995,6 @@ static void usb_bus_init (struct usb_bus *bus) bus->bandwidth_int_reqs = 0; bus->bandwidth_isoc_reqs = 0; mutex_init(&bus->usb_address0_mutex); - - INIT_LIST_HEAD (&bus->bus_list); } /*-------------------------------------------------------------------------*/ @@ -1018,16 +1015,12 @@ static int usb_register_bus(struct usb_bus *bus) int busnum; mutex_lock(&usb_bus_list_lock); - busnum = find_next_zero_bit(busmap, USB_MAXBUS, 1); - if (busnum >= USB_MAXBUS) { - printk (KERN_ERR "%s: too many buses\n", usbcore_name); + busnum = idr_alloc(&usb_bus_idr, bus, 1, USB_MAXBUS, GFP_KERNEL); + if (busnum < 0) { + pr_err("%s: failed to get bus number\n", usbcore_name); goto error_find_busnum; } - set_bit(busnum, busmap); bus->busnum = busnum; - - /* Add it to the local list of buses */ - list_add (&bus->bus_list, &usb_bus_list); mutex_unlock(&usb_bus_list_lock); usb_notify_add_bus(bus); @@ -1059,12 +1052,10 @@ static void usb_deregister_bus (struct usb_bus *bus) * itself up */ mutex_lock(&usb_bus_list_lock); - list_del (&bus->bus_list); + idr_remove(&usb_bus_idr, bus->busnum); mutex_unlock(&usb_bus_list_lock); usb_notify_remove_bus(bus); - - clear_bit(bus->busnum, busmap); } /** diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 16ade41759cd..524c9822d2bb 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -1115,6 +1115,7 @@ static void __exit usb_exit(void) bus_unregister(&usb_bus_type); usb_acpi_unregister(); usb_debugfs_cleanup(); + idr_destroy(&usb_bus_idr); } subsys_initcall(usb_init); diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 4cbd0633c5c2..1ef887361ac0 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2099,13 +2099,8 @@ static void r8a66597_check_detect_child(struct r8a66597 *r8a66597, memset(now_map, 0, sizeof(now_map)); - list_for_each_entry(bus, &usb_bus_list, bus_list) { - if (!bus->root_hub) - continue; - - if (bus->busnum != hcd->self.busnum) - continue; - + bus = idr_find(&usb_bus_idr, hcd->self.busnum); + if (bus && bus->root_hub) { collect_usb_address_map(bus->root_hub, now_map); update_usb_address_map(r8a66597, bus->root_hub, now_map); } diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index fec3f1128fdc..9b87efb0e50d 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c @@ -349,7 +349,7 @@ struct mon_bus *mon_bus_lookup(unsigned int num) static int __init mon_init(void) { struct usb_bus *ubus; - int rc; + int rc, id; if ((rc = mon_text_init()) != 0) goto err_text; @@ -366,9 +366,8 @@ static int __init mon_init(void) // MOD_INC_USE_COUNT(which_module?); mutex_lock(&usb_bus_list_lock); - list_for_each_entry (ubus, &usb_bus_list, bus_list) { + idr_for_each_entry(&usb_bus_idr, ubus, id) mon_bus_init(ubus); - } usb_register_notify(&mon_nb); mutex_unlock(&usb_bus_list_lock); return 0; diff --git a/include/linux/usb.h b/include/linux/usb.h index 89533ba38691..0d348fa84a66 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -375,7 +375,6 @@ struct usb_bus { struct usb_devmap devmap; /* device address allocation map */ struct usb_device *root_hub; /* Root hub */ struct usb_bus *hs_companion; /* Companion EHCI bus, if any */ - struct list_head bus_list; /* list of busses */ struct mutex usb_address0_mutex; /* unaddressed device mutex */ diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 4dcf8446dbcd..c293dd044599 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -23,6 +23,7 @@ #include #include +#include #define MAX_TOPO_LEVEL 6 @@ -630,7 +631,7 @@ extern void usb_set_device_state(struct usb_device *udev, /* exported only within usbcore */ -extern struct list_head usb_bus_list; +extern struct idr usb_bus_idr; extern struct mutex usb_bus_list_lock; extern wait_queue_head_t usb_kill_urb_queue; -- cgit v1.2.3 From 7dd9cba5bb90ffa9c60c1533b715dc91c5082cd9 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 21 Jan 2016 15:18:47 +0100 Subject: usb: sysfs: make locking interruptible 232275a USB: fix substandard locking for the sysfs files introduced needed locking into sysfs operations on USB devices It, however, uses uninterruptible sleep and if the error handling is on extreme cases of sleep lengths of 10s of seconds are possible. Unless we are removing the device we should use interruptible sleep. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/sysfs.c | 69 ++++++++++++++++++++++++++++++++++-------------- include/linux/device.h | 5 ++++ include/linux/usb.h | 7 ++--- 3 files changed, 58 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index f195320d35c0..7a6209314997 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -23,10 +23,12 @@ static ssize_t field##_show(struct device *dev, \ { \ struct usb_device *udev; \ struct usb_host_config *actconfig; \ - ssize_t rc = 0; \ + ssize_t rc; \ \ udev = to_usb_device(dev); \ - usb_lock_device(udev); \ + rc = usb_lock_device_interruptible(udev); \ + if (rc < 0) \ + return -EINTR; \ actconfig = udev->actconfig; \ if (actconfig) \ rc = sprintf(buf, format_string, \ @@ -47,10 +49,12 @@ static ssize_t bMaxPower_show(struct device *dev, { struct usb_device *udev; struct usb_host_config *actconfig; - ssize_t rc = 0; + ssize_t rc; udev = to_usb_device(dev); - usb_lock_device(udev); + rc = usb_lock_device_interruptible(udev); + if (rc < 0) + return -EINTR; actconfig = udev->actconfig; if (actconfig) rc = sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig)); @@ -64,10 +68,12 @@ static ssize_t configuration_show(struct device *dev, { struct usb_device *udev; struct usb_host_config *actconfig; - ssize_t rc = 0; + ssize_t rc; udev = to_usb_device(dev); - usb_lock_device(udev); + rc = usb_lock_device_interruptible(udev); + if (rc < 0) + return -EINTR; actconfig = udev->actconfig; if (actconfig && actconfig->string) rc = sprintf(buf, "%s\n", actconfig->string); @@ -84,11 +90,13 @@ static ssize_t bConfigurationValue_store(struct device *dev, const char *buf, size_t count) { struct usb_device *udev = to_usb_device(dev); - int config, value; + int config, value, rc; if (sscanf(buf, "%d", &config) != 1 || config < -1 || config > 255) return -EINVAL; - usb_lock_device(udev); + rc = usb_lock_device_interruptible(udev); + if (rc < 0) + return -EINTR; value = usb_set_configuration(udev, config); usb_unlock_device(udev); return (value < 0) ? value : count; @@ -105,7 +113,9 @@ static ssize_t name##_show(struct device *dev, \ int retval; \ \ udev = to_usb_device(dev); \ - usb_lock_device(udev); \ + retval = usb_lock_device_interruptible(udev); \ + if (retval < 0) \ + return -EINTR; \ retval = sprintf(buf, "%s\n", udev->name); \ usb_unlock_device(udev); \ return retval; \ @@ -227,11 +237,13 @@ static ssize_t avoid_reset_quirk_store(struct device *dev, const char *buf, size_t count) { struct usb_device *udev = to_usb_device(dev); - int val; + int val, rc; if (sscanf(buf, "%d", &val) != 1 || val < 0 || val > 1) return -EINVAL; - usb_lock_device(udev); + rc = usb_lock_device_interruptible(udev); + if (rc < 0) + return -EINTR; if (val) udev->quirks |= USB_QUIRK_RESET; else @@ -297,7 +309,7 @@ static ssize_t persist_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct usb_device *udev = to_usb_device(dev); - int value; + int value, rc; /* Hubs are always enabled for USB_PERSIST */ if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) @@ -306,7 +318,9 @@ static ssize_t persist_store(struct device *dev, struct device_attribute *attr, if (sscanf(buf, "%d", &value) != 1) return -EINVAL; - usb_lock_device(udev); + rc = usb_lock_device_interruptible(udev); + if (rc < 0) + return -EINTR; udev->persist_enabled = !!value; usb_unlock_device(udev); return count; @@ -423,13 +437,16 @@ static ssize_t level_store(struct device *dev, struct device_attribute *attr, int len = count; char *cp; int rc = count; + int rv; warn_level(); cp = memchr(buf, '\n', count); if (cp) len = cp - buf; - usb_lock_device(udev); + rv = usb_lock_device_interruptible(udev); + if (rv < 0) + return -EINTR; if (len == sizeof on_string - 1 && strncmp(buf, on_string, len) == 0) @@ -469,7 +486,9 @@ static ssize_t usb2_hardware_lpm_store(struct device *dev, bool value; int ret; - usb_lock_device(udev); + ret = usb_lock_device_interruptible(udev); + if (ret < 0) + return -EINTR; ret = strtobool(buf, &value); @@ -539,8 +558,11 @@ static ssize_t usb3_hardware_lpm_u1_show(struct device *dev, { struct usb_device *udev = to_usb_device(dev); const char *p; + int rc; - usb_lock_device(udev); + rc = usb_lock_device_interruptible(udev); + if (rc < 0) + return -EINTR; if (udev->usb3_lpm_u1_enabled) p = "enabled"; @@ -558,8 +580,11 @@ static ssize_t usb3_hardware_lpm_u2_show(struct device *dev, { struct usb_device *udev = to_usb_device(dev); const char *p; + int rc; - usb_lock_device(udev); + rc = usb_lock_device_interruptible(udev); + if (rc < 0) + return -EINTR; if (udev->usb3_lpm_u2_enabled) p = "enabled"; @@ -818,14 +843,16 @@ read_descriptors(struct file *filp, struct kobject *kobj, struct usb_device *udev = to_usb_device(dev); size_t nleft = count; size_t srclen, n; - int cfgno; + int cfgno, rc; void *src; /* The binary attribute begins with the device descriptor. * Following that are the raw descriptor entries for all the * configurations (config plus subsidiary descriptors). */ - usb_lock_device(udev); + rc = usb_lock_device_interruptible(udev); + if (rc < 0) + return -EINTR; for (cfgno = -1; cfgno < udev->descriptor.bNumConfigurations && nleft > 0; ++cfgno) { if (cfgno < 0) { @@ -972,7 +999,9 @@ static ssize_t supports_autosuspend_show(struct device *dev, { int s; - device_lock(dev); + s = device_lock_interruptible(dev); + if (s < 0) + return -EINTR; /* Devices will be autosuspended even when an interface isn't claimed */ s = (!dev->driver || to_usb_driver(dev->driver)->supports_autosuspend); device_unlock(dev); diff --git a/include/linux/device.h b/include/linux/device.h index 6d6f1fec092f..2d0e6e541d52 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -958,6 +958,11 @@ static inline void device_lock(struct device *dev) mutex_lock(&dev->mutex); } +static inline int device_lock_interruptible(struct device *dev) +{ + return mutex_lock_interruptible(&dev->mutex); +} + static inline int device_trylock(struct device *dev) { return mutex_trylock(&dev->mutex); diff --git a/include/linux/usb.h b/include/linux/usb.h index 0d348fa84a66..dc0ea0de8a81 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -641,9 +641,10 @@ extern struct usb_device *usb_hub_find_child(struct usb_device *hdev, if (!child) continue; else /* USB device locking */ -#define usb_lock_device(udev) device_lock(&(udev)->dev) -#define usb_unlock_device(udev) device_unlock(&(udev)->dev) -#define usb_trylock_device(udev) device_trylock(&(udev)->dev) +#define usb_lock_device(udev) device_lock(&(udev)->dev) +#define usb_unlock_device(udev) device_unlock(&(udev)->dev) +#define usb_lock_device_interruptible(udev) device_lock_interruptible(&(udev)->dev) +#define usb_trylock_device(udev) device_trylock(&(udev)->dev) extern int usb_lock_device_for_reset(struct usb_device *udev, const struct usb_interface *iface); -- cgit v1.2.3 From b4a90d04ac79349799f65dfd7fa30b2aac6b2a4d Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 21 Jan 2016 15:18:48 +0100 Subject: usb: no locking for reading descriptors in sysfs Quting the relevant thread: > In fact, I suspect the locking added by the kernel 3.13 commit for > read_descriptors() is invalid because read_descriptors() performs no USB > activity; read_descriptors() just reads information from an allocated > memory structure. This structure is protected as the structure is > existing before and after the sysfs vfs descriptors entry is created or > destroyed. You're right. For some reason I thought that usb_deauthorize_device() would destroy the rawdescriptor structures (as mentioned in that commit's Changelog), but it doesn't. The locking in read_descriptors() is unnecessary. > The information is only written at the time of enumeration > and does not change. At least that is my understanding. > > It is noted that in our testing of kernel 3.8 on ARM, that sysfs > read_descriptors() was non-blocking because the kernel 3.13 comment was > not there. > > The pre-kernel 3.13 sysfs read_descriptors() seemed to work OK. > > Proposal: > ========= > > Remove the usb_lock_device(udev) and usb_unlock_device(udev) from > devices/usb/core/sysfs.c in read_descriptors() that was added by the > kernel 3.13 commit > "232275a USB: fix substandard locking for the sysfs files" > > Any comments to this proposal ? It seems okay to me. Please submit a patch. So this removes the locking making the point about -EINTR in the first path moot. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/sysfs.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 7a6209314997..c953a0f1c695 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -843,16 +843,13 @@ read_descriptors(struct file *filp, struct kobject *kobj, struct usb_device *udev = to_usb_device(dev); size_t nleft = count; size_t srclen, n; - int cfgno, rc; + int cfgno; void *src; /* The binary attribute begins with the device descriptor. * Following that are the raw descriptor entries for all the * configurations (config plus subsidiary descriptors). */ - rc = usb_lock_device_interruptible(udev); - if (rc < 0) - return -EINTR; for (cfgno = -1; cfgno < udev->descriptor.bNumConfigurations && nleft > 0; ++cfgno) { if (cfgno < 0) { @@ -873,7 +870,6 @@ read_descriptors(struct file *filp, struct kobject *kobj, off -= srclen; } } - usb_unlock_device(udev); return count - nleft; } -- cgit v1.2.3 From 1c17a353c5a8346b1ce128c60ffb862d156f7e7e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 25 Jan 2016 16:21:54 +0100 Subject: usb: gadget: rndis: fix itnull.cocci warnings The index variable of list_for_each_entry_safe is an offset from a list pointer, and thus should not be NULL. Generated by: scripts/coccinelle/iterators/itnull.cocci CC: Geliang Tang Signed-off-by: Fengguang Wu Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/rndis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c index 34a76db2c8fd..943c21aafd3b 100644 --- a/drivers/usb/gadget/function/rndis.c +++ b/drivers/usb/gadget/function/rndis.c @@ -1009,7 +1009,7 @@ void rndis_free_response(struct rndis_params *params, u8 *buf) rndis_resp_t *r, *n; list_for_each_entry_safe(r, n, ¶ms->resp_queue, list) { - if (r && r->buf == buf) { + if (r->buf == buf) { list_del(&r->list); kfree(r); } -- cgit v1.2.3 From b5566d074d163f052283ec5f5df643a023feebc0 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:44 -0300 Subject: usb: host: ehci.h: remove space before comma Get rid of spaces before comma. Caught by checkpatch: "ERROR: space prohibited before that ','" Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index b13894550139..54a69d8b0abe 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -861,13 +861,13 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) /*-------------------------------------------------------------------------*/ #define ehci_dbg(ehci, fmt, args...) \ - dev_dbg(ehci_to_hcd(ehci)->self.controller , fmt , ## args) + dev_dbg(ehci_to_hcd(ehci)->self.controller, fmt, ## args) #define ehci_err(ehci, fmt, args...) \ - dev_err(ehci_to_hcd(ehci)->self.controller , fmt , ## args) + dev_err(ehci_to_hcd(ehci)->self.controller, fmt, ## args) #define ehci_info(ehci, fmt, args...) \ - dev_info(ehci_to_hcd(ehci)->self.controller , fmt , ## args) + dev_info(ehci_to_hcd(ehci)->self.controller, fmt, ## args) #define ehci_warn(ehci, fmt, args...) \ - dev_warn(ehci_to_hcd(ehci)->self.controller , fmt , ## args) + dev_warn(ehci_to_hcd(ehci)->self.controller, fmt, ## args) #ifndef CONFIG_DYNAMIC_DEBUG -- cgit v1.2.3 From e06e2264a3c9922c6f20c5ee020e9ba96b6917ab Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:45 -0300 Subject: usb: host: ehci.h: remove space before function open parenthesis Get rid of space between function name and open parenthesis. Caught by checkpatch: "WARNING: space prohibited between function name and open parenthesis '('" Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 54a69d8b0abe..8d1943cbfc7a 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -271,13 +271,13 @@ struct ehci_hcd { /* one per controller */ }; /* convert between an HCD pointer and the corresponding EHCI_HCD */ -static inline struct ehci_hcd *hcd_to_ehci (struct usb_hcd *hcd) +static inline struct ehci_hcd *hcd_to_ehci(struct usb_hcd *hcd) { return (struct ehci_hcd *) (hcd->hcd_priv); } -static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci) +static inline struct usb_hcd *ehci_to_hcd(struct ehci_hcd *ehci) { - return container_of ((void *) ehci, struct usb_hcd, hcd_priv); + return container_of((void *) ehci, struct usb_hcd, hcd_priv); } /*-------------------------------------------------------------------------*/ @@ -330,9 +330,9 @@ struct ehci_qtd { } __attribute__ ((aligned (32))); /* mask NakCnt+T in qh->hw_alt_next */ -#define QTD_MASK(ehci) cpu_to_hc32 (ehci, ~0x1f) +#define QTD_MASK(ehci) cpu_to_hc32(ehci, ~0x1f) -#define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1) +#define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1) /*-------------------------------------------------------------------------*/ @@ -815,7 +815,7 @@ static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational) #define ehci_big_endian_desc(e) ((e)->big_endian_desc) /* cpu to ehci */ -static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x) +static inline __hc32 cpu_to_hc32(const struct ehci_hcd *ehci, const u32 x) { return ehci_big_endian_desc(ehci) ? (__force __hc32)cpu_to_be32(x) @@ -823,14 +823,14 @@ static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x) } /* ehci to cpu */ -static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x) +static inline u32 hc32_to_cpu(const struct ehci_hcd *ehci, const __hc32 x) { return ehci_big_endian_desc(ehci) ? be32_to_cpu((__force __be32)x) : le32_to_cpu((__force __le32)x); } -static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) +static inline u32 hc32_to_cpup(const struct ehci_hcd *ehci, const __hc32 *x) { return ehci_big_endian_desc(ehci) ? be32_to_cpup((__force __be32 *)x) @@ -840,18 +840,18 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) #else /* cpu to ehci */ -static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x) +static inline __hc32 cpu_to_hc32(const struct ehci_hcd *ehci, const u32 x) { return cpu_to_le32(x); } /* ehci to cpu */ -static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x) +static inline u32 hc32_to_cpu(const struct ehci_hcd *ehci, const __hc32 x) { return le32_to_cpu(x); } -static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) +static inline u32 hc32_to_cpup(const struct ehci_hcd *ehci, const __hc32 *x) { return le32_to_cpup(x); } -- cgit v1.2.3 From 9dc3af5ed21fa7ec8ccd315a10b1f9a7771b244b Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:46 -0300 Subject: usb: host: ehci.h: remove space before open square bracket Get rid of space before open square bracket. Caught by checkpatch: "ERROR: space prohibited before open square bracket '['" Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 8d1943cbfc7a..484ab1a09166 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -188,7 +188,7 @@ struct ehci_hcd { /* one per controller */ struct ehci_sitd *last_sitd_to_free; /* per root hub port */ - unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; + unsigned long reset_done[EHCI_MAX_ROOT_PORTS]; /* bit vectors (one bit per port) */ unsigned long bus_suspended; /* which ports were @@ -319,8 +319,8 @@ struct ehci_qtd { #define HALT_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_HALT) #define STATUS_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_STS) - __hc32 hw_buf [5]; /* see EHCI 3.5.4 */ - __hc32 hw_buf_hi [5]; /* Appendix B */ + __hc32 hw_buf[5]; /* see EHCI 3.5.4 */ + __hc32 hw_buf_hi[5]; /* Appendix B */ /* the rest is HCD-private */ dma_addr_t qtd_dma; /* qtd address */ @@ -408,8 +408,8 @@ struct ehci_qh_hw { __hc32 hw_qtd_next; __hc32 hw_alt_next; __hc32 hw_token; - __hc32 hw_buf [5]; - __hc32 hw_buf_hi [5]; + __hc32 hw_buf[5]; + __hc32 hw_buf_hi[5]; } __attribute__ ((aligned(32))); struct ehci_qh { @@ -471,7 +471,7 @@ struct ehci_iso_sched { struct list_head td_list; unsigned span; unsigned first_packet; - struct ehci_iso_packet packet [0]; + struct ehci_iso_packet packet[0]; }; /* @@ -519,7 +519,7 @@ struct ehci_iso_stream { struct ehci_itd { /* first part defined by EHCI spec */ __hc32 hw_next; /* see EHCI 3.3.1 */ - __hc32 hw_transaction [8]; /* see EHCI 3.3.2 */ + __hc32 hw_transaction[8]; /* see EHCI 3.3.2 */ #define EHCI_ISOC_ACTIVE (1<<31) /* activate transfer this slot */ #define EHCI_ISOC_BUF_ERR (1<<30) /* Data buffer error */ #define EHCI_ISOC_BABBLE (1<<29) /* babble detected */ @@ -529,8 +529,8 @@ struct ehci_itd { #define ITD_ACTIVE(ehci) cpu_to_hc32(ehci, EHCI_ISOC_ACTIVE) - __hc32 hw_bufp [7]; /* see EHCI 3.3.3 */ - __hc32 hw_bufp_hi [7]; /* Appendix B */ + __hc32 hw_bufp[7]; /* see EHCI 3.3.3 */ + __hc32 hw_bufp_hi[7]; /* Appendix B */ /* the rest is HCD-private */ dma_addr_t itd_dma; /* for this itd */ @@ -574,9 +574,9 @@ struct ehci_sitd { #define SITD_ACTIVE(ehci) cpu_to_hc32(ehci, SITD_STS_ACTIVE) - __hc32 hw_buf [2]; /* EHCI table 3-12 */ + __hc32 hw_buf[2]; /* EHCI table 3-12 */ __hc32 hw_backpointer; /* EHCI table 3-13 */ - __hc32 hw_buf_hi [2]; /* Appendix B */ + __hc32 hw_buf_hi[2]; /* Appendix B */ /* the rest is HCD-private */ dma_addr_t sitd_dma; -- cgit v1.2.3 From bc4beadabf53a26268b12c930557b364fd4e2b28 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:47 -0300 Subject: usb: host: ehci.h: fix single statement macros Don't use the 'do {} while (0)' wrapper in a single statement macro. Caught by checkpatch: "WARNING: Single statement macros should not use a do {} while (0) loop" Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 484ab1a09166..06e20bc3ebb8 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -247,9 +247,9 @@ struct ehci_hcd { /* one per controller */ /* irq statistics */ #ifdef EHCI_STATS struct ehci_stats stats; -# define COUNT(x) do { (x)++; } while (0) +# define COUNT(x) ((x)++) #else -# define COUNT(x) do {} while (0) +# define COUNT(x) #endif /* debug files */ -- cgit v1.2.3 From 3a9e742f3c2cc63167abe10ea8099861dde28085 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:48 -0300 Subject: usb: host: ehci.h: remove direct use of __attribute__ keyword Prefer to use __aligned(size) macro instead of __attribute__((aligned(size))). Caught by checkpatch. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 06e20bc3ebb8..29b9617fd503 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -327,7 +327,7 @@ struct ehci_qtd { struct list_head qtd_list; /* sw qtd list */ struct urb *urb; /* qtd's urb */ size_t length; /* length of buffer */ -} __attribute__ ((aligned (32))); +} __aligned(32); /* mask NakCnt+T in qh->hw_alt_next */ #define QTD_MASK(ehci) cpu_to_hc32(ehci, ~0x1f) @@ -410,7 +410,7 @@ struct ehci_qh_hw { __hc32 hw_token; __hc32 hw_buf[5]; __hc32 hw_buf_hi[5]; -} __attribute__ ((aligned(32))); +} __aligned(32); struct ehci_qh { struct ehci_qh_hw *hw; /* Must come first */ @@ -544,7 +544,7 @@ struct ehci_itd { unsigned frame; /* where scheduled */ unsigned pg; unsigned index[8]; /* in urb->iso_frame_desc */ -} __attribute__ ((aligned (32))); +} __aligned(32); /*-------------------------------------------------------------------------*/ @@ -587,7 +587,7 @@ struct ehci_sitd { struct list_head sitd_list; /* list of stream's sitds */ unsigned frame; unsigned index; -} __attribute__ ((aligned (32))); +} __aligned(32); /*-------------------------------------------------------------------------*/ @@ -607,7 +607,7 @@ struct ehci_fstn { /* the rest is HCD-private */ dma_addr_t fstn_dma; union ehci_shadow fstn_next; /* ptr to periodic q entry */ -} __attribute__ ((aligned (32))); +} __aligned(32); /*-------------------------------------------------------------------------*/ -- cgit v1.2.3 From 10f2b962e65d4ef346ecacbb28f768f273b2a060 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:49 -0300 Subject: usb: host: ehci.h: use space after comma Put space after comma. This patch also changes QH_NEXT macro for better reading. Caught by checkpatch: "ERROR: space required after that ','" Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 29b9617fd503..bbed8750afb2 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -337,7 +337,7 @@ struct ehci_qtd { /*-------------------------------------------------------------------------*/ /* type tag from {qh,itd,sitd,fstn}->hw_next */ -#define Q_NEXT_TYPE(ehci,dma) ((dma) & cpu_to_hc32(ehci, 3 << 1)) +#define Q_NEXT_TYPE(ehci, dma) ((dma) & cpu_to_hc32(ehci, 3 << 1)) /* * Now the following defines are not converted using the @@ -353,7 +353,8 @@ struct ehci_qtd { #define Q_TYPE_FSTN (3 << 1) /* next async queue entry, or pointer to interrupt/periodic QH */ -#define QH_NEXT(ehci,dma) (cpu_to_hc32(ehci, (((u32)dma)&~0x01f)|Q_TYPE_QH)) +#define QH_NEXT(ehci, dma) \ + (cpu_to_hc32(ehci, (((u32) dma) & ~0x01f) | Q_TYPE_QH)) /* for periodic/async schedules and qtd lists, mark end of list */ #define EHCI_LIST_END(ehci) cpu_to_hc32(ehci, 1) /* "null pointer" to hw */ -- cgit v1.2.3 From 8af0219eea6387248f0d46b47742bb8c83b1b4f3 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:50 -0300 Subject: usb: host: ehci.h: remove macros trailing semicolon Removes trailing semicolon from macros. Caught by checkpatch: "WARNING: macros should not use a trailing semicolon" Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index bbed8750afb2..e587d4529e7a 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -644,10 +644,10 @@ struct ehci_tt { /* Prepare the PORTSC wakeup flags during controller suspend/resume */ #define ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup) \ - ehci_adjust_port_wakeup_flags(ehci, true, do_wakeup); + ehci_adjust_port_wakeup_flags(ehci, true, do_wakeup) #define ehci_prepare_ports_for_controller_resume(ehci) \ - ehci_adjust_port_wakeup_flags(ehci, false, false); + ehci_adjust_port_wakeup_flags(ehci, false, false) /*-------------------------------------------------------------------------*/ -- cgit v1.2.3 From c021170f1da3448d398614b6bc546f3dee256979 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:51 -0300 Subject: usb: host: ehci.h: move pointer operator to name side The pointer operator must be sticked to name. Caught by checkpatch: ERROR: "foo * bar" should be "foo *bar" Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index e587d4529e7a..30bf43750c67 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -741,7 +741,7 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc) #endif static inline unsigned int ehci_readl(const struct ehci_hcd *ehci, - __u32 __iomem * regs) + __u32 __iomem *regs) { #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO return ehci_big_endian_mmio(ehci) ? -- cgit v1.2.3 From 4510a072c60855d0e28000cbb3d7c718801023de Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:52 -0300 Subject: usb: host: ehci.h: move constant to right This patch moves the constant 0x3ff to right and put spaces in the right shift. Caught by coccinelle: scripts/coccinelle/misc/compare_const_fl.cocci Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 30bf43750c67..d1b29b36b347 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -564,7 +564,7 @@ struct ehci_sitd { __hc32 hw_results; /* EHCI table 3-11 */ #define SITD_IOC (1 << 31) /* interrupt on completion */ #define SITD_PAGE (1 << 30) /* buffer 0/1 */ -#define SITD_LENGTH(x) (0x3ff & ((x)>>16)) +#define SITD_LENGTH(x) (((x) >> 16) & 0x3ff) #define SITD_STS_ACTIVE (1 << 7) /* HC may execute this */ #define SITD_STS_ERR (1 << 6) /* error from TT */ #define SITD_STS_DBE (1 << 5) /* data buffer error (in HC) */ -- cgit v1.2.3 From 668ab0db27cbb4857d0f207d78bff2f96b537e13 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:53 -0300 Subject: usb: host: ehci-dbg: remove space before open parenthesis This patch fixes coding style issues reported by checkpatch. The vast majority of changes in this patch are removing spaces before opening parenthesis, but in some cases, a few additional changes are made to fix other coding style issues. These additional changes are: - Spaces around >> on line 50. - On line 55 a call to ehci_dbg reduced to a single line. - sizeof operands surrounded with parenthesis on lines 877, 883, 889 and 901. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 199 ++++++++++++++++++++++---------------------- 1 file changed, 99 insertions(+), 100 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index b7d623f1523c..fcbbdfa25766 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -24,41 +24,40 @@ * (host controller _Structural_ parameters) * see EHCI spec, Table 2-4 for each value */ -static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) +static void dbg_hcs_params(struct ehci_hcd *ehci, char *label) { u32 params = ehci_readl(ehci, &ehci->caps->hcs_params); - ehci_dbg (ehci, + ehci_dbg(ehci, "%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d\n", label, params, - HCS_DEBUG_PORT (params), - HCS_INDICATOR (params) ? " ind" : "", - HCS_N_CC (params), - HCS_N_PCC (params), - HCS_PORTROUTED (params) ? "" : " ordered", - HCS_PPC (params) ? "" : " !ppc", - HCS_N_PORTS (params) + HCS_DEBUG_PORT(params), + HCS_INDICATOR(params) ? " ind" : "", + HCS_N_CC(params), + HCS_N_PCC(params), + HCS_PORTROUTED(params) ? "" : " ordered", + HCS_PPC(params) ? "" : " !ppc", + HCS_N_PORTS(params) ); /* Port routing, per EHCI 0.95 Spec, Section 2.2.5 */ - if (HCS_PORTROUTED (params)) { + if (HCS_PORTROUTED(params)) { int i; char buf [46], tmp [7], byte; buf[0] = 0; - for (i = 0; i < HCS_N_PORTS (params); i++) { + for (i = 0; i < HCS_N_PORTS(params); i++) { // FIXME MIPS won't readb() ... - byte = readb (&ehci->caps->portroute[(i>>1)]); + byte = readb(&ehci->caps->portroute[(i >> 1)]); sprintf(tmp, "%d ", ((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf))); strcat(buf, tmp); } - ehci_dbg (ehci, "%s portroute %s\n", - label, buf); + ehci_dbg(ehci, "%s portroute %s\n", label, buf); } } #else -static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {} +static inline void dbg_hcs_params(struct ehci_hcd *ehci, char *label) {} #endif @@ -68,19 +67,19 @@ static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {} * (host controller _Capability_ parameters) * see EHCI Spec, Table 2-5 for each value * */ -static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) +static void dbg_hcc_params(struct ehci_hcd *ehci, char *label) { u32 params = ehci_readl(ehci, &ehci->caps->hcc_params); - if (HCC_ISOC_CACHE (params)) { - ehci_dbg (ehci, + if (HCC_ISOC_CACHE(params)) { + ehci_dbg(ehci, "%s hcc_params %04x caching frame %s%s%s\n", label, params, HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", HCC_CANPARK(params) ? " park" : "", HCC_64BIT_ADDR(params) ? " 64 bit addr" : ""); } else { - ehci_dbg (ehci, + ehci_dbg(ehci, "%s hcc_params %04x thresh %d uframes %s%s%s%s%s%s%s\n", label, params, @@ -97,14 +96,14 @@ static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) } #else -static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {} +static inline void dbg_hcc_params(struct ehci_hcd *ehci, char *label) {} #endif #ifdef CONFIG_DYNAMIC_DEBUG static void __maybe_unused -dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) +dbg_qtd(const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) { ehci_dbg(ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd, hc32_to_cpup(ehci, &qtd->hw_next), @@ -120,22 +119,22 @@ dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) } static void __maybe_unused -dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) +dbg_qh(const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) { struct ehci_qh_hw *hw = qh->hw; - ehci_dbg (ehci, "%s qh %p n%08x info %x %x qtd %x\n", label, + ehci_dbg(ehci, "%s qh %p n%08x info %x %x qtd %x\n", label, qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current); dbg_qtd("overlay", ehci, (struct ehci_qtd *) &hw->hw_qtd_next); } static void __maybe_unused -dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) +dbg_itd(const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) { - ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n", + ehci_dbg(ehci, "%s [%d] itd %p, next %08x, urb %p\n", label, itd->frame, itd, hc32_to_cpu(ehci, itd->hw_next), itd->urb); - ehci_dbg (ehci, + ehci_dbg(ehci, " trans: %08x %08x %08x %08x %08x %08x %08x %08x\n", hc32_to_cpu(ehci, itd->hw_transaction[0]), hc32_to_cpu(ehci, itd->hw_transaction[1]), @@ -145,7 +144,7 @@ dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) hc32_to_cpu(ehci, itd->hw_transaction[5]), hc32_to_cpu(ehci, itd->hw_transaction[6]), hc32_to_cpu(ehci, itd->hw_transaction[7])); - ehci_dbg (ehci, + ehci_dbg(ehci, " buf: %08x %08x %08x %08x %08x %08x %08x\n", hc32_to_cpu(ehci, itd->hw_bufp[0]), hc32_to_cpu(ehci, itd->hw_bufp[1]), @@ -154,19 +153,19 @@ dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) hc32_to_cpu(ehci, itd->hw_bufp[4]), hc32_to_cpu(ehci, itd->hw_bufp[5]), hc32_to_cpu(ehci, itd->hw_bufp[6])); - ehci_dbg (ehci, " index: %d %d %d %d %d %d %d %d\n", + ehci_dbg(ehci, " index: %d %d %d %d %d %d %d %d\n", itd->index[0], itd->index[1], itd->index[2], itd->index[3], itd->index[4], itd->index[5], itd->index[6], itd->index[7]); } static void __maybe_unused -dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) +dbg_sitd(const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) { - ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n", + ehci_dbg(ehci, "%s [%d] sitd %p, next %08x, urb %p\n", label, sitd->frame, sitd, hc32_to_cpu(ehci, sitd->hw_next), sitd->urb); - ehci_dbg (ehci, + ehci_dbg(ehci, " addr %08x sched %04x result %08x buf %08x %08x\n", hc32_to_cpu(ehci, sitd->hw_fullspeed_ep), hc32_to_cpu(ehci, sitd->hw_uframe), @@ -176,9 +175,9 @@ dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) } static int __maybe_unused -dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) +dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) { - return scnprintf (buf, len, + return scnprintf(buf, len, "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s%s", label, label [0] ? " " : "", status, (status & STS_PPCE_MASK) ? " PPCE" : "", @@ -196,9 +195,9 @@ dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) } static int __maybe_unused -dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) +dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) { - return scnprintf (buf, len, + return scnprintf(buf, len, "%s%sintrenable %02x%s%s%s%s%s%s%s", label, label [0] ? " " : "", enable, (enable & STS_PPCE_MASK) ? " PPCE" : "", @@ -215,9 +214,9 @@ static const char *const fls_strings [] = { "1024", "512", "256", "??" }; static int -dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) +dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) { - return scnprintf (buf, len, + return scnprintf(buf, len, "%s%scommand %07x %s%s%s%s%s%s=%d ithresh=%d%s%s%s%s " "period=%s%s %s", label, label [0] ? " " : "", command, @@ -227,7 +226,7 @@ dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) (command & CMD_ASPE) ? " ASPE" : "", (command & CMD_PSPE) ? " PSPE" : "", (command & CMD_PARK) ? " park" : "(park)", - CMD_PARK_CNT (command), + CMD_PARK_CNT(command), (command >> 16) & 0x3f, (command & CMD_LRESET) ? " LReset" : "", (command & CMD_IAAD) ? " IAAD" : "", @@ -240,7 +239,7 @@ dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) } static int -dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) +dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) { char *sig; @@ -252,7 +251,7 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) default: sig = "?"; break; } - return scnprintf (buf, len, + return scnprintf(buf, len, "%s%sport:%d status %06x %d %s%s%s%s%s%s " "sig=%s%s%s%s%s%s%s%s%s%s%s", label, label [0] ? " " : "", port, status, @@ -282,23 +281,23 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) #else static inline void __maybe_unused -dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) +dbg_qh(char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) {} static inline int __maybe_unused -dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) +dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) { return 0; } static inline int __maybe_unused -dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) +dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) { return 0; } static inline int __maybe_unused -dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) +dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) { return 0; } static inline int __maybe_unused -dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) +dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) { return 0; } #endif /* CONFIG_DYNAMIC_DEBUG */ @@ -326,8 +325,8 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) #ifdef STUB_DEBUG_FILES -static inline void create_debug_files (struct ehci_hcd *bus) { } -static inline void remove_debug_files (struct ehci_hcd *bus) { } +static inline void create_debug_files(struct ehci_hcd *bus) { } +static inline void remove_debug_files(struct ehci_hcd *bus) { } #else @@ -397,13 +396,13 @@ static inline char token_mark(struct ehci_hcd *ehci, __hc32 token) return '*'; if (v & QTD_STS_HALT) return '-'; - if (!IS_SHORT_READ (v)) + if (!IS_SHORT_READ(v)) return ' '; /* tries to advance through hw_alt_next */ return '/'; } -static void qh_lines ( +static void qh_lines( struct ehci_hcd *ehci, struct ehci_qh *qh, char **nextp, @@ -435,7 +434,7 @@ static void qh_lines ( } scratch = hc32_to_cpup(ehci, &hw->hw_info1); hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &hw->hw_current) : 0; - temp = scnprintf (next, size, + temp = scnprintf(next, size, "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)" " [cur %08x next %08x buf[0] %08x]", qh, scratch & 0x007f, @@ -453,21 +452,21 @@ static void qh_lines ( next += temp; /* hc may be modifying the list as we read it ... */ - list_for_each (entry, &qh->qtd_list) { - td = list_entry (entry, struct ehci_qtd, qtd_list); + list_for_each(entry, &qh->qtd_list) { + td = list_entry(entry, struct ehci_qtd, qtd_list); scratch = hc32_to_cpup(ehci, &td->hw_token); mark = ' '; if (hw_curr == td->qtd_dma) mark = '*'; else if (hw->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma)) mark = '+'; - else if (QTD_LENGTH (scratch)) { + else if (QTD_LENGTH(scratch)) { if (td->hw_alt_next == ehci->async->hw->hw_alt_next) mark = '#'; else if (td->hw_alt_next != list_end) mark = '/'; } - temp = snprintf (next, size, + temp = snprintf(next, size, "\n\t%p%c%s len=%d %08x urb %p" " [td %08x buf[0] %08x]", td, mark, ({ char *tmp; @@ -490,7 +489,7 @@ static void qh_lines ( goto done; } - temp = snprintf (next, size, "\n"); + temp = snprintf(next, size, "\n"); if (size < temp) temp = size; size -= temp; @@ -511,7 +510,7 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf) struct ehci_qh *qh; hcd = bus_to_hcd(buf->bus); - ehci = hcd_to_ehci (hcd); + ehci = hcd_to_ehci(hcd); next = buf->output_buf; size = buf->alloc_size; @@ -521,9 +520,9 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf) * usually empty except for long-term bulk reads, or head. * one QH per line, and TDs we know about */ - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh) - qh_lines (ehci, qh, &next, &size); + qh_lines(ehci, qh, &next, &size); if (!list_empty(&ehci->async_unlink) && size > 0) { temp = scnprintf(next, size, "\nunlink =\n"); size -= temp; @@ -535,7 +534,7 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf) qh_lines(ehci, qh, &next, &size); } } - spin_unlock_irqrestore (&ehci->lock, flags); + spin_unlock_irqrestore(&ehci->lock, flags); return strlen(buf->output_buf); } @@ -641,25 +640,25 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) seen_count = 0; hcd = bus_to_hcd(buf->bus); - ehci = hcd_to_ehci (hcd); + ehci = hcd_to_ehci(hcd); next = buf->output_buf; size = buf->alloc_size; - temp = scnprintf (next, size, "size = %d\n", ehci->periodic_size); + temp = scnprintf(next, size, "size = %d\n", ehci->periodic_size); size -= temp; next += temp; /* dump a snapshot of the periodic schedule. * iso changes, interrupt usually doesn't. */ - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); for (i = 0; i < ehci->periodic_size; i++) { p = ehci->pshadow [i]; - if (likely (!p.ptr)) + if (likely(!p.ptr)) continue; tag = Q_NEXT_TYPE(ehci, ehci->periodic [i]); - temp = scnprintf (next, size, "%4d: ", i); + temp = scnprintf(next, size, "%4d: ", i); size -= temp; next += temp; @@ -669,7 +668,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) switch (hc32_to_cpu(ehci, tag)) { case Q_TYPE_QH: hw = p.qh->hw; - temp = scnprintf (next, size, " qh%d-%04x/%p", + temp = scnprintf(next, size, " qh%d-%04x/%p", p.qh->ps.period, hc32_to_cpup(ehci, &hw->hw_info2) @@ -683,7 +682,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) if (seen [temp].ptr != p.ptr) continue; if (p.qh->qh_next.ptr) { - temp = scnprintf (next, size, + temp = scnprintf(next, size, " ..."); size -= temp; next += temp; @@ -699,7 +698,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) /* count tds, get ep direction */ temp = 0; - list_for_each_entry (qtd, + list_for_each_entry(qtd, &p.qh->qtd_list, qtd_list) { temp++; @@ -711,7 +710,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) } } - temp = scnprintf (next, size, + temp = scnprintf(next, size, " (%c%d ep%d%s " "[%d/%d] q%d p%d)", speed_char (scratch), @@ -730,20 +729,20 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) p = p.qh->qh_next; break; case Q_TYPE_FSTN: - temp = scnprintf (next, size, + temp = scnprintf(next, size, " fstn-%8x/%p", p.fstn->hw_prev, p.fstn); tag = Q_NEXT_TYPE(ehci, p.fstn->hw_next); p = p.fstn->fstn_next; break; case Q_TYPE_ITD: - temp = scnprintf (next, size, + temp = scnprintf(next, size, " itd/%p", p.itd); tag = Q_NEXT_TYPE(ehci, p.itd->hw_next); p = p.itd->itd_next; break; case Q_TYPE_SITD: - temp = scnprintf (next, size, + temp = scnprintf(next, size, " sitd%d-%04x/%p", p.sitd->stream->ps.period, hc32_to_cpup(ehci, &p.sitd->hw_uframe) @@ -757,12 +756,12 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) next += temp; } while (p.ptr); - temp = scnprintf (next, size, "\n"); + temp = scnprintf(next, size, "\n"); size -= temp; next += temp; } - spin_unlock_irqrestore (&ehci->lock, flags); - kfree (seen); + spin_unlock_irqrestore(&ehci->lock, flags); + kfree(seen); return buf->alloc_size - size; } @@ -794,14 +793,14 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) static char label [] = ""; hcd = bus_to_hcd(buf->bus); - ehci = hcd_to_ehci (hcd); + ehci = hcd_to_ehci(hcd); next = buf->output_buf; size = buf->alloc_size; - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); if (!HCD_HW_ACCESSIBLE(hcd)) { - size = scnprintf (next, size, + size = scnprintf(next, size, "bus %s, device %s\n" "%s\n" "SUSPENDED (no register access)\n", @@ -813,7 +812,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) /* Capability Registers */ i = HC_VERSION(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - temp = scnprintf (next, size, + temp = scnprintf(next, size, "bus %s, device %s\n" "%s\n" "EHCI %x.%02x, rh state %s\n", @@ -835,10 +834,10 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) offset = HCC_EXT_CAPS(ehci_readl(ehci, &ehci->caps->hcc_params)); while (offset && count--) { - pci_read_config_dword (pdev, offset, &cap); + pci_read_config_dword(pdev, offset, &cap); switch (cap & 0xff) { case 1: - temp = scnprintf (next, size, + temp = scnprintf(next, size, "ownership %08x%s%s\n", cap, (cap & (1 << 24)) ? " linux" : "", (cap & (1 << 16)) ? " firmware" : ""); @@ -846,8 +845,8 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) next += temp; offset += 4; - pci_read_config_dword (pdev, offset, &cap2); - temp = scnprintf (next, size, + pci_read_config_dword(pdev, offset, &cap2); + temp = scnprintf(next, size, "SMI sts/enable 0x%08x\n", cap2); size -= temp; next += temp; @@ -865,48 +864,48 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) // FIXME interpret both types of params i = ehci_readl(ehci, &ehci->caps->hcs_params); - temp = scnprintf (next, size, "structural params 0x%08x\n", i); + temp = scnprintf(next, size, "structural params 0x%08x\n", i); size -= temp; next += temp; i = ehci_readl(ehci, &ehci->caps->hcc_params); - temp = scnprintf (next, size, "capability params 0x%08x\n", i); + temp = scnprintf(next, size, "capability params 0x%08x\n", i); size -= temp; next += temp; /* Operational Registers */ - temp = dbg_status_buf (scratch, sizeof scratch, label, + temp = dbg_status_buf(scratch, sizeof(scratch), label, ehci_readl(ehci, &ehci->regs->status)); - temp = scnprintf (next, size, fmt, temp, scratch); + temp = scnprintf(next, size, fmt, temp, scratch); size -= temp; next += temp; - temp = dbg_command_buf (scratch, sizeof scratch, label, + temp = dbg_command_buf(scratch, sizeof(scratch), label, ehci_readl(ehci, &ehci->regs->command)); - temp = scnprintf (next, size, fmt, temp, scratch); + temp = scnprintf(next, size, fmt, temp, scratch); size -= temp; next += temp; - temp = dbg_intr_buf (scratch, sizeof scratch, label, + temp = dbg_intr_buf(scratch, sizeof(scratch), label, ehci_readl(ehci, &ehci->regs->intr_enable)); - temp = scnprintf (next, size, fmt, temp, scratch); + temp = scnprintf(next, size, fmt, temp, scratch); size -= temp; next += temp; - temp = scnprintf (next, size, "uframe %04x\n", + temp = scnprintf(next, size, "uframe %04x\n", ehci_read_frame_index(ehci)); size -= temp; next += temp; - for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) { - temp = dbg_port_buf (scratch, sizeof scratch, label, i, + for (i = 1; i <= HCS_N_PORTS(ehci->hcs_params); i++) { + temp = dbg_port_buf(scratch, sizeof(scratch), label, i, ehci_readl(ehci, &ehci->regs->port_status[i - 1])); - temp = scnprintf (next, size, fmt, temp, scratch); + temp = scnprintf(next, size, fmt, temp, scratch); size -= temp; next += temp; if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) { - temp = scnprintf (next, size, + temp = scnprintf(next, size, " debug control %08x\n", ehci_readl(ehci, &ehci->debug->control)); @@ -924,21 +923,21 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) } #ifdef EHCI_STATS - temp = scnprintf (next, size, + temp = scnprintf(next, size, "irq normal %ld err %ld iaa %ld (lost %ld)\n", ehci->stats.normal, ehci->stats.error, ehci->stats.iaa, ehci->stats.lost_iaa); size -= temp; next += temp; - temp = scnprintf (next, size, "complete %ld unlink %ld\n", + temp = scnprintf(next, size, "complete %ld unlink %ld\n", ehci->stats.complete, ehci->stats.unlink); size -= temp; next += temp; #endif done: - spin_unlock_irqrestore (&ehci->lock, flags); + spin_unlock_irqrestore(&ehci->lock, flags); return buf->alloc_size - size; } @@ -1054,7 +1053,7 @@ static int debug_registers_open(struct inode *inode, struct file *file) return file->private_data ? 0 : -ENOMEM; } -static inline void create_debug_files (struct ehci_hcd *ehci) +static inline void create_debug_files(struct ehci_hcd *ehci) { struct usb_bus *bus = &ehci_to_hcd(ehci)->self; @@ -1084,7 +1083,7 @@ file_error: debugfs_remove_recursive(ehci->debug_dir); } -static inline void remove_debug_files (struct ehci_hcd *ehci) +static inline void remove_debug_files(struct ehci_hcd *ehci) { debugfs_remove_recursive(ehci->debug_dir); } -- cgit v1.2.3 From 1cb1d1c0d0de5c69937ed781211da8abcf03112f Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:54 -0300 Subject: usb: host: ehci-dbg: remove space before open square bracket This patch fixes coding style issues reported by checkpatch. The only change in this patch that isn't just removing spaces before opening square brackets is at line 213 where the initialization of fls_strings[] is placed in same line. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index fcbbdfa25766..52bf3fe2a965 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -42,7 +42,7 @@ static void dbg_hcs_params(struct ehci_hcd *ehci, char *label) /* Port routing, per EHCI 0.95 Spec, Section 2.2.5 */ if (HCS_PORTROUTED(params)) { int i; - char buf [46], tmp [7], byte; + char buf[46], tmp[7], byte; buf[0] = 0; for (i = 0; i < HCS_N_PORTS(params); i++) { @@ -109,8 +109,8 @@ dbg_qtd(const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) hc32_to_cpup(ehci, &qtd->hw_next), hc32_to_cpup(ehci, &qtd->hw_alt_next), hc32_to_cpup(ehci, &qtd->hw_token), - hc32_to_cpup(ehci, &qtd->hw_buf [0])); - if (qtd->hw_buf [1]) + hc32_to_cpup(ehci, &qtd->hw_buf[0])); + if (qtd->hw_buf[1]) ehci_dbg(ehci, " p1=%08x p2=%08x p3=%08x p4=%08x\n", hc32_to_cpup(ehci, &qtd->hw_buf[1]), hc32_to_cpup(ehci, &qtd->hw_buf[2]), @@ -179,7 +179,7 @@ dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) { return scnprintf(buf, len, "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s%s", - label, label [0] ? " " : "", status, + label, label[0] ? " " : "", status, (status & STS_PPCE_MASK) ? " PPCE" : "", (status & STS_ASS) ? " Async" : "", (status & STS_PSS) ? " Periodic" : "", @@ -199,7 +199,7 @@ dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) { return scnprintf(buf, len, "%s%sintrenable %02x%s%s%s%s%s%s%s", - label, label [0] ? " " : "", enable, + label, label[0] ? " " : "", enable, (enable & STS_PPCE_MASK) ? " PPCE" : "", (enable & STS_IAA) ? " IAA" : "", (enable & STS_FATAL) ? " FATAL" : "", @@ -210,8 +210,7 @@ dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) ); } -static const char *const fls_strings [] = - { "1024", "512", "256", "??" }; +static const char *const fls_strings[] = { "1024", "512", "256", "??" }; static int dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) @@ -219,7 +218,7 @@ dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) return scnprintf(buf, len, "%s%scommand %07x %s%s%s%s%s%s=%d ithresh=%d%s%s%s%s " "period=%s%s %s", - label, label [0] ? " " : "", command, + label, label[0] ? " " : "", command, (command & CMD_HIRD) ? " HIRD" : "", (command & CMD_PPCEE) ? " PPCEE" : "", (command & CMD_FSP) ? " FSP" : "", @@ -232,7 +231,7 @@ dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) (command & CMD_IAAD) ? " IAAD" : "", (command & CMD_ASE) ? " Async" : "", (command & CMD_PSE) ? " Periodic" : "", - fls_strings [(command >> 2) & 0x3], + fls_strings[(command >> 2) & 0x3], (command & CMD_RESET) ? " Reset" : "", (command & CMD_RUN) ? "RUN" : "HALT" ); @@ -254,7 +253,7 @@ dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) return scnprintf(buf, len, "%s%sport:%d status %06x %d %s%s%s%s%s%s " "sig=%s%s%s%s%s%s%s%s%s%s%s", - label, label [0] ? " " : "", port, status, + label, label[0] ? " " : "", port, status, status>>25,/*device address */ (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_ACK ? " ACK" : "", @@ -653,10 +652,10 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) */ spin_lock_irqsave(&ehci->lock, flags); for (i = 0; i < ehci->periodic_size; i++) { - p = ehci->pshadow [i]; + p = ehci->pshadow[i]; if (likely(!p.ptr)) continue; - tag = Q_NEXT_TYPE(ehci, ehci->periodic [i]); + tag = Q_NEXT_TYPE(ehci, ehci->periodic[i]); temp = scnprintf(next, size, "%4d: ", i); size -= temp; @@ -679,7 +678,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) next += temp; /* don't repeat what follows this qh */ for (temp = 0; temp < seen_count; temp++) { - if (seen [temp].ptr != p.ptr) + if (seen[temp].ptr != p.ptr) continue; if (p.qh->qh_next.ptr) { temp = scnprintf(next, size, @@ -722,7 +721,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) 0x7ff & (scratch >> 16)); if (seen_count < DBG_SCHED_LIMIT) - seen [seen_count++].qh = p.qh; + seen[seen_count++].qh = p.qh; } else temp = 0; tag = Q_NEXT_TYPE(ehci, hw->hw_next); @@ -788,9 +787,9 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) struct ehci_hcd *ehci; unsigned long flags; unsigned temp, size, i; - char *next, scratch [80]; - static char fmt [] = "%*s\n"; - static char label [] = ""; + char *next, scratch[80]; + static char fmt[] = "%*s\n"; + static char label[] = ""; hcd = bus_to_hcd(buf->bus); ehci = hcd_to_ehci(hcd); -- cgit v1.2.3 From 0784b4d5a2a691394c1d4034d4879ac428365383 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:55 -0300 Subject: usb: host: ehci-dbg: use C89-style comments This patch fixes coding style issues reported by checkpatch. Coding style demands usage of C89-style comments and a specific format when it's multiline. This also removes the Free Software Foundation address because FSF can change it again. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 52bf3fe2a965..df9f5986696f 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -11,16 +11,14 @@ * 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. */ /* this file is part of ehci-hcd.c */ #ifdef CONFIG_DYNAMIC_DEBUG -/* check the values in the HCSPARAMS register +/* + * check the values in the HCSPARAMS register * (host controller _Structural_ parameters) * see EHCI spec, Table 2-4 for each value */ @@ -46,7 +44,7 @@ static void dbg_hcs_params(struct ehci_hcd *ehci, char *label) buf[0] = 0; for (i = 0; i < HCS_N_PORTS(params); i++) { - // FIXME MIPS won't readb() ... + /* FIXME MIPS won't readb() ... */ byte = readb(&ehci->caps->portroute[(i >> 1)]); sprintf(tmp, "%d ", ((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf))); @@ -63,10 +61,11 @@ static inline void dbg_hcs_params(struct ehci_hcd *ehci, char *label) {} #ifdef CONFIG_DYNAMIC_DEBUG -/* check the values in the HCCPARAMS register +/* + * check the values in the HCCPARAMS register * (host controller _Capability_ parameters) * see EHCI Spec, Table 2-5 for each value - * */ + */ static void dbg_hcc_params(struct ehci_hcd *ehci, char *label) { u32 params = ehci_readl(ehci, &ehci->caps->hcc_params); @@ -515,7 +514,8 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf) *next = 0; - /* dumps a snapshot of the async schedule. + /* + * dumps a snapshot of the async schedule. * usually empty except for long-term bulk reads, or head. * one QH per line, and TDs we know about */ @@ -647,7 +647,8 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) size -= temp; next += temp; - /* dump a snapshot of the periodic schedule. + /* + * dump a snapshot of the periodic schedule. * iso changes, interrupt usually doesn't. */ spin_lock_irqsave(&ehci->lock, flags); @@ -861,7 +862,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) } #endif - // FIXME interpret both types of params + /* FIXME interpret both types of params */ i = ehci_readl(ehci, &ehci->caps->hcs_params); temp = scnprintf(next, size, "structural params 0x%08x\n", i); size -= temp; -- cgit v1.2.3 From 5bb95ec8d74a99bdf69fd1cf28c340fd680effce Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:56 -0300 Subject: usb: host: ehci-dbg: move trailing statements to next line This patch fixes coding style issues reported by checkpatch concerning to switch case statements. There are few additional changes made to fix other coding styles issues. These additional changes are: - The compound statement "({...})" on line 474 is pulled out from snprintf parameters. - On line 723 the constant "0x03" is moved to right. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 54 +++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index df9f5986696f..c409e4ff9d95 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -243,10 +243,18 @@ dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) /* signaling state */ switch (status & (3 << 10)) { - case 0 << 10: sig = "se0"; break; - case 1 << 10: sig = "k"; break; /* low speed */ - case 2 << 10: sig = "j"; break; - default: sig = "?"; break; + case 0 << 10: + sig = "se0"; + break; + case 1 << 10: /* low speed */ + sig = "k"; + break; + case 2 << 10: + sig = "j"; + break; + default: + sig = "?"; + break; } return scnprintf(buf, len, @@ -451,6 +459,8 @@ static void qh_lines( /* hc may be modifying the list as we read it ... */ list_for_each(entry, &qh->qtd_list) { + char *type; + td = list_entry(entry, struct ehci_qtd, qtd_list); scratch = hc32_to_cpup(ehci, &td->hw_token); mark = ' '; @@ -464,16 +474,24 @@ static void qh_lines( else if (td->hw_alt_next != list_end) mark = '/'; } + switch ((scratch >> 8) & 0x03) { + case 0: + type = "out"; + break; + case 1: + type = "in"; + break; + case 2: + type = "setup"; + break; + default: + type = "?"; + break; + } temp = snprintf(next, size, "\n\t%p%c%s len=%d %08x urb %p" " [td %08x buf[0] %08x]", - td, mark, ({ char *tmp; - switch ((scratch>>8)&0x03) { - case 0: tmp = "out"; break; - case 1: tmp = "in"; break; - case 2: tmp = "setup"; break; - default: tmp = "?"; break; - } tmp;}), + td, mark, type, (scratch >> 16) & 0x7fff, scratch, td->urb, @@ -702,11 +720,15 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) &p.qh->qtd_list, qtd_list) { temp++; - switch (0x03 & (hc32_to_cpu( - ehci, - qtd->hw_token) >> 8)) { - case 0: type = "out"; continue; - case 1: type = "in"; continue; + switch ((hc32_to_cpu(ehci, + qtd->hw_token) >> 8) + & 0x03) { + case 0: + type = "out"; + continue; + case 1: + type = "in"; + continue; } } -- cgit v1.2.3 From 78698d66a1a7747b02e73e427d503c1426b8cd32 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:57 -0300 Subject: usb: host: ehci-dbg: fix up closing parenthesis This patch puts the closing parenthesis at the statement end removing unnecessary "new line". Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index c409e4ff9d95..3b423e122423 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -35,8 +35,7 @@ static void dbg_hcs_params(struct ehci_hcd *ehci, char *label) HCS_N_PCC(params), HCS_PORTROUTED(params) ? "" : " ordered", HCS_PPC(params) ? "" : " !ppc", - HCS_N_PORTS(params) - ); + HCS_N_PORTS(params)); /* Port routing, per EHCI 0.95 Spec, Section 2.2.5 */ if (HCS_PORTROUTED(params)) { int i; @@ -189,8 +188,7 @@ dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) (status & STS_FLR) ? " FLR" : "", (status & STS_PCD) ? " PCD" : "", (status & STS_ERR) ? " ERR" : "", - (status & STS_INT) ? " INT" : "" - ); + (status & STS_INT) ? " INT" : ""); } static int __maybe_unused @@ -205,8 +203,7 @@ dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) (enable & STS_FLR) ? " FLR" : "", (enable & STS_PCD) ? " PCD" : "", (enable & STS_ERR) ? " ERR" : "", - (enable & STS_INT) ? " INT" : "" - ); + (enable & STS_INT) ? " INT" : ""); } static const char *const fls_strings[] = { "1024", "512", "256", "??" }; @@ -232,8 +229,7 @@ dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) (command & CMD_PSE) ? " Periodic" : "", fls_strings[(command >> 2) & 0x3], (command & CMD_RESET) ? " Reset" : "", - (command & CMD_RUN) ? "RUN" : "HALT" - ); + (command & CMD_RUN) ? "RUN" : "HALT"); } static int -- cgit v1.2.3 From c2fb017104eaceb3245640d2bec988d8751552bc Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:58 -0300 Subject: usb: host: ehci-dbg: put spaces around operators This patch fixes coding style issues reported by checkpatch concerning to missing spaces around operators. There is an additional change on line 49 that removes unnecessary parentheses around ternary operands. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 3b423e122423..980ca55f466a 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -46,7 +46,7 @@ static void dbg_hcs_params(struct ehci_hcd *ehci, char *label) /* FIXME MIPS won't readb() ... */ byte = readb(&ehci->caps->portroute[(i >> 1)]); sprintf(tmp, "%d ", - ((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf))); + (i & 0x1) ? byte & 0xf : (byte >> 4) & 0xf); strcat(buf, tmp); } ehci_dbg(ehci, "%s portroute %s\n", label, buf); @@ -257,14 +257,14 @@ dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) "%s%sport:%d status %06x %d %s%s%s%s%s%s " "sig=%s%s%s%s%s%s%s%s%s%s%s", label, label[0] ? " " : "", port, status, - status>>25,/*device address */ - (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_ACK ? + status >> 25, /*device address */ + (status & PORT_SSTS) >> 23 == PORTSC_SUSPEND_STS_ACK ? " ACK" : "", - (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_NYET ? + (status & PORT_SSTS) >> 23 == PORTSC_SUSPEND_STS_NYET ? " NYET" : "", - (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_STALL ? + (status & PORT_SSTS) >> 23 == PORTSC_SUSPEND_STS_STALL ? " STALL" : "", - (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_ERR ? + (status & PORT_SSTS) >> 23 == PORTSC_SUSPEND_STS_ERR ? " ERR" : "", (status & PORT_POWER) ? " POWER" : "", (status & PORT_OWNER) ? " OWNER" : "", @@ -846,7 +846,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) if (dev_is_pci(hcd->self.controller)) { struct pci_dev *pdev; u32 offset, cap, cap2; - unsigned count = 256/4; + unsigned count = 256 / 4; pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); offset = HCC_EXT_CAPS(ehci_readl(ehci, @@ -1058,7 +1058,7 @@ static int debug_periodic_open(struct inode *inode, struct file *file) if (!buf) return -ENOMEM; - buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8)*PAGE_SIZE; + buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8) * PAGE_SIZE; file->private_data = buf; return 0; } -- cgit v1.2.3 From a5355977947dc4da93ac05a72989fecc95bc6dca Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:59 -0300 Subject: usb: host: ehci-dbg: use scnprintf() in qh_lines() This patch replaces two snprintf() calls with scnprintf() in qh_lines() and hence removes the unneeded sequential truncation tests. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 980ca55f466a..97a0582849b4 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -484,7 +484,7 @@ static void qh_lines( type = "?"; break; } - temp = snprintf(next, size, + temp = scnprintf(next, size, "\n\t%p%c%s len=%d %08x urb %p" " [td %08x buf[0] %08x]", td, mark, type, @@ -493,17 +493,13 @@ static void qh_lines( td->urb, (u32) td->qtd_dma, hc32_to_cpup(ehci, &td->hw_buf[0])); - if (size < temp) - temp = size; size -= temp; next += temp; if (temp == size) goto done; } - temp = snprintf(next, size, "\n"); - if (size < temp) - temp = size; + temp = scnprintf(next, size, "\n"); size -= temp; next += temp; -- cgit v1.2.3 From c768ffb891df375bc111515047fa56521401bab3 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:00 -0300 Subject: usb: host: ehci-dbg: fix up function definitions This patch indents not empty functions to have the opening brace at the beginning of the next line and body conforming coding style. This also makes the function definition consistent with the file coding style aligning parameters in sequential lines and indenting them with two tabs. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 97a0582849b4..44ca22639841 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -288,19 +288,27 @@ dbg_qh(char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) static inline int __maybe_unused dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) -{ return 0; } +{ + return 0; +} static inline int __maybe_unused dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) -{ return 0; } +{ + return 0; +} static inline int __maybe_unused dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) -{ return 0; } +{ + return 0; +} static inline int __maybe_unused dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) -{ return 0; } +{ + return 0; +} #endif /* CONFIG_DYNAMIC_DEBUG */ @@ -404,12 +412,8 @@ static inline char token_mark(struct ehci_hcd *ehci, __hc32 token) return '/'; } -static void qh_lines( - struct ehci_hcd *ehci, - struct ehci_qh *qh, - char **nextp, - unsigned *sizep -) +static void qh_lines(struct ehci_hcd *ehci, struct ehci_qh *qh, + char **nextp, unsigned *sizep) { u32 scratch; u32 hw_curr; @@ -957,7 +961,7 @@ done: } static struct debug_buffer *alloc_buffer(struct usb_bus *bus, - ssize_t (*fill_func)(struct debug_buffer *)) + ssize_t (*fill_func)(struct debug_buffer *)) { struct debug_buffer *buf; @@ -997,7 +1001,7 @@ out: } static ssize_t debug_output(struct file *file, char __user *user_buf, - size_t len, loff_t *offset) + size_t len, loff_t *offset) { struct debug_buffer *buf = file->private_data; int ret = 0; -- cgit v1.2.3 From e1666317d8c543b80cedacece72ebb17d80e2994 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:01 -0300 Subject: usb: host: ehci-dbg: use a blank line after struct declarations This patch fixes coding style issues reported by checkpatch concerning to missing line after struct declarations. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 44ca22639841..7e070144ec69 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -357,6 +357,7 @@ static const struct file_operations debug_async_fops = { .release = debug_close, .llseek = default_llseek, }; + static const struct file_operations debug_bandwidth_fops = { .owner = THIS_MODULE, .open = debug_bandwidth_open, @@ -364,6 +365,7 @@ static const struct file_operations debug_bandwidth_fops = { .release = debug_close, .llseek = default_llseek, }; + static const struct file_operations debug_periodic_fops = { .owner = THIS_MODULE, .open = debug_periodic_open, @@ -371,6 +373,7 @@ static const struct file_operations debug_periodic_fops = { .release = debug_close, .llseek = default_llseek, }; + static const struct file_operations debug_registers_fops = { .owner = THIS_MODULE, .open = debug_registers_open, -- cgit v1.2.3 From 1f8e5afdb28510eda75700e5c12af03550c10a8d Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:02 -0300 Subject: usb: host: ehci-dbg: convert macro to inline function This patch converts macros into inline functions since the usage of second is encouraged by Coding Style instead of the first. Macros converted to functions: - dbg_status - dbg_cmd - dbg_port - speed_char The size after changes remains the same. Before: text data bss dec hex filename 36920 81 12 37013 9095 drivers/usb/host/ehci-hcd.o After: text data bss dec hex filename 36920 81 12 37013 9095 drivers/usb/host/ehci-hcd.o Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 54 ++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 7e070144ec69..9efb2d1ca036 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -312,23 +312,31 @@ dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) #endif /* CONFIG_DYNAMIC_DEBUG */ -/* functions have the "wrong" filename when they're output... */ -#define dbg_status(ehci, label, status) { \ - char _buf [80]; \ - dbg_status_buf (_buf, sizeof _buf, label, status); \ - ehci_dbg (ehci, "%s\n", _buf); \ +static inline void +dbg_status(struct ehci_hcd *ehci, const char *label, u32 status) +{ + char buf[80]; + + dbg_status_buf(buf, sizeof(buf), label, status); + ehci_dbg(ehci, "%s\n", buf); } -#define dbg_cmd(ehci, label, command) { \ - char _buf [80]; \ - dbg_command_buf (_buf, sizeof _buf, label, command); \ - ehci_dbg (ehci, "%s\n", _buf); \ +static inline void +dbg_cmd(struct ehci_hcd *ehci, const char *label, u32 command) +{ + char buf[80]; + + dbg_command_buf(buf, sizeof(buf), label, command); + ehci_dbg(ehci, "%s\n", buf); } -#define dbg_port(ehci, label, port, status) { \ - char _buf [80]; \ - dbg_port_buf (_buf, sizeof _buf, label, port, status); \ - ehci_dbg (ehci, "%s\n", _buf); \ +static inline void +dbg_port(struct ehci_hcd *ehci, const char *label, int port, u32 status) +{ + char buf[80]; + + dbg_port_buf(buf, sizeof(buf), label, port, status); + ehci_dbg(ehci, "%s\n", buf); } /*-------------------------------------------------------------------------*/ @@ -393,13 +401,19 @@ struct debug_buffer { size_t alloc_size; }; -#define speed_char(info1) ({ char tmp; \ - switch (info1 & (3 << 12)) { \ - case QH_FULL_SPEED: tmp = 'f'; break; \ - case QH_LOW_SPEED: tmp = 'l'; break; \ - case QH_HIGH_SPEED: tmp = 'h'; break; \ - default: tmp = '?'; break; \ - } tmp; }) +static inline char speed_char(u32 info1) +{ + switch (info1 & (3 << 12)) { + case QH_FULL_SPEED: + return 'f'; + case QH_LOW_SPEED: + return 'l'; + case QH_HIGH_SPEED: + return 'h'; + default: + return '?'; + } +} static inline char token_mark(struct ehci_hcd *ehci, __hc32 token) { -- cgit v1.2.3 From 8d587d64955c42167e6fd413560452d064cd02d1 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:03 -0300 Subject: usb: host: ehci-dbg: add blank line after declarations This patch fixes coding style issues reported by checkpatch concerning to missing line after variable declarations. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 9efb2d1ca036..8c55d9a4be83 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -1071,6 +1071,7 @@ static int debug_bandwidth_open(struct inode *inode, struct file *file) static int debug_periodic_open(struct inode *inode, struct file *file) { struct debug_buffer *buf; + buf = alloc_buffer(inode->i_private, fill_periodic_buffer); if (!buf) return -ENOMEM; -- cgit v1.2.3 From e2432f06b5669538f79d64d18e60b2c8c05d59f2 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:04 -0300 Subject: usb: host: ehci-dbg: remove blank line before close brace This patch fixes coding style issue reported by checkpatch concerning to an unnecessary line before close brace. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 8c55d9a4be83..37dac751bac5 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -1038,7 +1038,6 @@ static ssize_t debug_output(struct file *file, char __user *user_buf, out: return ret; - } static int debug_close(struct inode *inode, struct file *file) -- cgit v1.2.3 From 12ef7dd97c3302c6c308484ffce392ef2383783a Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:05 -0300 Subject: usb: host: ehci-dbg: replace sizeof operand This patch fixes a coding style issue reported by checkpatch concerning to usage of sizeof operand as a variable instead the type. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 37dac751bac5..22e6d4c4548a 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -982,7 +982,7 @@ static struct debug_buffer *alloc_buffer(struct usb_bus *bus, { struct debug_buffer *buf; - buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); + buf = kzalloc(sizeof(*buf), GFP_KERNEL); if (buf) { buf->bus = bus; -- cgit v1.2.3 From 04b8ad436848b11ef6cc54589bd96cacd69fa6e7 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:06 -0300 Subject: usb: host: ehci-dbg: enclose conditional blocks with braces This patch fixes coding style issues reported by checkpatch concerning to conditional blocks without braces. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 22e6d4c4548a..760b1d6e429f 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -481,11 +481,11 @@ static void qh_lines(struct ehci_hcd *ehci, struct ehci_qh *qh, td = list_entry(entry, struct ehci_qtd, qtd_list); scratch = hc32_to_cpup(ehci, &td->hw_token); mark = ' '; - if (hw_curr == td->qtd_dma) + if (hw_curr == td->qtd_dma) { mark = '*'; - else if (hw->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma)) + } else if (hw->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma)) { mark = '+'; - else if (QTD_LENGTH(scratch)) { + } else if (QTD_LENGTH(scratch)) { if (td->hw_alt_next == ehci->async->hw->hw_alt_next) mark = '#'; else if (td->hw_alt_next != list_end) @@ -758,8 +758,9 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) if (seen_count < DBG_SCHED_LIMIT) seen[seen_count++].qh = p.qh; - } else + } else { temp = 0; + } tag = Q_NEXT_TYPE(ehci, hw->hw_next); p = p.qh->qh_next; break; -- cgit v1.2.3 From cb272521760a604924162487a6b73ff5531a5648 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:07 -0300 Subject: usb: host: ehci-dbg: prefer kmalloc_array over kmalloc times size This patch fixes a coding style issue reported by checkpatch related to kmalloc_array usage. On the same line the sizeof operand was enclosed in parentheses. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 760b1d6e429f..da4133492a5f 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -664,7 +664,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) unsigned i; __hc32 tag; - seen = kmalloc(DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC); + seen = kmalloc_array(DBG_SCHED_LIMIT, sizeof(*seen), GFP_ATOMIC); if (!seen) return 0; seen_count = 0; -- cgit v1.2.3 From 3fd29009f87ba49bcbba516a31f5cf582c4ba613 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:08 -0300 Subject: usb: host: ehci-dbg: add function output_buf_tds_dir() This patch fixes a coding style issue reported by checkpatch related to too many leading tabs. This moves part of the fill_periodic_buffer() to the new function output_buf_tds_dir(). Because it's inline, the file size has not changed. Before: text data bss dec hex filename 36920 81 12 37013 9095 drivers/usb/host/ehci-hcd.o After: text data bss dec hex filename 36920 81 12 37013 9095 drivers/usb/host/ehci-hcd.o Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 62 +++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index da4133492a5f..d2c0711d13e8 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -652,6 +652,33 @@ static ssize_t fill_bandwidth_buffer(struct debug_buffer *buf) return next - buf->output_buf; } +static unsigned output_buf_tds_dir(char *buf, struct ehci_hcd *ehci, + struct ehci_qh_hw *hw, struct ehci_qh *qh, unsigned size) +{ + u32 scratch = hc32_to_cpup(ehci, &hw->hw_info1); + struct ehci_qtd *qtd; + char *type = ""; + unsigned temp = 0; + + /* count tds, get ep direction */ + list_for_each_entry(qtd, &qh->qtd_list, qtd_list) { + temp++; + switch ((hc32_to_cpu(ehci, qtd->hw_token) >> 8) & 0x03) { + case 0: + type = "out"; + continue; + case 1: + type = "in"; + continue; + } + } + + return scnprintf(buf, size, " (%c%d ep%d%s [%d/%d] q%d p%d)", + speed_char(scratch), scratch & 0x007f, + (scratch >> 8) & 0x000f, type, qh->ps.usecs, + qh->ps.c_usecs, temp, 0x7ff & (scratch >> 16)); +} + #define DBG_SCHED_LIMIT 64 static ssize_t fill_periodic_buffer(struct debug_buffer *buf) { @@ -722,39 +749,8 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) } /* show more info the first time around */ if (temp == seen_count) { - u32 scratch = hc32_to_cpup(ehci, - &hw->hw_info1); - struct ehci_qtd *qtd; - char *type = ""; - - /* count tds, get ep direction */ - temp = 0; - list_for_each_entry(qtd, - &p.qh->qtd_list, - qtd_list) { - temp++; - switch ((hc32_to_cpu(ehci, - qtd->hw_token) >> 8) - & 0x03) { - case 0: - type = "out"; - continue; - case 1: - type = "in"; - continue; - } - } - - temp = scnprintf(next, size, - " (%c%d ep%d%s " - "[%d/%d] q%d p%d)", - speed_char (scratch), - scratch & 0x007f, - (scratch >> 8) & 0x000f, type, - p.qh->ps.usecs, - p.qh->ps.c_usecs, - temp, - 0x7ff & (scratch >> 16)); + temp = output_buf_tds_dir(next, ehci, + hw, p.qh, size); if (seen_count < DBG_SCHED_LIMIT) seen[seen_count++].qh = p.qh; -- cgit v1.2.3 From 93df42ba1b4fe5bc3157e4fbd15baf11b2129217 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:09 -0300 Subject: usb: ehci: remove old stub_debug_files definition This patch removes the local STUB_DEBUG_FILES debugging definition. STUB_DEBUG_FILES was used only in ehci-hcd, whereas CONFIG_DYNAMIC_DEBUG is used all over the kernel. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 4 ++-- drivers/usb/host/ehci.h | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index d2c0711d13e8..79d12b2ba3c4 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -341,7 +341,7 @@ dbg_port(struct ehci_hcd *ehci, const char *label, int port, u32 status) /*-------------------------------------------------------------------------*/ -#ifdef STUB_DEBUG_FILES +#ifndef CONFIG_DYNAMIC_DEBUG static inline void create_debug_files(struct ehci_hcd *bus) { } static inline void remove_debug_files(struct ehci_hcd *bus) { } @@ -1120,4 +1120,4 @@ static inline void remove_debug_files(struct ehci_hcd *ehci) debugfs_remove_recursive(ehci->debug_dir); } -#endif /* STUB_DEBUG_FILES */ +#endif /* CONFIG_DYNAMIC_DEBUG */ diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index d1b29b36b347..2ddf35203c05 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -870,11 +870,6 @@ static inline u32 hc32_to_cpup(const struct ehci_hcd *ehci, const __hc32 *x) #define ehci_warn(ehci, fmt, args...) \ dev_warn(ehci_to_hcd(ehci)->self.controller, fmt, ## args) - -#ifndef CONFIG_DYNAMIC_DEBUG -#define STUB_DEBUG_FILES -#endif - /*-------------------------------------------------------------------------*/ /* Declarations of things exported for use by ehci platform drivers */ -- cgit v1.2.3 From 3f122a997eddd518ac480e658ab034cbc98deabe Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:10 -0300 Subject: usb: host: ehci-sched: refactor scan_isoc function This patch removes an infinite 'for' loop and makes use of the already existing 'restart' tag instead, reducing one leading tab. The comments and code were corrected conforming file coding style. Tested by compilation only. Caught by checkpatch: WARNING: Too many leading tabs - consider code refactoring Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 202 +++++++++++++++++++++--------------------- 1 file changed, 101 insertions(+), 101 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index c1704a57e803..74c2023763ad 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -2379,9 +2379,11 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, static void scan_isoc(struct ehci_hcd *ehci) { - unsigned uf, now_frame, frame; - unsigned fmask = ehci->periodic_size - 1; - bool modified, live; + unsigned uf, now_frame, frame; + unsigned fmask = ehci->periodic_size - 1; + bool modified, live; + union ehci_shadow q, *q_p; + __hc32 type, *hw_p; /* * When running, scan from last scan point up to "now" @@ -2399,119 +2401,117 @@ static void scan_isoc(struct ehci_hcd *ehci) ehci->now_frame = now_frame; frame = ehci->last_iso_frame; - for (;;) { - union ehci_shadow q, *q_p; - __hc32 type, *hw_p; restart: - /* scan each element in frame's queue for completions */ - q_p = &ehci->pshadow [frame]; - hw_p = &ehci->periodic [frame]; - q.ptr = q_p->ptr; - type = Q_NEXT_TYPE(ehci, *hw_p); - modified = false; - - while (q.ptr != NULL) { - switch (hc32_to_cpu(ehci, type)) { - case Q_TYPE_ITD: - /* If this ITD is still active, leave it for - * later processing ... check the next entry. - * No need to check for activity unless the - * frame is current. - */ - if (frame == now_frame && live) { - rmb(); - for (uf = 0; uf < 8; uf++) { - if (q.itd->hw_transaction[uf] & - ITD_ACTIVE(ehci)) - break; - } - if (uf < 8) { - q_p = &q.itd->itd_next; - hw_p = &q.itd->hw_next; - type = Q_NEXT_TYPE(ehci, - q.itd->hw_next); - q = *q_p; + /* Scan each element in frame's queue for completions */ + q_p = &ehci->pshadow[frame]; + hw_p = &ehci->periodic[frame]; + q.ptr = q_p->ptr; + type = Q_NEXT_TYPE(ehci, *hw_p); + modified = false; + + while (q.ptr != NULL) { + switch (hc32_to_cpu(ehci, type)) { + case Q_TYPE_ITD: + /* + * If this ITD is still active, leave it for + * later processing ... check the next entry. + * No need to check for activity unless the + * frame is current. + */ + if (frame == now_frame && live) { + rmb(); + for (uf = 0; uf < 8; uf++) { + if (q.itd->hw_transaction[uf] & + ITD_ACTIVE(ehci)) break; - } } - - /* Take finished ITDs out of the schedule - * and process them: recycle, maybe report - * URB completion. HC won't cache the - * pointer for much longer, if at all. - */ - *q_p = q.itd->itd_next; - if (!ehci->use_dummy_qh || - q.itd->hw_next != EHCI_LIST_END(ehci)) - *hw_p = q.itd->hw_next; - else - *hw_p = cpu_to_hc32(ehci, - ehci->dummy->qh_dma); - type = Q_NEXT_TYPE(ehci, q.itd->hw_next); - wmb(); - modified = itd_complete (ehci, q.itd); - q = *q_p; - break; - case Q_TYPE_SITD: - /* If this SITD is still active, leave it for - * later processing ... check the next entry. - * No need to check for activity unless the - * frame is current. - */ - if (((frame == now_frame) || - (((frame + 1) & fmask) == now_frame)) - && live - && (q.sitd->hw_results & - SITD_ACTIVE(ehci))) { - - q_p = &q.sitd->sitd_next; - hw_p = &q.sitd->hw_next; + if (uf < 8) { + q_p = &q.itd->itd_next; + hw_p = &q.itd->hw_next; type = Q_NEXT_TYPE(ehci, - q.sitd->hw_next); + q.itd->hw_next); q = *q_p; break; } + } + + /* + * Take finished ITDs out of the schedule + * and process them: recycle, maybe report + * URB completion. HC won't cache the + * pointer for much longer, if at all. + */ + *q_p = q.itd->itd_next; + if (!ehci->use_dummy_qh || + q.itd->hw_next != EHCI_LIST_END(ehci)) + *hw_p = q.itd->hw_next; + else + *hw_p = cpu_to_hc32(ehci, ehci->dummy->qh_dma); + type = Q_NEXT_TYPE(ehci, q.itd->hw_next); + wmb(); + modified = itd_complete(ehci, q.itd); + q = *q_p; + break; + case Q_TYPE_SITD: + /* + * If this SITD is still active, leave it for + * later processing ... check the next entry. + * No need to check for activity unless the + * frame is current. + */ + if (((frame == now_frame) || + (((frame + 1) & fmask) == now_frame)) + && live + && (q.sitd->hw_results & SITD_ACTIVE(ehci))) { - /* Take finished SITDs out of the schedule - * and process them: recycle, maybe report - * URB completion. - */ - *q_p = q.sitd->sitd_next; - if (!ehci->use_dummy_qh || - q.sitd->hw_next != EHCI_LIST_END(ehci)) - *hw_p = q.sitd->hw_next; - else - *hw_p = cpu_to_hc32(ehci, - ehci->dummy->qh_dma); + q_p = &q.sitd->sitd_next; + hw_p = &q.sitd->hw_next; type = Q_NEXT_TYPE(ehci, q.sitd->hw_next); - wmb(); - modified = sitd_complete (ehci, q.sitd); q = *q_p; break; - default: - ehci_dbg(ehci, "corrupt type %d frame %d shadow %p\n", - type, frame, q.ptr); - // BUG (); - /* FALL THROUGH */ - case Q_TYPE_QH: - case Q_TYPE_FSTN: - /* End of the iTDs and siTDs */ - q.ptr = NULL; - break; } - /* assume completion callbacks modify the queue */ - if (unlikely(modified && ehci->isoc_count > 0)) - goto restart; - } - - /* Stop when we have reached the current frame */ - if (frame == now_frame) + /* + * Take finished SITDs out of the schedule + * and process them: recycle, maybe report + * URB completion. + */ + *q_p = q.sitd->sitd_next; + if (!ehci->use_dummy_qh || + q.sitd->hw_next != EHCI_LIST_END(ehci)) + *hw_p = q.sitd->hw_next; + else + *hw_p = cpu_to_hc32(ehci, ehci->dummy->qh_dma); + type = Q_NEXT_TYPE(ehci, q.sitd->hw_next); + wmb(); + modified = sitd_complete(ehci, q.sitd); + q = *q_p; break; + default: + ehci_dbg(ehci, "corrupt type %d frame %d shadow %p\n", + type, frame, q.ptr); + /* BUG(); */ + /* FALL THROUGH */ + case Q_TYPE_QH: + case Q_TYPE_FSTN: + /* End of the iTDs and siTDs */ + q.ptr = NULL; + break; + } - /* The last frame may still have active siTDs */ - ehci->last_iso_frame = frame; - frame = (frame + 1) & fmask; + /* Assume completion callbacks modify the queue */ + if (unlikely(modified && ehci->isoc_count > 0)) + goto restart; } + + /* Stop when we have reached the current frame */ + if (frame == now_frame) + return; + + /* The last frame may still have active siTDs */ + ehci->last_iso_frame = frame; + frame = (frame + 1) & fmask; + + goto restart; } -- cgit v1.2.3 From 25d108696c00142a083c61dc5892856516d38c0d Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:11 -0300 Subject: usb: host: ehci-sched: move constants to right This patch moves the constants to right. Tested by compilation only. Caught by coccinelle: scripts/coccinelle/misc/compare_const_fl.cocci Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 74c2023763ad..f4a94d443abe 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -330,7 +330,7 @@ static int __maybe_unused same_tt(struct usb_device *dev1, */ static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask) { - unsigned char smask = QH_SMASK & hc32_to_cpu(ehci, mask); + unsigned char smask = hc32_to_cpu(ehci, mask) & QH_SMASK; if (!smask) { ehci_err(ehci, "invalid empty smask!\n"); /* uframe 7 can't have bw so this will indicate failure */ @@ -409,11 +409,11 @@ static int tt_available ( * must be empty, so as to not illegally delay * already scheduled transactions */ - if (125 < usecs) { + if (usecs > 125) { int ufs = (usecs / 125); for (i = uframe; i < (uframe + ufs) && i < 8; i++) - if (0 < tt_usecs[i]) + if (tt_usecs[i] > 0) return 0; } -- cgit v1.2.3 From 77d6554d1b40be5c522b0dc0dc0df5e164150753 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:12 -0300 Subject: usb: host: ehci-sched: remove useless initializations This patch removes useless initializations. Tested by compilation only. Caught by cppcheck. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index f4a94d443abe..b28ec83361e1 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -2132,7 +2132,7 @@ sitd_patch( ) { struct ehci_iso_packet *uf = &iso_sched->packet [index]; - u64 bufp = uf->bufp; + u64 bufp; sitd->hw_next = EHCI_LIST_END(ehci); sitd->hw_fullspeed_ep = stream->address; @@ -2242,7 +2242,7 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd) struct urb *urb = sitd->urb; struct usb_iso_packet_descriptor *desc; u32 t; - int urb_index = -1; + int urb_index; struct ehci_iso_stream *stream = sitd->stream; struct usb_device *dev; bool retval = false; -- cgit v1.2.3 From 189b8ff0daa1b12befddf03b009d55a702aeecb2 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:13 -0300 Subject: usb: host: ehci-sched: add spaces around operators This patch adds spaces around operators. Tested by compilation only. Caught by checkpatch. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index b28ec83361e1..b8cc9d4fcb66 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -346,7 +346,7 @@ max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) { int i; - for (i=0; i<7; i++) { + for (i = 0; i < 7; i++) { if (max_tt_usecs[i] < tt_usecs[i]) { tt_usecs[i+1] += tt_usecs[i] - max_tt_usecs[i]; tt_usecs[i] = max_tt_usecs[i]; -- cgit v1.2.3 From ee906470618fcc03f4ae94334f600ee4d3e67b20 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:14 -0300 Subject: usb: host: ehci-sched: remove prohibited spaces This patch removes prohibited spaces before open parenthesis and open brackets. It also removes an assignment inside condition and unnecessary braces in single statement block. Tested by compilation only. Caught by checkpatch. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 265 +++++++++++++++++++++--------------------- 1 file changed, 133 insertions(+), 132 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index b8cc9d4fcb66..11d5efdddae2 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -34,7 +34,7 @@ * pre-calculated schedule data to make appending to the queue be quick. */ -static int ehci_get_frame (struct usb_hcd *hcd); +static int ehci_get_frame(struct usb_hcd *hcd); /* * periodic_next_shadow - return "next" pointer on shadow list @@ -73,7 +73,7 @@ shadow_next_periodic(struct ehci_hcd *ehci, union ehci_shadow *periodic, } /* caller must hold ehci->lock */ -static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) +static void periodic_unlink(struct ehci_hcd *ehci, unsigned frame, void *ptr) { union ehci_shadow *prev_p = &ehci->pshadow[frame]; __hc32 *hw_p = &ehci->periodic[frame]; @@ -375,7 +375,7 @@ static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) * limit of 16, specified in USB 2.0 spec section 11.18.4 requirement #4, * since proper scheduling limits ssplits to less than 16 per uframe. */ -static int tt_available ( +static int tt_available( struct ehci_hcd *ehci, struct ehci_per_sched *ps, struct ehci_tt *tt, @@ -435,7 +435,7 @@ static int tt_available ( * for a periodic transfer starting at the specified frame, using * all the uframes in the mask. */ -static int tt_no_collision ( +static int tt_no_collision( struct ehci_hcd *ehci, unsigned period, struct usb_device *dev, @@ -455,8 +455,8 @@ static int tt_no_collision ( __hc32 type; struct ehci_qh_hw *hw; - here = ehci->pshadow [frame]; - type = Q_NEXT_TYPE(ehci, ehci->periodic [frame]); + here = ehci->pshadow[frame]; + type = Q_NEXT_TYPE(ehci, ehci->periodic[frame]); while (here.ptr) { switch (hc32_to_cpu(ehci, type)) { case Q_TYPE_ITD: @@ -479,7 +479,7 @@ static int tt_no_collision ( here = here.qh->qh_next; continue; case Q_TYPE_SITD: - if (same_tt (dev, here.sitd->urb->dev)) { + if (same_tt(dev, here.sitd->urb->dev)) { u16 mask; mask = hc32_to_cpu(ehci, here.sitd @@ -494,7 +494,7 @@ static int tt_no_collision ( continue; // case Q_TYPE_FSTN: default: - ehci_dbg (ehci, + ehci_dbg(ehci, "periodic frame %d bogus type %d\n", frame, type); } @@ -588,9 +588,9 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) qh->qh_next = here; if (here.qh) qh->hw->hw_next = *hw_p; - wmb (); + wmb(); prev->qh = qh; - *hw_p = QH_NEXT (ehci, qh->qh_dma); + *hw_p = QH_NEXT(ehci, qh->qh_dma); } } qh->qh_state = QH_STATE_LINKED; @@ -633,7 +633,7 @@ static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) period = qh->ps.period ? : 1; for (i = qh->ps.phase; i < ehci->periodic_size; i += period) - periodic_unlink (ehci, i, qh); + periodic_unlink(ehci, i, qh); /* update per-qh bandwidth for debugfs */ ehci_to_hcd(ehci)->self.bandwidth_allocated -= qh->ps.bw_period @@ -679,7 +679,7 @@ static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh) /* if the qh is waiting for unlink, cancel it now */ cancel_unlink_wait_intr(ehci, qh); - qh_unlink_periodic (ehci, qh); + qh_unlink_periodic(ehci, qh); /* Make sure the unlinks are visible before starting the timer */ wmb(); @@ -763,7 +763,7 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh) /*-------------------------------------------------------------------------*/ -static int check_period ( +static int check_period( struct ehci_hcd *ehci, unsigned frame, unsigned uframe, @@ -789,7 +789,7 @@ static int check_period ( return 1; } -static int check_intr_schedule ( +static int check_intr_schedule( struct ehci_hcd *ehci, unsigned frame, unsigned uframe, @@ -925,7 +925,7 @@ done: return status; } -static int intr_submit ( +static int intr_submit( struct ehci_hcd *ehci, struct urb *urb, struct list_head *qtd_list, @@ -940,7 +940,7 @@ static int intr_submit ( /* get endpoint and transfer/schedule data */ epnum = urb->ep->desc.bEndpointAddress; - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { status = -ESHUTDOWN; @@ -951,20 +951,21 @@ static int intr_submit ( goto done_not_linked; /* get qh and force any scheduling errors */ - INIT_LIST_HEAD (&empty); + INIT_LIST_HEAD(&empty); qh = qh_append_tds(ehci, urb, &empty, epnum, &urb->ep->hcpriv); if (qh == NULL) { status = -ENOMEM; goto done; } if (qh->qh_state == QH_STATE_IDLE) { - if ((status = qh_schedule (ehci, qh)) != 0) + status = qh_schedule(ehci, qh); + if (status) goto done; } /* then queue the urb's tds to the qh */ qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv); - BUG_ON (qh == NULL); + BUG_ON(qh == NULL); /* stuff into the periodic schedule */ if (qh->qh_state == QH_STATE_IDLE) { @@ -982,9 +983,9 @@ done: if (unlikely(status)) usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); done_not_linked: - spin_unlock_irqrestore (&ehci->lock, flags); + spin_unlock_irqrestore(&ehci->lock, flags); if (status) - qtd_list_free (ehci, urb, qtd_list); + qtd_list_free(ehci, urb, qtd_list); return status; } @@ -1022,12 +1023,12 @@ static void scan_intr(struct ehci_hcd *ehci) /* ehci_iso_stream ops work with both ITD and SITD */ static struct ehci_iso_stream * -iso_stream_alloc (gfp_t mem_flags) +iso_stream_alloc(gfp_t mem_flags) { struct ehci_iso_stream *stream; stream = kzalloc(sizeof *stream, mem_flags); - if (likely (stream != NULL)) { + if (likely(stream != NULL)) { INIT_LIST_HEAD(&stream->td_list); INIT_LIST_HEAD(&stream->free_list); stream->next_uframe = NO_FRAME; @@ -1037,13 +1038,13 @@ iso_stream_alloc (gfp_t mem_flags) } static void -iso_stream_init ( +iso_stream_init( struct ehci_hcd *ehci, struct ehci_iso_stream *stream, struct urb *urb ) { - static const u8 smask_out [] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f }; + static const u8 smask_out[] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f }; struct usb_device *dev = urb->dev; u32 buf1; @@ -1111,7 +1112,7 @@ iso_stream_init ( think_time = dev->tt ? dev->tt->think_time : 0; stream->ps.tt_usecs = NS_TO_US(think_time + usb_calc_bus_time( dev->speed, is_input, 1, maxp)); - hs_transfers = max (1u, (maxp + 187) / 188); + hs_transfers = max(1u, (maxp + 187) / 188); if (is_input) { u32 tmp; @@ -1151,7 +1152,7 @@ iso_stream_init ( } static struct ehci_iso_stream * -iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) +iso_stream_find(struct ehci_hcd *ehci, struct urb *urb) { unsigned epnum; struct ehci_iso_stream *stream; @@ -1164,25 +1165,25 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) else ep = urb->dev->ep_out[epnum]; - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); stream = ep->hcpriv; - if (unlikely (stream == NULL)) { + if (unlikely(stream == NULL)) { stream = iso_stream_alloc(GFP_ATOMIC); - if (likely (stream != NULL)) { + if (likely(stream != NULL)) { ep->hcpriv = stream; iso_stream_init(ehci, stream, urb); } /* if dev->ep [epnum] is a QH, hw is set */ - } else if (unlikely (stream->hw != NULL)) { - ehci_dbg (ehci, "dev %s ep%d%s, not iso??\n", + } else if (unlikely(stream->hw != NULL)) { + ehci_dbg(ehci, "dev %s ep%d%s, not iso??\n", urb->dev->devpath, epnum, usb_pipein(urb->pipe) ? "in" : "out"); stream = NULL; } - spin_unlock_irqrestore (&ehci->lock, flags); + spin_unlock_irqrestore(&ehci->lock, flags); return stream; } @@ -1191,16 +1192,16 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) /* ehci_iso_sched ops can be ITD-only or SITD-only */ static struct ehci_iso_sched * -iso_sched_alloc (unsigned packets, gfp_t mem_flags) +iso_sched_alloc(unsigned packets, gfp_t mem_flags) { struct ehci_iso_sched *iso_sched; int size = sizeof *iso_sched; - size += packets * sizeof (struct ehci_iso_packet); + size += packets * sizeof(struct ehci_iso_packet); iso_sched = kzalloc(size, mem_flags); - if (likely (iso_sched != NULL)) { - INIT_LIST_HEAD (&iso_sched->td_list); - } + if (likely(iso_sched != NULL)) + INIT_LIST_HEAD(&iso_sched->td_list); + return iso_sched; } @@ -1222,17 +1223,17 @@ itd_sched_init( * when we fit new itds into the schedule. */ for (i = 0; i < urb->number_of_packets; i++) { - struct ehci_iso_packet *uframe = &iso_sched->packet [i]; + struct ehci_iso_packet *uframe = &iso_sched->packet[i]; unsigned length; dma_addr_t buf; u32 trans; - length = urb->iso_frame_desc [i].length; - buf = dma + urb->iso_frame_desc [i].offset; + length = urb->iso_frame_desc[i].length; + buf = dma + urb->iso_frame_desc[i].offset; trans = EHCI_ISOC_ACTIVE; trans |= buf & 0x0fff; - if (unlikely (((i + 1) == urb->number_of_packets)) + if (unlikely(((i + 1) == urb->number_of_packets)) && !(urb->transfer_flags & URB_NO_INTERRUPT)) trans |= EHCI_ITD_IOC; trans |= length << 16; @@ -1241,13 +1242,13 @@ itd_sched_init( /* might need to cross a buffer page within a uframe */ uframe->bufp = (buf & ~(u64)0x0fff); buf += length; - if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff)))) + if (unlikely((uframe->bufp != (buf & ~(u64)0x0fff)))) uframe->cross = 1; } } static void -iso_sched_free ( +iso_sched_free( struct ehci_iso_stream *stream, struct ehci_iso_sched *iso_sched ) @@ -1255,12 +1256,12 @@ iso_sched_free ( if (!iso_sched) return; // caller must hold ehci->lock! - list_splice (&iso_sched->td_list, &stream->free_list); - kfree (iso_sched); + list_splice(&iso_sched->td_list, &stream->free_list); + kfree(iso_sched); } static int -itd_urb_transaction ( +itd_urb_transaction( struct ehci_iso_stream *stream, struct ehci_hcd *ehci, struct urb *urb, @@ -1274,8 +1275,8 @@ itd_urb_transaction ( struct ehci_iso_sched *sched; unsigned long flags; - sched = iso_sched_alloc (urb->number_of_packets, mem_flags); - if (unlikely (sched == NULL)) + sched = iso_sched_alloc(urb->number_of_packets, mem_flags); + if (unlikely(sched == NULL)) return -ENOMEM; itd_sched_init(ehci, sched, stream, urb); @@ -1286,7 +1287,7 @@ itd_urb_transaction ( num_itds = urb->number_of_packets; /* allocate/init ITDs */ - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); for (i = 0; i < num_itds; i++) { /* @@ -1298,14 +1299,14 @@ itd_urb_transaction ( struct ehci_itd, itd_list); if (itd->frame == ehci->now_frame) goto alloc_itd; - list_del (&itd->itd_list); + list_del(&itd->itd_list); itd_dma = itd->itd_dma; } else { alloc_itd: - spin_unlock_irqrestore (&ehci->lock, flags); - itd = dma_pool_alloc (ehci->itd_pool, mem_flags, + spin_unlock_irqrestore(&ehci->lock, flags); + itd = dma_pool_alloc(ehci->itd_pool, mem_flags, &itd_dma); - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); if (!itd) { iso_sched_free(stream, sched); spin_unlock_irqrestore(&ehci->lock, flags); @@ -1313,12 +1314,12 @@ itd_urb_transaction ( } } - memset (itd, 0, sizeof *itd); + memset(itd, 0, sizeof *itd); itd->itd_dma = itd_dma; itd->frame = NO_FRAME; - list_add (&itd->itd_list, &sched->td_list); + list_add(&itd->itd_list, &sched->td_list); } - spin_unlock_irqrestore (&ehci->lock, flags); + spin_unlock_irqrestore(&ehci->lock, flags); /* temporarily store schedule info in hcpriv */ urb->hcpriv = sched; @@ -1385,7 +1386,7 @@ static void reserve_release_iso_bandwidth(struct ehci_hcd *ehci, } static inline int -itd_slot_ok ( +itd_slot_ok( struct ehci_hcd *ehci, struct ehci_iso_stream *stream, unsigned uframe @@ -1405,7 +1406,7 @@ itd_slot_ok ( } static inline int -sitd_slot_ok ( +sitd_slot_ok( struct ehci_hcd *ehci, struct ehci_iso_stream *stream, unsigned uframe, @@ -1492,7 +1493,7 @@ sitd_slot_ok ( */ static int -iso_stream_schedule ( +iso_stream_schedule( struct ehci_hcd *ehci, struct urb *urb, struct ehci_iso_stream *stream @@ -1693,9 +1694,9 @@ itd_init(struct ehci_hcd *ehci, struct ehci_iso_stream *stream, /* it's been recently zeroed */ itd->hw_next = EHCI_LIST_END(ehci); - itd->hw_bufp [0] = stream->buf0; - itd->hw_bufp [1] = stream->buf1; - itd->hw_bufp [2] = stream->buf2; + itd->hw_bufp[0] = stream->buf0; + itd->hw_bufp[1] = stream->buf1; + itd->hw_bufp[2] = stream->buf2; for (i = 0; i < 8; i++) itd->index[i] = -1; @@ -1712,13 +1713,13 @@ itd_patch( u16 uframe ) { - struct ehci_iso_packet *uf = &iso_sched->packet [index]; + struct ehci_iso_packet *uf = &iso_sched->packet[index]; unsigned pg = itd->pg; // BUG_ON (pg == 6 && uf->cross); uframe &= 0x07; - itd->index [uframe] = index; + itd->index[uframe] = index; itd->hw_transaction[uframe] = uf->transaction; itd->hw_transaction[uframe] |= cpu_to_hc32(ehci, pg << 12); @@ -1726,7 +1727,7 @@ itd_patch( itd->hw_bufp_hi[pg] |= cpu_to_hc32(ehci, (u32)(uf->bufp >> 32)); /* iso_frame_desc[].offset must be strictly increasing */ - if (unlikely (uf->cross)) { + if (unlikely(uf->cross)) { u64 bufp = uf->bufp + 4096; itd->pg = ++pg; @@ -1736,7 +1737,7 @@ itd_patch( } static inline void -itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) +itd_link(struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) { union ehci_shadow *prev = &ehci->pshadow[frame]; __hc32 *hw_p = &ehci->periodic[frame]; @@ -1757,7 +1758,7 @@ itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) itd->hw_next = *hw_p; prev->itd = itd; itd->frame = frame; - wmb (); + wmb(); *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD); } @@ -1776,7 +1777,7 @@ static void itd_link_urb( next_uframe = stream->next_uframe & (mod - 1); - if (unlikely (list_empty(&stream->td_list))) + if (unlikely(list_empty(&stream->td_list))) ehci_to_hcd(ehci)->self.bandwidth_allocated += stream->bandwidth; @@ -1796,12 +1797,12 @@ static void itd_link_urb( /* ASSERT: no itds for this endpoint in this uframe */ - itd = list_entry (iso_sched->td_list.next, + itd = list_entry(iso_sched->td_list.next, struct ehci_itd, itd_list); - list_move_tail (&itd->itd_list, &stream->td_list); + list_move_tail(&itd->itd_list, &stream->td_list); itd->stream = stream; itd->urb = urb; - itd_init (ehci, stream, itd); + itd_init(ehci, stream, itd); } uframe = next_uframe & 0x07; @@ -1823,7 +1824,7 @@ static void itd_link_urb( stream->next_uframe = next_uframe; /* don't need that schedule data any more */ - iso_sched_free (stream, iso_sched); + iso_sched_free(stream, iso_sched); urb->hcpriv = stream; ++ehci->isoc_count; @@ -1855,19 +1856,19 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd) /* for each uframe with a packet */ for (uframe = 0; uframe < 8; uframe++) { - if (likely (itd->index[uframe] == -1)) + if (likely(itd->index[uframe] == -1)) continue; urb_index = itd->index[uframe]; - desc = &urb->iso_frame_desc [urb_index]; + desc = &urb->iso_frame_desc[urb_index]; - t = hc32_to_cpup(ehci, &itd->hw_transaction [uframe]); - itd->hw_transaction [uframe] = 0; + t = hc32_to_cpup(ehci, &itd->hw_transaction[uframe]); + itd->hw_transaction[uframe] = 0; /* report transfer status */ - if (unlikely (t & ISO_ERRS)) { + if (unlikely(t & ISO_ERRS)) { urb->error_count++; if (t & EHCI_ISOC_BUF_ERR) - desc->status = usb_pipein (urb->pipe) + desc->status = usb_pipein(urb->pipe) ? -ENOSR /* hc couldn't read */ : -ECOMM; /* hc couldn't write */ else if (t & EHCI_ISOC_BABBLE) @@ -1880,7 +1881,7 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd) desc->actual_length = EHCI_ITD_LENGTH(t); urb->actual_length += desc->actual_length; } - } else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) { + } else if (likely((t & EHCI_ISOC_ACTIVE) == 0)) { desc->status = 0; desc->actual_length = EHCI_ITD_LENGTH(t); urb->actual_length += desc->actual_length; @@ -1891,7 +1892,7 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd) } /* handle completion now? */ - if (likely ((urb_index + 1) != urb->number_of_packets)) + if (likely((urb_index + 1) != urb->number_of_packets)) goto done; /* ASSERT: it's really the last itd for this urb @@ -1936,7 +1937,7 @@ done: /*-------------------------------------------------------------------------*/ -static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, +static int itd_submit(struct ehci_hcd *ehci, struct urb *urb, gfp_t mem_flags) { int status = -EINVAL; @@ -1944,37 +1945,37 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, struct ehci_iso_stream *stream; /* Get iso_stream head */ - stream = iso_stream_find (ehci, urb); - if (unlikely (stream == NULL)) { - ehci_dbg (ehci, "can't get iso stream\n"); + stream = iso_stream_find(ehci, urb); + if (unlikely(stream == NULL)) { + ehci_dbg(ehci, "can't get iso stream\n"); return -ENOMEM; } if (unlikely(urb->interval != stream->uperiod)) { - ehci_dbg (ehci, "can't change iso interval %d --> %d\n", + ehci_dbg(ehci, "can't change iso interval %d --> %d\n", stream->uperiod, urb->interval); goto done; } #ifdef EHCI_URB_TRACE - ehci_dbg (ehci, + ehci_dbg(ehci, "%s %s urb %p ep%d%s len %d, %d pkts %d uframes [%p]\n", __func__, urb->dev->devpath, urb, - usb_pipeendpoint (urb->pipe), - usb_pipein (urb->pipe) ? "in" : "out", + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out", urb->transfer_buffer_length, urb->number_of_packets, urb->interval, stream); #endif /* allocate ITDs w/o locking anything */ - status = itd_urb_transaction (stream, ehci, urb, mem_flags); - if (unlikely (status < 0)) { - ehci_dbg (ehci, "can't init itds\n"); + status = itd_urb_transaction(stream, ehci, urb, mem_flags); + if (unlikely(status < 0)) { + ehci_dbg(ehci, "can't init itds\n"); goto done; } /* schedule ... need to lock */ - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { status = -ESHUTDOWN; goto done_not_linked; @@ -1984,7 +1985,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, goto done_not_linked; status = iso_stream_schedule(ehci, urb, stream); if (likely(status == 0)) { - itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); + itd_link_urb(ehci, urb, ehci->periodic_size << 3, stream); } else if (status > 0) { status = 0; ehci_urb_done(ehci, urb, 0); @@ -1992,7 +1993,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); } done_not_linked: - spin_unlock_irqrestore (&ehci->lock, flags); + spin_unlock_irqrestore(&ehci->lock, flags); done: return status; } @@ -2022,13 +2023,13 @@ sitd_sched_init( * when we fit new sitds into the schedule. */ for (i = 0; i < urb->number_of_packets; i++) { - struct ehci_iso_packet *packet = &iso_sched->packet [i]; + struct ehci_iso_packet *packet = &iso_sched->packet[i]; unsigned length; dma_addr_t buf; u32 trans; - length = urb->iso_frame_desc [i].length & 0x03ff; - buf = dma + urb->iso_frame_desc [i].offset; + length = urb->iso_frame_desc[i].length & 0x03ff; + buf = dma + urb->iso_frame_desc[i].offset; trans = SITD_STS_ACTIVE; if (((i + 1) == urb->number_of_packets) @@ -2054,7 +2055,7 @@ sitd_sched_init( } static int -sitd_urb_transaction ( +sitd_urb_transaction( struct ehci_iso_stream *stream, struct ehci_hcd *ehci, struct urb *urb, @@ -2067,14 +2068,14 @@ sitd_urb_transaction ( struct ehci_iso_sched *iso_sched; unsigned long flags; - iso_sched = iso_sched_alloc (urb->number_of_packets, mem_flags); + iso_sched = iso_sched_alloc(urb->number_of_packets, mem_flags); if (iso_sched == NULL) return -ENOMEM; sitd_sched_init(ehci, iso_sched, stream, urb); /* allocate/init sITDs */ - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); for (i = 0; i < urb->number_of_packets; i++) { /* NOTE: for now, we don't try to handle wraparound cases @@ -2091,14 +2092,14 @@ sitd_urb_transaction ( struct ehci_sitd, sitd_list); if (sitd->frame == ehci->now_frame) goto alloc_sitd; - list_del (&sitd->sitd_list); + list_del(&sitd->sitd_list); sitd_dma = sitd->sitd_dma; } else { alloc_sitd: - spin_unlock_irqrestore (&ehci->lock, flags); - sitd = dma_pool_alloc (ehci->sitd_pool, mem_flags, + spin_unlock_irqrestore(&ehci->lock, flags); + sitd = dma_pool_alloc(ehci->sitd_pool, mem_flags, &sitd_dma); - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); if (!sitd) { iso_sched_free(stream, iso_sched); spin_unlock_irqrestore(&ehci->lock, flags); @@ -2106,17 +2107,17 @@ sitd_urb_transaction ( } } - memset (sitd, 0, sizeof *sitd); + memset(sitd, 0, sizeof *sitd); sitd->sitd_dma = sitd_dma; sitd->frame = NO_FRAME; - list_add (&sitd->sitd_list, &iso_sched->td_list); + list_add(&sitd->sitd_list, &iso_sched->td_list); } /* temporarily store schedule info in hcpriv */ urb->hcpriv = iso_sched; urb->error_count = 0; - spin_unlock_irqrestore (&ehci->lock, flags); + spin_unlock_irqrestore(&ehci->lock, flags); return 0; } @@ -2131,7 +2132,7 @@ sitd_patch( unsigned index ) { - struct ehci_iso_packet *uf = &iso_sched->packet [index]; + struct ehci_iso_packet *uf = &iso_sched->packet[index]; u64 bufp; sitd->hw_next = EHCI_LIST_END(ehci); @@ -2152,14 +2153,14 @@ sitd_patch( } static inline void -sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd) +sitd_link(struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd) { /* note: sitd ordering could matter (CSPLIT then SSPLIT) */ - sitd->sitd_next = ehci->pshadow [frame]; - sitd->hw_next = ehci->periodic [frame]; - ehci->pshadow [frame].sitd = sitd; + sitd->sitd_next = ehci->pshadow[frame]; + sitd->hw_next = ehci->periodic[frame]; + ehci->pshadow[frame].sitd = sitd; sitd->frame = frame; - wmb (); + wmb(); ehci->periodic[frame] = cpu_to_hc32(ehci, sitd->sitd_dma | Q_TYPE_SITD); } @@ -2196,13 +2197,13 @@ static void sitd_link_urb( packet++) { /* ASSERT: we have all necessary sitds */ - BUG_ON (list_empty (&sched->td_list)); + BUG_ON(list_empty(&sched->td_list)); /* ASSERT: no itds for this endpoint in this frame */ - sitd = list_entry (sched->td_list.next, + sitd = list_entry(sched->td_list.next, struct ehci_sitd, sitd_list); - list_move_tail (&sitd->sitd_list, &stream->td_list); + list_move_tail(&sitd->sitd_list, &stream->td_list); sitd->stream = stream; sitd->urb = urb; @@ -2215,7 +2216,7 @@ static void sitd_link_urb( stream->next_uframe = next_uframe & (mod - 1); /* don't need that schedule data any more */ - iso_sched_free (stream, sched); + iso_sched_free(stream, sched); urb->hcpriv = stream; ++ehci->isoc_count; @@ -2248,14 +2249,14 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd) bool retval = false; urb_index = sitd->index; - desc = &urb->iso_frame_desc [urb_index]; + desc = &urb->iso_frame_desc[urb_index]; t = hc32_to_cpup(ehci, &sitd->hw_results); /* report transfer status */ if (unlikely(t & SITD_ERRS)) { urb->error_count++; if (t & SITD_STS_DBE) - desc->status = usb_pipein (urb->pipe) + desc->status = usb_pipein(urb->pipe) ? -ENOSR /* hc couldn't read */ : -ECOMM; /* hc couldn't write */ else if (t & SITD_STS_BABBLE) @@ -2316,7 +2317,7 @@ done: } -static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, +static int sitd_submit(struct ehci_hcd *ehci, struct urb *urb, gfp_t mem_flags) { int status = -EINVAL; @@ -2324,35 +2325,35 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, struct ehci_iso_stream *stream; /* Get iso_stream head */ - stream = iso_stream_find (ehci, urb); + stream = iso_stream_find(ehci, urb); if (stream == NULL) { - ehci_dbg (ehci, "can't get iso stream\n"); + ehci_dbg(ehci, "can't get iso stream\n"); return -ENOMEM; } if (urb->interval != stream->ps.period) { - ehci_dbg (ehci, "can't change iso interval %d --> %d\n", + ehci_dbg(ehci, "can't change iso interval %d --> %d\n", stream->ps.period, urb->interval); goto done; } #ifdef EHCI_URB_TRACE - ehci_dbg (ehci, + ehci_dbg(ehci, "submit %p dev%s ep%d%s-iso len %d\n", urb, urb->dev->devpath, - usb_pipeendpoint (urb->pipe), - usb_pipein (urb->pipe) ? "in" : "out", + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out", urb->transfer_buffer_length); #endif /* allocate SITDs */ - status = sitd_urb_transaction (stream, ehci, urb, mem_flags); + status = sitd_urb_transaction(stream, ehci, urb, mem_flags); if (status < 0) { - ehci_dbg (ehci, "can't init sitds\n"); + ehci_dbg(ehci, "can't init sitds\n"); goto done; } /* schedule ... need to lock */ - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { status = -ESHUTDOWN; goto done_not_linked; @@ -2362,7 +2363,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, goto done_not_linked; status = iso_stream_schedule(ehci, urb, stream); if (likely(status == 0)) { - sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); + sitd_link_urb(ehci, urb, ehci->periodic_size << 3, stream); } else if (status > 0) { status = 0; ehci_urb_done(ehci, urb, 0); @@ -2370,7 +2371,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); } done_not_linked: - spin_unlock_irqrestore (&ehci->lock, flags); + spin_unlock_irqrestore(&ehci->lock, flags); done: return status; } -- cgit v1.2.3 From 2fee2fed78cb8952982ffc22cbdcf8e6327c1407 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:15 -0300 Subject: usb: host: ehci-sched: remove useless else branch This patch removes an useless else branch after a break, reducing one indent block. Tested by compilation only. Caught by checkpatch. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 11d5efdddae2..8b3abdcca08f 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -296,10 +296,9 @@ static void compute_tt_budget(u8 budget_table[EHCI_BANDWIDTH_SIZE], if (x <= 125) { budget_line[uf] = x; break; - } else { - budget_line[uf] = 125; - x -= 125; } + budget_line[uf] = 125; + x -= 125; } } } -- cgit v1.2.3 From 1ec2780cd7d25619faf9db1aa97eef6c453f0fad Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:16 -0300 Subject: usb: host: ehci-sched: use C89-style comments This patch changes comments conforming coding style. Caught by checkpatch. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 8b3abdcca08f..682fb42ca508 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -52,7 +52,7 @@ periodic_next_shadow(struct ehci_hcd *ehci, union ehci_shadow *periodic, return &periodic->fstn->fstn_next; case Q_TYPE_ITD: return &periodic->itd->itd_next; - // case Q_TYPE_SITD: + /* case Q_TYPE_SITD: */ default: return &periodic->sitd->sitd_next; } @@ -491,7 +491,7 @@ static int tt_no_collision( type = Q_NEXT_TYPE(ehci, here.sitd->hw_next); here = here.sitd->sitd_next; continue; - // case Q_TYPE_FSTN: + /* case Q_TYPE_FSTN: */ default: ehci_dbg(ehci, "periodic frame %d bogus type %d\n", @@ -784,7 +784,7 @@ static int check_period( return 0; } - // success! + /* success! */ return 1; } @@ -1254,7 +1254,7 @@ iso_sched_free( { if (!iso_sched) return; - // caller must hold ehci->lock! + /* caller must hold ehci->lock! */ list_splice(&iso_sched->td_list, &stream->free_list); kfree(iso_sched); } @@ -1715,7 +1715,7 @@ itd_patch( struct ehci_iso_packet *uf = &iso_sched->packet[index]; unsigned pg = itd->pg; - // BUG_ON (pg == 6 && uf->cross); + /* BUG_ON(pg == 6 && uf->cross); */ uframe &= 0x07; itd->index[uframe] = index; @@ -1792,7 +1792,7 @@ static void itd_link_urb( packet < urb->number_of_packets;) { if (itd == NULL) { /* ASSERT: we have all necessary itds */ - // BUG_ON (list_empty (&iso_sched->td_list)); + /* BUG_ON(list_empty(&iso_sched->td_list)); */ /* ASSERT: no itds for this endpoint in this uframe */ @@ -1894,9 +1894,10 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd) if (likely((urb_index + 1) != urb->number_of_packets)) goto done; - /* ASSERT: it's really the last itd for this urb - list_for_each_entry (itd, &stream->td_list, itd_list) - BUG_ON (itd->urb == urb); + /* + * ASSERT: it's really the last itd for this urb + * list_for_each_entry (itd, &stream->td_list, itd_list) + * BUG_ON(itd->urb == urb); */ /* give urb back to the driver; completion often (re)submits */ @@ -2275,9 +2276,10 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd) if ((urb_index + 1) != urb->number_of_packets) goto done; - /* ASSERT: it's really the last sitd for this urb - list_for_each_entry (sitd, &stream->td_list, sitd_list) - BUG_ON (sitd->urb == urb); + /* + * ASSERT: it's really the last sitd for this urb + * list_for_each_entry (sitd, &stream->td_list, sitd_list) + * BUG_ON(sitd->urb == urb); */ /* give urb back to the driver; completion often (re)submits */ -- cgit v1.2.3 From 6d0febcd271902bc6dba20aceea66a8bd9023198 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:17 -0300 Subject: usb: host: ehci-sched: add line after declarations This patch adds a blank line after declarations. Caught by checkpatch. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 682fb42ca508..b7b40ed6eeba 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -330,6 +330,7 @@ static int __maybe_unused same_tt(struct usb_device *dev1, static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask) { unsigned char smask = hc32_to_cpu(ehci, mask) & QH_SMASK; + if (!smask) { ehci_err(ehci, "invalid empty smask!\n"); /* uframe 7 can't have bw so this will indicate failure */ @@ -345,6 +346,7 @@ max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) { int i; + for (i = 0; i < 7; i++) { if (max_tt_usecs[i] < tt_usecs[i]) { tt_usecs[i+1] += tt_usecs[i] - max_tt_usecs[i]; -- cgit v1.2.3 From ee2a1d24b9b37686214aecfccccf611be6bc0144 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:18 -0300 Subject: usb: host: ehci-sched: use sizeof operator with parens This patch adds parens to sizeof operator uses. Tested by compilation only. Caught by checkpatch. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index b7b40ed6eeba..5e5d50b40d04 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1028,7 +1028,7 @@ iso_stream_alloc(gfp_t mem_flags) { struct ehci_iso_stream *stream; - stream = kzalloc(sizeof *stream, mem_flags); + stream = kzalloc(sizeof(*stream), mem_flags); if (likely(stream != NULL)) { INIT_LIST_HEAD(&stream->td_list); INIT_LIST_HEAD(&stream->free_list); @@ -1196,7 +1196,7 @@ static struct ehci_iso_sched * iso_sched_alloc(unsigned packets, gfp_t mem_flags) { struct ehci_iso_sched *iso_sched; - int size = sizeof *iso_sched; + int size = sizeof(*iso_sched); size += packets * sizeof(struct ehci_iso_packet); iso_sched = kzalloc(size, mem_flags); @@ -1315,7 +1315,7 @@ itd_urb_transaction( } } - memset(itd, 0, sizeof *itd); + memset(itd, 0, sizeof(*itd)); itd->itd_dma = itd_dma; itd->frame = NO_FRAME; list_add(&itd->itd_list, &sched->td_list); @@ -2109,7 +2109,7 @@ sitd_urb_transaction( } } - memset(sitd, 0, sizeof *sitd); + memset(sitd, 0, sizeof(*sitd)); sitd->sitd_dma = sitd_dma; sitd->frame = NO_FRAME; list_add(&sitd->sitd_list, &iso_sched->td_list); -- cgit v1.2.3 From d078c6e4ea5e6a93d44d5815d0ee4a9bb5c5718b Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:19 -0300 Subject: usb: host: ehci-sched: remove unnecessary braces This patch removes unnecessary braces in single statement blocks at the same time as replaces the if statement with a ternary conditional. Tested by compilation only. Caught by checkpatch. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 5e5d50b40d04..1dfe54f14737 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1060,11 +1060,7 @@ iso_stream_init( epnum = usb_pipeendpoint(urb->pipe); is_input = usb_pipein(urb->pipe) ? USB_DIR_IN : 0; maxp = usb_endpoint_maxp(&urb->ep->desc); - if (is_input) { - buf1 = (1 << 11); - } else { - buf1 = 0; - } + buf1 = is_input ? 1 << 11 : 0; /* knows about ITD vs SITD */ if (dev->speed == USB_SPEED_HIGH) { -- cgit v1.2.3 From e6533e879fd24f36c50a9db3b41d3433784222ff Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Wed, 27 Jan 2016 00:12:23 +0530 Subject: usb: storage: ene_ub6250: Remove unnecessary cast in kfree Remove unnecassary casts in the argument to kfree. Found using Coccinelle. The semantic patch used to find this is as follows: // @@ type T; expression *f; @@ - kfree((T *)(f)); + kfree(f); // Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/ene_ub6250.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index f3cf4cecd2b7..d3a17c65a702 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -1067,12 +1067,12 @@ static void ms_lib_free_writebuf(struct us_data *us) ms_lib_clear_pagemap(info); /* (pdx)->MS_Lib.pagemap memset 0 in ms.h */ if (info->MS_Lib.blkpag) { - kfree((u8 *)(info->MS_Lib.blkpag)); /* Arnold test ... */ + kfree(info->MS_Lib.blkpag); /* Arnold test ... */ info->MS_Lib.blkpag = NULL; } if (info->MS_Lib.blkext) { - kfree((u8 *)(info->MS_Lib.blkext)); /* Arnold test ... */ + kfree(info->MS_Lib.blkext); /* Arnold test ... */ info->MS_Lib.blkext = NULL; } } -- cgit v1.2.3 From 46e3cafb01feb107a681e89fd9b4f1cd938a601f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 30 Jan 2016 17:34:55 +0300 Subject: USB: cxacru: fix an bounds check warning This is a privileged operation so it doesn't matter much. We use "tmp" as an offset into an array. If it were invalid we could read out of bounds and trigger an oops if the memory is not mapped. Plus it makes static checkers complain. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/cxacru.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 1173f9cbc137..0a866e90b49c 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -476,6 +476,8 @@ static ssize_t cxacru_sysfs_store_adsl_config(struct device *dev, return -EINVAL; if (index < 0 || index > 0x7f) return -EINVAL; + if (tmp < 0 || tmp > len - pos) + return -EINVAL; pos += tmp; /* skip trailing newline */ -- cgit v1.2.3 From 21619792d1eca7e772ca190ba68588e57f29595b Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 2 Feb 2016 17:36:39 +0000 Subject: usb: usbip: Fix possible deadlocks reported by lockdep Change spin_lock calls to spin_lock_irqsave to prevent attmpted recursive lock taking in interrupt context. This patch fixes Bug 109351 https://bugzilla.kernel.org/show_bug.cgi?id=109351 Signed-off-by: Andrew Goodbody Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/usbip_event.c | 5 ++- drivers/usb/usbip/vhci_hcd.c | 88 ++++++++++++++++++++++++----------------- drivers/usb/usbip/vhci_rx.c | 30 ++++++++------ drivers/usb/usbip/vhci_sysfs.c | 19 +++++---- drivers/usb/usbip/vhci_tx.c | 14 ++++--- 5 files changed, 91 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/usbip/usbip_event.c b/drivers/usb/usbip/usbip_event.c index 64933b993d7a..2580a32bcdff 100644 --- a/drivers/usb/usbip/usbip_event.c +++ b/drivers/usb/usbip/usbip_event.c @@ -117,11 +117,12 @@ EXPORT_SYMBOL_GPL(usbip_event_add); int usbip_event_happened(struct usbip_device *ud) { int happened = 0; + unsigned long flags; - spin_lock(&ud->lock); + spin_lock_irqsave(&ud->lock, flags); if (ud->event != 0) happened = 1; - spin_unlock(&ud->lock); + spin_unlock_irqrestore(&ud->lock, flags); return happened; } diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c index 7fbe19d5279e..fca51105974e 100644 --- a/drivers/usb/usbip/vhci_hcd.c +++ b/drivers/usb/usbip/vhci_hcd.c @@ -121,9 +121,11 @@ static void dump_port_status_diff(u32 prev_status, u32 new_status) void rh_port_connect(int rhport, enum usb_device_speed speed) { + unsigned long flags; + usbip_dbg_vhci_rh("rh_port_connect %d\n", rhport); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); the_controller->port_status[rhport] |= USB_PORT_STAT_CONNECTION | (1 << USB_PORT_FEAT_C_CONNECTION); @@ -139,22 +141,24 @@ void rh_port_connect(int rhport, enum usb_device_speed speed) break; } - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_poll_rh_status(vhci_to_hcd(the_controller)); } static void rh_port_disconnect(int rhport) { + unsigned long flags; + usbip_dbg_vhci_rh("rh_port_disconnect %d\n", rhport); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); the_controller->port_status[rhport] &= ~USB_PORT_STAT_CONNECTION; the_controller->port_status[rhport] |= (1 << USB_PORT_FEAT_C_CONNECTION); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_poll_rh_status(vhci_to_hcd(the_controller)); } @@ -182,13 +186,14 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf) int retval; int rhport; int changed = 0; + unsigned long flags; retval = DIV_ROUND_UP(VHCI_NPORTS + 1, 8); memset(buf, 0, retval); vhci = hcd_to_vhci(hcd); - spin_lock(&vhci->lock); + spin_lock_irqsave(&vhci->lock, flags); if (!HCD_HW_ACCESSIBLE(hcd)) { usbip_dbg_vhci_rh("hw accessible flag not on?\n"); goto done; @@ -209,7 +214,7 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf) usb_hcd_resume_root_hub(hcd); done: - spin_unlock(&vhci->lock); + spin_unlock_irqrestore(&vhci->lock, flags); return changed ? retval : 0; } @@ -231,6 +236,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, struct vhci_hcd *dum; int retval = 0; int rhport; + unsigned long flags; u32 prev_port_status[VHCI_NPORTS]; @@ -249,7 +255,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, dum = hcd_to_vhci(hcd); - spin_lock(&dum->lock); + spin_lock_irqsave(&dum->lock, flags); /* store old status and compare now and old later */ if (usbip_dbg_flag_vhci_rh) { @@ -403,7 +409,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, } usbip_dbg_vhci_rh(" bye\n"); - spin_unlock(&dum->lock); + spin_unlock_irqrestore(&dum->lock, flags); return retval; } @@ -426,6 +432,7 @@ static void vhci_tx_urb(struct urb *urb) { struct vhci_device *vdev = get_vdev(urb->dev); struct vhci_priv *priv; + unsigned long flags; if (!vdev) { pr_err("could not get virtual device"); @@ -438,7 +445,7 @@ static void vhci_tx_urb(struct urb *urb) return; } - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); priv->seqnum = atomic_inc_return(&the_controller->seqnum); if (priv->seqnum == 0xffff) @@ -452,7 +459,7 @@ static void vhci_tx_urb(struct urb *urb) list_add_tail(&priv->list, &vdev->priv_tx); wake_up(&vdev->waitq_tx); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); } static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, @@ -461,6 +468,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, struct device *dev = &urb->dev->dev; int ret = 0; struct vhci_device *vdev; + unsigned long flags; usbip_dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n", hcd, urb, mem_flags); @@ -468,11 +476,11 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, /* patch to usb_sg_init() is in 2.5.60 */ BUG_ON(!urb->transfer_buffer && urb->transfer_buffer_length); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); if (urb->status != -EINPROGRESS) { dev_err(dev, "URB already unlinked!, status %d\n", urb->status); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return urb->status; } @@ -484,7 +492,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, vdev->ud.status == VDEV_ST_ERROR) { dev_err(dev, "enqueue for inactive port %d\n", vdev->rhport); spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return -ENODEV; } spin_unlock(&vdev->ud.lock); @@ -557,14 +565,14 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, out: vhci_tx_urb(urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return 0; no_need_xmit: usb_hcd_unlink_urb_from_ep(hcd, urb); no_need_unlink: - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); if (!ret) usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); @@ -621,16 +629,17 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) { struct vhci_priv *priv; struct vhci_device *vdev; + unsigned long flags; pr_info("dequeue a urb %p\n", urb); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); priv = urb->hcpriv; if (!priv) { /* URB was never linked! or will be soon given back by * vhci_rx. */ - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return -EIDRM; } @@ -639,7 +648,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ret = usb_hcd_check_unlink_urb(hcd, urb, status); if (ret) { - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return ret; } } @@ -667,10 +676,10 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) usb_hcd_unlink_urb_from_ep(hcd, urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); } else { /* tcp connection is alive */ @@ -682,7 +691,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) unlink = kzalloc(sizeof(struct vhci_unlink), GFP_ATOMIC); if (!unlink) { spin_unlock(&vdev->priv_lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC); return -ENOMEM; } @@ -703,7 +712,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) spin_unlock(&vdev->priv_lock); } - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usbip_dbg_vhci_hc("leave\n"); return 0; @@ -712,8 +721,9 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) static void vhci_device_unlink_cleanup(struct vhci_device *vdev) { struct vhci_unlink *unlink, *tmp; + unsigned long flags; - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); spin_lock(&vdev->priv_lock); list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { @@ -747,19 +757,19 @@ static void vhci_device_unlink_cleanup(struct vhci_device *vdev) list_del(&unlink->list); spin_unlock(&vdev->priv_lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); spin_lock(&vdev->priv_lock); kfree(unlink); } spin_unlock(&vdev->priv_lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); } /* @@ -826,8 +836,9 @@ static void vhci_shutdown_connection(struct usbip_device *ud) static void vhci_device_reset(struct usbip_device *ud) { struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); + unsigned long flags; - spin_lock(&ud->lock); + spin_lock_irqsave(&ud->lock, flags); vdev->speed = 0; vdev->devid = 0; @@ -841,14 +852,16 @@ static void vhci_device_reset(struct usbip_device *ud) } ud->status = VDEV_ST_NULL; - spin_unlock(&ud->lock); + spin_unlock_irqrestore(&ud->lock, flags); } static void vhci_device_unusable(struct usbip_device *ud) { - spin_lock(&ud->lock); + unsigned long flags; + + spin_lock_irqsave(&ud->lock, flags); ud->status = VDEV_ST_ERROR; - spin_unlock(&ud->lock); + spin_unlock_irqrestore(&ud->lock, flags); } static void vhci_device_init(struct vhci_device *vdev) @@ -938,12 +951,13 @@ static int vhci_get_frame_number(struct usb_hcd *hcd) static int vhci_bus_suspend(struct usb_hcd *hcd) { struct vhci_hcd *vhci = hcd_to_vhci(hcd); + unsigned long flags; dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__); - spin_lock(&vhci->lock); + spin_lock_irqsave(&vhci->lock, flags); hcd->state = HC_STATE_SUSPENDED; - spin_unlock(&vhci->lock); + spin_unlock_irqrestore(&vhci->lock, flags); return 0; } @@ -952,15 +966,16 @@ static int vhci_bus_resume(struct usb_hcd *hcd) { struct vhci_hcd *vhci = hcd_to_vhci(hcd); int rc = 0; + unsigned long flags; dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__); - spin_lock(&vhci->lock); + spin_lock_irqsave(&vhci->lock, flags); if (!HCD_HW_ACCESSIBLE(hcd)) rc = -ESHUTDOWN; else hcd->state = HC_STATE_RUNNING; - spin_unlock(&vhci->lock); + spin_unlock_irqrestore(&vhci->lock, flags); return rc; } @@ -1058,17 +1073,18 @@ static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state) int rhport = 0; int connected = 0; int ret = 0; + unsigned long flags; hcd = platform_get_drvdata(pdev); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); for (rhport = 0; rhport < VHCI_NPORTS; rhport++) if (the_controller->port_status[rhport] & USB_PORT_STAT_CONNECTION) connected += 1; - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); if (connected > 0) { dev_info(&pdev->dev, diff --git a/drivers/usb/usbip/vhci_rx.c b/drivers/usb/usbip/vhci_rx.c index 00e4a54308e4..d656e0edc3d5 100644 --- a/drivers/usb/usbip/vhci_rx.c +++ b/drivers/usb/usbip/vhci_rx.c @@ -72,10 +72,11 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, { struct usbip_device *ud = &vdev->ud; struct urb *urb; + unsigned long flags; - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); if (!urb) { pr_err("cannot find a urb of seqnum %u\n", pdu->base.seqnum); @@ -104,9 +105,9 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, usbip_dbg_vhci_rx("now giveback urb %p\n", urb); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); @@ -117,8 +118,9 @@ static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev, struct usbip_header *pdu) { struct vhci_unlink *unlink, *tmp; + unsigned long flags; - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { pr_info("unlink->seqnum %lu\n", unlink->seqnum); @@ -127,12 +129,12 @@ static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev, unlink->seqnum); list_del(&unlink->list); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return unlink; } } - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return NULL; } @@ -142,6 +144,7 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, { struct vhci_unlink *unlink; struct urb *urb; + unsigned long flags; usbip_dump_header(pdu); @@ -152,9 +155,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, return; } - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); if (!urb) { /* @@ -171,9 +174,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, urb->status = pdu->u.ret_unlink.status; pr_info("urb->status %d\n", urb->status); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); @@ -185,10 +188,11 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, static int vhci_priv_tx_empty(struct vhci_device *vdev) { int empty = 0; + unsigned long flags; - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); empty = list_empty(&vdev->priv_rx); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return empty; } diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c index 211f43f67ea2..5b5462eb1665 100644 --- a/drivers/usb/usbip/vhci_sysfs.c +++ b/drivers/usb/usbip/vhci_sysfs.c @@ -32,10 +32,11 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, { char *s = out; int i = 0; + unsigned long flags; BUG_ON(!the_controller || !out); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); /* * output example: @@ -70,7 +71,7 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, spin_unlock(&vdev->ud.lock); } - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return out - s; } @@ -80,11 +81,12 @@ static DEVICE_ATTR_RO(status); static int vhci_port_disconnect(__u32 rhport) { struct vhci_device *vdev; + unsigned long flags; usbip_dbg_vhci_sysfs("enter\n"); /* lock */ - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); vdev = port_to_vdev(rhport); @@ -94,14 +96,14 @@ static int vhci_port_disconnect(__u32 rhport) /* unlock */ spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return -EINVAL; } /* unlock */ spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN); @@ -177,6 +179,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, int sockfd = 0; __u32 rhport = 0, devid = 0, speed = 0; int err; + unsigned long flags; /* * @rhport: port number of vhci_hcd @@ -202,14 +205,14 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, /* now need lock until setting vdev status as used */ /* begin a lock */ - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); vdev = port_to_vdev(rhport); spin_lock(&vdev->ud.lock); if (vdev->ud.status != VDEV_ST_NULL) { /* end of the lock */ spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); sockfd_put(socket); @@ -227,7 +230,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, vdev->ud.status = VDEV_ST_NOTASSIGNED; spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); /* end the lock */ vdev->ud.tcp_rx = kthread_get_run(vhci_rx_loop, &vdev->ud, "vhci_rx"); diff --git a/drivers/usb/usbip/vhci_tx.c b/drivers/usb/usbip/vhci_tx.c index 409fd99f3257..3e7878fe2fd4 100644 --- a/drivers/usb/usbip/vhci_tx.c +++ b/drivers/usb/usbip/vhci_tx.c @@ -47,16 +47,17 @@ static void setup_cmd_submit_pdu(struct usbip_header *pdup, struct urb *urb) static struct vhci_priv *dequeue_from_priv_tx(struct vhci_device *vdev) { struct vhci_priv *priv, *tmp; + unsigned long flags; - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) { list_move_tail(&priv->list, &vdev->priv_rx); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return priv; } - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return NULL; } @@ -136,16 +137,17 @@ static int vhci_send_cmd_submit(struct vhci_device *vdev) static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev) { struct vhci_unlink *unlink, *tmp; + unsigned long flags; - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { list_move_tail(&unlink->list, &vdev->unlink_rx); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return unlink; } - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return NULL; } -- cgit v1.2.3 From dbf3e7f654c0f06a932b8fcafac78de9d0b81d68 Mon Sep 17 00:00:00 2001 From: Dave Penkler Date: Wed, 27 Jan 2016 19:09:24 +0100 Subject: Implement an ioctl to support the USMTMC-USB488 READ_STATUS_BYTE operation. Background: When performing a read on an instrument that is executing a function that runs longer than the USB timeout the instrument may hang and require a device reset to recover. The READ_STATUS_BYTE operation always returns even when the instrument is busy permitting to poll for the appropriate condition. This capability is referred to in instrument application notes on synchronizing acquisitions for other platforms. Signed-off-by: Dave Penkler Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 201 +++++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/usb/tmc.h | 2 + 2 files changed, 203 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 7a11a8263171..c2eb6fe9f4c8 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -87,6 +87,19 @@ struct usbtmc_device_data { u8 bTag_last_write; /* needed for abort */ u8 bTag_last_read; /* needed for abort */ + /* data for interrupt in endpoint handling */ + u8 bNotify1; + u8 bNotify2; + u16 ifnum; + u8 iin_bTag; + u8 *iin_buffer; + atomic_t iin_data_valid; + unsigned int iin_ep; + int iin_ep_present; + int iin_interval; + struct urb *iin_urb; + u16 iin_wMaxPacketSize; + u8 rigol_quirk; /* attributes from the USB TMC spec for this device */ @@ -99,6 +112,7 @@ struct usbtmc_device_data { struct usbtmc_dev_capabilities capabilities; struct kref kref; struct mutex io_mutex; /* only one i/o function running at a time */ + wait_queue_head_t waitq; }; #define to_usbtmc_data(d) container_of(d, struct usbtmc_device_data, kref) @@ -373,6 +387,84 @@ exit: return rv; } +static int usbtmc488_ioctl_read_stb(struct usbtmc_device_data *data, + void __user *arg) +{ + struct device *dev = &data->intf->dev; + u8 *buffer; + u8 tag; + __u8 stb; + int rv; + + dev_dbg(dev, "Enter ioctl_read_stb iin_ep_present: %d\n", + data->iin_ep_present); + + buffer = kmalloc(8, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + atomic_set(&data->iin_data_valid, 0); + + rv = usb_control_msg(data->usb_dev, + usb_rcvctrlpipe(data->usb_dev, 0), + USBTMC488_REQUEST_READ_STATUS_BYTE, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + data->iin_bTag, + data->ifnum, + buffer, 0x03, USBTMC_TIMEOUT); + if (rv < 0) { + dev_err(dev, "stb usb_control_msg returned %d\n", rv); + goto exit; + } + + if (buffer[0] != USBTMC_STATUS_SUCCESS) { + dev_err(dev, "control status returned %x\n", buffer[0]); + rv = -EIO; + goto exit; + } + + if (data->iin_ep_present) { + rv = wait_event_interruptible_timeout( + data->waitq, + atomic_read(&data->iin_data_valid) != 0, + USBTMC_TIMEOUT); + if (rv < 0) { + dev_dbg(dev, "wait interrupted %d\n", rv); + goto exit; + } + + if (rv == 0) { + dev_dbg(dev, "wait timed out\n"); + rv = -ETIME; + goto exit; + } + + tag = data->bNotify1 & 0x7f; + if (tag != data->iin_bTag) { + dev_err(dev, "expected bTag %x got %x\n", + data->iin_bTag, tag); + } + + stb = data->bNotify2; + } else { + stb = buffer[2]; + } + + rv = copy_to_user(arg, &stb, sizeof(stb)); + if (rv) + rv = -EFAULT; + + exit: + /* bump interrupt bTag */ + data->iin_bTag += 1; + if (data->iin_bTag > 127) + /* 1 is for SRQ see USBTMC-USB488 subclass spec section 4.3.1 */ + data->iin_bTag = 2; + + kfree(buffer); + return rv; +} + /* * Sends a REQUEST_DEV_DEP_MSG_IN message on the Bulk-IN endpoint. * @transfer_size: number of bytes to request from the device. @@ -1069,6 +1161,10 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case USBTMC_IOCTL_ABORT_BULK_IN: retval = usbtmc_ioctl_abort_bulk_in(data); break; + + case USBTMC488_IOCTL_READ_STB: + retval = usbtmc488_ioctl_read_stb(data, (void __user *)arg); + break; } skip_io_on_zombie: @@ -1092,6 +1188,57 @@ static struct usb_class_driver usbtmc_class = { .minor_base = USBTMC_MINOR_BASE, }; +static void usbtmc_interrupt(struct urb *urb) +{ + struct usbtmc_device_data *data = urb->context; + struct device *dev = &data->intf->dev; + int status = urb->status; + int rv; + + dev_dbg(&data->intf->dev, "int status: %d len %d\n", + status, urb->actual_length); + + switch (status) { + case 0: /* SUCCESS */ + /* check for valid STB notification */ + if (data->iin_buffer[0] > 0x81) { + data->bNotify1 = data->iin_buffer[0]; + data->bNotify2 = data->iin_buffer[1]; + atomic_set(&data->iin_data_valid, 1); + wake_up_interruptible(&data->waitq); + goto exit; + } + dev_warn(dev, "invalid notification: %x\n", data->iin_buffer[0]); + break; + case -EOVERFLOW: + dev_err(dev, "overflow with length %d, actual length is %d\n", + data->iin_wMaxPacketSize, urb->actual_length); + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + case -EILSEQ: + case -ETIME: + /* urb terminated, clean up */ + dev_dbg(dev, "urb terminated, status: %d\n", status); + return; + default: + dev_err(dev, "unknown status received: %d\n", status); + } +exit: + rv = usb_submit_urb(urb, GFP_ATOMIC); + if (rv) + dev_err(dev, "usb_submit_urb failed: %d\n", rv); +} + +static void usbtmc_free_int(struct usbtmc_device_data *data) +{ + if (!data->iin_ep_present || !data->iin_urb) + return; + usb_kill_urb(data->iin_urb); + kfree(data->iin_buffer); + usb_free_urb(data->iin_urb); + kref_put(&data->kref, usbtmc_delete); +} static int usbtmc_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -1114,6 +1261,8 @@ static int usbtmc_probe(struct usb_interface *intf, usb_set_intfdata(intf, data); kref_init(&data->kref); mutex_init(&data->io_mutex); + init_waitqueue_head(&data->waitq); + atomic_set(&data->iin_data_valid, 0); data->zombie = 0; /* Determine if it is a Rigol or not */ @@ -1134,9 +1283,12 @@ static int usbtmc_probe(struct usb_interface *intf, data->bTag = 1; data->TermCharEnabled = 0; data->TermChar = '\n'; + /* 2 <= bTag <= 127 USBTMC-USB488 subclass specification 4.3.1 */ + data->iin_bTag = 2; /* USBTMC devices have only one setting, so use that */ iface_desc = data->intf->cur_altsetting; + data->ifnum = iface_desc->desc.bInterfaceNumber; /* Find bulk in endpoint */ for (n = 0; n < iface_desc->desc.bNumEndpoints; n++) { @@ -1161,6 +1313,20 @@ static int usbtmc_probe(struct usb_interface *intf, break; } } + /* Find int endpoint */ + for (n = 0; n < iface_desc->desc.bNumEndpoints; n++) { + endpoint = &iface_desc->endpoint[n].desc; + + if (usb_endpoint_is_int_in(endpoint)) { + data->iin_ep_present = 1; + data->iin_ep = endpoint->bEndpointAddress; + data->iin_wMaxPacketSize = usb_endpoint_maxp(endpoint); + data->iin_interval = endpoint->bInterval; + dev_dbg(&intf->dev, "Found Int in endpoint at %u\n", + data->iin_ep); + break; + } + } retcode = get_capabilities(data); if (retcode) @@ -1169,6 +1335,39 @@ static int usbtmc_probe(struct usb_interface *intf, retcode = sysfs_create_group(&intf->dev.kobj, &capability_attr_grp); + if (data->iin_ep_present) { + /* allocate int urb */ + data->iin_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!data->iin_urb) { + dev_err(&intf->dev, "Failed to allocate int urb\n"); + goto error_register; + } + + /* will reference data in int urb */ + kref_get(&data->kref); + + /* allocate buffer for interrupt in */ + data->iin_buffer = kmalloc(data->iin_wMaxPacketSize, + GFP_KERNEL); + if (!data->iin_buffer) { + dev_err(&intf->dev, "Failed to allocate int buf\n"); + goto error_register; + } + + /* fill interrupt urb */ + usb_fill_int_urb(data->iin_urb, data->usb_dev, + usb_rcvintpipe(data->usb_dev, data->iin_ep), + data->iin_buffer, data->iin_wMaxPacketSize, + usbtmc_interrupt, + data, data->iin_interval); + + retcode = usb_submit_urb(data->iin_urb, GFP_KERNEL); + if (retcode) { + dev_err(&intf->dev, "Failed to submit iin_urb\n"); + goto error_register; + } + } + retcode = sysfs_create_group(&intf->dev.kobj, &data_attr_grp); retcode = usb_register_dev(intf, &usbtmc_class); @@ -1185,6 +1384,7 @@ static int usbtmc_probe(struct usb_interface *intf, error_register: sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); sysfs_remove_group(&intf->dev.kobj, &data_attr_grp); + usbtmc_free_int(data); kref_put(&data->kref, usbtmc_delete); return retcode; } @@ -1196,6 +1396,7 @@ static void usbtmc_disconnect(struct usb_interface *intf) dev_dbg(&intf->dev, "usbtmc_disconnect called\n"); data = usb_get_intfdata(intf); + usbtmc_free_int(data); usb_deregister_dev(intf, &usbtmc_class); sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); sysfs_remove_group(&intf->dev.kobj, &data_attr_grp); diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index c045ae12556c..7e5ced80548f 100644 --- a/include/uapi/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h @@ -30,6 +30,7 @@ #define USBTMC_REQUEST_CHECK_CLEAR_STATUS 6 #define USBTMC_REQUEST_GET_CAPABILITIES 7 #define USBTMC_REQUEST_INDICATOR_PULSE 64 +#define USBTMC488_REQUEST_READ_STATUS_BYTE 128 /* Request values for USBTMC driver's ioctl entry point */ #define USBTMC_IOC_NR 91 @@ -39,5 +40,6 @@ #define USBTMC_IOCTL_ABORT_BULK_IN _IO(USBTMC_IOC_NR, 4) #define USBTMC_IOCTL_CLEAR_OUT_HALT _IO(USBTMC_IOC_NR, 6) #define USBTMC_IOCTL_CLEAR_IN_HALT _IO(USBTMC_IOC_NR, 7) +#define USBTMC488_IOCTL_READ_STB _IOR(USBTMC_IOC_NR, 18, unsigned char) #endif -- cgit v1.2.3 From 82ed33811d7214198e071b785ee34dbe99f82140 Mon Sep 17 00:00:00 2001 From: Dave Penkler Date: Wed, 27 Jan 2016 19:15:15 +0100 Subject: Add support for USBTMC USB488 SRQ notification with fasync Background: By configuring an instrument's event status register various conditions can be reported via an SRQ notification. This complements the synchronous polling approach using the READ_STATUS_BYTE ioctl with an asynchronous notification. Signed-off-by: Dave Penkler Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index c2eb6fe9f4c8..d77da2fd7b70 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -99,6 +99,7 @@ struct usbtmc_device_data { int iin_interval; struct urb *iin_urb; u16 iin_wMaxPacketSize; + atomic_t srq_asserted; u8 rigol_quirk; @@ -113,6 +114,7 @@ struct usbtmc_device_data { struct kref kref; struct mutex io_mutex; /* only one i/o function running at a time */ wait_queue_head_t waitq; + struct fasync_struct *fasync; }; #define to_usbtmc_data(d) container_of(d, struct usbtmc_device_data, kref) @@ -405,6 +407,9 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_device_data *data, atomic_set(&data->iin_data_valid, 0); + /* must issue read_stb before using poll or select */ + atomic_set(&data->srq_asserted, 0); + rv = usb_control_msg(data->usb_dev, usb_rcvctrlpipe(data->usb_dev, 0), USBTMC488_REQUEST_READ_STATUS_BYTE, @@ -1172,6 +1177,13 @@ skip_io_on_zombie: return retval; } +static int usbtmc_fasync(int fd, struct file *file, int on) +{ + struct usbtmc_device_data *data = file->private_data; + + return fasync_helper(fd, file, on, &data->fasync); +} + static const struct file_operations fops = { .owner = THIS_MODULE, .read = usbtmc_read, @@ -1179,6 +1191,7 @@ static const struct file_operations fops = { .open = usbtmc_open, .release = usbtmc_release, .unlocked_ioctl = usbtmc_ioctl, + .fasync = usbtmc_fasync, .llseek = default_llseek, }; @@ -1208,6 +1221,16 @@ static void usbtmc_interrupt(struct urb *urb) wake_up_interruptible(&data->waitq); goto exit; } + /* check for SRQ notification */ + if (data->iin_buffer[0] == 0x81) { + if (data->fasync) + kill_fasync(&data->fasync, + SIGIO, POLL_IN); + + atomic_set(&data->srq_asserted, 1); + wake_up_interruptible(&data->waitq); + goto exit; + } dev_warn(dev, "invalid notification: %x\n", data->iin_buffer[0]); break; case -EOVERFLOW: @@ -1263,6 +1286,7 @@ static int usbtmc_probe(struct usb_interface *intf, mutex_init(&data->io_mutex); init_waitqueue_head(&data->waitq); atomic_set(&data->iin_data_valid, 0); + atomic_set(&data->srq_asserted, 0); data->zombie = 0; /* Determine if it is a Rigol or not */ -- cgit v1.2.3 From eb6b92ecc0f9412623ab1584ddd8389b371638d4 Mon Sep 17 00:00:00 2001 From: Dave Penkler Date: Wed, 27 Jan 2016 19:19:14 +0100 Subject: Add support for receiving USBTMC USB488 SRQ notifications via poll/select Background: In many situations operations on multiple instruments need to be synchronized. poll/select provide a convenient way of waiting on a number of different instruments and other peripherals simultaneously. Signed-off-by: Dave Penkler Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index d77da2fd7b70..867842951ea0 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1184,6 +1185,27 @@ static int usbtmc_fasync(int fd, struct file *file, int on) return fasync_helper(fd, file, on, &data->fasync); } +static unsigned int usbtmc_poll(struct file *file, poll_table *wait) +{ + struct usbtmc_device_data *data = file->private_data; + unsigned int mask; + + mutex_lock(&data->io_mutex); + + if (data->zombie) { + mask = POLLHUP | POLLERR; + goto no_poll; + } + + poll_wait(file, &data->waitq, wait); + + mask = (atomic_read(&data->srq_asserted)) ? POLLIN | POLLRDNORM : 0; + +no_poll: + mutex_unlock(&data->io_mutex); + return mask; +} + static const struct file_operations fops = { .owner = THIS_MODULE, .read = usbtmc_read, @@ -1192,6 +1214,7 @@ static const struct file_operations fops = { .release = usbtmc_release, .unlocked_ioctl = usbtmc_ioctl, .fasync = usbtmc_fasync, + .poll = usbtmc_poll, .llseek = default_llseek, }; -- cgit v1.2.3 From 29779d89fd049bfc6c07f19aaf9b8d19fe2ecc8c Mon Sep 17 00:00:00 2001 From: Dave Penkler Date: Wed, 27 Jan 2016 19:22:28 +0100 Subject: Add ioctl to retrieve USBTMC-USB488 capabilities This is a convenience function to obtain an instrument's capabilities from its file descriptor without having to access sysfs from the user program. Signed-off-by: Dave Penkler Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 12 ++++++++++++ include/uapi/linux/usb/tmc.h | 21 ++++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 867842951ea0..6edb21ca9989 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -102,6 +102,9 @@ struct usbtmc_device_data { u16 iin_wMaxPacketSize; atomic_t srq_asserted; + /* coalesced usb488_caps from usbtmc_dev_capabilities */ + __u8 usb488_caps; + u8 rigol_quirk; /* attributes from the USB TMC spec for this device */ @@ -993,6 +996,7 @@ static int get_capabilities(struct usbtmc_device_data *data) data->capabilities.device_capabilities = buffer[5]; data->capabilities.usb488_interface_capabilities = buffer[14]; data->capabilities.usb488_device_capabilities = buffer[15]; + data->usb488_caps = (buffer[14] & 0x07) | ((buffer[15] & 0x0f) << 4); rv = 0; err_out: @@ -1168,6 +1172,14 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) retval = usbtmc_ioctl_abort_bulk_in(data); break; + case USBTMC488_IOCTL_GET_CAPS: + retval = copy_to_user((void __user *)arg, + &data->usb488_caps, + sizeof(data->usb488_caps)); + if (retval) + retval = -EFAULT; + break; + case USBTMC488_IOCTL_READ_STB: retval = usbtmc488_ioctl_read_stb(data, (void __user *)arg); break; diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index 7e5ced80548f..b512fb2d403e 100644 --- a/include/uapi/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h @@ -2,12 +2,14 @@ * Copyright (C) 2007 Stefan Kopp, Gechingen, Germany * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 Greg Kroah-Hartman + * Copyright (C) 2015 Dave Penkler * * This file holds USB constants defined by the USB Device Class - * Definition for Test and Measurement devices published by the USB-IF. + * and USB488 Subclass Definitions for Test and Measurement devices + * published by the USB-IF. * - * It also has the ioctl definitions for the usbtmc kernel driver that - * userspace needs to know about. + * It also has the ioctl and capability definitions for the + * usbtmc kernel driver that userspace needs to know about. */ #ifndef __LINUX_USB_TMC_H @@ -40,6 +42,19 @@ #define USBTMC_IOCTL_ABORT_BULK_IN _IO(USBTMC_IOC_NR, 4) #define USBTMC_IOCTL_CLEAR_OUT_HALT _IO(USBTMC_IOC_NR, 6) #define USBTMC_IOCTL_CLEAR_IN_HALT _IO(USBTMC_IOC_NR, 7) +#define USBTMC488_IOCTL_GET_CAPS _IOR(USBTMC_IOC_NR, 17, unsigned char) #define USBTMC488_IOCTL_READ_STB _IOR(USBTMC_IOC_NR, 18, unsigned char) +/* Driver encoded usb488 capabilities */ +#define USBTMC488_CAPABILITY_TRIGGER 1 +#define USBTMC488_CAPABILITY_SIMPLE 2 +#define USBTMC488_CAPABILITY_REN_CONTROL 2 +#define USBTMC488_CAPABILITY_GOTO_LOCAL 2 +#define USBTMC488_CAPABILITY_LOCAL_LOCKOUT 2 +#define USBTMC488_CAPABILITY_488_DOT_2 4 +#define USBTMC488_CAPABILITY_DT1 16 +#define USBTMC488_CAPABILITY_RL1 32 +#define USBTMC488_CAPABILITY_SR1 64 +#define USBTMC488_CAPABILITY_FULL_SCPI 128 + #endif -- cgit v1.2.3 From 379d3d33c83b667b0edad0110693567306463882 Mon Sep 17 00:00:00 2001 From: Dave Penkler Date: Wed, 27 Jan 2016 19:25:24 +0100 Subject: Add ioctls to enable and disable local controls on an instrument These ioctls provide support for the USBTMC-USB488 control requests for REN_CONTROL, GO_TO_LOCAL and LOCAL_LOCKOUT Signed-off-by: Dave Penkler Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 70 ++++++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/usb/tmc.h | 6 ++++ 2 files changed, 76 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 6edb21ca9989..419c72e10464 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -474,6 +474,61 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_device_data *data, return rv; } +static int usbtmc488_ioctl_simple(struct usbtmc_device_data *data, + void __user *arg, unsigned int cmd) +{ + struct device *dev = &data->intf->dev; + __u8 val; + u8 *buffer; + u16 wValue; + int rv; + + if (!(data->usb488_caps & USBTMC488_CAPABILITY_SIMPLE)) + return -EINVAL; + + buffer = kmalloc(8, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + if (cmd == USBTMC488_REQUEST_REN_CONTROL) { + rv = copy_from_user(&val, arg, sizeof(val)); + if (rv) { + rv = -EFAULT; + goto exit; + } + wValue = val ? 1 : 0; + } else { + wValue = 0; + } + + rv = usb_control_msg(data->usb_dev, + usb_rcvctrlpipe(data->usb_dev, 0), + cmd, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + wValue, + data->ifnum, + buffer, 0x01, USBTMC_TIMEOUT); + if (rv < 0) { + dev_err(dev, "simple usb_control_msg failed %d\n", rv); + goto exit; + } else if (rv != 1) { + dev_warn(dev, "simple usb_control_msg returned %d\n", rv); + rv = -EIO; + goto exit; + } + + if (buffer[0] != USBTMC_STATUS_SUCCESS) { + dev_err(dev, "simple control status returned %x\n", buffer[0]); + rv = -EIO; + goto exit; + } + rv = 0; + + exit: + kfree(buffer); + return rv; +} + /* * Sends a REQUEST_DEV_DEP_MSG_IN message on the Bulk-IN endpoint. * @transfer_size: number of bytes to request from the device. @@ -1183,6 +1238,21 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case USBTMC488_IOCTL_READ_STB: retval = usbtmc488_ioctl_read_stb(data, (void __user *)arg); break; + + case USBTMC488_IOCTL_REN_CONTROL: + retval = usbtmc488_ioctl_simple(data, (void __user *)arg, + USBTMC488_REQUEST_REN_CONTROL); + break; + + case USBTMC488_IOCTL_GOTO_LOCAL: + retval = usbtmc488_ioctl_simple(data, (void __user *)arg, + USBTMC488_REQUEST_GOTO_LOCAL); + break; + + case USBTMC488_IOCTL_LOCAL_LOCKOUT: + retval = usbtmc488_ioctl_simple(data, (void __user *)arg, + USBTMC488_REQUEST_LOCAL_LOCKOUT); + break; } skip_io_on_zombie: diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index b512fb2d403e..2e59d9c50b8d 100644 --- a/include/uapi/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h @@ -33,6 +33,9 @@ #define USBTMC_REQUEST_GET_CAPABILITIES 7 #define USBTMC_REQUEST_INDICATOR_PULSE 64 #define USBTMC488_REQUEST_READ_STATUS_BYTE 128 +#define USBTMC488_REQUEST_REN_CONTROL 160 +#define USBTMC488_REQUEST_GOTO_LOCAL 161 +#define USBTMC488_REQUEST_LOCAL_LOCKOUT 162 /* Request values for USBTMC driver's ioctl entry point */ #define USBTMC_IOC_NR 91 @@ -44,6 +47,9 @@ #define USBTMC_IOCTL_CLEAR_IN_HALT _IO(USBTMC_IOC_NR, 7) #define USBTMC488_IOCTL_GET_CAPS _IOR(USBTMC_IOC_NR, 17, unsigned char) #define USBTMC488_IOCTL_READ_STB _IOR(USBTMC_IOC_NR, 18, unsigned char) +#define USBTMC488_IOCTL_REN_CONTROL _IOW(USBTMC_IOC_NR, 19, unsigned char) +#define USBTMC488_IOCTL_GOTO_LOCAL _IO(USBTMC_IOC_NR, 20) +#define USBTMC488_IOCTL_LOCAL_LOCKOUT _IO(USBTMC_IOC_NR, 21) /* Driver encoded usb488 capabilities */ #define USBTMC488_CAPABILITY_TRIGGER 1 -- cgit v1.2.3 From a6835090716a85f2297668ba593bd00e1051e662 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Tue, 26 Jan 2016 17:50:04 +0200 Subject: Revert "xhci: don't finish a TD if we get a short-transfer event mid TD" This reverts commit e210c422b6fd ("xhci: don't finish a TD if we get a short transfer event mid TD") Turns out that most host controllers do not follow the xHCI specs and never send the second event for the last TRB in the TD if there was a short event mid-TD. Returning the URB directly after the first short-transfer event is far better than never returning the URB. (class drivers usually timeout after 30sec). For the hosts that do send the second event we will go back to treating it as misplaced event and print an error message for it. The origial patch was sent to stable kernels and needs to be reverted from there as well Cc: stable@vger.kernel.org Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index f1c21c40b4a6..3915657e6078 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2193,10 +2193,6 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, } /* Fast path - was this the last TRB in the TD for this URB? */ } else if (event_trb == td->last_trb) { - if (td->urb_length_set && trb_comp_code == COMP_SHORT_TX) - return finish_td(xhci, td, event_trb, event, ep, - status, false); - if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { td->urb->actual_length = td->urb->transfer_buffer_length - @@ -2248,12 +2244,6 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, td->urb->actual_length += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); - - if (trb_comp_code == COMP_SHORT_TX) { - xhci_dbg(xhci, "mid bulk/intr SP, wait for last TRB event\n"); - td->urb_length_set = true; - return 0; - } } return finish_td(xhci, td, event_trb, event, ep, status, false); -- cgit v1.2.3 From 6a4290cc28be12d72d50644bd4bda1aede37cd41 Mon Sep 17 00:00:00 2001 From: Jianqiang Tang Date: Wed, 20 Jan 2016 14:09:39 +0800 Subject: usb: dwc3: gadget: set the OTG flag in dwc3 gadget driver. This patch is needed in order to pass one test case defined in the OTG Automated Compliance Test specification. Specification location: http://www.usb.org/developers/onthego/otgeh_compliance_plan_1_2.pdf This test case uses PET Tool, and PET Tool is one USB hardware equipment provided by MQP Electronics. Test case id is 6.8.3 B-UUT Bypass Capacitance. We must set this otg flag in order to be able to return OTG descriptor during enumeration, otherwise this test case with failed with below error: "Get OTG descriptor request stalled". Signed-off-by: Jianqiang Tang Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index af023a81a0b0..7d1dd82a95ac 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2789,6 +2789,7 @@ int dwc3_gadget_init(struct dwc3 *dwc) dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->gadget.sg_supported = true; dwc->gadget.name = "dwc3-gadget"; + dwc->gadget.is_otg = dwc->dr_mode == USB_DR_MODE_OTG; /* * FIXME We might be setting max_speed to Date: Tue, 26 Jan 2016 17:50:05 +0200 Subject: usb: xhci: handle both SSIC ports in PME stuck quirk Commit abce329c27b3 ("xhci: Workaround to get D3 working in Intel xHCI") adds a workaround for a limitation of PME storm caused by SSIC port in some Intel SoCs. This commit only handled one SSIC port, while there are actually two SSIC ports in the chips. This patch handles both SSIC ports. Without this fix, users still see PME storm. Cc: stable@vger.kernel.org # v4.2+ Signed-off-by: Zhuang Jin Can Signed-off-by: Lu Baolu Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 48 +++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 58c43ed7ff3b..67471fb28de5 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -28,7 +28,9 @@ #include "xhci.h" #include "xhci-trace.h" -#define PORT2_SSIC_CONFIG_REG2 0x883c +#define SSIC_PORT_NUM 2 +#define SSIC_PORT_CFG2 0x880c +#define SSIC_PORT_CFG2_OFFSET 0x30 #define PROG_DONE (1 << 30) #define SSIC_PORT_UNUSED (1 << 31) @@ -321,28 +323,36 @@ static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend) struct pci_dev *pdev = to_pci_dev(hcd->self.controller); u32 val; void __iomem *reg; + int i; if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) { - reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2; - - /* Notify SSIC that SSIC profile programming is not done */ - val = readl(reg) & ~PROG_DONE; - writel(val, reg); - - /* Mark SSIC port as unused(suspend) or used(resume) */ - val = readl(reg); - if (suspend) - val |= SSIC_PORT_UNUSED; - else - val &= ~SSIC_PORT_UNUSED; - writel(val, reg); - - /* Notify SSIC that SSIC profile programming is done */ - val = readl(reg) | PROG_DONE; - writel(val, reg); - readl(reg); + for (i = 0; i < SSIC_PORT_NUM; i++) { + reg = (void __iomem *) xhci->cap_regs + + SSIC_PORT_CFG2 + + i * SSIC_PORT_CFG2_OFFSET; + + /* + * Notify SSIC that SSIC profile programming + * is not done. + */ + val = readl(reg) & ~PROG_DONE; + writel(val, reg); + + /* Mark SSIC port as unused(suspend) or used(resume) */ + val = readl(reg); + if (suspend) + val |= SSIC_PORT_UNUSED; + else + val &= ~SSIC_PORT_UNUSED; + writel(val, reg); + + /* Notify SSIC that SSIC profile programming is done */ + val = readl(reg) | PROG_DONE; + writel(val, reg); + readl(reg); + } } reg = (void __iomem *) xhci->cap_regs + 0x80a4; -- cgit v1.2.3 From 7e70cbffe236721051bbaff965e477df06dcb190 Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Tue, 26 Jan 2016 17:50:06 +0200 Subject: usb: xhci: add a quirk bit for ssic port unused Two workarounds introduced by commit b8cb91e058cd ("xhci: Workaround for PME stuck issues in Intel xhci") and commit abce329c27b3 ("xhci: Workaround to get D3 working in Intel xHCI") share a single quirk bit XHCI_PME_STUCK_QUIRK. These two workarounds actually are different and might happen on different hardwares. Need to separate them by adding a quirk bit for the later. Cc: stable@vger.kernel.org Signed-off-by: Lu Baolu Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 79 ++++++++++++++++++++++++++------------------- drivers/usb/host/xhci.h | 1 + 2 files changed, 46 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 67471fb28de5..86377a0955e6 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -156,6 +156,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)) { xhci->quirks |= XHCI_PME_STUCK_QUIRK; } + if (pdev->vendor == PCI_VENDOR_ID_INTEL && + pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) { + xhci->quirks |= XHCI_SSIC_PORT_UNUSED; + } if (pdev->vendor == PCI_VENDOR_ID_ETRON && pdev->device == PCI_DEVICE_ID_EJ168) { xhci->quirks |= XHCI_RESET_ON_RESUME; @@ -314,46 +318,47 @@ static void xhci_pci_remove(struct pci_dev *dev) * SSIC PORT need to be marked as "unused" before putting xHCI * into D3. After D3 exit, the SSIC port need to be marked as "used". * Without this change, xHCI might not enter D3 state. - * Make sure PME works on some Intel xHCI controllers by writing 1 to clear - * the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4 */ -static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend) +static void xhci_ssic_port_unused_quirk(struct usb_hcd *hcd, bool suspend) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); u32 val; void __iomem *reg; int i; - if (pdev->vendor == PCI_VENDOR_ID_INTEL && - pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) { - - for (i = 0; i < SSIC_PORT_NUM; i++) { - reg = (void __iomem *) xhci->cap_regs + - SSIC_PORT_CFG2 + - i * SSIC_PORT_CFG2_OFFSET; - - /* - * Notify SSIC that SSIC profile programming - * is not done. - */ - val = readl(reg) & ~PROG_DONE; - writel(val, reg); - - /* Mark SSIC port as unused(suspend) or used(resume) */ - val = readl(reg); - if (suspend) - val |= SSIC_PORT_UNUSED; - else - val &= ~SSIC_PORT_UNUSED; - writel(val, reg); - - /* Notify SSIC that SSIC profile programming is done */ - val = readl(reg) | PROG_DONE; - writel(val, reg); - readl(reg); - } + for (i = 0; i < SSIC_PORT_NUM; i++) { + reg = (void __iomem *) xhci->cap_regs + + SSIC_PORT_CFG2 + + i * SSIC_PORT_CFG2_OFFSET; + + /* Notify SSIC that SSIC profile programming is not done. */ + val = readl(reg) & ~PROG_DONE; + writel(val, reg); + + /* Mark SSIC port as unused(suspend) or used(resume) */ + val = readl(reg); + if (suspend) + val |= SSIC_PORT_UNUSED; + else + val &= ~SSIC_PORT_UNUSED; + writel(val, reg); + + /* Notify SSIC that SSIC profile programming is done */ + val = readl(reg) | PROG_DONE; + writel(val, reg); + readl(reg); } +} + +/* + * Make sure PME works on some Intel xHCI controllers by writing 1 to clear + * the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4 + */ +static void xhci_pme_quirk(struct usb_hcd *hcd) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + void __iomem *reg; + u32 val; reg = (void __iomem *) xhci->cap_regs + 0x80a4; val = readl(reg); @@ -374,7 +379,10 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) pdev->no_d3cold = true; if (xhci->quirks & XHCI_PME_STUCK_QUIRK) - xhci_pme_quirk(hcd, true); + xhci_pme_quirk(hcd); + + if (xhci->quirks & XHCI_SSIC_PORT_UNUSED) + xhci_ssic_port_unused_quirk(hcd, true); return xhci_suspend(xhci, do_wakeup); } @@ -406,8 +414,11 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) if (pdev->vendor == PCI_VENDOR_ID_INTEL) usb_enable_intel_xhci_ports(pdev); + if (xhci->quirks & XHCI_SSIC_PORT_UNUSED) + xhci_ssic_port_unused_quirk(hcd, false); + if (xhci->quirks & XHCI_PME_STUCK_QUIRK) - xhci_pme_quirk(hcd, false); + xhci_pme_quirk(hcd); retval = xhci_resume(xhci, hibernated); return retval; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 9be7348872ba..cc651383ce5a 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1631,6 +1631,7 @@ struct xhci_hcd { #define XHCI_BROKEN_STREAMS (1 << 19) #define XHCI_PME_STUCK_QUIRK (1 << 20) #define XHCI_MTK_HOST (1 << 21) +#define XHCI_SSIC_PORT_UNUSED (1 << 22) unsigned int num_active_eps; unsigned int limit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ -- cgit v1.2.3 From 92149c930cce1865d0d4aca2ab07c2b4b197b418 Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Tue, 26 Jan 2016 17:50:07 +0200 Subject: usb: xhci: set SSIC port unused only if xhci_suspend succeeds XHCI_SSIC_PORT_UNUSED quirk was applied to the xHCI host controllers in some Intel SoC chips. With this quirk applied, SSIC port is set to "unused" prior to xhci_suspend(). This may cause problem if host fails to suspend. In this case, the port is set to unused without host further entering D3, and the port will not be usable anymore. Cc: stable@vger.kernel.org Signed-off-by: Zhuang Jin Can Signed-off-by: Lu Baolu Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 86377a0955e6..7ee1d0f6891c 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -370,6 +370,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + int ret; /* * Systems with the TI redriver that loses port status change events @@ -384,7 +385,11 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) if (xhci->quirks & XHCI_SSIC_PORT_UNUSED) xhci_ssic_port_unused_quirk(hcd, true); - return xhci_suspend(xhci, do_wakeup); + ret = xhci_suspend(xhci, do_wakeup); + if (ret && (xhci->quirks & XHCI_SSIC_PORT_UNUSED)) + xhci_ssic_port_unused_quirk(hcd, false); + + return ret; } static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) -- cgit v1.2.3 From ccc04afb72cddbdf7c0e1c17e92886405a71b754 Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Tue, 26 Jan 2016 17:50:08 +0200 Subject: usb: xhci: apply XHCI_PME_STUCK_QUIRK to Intel Broxton-M platforms Intel Broxton M was verifed to require XHCI_PME_STUCK_QUIRK quirk as well. Cc: stable@vger.kernel.org Signed-off-by: Lu Baolu Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 7ee1d0f6891c..f0640b7a1c42 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -47,6 +47,7 @@ #define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI 0x22b5 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI 0xa12f #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI 0x9d2f +#define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI 0x0aa8 static const char hcd_name[] = "xhci_hcd"; @@ -153,7 +154,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) if (pdev->vendor == PCI_VENDOR_ID_INTEL && (pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)) { + pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI)) { xhci->quirks |= XHCI_PME_STUCK_QUIRK; } if (pdev->vendor == PCI_VENDOR_ID_INTEL && -- cgit v1.2.3 From b765a16a11fad6b9c94fea7718c22692581e8d18 Mon Sep 17 00:00:00 2001 From: Chunfeng Yun Date: Tue, 26 Jan 2016 17:50:09 +0200 Subject: usb: xhci-mtk: fix bpkts value of LS/HS periodic eps not behind TT when a LS or FS device doesn't connect though a HS hub, the @bPkts field of its periodic endpoint context should be set to 1. Signed-off-by: Chunfeng Yun Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mtk-sch.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c index c30de7c39f44..73f763c4f5f5 100644 --- a/drivers/usb/host/xhci-mtk-sch.c +++ b/drivers/usb/host/xhci-mtk-sch.c @@ -275,8 +275,9 @@ static bool need_bw_sch(struct usb_host_endpoint *ep, return false; /* - * for LS & FS periodic endpoints which its device don't attach - * to TT are also ignored, root-hub will schedule them directly + * for LS & FS periodic endpoints which its device is not behind + * a TT are also ignored, root-hub will schedule them directly, + * but need set @bpkts field of endpoint context to 1. */ if (is_fs_or_ls(speed) && !has_tt) return false; @@ -339,8 +340,17 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev, GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)), usb_endpoint_dir_in(&ep->desc), ep); - if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT)) + if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT)) { + /* + * set @bpkts to 1 if it is LS or FS periodic endpoint, and its + * device does not connected through an external HS hub + */ + if (usb_endpoint_xfer_int(&ep->desc) + || usb_endpoint_xfer_isoc(&ep->desc)) + ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(1)); + return 0; + } bw_index = get_bw_index(xhci, udev, ep); sch_bw = &sch_array[bw_index]; -- cgit v1.2.3 From 882fa27f488ed3c4b67699d99e8c5ff64c7a9cd1 Mon Sep 17 00:00:00 2001 From: Chunfeng Yun Date: Tue, 26 Jan 2016 17:50:10 +0200 Subject: usb: xhci-mtk: fix AHB bus hang up caused by roothubs polling when ip fails to enter sleep mode, register access protection will be disabled, at the same time if all clocks are disabled, access register will hang up AHB bus. the common case causes ip sleep failure is that after all ports enter U3 but before ip enters sleep mode, a port receives a resume signal('K'). this will happens when such as clicks mouse to try to do remote-wakeup to stop system enter suspend. so stop polling root hubs to avoid access xHCI register on bus suspend, and restart it when bus resumes. Signed-off-by: Chunfeng Yun Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mtk.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index c9ab6a44c34a..9532f5aef71b 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -696,9 +696,24 @@ static int xhci_mtk_remove(struct platform_device *dev) } #ifdef CONFIG_PM_SLEEP +/* + * if ip sleep fails, and all clocks are disabled, access register will hang + * AHB bus, so stop polling roothubs to avoid regs access on bus suspend. + * and no need to check whether ip sleep failed or not; this will cause SPM + * to wake up system immediately after system suspend complete if ip sleep + * fails, it is what we wanted. + */ static int xhci_mtk_suspend(struct device *dev) { struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev); + struct usb_hcd *hcd = mtk->hcd; + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + xhci_dbg(xhci, "%s: stop port polling\n", __func__); + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + del_timer_sync(&hcd->rh_timer); + clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); + del_timer_sync(&xhci->shared_hcd->rh_timer); xhci_mtk_host_disable(mtk); xhci_mtk_phy_power_off(mtk); @@ -710,11 +725,19 @@ static int xhci_mtk_suspend(struct device *dev) static int xhci_mtk_resume(struct device *dev) { struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev); + struct usb_hcd *hcd = mtk->hcd; + struct xhci_hcd *xhci = hcd_to_xhci(hcd); usb_wakeup_disable(mtk); xhci_mtk_clks_enable(mtk); xhci_mtk_phy_power_on(mtk); xhci_mtk_host_enable(mtk); + + xhci_dbg(xhci, "%s: restart port polling\n", __func__); + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); + usb_hcd_poll_rh_status(hcd); + set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); + usb_hcd_poll_rh_status(xhci->shared_hcd); return 0; } -- cgit v1.2.3 From 2ad294d5f9d13d108c1e2f1a4be8542859ead134 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Tue, 26 Jan 2016 17:50:11 +0200 Subject: usb: host: xhci-plat: fix NULL pointer in probe for device tree case During probe, in the device tree case, the data pointer associated to a compatible is dereferenced. However, not all the compatibles are associated to a private data pointer. The generic-xhci and the xhci-platform don't need them, this patch adds a test on the data pointer before accessing it, avoiding a kernel crash. Fixes: 4efb2f694114 ("usb: host: xhci-plat: add struct xhci_plat_priv") Cc: stable@vger.kernel.org Signed-off-by: Gregory CLEMENT Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-plat.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 770b6b088797..d39d6bf1d090 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -184,7 +184,8 @@ static int xhci_plat_probe(struct platform_device *pdev) struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); /* Just copy data for now */ - *priv = *priv_match; + if (priv_match) + *priv = *priv_match; } if (xhci_plat_type_is(hcd, XHCI_PLAT_TYPE_MARVELL_ARMADA)) { -- cgit v1.2.3 From 5c82171167adb8e4ac77b91a42cd49fb211a81a0 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Tue, 26 Jan 2016 17:50:12 +0200 Subject: xhci: Fix list corruption in urb dequeue at host removal xhci driver frees data for all devices, both usb2 and and usb3 the first time usb_remove_hcd() is called, including td_list and and xhci_ring structures. When usb_remove_hcd() is called a second time for the second xhci bus it will try to dequeue all pending urbs, and touches td_list which is already freed for that endpoint. Cc: Reported-by: Joe Lawrence Tested-by: Joe Lawrence Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 26a44c0e969e..0c8087d3c313 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1554,7 +1554,9 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, "HW died, freeing TD."); urb_priv = urb->hcpriv; - for (i = urb_priv->td_cnt; i < urb_priv->length; i++) { + for (i = urb_priv->td_cnt; + i < urb_priv->length && xhci->devs[urb->dev->slot_id]; + i++) { td = urb_priv->td[i]; if (!list_empty(&td->td_list)) list_del_init(&td->td_list); -- cgit v1.2.3 From febe562c20dfa8f33bee7d419c6b517986a5aa33 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 11 Jan 2016 21:31:09 -0800 Subject: target: Fix LUN_RESET active I/O handling for ACK_KREF This patch fixes a NULL pointer se_cmd->cmd_kref < 0 refcount bug during TMR LUN_RESET with active se_cmd I/O, that can be triggered during se_cmd descriptor shutdown + release via core_tmr_drain_state_list() code. To address this bug, add common __target_check_io_state() helper for ABORT_TASK + LUN_RESET w/ CMD_T_COMPLETE checking, and set CMD_T_ABORTED + obtain ->cmd_kref for both cases ahead of last target_put_sess_cmd() after TFO->aborted_task() -> transport_cmd_finish_abort() callback has completed. It also introduces SCF_ACK_KREF to determine when transport_cmd_finish_abort() needs to drop the second extra reference, ahead of calling target_put_sess_cmd() for the final kref_put(&se_cmd->cmd_kref). It also updates transport_cmd_check_stop() to avoid holding se_cmd->t_state_lock while dropping se_cmd device state via target_remove_from_state_list(), now that core_tmr_drain_state_list() is holding the se_device lock while checking se_cmd state from within TMR logic. Finally, move transport_put_cmd() release of SGL + TMR + extended CDB memory into target_free_cmd_mem() in order to avoid potential resource leaks in TMR ABORT_TASK + LUN_RESET code-paths. Also update target_release_cmd_kref() accordingly. Reviewed-by: Quinn Tran Cc: Himanshu Madhani Cc: Sagi Grimberg Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Andy Grover Cc: Mike Christie Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_tmr.c | 69 ++++++++++++++++++++++------------ drivers/target/target_core_transport.c | 67 ++++++++++++++------------------- include/target/target_core_base.h | 1 + 3 files changed, 76 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index fcdcb117c60d..fb3decc28589 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -107,6 +107,34 @@ static int target_check_cdb_and_preempt(struct list_head *list, return 1; } +static bool __target_check_io_state(struct se_cmd *se_cmd) +{ + struct se_session *sess = se_cmd->se_sess; + + assert_spin_locked(&sess->sess_cmd_lock); + WARN_ON_ONCE(!irqs_disabled()); + /* + * If command already reached CMD_T_COMPLETE state within + * target_complete_cmd(), this se_cmd has been passed to + * fabric driver and will not be aborted. + * + * Otherwise, obtain a local se_cmd->cmd_kref now for TMR + * ABORT_TASK + LUN_RESET for CMD_T_ABORTED processing as + * long as se_cmd->cmd_kref is still active unless zero. + */ + spin_lock(&se_cmd->t_state_lock); + if (se_cmd->transport_state & CMD_T_COMPLETE) { + pr_debug("Attempted to abort io tag: %llu already complete," + " skipping\n", se_cmd->tag); + spin_unlock(&se_cmd->t_state_lock); + return false; + } + se_cmd->transport_state |= CMD_T_ABORTED; + spin_unlock(&se_cmd->t_state_lock); + + return kref_get_unless_zero(&se_cmd->cmd_kref); +} + void core_tmr_abort_task( struct se_device *dev, struct se_tmr_req *tmr, @@ -130,34 +158,22 @@ void core_tmr_abort_task( if (tmr->ref_task_tag != ref_tag) continue; - if (!kref_get_unless_zero(&se_cmd->cmd_kref)) - continue; - printk("ABORT_TASK: Found referenced %s task_tag: %llu\n", se_cmd->se_tfo->get_fabric_name(), ref_tag); - spin_lock(&se_cmd->t_state_lock); - if (se_cmd->transport_state & CMD_T_COMPLETE) { - printk("ABORT_TASK: ref_tag: %llu already complete," - " skipping\n", ref_tag); - spin_unlock(&se_cmd->t_state_lock); + if (!__target_check_io_state(se_cmd)) { spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); - target_put_sess_cmd(se_cmd); - goto out; } - se_cmd->transport_state |= CMD_T_ABORTED; - spin_unlock(&se_cmd->t_state_lock); - list_del_init(&se_cmd->se_cmd_list); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); cancel_work_sync(&se_cmd->work); transport_wait_for_tasks(se_cmd); - target_put_sess_cmd(se_cmd); transport_cmd_finish_abort(se_cmd, true); + target_put_sess_cmd(se_cmd); printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for" " ref_tag: %llu\n", ref_tag); @@ -242,8 +258,10 @@ static void core_tmr_drain_state_list( struct list_head *preempt_and_abort_list) { LIST_HEAD(drain_task_list); + struct se_session *sess; struct se_cmd *cmd, *next; unsigned long flags; + int rc; /* * Complete outstanding commands with TASK_ABORTED SAM status. @@ -282,6 +300,16 @@ static void core_tmr_drain_state_list( if (prout_cmd == cmd) continue; + sess = cmd->se_sess; + if (WARN_ON_ONCE(!sess)) + continue; + + spin_lock(&sess->sess_cmd_lock); + rc = __target_check_io_state(cmd); + spin_unlock(&sess->sess_cmd_lock); + if (!rc) + continue; + list_move_tail(&cmd->state_list, &drain_task_list); cmd->state_active = false; } @@ -289,7 +317,7 @@ static void core_tmr_drain_state_list( while (!list_empty(&drain_task_list)) { cmd = list_entry(drain_task_list.next, struct se_cmd, state_list); - list_del(&cmd->state_list); + list_del_init(&cmd->state_list); pr_debug("LUN_RESET: %s cmd: %p" " ITT/CmdSN: 0x%08llx/0x%08x, i_state: %d, t_state: %d" @@ -313,16 +341,11 @@ static void core_tmr_drain_state_list( * loop above, but we do it down here given that * cancel_work_sync may block. */ - if (cmd->t_state == TRANSPORT_COMPLETE) - cancel_work_sync(&cmd->work); - - spin_lock_irqsave(&cmd->t_state_lock, flags); - target_stop_cmd(cmd, &flags); - - cmd->transport_state |= CMD_T_ABORTED; - spin_unlock_irqrestore(&cmd->t_state_lock, flags); + cancel_work_sync(&cmd->work); + transport_wait_for_tasks(cmd); core_tmr_handle_tas_abort(tmr_nacl, cmd, tas); + target_put_sess_cmd(cmd); } } diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 9f3608e10f25..af52f8bd8954 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -534,9 +534,6 @@ void transport_deregister_session(struct se_session *se_sess) } EXPORT_SYMBOL(transport_deregister_session); -/* - * Called with cmd->t_state_lock held. - */ static void target_remove_from_state_list(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -561,10 +558,6 @@ static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists, { unsigned long flags; - spin_lock_irqsave(&cmd->t_state_lock, flags); - if (write_pending) - cmd->t_state = TRANSPORT_WRITE_PENDING; - if (remove_from_lists) { target_remove_from_state_list(cmd); @@ -574,6 +567,10 @@ static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists, cmd->se_lun = NULL; } + spin_lock_irqsave(&cmd->t_state_lock, flags); + if (write_pending) + cmd->t_state = TRANSPORT_WRITE_PENDING; + /* * Determine if frontend context caller is requesting the stopping of * this command for frontend exceptions. @@ -627,6 +624,8 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd) void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) { + bool ack_kref = (cmd->se_cmd_flags & SCF_ACK_KREF); + if (cmd->se_cmd_flags & SCF_SE_LUN_CMD) transport_lun_remove_cmd(cmd); /* @@ -638,7 +637,7 @@ void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) if (transport_cmd_check_stop_to_fabric(cmd)) return; - if (remove) + if (remove && ack_kref) transport_put_cmd(cmd); } @@ -706,7 +705,7 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) * Check for case where an explicit ABORT_TASK has been received * and transport_wait_for_tasks() will be waiting for completion.. */ - if (cmd->transport_state & CMD_T_ABORTED && + if (cmd->transport_state & CMD_T_ABORTED || cmd->transport_state & CMD_T_STOP) { spin_unlock_irqrestore(&cmd->t_state_lock, flags); complete_all(&cmd->t_transport_stop_comp); @@ -2222,20 +2221,14 @@ static inline void transport_free_pages(struct se_cmd *cmd) } /** - * transport_release_cmd - free a command - * @cmd: command to free + * transport_put_cmd - release a reference to a command + * @cmd: command to release * - * This routine unconditionally frees a command, and reference counting - * or list removal must be done in the caller. + * This routine releases our reference to the command and frees it if possible. */ -static int transport_release_cmd(struct se_cmd *cmd) +static int transport_put_cmd(struct se_cmd *cmd) { BUG_ON(!cmd->se_tfo); - - if (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) - core_tmr_release_req(cmd->se_tmr_req); - if (cmd->t_task_cdb != cmd->__t_task_cdb) - kfree(cmd->t_task_cdb); /* * If this cmd has been setup with target_get_sess_cmd(), drop * the kref and call ->release_cmd() in kref callback. @@ -2243,18 +2236,6 @@ static int transport_release_cmd(struct se_cmd *cmd) return target_put_sess_cmd(cmd); } -/** - * transport_put_cmd - release a reference to a command - * @cmd: command to release - * - * This routine releases our reference to the command and frees it if possible. - */ -static int transport_put_cmd(struct se_cmd *cmd) -{ - transport_free_pages(cmd); - return transport_release_cmd(cmd); -} - void *transport_kmap_data_sg(struct se_cmd *cmd) { struct scatterlist *sg = cmd->t_data_sg; @@ -2452,14 +2433,13 @@ static void transport_write_pending_qf(struct se_cmd *cmd) int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks) { - unsigned long flags; int ret = 0; if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD)) { if (wait_for_tasks && (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) - transport_wait_for_tasks(cmd); + transport_wait_for_tasks(cmd); - ret = transport_release_cmd(cmd); + ret = transport_put_cmd(cmd); } else { if (wait_for_tasks) transport_wait_for_tasks(cmd); @@ -2468,11 +2448,8 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks) * has already added se_cmd to state_list, but fabric has * failed command before I/O submission. */ - if (cmd->state_active) { - spin_lock_irqsave(&cmd->t_state_lock, flags); + if (cmd->state_active) target_remove_from_state_list(cmd); - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - } if (cmd->se_lun) transport_lun_remove_cmd(cmd); @@ -2517,6 +2494,16 @@ out: } EXPORT_SYMBOL(target_get_sess_cmd); +static void target_free_cmd_mem(struct se_cmd *cmd) +{ + transport_free_pages(cmd); + + if (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) + core_tmr_release_req(cmd->se_tmr_req); + if (cmd->t_task_cdb != cmd->__t_task_cdb) + kfree(cmd->t_task_cdb); +} + static void target_release_cmd_kref(struct kref *kref) { struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref); @@ -2526,17 +2513,20 @@ static void target_release_cmd_kref(struct kref *kref) spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); if (list_empty(&se_cmd->se_cmd_list)) { spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); + target_free_cmd_mem(se_cmd); se_cmd->se_tfo->release_cmd(se_cmd); return; } if (se_sess->sess_tearing_down && se_cmd->cmd_wait_set) { spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); + target_free_cmd_mem(se_cmd); complete(&se_cmd->cmd_wait_comp); return; } list_del(&se_cmd->se_cmd_list); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); + target_free_cmd_mem(se_cmd); se_cmd->se_tfo->release_cmd(se_cmd); } @@ -2548,6 +2538,7 @@ int target_put_sess_cmd(struct se_cmd *se_cmd) struct se_session *se_sess = se_cmd->se_sess; if (!se_sess) { + target_free_cmd_mem(se_cmd); se_cmd->se_tfo->release_cmd(se_cmd); return 1; } diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 5d82816cc4e3..1a76726c45a2 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -140,6 +140,7 @@ enum se_cmd_flags_table { SCF_COMPARE_AND_WRITE = 0x00080000, SCF_COMPARE_AND_WRITE_POST = 0x00100000, SCF_PASSTHROUGH_PROT_SG_TO_MEM_NOALLOC = 0x00200000, + SCF_ACK_KREF = 0x00400000, }; /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */ -- cgit v1.2.3 From a6d9bb1c9605cd4f44e2d8290dc4d0e88f20292d Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 11 Jan 2016 21:53:05 -0800 Subject: target: Fix LUN_RESET active TMR descriptor handling This patch fixes a NULL pointer se_cmd->cmd_kref < 0 refcount bug during TMR LUN_RESET with active TMRs, triggered during se_cmd + se_tmr_req descriptor shutdown + release via core_tmr_drain_tmr_list(). To address this bug, go ahead and obtain a local kref_get_unless_zero(&se_cmd->cmd_kref) for active I/O to set CMD_T_ABORTED, and transport_wait_for_tasks() followed by the final target_put_sess_cmd() to drop the local ->cmd_kref. Also add two new checks within target_tmr_work() to avoid CMD_T_ABORTED -> TFO->queue_tm_rsp() callbacks ahead of invoking the backend -> fabric put in transport_cmd_check_stop_to_fabric(). For good measure, also change core_tmr_release_req() to use list_del_init() ahead of se_tmr_req memory free. Reviewed-by: Quinn Tran Cc: Himanshu Madhani Cc: Sagi Grimberg Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Andy Grover Cc: Mike Christie Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_tmr.c | 22 +++++++++++++++++++++- drivers/target/target_core_transport.c | 17 +++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index fb3decc28589..072af07bd2ff 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -68,7 +68,7 @@ void core_tmr_release_req(struct se_tmr_req *tmr) if (dev) { spin_lock_irqsave(&dev->se_tmr_lock, flags); - list_del(&tmr->tmr_list); + list_del_init(&tmr->tmr_list); spin_unlock_irqrestore(&dev->se_tmr_lock, flags); } @@ -194,9 +194,11 @@ static void core_tmr_drain_tmr_list( struct list_head *preempt_and_abort_list) { LIST_HEAD(drain_tmr_list); + struct se_session *sess; struct se_tmr_req *tmr_p, *tmr_pp; struct se_cmd *cmd; unsigned long flags; + bool rc; /* * Release all pending and outgoing TMRs aside from the received * LUN_RESET tmr.. @@ -222,17 +224,31 @@ static void core_tmr_drain_tmr_list( if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd)) continue; + sess = cmd->se_sess; + if (WARN_ON_ONCE(!sess)) + continue; + + spin_lock(&sess->sess_cmd_lock); spin_lock(&cmd->t_state_lock); if (!(cmd->transport_state & CMD_T_ACTIVE)) { spin_unlock(&cmd->t_state_lock); + spin_unlock(&sess->sess_cmd_lock); continue; } if (cmd->t_state == TRANSPORT_ISTATE_PROCESSING) { spin_unlock(&cmd->t_state_lock); + spin_unlock(&sess->sess_cmd_lock); continue; } + cmd->transport_state |= CMD_T_ABORTED; spin_unlock(&cmd->t_state_lock); + rc = kref_get_unless_zero(&cmd->cmd_kref); + spin_unlock(&sess->sess_cmd_lock); + if (!rc) { + printk("LUN_RESET TMR: non-zero kref_get_unless_zero\n"); + continue; + } list_move_tail(&tmr_p->tmr_list, &drain_tmr_list); } spin_unlock_irqrestore(&dev->se_tmr_lock, flags); @@ -246,7 +262,11 @@ static void core_tmr_drain_tmr_list( (preempt_and_abort_list) ? "Preempt" : "", tmr_p, tmr_p->function, tmr_p->response, cmd->t_state); + cancel_work_sync(&cmd->work); + transport_wait_for_tasks(cmd); + transport_cmd_finish_abort(cmd, 1); + target_put_sess_cmd(cmd); } } diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index af52f8bd8954..94e372af9e28 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2900,8 +2900,17 @@ static void target_tmr_work(struct work_struct *work) struct se_cmd *cmd = container_of(work, struct se_cmd, work); struct se_device *dev = cmd->se_dev; struct se_tmr_req *tmr = cmd->se_tmr_req; + unsigned long flags; int ret; + spin_lock_irqsave(&cmd->t_state_lock, flags); + if (cmd->transport_state & CMD_T_ABORTED) { + tmr->response = TMR_FUNCTION_REJECTED; + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + goto check_stop; + } + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + switch (tmr->function) { case TMR_ABORT_TASK: core_tmr_abort_task(dev, tmr, cmd->se_sess); @@ -2934,9 +2943,17 @@ static void target_tmr_work(struct work_struct *work) break; } + spin_lock_irqsave(&cmd->t_state_lock, flags); + if (cmd->transport_state & CMD_T_ABORTED) { + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + goto check_stop; + } cmd->t_state = TRANSPORT_ISTATE_PROCESSING; + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + cmd->se_tfo->queue_tm_rsp(cmd); +check_stop: transport_cmd_check_stop_to_fabric(cmd); } -- cgit v1.2.3 From ebde1ca5a908b10312db4ecd7553e3ba039319ab Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sat, 16 Jan 2016 12:49:49 -0800 Subject: target: Fix TAS handling for multi-session se_node_acls This patch fixes a bug in TMR task aborted status (TAS) handling when multiple sessions are connected to the same target WWPN endpoint and se_node_acl descriptor, resulting in TASK_ABORTED status to not be generated for aborted se_cmds on the remote port. This is due to core_tmr_handle_tas_abort() incorrectly comparing se_node_acl instead of se_session, for which the multi-session case is expected to be sharing the same se_node_acl. Instead, go ahead and update core_tmr_handle_tas_abort() to compare tmr_sess + cmd->se_sess in order to determine if the LUN_RESET was received on a different I_T nexus, and TASK_ABORTED status response needs to be generated. Reviewed-by: Christoph Hellwig Cc: Quinn Tran Cc: Himanshu Madhani Cc: Sagi Grimberg Cc: Hannes Reinecke Cc: Andy Grover Cc: Mike Christie Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_tmr.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 072af07bd2ff..3e0d77a4c7b6 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -76,7 +76,7 @@ void core_tmr_release_req(struct se_tmr_req *tmr) } static void core_tmr_handle_tas_abort( - struct se_node_acl *tmr_nacl, + struct se_session *tmr_sess, struct se_cmd *cmd, int tas) { @@ -84,7 +84,7 @@ static void core_tmr_handle_tas_abort( /* * TASK ABORTED status (TAS) bit support */ - if ((tmr_nacl && (tmr_nacl != cmd->se_sess->se_node_acl)) && tas) { + if (tmr_sess && tmr_sess != cmd->se_sess && tas) { remove = false; transport_send_task_abort(cmd); } @@ -273,7 +273,7 @@ static void core_tmr_drain_tmr_list( static void core_tmr_drain_state_list( struct se_device *dev, struct se_cmd *prout_cmd, - struct se_node_acl *tmr_nacl, + struct se_session *tmr_sess, int tas, struct list_head *preempt_and_abort_list) { @@ -364,7 +364,7 @@ static void core_tmr_drain_state_list( cancel_work_sync(&cmd->work); transport_wait_for_tasks(cmd); - core_tmr_handle_tas_abort(tmr_nacl, cmd, tas); + core_tmr_handle_tas_abort(tmr_sess, cmd, tas); target_put_sess_cmd(cmd); } } @@ -377,6 +377,7 @@ int core_tmr_lun_reset( { struct se_node_acl *tmr_nacl = NULL; struct se_portal_group *tmr_tpg = NULL; + struct se_session *tmr_sess = NULL; int tas; /* * TASK_ABORTED status bit, this is configurable via ConfigFS @@ -395,8 +396,9 @@ int core_tmr_lun_reset( * or struct se_device passthrough.. */ if (tmr && tmr->task_cmd && tmr->task_cmd->se_sess) { - tmr_nacl = tmr->task_cmd->se_sess->se_node_acl; - tmr_tpg = tmr->task_cmd->se_sess->se_tpg; + tmr_sess = tmr->task_cmd->se_sess; + tmr_nacl = tmr_sess->se_node_acl; + tmr_tpg = tmr_sess->se_tpg; if (tmr_nacl && tmr_tpg) { pr_debug("LUN_RESET: TMR caller fabric: %s" " initiator port %s\n", @@ -409,7 +411,7 @@ int core_tmr_lun_reset( dev->transport->name, tas); core_tmr_drain_tmr_list(dev, tmr, preempt_and_abort_list); - core_tmr_drain_state_list(dev, prout_cmd, tmr_nacl, tas, + core_tmr_drain_state_list(dev, prout_cmd, tmr_sess, tas, preempt_and_abort_list); /* -- cgit v1.2.3 From 305b37bd01c220a7a6285911d43c9884270257be Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Wed, 3 Feb 2016 12:31:49 +0100 Subject: misc: Move panel driver out of staging Move panel driver from drivers/staging/panel to drivers/misc. Signed-off-by: Ksenija Stanojevic Acked-by: Willy Tarreau Signed-off-by: Greg Kroah-Hartman --- Documentation/misc-devices/lcd-panel-cgram.txt | 24 + MAINTAINERS | 12 +- drivers/misc/Kconfig | 278 +++ drivers/misc/Makefile | 1 + drivers/misc/panel.c | 2445 ++++++++++++++++++++++++ drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/panel/Kconfig | 278 --- drivers/staging/panel/Makefile | 1 - drivers/staging/panel/TODO | 8 - drivers/staging/panel/lcd-panel-cgram.txt | 24 - drivers/staging/panel/panel.c | 2445 ------------------------ 12 files changed, 2755 insertions(+), 2764 deletions(-) create mode 100644 Documentation/misc-devices/lcd-panel-cgram.txt create mode 100644 drivers/misc/panel.c delete mode 100644 drivers/staging/panel/Kconfig delete mode 100644 drivers/staging/panel/Makefile delete mode 100644 drivers/staging/panel/TODO delete mode 100644 drivers/staging/panel/lcd-panel-cgram.txt delete mode 100644 drivers/staging/panel/panel.c (limited to 'drivers') diff --git a/Documentation/misc-devices/lcd-panel-cgram.txt b/Documentation/misc-devices/lcd-panel-cgram.txt new file mode 100644 index 000000000000..7f82c905763d --- /dev/null +++ b/Documentation/misc-devices/lcd-panel-cgram.txt @@ -0,0 +1,24 @@ +Some LCDs allow you to define up to 8 characters, mapped to ASCII +characters 0 to 7. The escape code to define a new character is +'\e[LG' followed by one digit from 0 to 7, representing the character +number, and up to 8 couples of hex digits terminated by a semi-colon +(';'). Each couple of digits represents a line, with 1-bits for each +illuminated pixel with LSB on the right. Lines are numbered from the +top of the character to the bottom. On a 5x7 matrix, only the 5 lower +bits of the 7 first bytes are used for each character. If the string +is incomplete, only complete lines will be redefined. Here are some +examples : + + printf "\e[LG0010101050D1F0C04;" => 0 = [enter] + printf "\e[LG1040E1F0000000000;" => 1 = [up] + printf "\e[LG2000000001F0E0400;" => 2 = [down] + printf "\e[LG3040E1F001F0E0400;" => 3 = [up-down] + printf "\e[LG40002060E1E0E0602;" => 4 = [left] + printf "\e[LG500080C0E0F0E0C08;" => 5 = [right] + printf "\e[LG60016051516141400;" => 6 = "IP" + + printf "\e[LG00103071F1F070301;" => big speaker + printf "\e[LG00002061E1E060200;" => small speaker + +Willy + diff --git a/MAINTAINERS b/MAINTAINERS index 369f6aefc189..7c39a48b4118 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8168,6 +8168,13 @@ S: Maintained F: Documentation/mn10300/ F: arch/mn10300/ +PARALLEL LCD/KEYPAD PANEL DRIVER +M: Willy Tarreau +M: Ksenija Stanojevic +S: Odd Fixes +F: Documentation/misc-devices/lcd-panel-cgram.txt +F: drivers/misc/panel.c + PARALLEL PORT SUBSYSTEM M: Sudip Mukherjee M: Sudip Mukherjee @@ -10391,11 +10398,6 @@ L: linux-tegra@vger.kernel.org S: Maintained F: drivers/staging/nvec/ -STAGING - PARALLEL LCD/KEYPAD PANEL DRIVER -M: Willy Tarreau -S: Odd Fixes -F: drivers/staging/panel/ - STAGING - REALTEK RTL8712U DRIVERS M: Larry Finger M: Florian Schilhabel . diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 054fc10cb3b6..f0ba78289504 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -525,6 +525,284 @@ config VEXPRESS_SYSCFG ARM Ltd. Versatile Express uses specialised platform configuration bus. System Configuration interface is one of the possible means of generating transactions on this bus. +config PANEL + tristate "Parallel port LCD/Keypad Panel support" + depends on PARPORT + ---help--- + Say Y here if you have an HD44780 or KS-0074 LCD connected to your + parallel port. This driver also features 4 and 6-key keypads. The LCD + is accessible through the /dev/lcd char device (10, 156), and the + keypad through /dev/keypad (10, 185). Both require misc device to be + enabled. This code can either be compiled as a module, or linked into + the kernel and started at boot. If you don't understand what all this + is about, say N. + +config PANEL_PARPORT + int "Default parallel port number (0=LPT1)" + depends on PANEL + range 0 255 + default "0" + ---help--- + This is the index of the parallel port the panel is connected to. One + driver instance only supports one parallel port, so if your keypad + and LCD are connected to two separate ports, you have to start two + modules with different arguments. Numbering starts with '0' for LPT1, + and so on. + +config PANEL_PROFILE + int "Default panel profile (0-5, 0=custom)" + depends on PANEL + range 0 5 + default "5" + ---help--- + To ease configuration, the driver supports different configuration + profiles for past and recent wirings. These profiles can also be + used to define an approximative configuration, completed by a few + other options. Here are the profiles : + + 0 = custom (see further) + 1 = 2x16 parallel LCD, old keypad + 2 = 2x16 serial LCD (KS-0074), new keypad + 3 = 2x16 parallel LCD (Hantronix), no keypad + 4 = 2x16 parallel LCD (Nexcom NSA1045) with Nexcom's keypad + 5 = 2x40 parallel LCD (old one), with old keypad + + Custom configurations allow you to define how your display is + wired to the parallel port, and how it works. This is only intended + for experts. + +config PANEL_KEYPAD + depends on PANEL && PANEL_PROFILE="0" + int "Keypad type (0=none, 1=old 6 keys, 2=new 6 keys, 3=Nexcom 4 keys)" + range 0 3 + default 0 + ---help--- + This enables and configures a keypad connected to the parallel port. + The keys will be read from character device 10,185. Valid values are : + + 0 : do not enable this driver + 1 : old 6 keys keypad + 2 : new 6 keys keypad, as used on the server at www.ant-computing.com + 3 : Nexcom NSA1045's 4 keys keypad + + New profiles can be described in the driver source. The driver also + supports simultaneous keys pressed when the keypad supports them. + +config PANEL_LCD + depends on PANEL && PANEL_PROFILE="0" + int "LCD type (0=none, 1=custom, 2=old //, 3=ks0074, 4=hantronix, 5=Nexcom)" + range 0 5 + default 0 + ---help--- + This enables and configures an LCD connected to the parallel port. + The driver includes an interpreter for escape codes starting with + '\e[L' which are specific to the LCD, and a few ANSI codes. The + driver will be registered as character device 10,156, usually + under the name '/dev/lcd'. There are a total of 6 supported types : + + 0 : do not enable the driver + 1 : custom configuration and wiring (see further) + 2 : 2x16 & 2x40 parallel LCD (old wiring) + 3 : 2x16 serial LCD (KS-0074 based) + 4 : 2x16 parallel LCD (Hantronix wiring) + 5 : 2x16 parallel LCD (Nexcom wiring) + + When type '1' is specified, other options will appear to configure + more precise aspects (wiring, dimensions, protocol, ...). Please note + that those values changed from the 2.4 driver for better consistency. + +config PANEL_LCD_HEIGHT + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" + int "Number of lines on the LCD (1-2)" + range 1 2 + default 2 + ---help--- + This is the number of visible character lines on the LCD in custom profile. + It can either be 1 or 2. + +config PANEL_LCD_WIDTH + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" + int "Number of characters per line on the LCD (1-40)" + range 1 40 + default 40 + ---help--- + This is the number of characters per line on the LCD in custom profile. + Common values are 16,20,24,40. + +config PANEL_LCD_BWIDTH + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" + int "Internal LCD line width (1-40, 40 by default)" + range 1 40 + default 40 + ---help--- + Most LCDs use a standard controller which supports hardware lines of 40 + characters, although sometimes only 16, 20 or 24 of them are really wired + to the terminal. This results in some non-visible but addressable characters, + and is the case for most parallel LCDs. Other LCDs, and some serial ones, + however, use the same line width internally as what is visible. The KS0074 + for example, uses 16 characters per line for 16 visible characters per line. + + This option lets you configure the value used by your LCD in 'custom' profile. + If you don't know, put '40' here. + +config PANEL_LCD_HWIDTH + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" + int "Hardware LCD line width (1-64, 64 by default)" + range 1 64 + default 64 + ---help--- + Most LCDs use a single address bit to differentiate line 0 and line 1. Since + some of them need to be able to address 40 chars with the lower bits, they + often use the immediately superior power of 2, which is 64, to address the + next line. + + If you don't know what your LCD uses, in doubt let 16 here for a 2x16, and + 64 here for a 2x40. + +config PANEL_LCD_CHARSET + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" + int "LCD character set (0=normal, 1=KS0074)" + range 0 1 + default 0 + ---help--- + Some controllers such as the KS0074 use a somewhat strange character set + where many symbols are at unusual places. The driver knows how to map + 'standard' ASCII characters to the character sets used by these controllers. + Valid values are : + + 0 : normal (untranslated) character set + 1 : KS0074 character set + + If you don't know, use the normal one (0). + +config PANEL_LCD_PROTO + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" + int "LCD communication mode (0=parallel 8 bits, 1=serial)" + range 0 1 + default 0 + ---help--- + This driver now supports any serial or parallel LCD wired to a parallel + port. But before assigning signals, the driver needs to know if it will + be driving a serial LCD or a parallel one. Serial LCDs only use 2 wires + (SDA/SCL), while parallel ones use 2 or 3 wires for the control signals + (E, RS, sometimes RW), and 4 or 8 for the data. Use 0 here for a 8 bits + parallel LCD, and 1 for a serial LCD. + +config PANEL_LCD_PIN_E + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0" + int "Parallel port pin number & polarity connected to the LCD E signal (-17...17) " + range -17 17 + default 14 + ---help--- + This describes the number of the parallel port pin to which the LCD 'E' + signal has been connected. It can be : + + 0 : no connection (eg: connected to ground) + 1..17 : directly connected to any of these pins on the DB25 plug + -1..-17 : connected to the same pin through an inverter (eg: transistor). + + Default for the 'E' pin in custom profile is '14' (AUTOFEED). + +config PANEL_LCD_PIN_RS + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0" + int "Parallel port pin number & polarity connected to the LCD RS signal (-17...17) " + range -17 17 + default 17 + ---help--- + This describes the number of the parallel port pin to which the LCD 'RS' + signal has been connected. It can be : + + 0 : no connection (eg: connected to ground) + 1..17 : directly connected to any of these pins on the DB25 plug + -1..-17 : connected to the same pin through an inverter (eg: transistor). + + Default for the 'RS' pin in custom profile is '17' (SELECT IN). + +config PANEL_LCD_PIN_RW + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0" + int "Parallel port pin number & polarity connected to the LCD RW signal (-17...17) " + range -17 17 + default 16 + ---help--- + This describes the number of the parallel port pin to which the LCD 'RW' + signal has been connected. It can be : + + 0 : no connection (eg: connected to ground) + 1..17 : directly connected to any of these pins on the DB25 plug + -1..-17 : connected to the same pin through an inverter (eg: transistor). + + Default for the 'RW' pin in custom profile is '16' (INIT). + +config PANEL_LCD_PIN_SCL + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO!="0" + int "Parallel port pin number & polarity connected to the LCD SCL signal (-17...17) " + range -17 17 + default 1 + ---help--- + This describes the number of the parallel port pin to which the serial + LCD 'SCL' signal has been connected. It can be : + + 0 : no connection (eg: connected to ground) + 1..17 : directly connected to any of these pins on the DB25 plug + -1..-17 : connected to the same pin through an inverter (eg: transistor). + + Default for the 'SCL' pin in custom profile is '1' (STROBE). + +config PANEL_LCD_PIN_SDA + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO!="0" + int "Parallel port pin number & polarity connected to the LCD SDA signal (-17...17) " + range -17 17 + default 2 + ---help--- + This describes the number of the parallel port pin to which the serial + LCD 'SDA' signal has been connected. It can be : + + 0 : no connection (eg: connected to ground) + 1..17 : directly connected to any of these pins on the DB25 plug + -1..-17 : connected to the same pin through an inverter (eg: transistor). + + Default for the 'SDA' pin in custom profile is '2' (D0). + +config PANEL_LCD_PIN_BL + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" + int "Parallel port pin number & polarity connected to the LCD backlight signal (-17...17) " + range -17 17 + default 0 + ---help--- + This describes the number of the parallel port pin to which the LCD 'BL' signal + has been connected. It can be : + + 0 : no connection (eg: connected to ground) + 1..17 : directly connected to any of these pins on the DB25 plug + -1..-17 : connected to the same pin through an inverter (eg: transistor). + + Default for the 'BL' pin in custom profile is '0' (uncontrolled). + +config PANEL_CHANGE_MESSAGE + depends on PANEL + bool "Change LCD initialization message ?" + default "n" + ---help--- + This allows you to replace the boot message indicating the kernel version + and the driver version with a custom message. This is useful on appliances + where a simple 'Starting system' message can be enough to stop a customer + from worrying. + + If you say 'Y' here, you'll be able to choose a message yourself. Otherwise, + say 'N' and keep the default message with the version. + +config PANEL_BOOT_MESSAGE + depends on PANEL && PANEL_CHANGE_MESSAGE="y" + string "New initialization message" + default "" + ---help--- + This allows you to replace the boot message indicating the kernel version + and the driver version with a custom message. This is useful on appliances + where a simple 'Starting system' message can be enough to stop a customer + from worrying. + + An empty message will only clear the display at driver init time. Any other + printf()-formatted message is valid with newline and escape codes. source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 537d7f3b78da..b2fb6dbffcef 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -56,3 +56,4 @@ obj-$(CONFIG_GENWQE) += genwqe/ obj-$(CONFIG_ECHO) += echo/ obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o obj-$(CONFIG_CXL_BASE) += cxl/ +obj-$(CONFIG_PANEL) += panel.o diff --git a/drivers/misc/panel.c b/drivers/misc/panel.c new file mode 100644 index 000000000000..4262db0237f9 --- /dev/null +++ b/drivers/misc/panel.c @@ -0,0 +1,2445 @@ +/* + * Front panel driver for Linux + * Copyright (C) 2000-2008, Willy Tarreau + * + * 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 code drives an LCD module (/dev/lcd), and a keypad (/dev/keypad) + * connected to a parallel printer port. + * + * The LCD module may either be an HD44780-like 8-bit parallel LCD, or a 1-bit + * serial module compatible with Samsung's KS0074. The pins may be connected in + * any combination, everything is programmable. + * + * The keypad consists in a matrix of push buttons connecting input pins to + * data output pins or to the ground. The combinations have to be hard-coded + * in the driver, though several profiles exist and adding new ones is easy. + * + * Several profiles are provided for commonly found LCD+keypad modules on the + * market, such as those found in Nexcom's appliances. + * + * FIXME: + * - the initialization/deinitialization process is very dirty and should + * be rewritten. It may even be buggy. + * + * TODO: + * - document 24 keys keyboard (3 rows of 8 cols, 32 diodes + 2 inputs) + * - make the LCD a part of a virtual screen of Vx*Vy + * - make the inputs list smp-safe + * - change the keyboard to a double mapping : signals -> key_id -> values + * so that applications can change values without knowing signals + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define LCD_MINOR 156 +#define KEYPAD_MINOR 185 + +#define PANEL_VERSION "0.9.5" + +#define LCD_MAXBYTES 256 /* max burst write */ + +#define KEYPAD_BUFFER 64 + +/* poll the keyboard this every second */ +#define INPUT_POLL_TIME (HZ / 50) +/* a key starts to repeat after this times INPUT_POLL_TIME */ +#define KEYPAD_REP_START (10) +/* a key repeats this times INPUT_POLL_TIME */ +#define KEYPAD_REP_DELAY (2) + +/* keep the light on this times INPUT_POLL_TIME for each flash */ +#define FLASH_LIGHT_TEMPO (200) + +/* converts an r_str() input to an active high, bits string : 000BAOSE */ +#define PNL_PINPUT(a) ((((unsigned char)(a)) ^ 0x7F) >> 3) + +#define PNL_PBUSY 0x80 /* inverted input, active low */ +#define PNL_PACK 0x40 /* direct input, active low */ +#define PNL_POUTPA 0x20 /* direct input, active high */ +#define PNL_PSELECD 0x10 /* direct input, active high */ +#define PNL_PERRORP 0x08 /* direct input, active low */ + +#define PNL_PBIDIR 0x20 /* bi-directional ports */ +/* high to read data in or-ed with data out */ +#define PNL_PINTEN 0x10 +#define PNL_PSELECP 0x08 /* inverted output, active low */ +#define PNL_PINITP 0x04 /* direct output, active low */ +#define PNL_PAUTOLF 0x02 /* inverted output, active low */ +#define PNL_PSTROBE 0x01 /* inverted output */ + +#define PNL_PD0 0x01 +#define PNL_PD1 0x02 +#define PNL_PD2 0x04 +#define PNL_PD3 0x08 +#define PNL_PD4 0x10 +#define PNL_PD5 0x20 +#define PNL_PD6 0x40 +#define PNL_PD7 0x80 + +#define PIN_NONE 0 +#define PIN_STROBE 1 +#define PIN_D0 2 +#define PIN_D1 3 +#define PIN_D2 4 +#define PIN_D3 5 +#define PIN_D4 6 +#define PIN_D5 7 +#define PIN_D6 8 +#define PIN_D7 9 +#define PIN_AUTOLF 14 +#define PIN_INITP 16 +#define PIN_SELECP 17 +#define PIN_NOT_SET 127 + +#define LCD_FLAG_S 0x0001 +#define LCD_FLAG_ID 0x0002 +#define LCD_FLAG_B 0x0004 /* blink on */ +#define LCD_FLAG_C 0x0008 /* cursor on */ +#define LCD_FLAG_D 0x0010 /* display on */ +#define LCD_FLAG_F 0x0020 /* large font mode */ +#define LCD_FLAG_N 0x0040 /* 2-rows mode */ +#define LCD_FLAG_L 0x0080 /* backlight enabled */ + +/* LCD commands */ +#define LCD_CMD_DISPLAY_CLEAR 0x01 /* Clear entire display */ + +#define LCD_CMD_ENTRY_MODE 0x04 /* Set entry mode */ +#define LCD_CMD_CURSOR_INC 0x02 /* Increment cursor */ + +#define LCD_CMD_DISPLAY_CTRL 0x08 /* Display control */ +#define LCD_CMD_DISPLAY_ON 0x04 /* Set display on */ +#define LCD_CMD_CURSOR_ON 0x02 /* Set cursor on */ +#define LCD_CMD_BLINK_ON 0x01 /* Set blink on */ + +#define LCD_CMD_SHIFT 0x10 /* Shift cursor/display */ +#define LCD_CMD_DISPLAY_SHIFT 0x08 /* Shift display instead of cursor */ +#define LCD_CMD_SHIFT_RIGHT 0x04 /* Shift display/cursor to the right */ + +#define LCD_CMD_FUNCTION_SET 0x20 /* Set function */ +#define LCD_CMD_DATA_LEN_8BITS 0x10 /* Set data length to 8 bits */ +#define LCD_CMD_TWO_LINES 0x08 /* Set to two display lines */ +#define LCD_CMD_FONT_5X10_DOTS 0x04 /* Set char font to 5x10 dots */ + +#define LCD_CMD_SET_CGRAM_ADDR 0x40 /* Set char generator RAM address */ + +#define LCD_CMD_SET_DDRAM_ADDR 0x80 /* Set display data RAM address */ + +#define LCD_ESCAPE_LEN 24 /* max chars for LCD escape command */ +#define LCD_ESCAPE_CHAR 27 /* use char 27 for escape command */ + +#define NOT_SET -1 + +/* macros to simplify use of the parallel port */ +#define r_ctr(x) (parport_read_control((x)->port)) +#define r_dtr(x) (parport_read_data((x)->port)) +#define r_str(x) (parport_read_status((x)->port)) +#define w_ctr(x, y) (parport_write_control((x)->port, (y))) +#define w_dtr(x, y) (parport_write_data((x)->port, (y))) + +/* this defines which bits are to be used and which ones to be ignored */ +/* logical or of the output bits involved in the scan matrix */ +static __u8 scan_mask_o; +/* logical or of the input bits involved in the scan matrix */ +static __u8 scan_mask_i; + +enum input_type { + INPUT_TYPE_STD, + INPUT_TYPE_KBD, +}; + +enum input_state { + INPUT_ST_LOW, + INPUT_ST_RISING, + INPUT_ST_HIGH, + INPUT_ST_FALLING, +}; + +struct logical_input { + struct list_head list; + __u64 mask; + __u64 value; + enum input_type type; + enum input_state state; + __u8 rise_time, fall_time; + __u8 rise_timer, fall_timer, high_timer; + + union { + struct { /* valid when type == INPUT_TYPE_STD */ + void (*press_fct)(int); + void (*release_fct)(int); + int press_data; + int release_data; + } std; + struct { /* valid when type == INPUT_TYPE_KBD */ + /* strings can be non null-terminated */ + char press_str[sizeof(void *) + sizeof(int)]; + char repeat_str[sizeof(void *) + sizeof(int)]; + char release_str[sizeof(void *) + sizeof(int)]; + } kbd; + } u; +}; + +static LIST_HEAD(logical_inputs); /* list of all defined logical inputs */ + +/* physical contacts history + * Physical contacts are a 45 bits string of 9 groups of 5 bits each. + * The 8 lower groups correspond to output bits 0 to 7, and the 9th group + * corresponds to the ground. + * Within each group, bits are stored in the same order as read on the port : + * BAPSE (busy=4, ack=3, paper empty=2, select=1, error=0). + * So, each __u64 is represented like this : + * 0000000000000000000BAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSE + * <-----unused------> + */ + +/* what has just been read from the I/O ports */ +static __u64 phys_read; +/* previous phys_read */ +static __u64 phys_read_prev; +/* stabilized phys_read (phys_read|phys_read_prev) */ +static __u64 phys_curr; +/* previous phys_curr */ +static __u64 phys_prev; +/* 0 means that at least one logical signal needs be computed */ +static char inputs_stable; + +/* these variables are specific to the keypad */ +static struct { + bool enabled; +} keypad; + +static char keypad_buffer[KEYPAD_BUFFER]; +static int keypad_buflen; +static int keypad_start; +static char keypressed; +static wait_queue_head_t keypad_read_wait; + +/* lcd-specific variables */ +static struct { + bool enabled; + bool initialized; + bool must_clear; + + int height; + int width; + int bwidth; + int hwidth; + int charset; + int proto; + int light_tempo; + + /* TODO: use union here? */ + struct { + int e; + int rs; + int rw; + int cl; + int da; + int bl; + } pins; + + /* contains the LCD config state */ + unsigned long int flags; + + /* Contains the LCD X and Y offset */ + struct { + unsigned long int x; + unsigned long int y; + } addr; + + /* Current escape sequence and it's length or -1 if outside */ + struct { + char buf[LCD_ESCAPE_LEN + 1]; + int len; + } esc_seq; +} lcd; + +/* Needed only for init */ +static int selected_lcd_type = NOT_SET; + +/* + * Bit masks to convert LCD signals to parallel port outputs. + * _d_ are values for data port, _c_ are for control port. + * [0] = signal OFF, [1] = signal ON, [2] = mask + */ +#define BIT_CLR 0 +#define BIT_SET 1 +#define BIT_MSK 2 +#define BIT_STATES 3 +/* + * one entry for each bit on the LCD + */ +#define LCD_BIT_E 0 +#define LCD_BIT_RS 1 +#define LCD_BIT_RW 2 +#define LCD_BIT_BL 3 +#define LCD_BIT_CL 4 +#define LCD_BIT_DA 5 +#define LCD_BITS 6 + +/* + * each bit can be either connected to a DATA or CTRL port + */ +#define LCD_PORT_C 0 +#define LCD_PORT_D 1 +#define LCD_PORTS 2 + +static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES]; + +/* + * LCD protocols + */ +#define LCD_PROTO_PARALLEL 0 +#define LCD_PROTO_SERIAL 1 +#define LCD_PROTO_TI_DA8XX_LCD 2 + +/* + * LCD character sets + */ +#define LCD_CHARSET_NORMAL 0 +#define LCD_CHARSET_KS0074 1 + +/* + * LCD types + */ +#define LCD_TYPE_NONE 0 +#define LCD_TYPE_CUSTOM 1 +#define LCD_TYPE_OLD 2 +#define LCD_TYPE_KS0074 3 +#define LCD_TYPE_HANTRONIX 4 +#define LCD_TYPE_NEXCOM 5 + +/* + * keypad types + */ +#define KEYPAD_TYPE_NONE 0 +#define KEYPAD_TYPE_OLD 1 +#define KEYPAD_TYPE_NEW 2 +#define KEYPAD_TYPE_NEXCOM 3 + +/* + * panel profiles + */ +#define PANEL_PROFILE_CUSTOM 0 +#define PANEL_PROFILE_OLD 1 +#define PANEL_PROFILE_NEW 2 +#define PANEL_PROFILE_HANTRONIX 3 +#define PANEL_PROFILE_NEXCOM 4 +#define PANEL_PROFILE_LARGE 5 + +/* + * Construct custom config from the kernel's configuration + */ +#define DEFAULT_PARPORT 0 +#define DEFAULT_PROFILE PANEL_PROFILE_LARGE +#define DEFAULT_KEYPAD_TYPE KEYPAD_TYPE_OLD +#define DEFAULT_LCD_TYPE LCD_TYPE_OLD +#define DEFAULT_LCD_HEIGHT 2 +#define DEFAULT_LCD_WIDTH 40 +#define DEFAULT_LCD_BWIDTH 40 +#define DEFAULT_LCD_HWIDTH 64 +#define DEFAULT_LCD_CHARSET LCD_CHARSET_NORMAL +#define DEFAULT_LCD_PROTO LCD_PROTO_PARALLEL + +#define DEFAULT_LCD_PIN_E PIN_AUTOLF +#define DEFAULT_LCD_PIN_RS PIN_SELECP +#define DEFAULT_LCD_PIN_RW PIN_INITP +#define DEFAULT_LCD_PIN_SCL PIN_STROBE +#define DEFAULT_LCD_PIN_SDA PIN_D0 +#define DEFAULT_LCD_PIN_BL PIN_NOT_SET + +#ifdef CONFIG_PANEL_PARPORT +#undef DEFAULT_PARPORT +#define DEFAULT_PARPORT CONFIG_PANEL_PARPORT +#endif + +#ifdef CONFIG_PANEL_PROFILE +#undef DEFAULT_PROFILE +#define DEFAULT_PROFILE CONFIG_PANEL_PROFILE +#endif + +#if DEFAULT_PROFILE == 0 /* custom */ +#ifdef CONFIG_PANEL_KEYPAD +#undef DEFAULT_KEYPAD_TYPE +#define DEFAULT_KEYPAD_TYPE CONFIG_PANEL_KEYPAD +#endif + +#ifdef CONFIG_PANEL_LCD +#undef DEFAULT_LCD_TYPE +#define DEFAULT_LCD_TYPE CONFIG_PANEL_LCD +#endif + +#ifdef CONFIG_PANEL_LCD_HEIGHT +#undef DEFAULT_LCD_HEIGHT +#define DEFAULT_LCD_HEIGHT CONFIG_PANEL_LCD_HEIGHT +#endif + +#ifdef CONFIG_PANEL_LCD_WIDTH +#undef DEFAULT_LCD_WIDTH +#define DEFAULT_LCD_WIDTH CONFIG_PANEL_LCD_WIDTH +#endif + +#ifdef CONFIG_PANEL_LCD_BWIDTH +#undef DEFAULT_LCD_BWIDTH +#define DEFAULT_LCD_BWIDTH CONFIG_PANEL_LCD_BWIDTH +#endif + +#ifdef CONFIG_PANEL_LCD_HWIDTH +#undef DEFAULT_LCD_HWIDTH +#define DEFAULT_LCD_HWIDTH CONFIG_PANEL_LCD_HWIDTH +#endif + +#ifdef CONFIG_PANEL_LCD_CHARSET +#undef DEFAULT_LCD_CHARSET +#define DEFAULT_LCD_CHARSET CONFIG_PANEL_LCD_CHARSET +#endif + +#ifdef CONFIG_PANEL_LCD_PROTO +#undef DEFAULT_LCD_PROTO +#define DEFAULT_LCD_PROTO CONFIG_PANEL_LCD_PROTO +#endif + +#ifdef CONFIG_PANEL_LCD_PIN_E +#undef DEFAULT_LCD_PIN_E +#define DEFAULT_LCD_PIN_E CONFIG_PANEL_LCD_PIN_E +#endif + +#ifdef CONFIG_PANEL_LCD_PIN_RS +#undef DEFAULT_LCD_PIN_RS +#define DEFAULT_LCD_PIN_RS CONFIG_PANEL_LCD_PIN_RS +#endif + +#ifdef CONFIG_PANEL_LCD_PIN_RW +#undef DEFAULT_LCD_PIN_RW +#define DEFAULT_LCD_PIN_RW CONFIG_PANEL_LCD_PIN_RW +#endif + +#ifdef CONFIG_PANEL_LCD_PIN_SCL +#undef DEFAULT_LCD_PIN_SCL +#define DEFAULT_LCD_PIN_SCL CONFIG_PANEL_LCD_PIN_SCL +#endif + +#ifdef CONFIG_PANEL_LCD_PIN_SDA +#undef DEFAULT_LCD_PIN_SDA +#define DEFAULT_LCD_PIN_SDA CONFIG_PANEL_LCD_PIN_SDA +#endif + +#ifdef CONFIG_PANEL_LCD_PIN_BL +#undef DEFAULT_LCD_PIN_BL +#define DEFAULT_LCD_PIN_BL CONFIG_PANEL_LCD_PIN_BL +#endif + +#endif /* DEFAULT_PROFILE == 0 */ + +/* global variables */ + +/* Device single-open policy control */ +static atomic_t lcd_available = ATOMIC_INIT(1); +static atomic_t keypad_available = ATOMIC_INIT(1); + +static struct pardevice *pprt; + +static int keypad_initialized; + +static void (*lcd_write_cmd)(int); +static void (*lcd_write_data)(int); +static void (*lcd_clear_fast)(void); + +static DEFINE_SPINLOCK(pprt_lock); +static struct timer_list scan_timer; + +MODULE_DESCRIPTION("Generic parallel port LCD/Keypad driver"); + +static int parport = DEFAULT_PARPORT; +module_param(parport, int, 0000); +MODULE_PARM_DESC(parport, "Parallel port index (0=lpt1, 1=lpt2, ...)"); + +static int profile = DEFAULT_PROFILE; +module_param(profile, int, 0000); +MODULE_PARM_DESC(profile, + "1=16x2 old kp; 2=serial 16x2, new kp; 3=16x2 hantronix; " + "4=16x2 nexcom; default=40x2, old kp"); + +static int keypad_type = NOT_SET; +module_param(keypad_type, int, 0000); +MODULE_PARM_DESC(keypad_type, + "Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, 3=nexcom 4 keys"); + +static int lcd_type = NOT_SET; +module_param(lcd_type, int, 0000); +MODULE_PARM_DESC(lcd_type, + "LCD type: 0=none, 1=compiled-in, 2=old, 3=serial ks0074, 4=hantronix, 5=nexcom"); + +static int lcd_height = NOT_SET; +module_param(lcd_height, int, 0000); +MODULE_PARM_DESC(lcd_height, "Number of lines on the LCD"); + +static int lcd_width = NOT_SET; +module_param(lcd_width, int, 0000); +MODULE_PARM_DESC(lcd_width, "Number of columns on the LCD"); + +static int lcd_bwidth = NOT_SET; /* internal buffer width (usually 40) */ +module_param(lcd_bwidth, int, 0000); +MODULE_PARM_DESC(lcd_bwidth, "Internal LCD line width (40)"); + +static int lcd_hwidth = NOT_SET; /* hardware buffer width (usually 64) */ +module_param(lcd_hwidth, int, 0000); +MODULE_PARM_DESC(lcd_hwidth, "LCD line hardware address (64)"); + +static int lcd_charset = NOT_SET; +module_param(lcd_charset, int, 0000); +MODULE_PARM_DESC(lcd_charset, "LCD character set: 0=standard, 1=KS0074"); + +static int lcd_proto = NOT_SET; +module_param(lcd_proto, int, 0000); +MODULE_PARM_DESC(lcd_proto, + "LCD communication: 0=parallel (//), 1=serial, 2=TI LCD Interface"); + +/* + * These are the parallel port pins the LCD control signals are connected to. + * Set this to 0 if the signal is not used. Set it to its opposite value + * (negative) if the signal is negated. -MAXINT is used to indicate that the + * pin has not been explicitly specified. + * + * WARNING! no check will be performed about collisions with keypad ! + */ + +static int lcd_e_pin = PIN_NOT_SET; +module_param(lcd_e_pin, int, 0000); +MODULE_PARM_DESC(lcd_e_pin, + "# of the // port pin connected to LCD 'E' signal, with polarity (-17..17)"); + +static int lcd_rs_pin = PIN_NOT_SET; +module_param(lcd_rs_pin, int, 0000); +MODULE_PARM_DESC(lcd_rs_pin, + "# of the // port pin connected to LCD 'RS' signal, with polarity (-17..17)"); + +static int lcd_rw_pin = PIN_NOT_SET; +module_param(lcd_rw_pin, int, 0000); +MODULE_PARM_DESC(lcd_rw_pin, + "# of the // port pin connected to LCD 'RW' signal, with polarity (-17..17)"); + +static int lcd_cl_pin = PIN_NOT_SET; +module_param(lcd_cl_pin, int, 0000); +MODULE_PARM_DESC(lcd_cl_pin, + "# of the // port pin connected to serial LCD 'SCL' signal, with polarity (-17..17)"); + +static int lcd_da_pin = PIN_NOT_SET; +module_param(lcd_da_pin, int, 0000); +MODULE_PARM_DESC(lcd_da_pin, + "# of the // port pin connected to serial LCD 'SDA' signal, with polarity (-17..17)"); + +static int lcd_bl_pin = PIN_NOT_SET; +module_param(lcd_bl_pin, int, 0000); +MODULE_PARM_DESC(lcd_bl_pin, + "# of the // port pin connected to LCD backlight, with polarity (-17..17)"); + +/* Deprecated module parameters - consider not using them anymore */ + +static int lcd_enabled = NOT_SET; +module_param(lcd_enabled, int, 0000); +MODULE_PARM_DESC(lcd_enabled, "Deprecated option, use lcd_type instead"); + +static int keypad_enabled = NOT_SET; +module_param(keypad_enabled, int, 0000); +MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead"); + +static const unsigned char *lcd_char_conv; + +/* for some LCD drivers (ks0074) we need a charset conversion table. */ +static const unsigned char lcd_char_conv_ks0074[256] = { + /* 0|8 1|9 2|A 3|B 4|C 5|D 6|E 7|F */ + /* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + /* 0x08 */ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + /* 0x10 */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + /* 0x18 */ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + /* 0x20 */ 0x20, 0x21, 0x22, 0x23, 0xa2, 0x25, 0x26, 0x27, + /* 0x28 */ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + /* 0x30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + /* 0x38 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + /* 0x40 */ 0xa0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + /* 0x48 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + /* 0x50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + /* 0x58 */ 0x58, 0x59, 0x5a, 0xfa, 0xfb, 0xfc, 0x1d, 0xc4, + /* 0x60 */ 0x96, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + /* 0x68 */ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + /* 0x70 */ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + /* 0x78 */ 0x78, 0x79, 0x7a, 0xfd, 0xfe, 0xff, 0xce, 0x20, + /* 0x80 */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + /* 0x88 */ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + /* 0x90 */ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + /* 0x98 */ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + /* 0xA0 */ 0x20, 0x40, 0xb1, 0xa1, 0x24, 0xa3, 0xfe, 0x5f, + /* 0xA8 */ 0x22, 0xc8, 0x61, 0x14, 0x97, 0x2d, 0xad, 0x96, + /* 0xB0 */ 0x80, 0x8c, 0x82, 0x83, 0x27, 0x8f, 0x86, 0xdd, + /* 0xB8 */ 0x2c, 0x81, 0x6f, 0x15, 0x8b, 0x8a, 0x84, 0x60, + /* 0xC0 */ 0xe2, 0xe2, 0xe2, 0x5b, 0x5b, 0xae, 0xbc, 0xa9, + /* 0xC8 */ 0xc5, 0xbf, 0xc6, 0xf1, 0xe3, 0xe3, 0xe3, 0xe3, + /* 0xD0 */ 0x44, 0x5d, 0xa8, 0xe4, 0xec, 0xec, 0x5c, 0x78, + /* 0xD8 */ 0xab, 0xa6, 0xe5, 0x5e, 0x5e, 0xe6, 0xaa, 0xbe, + /* 0xE0 */ 0x7f, 0xe7, 0xaf, 0x7b, 0x7b, 0xaf, 0xbd, 0xc8, + /* 0xE8 */ 0xa4, 0xa5, 0xc7, 0xf6, 0xa7, 0xe8, 0x69, 0x69, + /* 0xF0 */ 0xed, 0x7d, 0xa8, 0xe4, 0xec, 0x5c, 0x5c, 0x25, + /* 0xF8 */ 0xac, 0xa6, 0xea, 0xef, 0x7e, 0xeb, 0xb2, 0x79, +}; + +static const char old_keypad_profile[][4][9] = { + {"S0", "Left\n", "Left\n", ""}, + {"S1", "Down\n", "Down\n", ""}, + {"S2", "Up\n", "Up\n", ""}, + {"S3", "Right\n", "Right\n", ""}, + {"S4", "Esc\n", "Esc\n", ""}, + {"S5", "Ret\n", "Ret\n", ""}, + {"", "", "", ""} +}; + +/* signals, press, repeat, release */ +static const char new_keypad_profile[][4][9] = { + {"S0", "Left\n", "Left\n", ""}, + {"S1", "Down\n", "Down\n", ""}, + {"S2", "Up\n", "Up\n", ""}, + {"S3", "Right\n", "Right\n", ""}, + {"S4s5", "", "Esc\n", "Esc\n"}, + {"s4S5", "", "Ret\n", "Ret\n"}, + {"S4S5", "Help\n", "", ""}, + /* add new signals above this line */ + {"", "", "", ""} +}; + +/* signals, press, repeat, release */ +static const char nexcom_keypad_profile[][4][9] = { + {"a-p-e-", "Down\n", "Down\n", ""}, + {"a-p-E-", "Ret\n", "Ret\n", ""}, + {"a-P-E-", "Esc\n", "Esc\n", ""}, + {"a-P-e-", "Up\n", "Up\n", ""}, + /* add new signals above this line */ + {"", "", "", ""} +}; + +static const char (*keypad_profile)[4][9] = old_keypad_profile; + +/* FIXME: this should be converted to a bit array containing signals states */ +static struct { + unsigned char e; /* parallel LCD E (data latch on falling edge) */ + unsigned char rs; /* parallel LCD RS (0 = cmd, 1 = data) */ + unsigned char rw; /* parallel LCD R/W (0 = W, 1 = R) */ + unsigned char bl; /* parallel LCD backlight (0 = off, 1 = on) */ + unsigned char cl; /* serial LCD clock (latch on rising edge) */ + unsigned char da; /* serial LCD data */ +} bits; + +static void init_scan_timer(void); + +/* sets data port bits according to current signals values */ +static int set_data_bits(void) +{ + int val, bit; + + val = r_dtr(pprt); + for (bit = 0; bit < LCD_BITS; bit++) + val &= lcd_bits[LCD_PORT_D][bit][BIT_MSK]; + + val |= lcd_bits[LCD_PORT_D][LCD_BIT_E][bits.e] + | lcd_bits[LCD_PORT_D][LCD_BIT_RS][bits.rs] + | lcd_bits[LCD_PORT_D][LCD_BIT_RW][bits.rw] + | lcd_bits[LCD_PORT_D][LCD_BIT_BL][bits.bl] + | lcd_bits[LCD_PORT_D][LCD_BIT_CL][bits.cl] + | lcd_bits[LCD_PORT_D][LCD_BIT_DA][bits.da]; + + w_dtr(pprt, val); + return val; +} + +/* sets ctrl port bits according to current signals values */ +static int set_ctrl_bits(void) +{ + int val, bit; + + val = r_ctr(pprt); + for (bit = 0; bit < LCD_BITS; bit++) + val &= lcd_bits[LCD_PORT_C][bit][BIT_MSK]; + + val |= lcd_bits[LCD_PORT_C][LCD_BIT_E][bits.e] + | lcd_bits[LCD_PORT_C][LCD_BIT_RS][bits.rs] + | lcd_bits[LCD_PORT_C][LCD_BIT_RW][bits.rw] + | lcd_bits[LCD_PORT_C][LCD_BIT_BL][bits.bl] + | lcd_bits[LCD_PORT_C][LCD_BIT_CL][bits.cl] + | lcd_bits[LCD_PORT_C][LCD_BIT_DA][bits.da]; + + w_ctr(pprt, val); + return val; +} + +/* sets ctrl & data port bits according to current signals values */ +static void panel_set_bits(void) +{ + set_data_bits(); + set_ctrl_bits(); +} + +/* + * Converts a parallel port pin (from -25 to 25) to data and control ports + * masks, and data and control port bits. The signal will be considered + * unconnected if it's on pin 0 or an invalid pin (<-25 or >25). + * + * Result will be used this way : + * out(dport, in(dport) & d_val[2] | d_val[signal_state]) + * out(cport, in(cport) & c_val[2] | c_val[signal_state]) + */ +static void pin_to_bits(int pin, unsigned char *d_val, unsigned char *c_val) +{ + int d_bit, c_bit, inv; + + d_val[0] = 0; + c_val[0] = 0; + d_val[1] = 0; + c_val[1] = 0; + d_val[2] = 0xFF; + c_val[2] = 0xFF; + + if (pin == 0) + return; + + inv = (pin < 0); + if (inv) + pin = -pin; + + d_bit = 0; + c_bit = 0; + + switch (pin) { + case PIN_STROBE: /* strobe, inverted */ + c_bit = PNL_PSTROBE; + inv = !inv; + break; + case PIN_D0...PIN_D7: /* D0 - D7 = 2 - 9 */ + d_bit = 1 << (pin - 2); + break; + case PIN_AUTOLF: /* autofeed, inverted */ + c_bit = PNL_PAUTOLF; + inv = !inv; + break; + case PIN_INITP: /* init, direct */ + c_bit = PNL_PINITP; + break; + case PIN_SELECP: /* select_in, inverted */ + c_bit = PNL_PSELECP; + inv = !inv; + break; + default: /* unknown pin, ignore */ + break; + } + + if (c_bit) { + c_val[2] &= ~c_bit; + c_val[!inv] = c_bit; + } else if (d_bit) { + d_val[2] &= ~d_bit; + d_val[!inv] = d_bit; + } +} + +/* sleeps that many milliseconds with a reschedule */ +static void long_sleep(int ms) +{ + if (in_interrupt()) + mdelay(ms); + else + schedule_timeout_interruptible(msecs_to_jiffies(ms)); +} + +/* + * send a serial byte to the LCD panel. The caller is responsible for locking + * if needed. + */ +static void lcd_send_serial(int byte) +{ + int bit; + + /* + * the data bit is set on D0, and the clock on STROBE. + * LCD reads D0 on STROBE's rising edge. + */ + for (bit = 0; bit < 8; bit++) { + bits.cl = BIT_CLR; /* CLK low */ + panel_set_bits(); + bits.da = byte & 1; + panel_set_bits(); + udelay(2); /* maintain the data during 2 us before CLK up */ + bits.cl = BIT_SET; /* CLK high */ + panel_set_bits(); + udelay(1); /* maintain the strobe during 1 us */ + byte >>= 1; + } +} + +/* turn the backlight on or off */ +static void lcd_backlight(int on) +{ + if (lcd.pins.bl == PIN_NONE) + return; + + /* The backlight is activated by setting the AUTOFEED line to +5V */ + spin_lock_irq(&pprt_lock); + bits.bl = on; + panel_set_bits(); + spin_unlock_irq(&pprt_lock); +} + +/* send a command to the LCD panel in serial mode */ +static void lcd_write_cmd_s(int cmd) +{ + spin_lock_irq(&pprt_lock); + lcd_send_serial(0x1F); /* R/W=W, RS=0 */ + lcd_send_serial(cmd & 0x0F); + lcd_send_serial((cmd >> 4) & 0x0F); + udelay(40); /* the shortest command takes at least 40 us */ + spin_unlock_irq(&pprt_lock); +} + +/* send data to the LCD panel in serial mode */ +static void lcd_write_data_s(int data) +{ + spin_lock_irq(&pprt_lock); + lcd_send_serial(0x5F); /* R/W=W, RS=1 */ + lcd_send_serial(data & 0x0F); + lcd_send_serial((data >> 4) & 0x0F); + udelay(40); /* the shortest data takes at least 40 us */ + spin_unlock_irq(&pprt_lock); +} + +/* send a command to the LCD panel in 8 bits parallel mode */ +static void lcd_write_cmd_p8(int cmd) +{ + spin_lock_irq(&pprt_lock); + /* present the data to the data port */ + w_dtr(pprt, cmd); + udelay(20); /* maintain the data during 20 us before the strobe */ + + bits.e = BIT_SET; + bits.rs = BIT_CLR; + bits.rw = BIT_CLR; + set_ctrl_bits(); + + udelay(40); /* maintain the strobe during 40 us */ + + bits.e = BIT_CLR; + set_ctrl_bits(); + + udelay(120); /* the shortest command takes at least 120 us */ + spin_unlock_irq(&pprt_lock); +} + +/* send data to the LCD panel in 8 bits parallel mode */ +static void lcd_write_data_p8(int data) +{ + spin_lock_irq(&pprt_lock); + /* present the data to the data port */ + w_dtr(pprt, data); + udelay(20); /* maintain the data during 20 us before the strobe */ + + bits.e = BIT_SET; + bits.rs = BIT_SET; + bits.rw = BIT_CLR; + set_ctrl_bits(); + + udelay(40); /* maintain the strobe during 40 us */ + + bits.e = BIT_CLR; + set_ctrl_bits(); + + udelay(45); /* the shortest data takes at least 45 us */ + spin_unlock_irq(&pprt_lock); +} + +/* send a command to the TI LCD panel */ +static void lcd_write_cmd_tilcd(int cmd) +{ + spin_lock_irq(&pprt_lock); + /* present the data to the control port */ + w_ctr(pprt, cmd); + udelay(60); + spin_unlock_irq(&pprt_lock); +} + +/* send data to the TI LCD panel */ +static void lcd_write_data_tilcd(int data) +{ + spin_lock_irq(&pprt_lock); + /* present the data to the data port */ + w_dtr(pprt, data); + udelay(60); + spin_unlock_irq(&pprt_lock); +} + +static void lcd_gotoxy(void) +{ + lcd_write_cmd(LCD_CMD_SET_DDRAM_ADDR + | (lcd.addr.y ? lcd.hwidth : 0) + /* + * we force the cursor to stay at the end of the + * line if it wants to go farther + */ + | ((lcd.addr.x < lcd.bwidth) ? lcd.addr.x & + (lcd.hwidth - 1) : lcd.bwidth - 1)); +} + +static void lcd_print(char c) +{ + if (lcd.addr.x < lcd.bwidth) { + if (lcd_char_conv) + c = lcd_char_conv[(unsigned char)c]; + lcd_write_data(c); + lcd.addr.x++; + } + /* prevents the cursor from wrapping onto the next line */ + if (lcd.addr.x == lcd.bwidth) + lcd_gotoxy(); +} + +/* fills the display with spaces and resets X/Y */ +static void lcd_clear_fast_s(void) +{ + int pos; + + lcd.addr.x = 0; + lcd.addr.y = 0; + lcd_gotoxy(); + + spin_lock_irq(&pprt_lock); + for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { + lcd_send_serial(0x5F); /* R/W=W, RS=1 */ + lcd_send_serial(' ' & 0x0F); + lcd_send_serial((' ' >> 4) & 0x0F); + /* the shortest data takes at least 40 us */ + udelay(40); + } + spin_unlock_irq(&pprt_lock); + + lcd.addr.x = 0; + lcd.addr.y = 0; + lcd_gotoxy(); +} + +/* fills the display with spaces and resets X/Y */ +static void lcd_clear_fast_p8(void) +{ + int pos; + + lcd.addr.x = 0; + lcd.addr.y = 0; + lcd_gotoxy(); + + spin_lock_irq(&pprt_lock); + for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { + /* present the data to the data port */ + w_dtr(pprt, ' '); + + /* maintain the data during 20 us before the strobe */ + udelay(20); + + bits.e = BIT_SET; + bits.rs = BIT_SET; + bits.rw = BIT_CLR; + set_ctrl_bits(); + + /* maintain the strobe during 40 us */ + udelay(40); + + bits.e = BIT_CLR; + set_ctrl_bits(); + + /* the shortest data takes at least 45 us */ + udelay(45); + } + spin_unlock_irq(&pprt_lock); + + lcd.addr.x = 0; + lcd.addr.y = 0; + lcd_gotoxy(); +} + +/* fills the display with spaces and resets X/Y */ +static void lcd_clear_fast_tilcd(void) +{ + int pos; + + lcd.addr.x = 0; + lcd.addr.y = 0; + lcd_gotoxy(); + + spin_lock_irq(&pprt_lock); + for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { + /* present the data to the data port */ + w_dtr(pprt, ' '); + udelay(60); + } + + spin_unlock_irq(&pprt_lock); + + lcd.addr.x = 0; + lcd.addr.y = 0; + lcd_gotoxy(); +} + +/* clears the display and resets X/Y */ +static void lcd_clear_display(void) +{ + lcd_write_cmd(LCD_CMD_DISPLAY_CLEAR); + lcd.addr.x = 0; + lcd.addr.y = 0; + /* we must wait a few milliseconds (15) */ + long_sleep(15); +} + +static void lcd_init_display(void) +{ + lcd.flags = ((lcd.height > 1) ? LCD_FLAG_N : 0) + | LCD_FLAG_D | LCD_FLAG_C | LCD_FLAG_B; + + long_sleep(20); /* wait 20 ms after power-up for the paranoid */ + + /* 8bits, 1 line, small fonts; let's do it 3 times */ + lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); + long_sleep(10); + lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); + long_sleep(10); + lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); + long_sleep(10); + + /* set font height and lines number */ + lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS + | ((lcd.flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) + | ((lcd.flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0) + ); + long_sleep(10); + + /* display off, cursor off, blink off */ + lcd_write_cmd(LCD_CMD_DISPLAY_CTRL); + long_sleep(10); + + lcd_write_cmd(LCD_CMD_DISPLAY_CTRL /* set display mode */ + | ((lcd.flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) + | ((lcd.flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) + | ((lcd.flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0) + ); + + lcd_backlight((lcd.flags & LCD_FLAG_L) ? 1 : 0); + + long_sleep(10); + + /* entry mode set : increment, cursor shifting */ + lcd_write_cmd(LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC); + + lcd_clear_display(); +} + +/* + * These are the file operation function for user access to /dev/lcd + * This function can also be called from inside the kernel, by + * setting file and ppos to NULL. + * + */ + +static inline int handle_lcd_special_code(void) +{ + /* LCD special codes */ + + int processed = 0; + + char *esc = lcd.esc_seq.buf + 2; + int oldflags = lcd.flags; + + /* check for display mode flags */ + switch (*esc) { + case 'D': /* Display ON */ + lcd.flags |= LCD_FLAG_D; + processed = 1; + break; + case 'd': /* Display OFF */ + lcd.flags &= ~LCD_FLAG_D; + processed = 1; + break; + case 'C': /* Cursor ON */ + lcd.flags |= LCD_FLAG_C; + processed = 1; + break; + case 'c': /* Cursor OFF */ + lcd.flags &= ~LCD_FLAG_C; + processed = 1; + break; + case 'B': /* Blink ON */ + lcd.flags |= LCD_FLAG_B; + processed = 1; + break; + case 'b': /* Blink OFF */ + lcd.flags &= ~LCD_FLAG_B; + processed = 1; + break; + case '+': /* Back light ON */ + lcd.flags |= LCD_FLAG_L; + processed = 1; + break; + case '-': /* Back light OFF */ + lcd.flags &= ~LCD_FLAG_L; + processed = 1; + break; + case '*': + /* flash back light using the keypad timer */ + if (scan_timer.function) { + if (lcd.light_tempo == 0 && + ((lcd.flags & LCD_FLAG_L) == 0)) + lcd_backlight(1); + lcd.light_tempo = FLASH_LIGHT_TEMPO; + } + processed = 1; + break; + case 'f': /* Small Font */ + lcd.flags &= ~LCD_FLAG_F; + processed = 1; + break; + case 'F': /* Large Font */ + lcd.flags |= LCD_FLAG_F; + processed = 1; + break; + case 'n': /* One Line */ + lcd.flags &= ~LCD_FLAG_N; + processed = 1; + break; + case 'N': /* Two Lines */ + lcd.flags |= LCD_FLAG_N; + break; + case 'l': /* Shift Cursor Left */ + if (lcd.addr.x > 0) { + /* back one char if not at end of line */ + if (lcd.addr.x < lcd.bwidth) + lcd_write_cmd(LCD_CMD_SHIFT); + lcd.addr.x--; + } + processed = 1; + break; + case 'r': /* shift cursor right */ + if (lcd.addr.x < lcd.width) { + /* allow the cursor to pass the end of the line */ + if (lcd.addr.x < (lcd.bwidth - 1)) + lcd_write_cmd(LCD_CMD_SHIFT | + LCD_CMD_SHIFT_RIGHT); + lcd.addr.x++; + } + processed = 1; + break; + case 'L': /* shift display left */ + lcd_write_cmd(LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT); + processed = 1; + break; + case 'R': /* shift display right */ + lcd_write_cmd(LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT | + LCD_CMD_SHIFT_RIGHT); + processed = 1; + break; + case 'k': { /* kill end of line */ + int x; + + for (x = lcd.addr.x; x < lcd.bwidth; x++) + lcd_write_data(' '); + + /* restore cursor position */ + lcd_gotoxy(); + processed = 1; + break; + } + case 'I': /* reinitialize display */ + lcd_init_display(); + processed = 1; + break; + case 'G': { + /* Generator : LGcxxxxx...xx; must have between '0' + * and '7', representing the numerical ASCII code of the + * redefined character, and a sequence of 16 + * hex digits representing 8 bytes for each character. + * Most LCDs will only use 5 lower bits of the 7 first + * bytes. + */ + + unsigned char cgbytes[8]; + unsigned char cgaddr; + int cgoffset; + int shift; + char value; + int addr; + + if (!strchr(esc, ';')) + break; + + esc++; + + cgaddr = *(esc++) - '0'; + if (cgaddr > 7) { + processed = 1; + break; + } + + cgoffset = 0; + shift = 0; + value = 0; + while (*esc && cgoffset < 8) { + shift ^= 4; + if (*esc >= '0' && *esc <= '9') { + value |= (*esc - '0') << shift; + } else if (*esc >= 'A' && *esc <= 'Z') { + value |= (*esc - 'A' + 10) << shift; + } else if (*esc >= 'a' && *esc <= 'z') { + value |= (*esc - 'a' + 10) << shift; + } else { + esc++; + continue; + } + + if (shift == 0) { + cgbytes[cgoffset++] = value; + value = 0; + } + + esc++; + } + + lcd_write_cmd(LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8)); + for (addr = 0; addr < cgoffset; addr++) + lcd_write_data(cgbytes[addr]); + + /* ensures that we stop writing to CGRAM */ + lcd_gotoxy(); + processed = 1; + break; + } + case 'x': /* gotoxy : LxXXX[yYYY]; */ + case 'y': /* gotoxy : LyYYY[xXXX]; */ + if (!strchr(esc, ';')) + break; + + while (*esc) { + if (*esc == 'x') { + esc++; + if (kstrtoul(esc, 10, &lcd.addr.x) < 0) + break; + } else if (*esc == 'y') { + esc++; + if (kstrtoul(esc, 10, &lcd.addr.y) < 0) + break; + } else { + break; + } + } + + lcd_gotoxy(); + processed = 1; + break; + } + + /* TODO: This indent party here got ugly, clean it! */ + /* Check whether one flag was changed */ + if (oldflags != lcd.flags) { + /* check whether one of B,C,D flags were changed */ + if ((oldflags ^ lcd.flags) & + (LCD_FLAG_B | LCD_FLAG_C | LCD_FLAG_D)) + /* set display mode */ + lcd_write_cmd(LCD_CMD_DISPLAY_CTRL + | ((lcd.flags & LCD_FLAG_D) + ? LCD_CMD_DISPLAY_ON : 0) + | ((lcd.flags & LCD_FLAG_C) + ? LCD_CMD_CURSOR_ON : 0) + | ((lcd.flags & LCD_FLAG_B) + ? LCD_CMD_BLINK_ON : 0)); + /* check whether one of F,N flags was changed */ + else if ((oldflags ^ lcd.flags) & (LCD_FLAG_F | LCD_FLAG_N)) + lcd_write_cmd(LCD_CMD_FUNCTION_SET + | LCD_CMD_DATA_LEN_8BITS + | ((lcd.flags & LCD_FLAG_F) + ? LCD_CMD_TWO_LINES : 0) + | ((lcd.flags & LCD_FLAG_N) + ? LCD_CMD_FONT_5X10_DOTS + : 0)); + /* check whether L flag was changed */ + else if ((oldflags ^ lcd.flags) & (LCD_FLAG_L)) { + if (lcd.flags & (LCD_FLAG_L)) + lcd_backlight(1); + else if (lcd.light_tempo == 0) + /* + * switch off the light only when the tempo + * lighting is gone + */ + lcd_backlight(0); + } + } + + return processed; +} + +static void lcd_write_char(char c) +{ + /* first, we'll test if we're in escape mode */ + if ((c != '\n') && lcd.esc_seq.len >= 0) { + /* yes, let's add this char to the buffer */ + lcd.esc_seq.buf[lcd.esc_seq.len++] = c; + lcd.esc_seq.buf[lcd.esc_seq.len] = 0; + } else { + /* aborts any previous escape sequence */ + lcd.esc_seq.len = -1; + + switch (c) { + case LCD_ESCAPE_CHAR: + /* start of an escape sequence */ + lcd.esc_seq.len = 0; + lcd.esc_seq.buf[lcd.esc_seq.len] = 0; + break; + case '\b': + /* go back one char and clear it */ + if (lcd.addr.x > 0) { + /* + * check if we're not at the + * end of the line + */ + if (lcd.addr.x < lcd.bwidth) + /* back one char */ + lcd_write_cmd(LCD_CMD_SHIFT); + lcd.addr.x--; + } + /* replace with a space */ + lcd_write_data(' '); + /* back one char again */ + lcd_write_cmd(LCD_CMD_SHIFT); + break; + case '\014': + /* quickly clear the display */ + lcd_clear_fast(); + break; + case '\n': + /* + * flush the remainder of the current line and + * go to the beginning of the next line + */ + for (; lcd.addr.x < lcd.bwidth; lcd.addr.x++) + lcd_write_data(' '); + lcd.addr.x = 0; + lcd.addr.y = (lcd.addr.y + 1) % lcd.height; + lcd_gotoxy(); + break; + case '\r': + /* go to the beginning of the same line */ + lcd.addr.x = 0; + lcd_gotoxy(); + break; + case '\t': + /* print a space instead of the tab */ + lcd_print(' '); + break; + default: + /* simply print this char */ + lcd_print(c); + break; + } + } + + /* + * now we'll see if we're in an escape mode and if the current + * escape sequence can be understood. + */ + if (lcd.esc_seq.len >= 2) { + int processed = 0; + + if (!strcmp(lcd.esc_seq.buf, "[2J")) { + /* clear the display */ + lcd_clear_fast(); + processed = 1; + } else if (!strcmp(lcd.esc_seq.buf, "[H")) { + /* cursor to home */ + lcd.addr.x = 0; + lcd.addr.y = 0; + lcd_gotoxy(); + processed = 1; + } + /* codes starting with ^[[L */ + else if ((lcd.esc_seq.len >= 3) && + (lcd.esc_seq.buf[0] == '[') && + (lcd.esc_seq.buf[1] == 'L')) { + processed = handle_lcd_special_code(); + } + + /* LCD special escape codes */ + /* + * flush the escape sequence if it's been processed + * or if it is getting too long. + */ + if (processed || (lcd.esc_seq.len >= LCD_ESCAPE_LEN)) + lcd.esc_seq.len = -1; + } /* escape codes */ +} + +static ssize_t lcd_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos) +{ + const char __user *tmp = buf; + char c; + + for (; count-- > 0; (*ppos)++, tmp++) { + if (!in_interrupt() && (((count + 1) & 0x1f) == 0)) + /* + * let's be a little nice with other processes + * that need some CPU + */ + schedule(); + + if (get_user(c, tmp)) + return -EFAULT; + + lcd_write_char(c); + } + + return tmp - buf; +} + +static int lcd_open(struct inode *inode, struct file *file) +{ + if (!atomic_dec_and_test(&lcd_available)) + return -EBUSY; /* open only once at a time */ + + if (file->f_mode & FMODE_READ) /* device is write-only */ + return -EPERM; + + if (lcd.must_clear) { + lcd_clear_display(); + lcd.must_clear = false; + } + return nonseekable_open(inode, file); +} + +static int lcd_release(struct inode *inode, struct file *file) +{ + atomic_inc(&lcd_available); + return 0; +} + +static const struct file_operations lcd_fops = { + .write = lcd_write, + .open = lcd_open, + .release = lcd_release, + .llseek = no_llseek, +}; + +static struct miscdevice lcd_dev = { + .minor = LCD_MINOR, + .name = "lcd", + .fops = &lcd_fops, +}; + +/* public function usable from the kernel for any purpose */ +static void panel_lcd_print(const char *s) +{ + const char *tmp = s; + int count = strlen(s); + + if (lcd.enabled && lcd.initialized) { + for (; count-- > 0; tmp++) { + if (!in_interrupt() && (((count + 1) & 0x1f) == 0)) + /* + * let's be a little nice with other processes + * that need some CPU + */ + schedule(); + + lcd_write_char(*tmp); + } + } +} + +/* initialize the LCD driver */ +static void lcd_init(void) +{ + switch (selected_lcd_type) { + case LCD_TYPE_OLD: + /* parallel mode, 8 bits */ + lcd.proto = LCD_PROTO_PARALLEL; + lcd.charset = LCD_CHARSET_NORMAL; + lcd.pins.e = PIN_STROBE; + lcd.pins.rs = PIN_AUTOLF; + + lcd.width = 40; + lcd.bwidth = 40; + lcd.hwidth = 64; + lcd.height = 2; + break; + case LCD_TYPE_KS0074: + /* serial mode, ks0074 */ + lcd.proto = LCD_PROTO_SERIAL; + lcd.charset = LCD_CHARSET_KS0074; + lcd.pins.bl = PIN_AUTOLF; + lcd.pins.cl = PIN_STROBE; + lcd.pins.da = PIN_D0; + + lcd.width = 16; + lcd.bwidth = 40; + lcd.hwidth = 16; + lcd.height = 2; + break; + case LCD_TYPE_NEXCOM: + /* parallel mode, 8 bits, generic */ + lcd.proto = LCD_PROTO_PARALLEL; + lcd.charset = LCD_CHARSET_NORMAL; + lcd.pins.e = PIN_AUTOLF; + lcd.pins.rs = PIN_SELECP; + lcd.pins.rw = PIN_INITP; + + lcd.width = 16; + lcd.bwidth = 40; + lcd.hwidth = 64; + lcd.height = 2; + break; + case LCD_TYPE_CUSTOM: + /* customer-defined */ + lcd.proto = DEFAULT_LCD_PROTO; + lcd.charset = DEFAULT_LCD_CHARSET; + /* default geometry will be set later */ + break; + case LCD_TYPE_HANTRONIX: + /* parallel mode, 8 bits, hantronix-like */ + default: + lcd.proto = LCD_PROTO_PARALLEL; + lcd.charset = LCD_CHARSET_NORMAL; + lcd.pins.e = PIN_STROBE; + lcd.pins.rs = PIN_SELECP; + + lcd.width = 16; + lcd.bwidth = 40; + lcd.hwidth = 64; + lcd.height = 2; + break; + } + + /* Overwrite with module params set on loading */ + if (lcd_height != NOT_SET) + lcd.height = lcd_height; + if (lcd_width != NOT_SET) + lcd.width = lcd_width; + if (lcd_bwidth != NOT_SET) + lcd.bwidth = lcd_bwidth; + if (lcd_hwidth != NOT_SET) + lcd.hwidth = lcd_hwidth; + if (lcd_charset != NOT_SET) + lcd.charset = lcd_charset; + if (lcd_proto != NOT_SET) + lcd.proto = lcd_proto; + if (lcd_e_pin != PIN_NOT_SET) + lcd.pins.e = lcd_e_pin; + if (lcd_rs_pin != PIN_NOT_SET) + lcd.pins.rs = lcd_rs_pin; + if (lcd_rw_pin != PIN_NOT_SET) + lcd.pins.rw = lcd_rw_pin; + if (lcd_cl_pin != PIN_NOT_SET) + lcd.pins.cl = lcd_cl_pin; + if (lcd_da_pin != PIN_NOT_SET) + lcd.pins.da = lcd_da_pin; + if (lcd_bl_pin != PIN_NOT_SET) + lcd.pins.bl = lcd_bl_pin; + + /* this is used to catch wrong and default values */ + if (lcd.width <= 0) + lcd.width = DEFAULT_LCD_WIDTH; + if (lcd.bwidth <= 0) + lcd.bwidth = DEFAULT_LCD_BWIDTH; + if (lcd.hwidth <= 0) + lcd.hwidth = DEFAULT_LCD_HWIDTH; + if (lcd.height <= 0) + lcd.height = DEFAULT_LCD_HEIGHT; + + if (lcd.proto == LCD_PROTO_SERIAL) { /* SERIAL */ + lcd_write_cmd = lcd_write_cmd_s; + lcd_write_data = lcd_write_data_s; + lcd_clear_fast = lcd_clear_fast_s; + + if (lcd.pins.cl == PIN_NOT_SET) + lcd.pins.cl = DEFAULT_LCD_PIN_SCL; + if (lcd.pins.da == PIN_NOT_SET) + lcd.pins.da = DEFAULT_LCD_PIN_SDA; + + } else if (lcd.proto == LCD_PROTO_PARALLEL) { /* PARALLEL */ + lcd_write_cmd = lcd_write_cmd_p8; + lcd_write_data = lcd_write_data_p8; + lcd_clear_fast = lcd_clear_fast_p8; + + if (lcd.pins.e == PIN_NOT_SET) + lcd.pins.e = DEFAULT_LCD_PIN_E; + if (lcd.pins.rs == PIN_NOT_SET) + lcd.pins.rs = DEFAULT_LCD_PIN_RS; + if (lcd.pins.rw == PIN_NOT_SET) + lcd.pins.rw = DEFAULT_LCD_PIN_RW; + } else { + lcd_write_cmd = lcd_write_cmd_tilcd; + lcd_write_data = lcd_write_data_tilcd; + lcd_clear_fast = lcd_clear_fast_tilcd; + } + + if (lcd.pins.bl == PIN_NOT_SET) + lcd.pins.bl = DEFAULT_LCD_PIN_BL; + + if (lcd.pins.e == PIN_NOT_SET) + lcd.pins.e = PIN_NONE; + if (lcd.pins.rs == PIN_NOT_SET) + lcd.pins.rs = PIN_NONE; + if (lcd.pins.rw == PIN_NOT_SET) + lcd.pins.rw = PIN_NONE; + if (lcd.pins.bl == PIN_NOT_SET) + lcd.pins.bl = PIN_NONE; + if (lcd.pins.cl == PIN_NOT_SET) + lcd.pins.cl = PIN_NONE; + if (lcd.pins.da == PIN_NOT_SET) + lcd.pins.da = PIN_NONE; + + if (lcd.charset == NOT_SET) + lcd.charset = DEFAULT_LCD_CHARSET; + + if (lcd.charset == LCD_CHARSET_KS0074) + lcd_char_conv = lcd_char_conv_ks0074; + else + lcd_char_conv = NULL; + + if (lcd.pins.bl != PIN_NONE) + init_scan_timer(); + + pin_to_bits(lcd.pins.e, lcd_bits[LCD_PORT_D][LCD_BIT_E], + lcd_bits[LCD_PORT_C][LCD_BIT_E]); + pin_to_bits(lcd.pins.rs, lcd_bits[LCD_PORT_D][LCD_BIT_RS], + lcd_bits[LCD_PORT_C][LCD_BIT_RS]); + pin_to_bits(lcd.pins.rw, lcd_bits[LCD_PORT_D][LCD_BIT_RW], + lcd_bits[LCD_PORT_C][LCD_BIT_RW]); + pin_to_bits(lcd.pins.bl, lcd_bits[LCD_PORT_D][LCD_BIT_BL], + lcd_bits[LCD_PORT_C][LCD_BIT_BL]); + pin_to_bits(lcd.pins.cl, lcd_bits[LCD_PORT_D][LCD_BIT_CL], + lcd_bits[LCD_PORT_C][LCD_BIT_CL]); + pin_to_bits(lcd.pins.da, lcd_bits[LCD_PORT_D][LCD_BIT_DA], + lcd_bits[LCD_PORT_C][LCD_BIT_DA]); + + /* + * before this line, we must NOT send anything to the display. + * Since lcd_init_display() needs to write data, we have to + * enable mark the LCD initialized just before. + */ + lcd.initialized = true; + lcd_init_display(); + + /* display a short message */ +#ifdef CONFIG_PANEL_CHANGE_MESSAGE +#ifdef CONFIG_PANEL_BOOT_MESSAGE + panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*" CONFIG_PANEL_BOOT_MESSAGE); +#endif +#else + panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*Linux-" UTS_RELEASE "\nPanel-" + PANEL_VERSION); +#endif + lcd.addr.x = 0; + lcd.addr.y = 0; + /* clear the display on the next device opening */ + lcd.must_clear = true; + lcd_gotoxy(); +} + +/* + * These are the file operation function for user access to /dev/keypad + */ + +static ssize_t keypad_read(struct file *file, + char __user *buf, size_t count, loff_t *ppos) +{ + unsigned i = *ppos; + char __user *tmp = buf; + + if (keypad_buflen == 0) { + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + + if (wait_event_interruptible(keypad_read_wait, + keypad_buflen != 0)) + return -EINTR; + } + + for (; count-- > 0 && (keypad_buflen > 0); + ++i, ++tmp, --keypad_buflen) { + put_user(keypad_buffer[keypad_start], tmp); + keypad_start = (keypad_start + 1) % KEYPAD_BUFFER; + } + *ppos = i; + + return tmp - buf; +} + +static int keypad_open(struct inode *inode, struct file *file) +{ + if (!atomic_dec_and_test(&keypad_available)) + return -EBUSY; /* open only once at a time */ + + if (file->f_mode & FMODE_WRITE) /* device is read-only */ + return -EPERM; + + keypad_buflen = 0; /* flush the buffer on opening */ + return 0; +} + +static int keypad_release(struct inode *inode, struct file *file) +{ + atomic_inc(&keypad_available); + return 0; +} + +static const struct file_operations keypad_fops = { + .read = keypad_read, /* read */ + .open = keypad_open, /* open */ + .release = keypad_release, /* close */ + .llseek = default_llseek, +}; + +static struct miscdevice keypad_dev = { + .minor = KEYPAD_MINOR, + .name = "keypad", + .fops = &keypad_fops, +}; + +static void keypad_send_key(const char *string, int max_len) +{ + /* send the key to the device only if a process is attached to it. */ + if (!atomic_read(&keypad_available)) { + while (max_len-- && keypad_buflen < KEYPAD_BUFFER && *string) { + keypad_buffer[(keypad_start + keypad_buflen++) % + KEYPAD_BUFFER] = *string++; + } + wake_up_interruptible(&keypad_read_wait); + } +} + +/* this function scans all the bits involving at least one logical signal, + * and puts the results in the bitfield "phys_read" (one bit per established + * contact), and sets "phys_read_prev" to "phys_read". + * + * Note: to debounce input signals, we will only consider as switched a signal + * which is stable across 2 measures. Signals which are different between two + * reads will be kept as they previously were in their logical form (phys_prev). + * A signal which has just switched will have a 1 in + * (phys_read ^ phys_read_prev). + */ +static void phys_scan_contacts(void) +{ + int bit, bitval; + char oldval; + char bitmask; + char gndmask; + + phys_prev = phys_curr; + phys_read_prev = phys_read; + phys_read = 0; /* flush all signals */ + + /* keep track of old value, with all outputs disabled */ + oldval = r_dtr(pprt) | scan_mask_o; + /* activate all keyboard outputs (active low) */ + w_dtr(pprt, oldval & ~scan_mask_o); + + /* will have a 1 for each bit set to gnd */ + bitmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i; + /* disable all matrix signals */ + w_dtr(pprt, oldval); + + /* now that all outputs are cleared, the only active input bits are + * directly connected to the ground + */ + + /* 1 for each grounded input */ + gndmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i; + + /* grounded inputs are signals 40-44 */ + phys_read |= (__u64)gndmask << 40; + + if (bitmask != gndmask) { + /* + * since clearing the outputs changed some inputs, we know + * that some input signals are currently tied to some outputs. + * So we'll scan them. + */ + for (bit = 0; bit < 8; bit++) { + bitval = BIT(bit); + + if (!(scan_mask_o & bitval)) /* skip unused bits */ + continue; + + w_dtr(pprt, oldval & ~bitval); /* enable this output */ + bitmask = PNL_PINPUT(r_str(pprt)) & ~gndmask; + phys_read |= (__u64)bitmask << (5 * bit); + } + w_dtr(pprt, oldval); /* disable all outputs */ + } + /* + * this is easy: use old bits when they are flapping, + * use new ones when stable + */ + phys_curr = (phys_prev & (phys_read ^ phys_read_prev)) | + (phys_read & ~(phys_read ^ phys_read_prev)); +} + +static inline int input_state_high(struct logical_input *input) +{ +#if 0 + /* FIXME: + * this is an invalid test. It tries to catch + * transitions from single-key to multiple-key, but + * doesn't take into account the contacts polarity. + * The only solution to the problem is to parse keys + * from the most complex to the simplest combinations, + * and mark them as 'caught' once a combination + * matches, then unmatch it for all other ones. + */ + + /* try to catch dangerous transitions cases : + * someone adds a bit, so this signal was a false + * positive resulting from a transition. We should + * invalidate the signal immediately and not call the + * release function. + * eg: 0 -(press A)-> A -(press B)-> AB : don't match A's release. + */ + if (((phys_prev & input->mask) == input->value) && + ((phys_curr & input->mask) > input->value)) { + input->state = INPUT_ST_LOW; /* invalidate */ + return 1; + } +#endif + + if ((phys_curr & input->mask) == input->value) { + if ((input->type == INPUT_TYPE_STD) && + (input->high_timer == 0)) { + input->high_timer++; + if (input->u.std.press_fct) + input->u.std.press_fct(input->u.std.press_data); + } else if (input->type == INPUT_TYPE_KBD) { + /* will turn on the light */ + keypressed = 1; + + if (input->high_timer == 0) { + char *press_str = input->u.kbd.press_str; + + if (press_str[0]) { + int s = sizeof(input->u.kbd.press_str); + + keypad_send_key(press_str, s); + } + } + + if (input->u.kbd.repeat_str[0]) { + char *repeat_str = input->u.kbd.repeat_str; + + if (input->high_timer >= KEYPAD_REP_START) { + int s = sizeof(input->u.kbd.repeat_str); + + input->high_timer -= KEYPAD_REP_DELAY; + keypad_send_key(repeat_str, s); + } + /* we will need to come back here soon */ + inputs_stable = 0; + } + + if (input->high_timer < 255) + input->high_timer++; + } + return 1; + } + + /* else signal falling down. Let's fall through. */ + input->state = INPUT_ST_FALLING; + input->fall_timer = 0; + + return 0; +} + +static inline void input_state_falling(struct logical_input *input) +{ +#if 0 + /* FIXME !!! same comment as in input_state_high */ + if (((phys_prev & input->mask) == input->value) && + ((phys_curr & input->mask) > input->value)) { + input->state = INPUT_ST_LOW; /* invalidate */ + return; + } +#endif + + if ((phys_curr & input->mask) == input->value) { + if (input->type == INPUT_TYPE_KBD) { + /* will turn on the light */ + keypressed = 1; + + if (input->u.kbd.repeat_str[0]) { + char *repeat_str = input->u.kbd.repeat_str; + + if (input->high_timer >= KEYPAD_REP_START) { + int s = sizeof(input->u.kbd.repeat_str); + + input->high_timer -= KEYPAD_REP_DELAY; + keypad_send_key(repeat_str, s); + } + /* we will need to come back here soon */ + inputs_stable = 0; + } + + if (input->high_timer < 255) + input->high_timer++; + } + input->state = INPUT_ST_HIGH; + } else if (input->fall_timer >= input->fall_time) { + /* call release event */ + if (input->type == INPUT_TYPE_STD) { + void (*release_fct)(int) = input->u.std.release_fct; + + if (release_fct) + release_fct(input->u.std.release_data); + } else if (input->type == INPUT_TYPE_KBD) { + char *release_str = input->u.kbd.release_str; + + if (release_str[0]) { + int s = sizeof(input->u.kbd.release_str); + + keypad_send_key(release_str, s); + } + } + + input->state = INPUT_ST_LOW; + } else { + input->fall_timer++; + inputs_stable = 0; + } +} + +static void panel_process_inputs(void) +{ + struct list_head *item; + struct logical_input *input; + + keypressed = 0; + inputs_stable = 1; + list_for_each(item, &logical_inputs) { + input = list_entry(item, struct logical_input, list); + + switch (input->state) { + case INPUT_ST_LOW: + if ((phys_curr & input->mask) != input->value) + break; + /* if all needed ones were already set previously, + * this means that this logical signal has been + * activated by the releasing of another combined + * signal, so we don't want to match. + * eg: AB -(release B)-> A -(release A)-> 0 : + * don't match A. + */ + if ((phys_prev & input->mask) == input->value) + break; + input->rise_timer = 0; + input->state = INPUT_ST_RISING; + /* no break here, fall through */ + case INPUT_ST_RISING: + if ((phys_curr & input->mask) != input->value) { + input->state = INPUT_ST_LOW; + break; + } + if (input->rise_timer < input->rise_time) { + inputs_stable = 0; + input->rise_timer++; + break; + } + input->high_timer = 0; + input->state = INPUT_ST_HIGH; + /* no break here, fall through */ + case INPUT_ST_HIGH: + if (input_state_high(input)) + break; + /* no break here, fall through */ + case INPUT_ST_FALLING: + input_state_falling(input); + } + } +} + +static void panel_scan_timer(void) +{ + if (keypad.enabled && keypad_initialized) { + if (spin_trylock_irq(&pprt_lock)) { + phys_scan_contacts(); + + /* no need for the parport anymore */ + spin_unlock_irq(&pprt_lock); + } + + if (!inputs_stable || phys_curr != phys_prev) + panel_process_inputs(); + } + + if (lcd.enabled && lcd.initialized) { + if (keypressed) { + if (lcd.light_tempo == 0 && + ((lcd.flags & LCD_FLAG_L) == 0)) + lcd_backlight(1); + lcd.light_tempo = FLASH_LIGHT_TEMPO; + } else if (lcd.light_tempo > 0) { + lcd.light_tempo--; + if (lcd.light_tempo == 0 && + ((lcd.flags & LCD_FLAG_L) == 0)) + lcd_backlight(0); + } + } + + mod_timer(&scan_timer, jiffies + INPUT_POLL_TIME); +} + +static void init_scan_timer(void) +{ + if (scan_timer.function) + return; /* already started */ + + setup_timer(&scan_timer, (void *)&panel_scan_timer, 0); + scan_timer.expires = jiffies + INPUT_POLL_TIME; + add_timer(&scan_timer); +} + +/* converts a name of the form "({BbAaPpSsEe}{01234567-})*" to a series of bits. + * if or are non-null, they will be or'ed with the bits + * corresponding to out and in bits respectively. + * returns 1 if ok, 0 if error (in which case, nothing is written). + */ +static u8 input_name2mask(const char *name, __u64 *mask, __u64 *value, + u8 *imask, u8 *omask) +{ + const char sigtab[] = "EeSsPpAaBb"; + u8 im, om; + __u64 m, v; + + om = 0; + im = 0; + m = 0ULL; + v = 0ULL; + while (*name) { + int in, out, bit, neg; + const char *idx; + + idx = strchr(sigtab, *name); + if (!idx) + return 0; /* input name not found */ + + in = idx - sigtab; + neg = (in & 1); /* odd (lower) names are negated */ + in >>= 1; + im |= BIT(in); + + name++; + if (*name >= '0' && *name <= '7') { + out = *name - '0'; + om |= BIT(out); + } else if (*name == '-') { + out = 8; + } else { + return 0; /* unknown bit name */ + } + + bit = (out * 5) + in; + + m |= 1ULL << bit; + if (!neg) + v |= 1ULL << bit; + name++; + } + *mask = m; + *value = v; + if (imask) + *imask |= im; + if (omask) + *omask |= om; + return 1; +} + +/* tries to bind a key to the signal name . The key will send the + * strings , , for these respective events. + * Returns the pointer to the new key if ok, NULL if the key could not be bound. + */ +static struct logical_input *panel_bind_key(const char *name, const char *press, + const char *repeat, + const char *release) +{ + struct logical_input *key; + + key = kzalloc(sizeof(*key), GFP_KERNEL); + if (!key) + return NULL; + + if (!input_name2mask(name, &key->mask, &key->value, &scan_mask_i, + &scan_mask_o)) { + kfree(key); + return NULL; + } + + key->type = INPUT_TYPE_KBD; + key->state = INPUT_ST_LOW; + key->rise_time = 1; + key->fall_time = 1; + + strncpy(key->u.kbd.press_str, press, sizeof(key->u.kbd.press_str)); + strncpy(key->u.kbd.repeat_str, repeat, sizeof(key->u.kbd.repeat_str)); + strncpy(key->u.kbd.release_str, release, + sizeof(key->u.kbd.release_str)); + list_add(&key->list, &logical_inputs); + return key; +} + +#if 0 +/* tries to bind a callback function to the signal name . The function + * will be called with the arg when the signal is + * activated, and so on for / + * Returns the pointer to the new signal if ok, NULL if the signal could not + * be bound. + */ +static struct logical_input *panel_bind_callback(char *name, + void (*press_fct)(int), + int press_data, + void (*release_fct)(int), + int release_data) +{ + struct logical_input *callback; + + callback = kmalloc(sizeof(*callback), GFP_KERNEL); + if (!callback) + return NULL; + + memset(callback, 0, sizeof(struct logical_input)); + if (!input_name2mask(name, &callback->mask, &callback->value, + &scan_mask_i, &scan_mask_o)) + return NULL; + + callback->type = INPUT_TYPE_STD; + callback->state = INPUT_ST_LOW; + callback->rise_time = 1; + callback->fall_time = 1; + callback->u.std.press_fct = press_fct; + callback->u.std.press_data = press_data; + callback->u.std.release_fct = release_fct; + callback->u.std.release_data = release_data; + list_add(&callback->list, &logical_inputs); + return callback; +} +#endif + +static void keypad_init(void) +{ + int keynum; + + init_waitqueue_head(&keypad_read_wait); + keypad_buflen = 0; /* flushes any eventual noisy keystroke */ + + /* Let's create all known keys */ + + for (keynum = 0; keypad_profile[keynum][0][0]; keynum++) { + panel_bind_key(keypad_profile[keynum][0], + keypad_profile[keynum][1], + keypad_profile[keynum][2], + keypad_profile[keynum][3]); + } + + init_scan_timer(); + keypad_initialized = 1; +} + +/**************************************************/ +/* device initialization */ +/**************************************************/ + +static int panel_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (lcd.enabled && lcd.initialized) { + switch (code) { + case SYS_DOWN: + panel_lcd_print + ("\x0cReloading\nSystem...\x1b[Lc\x1b[Lb\x1b[L+"); + break; + case SYS_HALT: + panel_lcd_print + ("\x0cSystem Halted.\x1b[Lc\x1b[Lb\x1b[L+"); + break; + case SYS_POWER_OFF: + panel_lcd_print("\x0cPower off.\x1b[Lc\x1b[Lb\x1b[L+"); + break; + default: + break; + } + } + return NOTIFY_DONE; +} + +static struct notifier_block panel_notifier = { + panel_notify_sys, + NULL, + 0 +}; + +static void panel_attach(struct parport *port) +{ + struct pardev_cb panel_cb; + + if (port->number != parport) + return; + + if (pprt) { + pr_err("%s: port->number=%d parport=%d, already registered!\n", + __func__, port->number, parport); + return; + } + + memset(&panel_cb, 0, sizeof(panel_cb)); + panel_cb.private = &pprt; + /* panel_cb.flags = 0 should be PARPORT_DEV_EXCL? */ + + pprt = parport_register_dev_model(port, "panel", &panel_cb, 0); + if (!pprt) { + pr_err("%s: port->number=%d parport=%d, parport_register_device() failed\n", + __func__, port->number, parport); + return; + } + + if (parport_claim(pprt)) { + pr_err("could not claim access to parport%d. Aborting.\n", + parport); + goto err_unreg_device; + } + + /* must init LCD first, just in case an IRQ from the keypad is + * generated at keypad init + */ + if (lcd.enabled) { + lcd_init(); + if (misc_register(&lcd_dev)) + goto err_unreg_device; + } + + if (keypad.enabled) { + keypad_init(); + if (misc_register(&keypad_dev)) + goto err_lcd_unreg; + } + register_reboot_notifier(&panel_notifier); + return; + +err_lcd_unreg: + if (lcd.enabled) + misc_deregister(&lcd_dev); +err_unreg_device: + parport_unregister_device(pprt); + pprt = NULL; +} + +static void panel_detach(struct parport *port) +{ + if (port->number != parport) + return; + + if (!pprt) { + pr_err("%s: port->number=%d parport=%d, nothing to unregister.\n", + __func__, port->number, parport); + return; + } + if (scan_timer.function) + del_timer_sync(&scan_timer); + + if (pprt) { + if (keypad.enabled) { + misc_deregister(&keypad_dev); + keypad_initialized = 0; + } + + if (lcd.enabled) { + panel_lcd_print("\x0cLCD driver " PANEL_VERSION + "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-"); + misc_deregister(&lcd_dev); + lcd.initialized = false; + } + + /* TODO: free all input signals */ + parport_release(pprt); + parport_unregister_device(pprt); + pprt = NULL; + unregister_reboot_notifier(&panel_notifier); + } +} + +static struct parport_driver panel_driver = { + .name = "panel", + .match_port = panel_attach, + .detach = panel_detach, + .devmodel = true, +}; + +/* init function */ +static int __init panel_init_module(void) +{ + int selected_keypad_type = NOT_SET, err; + + /* take care of an eventual profile */ + switch (profile) { + case PANEL_PROFILE_CUSTOM: + /* custom profile */ + selected_keypad_type = DEFAULT_KEYPAD_TYPE; + selected_lcd_type = DEFAULT_LCD_TYPE; + break; + case PANEL_PROFILE_OLD: + /* 8 bits, 2*16, old keypad */ + selected_keypad_type = KEYPAD_TYPE_OLD; + selected_lcd_type = LCD_TYPE_OLD; + + /* TODO: This two are a little hacky, sort it out later */ + if (lcd_width == NOT_SET) + lcd_width = 16; + if (lcd_hwidth == NOT_SET) + lcd_hwidth = 16; + break; + case PANEL_PROFILE_NEW: + /* serial, 2*16, new keypad */ + selected_keypad_type = KEYPAD_TYPE_NEW; + selected_lcd_type = LCD_TYPE_KS0074; + break; + case PANEL_PROFILE_HANTRONIX: + /* 8 bits, 2*16 hantronix-like, no keypad */ + selected_keypad_type = KEYPAD_TYPE_NONE; + selected_lcd_type = LCD_TYPE_HANTRONIX; + break; + case PANEL_PROFILE_NEXCOM: + /* generic 8 bits, 2*16, nexcom keypad, eg. Nexcom. */ + selected_keypad_type = KEYPAD_TYPE_NEXCOM; + selected_lcd_type = LCD_TYPE_NEXCOM; + break; + case PANEL_PROFILE_LARGE: + /* 8 bits, 2*40, old keypad */ + selected_keypad_type = KEYPAD_TYPE_OLD; + selected_lcd_type = LCD_TYPE_OLD; + break; + } + + /* + * Overwrite selection with module param values (both keypad and lcd), + * where the deprecated params have lower prio. + */ + if (keypad_enabled != NOT_SET) + selected_keypad_type = keypad_enabled; + if (keypad_type != NOT_SET) + selected_keypad_type = keypad_type; + + keypad.enabled = (selected_keypad_type > 0); + + if (lcd_enabled != NOT_SET) + selected_lcd_type = lcd_enabled; + if (lcd_type != NOT_SET) + selected_lcd_type = lcd_type; + + lcd.enabled = (selected_lcd_type > 0); + + if (lcd.enabled) { + /* + * Init lcd struct with load-time values to preserve exact + * current functionality (at least for now). + */ + lcd.height = lcd_height; + lcd.width = lcd_width; + lcd.bwidth = lcd_bwidth; + lcd.hwidth = lcd_hwidth; + lcd.charset = lcd_charset; + lcd.proto = lcd_proto; + lcd.pins.e = lcd_e_pin; + lcd.pins.rs = lcd_rs_pin; + lcd.pins.rw = lcd_rw_pin; + lcd.pins.cl = lcd_cl_pin; + lcd.pins.da = lcd_da_pin; + lcd.pins.bl = lcd_bl_pin; + + /* Leave it for now, just in case */ + lcd.esc_seq.len = -1; + } + + switch (selected_keypad_type) { + case KEYPAD_TYPE_OLD: + keypad_profile = old_keypad_profile; + break; + case KEYPAD_TYPE_NEW: + keypad_profile = new_keypad_profile; + break; + case KEYPAD_TYPE_NEXCOM: + keypad_profile = nexcom_keypad_profile; + break; + default: + keypad_profile = NULL; + break; + } + + if (!lcd.enabled && !keypad.enabled) { + /* no device enabled, let's exit */ + pr_err("driver version " PANEL_VERSION " disabled.\n"); + return -ENODEV; + } + + err = parport_register_driver(&panel_driver); + if (err) { + pr_err("could not register with parport. Aborting.\n"); + return err; + } + + if (pprt) + pr_info("driver version " PANEL_VERSION + " registered on parport%d (io=0x%lx).\n", parport, + pprt->port->base); + else + pr_info("driver version " PANEL_VERSION + " not yet registered\n"); + return 0; +} + +static void __exit panel_cleanup_module(void) +{ + parport_unregister_driver(&panel_driver); +} + +module_init(panel_init_module); +module_exit(panel_cleanup_module); +MODULE_AUTHOR("Willy Tarreau"); +MODULE_LICENSE("GPL"); + +/* + * Local variables: + * c-indent-level: 4 + * tab-width: 8 + * End: + */ diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index e80268ae8c9d..5f9a97a77393 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -30,8 +30,6 @@ source "drivers/staging/wlan-ng/Kconfig" source "drivers/staging/comedi/Kconfig" -source "drivers/staging/panel/Kconfig" - source "drivers/staging/rtl8192u/Kconfig" source "drivers/staging/rtl8192e/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index ba160f1ec02d..dbab17e9d45c 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -7,7 +7,6 @@ obj-y += media/ obj-$(CONFIG_SLICOSS) += slicoss/ obj-$(CONFIG_PRISM2_USB) += wlan-ng/ obj-$(CONFIG_COMEDI) += comedi/ -obj-$(CONFIG_PANEL) += panel/ obj-$(CONFIG_RTL8192U) += rtl8192u/ obj-$(CONFIG_RTL8192E) += rtl8192e/ obj-$(CONFIG_R8712U) += rtl8712/ diff --git a/drivers/staging/panel/Kconfig b/drivers/staging/panel/Kconfig deleted file mode 100644 index 3defa0133f2e..000000000000 --- a/drivers/staging/panel/Kconfig +++ /dev/null @@ -1,278 +0,0 @@ -config PANEL - tristate "Parallel port LCD/Keypad Panel support" - depends on PARPORT - ---help--- - Say Y here if you have an HD44780 or KS-0074 LCD connected to your - parallel port. This driver also features 4 and 6-key keypads. The LCD - is accessible through the /dev/lcd char device (10, 156), and the - keypad through /dev/keypad (10, 185). Both require misc device to be - enabled. This code can either be compiled as a module, or linked into - the kernel and started at boot. If you don't understand what all this - is about, say N. - -config PANEL_PARPORT - int "Default parallel port number (0=LPT1)" - depends on PANEL - range 0 255 - default "0" - ---help--- - This is the index of the parallel port the panel is connected to. One - driver instance only supports one parallel port, so if your keypad - and LCD are connected to two separate ports, you have to start two - modules with different arguments. Numbering starts with '0' for LPT1, - and so on. - -config PANEL_PROFILE - int "Default panel profile (0-5, 0=custom)" - depends on PANEL - range 0 5 - default "5" - ---help--- - To ease configuration, the driver supports different configuration - profiles for past and recent wirings. These profiles can also be - used to define an approximative configuration, completed by a few - other options. Here are the profiles : - - 0 = custom (see further) - 1 = 2x16 parallel LCD, old keypad - 2 = 2x16 serial LCD (KS-0074), new keypad - 3 = 2x16 parallel LCD (Hantronix), no keypad - 4 = 2x16 parallel LCD (Nexcom NSA1045) with Nexcom's keypad - 5 = 2x40 parallel LCD (old one), with old keypad - - Custom configurations allow you to define how your display is - wired to the parallel port, and how it works. This is only intended - for experts. - -config PANEL_KEYPAD - depends on PANEL && PANEL_PROFILE="0" - int "Keypad type (0=none, 1=old 6 keys, 2=new 6 keys, 3=Nexcom 4 keys)" - range 0 3 - default 0 - ---help--- - This enables and configures a keypad connected to the parallel port. - The keys will be read from character device 10,185. Valid values are : - - 0 : do not enable this driver - 1 : old 6 keys keypad - 2 : new 6 keys keypad, as used on the server at www.ant-computing.com - 3 : Nexcom NSA1045's 4 keys keypad - - New profiles can be described in the driver source. The driver also - supports simultaneous keys pressed when the keypad supports them. - -config PANEL_LCD - depends on PANEL && PANEL_PROFILE="0" - int "LCD type (0=none, 1=custom, 2=old //, 3=ks0074, 4=hantronix, 5=Nexcom)" - range 0 5 - default 0 - ---help--- - This enables and configures an LCD connected to the parallel port. - The driver includes an interpreter for escape codes starting with - '\e[L' which are specific to the LCD, and a few ANSI codes. The - driver will be registered as character device 10,156, usually - under the name '/dev/lcd'. There are a total of 6 supported types : - - 0 : do not enable the driver - 1 : custom configuration and wiring (see further) - 2 : 2x16 & 2x40 parallel LCD (old wiring) - 3 : 2x16 serial LCD (KS-0074 based) - 4 : 2x16 parallel LCD (Hantronix wiring) - 5 : 2x16 parallel LCD (Nexcom wiring) - - When type '1' is specified, other options will appear to configure - more precise aspects (wiring, dimensions, protocol, ...). Please note - that those values changed from the 2.4 driver for better consistency. - -config PANEL_LCD_HEIGHT - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" - int "Number of lines on the LCD (1-2)" - range 1 2 - default 2 - ---help--- - This is the number of visible character lines on the LCD in custom profile. - It can either be 1 or 2. - -config PANEL_LCD_WIDTH - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" - int "Number of characters per line on the LCD (1-40)" - range 1 40 - default 40 - ---help--- - This is the number of characters per line on the LCD in custom profile. - Common values are 16,20,24,40. - -config PANEL_LCD_BWIDTH - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" - int "Internal LCD line width (1-40, 40 by default)" - range 1 40 - default 40 - ---help--- - Most LCDs use a standard controller which supports hardware lines of 40 - characters, although sometimes only 16, 20 or 24 of them are really wired - to the terminal. This results in some non-visible but addressable characters, - and is the case for most parallel LCDs. Other LCDs, and some serial ones, - however, use the same line width internally as what is visible. The KS0074 - for example, uses 16 characters per line for 16 visible characters per line. - - This option lets you configure the value used by your LCD in 'custom' profile. - If you don't know, put '40' here. - -config PANEL_LCD_HWIDTH - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" - int "Hardware LCD line width (1-64, 64 by default)" - range 1 64 - default 64 - ---help--- - Most LCDs use a single address bit to differentiate line 0 and line 1. Since - some of them need to be able to address 40 chars with the lower bits, they - often use the immediately superior power of 2, which is 64, to address the - next line. - - If you don't know what your LCD uses, in doubt let 16 here for a 2x16, and - 64 here for a 2x40. - -config PANEL_LCD_CHARSET - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" - int "LCD character set (0=normal, 1=KS0074)" - range 0 1 - default 0 - ---help--- - Some controllers such as the KS0074 use a somewhat strange character set - where many symbols are at unusual places. The driver knows how to map - 'standard' ASCII characters to the character sets used by these controllers. - Valid values are : - - 0 : normal (untranslated) character set - 1 : KS0074 character set - - If you don't know, use the normal one (0). - -config PANEL_LCD_PROTO - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" - int "LCD communication mode (0=parallel 8 bits, 1=serial)" - range 0 1 - default 0 - ---help--- - This driver now supports any serial or parallel LCD wired to a parallel - port. But before assigning signals, the driver needs to know if it will - be driving a serial LCD or a parallel one. Serial LCDs only use 2 wires - (SDA/SCL), while parallel ones use 2 or 3 wires for the control signals - (E, RS, sometimes RW), and 4 or 8 for the data. Use 0 here for a 8 bits - parallel LCD, and 1 for a serial LCD. - -config PANEL_LCD_PIN_E - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0" - int "Parallel port pin number & polarity connected to the LCD E signal (-17...17) " - range -17 17 - default 14 - ---help--- - This describes the number of the parallel port pin to which the LCD 'E' - signal has been connected. It can be : - - 0 : no connection (eg: connected to ground) - 1..17 : directly connected to any of these pins on the DB25 plug - -1..-17 : connected to the same pin through an inverter (eg: transistor). - - Default for the 'E' pin in custom profile is '14' (AUTOFEED). - -config PANEL_LCD_PIN_RS - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0" - int "Parallel port pin number & polarity connected to the LCD RS signal (-17...17) " - range -17 17 - default 17 - ---help--- - This describes the number of the parallel port pin to which the LCD 'RS' - signal has been connected. It can be : - - 0 : no connection (eg: connected to ground) - 1..17 : directly connected to any of these pins on the DB25 plug - -1..-17 : connected to the same pin through an inverter (eg: transistor). - - Default for the 'RS' pin in custom profile is '17' (SELECT IN). - -config PANEL_LCD_PIN_RW - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0" - int "Parallel port pin number & polarity connected to the LCD RW signal (-17...17) " - range -17 17 - default 16 - ---help--- - This describes the number of the parallel port pin to which the LCD 'RW' - signal has been connected. It can be : - - 0 : no connection (eg: connected to ground) - 1..17 : directly connected to any of these pins on the DB25 plug - -1..-17 : connected to the same pin through an inverter (eg: transistor). - - Default for the 'RW' pin in custom profile is '16' (INIT). - -config PANEL_LCD_PIN_SCL - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO!="0" - int "Parallel port pin number & polarity connected to the LCD SCL signal (-17...17) " - range -17 17 - default 1 - ---help--- - This describes the number of the parallel port pin to which the serial - LCD 'SCL' signal has been connected. It can be : - - 0 : no connection (eg: connected to ground) - 1..17 : directly connected to any of these pins on the DB25 plug - -1..-17 : connected to the same pin through an inverter (eg: transistor). - - Default for the 'SCL' pin in custom profile is '1' (STROBE). - -config PANEL_LCD_PIN_SDA - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO!="0" - int "Parallel port pin number & polarity connected to the LCD SDA signal (-17...17) " - range -17 17 - default 2 - ---help--- - This describes the number of the parallel port pin to which the serial - LCD 'SDA' signal has been connected. It can be : - - 0 : no connection (eg: connected to ground) - 1..17 : directly connected to any of these pins on the DB25 plug - -1..-17 : connected to the same pin through an inverter (eg: transistor). - - Default for the 'SDA' pin in custom profile is '2' (D0). - -config PANEL_LCD_PIN_BL - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" - int "Parallel port pin number & polarity connected to the LCD backlight signal (-17...17) " - range -17 17 - default 0 - ---help--- - This describes the number of the parallel port pin to which the LCD 'BL' signal - has been connected. It can be : - - 0 : no connection (eg: connected to ground) - 1..17 : directly connected to any of these pins on the DB25 plug - -1..-17 : connected to the same pin through an inverter (eg: transistor). - - Default for the 'BL' pin in custom profile is '0' (uncontrolled). - -config PANEL_CHANGE_MESSAGE - depends on PANEL - bool "Change LCD initialization message ?" - default "n" - ---help--- - This allows you to replace the boot message indicating the kernel version - and the driver version with a custom message. This is useful on appliances - where a simple 'Starting system' message can be enough to stop a customer - from worrying. - - If you say 'Y' here, you'll be able to choose a message yourself. Otherwise, - say 'N' and keep the default message with the version. - -config PANEL_BOOT_MESSAGE - depends on PANEL && PANEL_CHANGE_MESSAGE="y" - string "New initialization message" - default "" - ---help--- - This allows you to replace the boot message indicating the kernel version - and the driver version with a custom message. This is useful on appliances - where a simple 'Starting system' message can be enough to stop a customer - from worrying. - - An empty message will only clear the display at driver init time. Any other - printf()-formatted message is valid with newline and escape codes. diff --git a/drivers/staging/panel/Makefile b/drivers/staging/panel/Makefile deleted file mode 100644 index 747c238b82f9..000000000000 --- a/drivers/staging/panel/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_PANEL) += panel.o diff --git a/drivers/staging/panel/TODO b/drivers/staging/panel/TODO deleted file mode 100644 index 3a6405ab91e0..000000000000 --- a/drivers/staging/panel/TODO +++ /dev/null @@ -1,8 +0,0 @@ -TODO: - - checkpatch.pl cleanups - - review major/minor usages - - review userspace api - - see if all of this could be easier done in userspace instead. - -Please send patches to Greg Kroah-Hartman and -Willy Tarreau diff --git a/drivers/staging/panel/lcd-panel-cgram.txt b/drivers/staging/panel/lcd-panel-cgram.txt deleted file mode 100644 index 7f82c905763d..000000000000 --- a/drivers/staging/panel/lcd-panel-cgram.txt +++ /dev/null @@ -1,24 +0,0 @@ -Some LCDs allow you to define up to 8 characters, mapped to ASCII -characters 0 to 7. The escape code to define a new character is -'\e[LG' followed by one digit from 0 to 7, representing the character -number, and up to 8 couples of hex digits terminated by a semi-colon -(';'). Each couple of digits represents a line, with 1-bits for each -illuminated pixel with LSB on the right. Lines are numbered from the -top of the character to the bottom. On a 5x7 matrix, only the 5 lower -bits of the 7 first bytes are used for each character. If the string -is incomplete, only complete lines will be redefined. Here are some -examples : - - printf "\e[LG0010101050D1F0C04;" => 0 = [enter] - printf "\e[LG1040E1F0000000000;" => 1 = [up] - printf "\e[LG2000000001F0E0400;" => 2 = [down] - printf "\e[LG3040E1F001F0E0400;" => 3 = [up-down] - printf "\e[LG40002060E1E0E0602;" => 4 = [left] - printf "\e[LG500080C0E0F0E0C08;" => 5 = [right] - printf "\e[LG60016051516141400;" => 6 = "IP" - - printf "\e[LG00103071F1F070301;" => big speaker - printf "\e[LG00002061E1E060200;" => small speaker - -Willy - diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c deleted file mode 100644 index 4262db0237f9..000000000000 --- a/drivers/staging/panel/panel.c +++ /dev/null @@ -1,2445 +0,0 @@ -/* - * Front panel driver for Linux - * Copyright (C) 2000-2008, Willy Tarreau - * - * 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 code drives an LCD module (/dev/lcd), and a keypad (/dev/keypad) - * connected to a parallel printer port. - * - * The LCD module may either be an HD44780-like 8-bit parallel LCD, or a 1-bit - * serial module compatible with Samsung's KS0074. The pins may be connected in - * any combination, everything is programmable. - * - * The keypad consists in a matrix of push buttons connecting input pins to - * data output pins or to the ground. The combinations have to be hard-coded - * in the driver, though several profiles exist and adding new ones is easy. - * - * Several profiles are provided for commonly found LCD+keypad modules on the - * market, such as those found in Nexcom's appliances. - * - * FIXME: - * - the initialization/deinitialization process is very dirty and should - * be rewritten. It may even be buggy. - * - * TODO: - * - document 24 keys keyboard (3 rows of 8 cols, 32 diodes + 2 inputs) - * - make the LCD a part of a virtual screen of Vx*Vy - * - make the inputs list smp-safe - * - change the keyboard to a double mapping : signals -> key_id -> values - * so that applications can change values without knowing signals - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define LCD_MINOR 156 -#define KEYPAD_MINOR 185 - -#define PANEL_VERSION "0.9.5" - -#define LCD_MAXBYTES 256 /* max burst write */ - -#define KEYPAD_BUFFER 64 - -/* poll the keyboard this every second */ -#define INPUT_POLL_TIME (HZ / 50) -/* a key starts to repeat after this times INPUT_POLL_TIME */ -#define KEYPAD_REP_START (10) -/* a key repeats this times INPUT_POLL_TIME */ -#define KEYPAD_REP_DELAY (2) - -/* keep the light on this times INPUT_POLL_TIME for each flash */ -#define FLASH_LIGHT_TEMPO (200) - -/* converts an r_str() input to an active high, bits string : 000BAOSE */ -#define PNL_PINPUT(a) ((((unsigned char)(a)) ^ 0x7F) >> 3) - -#define PNL_PBUSY 0x80 /* inverted input, active low */ -#define PNL_PACK 0x40 /* direct input, active low */ -#define PNL_POUTPA 0x20 /* direct input, active high */ -#define PNL_PSELECD 0x10 /* direct input, active high */ -#define PNL_PERRORP 0x08 /* direct input, active low */ - -#define PNL_PBIDIR 0x20 /* bi-directional ports */ -/* high to read data in or-ed with data out */ -#define PNL_PINTEN 0x10 -#define PNL_PSELECP 0x08 /* inverted output, active low */ -#define PNL_PINITP 0x04 /* direct output, active low */ -#define PNL_PAUTOLF 0x02 /* inverted output, active low */ -#define PNL_PSTROBE 0x01 /* inverted output */ - -#define PNL_PD0 0x01 -#define PNL_PD1 0x02 -#define PNL_PD2 0x04 -#define PNL_PD3 0x08 -#define PNL_PD4 0x10 -#define PNL_PD5 0x20 -#define PNL_PD6 0x40 -#define PNL_PD7 0x80 - -#define PIN_NONE 0 -#define PIN_STROBE 1 -#define PIN_D0 2 -#define PIN_D1 3 -#define PIN_D2 4 -#define PIN_D3 5 -#define PIN_D4 6 -#define PIN_D5 7 -#define PIN_D6 8 -#define PIN_D7 9 -#define PIN_AUTOLF 14 -#define PIN_INITP 16 -#define PIN_SELECP 17 -#define PIN_NOT_SET 127 - -#define LCD_FLAG_S 0x0001 -#define LCD_FLAG_ID 0x0002 -#define LCD_FLAG_B 0x0004 /* blink on */ -#define LCD_FLAG_C 0x0008 /* cursor on */ -#define LCD_FLAG_D 0x0010 /* display on */ -#define LCD_FLAG_F 0x0020 /* large font mode */ -#define LCD_FLAG_N 0x0040 /* 2-rows mode */ -#define LCD_FLAG_L 0x0080 /* backlight enabled */ - -/* LCD commands */ -#define LCD_CMD_DISPLAY_CLEAR 0x01 /* Clear entire display */ - -#define LCD_CMD_ENTRY_MODE 0x04 /* Set entry mode */ -#define LCD_CMD_CURSOR_INC 0x02 /* Increment cursor */ - -#define LCD_CMD_DISPLAY_CTRL 0x08 /* Display control */ -#define LCD_CMD_DISPLAY_ON 0x04 /* Set display on */ -#define LCD_CMD_CURSOR_ON 0x02 /* Set cursor on */ -#define LCD_CMD_BLINK_ON 0x01 /* Set blink on */ - -#define LCD_CMD_SHIFT 0x10 /* Shift cursor/display */ -#define LCD_CMD_DISPLAY_SHIFT 0x08 /* Shift display instead of cursor */ -#define LCD_CMD_SHIFT_RIGHT 0x04 /* Shift display/cursor to the right */ - -#define LCD_CMD_FUNCTION_SET 0x20 /* Set function */ -#define LCD_CMD_DATA_LEN_8BITS 0x10 /* Set data length to 8 bits */ -#define LCD_CMD_TWO_LINES 0x08 /* Set to two display lines */ -#define LCD_CMD_FONT_5X10_DOTS 0x04 /* Set char font to 5x10 dots */ - -#define LCD_CMD_SET_CGRAM_ADDR 0x40 /* Set char generator RAM address */ - -#define LCD_CMD_SET_DDRAM_ADDR 0x80 /* Set display data RAM address */ - -#define LCD_ESCAPE_LEN 24 /* max chars for LCD escape command */ -#define LCD_ESCAPE_CHAR 27 /* use char 27 for escape command */ - -#define NOT_SET -1 - -/* macros to simplify use of the parallel port */ -#define r_ctr(x) (parport_read_control((x)->port)) -#define r_dtr(x) (parport_read_data((x)->port)) -#define r_str(x) (parport_read_status((x)->port)) -#define w_ctr(x, y) (parport_write_control((x)->port, (y))) -#define w_dtr(x, y) (parport_write_data((x)->port, (y))) - -/* this defines which bits are to be used and which ones to be ignored */ -/* logical or of the output bits involved in the scan matrix */ -static __u8 scan_mask_o; -/* logical or of the input bits involved in the scan matrix */ -static __u8 scan_mask_i; - -enum input_type { - INPUT_TYPE_STD, - INPUT_TYPE_KBD, -}; - -enum input_state { - INPUT_ST_LOW, - INPUT_ST_RISING, - INPUT_ST_HIGH, - INPUT_ST_FALLING, -}; - -struct logical_input { - struct list_head list; - __u64 mask; - __u64 value; - enum input_type type; - enum input_state state; - __u8 rise_time, fall_time; - __u8 rise_timer, fall_timer, high_timer; - - union { - struct { /* valid when type == INPUT_TYPE_STD */ - void (*press_fct)(int); - void (*release_fct)(int); - int press_data; - int release_data; - } std; - struct { /* valid when type == INPUT_TYPE_KBD */ - /* strings can be non null-terminated */ - char press_str[sizeof(void *) + sizeof(int)]; - char repeat_str[sizeof(void *) + sizeof(int)]; - char release_str[sizeof(void *) + sizeof(int)]; - } kbd; - } u; -}; - -static LIST_HEAD(logical_inputs); /* list of all defined logical inputs */ - -/* physical contacts history - * Physical contacts are a 45 bits string of 9 groups of 5 bits each. - * The 8 lower groups correspond to output bits 0 to 7, and the 9th group - * corresponds to the ground. - * Within each group, bits are stored in the same order as read on the port : - * BAPSE (busy=4, ack=3, paper empty=2, select=1, error=0). - * So, each __u64 is represented like this : - * 0000000000000000000BAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSE - * <-----unused------> - */ - -/* what has just been read from the I/O ports */ -static __u64 phys_read; -/* previous phys_read */ -static __u64 phys_read_prev; -/* stabilized phys_read (phys_read|phys_read_prev) */ -static __u64 phys_curr; -/* previous phys_curr */ -static __u64 phys_prev; -/* 0 means that at least one logical signal needs be computed */ -static char inputs_stable; - -/* these variables are specific to the keypad */ -static struct { - bool enabled; -} keypad; - -static char keypad_buffer[KEYPAD_BUFFER]; -static int keypad_buflen; -static int keypad_start; -static char keypressed; -static wait_queue_head_t keypad_read_wait; - -/* lcd-specific variables */ -static struct { - bool enabled; - bool initialized; - bool must_clear; - - int height; - int width; - int bwidth; - int hwidth; - int charset; - int proto; - int light_tempo; - - /* TODO: use union here? */ - struct { - int e; - int rs; - int rw; - int cl; - int da; - int bl; - } pins; - - /* contains the LCD config state */ - unsigned long int flags; - - /* Contains the LCD X and Y offset */ - struct { - unsigned long int x; - unsigned long int y; - } addr; - - /* Current escape sequence and it's length or -1 if outside */ - struct { - char buf[LCD_ESCAPE_LEN + 1]; - int len; - } esc_seq; -} lcd; - -/* Needed only for init */ -static int selected_lcd_type = NOT_SET; - -/* - * Bit masks to convert LCD signals to parallel port outputs. - * _d_ are values for data port, _c_ are for control port. - * [0] = signal OFF, [1] = signal ON, [2] = mask - */ -#define BIT_CLR 0 -#define BIT_SET 1 -#define BIT_MSK 2 -#define BIT_STATES 3 -/* - * one entry for each bit on the LCD - */ -#define LCD_BIT_E 0 -#define LCD_BIT_RS 1 -#define LCD_BIT_RW 2 -#define LCD_BIT_BL 3 -#define LCD_BIT_CL 4 -#define LCD_BIT_DA 5 -#define LCD_BITS 6 - -/* - * each bit can be either connected to a DATA or CTRL port - */ -#define LCD_PORT_C 0 -#define LCD_PORT_D 1 -#define LCD_PORTS 2 - -static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES]; - -/* - * LCD protocols - */ -#define LCD_PROTO_PARALLEL 0 -#define LCD_PROTO_SERIAL 1 -#define LCD_PROTO_TI_DA8XX_LCD 2 - -/* - * LCD character sets - */ -#define LCD_CHARSET_NORMAL 0 -#define LCD_CHARSET_KS0074 1 - -/* - * LCD types - */ -#define LCD_TYPE_NONE 0 -#define LCD_TYPE_CUSTOM 1 -#define LCD_TYPE_OLD 2 -#define LCD_TYPE_KS0074 3 -#define LCD_TYPE_HANTRONIX 4 -#define LCD_TYPE_NEXCOM 5 - -/* - * keypad types - */ -#define KEYPAD_TYPE_NONE 0 -#define KEYPAD_TYPE_OLD 1 -#define KEYPAD_TYPE_NEW 2 -#define KEYPAD_TYPE_NEXCOM 3 - -/* - * panel profiles - */ -#define PANEL_PROFILE_CUSTOM 0 -#define PANEL_PROFILE_OLD 1 -#define PANEL_PROFILE_NEW 2 -#define PANEL_PROFILE_HANTRONIX 3 -#define PANEL_PROFILE_NEXCOM 4 -#define PANEL_PROFILE_LARGE 5 - -/* - * Construct custom config from the kernel's configuration - */ -#define DEFAULT_PARPORT 0 -#define DEFAULT_PROFILE PANEL_PROFILE_LARGE -#define DEFAULT_KEYPAD_TYPE KEYPAD_TYPE_OLD -#define DEFAULT_LCD_TYPE LCD_TYPE_OLD -#define DEFAULT_LCD_HEIGHT 2 -#define DEFAULT_LCD_WIDTH 40 -#define DEFAULT_LCD_BWIDTH 40 -#define DEFAULT_LCD_HWIDTH 64 -#define DEFAULT_LCD_CHARSET LCD_CHARSET_NORMAL -#define DEFAULT_LCD_PROTO LCD_PROTO_PARALLEL - -#define DEFAULT_LCD_PIN_E PIN_AUTOLF -#define DEFAULT_LCD_PIN_RS PIN_SELECP -#define DEFAULT_LCD_PIN_RW PIN_INITP -#define DEFAULT_LCD_PIN_SCL PIN_STROBE -#define DEFAULT_LCD_PIN_SDA PIN_D0 -#define DEFAULT_LCD_PIN_BL PIN_NOT_SET - -#ifdef CONFIG_PANEL_PARPORT -#undef DEFAULT_PARPORT -#define DEFAULT_PARPORT CONFIG_PANEL_PARPORT -#endif - -#ifdef CONFIG_PANEL_PROFILE -#undef DEFAULT_PROFILE -#define DEFAULT_PROFILE CONFIG_PANEL_PROFILE -#endif - -#if DEFAULT_PROFILE == 0 /* custom */ -#ifdef CONFIG_PANEL_KEYPAD -#undef DEFAULT_KEYPAD_TYPE -#define DEFAULT_KEYPAD_TYPE CONFIG_PANEL_KEYPAD -#endif - -#ifdef CONFIG_PANEL_LCD -#undef DEFAULT_LCD_TYPE -#define DEFAULT_LCD_TYPE CONFIG_PANEL_LCD -#endif - -#ifdef CONFIG_PANEL_LCD_HEIGHT -#undef DEFAULT_LCD_HEIGHT -#define DEFAULT_LCD_HEIGHT CONFIG_PANEL_LCD_HEIGHT -#endif - -#ifdef CONFIG_PANEL_LCD_WIDTH -#undef DEFAULT_LCD_WIDTH -#define DEFAULT_LCD_WIDTH CONFIG_PANEL_LCD_WIDTH -#endif - -#ifdef CONFIG_PANEL_LCD_BWIDTH -#undef DEFAULT_LCD_BWIDTH -#define DEFAULT_LCD_BWIDTH CONFIG_PANEL_LCD_BWIDTH -#endif - -#ifdef CONFIG_PANEL_LCD_HWIDTH -#undef DEFAULT_LCD_HWIDTH -#define DEFAULT_LCD_HWIDTH CONFIG_PANEL_LCD_HWIDTH -#endif - -#ifdef CONFIG_PANEL_LCD_CHARSET -#undef DEFAULT_LCD_CHARSET -#define DEFAULT_LCD_CHARSET CONFIG_PANEL_LCD_CHARSET -#endif - -#ifdef CONFIG_PANEL_LCD_PROTO -#undef DEFAULT_LCD_PROTO -#define DEFAULT_LCD_PROTO CONFIG_PANEL_LCD_PROTO -#endif - -#ifdef CONFIG_PANEL_LCD_PIN_E -#undef DEFAULT_LCD_PIN_E -#define DEFAULT_LCD_PIN_E CONFIG_PANEL_LCD_PIN_E -#endif - -#ifdef CONFIG_PANEL_LCD_PIN_RS -#undef DEFAULT_LCD_PIN_RS -#define DEFAULT_LCD_PIN_RS CONFIG_PANEL_LCD_PIN_RS -#endif - -#ifdef CONFIG_PANEL_LCD_PIN_RW -#undef DEFAULT_LCD_PIN_RW -#define DEFAULT_LCD_PIN_RW CONFIG_PANEL_LCD_PIN_RW -#endif - -#ifdef CONFIG_PANEL_LCD_PIN_SCL -#undef DEFAULT_LCD_PIN_SCL -#define DEFAULT_LCD_PIN_SCL CONFIG_PANEL_LCD_PIN_SCL -#endif - -#ifdef CONFIG_PANEL_LCD_PIN_SDA -#undef DEFAULT_LCD_PIN_SDA -#define DEFAULT_LCD_PIN_SDA CONFIG_PANEL_LCD_PIN_SDA -#endif - -#ifdef CONFIG_PANEL_LCD_PIN_BL -#undef DEFAULT_LCD_PIN_BL -#define DEFAULT_LCD_PIN_BL CONFIG_PANEL_LCD_PIN_BL -#endif - -#endif /* DEFAULT_PROFILE == 0 */ - -/* global variables */ - -/* Device single-open policy control */ -static atomic_t lcd_available = ATOMIC_INIT(1); -static atomic_t keypad_available = ATOMIC_INIT(1); - -static struct pardevice *pprt; - -static int keypad_initialized; - -static void (*lcd_write_cmd)(int); -static void (*lcd_write_data)(int); -static void (*lcd_clear_fast)(void); - -static DEFINE_SPINLOCK(pprt_lock); -static struct timer_list scan_timer; - -MODULE_DESCRIPTION("Generic parallel port LCD/Keypad driver"); - -static int parport = DEFAULT_PARPORT; -module_param(parport, int, 0000); -MODULE_PARM_DESC(parport, "Parallel port index (0=lpt1, 1=lpt2, ...)"); - -static int profile = DEFAULT_PROFILE; -module_param(profile, int, 0000); -MODULE_PARM_DESC(profile, - "1=16x2 old kp; 2=serial 16x2, new kp; 3=16x2 hantronix; " - "4=16x2 nexcom; default=40x2, old kp"); - -static int keypad_type = NOT_SET; -module_param(keypad_type, int, 0000); -MODULE_PARM_DESC(keypad_type, - "Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, 3=nexcom 4 keys"); - -static int lcd_type = NOT_SET; -module_param(lcd_type, int, 0000); -MODULE_PARM_DESC(lcd_type, - "LCD type: 0=none, 1=compiled-in, 2=old, 3=serial ks0074, 4=hantronix, 5=nexcom"); - -static int lcd_height = NOT_SET; -module_param(lcd_height, int, 0000); -MODULE_PARM_DESC(lcd_height, "Number of lines on the LCD"); - -static int lcd_width = NOT_SET; -module_param(lcd_width, int, 0000); -MODULE_PARM_DESC(lcd_width, "Number of columns on the LCD"); - -static int lcd_bwidth = NOT_SET; /* internal buffer width (usually 40) */ -module_param(lcd_bwidth, int, 0000); -MODULE_PARM_DESC(lcd_bwidth, "Internal LCD line width (40)"); - -static int lcd_hwidth = NOT_SET; /* hardware buffer width (usually 64) */ -module_param(lcd_hwidth, int, 0000); -MODULE_PARM_DESC(lcd_hwidth, "LCD line hardware address (64)"); - -static int lcd_charset = NOT_SET; -module_param(lcd_charset, int, 0000); -MODULE_PARM_DESC(lcd_charset, "LCD character set: 0=standard, 1=KS0074"); - -static int lcd_proto = NOT_SET; -module_param(lcd_proto, int, 0000); -MODULE_PARM_DESC(lcd_proto, - "LCD communication: 0=parallel (//), 1=serial, 2=TI LCD Interface"); - -/* - * These are the parallel port pins the LCD control signals are connected to. - * Set this to 0 if the signal is not used. Set it to its opposite value - * (negative) if the signal is negated. -MAXINT is used to indicate that the - * pin has not been explicitly specified. - * - * WARNING! no check will be performed about collisions with keypad ! - */ - -static int lcd_e_pin = PIN_NOT_SET; -module_param(lcd_e_pin, int, 0000); -MODULE_PARM_DESC(lcd_e_pin, - "# of the // port pin connected to LCD 'E' signal, with polarity (-17..17)"); - -static int lcd_rs_pin = PIN_NOT_SET; -module_param(lcd_rs_pin, int, 0000); -MODULE_PARM_DESC(lcd_rs_pin, - "# of the // port pin connected to LCD 'RS' signal, with polarity (-17..17)"); - -static int lcd_rw_pin = PIN_NOT_SET; -module_param(lcd_rw_pin, int, 0000); -MODULE_PARM_DESC(lcd_rw_pin, - "# of the // port pin connected to LCD 'RW' signal, with polarity (-17..17)"); - -static int lcd_cl_pin = PIN_NOT_SET; -module_param(lcd_cl_pin, int, 0000); -MODULE_PARM_DESC(lcd_cl_pin, - "# of the // port pin connected to serial LCD 'SCL' signal, with polarity (-17..17)"); - -static int lcd_da_pin = PIN_NOT_SET; -module_param(lcd_da_pin, int, 0000); -MODULE_PARM_DESC(lcd_da_pin, - "# of the // port pin connected to serial LCD 'SDA' signal, with polarity (-17..17)"); - -static int lcd_bl_pin = PIN_NOT_SET; -module_param(lcd_bl_pin, int, 0000); -MODULE_PARM_DESC(lcd_bl_pin, - "# of the // port pin connected to LCD backlight, with polarity (-17..17)"); - -/* Deprecated module parameters - consider not using them anymore */ - -static int lcd_enabled = NOT_SET; -module_param(lcd_enabled, int, 0000); -MODULE_PARM_DESC(lcd_enabled, "Deprecated option, use lcd_type instead"); - -static int keypad_enabled = NOT_SET; -module_param(keypad_enabled, int, 0000); -MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead"); - -static const unsigned char *lcd_char_conv; - -/* for some LCD drivers (ks0074) we need a charset conversion table. */ -static const unsigned char lcd_char_conv_ks0074[256] = { - /* 0|8 1|9 2|A 3|B 4|C 5|D 6|E 7|F */ - /* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - /* 0x08 */ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - /* 0x10 */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - /* 0x18 */ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - /* 0x20 */ 0x20, 0x21, 0x22, 0x23, 0xa2, 0x25, 0x26, 0x27, - /* 0x28 */ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - /* 0x30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - /* 0x38 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - /* 0x40 */ 0xa0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - /* 0x48 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - /* 0x50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - /* 0x58 */ 0x58, 0x59, 0x5a, 0xfa, 0xfb, 0xfc, 0x1d, 0xc4, - /* 0x60 */ 0x96, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - /* 0x68 */ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - /* 0x70 */ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - /* 0x78 */ 0x78, 0x79, 0x7a, 0xfd, 0xfe, 0xff, 0xce, 0x20, - /* 0x80 */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - /* 0x88 */ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - /* 0x90 */ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - /* 0x98 */ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - /* 0xA0 */ 0x20, 0x40, 0xb1, 0xa1, 0x24, 0xa3, 0xfe, 0x5f, - /* 0xA8 */ 0x22, 0xc8, 0x61, 0x14, 0x97, 0x2d, 0xad, 0x96, - /* 0xB0 */ 0x80, 0x8c, 0x82, 0x83, 0x27, 0x8f, 0x86, 0xdd, - /* 0xB8 */ 0x2c, 0x81, 0x6f, 0x15, 0x8b, 0x8a, 0x84, 0x60, - /* 0xC0 */ 0xe2, 0xe2, 0xe2, 0x5b, 0x5b, 0xae, 0xbc, 0xa9, - /* 0xC8 */ 0xc5, 0xbf, 0xc6, 0xf1, 0xe3, 0xe3, 0xe3, 0xe3, - /* 0xD0 */ 0x44, 0x5d, 0xa8, 0xe4, 0xec, 0xec, 0x5c, 0x78, - /* 0xD8 */ 0xab, 0xa6, 0xe5, 0x5e, 0x5e, 0xe6, 0xaa, 0xbe, - /* 0xE0 */ 0x7f, 0xe7, 0xaf, 0x7b, 0x7b, 0xaf, 0xbd, 0xc8, - /* 0xE8 */ 0xa4, 0xa5, 0xc7, 0xf6, 0xa7, 0xe8, 0x69, 0x69, - /* 0xF0 */ 0xed, 0x7d, 0xa8, 0xe4, 0xec, 0x5c, 0x5c, 0x25, - /* 0xF8 */ 0xac, 0xa6, 0xea, 0xef, 0x7e, 0xeb, 0xb2, 0x79, -}; - -static const char old_keypad_profile[][4][9] = { - {"S0", "Left\n", "Left\n", ""}, - {"S1", "Down\n", "Down\n", ""}, - {"S2", "Up\n", "Up\n", ""}, - {"S3", "Right\n", "Right\n", ""}, - {"S4", "Esc\n", "Esc\n", ""}, - {"S5", "Ret\n", "Ret\n", ""}, - {"", "", "", ""} -}; - -/* signals, press, repeat, release */ -static const char new_keypad_profile[][4][9] = { - {"S0", "Left\n", "Left\n", ""}, - {"S1", "Down\n", "Down\n", ""}, - {"S2", "Up\n", "Up\n", ""}, - {"S3", "Right\n", "Right\n", ""}, - {"S4s5", "", "Esc\n", "Esc\n"}, - {"s4S5", "", "Ret\n", "Ret\n"}, - {"S4S5", "Help\n", "", ""}, - /* add new signals above this line */ - {"", "", "", ""} -}; - -/* signals, press, repeat, release */ -static const char nexcom_keypad_profile[][4][9] = { - {"a-p-e-", "Down\n", "Down\n", ""}, - {"a-p-E-", "Ret\n", "Ret\n", ""}, - {"a-P-E-", "Esc\n", "Esc\n", ""}, - {"a-P-e-", "Up\n", "Up\n", ""}, - /* add new signals above this line */ - {"", "", "", ""} -}; - -static const char (*keypad_profile)[4][9] = old_keypad_profile; - -/* FIXME: this should be converted to a bit array containing signals states */ -static struct { - unsigned char e; /* parallel LCD E (data latch on falling edge) */ - unsigned char rs; /* parallel LCD RS (0 = cmd, 1 = data) */ - unsigned char rw; /* parallel LCD R/W (0 = W, 1 = R) */ - unsigned char bl; /* parallel LCD backlight (0 = off, 1 = on) */ - unsigned char cl; /* serial LCD clock (latch on rising edge) */ - unsigned char da; /* serial LCD data */ -} bits; - -static void init_scan_timer(void); - -/* sets data port bits according to current signals values */ -static int set_data_bits(void) -{ - int val, bit; - - val = r_dtr(pprt); - for (bit = 0; bit < LCD_BITS; bit++) - val &= lcd_bits[LCD_PORT_D][bit][BIT_MSK]; - - val |= lcd_bits[LCD_PORT_D][LCD_BIT_E][bits.e] - | lcd_bits[LCD_PORT_D][LCD_BIT_RS][bits.rs] - | lcd_bits[LCD_PORT_D][LCD_BIT_RW][bits.rw] - | lcd_bits[LCD_PORT_D][LCD_BIT_BL][bits.bl] - | lcd_bits[LCD_PORT_D][LCD_BIT_CL][bits.cl] - | lcd_bits[LCD_PORT_D][LCD_BIT_DA][bits.da]; - - w_dtr(pprt, val); - return val; -} - -/* sets ctrl port bits according to current signals values */ -static int set_ctrl_bits(void) -{ - int val, bit; - - val = r_ctr(pprt); - for (bit = 0; bit < LCD_BITS; bit++) - val &= lcd_bits[LCD_PORT_C][bit][BIT_MSK]; - - val |= lcd_bits[LCD_PORT_C][LCD_BIT_E][bits.e] - | lcd_bits[LCD_PORT_C][LCD_BIT_RS][bits.rs] - | lcd_bits[LCD_PORT_C][LCD_BIT_RW][bits.rw] - | lcd_bits[LCD_PORT_C][LCD_BIT_BL][bits.bl] - | lcd_bits[LCD_PORT_C][LCD_BIT_CL][bits.cl] - | lcd_bits[LCD_PORT_C][LCD_BIT_DA][bits.da]; - - w_ctr(pprt, val); - return val; -} - -/* sets ctrl & data port bits according to current signals values */ -static void panel_set_bits(void) -{ - set_data_bits(); - set_ctrl_bits(); -} - -/* - * Converts a parallel port pin (from -25 to 25) to data and control ports - * masks, and data and control port bits. The signal will be considered - * unconnected if it's on pin 0 or an invalid pin (<-25 or >25). - * - * Result will be used this way : - * out(dport, in(dport) & d_val[2] | d_val[signal_state]) - * out(cport, in(cport) & c_val[2] | c_val[signal_state]) - */ -static void pin_to_bits(int pin, unsigned char *d_val, unsigned char *c_val) -{ - int d_bit, c_bit, inv; - - d_val[0] = 0; - c_val[0] = 0; - d_val[1] = 0; - c_val[1] = 0; - d_val[2] = 0xFF; - c_val[2] = 0xFF; - - if (pin == 0) - return; - - inv = (pin < 0); - if (inv) - pin = -pin; - - d_bit = 0; - c_bit = 0; - - switch (pin) { - case PIN_STROBE: /* strobe, inverted */ - c_bit = PNL_PSTROBE; - inv = !inv; - break; - case PIN_D0...PIN_D7: /* D0 - D7 = 2 - 9 */ - d_bit = 1 << (pin - 2); - break; - case PIN_AUTOLF: /* autofeed, inverted */ - c_bit = PNL_PAUTOLF; - inv = !inv; - break; - case PIN_INITP: /* init, direct */ - c_bit = PNL_PINITP; - break; - case PIN_SELECP: /* select_in, inverted */ - c_bit = PNL_PSELECP; - inv = !inv; - break; - default: /* unknown pin, ignore */ - break; - } - - if (c_bit) { - c_val[2] &= ~c_bit; - c_val[!inv] = c_bit; - } else if (d_bit) { - d_val[2] &= ~d_bit; - d_val[!inv] = d_bit; - } -} - -/* sleeps that many milliseconds with a reschedule */ -static void long_sleep(int ms) -{ - if (in_interrupt()) - mdelay(ms); - else - schedule_timeout_interruptible(msecs_to_jiffies(ms)); -} - -/* - * send a serial byte to the LCD panel. The caller is responsible for locking - * if needed. - */ -static void lcd_send_serial(int byte) -{ - int bit; - - /* - * the data bit is set on D0, and the clock on STROBE. - * LCD reads D0 on STROBE's rising edge. - */ - for (bit = 0; bit < 8; bit++) { - bits.cl = BIT_CLR; /* CLK low */ - panel_set_bits(); - bits.da = byte & 1; - panel_set_bits(); - udelay(2); /* maintain the data during 2 us before CLK up */ - bits.cl = BIT_SET; /* CLK high */ - panel_set_bits(); - udelay(1); /* maintain the strobe during 1 us */ - byte >>= 1; - } -} - -/* turn the backlight on or off */ -static void lcd_backlight(int on) -{ - if (lcd.pins.bl == PIN_NONE) - return; - - /* The backlight is activated by setting the AUTOFEED line to +5V */ - spin_lock_irq(&pprt_lock); - bits.bl = on; - panel_set_bits(); - spin_unlock_irq(&pprt_lock); -} - -/* send a command to the LCD panel in serial mode */ -static void lcd_write_cmd_s(int cmd) -{ - spin_lock_irq(&pprt_lock); - lcd_send_serial(0x1F); /* R/W=W, RS=0 */ - lcd_send_serial(cmd & 0x0F); - lcd_send_serial((cmd >> 4) & 0x0F); - udelay(40); /* the shortest command takes at least 40 us */ - spin_unlock_irq(&pprt_lock); -} - -/* send data to the LCD panel in serial mode */ -static void lcd_write_data_s(int data) -{ - spin_lock_irq(&pprt_lock); - lcd_send_serial(0x5F); /* R/W=W, RS=1 */ - lcd_send_serial(data & 0x0F); - lcd_send_serial((data >> 4) & 0x0F); - udelay(40); /* the shortest data takes at least 40 us */ - spin_unlock_irq(&pprt_lock); -} - -/* send a command to the LCD panel in 8 bits parallel mode */ -static void lcd_write_cmd_p8(int cmd) -{ - spin_lock_irq(&pprt_lock); - /* present the data to the data port */ - w_dtr(pprt, cmd); - udelay(20); /* maintain the data during 20 us before the strobe */ - - bits.e = BIT_SET; - bits.rs = BIT_CLR; - bits.rw = BIT_CLR; - set_ctrl_bits(); - - udelay(40); /* maintain the strobe during 40 us */ - - bits.e = BIT_CLR; - set_ctrl_bits(); - - udelay(120); /* the shortest command takes at least 120 us */ - spin_unlock_irq(&pprt_lock); -} - -/* send data to the LCD panel in 8 bits parallel mode */ -static void lcd_write_data_p8(int data) -{ - spin_lock_irq(&pprt_lock); - /* present the data to the data port */ - w_dtr(pprt, data); - udelay(20); /* maintain the data during 20 us before the strobe */ - - bits.e = BIT_SET; - bits.rs = BIT_SET; - bits.rw = BIT_CLR; - set_ctrl_bits(); - - udelay(40); /* maintain the strobe during 40 us */ - - bits.e = BIT_CLR; - set_ctrl_bits(); - - udelay(45); /* the shortest data takes at least 45 us */ - spin_unlock_irq(&pprt_lock); -} - -/* send a command to the TI LCD panel */ -static void lcd_write_cmd_tilcd(int cmd) -{ - spin_lock_irq(&pprt_lock); - /* present the data to the control port */ - w_ctr(pprt, cmd); - udelay(60); - spin_unlock_irq(&pprt_lock); -} - -/* send data to the TI LCD panel */ -static void lcd_write_data_tilcd(int data) -{ - spin_lock_irq(&pprt_lock); - /* present the data to the data port */ - w_dtr(pprt, data); - udelay(60); - spin_unlock_irq(&pprt_lock); -} - -static void lcd_gotoxy(void) -{ - lcd_write_cmd(LCD_CMD_SET_DDRAM_ADDR - | (lcd.addr.y ? lcd.hwidth : 0) - /* - * we force the cursor to stay at the end of the - * line if it wants to go farther - */ - | ((lcd.addr.x < lcd.bwidth) ? lcd.addr.x & - (lcd.hwidth - 1) : lcd.bwidth - 1)); -} - -static void lcd_print(char c) -{ - if (lcd.addr.x < lcd.bwidth) { - if (lcd_char_conv) - c = lcd_char_conv[(unsigned char)c]; - lcd_write_data(c); - lcd.addr.x++; - } - /* prevents the cursor from wrapping onto the next line */ - if (lcd.addr.x == lcd.bwidth) - lcd_gotoxy(); -} - -/* fills the display with spaces and resets X/Y */ -static void lcd_clear_fast_s(void) -{ - int pos; - - lcd.addr.x = 0; - lcd.addr.y = 0; - lcd_gotoxy(); - - spin_lock_irq(&pprt_lock); - for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { - lcd_send_serial(0x5F); /* R/W=W, RS=1 */ - lcd_send_serial(' ' & 0x0F); - lcd_send_serial((' ' >> 4) & 0x0F); - /* the shortest data takes at least 40 us */ - udelay(40); - } - spin_unlock_irq(&pprt_lock); - - lcd.addr.x = 0; - lcd.addr.y = 0; - lcd_gotoxy(); -} - -/* fills the display with spaces and resets X/Y */ -static void lcd_clear_fast_p8(void) -{ - int pos; - - lcd.addr.x = 0; - lcd.addr.y = 0; - lcd_gotoxy(); - - spin_lock_irq(&pprt_lock); - for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { - /* present the data to the data port */ - w_dtr(pprt, ' '); - - /* maintain the data during 20 us before the strobe */ - udelay(20); - - bits.e = BIT_SET; - bits.rs = BIT_SET; - bits.rw = BIT_CLR; - set_ctrl_bits(); - - /* maintain the strobe during 40 us */ - udelay(40); - - bits.e = BIT_CLR; - set_ctrl_bits(); - - /* the shortest data takes at least 45 us */ - udelay(45); - } - spin_unlock_irq(&pprt_lock); - - lcd.addr.x = 0; - lcd.addr.y = 0; - lcd_gotoxy(); -} - -/* fills the display with spaces and resets X/Y */ -static void lcd_clear_fast_tilcd(void) -{ - int pos; - - lcd.addr.x = 0; - lcd.addr.y = 0; - lcd_gotoxy(); - - spin_lock_irq(&pprt_lock); - for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { - /* present the data to the data port */ - w_dtr(pprt, ' '); - udelay(60); - } - - spin_unlock_irq(&pprt_lock); - - lcd.addr.x = 0; - lcd.addr.y = 0; - lcd_gotoxy(); -} - -/* clears the display and resets X/Y */ -static void lcd_clear_display(void) -{ - lcd_write_cmd(LCD_CMD_DISPLAY_CLEAR); - lcd.addr.x = 0; - lcd.addr.y = 0; - /* we must wait a few milliseconds (15) */ - long_sleep(15); -} - -static void lcd_init_display(void) -{ - lcd.flags = ((lcd.height > 1) ? LCD_FLAG_N : 0) - | LCD_FLAG_D | LCD_FLAG_C | LCD_FLAG_B; - - long_sleep(20); /* wait 20 ms after power-up for the paranoid */ - - /* 8bits, 1 line, small fonts; let's do it 3 times */ - lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); - long_sleep(10); - lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); - long_sleep(10); - lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); - long_sleep(10); - - /* set font height and lines number */ - lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS - | ((lcd.flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) - | ((lcd.flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0) - ); - long_sleep(10); - - /* display off, cursor off, blink off */ - lcd_write_cmd(LCD_CMD_DISPLAY_CTRL); - long_sleep(10); - - lcd_write_cmd(LCD_CMD_DISPLAY_CTRL /* set display mode */ - | ((lcd.flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) - | ((lcd.flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) - | ((lcd.flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0) - ); - - lcd_backlight((lcd.flags & LCD_FLAG_L) ? 1 : 0); - - long_sleep(10); - - /* entry mode set : increment, cursor shifting */ - lcd_write_cmd(LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC); - - lcd_clear_display(); -} - -/* - * These are the file operation function for user access to /dev/lcd - * This function can also be called from inside the kernel, by - * setting file and ppos to NULL. - * - */ - -static inline int handle_lcd_special_code(void) -{ - /* LCD special codes */ - - int processed = 0; - - char *esc = lcd.esc_seq.buf + 2; - int oldflags = lcd.flags; - - /* check for display mode flags */ - switch (*esc) { - case 'D': /* Display ON */ - lcd.flags |= LCD_FLAG_D; - processed = 1; - break; - case 'd': /* Display OFF */ - lcd.flags &= ~LCD_FLAG_D; - processed = 1; - break; - case 'C': /* Cursor ON */ - lcd.flags |= LCD_FLAG_C; - processed = 1; - break; - case 'c': /* Cursor OFF */ - lcd.flags &= ~LCD_FLAG_C; - processed = 1; - break; - case 'B': /* Blink ON */ - lcd.flags |= LCD_FLAG_B; - processed = 1; - break; - case 'b': /* Blink OFF */ - lcd.flags &= ~LCD_FLAG_B; - processed = 1; - break; - case '+': /* Back light ON */ - lcd.flags |= LCD_FLAG_L; - processed = 1; - break; - case '-': /* Back light OFF */ - lcd.flags &= ~LCD_FLAG_L; - processed = 1; - break; - case '*': - /* flash back light using the keypad timer */ - if (scan_timer.function) { - if (lcd.light_tempo == 0 && - ((lcd.flags & LCD_FLAG_L) == 0)) - lcd_backlight(1); - lcd.light_tempo = FLASH_LIGHT_TEMPO; - } - processed = 1; - break; - case 'f': /* Small Font */ - lcd.flags &= ~LCD_FLAG_F; - processed = 1; - break; - case 'F': /* Large Font */ - lcd.flags |= LCD_FLAG_F; - processed = 1; - break; - case 'n': /* One Line */ - lcd.flags &= ~LCD_FLAG_N; - processed = 1; - break; - case 'N': /* Two Lines */ - lcd.flags |= LCD_FLAG_N; - break; - case 'l': /* Shift Cursor Left */ - if (lcd.addr.x > 0) { - /* back one char if not at end of line */ - if (lcd.addr.x < lcd.bwidth) - lcd_write_cmd(LCD_CMD_SHIFT); - lcd.addr.x--; - } - processed = 1; - break; - case 'r': /* shift cursor right */ - if (lcd.addr.x < lcd.width) { - /* allow the cursor to pass the end of the line */ - if (lcd.addr.x < (lcd.bwidth - 1)) - lcd_write_cmd(LCD_CMD_SHIFT | - LCD_CMD_SHIFT_RIGHT); - lcd.addr.x++; - } - processed = 1; - break; - case 'L': /* shift display left */ - lcd_write_cmd(LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT); - processed = 1; - break; - case 'R': /* shift display right */ - lcd_write_cmd(LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT | - LCD_CMD_SHIFT_RIGHT); - processed = 1; - break; - case 'k': { /* kill end of line */ - int x; - - for (x = lcd.addr.x; x < lcd.bwidth; x++) - lcd_write_data(' '); - - /* restore cursor position */ - lcd_gotoxy(); - processed = 1; - break; - } - case 'I': /* reinitialize display */ - lcd_init_display(); - processed = 1; - break; - case 'G': { - /* Generator : LGcxxxxx...xx; must have between '0' - * and '7', representing the numerical ASCII code of the - * redefined character, and a sequence of 16 - * hex digits representing 8 bytes for each character. - * Most LCDs will only use 5 lower bits of the 7 first - * bytes. - */ - - unsigned char cgbytes[8]; - unsigned char cgaddr; - int cgoffset; - int shift; - char value; - int addr; - - if (!strchr(esc, ';')) - break; - - esc++; - - cgaddr = *(esc++) - '0'; - if (cgaddr > 7) { - processed = 1; - break; - } - - cgoffset = 0; - shift = 0; - value = 0; - while (*esc && cgoffset < 8) { - shift ^= 4; - if (*esc >= '0' && *esc <= '9') { - value |= (*esc - '0') << shift; - } else if (*esc >= 'A' && *esc <= 'Z') { - value |= (*esc - 'A' + 10) << shift; - } else if (*esc >= 'a' && *esc <= 'z') { - value |= (*esc - 'a' + 10) << shift; - } else { - esc++; - continue; - } - - if (shift == 0) { - cgbytes[cgoffset++] = value; - value = 0; - } - - esc++; - } - - lcd_write_cmd(LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8)); - for (addr = 0; addr < cgoffset; addr++) - lcd_write_data(cgbytes[addr]); - - /* ensures that we stop writing to CGRAM */ - lcd_gotoxy(); - processed = 1; - break; - } - case 'x': /* gotoxy : LxXXX[yYYY]; */ - case 'y': /* gotoxy : LyYYY[xXXX]; */ - if (!strchr(esc, ';')) - break; - - while (*esc) { - if (*esc == 'x') { - esc++; - if (kstrtoul(esc, 10, &lcd.addr.x) < 0) - break; - } else if (*esc == 'y') { - esc++; - if (kstrtoul(esc, 10, &lcd.addr.y) < 0) - break; - } else { - break; - } - } - - lcd_gotoxy(); - processed = 1; - break; - } - - /* TODO: This indent party here got ugly, clean it! */ - /* Check whether one flag was changed */ - if (oldflags != lcd.flags) { - /* check whether one of B,C,D flags were changed */ - if ((oldflags ^ lcd.flags) & - (LCD_FLAG_B | LCD_FLAG_C | LCD_FLAG_D)) - /* set display mode */ - lcd_write_cmd(LCD_CMD_DISPLAY_CTRL - | ((lcd.flags & LCD_FLAG_D) - ? LCD_CMD_DISPLAY_ON : 0) - | ((lcd.flags & LCD_FLAG_C) - ? LCD_CMD_CURSOR_ON : 0) - | ((lcd.flags & LCD_FLAG_B) - ? LCD_CMD_BLINK_ON : 0)); - /* check whether one of F,N flags was changed */ - else if ((oldflags ^ lcd.flags) & (LCD_FLAG_F | LCD_FLAG_N)) - lcd_write_cmd(LCD_CMD_FUNCTION_SET - | LCD_CMD_DATA_LEN_8BITS - | ((lcd.flags & LCD_FLAG_F) - ? LCD_CMD_TWO_LINES : 0) - | ((lcd.flags & LCD_FLAG_N) - ? LCD_CMD_FONT_5X10_DOTS - : 0)); - /* check whether L flag was changed */ - else if ((oldflags ^ lcd.flags) & (LCD_FLAG_L)) { - if (lcd.flags & (LCD_FLAG_L)) - lcd_backlight(1); - else if (lcd.light_tempo == 0) - /* - * switch off the light only when the tempo - * lighting is gone - */ - lcd_backlight(0); - } - } - - return processed; -} - -static void lcd_write_char(char c) -{ - /* first, we'll test if we're in escape mode */ - if ((c != '\n') && lcd.esc_seq.len >= 0) { - /* yes, let's add this char to the buffer */ - lcd.esc_seq.buf[lcd.esc_seq.len++] = c; - lcd.esc_seq.buf[lcd.esc_seq.len] = 0; - } else { - /* aborts any previous escape sequence */ - lcd.esc_seq.len = -1; - - switch (c) { - case LCD_ESCAPE_CHAR: - /* start of an escape sequence */ - lcd.esc_seq.len = 0; - lcd.esc_seq.buf[lcd.esc_seq.len] = 0; - break; - case '\b': - /* go back one char and clear it */ - if (lcd.addr.x > 0) { - /* - * check if we're not at the - * end of the line - */ - if (lcd.addr.x < lcd.bwidth) - /* back one char */ - lcd_write_cmd(LCD_CMD_SHIFT); - lcd.addr.x--; - } - /* replace with a space */ - lcd_write_data(' '); - /* back one char again */ - lcd_write_cmd(LCD_CMD_SHIFT); - break; - case '\014': - /* quickly clear the display */ - lcd_clear_fast(); - break; - case '\n': - /* - * flush the remainder of the current line and - * go to the beginning of the next line - */ - for (; lcd.addr.x < lcd.bwidth; lcd.addr.x++) - lcd_write_data(' '); - lcd.addr.x = 0; - lcd.addr.y = (lcd.addr.y + 1) % lcd.height; - lcd_gotoxy(); - break; - case '\r': - /* go to the beginning of the same line */ - lcd.addr.x = 0; - lcd_gotoxy(); - break; - case '\t': - /* print a space instead of the tab */ - lcd_print(' '); - break; - default: - /* simply print this char */ - lcd_print(c); - break; - } - } - - /* - * now we'll see if we're in an escape mode and if the current - * escape sequence can be understood. - */ - if (lcd.esc_seq.len >= 2) { - int processed = 0; - - if (!strcmp(lcd.esc_seq.buf, "[2J")) { - /* clear the display */ - lcd_clear_fast(); - processed = 1; - } else if (!strcmp(lcd.esc_seq.buf, "[H")) { - /* cursor to home */ - lcd.addr.x = 0; - lcd.addr.y = 0; - lcd_gotoxy(); - processed = 1; - } - /* codes starting with ^[[L */ - else if ((lcd.esc_seq.len >= 3) && - (lcd.esc_seq.buf[0] == '[') && - (lcd.esc_seq.buf[1] == 'L')) { - processed = handle_lcd_special_code(); - } - - /* LCD special escape codes */ - /* - * flush the escape sequence if it's been processed - * or if it is getting too long. - */ - if (processed || (lcd.esc_seq.len >= LCD_ESCAPE_LEN)) - lcd.esc_seq.len = -1; - } /* escape codes */ -} - -static ssize_t lcd_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - const char __user *tmp = buf; - char c; - - for (; count-- > 0; (*ppos)++, tmp++) { - if (!in_interrupt() && (((count + 1) & 0x1f) == 0)) - /* - * let's be a little nice with other processes - * that need some CPU - */ - schedule(); - - if (get_user(c, tmp)) - return -EFAULT; - - lcd_write_char(c); - } - - return tmp - buf; -} - -static int lcd_open(struct inode *inode, struct file *file) -{ - if (!atomic_dec_and_test(&lcd_available)) - return -EBUSY; /* open only once at a time */ - - if (file->f_mode & FMODE_READ) /* device is write-only */ - return -EPERM; - - if (lcd.must_clear) { - lcd_clear_display(); - lcd.must_clear = false; - } - return nonseekable_open(inode, file); -} - -static int lcd_release(struct inode *inode, struct file *file) -{ - atomic_inc(&lcd_available); - return 0; -} - -static const struct file_operations lcd_fops = { - .write = lcd_write, - .open = lcd_open, - .release = lcd_release, - .llseek = no_llseek, -}; - -static struct miscdevice lcd_dev = { - .minor = LCD_MINOR, - .name = "lcd", - .fops = &lcd_fops, -}; - -/* public function usable from the kernel for any purpose */ -static void panel_lcd_print(const char *s) -{ - const char *tmp = s; - int count = strlen(s); - - if (lcd.enabled && lcd.initialized) { - for (; count-- > 0; tmp++) { - if (!in_interrupt() && (((count + 1) & 0x1f) == 0)) - /* - * let's be a little nice with other processes - * that need some CPU - */ - schedule(); - - lcd_write_char(*tmp); - } - } -} - -/* initialize the LCD driver */ -static void lcd_init(void) -{ - switch (selected_lcd_type) { - case LCD_TYPE_OLD: - /* parallel mode, 8 bits */ - lcd.proto = LCD_PROTO_PARALLEL; - lcd.charset = LCD_CHARSET_NORMAL; - lcd.pins.e = PIN_STROBE; - lcd.pins.rs = PIN_AUTOLF; - - lcd.width = 40; - lcd.bwidth = 40; - lcd.hwidth = 64; - lcd.height = 2; - break; - case LCD_TYPE_KS0074: - /* serial mode, ks0074 */ - lcd.proto = LCD_PROTO_SERIAL; - lcd.charset = LCD_CHARSET_KS0074; - lcd.pins.bl = PIN_AUTOLF; - lcd.pins.cl = PIN_STROBE; - lcd.pins.da = PIN_D0; - - lcd.width = 16; - lcd.bwidth = 40; - lcd.hwidth = 16; - lcd.height = 2; - break; - case LCD_TYPE_NEXCOM: - /* parallel mode, 8 bits, generic */ - lcd.proto = LCD_PROTO_PARALLEL; - lcd.charset = LCD_CHARSET_NORMAL; - lcd.pins.e = PIN_AUTOLF; - lcd.pins.rs = PIN_SELECP; - lcd.pins.rw = PIN_INITP; - - lcd.width = 16; - lcd.bwidth = 40; - lcd.hwidth = 64; - lcd.height = 2; - break; - case LCD_TYPE_CUSTOM: - /* customer-defined */ - lcd.proto = DEFAULT_LCD_PROTO; - lcd.charset = DEFAULT_LCD_CHARSET; - /* default geometry will be set later */ - break; - case LCD_TYPE_HANTRONIX: - /* parallel mode, 8 bits, hantronix-like */ - default: - lcd.proto = LCD_PROTO_PARALLEL; - lcd.charset = LCD_CHARSET_NORMAL; - lcd.pins.e = PIN_STROBE; - lcd.pins.rs = PIN_SELECP; - - lcd.width = 16; - lcd.bwidth = 40; - lcd.hwidth = 64; - lcd.height = 2; - break; - } - - /* Overwrite with module params set on loading */ - if (lcd_height != NOT_SET) - lcd.height = lcd_height; - if (lcd_width != NOT_SET) - lcd.width = lcd_width; - if (lcd_bwidth != NOT_SET) - lcd.bwidth = lcd_bwidth; - if (lcd_hwidth != NOT_SET) - lcd.hwidth = lcd_hwidth; - if (lcd_charset != NOT_SET) - lcd.charset = lcd_charset; - if (lcd_proto != NOT_SET) - lcd.proto = lcd_proto; - if (lcd_e_pin != PIN_NOT_SET) - lcd.pins.e = lcd_e_pin; - if (lcd_rs_pin != PIN_NOT_SET) - lcd.pins.rs = lcd_rs_pin; - if (lcd_rw_pin != PIN_NOT_SET) - lcd.pins.rw = lcd_rw_pin; - if (lcd_cl_pin != PIN_NOT_SET) - lcd.pins.cl = lcd_cl_pin; - if (lcd_da_pin != PIN_NOT_SET) - lcd.pins.da = lcd_da_pin; - if (lcd_bl_pin != PIN_NOT_SET) - lcd.pins.bl = lcd_bl_pin; - - /* this is used to catch wrong and default values */ - if (lcd.width <= 0) - lcd.width = DEFAULT_LCD_WIDTH; - if (lcd.bwidth <= 0) - lcd.bwidth = DEFAULT_LCD_BWIDTH; - if (lcd.hwidth <= 0) - lcd.hwidth = DEFAULT_LCD_HWIDTH; - if (lcd.height <= 0) - lcd.height = DEFAULT_LCD_HEIGHT; - - if (lcd.proto == LCD_PROTO_SERIAL) { /* SERIAL */ - lcd_write_cmd = lcd_write_cmd_s; - lcd_write_data = lcd_write_data_s; - lcd_clear_fast = lcd_clear_fast_s; - - if (lcd.pins.cl == PIN_NOT_SET) - lcd.pins.cl = DEFAULT_LCD_PIN_SCL; - if (lcd.pins.da == PIN_NOT_SET) - lcd.pins.da = DEFAULT_LCD_PIN_SDA; - - } else if (lcd.proto == LCD_PROTO_PARALLEL) { /* PARALLEL */ - lcd_write_cmd = lcd_write_cmd_p8; - lcd_write_data = lcd_write_data_p8; - lcd_clear_fast = lcd_clear_fast_p8; - - if (lcd.pins.e == PIN_NOT_SET) - lcd.pins.e = DEFAULT_LCD_PIN_E; - if (lcd.pins.rs == PIN_NOT_SET) - lcd.pins.rs = DEFAULT_LCD_PIN_RS; - if (lcd.pins.rw == PIN_NOT_SET) - lcd.pins.rw = DEFAULT_LCD_PIN_RW; - } else { - lcd_write_cmd = lcd_write_cmd_tilcd; - lcd_write_data = lcd_write_data_tilcd; - lcd_clear_fast = lcd_clear_fast_tilcd; - } - - if (lcd.pins.bl == PIN_NOT_SET) - lcd.pins.bl = DEFAULT_LCD_PIN_BL; - - if (lcd.pins.e == PIN_NOT_SET) - lcd.pins.e = PIN_NONE; - if (lcd.pins.rs == PIN_NOT_SET) - lcd.pins.rs = PIN_NONE; - if (lcd.pins.rw == PIN_NOT_SET) - lcd.pins.rw = PIN_NONE; - if (lcd.pins.bl == PIN_NOT_SET) - lcd.pins.bl = PIN_NONE; - if (lcd.pins.cl == PIN_NOT_SET) - lcd.pins.cl = PIN_NONE; - if (lcd.pins.da == PIN_NOT_SET) - lcd.pins.da = PIN_NONE; - - if (lcd.charset == NOT_SET) - lcd.charset = DEFAULT_LCD_CHARSET; - - if (lcd.charset == LCD_CHARSET_KS0074) - lcd_char_conv = lcd_char_conv_ks0074; - else - lcd_char_conv = NULL; - - if (lcd.pins.bl != PIN_NONE) - init_scan_timer(); - - pin_to_bits(lcd.pins.e, lcd_bits[LCD_PORT_D][LCD_BIT_E], - lcd_bits[LCD_PORT_C][LCD_BIT_E]); - pin_to_bits(lcd.pins.rs, lcd_bits[LCD_PORT_D][LCD_BIT_RS], - lcd_bits[LCD_PORT_C][LCD_BIT_RS]); - pin_to_bits(lcd.pins.rw, lcd_bits[LCD_PORT_D][LCD_BIT_RW], - lcd_bits[LCD_PORT_C][LCD_BIT_RW]); - pin_to_bits(lcd.pins.bl, lcd_bits[LCD_PORT_D][LCD_BIT_BL], - lcd_bits[LCD_PORT_C][LCD_BIT_BL]); - pin_to_bits(lcd.pins.cl, lcd_bits[LCD_PORT_D][LCD_BIT_CL], - lcd_bits[LCD_PORT_C][LCD_BIT_CL]); - pin_to_bits(lcd.pins.da, lcd_bits[LCD_PORT_D][LCD_BIT_DA], - lcd_bits[LCD_PORT_C][LCD_BIT_DA]); - - /* - * before this line, we must NOT send anything to the display. - * Since lcd_init_display() needs to write data, we have to - * enable mark the LCD initialized just before. - */ - lcd.initialized = true; - lcd_init_display(); - - /* display a short message */ -#ifdef CONFIG_PANEL_CHANGE_MESSAGE -#ifdef CONFIG_PANEL_BOOT_MESSAGE - panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*" CONFIG_PANEL_BOOT_MESSAGE); -#endif -#else - panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*Linux-" UTS_RELEASE "\nPanel-" - PANEL_VERSION); -#endif - lcd.addr.x = 0; - lcd.addr.y = 0; - /* clear the display on the next device opening */ - lcd.must_clear = true; - lcd_gotoxy(); -} - -/* - * These are the file operation function for user access to /dev/keypad - */ - -static ssize_t keypad_read(struct file *file, - char __user *buf, size_t count, loff_t *ppos) -{ - unsigned i = *ppos; - char __user *tmp = buf; - - if (keypad_buflen == 0) { - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - - if (wait_event_interruptible(keypad_read_wait, - keypad_buflen != 0)) - return -EINTR; - } - - for (; count-- > 0 && (keypad_buflen > 0); - ++i, ++tmp, --keypad_buflen) { - put_user(keypad_buffer[keypad_start], tmp); - keypad_start = (keypad_start + 1) % KEYPAD_BUFFER; - } - *ppos = i; - - return tmp - buf; -} - -static int keypad_open(struct inode *inode, struct file *file) -{ - if (!atomic_dec_and_test(&keypad_available)) - return -EBUSY; /* open only once at a time */ - - if (file->f_mode & FMODE_WRITE) /* device is read-only */ - return -EPERM; - - keypad_buflen = 0; /* flush the buffer on opening */ - return 0; -} - -static int keypad_release(struct inode *inode, struct file *file) -{ - atomic_inc(&keypad_available); - return 0; -} - -static const struct file_operations keypad_fops = { - .read = keypad_read, /* read */ - .open = keypad_open, /* open */ - .release = keypad_release, /* close */ - .llseek = default_llseek, -}; - -static struct miscdevice keypad_dev = { - .minor = KEYPAD_MINOR, - .name = "keypad", - .fops = &keypad_fops, -}; - -static void keypad_send_key(const char *string, int max_len) -{ - /* send the key to the device only if a process is attached to it. */ - if (!atomic_read(&keypad_available)) { - while (max_len-- && keypad_buflen < KEYPAD_BUFFER && *string) { - keypad_buffer[(keypad_start + keypad_buflen++) % - KEYPAD_BUFFER] = *string++; - } - wake_up_interruptible(&keypad_read_wait); - } -} - -/* this function scans all the bits involving at least one logical signal, - * and puts the results in the bitfield "phys_read" (one bit per established - * contact), and sets "phys_read_prev" to "phys_read". - * - * Note: to debounce input signals, we will only consider as switched a signal - * which is stable across 2 measures. Signals which are different between two - * reads will be kept as they previously were in their logical form (phys_prev). - * A signal which has just switched will have a 1 in - * (phys_read ^ phys_read_prev). - */ -static void phys_scan_contacts(void) -{ - int bit, bitval; - char oldval; - char bitmask; - char gndmask; - - phys_prev = phys_curr; - phys_read_prev = phys_read; - phys_read = 0; /* flush all signals */ - - /* keep track of old value, with all outputs disabled */ - oldval = r_dtr(pprt) | scan_mask_o; - /* activate all keyboard outputs (active low) */ - w_dtr(pprt, oldval & ~scan_mask_o); - - /* will have a 1 for each bit set to gnd */ - bitmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i; - /* disable all matrix signals */ - w_dtr(pprt, oldval); - - /* now that all outputs are cleared, the only active input bits are - * directly connected to the ground - */ - - /* 1 for each grounded input */ - gndmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i; - - /* grounded inputs are signals 40-44 */ - phys_read |= (__u64)gndmask << 40; - - if (bitmask != gndmask) { - /* - * since clearing the outputs changed some inputs, we know - * that some input signals are currently tied to some outputs. - * So we'll scan them. - */ - for (bit = 0; bit < 8; bit++) { - bitval = BIT(bit); - - if (!(scan_mask_o & bitval)) /* skip unused bits */ - continue; - - w_dtr(pprt, oldval & ~bitval); /* enable this output */ - bitmask = PNL_PINPUT(r_str(pprt)) & ~gndmask; - phys_read |= (__u64)bitmask << (5 * bit); - } - w_dtr(pprt, oldval); /* disable all outputs */ - } - /* - * this is easy: use old bits when they are flapping, - * use new ones when stable - */ - phys_curr = (phys_prev & (phys_read ^ phys_read_prev)) | - (phys_read & ~(phys_read ^ phys_read_prev)); -} - -static inline int input_state_high(struct logical_input *input) -{ -#if 0 - /* FIXME: - * this is an invalid test. It tries to catch - * transitions from single-key to multiple-key, but - * doesn't take into account the contacts polarity. - * The only solution to the problem is to parse keys - * from the most complex to the simplest combinations, - * and mark them as 'caught' once a combination - * matches, then unmatch it for all other ones. - */ - - /* try to catch dangerous transitions cases : - * someone adds a bit, so this signal was a false - * positive resulting from a transition. We should - * invalidate the signal immediately and not call the - * release function. - * eg: 0 -(press A)-> A -(press B)-> AB : don't match A's release. - */ - if (((phys_prev & input->mask) == input->value) && - ((phys_curr & input->mask) > input->value)) { - input->state = INPUT_ST_LOW; /* invalidate */ - return 1; - } -#endif - - if ((phys_curr & input->mask) == input->value) { - if ((input->type == INPUT_TYPE_STD) && - (input->high_timer == 0)) { - input->high_timer++; - if (input->u.std.press_fct) - input->u.std.press_fct(input->u.std.press_data); - } else if (input->type == INPUT_TYPE_KBD) { - /* will turn on the light */ - keypressed = 1; - - if (input->high_timer == 0) { - char *press_str = input->u.kbd.press_str; - - if (press_str[0]) { - int s = sizeof(input->u.kbd.press_str); - - keypad_send_key(press_str, s); - } - } - - if (input->u.kbd.repeat_str[0]) { - char *repeat_str = input->u.kbd.repeat_str; - - if (input->high_timer >= KEYPAD_REP_START) { - int s = sizeof(input->u.kbd.repeat_str); - - input->high_timer -= KEYPAD_REP_DELAY; - keypad_send_key(repeat_str, s); - } - /* we will need to come back here soon */ - inputs_stable = 0; - } - - if (input->high_timer < 255) - input->high_timer++; - } - return 1; - } - - /* else signal falling down. Let's fall through. */ - input->state = INPUT_ST_FALLING; - input->fall_timer = 0; - - return 0; -} - -static inline void input_state_falling(struct logical_input *input) -{ -#if 0 - /* FIXME !!! same comment as in input_state_high */ - if (((phys_prev & input->mask) == input->value) && - ((phys_curr & input->mask) > input->value)) { - input->state = INPUT_ST_LOW; /* invalidate */ - return; - } -#endif - - if ((phys_curr & input->mask) == input->value) { - if (input->type == INPUT_TYPE_KBD) { - /* will turn on the light */ - keypressed = 1; - - if (input->u.kbd.repeat_str[0]) { - char *repeat_str = input->u.kbd.repeat_str; - - if (input->high_timer >= KEYPAD_REP_START) { - int s = sizeof(input->u.kbd.repeat_str); - - input->high_timer -= KEYPAD_REP_DELAY; - keypad_send_key(repeat_str, s); - } - /* we will need to come back here soon */ - inputs_stable = 0; - } - - if (input->high_timer < 255) - input->high_timer++; - } - input->state = INPUT_ST_HIGH; - } else if (input->fall_timer >= input->fall_time) { - /* call release event */ - if (input->type == INPUT_TYPE_STD) { - void (*release_fct)(int) = input->u.std.release_fct; - - if (release_fct) - release_fct(input->u.std.release_data); - } else if (input->type == INPUT_TYPE_KBD) { - char *release_str = input->u.kbd.release_str; - - if (release_str[0]) { - int s = sizeof(input->u.kbd.release_str); - - keypad_send_key(release_str, s); - } - } - - input->state = INPUT_ST_LOW; - } else { - input->fall_timer++; - inputs_stable = 0; - } -} - -static void panel_process_inputs(void) -{ - struct list_head *item; - struct logical_input *input; - - keypressed = 0; - inputs_stable = 1; - list_for_each(item, &logical_inputs) { - input = list_entry(item, struct logical_input, list); - - switch (input->state) { - case INPUT_ST_LOW: - if ((phys_curr & input->mask) != input->value) - break; - /* if all needed ones were already set previously, - * this means that this logical signal has been - * activated by the releasing of another combined - * signal, so we don't want to match. - * eg: AB -(release B)-> A -(release A)-> 0 : - * don't match A. - */ - if ((phys_prev & input->mask) == input->value) - break; - input->rise_timer = 0; - input->state = INPUT_ST_RISING; - /* no break here, fall through */ - case INPUT_ST_RISING: - if ((phys_curr & input->mask) != input->value) { - input->state = INPUT_ST_LOW; - break; - } - if (input->rise_timer < input->rise_time) { - inputs_stable = 0; - input->rise_timer++; - break; - } - input->high_timer = 0; - input->state = INPUT_ST_HIGH; - /* no break here, fall through */ - case INPUT_ST_HIGH: - if (input_state_high(input)) - break; - /* no break here, fall through */ - case INPUT_ST_FALLING: - input_state_falling(input); - } - } -} - -static void panel_scan_timer(void) -{ - if (keypad.enabled && keypad_initialized) { - if (spin_trylock_irq(&pprt_lock)) { - phys_scan_contacts(); - - /* no need for the parport anymore */ - spin_unlock_irq(&pprt_lock); - } - - if (!inputs_stable || phys_curr != phys_prev) - panel_process_inputs(); - } - - if (lcd.enabled && lcd.initialized) { - if (keypressed) { - if (lcd.light_tempo == 0 && - ((lcd.flags & LCD_FLAG_L) == 0)) - lcd_backlight(1); - lcd.light_tempo = FLASH_LIGHT_TEMPO; - } else if (lcd.light_tempo > 0) { - lcd.light_tempo--; - if (lcd.light_tempo == 0 && - ((lcd.flags & LCD_FLAG_L) == 0)) - lcd_backlight(0); - } - } - - mod_timer(&scan_timer, jiffies + INPUT_POLL_TIME); -} - -static void init_scan_timer(void) -{ - if (scan_timer.function) - return; /* already started */ - - setup_timer(&scan_timer, (void *)&panel_scan_timer, 0); - scan_timer.expires = jiffies + INPUT_POLL_TIME; - add_timer(&scan_timer); -} - -/* converts a name of the form "({BbAaPpSsEe}{01234567-})*" to a series of bits. - * if or are non-null, they will be or'ed with the bits - * corresponding to out and in bits respectively. - * returns 1 if ok, 0 if error (in which case, nothing is written). - */ -static u8 input_name2mask(const char *name, __u64 *mask, __u64 *value, - u8 *imask, u8 *omask) -{ - const char sigtab[] = "EeSsPpAaBb"; - u8 im, om; - __u64 m, v; - - om = 0; - im = 0; - m = 0ULL; - v = 0ULL; - while (*name) { - int in, out, bit, neg; - const char *idx; - - idx = strchr(sigtab, *name); - if (!idx) - return 0; /* input name not found */ - - in = idx - sigtab; - neg = (in & 1); /* odd (lower) names are negated */ - in >>= 1; - im |= BIT(in); - - name++; - if (*name >= '0' && *name <= '7') { - out = *name - '0'; - om |= BIT(out); - } else if (*name == '-') { - out = 8; - } else { - return 0; /* unknown bit name */ - } - - bit = (out * 5) + in; - - m |= 1ULL << bit; - if (!neg) - v |= 1ULL << bit; - name++; - } - *mask = m; - *value = v; - if (imask) - *imask |= im; - if (omask) - *omask |= om; - return 1; -} - -/* tries to bind a key to the signal name . The key will send the - * strings , , for these respective events. - * Returns the pointer to the new key if ok, NULL if the key could not be bound. - */ -static struct logical_input *panel_bind_key(const char *name, const char *press, - const char *repeat, - const char *release) -{ - struct logical_input *key; - - key = kzalloc(sizeof(*key), GFP_KERNEL); - if (!key) - return NULL; - - if (!input_name2mask(name, &key->mask, &key->value, &scan_mask_i, - &scan_mask_o)) { - kfree(key); - return NULL; - } - - key->type = INPUT_TYPE_KBD; - key->state = INPUT_ST_LOW; - key->rise_time = 1; - key->fall_time = 1; - - strncpy(key->u.kbd.press_str, press, sizeof(key->u.kbd.press_str)); - strncpy(key->u.kbd.repeat_str, repeat, sizeof(key->u.kbd.repeat_str)); - strncpy(key->u.kbd.release_str, release, - sizeof(key->u.kbd.release_str)); - list_add(&key->list, &logical_inputs); - return key; -} - -#if 0 -/* tries to bind a callback function to the signal name . The function - * will be called with the arg when the signal is - * activated, and so on for / - * Returns the pointer to the new signal if ok, NULL if the signal could not - * be bound. - */ -static struct logical_input *panel_bind_callback(char *name, - void (*press_fct)(int), - int press_data, - void (*release_fct)(int), - int release_data) -{ - struct logical_input *callback; - - callback = kmalloc(sizeof(*callback), GFP_KERNEL); - if (!callback) - return NULL; - - memset(callback, 0, sizeof(struct logical_input)); - if (!input_name2mask(name, &callback->mask, &callback->value, - &scan_mask_i, &scan_mask_o)) - return NULL; - - callback->type = INPUT_TYPE_STD; - callback->state = INPUT_ST_LOW; - callback->rise_time = 1; - callback->fall_time = 1; - callback->u.std.press_fct = press_fct; - callback->u.std.press_data = press_data; - callback->u.std.release_fct = release_fct; - callback->u.std.release_data = release_data; - list_add(&callback->list, &logical_inputs); - return callback; -} -#endif - -static void keypad_init(void) -{ - int keynum; - - init_waitqueue_head(&keypad_read_wait); - keypad_buflen = 0; /* flushes any eventual noisy keystroke */ - - /* Let's create all known keys */ - - for (keynum = 0; keypad_profile[keynum][0][0]; keynum++) { - panel_bind_key(keypad_profile[keynum][0], - keypad_profile[keynum][1], - keypad_profile[keynum][2], - keypad_profile[keynum][3]); - } - - init_scan_timer(); - keypad_initialized = 1; -} - -/**************************************************/ -/* device initialization */ -/**************************************************/ - -static int panel_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if (lcd.enabled && lcd.initialized) { - switch (code) { - case SYS_DOWN: - panel_lcd_print - ("\x0cReloading\nSystem...\x1b[Lc\x1b[Lb\x1b[L+"); - break; - case SYS_HALT: - panel_lcd_print - ("\x0cSystem Halted.\x1b[Lc\x1b[Lb\x1b[L+"); - break; - case SYS_POWER_OFF: - panel_lcd_print("\x0cPower off.\x1b[Lc\x1b[Lb\x1b[L+"); - break; - default: - break; - } - } - return NOTIFY_DONE; -} - -static struct notifier_block panel_notifier = { - panel_notify_sys, - NULL, - 0 -}; - -static void panel_attach(struct parport *port) -{ - struct pardev_cb panel_cb; - - if (port->number != parport) - return; - - if (pprt) { - pr_err("%s: port->number=%d parport=%d, already registered!\n", - __func__, port->number, parport); - return; - } - - memset(&panel_cb, 0, sizeof(panel_cb)); - panel_cb.private = &pprt; - /* panel_cb.flags = 0 should be PARPORT_DEV_EXCL? */ - - pprt = parport_register_dev_model(port, "panel", &panel_cb, 0); - if (!pprt) { - pr_err("%s: port->number=%d parport=%d, parport_register_device() failed\n", - __func__, port->number, parport); - return; - } - - if (parport_claim(pprt)) { - pr_err("could not claim access to parport%d. Aborting.\n", - parport); - goto err_unreg_device; - } - - /* must init LCD first, just in case an IRQ from the keypad is - * generated at keypad init - */ - if (lcd.enabled) { - lcd_init(); - if (misc_register(&lcd_dev)) - goto err_unreg_device; - } - - if (keypad.enabled) { - keypad_init(); - if (misc_register(&keypad_dev)) - goto err_lcd_unreg; - } - register_reboot_notifier(&panel_notifier); - return; - -err_lcd_unreg: - if (lcd.enabled) - misc_deregister(&lcd_dev); -err_unreg_device: - parport_unregister_device(pprt); - pprt = NULL; -} - -static void panel_detach(struct parport *port) -{ - if (port->number != parport) - return; - - if (!pprt) { - pr_err("%s: port->number=%d parport=%d, nothing to unregister.\n", - __func__, port->number, parport); - return; - } - if (scan_timer.function) - del_timer_sync(&scan_timer); - - if (pprt) { - if (keypad.enabled) { - misc_deregister(&keypad_dev); - keypad_initialized = 0; - } - - if (lcd.enabled) { - panel_lcd_print("\x0cLCD driver " PANEL_VERSION - "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-"); - misc_deregister(&lcd_dev); - lcd.initialized = false; - } - - /* TODO: free all input signals */ - parport_release(pprt); - parport_unregister_device(pprt); - pprt = NULL; - unregister_reboot_notifier(&panel_notifier); - } -} - -static struct parport_driver panel_driver = { - .name = "panel", - .match_port = panel_attach, - .detach = panel_detach, - .devmodel = true, -}; - -/* init function */ -static int __init panel_init_module(void) -{ - int selected_keypad_type = NOT_SET, err; - - /* take care of an eventual profile */ - switch (profile) { - case PANEL_PROFILE_CUSTOM: - /* custom profile */ - selected_keypad_type = DEFAULT_KEYPAD_TYPE; - selected_lcd_type = DEFAULT_LCD_TYPE; - break; - case PANEL_PROFILE_OLD: - /* 8 bits, 2*16, old keypad */ - selected_keypad_type = KEYPAD_TYPE_OLD; - selected_lcd_type = LCD_TYPE_OLD; - - /* TODO: This two are a little hacky, sort it out later */ - if (lcd_width == NOT_SET) - lcd_width = 16; - if (lcd_hwidth == NOT_SET) - lcd_hwidth = 16; - break; - case PANEL_PROFILE_NEW: - /* serial, 2*16, new keypad */ - selected_keypad_type = KEYPAD_TYPE_NEW; - selected_lcd_type = LCD_TYPE_KS0074; - break; - case PANEL_PROFILE_HANTRONIX: - /* 8 bits, 2*16 hantronix-like, no keypad */ - selected_keypad_type = KEYPAD_TYPE_NONE; - selected_lcd_type = LCD_TYPE_HANTRONIX; - break; - case PANEL_PROFILE_NEXCOM: - /* generic 8 bits, 2*16, nexcom keypad, eg. Nexcom. */ - selected_keypad_type = KEYPAD_TYPE_NEXCOM; - selected_lcd_type = LCD_TYPE_NEXCOM; - break; - case PANEL_PROFILE_LARGE: - /* 8 bits, 2*40, old keypad */ - selected_keypad_type = KEYPAD_TYPE_OLD; - selected_lcd_type = LCD_TYPE_OLD; - break; - } - - /* - * Overwrite selection with module param values (both keypad and lcd), - * where the deprecated params have lower prio. - */ - if (keypad_enabled != NOT_SET) - selected_keypad_type = keypad_enabled; - if (keypad_type != NOT_SET) - selected_keypad_type = keypad_type; - - keypad.enabled = (selected_keypad_type > 0); - - if (lcd_enabled != NOT_SET) - selected_lcd_type = lcd_enabled; - if (lcd_type != NOT_SET) - selected_lcd_type = lcd_type; - - lcd.enabled = (selected_lcd_type > 0); - - if (lcd.enabled) { - /* - * Init lcd struct with load-time values to preserve exact - * current functionality (at least for now). - */ - lcd.height = lcd_height; - lcd.width = lcd_width; - lcd.bwidth = lcd_bwidth; - lcd.hwidth = lcd_hwidth; - lcd.charset = lcd_charset; - lcd.proto = lcd_proto; - lcd.pins.e = lcd_e_pin; - lcd.pins.rs = lcd_rs_pin; - lcd.pins.rw = lcd_rw_pin; - lcd.pins.cl = lcd_cl_pin; - lcd.pins.da = lcd_da_pin; - lcd.pins.bl = lcd_bl_pin; - - /* Leave it for now, just in case */ - lcd.esc_seq.len = -1; - } - - switch (selected_keypad_type) { - case KEYPAD_TYPE_OLD: - keypad_profile = old_keypad_profile; - break; - case KEYPAD_TYPE_NEW: - keypad_profile = new_keypad_profile; - break; - case KEYPAD_TYPE_NEXCOM: - keypad_profile = nexcom_keypad_profile; - break; - default: - keypad_profile = NULL; - break; - } - - if (!lcd.enabled && !keypad.enabled) { - /* no device enabled, let's exit */ - pr_err("driver version " PANEL_VERSION " disabled.\n"); - return -ENODEV; - } - - err = parport_register_driver(&panel_driver); - if (err) { - pr_err("could not register with parport. Aborting.\n"); - return err; - } - - if (pprt) - pr_info("driver version " PANEL_VERSION - " registered on parport%d (io=0x%lx).\n", parport, - pprt->port->base); - else - pr_info("driver version " PANEL_VERSION - " not yet registered\n"); - return 0; -} - -static void __exit panel_cleanup_module(void) -{ - parport_unregister_driver(&panel_driver); -} - -module_init(panel_init_module); -module_exit(panel_cleanup_module); -MODULE_AUTHOR("Willy Tarreau"); -MODULE_LICENSE("GPL"); - -/* - * Local variables: - * c-indent-level: 4 - * tab-width: 8 - * End: - */ -- cgit v1.2.3 From de01e10c1571188a02b2fc3be7c3641f9d90d84b Mon Sep 17 00:00:00 2001 From: Niranjan Dighe Date: Wed, 23 Dec 2015 09:40:18 +0000 Subject: staging: lustre: Remove unused memhog functionality Remove IOC_LIBCFS_MEMHOG ioctl functionality as it is no longer needed thereby making functions like - kportal_memhog_alloc(), kportal_memhog_free() and type - struct libcfs_device_userstate unused. Signed-off-by: Niranjan Dighe Acked-by: James Simmons Reviewed-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_private.h | 5 - .../lustre/lustre/libcfs/linux/linux-module.c | 14 +-- drivers/staging/lustre/lustre/libcfs/module.c | 139 --------------------- 3 files changed, 2 insertions(+), 156 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h index a80d993b882e..dab486261154 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h @@ -387,11 +387,6 @@ int cfs_percpt_atomic_summary(atomic_t **refs); * Support for temporary event tracing with minimal Heisenberg effect. * -------------------------------------------------------------------- */ -struct libcfs_device_userstate { - int ldu_memhog_pages; - struct page *ldu_memhog_root_page; -}; - #define MKSTR(ptr) ((ptr)) ? (ptr) : "" static inline int cfs_size_round4(int val) diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c index 70a99cf019de..eccfe8bd57a2 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c @@ -98,14 +98,12 @@ int libcfs_ioctl_popdata(void *arg, void *data, int size) static int libcfs_psdev_open(struct inode *inode, struct file *file) { - struct libcfs_device_userstate **pdu = NULL; int rc = 0; if (!inode) return -EINVAL; - pdu = (struct libcfs_device_userstate **)&file->private_data; if (libcfs_psdev_ops.p_open != NULL) - rc = libcfs_psdev_ops.p_open(0, (void *)pdu); + rc = libcfs_psdev_ops.p_open(0, NULL); else return -EPERM; return rc; @@ -115,14 +113,12 @@ libcfs_psdev_open(struct inode *inode, struct file *file) static int libcfs_psdev_release(struct inode *inode, struct file *file) { - struct libcfs_device_userstate *pdu; int rc = 0; if (!inode) return -EINVAL; - pdu = file->private_data; if (libcfs_psdev_ops.p_close != NULL) - rc = libcfs_psdev_ops.p_close(0, (void *)pdu); + rc = libcfs_psdev_ops.p_close(0, NULL); else rc = -EPERM; return rc; @@ -152,14 +148,8 @@ static long libcfs_ioctl(struct file *file, return -EPERM; panic("debugctl-invoked panic"); return 0; - case IOC_LIBCFS_MEMHOG: - if (!capable(CFS_CAP_SYS_ADMIN)) - return -EPERM; - /* go thought */ } - pfile.off = 0; - pfile.private_data = file->private_data; if (libcfs_psdev_ops.p_ioctl != NULL) rc = libcfs_psdev_ops.p_ioctl(&pfile, cmd, (void *)arg); else diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c index 329d78ce272d..0067e5347884 100644 --- a/drivers/staging/lustre/lustre/libcfs/module.c +++ b/drivers/staging/lustre/lustre/libcfs/module.c @@ -68,142 +68,16 @@ MODULE_LICENSE("GPL"); static struct dentry *lnet_debugfs_root; -static void kportal_memhog_free(struct libcfs_device_userstate *ldu) -{ - struct page **level0p = &ldu->ldu_memhog_root_page; - struct page **level1p; - struct page **level2p; - int count1; - int count2; - - if (*level0p != NULL) { - - level1p = (struct page **)page_address(*level0p); - count1 = 0; - - while (count1 < PAGE_CACHE_SIZE/sizeof(struct page *) && - *level1p != NULL) { - - level2p = (struct page **)page_address(*level1p); - count2 = 0; - - while (count2 < PAGE_CACHE_SIZE/sizeof(struct page *) && - *level2p != NULL) { - - __free_page(*level2p); - ldu->ldu_memhog_pages--; - level2p++; - count2++; - } - - __free_page(*level1p); - ldu->ldu_memhog_pages--; - level1p++; - count1++; - } - - __free_page(*level0p); - ldu->ldu_memhog_pages--; - - *level0p = NULL; - } - - LASSERT(ldu->ldu_memhog_pages == 0); -} - -static int kportal_memhog_alloc(struct libcfs_device_userstate *ldu, int npages, - gfp_t flags) -{ - struct page **level0p; - struct page **level1p; - struct page **level2p; - int count1; - int count2; - - LASSERT(ldu->ldu_memhog_pages == 0); - LASSERT(ldu->ldu_memhog_root_page == NULL); - - if (npages < 0) - return -EINVAL; - - if (npages == 0) - return 0; - - level0p = &ldu->ldu_memhog_root_page; - *level0p = alloc_page(flags); - if (*level0p == NULL) - return -ENOMEM; - ldu->ldu_memhog_pages++; - - level1p = (struct page **)page_address(*level0p); - count1 = 0; - memset(level1p, 0, PAGE_CACHE_SIZE); - - while (ldu->ldu_memhog_pages < npages && - count1 < PAGE_CACHE_SIZE/sizeof(struct page *)) { - - if (cfs_signal_pending()) - return -EINTR; - - *level1p = alloc_page(flags); - if (*level1p == NULL) - return -ENOMEM; - ldu->ldu_memhog_pages++; - - level2p = (struct page **)page_address(*level1p); - count2 = 0; - memset(level2p, 0, PAGE_CACHE_SIZE); - - while (ldu->ldu_memhog_pages < npages && - count2 < PAGE_CACHE_SIZE/sizeof(struct page *)) { - - if (cfs_signal_pending()) - return -EINTR; - - *level2p = alloc_page(flags); - if (*level2p == NULL) - return -ENOMEM; - ldu->ldu_memhog_pages++; - - level2p++; - count2++; - } - - level1p++; - count1++; - } - - return 0; -} - /* called when opening /dev/device */ static int libcfs_psdev_open(unsigned long flags, void *args) { - struct libcfs_device_userstate *ldu; - try_module_get(THIS_MODULE); - - LIBCFS_ALLOC(ldu, sizeof(*ldu)); - if (ldu != NULL) { - ldu->ldu_memhog_pages = 0; - ldu->ldu_memhog_root_page = NULL; - } - *(struct libcfs_device_userstate **)args = ldu; - return 0; } /* called when closing /dev/device */ static int libcfs_psdev_release(unsigned long flags, void *args) { - struct libcfs_device_userstate *ldu; - - ldu = (struct libcfs_device_userstate *)args; - if (ldu != NULL) { - kportal_memhog_free(ldu); - LIBCFS_FREE(ldu, sizeof(*ldu)); - } - module_put(THIS_MODULE); return 0; } @@ -260,19 +134,6 @@ static int libcfs_ioctl_int(struct cfs_psdev_file *pfile, unsigned long cmd, return -EINVAL; libcfs_debug_mark_buffer(data->ioc_inlbuf1); return 0; - case IOC_LIBCFS_MEMHOG: - if (pfile->private_data == NULL) { - err = -EINVAL; - } else { - kportal_memhog_free(pfile->private_data); - /* XXX The ioc_flags is not GFP flags now, need to be fixed */ - err = kportal_memhog_alloc(pfile->private_data, - data->ioc_count, - data->ioc_flags); - if (err != 0) - kportal_memhog_free(pfile->private_data); - } - break; default: { struct libcfs_ioctl_handler *hand; -- cgit v1.2.3 From d3ae87be4ccc6d241677405f17f984f853822b1b Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 12:32:08 -0500 Subject: staging: lustre: Handle nodemask on UMP machines For UMP and SMP machines the struct cfs_cpt_table are defined differently. In the case handled by this patch nodemask is defined as a integer for the UMP case and as a pointer for the SMP case. This will cause a problem for ost_setup which reads the nodemask directly. Instead we create a UMP version of cfs_cpt_nodemask and use that in ost_setup. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4199 Reviewed-on: http://review.whamcloud.com/9219 Starting in 3.14 kernels nodemask_t was changed from a a unsigned long to a linux bitmap so more than 32 cores could be supported. Using set_bit in cfs_cpt_table_alloc no longer compiles so this patch backports bits of the node management function that use a linux bitmap back end. Cleaned up libcfs bitmap.h to use the libcfs layers memory allocation function. This was pulling in lustre related code that was not defined. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4993 Reviewed-on: http://review.whamcloud.com/10332 Signed-off-by: James Simmons Reviewed-by: Liang Zhen Reviewed-by: Li Xi Reviewed-by: Andreas Dilger Reviewed-by: Bob Glossman Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c b/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c index 933525c73da1..ba97c79a31bd 100644 --- a/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c +++ b/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c @@ -58,6 +58,7 @@ cfs_cpt_table_alloc(unsigned int ncpt) LIBCFS_ALLOC(cptab, sizeof(*cptab)); if (cptab != NULL) { cptab->ctb_version = CFS_CPU_VERSION_MAGIC; + node_set(0, cptab->ctb_nodemask); cptab->ctb_nparts = ncpt; } @@ -111,6 +112,13 @@ cfs_cpt_online(struct cfs_cpt_table *cptab, int cpt) } EXPORT_SYMBOL(cfs_cpt_online); +nodemask_t * +cfs_cpt_nodemask(struct cfs_cpt_table *cptab, int cpt) +{ + return &cptab->ctb_nodemask; +} +EXPORT_SYMBOL(cfs_cpt_cpumask); + int cfs_cpt_set_cpu(struct cfs_cpt_table *cptab, int cpt, int cpu) { -- cgit v1.2.3 From a161de8608909e8d07fb162bf3dabdbf9190c69d Mon Sep 17 00:00:00 2001 From: frank zago Date: Wed, 23 Dec 2015 12:32:11 -0500 Subject: staging: lustre: add sparse locking annotations Adds __acquires / __releases / __must_hold sparse locking annotations to several functions. Fixes sparse warnings such as: libcfs/libcfs/hash.c:127:1: warning: context imbalance in 'cfs_hash_spin_lock' - wrong count at exit libcfs/libcfs/hash.c:133:1: warning: context imbalance in 'cfs_hash_spin_unlock' - unexpected unlock libcfs/libcfs/hash.c:141:9: warning: context imbalance in 'cfs_hash_rw_lock' - wrong count at exit include/linux/rwlock_api_smp.h:221:9: warning: context imbalance in 'cfs_hash_rw_unlock' - unexpected unlock Signed-off-by: frank zago Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5396 Reviewed-on: http://review.whamcloud.com/11295 Reviewed-by: John L. Hammond Reviewed-by: Patrick Farrell Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c | 3 +-- drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c | 1 + drivers/staging/lustre/lustre/libcfs/libcfs_lock.c | 2 ++ drivers/staging/lustre/lustre/osc/osc_cache.c | 3 +++ drivers/staging/lustre/lustre/ptlrpc/client.c | 1 + 5 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index c7b9ccb13f1c..176c79b95692 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -750,8 +750,7 @@ kiblnd_setup_rd_kiov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, static int kiblnd_post_tx_locked(kib_conn_t *conn, kib_tx_t *tx, int credit) - __releases(conn->ibc_lock) - __acquires(conn->ibc_lock) + __must_hold(&conn->ibc_lock) { kib_msg_t *msg = tx->tx_msg; kib_peer_t *peer = conn->ibc_peer; diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index 477b385f15e0..a0955d21fec2 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -2336,6 +2336,7 @@ ksocknal_flush_stale_txs(ksock_peer_t *peer) static int ksocknal_send_keepalive_locked(ksock_peer_t *peer) + __must_hold(&ksocknal_data.ksnd_global_lock) { ksock_sched_t *sched; ksock_conn_t *conn; diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c b/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c index 15782d9e6aa9..32db78803d46 100644 --- a/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c +++ b/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c @@ -90,6 +90,7 @@ EXPORT_SYMBOL(cfs_percpt_lock_alloc); */ void cfs_percpt_lock(struct cfs_percpt_lock *pcl, int index) + __acquires(pcl->pcl_locks) { int ncpt = cfs_cpt_number(pcl->pcl_cptab); int i; @@ -124,6 +125,7 @@ EXPORT_SYMBOL(cfs_percpt_lock); /** unlock a CPU partition */ void cfs_percpt_unlock(struct cfs_percpt_lock *pcl, int index) + __releases(pcl->pcl_locks) { int ncpt = cfs_cpt_number(pcl->pcl_cptab); int i; diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 2229419b7184..6b5f8d0d53df 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1938,6 +1938,7 @@ static int get_write_extents(struct osc_object *obj, struct list_head *rpclist) static int osc_send_write_rpc(const struct lu_env *env, struct client_obd *cli, struct osc_object *osc) + __must_hold(osc) { LIST_HEAD(rpclist); struct osc_extent *ext; @@ -2010,6 +2011,7 @@ osc_send_write_rpc(const struct lu_env *env, struct client_obd *cli, static int osc_send_read_rpc(const struct lu_env *env, struct client_obd *cli, struct osc_object *osc) + __must_hold(osc) { struct osc_extent *ext; struct osc_extent *next; @@ -2083,6 +2085,7 @@ static struct osc_object *osc_next_obj(struct client_obd *cli) /* called with the loi list lock held */ static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli) + __must_hold(&cli->cl_loi_list_lock) { struct osc_object *osc; int rc = 0; diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index efdda09507bf..8f3c26f1398f 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -353,6 +353,7 @@ static int unpack_reply(struct ptlrpc_request *req) * If anything goes wrong just ignore it - same as if it never happened */ static int ptlrpc_at_recv_early_reply(struct ptlrpc_request *req) + __must_hold(&req->rq_lock) { struct ptlrpc_request *early_req; time64_t olddl; -- cgit v1.2.3 From 9581c2c44e73d7876d3836e3b09811493e65279e Mon Sep 17 00:00:00 2001 From: Fan Yong Date: Wed, 23 Dec 2015 12:32:10 -0500 Subject: staging: lustre: add debugging ability for LFSCK Add the ability to debug LFSCK to libcfs. This is broken out of patch http://review.whamcloud.com/6321. Signed-off-by: Fan Yong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2914 Reviewed-on: http://review.whamcloud.com/6321 Reviewed-by: Alex Zhuravlev Reviewed-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h | 2 +- drivers/staging/lustre/lustre/libcfs/debug.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h index a1787bb43483..98430e7108c1 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h @@ -106,7 +106,7 @@ struct ptldebug_header { #define S_LOV 0x00020000 #define S_LQUOTA 0x00040000 #define S_OSD 0x00080000 -/* unused */ +#define S_LFSCK 0x00100000 /* unused */ /* unused */ #define S_LMV 0x00800000 /* b_new_cmd */ diff --git a/drivers/staging/lustre/lustre/libcfs/debug.c b/drivers/staging/lustre/lustre/libcfs/debug.c index 0b38dad13546..6274558421a8 100644 --- a/drivers/staging/lustre/lustre/libcfs/debug.c +++ b/drivers/staging/lustre/lustre/libcfs/debug.c @@ -271,6 +271,8 @@ libcfs_debug_subsys2str(int subsys) return "lquota"; case S_OSD: return "osd"; + case S_LFSCK: + return "lfsck"; case S_LMV: return "lmv"; case S_SEC: -- cgit v1.2.3 From 0d8be841081a90b7f73436668a42ebcecc5ca229 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 12:32:09 -0500 Subject: staging: lustre: Use kernel's strncasecmp and remove cfs_get_blocked_sigs Remove libcfs function cfs_strncasecmp() since the kernel already has its own strncasecmp(). Lastly remove from libcfs.h cfs_get_blocked_sigs() since this function no longer exist. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3963 Reviewed-on: http://review.whamcloud.com/13070 Reviewed-by: John L. Hammond Reviewed-by: Bob Glossman Reviewed-by: Patrick Farrell Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs.h | 1 - drivers/staging/lustre/include/linux/libcfs/libcfs_string.h | 2 -- 2 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 0d8a91ee5ffc..1574ae24f46c 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -90,7 +90,6 @@ void cfs_enter_debugger(void); * Defined by platform */ int unshare_fs_struct(void); -sigset_t cfs_get_blocked_sigs(void); sigset_t cfs_block_allsigs(void); sigset_t cfs_block_sigs(unsigned long sigs); sigset_t cfs_block_sigsinv(unsigned long sigs); diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h index d8d2e7dc212e..e02cde5aeca1 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h @@ -44,8 +44,6 @@ #define __LIBCFS_STRING_H__ /* libcfs_string.c */ -/* string comparison ignoring case */ -int cfs_strncasecmp(const char *s1, const char *s2, size_t n); /* Convert a text string to a bitmask */ int cfs_str2mask(const char *str, const char *(*bit2str)(int bit), int *oldmask, int minmask, int allmask); -- cgit v1.2.3 From 8b88bcabca1e10d4e7e42f9ad7cefc2aed56d8b1 Mon Sep 17 00:00:00 2001 From: Fan Yong Date: Wed, 23 Dec 2015 12:32:12 -0500 Subject: staging: lustre: enum lu_object_header_flags comma style fix Cleanup the a style issues for the lu_object_header_flags enum by adding a comma for the last field. This is broken out of patch http://review.whamcloud.com/6321. Signed-off-by: Fan Yong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2914 Reviewed-on: http://review.whamcloud.com/6321 Reviewed-by: Alex Zhuravlev Reviewed-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lu_object.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index 1d79341a495d..ee1dbb257d5d 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -488,7 +488,7 @@ enum lu_object_header_flags { /** * Mark this object has already been taken out of cache. */ - LU_OBJECT_UNHASHED = 1 + LU_OBJECT_UNHASHED = 1, }; enum lu_object_header_attr { -- cgit v1.2.3 From 50a10043fd4c12c008bc607d30a72b59d2f2dee9 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:40 -0500 Subject: staging: lustre: kg_sem semaphore handling is incorrectly During the removal of the cfs wrappers the kg_sem semaphore was handled incorrectly. We need to take a write lock when writing data to the kkuc_groups. The libcfs_kkuc_group_foreach needs to only take a read lock. This makes use match the OpenSFS development branch. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c index d8230aec9a2b..1a052ac8524d 100644 --- a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c +++ b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c @@ -186,7 +186,7 @@ int libcfs_kkuc_group_put(int group, void *payload) int rc = 0; int one_success = 0; - down_read(&kg_sem); + down_write(&kg_sem); list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { if (reg->kr_fp != NULL) { rc = libcfs_kkuc_msg_put(reg->kr_fp, payload); @@ -198,7 +198,7 @@ int libcfs_kkuc_group_put(int group, void *payload) } } } - up_read(&kg_sem); + up_write(&kg_sem); /* don't return an error if the message has been delivered * at least to one agent */ @@ -230,12 +230,12 @@ int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, if (kkuc_groups[group].next == NULL) return 0; - down_write(&kg_sem); + down_read(&kg_sem); list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { if (reg->kr_fp != NULL) rc = cb_func(reg->kr_data, cb_arg); } - up_write(&kg_sem); + up_read(&kg_sem); return rc; } -- cgit v1.2.3 From 406fc91338d6848a1dda0e1851dffa5946817e7e Mon Sep 17 00:00:00 2001 From: Henri Doreau Date: Wed, 23 Dec 2015 16:24:41 -0500 Subject: staging: lustre: Prevent duplicate CT registrations Associate copytool registration to a given MDC import so that multiple mounts of the same filesystem do not lead to having the copytool registered multiple time. Signed-off-by: Henri Doreau Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3882 Reviewed-on: http://review.whamcloud.com/7612 Reviewed-by: John L. Hammond Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/libcfs_kernelcomm.h | 6 ++-- .../staging/lustre/lustre/include/lustre_export.h | 7 ++++ .../lustre/lustre/libcfs/kernel_user_comm.c | 15 +++++---- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 39 ++++++++++++++++------ drivers/staging/lustre/lustre/mdc/mdc_request.c | 22 +++++++----- 5 files changed, 62 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h index 41f3d810aea4..3a89a3ba4553 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h @@ -77,7 +77,7 @@ enum kuc_generic_message_type { }; /* prototype for callback function on kuc groups */ -typedef int (*libcfs_kkuc_cb_t)(__u32 data, void *cb_arg); +typedef int (*libcfs_kkuc_cb_t)(void *data, void *cb_arg); /* KUC Broadcast Groups. This determines which userspace process hears which * messages. Mutliple transports may be used within a group, or multiple @@ -92,8 +92,8 @@ typedef int (*libcfs_kkuc_cb_t)(__u32 data, void *cb_arg); int libcfs_kkuc_msg_put(struct file *fp, void *payload); int libcfs_kkuc_group_put(int group, void *payload); int libcfs_kkuc_group_add(struct file *fp, int uid, unsigned int group, - __u32 data); -int libcfs_kkuc_group_rem(int uid, int group); + void *data); +int libcfs_kkuc_group_rem(int uid, int group, void **pdata); int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, void *cb_arg); diff --git a/drivers/staging/lustre/lustre/include/lustre_export.h b/drivers/staging/lustre/lustre/include/lustre_export.h index 311e5aa9b0db..a030a98f5656 100644 --- a/drivers/staging/lustre/lustre/include/lustre_export.h +++ b/drivers/staging/lustre/lustre/include/lustre_export.h @@ -338,6 +338,13 @@ static inline bool imp_connect_disp_stripe(struct obd_import *imp) struct obd_export *class_conn2export(struct lustre_handle *conn); +#define KKUC_CT_DATA_MAGIC 0x092013cea +struct kkuc_ct_data { + __u32 kcd_magic; + struct obd_uuid kcd_uuid; + __u32 kcd_archive; +}; + /** @} export */ #endif /* __EXPORT_H */ diff --git a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c index 1a052ac8524d..3b4731aff9ed 100644 --- a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c +++ b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c @@ -95,10 +95,10 @@ EXPORT_SYMBOL(libcfs_kkuc_msg_put); * group from any fs */ /** A single group registration has a uid and a file pointer */ struct kkuc_reg { - struct list_head kr_chain; - int kr_uid; + struct list_head kr_chain; + int kr_uid; struct file *kr_fp; - __u32 kr_data; + void *kr_data; }; static struct list_head kkuc_groups[KUC_GRP_MAX+1] = {}; @@ -109,9 +109,10 @@ static DECLARE_RWSEM(kg_sem); * @param filp pipe to write into * @param uid identifier for this receiver * @param group group number + * @param data user data */ int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, - __u32 data) + void *data) { struct kkuc_reg *reg; @@ -145,7 +146,7 @@ int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, } EXPORT_SYMBOL(libcfs_kkuc_group_add); -int libcfs_kkuc_group_rem(int uid, int group) +int libcfs_kkuc_group_rem(int uid, int group, void **pdata) { struct kkuc_reg *reg, *next; @@ -171,6 +172,8 @@ int libcfs_kkuc_group_rem(int uid, int group) reg->kr_uid, reg->kr_fp, group); if (reg->kr_fp != NULL) fput(reg->kr_fp); + if (pdata) + *pdata = reg->kr_data; kfree(reg); } } @@ -213,7 +216,7 @@ EXPORT_SYMBOL(libcfs_kkuc_group_put); * Calls a callback function for each link of the given kuc group. * @param group the group to call the function on. * @param cb_func the function to be called. - * @param cb_arg iextra argument to be passed to the callback function. + * @param cb_arg extra argument to be passed to the callback function. */ int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, void *cb_arg) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index bbafe0a710d8..e2f181edf68f 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -794,7 +794,9 @@ static void lmv_hsm_req_build(struct lmv_obd *lmv, static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len, struct lustre_kernelcomm *lk, void *uarg) { - int i, rc = 0; + struct kkuc_ct_data *kcd = NULL; + int rc = 0; + __u32 i; /* unregister request (call from llapi_hsm_copytool_fini) */ for (i = 0; i < lmv->desc.ld_tgt_count; i++) { @@ -807,17 +809,21 @@ static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len, * Unreached coordinators will get EPIPE on next requests * and will unregister automatically. */ - rc = libcfs_kkuc_group_rem(lk->lk_uid, lk->lk_group); + rc = libcfs_kkuc_group_rem(lk->lk_uid, lk->lk_group, (void **)&kcd); + if (kcd) + kfree(kcd); + return rc; } static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, struct lustre_kernelcomm *lk, void *uarg) { - struct file *filp; - int i, j, err; - int rc = 0; - bool any_set = false; + struct file *filp; + __u32 i, j; + int err, rc = 0; + bool any_set = false; + struct kkuc_ct_data *kcd; /* All or nothing: try to register to all MDS. * In case of failure, unregister from previous MDS, @@ -854,12 +860,25 @@ static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, /* at least one registration done, with no failure */ filp = fget(lk->lk_wfd); - if (filp == NULL) { + if (!filp) return -EBADF; - } - rc = libcfs_kkuc_group_add(filp, lk->lk_uid, lk->lk_group, lk->lk_data); - if (rc != 0 && filp != NULL) + + kcd = kzalloc(sizeof(*kcd), GFP_NOFS); + if (!kcd) { fput(filp); + return -ENOMEM; + } + kcd->kcd_magic = KKUC_CT_DATA_MAGIC; + kcd->kcd_uuid = lmv->cluuid; + kcd->kcd_archive = lk->lk_data; + + rc = libcfs_kkuc_group_add(filp, lk->lk_uid, lk->lk_group, kcd); + if (rc) { + if (filp) + fput(filp); + kfree(kcd); + } + return rc; } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 57e0fc1e8549..1936b491e59a 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -2013,21 +2013,27 @@ static int mdc_hsm_copytool_send(int len, void *val) /** * callback function passed to kuc for re-registering each HSM copytool * running on MDC, after MDT shutdown/recovery. - * @param data archive id served by the copytool + * @param data copytool registration data * @param cb_arg callback argument (obd_import) */ -static int mdc_hsm_ct_reregister(__u32 data, void *cb_arg) +static int mdc_hsm_ct_reregister(void *data, void *cb_arg) { + struct kkuc_ct_data *kcd = data; struct obd_import *imp = (struct obd_import *)cb_arg; - __u32 archive = data; int rc; - CDEBUG(D_HA, "recover copytool registration to MDT (archive=%#x)\n", - archive); - rc = mdc_ioc_hsm_ct_register(imp, archive); + if (!kcd || kcd->kcd_magic != KKUC_CT_DATA_MAGIC) + return -EPROTO; + + if (!obd_uuid_equals(&kcd->kcd_uuid, &imp->imp_obd->obd_uuid)) + return 0; + + CDEBUG(D_HA, "%s: recover copytool registration to MDT (archive=%#x)\n", + imp->imp_obd->obd_name, kcd->kcd_archive); + rc = mdc_ioc_hsm_ct_register(imp, kcd->kcd_archive); /* ignore error if the copytool is already registered */ - return ((rc != 0) && (rc != -EEXIST)) ? rc : 0; + return (rc == -EEXIST) ? 0 : rc; } static int mdc_set_info_async(const struct lu_env *env, @@ -2369,7 +2375,7 @@ static int mdc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) case OBD_CLEANUP_EXPORTS: /* Failsafe, ok if racy */ if (obd->obd_type->typ_refcnt <= 1) - libcfs_kkuc_group_rem(0, KUC_GRP_HSM); + libcfs_kkuc_group_rem(0, KUC_GRP_HSM, NULL); obd_cleanup_client_import(obd); ptlrpc_lprocfs_unregister_obd(obd); -- cgit v1.2.3 From db953dad0ceb8a25a4f6669edef1dd5c12d72f94 Mon Sep 17 00:00:00 2001 From: frank zago Date: Wed, 23 Dec 2015 16:24:42 -0500 Subject: staging: lustre: move kernel_user_comm.c from libcfs to lustre Move the kernel portion from libcfs to obdclass. This code is only used by lustre. This is broken out of the original patch 14270. The part covered by this change is as follows: The original code in kernel_user_comm.c is split into two parts: * obdclass/kernelcomm.c for the kernel part. filp_user_write() was moved there, and linux-fs.c deleted; * liblustreapi_kernelconn.c for the user part. The calls to CDEBUG have been removed, and calls to CERROR have been transformed to llapi_err_noerrno. The type lustre_kernelcomm has been removed and replace by struct lustre_kernelcomm. Various names and filenames have been harmonized to *kernelcomm*. Signed-off-by: frank zago Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/14270 Reviewed-by: Nathan Rutman Reviewed-by: James Simmons Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/Makefile | 5 +- .../lustre/lustre/libcfs/kernel_user_comm.c | 245 --------------------- drivers/staging/lustre/lustre/obdclass/Makefile | 10 +- .../staging/lustre/lustre/obdclass/kernelcomm.c | 245 +++++++++++++++++++++ 4 files changed, 252 insertions(+), 253 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c create mode 100644 drivers/staging/lustre/lustre/obdclass/kernelcomm.c (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/libcfs/Makefile b/drivers/staging/lustre/lustre/libcfs/Makefile index 03d3f3d7b1f8..277c1235eb32 100644 --- a/drivers/staging/lustre/lustre/libcfs/Makefile +++ b/drivers/staging/lustre/lustre/libcfs/Makefile @@ -11,8 +11,7 @@ libcfs-linux-objs += linux-mem.o libcfs-linux-objs := $(addprefix linux/,$(libcfs-linux-objs)) libcfs-all-objs := debug.o fail.o module.o tracefile.o \ - libcfs_string.o hash.o kernel_user_comm.o \ - prng.o workitem.o libcfs_cpu.o \ - libcfs_mem.o libcfs_lock.o + libcfs_string.o hash.o prng.o workitem.o \ + libcfs_cpu.o libcfs_mem.o libcfs_lock.o libcfs-objs := $(libcfs-linux-objs) $(libcfs-all-objs) diff --git a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c deleted file mode 100644 index 3b4731aff9ed..000000000000 --- a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * 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 version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * Author: Nathan Rutman - * - * Kernel <-> userspace communication routines. - * Using pipes for all arches. - */ - -#define DEBUG_SUBSYSTEM S_CLASS -#define D_KUC D_OTHER - -#include "../../include/linux/libcfs/libcfs.h" - -/* This is the kernel side (liblustre as well). */ - -/** - * libcfs_kkuc_msg_put - send an message from kernel to userspace - * @param fp to send the message to - * @param payload Payload data. First field of payload is always - * struct kuc_hdr - */ -int libcfs_kkuc_msg_put(struct file *filp, void *payload) -{ - struct kuc_hdr *kuch = (struct kuc_hdr *)payload; - ssize_t count = kuch->kuc_msglen; - loff_t offset = 0; - mm_segment_t fs; - int rc = -ENOSYS; - - if (filp == NULL || IS_ERR(filp)) - return -EBADF; - - if (kuch->kuc_magic != KUC_MAGIC) { - CERROR("KernelComm: bad magic %x\n", kuch->kuc_magic); - return -ENOSYS; - } - - fs = get_fs(); - set_fs(KERNEL_DS); - while (count > 0) { - rc = vfs_write(filp, (void __force __user *)payload, - count, &offset); - if (rc < 0) - break; - count -= rc; - payload += rc; - rc = 0; - } - set_fs(fs); - - if (rc < 0) - CWARN("message send failed (%d)\n", rc); - else - CDEBUG(D_KUC, "Sent message rc=%d, fp=%p\n", rc, filp); - - return rc; -} -EXPORT_SYMBOL(libcfs_kkuc_msg_put); - -/* Broadcast groups are global across all mounted filesystems; - * i.e. registering for a group on 1 fs will get messages for that - * group from any fs */ -/** A single group registration has a uid and a file pointer */ -struct kkuc_reg { - struct list_head kr_chain; - int kr_uid; - struct file *kr_fp; - void *kr_data; -}; - -static struct list_head kkuc_groups[KUC_GRP_MAX+1] = {}; -/* Protect message sending against remove and adds */ -static DECLARE_RWSEM(kg_sem); - -/** Add a receiver to a broadcast group - * @param filp pipe to write into - * @param uid identifier for this receiver - * @param group group number - * @param data user data - */ -int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, - void *data) -{ - struct kkuc_reg *reg; - - if (group > KUC_GRP_MAX) { - CDEBUG(D_WARNING, "Kernelcomm: bad group %d\n", group); - return -EINVAL; - } - - /* fput in group_rem */ - if (filp == NULL) - return -EBADF; - - /* freed in group_rem */ - reg = kmalloc(sizeof(*reg), 0); - if (reg == NULL) - return -ENOMEM; - - reg->kr_fp = filp; - reg->kr_uid = uid; - reg->kr_data = data; - - down_write(&kg_sem); - if (kkuc_groups[group].next == NULL) - INIT_LIST_HEAD(&kkuc_groups[group]); - list_add(®->kr_chain, &kkuc_groups[group]); - up_write(&kg_sem); - - CDEBUG(D_KUC, "Added uid=%d fp=%p to group %d\n", uid, filp, group); - - return 0; -} -EXPORT_SYMBOL(libcfs_kkuc_group_add); - -int libcfs_kkuc_group_rem(int uid, int group, void **pdata) -{ - struct kkuc_reg *reg, *next; - - if (kkuc_groups[group].next == NULL) - return 0; - - if (uid == 0) { - /* Broadcast a shutdown message */ - struct kuc_hdr lh; - - lh.kuc_magic = KUC_MAGIC; - lh.kuc_transport = KUC_TRANSPORT_GENERIC; - lh.kuc_msgtype = KUC_MSG_SHUTDOWN; - lh.kuc_msglen = sizeof(lh); - libcfs_kkuc_group_put(group, &lh); - } - - down_write(&kg_sem); - list_for_each_entry_safe(reg, next, &kkuc_groups[group], kr_chain) { - if ((uid == 0) || (uid == reg->kr_uid)) { - list_del(®->kr_chain); - CDEBUG(D_KUC, "Removed uid=%d fp=%p from group %d\n", - reg->kr_uid, reg->kr_fp, group); - if (reg->kr_fp != NULL) - fput(reg->kr_fp); - if (pdata) - *pdata = reg->kr_data; - kfree(reg); - } - } - up_write(&kg_sem); - - return 0; -} -EXPORT_SYMBOL(libcfs_kkuc_group_rem); - -int libcfs_kkuc_group_put(int group, void *payload) -{ - struct kkuc_reg *reg; - int rc = 0; - int one_success = 0; - - down_write(&kg_sem); - list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { - if (reg->kr_fp != NULL) { - rc = libcfs_kkuc_msg_put(reg->kr_fp, payload); - if (rc == 0) - one_success = 1; - else if (rc == -EPIPE) { - fput(reg->kr_fp); - reg->kr_fp = NULL; - } - } - } - up_write(&kg_sem); - - /* don't return an error if the message has been delivered - * at least to one agent */ - if (one_success) - rc = 0; - - return rc; -} -EXPORT_SYMBOL(libcfs_kkuc_group_put); - -/** - * Calls a callback function for each link of the given kuc group. - * @param group the group to call the function on. - * @param cb_func the function to be called. - * @param cb_arg extra argument to be passed to the callback function. - */ -int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, - void *cb_arg) -{ - struct kkuc_reg *reg; - int rc = 0; - - if (group > KUC_GRP_MAX) { - CDEBUG(D_WARNING, "Kernelcomm: bad group %d\n", group); - return -EINVAL; - } - - /* no link for this group */ - if (kkuc_groups[group].next == NULL) - return 0; - - down_read(&kg_sem); - list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { - if (reg->kr_fp != NULL) - rc = cb_func(reg->kr_data, cb_arg); - } - up_read(&kg_sem); - - return rc; -} -EXPORT_SYMBOL(libcfs_kkuc_group_foreach); diff --git a/drivers/staging/lustre/lustre/obdclass/Makefile b/drivers/staging/lustre/lustre/obdclass/Makefile index acc685712ce9..c404eb3864ff 100644 --- a/drivers/staging/lustre/lustre/obdclass/Makefile +++ b/drivers/staging/lustre/lustre/obdclass/Makefile @@ -2,8 +2,8 @@ obj-$(CONFIG_LUSTRE_FS) += obdclass.o obdclass-y := linux/linux-module.o linux/linux-obdo.o linux/linux-sysctl.o \ llog.o llog_cat.o llog_obd.o llog_swab.o class_obd.o debug.o \ - genops.o uuid.o lprocfs_status.o \ - lustre_handles.o lustre_peer.o \ - statfs_pack.o obdo.o obd_config.o obd_mount.o \ - lu_object.o cl_object.o \ - cl_page.o cl_lock.o cl_io.o lu_ref.o acl.o lprocfs_counters.o + genops.o uuid.o lprocfs_status.o lprocfs_counters.o \ + lustre_handles.o lustre_peer.o statfs_pack.o \ + obdo.o obd_config.o obd_mount.o lu_object.o lu_ref.o \ + cl_object.o cl_page.o cl_lock.o cl_io.o \ + acl.o kernelcomm.o diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c new file mode 100644 index 000000000000..3b4731aff9ed --- /dev/null +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -0,0 +1,245 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * 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 version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + * GPL HEADER END + */ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 2012, Intel Corporation. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Sun Microsystems, Inc. + * + * Author: Nathan Rutman + * + * Kernel <-> userspace communication routines. + * Using pipes for all arches. + */ + +#define DEBUG_SUBSYSTEM S_CLASS +#define D_KUC D_OTHER + +#include "../../include/linux/libcfs/libcfs.h" + +/* This is the kernel side (liblustre as well). */ + +/** + * libcfs_kkuc_msg_put - send an message from kernel to userspace + * @param fp to send the message to + * @param payload Payload data. First field of payload is always + * struct kuc_hdr + */ +int libcfs_kkuc_msg_put(struct file *filp, void *payload) +{ + struct kuc_hdr *kuch = (struct kuc_hdr *)payload; + ssize_t count = kuch->kuc_msglen; + loff_t offset = 0; + mm_segment_t fs; + int rc = -ENOSYS; + + if (filp == NULL || IS_ERR(filp)) + return -EBADF; + + if (kuch->kuc_magic != KUC_MAGIC) { + CERROR("KernelComm: bad magic %x\n", kuch->kuc_magic); + return -ENOSYS; + } + + fs = get_fs(); + set_fs(KERNEL_DS); + while (count > 0) { + rc = vfs_write(filp, (void __force __user *)payload, + count, &offset); + if (rc < 0) + break; + count -= rc; + payload += rc; + rc = 0; + } + set_fs(fs); + + if (rc < 0) + CWARN("message send failed (%d)\n", rc); + else + CDEBUG(D_KUC, "Sent message rc=%d, fp=%p\n", rc, filp); + + return rc; +} +EXPORT_SYMBOL(libcfs_kkuc_msg_put); + +/* Broadcast groups are global across all mounted filesystems; + * i.e. registering for a group on 1 fs will get messages for that + * group from any fs */ +/** A single group registration has a uid and a file pointer */ +struct kkuc_reg { + struct list_head kr_chain; + int kr_uid; + struct file *kr_fp; + void *kr_data; +}; + +static struct list_head kkuc_groups[KUC_GRP_MAX+1] = {}; +/* Protect message sending against remove and adds */ +static DECLARE_RWSEM(kg_sem); + +/** Add a receiver to a broadcast group + * @param filp pipe to write into + * @param uid identifier for this receiver + * @param group group number + * @param data user data + */ +int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, + void *data) +{ + struct kkuc_reg *reg; + + if (group > KUC_GRP_MAX) { + CDEBUG(D_WARNING, "Kernelcomm: bad group %d\n", group); + return -EINVAL; + } + + /* fput in group_rem */ + if (filp == NULL) + return -EBADF; + + /* freed in group_rem */ + reg = kmalloc(sizeof(*reg), 0); + if (reg == NULL) + return -ENOMEM; + + reg->kr_fp = filp; + reg->kr_uid = uid; + reg->kr_data = data; + + down_write(&kg_sem); + if (kkuc_groups[group].next == NULL) + INIT_LIST_HEAD(&kkuc_groups[group]); + list_add(®->kr_chain, &kkuc_groups[group]); + up_write(&kg_sem); + + CDEBUG(D_KUC, "Added uid=%d fp=%p to group %d\n", uid, filp, group); + + return 0; +} +EXPORT_SYMBOL(libcfs_kkuc_group_add); + +int libcfs_kkuc_group_rem(int uid, int group, void **pdata) +{ + struct kkuc_reg *reg, *next; + + if (kkuc_groups[group].next == NULL) + return 0; + + if (uid == 0) { + /* Broadcast a shutdown message */ + struct kuc_hdr lh; + + lh.kuc_magic = KUC_MAGIC; + lh.kuc_transport = KUC_TRANSPORT_GENERIC; + lh.kuc_msgtype = KUC_MSG_SHUTDOWN; + lh.kuc_msglen = sizeof(lh); + libcfs_kkuc_group_put(group, &lh); + } + + down_write(&kg_sem); + list_for_each_entry_safe(reg, next, &kkuc_groups[group], kr_chain) { + if ((uid == 0) || (uid == reg->kr_uid)) { + list_del(®->kr_chain); + CDEBUG(D_KUC, "Removed uid=%d fp=%p from group %d\n", + reg->kr_uid, reg->kr_fp, group); + if (reg->kr_fp != NULL) + fput(reg->kr_fp); + if (pdata) + *pdata = reg->kr_data; + kfree(reg); + } + } + up_write(&kg_sem); + + return 0; +} +EXPORT_SYMBOL(libcfs_kkuc_group_rem); + +int libcfs_kkuc_group_put(int group, void *payload) +{ + struct kkuc_reg *reg; + int rc = 0; + int one_success = 0; + + down_write(&kg_sem); + list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { + if (reg->kr_fp != NULL) { + rc = libcfs_kkuc_msg_put(reg->kr_fp, payload); + if (rc == 0) + one_success = 1; + else if (rc == -EPIPE) { + fput(reg->kr_fp); + reg->kr_fp = NULL; + } + } + } + up_write(&kg_sem); + + /* don't return an error if the message has been delivered + * at least to one agent */ + if (one_success) + rc = 0; + + return rc; +} +EXPORT_SYMBOL(libcfs_kkuc_group_put); + +/** + * Calls a callback function for each link of the given kuc group. + * @param group the group to call the function on. + * @param cb_func the function to be called. + * @param cb_arg extra argument to be passed to the callback function. + */ +int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, + void *cb_arg) +{ + struct kkuc_reg *reg; + int rc = 0; + + if (group > KUC_GRP_MAX) { + CDEBUG(D_WARNING, "Kernelcomm: bad group %d\n", group); + return -EINVAL; + } + + /* no link for this group */ + if (kkuc_groups[group].next == NULL) + return 0; + + down_read(&kg_sem); + list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { + if (reg->kr_fp != NULL) + rc = cb_func(reg->kr_data, cb_arg); + } + up_read(&kg_sem); + + return rc; +} +EXPORT_SYMBOL(libcfs_kkuc_group_foreach); -- cgit v1.2.3 From e2780478fe011f80ef9d872e3b6941f946dcb6b2 Mon Sep 17 00:00:00 2001 From: frank zago Date: Wed, 23 Dec 2015 16:24:43 -0500 Subject: staging: lustre: split kernel comm between user and kernel Split the kernel comm header in libcfs into two new headers to handle both kernel space and user space for the lustre layer. This is broken out of the original patch 14270. The part covered by this change is as follows: The original libcfs_kernelcomm.h header is split into three parts: * lustre_kernelcomm.h, a new header for the kernel parts; * uapi_kernelcomm.h, a new header for the data structures shared between userspace and kernelspace; * lustreapi_internal.h receives the private liblustreapi prototypes. Various names and filenames have been harmonized to *kernelcomm*. The unused symbol KUC_FL_BLOCK has been removed. Signed-off-by: frank zago Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/14270 Reviewed-by: Nathan Rutman Reviewed-by: James Simmons Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/include/linux/libcfs/libcfs.h | 1 - .../include/linux/libcfs/libcfs_kernelcomm.h | 118 --------------------- .../lustre/lustre/include/lustre_kernelcomm.h | 55 ++++++++++ .../lustre/lustre/include/uapi_kernelcomm.h | 92 ++++++++++++++++ drivers/staging/lustre/lustre/llite/dir.c | 1 + drivers/staging/lustre/lustre/lmv/lmv_obd.c | 1 + drivers/staging/lustre/lustre/mdc/mdc_request.c | 1 + drivers/staging/lustre/lustre/obdclass/genops.c | 1 + .../staging/lustre/lustre/obdclass/kernelcomm.c | 5 +- 9 files changed, 153 insertions(+), 122 deletions(-) delete mode 100644 drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h create mode 100644 drivers/staging/lustre/lustre/include/lustre_kernelcomm.h create mode 100644 drivers/staging/lustre/lustre/include/uapi_kernelcomm.h (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 1574ae24f46c..094eb0f27954 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -114,7 +114,6 @@ void cfs_get_random_bytes(void *buf, int size); #include "libcfs_prim.h" #include "libcfs_time.h" #include "libcfs_string.h" -#include "libcfs_kernelcomm.h" #include "libcfs_workitem.h" #include "libcfs_hash.h" #include "libcfs_fail.h" diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h deleted file mode 100644 index 3a89a3ba4553..000000000000 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * 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 version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * Author: Nathan Rutman - * - * libcfs/include/libcfs/libcfs_kernelcomm.h - * - * Kernel <-> userspace communication routines. - * The definitions below are used in the kernel and userspace. - * - */ - -#ifndef __LIBCFS_KERNELCOMM_H__ -#define __LIBCFS_KERNELCOMM_H__ - -#ifndef __LIBCFS_LIBCFS_H__ -#error Do not #include this file directly. #include instead -#endif - -/* KUC message header. - * All current and future KUC messages should use this header. - * To avoid having to include Lustre headers from libcfs, define this here. - */ -struct kuc_hdr { - __u16 kuc_magic; - __u8 kuc_transport; /* Each new Lustre feature should use a different - transport */ - __u8 kuc_flags; - __u16 kuc_msgtype; /* Message type or opcode, transport-specific */ - __u16 kuc_msglen; /* Including header */ -} __aligned(sizeof(__u64)); - -#define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr)+CR_MAXSIZE) - -#define KUC_MAGIC 0x191C /*Lustre9etLinC */ -#define KUC_FL_BLOCK 0x01 /* Wait for send */ - -/* kuc_msgtype values are defined in each transport */ -enum kuc_transport_type { - KUC_TRANSPORT_GENERIC = 1, - KUC_TRANSPORT_HSM = 2, - KUC_TRANSPORT_CHANGELOG = 3, -}; - -enum kuc_generic_message_type { - KUC_MSG_SHUTDOWN = 1, -}; - -/* prototype for callback function on kuc groups */ -typedef int (*libcfs_kkuc_cb_t)(void *data, void *cb_arg); - -/* KUC Broadcast Groups. This determines which userspace process hears which - * messages. Mutliple transports may be used within a group, or multiple - * groups may use the same transport. Broadcast - * groups need not be used if e.g. a UID is specified instead; - * use group 0 to signify unicast. - */ -#define KUC_GRP_HSM 0x02 -#define KUC_GRP_MAX KUC_GRP_HSM - -/* Kernel methods */ -int libcfs_kkuc_msg_put(struct file *fp, void *payload); -int libcfs_kkuc_group_put(int group, void *payload); -int libcfs_kkuc_group_add(struct file *fp, int uid, unsigned int group, - void *data); -int libcfs_kkuc_group_rem(int uid, int group, void **pdata); -int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, - void *cb_arg); - -#define LK_FLG_STOP 0x01 - -/* kernelcomm control structure, passed from userspace to kernel */ -typedef struct lustre_kernelcomm { - __u32 lk_wfd; - __u32 lk_rfd; - __u32 lk_uid; - __u32 lk_group; - __u32 lk_data; - __u32 lk_flags; -} __packed lustre_kernelcomm; - -/* Userspace methods */ -int libcfs_ukuc_start(lustre_kernelcomm *l, int groups); -int libcfs_ukuc_stop(lustre_kernelcomm *l); -int libcfs_ukuc_msg_get(lustre_kernelcomm *l, char *buf, int maxsize, - int transport); - -#endif /* __LIBCFS_KERNELCOMM_H__ */ diff --git a/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h b/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h new file mode 100644 index 000000000000..9dd057cc56a5 --- /dev/null +++ b/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h @@ -0,0 +1,55 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * 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 version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 2013 Intel Corporation. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * + * Author: Nathan Rutman + * + * Kernel <-> userspace communication routines. + * The definitions below are used in the kernel and userspace. + */ + +#ifndef __LUSTRE_KERNELCOMM_H__ +#define __LUSTRE_KERNELCOMM_H__ + +/* For declarations shared with userspace */ +#include "uapi_kernelcomm.h" + +/* prototype for callback function on kuc groups */ +typedef int (*libcfs_kkuc_cb_t)(void *data, void *cb_arg); + +/* Kernel methods */ +int libcfs_kkuc_msg_put(struct file *fp, void *payload); +int libcfs_kkuc_group_put(int group, void *payload); +int libcfs_kkuc_group_add(struct file *fp, int uid, unsigned int group, + void *data); +int libcfs_kkuc_group_rem(int uid, int group, void **pdata); +int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, + void *cb_arg); + +#endif /* __LUSTRE_KERNELCOMM_H__ */ diff --git a/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h b/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h new file mode 100644 index 000000000000..5e0b8de687c1 --- /dev/null +++ b/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h @@ -0,0 +1,92 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * 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 version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 2013, Intel Corporation. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * + * Author: Nathan Rutman + * + * Kernel <-> userspace communication routines. + * The definitions below are used in the kernel and userspace. + */ + +#ifndef __UAPI_KERNELCOMM_H__ +#define __UAPI_KERNELCOMM_H__ + +#include + +/* KUC message header. + * All current and future KUC messages should use this header. + * To avoid having to include Lustre headers from libcfs, define this here. + */ +struct kuc_hdr { + __u16 kuc_magic; + __u8 kuc_transport; /* Each new Lustre feature should use a different + transport */ + __u8 kuc_flags; + __u16 kuc_msgtype; /* Message type or opcode, transport-specific */ + __u16 kuc_msglen; /* Including header */ +} __aligned(sizeof(__u64)); + +#define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr)+CR_MAXSIZE) + +#define KUC_MAGIC 0x191C /*Lustre9etLinC */ + +/* kuc_msgtype values are defined in each transport */ +enum kuc_transport_type { + KUC_TRANSPORT_GENERIC = 1, + KUC_TRANSPORT_HSM = 2, + KUC_TRANSPORT_CHANGELOG = 3, +}; + +enum kuc_generic_message_type { + KUC_MSG_SHUTDOWN = 1, +}; + +/* KUC Broadcast Groups. This determines which userspace process hears which + * messages. Mutliple transports may be used within a group, or multiple + * groups may use the same transport. Broadcast + * groups need not be used if e.g. a UID is specified instead; + * use group 0 to signify unicast. + */ +#define KUC_GRP_HSM 0x02 +#define KUC_GRP_MAX KUC_GRP_HSM + +#define LK_FLG_STOP 0x01 +#define LK_NOFD -1U + +/* kernelcomm control structure, passed from userspace to kernel */ +struct lustre_kernelcomm { + __u32 lk_wfd; + __u32 lk_rfd; + __u32 lk_uid; + __u32 lk_group; + __u32 lk_data; + __u32 lk_flags; +} __packed; + +#endif /* __UAPI_KERNELCOMM_H__ */ diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 8982f7d1b374..2a5babe555e6 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -55,6 +55,7 @@ #include "../include/lustre_lite.h" #include "../include/lustre_dlm.h" #include "../include/lustre_fid.h" +#include "../include/lustre_kernelcomm.h" #include "llite_internal.h" /* diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index e2f181edf68f..30c73c2d3f51 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -53,6 +53,7 @@ #include "../include/lprocfs_status.h" #include "../include/lustre_lite.h" #include "../include/lustre_fid.h" +#include "../include/lustre_kernelcomm.h" #include "lmv_internal.h" static void lmv_activate_target(struct lmv_obd *lmv, diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 1936b491e59a..6923acef28bd 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -48,6 +48,7 @@ #include "../include/lprocfs_status.h" #include "../include/lustre_param.h" #include "../include/lustre_log.h" +#include "../include/lustre_kernelcomm.h" #include "mdc_internal.h" diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index 228c44c37c4a..5665655fd6ee 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -42,6 +42,7 @@ #define DEBUG_SUBSYSTEM S_CLASS #include "../include/obd_class.h" #include "../include/lprocfs_status.h" +#include "../include/lustre_kernelcomm.h" spinlock_t obd_types_lock; diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index 3b4731aff9ed..e3f5a3c40331 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -42,9 +42,8 @@ #define DEBUG_SUBSYSTEM S_CLASS #define D_KUC D_OTHER -#include "../../include/linux/libcfs/libcfs.h" - -/* This is the kernel side (liblustre as well). */ +#include "../include/obd_support.h" +#include "../include/lustre_kernelcomm.h" /** * libcfs_kkuc_msg_put - send an message from kernel to userspace -- cgit v1.2.3 From 17328956b0a232c2b50e8e20a078542242759047 Mon Sep 17 00:00:00 2001 From: Hongchao Zhang Date: Wed, 23 Dec 2015 16:24:44 -0500 Subject: staging: lustre: embed kr_data into kkuc_reg In struct kkuc_reg, the "kr_data" is difficult to be freed outside of libcfs, then it's better to change it to be inline data instead of the data pointer. Signed-off-by: Hongchao Zhang Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6485 Reviewed-on: http://review.whamcloud.com/14638 Reviewed-by: John L. Hammond Reviewed-by: James Simmons Reviewed-by: frank zago Reviewed-by: Robert Read Reviewed-by: Henri Doreau Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre_kernelcomm.h | 4 ++-- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 22 +++++++--------------- drivers/staging/lustre/lustre/mdc/mdc_request.c | 2 +- .../staging/lustre/lustre/obdclass/kernelcomm.c | 12 +++++------- 4 files changed, 15 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h b/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h index 9dd057cc56a5..cfd415f7e49b 100644 --- a/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h +++ b/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h @@ -47,8 +47,8 @@ typedef int (*libcfs_kkuc_cb_t)(void *data, void *cb_arg); int libcfs_kkuc_msg_put(struct file *fp, void *payload); int libcfs_kkuc_group_put(int group, void *payload); int libcfs_kkuc_group_add(struct file *fp, int uid, unsigned int group, - void *data); -int libcfs_kkuc_group_rem(int uid, int group, void **pdata); + void *data, size_t data_len); +int libcfs_kkuc_group_rem(int uid, int group); int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, void *cb_arg); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 30c73c2d3f51..9ebfb39a8188 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -795,7 +795,6 @@ static void lmv_hsm_req_build(struct lmv_obd *lmv, static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len, struct lustre_kernelcomm *lk, void *uarg) { - struct kkuc_ct_data *kcd = NULL; int rc = 0; __u32 i; @@ -810,9 +809,7 @@ static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len, * Unreached coordinators will get EPIPE on next requests * and will unregister automatically. */ - rc = libcfs_kkuc_group_rem(lk->lk_uid, lk->lk_group, (void **)&kcd); - if (kcd) - kfree(kcd); + rc = libcfs_kkuc_group_rem(lk->lk_uid, lk->lk_group); return rc; } @@ -824,7 +821,7 @@ static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, __u32 i, j; int err, rc = 0; bool any_set = false; - struct kkuc_ct_data *kcd; + struct kkuc_ct_data kcd = { 0 }; /* All or nothing: try to register to all MDS. * In case of failure, unregister from previous MDS, @@ -864,20 +861,15 @@ static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, if (!filp) return -EBADF; - kcd = kzalloc(sizeof(*kcd), GFP_NOFS); - if (!kcd) { - fput(filp); - return -ENOMEM; - } - kcd->kcd_magic = KKUC_CT_DATA_MAGIC; - kcd->kcd_uuid = lmv->cluuid; - kcd->kcd_archive = lk->lk_data; + kcd.kcd_magic = KKUC_CT_DATA_MAGIC; + kcd.kcd_uuid = lmv->cluuid; + kcd.kcd_archive = lk->lk_data; - rc = libcfs_kkuc_group_add(filp, lk->lk_uid, lk->lk_group, kcd); + rc = libcfs_kkuc_group_add(filp, lk->lk_uid, lk->lk_group, + &kcd, sizeof(kcd)); if (rc) { if (filp) fput(filp); - kfree(kcd); } return rc; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 6923acef28bd..3929f9129c8b 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -2376,7 +2376,7 @@ static int mdc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) case OBD_CLEANUP_EXPORTS: /* Failsafe, ok if racy */ if (obd->obd_type->typ_refcnt <= 1) - libcfs_kkuc_group_rem(0, KUC_GRP_HSM, NULL); + libcfs_kkuc_group_rem(0, KUC_GRP_HSM); obd_cleanup_client_import(obd); ptlrpc_lprocfs_unregister_obd(obd); diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index e3f5a3c40331..e29024655286 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -97,7 +97,7 @@ struct kkuc_reg { struct list_head kr_chain; int kr_uid; struct file *kr_fp; - void *kr_data; + char kr_data[0]; }; static struct list_head kkuc_groups[KUC_GRP_MAX+1] = {}; @@ -111,7 +111,7 @@ static DECLARE_RWSEM(kg_sem); * @param data user data */ int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, - void *data) + void *data, size_t data_len) { struct kkuc_reg *reg; @@ -125,13 +125,13 @@ int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, return -EBADF; /* freed in group_rem */ - reg = kmalloc(sizeof(*reg), 0); + reg = kmalloc(sizeof(*reg) + data_len, 0); if (reg == NULL) return -ENOMEM; reg->kr_fp = filp; reg->kr_uid = uid; - reg->kr_data = data; + memcpy(reg->kr_data, data, data_len); down_write(&kg_sem); if (kkuc_groups[group].next == NULL) @@ -145,7 +145,7 @@ int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, } EXPORT_SYMBOL(libcfs_kkuc_group_add); -int libcfs_kkuc_group_rem(int uid, int group, void **pdata) +int libcfs_kkuc_group_rem(int uid, int group) { struct kkuc_reg *reg, *next; @@ -171,8 +171,6 @@ int libcfs_kkuc_group_rem(int uid, int group, void **pdata) reg->kr_uid, reg->kr_fp, group); if (reg->kr_fp != NULL) fput(reg->kr_fp); - if (pdata) - *pdata = reg->kr_data; kfree(reg); } } -- cgit v1.2.3 From 16b376bbef5167783721d10fc633d8f2e698274c Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:45 -0500 Subject: staging: lustre: convert kernelcomm group to unsigned int The group variable was converted to an unsigned int in libcfs_kkuc_group_add() to avoid a potential overflow. The variable group is used in other kernelcomm functions so it makes sense to convert the rest of the group variables to unsigned int. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_kernelcomm.h | 6 +++--- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h b/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h index cfd415f7e49b..970610b6de89 100644 --- a/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h +++ b/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h @@ -45,11 +45,11 @@ typedef int (*libcfs_kkuc_cb_t)(void *data, void *cb_arg); /* Kernel methods */ int libcfs_kkuc_msg_put(struct file *fp, void *payload); -int libcfs_kkuc_group_put(int group, void *payload); +int libcfs_kkuc_group_put(unsigned int group, void *payload); int libcfs_kkuc_group_add(struct file *fp, int uid, unsigned int group, void *data, size_t data_len); -int libcfs_kkuc_group_rem(int uid, int group); -int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, +int libcfs_kkuc_group_rem(int uid, unsigned int group); +int libcfs_kkuc_group_foreach(unsigned int group, libcfs_kkuc_cb_t cb_func, void *cb_arg); #endif /* __LUSTRE_KERNELCOMM_H__ */ diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index e29024655286..1081253eefef 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -145,7 +145,7 @@ int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, } EXPORT_SYMBOL(libcfs_kkuc_group_add); -int libcfs_kkuc_group_rem(int uid, int group) +int libcfs_kkuc_group_rem(int uid, unsigned int group) { struct kkuc_reg *reg, *next; @@ -180,7 +180,7 @@ int libcfs_kkuc_group_rem(int uid, int group) } EXPORT_SYMBOL(libcfs_kkuc_group_rem); -int libcfs_kkuc_group_put(int group, void *payload) +int libcfs_kkuc_group_put(unsigned int group, void *payload) { struct kkuc_reg *reg; int rc = 0; @@ -215,7 +215,7 @@ EXPORT_SYMBOL(libcfs_kkuc_group_put); * @param cb_func the function to be called. * @param cb_arg extra argument to be passed to the callback function. */ -int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, +int libcfs_kkuc_group_foreach(unsigned int group, libcfs_kkuc_cb_t cb_func, void *cb_arg) { struct kkuc_reg *reg; -- cgit v1.2.3 From fb81e732440d08da9d7ec7f7ac189f8bdd51b8c6 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:46 -0500 Subject: staging: lustre: remove unnecessary NULL checks in kernel_comm.c Fix checkpatch.pl reports of NULL comparison in kernel_comm.c. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index 1081253eefef..c9405e689862 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -59,7 +59,7 @@ int libcfs_kkuc_msg_put(struct file *filp, void *payload) mm_segment_t fs; int rc = -ENOSYS; - if (filp == NULL || IS_ERR(filp)) + if (!filp || IS_ERR(filp)) return -EBADF; if (kuch->kuc_magic != KUC_MAGIC) { @@ -121,12 +121,12 @@ int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, } /* fput in group_rem */ - if (filp == NULL) + if (!filp) return -EBADF; /* freed in group_rem */ reg = kmalloc(sizeof(*reg) + data_len, 0); - if (reg == NULL) + if (!reg) return -ENOMEM; reg->kr_fp = filp; @@ -134,7 +134,7 @@ int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, memcpy(reg->kr_data, data, data_len); down_write(&kg_sem); - if (kkuc_groups[group].next == NULL) + if (!kkuc_groups[group].next) INIT_LIST_HEAD(&kkuc_groups[group]); list_add(®->kr_chain, &kkuc_groups[group]); up_write(&kg_sem); @@ -149,7 +149,7 @@ int libcfs_kkuc_group_rem(int uid, unsigned int group) { struct kkuc_reg *reg, *next; - if (kkuc_groups[group].next == NULL) + if (!kkuc_groups[group].next) return 0; if (uid == 0) { @@ -169,7 +169,7 @@ int libcfs_kkuc_group_rem(int uid, unsigned int group) list_del(®->kr_chain); CDEBUG(D_KUC, "Removed uid=%d fp=%p from group %d\n", reg->kr_uid, reg->kr_fp, group); - if (reg->kr_fp != NULL) + if (reg->kr_fp) fput(reg->kr_fp); kfree(reg); } @@ -188,7 +188,7 @@ int libcfs_kkuc_group_put(unsigned int group, void *payload) down_write(&kg_sem); list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { - if (reg->kr_fp != NULL) { + if (reg->kr_fp) { rc = libcfs_kkuc_msg_put(reg->kr_fp, payload); if (rc == 0) one_success = 1; @@ -227,12 +227,12 @@ int libcfs_kkuc_group_foreach(unsigned int group, libcfs_kkuc_cb_t cb_func, } /* no link for this group */ - if (kkuc_groups[group].next == NULL) + if (!kkuc_groups[group].next) return 0; down_read(&kg_sem); list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { - if (reg->kr_fp != NULL) + if (reg->kr_fp) rc = cb_func(reg->kr_data, cb_arg); } up_read(&kg_sem); -- cgit v1.2.3 From 25c450ea43333a2c47d972467b87a722cba0bb4a Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:47 -0500 Subject: staging: lustre: cleanup block comment style in kernel_comm code Fixup the comments to the linux kernel style for the source and headers related to the kernel_comm work. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/uapi_kernelcomm.h | 10 ++++++---- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 12 ++++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h b/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h index 5e0b8de687c1..a8feab616f75 100644 --- a/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h +++ b/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h @@ -45,11 +45,13 @@ */ struct kuc_hdr { __u16 kuc_magic; - __u8 kuc_transport; /* Each new Lustre feature should use a different - transport */ + /* Each new Lustre feature should use a different transport */ + __u8 kuc_transport; __u8 kuc_flags; - __u16 kuc_msgtype; /* Message type or opcode, transport-specific */ - __u16 kuc_msglen; /* Including header */ + /* Message type or opcode, transport-specific */ + __u16 kuc_msgtype; + /* Including header */ + __u16 kuc_msglen; } __aligned(sizeof(__u64)); #define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr)+CR_MAXSIZE) diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index c9405e689862..eb5b0bede6ba 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -89,9 +89,11 @@ int libcfs_kkuc_msg_put(struct file *filp, void *payload) } EXPORT_SYMBOL(libcfs_kkuc_msg_put); -/* Broadcast groups are global across all mounted filesystems; +/* + * Broadcast groups are global across all mounted filesystems; * i.e. registering for a group on 1 fs will get messages for that - * group from any fs */ + * group from any fs + */ /** A single group registration has a uid and a file pointer */ struct kkuc_reg { struct list_head kr_chain; @@ -200,8 +202,10 @@ int libcfs_kkuc_group_put(unsigned int group, void *payload) } up_write(&kg_sem); - /* don't return an error if the message has been delivered - * at least to one agent */ + /* + * don't return an error if the message has been delivered + * at least to one agent + */ if (one_success) rc = 0; -- cgit v1.2.3 From 13c26b26066434b3b167e33a075c983a2e480395 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:48 -0500 Subject: staging: lustre: add space around '+' in kernel_comm code Add in missing space arouund '+' in the kernel_comm code. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/uapi_kernelcomm.h | 2 +- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h b/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h index a8feab616f75..5ace9f84422c 100644 --- a/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h +++ b/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h @@ -54,7 +54,7 @@ struct kuc_hdr { __u16 kuc_msglen; } __aligned(sizeof(__u64)); -#define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr)+CR_MAXSIZE) +#define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr) + CR_MAXSIZE) #define KUC_MAGIC 0x191C /*Lustre9etLinC */ diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index eb5b0bede6ba..709b1ab80939 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -102,7 +102,7 @@ struct kkuc_reg { char kr_data[0]; }; -static struct list_head kkuc_groups[KUC_GRP_MAX+1] = {}; +static struct list_head kkuc_groups[KUC_GRP_MAX + 1] = {}; /* Protect message sending against remove and adds */ static DECLARE_RWSEM(kg_sem); -- cgit v1.2.3 From a0d5e63e436629f41c1e8ea6aa0d506192afd75e Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:49 -0500 Subject: staging: lustre: use proper braces in libcfs_kkuc_group_put Add in missing braces for libcfs_kkuc_group_put();. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index 709b1ab80939..46cb81ab3c5f 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -192,9 +192,9 @@ int libcfs_kkuc_group_put(unsigned int group, void *payload) list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { if (reg->kr_fp) { rc = libcfs_kkuc_msg_put(reg->kr_fp, payload); - if (rc == 0) + if (rc == 0) { one_success = 1; - else if (rc == -EPIPE) { + } else if (rc == -EPIPE) { fput(reg->kr_fp); reg->kr_fp = NULL; } -- cgit v1.2.3 From 2bab480d1ca9b654eff316eba44fad2eac8884b4 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:50 -0500 Subject: staging: lustre: return proper error code for libcfs_kkuc_msg_put The functon libcfs_kkuc_msg_put() returns -ENOSYS which is not correct. Return -ENXIO instead if the kuc header is corrupt. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index 46cb81ab3c5f..281cfd6c2bc7 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -57,14 +57,14 @@ int libcfs_kkuc_msg_put(struct file *filp, void *payload) ssize_t count = kuch->kuc_msglen; loff_t offset = 0; mm_segment_t fs; - int rc = -ENOSYS; + int rc = -ENXIO; if (!filp || IS_ERR(filp)) return -EBADF; if (kuch->kuc_magic != KUC_MAGIC) { CERROR("KernelComm: bad magic %x\n", kuch->kuc_magic); - return -ENOSYS; + return rc; } fs = get_fs(); -- cgit v1.2.3 From a5f533f593c82a3f7ed50c4c0c97078cc7a9487a Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:51 -0500 Subject: staging: lustre: fix all conditional comparison to zero for kernelcomm.c Doing if (rc != 0) or if (rc == 0) is bad form. This patch corrects kernelcomm.c to behavior according to kernel coding standards. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index 281cfd6c2bc7..285fee0ecaea 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -154,7 +154,7 @@ int libcfs_kkuc_group_rem(int uid, unsigned int group) if (!kkuc_groups[group].next) return 0; - if (uid == 0) { + if (!uid) { /* Broadcast a shutdown message */ struct kuc_hdr lh; @@ -167,7 +167,7 @@ int libcfs_kkuc_group_rem(int uid, unsigned int group) down_write(&kg_sem); list_for_each_entry_safe(reg, next, &kkuc_groups[group], kr_chain) { - if ((uid == 0) || (uid == reg->kr_uid)) { + if (!uid || (uid == reg->kr_uid)) { list_del(®->kr_chain); CDEBUG(D_KUC, "Removed uid=%d fp=%p from group %d\n", reg->kr_uid, reg->kr_fp, group); @@ -192,7 +192,7 @@ int libcfs_kkuc_group_put(unsigned int group, void *payload) list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { if (reg->kr_fp) { rc = libcfs_kkuc_msg_put(reg->kr_fp, payload); - if (rc == 0) { + if (!rc) { one_success = 1; } else if (rc == -EPIPE) { fput(reg->kr_fp); -- cgit v1.2.3 From 85de1f5516eb08812d4f5b445481fbde7aacd503 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:52 -0500 Subject: staging: lustre: cleanup white space in kernel comm code Cleanup the last white space issues in the kernel comm code. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/uapi_kernelcomm.h | 10 +++++----- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h b/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h index 5ace9f84422c..5e998362e44b 100644 --- a/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h +++ b/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h @@ -56,17 +56,17 @@ struct kuc_hdr { #define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr) + CR_MAXSIZE) -#define KUC_MAGIC 0x191C /*Lustre9etLinC */ +#define KUC_MAGIC 0x191C /*Lustre9etLinC */ /* kuc_msgtype values are defined in each transport */ enum kuc_transport_type { - KUC_TRANSPORT_GENERIC = 1, - KUC_TRANSPORT_HSM = 2, - KUC_TRANSPORT_CHANGELOG = 3, + KUC_TRANSPORT_GENERIC = 1, + KUC_TRANSPORT_HSM = 2, + KUC_TRANSPORT_CHANGELOG = 3, }; enum kuc_generic_message_type { - KUC_MSG_SHUTDOWN = 1, + KUC_MSG_SHUTDOWN = 1, }; /* KUC Broadcast Groups. This determines which userspace process hears which diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index 285fee0ecaea..be4867c5446c 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -185,7 +185,7 @@ EXPORT_SYMBOL(libcfs_kkuc_group_rem); int libcfs_kkuc_group_put(unsigned int group, void *payload) { struct kkuc_reg *reg; - int rc = 0; + int rc = 0; int one_success = 0; down_write(&kg_sem); -- cgit v1.2.3 From b8947b399dbbce510183521d80f361df462e4383 Mon Sep 17 00:00:00 2001 From: Valdis Kletnieks Date: Tue, 22 Dec 2015 19:36:49 -0500 Subject: drivers/staging/lustre: Silence warning about 'inline' Low-hanging fruit first: CC [M] drivers/staging/lustre/lustre/fid/fid_request.o In file included from drivers/staging/lustre/lustre/fid/../include/lustre_net.h:66:0, from drivers/staging/lustre/lustre/fid/../include/lustre_lib.h:64, from drivers/staging/lustre/lustre/fid/../include/obd.h:52, from drivers/staging/lustre/lustre/fid/fid_request.c:48: drivers/staging/lustre/lustre/fid/../include/lu_object.h:765:1: warning: 'inline' is not at beginning of declaration [-Wold-style-declaration] static const inline struct lu_device_operations * ^ So we just swap inline and const. 272 warnings gone. :) Signed-off-by: Valdis Kletnieks Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lu_object.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index ee1dbb257d5d..0b22e5ee99ac 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -756,7 +756,7 @@ static inline const struct lu_fid *lu_object_fid(const struct lu_object *o) /** * return device operations vector for this object */ -static const inline struct lu_device_operations * +static inline const struct lu_device_operations * lu_object_ops(const struct lu_object *o) { return o->lo_dev->ld_ops; -- cgit v1.2.3 From f65a0922f024d44a73fa113a833e55f4a5033597 Mon Sep 17 00:00:00 2001 From: Valdis Kletnieks Date: Tue, 22 Dec 2015 19:36:50 -0500 Subject: drivers/staging/lustre: Fix set-but-unused whinge. drivers/staging/lustre/lustre/fid/lproc_fid.c: In function 'ldebugfs_fid_write_common': drivers/staging/lustre/lustre/fid/lproc_fid.c:67:6: warning: variable 'rc' set but not used [-Wunused-but-set-variable] int rc; We fix it by *using* the return code to help bulletproof it. It says it's test code - it should be *more* bulletproof than production, not less. Signed-off-by: Valdis Kletnieks Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/fid/lproc_fid.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/fid/lproc_fid.c b/drivers/staging/lustre/lustre/fid/lproc_fid.c index 39f2aa32e984..0320b6e83576 100644 --- a/drivers/staging/lustre/lustre/fid/lproc_fid.c +++ b/drivers/staging/lustre/lustre/fid/lproc_fid.c @@ -85,6 +85,8 @@ ldebugfs_fid_write_common(const char __user *buffer, size_t count, rc = sscanf(kernbuf, "[%llx - %llx]\n", (unsigned long long *)&tmp.lsr_start, (unsigned long long *)&tmp.lsr_end); + if (rc != 2) + return -EINVAL; if (!range_is_sane(&tmp) || range_is_zero(&tmp) || tmp.lsr_start < range->lsr_start || tmp.lsr_end > range->lsr_end) return -EINVAL; -- cgit v1.2.3 From 7f6ab07293c8ee6a64783b01840189f894dc3f16 Mon Sep 17 00:00:00 2001 From: Valdis Kletnieks Date: Tue, 22 Dec 2015 19:36:51 -0500 Subject: drivers/staging/lustre: Clean up another C warnining: set but not used drivers/staging/lustre/lustre/fid/../include/lustre_cfg.h: In function 'lustre_cfg_free': drivers/staging/lustre/lustre/fid/../include/lustre_cfg.h:253:6: warning: variable 'len' set but not used [-Wunused-but-set-variable] int len; Yep, we're just gonna call kfree, no need to calculate len. Bye-bye. Signed-off-by: Valdis Kletnieks Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_cfg.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_cfg.h b/drivers/staging/lustre/lustre/include/lustre_cfg.h index eb6b292b7b25..d30d8b054c92 100644 --- a/drivers/staging/lustre/lustre/include/lustre_cfg.h +++ b/drivers/staging/lustre/lustre/include/lustre_cfg.h @@ -252,10 +252,6 @@ static inline struct lustre_cfg *lustre_cfg_new(int cmd, static inline void lustre_cfg_free(struct lustre_cfg *lcfg) { - int len; - - len = lustre_cfg_len(lcfg->lcfg_bufcount, lcfg->lcfg_buflens); - kfree(lcfg); return; } -- cgit v1.2.3 From 5aec2e0791a5a76bec020b088a8b8a10afcfd522 Mon Sep 17 00:00:00 2001 From: Valdis Kletnieks Date: Tue, 22 Dec 2015 19:36:52 -0500 Subject: drivers/staging/lustre: Fix another C compiler whine: set but not used CC [M] drivers/staging/lustre/lustre/libcfs/module.o drivers/staging/lustre/lustre/libcfs/module.c: In function 'lustre_insert_debugfs': drivers/staging/lustre/lustre/libcfs/module.c:670:17: warning: variable 'entry' set but not used [-Wunused-but-set-variable] struct dentry *entry; ^ Just ignore the dentry returned, and add a comment that we *know* we're not really leaking the dentry because something else will be able to reap it via recursion. Signed-off-by: Valdis Kletnieks Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/module.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c index 0067e5347884..af516a29c20e 100644 --- a/drivers/staging/lustre/lustre/libcfs/module.c +++ b/drivers/staging/lustre/lustre/libcfs/module.c @@ -511,8 +511,6 @@ static const struct file_operations lnet_debugfs_file_operations = { void lustre_insert_debugfs(struct ctl_table *table, const struct lnet_debugfs_symlink_def *symlinks) { - struct dentry *entry; - if (lnet_debugfs_root == NULL) lnet_debugfs_root = debugfs_create_dir("lnet", NULL); @@ -520,15 +518,17 @@ void lustre_insert_debugfs(struct ctl_table *table, if (IS_ERR_OR_NULL(lnet_debugfs_root)) return; + /* We don't save the dentry returned in next two calls, because + * we don't call debugfs_remove() but rather remove_recursive() + */ for (; table->procname; table++) - entry = debugfs_create_file(table->procname, table->mode, - lnet_debugfs_root, table, - &lnet_debugfs_file_operations); + debugfs_create_file(table->procname, table->mode, + lnet_debugfs_root, table, + &lnet_debugfs_file_operations); for (; symlinks && symlinks->name; symlinks++) - entry = debugfs_create_symlink(symlinks->name, - lnet_debugfs_root, - symlinks->target); + debugfs_create_symlink(symlinks->name, lnet_debugfs_root, + symlinks->target); } EXPORT_SYMBOL_GPL(lustre_insert_debugfs); -- cgit v1.2.3 From bd6455de1a1af6b382b9ee93311397284c165c92 Mon Sep 17 00:00:00 2001 From: Valdis Kletnieks Date: Tue, 22 Dec 2015 19:36:53 -0500 Subject: drivers/staging/lustre: Nuke an unsigned >= 0 assert Writing asserts for almost-never-can-happen things can be valuable. Writing an assert that tests that an "unsigned int" hasn't gone negative isn't. And it generates an *ugly* message: drivers/staging/lustre/lustre/llite/rw.c:763:20: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] LASSERTF(reserved >= 0, "reserved %lu\n", reserved); ^ include/linux/compiler.h:137:45: note: in definition of macro 'unlikely' # define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0)) ^ drivers/staging/lustre/lustre/llite/rw.c:763:2: note: in expansion of macro 'LASSERTF' LASSERTF(reserved >= 0, "reserved %lu\n", reserved); ^ drivers/staging/lustre/lustre/llite/rw.c:763:20: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] LASSERTF(reserved >= 0, "reserved %lu\n", reserved); ^ include/linux/compiler.h:137:53: note: in definition of macro 'unlikely' # define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0)) ^ drivers/staging/lustre/lustre/llite/rw.c:763:2: note: in expansion of macro 'LASSERTF' LASSERTF(reserved >= 0, "reserved %lu\n", reserved); ^ drivers/staging/lustre/lustre/llite/rw.c:763:20: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] LASSERTF(reserved >= 0, "reserved %lu\n", reserved); ^ include/linux/compiler.h:110:47: note: in definition of macro 'likely_notrace' #define likely_notrace(x) __builtin_expect(!!(x), 1) ^ include/linux/compiler.h:137:58: note: in expansion of macro '__branch_check__' # define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0)) ^ drivers/staging/lustre/lustre/llite/../include/linux/../../../include/linux/libcfs/libcfs_private.h:58:6: note: in expansion of macro 'unlikely' if (unlikely(!(cond))) { \ ^ drivers/staging/lustre/lustre/llite/rw.c:763:2: note: in expansion of macro 'LASSERTF' LASSERTF(reserved >= 0, "reserved %lu\n", reserved); ^ Umm, thank you, GCC. We'll delete the problem line so we never see that spew again. Signed-off-by: Valdis Kletnieks Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/rw.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index f355474967d6..6b587d66d1b3 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -764,7 +764,6 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, ret = ll_read_ahead_pages(env, io, queue, ria, &reserved, mapping, &ra_end); - LASSERTF(reserved >= 0, "reserved %lu\n", reserved); if (reserved != 0) ll_ra_count_put(ll_i2sbi(inode), reserved); -- cgit v1.2.3 From ad0d7799382b37e6afa910f27fa342af62d80ded Mon Sep 17 00:00:00 2001 From: Valdis Kletnieks Date: Tue, 22 Dec 2015 19:36:54 -0500 Subject: drivers/staging/lustre: Nuke another unsigned >= 0 assert Clean up another case of the compiler remininding the programmer they are an idiot: drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c:308:34: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] LASSERT(page_pools.epp_waitqlen >= 0); Just lose the assert, and save a page of compiler spew. Signed-off-by: Valdis Kletnieks Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c index 6152c1b766c3..22621c74a66a 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c @@ -304,7 +304,6 @@ static unsigned long enc_pools_cleanup(struct page ***pools, int npools) static inline void enc_pools_wakeup(void) { assert_spin_locked(&page_pools.epp_lock); - LASSERT(page_pools.epp_waitqlen >= 0); if (unlikely(page_pools.epp_waitqlen)) { LASSERT(waitqueue_active(&page_pools.epp_waitq)); -- cgit v1.2.3 From a4113d61e53c6cd866f1e760648a41ff95c9b9ba Mon Sep 17 00:00:00 2001 From: Joshua Clayton Date: Sat, 26 Dec 2015 22:47:36 -0800 Subject: staging: lustre: fix lock imbalance nrs_resource_put_safe() might hold a lock one one struct while operating on the other. There are 2 levels of structures. Use nrs_policy_put(), which has locking baked in. sparse gives the following warning: drivers/staging/lustre//lustre/ptlrpc/nrs.c:498:39: warning: context imbalance in 'nrs_resource_put_safe' - different lock contexts for basic block Signed-off-by: Joshua Clayton Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/nrs.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ptlrpc/nrs.c b/drivers/staging/lustre/lustre/ptlrpc/nrs.c index 7044e1ff6692..57acf8c45f9e 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/nrs.c +++ b/drivers/staging/lustre/lustre/ptlrpc/nrs.c @@ -482,7 +482,6 @@ static void nrs_resource_get_safe(struct ptlrpc_nrs *nrs, static void nrs_resource_put_safe(struct ptlrpc_nrs_resource **resp) { struct ptlrpc_nrs_policy *pols[NRS_RES_MAX]; - struct ptlrpc_nrs *nrs = NULL; int i; for (i = 0; i < NRS_RES_MAX; i++) { @@ -496,18 +495,9 @@ static void nrs_resource_put_safe(struct ptlrpc_nrs_resource **resp) } for (i = 0; i < NRS_RES_MAX; i++) { - if (pols[i] == NULL) - continue; - - if (nrs == NULL) { - nrs = pols[i]->pol_nrs; - spin_lock(&nrs->nrs_lock); - } - nrs_policy_put_locked(pols[i]); + if (pols[i]) + nrs_policy_put(pols[i]); } - - if (nrs != NULL) - spin_unlock(&nrs->nrs_lock); } /** -- cgit v1.2.3 From 161106c5fa86cf76c16d5fe71abb8c2e836be842 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 1 Jan 2016 09:37:03 +0100 Subject: staging: lustre: obdecho: constify lu_device_operations and cl_device_operations structures These lu_device_operations and cl_device_operations structures are never modified, so declare them as const. Other structures of these types are already const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdecho/echo_client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 7b53f7dd1797..f32f1e72d569 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -582,13 +582,13 @@ static struct lu_object *echo_object_alloc(const struct lu_env *env, return obj; } -static struct lu_device_operations echo_device_lu_ops = { +static const struct lu_device_operations echo_device_lu_ops = { .ldo_object_alloc = echo_object_alloc, }; /** @} echo_lu_dev_ops */ -static struct cl_device_operations echo_device_cl_ops = { +static const struct cl_device_operations echo_device_cl_ops = { }; /** \defgroup echo_init Setup and teardown -- cgit v1.2.3 From 98aa7661788198dadf37f71286c4cc703b0c6684 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 1 Jan 2016 10:02:03 +0100 Subject: staging/lustre/llite: constify export_operations structures This export_operations structure is never modified, so declare it as const. Most other structures of this type are already const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_internal.h | 2 +- drivers/staging/lustre/lustre/llite/llite_nfs.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 845e992ca5fc..e73024778808 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -796,7 +796,7 @@ char *ll_get_fsname(struct super_block *sb, char *buf, int buflen); void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req); /* llite/llite_nfs.c */ -extern struct export_operations lustre_export_operations; +extern const struct export_operations lustre_export_operations; __u32 get_uuid2int(const char *name, int len); void get_uuid2fsid(const char *name, int len, __kernel_fsid_t *fsid); struct inode *search_inode_for_lustre(struct super_block *sb, diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index 18aab25f9cd9..9f64dd18f452 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -323,7 +323,7 @@ static struct dentry *ll_get_parent(struct dentry *dchild) return result; } -struct export_operations lustre_export_operations = { +const struct export_operations lustre_export_operations = { .get_parent = ll_get_parent, .encode_fh = ll_encode_fh, .get_name = ll_get_name, -- cgit v1.2.3 From fccfde7d5d94327a991244124e01fa1daa9bb543 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:32 -0500 Subject: staging/lustre/lnet: Make lnet_ping static It's not used anywhere outside of api-ni.c anyway. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/lnet/lib-lnet.h | 2 -- drivers/staging/lustre/lnet/lnet/api-ni.c | 7 +++++-- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h index b67a6607bb3b..40acddd728e6 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h @@ -662,8 +662,6 @@ void lnet_swap_pinginfo(lnet_ping_info_t *info); int lnet_ping_target_init(void); void lnet_ping_target_fini(void); -int lnet_ping(lnet_process_id_t id, int timeout_ms, - lnet_process_id_t *ids, int n_ids); int lnet_parse_ip2nets(char **networksp, char *ip2nets); int lnet_parse_routes(char *route_str, int *im_a_router); diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index 362282fa00bf..de453ceb8649 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -61,6 +61,9 @@ static int rnet_htable_size = LNET_REMOTE_NETS_HASH_DEFAULT; module_param(rnet_htable_size, int, 0444); MODULE_PARM_DESC(rnet_htable_size, "size of remote network hash table"); +static int lnet_ping(lnet_process_id_t id, int timeout_ms, + lnet_process_id_t *ids, int n_ids); + static char * lnet_get_routes(void) { @@ -1672,8 +1675,8 @@ lnet_ping_target_fini(void) cfs_restore_sigs(blocked); } -int -lnet_ping(lnet_process_id_t id, int timeout_ms, lnet_process_id_t *ids, int n_ids) +static int lnet_ping(lnet_process_id_t id, int timeout_ms, + lnet_process_id_t *ids, int n_ids) { lnet_handle_eq_t eqh; lnet_handle_md_t mdh; -- cgit v1.2.3 From 71c36dd795b308df112da7d7f2f8b1a98fb6e7ed Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:33 -0500 Subject: staging/lustre/lnet: Get rid of IOC_LIBCFS_DEBUG_PEER hack IOC_LIBCFS_DEBUG_PEER was added back in the stone ages to print debug statistics on a peer when peer timeout happens. Redo it properly as a separate LNet API call, also get rid of "ioctl" forwarding into the underlying LNDs, since no current LNDs implement this function anymore. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_ioctl.h | 2 +- drivers/staging/lustre/include/linux/lnet/api.h | 1 + drivers/staging/lustre/lnet/lnet/api-ni.c | 38 ++++------------------ drivers/staging/lustre/lustre/ptlrpc/client.c | 2 +- 4 files changed, 10 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 485ab2670918..7c5e5c805fe6 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -123,7 +123,7 @@ struct libcfs_ioctl_handler { #define IOC_LIBCFS_CONFIGURE _IOWR('e', 59, long) #define IOC_LIBCFS_TESTPROTOCOMPAT _IOWR('e', 60, long) #define IOC_LIBCFS_PING _IOWR('e', 61, long) -#define IOC_LIBCFS_DEBUG_PEER _IOWR('e', 62, long) +/* #define IOC_LIBCFS_DEBUG_PEER _IOWR('e', 62, long) */ #define IOC_LIBCFS_LNETST _IOWR('e', 63, long) /* lnd ioctls */ #define IOC_LIBCFS_REGISTER_MYNID _IOWR('e', 70, long) diff --git a/drivers/staging/lustre/include/linux/lnet/api.h b/drivers/staging/lustre/include/linux/lnet/api.h index 75285fde15e8..fa5fad3582b3 100644 --- a/drivers/staging/lustre/include/linux/lnet/api.h +++ b/drivers/staging/lustre/include/linux/lnet/api.h @@ -197,6 +197,7 @@ int LNetGet(lnet_nid_t self, int LNetSetLazyPortal(int portal); int LNetClearLazyPortal(int portal); int LNetCtl(unsigned int cmd, void *arg); +void LNetDebugPeer(lnet_process_id_t id); /** @} lnet_misc */ diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index de453ceb8649..94ccef56c4bf 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -1316,17 +1316,10 @@ LNetNIFini(void) EXPORT_SYMBOL(LNetNIFini); /** - * This is an ugly hack to export IOC_LIBCFS_DEBUG_PEER and - * IOC_LIBCFS_PORTALS_COMPATIBILITY commands to users, by tweaking the LNet - * internal ioctl handler. + * LNet ioctl handler. * * IOC_LIBCFS_PORTALS_COMPATIBILITY is now deprecated, don't use it. * - * \param cmd IOC_LIBCFS_DEBUG_PEER to print debugging data about a peer. - * The data will be printed to system console. Don't use it excessively. - * \param arg A pointer to lnet_process_id_t, process ID of the peer. - * - * \return Always return 0 when called by users directly (i.e., not via ioctl). */ int LNetCtl(unsigned int cmd, void *arg) @@ -1396,29 +1389,6 @@ LNetCtl(unsigned int cmd, void *arg) data->ioc_count = rc; return 0; - case IOC_LIBCFS_DEBUG_PEER: { - /* CAVEAT EMPTOR: this one designed for calling directly; not - * via an ioctl */ - id = *((lnet_process_id_t *) arg); - - lnet_debug_peer(id.nid); - - ni = lnet_net2ni(LNET_NIDNET(id.nid)); - if (ni == NULL) { - CDEBUG(D_WARNING, "No NI for %s\n", libcfs_id2str(id)); - } else { - if (ni->ni_lnd->lnd_ctl == NULL) { - CDEBUG(D_WARNING, "No ctl for %s\n", - libcfs_id2str(id)); - } else { - (void)ni->ni_lnd->lnd_ctl(ni, cmd, arg); - } - - lnet_ni_decref(ni); - } - return 0; - } - default: ni = lnet_net2ni(data->ioc_net); if (ni == NULL) @@ -1436,6 +1406,12 @@ LNetCtl(unsigned int cmd, void *arg) } EXPORT_SYMBOL(LNetCtl); +void LNetDebugPeer(lnet_process_id_t id) +{ + lnet_debug_peer(id.nid); +} +EXPORT_SYMBOL(LNetDebugPeer); + /** * Retrieve the lnet_process_id_t ID of LNet interface at \a index. Note that * all interfaces share a same PID, as requested by LNetNIInit(). diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 8f3c26f1398f..1cc3c69a175a 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1884,7 +1884,7 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink) (s64)req->rq_sent, (s64)req->rq_real_sent); if (imp != NULL && obd_debug_peer_on_timeout) - LNetCtl(IOC_LIBCFS_DEBUG_PEER, &imp->imp_connection->c_peer); + LNetDebugPeer(imp->imp_connection->c_peer); ptlrpc_unregister_reply(req, async_unlink); ptlrpc_unregister_bulk(req, async_unlink); -- cgit v1.2.3 From ee11f9223eeec882c3dfe2ca0af18feb53ff8ddf Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:34 -0500 Subject: staging/lustre/lnet: Get rid of IOC_LIBCFS_PORTALS_COMPATIBILITY ioctl This has been unused for ages and could be safely removed now. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h | 2 +- drivers/staging/lustre/lnet/lnet/api-ni.c | 6 ------ drivers/staging/lustre/lustre/ptlrpc/events.c | 11 ----------- 3 files changed, 1 insertion(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 7c5e5c805fe6..3b16fcef1dad 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -118,7 +118,7 @@ struct libcfs_ioctl_handler { #define IOC_LIBCFS_GET_ROUTE _IOWR('e', 54, long) #define IOC_LIBCFS_NOTIFY_ROUTER _IOWR('e', 55, long) #define IOC_LIBCFS_UNCONFIGURE _IOWR('e', 56, long) -#define IOC_LIBCFS_PORTALS_COMPATIBILITY _IOWR('e', 57, long) +/* #define IOC_LIBCFS_PORTALS_COMPATIBILITY _IOWR('e', 57, long) */ #define IOC_LIBCFS_LNET_DIST _IOWR('e', 58, long) #define IOC_LIBCFS_CONFIGURE _IOWR('e', 59, long) #define IOC_LIBCFS_TESTPROTOCOMPAT _IOWR('e', 60, long) diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index 94ccef56c4bf..80b170ee5582 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -1318,8 +1318,6 @@ EXPORT_SYMBOL(LNetNIFini); /** * LNet ioctl handler. * - * IOC_LIBCFS_PORTALS_COMPATIBILITY is now deprecated, don't use it. - * */ int LNetCtl(unsigned int cmd, void *arg) @@ -1360,10 +1358,6 @@ LNetCtl(unsigned int cmd, void *arg) return lnet_notify(NULL, data->ioc_nid, data->ioc_flags, jiffies - secs_passed * HZ); - case IOC_LIBCFS_PORTALS_COMPATIBILITY: - /* This can be removed once lustre stops calling it */ - return 0; - case IOC_LIBCFS_LNET_DIST: rc = LNetDist(data->ioc_nid, &data->ioc_nid, &data->ioc_u32[1]); if (rc < 0 && rc != -EHOSTUNREACH) diff --git a/drivers/staging/lustre/lustre/ptlrpc/events.c b/drivers/staging/lustre/lustre/ptlrpc/events.c index 990156986986..07e76a2b1291 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/events.c +++ b/drivers/staging/lustre/lustre/ptlrpc/events.c @@ -438,14 +438,11 @@ int ptlrpc_uuid_to_peer(struct obd_uuid *uuid, __u32 best_order = 0; int count = 0; int rc = -ENOENT; - int portals_compatibility; int dist; __u32 order; lnet_nid_t dst_nid; lnet_nid_t src_nid; - portals_compatibility = LNetCtl(IOC_LIBCFS_PORTALS_COMPATIBILITY, NULL); - peer->pid = LUSTRE_SRV_LNET_PID; /* Choose the matching UUID that's closest */ @@ -466,14 +463,6 @@ int ptlrpc_uuid_to_peer(struct obd_uuid *uuid, best_dist = dist; best_order = order; - if (portals_compatibility > 1) { - /* Strong portals compatibility: Zero the nid's - * NET, so if I'm reading new config logs, or - * getting configured by (new) lconf I can - * still talk to old servers. */ - dst_nid = LNET_MKNID(0, LNET_NIDADDR(dst_nid)); - src_nid = LNET_MKNID(0, LNET_NIDADDR(src_nid)); - } peer->nid = dst_nid; *self = src_nid; rc = 0; -- cgit v1.2.3 From 6973cd73af2068d029edae419515381df7bfd7e5 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:35 -0500 Subject: staging/lustre/obdecho: Remove unused ioctls Remove long unused ECHO_IOC_GET_STRIPE, ECHO_IOC_SET_STRIPE, ECHO_IOC_ENQUEUE and ECHO_IOC_CANCEL ioctls. Signed-off-by: John L. Hammond Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_lib.h | 8 +- .../staging/lustre/lustre/obdecho/echo_client.c | 163 --------------------- 2 files changed, 4 insertions(+), 167 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index 428469fec534..7daf9543f32c 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -365,10 +365,10 @@ static inline void obd_ioctl_freedata(char *buf, int len) /* OBD_IOC_LLOG_CATINFO is deprecated */ #define OBD_IOC_LLOG_CATINFO _IOWR('f', 196, OBD_IOC_DATA_TYPE) -#define ECHO_IOC_GET_STRIPE _IOWR('f', 200, OBD_IOC_DATA_TYPE) -#define ECHO_IOC_SET_STRIPE _IOWR('f', 201, OBD_IOC_DATA_TYPE) -#define ECHO_IOC_ENQUEUE _IOWR('f', 202, OBD_IOC_DATA_TYPE) -#define ECHO_IOC_CANCEL _IOWR('f', 203, OBD_IOC_DATA_TYPE) +/* #define ECHO_IOC_GET_STRIPE _IOWR('f', 200, OBD_IOC_DATA_TYPE) */ +/* #define ECHO_IOC_SET_STRIPE _IOWR('f', 201, OBD_IOC_DATA_TYPE) */ +/* #define ECHO_IOC_ENQUEUE _IOWR('f', 202, OBD_IOC_DATA_TYPE) */ +/* #define ECHO_IOC_CANCEL _IOWR('f', 203, OBD_IOC_DATA_TYPE) */ #define OBD_IOC_GET_OBJ_VERSION _IOR('f', 210, OBD_IOC_DATA_TYPE) diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index f32f1e72d569..ec8a26bd0835 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -162,9 +162,6 @@ struct echo_object_conf *cl2echo_conf(const struct cl_object_conf *c) static struct echo_object *cl_echo_object_find(struct echo_device *d, struct lov_stripe_md **lsm); static int cl_echo_object_put(struct echo_object *eco); -static int cl_echo_enqueue(struct echo_object *eco, u64 start, - u64 end, int mode, __u64 *cookie); -static int cl_echo_cancel(struct echo_device *d, __u64 cookie); static int cl_echo_object_brw(struct echo_object *eco, int rw, u64 offset, struct page **pages, int npages, int async); @@ -1076,36 +1073,6 @@ static int cl_echo_enqueue0(struct lu_env *env, struct echo_object *eco, return rc; } -static int cl_echo_enqueue(struct echo_object *eco, u64 start, u64 end, - int mode, __u64 *cookie) -{ - struct echo_thread_info *info; - struct lu_env *env; - struct cl_io *io; - int refcheck; - int result; - - env = cl_env_get(&refcheck); - if (IS_ERR(env)) - return PTR_ERR(env); - - info = echo_env_info(env); - io = &info->eti_io; - - io->ci_ignore_layout = 1; - result = cl_io_init(env, io, CIT_MISC, echo_obj2cl(eco)); - if (result < 0) - goto out; - LASSERT(result == 0); - - result = cl_echo_enqueue0(env, eco, start, end, mode, cookie, 0); - cl_io_fini(env, io); - -out: - cl_env_put(env, &refcheck); - return result; -} - static int cl_echo_cancel0(struct lu_env *env, struct echo_device *ed, __u64 cookie) { @@ -1137,22 +1104,6 @@ static int cl_echo_cancel0(struct lu_env *env, struct echo_device *ed, return 0; } -static int cl_echo_cancel(struct echo_device *ed, __u64 cookie) -{ - struct lu_env *env; - int refcheck; - int rc; - - env = cl_env_get(&refcheck); - if (IS_ERR(env)) - return PTR_ERR(env); - - rc = cl_echo_cancel0(env, ed, cookie); - - cl_env_put(env, &refcheck); - return rc; -} - static int cl_echo_async_brw(const struct lu_env *env, struct cl_io *io, enum cl_req_type unused, struct cl_2queue *queue) { @@ -1268,29 +1219,6 @@ out: static u64 last_object_id; -static int -echo_copyout_lsm(struct lov_stripe_md *lsm, void *_ulsm, int ulsm_nob) -{ - struct lov_stripe_md *ulsm = _ulsm; - struct lov_oinfo **p; - int nob, i; - - nob = offsetof(struct lov_stripe_md, lsm_oinfo[lsm->lsm_stripe_count]); - if (nob > ulsm_nob) - return -EINVAL; - - if (copy_to_user(ulsm, lsm, sizeof(*ulsm))) - return -EFAULT; - - for (i = 0, p = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++, p++) { - struct lov_oinfo __user *up; - if (get_user(up, ulsm->lsm_oinfo + i) || - copy_to_user(up, *p, sizeof(struct lov_oinfo))) - return -EFAULT; - } - return 0; -} - static int echo_copyin_lsm(struct echo_device *ed, struct lov_stripe_md *lsm, struct lov_stripe_md __user *ulsm, int ulsm_nob) @@ -1804,53 +1732,6 @@ static int echo_client_brw_ioctl(const struct lu_env *env, int rw, return rc; } -static int -echo_client_enqueue(struct obd_export *exp, struct obdo *oa, - int mode, u64 offset, u64 nob) -{ - struct echo_device *ed = obd2echo_dev(exp->exp_obd); - struct lustre_handle *ulh = &oa->o_handle; - struct echo_object *eco; - u64 end; - int rc; - - if (ed->ed_next == NULL) - return -EOPNOTSUPP; - - if (!(mode == LCK_PR || mode == LCK_PW)) - return -EINVAL; - - if ((offset & (~CFS_PAGE_MASK)) != 0 || - (nob & (~CFS_PAGE_MASK)) != 0) - return -EINVAL; - - rc = echo_get_object(&eco, ed, oa); - if (rc != 0) - return rc; - - end = (nob == 0) ? ((u64) -1) : (offset + nob - 1); - rc = cl_echo_enqueue(eco, offset, end, mode, &ulh->cookie); - if (rc == 0) { - oa->o_valid |= OBD_MD_FLHANDLE; - CDEBUG(D_INFO, "Cookie is %#llx\n", ulh->cookie); - } - echo_put_object(eco); - return rc; -} - -static int -echo_client_cancel(struct obd_export *exp, struct obdo *oa) -{ - struct echo_device *ed = obd2echo_dev(exp->exp_obd); - __u64 cookie = oa->o_handle.cookie; - - if ((oa->o_valid & OBD_MD_FLHANDLE) == 0) - return -EINVAL; - - CDEBUG(D_INFO, "Cookie is %#llx\n", cookie); - return cl_echo_cancel(ed, cookie); -} - static int echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, void *karg, void *uarg) @@ -1961,50 +1842,6 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, rc = echo_client_brw_ioctl(env, rw, exp, data, &dummy_oti); goto out; - case ECHO_IOC_GET_STRIPE: - rc = echo_get_object(&eco, ed, oa); - if (rc == 0) { - rc = echo_copyout_lsm(eco->eo_lsm, data->ioc_pbuf1, - data->ioc_plen1); - echo_put_object(eco); - } - goto out; - - case ECHO_IOC_SET_STRIPE: - if (!capable(CFS_CAP_SYS_ADMIN)) { - rc = -EPERM; - goto out; - } - - if (data->ioc_pbuf1 == NULL) { /* unset */ - rc = echo_get_object(&eco, ed, oa); - if (rc == 0) { - eco->eo_deleted = 1; - echo_put_object(eco); - } - } else { - rc = echo_create_object(env, ed, 0, oa, - data->ioc_pbuf1, - data->ioc_plen1, &dummy_oti); - } - goto out; - - case ECHO_IOC_ENQUEUE: - if (!capable(CFS_CAP_SYS_ADMIN)) { - rc = -EPERM; - goto out; - } - - rc = echo_client_enqueue(exp, oa, - data->ioc_conn1, /* lock mode */ - data->ioc_offset, - data->ioc_count);/*extent*/ - goto out; - - case ECHO_IOC_CANCEL: - rc = echo_client_cancel(exp, oa); - goto out; - default: CERROR("echo_ioctl(): unrecognised ioctl %#x\n", cmd); rc = -ENOTTY; -- cgit v1.2.3 From f833ea10c7bb87ac0c16d77ec0048b01e1fd996d Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sun, 3 Jan 2016 12:05:36 -0500 Subject: staging/lustre/obdecho: remove userspace LSM handling In lustre/obdecho/echo_client.c, remove handling of lov_stripe_md passed from userspace (since userspace never passes it). Remove the LOV specific code (ed_next_islov) from the echo client (since it doesn't work). Remove echo_get_stripe_off_id() and all calls to it since the stripe count of the passed in lsm is always 0 and the funciton does nothing in this case. Remove the then unused lsm parameters of echo_client_page_debug_setup() and echo_client_page_debug_check(). In the OBD_IOC_GETATTR and OBD_IOC_SETATTR cases of echo_client_iocontrol() do not set the oi_md member of struct obd_info since only LOV OBD methods access it. Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/12446 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5814 Reviewed-by: Bobi Jam Reviewed-by: Andreas Dilger Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/obd.h | 1 - .../staging/lustre/lustre/obdecho/echo_client.c | 180 ++++----------------- 2 files changed, 31 insertions(+), 150 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index bcbe61301713..86897c2f6c68 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -375,7 +375,6 @@ struct echo_client_obd { spinlock_t ec_lock; struct list_head ec_objects; struct list_head ec_locks; - int ec_nstripes; __u64 ec_unique; }; diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index ec8a26bd0835..5b76c222e2cf 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -60,7 +60,6 @@ struct echo_device { struct cl_site ed_site_myself; struct cl_site *ed_site; struct lu_device *ed_next; - int ed_next_islov; }; struct echo_object { @@ -767,14 +766,6 @@ static struct lu_device *echo_device_alloc(const struct lu_env *env, if (rc) goto out; - /* Tricky case, I have to determine the obd type since - * CLIO uses the different parameters to initialize - * objects for lov & osc. */ - if (strcmp(tgt_type_name, LUSTRE_LOV_NAME) == 0) - ed->ed_next_islov = 1; - else - LASSERT(strcmp(tgt_type_name, - LUSTRE_OSC_NAME) == 0); } else { LASSERT(strcmp(tgt_type_name, LUSTRE_OST_NAME) == 0); } @@ -960,20 +951,11 @@ static struct echo_object *cl_echo_object_find(struct echo_device *d, info = echo_env_info(env); conf = &info->eti_conf; if (d->ed_next) { - if (!d->ed_next_islov) { - struct lov_oinfo *oinfo = lsm->lsm_oinfo[0]; - - LASSERT(oinfo != NULL); - oinfo->loi_oi = lsm->lsm_oi; - conf->eoc_cl.u.coc_oinfo = oinfo; - } else { - struct lustre_md *md; + struct lov_oinfo *oinfo = lsm->lsm_oinfo[0]; - md = &info->eti_md; - memset(md, 0, sizeof(*md)); - md->lsm = lsm; - conf->eoc_cl.u.coc_md = md; - } + LASSERT(oinfo); + oinfo->loi_oi = lsm->lsm_oi; + conf->eoc_cl.u.coc_oinfo = oinfo; } conf->eoc_md = lsmp; @@ -1219,38 +1201,8 @@ out: static u64 last_object_id; -static int -echo_copyin_lsm(struct echo_device *ed, struct lov_stripe_md *lsm, - struct lov_stripe_md __user *ulsm, int ulsm_nob) -{ - struct echo_client_obd *ec = ed->ed_ec; - struct lov_oinfo **p; - int i; - - if (ulsm_nob < sizeof(*lsm)) - return -EINVAL; - - if (copy_from_user(lsm, ulsm, sizeof(*lsm))) - return -EFAULT; - - if (lsm->lsm_stripe_count > ec->ec_nstripes || - lsm->lsm_magic != LOV_MAGIC || - (lsm->lsm_stripe_size & (~CFS_PAGE_MASK)) != 0 || - ((__u64)lsm->lsm_stripe_size * lsm->lsm_stripe_count > ~0UL)) - return -EINVAL; - - for (i = 0, p = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++, p++) { - struct lov_oinfo __user *up; - if (get_user(up, ulsm->lsm_oinfo + i) || - copy_from_user(*p, up, sizeof(struct lov_oinfo))) - return -EFAULT; - } - return 0; -} - static int echo_create_object(const struct lu_env *env, struct echo_device *ed, - int on_target, struct obdo *oa, void *ulsm, - int ulsm_nob, struct obd_trans_info *oti) + struct obdo *oa, struct obd_trans_info *oti) { struct echo_object *eco; struct echo_client_obd *ec = ed->ed_ec; @@ -1258,9 +1210,7 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, int rc; int created = 0; - if ((oa->o_valid & OBD_MD_FLID) == 0 && /* no obj id */ - (on_target || /* set_stripe */ - ec->ec_nstripes != 0)) { /* LOV */ + if ((oa->o_valid & OBD_MD_FLID) == 0) { /* no obj id */ CERROR("No valid oid\n"); return -EINVAL; } @@ -1271,32 +1221,7 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, goto failed; } - if (ulsm != NULL) { - int i, idx; - - rc = echo_copyin_lsm(ed, lsm, ulsm, ulsm_nob); - if (rc != 0) - goto failed; - - if (lsm->lsm_stripe_count == 0) - lsm->lsm_stripe_count = ec->ec_nstripes; - - if (lsm->lsm_stripe_size == 0) - lsm->lsm_stripe_size = PAGE_CACHE_SIZE; - - idx = cfs_rand(); - - /* setup stripes: indices + default ids if required */ - for (i = 0; i < lsm->lsm_stripe_count; i++) { - if (ostid_id(&lsm->lsm_oinfo[i]->loi_oi) == 0) - lsm->lsm_oinfo[i]->loi_oi = lsm->lsm_oi; - - lsm->lsm_oinfo[i]->loi_ost_idx = - (idx + i) % ec->ec_nstripes; - } - } - - /* setup object ID here for !on_target and LOV hint */ + /* setup object ID here */ if (oa->o_valid & OBD_MD_FLID) { LASSERT(oa->o_valid & OBD_MD_FLGROUP); lsm->lsm_oi = oa->o_oi; @@ -1305,18 +1230,16 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, if (ostid_id(&lsm->lsm_oi) == 0) ostid_set_id(&lsm->lsm_oi, ++last_object_id); - rc = 0; - if (on_target) { - /* Only echo objects are allowed to be created */ - LASSERT((oa->o_valid & OBD_MD_FLGROUP) && - (ostid_seq(&oa->o_oi) == FID_SEQ_ECHO)); - rc = obd_create(env, ec->ec_exp, oa, &lsm, oti); - if (rc != 0) { - CERROR("Cannot create objects: rc = %d\n", rc); - goto failed; - } - created = 1; + /* Only echo objects are allowed to be created */ + LASSERT((oa->o_valid & OBD_MD_FLGROUP) && + (ostid_seq(&oa->o_oi) == FID_SEQ_ECHO)); + + rc = obd_create(env, ec->ec_exp, oa, &lsm, oti); + if (rc != 0) { + CERROR("Cannot create objects: rc = %d\n", rc); + goto failed; } + created = 1; /* See what object ID we were given */ oa->o_oi = lsm->lsm_oi; @@ -1380,37 +1303,7 @@ static void echo_put_object(struct echo_object *eco) } static void -echo_get_stripe_off_id(struct lov_stripe_md *lsm, u64 *offp, u64 *idp) -{ - unsigned long stripe_count; - unsigned long stripe_size; - unsigned long width; - unsigned long woffset; - int stripe_index; - u64 offset; - - if (lsm->lsm_stripe_count <= 1) - return; - - offset = *offp; - stripe_size = lsm->lsm_stripe_size; - stripe_count = lsm->lsm_stripe_count; - - /* width = # bytes in all stripes */ - width = stripe_size * stripe_count; - - /* woffset = offset within a width; offset = whole number of widths */ - woffset = do_div(offset, width); - - stripe_index = woffset / stripe_size; - - *idp = ostid_id(&lsm->lsm_oinfo[stripe_index]->loi_oi); - *offp = offset * stripe_size + woffset % stripe_size; -} - -static void -echo_client_page_debug_setup(struct lov_stripe_md *lsm, - struct page *page, int rw, u64 id, +echo_client_page_debug_setup(struct page *page, int rw, u64 id, u64 offset, u64 count) { char *addr; @@ -1427,7 +1320,6 @@ echo_client_page_debug_setup(struct lov_stripe_md *lsm, if (rw == OBD_BRW_WRITE) { stripe_off = offset + delta; stripe_id = id; - echo_get_stripe_off_id(lsm, &stripe_off, &stripe_id); } else { stripe_off = 0xdeadbeef00c0ffeeULL; stripe_id = 0xdeadbeef00c0ffeeULL; @@ -1439,8 +1331,7 @@ echo_client_page_debug_setup(struct lov_stripe_md *lsm, kunmap(page); } -static int echo_client_page_debug_check(struct lov_stripe_md *lsm, - struct page *page, u64 id, +static int echo_client_page_debug_check(struct page *page, u64 id, u64 offset, u64 count) { u64 stripe_off; @@ -1458,7 +1349,6 @@ static int echo_client_page_debug_check(struct lov_stripe_md *lsm, for (rc = delta = 0; delta < PAGE_CACHE_SIZE; delta += OBD_ECHO_BLOCK_SIZE) { stripe_off = offset + delta; stripe_id = id; - echo_get_stripe_off_id(lsm, &stripe_off, &stripe_id); rc2 = block_debug_check("test_brw", addr + delta, OBD_ECHO_BLOCK_SIZE, @@ -1478,7 +1368,6 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa, u64 count, int async, struct obd_trans_info *oti) { - struct lov_stripe_md *lsm = eco->eo_lsm; u32 npages; struct brw_page *pga; struct brw_page *pgp; @@ -1497,8 +1386,6 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa, gfp_mask = ((ostid_id(&oa->o_oi) & 2) == 0) ? GFP_KERNEL : GFP_HIGHUSER; LASSERT(rw == OBD_BRW_WRITE || rw == OBD_BRW_READ); - LASSERT(lsm != NULL); - LASSERT(ostid_id(&lsm->lsm_oi) == ostid_id(&oa->o_oi)); if (count <= 0 || (count & (~CFS_PAGE_MASK)) != 0) @@ -1537,7 +1424,7 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa, pgp->flag = brw_flags; if (verify) - echo_client_page_debug_setup(lsm, pgp->pg, rw, + echo_client_page_debug_setup(pgp->pg, rw, ostid_id(&oa->o_oi), off, pgp->count); } @@ -1557,7 +1444,7 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa, if (verify) { int vrc; - vrc = echo_client_page_debug_check(lsm, pgp->pg, + vrc = echo_client_page_debug_check(pgp->pg, ostid_id(&oa->o_oi), pgp->off, pgp->count); if (vrc != 0 && rc == 0) @@ -1577,7 +1464,6 @@ static int echo_client_prep_commit(const struct lu_env *env, u64 batch, struct obd_trans_info *oti, int async) { - struct lov_stripe_md *lsm = eco->eo_lsm; struct obd_ioobj ioo; struct niobuf_local *lnb; struct niobuf_remote *rnb; @@ -1585,8 +1471,7 @@ static int echo_client_prep_commit(const struct lu_env *env, u64 npages, tot_pages; int i, ret = 0, brw_flags = 0; - if (count <= 0 || (count & (~CFS_PAGE_MASK)) != 0 || - (lsm != NULL && ostid_id(&lsm->lsm_oi) != ostid_id(&oa->o_oi))) + if (count <= 0 || (count & (~CFS_PAGE_MASK)) != 0) return -EINVAL; npages = batch >> PAGE_CACHE_SHIFT; @@ -1645,12 +1530,12 @@ static int echo_client_prep_commit(const struct lu_env *env, continue; if (rw == OBD_BRW_WRITE) - echo_client_page_debug_setup(lsm, page, rw, + echo_client_page_debug_setup(page, rw, ostid_id(&oa->o_oi), rnb[i].offset, rnb[i].len); else - echo_client_page_debug_check(lsm, page, + echo_client_page_debug_check(page, ostid_id(&oa->o_oi), rnb[i].offset, rnb[i].len); @@ -1780,8 +1665,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, goto out; } - rc = echo_create_object(env, ed, 1, oa, data->ioc_pbuf1, - data->ioc_plen1, &dummy_oti); + rc = echo_create_object(env, ed, oa, &dummy_oti); goto out; case OBD_IOC_DESTROY: @@ -1792,7 +1676,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, rc = echo_get_object(&eco, ed, oa); if (rc == 0) { - rc = obd_destroy(env, ec->ec_exp, oa, eco->eo_lsm, + rc = obd_destroy(env, ec->ec_exp, oa, NULL, &dummy_oti, NULL); if (rc == 0) eco->eo_deleted = 1; @@ -1803,10 +1687,10 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, case OBD_IOC_GETATTR: rc = echo_get_object(&eco, ed, oa); if (rc == 0) { - struct obd_info oinfo = { }; + struct obd_info oinfo = { + .oi_oa = oa, + }; - oinfo.oi_md = eco->eo_lsm; - oinfo.oi_oa = oa; rc = obd_getattr(env, ec->ec_exp, &oinfo); echo_put_object(eco); } @@ -1820,10 +1704,9 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, rc = echo_get_object(&eco, ed, oa); if (rc == 0) { - struct obd_info oinfo = { }; - - oinfo.oi_oa = oa; - oinfo.oi_md = eco->eo_lsm; + struct obd_info oinfo = { + .oi_oa = oa, + }; rc = obd_setattr(env, ec->ec_exp, &oinfo, NULL); echo_put_object(eco); @@ -1888,7 +1771,6 @@ static int echo_client_setup(const struct lu_env *env, INIT_LIST_HEAD(&ec->ec_objects); INIT_LIST_HEAD(&ec->ec_locks); ec->ec_unique = 0; - ec->ec_nstripes = 0; ocd = kzalloc(sizeof(*ocd), GFP_NOFS); if (!ocd) { -- cgit v1.2.3 From e2d52f7b3adb0e5b80a068a2b2628bc8c2e01c6d Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:37 -0500 Subject: staging/lustre: Add __user attributes to libcfs_ioctl_get/popdata args Just make clear which pointers are from userspace and which are not in libcfs_ioctl_getdata/libcfs_ioctl_popdata and their callers. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h | 4 ++-- drivers/staging/lustre/lustre/libcfs/linux/linux-module.c | 6 +++--- drivers/staging/lustre/lustre/libcfs/module.c | 5 +++-- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 3b16fcef1dad..0c31bf9b8e8d 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -207,7 +207,7 @@ static inline int libcfs_ioctl_is_invalid(struct libcfs_ioctl_data *data) int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand); int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand); -int libcfs_ioctl_getdata(char *buf, char *end, void *arg); -int libcfs_ioctl_popdata(void *arg, void *buf, int size); +int libcfs_ioctl_getdata(char *buf, char *end, void __user *arg); +int libcfs_ioctl_popdata(void __user *arg, void *buf, int size); #endif /* __LIBCFS_IOCTL_H__ */ diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c index eccfe8bd57a2..c089b044ef2e 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c @@ -40,7 +40,7 @@ #define LNET_MINOR 240 -int libcfs_ioctl_getdata(char *buf, char *end, void *arg) +int libcfs_ioctl_getdata(char *buf, char *end, void __user *arg) { struct libcfs_ioctl_hdr *hdr; struct libcfs_ioctl_data *data; @@ -88,9 +88,9 @@ int libcfs_ioctl_getdata(char *buf, char *end, void *arg) return 0; } -int libcfs_ioctl_popdata(void *arg, void *data, int size) +int libcfs_ioctl_popdata(void __user *arg, void *data, int size) { - if (copy_to_user((char *)arg, data, size)) + if (copy_to_user(arg, data, size)) return -EFAULT; return 0; } diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c index af516a29c20e..d5a047bd0180 100644 --- a/drivers/staging/lustre/lustre/libcfs/module.c +++ b/drivers/staging/lustre/lustre/libcfs/module.c @@ -116,7 +116,7 @@ int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand) EXPORT_SYMBOL(libcfs_deregister_ioctl); static int libcfs_ioctl_int(struct cfs_psdev_file *pfile, unsigned long cmd, - void *arg, struct libcfs_ioctl_data *data) + void __user *arg, struct libcfs_ioctl_data *data) { int err = -EINVAL; @@ -157,7 +157,8 @@ static int libcfs_ioctl_int(struct cfs_psdev_file *pfile, unsigned long cmd, return err; } -static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, void *arg) +static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, + void __user *arg) { char *buf; struct libcfs_ioctl_data *data; -- cgit v1.2.3 From 33ab3abce72e2a02a06e1927c0f2c7999e8b860e Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:38 -0500 Subject: staging/lustre: Change ioctl user pointers in libcfs_ioctl_data Make them void __user * instead of char * (or char __user *), void * removes the necessity of explicit casts to proper type where people also need to remember __user qualifiers, so I think it works better here. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 0c31bf9b8e8d..05f2191e08fb 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -61,9 +61,9 @@ struct libcfs_ioctl_data { char *ioc_inlbuf2; __u32 ioc_plen1; /* buffers in userspace */ - char *ioc_pbuf1; + void __user *ioc_pbuf1; __u32 ioc_plen2; /* buffers in userspace */ - char *ioc_pbuf2; + void __user *ioc_pbuf2; char ioc_bulk[0]; }; -- cgit v1.2.3 From 922cb32ca374fb729194d087c8f9aa17205d586e Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:39 -0500 Subject: staging/lustre: Update user pointers in struct obd_ioctl_data Make them void __user * instead of char * (or char __user *), void * removes the necessity of explicit casts to proper type where people also need to remember __user qualifiers, so I think it works better here. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_lib.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index 7daf9543f32c..3d75a8292d5f 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -153,9 +153,9 @@ struct obd_ioctl_data { /* buffers the kernel will treat as user pointers */ __u32 ioc_plen1; - char *ioc_pbuf1; + void __user *ioc_pbuf1; __u32 ioc_plen2; - char *ioc_pbuf2; + void __user *ioc_pbuf2; /* inline buffers for various arguments */ __u32 ioc_inllen1; -- cgit v1.2.3 From e3e8ff41c0ffe579ea48bd3250bc23abc4bd4b37 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:40 -0500 Subject: staging/lustre: Mark obd_ioctl_popdata/getdata argument as __user arg is a userspace pointer and marking it as such makes sparse happy. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_lib.h | 4 ++-- drivers/staging/lustre/lustre/llite/dir.c | 4 ++-- drivers/staging/lustre/lustre/obdclass/class_obd.c | 14 ++++++++------ .../staging/lustre/lustre/obdclass/linux/linux-module.c | 8 ++++---- 4 files changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index 3d75a8292d5f..cfccf7ca04c4 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -252,8 +252,8 @@ static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data) #include "obd_support.h" /* function defined in lustre/obdclass//-module.c */ -int obd_ioctl_getdata(char **buf, int *len, void *arg); -int obd_ioctl_popdata(void *arg, void *data, int len); +int obd_ioctl_getdata(char **buf, int *len, void __user *arg); +int obd_ioctl_popdata(void __user *arg, void *data, int len); static inline void obd_ioctl_freedata(char *buf, int len) { diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 2a5babe555e6..eb2fc23574ca 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1279,7 +1279,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) char *filename; struct md_op_data *op_data; - rc = obd_ioctl_getdata(&buf, &len, (void *)arg); + rc = obd_ioctl_getdata(&buf, &len, (void __user *)arg); if (rc) return rc; data = (void *)buf; @@ -1321,7 +1321,7 @@ out_free: int len; int rc; - rc = obd_ioctl_getdata(&buf, &len, (void *)arg); + rc = obd_ioctl_getdata(&buf, &len, (void __user *)arg); if (rc) return rc; diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 0975e443057c..65cf46c8c86e 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -180,7 +180,7 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) } CDEBUG(D_IOCTL, "cmd = %x\n", cmd); - if (obd_ioctl_getdata(&buf, &len, (void *)arg)) { + if (obd_ioctl_getdata(&buf, &len, (void __user *)arg)) { CERROR("OBD ioctl: data error\n"); return -EINVAL; } @@ -227,7 +227,7 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) memcpy(data->ioc_bulk, BUILD_VERSION, strlen(BUILD_VERSION) + 1); - err = obd_ioctl_popdata((void *)arg, data, len); + err = obd_ioctl_popdata((void __user *)arg, data, len); if (err) err = -EFAULT; goto out; @@ -246,7 +246,8 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) goto out; } - err = obd_ioctl_popdata((void *)arg, data, sizeof(*data)); + err = obd_ioctl_popdata((void __user *)arg, data, + sizeof(*data)); if (err) err = -EFAULT; goto out; @@ -283,7 +284,8 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1, dev); - err = obd_ioctl_popdata((void *)arg, data, sizeof(*data)); + err = obd_ioctl_popdata((void __user *)arg, data, + sizeof(*data)); if (err) err = -EFAULT; goto out; @@ -330,7 +332,7 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) (int)index, status, obd->obd_type->typ_name, obd->obd_name, obd->obd_uuid.uuid, atomic_read(&obd->obd_refcount)); - err = obd_ioctl_popdata((void *)arg, data, len); + err = obd_ioctl_popdata((void __user *)arg, data, len); err = 0; goto out; @@ -388,7 +390,7 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) if (err) goto out; - err = obd_ioctl_popdata((void *)arg, data, len); + err = obd_ioctl_popdata((void __user *)arg, data, len); if (err) err = -EFAULT; goto out; diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index a055cbb4f162..f8d3a639e85c 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -74,14 +74,14 @@ #include "../../include/lustre/lustre_build_version.h" /* buffer MUST be at least the size of obd_ioctl_hdr */ -int obd_ioctl_getdata(char **buf, int *len, void *arg) +int obd_ioctl_getdata(char **buf, int *len, void __user *arg) { struct obd_ioctl_hdr hdr; struct obd_ioctl_data *data; int err; int offset = 0; - if (copy_from_user(&hdr, (void *)arg, sizeof(hdr))) + if (copy_from_user(&hdr, arg, sizeof(hdr))) return -EFAULT; if (hdr.ioc_version != OBD_IOCTL_VERSION) { @@ -114,7 +114,7 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg) *len = hdr.ioc_len; data = (struct obd_ioctl_data *)*buf; - if (copy_from_user(*buf, (void *)arg, hdr.ioc_len)) { + if (copy_from_user(*buf, arg, hdr.ioc_len)) { err = -EFAULT; goto free_buf; } @@ -156,7 +156,7 @@ free_buf: } EXPORT_SYMBOL(obd_ioctl_getdata); -int obd_ioctl_popdata(void *arg, void *data, int len) +int obd_ioctl_popdata(void __user *arg, void *data, int len) { int err; -- cgit v1.2.3 From 4eb53dfd23281c6e358f26af56b3572bdcbfd43a Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:41 -0500 Subject: staging/lustre/lnet: Properly mark userspace pointer of lnet_ping() This also happens to silence sparce warnings about different address spaces. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/lnet/api-ni.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index 80b170ee5582..d33fbdf99505 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -62,7 +62,7 @@ module_param(rnet_htable_size, int, 0444); MODULE_PARM_DESC(rnet_htable_size, "size of remote network hash table"); static int lnet_ping(lnet_process_id_t id, int timeout_ms, - lnet_process_id_t *ids, int n_ids); + lnet_process_id_t __user *ids, int n_ids); static char * lnet_get_routes(void) @@ -1376,7 +1376,7 @@ LNetCtl(unsigned int cmd, void *arg) id.nid = data->ioc_nid; id.pid = data->ioc_u32[0]; rc = lnet_ping(id, data->ioc_u32[1], /* timeout */ - (lnet_process_id_t *)data->ioc_pbuf1, + data->ioc_pbuf1, data->ioc_plen1/sizeof(lnet_process_id_t)); if (rc < 0) return rc; @@ -1646,7 +1646,7 @@ lnet_ping_target_fini(void) } static int lnet_ping(lnet_process_id_t id, int timeout_ms, - lnet_process_id_t *ids, int n_ids) + lnet_process_id_t __user *ids, int n_ids) { lnet_handle_eq_t eqh; lnet_handle_md_t mdh; -- cgit v1.2.3 From 44164fc9922d4d5bd60de7a576ba5ebdeefe79a3 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:42 -0500 Subject: staging/lustre: Get rid of an ugly statfs hack in lov_iocontrol For some crazy reason ll_obd_statfs decided to decode async flag passed from userspace and then pass it via a userspace pointer argument to lov_iocontrol. This patch moves flags decoding to lov_iocontrol where it belongs. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_lib.c | 4 +--- drivers/staging/lustre/lustre/lov/lov_obd.c | 4 +++- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index b2fc5b3786ee..efff8307fb06 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -2026,7 +2026,6 @@ int ll_obd_statfs(struct inode *inode, void *arg) char *buf = NULL; struct obd_ioctl_data *data = NULL; __u32 type; - __u32 flags; int len = 0, rc; if (!inode) { @@ -2069,8 +2068,7 @@ int ll_obd_statfs(struct inode *inode, void *arg) goto out_statfs; } - flags = (type & LL_STATFS_NODELAY) ? OBD_STATFS_NODELAY : 0; - rc = obd_iocontrol(IOC_OBD_STATFS, exp, len, buf, &flags); + rc = obd_iocontrol(IOC_OBD_STATFS, exp, len, buf, NULL); if (rc) goto out_statfs; out_statfs: diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 6c2bdfe9cdcf..1dde0b8fa9a6 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1420,7 +1420,9 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, (int) sizeof(struct obd_uuid)))) return -EFAULT; - flags = uarg ? *(__u32 *)uarg : 0; + memcpy(&flags, data->ioc_inlbuf1, sizeof(__u32)); + flags = flags & LL_STATFS_NODELAY ? OBD_STATFS_NODELAY : 0; + /* got statfs data */ rc = obd_statfs(NULL, lov->lov_tgts[index]->ltd_exp, &stat_buf, cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), -- cgit v1.2.3 From e09bee346e3f10a3739c4c9ae4286bd09cdf2631 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:43 -0500 Subject: staging/lustre: Properly mark obd_iocontrol argument as __user Also update all methods and calls everywhere. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/obd.h | 2 +- drivers/staging/lustre/lustre/include/obd_class.h | 2 +- drivers/staging/lustre/lustre/llite/dir.c | 6 ++++-- drivers/staging/lustre/lustre/llite/file.c | 6 +++--- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 2 +- drivers/staging/lustre/lustre/lov/lov_obd.c | 2 +- drivers/staging/lustre/lustre/mdc/mdc_request.c | 2 +- drivers/staging/lustre/lustre/obdecho/echo_client.c | 2 +- drivers/staging/lustre/lustre/osc/osc_request.c | 2 +- 9 files changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 86897c2f6c68..f00d9a2e7afe 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -964,7 +964,7 @@ struct md_enqueue_info { struct obd_ops { struct module *owner; int (*iocontrol)(unsigned int cmd, struct obd_export *exp, int len, - void *karg, void *uarg); + void *karg, void __user *uarg); int (*get_info)(const struct lu_env *env, struct obd_export *, __u32 keylen, void *key, __u32 *vallen, void *val, struct lov_stripe_md *lsm); diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 97d80397503c..4f631e6bf048 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -1155,7 +1155,7 @@ static inline int obd_adjust_kms(struct obd_export *exp, } static inline int obd_iocontrol(unsigned int cmd, struct obd_export *exp, - int len, void *karg, void *uarg) + int len, void *karg, void __user *uarg) { int rc; diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index eb2fc23574ca..5cfe8bb5fce2 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1724,7 +1724,8 @@ out_quotactl: return -EFAULT; return 0; case LL_IOC_GET_CONNECT_FLAGS: { - return obd_iocontrol(cmd, sbi->ll_md_exp, 0, NULL, (void *)arg); + return obd_iocontrol(cmd, sbi->ll_md_exp, 0, NULL, + (void __user *)arg); } case OBD_IOC_CHANGELOG_SEND: case OBD_IOC_CHANGELOG_CLEAR: @@ -1847,7 +1848,8 @@ out_quotactl: return rc; } default: - return obd_iocontrol(cmd, sbi->ll_dt_exp, 0, NULL, (void *)arg); + return obd_iocontrol(cmd, sbi->ll_dt_exp, 0, NULL, + (void __user *)arg); } } diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 39e2ffd5f97f..c91b5b4111c9 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1518,7 +1518,7 @@ static int ll_lov_setstripe(struct inode *inode, struct file *file, ll_layout_refresh(inode, &gen); lsm = ccc_inode_lsm_get(inode); rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode), - 0, lsm, (void *)arg); + 0, lsm, (void __user *)arg); ccc_inode_lsm_put(inode, lsm); } return rc; @@ -1532,7 +1532,7 @@ static int ll_lov_getstripe(struct inode *inode, unsigned long arg) lsm = ccc_inode_lsm_get(inode); if (lsm != NULL) rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode), 0, - lsm, (void *)arg); + lsm, (void __user *)arg); ccc_inode_lsm_put(inode, lsm); return rc; } @@ -2497,7 +2497,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return err; return obd_iocontrol(cmd, ll_i2dtexp(inode), 0, NULL, - (void *)arg); + (void __user *)arg); } } } diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 9ebfb39a8188..59bdd580b249 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -876,7 +876,7 @@ static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, } static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp, - int len, void *karg, void *uarg) + int len, void *karg, void __user *uarg) { struct obd_device *obddev = class_exp2obd(exp); struct lmv_obd *lmv = &obddev->u.lmv; diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 1dde0b8fa9a6..65077b7e235b 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1385,7 +1385,7 @@ static int lov_statfs(const struct lu_env *env, struct obd_export *exp, } static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, - void *karg, void *uarg) + void *karg, void __user *uarg) { struct obd_device *obddev = class_exp2obd(exp); struct lov_obd *lov = &obddev->u.lov; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 3929f9129c8b..43481278096f 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1722,7 +1722,7 @@ static int mdc_ioc_swap_layouts(struct obd_export *exp, } static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, - void *karg, void *uarg) + void *karg, void __user *uarg) { struct obd_device *obd = exp->exp_obd; struct obd_ioctl_data *data = karg; diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 5b76c222e2cf..d3e398f70434 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1619,7 +1619,7 @@ static int echo_client_brw_ioctl(const struct lu_env *env, int rw, static int echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, - void *karg, void *uarg) + void *karg, void __user *uarg) { struct obd_device *obd = exp->exp_obd; struct echo_device *ed = obd2echo_dev(obd); diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 7034f0a942c5..6eb678c00e7b 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2591,7 +2591,7 @@ static int osc_getstripe(struct lov_stripe_md *lsm, struct lov_user_md *lump) } static int osc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, - void *karg, void *uarg) + void *karg, void __user *uarg) { struct obd_device *obd = exp->exp_obd; struct obd_ioctl_data *data = karg; -- cgit v1.2.3 From f2938c04b8f9b0223767ade931eeb63f3d7e0e68 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:44 -0500 Subject: staging/lustre: Properly mark argument to p_ioctl in cfs_psdev_ops as __user This also silents a sparse address space warning Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs.h | 2 +- drivers/staging/lustre/lustre/libcfs/linux/linux-module.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 094eb0f27954..dc9b88f2f977 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -77,7 +77,7 @@ struct cfs_psdev_ops { int (*p_close)(unsigned long, void *); int (*p_read)(struct cfs_psdev_file *, char *, unsigned long); int (*p_write)(struct cfs_psdev_file *, char *, unsigned long); - int (*p_ioctl)(struct cfs_psdev_file *, unsigned long, void *); + int (*p_ioctl)(struct cfs_psdev_file *, unsigned long, void __user *); }; /* diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c index c089b044ef2e..e5bc3d349d78 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c @@ -151,7 +151,7 @@ static long libcfs_ioctl(struct file *file, } if (libcfs_psdev_ops.p_ioctl != NULL) - rc = libcfs_psdev_ops.p_ioctl(&pfile, cmd, (void *)arg); + rc = libcfs_psdev_ops.p_ioctl(&pfile, cmd, (void __user *)arg); else rc = -EPERM; return rc; -- cgit v1.2.3 From cadffe60eae0a798d5fd5368930684d7d6d0998e Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:45 -0500 Subject: staging/lustre: Declare lprocfs_write_frac_u64_helper argument as __user The buffer that lprocfs_write_frac_u64_helper is working on is presumed to be a userspace one, so it's not suitable for use on kernel buffers. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lprocfs_status.h | 2 +- drivers/staging/lustre/lustre/obdclass/lprocfs_status.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h index 0ac8e0edcc48..fb13094d8b0b 100644 --- a/drivers/staging/lustre/lustre/include/lprocfs_status.h +++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h @@ -608,7 +608,7 @@ int lprocfs_write_helper(const char __user *buffer, unsigned long count, int *val); int lprocfs_write_u64_helper(const char __user *buffer, unsigned long count, __u64 *val); -int lprocfs_write_frac_u64_helper(const char *buffer, +int lprocfs_write_frac_u64_helper(const char __user *buffer, unsigned long count, __u64 *val, int mult); char *lprocfs_find_named_value(const char *buffer, const char *name, diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 51fe15f5d687..b65ad93eca4b 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -1319,8 +1319,8 @@ int lprocfs_write_u64_helper(const char __user *buffer, unsigned long count, } EXPORT_SYMBOL(lprocfs_write_u64_helper); -int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, - __u64 *val, int mult) +int lprocfs_write_frac_u64_helper(const char __user *buffer, + unsigned long count, __u64 *val, int mult) { char kernbuf[22], *end, *pbuf; __u64 whole, frac = 0, units; -- cgit v1.2.3 From 0dd48a43fd2591e4b48ae6fd6196779de49dcf51 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:46 -0500 Subject: staging/lustre/osc: Do not use lprocfs_write_helper in sysfs store methods sysfs store methods provide us with a kernel buffer already, but lprocfs_write_helper is expecting a user buffer. Replace lprocfs_write_helper with kstrto[u]int() calls instead in contention_seconds_store() and lockless_truncate_store() Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/lproc_osc.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c index 1091536fc90d..b69ec0fa0203 100644 --- a/drivers/staging/lustre/lustre/osc/lproc_osc.c +++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c @@ -480,9 +480,19 @@ static ssize_t contention_seconds_store(struct kobject *kobj, struct obd_device *obd = container_of(kobj, struct obd_device, obd_kobj); struct osc_device *od = obd2osc_dev(obd); + int rc; + int val; + + rc = kstrtoint(buffer, 10, &val); + if (rc) + return rc; + + if (val < 0) + return -EINVAL; + + od->od_contention_time = val; - return lprocfs_write_helper(buffer, count, &od->od_contention_time) ?: - count; + return count; } LUSTRE_RW_ATTR(contention_seconds); @@ -505,9 +515,16 @@ static ssize_t lockless_truncate_store(struct kobject *kobj, struct obd_device *obd = container_of(kobj, struct obd_device, obd_kobj); struct osc_device *od = obd2osc_dev(obd); + int rc; + unsigned int val; - return lprocfs_write_helper(buffer, count, &od->od_lockless_truncate) ?: - count; + rc = kstrtouint(buffer, 10, &val); + if (rc) + return rc; + + od->od_lockless_truncate = val; + + return count; } LUSTRE_RW_ATTR(lockless_truncate); -- cgit v1.2.3 From 4c6243ec8437550019963335f252842a750cb6f6 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:47 -0500 Subject: staging/lustre/llite: Properly mark ll_obd_statfs argument as __user Also update all callers. This fixes a bunch of address space mismatch warnings from sparse. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 2 +- drivers/staging/lustre/lustre/llite/file.c | 2 +- drivers/staging/lustre/lustre/llite/llite_internal.h | 2 +- drivers/staging/lustre/lustre/llite/llite_lib.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 5cfe8bb5fce2..5b41162c7b35 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1434,7 +1434,7 @@ free_lmv: case LL_IOC_LOV_SWAP_LAYOUTS: return -EPERM; case LL_IOC_OBD_STATFS: - return ll_obd_statfs(inode, (void *)arg); + return ll_obd_statfs(inode, (void __user *)arg); case LL_IOC_LOV_GETSTRIPE: case LL_IOC_MDC_GETINFO: case IOC_MDC_GETFILEINFO: diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index c91b5b4111c9..6652fdf2ca8a 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2278,7 +2278,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case LL_IOC_GROUP_UNLOCK: return ll_put_grouplock(inode, file, arg); case IOC_OBD_STATFS: - return ll_obd_statfs(inode, (void *)arg); + return ll_obd_statfs(inode, (void __user *)arg); /* We need to special case any other ioctls we want to handle, * to send them to the MDS/OST as appropriate and to properly diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index e73024778808..29c325d5c4e6 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -782,7 +782,7 @@ int ll_show_options(struct seq_file *seq, struct dentry *dentry); void ll_dirty_page_discard_warn(struct page *page, int ioret); int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, struct super_block *, struct lookup_intent *); -int ll_obd_statfs(struct inode *inode, void *arg); +int ll_obd_statfs(struct inode *inode, void __user *arg); int ll_get_max_mdsize(struct ll_sb_info *sbi, int *max_mdsize); int ll_get_default_mdsize(struct ll_sb_info *sbi, int *default_mdsize); int ll_process_config(struct lustre_cfg *lcfg); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index efff8307fb06..68fa766adcbb 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -2019,7 +2019,7 @@ cleanup: return rc; } -int ll_obd_statfs(struct inode *inode, void *arg) +int ll_obd_statfs(struct inode *inode, void __user *arg) { struct ll_sb_info *sbi = NULL; struct obd_export *exp; -- cgit v1.2.3 From 97514241423bfebf4a87395698c54d8c244eaf22 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:48 -0500 Subject: staging/lustre/llite: Fix improper userspace access in ll_fiemap Cannot use memcpy, but use copy_to/from_user instead Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 6652fdf2ca8a..9e50e9e19a28 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -3033,19 +3033,26 @@ static int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, fiemap->fm_extent_count = fieinfo->fi_extents_max; fiemap->fm_start = start; fiemap->fm_length = len; - if (extent_count > 0) - memcpy(&fiemap->fm_extents[0], fieinfo->fi_extents_start, - sizeof(struct ll_fiemap_extent)); + if (extent_count > 0 && + copy_from_user(&fiemap->fm_extents[0], fieinfo->fi_extents_start, + sizeof(struct ll_fiemap_extent)) != 0) { + rc = -EFAULT; + goto out; + } rc = ll_do_fiemap(inode, fiemap, num_bytes); fieinfo->fi_flags = fiemap->fm_flags; fieinfo->fi_extents_mapped = fiemap->fm_mapped_extents; - if (extent_count > 0) - memcpy(fieinfo->fi_extents_start, &fiemap->fm_extents[0], - fiemap->fm_mapped_extents * - sizeof(struct ll_fiemap_extent)); + if (extent_count > 0 && + copy_to_user(fieinfo->fi_extents_start, &fiemap->fm_extents[0], + fiemap->fm_mapped_extents * + sizeof(struct ll_fiemap_extent)) != 0) { + rc = -EFAULT; + goto out; + } +out: kvfree(fiemap); return rc; } -- cgit v1.2.3 From 55f37f01f92163760970a4b866caf8cef2f57f12 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:49 -0500 Subject: staging/lustre: Declare lov_getstripe lump argument as __user This is a user pointer, so that makes sparse a lot happier. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_internal.h | 2 +- drivers/staging/lustre/lustre/lov/lov_pack.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index 2d00bad58e35..f8e92fee02ce 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -197,7 +197,7 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmm, int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, struct lov_mds_md *lmm, int lmm_bytes); int lov_getstripe(struct obd_export *exp, - struct lov_stripe_md *lsm, struct lov_user_md *lump); + struct lov_stripe_md *lsm, struct lov_user_md __user *lump); int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count, int pattern, int magic); int lov_free_memmd(struct lov_stripe_md **lsmp); diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index 6b2d1007192b..a78211f64007 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -376,7 +376,7 @@ int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, * lmm_magic must be LOV_USER_MAGIC. */ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, - struct lov_user_md *lump) + struct lov_user_md __user *lump) { /* * XXX huge struct allocated on stack. -- cgit v1.2.3 From 7ac5db212d5cf77b84e9d3bd300056c217d6e49e Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:50 -0500 Subject: staging/lustre/llite: Update llite_lib.c with proper __user attributes Casts for get/put_user and copy_to/from_user should have __user attribute for the userspace buffer address. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_lib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 68fa766adcbb..446e4b8d3b4e 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1744,14 +1744,14 @@ int ll_iocontrol(struct inode *inode, struct file *file, ptlrpc_req_finished(req); - return put_user(flags, (int *)arg); + return put_user(flags, (int __user *)arg); } case FSFILT_IOC_SETFLAGS: { struct lov_stripe_md *lsm; struct obd_info oinfo = { }; struct md_op_data *op_data; - if (get_user(flags, (int *)arg)) + if (get_user(flags, (int __user *)arg)) return -EFAULT; op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, @@ -2219,8 +2219,8 @@ int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg) if (!obd) return -ENOENT; - if (copy_to_user((void *)arg, obd->obd_name, - strlen(obd->obd_name) + 1)) + if (copy_to_user((void __user *)arg, obd->obd_name, + strlen(obd->obd_name) + 1)) return -EFAULT; return 0; -- cgit v1.2.3 From ec2d71d0835decc8e5a358e7d8080a92eead4baa Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:51 -0500 Subject: staging/lustre/osc: Mark osc_getstripe user pointer argument as __user This shuts some sparse address space mismatch warnings Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/osc_request.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 6eb678c00e7b..3ae00fc3f996 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2534,7 +2534,8 @@ static int osc_statfs(const struct lu_env *env, struct obd_export *exp, * the maximum number of OST indices which will fit in the user buffer. * lmm_magic must be LOV_MAGIC (we only use 1 slot here). */ -static int osc_getstripe(struct lov_stripe_md *lsm, struct lov_user_md *lump) +static int osc_getstripe(struct lov_stripe_md *lsm, + struct lov_user_md __user *lump) { /* we use lov_user_md_v3 because it is larger than lov_user_md_v1 */ struct lov_user_md_v3 lum, *lumk; -- cgit v1.2.3 From 6f9a3bd93f48127164e1599f0e1f9d4e16f9cb89 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:52 -0500 Subject: staging/lustre/lloop: Properly mark userspace pointers in lo/lloop_ioctl When casting unsigned long userspace pointer for use with userspace-accessing functions, need to use __user attribute to make sparse happy. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/lloop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c index 871924b3f2e7..69c41afd1faa 100644 --- a/drivers/staging/lustre/lustre/llite/lloop.c +++ b/drivers/staging/lustre/lustre/llite/lloop.c @@ -636,7 +636,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, else fid_zero(&fid); - if (copy_to_user((struct lu_fid *)arg, &fid, sizeof(fid))) + if (copy_to_user((void __user *)arg, &fid, sizeof(fid))) err = -EFAULT; break; } @@ -708,7 +708,7 @@ static enum llioc_iter lloop_ioctl(struct inode *unused, struct file *file, dev = MKDEV(lloop_major, lo->lo_number); /* quit if the used pointer is writable */ - if (put_user((long)old_encode_dev(dev), (long *)arg)) { + if (put_user((long)old_encode_dev(dev), (long __user *)arg)) { err = -EFAULT; goto out; } -- cgit v1.2.3 From 0f881d7b266eaa010c9cd6b621f74a876337c5a5 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:53 -0500 Subject: staging/lustre: Properly mark lmv_fid2path uarg argment as __user This makes sparse happy too. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 59bdd580b249..7a6fc5555ea1 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -663,7 +663,8 @@ out_local: return rc; } -static int lmv_fid2path(struct obd_export *exp, int len, void *karg, void *uarg) +static int lmv_fid2path(struct obd_export *exp, int len, void *karg, + void __user *uarg) { struct obd_device *obddev = class_exp2obd(exp); struct lmv_obd *lmv = &obddev->u.lmv; -- cgit v1.2.3 From 11be8f6cdc8b0cdeb1d392dfb473f533ef435d0c Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:54 -0500 Subject: staging/lustre: Mark lmv_hsm_ct_register/unregister uarg as __user Since it is a userspace pointer, this makes things neater and sparse happier. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 7a6fc5555ea1..733222cb1a1c 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -794,7 +794,8 @@ static void lmv_hsm_req_build(struct lmv_obd *lmv, } static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len, - struct lustre_kernelcomm *lk, void *uarg) + struct lustre_kernelcomm *lk, + void __user *uarg) { int rc = 0; __u32 i; @@ -816,7 +817,7 @@ static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len, } static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, - struct lustre_kernelcomm *lk, void *uarg) + struct lustre_kernelcomm *lk, void __user *uarg) { struct file *filp; __u32 i, j; -- cgit v1.2.3 From 02f9c12e32605446f4ac48be0598b92f0b940764 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:55 -0500 Subject: staging/lustre/llite: Update all file.c user pointer casts to __user unsigned long user address must be casted with __user attribute to make sparse happy when used with userspace access functions. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 47 +++++++++++++++--------------- 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 9e50e9e19a28..f31f75a446ec 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1307,7 +1307,7 @@ static int ll_lov_recreate_obj(struct inode *inode, unsigned long arg) if (!capable(CFS_CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&ucreat, (struct ll_recreate_obj *)arg, + if (copy_from_user(&ucreat, (struct ll_recreate_obj __user *)arg, sizeof(ucreat))) return -EFAULT; @@ -1325,7 +1325,7 @@ static int ll_lov_recreate_fid(struct inode *inode, unsigned long arg) if (!capable(CFS_CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&fid, (struct lu_fid *)arg, sizeof(fid))) + if (copy_from_user(&fid, (struct lu_fid __user *)arg, sizeof(fid))) return -EFAULT; fid_to_ostid(&fid, &oi); @@ -1472,7 +1472,7 @@ static int ll_lov_setea(struct inode *inode, struct file *file, if (lump == NULL) return -ENOMEM; - if (copy_from_user(lump, (struct lov_user_md *)arg, lum_size)) { + if (copy_from_user(lump, (struct lov_user_md __user *)arg, lum_size)) { kvfree(lump); return -EFAULT; } @@ -1488,12 +1488,12 @@ static int ll_lov_setea(struct inode *inode, struct file *file, static int ll_lov_setstripe(struct inode *inode, struct file *file, unsigned long arg) { - struct lov_user_md_v3 lumv3; - struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3; - struct lov_user_md_v1 *lumv1p = (struct lov_user_md_v1 *)arg; - struct lov_user_md_v3 *lumv3p = (struct lov_user_md_v3 *)arg; - int lum_size, rc; - int flags = FMODE_WRITE; + struct lov_user_md_v3 lumv3; + struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3; + struct lov_user_md_v1 __user *lumv1p = (void __user *)arg; + struct lov_user_md_v3 __user *lumv3p = (void __user *)arg; + int lum_size, rc; + int flags = FMODE_WRITE; /* first try with v1 which is smaller than v3 */ lum_size = sizeof(struct lov_user_md_v1); @@ -1826,7 +1826,7 @@ static int ll_ioctl_fiemap(struct inode *inode, unsigned long arg) ret_bytes += (fiemap_s->fm_mapped_extents * sizeof(struct ll_fiemap_extent)); - if (copy_to_user((void *)arg, fiemap_s, ret_bytes)) + if (copy_to_user((void __user *)arg, fiemap_s, ret_bytes)) rc = -EFAULT; error: @@ -2211,14 +2211,14 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) switch (cmd) { case LL_IOC_GETFLAGS: /* Get the current value of the file flags */ - return put_user(fd->fd_flags, (int *)arg); + return put_user(fd->fd_flags, (int __user *)arg); case LL_IOC_SETFLAGS: case LL_IOC_CLRFLAGS: /* Set or clear specific file flags */ /* XXX This probably needs checks to ensure the flags are * not abused, and to handle any flag side effects. */ - if (get_user(flags, (int *) arg)) + if (get_user(flags, (int __user *)arg)) return -EFAULT; if (cmd == LL_IOC_SETFLAGS) { @@ -2242,8 +2242,8 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct file *file2; struct lustre_swap_layouts lsl; - if (copy_from_user(&lsl, (char *)arg, - sizeof(struct lustre_swap_layouts))) + if (copy_from_user(&lsl, (char __user *)arg, + sizeof(struct lustre_swap_layouts))) return -EFAULT; if ((file->f_flags & O_ACCMODE) == 0) /* O_RDONLY */ @@ -2272,7 +2272,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return ll_iocontrol(inode, file, cmd, arg); case FSFILT_IOC_GETVERSION_OLD: case FSFILT_IOC_GETVERSION: - return put_user(inode->i_generation, (int *)arg); + return put_user(inode->i_generation, (int __user *)arg); case LL_IOC_GROUP_LOCK: return ll_get_grouplock(inode, file, arg); case LL_IOC_GROUP_UNLOCK: @@ -2289,7 +2289,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case LL_IOC_FLUSHCTX: return ll_flush_ctx(inode); case LL_IOC_PATH2FID: { - if (copy_to_user((void *)arg, ll_inode2fid(inode), + if (copy_to_user((void __user *)arg, ll_inode2fid(inode), sizeof(struct lu_fid))) return -EFAULT; @@ -2301,13 +2301,14 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct ioc_data_version idv; int rc; - if (copy_from_user(&idv, (char *)arg, sizeof(idv))) + if (copy_from_user(&idv, (char __user *)arg, sizeof(idv))) return -EFAULT; rc = ll_data_version(inode, &idv.idv_version, !(idv.idv_flags & LL_DV_NOFLUSH)); - if (rc == 0 && copy_to_user((char *) arg, &idv, sizeof(idv))) + if (rc == 0 && copy_to_user((char __user *)arg, &idv, + sizeof(idv))) return -EFAULT; return rc; @@ -2320,7 +2321,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (mdtidx < 0) return mdtidx; - if (put_user((int)mdtidx, (int *)arg)) + if (put_user(mdtidx, (int __user *)arg)) return -EFAULT; return 0; @@ -2347,7 +2348,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) rc = obd_iocontrol(cmd, ll_i2mdexp(inode), sizeof(*op_data), op_data, NULL); - if (copy_to_user((void *)arg, hus, sizeof(*hus))) + if (copy_to_user((void __user *)arg, hus, sizeof(*hus))) rc = -EFAULT; ll_finish_md_op_data(op_data); @@ -2358,7 +2359,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct hsm_state_set *hss; int rc; - hss = memdup_user((char *)arg, sizeof(*hss)); + hss = memdup_user((char __user *)arg, sizeof(*hss)); if (IS_ERR(hss)) return PTR_ERR(hss); @@ -2386,7 +2387,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) rc = obd_iocontrol(cmd, ll_i2mdexp(inode), sizeof(*op_data), op_data, NULL); - if (copy_to_user((char *)arg, hca, sizeof(*hca))) + if (copy_to_user((char __user *)arg, hca, sizeof(*hca))) rc = -EFAULT; ll_finish_md_op_data(op_data); @@ -2480,7 +2481,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case LL_IOC_HSM_IMPORT: { struct hsm_user_import *hui; - hui = memdup_user((void *)arg, sizeof(*hui)); + hui = memdup_user((void __user *)arg, sizeof(*hui)); if (IS_ERR(hui)) return PTR_ERR(hui); -- cgit v1.2.3 From 61dad0ba9abbe97b80b2199c126e56b1598545eb Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:56 -0500 Subject: staging/lustre: Properly cast ll_fid2path argument to __user in ll_file_ioctl When calling ll_fid2path, it expects a userspace pointer. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index f31f75a446ec..132d19b62147 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2296,7 +2296,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; } case OBD_IOC_FID2PATH: - return ll_fid2path(inode, (void *)arg); + return ll_fid2path(inode, (void __user *)arg); case LL_IOC_DATA_VERSION: { struct ioc_data_version idv; int rc; -- cgit v1.2.3 From 7ec89fa54a37b3e8eb8ec5e5b64c845961762e22 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:57 -0500 Subject: staging/lustre: Properly cast ll_fid2path argument to __user in ll_dir_ioctl This makes sparse happier. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 5b41162c7b35..15b8e0a444fa 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1736,7 +1736,7 @@ out_quotactl: sizeof(struct ioc_changelog)); return rc; case OBD_IOC_FID2PATH: - return ll_fid2path(inode, (void *)arg); + return ll_fid2path(inode, (void __user *)arg); case LL_IOC_HSM_REQUEST: { struct hsm_user_request *hur; ssize_t totalsize; -- cgit v1.2.3 From d47bb83b1bb778fb8429dc1f12a137039cee4e14 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:58 -0500 Subject: staging/lustre: Properly cast ll_getname argument to __user in ll_dir_ioctl This makes sparse happy. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 15b8e0a444fa..fc68e8b4c176 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1448,7 +1448,7 @@ free_lmv: if (cmd == IOC_MDC_GETFILEINFO || cmd == IOC_MDC_GETFILESTRIPE) { - filename = ll_getname((const char *)arg); + filename = ll_getname((const char __user *)arg); if (IS_ERR(filename)) return PTR_ERR(filename); -- cgit v1.2.3 From af00f6c5ac2470b44cba595cbc17160e60356d08 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:59 -0500 Subject: staging/lustre/llite: Update ll_dir_ioctl pointer casts with __user When casting unsingned long userspace pointer from ioctl argument to a pointer suitable for use with userspace access functions, need to remember to add __user attribute, to make sparse happy. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 69 ++++++++++++++++--------------- 1 file changed, 35 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index fc68e8b4c176..36b10559154a 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1253,7 +1253,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return ll_iocontrol(inode, file, cmd, arg); case FSFILT_IOC_GETVERSION_OLD: case FSFILT_IOC_GETVERSION: - return put_user(inode->i_generation, (int *)arg); + return put_user(inode->i_generation, (int __user *)arg); /* We need to special case any other ioctls we want to handle, * to send them to the MDS/OST as appropriate and to properly * network encode the arg field. @@ -1267,7 +1267,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (mdtidx < 0) return mdtidx; - if (put_user((int)mdtidx, (int *)arg)) + if (put_user((int)mdtidx, (int __user *)arg)) return -EFAULT; return 0; @@ -1364,8 +1364,8 @@ lmv_out_free: case LL_IOC_LOV_SETSTRIPE: { struct lov_user_md_v3 lumv3; struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3; - struct lov_user_md_v1 *lumv1p = (struct lov_user_md_v1 *)arg; - struct lov_user_md_v3 *lumv3p = (struct lov_user_md_v3 *)arg; + struct lov_user_md_v1 __user *lumv1p = (void __user *)arg; + struct lov_user_md_v3 __user *lumv3p = (void __user *)arg; int set_default = 0; @@ -1390,7 +1390,7 @@ lmv_out_free: return rc; } case LL_IOC_LMV_GETSTRIPE: { - struct lmv_user_md *lump = (struct lmv_user_md *)arg; + struct lmv_user_md __user *lump = (void __user *)arg; struct lmv_user_md lum; struct lmv_user_md *tmp; int lum_size; @@ -1423,7 +1423,7 @@ lmv_out_free: tmp->lum_objects[0].lum_mds = mdtindex; memcpy(&tmp->lum_objects[0].lum_fid, ll_inode2fid(inode), sizeof(struct lu_fid)); - if (copy_to_user((void *)arg, tmp, lum_size)) { + if (copy_to_user((void __user *)arg, tmp, lum_size)) { rc = -EFAULT; goto free_lmv; } @@ -1440,7 +1440,7 @@ free_lmv: case IOC_MDC_GETFILEINFO: case IOC_MDC_GETFILESTRIPE: { struct ptlrpc_request *request = NULL; - struct lov_user_md *lump; + struct lov_user_md __user *lump; struct lov_mds_md *lmm = NULL; struct mdt_body *body; char *filename = NULL; @@ -1477,11 +1477,11 @@ free_lmv: if (cmd == IOC_MDC_GETFILESTRIPE || cmd == LL_IOC_LOV_GETSTRIPE) { - lump = (struct lov_user_md *)arg; + lump = (struct lov_user_md __user *)arg; } else { - struct lov_user_mds_data *lmdp; + struct lov_user_mds_data __user *lmdp; - lmdp = (struct lov_user_mds_data *)arg; + lmdp = (struct lov_user_mds_data __user *)arg; lump = &lmdp->lmd_lmm; } if (copy_to_user(lump, lmm, lmmsize)) { @@ -1493,7 +1493,7 @@ free_lmv: } skip_lmm: if (cmd == IOC_MDC_GETFILEINFO || cmd == LL_IOC_MDC_GETINFO) { - struct lov_user_mds_data *lmdp; + struct lov_user_mds_data __user *lmdp; lstat_t st = { 0 }; st.st_dev = inode->i_sb->s_dev; @@ -1510,7 +1510,7 @@ skip_lmm: st.st_ctime = body->ctime; st.st_ino = inode->i_ino; - lmdp = (struct lov_user_mds_data *)arg; + lmdp = (struct lov_user_mds_data __user *)arg; if (copy_to_user(&lmdp->lmd_st, &st, sizeof(st))) { rc = -EFAULT; goto out_req; @@ -1524,14 +1524,14 @@ out_req: return rc; } case IOC_LOV_GETINFO: { - struct lov_user_mds_data *lumd; + struct lov_user_mds_data __user *lumd; struct lov_stripe_md *lsm; - struct lov_user_md *lum; + struct lov_user_md __user *lum; struct lov_mds_md *lmm; int lmmsize; lstat_t st; - lumd = (struct lov_user_mds_data *)arg; + lumd = (struct lov_user_mds_data __user *)arg; lum = &lumd->lmd_lmm; rc = ll_get_max_mdsize(sbi, &lmmsize); @@ -1637,8 +1637,8 @@ free_lmm: NULL); if (rc) { CDEBUG(D_QUOTA, "mdc ioctl %d failed: %d\n", cmd, rc); - if (copy_to_user((void *)arg, check, - sizeof(*check))) + if (copy_to_user((void __user *)arg, check, + sizeof(*check))) CDEBUG(D_QUOTA, "copy_to_user failed\n"); goto out_poll; } @@ -1647,8 +1647,8 @@ free_lmm: NULL); if (rc) { CDEBUG(D_QUOTA, "osc ioctl %d failed: %d\n", cmd, rc); - if (copy_to_user((void *)arg, check, - sizeof(*check))) + if (copy_to_user((void __user *)arg, check, + sizeof(*check))) CDEBUG(D_QUOTA, "copy_to_user failed\n"); goto out_poll; } @@ -1663,14 +1663,15 @@ out_poll: if (!qctl) return -ENOMEM; - if (copy_from_user(qctl, (void *)arg, sizeof(*qctl))) { + if (copy_from_user(qctl, (void __user *)arg, sizeof(*qctl))) { rc = -EFAULT; goto out_quotactl; } rc = quotactl_ioctl(sbi, qctl); - if (rc == 0 && copy_to_user((void *)arg, qctl, sizeof(*qctl))) + if (rc == 0 && copy_to_user((void __user *)arg, qctl, + sizeof(*qctl))) rc = -EFAULT; out_quotactl: @@ -1700,7 +1701,7 @@ out_quotactl: int count, vallen; struct obd_export *exp; - if (copy_from_user(&count, (int *)arg, sizeof(int))) + if (copy_from_user(&count, (int __user *)arg, sizeof(int))) return -EFAULT; /* get ost count when count is zero, get mdt count otherwise */ @@ -1713,14 +1714,14 @@ out_quotactl: return rc; } - if (copy_to_user((int *)arg, &count, sizeof(int))) + if (copy_to_user((int __user *)arg, &count, sizeof(int))) return -EFAULT; return 0; } case LL_IOC_PATH2FID: - if (copy_to_user((void *)arg, ll_inode2fid(inode), - sizeof(struct lu_fid))) + if (copy_to_user((void __user *)arg, ll_inode2fid(inode), + sizeof(struct lu_fid))) return -EFAULT; return 0; case LL_IOC_GET_CONNECT_FLAGS: { @@ -1732,7 +1733,7 @@ out_quotactl: if (!capable(CFS_CAP_SYS_ADMIN)) return -EPERM; - rc = copy_and_ioctl(cmd, sbi->ll_md_exp, (void *)arg, + rc = copy_and_ioctl(cmd, sbi->ll_md_exp, (void __user *)arg, sizeof(struct ioc_changelog)); return rc; case OBD_IOC_FID2PATH: @@ -1741,7 +1742,7 @@ out_quotactl: struct hsm_user_request *hur; ssize_t totalsize; - hur = memdup_user((void *)arg, sizeof(*hur)); + hur = memdup_user((void __user *)arg, sizeof(*hur)); if (IS_ERR(hur)) return PTR_ERR(hur); @@ -1760,7 +1761,7 @@ out_quotactl: return -ENOMEM; /* Copy the whole struct */ - if (copy_from_user(hur, (void *)arg, totalsize)) { + if (copy_from_user(hur, (void __user *)arg, totalsize)) { kvfree(hur); return -EFAULT; } @@ -1796,7 +1797,7 @@ out_quotactl: struct hsm_progress_kernel hpk; struct hsm_progress hp; - if (copy_from_user(&hp, (void *)arg, sizeof(hp))) + if (copy_from_user(&hp, (void __user *)arg, sizeof(hp))) return -EFAULT; hpk.hpk_fid = hp.hp_fid; @@ -1813,7 +1814,7 @@ out_quotactl: return rc; } case LL_IOC_HSM_CT_START: - rc = copy_and_ioctl(cmd, sbi->ll_md_exp, (void *)arg, + rc = copy_and_ioctl(cmd, sbi->ll_md_exp, (void __user *)arg, sizeof(struct lustre_kernelcomm)); return rc; @@ -1821,12 +1822,12 @@ out_quotactl: struct hsm_copy *copy; int rc; - copy = memdup_user((char *)arg, sizeof(*copy)); + copy = memdup_user((char __user *)arg, sizeof(*copy)); if (IS_ERR(copy)) return PTR_ERR(copy); rc = ll_ioc_copy_start(inode->i_sb, copy); - if (copy_to_user((char *)arg, copy, sizeof(*copy))) + if (copy_to_user((char __user *)arg, copy, sizeof(*copy))) rc = -EFAULT; kfree(copy); @@ -1836,12 +1837,12 @@ out_quotactl: struct hsm_copy *copy; int rc; - copy = memdup_user((char *)arg, sizeof(*copy)); + copy = memdup_user((char __user *)arg, sizeof(*copy)); if (IS_ERR(copy)) return PTR_ERR(copy); rc = ll_ioc_copy_end(inode->i_sb, copy); - if (copy_to_user((char *)arg, copy, sizeof(*copy))) + if (copy_to_user((char __user *)arg, copy, sizeof(*copy))) rc = -EFAULT; kfree(copy); -- cgit v1.2.3 From 08816b2eb1ee4b41b52abc4b94b97cd2c5c15c10 Mon Sep 17 00:00:00 2001 From: Frank Zago Date: Sun, 3 Jan 2016 12:06:00 -0500 Subject: staging/lustre: Add __user annotations in lnetselftest code This fixes a bunch of sparse warnings. There is no code change. Signed-off-by: frank zago Reviewed-on: http://review.whamcloud.com/11819 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5396 Reviewed-by: James Simmons Reviewed-by: Dmitry Eremin Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/lnet/lnetst.h | 104 ++++++++++----------- drivers/staging/lustre/lnet/selftest/conrpc.c | 4 +- drivers/staging/lustre/lnet/selftest/conrpc.h | 5 +- drivers/staging/lustre/lnet/selftest/console.c | 96 ++++++++++--------- drivers/staging/lustre/lnet/selftest/console.h | 56 +++++------ 5 files changed, 138 insertions(+), 127 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/lnet/lnetst.h b/drivers/staging/lustre/include/linux/lnet/lnetst.h index fd1e0fd3696f..417044552d3f 100644 --- a/drivers/staging/lustre/include/linux/lnet/lnetst.h +++ b/drivers/staging/lustre/include/linux/lnet/lnetst.h @@ -245,20 +245,20 @@ typedef struct { int lstio_ses_force; /* IN: force create ? */ /** IN: session features */ unsigned lstio_ses_feats; - lst_sid_t *lstio_ses_idp; /* OUT: session id */ + lst_sid_t __user *lstio_ses_idp; /* OUT: session id */ int lstio_ses_nmlen; /* IN: name length */ - char *lstio_ses_namep; /* IN: session name */ + char __user *lstio_ses_namep; /* IN: session name */ } lstio_session_new_args_t; /* query current session */ typedef struct { - lst_sid_t *lstio_ses_idp; /* OUT: session id */ - int *lstio_ses_keyp; /* OUT: local key */ + lst_sid_t __user *lstio_ses_idp; /* OUT: session id */ + int __user *lstio_ses_keyp; /* OUT: local key */ /** OUT: session features */ - unsigned *lstio_ses_featp; - lstcon_ndlist_ent_t *lstio_ses_ndinfo; /* OUT: */ + unsigned __user *lstio_ses_featp; + lstcon_ndlist_ent_t __user *lstio_ses_ndinfo; /* OUT: */ int lstio_ses_nmlen; /* IN: name length */ - char *lstio_ses_namep; /* OUT: session name */ + char __user *lstio_ses_namep; /* OUT: session name */ } lstio_session_info_args_t; /* delete a session */ @@ -283,26 +283,26 @@ typedef struct { int lstio_dbg_timeout; /* IN: timeout of debug */ int lstio_dbg_nmlen; /* IN: len of name */ - char *lstio_dbg_namep; /* IN: name of + char __user *lstio_dbg_namep; /* IN: name of group|batch */ int lstio_dbg_count; /* IN: # of test nodes to debug */ - lnet_process_id_t *lstio_dbg_idsp; /* IN: id of test + lnet_process_id_t __user *lstio_dbg_idsp; /* IN: id of test nodes */ - struct list_head *lstio_dbg_resultp; /* OUT: list head of + struct list_head __user *lstio_dbg_resultp; /* OUT: list head of result buffer */ } lstio_debug_args_t; typedef struct { - int lstio_grp_key; /* IN: session key */ - int lstio_grp_nmlen; /* IN: name length */ - char *lstio_grp_namep; /* IN: group name */ + int lstio_grp_key; /* IN: session key */ + int lstio_grp_nmlen; /* IN: name length */ + char __user *lstio_grp_namep; /* IN: group name */ } lstio_group_add_args_t; typedef struct { - int lstio_grp_key; /* IN: session key */ - int lstio_grp_nmlen; /* IN: name length */ - char *lstio_grp_namep; /* IN: group name */ + int lstio_grp_key; /* IN: session key */ + int lstio_grp_nmlen; /* IN: name length */ + char __user *lstio_grp_namep; /* IN: group name */ } lstio_group_del_args_t; #define LST_GROUP_CLEAN 1 /* remove inactive nodes in the group */ @@ -315,22 +315,22 @@ typedef struct { int lstio_grp_opc; /* IN: OPC */ int lstio_grp_args; /* IN: arguments */ int lstio_grp_nmlen; /* IN: name length */ - char *lstio_grp_namep; /* IN: group name */ + char __user *lstio_grp_namep; /* IN: group name */ int lstio_grp_count; /* IN: # of nodes id */ - lnet_process_id_t *lstio_grp_idsp; /* IN: array of nodes */ - struct list_head *lstio_grp_resultp; /* OUT: list head of + lnet_process_id_t __user *lstio_grp_idsp; /* IN: array of nodes */ + struct list_head __user *lstio_grp_resultp; /* OUT: list head of result buffer */ } lstio_group_update_args_t; typedef struct { int lstio_grp_key; /* IN: session key */ int lstio_grp_nmlen; /* IN: name length */ - char *lstio_grp_namep; /* IN: group name */ + char __user *lstio_grp_namep; /* IN: group name */ int lstio_grp_count; /* IN: # of nodes */ /** OUT: session features */ - unsigned *lstio_grp_featp; - lnet_process_id_t *lstio_grp_idsp; /* IN: nodes */ - struct list_head *lstio_grp_resultp; /* OUT: list head of + unsigned __user *lstio_grp_featp; + lnet_process_id_t __user *lstio_grp_idsp; /* IN: nodes */ + struct list_head __user *lstio_grp_resultp; /* OUT: list head of result buffer */ } lstio_group_nodes_args_t; @@ -338,18 +338,18 @@ typedef struct { int lstio_grp_key; /* IN: session key */ int lstio_grp_idx; /* IN: group idx */ int lstio_grp_nmlen; /* IN: name len */ - char *lstio_grp_namep; /* OUT: name */ + char __user *lstio_grp_namep; /* OUT: name */ } lstio_group_list_args_t; typedef struct { int lstio_grp_key; /* IN: session key */ int lstio_grp_nmlen; /* IN: name len */ - char *lstio_grp_namep; /* IN: name */ - lstcon_ndlist_ent_t *lstio_grp_entp; /* OUT: description of + char __user *lstio_grp_namep; /* IN: name */ + lstcon_ndlist_ent_t __user *lstio_grp_entp; /* OUT: description of group */ - int *lstio_grp_idxp; /* IN/OUT: node index */ - int *lstio_grp_ndentp; /* IN/OUT: # of nodent */ - lstcon_node_ent_t *lstio_grp_dentsp; /* OUT: nodent array */ + int __user *lstio_grp_idxp; /* IN/OUT: node index */ + int __user *lstio_grp_ndentp; /* IN/OUT: # of nodent */ + lstcon_node_ent_t __user *lstio_grp_dentsp; /* OUT: nodent array */ } lstio_group_info_args_t; #define LST_DEFAULT_BATCH "batch" /* default batch name */ @@ -357,13 +357,13 @@ typedef struct { typedef struct { int lstio_bat_key; /* IN: session key */ int lstio_bat_nmlen; /* IN: name length */ - char *lstio_bat_namep; /* IN: batch name */ + char __user *lstio_bat_namep; /* IN: batch name */ } lstio_batch_add_args_t; typedef struct { int lstio_bat_key; /* IN: session key */ int lstio_bat_nmlen; /* IN: name length */ - char *lstio_bat_namep; /* IN: batch name */ + char __user *lstio_bat_namep; /* IN: batch name */ } lstio_batch_del_args_t; typedef struct { @@ -371,8 +371,8 @@ typedef struct { int lstio_bat_timeout; /* IN: timeout for the batch */ int lstio_bat_nmlen; /* IN: name length */ - char *lstio_bat_namep; /* IN: batch name */ - struct list_head *lstio_bat_resultp; /* OUT: list head of + char __user *lstio_bat_namep; /* IN: batch name */ + struct list_head __user *lstio_bat_resultp; /* OUT: list head of result buffer */ } lstio_batch_run_args_t; @@ -381,8 +381,8 @@ typedef struct { int lstio_bat_force; /* IN: abort unfinished test RPC */ int lstio_bat_nmlen; /* IN: name length */ - char *lstio_bat_namep; /* IN: batch name */ - struct list_head *lstio_bat_resultp; /* OUT: list head of + char __user *lstio_bat_namep; /* IN: batch name */ + struct list_head __user *lstio_bat_resultp; /* OUT: list head of result buffer */ } lstio_batch_stop_args_t; @@ -394,8 +394,8 @@ typedef struct { int lstio_bat_timeout; /* IN: timeout for waiting */ int lstio_bat_nmlen; /* IN: name length */ - char *lstio_bat_namep; /* IN: batch name */ - struct list_head *lstio_bat_resultp; /* OUT: list head of + char __user *lstio_bat_namep; /* IN: batch name */ + struct list_head __user *lstio_bat_resultp; /* OUT: list head of result buffer */ } lstio_batch_query_args_t; @@ -403,21 +403,21 @@ typedef struct { int lstio_bat_key; /* IN: session key */ int lstio_bat_idx; /* IN: index */ int lstio_bat_nmlen; /* IN: name length */ - char *lstio_bat_namep; /* IN: batch name */ + char __user *lstio_bat_namep; /* IN: batch name */ } lstio_batch_list_args_t; typedef struct { int lstio_bat_key; /* IN: session key */ int lstio_bat_nmlen; /* IN: name length */ - char *lstio_bat_namep; /* IN: name */ + char __user *lstio_bat_namep; /* IN: name */ int lstio_bat_server; /* IN: query server or not */ int lstio_bat_testidx; /* IN: test index */ - lstcon_test_batch_ent_t *lstio_bat_entp; /* OUT: batch ent */ + lstcon_test_batch_ent_t __user *lstio_bat_entp; /* OUT: batch ent */ - int *lstio_bat_idxp; /* IN/OUT: index of node */ - int *lstio_bat_ndentp; /* IN/OUT: # of nodent */ - lstcon_node_ent_t *lstio_bat_dentsp; /* array of nodent */ + int __user *lstio_bat_idxp; /* IN/OUT: index of node */ + int __user *lstio_bat_ndentp; /* IN/OUT: # of nodent */ + lstcon_node_ent_t __user *lstio_bat_dentsp; /* array of nodent */ } lstio_batch_info_args_t; /* add stat in session */ @@ -427,10 +427,10 @@ typedef struct { stat request */ int lstio_sta_nmlen; /* IN: group name length */ - char *lstio_sta_namep; /* IN: group name */ + char __user *lstio_sta_namep; /* IN: group name */ int lstio_sta_count; /* IN: # of pid */ - lnet_process_id_t *lstio_sta_idsp; /* IN: pid */ - struct list_head *lstio_sta_resultp; /* OUT: list head of + lnet_process_id_t __user *lstio_sta_idsp; /* IN: pid */ + struct list_head __user *lstio_sta_resultp; /* OUT: list head of result buffer */ } lstio_stat_args_t; @@ -445,7 +445,7 @@ typedef enum { typedef struct { int lstio_tes_key; /* IN: session key */ int lstio_tes_bat_nmlen; /* IN: batch name len */ - char *lstio_tes_bat_name; /* IN: batch name */ + char __user *lstio_tes_bat_name; /* IN: batch name */ int lstio_tes_type; /* IN: test type */ int lstio_tes_oneside; /* IN: one sided test */ int lstio_tes_loop; /* IN: loop count */ @@ -457,20 +457,20 @@ typedef struct { destination groups */ int lstio_tes_sgrp_nmlen; /* IN: source group name length */ - char *lstio_tes_sgrp_name; /* IN: group name */ + char __user *lstio_tes_sgrp_name; /* IN: group name */ int lstio_tes_dgrp_nmlen; /* IN: destination group name length */ - char *lstio_tes_dgrp_name; /* IN: group name */ + char __user *lstio_tes_dgrp_name; /* IN: group name */ int lstio_tes_param_len; /* IN: param buffer len */ - void *lstio_tes_param; /* IN: parameter for specified + void __user *lstio_tes_param; /* IN: parameter for specified test: lstio_bulk_param_t, lstio_ping_param_t, ... more */ - int *lstio_tes_retp; /* OUT: private returned + int __user *lstio_tes_retp; /* OUT: private returned value */ - struct list_head *lstio_tes_resultp; /* OUT: list head of + struct list_head __user *lstio_tes_resultp;/* OUT: list head of result buffer */ } lstio_test_args_t; diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 1066c70434b1..15a61ded6206 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -466,11 +466,11 @@ lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, lstcon_trans_stat_t *stat) int lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, - struct list_head *head_up, + struct list_head __user *head_up, lstcon_rpc_readent_func_t readent) { struct list_head tmp; - struct list_head *next; + struct list_head __user *next; lstcon_rpc_ent_t *ent; srpc_generic_reply_t *rep; lstcon_rpc_t *crpc; diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.h b/drivers/staging/lustre/lnet/selftest/conrpc.h index 95c832ff7375..d2133bc76e93 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.h +++ b/drivers/staging/lustre/lnet/selftest/conrpc.h @@ -106,7 +106,8 @@ typedef struct lstcon_rpc_trans { #define LST_TRANS_STATQRY 0x21 typedef int (*lstcon_rpc_cond_func_t)(int, struct lstcon_node *, void *); -typedef int (*lstcon_rpc_readent_func_t)(int, srpc_msg_t *, lstcon_rpc_ent_t *); +typedef int (*lstcon_rpc_readent_func_t)(int, srpc_msg_t *, + lstcon_rpc_ent_t __user *); int lstcon_sesrpc_prep(struct lstcon_node *nd, int transop, unsigned version, lstcon_rpc_t **crpc); @@ -128,7 +129,7 @@ int lstcon_rpc_trans_ndlist(struct list_head *ndlist, void lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, lstcon_trans_stat_t *stat); int lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, - struct list_head *head_up, + struct list_head __user *head_up, lstcon_rpc_readent_func_t readent); void lstcon_rpc_trans_abort(lstcon_rpc_trans_t *trans, int error); void lstcon_rpc_trans_destroy(lstcon_rpc_trans_t *trans); diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 5619fc430e8d..366211e02ed8 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -363,7 +363,7 @@ lstcon_sesrpc_condition(int transop, lstcon_node_t *nd, void *arg) static int lstcon_sesrpc_readent(int transop, srpc_msg_t *msg, - lstcon_rpc_ent_t *ent_up) + lstcon_rpc_ent_t __user *ent_up) { srpc_debug_reply_t *rep; @@ -392,8 +392,8 @@ lstcon_sesrpc_readent(int transop, srpc_msg_t *msg, static int lstcon_group_nodes_add(lstcon_group_t *grp, - int count, lnet_process_id_t *ids_up, - unsigned *featp, struct list_head *result_up) + int count, lnet_process_id_t __user *ids_up, + unsigned *featp, struct list_head __user *result_up) { lstcon_rpc_trans_t *trans; lstcon_ndlink_t *ndl; @@ -459,8 +459,8 @@ lstcon_group_nodes_add(lstcon_group_t *grp, static int lstcon_group_nodes_remove(lstcon_group_t *grp, - int count, lnet_process_id_t *ids_up, - struct list_head *result_up) + int count, lnet_process_id_t __user *ids_up, + struct list_head __user *result_up) { lstcon_rpc_trans_t *trans; lstcon_ndlink_t *ndl; @@ -537,8 +537,8 @@ lstcon_group_add(char *name) } int -lstcon_nodes_add(char *name, int count, lnet_process_id_t *ids_up, - unsigned *featp, struct list_head *result_up) +lstcon_nodes_add(char *name, int count, lnet_process_id_t __user *ids_up, + unsigned *featp, struct list_head __user *result_up) { lstcon_group_t *grp; int rc; @@ -641,8 +641,8 @@ lstcon_group_clean(char *name, int args) } int -lstcon_nodes_remove(char *name, int count, - lnet_process_id_t *ids_up, struct list_head *result_up) +lstcon_nodes_remove(char *name, int count, lnet_process_id_t __user *ids_up, + struct list_head __user *result_up) { lstcon_group_t *grp = NULL; int rc; @@ -671,7 +671,7 @@ lstcon_nodes_remove(char *name, int count, } int -lstcon_group_refresh(char *name, struct list_head *result_up) +lstcon_group_refresh(char *name, struct list_head __user *result_up) { lstcon_rpc_trans_t *trans; lstcon_group_t *grp; @@ -713,7 +713,7 @@ lstcon_group_refresh(char *name, struct list_head *result_up) } int -lstcon_group_list(int index, int len, char *name_up) +lstcon_group_list(int index, int len, char __user *name_up) { lstcon_group_t *grp; @@ -732,7 +732,7 @@ lstcon_group_list(int index, int len, char *name_up) static int lstcon_nodes_getent(struct list_head *head, int *index_p, - int *count_p, lstcon_node_ent_t *dents_up) + int *count_p, lstcon_node_ent_t __user *dents_up) { lstcon_ndlink_t *ndl; lstcon_node_t *nd; @@ -771,8 +771,9 @@ lstcon_nodes_getent(struct list_head *head, int *index_p, } int -lstcon_group_info(char *name, lstcon_ndlist_ent_t *gents_p, - int *index_p, int *count_p, lstcon_node_ent_t *dents_up) +lstcon_group_info(char *name, lstcon_ndlist_ent_t __user *gents_p, + int *index_p, int *count_p, + lstcon_node_ent_t __user *dents_up) { lstcon_ndlist_ent_t *gentp; lstcon_group_t *grp; @@ -892,7 +893,7 @@ lstcon_batch_add(char *name) } int -lstcon_batch_list(int index, int len, char *name_up) +lstcon_batch_list(int index, int len, char __user *name_up) { lstcon_batch_t *bat; @@ -910,9 +911,9 @@ lstcon_batch_list(int index, int len, char *name_up) } int -lstcon_batch_info(char *name, lstcon_test_batch_ent_t *ent_up, int server, - int testidx, int *index_p, int *ndent_p, - lstcon_node_ent_t *dents_up) +lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up, + int server, int testidx, int *index_p, int *ndent_p, + lstcon_node_ent_t __user *dents_up) { lstcon_test_batch_ent_t *entp; struct list_head *clilst; @@ -1006,7 +1007,7 @@ lstcon_batrpc_condition(int transop, lstcon_node_t *nd, void *arg) static int lstcon_batch_op(lstcon_batch_t *bat, int transop, - struct list_head *result_up) + struct list_head __user *result_up) { lstcon_rpc_trans_t *trans; int rc; @@ -1029,7 +1030,7 @@ lstcon_batch_op(lstcon_batch_t *bat, int transop, } int -lstcon_batch_run(char *name, int timeout, struct list_head *result_up) +lstcon_batch_run(char *name, int timeout, struct list_head __user *result_up) { lstcon_batch_t *bat; int rc; @@ -1051,7 +1052,7 @@ lstcon_batch_run(char *name, int timeout, struct list_head *result_up) } int -lstcon_batch_stop(char *name, int force, struct list_head *result_up) +lstcon_batch_stop(char *name, int force, struct list_head __user *result_up) { lstcon_batch_t *bat; int rc; @@ -1170,7 +1171,7 @@ lstcon_testrpc_condition(int transop, lstcon_node_t *nd, void *arg) } static int -lstcon_test_nodes_add(lstcon_test_t *test, struct list_head *result_up) +lstcon_test_nodes_add(lstcon_test_t *test, struct list_head __user *result_up) { lstcon_rpc_trans_t *trans; lstcon_group_t *grp; @@ -1266,7 +1267,7 @@ lstcon_test_add(char *batch_name, int type, int loop, int concur, int dist, int span, char *src_name, char *dst_name, void *param, int paramlen, int *retp, - struct list_head *result_up) + struct list_head __user *result_up) { lstcon_test_t *test = NULL; int rc; @@ -1369,7 +1370,7 @@ lstcon_test_find(lstcon_batch_t *batch, int idx, lstcon_test_t **testpp) static int lstcon_tsbrpc_readent(int transop, srpc_msg_t *msg, - lstcon_rpc_ent_t *ent_up) + lstcon_rpc_ent_t __user *ent_up) { srpc_batch_reply_t *rep = &msg->msg_body.bat_reply; @@ -1386,7 +1387,7 @@ lstcon_tsbrpc_readent(int transop, srpc_msg_t *msg, int lstcon_test_batch_query(char *name, int testidx, int client, - int timeout, struct list_head *result_up) + int timeout, struct list_head __user *result_up) { lstcon_rpc_trans_t *trans; struct list_head *translist; @@ -1448,19 +1449,21 @@ lstcon_test_batch_query(char *name, int testidx, int client, static int lstcon_statrpc_readent(int transop, srpc_msg_t *msg, - lstcon_rpc_ent_t *ent_up) + lstcon_rpc_ent_t __user *ent_up) { srpc_stat_reply_t *rep = &msg->msg_body.stat_reply; - sfw_counters_t *sfwk_stat; - srpc_counters_t *srpc_stat; - lnet_counters_t *lnet_stat; + sfw_counters_t __user *sfwk_stat; + srpc_counters_t __user *srpc_stat; + lnet_counters_t __user *lnet_stat; if (rep->str_status != 0) return 0; - sfwk_stat = (sfw_counters_t *)&ent_up->rpe_payload[0]; - srpc_stat = (srpc_counters_t *)((char *)sfwk_stat + sizeof(*sfwk_stat)); - lnet_stat = (lnet_counters_t *)((char *)srpc_stat + sizeof(*srpc_stat)); + sfwk_stat = (sfw_counters_t __user *)&ent_up->rpe_payload[0]; + srpc_stat = (srpc_counters_t __user *) + ((char *)sfwk_stat + sizeof(*sfwk_stat)); + lnet_stat = (lnet_counters_t __user *) + ((char *)srpc_stat + sizeof(*srpc_stat)); if (copy_to_user(sfwk_stat, &rep->str_fw, sizeof(*sfwk_stat)) || copy_to_user(srpc_stat, &rep->str_rpc, sizeof(*srpc_stat)) || @@ -1472,7 +1475,7 @@ lstcon_statrpc_readent(int transop, srpc_msg_t *msg, static int lstcon_ndlist_stat(struct list_head *ndlist, - int timeout, struct list_head *result_up) + int timeout, struct list_head __user *result_up) { struct list_head head; lstcon_rpc_trans_t *trans; @@ -1497,7 +1500,8 @@ lstcon_ndlist_stat(struct list_head *ndlist, } int -lstcon_group_stat(char *grp_name, int timeout, struct list_head *result_up) +lstcon_group_stat(char *grp_name, int timeout, + struct list_head __user *result_up) { lstcon_group_t *grp; int rc; @@ -1516,8 +1520,8 @@ lstcon_group_stat(char *grp_name, int timeout, struct list_head *result_up) } int -lstcon_nodes_stat(int count, lnet_process_id_t *ids_up, - int timeout, struct list_head *result_up) +lstcon_nodes_stat(int count, lnet_process_id_t __user *ids_up, + int timeout, struct list_head __user *result_up) { lstcon_ndlink_t *ndl; lstcon_group_t *tmp; @@ -1562,7 +1566,7 @@ lstcon_nodes_stat(int count, lnet_process_id_t *ids_up, static int lstcon_debug_ndlist(struct list_head *ndlist, struct list_head *translist, - int timeout, struct list_head *result_up) + int timeout, struct list_head __user *result_up) { lstcon_rpc_trans_t *trans; int rc; @@ -1584,7 +1588,7 @@ lstcon_debug_ndlist(struct list_head *ndlist, } int -lstcon_session_debug(int timeout, struct list_head *result_up) +lstcon_session_debug(int timeout, struct list_head __user *result_up) { return lstcon_debug_ndlist(&console_session.ses_ndl_list, NULL, timeout, result_up); @@ -1592,7 +1596,7 @@ lstcon_session_debug(int timeout, struct list_head *result_up) int lstcon_batch_debug(int timeout, char *name, - int client, struct list_head *result_up) + int client, struct list_head __user *result_up) { lstcon_batch_t *bat; int rc; @@ -1610,7 +1614,7 @@ lstcon_batch_debug(int timeout, char *name, int lstcon_group_debug(int timeout, char *name, - struct list_head *result_up) + struct list_head __user *result_up) { lstcon_group_t *grp; int rc; @@ -1628,8 +1632,8 @@ lstcon_group_debug(int timeout, char *name, int lstcon_nodes_debug(int timeout, - int count, lnet_process_id_t *ids_up, - struct list_head *result_up) + int count, lnet_process_id_t __user *ids_up, + struct list_head __user *result_up) { lnet_process_id_t id; lstcon_ndlink_t *ndl; @@ -1693,7 +1697,7 @@ extern srpc_service_t lstcon_acceptor_service; int lstcon_session_new(char *name, int key, unsigned feats, - int timeout, int force, lst_sid_t *sid_up) + int timeout, int force, lst_sid_t __user *sid_up) { int rc = 0; int i; @@ -1758,8 +1762,10 @@ lstcon_session_new(char *name, int key, unsigned feats, } int -lstcon_session_info(lst_sid_t *sid_up, int *key_up, unsigned *featp, - lstcon_ndlist_ent_t *ndinfo_up, char *name_up, int len) +lstcon_session_info(lst_sid_t __user *sid_up, int __user *key_up, + unsigned __user *featp, + lstcon_ndlist_ent_t __user *ndinfo_up, + char __user *name_up, int len) { lstcon_ndlist_ent_t *entp; lstcon_ndlink_t *ndl; diff --git a/drivers/staging/lustre/lnet/selftest/console.h b/drivers/staging/lustre/lnet/selftest/console.h index 3f3286c0c7bf..f7ccaeb28be0 100644 --- a/drivers/staging/lustre/lnet/selftest/console.h +++ b/drivers/staging/lustre/lnet/selftest/console.h @@ -188,47 +188,51 @@ int lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_data *data); int lstcon_console_fini(void); int lstcon_session_match(lst_sid_t sid); int lstcon_session_new(char *name, int key, unsigned version, - int timeout, int flags, lst_sid_t *sid_up); -int lstcon_session_info(lst_sid_t *sid_up, int *key, unsigned *verp, - lstcon_ndlist_ent_t *entp, char *name_up, int len); + int timeout, int flags, lst_sid_t __user *sid_up); +int lstcon_session_info(lst_sid_t __user *sid_up, int __user *key, + unsigned __user *verp, lstcon_ndlist_ent_t __user *entp, + char __user *name_up, int len); int lstcon_session_end(void); -int lstcon_session_debug(int timeout, struct list_head *result_up); +int lstcon_session_debug(int timeout, struct list_head __user *result_up); int lstcon_session_feats_check(unsigned feats); int lstcon_batch_debug(int timeout, char *name, - int client, struct list_head *result_up); + int client, struct list_head __user *result_up); int lstcon_group_debug(int timeout, char *name, - struct list_head *result_up); -int lstcon_nodes_debug(int timeout, int nnd, lnet_process_id_t *nds_up, - struct list_head *result_up); + struct list_head __user *result_up); +int lstcon_nodes_debug(int timeout, int nnd, lnet_process_id_t __user *nds_up, + struct list_head __user *result_up); int lstcon_group_add(char *name); int lstcon_group_del(char *name); int lstcon_group_clean(char *name, int args); -int lstcon_group_refresh(char *name, struct list_head *result_up); -int lstcon_nodes_add(char *name, int nnd, lnet_process_id_t *nds_up, - unsigned *featp, struct list_head *result_up); -int lstcon_nodes_remove(char *name, int nnd, lnet_process_id_t *nds_up, - struct list_head *result_up); -int lstcon_group_info(char *name, lstcon_ndlist_ent_t *gent_up, - int *index_p, int *ndent_p, lstcon_node_ent_t *ndents_up); -int lstcon_group_list(int idx, int len, char *name_up); +int lstcon_group_refresh(char *name, struct list_head __user *result_up); +int lstcon_nodes_add(char *name, int nnd, lnet_process_id_t __user *nds_up, + unsigned *featp, struct list_head __user *result_up); +int lstcon_nodes_remove(char *name, int nnd, lnet_process_id_t __user *nds_up, + struct list_head __user *result_up); +int lstcon_group_info(char *name, lstcon_ndlist_ent_t __user *gent_up, + int *index_p, int *ndent_p, + lstcon_node_ent_t __user *ndents_up); +int lstcon_group_list(int idx, int len, char __user *name_up); int lstcon_batch_add(char *name); -int lstcon_batch_run(char *name, int timeout, struct list_head *result_up); -int lstcon_batch_stop(char *name, int force, struct list_head *result_up); +int lstcon_batch_run(char *name, int timeout, + struct list_head __user *result_up); +int lstcon_batch_stop(char *name, int force, + struct list_head __user *result_up); int lstcon_test_batch_query(char *name, int testidx, int client, int timeout, - struct list_head *result_up); + struct list_head __user *result_up); int lstcon_batch_del(char *name); -int lstcon_batch_list(int idx, int namelen, char *name_up); -int lstcon_batch_info(char *name, lstcon_test_batch_ent_t *ent_up, +int lstcon_batch_list(int idx, int namelen, char __user *name_up); +int lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up, int server, int testidx, int *index_p, - int *ndent_p, lstcon_node_ent_t *dents_up); + int *ndent_p, lstcon_node_ent_t __user *dents_up); int lstcon_group_stat(char *grp_name, int timeout, - struct list_head *result_up); -int lstcon_nodes_stat(int count, lnet_process_id_t *ids_up, - int timeout, struct list_head *result_up); + struct list_head __user *result_up); +int lstcon_nodes_stat(int count, lnet_process_id_t __user *ids_up, + int timeout, struct list_head __user *result_up); int lstcon_test_add(char *batch_name, int type, int loop, int concur, int dist, int span, char *src_name, char *dst_name, void *param, int paramlen, int *retp, - struct list_head *result_up); + struct list_head __user *result_up); #endif -- cgit v1.2.3 From b0e7d960884abf9044c5c84c185bc6815f4b88e5 Mon Sep 17 00:00:00 2001 From: Parinay Kondekar Date: Tue, 5 Jan 2016 14:35:13 -0500 Subject: staging:lustre: remove obsolete comment in libcfs_ioctl.h The libcfs_ioctl.h header has a comment about a snapshot ioctl which has been removed for years. Lets remove the comment to avoid confusion. Broken out of patch 17492. Signed-off-by: Parinay Kondekar Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5844 Reviewed-on: http://review.whamcloud.com/17492 Reviewed-by: Andreas Dilger Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 05f2191e08fb..e4463ada0343 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -102,7 +102,6 @@ struct libcfs_ioctl_handler { /* FIXME check conflict with lustre_lib.h */ #define LIBCFS_IOC_DEBUG_MASK _IOWR('f', 250, long) -/* ioctls for manipulating snapshots 30- */ #define IOC_LIBCFS_TYPE 'e' #define IOC_LIBCFS_MIN_NR 30 /* libcfs ioctls */ -- cgit v1.2.3 From 62fcd58943654b0474f8d97309185dca1addd5a7 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 15 Jan 2016 11:32:11 +0530 Subject: Staging:lustre:lustre:obdclass:Remove return from void function This patch removes the return statement at the end of a void function as it is not necessary.This was found by checkpatch.pl . Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/llog_swab.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/llog_swab.c b/drivers/staging/lustre/lustre/obdclass/llog_swab.c index 3aa7393b20c3..8f57a8eb412c 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_swab.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_swab.c @@ -406,7 +406,5 @@ void lustre_swab_cfg_marker(struct cfg_marker *marker, int swab, int size) __swab64s(&marker->cm_createtime); __swab64s(&marker->cm_canceltime); } - - return; } EXPORT_SYMBOL(lustre_swab_cfg_marker); -- cgit v1.2.3 From 9edece72e2cfb449a8c1a18275cb369861ab8fc8 Mon Sep 17 00:00:00 2001 From: Anjali Menon Date: Sat, 16 Jan 2016 15:30:50 +0530 Subject: staging: lustre: lustre: lov: Added space Added a spaces around '|' to fix the check detected by checkpatch.pl CHECK: spaces preferred around that '|' (ctx:VxV) Signed-off-by: Anjali Menon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/lov/lov_dev.c b/drivers/staging/lustre/lustre/lov/lov_dev.c index 3733fdc88c8c..2c33cbce5940 100644 --- a/drivers/staging/lustre/lustre/lov/lov_dev.c +++ b/drivers/staging/lustre/lustre/lov/lov_dev.c @@ -334,7 +334,7 @@ static struct lov_device_emerg **lov_emerg_alloc(int nr) emerg[i] = em; cl_page_list_init(&em->emrg_page_list); em->emrg_env = cl_env_alloc(&em->emrg_refcheck, - LCT_REMEMBER|LCT_NOREF); + LCT_REMEMBER | LCT_NOREF); if (!IS_ERR(em->emrg_env)) em->emrg_env->le_ctx.lc_cookie = 0x2; else { -- cgit v1.2.3 From 587cb02269c38dbd5d0f33e8ee08e5ca280b4b07 Mon Sep 17 00:00:00 2001 From: Sushuruth Sadagopan Date: Mon, 18 Jan 2016 02:09:23 -0500 Subject: staging: lustre: fix comment style Fix style of several comments. Signed-off-by: Sushuruth Sadagopan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/lnet/config.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/lnet/config.c b/drivers/staging/lustre/lnet/lnet/config.c index 284a3c271bc6..74d644d7d729 100644 --- a/drivers/staging/lustre/lnet/lnet/config.c +++ b/drivers/staging/lustre/lnet/lnet/config.c @@ -217,12 +217,16 @@ lnet_parse_networks(struct list_head *nilist, char *networks) int niface; int rc; - /* NB we don't check interface conflicts here; it's the LNDs - * responsibility (if it cares at all) */ + /* + * NB we don't check interface conflicts here; it's the LNDs + * responsibility (if it cares at all) + */ if (square != NULL && (comma == NULL || square < comma)) { - /* i.e: o2ib0(ib0)[1,2], number between square - * brackets are CPTs this NI needs to be bond */ + /* + * i.e: o2ib0(ib0)[1,2], number between square + * brackets are CPTs this NI needs to be bond + */ if (bracket != NULL && bracket > square) { tmp = square; goto failed_syntax; @@ -609,8 +613,10 @@ lnet_parse_priority(char *str, unsigned int *priority, char **token) len = strlen(sep + 1); if ((sscanf((sep+1), "%u%n", priority, &nob) < 1) || (len != nob)) { - /* Update the caller's token pointer so it treats the found - priority as the token to report in the error message. */ + /* + * Update the caller's token pointer so it treats the found + * priority as the token to report in the error message. + */ *token += sep - str + 1; return -1; } -- cgit v1.2.3 From 197cb405b3ed1707ab4347b3ce8803fca7403939 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Thu, 21 Jan 2016 00:17:44 +0530 Subject: Staging:lustre:obdclass:linux:remove unnecessary braces Fixed 'braces {} are not necessary for single statement blocks' checkpatch.pl warning. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/linux/linux-module.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index f8d3a639e85c..b0ee4db1e82b 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -144,9 +144,8 @@ int obd_ioctl_getdata(char **buf, int *len, void __user *arg) offset += cfs_size_round(data->ioc_inllen3); } - if (data->ioc_inllen4) { + if (data->ioc_inllen4) data->ioc_inlbuf4 = &data->ioc_bulk[0] + offset; - } return 0; @@ -250,9 +249,8 @@ static ssize_t health_show(struct kobject *kobj, struct attribute *attr, class_incref(obd, __func__, current); read_unlock(&obd_dev_lock); - if (obd_health_check(NULL, obd)) { + if (obd_health_check(NULL, obd)) healthy = false; - } class_decref(obd, __func__, current); read_lock(&obd_dev_lock); } -- cgit v1.2.3 From 6ae07f1b38d18589fdeaa150b86252f02b2750fb Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Thu, 21 Jan 2016 00:17:45 +0530 Subject: Staging:lustre:obdclass:linux:simplify NULL comparison Remove explicit NULL comparision and replace it with a simpier form. Detected using checkpatch.pl. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/linux/linux-module.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index b0ee4db1e82b..1913f3e00ad5 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -239,7 +239,7 @@ static ssize_t health_show(struct kobject *kobj, struct attribute *attr, struct obd_device *obd; obd = class_num2obd(i); - if (obd == NULL || !obd->obd_attached || !obd->obd_set_up) + if (!obd || !obd->obd_attached || !obd->obd_set_up) continue; LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC); @@ -358,7 +358,7 @@ static int obd_device_list_seq_show(struct seq_file *p, void *v) struct obd_device *obd = class_num2obd((int)index); char *status; - if (obd == NULL) + if (!obd) return 0; LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC); @@ -422,7 +422,7 @@ int class_procfs_init(void) struct dentry *file; lustre_kobj = kobject_create_and_add("lustre", fs_kobj); - if (lustre_kobj == NULL) + if (!lustre_kobj) goto out; /* Create the files associated with this kobject */ -- cgit v1.2.3 From 61382aa809e48dcd09109becf6b09715a8f492ac Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 23 Jan 2016 18:41:53 +0530 Subject: Staging:lustre:lustre:llite:Remove explicit NULL comparision Replaced explicit NULL comparision with its simplier form. Found using coccinelle: @replace_rule@ expression e; @@ -e == NULL + !e Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dcache.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index 3d6745e63fe3..bc179e5ac260 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -62,7 +62,7 @@ static void ll_release(struct dentry *de) LASSERT(de != NULL); lld = ll_d2d(de); - if (lld == NULL) /* NFS copies the de->d_op methods (bug 4655) */ + if (!lld) /* NFS copies the de->d_op methods (bug 4655) */ return; if (lld->lld_it) { @@ -131,7 +131,7 @@ static int find_cbdata(struct inode *inode) return rc; lsm = ccc_inode_lsm_get(inode); - if (lsm == NULL) + if (!lsm) return rc; rc = obd_find_cbdata(sbi->ll_dt_exp, lsm, return_if_equal, NULL); @@ -184,13 +184,13 @@ int ll_d_init(struct dentry *de) de, de, de->d_parent, d_inode(de), d_count(de)); - if (de->d_fsdata == NULL) { + if (!de->d_fsdata) { struct ll_dentry_data *lld; lld = kzalloc(sizeof(*lld), GFP_NOFS); if (likely(lld)) { spin_lock(&de->d_lock); - if (likely(de->d_fsdata == NULL)) { + if (likely(!de->d_fsdata)) { de->d_fsdata = lld; __d_lustre_invalidate(de); } else { @@ -328,7 +328,7 @@ static int ll_revalidate_dentry(struct dentry *dentry, if (lookup_flags & LOOKUP_RCU) return -ECHILD; - do_statahead_enter(dir, &dentry, d_inode(dentry) == NULL); + do_statahead_enter(dir, &dentry, !d_inode(dentry)); ll_statahead_mark(dir, dentry); return 1; } -- cgit v1.2.3 From 364b72e5009fefd3d30e311465924e78ac07af14 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 29 Jan 2016 14:14:26 +0530 Subject: Staging:lustre:lclient:Remove unused function Discard the function ccc_vmpage_page_transient as it is not used anywhere in the kernel. Used grep to find occurences. Problem found using sparse. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lclient/lcommon_cl.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c index 34dde7dede74..4dfeb4e07d41 100644 --- a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c @@ -985,17 +985,6 @@ struct inode *ccc_object_inode(const struct cl_object *obj) return cl2ccc(obj)->cob_inode; } -/** - * Returns a pointer to cl_page associated with \a vmpage, without acquiring - * additional reference to the resulting page. This is an unsafe version of - * cl_vmpage_page() that can only be used under vmpage lock. - */ -struct cl_page *ccc_vmpage_page_transient(struct page *vmpage) -{ - KLASSERT(PageLocked(vmpage)); - return (struct cl_page *)vmpage->private; -} - /** * Initialize or update CLIO structures for regular files when new * meta-data arrives from the server. -- cgit v1.2.3 From 1dd44dda6e7d1ca25765f7119d566c3669b6c909 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:48:57 +0900 Subject: staging: wilc1000: fix return type of wilc_add_pkt declaration This patch changes return type of wilc_add_pkt declaration from s32 to int. The return type of this function declaration and definition should be same as data type of int. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 8faac27002e9..be1536ada175 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -312,7 +312,7 @@ int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len, u8 index); int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len, u8 index, u8 mode, enum AUTHTYPE auth_type); -s32 wilc_add_ptk(struct wilc_vif *vif, const u8 *pu8Ptk, u8 u8PtkKeylen, +int wilc_add_ptk(struct wilc_vif *vif, const u8 *pu8Ptk, u8 u8PtkKeylen, const u8 *mac_addr, const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode, u8 u8Idx); s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, -- cgit v1.2.3 From 961875ed9e7d88fc0e79d32c883775064cbb63fd Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:48:58 +0900 Subject: staging: wilc1000: match argument name of wilc_add_ptk declaration Some arguments name of wilc_add_pkt declaration is different to those of this function definition. It is changed as same name of this function declaration and definition. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index be1536ada175..7e89776baa97 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -312,9 +312,9 @@ int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len, u8 index); int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len, u8 index, u8 mode, enum AUTHTYPE auth_type); -int wilc_add_ptk(struct wilc_vif *vif, const u8 *pu8Ptk, u8 u8PtkKeylen, - const u8 *mac_addr, const u8 *pu8RxMic, const u8 *pu8TxMic, - u8 mode, u8 u8Ciphermode, u8 u8Idx); +int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, + const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic, + u8 mode, u8 cipher_mode, u8 index); s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *pu32InactiveTime); s32 wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *pu8RxGtk, u8 u8GtkKeylen, -- cgit v1.2.3 From a11486e48b24bb8c2fef218adfedafde65345d05 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:48:59 +0900 Subject: staging: wilc1000: fix return type of wilc_add_rx_gtk declaration This patch changes return type of wilc_add_rx_gtk declaration from s32 to int. The return type of this function declaration and definition should be same as data type of int. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 7e89776baa97..02c1017156d5 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -317,7 +317,7 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, u8 mode, u8 cipher_mode, u8 index); s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *pu32InactiveTime); -s32 wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *pu8RxGtk, u8 u8GtkKeylen, +int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *pu8RxGtk, u8 u8GtkKeylen, u8 u8KeyIdx, u32 u32KeyRSClen, const u8 *KeyRSC, const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode); -- cgit v1.2.3 From 9676108e926a1432bb9dcfc8eef0de2243cadda4 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:00 +0900 Subject: staging: wilc1000: match argument name of wilc_add_rx_gtk declaration Some argument name of wilc_add_rx_gtk declaration is different to those of this function definition. It is changed as same name of this function declaration and definition. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 02c1017156d5..6a5f3bd23055 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -317,10 +317,10 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, u8 mode, u8 cipher_mode, u8 index); s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *pu32InactiveTime); -int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *pu8RxGtk, u8 u8GtkKeylen, - u8 u8KeyIdx, u32 u32KeyRSClen, const u8 *KeyRSC, - const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, - u8 u8Ciphermode); +int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, + u8 index, u32 key_rsc_len, const u8 *key_rsc, + const u8 *rx_mic, const u8 *tx_mic, u8 mode, + u8 cipher_mode); s32 wilc_add_tx_gtk(struct host_if_drv *hWFIDrv, u8 u8KeyLen, u8 *pu8TxGtk, u8 u8KeyIdx); s32 wilc_set_pmkid_info(struct wilc_vif *vif, -- cgit v1.2.3 From ad510dac485718de0c65fb27888aa6ef274bdaf9 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:01 +0900 Subject: staging: wilc1000: remove wilc_add_tx_gtk declaration This patch deletes wilc_add_tx_gtk declaration. It is not find wilc_add_tx_gtk definition in this driver. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 6a5f3bd23055..a21ca3768124 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -321,8 +321,6 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, u8 index, u32 key_rsc_len, const u8 *key_rsc, const u8 *rx_mic, const u8 *tx_mic, u8 mode, u8 cipher_mode); -s32 wilc_add_tx_gtk(struct host_if_drv *hWFIDrv, u8 u8KeyLen, - u8 *pu8TxGtk, u8 u8KeyIdx); s32 wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pu8PmkidInfoArray); s32 wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); -- cgit v1.2.3 From 000b5625307dc34fdae9e6f004912a3f6b7195ae Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:02 +0900 Subject: staging: wilc1000: remove wilc_set_start_scan_req declaration This patch deletes wilc_set_start_scan_req declaration. It is not find wilc_set_start_scan_req definition in this driver. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index a21ca3768124..1e3f38999821 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -326,7 +326,6 @@ s32 wilc_set_pmkid_info(struct wilc_vif *vif, s32 wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); s32 wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); int wilc_wait_msg_queue_idle(void); -s32 wilc_set_start_scan_req(struct host_if_drv *hWFIDrv, u8 scanSource); s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, -- cgit v1.2.3 From 1ab587052b584647ec16e2e021f57cee988213b7 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:03 +0900 Subject: staging: wilc1000: fix return type of wilc_set_pmkid_info This patch changes return type of wilc_set_pmkid_info from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 8c7752034032..c976c1f202f6 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3291,10 +3291,10 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, return result; } -s32 wilc_set_pmkid_info(struct wilc_vif *vif, +int wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pu8PmkidInfoArray) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; u32 i; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 1e3f38999821..3dfdc048b7c2 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -321,7 +321,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, u8 index, u32 key_rsc_len, const u8 *key_rsc, const u8 *rx_mic, const u8 *tx_mic, u8 mode, u8 cipher_mode); -s32 wilc_set_pmkid_info(struct wilc_vif *vif, +int wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pu8PmkidInfoArray); s32 wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); s32 wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); -- cgit v1.2.3 From 89dec13951e63f8d67ef32b3d6dd6ea782cd8c5b Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:04 +0900 Subject: staging: wilc1000: replace u32 with int The data type of variable i changes u32 to int. It is used as array index to copy some data with memcpy function so that it is better to use data type of int. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c976c1f202f6..3ad4b0e09d88 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3297,7 +3297,7 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; - u32 i; + int i; if (!hif_drv) { PRINT_ER("driver is null\n"); -- cgit v1.2.3 From 16c0cba77369b25b790a4dee1a616ce6d69c92c6 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:05 +0900 Subject: staging: wilc1000: rename pu8PmkidInfoArray in wilc_set_pmkid_info This patch changes pu8PmkidInfoArray to pmkid to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 3ad4b0e09d88..485318fcdb05 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3292,7 +3292,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, } int wilc_set_pmkid_info(struct wilc_vif *vif, - struct host_if_pmkid_attr *pu8PmkidInfoArray) + struct host_if_pmkid_attr *pmkid) { int result = 0; struct host_if_msg msg; @@ -3311,11 +3311,11 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, msg.body.key_info.action = ADDKEY; msg.vif = vif; - for (i = 0; i < pu8PmkidInfoArray->numpmkid; i++) { + for (i = 0; i < pmkid->numpmkid; i++) { memcpy(msg.body.key_info.attr.pmkid.pmkidlist[i].bssid, - &pu8PmkidInfoArray->pmkidlist[i].bssid, ETH_ALEN); + &pmkid->pmkidlist[i].bssid, ETH_ALEN); memcpy(msg.body.key_info.attr.pmkid.pmkidlist[i].pmkid, - &pu8PmkidInfoArray->pmkidlist[i].pmkid, PMKID_LEN); + &pmkid->pmkidlist[i].pmkid, PMKID_LEN); } result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 3dfdc048b7c2..675a4e13a3ba 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -322,7 +322,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, const u8 *rx_mic, const u8 *tx_mic, u8 mode, u8 cipher_mode); int wilc_set_pmkid_info(struct wilc_vif *vif, - struct host_if_pmkid_attr *pu8PmkidInfoArray); + struct host_if_pmkid_attr *pmkid); s32 wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); s32 wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); int wilc_wait_msg_queue_idle(void); -- cgit v1.2.3 From dcb15a0810749865068784fae9f1e3d6c89240be Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:06 +0900 Subject: staging: wilc1000: fix return type of wilc_get_mac_address This patch changes return type of wilc_get_mac_address from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 485318fcdb05..affd1e656f7f 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3325,9 +3325,9 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, return result; } -s32 wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress) +int wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress) { - s32 result = 0; + int result = 0; struct host_if_msg msg; memset(&msg, 0, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 675a4e13a3ba..6be4b14950cf 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -323,7 +323,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, u8 cipher_mode); int wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pmkid); -s32 wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); +int wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); s32 wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); int wilc_wait_msg_queue_idle(void); s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, -- cgit v1.2.3 From 1eabfe3fe7107feef75dbb2f4afa9aee7eb64960 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:07 +0900 Subject: staging: wilc1000: rename pu8MacAddress in wilc_get_mac_address This patch changes pu8MacAddress to mac_addr to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index affd1e656f7f..613c5a2d403b 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3325,7 +3325,7 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, return result; } -int wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress) +int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr) { int result = 0; struct host_if_msg msg; @@ -3333,7 +3333,7 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress) memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_GET_MAC_ADDRESS; - msg.body.get_mac_info.mac_addr = pu8MacAddress; + msg.body.get_mac_info.mac_addr = mac_addr; msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 6be4b14950cf..76f90cdaa496 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -323,7 +323,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, u8 cipher_mode); int wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pmkid); -int wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); +int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); s32 wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); int wilc_wait_msg_queue_idle(void); s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, -- cgit v1.2.3 From 0b477624906983df8c0bd705020982c956db1e57 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:08 +0900 Subject: staging: wilc1000: fix return type of wilc_set_mac_address This patch changes return type of wilc_set_mac_address from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 613c5a2d403b..ed6f93289410 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3346,9 +3346,9 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr) return result; } -s32 wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress) +int wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress) { - s32 result = 0; + int result = 0; struct host_if_msg msg; PRINT_D(GENERIC_DBG, "mac addr = %x:%x:%x\n", pu8MacAddress[0], pu8MacAddress[1], pu8MacAddress[2]); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 76f90cdaa496..337965f96927 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -324,7 +324,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, int wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pmkid); int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); -s32 wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); +int wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); int wilc_wait_msg_queue_idle(void); s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, -- cgit v1.2.3 From f95f480c51125bbfa56ea2dc5383859dc43b0a15 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:09 +0900 Subject: staging: wilc1000: rename pu8MacAddress in wilc_set_mac_address This patch changes pu8MacAddress to mac_addr to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index ed6f93289410..78d26ee016aa 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3346,16 +3346,16 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr) return result; } -int wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress) +int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) { int result = 0; struct host_if_msg msg; - PRINT_D(GENERIC_DBG, "mac addr = %x:%x:%x\n", pu8MacAddress[0], pu8MacAddress[1], pu8MacAddress[2]); + PRINT_D(GENERIC_DBG, "mac addr = %x:%x:%x\n", mac_addr[0], mac_addr[1], mac_addr[2]); memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_SET_MAC_ADDRESS; - memcpy(msg.body.set_mac_info.mac_addr, pu8MacAddress, ETH_ALEN); + memcpy(msg.body.set_mac_info.mac_addr, mac_addr, ETH_ALEN); msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 337965f96927..13d253c6a5fd 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -324,7 +324,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, int wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pmkid); int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); -int wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); +int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, -- cgit v1.2.3 From e663900aed9b90270e3452d500426ca0ae5762ed Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 24 Dec 2015 15:02:51 +0900 Subject: staging: wilc1000: fix always return 0 error This patch fixes a bug that return always 0 so it fails every time. Fixes: c1af9db78950 ("staging: wilc1000: call linux_sdio_init instead of io_init") Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_sdio.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index e961b5004902..464d27df829a 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -614,8 +614,6 @@ static int sdio_init(struct wilc *wilc) if (!wilc_sdio_init()) { dev_err(&func->dev, "Failed io init bus...\n"); return 0; - } else { - return 0; } /** -- cgit v1.2.3 From 43d1ca528436bc3f629edd8b622b39fb1611d5f7 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 24 Dec 2015 15:02:52 +0900 Subject: staging: wilc1000: remove wilc_sdio_init wilc_sdio_init return always 1, which is needless. Remove it and it's related codes also. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_sdio.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index 464d27df829a..caad876a8249 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -185,11 +185,6 @@ static void wilc_sdio_disable_interrupt(struct wilc *dev) dev_info(&func->dev, "wilc_sdio_disable_interrupt OUT\n"); } -static int wilc_sdio_init(void) -{ - return 1; -} - /******************************************** * * Function 0 @@ -611,11 +606,6 @@ static int sdio_init(struct wilc *wilc) g_sdio.irq_gpio = (wilc->dev_irq_num); - if (!wilc_sdio_init()) { - dev_err(&func->dev, "Failed io init bus...\n"); - return 0; - } - /** * function 0 csa enable **/ -- cgit v1.2.3 From a045618e01ac486528f848841a3b31b9b7582c0c Mon Sep 17 00:00:00 2001 From: Hari Prasath Gujulan Elango Date: Tue, 22 Dec 2015 11:44:43 +0000 Subject: staging: wilc1000: replace numerical constant with predefined MACRO Replace the pre-defined macro signifying the ethernet protocol type defined in the kernel headers instead of the numerical constant Signed-off-by: Hari Prasath Gujulan Elango Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 83af51bb83e8..0b62cc5df488 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -248,7 +248,7 @@ static inline int tcp_process(struct net_device *dev, struct txq_entry_t *tqe) eth_hdr_ptr = &buffer[0]; h_proto = ntohs(*((unsigned short *)ð_hdr_ptr[12])); - if (h_proto == 0x0800) { + if (h_proto == ETH_P_IP) { u8 *ip_hdr_ptr; u8 protocol; -- cgit v1.2.3 From 30205892ecaa6a151e85bdd8e1bf9f7ee7a0fc17 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:19 +0900 Subject: staging: wilc1000: fix return type of wilc_flush_join_req This patch changes return type of wilc_flush_join_req from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 78d26ee016aa..78d58e092d20 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3432,9 +3432,9 @@ s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, return result; } -s32 wilc_flush_join_req(struct wilc_vif *vif) +int wilc_flush_join_req(struct wilc_vif *vif) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 13d253c6a5fd..af8582456cd6 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -331,7 +331,7 @@ s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams); -s32 wilc_flush_join_req(struct wilc_vif *vif); +int wilc_flush_join_req(struct wilc_vif *vif); s32 wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); s32 wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi); -- cgit v1.2.3 From 0a285b2770f022987233c98e9bb44af923df1306 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:20 +0900 Subject: staging: wilc1000: fix return type of wilc_set_join_req This patch changes return type of wilc_set_join_req from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 78d58e092d20..b24697baa159 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3365,13 +3365,13 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) return result; } -s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, +int wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index af8582456cd6..eaf3a1002e79 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -326,7 +326,7 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); -s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, +int wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, -- cgit v1.2.3 From 16a537ca78d7d1a077eb53ccb2ba98eaa7132ae8 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:21 +0900 Subject: staging: wilc1000: rename pu8bssid in wilc_set_join_req This patch renames pu8bssid to bssid to remove pu8 prefix. There is no need to add this prefix in order to show data type of this variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index b24697baa159..bb4b61284ef2 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3365,7 +3365,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) return result; } -int wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, +int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *pu8ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, @@ -3397,9 +3397,9 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, msg.body.con_info.params = pJoinParams; msg.vif = vif; - if (pu8bssid) { + if (bssid) { msg.body.con_info.bssid = kmalloc(6, GFP_KERNEL); - memcpy(msg.body.con_info.bssid, pu8bssid, 6); + memcpy(msg.body.con_info.bssid, bssid, 6); } if (pu8ssid) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index eaf3a1002e79..0e40c8f96e00 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -326,7 +326,7 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); -int wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, +int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *pu8ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, -- cgit v1.2.3 From f2cb5f3f1b47f3642cf9367d877d785973c0c267 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:22 +0900 Subject: staging: wilc1000: rename pu8ssid in wilc_set_join_req This patch renames pu8ssid to ssid to remove pu8 prefix. There is no need to add this prefix in order to show data type of this variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index bb4b61284ef2..a146d4fa2b3f 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3365,7 +3365,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) return result; } -int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *pu8ssid, +int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, @@ -3402,10 +3402,10 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *pu8ssid, memcpy(msg.body.con_info.bssid, bssid, 6); } - if (pu8ssid) { + if (ssid) { msg.body.con_info.ssid_len = ssidLen; msg.body.con_info.ssid = kmalloc(ssidLen, GFP_KERNEL); - memcpy(msg.body.con_info.ssid, pu8ssid, ssidLen); + memcpy(msg.body.con_info.ssid, ssid, ssidLen); } if (pu8IEs) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 0e40c8f96e00..5d6f8079c7cc 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -326,7 +326,7 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); -int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *pu8ssid, +int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, -- cgit v1.2.3 From dee39b1b1b0553903f7994a73660d254a195713c Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:23 +0900 Subject: staging: wilc1000: rename ssidLen in wilc_set_join_req This patch renames ssidLen to ssid_len to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index a146d4fa2b3f..4730b60fe373 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3366,7 +3366,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) } int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, - size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, + size_t ssid_len, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams) @@ -3403,9 +3403,9 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, } if (ssid) { - msg.body.con_info.ssid_len = ssidLen; - msg.body.con_info.ssid = kmalloc(ssidLen, GFP_KERNEL); - memcpy(msg.body.con_info.ssid, ssid, ssidLen); + msg.body.con_info.ssid_len = ssid_len; + msg.body.con_info.ssid = kmalloc(ssid_len, GFP_KERNEL); + memcpy(msg.body.con_info.ssid, ssid, ssid_len); } if (pu8IEs) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 5d6f8079c7cc..4c4674ba791b 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -327,7 +327,7 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, - size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, + size_t ssid_len, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams); -- cgit v1.2.3 From 88c9421ad21172f5ed9e53349e4713613c7798f7 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:24 +0900 Subject: staging: wilc1000: rename pu8IEs in wilc_set_join_req This patch renames pu8IEs to ies to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 4730b60fe373..bf1597c92f4b 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3366,7 +3366,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) } int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, - size_t ssid_len, const u8 *pu8IEs, size_t IEsLen, + size_t ssid_len, const u8 *ies, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams) @@ -3408,10 +3408,10 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, memcpy(msg.body.con_info.ssid, ssid, ssid_len); } - if (pu8IEs) { + if (ies) { msg.body.con_info.ies_len = IEsLen; msg.body.con_info.ies = kmalloc(IEsLen, GFP_KERNEL); - memcpy(msg.body.con_info.ies, pu8IEs, IEsLen); + memcpy(msg.body.con_info.ies, ies, IEsLen); } if (hif_drv->hif_state < HOST_IF_CONNECTING) hif_drv->hif_state = HOST_IF_CONNECTING; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 4c4674ba791b..44929a61608e 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -327,7 +327,7 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, - size_t ssid_len, const u8 *pu8IEs, size_t IEsLen, + size_t ssid_len, const u8 *ies, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams); -- cgit v1.2.3 From 8c38d960a416b99b05a905b304582e688a707f1a Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:25 +0900 Subject: staging: wilc1000: rename IEsLen in wilc_set_join_req This patch renames IEsLen to ies_len to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index bf1597c92f4b..4421babeea0e 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3366,7 +3366,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) } int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, - size_t ssid_len, const u8 *ies, size_t IEsLen, + size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams) @@ -3409,9 +3409,9 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, } if (ies) { - msg.body.con_info.ies_len = IEsLen; - msg.body.con_info.ies = kmalloc(IEsLen, GFP_KERNEL); - memcpy(msg.body.con_info.ies, ies, IEsLen); + msg.body.con_info.ies_len = ies_len; + msg.body.con_info.ies = kmalloc(ies_len, GFP_KERNEL); + memcpy(msg.body.con_info.ies, ies, ies_len); } if (hif_drv->hif_state < HOST_IF_CONNECTING) hif_drv->hif_state = HOST_IF_CONNECTING; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 44929a61608e..5edb178f6f1d 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -327,7 +327,7 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, - size_t ssid_len, const u8 *ies, size_t IEsLen, + size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams); -- cgit v1.2.3 From 81c23a7ebca2a4b9f1b35e6c1d7894d951eb7f56 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:26 +0900 Subject: staging: wilc1000: rename pfConnectResult in wilc_set_join_req This patch renames pfConnectResult to connect_result to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 4421babeea0e..d691c95fd8bb 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3367,7 +3367,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, - wilc_connect_result pfConnectResult, void *pvUserArg, + wilc_connect_result connect_result, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams) { @@ -3375,7 +3375,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; - if (!hif_drv || !pfConnectResult) { + if (!hif_drv || !connect_result) { PRINT_ER("Driver is null\n"); return -EFAULT; } @@ -3392,7 +3392,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, msg.body.con_info.security = u8security; msg.body.con_info.auth_type = tenuAuth_type; msg.body.con_info.ch = u8channel; - msg.body.con_info.result = pfConnectResult; + msg.body.con_info.result = connect_result; msg.body.con_info.arg = pvUserArg; msg.body.con_info.params = pJoinParams; msg.vif = vif; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 5edb178f6f1d..b42613255a34 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -328,7 +328,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, - wilc_connect_result pfConnectResult, void *pvUserArg, + wilc_connect_result connect_result, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams); int wilc_flush_join_req(struct wilc_vif *vif); -- cgit v1.2.3 From 2ef29833e1c45948b48b5d4c77da70e3ccd90ab1 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:27 +0900 Subject: staging: wilc1000: rename pvUserArg in wilc_set_join_req This patch renames pvUserArg to user_arg to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index d691c95fd8bb..11903593ad82 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3367,7 +3367,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, - wilc_connect_result connect_result, void *pvUserArg, + wilc_connect_result connect_result, void *user_arg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams) { @@ -3393,7 +3393,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, msg.body.con_info.auth_type = tenuAuth_type; msg.body.con_info.ch = u8channel; msg.body.con_info.result = connect_result; - msg.body.con_info.arg = pvUserArg; + msg.body.con_info.arg = user_arg; msg.body.con_info.params = pJoinParams; msg.vif = vif; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index b42613255a34..9e66d5eb229d 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -328,7 +328,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, - wilc_connect_result connect_result, void *pvUserArg, + wilc_connect_result connect_result, void *user_arg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams); int wilc_flush_join_req(struct wilc_vif *vif); -- cgit v1.2.3 From e0c54a883f816b7d9e72cf694329969178615687 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:28 +0900 Subject: staging: wilc1000: rename u8security in wilc_set_join_req This patch renames u8security to security to remove u8 prefix. There is no need to add prefix in order to show data type of this variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 11903593ad82..64189faf3443 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3368,7 +3368,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, - u8 u8security, enum AUTHTYPE tenuAuth_type, + u8 security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams) { int result = 0; @@ -3389,7 +3389,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, msg.id = HOST_IF_MSG_CONNECT; - msg.body.con_info.security = u8security; + msg.body.con_info.security = security; msg.body.con_info.auth_type = tenuAuth_type; msg.body.con_info.ch = u8channel; msg.body.con_info.result = connect_result; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 9e66d5eb229d..bb08e7fc7d6c 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -329,7 +329,7 @@ int wilc_wait_msg_queue_idle(void); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, - u8 u8security, enum AUTHTYPE tenuAuth_type, + u8 security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams); int wilc_flush_join_req(struct wilc_vif *vif); s32 wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode); -- cgit v1.2.3 From 12a3b8bc26ae1f81297dfdb80775191d03deca1d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:29 +0900 Subject: staging: wilc1000: rename tenuAuth_type in wilc_set_join_req This patch renames tenuAuth_type to auth_type to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 64189faf3443..d3c595e57d2f 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3368,7 +3368,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, - u8 security, enum AUTHTYPE tenuAuth_type, + u8 security, enum AUTHTYPE auth_type, u8 u8channel, void *pJoinParams) { int result = 0; @@ -3390,7 +3390,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, msg.id = HOST_IF_MSG_CONNECT; msg.body.con_info.security = security; - msg.body.con_info.auth_type = tenuAuth_type; + msg.body.con_info.auth_type = auth_type; msg.body.con_info.ch = u8channel; msg.body.con_info.result = connect_result; msg.body.con_info.arg = user_arg; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index bb08e7fc7d6c..3d5fea7c671b 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -329,7 +329,7 @@ int wilc_wait_msg_queue_idle(void); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, - u8 security, enum AUTHTYPE tenuAuth_type, + u8 security, enum AUTHTYPE auth_type, u8 u8channel, void *pJoinParams); int wilc_flush_join_req(struct wilc_vif *vif); s32 wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode); -- cgit v1.2.3 From 0ea1ece02d7d7d6ba7f362d749700fc537dbf349 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:30 +0900 Subject: staging: wilc1000: rename u8channel in wilc_set_join_req This patch renames u8channel to channel to remove u8 prefix. There is no need to add prefix in order to show data type of this variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index d3c595e57d2f..66abfa74153b 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3369,7 +3369,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, u8 security, enum AUTHTYPE auth_type, - u8 u8channel, void *pJoinParams) + u8 channel, void *pJoinParams) { int result = 0; struct host_if_msg msg; @@ -3391,7 +3391,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, msg.body.con_info.security = security; msg.body.con_info.auth_type = auth_type; - msg.body.con_info.ch = u8channel; + msg.body.con_info.ch = channel; msg.body.con_info.result = connect_result; msg.body.con_info.arg = user_arg; msg.body.con_info.params = pJoinParams; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 3d5fea7c671b..b12c04fdf69c 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -330,7 +330,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, u8 security, enum AUTHTYPE auth_type, - u8 u8channel, void *pJoinParams); + u8 channel, void *pJoinParams); int wilc_flush_join_req(struct wilc_vif *vif); s32 wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); -- cgit v1.2.3 From f382b376064fd513aa83f9ddc47920d2ac6abf59 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:31 +0900 Subject: staging: wilc1000: rename pJoinParams in wilc_set_join_req This patch renames pJoinParams to join_params to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 66abfa74153b..79f3d9f2e7cd 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3369,7 +3369,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, u8 security, enum AUTHTYPE auth_type, - u8 channel, void *pJoinParams) + u8 channel, void *join_params) { int result = 0; struct host_if_msg msg; @@ -3380,7 +3380,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, return -EFAULT; } - if (!pJoinParams) { + if (!join_params) { PRINT_ER("Unable to Join - JoinParams is NULL\n"); return -EFAULT; } @@ -3394,7 +3394,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, msg.body.con_info.ch = channel; msg.body.con_info.result = connect_result; msg.body.con_info.arg = user_arg; - msg.body.con_info.params = pJoinParams; + msg.body.con_info.params = join_params; msg.vif = vif; if (bssid) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index b12c04fdf69c..698d1b6bc330 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -330,7 +330,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, u8 security, enum AUTHTYPE auth_type, - u8 channel, void *pJoinParams); + u8 channel, void *join_params); int wilc_flush_join_req(struct wilc_vif *vif); s32 wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); -- cgit v1.2.3 From 11623136ef54ca945d64d3f8a1d1f3763ca13563 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:32 +0900 Subject: staging: wilc1000: use kmemdup instead of kmalloc and memcpy This patch changes kmalloc/memcpy to kmemdup. It is also added error checking to return -ENOMEM if kmemdup is failed. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 79f3d9f2e7cd..65189422432f 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3398,20 +3398,23 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, msg.vif = vif; if (bssid) { - msg.body.con_info.bssid = kmalloc(6, GFP_KERNEL); - memcpy(msg.body.con_info.bssid, bssid, 6); + msg.body.con_info.bssid = kmemdup(bssid, 6, GFP_KERNEL); + if (!msg.body.con_info.bssid) + return -ENOMEM; } if (ssid) { msg.body.con_info.ssid_len = ssid_len; - msg.body.con_info.ssid = kmalloc(ssid_len, GFP_KERNEL); - memcpy(msg.body.con_info.ssid, ssid, ssid_len); + msg.body.con_info.ssid = kmemdup(ssid, ssid_len, GFP_KERNEL); + if (!msg.body.con_info.ssid) + return -ENOMEM; } if (ies) { msg.body.con_info.ies_len = ies_len; - msg.body.con_info.ies = kmalloc(ies_len, GFP_KERNEL); - memcpy(msg.body.con_info.ies, ies, ies_len); + msg.body.con_info.ies = kmemdup(ies, ies_len, GFP_KERNEL); + if (!msg.body.con_info.ies) + return -ENOMEM; } if (hif_drv->hif_state < HOST_IF_CONNECTING) hif_drv->hif_state = HOST_IF_CONNECTING; -- cgit v1.2.3 From 5350251a9bba780fe1a92aebb71ecd7c37fa2e2f Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:33 +0900 Subject: staging: wilc1000: fix return type of wilc_disconnect This patch changes return type of wilc_disconnect from s32 to int. The result variable gets return value from wilc_disconnect that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 65189422432f..5ddf78df8a8a 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3461,9 +3461,9 @@ int wilc_flush_join_req(struct wilc_vif *vif) return result; } -s32 wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode) +int wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 698d1b6bc330..e8c556a0c4aa 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -332,7 +332,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, u8 security, enum AUTHTYPE auth_type, u8 channel, void *join_params); int wilc_flush_join_req(struct wilc_vif *vif); -s32 wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode); +int wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); s32 wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi); s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, -- cgit v1.2.3 From 9f723fdeb84e5c4f061bba21348e280c3a73d58d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:34 +0900 Subject: staging: wilc1000: rename u16ReasonCode in wilc_disconnect This patch renames u16ReasonCode to reason_code to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 5ddf78df8a8a..6e5bccc8bc3d 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3461,7 +3461,7 @@ int wilc_flush_join_req(struct wilc_vif *vif) return result; } -int wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode) +int wilc_disconnect(struct wilc_vif *vif, u16 reason_code) { int result = 0; struct host_if_msg msg; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index e8c556a0c4aa..fa5d2925e47a 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -332,7 +332,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, u8 security, enum AUTHTYPE auth_type, u8 channel, void *join_params); int wilc_flush_join_req(struct wilc_vif *vif); -int wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode); +int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); s32 wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi); s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, -- cgit v1.2.3 From a5f9943cc01e10a118c85845d8638b5f1331827e Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:35 +0900 Subject: staging: wilc1000: remove wilc_free_join_params wilc_free_join_params call kfree. There is no need to use wrapper function, so use kfree directly. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 -------- drivers/staging/wilc1000/host_interface.h | 3 --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 6 +++--- 3 files changed, 3 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 6e5bccc8bc3d..724b4bd75ac0 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4609,14 +4609,6 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo) return (void *)pNewJoinBssParam; } -void wilc_free_join_params(void *pJoinParams) -{ - if ((struct bss_param *)pJoinParams) - kfree((struct bss_param *)pJoinParams); - else - PRINT_ER("Unable to FREE null pointer\n"); -} - s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID) { s32 result = 0; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index fa5d2925e47a..7ac85f27217e 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -365,9 +365,6 @@ s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); s32 wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); - -void wilc_free_join_params(void *pJoinParams); - s32 wilc_get_statistics(struct wilc_vif *vif, struct rf_info *pstrStatistics); void wilc_resolve_disconnect_aberration(struct wilc_vif *vif); int wilc_get_vif_idx(struct wilc_vif *vif); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 53fb2d4bb0bd..be5704bfc382 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -196,7 +196,7 @@ static void clear_shadow_scan(void) last_scanned_shadow[last_scanned_cnt].pu8IEs = NULL; } - wilc_free_join_params(last_scanned_shadow[i].pJoinParams); + kfree(last_scanned_shadow[i].pJoinParams); last_scanned_shadow[i].pJoinParams = NULL; } last_scanned_cnt = 0; @@ -282,7 +282,7 @@ static void remove_network_from_shadow(unsigned long arg) kfree(last_scanned_shadow[i].pu8IEs); last_scanned_shadow[i].pu8IEs = NULL; - wilc_free_join_params(last_scanned_shadow[i].pJoinParams); + kfree(last_scanned_shadow[i].pJoinParams); for (j = i; (j < last_scanned_cnt - 1); j++) last_scanned_shadow[j] = last_scanned_shadow[j + 1]; @@ -376,7 +376,7 @@ static void add_network_to_shadow(tstrNetworkInfo *pstrNetworkInfo, last_scanned_shadow[ap_index].u32TimeRcvdInScanCached = jiffies; last_scanned_shadow[ap_index].u8Found = 1; if (ap_found != -1) - wilc_free_join_params(last_scanned_shadow[ap_index].pJoinParams); + kfree(last_scanned_shadow[ap_index].pJoinParams); last_scanned_shadow[ap_index].pJoinParams = pJoinParams; } -- cgit v1.2.3 From e16aed64cfbd15f358edc89f19e9da4a6fae4935 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:36 +0900 Subject: staging: wilc1000: fix return type of wilc_get_rssi This patch changes return type of wilc_get_rssi from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 724b4bd75ac0..c059e6d915eb 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3628,9 +3628,9 @@ s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, return result; } -s32 wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi) +int wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 7ac85f27217e..51ec72c01da7 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -334,7 +334,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, int wilc_flush_join_req(struct wilc_vif *vif); int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); -s32 wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi); +int wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi); s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, -- cgit v1.2.3 From 652bb5e888bca319c3d69e5473a0823a739592b5 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:37 +0900 Subject: staging: wilc1000: rename ps8Rssi in wilc_get_rssi This patch renames ps8Rssi to rssi_level to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c059e6d915eb..e1e123b7d9a8 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3628,7 +3628,7 @@ s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, return result; } -int wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi) +int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level) { int result = 0; struct host_if_msg msg; @@ -3646,12 +3646,12 @@ int wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi) down(&hif_drv->sem_get_rssi); - if (!ps8Rssi) { + if (!rssi_level) { PRINT_ER("RSS pointer value is null"); return -EFAULT; } - *ps8Rssi = rssi; + *rssi_level = rssi; return result; } diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 51ec72c01da7..4506e0b66935 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -334,7 +334,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, int wilc_flush_join_req(struct wilc_vif *vif); int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); -int wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi); +int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, -- cgit v1.2.3 From cd163d32d1db882e01e7143be8ea7f7a6f61c108 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:38 +0900 Subject: staging: wilc1000: fix return type of wilc_get_statistics This patch changes return type of wilc_get_statistics from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index e1e123b7d9a8..732ea9660d13 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3656,9 +3656,9 @@ int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level) return result; } -s32 wilc_get_statistics(struct wilc_vif *vif, struct rf_info *pstrStatistics) +int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *pstrStatistics) { - s32 result = 0; + int result = 0; struct host_if_msg msg; memset(&msg, 0, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 4506e0b66935..c64dc13deae7 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -365,7 +365,7 @@ s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); s32 wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); -s32 wilc_get_statistics(struct wilc_vif *vif, struct rf_info *pstrStatistics); +int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *pstrStatistics); void wilc_resolve_disconnect_aberration(struct wilc_vif *vif); int wilc_get_vif_idx(struct wilc_vif *vif); -- cgit v1.2.3 From f70b25ff32baf75fc460210fa4ac75626a465396 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:39 +0900 Subject: staging: wilc1000: rename pstrStatistics in wilc_get_statistics This patch renames pstrStatistics to stats to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 732ea9660d13..5113d3d5c5dc 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3656,14 +3656,14 @@ int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level) return result; } -int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *pstrStatistics) +int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) { int result = 0; struct host_if_msg msg; memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_GET_STATISTICS; - msg.body.data = (char *)pstrStatistics; + msg.body.data = (char *)stats; msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index c64dc13deae7..b8b235d72412 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -365,7 +365,7 @@ s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); s32 wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); -int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *pstrStatistics); +int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); void wilc_resolve_disconnect_aberration(struct wilc_vif *vif); int wilc_get_vif_idx(struct wilc_vif *vif); -- cgit v1.2.3 From de61db9e07e38f872541b02ee4f52965688d7e7b Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:25 +0900 Subject: staging: wilc1000: fix return type of wilc_frame_register This patch changes return type of wilc_frame_register from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 5113d3d5c5dc..d9e4e11f04d9 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4123,9 +4123,9 @@ s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID) return result; } -s32 wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg) +int wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index b8b235d72412..5ecc978dd6aa 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -362,7 +362,7 @@ s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg); s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); -s32 wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg); +int wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); -- cgit v1.2.3 From 2a8432ff3959ed483d3f55e968b746879676815d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:26 +0900 Subject: staging: wilc1000: rename u16FrameType in wilc_frame_register This patch renames u16FrameType to frame_type to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index d9e4e11f04d9..c3e59d8b18be 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4123,7 +4123,7 @@ s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID) return result; } -int wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg) +int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool bReg) { int result = 0; struct host_if_msg msg; @@ -4137,7 +4137,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg) memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_REGISTER_FRAME; - switch (u16FrameType) { + switch (frame_type) { case ACTION: PRINT_D(HOSTINF_DBG, "ACTION\n"); msg.body.reg_frame.reg_id = ACTION_FRM_IDX; @@ -4152,7 +4152,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg) PRINT_D(HOSTINF_DBG, "Not valid frame type\n"); break; } - msg.body.reg_frame.frame_type = u16FrameType; + msg.body.reg_frame.frame_type = frame_type; msg.body.reg_frame.reg = bReg; msg.vif = vif; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 5ecc978dd6aa..efb657bd3cef 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -362,7 +362,7 @@ s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg); s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); -int wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg); +int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool bReg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); -- cgit v1.2.3 From 8859fc2898c5e6d40b29e4cbabdae4f4e2902f91 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:27 +0900 Subject: staging: wilc1000: rename bReg in wilc_frame_register This patch renames bReg to reg to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c3e59d8b18be..9b72519713b9 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4123,7 +4123,7 @@ s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID) return result; } -int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool bReg) +int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) { int result = 0; struct host_if_msg msg; @@ -4153,7 +4153,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool bReg) break; } msg.body.reg_frame.frame_type = frame_type; - msg.body.reg_frame.reg = bReg; + msg.body.reg_frame.reg = reg; msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index efb657bd3cef..b43e0a1ff4e5 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -362,7 +362,7 @@ s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg); s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); -int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool bReg); +int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); -- cgit v1.2.3 From 5ca581ef48d8e3188e580e0c246208c47ceb0ca7 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:28 +0900 Subject: staging: wilc1000: fix return type of wilc_listen_state_expired This patch changes return type of wilc_listen_state_expired from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 9b72519713b9..4db211b2c9f3 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4098,9 +4098,9 @@ s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, return result; } -s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID) +int wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index b43e0a1ff4e5..fbc1ee1fccf4 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -361,7 +361,7 @@ s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg); -s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); +int wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); -- cgit v1.2.3 From 6b0f7cdd893b480ed03ff60f1c122b1aa063205a Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:29 +0900 Subject: staging: wilc1000: rename u32SessionID in wilc_listen_state_expired This patch renames u32SessionID to session_id to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 4db211b2c9f3..3a9a967390f5 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4098,7 +4098,7 @@ s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, return result; } -int wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID) +int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id) { int result = 0; struct host_if_msg msg; @@ -4114,7 +4114,7 @@ int wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID) memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_LISTEN_TIMER_FIRED; msg.vif = vif; - msg.body.remain_on_ch.id = u32SessionID; + msg.body.remain_on_ch.id = session_id; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index fbc1ee1fccf4..47c664e15194 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -361,7 +361,7 @@ s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg); -int wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); +int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id); int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); -- cgit v1.2.3 From 5d48f12c4c520e36833ab2c5189393113a65e2c6 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:30 +0900 Subject: staging: wilc1000: fix return type of wilc_set_power_mgmt This patch changes return type of wilc_set_power_mgmt from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 3a9a967390f5..8b1e535d7830 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4393,9 +4393,9 @@ s32 wilc_edit_station(struct wilc_vif *vif, return result; } -s32 wilc_set_power_mgmt(struct wilc_vif *vif, bool bIsEnabled, u32 u32Timeout) +int wilc_set_power_mgmt(struct wilc_vif *vif, bool bIsEnabled, u32 u32Timeout) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct power_mgmt_param *pstrPowerMgmtParam = &msg.body.pwr_mgmt_info; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 47c664e15194..fb9c0ead48ea 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -351,7 +351,7 @@ s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]); int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); s32 wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *pstrStaParams); -s32 wilc_set_power_mgmt(struct wilc_vif *vif, bool bIsEnabled, u32 u32Timeout); +int wilc_set_power_mgmt(struct wilc_vif *vif, bool bIsEnabled, u32 u32Timeout); s32 wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, u32 u32count); s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); -- cgit v1.2.3 From dbaa524e231630033a92d86521ececf4a0a1f019 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:31 +0900 Subject: staging: wilc1000: rename bIsEnabled in wilc_set_power_mgmt This patch renames bIsEnabled to enabled to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 8b1e535d7830..3ed8275c30ea 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4393,14 +4393,14 @@ s32 wilc_edit_station(struct wilc_vif *vif, return result; } -int wilc_set_power_mgmt(struct wilc_vif *vif, bool bIsEnabled, u32 u32Timeout) +int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 u32Timeout) { int result = 0; struct host_if_msg msg; struct power_mgmt_param *pstrPowerMgmtParam = &msg.body.pwr_mgmt_info; struct host_if_drv *hif_drv = vif->hif_drv; - PRINT_INFO(HOSTINF_DBG, "\n\n>> Setting PS to %d <<\n\n", bIsEnabled); + PRINT_INFO(HOSTINF_DBG, "\n\n>> Setting PS to %d <<\n\n", enabled); if (!hif_drv) { PRINT_ER("driver is null\n"); @@ -4414,7 +4414,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool bIsEnabled, u32 u32Timeout) msg.id = HOST_IF_MSG_POWER_MGMT; msg.vif = vif; - pstrPowerMgmtParam->enabled = bIsEnabled; + pstrPowerMgmtParam->enabled = enabled; pstrPowerMgmtParam->timeout = u32Timeout; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index fb9c0ead48ea..89765b89e429 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -351,7 +351,7 @@ s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]); int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); s32 wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *pstrStaParams); -int wilc_set_power_mgmt(struct wilc_vif *vif, bool bIsEnabled, u32 u32Timeout); +int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 u32Timeout); s32 wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, u32 u32count); s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); -- cgit v1.2.3 From ecd275000a8e1c80593255b327ab14989eb18c4c Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:32 +0900 Subject: staging: wilc1000: rename u32Timeout in wilc_set_power_mgmt This patch renames u32Timeout to timeout to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 3ed8275c30ea..dc1773deafe5 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4393,7 +4393,7 @@ s32 wilc_edit_station(struct wilc_vif *vif, return result; } -int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 u32Timeout) +int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) { int result = 0; struct host_if_msg msg; @@ -4415,7 +4415,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 u32Timeout) msg.vif = vif; pstrPowerMgmtParam->enabled = enabled; - pstrPowerMgmtParam->timeout = u32Timeout; + pstrPowerMgmtParam->timeout = timeout; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 89765b89e429..7b12425efeca 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -351,7 +351,7 @@ s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]); int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); s32 wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *pstrStaParams); -int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 u32Timeout); +int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); s32 wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, u32 u32count); s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); -- cgit v1.2.3 From 568640e4f1f00a0092559db6fbc760ae42a559ca Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:33 +0900 Subject: staging: wilc1000: rename pstrPowerMgmtParam in wilc_set_power_mgmt This patch renames pstrPowerMgmtParam to pwr_mgmt_info to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index dc1773deafe5..83ac21a3c8d6 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4397,7 +4397,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) { int result = 0; struct host_if_msg msg; - struct power_mgmt_param *pstrPowerMgmtParam = &msg.body.pwr_mgmt_info; + struct power_mgmt_param *pwr_mgmt_info = &msg.body.pwr_mgmt_info; struct host_if_drv *hif_drv = vif->hif_drv; PRINT_INFO(HOSTINF_DBG, "\n\n>> Setting PS to %d <<\n\n", enabled); @@ -4414,8 +4414,8 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) msg.id = HOST_IF_MSG_POWER_MGMT; msg.vif = vif; - pstrPowerMgmtParam->enabled = enabled; - pstrPowerMgmtParam->timeout = timeout; + pwr_mgmt_info->enabled = enabled; + pwr_mgmt_info->timeout = timeout; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) -- cgit v1.2.3 From 14d9526f69d2b283e6326dce2c4c21e529a1e23c Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:34 +0900 Subject: staging: wilc1000: fix return type of wilc_setup_multicast_filter This patch changes return type of wilc_setup_multicast_filter from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 83ac21a3c8d6..8e8e70ed2c82 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4423,10 +4423,10 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) return result; } -s32 wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, +int wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, u32 u32count) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct set_multicast *pstrMulticastFilterParam = &msg.body.multicast_info; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 7b12425efeca..52032be6a81d 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -352,7 +352,7 @@ int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); s32 wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *pstrStaParams); int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); -s32 wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, +int wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, u32 u32count); s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); -- cgit v1.2.3 From b80c0943022915b371911707adf619ccc6d3365d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:35 +0900 Subject: staging: wilc1000: rename bIsEnabled in wilc_setup_multicast_filter This patch renames bIsEnabled to enabled to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 8e8e70ed2c82..a32e930e7c53 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4423,7 +4423,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) return result; } -int wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, +int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 u32count) { int result = 0; @@ -4443,7 +4443,7 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, msg.id = HOST_IF_MSG_SET_MULTICAST_FILTER; msg.vif = vif; - pstrMulticastFilterParam->enabled = bIsEnabled; + pstrMulticastFilterParam->enabled = enabled; pstrMulticastFilterParam->cnt = u32count; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 52032be6a81d..9abdd3f49946 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -352,7 +352,7 @@ int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); s32 wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *pstrStaParams); int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); -int wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, +int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 u32count); s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); -- cgit v1.2.3 From 2dff2d4228f6c1b14dc7ea169c891783e63dc743 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:36 +0900 Subject: staging: wilc1000: rename u32count in wilc_setup_multicast_filter This patch renames u32count to count to remove u32 prefix. There is no need to use this prefix to show data type of this argument. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index a32e930e7c53..489ab290af24 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4424,7 +4424,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) } int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, - u32 u32count) + u32 count) { int result = 0; struct host_if_msg msg; @@ -4444,7 +4444,7 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, msg.vif = vif; pstrMulticastFilterParam->enabled = enabled; - pstrMulticastFilterParam->cnt = u32count; + pstrMulticastFilterParam->cnt = count; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 9abdd3f49946..5c271b180ca3 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -353,7 +353,7 @@ s32 wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *pstrStaParams); int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, - u32 u32count); + u32 count); s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, -- cgit v1.2.3 From 40ecd38a6e1ab30ef4fe843ca9e77754cde41287 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:37 +0900 Subject: staging: wilc1000: rename pstrMulticastFilterParam in wilc_setup_multicast_filter This patch renames pstrMulticastFilterParam to multicast_filter_param to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 489ab290af24..aeb327158c58 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4428,7 +4428,7 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, { int result = 0; struct host_if_msg msg; - struct set_multicast *pstrMulticastFilterParam = &msg.body.multicast_info; + struct set_multicast *multicast_filter_param = &msg.body.multicast_info; struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv) { @@ -4443,8 +4443,8 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, msg.id = HOST_IF_MSG_SET_MULTICAST_FILTER; msg.vif = vif; - pstrMulticastFilterParam->enabled = enabled; - pstrMulticastFilterParam->cnt = count; + multicast_filter_param->enabled = enabled; + multicast_filter_param->cnt = count; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) -- cgit v1.2.3 From 3d2a0bf719defc6087cf526af1e2ba98ae5e3bae Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:38 +0900 Subject: staging: wilc1000: fix return type of wilc_setup_ipaddress This patch changes return type of wilc_setup_ipaddress from s32 to int. The result variable gets return value from wilc_mq_send that has data type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index aeb327158c58..dacadc91aca7 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4638,9 +4638,9 @@ s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID) return result; } -s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx) +int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 5c271b180ca3..d36a9f5c5ad3 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -354,7 +354,7 @@ s32 wilc_edit_station(struct wilc_vif *vif, int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); -s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); +int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, u32 u32duration, u16 chan, -- cgit v1.2.3 From 6964f086e5a8b72d7d911f322738a27621f8533d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:39 +0900 Subject: staging: wilc1000: rename u16ipadd in wilc_setup_ipaddress This patch renames u16ipadd to ip_addr to remove u16 prefix. There is no need to use prefix to show data type of this argument. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index dacadc91aca7..0d41657a4624 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4638,7 +4638,7 @@ s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID) return result; } -int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx) +int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) { int result = 0; struct host_if_msg msg; @@ -4655,7 +4655,7 @@ int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx) msg.id = HOST_IF_MSG_SET_IPADDRESS; - msg.body.ip_info.ip_addr = u16ipadd; + msg.body.ip_info.ip_addr = ip_addr; msg.vif = vif; msg.body.ip_info.idx = idx; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index d36a9f5c5ad3..f90a530e24e6 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -354,7 +354,7 @@ s32 wilc_edit_station(struct wilc_vif *vif, int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); -int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); +int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, u32 u32duration, u16 chan, -- cgit v1.2.3 From 0fd6fa32988413fff37c9c38940737dc2831a11f Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:40 +0900 Subject: staging: wilc1000: remove return statement This patch removes return statement that is always returned 0. wilc_setup_ipaddress can not run to the end due to return statement. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 0d41657a4624..90fdbddaf9cd 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4644,8 +4644,6 @@ int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; - return 0; - if (!hif_drv) { PRINT_ER("driver is null\n"); return -EFAULT; -- cgit v1.2.3 From cb8f4e0e6d8bc1d37a50578bf0a84dd5567afa08 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:41 +0900 Subject: staging: wilc1000: fix return type of host_int_get_ipaddress This patch changes return type of host_int_get_ipaddress from s32 to int. The result variable gets return value from wilc_mq_send that has data type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 90fdbddaf9cd..a203647eb27d 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -362,7 +362,7 @@ static s32 handle_set_operation_mode(struct wilc_vif *vif, return result; } -static s32 host_int_get_ipaddress(struct wilc_vif *vif, +static int host_int_get_ipaddress(struct wilc_vif *vif, struct host_if_drv *hif_drv, u8 *u16ipadd, u8 idx); @@ -4664,11 +4664,11 @@ int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) return result; } -static s32 host_int_get_ipaddress(struct wilc_vif *vif, +static int host_int_get_ipaddress(struct wilc_vif *vif, struct host_if_drv *hif_drv, u8 *u16ipadd, u8 idx) { - s32 result = 0; + int result = 0; struct host_if_msg msg; if (!hif_drv) { -- cgit v1.2.3 From f8813d3aa26993178cc4d62e58eb74427f272c66 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:42 +0900 Subject: staging: wilc1000: remove argument hif_drv in host_int_get_ipaddress This patch removes hif_drv argument of host_int_get_ipaddress. There is no need to pass hif_drv in this function because hif_drv is a member of vif. It is removed struct host_if_drv and use hif_drv of vif. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index a203647eb27d..72115ae96de2 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -362,16 +362,13 @@ static s32 handle_set_operation_mode(struct wilc_vif *vif, return result; } -static int host_int_get_ipaddress(struct wilc_vif *vif, - struct host_if_drv *hif_drv, - u8 *u16ipadd, u8 idx); +static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) { s32 result = 0; struct wid wid; char firmware_ip_addr[4] = {0}; - struct host_if_drv *hif_drv = vif->hif_drv; if (ip_addr[0] < 192) ip_addr[0] = 0; @@ -389,7 +386,7 @@ static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); - host_int_get_ipaddress(vif, hif_drv, firmware_ip_addr, idx); + host_int_get_ipaddress(vif, firmware_ip_addr, idx); if (result) { PRINT_ER("Failed to set IP address\n"); @@ -4664,12 +4661,11 @@ int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) return result; } -static int host_int_get_ipaddress(struct wilc_vif *vif, - struct host_if_drv *hif_drv, - u8 *u16ipadd, u8 idx) +static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx) { int result = 0; struct host_if_msg msg; + struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv) { PRINT_ER("driver is null\n"); -- cgit v1.2.3 From 3b4276d92f8d4f2a0999fb9ea76e98546895a1ba Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:43 +0900 Subject: staging: wilc1000: rename u16ipadd in host_int_get_ipaddress This patch renames u16ipadd to ip_addr to remove u16 prefix. There is no need to use this prefix to show data type of this argument. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 72115ae96de2..c8b4b320df31 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -362,7 +362,7 @@ static s32 handle_set_operation_mode(struct wilc_vif *vif, return result; } -static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); +static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) { @@ -4661,7 +4661,7 @@ int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) return result; } -static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx) +static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) { int result = 0; struct host_if_msg msg; @@ -4676,7 +4676,7 @@ static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx) msg.id = HOST_IF_MSG_GET_IPADDRESS; - msg.body.ip_info.ip_addr = u16ipadd; + msg.body.ip_info.ip_addr = ip_addr; msg.vif = vif; msg.body.ip_info.idx = idx; -- cgit v1.2.3 From 4ad878bee170cfa6722af26d39740a3c73614218 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:44 +0900 Subject: staging: wilc1000: move static declaration of host_int_get_ipaddress This patch moves static function declaration to front part of host_interface.c file. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c8b4b320df31..5a97a9ddb4e3 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -263,6 +263,7 @@ static struct wilc_vif *join_req_vif; #define FLUSHED_BYTE_POS 79 static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo); +static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); /* The u8IfIdx starts from 0 to NUM_CONCURRENT_IFC -1, but 0 index used as * special purpose in wilc device, so we add 1 to the index to starts from 1. @@ -362,8 +363,6 @@ static s32 handle_set_operation_mode(struct wilc_vif *vif, return result; } -static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); - static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) { s32 result = 0; -- cgit v1.2.3 From fb6e06806b31867e31e095303688cc5dd7503f4a Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:33 +0900 Subject: staging: wilc1000: rename u32duration in struct remain_ch The patch renames u32duration to duration that is a member of struct remain_ch. The prefix u32 shows data type of its member, but there is no need to use u32 prefix to represent data type. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 5a97a9ddb4e3..39fa5a3c6021 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -2558,7 +2558,7 @@ ERRORHANDLER: hif_drv->remain_on_ch_timer.data = (unsigned long)vif; mod_timer(&hif_drv->remain_on_ch_timer, jiffies + - msecs_to_jiffies(pstrHostIfRemainOnChan->u32duration)); + msecs_to_jiffies(pstrHostIfRemainOnChan->duration)); if (hif_drv->remain_on_ch.ready) hif_drv->remain_on_ch.ready(hif_drv->remain_on_ch.arg); @@ -4083,7 +4083,7 @@ s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, msg.body.remain_on_ch.expired = RemainOnChanExpired; msg.body.remain_on_ch.ready = RemainOnChanReady; msg.body.remain_on_ch.arg = pvUserArg; - msg.body.remain_on_ch.u32duration = u32duration; + msg.body.remain_on_ch.duration = u32duration; msg.body.remain_on_ch.id = u32SessionID; msg.vif = vif; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index f90a530e24e6..a2f428f1db18 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -240,7 +240,7 @@ struct ba_session_info { struct remain_ch { u16 ch; - u32 u32duration; + u32 duration; wilc_remain_on_chan_expired expired; wilc_remain_on_chan_ready ready; void *arg; -- cgit v1.2.3 From 6d6bc4003b0a0930b8be8d69d5fc5ea4174577b7 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:34 +0900 Subject: staging: wilc1000: fix return type of wilc_remain_on_channel This patch changes return type of wilc_remain_on_channel from s32 to int. The result variable gets return value from wilc_mq_send that has data type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 39fa5a3c6021..30b4f3056433 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4061,13 +4061,13 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, return; } -s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, +int wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, u32 u32duration, u16 chan, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index a2f428f1db18..e28f46266cbe 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -356,7 +356,7 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); -s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, +int wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, u32 u32duration, u16 chan, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, -- cgit v1.2.3 From 6f7584be30f03f13704c7dd928f816110a2aa170 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:35 +0900 Subject: staging: wilc1000: rename u32SessionID in wilc_remain_on_channel This patch renames u32SessionID to session_id to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 30b4f3056433..6ea907e3b30c 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4061,7 +4061,7 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, return; } -int wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, +int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 u32duration, u16 chan, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, @@ -4084,7 +4084,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, msg.body.remain_on_ch.ready = RemainOnChanReady; msg.body.remain_on_ch.arg = pvUserArg; msg.body.remain_on_ch.duration = u32duration; - msg.body.remain_on_ch.id = u32SessionID; + msg.body.remain_on_ch.id = session_id; msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index e28f46266cbe..c935e49d8f8f 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -356,7 +356,7 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); -int wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, +int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 u32duration, u16 chan, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, -- cgit v1.2.3 From d44cd45ee1a8984c017f54a4d6afc484bbd152af Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:36 +0900 Subject: staging: wilc1000: rename u32duration in wilc_remain_on_channel This patch renames u32duration to duration to remove u32 prefix. There is no need u32 prefix to show data type of this variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 6ea907e3b30c..116942df424a 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4062,7 +4062,7 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, } int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, - u32 u32duration, u16 chan, + u32 duration, u16 chan, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg) @@ -4083,7 +4083,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, msg.body.remain_on_ch.expired = RemainOnChanExpired; msg.body.remain_on_ch.ready = RemainOnChanReady; msg.body.remain_on_ch.arg = pvUserArg; - msg.body.remain_on_ch.duration = u32duration; + msg.body.remain_on_ch.duration = duration; msg.body.remain_on_ch.id = session_id; msg.vif = vif; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index c935e49d8f8f..4902cc8688a5 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -357,7 +357,7 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, - u32 u32duration, u16 chan, + u32 duration, u16 chan, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg); -- cgit v1.2.3 From 95bfdd58c07d6e1bec252b8f175c7934f75d4796 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:37 +0900 Subject: staging: wilc1000: rename RemainOnChanExpired in wilc_remain_on_channel This patch renames RemainOnChanExpired to expired to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 116942df424a..9265328325d3 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4063,7 +4063,7 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, - wilc_remain_on_chan_expired RemainOnChanExpired, + wilc_remain_on_chan_expired expired, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg) { @@ -4080,7 +4080,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, msg.id = HOST_IF_MSG_REMAIN_ON_CHAN; msg.body.remain_on_ch.ch = chan; - msg.body.remain_on_ch.expired = RemainOnChanExpired; + msg.body.remain_on_ch.expired = expired; msg.body.remain_on_ch.ready = RemainOnChanReady; msg.body.remain_on_ch.arg = pvUserArg; msg.body.remain_on_ch.duration = duration; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 4902cc8688a5..d2ca27eb3284 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -358,7 +358,7 @@ int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, - wilc_remain_on_chan_expired RemainOnChanExpired, + wilc_remain_on_chan_expired expired, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg); int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id); -- cgit v1.2.3 From 1aae9398e5756588df58880be67b7f318b6d21ce Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:38 +0900 Subject: staging: wilc1000: rename RemainOnChanReady in wilc_remain_on_channel This patch renames RemainOnChanReady to ready to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 9265328325d3..21d1e87e2db1 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4064,7 +4064,7 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, wilc_remain_on_chan_expired expired, - wilc_remain_on_chan_ready RemainOnChanReady, + wilc_remain_on_chan_ready ready, void *pvUserArg) { int result = 0; @@ -4081,7 +4081,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, msg.id = HOST_IF_MSG_REMAIN_ON_CHAN; msg.body.remain_on_ch.ch = chan; msg.body.remain_on_ch.expired = expired; - msg.body.remain_on_ch.ready = RemainOnChanReady; + msg.body.remain_on_ch.ready = ready; msg.body.remain_on_ch.arg = pvUserArg; msg.body.remain_on_ch.duration = duration; msg.body.remain_on_ch.id = session_id; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index d2ca27eb3284..8a03055bcf5d 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -359,7 +359,7 @@ s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, wilc_remain_on_chan_expired expired, - wilc_remain_on_chan_ready RemainOnChanReady, + wilc_remain_on_chan_ready ready, void *pvUserArg); int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id); int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); -- cgit v1.2.3 From 482c43301d937dd5d3a565be856d8dda5b51a1dd Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:39 +0900 Subject: staging: wilc1000: rename pvUserArg in wilc_remain_on_channel This patch renames pvUserArg to user_arg to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 21d1e87e2db1..3636f7664b21 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4065,7 +4065,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, wilc_remain_on_chan_expired expired, wilc_remain_on_chan_ready ready, - void *pvUserArg) + void *user_arg) { int result = 0; struct host_if_msg msg; @@ -4082,7 +4082,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, msg.body.remain_on_ch.ch = chan; msg.body.remain_on_ch.expired = expired; msg.body.remain_on_ch.ready = ready; - msg.body.remain_on_ch.arg = pvUserArg; + msg.body.remain_on_ch.arg = user_arg; msg.body.remain_on_ch.duration = duration; msg.body.remain_on_ch.id = session_id; msg.vif = vif; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 8a03055bcf5d..4f741ff53f65 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -360,7 +360,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, wilc_remain_on_chan_expired expired, wilc_remain_on_chan_ready ready, - void *pvUserArg); + void *user_arg); int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id); int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); -- cgit v1.2.3 From 2c2e461b1d0a0ee5374aded6056c2f1fbdcecdf7 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:40 +0900 Subject: staging: wilc1000: fix return type of wilc_del_all_rx_ba_session This patch changes return type of wilc_del_all_rx_ba_session from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 3636f7664b21..bf01e83c445d 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4605,9 +4605,9 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo) return (void *)pNewJoinBssParam; } -s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID) +int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct ba_session_info *pBASessionInfo = &msg.body.session_info; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 4f741ff53f65..85064cd4c9c8 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -355,7 +355,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); -s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); +int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, wilc_remain_on_chan_expired expired, -- cgit v1.2.3 From 73d41cce7769570857a1f223ab9faa7233f8e0bf Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:41 +0900 Subject: staging: wilc1000: rename pBSSID in wilc_del_all_rx_ba_session This patch renames pBSSID to bssid to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index bf01e83c445d..735e6f1dc25f 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4605,7 +4605,7 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo) return (void *)pNewJoinBssParam; } -int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID) +int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char TID) { int result = 0; struct host_if_msg msg; @@ -4621,7 +4621,7 @@ int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID) msg.id = HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS; - memcpy(pBASessionInfo->bssid, pBSSID, ETH_ALEN); + memcpy(pBASessionInfo->bssid, bssid, ETH_ALEN); pBASessionInfo->tid = TID; msg.vif = vif; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 85064cd4c9c8..5f7156e84f22 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -355,7 +355,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); -int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); +int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char TID); int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, wilc_remain_on_chan_expired expired, -- cgit v1.2.3 From d7954748de0e2368811ef68646d76184ed108f72 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:42 +0900 Subject: staging: wilc1000: rename TID in wilc_del_all_rx_ba_session This patch renames TID to tid to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 735e6f1dc25f..265c42beb0ba 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4605,7 +4605,7 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo) return (void *)pNewJoinBssParam; } -int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char TID) +int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char tid) { int result = 0; struct host_if_msg msg; @@ -4622,7 +4622,7 @@ int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char TID) msg.id = HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS; memcpy(pBASessionInfo->bssid, bssid, ETH_ALEN); - pBASessionInfo->tid = TID; + pBASessionInfo->tid = tid; msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 5f7156e84f22..6c8fe3a0ced8 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -355,7 +355,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); -int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char TID); +int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char tid); int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, wilc_remain_on_chan_expired expired, -- cgit v1.2.3 From b91e6f33771ed5372bf379d5a33d2aae81842c50 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:43 +0900 Subject: staging: wilc1000: rename pBASessionInfo in wilc_del_all_rx_ba_session This patch renames pBASessionInfo to ba_session_info to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 265c42beb0ba..409d910a5ca7 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4609,7 +4609,7 @@ int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char tid) { int result = 0; struct host_if_msg msg; - struct ba_session_info *pBASessionInfo = &msg.body.session_info; + struct ba_session_info *ba_session_info = &msg.body.session_info; struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv) { @@ -4621,8 +4621,8 @@ int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char tid) msg.id = HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS; - memcpy(pBASessionInfo->bssid, bssid, ETH_ALEN); - pBASessionInfo->tid = tid; + memcpy(ba_session_info->bssid, bssid, ETH_ALEN); + ba_session_info->tid = tid; msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); -- cgit v1.2.3 From 4208e6632138c9295820092d254016dd66b50e1c Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:44 +0900 Subject: staging: wilc1000: fix return type of wilc_edit_station This patch changes return type of wilc_edit_station from s32 to int. The result variable gets return value from wilc_mq_send that has data type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 409d910a5ca7..eb2d664cc038 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4350,10 +4350,10 @@ s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]) return result; } -s32 wilc_edit_station(struct wilc_vif *vif, +int wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *pstrStaParams) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct add_sta_param *pstrAddStationMsg = &msg.body.add_sta_info; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 6c8fe3a0ced8..f60bebb34477 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -349,7 +349,7 @@ int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]); int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); -s32 wilc_edit_station(struct wilc_vif *vif, +int wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *pstrStaParams); int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, -- cgit v1.2.3 From 4c7abe191922f1f76c0f66e553fa307fb499160e Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:45 +0900 Subject: staging: wilc1000: rename pstrStaParams in wilc_edit_station This patch renames pstrStaParams to sta_param to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index eb2d664cc038..de921fa0f19f 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4351,7 +4351,7 @@ s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]) } int wilc_edit_station(struct wilc_vif *vif, - struct add_sta_param *pstrStaParams) + struct add_sta_param *sta_param) { int result = 0; struct host_if_msg msg; @@ -4370,14 +4370,14 @@ int wilc_edit_station(struct wilc_vif *vif, msg.id = HOST_IF_MSG_EDIT_STATION; msg.vif = vif; - memcpy(pstrAddStationMsg, pstrStaParams, sizeof(struct add_sta_param)); + memcpy(pstrAddStationMsg, sta_param, sizeof(struct add_sta_param)); if (pstrAddStationMsg->rates_len > 0) { u8 *rates = kmalloc(pstrAddStationMsg->rates_len, GFP_KERNEL); if (!rates) return -ENOMEM; - memcpy(rates, pstrStaParams->rates, + memcpy(rates, sta_param->rates, pstrAddStationMsg->rates_len); pstrAddStationMsg->rates = rates; } diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index f60bebb34477..abb626e92dbb 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -350,7 +350,7 @@ int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]); int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); int wilc_edit_station(struct wilc_vif *vif, - struct add_sta_param *pstrStaParams); + struct add_sta_param *sta_param); int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); -- cgit v1.2.3 From 785c0712048afa9528a48970eec1863cf71d4ffc Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:46 +0900 Subject: staging: wilc1000: rename pstrAddStationMsg in wilc_edit_station This patch renames pstrAddStationMsg to add_sta_info to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index de921fa0f19f..2f94804e28a0 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4355,7 +4355,7 @@ int wilc_edit_station(struct wilc_vif *vif, { int result = 0; struct host_if_msg msg; - struct add_sta_param *pstrAddStationMsg = &msg.body.add_sta_info; + struct add_sta_param *add_sta_info = &msg.body.add_sta_info; struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv) { @@ -4370,16 +4370,16 @@ int wilc_edit_station(struct wilc_vif *vif, msg.id = HOST_IF_MSG_EDIT_STATION; msg.vif = vif; - memcpy(pstrAddStationMsg, sta_param, sizeof(struct add_sta_param)); - if (pstrAddStationMsg->rates_len > 0) { - u8 *rates = kmalloc(pstrAddStationMsg->rates_len, GFP_KERNEL); + memcpy(add_sta_info, sta_param, sizeof(struct add_sta_param)); + if (add_sta_info->rates_len > 0) { + u8 *rates = kmalloc(add_sta_info->rates_len, GFP_KERNEL); if (!rates) return -ENOMEM; memcpy(rates, sta_param->rates, - pstrAddStationMsg->rates_len); - pstrAddStationMsg->rates = rates; + add_sta_info->rates_len); + add_sta_info->rates = rates; } result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); -- cgit v1.2.3 From 1ae82d1ab0adf01fc3b049d375ccdf9c878085e0 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:47 +0900 Subject: staging: wilc1000: use kmemdup in wilc_edit_station This patch replaces kmalloc followed by memcpy with kmemdup. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 2f94804e28a0..290c27aa0184 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4372,13 +4372,11 @@ int wilc_edit_station(struct wilc_vif *vif, memcpy(add_sta_info, sta_param, sizeof(struct add_sta_param)); if (add_sta_info->rates_len > 0) { - u8 *rates = kmalloc(add_sta_info->rates_len, GFP_KERNEL); - + u8 *rates = kmemdup(sta_param->rates, + add_sta_info->rates_len, + GFP_KERNEL); if (!rates) return -ENOMEM; - - memcpy(rates, sta_param->rates, - add_sta_info->rates_len); add_sta_info->rates = rates; } -- cgit v1.2.3 From e38d850f70a2a3a19d26c662bb2fc9c897e99e92 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:48 +0900 Subject: staging: wilc1000: remove rates variable in wilc_edit_station Instead of using rates variable, it is used as add_sta_info->rates directly. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 290c27aa0184..57d59dc77cba 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4372,12 +4372,11 @@ int wilc_edit_station(struct wilc_vif *vif, memcpy(add_sta_info, sta_param, sizeof(struct add_sta_param)); if (add_sta_info->rates_len > 0) { - u8 *rates = kmemdup(sta_param->rates, - add_sta_info->rates_len, - GFP_KERNEL); - if (!rates) + add_sta_info->rates = kmemdup(sta_param->rates, + add_sta_info->rates_len, + GFP_KERNEL); + if (!add_sta_info->rates) return -ENOMEM; - add_sta_info->rates = rates; } result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); -- cgit v1.2.3 From 253eb92e40bb8a3a9e3f4f293354820bfd4bc049 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:49 +0900 Subject: staging: wilc1000: fix return type of wilc_del_allstation This patch changes return type of wilc_del_allstation from s32 to int. The result variable gets return value from wilc_mq_send that has data type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 57d59dc77cba..3f410b2b4ee4 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4299,9 +4299,9 @@ int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr) return result; } -s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]) +int wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct del_all_sta *pstrDelAllStationMsg = &msg.body.del_all_sta_info; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index abb626e92dbb..6d424e73629e 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -347,7 +347,7 @@ s32 wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); -s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]); +int wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]); int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); int wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *sta_param); -- cgit v1.2.3 From 2092374d7ec53b91c4921ce2d21cc0ad2382cb9f Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:50 +0900 Subject: staging: wilc1000: rename pu8MacAddr in wilc_del_allstation This patch renames pu8MacAddr to mac_addr to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 3f410b2b4ee4..37a78a33d0ce 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4299,7 +4299,7 @@ int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr) return result; } -int wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]) +int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) { int result = 0; struct host_if_msg msg; @@ -4322,8 +4322,8 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]) msg.vif = vif; for (i = 0; i < MAX_NUM_STA; i++) { - if (memcmp(pu8MacAddr[i], au8Zero_Buff, ETH_ALEN)) { - memcpy(pstrDelAllStationMsg->del_all_sta[i], pu8MacAddr[i], ETH_ALEN); + if (memcmp(mac_addr[i], au8Zero_Buff, ETH_ALEN)) { + memcpy(pstrDelAllStationMsg->del_all_sta[i], mac_addr[i], ETH_ALEN); PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", pstrDelAllStationMsg->del_all_sta[i][0], pstrDelAllStationMsg->del_all_sta[i][1], diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 6d424e73629e..3c932e7a9b76 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -347,7 +347,7 @@ s32 wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); -int wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]); +int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]); int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); int wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *sta_param); -- cgit v1.2.3 From 55d44a621dcb8eaadfffd28f74123f51d2e75eb2 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:51 +0900 Subject: staging: wilc1000: rename pstrDelAllStationMsg in wilc_del_allstation This patch renames pstrDelAllStationMsg to del_all_sta_info to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 37a78a33d0ce..7686a521f548 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4303,7 +4303,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) { int result = 0; struct host_if_msg msg; - struct del_all_sta *pstrDelAllStationMsg = &msg.body.del_all_sta_info; + struct del_all_sta *del_all_sta_info = &msg.body.del_all_sta_info; struct host_if_drv *hif_drv = vif->hif_drv; u8 au8Zero_Buff[ETH_ALEN] = {0}; u32 i; @@ -4323,14 +4323,14 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) for (i = 0; i < MAX_NUM_STA; i++) { if (memcmp(mac_addr[i], au8Zero_Buff, ETH_ALEN)) { - memcpy(pstrDelAllStationMsg->del_all_sta[i], mac_addr[i], ETH_ALEN); + memcpy(del_all_sta_info->del_all_sta[i], mac_addr[i], ETH_ALEN); PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", - pstrDelAllStationMsg->del_all_sta[i][0], - pstrDelAllStationMsg->del_all_sta[i][1], - pstrDelAllStationMsg->del_all_sta[i][2], - pstrDelAllStationMsg->del_all_sta[i][3], - pstrDelAllStationMsg->del_all_sta[i][4], - pstrDelAllStationMsg->del_all_sta[i][5]); + del_all_sta_info->del_all_sta[i][0], + del_all_sta_info->del_all_sta[i][1], + del_all_sta_info->del_all_sta[i][2], + del_all_sta_info->del_all_sta[i][3], + del_all_sta_info->del_all_sta[i][4], + del_all_sta_info->del_all_sta[i][5]); u8AssocNumb++; } } @@ -4339,7 +4339,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) return result; } - pstrDelAllStationMsg->assoc_sta = u8AssocNumb; + del_all_sta_info->assoc_sta = u8AssocNumb; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) -- cgit v1.2.3 From 06e682b06e9823bba7a10dbb0a33d8c6a14ec78d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:52 +0900 Subject: staging: wilc1000: rename au8Zero_Buff in wilc_del_allstation This patch renames au8Zero_Buff to zero_addr to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 7686a521f548..a3f120aebf04 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4305,7 +4305,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) struct host_if_msg msg; struct del_all_sta *del_all_sta_info = &msg.body.del_all_sta_info; struct host_if_drv *hif_drv = vif->hif_drv; - u8 au8Zero_Buff[ETH_ALEN] = {0}; + u8 zero_addr[ETH_ALEN] = {0}; u32 i; u8 u8AssocNumb = 0; @@ -4322,7 +4322,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) msg.vif = vif; for (i = 0; i < MAX_NUM_STA; i++) { - if (memcmp(mac_addr[i], au8Zero_Buff, ETH_ALEN)) { + if (memcmp(mac_addr[i], zero_addr, ETH_ALEN)) { memcpy(del_all_sta_info->del_all_sta[i], mac_addr[i], ETH_ALEN); PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", del_all_sta_info->del_all_sta[i][0], -- cgit v1.2.3 From cc971eec560bdde8ff0dbc68ebeea3056892ba60 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:53 +0900 Subject: staging: wilc1000: use int instead of u32 The variable i is used as array index so that it is better to use data type of int. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index a3f120aebf04..c0f30a29cc9b 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4306,7 +4306,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) struct del_all_sta *del_all_sta_info = &msg.body.del_all_sta_info; struct host_if_drv *hif_drv = vif->hif_drv; u8 zero_addr[ETH_ALEN] = {0}; - u32 i; + int i; u8 u8AssocNumb = 0; if (!hif_drv) { -- cgit v1.2.3 From 9d6cec9f46eb993a158d6ad48f65aec419683795 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:54 +0900 Subject: staging: wilc1000: rename u8AssocNumb in wilc_del_allstation This patch renames u8AssocNumb to assoc_sta to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c0f30a29cc9b..0ff500d5b7ae 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4307,7 +4307,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) struct host_if_drv *hif_drv = vif->hif_drv; u8 zero_addr[ETH_ALEN] = {0}; int i; - u8 u8AssocNumb = 0; + u8 assoc_sta = 0; if (!hif_drv) { PRINT_ER("driver is null\n"); @@ -4331,15 +4331,15 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) del_all_sta_info->del_all_sta[i][3], del_all_sta_info->del_all_sta[i][4], del_all_sta_info->del_all_sta[i][5]); - u8AssocNumb++; + assoc_sta++; } } - if (!u8AssocNumb) { + if (!assoc_sta) { PRINT_D(CFG80211_DBG, "NO ASSOCIATED STAS\n"); return result; } - del_all_sta_info->assoc_sta = u8AssocNumb; + del_all_sta_info->assoc_sta = assoc_sta; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) -- cgit v1.2.3 From 4d84dbed22cf4c9c0f98b72429499b1a59d63103 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:55 +0900 Subject: staging: wilc1000: fix return type of wilc_add_beacon This patch changes return type of wilc_add_beacon from s32 to int. The result variable gets return value from wilc_mq_send that has data type of int. It should be changed return type of this function as well as result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 0ff500d5b7ae..8d935e4112c0 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4159,10 +4159,10 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) return result; } -s32 wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, +int wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct beacon_attr *pstrSetBeaconParam = &msg.body.beacon_info; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 3c932e7a9b76..272b69691849 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -343,7 +343,7 @@ s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); s32 wilc_deinit(struct wilc_vif *vif); -s32 wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, +int wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); -- cgit v1.2.3 From 8b1844bb20fe435f9bf4a86ea6572aec575a5659 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:56 +0900 Subject: staging: wilc1000: rename u32Interval in wilc_add_beacon This patch renames u32Interval to interval to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 8d935e4112c0..615ae5916691 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4159,7 +4159,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) return result; } -int wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, +int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 u32DTIMPeriod, u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail) { int result = 0; @@ -4178,7 +4178,7 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, msg.id = HOST_IF_MSG_ADD_BEACON; msg.vif = vif; - pstrSetBeaconParam->interval = u32Interval; + pstrSetBeaconParam->interval = interval; pstrSetBeaconParam->dtim_period = u32DTIMPeriod; pstrSetBeaconParam->head_len = u32HeadLen; pstrSetBeaconParam->head = kmemdup(pu8Head, u32HeadLen, GFP_KERNEL); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 272b69691849..93a8abb47341 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -343,7 +343,7 @@ s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); s32 wilc_deinit(struct wilc_vif *vif); -int wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, +int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 u32DTIMPeriod, u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); -- cgit v1.2.3 From 916935f5c8e313bdbecc6c7de60c5abb04e95986 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:57 +0900 Subject: staging: wilc1000: rename u32DTIMPeriod in wilc_add_beacon This patch renames u32DTIMPeriod to dtim_period to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 615ae5916691..9d9cf9126c4e 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4159,7 +4159,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) return result; } -int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 u32DTIMPeriod, +int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail) { int result = 0; @@ -4179,7 +4179,7 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 u32DTIMPeriod, msg.id = HOST_IF_MSG_ADD_BEACON; msg.vif = vif; pstrSetBeaconParam->interval = interval; - pstrSetBeaconParam->dtim_period = u32DTIMPeriod; + pstrSetBeaconParam->dtim_period = dtim_period; pstrSetBeaconParam->head_len = u32HeadLen; pstrSetBeaconParam->head = kmemdup(pu8Head, u32HeadLen, GFP_KERNEL); if (!pstrSetBeaconParam->head) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 93a8abb47341..58b73d665292 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -343,7 +343,7 @@ s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); s32 wilc_deinit(struct wilc_vif *vif); -int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 u32DTIMPeriod, +int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); -- cgit v1.2.3 From 418990415fbf36bdafcb92a6313b56a2516b5f32 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:58 +0900 Subject: staging: wilc1000: rename u32HeadLen in wilc_add_beacon This patch renames u32HeadLen to head_len to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 9d9cf9126c4e..07674d2f5404 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4160,7 +4160,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) } int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail) + u32 head_len, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail) { int result = 0; struct host_if_msg msg; @@ -4180,8 +4180,8 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, msg.vif = vif; pstrSetBeaconParam->interval = interval; pstrSetBeaconParam->dtim_period = dtim_period; - pstrSetBeaconParam->head_len = u32HeadLen; - pstrSetBeaconParam->head = kmemdup(pu8Head, u32HeadLen, GFP_KERNEL); + pstrSetBeaconParam->head_len = head_len; + pstrSetBeaconParam->head = kmemdup(pu8Head, head_len, GFP_KERNEL); if (!pstrSetBeaconParam->head) { result = -ENOMEM; goto ERRORHANDLER; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 58b73d665292..02750281fe0f 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -344,7 +344,7 @@ s32 wilc_hif_set_cfg(struct wilc_vif *vif, s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); s32 wilc_deinit(struct wilc_vif *vif); int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail); + u32 head_len, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]); -- cgit v1.2.3 From 55a76be054fb3826e691b2f9370ac4ac76bf9fdd Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:59 +0900 Subject: staging: wilc1000: rename pu8Head in wilc_add_beacon This patch renames pu8Head to head to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 07674d2f5404..e35465e8fe4d 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4160,7 +4160,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) } int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 head_len, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail) + u32 head_len, u8 *head, u32 u32TailLen, u8 *pu8Tail) { int result = 0; struct host_if_msg msg; @@ -4181,7 +4181,7 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, pstrSetBeaconParam->interval = interval; pstrSetBeaconParam->dtim_period = dtim_period; pstrSetBeaconParam->head_len = head_len; - pstrSetBeaconParam->head = kmemdup(pu8Head, head_len, GFP_KERNEL); + pstrSetBeaconParam->head = kmemdup(head, head_len, GFP_KERNEL); if (!pstrSetBeaconParam->head) { result = -ENOMEM; goto ERRORHANDLER; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 02750281fe0f..1c3f741ea48a 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -344,7 +344,7 @@ s32 wilc_hif_set_cfg(struct wilc_vif *vif, s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); s32 wilc_deinit(struct wilc_vif *vif); int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 head_len, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail); + u32 head_len, u8 *head, u32 u32TailLen, u8 *pu8Tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]); -- cgit v1.2.3 From 2df3585b12554f242816b21c4d6bd9f7e7f4c8cc Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:36:00 +0900 Subject: staging: wilc1000: rename u32TailLen in wilc_add_beacon This patch renames u32TailLen to tail_len to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index e35465e8fe4d..c81c74916570 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4160,7 +4160,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) } int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 head_len, u8 *head, u32 u32TailLen, u8 *pu8Tail) + u32 head_len, u8 *head, u32 tail_len, u8 *pu8Tail) { int result = 0; struct host_if_msg msg; @@ -4186,10 +4186,10 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, result = -ENOMEM; goto ERRORHANDLER; } - pstrSetBeaconParam->tail_len = u32TailLen; + pstrSetBeaconParam->tail_len = tail_len; - if (u32TailLen > 0) { - pstrSetBeaconParam->tail = kmemdup(pu8Tail, u32TailLen, + if (tail_len > 0) { + pstrSetBeaconParam->tail = kmemdup(pu8Tail, tail_len, GFP_KERNEL); if (!pstrSetBeaconParam->tail) { result = -ENOMEM; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 1c3f741ea48a..7e4ea186b4a2 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -344,7 +344,7 @@ s32 wilc_hif_set_cfg(struct wilc_vif *vif, s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); s32 wilc_deinit(struct wilc_vif *vif); int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 head_len, u8 *head, u32 u32TailLen, u8 *pu8Tail); + u32 head_len, u8 *head, u32 tail_len, u8 *pu8Tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]); -- cgit v1.2.3 From 733d10312c9796a14da7be56a10e407ad4b9a0bf Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:36:01 +0900 Subject: staging: wilc1000: rename pu8Tail in wilc_add_beacon This patch renames pu8Tail to tail to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c81c74916570..8f8c58312c85 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4160,7 +4160,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) } int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 head_len, u8 *head, u32 tail_len, u8 *pu8Tail) + u32 head_len, u8 *head, u32 tail_len, u8 *tail) { int result = 0; struct host_if_msg msg; @@ -4189,7 +4189,7 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, pstrSetBeaconParam->tail_len = tail_len; if (tail_len > 0) { - pstrSetBeaconParam->tail = kmemdup(pu8Tail, tail_len, + pstrSetBeaconParam->tail = kmemdup(tail, tail_len, GFP_KERNEL); if (!pstrSetBeaconParam->tail) { result = -ENOMEM; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 7e4ea186b4a2..b61b4845e509 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -344,7 +344,7 @@ s32 wilc_hif_set_cfg(struct wilc_vif *vif, s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); s32 wilc_deinit(struct wilc_vif *vif); int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 head_len, u8 *head, u32 tail_len, u8 *pu8Tail); + u32 head_len, u8 *head, u32 tail_len, u8 *tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]); -- cgit v1.2.3 From 75bf22c14c76c48241ca877737c59f8e049e0e60 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:36:02 +0900 Subject: staging: wilc1000: rename pstrSetBeaconParam in wilc_add_beacon This patch renames pstrSetBeaconParam to beacon_info to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 8f8c58312c85..34d56cdd16c5 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4164,7 +4164,7 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, { int result = 0; struct host_if_msg msg; - struct beacon_attr *pstrSetBeaconParam = &msg.body.beacon_info; + struct beacon_attr *beacon_info = &msg.body.beacon_info; struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv) { @@ -4178,25 +4178,24 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, msg.id = HOST_IF_MSG_ADD_BEACON; msg.vif = vif; - pstrSetBeaconParam->interval = interval; - pstrSetBeaconParam->dtim_period = dtim_period; - pstrSetBeaconParam->head_len = head_len; - pstrSetBeaconParam->head = kmemdup(head, head_len, GFP_KERNEL); - if (!pstrSetBeaconParam->head) { + beacon_info->interval = interval; + beacon_info->dtim_period = dtim_period; + beacon_info->head_len = head_len; + beacon_info->head = kmemdup(head, head_len, GFP_KERNEL); + if (!beacon_info->head) { result = -ENOMEM; goto ERRORHANDLER; } - pstrSetBeaconParam->tail_len = tail_len; + beacon_info->tail_len = tail_len; if (tail_len > 0) { - pstrSetBeaconParam->tail = kmemdup(tail, tail_len, - GFP_KERNEL); - if (!pstrSetBeaconParam->tail) { + beacon_info->tail = kmemdup(tail, tail_len, GFP_KERNEL); + if (!beacon_info->tail) { result = -ENOMEM; goto ERRORHANDLER; } } else { - pstrSetBeaconParam->tail = NULL; + beacon_info->tail = NULL; } result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); @@ -4205,9 +4204,9 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, ERRORHANDLER: if (result) { - kfree(pstrSetBeaconParam->head); + kfree(beacon_info->head); - kfree(pstrSetBeaconParam->tail); + kfree(beacon_info->tail); } return result; -- cgit v1.2.3 From 1870394394734c596ec2ef4a3a853a03e128f0e2 Mon Sep 17 00:00:00 2001 From: Hugo Camboulive Date: Mon, 4 Jan 2016 20:33:50 +0000 Subject: staging: wilc1000: add missing __user attribute This removes a Sparse warning. Signed-off-by: Hugo Camboulive Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index 27c653a0cdf9..291e6faa90e9 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -89,7 +89,7 @@ static ssize_t wilc_debug_region_read(struct file *file, char __user *userbuf, s return simple_read_from_buffer(userbuf, count, ppos, buf, res); } -static ssize_t wilc_debug_region_write(struct file *filp, const char *buf, size_t count, loff_t *ppos) +static ssize_t wilc_debug_region_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { char buffer[128] = {}; int flag; -- cgit v1.2.3 From d27afda304a502302b0baf4c21c7ba9451dbd992 Mon Sep 17 00:00:00 2001 From: Hugo Camboulive Date: Mon, 4 Jan 2016 22:02:23 +0000 Subject: staging: wilc1000: make some variables static terminated_handle is used only in host_interface.c wilc1000_spi_driver is exported by module_spi_driver() This fixes a few Sparse warnings. Signed-off-by: Hugo Camboulive Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/wilc_spi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 34d56cdd16c5..69946df84baf 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -225,7 +225,7 @@ struct join_bss_param { u8 start_time[4]; }; -struct host_if_drv *terminated_handle; +static struct host_if_drv *terminated_handle; bool wilc_optaining_ip; static u8 P2P_LISTEN_STATE; static struct task_struct *hif_thread_handler; diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index 86de50c9f7f5..b9dc91de90e8 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -153,7 +153,7 @@ static const struct of_device_id wilc1000_of_match[] = { }; MODULE_DEVICE_TABLE(of, wilc1000_of_match); -struct spi_driver wilc1000_spi_driver = { +static struct spi_driver wilc1000_spi_driver = { .driver = { .name = MODALIAS, .of_match_table = wilc1000_of_match, -- cgit v1.2.3 From 8c6492aa9065c33de127cbbcad8e84b828ce6f2e Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 13:26:30 +0900 Subject: staging: wilc1000: rename pu8ssid in struct hidden_net_info This patch renames pu8ssid to ssid that is a member of struct hidden_net_info. There is no need to use pu8 prefix to show data type so just remove it. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/host_interface.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 69946df84baf..3ec40b1425d6 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -842,7 +842,7 @@ static s32 Handle_Scan(struct wilc_vif *vif, for (i = 0; i < pstrHostIFscanAttr->hidden_network.u8ssidnum; i++) { *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen; - memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].pu8ssid, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen); + memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen); pu8Buffer += pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen; } diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index b61b4845e509..3b5740063939 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -186,7 +186,7 @@ struct rcvd_net_info { }; struct hidden_net_info { - u8 *pu8ssid; + u8 *ssid; u8 u8ssidlen; }; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index be5704bfc382..acd0c8d9b103 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -651,8 +651,8 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) for (i = 0; i < request->n_ssids; i++) { if (request->ssids[i].ssid && request->ssids[i].ssid_len != 0) { - strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL); - memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid, request->ssids[i].ssid, request->ssids[i].ssid_len); + strHiddenNetwork.pstrHiddenNetworkInfo[i].ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL); + memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].ssid, request->ssids[i].ssid, request->ssids[i].ssid_len); strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen = request->ssids[i].ssid_len; } else { PRINT_D(CFG80211_DBG, "Received one NULL SSID\n"); -- cgit v1.2.3 From a2d4969bc9029235a85f48b4540105a0dbb6666d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 13:26:31 +0900 Subject: staging: wilc1000: rename u8ssidlen in struct hidden_net_info This patch renames u8ssidlen to ssid_len that is a member of hidden_net_info. There is no need to use u8 prefix to show data type so just rename it. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 3ec40b1425d6..21e0dcf1894b 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -830,7 +830,7 @@ static s32 Handle_Scan(struct wilc_vif *vif, strWIDList[u32WidsCount].type = WID_STR; for (i = 0; i < pstrHostIFscanAttr->hidden_network.u8ssidnum; i++) - valuesize += ((pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen) + 1); + valuesize += ((pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid_len) + 1); pu8HdnNtwrksWidVal = kmalloc(valuesize + 1, GFP_KERNEL); strWIDList[u32WidsCount].val = pu8HdnNtwrksWidVal; if (strWIDList[u32WidsCount].val) { @@ -841,9 +841,9 @@ static s32 Handle_Scan(struct wilc_vif *vif, PRINT_D(HOSTINF_DBG, "In Handle_ProbeRequest number of ssid %d\n", pstrHostIFscanAttr->hidden_network.u8ssidnum); for (i = 0; i < pstrHostIFscanAttr->hidden_network.u8ssidnum; i++) { - *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen; - memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen); - pu8Buffer += pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen; + *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid_len; + memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid_len); + pu8Buffer += pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid_len; } strWIDList[u32WidsCount].size = (s32)(valuesize + 1); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 3b5740063939..42ab2ad97026 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -187,7 +187,7 @@ struct rcvd_net_info { struct hidden_net_info { u8 *ssid; - u8 u8ssidlen; + u8 ssid_len; }; struct hidden_network { diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index acd0c8d9b103..56d736cd0714 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -653,7 +653,7 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) request->ssids[i].ssid_len != 0) { strHiddenNetwork.pstrHiddenNetworkInfo[i].ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL); memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].ssid, request->ssids[i].ssid, request->ssids[i].ssid_len); - strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen = request->ssids[i].ssid_len; + strHiddenNetwork.pstrHiddenNetworkInfo[i].ssid_len = request->ssids[i].ssid_len; } else { PRINT_D(CFG80211_DBG, "Received one NULL SSID\n"); strHiddenNetwork.u8ssidnum -= 1; -- cgit v1.2.3 From 245a18654ffeb2e682200d0a0204b563762935be Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 13:26:32 +0900 Subject: staging: wilc1000: rename pstrHiddenNetworkInfo in struct hidden_network This patch renames pstrHiddenNetworkInfo to net_info to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 14 +++++++------- drivers/staging/wilc1000/host_interface.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 21e0dcf1894b..437cb41e8e44 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -830,7 +830,7 @@ static s32 Handle_Scan(struct wilc_vif *vif, strWIDList[u32WidsCount].type = WID_STR; for (i = 0; i < pstrHostIFscanAttr->hidden_network.u8ssidnum; i++) - valuesize += ((pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid_len) + 1); + valuesize += ((pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len) + 1); pu8HdnNtwrksWidVal = kmalloc(valuesize + 1, GFP_KERNEL); strWIDList[u32WidsCount].val = pu8HdnNtwrksWidVal; if (strWIDList[u32WidsCount].val) { @@ -841,9 +841,9 @@ static s32 Handle_Scan(struct wilc_vif *vif, PRINT_D(HOSTINF_DBG, "In Handle_ProbeRequest number of ssid %d\n", pstrHostIFscanAttr->hidden_network.u8ssidnum); for (i = 0; i < pstrHostIFscanAttr->hidden_network.u8ssidnum; i++) { - *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid_len; - memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid_len); - pu8Buffer += pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid_len; + *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len; + memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.net_info[i].ssid, pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len); + pu8Buffer += pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len; } strWIDList[u32WidsCount].size = (s32)(valuesize + 1); @@ -912,8 +912,8 @@ ERRORHANDLER: kfree(pstrHostIFscanAttr->ies); pstrHostIFscanAttr->ies = NULL; - kfree(pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo); - pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo = NULL; + kfree(pstrHostIFscanAttr->hidden_network.net_info); + pstrHostIFscanAttr->hidden_network.net_info = NULL; kfree(pu8HdnNtwrksWidVal); @@ -3691,7 +3691,7 @@ s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, msg.id = HOST_IF_MSG_SCAN; if (pstrHiddenNetwork) { - msg.body.scan_info.hidden_network.pstrHiddenNetworkInfo = pstrHiddenNetwork->pstrHiddenNetworkInfo; + msg.body.scan_info.hidden_network.net_info = pstrHiddenNetwork->net_info; msg.body.scan_info.hidden_network.u8ssidnum = pstrHiddenNetwork->u8ssidnum; } else diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 42ab2ad97026..a0345e924963 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -191,7 +191,7 @@ struct hidden_net_info { }; struct hidden_network { - struct hidden_net_info *pstrHiddenNetworkInfo; + struct hidden_net_info *net_info; u8 u8ssidnum; }; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 56d736cd0714..f0dd38d23a1b 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -644,16 +644,16 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) PRINT_D(CFG80211_DBG, "Number of SSIDs %d\n", request->n_ssids); if (request->n_ssids >= 1) { - strHiddenNetwork.pstrHiddenNetworkInfo = kmalloc(request->n_ssids * sizeof(struct hidden_network), GFP_KERNEL); + strHiddenNetwork.net_info = kmalloc(request->n_ssids * sizeof(struct hidden_network), GFP_KERNEL); strHiddenNetwork.u8ssidnum = request->n_ssids; for (i = 0; i < request->n_ssids; i++) { if (request->ssids[i].ssid && request->ssids[i].ssid_len != 0) { - strHiddenNetwork.pstrHiddenNetworkInfo[i].ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL); - memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].ssid, request->ssids[i].ssid, request->ssids[i].ssid_len); - strHiddenNetwork.pstrHiddenNetworkInfo[i].ssid_len = request->ssids[i].ssid_len; + strHiddenNetwork.net_info[i].ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL); + memcpy(strHiddenNetwork.net_info[i].ssid, request->ssids[i].ssid, request->ssids[i].ssid_len); + strHiddenNetwork.net_info[i].ssid_len = request->ssids[i].ssid_len; } else { PRINT_D(CFG80211_DBG, "Received one NULL SSID\n"); strHiddenNetwork.u8ssidnum -= 1; -- cgit v1.2.3 From 40e05e86d5fcb3d652c49a2b0ad93573a7dca2b4 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 13:26:33 +0900 Subject: staging: wilc1000: rename u8ssidnum in struct hidden_network This patch renames u8ssidnum to n_ssids that is a member of struct hidden_network. There is no need to use u8 prefix to show data type so just rename it. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 10 +++++----- drivers/staging/wilc1000/host_interface.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 437cb41e8e44..b0de6e444a33 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -829,18 +829,18 @@ static s32 Handle_Scan(struct wilc_vif *vif, strWIDList[u32WidsCount].id = (u16)WID_SSID_PROBE_REQ; strWIDList[u32WidsCount].type = WID_STR; - for (i = 0; i < pstrHostIFscanAttr->hidden_network.u8ssidnum; i++) + for (i = 0; i < pstrHostIFscanAttr->hidden_network.n_ssids; i++) valuesize += ((pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len) + 1); pu8HdnNtwrksWidVal = kmalloc(valuesize + 1, GFP_KERNEL); strWIDList[u32WidsCount].val = pu8HdnNtwrksWidVal; if (strWIDList[u32WidsCount].val) { pu8Buffer = strWIDList[u32WidsCount].val; - *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.u8ssidnum; + *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.n_ssids; - PRINT_D(HOSTINF_DBG, "In Handle_ProbeRequest number of ssid %d\n", pstrHostIFscanAttr->hidden_network.u8ssidnum); + PRINT_D(HOSTINF_DBG, "In Handle_ProbeRequest number of ssid %d\n", pstrHostIFscanAttr->hidden_network.n_ssids); - for (i = 0; i < pstrHostIFscanAttr->hidden_network.u8ssidnum; i++) { + for (i = 0; i < pstrHostIFscanAttr->hidden_network.n_ssids; i++) { *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len; memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.net_info[i].ssid, pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len); pu8Buffer += pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len; @@ -3692,7 +3692,7 @@ s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, if (pstrHiddenNetwork) { msg.body.scan_info.hidden_network.net_info = pstrHiddenNetwork->net_info; - msg.body.scan_info.hidden_network.u8ssidnum = pstrHiddenNetwork->u8ssidnum; + msg.body.scan_info.hidden_network.n_ssids = pstrHiddenNetwork->n_ssids; } else PRINT_D(HOSTINF_DBG, "pstrHiddenNetwork IS EQUAL TO NULL\n"); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index a0345e924963..9cb08544fa35 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -192,7 +192,7 @@ struct hidden_net_info { struct hidden_network { struct hidden_net_info *net_info; - u8 u8ssidnum; + u8 n_ssids; }; struct user_scan_req { diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index f0dd38d23a1b..792fdff4bca9 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -645,7 +645,7 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) if (request->n_ssids >= 1) { strHiddenNetwork.net_info = kmalloc(request->n_ssids * sizeof(struct hidden_network), GFP_KERNEL); - strHiddenNetwork.u8ssidnum = request->n_ssids; + strHiddenNetwork.n_ssids = request->n_ssids; for (i = 0; i < request->n_ssids; i++) { @@ -656,7 +656,7 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) strHiddenNetwork.net_info[i].ssid_len = request->ssids[i].ssid_len; } else { PRINT_D(CFG80211_DBG, "Received one NULL SSID\n"); - strHiddenNetwork.u8ssidnum -= 1; + strHiddenNetwork.n_ssids -= 1; } } PRINT_D(CFG80211_DBG, "Trigger Scan Request\n"); -- cgit v1.2.3 From 03a5d8c0854c02a3c54ee09d9b784e82f0c1c9aa Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:45 +0900 Subject: staging: wilc1000: fix return type of wilc_scan This patch changes return type of wilc_scan from s32 to int. The result variable gets return value from wilc_mq_send that has data type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index b0de6e444a33..c8a07cdb9141 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3672,12 +3672,12 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) return result; } -s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, +int wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 9cb08544fa35..2bf4ef0cda93 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -335,7 +335,7 @@ int wilc_flush_join_req(struct wilc_vif *vif); int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); -s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, +int wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork); -- cgit v1.2.3 From 3c2be65f28b9664e9f62c4dd4a9022b602174b29 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:46 +0900 Subject: staging: wilc1000: rename u8ScanSource in wilc_scan This patch renames u8ScanSource to scan_source to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c8a07cdb9141..ac00b17c6d3b 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3672,7 +3672,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) return result; } -int wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, +int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 u8ScanType, u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork) @@ -3698,7 +3698,7 @@ int wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, PRINT_D(HOSTINF_DBG, "pstrHiddenNetwork IS EQUAL TO NULL\n"); msg.vif = vif; - msg.body.scan_info.src = u8ScanSource; + msg.body.scan_info.src = scan_source; msg.body.scan_info.type = u8ScanType; msg.body.scan_info.result = ScanResult; msg.body.scan_info.arg = pvUserArg; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 2bf4ef0cda93..6ef594be0107 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -335,7 +335,7 @@ int wilc_flush_join_req(struct wilc_vif *vif); int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); -int wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, +int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 u8ScanType, u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork); -- cgit v1.2.3 From c0734df9b3d51e190290a5674bebb9f888716f7c Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:47 +0900 Subject: staging: wilc1000: rename u8ScanType in wilc_scan This patch renames u8ScanType to scan_type to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index ac00b17c6d3b..6d96323f8589 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3672,7 +3672,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) return result; } -int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 u8ScanType, +int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork) @@ -3699,7 +3699,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 u8ScanType, msg.vif = vif; msg.body.scan_info.src = scan_source; - msg.body.scan_info.type = u8ScanType; + msg.body.scan_info.type = scan_type; msg.body.scan_info.result = ScanResult; msg.body.scan_info.arg = pvUserArg; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 6ef594be0107..0d7ed5549272 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -335,7 +335,7 @@ int wilc_flush_join_req(struct wilc_vif *vif); int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); -int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 u8ScanType, +int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork); -- cgit v1.2.3 From 5eb037e6d30aa59adbf72367ec76045a73d7a4e4 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:48 +0900 Subject: staging: wilc1000: rename pu8ChnlFreqList in wilc_scan This patch renames pu8ChnlFreqList to ch_freq_list to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 6d96323f8589..fcbfee609b70 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3673,7 +3673,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) } int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, - u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, + u8 *ch_freq_list, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork) { @@ -3705,7 +3705,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.body.scan_info.ch_list_len = u8ChnlListLen; msg.body.scan_info.ch_freq_list = kmalloc(u8ChnlListLen, GFP_KERNEL); - memcpy(msg.body.scan_info.ch_freq_list, pu8ChnlFreqList, u8ChnlListLen); + memcpy(msg.body.scan_info.ch_freq_list, ch_freq_list, u8ChnlListLen); msg.body.scan_info.ies_len = IEsLen; msg.body.scan_info.ies = kmalloc(IEsLen, GFP_KERNEL); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 0d7ed5549272..863332e741d1 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -336,7 +336,7 @@ int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, - u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, + u8 *ch_freq_list, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork); s32 wilc_hif_set_cfg(struct wilc_vif *vif, -- cgit v1.2.3 From 86163ec9902c3fffff5b047bcbb8e5d0de69f624 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:49 +0900 Subject: staging: wilc1000: rename u8ChnlListLen in wilc_scan This patch renames u8ChnlListLen to ch_list_len to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index fcbfee609b70..99455909c489 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3673,7 +3673,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) } int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, - u8 *ch_freq_list, u8 u8ChnlListLen, const u8 *pu8IEs, + u8 *ch_freq_list, u8 ch_list_len, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork) { @@ -3703,9 +3703,9 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.body.scan_info.result = ScanResult; msg.body.scan_info.arg = pvUserArg; - msg.body.scan_info.ch_list_len = u8ChnlListLen; - msg.body.scan_info.ch_freq_list = kmalloc(u8ChnlListLen, GFP_KERNEL); - memcpy(msg.body.scan_info.ch_freq_list, ch_freq_list, u8ChnlListLen); + msg.body.scan_info.ch_list_len = ch_list_len; + msg.body.scan_info.ch_freq_list = kmalloc(ch_list_len, GFP_KERNEL); + memcpy(msg.body.scan_info.ch_freq_list, ch_freq_list, ch_list_len); msg.body.scan_info.ies_len = IEsLen; msg.body.scan_info.ies = kmalloc(IEsLen, GFP_KERNEL); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 863332e741d1..c56c3f658a7b 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -336,7 +336,7 @@ int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, - u8 *ch_freq_list, u8 u8ChnlListLen, const u8 *pu8IEs, + u8 *ch_freq_list, u8 ch_list_len, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork); s32 wilc_hif_set_cfg(struct wilc_vif *vif, -- cgit v1.2.3 From ce2d023ff5533bca864735229aea8a5538e48584 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:50 +0900 Subject: staging: wilc1000: rename pu8IEs in wilc_scan This patch renames pu8IEs to ies to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 99455909c489..6cd831069841 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3673,7 +3673,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) } int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, - u8 *ch_freq_list, u8 ch_list_len, const u8 *pu8IEs, + u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork) { @@ -3709,7 +3709,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.body.scan_info.ies_len = IEsLen; msg.body.scan_info.ies = kmalloc(IEsLen, GFP_KERNEL); - memcpy(msg.body.scan_info.ies, pu8IEs, IEsLen); + memcpy(msg.body.scan_info.ies, ies, IEsLen); result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index c56c3f658a7b..5356492848c7 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -336,7 +336,7 @@ int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, - u8 *ch_freq_list, u8 ch_list_len, const u8 *pu8IEs, + u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork); s32 wilc_hif_set_cfg(struct wilc_vif *vif, -- cgit v1.2.3 From 6ca31901d9db58ba68552ef7eec8a7125ad3f4f7 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:51 +0900 Subject: staging: wilc1000: rename IEsLen in wilc_scan This patch renames IEsLen to ies_len to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 6cd831069841..a3c13cb12b2f 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3674,7 +3674,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, - size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, + size_t ies_len, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork) { int result = 0; @@ -3707,9 +3707,9 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.body.scan_info.ch_freq_list = kmalloc(ch_list_len, GFP_KERNEL); memcpy(msg.body.scan_info.ch_freq_list, ch_freq_list, ch_list_len); - msg.body.scan_info.ies_len = IEsLen; - msg.body.scan_info.ies = kmalloc(IEsLen, GFP_KERNEL); - memcpy(msg.body.scan_info.ies, ies, IEsLen); + msg.body.scan_info.ies_len = ies_len; + msg.body.scan_info.ies = kmalloc(ies_len, GFP_KERNEL); + memcpy(msg.body.scan_info.ies, ies, ies_len); result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 5356492848c7..a782b9e54a6f 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -337,7 +337,7 @@ int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, - size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, + size_t ies_len, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork); s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); -- cgit v1.2.3 From c8fb0bf931decb8a78a51e275609c4573b4f728d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:52 +0900 Subject: staging: wilc1000: rename ScanResult in wilc_scan This patch renames ScanResult to scan_result to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index a3c13cb12b2f..e475c775061e 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3674,15 +3674,15 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, - size_t ies_len, wilc_scan_result ScanResult, void *pvUserArg, + size_t ies_len, wilc_scan_result scan_result, void *pvUserArg, struct hidden_network *pstrHiddenNetwork) { int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; - if (!hif_drv || !ScanResult) { - PRINT_ER("hif_drv or ScanResult = NULL\n"); + if (!hif_drv || !scan_result) { + PRINT_ER("hif_drv or scan_result = NULL\n"); return -EFAULT; } @@ -3700,7 +3700,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.vif = vif; msg.body.scan_info.src = scan_source; msg.body.scan_info.type = scan_type; - msg.body.scan_info.result = ScanResult; + msg.body.scan_info.result = scan_result; msg.body.scan_info.arg = pvUserArg; msg.body.scan_info.ch_list_len = ch_list_len; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index a782b9e54a6f..aaaa5f7b729e 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -337,7 +337,7 @@ int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, - size_t ies_len, wilc_scan_result ScanResult, void *pvUserArg, + size_t ies_len, wilc_scan_result scan_result, void *pvUserArg, struct hidden_network *pstrHiddenNetwork); s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); -- cgit v1.2.3 From 2c97f2d4ed34f77481836d4511fa9fbb072c258e Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:53 +0900 Subject: staging: wilc1000: rename pvUserArg in wilc_scan This patch renames pvUserArg to user_arg to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index e475c775061e..56b58d3dd292 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3674,7 +3674,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, - size_t ies_len, wilc_scan_result scan_result, void *pvUserArg, + size_t ies_len, wilc_scan_result scan_result, void *user_arg, struct hidden_network *pstrHiddenNetwork) { int result = 0; @@ -3701,7 +3701,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.body.scan_info.src = scan_source; msg.body.scan_info.type = scan_type; msg.body.scan_info.result = scan_result; - msg.body.scan_info.arg = pvUserArg; + msg.body.scan_info.arg = user_arg; msg.body.scan_info.ch_list_len = ch_list_len; msg.body.scan_info.ch_freq_list = kmalloc(ch_list_len, GFP_KERNEL); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index aaaa5f7b729e..1923a3093751 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -337,7 +337,7 @@ int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, - size_t ies_len, wilc_scan_result scan_result, void *pvUserArg, + size_t ies_len, wilc_scan_result scan_result, void *user_arg, struct hidden_network *pstrHiddenNetwork); s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); -- cgit v1.2.3 From d317818bf4c1238c21efbe407e24727b50f324a1 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:54 +0900 Subject: staging: wilc1000: rename pstrHiddenNetwork in wilc_scan This patch renames pstrHiddenNetwork to hidden_network to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 10 +++++----- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 56b58d3dd292..07fe5c84ce1c 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3675,7 +3675,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t ies_len, wilc_scan_result scan_result, void *user_arg, - struct hidden_network *pstrHiddenNetwork) + struct hidden_network *hidden_network) { int result = 0; struct host_if_msg msg; @@ -3690,12 +3690,12 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.id = HOST_IF_MSG_SCAN; - if (pstrHiddenNetwork) { - msg.body.scan_info.hidden_network.net_info = pstrHiddenNetwork->net_info; - msg.body.scan_info.hidden_network.n_ssids = pstrHiddenNetwork->n_ssids; + if (hidden_network) { + msg.body.scan_info.hidden_network.net_info = hidden_network->net_info; + msg.body.scan_info.hidden_network.n_ssids = hidden_network->n_ssids; } else - PRINT_D(HOSTINF_DBG, "pstrHiddenNetwork IS EQUAL TO NULL\n"); + PRINT_D(HOSTINF_DBG, "hidden_network IS EQUAL TO NULL\n"); msg.vif = vif; msg.body.scan_info.src = scan_source; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 1923a3093751..f8969774a23c 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -338,7 +338,7 @@ int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t ies_len, wilc_scan_result scan_result, void *user_arg, - struct hidden_network *pstrHiddenNetwork); + struct hidden_network *hidden_network); s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); -- cgit v1.2.3 From 1a271d996097367da1f35cf257da11f472fd39d2 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:55 +0900 Subject: staging: wilc1000: use kmemdup instead of kmalloc/memcpy This patch replaces kmalloc followed by memcpy with kmemdup. It is also added error checking to return -ENOMEM when kmemdup is failed. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 07fe5c84ce1c..3de0fad2fa1c 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3704,12 +3704,16 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.body.scan_info.arg = user_arg; msg.body.scan_info.ch_list_len = ch_list_len; - msg.body.scan_info.ch_freq_list = kmalloc(ch_list_len, GFP_KERNEL); - memcpy(msg.body.scan_info.ch_freq_list, ch_freq_list, ch_list_len); + msg.body.scan_info.ch_freq_list = kmemdup(ch_freq_list, + ch_list_len, + GFP_KERNEL); + if (!msg.body.scan_info.ch_freq_list) + return -ENOMEM; msg.body.scan_info.ies_len = ies_len; - msg.body.scan_info.ies = kmalloc(ies_len, GFP_KERNEL); - memcpy(msg.body.scan_info.ies, ies, ies_len); + msg.body.scan_info.ies = kmemdup(ies, ies_len, GFP_KERNEL); + if (!msg.body.scan_info.ies) + return -ENOMEM; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) { -- cgit v1.2.3 From 3bff53a880b94df68e95b64b49929578af1b007a Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:56 +0900 Subject: staging: wilc1000: rename phWFIDrv in wilc_init declaration The second argument name is different between wilc_init declaration and definition. This patch renames phWFIDrv to hif_drv_handler to match argument name. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index f8969774a23c..b1ebd4d9df34 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -341,7 +341,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, struct hidden_network *hidden_network); s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); -s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); +s32 wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler); s32 wilc_deinit(struct wilc_vif *vif); int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, u32 head_len, u8 *head, u32 tail_len, u8 *tail); -- cgit v1.2.3 From 1e995c10791f83f606b94b73c0f89ac29aea4824 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:57 +0900 Subject: staging: wilc1000: fix return type of wilc_init This patch changes return type of wilc_init from s32 to int. The error code as -ENOMEM or -EFAULT is returned in the wilc_init. It is better to use return type of int in this function, not s32. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 3de0fad2fa1c..5801d41ef988 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3779,9 +3779,9 @@ static void GetPeriodicRSSI(unsigned long arg) mod_timer(&periodic_rssi, jiffies + msecs_to_jiffies(5000)); } -s32 wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) +int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) { - s32 result = 0; + int result = 0; struct host_if_drv *hif_drv; struct wilc_vif *vif; struct wilc *wilc; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index b1ebd4d9df34..4c02e6bbed41 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -341,7 +341,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, struct hidden_network *hidden_network); s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); -s32 wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler); +int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler); s32 wilc_deinit(struct wilc_vif *vif); int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, u32 head_len, u8 *head, u32 tail_len, u8 *tail); -- cgit v1.2.3 From ce7b516f3f9e11fe4ee06fad0d7e853bb6e8f160 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 13 Jan 2016 15:36:17 +0100 Subject: staging: wilc1000: remove extraneous variable Building wilc1000 with clang currently fails in the staging-next branch: drivers/staging/wilc1000/wilc_spi.c:123:34: warning: tentative definition of variable with internal linkage has incomplete non-array type 'const struct wilc1000_ops' [-Wtentative-definition-incomplete-type] static const struct wilc1000_ops wilc1000_spi_ops; The reason is that wilc1000_ops was left behind after a recent cleanup, and is completely unused and also uninitialized and const and has an incomplete type. Removing the variable is obviously correct, and gets rid of the warning. No idea why gcc does not complain about it though. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_spi.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index b9dc91de90e8..1df07e7bea59 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -120,8 +120,6 @@ static u8 crc7(u8 crc, const u8 *buffer, u32 len) #define USE_SPI_DMA 0 -static const struct wilc1000_ops wilc1000_spi_ops; - static int wilc_bus_probe(struct spi_device *spi) { int ret, gpio; -- cgit v1.2.3 From eec826439dbe1ad253bb7c4d54ed8777773ec630 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 20 Jan 2016 16:44:57 +0900 Subject: staging: wilc1000: remove redundant check in wilc_mq_recv At the beginning of wilc_mq_recv, it is checked if pHandle->bExiting is false or true. There is no need to check it again at the middle of this function. So just remove it. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 098390cdf319..abc780c7686c 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -133,12 +133,6 @@ int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); down(&pHandle->hSem); - - if (pHandle->bExiting) { - PRINT_ER("pHandle fail\n"); - return -EFAULT; - } - spin_lock_irqsave(&pHandle->strCriticalSection, flags); pstrMessage = pHandle->pstrMessageList; -- cgit v1.2.3 From d16791bfd52b628eb5759085f1a708c1843d10ef Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:31 +0900 Subject: staging: wilc1000: rename struct __Message_struct This patch renames typedef from struct __Message_struct and renames it to struct message. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 10 +++++----- drivers/staging/wilc1000/wilc_msgqueue.h | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index abc780c7686c..9b78fcd1291f 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -38,7 +38,7 @@ int wilc_mq_destroy(WILC_MsgQueueHandle *pHandle) } while (pHandle->pstrMessageList) { - Message *pstrMessge = pHandle->pstrMessageList->pstrNext; + struct message *pstrMessge = pHandle->pstrMessageList->pstrNext; kfree(pHandle->pstrMessageList); pHandle->pstrMessageList = pstrMessge; @@ -57,7 +57,7 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, const void *pvSendBuffer, u32 u32SendBufferSize) { unsigned long flags; - Message *pstrMessage = NULL; + struct message *pstrMessage = NULL; if ((!pHandle) || (u32SendBufferSize == 0) || (!pvSendBuffer)) { PRINT_ER("pHandle or pvSendBuffer is null\n"); @@ -70,7 +70,7 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, } /* construct a new message */ - pstrMessage = kmalloc(sizeof(Message), GFP_ATOMIC); + pstrMessage = kmalloc(sizeof(struct message), GFP_ATOMIC); if (!pstrMessage) return -ENOMEM; @@ -89,7 +89,7 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, if (!pHandle->pstrMessageList) { pHandle->pstrMessageList = pstrMessage; } else { - Message *pstrTailMsg = pHandle->pstrMessageList; + struct message *pstrTailMsg = pHandle->pstrMessageList; while (pstrTailMsg->pstrNext) pstrTailMsg = pstrTailMsg->pstrNext; @@ -114,7 +114,7 @@ int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, void *pvRecvBuffer, u32 u32RecvBufferSize, u32 *pu32ReceivedLength) { - Message *pstrMessage; + struct message *pstrMessage; unsigned long flags; if ((!pHandle) || (u32RecvBufferSize == 0) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index d7e0328bacee..1a7c652df119 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -13,18 +13,18 @@ #include /* Message Queue type is a structure */ -typedef struct __Message_struct { +struct message { void *pvBuffer; u32 u32Length; - struct __Message_struct *pstrNext; -} Message; + struct message *pstrNext; +}; typedef struct __MessageQueue_struct { struct semaphore hSem; spinlock_t strCriticalSection; bool bExiting; u32 u32ReceiversCount; - Message *pstrMessageList; + struct message *pstrMessageList; } WILC_MsgQueueHandle; /*! -- cgit v1.2.3 From 78d50f94f017b6e6becda2dce42462e473b23252 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:32 +0900 Subject: staging: wilc1000: rename pvBuffer in struct message This patch renames pvBuffer to buf to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 10 +++++----- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 9b78fcd1291f..a4e612d51c67 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -76,9 +76,9 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, pstrMessage->u32Length = u32SendBufferSize; pstrMessage->pstrNext = NULL; - pstrMessage->pvBuffer = kmemdup(pvSendBuffer, u32SendBufferSize, - GFP_ATOMIC); - if (!pstrMessage->pvBuffer) { + pstrMessage->buf = kmemdup(pvSendBuffer, u32SendBufferSize, + GFP_ATOMIC); + if (!pstrMessage->buf) { kfree(pstrMessage); return -ENOMEM; } @@ -151,12 +151,12 @@ int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, /* consume the message */ pHandle->u32ReceiversCount--; - memcpy(pvRecvBuffer, pstrMessage->pvBuffer, pstrMessage->u32Length); + memcpy(pvRecvBuffer, pstrMessage->buf, pstrMessage->u32Length); *pu32ReceivedLength = pstrMessage->u32Length; pHandle->pstrMessageList = pstrMessage->pstrNext; - kfree(pstrMessage->pvBuffer); + kfree(pstrMessage->buf); kfree(pstrMessage); spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 1a7c652df119..848ed827a4b4 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -14,7 +14,7 @@ /* Message Queue type is a structure */ struct message { - void *pvBuffer; + void *buf; u32 u32Length; struct message *pstrNext; }; -- cgit v1.2.3 From d3ff0580b9a7526f4292e2eca3a0f720d1c0f01b Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:33 +0900 Subject: staging: wilc1000: rename u32Length in struct message This patch renames u32Length to len to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 8 ++++---- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index a4e612d51c67..0e66a649f638 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -74,7 +74,7 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, if (!pstrMessage) return -ENOMEM; - pstrMessage->u32Length = u32SendBufferSize; + pstrMessage->len = u32SendBufferSize; pstrMessage->pstrNext = NULL; pstrMessage->buf = kmemdup(pvSendBuffer, u32SendBufferSize, GFP_ATOMIC); @@ -142,7 +142,7 @@ int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, return -EFAULT; } /* check buffer size */ - if (u32RecvBufferSize < pstrMessage->u32Length) { + if (u32RecvBufferSize < pstrMessage->len) { spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); up(&pHandle->hSem); PRINT_ER("u32RecvBufferSize overflow\n"); @@ -151,8 +151,8 @@ int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, /* consume the message */ pHandle->u32ReceiversCount--; - memcpy(pvRecvBuffer, pstrMessage->buf, pstrMessage->u32Length); - *pu32ReceivedLength = pstrMessage->u32Length; + memcpy(pvRecvBuffer, pstrMessage->buf, pstrMessage->len); + *pu32ReceivedLength = pstrMessage->len; pHandle->pstrMessageList = pstrMessage->pstrNext; diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 848ed827a4b4..b0ccd1de3765 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -15,7 +15,7 @@ /* Message Queue type is a structure */ struct message { void *buf; - u32 u32Length; + u32 len; struct message *pstrNext; }; -- cgit v1.2.3 From 3356116124d8e868d5173afcfc86854994605e44 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:34 +0900 Subject: staging: wilc1000: rename pstrNext in struct message This patch renames pstrNext to next to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 12 ++++++------ drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 0e66a649f638..4d79a315662d 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -38,7 +38,7 @@ int wilc_mq_destroy(WILC_MsgQueueHandle *pHandle) } while (pHandle->pstrMessageList) { - struct message *pstrMessge = pHandle->pstrMessageList->pstrNext; + struct message *pstrMessge = pHandle->pstrMessageList->next; kfree(pHandle->pstrMessageList); pHandle->pstrMessageList = pstrMessge; @@ -75,7 +75,7 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, return -ENOMEM; pstrMessage->len = u32SendBufferSize; - pstrMessage->pstrNext = NULL; + pstrMessage->next = NULL; pstrMessage->buf = kmemdup(pvSendBuffer, u32SendBufferSize, GFP_ATOMIC); if (!pstrMessage->buf) { @@ -91,10 +91,10 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, } else { struct message *pstrTailMsg = pHandle->pstrMessageList; - while (pstrTailMsg->pstrNext) - pstrTailMsg = pstrTailMsg->pstrNext; + while (pstrTailMsg->next) + pstrTailMsg = pstrTailMsg->next; - pstrTailMsg->pstrNext = pstrMessage; + pstrTailMsg->next = pstrMessage; } spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); @@ -154,7 +154,7 @@ int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, memcpy(pvRecvBuffer, pstrMessage->buf, pstrMessage->len); *pu32ReceivedLength = pstrMessage->len; - pHandle->pstrMessageList = pstrMessage->pstrNext; + pHandle->pstrMessageList = pstrMessage->next; kfree(pstrMessage->buf); kfree(pstrMessage); diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index b0ccd1de3765..ec503c356ee3 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -16,7 +16,7 @@ struct message { void *buf; u32 len; - struct message *pstrNext; + struct message *next; }; typedef struct __MessageQueue_struct { -- cgit v1.2.3 From 5ba89554047425734caf59f4b744fc7c79c7b055 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:35 +0900 Subject: staging: wilc1000: rename struct WILC_MsgQueueHandle This patch removes typedef from struct WILC_MsgQueueHandle and renames it to struct message_queue. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/wilc_msgqueue.c | 14 +++++++------- drivers/staging/wilc1000/wilc_msgqueue.h | 18 +++++++++--------- 3 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 5801d41ef988..79e8b7aa482b 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -229,7 +229,7 @@ static struct host_if_drv *terminated_handle; bool wilc_optaining_ip; static u8 P2P_LISTEN_STATE; static struct task_struct *hif_thread_handler; -static WILC_MsgQueueHandle hif_msg_q; +static struct message_queue hif_msg_q; static struct semaphore hif_sema_thread; static struct semaphore hif_sema_driver; static struct semaphore hif_sema_wait_response; diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 4d79a315662d..907bae19f494 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -11,7 +11,7 @@ * @note copied from FLO glue implementatuion * @version 1.0 */ -int wilc_mq_create(WILC_MsgQueueHandle *pHandle) +int wilc_mq_create(struct message_queue *pHandle) { spin_lock_init(&pHandle->strCriticalSection); sema_init(&pHandle->hSem, 0); @@ -27,7 +27,7 @@ int wilc_mq_create(WILC_MsgQueueHandle *pHandle) * @note copied from FLO glue implementatuion * @version 1.0 */ -int wilc_mq_destroy(WILC_MsgQueueHandle *pHandle) +int wilc_mq_destroy(struct message_queue *pHandle) { pHandle->bExiting = true; @@ -53,8 +53,8 @@ int wilc_mq_destroy(WILC_MsgQueueHandle *pHandle) * @note copied from FLO glue implementatuion * @version 1.0 */ -int wilc_mq_send(WILC_MsgQueueHandle *pHandle, - const void *pvSendBuffer, u32 u32SendBufferSize) +int wilc_mq_send(struct message_queue *pHandle, + const void *pvSendBuffer, u32 u32SendBufferSize) { unsigned long flags; struct message *pstrMessage = NULL; @@ -110,9 +110,9 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, * @note copied from FLO glue implementatuion * @version 1.0 */ -int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, - void *pvRecvBuffer, u32 u32RecvBufferSize, - u32 *pu32ReceivedLength) +int wilc_mq_recv(struct message_queue *pHandle, + void *pvRecvBuffer, u32 u32RecvBufferSize, + u32 *pu32ReceivedLength) { struct message *pstrMessage; unsigned long flags; diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index ec503c356ee3..111be463d335 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -19,13 +19,13 @@ struct message { struct message *next; }; -typedef struct __MessageQueue_struct { +struct message_queue { struct semaphore hSem; spinlock_t strCriticalSection; bool bExiting; u32 u32ReceiversCount; struct message *pstrMessageList; -} WILC_MsgQueueHandle; +}; /*! * @brief Creates a new Message queue @@ -40,7 +40,7 @@ typedef struct __MessageQueue_struct { * @date 30 Aug 2010 * @version 1.0 */ -int wilc_mq_create(WILC_MsgQueueHandle *pHandle); +int wilc_mq_create(struct message_queue *pHandle); /*! * @brief Sends a message @@ -57,8 +57,8 @@ int wilc_mq_create(WILC_MsgQueueHandle *pHandle); * @date 30 Aug 2010 * @version 1.0 */ -int wilc_mq_send(WILC_MsgQueueHandle *pHandle, - const void *pvSendBuffer, u32 u32SendBufferSize); +int wilc_mq_send(struct message_queue *pHandle, + const void *pvSendBuffer, u32 u32SendBufferSize); /*! * @brief Receives a message @@ -76,9 +76,9 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, * @date 30 Aug 2010 * @version 1.0 */ -int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, - void *pvRecvBuffer, u32 u32RecvBufferSize, - u32 *pu32ReceivedLength); +int wilc_mq_recv(struct message_queue *pHandle, + void *pvRecvBuffer, u32 u32RecvBufferSize, + u32 *pu32ReceivedLength); /*! * @brief Destroys an existing Message queue @@ -89,6 +89,6 @@ int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, * @date 30 Aug 2010 * @version 1.0 */ -int wilc_mq_destroy(WILC_MsgQueueHandle *pHandle); +int wilc_mq_destroy(struct message_queue *pHandle); #endif -- cgit v1.2.3 From 9b849fd9ade195e4ca4b376f90184660e304dc51 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:36 +0900 Subject: staging: wilc1000: rename hSem in struct message_queue This patch renames hSem to sem to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 10 +++++----- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 907bae19f494..b996c47af15d 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -14,7 +14,7 @@ int wilc_mq_create(struct message_queue *pHandle) { spin_lock_init(&pHandle->strCriticalSection); - sema_init(&pHandle->hSem, 0); + sema_init(&pHandle->sem, 0); pHandle->pstrMessageList = NULL; pHandle->u32ReceiversCount = 0; pHandle->bExiting = false; @@ -33,7 +33,7 @@ int wilc_mq_destroy(struct message_queue *pHandle) /* Release any waiting receiver thread. */ while (pHandle->u32ReceiversCount > 0) { - up(&pHandle->hSem); + up(&pHandle->sem); pHandle->u32ReceiversCount--; } @@ -99,7 +99,7 @@ int wilc_mq_send(struct message_queue *pHandle, spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); - up(&pHandle->hSem); + up(&pHandle->sem); return 0; } @@ -132,7 +132,7 @@ int wilc_mq_recv(struct message_queue *pHandle, pHandle->u32ReceiversCount++; spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); - down(&pHandle->hSem); + down(&pHandle->sem); spin_lock_irqsave(&pHandle->strCriticalSection, flags); pstrMessage = pHandle->pstrMessageList; @@ -144,7 +144,7 @@ int wilc_mq_recv(struct message_queue *pHandle, /* check buffer size */ if (u32RecvBufferSize < pstrMessage->len) { spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); - up(&pHandle->hSem); + up(&pHandle->sem); PRINT_ER("u32RecvBufferSize overflow\n"); return -EOVERFLOW; } diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 111be463d335..3ea40682cdf0 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -20,7 +20,7 @@ struct message { }; struct message_queue { - struct semaphore hSem; + struct semaphore sem; spinlock_t strCriticalSection; bool bExiting; u32 u32ReceiversCount; -- cgit v1.2.3 From 3c09bb2e1eb0a4db3f297d2c70c0c1f553d7930e Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:37 +0900 Subject: staging: wilc1000: rename strCriticalSection in struct message_queue This patch renames strCriticalSection to lock to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 18 +++++++++--------- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index b996c47af15d..67bf147d7122 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -13,7 +13,7 @@ */ int wilc_mq_create(struct message_queue *pHandle) { - spin_lock_init(&pHandle->strCriticalSection); + spin_lock_init(&pHandle->lock); sema_init(&pHandle->sem, 0); pHandle->pstrMessageList = NULL; pHandle->u32ReceiversCount = 0; @@ -83,7 +83,7 @@ int wilc_mq_send(struct message_queue *pHandle, return -ENOMEM; } - spin_lock_irqsave(&pHandle->strCriticalSection, flags); + spin_lock_irqsave(&pHandle->lock, flags); /* add it to the message queue */ if (!pHandle->pstrMessageList) { @@ -97,7 +97,7 @@ int wilc_mq_send(struct message_queue *pHandle, pstrTailMsg->next = pstrMessage; } - spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); + spin_unlock_irqrestore(&pHandle->lock, flags); up(&pHandle->sem); @@ -128,22 +128,22 @@ int wilc_mq_recv(struct message_queue *pHandle, return -EFAULT; } - spin_lock_irqsave(&pHandle->strCriticalSection, flags); + spin_lock_irqsave(&pHandle->lock, flags); pHandle->u32ReceiversCount++; - spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); + spin_unlock_irqrestore(&pHandle->lock, flags); down(&pHandle->sem); - spin_lock_irqsave(&pHandle->strCriticalSection, flags); + spin_lock_irqsave(&pHandle->lock, flags); pstrMessage = pHandle->pstrMessageList; if (!pstrMessage) { - spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); + spin_unlock_irqrestore(&pHandle->lock, flags); PRINT_ER("pstrMessage is null\n"); return -EFAULT; } /* check buffer size */ if (u32RecvBufferSize < pstrMessage->len) { - spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); + spin_unlock_irqrestore(&pHandle->lock, flags); up(&pHandle->sem); PRINT_ER("u32RecvBufferSize overflow\n"); return -EOVERFLOW; @@ -159,7 +159,7 @@ int wilc_mq_recv(struct message_queue *pHandle, kfree(pstrMessage->buf); kfree(pstrMessage); - spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); + spin_unlock_irqrestore(&pHandle->lock, flags); return 0; } diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 3ea40682cdf0..6cdebbf09c11 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -21,7 +21,7 @@ struct message { struct message_queue { struct semaphore sem; - spinlock_t strCriticalSection; + spinlock_t lock; bool bExiting; u32 u32ReceiversCount; struct message *pstrMessageList; -- cgit v1.2.3 From c700cab3018cab34f510ba6e9fac5cbd6b030b1b Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:38 +0900 Subject: staging: wilc1000: rename bExiting in struct message_queue This patch renames bExiting to exiting to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 8 ++++---- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 67bf147d7122..47ba2564d931 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -17,7 +17,7 @@ int wilc_mq_create(struct message_queue *pHandle) sema_init(&pHandle->sem, 0); pHandle->pstrMessageList = NULL; pHandle->u32ReceiversCount = 0; - pHandle->bExiting = false; + pHandle->exiting = false; return 0; } @@ -29,7 +29,7 @@ int wilc_mq_create(struct message_queue *pHandle) */ int wilc_mq_destroy(struct message_queue *pHandle) { - pHandle->bExiting = true; + pHandle->exiting = true; /* Release any waiting receiver thread. */ while (pHandle->u32ReceiversCount > 0) { @@ -64,7 +64,7 @@ int wilc_mq_send(struct message_queue *pHandle, return -EFAULT; } - if (pHandle->bExiting) { + if (pHandle->exiting) { PRINT_ER("pHandle fail\n"); return -EFAULT; } @@ -123,7 +123,7 @@ int wilc_mq_recv(struct message_queue *pHandle, return -EINVAL; } - if (pHandle->bExiting) { + if (pHandle->exiting) { PRINT_ER("pHandle fail\n"); return -EFAULT; } diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 6cdebbf09c11..2c21b3e5cd3f 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -22,7 +22,7 @@ struct message { struct message_queue { struct semaphore sem; spinlock_t lock; - bool bExiting; + bool exiting; u32 u32ReceiversCount; struct message *pstrMessageList; }; -- cgit v1.2.3 From ec815ec5fd57e1ce016485336a68b8ab73316653 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:39 +0900 Subject: staging: wilc1000: rename u32ReceiversCount in struct message_queue This patch renames u32ReceiversCount to recv_count to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 10 +++++----- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 47ba2564d931..363e00389d22 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -16,7 +16,7 @@ int wilc_mq_create(struct message_queue *pHandle) spin_lock_init(&pHandle->lock); sema_init(&pHandle->sem, 0); pHandle->pstrMessageList = NULL; - pHandle->u32ReceiversCount = 0; + pHandle->recv_count = 0; pHandle->exiting = false; return 0; } @@ -32,9 +32,9 @@ int wilc_mq_destroy(struct message_queue *pHandle) pHandle->exiting = true; /* Release any waiting receiver thread. */ - while (pHandle->u32ReceiversCount > 0) { + while (pHandle->recv_count > 0) { up(&pHandle->sem); - pHandle->u32ReceiversCount--; + pHandle->recv_count--; } while (pHandle->pstrMessageList) { @@ -129,7 +129,7 @@ int wilc_mq_recv(struct message_queue *pHandle, } spin_lock_irqsave(&pHandle->lock, flags); - pHandle->u32ReceiversCount++; + pHandle->recv_count++; spin_unlock_irqrestore(&pHandle->lock, flags); down(&pHandle->sem); @@ -150,7 +150,7 @@ int wilc_mq_recv(struct message_queue *pHandle, } /* consume the message */ - pHandle->u32ReceiversCount--; + pHandle->recv_count--; memcpy(pvRecvBuffer, pstrMessage->buf, pstrMessage->len); *pu32ReceivedLength = pstrMessage->len; diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 2c21b3e5cd3f..dcf54ea4a874 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -23,7 +23,7 @@ struct message_queue { struct semaphore sem; spinlock_t lock; bool exiting; - u32 u32ReceiversCount; + u32 recv_count; struct message *pstrMessageList; }; -- cgit v1.2.3 From f9d26e21a874ce0799e5c0e54e0e6b473b3c0286 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:40 +0900 Subject: staging: wilc1000: rename pstrMessageList in struct message_queue This patch renames pstrMessageList to msg_list to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 20 ++++++++++---------- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 363e00389d22..d13c9a76ab92 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -15,7 +15,7 @@ int wilc_mq_create(struct message_queue *pHandle) { spin_lock_init(&pHandle->lock); sema_init(&pHandle->sem, 0); - pHandle->pstrMessageList = NULL; + pHandle->msg_list = NULL; pHandle->recv_count = 0; pHandle->exiting = false; return 0; @@ -37,11 +37,11 @@ int wilc_mq_destroy(struct message_queue *pHandle) pHandle->recv_count--; } - while (pHandle->pstrMessageList) { - struct message *pstrMessge = pHandle->pstrMessageList->next; + while (pHandle->msg_list) { + struct message *pstrMessge = pHandle->msg_list->next; - kfree(pHandle->pstrMessageList); - pHandle->pstrMessageList = pstrMessge; + kfree(pHandle->msg_list); + pHandle->msg_list = pstrMessge; } return 0; @@ -86,10 +86,10 @@ int wilc_mq_send(struct message_queue *pHandle, spin_lock_irqsave(&pHandle->lock, flags); /* add it to the message queue */ - if (!pHandle->pstrMessageList) { - pHandle->pstrMessageList = pstrMessage; + if (!pHandle->msg_list) { + pHandle->msg_list = pstrMessage; } else { - struct message *pstrTailMsg = pHandle->pstrMessageList; + struct message *pstrTailMsg = pHandle->msg_list; while (pstrTailMsg->next) pstrTailMsg = pstrTailMsg->next; @@ -135,7 +135,7 @@ int wilc_mq_recv(struct message_queue *pHandle, down(&pHandle->sem); spin_lock_irqsave(&pHandle->lock, flags); - pstrMessage = pHandle->pstrMessageList; + pstrMessage = pHandle->msg_list; if (!pstrMessage) { spin_unlock_irqrestore(&pHandle->lock, flags); PRINT_ER("pstrMessage is null\n"); @@ -154,7 +154,7 @@ int wilc_mq_recv(struct message_queue *pHandle, memcpy(pvRecvBuffer, pstrMessage->buf, pstrMessage->len); *pu32ReceivedLength = pstrMessage->len; - pHandle->pstrMessageList = pstrMessage->next; + pHandle->msg_list = pstrMessage->next; kfree(pstrMessage->buf); kfree(pstrMessage); diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index dcf54ea4a874..7e7ec06b132e 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -24,7 +24,7 @@ struct message_queue { spinlock_t lock; bool exiting; u32 recv_count; - struct message *pstrMessageList; + struct message *msg_list; }; /*! -- cgit v1.2.3 From 2cc08b4f2645c3689b48c0b94245fc2ef93556c3 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:41 +0900 Subject: staging: wilc1000: rename pHandle in wilc_mq_create This patch renames pHandle to mq to avoid camelcase Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 12 ++++++------ drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index d13c9a76ab92..453fa197738d 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -11,13 +11,13 @@ * @note copied from FLO glue implementatuion * @version 1.0 */ -int wilc_mq_create(struct message_queue *pHandle) +int wilc_mq_create(struct message_queue *mq) { - spin_lock_init(&pHandle->lock); - sema_init(&pHandle->sem, 0); - pHandle->msg_list = NULL; - pHandle->recv_count = 0; - pHandle->exiting = false; + spin_lock_init(&mq->lock); + sema_init(&mq->sem, 0); + mq->msg_list = NULL; + mq->recv_count = 0; + mq->exiting = false; return 0; } diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 7e7ec06b132e..bfd2347e5497 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -40,7 +40,7 @@ struct message_queue { * @date 30 Aug 2010 * @version 1.0 */ -int wilc_mq_create(struct message_queue *pHandle); +int wilc_mq_create(struct message_queue *mq); /*! * @brief Sends a message -- cgit v1.2.3 From d742f67ee129261ad37a88d8d0d7a36c81ace631 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:42 +0900 Subject: staging: wilc1000: rename pHandle in wilc_mq_destroy This patch renames pHandle to mq to avoid camelcase Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 18 +++++++++--------- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 453fa197738d..103fcfd9148a 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -27,21 +27,21 @@ int wilc_mq_create(struct message_queue *mq) * @note copied from FLO glue implementatuion * @version 1.0 */ -int wilc_mq_destroy(struct message_queue *pHandle) +int wilc_mq_destroy(struct message_queue *mq) { - pHandle->exiting = true; + mq->exiting = true; /* Release any waiting receiver thread. */ - while (pHandle->recv_count > 0) { - up(&pHandle->sem); - pHandle->recv_count--; + while (mq->recv_count > 0) { + up(&mq->sem); + mq->recv_count--; } - while (pHandle->msg_list) { - struct message *pstrMessge = pHandle->msg_list->next; + while (mq->msg_list) { + struct message *pstrMessge = mq->msg_list->next; - kfree(pHandle->msg_list); - pHandle->msg_list = pstrMessge; + kfree(mq->msg_list); + mq->msg_list = pstrMessge; } return 0; diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index bfd2347e5497..b91822e95ee9 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -89,6 +89,6 @@ int wilc_mq_recv(struct message_queue *pHandle, * @date 30 Aug 2010 * @version 1.0 */ -int wilc_mq_destroy(struct message_queue *pHandle); +int wilc_mq_destroy(struct message_queue *mq); #endif -- cgit v1.2.3 From fca978b718628e5c9ddd0a94f7fdaf7040bea1c4 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:43 +0900 Subject: staging: wilc1000: rename pstrMessge in wilc_mq_destroy This patch renames pstrMessge to msg to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 103fcfd9148a..a01420a9a729 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -38,10 +38,10 @@ int wilc_mq_destroy(struct message_queue *mq) } while (mq->msg_list) { - struct message *pstrMessge = mq->msg_list->next; + struct message *msg = mq->msg_list->next; kfree(mq->msg_list); - mq->msg_list = pstrMessge; + mq->msg_list = msg; } return 0; -- cgit v1.2.3 From 5eb359756f3b881cd52d26f257cde95f162177ec Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:44 +0900 Subject: staging: wilc1000: rename pHandle in wilc_mq_send This patch renames pHandle to mq to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 22 +++++++++++----------- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index a01420a9a729..71ce1f585c3c 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -53,19 +53,19 @@ int wilc_mq_destroy(struct message_queue *mq) * @note copied from FLO glue implementatuion * @version 1.0 */ -int wilc_mq_send(struct message_queue *pHandle, +int wilc_mq_send(struct message_queue *mq, const void *pvSendBuffer, u32 u32SendBufferSize) { unsigned long flags; struct message *pstrMessage = NULL; - if ((!pHandle) || (u32SendBufferSize == 0) || (!pvSendBuffer)) { - PRINT_ER("pHandle or pvSendBuffer is null\n"); + if ((!mq) || (u32SendBufferSize == 0) || (!pvSendBuffer)) { + PRINT_ER("mq or pvSendBuffer is null\n"); return -EFAULT; } - if (pHandle->exiting) { - PRINT_ER("pHandle fail\n"); + if (mq->exiting) { + PRINT_ER("mq fail\n"); return -EFAULT; } @@ -83,13 +83,13 @@ int wilc_mq_send(struct message_queue *pHandle, return -ENOMEM; } - spin_lock_irqsave(&pHandle->lock, flags); + spin_lock_irqsave(&mq->lock, flags); /* add it to the message queue */ - if (!pHandle->msg_list) { - pHandle->msg_list = pstrMessage; + if (!mq->msg_list) { + mq->msg_list = pstrMessage; } else { - struct message *pstrTailMsg = pHandle->msg_list; + struct message *pstrTailMsg = mq->msg_list; while (pstrTailMsg->next) pstrTailMsg = pstrTailMsg->next; @@ -97,9 +97,9 @@ int wilc_mq_send(struct message_queue *pHandle, pstrTailMsg->next = pstrMessage; } - spin_unlock_irqrestore(&pHandle->lock, flags); + spin_unlock_irqrestore(&mq->lock, flags); - up(&pHandle->sem); + up(&mq->sem); return 0; } diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index b91822e95ee9..e6cdc10fb1da 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -57,7 +57,7 @@ int wilc_mq_create(struct message_queue *mq); * @date 30 Aug 2010 * @version 1.0 */ -int wilc_mq_send(struct message_queue *pHandle, +int wilc_mq_send(struct message_queue *mq, const void *pvSendBuffer, u32 u32SendBufferSize); /*! -- cgit v1.2.3 From 832f4fa5f10fed19f3fe20609a87d1fe09fc7d0e Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:45 +0900 Subject: staging: wilc1000: rename pvSendBuffer in wilc_mq_send This patch renames pvSendBuffer to send_buf to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 8 ++++---- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 71ce1f585c3c..5feb87c88e0d 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -54,13 +54,13 @@ int wilc_mq_destroy(struct message_queue *mq) * @version 1.0 */ int wilc_mq_send(struct message_queue *mq, - const void *pvSendBuffer, u32 u32SendBufferSize) + const void *send_buf, u32 u32SendBufferSize) { unsigned long flags; struct message *pstrMessage = NULL; - if ((!mq) || (u32SendBufferSize == 0) || (!pvSendBuffer)) { - PRINT_ER("mq or pvSendBuffer is null\n"); + if ((!mq) || (u32SendBufferSize == 0) || (!send_buf)) { + PRINT_ER("mq or send_buf is null\n"); return -EFAULT; } @@ -76,7 +76,7 @@ int wilc_mq_send(struct message_queue *mq, pstrMessage->len = u32SendBufferSize; pstrMessage->next = NULL; - pstrMessage->buf = kmemdup(pvSendBuffer, u32SendBufferSize, + pstrMessage->buf = kmemdup(send_buf, u32SendBufferSize, GFP_ATOMIC); if (!pstrMessage->buf) { kfree(pstrMessage); diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index e6cdc10fb1da..3adee906c517 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -58,7 +58,7 @@ int wilc_mq_create(struct message_queue *mq); * @version 1.0 */ int wilc_mq_send(struct message_queue *mq, - const void *pvSendBuffer, u32 u32SendBufferSize); + const void *send_buf, u32 u32SendBufferSize); /*! * @brief Receives a message -- cgit v1.2.3 From 81e886e0b7d00c1e6c8bd820fb66a4144361020b Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:46 +0900 Subject: staging: wilc1000: rename u32SendBufferSize in wilc_mq_send This patch renames u32SendBufferSize to send_buf_size to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 8 ++++---- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 5feb87c88e0d..8e37cff02f9d 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -54,12 +54,12 @@ int wilc_mq_destroy(struct message_queue *mq) * @version 1.0 */ int wilc_mq_send(struct message_queue *mq, - const void *send_buf, u32 u32SendBufferSize) + const void *send_buf, u32 send_buf_size) { unsigned long flags; struct message *pstrMessage = NULL; - if ((!mq) || (u32SendBufferSize == 0) || (!send_buf)) { + if ((!mq) || (send_buf_size == 0) || (!send_buf)) { PRINT_ER("mq or send_buf is null\n"); return -EFAULT; } @@ -74,9 +74,9 @@ int wilc_mq_send(struct message_queue *mq, if (!pstrMessage) return -ENOMEM; - pstrMessage->len = u32SendBufferSize; + pstrMessage->len = send_buf_size; pstrMessage->next = NULL; - pstrMessage->buf = kmemdup(send_buf, u32SendBufferSize, + pstrMessage->buf = kmemdup(send_buf, send_buf_size, GFP_ATOMIC); if (!pstrMessage->buf) { kfree(pstrMessage); diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 3adee906c517..70e1be11a700 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -58,7 +58,7 @@ int wilc_mq_create(struct message_queue *mq); * @version 1.0 */ int wilc_mq_send(struct message_queue *mq, - const void *send_buf, u32 u32SendBufferSize); + const void *send_buf, u32 send_buf_size); /*! * @brief Receives a message -- cgit v1.2.3 From 669fd5077fede8af2aa6693280e38a37ef1efba1 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:47 +0900 Subject: staging: wilc1000: rename pstrMessage in wilc_mq_send This patch renames pstrMessage to new_msg to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 8e37cff02f9d..9a80fe694822 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -57,7 +57,7 @@ int wilc_mq_send(struct message_queue *mq, const void *send_buf, u32 send_buf_size) { unsigned long flags; - struct message *pstrMessage = NULL; + struct message *new_msg = NULL; if ((!mq) || (send_buf_size == 0) || (!send_buf)) { PRINT_ER("mq or send_buf is null\n"); @@ -70,16 +70,15 @@ int wilc_mq_send(struct message_queue *mq, } /* construct a new message */ - pstrMessage = kmalloc(sizeof(struct message), GFP_ATOMIC); - if (!pstrMessage) + new_msg = kmalloc(sizeof(struct message), GFP_ATOMIC); + if (!new_msg) return -ENOMEM; - pstrMessage->len = send_buf_size; - pstrMessage->next = NULL; - pstrMessage->buf = kmemdup(send_buf, send_buf_size, - GFP_ATOMIC); - if (!pstrMessage->buf) { - kfree(pstrMessage); + new_msg->len = send_buf_size; + new_msg->next = NULL; + new_msg->buf = kmemdup(send_buf, send_buf_size, GFP_ATOMIC); + if (!new_msg->buf) { + kfree(new_msg); return -ENOMEM; } @@ -87,14 +86,14 @@ int wilc_mq_send(struct message_queue *mq, /* add it to the message queue */ if (!mq->msg_list) { - mq->msg_list = pstrMessage; + mq->msg_list = new_msg; } else { struct message *pstrTailMsg = mq->msg_list; while (pstrTailMsg->next) pstrTailMsg = pstrTailMsg->next; - pstrTailMsg->next = pstrMessage; + pstrTailMsg->next = new_msg; } spin_unlock_irqrestore(&mq->lock, flags); -- cgit v1.2.3 From bd07b0076b465712804a5b01609dbe8fba9b9110 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:48 +0900 Subject: staging: wilc1000: rename pstrTailMsg in wilc_mq_send This patch renames pstrTailMsg to tail_msg to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 9a80fe694822..764723f99996 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -88,12 +88,12 @@ int wilc_mq_send(struct message_queue *mq, if (!mq->msg_list) { mq->msg_list = new_msg; } else { - struct message *pstrTailMsg = mq->msg_list; + struct message *tail_msg = mq->msg_list; - while (pstrTailMsg->next) - pstrTailMsg = pstrTailMsg->next; + while (tail_msg->next) + tail_msg = tail_msg->next; - pstrTailMsg->next = new_msg; + tail_msg->next = new_msg; } spin_unlock_irqrestore(&mq->lock, flags); -- cgit v1.2.3 From dee1bf76d96783a902a9aa5804e6a108f283b2d1 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:49 +0900 Subject: staging: wilc1000: fix return error code Three argument are checked at the beginning of wilc_mq_send whether they are valid arguments or not. It is correct to use return error code as -EINVAL, not -EFAULT. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 764723f99996..361ca8fbac31 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -61,7 +61,7 @@ int wilc_mq_send(struct message_queue *mq, if ((!mq) || (send_buf_size == 0) || (!send_buf)) { PRINT_ER("mq or send_buf is null\n"); - return -EFAULT; + return -EINVAL; } if (mq->exiting) { -- cgit v1.2.3 From 24752783baae2cfdd061140a61797957963bf069 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:50 +0900 Subject: staging: wilc1000: rename pHandle in wilc_mq_recv This patch renames pHandle to mq to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 34 ++++++++++++++++---------------- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 361ca8fbac31..d2df1795facb 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -109,56 +109,56 @@ int wilc_mq_send(struct message_queue *mq, * @note copied from FLO glue implementatuion * @version 1.0 */ -int wilc_mq_recv(struct message_queue *pHandle, +int wilc_mq_recv(struct message_queue *mq, void *pvRecvBuffer, u32 u32RecvBufferSize, u32 *pu32ReceivedLength) { struct message *pstrMessage; unsigned long flags; - if ((!pHandle) || (u32RecvBufferSize == 0) + if ((!mq) || (u32RecvBufferSize == 0) || (!pvRecvBuffer) || (!pu32ReceivedLength)) { - PRINT_ER("pHandle or pvRecvBuffer is null\n"); + PRINT_ER("mq or pvRecvBuffer is null\n"); return -EINVAL; } - if (pHandle->exiting) { - PRINT_ER("pHandle fail\n"); + if (mq->exiting) { + PRINT_ER("mq fail\n"); return -EFAULT; } - spin_lock_irqsave(&pHandle->lock, flags); - pHandle->recv_count++; - spin_unlock_irqrestore(&pHandle->lock, flags); + spin_lock_irqsave(&mq->lock, flags); + mq->recv_count++; + spin_unlock_irqrestore(&mq->lock, flags); - down(&pHandle->sem); - spin_lock_irqsave(&pHandle->lock, flags); + down(&mq->sem); + spin_lock_irqsave(&mq->lock, flags); - pstrMessage = pHandle->msg_list; + pstrMessage = mq->msg_list; if (!pstrMessage) { - spin_unlock_irqrestore(&pHandle->lock, flags); + spin_unlock_irqrestore(&mq->lock, flags); PRINT_ER("pstrMessage is null\n"); return -EFAULT; } /* check buffer size */ if (u32RecvBufferSize < pstrMessage->len) { - spin_unlock_irqrestore(&pHandle->lock, flags); - up(&pHandle->sem); + spin_unlock_irqrestore(&mq->lock, flags); + up(&mq->sem); PRINT_ER("u32RecvBufferSize overflow\n"); return -EOVERFLOW; } /* consume the message */ - pHandle->recv_count--; + mq->recv_count--; memcpy(pvRecvBuffer, pstrMessage->buf, pstrMessage->len); *pu32ReceivedLength = pstrMessage->len; - pHandle->msg_list = pstrMessage->next; + mq->msg_list = pstrMessage->next; kfree(pstrMessage->buf); kfree(pstrMessage); - spin_unlock_irqrestore(&pHandle->lock, flags); + spin_unlock_irqrestore(&mq->lock, flags); return 0; } diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 70e1be11a700..0c1eead47b42 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -76,7 +76,7 @@ int wilc_mq_send(struct message_queue *mq, * @date 30 Aug 2010 * @version 1.0 */ -int wilc_mq_recv(struct message_queue *pHandle, +int wilc_mq_recv(struct message_queue *mq, void *pvRecvBuffer, u32 u32RecvBufferSize, u32 *pu32ReceivedLength); -- cgit v1.2.3 From f034b01ea6236442c391c7d22623cd440d778de1 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:51 +0900 Subject: staging: wilc1000: rename pvRecvBuffer in wilc_mq_recv This patch renames pvRecvBuffer to recv_buf to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 8 ++++---- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index d2df1795facb..b836b2eac5cc 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -110,15 +110,15 @@ int wilc_mq_send(struct message_queue *mq, * @version 1.0 */ int wilc_mq_recv(struct message_queue *mq, - void *pvRecvBuffer, u32 u32RecvBufferSize, + void *recv_buf, u32 u32RecvBufferSize, u32 *pu32ReceivedLength) { struct message *pstrMessage; unsigned long flags; if ((!mq) || (u32RecvBufferSize == 0) - || (!pvRecvBuffer) || (!pu32ReceivedLength)) { - PRINT_ER("mq or pvRecvBuffer is null\n"); + || (!recv_buf) || (!pu32ReceivedLength)) { + PRINT_ER("mq or recv_buf is null\n"); return -EINVAL; } @@ -150,7 +150,7 @@ int wilc_mq_recv(struct message_queue *mq, /* consume the message */ mq->recv_count--; - memcpy(pvRecvBuffer, pstrMessage->buf, pstrMessage->len); + memcpy(recv_buf, pstrMessage->buf, pstrMessage->len); *pu32ReceivedLength = pstrMessage->len; mq->msg_list = pstrMessage->next; diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 0c1eead47b42..81b51dd88e6b 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -77,7 +77,7 @@ int wilc_mq_send(struct message_queue *mq, * @version 1.0 */ int wilc_mq_recv(struct message_queue *mq, - void *pvRecvBuffer, u32 u32RecvBufferSize, + void *recv_buf, u32 u32RecvBufferSize, u32 *pu32ReceivedLength); /*! -- cgit v1.2.3 From e8f2d1f19c6b18f2dbf2661311f4456850450a5f Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:52 +0900 Subject: staging: wilc1000: rename u32RecvBufferSize in wilc_mq_recv This patch renames u32RecvBufferSize to recv_buf_size to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 8 ++++---- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index b836b2eac5cc..c86bd7c6b72d 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -110,13 +110,13 @@ int wilc_mq_send(struct message_queue *mq, * @version 1.0 */ int wilc_mq_recv(struct message_queue *mq, - void *recv_buf, u32 u32RecvBufferSize, + void *recv_buf, u32 recv_buf_size, u32 *pu32ReceivedLength) { struct message *pstrMessage; unsigned long flags; - if ((!mq) || (u32RecvBufferSize == 0) + if ((!mq) || (recv_buf_size == 0) || (!recv_buf) || (!pu32ReceivedLength)) { PRINT_ER("mq or recv_buf is null\n"); return -EINVAL; @@ -141,10 +141,10 @@ int wilc_mq_recv(struct message_queue *mq, return -EFAULT; } /* check buffer size */ - if (u32RecvBufferSize < pstrMessage->len) { + if (recv_buf_size < pstrMessage->len) { spin_unlock_irqrestore(&mq->lock, flags); up(&mq->sem); - PRINT_ER("u32RecvBufferSize overflow\n"); + PRINT_ER("recv_buf_size overflow\n"); return -EOVERFLOW; } diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 81b51dd88e6b..3804b3bf4f01 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -77,7 +77,7 @@ int wilc_mq_send(struct message_queue *mq, * @version 1.0 */ int wilc_mq_recv(struct message_queue *mq, - void *recv_buf, u32 u32RecvBufferSize, + void *recv_buf, u32 recv_buf_size, u32 *pu32ReceivedLength); /*! -- cgit v1.2.3 From 62082cbe723299129948b35b15a18d2567cec651 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:53 +0900 Subject: staging: wilc1000: rename pu32ReceivedLength in wilc_mq_recv This patch renames pu32ReceivedLength to recv_len to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 7 +++---- drivers/staging/wilc1000/wilc_msgqueue.h | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index c86bd7c6b72d..5601de86656f 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -110,14 +110,13 @@ int wilc_mq_send(struct message_queue *mq, * @version 1.0 */ int wilc_mq_recv(struct message_queue *mq, - void *recv_buf, u32 recv_buf_size, - u32 *pu32ReceivedLength) + void *recv_buf, u32 recv_buf_size, u32 *recv_len) { struct message *pstrMessage; unsigned long flags; if ((!mq) || (recv_buf_size == 0) - || (!recv_buf) || (!pu32ReceivedLength)) { + || (!recv_buf) || (!recv_len)) { PRINT_ER("mq or recv_buf is null\n"); return -EINVAL; } @@ -151,7 +150,7 @@ int wilc_mq_recv(struct message_queue *mq, /* consume the message */ mq->recv_count--; memcpy(recv_buf, pstrMessage->buf, pstrMessage->len); - *pu32ReceivedLength = pstrMessage->len; + *recv_len = pstrMessage->len; mq->msg_list = pstrMessage->next; diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 3804b3bf4f01..4f79ead933ba 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -77,8 +77,7 @@ int wilc_mq_send(struct message_queue *mq, * @version 1.0 */ int wilc_mq_recv(struct message_queue *mq, - void *recv_buf, u32 recv_buf_size, - u32 *pu32ReceivedLength); + void *recv_buf, u32 recv_buf_size, u32 *recv_len); /*! * @brief Destroys an existing Message queue -- cgit v1.2.3 From 5b8e7ba9fdb01323867d8df6b6758527f9b87b81 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:54 +0900 Subject: staging: wilc1000: rename pstrMessage in wilc_mq_recv This patch renames pstrMessage to msg to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 5601de86656f..71077157033c 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -112,7 +112,7 @@ int wilc_mq_send(struct message_queue *mq, int wilc_mq_recv(struct message_queue *mq, void *recv_buf, u32 recv_buf_size, u32 *recv_len) { - struct message *pstrMessage; + struct message *msg; unsigned long flags; if ((!mq) || (recv_buf_size == 0) @@ -133,14 +133,14 @@ int wilc_mq_recv(struct message_queue *mq, down(&mq->sem); spin_lock_irqsave(&mq->lock, flags); - pstrMessage = mq->msg_list; - if (!pstrMessage) { + msg = mq->msg_list; + if (!msg) { spin_unlock_irqrestore(&mq->lock, flags); - PRINT_ER("pstrMessage is null\n"); + PRINT_ER("msg is null\n"); return -EFAULT; } /* check buffer size */ - if (recv_buf_size < pstrMessage->len) { + if (recv_buf_size < msg->len) { spin_unlock_irqrestore(&mq->lock, flags); up(&mq->sem); PRINT_ER("recv_buf_size overflow\n"); @@ -149,13 +149,13 @@ int wilc_mq_recv(struct message_queue *mq, /* consume the message */ mq->recv_count--; - memcpy(recv_buf, pstrMessage->buf, pstrMessage->len); - *recv_len = pstrMessage->len; + memcpy(recv_buf, msg->buf, msg->len); + *recv_len = msg->len; - mq->msg_list = pstrMessage->next; + mq->msg_list = msg->next; - kfree(pstrMessage->buf); - kfree(pstrMessage); + kfree(msg->buf); + kfree(msg); spin_unlock_irqrestore(&mq->lock, flags); -- cgit v1.2.3 From 7adf4f312bb7e1f3bda90ed048d78a5a55099f10 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:55 +0900 Subject: staging: wilc1000: fix coding style of kmalloc usage This patch fixes coding style of kmalloc usage found by checkpatch. CHECK: Prefer kmalloc(sizeof(*new_msg)...) over kmalloc(sizeof(struct message)...) Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 71077157033c..c7a60f44db77 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -70,7 +70,7 @@ int wilc_mq_send(struct message_queue *mq, } /* construct a new message */ - new_msg = kmalloc(sizeof(struct message), GFP_ATOMIC); + new_msg = kmalloc(sizeof(*new_msg), GFP_ATOMIC); if (!new_msg) return -ENOMEM; -- cgit v1.2.3 From 2c8e2dcb88bcd1c875e0d8f0581f18199073ec33 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:56 +0900 Subject: staging: wilc1000: fix logical continuations This patch fixes logical continuations found by checkpatch CHECK: Logical continuations should be on the previous line Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index c7a60f44db77..4493ca9adcce 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -115,8 +115,7 @@ int wilc_mq_recv(struct message_queue *mq, struct message *msg; unsigned long flags; - if ((!mq) || (recv_buf_size == 0) - || (!recv_buf) || (!recv_len)) { + if ((!mq) || (recv_buf_size == 0) || (!recv_buf) || (!recv_len)) { PRINT_ER("mq or recv_buf is null\n"); return -EINVAL; } -- cgit v1.2.3 From 734fadce60a810beb9471d260e5e8af820d50b1d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:57 +0900 Subject: staging: wilc1000: remove over-commenting There are over-commenting in wilc_msgqueue.h file. This comment is not explain exactly what codes do and make checkpatch warning about "line over 80 charcters". If necessary, comment will be added later with preferred coding style. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.h | 66 -------------------------------- 1 file changed, 66 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 4f79ead933ba..ddd0984337ea 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -1,18 +1,8 @@ #ifndef __WILC_MSG_QUEUE_H__ #define __WILC_MSG_QUEUE_H__ -/*! - * @file wilc_msgqueue.h - * @brief Message Queue OS wrapper functionality - * @author syounan - * @sa wilc_oswrapper.h top level OS wrapper file - * @date 30 Aug 2010 - * @version 1.0 - */ - #include -/* Message Queue type is a structure */ struct message { void *buf; u32 len; @@ -27,67 +17,11 @@ struct message_queue { struct message *msg_list; }; -/*! - * @brief Creates a new Message queue - * @details Creates a new Message queue, if the feature - * CONFIG_WILC_MSG_QUEUE_IPC_NAME is enabled and pstrAttrs->pcName - * is not Null, then this message queue can be used for IPC with - * any other message queue having the same name in the system - * @param[in,out] pHandle handle to the message queue object - * @param[in] pstrAttrs Optional attributes, NULL for default - * @return Error code indicating success/failure - * @author syounan - * @date 30 Aug 2010 - * @version 1.0 - */ int wilc_mq_create(struct message_queue *mq); - -/*! - * @brief Sends a message - * @details Sends a message, this API will block until the message is - * actually sent or until it is timedout (as long as the feature - * CONFIG_WILC_MSG_QUEUE_TIMEOUT is enabled and pstrAttrs->u32Timeout - * is not set to WILC_OS_INFINITY), zero timeout is a valid value - * @param[in] pHandle handle to the message queue object - * @param[in] pvSendBuffer pointer to the data to send - * @param[in] u32SendBufferSize the size of the data to send - * @param[in] pstrAttrs Optional attributes, NULL for default - * @return Error code indicating success/failure - * @author syounan - * @date 30 Aug 2010 - * @version 1.0 - */ int wilc_mq_send(struct message_queue *mq, const void *send_buf, u32 send_buf_size); - -/*! - * @brief Receives a message - * @details Receives a message, this API will block until a message is - * received or until it is timedout (as long as the feature - * CONFIG_WILC_MSG_QUEUE_TIMEOUT is enabled and pstrAttrs->u32Timeout - * is not set to WILC_OS_INFINITY), zero timeout is a valid value - * @param[in] pHandle handle to the message queue object - * @param[out] pvRecvBuffer pointer to a buffer to fill with the received message - * @param[in] u32RecvBufferSize the size of the receive buffer - * @param[out] pu32ReceivedLength the length of received data - * @param[in] pstrAttrs Optional attributes, NULL for default - * @return Error code indicating success/failure - * @author syounan - * @date 30 Aug 2010 - * @version 1.0 - */ int wilc_mq_recv(struct message_queue *mq, void *recv_buf, u32 recv_buf_size, u32 *recv_len); - -/*! - * @brief Destroys an existing Message queue - * @param[in] pHandle handle to the message queue object - * @param[in] pstrAttrs Optional attributes, NULL for default - * @return Error code indicating success/failure - * @author syounan - * @date 30 Aug 2010 - * @version 1.0 - */ int wilc_mq_destroy(struct message_queue *mq); #endif -- cgit v1.2.3 From 0c94df023602803fe4eaeb655510f5230b245beb Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:05 +0900 Subject: staging: wilc1000: fix bug when changing virtual interface This patch fixes a bug connection error when changing virtual interface to p2p. Variable quit needs to be set 0 when wilc is reinitialized again. Fixes : 67e2a07ed800 ("staging: wilc1000: move all of wilc_wlan_dev_t to struct wilc") Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 0b62cc5df488..07627b6ef8ec 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1588,6 +1588,8 @@ int wilc_wlan_init(struct net_device *dev) PRINT_D(INIT_DBG, "Initializing WILC_Wlan ...\n"); + wilc->quit = 0; + if (!wilc->hif_func->hif_init(wilc)) { ret = -EIO; goto _fail_; -- cgit v1.2.3 From 33c64975e3ebb5ce2301005ab3602dbb2fdf1cd0 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:06 +0900 Subject: staging: wilc1000: remove define WILC_OPTIMIZE_SLEEP_INT Take the codes of WILC_OPTIMIZE_SLEEP_INT and remove codes inside ifndef. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 74 +----------------------------------- 1 file changed, 2 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 07627b6ef8ec..e2ac0412014e 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -3,9 +3,7 @@ #include "wilc_wfi_netdevice.h" #include "wilc_wlan_cfg.h" -#ifdef WILC_OPTIMIZE_SLEEP_INT static inline void chip_allow_sleep(struct wilc *wilc); -#endif static inline void chip_wakeup(struct wilc *wilc); static u32 dbgflag = N_INIT | N_ERR | N_INTR | N_TXQ | N_RXQ; @@ -29,21 +27,14 @@ static CHIP_PS_STATE_T chip_ps_state = CHIP_WAKEDUP; static inline void acquire_bus(struct wilc *wilc, BUS_ACQUIRE_T acquire) { mutex_lock(&wilc->hif_cs); - #ifndef WILC_OPTIMIZE_SLEEP_INT - if (chip_ps_state != CHIP_WAKEDUP) - #endif - { - if (acquire == ACQUIRE_AND_WAKEUP) - chip_wakeup(wilc); - } + if (acquire == ACQUIRE_AND_WAKEUP) + chip_wakeup(wilc); } static inline void release_bus(struct wilc *wilc, BUS_RELEASE_T release) { - #ifdef WILC_OPTIMIZE_SLEEP_INT if (release == RELEASE_ALLOW_SLEEP) chip_allow_sleep(wilc); - #endif mutex_unlock(&wilc->hif_cs); } @@ -524,8 +515,6 @@ static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc) return NULL; } -#ifdef WILC_OPTIMIZE_SLEEP_INT - static inline void chip_allow_sleep(struct wilc *wilc) { u32 reg = 0; @@ -538,7 +527,6 @@ static inline void chip_allow_sleep(struct wilc *wilc) static inline void chip_wakeup(struct wilc *wilc) { u32 reg, clk_status_reg, trials = 0; - u32 sleep_time; if ((wilc->io_type & 0x1) == HIF_SPI) { do { @@ -597,66 +585,14 @@ static inline void chip_wakeup(struct wilc *wilc) } chip_ps_state = CHIP_WAKEDUP; } -#else -static inline void chip_wakeup(struct wilc *wilc) -{ - u32 reg, trials = 0; - - do { - if ((wilc->io_type & 0x1) == HIF_SPI) { - wilc->hif_func->hif_read_reg(wilc, 1, ®); - wilc->hif_func->hif_write_reg(wilc, 1, reg & ~BIT(1)); - wilc->hif_func->hif_write_reg(wilc, 1, reg | BIT(1)); - wilc->hif_func->hif_write_reg(wilc, 1, reg & ~BIT(1)); - } else if ((wilc->io_type & 0x1) == HIF_SDIO) { - wilc->hif_func->hif_read_reg(wilc, 0xf0, ®); - wilc->hif_func->hif_write_reg(wilc, 0xf0, - reg & ~BIT(0)); - wilc->hif_func->hif_write_reg(wilc, 0xf0, - reg | BIT(0)); - wilc->hif_func->hif_write_reg(wilc, 0xf0, - reg & ~BIT(0)); - } - - do { - mdelay(3); - - if ((wilc_get_chipid(wilc, true) == 0)) - wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n"); - - } while ((wilc_get_chipid(wilc, true) == 0) && ((++trials % 3) == 0)); - - } while (wilc_get_chipid(wilc, true) == 0); - if (chip_ps_state == CHIP_SLEEPING_MANUAL) { - wilc->hif_func->hif_read_reg(wilc, 0x1C0C, ®); - reg &= ~BIT(0); - wilc->hif_func->hif_write_reg(wilc, 0x1C0C, reg); - - if (wilc_get_chipid(wilc, false) >= 0x1002b0) { - u32 val32; - - wilc->hif_func->hif_read_reg(wilc, 0x1e1c, &val32); - val32 |= BIT(6); - wilc->hif_func->hif_write_reg(wilc, 0x1e1c, val32); - - wilc->hif_func->hif_read_reg(wilc, 0x1e9c, &val32); - val32 |= BIT(6); - wilc->hif_func->hif_write_reg(wilc, 0x1e9c, val32); - } - } - chip_ps_state = CHIP_WAKEDUP; -} -#endif void wilc_chip_sleep_manually(struct wilc *wilc) { if (chip_ps_state != CHIP_WAKEDUP) return; acquire_bus(wilc, ACQUIRE_ONLY); -#ifdef WILC_OPTIMIZE_SLEEP_INT chip_allow_sleep(wilc); -#endif wilc->hif_func->hif_write_reg(wilc, 0x10a8, 1); chip_ps_state = CHIP_SLEEPING_MANUAL; @@ -1041,9 +977,6 @@ static void wilc_pllupdate_isr_ext(struct wilc *wilc, u32 int_stats) static void wilc_sleeptimer_isr_ext(struct wilc *wilc, u32 int_stats1) { wilc->hif_func->hif_clear_int_ext(wilc, SLEEP_INT_CLR); -#ifndef WILC_OPTIMIZE_SLEEP_INT - chip_ps_state = CHIP_SLEEPING_AUTO; -#endif } static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status) @@ -1113,9 +1046,6 @@ void wilc_handle_isr(struct wilc *wilc) if (int_status & DATA_INT_EXT) { wilc_wlan_handle_isr_ext(wilc, int_status); - #ifndef WILC_OPTIMIZE_SLEEP_INT - chip_ps_state = CHIP_WAKEDUP; - #endif } if (int_status & SLEEP_INT_EXT) wilc_sleeptimer_isr_ext(wilc, int_status); -- cgit v1.2.3 From fdc2ac1aafc62dfea1ae116f832ff1874104a0ee Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:07 +0900 Subject: staging: wilc1000: support suspend/resume functionality wilc supports suspend/resume functionality. Introduce new sleep and wakeup functions and remove old codes since that will be handled in the new functions. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 31 +++++++++++++++++++------------ drivers/staging/wilc1000/wilc_wlan.h | 4 +++- 2 files changed, 22 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index e2ac0412014e..d824606a248b 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -522,6 +522,7 @@ static inline void chip_allow_sleep(struct wilc *wilc) wilc->hif_func->hif_read_reg(wilc, 0xf0, ®); wilc->hif_func->hif_write_reg(wilc, 0xf0, reg & ~BIT(0)); + wilc->hif_func->hif_write_reg(wilc, 0xfa, 0); } static inline void chip_wakeup(struct wilc *wilc) @@ -543,6 +544,8 @@ static inline void chip_wakeup(struct wilc *wilc) } while (wilc_get_chipid(wilc, true) == 0); } else if ((wilc->io_type & 0x1) == HIF_SDIO) { + wilc->hif_func->hif_write_reg(wilc, 0xfa, 1); + udelay(200); wilc->hif_func->hif_read_reg(wilc, 0xf0, ®); do { wilc->hif_func->hif_write_reg(wilc, 0xf0, @@ -567,11 +570,7 @@ static inline void chip_wakeup(struct wilc *wilc) } if (chip_ps_state == CHIP_SLEEPING_MANUAL) { - wilc->hif_func->hif_read_reg(wilc, 0x1C0C, ®); - reg &= ~BIT(0); - wilc->hif_func->hif_write_reg(wilc, 0x1C0C, reg); - - if (wilc_get_chipid(wilc, false) >= 0x1002b0) { + if (wilc_get_chipid(wilc, false) < 0x1002b0) { u32 val32; wilc->hif_func->hif_read_reg(wilc, 0x1e1c, &val32); @@ -599,6 +598,20 @@ void wilc_chip_sleep_manually(struct wilc *wilc) release_bus(wilc, RELEASE_ONLY); } +void host_wakeup_notify(struct wilc *wilc) +{ + acquire_bus(wilc, ACQUIRE_ONLY); + wilc->hif_func->hif_write_reg(wilc, 0x10b0, 1); + release_bus(wilc, RELEASE_ONLY); +} + +void host_sleep_notify(struct wilc *wilc) +{ + acquire_bus(wilc, ACQUIRE_ONLY); + wilc->hif_func->hif_write_reg(wilc, 0x10ac, 1); + release_bus(wilc, RELEASE_ONLY); +} + int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) { int i, entries = 0; @@ -701,9 +714,6 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) break; } PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait...\n"); - release_bus(wilc, RELEASE_ALLOW_SLEEP); - usleep_range(3000, 3000); - acquire_bus(wilc, ACQUIRE_AND_WAKEUP); } } while (!wilc->quit); @@ -736,9 +746,6 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) break; } else { release_bus(wilc, RELEASE_ALLOW_SLEEP); - usleep_range(3000, 3000); - acquire_bus(wilc, ACQUIRE_AND_WAKEUP); - PRINT_WRN(GENERIC_DBG, "Can't get VMM entery - reg = %2x\n", reg); } } while (--timeout); if (timeout <= 0) { @@ -1156,7 +1163,7 @@ int wilc_wlan_start(struct wilc *wilc) #ifdef WILC_EXT_PA_INV_TX_RX reg |= WILC_HAVE_EXT_PA_INV_TX_RX; #endif - + reg |= WILC_HAVE_USE_IRQ_AS_HOST_WAKE; reg |= WILC_HAVE_LEGACY_RF_SETTINGS; #ifdef XTAL_24 reg |= WILC_HAVE_XTAL_24; diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index 2edd7445f4a3..dd5abc52dfd9 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -106,6 +106,7 @@ #define WILC_HAVE_LEGACY_RF_SETTINGS BIT(5) #define WILC_HAVE_XTAL_24 BIT(6) #define WILC_HAVE_DISABLE_WILC_UART BIT(7) +#define WILC_HAVE_USE_IRQ_AS_HOST_WAKE BIT(8) /******************************************** * @@ -294,7 +295,8 @@ int wilc_mac_close(struct net_device *ndev); int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *pBSSID); void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size); - +void host_wakeup_notify(struct wilc *wilc); +void host_sleep_notify(struct wilc *wilc); extern bool wilc_enable_ps; #endif -- cgit v1.2.3 From 76855ba75fbc0787a5c0d32f991e54c81d2e5ad6 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:08 +0900 Subject: staging: wilc1000: add sdio resume/suspend This patch introduces sdio device suspend and resume functionality. sdio_reset function is added to reset sdio. Remove static inline keyword from chip_allow_sleep and chip_wakeup, and export symbols. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_sdio.c | 72 +++++++++++++++++++++++++++ drivers/staging/wilc1000/wilc_wfi_netdevice.h | 1 + drivers/staging/wilc1000/wilc_wlan.c | 11 ++-- drivers/staging/wilc1000/wilc_wlan.h | 3 +- 4 files changed, 82 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index caad876a8249..f40a52730bc6 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -42,6 +42,7 @@ static wilc_sdio_t g_sdio; static int sdio_write_reg(struct wilc *wilc, u32 addr, u32 data); static int sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data); +static int sdio_init(struct wilc *wilc); static void wilc_sdio_interrupt(struct sdio_func *func) { @@ -142,11 +143,82 @@ static void linux_sdio_remove(struct sdio_func *func) wilc_netdev_cleanup(sdio_get_drvdata(func)); } +static int sdio_reset(struct wilc *wilc) +{ + sdio_cmd52_t cmd; + int ret; + struct sdio_func *func = dev_to_sdio_func(wilc->dev); + + cmd.read_write = 1; + cmd.function = 0; + cmd.raw = 0; + cmd.address = 0x6; + cmd.data = 0x8; + ret = wilc_sdio_cmd52(wilc, &cmd); + if (ret) { + dev_err(&func->dev, "Fail cmd 52, reset cmd ...\n"); + return ret; + } + return 0; +} + +static int wilc_sdio_suspend(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + struct wilc *wilc = sdio_get_drvdata(func); + int ret; + + dev_info(dev, "sdio suspend\n"); + chip_wakeup(wilc); + + if (!wilc->suspend_event) { + wilc_chip_sleep_manually(wilc); + } else { + host_sleep_notify(wilc); + chip_allow_sleep(wilc); + } + + ret = sdio_reset(wilc); + if (ret) { + dev_err(&func->dev, "Fail reset sdio\n"); + return ret; + } + sdio_claim_host(func); + + return 0; +} + +static int wilc_sdio_resume(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + struct wilc *wilc = sdio_get_drvdata(func); + + dev_info(dev, "sdio resume\n"); + sdio_release_host(func); + chip_wakeup(wilc); + sdio_init(wilc); + + if (wilc->suspend_event) + host_wakeup_notify(wilc); + + chip_allow_sleep(wilc); + + return 0; +} + +static const struct dev_pm_ops wilc_sdio_pm_ops = { + .suspend = wilc_sdio_suspend, + .resume = wilc_sdio_resume, +}; + static struct sdio_driver wilc1000_sdio_driver = { .name = SDIO_MODALIAS, .id_table = wilc_sdio_ids, .probe = linux_sdio_probe, .remove = linux_sdio_remove, + .drv = { + .pm = &wilc_sdio_pm_ops, + } }; module_driver(wilc1000_sdio_driver, sdio_register_driver, diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 98ac8ed04a06..cd3d21d61bed 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -215,6 +215,7 @@ struct wilc { const struct firmware *firmware; struct device *dev; + bool suspend_event; }; struct WILC_WFI_mon_priv { diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index d824606a248b..74e20879f8ef 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -3,8 +3,6 @@ #include "wilc_wfi_netdevice.h" #include "wilc_wlan_cfg.h" -static inline void chip_allow_sleep(struct wilc *wilc); -static inline void chip_wakeup(struct wilc *wilc); static u32 dbgflag = N_INIT | N_ERR | N_INTR | N_TXQ | N_RXQ; /* FIXME: replace with dev_debug() */ @@ -515,7 +513,7 @@ static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc) return NULL; } -static inline void chip_allow_sleep(struct wilc *wilc) +void chip_allow_sleep(struct wilc *wilc) { u32 reg = 0; @@ -524,8 +522,9 @@ static inline void chip_allow_sleep(struct wilc *wilc) wilc->hif_func->hif_write_reg(wilc, 0xf0, reg & ~BIT(0)); wilc->hif_func->hif_write_reg(wilc, 0xfa, 0); } +EXPORT_SYMBOL_GPL(chip_allow_sleep); -static inline void chip_wakeup(struct wilc *wilc) +void chip_wakeup(struct wilc *wilc) { u32 reg, clk_status_reg, trials = 0; @@ -584,6 +583,7 @@ static inline void chip_wakeup(struct wilc *wilc) } chip_ps_state = CHIP_WAKEDUP; } +EXPORT_SYMBOL_GPL(chip_wakeup); void wilc_chip_sleep_manually(struct wilc *wilc) { @@ -597,6 +597,7 @@ void wilc_chip_sleep_manually(struct wilc *wilc) chip_ps_state = CHIP_SLEEPING_MANUAL; release_bus(wilc, RELEASE_ONLY); } +EXPORT_SYMBOL_GPL(wilc_chip_sleep_manually); void host_wakeup_notify(struct wilc *wilc) { @@ -604,6 +605,7 @@ void host_wakeup_notify(struct wilc *wilc) wilc->hif_func->hif_write_reg(wilc, 0x10b0, 1); release_bus(wilc, RELEASE_ONLY); } +EXPORT_SYMBOL_GPL(host_wakeup_notify); void host_sleep_notify(struct wilc *wilc) { @@ -611,6 +613,7 @@ void host_sleep_notify(struct wilc *wilc) wilc->hif_func->hif_write_reg(wilc, 0x10ac, 1); release_bus(wilc, RELEASE_ONLY); } +EXPORT_SYMBOL_GPL(host_sleep_notify); int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) { diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index dd5abc52dfd9..53e56ff4d401 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -298,5 +298,6 @@ void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size); void host_wakeup_notify(struct wilc *wilc); void host_sleep_notify(struct wilc *wilc); extern bool wilc_enable_ps; - +void chip_allow_sleep(struct wilc *wilc); +void chip_wakeup(struct wilc *wilc); #endif -- cgit v1.2.3 From 5397cbc231e20c8166709e696e70cff08d8ae503 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:09 +0900 Subject: staging: wilc1000: sdio_init: add resume argument Part of sdio init codes should not run when sdio init function is called on sdio resume so skip them. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_sdio.c | 34 +++++++++++++++++++--------------- drivers/staging/wilc1000/wilc_spi.c | 2 +- drivers/staging/wilc1000/wilc_wlan.c | 2 +- drivers/staging/wilc1000/wilc_wlan.h | 2 +- 4 files changed, 22 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index f40a52730bc6..7c20c8c9c2bc 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -42,7 +42,7 @@ static wilc_sdio_t g_sdio; static int sdio_write_reg(struct wilc *wilc, u32 addr, u32 data); static int sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data); -static int sdio_init(struct wilc *wilc); +static int sdio_init(struct wilc *wilc, bool resume); static void wilc_sdio_interrupt(struct sdio_func *func) { @@ -196,7 +196,7 @@ static int wilc_sdio_resume(struct device *dev) dev_info(dev, "sdio resume\n"); sdio_release_host(func); chip_wakeup(wilc); - sdio_init(wilc); + sdio_init(wilc, true); if (wilc->suspend_event) host_wakeup_notify(wilc); @@ -667,16 +667,17 @@ static int sdio_deinit(struct wilc *wilc) return 1; } -static int sdio_init(struct wilc *wilc) +static int sdio_init(struct wilc *wilc, bool resume) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); sdio_cmd52_t cmd; int loop, ret; u32 chipid; - memset(&g_sdio, 0, sizeof(wilc_sdio_t)); - - g_sdio.irq_gpio = (wilc->dev_irq_num); + if (!resume) { + memset(&g_sdio, 0, sizeof(wilc_sdio_t)); + g_sdio.irq_gpio = (wilc->dev_irq_num); + } /** * function 0 csa enable @@ -766,16 +767,19 @@ static int sdio_init(struct wilc *wilc) /** * make sure can read back chip id correctly **/ - if (!sdio_read_reg(wilc, 0x1000, &chipid)) { - dev_err(&func->dev, "Fail cmd read chip id...\n"); - goto _fail_; + if (!resume) { + if (!sdio_read_reg(wilc, 0x1000, &chipid)) { + dev_err(&func->dev, "Fail cmd read chip id...\n"); + goto _fail_; + } + dev_err(&func->dev, "chipid (%08x)\n", chipid); + if ((chipid & 0xfff) > 0x2a0) + g_sdio.has_thrpt_enh3 = 1; + else + g_sdio.has_thrpt_enh3 = 0; + dev_info(&func->dev, "has_thrpt_enh3 = %d...\n", + g_sdio.has_thrpt_enh3); } - dev_err(&func->dev, "chipid (%08x)\n", chipid); - if ((chipid & 0xfff) > 0x2a0) - g_sdio.has_thrpt_enh3 = 1; - else - g_sdio.has_thrpt_enh3 = 0; - dev_info(&func->dev, "has_thrpt_enh3 = %d...\n", g_sdio.has_thrpt_enh3); return 1; diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index 1df07e7bea59..29287122d1ca 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -850,7 +850,7 @@ static int _wilc_spi_deinit(struct wilc *wilc) return 1; } -static int wilc_spi_init(struct wilc *wilc) +static int wilc_spi_init(struct wilc *wilc, bool resume) { struct spi_device *spi = to_spi_device(wilc->dev); u32 reg; diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 74e20879f8ef..36debb4d061c 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1530,7 +1530,7 @@ int wilc_wlan_init(struct net_device *dev) wilc->quit = 0; - if (!wilc->hif_func->hif_init(wilc)) { + if (!wilc->hif_func->hif_init(wilc, false)) { ret = -EIO; goto _fail_; } diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index 53e56ff4d401..a1096edd6b63 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -227,7 +227,7 @@ struct rxq_entry_t { ********************************************/ struct wilc; struct wilc_hif_func { - int (*hif_init)(struct wilc *); + int (*hif_init)(struct wilc *, bool resume); int (*hif_deinit)(struct wilc *); int (*hif_read_reg)(struct wilc *, u32, u32 *); int (*hif_write_reg)(struct wilc *, u32, u32); -- cgit v1.2.3 From 73584a40d7484f199a98893e97dcea8b2cbe4986 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:10 +0900 Subject: staging: wilc1000: add ops resuem/suspend/wakeup in cfg80211 This patch adds ops resume, suspend and set_wakeup in cfg80211. Together with previous patches, driver will support suspend/resume functionality. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 39 +++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 792fdff4bca9..0b6df6a95448 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -74,6 +74,10 @@ static const struct ieee80211_txrx_stypes } }; +static const struct wiphy_wowlan_support wowlan_support = { + .flags = WIPHY_WOWLAN_ANY +}; + #define WILC_WFI_DWELL_PASSIVE 100 #define WILC_WFI_DWELL_ACTIVE 40 @@ -2673,6 +2677,36 @@ static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) return 0; } +static int wilc_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) +{ + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); + + if (!wow && wilc_wlan_get_num_conn_ifcs(vif->wilc)) + vif->wilc->suspend_event = true; + else + vif->wilc->suspend_event = false; + + return 0; +} + +static int wilc_resume(struct wiphy *wiphy) +{ + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); + + netdev_info(vif->ndev, "cfg resume\n"); + return 0; +} + +static void wilc_set_wakeup(struct wiphy *wiphy, bool enabled) +{ + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); + + netdev_info(vif->ndev, "cfg set wake up = %d\n", enabled); +} + static struct cfg80211_ops wilc_cfg80211_ops = { .set_monitor_channel = set_channel, .scan = scan, @@ -2708,6 +2742,10 @@ static struct cfg80211_ops wilc_cfg80211_ops = { .set_power_mgmt = set_power_mgmt, .set_cqm_rssi_config = set_cqm_rssi_config, + .suspend = wilc_suspend, + .resume = wilc_resume, + .set_wakeup = wilc_set_wakeup, + }; int WILC_WFI_update_stats(struct wiphy *wiphy, u32 pktlen, u8 changed) @@ -2792,6 +2830,7 @@ struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct device *de sema_init(&(priv->SemHandleUpdateStats), 1); priv->wdev = wdev; wdev->wiphy->max_scan_ssids = MAX_NUM_PROBED_SSID; + wdev->wiphy->wowlan = &wowlan_support; wdev->wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS; PRINT_INFO(CFG80211_DBG, "Max number of PMKIDs = %d\n", wdev->wiphy->max_num_pmkids); -- cgit v1.2.3 From 08037941d68497032f54a43c32ca20ccd5e2406b Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:11 +0900 Subject: staging: wilc1000: remove sleep and reduce close timeout sleep is not necessary during handling tx queue so remove it and also reduce close time to 5 sec since it is enough time to close. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 54fe9d74b780..236996fd8677 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -391,9 +391,6 @@ static int linux_wlan_txq_task(void *vp) } if (ret == WILC_TX_ERR_NO_BUF) { - do { - msleep(TX_BACKOFF_WEIGHT_UNIT_MS << backoff_weight); - } while (0); backoff_weight += TX_BACKOFF_WEIGHT_INCR_STEP; if (backoff_weight > TX_BACKOFF_WEIGHT_MAX) backoff_weight = TX_BACKOFF_WEIGHT_MAX; @@ -1403,7 +1400,7 @@ void wilc_netdev_cleanup(struct wilc *wilc) release_firmware(wilc->firmware); if (wilc && (wilc->vif[0]->ndev || wilc->vif[1]->ndev)) { - wilc_lock_timeout(wilc, &close_exit_sync, 12 * 1000); + wilc_lock_timeout(wilc, &close_exit_sync, 5 * 1000); for (i = 0; i < NUM_CONCURRENT_IFC; i++) if (wilc->vif[i]->ndev) -- cgit v1.2.3 From b8f6ca0b169dbf1d2800c3b7c618288aad91f039 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:12 +0900 Subject: staging: wilc1000: get address from wilc Get mac address from wilc device instead of using random mac address. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 236996fd8677..58837d7f1be2 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -511,20 +511,19 @@ static int wilc1000_firmware_download(struct net_device *dev) } static int linux_wlan_init_test_config(struct net_device *dev, - struct wilc *wilc) + struct wilc_vif *vif) { unsigned char c_val[64]; unsigned char mac_add[] = {0x00, 0x80, 0xC2, 0x5E, 0xa2, 0xff}; - + struct wilc *wilc = vif->wilc; struct wilc_priv *priv; struct host_if_drv *hif_drv; PRINT_D(TX_DBG, "Start configuring Firmware\n"); - get_random_bytes(&mac_add[5], 1); - get_random_bytes(&mac_add[4], 1); priv = wiphy_priv(dev->ieee80211_ptr->wiphy); hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv; PRINT_D(INIT_DBG, "Host = %p\n", hif_drv); + wilc_get_mac_address(vif, mac_add); PRINT_D(INIT_DBG, "MAC address is : %02x-%02x-%02x-%02x-%02x-%02x\n", mac_add[0], mac_add[1], mac_add[2], @@ -944,7 +943,7 @@ int wilc1000_wlan_init(struct net_device *dev, struct wilc_vif *vif) Firmware_ver[size] = '\0'; PRINT_D(INIT_DBG, "***** Firmware Ver = %s *******\n", Firmware_ver); } - ret = linux_wlan_init_test_config(dev, wl); + ret = linux_wlan_init_test_config(dev, vif); if (ret < 0) { PRINT_ER("Failed to configure firmware\n"); -- cgit v1.2.3 From 14823bf2ea000c8762ec38ed7b67ee049a2b6fbf Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:13 +0900 Subject: staging: wilc1000: use unified firmware Use a unified firmware for all mode of operations which are station, ap and p2p. Two firmware are introduced for 1002 and 1003 chipset. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/Makefile | 5 ++--- drivers/staging/wilc1000/linux_wlan.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/Makefile b/drivers/staging/wilc1000/Makefile index 20a5cb9d4f4c..90c37606f202 100644 --- a/drivers/staging/wilc1000/Makefile +++ b/drivers/staging/wilc1000/Makefile @@ -1,8 +1,7 @@ obj-$(CONFIG_WILC1000) += wilc1000.o -ccflags-y += -DSTA_FIRMWARE=\"atmel/wilc1000_fw.bin\" \ - -DAP_FIRMWARE=\"atmel/wilc1000_ap_fw.bin\" \ - -DP2P_CONCURRENCY_FIRMWARE=\"atmel/wilc1000_p2p_fw.bin\" +ccflags-y += -DFIRMWARE_1002=\"atmel/wilc1002_firmware.bin\" \ + -DFIRMWARE_1003=\"atmel/wilc1003_firmware.bin\" ccflags-y += -I$(src)/ -DWILC_ASIC_A0 -DWILC_DEBUGFS #ccflags-y += -DTCP_ACK_FILTER diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 58837d7f1be2..006f75f7c675 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -416,21 +416,21 @@ int wilc_wlan_get_firmware(struct net_device *dev) { struct wilc_vif *vif; struct wilc *wilc; - int ret = 0; + int chip_id, ret = 0; const struct firmware *wilc_firmware; char *firmware; vif = netdev_priv(dev); wilc = vif->wilc; - if (vif->iftype == AP_MODE) { - firmware = AP_FIRMWARE; - } else if (vif->iftype == STATION_MODE) { - firmware = STA_FIRMWARE; - } else { - PRINT_D(INIT_DBG, "Get P2P_CONCURRENCY_FIRMWARE\n"); - firmware = P2P_CONCURRENCY_FIRMWARE; - } + chip_id = wilc_get_chipid(wilc, 0); + + if (chip_id < 0x1003a0) + firmware = FIRMWARE_1002; + else + firmware = FIRMWARE_1003; + + netdev_info(dev, "loading firmware %s\n", firmware); if (!vif) { PRINT_ER("vif is NULL\n"); -- cgit v1.2.3 From e32737e9da8d870006fa34a4374391d103d87eb6 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:14 +0900 Subject: staging: wilc1000: remove wilc_set_machw_change_vir_if wilc_set_machw_change_vir_if is not used anymore since we use one unified firmware. Instead, wilc_set_operation_mode is called when wilc_mac_open to let the wilc use the proper firmware. Remove wilc_set_machw_change_vir_if and it's functions calls. In the later patch, mac index will be passed to wilc device. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 3 +-- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 6 ----- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 1 - drivers/staging/wilc1000/wilc_wlan.c | 32 ----------------------- 4 files changed, 1 insertion(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 006f75f7c675..08d2cb2c00b8 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1024,14 +1024,13 @@ int wilc_mac_open(struct net_device *ndev) return ret; } - wilc_set_machw_change_vir_if(ndev, false); - wilc_get_mac_address(vif, mac_add); PRINT_D(INIT_DBG, "Mac address: %pM\n", mac_add); for (i = 0; i < wl->vif_num; i++) { if (ndev == wl->vif[i]->ndev) { memcpy(wl->vif[i]->src_addr, mac_add, ETH_ALEN); + wilc_set_operation_mode(vif, vif->iftype); break; } } diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 0b6df6a95448..d2b7a8be484c 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1274,7 +1274,6 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev, kfree(g_key_gtk_params.seq); g_key_gtk_params.seq = NULL; - wilc_set_machw_change_vir_if(netdev, false); } if (key_index >= 0 && key_index <= 3) { @@ -2116,10 +2115,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, del_timer(&wilc_during_ip_timer); PRINT_D(GENERIC_DBG, "Changing virtual interface, enable scan\n"); - if (g_ptk_keys_saved && g_gtk_keys_saved) { - wilc_set_machw_change_vir_if(dev, true); - } - switch (type) { case NL80211_IFTYPE_STATION: wilc_connecting = 0; @@ -2261,7 +2256,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, } refresh_scan(priv, 1, true); - wilc_set_machw_change_vir_if(dev, false); if (wl->initialized) { for (i = 0; i < num_reg_frame; i++) { diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index cd3d21d61bed..0d851f863b91 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -235,7 +235,6 @@ int wilc_netdev_init(struct wilc **wilc, struct device *, int io_type, int gpio, const struct wilc_hif_func *ops); void wilc1000_wlan_deinit(struct net_device *dev); void WILC_WFI_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size); -u16 wilc_set_machw_change_vir_if(struct net_device *dev, bool value); int wilc_wlan_get_firmware(struct net_device *dev); int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid); diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 36debb4d061c..5682581ebcc3 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1578,35 +1578,3 @@ _fail_: return ret; } - -u16 wilc_set_machw_change_vir_if(struct net_device *dev, bool value) -{ - u16 ret; - u32 reg; - struct wilc_vif *vif; - struct wilc *wilc; - - vif = netdev_priv(dev); - wilc = vif->wilc; - - mutex_lock(&wilc->hif_cs); - ret = wilc->hif_func->hif_read_reg(wilc, WILC_CHANGING_VIR_IF, - ®); - if (!ret) - PRINT_ER("Error while Reading reg WILC_CHANGING_VIR_IF\n"); - - if (value) - reg |= BIT(31); - else - reg &= ~BIT(31); - - ret = wilc->hif_func->hif_write_reg(wilc, WILC_CHANGING_VIR_IF, - reg); - - if (!ret) - PRINT_ER("Error while writing reg WILC_CHANGING_VIR_IF\n"); - - mutex_unlock(&wilc->hif_cs); - - return ret; -} -- cgit v1.2.3 From ba615f1ef9cc8272ac8def632286c53524ce4f57 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:15 +0900 Subject: staging: wilc1000: set bssid with mode This patch add new argument mode to wilc_wlan_set_bssid and define mode in struct wilc_vif also. The mode is used by get_if_handler function to get proper netdevice for each mode. The get_if_handler is changed together. Remove invalid handle codes and add mode condition to get netdevice for the mode. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 26 +++++++++-------------- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 13 ++++++------ drivers/staging/wilc1000/wilc_wfi_netdevice.h | 3 ++- drivers/staging/wilc1000/wilc_wlan.h | 1 - 4 files changed, 19 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 08d2cb2c00b8..2489ea30855c 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -288,26 +288,19 @@ static struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header) bssid = mac_header + 10; bssid1 = mac_header + 4; - for (i = 0; i < wilc->vif_num; i++) - if (!memcmp(bssid1, wilc->vif[i]->bssid, ETH_ALEN) || - !memcmp(bssid, wilc->vif[i]->bssid, ETH_ALEN)) - return wilc->vif[i]->ndev; - - PRINT_INFO(INIT_DBG, "Invalide handle\n"); - for (i = 0; i < 25; i++) - PRINT_D(INIT_DBG, "%02x ", mac_header[i]); - bssid = mac_header + 18; - bssid1 = mac_header + 12; - for (i = 0; i < wilc->vif_num; i++) - if (!memcmp(bssid1, wilc->vif[i]->bssid, ETH_ALEN) || - !memcmp(bssid, wilc->vif[i]->bssid, ETH_ALEN)) - return wilc->vif[i]->ndev; + for (i = 0; i < wilc->vif_num; i++) { + if (wilc->vif[i]->mode == STATION_MODE) + if (!memcmp(bssid, wilc->vif[i]->bssid, ETH_ALEN)) + return wilc->vif[i]->ndev; + if (wilc->vif[i]->mode == AP_MODE) + if (!memcmp(bssid1, wilc->vif[i]->bssid, ETH_ALEN)) + return wilc->vif[i]->ndev; + } - PRINT_INFO(INIT_DBG, "\n"); return NULL; } -int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid) +int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode) { int i = 0; int ret = -1; @@ -320,6 +313,7 @@ int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid) for (i = 0; i < wilc->vif_num; i++) if (wilc->vif[i]->ndev == wilc_netdev) { memcpy(wilc->vif[i]->bssid, bssid, 6); + wilc->vif[i]->mode = mode; ret = 0; break; } diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index d2b7a8be484c..1b2eae59b51e 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -524,7 +524,8 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, if ((u8MacStatus == MAC_DISCONNECTED) && (pstrConnectInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE)) { u16ConnectStatus = WLAN_STATUS_UNSPECIFIED_FAILURE; - wilc_wlan_set_bssid(priv->dev, NullBssid); + wilc_wlan_set_bssid(priv->dev, NullBssid, + STATION_MODE); eth_zero_addr(wilc_connected_ssid); if (!pstrWFIDrv->p2p_connect) @@ -577,7 +578,7 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, p2p_recv_random = 0x00; wilc_ie = false; eth_zero_addr(priv->au8AssociatedBss); - wilc_wlan_set_bssid(priv->dev, NullBssid); + wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE); eth_zero_addr(wilc_connected_ssid); if (!pstrWFIDrv->p2p_connect) @@ -903,7 +904,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, if (!pstrWFIDrv->p2p_connect) wlan_channel = pstrNetworkInfo->u8channel; - wilc_wlan_set_bssid(dev, pstrNetworkInfo->au8bssid); + wilc_wlan_set_bssid(dev, pstrNetworkInfo->au8bssid, STATION_MODE); s32Error = wilc_set_join_req(vif, pstrNetworkInfo->au8bssid, sme->ssid, sme->ssid_len, sme->ie, sme->ie_len, @@ -937,7 +938,7 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_co pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv; if (!pstrWFIDrv->p2p_connect) wlan_channel = INVALID_CHANNEL; - wilc_wlan_set_bssid(priv->dev, NullBssid); + wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE); PRINT_D(CFG80211_DBG, "Disconnecting with reason code(%d)\n", reason_code); @@ -2400,7 +2401,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, if (s32Error != 0) PRINT_ER("Error in setting channel\n"); - wilc_wlan_set_bssid(dev, wl->vif[0]->src_addr); + wilc_wlan_set_bssid(dev, wl->vif[0]->src_addr, AP_MODE); s32Error = wilc_add_beacon(vif, settings->beacon_interval, settings->dtim_period, beacon->head_len, @@ -2444,7 +2445,7 @@ static int stop_ap(struct wiphy *wiphy, struct net_device *dev) PRINT_D(HOSTAPD_DBG, "Deleting beacon\n"); - wilc_wlan_set_bssid(dev, NullBssid); + wilc_wlan_set_bssid(dev, NullBssid, AP_MODE); s32Error = wilc_del_beacon(vif); diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 0d851f863b91..54e762ec815f 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -160,6 +160,7 @@ struct wilc_vif { u8 bssid[ETH_ALEN]; struct host_if_drv *hif_drv; struct net_device *ndev; + u8 mode; }; struct wilc { @@ -236,6 +237,6 @@ int wilc_netdev_init(struct wilc **wilc, struct device *, int io_type, int gpio, void wilc1000_wlan_deinit(struct net_device *dev); void WILC_WFI_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size); int wilc_wlan_get_firmware(struct net_device *dev); -int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid); +int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode); #endif diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index a1096edd6b63..7f046531be01 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -293,7 +293,6 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev); int wilc_mac_open(struct net_device *ndev); int wilc_mac_close(struct net_device *ndev); -int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *pBSSID); void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size); void host_wakeup_notify(struct wilc *wilc); void host_sleep_notify(struct wilc *wilc); -- cgit v1.2.3 From ff35567923c7df4af03adec0a36871914b48bead Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:16 +0900 Subject: staging: wilc1000: set proper bssid address This patch changes index 0 to index of vif which is currently beging used because AP mode can run on any interface. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 1b2eae59b51e..7db96c7097c2 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2401,7 +2401,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, if (s32Error != 0) PRINT_ER("Error in setting channel\n"); - wilc_wlan_set_bssid(dev, wl->vif[0]->src_addr, AP_MODE); + wilc_wlan_set_bssid(dev, wl->vif[vif->u8IfIdx]->src_addr, AP_MODE); s32Error = wilc_add_beacon(vif, settings->beacon_interval, settings->dtim_period, beacon->head_len, -- cgit v1.2.3 From 86bff01b94bb0cd1a2cbcaae46c3677d60768c1a Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:17 +0900 Subject: staging: wilc1000: change_virtual_intf: change codes for unified firmware In previous patch, we use unified firmware on wilc, which means we do not need to download firmware again to change virtual interfaces. There are a lot of codes to change interface and they are needless now, so remove them except wilc_set_operation_mode function which change the mode and wilc_set_power_mgmt which control power save. There will be unused functions and they will be removed in later patch. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 220 ++-------------------- 1 file changed, 11 insertions(+), 209 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 7db96c7097c2..d282a871ddcb 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2098,9 +2098,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, { struct wilc_priv *priv; struct wilc_vif *vif; - u8 interface_type; - u16 TID = 0; - u8 i; struct wilc *wl; vif = netdev_priv(dev); @@ -2125,74 +2122,12 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, priv->wdev->iftype = type; vif->monitor_flag = 0; vif->iftype = STATION_MODE; + wilc_set_operation_mode(vif, STATION_MODE); memset(priv->assoc_stainfo.au8Sta_AssociatedBss, 0, MAX_NUM_STA * ETH_ALEN); - interface_type = vif->iftype; - vif->iftype = STATION_MODE; - - if (wl->initialized) { - wilc_del_all_rx_ba_session(vif, wl->vif[0]->bssid, - TID); - wilc_wait_msg_queue_idle(); - - up(&wl->cfg_event); - - wilc1000_wlan_deinit(dev); - wilc1000_wlan_init(dev, vif); - wilc_initialized = 1; - vif->iftype = interface_type; - - wilc_set_wfi_drv_handler(vif, - wilc_get_vif_idx(wl->vif[0])); - wilc_set_mac_address(wl->vif[0], wl->vif[0]->src_addr); - wilc_set_operation_mode(vif, STATION_MODE); - - if (g_wep_keys_saved) { - wilc_set_wep_default_keyid(wl->vif[0], - g_key_wep_params.key_idx); - wilc_add_wep_key_bss_sta(wl->vif[0], - g_key_wep_params.key, - g_key_wep_params.key_len, - g_key_wep_params.key_idx); - } - - wilc_flush_join_req(vif); - - if (g_ptk_keys_saved && g_gtk_keys_saved) { - PRINT_D(CFG80211_DBG, "ptk %x %x %x\n", g_key_ptk_params.key[0], - g_key_ptk_params.key[1], - g_key_ptk_params.key[2]); - PRINT_D(CFG80211_DBG, "gtk %x %x %x\n", g_key_gtk_params.key[0], - g_key_gtk_params.key[1], - g_key_gtk_params.key[2]); - add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy, - wl->vif[0]->ndev, - g_add_ptk_key_params.key_idx, - g_add_ptk_key_params.pairwise, - g_add_ptk_key_params.mac_addr, - (struct key_params *)(&g_key_ptk_params)); - - add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy, - wl->vif[0]->ndev, - g_add_gtk_key_params.key_idx, - g_add_gtk_key_params.pairwise, - g_add_gtk_key_params.mac_addr, - (struct key_params *)(&g_key_gtk_params)); - } - - if (wl->initialized) { - for (i = 0; i < num_reg_frame; i++) { - PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", vif->g_struct_frame_reg[i].frame_type, - vif->g_struct_frame_reg[i].reg); - wilc_frame_register(vif, - vif->g_struct_frame_reg[i].frame_type, - vif->g_struct_frame_reg[i].reg); - } - } - wilc_enable_ps = true; - wilc_set_power_mgmt(vif, 1, 0); - } + wilc_enable_ps = true; + wilc_set_power_mgmt(vif, 1, 0); break; case NL80211_IFTYPE_P2P_CLIENT: @@ -2201,73 +2136,11 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, wilc_connecting = 0; PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_P2P_CLIENT\n"); - wilc_del_all_rx_ba_session(vif, wl->vif[0]->bssid, TID); - dev->ieee80211_ptr->iftype = type; priv->wdev->iftype = type; vif->monitor_flag = 0; - - PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n"); vif->iftype = CLIENT_MODE; - - - if (wl->initialized) { - wilc_wait_msg_queue_idle(); - - wilc1000_wlan_deinit(dev); - wilc1000_wlan_init(dev, vif); - wilc_initialized = 1; - - wilc_set_wfi_drv_handler(vif, - wilc_get_vif_idx(wl->vif[0])); - wilc_set_mac_address(wl->vif[0], wl->vif[0]->src_addr); - wilc_set_operation_mode(vif, STATION_MODE); - - if (g_wep_keys_saved) { - wilc_set_wep_default_keyid(wl->vif[0], - g_key_wep_params.key_idx); - wilc_add_wep_key_bss_sta(wl->vif[0], - g_key_wep_params.key, - g_key_wep_params.key_len, - g_key_wep_params.key_idx); - } - - wilc_flush_join_req(vif); - - if (g_ptk_keys_saved && g_gtk_keys_saved) { - PRINT_D(CFG80211_DBG, "ptk %x %x %x\n", g_key_ptk_params.key[0], - g_key_ptk_params.key[1], - g_key_ptk_params.key[2]); - PRINT_D(CFG80211_DBG, "gtk %x %x %x\n", g_key_gtk_params.key[0], - g_key_gtk_params.key[1], - g_key_gtk_params.key[2]); - add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy, - wl->vif[0]->ndev, - g_add_ptk_key_params.key_idx, - g_add_ptk_key_params.pairwise, - g_add_ptk_key_params.mac_addr, - (struct key_params *)(&g_key_ptk_params)); - - add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy, - wl->vif[0]->ndev, - g_add_gtk_key_params.key_idx, - g_add_gtk_key_params.pairwise, - g_add_gtk_key_params.mac_addr, - (struct key_params *)(&g_key_gtk_params)); - } - - refresh_scan(priv, 1, true); - - if (wl->initialized) { - for (i = 0; i < num_reg_frame; i++) { - PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", vif->g_struct_frame_reg[i].frame_type, - vif->g_struct_frame_reg[i].reg); - wilc_frame_register(vif, - vif->g_struct_frame_reg[i].frame_type, - vif->g_struct_frame_reg[i].reg); - } - } - } + wilc_set_operation_mode(vif, STATION_MODE); break; case NL80211_IFTYPE_AP: @@ -2276,23 +2149,11 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, dev->ieee80211_ptr->iftype = type; priv->wdev->iftype = type; vif->iftype = AP_MODE; - PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv); - - PRINT_D(HOSTAPD_DBG, "Downloading AP firmware\n"); - wilc_wlan_get_firmware(dev); - - if (wl->initialized) { - vif->iftype = AP_MODE; - wilc_mac_close(dev); - wilc_mac_open(dev); - - for (i = 0; i < num_reg_frame; i++) { - PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", vif->g_struct_frame_reg[i].frame_type, - vif->g_struct_frame_reg[i].reg); - wilc_frame_register(vif, - vif->g_struct_frame_reg[i].frame_type, - vif->g_struct_frame_reg[i].reg); - } + + if (wl->initialized) { + wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif)); + wilc_set_operation_mode(vif, AP_MODE); + wilc_set_power_mgmt(vif, 0, 0); } break; @@ -2303,72 +2164,13 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, mod_timer(&wilc_during_ip_timer, jiffies + msecs_to_jiffies(during_ip_time)); wilc_set_power_mgmt(vif, 0, 0); - wilc_del_all_rx_ba_session(vif, wl->vif[0]->bssid, TID); wilc_enable_ps = false; PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_GO\n"); + + wilc_set_operation_mode(vif, AP_MODE); dev->ieee80211_ptr->iftype = type; priv->wdev->iftype = type; - - PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv); - - PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n"); - - vif->iftype = GO_MODE; - - wilc_wait_msg_queue_idle(); - wilc1000_wlan_deinit(dev); - wilc1000_wlan_init(dev, vif); - wilc_initialized = 1; - - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(wl->vif[0])); - wilc_set_mac_address(wl->vif[0], wl->vif[0]->src_addr); - wilc_set_operation_mode(vif, AP_MODE); - - if (g_wep_keys_saved) { - wilc_set_wep_default_keyid(wl->vif[0], - g_key_wep_params.key_idx); - wilc_add_wep_key_bss_sta(wl->vif[0], - g_key_wep_params.key, - g_key_wep_params.key_len, - g_key_wep_params.key_idx); - } - - wilc_flush_join_req(vif); - - if (g_ptk_keys_saved && g_gtk_keys_saved) { - PRINT_D(CFG80211_DBG, "ptk %x %x %x cipher %x\n", g_key_ptk_params.key[0], - g_key_ptk_params.key[1], - g_key_ptk_params.key[2], - g_key_ptk_params.cipher); - PRINT_D(CFG80211_DBG, "gtk %x %x %x cipher %x\n", g_key_gtk_params.key[0], - g_key_gtk_params.key[1], - g_key_gtk_params.key[2], - g_key_gtk_params.cipher); - add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy, - wl->vif[0]->ndev, - g_add_ptk_key_params.key_idx, - g_add_ptk_key_params.pairwise, - g_add_ptk_key_params.mac_addr, - (struct key_params *)(&g_key_ptk_params)); - - add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy, - wl->vif[0]->ndev, - g_add_gtk_key_params.key_idx, - g_add_gtk_key_params.pairwise, - g_add_gtk_key_params.mac_addr, - (struct key_params *)(&g_key_gtk_params)); - } - - if (wl->initialized) { - for (i = 0; i < num_reg_frame; i++) { - PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", vif->g_struct_frame_reg[i].frame_type, - vif->g_struct_frame_reg[i].reg); - wilc_frame_register(vif, - vif->g_struct_frame_reg[i].frame_type, - vif->g_struct_frame_reg[i].reg); - } - } break; default: -- cgit v1.2.3 From ee632309208c823419429d9a3b9702144a756431 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:18 +0900 Subject: staging: wilc1000: call power save after changing mode host_int_set_power_mgmt should be called after changing operation mode to work properly. Move the function below host_int_set_operation_mode. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index d282a871ddcb..4eede2b4e661 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2131,8 +2131,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, break; case NL80211_IFTYPE_P2P_CLIENT: - wilc_enable_ps = false; - wilc_set_power_mgmt(vif, 0, 0); wilc_connecting = 0; PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_P2P_CLIENT\n"); @@ -2141,6 +2139,9 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, vif->monitor_flag = 0; vif->iftype = CLIENT_MODE; wilc_set_operation_mode(vif, STATION_MODE); + + wilc_enable_ps = false; + wilc_set_power_mgmt(vif, 0, 0); break; case NL80211_IFTYPE_AP: @@ -2163,14 +2164,15 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, wilc_optaining_ip = true; mod_timer(&wilc_during_ip_timer, jiffies + msecs_to_jiffies(during_ip_time)); - wilc_set_power_mgmt(vif, 0, 0); - wilc_enable_ps = false; PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_GO\n"); wilc_set_operation_mode(vif, AP_MODE); dev->ieee80211_ptr->iftype = type; priv->wdev->iftype = type; vif->iftype = GO_MODE; + + wilc_enable_ps = false; + wilc_set_power_mgmt(vif, 0, 0); break; default: -- cgit v1.2.3 From 4cf93d706fb9178cd9c8366c958b52a4ebca41f0 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 26 Jan 2016 18:50:00 +0900 Subject: staging: wilc1000: fix alignment for open parenthesis This patch fixes the check found by checkpatch.pl CHECK: Alignment should match open parenthesis Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 90 +++++++++++++++---------------- 1 file changed, 45 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 79e8b7aa482b..d77e2b2bea3d 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -303,7 +303,7 @@ static s32 handle_set_channel(struct wilc_vif *vif, PRINT_D(HOSTINF_DBG, "Setting channel\n"); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to set channel\n"); @@ -350,7 +350,7 @@ static s32 handle_set_operation_mode(struct wilc_vif *vif, wid.size = sizeof(u32); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if ((hif_op_mode->mode) == IDLE_MODE) up(&hif_sema_driver); @@ -383,7 +383,7 @@ static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) wid.size = IP_ALEN; result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); host_int_get_ipaddress(vif, firmware_ip_addr, idx); @@ -408,7 +408,7 @@ static s32 handle_get_ip_address(struct wilc_vif *vif, u8 idx) wid.size = IP_ALEN; result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); PRINT_INFO(HOSTINF_DBG, "%pI4\n", wid.val); @@ -451,7 +451,7 @@ static s32 handle_set_mac_address(struct wilc_vif *vif, PRINT_D(GENERIC_DBG, "mac addr = :%pM\n", wid.val); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to set mac address\n"); result = -EFAULT; @@ -473,7 +473,7 @@ static s32 handle_get_mac_address(struct wilc_vif *vif, wid.size = ETH_ALEN; result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to get mac address\n"); @@ -939,7 +939,7 @@ static s32 Handle_ScanDone(struct wilc_vif *vif, wid.size = sizeof(char); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to set abort running scan\n"); @@ -1356,7 +1356,7 @@ static s32 Handle_ConnectTimeout(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Sending disconnect request\n"); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send dissconect config packet\n"); @@ -1750,8 +1750,8 @@ static int Handle_Key(struct wilc_vif *vif, strWIDList[3].val = (s8 *)pu8keybuf; result = wilc_send_config_pkt(vif->wilc, SET_CFG, - strWIDList, 4, - wilc_get_vif_idx(vif)); + strWIDList, 4, + wilc_get_vif_idx(vif)); kfree(pu8keybuf); } else if (pstrHostIFkeyAttr->action & ADDKEY) { PRINT_D(HOSTINF_DBG, "Handling WEP key\n"); @@ -1772,8 +1772,8 @@ static int Handle_Key(struct wilc_vif *vif, wid.size = pstrHostIFkeyAttr->attr.wep.key_len + 2; result = wilc_send_config_pkt(vif->wilc, SET_CFG, - &wid, 1, - wilc_get_vif_idx(vif)); + &wid, 1, + wilc_get_vif_idx(vif)); kfree(pu8keybuf); } else if (pstrHostIFkeyAttr->action & REMOVEKEY) { PRINT_D(HOSTINF_DBG, "Removing key\n"); @@ -1785,8 +1785,8 @@ static int Handle_Key(struct wilc_vif *vif, wid.size = 1; result = wilc_send_config_pkt(vif->wilc, SET_CFG, - &wid, 1, - wilc_get_vif_idx(vif)); + &wid, 1, + wilc_get_vif_idx(vif)); } else { wid.id = (u16)WID_KEY_ID; wid.type = WID_CHAR; @@ -1796,8 +1796,8 @@ static int Handle_Key(struct wilc_vif *vif, PRINT_D(HOSTINF_DBG, "Setting default key index\n"); result = wilc_send_config_pkt(vif->wilc, SET_CFG, - &wid, 1, - wilc_get_vif_idx(vif)); + &wid, 1, + wilc_get_vif_idx(vif)); } up(&hif_drv->sem_test_key_block); break; @@ -1830,8 +1830,8 @@ static int Handle_Key(struct wilc_vif *vif, strWIDList[1].size = RX_MIC_KEY_MSG_LEN; result = wilc_send_config_pkt(vif->wilc, SET_CFG, - strWIDList, 2, - wilc_get_vif_idx(vif)); + strWIDList, 2, + wilc_get_vif_idx(vif)); kfree(pu8keybuf); up(&hif_drv->sem_test_key_block); @@ -1862,8 +1862,8 @@ static int Handle_Key(struct wilc_vif *vif, wid.size = RX_MIC_KEY_MSG_LEN; result = wilc_send_config_pkt(vif->wilc, SET_CFG, - &wid, 1, - wilc_get_vif_idx(vif)); + &wid, 1, + wilc_get_vif_idx(vif)); kfree(pu8keybuf); up(&hif_drv->sem_test_key_block); @@ -1902,8 +1902,8 @@ _WPARxGtk_end_case_: strWIDList[1].size = PTK_KEY_MSG_LEN + 1; result = wilc_send_config_pkt(vif->wilc, SET_CFG, - strWIDList, 2, - wilc_get_vif_idx(vif)); + strWIDList, 2, + wilc_get_vif_idx(vif)); kfree(pu8keybuf); up(&hif_drv->sem_test_key_block); } else if (pstrHostIFkeyAttr->action & ADDKEY) { @@ -1925,8 +1925,8 @@ _WPARxGtk_end_case_: wid.size = PTK_KEY_MSG_LEN; result = wilc_send_config_pkt(vif->wilc, SET_CFG, - &wid, 1, - wilc_get_vif_idx(vif)); + &wid, 1, + wilc_get_vif_idx(vif)); kfree(pu8keybuf); up(&hif_drv->sem_test_key_block); } @@ -1961,7 +1961,7 @@ _WPAPtk_end_case_: wid.size = (pstrHostIFkeyAttr->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1; result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); kfree(pu8keybuf); break; @@ -1994,7 +1994,7 @@ static void Handle_Disconnect(struct wilc_vif *vif) eth_zero_addr(wilc_connected_ssid); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to send dissconect config packet\n"); @@ -2085,7 +2085,7 @@ static s32 Handle_GetChnl(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Getting channel value\n"); result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to get channel number\n"); @@ -2110,7 +2110,7 @@ static void Handle_GetRssi(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Getting RSSI value\n"); result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to get RSSI value\n"); result = -EFAULT; @@ -2135,7 +2135,7 @@ static void Handle_GetLinkspeed(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Getting LINKSPEED value\n"); result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to get LINKSPEED value\n"); result = -EFAULT; @@ -2181,8 +2181,8 @@ static s32 Handle_GetStatistics(struct wilc_vif *vif, u32WidsCount++; result = wilc_send_config_pkt(vif->wilc, GET_CFG, strWIDList, - u32WidsCount, - wilc_get_vif_idx(vif)); + u32WidsCount, + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send scan paramters config packet\n"); @@ -2210,7 +2210,7 @@ static s32 Handle_Get_InActiveTime(struct wilc_vif *vif, PRINT_D(CFG80211_DBG, "SETING STA inactive time\n"); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to SET incative time\n"); @@ -2223,7 +2223,7 @@ static s32 Handle_Get_InActiveTime(struct wilc_vif *vif, wid.size = sizeof(u32); result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to get incative time\n"); @@ -2311,7 +2311,7 @@ static void Handle_DelBeacon(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Deleting BEACON\n"); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send delete beacon config packet\n"); } @@ -2384,7 +2384,7 @@ static void Handle_AddStation(struct wilc_vif *vif, pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result != 0) PRINT_ER("Failed to send add station config packet\n"); @@ -2426,7 +2426,7 @@ static void Handle_DelAllSta(struct wilc_vif *vif, } result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send add station config packet\n"); @@ -2458,7 +2458,7 @@ static void Handle_DelStation(struct wilc_vif *vif, memcpy(pu8CurrByte, pstrDelStaParam->mac_addr, ETH_ALEN); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send add station config packet\n"); @@ -2486,7 +2486,7 @@ static void Handle_EditStation(struct wilc_vif *vif, pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send edit station config packet\n"); @@ -2548,7 +2548,7 @@ static int Handle_RemainOnChan(struct wilc_vif *vif, wid.val[1] = (s8)pstrHostIfRemainOnChan->ch; result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result != 0) PRINT_ER("Failed to set remain on channel\n"); @@ -2596,7 +2596,7 @@ static int Handle_RegisterFrame(struct wilc_vif *vif, wid.size = sizeof(u16) + 2; result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to frame register config packet\n"); result = -EINVAL; @@ -2631,7 +2631,7 @@ static u32 Handle_ListenStateExpired(struct wilc_vif *vif, wid.val[1] = FALSE_FRMWR_CHANNEL; result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result != 0) { PRINT_ER("Failed to set remain on channel\n"); goto _done_; @@ -2689,7 +2689,7 @@ static void Handle_PowerManagement(struct wilc_vif *vif, PRINT_D(HOSTINF_DBG, "Handling Power Management\n"); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send power management config packet\n"); } @@ -2726,7 +2726,7 @@ static void Handle_SetMulticastFilter(struct wilc_vif *vif, ((strHostIfSetMulti->cnt) * ETH_ALEN)); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send setup multicast config packet\n"); @@ -2762,7 +2762,7 @@ static s32 Handle_DelAllRxBASessions(struct wilc_vif *vif, *ptr++ = 32; result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) PRINT_D(HOSTINF_DBG, "Couldn't delete BA Session\n"); @@ -3502,7 +3502,7 @@ static s32 host_int_get_assoc_res_info(struct wilc_vif *vif, wid.size = u32MaxAssocRespInfoLen; result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { *pu32RcvdAssocRespInfoLen = 0; PRINT_ER("Failed to send association response config packet\n"); -- cgit v1.2.3 From 0953a2e33b0fca7db82081f85eb7ed6b4b76a669 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Wed, 27 Jan 2016 11:50:25 +0900 Subject: staging: wilc1000: wilc_frmw_to_linux(): fixes null check Null checking wilc_netdev and skb->dev are already done in the begining of the function and they are just print printing error log, so delete them. Null checking wilc is needed before is used so add null ckeck before it is used. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 2489ea30855c..505b1233386c 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1322,6 +1322,9 @@ void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset) struct net_device *wilc_netdev; struct wilc_vif *vif; + if (!wilc) + return; + wilc_netdev = get_if_handler(wilc, buff); if (!wilc_netdev) return; @@ -1338,14 +1341,8 @@ void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset) PRINT_ER("Low memory - packet droped\n"); return; } - - if (!wilc || !wilc_netdev) - PRINT_ER("wilc_netdev in wilc is NULL"); skb->dev = wilc_netdev; - if (!skb->dev) - PRINT_ER("skb->dev is NULL\n"); - memcpy(skb_put(skb, frame_len), buff_to_send, frame_len); skb->protocol = eth_type_trans(skb, wilc_netdev); -- cgit v1.2.3 From f05ab24945fcf66089a3c8276239ba50c121d7ab Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Wed, 27 Jan 2016 11:50:26 +0900 Subject: staging: wilc1000: fixes no space is necessary after a cast This patch fixes the check reported by checkpatch.pl for 'no space is necessary after a cast'. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 505b1233386c..6b0800bd26ea 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1267,7 +1267,7 @@ static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd) switch (cmd) { case SIOCSIWPRIV: { - struct iwreq *wrq = (struct iwreq *) req; + struct iwreq *wrq = (struct iwreq *)req; size = wrq->u.data.length; -- cgit v1.2.3 From 40095ad9ecdc17b4f8cd7a4da67579ac64c26a95 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Wed, 27 Jan 2016 11:50:27 +0900 Subject: staging: wilc1000: fixes add spaces required around This patch fixes the checks reported by checkpatch.pl for spaces required around that '=' or '||' or '('. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 6b0800bd26ea..b368c2d9bf14 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -993,7 +993,7 @@ int wilc_mac_open(struct net_device *ndev) vif = netdev_priv(ndev); wl = vif->wilc; - if (!wl|| !wl->dev) { + if (!wl || !wl->dev) { netdev_err(ndev, "wilc1000: SPI device not ready\n"); return -ENODEV; } @@ -1054,7 +1054,7 @@ int wilc_mac_open(struct net_device *ndev) static struct net_device_stats *mac_stats(struct net_device *dev) { - struct wilc_vif *vif= netdev_priv(dev); + struct wilc_vif *vif = netdev_priv(dev); return &vif->netstats; } -- cgit v1.2.3 From 43b36e42a55cf9cd669a1f29ef1db46c5ea37908 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 28 Jan 2016 16:13:35 +0900 Subject: staging: wilc1000: coreconfigurator.c : remove over-commenting There are over-commenting in the coreconfigurator.c file and most of them are not helpful to explain what the code does and generate 80 ending line over warnings. So, all of comments are removed in this patch and the comments will later be added if necessary with the preferred Linux style. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 141 +--------------------------- 1 file changed, 1 insertion(+), 140 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 2d4d3f190c01..e6f50bac4b90 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -1,13 +1,3 @@ - -/*! - * @file coreconfigurator.c - * @brief - * @author - * @sa coreconfigurator.h - * @date 1 Mar 2012 - * @version 1.0 - */ - #include "coreconfigurator.h" #include "wilc_wlan_if.h" #include "wilc_wlan.h" @@ -16,7 +6,6 @@ #define TAG_PARAM_OFFSET (MAC_HDR_LEN + TIME_STAMP_LEN + \ BEACON_INTERVAL_LEN + CAP_INFO_LEN) -/* Basic Frame Type Codes (2-bit) */ enum basic_frame_type { FRAME_TYPE_CONTROL = 0x04, FRAME_TYPE_DATA = 0x08, @@ -25,7 +14,6 @@ enum basic_frame_type { FRAME_TYPE_FORCE_32BIT = 0xFFFFFFFF }; -/* Frame Type and Subtype Codes (6-bit) */ enum sub_frame_type { ASSOC_REQ = 0x00, ASSOC_RSP = 0x10, @@ -65,7 +53,6 @@ enum sub_frame_type { FRAME_SUBTYPE_FORCE_32BIT = 0xFFFFFFFF }; -/* Element ID of various Information Elements */ enum info_element_id { ISSID = 0, /* Service Set Identifier */ ISUPRATES = 1, /* Supported Rates */ @@ -109,8 +96,6 @@ enum info_element_id { INFOELEM_ID_FORCE_32BIT = 0xFFFFFFFF }; -/* This function extracts the beacon period field from the beacon or probe */ -/* response frame. */ static inline u16 get_beacon_period(u8 *data) { u16 bcn_per; @@ -147,54 +132,36 @@ static inline u32 get_beacon_timestamp_hi(u8 *data) return time_stamp; } -/* This function extracts the 'frame type and sub type' bits from the MAC */ -/* header of the input frame. */ -/* Returns the value in the LSB of the returned value. */ static inline enum sub_frame_type get_sub_type(u8 *header) { return ((enum sub_frame_type)(header[0] & 0xFC)); } -/* This function extracts the 'to ds' bit from the MAC header of the input */ -/* frame. */ -/* Returns the value in the LSB of the returned value. */ static inline u8 get_to_ds(u8 *header) { return (header[1] & 0x01); } -/* This function extracts the 'from ds' bit from the MAC header of the input */ -/* frame. */ -/* Returns the value in the LSB of the returned value. */ static inline u8 get_from_ds(u8 *header) { return ((header[1] & 0x02) >> 1); } -/* This function extracts the MAC Address in 'address1' field of the MAC */ -/* header and updates the MAC Address in the allocated 'addr' variable. */ static inline void get_address1(u8 *pu8msa, u8 *addr) { memcpy(addr, pu8msa + 4, 6); } -/* This function extracts the MAC Address in 'address2' field of the MAC */ -/* header and updates the MAC Address in the allocated 'addr' variable. */ static inline void get_address2(u8 *pu8msa, u8 *addr) { memcpy(addr, pu8msa + 10, 6); } -/* This function extracts the MAC Address in 'address3' field of the MAC */ -/* header and updates the MAC Address in the allocated 'addr' variable. */ static inline void get_address3(u8 *pu8msa, u8 *addr) { memcpy(addr, pu8msa + 16, 6); } -/* This function extracts the BSSID from the incoming WLAN packet based on */ -/* the 'from ds' bit, and updates the MAC Address in the allocated 'addr' */ -/* variable. */ static inline void get_BSSID(u8 *data, u8 *bssid) { if (get_from_ds(data) == 1) @@ -205,7 +172,6 @@ static inline void get_BSSID(u8 *data, u8 *bssid) get_address3(data, bssid); } -/* This function extracts the SSID from a beacon/probe response frame */ static inline void get_ssid(u8 *data, u8 *ssid, u8 *p_ssid_len) { u8 len = 0; @@ -217,8 +183,6 @@ static inline void get_ssid(u8 *data, u8 *ssid, u8 *p_ssid_len) j = MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN + 2; - /* If the SSID length field is set wrongly to a value greater than the */ - /* allowed maximum SSID length limit, reset the length to 0 */ if (len >= MAX_SSID_LEN) len = 0; @@ -230,8 +194,6 @@ static inline void get_ssid(u8 *data, u8 *ssid, u8 *p_ssid_len) *p_ssid_len = len; } -/* This function extracts the capability info field from the beacon or probe */ -/* response frame. */ static inline u16 get_cap_info(u8 *data) { u16 cap_info = 0; @@ -240,8 +202,6 @@ static inline u16 get_cap_info(u8 *data) st = get_sub_type(data); - /* Location of the Capability field is different for Beacon and */ - /* Association frames. */ if ((st == BEACON) || (st == PROBE_RSP)) index += TIME_STAMP_LEN + BEACON_INTERVAL_LEN; @@ -251,8 +211,6 @@ static inline u16 get_cap_info(u8 *data) return cap_info; } -/* This function extracts the capability info field from the Association */ -/* response frame. */ static inline u16 get_assoc_resp_cap_info(u8 *data) { u16 cap_info; @@ -263,8 +221,6 @@ static inline u16 get_assoc_resp_cap_info(u8 *data) return cap_info; } -/* This function extracts the association status code from the incoming */ -/* association response frame and returns association status code */ static inline u16 get_asoc_status(u8 *data) { u16 asoc_status; @@ -275,8 +231,6 @@ static inline u16 get_asoc_status(u8 *data) return asoc_status; } -/* This function extracts association ID from the incoming association */ -/* response frame */ static inline u16 get_asoc_id(u8 *data) { u16 asoc_id; @@ -291,19 +245,8 @@ static u8 *get_tim_elm(u8 *pu8msa, u16 u16RxLen, u16 u16TagParamOffset) { u16 u16index; - /*************************************************************************/ - /* Beacon Frame - Frame Body */ - /* --------------------------------------------------------------------- */ - /* |Timestamp |BeaconInt |CapInfo |SSID |SupRates |DSParSet |TIM elm | */ - /* --------------------------------------------------------------------- */ - /* |8 |2 |2 |2-34 |3-10 |3 |4-256 | */ - /* --------------------------------------------------------------------- */ - /* */ - /*************************************************************************/ - u16index = u16TagParamOffset; - /* Search for the TIM Element Field and return if the element is found */ while (u16index < (u16RxLen - FCS_LEN)) { if (pu8msa[u16index] == ITIM) return &pu8msa[u16index]; @@ -313,8 +256,6 @@ static u8 *get_tim_elm(u8 *pu8msa, u16 u16RxLen, u16 u16TagParamOffset) return NULL; } -/* This function gets the current channel information from - * the 802.11n beacon/probe response frame */ static u8 get_current_channel_802_11n(u8 *pu8msa, u16 u16RxLen) { u16 index; @@ -323,27 +264,12 @@ static u8 get_current_channel_802_11n(u8 *pu8msa, u16 u16RxLen) while (index < (u16RxLen - FCS_LEN)) { if (pu8msa[index] == IDSPARMS) return pu8msa[index + 2]; - /* Increment index by length information and header */ index += pu8msa[index + 1] + IE_HDR_LEN; } - /* Return current channel information from the MIB, if beacon/probe */ - /* response frame does not contain the DS parameter set IE */ - /* return (mget_CurrentChannel() + 1); */ - return 0; /* no MIB here */ + return 0; } -/** - * @brief parses the received 'N' message - * @details - * @param[in] pu8MsgBuffer The message to be parsed - * @param[out] ppstrNetworkInfo pointer to pointer to the structure containing the parsed Network Info - * @return Error code indicating success/failure - * @note - * @author mabubakr - * @date 1 Mar 2012 - * @version 1.0 - */ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo) { tstrNetworkInfo *pstrNetworkInfo = NULL; @@ -357,28 +283,17 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo u8MsgType = pu8MsgBuffer[0]; - /* Check whether the received message type is 'N' */ if ('N' != u8MsgType) { PRINT_ER("Received Message format incorrect.\n"); return -EFAULT; } - /* Extract message ID */ u8MsgID = pu8MsgBuffer[1]; - - /* Extract message Length */ u16MsgLen = MAKE_WORD16(pu8MsgBuffer[2], pu8MsgBuffer[3]); - - /* Extract WID ID */ u16WidID = MAKE_WORD16(pu8MsgBuffer[4], pu8MsgBuffer[5]); - - /* Extract WID Length */ u16WidLen = MAKE_WORD16(pu8MsgBuffer[6], pu8MsgBuffer[7]); - - /* Assign a pointer to the WID value */ pu8WidVal = &pu8MsgBuffer[8]; - /* parse the WID value of the WID "WID_NEWORK_INFO" */ { u8 *pu8msa = NULL; u16 u16RxLen = 0; @@ -395,46 +310,30 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo pstrNetworkInfo->s8rssi = pu8WidVal[0]; - /* Assign a pointer to msa "Mac Header Start Address" */ pu8msa = &pu8WidVal[1]; u16RxLen = u16WidLen - 1; - - /* parse msa*/ - - /* Get the cap_info */ pstrNetworkInfo->u16CapInfo = get_cap_info(pu8msa); - /* Get time-stamp [Low only 32 bit] */ pstrNetworkInfo->u32Tsf = get_beacon_timestamp_lo(pu8msa); PRINT_D(CORECONFIG_DBG, "TSF :%x\n", pstrNetworkInfo->u32Tsf); - /* Get full time-stamp [Low and High 64 bit] */ u32Tsf_Lo = get_beacon_timestamp_lo(pu8msa); u32Tsf_Hi = get_beacon_timestamp_hi(pu8msa); pstrNetworkInfo->u64Tsf = u32Tsf_Lo | ((u64)u32Tsf_Hi << 32); - /* Get SSID */ get_ssid(pu8msa, pstrNetworkInfo->au8ssid, &pstrNetworkInfo->u8SsidLen); - - /* Get BSSID */ get_BSSID(pu8msa, pstrNetworkInfo->au8bssid); - /* - * Extract current channel information from - * the beacon/probe response frame - */ pstrNetworkInfo->u8channel = get_current_channel_802_11n(pu8msa, u16RxLen + FCS_LEN); - /* Get beacon period */ u8index = MAC_HDR_LEN + TIME_STAMP_LEN; pstrNetworkInfo->u16BeaconPeriod = get_beacon_period(pu8msa + u8index); u8index += BEACON_INTERVAL_LEN + CAP_INFO_LEN; - /* Get DTIM Period */ pu8TimElm = get_tim_elm(pu8msa, u16RxLen + FCS_LEN, u8index); if (pu8TimElm) pstrNetworkInfo->u8DtimPeriod = pu8TimElm[3]; @@ -456,16 +355,6 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo return 0; } -/** - * @brief Deallocates the parsed Network Info - * @details - * @param[in] pstrNetworkInfo Network Info to be deallocated - * @return Error code indicating success/failure - * @note - * @author mabubakr - * @date 1 Mar 2012 - * @version 1.0 - */ s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo) { s32 s32Error = 0; @@ -488,17 +377,6 @@ s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo) return s32Error; } -/** - * @brief parses the received Association Response frame - * @details - * @param[in] pu8Buffer The Association Response frame to be parsed - * @param[out] ppstrConnectRespInfo pointer to pointer to the structure containing the parsed Association Response Info - * @return Error code indicating success/failure - * @note - * @author mabubakr - * @date 2 Apr 2012 - * @version 1.0 - */ s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, tstrConnectRespInfo **ppstrConnectRespInfo) { @@ -512,20 +390,13 @@ s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, if (!pstrConnectRespInfo) return -ENOMEM; - /* u16AssocRespLen = pu8Buffer[0]; */ u16AssocRespLen = (u16)u32BufferLen; - /* get the status code */ pstrConnectRespInfo->u16ConnectStatus = get_asoc_status(pu8Buffer); if (pstrConnectRespInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE) { - - /* get the capability */ pstrConnectRespInfo->u16capability = get_assoc_resp_cap_info(pu8Buffer); - - /* get the Association ID */ pstrConnectRespInfo->u16AssocID = get_asoc_id(pu8Buffer); - /* get the Information Elements */ pu8IEs = &pu8Buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN]; u16IEsLen = u16AssocRespLen - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN); @@ -541,16 +412,6 @@ s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, return s32Error; } -/** - * @brief Deallocates the parsed Association Response Info - * @details - * @param[in] pstrNetworkInfo Network Info to be deallocated - * @return Error code indicating success/failure - * @note - * @author mabubakr - * @date 2 Apr 2012 - * @version 1.0 - */ s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *pstrConnectRespInfo) { s32 s32Error = 0; -- cgit v1.2.3 From e1a9db87a6cfa357c02cbcbaf9c351571b237c41 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 28 Jan 2016 16:13:36 +0900 Subject: staging: wilc1000: renames u16RxLen variable This patch renames u16RxLen variable to rx_len to avoid camelcase. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index e6f50bac4b90..ed626b8fa9a0 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -241,13 +241,13 @@ static inline u16 get_asoc_id(u8 *data) return asoc_id; } -static u8 *get_tim_elm(u8 *pu8msa, u16 u16RxLen, u16 u16TagParamOffset) +static u8 *get_tim_elm(u8 *pu8msa, u16 rx_len, u16 u16TagParamOffset) { u16 u16index; u16index = u16TagParamOffset; - while (u16index < (u16RxLen - FCS_LEN)) { + while (u16index < (rx_len - FCS_LEN)) { if (pu8msa[u16index] == ITIM) return &pu8msa[u16index]; u16index += (IE_HDR_LEN + pu8msa[u16index + 1]); @@ -256,12 +256,12 @@ static u8 *get_tim_elm(u8 *pu8msa, u16 u16RxLen, u16 u16TagParamOffset) return NULL; } -static u8 get_current_channel_802_11n(u8 *pu8msa, u16 u16RxLen) +static u8 get_current_channel_802_11n(u8 *pu8msa, u16 rx_len) { u16 index; index = TAG_PARAM_OFFSET; - while (index < (u16RxLen - FCS_LEN)) { + while (index < (rx_len - FCS_LEN)) { if (pu8msa[index] == IDSPARMS) return pu8msa[index + 2]; index += pu8msa[index + 1] + IE_HDR_LEN; @@ -296,7 +296,7 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo { u8 *pu8msa = NULL; - u16 u16RxLen = 0; + u16 rx_len = 0; u8 *pu8TimElm = NULL; u8 *pu8IEs = NULL; u16 u16IEsLen = 0; @@ -312,7 +312,7 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo pu8msa = &pu8WidVal[1]; - u16RxLen = u16WidLen - 1; + rx_len = u16WidLen - 1; pstrNetworkInfo->u16CapInfo = get_cap_info(pu8msa); pstrNetworkInfo->u32Tsf = get_beacon_timestamp_lo(pu8msa); PRINT_D(CORECONFIG_DBG, "TSF :%x\n", pstrNetworkInfo->u32Tsf); @@ -326,7 +326,7 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo get_BSSID(pu8msa, pstrNetworkInfo->au8bssid); pstrNetworkInfo->u8channel = get_current_channel_802_11n(pu8msa, - u16RxLen + FCS_LEN); + rx_len + FCS_LEN); u8index = MAC_HDR_LEN + TIME_STAMP_LEN; @@ -334,11 +334,11 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo u8index += BEACON_INTERVAL_LEN + CAP_INFO_LEN; - pu8TimElm = get_tim_elm(pu8msa, u16RxLen + FCS_LEN, u8index); + pu8TimElm = get_tim_elm(pu8msa, rx_len + FCS_LEN, u8index); if (pu8TimElm) pstrNetworkInfo->u8DtimPeriod = pu8TimElm[3]; pu8IEs = &pu8msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN]; - u16IEsLen = u16RxLen - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); + u16IEsLen = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); if (u16IEsLen > 0) { pstrNetworkInfo->pu8IEs = kmemdup(pu8IEs, u16IEsLen, -- cgit v1.2.3 From 6c25d7cbabb287956643775eabef1a1a2808dcaa Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 28 Jan 2016 16:13:37 +0900 Subject: staging: wilc1000: renames u16TagParamOffset variable This patch renames u16TagParamOffset variable to tag_param_offset to avoid camelcase. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index ed626b8fa9a0..2f790f5a398c 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -241,11 +241,11 @@ static inline u16 get_asoc_id(u8 *data) return asoc_id; } -static u8 *get_tim_elm(u8 *pu8msa, u16 rx_len, u16 u16TagParamOffset) +static u8 *get_tim_elm(u8 *pu8msa, u16 rx_len, u16 tag_param_offset) { u16 u16index; - u16index = u16TagParamOffset; + u16index = tag_param_offset; while (u16index < (rx_len - FCS_LEN)) { if (pu8msa[u16index] == ITIM) -- cgit v1.2.3 From c8a06381501c9b4d9750059967e78ffe6263e537 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 28 Jan 2016 16:13:38 +0900 Subject: staging: wilc1000: renames u16index variable This patch renames u16index variable to index to remove the prefix variable defined name. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 2f790f5a398c..49ae9b152654 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -243,14 +243,14 @@ static inline u16 get_asoc_id(u8 *data) static u8 *get_tim_elm(u8 *pu8msa, u16 rx_len, u16 tag_param_offset) { - u16 u16index; + u16 index; - u16index = tag_param_offset; + index = tag_param_offset; - while (u16index < (rx_len - FCS_LEN)) { - if (pu8msa[u16index] == ITIM) - return &pu8msa[u16index]; - u16index += (IE_HDR_LEN + pu8msa[u16index + 1]); + while (index < (rx_len - FCS_LEN)) { + if (pu8msa[index] == ITIM) + return &pu8msa[index]; + index += (IE_HDR_LEN + pu8msa[index + 1]); } return NULL; -- cgit v1.2.3 From e9670aba93bce75cd6dc78010a8548da793ef1bb Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 29 Jan 2016 23:51:32 +0900 Subject: staging: wilc1000: wilc_msgqueue: use standard struct list_head This patch uses standard struct list_head in struct message and message_queue instead of custom linked list. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 32 ++++++++++++-------------------- drivers/staging/wilc1000/wilc_msgqueue.h | 5 +++-- 2 files changed, 15 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 4493ca9adcce..f57e4ec3c742 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -15,7 +15,7 @@ int wilc_mq_create(struct message_queue *mq) { spin_lock_init(&mq->lock); sema_init(&mq->sem, 0); - mq->msg_list = NULL; + INIT_LIST_HEAD(&mq->msg_list); mq->recv_count = 0; mq->exiting = false; return 0; @@ -29,6 +29,8 @@ int wilc_mq_create(struct message_queue *mq) */ int wilc_mq_destroy(struct message_queue *mq) { + struct message *msg; + mq->exiting = true; /* Release any waiting receiver thread. */ @@ -37,11 +39,10 @@ int wilc_mq_destroy(struct message_queue *mq) mq->recv_count--; } - while (mq->msg_list) { - struct message *msg = mq->msg_list->next; - - kfree(mq->msg_list); - mq->msg_list = msg; + while (!list_empty(&mq->msg_list)) { + msg = list_first_entry(&mq->msg_list, struct message, list); + list_del(&msg->list); + kfree(msg->buf); } return 0; @@ -75,7 +76,7 @@ int wilc_mq_send(struct message_queue *mq, return -ENOMEM; new_msg->len = send_buf_size; - new_msg->next = NULL; + INIT_LIST_HEAD(&new_msg->list); new_msg->buf = kmemdup(send_buf, send_buf_size, GFP_ATOMIC); if (!new_msg->buf) { kfree(new_msg); @@ -85,16 +86,7 @@ int wilc_mq_send(struct message_queue *mq, spin_lock_irqsave(&mq->lock, flags); /* add it to the message queue */ - if (!mq->msg_list) { - mq->msg_list = new_msg; - } else { - struct message *tail_msg = mq->msg_list; - - while (tail_msg->next) - tail_msg = tail_msg->next; - - tail_msg->next = new_msg; - } + list_add_tail(&new_msg->list, &mq->msg_list); spin_unlock_irqrestore(&mq->lock, flags); @@ -132,13 +124,13 @@ int wilc_mq_recv(struct message_queue *mq, down(&mq->sem); spin_lock_irqsave(&mq->lock, flags); - msg = mq->msg_list; - if (!msg) { + if (list_empty(&mq->msg_list)) { spin_unlock_irqrestore(&mq->lock, flags); PRINT_ER("msg is null\n"); return -EFAULT; } /* check buffer size */ + msg = list_first_entry(&mq->msg_list, struct message, list); if (recv_buf_size < msg->len) { spin_unlock_irqrestore(&mq->lock, flags); up(&mq->sem); @@ -151,7 +143,7 @@ int wilc_mq_recv(struct message_queue *mq, memcpy(recv_buf, msg->buf, msg->len); *recv_len = msg->len; - mq->msg_list = msg->next; + list_del(&msg->list); kfree(msg->buf); kfree(msg); diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index ddd0984337ea..846a4840e6e7 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -2,11 +2,12 @@ #define __WILC_MSG_QUEUE_H__ #include +#include struct message { void *buf; u32 len; - struct message *next; + struct list_head list; }; struct message_queue { @@ -14,7 +15,7 @@ struct message_queue { spinlock_t lock; bool exiting; u32 recv_count; - struct message *msg_list; + struct list_head msg_list; }; int wilc_mq_create(struct message_queue *mq); -- cgit v1.2.3 From 8231dfc0879f8f0caecfcdc4b1ebae67cad6878d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 29 Jan 2016 23:51:33 +0900 Subject: staging: wilc1000: wilc_msgqueue: release semaphore in error path It should be called up(&mq->sem) to release semaphore before returning error codes as -EFAULT when list is empty. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index f57e4ec3c742..5fe85eb40146 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -126,6 +126,7 @@ int wilc_mq_recv(struct message_queue *mq, if (list_empty(&mq->msg_list)) { spin_unlock_irqrestore(&mq->lock, flags); + up(&mq->sem); PRINT_ER("msg is null\n"); return -EFAULT; } -- cgit v1.2.3 From d8c7d2b35d156e4faccfe2742b6c58492b60d065 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:37 +0900 Subject: staging: wilc1000: linux_mon: use __packed instead of __attribute__((packed)) This patch fixes the following checkpatch warning: WARNING: __packed is preferred over __attribute__((packed)) Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index e550027645b7..284dfb010f75 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -15,14 +15,14 @@ struct wilc_wfi_radiotap_hdr { struct ieee80211_radiotap_header hdr; u8 rate; -} __attribute__((packed)); +} __packed; struct wilc_wfi_radiotap_cb_hdr { struct ieee80211_radiotap_header hdr; u8 rate; u8 dump; u16 tx_flags; -} __attribute__((packed)); +} __packed; static struct net_device *wilc_wfi_mon; /* global monitor netdev */ -- cgit v1.2.3 From 570549141aec0d21dc93f6d4cd115efe504d8a98 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:38 +0900 Subject: staging: wilc1000: linux_mon: remove blank lines after open brace '{' This patch remove blank lines after open brace found by checkpatch.pl CHECK: Blank lines aren't necessary after an open brace '{' Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 284dfb010f75..73c81134e9cb 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -71,7 +71,6 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) pkt_offset = GET_PKT_OFFSET(header); if (pkt_offset & IS_MANAGMEMENT_CALLBACK) { - /* hostapd callback mgmt frame */ skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_cb_hdr)); @@ -103,7 +102,6 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) } } else { - skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_hdr)); if (skb == NULL) { @@ -145,7 +143,6 @@ struct tx_complete_mon_data { static void mgmt_tx_complete(void *priv, int status) { - struct tx_complete_mon_data *pv_data = (struct tx_complete_mon_data *)priv; u8 *buf = pv_data->buff; @@ -316,8 +313,6 @@ static const struct net_device_ops wilc_wfi_netdev_ops = { */ struct net_device *WILC_WFI_init_mon_interface(const char *name, struct net_device *real_dev) { - - u32 ret = 0; struct WILC_WFI_mon_priv *priv; -- cgit v1.2.3 From c7843469a7c692a5d6e06ba393825b9bf55cd0f7 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:39 +0900 Subject: staging: wilc1000: linux_mon: remove blank line before a close brace '}' This patch removes blank lines before a close brace found by checkpatch.pl CHECK: Blank lines aren't necessary before a close brace '}' Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 73c81134e9cb..bd0b17e1e75d 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -119,7 +119,6 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) (1 << IEEE80211_RADIOTAP_RATE); /* | */ PRINT_INFO(HOSTAPD_DBG, "Presentflags %d\n", hdr->hdr.it_present); hdr->rate = 5; /* txrate->bitrate / 5; */ - } @@ -132,8 +131,6 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) memset(skb->cb, 0, sizeof(skb->cb)); netif_rx(skb); - - } struct tx_complete_mon_data { @@ -183,7 +180,6 @@ static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) PRINT_ER("Failed to allocate memory for mgmt_tx buff\n"); kfree(mgmt_tx); return -EFAULT; - } mgmt_tx->size = len; @@ -325,7 +321,6 @@ struct net_device *WILC_WFI_init_mon_interface(const char *name, struct net_devi if (!wilc_wfi_mon) { PRINT_ER("failed to allocate memory\n"); return NULL; - } wilc_wfi_mon->type = ARPHRD_IEEE80211_RADIOTAP; @@ -379,5 +374,4 @@ int WILC_WFI_deinit_mon_interface(void) wilc_wfi_mon = NULL; } return 0; - } -- cgit v1.2.3 From 24e33bd5d43568c55faf049ae653bfad41f8a472 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:40 +0900 Subject: staging: wilc1000: linux_mon: remove multiple blank lines This patch removes multiple blank lines found by checkpatch.pl CHECK: Please don't use multiple blank lines Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index bd0b17e1e75d..398fdea2ac6e 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -11,7 +11,6 @@ #include "wilc_wlan_if.h" #include "wilc_wlan.h" - struct wilc_wfi_radiotap_hdr { struct ieee80211_radiotap_header hdr; u8 rate; @@ -121,8 +120,6 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) hdr->rate = 5; /* txrate->bitrate / 5; */ } - - skb->dev = wilc_wfi_mon; skb_set_mac_header(skb, 0); skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -143,8 +140,6 @@ static void mgmt_tx_complete(void *priv, int status) struct tx_complete_mon_data *pv_data = (struct tx_complete_mon_data *)priv; u8 *buf = pv_data->buff; - - if (status == 1) { if (INFO || buf[0] == 0x10 || buf[0] == 0xb0) PRINT_INFO(HOSTAPD_DBG, "Packet sent successfully - Size = %d - Address = %p.\n", pv_data->size, pv_data->buff); @@ -152,8 +147,6 @@ static void mgmt_tx_complete(void *priv, int status) PRINT_INFO(HOSTAPD_DBG, "Couldn't send packet - Size = %d - Address = %p.\n", pv_data->size, pv_data->buff); } - - /* incase of fully hosting mode, the freeing will be done in response to the cfg packet */ kfree(pv_data->buff); @@ -220,7 +213,6 @@ static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb, return -EFAULT; } - rtap_len = ieee80211_get_radiotap_len(skb->data); if (skb->len < rtap_len) { PRINT_ER("Error in radiotap header\n"); @@ -273,8 +265,6 @@ static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb, PRINT_INFO(HOSTAPD_DBG, "Skipping the radiotap header\n"); - - /* actual deliver of data is device-specific, and not shown here */ PRINT_INFO(HOSTAPD_DBG, "SKB netdevice name = %s\n", skb->dev->name); PRINT_INFO(HOSTAPD_DBG, "MONITOR real dev name = %s\n", mon_priv->real_ndev->name); -- cgit v1.2.3 From a1436579493a26608318cf0b18f2eed31cd89dd0 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:41 +0900 Subject: staging: wilc1000: linux_mon: fix NULL comparison style This patch fixes NULL comparsion style found by checkpatch.pl CHECK: Comparison to NULL could be written "!wilc_wfi_mon" CHECK: Comparison to NULL could be written "!skb" CHECK: Comparison to NULL could be written "!skb" CHECK: Comparison to NULL could be written "!dev" CHECK: Comparison to NULL could be written "!mgmt_tx" CHECK: Comparison to NULL could be written "!mgmt_tx->buff" CHECK: Comparison to NULL could be written "!wilc_wfi_mon" CHECK: Comparison to NULL could be written "!mon_priv" CHECK: Comparison to NULL could be written "!priv" CHECK: Comparison to NULL could be written "wilc_wfi_mon" Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 398fdea2ac6e..7b9cc02c976b 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -54,7 +54,7 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) PRINT_INFO(HOSTAPD_DBG, "In monitor interface receive function\n"); - if (wilc_wfi_mon == NULL) + if (!wilc_wfi_mon) return; if (!netif_running(wilc_wfi_mon)) { @@ -73,7 +73,7 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) /* hostapd callback mgmt frame */ skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_cb_hdr)); - if (skb == NULL) { + if (!skb) { PRINT_INFO(HOSTAPD_DBG, "Monitor if : No memory to allocate skb"); return; } @@ -103,7 +103,7 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) } else { skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_hdr)); - if (skb == NULL) { + if (!skb) { PRINT_INFO(HOSTAPD_DBG, "Monitor if : No memory to allocate skb"); return; } @@ -156,20 +156,20 @@ static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) { struct tx_complete_mon_data *mgmt_tx = NULL; - if (dev == NULL) { + if (!dev) { PRINT_D(HOSTAPD_DBG, "ERROR: dev == NULL\n"); return -EFAULT; } netif_stop_queue(dev); mgmt_tx = kmalloc(sizeof(struct tx_complete_mon_data), GFP_ATOMIC); - if (mgmt_tx == NULL) { + if (!mgmt_tx) { PRINT_ER("Failed to allocate memory for mgmt_tx structure\n"); return -EFAULT; } mgmt_tx->buff = kmalloc(len, GFP_ATOMIC); - if (mgmt_tx->buff == NULL) { + if (!mgmt_tx->buff) { PRINT_ER("Failed to allocate memory for mgmt_tx buff\n"); kfree(mgmt_tx); return -EFAULT; @@ -203,12 +203,12 @@ static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb, struct sk_buff *skb2; struct wilc_wfi_radiotap_cb_hdr *cb_hdr; - if (wilc_wfi_mon == NULL) + if (!wilc_wfi_mon) return -EFAULT; mon_priv = netdev_priv(wilc_wfi_mon); - if (mon_priv == NULL) { + if (!mon_priv) { PRINT_ER("Monitor interface private structure is NULL\n"); return -EFAULT; } @@ -324,7 +324,7 @@ struct net_device *WILC_WFI_init_mon_interface(const char *name, struct net_devi return NULL; } priv = netdev_priv(wilc_wfi_mon); - if (priv == NULL) { + if (!priv) { PRINT_ER("private structure is NULL\n"); return NULL; } @@ -347,7 +347,7 @@ int WILC_WFI_deinit_mon_interface(void) { bool rollback_lock = false; - if (wilc_wfi_mon != NULL) { + if (wilc_wfi_mon) { PRINT_D(HOSTAPD_DBG, "In Deinit monitor interface\n"); PRINT_D(HOSTAPD_DBG, "RTNL is being locked\n"); if (rtnl_is_locked()) { -- cgit v1.2.3 From 382af7f2fdedb62bccdd887af4d43b736804d16f Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:42 +0900 Subject: staging: wilc1000: linux_mon: remove space after a cast This patch removes space after a type cast found by checkpatch.pl CHECK: No space is necessary after a cast Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 7b9cc02c976b..0c3dee36936f 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -80,7 +80,7 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) memcpy(skb_put(skb, size), buff, size); - cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb, sizeof(*cb_hdr)); + cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *)skb_push(skb, sizeof(*cb_hdr)); memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr)); cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */ @@ -109,7 +109,7 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) } memcpy(skb_put(skb, size), buff, size); - hdr = (struct wilc_wfi_radiotap_hdr *) skb_push(skb, sizeof(*hdr)); + hdr = (struct wilc_wfi_radiotap_hdr *)skb_push(skb, sizeof(*hdr)); memset(hdr, 0, sizeof(struct wilc_wfi_radiotap_hdr)); hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */ hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_hdr)); @@ -236,7 +236,7 @@ static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb, memcpy(skb_put(skb2, skb->len), skb->data, skb->len); - cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb2, sizeof(*cb_hdr)); + cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *)skb_push(skb2, sizeof(*cb_hdr)); memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr)); cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */ -- cgit v1.2.3 From 964d8936dd3578c706214461e428167fb282a3e1 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:43 +0900 Subject: staging: wilc1000: linux_mon: insert blank line after a function This patch inserts a blank line afer function found by checkpatch.pl CHECK: Please use a blank line after function/struct/union/enum declarations Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 0c3dee36936f..53d0caf9d91e 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -152,6 +152,7 @@ static void mgmt_tx_complete(void *priv, int status) kfree(pv_data); } + static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) { struct tx_complete_mon_data *mgmt_tx = NULL; -- cgit v1.2.3 From b4a53a621223d2e6f3f4012c7165f5ccaca41d9c Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:44 +0900 Subject: staging: wilc1000: linux_mon: add braces on all arms of if statement This patch adds braces on all arms of if statement found by checkpatch.pl CHECK: braces {} should be used on all arms of this statement Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 53d0caf9d91e..255383c6cf2b 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -278,8 +278,9 @@ static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb, if (!(memcmp(srcAdd, bssid, 6))) { mon_mgmt_tx(mon_priv->real_ndev, skb->data, skb->len); dev_kfree_skb(skb); - } else + } else { ret = wilc_mac_xmit(skb, mon_priv->real_ndev); + } return ret; } -- cgit v1.2.3 From fa611271b4d681d02520c458c555e48ee11d61d4 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:45 +0900 Subject: staging: wilc1000: linux_mon: fix coding style of kmalloc usage This patch fixes coding style of kmalloc usage found by checkpatch.pl CHECK: Prefer kmalloc(sizeof(*mgmt_tx)...) over kmalloc(sizeof(struct tx_complete_mon_data)...) Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 255383c6cf2b..a19755ebd72c 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -163,7 +163,7 @@ static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) } netif_stop_queue(dev); - mgmt_tx = kmalloc(sizeof(struct tx_complete_mon_data), GFP_ATOMIC); + mgmt_tx = kmalloc(sizeof(*mgmt_tx), GFP_ATOMIC); if (!mgmt_tx) { PRINT_ER("Failed to allocate memory for mgmt_tx structure\n"); return -EFAULT; -- cgit v1.2.3 From b026f6e8d607f40f9fcdc0bc9966db4bde4a1129 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:46 +0900 Subject: staging: wilc1000: linux_mon: fix error code of kmalloc This patch fixes error codes as -ENOMEM instead of using -EFAULT if kmalloc is failed. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index a19755ebd72c..1443a238a520 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -166,14 +166,14 @@ static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) mgmt_tx = kmalloc(sizeof(*mgmt_tx), GFP_ATOMIC); if (!mgmt_tx) { PRINT_ER("Failed to allocate memory for mgmt_tx structure\n"); - return -EFAULT; + return -ENOMEM; } mgmt_tx->buff = kmalloc(len, GFP_ATOMIC); if (!mgmt_tx->buff) { PRINT_ER("Failed to allocate memory for mgmt_tx buff\n"); kfree(mgmt_tx); - return -EFAULT; + return -ENOMEM; } mgmt_tx->size = len; -- cgit v1.2.3 From e5349952de5b1138e6275529e4ec08c0ed33777f Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:47 +0900 Subject: staging: wilc1000: linux_mon: remove debug message of kmalloc failure There is no need to print debug message when kmalloc is failed. This message is redundant. The code already show us that kmalloc is failed. The braces of first if statement is remove as well because if statement has a single statement. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 1443a238a520..e9bb0ec5cbc6 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -164,14 +164,11 @@ static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) netif_stop_queue(dev); mgmt_tx = kmalloc(sizeof(*mgmt_tx), GFP_ATOMIC); - if (!mgmt_tx) { - PRINT_ER("Failed to allocate memory for mgmt_tx structure\n"); + if (!mgmt_tx) return -ENOMEM; - } mgmt_tx->buff = kmalloc(len, GFP_ATOMIC); if (!mgmt_tx->buff) { - PRINT_ER("Failed to allocate memory for mgmt_tx buff\n"); kfree(mgmt_tx); return -ENOMEM; } -- cgit v1.2.3 From 04d5a21d62887b9bc5383fc68ab2756287da4532 Mon Sep 17 00:00:00 2001 From: Kiran Patil Date: Wed, 9 Dec 2015 15:50:23 -0800 Subject: i40e: Add mac_filter_element at the end of the list instead of HEAD Add MAC filter element to the end of the list in the given order, just to be tidy, and just in case there are ever any ordering issues in the future. Change-ID: Idc15276147593ea9393ac72c861f9c7905a791b4 Signed-off-by: Kiran Patil Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 8f3b53e0dc46..d078a6331365 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1368,7 +1368,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, f->changed = true; INIT_LIST_HEAD(&f->list); - list_add(&f->list, &vsi->mac_filter_list); + list_add_tail(&f->list, &vsi->mac_filter_list); } /* increment counter and add a new flag if needed */ -- cgit v1.2.3 From 6e35c04cf633e55648acb9ccabff42aa37bd4044 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Wed, 9 Dec 2015 15:50:24 -0800 Subject: i40e/i40evf: Fix RSS rx-flow-hash configuration through ethtool This patch fixes the Hash PCTYPE enable for X722 since it supports a broader selection of PCTYPES for TCP and UDP. This patch also fixes a bug in XL710, X710, X722 support for RSS, as of now we cannot reduce the (4)tuple for RSS for TCP/IPv4/IPV6 or UDP/IPv4/IPv6 packets since this requires a product feature change that comes in a later release. A VF should never be allowed to change the tuples for RSS for any PCTYPE since that's a global setting for the device in case of i40e devices. Change-ID: I0ee7203c9b24813260f58f3220798bc9d9ac4a12 Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 14 +++----- drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | 40 +++++----------------- 2 files changed, 12 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 29d5833e24a3..c8b9dcae630a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -2166,8 +2166,7 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case TCP_V4_FLOW: switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: - hena &= ~BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); - break; + return -EINVAL; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); break; @@ -2178,8 +2177,7 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case TCP_V6_FLOW: switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: - hena &= ~BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); - break; + return -EINVAL; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); break; @@ -2190,9 +2188,7 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case UDP_V4_FLOW: switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: - hena &= ~(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | - BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); - break; + return -EINVAL; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); @@ -2204,9 +2200,7 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case UDP_V6_FLOW: switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: - hena &= ~(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | - BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); - break; + return -EINVAL; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c index a4c9feb589e7..8906785446ab 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c @@ -477,54 +477,30 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, switch (nfc->flow_type) { case TCP_V4_FLOW: - switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - hena &= ~BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); - break; - default: + else return -EINVAL; - } break; case TCP_V6_FLOW: - switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - hena &= ~BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); - break; - default: + else return -EINVAL; - } break; case UDP_V4_FLOW: - switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - hena &= ~(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | - BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); - break; - default: + } else { return -EINVAL; } break; case UDP_V6_FLOW: - switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - hena &= ~(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | - BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); - break; - default: + } else { return -EINVAL; } break; -- cgit v1.2.3 From 48b1804ee3cdad7bf115666eb35edf12a734710f Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Wed, 9 Dec 2015 15:50:25 -0800 Subject: i40e: Replace X722 mac check in ethtool get_settings 100M SGMII is only supported on X722. Replace the mac check with a feature flag check that is only set for the X722 device. Change-ID: I53452d9af6af8cd9dca8500215fbc6ce93418f52 Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 68f2204ec6f3..47f6c0a9c9fe 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -339,6 +339,7 @@ struct i40e_pf { #define I40E_FLAG_VEB_MODE_ENABLED BIT_ULL(40) #define I40E_FLAG_GENEVE_OFFLOAD_CAPABLE BIT_ULL(41) #define I40E_FLAG_NO_PCI_LINK_CHECK BIT_ULL(42) +#define I40E_FLAG_100M_SGMII_CAPABLE BIT_ULL(43) #define I40E_FLAG_PF_MAC BIT_ULL(50) /* tracks features that get auto disabled by errors */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index c8b9dcae630a..252a9dd941d4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -340,7 +340,7 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, SUPPORTED_1000baseT_Full; if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) ecmd->advertising |= ADVERTISED_1000baseT_Full; - if (pf->hw.mac.type == I40E_MAC_X722) { + if (pf->flags & I40E_FLAG_100M_SGMII_CAPABLE) { ecmd->supported |= SUPPORTED_100baseT_Full; if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB) -- cgit v1.2.3 From 209dc4daf23f92b3e0bc6d602411506c4083e421 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Wed, 9 Dec 2015 15:50:27 -0800 Subject: i40evf: allow channel bonding of VFs In some modes, bonding would not enslave VF interfaces. This is due to bonding calling change_mtu and the immediately calling open. Because of the asynchronous nature of the admin queue mechanism, the VF returns -EBUSY to the open call, because it knows the previous operation hasn't finished yet. This causes bonding to fail with a less-than-useful error message. To fix this, remove the check for pending operations at the beginning of open. But this introduces a new bug where the driver will panic on a quick close/open cycle. To fix that, we add a new driver state, __I40EVF_DOWN_PENDING, that the driver enters when down is called. The driver finally transitions to a fully DOWN state when it receives confirmation from the PF driver that all the queues are disabled. This allows open to complete even if there is a pending mtu change, and bonding is finally happy. Change-ID: I06f4c7e435d5bacbfceaa7c3f209e0ff04be21cc Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf.h | 1 + drivers/net/ethernet/intel/i40evf/i40evf_main.c | 9 +++++---- drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c | 2 ++ 3 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index be1b72b93888..9e15f68d9ddd 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -173,6 +173,7 @@ enum i40evf_state_t { __I40EVF_RESETTING, /* in reset */ /* Below here, watchdog is running */ __I40EVF_DOWN, /* ready, can be opened */ + __I40EVF_DOWN_PENDING, /* descending, waiting for watchdog */ __I40EVF_TESTING, /* in ethtool self-test */ __I40EVF_RUNNING, /* opened, working */ }; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 94da913b151d..d1c4335114fc 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1032,7 +1032,7 @@ void i40evf_down(struct i40evf_adapter *adapter) struct net_device *netdev = adapter->netdev; struct i40evf_mac_filter *f; - if (adapter->state == __I40EVF_DOWN) + if (adapter->state <= __I40EVF_DOWN_PENDING) return; while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, @@ -2142,7 +2142,8 @@ static int i40evf_open(struct net_device *netdev) dev_err(&adapter->pdev->dev, "Unable to open device due to PF driver failure.\n"); return -EIO; } - if (adapter->state != __I40EVF_DOWN || adapter->aq_required) + + if (adapter->state != __I40EVF_DOWN) return -EBUSY; /* allocate transmit descriptors */ @@ -2197,14 +2198,14 @@ static int i40evf_close(struct net_device *netdev) { struct i40evf_adapter *adapter = netdev_priv(netdev); - if (adapter->state <= __I40EVF_DOWN) + if (adapter->state <= __I40EVF_DOWN_PENDING) return 0; set_bit(__I40E_DOWN, &adapter->vsi.state); i40evf_down(adapter); - adapter->state = __I40EVF_DOWN; + adapter->state = __I40EVF_DOWN_PENDING; i40evf_free_traffic_irqs(adapter); return 0; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c index c1c526283757..d3739cc5b608 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c @@ -804,6 +804,8 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter, case I40E_VIRTCHNL_OP_DISABLE_QUEUES: i40evf_free_all_tx_resources(adapter); i40evf_free_all_rx_resources(adapter); + if (adapter->state == __I40EVF_DOWN_PENDING) + adapter->state = __I40EVF_DOWN; break; case I40E_VIRTCHNL_OP_VERSION: case I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP: -- cgit v1.2.3 From 406e734aa893fa5841e67de6d4f688ba70a82e4f Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 10 Dec 2015 11:38:49 -0800 Subject: i40e: define function capabilities in only one place The device capabilities were defined in two places, and neither had all the definitions. It really belongs with the AQ API definition, so this patch removes the other set of definitions and fills out the missing item. Change-ID: I273ba7d79a476cd11d2e0ca5825fec1716740de2 Signed-off-by: Shannon Nelson Acked-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 1 + drivers/net/ethernet/intel/i40e/i40e_common.c | 85 +++++++--------------- .../net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 1 + 3 files changed, 30 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index b22012a446a6..256ce6549f61 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -422,6 +422,7 @@ struct i40e_aqc_list_capabilities_element_resp { #define I40E_AQ_CAP_ID_LED 0x0061 #define I40E_AQ_CAP_ID_SDP 0x0062 #define I40E_AQ_CAP_ID_MDIO 0x0063 +#define I40E_AQ_CAP_ID_WSR_PROT 0x0064 #define I40E_AQ_CAP_ID_FLEX10 0x00F1 #define I40E_AQ_CAP_ID_CEM 0x00F2 diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 6a034ddac36a..4bdb08bb27d7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -2765,35 +2765,6 @@ i40e_aq_erase_nvm_exit: return status; } -#define I40E_DEV_FUNC_CAP_SWITCH_MODE 0x01 -#define I40E_DEV_FUNC_CAP_MGMT_MODE 0x02 -#define I40E_DEV_FUNC_CAP_NPAR 0x03 -#define I40E_DEV_FUNC_CAP_OS2BMC 0x04 -#define I40E_DEV_FUNC_CAP_VALID_FUNC 0x05 -#define I40E_DEV_FUNC_CAP_SRIOV_1_1 0x12 -#define I40E_DEV_FUNC_CAP_VF 0x13 -#define I40E_DEV_FUNC_CAP_VMDQ 0x14 -#define I40E_DEV_FUNC_CAP_802_1_QBG 0x15 -#define I40E_DEV_FUNC_CAP_802_1_QBH 0x16 -#define I40E_DEV_FUNC_CAP_VSI 0x17 -#define I40E_DEV_FUNC_CAP_DCB 0x18 -#define I40E_DEV_FUNC_CAP_FCOE 0x21 -#define I40E_DEV_FUNC_CAP_ISCSI 0x22 -#define I40E_DEV_FUNC_CAP_RSS 0x40 -#define I40E_DEV_FUNC_CAP_RX_QUEUES 0x41 -#define I40E_DEV_FUNC_CAP_TX_QUEUES 0x42 -#define I40E_DEV_FUNC_CAP_MSIX 0x43 -#define I40E_DEV_FUNC_CAP_MSIX_VF 0x44 -#define I40E_DEV_FUNC_CAP_FLOW_DIRECTOR 0x45 -#define I40E_DEV_FUNC_CAP_IEEE_1588 0x46 -#define I40E_DEV_FUNC_CAP_FLEX10 0xF1 -#define I40E_DEV_FUNC_CAP_CEM 0xF2 -#define I40E_DEV_FUNC_CAP_IWARP 0x51 -#define I40E_DEV_FUNC_CAP_LED 0x61 -#define I40E_DEV_FUNC_CAP_SDP 0x62 -#define I40E_DEV_FUNC_CAP_MDIO 0x63 -#define I40E_DEV_FUNC_CAP_WR_CSR_PROT 0x64 - /** * i40e_parse_discover_capabilities * @hw: pointer to the hw struct @@ -2832,79 +2803,79 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff, major_rev = cap->major_rev; switch (id) { - case I40E_DEV_FUNC_CAP_SWITCH_MODE: + case I40E_AQ_CAP_ID_SWITCH_MODE: p->switch_mode = number; break; - case I40E_DEV_FUNC_CAP_MGMT_MODE: + case I40E_AQ_CAP_ID_MNG_MODE: p->management_mode = number; break; - case I40E_DEV_FUNC_CAP_NPAR: + case I40E_AQ_CAP_ID_NPAR_ACTIVE: p->npar_enable = number; break; - case I40E_DEV_FUNC_CAP_OS2BMC: + case I40E_AQ_CAP_ID_OS2BMC_CAP: p->os2bmc = number; break; - case I40E_DEV_FUNC_CAP_VALID_FUNC: + case I40E_AQ_CAP_ID_FUNCTIONS_VALID: p->valid_functions = number; break; - case I40E_DEV_FUNC_CAP_SRIOV_1_1: + case I40E_AQ_CAP_ID_SRIOV: if (number == 1) p->sr_iov_1_1 = true; break; - case I40E_DEV_FUNC_CAP_VF: + case I40E_AQ_CAP_ID_VF: p->num_vfs = number; p->vf_base_id = logical_id; break; - case I40E_DEV_FUNC_CAP_VMDQ: + case I40E_AQ_CAP_ID_VMDQ: if (number == 1) p->vmdq = true; break; - case I40E_DEV_FUNC_CAP_802_1_QBG: + case I40E_AQ_CAP_ID_8021QBG: if (number == 1) p->evb_802_1_qbg = true; break; - case I40E_DEV_FUNC_CAP_802_1_QBH: + case I40E_AQ_CAP_ID_8021QBR: if (number == 1) p->evb_802_1_qbh = true; break; - case I40E_DEV_FUNC_CAP_VSI: + case I40E_AQ_CAP_ID_VSI: p->num_vsis = number; break; - case I40E_DEV_FUNC_CAP_DCB: + case I40E_AQ_CAP_ID_DCB: if (number == 1) { p->dcb = true; p->enabled_tcmap = logical_id; p->maxtc = phys_id; } break; - case I40E_DEV_FUNC_CAP_FCOE: + case I40E_AQ_CAP_ID_FCOE: if (number == 1) p->fcoe = true; break; - case I40E_DEV_FUNC_CAP_ISCSI: + case I40E_AQ_CAP_ID_ISCSI: if (number == 1) p->iscsi = true; break; - case I40E_DEV_FUNC_CAP_RSS: + case I40E_AQ_CAP_ID_RSS: p->rss = true; p->rss_table_size = number; p->rss_table_entry_width = logical_id; break; - case I40E_DEV_FUNC_CAP_RX_QUEUES: + case I40E_AQ_CAP_ID_RXQ: p->num_rx_qp = number; p->base_queue = phys_id; break; - case I40E_DEV_FUNC_CAP_TX_QUEUES: + case I40E_AQ_CAP_ID_TXQ: p->num_tx_qp = number; p->base_queue = phys_id; break; - case I40E_DEV_FUNC_CAP_MSIX: + case I40E_AQ_CAP_ID_MSIX: p->num_msix_vectors = number; break; - case I40E_DEV_FUNC_CAP_MSIX_VF: + case I40E_AQ_CAP_ID_VF_MSIX: p->num_msix_vectors_vf = number; break; - case I40E_DEV_FUNC_CAP_FLEX10: + case I40E_AQ_CAP_ID_FLEX10: if (major_rev == 1) { if (number == 1) { p->flex10_enable = true; @@ -2920,38 +2891,38 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff, p->flex10_mode = logical_id; p->flex10_status = phys_id; break; - case I40E_DEV_FUNC_CAP_CEM: + case I40E_AQ_CAP_ID_CEM: if (number == 1) p->mgmt_cem = true; break; - case I40E_DEV_FUNC_CAP_IWARP: + case I40E_AQ_CAP_ID_IWARP: if (number == 1) p->iwarp = true; break; - case I40E_DEV_FUNC_CAP_LED: + case I40E_AQ_CAP_ID_LED: if (phys_id < I40E_HW_CAP_MAX_GPIO) p->led[phys_id] = true; break; - case I40E_DEV_FUNC_CAP_SDP: + case I40E_AQ_CAP_ID_SDP: if (phys_id < I40E_HW_CAP_MAX_GPIO) p->sdp[phys_id] = true; break; - case I40E_DEV_FUNC_CAP_MDIO: + case I40E_AQ_CAP_ID_MDIO: if (number == 1) { p->mdio_port_num = phys_id; p->mdio_port_mode = logical_id; } break; - case I40E_DEV_FUNC_CAP_IEEE_1588: + case I40E_AQ_CAP_ID_1588: if (number == 1) p->ieee_1588 = true; break; - case I40E_DEV_FUNC_CAP_FLOW_DIRECTOR: + case I40E_AQ_CAP_ID_FLOW_DIRECTOR: p->fd = true; p->fd_filters_guaranteed = number; p->fd_filters_best_effort = logical_id; break; - case I40E_DEV_FUNC_CAP_WR_CSR_PROT: + case I40E_AQ_CAP_ID_WSR_PROT: p->wr_csr_prot = (u64)number; p->wr_csr_prot |= (u64)logical_id << 32; break; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h index f5b2b369dc7c..0d3bc3be0527 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h @@ -419,6 +419,7 @@ struct i40e_aqc_list_capabilities_element_resp { #define I40E_AQ_CAP_ID_LED 0x0061 #define I40E_AQ_CAP_ID_SDP 0x0062 #define I40E_AQ_CAP_ID_MDIO 0x0063 +#define I40E_AQ_CAP_ID_WSR_PROT 0x0064 #define I40E_AQ_CAP_ID_FLEX10 0x00F1 #define I40E_AQ_CAP_ID_CEM 0x00F2 -- cgit v1.2.3 From 10311540fab76c7e5530bf5f0267a3d1b8d5818e Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Wed, 9 Dec 2015 15:50:30 -0800 Subject: i40evf: null out ring pointers on free Since we check these ring pointers to make sure we don't double-allocate or double-free the rings, we had better null them out after we free them. In very rare cases this can cause a panic if the driver is removed during reset recovery. Change-ID: Ib06eb4910a3058275c8f7ec5ef7f45baa4674f96 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index d1c4335114fc..81d958422ccf 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1122,7 +1122,9 @@ static void i40evf_free_queues(struct i40evf_adapter *adapter) if (!adapter->vsi_res) return; kfree(adapter->tx_rings); + adapter->tx_rings = NULL; kfree(adapter->rx_rings); + adapter->rx_rings = NULL; } /** -- cgit v1.2.3 From 8eed76fa4885f1ed9f19f4d3a16dd24cebf09c19 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Wed, 9 Dec 2015 15:50:31 -0800 Subject: i40e: Cleanup the code with respect to restarting autoneg The restart-autoneg work around does not apply to X722. Added a flag to set it only for the right MAC and right FW version where the work around should be applied. Signed-off-by: Anjali Singhai Jain Change-ID: I942c3ff40cccd1e56f424b1da776b020fe3c9d2a Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 47f6c0a9c9fe..53ed3bdd8363 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -340,6 +340,7 @@ struct i40e_pf { #define I40E_FLAG_GENEVE_OFFLOAD_CAPABLE BIT_ULL(41) #define I40E_FLAG_NO_PCI_LINK_CHECK BIT_ULL(42) #define I40E_FLAG_100M_SGMII_CAPABLE BIT_ULL(43) +#define I40E_FLAG_RESTART_AUTONEG BIT_ULL(44) #define I40E_FLAG_PF_MAC BIT_ULL(50) /* tracks features that get auto disabled by errors */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index d078a6331365..1a7022ca4750 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6889,8 +6889,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) wr32(hw, I40E_REG_MSS, val); } - if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 33)) || - (pf->hw.aq.fw_maj_ver < 4)) { + if (pf->flags & I40E_FLAG_RESTART_AUTONEG) { msleep(75); ret = i40e_aq_set_link_restart_an(&pf->hw, true, NULL); if (ret) @@ -8367,6 +8366,12 @@ static int i40e_sw_init(struct i40e_pf *pf) pf->hw.func_caps.fd_filters_best_effort; } + if (((pf->hw.mac.type == I40E_MAC_X710) || + (pf->hw.mac.type == I40E_MAC_XL710)) && + (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 33)) || + (pf->hw.aq.fw_maj_ver < 4))) + pf->flags |= I40E_FLAG_RESTART_AUTONEG; + if (pf->hw.func_caps.vmdq) { pf->num_vmdq_vsis = I40E_DEFAULT_NUM_VMDQ_VSI; pf->flags |= I40E_FLAG_VMDQ_ENABLED; @@ -10904,8 +10909,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) wr32(hw, I40E_REG_MSS, val); } - if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 33)) || - (pf->hw.aq.fw_maj_ver < 4)) { + if (pf->flags & I40E_FLAG_RESTART_AUTONEG) { msleep(75); err = i40e_aq_set_link_restart_an(&pf->hw, true, NULL); if (err) -- cgit v1.2.3 From 5afdaaa0555257f3c42b141908567d40aca0e1d1 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 10 Dec 2015 11:38:50 -0800 Subject: i40e: update features with right offload Synchronize code bases and add SCTP offload support. Change-ID: I9f99071f7176225479026930c387bf681a47494e Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 1a7022ca4750..486ae1604138 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8947,11 +8947,11 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) np = netdev_priv(netdev); np->vsi = vsi; - netdev->hw_enc_features |= NETIF_F_IP_CSUM | - NETIF_F_RXCSUM | - NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_GRE | - NETIF_F_TSO; + netdev->hw_enc_features |= NETIF_F_IP_CSUM | + NETIF_F_GSO_UDP_TUNNEL | + NETIF_F_GSO_GRE | + NETIF_F_TSO | + 0; netdev->features = NETIF_F_SG | NETIF_F_IP_CSUM | -- cgit v1.2.3 From 4f9e697ebbf40ba482ad0481da1e978440f2a53e Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Thu, 10 Dec 2015 11:38:51 -0800 Subject: i40e: bump version to 1.4.10 Bump. Change-ID: Ic9a495feb9ab0606f953c3848b0acf67169d3930 Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 486ae1604138..c88583e112fa 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -51,7 +51,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 4 -#define DRV_VERSION_BUILD 8 +#define DRV_VERSION_BUILD 10 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN -- cgit v1.2.3 From 35dae51de3e99db10f355642f5fc67719b93f558 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 22 Dec 2015 14:25:03 -0800 Subject: i40e: add new device IDs for X722 Add the KX and QSFP device IDs for X722. Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 2 ++ drivers/net/ethernet/intel/i40e/i40e_devids.h | 2 ++ drivers/net/ethernet/intel/i40e/i40e_main.c | 2 ++ 3 files changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 4bdb08bb27d7..3b03a3165ca7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -55,6 +55,8 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw) case I40E_DEV_ID_20G_KR2_A: hw->mac.type = I40E_MAC_XL710; break; + case I40E_DEV_ID_KX_X722: + case I40E_DEV_ID_QSFP_X722: case I40E_DEV_ID_SFP_X722: case I40E_DEV_ID_1G_BASE_T_X722: case I40E_DEV_ID_10G_BASE_T_X722: diff --git a/drivers/net/ethernet/intel/i40e/i40e_devids.h b/drivers/net/ethernet/intel/i40e/i40e_devids.h index 448ef4c17efb..f7ce5c7c9003 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_devids.h +++ b/drivers/net/ethernet/intel/i40e/i40e_devids.h @@ -41,6 +41,8 @@ #define I40E_DEV_ID_10G_BASE_T4 0x1589 #define I40E_DEV_ID_VF 0x154C #define I40E_DEV_ID_VF_HV 0x1571 +#define I40E_DEV_ID_KX_X722 0x37CE +#define I40E_DEV_ID_QSFP_X722 0x37CF #define I40E_DEV_ID_SFP_X722 0x37D0 #define I40E_DEV_ID_1G_BASE_T_X722 0x37D1 #define I40E_DEV_ID_10G_BASE_T_X722 0x37D2 diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index c88583e112fa..b3e671bb83ff 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -90,6 +90,8 @@ static const struct pci_device_id i40e_pci_tbl[] = { {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T4), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2), 0}, + {PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_X722), 0}, + {PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_X722), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_X722), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_1G_BASE_T_X722), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T_X722), 0}, -- cgit v1.2.3 From 95a73780921aecc5e66022e000fcf8aeecfb53cf Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 22 Dec 2015 14:25:04 -0800 Subject: i40e: Extend ethtool RSS hooks for X722 This patch adds another way to access the RSS keys and lut using the AQ for X722 devices. Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 53 ++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index b3e671bb83ff..bd81a9770c5b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -7936,6 +7936,52 @@ static int i40e_vsi_config_rss(struct i40e_vsi *vsi) return ret; } +/** + * i40e_get_rss_aq - Get RSS keys and lut by using AQ commands + * @vsi: Pointer to vsi structure + * @seed: Buffter to store the hash keys + * @lut: Buffer to store the lookup table entries + * @lut_size: Size of buffer to store the lookup table entries + * + * Return 0 on success, negative on failure + */ +static int i40e_get_rss_aq(struct i40e_vsi *vsi, const u8 *seed, + u8 *lut, u16 lut_size) +{ + struct i40e_pf *pf = vsi->back; + struct i40e_hw *hw = &pf->hw; + int ret = 0; + + if (seed) { + ret = i40e_aq_get_rss_key(hw, vsi->id, + (struct i40e_aqc_get_set_rss_key_data *)seed); + if (ret) { + dev_info(&pf->pdev->dev, + "Cannot get RSS key, err %s aq_err %s\n", + i40e_stat_str(&pf->hw, ret), + i40e_aq_str(&pf->hw, + pf->hw.aq.asq_last_status)); + return ret; + } + } + + if (lut) { + bool pf_lut = vsi->type == I40E_VSI_MAIN ? true : false; + + ret = i40e_aq_get_rss_lut(hw, vsi->id, pf_lut, lut, lut_size); + if (ret) { + dev_info(&pf->pdev->dev, + "Cannot get RSS lut, err %s aq_err %s\n", + i40e_stat_str(&pf->hw, ret), + i40e_aq_str(&pf->hw, + pf->hw.aq.asq_last_status)); + return ret; + } + } + + return ret; +} + /** * i40e_config_rss_reg - Configure RSS keys and lut by writing registers * @vsi: Pointer to vsi structure @@ -8038,7 +8084,12 @@ int i40e_config_rss(struct i40e_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size) */ int i40e_get_rss(struct i40e_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size) { - return i40e_get_rss_reg(vsi, seed, lut, lut_size); + struct i40e_pf *pf = vsi->back; + + if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) + return i40e_get_rss_aq(vsi, seed, lut, lut_size); + else + return i40e_get_rss_reg(vsi, seed, lut, lut_size); } /** -- cgit v1.2.3 From 3d0da5b78262c1f86294419c7a70e4c837aca159 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 22 Dec 2015 14:25:05 -0800 Subject: i40e/i40evf: Fix for UDP/TCP RSS for X722 The PCTYPES for the X710 and X722 families are different. This patch makes adjustments for that. Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 18 ++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 6 +++++ drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | 29 +++++++++++++++++++--- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 8 +++--- 4 files changed, 54 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 252a9dd941d4..8a3f93ddbcc3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -2168,6 +2168,10 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case 0: return -EINVAL; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) + hena |= + BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK); + hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); break; default: @@ -2179,6 +2183,10 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case 0: return -EINVAL; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) + hena |= + BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK); + hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); break; default: @@ -2190,6 +2198,11 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case 0: return -EINVAL; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) + hena |= + BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | + BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP); + hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); break; @@ -2202,6 +2215,11 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case 0: return -EINVAL; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) + hena |= + BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | + BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP); + hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); break; diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 63e62f9aec6e..86aacb9f4d44 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1213,6 +1213,12 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG; } + if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) { + if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2) + vfres->vf_offload_flags |= + I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2; + } + if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING) vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c index 8906785446ab..bd1c2728bc5c 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c @@ -459,6 +459,7 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, struct ethtool_rxnfc *nfc) { struct i40e_hw *hw = &adapter->hw; + u32 flags = adapter->vf_res->vf_offload_flags; u64 hena = (u64)rd32(hw, I40E_VFQF_HENA(0)) | ((u64)rd32(hw, I40E_VFQF_HENA(1)) << 32); @@ -477,19 +478,34 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, switch (nfc->flow_type) { case TCP_V4_FLOW: - if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) + if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2) + hena |= + BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK); + hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); - else + } else { return -EINVAL; + } break; case TCP_V6_FLOW: - if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) + if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2) + hena |= + BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK); + hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); - else + } else { return -EINVAL; + } break; case UDP_V4_FLOW: if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2) + hena |= + BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | + BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP); + hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); } else { @@ -498,6 +514,11 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, break; case UDP_V6_FLOW: if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2) + hena |= + BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | + BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP); + hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); } else { diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 81d958422ccf..798f0dedf14f 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1456,7 +1456,11 @@ static int i40evf_init_rss(struct i40evf_adapter *adapter) int ret; /* Enable PCTYPES for RSS, TCP/UDP with IPv4/IPv6 */ - hena = I40E_DEFAULT_RSS_HENA; + if (adapter->vf_res->vf_offload_flags & + I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2) + hena = I40E_DEFAULT_RSS_HENA_EXPANDED; + else + hena = I40E_DEFAULT_RSS_HENA; wr32(hw, I40E_VFQF_HENA(0), (u32)hena); wr32(hw, I40E_VFQF_HENA(1), (u32)(hena >> 32)); @@ -2507,8 +2511,6 @@ static void i40evf_init_task(struct work_struct *work) if (adapter->vf_res->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) adapter->flags |= I40EVF_FLAG_WB_ON_ITR_CAPABLE; - if (!RSS_AQ(adapter)) - i40evf_init_rss(adapter); err = i40evf_request_misc_irq(adapter); if (err) goto err_sw_init; -- cgit v1.2.3 From f6d83d1376f496e6218080dd6eb663830672813f Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 22 Dec 2015 14:25:07 -0800 Subject: i40evf: add new write-back mode Add write-back on interrupt throttle rate timer expiration support for the i40evf driver, when running on X722 devices. Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 6 ++++++ drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 16 ++++++++++++++++ drivers/net/ethernet/intel/i40evf/i40evf_main.c | 5 +++++ 3 files changed, 27 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 86aacb9f4d44..659d78270fdb 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1222,6 +1222,12 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING) vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING; + if (pf->flags & I40E_FLAG_WB_ON_ITR_CAPABLE) { + if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) + vfres->vf_offload_flags |= + I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR; + } + vfres->num_vsis = num_vsis; vfres->num_queue_pairs = vf->num_queue_pairs; vfres->max_vectors = pf->hw.func_caps.num_msix_vectors_vf; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 7a00657dacda..7d663fb61927 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -252,6 +252,22 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) tx_ring->q_vector->tx.total_bytes += total_bytes; tx_ring->q_vector->tx.total_packets += total_packets; + if (tx_ring->flags & I40E_TXR_FLAGS_WB_ON_ITR) { + unsigned int j = 0; + /* check to see if there are < 4 descriptors + * waiting to be written back, then kick the hardware to force + * them to be written back in case we stay in NAPI. + * In this mode on X722 we do not enable Interrupt. + */ + j = i40evf_get_tx_pending(tx_ring); + + if (budget && + ((j / (WB_STRIDE + 1)) == 0) && (j > 0) && + !test_bit(__I40E_DOWN, &tx_ring->vsi->state) && + (I40E_DESC_UNUSED(tx_ring) != tx_ring->count)) + tx_ring->arm_wb = true; + } + netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index), total_packets, total_bytes); diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 798f0dedf14f..615ad0f1fdc4 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2511,6 +2511,11 @@ static void i40evf_init_task(struct work_struct *work) if (adapter->vf_res->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) adapter->flags |= I40EVF_FLAG_WB_ON_ITR_CAPABLE; + + if (adapter->vf_res->vf_offload_flags & + I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) + adapter->flags |= I40EVF_FLAG_WB_ON_ITR_CAPABLE; + err = i40evf_request_misc_irq(adapter); if (err) goto err_sw_init; -- cgit v1.2.3 From 2803b16c10ea7eec170c485388f5f26ae30e92fe Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 22 Dec 2015 14:25:08 -0800 Subject: i40e/i40evf: Use private workqueue As done per ixgbe, use a private workqueue to avoid blocking the system workqueue. This avoids some strange side effects when some other entity is depending on the system work queue. Change-ID: Ic8ba08f5b03696cf638b21afd25fbae7738d55ee Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 15 ++++++++++++++- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 10 +++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index bd81a9770c5b..3e482bcd5287 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -112,6 +112,8 @@ MODULE_DESCRIPTION("Intel(R) Ethernet Connection XL710 Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); +static struct workqueue_struct *i40e_wq; + /** * i40e_allocate_dma_mem_d - OS specific memory alloc for shared code * @hw: pointer to the HW structure @@ -297,7 +299,7 @@ static void i40e_service_event_schedule(struct i40e_pf *pf) if (!test_bit(__I40E_DOWN, &pf->state) && !test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) && !test_and_set_bit(__I40E_SERVICE_SCHED, &pf->state)) - schedule_work(&pf->service_task); + queue_work(i40e_wq, &pf->service_task); } /** @@ -11470,6 +11472,16 @@ static int __init i40e_init_module(void) i40e_driver_string, i40e_driver_version_str); pr_info("%s: %s\n", i40e_driver_name, i40e_copyright); + /* we will see if single thread per module is enough for now, + * it can't be any worse than using the system workqueue which + * was already single threaded + */ + i40e_wq = create_singlethread_workqueue(i40e_driver_name); + if (!i40e_wq) { + pr_err("%s: Failed to create workqueue\n", i40e_driver_name); + return -ENOMEM; + } + i40e_dbg_init(); return pci_register_driver(&i40e_driver); } @@ -11484,6 +11496,7 @@ module_init(i40e_init_module); static void __exit i40e_exit_module(void) { pci_unregister_driver(&i40e_driver); + destroy_workqueue(i40e_wq); i40e_dbg_exit(); } module_exit(i40e_exit_module); diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 615ad0f1fdc4..66964eb6b7de 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -69,6 +69,8 @@ MODULE_DESCRIPTION("Intel(R) XL710 X710 Virtual Function Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); +static struct workqueue_struct *i40evf_wq; + /** * i40evf_allocate_dma_mem_d - OS specific memory alloc for shared code * @hw: pointer to the HW structure @@ -182,7 +184,7 @@ static void i40evf_tx_timeout(struct net_device *netdev) if (!(adapter->flags & (I40EVF_FLAG_RESET_PENDING | I40EVF_FLAG_RESET_NEEDED))) { adapter->flags |= I40EVF_FLAG_RESET_NEEDED; - schedule_work(&adapter->reset_task); + queue_work(i40evf_wq, &adapter->reset_task); } } @@ -2895,6 +2897,11 @@ static int __init i40evf_init_module(void) pr_info("%s\n", i40evf_copyright); + i40evf_wq = create_singlethread_workqueue(i40evf_driver_name); + if (!i40evf_wq) { + pr_err("%s: Failed to create workqueue\n", i40evf_driver_name); + return -ENOMEM; + } ret = pci_register_driver(&i40evf_driver); return ret; } @@ -2910,6 +2917,7 @@ module_init(i40evf_init_module); static void __exit i40evf_exit_module(void) { pci_unregister_driver(&i40evf_driver); + destroy_workqueue(i40evf_wq); } module_exit(i40evf_exit_module); -- cgit v1.2.3 From 4ba40bcea7046a1fa9b57a8cb4bcb8776e86e7ed Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Tue, 22 Dec 2015 14:25:09 -0800 Subject: i40e: add new proxy-wol bit for X722 Add the new proxy-wake-on-lan capability bit available with the new X722 device. Signed-off-by: Shannon Nelson Acked-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 1 + drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index 256ce6549f61..bff09957cdc0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -402,6 +402,7 @@ struct i40e_aqc_list_capabilities_element_resp { #define I40E_AQ_CAP_ID_OS2BMC_CAP 0x0004 #define I40E_AQ_CAP_ID_FUNCTIONS_VALID 0x0005 #define I40E_AQ_CAP_ID_ALTERNATE_RAM 0x0006 +#define I40E_AQ_CAP_ID_WOL_AND_PROXY 0x0008 #define I40E_AQ_CAP_ID_SRIOV 0x0012 #define I40E_AQ_CAP_ID_VF 0x0013 #define I40E_AQ_CAP_ID_VMDQ 0x0014 diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h index 0d3bc3be0527..365a7d6231a0 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h @@ -399,6 +399,7 @@ struct i40e_aqc_list_capabilities_element_resp { #define I40E_AQ_CAP_ID_OS2BMC_CAP 0x0004 #define I40E_AQ_CAP_ID_FUNCTIONS_VALID 0x0005 #define I40E_AQ_CAP_ID_ALTERNATE_RAM 0x0006 +#define I40E_AQ_CAP_ID_WOL_AND_PROXY 0x0008 #define I40E_AQ_CAP_ID_SRIOV 0x0012 #define I40E_AQ_CAP_ID_VF 0x0013 #define I40E_AQ_CAP_ID_VMDQ 0x0014 -- cgit v1.2.3 From 6dfae3892473e91080accdb2da8476481393f769 Mon Sep 17 00:00:00 2001 From: Greg Bowers Date: Tue, 22 Dec 2015 14:25:10 -0800 Subject: i40e: Limit DCB FW version checks to X710/XL710 devices X710/XL710 devices require FW version checks to properly handle DCB configurations from the FW. Newer devices do not, so limit these checks to X710/XL710. Signed-off-by: Greg Bowers Acked-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_dcb.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.c b/drivers/net/ethernet/intel/i40e/i40e_dcb.c index 2691277c0055..582daa7ad776 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.c @@ -814,13 +814,15 @@ i40e_status i40e_get_dcb_config(struct i40e_hw *hw) struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg; struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg; - /* If Firmware version < v4.33 IEEE only */ - if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) || - (hw->aq.fw_maj_ver < 4)) + /* If Firmware version < v4.33 on X710/XL710, IEEE only */ + if ((hw->mac.type == I40E_MAC_XL710) && + (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) || + (hw->aq.fw_maj_ver < 4))) return i40e_get_ieee_dcb_config(hw); - /* If Firmware version == v4.33 use old CEE struct */ - if ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33)) { + /* If Firmware version == v4.33 on X710/XL710, use old CEE struct */ + if ((hw->mac.type == I40E_MAC_XL710) && + ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33))) { ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg, sizeof(cee_v1_cfg), NULL); if (!ret) { -- cgit v1.2.3 From 5394f02f0c0553f97bb4c5596a34c9a7333c032b Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Tue, 22 Dec 2015 14:25:11 -0800 Subject: i40e: AQ Add Run PHY Activity struct Add the AQ opcode and struct definitions for the Run PHY Activity command Signed-off-by: Shannon Nelson Acked-by: Kevin Scott Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 13 +++++++++++++ drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 13 +++++++++++++ 2 files changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index bff09957cdc0..9e340ca03440 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -220,6 +220,7 @@ enum i40e_admin_queue_opc { i40e_aqc_opc_get_phy_wol_caps = 0x0621, i40e_aqc_opc_set_phy_debug = 0x0622, i40e_aqc_opc_upload_ext_phy_fm = 0x0625, + i40e_aqc_opc_run_phy_activity = 0x0626, /* NVM commands */ i40e_aqc_opc_nvm_read = 0x0701, @@ -1825,6 +1826,18 @@ enum i40e_aq_phy_reg_type { I40E_AQC_PHY_REG_EXERNAL_MODULE = 0x3 }; +/* Run PHY Activity (0x0626) */ +struct i40e_aqc_run_phy_activity { + __le16 activity_id; + u8 flags; + u8 reserved1; + __le32 control; + __le32 data; + u8 reserved2[4]; +}; + +I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity); + /* NVM Read command (indirect 0x0701) * NVM Erase commands (direct 0x0702) * NVM Update commands (indirect 0x0703) diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h index 365a7d6231a0..51d83c634519 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h @@ -220,6 +220,7 @@ enum i40e_admin_queue_opc { i40e_aqc_opc_get_phy_wol_caps = 0x0621, i40e_aqc_opc_set_phy_debug = 0x0622, i40e_aqc_opc_upload_ext_phy_fm = 0x0625, + i40e_aqc_opc_run_phy_activity = 0x0626, /* NVM commands */ i40e_aqc_opc_nvm_read = 0x0701, @@ -1822,6 +1823,18 @@ enum i40e_aq_phy_reg_type { I40E_AQC_PHY_REG_EXERNAL_MODULE = 0x3 }; +/* Run PHY Activity (0x0626) */ +struct i40e_aqc_run_phy_activity { + __le16 activity_id; + u8 flags; + u8 reserved1; + __le32 control; + __le32 data; + u8 reserved2[4]; +}; + +I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity); + /* NVM Read command (indirect 0x0701) * NVM Erase commands (direct 0x0702) * NVM Update commands (indirect 0x0703) -- cgit v1.2.3 From 5926425368ba8f1b186d45d96020c288e3bb9b8d Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Tue, 22 Dec 2015 14:25:12 -0800 Subject: i40e: AQ Geneve cloud tunnel type Fix the name of the new cloud tunnel type from the place-holder NGE name to the official Geneve. Also fix the spelling of the VXLAN type. Signed-off-by: Shannon Nelson Acked-by: Kevin Scott Signed-off-by: Jeff Kirsher Tested-by: Andrew Bowers --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 4 ++-- drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index 9e340ca03440..eab55eacb01c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -1260,9 +1260,9 @@ struct i40e_aqc_add_remove_cloud_filters_element_data { #define I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT 9 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK 0x1E00 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_XVLAN 0 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_VXLAN 0 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC 1 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NGE 2 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_GENEVE 2 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_IP 3 __le32 tenant_id; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h index 51d83c634519..30b5a33aa424 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h @@ -1257,9 +1257,9 @@ struct i40e_aqc_add_remove_cloud_filters_element_data { #define I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT 9 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK 0x1E00 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_XVLAN 0 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_VXLAN 0 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC 1 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NGE 2 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_GENEVE 2 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_IP 3 __le32 tenant_id; -- cgit v1.2.3 From 5eb772f7ca86267565ef40c7b987c88405689b96 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Tue, 22 Dec 2015 14:25:13 -0800 Subject: i40e: AQ Add external power class to get link status Add the new External Device Power Ability field to the get_link_status data structure, using space from the reserved field at the end of the struct. Signed-off-by: Shannon Nelson Acked-by: Kevin Scott Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 7 ++++++- drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index eab55eacb01c..0e608d2a70d5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -1758,7 +1758,12 @@ struct i40e_aqc_get_link_status { u8 config; #define I40E_AQ_CONFIG_CRC_ENA 0x04 #define I40E_AQ_CONFIG_PACING_MASK 0x78 - u8 reserved[5]; + u8 external_power_ability; +#define I40E_AQ_LINK_POWER_CLASS_1 0x00 +#define I40E_AQ_LINK_POWER_CLASS_2 0x01 +#define I40E_AQ_LINK_POWER_CLASS_3 0x02 +#define I40E_AQ_LINK_POWER_CLASS_4 0x03 + u8 reserved[4]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status); diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h index 30b5a33aa424..578b1780fb08 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h @@ -1755,7 +1755,12 @@ struct i40e_aqc_get_link_status { u8 config; #define I40E_AQ_CONFIG_CRC_ENA 0x04 #define I40E_AQ_CONFIG_PACING_MASK 0x78 - u8 reserved[5]; + u8 external_power_ability; +#define I40E_AQ_LINK_POWER_CLASS_1 0x00 +#define I40E_AQ_LINK_POWER_CLASS_2 0x01 +#define I40E_AQ_LINK_POWER_CLASS_3 0x02 +#define I40E_AQ_LINK_POWER_CLASS_4 0x03 + u8 reserved[4]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status); -- cgit v1.2.3 From f8db54cc4df7b065b0028f8c919e2f47983f2043 Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Tue, 22 Dec 2015 14:25:14 -0800 Subject: i40e: add 100Mb ethtool reporting Add some missing reporting/advertisement of 100Mb capability for adapters that support it. Change-ID: I8b8523fbdc99517bec29d90c71b3744db11542ac Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 4 ++++ drivers/net/ethernet/intel/i40e/i40e_main.c | 1 + 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 8a3f93ddbcc3..45495911c5a4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -411,6 +411,10 @@ static void i40e_get_settings_link_down(struct i40e_hw *hw, if (pf->hw.mac.type == I40E_MAC_X722) { ecmd->supported |= SUPPORTED_100baseT_Full; ecmd->advertising |= ADVERTISED_100baseT_Full; + if (pf->flags & I40E_FLAG_100M_SGMII_CAPABLE) { + ecmd->supported |= SUPPORTED_100baseT_Full; + ecmd->advertising |= ADVERTISED_100baseT_Full; + } } } if (phy_types & I40E_CAP_PHY_TYPE_XAUI || diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 3e482bcd5287..320b0491abd9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8453,6 +8453,7 @@ static int i40e_sw_init(struct i40e_pf *pf) I40E_FLAG_OUTER_UDP_CSUM_CAPABLE | I40E_FLAG_WB_ON_ITR_CAPABLE | I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE | + I40E_FLAG_100M_SGMII_CAPABLE | I40E_FLAG_GENEVE_OFFLOAD_CAPABLE; } pf->eeprom_version = 0xDEAD; -- cgit v1.2.3 From 58d4d32f431a560baff5fbb6deae8ad324552dde Mon Sep 17 00:00:00 2001 From: Ramalingam C Date: Wed, 3 Feb 2016 18:20:46 +0530 Subject: drm/i915/dsi: Configure DSI after enabling DSI pll We need to enable DSI PLL before configuring the DSI registers. This has worked before on BYT/CHV, but BXT is more fussy. Signed-off-by: Ramalingam C Reviewed-by: Mika Kahola Tested-by: Mika Kahola # BXT Tested-by: Jani Nikula # BYT Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1454503846-12103-1-git-send-email-ramalingam.c@intel.com --- drivers/gpu/drm/i915/intel_dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 91cef3525c93..378f879f4015 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -478,8 +478,8 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder) DRM_DEBUG_KMS("\n"); - intel_dsi_prepare(encoder); intel_enable_dsi_pll(encoder); + intel_dsi_prepare(encoder); /* Panel Enable over CRC PMIC */ if (intel_dsi->gpio_panel) -- cgit v1.2.3 From 07550df04712c88717d2ab6578bb36bbd4305e35 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 4 Feb 2016 12:30:56 +0200 Subject: spi: pxa2xx: Update comment in int_transfer_complete() The register writes here actually don't stop the SSP but clean and disable interrupts and set the receive FIFO inactivity timeout to zero. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 227e8bad19e6..9b9a528a9fbd 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -572,7 +572,7 @@ static void int_error_stop(struct driver_data *drv_data, const char* msg) static void int_transfer_complete(struct driver_data *drv_data) { - /* Stop SSP */ + /* Clear and disable interrupts */ write_SSSR_CS(drv_data, drv_data->clear_sr); reset_sccr1(drv_data); if (!pxa25x_ssp_comp(drv_data)) -- cgit v1.2.3 From 7a8d44bc89e5cddcd5c0704a11a90484d36ba6ba Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 4 Feb 2016 12:30:57 +0200 Subject: spi: pxa2xx: Fix too early chipselect deassert There is a chance that chipselect is deasserted too early while the last clock cycle is still running. Protocol analyzers will see this as a failed last byte. This is more likely to occur with slow bitrates, for instance at 25 kbps. Reason for this is when using SPI mode 0 that both SPI host controller and SPI slave will drive the data lines at the falling edge of clock signal and sample at the rising edge. Receive FIFO gets the last bit now at the rising edge and code sees transfer to be finished either by the interrupt in PIO mode or by the DMA completion in DMA mode. The SSP Time Out register SSTO should take care of delaying the completion but it does not seems to have effect at least on Intel Skylake and Broxton even when using long enough values. Depending on timing code may get into point where chipselect is deasserted while the last clock cycle is still running at its second half cycle. Fix this by adding a wait loop in giveback() that waits until SSP becomes idle before deasserting the chipselect. Reported-by: Weifeng Voon Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 9b9a528a9fbd..ce66cf44bba5 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -496,6 +496,7 @@ static void giveback(struct driver_data *drv_data) { struct spi_transfer* last_transfer; struct spi_message *msg; + unsigned long timeout; msg = drv_data->cur_msg; drv_data->cur_msg = NULL; @@ -508,6 +509,12 @@ static void giveback(struct driver_data *drv_data) if (last_transfer->delay_usecs) udelay(last_transfer->delay_usecs); + /* Wait until SSP becomes idle before deasserting the CS */ + timeout = jiffies + msecs_to_jiffies(10); + while (pxa2xx_spi_read(drv_data, SSSR) & SSSR_BSY && + !time_after(jiffies, timeout)) + cpu_relax(); + /* Drop chip select UNLESS cs_change is true or we are returning * a message with an error, or next message is for another chip */ -- cgit v1.2.3 From c29ebb64a553074dc52b6ad36cf0e573d6991c09 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 3 Feb 2016 17:29:41 -0200 Subject: [media] dvb_frontend: print DTV property dump also for SET_PROPERTY When debugging troubles with DTV properties get/set, it is important to be able to see not only the properties from get, but also the ones from set. So, improve the dumps to allow reporting both. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 03cc508b8c42..b1255b7c0b0e 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -1162,18 +1162,24 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { _DTV_CMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0, 0), }; -static void dtv_property_dump(struct dvb_frontend *fe, struct dtv_property *tvp) +static void dtv_property_dump(struct dvb_frontend *fe, + bool is_set, + struct dtv_property *tvp) { int i; if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) { - dev_warn(fe->dvb->device, "%s: tvp.cmd = 0x%08x undefined\n", - __func__, tvp->cmd); + dev_warn(fe->dvb->device, "%s: %s tvp.cmd = 0x%08x undefined\n", + __func__, + is_set ? "SET" : "GET", + tvp->cmd); return; } - dev_dbg(fe->dvb->device, "%s: tvp.cmd = 0x%08x (%s)\n", __func__, - tvp->cmd, dtv_cmds[tvp->cmd].name); + dev_dbg(fe->dvb->device, "%s: %s tvp.cmd = 0x%08x (%s)\n", __func__, + is_set ? "SET" : "GET", + tvp->cmd, + dtv_cmds[tvp->cmd].name); if (dtv_cmds[tvp->cmd].buffer) { dev_dbg(fe->dvb->device, "%s: tvp.u.buffer.len = 0x%02x\n", @@ -1589,7 +1595,7 @@ static int dtv_property_process_get(struct dvb_frontend *fe, return r; } - dtv_property_dump(fe, tvp); + dtv_property_dump(fe, false, tvp); return 0; } @@ -1830,6 +1836,8 @@ static int dtv_property_process_set(struct dvb_frontend *fe, return r; } + dtv_property_dump(fe, true, tvp); + switch(tvp->cmd) { case DTV_CLEAR: /* -- cgit v1.2.3 From e8beb02343e7582980c6705816cd957cf4f74c7a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 3 Feb 2016 17:33:48 -0200 Subject: [media] tda1004x: only update the frontend properties if locked The tda1004x was updating the properties cache before locking. If the device is not locked, the data at the registers are just random values with no real meaning. This caused the driver to fail with libdvbv5, as such library calls GET_PROPERTY from time to time, in order to return the DVB stats. Tested with a saa7134 card 78: ASUSTeK P7131 Dual, vendor PCI ID: 1043:4862 Cc: stable@vger.kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/tda1004x.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/tda1004x.c b/drivers/media/dvb-frontends/tda1004x.c index 0e209b56c76c..c6abeb4fba9d 100644 --- a/drivers/media/dvb-frontends/tda1004x.c +++ b/drivers/media/dvb-frontends/tda1004x.c @@ -903,9 +903,18 @@ static int tda1004x_get_fe(struct dvb_frontend *fe) { struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache; struct tda1004x_state* state = fe->demodulator_priv; + int status; dprintk("%s\n", __func__); + status = tda1004x_read_byte(state, TDA1004X_STATUS_CD); + if (status == -1) + return -EIO; + + /* Only update the properties cache if device is locked */ + if (!(status & 8)) + return 0; + // inversion status fe_params->inversion = INVERSION_OFF; if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20) -- cgit v1.2.3 From fac710e45d0b12443acd4d905c9acec27ab4ca14 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 27 Jan 2016 10:08:42 -0200 Subject: [media] vb2: fix nasty vb2_thread regression The vb2_thread implementation was made generic and was moved from videobuf2-v4l2.c to videobuf2-core.c in commit af3bac1a. Unfortunately that clearly was never tested since it broke read() causing NULL address references. The root cause was confused handling of vb2_buffer vs v4l2_buffer (the pb pointer in various core functions). The v4l2_buffer no longer exists after moving the code into the core and it is no longer needed. However, the vb2_thread code passed a pointer to a vb2_buffer to the core functions were a v4l2_buffer pointer was expected and vb2_thread expected that the vb2_buffer fields would be filled in correctly. This is obviously wrong since v4l2_buffer != vb2_buffer. Note that the pb pointer is a void pointer, so no type-checking took place. This patch fixes this problem: 1) allow pb to be NULL for vb2_core_(d)qbuf. The vb2_thread code will use a NULL pointer here since they don't care about v4l2_buffer anyway. 2) let vb2_core_dqbuf pass back the index of the received buffer. This is all vb2_thread needs: this index is the index into the q->bufs array and vb2_thread just gets the vb2_buffer from there. 3) the fileio->b pointer (that originally contained a v4l2_buffer) is removed altogether since it is no longer needed. Tested with vivid and the cobalt driver. Cc: stable@vger.kernel.org # Kernel >= 4.3 Signed-off-by: Hans Verkuil Reported-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 95 +++++++++++++++----------------- drivers/media/v4l2-core/videobuf2-v4l2.c | 2 +- include/media/videobuf2-core.h | 3 +- 3 files changed, 46 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index c5d49d7a0d76..b53e42c329cb 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1063,8 +1063,11 @@ EXPORT_SYMBOL_GPL(vb2_discard_done); */ static int __qbuf_mmap(struct vb2_buffer *vb, const void *pb) { - int ret = call_bufop(vb->vb2_queue, fill_vb2_buffer, - vb, pb, vb->planes); + int ret = 0; + + if (pb) + ret = call_bufop(vb->vb2_queue, fill_vb2_buffer, + vb, pb, vb->planes); return ret ? ret : call_vb_qop(vb, buf_prepare, vb); } @@ -1077,14 +1080,16 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void *pb) struct vb2_queue *q = vb->vb2_queue; void *mem_priv; unsigned int plane; - int ret; + int ret = 0; enum dma_data_direction dma_dir = q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); /* Copy relevant information provided by the userspace */ - ret = call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes); + if (pb) + ret = call_bufop(vb->vb2_queue, fill_vb2_buffer, + vb, pb, planes); if (ret) return ret; @@ -1192,14 +1197,16 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb) struct vb2_queue *q = vb->vb2_queue; void *mem_priv; unsigned int plane; - int ret; + int ret = 0; enum dma_data_direction dma_dir = q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE; bool reacquired = vb->planes[0].mem_priv == NULL; memset(planes, 0, sizeof(planes[0]) * vb->num_planes); /* Copy relevant information provided by the userspace */ - ret = call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes); + if (pb) + ret = call_bufop(vb->vb2_queue, fill_vb2_buffer, + vb, pb, planes); if (ret) return ret; @@ -1520,7 +1527,8 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) q->waiting_for_buffers = false; vb->state = VB2_BUF_STATE_QUEUED; - call_void_bufop(q, copy_timestamp, vb, pb); + if (pb) + call_void_bufop(q, copy_timestamp, vb, pb); trace_vb2_qbuf(q, vb); @@ -1532,7 +1540,8 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) __enqueue_in_driver(vb); /* Fill buffer information for the userspace */ - call_void_bufop(q, fill_user_buffer, vb, pb); + if (pb) + call_void_bufop(q, fill_user_buffer, vb, pb); /* * If streamon has been called, and we haven't yet called @@ -1731,7 +1740,8 @@ static void __vb2_dqbuf(struct vb2_buffer *vb) * The return values from this function are intended to be directly returned * from vidioc_dqbuf handler in driver. */ -int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking) +int vb2_core_dqbuf(struct vb2_queue *q, unsigned int *pindex, void *pb, + bool nonblocking) { struct vb2_buffer *vb = NULL; int ret; @@ -1754,8 +1764,12 @@ int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking) call_void_vb_qop(vb, buf_finish, vb); + if (pindex) + *pindex = vb->index; + /* Fill buffer information for the userspace */ - call_void_bufop(q, fill_user_buffer, vb, pb); + if (pb) + call_void_bufop(q, fill_user_buffer, vb, pb); /* Remove from videobuf queue */ list_del(&vb->queued_entry); @@ -1828,7 +1842,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q) * that's done in dqbuf, but that's not going to happen when we * cancel the whole queue. Note: this code belongs here, not in * __vb2_dqbuf() since in vb2_internal_dqbuf() there is a critical - * call to __fill_v4l2_buffer() after buf_finish(). That order can't + * call to __fill_user_buffer() after buf_finish(). That order can't * be changed, so we can't move the buf_finish() to __vb2_dqbuf(). */ for (i = 0; i < q->num_buffers; ++i) { @@ -2357,7 +2371,6 @@ struct vb2_fileio_data { unsigned int count; unsigned int type; unsigned int memory; - struct vb2_buffer *b; struct vb2_fileio_buf bufs[VB2_MAX_FRAME]; unsigned int cur_index; unsigned int initial_index; @@ -2410,12 +2423,6 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read) if (fileio == NULL) return -ENOMEM; - fileio->b = kzalloc(q->buf_struct_size, GFP_KERNEL); - if (fileio->b == NULL) { - kfree(fileio); - return -ENOMEM; - } - fileio->read_once = q->fileio_read_once; fileio->write_immediately = q->fileio_write_immediately; @@ -2460,13 +2467,7 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read) * Queue all buffers. */ for (i = 0; i < q->num_buffers; i++) { - struct vb2_buffer *b = fileio->b; - - memset(b, 0, q->buf_struct_size); - b->type = q->type; - b->memory = q->memory; - b->index = i; - ret = vb2_core_qbuf(q, i, b); + ret = vb2_core_qbuf(q, i, NULL); if (ret) goto err_reqbufs; fileio->bufs[i].queued = 1; @@ -2511,7 +2512,6 @@ static int __vb2_cleanup_fileio(struct vb2_queue *q) q->fileio = NULL; fileio->count = 0; vb2_core_reqbufs(q, fileio->memory, &fileio->count); - kfree(fileio->b); kfree(fileio); dprintk(3, "file io emulator closed\n"); } @@ -2539,7 +2539,8 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_ * else is able to provide this information with the write() operation. */ bool copy_timestamp = !read && q->copy_timestamp; - int ret, index; + unsigned index; + int ret; dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n", read ? "read" : "write", (long)*ppos, count, @@ -2564,22 +2565,20 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_ */ index = fileio->cur_index; if (index >= q->num_buffers) { - struct vb2_buffer *b = fileio->b; + struct vb2_buffer *b; /* * Call vb2_dqbuf to get buffer back. */ - memset(b, 0, q->buf_struct_size); - b->type = q->type; - b->memory = q->memory; - ret = vb2_core_dqbuf(q, b, nonblock); + ret = vb2_core_dqbuf(q, &index, NULL, nonblock); dprintk(5, "vb2_dqbuf result: %d\n", ret); if (ret) return ret; fileio->dq_count += 1; - fileio->cur_index = index = b->index; + fileio->cur_index = index; buf = &fileio->bufs[index]; + b = q->bufs[index]; /* * Get number of bytes filled by the driver @@ -2630,7 +2629,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_ * Queue next buffer if required. */ if (buf->pos == buf->size || (!read && fileio->write_immediately)) { - struct vb2_buffer *b = fileio->b; + struct vb2_buffer *b = q->bufs[index]; /* * Check if this is the last buffer to read. @@ -2643,15 +2642,11 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_ /* * Call vb2_qbuf and give buffer to the driver. */ - memset(b, 0, q->buf_struct_size); - b->type = q->type; - b->memory = q->memory; - b->index = index; b->planes[0].bytesused = buf->pos; if (copy_timestamp) b->timestamp = ktime_get_ns(); - ret = vb2_core_qbuf(q, index, b); + ret = vb2_core_qbuf(q, index, NULL); dprintk(5, "vb2_dbuf result: %d\n", ret); if (ret) return ret; @@ -2713,10 +2708,9 @@ static int vb2_thread(void *data) { struct vb2_queue *q = data; struct vb2_threadio_data *threadio = q->threadio; - struct vb2_fileio_data *fileio = q->fileio; bool copy_timestamp = false; - int prequeue = 0; - int index = 0; + unsigned prequeue = 0; + unsigned index = 0; int ret = 0; if (q->is_output) { @@ -2728,37 +2722,34 @@ static int vb2_thread(void *data) for (;;) { struct vb2_buffer *vb; - struct vb2_buffer *b = fileio->b; /* * Call vb2_dqbuf to get buffer back. */ - memset(b, 0, q->buf_struct_size); - b->type = q->type; - b->memory = q->memory; if (prequeue) { - b->index = index++; + vb = q->bufs[index++]; prequeue--; } else { call_void_qop(q, wait_finish, q); if (!threadio->stop) - ret = vb2_core_dqbuf(q, b, 0); + ret = vb2_core_dqbuf(q, &index, NULL, 0); call_void_qop(q, wait_prepare, q); dprintk(5, "file io: vb2_dqbuf result: %d\n", ret); + if (!ret) + vb = q->bufs[index]; } if (ret || threadio->stop) break; try_to_freeze(); - vb = q->bufs[b->index]; - if (b->state == VB2_BUF_STATE_DONE) + if (vb->state == VB2_BUF_STATE_DONE) if (threadio->fnc(vb, threadio->priv)) break; call_void_qop(q, wait_finish, q); if (copy_timestamp) - b->timestamp = ktime_get_ns();; + vb->timestamp = ktime_get_ns();; if (!threadio->stop) - ret = vb2_core_qbuf(q, b->index, b); + ret = vb2_core_qbuf(q, vb->index, NULL); call_void_qop(q, wait_prepare, q); if (ret || threadio->stop) break; diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c index c9a28605511a..91f552124050 100644 --- a/drivers/media/v4l2-core/videobuf2-v4l2.c +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c @@ -625,7 +625,7 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, return -EINVAL; } - ret = vb2_core_dqbuf(q, b, nonblocking); + ret = vb2_core_dqbuf(q, NULL, b, nonblocking); return ret; } diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index ef03ae56b1c1..8a0f55b6c2ba 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -533,7 +533,8 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory, const unsigned int requested_sizes[]); int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb); int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb); -int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking); +int vb2_core_dqbuf(struct vb2_queue *q, unsigned int *pindex, void *pb, + bool nonblocking); int vb2_core_streamon(struct vb2_queue *q, unsigned int type); int vb2_core_streamoff(struct vb2_queue *q, unsigned int type); -- cgit v1.2.3 From 1f2c450185b7b8d50d38d37ee30387ff4cd337f8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 3 Feb 2016 19:30:31 -0200 Subject: [media] vb2-core: call threadio->fnc() if !VB2_BUF_STATE_ERROR changeset 70433a152f0 ("media: videobuf2: Refactor vb2_fileio_data and vb2_thread") broke videobuf2-dvb. The root cause is that, instead of calling threadio->fnc() for all types of events except for VB2_BUF_STATE_ERROR, it was calling it only for VB2_BUF_STATE_DONE. With that, the DVB thread were never called. Cc: stable@vger.kernel.org # Kernel >= 4.3 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index b53e42c329cb..ff8953ae52d1 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -2742,7 +2742,7 @@ static int vb2_thread(void *data) break; try_to_freeze(); - if (vb->state == VB2_BUF_STATE_DONE) + if (vb->state != VB2_BUF_STATE_ERROR) if (threadio->fnc(vb, threadio->priv)) break; call_void_qop(q, wait_finish, q); -- cgit v1.2.3 From 210bd104c6acd31c3c6b8b075b3f12d4a9f6b60d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 3 Feb 2016 13:34:00 -0200 Subject: [media] xc2028: unlock on error in xc2028_set_config() We have to unlock before returning -ENOMEM. Fixes: 8dfbcc4351a0 ('[media] xc2028: avoid use after free') Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/tuner-xc2028.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c index 082ff5608455..317ef63ee789 100644 --- a/drivers/media/tuners/tuner-xc2028.c +++ b/drivers/media/tuners/tuner-xc2028.c @@ -1407,8 +1407,10 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); if (p->fname) { priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); - if (priv->ctrl.fname == NULL) - return -ENOMEM; + if (priv->ctrl.fname == NULL) { + rc = -ENOMEM; + goto unlock; + } } /* @@ -1440,6 +1442,7 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) } else priv->state = XC2028_WAITING_FIRMWARE; } +unlock: mutex_unlock(&priv->lock); return rc; -- cgit v1.2.3 From 2ea9a08d59b99fbb257bcd8c47e2cbc8be136f8c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 09:45:14 -0200 Subject: [media] dvb_frontend: add props argument to dtv_get_frontend() Instead of implicitly using the DTV cache properties at dtv_get_frontend(), pass it as an additional argument. This patch prepares to use a separate cache for G_PROPERTY, in order to avoid it to mangle with the DVB thread zigzag logic. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index b1255b7c0b0e..ca6d60f9d492 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -140,9 +140,12 @@ struct dvb_frontend_private { static void dvb_frontend_wakeup(struct dvb_frontend *fe); static int dtv_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c, struct dvb_frontend_parameters *p_out); -static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, - struct dvb_frontend_parameters *p); +static int +dtv_property_legacy_params_sync(struct dvb_frontend *fe, + const struct dtv_frontend_properties *c, + struct dvb_frontend_parameters *p); static bool has_get_frontend(struct dvb_frontend *fe) { @@ -202,6 +205,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, enum fe_status status) { struct dvb_frontend_private *fepriv = fe->frontend_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dvb_fe_events *events = &fepriv->events; struct dvb_frontend_event *e; int wp; @@ -209,7 +213,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, dev_dbg(fe->dvb->device, "%s:\n", __func__); if ((status & FE_HAS_LOCK) && has_get_frontend(fe)) - dtv_get_frontend(fe, &fepriv->parameters_out); + dtv_get_frontend(fe, c, &fepriv->parameters_out); mutex_lock(&events->mtx); @@ -687,6 +691,7 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe) static int dvb_frontend_thread(void *data) { struct dvb_frontend *fe = data; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dvb_frontend_private *fepriv = fe->frontend_priv; enum fe_status s; enum dvbfe_algo algo; @@ -807,7 +812,7 @@ restart: fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; fepriv->delay = HZ / 2; } - dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); + dtv_property_legacy_params_sync(fe, c, &fepriv->parameters_out); fe->ops.read_status(fe, &s); if (s != fepriv->status) { dvb_frontend_add_event(fe, s); /* update event list */ @@ -1274,11 +1279,11 @@ static int dtv_property_cache_sync(struct dvb_frontend *fe, /* Ensure the cached values are set correctly in the frontend * legacy tuning structures, for the advanced tuning API. */ -static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, - struct dvb_frontend_parameters *p) +static int +dtv_property_legacy_params_sync(struct dvb_frontend *fe, + const struct dtv_frontend_properties *c, + struct dvb_frontend_parameters *p) { - const struct dtv_frontend_properties *c = &fe->dtv_property_cache; - p->frequency = c->frequency; p->inversion = c->inversion; @@ -1350,6 +1355,7 @@ static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, * If p_out is not null, it will update the DVBv3 params pointed by it. */ static int dtv_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c, struct dvb_frontend_parameters *p_out) { int r; @@ -1359,7 +1365,7 @@ static int dtv_get_frontend(struct dvb_frontend *fe, if (unlikely(r < 0)) return r; if (p_out) - dtv_property_legacy_params_sync(fe, p_out); + dtv_property_legacy_params_sync(fe, c, p_out); return 0; } @@ -2107,7 +2113,7 @@ static int dvb_frontend_ioctl_properties(struct file *file, * is not idle. Otherwise, returns the cached content */ if (fepriv->state != FESTATE_IDLE) { - err = dtv_get_frontend(fe, NULL); + err = dtv_get_frontend(fe, c, NULL); if (err < 0) goto out; } @@ -2147,7 +2153,7 @@ static int dtv_set_frontend(struct dvb_frontend *fe) * the user. FE_SET_FRONTEND triggers an initial frontend event * with status = 0, which copies output parameters to userspace. */ - dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); + dtv_property_legacy_params_sync(fe, c, &fepriv->parameters_out); /* * Be sure that the bandwidth will be filled for all @@ -2518,7 +2524,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file, break; case FE_GET_FRONTEND: - err = dtv_get_frontend(fe, parg); + err = dtv_get_frontend(fe, c, parg); break; case FE_SET_FRONTEND_TUNE_MODE: -- cgit v1.2.3 From bb6a777369449d15a4a890306d2f925cae720e1c Mon Sep 17 00:00:00 2001 From: Carol L Soto Date: Wed, 3 Feb 2016 15:55:37 -0500 Subject: IB/IPoIB: Do not set skb truesize since using one linearskb We are seeing this warning: at net/core/skbuff.c:4174 and before commit a44878d10063 ("IB/ipoib: Use one linear skb in RX flow") skb truesize was not being set when ipoib was using just one skb. Removing this line avoids the warning when running tcp tests like iperf. Fixes: a44878d10063 ("IB/ipoib: Use one linear skb in RX flow") Signed-off-by: Carol L Soto Signed-off-by: Doug Ledford --- drivers/infiniband/ulp/ipoib/ipoib_ib.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 5ea0c14070d1..fa9c42ff1fb0 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -245,8 +245,6 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) skb_reset_mac_header(skb); skb_pull(skb, IPOIB_ENCAP_LEN); - skb->truesize = SKB_TRUESIZE(skb->len); - ++dev->stats.rx_packets; dev->stats.rx_bytes += skb->len; -- cgit v1.2.3 From 9f780dab7fb5618ee8bacbf6f91832374231c30c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 25 Jan 2016 18:38:06 +0000 Subject: IB/sysfs: remove unused va_list args _show_port_gid_attr performs a va_end on some unused va_list args. Clean this up by removing the args completely. Fixes: 470be516a226e8 ("IB/core: Add gid attributes to sysfs") Signed-off-by: Colin Ian King Reviewed-by: Ira Weiny Reviewed-by: Jason Gunthorpe Signed-off-by: Doug Ledford --- drivers/infiniband/core/sysfs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 3de93517efe4..ec46386e3c7f 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -336,7 +336,6 @@ static ssize_t _show_port_gid_attr(struct ib_port *p, union ib_gid gid; struct ib_gid_attr gid_attr = {}; ssize_t ret; - va_list args; ret = ib_query_gid(p->ibdev, p->port_num, tab_attr->index, &gid, &gid_attr); @@ -348,7 +347,6 @@ static ssize_t _show_port_gid_attr(struct ib_port *p, err: if (gid_attr.ndev) dev_put(gid_attr.ndev); - va_end(args); return ret; } -- cgit v1.2.3 From aebe3ad801ebbcd90b3649c24ae0e90d2db8bde8 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 27 Jan 2016 21:38:37 +0100 Subject: clk: rockchip: fix parent of hclk_vcodec on rk3036 hclk_vcodec is a child of aclk_vcodec with the fixed factor clock hclk_vcodec_pre in between and not a child of hclk_disp_pre. Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3036.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index 9c317a3b81e5..38139dce9f7e 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -380,7 +380,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { GATE(HCLK_LCDC, "hclk_lcdc", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS), /* hclk_video gates */ - GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(3), 12, GFLAGS), + GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_vcodec_pre", 0, RK2928_CLKGATE_CON(3), 12, GFLAGS), /* xin24m gates */ GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK2928_CLKGATE_CON(10), 0, GFLAGS), -- cgit v1.2.3 From 1a485f4d2e28efd77075b2952926683d6c245633 Mon Sep 17 00:00:00 2001 From: Shanker Donthineni Date: Mon, 1 Feb 2016 20:19:44 -0600 Subject: irqchip/gicv3-its: Fix memory leak in its_free_tables() The current ITS driver has a memory leak in its_free_tables(). It happens on tear down path of the driver when its_probe() call fails. its_free_tables() should free the exact number of pages that have been allocated, not just a single page as current code does. This patch records the memory size for each ITS_BASERn at the time of page allocation and uses the same size information when freeing pages to fix the issue. Signed-off-by: Shanker Donthineni Acked-by: Marc Zyngier Cc: Jason Cooper Cc: Vikram Sethi Cc: linux-arm-kernel@lists.infradead.org Link: http://lkml.kernel.org/r/1454379584-21772-1-git-send-email-shankerd@codeaurora.org Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-gic-v3-its.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 3447549fcc93..0a73632b28d5 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -66,7 +66,10 @@ struct its_node { unsigned long phys_base; struct its_cmd_block *cmd_base; struct its_cmd_block *cmd_write; - void *tables[GITS_BASER_NR_REGS]; + struct { + void *base; + u32 order; + } tables[GITS_BASER_NR_REGS]; struct its_collection *collections; struct list_head its_device_list; u64 flags; @@ -807,9 +810,10 @@ static void its_free_tables(struct its_node *its) int i; for (i = 0; i < GITS_BASER_NR_REGS; i++) { - if (its->tables[i]) { - free_page((unsigned long)its->tables[i]); - its->tables[i] = NULL; + if (its->tables[i].base) { + free_pages((unsigned long)its->tables[i].base, + its->tables[i].order); + its->tables[i].base = NULL; } } } @@ -890,7 +894,8 @@ retry_alloc_baser: goto out_free; } - its->tables[i] = base; + its->tables[i].base = base; + its->tables[i].order = order; retry_baser: val = (virt_to_phys(base) | @@ -940,7 +945,7 @@ retry_baser: * something is horribly wrong... */ free_pages((unsigned long)base, order); - its->tables[i] = NULL; + its->tables[i].base = NULL; switch (psz) { case SZ_16K: -- cgit v1.2.3 From d5165ebd527c54bbe3761fd5810dede32b5246a3 Mon Sep 17 00:00:00 2001 From: Tim Gore Date: Thu, 4 Feb 2016 11:49:34 +0000 Subject: drm/i915: implement WaIncreaseDefaultTLBEntries WaIncreaseDefaultTLBEntries increases the number of TLB entries available for GPGPU workloads and gives significant ( > 10% ) performance gain for some OCL benchmarks. Put this in a new function that can be a place for workarounds that are GT related but not required per ring. This function is called on driver load and also after a reset and on resume, so it is safe for workarounds that get clobbered in these situations. This function currently has just this one workaround. v2: This was originally split into 3 patches but following review feedback was squashed into 1. I have not incorporated some style comments from Chris Wilson as I felt that after defining and intialising a temporary variable and then adding an additional if block to only write the register if the temporary variable had been set, this didn't really give a net gain. v3: Resending in the hope that BAT will run v4: Change subject line to trigger BAT (please!) Signed-off-by: Tim Gore Reviewed-by: Mika Kuoppala Signed-off-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/1454586574-2343-1-git-send-email-tim.gore@intel.com --- drivers/gpu/drm/i915/i915_gem_gtt.c | 21 +++++++++++++++++++++ drivers/gpu/drm/i915/i915_reg.h | 7 +++++++ 2 files changed, 28 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 715a771f0b31..9127f8f3561c 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2132,6 +2132,25 @@ static void i915_address_space_init(struct i915_address_space *vm, list_add_tail(&vm->global_link, &dev_priv->vm_list); } +static void gtt_write_workarounds(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + /* This function is for gtt related workarounds. This function is + * called on driver load and after a GPU reset, so you can place + * workarounds here even if they get overwritten by GPU reset. + */ + /* WaIncreaseDefaultTLBEntries:chv,bdw,skl,bxt */ + if (IS_BROADWELL(dev)) + I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_BDW); + else if (IS_CHERRYVIEW(dev)) + I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV); + else if (IS_SKYLAKE(dev)) + I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL); + else if (IS_BROXTON(dev)) + I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT); +} + int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -2148,6 +2167,8 @@ int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) int i915_ppgtt_init_hw(struct drm_device *dev) { + gtt_write_workarounds(dev); + /* In the case of execlists, PPGTT is enabled by the context descriptor * and the PDPs are contained within the context itself. We don't * need to do anything here. */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c0bd691b41f8..ec6444ae6e2f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8173,4 +8173,11 @@ enum skl_disp_power_wells { #define GEN9_VEBOX_MOCS(i) _MMIO(0xcb00 + (i) * 4) /* Video MOCS registers */ #define GEN9_BLT_MOCS(i) _MMIO(0xcc00 + (i) * 4) /* Blitter MOCS registers */ +/* gamt regs */ +#define GEN8_L3_LRA_1_GPGPU _MMIO(0x4dd4) +#define GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_BDW 0x67F1427F /* max/min for LRA1/2 */ +#define GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV 0x5FF101FF /* max/min for LRA1/2 */ +#define GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL 0x67F1427F /* " " */ +#define GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT 0x5FF101FF /* " " */ + #endif /* _I915_REG_H_ */ -- cgit v1.2.3 From 29a30c269aba4223e2a8b443f443d7def1e43fea Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Sat, 20 Jun 2015 13:08:57 +0200 Subject: clk: rockchip: add a factor clock type Add a clock type for fixed factor clocks. This allows us to define fixed factor clocks where they appear in the clock hierarchy instead of in the init function. The additional factor_gate type, finally allows us to model some last parts of the clock tree correctly. Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/rockchip/clk.h | 28 +++++++++++++++++++++++ 2 files changed, 83 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 62fbe2c6eaaf..ab5052478870 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -265,6 +265,53 @@ static struct clk *rockchip_clk_register_frac_branch(const char *name, return clk; } +static struct clk *rockchip_clk_register_factor_branch(const char *name, + const char *const *parent_names, u8 num_parents, + void __iomem *base, unsigned int mult, unsigned int div, + int gate_offset, u8 gate_shift, u8 gate_flags, + unsigned long flags, spinlock_t *lock) +{ + struct clk *clk; + struct clk_gate *gate = NULL; + struct clk_fixed_factor *fix = NULL; + + /* without gate, register a simple factor clock */ + if (gate_offset == 0) { + return clk_register_fixed_factor(NULL, name, + parent_names[0], flags, mult, + div); + } + + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + return ERR_PTR(-ENOMEM); + + gate->flags = gate_flags; + gate->reg = base + gate_offset; + gate->bit_idx = gate_shift; + gate->lock = lock; + + fix = kzalloc(sizeof(*fix), GFP_KERNEL); + if (!fix) { + kfree(gate); + return ERR_PTR(-ENOMEM); + } + + fix->mult = mult; + fix->div = div; + + clk = clk_register_composite(NULL, name, parent_names, num_parents, + NULL, NULL, + &fix->hw, &clk_fixed_factor_ops, + &gate->hw, &clk_gate_ops, flags); + if (IS_ERR(clk)) { + kfree(fix); + kfree(gate); + } + + return clk; +} + static DEFINE_SPINLOCK(clk_lock); static struct clk **clk_table; static void __iomem *reg_base; @@ -400,6 +447,14 @@ void __init rockchip_clk_register_branches( reg_base + list->muxdiv_offset, list->div_shift, list->div_flags, &clk_lock); break; + case branch_factor: + clk = rockchip_clk_register_factor_branch( + list->name, list->parent_names, + list->num_parents, reg_base, + list->div_shift, list->div_width, + list->gate_offset, list->gate_shift, + list->gate_flags, flags, &clk_lock); + break; } /* none of the cases above matched */ diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index ff8bd23a93ec..39c198bbcbee 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -254,6 +254,7 @@ enum rockchip_clk_branch_type { branch_gate, branch_mmc, branch_inverter, + branch_factor, }; struct rockchip_clk_branch { @@ -508,6 +509,33 @@ struct rockchip_clk_branch { .div_flags = if, \ } +#define FACTOR(_id, cname, pname, f, fm, fd) \ + { \ + .id = _id, \ + .branch_type = branch_factor, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .flags = f, \ + .div_shift = fm, \ + .div_width = fd, \ + } + +#define FACTOR_GATE(_id, cname, pname, f, fm, fd, go, gb, gf) \ + { \ + .id = _id, \ + .branch_type = branch_factor, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .flags = f, \ + .div_shift = fm, \ + .div_width = fd, \ + .gate_offset = go, \ + .gate_shift = gb, \ + .gate_flags = gf, \ + } + void rockchip_clk_init(struct device_node *np, void __iomem *base, unsigned long nr_clks); struct regmap *rockchip_clk_get_grf(void); -- cgit v1.2.3 From 36714529f8bbd4f8eaf93b50f4a64c52a24879aa Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Sat, 20 Jun 2015 16:06:02 +0200 Subject: clk: rockchip: convert manually created factor clocks to the new type Clean up the init code and move the creation of factor clocks to the appropriate positions coming from the clock architecture diagrams. This also unifies the artificial separation of the hclk_vcodec etc clocks again. We do keep the separate definition of some watchdog and usb480m pseudo clocks for now, as they're not real factor clocks from the clock-tree but placeholders for fixes to come (usb480m gets supplied by the missing driver for the new usbphy type and the watchdog-gate is sitting somewhere else together which we cannot model currently). Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3036.c | 31 ++++++------------------------- drivers/clk/rockchip/clk-rk3188.c | 9 ++------- drivers/clk/rockchip/clk-rk3228.c | 32 +++++--------------------------- drivers/clk/rockchip/clk-rk3288.c | 22 +++++----------------- drivers/clk/rockchip/clk-rk3368.c | 28 ++++++---------------------- 5 files changed, 24 insertions(+), 98 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index 38139dce9f7e..5759d75780cf 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -177,6 +177,8 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { GATE(0, "gpll_armclk", "gpll", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(0), 6, GFLAGS), + FACTOR(0, "xin12m", "xin24m", 0, 1, 2), + /* * Clock-Architecture Diagram 2 */ @@ -187,6 +189,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { RK2928_CLKGATE_CON(0), 8, GFLAGS), COMPOSITE_NOGATE(0, "ddrphy2x", mux_ddrphy_p, CLK_IGNORE_UNUSED, RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO), + FACTOR(0, "ddrphy", "ddrphy2x", 0, 1, 2), COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED, RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, @@ -263,6 +266,8 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { COMPOSITE(0, "aclk_vcodec", mux_pll_src_3plls_p, 0, RK2928_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS, RK2928_CLKGATE_CON(3), 11, GFLAGS), + FACTOR_GATE(HCLK_VCODEC, "hclk_vcodec", "aclk_vcodec", 0, 1, 4, + RK2928_CLKGATE_CON(3), 12, GFLAGS), COMPOSITE(0, "aclk_hvec", mux_pll_src_3plls_p, 0, RK2928_CLKSEL_CON(20), 0, 2, MFLAGS, 2, 5, DFLAGS, @@ -351,6 +356,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { COMPOSITE_NOMUX(SCLK_MAC, "mac_clk", "mac_clk_ref", 0, RK2928_CLKSEL_CON(21), 9, 5, DFLAGS, RK2928_CLKGATE_CON(2), 6, GFLAGS), + FACTOR(0, "sclk_macref_out", "hclk_peri_src", 0, 1, 2), MUX(SCLK_HDMI, "dclk_hdmi", mux_dclk_p, 0, RK2928_CLKSEL_CON(31), 0, 1, MFLAGS), @@ -379,8 +385,6 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { GATE(HCLK_VIO_BUS, "hclk_vio_bus", "hclk_disp_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(6), 12, GFLAGS), GATE(HCLK_LCDC, "hclk_lcdc", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS), - /* hclk_video gates */ - GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_vcodec_pre", 0, RK2928_CLKGATE_CON(3), 12, GFLAGS), /* xin24m gates */ GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK2928_CLKGATE_CON(10), 0, GFLAGS), @@ -444,34 +448,11 @@ static void __init rk3036_clk_init(struct device_node *np) rockchip_clk_init(np, reg_base, CLK_NR_CLKS); - /* xin12m is created by an cru-internal divider */ - clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock xin12m: %ld\n", - __func__, PTR_ERR(clk)); - clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1); if (IS_ERR(clk)) pr_warn("%s: could not register clock usb480m: %ld\n", __func__, PTR_ERR(clk)); - clk = clk_register_fixed_factor(NULL, "ddrphy", "ddrphy2x", 0, 1, 2); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock ddrphy: %ld\n", - __func__, PTR_ERR(clk)); - - clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre", - "aclk_vcodec", 0, 1, 4); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n", - __func__, PTR_ERR(clk)); - - clk = clk_register_fixed_factor(NULL, "sclk_macref_out", - "hclk_peri_src", 0, 1, 2); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock sclk_macref_out: %ld\n", - __func__, PTR_ERR(clk)); - rockchip_clk_register_plls(rk3036_pll_clks, ARRAY_SIZE(rk3036_pll_clks), RK3036_GRF_SOC_STATUS0); diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index 629c65df1f2d..40bab3901491 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -339,6 +339,8 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { INVERTER(0, "pclk_cif0", "pclkin_cif0", RK2928_CLKSEL_CON(30), 8, IFLAGS), + FACTOR(0, "xin12m", "xin24m", 0, 1, 2), + /* * the 480m are generated inside the usb block from these clocks, * but they are also a source for the hsicphy clock. @@ -754,7 +756,6 @@ static const char *const rk3188_critical_clocks[] __initconst = { static void __init rk3188_common_clk_init(struct device_node *np) { void __iomem *reg_base; - struct clk *clk; reg_base = of_iomap(np, 0); if (!reg_base) { @@ -764,12 +765,6 @@ static void __init rk3188_common_clk_init(struct device_node *np) rockchip_clk_init(np, reg_base, CLK_NR_CLKS); - /* xin12m is created by an cru-internal divider */ - clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock xin12m: %ld\n", - __func__, PTR_ERR(clk)); - rockchip_clk_register_branches(common_clk_branches, ARRAY_SIZE(common_clk_branches)); diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index 97f49aab8d42..c515915850a1 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c @@ -187,7 +187,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { RK2928_CLKGATE_CON(7), 1, GFLAGS), GATE(0, "ddrc", "ddrphy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 5, GFLAGS), - GATE(0, "ddrphy", "ddrphy_pre", CLK_IGNORE_UNUSED, + FACTOR_GATE(0, "ddrphy", "ddrphy4x", CLK_IGNORE_UNUSED, 1, 4, RK2928_CLKGATE_CON(7), 0, GFLAGS), /* PD_CORE */ @@ -240,13 +240,13 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { COMPOSITE(0, "aclk_vpu_pre", mux_pll_src_4plls_p, 0, RK2928_CLKSEL_CON(32), 5, 2, MFLAGS, 0, 5, DFLAGS, RK2928_CLKGATE_CON(3), 11, GFLAGS), - GATE(0, "hclk_vpu_src", "aclk_vpu_pre", 0, + FACTOR_GATE(0, "hclk_vpu_pre", "aclk_vpu_pre", 0, 1, 4, RK2928_CLKGATE_CON(4), 4, GFLAGS), COMPOSITE(0, "aclk_rkvdec_pre", mux_pll_src_4plls_p, 0, RK2928_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS, RK2928_CLKGATE_CON(3), 2, GFLAGS), - GATE(0, "hclk_rkvdec_src", "aclk_rkvdec_pre", 0, + FACTOR_GATE(0, "hclk_rkvdec_pre", "aclk_rkvdec_pre", 0, 1, 4, RK2928_CLKGATE_CON(4), 5, GFLAGS), COMPOSITE(0, "sclk_vdec_cabac", mux_pll_src_4plls_p, 0, @@ -371,6 +371,8 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { MUX(0, "dclk_vop", mux_dclk_vop_p, 0, RK2928_CLKSEL_CON(27), 1, 1, MFLAGS), + FACTOR(0, "xin12m", "xin24m", 0, 1, 2), + COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0, RK2928_CLKSEL_CON(9), 15, 1, MFLAGS, 0, 7, DFLAGS, RK2928_CLKGATE_CON(0), 3, GFLAGS), @@ -624,7 +626,6 @@ static const char *const rk3228_critical_clocks[] __initconst = { static void __init rk3228_clk_init(struct device_node *np) { void __iomem *reg_base; - struct clk *clk; reg_base = of_iomap(np, 0); if (!reg_base) { @@ -634,29 +635,6 @@ static void __init rk3228_clk_init(struct device_node *np) rockchip_clk_init(np, reg_base, CLK_NR_CLKS); - /* xin12m is created by an cru-internal divider */ - clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock xin12m: %ld\n", - __func__, PTR_ERR(clk)); - - clk = clk_register_fixed_factor(NULL, "ddrphy_pre", "ddrphy4x", 0, 1, 4); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock ddrphy_pre: %ld\n", - __func__, PTR_ERR(clk)); - - clk = clk_register_fixed_factor(NULL, "hclk_vpu_pre", - "hclk_vpu_src", 0, 1, 4); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock hclk_vpu_pre: %ld\n", - __func__, PTR_ERR(clk)); - - clk = clk_register_fixed_factor(NULL, "hclk_rkvdec_pre", - "hclk_rkvdec_src", 0, 1, 4); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock hclk_rkvdec_pre: %ld\n", - __func__, PTR_ERR(clk)); - rockchip_clk_register_plls(rk3228_pll_clks, ARRAY_SIZE(rk3228_pll_clks), RK3228_GRF_SOC_STATUS0); diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 0d23937c594a..3cb72163a512 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -333,6 +333,8 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { GATE(0, "aclk_bus_2pmu", "aclk_cpu_pre", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(0), 7, GFLAGS), + FACTOR(0, "xin12m", "xin24m", 0, 1, 2), + COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0, RK3288_CLKSEL_CON(4), 15, 1, MFLAGS, 0, 7, DFLAGS, RK3288_CLKGATE_CON(4), 1, GFLAGS), @@ -399,12 +401,10 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { */ GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vdpu", 0, RK3288_CLKGATE_CON(9), 0, GFLAGS), - /* - * We introduce a virtul node of hclk_vodec_pre_v to split one clock - * struct with a gate and a fix divider into two node in software. - */ - GATE(0, "hclk_vcodec_pre_v", "aclk_vdpu", 0, + + FACTOR_GATE(0, "hclk_vcodec_pre", "aclk_vdpu", 0, 1, 4, RK3288_CLKGATE_CON(3), 10, GFLAGS), + GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_vcodec_pre", 0, RK3288_CLKGATE_CON(9), 1, GFLAGS), @@ -888,18 +888,6 @@ static void __init rk3288_clk_init(struct device_node *np) rockchip_clk_init(np, rk3288_cru_base, CLK_NR_CLKS); - /* xin12m is created by an cru-internal divider */ - clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock xin12m: %ld\n", - __func__, PTR_ERR(clk)); - - clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre", - "hclk_vcodec_pre_v", 0, 1, 4); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n", - __func__, PTR_ERR(clk)); - /* Watchdog pclk is controlled by RK3288_SGRF_SOC_CON0[1]. */ clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1); if (IS_ERR(clk)) diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index e90abe8bf7c0..31facd8426f7 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -248,6 +248,8 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { * Clock-Architecture Diagram 2 */ + FACTOR(0, "xin12m", "xin24m", 0, 1, 2), + MUX(SCLK_USBPHY480M, "usbphy_480m", mux_usbphy480m_p, CLK_SET_RATE_PARENT, RK3368_CLKSEL_CON(13), 8, 1, MFLAGS), @@ -299,7 +301,7 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { COMPOSITE_NOGATE_DIVTBL(0, "ddrphy_src", mux_ddrphy_p, CLK_IGNORE_UNUSED, RK3368_CLKSEL_CON(13), 4, 1, MFLAGS, 0, 2, DFLAGS, div_ddrphy_t), - GATE(0, "sclk_ddr", "ddrphy_div4", CLK_IGNORE_UNUSED, + FACTOR_GATE(0, "sclk_ddr", "ddrphy_src", CLK_IGNORE_UNUSED, 1, 4, RK3368_CLKGATE_CON(6), 14, GFLAGS), GATE(0, "sclk_ddr4x", "ddrphy_src", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(6), 15, GFLAGS), @@ -392,10 +394,10 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { RK3368_CLKGATE_CON(4), 7, GFLAGS), /* - * We introduce a virtual node of hclk_vodec_pre_v to split one clock - * struct with a gate and a fix divider into two node in software. + * We use aclk_vdpu by default ---GRF_SOC_CON0[7] setting in system, + * so we ignore the mux and make clocks nodes as following, */ - GATE(0, "hclk_video_pre_v", "aclk_vdpu", 0, + FACTOR_GATE(0, "hclk_video_pre", "aclk_vdpu", 0, 1, 4, RK3368_CLKGATE_CON(4), 8, GFLAGS), COMPOSITE(0, "sclk_hevc_cabac_src", mux_pll_src_cpll_gpll_npll_usb_p, 0, @@ -842,24 +844,6 @@ static void __init rk3368_clk_init(struct device_node *np) rockchip_clk_init(np, reg_base, CLK_NR_CLKS); - /* xin12m is created by a cru-internal divider */ - clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock xin12m: %ld\n", - __func__, PTR_ERR(clk)); - - /* ddrphy_div4 is created by a cru-internal divider */ - clk = clk_register_fixed_factor(NULL, "ddrphy_div4", "ddrphy_src", 0, 1, 4); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock xin12m: %ld\n", - __func__, PTR_ERR(clk)); - - clk = clk_register_fixed_factor(NULL, "hclk_video_pre", - "hclk_video_pre_v", 0, 1, 4); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n", - __func__, PTR_ERR(clk)); - /* Watchdog pclk is controlled by sgrf_soc_con3[7]. */ clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1); if (IS_ERR(clk)) -- cgit v1.2.3 From 3eb7c38bfed5dc6ea0e24c8bc2fd249760bdde8c Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 29 Jan 2016 18:57:38 -0200 Subject: drm/i915: don't deactivate FBC at skylake_disable_primary_plane FBC is already deactivated at this point. Besides, nothing should be calling these lower-level function pointers. A few months ago, the only caller of dev_priv->fbc.deactivate was intel_pipe_set_base_atomic(), which was the kgdboc function. But the following commit added it to the SKL function: commit a8d201af68506b375b701d0d8dbe8487034256f2 Author: Maarten Lankhorst Date: Thu Jan 7 11:54:11 2016 +0100 drm/i915: Use plane state for primary plane updates. Cc: Maarten Lankhorst Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1454101060-23198-1-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_display.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a66220ad2e4a..186d6cadba84 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3156,9 +3156,6 @@ static void skylake_disable_primary_plane(struct drm_plane *primary, struct drm_i915_private *dev_priv = dev->dev_private; int pipe = to_intel_crtc(crtc)->pipe; - if (dev_priv->fbc.deactivate) - dev_priv->fbc.deactivate(dev_priv); - I915_WRITE(PLANE_CTL(pipe, 0), 0); I915_WRITE(PLANE_SURF(pipe, 0), 0); POSTING_READ(PLANE_SURF(pipe, 0)); -- cgit v1.2.3 From 8c40074cb219f8e5e6122d17fad869bc43c3e9df Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 29 Jan 2016 18:57:39 -0200 Subject: drm/i915/fbc: unexport the HW level activation functions The recent introduction of a new caller of dev_priv->fbc.deactivate() is a good example of why we need unexport those functions. Anything outside intel_fbc.c should only call the functions exported by intel_fbc.c, so in order to enforce that, kill the function pointers stored inside dev_priv->fbc and replace them with functions that can't be called from outside intel_fbc.c. This should make it much harder for new code to call these functions from outside intel_fbc.c. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1454101060-23198-2-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 4 --- drivers/gpu/drm/i915/intel_fbc.c | 65 ++++++++++++++++++++++++---------------- 2 files changed, 40 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 77227a39f3d5..856bfe8d1f42 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -964,10 +964,6 @@ struct intel_fbc { } work; const char *no_fbc_reason; - - bool (*is_active)(struct drm_i915_private *dev_priv); - void (*activate)(struct drm_i915_private *dev_priv); - void (*deactivate)(struct drm_i915_private *dev_priv); }; /** diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 5adf6d7620ad..8d3caf26fc53 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -43,7 +43,7 @@ static inline bool fbc_supported(struct drm_i915_private *dev_priv) { - return dev_priv->fbc.activate != NULL; + return HAS_FBC(dev_priv); } static inline bool fbc_on_pipe_a_only(struct drm_i915_private *dev_priv) @@ -343,6 +343,38 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv) intel_fbc_recompress(dev_priv); } +static bool intel_fbc_hw_is_active(struct drm_i915_private *dev_priv) +{ + if (INTEL_INFO(dev_priv)->gen >= 5) + return ilk_fbc_is_active(dev_priv); + else if (IS_GM45(dev_priv)) + return g4x_fbc_is_active(dev_priv); + else + return i8xx_fbc_is_active(dev_priv); +} + +static void intel_fbc_hw_activate(struct drm_i915_private *dev_priv) +{ + if (INTEL_INFO(dev_priv)->gen >= 7) + gen7_fbc_activate(dev_priv); + else if (INTEL_INFO(dev_priv)->gen >= 5) + ilk_fbc_activate(dev_priv); + else if (IS_GM45(dev_priv)) + g4x_fbc_activate(dev_priv); + else + i8xx_fbc_activate(dev_priv); +} + +static void intel_fbc_hw_deactivate(struct drm_i915_private *dev_priv) +{ + if (INTEL_INFO(dev_priv)->gen >= 5) + ilk_fbc_deactivate(dev_priv); + else if (IS_GM45(dev_priv)) + g4x_fbc_deactivate(dev_priv); + else + i8xx_fbc_deactivate(dev_priv); +} + /** * intel_fbc_is_active - Is FBC active? * @dev_priv: i915 device instance @@ -405,7 +437,7 @@ retry: goto retry; } - fbc->activate(dev_priv); + intel_fbc_hw_activate(dev_priv); work->scheduled = false; @@ -451,7 +483,7 @@ static void intel_fbc_deactivate(struct drm_i915_private *dev_priv) fbc->work.scheduled = false; if (fbc->active) - fbc->deactivate(dev_priv); + intel_fbc_hw_deactivate(dev_priv); } static bool multiple_pipes_ok(struct intel_crtc *crtc) @@ -713,7 +745,7 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc) /* FIXME: We lack the proper locking here, so only run this on the * platforms that need. */ - if (dev_priv->fbc.activate == ilk_fbc_activate) + if (INTEL_INFO(dev_priv)->gen >= 5 && INTEL_INFO(dev_priv)->gen < 7) cache->fb.ilk_ggtt_offset = i915_gem_obj_ggtt_offset(obj); cache->fb.pixel_format = fb->pixel_format; cache->fb.stride = fb->pitches[0]; @@ -1223,30 +1255,13 @@ void intel_fbc_init(struct drm_i915_private *dev_priv) break; } - if (INTEL_INFO(dev_priv)->gen >= 7) { - fbc->is_active = ilk_fbc_is_active; - fbc->activate = gen7_fbc_activate; - fbc->deactivate = ilk_fbc_deactivate; - } else if (INTEL_INFO(dev_priv)->gen >= 5) { - fbc->is_active = ilk_fbc_is_active; - fbc->activate = ilk_fbc_activate; - fbc->deactivate = ilk_fbc_deactivate; - } else if (IS_GM45(dev_priv)) { - fbc->is_active = g4x_fbc_is_active; - fbc->activate = g4x_fbc_activate; - fbc->deactivate = g4x_fbc_deactivate; - } else { - fbc->is_active = i8xx_fbc_is_active; - fbc->activate = i8xx_fbc_activate; - fbc->deactivate = i8xx_fbc_deactivate; - - /* This value was pulled out of someone's hat */ + /* This value was pulled out of someone's hat */ + if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_GM45(dev_priv)) I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT); - } /* We still don't have any sort of hardware state readout for FBC, so * deactivate it in case the BIOS activated it to make sure software * matches the hardware state. */ - if (fbc->is_active(dev_priv)) - fbc->deactivate(dev_priv); + if (intel_fbc_hw_is_active(dev_priv)) + intel_fbc_hw_deactivate(dev_priv); } -- cgit v1.2.3 From 5375ce9f38291c1d725db40519465dfe89c60ea9 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 29 Jan 2016 18:57:40 -0200 Subject: drm/i915/fbc: set fbc->active from the new activation functions Now that we have top-level gen-independent hw_activate and hw_deactivate functions, set fbc->active directly from them, removing the duplicated code. Reviewed-by: Maarten Lankhorst Signed-off-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/1454101060-23198-3-git-send-email-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_fbc.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 8d3caf26fc53..3614a951736b 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -115,8 +115,6 @@ static void i8xx_fbc_deactivate(struct drm_i915_private *dev_priv) { u32 fbc_ctl; - dev_priv->fbc.active = false; - /* Disable compression */ fbc_ctl = I915_READ(FBC_CONTROL); if ((fbc_ctl & FBC_CTL_EN) == 0) @@ -139,8 +137,6 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv) int i; u32 fbc_ctl; - dev_priv->fbc.active = true; - /* Note: fbc.threshold == 1 for i8xx */ cfb_pitch = params->cfb_size / FBC_LL_SIZE; if (params->fb.stride < cfb_pitch) @@ -187,8 +183,6 @@ static void g4x_fbc_activate(struct drm_i915_private *dev_priv) struct intel_fbc_reg_params *params = &dev_priv->fbc.params; u32 dpfc_ctl; - dev_priv->fbc.active = true; - dpfc_ctl = DPFC_CTL_PLANE(params->crtc.plane) | DPFC_SR_EN; if (drm_format_plane_cpp(params->fb.pixel_format, 0) == 2) dpfc_ctl |= DPFC_CTL_LIMIT_2X; @@ -206,8 +200,6 @@ static void g4x_fbc_deactivate(struct drm_i915_private *dev_priv) { u32 dpfc_ctl; - dev_priv->fbc.active = false; - /* Disable compression */ dpfc_ctl = I915_READ(DPFC_CONTROL); if (dpfc_ctl & DPFC_CTL_EN) { @@ -234,8 +226,6 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv) u32 dpfc_ctl; int threshold = dev_priv->fbc.threshold; - dev_priv->fbc.active = true; - dpfc_ctl = DPFC_CTL_PLANE(params->crtc.plane); if (drm_format_plane_cpp(params->fb.pixel_format, 0) == 2) threshold++; @@ -274,8 +264,6 @@ static void ilk_fbc_deactivate(struct drm_i915_private *dev_priv) { u32 dpfc_ctl; - dev_priv->fbc.active = false; - /* Disable compression */ dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); if (dpfc_ctl & DPFC_CTL_EN) { @@ -295,8 +283,6 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv) u32 dpfc_ctl; int threshold = dev_priv->fbc.threshold; - dev_priv->fbc.active = true; - dpfc_ctl = 0; if (IS_IVYBRIDGE(dev_priv)) dpfc_ctl |= IVB_DPFC_CTL_PLANE(params->crtc.plane); @@ -355,6 +341,10 @@ static bool intel_fbc_hw_is_active(struct drm_i915_private *dev_priv) static void intel_fbc_hw_activate(struct drm_i915_private *dev_priv) { + struct intel_fbc *fbc = &dev_priv->fbc; + + fbc->active = true; + if (INTEL_INFO(dev_priv)->gen >= 7) gen7_fbc_activate(dev_priv); else if (INTEL_INFO(dev_priv)->gen >= 5) @@ -367,6 +357,10 @@ static void intel_fbc_hw_activate(struct drm_i915_private *dev_priv) static void intel_fbc_hw_deactivate(struct drm_i915_private *dev_priv) { + struct intel_fbc *fbc = &dev_priv->fbc; + + fbc->active = false; + if (INTEL_INFO(dev_priv)->gen >= 5) ilk_fbc_deactivate(dev_priv); else if (IS_GM45(dev_priv)) -- cgit v1.2.3 From 16c6d048d7b74249a4387700887e8adb13028866 Mon Sep 17 00:00:00 2001 From: Wenwei Tao Date: Thu, 4 Feb 2016 15:13:23 +0100 Subject: lightnvm: put bio before return MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bio is not returned if the data page cannot be allocated. Signed-off-by: Wenwei Tao Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/rrpc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c index d8c75958ced3..307db1ea22de 100644 --- a/drivers/lightnvm/rrpc.c +++ b/drivers/lightnvm/rrpc.c @@ -300,8 +300,10 @@ static int rrpc_move_valid_pages(struct rrpc *rrpc, struct rrpc_block *rblk) } page = mempool_alloc(rrpc->page_pool, GFP_NOIO); - if (!page) + if (!page) { + bio_put(bio); return -ENOMEM; + } while ((slot = find_first_zero_bit(rblk->invalid_pages, nr_pgs_per_blk)) < nr_pgs_per_blk) { -- cgit v1.2.3 From bba7f40a029c1e2966146e3a021b3deaf5639904 Mon Sep 17 00:00:00 2001 From: Javier González Date: Thu, 4 Feb 2016 15:13:24 +0100 Subject: lightnvm: warn if irqs are disabled in lock laddr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a warning if irqs are disabled when locking a new address in rrpc. The typical path to a new request does not disable irqs, but this is not guaranteed in the future. Signed-off-by: Javier González Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/rrpc.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/lightnvm/rrpc.h b/drivers/lightnvm/rrpc.h index ef13ac7700c8..b0277cbf93d6 100644 --- a/drivers/lightnvm/rrpc.h +++ b/drivers/lightnvm/rrpc.h @@ -184,6 +184,8 @@ static int __rrpc_lock_laddr(struct rrpc *rrpc, sector_t laddr, sector_t laddr_end = laddr + pages - 1; struct rrpc_inflight_rq *rtmp; + WARN_ON(irqs_disabled()); + spin_lock_irq(&rrpc->inflights.lock); list_for_each_entry(rtmp, &rrpc->inflights.reqs, list) { if (unlikely(request_intersects(rtmp, laddr, laddr_end))) { -- cgit v1.2.3 From 3704e098cc1a4c2cabcf4e1cfbbff38b4bfb1ea7 Mon Sep 17 00:00:00 2001 From: Javier González Date: Thu, 4 Feb 2016 15:13:25 +0100 Subject: lightnvm: fix request intersection locking in rrpc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes an error on the calculation of intersecting logical addresses; it contemplates the case where a new request including several addresses intersects with a single locked address. This case is typical when multiple pages are sent in a new request, while GC - which at the moment sends one address at the time - is running. Signed-off-by: Javier González Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/rrpc.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/lightnvm/rrpc.h b/drivers/lightnvm/rrpc.h index b0277cbf93d6..f7b37336353f 100644 --- a/drivers/lightnvm/rrpc.h +++ b/drivers/lightnvm/rrpc.h @@ -174,8 +174,7 @@ static inline sector_t rrpc_get_sector(sector_t laddr) static inline int request_intersects(struct rrpc_inflight_rq *r, sector_t laddr_start, sector_t laddr_end) { - return (laddr_end >= r->l_start && laddr_end <= r->l_end) && - (laddr_start >= r->l_start && laddr_start <= r->l_end); + return (laddr_end >= r->l_start) && (laddr_start <= r->l_end); } static int __rrpc_lock_laddr(struct rrpc *rrpc, sector_t laddr, -- cgit v1.2.3 From 6dde1d6c9094a7c20a680aa2196ad6d032ec7ded Mon Sep 17 00:00:00 2001 From: Matias Bjørling Date: Thu, 4 Feb 2016 15:13:26 +0100 Subject: lightnvm: check overflow and correct mlc pairs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The specification currently limits the number of MLC pairs to 886. Make sure that a device is unable to be instantiate if more is configured. Also, previously the patch had the wrong math for copying MLC pairs, as it only copied half of the actual entries. Fixes: ca5927e7ab53 "lightnvm: introduce mlc lower page table mappings" Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/nvme/host/lightnvm.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c index 5cd3725e2fa4..6bb15e4926dc 100644 --- a/drivers/nvme/host/lightnvm.c +++ b/drivers/nvme/host/lightnvm.c @@ -146,9 +146,10 @@ struct nvme_nvm_command { }; }; +#define NVME_NVM_LP_MLC_PAIRS 886 struct nvme_nvm_lp_mlc { __u16 num_pairs; - __u8 pairs[886]; + __u8 pairs[NVME_NVM_LP_MLC_PAIRS]; }; struct nvme_nvm_lp_tbl { @@ -282,9 +283,14 @@ static int init_grps(struct nvm_id *nvm_id, struct nvme_nvm_id *nvme_nvm_id) memcpy(dst->lptbl.id, src->lptbl.id, 8); dst->lptbl.mlc.num_pairs = le16_to_cpu(src->lptbl.mlc.num_pairs); - /* 4 bits per pair */ + + if (dst->lptbl.mlc.num_pairs > NVME_NVM_LP_MLC_PAIRS) { + pr_err("nvm: number of MLC pairs not supported\n"); + return -EINVAL; + } + memcpy(dst->lptbl.mlc.pairs, src->lptbl.mlc.pairs, - dst->lptbl.mlc.num_pairs >> 1); + dst->lptbl.mlc.num_pairs); } } -- cgit v1.2.3 From bf64318564c43385ffc3d3dfedab5287bdf3dfdd Mon Sep 17 00:00:00 2001 From: Matias Bjørling Date: Thu, 4 Feb 2016 15:13:27 +0100 Subject: lightnvm: allow to force mm initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit System block allows the device to initialize with its configured media manager. The system blocks is written to disk, and read again when media manager is determined. For this to work, the backend must store the data. Device drivers, such as null_blk, does not have any backend storage. This patch allows the media manager to be initialized without a storage backend. It also fix incorrect configuration of capabilities in null_blk, as it does not support get/set bad block interface. Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/block/null_blk.c | 2 +- drivers/lightnvm/core.c | 25 ++++++++++++++++--------- include/linux/lightnvm.h | 4 ++++ 3 files changed, 21 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c index 8ba1e97d573c..ae05d31c0559 100644 --- a/drivers/block/null_blk.c +++ b/drivers/block/null_blk.c @@ -478,7 +478,7 @@ static int null_lnvm_id(struct nvm_dev *dev, struct nvm_id *id) id->ver_id = 0x1; id->vmnt = 0; id->cgrps = 1; - id->cap = 0x3; + id->cap = 0x2; id->dom = 0x1; id->ppaf.blk_offset = 0; diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index 33224cb91c5b..9f6acd5d1d2e 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -572,11 +572,13 @@ int nvm_register(struct request_queue *q, char *disk_name, } } - ret = nvm_get_sysblock(dev, &dev->sb); - if (!ret) - pr_err("nvm: device not initialized.\n"); - else if (ret < 0) - pr_err("nvm: err (%d) on device initialization\n", ret); + if (dev->identity.cap & NVM_ID_DCAP_BBLKMGMT) { + ret = nvm_get_sysblock(dev, &dev->sb); + if (!ret) + pr_err("nvm: device not initialized.\n"); + else if (ret < 0) + pr_err("nvm: err (%d) on device initialization\n", ret); + } /* register device with a supported media manager */ down_write(&nvm_lock); @@ -1055,9 +1057,11 @@ static long __nvm_ioctl_dev_init(struct nvm_ioctl_dev_init *init) strncpy(info.mmtype, init->mmtype, NVM_MMTYPE_LEN); info.fs_ppa.ppa = -1; - ret = nvm_init_sysblock(dev, &info); - if (ret) - return ret; + if (dev->identity.cap & NVM_ID_DCAP_BBLKMGMT) { + ret = nvm_init_sysblock(dev, &info); + if (ret) + return ret; + } memcpy(&dev->sb, &info, sizeof(struct nvm_sb_info)); @@ -1117,7 +1121,10 @@ static long nvm_ioctl_dev_factory(struct file *file, void __user *arg) dev->mt = NULL; } - return nvm_dev_factory(dev, fact.flags); + if (dev->identity.cap & NVM_ID_DCAP_BBLKMGMT) + return nvm_dev_factory(dev, fact.flags); + + return 0; } static long nvm_ctl_ioctl(struct file *file, uint cmd, unsigned long arg) diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index d6750111e48e..2190419bdf0a 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -135,6 +135,10 @@ enum { /* Memory types */ NVM_ID_FMTYPE_SLC = 0, NVM_ID_FMTYPE_MLC = 1, + + /* Device capabilities */ + NVM_ID_DCAP_BBLKMGMT = 0x1, + NVM_UD_DCAP_ECC = 0x2, }; struct nvm_id_lp_mlc { -- cgit v1.2.3 From 5d2d0a12d3d08bf50434f0b5947bb73bac04b941 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 4 Feb 2016 12:50:49 +0200 Subject: drm/i915/dsi: defend gpio table against out of bounds access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not blindly trust the VBT data used for indexing. Cc: stable@vger.kernel.org Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/cc32d40c2b47f2d2151811855ac2c3dabab1d57d.1454582914.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 1d43e6f37fc1..4775aa5462e8 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -209,6 +209,11 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) /* pull up/down */ action = *data++; + if (gpio >= ARRAY_SIZE(gtable)) { + DRM_DEBUG_KMS("unknown gpio %u\n", gpio); + goto out; + } + function = gtable[gpio].function_reg; pad = gtable[gpio].pad_reg; @@ -226,6 +231,7 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) vlv_gpio_nc_write(dev_priv, pad, val); mutex_unlock(&dev_priv->sb_lock); +out: return data; } -- cgit v1.2.3 From 4e1c63e3761b84ec7d87c75b58bbc8bcf18e98ee Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 4 Feb 2016 12:50:50 +0200 Subject: drm/i915/dsi: don't pass arbitrary data to sideband MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since sequence block v2 the second byte contains flags other than just pull up/down. Don't pass arbitrary data to the sideband interface. The rest may or may not work for sequence block v2, but there should be no harm done. Cc: stable@vger.kernel.org Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/ebe3c2eee623afc4b3a134533b01f8d591d13f32.1454582914.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 4775aa5462e8..6f013efba45b 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -207,7 +207,7 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) gpio = *data++; /* pull up/down */ - action = *data++; + action = *data++ & 1; if (gpio >= ARRAY_SIZE(gtable)) { DRM_DEBUG_KMS("unknown gpio %u\n", gpio); -- cgit v1.2.3 From 4688d45f97f215447d552ff5bc960072e865e0ff Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 4 Feb 2016 12:50:53 +0200 Subject: drm/i915: put the IOSF port defines in numerical order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make it easier to spot duplicates. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/a89f10d2d1954ac1b9a278534cb5209973354caa.1454582914.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ec6444ae6e2f..85d56ad29516 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -610,16 +610,16 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define IOSF_BYTE_ENABLES_SHIFT 4 #define IOSF_BAR_SHIFT 1 #define IOSF_SB_BUSY (1<<0) -#define IOSF_PORT_BUNIT 0x3 -#define IOSF_PORT_PUNIT 0x4 +#define IOSF_PORT_BUNIT 0x03 +#define IOSF_PORT_PUNIT 0x04 #define IOSF_PORT_NC 0x11 #define IOSF_PORT_DPIO 0x12 -#define IOSF_PORT_DPIO_2 0x1a #define IOSF_PORT_GPIO_NC 0x13 #define IOSF_PORT_CCK 0x14 -#define IOSF_PORT_CCU 0xA9 +#define IOSF_PORT_DPIO_2 0x1a +#define IOSF_PORT_FLISDSI 0x1b #define IOSF_PORT_GPS_CORE 0x48 -#define IOSF_PORT_FLISDSI 0x1B +#define IOSF_PORT_CCU 0xa9 #define VLV_IOSF_DATA _MMIO(VLV_DISPLAY_BASE + 0x2104) #define VLV_IOSF_ADDR _MMIO(VLV_DISPLAY_BASE + 0x2108) -- cgit v1.2.3 From 10182e77f52f1f703c9e5fea3656446aa850ebda Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 4 Feb 2016 12:50:54 +0200 Subject: drm/i915/vlv: drop unused vlv_gps_core_read/write functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not needed. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/532150999335216b1374c606e1b3c253a6c9fe9d.1454582914.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/i915_reg.h | 1 - drivers/gpu/drm/i915/intel_sideband.c | 14 -------------- 3 files changed, 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 856bfe8d1f42..bd126ff3a6e2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3479,8 +3479,6 @@ u32 vlv_ccu_read(struct drm_i915_private *dev_priv, u32 reg); void vlv_ccu_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); u32 vlv_bunit_read(struct drm_i915_private *dev_priv, u32 reg); void vlv_bunit_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); -u32 vlv_gps_core_read(struct drm_i915_private *dev_priv, u32 reg); -void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg); void vlv_dpio_write(struct drm_i915_private *dev_priv, enum pipe pipe, int reg, u32 val); u32 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg, diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 85d56ad29516..6867295dbdc1 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -618,7 +618,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define IOSF_PORT_CCK 0x14 #define IOSF_PORT_DPIO_2 0x1a #define IOSF_PORT_FLISDSI 0x1b -#define IOSF_PORT_GPS_CORE 0x48 #define IOSF_PORT_CCU 0xa9 #define VLV_IOSF_DATA _MMIO(VLV_DISPLAY_BASE + 0x2104) #define VLV_IOSF_ADDR _MMIO(VLV_DISPLAY_BASE + 0x2108) diff --git a/drivers/gpu/drm/i915/intel_sideband.c b/drivers/gpu/drm/i915/intel_sideband.c index 8831fc579ade..f5b0ab6f5942 100644 --- a/drivers/gpu/drm/i915/intel_sideband.c +++ b/drivers/gpu/drm/i915/intel_sideband.c @@ -171,20 +171,6 @@ void vlv_ccu_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) SB_CRWRDA_NP, reg, &val); } -u32 vlv_gps_core_read(struct drm_i915_private *dev_priv, u32 reg) -{ - u32 val = 0; - vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_GPS_CORE, - SB_CRRDDA_NP, reg, &val); - return val; -} - -void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) -{ - vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_GPS_CORE, - SB_CRWRDA_NP, reg, &val); -} - u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) { u32 val = 0; -- cgit v1.2.3 From dfb19ed20c322616a73b212c96f2e0309e35cd1a Mon Sep 17 00:00:00 2001 From: Deepak M Date: Thu, 4 Feb 2016 18:55:15 +0200 Subject: drm/i915: Extend gpio read/write to other cores MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the gpio read/write functions more generic iosf sideband read/write functions, taking the iosf port as argument. v2: rebase v3: rebase v4 by Jani: address Ville's review v5 by Jani: drop the PCI_DEVFN change (Ville) Signed-off-by: Deepak M Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1454604915-17142-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- drivers/gpu/drm/i915/i915_reg.h | 2 ++ drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 5 +++-- drivers/gpu/drm/i915/intel_sideband.c | 9 +++++---- 4 files changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bd126ff3a6e2..8216665405eb 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3471,8 +3471,8 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u32 mbox, u32 val u32 vlv_punit_read(struct drm_i915_private *dev_priv, u32 addr); void vlv_punit_write(struct drm_i915_private *dev_priv, u32 addr, u32 val); u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr); -u32 vlv_gpio_nc_read(struct drm_i915_private *dev_priv, u32 reg); -void vlv_gpio_nc_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); +u32 vlv_iosf_sb_read(struct drm_i915_private *dev_priv, u8 port, u32 reg); +void vlv_iosf_sb_write(struct drm_i915_private *dev_priv, u8 port, u32 reg, u32 val); u32 vlv_cck_read(struct drm_i915_private *dev_priv, u32 reg); void vlv_cck_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); u32 vlv_ccu_read(struct drm_i915_private *dev_priv, u32 reg); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 6867295dbdc1..6732fc139196 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -618,6 +618,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define IOSF_PORT_CCK 0x14 #define IOSF_PORT_DPIO_2 0x1a #define IOSF_PORT_FLISDSI 0x1b +#define IOSF_PORT_GPIO_SC 0x48 +#define IOSF_PORT_GPIO_SUS 0xa8 #define IOSF_PORT_CCU 0xa9 #define VLV_IOSF_DATA _MMIO(VLV_DISPLAY_BASE + 0x2104) #define VLV_IOSF_ADDR _MMIO(VLV_DISPLAY_BASE + 0x2108) diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 6f013efba45b..76dbd1a36c57 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -221,14 +221,15 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) if (!gtable[gpio].init) { /* program the function */ /* FIXME: remove constant below */ - vlv_gpio_nc_write(dev_priv, function, 0x2000CC00); + vlv_iosf_sb_write(dev_priv, IOSF_PORT_GPIO_NC, function, + 0x2000CC00); gtable[gpio].init = 1; } val = 0x4 | action; /* pull up/down */ - vlv_gpio_nc_write(dev_priv, pad, val); + vlv_iosf_sb_write(dev_priv, IOSF_PORT_GPIO_NC, pad, val); mutex_unlock(&dev_priv->sb_lock); out: diff --git a/drivers/gpu/drm/i915/intel_sideband.c b/drivers/gpu/drm/i915/intel_sideband.c index f5b0ab6f5942..c3998188cf35 100644 --- a/drivers/gpu/drm/i915/intel_sideband.c +++ b/drivers/gpu/drm/i915/intel_sideband.c @@ -129,17 +129,18 @@ u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr) return val; } -u32 vlv_gpio_nc_read(struct drm_i915_private *dev_priv, u32 reg) +u32 vlv_iosf_sb_read(struct drm_i915_private *dev_priv, u8 port, u32 reg) { u32 val = 0; - vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_GPIO_NC, + vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), port, SB_CRRDDA_NP, reg, &val); return val; } -void vlv_gpio_nc_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) +void vlv_iosf_sb_write(struct drm_i915_private *dev_priv, + u8 port, u32 reg, u32 val) { - vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_GPIO_NC, + vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), port, SB_CRWRDA_NP, reg, &val); } -- cgit v1.2.3 From ac75fe5d8fe4a0bf063be18fb29684405279e79e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 15:59:43 -0200 Subject: [media] saa7134-alsa: Only frees registered sound cards That prevents this bug: [ 2382.269496] BUG: unable to handle kernel NULL pointer dereference at 0000000000000540 [ 2382.270013] IP: [] snd_card_free+0x36/0x70 [snd] [ 2382.270013] PGD 0 [ 2382.270013] Oops: 0002 [#1] SMP [ 2382.270013] Modules linked in: saa7134_alsa(-) tda1004x saa7134_dvb videobuf2_dvb dvb_core tda827x tda8290 tuner saa7134 tveeprom videobuf2_dma_sg videobuf2_memops videobuf2_v4l2 videobuf2_core v4l2_common videodev media auth_rpcgss nfsv4 dns_resolver nfs lockd grace sunrpc tun bridge stp llc ebtables ip6table_filter ip6_tables nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack it87 hwmon_vid snd_hda_codec_idt snd_hda_codec_generic iTCO_wdt iTCO_vendor_support snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_seq pcspkr i2c_i801 snd_seq_device snd_pcm snd_timer lpc_ich snd mfd_core soundcore binfmt_misc i915 video i2c_algo_bit drm_kms_helper drm r8169 ata_generic serio_raw pata_acpi mii i2c_core [last unloaded: videobuf2_memops] [ 2382.270013] CPU: 0 PID: 4899 Comm: rmmod Not tainted 4.5.0-rc1+ #4 [ 2382.270013] Hardware name: PCCHIPS P17G/P17G, BIOS 080012 05/14/2008 [ 2382.270013] task: ffff880039c38000 ti: ffff88003c764000 task.ti: ffff88003c764000 [ 2382.270013] RIP: 0010:[] [] snd_card_free+0x36/0x70 [snd] [ 2382.270013] RSP: 0018:ffff88003c767ea0 EFLAGS: 00010286 [ 2382.270013] RAX: ffff88003c767eb8 RBX: 0000000000000000 RCX: 0000000000006260 [ 2382.270013] RDX: ffffffffa020a060 RSI: ffffffffa0206de1 RDI: ffff88003c767eb0 [ 2382.270013] RBP: ffff88003c767ed8 R08: 0000000000019960 R09: ffffffff811a5412 [ 2382.270013] R10: ffffea0000d7c200 R11: 0000000000000000 R12: ffff88003c767ea8 [ 2382.270013] R13: 00007ffe760617f7 R14: 0000000000000000 R15: 0000557625d7f1e0 [ 2382.270013] FS: 00007f80bb1c0700(0000) GS:ffff88003f400000(0000) knlGS:0000000000000000 [ 2382.270013] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 2382.270013] CR2: 0000000000000540 CR3: 000000003c00f000 CR4: 00000000000006f0 [ 2382.270013] Stack: [ 2382.270013] 000000003c767ed8 ffffffff00000000 ffff880000000000 ffff88003c767eb8 [ 2382.270013] ffff88003c767eb8 ffffffffa049a890 00007ffe76060060 ffff88003c767ef0 [ 2382.270013] ffffffffa049889d ffffffffa049a500 ffff88003c767f48 ffffffff8111079c [ 2382.270013] Call Trace: [ 2382.270013] [] saa7134_alsa_exit+0x1d/0x780 [saa7134_alsa] [ 2382.270013] [] SyS_delete_module+0x19c/0x1f0 [ 2382.270013] [] entry_SYSCALL_64_fastpath+0x12/0x71 [ 2382.270013] Code: 20 a0 48 c7 c6 e1 6d 20 a0 48 89 e5 41 54 53 4c 8d 65 d0 48 89 fb 48 83 ec 28 c7 45 d0 00 00 00 00 49 8d 7c 24 08 e8 7a 55 ed e0 <4c> 89 a3 40 05 00 00 48 89 df e8 eb fd ff ff 85 c0 75 1a 48 8d [ 2382.270013] RIP [] snd_card_free+0x36/0x70 [snd] [ 2382.270013] RSP [ 2382.270013] CR2: 0000000000000540 Cc: stable@vger.kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-alsa.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c index 1d2c310ce838..94f816244407 100644 --- a/drivers/media/pci/saa7134/saa7134-alsa.c +++ b/drivers/media/pci/saa7134/saa7134-alsa.c @@ -1211,6 +1211,8 @@ static int alsa_device_init(struct saa7134_dev *dev) static int alsa_device_exit(struct saa7134_dev *dev) { + if (!snd_saa7134_cards[dev->nr]) + return 1; snd_card_free(snd_saa7134_cards[dev->nr]); snd_saa7134_cards[dev->nr] = NULL; @@ -1260,7 +1262,8 @@ static void saa7134_alsa_exit(void) int idx; for (idx = 0; idx < SNDRV_CARDS; idx++) { - snd_card_free(snd_saa7134_cards[idx]); + if (snd_saa7134_cards[idx]) + snd_card_free(snd_saa7134_cards[idx]); } saa7134_dmasound_init = NULL; -- cgit v1.2.3 From 83a74ff8e63e39d8122ff17ac000064605884127 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 09:54:25 -0200 Subject: [media] siano: remove get_frontend stub There's nothing at siano's get_frontend() callback. So, remove it, as the core will handle it. Reviewed-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/siano/smsdvb-main.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/common/siano/smsdvb-main.c b/drivers/media/common/siano/smsdvb-main.c index d31f468830cf..9148e14c9d07 100644 --- a/drivers/media/common/siano/smsdvb-main.c +++ b/drivers/media/common/siano/smsdvb-main.c @@ -1015,12 +1015,6 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe) } } -/* Nothing to do here, as stats are automatically updated */ -static int smsdvb_get_frontend(struct dvb_frontend *fe) -{ - return 0; -} - static int smsdvb_init(struct dvb_frontend *fe) { struct smsdvb_client_t *client = @@ -1069,7 +1063,6 @@ static struct dvb_frontend_ops smsdvb_fe_ops = { .release = smsdvb_release, .set_frontend = smsdvb_set_frontend, - .get_frontend = smsdvb_get_frontend, .get_tune_settings = smsdvb_get_tune_settings, .read_status = smsdvb_read_status, -- cgit v1.2.3 From 6f1bd426122da4a2d22570494bba9cf3dffbd753 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 10:01:05 -0200 Subject: [media] friio-fe: remove get_frontend() callback This driver doesn't support getting frontend information and it only works in automatic mode. So, let's remove get_frontend() and update the cache at set_frontend(). Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/friio-fe.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/dvb-usb/friio-fe.c b/drivers/media/usb/dvb-usb/friio-fe.c index 8ec92fbeabad..979f05b4b87c 100644 --- a/drivers/media/usb/dvb-usb/friio-fe.c +++ b/drivers/media/usb/dvb-usb/friio-fe.c @@ -283,20 +283,6 @@ static int jdvbt90502_set_property(struct dvb_frontend *fe, return r; } -static int jdvbt90502_get_frontend(struct dvb_frontend *fe) -{ - struct dtv_frontend_properties *p = &fe->dtv_property_cache; - p->inversion = INVERSION_AUTO; - p->bandwidth_hz = 6000000; - p->code_rate_HP = FEC_AUTO; - p->code_rate_LP = FEC_AUTO; - p->modulation = QAM_64; - p->transmission_mode = TRANSMISSION_MODE_AUTO; - p->guard_interval = GUARD_INTERVAL_AUTO; - p->hierarchy = HIERARCHY_AUTO; - return 0; -} - static int jdvbt90502_set_frontend(struct dvb_frontend *fe) { struct dtv_frontend_properties *p = &fe->dtv_property_cache; @@ -312,8 +298,16 @@ static int jdvbt90502_set_frontend(struct dvb_frontend *fe) deb_fe("%s: Freq:%d\n", __func__, p->frequency); - /* for recovery from DTV_CLEAN */ - fe->dtv_property_cache.delivery_system = SYS_ISDBT; + /* This driver only works on auto mode */ + p->inversion = INVERSION_AUTO; + p->bandwidth_hz = 6000000; + p->code_rate_HP = FEC_AUTO; + p->code_rate_LP = FEC_AUTO; + p->modulation = QAM_64; + p->transmission_mode = TRANSMISSION_MODE_AUTO; + p->guard_interval = GUARD_INTERVAL_AUTO; + p->hierarchy = HIERARCHY_AUTO; + p->delivery_system = SYS_ISDBT; ret = jdvbt90502_pll_set_freq(state, p->frequency); if (ret) { @@ -466,7 +460,6 @@ static struct dvb_frontend_ops jdvbt90502_ops = { .set_property = jdvbt90502_set_property, .set_frontend = jdvbt90502_set_frontend, - .get_frontend = jdvbt90502_get_frontend, .read_status = jdvbt90502_read_status, .read_signal_strength = jdvbt90502_read_signal_strength, -- cgit v1.2.3 From 0fa301d796ce7d78d12cf35440143e3f232f5663 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 10:37:37 -0200 Subject: [media] lgs8gxx: don't export get_frontend() callback This device doesn't really have a get_frontend(). All it does is to blindly set everything to auto mode. Remove the get_frontend(), as the code does that already, and put the frontend changes at set_frontend, where it belongs. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/lgs8gxx.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/lgs8gxx.c b/drivers/media/dvb-frontends/lgs8gxx.c index e2c191c8b196..919daeb96747 100644 --- a/drivers/media/dvb-frontends/lgs8gxx.c +++ b/drivers/media/dvb-frontends/lgs8gxx.c @@ -672,7 +672,7 @@ static int lgs8gxx_write(struct dvb_frontend *fe, const u8 buf[], int len) static int lgs8gxx_set_fe(struct dvb_frontend *fe) { - + struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache; struct lgs8gxx_state *priv = fe->demodulator_priv; dprintk("%s\n", __func__); @@ -689,17 +689,7 @@ static int lgs8gxx_set_fe(struct dvb_frontend *fe) msleep(10); - return 0; -} - -static int lgs8gxx_get_fe(struct dvb_frontend *fe) -{ - struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache; - dprintk("%s\n", __func__); - /* TODO: get real readings from device */ - /* inversion status */ - fe_params->inversion = INVERSION_OFF; /* bandwidth */ fe_params->bandwidth_hz = 8000000; @@ -1016,7 +1006,6 @@ static struct dvb_frontend_ops lgs8gxx_ops = { .i2c_gate_ctrl = lgs8gxx_i2c_gate_ctrl, .set_frontend = lgs8gxx_set_fe, - .get_frontend = lgs8gxx_get_fe, .get_tune_settings = lgs8gxx_get_tune_settings, .read_status = lgs8gxx_read_status, -- cgit v1.2.3 From a7497049841f04712ad525969e5eb4a42b5a1704 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 12:47:04 -0200 Subject: [media] mb86a20s: get rid of dummy get_frontend() This is not needed, as the core handles well if get_frontend() is not present. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/mb86a20s.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c index cfc005ee11d8..fb88dddaf3a3 100644 --- a/drivers/media/dvb-frontends/mb86a20s.c +++ b/drivers/media/dvb-frontends/mb86a20s.c @@ -2028,16 +2028,6 @@ static int mb86a20s_read_signal_strength_from_cache(struct dvb_frontend *fe, return 0; } -static int mb86a20s_get_frontend_dummy(struct dvb_frontend *fe) -{ - /* - * get_frontend is now handled together with other stats - * retrival, when read_status() is called, as some statistics - * will depend on the layers detection. - */ - return 0; -}; - static int mb86a20s_tune(struct dvb_frontend *fe, bool re_tune, unsigned int mode_flags, @@ -2136,7 +2126,6 @@ static struct dvb_frontend_ops mb86a20s_ops = { .init = mb86a20s_initfe, .set_frontend = mb86a20s_set_frontend, - .get_frontend = mb86a20s_get_frontend_dummy, .read_status = mb86a20s_read_status_and_stats, .read_signal_strength = mb86a20s_read_signal_strength_from_cache, .tune = mb86a20s_tune, -- cgit v1.2.3 From 7e3e68bcfd7713fb1470070c8fa0f108609dd76b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 12:58:30 -0200 Subject: [media] dvb_frontend: pass the props cache to get_frontend() as arg Instead of using the DTV properties cache directly, pass the get frontend data as an argument. For now, everything should remain the same, but the next patch will prevent get_frontend to affect the global cache. This is needed because several drivers don't care enough to only change the properties if locked. Due to that, calling G_PROPERTY before locking on those drivers will make them to never lock. Ok, those drivers are crap and should never be merged like that, but the core should not rely that the drivers would be doing the right thing. Reviewed-by: Michael Ira Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 2 +- drivers/media/dvb-core/dvb_frontend.h | 3 +- drivers/media/dvb-frontends/af9013.c | 4 +- drivers/media/dvb-frontends/af9033.c | 4 +- drivers/media/dvb-frontends/as102_fe.c | 4 +- drivers/media/dvb-frontends/atbm8830.c | 4 +- drivers/media/dvb-frontends/au8522_dig.c | 4 +- drivers/media/dvb-frontends/cx22700.c | 4 +- drivers/media/dvb-frontends/cx22702.c | 4 +- drivers/media/dvb-frontends/cx24110.c | 4 +- drivers/media/dvb-frontends/cx24117.c | 4 +- drivers/media/dvb-frontends/cx24120.c | 4 +- drivers/media/dvb-frontends/cx24123.c | 4 +- drivers/media/dvb-frontends/cxd2820r_c.c | 4 +- drivers/media/dvb-frontends/cxd2820r_core.c | 9 ++-- drivers/media/dvb-frontends/cxd2820r_priv.h | 9 ++-- drivers/media/dvb-frontends/cxd2820r_t.c | 4 +- drivers/media/dvb-frontends/cxd2820r_t2.c | 6 +-- drivers/media/dvb-frontends/cxd2841er.c | 4 +- drivers/media/dvb-frontends/dib3000mb.c | 9 ++-- drivers/media/dvb-frontends/dib3000mc.c | 6 +-- drivers/media/dvb-frontends/dib7000m.c | 6 +-- drivers/media/dvb-frontends/dib7000p.c | 6 +-- drivers/media/dvb-frontends/dib8000.c | 75 ++++++++++++++------------- drivers/media/dvb-frontends/dib9000.c | 23 ++++---- drivers/media/dvb-frontends/dvb_dummy_fe.c | 7 ++- drivers/media/dvb-frontends/hd29l2.c | 4 +- drivers/media/dvb-frontends/l64781.c | 4 +- drivers/media/dvb-frontends/lg2160.c | 62 +++++++++++----------- drivers/media/dvb-frontends/lgdt3305.c | 4 +- drivers/media/dvb-frontends/lgdt3306a.c | 4 +- drivers/media/dvb-frontends/lgdt330x.c | 5 +- drivers/media/dvb-frontends/lgs8gl5.c | 5 +- drivers/media/dvb-frontends/m88ds3103.c | 4 +- drivers/media/dvb-frontends/m88rs2000.c | 5 +- drivers/media/dvb-frontends/mt312.c | 4 +- drivers/media/dvb-frontends/mt352.c | 4 +- drivers/media/dvb-frontends/or51132.c | 4 +- drivers/media/dvb-frontends/rtl2830.c | 4 +- drivers/media/dvb-frontends/rtl2832.c | 4 +- drivers/media/dvb-frontends/s5h1409.c | 4 +- drivers/media/dvb-frontends/s5h1411.c | 4 +- drivers/media/dvb-frontends/s5h1420.c | 4 +- drivers/media/dvb-frontends/s921.c | 4 +- drivers/media/dvb-frontends/stb0899_drv.c | 4 +- drivers/media/dvb-frontends/stb6100.c | 2 +- drivers/media/dvb-frontends/stv0297.c | 4 +- drivers/media/dvb-frontends/stv0299.c | 4 +- drivers/media/dvb-frontends/stv0367.c | 8 +-- drivers/media/dvb-frontends/stv0900_core.c | 4 +- drivers/media/dvb-frontends/tc90522.c | 10 ++-- drivers/media/dvb-frontends/tda10021.c | 4 +- drivers/media/dvb-frontends/tda10023.c | 4 +- drivers/media/dvb-frontends/tda10048.c | 4 +- drivers/media/dvb-frontends/tda1004x.c | 4 +- drivers/media/dvb-frontends/tda10071.c | 4 +- drivers/media/dvb-frontends/tda10086.c | 4 +- drivers/media/dvb-frontends/tda8083.c | 4 +- drivers/media/dvb-frontends/ves1820.c | 4 +- drivers/media/dvb-frontends/ves1x93.c | 4 +- drivers/media/dvb-frontends/zl10353.c | 4 +- drivers/media/pci/bt8xx/dst.c | 4 +- drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c | 4 +- drivers/media/usb/dvb-usb/af9005-fe.c | 4 +- drivers/media/usb/dvb-usb/dtt200u-fe.c | 5 +- 65 files changed, 230 insertions(+), 213 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index ca6d60f9d492..d009478f16c4 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -1361,7 +1361,7 @@ static int dtv_get_frontend(struct dvb_frontend *fe, int r; if (fe->ops.get_frontend) { - r = fe->ops.get_frontend(fe); + r = fe->ops.get_frontend(fe, c); if (unlikely(r < 0)) return r; if (p_out) diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h index 458bcce20e38..9592573a0b41 100644 --- a/drivers/media/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb-core/dvb_frontend.h @@ -449,7 +449,8 @@ struct dvb_frontend_ops { int (*set_frontend)(struct dvb_frontend *fe); int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings); - int (*get_frontend)(struct dvb_frontend *fe); + int (*get_frontend)(struct dvb_frontend *fe, + struct dtv_frontend_properties *props); int (*read_status)(struct dvb_frontend *fe, enum fe_status *status); int (*read_ber)(struct dvb_frontend* fe, u32* ber); diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c index 41ab5defb798..8bcde336ffd7 100644 --- a/drivers/media/dvb-frontends/af9013.c +++ b/drivers/media/dvb-frontends/af9013.c @@ -866,9 +866,9 @@ err: return ret; } -static int af9013_get_frontend(struct dvb_frontend *fe) +static int af9013_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct af9013_state *state = fe->demodulator_priv; int ret; u8 buf[3]; diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c index 8b328d1ca8d3..efebe5ce2429 100644 --- a/drivers/media/dvb-frontends/af9033.c +++ b/drivers/media/dvb-frontends/af9033.c @@ -691,10 +691,10 @@ err: return ret; } -static int af9033_get_frontend(struct dvb_frontend *fe) +static int af9033_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct af9033_dev *dev = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[8]; diff --git a/drivers/media/dvb-frontends/as102_fe.c b/drivers/media/dvb-frontends/as102_fe.c index 544c5f65d19a..9412fcd1bddb 100644 --- a/drivers/media/dvb-frontends/as102_fe.c +++ b/drivers/media/dvb-frontends/as102_fe.c @@ -190,10 +190,10 @@ static int as102_fe_set_frontend(struct dvb_frontend *fe) return state->ops->set_tune(state->priv, &tune_args); } -static int as102_fe_get_frontend(struct dvb_frontend *fe) +static int as102_fe_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct as102_state *state = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret = 0; struct as10x_tps tps = { 0 }; diff --git a/drivers/media/dvb-frontends/atbm8830.c b/drivers/media/dvb-frontends/atbm8830.c index 8fe552e293ed..47248b868e38 100644 --- a/drivers/media/dvb-frontends/atbm8830.c +++ b/drivers/media/dvb-frontends/atbm8830.c @@ -297,9 +297,9 @@ static int atbm8830_set_fe(struct dvb_frontend *fe) return 0; } -static int atbm8830_get_fe(struct dvb_frontend *fe) +static int atbm8830_get_fe(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; dprintk("%s\n", __func__); /* TODO: get real readings from device */ diff --git a/drivers/media/dvb-frontends/au8522_dig.c b/drivers/media/dvb-frontends/au8522_dig.c index 6c1e97640f3f..e676b9461a59 100644 --- a/drivers/media/dvb-frontends/au8522_dig.c +++ b/drivers/media/dvb-frontends/au8522_dig.c @@ -816,9 +816,9 @@ static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber) return au8522_read_ucblocks(fe, ber); } -static int au8522_get_frontend(struct dvb_frontend *fe) +static int au8522_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct au8522_state *state = fe->demodulator_priv; c->frequency = state->current_frequency; diff --git a/drivers/media/dvb-frontends/cx22700.c b/drivers/media/dvb-frontends/cx22700.c index fd033cca6e11..5cad925609e0 100644 --- a/drivers/media/dvb-frontends/cx22700.c +++ b/drivers/media/dvb-frontends/cx22700.c @@ -345,9 +345,9 @@ static int cx22700_set_frontend(struct dvb_frontend *fe) return 0; } -static int cx22700_get_frontend(struct dvb_frontend *fe) +static int cx22700_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct cx22700_state* state = fe->demodulator_priv; u8 reg09 = cx22700_readreg (state, 0x09); diff --git a/drivers/media/dvb-frontends/cx22702.c b/drivers/media/dvb-frontends/cx22702.c index d2d06dcd7683..c0e54c59cccf 100644 --- a/drivers/media/dvb-frontends/cx22702.c +++ b/drivers/media/dvb-frontends/cx22702.c @@ -562,9 +562,9 @@ static int cx22702_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) return 0; } -static int cx22702_get_frontend(struct dvb_frontend *fe) +static int cx22702_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct cx22702_state *state = fe->demodulator_priv; u8 reg0C = cx22702_readreg(state, 0x0C); diff --git a/drivers/media/dvb-frontends/cx24110.c b/drivers/media/dvb-frontends/cx24110.c index cb36475e322b..6cb81ec12847 100644 --- a/drivers/media/dvb-frontends/cx24110.c +++ b/drivers/media/dvb-frontends/cx24110.c @@ -550,9 +550,9 @@ static int cx24110_set_frontend(struct dvb_frontend *fe) return 0; } -static int cx24110_get_frontend(struct dvb_frontend *fe) +static int cx24110_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct cx24110_state *state = fe->demodulator_priv; s32 afc; unsigned sclk; diff --git a/drivers/media/dvb-frontends/cx24117.c b/drivers/media/dvb-frontends/cx24117.c index 5f77bc80a896..a3f7eb4e609d 100644 --- a/drivers/media/dvb-frontends/cx24117.c +++ b/drivers/media/dvb-frontends/cx24117.c @@ -1560,10 +1560,10 @@ static int cx24117_get_algo(struct dvb_frontend *fe) return DVBFE_ALGO_HW; } -static int cx24117_get_frontend(struct dvb_frontend *fe) +static int cx24117_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct cx24117_state *state = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct cx24117_cmd cmd; u8 reg, st, inv; int ret, idx; diff --git a/drivers/media/dvb-frontends/cx24120.c b/drivers/media/dvb-frontends/cx24120.c index 3b0ef52bb834..6ccbd86c9490 100644 --- a/drivers/media/dvb-frontends/cx24120.c +++ b/drivers/media/dvb-frontends/cx24120.c @@ -1502,9 +1502,9 @@ static int cx24120_sleep(struct dvb_frontend *fe) return 0; } -static int cx24120_get_frontend(struct dvb_frontend *fe) +static int cx24120_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct cx24120_state *state = fe->demodulator_priv; u8 freq1, freq2, freq3; diff --git a/drivers/media/dvb-frontends/cx24123.c b/drivers/media/dvb-frontends/cx24123.c index 0fe7fb11124b..113b0949408a 100644 --- a/drivers/media/dvb-frontends/cx24123.c +++ b/drivers/media/dvb-frontends/cx24123.c @@ -945,9 +945,9 @@ static int cx24123_set_frontend(struct dvb_frontend *fe) return 0; } -static int cx24123_get_frontend(struct dvb_frontend *fe) +static int cx24123_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct cx24123_state *state = fe->demodulator_priv; dprintk("\n"); diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c b/drivers/media/dvb-frontends/cxd2820r_c.c index 42fad6aa3958..a674a6312c38 100644 --- a/drivers/media/dvb-frontends/cxd2820r_c.c +++ b/drivers/media/dvb-frontends/cxd2820r_c.c @@ -101,10 +101,10 @@ error: return ret; } -int cxd2820r_get_frontend_c(struct dvb_frontend *fe) +int cxd2820r_get_frontend_c(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct cxd2820r_priv *priv = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[2]; diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c index ba4cb7557aa5..314d3b8c1080 100644 --- a/drivers/media/dvb-frontends/cxd2820r_core.c +++ b/drivers/media/dvb-frontends/cxd2820r_core.c @@ -313,7 +313,8 @@ static int cxd2820r_read_status(struct dvb_frontend *fe, enum fe_status *status) return ret; } -static int cxd2820r_get_frontend(struct dvb_frontend *fe) +static int cxd2820r_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { struct cxd2820r_priv *priv = fe->demodulator_priv; int ret; @@ -326,13 +327,13 @@ static int cxd2820r_get_frontend(struct dvb_frontend *fe) switch (fe->dtv_property_cache.delivery_system) { case SYS_DVBT: - ret = cxd2820r_get_frontend_t(fe); + ret = cxd2820r_get_frontend_t(fe, p); break; case SYS_DVBT2: - ret = cxd2820r_get_frontend_t2(fe); + ret = cxd2820r_get_frontend_t2(fe, p); break; case SYS_DVBC_ANNEX_A: - ret = cxd2820r_get_frontend_c(fe); + ret = cxd2820r_get_frontend_c(fe, p); break; default: ret = -EINVAL; diff --git a/drivers/media/dvb-frontends/cxd2820r_priv.h b/drivers/media/dvb-frontends/cxd2820r_priv.h index a0d53f01a8bf..e31c48e53097 100644 --- a/drivers/media/dvb-frontends/cxd2820r_priv.h +++ b/drivers/media/dvb-frontends/cxd2820r_priv.h @@ -76,7 +76,8 @@ int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val); /* cxd2820r_c.c */ -int cxd2820r_get_frontend_c(struct dvb_frontend *fe); +int cxd2820r_get_frontend_c(struct dvb_frontend *fe, + struct dtv_frontend_properties *p); int cxd2820r_set_frontend_c(struct dvb_frontend *fe); @@ -99,7 +100,8 @@ int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe, /* cxd2820r_t.c */ -int cxd2820r_get_frontend_t(struct dvb_frontend *fe); +int cxd2820r_get_frontend_t(struct dvb_frontend *fe, + struct dtv_frontend_properties *p); int cxd2820r_set_frontend_t(struct dvb_frontend *fe); @@ -122,7 +124,8 @@ int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe, /* cxd2820r_t2.c */ -int cxd2820r_get_frontend_t2(struct dvb_frontend *fe); +int cxd2820r_get_frontend_t2(struct dvb_frontend *fe, + struct dtv_frontend_properties *p); int cxd2820r_set_frontend_t2(struct dvb_frontend *fe); diff --git a/drivers/media/dvb-frontends/cxd2820r_t.c b/drivers/media/dvb-frontends/cxd2820r_t.c index 21abf1b4ed4d..75ce7d8ded00 100644 --- a/drivers/media/dvb-frontends/cxd2820r_t.c +++ b/drivers/media/dvb-frontends/cxd2820r_t.c @@ -138,10 +138,10 @@ error: return ret; } -int cxd2820r_get_frontend_t(struct dvb_frontend *fe) +int cxd2820r_get_frontend_t(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct cxd2820r_priv *priv = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[2]; diff --git a/drivers/media/dvb-frontends/cxd2820r_t2.c b/drivers/media/dvb-frontends/cxd2820r_t2.c index 4e028b41c0d5..704475676234 100644 --- a/drivers/media/dvb-frontends/cxd2820r_t2.c +++ b/drivers/media/dvb-frontends/cxd2820r_t2.c @@ -23,8 +23,8 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe) { - struct cxd2820r_priv *priv = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct cxd2820r_priv *priv = fe->demodulator_priv; int ret, i, bw_i; u32 if_freq, if_ctl; u64 num; @@ -169,10 +169,10 @@ error: } -int cxd2820r_get_frontend_t2(struct dvb_frontend *fe) +int cxd2820r_get_frontend_t2(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct cxd2820r_priv *priv = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[2]; diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c index fdffb2f0ded8..900186ba8e62 100644 --- a/drivers/media/dvb-frontends/cxd2841er.c +++ b/drivers/media/dvb-frontends/cxd2841er.c @@ -2090,13 +2090,13 @@ static int cxd2841er_sleep_tc_to_active_c(struct cxd2841er_priv *priv, return 0; } -static int cxd2841er_get_frontend(struct dvb_frontend *fe) +static int cxd2841er_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { enum fe_status status = 0; u16 strength = 0, snr = 0; u32 errors = 0, ber = 0; struct cxd2841er_priv *priv = fe->demodulator_priv; - struct dtv_frontend_properties *p = &fe->dtv_property_cache; dev_dbg(&priv->i2c->dev, "%s()\n", __func__); if (priv->state == STATE_ACTIVE_S) diff --git a/drivers/media/dvb-frontends/dib3000mb.c b/drivers/media/dvb-frontends/dib3000mb.c index 3ca300939f79..6821ecb53d63 100644 --- a/drivers/media/dvb-frontends/dib3000mb.c +++ b/drivers/media/dvb-frontends/dib3000mb.c @@ -112,7 +112,8 @@ static u16 dib3000_seq[2][2][2] = /* fft,gua, inv */ } }; -static int dib3000mb_get_frontend(struct dvb_frontend* fe); +static int dib3000mb_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *c); static int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner) { @@ -359,7 +360,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner) deb_setf("search_state after autosearch %d after %d checks\n",search_state,as_count); if (search_state == 1) { - if (dib3000mb_get_frontend(fe) == 0) { + if (dib3000mb_get_frontend(fe, c) == 0) { deb_setf("reading tuning data from frontend succeeded.\n"); return dib3000mb_set_frontend(fe, 0); } @@ -450,9 +451,9 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode) return 0; } -static int dib3000mb_get_frontend(struct dvb_frontend* fe) +static int dib3000mb_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dib3000_state* state = fe->demodulator_priv; enum fe_code_rate *cr; u16 tps_val; diff --git a/drivers/media/dvb-frontends/dib3000mc.c b/drivers/media/dvb-frontends/dib3000mc.c index ac90ed3af37e..da0f1dc5aaf7 100644 --- a/drivers/media/dvb-frontends/dib3000mc.c +++ b/drivers/media/dvb-frontends/dib3000mc.c @@ -636,9 +636,9 @@ struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master); -static int dib3000mc_get_frontend(struct dvb_frontend* fe) +static int dib3000mc_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *fep) { - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct dib3000mc_state *state = fe->demodulator_priv; u16 tps = dib3000mc_read_word(state,458); @@ -726,7 +726,7 @@ static int dib3000mc_set_frontend(struct dvb_frontend *fe) if (found == 0 || found == 1) return 0; // no channel found - dib3000mc_get_frontend(fe); + dib3000mc_get_frontend(fe, fep); } ret = dib3000mc_tune(fe); diff --git a/drivers/media/dvb-frontends/dib7000m.c b/drivers/media/dvb-frontends/dib7000m.c index 8b21cccf3c3a..b3ddae8885ac 100644 --- a/drivers/media/dvb-frontends/dib7000m.c +++ b/drivers/media/dvb-frontends/dib7000m.c @@ -1151,9 +1151,9 @@ static int dib7000m_identify(struct dib7000m_state *state) } -static int dib7000m_get_frontend(struct dvb_frontend* fe) +static int dib7000m_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *fep) { - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct dib7000m_state *state = fe->demodulator_priv; u16 tps = dib7000m_read_word(state,480); @@ -1246,7 +1246,7 @@ static int dib7000m_set_frontend(struct dvb_frontend *fe) if (found == 0 || found == 1) return 0; // no channel found - dib7000m_get_frontend(fe); + dib7000m_get_frontend(fe, fep); } ret = dib7000m_tune(fe); diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c index 65ab79ed5e3e..b861d4437f2a 100644 --- a/drivers/media/dvb-frontends/dib7000p.c +++ b/drivers/media/dvb-frontends/dib7000p.c @@ -1405,9 +1405,9 @@ static int dib7000p_identify(struct dib7000p_state *st) return 0; } -static int dib7000p_get_frontend(struct dvb_frontend *fe) +static int dib7000p_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *fep) { - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct dib7000p_state *state = fe->demodulator_priv; u16 tps = dib7000p_read_word(state, 463); @@ -1540,7 +1540,7 @@ static int dib7000p_set_frontend(struct dvb_frontend *fe) if (found == 0 || found == 1) return 0; - dib7000p_get_frontend(fe); + dib7000p_get_frontend(fe, fep); } ret = dib7000p_tune(fe); diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index 349d2f1f62ce..ddf9c44877a2 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -3382,14 +3382,15 @@ static int dib8000_sleep(struct dvb_frontend *fe) static int dib8000_read_status(struct dvb_frontend *fe, enum fe_status *stat); -static int dib8000_get_frontend(struct dvb_frontend *fe) +static int dib8000_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct dib8000_state *state = fe->demodulator_priv; u16 i, val = 0; enum fe_status stat = 0; u8 index_frontend, sub_index_frontend; - fe->dtv_property_cache.bandwidth_hz = 6000000; + c->bandwidth_hz = 6000000; /* * If called to early, get_frontend makes dib8000_tune to either @@ -3406,7 +3407,7 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) if (stat&FE_HAS_SYNC) { dprintk("TMCC lock on the slave%i", index_frontend); /* synchronize the cache with the other frontends */ - state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]); + state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], c); for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) { if (sub_index_frontend != index_frontend) { state->fe[sub_index_frontend]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode; @@ -3426,57 +3427,57 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) } } - fe->dtv_property_cache.isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1; + c->isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1; if (state->revision == 0x8090) val = dib8000_read_word(state, 572); else val = dib8000_read_word(state, 570); - fe->dtv_property_cache.inversion = (val & 0x40) >> 6; + c->inversion = (val & 0x40) >> 6; switch ((val & 0x30) >> 4) { case 1: - fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K; + c->transmission_mode = TRANSMISSION_MODE_2K; dprintk("dib8000_get_frontend: transmission mode 2K"); break; case 2: - fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_4K; + c->transmission_mode = TRANSMISSION_MODE_4K; dprintk("dib8000_get_frontend: transmission mode 4K"); break; case 3: default: - fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; + c->transmission_mode = TRANSMISSION_MODE_8K; dprintk("dib8000_get_frontend: transmission mode 8K"); break; } switch (val & 0x3) { case 0: - fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32; + c->guard_interval = GUARD_INTERVAL_1_32; dprintk("dib8000_get_frontend: Guard Interval = 1/32 "); break; case 1: - fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16; + c->guard_interval = GUARD_INTERVAL_1_16; dprintk("dib8000_get_frontend: Guard Interval = 1/16 "); break; case 2: dprintk("dib8000_get_frontend: Guard Interval = 1/8 "); - fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; + c->guard_interval = GUARD_INTERVAL_1_8; break; case 3: dprintk("dib8000_get_frontend: Guard Interval = 1/4 "); - fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4; + c->guard_interval = GUARD_INTERVAL_1_4; break; } val = dib8000_read_word(state, 505); - fe->dtv_property_cache.isdbt_partial_reception = val & 1; - dprintk("dib8000_get_frontend: partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception); + c->isdbt_partial_reception = val & 1; + dprintk("dib8000_get_frontend: partial_reception = %d ", c->isdbt_partial_reception); for (i = 0; i < 3; i++) { int show; val = dib8000_read_word(state, 493 + i) & 0x0f; - fe->dtv_property_cache.layer[i].segment_count = val; + c->layer[i].segment_count = val; if (val == 0 || val > 13) show = 0; @@ -3485,41 +3486,41 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) if (show) dprintk("dib8000_get_frontend: Layer %d segments = %d ", - i, fe->dtv_property_cache.layer[i].segment_count); + i, c->layer[i].segment_count); val = dib8000_read_word(state, 499 + i) & 0x3; /* Interleaving can be 0, 1, 2 or 4 */ if (val == 3) val = 4; - fe->dtv_property_cache.layer[i].interleaving = val; + c->layer[i].interleaving = val; if (show) dprintk("dib8000_get_frontend: Layer %d time_intlv = %d ", - i, fe->dtv_property_cache.layer[i].interleaving); + i, c->layer[i].interleaving); val = dib8000_read_word(state, 481 + i); switch (val & 0x7) { case 1: - fe->dtv_property_cache.layer[i].fec = FEC_1_2; + c->layer[i].fec = FEC_1_2; if (show) dprintk("dib8000_get_frontend: Layer %d Code Rate = 1/2 ", i); break; case 2: - fe->dtv_property_cache.layer[i].fec = FEC_2_3; + c->layer[i].fec = FEC_2_3; if (show) dprintk("dib8000_get_frontend: Layer %d Code Rate = 2/3 ", i); break; case 3: - fe->dtv_property_cache.layer[i].fec = FEC_3_4; + c->layer[i].fec = FEC_3_4; if (show) dprintk("dib8000_get_frontend: Layer %d Code Rate = 3/4 ", i); break; case 5: - fe->dtv_property_cache.layer[i].fec = FEC_5_6; + c->layer[i].fec = FEC_5_6; if (show) dprintk("dib8000_get_frontend: Layer %d Code Rate = 5/6 ", i); break; default: - fe->dtv_property_cache.layer[i].fec = FEC_7_8; + c->layer[i].fec = FEC_7_8; if (show) dprintk("dib8000_get_frontend: Layer %d Code Rate = 7/8 ", i); break; @@ -3528,23 +3529,23 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) val = dib8000_read_word(state, 487 + i); switch (val & 0x3) { case 0: - fe->dtv_property_cache.layer[i].modulation = DQPSK; + c->layer[i].modulation = DQPSK; if (show) dprintk("dib8000_get_frontend: Layer %d DQPSK ", i); break; case 1: - fe->dtv_property_cache.layer[i].modulation = QPSK; + c->layer[i].modulation = QPSK; if (show) dprintk("dib8000_get_frontend: Layer %d QPSK ", i); break; case 2: - fe->dtv_property_cache.layer[i].modulation = QAM_16; + c->layer[i].modulation = QAM_16; if (show) dprintk("dib8000_get_frontend: Layer %d QAM16 ", i); break; case 3: default: - fe->dtv_property_cache.layer[i].modulation = QAM_64; + c->layer[i].modulation = QAM_64; if (show) dprintk("dib8000_get_frontend: Layer %d QAM64 ", i); break; @@ -3553,16 +3554,16 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) /* synchronize the cache with the other frontends */ for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = fe->dtv_property_cache.isdbt_sb_mode; - state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion; - state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode; - state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval; - state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = fe->dtv_property_cache.isdbt_partial_reception; + state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = c->isdbt_sb_mode; + state->fe[index_frontend]->dtv_property_cache.inversion = c->inversion; + state->fe[index_frontend]->dtv_property_cache.transmission_mode = c->transmission_mode; + state->fe[index_frontend]->dtv_property_cache.guard_interval = c->guard_interval; + state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = c->isdbt_partial_reception; for (i = 0; i < 3; i++) { - state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = fe->dtv_property_cache.layer[i].segment_count; - state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = fe->dtv_property_cache.layer[i].interleaving; - state->fe[index_frontend]->dtv_property_cache.layer[i].fec = fe->dtv_property_cache.layer[i].fec; - state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = fe->dtv_property_cache.layer[i].modulation; + state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = c->layer[i].segment_count; + state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = c->layer[i].interleaving; + state->fe[index_frontend]->dtv_property_cache.layer[i].fec = c->layer[i].fec; + state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = c->layer[i].modulation; } } return 0; @@ -3671,7 +3672,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe) if (state->channel_parameters_set == 0) { /* searching */ if ((dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_DEMOD_SUCCESS) || (dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_FFT_SUCCESS)) { dprintk("autosearch succeeded on fe%i", index_frontend); - dib8000_get_frontend(state->fe[index_frontend]); /* we read the channel parameters from the frontend which was successful */ + dib8000_get_frontend(state->fe[index_frontend], c); /* we read the channel parameters from the frontend which was successful */ state->channel_parameters_set = 1; for (l = 0; (l < MAX_NUMBER_OF_FRONTENDS) && (state->fe[l] != NULL); l++) { diff --git a/drivers/media/dvb-frontends/dib9000.c b/drivers/media/dvb-frontends/dib9000.c index 91888a2f5301..bab8c5a980a2 100644 --- a/drivers/media/dvb-frontends/dib9000.c +++ b/drivers/media/dvb-frontends/dib9000.c @@ -1889,7 +1889,8 @@ static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_fron return 0; } -static int dib9000_get_frontend(struct dvb_frontend *fe) +static int dib9000_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct dib9000_state *state = fe->demodulator_priv; u8 index_frontend, sub_index_frontend; @@ -1909,7 +1910,7 @@ static int dib9000_get_frontend(struct dvb_frontend *fe) dprintk("TPS lock on the slave%i", index_frontend); /* synchronize the cache with the other frontends */ - state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]); + state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], c); for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) { if (sub_index_frontend != index_frontend) { @@ -1943,14 +1944,14 @@ static int dib9000_get_frontend(struct dvb_frontend *fe) /* synchronize the cache with the other frontends */ for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion; - state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode; - state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval; - state->fe[index_frontend]->dtv_property_cache.modulation = fe->dtv_property_cache.modulation; - state->fe[index_frontend]->dtv_property_cache.hierarchy = fe->dtv_property_cache.hierarchy; - state->fe[index_frontend]->dtv_property_cache.code_rate_HP = fe->dtv_property_cache.code_rate_HP; - state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP; - state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff; + state->fe[index_frontend]->dtv_property_cache.inversion = c->inversion; + state->fe[index_frontend]->dtv_property_cache.transmission_mode = c->transmission_mode; + state->fe[index_frontend]->dtv_property_cache.guard_interval = c->guard_interval; + state->fe[index_frontend]->dtv_property_cache.modulation = c->modulation; + state->fe[index_frontend]->dtv_property_cache.hierarchy = c->hierarchy; + state->fe[index_frontend]->dtv_property_cache.code_rate_HP = c->code_rate_HP; + state->fe[index_frontend]->dtv_property_cache.code_rate_LP = c->code_rate_LP; + state->fe[index_frontend]->dtv_property_cache.rolloff = c->rolloff; } ret = 0; @@ -2083,7 +2084,7 @@ static int dib9000_set_frontend(struct dvb_frontend *fe) /* synchronize all the channel cache */ state->get_frontend_internal = 1; - dib9000_get_frontend(state->fe[0]); + dib9000_get_frontend(state->fe[0], &state->fe[0]->dtv_property_cache); state->get_frontend_internal = 0; /* retune the other frontends with the found channel */ diff --git a/drivers/media/dvb-frontends/dvb_dummy_fe.c b/drivers/media/dvb-frontends/dvb_dummy_fe.c index 14e996d45fac..e5bd8c62ad3a 100644 --- a/drivers/media/dvb-frontends/dvb_dummy_fe.c +++ b/drivers/media/dvb-frontends/dvb_dummy_fe.c @@ -70,9 +70,12 @@ static int dvb_dummy_fe_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) } /* - * Only needed if it actually reads something from the hardware + * Should only be implemented if it actually reads something from the hardware. + * Also, it should check for the locks, in order to avoid report wrong data + * to userspace. */ -static int dvb_dummy_fe_get_frontend(struct dvb_frontend *fe) +static int dvb_dummy_fe_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { return 0; } diff --git a/drivers/media/dvb-frontends/hd29l2.c b/drivers/media/dvb-frontends/hd29l2.c index 40e359f2d17d..1c7eb477e2cd 100644 --- a/drivers/media/dvb-frontends/hd29l2.c +++ b/drivers/media/dvb-frontends/hd29l2.c @@ -560,11 +560,11 @@ static int hd29l2_get_frontend_algo(struct dvb_frontend *fe) return DVBFE_ALGO_CUSTOM; } -static int hd29l2_get_frontend(struct dvb_frontend *fe) +static int hd29l2_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { int ret; struct hd29l2_priv *priv = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; u8 buf[3]; u32 if_ctl; char *str_constellation, *str_code_rate, *str_constellation_code_rate, diff --git a/drivers/media/dvb-frontends/l64781.c b/drivers/media/dvb-frontends/l64781.c index 0977871232a2..2f3d0519e19b 100644 --- a/drivers/media/dvb-frontends/l64781.c +++ b/drivers/media/dvb-frontends/l64781.c @@ -243,9 +243,9 @@ static int apply_frontend_param(struct dvb_frontend *fe) return 0; } -static int get_frontend(struct dvb_frontend *fe) +static int get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct l64781_state* state = fe->demodulator_priv; int tmp; diff --git a/drivers/media/dvb-frontends/lg2160.c b/drivers/media/dvb-frontends/lg2160.c index 7880f71ccd8a..f51a3a0b3949 100644 --- a/drivers/media/dvb-frontends/lg2160.c +++ b/drivers/media/dvb-frontends/lg2160.c @@ -942,101 +942,102 @@ static int lg216x_read_rs_err_count(struct lg216x_state *state, u16 *err) /* ------------------------------------------------------------------------ */ -static int lg216x_get_frontend(struct dvb_frontend *fe) +static int lg216x_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct lg216x_state *state = fe->demodulator_priv; int ret; lg_dbg("\n"); - fe->dtv_property_cache.modulation = VSB_8; - fe->dtv_property_cache.frequency = state->current_frequency; - fe->dtv_property_cache.delivery_system = SYS_ATSCMH; + c->modulation = VSB_8; + c->frequency = state->current_frequency; + c->delivery_system = SYS_ATSCMH; ret = lg216x_get_fic_version(state, - &fe->dtv_property_cache.atscmh_fic_ver); + &c->atscmh_fic_ver); if (lg_fail(ret)) goto fail; - if (state->fic_ver != fe->dtv_property_cache.atscmh_fic_ver) { - state->fic_ver = fe->dtv_property_cache.atscmh_fic_ver; + if (state->fic_ver != c->atscmh_fic_ver) { + state->fic_ver = c->atscmh_fic_ver; #if 0 ret = lg2160_get_parade_id(state, - &fe->dtv_property_cache.atscmh_parade_id); + &c->atscmh_parade_id); if (lg_fail(ret)) goto fail; /* #else */ - fe->dtv_property_cache.atscmh_parade_id = state->parade_id; + c->atscmh_parade_id = state->parade_id; #endif ret = lg216x_get_nog(state, - &fe->dtv_property_cache.atscmh_nog); + &c->atscmh_nog); if (lg_fail(ret)) goto fail; ret = lg216x_get_tnog(state, - &fe->dtv_property_cache.atscmh_tnog); + &c->atscmh_tnog); if (lg_fail(ret)) goto fail; ret = lg216x_get_sgn(state, - &fe->dtv_property_cache.atscmh_sgn); + &c->atscmh_sgn); if (lg_fail(ret)) goto fail; ret = lg216x_get_prc(state, - &fe->dtv_property_cache.atscmh_prc); + &c->atscmh_prc); if (lg_fail(ret)) goto fail; ret = lg216x_get_rs_frame_mode(state, (enum atscmh_rs_frame_mode *) - &fe->dtv_property_cache.atscmh_rs_frame_mode); + &c->atscmh_rs_frame_mode); if (lg_fail(ret)) goto fail; ret = lg216x_get_rs_frame_ensemble(state, (enum atscmh_rs_frame_ensemble *) - &fe->dtv_property_cache.atscmh_rs_frame_ensemble); + &c->atscmh_rs_frame_ensemble); if (lg_fail(ret)) goto fail; ret = lg216x_get_rs_code_mode(state, (enum atscmh_rs_code_mode *) - &fe->dtv_property_cache.atscmh_rs_code_mode_pri, + &c->atscmh_rs_code_mode_pri, (enum atscmh_rs_code_mode *) - &fe->dtv_property_cache.atscmh_rs_code_mode_sec); + &c->atscmh_rs_code_mode_sec); if (lg_fail(ret)) goto fail; ret = lg216x_get_sccc_block_mode(state, (enum atscmh_sccc_block_mode *) - &fe->dtv_property_cache.atscmh_sccc_block_mode); + &c->atscmh_sccc_block_mode); if (lg_fail(ret)) goto fail; ret = lg216x_get_sccc_code_mode(state, (enum atscmh_sccc_code_mode *) - &fe->dtv_property_cache.atscmh_sccc_code_mode_a, + &c->atscmh_sccc_code_mode_a, (enum atscmh_sccc_code_mode *) - &fe->dtv_property_cache.atscmh_sccc_code_mode_b, + &c->atscmh_sccc_code_mode_b, (enum atscmh_sccc_code_mode *) - &fe->dtv_property_cache.atscmh_sccc_code_mode_c, + &c->atscmh_sccc_code_mode_c, (enum atscmh_sccc_code_mode *) - &fe->dtv_property_cache.atscmh_sccc_code_mode_d); + &c->atscmh_sccc_code_mode_d); if (lg_fail(ret)) goto fail; } #if 0 ret = lg216x_read_fic_err_count(state, - (u8 *)&fe->dtv_property_cache.atscmh_fic_err); + (u8 *)&c->atscmh_fic_err); if (lg_fail(ret)) goto fail; ret = lg216x_read_crc_err_count(state, - &fe->dtv_property_cache.atscmh_crc_err); + &c->atscmh_crc_err); if (lg_fail(ret)) goto fail; ret = lg216x_read_rs_err_count(state, - &fe->dtv_property_cache.atscmh_rs_err); + &c->atscmh_rs_err); if (lg_fail(ret)) goto fail; switch (state->cfg->lg_chip) { case LG2160: - if (((fe->dtv_property_cache.atscmh_rs_err >= 240) && - (fe->dtv_property_cache.atscmh_crc_err >= 240)) && + if (((c->atscmh_rs_err >= 240) && + (c->atscmh_crc_err >= 240)) && ((jiffies_to_msecs(jiffies) - state->last_reset) > 6000)) ret = lg216x_soft_reset(state); break; @@ -1054,14 +1055,17 @@ fail: static int lg216x_get_property(struct dvb_frontend *fe, struct dtv_property *tvp) { + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + return (DTV_ATSCMH_FIC_VER == tvp->cmd) ? - lg216x_get_frontend(fe) : 0; + lg216x_get_frontend(fe, c) : 0; } static int lg2160_set_frontend(struct dvb_frontend *fe) { struct lg216x_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; lg_dbg("(%d)\n", fe->dtv_property_cache.frequency); @@ -1129,7 +1133,7 @@ static int lg2160_set_frontend(struct dvb_frontend *fe) ret = lg216x_enable_fic(state, 1); lg_fail(ret); - lg216x_get_frontend(fe); + lg216x_get_frontend(fe, c); fail: return ret; } diff --git a/drivers/media/dvb-frontends/lgdt3305.c b/drivers/media/dvb-frontends/lgdt3305.c index 47121866163d..4503e8852fd1 100644 --- a/drivers/media/dvb-frontends/lgdt3305.c +++ b/drivers/media/dvb-frontends/lgdt3305.c @@ -812,9 +812,9 @@ fail: return ret; } -static int lgdt3305_get_frontend(struct dvb_frontend *fe) +static int lgdt3305_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct lgdt3305_state *state = fe->demodulator_priv; lg_dbg("\n"); diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c index 721fbc07e9ee..179c26e5eb4e 100644 --- a/drivers/media/dvb-frontends/lgdt3306a.c +++ b/drivers/media/dvb-frontends/lgdt3306a.c @@ -1040,10 +1040,10 @@ fail: return ret; } -static int lgdt3306a_get_frontend(struct dvb_frontend *fe) +static int lgdt3306a_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { struct lgdt3306a_state *state = fe->demodulator_priv; - struct dtv_frontend_properties *p = &fe->dtv_property_cache; dbg_info("(%u, %d)\n", state->current_frequency, state->current_modulation); diff --git a/drivers/media/dvb-frontends/lgdt330x.c b/drivers/media/dvb-frontends/lgdt330x.c index cf3cc20510da..96bf254da21e 100644 --- a/drivers/media/dvb-frontends/lgdt330x.c +++ b/drivers/media/dvb-frontends/lgdt330x.c @@ -439,10 +439,11 @@ static int lgdt330x_set_parameters(struct dvb_frontend *fe) return 0; } -static int lgdt330x_get_frontend(struct dvb_frontend *fe) +static int lgdt330x_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct lgdt330x_state *state = fe->demodulator_priv; + p->frequency = state->current_frequency; return 0; } diff --git a/drivers/media/dvb-frontends/lgs8gl5.c b/drivers/media/dvb-frontends/lgs8gl5.c index 7bbb2c18c2dd..fbfd87b5b803 100644 --- a/drivers/media/dvb-frontends/lgs8gl5.c +++ b/drivers/media/dvb-frontends/lgs8gl5.c @@ -336,10 +336,11 @@ lgs8gl5_set_frontend(struct dvb_frontend *fe) static int -lgs8gl5_get_frontend(struct dvb_frontend *fe) +lgs8gl5_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct lgs8gl5_state *state = fe->demodulator_priv; + u8 inv = lgs8gl5_read_reg(state, REG_INVERSION); p->inversion = (inv & REG_INVERSION_ON) ? INVERSION_ON : INVERSION_OFF; diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c index ce73a5ec6036..76883600ec6f 100644 --- a/drivers/media/dvb-frontends/m88ds3103.c +++ b/drivers/media/dvb-frontends/m88ds3103.c @@ -791,11 +791,11 @@ err: return ret; } -static int m88ds3103_get_frontend(struct dvb_frontend *fe) +static int m88ds3103_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct m88ds3103_dev *dev = fe->demodulator_priv; struct i2c_client *client = dev->client; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[3]; diff --git a/drivers/media/dvb-frontends/m88rs2000.c b/drivers/media/dvb-frontends/m88rs2000.c index 9b6f464c48bd..a09b12313a73 100644 --- a/drivers/media/dvb-frontends/m88rs2000.c +++ b/drivers/media/dvb-frontends/m88rs2000.c @@ -708,10 +708,11 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe) return 0; } -static int m88rs2000_get_frontend(struct dvb_frontend *fe) +static int m88rs2000_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct m88rs2000_state *state = fe->demodulator_priv; + c->fec_inner = state->fec_inner; c->frequency = state->tuner_frequency; c->symbol_rate = state->symbol_rate; diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c index c36e6764eead..fc08429c99b7 100644 --- a/drivers/media/dvb-frontends/mt312.c +++ b/drivers/media/dvb-frontends/mt312.c @@ -647,9 +647,9 @@ static int mt312_set_frontend(struct dvb_frontend *fe) return 0; } -static int mt312_get_frontend(struct dvb_frontend *fe) +static int mt312_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct mt312_state *state = fe->demodulator_priv; int ret; diff --git a/drivers/media/dvb-frontends/mt352.c b/drivers/media/dvb-frontends/mt352.c index 123bb2f8e4b6..c0bb6328956b 100644 --- a/drivers/media/dvb-frontends/mt352.c +++ b/drivers/media/dvb-frontends/mt352.c @@ -311,9 +311,9 @@ static int mt352_set_parameters(struct dvb_frontend *fe) return 0; } -static int mt352_get_parameters(struct dvb_frontend* fe) +static int mt352_get_parameters(struct dvb_frontend* fe, + struct dtv_frontend_properties *op) { - struct dtv_frontend_properties *op = &fe->dtv_property_cache; struct mt352_state* state = fe->demodulator_priv; u16 tps; u16 div; diff --git a/drivers/media/dvb-frontends/or51132.c b/drivers/media/dvb-frontends/or51132.c index 35b1053b3640..a165af990672 100644 --- a/drivers/media/dvb-frontends/or51132.c +++ b/drivers/media/dvb-frontends/or51132.c @@ -375,9 +375,9 @@ static int or51132_set_parameters(struct dvb_frontend *fe) return 0; } -static int or51132_get_parameters(struct dvb_frontend* fe) +static int or51132_get_parameters(struct dvb_frontend* fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct or51132_state* state = fe->demodulator_priv; int status; int retry = 1; diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 74b771218033..3f96429af0e5 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -279,11 +279,11 @@ err: return ret; } -static int rtl2830_get_frontend(struct dvb_frontend *fe) +static int rtl2830_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct i2c_client *client = fe->demodulator_priv; struct rtl2830_dev *dev = i2c_get_clientdata(client); - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[3]; diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 10f2119935da..c2469fb42f12 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -575,11 +575,11 @@ err: return ret; } -static int rtl2832_get_frontend(struct dvb_frontend *fe) +static int rtl2832_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct rtl2832_dev *dev = fe->demodulator_priv; struct i2c_client *client = dev->client; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[3]; diff --git a/drivers/media/dvb-frontends/s5h1409.c b/drivers/media/dvb-frontends/s5h1409.c index 10964848a2f1..c68965ad97c0 100644 --- a/drivers/media/dvb-frontends/s5h1409.c +++ b/drivers/media/dvb-frontends/s5h1409.c @@ -925,9 +925,9 @@ static int s5h1409_read_ber(struct dvb_frontend *fe, u32 *ber) return s5h1409_read_ucblocks(fe, ber); } -static int s5h1409_get_frontend(struct dvb_frontend *fe) +static int s5h1409_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct s5h1409_state *state = fe->demodulator_priv; p->frequency = state->current_frequency; diff --git a/drivers/media/dvb-frontends/s5h1411.c b/drivers/media/dvb-frontends/s5h1411.c index 9afc3f42290e..90f86e82b087 100644 --- a/drivers/media/dvb-frontends/s5h1411.c +++ b/drivers/media/dvb-frontends/s5h1411.c @@ -840,9 +840,9 @@ static int s5h1411_read_ber(struct dvb_frontend *fe, u32 *ber) return s5h1411_read_ucblocks(fe, ber); } -static int s5h1411_get_frontend(struct dvb_frontend *fe) +static int s5h1411_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct s5h1411_state *state = fe->demodulator_priv; p->frequency = state->current_frequency; diff --git a/drivers/media/dvb-frontends/s5h1420.c b/drivers/media/dvb-frontends/s5h1420.c index 9c22a4c70d87..d7d0b7d57ad7 100644 --- a/drivers/media/dvb-frontends/s5h1420.c +++ b/drivers/media/dvb-frontends/s5h1420.c @@ -756,9 +756,9 @@ static int s5h1420_set_frontend(struct dvb_frontend *fe) return 0; } -static int s5h1420_get_frontend(struct dvb_frontend* fe) +static int s5h1420_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct s5h1420_state* state = fe->demodulator_priv; p->frequency = state->tunedfreq + s5h1420_getfreqoffset(state); diff --git a/drivers/media/dvb-frontends/s921.c b/drivers/media/dvb-frontends/s921.c index d6a8fa63040b..b5e3d90eba5e 100644 --- a/drivers/media/dvb-frontends/s921.c +++ b/drivers/media/dvb-frontends/s921.c @@ -433,9 +433,9 @@ static int s921_set_frontend(struct dvb_frontend *fe) return 0; } -static int s921_get_frontend(struct dvb_frontend *fe) +static int s921_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct s921_state *state = fe->demodulator_priv; /* FIXME: Probably it is possible to get it from regs f1 and f2 */ diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c index 756650f154ab..3d171b0e00c2 100644 --- a/drivers/media/dvb-frontends/stb0899_drv.c +++ b/drivers/media/dvb-frontends/stb0899_drv.c @@ -1568,9 +1568,9 @@ static enum dvbfe_search stb0899_search(struct dvb_frontend *fe) return DVBFE_ALGO_SEARCH_ERROR; } -static int stb0899_get_frontend(struct dvb_frontend *fe) +static int stb0899_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stb0899_state *state = fe->demodulator_priv; struct stb0899_internal *internal = &state->internal; diff --git a/drivers/media/dvb-frontends/stb6100.c b/drivers/media/dvb-frontends/stb6100.c index c978c801c7aa..b9c2511bf019 100644 --- a/drivers/media/dvb-frontends/stb6100.c +++ b/drivers/media/dvb-frontends/stb6100.c @@ -346,7 +346,7 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency) if (fe->ops.get_frontend) { dprintk(verbose, FE_DEBUG, 1, "Get frontend parameters"); - fe->ops.get_frontend(fe); + fe->ops.get_frontend(fe, p); } srate = p->symbol_rate; diff --git a/drivers/media/dvb-frontends/stv0297.c b/drivers/media/dvb-frontends/stv0297.c index 75b4d8b25657..81b27b7c0c96 100644 --- a/drivers/media/dvb-frontends/stv0297.c +++ b/drivers/media/dvb-frontends/stv0297.c @@ -615,9 +615,9 @@ timeout: return 0; } -static int stv0297_get_frontend(struct dvb_frontend *fe) +static int stv0297_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stv0297_state *state = fe->demodulator_priv; int reg_00, reg_83; diff --git a/drivers/media/dvb-frontends/stv0299.c b/drivers/media/dvb-frontends/stv0299.c index c43f36d32340..7927fa925f2f 100644 --- a/drivers/media/dvb-frontends/stv0299.c +++ b/drivers/media/dvb-frontends/stv0299.c @@ -602,9 +602,9 @@ static int stv0299_set_frontend(struct dvb_frontend *fe) return 0; } -static int stv0299_get_frontend(struct dvb_frontend *fe) +static int stv0299_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stv0299_state* state = fe->demodulator_priv; s32 derot_freq; int invval; diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c index 44cb73f68af6..abc379aea713 100644 --- a/drivers/media/dvb-frontends/stv0367.c +++ b/drivers/media/dvb-frontends/stv0367.c @@ -1938,9 +1938,9 @@ static int stv0367ter_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) return 0; } -static int stv0367ter_get_frontend(struct dvb_frontend *fe) +static int stv0367ter_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stv0367_state *state = fe->demodulator_priv; struct stv0367ter_state *ter_state = state->ter_state; enum stv0367_ter_mode mode; @@ -3146,9 +3146,9 @@ static int stv0367cab_set_frontend(struct dvb_frontend *fe) return 0; } -static int stv0367cab_get_frontend(struct dvb_frontend *fe) +static int stv0367cab_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stv0367_state *state = fe->demodulator_priv; struct stv0367cab_state *cab_state = state->cab_state; diff --git a/drivers/media/dvb-frontends/stv0900_core.c b/drivers/media/dvb-frontends/stv0900_core.c index fe31dd541955..28239b1fd954 100644 --- a/drivers/media/dvb-frontends/stv0900_core.c +++ b/drivers/media/dvb-frontends/stv0900_core.c @@ -1859,9 +1859,9 @@ static int stv0900_sleep(struct dvb_frontend *fe) return 0; } -static int stv0900_get_frontend(struct dvb_frontend *fe) +static int stv0900_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stv0900_state *state = fe->demodulator_priv; struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; diff --git a/drivers/media/dvb-frontends/tc90522.c b/drivers/media/dvb-frontends/tc90522.c index 456cdc7fb1e7..31cd32532387 100644 --- a/drivers/media/dvb-frontends/tc90522.c +++ b/drivers/media/dvb-frontends/tc90522.c @@ -201,10 +201,10 @@ static const enum fe_code_rate fec_conv_sat[] = { FEC_2_3, /* for 8PSK. (trellis code) */ }; -static int tc90522s_get_frontend(struct dvb_frontend *fe) +static int tc90522s_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct tc90522_state *state; - struct dtv_frontend_properties *c; struct dtv_fe_stats *stats; int ret, i; int layers; @@ -212,7 +212,6 @@ static int tc90522s_get_frontend(struct dvb_frontend *fe) u32 cndat; state = fe->demodulator_priv; - c = &fe->dtv_property_cache; c->delivery_system = SYS_ISDBS; c->symbol_rate = 28860000; @@ -337,10 +336,10 @@ static const enum fe_modulation mod_conv[] = { DQPSK, QPSK, QAM_16, QAM_64, 0, 0, 0, 0 }; -static int tc90522t_get_frontend(struct dvb_frontend *fe) +static int tc90522t_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct tc90522_state *state; - struct dtv_frontend_properties *c; struct dtv_fe_stats *stats; int ret, i; int layers; @@ -348,7 +347,6 @@ static int tc90522t_get_frontend(struct dvb_frontend *fe) u32 cndat; state = fe->demodulator_priv; - c = &fe->dtv_property_cache; c->delivery_system = SYS_ISDBT; c->bandwidth_hz = 6000000; mode = 1; diff --git a/drivers/media/dvb-frontends/tda10021.c b/drivers/media/dvb-frontends/tda10021.c index a684424e665a..806c56691ca5 100644 --- a/drivers/media/dvb-frontends/tda10021.c +++ b/drivers/media/dvb-frontends/tda10021.c @@ -387,9 +387,9 @@ static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) return 0; } -static int tda10021_get_frontend(struct dvb_frontend *fe) +static int tda10021_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct tda10021_state* state = fe->demodulator_priv; int sync; s8 afc = 0; diff --git a/drivers/media/dvb-frontends/tda10023.c b/drivers/media/dvb-frontends/tda10023.c index 44a55656093f..3b8c7e499d0d 100644 --- a/drivers/media/dvb-frontends/tda10023.c +++ b/drivers/media/dvb-frontends/tda10023.c @@ -457,9 +457,9 @@ static int tda10023_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) return 0; } -static int tda10023_get_frontend(struct dvb_frontend *fe) +static int tda10023_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct tda10023_state* state = fe->demodulator_priv; int sync,inv; s8 afc = 0; diff --git a/drivers/media/dvb-frontends/tda10048.c b/drivers/media/dvb-frontends/tda10048.c index 8451086c563f..c2bf89d0b0b0 100644 --- a/drivers/media/dvb-frontends/tda10048.c +++ b/drivers/media/dvb-frontends/tda10048.c @@ -1028,9 +1028,9 @@ static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) return 0; } -static int tda10048_get_frontend(struct dvb_frontend *fe) +static int tda10048_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct tda10048_state *state = fe->demodulator_priv; dprintk(1, "%s()\n", __func__); diff --git a/drivers/media/dvb-frontends/tda1004x.c b/drivers/media/dvb-frontends/tda1004x.c index 0e209b56c76c..3137a9ba3a32 100644 --- a/drivers/media/dvb-frontends/tda1004x.c +++ b/drivers/media/dvb-frontends/tda1004x.c @@ -899,9 +899,9 @@ static int tda1004x_set_fe(struct dvb_frontend *fe) return 0; } -static int tda1004x_get_fe(struct dvb_frontend *fe) +static int tda1004x_get_fe(struct dvb_frontend *fe, + struct dtv_frontend_properties *fe_params) { - struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache; struct tda1004x_state* state = fe->demodulator_priv; dprintk("%s\n", __func__); diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c index 119d47596ac8..37ebeef2bbd0 100644 --- a/drivers/media/dvb-frontends/tda10071.c +++ b/drivers/media/dvb-frontends/tda10071.c @@ -701,11 +701,11 @@ error: return ret; } -static int tda10071_get_frontend(struct dvb_frontend *fe) +static int tda10071_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct tda10071_dev *dev = fe->demodulator_priv; struct i2c_client *client = dev->client; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i; u8 buf[5], tmp; diff --git a/drivers/media/dvb-frontends/tda10086.c b/drivers/media/dvb-frontends/tda10086.c index 95a33e187f8e..31d0acb54fe8 100644 --- a/drivers/media/dvb-frontends/tda10086.c +++ b/drivers/media/dvb-frontends/tda10086.c @@ -459,9 +459,9 @@ static int tda10086_set_frontend(struct dvb_frontend *fe) return 0; } -static int tda10086_get_frontend(struct dvb_frontend *fe) +static int tda10086_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *fe_params) { - struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache; struct tda10086_state* state = fe->demodulator_priv; u8 val; int tmp; diff --git a/drivers/media/dvb-frontends/tda8083.c b/drivers/media/dvb-frontends/tda8083.c index 796543fa2c8d..9072d6463094 100644 --- a/drivers/media/dvb-frontends/tda8083.c +++ b/drivers/media/dvb-frontends/tda8083.c @@ -342,9 +342,9 @@ static int tda8083_set_frontend(struct dvb_frontend *fe) return 0; } -static int tda8083_get_frontend(struct dvb_frontend *fe) +static int tda8083_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct tda8083_state* state = fe->demodulator_priv; /* FIXME: get symbolrate & frequency offset...*/ diff --git a/drivers/media/dvb-frontends/ves1820.c b/drivers/media/dvb-frontends/ves1820.c index aacfdda3e005..b09fe88c40f8 100644 --- a/drivers/media/dvb-frontends/ves1820.c +++ b/drivers/media/dvb-frontends/ves1820.c @@ -312,9 +312,9 @@ static int ves1820_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) return 0; } -static int ves1820_get_frontend(struct dvb_frontend *fe) +static int ves1820_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct ves1820_state* state = fe->demodulator_priv; int sync; s8 afc = 0; diff --git a/drivers/media/dvb-frontends/ves1x93.c b/drivers/media/dvb-frontends/ves1x93.c index 526952396422..ed113e216e14 100644 --- a/drivers/media/dvb-frontends/ves1x93.c +++ b/drivers/media/dvb-frontends/ves1x93.c @@ -406,9 +406,9 @@ static int ves1x93_set_frontend(struct dvb_frontend *fe) return 0; } -static int ves1x93_get_frontend(struct dvb_frontend *fe) +static int ves1x93_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct ves1x93_state* state = fe->demodulator_priv; int afc; diff --git a/drivers/media/dvb-frontends/zl10353.c b/drivers/media/dvb-frontends/zl10353.c index ef9764a02d4c..1832c2f7695c 100644 --- a/drivers/media/dvb-frontends/zl10353.c +++ b/drivers/media/dvb-frontends/zl10353.c @@ -371,9 +371,9 @@ static int zl10353_set_parameters(struct dvb_frontend *fe) return 0; } -static int zl10353_get_parameters(struct dvb_frontend *fe) +static int zl10353_get_parameters(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct zl10353_state *state = fe->demodulator_priv; int s6, s9; u16 tps; diff --git a/drivers/media/pci/bt8xx/dst.c b/drivers/media/pci/bt8xx/dst.c index 4a90eee5e3bb..35bc9b2287b4 100644 --- a/drivers/media/pci/bt8xx/dst.c +++ b/drivers/media/pci/bt8xx/dst.c @@ -1688,9 +1688,9 @@ static int dst_get_tuning_algo(struct dvb_frontend *fe) return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW; } -static int dst_get_frontend(struct dvb_frontend *fe) +static int dst_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct dst_state *state = fe->demodulator_priv; p->frequency = state->decode_freq; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c index 84f6de6fa07d..047a32fe43ea 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c @@ -507,9 +507,9 @@ static int mxl111sf_demod_read_signal_strength(struct dvb_frontend *fe, return 0; } -static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe) +static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct mxl111sf_demod_state *state = fe->demodulator_priv; mxl_dbg("()"); diff --git a/drivers/media/usb/dvb-usb/af9005-fe.c b/drivers/media/usb/dvb-usb/af9005-fe.c index ac97075d75f7..09db3d02bd82 100644 --- a/drivers/media/usb/dvb-usb/af9005-fe.c +++ b/drivers/media/usb/dvb-usb/af9005-fe.c @@ -1227,9 +1227,9 @@ static int af9005_fe_set_frontend(struct dvb_frontend *fe) return 0; } -static int af9005_fe_get_frontend(struct dvb_frontend *fe) +static int af9005_fe_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *fep) { - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct af9005_fe_state *state = fe->demodulator_priv; int ret; u8 temp; diff --git a/drivers/media/usb/dvb-usb/dtt200u-fe.c b/drivers/media/usb/dvb-usb/dtt200u-fe.c index 7e72a1bef76a..c09332bd99cb 100644 --- a/drivers/media/usb/dvb-usb/dtt200u-fe.c +++ b/drivers/media/usb/dvb-usb/dtt200u-fe.c @@ -140,10 +140,11 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend *fe) return 0; } -static int dtt200u_fe_get_frontend(struct dvb_frontend* fe) +static int dtt200u_fe_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *fep) { - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct dtt200u_fe_state *state = fe->demodulator_priv; + memcpy(fep, &state->fep, sizeof(struct dtv_frontend_properties)); return 0; } -- cgit v1.2.3 From bb31d2381c730485be00a7da44c45416e9781709 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 13:26:22 -0200 Subject: [media] dvb_frontend: Don't let drivers to trash data at cache GET_FRONTEND and G_PROPERTY can be called anytime, even when the tuner/demod is not fully locked. However, several parameters returned by those calls are available only after the demod get VITERBI lock. While several drivers do the right thing by checking the status before returning the parameter, some drivers simply blindly update the DTV properties cache without checking if the registers at the hardware contain valid values. Due to that, programs that call G_PROPERTY (or GET_FRONTEND) before having a tuner lock may interfere at the zigzag logic, as the DVB kthread calls the set_frontend() callback several times, to fine tune the frequency and to identify if the signal is inverted or not. While the drivers should be fixed to report the right status, we should prevent that such bugs would actually interfere at the device operation. So, let's use a separate var for userspace calls to get frontend. As we copy the content of the cache, this should not cause any troubles. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index d009478f16c4..4c35eb47472b 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -2087,6 +2087,8 @@ static int dvb_frontend_ioctl_properties(struct file *file, dev_dbg(fe->dvb->device, "%s: Property cache is full, tuning\n", __func__); } else if (cmd == FE_GET_PROPERTY) { + struct dtv_frontend_properties getp = fe->dtv_property_cache; + dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num); dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props); @@ -2108,17 +2110,18 @@ static int dvb_frontend_ioctl_properties(struct file *file, } /* - * Fills the cache out struct with the cache contents, plus - * the data retrieved from get_frontend, if the frontend - * is not idle. Otherwise, returns the cached content + * Let's use our own copy of property cache, in order to + * avoid mangling with DTV zigzag logic, as drivers might + * return crap, if they don't check if the data is available + * before updating the properties cache. */ if (fepriv->state != FESTATE_IDLE) { - err = dtv_get_frontend(fe, c, NULL); + err = dtv_get_frontend(fe, &getp, NULL); if (err < 0) goto out; } for (i = 0; i < tvps->num; i++) { - err = dtv_property_process_get(fe, c, tvp + i, file); + err = dtv_property_process_get(fe, &getp, tvp + i, file); if (err < 0) goto out; (tvp + i)->result = err; @@ -2523,10 +2526,18 @@ static int dvb_frontend_ioctl_legacy(struct file *file, err = dvb_frontend_get_event (fe, parg, file->f_flags); break; - case FE_GET_FRONTEND: - err = dtv_get_frontend(fe, c, parg); - break; + case FE_GET_FRONTEND: { + struct dtv_frontend_properties getp = fe->dtv_property_cache; + /* + * Let's use our own copy of property cache, in order to + * avoid mangling with DTV zigzag logic, as drivers might + * return crap, if they don't check if the data is available + * before updating the properties cache. + */ + err = dtv_get_frontend(fe, &getp, parg); + break; + } case FE_SET_FRONTEND_TUNE_MODE: fepriv->tune_mode_flags = (unsigned long) parg; err = 0; -- cgit v1.2.3 From 96afef1d5adee8722549c8c2b788d656ea2ecf21 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 4 Feb 2016 18:52:47 +0200 Subject: drm/i915/dsi: skip gpio element execution when not supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Skip v3 gpio element because the support is not there, and skip gpio element on non-vlv because the sideband code is vlv specific. v2: the gpio stuff is currently only supported on vlv (Ville) Cc: drm-intel-fixes@lists.freedesktop.org Fixes: 2a33d93486f2 ("drm/i915/bios: add support for MIPI sequence block v3") Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1454604767-2440-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 76dbd1a36c57..787f01c63984 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -204,6 +204,9 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) struct drm_device *dev = intel_dsi->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + if (dev_priv->vbt.dsi.seq_version >= 3) + data++; + gpio = *data++; /* pull up/down */ @@ -214,6 +217,16 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) goto out; } + if (!IS_VALLEYVIEW(dev_priv)) { + DRM_DEBUG_KMS("GPIO element not supported on this platform\n"); + goto out; + } + + if (dev_priv->vbt.dsi.seq_version >= 3) { + DRM_DEBUG_KMS("GPIO element v3 not supported\n"); + goto out; + } + function = gtable[gpio].function_reg; pad = gtable[gpio].pad_reg; -- cgit v1.2.3 From 1586ba0c218b10cce1de57c45f599dd8831a2d12 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 4 Feb 2016 11:17:36 -0500 Subject: USB: EHCI: fix compiler warning introduced by commit 2a40f324541e Fix the following compiler warning (found by the kbuild test robot): drivers/usb/host/ehci-hcd.c:312:13: warning: 'unlink_empty_async_suspended' declared 'static' but never defined Commit 2a40f324541e ("USB: EHCI: fix regression during bus resume") protected the function definition with a "#ifdef CONFIG_PM" block, so now the declaration needs to be similarly protected. This patch moves it to a better location. Reported-by: kbuild test robot Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 1 - drivers/usb/host/ehci-hub.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a93d445b63a4..ae1b6e69eb96 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -309,7 +309,6 @@ static void ehci_quiesce (struct ehci_hcd *ehci) static void end_iaa_cycle(struct ehci_hcd *ehci); static void end_unlink_async(struct ehci_hcd *ehci); static void unlink_empty_async(struct ehci_hcd *ehci); -static void unlink_empty_async_suspended(struct ehci_hcd *ehci); static void ehci_work(struct ehci_hcd *ehci); static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 6333d3c2be9c..ffc90295a95f 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -33,6 +33,8 @@ #ifdef CONFIG_PM +static void unlink_empty_async_suspended(struct ehci_hcd *ehci); + static int persist_enabled_on_companion(struct usb_device *udev, void *unused) { return !udev->maxchild && udev->persist_enabled && -- cgit v1.2.3 From 3b0a6d1a1b3335fde9cbbc659568ed619b07d24a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 4 Feb 2016 14:02:45 -0600 Subject: PCI/AER: Rename pci_ops_aer to aer_inj_pci_ops Rename pci_ops_aer to aer_inj_pci_ops pci_read_aer() to aer_inj_read_config() pci_write_aer() to aer_inj_write_config() This is more conventional and more informative. No functional change. Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/aer/aer_inject.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 20db790465dd..148a301a6b3c 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -181,8 +181,8 @@ static u32 *find_pci_config_dword(struct aer_error *err, int where, return target; } -static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where, - int size, u32 *val) +static int aer_inj_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) { u32 *sim; struct aer_error *err; @@ -212,8 +212,8 @@ out: return ops->read(bus, devfn, where, size, val); } -static int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, - int size, u32 val) +static int aer_inj_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) { u32 *sim; struct aer_error *err; @@ -247,9 +247,9 @@ out: return ops->write(bus, devfn, where, size, val); } -static struct pci_ops pci_ops_aer = { - .read = pci_read_aer, - .write = pci_write_aer, +static struct pci_ops aer_inj_pci_ops = { + .read = aer_inj_read_config, + .write = aer_inj_write_config, }; static void pci_bus_ops_init(struct pci_bus_ops *bus_ops, @@ -270,9 +270,9 @@ static int pci_bus_set_aer_ops(struct pci_bus *bus) bus_ops = kmalloc(sizeof(*bus_ops), GFP_KERNEL); if (!bus_ops) return -ENOMEM; - ops = pci_bus_set_ops(bus, &pci_ops_aer); + ops = pci_bus_set_ops(bus, &aer_inj_pci_ops); spin_lock_irqsave(&inject_lock, flags); - if (ops == &pci_ops_aer) + if (ops == &aer_inj_pci_ops) goto out; pci_bus_ops_init(bus_ops, bus, ops); list_add(&bus_ops->list, &pci_bus_ops_list); -- cgit v1.2.3 From 7e8fbdc628760857369af05636ed4ddc4fc8569b Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 22 Dec 2015 13:44:51 -0800 Subject: PCI/AER: Restore pci_ops pointer while calling original pci_ops The aer_inject module intercepts config space accesses by replacing the bus->ops pointer. If it forwards accesses to the original pci_ops, and those original ops use bus->ops, they see the aer_pci_ops instead of their own pci_ops, which can cause a crash. For example, pci_generic_config_read() uses the bus->ops->map_bus pointer. If bus->ops is set to aer_pci_ops, which doesn't supply .map_bus, pci_generic_config_read() will dereference an invalid pointer and cause a crash. Temporarily restore the original bus->ops pointer while calling ops->read() or ops->write(). Callers of these functions already hold pci_lock, which prevents other users of bus->ops until we're finished. [bhelgaas: changelog] Signed-off-by: David Daney Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/aer/aer_inject.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 148a301a6b3c..79a5e112711a 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -188,7 +188,9 @@ static int aer_inj_read_config(struct pci_bus *bus, unsigned int devfn, struct aer_error *err; unsigned long flags; struct pci_ops *ops; + struct pci_ops *my_ops; int domain; + int rv; spin_lock_irqsave(&inject_lock, flags); if (size != sizeof(u32)) @@ -208,8 +210,19 @@ static int aer_inj_read_config(struct pci_bus *bus, unsigned int devfn, } out: ops = __find_pci_bus_ops(bus); + /* + * pci_lock must already be held, so we can directly + * manipulate bus->ops. Many config access functions, + * including pci_generic_config_read() require the original + * bus->ops be installed to function, so temporarily put them + * back. + */ + my_ops = bus->ops; + bus->ops = ops; + rv = ops->read(bus, devfn, where, size, val); + bus->ops = my_ops; spin_unlock_irqrestore(&inject_lock, flags); - return ops->read(bus, devfn, where, size, val); + return rv; } static int aer_inj_write_config(struct pci_bus *bus, unsigned int devfn, @@ -220,7 +233,9 @@ static int aer_inj_write_config(struct pci_bus *bus, unsigned int devfn, unsigned long flags; int rw1cs; struct pci_ops *ops; + struct pci_ops *my_ops; int domain; + int rv; spin_lock_irqsave(&inject_lock, flags); if (size != sizeof(u32)) @@ -243,8 +258,19 @@ static int aer_inj_write_config(struct pci_bus *bus, unsigned int devfn, } out: ops = __find_pci_bus_ops(bus); + /* + * pci_lock must already be held, so we can directly + * manipulate bus->ops. Many config access functions, + * including pci_generic_config_write() require the original + * bus->ops be installed to function, so temporarily put them + * back. + */ + my_ops = bus->ops; + bus->ops = ops; + rv = ops->write(bus, devfn, where, size, val); + bus->ops = my_ops; spin_unlock_irqrestore(&inject_lock, flags); - return ops->write(bus, devfn, where, size, val); + return rv; } static struct pci_ops aer_inj_pci_ops = { -- cgit v1.2.3 From 0e6053dc6e7a42c8ba9ce6e81adb3350c7df4bc8 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Fri, 22 Jan 2016 22:50:19 +0800 Subject: PCI/AER: Use list_first_entry_or_null() to simplify code Use list_first_entry_or_null() instead of list_empty() + list_entry() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/aer/aer_inject.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 79a5e112711a..e2760a39a98a 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -124,16 +124,13 @@ static struct pci_ops *__find_pci_bus_ops(struct pci_bus *bus) static struct pci_bus_ops *pci_bus_ops_pop(void) { unsigned long flags; - struct pci_bus_ops *bus_ops = NULL; + struct pci_bus_ops *bus_ops; spin_lock_irqsave(&inject_lock, flags); - if (list_empty(&pci_bus_ops_list)) - bus_ops = NULL; - else { - struct list_head *lh = pci_bus_ops_list.next; - list_del(lh); - bus_ops = list_entry(lh, struct pci_bus_ops, list); - } + bus_ops = list_first_entry_or_null(&pci_bus_ops_list, + struct pci_bus_ops, list); + if (bus_ops) + list_del(&bus_ops->list); spin_unlock_irqrestore(&inject_lock, flags); return bus_ops; } -- cgit v1.2.3 From b404bcfbf035413dcce539c8ba2c9986d220d8ed Mon Sep 17 00:00:00 2001 From: Manish Jaggi Date: Sat, 30 Jan 2016 01:33:58 +0530 Subject: PCI: Add ACS quirk for all Cavium devices Cavium devices matching this quirk do not perform peer-to-peer with other functions, allowing masking out these bits as if they were unimplemented in the ACS capability. Signed-off-by: Manish Jaggi Signed-off-by: Bjorn Helgaas Acked-by: Tirumalesh Chalamarla --- drivers/pci/quirks.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 0575a1e026b4..85fa6a2a6dd2 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3832,6 +3832,19 @@ static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags) #endif } +static int pci_quirk_cavium_acs(struct pci_dev *dev, u16 acs_flags) +{ + /* + * Cavium devices matching this quirk do not perform peer-to-peer + * with other functions, allowing masking out these bits as if they + * were unimplemented in the ACS capability. + */ + acs_flags &= ~(PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR | + PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_DT); + + return acs_flags ? 0 : 1; +} + /* * Many Intel PCH root ports do provide ACS-like features to disable peer * transactions and validate bus numbers in requests, but do not provide an @@ -3984,6 +3997,8 @@ static const struct pci_dev_acs_enabled { { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs }, { 0x19a2, 0x710, pci_quirk_mf_endpoint_acs }, /* Emulex BE3-R */ { 0x10df, 0x720, pci_quirk_mf_endpoint_acs }, /* Emulex Skyhawk-R */ + /* Cavium ThunderX */ + { PCI_VENDOR_ID_CAVIUM, PCI_ANY_ID, pci_quirk_cavium_acs }, { 0 } }; -- cgit v1.2.3 From 7cdffeb534360609d57a39403ee951e08dcffbe7 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 00:36:37 -0300 Subject: rtc: max77686: Fix max77686_rtc_read_alarm() return value The function is always returning zero even in case of failures since the ret value was not propagated to the callers. Fix the error path. Reported-by: Krzysztof Kozlowski Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Tested-by: Krzysztof Kozlowski Acked-by: Laxman Dewangan Reviewed-by: Andi Shyti Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 7184a0eda793..6653c3d11b66 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -235,7 +235,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) out: mutex_unlock(&info->lock); - return 0; + return ret; } static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) -- cgit v1.2.3 From 862f9453bd1494f10b059076a3c97c3b90d248aa Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 00:36:38 -0300 Subject: rtc: max77686: Use ARRAY_SIZE() instead of current array length It is better to use the ARRAY_SIZE() macro instead of the array length to avoid bugs if the array is later changed and the length not updated. Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Tested-by: Krzysztof Kozlowski Reviewed-by: Andi Shyti Acked-by: Laxman Dewangan Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 6653c3d11b66..d84a50c9f7f7 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -149,7 +149,7 @@ static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm) goto out; ret = regmap_bulk_read(info->max77686->rtc_regmap, - MAX77686_RTC_SEC, data, RTC_NR_TIME); + MAX77686_RTC_SEC, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, ret); goto out; @@ -177,7 +177,7 @@ static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm) mutex_lock(&info->lock); ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_RTC_SEC, data, RTC_NR_TIME); + MAX77686_RTC_SEC, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__, ret); @@ -205,7 +205,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) goto out; ret = regmap_bulk_read(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, RTC_NR_TIME); + MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n", __func__, __LINE__, ret); @@ -215,7 +215,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) max77686_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); alrm->enabled = 0; - for (i = 0; i < RTC_NR_TIME; i++) { + for (i = 0; i < ARRAY_SIZE(data); i++) { if (data[i] & ALARM_ENABLE_MASK) { alrm->enabled = 1; break; @@ -252,7 +252,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) goto out; ret = regmap_bulk_read(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, RTC_NR_TIME); + MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", __func__, ret); @@ -261,11 +261,11 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) max77686_rtc_data_to_tm(data, &tm, info->rtc_24hr_mode); - for (i = 0; i < RTC_NR_TIME; i++) + for (i = 0; i < ARRAY_SIZE(data); i++) data[i] &= ~ALARM_ENABLE_MASK; ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, RTC_NR_TIME); + MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", __func__, ret); @@ -291,7 +291,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) goto out; ret = regmap_bulk_read(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, RTC_NR_TIME); + MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", __func__, ret); @@ -312,7 +312,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT); ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, RTC_NR_TIME); + MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", __func__, ret); @@ -341,7 +341,7 @@ static int max77686_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) goto out; ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, RTC_NR_TIME); + MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", @@ -406,7 +406,8 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info) info->rtc_24hr_mode = 1; - ret = regmap_bulk_write(info->max77686->rtc_regmap, MAX77686_RTC_CONTROLM, data, 2); + ret = regmap_bulk_write(info->max77686->rtc_regmap, + MAX77686_RTC_CONTROLM, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", __func__, ret); -- cgit v1.2.3 From 5981804b83650de558c40769fb06f76fab31724e Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 00:36:39 -0300 Subject: rtc: max77686: Use usleep_range() instead of msleep() Documentation/timers/timers-howto.txt suggest to use usleep_range() instead of msleep() for small msec (1ms - 20ms) since msleep() will often sleep for 20ms for any value in that range. This is fine in this case since 16ms is the _minimum_ delay required by max77686 for an RTC update but by using usleep_range() instead of msleep(), the driver can support other RTC IP blocks with a shorter minimum delay (i.e: in the range of usecs instead of msecs). Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Tested-by: Krzysztof Kozlowski Reviewed-by: Andi Shyti Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index d84a50c9f7f7..025a17a95da3 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -41,7 +41,7 @@ #define ALARM_ENABLE_SHIFT 7 #define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT) -#define MAX77686_RTC_UPDATE_DELAY 16 +#define MAX77686_RTC_UPDATE_DELAY 16000 enum { RTC_SEC = 0, @@ -130,7 +130,8 @@ static int max77686_rtc_update(struct max77686_rtc_info *info, __func__, ret, data); else { /* Minimum 16ms delay required before RTC update. */ - msleep(MAX77686_RTC_UPDATE_DELAY); + usleep_range(MAX77686_RTC_UPDATE_DELAY, + MAX77686_RTC_UPDATE_DELAY * 2); } return ret; -- cgit v1.2.3 From 01ea01b35120663a8ec727566e757ea6efdbd2d1 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 00:36:40 -0300 Subject: rtc: max77686: Use a driver data struct instead hard-coded values The driver has some hard-coded values such as the minimum delay needed before a RTC update or the mask used for the sec/min/hour/etc registers. Use a data structure that contains these values and pass as driver data using the platform device ID table for each device. This allows to make the driver's ops callbacks more generic so other RTC that are similar but don't have the same values can also be supported. Signed-off-by: Javier Martinez Canillas Acked-by: Laxman Dewangan Reviewed-by: Andi Shyti Tested-by: Krzysztof Kozlowski Reviewed-by: Krzysztof Kozlowski Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 51 ++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 025a17a95da3..8c4ca35029c3 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -41,8 +41,6 @@ #define ALARM_ENABLE_SHIFT 7 #define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT) -#define MAX77686_RTC_UPDATE_DELAY 16000 - enum { RTC_SEC = 0, RTC_MIN, @@ -54,6 +52,13 @@ enum { RTC_NR_TIME }; +struct max77686_rtc_driver_data { + /* Minimum usecs needed for a RTC update */ + unsigned long delay; + /* Mask used to read RTC registers value */ + u8 mask; +}; + struct max77686_rtc_info { struct device *dev; struct max77686_dev *max77686; @@ -63,6 +68,8 @@ struct max77686_rtc_info { struct regmap *regmap; + const struct max77686_rtc_driver_data *drv_data; + int virq; int rtc_24hr_mode; }; @@ -72,12 +79,19 @@ enum MAX77686_RTC_OP { MAX77686_RTC_READ, }; +static const struct max77686_rtc_driver_data max77686_drv_data = { + .delay = 16000, + .mask = 0x7f, +}; + static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, - int rtc_24hr_mode) + struct max77686_rtc_info *info) { - tm->tm_sec = data[RTC_SEC] & 0x7f; - tm->tm_min = data[RTC_MIN] & 0x7f; - if (rtc_24hr_mode) + u8 mask = info->drv_data->mask; + + tm->tm_sec = data[RTC_SEC] & mask; + tm->tm_min = data[RTC_MIN] & mask; + if (info->rtc_24hr_mode) tm->tm_hour = data[RTC_HOUR] & 0x1f; else { tm->tm_hour = data[RTC_HOUR] & 0x0f; @@ -86,10 +100,10 @@ static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, } /* Only a single bit is set in data[], so fls() would be equivalent */ - tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0x7f) - 1; + tm->tm_wday = ffs(data[RTC_WEEKDAY] & mask) - 1; tm->tm_mday = data[RTC_DATE] & 0x1f; tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; - tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100; + tm->tm_year = (data[RTC_YEAR] & mask) + 100; tm->tm_yday = 0; tm->tm_isdst = 0; } @@ -117,6 +131,7 @@ static int max77686_rtc_update(struct max77686_rtc_info *info, { int ret; unsigned int data; + unsigned long delay = info->drv_data->delay; if (op == MAX77686_RTC_WRITE) data = 1 << RTC_UDR_SHIFT; @@ -129,9 +144,8 @@ static int max77686_rtc_update(struct max77686_rtc_info *info, dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n", __func__, ret, data); else { - /* Minimum 16ms delay required before RTC update. */ - usleep_range(MAX77686_RTC_UPDATE_DELAY, - MAX77686_RTC_UPDATE_DELAY * 2); + /* Minimum delay required before RTC update. */ + usleep_range(delay, delay * 2); } return ret; @@ -156,7 +170,7 @@ static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm) goto out; } - max77686_rtc_data_to_tm(data, tm, info->rtc_24hr_mode); + max77686_rtc_data_to_tm(data, tm, info); ret = rtc_valid_tm(tm); @@ -213,7 +227,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) goto out; } - max77686_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); + max77686_rtc_data_to_tm(data, &alrm->time, info); alrm->enabled = 0; for (i = 0; i < ARRAY_SIZE(data); i++) { @@ -260,7 +274,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) goto out; } - max77686_rtc_data_to_tm(data, &tm, info->rtc_24hr_mode); + max77686_rtc_data_to_tm(data, &tm, info); for (i = 0; i < ARRAY_SIZE(data); i++) data[i] &= ~ALARM_ENABLE_MASK; @@ -299,7 +313,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) goto out; } - max77686_rtc_data_to_tm(data, &tm, info->rtc_24hr_mode); + max77686_rtc_data_to_tm(data, &tm, info); data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT); data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT); @@ -307,7 +321,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK; if (data[RTC_MONTH] & 0xf) data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT); - if (data[RTC_YEAR] & 0x7f) + if (data[RTC_YEAR] & info->drv_data->mask) data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT); if (data[RTC_DATE] & 0x1f) data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT); @@ -423,6 +437,7 @@ static int max77686_rtc_probe(struct platform_device *pdev) { struct max77686_dev *max77686 = dev_get_drvdata(pdev->dev.parent); struct max77686_rtc_info *info; + const struct platform_device_id *id = platform_get_device_id(pdev); int ret; dev_info(&pdev->dev, "%s\n", __func__); @@ -436,6 +451,8 @@ static int max77686_rtc_probe(struct platform_device *pdev) info->dev = &pdev->dev; info->max77686 = max77686; info->rtc = max77686->rtc; + info->drv_data = (const struct max77686_rtc_driver_data *) + id->driver_data; platform_set_drvdata(pdev, info); @@ -510,7 +527,7 @@ static SIMPLE_DEV_PM_OPS(max77686_rtc_pm_ops, max77686_rtc_suspend, max77686_rtc_resume); static const struct platform_device_id rtc_id[] = { - { "max77686-rtc", 0 }, + { "max77686-rtc", .driver_data = (kernel_ulong_t)&max77686_drv_data, }, {}, }; MODULE_DEVICE_TABLE(platform, rtc_id); -- cgit v1.2.3 From 90a5698a86ba968e6fbe2e03cfab9ffc18a17186 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 00:36:41 -0300 Subject: rtc: max77686: Add an indirection level to access RTC registers The max77686 driver is generic enough that can be used for other Maxim RTC IP blocks but these might not have the same registers layout so instead of accessing the registers directly, add a map to translate offsets to the real registers addresses for each IP. Signed-off-by: Javier Martinez Canillas Acked-by: Laxman Dewangan Tested-by: Krzysztof Kozlowski Reviewed-by: Krzysztof Kozlowski Reviewed-by: Andi Shyti Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 90 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 8c4ca35029c3..1f501b6fc314 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -57,6 +57,8 @@ struct max77686_rtc_driver_data { unsigned long delay; /* Mask used to read RTC registers value */ u8 mask; + /* Registers offset to I2C addresses map */ + const unsigned int *map; }; struct max77686_rtc_info { @@ -79,9 +81,69 @@ enum MAX77686_RTC_OP { MAX77686_RTC_READ, }; +/* These are not registers but just offsets that are mapped to addresses */ +enum max77686_rtc_reg_offset { + REG_RTC_CONTROLM = 0, + REG_RTC_CONTROL, + REG_RTC_UPDATE0, + REG_WTSR_SMPL_CNTL, + REG_RTC_SEC, + REG_RTC_MIN, + REG_RTC_HOUR, + REG_RTC_WEEKDAY, + REG_RTC_MONTH, + REG_RTC_YEAR, + REG_RTC_DATE, + REG_ALARM1_SEC, + REG_ALARM1_MIN, + REG_ALARM1_HOUR, + REG_ALARM1_WEEKDAY, + REG_ALARM1_MONTH, + REG_ALARM1_YEAR, + REG_ALARM1_DATE, + REG_ALARM2_SEC, + REG_ALARM2_MIN, + REG_ALARM2_HOUR, + REG_ALARM2_WEEKDAY, + REG_ALARM2_MONTH, + REG_ALARM2_YEAR, + REG_ALARM2_DATE, + REG_RTC_END, +}; + +/* Maps RTC registers offset to the MAX77686 register addresses */ +static const unsigned int max77686_map[REG_RTC_END] = { + [REG_RTC_CONTROLM] = MAX77686_RTC_CONTROLM, + [REG_RTC_CONTROL] = MAX77686_RTC_CONTROL, + [REG_RTC_UPDATE0] = MAX77686_RTC_UPDATE0, + [REG_WTSR_SMPL_CNTL] = MAX77686_WTSR_SMPL_CNTL, + [REG_RTC_SEC] = MAX77686_RTC_SEC, + [REG_RTC_MIN] = MAX77686_RTC_MIN, + [REG_RTC_HOUR] = MAX77686_RTC_HOUR, + [REG_RTC_WEEKDAY] = MAX77686_RTC_WEEKDAY, + [REG_RTC_MONTH] = MAX77686_RTC_MONTH, + [REG_RTC_YEAR] = MAX77686_RTC_YEAR, + [REG_RTC_DATE] = MAX77686_RTC_DATE, + [REG_ALARM1_SEC] = MAX77686_ALARM1_SEC, + [REG_ALARM1_MIN] = MAX77686_ALARM1_MIN, + [REG_ALARM1_HOUR] = MAX77686_ALARM1_HOUR, + [REG_ALARM1_WEEKDAY] = MAX77686_ALARM1_WEEKDAY, + [REG_ALARM1_MONTH] = MAX77686_ALARM1_MONTH, + [REG_ALARM1_YEAR] = MAX77686_ALARM1_YEAR, + [REG_ALARM1_DATE] = MAX77686_ALARM1_DATE, + [REG_ALARM2_SEC] = MAX77686_ALARM2_SEC, + [REG_ALARM2_MIN] = MAX77686_ALARM2_MIN, + [REG_ALARM2_HOUR] = MAX77686_ALARM2_HOUR, + [REG_ALARM2_WEEKDAY] = MAX77686_ALARM2_WEEKDAY, + [REG_ALARM2_MONTH] = MAX77686_ALARM2_MONTH, + [REG_ALARM2_YEAR] = MAX77686_ALARM2_YEAR, + [REG_ALARM2_DATE] = MAX77686_ALARM2_DATE, +}; + static const struct max77686_rtc_driver_data max77686_drv_data = { .delay = 16000, .mask = 0x7f, + .map = max77686_map, }; static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, @@ -139,7 +201,8 @@ static int max77686_rtc_update(struct max77686_rtc_info *info, data = 1 << RTC_RBUDR_SHIFT; ret = regmap_update_bits(info->max77686->rtc_regmap, - MAX77686_RTC_UPDATE0, data, data); + info->drv_data->map[REG_RTC_UPDATE0], + data, data); if (ret < 0) dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n", __func__, ret, data); @@ -164,7 +227,8 @@ static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm) goto out; ret = regmap_bulk_read(info->max77686->rtc_regmap, - MAX77686_RTC_SEC, data, ARRAY_SIZE(data)); + info->drv_data->map[REG_RTC_SEC], + data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, ret); goto out; @@ -192,7 +256,8 @@ static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm) mutex_lock(&info->lock); ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_RTC_SEC, data, ARRAY_SIZE(data)); + info->drv_data->map[REG_RTC_SEC], + data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__, ret); @@ -211,6 +276,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) struct max77686_rtc_info *info = dev_get_drvdata(dev); u8 data[RTC_NR_TIME]; unsigned int val; + const unsigned int *map = info->drv_data->map; int i, ret; mutex_lock(&info->lock); @@ -220,7 +286,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) goto out; ret = regmap_bulk_read(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); + map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n", __func__, __LINE__, ret); @@ -258,6 +324,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) u8 data[RTC_NR_TIME]; int ret, i; struct rtc_time tm; + const unsigned int *map = info->drv_data->map; if (!mutex_is_locked(&info->lock)) dev_warn(info->dev, "%s: should have mutex locked\n", __func__); @@ -267,7 +334,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) goto out; ret = regmap_bulk_read(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); + map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", __func__, ret); @@ -280,7 +347,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) data[i] &= ~ALARM_ENABLE_MASK; ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); + map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", __func__, ret); @@ -297,6 +364,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) u8 data[RTC_NR_TIME]; int ret; struct rtc_time tm; + const unsigned int *map = info->drv_data->map; if (!mutex_is_locked(&info->lock)) dev_warn(info->dev, "%s: should have mutex locked\n", __func__); @@ -306,7 +374,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) goto out; ret = regmap_bulk_read(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); + map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", __func__, ret); @@ -327,7 +395,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT); ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); + map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", __func__, ret); @@ -356,7 +424,8 @@ static int max77686_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) goto out; ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); + info->drv_data->map[REG_ALARM1_SEC], + data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", @@ -422,7 +491,8 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info) info->rtc_24hr_mode = 1; ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_RTC_CONTROLM, data, ARRAY_SIZE(data)); + info->drv_data->map[REG_RTC_CONTROLM], + data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", __func__, ret); -- cgit v1.2.3 From f903129b86070befa996d7bdc53d0b82b1fa09d3 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 00:36:42 -0300 Subject: rtc: max77686: Add max77802 support The MAX77686 and MAX77802 RTC IP blocks are very similar with only these differences: 0) The RTC registers layout and addresses are different. 1) The MAX77686 use 1 bit of the sec/min/hour/etc registers as the alarm enable while MAX77802 has a separate register for that. 2) The MAX77686 RTCYEAR register valid values range is 0..99 while for MAX77802 is 0..199. 3) The MAX77686 has a separate I2C address for the RTC registers while the MAX77802 uses the same I2C address as the PMIC regs. 5) The minimum delay before a RTC update (16 msecs vs 200 usecs). There are separate drivers for MAX77686 and MAX77802 RTC IP blocks but the differences are not that big so the driver can be extended to support both instead of duplicating a lot of code in 2 drivers. Suggested-by: Krzysztof Kozlowski Signed-off-by: Javier Martinez Canillas Acked-by: Laxman Dewangan Tested-by: Krzysztof Kozlowski Reviewed-by: Andi Shyti Reviewed-by: Krzysztof Kozlowski Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 196 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 156 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 1f501b6fc314..a9a4ee0f0f41 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -1,5 +1,5 @@ /* - * RTC driver for Maxim MAX77686 + * RTC driver for Maxim MAX77686 and MAX77802 * * Copyright (C) 2012 Samsung Electronics Co.Ltd * @@ -41,6 +41,15 @@ #define ALARM_ENABLE_SHIFT 7 #define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT) +#define REG_RTC_NONE 0xdeadbeef + +/* + * MAX77802 has separate register (RTCAE1) for alarm enable instead + * using 1 bit from registers RTC{SEC,MIN,HOUR,DAY,MONTH,YEAR,DATE} + * as in done in MAX77686. + */ +#define MAX77802_ALARM_ENABLE_VALUE 0x77 + enum { RTC_SEC = 0, RTC_MIN, @@ -59,6 +68,10 @@ struct max77686_rtc_driver_data { u8 mask; /* Registers offset to I2C addresses map */ const unsigned int *map; + /* Has a separate alarm enable register? */ + bool alarm_enable_reg; + /* Has a separate I2C regmap for the RTC? */ + bool separate_i2c_addr; }; struct max77686_rtc_info { @@ -108,6 +121,7 @@ enum max77686_rtc_reg_offset { REG_ALARM2_MONTH, REG_ALARM2_YEAR, REG_ALARM2_DATE, + REG_RTC_AE1, REG_RTC_END, }; @@ -138,12 +152,52 @@ static const unsigned int max77686_map[REG_RTC_END] = { [REG_ALARM2_MONTH] = MAX77686_ALARM2_MONTH, [REG_ALARM2_YEAR] = MAX77686_ALARM2_YEAR, [REG_ALARM2_DATE] = MAX77686_ALARM2_DATE, + [REG_RTC_AE1] = REG_RTC_NONE, }; static const struct max77686_rtc_driver_data max77686_drv_data = { .delay = 16000, .mask = 0x7f, .map = max77686_map, + .alarm_enable_reg = false, + .separate_i2c_addr = true, +}; + +static const unsigned int max77802_map[REG_RTC_END] = { + [REG_RTC_CONTROLM] = MAX77802_RTC_CONTROLM, + [REG_RTC_CONTROL] = MAX77802_RTC_CONTROL, + [REG_RTC_UPDATE0] = MAX77802_RTC_UPDATE0, + [REG_WTSR_SMPL_CNTL] = MAX77802_WTSR_SMPL_CNTL, + [REG_RTC_SEC] = MAX77802_RTC_SEC, + [REG_RTC_MIN] = MAX77802_RTC_MIN, + [REG_RTC_HOUR] = MAX77802_RTC_HOUR, + [REG_RTC_WEEKDAY] = MAX77802_RTC_WEEKDAY, + [REG_RTC_MONTH] = MAX77802_RTC_MONTH, + [REG_RTC_YEAR] = MAX77802_RTC_YEAR, + [REG_RTC_DATE] = MAX77802_RTC_DATE, + [REG_ALARM1_SEC] = MAX77802_ALARM1_SEC, + [REG_ALARM1_MIN] = MAX77802_ALARM1_MIN, + [REG_ALARM1_HOUR] = MAX77802_ALARM1_HOUR, + [REG_ALARM1_WEEKDAY] = MAX77802_ALARM1_WEEKDAY, + [REG_ALARM1_MONTH] = MAX77802_ALARM1_MONTH, + [REG_ALARM1_YEAR] = MAX77802_ALARM1_YEAR, + [REG_ALARM1_DATE] = MAX77802_ALARM1_DATE, + [REG_ALARM2_SEC] = MAX77802_ALARM2_SEC, + [REG_ALARM2_MIN] = MAX77802_ALARM2_MIN, + [REG_ALARM2_HOUR] = MAX77802_ALARM2_HOUR, + [REG_ALARM2_WEEKDAY] = MAX77802_ALARM2_WEEKDAY, + [REG_ALARM2_MONTH] = MAX77802_ALARM2_MONTH, + [REG_ALARM2_YEAR] = MAX77802_ALARM2_YEAR, + [REG_ALARM2_DATE] = MAX77802_ALARM2_DATE, + [REG_RTC_AE1] = MAX77802_RTC_AE1, +}; + +static const struct max77686_rtc_driver_data max77802_drv_data = { + .delay = 200, + .mask = 0xff, + .map = max77802_map, + .alarm_enable_reg = true, + .separate_i2c_addr = false, }; static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, @@ -165,12 +219,20 @@ static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, tm->tm_wday = ffs(data[RTC_WEEKDAY] & mask) - 1; tm->tm_mday = data[RTC_DATE] & 0x1f; tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; - tm->tm_year = (data[RTC_YEAR] & mask) + 100; + tm->tm_year = data[RTC_YEAR] & mask; tm->tm_yday = 0; tm->tm_isdst = 0; + + /* + * MAX77686 uses 1 bit from sec/min/hour/etc RTC registers and the + * year values are just 0..99 so add 100 to support up to 2099. + */ + if (!info->drv_data->alarm_enable_reg) + tm->tm_year += 100; } -static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data) +static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data, + struct max77686_rtc_info *info) { data[RTC_SEC] = tm->tm_sec; data[RTC_MIN] = tm->tm_min; @@ -178,6 +240,12 @@ static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data) data[RTC_WEEKDAY] = 1 << tm->tm_wday; data[RTC_DATE] = tm->tm_mday; data[RTC_MONTH] = tm->tm_mon + 1; + + if (info->drv_data->alarm_enable_reg) { + data[RTC_YEAR] = tm->tm_year; + return 0; + } + data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0; if (tm->tm_year < 100) { @@ -185,6 +253,7 @@ static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data) 1900 + tm->tm_year); return -EINVAL; } + return 0; } @@ -249,7 +318,7 @@ static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm) u8 data[RTC_NR_TIME]; int ret; - ret = max77686_rtc_tm_to_data(tm, data); + ret = max77686_rtc_tm_to_data(tm, data, info); if (ret < 0) return ret; @@ -296,10 +365,31 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) max77686_rtc_data_to_tm(data, &alrm->time, info); alrm->enabled = 0; - for (i = 0; i < ARRAY_SIZE(data); i++) { - if (data[i] & ALARM_ENABLE_MASK) { + + if (info->drv_data->alarm_enable_reg) { + if (map[REG_RTC_AE1] == REG_RTC_NONE) { + ret = -EINVAL; + dev_err(info->dev, + "alarm enable register not set(%d)\n", ret); + goto out; + } + + ret = regmap_read(info->max77686->regmap, + map[REG_RTC_AE1], &val); + if (ret < 0) { + dev_err(info->dev, + "fail to read alarm enable(%d)\n", ret); + goto out; + } + + if (val) alrm->enabled = 1; - break; + } else { + for (i = 0; i < ARRAY_SIZE(data); i++) { + if (data[i] & ALARM_ENABLE_MASK) { + alrm->enabled = 1; + break; + } } } @@ -333,21 +423,35 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) if (ret < 0) goto out; - ret = regmap_bulk_read(info->max77686->rtc_regmap, - map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); - if (ret < 0) { - dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", + if (info->drv_data->alarm_enable_reg) { + if (map[REG_RTC_AE1] == REG_RTC_NONE) { + ret = -EINVAL; + dev_err(info->dev, + "alarm enable register not set(%d)\n", ret); + goto out; + } + + ret = regmap_write(info->max77686->regmap, map[REG_RTC_AE1], 0); + } else { + ret = regmap_bulk_read(info->max77686->rtc_regmap, + map[REG_ALARM1_SEC], data, + ARRAY_SIZE(data)); + if (ret < 0) { + dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", __func__, ret); - goto out; - } + goto out; + } - max77686_rtc_data_to_tm(data, &tm, info); + max77686_rtc_data_to_tm(data, &tm, info); - for (i = 0; i < ARRAY_SIZE(data); i++) - data[i] &= ~ALARM_ENABLE_MASK; + for (i = 0; i < ARRAY_SIZE(data); i++) + data[i] &= ~ALARM_ENABLE_MASK; + + ret = regmap_bulk_write(info->max77686->rtc_regmap, + map[REG_ALARM1_SEC], data, + ARRAY_SIZE(data)); + } - ret = regmap_bulk_write(info->max77686->rtc_regmap, - map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", __func__, ret); @@ -373,29 +477,37 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) if (ret < 0) goto out; - ret = regmap_bulk_read(info->max77686->rtc_regmap, - map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); - if (ret < 0) { - dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", + if (info->drv_data->alarm_enable_reg) { + ret = regmap_write(info->max77686->regmap, map[REG_RTC_AE1], + MAX77802_ALARM_ENABLE_VALUE); + } else { + ret = regmap_bulk_read(info->max77686->rtc_regmap, + map[REG_ALARM1_SEC], data, + ARRAY_SIZE(data)); + if (ret < 0) { + dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", __func__, ret); - goto out; - } - - max77686_rtc_data_to_tm(data, &tm, info); + goto out; + } - data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT); - data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT); - data[RTC_HOUR] |= (1 << ALARM_ENABLE_SHIFT); - data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK; - if (data[RTC_MONTH] & 0xf) - data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT); - if (data[RTC_YEAR] & info->drv_data->mask) - data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT); - if (data[RTC_DATE] & 0x1f) - data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT); + max77686_rtc_data_to_tm(data, &tm, info); + + data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT); + data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT); + data[RTC_HOUR] |= (1 << ALARM_ENABLE_SHIFT); + data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK; + if (data[RTC_MONTH] & 0xf) + data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT); + if (data[RTC_YEAR] & info->drv_data->mask) + data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT); + if (data[RTC_DATE] & 0x1f) + data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT); + + ret = regmap_bulk_write(info->max77686->rtc_regmap, + map[REG_ALARM1_SEC], data, + ARRAY_SIZE(data)); + } - ret = regmap_bulk_write(info->max77686->rtc_regmap, - map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", __func__, ret); @@ -413,7 +525,7 @@ static int max77686_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) u8 data[RTC_NR_TIME]; int ret; - ret = max77686_rtc_tm_to_data(&alrm->time, data); + ret = max77686_rtc_tm_to_data(&alrm->time, data, info); if (ret < 0) return ret; @@ -524,6 +636,9 @@ static int max77686_rtc_probe(struct platform_device *pdev) info->drv_data = (const struct max77686_rtc_driver_data *) id->driver_data; + if (!info->drv_data->separate_i2c_addr) + info->max77686->rtc_regmap = info->max77686->regmap; + platform_set_drvdata(pdev, info); ret = max77686_rtc_init_reg(info); @@ -535,7 +650,7 @@ static int max77686_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); - info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77686-rtc", + info->rtc_dev = devm_rtc_device_register(&pdev->dev, id->name, &max77686_rtc_ops, THIS_MODULE); if (IS_ERR(info->rtc_dev)) { @@ -598,6 +713,7 @@ static SIMPLE_DEV_PM_OPS(max77686_rtc_pm_ops, static const struct platform_device_id rtc_id[] = { { "max77686-rtc", .driver_data = (kernel_ulong_t)&max77686_drv_data, }, + { "max77802-rtc", .driver_data = (kernel_ulong_t)&max77802_drv_data, }, {}, }; MODULE_DEVICE_TABLE(platform, rtc_id); -- cgit v1.2.3 From 1e5813bded3c6702841549ac2533680f410aea43 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 00:36:43 -0300 Subject: rtc: max77686: Fix unsupported year message The max77686 RTC only supports a range of 99 years so instead of using year 1900 as the base, the year 2000 is used. This means that 1900 to 1999 are unsupported years. The driver was printing a warning for those values but was returning a error so for consistency, print an error message instead and don't say that a year 2000 is assumed, since the year is not set. Also, it is better to use dev_* log functions instead of pr_* to print information about the device in the kernel log in a standardized way. This also allows to remove the local pr_fmt() defined macro. Suggested-by: Krzysztof Kozlowski Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Reviewed-by: Andi Shyti Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index a9a4ee0f0f41..bbb06dd2ee35 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -12,8 +12,6 @@ * */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -249,7 +247,7 @@ static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data, data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0; if (tm->tm_year < 100) { - pr_warn("RTC cannot handle the year %d. Assume it's 2000.\n", + dev_err(info->dev, "RTC cannot handle the year %d.\n", 1900 + tm->tm_year); return -EINVAL; } -- cgit v1.2.3 From fb166ba1d7f0a662f7332f4ff660a0d6f4d76915 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 4 Feb 2016 09:26:35 +0900 Subject: rtc: max77686: Properly handle regmap_irq_get_virq() error code The regmap_irq_get_virq() can return 0 or -EINVAL in error conditions but driver checked only for value of 0. This could lead to a cast of -EINVAL to an unsigned int used as a interrupt number for devm_request_threaded_irq(). Although this is not yet fatal (devm_request_threaded_irq() will just fail with -EINVAL) but might be a misleading when diagnosing errors. Signed-off-by: Krzysztof Kozlowski Fixes: 6f1c1e71d933 ("mfd: max77686: Convert to use regmap_irq") Reviewed-by: Javier Martinez Canillas Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index bbb06dd2ee35..d2d1176a1f60 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -667,7 +667,7 @@ static int max77686_rtc_probe(struct platform_device *pdev) info->virq = regmap_irq_get_virq(max77686->rtc_irq_data, MAX77686_RTCIRQ_RTCA1); - if (!info->virq) { + if (info->virq <= 0) { ret = -ENXIO; goto err_rtc; } -- cgit v1.2.3 From cd0e7c1e54af2dd4d275177cb5dea0ced398e5ef Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 00:36:44 -0300 Subject: rtc: Remove Maxim 77802 driver The max77686 RTC driver now supports the max77802 RTC as well so there's no need to have a separate driver anymore. Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Acked-by: Laxman Dewangan Reviewed-by: Andi Shyti Tested-by: Krzysztof Kozlowski Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 10 - drivers/rtc/Makefile | 1 - drivers/rtc/rtc-max77802.c | 502 --------------------------------------------- 3 files changed, 513 deletions(-) delete mode 100644 drivers/rtc/rtc-max77802.c (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 376322f71fd5..ef456d3cf265 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -335,16 +335,6 @@ config RTC_DRV_RK808 This driver can also be built as a module. If so, the module will be called rk808-rtc. -config RTC_DRV_MAX77802 - tristate "Maxim 77802 RTC" - depends on MFD_MAX77686 - help - If you say yes here you will get support for the - RTC of Maxim MAX77802 PMIC. - - This driver can also be built as a module. If so, the module - will be called rtc-max77802. - config RTC_DRV_RS5C372 tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" help diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 62d61b26ca7e..ed4519efa3ca 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -86,7 +86,6 @@ obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o -obj-$(CONFIG_RTC_DRV_MAX77802) += rtc-max77802.o obj-$(CONFIG_RTC_DRV_MAX8907) += rtc-max8907.o obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o obj-$(CONFIG_RTC_DRV_MAX8997) += rtc-max8997.o diff --git a/drivers/rtc/rtc-max77802.c b/drivers/rtc/rtc-max77802.c deleted file mode 100644 index 82ffcc5a5345..000000000000 --- a/drivers/rtc/rtc-max77802.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * RTC driver for Maxim MAX77802 - * - * Copyright (C) 2013 Google, Inc - * - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * - * based on rtc-max8997.c - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* RTC Control Register */ -#define BCD_EN_SHIFT 0 -#define BCD_EN_MASK (1 << BCD_EN_SHIFT) -#define MODEL24_SHIFT 1 -#define MODEL24_MASK (1 << MODEL24_SHIFT) -/* RTC Update Register1 */ -#define RTC_UDR_SHIFT 0 -#define RTC_UDR_MASK (1 << RTC_UDR_SHIFT) -#define RTC_RBUDR_SHIFT 4 -#define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT) -/* RTC Hour register */ -#define HOUR_PM_SHIFT 6 -#define HOUR_PM_MASK (1 << HOUR_PM_SHIFT) -/* RTC Alarm Enable */ -#define ALARM_ENABLE_SHIFT 7 -#define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT) - -/* For the RTCAE1 register, we write this value to enable the alarm */ -#define ALARM_ENABLE_VALUE 0x77 - -#define MAX77802_RTC_UPDATE_DELAY_US 200 - -enum { - RTC_SEC = 0, - RTC_MIN, - RTC_HOUR, - RTC_WEEKDAY, - RTC_MONTH, - RTC_YEAR, - RTC_DATE, - RTC_NR_TIME -}; - -struct max77802_rtc_info { - struct device *dev; - struct max77686_dev *max77802; - struct i2c_client *rtc; - struct rtc_device *rtc_dev; - struct mutex lock; - - struct regmap *regmap; - - int virq; - int rtc_24hr_mode; -}; - -enum MAX77802_RTC_OP { - MAX77802_RTC_WRITE, - MAX77802_RTC_READ, -}; - -static void max77802_rtc_data_to_tm(u8 *data, struct rtc_time *tm, - int rtc_24hr_mode) -{ - tm->tm_sec = data[RTC_SEC] & 0xff; - tm->tm_min = data[RTC_MIN] & 0xff; - if (rtc_24hr_mode) - tm->tm_hour = data[RTC_HOUR] & 0x1f; - else { - tm->tm_hour = data[RTC_HOUR] & 0x0f; - if (data[RTC_HOUR] & HOUR_PM_MASK) - tm->tm_hour += 12; - } - - /* Only a single bit is set in data[], so fls() would be equivalent */ - tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0xff) - 1; - tm->tm_mday = data[RTC_DATE] & 0x1f; - tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; - - tm->tm_year = data[RTC_YEAR] & 0xff; - tm->tm_yday = 0; - tm->tm_isdst = 0; -} - -static int max77802_rtc_tm_to_data(struct rtc_time *tm, u8 *data) -{ - data[RTC_SEC] = tm->tm_sec; - data[RTC_MIN] = tm->tm_min; - data[RTC_HOUR] = tm->tm_hour; - data[RTC_WEEKDAY] = 1 << tm->tm_wday; - data[RTC_DATE] = tm->tm_mday; - data[RTC_MONTH] = tm->tm_mon + 1; - data[RTC_YEAR] = tm->tm_year; - - return 0; -} - -static int max77802_rtc_update(struct max77802_rtc_info *info, - enum MAX77802_RTC_OP op) -{ - int ret; - unsigned int data; - - if (op == MAX77802_RTC_WRITE) - data = 1 << RTC_UDR_SHIFT; - else - data = 1 << RTC_RBUDR_SHIFT; - - ret = regmap_update_bits(info->max77802->regmap, - MAX77802_RTC_UPDATE0, data, data); - if (ret < 0) - dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n", - __func__, ret, data); - else { - /* Minimum delay required before RTC update. */ - usleep_range(MAX77802_RTC_UPDATE_DELAY_US, - MAX77802_RTC_UPDATE_DELAY_US * 2); - } - - return ret; -} - -static int max77802_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - struct max77802_rtc_info *info = dev_get_drvdata(dev); - u8 data[RTC_NR_TIME]; - int ret; - - mutex_lock(&info->lock); - - ret = max77802_rtc_update(info, MAX77802_RTC_READ); - if (ret < 0) - goto out; - - ret = regmap_bulk_read(info->max77802->regmap, - MAX77802_RTC_SEC, data, RTC_NR_TIME); - if (ret < 0) { - dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, - ret); - goto out; - } - - max77802_rtc_data_to_tm(data, tm, info->rtc_24hr_mode); - - ret = rtc_valid_tm(tm); - -out: - mutex_unlock(&info->lock); - return ret; -} - -static int max77802_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - struct max77802_rtc_info *info = dev_get_drvdata(dev); - u8 data[RTC_NR_TIME]; - int ret; - - ret = max77802_rtc_tm_to_data(tm, data); - if (ret < 0) - return ret; - - mutex_lock(&info->lock); - - ret = regmap_bulk_write(info->max77802->regmap, - MAX77802_RTC_SEC, data, RTC_NR_TIME); - if (ret < 0) { - dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__, - ret); - goto out; - } - - ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); - -out: - mutex_unlock(&info->lock); - return ret; -} - -static int max77802_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct max77802_rtc_info *info = dev_get_drvdata(dev); - u8 data[RTC_NR_TIME]; - unsigned int val; - int ret; - - mutex_lock(&info->lock); - - ret = max77802_rtc_update(info, MAX77802_RTC_READ); - if (ret < 0) - goto out; - - ret = regmap_bulk_read(info->max77802->regmap, - MAX77802_ALARM1_SEC, data, RTC_NR_TIME); - if (ret < 0) { - dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n", - __func__, __LINE__, ret); - goto out; - } - - max77802_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); - - alrm->enabled = 0; - ret = regmap_read(info->max77802->regmap, - MAX77802_RTC_AE1, &val); - if (ret < 0) { - dev_err(info->dev, "%s:%d fail to read alarm enable(%d)\n", - __func__, __LINE__, ret); - goto out; - } - if (val) - alrm->enabled = 1; - - alrm->pending = 0; - ret = regmap_read(info->max77802->regmap, MAX77802_REG_STATUS2, &val); - if (ret < 0) { - dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n", - __func__, __LINE__, ret); - goto out; - } - - if (val & (1 << 2)) /* RTCA1 */ - alrm->pending = 1; - -out: - mutex_unlock(&info->lock); - return 0; -} - -static int max77802_rtc_stop_alarm(struct max77802_rtc_info *info) -{ - int ret; - - if (!mutex_is_locked(&info->lock)) - dev_warn(info->dev, "%s: should have mutex locked\n", __func__); - - ret = max77802_rtc_update(info, MAX77802_RTC_READ); - if (ret < 0) - goto out; - - ret = regmap_write(info->max77802->regmap, - MAX77802_RTC_AE1, 0); - if (ret < 0) { - dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", - __func__, ret); - goto out; - } - - ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); -out: - return ret; -} - -static int max77802_rtc_start_alarm(struct max77802_rtc_info *info) -{ - int ret; - - if (!mutex_is_locked(&info->lock)) - dev_warn(info->dev, "%s: should have mutex locked\n", - __func__); - - ret = max77802_rtc_update(info, MAX77802_RTC_READ); - if (ret < 0) - goto out; - - ret = regmap_write(info->max77802->regmap, - MAX77802_RTC_AE1, - ALARM_ENABLE_VALUE); - - if (ret < 0) { - dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", - __func__, ret); - goto out; - } - - ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); -out: - return ret; -} - -static int max77802_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct max77802_rtc_info *info = dev_get_drvdata(dev); - u8 data[RTC_NR_TIME]; - int ret; - - ret = max77802_rtc_tm_to_data(&alrm->time, data); - if (ret < 0) - return ret; - - mutex_lock(&info->lock); - - ret = max77802_rtc_stop_alarm(info); - if (ret < 0) - goto out; - - ret = regmap_bulk_write(info->max77802->regmap, - MAX77802_ALARM1_SEC, data, RTC_NR_TIME); - - if (ret < 0) { - dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", - __func__, ret); - goto out; - } - - ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); - if (ret < 0) - goto out; - - if (alrm->enabled) - ret = max77802_rtc_start_alarm(info); -out: - mutex_unlock(&info->lock); - return ret; -} - -static int max77802_rtc_alarm_irq_enable(struct device *dev, - unsigned int enabled) -{ - struct max77802_rtc_info *info = dev_get_drvdata(dev); - int ret; - - mutex_lock(&info->lock); - if (enabled) - ret = max77802_rtc_start_alarm(info); - else - ret = max77802_rtc_stop_alarm(info); - mutex_unlock(&info->lock); - - return ret; -} - -static irqreturn_t max77802_rtc_alarm_irq(int irq, void *data) -{ - struct max77802_rtc_info *info = data; - - dev_dbg(info->dev, "%s:irq(%d)\n", __func__, irq); - - rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); - - return IRQ_HANDLED; -} - -static const struct rtc_class_ops max77802_rtc_ops = { - .read_time = max77802_rtc_read_time, - .set_time = max77802_rtc_set_time, - .read_alarm = max77802_rtc_read_alarm, - .set_alarm = max77802_rtc_set_alarm, - .alarm_irq_enable = max77802_rtc_alarm_irq_enable, -}; - -static int max77802_rtc_init_reg(struct max77802_rtc_info *info) -{ - u8 data[2]; - int ret; - - max77802_rtc_update(info, MAX77802_RTC_READ); - - /* Set RTC control register : Binary mode, 24hour mdoe */ - data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); - data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); - - info->rtc_24hr_mode = 1; - - ret = regmap_bulk_write(info->max77802->regmap, - MAX77802_RTC_CONTROLM, data, ARRAY_SIZE(data)); - if (ret < 0) { - dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", - __func__, ret); - return ret; - } - - ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); - return ret; -} - -static int max77802_rtc_probe(struct platform_device *pdev) -{ - struct max77686_dev *max77802 = dev_get_drvdata(pdev->dev.parent); - struct max77802_rtc_info *info; - int ret; - - dev_dbg(&pdev->dev, "%s\n", __func__); - - info = devm_kzalloc(&pdev->dev, sizeof(struct max77802_rtc_info), - GFP_KERNEL); - if (!info) - return -ENOMEM; - - mutex_init(&info->lock); - info->dev = &pdev->dev; - info->max77802 = max77802; - info->rtc = max77802->i2c; - - platform_set_drvdata(pdev, info); - - ret = max77802_rtc_init_reg(info); - - if (ret < 0) { - dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret); - return ret; - } - - device_init_wakeup(&pdev->dev, 1); - - info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77802-rtc", - &max77802_rtc_ops, THIS_MODULE); - - if (IS_ERR(info->rtc_dev)) { - ret = PTR_ERR(info->rtc_dev); - dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); - if (ret == 0) - ret = -EINVAL; - return ret; - } - - if (!max77802->rtc_irq_data) { - dev_err(&pdev->dev, "No RTC regmap IRQ chip\n"); - return -EINVAL; - } - - info->virq = regmap_irq_get_virq(max77802->rtc_irq_data, - MAX77686_RTCIRQ_RTCA1); - - if (info->virq <= 0) { - dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n", - MAX77686_RTCIRQ_RTCA1); - return -EINVAL; - } - - ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL, - max77802_rtc_alarm_irq, 0, "rtc-alarm1", - info); - if (ret < 0) - dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", - info->virq, ret); - - return ret; -} - -#ifdef CONFIG_PM_SLEEP -static int max77802_rtc_suspend(struct device *dev) -{ - if (device_may_wakeup(dev)) { - struct max77802_rtc_info *info = dev_get_drvdata(dev); - - return enable_irq_wake(info->virq); - } - - return 0; -} - -static int max77802_rtc_resume(struct device *dev) -{ - if (device_may_wakeup(dev)) { - struct max77802_rtc_info *info = dev_get_drvdata(dev); - - return disable_irq_wake(info->virq); - } - - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(max77802_rtc_pm_ops, - max77802_rtc_suspend, max77802_rtc_resume); - -static const struct platform_device_id rtc_id[] = { - { "max77802-rtc", 0 }, - {}, -}; -MODULE_DEVICE_TABLE(platform, rtc_id); - -static struct platform_driver max77802_rtc_driver = { - .driver = { - .name = "max77802-rtc", - .pm = &max77802_rtc_pm_ops, - }, - .probe = max77802_rtc_probe, - .id_table = rtc_id, -}; - -module_platform_driver(max77802_rtc_driver); - -MODULE_DESCRIPTION("Maxim MAX77802 RTC driver"); -MODULE_AUTHOR("Simon Glass "); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From bf035f42344a3e790c2d37ed3ee9005311f98075 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Jan 2016 15:46:11 +0900 Subject: rtc: max77686: Cleanup and reduce dmesg output Cleanup of entire driver of its dmesg output: 1. Remove printing of the function name, because printing device name is sufficient. This also makes the dev_err()-like functions more compact and readable (not need of line break). 2. Lower from info to debug printing of each RTC interrupt (no need to make noise on each alarm). 3. Remove dev_info() at beginning of probe because a message is already always printed by either probe failure or from registering the RTC device as /dev/rtcX. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index d2d1176a1f60..0f2965d912ae 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -271,8 +271,8 @@ static int max77686_rtc_update(struct max77686_rtc_info *info, info->drv_data->map[REG_RTC_UPDATE0], data, data); if (ret < 0) - dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n", - __func__, ret, data); + dev_err(info->dev, "Fail to write update reg(ret=%d, data=0x%x)\n", + ret, data); else { /* Minimum delay required before RTC update. */ usleep_range(delay, delay * 2); @@ -297,7 +297,7 @@ static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm) info->drv_data->map[REG_RTC_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { - dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, ret); + dev_err(info->dev, "Fail to read time reg(%d)\n", ret); goto out; } @@ -326,8 +326,7 @@ static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm) info->drv_data->map[REG_RTC_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { - dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__, - ret); + dev_err(info->dev, "Fail to write time reg(%d)\n", ret); goto out; } @@ -355,8 +354,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) ret = regmap_bulk_read(info->max77686->rtc_regmap, map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { - dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n", - __func__, __LINE__, ret); + dev_err(info->dev, "Fail to read alarm reg(%d)\n", ret); goto out; } @@ -394,8 +392,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) alrm->pending = 0; ret = regmap_read(info->max77686->regmap, MAX77686_REG_STATUS2, &val); if (ret < 0) { - dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n", - __func__, __LINE__, ret); + dev_err(info->dev, "Fail to read status2 reg(%d)\n", ret); goto out; } @@ -435,8 +432,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { - dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", - __func__, ret); + dev_err(info->dev, "Fail to read alarm reg(%d)\n", ret); goto out; } @@ -451,8 +447,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) } if (ret < 0) { - dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", - __func__, ret); + dev_err(info->dev, "Fail to write alarm reg(%d)\n", ret); goto out; } @@ -483,8 +478,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { - dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", - __func__, ret); + dev_err(info->dev, "Fail to read alarm reg(%d)\n", ret); goto out; } @@ -507,8 +501,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) } if (ret < 0) { - dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", - __func__, ret); + dev_err(info->dev, "Fail to write alarm reg(%d)\n", ret); goto out; } @@ -538,8 +531,7 @@ static int max77686_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) data, ARRAY_SIZE(data)); if (ret < 0) { - dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", - __func__, ret); + dev_err(info->dev, "Fail to write alarm reg(%d)\n", ret); goto out; } @@ -574,7 +566,7 @@ static irqreturn_t max77686_rtc_alarm_irq(int irq, void *data) { struct max77686_rtc_info *info = data; - dev_info(info->dev, "%s:irq(%d)\n", __func__, irq); + dev_dbg(info->dev, "RTC alarm IRQ: %d\n", irq); rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); @@ -604,8 +596,7 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info) info->drv_data->map[REG_RTC_CONTROLM], data, ARRAY_SIZE(data)); if (ret < 0) { - dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", - __func__, ret); + dev_err(info->dev, "Fail to write controlm reg(%d)\n", ret); return ret; } @@ -620,8 +611,6 @@ static int max77686_rtc_probe(struct platform_device *pdev) const struct platform_device_id *id = platform_get_device_id(pdev); int ret; - dev_info(&pdev->dev, "%s\n", __func__); - info = devm_kzalloc(&pdev->dev, sizeof(struct max77686_rtc_info), GFP_KERNEL); if (!info) @@ -661,7 +650,7 @@ static int max77686_rtc_probe(struct platform_device *pdev) if (!max77686->rtc_irq_data) { ret = -EINVAL; - dev_err(&pdev->dev, "%s: no RTC regmap IRQ chip\n", __func__); + dev_err(&pdev->dev, "No RTC regmap IRQ chip\n"); goto err_rtc; } -- cgit v1.2.3 From 54dd1c4c2979d1ad127d0e615fdd0f5016a5d713 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 23 Dec 2015 20:54:33 +0800 Subject: rtc: ds1305: use to_spi_device and kobj_to_dev For better readability, use to_spi_device() and kobj_to_dev() instead of container_of(). Signed-off-by: Geliang Tang Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1305.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index f39691eea736..8e41c4613e51 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -532,7 +532,7 @@ ds1305_nvram_read(struct file *filp, struct kobject *kobj, struct spi_transfer x[2]; int status; - spi = container_of(kobj, struct spi_device, dev.kobj); + spi = to_spi_device(kobj_to_dev(kobj)); addr = DS1305_NVRAM + off; msg_init(&m, x, &addr, count, NULL, buf); @@ -554,7 +554,7 @@ ds1305_nvram_write(struct file *filp, struct kobject *kobj, struct spi_transfer x[2]; int status; - spi = container_of(kobj, struct spi_device, dev.kobj); + spi = to_spi_device(kobj_to_dev(kobj)); addr = (DS1305_WRITE | DS1305_NVRAM) + off; msg_init(&m, x, &addr, count, buf, NULL); -- cgit v1.2.3 From aaa3cee5deffa28415a6e1852c5afae0f5d210e2 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 21 Jan 2016 13:24:21 +0100 Subject: rtc: rx8025: remove rv8803 id The rv8803 has its own driver that should be used. Remove its id from the rx8025 driver. Fixes: b1f9d790b59dc04f8813a49a92ddd8651770ffee Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx8025.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index bd911bafb809..17341feadad1 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c @@ -65,7 +65,6 @@ static const struct i2c_device_id rx8025_id[] = { { "rx8025", 0 }, - { "rv8803", 1 }, { } }; MODULE_DEVICE_TABLE(i2c, rx8025_id); -- cgit v1.2.3 From 04d3ba70a3c9c9ba593d3208531463c65f055526 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 17:04:46 +0100 Subject: rtc: mt6397: add IRQ domain dependency The mt6397 RTC driver can be built either when the MFD_MT6397 driver is enabled (which selects IRQ_DOMAIN), or when compile testing. The latter however fails without IRQ domains: drivers/rtc/rtc-mt6397.c: In function 'mtk_rtc_probe': drivers/rtc/rtc-mt6397.c:326:13: error: implicit declaration of function 'irq_create_mapping' [-Werror=implicit-function-declaration] rtc->irq = irq_create_mapping(mt6397_chip->irq_domain, res->start); This adds an explicit dependency for the COMPILE_TEST case. Signed-off-by: Arnd Bergmann Acked-by: Eddie Huang Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index ef456d3cf265..27f6ac46c596 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1593,7 +1593,7 @@ config RTC_DRV_MOXART config RTC_DRV_MT6397 tristate "Mediatek Real Time Clock driver" - depends on MFD_MT6397 || COMPILE_TEST + depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN) help This selects the Mediatek(R) RTC driver. RTC is part of Mediatek MT6397 PMIC. You should enable MT6397 PMIC MFD before select -- cgit v1.2.3 From 8bc2a40730ec74271a0573a6882871308d069f5d Mon Sep 17 00:00:00 2001 From: Michael Lange Date: Thu, 21 Jan 2016 18:10:16 +0100 Subject: rtc: ds1307: add support for the DT property 'wakeup-source' For RTC chips with no IRQ directly connected to the SoC, the RTC chip can be forced as a wakeup source by stating that explicitly in the device's .dts file using the "wakeup-source" boolean property. This will guarantee the 'wakealarm' sysfs entry is available on the device, if supported by the RTC. With these changes to the driver rtc-ds1307 and the necessary entries in the .dts file, I get an working ds1337 RTC on the Witty Pi extension board by UUGear for the Raspberry Pi. An example for the entry in the .dts file: rtc: ds1337@68 { compatible = "dallas,ds1337"; reg = <0x68>; wakeup-source; If the "wakeup-source" property is set, do not request an IRQ. Set also UIE mode to unsupported, to get a working 'hwclock' binary. Signed-off-by: Michael Lange Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1307.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index cf685f67b391..bfedeb543bfd 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -851,6 +851,7 @@ static int ds1307_probe(struct i2c_client *client, struct chip_desc *chip = &chips[id->driver_data]; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); bool want_irq = false; + bool ds1307_can_wakeup_device = false; unsigned char *buf; struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev); irq_handler_t irq_handler = ds1307_irq; @@ -898,6 +899,20 @@ static int ds1307_probe(struct i2c_client *client, ds1307->write_block_data = ds1307_write_block_data; } +#ifdef CONFIG_OF +/* + * For devices with no IRQ directly connected to the SoC, the RTC chip + * can be forced as a wakeup source by stating that explicitly in + * the device's .dts file using the "wakeup-source" boolean property. + * If the "wakeup-source" property is set, don't request an IRQ. + * This will guarantee the 'wakealarm' sysfs entry is available on the device, + * if supported by the RTC. + */ + if (of_property_read_bool(client->dev.of_node, "wakeup-source")) { + ds1307_can_wakeup_device = true; + } +#endif + switch (ds1307->type) { case ds_1337: case ds_1339: @@ -916,11 +931,13 @@ static int ds1307_probe(struct i2c_client *client, ds1307->regs[0] &= ~DS1337_BIT_nEOSC; /* - * Using IRQ? Disable the square wave and both alarms. + * Using IRQ or defined as wakeup-source? + * Disable the square wave and both alarms. * For some variants, be sure alarms can trigger when we're * running on Vbackup (BBSQI/BBSQW) */ - if (ds1307->client->irq > 0 && chip->alarm) { + if (chip->alarm && (ds1307->client->irq > 0 || + ds1307_can_wakeup_device)) { ds1307->regs[0] |= DS1337_BIT_INTCN | bbsqi_bitpos[ds1307->type]; ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE); @@ -1135,6 +1152,14 @@ read_rtc: return PTR_ERR(ds1307->rtc); } + if (ds1307_can_wakeup_device) { + /* Disable request for an IRQ */ + want_irq = false; + dev_info(&client->dev, "'wakeup-source' is set, request for an IRQ is disabled!\n"); + /* We cannot support UIE mode if we do not have an IRQ line */ + ds1307->rtc->uie_unsupported = 1; + } + if (want_irq) { err = devm_request_threaded_irq(&client->dev, client->irq, NULL, irq_handler, -- cgit v1.2.3 From 445c02076f1e60d2ee51503bf1288ef9f3bc8809 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 25 Jan 2016 00:22:16 +0900 Subject: rtc: ds1307: add temperature sensor support for ds3231 DS3231 has the temperature registers with a resolution of 0.25 degree celsius. This enables to get the value through hwmon. # cat /sys/class/i2c-adapter/i2c-2/2-0068/hwmon/hwmon0/temp1_input 21000 Signed-off-by: Akinobu Mita Acked-by: Guenter Roeck Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 9 +++++ drivers/rtc/rtc-ds1307.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 27f6ac46c596..d47ad96132bf 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -212,6 +212,15 @@ config RTC_DRV_DS1307 This driver can also be built as a module. If so, the module will be called rtc-ds1307. +config RTC_DRV_DS1307_HWMON + bool "HWMON support for rtc-ds1307" + depends on RTC_DRV_DS1307 && HWMON + depends on !(RTC_DRV_DS1307=y && HWMON=m) + default y + help + Say Y here if you want to expose temperature sensor data on + rtc-ds1307 (only DS3231) + config RTC_DRV_DS1374 tristate "Dallas/Maxim DS1374" help diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index bfedeb543bfd..2462d5a53a53 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include /* * We can't determine type by probing, but if we expect pre-Linux code @@ -842,6 +844,90 @@ out: return; } +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_RTC_DRV_DS1307_HWMON + +/* + * Temperature sensor support for ds3231 devices. + */ + +#define DS3231_REG_TEMPERATURE 0x11 + +/* + * A user-initiated temperature conversion is not started by this function, + * so the temperature is updated once every 64 seconds. + */ +static int ds3231_hwmon_read_temp(struct device *dev, s16 *mC) +{ + struct ds1307 *ds1307 = dev_get_drvdata(dev); + u8 temp_buf[2]; + s16 temp; + int ret; + + ret = ds1307->read_block_data(ds1307->client, DS3231_REG_TEMPERATURE, + sizeof(temp_buf), temp_buf); + if (ret < 0) + return ret; + if (ret != sizeof(temp_buf)) + return -EIO; + + /* + * Temperature is represented as a 10-bit code with a resolution of + * 0.25 degree celsius and encoded in two's complement format. + */ + temp = (temp_buf[0] << 8) | temp_buf[1]; + temp >>= 6; + *mC = temp * 250; + + return 0; +} + +static ssize_t ds3231_hwmon_show_temp(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + s16 temp; + + ret = ds3231_hwmon_read_temp(dev, &temp); + if (ret) + return ret; + + return sprintf(buf, "%d\n", temp); +} +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ds3231_hwmon_show_temp, + NULL, 0); + +static struct attribute *ds3231_hwmon_attrs[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + NULL, +}; +ATTRIBUTE_GROUPS(ds3231_hwmon); + +static void ds1307_hwmon_register(struct ds1307 *ds1307) +{ + struct device *dev; + + if (ds1307->type != ds_3231) + return; + + dev = devm_hwmon_device_register_with_groups(&ds1307->client->dev, + ds1307->client->name, + ds1307, ds3231_hwmon_groups); + if (IS_ERR(dev)) { + dev_warn(&ds1307->client->dev, + "unable to register hwmon device %ld\n", PTR_ERR(dev)); + } +} + +#else + +static void ds1307_hwmon_register(struct ds1307 *ds1307) +{ +} + +#endif + static int ds1307_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1207,6 +1293,8 @@ read_rtc: } } + ds1307_hwmon_register(ds1307); + return 0; exit: -- cgit v1.2.3 From 296d48568042360d0e2a6e6e91b0130acb5ca738 Mon Sep 17 00:00:00 2001 From: Mahesh Bandewar Date: Wed, 27 Jan 2016 23:33:28 -0800 Subject: ipvlan: inherit MTU from master device When we create IPvlan slave; we use ether_setup() and that sets up default MTU to 1500 while the master device may have lower / different MTU. Any subsequent changes to the masters' MTU are reflected into the slaves' MTU setting. However if those don't happen (most likely scenario), the slaves' MTU stays at 1500 which could be bad. This change adds code to inherit MTU from the master device instead of using the default value during the link initialization phase. Signed-off-by: Mahesh Bandewar CC: Eric Dumazet CC: Tim Hockins Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index f94392d07126..7a3b41468a55 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -468,6 +468,7 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev, ipvlan->dev = dev; ipvlan->port = port; ipvlan->sfeatures = IPVLAN_FEATURES; + ipvlan_adjust_mtu(ipvlan, phy_dev); INIT_LIST_HEAD(&ipvlan->addrs); /* TODO Probably put random address here to be presented to the -- cgit v1.2.3 From 89140fdaf11aec81e93d5590a993720f2ef0d26e Mon Sep 17 00:00:00 2001 From: Joe Lawrence Date: Wed, 3 Feb 2016 12:51:12 -0500 Subject: xhci: harden xhci_find_next_ext_cap against device removal xhci_find_next_ext_cap doesn't check for PCI hotplug removal and may use the PCI master abort bit pattern (~0) to calculate a new PCI address offset to read/write. The has lead to reproducable crashes when testing surprise removal during device initialization on a Stratus platform, at least after commit d5ddcdf4d672 ("xhci: rework xhci extended capability list parsing functions"). The crash is repeatable on a Stratus platform when injecting hardware faults to induce xHCI host controller hotplug during driver initialization. If a PCI read in xhci_find_next_ext_cap returns the master abort pattern, quirk_usb_handoff_xhci may start using a bogus ext_cap_offset to start searching more bogus PCI addresses. Signed-off-by: Joe Lawrence Acked-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ext-caps.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h index 04ce6b156b35..e0244fb3903d 100644 --- a/drivers/usb/host/xhci-ext-caps.h +++ b/drivers/usb/host/xhci-ext-caps.h @@ -112,12 +112,16 @@ static inline int xhci_find_next_ext_cap(void __iomem *base, u32 start, int id) offset = start; if (!start || start == XHCI_HCC_PARAMS_OFFSET) { val = readl(base + XHCI_HCC_PARAMS_OFFSET); + if (val == ~0) + return 0; offset = XHCI_HCC_EXT_CAPS(val) << 2; if (!offset) return 0; }; do { val = readl(base + offset); + if (val == ~0) + return 0; if (XHCI_EXT_CAPS_ID(val) == id && offset != start) return offset; -- cgit v1.2.3 From de1df26b7cef702a32ae876ed45c1112f523df48 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 5 Feb 2016 02:37:42 +0100 Subject: cpufreq: Clean up default and fallback governor setup The preprocessor magic used for setting the default cpufreq governor (and for using the performance governor as a fallback one for that matter) is really nasty, so replace it with __weak functions and overrides. Signed-off-by: Rafael J. Wysocki Acked-by: Saravana Kannan Acked-by: Viresh Kumar --- drivers/cpufreq/cpufreq.c | 37 +++++++++++++++++++--------------- drivers/cpufreq/cpufreq_conservative.c | 10 +++++---- drivers/cpufreq/cpufreq_ondemand.c | 36 ++++++++++++++++----------------- drivers/cpufreq/cpufreq_performance.c | 18 +++++++++++++---- drivers/cpufreq/cpufreq_powersave.c | 10 +++++---- drivers/cpufreq/cpufreq_userspace.c | 10 +++++---- include/linux/cpufreq.h | 25 ++--------------------- 7 files changed, 73 insertions(+), 73 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index e979ec78b695..34b17447e0d1 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -959,6 +959,11 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy) return cpufreq_add_dev_symlink(policy); } +__weak struct cpufreq_governor *cpufreq_default_governor(void) +{ + return NULL; +} + static int cpufreq_init_policy(struct cpufreq_policy *policy) { struct cpufreq_governor *gov = NULL; @@ -968,11 +973,14 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy) /* Update governor of new_policy to the governor used before hotplug */ gov = find_governor(policy->last_governor); - if (gov) + if (gov) { pr_debug("Restoring governor %s for cpu %d\n", policy->governor->name, policy->cpu); - else - gov = CPUFREQ_DEFAULT_GOVERNOR; + } else { + gov = cpufreq_default_governor(); + if (!gov) + return -ENODATA; + } new_policy.governor = gov; @@ -1920,21 +1928,16 @@ int cpufreq_driver_target(struct cpufreq_policy *policy, } EXPORT_SYMBOL_GPL(cpufreq_driver_target); +__weak struct cpufreq_governor *cpufreq_fallback_governor(void) +{ + return NULL; +} + static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) { int ret; - /* Only must be defined when default governor is known to have latency - restrictions, like e.g. conservative or ondemand. - That this is the case is already ensured in Kconfig - */ -#ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE - struct cpufreq_governor *gov = &cpufreq_gov_performance; -#else - struct cpufreq_governor *gov = NULL; -#endif - /* Don't start any governor operations if we are entering suspend */ if (cpufreq_suspended) return 0; @@ -1948,12 +1951,14 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, if (policy->governor->max_transition_latency && policy->cpuinfo.transition_latency > policy->governor->max_transition_latency) { - if (!gov) - return -EINVAL; - else { + struct cpufreq_governor *gov = cpufreq_fallback_governor(); + + if (gov) { pr_warn("%s governor failed, too long transition latency of HW, fallback to %s governor\n", policy->governor->name, gov->name); policy->governor = gov; + } else { + return -EINVAL; } } diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 606ad74abe6e..8504a70a4785 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -26,10 +26,7 @@ static DEFINE_PER_CPU(struct cs_cpu_dbs_info_s, cs_cpu_dbs_info); static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event); -#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE -static -#endif -struct cpufreq_governor cpufreq_gov_conservative = { +static struct cpufreq_governor cpufreq_gov_conservative = { .name = "conservative", .governor = cs_cpufreq_governor_dbs, .max_transition_latency = TRANSITION_LATENCY_LIMIT, @@ -399,6 +396,11 @@ MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for " MODULE_LICENSE("GPL"); #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE +struct cpufreq_governor *cpufreq_default_governor(void) +{ + return &cpufreq_gov_conservative; +} + fs_initcall(cpufreq_gov_dbs_init); #else module_init(cpufreq_gov_dbs_init); diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index eae51070c034..929e193ac1c1 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -31,9 +31,7 @@ static DEFINE_PER_CPU(struct od_cpu_dbs_info_s, od_cpu_dbs_info); static struct od_ops od_ops; -#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND static struct cpufreq_governor cpufreq_gov_ondemand; -#endif static unsigned int default_powersave_bias; @@ -554,6 +552,19 @@ static struct common_dbs_data od_dbs_cdata = { .mutex = __MUTEX_INITIALIZER(od_dbs_cdata.mutex), }; +static int od_cpufreq_governor_dbs(struct cpufreq_policy *policy, + unsigned int event) +{ + return cpufreq_governor_dbs(policy, &od_dbs_cdata, event); +} + +static struct cpufreq_governor cpufreq_gov_ondemand = { + .name = "ondemand", + .governor = od_cpufreq_governor_dbs, + .max_transition_latency = TRANSITION_LATENCY_LIMIT, + .owner = THIS_MODULE, +}; + static void od_set_powersave_bias(unsigned int powersave_bias) { struct cpufreq_policy *policy; @@ -605,22 +616,6 @@ void od_unregister_powersave_bias_handler(void) } EXPORT_SYMBOL_GPL(od_unregister_powersave_bias_handler); -static int od_cpufreq_governor_dbs(struct cpufreq_policy *policy, - unsigned int event) -{ - return cpufreq_governor_dbs(policy, &od_dbs_cdata, event); -} - -#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND -static -#endif -struct cpufreq_governor cpufreq_gov_ondemand = { - .name = "ondemand", - .governor = od_cpufreq_governor_dbs, - .max_transition_latency = TRANSITION_LATENCY_LIMIT, - .owner = THIS_MODULE, -}; - static int __init cpufreq_gov_dbs_init(void) { return cpufreq_register_governor(&cpufreq_gov_ondemand); @@ -638,6 +633,11 @@ MODULE_DESCRIPTION("'cpufreq_ondemand' - A dynamic cpufreq governor for " MODULE_LICENSE("GPL"); #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND +struct cpufreq_governor *cpufreq_default_governor(void) +{ + return &cpufreq_gov_ondemand; +} + fs_initcall(cpufreq_gov_dbs_init); #else module_init(cpufreq_gov_dbs_init); diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c index cf117deb39b1..af9f4b96f5a8 100644 --- a/drivers/cpufreq/cpufreq_performance.c +++ b/drivers/cpufreq/cpufreq_performance.c @@ -33,10 +33,7 @@ static int cpufreq_governor_performance(struct cpufreq_policy *policy, return 0; } -#ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE_MODULE -static -#endif -struct cpufreq_governor cpufreq_gov_performance = { +static struct cpufreq_governor cpufreq_gov_performance = { .name = "performance", .governor = cpufreq_governor_performance, .owner = THIS_MODULE, @@ -52,6 +49,19 @@ static void __exit cpufreq_gov_performance_exit(void) cpufreq_unregister_governor(&cpufreq_gov_performance); } +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE +struct cpufreq_governor *cpufreq_default_governor(void) +{ + return &cpufreq_gov_performance; +} +#endif +#ifndef CONFIG_CPU_FREQ_GOV_PERFORMANCE_MODULE +struct cpufreq_governor *cpufreq_fallback_governor(void) +{ + return &cpufreq_gov_performance; +} +#endif + MODULE_AUTHOR("Dominik Brodowski "); MODULE_DESCRIPTION("CPUfreq policy governor 'performance'"); MODULE_LICENSE("GPL"); diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c index e3b874c235ea..b8b400232a74 100644 --- a/drivers/cpufreq/cpufreq_powersave.c +++ b/drivers/cpufreq/cpufreq_powersave.c @@ -33,10 +33,7 @@ static int cpufreq_governor_powersave(struct cpufreq_policy *policy, return 0; } -#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE -static -#endif -struct cpufreq_governor cpufreq_gov_powersave = { +static struct cpufreq_governor cpufreq_gov_powersave = { .name = "powersave", .governor = cpufreq_governor_powersave, .owner = THIS_MODULE, @@ -57,6 +54,11 @@ MODULE_DESCRIPTION("CPUfreq policy governor 'powersave'"); MODULE_LICENSE("GPL"); #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE +struct cpufreq_governor *cpufreq_default_governor(void) +{ + return &cpufreq_gov_powersave; +} + fs_initcall(cpufreq_gov_powersave_init); #else module_init(cpufreq_gov_powersave_init); diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c index 4dbf1db16aca..4d16f45ee1da 100644 --- a/drivers/cpufreq/cpufreq_userspace.c +++ b/drivers/cpufreq/cpufreq_userspace.c @@ -89,10 +89,7 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, return rc; } -#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE -static -#endif -struct cpufreq_governor cpufreq_gov_userspace = { +static struct cpufreq_governor cpufreq_gov_userspace = { .name = "userspace", .governor = cpufreq_governor_userspace, .store_setspeed = cpufreq_set, @@ -116,6 +113,11 @@ MODULE_DESCRIPTION("CPUfreq policy governor 'userspace'"); MODULE_LICENSE("GPL"); #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE +struct cpufreq_governor *cpufreq_default_governor(void) +{ + return &cpufreq_gov_userspace; +} + fs_initcall(cpufreq_gov_userspace_init); #else module_init(cpufreq_gov_userspace_init); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 88a4215125bc..d0bf555b6bbf 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -464,29 +464,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, int cpufreq_register_governor(struct cpufreq_governor *governor); void cpufreq_unregister_governor(struct cpufreq_governor *governor); -/* CPUFREQ DEFAULT GOVERNOR */ -/* - * Performance governor is fallback governor if any other gov failed to auto - * load due latency restrictions - */ -#ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE -extern struct cpufreq_governor cpufreq_gov_performance; -#endif -#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE -#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_performance) -#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE) -extern struct cpufreq_governor cpufreq_gov_powersave; -#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_powersave) -#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE) -extern struct cpufreq_governor cpufreq_gov_userspace; -#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_userspace) -#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND) -extern struct cpufreq_governor cpufreq_gov_ondemand; -#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_ondemand) -#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE) -extern struct cpufreq_governor cpufreq_gov_conservative; -#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_conservative) -#endif +struct cpufreq_governor *cpufreq_default_governor(void); +struct cpufreq_governor *cpufreq_fallback_governor(void); /********************************************************************* * FREQUENCY TABLE HELPERS * -- cgit v1.2.3 From 86622cb8c57abb05fe95bea3a068949c0ca79fc3 Mon Sep 17 00:00:00 2001 From: Shilpasri G Bhat Date: Wed, 3 Feb 2016 01:11:37 +0530 Subject: cpufreq: powernv: Free 'chips' on module exit This will free the dynamically allocated memory of 'chips' on module exit. Signed-off-by: Shilpasri G Bhat Reviewed-by: Gautham R. Shenoy Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/powernv-cpufreq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index 547890fd9572..53f980bf9b77 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -612,6 +612,7 @@ static void __exit powernv_cpufreq_exit(void) unregister_reboot_notifier(&powernv_cpufreq_reboot_nb); opal_message_notifier_unregister(OPAL_MSG_OCC, &powernv_cpufreq_opal_nb); + kfree(chips); cpufreq_unregister_driver(&powernv_cpufreq_driver); } module_exit(powernv_cpufreq_exit); -- cgit v1.2.3 From 6d167a44e6c8da3316e037b788585fcf96112bea Mon Sep 17 00:00:00 2001 From: Shilpasri G Bhat Date: Wed, 3 Feb 2016 01:11:38 +0530 Subject: cpufreq: powernv: Hot-plug safe the kworker thread In the kworker_thread powernv_cpufreq_work_fn(), we can end up sending an IPI to a cpu going offline. This is a rare corner case which is fixed using {get/put}_online_cpus(). Along with this fix, this patch adds changes to do oneshot cpumask_{clear/and} operation. Suggested-by: Shreyas B Prabhu Suggested-by: Gautham R Shenoy Signed-off-by: Shilpasri G Bhat Reviewed-by: Gautham R. Shenoy Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/powernv-cpufreq.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index 53f980bf9b77..a271b0fbe8b9 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -423,18 +424,19 @@ void powernv_cpufreq_work_fn(struct work_struct *work) { struct chip *chip = container_of(work, struct chip, throttle); unsigned int cpu; - cpumask_var_t mask; + cpumask_t mask; - smp_call_function_any(&chip->mask, + get_online_cpus(); + cpumask_and(&mask, &chip->mask, cpu_online_mask); + smp_call_function_any(&mask, powernv_cpufreq_throttle_check, NULL, 0); if (!chip->restore) - return; + goto out; chip->restore = false; - cpumask_copy(mask, &chip->mask); - for_each_cpu_and(cpu, mask, cpu_online_mask) { - int index, tcpu; + for_each_cpu(cpu, &mask) { + int index; struct cpufreq_policy policy; cpufreq_get_policy(&policy, cpu); @@ -442,9 +444,10 @@ void powernv_cpufreq_work_fn(struct work_struct *work) policy.cur, CPUFREQ_RELATION_C, &index); powernv_cpufreq_target_index(&policy, index); - for_each_cpu(tcpu, policy.cpus) - cpumask_clear_cpu(tcpu, mask); + cpumask_andnot(&mask, &mask, policy.cpus); } +out: + put_online_cpus(); } static char throttle_reason[][30] = { -- cgit v1.2.3 From 96c4726f01cdbf53acf74cf2394e287d74bf40a3 Mon Sep 17 00:00:00 2001 From: Shilpasri G Bhat Date: Wed, 3 Feb 2016 01:11:39 +0530 Subject: cpufreq: powernv: Remove cpu_to_chip_id() from hot-path cpu_to_chip_id() does a DT walk through to find out the chip id by taking a contended device tree lock. This adds an unnecessary overhead in a hot path. So instead of calling cpu_to_chip_id() everytime cache the chip ids for all cores in the array 'core_to_chip_map' and use it in the hotpath. Reported-by: Anton Blanchard Signed-off-by: Shilpasri G Bhat Reviewed-by: Gautham R. Shenoy Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/powernv-cpufreq.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index a271b0fbe8b9..c670314053af 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -43,6 +43,7 @@ static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1]; static bool rebooting, throttled, occ_reset; +static unsigned int *core_to_chip_map; static struct chip { unsigned int id; @@ -313,13 +314,14 @@ static inline unsigned int get_nominal_index(void) static void powernv_cpufreq_throttle_check(void *data) { unsigned int cpu = smp_processor_id(); + unsigned int chip_id = core_to_chip_map[cpu_core_index_of_thread(cpu)]; unsigned long pmsr; int pmsr_pmax, i; pmsr = get_pmspr(SPRN_PMSR); for (i = 0; i < nr_chips; i++) - if (chips[i].id == cpu_to_chip_id(cpu)) + if (chips[i].id == chip_id) break; /* Check for Pmax Capping */ @@ -559,19 +561,29 @@ static int init_chip_info(void) unsigned int chip[256]; unsigned int cpu, i; unsigned int prev_chip_id = UINT_MAX; + cpumask_t cpu_mask; + int ret = -ENOMEM; - for_each_possible_cpu(cpu) { + core_to_chip_map = kcalloc(cpu_nr_cores(), sizeof(unsigned int), + GFP_KERNEL); + if (!core_to_chip_map) + goto out; + + cpumask_copy(&cpu_mask, cpu_possible_mask); + for_each_cpu(cpu, &cpu_mask) { unsigned int id = cpu_to_chip_id(cpu); if (prev_chip_id != id) { prev_chip_id = id; chip[nr_chips++] = id; } + core_to_chip_map[cpu_core_index_of_thread(cpu)] = id; + cpumask_andnot(&cpu_mask, &cpu_mask, cpu_sibling_mask(cpu)); } chips = kmalloc_array(nr_chips, sizeof(struct chip), GFP_KERNEL); if (!chips) - return -ENOMEM; + goto free_chip_map; for (i = 0; i < nr_chips; i++) { chips[i].id = chip[i]; @@ -582,6 +594,10 @@ static int init_chip_info(void) } return 0; +free_chip_map: + kfree(core_to_chip_map); +out: + return ret; } static int __init powernv_cpufreq_init(void) @@ -616,6 +632,7 @@ static void __exit powernv_cpufreq_exit(void) opal_message_notifier_unregister(OPAL_MSG_OCC, &powernv_cpufreq_opal_nb); kfree(chips); + kfree(core_to_chip_map); cpufreq_unregister_driver(&powernv_cpufreq_driver); } module_exit(powernv_cpufreq_exit); -- cgit v1.2.3 From c89f2682a39192433c296bf97b834fd2815a758b Mon Sep 17 00:00:00 2001 From: Shilpasri G Bhat Date: Wed, 3 Feb 2016 01:11:41 +0530 Subject: cpufreq: powernv: Replace pr_info with trace print for throttle event Currently we use printk message to notify the throttle event. But this can flood the console if the cpu is throttled frequently. So replace the printk with the tracepoint to notify the throttle event. And also events like throttle below nominal frequency and OCC_RESET are reduced to pr_warn/pr_warn_once as pointed by MFG to not mark them as critical messages. This patch adds 'throttle_reason' to struct chip to store the throttle reason. Signed-off-by: Shilpasri G Bhat Reviewed-by: Gautham R. Shenoy Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/powernv-cpufreq.c | 73 ++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index c670314053af..1bbc10a54c59 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -45,12 +46,22 @@ static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1]; static bool rebooting, throttled, occ_reset; static unsigned int *core_to_chip_map; +static const char * const throttle_reason[] = { + "No throttling", + "Power Cap", + "Processor Over Temperature", + "Power Supply Failure", + "Over Current", + "OCC Reset" +}; + static struct chip { unsigned int id; bool throttled; + bool restore; + u8 throttle_reason; cpumask_t mask; struct work_struct throttle; - bool restore; } *chips; static int nr_chips; @@ -331,17 +342,17 @@ static void powernv_cpufreq_throttle_check(void *data) goto next; chips[i].throttled = true; if (pmsr_pmax < powernv_pstate_info.nominal) - pr_crit("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n", - cpu, chips[i].id, pmsr_pmax, - powernv_pstate_info.nominal); - else - pr_info("CPU %d on Chip %u has Pmax reduced below turbo frequency (%d < %d)\n", - cpu, chips[i].id, pmsr_pmax, - powernv_pstate_info.max); + pr_warn_once("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n", + cpu, chips[i].id, pmsr_pmax, + powernv_pstate_info.nominal); + trace_powernv_throttle(chips[i].id, + throttle_reason[chips[i].throttle_reason], + pmsr_pmax); } else if (chips[i].throttled) { chips[i].throttled = false; - pr_info("CPU %d on Chip %u has Pmax restored to %d\n", cpu, - chips[i].id, pmsr_pmax); + trace_powernv_throttle(chips[i].id, + throttle_reason[chips[i].throttle_reason], + pmsr_pmax); } /* Check if Psafe_mode_active is set in PMSR. */ @@ -359,7 +370,7 @@ next: if (throttled) { pr_info("PMSR = %16lx\n", pmsr); - pr_crit("CPU Frequency could be throttled\n"); + pr_warn("CPU Frequency could be throttled\n"); } } @@ -452,15 +463,6 @@ out: put_online_cpus(); } -static char throttle_reason[][30] = { - "No throttling", - "Power Cap", - "Processor Over Temperature", - "Power Supply Failure", - "Over Current", - "OCC Reset" - }; - static int powernv_cpufreq_occ_msg(struct notifier_block *nb, unsigned long msg_type, void *_msg) { @@ -486,7 +488,7 @@ static int powernv_cpufreq_occ_msg(struct notifier_block *nb, */ if (!throttled) { throttled = true; - pr_crit("CPU frequency is throttled for duration\n"); + pr_warn("CPU frequency is throttled for duration\n"); } break; @@ -510,23 +512,18 @@ static int powernv_cpufreq_occ_msg(struct notifier_block *nb, return 0; } - if (omsg.throttle_status && + for (i = 0; i < nr_chips; i++) + if (chips[i].id == omsg.chip) + break; + + if (omsg.throttle_status >= 0 && omsg.throttle_status <= OCC_MAX_THROTTLE_STATUS) - pr_info("OCC: Chip %u Pmax reduced due to %s\n", - (unsigned int)omsg.chip, - throttle_reason[omsg.throttle_status]); - else if (!omsg.throttle_status) - pr_info("OCC: Chip %u %s\n", (unsigned int)omsg.chip, - throttle_reason[omsg.throttle_status]); - else - return 0; + chips[i].throttle_reason = omsg.throttle_status; - for (i = 0; i < nr_chips; i++) - if (chips[i].id == omsg.chip) { - if (!omsg.throttle_status) - chips[i].restore = true; - schedule_work(&chips[i].throttle); - } + if (!omsg.throttle_status) + chips[i].restore = true; + + schedule_work(&chips[i].throttle); } return 0; } @@ -581,16 +578,14 @@ static int init_chip_info(void) cpumask_andnot(&cpu_mask, &cpu_mask, cpu_sibling_mask(cpu)); } - chips = kmalloc_array(nr_chips, sizeof(struct chip), GFP_KERNEL); + chips = kcalloc(nr_chips, sizeof(struct chip), GFP_KERNEL); if (!chips) goto free_chip_map; for (i = 0; i < nr_chips; i++) { chips[i].id = chip[i]; - chips[i].throttled = false; cpumask_copy(&chips[i].mask, cpumask_of_node(chip[i])); INIT_WORK(&chips[i].throttle, powernv_cpufreq_work_fn); - chips[i].restore = false; } return 0; -- cgit v1.2.3 From c4924e92442d7218bd725e47fa3988c73aae84c9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 4 Feb 2016 14:36:09 +0300 Subject: extcon: max77843: Use correct size for reading the interrupt register The info->status[] array has 3 elements. We are using size MAX77843_MUIC_IRQ_NUM (16) instead of MAX77843_MUIC_STATUS_NUM (3) as intended. Fixes: 135d9f7d135a ('extcon: max77843: Clear IRQ bits state before request IRQ') Signed-off-by: Dan Carpenter Reviewed-by: Jaewon Kim Reviewed-by: Krzysztof Kozlowski [cw00.choi: Modify the patch title] Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-max77843.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c index 7bbc30097771..b188bd650efa 100644 --- a/drivers/extcon/extcon-max77843.c +++ b/drivers/extcon/extcon-max77843.c @@ -806,7 +806,7 @@ static int max77843_muic_probe(struct platform_device *pdev) /* Clear IRQ bits before request IRQs */ ret = regmap_bulk_read(max77843->regmap_muic, MAX77843_MUIC_REG_INT1, info->status, - MAX77843_MUIC_IRQ_NUM); + MAX77843_MUIC_STATUS_NUM); if (ret) { dev_err(&pdev->dev, "Failed to Clear IRQ bits\n"); goto err_muic_irq; -- cgit v1.2.3 From d2d06d4fe0f2cc2df9b17fefec96e6e1a1271d91 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 22 Jan 2016 15:42:41 +0100 Subject: scsi_dh_rdac: always retry MODE SELECT on command lock violation If MODE SELECT returns with sense '05/91/36' (command lock violation) it should always be retried without counting the number of retries. During an HBA upgrade or similar circumstances one might see a flood of MODE SELECT command from various HBAs, which will easily trigger the sense code and exceed the retry count. Cc: Signed-off-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/device_handler/scsi_dh_rdac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 361358134315..93880ed6291c 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -562,7 +562,7 @@ static int mode_select_handle_sense(struct scsi_device *sdev, /* * Command Lock contention */ - err = SCSI_DH_RETRY; + err = SCSI_DH_IMM_RETRY; break; default: break; @@ -612,6 +612,8 @@ retry: err = mode_select_handle_sense(sdev, h->sense); if (err == SCSI_DH_RETRY && retry_cnt--) goto retry; + if (err == SCSI_DH_IMM_RETRY) + goto retry; } if (err == SCSI_DH_OK) { h->state = RDAC_STATE_ACTIVE; -- cgit v1.2.3 From 82c43310508eb19eb41fe7862e89afeb74030b84 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 27 Jan 2016 16:19:13 +0200 Subject: SCSI: Add Marvell Console to VPD blacklist I have a Marvell 88SE9230 SATA Controller that has some sort of integrated console SCSI device attached to one of the ports. ata14: SATA link up 1.5 Gbps (SStatus 113 SControl 300) ata14.00: ATAPI: MARVELL VIRTUALL, 1.09, max UDMA/66 ata14.00: configured for UDMA/66 scsi 13:0:0:0: Processor Marvell Console 1.01 PQ: 0 ANSI: 5 Sending it VPD INQUIRY command seem to always fail with following error: ata14.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 ata14.00: irq_stat 0x40000001 ata14.00: cmd a0/01:00:00:00:01/00:00:00:00:00/a0 tag 2 dma 16640 in Inquiry 12 01 00 00 ff 00res 00/00:00:00:00:00/00:00:00:00:00/00 Emask 0x3 (HSM violation) ata14: hard resetting link This has been minor annoyance (only error printed on dmesg) until commit 09e2b0b14690 ("scsi: rescan VPD attributes") added call to scsi_attach_vpd() in scsi_rescan_device(). The commit causes the system to splat out following errors continuously without ever reaching the UI: ata14.00: configured for UDMA/66 ata14: EH complete ata14.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 ata14.00: irq_stat 0x40000001 ata14.00: cmd a0/01:00:00:00:01/00:00:00:00:00/a0 tag 6 dma 16640 in Inquiry 12 01 00 00 ff 00res 00/00:00:00:00:00/00:00:00:00:00/00 Emask 0x3 (HSM violation) ata14: hard resetting link ata14: SATA link up 1.5 Gbps (SStatus 113 SControl 300) ata14.00: configured for UDMA/66 ata14: EH complete ata14.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 ata14.00: irq_stat 0x40000001 ata14.00: cmd a0/01:00:00:00:01/00:00:00:00:00/a0 tag 7 dma 16640 in Inquiry 12 01 00 00 ff 00res 00/00:00:00:00:00/00:00:00:00:00/00 Emask 0x3 (HSM violation) Without in-depth understanding of SCSI layer and the Marvell controller, I suspect this happens because when the link goes down (because of an error) we schedule scsi_rescan_device() which again fails to read VPD data... ad infinitum. Since VPD data cannot be read from the device anyway we prevent the SCSI layer from even trying by blacklisting the device. This gets away the error and the system starts up normally. [mkp: Widened the match to all revisions of this device] Cc: Signed-off-by: Mika Westerberg Reported-by: Kirill A. Shutemov Reported-by: Alexander Duyck Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_devinfo.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 2c1160c7ec92..820416665324 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -205,6 +205,7 @@ static struct { {"Intel", "Multi-Flex", NULL, BLIST_NO_RSOC}, {"iRiver", "iFP Mass Driver", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36}, {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN}, + {"Marvell", "Console", NULL, BLIST_SKIP_VPD_PAGES}, {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, {"MATSHITA", "DMC-LC5", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36}, {"MATSHITA", "DMC-LC40", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36}, -- cgit v1.2.3 From 0fb5b1fb30fba3671dd5b1489d78e93e08d62e4e Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Thu, 4 Feb 2016 00:52:12 -0500 Subject: block/sd: Return -EREMOTEIO when WRITE SAME and DISCARD are disabled When a storage device rejects a WRITE SAME command we will disable write same functionality for the device and return -EREMOTEIO to the block layer. -EREMOTEIO will in turn prevent DM from retrying the I/O and/or failing the path. Yiwen Jiang discovered a small race where WRITE SAME requests issued simultaneously would cause -EIO to be returned. This happened because any requests being prepared after WRITE SAME had been disabled for the device caused us to return BLKPREP_KILL. The latter caused the block layer to return -EIO upon completion. To overcome this we introduce BLKPREP_INVALID which indicates that this is an invalid request for the device. blk_peek_request() is modified to return -EREMOTEIO in that case. Reported-by: Yiwen Jiang Suggested-by: Mike Snitzer Reviewed-by: Hannes Reinicke Reviewed-by: Ewan Milne Reviewed-by: Yiwen Jiang Signed-off-by: Martin K. Petersen --- block/blk-core.c | 6 ++++-- drivers/scsi/sd.c | 4 ++-- include/linux/blkdev.h | 9 ++++++--- 3 files changed, 12 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/block/blk-core.c b/block/blk-core.c index 476244d59309..35607dd0223b 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2447,14 +2447,16 @@ struct request *blk_peek_request(struct request_queue *q) rq = NULL; break; - } else if (ret == BLKPREP_KILL) { + } else if (ret == BLKPREP_KILL || ret == BLKPREP_INVALID) { + int err = (ret == BLKPREP_INVALID) ? -EREMOTEIO : -EIO; + rq->cmd_flags |= REQ_QUIET; /* * Mark this request as started so we don't trigger * any debug logic in the end I/O path. */ blk_start_request(rq); - __blk_end_request_all(rq, -EIO); + __blk_end_request_all(rq, err); } else { printk(KERN_ERR "%s: bad return=%d\n", __func__, ret); break; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index ec163d08f6c3..6e841c6da632 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -761,7 +761,7 @@ static int sd_setup_discard_cmnd(struct scsi_cmnd *cmd) break; default: - ret = BLKPREP_KILL; + ret = BLKPREP_INVALID; goto out; } @@ -839,7 +839,7 @@ static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd) int ret; if (sdkp->device->no_write_same) - return BLKPREP_KILL; + return BLKPREP_INVALID; BUG_ON(bio_offset(bio) || bio_iovec(bio).bv_len != sdp->sector_size); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index d372ea87ead5..a9b643a0647f 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -681,9 +681,12 @@ static inline bool blk_write_same_mergeable(struct bio *a, struct bio *b) /* * q->prep_rq_fn return values */ -#define BLKPREP_OK 0 /* serve it */ -#define BLKPREP_KILL 1 /* fatal error, kill */ -#define BLKPREP_DEFER 2 /* leave on queue */ +enum { + BLKPREP_OK, /* serve it */ + BLKPREP_KILL, /* fatal error, kill, return -EIO */ + BLKPREP_DEFER, /* leave on queue */ + BLKPREP_INVALID, /* invalid command, kill, return -EREMOTEIO */ +}; extern unsigned long blk_max_low_pfn, blk_max_pfn; -- cgit v1.2.3 From b7aad8e2685b0aa58295bc4250c8476c9c7193eb Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 30 Dec 2015 09:55:45 +0900 Subject: extcon: palmas: Add the support for VBUS detection by using GPIO This patch support for VBUS detection by using GPIO pin. Signed-off-by: Felipe Balbi Signed-off-by: Chanwoo Choi Acked-by: Lee Jones --- drivers/extcon/extcon-palmas.c | 50 ++++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/palmas.h | 3 +++ 2 files changed, 53 insertions(+) (limited to 'drivers') diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c index 93c30a885740..885ee95a6a7b 100644 --- a/drivers/extcon/extcon-palmas.c +++ b/drivers/extcon/extcon-palmas.c @@ -216,11 +216,23 @@ static int palmas_usb_probe(struct platform_device *pdev) return PTR_ERR(palmas_usb->id_gpiod); } + palmas_usb->vbus_gpiod = devm_gpiod_get_optional(&pdev->dev, "vbus", + GPIOD_IN); + if (IS_ERR(palmas_usb->vbus_gpiod)) { + dev_err(&pdev->dev, "failed to get vbus gpio\n"); + return PTR_ERR(palmas_usb->vbus_gpiod); + } + if (palmas_usb->enable_id_detection && palmas_usb->id_gpiod) { palmas_usb->enable_id_detection = false; palmas_usb->enable_gpio_id_detection = true; } + if (palmas_usb->enable_vbus_detection && palmas_usb->vbus_gpiod) { + palmas_usb->enable_vbus_detection = false; + palmas_usb->enable_gpio_vbus_detection = true; + } + if (palmas_usb->enable_gpio_id_detection) { u32 debounce; @@ -311,6 +323,40 @@ static int palmas_usb_probe(struct platform_device *pdev) palmas_usb->vbus_irq, status); return status; } + } else if (palmas_usb->enable_gpio_vbus_detection) { + /* remux GPIO_1 as VBUSDET */ + status = palmas_update_bits(palmas, + PALMAS_PU_PD_OD_BASE, + PALMAS_PRIMARY_SECONDARY_PAD1, + PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK, + (1 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_SHIFT)); + if (status < 0) { + dev_err(&pdev->dev, "can't remux GPIO1\n"); + return status; + } + + palmas_usb->vbus_otg_irq = regmap_irq_get_virq(palmas->irq_data, + PALMAS_VBUS_OTG_IRQ); + palmas_usb->gpio_vbus_irq = gpiod_to_irq(palmas_usb->vbus_gpiod); + if (palmas_usb->gpio_vbus_irq < 0) { + dev_err(&pdev->dev, "failed to get vbus irq\n"); + return palmas_usb->gpio_vbus_irq; + } + status = devm_request_threaded_irq(&pdev->dev, + palmas_usb->gpio_vbus_irq, + NULL, + palmas_vbus_irq_handler, + IRQF_TRIGGER_FALLING | + IRQF_TRIGGER_RISING | + IRQF_ONESHOT | + IRQF_EARLY_RESUME, + "palmas_usb_vbus", + palmas_usb); + if (status < 0) { + dev_err(&pdev->dev, + "failed to request handler for vbus irq\n"); + return status; + } } palmas_enable_irq(palmas_usb); @@ -337,6 +383,8 @@ static int palmas_usb_suspend(struct device *dev) if (device_may_wakeup(dev)) { if (palmas_usb->enable_vbus_detection) enable_irq_wake(palmas_usb->vbus_irq); + if (palmas_usb->enable_gpio_vbus_detection) + enable_irq_wake(palmas_usb->gpio_vbus_irq); if (palmas_usb->enable_id_detection) enable_irq_wake(palmas_usb->id_irq); if (palmas_usb->enable_gpio_id_detection) @@ -352,6 +400,8 @@ static int palmas_usb_resume(struct device *dev) if (device_may_wakeup(dev)) { if (palmas_usb->enable_vbus_detection) disable_irq_wake(palmas_usb->vbus_irq); + if (palmas_usb->enable_gpio_vbus_detection) + disable_irq_wake(palmas_usb->gpio_vbus_irq); if (palmas_usb->enable_id_detection) disable_irq_wake(palmas_usb->id_irq); if (palmas_usb->enable_gpio_id_detection) diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h index c800dbc42079..5c9a1d44c125 100644 --- a/include/linux/mfd/palmas.h +++ b/include/linux/mfd/palmas.h @@ -580,7 +580,9 @@ struct palmas_usb { int vbus_irq; int gpio_id_irq; + int gpio_vbus_irq; struct gpio_desc *id_gpiod; + struct gpio_desc *vbus_gpiod; unsigned long sw_debounce_jiffies; struct delayed_work wq_detectid; @@ -589,6 +591,7 @@ struct palmas_usb { bool enable_vbus_detection; bool enable_id_detection; bool enable_gpio_id_detection; + bool enable_gpio_vbus_detection; }; #define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator) -- cgit v1.2.3 From dabe19540af9e563d526113bb102e1b9b9fa73f9 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Mon, 1 Feb 2016 11:08:29 -0500 Subject: drm: fix missing reference counting decrease In drm_dp_mst_allocate_vcpi, it returns true in two paths, but in one path, there is no reference couting decrease. Signed-off-by: Insu Yun Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_dp_mst_topology.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 6ed90a2437e5..fe273b681fe5 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2446,6 +2446,7 @@ bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp DRM_DEBUG_KMS("payload: vcpi %d already allocated for pbn %d - requested pbn %d\n", port->vcpi.vcpi, port->vcpi.pbn, pbn); if (pbn == port->vcpi.pbn) { *slots = port->vcpi.num_slots; + drm_dp_put_port(port); return true; } } -- cgit v1.2.3 From 441388a8a73f905359e60518cfc18eca6aed2b6a Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 29 Jan 2016 14:44:28 +0200 Subject: drm/mst: Don't ignore the MST PBN self-test result Otherwise this call would have no effect. Caught by Coverity. Signed-off-by: Imre Deak Reviewed-by: David Weinehall Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_dp_mst_topology.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index fe273b681fe5..2b7c2f068834 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2855,7 +2855,9 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, if (!mgr->proposed_vcpis) return -ENOMEM; set_bit(0, &mgr->payload_mask); - test_calc_pbn_mode(); + if (test_calc_pbn_mode() < 0) + DRM_ERROR("MST PBN self-test failed\n"); + return 0; } EXPORT_SYMBOL(drm_dp_mst_topology_mgr_init); -- cgit v1.2.3 From 4d6a10da79fddcf7460299ab390da74ef2b592f6 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 29 Jan 2016 14:44:29 +0200 Subject: drm/mst: Add range check for max_payloads during init max_payload is limited by the space we have in drm_dp_mst_topology_mgr::vcpi_mask,payload_mask. We need to track max_payloads+1 IDs in these masks, see drm_dp_mst_assign_payload_id(). Add a sanity check for this. Caught by coverity. Signed-off-by: Imre Deak Reviewed-by: David Weinehall Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_dp_mst_topology.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 2b7c2f068834..0680e7aecac4 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2848,6 +2848,9 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, mgr->max_dpcd_transaction_bytes = max_dpcd_transaction_bytes; mgr->max_payloads = max_payloads; mgr->conn_base_id = conn_base_id; + if (max_payloads + 1 > sizeof(mgr->payload_mask) * 8 || + max_payloads + 1 > sizeof(mgr->vcpi_mask) * 8) + return -EINVAL; mgr->payloads = kcalloc(max_payloads, sizeof(struct drm_dp_payload), GFP_KERNEL); if (!mgr->payloads) return -ENOMEM; -- cgit v1.2.3 From a9ebb3e46c7ef6112c0da466ef0954673ad36832 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 22 Jan 2016 17:07:26 -0500 Subject: drm/dp/mst: Calculate MST PBN with 31.32 fixed point Our PBN value overflows the 20 bits integer part of the 20.12 fixed point. We need to use 31.32 fixed point to avoid this. This happens with display clocks larger than 293122 (at 24 bpp), which we see with the Sharp (and similar) 4k tiled displays. Signed-off-by: Harry Wentland Cc: stable@vger.kernel.org Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_dp_mst_topology.c | 67 ++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 0680e7aecac4..84047b802c18 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2606,32 +2606,31 @@ EXPORT_SYMBOL(drm_dp_check_act_status); */ int drm_dp_calc_pbn_mode(int clock, int bpp) { - fixed20_12 pix_bw; - fixed20_12 fbpp; - fixed20_12 result; - fixed20_12 margin, tmp; - u32 res; - - pix_bw.full = dfixed_const(clock); - fbpp.full = dfixed_const(bpp); - tmp.full = dfixed_const(8); - fbpp.full = dfixed_div(fbpp, tmp); - - result.full = dfixed_mul(pix_bw, fbpp); - margin.full = dfixed_const(54); - tmp.full = dfixed_const(64); - margin.full = dfixed_div(margin, tmp); - result.full = dfixed_div(result, margin); - - margin.full = dfixed_const(1006); - tmp.full = dfixed_const(1000); - margin.full = dfixed_div(margin, tmp); - result.full = dfixed_mul(result, margin); - - result.full = dfixed_div(result, tmp); - result.full = dfixed_ceil(result); - res = dfixed_trunc(result); - return res; + u64 kbps; + s64 peak_kbps; + u32 numerator; + u32 denominator; + + kbps = clock * bpp; + + /* + * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006 + * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on + * common multiplier to render an integer PBN for all link rate/lane + * counts combinations + * calculate + * peak_kbps *= (1006/1000) + * peak_kbps *= (64/54) + * peak_kbps *= 8 convert to bytes + */ + + numerator = 64 * 1006; + denominator = 54 * 8 * 1000 * 1000; + + kbps *= numerator; + peak_kbps = drm_fixp_from_fraction(kbps, denominator); + + return drm_fixp2int_ceil(peak_kbps); } EXPORT_SYMBOL(drm_dp_calc_pbn_mode); @@ -2639,11 +2638,23 @@ static int test_calc_pbn_mode(void) { int ret; ret = drm_dp_calc_pbn_mode(154000, 30); - if (ret != 689) + if (ret != 689) { + DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n", + 154000, 30, 689, ret); return -EINVAL; + } ret = drm_dp_calc_pbn_mode(234000, 30); - if (ret != 1047) + if (ret != 1047) { + DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n", + 234000, 30, 1047, ret); return -EINVAL; + } + ret = drm_dp_calc_pbn_mode(297000, 24); + if (ret != 1063) { + DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n", + 297000, 24, 1063, ret); + return -EINVAL; + } return 0; } -- cgit v1.2.3 From cfcfa086d43ced33e1099b9befb12f17fca102e1 Mon Sep 17 00:00:00 2001 From: Mykola Lysenko Date: Fri, 22 Jan 2016 17:07:27 -0500 Subject: drm/dp/mst: change MST detection scheme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Get edid for all connected MST displays, not only on logical ports, in the same thread as MST topology detection is done: There are displays that have branches inside w/o logical ports. So in case another SST display connected downstream system can end-up in situation when 3 DOWN requests sent: two for ‘remote i2c read’ and one for ‘enum path resources’, making slots full. 2. Call notification callback in one place in the end of topology discovery/update: This is done to reduce number of events sent to userspace in case complex topology discovery is going, adding multiple number of connectors; 3. Remove notification callback call from short pulse interrupt processing function: This is done in order not to block interrupt processing function, in case any MST request will be made from it. Notification will be send from topology discovery/update work item. Signed-off-by: Mykola Lysenko Reviewed-by: Harry Wentland Cc: stable@vger.kernel.org Acked-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_dp_mst_topology.c | 37 ++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 84047b802c18..630e6eb55fa3 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1130,13 +1130,11 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, drm_dp_put_port(port); goto out; } - if (port->port_num >= DP_MST_LOGICAL_PORT_0) { - port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc); - drm_mode_connector_set_tile_property(port->connector); - } + + drm_mode_connector_set_tile_property(port->connector); + (*mstb->mgr->cbs->register_connector)(port->connector); } - out: /* put reference to this port */ drm_dp_put_port(port); @@ -1161,9 +1159,9 @@ static void drm_dp_update_port(struct drm_dp_mst_branch *mstb, port->ddps = conn_stat->displayport_device_plug_status; if (old_ddps != port->ddps) { + dowork = true; if (port->ddps) { drm_dp_check_port_guid(mstb, port); - dowork = true; } else { port->guid_valid = false; port->available_pbn = 0; @@ -1271,8 +1269,13 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m if (port->input) continue; - if (!port->ddps) + if (!port->ddps) { + if (port->cached_edid) { + kfree(port->cached_edid); + port->cached_edid = NULL; + } continue; + } if (!port->available_pbn) drm_dp_send_enum_path_resources(mgr, mstb, port); @@ -1283,6 +1286,12 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m drm_dp_check_and_send_link_address(mgr, mstb_child); drm_dp_put_mst_branch_device(mstb_child); } + } else if (port->pdt == DP_PEER_DEVICE_SST_SINK || + port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV) { + if (!port->cached_edid) { + port->cached_edid = + drm_get_edid(port->connector, &port->aux.ddc); + } } } } @@ -1302,6 +1311,8 @@ static void drm_dp_mst_link_probe_work(struct work_struct *work) drm_dp_check_and_send_link_address(mgr, mstb); drm_dp_put_mst_branch_device(mstb); } + + (*mgr->cbs->hotplug)(mgr); } static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr, @@ -1558,7 +1569,6 @@ static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr, for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) { drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]); } - (*mgr->cbs->hotplug)(mgr); } } else { mstb->link_address_sent = false; @@ -2232,8 +2242,6 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) drm_dp_update_port(mstb, &msg.u.conn_stat); DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type); - (*mgr->cbs->hotplug)(mgr); - } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) { drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false); if (!mstb) @@ -2320,10 +2328,6 @@ enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector case DP_PEER_DEVICE_SST_SINK: status = connector_status_connected; - /* for logical ports - cache the EDID */ - if (port->port_num >= 8 && !port->cached_edid) { - port->cached_edid = drm_get_edid(connector, &port->aux.ddc); - } break; case DP_PEER_DEVICE_DP_LEGACY_CONV: if (port->ldps) @@ -2378,10 +2382,7 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_ if (port->cached_edid) edid = drm_edid_duplicate(port->cached_edid); - else { - edid = drm_get_edid(connector, &port->aux.ddc); - drm_mode_connector_set_tile_property(connector); - } + port->has_audio = drm_detect_monitor_audio(edid); drm_dp_put_port(port); return edid; -- cgit v1.2.3 From 5e93b8208d3c419b515fb75e2601931c027e12ab Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 22 Jan 2016 17:07:28 -0500 Subject: drm/dp/mst: move GUID storage from mgr, port to only mst branch Previous implementation does not handle case below: boot up one MST branch to DP connector of ASIC. After boot up, hot plug 2nd MST branch to DP output of 1st MST, GUID is not created for 2nd MST branch. When downstream port of 2nd MST branch send upstream request, it fails because 2nd MST branch GUID is not available. New Implementation: only create GUID for MST branch and save it within Branch. Signed-off-by: Hersen Wu Reviewed-by: Harry Wentland Cc: stable@vger.kernel.org Acked-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_dp_mst_topology.c | 64 +++++++++++++++-------------------- include/drm/drm_dp_mst_helper.h | 25 ++++++-------- 2 files changed, 38 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 630e6eb55fa3..2c12a20ff08e 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1018,18 +1018,27 @@ static bool drm_dp_port_setup_pdt(struct drm_dp_mst_port *port) return send_link; } -static void drm_dp_check_port_guid(struct drm_dp_mst_branch *mstb, - struct drm_dp_mst_port *port) +static void drm_dp_check_mstb_guid(struct drm_dp_mst_branch *mstb, u8 *guid) { int ret; - if (port->dpcd_rev >= 0x12) { - port->guid_valid = drm_dp_validate_guid(mstb->mgr, port->guid); - if (!port->guid_valid) { - ret = drm_dp_send_dpcd_write(mstb->mgr, - port, - DP_GUID, - 16, port->guid); - port->guid_valid = true; + + memcpy(mstb->guid, guid, 16); + + if (!drm_dp_validate_guid(mstb->mgr, mstb->guid)) { + if (mstb->port_parent) { + ret = drm_dp_send_dpcd_write( + mstb->mgr, + mstb->port_parent, + DP_GUID, + 16, + mstb->guid); + } else { + + ret = drm_dp_dpcd_write( + mstb->mgr->aux, + DP_GUID, + mstb->guid, + 16); } } } @@ -1086,7 +1095,6 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, port->dpcd_rev = port_msg->dpcd_revision; port->num_sdp_streams = port_msg->num_sdp_streams; port->num_sdp_stream_sinks = port_msg->num_sdp_stream_sinks; - memcpy(port->guid, port_msg->peer_guid, 16); /* manage mstb port lists with mgr lock - take a reference for this list */ @@ -1099,11 +1107,9 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, if (old_ddps != port->ddps) { if (port->ddps) { - drm_dp_check_port_guid(mstb, port); if (!port->input) drm_dp_send_enum_path_resources(mstb->mgr, mstb, port); } else { - port->guid_valid = false; port->available_pbn = 0; } } @@ -1161,9 +1167,7 @@ static void drm_dp_update_port(struct drm_dp_mst_branch *mstb, if (old_ddps != port->ddps) { dowork = true; if (port->ddps) { - drm_dp_check_port_guid(mstb, port); } else { - port->guid_valid = false; port->available_pbn = 0; } } @@ -1220,13 +1224,14 @@ static struct drm_dp_mst_branch *get_mst_branch_device_by_guid_helper( struct drm_dp_mst_branch *found_mstb; struct drm_dp_mst_port *port; + if (memcmp(mstb->guid, guid, 16) == 0) + return mstb; + + list_for_each_entry(port, &mstb->ports, next) { if (!port->mstb) continue; - if (port->guid_valid && memcmp(port->guid, guid, 16) == 0) - return port->mstb; - found_mstb = get_mst_branch_device_by_guid_helper(port->mstb, guid); if (found_mstb) @@ -1245,10 +1250,7 @@ static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device_by_guid( /* find the port by iterating down */ mutex_lock(&mgr->lock); - if (mgr->guid_valid && memcmp(mgr->guid, guid, 16) == 0) - mstb = mgr->mst_primary; - else - mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid); + mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid); if (mstb) kref_get(&mstb->kref); @@ -1566,6 +1568,9 @@ static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr, txmsg->reply.u.link_addr.ports[i].num_sdp_streams, txmsg->reply.u.link_addr.ports[i].num_sdp_stream_sinks); } + + drm_dp_check_mstb_guid(mstb, txmsg->reply.u.link_addr.guid); + for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) { drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]); } @@ -2006,20 +2011,6 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms goto out_unlock; } - - /* sort out guid */ - ret = drm_dp_dpcd_read(mgr->aux, DP_GUID, mgr->guid, 16); - if (ret != 16) { - DRM_DEBUG_KMS("failed to read DP GUID %d\n", ret); - goto out_unlock; - } - - mgr->guid_valid = drm_dp_validate_guid(mgr, mgr->guid); - if (!mgr->guid_valid) { - ret = drm_dp_dpcd_write(mgr->aux, DP_GUID, mgr->guid, 16); - mgr->guid_valid = true; - } - queue_work(system_long_wq, &mgr->work); ret = 0; @@ -2241,6 +2232,7 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) } drm_dp_update_port(mstb, &msg.u.conn_stat); + DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type); } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) { drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false); diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 24ab1787b771..fdb47051d549 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -44,8 +44,6 @@ struct drm_dp_vcpi { /** * struct drm_dp_mst_port - MST port * @kref: reference count for this port. - * @guid_valid: for DP 1.2 devices if we have validated the GUID. - * @guid: guid for DP 1.2 device on this port. * @port_num: port number * @input: if this port is an input port. * @mcs: message capability status - DP 1.2 spec. @@ -70,10 +68,6 @@ struct drm_dp_vcpi { struct drm_dp_mst_port { struct kref kref; - /* if dpcd 1.2 device is on this port - its GUID info */ - bool guid_valid; - u8 guid[16]; - u8 port_num; bool input; bool mcs; @@ -110,10 +104,12 @@ struct drm_dp_mst_port { * @tx_slots: transmission slots for this device. * @last_seqno: last sequence number used to talk to this. * @link_address_sent: if a link address message has been sent to this device yet. + * @guid: guid for DP 1.2 branch device. port under this branch can be + * identified by port #. * * This structure represents an MST branch device, there is one - * primary branch device at the root, along with any others connected - * to downstream ports + * primary branch device at the root, along with any other branches connected + * to downstream port of parent branches. */ struct drm_dp_mst_branch { struct kref kref; @@ -132,6 +128,9 @@ struct drm_dp_mst_branch { struct drm_dp_sideband_msg_tx *tx_slots[2]; int last_seqno; bool link_address_sent; + + /* global unique identifier to identify branch devices */ + u8 guid[16]; }; @@ -406,11 +405,9 @@ struct drm_dp_payload { * @conn_base_id: DRM connector ID this mgr is connected to. * @down_rep_recv: msg receiver state for down replies. * @up_req_recv: msg receiver state for up requests. - * @lock: protects mst state, primary, guid, dpcd. + * @lock: protects mst state, primary, dpcd. * @mst_state: if this manager is enabled for an MST capable port. * @mst_primary: pointer to the primary branch device. - * @guid_valid: GUID valid for the primary branch device. - * @guid: GUID for primary port. * @dpcd: cache of DPCD for primary port. * @pbn_div: PBN to slots divisor. * @@ -432,13 +429,11 @@ struct drm_dp_mst_topology_mgr { struct drm_dp_sideband_msg_rx up_req_recv; /* pointer to info about the initial MST device */ - struct mutex lock; /* protects mst_state + primary + guid + dpcd */ + struct mutex lock; /* protects mst_state + primary + dpcd */ bool mst_state; struct drm_dp_mst_branch *mst_primary; - /* primary MST device GUID */ - bool guid_valid; - u8 guid[16]; + u8 dpcd[DP_RECEIVER_CAP_SIZE]; u8 sink_count; int pbn_div; -- cgit v1.2.3 From c175cd16df272119534058f28cbd5eeac6ff2d24 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 22 Jan 2016 17:07:29 -0500 Subject: drm/dp/mst: Reverse order of MST enable and clearing VC payload table. On DELL U3014 if you clear the table before enabling MST it sometimes hangs the receiver. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Cc: stable@vger.kernel.org Acked-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_dp_mst_topology.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 2c12a20ff08e..7e5d98c7b908 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1998,6 +1998,12 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms mgr->mst_primary = mstb; kref_get(&mgr->mst_primary->kref); + ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, + DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC); + if (ret < 0) { + goto out_unlock; + } + { struct drm_dp_payload reset_pay; reset_pay.start_slot = 0; @@ -2005,12 +2011,6 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms drm_dp_dpcd_write_payload(mgr, 0, &reset_pay); } - ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, - DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC); - if (ret < 0) { - goto out_unlock; - } - queue_work(system_long_wq, &mgr->work); ret = 0; -- cgit v1.2.3 From 91a25e463130c8e19bdb42f2d827836c7937992e Mon Sep 17 00:00:00 2001 From: Mykola Lysenko Date: Wed, 27 Jan 2016 09:39:36 -0500 Subject: drm/dp/mst: deallocate payload on port destruction This is needed to properly deallocate port payload after downstream branch get unplugged. In order to do this unplugged MST topology should be preserved, to find first alive port on path to unplugged MST topology, and send payload deallocation request to branch device of found port. For this mstb and port kref's are used in reversed order to track when port and branch memory could be freed. Added additional functions to find appropriate mstb as described above. Signed-off-by: Mykola Lysenko Reviewed-by: Harry Wentland Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_dp_mst_topology.c | 91 ++++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 7e5d98c7b908..8ae13de272c4 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -803,12 +803,33 @@ static struct drm_dp_mst_branch *drm_dp_add_mst_branch_device(u8 lct, u8 *rad) return mstb; } +static void drm_dp_free_mst_port(struct kref *kref); + +static void drm_dp_free_mst_branch_device(struct kref *kref) +{ + struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref); + if (mstb->port_parent) { + if (list_empty(&mstb->port_parent->next)) + kref_put(&mstb->port_parent->kref, drm_dp_free_mst_port); + } + kfree(mstb); +} + static void drm_dp_destroy_mst_branch_device(struct kref *kref) { struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref); struct drm_dp_mst_port *port, *tmp; bool wake_tx = false; + /* + * init kref again to be used by ports to remove mst branch when it is + * not needed anymore + */ + kref_init(kref); + + if (mstb->port_parent && list_empty(&mstb->port_parent->next)) + kref_get(&mstb->port_parent->kref); + /* * destroy all ports - don't need lock * as there are no more references to the mst branch @@ -835,7 +856,8 @@ static void drm_dp_destroy_mst_branch_device(struct kref *kref) if (wake_tx) wake_up(&mstb->mgr->tx_waitq); - kfree(mstb); + + kref_put(kref, drm_dp_free_mst_branch_device); } static void drm_dp_put_mst_branch_device(struct drm_dp_mst_branch *mstb) @@ -883,6 +905,7 @@ static void drm_dp_destroy_port(struct kref *kref) * from an EDID retrieval */ mutex_lock(&mgr->destroy_connector_lock); + kref_get(&port->parent->kref); list_add(&port->next, &mgr->destroy_connector_list); mutex_unlock(&mgr->destroy_connector_lock); schedule_work(&mgr->destroy_connector_work); @@ -1617,6 +1640,37 @@ static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr, return 0; } +static struct drm_dp_mst_port *drm_dp_get_last_connected_port_to_mstb(struct drm_dp_mst_branch *mstb) +{ + if (!mstb->port_parent) + return NULL; + + if (mstb->port_parent->mstb != mstb) + return mstb->port_parent; + + return drm_dp_get_last_connected_port_to_mstb(mstb->port_parent->parent); +} + +static struct drm_dp_mst_branch *drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_branch *mstb, + int *port_num) +{ + struct drm_dp_mst_branch *rmstb = NULL; + struct drm_dp_mst_port *found_port; + mutex_lock(&mgr->lock); + if (mgr->mst_primary) { + found_port = drm_dp_get_last_connected_port_to_mstb(mstb); + + if (found_port) { + rmstb = found_port->parent; + kref_get(&rmstb->kref); + *port_num = found_port->port_num; + } + } + mutex_unlock(&mgr->lock); + return rmstb; +} + static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int id, @@ -1624,13 +1678,18 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, { struct drm_dp_sideband_msg_tx *txmsg; struct drm_dp_mst_branch *mstb; - int len, ret; + int len, ret, port_num; u8 sinks[DRM_DP_MAX_SDP_STREAMS]; int i; + port_num = port->port_num; mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent); - if (!mstb) - return -EINVAL; + if (!mstb) { + mstb = drm_dp_get_last_connected_port_and_mstb(mgr, port->parent, &port_num); + + if (!mstb) + return -EINVAL; + } txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); if (!txmsg) { @@ -1642,7 +1701,7 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, sinks[i] = i; txmsg->dst = mstb; - len = build_allocate_payload(txmsg, port->port_num, + len = build_allocate_payload(txmsg, port_num, id, pbn, port->num_sdp_streams, sinks); @@ -2788,6 +2847,13 @@ static void drm_dp_tx_work(struct work_struct *work) mutex_unlock(&mgr->qlock); } +static void drm_dp_free_mst_port(struct kref *kref) +{ + struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref); + kref_put(&port->parent->kref, drm_dp_free_mst_branch_device); + kfree(port); +} + static void drm_dp_destroy_connector_work(struct work_struct *work) { struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work); @@ -2808,13 +2874,22 @@ static void drm_dp_destroy_connector_work(struct work_struct *work) list_del(&port->next); mutex_unlock(&mgr->destroy_connector_lock); + kref_init(&port->kref); + INIT_LIST_HEAD(&port->next); + mgr->cbs->destroy_connector(mgr, port->connector); drm_dp_port_teardown_pdt(port, port->pdt); - if (!port->input && port->vcpi.vcpi > 0) - drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi); - kfree(port); + if (!port->input && port->vcpi.vcpi > 0) { + if (mgr->mst_state) { + drm_dp_mst_reset_vcpi_slots(mgr, port); + drm_dp_update_payload_part1(mgr); + drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi); + } + } + + kref_put(&port->kref, drm_dp_free_mst_port); send_hotplug = true; } if (send_hotplug) -- cgit v1.2.3 From 23272a6754b81ff6503e09c743bb4ceeeab39997 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 29 Oct 2015 11:51:16 +0100 Subject: nbd: Remove signal usage As discussed on the mailing list, the usage of signals for timeout handling has a lot of potential issues. The nbd driver used for some time signals for timeouts. These signals where able to get the threads out of the blocking socket operations. This patch removes all signal usage and uses a socket shutdown instead. The socket descriptor itself is cleared later when the whole nbd device is closed. The tasks_lock is removed as we do not depend on this anymore. Instead a new lock for the socket is introduced so we can safely work with the socket in the timeout handler outside of the two main threads. Cc: Oleg Nesterov Cc: Christoph Hellwig Signed-off-by: Markus Pargmann Reviewed-by: Christoph Hellwig --- drivers/block/nbd.c | 126 ++++++++++++++++++++-------------------------------- 1 file changed, 48 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index d61a04155d99..438f4dc549db 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -60,7 +60,8 @@ struct nbd_device { bool disconnect; /* a disconnect has been requested by user */ struct timer_list timeout_timer; - spinlock_t tasks_lock; + /* protects initialization and shutdown of the socket */ + spinlock_t sock_lock; struct task_struct *task_recv; struct task_struct *task_send; @@ -129,13 +130,20 @@ static void nbd_end_request(struct nbd_device *nbd, struct request *req) */ static void sock_shutdown(struct nbd_device *nbd) { - if (!nbd->sock) + spin_lock_irq(&nbd->sock_lock); + + if (!nbd->sock) { + spin_unlock_irq(&nbd->sock_lock); return; + } dev_warn(disk_to_dev(nbd->disk), "shutting down socket\n"); kernel_sock_shutdown(nbd->sock, SHUT_RDWR); + sockfd_put(nbd->sock); nbd->sock = NULL; - del_timer_sync(&nbd->timeout_timer); + spin_unlock_irq(&nbd->sock_lock); + + del_timer(&nbd->timeout_timer); } static void nbd_xmit_timeout(unsigned long arg) @@ -148,17 +156,15 @@ static void nbd_xmit_timeout(unsigned long arg) nbd->disconnect = true; - spin_lock_irqsave(&nbd->tasks_lock, flags); + spin_lock_irqsave(&nbd->sock_lock, flags); - if (nbd->task_recv) - force_sig(SIGKILL, nbd->task_recv); - if (nbd->task_send) - force_sig(SIGKILL, nbd->task_send); + if (nbd->sock) + kernel_sock_shutdown(nbd->sock, SHUT_RDWR); - spin_unlock_irqrestore(&nbd->tasks_lock, flags); + spin_unlock_irqrestore(&nbd->sock_lock, flags); - dev_err(nbd_to_dev(nbd), "Connection timed out, killed receiver and sender, shutting down connection\n"); + dev_err(nbd_to_dev(nbd), "Connection timed out, shutting down connection\n"); } /* @@ -171,7 +177,6 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size, int result; struct msghdr msg; struct kvec iov; - sigset_t blocked, oldset; unsigned long pflags = current->flags; if (unlikely(!sock)) { @@ -181,11 +186,6 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size, return -EINVAL; } - /* Allow interception of SIGKILL only - * Don't allow other signals to interrupt the transmission */ - siginitsetinv(&blocked, sigmask(SIGKILL)); - sigprocmask(SIG_SETMASK, &blocked, &oldset); - current->flags |= PF_MEMALLOC; do { sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC; @@ -212,7 +212,6 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size, buf += result; } while (size > 0); - sigprocmask(SIG_SETMASK, &oldset, NULL); tsk_restore_flags(current, pflags, PF_MEMALLOC); if (!send && nbd->xmit_timeout) @@ -406,23 +405,18 @@ static int nbd_thread_recv(struct nbd_device *nbd) { struct request *req; int ret; - unsigned long flags; BUG_ON(nbd->magic != NBD_MAGIC); sk_set_memalloc(nbd->sock->sk); - spin_lock_irqsave(&nbd->tasks_lock, flags); nbd->task_recv = current; - spin_unlock_irqrestore(&nbd->tasks_lock, flags); ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr); if (ret) { dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n"); - spin_lock_irqsave(&nbd->tasks_lock, flags); nbd->task_recv = NULL; - spin_unlock_irqrestore(&nbd->tasks_lock, flags); return ret; } @@ -439,19 +433,7 @@ static int nbd_thread_recv(struct nbd_device *nbd) device_remove_file(disk_to_dev(nbd->disk), &pid_attr); - spin_lock_irqsave(&nbd->tasks_lock, flags); nbd->task_recv = NULL; - spin_unlock_irqrestore(&nbd->tasks_lock, flags); - - if (signal_pending(current)) { - ret = kernel_dequeue_signal(NULL); - dev_warn(nbd_to_dev(nbd), "pid %d, %s, got signal %d\n", - task_pid_nr(current), current->comm, ret); - mutex_lock(&nbd->tx_lock); - sock_shutdown(nbd); - mutex_unlock(&nbd->tx_lock); - ret = -ETIMEDOUT; - } return ret; } @@ -544,11 +526,8 @@ static int nbd_thread_send(void *data) { struct nbd_device *nbd = data; struct request *req; - unsigned long flags; - spin_lock_irqsave(&nbd->tasks_lock, flags); nbd->task_send = current; - spin_unlock_irqrestore(&nbd->tasks_lock, flags); set_user_nice(current, MIN_NICE); while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) { @@ -557,17 +536,6 @@ static int nbd_thread_send(void *data) kthread_should_stop() || !list_empty(&nbd->waiting_queue)); - if (signal_pending(current)) { - int ret = kernel_dequeue_signal(NULL); - - dev_warn(nbd_to_dev(nbd), "pid %d, %s, got signal %d\n", - task_pid_nr(current), current->comm, ret); - mutex_lock(&nbd->tx_lock); - sock_shutdown(nbd); - mutex_unlock(&nbd->tx_lock); - break; - } - /* extract request */ if (list_empty(&nbd->waiting_queue)) continue; @@ -582,13 +550,7 @@ static int nbd_thread_send(void *data) nbd_handle_req(nbd, req); } - spin_lock_irqsave(&nbd->tasks_lock, flags); nbd->task_send = NULL; - spin_unlock_irqrestore(&nbd->tasks_lock, flags); - - /* Clear maybe pending signals */ - if (signal_pending(current)) - kernel_dequeue_signal(NULL); return 0; } @@ -636,6 +598,25 @@ static void nbd_request_handler(struct request_queue *q) } } +static int nbd_set_socket(struct nbd_device *nbd, struct socket *sock) +{ + int ret = 0; + + spin_lock_irq(&nbd->sock_lock); + + if (nbd->sock) { + ret = -EBUSY; + goto out; + } + + nbd->sock = sock; + +out: + spin_unlock_irq(&nbd->sock_lock); + + return ret; +} + static int nbd_dev_dbg_init(struct nbd_device *nbd); static void nbd_dev_dbg_close(struct nbd_device *nbd); @@ -668,32 +649,26 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, return 0; } - case NBD_CLEAR_SOCK: { - struct socket *sock = nbd->sock; - nbd->sock = NULL; + case NBD_CLEAR_SOCK: + sock_shutdown(nbd); nbd_clear_que(nbd); BUG_ON(!list_empty(&nbd->queue_head)); BUG_ON(!list_empty(&nbd->waiting_queue)); kill_bdev(bdev); - if (sock) - sockfd_put(sock); return 0; - } case NBD_SET_SOCK: { - struct socket *sock; int err; - if (nbd->sock) - return -EBUSY; - sock = sockfd_lookup(arg, &err); - if (sock) { - nbd->sock = sock; - if (max_part > 0) - bdev->bd_invalidated = 1; - nbd->disconnect = false; /* we're connected now */ - return 0; - } - return -EINVAL; + struct socket *sock = sockfd_lookup(arg, &err); + + if (!sock) + return err; + + err = nbd_set_socket(nbd, sock); + if (!err && max_part) + bdev->bd_invalidated = 1; + + return err; } case NBD_SET_BLKSIZE: @@ -734,7 +709,6 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, case NBD_DO_IT: { struct task_struct *thread; - struct socket *sock; int error; if (nbd->task_recv) @@ -769,14 +743,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, mutex_lock(&nbd->tx_lock); sock_shutdown(nbd); - sock = nbd->sock; - nbd->sock = NULL; nbd_clear_que(nbd); kill_bdev(bdev); queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); set_device_ro(bdev, false); - if (sock) - sockfd_put(sock); nbd->flags = 0; nbd->bytesize = 0; bdev->bd_inode->i_size = 0; @@ -1042,7 +1012,7 @@ static int __init nbd_init(void) nbd_dev[i].magic = NBD_MAGIC; INIT_LIST_HEAD(&nbd_dev[i].waiting_queue); spin_lock_init(&nbd_dev[i].queue_lock); - spin_lock_init(&nbd_dev[i].tasks_lock); + spin_lock_init(&nbd_dev[i].sock_lock); INIT_LIST_HEAD(&nbd_dev[i].queue_head); mutex_init(&nbd_dev[i].tx_lock); init_timer(&nbd_dev[i].timeout_timer); -- cgit v1.2.3 From 1f7b5cf1be4351e60cf8ae7aab976503dd73c5f8 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 29 Oct 2015 12:01:34 +0100 Subject: nbd: Timeouts are not user requested disconnects It may be useful to know in the client that a connection timed out. The current code returns success for a timeout. This patch reports the error code -ETIMEDOUT for a timeout. Signed-off-by: Markus Pargmann --- drivers/block/nbd.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 438f4dc549db..2e14e51b5ea3 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -57,6 +57,7 @@ struct nbd_device { int blksize; loff_t bytesize; int xmit_timeout; + bool timedout; bool disconnect; /* a disconnect has been requested by user */ struct timer_list timeout_timer; @@ -154,10 +155,9 @@ static void nbd_xmit_timeout(unsigned long arg) if (list_empty(&nbd->queue_head)) return; - nbd->disconnect = true; - spin_lock_irqsave(&nbd->sock_lock, flags); + nbd->timedout = true; if (nbd->sock) kernel_sock_shutdown(nbd->sock, SHUT_RDWR); @@ -754,7 +754,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, if (max_part > 0) blkdev_reread_part(bdev); if (nbd->disconnect) /* user requested, ignore socket errors */ - return 0; + error = 0; + if (nbd->timedout) + error = -ETIMEDOUT; + return error; } -- cgit v1.2.3 From 0e4f0f6f63d3416a9e529d99febfe98545427b81 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 29 Oct 2015 12:04:51 +0100 Subject: nbd: Cleanup reset of nbd and bdev after a disconnect Group all variables that are reset after a disconnect into reset functions. This patch adds two of these functions, nbd_reset() and nbd_bdev_reset(). Signed-off-by: Markus Pargmann --- drivers/block/nbd.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 2e14e51b5ea3..34a46c32c24f 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -617,6 +617,30 @@ out: return ret; } +/* Reset all properties of an NBD device */ +static void nbd_reset(struct nbd_device *nbd) +{ + nbd->disconnect = false; + nbd->timedout = false; + nbd->blksize = 1024; + nbd->bytesize = 0; + set_capacity(nbd->disk, 0); + nbd->flags = 0; + nbd->xmit_timeout = 0; + queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); + del_timer_sync(&nbd->timeout_timer); +} + +static void nbd_bdev_reset(struct block_device *bdev) +{ + set_device_ro(bdev, false); + bdev->bd_inode->i_size = 0; + if (max_part > 0) { + blkdev_reread_part(bdev); + bdev->bd_invalidated = 1; + } +} + static int nbd_dev_dbg_init(struct nbd_device *nbd); static void nbd_dev_dbg_close(struct nbd_device *nbd); @@ -745,19 +769,15 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, sock_shutdown(nbd); nbd_clear_que(nbd); kill_bdev(bdev); - queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); - set_device_ro(bdev, false); - nbd->flags = 0; - nbd->bytesize = 0; - bdev->bd_inode->i_size = 0; - set_capacity(nbd->disk, 0); - if (max_part > 0) - blkdev_reread_part(bdev); + nbd_bdev_reset(bdev); + if (nbd->disconnect) /* user requested, ignore socket errors */ error = 0; if (nbd->timedout) error = -ETIMEDOUT; + nbd_reset(nbd); + return error; } @@ -1023,14 +1043,12 @@ static int __init nbd_init(void) nbd_dev[i].timeout_timer.data = (unsigned long)&nbd_dev[i]; init_waitqueue_head(&nbd_dev[i].active_wq); init_waitqueue_head(&nbd_dev[i].waiting_wq); - nbd_dev[i].blksize = 1024; - nbd_dev[i].bytesize = 0; disk->major = NBD_MAJOR; disk->first_minor = i << part_shift; disk->fops = &nbd_fops; disk->private_data = &nbd_dev[i]; sprintf(disk->disk_name, "nbd%d", i); - set_capacity(disk, 0); + nbd_reset(&nbd_dev[i]); add_disk(disk); } -- cgit v1.2.3 From d02cf53107792df373558851d6162dc4e4ceb95a Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 29 Oct 2015 12:06:15 +0100 Subject: nbd: Move flag parsing to a function nbd changes properties of the blockdevice depending on flags that were received. This patch moves this flag parsing into a separate function nbd_parse_flags(). Signed-off-by: Markus Pargmann --- drivers/block/nbd.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 34a46c32c24f..b67500d5b338 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -641,6 +641,18 @@ static void nbd_bdev_reset(struct block_device *bdev) } } +static void nbd_parse_flags(struct nbd_device *nbd, struct block_device *bdev) +{ + if (nbd->flags & NBD_FLAG_READ_ONLY) + set_device_ro(bdev, true); + if (nbd->flags & NBD_FLAG_SEND_TRIM) + queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); + if (nbd->flags & NBD_FLAG_SEND_FLUSH) + blk_queue_flush(nbd->disk->queue, REQ_FLUSH); + else + blk_queue_flush(nbd->disk->queue, 0); +} + static int nbd_dev_dbg_init(struct nbd_device *nbd); static void nbd_dev_dbg_close(struct nbd_device *nbd); @@ -742,15 +754,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, mutex_unlock(&nbd->tx_lock); - if (nbd->flags & NBD_FLAG_READ_ONLY) - set_device_ro(bdev, true); - if (nbd->flags & NBD_FLAG_SEND_TRIM) - queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, - nbd->disk->queue); - if (nbd->flags & NBD_FLAG_SEND_FLUSH) - blk_queue_flush(nbd->disk->queue, REQ_FLUSH); - else - blk_queue_flush(nbd->disk->queue, 0); + nbd_parse_flags(nbd, bdev); thread = kthread_run(nbd_thread_send, nbd, "%s", nbd_name(nbd)); -- cgit v1.2.3 From da6ccaaa79caca4f38b540b651238f87215217a2 Mon Sep 17 00:00:00 2001 From: Dan Streetman Date: Thu, 14 Jan 2016 13:42:32 -0500 Subject: nbd: ratelimit error msgs after socket close Make the "Attempted send on closed socket" error messages generated in nbd_request_handler() ratelimited. When the nbd socket is shutdown, the nbd_request_handler() function emits an error message for every request remaining in its queue. If the queue is large, this will spam a large amount of messages to the log. There's no need for a separate error message for each request, so this patch ratelimits it. In the specific case this was found, the system was virtual and the error messages were logged to the serial port, which overwhelmed it. Fixes: 4d48a542b427 ("nbd: fix I/O hang on disconnected nbds") Signed-off-by: Dan Streetman Signed-off-by: Markus Pargmann --- drivers/block/nbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index b67500d5b338..4c5d94146aa3 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -580,8 +580,8 @@ static void nbd_request_handler(struct request_queue *q) req, req->cmd_type); if (unlikely(!nbd->sock)) { - dev_err(disk_to_dev(nbd->disk), - "Attempted send on closed socket\n"); + dev_err_ratelimited(disk_to_dev(nbd->disk), + "Attempted send on closed socket\n"); req->errors++; nbd_end_request(nbd, req); spin_lock_irq(q->queue_lock); -- cgit v1.2.3 From 320549a22484952d88d4e0320218765b16cd2174 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 5 Feb 2016 11:22:04 +0000 Subject: regmap: mmio: Revert to v4.4 endianness handling Commit 29bb45f25ff3 (regmap-mmio: Use native endianness for read/write) attempted to fix some long standing bugs in the MMIO implementation for big endian systems caused by duplicate byte swapping in both regmap and readl()/writel() which affected MIPS systems as when they are in big endian mode they flip the endianness of all registers in the system, not just the CPU. MIPS systems had worked around this by declaring regmap using IPs as little endian which is inaccurate, unfortunately the issue had not been reported. Sadly the fix makes things worse rather than better. By changing the behaviour to match the documentation it caused behaviour changes for other IPs which broke them and by using the __raw I/O accessors to avoid the endianness swapping in readl()/writel() it removed some memory ordering guarantees and could potentially generate unvirtualisable instructions on some architectures. Unfortunately sorting out all this mess in any half way sensible fashion was far too invasive to go in during an -rc cycle so instead let's go back to the old broken behaviour for v4.5, the better fixes are already queued for v4.6. This does mean that we keep the broken MIPS DTs for another release but that seems the least bad way of handling the situation. Reported-by: Johannes Berg Signed-off-by: Mark Brown --- arch/mips/boot/dts/brcm/bcm6328.dtsi | 1 + arch/mips/boot/dts/brcm/bcm7125.dtsi | 1 + arch/mips/boot/dts/brcm/bcm7346.dtsi | 1 + arch/mips/boot/dts/brcm/bcm7358.dtsi | 1 + arch/mips/boot/dts/brcm/bcm7360.dtsi | 1 + arch/mips/boot/dts/brcm/bcm7362.dtsi | 1 + arch/mips/boot/dts/brcm/bcm7420.dtsi | 1 + arch/mips/boot/dts/brcm/bcm7425.dtsi | 1 + arch/mips/boot/dts/brcm/bcm7435.dtsi | 1 + drivers/base/regmap/regmap-mmio.c | 16 ++++++++-------- 10 files changed, 17 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/arch/mips/boot/dts/brcm/bcm6328.dtsi b/arch/mips/boot/dts/brcm/bcm6328.dtsi index 459b9b252c3b..d61b1616b604 100644 --- a/arch/mips/boot/dts/brcm/bcm6328.dtsi +++ b/arch/mips/boot/dts/brcm/bcm6328.dtsi @@ -74,6 +74,7 @@ timer: timer@10000040 { compatible = "syscon"; reg = <0x10000040 0x2c>; + little-endian; }; reboot { diff --git a/arch/mips/boot/dts/brcm/bcm7125.dtsi b/arch/mips/boot/dts/brcm/bcm7125.dtsi index 4fc7ecee273c..1a7efa883c5e 100644 --- a/arch/mips/boot/dts/brcm/bcm7125.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7125.dtsi @@ -98,6 +98,7 @@ sun_top_ctrl: syscon@404000 { compatible = "brcm,bcm7125-sun-top-ctrl", "syscon"; reg = <0x404000 0x60c>; + little-endian; }; reboot { diff --git a/arch/mips/boot/dts/brcm/bcm7346.dtsi b/arch/mips/boot/dts/brcm/bcm7346.dtsi index a3039bb53477..d4bf52cfcf17 100644 --- a/arch/mips/boot/dts/brcm/bcm7346.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7346.dtsi @@ -118,6 +118,7 @@ sun_top_ctrl: syscon@404000 { compatible = "brcm,bcm7346-sun-top-ctrl", "syscon"; reg = <0x404000 0x51c>; + little-endian; }; reboot { diff --git a/arch/mips/boot/dts/brcm/bcm7358.dtsi b/arch/mips/boot/dts/brcm/bcm7358.dtsi index 4274ff41ec21..8e2501694d03 100644 --- a/arch/mips/boot/dts/brcm/bcm7358.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7358.dtsi @@ -112,6 +112,7 @@ sun_top_ctrl: syscon@404000 { compatible = "brcm,bcm7358-sun-top-ctrl", "syscon"; reg = <0x404000 0x51c>; + little-endian; }; reboot { diff --git a/arch/mips/boot/dts/brcm/bcm7360.dtsi b/arch/mips/boot/dts/brcm/bcm7360.dtsi index 0dcc9163c27b..7e5f76040fb8 100644 --- a/arch/mips/boot/dts/brcm/bcm7360.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7360.dtsi @@ -112,6 +112,7 @@ sun_top_ctrl: syscon@404000 { compatible = "brcm,bcm7360-sun-top-ctrl", "syscon"; reg = <0x404000 0x51c>; + little-endian; }; reboot { diff --git a/arch/mips/boot/dts/brcm/bcm7362.dtsi b/arch/mips/boot/dts/brcm/bcm7362.dtsi index 2f3f9fc2c478..c739ea77acb0 100644 --- a/arch/mips/boot/dts/brcm/bcm7362.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7362.dtsi @@ -118,6 +118,7 @@ sun_top_ctrl: syscon@404000 { compatible = "brcm,bcm7362-sun-top-ctrl", "syscon"; reg = <0x404000 0x51c>; + little-endian; }; reboot { diff --git a/arch/mips/boot/dts/brcm/bcm7420.dtsi b/arch/mips/boot/dts/brcm/bcm7420.dtsi index bee221b3b568..5f55d0a50a28 100644 --- a/arch/mips/boot/dts/brcm/bcm7420.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7420.dtsi @@ -99,6 +99,7 @@ sun_top_ctrl: syscon@404000 { compatible = "brcm,bcm7420-sun-top-ctrl", "syscon"; reg = <0x404000 0x60c>; + little-endian; }; reboot { diff --git a/arch/mips/boot/dts/brcm/bcm7425.dtsi b/arch/mips/boot/dts/brcm/bcm7425.dtsi index 571f30f52e3f..e24d41ab4e30 100644 --- a/arch/mips/boot/dts/brcm/bcm7425.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7425.dtsi @@ -100,6 +100,7 @@ sun_top_ctrl: syscon@404000 { compatible = "brcm,bcm7425-sun-top-ctrl", "syscon"; reg = <0x404000 0x51c>; + little-endian; }; reboot { diff --git a/arch/mips/boot/dts/brcm/bcm7435.dtsi b/arch/mips/boot/dts/brcm/bcm7435.dtsi index 614ee211f71a..8b9432cc062b 100644 --- a/arch/mips/boot/dts/brcm/bcm7435.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7435.dtsi @@ -114,6 +114,7 @@ sun_top_ctrl: syscon@404000 { compatible = "brcm,bcm7425-sun-top-ctrl", "syscon"; reg = <0x404000 0x51c>; + little-endian; }; reboot { diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index 8812bfb9e3b8..eea51569f0eb 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c @@ -133,17 +133,17 @@ static int regmap_mmio_gather_write(void *context, while (val_size) { switch (ctx->val_bytes) { case 1: - __raw_writeb(*(u8 *)val, ctx->regs + offset); + writeb(*(u8 *)val, ctx->regs + offset); break; case 2: - __raw_writew(*(u16 *)val, ctx->regs + offset); + writew(*(u16 *)val, ctx->regs + offset); break; case 4: - __raw_writel(*(u32 *)val, ctx->regs + offset); + writel(*(u32 *)val, ctx->regs + offset); break; #ifdef CONFIG_64BIT case 8: - __raw_writeq(*(u64 *)val, ctx->regs + offset); + writeq(*(u64 *)val, ctx->regs + offset); break; #endif default: @@ -193,17 +193,17 @@ static int regmap_mmio_read(void *context, while (val_size) { switch (ctx->val_bytes) { case 1: - *(u8 *)val = __raw_readb(ctx->regs + offset); + *(u8 *)val = readb(ctx->regs + offset); break; case 2: - *(u16 *)val = __raw_readw(ctx->regs + offset); + *(u16 *)val = readw(ctx->regs + offset); break; case 4: - *(u32 *)val = __raw_readl(ctx->regs + offset); + *(u32 *)val = readl(ctx->regs + offset); break; #ifdef CONFIG_64BIT case 8: - *(u64 *)val = __raw_readq(ctx->regs + offset); + *(u64 *)val = readq(ctx->regs + offset); break; #endif default: -- cgit v1.2.3 From 23a5110dc619073b57d90c36eae383f51df03aac Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 5 Feb 2016 12:16:09 +0200 Subject: drm/i915/dp: abstract training pattern selection Make it cleaner to add more checks in the function. No functional changes. Cc: Ander Conselvan de Oliveira Cc: Sivakumar Thulasimani Reviewed-by: Sivakumar Thulasimani Cc: drm-intel-fixes@lists.freedesktop.org # dependency on the next patch Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1454667370-8001-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dp_link_training.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c index 88887938e0bf..83e667b92fda 100644 --- a/drivers/gpu/drm/i915/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c @@ -215,16 +215,15 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp) } } -static void -intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp) +/* + * Pick training pattern for channel equalization. Training Pattern 3 for HBR2 + * or 1.2 devices that support it, Training Pattern 2 otherwise. + */ +static u32 intel_dp_training_pattern(struct intel_dp *intel_dp) { - bool channel_eq = false; - int tries, cr_tries; - uint32_t training_pattern = DP_TRAINING_PATTERN_2; + u32 training_pattern = DP_TRAINING_PATTERN_2; /* - * Training Pattern 3 for HBR2 or 1.2 devices that support it. - * * Intel platforms that support HBR2 also support TPS3. TPS3 support is * also mandatory for downstream devices that support HBR2. * @@ -237,6 +236,18 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp) else if (intel_dp->link_rate == 540000) DRM_ERROR("5.4 Gbps link rate without HBR2/TPS3 support\n"); + return training_pattern; +} + +static void +intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp) +{ + bool channel_eq = false; + int tries, cr_tries; + u32 training_pattern; + + training_pattern = intel_dp_training_pattern(intel_dp); + /* channel equalization */ if (!intel_dp_set_link_train(intel_dp, training_pattern | -- cgit v1.2.3 From bfcef5d2135ea1200ac1ea44661619ab8785c9f0 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 5 Feb 2016 12:16:10 +0200 Subject: drm/i915/dp: reduce missing TPS3 support errors to debug logging Per spec, TPS3 support is mandatory for downstream devices that support HBR2. We've therefore logged errors on HBR2 without TPS3 since commit 1da7d7131c35cde83f1bab8ec732b57b69bef814 Author: Jani Nikula Date: Thu Sep 3 11:16:08 2015 +0300 drm/i915: ignore link rate in TPS3 selection However, it seems there are real world devices out there that just aren't spec compliant, and still work at HBR2 using TPS2. So reduce the error message to debug logging. Cc: Ander Conselvan de Oliveira Cc: Sivakumar Thulasimani Reviewed-by: Sivakumar Thulasimani Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92932 Fixes: 1da7d7131c35 ("drm/i915: ignore link rate in TPS3 selection") Cc: drm-intel-fixes@lists.freedesktop.org Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1454667370-8001-2-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dp_link_training.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c index 83e667b92fda..0b8eefc2acc5 100644 --- a/drivers/gpu/drm/i915/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c @@ -222,19 +222,27 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp) static u32 intel_dp_training_pattern(struct intel_dp *intel_dp) { u32 training_pattern = DP_TRAINING_PATTERN_2; + bool source_tps3, sink_tps3; /* * Intel platforms that support HBR2 also support TPS3. TPS3 support is - * also mandatory for downstream devices that support HBR2. + * also mandatory for downstream devices that support HBR2. However, not + * all sinks follow the spec. * * Due to WaDisableHBR2 SKL < B0 is the only exception where TPS3 is - * supported but still not enabled. + * supported in source but still not enabled. */ - if (intel_dp_source_supports_hbr2(intel_dp) && - drm_dp_tps3_supported(intel_dp->dpcd)) + source_tps3 = intel_dp_source_supports_hbr2(intel_dp); + sink_tps3 = drm_dp_tps3_supported(intel_dp->dpcd); + + if (source_tps3 && sink_tps3) { training_pattern = DP_TRAINING_PATTERN_3; - else if (intel_dp->link_rate == 540000) - DRM_ERROR("5.4 Gbps link rate without HBR2/TPS3 support\n"); + } else if (intel_dp->link_rate == 540000) { + if (!source_tps3) + DRM_DEBUG_KMS("5.4 Gbps link rate without source HBR2/TPS3 support\n"); + if (!sink_tps3) + DRM_DEBUG_KMS("5.4 Gbps link rate without sink TPS3 support\n"); + } return training_pattern; } -- cgit v1.2.3 From 0c4b3c637ca5fe20fe513dbdee6f62166c97fed1 Mon Sep 17 00:00:00 2001 From: Nicholas Krause Date: Thu, 4 Feb 2016 10:52:40 -0500 Subject: HID: multitouch: warn on sysfs group creation failure This adds a warning message stating that the sysfs group was not able to be created for the passed hid_device structure pointer with dev_warn. Signed-off-by: Nicholas Krause Reviewed-by: Benjamin Tissoires [jkosina@suse.cz: massaged changelog a bit] [jkosina@suse.cz: reformatted source] Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 296d4991560e..6adb788bbfca 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1133,6 +1133,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) return ret; ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group); + if (ret) + dev_warn(&hdev->dev, "Cannot allocate sysfs group for %s\n", + hdev->name); mt_set_maxcontacts(hdev); mt_set_input_mode(hdev); -- cgit v1.2.3 From eceb3e61c74356590f37cec89708770b333162c4 Mon Sep 17 00:00:00 2001 From: Biao Huang Date: Wed, 3 Feb 2016 09:24:45 +0800 Subject: pinctrl: mediatek: fix direction control issue Since input-enable/disable and input-schmitt-enable/disable are workable when gpio direction is input, so add direction setting when do input-enable/disable and input-schmitt-enable/disable properties. Signed-off-by: Biao Huang Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 16d48a4ed225..e96e86d2e745 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -347,6 +347,7 @@ static int mtk_pconf_parse_conf(struct pinctrl_dev *pctldev, ret = mtk_pconf_set_pull_select(pctl, pin, true, false, arg); break; case PIN_CONFIG_INPUT_ENABLE: + mtk_pmx_gpio_set_direction(pctldev, NULL, pin, true); ret = mtk_pconf_set_ies_smt(pctl, pin, arg, param); break; case PIN_CONFIG_OUTPUT: @@ -354,6 +355,7 @@ static int mtk_pconf_parse_conf(struct pinctrl_dev *pctldev, ret = mtk_pmx_gpio_set_direction(pctldev, NULL, pin, false); break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: + mtk_pmx_gpio_set_direction(pctldev, NULL, pin, true); ret = mtk_pconf_set_ies_smt(pctl, pin, arg, param); break; case PIN_CONFIG_DRIVE_STRENGTH: -- cgit v1.2.3 From 59ee9c96dd5d1aa5f982d2849ed406af8d071134 Mon Sep 17 00:00:00 2001 From: Biao Huang Date: Wed, 3 Feb 2016 09:24:46 +0800 Subject: pinctrl: mediatek: Add gpio_request_enable support Implement the .gpio_request_enable() callbacks in struct pinmux_ops in mediatek pinctrl driver. Make sure that when gpio_request is called, GPIO on the pin is enabled. Signed-off-by: Biao Huang Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 36 +++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 8cac73d9c382..b752f5aee6a4 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -43,6 +43,7 @@ #define MAX_GPIO_MODE_PER_REG 5 #define GPIO_MODE_BITS 3 +#define GPIO_MODE_PREFIX "GPIO" static const char * const mtk_gpio_functions[] = { "func0", "func1", "func2", "func3", @@ -733,12 +734,47 @@ static int mtk_pmx_set_mux(struct pinctrl_dev *pctldev, return 0; } +static int mtk_pmx_find_gpio_mode(struct mtk_pinctrl *pctl, + unsigned offset) +{ + const struct mtk_desc_pin *pin = pctl->devdata->pins + offset; + const struct mtk_desc_function *func = pin->functions; + + while (func && func->name) { + if (!strncmp(func->name, GPIO_MODE_PREFIX, + sizeof(GPIO_MODE_PREFIX)-1)) + return func->muxval; + func++; + } + return -EINVAL; +} + +static int mtk_pmx_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned offset) +{ + unsigned long muxval; + struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + muxval = mtk_pmx_find_gpio_mode(pctl, offset); + + if (muxval < 0) { + dev_err(pctl->dev, "invalid gpio pin %d.\n", offset); + return -EINVAL; + } + + mtk_pmx_set_mode(pctldev, offset, muxval); + + return 0; +} + static const struct pinmux_ops mtk_pmx_ops = { .get_functions_count = mtk_pmx_get_funcs_cnt, .get_function_name = mtk_pmx_get_func_name, .get_function_groups = mtk_pmx_get_func_groups, .set_mux = mtk_pmx_set_mux, .gpio_set_direction = mtk_pmx_gpio_set_direction, + .gpio_request_enable = mtk_pmx_gpio_request_enable, }; static int mtk_gpio_direction_input(struct gpio_chip *chip, -- cgit v1.2.3 From 5041e791440a53930f06ce22deeb17a72e343ad0 Mon Sep 17 00:00:00 2001 From: Julien Grossholtz Date: Wed, 13 Jan 2016 11:57:43 -0500 Subject: gpio: add TS-4800 fpga GPIO support The TS-4800 GPIO driver provide support for the GPIOs available on the Technologic Sytems board FPGA. It allows to set direction and read/write states. It uses the generic gpio driver. Signed-off-by: Julien Grossholtz Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 7 ++++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-ts4800.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 drivers/gpio/gpio-ts4800.c (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 00f17673e7e0..77df86635480 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -382,6 +382,13 @@ config GPIO_TB10X select GENERIC_IRQ_CHIP select OF_GPIO +config GPIO_TS4800 + tristate "TS-4800 DIO blocks and compatibles" + depends on OF_GPIO + select GPIO_GENERIC + help + This driver support TS-4800 FPGA GPIO controllers. + config GPIO_TZ1090 bool "Toumaz Xenif TZ1090 GPIO support" depends on SOC_TZ1090 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index d4cc4f3d3674..2f5852daab0d 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -99,6 +99,7 @@ obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o +obj-$(CONFIG_GPIO_TS4800) += gpio-ts4800.o obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o diff --git a/drivers/gpio/gpio-ts4800.c b/drivers/gpio/gpio-ts4800.c new file mode 100644 index 000000000000..c4908a45c523 --- /dev/null +++ b/drivers/gpio/gpio-ts4800.c @@ -0,0 +1,94 @@ +/* + * GPIO driver for the TS-4800 board + * + * Copyright (c) 2016 - Savoir-faire Linux + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include + +#define DEFAULT_PIN_NUMBER 16 +#define INPUT_REG_OFFSET 0x00 +#define OUTPUT_REG_OFFSET 0x02 +#define DIRECTION_REG_OFFSET 0x04 + +static int ts4800_gpio_probe(struct platform_device *pdev) +{ + struct device_node *node; + struct gpio_chip *chip; + struct resource *res; + void __iomem *base_addr; + int retval; + u32 ngpios; + + chip = devm_kzalloc(&pdev->dev, sizeof(struct gpio_chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base_addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base_addr)) + return PTR_ERR(base_addr); + + node = pdev->dev.of_node; + if (!node) + return -EINVAL; + + retval = of_property_read_u32(node, "ngpios", &ngpios); + if (retval == -EINVAL) + ngpios = DEFAULT_PIN_NUMBER; + else if (retval) + return retval; + + retval = bgpio_init(chip, &pdev->dev, 2, base_addr + INPUT_REG_OFFSET, + base_addr + OUTPUT_REG_OFFSET, NULL, + base_addr + DIRECTION_REG_OFFSET, NULL, + BGPIOF_BIG_ENDIAN & BGPIOF_BIG_ENDIAN_BYTE_ORDER); + if (retval) { + dev_err(&pdev->dev, "bgpio_init failed\n"); + return retval; + } + + chip->base = -1; + chip->label = dev_name(&pdev->dev); + chip->ngpio = ngpios; + + platform_set_drvdata(pdev, chip); + + return gpiochip_add_data(chip, NULL); +} + +static int ts4800_gpio_remove(struct platform_device *pdev) +{ + struct gpio_chip *chip = platform_get_drvdata(pdev); + + gpiochip_remove(chip); + + return 0; +} + +static const struct of_device_id ts4800_gpio_of_match[] = { + { .compatible = "technologic,ts4800-gpio", }, + {}, +}; + +static struct platform_driver ts4800_gpio_driver = { + .driver = { + .name = "ts4800-gpio", + .of_match_table = ts4800_gpio_of_match, + }, + .probe = ts4800_gpio_probe, + .remove = ts4800_gpio_remove, +}; + +module_platform_driver_probe(ts4800_gpio_driver, ts4800_gpio_probe); + +MODULE_AUTHOR("Julien Grossholtz "); +MODULE_DESCRIPTION("TS4800 FPGA GPIO driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 25cbac7716be6a8d5c57534645ca472d2e4be1fd Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 24 Jan 2016 00:30:08 +0900 Subject: pinctrl: tegra: move Tegra pinctrl drivers to sub-directory Tegra has several pinctrl drivers. Now it is reasonable enough to move them into drivers/pinctrl/tegra/. Signed-off-by: Masahiro Yamada Acked-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 32 +- drivers/pinctrl/Makefile | 8 +- drivers/pinctrl/pinctrl-tegra-xusb.c | 985 ----------- drivers/pinctrl/pinctrl-tegra.c | 747 --------- drivers/pinctrl/pinctrl-tegra.h | 194 --- drivers/pinctrl/pinctrl-tegra114.c | 1872 --------------------- drivers/pinctrl/pinctrl-tegra124.c | 2084 ----------------------- drivers/pinctrl/pinctrl-tegra20.c | 2252 ------------------------- drivers/pinctrl/pinctrl-tegra210.c | 1588 ------------------ drivers/pinctrl/pinctrl-tegra30.c | 2507 ---------------------------- drivers/pinctrl/tegra/Kconfig | 30 + drivers/pinctrl/tegra/Makefile | 7 + drivers/pinctrl/tegra/pinctrl-tegra-xusb.c | 985 +++++++++++ drivers/pinctrl/tegra/pinctrl-tegra.c | 747 +++++++++ drivers/pinctrl/tegra/pinctrl-tegra.h | 194 +++ drivers/pinctrl/tegra/pinctrl-tegra114.c | 1872 +++++++++++++++++++++ drivers/pinctrl/tegra/pinctrl-tegra124.c | 2084 +++++++++++++++++++++++ drivers/pinctrl/tegra/pinctrl-tegra20.c | 2252 +++++++++++++++++++++++++ drivers/pinctrl/tegra/pinctrl-tegra210.c | 1588 ++++++++++++++++++ drivers/pinctrl/tegra/pinctrl-tegra30.c | 2507 ++++++++++++++++++++++++++++ 20 files changed, 12268 insertions(+), 12267 deletions(-) delete mode 100644 drivers/pinctrl/pinctrl-tegra-xusb.c delete mode 100644 drivers/pinctrl/pinctrl-tegra.c delete mode 100644 drivers/pinctrl/pinctrl-tegra.h delete mode 100644 drivers/pinctrl/pinctrl-tegra114.c delete mode 100644 drivers/pinctrl/pinctrl-tegra124.c delete mode 100644 drivers/pinctrl/pinctrl-tegra20.c delete mode 100644 drivers/pinctrl/pinctrl-tegra210.c delete mode 100644 drivers/pinctrl/pinctrl-tegra30.c create mode 100644 drivers/pinctrl/tegra/Kconfig create mode 100644 drivers/pinctrl/tegra/Makefile create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra-xusb.c create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra.c create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra.h create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra114.c create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra124.c create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra20.c create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra210.c create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra30.c (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index f8405cdeb5fb..6ba67a619062 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -168,37 +168,6 @@ config PINCTRL_ST select PINCONF select GPIOLIB_IRQCHIP -config PINCTRL_TEGRA - bool - select PINMUX - select PINCONF - -config PINCTRL_TEGRA20 - bool - select PINCTRL_TEGRA - -config PINCTRL_TEGRA30 - bool - select PINCTRL_TEGRA - -config PINCTRL_TEGRA114 - bool - select PINCTRL_TEGRA - -config PINCTRL_TEGRA124 - bool - select PINCTRL_TEGRA - -config PINCTRL_TEGRA210 - bool - select PINCTRL_TEGRA - -config PINCTRL_TEGRA_XUSB - def_bool y if ARCH_TEGRA - select GENERIC_PHY - select PINCONF - select PINMUX - config PINCTRL_TZ1090 bool "Toumaz Xenif TZ1090 pin control driver" depends on SOC_TZ1090 @@ -259,6 +228,7 @@ source "drivers/pinctrl/sh-pfc/Kconfig" source "drivers/pinctrl/spear/Kconfig" source "drivers/pinctrl/stm32/Kconfig" source "drivers/pinctrl/sunxi/Kconfig" +source "drivers/pinctrl/tegra/Kconfig" source "drivers/pinctrl/uniphier/Kconfig" source "drivers/pinctrl/vt8500/Kconfig" source "drivers/pinctrl/mediatek/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index d25dcbd28dfa..e4e673e2a448 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -22,13 +22,7 @@ obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o obj-$(CONFIG_PINCTRL_SIRF) += sirf/ -obj-$(CONFIG_PINCTRL_TEGRA) += pinctrl-tegra.o -obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o -obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o -obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o -obj-$(CONFIG_PINCTRL_TEGRA124) += pinctrl-tegra124.o -obj-$(CONFIG_PINCTRL_TEGRA210) += pinctrl-tegra210.o -obj-$(CONFIG_PINCTRL_TEGRA_XUSB) += pinctrl-tegra-xusb.o +obj-$(CONFIG_PINCTRL_TEGRA) += tegra/ obj-$(CONFIG_PINCTRL_TZ1090) += pinctrl-tz1090.o obj-$(CONFIG_PINCTRL_TZ1090_PDC) += pinctrl-tz1090-pdc.o obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c deleted file mode 100644 index bd3aa5a4fd6d..000000000000 --- a/drivers/pinctrl/pinctrl-tegra-xusb.c +++ /dev/null @@ -1,985 +0,0 @@ -/* - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "core.h" -#include "pinctrl-utils.h" - -#define XUSB_PADCTL_ELPG_PROGRAM 0x01c -#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26) -#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25) -#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24) - -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040 -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19) -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12) -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1) - -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044 -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6) -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5) -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4) - -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138 -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27) -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24) -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3) -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1) -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0) - -#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148 -#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1) -#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0) - -struct tegra_xusb_padctl_function { - const char *name; - const char * const *groups; - unsigned int num_groups; -}; - -struct tegra_xusb_padctl_soc { - const struct pinctrl_pin_desc *pins; - unsigned int num_pins; - - const struct tegra_xusb_padctl_function *functions; - unsigned int num_functions; - - const struct tegra_xusb_padctl_lane *lanes; - unsigned int num_lanes; -}; - -struct tegra_xusb_padctl_lane { - const char *name; - - unsigned int offset; - unsigned int shift; - unsigned int mask; - unsigned int iddq; - - const unsigned int *funcs; - unsigned int num_funcs; -}; - -struct tegra_xusb_padctl { - struct device *dev; - void __iomem *regs; - struct mutex lock; - struct reset_control *rst; - - const struct tegra_xusb_padctl_soc *soc; - struct pinctrl_dev *pinctrl; - struct pinctrl_desc desc; - - struct phy_provider *provider; - struct phy *phys[2]; - - unsigned int enable; -}; - -static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value, - unsigned long offset) -{ - writel(value, padctl->regs + offset); -} - -static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl, - unsigned long offset) -{ - return readl(padctl->regs + offset); -} - -static int tegra_xusb_padctl_get_groups_count(struct pinctrl_dev *pinctrl) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - - return padctl->soc->num_pins; -} - -static const char *tegra_xusb_padctl_get_group_name(struct pinctrl_dev *pinctrl, - unsigned int group) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - - return padctl->soc->pins[group].name; -} - -static int tegra_xusb_padctl_get_group_pins(struct pinctrl_dev *pinctrl, - unsigned group, - const unsigned **pins, - unsigned *num_pins) -{ - /* - * For the tegra-xusb pad controller groups are synonomous - * with lanes/pins and there is always one lane/pin per group. - */ - *pins = &pinctrl->desc->pins[group].number; - *num_pins = 1; - - return 0; -} - -enum tegra_xusb_padctl_param { - TEGRA_XUSB_PADCTL_IDDQ, -}; - -static const struct tegra_xusb_padctl_property { - const char *name; - enum tegra_xusb_padctl_param param; -} properties[] = { - { "nvidia,iddq", TEGRA_XUSB_PADCTL_IDDQ }, -}; - -#define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value)) -#define TEGRA_XUSB_PADCTL_UNPACK_PARAM(config) ((config) >> 16) -#define TEGRA_XUSB_PADCTL_UNPACK_VALUE(config) ((config) & 0xffff) - -static int tegra_xusb_padctl_parse_subnode(struct tegra_xusb_padctl *padctl, - struct device_node *np, - struct pinctrl_map **maps, - unsigned int *reserved_maps, - unsigned int *num_maps) -{ - unsigned int i, reserve = 0, num_configs = 0; - unsigned long config, *configs = NULL; - const char *function, *group; - struct property *prop; - int err = 0; - u32 value; - - err = of_property_read_string(np, "nvidia,function", &function); - if (err < 0) { - if (err != -EINVAL) - return err; - - function = NULL; - } - - for (i = 0; i < ARRAY_SIZE(properties); i++) { - err = of_property_read_u32(np, properties[i].name, &value); - if (err < 0) { - if (err == -EINVAL) - continue; - - goto out; - } - - config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, value); - - err = pinctrl_utils_add_config(padctl->pinctrl, &configs, - &num_configs, config); - if (err < 0) - goto out; - } - - if (function) - reserve++; - - if (num_configs) - reserve++; - - err = of_property_count_strings(np, "nvidia,lanes"); - if (err < 0) - goto out; - - reserve *= err; - - err = pinctrl_utils_reserve_map(padctl->pinctrl, maps, reserved_maps, - num_maps, reserve); - if (err < 0) - goto out; - - of_property_for_each_string(np, "nvidia,lanes", prop, group) { - if (function) { - err = pinctrl_utils_add_map_mux(padctl->pinctrl, maps, - reserved_maps, num_maps, group, - function); - if (err < 0) - goto out; - } - - if (num_configs) { - err = pinctrl_utils_add_map_configs(padctl->pinctrl, - maps, reserved_maps, num_maps, group, - configs, num_configs, - PIN_MAP_TYPE_CONFIGS_GROUP); - if (err < 0) - goto out; - } - } - - err = 0; - -out: - kfree(configs); - return err; -} - -static int tegra_xusb_padctl_dt_node_to_map(struct pinctrl_dev *pinctrl, - struct device_node *parent, - struct pinctrl_map **maps, - unsigned int *num_maps) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - unsigned int reserved_maps = 0; - struct device_node *np; - int err; - - *num_maps = 0; - *maps = NULL; - - for_each_child_of_node(parent, np) { - err = tegra_xusb_padctl_parse_subnode(padctl, np, maps, - &reserved_maps, - num_maps); - if (err < 0) { - of_node_put(np); - return err; - } - } - - return 0; -} - -static const struct pinctrl_ops tegra_xusb_padctl_pinctrl_ops = { - .get_groups_count = tegra_xusb_padctl_get_groups_count, - .get_group_name = tegra_xusb_padctl_get_group_name, - .get_group_pins = tegra_xusb_padctl_get_group_pins, - .dt_node_to_map = tegra_xusb_padctl_dt_node_to_map, - .dt_free_map = pinctrl_utils_dt_free_map, -}; - -static int tegra_xusb_padctl_get_functions_count(struct pinctrl_dev *pinctrl) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - - return padctl->soc->num_functions; -} - -static const char * -tegra_xusb_padctl_get_function_name(struct pinctrl_dev *pinctrl, - unsigned int function) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - - return padctl->soc->functions[function].name; -} - -static int tegra_xusb_padctl_get_function_groups(struct pinctrl_dev *pinctrl, - unsigned int function, - const char * const **groups, - unsigned * const num_groups) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - - *num_groups = padctl->soc->functions[function].num_groups; - *groups = padctl->soc->functions[function].groups; - - return 0; -} - -static int tegra_xusb_padctl_pinmux_set(struct pinctrl_dev *pinctrl, - unsigned int function, - unsigned int group) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - const struct tegra_xusb_padctl_lane *lane; - unsigned int i; - u32 value; - - lane = &padctl->soc->lanes[group]; - - for (i = 0; i < lane->num_funcs; i++) - if (lane->funcs[i] == function) - break; - - if (i >= lane->num_funcs) - return -EINVAL; - - value = padctl_readl(padctl, lane->offset); - value &= ~(lane->mask << lane->shift); - value |= i << lane->shift; - padctl_writel(padctl, value, lane->offset); - - return 0; -} - -static const struct pinmux_ops tegra_xusb_padctl_pinmux_ops = { - .get_functions_count = tegra_xusb_padctl_get_functions_count, - .get_function_name = tegra_xusb_padctl_get_function_name, - .get_function_groups = tegra_xusb_padctl_get_function_groups, - .set_mux = tegra_xusb_padctl_pinmux_set, -}; - -static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl, - unsigned int group, - unsigned long *config) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - const struct tegra_xusb_padctl_lane *lane; - enum tegra_xusb_padctl_param param; - u32 value; - - param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(*config); - lane = &padctl->soc->lanes[group]; - - switch (param) { - case TEGRA_XUSB_PADCTL_IDDQ: - /* lanes with iddq == 0 don't support this parameter */ - if (lane->iddq == 0) - return -EINVAL; - - value = padctl_readl(padctl, lane->offset); - - if (value & BIT(lane->iddq)) - value = 0; - else - value = 1; - - *config = TEGRA_XUSB_PADCTL_PACK(param, value); - break; - - default: - dev_err(padctl->dev, "invalid configuration parameter: %04x\n", - param); - return -ENOTSUPP; - } - - return 0; -} - -static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl, - unsigned int group, - unsigned long *configs, - unsigned int num_configs) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - const struct tegra_xusb_padctl_lane *lane; - enum tegra_xusb_padctl_param param; - unsigned long value; - unsigned int i; - u32 regval; - - lane = &padctl->soc->lanes[group]; - - for (i = 0; i < num_configs; i++) { - param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(configs[i]); - value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(configs[i]); - - switch (param) { - case TEGRA_XUSB_PADCTL_IDDQ: - /* lanes with iddq == 0 don't support this parameter */ - if (lane->iddq == 0) - return -EINVAL; - - regval = padctl_readl(padctl, lane->offset); - - if (value) - regval &= ~BIT(lane->iddq); - else - regval |= BIT(lane->iddq); - - padctl_writel(padctl, regval, lane->offset); - break; - - default: - dev_err(padctl->dev, - "invalid configuration parameter: %04x\n", - param); - return -ENOTSUPP; - } - } - - return 0; -} - -#ifdef CONFIG_DEBUG_FS -static const char *strip_prefix(const char *s) -{ - const char *comma = strchr(s, ','); - if (!comma) - return s; - - return comma + 1; -} - -static void -tegra_xusb_padctl_pinconf_group_dbg_show(struct pinctrl_dev *pinctrl, - struct seq_file *s, - unsigned int group) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(properties); i++) { - unsigned long config, value; - int err; - - config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, 0); - - err = tegra_xusb_padctl_pinconf_group_get(pinctrl, group, - &config); - if (err < 0) - continue; - - value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config); - - seq_printf(s, "\n\t%s=%lu\n", strip_prefix(properties[i].name), - value); - } -} - -static void -tegra_xusb_padctl_pinconf_config_dbg_show(struct pinctrl_dev *pinctrl, - struct seq_file *s, - unsigned long config) -{ - enum tegra_xusb_padctl_param param; - const char *name = "unknown"; - unsigned long value; - unsigned int i; - - param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(config); - value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config); - - for (i = 0; i < ARRAY_SIZE(properties); i++) { - if (properties[i].param == param) { - name = properties[i].name; - break; - } - } - - seq_printf(s, "%s=%lu", strip_prefix(name), value); -} -#endif - -static const struct pinconf_ops tegra_xusb_padctl_pinconf_ops = { - .pin_config_group_get = tegra_xusb_padctl_pinconf_group_get, - .pin_config_group_set = tegra_xusb_padctl_pinconf_group_set, -#ifdef CONFIG_DEBUG_FS - .pin_config_group_dbg_show = tegra_xusb_padctl_pinconf_group_dbg_show, - .pin_config_config_dbg_show = tegra_xusb_padctl_pinconf_config_dbg_show, -#endif -}; - -static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) -{ - u32 value; - - mutex_lock(&padctl->lock); - - if (padctl->enable++ > 0) - goto out; - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - - usleep_range(100, 200); - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - - usleep_range(100, 200); - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - -out: - mutex_unlock(&padctl->lock); - return 0; -} - -static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) -{ - u32 value; - - mutex_lock(&padctl->lock); - - if (WARN_ON(padctl->enable == 0)) - goto out; - - if (--padctl->enable > 0) - goto out; - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - - usleep_range(100, 200); - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - - usleep_range(100, 200); - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - -out: - mutex_unlock(&padctl->lock); - return 0; -} - -static int tegra_xusb_phy_init(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - - return tegra_xusb_padctl_enable(padctl); -} - -static int tegra_xusb_phy_exit(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - - return tegra_xusb_padctl_disable(padctl); -} - -static int pcie_phy_power_on(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - unsigned long timeout; - int err = -ETIMEDOUT; - u32 value; - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); - value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN | - XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN | - XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - - timeout = jiffies + msecs_to_jiffies(50); - - while (time_before(jiffies, timeout)) { - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) { - err = 0; - break; - } - - usleep_range(100, 200); - } - - return err; -} - -static int pcie_phy_power_off(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - u32 value; - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - - return 0; -} - -static const struct phy_ops pcie_phy_ops = { - .init = tegra_xusb_phy_init, - .exit = tegra_xusb_phy_exit, - .power_on = pcie_phy_power_on, - .power_off = pcie_phy_power_off, - .owner = THIS_MODULE, -}; - -static int sata_phy_power_on(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - unsigned long timeout; - int err = -ETIMEDOUT; - u32 value; - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; - value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; - value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - timeout = jiffies + msecs_to_jiffies(50); - - while (time_before(jiffies, timeout)) { - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) { - err = 0; - break; - } - - usleep_range(100, 200); - } - - return err; -} - -static int sata_phy_power_off(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - u32 value; - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; - value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); - value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; - value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); - - return 0; -} - -static const struct phy_ops sata_phy_ops = { - .init = tegra_xusb_phy_init, - .exit = tegra_xusb_phy_exit, - .power_on = sata_phy_power_on, - .power_off = sata_phy_power_off, - .owner = THIS_MODULE, -}; - -static struct phy *tegra_xusb_padctl_xlate(struct device *dev, - struct of_phandle_args *args) -{ - struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev); - unsigned int index = args->args[0]; - - if (args->args_count <= 0) - return ERR_PTR(-EINVAL); - - if (index >= ARRAY_SIZE(padctl->phys)) - return ERR_PTR(-EINVAL); - - return padctl->phys[index]; -} - -#define PIN_OTG_0 0 -#define PIN_OTG_1 1 -#define PIN_OTG_2 2 -#define PIN_ULPI_0 3 -#define PIN_HSIC_0 4 -#define PIN_HSIC_1 5 -#define PIN_PCIE_0 6 -#define PIN_PCIE_1 7 -#define PIN_PCIE_2 8 -#define PIN_PCIE_3 9 -#define PIN_PCIE_4 10 -#define PIN_SATA_0 11 - -static const struct pinctrl_pin_desc tegra124_pins[] = { - PINCTRL_PIN(PIN_OTG_0, "otg-0"), - PINCTRL_PIN(PIN_OTG_1, "otg-1"), - PINCTRL_PIN(PIN_OTG_2, "otg-2"), - PINCTRL_PIN(PIN_ULPI_0, "ulpi-0"), - PINCTRL_PIN(PIN_HSIC_0, "hsic-0"), - PINCTRL_PIN(PIN_HSIC_1, "hsic-1"), - PINCTRL_PIN(PIN_PCIE_0, "pcie-0"), - PINCTRL_PIN(PIN_PCIE_1, "pcie-1"), - PINCTRL_PIN(PIN_PCIE_2, "pcie-2"), - PINCTRL_PIN(PIN_PCIE_3, "pcie-3"), - PINCTRL_PIN(PIN_PCIE_4, "pcie-4"), - PINCTRL_PIN(PIN_SATA_0, "sata-0"), -}; - -static const char * const tegra124_snps_groups[] = { - "otg-0", - "otg-1", - "otg-2", - "ulpi-0", - "hsic-0", - "hsic-1", -}; - -static const char * const tegra124_xusb_groups[] = { - "otg-0", - "otg-1", - "otg-2", - "ulpi-0", - "hsic-0", - "hsic-1", -}; - -static const char * const tegra124_uart_groups[] = { - "otg-0", - "otg-1", - "otg-2", -}; - -static const char * const tegra124_pcie_groups[] = { - "pcie-0", - "pcie-1", - "pcie-2", - "pcie-3", - "pcie-4", -}; - -static const char * const tegra124_usb3_groups[] = { - "pcie-0", - "pcie-1", - "sata-0", -}; - -static const char * const tegra124_sata_groups[] = { - "sata-0", -}; - -static const char * const tegra124_rsvd_groups[] = { - "otg-0", - "otg-1", - "otg-2", - "pcie-0", - "pcie-1", - "pcie-2", - "pcie-3", - "pcie-4", - "sata-0", -}; - -#define TEGRA124_FUNCTION(_name) \ - { \ - .name = #_name, \ - .num_groups = ARRAY_SIZE(tegra124_##_name##_groups), \ - .groups = tegra124_##_name##_groups, \ - } - -static struct tegra_xusb_padctl_function tegra124_functions[] = { - TEGRA124_FUNCTION(snps), - TEGRA124_FUNCTION(xusb), - TEGRA124_FUNCTION(uart), - TEGRA124_FUNCTION(pcie), - TEGRA124_FUNCTION(usb3), - TEGRA124_FUNCTION(sata), - TEGRA124_FUNCTION(rsvd), -}; - -enum tegra124_function { - TEGRA124_FUNC_SNPS, - TEGRA124_FUNC_XUSB, - TEGRA124_FUNC_UART, - TEGRA124_FUNC_PCIE, - TEGRA124_FUNC_USB3, - TEGRA124_FUNC_SATA, - TEGRA124_FUNC_RSVD, -}; - -static const unsigned int tegra124_otg_functions[] = { - TEGRA124_FUNC_SNPS, - TEGRA124_FUNC_XUSB, - TEGRA124_FUNC_UART, - TEGRA124_FUNC_RSVD, -}; - -static const unsigned int tegra124_usb_functions[] = { - TEGRA124_FUNC_SNPS, - TEGRA124_FUNC_XUSB, -}; - -static const unsigned int tegra124_pci_functions[] = { - TEGRA124_FUNC_PCIE, - TEGRA124_FUNC_USB3, - TEGRA124_FUNC_SATA, - TEGRA124_FUNC_RSVD, -}; - -#define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs) \ - { \ - .name = _name, \ - .offset = _offset, \ - .shift = _shift, \ - .mask = _mask, \ - .iddq = _iddq, \ - .num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions), \ - .funcs = tegra124_##_funcs##_functions, \ - } - -static const struct tegra_xusb_padctl_lane tegra124_lanes[] = { - TEGRA124_LANE("otg-0", 0x004, 0, 0x3, 0, otg), - TEGRA124_LANE("otg-1", 0x004, 2, 0x3, 0, otg), - TEGRA124_LANE("otg-2", 0x004, 4, 0x3, 0, otg), - TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb), - TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb), - TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb), - TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci), - TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci), - TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci), - TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci), - TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci), - TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci), -}; - -static const struct tegra_xusb_padctl_soc tegra124_soc = { - .num_pins = ARRAY_SIZE(tegra124_pins), - .pins = tegra124_pins, - .num_functions = ARRAY_SIZE(tegra124_functions), - .functions = tegra124_functions, - .num_lanes = ARRAY_SIZE(tegra124_lanes), - .lanes = tegra124_lanes, -}; - -static const struct of_device_id tegra_xusb_padctl_of_match[] = { - { .compatible = "nvidia,tegra124-xusb-padctl", .data = &tegra124_soc }, - { } -}; -MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match); - -static int tegra_xusb_padctl_probe(struct platform_device *pdev) -{ - struct tegra_xusb_padctl *padctl; - const struct of_device_id *match; - struct resource *res; - struct phy *phy; - int err; - - padctl = devm_kzalloc(&pdev->dev, sizeof(*padctl), GFP_KERNEL); - if (!padctl) - return -ENOMEM; - - platform_set_drvdata(pdev, padctl); - mutex_init(&padctl->lock); - padctl->dev = &pdev->dev; - - match = of_match_node(tegra_xusb_padctl_of_match, pdev->dev.of_node); - padctl->soc = match->data; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - padctl->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(padctl->regs)) - return PTR_ERR(padctl->regs); - - padctl->rst = devm_reset_control_get(&pdev->dev, NULL); - if (IS_ERR(padctl->rst)) - return PTR_ERR(padctl->rst); - - err = reset_control_deassert(padctl->rst); - if (err < 0) - return err; - - memset(&padctl->desc, 0, sizeof(padctl->desc)); - padctl->desc.name = dev_name(padctl->dev); - padctl->desc.pins = tegra124_pins; - padctl->desc.npins = ARRAY_SIZE(tegra124_pins); - padctl->desc.pctlops = &tegra_xusb_padctl_pinctrl_ops; - padctl->desc.pmxops = &tegra_xusb_padctl_pinmux_ops; - padctl->desc.confops = &tegra_xusb_padctl_pinconf_ops; - padctl->desc.owner = THIS_MODULE; - - padctl->pinctrl = pinctrl_register(&padctl->desc, &pdev->dev, padctl); - if (IS_ERR(padctl->pinctrl)) { - dev_err(&pdev->dev, "failed to register pincontrol\n"); - err = PTR_ERR(padctl->pinctrl); - goto reset; - } - - phy = devm_phy_create(&pdev->dev, NULL, &pcie_phy_ops); - if (IS_ERR(phy)) { - err = PTR_ERR(phy); - goto unregister; - } - - padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy; - phy_set_drvdata(phy, padctl); - - phy = devm_phy_create(&pdev->dev, NULL, &sata_phy_ops); - if (IS_ERR(phy)) { - err = PTR_ERR(phy); - goto unregister; - } - - padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy; - phy_set_drvdata(phy, padctl); - - padctl->provider = devm_of_phy_provider_register(&pdev->dev, - tegra_xusb_padctl_xlate); - if (IS_ERR(padctl->provider)) { - err = PTR_ERR(padctl->provider); - dev_err(&pdev->dev, "failed to register PHYs: %d\n", err); - goto unregister; - } - - return 0; - -unregister: - pinctrl_unregister(padctl->pinctrl); -reset: - reset_control_assert(padctl->rst); - return err; -} - -static int tegra_xusb_padctl_remove(struct platform_device *pdev) -{ - struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev); - int err; - - pinctrl_unregister(padctl->pinctrl); - - err = reset_control_assert(padctl->rst); - if (err < 0) - dev_err(&pdev->dev, "failed to assert reset: %d\n", err); - - return err; -} - -static struct platform_driver tegra_xusb_padctl_driver = { - .driver = { - .name = "tegra-xusb-padctl", - .of_match_table = tegra_xusb_padctl_of_match, - }, - .probe = tegra_xusb_padctl_probe, - .remove = tegra_xusb_padctl_remove, -}; -module_platform_driver(tegra_xusb_padctl_driver); - -MODULE_AUTHOR("Thierry Reding "); -MODULE_DESCRIPTION("Tegra 124 XUSB Pad Control driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c deleted file mode 100644 index 9da4da219a07..000000000000 --- a/drivers/pinctrl/pinctrl-tegra.c +++ /dev/null @@ -1,747 +0,0 @@ -/* - * Driver for the NVIDIA Tegra pinmux - * - * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. - * - * Derived from code: - * Copyright (C) 2010 Google, Inc. - * Copyright (C) 2010 NVIDIA Corporation - * Copyright (C) 2009-2011 ST-Ericsson AB - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "core.h" -#include "pinctrl-tegra.h" -#include "pinctrl-utils.h" - -struct tegra_pmx { - struct device *dev; - struct pinctrl_dev *pctl; - - const struct tegra_pinctrl_soc_data *soc; - const char **group_pins; - - int nbanks; - void __iomem **regs; -}; - -static inline u32 pmx_readl(struct tegra_pmx *pmx, u32 bank, u32 reg) -{ - return readl(pmx->regs[bank] + reg); -} - -static inline void pmx_writel(struct tegra_pmx *pmx, u32 val, u32 bank, u32 reg) -{ - writel(val, pmx->regs[bank] + reg); -} - -static int tegra_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - - return pmx->soc->ngroups; -} - -static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev, - unsigned group) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - - return pmx->soc->groups[group].name; -} - -static int tegra_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, - unsigned group, - const unsigned **pins, - unsigned *num_pins) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - - *pins = pmx->soc->groups[group].pins; - *num_pins = pmx->soc->groups[group].npins; - - return 0; -} - -#ifdef CONFIG_DEBUG_FS -static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev, - struct seq_file *s, - unsigned offset) -{ - seq_printf(s, " %s", dev_name(pctldev->dev)); -} -#endif - -static const struct cfg_param { - const char *property; - enum tegra_pinconf_param param; -} cfg_params[] = { - {"nvidia,pull", TEGRA_PINCONF_PARAM_PULL}, - {"nvidia,tristate", TEGRA_PINCONF_PARAM_TRISTATE}, - {"nvidia,enable-input", TEGRA_PINCONF_PARAM_ENABLE_INPUT}, - {"nvidia,open-drain", TEGRA_PINCONF_PARAM_OPEN_DRAIN}, - {"nvidia,lock", TEGRA_PINCONF_PARAM_LOCK}, - {"nvidia,io-reset", TEGRA_PINCONF_PARAM_IORESET}, - {"nvidia,rcv-sel", TEGRA_PINCONF_PARAM_RCV_SEL}, - {"nvidia,io-hv", TEGRA_PINCONF_PARAM_RCV_SEL}, - {"nvidia,high-speed-mode", TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE}, - {"nvidia,schmitt", TEGRA_PINCONF_PARAM_SCHMITT}, - {"nvidia,low-power-mode", TEGRA_PINCONF_PARAM_LOW_POWER_MODE}, - {"nvidia,pull-down-strength", TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH}, - {"nvidia,pull-up-strength", TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH}, - {"nvidia,slew-rate-falling", TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING}, - {"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING}, - {"nvidia,drive-type", TEGRA_PINCONF_PARAM_DRIVE_TYPE}, -}; - -static int tegra_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, - struct device_node *np, - struct pinctrl_map **map, - unsigned *reserved_maps, - unsigned *num_maps) -{ - struct device *dev = pctldev->dev; - int ret, i; - const char *function; - u32 val; - unsigned long config; - unsigned long *configs = NULL; - unsigned num_configs = 0; - unsigned reserve; - struct property *prop; - const char *group; - - ret = of_property_read_string(np, "nvidia,function", &function); - if (ret < 0) { - /* EINVAL=missing, which is fine since it's optional */ - if (ret != -EINVAL) - dev_err(dev, - "could not parse property nvidia,function\n"); - function = NULL; - } - - for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { - ret = of_property_read_u32(np, cfg_params[i].property, &val); - if (!ret) { - config = TEGRA_PINCONF_PACK(cfg_params[i].param, val); - ret = pinctrl_utils_add_config(pctldev, &configs, - &num_configs, config); - if (ret < 0) - goto exit; - /* EINVAL=missing, which is fine since it's optional */ - } else if (ret != -EINVAL) { - dev_err(dev, "could not parse property %s\n", - cfg_params[i].property); - } - } - - reserve = 0; - if (function != NULL) - reserve++; - if (num_configs) - reserve++; - ret = of_property_count_strings(np, "nvidia,pins"); - if (ret < 0) { - dev_err(dev, "could not parse property nvidia,pins\n"); - goto exit; - } - reserve *= ret; - - ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, - num_maps, reserve); - if (ret < 0) - goto exit; - - of_property_for_each_string(np, "nvidia,pins", prop, group) { - if (function) { - ret = pinctrl_utils_add_map_mux(pctldev, map, - reserved_maps, num_maps, group, - function); - if (ret < 0) - goto exit; - } - - if (num_configs) { - ret = pinctrl_utils_add_map_configs(pctldev, map, - reserved_maps, num_maps, group, - configs, num_configs, - PIN_MAP_TYPE_CONFIGS_GROUP); - if (ret < 0) - goto exit; - } - } - - ret = 0; - -exit: - kfree(configs); - return ret; -} - -static int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, - struct device_node *np_config, - struct pinctrl_map **map, - unsigned *num_maps) -{ - unsigned reserved_maps; - struct device_node *np; - int ret; - - reserved_maps = 0; - *map = NULL; - *num_maps = 0; - - for_each_child_of_node(np_config, np) { - ret = tegra_pinctrl_dt_subnode_to_map(pctldev, np, map, - &reserved_maps, num_maps); - if (ret < 0) { - pinctrl_utils_dt_free_map(pctldev, *map, - *num_maps); - of_node_put(np); - return ret; - } - } - - return 0; -} - -static const struct pinctrl_ops tegra_pinctrl_ops = { - .get_groups_count = tegra_pinctrl_get_groups_count, - .get_group_name = tegra_pinctrl_get_group_name, - .get_group_pins = tegra_pinctrl_get_group_pins, -#ifdef CONFIG_DEBUG_FS - .pin_dbg_show = tegra_pinctrl_pin_dbg_show, -#endif - .dt_node_to_map = tegra_pinctrl_dt_node_to_map, - .dt_free_map = pinctrl_utils_dt_free_map, -}; - -static int tegra_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - - return pmx->soc->nfunctions; -} - -static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev, - unsigned function) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - - return pmx->soc->functions[function].name; -} - -static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, - unsigned function, - const char * const **groups, - unsigned * const num_groups) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - - *groups = pmx->soc->functions[function].groups; - *num_groups = pmx->soc->functions[function].ngroups; - - return 0; -} - -static int tegra_pinctrl_set_mux(struct pinctrl_dev *pctldev, - unsigned function, - unsigned group) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - const struct tegra_pingroup *g; - int i; - u32 val; - - g = &pmx->soc->groups[group]; - - if (WARN_ON(g->mux_reg < 0)) - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(g->funcs); i++) { - if (g->funcs[i] == function) - break; - } - if (WARN_ON(i == ARRAY_SIZE(g->funcs))) - return -EINVAL; - - val = pmx_readl(pmx, g->mux_bank, g->mux_reg); - val &= ~(0x3 << g->mux_bit); - val |= i << g->mux_bit; - pmx_writel(pmx, val, g->mux_bank, g->mux_reg); - - return 0; -} - -static const struct pinmux_ops tegra_pinmux_ops = { - .get_functions_count = tegra_pinctrl_get_funcs_count, - .get_function_name = tegra_pinctrl_get_func_name, - .get_function_groups = tegra_pinctrl_get_func_groups, - .set_mux = tegra_pinctrl_set_mux, -}; - -static int tegra_pinconf_reg(struct tegra_pmx *pmx, - const struct tegra_pingroup *g, - enum tegra_pinconf_param param, - bool report_err, - s8 *bank, s16 *reg, s8 *bit, s8 *width) -{ - switch (param) { - case TEGRA_PINCONF_PARAM_PULL: - *bank = g->pupd_bank; - *reg = g->pupd_reg; - *bit = g->pupd_bit; - *width = 2; - break; - case TEGRA_PINCONF_PARAM_TRISTATE: - *bank = g->tri_bank; - *reg = g->tri_reg; - *bit = g->tri_bit; - *width = 1; - break; - case TEGRA_PINCONF_PARAM_ENABLE_INPUT: - *bank = g->mux_bank; - *reg = g->mux_reg; - *bit = g->einput_bit; - *width = 1; - break; - case TEGRA_PINCONF_PARAM_OPEN_DRAIN: - *bank = g->mux_bank; - *reg = g->mux_reg; - *bit = g->odrain_bit; - *width = 1; - break; - case TEGRA_PINCONF_PARAM_LOCK: - *bank = g->mux_bank; - *reg = g->mux_reg; - *bit = g->lock_bit; - *width = 1; - break; - case TEGRA_PINCONF_PARAM_IORESET: - *bank = g->mux_bank; - *reg = g->mux_reg; - *bit = g->ioreset_bit; - *width = 1; - break; - case TEGRA_PINCONF_PARAM_RCV_SEL: - *bank = g->mux_bank; - *reg = g->mux_reg; - *bit = g->rcv_sel_bit; - *width = 1; - break; - case TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE: - if (pmx->soc->hsm_in_mux) { - *bank = g->mux_bank; - *reg = g->mux_reg; - } else { - *bank = g->drv_bank; - *reg = g->drv_reg; - } - *bit = g->hsm_bit; - *width = 1; - break; - case TEGRA_PINCONF_PARAM_SCHMITT: - if (pmx->soc->schmitt_in_mux) { - *bank = g->mux_bank; - *reg = g->mux_reg; - } else { - *bank = g->drv_bank; - *reg = g->drv_reg; - } - *bit = g->schmitt_bit; - *width = 1; - break; - case TEGRA_PINCONF_PARAM_LOW_POWER_MODE: - *bank = g->drv_bank; - *reg = g->drv_reg; - *bit = g->lpmd_bit; - *width = 2; - break; - case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH: - *bank = g->drv_bank; - *reg = g->drv_reg; - *bit = g->drvdn_bit; - *width = g->drvdn_width; - break; - case TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH: - *bank = g->drv_bank; - *reg = g->drv_reg; - *bit = g->drvup_bit; - *width = g->drvup_width; - break; - case TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING: - *bank = g->drv_bank; - *reg = g->drv_reg; - *bit = g->slwf_bit; - *width = g->slwf_width; - break; - case TEGRA_PINCONF_PARAM_SLEW_RATE_RISING: - *bank = g->drv_bank; - *reg = g->drv_reg; - *bit = g->slwr_bit; - *width = g->slwr_width; - break; - case TEGRA_PINCONF_PARAM_DRIVE_TYPE: - if (pmx->soc->drvtype_in_mux) { - *bank = g->mux_bank; - *reg = g->mux_reg; - } else { - *bank = g->drv_bank; - *reg = g->drv_reg; - } - *bit = g->drvtype_bit; - *width = 2; - break; - default: - dev_err(pmx->dev, "Invalid config param %04x\n", param); - return -ENOTSUPP; - } - - if (*reg < 0 || *bit > 31) { - if (report_err) { - const char *prop = "unknown"; - int i; - - for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { - if (cfg_params[i].param == param) { - prop = cfg_params[i].property; - break; - } - } - - dev_err(pmx->dev, - "Config param %04x (%s) not supported on group %s\n", - param, prop, g->name); - } - return -ENOTSUPP; - } - - return 0; -} - -static int tegra_pinconf_get(struct pinctrl_dev *pctldev, - unsigned pin, unsigned long *config) -{ - dev_err(pctldev->dev, "pin_config_get op not supported\n"); - return -ENOTSUPP; -} - -static int tegra_pinconf_set(struct pinctrl_dev *pctldev, - unsigned pin, unsigned long *configs, - unsigned num_configs) -{ - dev_err(pctldev->dev, "pin_config_set op not supported\n"); - return -ENOTSUPP; -} - -static int tegra_pinconf_group_get(struct pinctrl_dev *pctldev, - unsigned group, unsigned long *config) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(*config); - u16 arg; - const struct tegra_pingroup *g; - int ret; - s8 bank, bit, width; - s16 reg; - u32 val, mask; - - g = &pmx->soc->groups[group]; - - ret = tegra_pinconf_reg(pmx, g, param, true, &bank, ®, &bit, - &width); - if (ret < 0) - return ret; - - val = pmx_readl(pmx, bank, reg); - mask = (1 << width) - 1; - arg = (val >> bit) & mask; - - *config = TEGRA_PINCONF_PACK(param, arg); - - return 0; -} - -static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev, - unsigned group, unsigned long *configs, - unsigned num_configs) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - enum tegra_pinconf_param param; - u16 arg; - const struct tegra_pingroup *g; - int ret, i; - s8 bank, bit, width; - s16 reg; - u32 val, mask; - - g = &pmx->soc->groups[group]; - - for (i = 0; i < num_configs; i++) { - param = TEGRA_PINCONF_UNPACK_PARAM(configs[i]); - arg = TEGRA_PINCONF_UNPACK_ARG(configs[i]); - - ret = tegra_pinconf_reg(pmx, g, param, true, &bank, ®, &bit, - &width); - if (ret < 0) - return ret; - - val = pmx_readl(pmx, bank, reg); - - /* LOCK can't be cleared */ - if (param == TEGRA_PINCONF_PARAM_LOCK) { - if ((val & BIT(bit)) && !arg) { - dev_err(pctldev->dev, "LOCK bit cannot be cleared\n"); - return -EINVAL; - } - } - - /* Special-case Boolean values; allow any non-zero as true */ - if (width == 1) - arg = !!arg; - - /* Range-check user-supplied value */ - mask = (1 << width) - 1; - if (arg & ~mask) { - dev_err(pctldev->dev, - "config %lx: %x too big for %d bit register\n", - configs[i], arg, width); - return -EINVAL; - } - - /* Update register */ - val &= ~(mask << bit); - val |= arg << bit; - pmx_writel(pmx, val, bank, reg); - } /* for each config */ - - return 0; -} - -#ifdef CONFIG_DEBUG_FS -static void tegra_pinconf_dbg_show(struct pinctrl_dev *pctldev, - struct seq_file *s, unsigned offset) -{ -} - -static const char *strip_prefix(const char *s) -{ - const char *comma = strchr(s, ','); - if (!comma) - return s; - - return comma + 1; -} - -static void tegra_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, - struct seq_file *s, unsigned group) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - const struct tegra_pingroup *g; - int i, ret; - s8 bank, bit, width; - s16 reg; - u32 val; - - g = &pmx->soc->groups[group]; - - for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { - ret = tegra_pinconf_reg(pmx, g, cfg_params[i].param, false, - &bank, ®, &bit, &width); - if (ret < 0) - continue; - - val = pmx_readl(pmx, bank, reg); - val >>= bit; - val &= (1 << width) - 1; - - seq_printf(s, "\n\t%s=%u", - strip_prefix(cfg_params[i].property), val); - } -} - -static void tegra_pinconf_config_dbg_show(struct pinctrl_dev *pctldev, - struct seq_file *s, - unsigned long config) -{ - enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(config); - u16 arg = TEGRA_PINCONF_UNPACK_ARG(config); - const char *pname = "unknown"; - int i; - - for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { - if (cfg_params[i].param == param) { - pname = cfg_params[i].property; - break; - } - } - - seq_printf(s, "%s=%d", strip_prefix(pname), arg); -} -#endif - -static const struct pinconf_ops tegra_pinconf_ops = { - .pin_config_get = tegra_pinconf_get, - .pin_config_set = tegra_pinconf_set, - .pin_config_group_get = tegra_pinconf_group_get, - .pin_config_group_set = tegra_pinconf_group_set, -#ifdef CONFIG_DEBUG_FS - .pin_config_dbg_show = tegra_pinconf_dbg_show, - .pin_config_group_dbg_show = tegra_pinconf_group_dbg_show, - .pin_config_config_dbg_show = tegra_pinconf_config_dbg_show, -#endif -}; - -static struct pinctrl_gpio_range tegra_pinctrl_gpio_range = { - .name = "Tegra GPIOs", - .id = 0, - .base = 0, -}; - -static struct pinctrl_desc tegra_pinctrl_desc = { - .pctlops = &tegra_pinctrl_ops, - .pmxops = &tegra_pinmux_ops, - .confops = &tegra_pinconf_ops, - .owner = THIS_MODULE, -}; - -static bool gpio_node_has_range(void) -{ - struct device_node *np; - bool has_prop = false; - - np = of_find_compatible_node(NULL, NULL, "nvidia,tegra30-gpio"); - if (!np) - return has_prop; - - has_prop = of_find_property(np, "gpio-ranges", NULL); - - of_node_put(np); - - return has_prop; -} - -int tegra_pinctrl_probe(struct platform_device *pdev, - const struct tegra_pinctrl_soc_data *soc_data) -{ - struct tegra_pmx *pmx; - struct resource *res; - int i; - const char **group_pins; - int fn, gn, gfn; - - pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL); - if (!pmx) { - dev_err(&pdev->dev, "Can't alloc tegra_pmx\n"); - return -ENOMEM; - } - pmx->dev = &pdev->dev; - pmx->soc = soc_data; - - /* - * Each mux group will appear in 4 functions' list of groups. - * This over-allocates slightly, since not all groups are mux groups. - */ - pmx->group_pins = devm_kzalloc(&pdev->dev, - soc_data->ngroups * 4 * sizeof(*pmx->group_pins), - GFP_KERNEL); - if (!pmx->group_pins) - return -ENOMEM; - - group_pins = pmx->group_pins; - for (fn = 0; fn < soc_data->nfunctions; fn++) { - struct tegra_function *func = &soc_data->functions[fn]; - - func->groups = group_pins; - - for (gn = 0; gn < soc_data->ngroups; gn++) { - const struct tegra_pingroup *g = &soc_data->groups[gn]; - - if (g->mux_reg == -1) - continue; - - for (gfn = 0; gfn < 4; gfn++) - if (g->funcs[gfn] == fn) - break; - if (gfn == 4) - continue; - - BUG_ON(group_pins - pmx->group_pins >= - soc_data->ngroups * 4); - *group_pins++ = g->name; - func->ngroups++; - } - } - - tegra_pinctrl_gpio_range.npins = pmx->soc->ngpios; - tegra_pinctrl_desc.name = dev_name(&pdev->dev); - tegra_pinctrl_desc.pins = pmx->soc->pins; - tegra_pinctrl_desc.npins = pmx->soc->npins; - - for (i = 0; ; i++) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - if (!res) - break; - } - pmx->nbanks = i; - - pmx->regs = devm_kzalloc(&pdev->dev, pmx->nbanks * sizeof(*pmx->regs), - GFP_KERNEL); - if (!pmx->regs) { - dev_err(&pdev->dev, "Can't alloc regs pointer\n"); - return -ENOMEM; - } - - for (i = 0; i < pmx->nbanks; i++) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - pmx->regs[i] = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(pmx->regs[i])) - return PTR_ERR(pmx->regs[i]); - } - - pmx->pctl = pinctrl_register(&tegra_pinctrl_desc, &pdev->dev, pmx); - if (IS_ERR(pmx->pctl)) { - dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); - return PTR_ERR(pmx->pctl); - } - - if (!gpio_node_has_range()) - pinctrl_add_gpio_range(pmx->pctl, &tegra_pinctrl_gpio_range); - - platform_set_drvdata(pdev, pmx); - - dev_dbg(&pdev->dev, "Probed Tegra pinctrl driver\n"); - - return 0; -} -EXPORT_SYMBOL_GPL(tegra_pinctrl_probe); - -int tegra_pinctrl_remove(struct platform_device *pdev) -{ - struct tegra_pmx *pmx = platform_get_drvdata(pdev); - - pinctrl_unregister(pmx->pctl); - - return 0; -} -EXPORT_SYMBOL_GPL(tegra_pinctrl_remove); diff --git a/drivers/pinctrl/pinctrl-tegra.h b/drivers/pinctrl/pinctrl-tegra.h deleted file mode 100644 index 1615db7e3a4b..000000000000 --- a/drivers/pinctrl/pinctrl-tegra.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Driver for the NVIDIA Tegra pinmux - * - * Copyright (c) 2011, NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - */ - -#ifndef __PINMUX_TEGRA_H__ -#define __PINMUX_TEGRA_H__ - -enum tegra_pinconf_param { - /* argument: tegra_pinconf_pull */ - TEGRA_PINCONF_PARAM_PULL, - /* argument: tegra_pinconf_tristate */ - TEGRA_PINCONF_PARAM_TRISTATE, - /* argument: Boolean */ - TEGRA_PINCONF_PARAM_ENABLE_INPUT, - /* argument: Boolean */ - TEGRA_PINCONF_PARAM_OPEN_DRAIN, - /* argument: Boolean */ - TEGRA_PINCONF_PARAM_LOCK, - /* argument: Boolean */ - TEGRA_PINCONF_PARAM_IORESET, - /* argument: Boolean */ - TEGRA_PINCONF_PARAM_RCV_SEL, - /* argument: Boolean */ - TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE, - /* argument: Boolean */ - TEGRA_PINCONF_PARAM_SCHMITT, - /* argument: Boolean */ - TEGRA_PINCONF_PARAM_LOW_POWER_MODE, - /* argument: Integer, range is HW-dependant */ - TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH, - /* argument: Integer, range is HW-dependant */ - TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH, - /* argument: Integer, range is HW-dependant */ - TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING, - /* argument: Integer, range is HW-dependant */ - TEGRA_PINCONF_PARAM_SLEW_RATE_RISING, - /* argument: Integer, range is HW-dependant */ - TEGRA_PINCONF_PARAM_DRIVE_TYPE, -}; - -enum tegra_pinconf_pull { - TEGRA_PINCONFIG_PULL_NONE, - TEGRA_PINCONFIG_PULL_DOWN, - TEGRA_PINCONFIG_PULL_UP, -}; - -enum tegra_pinconf_tristate { - TEGRA_PINCONFIG_DRIVEN, - TEGRA_PINCONFIG_TRISTATE, -}; - -#define TEGRA_PINCONF_PACK(_param_, _arg_) ((_param_) << 16 | (_arg_)) -#define TEGRA_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16) -#define TEGRA_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff) - -/** - * struct tegra_function - Tegra pinctrl mux function - * @name: The name of the function, exported to pinctrl core. - * @groups: An array of pin groups that may select this function. - * @ngroups: The number of entries in @groups. - */ -struct tegra_function { - const char *name; - const char **groups; - unsigned ngroups; -}; - -/** - * struct tegra_pingroup - Tegra pin group - * @name The name of the pin group. - * @pins An array of pin IDs included in this pin group. - * @npins The number of entries in @pins. - * @funcs The mux functions which can be muxed onto this group. - * @mux_reg: Mux register offset. - * This register contains the mux, einput, odrain, lock, - * ioreset, rcv_sel parameters. - * @mux_bank: Mux register bank. - * @mux_bit: Mux register bit. - * @pupd_reg: Pull-up/down register offset. - * @pupd_bank: Pull-up/down register bank. - * @pupd_bit: Pull-up/down register bit. - * @tri_reg: Tri-state register offset. - * @tri_bank: Tri-state register bank. - * @tri_bit: Tri-state register bit. - * @einput_bit: Enable-input register bit. - * @odrain_bit: Open-drain register bit. - * @lock_bit: Lock register bit. - * @ioreset_bit: IO reset register bit. - * @rcv_sel_bit: Receiver select bit. - * @drv_reg: Drive fields register offset. - * This register contains hsm, schmitt, lpmd, drvdn, - * drvup, slwr, slwf, and drvtype parameters. - * @drv_bank: Drive fields register bank. - * @hsm_bit: High Speed Mode register bit. - * @schmitt_bit: Scmitt register bit. - * @lpmd_bit: Low Power Mode register bit. - * @drvdn_bit: Drive Down register bit. - * @drvdn_width: Drive Down field width. - * @drvup_bit: Drive Up register bit. - * @drvup_width: Drive Up field width. - * @slwr_bit: Slew Rising register bit. - * @slwr_width: Slew Rising field width. - * @slwf_bit: Slew Falling register bit. - * @slwf_width: Slew Falling field width. - * @drvtype_bit: Drive type register bit. - * - * -1 in a *_reg field means that feature is unsupported for this group. - * *_bank and *_reg values are irrelevant when *_reg is -1. - * When *_reg is valid, *_bit may be -1 to indicate an unsupported feature. - * - * A representation of a group of pins (possibly just one pin) in the Tegra - * pin controller. Each group allows some parameter or parameters to be - * configured. The most common is mux function selection. Many others exist - * such as pull-up/down, tri-state, etc. Tegra's pin controller is complex; - * certain groups may only support configuring certain parameters, hence - * each parameter is optional. - */ -struct tegra_pingroup { - const char *name; - const unsigned *pins; - u8 npins; - u8 funcs[4]; - s16 mux_reg; - s16 pupd_reg; - s16 tri_reg; - s16 drv_reg; - u32 mux_bank:2; - u32 pupd_bank:2; - u32 tri_bank:2; - u32 drv_bank:2; - s32 mux_bit:6; - s32 pupd_bit:6; - s32 tri_bit:6; - s32 einput_bit:6; - s32 odrain_bit:6; - s32 lock_bit:6; - s32 ioreset_bit:6; - s32 rcv_sel_bit:6; - s32 hsm_bit:6; - s32 schmitt_bit:6; - s32 lpmd_bit:6; - s32 drvdn_bit:6; - s32 drvup_bit:6; - s32 slwr_bit:6; - s32 slwf_bit:6; - s32 drvtype_bit:6; - s32 drvdn_width:6; - s32 drvup_width:6; - s32 slwr_width:6; - s32 slwf_width:6; -}; - -/** - * struct tegra_pinctrl_soc_data - Tegra pin controller driver configuration - * @ngpios: The number of GPIO pins the pin controller HW affects. - * @pins: An array describing all pins the pin controller affects. - * All pins which are also GPIOs must be listed first within the - * array, and be numbered identically to the GPIO controller's - * numbering. - * @npins: The numbmer of entries in @pins. - * @functions: An array describing all mux functions the SoC supports. - * @nfunctions: The numbmer of entries in @functions. - * @groups: An array describing all pin groups the pin SoC supports. - * @ngroups: The numbmer of entries in @groups. - */ -struct tegra_pinctrl_soc_data { - unsigned ngpios; - const struct pinctrl_pin_desc *pins; - unsigned npins; - struct tegra_function *functions; - unsigned nfunctions; - const struct tegra_pingroup *groups; - unsigned ngroups; - bool hsm_in_mux; - bool schmitt_in_mux; - bool drvtype_in_mux; -}; - -int tegra_pinctrl_probe(struct platform_device *pdev, - const struct tegra_pinctrl_soc_data *soc_data); -int tegra_pinctrl_remove(struct platform_device *pdev); - -#endif diff --git a/drivers/pinctrl/pinctrl-tegra114.c b/drivers/pinctrl/pinctrl-tegra114.c deleted file mode 100644 index 05e49d5137ab..000000000000 --- a/drivers/pinctrl/pinctrl-tegra114.c +++ /dev/null @@ -1,1872 +0,0 @@ -/* - * Pinctrl data for the NVIDIA Tegra114 pinmux - * - * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - */ - -#include -#include -#include -#include -#include - -#include "pinctrl-tegra.h" - -/* - * Most pins affected by the pinmux can also be GPIOs. Define these first. - * These must match how the GPIO driver names/numbers its pins. - */ -#define _GPIO(offset) (offset) - -#define TEGRA_PIN_CLK_32K_OUT_PA0 _GPIO(0) -#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) -#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) -#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) -#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) -#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) -#define TEGRA_PIN_SDMMC3_CLK_PA6 _GPIO(6) -#define TEGRA_PIN_SDMMC3_CMD_PA7 _GPIO(7) -#define TEGRA_PIN_GMI_A17_PB0 _GPIO(8) -#define TEGRA_PIN_GMI_A18_PB1 _GPIO(9) -#define TEGRA_PIN_SDMMC3_DAT3_PB4 _GPIO(12) -#define TEGRA_PIN_SDMMC3_DAT2_PB5 _GPIO(13) -#define TEGRA_PIN_SDMMC3_DAT1_PB6 _GPIO(14) -#define TEGRA_PIN_SDMMC3_DAT0_PB7 _GPIO(15) -#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) -#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) -#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) -#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) -#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) -#define TEGRA_PIN_GMI_WP_N_PC7 _GPIO(23) -#define TEGRA_PIN_GMI_AD0_PG0 _GPIO(48) -#define TEGRA_PIN_GMI_AD1_PG1 _GPIO(49) -#define TEGRA_PIN_GMI_AD2_PG2 _GPIO(50) -#define TEGRA_PIN_GMI_AD3_PG3 _GPIO(51) -#define TEGRA_PIN_GMI_AD4_PG4 _GPIO(52) -#define TEGRA_PIN_GMI_AD5_PG5 _GPIO(53) -#define TEGRA_PIN_GMI_AD6_PG6 _GPIO(54) -#define TEGRA_PIN_GMI_AD7_PG7 _GPIO(55) -#define TEGRA_PIN_GMI_AD8_PH0 _GPIO(56) -#define TEGRA_PIN_GMI_AD9_PH1 _GPIO(57) -#define TEGRA_PIN_GMI_AD10_PH2 _GPIO(58) -#define TEGRA_PIN_GMI_AD11_PH3 _GPIO(59) -#define TEGRA_PIN_GMI_AD12_PH4 _GPIO(60) -#define TEGRA_PIN_GMI_AD13_PH5 _GPIO(61) -#define TEGRA_PIN_GMI_AD14_PH6 _GPIO(62) -#define TEGRA_PIN_GMI_AD15_PH7 _GPIO(63) -#define TEGRA_PIN_GMI_WR_N_PI0 _GPIO(64) -#define TEGRA_PIN_GMI_OE_N_PI1 _GPIO(65) -#define TEGRA_PIN_GMI_CS6_N_PI3 _GPIO(67) -#define TEGRA_PIN_GMI_RST_N_PI4 _GPIO(68) -#define TEGRA_PIN_GMI_IORDY_PI5 _GPIO(69) -#define TEGRA_PIN_GMI_CS7_N_PI6 _GPIO(70) -#define TEGRA_PIN_GMI_WAIT_PI7 _GPIO(71) -#define TEGRA_PIN_GMI_CS0_N_PJ0 _GPIO(72) -#define TEGRA_PIN_GMI_CS1_N_PJ2 _GPIO(74) -#define TEGRA_PIN_GMI_DQS_P_PJ3 _GPIO(75) -#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) -#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) -#define TEGRA_PIN_GMI_A16_PJ7 _GPIO(79) -#define TEGRA_PIN_GMI_ADV_N_PK0 _GPIO(80) -#define TEGRA_PIN_GMI_CLK_PK1 _GPIO(81) -#define TEGRA_PIN_GMI_CS4_N_PK2 _GPIO(82) -#define TEGRA_PIN_GMI_CS2_N_PK3 _GPIO(83) -#define TEGRA_PIN_GMI_CS3_N_PK4 _GPIO(84) -#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) -#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) -#define TEGRA_PIN_GMI_A19_PK7 _GPIO(87) -#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) -#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) -#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) -#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) -#define TEGRA_PIN_USB_VBUS_EN0_PN4 _GPIO(108) -#define TEGRA_PIN_USB_VBUS_EN1_PN5 _GPIO(109) -#define TEGRA_PIN_HDMI_INT_PN7 _GPIO(111) -#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) -#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) -#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) -#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) -#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) -#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) -#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) -#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) -#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) -#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) -#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) -#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) -#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) -#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) -#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) -#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) -#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) -#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) -#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) -#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) -#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) -#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) -#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) -#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) -#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) -#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) -#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) -#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) -#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) -#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) -#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) -#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) -#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) -#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) -#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) -#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) -#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) -#define TEGRA_PIN_SDMMC4_CMD_PT7 _GPIO(159) -#define TEGRA_PIN_PU0 _GPIO(160) -#define TEGRA_PIN_PU1 _GPIO(161) -#define TEGRA_PIN_PU2 _GPIO(162) -#define TEGRA_PIN_PU3 _GPIO(163) -#define TEGRA_PIN_PU4 _GPIO(164) -#define TEGRA_PIN_PU5 _GPIO(165) -#define TEGRA_PIN_PU6 _GPIO(166) -#define TEGRA_PIN_PV0 _GPIO(168) -#define TEGRA_PIN_PV1 _GPIO(169) -#define TEGRA_PIN_SDMMC3_CD_N_PV2 _GPIO(170) -#define TEGRA_PIN_SDMMC1_WP_N_PV3 _GPIO(171) -#define TEGRA_PIN_DDC_SCL_PV4 _GPIO(172) -#define TEGRA_PIN_DDC_SDA_PV5 _GPIO(173) -#define TEGRA_PIN_GPIO_W2_AUD_PW2 _GPIO(178) -#define TEGRA_PIN_GPIO_W3_AUD_PW3 _GPIO(179) -#define TEGRA_PIN_CLK1_OUT_PW4 _GPIO(180) -#define TEGRA_PIN_CLK2_OUT_PW5 _GPIO(181) -#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) -#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) -#define TEGRA_PIN_DVFS_PWM_PX0 _GPIO(184) -#define TEGRA_PIN_GPIO_X1_AUD_PX1 _GPIO(185) -#define TEGRA_PIN_DVFS_CLK_PX2 _GPIO(186) -#define TEGRA_PIN_GPIO_X3_AUD_PX3 _GPIO(187) -#define TEGRA_PIN_GPIO_X4_AUD_PX4 _GPIO(188) -#define TEGRA_PIN_GPIO_X5_AUD_PX5 _GPIO(189) -#define TEGRA_PIN_GPIO_X6_AUD_PX6 _GPIO(190) -#define TEGRA_PIN_GPIO_X7_AUD_PX7 _GPIO(191) -#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) -#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) -#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) -#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) -#define TEGRA_PIN_SDMMC1_DAT3_PY4 _GPIO(196) -#define TEGRA_PIN_SDMMC1_DAT2_PY5 _GPIO(197) -#define TEGRA_PIN_SDMMC1_DAT1_PY6 _GPIO(198) -#define TEGRA_PIN_SDMMC1_DAT0_PY7 _GPIO(199) -#define TEGRA_PIN_SDMMC1_CLK_PZ0 _GPIO(200) -#define TEGRA_PIN_SDMMC1_CMD_PZ1 _GPIO(201) -#define TEGRA_PIN_SYS_CLK_REQ_PZ5 _GPIO(205) -#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) -#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) -#define TEGRA_PIN_SDMMC4_DAT0_PAA0 _GPIO(208) -#define TEGRA_PIN_SDMMC4_DAT1_PAA1 _GPIO(209) -#define TEGRA_PIN_SDMMC4_DAT2_PAA2 _GPIO(210) -#define TEGRA_PIN_SDMMC4_DAT3_PAA3 _GPIO(211) -#define TEGRA_PIN_SDMMC4_DAT4_PAA4 _GPIO(212) -#define TEGRA_PIN_SDMMC4_DAT5_PAA5 _GPIO(213) -#define TEGRA_PIN_SDMMC4_DAT6_PAA6 _GPIO(214) -#define TEGRA_PIN_SDMMC4_DAT7_PAA7 _GPIO(215) -#define TEGRA_PIN_PBB0 _GPIO(216) -#define TEGRA_PIN_CAM_I2C_SCL_PBB1 _GPIO(217) -#define TEGRA_PIN_CAM_I2C_SDA_PBB2 _GPIO(218) -#define TEGRA_PIN_PBB3 _GPIO(219) -#define TEGRA_PIN_PBB4 _GPIO(220) -#define TEGRA_PIN_PBB5 _GPIO(221) -#define TEGRA_PIN_PBB6 _GPIO(222) -#define TEGRA_PIN_PBB7 _GPIO(223) -#define TEGRA_PIN_CAM_MCLK_PCC0 _GPIO(224) -#define TEGRA_PIN_PCC1 _GPIO(225) -#define TEGRA_PIN_PCC2 _GPIO(226) -#define TEGRA_PIN_SDMMC4_CLK_PCC4 _GPIO(228) -#define TEGRA_PIN_CLK2_REQ_PCC5 _GPIO(229) -#define TEGRA_PIN_CLK3_OUT_PEE0 _GPIO(240) -#define TEGRA_PIN_CLK3_REQ_PEE1 _GPIO(241) -#define TEGRA_PIN_CLK1_REQ_PEE2 _GPIO(242) -#define TEGRA_PIN_HDMI_CEC_PEE3 _GPIO(243) -#define TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4 _GPIO(244) -#define TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5 _GPIO(245) - -/* All non-GPIO pins follow */ -#define NUM_GPIOS (TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5 + 1) -#define _PIN(offset) (NUM_GPIOS + (offset)) - -/* Non-GPIO pins */ -#define TEGRA_PIN_CORE_PWR_REQ _PIN(0) -#define TEGRA_PIN_CPU_PWR_REQ _PIN(1) -#define TEGRA_PIN_PWR_INT_N _PIN(2) -#define TEGRA_PIN_RESET_OUT_N _PIN(3) -#define TEGRA_PIN_OWR _PIN(4) -#define TEGRA_PIN_JTAG_RTCK _PIN(5) -#define TEGRA_PIN_CLK_32K_IN _PIN(6) -#define TEGRA_PIN_GMI_CLK_LB _PIN(7) - -static const struct pinctrl_pin_desc tegra114_pins[] = { - PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"), - PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), - PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), - PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"), - PINCTRL_PIN(TEGRA_PIN_GMI_A17_PB0, "GMI_A17 PB0"), - PINCTRL_PIN(TEGRA_PIN_GMI_A18_PB1, "GMI_A18 PB1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"), - PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), - PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), - PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), - PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"), - PINCTRL_PIN(TEGRA_PIN_GMI_WR_N_PI0, "GMI_WR_N PI0"), - PINCTRL_PIN(TEGRA_PIN_GMI_OE_N_PI1, "GMI_OE_N PI1"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"), - PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"), - PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"), - PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"), - PINCTRL_PIN(TEGRA_PIN_GMI_DQS_P_PJ3, "GMI_DQS_P PJ3"), - PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), - PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), - PINCTRL_PIN(TEGRA_PIN_GMI_A16_PJ7, "GMI_A16 PJ7"), - PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"), - PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), - PINCTRL_PIN(TEGRA_PIN_GMI_A19_PK7, "GMI_A19 PK7"), - PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), - PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), - PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PN4, "USB_VBUS_EN0 PN4"), - PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PN5, "USB_VBUS_EN1 PN5"), - PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), - PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), - PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), - PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), - PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), - PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), - PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), - PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), - PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), - PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), - PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), - PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), - PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), - PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), - PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"), - PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), - PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), - PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), - PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), - PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), - PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), - PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), - PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), - PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CD_N_PV2, "SDMMC3_CD_N PV2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_WP_N_PV3, "SDMMC1_WP_N PV3"), - PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"), - PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"), - PINCTRL_PIN(TEGRA_PIN_GPIO_W2_AUD_PW2, "GPIO_W2_AUD PW2"), - PINCTRL_PIN(TEGRA_PIN_GPIO_W3_AUD_PW3, "GPIO_W3_AUD PW3"), - PINCTRL_PIN(TEGRA_PIN_CLK1_OUT_PW4, "CLK1_OUT PW4"), - PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"), - PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), - PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), - PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PX0, "DVFS_PWM PX0"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PX1, "GPIO_X1_AUD PX1"), - PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PX2, "DVFS_CLK PX2"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PX3, "GPIO_X3_AUD PX3"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X4_AUD_PX4, "GPIO_X4_AUD PX4"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X5_AUD_PX5, "GPIO_X5_AUD PX5"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X6_AUD_PX6, "GPIO_X6_AUD PX6"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X7_AUD_PX7, "GPIO_X7_AUD PX7"), - PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), - PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), - PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"), - PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"), - PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"), - PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"), - PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"), - PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"), - PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), - PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), - PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"), - PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"), - PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"), - PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"), - PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"), - PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"), - PINCTRL_PIN(TEGRA_PIN_CLK1_REQ_PEE2, "CLK1_REQ PEE2"), - PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, "SDMMC3_CLK_LB_OUT PEE4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, "SDMMC3_CLK_LB_IN PEE5"), - PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), - PINCTRL_PIN(TEGRA_PIN_RESET_OUT_N, "RESET_OUT_N"), - PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"), - PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"), - PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), - PINCTRL_PIN(TEGRA_PIN_GMI_CLK_LB, "GMI_CLK_LB"), -}; - -static const unsigned clk_32k_out_pa0_pins[] = { - TEGRA_PIN_CLK_32K_OUT_PA0, -}; - -static const unsigned uart3_cts_n_pa1_pins[] = { - TEGRA_PIN_UART3_CTS_N_PA1, -}; - -static const unsigned dap2_fs_pa2_pins[] = { - TEGRA_PIN_DAP2_FS_PA2, -}; - -static const unsigned dap2_sclk_pa3_pins[] = { - TEGRA_PIN_DAP2_SCLK_PA3, -}; - -static const unsigned dap2_din_pa4_pins[] = { - TEGRA_PIN_DAP2_DIN_PA4, -}; - -static const unsigned dap2_dout_pa5_pins[] = { - TEGRA_PIN_DAP2_DOUT_PA5, -}; - -static const unsigned sdmmc3_clk_pa6_pins[] = { - TEGRA_PIN_SDMMC3_CLK_PA6, -}; - -static const unsigned sdmmc3_cmd_pa7_pins[] = { - TEGRA_PIN_SDMMC3_CMD_PA7, -}; - -static const unsigned gmi_a17_pb0_pins[] = { - TEGRA_PIN_GMI_A17_PB0, -}; - -static const unsigned gmi_a18_pb1_pins[] = { - TEGRA_PIN_GMI_A18_PB1, -}; - -static const unsigned sdmmc3_dat3_pb4_pins[] = { - TEGRA_PIN_SDMMC3_DAT3_PB4, -}; - -static const unsigned sdmmc3_dat2_pb5_pins[] = { - TEGRA_PIN_SDMMC3_DAT2_PB5, -}; - -static const unsigned sdmmc3_dat1_pb6_pins[] = { - TEGRA_PIN_SDMMC3_DAT1_PB6, -}; - -static const unsigned sdmmc3_dat0_pb7_pins[] = { - TEGRA_PIN_SDMMC3_DAT0_PB7, -}; - -static const unsigned uart3_rts_n_pc0_pins[] = { - TEGRA_PIN_UART3_RTS_N_PC0, -}; - -static const unsigned uart2_txd_pc2_pins[] = { - TEGRA_PIN_UART2_TXD_PC2, -}; - -static const unsigned uart2_rxd_pc3_pins[] = { - TEGRA_PIN_UART2_RXD_PC3, -}; - -static const unsigned gen1_i2c_scl_pc4_pins[] = { - TEGRA_PIN_GEN1_I2C_SCL_PC4, -}; - -static const unsigned gen1_i2c_sda_pc5_pins[] = { - TEGRA_PIN_GEN1_I2C_SDA_PC5, -}; - -static const unsigned gmi_wp_n_pc7_pins[] = { - TEGRA_PIN_GMI_WP_N_PC7, -}; - -static const unsigned gmi_ad0_pg0_pins[] = { - TEGRA_PIN_GMI_AD0_PG0, -}; - -static const unsigned gmi_ad1_pg1_pins[] = { - TEGRA_PIN_GMI_AD1_PG1, -}; - -static const unsigned gmi_ad2_pg2_pins[] = { - TEGRA_PIN_GMI_AD2_PG2, -}; - -static const unsigned gmi_ad3_pg3_pins[] = { - TEGRA_PIN_GMI_AD3_PG3, -}; - -static const unsigned gmi_ad4_pg4_pins[] = { - TEGRA_PIN_GMI_AD4_PG4, -}; - -static const unsigned gmi_ad5_pg5_pins[] = { - TEGRA_PIN_GMI_AD5_PG5, -}; - -static const unsigned gmi_ad6_pg6_pins[] = { - TEGRA_PIN_GMI_AD6_PG6, -}; - -static const unsigned gmi_ad7_pg7_pins[] = { - TEGRA_PIN_GMI_AD7_PG7, -}; - -static const unsigned gmi_ad8_ph0_pins[] = { - TEGRA_PIN_GMI_AD8_PH0, -}; - -static const unsigned gmi_ad9_ph1_pins[] = { - TEGRA_PIN_GMI_AD9_PH1, -}; - -static const unsigned gmi_ad10_ph2_pins[] = { - TEGRA_PIN_GMI_AD10_PH2, -}; - -static const unsigned gmi_ad11_ph3_pins[] = { - TEGRA_PIN_GMI_AD11_PH3, -}; - -static const unsigned gmi_ad12_ph4_pins[] = { - TEGRA_PIN_GMI_AD12_PH4, -}; - -static const unsigned gmi_ad13_ph5_pins[] = { - TEGRA_PIN_GMI_AD13_PH5, -}; - -static const unsigned gmi_ad14_ph6_pins[] = { - TEGRA_PIN_GMI_AD14_PH6, -}; - -static const unsigned gmi_ad15_ph7_pins[] = { - TEGRA_PIN_GMI_AD15_PH7, -}; - -static const unsigned gmi_wr_n_pi0_pins[] = { - TEGRA_PIN_GMI_WR_N_PI0, -}; - -static const unsigned gmi_oe_n_pi1_pins[] = { - TEGRA_PIN_GMI_OE_N_PI1, -}; - -static const unsigned gmi_cs6_n_pi3_pins[] = { - TEGRA_PIN_GMI_CS6_N_PI3, -}; - -static const unsigned gmi_rst_n_pi4_pins[] = { - TEGRA_PIN_GMI_RST_N_PI4, -}; - -static const unsigned gmi_iordy_pi5_pins[] = { - TEGRA_PIN_GMI_IORDY_PI5, -}; - -static const unsigned gmi_cs7_n_pi6_pins[] = { - TEGRA_PIN_GMI_CS7_N_PI6, -}; - -static const unsigned gmi_wait_pi7_pins[] = { - TEGRA_PIN_GMI_WAIT_PI7, -}; - -static const unsigned gmi_cs0_n_pj0_pins[] = { - TEGRA_PIN_GMI_CS0_N_PJ0, -}; - -static const unsigned gmi_cs1_n_pj2_pins[] = { - TEGRA_PIN_GMI_CS1_N_PJ2, -}; - -static const unsigned gmi_dqs_p_pj3_pins[] = { - TEGRA_PIN_GMI_DQS_P_PJ3, -}; - -static const unsigned uart2_cts_n_pj5_pins[] = { - TEGRA_PIN_UART2_CTS_N_PJ5, -}; - -static const unsigned uart2_rts_n_pj6_pins[] = { - TEGRA_PIN_UART2_RTS_N_PJ6, -}; - -static const unsigned gmi_a16_pj7_pins[] = { - TEGRA_PIN_GMI_A16_PJ7, -}; - -static const unsigned gmi_adv_n_pk0_pins[] = { - TEGRA_PIN_GMI_ADV_N_PK0, -}; - -static const unsigned gmi_clk_pk1_pins[] = { - TEGRA_PIN_GMI_CLK_PK1, -}; - -static const unsigned gmi_cs4_n_pk2_pins[] = { - TEGRA_PIN_GMI_CS4_N_PK2, -}; - -static const unsigned gmi_cs2_n_pk3_pins[] = { - TEGRA_PIN_GMI_CS2_N_PK3, -}; - -static const unsigned gmi_cs3_n_pk4_pins[] = { - TEGRA_PIN_GMI_CS3_N_PK4, -}; - -static const unsigned spdif_out_pk5_pins[] = { - TEGRA_PIN_SPDIF_OUT_PK5, -}; - -static const unsigned spdif_in_pk6_pins[] = { - TEGRA_PIN_SPDIF_IN_PK6, -}; - -static const unsigned gmi_a19_pk7_pins[] = { - TEGRA_PIN_GMI_A19_PK7, -}; - -static const unsigned dap1_fs_pn0_pins[] = { - TEGRA_PIN_DAP1_FS_PN0, -}; - -static const unsigned dap1_din_pn1_pins[] = { - TEGRA_PIN_DAP1_DIN_PN1, -}; - -static const unsigned dap1_dout_pn2_pins[] = { - TEGRA_PIN_DAP1_DOUT_PN2, -}; - -static const unsigned dap1_sclk_pn3_pins[] = { - TEGRA_PIN_DAP1_SCLK_PN3, -}; - -static const unsigned usb_vbus_en0_pn4_pins[] = { - TEGRA_PIN_USB_VBUS_EN0_PN4, -}; - -static const unsigned usb_vbus_en1_pn5_pins[] = { - TEGRA_PIN_USB_VBUS_EN1_PN5, -}; - -static const unsigned hdmi_int_pn7_pins[] = { - TEGRA_PIN_HDMI_INT_PN7, -}; - -static const unsigned ulpi_data7_po0_pins[] = { - TEGRA_PIN_ULPI_DATA7_PO0, -}; - -static const unsigned ulpi_data0_po1_pins[] = { - TEGRA_PIN_ULPI_DATA0_PO1, -}; - -static const unsigned ulpi_data1_po2_pins[] = { - TEGRA_PIN_ULPI_DATA1_PO2, -}; - -static const unsigned ulpi_data2_po3_pins[] = { - TEGRA_PIN_ULPI_DATA2_PO3, -}; - -static const unsigned ulpi_data3_po4_pins[] = { - TEGRA_PIN_ULPI_DATA3_PO4, -}; - -static const unsigned ulpi_data4_po5_pins[] = { - TEGRA_PIN_ULPI_DATA4_PO5, -}; - -static const unsigned ulpi_data5_po6_pins[] = { - TEGRA_PIN_ULPI_DATA5_PO6, -}; - -static const unsigned ulpi_data6_po7_pins[] = { - TEGRA_PIN_ULPI_DATA6_PO7, -}; - -static const unsigned dap3_fs_pp0_pins[] = { - TEGRA_PIN_DAP3_FS_PP0, -}; - -static const unsigned dap3_din_pp1_pins[] = { - TEGRA_PIN_DAP3_DIN_PP1, -}; - -static const unsigned dap3_dout_pp2_pins[] = { - TEGRA_PIN_DAP3_DOUT_PP2, -}; - -static const unsigned dap3_sclk_pp3_pins[] = { - TEGRA_PIN_DAP3_SCLK_PP3, -}; - -static const unsigned dap4_fs_pp4_pins[] = { - TEGRA_PIN_DAP4_FS_PP4, -}; - -static const unsigned dap4_din_pp5_pins[] = { - TEGRA_PIN_DAP4_DIN_PP5, -}; - -static const unsigned dap4_dout_pp6_pins[] = { - TEGRA_PIN_DAP4_DOUT_PP6, -}; - -static const unsigned dap4_sclk_pp7_pins[] = { - TEGRA_PIN_DAP4_SCLK_PP7, -}; - -static const unsigned kb_col0_pq0_pins[] = { - TEGRA_PIN_KB_COL0_PQ0, -}; - -static const unsigned kb_col1_pq1_pins[] = { - TEGRA_PIN_KB_COL1_PQ1, -}; - -static const unsigned kb_col2_pq2_pins[] = { - TEGRA_PIN_KB_COL2_PQ2, -}; - -static const unsigned kb_col3_pq3_pins[] = { - TEGRA_PIN_KB_COL3_PQ3, -}; - -static const unsigned kb_col4_pq4_pins[] = { - TEGRA_PIN_KB_COL4_PQ4, -}; - -static const unsigned kb_col5_pq5_pins[] = { - TEGRA_PIN_KB_COL5_PQ5, -}; - -static const unsigned kb_col6_pq6_pins[] = { - TEGRA_PIN_KB_COL6_PQ6, -}; - -static const unsigned kb_col7_pq7_pins[] = { - TEGRA_PIN_KB_COL7_PQ7, -}; - -static const unsigned kb_row0_pr0_pins[] = { - TEGRA_PIN_KB_ROW0_PR0, -}; - -static const unsigned kb_row1_pr1_pins[] = { - TEGRA_PIN_KB_ROW1_PR1, -}; - -static const unsigned kb_row2_pr2_pins[] = { - TEGRA_PIN_KB_ROW2_PR2, -}; - -static const unsigned kb_row3_pr3_pins[] = { - TEGRA_PIN_KB_ROW3_PR3, -}; - -static const unsigned kb_row4_pr4_pins[] = { - TEGRA_PIN_KB_ROW4_PR4, -}; - -static const unsigned kb_row5_pr5_pins[] = { - TEGRA_PIN_KB_ROW5_PR5, -}; - -static const unsigned kb_row6_pr6_pins[] = { - TEGRA_PIN_KB_ROW6_PR6, -}; - -static const unsigned kb_row7_pr7_pins[] = { - TEGRA_PIN_KB_ROW7_PR7, -}; - -static const unsigned kb_row8_ps0_pins[] = { - TEGRA_PIN_KB_ROW8_PS0, -}; - -static const unsigned kb_row9_ps1_pins[] = { - TEGRA_PIN_KB_ROW9_PS1, -}; - -static const unsigned kb_row10_ps2_pins[] = { - TEGRA_PIN_KB_ROW10_PS2, -}; - -static const unsigned gen2_i2c_scl_pt5_pins[] = { - TEGRA_PIN_GEN2_I2C_SCL_PT5, -}; - -static const unsigned gen2_i2c_sda_pt6_pins[] = { - TEGRA_PIN_GEN2_I2C_SDA_PT6, -}; - -static const unsigned sdmmc4_cmd_pt7_pins[] = { - TEGRA_PIN_SDMMC4_CMD_PT7, -}; - -static const unsigned pu0_pins[] = { - TEGRA_PIN_PU0, -}; - -static const unsigned pu1_pins[] = { - TEGRA_PIN_PU1, -}; - -static const unsigned pu2_pins[] = { - TEGRA_PIN_PU2, -}; - -static const unsigned pu3_pins[] = { - TEGRA_PIN_PU3, -}; - -static const unsigned pu4_pins[] = { - TEGRA_PIN_PU4, -}; - -static const unsigned pu5_pins[] = { - TEGRA_PIN_PU5, -}; - -static const unsigned pu6_pins[] = { - TEGRA_PIN_PU6, -}; - -static const unsigned pv0_pins[] = { - TEGRA_PIN_PV0, -}; - -static const unsigned pv1_pins[] = { - TEGRA_PIN_PV1, -}; - -static const unsigned sdmmc3_cd_n_pv2_pins[] = { - TEGRA_PIN_SDMMC3_CD_N_PV2, -}; - -static const unsigned sdmmc1_wp_n_pv3_pins[] = { - TEGRA_PIN_SDMMC1_WP_N_PV3, -}; - -static const unsigned ddc_scl_pv4_pins[] = { - TEGRA_PIN_DDC_SCL_PV4, -}; - -static const unsigned ddc_sda_pv5_pins[] = { - TEGRA_PIN_DDC_SDA_PV5, -}; - -static const unsigned gpio_w2_aud_pw2_pins[] = { - TEGRA_PIN_GPIO_W2_AUD_PW2, -}; - -static const unsigned gpio_w3_aud_pw3_pins[] = { - TEGRA_PIN_GPIO_W3_AUD_PW3, -}; - -static const unsigned clk1_out_pw4_pins[] = { - TEGRA_PIN_CLK1_OUT_PW4, -}; - -static const unsigned clk2_out_pw5_pins[] = { - TEGRA_PIN_CLK2_OUT_PW5, -}; - -static const unsigned uart3_txd_pw6_pins[] = { - TEGRA_PIN_UART3_TXD_PW6, -}; - -static const unsigned uart3_rxd_pw7_pins[] = { - TEGRA_PIN_UART3_RXD_PW7, -}; - -static const unsigned dvfs_pwm_px0_pins[] = { - TEGRA_PIN_DVFS_PWM_PX0, -}; - -static const unsigned gpio_x1_aud_px1_pins[] = { - TEGRA_PIN_GPIO_X1_AUD_PX1, -}; - -static const unsigned dvfs_clk_px2_pins[] = { - TEGRA_PIN_DVFS_CLK_PX2, -}; - -static const unsigned gpio_x3_aud_px3_pins[] = { - TEGRA_PIN_GPIO_X3_AUD_PX3, -}; - -static const unsigned gpio_x4_aud_px4_pins[] = { - TEGRA_PIN_GPIO_X4_AUD_PX4, -}; - -static const unsigned gpio_x5_aud_px5_pins[] = { - TEGRA_PIN_GPIO_X5_AUD_PX5, -}; - -static const unsigned gpio_x6_aud_px6_pins[] = { - TEGRA_PIN_GPIO_X6_AUD_PX6, -}; - -static const unsigned gpio_x7_aud_px7_pins[] = { - TEGRA_PIN_GPIO_X7_AUD_PX7, -}; - -static const unsigned ulpi_clk_py0_pins[] = { - TEGRA_PIN_ULPI_CLK_PY0, -}; - -static const unsigned ulpi_dir_py1_pins[] = { - TEGRA_PIN_ULPI_DIR_PY1, -}; - -static const unsigned ulpi_nxt_py2_pins[] = { - TEGRA_PIN_ULPI_NXT_PY2, -}; - -static const unsigned ulpi_stp_py3_pins[] = { - TEGRA_PIN_ULPI_STP_PY3, -}; - -static const unsigned sdmmc1_dat3_py4_pins[] = { - TEGRA_PIN_SDMMC1_DAT3_PY4, -}; - -static const unsigned sdmmc1_dat2_py5_pins[] = { - TEGRA_PIN_SDMMC1_DAT2_PY5, -}; - -static const unsigned sdmmc1_dat1_py6_pins[] = { - TEGRA_PIN_SDMMC1_DAT1_PY6, -}; - -static const unsigned sdmmc1_dat0_py7_pins[] = { - TEGRA_PIN_SDMMC1_DAT0_PY7, -}; - -static const unsigned sdmmc1_clk_pz0_pins[] = { - TEGRA_PIN_SDMMC1_CLK_PZ0, -}; - -static const unsigned sdmmc1_cmd_pz1_pins[] = { - TEGRA_PIN_SDMMC1_CMD_PZ1, -}; - -static const unsigned sys_clk_req_pz5_pins[] = { - TEGRA_PIN_SYS_CLK_REQ_PZ5, -}; - -static const unsigned pwr_i2c_scl_pz6_pins[] = { - TEGRA_PIN_PWR_I2C_SCL_PZ6, -}; - -static const unsigned pwr_i2c_sda_pz7_pins[] = { - TEGRA_PIN_PWR_I2C_SDA_PZ7, -}; - -static const unsigned sdmmc4_dat0_paa0_pins[] = { - TEGRA_PIN_SDMMC4_DAT0_PAA0, -}; - -static const unsigned sdmmc4_dat1_paa1_pins[] = { - TEGRA_PIN_SDMMC4_DAT1_PAA1, -}; - -static const unsigned sdmmc4_dat2_paa2_pins[] = { - TEGRA_PIN_SDMMC4_DAT2_PAA2, -}; - -static const unsigned sdmmc4_dat3_paa3_pins[] = { - TEGRA_PIN_SDMMC4_DAT3_PAA3, -}; - -static const unsigned sdmmc4_dat4_paa4_pins[] = { - TEGRA_PIN_SDMMC4_DAT4_PAA4, -}; - -static const unsigned sdmmc4_dat5_paa5_pins[] = { - TEGRA_PIN_SDMMC4_DAT5_PAA5, -}; - -static const unsigned sdmmc4_dat6_paa6_pins[] = { - TEGRA_PIN_SDMMC4_DAT6_PAA6, -}; - -static const unsigned sdmmc4_dat7_paa7_pins[] = { - TEGRA_PIN_SDMMC4_DAT7_PAA7, -}; - -static const unsigned pbb0_pins[] = { - TEGRA_PIN_PBB0, -}; - -static const unsigned cam_i2c_scl_pbb1_pins[] = { - TEGRA_PIN_CAM_I2C_SCL_PBB1, -}; - -static const unsigned cam_i2c_sda_pbb2_pins[] = { - TEGRA_PIN_CAM_I2C_SDA_PBB2, -}; - -static const unsigned pbb3_pins[] = { - TEGRA_PIN_PBB3, -}; - -static const unsigned pbb4_pins[] = { - TEGRA_PIN_PBB4, -}; - -static const unsigned pbb5_pins[] = { - TEGRA_PIN_PBB5, -}; - -static const unsigned pbb6_pins[] = { - TEGRA_PIN_PBB6, -}; - -static const unsigned pbb7_pins[] = { - TEGRA_PIN_PBB7, -}; - -static const unsigned cam_mclk_pcc0_pins[] = { - TEGRA_PIN_CAM_MCLK_PCC0, -}; - -static const unsigned pcc1_pins[] = { - TEGRA_PIN_PCC1, -}; - -static const unsigned pcc2_pins[] = { - TEGRA_PIN_PCC2, -}; - -static const unsigned sdmmc4_clk_pcc4_pins[] = { - TEGRA_PIN_SDMMC4_CLK_PCC4, -}; - -static const unsigned clk2_req_pcc5_pins[] = { - TEGRA_PIN_CLK2_REQ_PCC5, -}; - -static const unsigned clk3_out_pee0_pins[] = { - TEGRA_PIN_CLK3_OUT_PEE0, -}; - -static const unsigned clk3_req_pee1_pins[] = { - TEGRA_PIN_CLK3_REQ_PEE1, -}; - -static const unsigned clk1_req_pee2_pins[] = { - TEGRA_PIN_CLK1_REQ_PEE2, -}; - -static const unsigned hdmi_cec_pee3_pins[] = { - TEGRA_PIN_HDMI_CEC_PEE3, -}; - -static const unsigned sdmmc3_clk_lb_out_pee4_pins[] = { - TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, -}; - -static const unsigned sdmmc3_clk_lb_in_pee5_pins[] = { - TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, -}; - -static const unsigned core_pwr_req_pins[] = { - TEGRA_PIN_CORE_PWR_REQ, -}; - -static const unsigned cpu_pwr_req_pins[] = { - TEGRA_PIN_CPU_PWR_REQ, -}; - -static const unsigned pwr_int_n_pins[] = { - TEGRA_PIN_PWR_INT_N, -}; - -static const unsigned reset_out_n_pins[] = { - TEGRA_PIN_RESET_OUT_N, -}; - -static const unsigned owr_pins[] = { - TEGRA_PIN_OWR, -}; - -static const unsigned jtag_rtck_pins[] = { - TEGRA_PIN_JTAG_RTCK, -}; - -static const unsigned clk_32k_in_pins[] = { - TEGRA_PIN_CLK_32K_IN, -}; - -static const unsigned gmi_clk_lb_pins[] = { - TEGRA_PIN_GMI_CLK_LB, -}; - -static const unsigned drive_ao1_pins[] = { - TEGRA_PIN_KB_ROW0_PR0, - TEGRA_PIN_KB_ROW1_PR1, - TEGRA_PIN_KB_ROW2_PR2, - TEGRA_PIN_KB_ROW3_PR3, - TEGRA_PIN_KB_ROW4_PR4, - TEGRA_PIN_KB_ROW5_PR5, - TEGRA_PIN_KB_ROW6_PR6, - TEGRA_PIN_KB_ROW7_PR7, - TEGRA_PIN_PWR_I2C_SCL_PZ6, - TEGRA_PIN_PWR_I2C_SDA_PZ7, -}; - -static const unsigned drive_ao2_pins[] = { - TEGRA_PIN_CLK_32K_OUT_PA0, - TEGRA_PIN_KB_COL0_PQ0, - TEGRA_PIN_KB_COL1_PQ1, - TEGRA_PIN_KB_COL2_PQ2, - TEGRA_PIN_KB_COL3_PQ3, - TEGRA_PIN_KB_COL4_PQ4, - TEGRA_PIN_KB_COL5_PQ5, - TEGRA_PIN_KB_COL6_PQ6, - TEGRA_PIN_KB_COL7_PQ7, - TEGRA_PIN_KB_ROW8_PS0, - TEGRA_PIN_KB_ROW9_PS1, - TEGRA_PIN_KB_ROW10_PS2, - TEGRA_PIN_SYS_CLK_REQ_PZ5, - TEGRA_PIN_CORE_PWR_REQ, - TEGRA_PIN_CPU_PWR_REQ, - TEGRA_PIN_RESET_OUT_N, -}; - -static const unsigned drive_at1_pins[] = { - TEGRA_PIN_GMI_AD8_PH0, - TEGRA_PIN_GMI_AD9_PH1, - TEGRA_PIN_GMI_AD10_PH2, - TEGRA_PIN_GMI_AD11_PH3, - TEGRA_PIN_GMI_AD12_PH4, - TEGRA_PIN_GMI_AD13_PH5, - TEGRA_PIN_GMI_AD14_PH6, - TEGRA_PIN_GMI_AD15_PH7, - TEGRA_PIN_GMI_IORDY_PI5, - TEGRA_PIN_GMI_CS7_N_PI6, -}; - -static const unsigned drive_at2_pins[] = { - TEGRA_PIN_GMI_AD0_PG0, - TEGRA_PIN_GMI_AD1_PG1, - TEGRA_PIN_GMI_AD2_PG2, - TEGRA_PIN_GMI_AD3_PG3, - TEGRA_PIN_GMI_AD4_PG4, - TEGRA_PIN_GMI_AD5_PG5, - TEGRA_PIN_GMI_AD6_PG6, - TEGRA_PIN_GMI_AD7_PG7, - TEGRA_PIN_GMI_WR_N_PI0, - TEGRA_PIN_GMI_OE_N_PI1, - TEGRA_PIN_GMI_CS6_N_PI3, - TEGRA_PIN_GMI_RST_N_PI4, - TEGRA_PIN_GMI_WAIT_PI7, - TEGRA_PIN_GMI_DQS_P_PJ3, - TEGRA_PIN_GMI_ADV_N_PK0, - TEGRA_PIN_GMI_CLK_PK1, - TEGRA_PIN_GMI_CS4_N_PK2, - TEGRA_PIN_GMI_CS2_N_PK3, - TEGRA_PIN_GMI_CS3_N_PK4, -}; - -static const unsigned drive_at3_pins[] = { - TEGRA_PIN_GMI_WP_N_PC7, - TEGRA_PIN_GMI_CS0_N_PJ0, -}; - -static const unsigned drive_at4_pins[] = { - TEGRA_PIN_GMI_A17_PB0, - TEGRA_PIN_GMI_A18_PB1, - TEGRA_PIN_GMI_CS1_N_PJ2, - TEGRA_PIN_GMI_A16_PJ7, - TEGRA_PIN_GMI_A19_PK7, -}; - -static const unsigned drive_at5_pins[] = { - TEGRA_PIN_GEN2_I2C_SCL_PT5, - TEGRA_PIN_GEN2_I2C_SDA_PT6, -}; - -static const unsigned drive_cdev1_pins[] = { - TEGRA_PIN_CLK1_OUT_PW4, - TEGRA_PIN_CLK1_REQ_PEE2, -}; - -static const unsigned drive_cdev2_pins[] = { - TEGRA_PIN_CLK2_OUT_PW5, - TEGRA_PIN_CLK2_REQ_PCC5, - TEGRA_PIN_SDMMC1_WP_N_PV3, -}; - -static const unsigned drive_dap1_pins[] = { - TEGRA_PIN_DAP1_FS_PN0, - TEGRA_PIN_DAP1_DIN_PN1, - TEGRA_PIN_DAP1_DOUT_PN2, - TEGRA_PIN_DAP1_SCLK_PN3, -}; - -static const unsigned drive_dap2_pins[] = { - TEGRA_PIN_DAP2_FS_PA2, - TEGRA_PIN_DAP2_SCLK_PA3, - TEGRA_PIN_DAP2_DIN_PA4, - TEGRA_PIN_DAP2_DOUT_PA5, -}; - -static const unsigned drive_dap3_pins[] = { - TEGRA_PIN_DAP3_FS_PP0, - TEGRA_PIN_DAP3_DIN_PP1, - TEGRA_PIN_DAP3_DOUT_PP2, - TEGRA_PIN_DAP3_SCLK_PP3, -}; - -static const unsigned drive_dap4_pins[] = { - TEGRA_PIN_DAP4_FS_PP4, - TEGRA_PIN_DAP4_DIN_PP5, - TEGRA_PIN_DAP4_DOUT_PP6, - TEGRA_PIN_DAP4_SCLK_PP7, -}; - -static const unsigned drive_dbg_pins[] = { - TEGRA_PIN_GEN1_I2C_SCL_PC4, - TEGRA_PIN_GEN1_I2C_SDA_PC5, - TEGRA_PIN_PU0, - TEGRA_PIN_PU1, - TEGRA_PIN_PU2, - TEGRA_PIN_PU3, - TEGRA_PIN_PU4, - TEGRA_PIN_PU5, - TEGRA_PIN_PU6, -}; - -static const unsigned drive_sdio3_pins[] = { - TEGRA_PIN_SDMMC3_CLK_PA6, - TEGRA_PIN_SDMMC3_CMD_PA7, - TEGRA_PIN_SDMMC3_DAT3_PB4, - TEGRA_PIN_SDMMC3_DAT2_PB5, - TEGRA_PIN_SDMMC3_DAT1_PB6, - TEGRA_PIN_SDMMC3_DAT0_PB7, - TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, - TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, -}; - -static const unsigned drive_spi_pins[] = { - TEGRA_PIN_DVFS_PWM_PX0, - TEGRA_PIN_GPIO_X1_AUD_PX1, - TEGRA_PIN_DVFS_CLK_PX2, - TEGRA_PIN_GPIO_X3_AUD_PX3, - TEGRA_PIN_GPIO_X4_AUD_PX4, - TEGRA_PIN_GPIO_X5_AUD_PX5, - TEGRA_PIN_GPIO_X6_AUD_PX6, - TEGRA_PIN_GPIO_X7_AUD_PX7, - TEGRA_PIN_GPIO_W2_AUD_PW2, - TEGRA_PIN_GPIO_W3_AUD_PW3, -}; - -static const unsigned drive_uaa_pins[] = { - TEGRA_PIN_ULPI_DATA0_PO1, - TEGRA_PIN_ULPI_DATA1_PO2, - TEGRA_PIN_ULPI_DATA2_PO3, - TEGRA_PIN_ULPI_DATA3_PO4, -}; - -static const unsigned drive_uab_pins[] = { - TEGRA_PIN_ULPI_DATA7_PO0, - TEGRA_PIN_ULPI_DATA4_PO5, - TEGRA_PIN_ULPI_DATA5_PO6, - TEGRA_PIN_ULPI_DATA6_PO7, - TEGRA_PIN_PV0, - TEGRA_PIN_PV1, -}; - -static const unsigned drive_uart2_pins[] = { - TEGRA_PIN_UART2_TXD_PC2, - TEGRA_PIN_UART2_RXD_PC3, - TEGRA_PIN_UART2_CTS_N_PJ5, - TEGRA_PIN_UART2_RTS_N_PJ6, -}; - -static const unsigned drive_uart3_pins[] = { - TEGRA_PIN_UART3_CTS_N_PA1, - TEGRA_PIN_UART3_RTS_N_PC0, - TEGRA_PIN_UART3_TXD_PW6, - TEGRA_PIN_UART3_RXD_PW7, -}; - -static const unsigned drive_sdio1_pins[] = { - TEGRA_PIN_SDMMC1_DAT3_PY4, - TEGRA_PIN_SDMMC1_DAT2_PY5, - TEGRA_PIN_SDMMC1_DAT1_PY6, - TEGRA_PIN_SDMMC1_DAT0_PY7, - TEGRA_PIN_SDMMC1_CLK_PZ0, - TEGRA_PIN_SDMMC1_CMD_PZ1, -}; - -static const unsigned drive_ddc_pins[] = { - TEGRA_PIN_DDC_SCL_PV4, - TEGRA_PIN_DDC_SDA_PV5, -}; - -static const unsigned drive_gma_pins[] = { - TEGRA_PIN_SDMMC4_CLK_PCC4, - TEGRA_PIN_SDMMC4_CMD_PT7, - TEGRA_PIN_SDMMC4_DAT0_PAA0, - TEGRA_PIN_SDMMC4_DAT1_PAA1, - TEGRA_PIN_SDMMC4_DAT2_PAA2, - TEGRA_PIN_SDMMC4_DAT3_PAA3, - TEGRA_PIN_SDMMC4_DAT4_PAA4, - TEGRA_PIN_SDMMC4_DAT5_PAA5, - TEGRA_PIN_SDMMC4_DAT6_PAA6, - TEGRA_PIN_SDMMC4_DAT7_PAA7, -}; - -static const unsigned drive_gme_pins[] = { - TEGRA_PIN_PBB0, - TEGRA_PIN_CAM_I2C_SCL_PBB1, - TEGRA_PIN_CAM_I2C_SDA_PBB2, - TEGRA_PIN_PBB3, - TEGRA_PIN_PCC2, -}; - -static const unsigned drive_gmf_pins[] = { - TEGRA_PIN_PBB4, - TEGRA_PIN_PBB5, - TEGRA_PIN_PBB6, - TEGRA_PIN_PBB7, -}; - -static const unsigned drive_gmg_pins[] = { - TEGRA_PIN_CAM_MCLK_PCC0, -}; - -static const unsigned drive_gmh_pins[] = { - TEGRA_PIN_PCC1, -}; - -static const unsigned drive_owr_pins[] = { - TEGRA_PIN_SDMMC3_CD_N_PV2, -}; - -static const unsigned drive_uda_pins[] = { - TEGRA_PIN_ULPI_CLK_PY0, - TEGRA_PIN_ULPI_DIR_PY1, - TEGRA_PIN_ULPI_NXT_PY2, - TEGRA_PIN_ULPI_STP_PY3, -}; - -static const unsigned drive_dev3_pins[] = { -}; - -static const unsigned drive_cec_pins[] = { -}; - -static const unsigned drive_at6_pins[] = { -}; - -static const unsigned drive_dap5_pins[] = { -}; - -static const unsigned drive_usb_vbus_en_pins[] = { -}; - -static const unsigned drive_ao3_pins[] = { -}; - -static const unsigned drive_hv0_pins[] = { -}; - -static const unsigned drive_sdio4_pins[] = { -}; - -static const unsigned drive_ao0_pins[] = { -}; - -enum tegra_mux { - TEGRA_MUX_BLINK, - TEGRA_MUX_CEC, - TEGRA_MUX_CLDVFS, - TEGRA_MUX_CLK, - TEGRA_MUX_CLK12, - TEGRA_MUX_CPU, - TEGRA_MUX_DAP, - TEGRA_MUX_DAP1, - TEGRA_MUX_DAP2, - TEGRA_MUX_DEV3, - TEGRA_MUX_DISPLAYA, - TEGRA_MUX_DISPLAYA_ALT, - TEGRA_MUX_DISPLAYB, - TEGRA_MUX_DTV, - TEGRA_MUX_EMC_DLL, - TEGRA_MUX_EXTPERIPH1, - TEGRA_MUX_EXTPERIPH2, - TEGRA_MUX_EXTPERIPH3, - TEGRA_MUX_GMI, - TEGRA_MUX_GMI_ALT, - TEGRA_MUX_HDA, - TEGRA_MUX_HSI, - TEGRA_MUX_I2C1, - TEGRA_MUX_I2C2, - TEGRA_MUX_I2C3, - TEGRA_MUX_I2C4, - TEGRA_MUX_I2CPWR, - TEGRA_MUX_I2S0, - TEGRA_MUX_I2S1, - TEGRA_MUX_I2S2, - TEGRA_MUX_I2S3, - TEGRA_MUX_I2S4, - TEGRA_MUX_IRDA, - TEGRA_MUX_KBC, - TEGRA_MUX_NAND, - TEGRA_MUX_NAND_ALT, - TEGRA_MUX_OWR, - TEGRA_MUX_PMI, - TEGRA_MUX_PWM0, - TEGRA_MUX_PWM1, - TEGRA_MUX_PWM2, - TEGRA_MUX_PWM3, - TEGRA_MUX_PWRON, - TEGRA_MUX_RESET_OUT_N, - TEGRA_MUX_RSVD1, - TEGRA_MUX_RSVD2, - TEGRA_MUX_RSVD3, - TEGRA_MUX_RSVD4, - TEGRA_MUX_RTCK, - TEGRA_MUX_SDMMC1, - TEGRA_MUX_SDMMC2, - TEGRA_MUX_SDMMC3, - TEGRA_MUX_SDMMC4, - TEGRA_MUX_SOC, - TEGRA_MUX_SPDIF, - TEGRA_MUX_SPI1, - TEGRA_MUX_SPI2, - TEGRA_MUX_SPI3, - TEGRA_MUX_SPI4, - TEGRA_MUX_SPI5, - TEGRA_MUX_SPI6, - TEGRA_MUX_SYSCLK, - TEGRA_MUX_TRACE, - TEGRA_MUX_UARTA, - TEGRA_MUX_UARTB, - TEGRA_MUX_UARTC, - TEGRA_MUX_UARTD, - TEGRA_MUX_ULPI, - TEGRA_MUX_USB, - TEGRA_MUX_VGP1, - TEGRA_MUX_VGP2, - TEGRA_MUX_VGP3, - TEGRA_MUX_VGP4, - TEGRA_MUX_VGP5, - TEGRA_MUX_VGP6, - TEGRA_MUX_VI, - TEGRA_MUX_VI_ALT1, - TEGRA_MUX_VI_ALT3, -}; - -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } - -static struct tegra_function tegra114_functions[] = { - FUNCTION(blink), - FUNCTION(cec), - FUNCTION(cldvfs), - FUNCTION(clk), - FUNCTION(clk12), - FUNCTION(cpu), - FUNCTION(dap), - FUNCTION(dap1), - FUNCTION(dap2), - FUNCTION(dev3), - FUNCTION(displaya), - FUNCTION(displaya_alt), - FUNCTION(displayb), - FUNCTION(dtv), - FUNCTION(emc_dll), - FUNCTION(extperiph1), - FUNCTION(extperiph2), - FUNCTION(extperiph3), - FUNCTION(gmi), - FUNCTION(gmi_alt), - FUNCTION(hda), - FUNCTION(hsi), - FUNCTION(i2c1), - FUNCTION(i2c2), - FUNCTION(i2c3), - FUNCTION(i2c4), - FUNCTION(i2cpwr), - FUNCTION(i2s0), - FUNCTION(i2s1), - FUNCTION(i2s2), - FUNCTION(i2s3), - FUNCTION(i2s4), - FUNCTION(irda), - FUNCTION(kbc), - FUNCTION(nand), - FUNCTION(nand_alt), - FUNCTION(owr), - FUNCTION(pmi), - FUNCTION(pwm0), - FUNCTION(pwm1), - FUNCTION(pwm2), - FUNCTION(pwm3), - FUNCTION(pwron), - FUNCTION(reset_out_n), - FUNCTION(rsvd1), - FUNCTION(rsvd2), - FUNCTION(rsvd3), - FUNCTION(rsvd4), - FUNCTION(rtck), - FUNCTION(sdmmc1), - FUNCTION(sdmmc2), - FUNCTION(sdmmc3), - FUNCTION(sdmmc4), - FUNCTION(soc), - FUNCTION(spdif), - FUNCTION(spi1), - FUNCTION(spi2), - FUNCTION(spi3), - FUNCTION(spi4), - FUNCTION(spi5), - FUNCTION(spi6), - FUNCTION(sysclk), - FUNCTION(trace), - FUNCTION(uarta), - FUNCTION(uartb), - FUNCTION(uartc), - FUNCTION(uartd), - FUNCTION(ulpi), - FUNCTION(usb), - FUNCTION(vgp1), - FUNCTION(vgp2), - FUNCTION(vgp3), - FUNCTION(vgp4), - FUNCTION(vgp5), - FUNCTION(vgp6), - FUNCTION(vi), - FUNCTION(vi_alt1), - FUNCTION(vi_alt3), -}; - -#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ -#define PINGROUP_REG_A 0x3000 /* bank 1 */ - -#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A) -#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) - -#define PINGROUP_BIT_Y(b) (b) -#define PINGROUP_BIT_N(b) (-1) - -#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel) \ - { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ - .funcs = { \ - TEGRA_MUX_##f0, \ - TEGRA_MUX_##f1, \ - TEGRA_MUX_##f2, \ - TEGRA_MUX_##f3, \ - }, \ - .mux_reg = PINGROUP_REG(r), \ - .mux_bank = 1, \ - .mux_bit = 0, \ - .pupd_reg = PINGROUP_REG(r), \ - .pupd_bank = 1, \ - .pupd_bit = 2, \ - .tri_reg = PINGROUP_REG(r), \ - .tri_bank = 1, \ - .tri_bit = 4, \ - .einput_bit = 5, \ - .odrain_bit = PINGROUP_BIT_##od(6), \ - .lock_bit = 7, \ - .ioreset_bit = PINGROUP_BIT_##ior(8), \ - .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9), \ - .drv_reg = -1, \ - } - -#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, \ - drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, \ - slwf_b, slwf_w, drvtype) \ - { \ - .name = "drive_" #pg_name, \ - .pins = drive_##pg_name##_pins, \ - .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ - .mux_reg = -1, \ - .pupd_reg = -1, \ - .tri_reg = -1, \ - .einput_bit = -1, \ - .odrain_bit = -1, \ - .lock_bit = -1, \ - .ioreset_bit = -1, \ - .rcv_sel_bit = -1, \ - .drv_reg = DRV_PINGROUP_REG(r), \ - .drv_bank = 0, \ - .hsm_bit = hsm_b, \ - .schmitt_bit = schmitt_b, \ - .lpmd_bit = lpmd_b, \ - .drvdn_bit = drvdn_b, \ - .drvdn_width = drvdn_w, \ - .drvup_bit = drvup_b, \ - .drvup_width = drvup_w, \ - .slwr_bit = slwr_b, \ - .slwr_width = slwr_w, \ - .slwf_bit = slwf_b, \ - .slwf_width = slwf_w, \ - .drvtype_bit = PINGROUP_BIT_##drvtype(6), \ - } - -static const struct tegra_pingroup tegra114_groups[] = { - /* pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel */ - PINGROUP(ulpi_data0_po1, SPI3, HSI, UARTA, ULPI, 0x3000, N, N, N), - PINGROUP(ulpi_data1_po2, SPI3, HSI, UARTA, ULPI, 0x3004, N, N, N), - PINGROUP(ulpi_data2_po3, SPI3, HSI, UARTA, ULPI, 0x3008, N, N, N), - PINGROUP(ulpi_data3_po4, SPI3, HSI, UARTA, ULPI, 0x300c, N, N, N), - PINGROUP(ulpi_data4_po5, SPI2, HSI, UARTA, ULPI, 0x3010, N, N, N), - PINGROUP(ulpi_data5_po6, SPI2, HSI, UARTA, ULPI, 0x3014, N, N, N), - PINGROUP(ulpi_data6_po7, SPI2, HSI, UARTA, ULPI, 0x3018, N, N, N), - PINGROUP(ulpi_data7_po0, SPI2, HSI, UARTA, ULPI, 0x301c, N, N, N), - PINGROUP(ulpi_clk_py0, SPI1, SPI5, UARTD, ULPI, 0x3020, N, N, N), - PINGROUP(ulpi_dir_py1, SPI1, SPI5, UARTD, ULPI, 0x3024, N, N, N), - PINGROUP(ulpi_nxt_py2, SPI1, SPI5, UARTD, ULPI, 0x3028, N, N, N), - PINGROUP(ulpi_stp_py3, SPI1, SPI5, UARTD, ULPI, 0x302c, N, N, N), - PINGROUP(dap3_fs_pp0, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3030, N, N, N), - PINGROUP(dap3_din_pp1, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3034, N, N, N), - PINGROUP(dap3_dout_pp2, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3038, N, N, N), - PINGROUP(dap3_sclk_pp3, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x303c, N, N, N), - PINGROUP(pv0, USB, RSVD2, RSVD3, RSVD4, 0x3040, N, N, N), - PINGROUP(pv1, RSVD1, RSVD2, RSVD3, RSVD4, 0x3044, N, N, N), - PINGROUP(sdmmc1_clk_pz0, SDMMC1, CLK12, RSVD3, RSVD4, 0x3048, N, N, N), - PINGROUP(sdmmc1_cmd_pz1, SDMMC1, SPDIF, SPI4, UARTA, 0x304c, N, N, N), - PINGROUP(sdmmc1_dat3_py4, SDMMC1, SPDIF, SPI4, UARTA, 0x3050, N, N, N), - PINGROUP(sdmmc1_dat2_py5, SDMMC1, PWM0, SPI4, UARTA, 0x3054, N, N, N), - PINGROUP(sdmmc1_dat1_py6, SDMMC1, PWM1, SPI4, UARTA, 0x3058, N, N, N), - PINGROUP(sdmmc1_dat0_py7, SDMMC1, RSVD2, SPI4, UARTA, 0x305c, N, N, N), - PINGROUP(clk2_out_pw5, EXTPERIPH2, RSVD2, RSVD3, RSVD4, 0x3068, N, N, N), - PINGROUP(clk2_req_pcc5, DAP, RSVD2, RSVD3, RSVD4, 0x306c, N, N, N), - PINGROUP(hdmi_int_pn7, RSVD1, RSVD2, RSVD3, RSVD4, 0x3110, N, N, Y), - PINGROUP(ddc_scl_pv4, I2C4, RSVD2, RSVD3, RSVD4, 0x3114, N, N, Y), - PINGROUP(ddc_sda_pv5, I2C4, RSVD2, RSVD3, RSVD4, 0x3118, N, N, Y), - PINGROUP(uart2_rxd_pc3, IRDA, SPDIF, UARTA, SPI4, 0x3164, N, N, N), - PINGROUP(uart2_txd_pc2, IRDA, SPDIF, UARTA, SPI4, 0x3168, N, N, N), - PINGROUP(uart2_rts_n_pj6, UARTA, UARTB, RSVD3, SPI4, 0x316c, N, N, N), - PINGROUP(uart2_cts_n_pj5, UARTA, UARTB, RSVD3, SPI4, 0x3170, N, N, N), - PINGROUP(uart3_txd_pw6, UARTC, RSVD2, RSVD3, SPI4, 0x3174, N, N, N), - PINGROUP(uart3_rxd_pw7, UARTC, RSVD2, RSVD3, SPI4, 0x3178, N, N, N), - PINGROUP(uart3_cts_n_pa1, UARTC, SDMMC1, DTV, SPI4, 0x317c, N, N, N), - PINGROUP(uart3_rts_n_pc0, UARTC, PWM0, DTV, DISPLAYA, 0x3180, N, N, N), - PINGROUP(pu0, OWR, UARTA, RSVD3, RSVD4, 0x3184, N, N, N), - PINGROUP(pu1, RSVD1, UARTA, RSVD3, RSVD4, 0x3188, N, N, N), - PINGROUP(pu2, RSVD1, UARTA, RSVD3, RSVD4, 0x318c, N, N, N), - PINGROUP(pu3, PWM0, UARTA, DISPLAYA, DISPLAYB, 0x3190, N, N, N), - PINGROUP(pu4, PWM1, UARTA, DISPLAYA, DISPLAYB, 0x3194, N, N, N), - PINGROUP(pu5, PWM2, UARTA, DISPLAYA, DISPLAYB, 0x3198, N, N, N), - PINGROUP(pu6, PWM3, UARTA, USB, DISPLAYB, 0x319c, N, N, N), - PINGROUP(gen1_i2c_sda_pc5, I2C1, RSVD2, RSVD3, RSVD4, 0x31a0, Y, N, N), - PINGROUP(gen1_i2c_scl_pc4, I2C1, RSVD2, RSVD3, RSVD4, 0x31a4, Y, N, N), - PINGROUP(dap4_fs_pp4, I2S3, RSVD2, DTV, RSVD4, 0x31a8, N, N, N), - PINGROUP(dap4_din_pp5, I2S3, RSVD2, RSVD3, RSVD4, 0x31ac, N, N, N), - PINGROUP(dap4_dout_pp6, I2S3, RSVD2, DTV, RSVD4, 0x31b0, N, N, N), - PINGROUP(dap4_sclk_pp7, I2S3, RSVD2, RSVD3, RSVD4, 0x31b4, N, N, N), - PINGROUP(clk3_out_pee0, EXTPERIPH3, RSVD2, RSVD3, RSVD4, 0x31b8, N, N, N), - PINGROUP(clk3_req_pee1, DEV3, RSVD2, RSVD3, RSVD4, 0x31bc, N, N, N), - PINGROUP(gmi_wp_n_pc7, RSVD1, NAND, GMI, GMI_ALT, 0x31c0, N, N, N), - PINGROUP(gmi_iordy_pi5, SDMMC2, RSVD2, GMI, TRACE, 0x31c4, N, N, N), - PINGROUP(gmi_wait_pi7, SPI4, NAND, GMI, DTV, 0x31c8, N, N, N), - PINGROUP(gmi_adv_n_pk0, RSVD1, NAND, GMI, TRACE, 0x31cc, N, N, N), - PINGROUP(gmi_clk_pk1, SDMMC2, NAND, GMI, TRACE, 0x31d0, N, N, N), - PINGROUP(gmi_cs0_n_pj0, RSVD1, NAND, GMI, USB, 0x31d4, N, N, N), - PINGROUP(gmi_cs1_n_pj2, RSVD1, NAND, GMI, SOC, 0x31d8, N, N, N), - PINGROUP(gmi_cs2_n_pk3, SDMMC2, NAND, GMI, TRACE, 0x31dc, N, N, N), - PINGROUP(gmi_cs3_n_pk4, SDMMC2, NAND, GMI, GMI_ALT, 0x31e0, N, N, N), - PINGROUP(gmi_cs4_n_pk2, USB, NAND, GMI, TRACE, 0x31e4, N, N, N), - PINGROUP(gmi_cs6_n_pi3, NAND, NAND_ALT, GMI, SPI4, 0x31e8, N, N, N), - PINGROUP(gmi_cs7_n_pi6, NAND, NAND_ALT, GMI, SDMMC2, 0x31ec, N, N, N), - PINGROUP(gmi_ad0_pg0, RSVD1, NAND, GMI, RSVD4, 0x31f0, N, N, N), - PINGROUP(gmi_ad1_pg1, RSVD1, NAND, GMI, RSVD4, 0x31f4, N, N, N), - PINGROUP(gmi_ad2_pg2, RSVD1, NAND, GMI, RSVD4, 0x31f8, N, N, N), - PINGROUP(gmi_ad3_pg3, RSVD1, NAND, GMI, RSVD4, 0x31fc, N, N, N), - PINGROUP(gmi_ad4_pg4, RSVD1, NAND, GMI, RSVD4, 0x3200, N, N, N), - PINGROUP(gmi_ad5_pg5, RSVD1, NAND, GMI, SPI4, 0x3204, N, N, N), - PINGROUP(gmi_ad6_pg6, RSVD1, NAND, GMI, SPI4, 0x3208, N, N, N), - PINGROUP(gmi_ad7_pg7, RSVD1, NAND, GMI, SPI4, 0x320c, N, N, N), - PINGROUP(gmi_ad8_ph0, PWM0, NAND, GMI, DTV, 0x3210, N, N, N), - PINGROUP(gmi_ad9_ph1, PWM1, NAND, GMI, CLDVFS, 0x3214, N, N, N), - PINGROUP(gmi_ad10_ph2, PWM2, NAND, GMI, CLDVFS, 0x3218, N, N, N), - PINGROUP(gmi_ad11_ph3, PWM3, NAND, GMI, USB, 0x321c, N, N, N), - PINGROUP(gmi_ad12_ph4, SDMMC2, NAND, GMI, RSVD4, 0x3220, N, N, N), - PINGROUP(gmi_ad13_ph5, SDMMC2, NAND, GMI, RSVD4, 0x3224, N, N, N), - PINGROUP(gmi_ad14_ph6, SDMMC2, NAND, GMI, DTV, 0x3228, N, N, N), - PINGROUP(gmi_ad15_ph7, SDMMC2, NAND, GMI, DTV, 0x322c, N, N, N), - PINGROUP(gmi_a16_pj7, UARTD, TRACE, GMI, GMI_ALT, 0x3230, N, N, N), - PINGROUP(gmi_a17_pb0, UARTD, RSVD2, GMI, TRACE, 0x3234, N, N, N), - PINGROUP(gmi_a18_pb1, UARTD, RSVD2, GMI, TRACE, 0x3238, N, N, N), - PINGROUP(gmi_a19_pk7, UARTD, SPI4, GMI, TRACE, 0x323c, N, N, N), - PINGROUP(gmi_wr_n_pi0, RSVD1, NAND, GMI, SPI4, 0x3240, N, N, N), - PINGROUP(gmi_oe_n_pi1, RSVD1, NAND, GMI, SOC, 0x3244, N, N, N), - PINGROUP(gmi_dqs_p_pj3, SDMMC2, NAND, GMI, TRACE, 0x3248, N, N, N), - PINGROUP(gmi_rst_n_pi4, NAND, NAND_ALT, GMI, RSVD4, 0x324c, N, N, N), - PINGROUP(gen2_i2c_scl_pt5, I2C2, RSVD2, GMI, RSVD4, 0x3250, Y, N, N), - PINGROUP(gen2_i2c_sda_pt6, I2C2, RSVD2, GMI, RSVD4, 0x3254, Y, N, N), - PINGROUP(sdmmc4_clk_pcc4, SDMMC4, RSVD2, GMI, RSVD4, 0x3258, N, Y, N), - PINGROUP(sdmmc4_cmd_pt7, SDMMC4, RSVD2, GMI, RSVD4, 0x325c, N, Y, N), - PINGROUP(sdmmc4_dat0_paa0, SDMMC4, SPI3, GMI, RSVD4, 0x3260, N, Y, N), - PINGROUP(sdmmc4_dat1_paa1, SDMMC4, SPI3, GMI, RSVD4, 0x3264, N, Y, N), - PINGROUP(sdmmc4_dat2_paa2, SDMMC4, SPI3, GMI, RSVD4, 0x3268, N, Y, N), - PINGROUP(sdmmc4_dat3_paa3, SDMMC4, SPI3, GMI, RSVD4, 0x326c, N, Y, N), - PINGROUP(sdmmc4_dat4_paa4, SDMMC4, SPI3, GMI, RSVD4, 0x3270, N, Y, N), - PINGROUP(sdmmc4_dat5_paa5, SDMMC4, SPI3, GMI, RSVD4, 0x3274, N, Y, N), - PINGROUP(sdmmc4_dat6_paa6, SDMMC4, SPI3, GMI, RSVD4, 0x3278, N, Y, N), - PINGROUP(sdmmc4_dat7_paa7, SDMMC4, RSVD2, GMI, RSVD4, 0x327c, N, Y, N), - PINGROUP(cam_mclk_pcc0, VI, VI_ALT1, VI_ALT3, RSVD4, 0x3284, N, N, N), - PINGROUP(pcc1, I2S4, RSVD2, RSVD3, RSVD4, 0x3288, N, N, N), - PINGROUP(pbb0, I2S4, VI, VI_ALT1, VI_ALT3, 0x328c, N, N, N), - PINGROUP(cam_i2c_scl_pbb1, VGP1, I2C3, RSVD3, RSVD4, 0x3290, Y, N, N), - PINGROUP(cam_i2c_sda_pbb2, VGP2, I2C3, RSVD3, RSVD4, 0x3294, Y, N, N), - PINGROUP(pbb3, VGP3, DISPLAYA, DISPLAYB, RSVD4, 0x3298, N, N, N), - PINGROUP(pbb4, VGP4, DISPLAYA, DISPLAYB, RSVD4, 0x329c, N, N, N), - PINGROUP(pbb5, VGP5, DISPLAYA, DISPLAYB, RSVD4, 0x32a0, N, N, N), - PINGROUP(pbb6, VGP6, DISPLAYA, DISPLAYB, RSVD4, 0x32a4, N, N, N), - PINGROUP(pbb7, I2S4, RSVD2, RSVD3, RSVD4, 0x32a8, N, N, N), - PINGROUP(pcc2, I2S4, RSVD2, RSVD3, RSVD4, 0x32ac, N, N, N), - PINGROUP(jtag_rtck, RTCK, RSVD2, RSVD3, RSVD4, 0x32b0, N, N, N), - PINGROUP(pwr_i2c_scl_pz6, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b4, Y, N, N), - PINGROUP(pwr_i2c_sda_pz7, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b8, Y, N, N), - PINGROUP(kb_row0_pr0, KBC, RSVD2, RSVD3, RSVD4, 0x32bc, N, N, N), - PINGROUP(kb_row1_pr1, KBC, RSVD2, RSVD3, RSVD4, 0x32c0, N, N, N), - PINGROUP(kb_row2_pr2, KBC, RSVD2, RSVD3, RSVD4, 0x32c4, N, N, N), - PINGROUP(kb_row3_pr3, KBC, DISPLAYA, RSVD3, DISPLAYB, 0x32c8, N, N, N), - PINGROUP(kb_row4_pr4, KBC, DISPLAYA, SPI2, DISPLAYB, 0x32cc, N, N, N), - PINGROUP(kb_row5_pr5, KBC, DISPLAYA, SPI2, DISPLAYB, 0x32d0, N, N, N), - PINGROUP(kb_row6_pr6, KBC, DISPLAYA, DISPLAYA_ALT, DISPLAYB, 0x32d4, N, N, N), - PINGROUP(kb_row7_pr7, KBC, RSVD2, CLDVFS, UARTA, 0x32d8, N, N, N), - PINGROUP(kb_row8_ps0, KBC, RSVD2, CLDVFS, UARTA, 0x32dc, N, N, N), - PINGROUP(kb_row9_ps1, KBC, RSVD2, RSVD3, UARTA, 0x32e0, N, N, N), - PINGROUP(kb_row10_ps2, KBC, RSVD2, RSVD3, UARTA, 0x32e4, N, N, N), - PINGROUP(kb_col0_pq0, KBC, USB, SPI2, EMC_DLL, 0x32fc, N, N, N), - PINGROUP(kb_col1_pq1, KBC, RSVD2, SPI2, EMC_DLL, 0x3300, N, N, N), - PINGROUP(kb_col2_pq2, KBC, RSVD2, SPI2, RSVD4, 0x3304, N, N, N), - PINGROUP(kb_col3_pq3, KBC, DISPLAYA, PWM2, UARTA, 0x3308, N, N, N), - PINGROUP(kb_col4_pq4, KBC, OWR, SDMMC3, UARTA, 0x330c, N, N, N), - PINGROUP(kb_col5_pq5, KBC, RSVD2, SDMMC1, RSVD4, 0x3310, N, N, N), - PINGROUP(kb_col6_pq6, KBC, RSVD2, SPI2, RSVD4, 0x3314, N, N, N), - PINGROUP(kb_col7_pq7, KBC, RSVD2, SPI2, RSVD4, 0x3318, N, N, N), - PINGROUP(clk_32k_out_pa0, BLINK, SOC, RSVD3, RSVD4, 0x331c, N, N, N), - PINGROUP(sys_clk_req_pz5, SYSCLK, RSVD2, RSVD3, RSVD4, 0x3320, N, N, N), - PINGROUP(core_pwr_req, PWRON, RSVD2, RSVD3, RSVD4, 0x3324, N, N, N), - PINGROUP(cpu_pwr_req, CPU, RSVD2, RSVD3, RSVD4, 0x3328, N, N, N), - PINGROUP(pwr_int_n, PMI, RSVD2, RSVD3, RSVD4, 0x332c, N, N, N), - PINGROUP(clk_32k_in, CLK, RSVD2, RSVD3, RSVD4, 0x3330, N, N, N), - PINGROUP(owr, OWR, RSVD2, RSVD3, RSVD4, 0x3334, N, N, Y), - PINGROUP(dap1_fs_pn0, I2S0, HDA, GMI, RSVD4, 0x3338, N, N, N), - PINGROUP(dap1_din_pn1, I2S0, HDA, GMI, RSVD4, 0x333c, N, N, N), - PINGROUP(dap1_dout_pn2, I2S0, HDA, GMI, RSVD4, 0x3340, N, N, N), - PINGROUP(dap1_sclk_pn3, I2S0, HDA, GMI, RSVD4, 0x3344, N, N, N), - PINGROUP(clk1_req_pee2, DAP, DAP1, RSVD3, RSVD4, 0x3348, N, N, N), - PINGROUP(clk1_out_pw4, EXTPERIPH1, DAP2, RSVD3, RSVD4, 0x334c, N, N, N), - PINGROUP(spdif_in_pk6, SPDIF, USB, RSVD3, RSVD4, 0x3350, N, N, N), - PINGROUP(spdif_out_pk5, SPDIF, RSVD2, RSVD3, RSVD4, 0x3354, N, N, N), - PINGROUP(dap2_fs_pa2, I2S1, HDA, RSVD3, RSVD4, 0x3358, N, N, N), - PINGROUP(dap2_din_pa4, I2S1, HDA, RSVD3, RSVD4, 0x335c, N, N, N), - PINGROUP(dap2_dout_pa5, I2S1, HDA, RSVD3, RSVD4, 0x3360, N, N, N), - PINGROUP(dap2_sclk_pa3, I2S1, HDA, RSVD3, RSVD4, 0x3364, N, N, N), - PINGROUP(dvfs_pwm_px0, SPI6, CLDVFS, RSVD3, RSVD4, 0x3368, N, N, N), - PINGROUP(gpio_x1_aud_px1, SPI6, RSVD2, RSVD3, RSVD4, 0x336c, N, N, N), - PINGROUP(gpio_x3_aud_px3, SPI6, SPI1, RSVD3, RSVD4, 0x3370, N, N, N), - PINGROUP(dvfs_clk_px2, SPI6, CLDVFS, RSVD3, RSVD4, 0x3374, N, N, N), - PINGROUP(gpio_x4_aud_px4, RSVD1, SPI1, SPI2, DAP2, 0x3378, N, N, N), - PINGROUP(gpio_x5_aud_px5, RSVD1, SPI1, SPI2, RSVD4, 0x337c, N, N, N), - PINGROUP(gpio_x6_aud_px6, SPI6, SPI1, SPI2, RSVD4, 0x3380, N, N, N), - PINGROUP(gpio_x7_aud_px7, RSVD1, SPI1, SPI2, RSVD4, 0x3384, N, N, N), - PINGROUP(sdmmc3_clk_pa6, SDMMC3, RSVD2, RSVD3, SPI3, 0x3390, N, N, N), - PINGROUP(sdmmc3_cmd_pa7, SDMMC3, PWM3, UARTA, SPI3, 0x3394, N, N, N), - PINGROUP(sdmmc3_dat0_pb7, SDMMC3, RSVD2, RSVD3, SPI3, 0x3398, N, N, N), - PINGROUP(sdmmc3_dat1_pb6, SDMMC3, PWM2, UARTA, SPI3, 0x339c, N, N, N), - PINGROUP(sdmmc3_dat2_pb5, SDMMC3, PWM1, DISPLAYA, SPI3, 0x33a0, N, N, N), - PINGROUP(sdmmc3_dat3_pb4, SDMMC3, PWM0, DISPLAYB, SPI3, 0x33a4, N, N, N), - PINGROUP(hdmi_cec_pee3, CEC, SDMMC3, RSVD3, SOC, 0x33e0, Y, N, N), - PINGROUP(sdmmc1_wp_n_pv3, SDMMC1, CLK12, SPI4, UARTA, 0x33e4, N, N, N), - PINGROUP(sdmmc3_cd_n_pv2, SDMMC3, OWR, RSVD3, RSVD4, 0x33e8, N, N, N), - PINGROUP(gpio_w2_aud_pw2, SPI6, RSVD2, SPI2, I2C1, 0x33ec, N, N, N), - PINGROUP(gpio_w3_aud_pw3, SPI6, SPI1, SPI2, I2C1, 0x33f0, N, N, N), - PINGROUP(usb_vbus_en0_pn4, USB, RSVD2, RSVD3, RSVD4, 0x33f4, Y, N, N), - PINGROUP(usb_vbus_en1_pn5, USB, RSVD2, RSVD3, RSVD4, 0x33f8, Y, N, N), - PINGROUP(sdmmc3_clk_lb_in_pee5, SDMMC3, RSVD2, RSVD3, RSVD4, 0x33fc, N, N, N), - PINGROUP(sdmmc3_clk_lb_out_pee4, SDMMC3, RSVD2, RSVD3, RSVD4, 0x3400, N, N, N), - PINGROUP(gmi_clk_lb, SDMMC2, NAND, GMI, RSVD4, 0x3404, N, N, N), - PINGROUP(reset_out_n, RSVD1, RSVD2, RSVD3, RESET_OUT_N, 0x3408, N, N, N), - - /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w, drvtype */ - DRV_PINGROUP(ao1, 0x868, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(ao2, 0x86c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(at1, 0x870, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(at2, 0x874, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(at3, 0x878, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(at4, 0x87c, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(at5, 0x880, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(cdev1, 0x884, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(cdev2, 0x888, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dap1, 0x890, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dap2, 0x894, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dap3, 0x898, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dap4, 0x89c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dbg, 0x8a0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(sdio3, 0x8b0, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), - DRV_PINGROUP(spi, 0x8b4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uaa, 0x8b8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uab, 0x8bc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uart2, 0x8c0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uart3, 0x8c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(sdio1, 0x8ec, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), - DRV_PINGROUP(ddc, 0x8fc, 2, 3, -1, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gma, 0x900, 2, 3, -1, 14, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gme, 0x910, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gmf, 0x914, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gmg, 0x918, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gmh, 0x91c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(owr, 0x920, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uda, 0x924, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dev3, 0x92c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(cec, 0x938, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(at6, 0x994, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, Y), - DRV_PINGROUP(dap5, 0x998, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(usb_vbus_en, 0x99c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(ao3, 0x9a0, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), - DRV_PINGROUP(hv0, 0x9a4, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), - DRV_PINGROUP(sdio4, 0x9a8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(ao0, 0x9ac, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), -}; - -static const struct tegra_pinctrl_soc_data tegra114_pinctrl = { - .ngpios = NUM_GPIOS, - .pins = tegra114_pins, - .npins = ARRAY_SIZE(tegra114_pins), - .functions = tegra114_functions, - .nfunctions = ARRAY_SIZE(tegra114_functions), - .groups = tegra114_groups, - .ngroups = ARRAY_SIZE(tegra114_groups), - .hsm_in_mux = false, - .schmitt_in_mux = false, - .drvtype_in_mux = false, -}; - -static int tegra114_pinctrl_probe(struct platform_device *pdev) -{ - return tegra_pinctrl_probe(pdev, &tegra114_pinctrl); -} - -static const struct of_device_id tegra114_pinctrl_of_match[] = { - { .compatible = "nvidia,tegra114-pinmux", }, - { }, -}; -MODULE_DEVICE_TABLE(of, tegra114_pinctrl_of_match); - -static struct platform_driver tegra114_pinctrl_driver = { - .driver = { - .name = "tegra114-pinctrl", - .of_match_table = tegra114_pinctrl_of_match, - }, - .probe = tegra114_pinctrl_probe, - .remove = tegra_pinctrl_remove, -}; -module_platform_driver(tegra114_pinctrl_driver); - -MODULE_AUTHOR("Pritesh Raithatha "); -MODULE_DESCRIPTION("NVIDIA Tegra114 pinctrl driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/pinctrl-tegra124.c b/drivers/pinctrl/pinctrl-tegra124.c deleted file mode 100644 index 7cd44c7c296d..000000000000 --- a/drivers/pinctrl/pinctrl-tegra124.c +++ /dev/null @@ -1,2084 +0,0 @@ -/* - * Pinctrl data for the NVIDIA Tegra124 pinmux - * - * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - */ - -#include -#include -#include -#include -#include - -#include "pinctrl-tegra.h" - -/* - * Most pins affected by the pinmux can also be GPIOs. Define these first. - * These must match how the GPIO driver names/numbers its pins. - */ -#define _GPIO(offset) (offset) - -#define TEGRA_PIN_CLK_32K_OUT_PA0 _GPIO(0) -#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) -#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) -#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) -#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) -#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) -#define TEGRA_PIN_SDMMC3_CLK_PA6 _GPIO(6) -#define TEGRA_PIN_SDMMC3_CMD_PA7 _GPIO(7) -#define TEGRA_PIN_PB0 _GPIO(8) -#define TEGRA_PIN_PB1 _GPIO(9) -#define TEGRA_PIN_SDMMC3_DAT3_PB4 _GPIO(12) -#define TEGRA_PIN_SDMMC3_DAT2_PB5 _GPIO(13) -#define TEGRA_PIN_SDMMC3_DAT1_PB6 _GPIO(14) -#define TEGRA_PIN_SDMMC3_DAT0_PB7 _GPIO(15) -#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) -#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) -#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) -#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) -#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) -#define TEGRA_PIN_PC7 _GPIO(23) -#define TEGRA_PIN_PG0 _GPIO(48) -#define TEGRA_PIN_PG1 _GPIO(49) -#define TEGRA_PIN_PG2 _GPIO(50) -#define TEGRA_PIN_PG3 _GPIO(51) -#define TEGRA_PIN_PG4 _GPIO(52) -#define TEGRA_PIN_PG5 _GPIO(53) -#define TEGRA_PIN_PG6 _GPIO(54) -#define TEGRA_PIN_PG7 _GPIO(55) -#define TEGRA_PIN_PH0 _GPIO(56) -#define TEGRA_PIN_PH1 _GPIO(57) -#define TEGRA_PIN_PH2 _GPIO(58) -#define TEGRA_PIN_PH3 _GPIO(59) -#define TEGRA_PIN_PH4 _GPIO(60) -#define TEGRA_PIN_PH5 _GPIO(61) -#define TEGRA_PIN_PH6 _GPIO(62) -#define TEGRA_PIN_PH7 _GPIO(63) -#define TEGRA_PIN_PI0 _GPIO(64) -#define TEGRA_PIN_PI1 _GPIO(65) -#define TEGRA_PIN_PI2 _GPIO(66) -#define TEGRA_PIN_PI3 _GPIO(67) -#define TEGRA_PIN_PI4 _GPIO(68) -#define TEGRA_PIN_PI5 _GPIO(69) -#define TEGRA_PIN_PI6 _GPIO(70) -#define TEGRA_PIN_PI7 _GPIO(71) -#define TEGRA_PIN_PJ0 _GPIO(72) -#define TEGRA_PIN_PJ2 _GPIO(74) -#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) -#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) -#define TEGRA_PIN_PJ7 _GPIO(79) -#define TEGRA_PIN_PK0 _GPIO(80) -#define TEGRA_PIN_PK1 _GPIO(81) -#define TEGRA_PIN_PK2 _GPIO(82) -#define TEGRA_PIN_PK3 _GPIO(83) -#define TEGRA_PIN_PK4 _GPIO(84) -#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) -#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) -#define TEGRA_PIN_PK7 _GPIO(87) -#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) -#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) -#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) -#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) -#define TEGRA_PIN_USB_VBUS_EN0_PN4 _GPIO(108) -#define TEGRA_PIN_USB_VBUS_EN1_PN5 _GPIO(109) -#define TEGRA_PIN_HDMI_INT_PN7 _GPIO(111) -#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) -#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) -#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) -#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) -#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) -#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) -#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) -#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) -#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) -#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) -#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) -#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) -#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) -#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) -#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) -#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) -#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) -#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) -#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) -#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) -#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) -#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) -#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) -#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) -#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) -#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) -#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) -#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) -#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) -#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) -#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) -#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) -#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) -#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) -#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) -#define TEGRA_PIN_KB_ROW11_PS3 _GPIO(147) -#define TEGRA_PIN_KB_ROW12_PS4 _GPIO(148) -#define TEGRA_PIN_KB_ROW13_PS5 _GPIO(149) -#define TEGRA_PIN_KB_ROW14_PS6 _GPIO(150) -#define TEGRA_PIN_KB_ROW15_PS7 _GPIO(151) -#define TEGRA_PIN_KB_ROW16_PT0 _GPIO(152) -#define TEGRA_PIN_KB_ROW17_PT1 _GPIO(153) -#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) -#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) -#define TEGRA_PIN_SDMMC4_CMD_PT7 _GPIO(159) -#define TEGRA_PIN_PU0 _GPIO(160) -#define TEGRA_PIN_PU1 _GPIO(161) -#define TEGRA_PIN_PU2 _GPIO(162) -#define TEGRA_PIN_PU3 _GPIO(163) -#define TEGRA_PIN_PU4 _GPIO(164) -#define TEGRA_PIN_PU5 _GPIO(165) -#define TEGRA_PIN_PU6 _GPIO(166) -#define TEGRA_PIN_PV0 _GPIO(168) -#define TEGRA_PIN_PV1 _GPIO(169) -#define TEGRA_PIN_SDMMC3_CD_N_PV2 _GPIO(170) -#define TEGRA_PIN_SDMMC1_WP_N_PV3 _GPIO(171) -#define TEGRA_PIN_DDC_SCL_PV4 _GPIO(172) -#define TEGRA_PIN_DDC_SDA_PV5 _GPIO(173) -#define TEGRA_PIN_GPIO_W2_AUD_PW2 _GPIO(178) -#define TEGRA_PIN_GPIO_W3_AUD_PW3 _GPIO(179) -#define TEGRA_PIN_DAP_MCLK1_PW4 _GPIO(180) -#define TEGRA_PIN_CLK2_OUT_PW5 _GPIO(181) -#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) -#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) -#define TEGRA_PIN_DVFS_PWM_PX0 _GPIO(184) -#define TEGRA_PIN_GPIO_X1_AUD_PX1 _GPIO(185) -#define TEGRA_PIN_DVFS_CLK_PX2 _GPIO(186) -#define TEGRA_PIN_GPIO_X3_AUD_PX3 _GPIO(187) -#define TEGRA_PIN_GPIO_X4_AUD_PX4 _GPIO(188) -#define TEGRA_PIN_GPIO_X5_AUD_PX5 _GPIO(189) -#define TEGRA_PIN_GPIO_X6_AUD_PX6 _GPIO(190) -#define TEGRA_PIN_GPIO_X7_AUD_PX7 _GPIO(191) -#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) -#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) -#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) -#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) -#define TEGRA_PIN_SDMMC1_DAT3_PY4 _GPIO(196) -#define TEGRA_PIN_SDMMC1_DAT2_PY5 _GPIO(197) -#define TEGRA_PIN_SDMMC1_DAT1_PY6 _GPIO(198) -#define TEGRA_PIN_SDMMC1_DAT0_PY7 _GPIO(199) -#define TEGRA_PIN_SDMMC1_CLK_PZ0 _GPIO(200) -#define TEGRA_PIN_SDMMC1_CMD_PZ1 _GPIO(201) -#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) -#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) -#define TEGRA_PIN_SDMMC4_DAT0_PAA0 _GPIO(208) -#define TEGRA_PIN_SDMMC4_DAT1_PAA1 _GPIO(209) -#define TEGRA_PIN_SDMMC4_DAT2_PAA2 _GPIO(210) -#define TEGRA_PIN_SDMMC4_DAT3_PAA3 _GPIO(211) -#define TEGRA_PIN_SDMMC4_DAT4_PAA4 _GPIO(212) -#define TEGRA_PIN_SDMMC4_DAT5_PAA5 _GPIO(213) -#define TEGRA_PIN_SDMMC4_DAT6_PAA6 _GPIO(214) -#define TEGRA_PIN_SDMMC4_DAT7_PAA7 _GPIO(215) -#define TEGRA_PIN_PBB0 _GPIO(216) -#define TEGRA_PIN_CAM_I2C_SCL_PBB1 _GPIO(217) -#define TEGRA_PIN_CAM_I2C_SDA_PBB2 _GPIO(218) -#define TEGRA_PIN_PBB3 _GPIO(219) -#define TEGRA_PIN_PBB4 _GPIO(220) -#define TEGRA_PIN_PBB5 _GPIO(221) -#define TEGRA_PIN_PBB6 _GPIO(222) -#define TEGRA_PIN_PBB7 _GPIO(223) -#define TEGRA_PIN_CAM_MCLK_PCC0 _GPIO(224) -#define TEGRA_PIN_PCC1 _GPIO(225) -#define TEGRA_PIN_PCC2 _GPIO(226) -#define TEGRA_PIN_SDMMC4_CLK_PCC4 _GPIO(228) -#define TEGRA_PIN_CLK2_REQ_PCC5 _GPIO(229) -#define TEGRA_PIN_PEX_L0_RST_N_PDD1 _GPIO(233) -#define TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2 _GPIO(234) -#define TEGRA_PIN_PEX_WAKE_N_PDD3 _GPIO(235) -#define TEGRA_PIN_PEX_L1_RST_N_PDD5 _GPIO(237) -#define TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6 _GPIO(238) -#define TEGRA_PIN_CLK3_OUT_PEE0 _GPIO(240) -#define TEGRA_PIN_CLK3_REQ_PEE1 _GPIO(241) -#define TEGRA_PIN_DAP_MCLK1_REQ_PEE2 _GPIO(242) -#define TEGRA_PIN_HDMI_CEC_PEE3 _GPIO(243) -#define TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4 _GPIO(244) -#define TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5 _GPIO(245) -#define TEGRA_PIN_DP_HPD_PFF0 _GPIO(248) -#define TEGRA_PIN_USB_VBUS_EN2_PFF1 _GPIO(249) -#define TEGRA_PIN_PFF2 _GPIO(250) - -/* All non-GPIO pins follow */ -#define NUM_GPIOS (TEGRA_PIN_PFF2 + 1) -#define _PIN(offset) (NUM_GPIOS + (offset)) - -/* Non-GPIO pins */ -#define TEGRA_PIN_CORE_PWR_REQ _PIN(0) -#define TEGRA_PIN_CPU_PWR_REQ _PIN(1) -#define TEGRA_PIN_PWR_INT_N _PIN(2) -#define TEGRA_PIN_GMI_CLK_LB _PIN(3) -#define TEGRA_PIN_RESET_OUT_N _PIN(4) -#define TEGRA_PIN_OWR _PIN(5) -#define TEGRA_PIN_CLK_32K_IN _PIN(6) -#define TEGRA_PIN_JTAG_RTCK _PIN(7) -#define TEGRA_PIN_DSI_B_CLK_P _PIN(8) -#define TEGRA_PIN_DSI_B_CLK_N _PIN(9) -#define TEGRA_PIN_DSI_B_D0_P _PIN(10) -#define TEGRA_PIN_DSI_B_D0_N _PIN(11) -#define TEGRA_PIN_DSI_B_D1_P _PIN(12) -#define TEGRA_PIN_DSI_B_D1_N _PIN(13) -#define TEGRA_PIN_DSI_B_D2_P _PIN(14) -#define TEGRA_PIN_DSI_B_D2_N _PIN(15) -#define TEGRA_PIN_DSI_B_D3_P _PIN(16) -#define TEGRA_PIN_DSI_B_D3_N _PIN(17) - -static const struct pinctrl_pin_desc tegra124_pins[] = { - PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"), - PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), - PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), - PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"), - PINCTRL_PIN(TEGRA_PIN_PB0, "PB0"), - PINCTRL_PIN(TEGRA_PIN_PB1, "PB1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"), - PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), - PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), - PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), - PINCTRL_PIN(TEGRA_PIN_PC7, "PC7"), - PINCTRL_PIN(TEGRA_PIN_PG0, "PG0"), - PINCTRL_PIN(TEGRA_PIN_PG1, "PG1"), - PINCTRL_PIN(TEGRA_PIN_PG2, "PG2"), - PINCTRL_PIN(TEGRA_PIN_PG3, "PG3"), - PINCTRL_PIN(TEGRA_PIN_PG4, "PG4"), - PINCTRL_PIN(TEGRA_PIN_PG5, "PG5"), - PINCTRL_PIN(TEGRA_PIN_PG6, "PG6"), - PINCTRL_PIN(TEGRA_PIN_PG7, "PG7"), - PINCTRL_PIN(TEGRA_PIN_PH0, "PH0"), - PINCTRL_PIN(TEGRA_PIN_PH1, "PH1"), - PINCTRL_PIN(TEGRA_PIN_PH2, "PH2"), - PINCTRL_PIN(TEGRA_PIN_PH3, "PH3"), - PINCTRL_PIN(TEGRA_PIN_PH4, "PH4"), - PINCTRL_PIN(TEGRA_PIN_PH5, "PH5"), - PINCTRL_PIN(TEGRA_PIN_PH6, "PH6"), - PINCTRL_PIN(TEGRA_PIN_PH7, "PH7"), - PINCTRL_PIN(TEGRA_PIN_PI0, "PI0"), - PINCTRL_PIN(TEGRA_PIN_PI1, "PI1"), - PINCTRL_PIN(TEGRA_PIN_PI2, "PI2"), - PINCTRL_PIN(TEGRA_PIN_PI3, "PI3"), - PINCTRL_PIN(TEGRA_PIN_PI4, "PI4"), - PINCTRL_PIN(TEGRA_PIN_PI5, "PI5"), - PINCTRL_PIN(TEGRA_PIN_PI6, "PI6"), - PINCTRL_PIN(TEGRA_PIN_PI7, "PI7"), - PINCTRL_PIN(TEGRA_PIN_PJ0, "PJ0"), - PINCTRL_PIN(TEGRA_PIN_PJ2, "PJ2"), - PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), - PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), - PINCTRL_PIN(TEGRA_PIN_PJ7, "PJ7"), - PINCTRL_PIN(TEGRA_PIN_PK0, "PK0"), - PINCTRL_PIN(TEGRA_PIN_PK1, "PK1"), - PINCTRL_PIN(TEGRA_PIN_PK2, "PK2"), - PINCTRL_PIN(TEGRA_PIN_PK3, "PK3"), - PINCTRL_PIN(TEGRA_PIN_PK4, "PK4"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), - PINCTRL_PIN(TEGRA_PIN_PK7, "PK7"), - PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), - PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), - PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PN4, "USB_VBUS_EN0 PN4"), - PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PN5, "USB_VBUS_EN1 PN5"), - PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), - PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), - PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), - PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), - PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), - PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), - PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), - PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), - PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), - PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), - PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), - PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), - PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), - PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), - PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW16_PT0, "KB_ROW16 PT0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW17_PT1, "KB_ROW17 PT1"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"), - PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), - PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), - PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), - PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), - PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), - PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), - PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), - PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), - PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CD_N_PV2, "SDMMC3_CD_N PV2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_WP_N_PV3, "SDMMC1_WP_N PV3"), - PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"), - PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"), - PINCTRL_PIN(TEGRA_PIN_GPIO_W2_AUD_PW2, "GPIO_W2_AUD PW2"), - PINCTRL_PIN(TEGRA_PIN_GPIO_W3_AUD_PW3, "GPIO_W3_AUD PW3"), - PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_PW4, "DAP_MCLK1 PW4"), - PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"), - PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), - PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), - PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PX0, "DVFS_PWM PX0"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PX1, "GPIO_X1_AUD PX1"), - PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PX2, "DVFS_CLK PX2"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PX3, "GPIO_X3_AUD PX3"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X4_AUD_PX4, "GPIO_X4_AUD PX4"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X5_AUD_PX5, "GPIO_X5_AUD PX5"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X6_AUD_PX6, "GPIO_X6_AUD PX6"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X7_AUD_PX7, "GPIO_X7_AUD PX7"), - PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), - PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), - PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"), - PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"), - PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"), - PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"), - PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"), - PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), - PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), - PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"), - PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"), - PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"), - PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"), - PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PDD1, "PEX_L0_RST_N PDD1"), - PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, "PEX_L0_CLKREQ_N PDD2"), - PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PDD3, "PEX_WAKE_N PDD3"), - PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PDD5, "PEX_L1_RST_N PDD5"), - PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, "PEX_L1_CLKREQ_N PDD6"), - PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"), - PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"), - PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_REQ_PEE2, "DAP_MCLK1_REQ PEE2"), - PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, "SDMMC3_CLK_LB_OUT PEE4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, "SDMMC3_CLK_LB_IN PEE5"), - PINCTRL_PIN(TEGRA_PIN_DP_HPD_PFF0, "DP_HPD PFF0"), - PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN2_PFF1, "USB_VBUS_EN2 PFF1"), - PINCTRL_PIN(TEGRA_PIN_PFF2, "PFF2"), - PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), - PINCTRL_PIN(TEGRA_PIN_GMI_CLK_LB, "GMI_CLK_LB"), - PINCTRL_PIN(TEGRA_PIN_RESET_OUT_N, "RESET_OUT_N"), - PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"), - PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), - PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_CLK_P, "DSI_B_CLK_P"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_CLK_N, "DSI_B_CLK_N"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_D0_P, "DSI_B_D0_P"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_D0_N, "DSI_B_D0_N"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_D1_P, "DSI_B_D1_P"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_D1_N, "DSI_B_D1_N"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_D2_P, "DSI_B_D2_P"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_D2_N, "DSI_B_D2_N"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_D3_P, "DSI_B_D3_P"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_D3_N, "DSI_B_D3_N"), -}; - -static const unsigned clk_32k_out_pa0_pins[] = { - TEGRA_PIN_CLK_32K_OUT_PA0, -}; - -static const unsigned uart3_cts_n_pa1_pins[] = { - TEGRA_PIN_UART3_CTS_N_PA1, -}; - -static const unsigned dap2_fs_pa2_pins[] = { - TEGRA_PIN_DAP2_FS_PA2, -}; - -static const unsigned dap2_sclk_pa3_pins[] = { - TEGRA_PIN_DAP2_SCLK_PA3, -}; - -static const unsigned dap2_din_pa4_pins[] = { - TEGRA_PIN_DAP2_DIN_PA4, -}; - -static const unsigned dap2_dout_pa5_pins[] = { - TEGRA_PIN_DAP2_DOUT_PA5, -}; - -static const unsigned sdmmc3_clk_pa6_pins[] = { - TEGRA_PIN_SDMMC3_CLK_PA6, -}; - -static const unsigned sdmmc3_cmd_pa7_pins[] = { - TEGRA_PIN_SDMMC3_CMD_PA7, -}; - -static const unsigned pb0_pins[] = { - TEGRA_PIN_PB0, -}; - -static const unsigned pb1_pins[] = { - TEGRA_PIN_PB1, -}; - -static const unsigned sdmmc3_dat3_pb4_pins[] = { - TEGRA_PIN_SDMMC3_DAT3_PB4, -}; - -static const unsigned sdmmc3_dat2_pb5_pins[] = { - TEGRA_PIN_SDMMC3_DAT2_PB5, -}; - -static const unsigned sdmmc3_dat1_pb6_pins[] = { - TEGRA_PIN_SDMMC3_DAT1_PB6, -}; - -static const unsigned sdmmc3_dat0_pb7_pins[] = { - TEGRA_PIN_SDMMC3_DAT0_PB7, -}; - -static const unsigned uart3_rts_n_pc0_pins[] = { - TEGRA_PIN_UART3_RTS_N_PC0, -}; - -static const unsigned uart2_txd_pc2_pins[] = { - TEGRA_PIN_UART2_TXD_PC2, -}; - -static const unsigned uart2_rxd_pc3_pins[] = { - TEGRA_PIN_UART2_RXD_PC3, -}; - -static const unsigned gen1_i2c_scl_pc4_pins[] = { - TEGRA_PIN_GEN1_I2C_SCL_PC4, -}; - -static const unsigned gen1_i2c_sda_pc5_pins[] = { - TEGRA_PIN_GEN1_I2C_SDA_PC5, -}; - -static const unsigned pc7_pins[] = { - TEGRA_PIN_PC7, -}; - -static const unsigned pg0_pins[] = { - TEGRA_PIN_PG0, -}; - -static const unsigned pg1_pins[] = { - TEGRA_PIN_PG1, -}; - -static const unsigned pg2_pins[] = { - TEGRA_PIN_PG2, -}; - -static const unsigned pg3_pins[] = { - TEGRA_PIN_PG3, -}; - -static const unsigned pg4_pins[] = { - TEGRA_PIN_PG4, -}; - -static const unsigned pg5_pins[] = { - TEGRA_PIN_PG5, -}; - -static const unsigned pg6_pins[] = { - TEGRA_PIN_PG6, -}; - -static const unsigned pg7_pins[] = { - TEGRA_PIN_PG7, -}; - -static const unsigned ph0_pins[] = { - TEGRA_PIN_PH0, -}; - -static const unsigned ph1_pins[] = { - TEGRA_PIN_PH1, -}; - -static const unsigned ph2_pins[] = { - TEGRA_PIN_PH2, -}; - -static const unsigned ph3_pins[] = { - TEGRA_PIN_PH3, -}; - -static const unsigned ph4_pins[] = { - TEGRA_PIN_PH4, -}; - -static const unsigned ph5_pins[] = { - TEGRA_PIN_PH5, -}; - -static const unsigned ph6_pins[] = { - TEGRA_PIN_PH6, -}; - -static const unsigned ph7_pins[] = { - TEGRA_PIN_PH7, -}; - -static const unsigned pi0_pins[] = { - TEGRA_PIN_PI0, -}; - -static const unsigned pi1_pins[] = { - TEGRA_PIN_PI1, -}; - -static const unsigned pi2_pins[] = { - TEGRA_PIN_PI2, -}; - -static const unsigned pi3_pins[] = { - TEGRA_PIN_PI3, -}; - -static const unsigned pi4_pins[] = { - TEGRA_PIN_PI4, -}; - -static const unsigned pi5_pins[] = { - TEGRA_PIN_PI5, -}; - -static const unsigned pi6_pins[] = { - TEGRA_PIN_PI6, -}; - -static const unsigned pi7_pins[] = { - TEGRA_PIN_PI7, -}; - -static const unsigned pj0_pins[] = { - TEGRA_PIN_PJ0, -}; - -static const unsigned pj2_pins[] = { - TEGRA_PIN_PJ2, -}; - -static const unsigned uart2_cts_n_pj5_pins[] = { - TEGRA_PIN_UART2_CTS_N_PJ5, -}; - -static const unsigned uart2_rts_n_pj6_pins[] = { - TEGRA_PIN_UART2_RTS_N_PJ6, -}; - -static const unsigned pj7_pins[] = { - TEGRA_PIN_PJ7, -}; - -static const unsigned pk0_pins[] = { - TEGRA_PIN_PK0, -}; - -static const unsigned pk1_pins[] = { - TEGRA_PIN_PK1, -}; - -static const unsigned pk2_pins[] = { - TEGRA_PIN_PK2, -}; - -static const unsigned pk3_pins[] = { - TEGRA_PIN_PK3, -}; - -static const unsigned pk4_pins[] = { - TEGRA_PIN_PK4, -}; - -static const unsigned spdif_out_pk5_pins[] = { - TEGRA_PIN_SPDIF_OUT_PK5, -}; - -static const unsigned spdif_in_pk6_pins[] = { - TEGRA_PIN_SPDIF_IN_PK6, -}; - -static const unsigned pk7_pins[] = { - TEGRA_PIN_PK7, -}; - -static const unsigned dap1_fs_pn0_pins[] = { - TEGRA_PIN_DAP1_FS_PN0, -}; - -static const unsigned dap1_din_pn1_pins[] = { - TEGRA_PIN_DAP1_DIN_PN1, -}; - -static const unsigned dap1_dout_pn2_pins[] = { - TEGRA_PIN_DAP1_DOUT_PN2, -}; - -static const unsigned dap1_sclk_pn3_pins[] = { - TEGRA_PIN_DAP1_SCLK_PN3, -}; - -static const unsigned usb_vbus_en0_pn4_pins[] = { - TEGRA_PIN_USB_VBUS_EN0_PN4, -}; - -static const unsigned usb_vbus_en1_pn5_pins[] = { - TEGRA_PIN_USB_VBUS_EN1_PN5, -}; - -static const unsigned hdmi_int_pn7_pins[] = { - TEGRA_PIN_HDMI_INT_PN7, -}; - -static const unsigned ulpi_data7_po0_pins[] = { - TEGRA_PIN_ULPI_DATA7_PO0, -}; - -static const unsigned ulpi_data0_po1_pins[] = { - TEGRA_PIN_ULPI_DATA0_PO1, -}; - -static const unsigned ulpi_data1_po2_pins[] = { - TEGRA_PIN_ULPI_DATA1_PO2, -}; - -static const unsigned ulpi_data2_po3_pins[] = { - TEGRA_PIN_ULPI_DATA2_PO3, -}; - -static const unsigned ulpi_data3_po4_pins[] = { - TEGRA_PIN_ULPI_DATA3_PO4, -}; - -static const unsigned ulpi_data4_po5_pins[] = { - TEGRA_PIN_ULPI_DATA4_PO5, -}; - -static const unsigned ulpi_data5_po6_pins[] = { - TEGRA_PIN_ULPI_DATA5_PO6, -}; - -static const unsigned ulpi_data6_po7_pins[] = { - TEGRA_PIN_ULPI_DATA6_PO7, -}; - -static const unsigned dap3_fs_pp0_pins[] = { - TEGRA_PIN_DAP3_FS_PP0, -}; - -static const unsigned dap3_din_pp1_pins[] = { - TEGRA_PIN_DAP3_DIN_PP1, -}; - -static const unsigned dap3_dout_pp2_pins[] = { - TEGRA_PIN_DAP3_DOUT_PP2, -}; - -static const unsigned dap3_sclk_pp3_pins[] = { - TEGRA_PIN_DAP3_SCLK_PP3, -}; - -static const unsigned dap4_fs_pp4_pins[] = { - TEGRA_PIN_DAP4_FS_PP4, -}; - -static const unsigned dap4_din_pp5_pins[] = { - TEGRA_PIN_DAP4_DIN_PP5, -}; - -static const unsigned dap4_dout_pp6_pins[] = { - TEGRA_PIN_DAP4_DOUT_PP6, -}; - -static const unsigned dap4_sclk_pp7_pins[] = { - TEGRA_PIN_DAP4_SCLK_PP7, -}; - -static const unsigned kb_col0_pq0_pins[] = { - TEGRA_PIN_KB_COL0_PQ0, -}; - -static const unsigned kb_col1_pq1_pins[] = { - TEGRA_PIN_KB_COL1_PQ1, -}; - -static const unsigned kb_col2_pq2_pins[] = { - TEGRA_PIN_KB_COL2_PQ2, -}; - -static const unsigned kb_col3_pq3_pins[] = { - TEGRA_PIN_KB_COL3_PQ3, -}; - -static const unsigned kb_col4_pq4_pins[] = { - TEGRA_PIN_KB_COL4_PQ4, -}; - -static const unsigned kb_col5_pq5_pins[] = { - TEGRA_PIN_KB_COL5_PQ5, -}; - -static const unsigned kb_col6_pq6_pins[] = { - TEGRA_PIN_KB_COL6_PQ6, -}; - -static const unsigned kb_col7_pq7_pins[] = { - TEGRA_PIN_KB_COL7_PQ7, -}; - -static const unsigned kb_row0_pr0_pins[] = { - TEGRA_PIN_KB_ROW0_PR0, -}; - -static const unsigned kb_row1_pr1_pins[] = { - TEGRA_PIN_KB_ROW1_PR1, -}; - -static const unsigned kb_row2_pr2_pins[] = { - TEGRA_PIN_KB_ROW2_PR2, -}; - -static const unsigned kb_row3_pr3_pins[] = { - TEGRA_PIN_KB_ROW3_PR3, -}; - -static const unsigned kb_row4_pr4_pins[] = { - TEGRA_PIN_KB_ROW4_PR4, -}; - -static const unsigned kb_row5_pr5_pins[] = { - TEGRA_PIN_KB_ROW5_PR5, -}; - -static const unsigned kb_row6_pr6_pins[] = { - TEGRA_PIN_KB_ROW6_PR6, -}; - -static const unsigned kb_row7_pr7_pins[] = { - TEGRA_PIN_KB_ROW7_PR7, -}; - -static const unsigned kb_row8_ps0_pins[] = { - TEGRA_PIN_KB_ROW8_PS0, -}; - -static const unsigned kb_row9_ps1_pins[] = { - TEGRA_PIN_KB_ROW9_PS1, -}; - -static const unsigned kb_row10_ps2_pins[] = { - TEGRA_PIN_KB_ROW10_PS2, -}; - -static const unsigned kb_row11_ps3_pins[] = { - TEGRA_PIN_KB_ROW11_PS3, -}; - -static const unsigned kb_row12_ps4_pins[] = { - TEGRA_PIN_KB_ROW12_PS4, -}; - -static const unsigned kb_row13_ps5_pins[] = { - TEGRA_PIN_KB_ROW13_PS5, -}; - -static const unsigned kb_row14_ps6_pins[] = { - TEGRA_PIN_KB_ROW14_PS6, -}; - -static const unsigned kb_row15_ps7_pins[] = { - TEGRA_PIN_KB_ROW15_PS7, -}; - -static const unsigned kb_row16_pt0_pins[] = { - TEGRA_PIN_KB_ROW16_PT0, -}; - -static const unsigned kb_row17_pt1_pins[] = { - TEGRA_PIN_KB_ROW17_PT1, -}; - -static const unsigned gen2_i2c_scl_pt5_pins[] = { - TEGRA_PIN_GEN2_I2C_SCL_PT5, -}; - -static const unsigned gen2_i2c_sda_pt6_pins[] = { - TEGRA_PIN_GEN2_I2C_SDA_PT6, -}; - -static const unsigned sdmmc4_cmd_pt7_pins[] = { - TEGRA_PIN_SDMMC4_CMD_PT7, -}; - -static const unsigned pu0_pins[] = { - TEGRA_PIN_PU0, -}; - -static const unsigned pu1_pins[] = { - TEGRA_PIN_PU1, -}; - -static const unsigned pu2_pins[] = { - TEGRA_PIN_PU2, -}; - -static const unsigned pu3_pins[] = { - TEGRA_PIN_PU3, -}; - -static const unsigned pu4_pins[] = { - TEGRA_PIN_PU4, -}; - -static const unsigned pu5_pins[] = { - TEGRA_PIN_PU5, -}; - -static const unsigned pu6_pins[] = { - TEGRA_PIN_PU6, -}; - -static const unsigned pv0_pins[] = { - TEGRA_PIN_PV0, -}; - -static const unsigned pv1_pins[] = { - TEGRA_PIN_PV1, -}; - -static const unsigned sdmmc3_cd_n_pv2_pins[] = { - TEGRA_PIN_SDMMC3_CD_N_PV2, -}; - -static const unsigned sdmmc1_wp_n_pv3_pins[] = { - TEGRA_PIN_SDMMC1_WP_N_PV3, -}; - -static const unsigned ddc_scl_pv4_pins[] = { - TEGRA_PIN_DDC_SCL_PV4, -}; - -static const unsigned ddc_sda_pv5_pins[] = { - TEGRA_PIN_DDC_SDA_PV5, -}; - -static const unsigned gpio_w2_aud_pw2_pins[] = { - TEGRA_PIN_GPIO_W2_AUD_PW2, -}; - -static const unsigned gpio_w3_aud_pw3_pins[] = { - TEGRA_PIN_GPIO_W3_AUD_PW3, -}; - -static const unsigned dap_mclk1_pw4_pins[] = { - TEGRA_PIN_DAP_MCLK1_PW4, -}; - -static const unsigned clk2_out_pw5_pins[] = { - TEGRA_PIN_CLK2_OUT_PW5, -}; - -static const unsigned uart3_txd_pw6_pins[] = { - TEGRA_PIN_UART3_TXD_PW6, -}; - -static const unsigned uart3_rxd_pw7_pins[] = { - TEGRA_PIN_UART3_RXD_PW7, -}; - -static const unsigned dvfs_pwm_px0_pins[] = { - TEGRA_PIN_DVFS_PWM_PX0, -}; - -static const unsigned gpio_x1_aud_px1_pins[] = { - TEGRA_PIN_GPIO_X1_AUD_PX1, -}; - -static const unsigned dvfs_clk_px2_pins[] = { - TEGRA_PIN_DVFS_CLK_PX2, -}; - -static const unsigned gpio_x3_aud_px3_pins[] = { - TEGRA_PIN_GPIO_X3_AUD_PX3, -}; - -static const unsigned gpio_x4_aud_px4_pins[] = { - TEGRA_PIN_GPIO_X4_AUD_PX4, -}; - -static const unsigned gpio_x5_aud_px5_pins[] = { - TEGRA_PIN_GPIO_X5_AUD_PX5, -}; - -static const unsigned gpio_x6_aud_px6_pins[] = { - TEGRA_PIN_GPIO_X6_AUD_PX6, -}; - -static const unsigned gpio_x7_aud_px7_pins[] = { - TEGRA_PIN_GPIO_X7_AUD_PX7, -}; - -static const unsigned ulpi_clk_py0_pins[] = { - TEGRA_PIN_ULPI_CLK_PY0, -}; - -static const unsigned ulpi_dir_py1_pins[] = { - TEGRA_PIN_ULPI_DIR_PY1, -}; - -static const unsigned ulpi_nxt_py2_pins[] = { - TEGRA_PIN_ULPI_NXT_PY2, -}; - -static const unsigned ulpi_stp_py3_pins[] = { - TEGRA_PIN_ULPI_STP_PY3, -}; - -static const unsigned sdmmc1_dat3_py4_pins[] = { - TEGRA_PIN_SDMMC1_DAT3_PY4, -}; - -static const unsigned sdmmc1_dat2_py5_pins[] = { - TEGRA_PIN_SDMMC1_DAT2_PY5, -}; - -static const unsigned sdmmc1_dat1_py6_pins[] = { - TEGRA_PIN_SDMMC1_DAT1_PY6, -}; - -static const unsigned sdmmc1_dat0_py7_pins[] = { - TEGRA_PIN_SDMMC1_DAT0_PY7, -}; - -static const unsigned sdmmc1_clk_pz0_pins[] = { - TEGRA_PIN_SDMMC1_CLK_PZ0, -}; - -static const unsigned sdmmc1_cmd_pz1_pins[] = { - TEGRA_PIN_SDMMC1_CMD_PZ1, -}; - -static const unsigned pwr_i2c_scl_pz6_pins[] = { - TEGRA_PIN_PWR_I2C_SCL_PZ6, -}; - -static const unsigned pwr_i2c_sda_pz7_pins[] = { - TEGRA_PIN_PWR_I2C_SDA_PZ7, -}; - -static const unsigned sdmmc4_dat0_paa0_pins[] = { - TEGRA_PIN_SDMMC4_DAT0_PAA0, -}; - -static const unsigned sdmmc4_dat1_paa1_pins[] = { - TEGRA_PIN_SDMMC4_DAT1_PAA1, -}; - -static const unsigned sdmmc4_dat2_paa2_pins[] = { - TEGRA_PIN_SDMMC4_DAT2_PAA2, -}; - -static const unsigned sdmmc4_dat3_paa3_pins[] = { - TEGRA_PIN_SDMMC4_DAT3_PAA3, -}; - -static const unsigned sdmmc4_dat4_paa4_pins[] = { - TEGRA_PIN_SDMMC4_DAT4_PAA4, -}; - -static const unsigned sdmmc4_dat5_paa5_pins[] = { - TEGRA_PIN_SDMMC4_DAT5_PAA5, -}; - -static const unsigned sdmmc4_dat6_paa6_pins[] = { - TEGRA_PIN_SDMMC4_DAT6_PAA6, -}; - -static const unsigned sdmmc4_dat7_paa7_pins[] = { - TEGRA_PIN_SDMMC4_DAT7_PAA7, -}; - -static const unsigned pbb0_pins[] = { - TEGRA_PIN_PBB0, -}; - -static const unsigned cam_i2c_scl_pbb1_pins[] = { - TEGRA_PIN_CAM_I2C_SCL_PBB1, -}; - -static const unsigned cam_i2c_sda_pbb2_pins[] = { - TEGRA_PIN_CAM_I2C_SDA_PBB2, -}; - -static const unsigned pbb3_pins[] = { - TEGRA_PIN_PBB3, -}; - -static const unsigned pbb4_pins[] = { - TEGRA_PIN_PBB4, -}; - -static const unsigned pbb5_pins[] = { - TEGRA_PIN_PBB5, -}; - -static const unsigned pbb6_pins[] = { - TEGRA_PIN_PBB6, -}; - -static const unsigned pbb7_pins[] = { - TEGRA_PIN_PBB7, -}; - -static const unsigned cam_mclk_pcc0_pins[] = { - TEGRA_PIN_CAM_MCLK_PCC0, -}; - -static const unsigned pcc1_pins[] = { - TEGRA_PIN_PCC1, -}; - -static const unsigned pcc2_pins[] = { - TEGRA_PIN_PCC2, -}; - -static const unsigned sdmmc4_clk_pcc4_pins[] = { - TEGRA_PIN_SDMMC4_CLK_PCC4, -}; - -static const unsigned clk2_req_pcc5_pins[] = { - TEGRA_PIN_CLK2_REQ_PCC5, -}; - -static const unsigned pex_l0_rst_n_pdd1_pins[] = { - TEGRA_PIN_PEX_L0_RST_N_PDD1, -}; - -static const unsigned pex_l0_clkreq_n_pdd2_pins[] = { - TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, -}; - -static const unsigned pex_wake_n_pdd3_pins[] = { - TEGRA_PIN_PEX_WAKE_N_PDD3, -}; - -static const unsigned pex_l1_rst_n_pdd5_pins[] = { - TEGRA_PIN_PEX_L1_RST_N_PDD5, -}; - -static const unsigned pex_l1_clkreq_n_pdd6_pins[] = { - TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, -}; - -static const unsigned clk3_out_pee0_pins[] = { - TEGRA_PIN_CLK3_OUT_PEE0, -}; - -static const unsigned clk3_req_pee1_pins[] = { - TEGRA_PIN_CLK3_REQ_PEE1, -}; - -static const unsigned dap_mclk1_req_pee2_pins[] = { - TEGRA_PIN_DAP_MCLK1_REQ_PEE2, -}; - -static const unsigned hdmi_cec_pee3_pins[] = { - TEGRA_PIN_HDMI_CEC_PEE3, -}; - -static const unsigned sdmmc3_clk_lb_out_pee4_pins[] = { - TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, -}; - -static const unsigned sdmmc3_clk_lb_in_pee5_pins[] = { - TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, -}; - -static const unsigned dp_hpd_pff0_pins[] = { - TEGRA_PIN_DP_HPD_PFF0, -}; - -static const unsigned usb_vbus_en2_pff1_pins[] = { - TEGRA_PIN_USB_VBUS_EN2_PFF1, -}; - -static const unsigned pff2_pins[] = { - TEGRA_PIN_PFF2, -}; - -static const unsigned core_pwr_req_pins[] = { - TEGRA_PIN_CORE_PWR_REQ, -}; - -static const unsigned cpu_pwr_req_pins[] = { - TEGRA_PIN_CPU_PWR_REQ, -}; - -static const unsigned pwr_int_n_pins[] = { - TEGRA_PIN_PWR_INT_N, -}; - -static const unsigned gmi_clk_lb_pins[] = { - TEGRA_PIN_GMI_CLK_LB, -}; - -static const unsigned reset_out_n_pins[] = { - TEGRA_PIN_RESET_OUT_N, -}; - -static const unsigned owr_pins[] = { - TEGRA_PIN_OWR, -}; - -static const unsigned clk_32k_in_pins[] = { - TEGRA_PIN_CLK_32K_IN, -}; - -static const unsigned jtag_rtck_pins[] = { - TEGRA_PIN_JTAG_RTCK, -}; - -static const unsigned drive_ao1_pins[] = { - TEGRA_PIN_KB_ROW0_PR0, - TEGRA_PIN_KB_ROW1_PR1, - TEGRA_PIN_KB_ROW2_PR2, - TEGRA_PIN_KB_ROW3_PR3, - TEGRA_PIN_KB_ROW4_PR4, - TEGRA_PIN_KB_ROW5_PR5, - TEGRA_PIN_KB_ROW6_PR6, - TEGRA_PIN_KB_ROW7_PR7, - TEGRA_PIN_PWR_I2C_SCL_PZ6, - TEGRA_PIN_PWR_I2C_SDA_PZ7, -}; - -static const unsigned drive_ao2_pins[] = { - TEGRA_PIN_CLK_32K_OUT_PA0, - TEGRA_PIN_CLK_32K_IN, - TEGRA_PIN_KB_COL0_PQ0, - TEGRA_PIN_KB_COL1_PQ1, - TEGRA_PIN_KB_COL2_PQ2, - TEGRA_PIN_KB_COL3_PQ3, - TEGRA_PIN_KB_COL4_PQ4, - TEGRA_PIN_KB_COL5_PQ5, - TEGRA_PIN_KB_COL6_PQ6, - TEGRA_PIN_KB_COL7_PQ7, - TEGRA_PIN_KB_ROW8_PS0, - TEGRA_PIN_KB_ROW9_PS1, - TEGRA_PIN_KB_ROW10_PS2, - TEGRA_PIN_KB_ROW11_PS3, - TEGRA_PIN_KB_ROW12_PS4, - TEGRA_PIN_KB_ROW13_PS5, - TEGRA_PIN_KB_ROW14_PS6, - TEGRA_PIN_KB_ROW15_PS7, - TEGRA_PIN_KB_ROW16_PT0, - TEGRA_PIN_KB_ROW17_PT1, - TEGRA_PIN_SDMMC3_CD_N_PV2, - TEGRA_PIN_CORE_PWR_REQ, - TEGRA_PIN_CPU_PWR_REQ, - TEGRA_PIN_PWR_INT_N, -}; - -static const unsigned drive_at1_pins[] = { - TEGRA_PIN_PH0, - TEGRA_PIN_PH1, - TEGRA_PIN_PH2, - TEGRA_PIN_PH3, -}; - -static const unsigned drive_at2_pins[] = { - TEGRA_PIN_PG0, - TEGRA_PIN_PG1, - TEGRA_PIN_PG2, - TEGRA_PIN_PG3, - TEGRA_PIN_PG4, - TEGRA_PIN_PG5, - TEGRA_PIN_PG6, - TEGRA_PIN_PG7, - TEGRA_PIN_PI0, - TEGRA_PIN_PI1, - TEGRA_PIN_PI3, - TEGRA_PIN_PI4, - TEGRA_PIN_PI7, - TEGRA_PIN_PK0, - TEGRA_PIN_PK2, -}; - -static const unsigned drive_at3_pins[] = { - TEGRA_PIN_PC7, - TEGRA_PIN_PJ0, -}; - -static const unsigned drive_at4_pins[] = { - TEGRA_PIN_PB0, - TEGRA_PIN_PB1, - TEGRA_PIN_PJ0, - TEGRA_PIN_PJ7, - TEGRA_PIN_PK7, -}; - -static const unsigned drive_at5_pins[] = { - TEGRA_PIN_GEN2_I2C_SCL_PT5, - TEGRA_PIN_GEN2_I2C_SDA_PT6, -}; - -static const unsigned drive_cdev1_pins[] = { - TEGRA_PIN_DAP_MCLK1_PW4, - TEGRA_PIN_DAP_MCLK1_REQ_PEE2, -}; - -static const unsigned drive_cdev2_pins[] = { - TEGRA_PIN_CLK2_OUT_PW5, - TEGRA_PIN_CLK2_REQ_PCC5, -}; - -static const unsigned drive_dap1_pins[] = { - TEGRA_PIN_DAP1_FS_PN0, - TEGRA_PIN_DAP1_DIN_PN1, - TEGRA_PIN_DAP1_DOUT_PN2, - TEGRA_PIN_DAP1_SCLK_PN3, -}; - -static const unsigned drive_dap2_pins[] = { - TEGRA_PIN_DAP2_FS_PA2, - TEGRA_PIN_DAP2_SCLK_PA3, - TEGRA_PIN_DAP2_DIN_PA4, - TEGRA_PIN_DAP2_DOUT_PA5, -}; - -static const unsigned drive_dap3_pins[] = { - TEGRA_PIN_DAP3_FS_PP0, - TEGRA_PIN_DAP3_DIN_PP1, - TEGRA_PIN_DAP3_DOUT_PP2, - TEGRA_PIN_DAP3_SCLK_PP3, -}; - -static const unsigned drive_dap4_pins[] = { - TEGRA_PIN_DAP4_FS_PP4, - TEGRA_PIN_DAP4_DIN_PP5, - TEGRA_PIN_DAP4_DOUT_PP6, - TEGRA_PIN_DAP4_SCLK_PP7, -}; - -static const unsigned drive_dbg_pins[] = { - TEGRA_PIN_GEN1_I2C_SCL_PC4, - TEGRA_PIN_GEN1_I2C_SDA_PC5, - TEGRA_PIN_PU0, - TEGRA_PIN_PU1, - TEGRA_PIN_PU2, - TEGRA_PIN_PU3, - TEGRA_PIN_PU4, - TEGRA_PIN_PU5, - TEGRA_PIN_PU6, -}; - -static const unsigned drive_sdio3_pins[] = { - TEGRA_PIN_SDMMC3_CLK_PA6, - TEGRA_PIN_SDMMC3_CMD_PA7, - TEGRA_PIN_SDMMC3_DAT3_PB4, - TEGRA_PIN_SDMMC3_DAT2_PB5, - TEGRA_PIN_SDMMC3_DAT1_PB6, - TEGRA_PIN_SDMMC3_DAT0_PB7, - TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, - TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, -}; - -static const unsigned drive_spi_pins[] = { - TEGRA_PIN_DVFS_PWM_PX0, - TEGRA_PIN_GPIO_X1_AUD_PX1, - TEGRA_PIN_DVFS_CLK_PX2, - TEGRA_PIN_GPIO_X3_AUD_PX3, - TEGRA_PIN_GPIO_X4_AUD_PX4, - TEGRA_PIN_GPIO_X5_AUD_PX5, - TEGRA_PIN_GPIO_X6_AUD_PX6, - TEGRA_PIN_GPIO_X7_AUD_PX7, - TEGRA_PIN_GPIO_W2_AUD_PW2, - TEGRA_PIN_GPIO_W3_AUD_PW3, -}; - -static const unsigned drive_uaa_pins[] = { - TEGRA_PIN_ULPI_DATA0_PO1, - TEGRA_PIN_ULPI_DATA1_PO2, - TEGRA_PIN_ULPI_DATA2_PO3, - TEGRA_PIN_ULPI_DATA3_PO4, -}; - -static const unsigned drive_uab_pins[] = { - TEGRA_PIN_ULPI_DATA7_PO0, - TEGRA_PIN_ULPI_DATA4_PO5, - TEGRA_PIN_ULPI_DATA5_PO6, - TEGRA_PIN_ULPI_DATA6_PO7, - TEGRA_PIN_PV0, - TEGRA_PIN_PV1, -}; - -static const unsigned drive_uart2_pins[] = { - TEGRA_PIN_UART2_TXD_PC2, - TEGRA_PIN_UART2_RXD_PC3, - TEGRA_PIN_UART2_CTS_N_PJ5, - TEGRA_PIN_UART2_RTS_N_PJ6, -}; - -static const unsigned drive_uart3_pins[] = { - TEGRA_PIN_UART3_CTS_N_PA1, - TEGRA_PIN_UART3_RTS_N_PC0, - TEGRA_PIN_UART3_TXD_PW6, - TEGRA_PIN_UART3_RXD_PW7, -}; - -static const unsigned drive_sdio1_pins[] = { - TEGRA_PIN_SDMMC1_DAT3_PY4, - TEGRA_PIN_SDMMC1_DAT2_PY5, - TEGRA_PIN_SDMMC1_DAT1_PY6, - TEGRA_PIN_SDMMC1_DAT0_PY7, - TEGRA_PIN_SDMMC1_CLK_PZ0, - TEGRA_PIN_SDMMC1_CMD_PZ1, -}; - -static const unsigned drive_ddc_pins[] = { - TEGRA_PIN_DDC_SCL_PV4, - TEGRA_PIN_DDC_SDA_PV5, -}; - -static const unsigned drive_gma_pins[] = { - TEGRA_PIN_SDMMC4_CLK_PCC4, - TEGRA_PIN_SDMMC4_CMD_PT7, - TEGRA_PIN_SDMMC4_DAT0_PAA0, - TEGRA_PIN_SDMMC4_DAT1_PAA1, - TEGRA_PIN_SDMMC4_DAT2_PAA2, - TEGRA_PIN_SDMMC4_DAT3_PAA3, - TEGRA_PIN_SDMMC4_DAT4_PAA4, - TEGRA_PIN_SDMMC4_DAT5_PAA5, - TEGRA_PIN_SDMMC4_DAT6_PAA6, - TEGRA_PIN_SDMMC4_DAT7_PAA7, -}; - -static const unsigned drive_gme_pins[] = { - TEGRA_PIN_PBB0, - TEGRA_PIN_CAM_I2C_SCL_PBB1, - TEGRA_PIN_CAM_I2C_SDA_PBB2, - TEGRA_PIN_PBB3, - TEGRA_PIN_PCC2, -}; - -static const unsigned drive_gmf_pins[] = { - TEGRA_PIN_PBB4, - TEGRA_PIN_PBB5, - TEGRA_PIN_PBB6, - TEGRA_PIN_PBB7, -}; - -static const unsigned drive_gmg_pins[] = { - TEGRA_PIN_CAM_MCLK_PCC0, -}; - -static const unsigned drive_gmh_pins[] = { - TEGRA_PIN_PCC1, -}; - -static const unsigned drive_owr_pins[] = { - TEGRA_PIN_SDMMC3_CD_N_PV2, - TEGRA_PIN_OWR, -}; - -static const unsigned drive_uda_pins[] = { - TEGRA_PIN_ULPI_CLK_PY0, - TEGRA_PIN_ULPI_DIR_PY1, - TEGRA_PIN_ULPI_NXT_PY2, - TEGRA_PIN_ULPI_STP_PY3, -}; - -static const unsigned drive_gpv_pins[] = { - TEGRA_PIN_PEX_L0_RST_N_PDD1, - TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, - TEGRA_PIN_PEX_WAKE_N_PDD3, - TEGRA_PIN_PEX_L1_RST_N_PDD5, - TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, - TEGRA_PIN_USB_VBUS_EN2_PFF1, - TEGRA_PIN_PFF2, -}; - -static const unsigned drive_dev3_pins[] = { - TEGRA_PIN_CLK3_OUT_PEE0, - TEGRA_PIN_CLK3_REQ_PEE1, -}; - -static const unsigned drive_cec_pins[] = { - TEGRA_PIN_HDMI_CEC_PEE3, -}; - -static const unsigned drive_at6_pins[] = { - TEGRA_PIN_PK1, - TEGRA_PIN_PK3, - TEGRA_PIN_PK4, - TEGRA_PIN_PI2, - TEGRA_PIN_PI5, - TEGRA_PIN_PI6, - TEGRA_PIN_PH4, - TEGRA_PIN_PH5, - TEGRA_PIN_PH6, - TEGRA_PIN_PH7, -}; - -static const unsigned drive_dap5_pins[] = { - TEGRA_PIN_SPDIF_IN_PK6, - TEGRA_PIN_SPDIF_OUT_PK5, - TEGRA_PIN_DP_HPD_PFF0, -}; - -static const unsigned drive_usb_vbus_en_pins[] = { - TEGRA_PIN_USB_VBUS_EN0_PN4, - TEGRA_PIN_USB_VBUS_EN1_PN5, -}; - -static const unsigned drive_ao3_pins[] = { - TEGRA_PIN_RESET_OUT_N, -}; - -static const unsigned drive_ao0_pins[] = { - TEGRA_PIN_JTAG_RTCK, -}; - -static const unsigned drive_hv0_pins[] = { - TEGRA_PIN_HDMI_INT_PN7, -}; - -static const unsigned drive_sdio4_pins[] = { - TEGRA_PIN_SDMMC1_WP_N_PV3, -}; - -static const unsigned drive_ao4_pins[] = { - TEGRA_PIN_JTAG_RTCK, -}; - -static const unsigned mipi_pad_ctrl_dsi_b_pins[] = { - TEGRA_PIN_DSI_B_CLK_P, - TEGRA_PIN_DSI_B_CLK_N, - TEGRA_PIN_DSI_B_D0_P, - TEGRA_PIN_DSI_B_D0_N, - TEGRA_PIN_DSI_B_D1_P, - TEGRA_PIN_DSI_B_D1_N, - TEGRA_PIN_DSI_B_D2_P, - TEGRA_PIN_DSI_B_D2_N, - TEGRA_PIN_DSI_B_D3_P, - TEGRA_PIN_DSI_B_D3_N, -}; - -enum tegra_mux { - TEGRA_MUX_BLINK, - TEGRA_MUX_CCLA, - TEGRA_MUX_CEC, - TEGRA_MUX_CLDVFS, - TEGRA_MUX_CLK, - TEGRA_MUX_CLK12, - TEGRA_MUX_CPU, - TEGRA_MUX_CSI, - TEGRA_MUX_DAP, - TEGRA_MUX_DAP1, - TEGRA_MUX_DAP2, - TEGRA_MUX_DEV3, - TEGRA_MUX_DISPLAYA, - TEGRA_MUX_DISPLAYA_ALT, - TEGRA_MUX_DISPLAYB, - TEGRA_MUX_DP, - TEGRA_MUX_DSI_B, - TEGRA_MUX_DTV, - TEGRA_MUX_EXTPERIPH1, - TEGRA_MUX_EXTPERIPH2, - TEGRA_MUX_EXTPERIPH3, - TEGRA_MUX_GMI, - TEGRA_MUX_GMI_ALT, - TEGRA_MUX_HDA, - TEGRA_MUX_HSI, - TEGRA_MUX_I2C1, - TEGRA_MUX_I2C2, - TEGRA_MUX_I2C3, - TEGRA_MUX_I2C4, - TEGRA_MUX_I2CPWR, - TEGRA_MUX_I2S0, - TEGRA_MUX_I2S1, - TEGRA_MUX_I2S2, - TEGRA_MUX_I2S3, - TEGRA_MUX_I2S4, - TEGRA_MUX_IRDA, - TEGRA_MUX_KBC, - TEGRA_MUX_OWR, - TEGRA_MUX_PE, - TEGRA_MUX_PE0, - TEGRA_MUX_PE1, - TEGRA_MUX_PMI, - TEGRA_MUX_PWM0, - TEGRA_MUX_PWM1, - TEGRA_MUX_PWM2, - TEGRA_MUX_PWM3, - TEGRA_MUX_PWRON, - TEGRA_MUX_RESET_OUT_N, - TEGRA_MUX_RSVD1, - TEGRA_MUX_RSVD2, - TEGRA_MUX_RSVD3, - TEGRA_MUX_RSVD4, - TEGRA_MUX_RTCK, - TEGRA_MUX_SATA, - TEGRA_MUX_SDMMC1, - TEGRA_MUX_SDMMC2, - TEGRA_MUX_SDMMC3, - TEGRA_MUX_SDMMC4, - TEGRA_MUX_SOC, - TEGRA_MUX_SPDIF, - TEGRA_MUX_SPI1, - TEGRA_MUX_SPI2, - TEGRA_MUX_SPI3, - TEGRA_MUX_SPI4, - TEGRA_MUX_SPI5, - TEGRA_MUX_SPI6, - TEGRA_MUX_SYS, - TEGRA_MUX_TMDS, - TEGRA_MUX_TRACE, - TEGRA_MUX_UARTA, - TEGRA_MUX_UARTB, - TEGRA_MUX_UARTC, - TEGRA_MUX_UARTD, - TEGRA_MUX_ULPI, - TEGRA_MUX_USB, - TEGRA_MUX_VGP1, - TEGRA_MUX_VGP2, - TEGRA_MUX_VGP3, - TEGRA_MUX_VGP4, - TEGRA_MUX_VGP5, - TEGRA_MUX_VGP6, - TEGRA_MUX_VI, - TEGRA_MUX_VI_ALT1, - TEGRA_MUX_VI_ALT3, - TEGRA_MUX_VIMCLK2, - TEGRA_MUX_VIMCLK2_ALT, -}; - -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } - -static struct tegra_function tegra124_functions[] = { - FUNCTION(blink), - FUNCTION(ccla), - FUNCTION(cec), - FUNCTION(cldvfs), - FUNCTION(clk), - FUNCTION(clk12), - FUNCTION(cpu), - FUNCTION(csi), - FUNCTION(dap), - FUNCTION(dap1), - FUNCTION(dap2), - FUNCTION(dev3), - FUNCTION(displaya), - FUNCTION(displaya_alt), - FUNCTION(displayb), - FUNCTION(dp), - FUNCTION(dsi_b), - FUNCTION(dtv), - FUNCTION(extperiph1), - FUNCTION(extperiph2), - FUNCTION(extperiph3), - FUNCTION(gmi), - FUNCTION(gmi_alt), - FUNCTION(hda), - FUNCTION(hsi), - FUNCTION(i2c1), - FUNCTION(i2c2), - FUNCTION(i2c3), - FUNCTION(i2c4), - FUNCTION(i2cpwr), - FUNCTION(i2s0), - FUNCTION(i2s1), - FUNCTION(i2s2), - FUNCTION(i2s3), - FUNCTION(i2s4), - FUNCTION(irda), - FUNCTION(kbc), - FUNCTION(owr), - FUNCTION(pe), - FUNCTION(pe0), - FUNCTION(pe1), - FUNCTION(pmi), - FUNCTION(pwm0), - FUNCTION(pwm1), - FUNCTION(pwm2), - FUNCTION(pwm3), - FUNCTION(pwron), - FUNCTION(reset_out_n), - FUNCTION(rsvd1), - FUNCTION(rsvd2), - FUNCTION(rsvd3), - FUNCTION(rsvd4), - FUNCTION(rtck), - FUNCTION(sata), - FUNCTION(sdmmc1), - FUNCTION(sdmmc2), - FUNCTION(sdmmc3), - FUNCTION(sdmmc4), - FUNCTION(soc), - FUNCTION(spdif), - FUNCTION(spi1), - FUNCTION(spi2), - FUNCTION(spi3), - FUNCTION(spi4), - FUNCTION(spi5), - FUNCTION(spi6), - FUNCTION(sys), - FUNCTION(tmds), - FUNCTION(trace), - FUNCTION(uarta), - FUNCTION(uartb), - FUNCTION(uartc), - FUNCTION(uartd), - FUNCTION(ulpi), - FUNCTION(usb), - FUNCTION(vgp1), - FUNCTION(vgp2), - FUNCTION(vgp3), - FUNCTION(vgp4), - FUNCTION(vgp5), - FUNCTION(vgp6), - FUNCTION(vi), - FUNCTION(vi_alt1), - FUNCTION(vi_alt3), - FUNCTION(vimclk2), - FUNCTION(vimclk2_alt), -}; - -#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ -#define PINGROUP_REG_A 0x3000 /* bank 1 */ -#define MIPI_PAD_CTRL_PINGROUP_REG_A 0x820 /* bank 2 */ - -#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A) -#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) -#define MIPI_PAD_CTRL_PINGROUP_REG_Y(r) ((r) - MIPI_PAD_CTRL_PINGROUP_REG_A) - -#define PINGROUP_BIT_Y(b) (b) -#define PINGROUP_BIT_N(b) (-1) - -#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel) \ - { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ - .funcs = { \ - TEGRA_MUX_##f0, \ - TEGRA_MUX_##f1, \ - TEGRA_MUX_##f2, \ - TEGRA_MUX_##f3, \ - }, \ - .mux_reg = PINGROUP_REG(r), \ - .mux_bank = 1, \ - .mux_bit = 0, \ - .pupd_reg = PINGROUP_REG(r), \ - .pupd_bank = 1, \ - .pupd_bit = 2, \ - .tri_reg = PINGROUP_REG(r), \ - .tri_bank = 1, \ - .tri_bit = 4, \ - .einput_bit = 5, \ - .odrain_bit = PINGROUP_BIT_##od(6), \ - .lock_bit = 7, \ - .ioreset_bit = PINGROUP_BIT_##ior(8), \ - .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9), \ - .drv_reg = -1, \ - } - -#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, \ - drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, \ - slwf_b, slwf_w, drvtype) \ - { \ - .name = "drive_" #pg_name, \ - .pins = drive_##pg_name##_pins, \ - .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ - .mux_reg = -1, \ - .pupd_reg = -1, \ - .tri_reg = -1, \ - .einput_bit = -1, \ - .odrain_bit = -1, \ - .lock_bit = -1, \ - .ioreset_bit = -1, \ - .rcv_sel_bit = -1, \ - .drv_reg = DRV_PINGROUP_REG(r), \ - .drv_bank = 0, \ - .hsm_bit = hsm_b, \ - .schmitt_bit = schmitt_b, \ - .lpmd_bit = lpmd_b, \ - .drvdn_bit = drvdn_b, \ - .drvdn_width = drvdn_w, \ - .drvup_bit = drvup_b, \ - .drvup_width = drvup_w, \ - .slwr_bit = slwr_b, \ - .slwr_width = slwr_w, \ - .slwf_bit = slwf_b, \ - .slwf_width = slwf_w, \ - .drvtype_bit = PINGROUP_BIT_##drvtype(6), \ - } - -#define MIPI_PAD_CTRL_PINGROUP(pg_name, r, b, f0, f1) \ - { \ - .name = "mipi_pad_ctrl_" #pg_name, \ - .pins = mipi_pad_ctrl_##pg_name##_pins, \ - .npins = ARRAY_SIZE(mipi_pad_ctrl_##pg_name##_pins), \ - .funcs = { \ - TEGRA_MUX_ ## f0, \ - TEGRA_MUX_ ## f1, \ - TEGRA_MUX_RSVD3, \ - TEGRA_MUX_RSVD4, \ - }, \ - .mux_reg = MIPI_PAD_CTRL_PINGROUP_REG_Y(r), \ - .mux_bank = 2, \ - .mux_bit = b, \ - .pupd_reg = -1, \ - .tri_reg = -1, \ - .einput_bit = -1, \ - .odrain_bit = -1, \ - .lock_bit = -1, \ - .ioreset_bit = -1, \ - .rcv_sel_bit = -1, \ - .drv_reg = -1, \ - } - -static const struct tegra_pingroup tegra124_groups[] = { - /* pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel */ - PINGROUP(ulpi_data0_po1, SPI3, HSI, UARTA, ULPI, 0x3000, N, N, N), - PINGROUP(ulpi_data1_po2, SPI3, HSI, UARTA, ULPI, 0x3004, N, N, N), - PINGROUP(ulpi_data2_po3, SPI3, HSI, UARTA, ULPI, 0x3008, N, N, N), - PINGROUP(ulpi_data3_po4, SPI3, HSI, UARTA, ULPI, 0x300c, N, N, N), - PINGROUP(ulpi_data4_po5, SPI2, HSI, UARTA, ULPI, 0x3010, N, N, N), - PINGROUP(ulpi_data5_po6, SPI2, HSI, UARTA, ULPI, 0x3014, N, N, N), - PINGROUP(ulpi_data6_po7, SPI2, HSI, UARTA, ULPI, 0x3018, N, N, N), - PINGROUP(ulpi_data7_po0, SPI2, HSI, UARTA, ULPI, 0x301c, N, N, N), - PINGROUP(ulpi_clk_py0, SPI1, SPI5, UARTD, ULPI, 0x3020, N, N, N), - PINGROUP(ulpi_dir_py1, SPI1, SPI5, UARTD, ULPI, 0x3024, N, N, N), - PINGROUP(ulpi_nxt_py2, SPI1, SPI5, UARTD, ULPI, 0x3028, N, N, N), - PINGROUP(ulpi_stp_py3, SPI1, SPI5, UARTD, ULPI, 0x302c, N, N, N), - PINGROUP(dap3_fs_pp0, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3030, N, N, N), - PINGROUP(dap3_din_pp1, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3034, N, N, N), - PINGROUP(dap3_dout_pp2, I2S2, SPI5, DISPLAYA, RSVD4, 0x3038, N, N, N), - PINGROUP(dap3_sclk_pp3, I2S2, SPI5, RSVD3, DISPLAYB, 0x303c, N, N, N), - PINGROUP(pv0, RSVD1, RSVD2, RSVD3, RSVD4, 0x3040, N, N, N), - PINGROUP(pv1, RSVD1, RSVD2, RSVD3, RSVD4, 0x3044, N, N, N), - PINGROUP(sdmmc1_clk_pz0, SDMMC1, CLK12, RSVD3, RSVD4, 0x3048, N, N, N), - PINGROUP(sdmmc1_cmd_pz1, SDMMC1, SPDIF, SPI4, UARTA, 0x304c, N, N, N), - PINGROUP(sdmmc1_dat3_py4, SDMMC1, SPDIF, SPI4, UARTA, 0x3050, N, N, N), - PINGROUP(sdmmc1_dat2_py5, SDMMC1, PWM0, SPI4, UARTA, 0x3054, N, N, N), - PINGROUP(sdmmc1_dat1_py6, SDMMC1, PWM1, SPI4, UARTA, 0x3058, N, N, N), - PINGROUP(sdmmc1_dat0_py7, SDMMC1, RSVD2, SPI4, UARTA, 0x305c, N, N, N), - PINGROUP(clk2_out_pw5, EXTPERIPH2, RSVD2, RSVD3, RSVD4, 0x3068, N, N, N), - PINGROUP(clk2_req_pcc5, DAP, RSVD2, RSVD3, RSVD4, 0x306c, N, N, N), - PINGROUP(hdmi_int_pn7, RSVD1, RSVD2, RSVD3, RSVD4, 0x3110, N, N, Y), - PINGROUP(ddc_scl_pv4, I2C4, RSVD2, RSVD3, RSVD4, 0x3114, N, N, Y), - PINGROUP(ddc_sda_pv5, I2C4, RSVD2, RSVD3, RSVD4, 0x3118, N, N, Y), - PINGROUP(uart2_rxd_pc3, IRDA, SPDIF, UARTA, SPI4, 0x3164, N, N, N), - PINGROUP(uart2_txd_pc2, IRDA, SPDIF, UARTA, SPI4, 0x3168, N, N, N), - PINGROUP(uart2_rts_n_pj6, UARTA, UARTB, GMI, SPI4, 0x316c, N, N, N), - PINGROUP(uart2_cts_n_pj5, UARTA, UARTB, GMI, SPI4, 0x3170, N, N, N), - PINGROUP(uart3_txd_pw6, UARTC, RSVD2, GMI, SPI4, 0x3174, N, N, N), - PINGROUP(uart3_rxd_pw7, UARTC, RSVD2, GMI, SPI4, 0x3178, N, N, N), - PINGROUP(uart3_cts_n_pa1, UARTC, SDMMC1, DTV, GMI, 0x317c, N, N, N), - PINGROUP(uart3_rts_n_pc0, UARTC, PWM0, DTV, GMI, 0x3180, N, N, N), - PINGROUP(pu0, OWR, UARTA, GMI, RSVD4, 0x3184, N, N, N), - PINGROUP(pu1, RSVD1, UARTA, GMI, RSVD4, 0x3188, N, N, N), - PINGROUP(pu2, RSVD1, UARTA, GMI, RSVD4, 0x318c, N, N, N), - PINGROUP(pu3, PWM0, UARTA, GMI, DISPLAYB, 0x3190, N, N, N), - PINGROUP(pu4, PWM1, UARTA, GMI, DISPLAYB, 0x3194, N, N, N), - PINGROUP(pu5, PWM2, UARTA, GMI, DISPLAYB, 0x3198, N, N, N), - PINGROUP(pu6, PWM3, UARTA, RSVD3, GMI, 0x319c, N, N, N), - PINGROUP(gen1_i2c_sda_pc5, I2C1, RSVD2, RSVD3, RSVD4, 0x31a0, Y, N, N), - PINGROUP(gen1_i2c_scl_pc4, I2C1, RSVD2, RSVD3, RSVD4, 0x31a4, Y, N, N), - PINGROUP(dap4_fs_pp4, I2S3, GMI, DTV, RSVD4, 0x31a8, N, N, N), - PINGROUP(dap4_din_pp5, I2S3, GMI, RSVD3, RSVD4, 0x31ac, N, N, N), - PINGROUP(dap4_dout_pp6, I2S3, GMI, DTV, RSVD4, 0x31b0, N, N, N), - PINGROUP(dap4_sclk_pp7, I2S3, GMI, RSVD3, RSVD4, 0x31b4, N, N, N), - PINGROUP(clk3_out_pee0, EXTPERIPH3, RSVD2, RSVD3, RSVD4, 0x31b8, N, N, N), - PINGROUP(clk3_req_pee1, DEV3, RSVD2, RSVD3, RSVD4, 0x31bc, N, N, N), - PINGROUP(pc7, RSVD1, RSVD2, GMI, GMI_ALT, 0x31c0, N, N, N), - PINGROUP(pi5, SDMMC2, RSVD2, GMI, RSVD4, 0x31c4, N, N, N), - PINGROUP(pi7, RSVD1, TRACE, GMI, DTV, 0x31c8, N, N, N), - PINGROUP(pk0, RSVD1, SDMMC3, GMI, SOC, 0x31cc, N, N, N), - PINGROUP(pk1, SDMMC2, TRACE, GMI, RSVD4, 0x31d0, N, N, N), - PINGROUP(pj0, RSVD1, RSVD2, GMI, USB, 0x31d4, N, N, N), - PINGROUP(pj2, RSVD1, RSVD2, GMI, SOC, 0x31d8, N, N, N), - PINGROUP(pk3, SDMMC2, TRACE, GMI, CCLA, 0x31dc, N, N, N), - PINGROUP(pk4, SDMMC2, RSVD2, GMI, GMI_ALT, 0x31e0, N, N, N), - PINGROUP(pk2, RSVD1, RSVD2, GMI, RSVD4, 0x31e4, N, N, N), - PINGROUP(pi3, RSVD1, RSVD2, GMI, SPI4, 0x31e8, N, N, N), - PINGROUP(pi6, RSVD1, RSVD2, GMI, SDMMC2, 0x31ec, N, N, N), - PINGROUP(pg0, RSVD1, RSVD2, GMI, RSVD4, 0x31f0, N, N, N), - PINGROUP(pg1, RSVD1, RSVD2, GMI, RSVD4, 0x31f4, N, N, N), - PINGROUP(pg2, RSVD1, TRACE, GMI, RSVD4, 0x31f8, N, N, N), - PINGROUP(pg3, RSVD1, TRACE, GMI, RSVD4, 0x31fc, N, N, N), - PINGROUP(pg4, RSVD1, TMDS, GMI, SPI4, 0x3200, N, N, N), - PINGROUP(pg5, RSVD1, RSVD2, GMI, SPI4, 0x3204, N, N, N), - PINGROUP(pg6, RSVD1, RSVD2, GMI, SPI4, 0x3208, N, N, N), - PINGROUP(pg7, RSVD1, RSVD2, GMI, SPI4, 0x320c, N, N, N), - PINGROUP(ph0, PWM0, TRACE, GMI, DTV, 0x3210, N, N, N), - PINGROUP(ph1, PWM1, TMDS, GMI, DISPLAYA, 0x3214, N, N, N), - PINGROUP(ph2, PWM2, TMDS, GMI, CLDVFS, 0x3218, N, N, N), - PINGROUP(ph3, PWM3, SPI4, GMI, CLDVFS, 0x321c, N, N, N), - PINGROUP(ph4, SDMMC2, RSVD2, GMI, RSVD4, 0x3220, N, N, N), - PINGROUP(ph5, SDMMC2, RSVD2, GMI, RSVD4, 0x3224, N, N, N), - PINGROUP(ph6, SDMMC2, TRACE, GMI, DTV, 0x3228, N, N, N), - PINGROUP(ph7, SDMMC2, TRACE, GMI, DTV, 0x322c, N, N, N), - PINGROUP(pj7, UARTD, RSVD2, GMI, GMI_ALT, 0x3230, N, N, N), - PINGROUP(pb0, UARTD, RSVD2, GMI, RSVD4, 0x3234, N, N, N), - PINGROUP(pb1, UARTD, RSVD2, GMI, RSVD4, 0x3238, N, N, N), - PINGROUP(pk7, UARTD, RSVD2, GMI, RSVD4, 0x323c, N, N, N), - PINGROUP(pi0, RSVD1, RSVD2, GMI, RSVD4, 0x3240, N, N, N), - PINGROUP(pi1, RSVD1, RSVD2, GMI, RSVD4, 0x3244, N, N, N), - PINGROUP(pi2, SDMMC2, TRACE, GMI, RSVD4, 0x3248, N, N, N), - PINGROUP(pi4, SPI4, TRACE, GMI, DISPLAYA, 0x324c, N, N, N), - PINGROUP(gen2_i2c_scl_pt5, I2C2, RSVD2, GMI, RSVD4, 0x3250, Y, N, N), - PINGROUP(gen2_i2c_sda_pt6, I2C2, RSVD2, GMI, RSVD4, 0x3254, Y, N, N), - PINGROUP(sdmmc4_clk_pcc4, SDMMC4, RSVD2, GMI, RSVD4, 0x3258, N, Y, N), - PINGROUP(sdmmc4_cmd_pt7, SDMMC4, RSVD2, GMI, RSVD4, 0x325c, N, Y, N), - PINGROUP(sdmmc4_dat0_paa0, SDMMC4, SPI3, GMI, RSVD4, 0x3260, N, Y, N), - PINGROUP(sdmmc4_dat1_paa1, SDMMC4, SPI3, GMI, RSVD4, 0x3264, N, Y, N), - PINGROUP(sdmmc4_dat2_paa2, SDMMC4, SPI3, GMI, RSVD4, 0x3268, N, Y, N), - PINGROUP(sdmmc4_dat3_paa3, SDMMC4, SPI3, GMI, RSVD4, 0x326c, N, Y, N), - PINGROUP(sdmmc4_dat4_paa4, SDMMC4, SPI3, GMI, RSVD4, 0x3270, N, Y, N), - PINGROUP(sdmmc4_dat5_paa5, SDMMC4, SPI3, RSVD3, RSVD4, 0x3274, N, Y, N), - PINGROUP(sdmmc4_dat6_paa6, SDMMC4, SPI3, GMI, RSVD4, 0x3278, N, Y, N), - PINGROUP(sdmmc4_dat7_paa7, SDMMC4, RSVD2, GMI, RSVD4, 0x327c, N, Y, N), - PINGROUP(cam_mclk_pcc0, VI, VI_ALT1, VI_ALT3, SDMMC2, 0x3284, N, N, N), - PINGROUP(pcc1, I2S4, RSVD2, RSVD3, SDMMC2, 0x3288, N, N, N), - PINGROUP(pbb0, VGP6, VIMCLK2, SDMMC2, VIMCLK2_ALT, 0x328c, N, N, N), - PINGROUP(cam_i2c_scl_pbb1, VGP1, I2C3, RSVD3, SDMMC2, 0x3290, Y, N, N), - PINGROUP(cam_i2c_sda_pbb2, VGP2, I2C3, RSVD3, SDMMC2, 0x3294, Y, N, N), - PINGROUP(pbb3, VGP3, DISPLAYA, DISPLAYB, SDMMC2, 0x3298, N, N, N), - PINGROUP(pbb4, VGP4, DISPLAYA, DISPLAYB, SDMMC2, 0x329c, N, N, N), - PINGROUP(pbb5, VGP5, DISPLAYA, RSVD3, SDMMC2, 0x32a0, N, N, N), - PINGROUP(pbb6, I2S4, RSVD2, DISPLAYB, SDMMC2, 0x32a4, N, N, N), - PINGROUP(pbb7, I2S4, RSVD2, RSVD3, SDMMC2, 0x32a8, N, N, N), - PINGROUP(pcc2, I2S4, RSVD2, SDMMC3, SDMMC2, 0x32ac, N, N, N), - PINGROUP(jtag_rtck, RTCK, RSVD2, RSVD3, RSVD4, 0x32b0, N, N, N), - PINGROUP(pwr_i2c_scl_pz6, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b4, Y, N, N), - PINGROUP(pwr_i2c_sda_pz7, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b8, Y, N, N), - PINGROUP(kb_row0_pr0, KBC, RSVD2, RSVD3, RSVD4, 0x32bc, N, N, N), - PINGROUP(kb_row1_pr1, KBC, RSVD2, RSVD3, RSVD4, 0x32c0, N, N, N), - PINGROUP(kb_row2_pr2, KBC, RSVD2, RSVD3, RSVD4, 0x32c4, N, N, N), - PINGROUP(kb_row3_pr3, KBC, DISPLAYA, SYS, DISPLAYB, 0x32c8, N, N, N), - PINGROUP(kb_row4_pr4, KBC, DISPLAYA, RSVD3, DISPLAYB, 0x32cc, N, N, N), - PINGROUP(kb_row5_pr5, KBC, DISPLAYA, RSVD3, DISPLAYB, 0x32d0, N, N, N), - PINGROUP(kb_row6_pr6, KBC, DISPLAYA, DISPLAYA_ALT, DISPLAYB, 0x32d4, N, N, N), - PINGROUP(kb_row7_pr7, KBC, RSVD2, CLDVFS, UARTA, 0x32d8, N, N, N), - PINGROUP(kb_row8_ps0, KBC, RSVD2, CLDVFS, UARTA, 0x32dc, N, N, N), - PINGROUP(kb_row9_ps1, KBC, RSVD2, RSVD3, UARTA, 0x32e0, N, N, N), - PINGROUP(kb_row10_ps2, KBC, RSVD2, RSVD3, UARTA, 0x32e4, N, N, N), - PINGROUP(kb_row11_ps3, KBC, RSVD2, RSVD3, IRDA, 0x32e8, N, N, N), - PINGROUP(kb_row12_ps4, KBC, RSVD2, RSVD3, IRDA, 0x32ec, N, N, N), - PINGROUP(kb_row13_ps5, KBC, RSVD2, SPI2, RSVD4, 0x32f0, N, N, N), - PINGROUP(kb_row14_ps6, KBC, RSVD2, SPI2, RSVD4, 0x32f4, N, N, N), - PINGROUP(kb_row15_ps7, KBC, SOC, RSVD3, RSVD4, 0x32f8, N, N, N), - PINGROUP(kb_col0_pq0, KBC, RSVD2, SPI2, RSVD4, 0x32fc, N, N, N), - PINGROUP(kb_col1_pq1, KBC, RSVD2, SPI2, RSVD4, 0x3300, N, N, N), - PINGROUP(kb_col2_pq2, KBC, RSVD2, SPI2, RSVD4, 0x3304, N, N, N), - PINGROUP(kb_col3_pq3, KBC, DISPLAYA, PWM2, UARTA, 0x3308, N, N, N), - PINGROUP(kb_col4_pq4, KBC, OWR, SDMMC3, UARTA, 0x330c, N, N, N), - PINGROUP(kb_col5_pq5, KBC, RSVD2, SDMMC3, RSVD4, 0x3310, N, N, N), - PINGROUP(kb_col6_pq6, KBC, RSVD2, SPI2, UARTD, 0x3314, N, N, N), - PINGROUP(kb_col7_pq7, KBC, RSVD2, SPI2, UARTD, 0x3318, N, N, N), - PINGROUP(clk_32k_out_pa0, BLINK, SOC, RSVD3, RSVD4, 0x331c, N, N, N), - PINGROUP(core_pwr_req, PWRON, RSVD2, RSVD3, RSVD4, 0x3324, N, N, N), - PINGROUP(cpu_pwr_req, CPU, RSVD2, RSVD3, RSVD4, 0x3328, N, N, N), - PINGROUP(pwr_int_n, PMI, RSVD2, RSVD3, RSVD4, 0x332c, N, N, N), - PINGROUP(clk_32k_in, CLK, RSVD2, RSVD3, RSVD4, 0x3330, N, N, N), - PINGROUP(owr, OWR, RSVD2, RSVD3, RSVD4, 0x3334, N, N, Y), - PINGROUP(dap1_fs_pn0, I2S0, HDA, GMI, RSVD4, 0x3338, N, N, N), - PINGROUP(dap1_din_pn1, I2S0, HDA, GMI, RSVD4, 0x333c, N, N, N), - PINGROUP(dap1_dout_pn2, I2S0, HDA, GMI, SATA, 0x3340, N, N, N), - PINGROUP(dap1_sclk_pn3, I2S0, HDA, GMI, RSVD4, 0x3344, N, N, N), - PINGROUP(dap_mclk1_req_pee2, DAP, DAP1, SATA, RSVD4, 0x3348, N, N, N), - PINGROUP(dap_mclk1_pw4, EXTPERIPH1, DAP2, RSVD3, RSVD4, 0x334c, N, N, N), - PINGROUP(spdif_in_pk6, SPDIF, RSVD2, RSVD3, I2C3, 0x3350, N, N, N), - PINGROUP(spdif_out_pk5, SPDIF, RSVD2, RSVD3, I2C3, 0x3354, N, N, N), - PINGROUP(dap2_fs_pa2, I2S1, HDA, GMI, RSVD4, 0x3358, N, N, N), - PINGROUP(dap2_din_pa4, I2S1, HDA, GMI, RSVD4, 0x335c, N, N, N), - PINGROUP(dap2_dout_pa5, I2S1, HDA, GMI, RSVD4, 0x3360, N, N, N), - PINGROUP(dap2_sclk_pa3, I2S1, HDA, GMI, RSVD4, 0x3364, N, N, N), - PINGROUP(dvfs_pwm_px0, SPI6, CLDVFS, GMI, RSVD4, 0x3368, N, N, N), - PINGROUP(gpio_x1_aud_px1, SPI6, RSVD2, GMI, RSVD4, 0x336c, N, N, N), - PINGROUP(gpio_x3_aud_px3, SPI6, SPI1, GMI, RSVD4, 0x3370, N, N, N), - PINGROUP(dvfs_clk_px2, SPI6, CLDVFS, GMI, RSVD4, 0x3374, N, N, N), - PINGROUP(gpio_x4_aud_px4, GMI, SPI1, SPI2, DAP2, 0x3378, N, N, N), - PINGROUP(gpio_x5_aud_px5, GMI, SPI1, SPI2, RSVD4, 0x337c, N, N, N), - PINGROUP(gpio_x6_aud_px6, SPI6, SPI1, SPI2, GMI, 0x3380, N, N, N), - PINGROUP(gpio_x7_aud_px7, RSVD1, SPI1, SPI2, RSVD4, 0x3384, N, N, N), - PINGROUP(sdmmc3_clk_pa6, SDMMC3, RSVD2, RSVD3, SPI3, 0x3390, N, N, N), - PINGROUP(sdmmc3_cmd_pa7, SDMMC3, PWM3, UARTA, SPI3, 0x3394, N, N, N), - PINGROUP(sdmmc3_dat0_pb7, SDMMC3, RSVD2, RSVD3, SPI3, 0x3398, N, N, N), - PINGROUP(sdmmc3_dat1_pb6, SDMMC3, PWM2, UARTA, SPI3, 0x339c, N, N, N), - PINGROUP(sdmmc3_dat2_pb5, SDMMC3, PWM1, DISPLAYA, SPI3, 0x33a0, N, N, N), - PINGROUP(sdmmc3_dat3_pb4, SDMMC3, PWM0, DISPLAYB, SPI3, 0x33a4, N, N, N), - PINGROUP(pex_l0_rst_n_pdd1, PE0, RSVD2, RSVD3, RSVD4, 0x33bc, N, N, N), - PINGROUP(pex_l0_clkreq_n_pdd2, PE0, RSVD2, RSVD3, RSVD4, 0x33c0, N, N, N), - PINGROUP(pex_wake_n_pdd3, PE, RSVD2, RSVD3, RSVD4, 0x33c4, N, N, N), - PINGROUP(pex_l1_rst_n_pdd5, PE1, RSVD2, RSVD3, RSVD4, 0x33cc, N, N, N), - PINGROUP(pex_l1_clkreq_n_pdd6, PE1, RSVD2, RSVD3, RSVD4, 0x33d0, N, N, N), - PINGROUP(hdmi_cec_pee3, CEC, RSVD2, RSVD3, RSVD4, 0x33e0, Y, N, N), - PINGROUP(sdmmc1_wp_n_pv3, SDMMC1, CLK12, SPI4, UARTA, 0x33e4, N, N, N), - PINGROUP(sdmmc3_cd_n_pv2, SDMMC3, OWR, RSVD3, RSVD4, 0x33e8, N, N, N), - PINGROUP(gpio_w2_aud_pw2, SPI6, RSVD2, SPI2, I2C1, 0x33ec, N, N, N), - PINGROUP(gpio_w3_aud_pw3, SPI6, SPI1, SPI2, I2C1, 0x33f0, N, N, N), - PINGROUP(usb_vbus_en0_pn4, USB, RSVD2, RSVD3, RSVD4, 0x33f4, Y, N, N), - PINGROUP(usb_vbus_en1_pn5, USB, RSVD2, RSVD3, RSVD4, 0x33f8, Y, N, N), - PINGROUP(sdmmc3_clk_lb_in_pee5, SDMMC3, RSVD2, RSVD3, RSVD4, 0x33fc, N, N, N), - PINGROUP(sdmmc3_clk_lb_out_pee4, SDMMC3, RSVD2, RSVD3, RSVD4, 0x3400, N, N, N), - PINGROUP(gmi_clk_lb, SDMMC2, RSVD2, GMI, RSVD4, 0x3404, N, N, N), - PINGROUP(reset_out_n, RSVD1, RSVD2, RSVD3, RESET_OUT_N, 0x3408, N, N, N), - PINGROUP(kb_row16_pt0, KBC, RSVD2, RSVD3, UARTC, 0x340c, N, N, N), - PINGROUP(kb_row17_pt1, KBC, RSVD2, RSVD3, UARTC, 0x3410, N, N, N), - PINGROUP(usb_vbus_en2_pff1, USB, RSVD2, RSVD3, RSVD4, 0x3414, Y, N, N), - PINGROUP(pff2, SATA, RSVD2, RSVD3, RSVD4, 0x3418, Y, N, N), - PINGROUP(dp_hpd_pff0, DP, RSVD2, RSVD3, RSVD4, 0x3430, N, N, N), - - /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w, drvtype */ - DRV_PINGROUP(ao1, 0x868, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(ao2, 0x86c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(at1, 0x870, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(at2, 0x874, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(at3, 0x878, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(at4, 0x87c, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(at5, 0x880, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(cdev1, 0x884, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(cdev2, 0x888, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dap1, 0x890, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dap2, 0x894, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dap3, 0x898, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dap4, 0x89c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dbg, 0x8a0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(sdio3, 0x8b0, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), - DRV_PINGROUP(spi, 0x8b4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uaa, 0x8b8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uab, 0x8bc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uart2, 0x8c0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uart3, 0x8c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(sdio1, 0x8ec, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), - DRV_PINGROUP(ddc, 0x8fc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gma, 0x900, 2, 3, 4, 14, 5, 20, 5, 28, 2, 30, 2, Y), - DRV_PINGROUP(gme, 0x910, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gmf, 0x914, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gmg, 0x918, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gmh, 0x91c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(owr, 0x920, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uda, 0x924, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gpv, 0x928, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dev3, 0x92c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(cec, 0x938, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(at6, 0x994, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(dap5, 0x998, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(usb_vbus_en, 0x99c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(ao3, 0x9a8, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), - DRV_PINGROUP(ao0, 0x9b0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(hv0, 0x9b4, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), - DRV_PINGROUP(sdio4, 0x9c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(ao4, 0x9c8, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), - - /* pg_name, r, b, f0, f1 */ - MIPI_PAD_CTRL_PINGROUP(dsi_b, 0x820, 1, CSI, DSI_B), -}; - -static const struct tegra_pinctrl_soc_data tegra124_pinctrl = { - .ngpios = NUM_GPIOS, - .pins = tegra124_pins, - .npins = ARRAY_SIZE(tegra124_pins), - .functions = tegra124_functions, - .nfunctions = ARRAY_SIZE(tegra124_functions), - .groups = tegra124_groups, - .ngroups = ARRAY_SIZE(tegra124_groups), - .hsm_in_mux = false, - .schmitt_in_mux = false, - .drvtype_in_mux = false, -}; - -static int tegra124_pinctrl_probe(struct platform_device *pdev) -{ - return tegra_pinctrl_probe(pdev, &tegra124_pinctrl); -} - -static const struct of_device_id tegra124_pinctrl_of_match[] = { - { .compatible = "nvidia,tegra124-pinmux", }, - { }, -}; -MODULE_DEVICE_TABLE(of, tegra124_pinctrl_of_match); - -static struct platform_driver tegra124_pinctrl_driver = { - .driver = { - .name = "tegra124-pinctrl", - .of_match_table = tegra124_pinctrl_of_match, - }, - .probe = tegra124_pinctrl_probe, - .remove = tegra_pinctrl_remove, -}; -module_platform_driver(tegra124_pinctrl_driver); - -MODULE_AUTHOR("Ashwini Ghuge "); -MODULE_DESCRIPTION("NVIDIA Tegra124 pinctrl driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/pinctrl-tegra20.c b/drivers/pinctrl/pinctrl-tegra20.c deleted file mode 100644 index 4833db4433d9..000000000000 --- a/drivers/pinctrl/pinctrl-tegra20.c +++ /dev/null @@ -1,2252 +0,0 @@ -/* - * Pinctrl data for the NVIDIA Tegra20 pinmux - * - * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. - * - * Derived from code: - * Copyright (C) 2010 Google, Inc. - * Copyright (C) 2010 NVIDIA 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, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - */ - -#include -#include -#include -#include -#include - -#include "pinctrl-tegra.h" - -/* - * Most pins affected by the pinmux can also be GPIOs. Define these first. - * These must match how the GPIO driver names/numbers its pins. - */ -#define _GPIO(offset) (offset) - -#define TEGRA_PIN_VI_GP6_PA0 _GPIO(0) -#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) -#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) -#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) -#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) -#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) -#define TEGRA_PIN_SDIO3_CLK_PA6 _GPIO(6) -#define TEGRA_PIN_SDIO3_CMD_PA7 _GPIO(7) -#define TEGRA_PIN_GMI_AD17_PB0 _GPIO(8) -#define TEGRA_PIN_GMI_AD18_PB1 _GPIO(9) -#define TEGRA_PIN_LCD_PWR0_PB2 _GPIO(10) -#define TEGRA_PIN_LCD_PCLK_PB3 _GPIO(11) -#define TEGRA_PIN_SDIO3_DAT3_PB4 _GPIO(12) -#define TEGRA_PIN_SDIO3_DAT2_PB5 _GPIO(13) -#define TEGRA_PIN_SDIO3_DAT1_PB6 _GPIO(14) -#define TEGRA_PIN_SDIO3_DAT0_PB7 _GPIO(15) -#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) -#define TEGRA_PIN_LCD_PWR1_PC1 _GPIO(17) -#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) -#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) -#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) -#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) -#define TEGRA_PIN_LCD_PWR2_PC6 _GPIO(22) -#define TEGRA_PIN_GMI_WP_N_PC7 _GPIO(23) -#define TEGRA_PIN_SDIO3_DAT5_PD0 _GPIO(24) -#define TEGRA_PIN_SDIO3_DAT4_PD1 _GPIO(25) -#define TEGRA_PIN_VI_GP5_PD2 _GPIO(26) -#define TEGRA_PIN_SDIO3_DAT6_PD3 _GPIO(27) -#define TEGRA_PIN_SDIO3_DAT7_PD4 _GPIO(28) -#define TEGRA_PIN_VI_D1_PD5 _GPIO(29) -#define TEGRA_PIN_VI_VSYNC_PD6 _GPIO(30) -#define TEGRA_PIN_VI_HSYNC_PD7 _GPIO(31) -#define TEGRA_PIN_LCD_D0_PE0 _GPIO(32) -#define TEGRA_PIN_LCD_D1_PE1 _GPIO(33) -#define TEGRA_PIN_LCD_D2_PE2 _GPIO(34) -#define TEGRA_PIN_LCD_D3_PE3 _GPIO(35) -#define TEGRA_PIN_LCD_D4_PE4 _GPIO(36) -#define TEGRA_PIN_LCD_D5_PE5 _GPIO(37) -#define TEGRA_PIN_LCD_D6_PE6 _GPIO(38) -#define TEGRA_PIN_LCD_D7_PE7 _GPIO(39) -#define TEGRA_PIN_LCD_D8_PF0 _GPIO(40) -#define TEGRA_PIN_LCD_D9_PF1 _GPIO(41) -#define TEGRA_PIN_LCD_D10_PF2 _GPIO(42) -#define TEGRA_PIN_LCD_D11_PF3 _GPIO(43) -#define TEGRA_PIN_LCD_D12_PF4 _GPIO(44) -#define TEGRA_PIN_LCD_D13_PF5 _GPIO(45) -#define TEGRA_PIN_LCD_D14_PF6 _GPIO(46) -#define TEGRA_PIN_LCD_D15_PF7 _GPIO(47) -#define TEGRA_PIN_GMI_AD0_PG0 _GPIO(48) -#define TEGRA_PIN_GMI_AD1_PG1 _GPIO(49) -#define TEGRA_PIN_GMI_AD2_PG2 _GPIO(50) -#define TEGRA_PIN_GMI_AD3_PG3 _GPIO(51) -#define TEGRA_PIN_GMI_AD4_PG4 _GPIO(52) -#define TEGRA_PIN_GMI_AD5_PG5 _GPIO(53) -#define TEGRA_PIN_GMI_AD6_PG6 _GPIO(54) -#define TEGRA_PIN_GMI_AD7_PG7 _GPIO(55) -#define TEGRA_PIN_GMI_AD8_PH0 _GPIO(56) -#define TEGRA_PIN_GMI_AD9_PH1 _GPIO(57) -#define TEGRA_PIN_GMI_AD10_PH2 _GPIO(58) -#define TEGRA_PIN_GMI_AD11_PH3 _GPIO(59) -#define TEGRA_PIN_GMI_AD12_PH4 _GPIO(60) -#define TEGRA_PIN_GMI_AD13_PH5 _GPIO(61) -#define TEGRA_PIN_GMI_AD14_PH6 _GPIO(62) -#define TEGRA_PIN_GMI_AD15_PH7 _GPIO(63) -#define TEGRA_PIN_GMI_HIOW_N_PI0 _GPIO(64) -#define TEGRA_PIN_GMI_HIOR_N_PI1 _GPIO(65) -#define TEGRA_PIN_GMI_CS5_N_PI2 _GPIO(66) -#define TEGRA_PIN_GMI_CS6_N_PI3 _GPIO(67) -#define TEGRA_PIN_GMI_RST_N_PI4 _GPIO(68) -#define TEGRA_PIN_GMI_IORDY_PI5 _GPIO(69) -#define TEGRA_PIN_GMI_CS7_N_PI6 _GPIO(70) -#define TEGRA_PIN_GMI_WAIT_PI7 _GPIO(71) -#define TEGRA_PIN_GMI_CS0_N_PJ0 _GPIO(72) -#define TEGRA_PIN_LCD_DE_PJ1 _GPIO(73) -#define TEGRA_PIN_GMI_CS1_N_PJ2 _GPIO(74) -#define TEGRA_PIN_LCD_HSYNC_PJ3 _GPIO(75) -#define TEGRA_PIN_LCD_VSYNC_PJ4 _GPIO(76) -#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) -#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) -#define TEGRA_PIN_GMI_AD16_PJ7 _GPIO(79) -#define TEGRA_PIN_GMI_ADV_N_PK0 _GPIO(80) -#define TEGRA_PIN_GMI_CLK_PK1 _GPIO(81) -#define TEGRA_PIN_GMI_CS4_N_PK2 _GPIO(82) -#define TEGRA_PIN_GMI_CS2_N_PK3 _GPIO(83) -#define TEGRA_PIN_GMI_CS3_N_PK4 _GPIO(84) -#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) -#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) -#define TEGRA_PIN_GMI_AD19_PK7 _GPIO(87) -#define TEGRA_PIN_VI_D2_PL0 _GPIO(88) -#define TEGRA_PIN_VI_D3_PL1 _GPIO(89) -#define TEGRA_PIN_VI_D4_PL2 _GPIO(90) -#define TEGRA_PIN_VI_D5_PL3 _GPIO(91) -#define TEGRA_PIN_VI_D6_PL4 _GPIO(92) -#define TEGRA_PIN_VI_D7_PL5 _GPIO(93) -#define TEGRA_PIN_VI_D8_PL6 _GPIO(94) -#define TEGRA_PIN_VI_D9_PL7 _GPIO(95) -#define TEGRA_PIN_LCD_D16_PM0 _GPIO(96) -#define TEGRA_PIN_LCD_D17_PM1 _GPIO(97) -#define TEGRA_PIN_LCD_D18_PM2 _GPIO(98) -#define TEGRA_PIN_LCD_D19_PM3 _GPIO(99) -#define TEGRA_PIN_LCD_D20_PM4 _GPIO(100) -#define TEGRA_PIN_LCD_D21_PM5 _GPIO(101) -#define TEGRA_PIN_LCD_D22_PM6 _GPIO(102) -#define TEGRA_PIN_LCD_D23_PM7 _GPIO(103) -#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) -#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) -#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) -#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) -#define TEGRA_PIN_LCD_CS0_N_PN4 _GPIO(108) -#define TEGRA_PIN_LCD_SDOUT_PN5 _GPIO(109) -#define TEGRA_PIN_LCD_DC0_PN6 _GPIO(110) -#define TEGRA_PIN_HDMI_INT_N_PN7 _GPIO(111) -#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) -#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) -#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) -#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) -#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) -#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) -#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) -#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) -#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) -#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) -#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) -#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) -#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) -#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) -#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) -#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) -#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) -#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) -#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) -#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) -#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) -#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) -#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) -#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) -#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) -#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) -#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) -#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) -#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) -#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) -#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) -#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) -#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) -#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) -#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) -#define TEGRA_PIN_KB_ROW11_PS3 _GPIO(147) -#define TEGRA_PIN_KB_ROW12_PS4 _GPIO(148) -#define TEGRA_PIN_KB_ROW13_PS5 _GPIO(149) -#define TEGRA_PIN_KB_ROW14_PS6 _GPIO(150) -#define TEGRA_PIN_KB_ROW15_PS7 _GPIO(151) -#define TEGRA_PIN_VI_PCLK_PT0 _GPIO(152) -#define TEGRA_PIN_VI_MCLK_PT1 _GPIO(153) -#define TEGRA_PIN_VI_D10_PT2 _GPIO(154) -#define TEGRA_PIN_VI_D11_PT3 _GPIO(155) -#define TEGRA_PIN_VI_D0_PT4 _GPIO(156) -#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) -#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) -#define TEGRA_PIN_GMI_DPD_PT7 _GPIO(159) -#define TEGRA_PIN_PU0 _GPIO(160) -#define TEGRA_PIN_PU1 _GPIO(161) -#define TEGRA_PIN_PU2 _GPIO(162) -#define TEGRA_PIN_PU3 _GPIO(163) -#define TEGRA_PIN_PU4 _GPIO(164) -#define TEGRA_PIN_PU5 _GPIO(165) -#define TEGRA_PIN_PU6 _GPIO(166) -#define TEGRA_PIN_JTAG_RTCK_PU7 _GPIO(167) -#define TEGRA_PIN_PV0 _GPIO(168) -#define TEGRA_PIN_PV1 _GPIO(169) -#define TEGRA_PIN_PV2 _GPIO(170) -#define TEGRA_PIN_PV3 _GPIO(171) -#define TEGRA_PIN_PV4 _GPIO(172) -#define TEGRA_PIN_PV5 _GPIO(173) -#define TEGRA_PIN_PV6 _GPIO(174) -#define TEGRA_PIN_LCD_DC1_PV7 _GPIO(175) -#define TEGRA_PIN_LCD_CS1_N_PW0 _GPIO(176) -#define TEGRA_PIN_LCD_M1_PW1 _GPIO(177) -#define TEGRA_PIN_SPI2_CS1_N_PW2 _GPIO(178) -#define TEGRA_PIN_SPI2_CS2_N_PW3 _GPIO(179) -#define TEGRA_PIN_DAP_MCLK1_PW4 _GPIO(180) -#define TEGRA_PIN_DAP_MCLK2_PW5 _GPIO(181) -#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) -#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) -#define TEGRA_PIN_SPI2_MOSI_PX0 _GPIO(184) -#define TEGRA_PIN_SPI2_MISO_PX1 _GPIO(185) -#define TEGRA_PIN_SPI2_SCK_PX2 _GPIO(186) -#define TEGRA_PIN_SPI2_CS0_N_PX3 _GPIO(187) -#define TEGRA_PIN_SPI1_MOSI_PX4 _GPIO(188) -#define TEGRA_PIN_SPI1_SCK_PX5 _GPIO(189) -#define TEGRA_PIN_SPI1_CS0_N_PX6 _GPIO(190) -#define TEGRA_PIN_SPI1_MISO_PX7 _GPIO(191) -#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) -#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) -#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) -#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) -#define TEGRA_PIN_SDIO1_DAT3_PY4 _GPIO(196) -#define TEGRA_PIN_SDIO1_DAT2_PY5 _GPIO(197) -#define TEGRA_PIN_SDIO1_DAT1_PY6 _GPIO(198) -#define TEGRA_PIN_SDIO1_DAT0_PY7 _GPIO(199) -#define TEGRA_PIN_SDIO1_CLK_PZ0 _GPIO(200) -#define TEGRA_PIN_SDIO1_CMD_PZ1 _GPIO(201) -#define TEGRA_PIN_LCD_SDIN_PZ2 _GPIO(202) -#define TEGRA_PIN_LCD_WR_N_PZ3 _GPIO(203) -#define TEGRA_PIN_LCD_SCK_PZ4 _GPIO(204) -#define TEGRA_PIN_SYS_CLK_REQ_PZ5 _GPIO(205) -#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) -#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) -#define TEGRA_PIN_GMI_AD20_PAA0 _GPIO(208) -#define TEGRA_PIN_GMI_AD21_PAA1 _GPIO(209) -#define TEGRA_PIN_GMI_AD22_PAA2 _GPIO(210) -#define TEGRA_PIN_GMI_AD23_PAA3 _GPIO(211) -#define TEGRA_PIN_GMI_AD24_PAA4 _GPIO(212) -#define TEGRA_PIN_GMI_AD25_PAA5 _GPIO(213) -#define TEGRA_PIN_GMI_AD26_PAA6 _GPIO(214) -#define TEGRA_PIN_GMI_AD27_PAA7 _GPIO(215) -#define TEGRA_PIN_LED_BLINK_PBB0 _GPIO(216) -#define TEGRA_PIN_VI_GP0_PBB1 _GPIO(217) -#define TEGRA_PIN_CAM_I2C_SCL_PBB2 _GPIO(218) -#define TEGRA_PIN_CAM_I2C_SDA_PBB3 _GPIO(219) -#define TEGRA_PIN_VI_GP3_PBB4 _GPIO(220) -#define TEGRA_PIN_VI_GP4_PBB5 _GPIO(221) -#define TEGRA_PIN_PBB6 _GPIO(222) -#define TEGRA_PIN_PBB7 _GPIO(223) - -/* All non-GPIO pins follow */ -#define NUM_GPIOS (TEGRA_PIN_PBB7 + 1) -#define _PIN(offset) (NUM_GPIOS + (offset)) - -#define TEGRA_PIN_CRT_HSYNC _PIN(30) -#define TEGRA_PIN_CRT_VSYNC _PIN(31) -#define TEGRA_PIN_DDC_SCL _PIN(32) -#define TEGRA_PIN_DDC_SDA _PIN(33) -#define TEGRA_PIN_OWC _PIN(34) -#define TEGRA_PIN_CORE_PWR_REQ _PIN(35) -#define TEGRA_PIN_CPU_PWR_REQ _PIN(36) -#define TEGRA_PIN_PWR_INT_N _PIN(37) -#define TEGRA_PIN_CLK_32_K_IN _PIN(38) -#define TEGRA_PIN_DDR_COMP_PD _PIN(39) -#define TEGRA_PIN_DDR_COMP_PU _PIN(40) -#define TEGRA_PIN_DDR_A0 _PIN(41) -#define TEGRA_PIN_DDR_A1 _PIN(42) -#define TEGRA_PIN_DDR_A2 _PIN(43) -#define TEGRA_PIN_DDR_A3 _PIN(44) -#define TEGRA_PIN_DDR_A4 _PIN(45) -#define TEGRA_PIN_DDR_A5 _PIN(46) -#define TEGRA_PIN_DDR_A6 _PIN(47) -#define TEGRA_PIN_DDR_A7 _PIN(48) -#define TEGRA_PIN_DDR_A8 _PIN(49) -#define TEGRA_PIN_DDR_A9 _PIN(50) -#define TEGRA_PIN_DDR_A10 _PIN(51) -#define TEGRA_PIN_DDR_A11 _PIN(52) -#define TEGRA_PIN_DDR_A12 _PIN(53) -#define TEGRA_PIN_DDR_A13 _PIN(54) -#define TEGRA_PIN_DDR_A14 _PIN(55) -#define TEGRA_PIN_DDR_CAS_N _PIN(56) -#define TEGRA_PIN_DDR_BA0 _PIN(57) -#define TEGRA_PIN_DDR_BA1 _PIN(58) -#define TEGRA_PIN_DDR_BA2 _PIN(59) -#define TEGRA_PIN_DDR_DQS0P _PIN(60) -#define TEGRA_PIN_DDR_DQS0N _PIN(61) -#define TEGRA_PIN_DDR_DQS1P _PIN(62) -#define TEGRA_PIN_DDR_DQS1N _PIN(63) -#define TEGRA_PIN_DDR_DQS2P _PIN(64) -#define TEGRA_PIN_DDR_DQS2N _PIN(65) -#define TEGRA_PIN_DDR_DQS3P _PIN(66) -#define TEGRA_PIN_DDR_DQS3N _PIN(67) -#define TEGRA_PIN_DDR_CKE0 _PIN(68) -#define TEGRA_PIN_DDR_CKE1 _PIN(69) -#define TEGRA_PIN_DDR_CLK _PIN(70) -#define TEGRA_PIN_DDR_CLK_N _PIN(71) -#define TEGRA_PIN_DDR_DM0 _PIN(72) -#define TEGRA_PIN_DDR_DM1 _PIN(73) -#define TEGRA_PIN_DDR_DM2 _PIN(74) -#define TEGRA_PIN_DDR_DM3 _PIN(75) -#define TEGRA_PIN_DDR_ODT _PIN(76) -#define TEGRA_PIN_DDR_QUSE0 _PIN(77) -#define TEGRA_PIN_DDR_QUSE1 _PIN(78) -#define TEGRA_PIN_DDR_QUSE2 _PIN(79) -#define TEGRA_PIN_DDR_QUSE3 _PIN(80) -#define TEGRA_PIN_DDR_RAS_N _PIN(81) -#define TEGRA_PIN_DDR_WE_N _PIN(82) -#define TEGRA_PIN_DDR_DQ0 _PIN(83) -#define TEGRA_PIN_DDR_DQ1 _PIN(84) -#define TEGRA_PIN_DDR_DQ2 _PIN(85) -#define TEGRA_PIN_DDR_DQ3 _PIN(86) -#define TEGRA_PIN_DDR_DQ4 _PIN(87) -#define TEGRA_PIN_DDR_DQ5 _PIN(88) -#define TEGRA_PIN_DDR_DQ6 _PIN(89) -#define TEGRA_PIN_DDR_DQ7 _PIN(90) -#define TEGRA_PIN_DDR_DQ8 _PIN(91) -#define TEGRA_PIN_DDR_DQ9 _PIN(92) -#define TEGRA_PIN_DDR_DQ10 _PIN(93) -#define TEGRA_PIN_DDR_DQ11 _PIN(94) -#define TEGRA_PIN_DDR_DQ12 _PIN(95) -#define TEGRA_PIN_DDR_DQ13 _PIN(96) -#define TEGRA_PIN_DDR_DQ14 _PIN(97) -#define TEGRA_PIN_DDR_DQ15 _PIN(98) -#define TEGRA_PIN_DDR_DQ16 _PIN(99) -#define TEGRA_PIN_DDR_DQ17 _PIN(100) -#define TEGRA_PIN_DDR_DQ18 _PIN(101) -#define TEGRA_PIN_DDR_DQ19 _PIN(102) -#define TEGRA_PIN_DDR_DQ20 _PIN(103) -#define TEGRA_PIN_DDR_DQ21 _PIN(104) -#define TEGRA_PIN_DDR_DQ22 _PIN(105) -#define TEGRA_PIN_DDR_DQ23 _PIN(106) -#define TEGRA_PIN_DDR_DQ24 _PIN(107) -#define TEGRA_PIN_DDR_DQ25 _PIN(108) -#define TEGRA_PIN_DDR_DQ26 _PIN(109) -#define TEGRA_PIN_DDR_DQ27 _PIN(110) -#define TEGRA_PIN_DDR_DQ28 _PIN(111) -#define TEGRA_PIN_DDR_DQ29 _PIN(112) -#define TEGRA_PIN_DDR_DQ30 _PIN(113) -#define TEGRA_PIN_DDR_DQ31 _PIN(114) -#define TEGRA_PIN_DDR_CS0_N _PIN(115) -#define TEGRA_PIN_DDR_CS1_N _PIN(116) -#define TEGRA_PIN_SYS_RESET _PIN(117) -#define TEGRA_PIN_JTAG_TRST_N _PIN(118) -#define TEGRA_PIN_JTAG_TDO _PIN(119) -#define TEGRA_PIN_JTAG_TMS _PIN(120) -#define TEGRA_PIN_JTAG_TCK _PIN(121) -#define TEGRA_PIN_JTAG_TDI _PIN(122) -#define TEGRA_PIN_TEST_MODE_EN _PIN(123) - -static const struct pinctrl_pin_desc tegra20_pins[] = { - PINCTRL_PIN(TEGRA_PIN_VI_GP6_PA0, "VI_GP6 PA0"), - PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), - PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), - PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_CLK_PA6, "SDIO3_CLK PA6"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_CMD_PA7, "SDIO3_CMD PA7"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD17_PB0, "GMI_AD17 PB0"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD18_PB1, "GMI_AD18 PB1"), - PINCTRL_PIN(TEGRA_PIN_LCD_PWR0_PB2, "LCD_PWR0 PB2"), - PINCTRL_PIN(TEGRA_PIN_LCD_PCLK_PB3, "LCD_PCLK PB3"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT3_PB4, "SDIO3_DAT3 PB4"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT2_PB5, "SDIO3_DAT2 PB5"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT1_PB6, "SDIO3_DAT1 PB6"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT0_PB7, "SDIO3_DAT0 PB7"), - PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), - PINCTRL_PIN(TEGRA_PIN_LCD_PWR1_PC1, "LCD_PWR1 PC1"), - PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), - PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), - PINCTRL_PIN(TEGRA_PIN_LCD_PWR2_PC6, "LCD_PWR2 PC6"), - PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT5_PD0, "SDIO3_DAT5 PD0"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT4_PD1, "SDIO3_DAT4 PD1"), - PINCTRL_PIN(TEGRA_PIN_VI_GP5_PD2, "VI_GP5 PD2"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT6_PD3, "SDIO3_DAT6 PD3"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT7_PD4, "SDIO3_DAT7 PD4"), - PINCTRL_PIN(TEGRA_PIN_VI_D1_PD5, "VI_D1 PD5"), - PINCTRL_PIN(TEGRA_PIN_VI_VSYNC_PD6, "VI_VSYNC PD6"), - PINCTRL_PIN(TEGRA_PIN_VI_HSYNC_PD7, "VI_HSYNC PD7"), - PINCTRL_PIN(TEGRA_PIN_LCD_D0_PE0, "LCD_D0 PE0"), - PINCTRL_PIN(TEGRA_PIN_LCD_D1_PE1, "LCD_D1 PE1"), - PINCTRL_PIN(TEGRA_PIN_LCD_D2_PE2, "LCD_D2 PE2"), - PINCTRL_PIN(TEGRA_PIN_LCD_D3_PE3, "LCD_D3 PE3"), - PINCTRL_PIN(TEGRA_PIN_LCD_D4_PE4, "LCD_D4 PE4"), - PINCTRL_PIN(TEGRA_PIN_LCD_D5_PE5, "LCD_D5 PE5"), - PINCTRL_PIN(TEGRA_PIN_LCD_D6_PE6, "LCD_D6 PE6"), - PINCTRL_PIN(TEGRA_PIN_LCD_D7_PE7, "LCD_D7 PE7"), - PINCTRL_PIN(TEGRA_PIN_LCD_D8_PF0, "LCD_D8 PF0"), - PINCTRL_PIN(TEGRA_PIN_LCD_D9_PF1, "LCD_D9 PF1"), - PINCTRL_PIN(TEGRA_PIN_LCD_D10_PF2, "LCD_D10 PF2"), - PINCTRL_PIN(TEGRA_PIN_LCD_D11_PF3, "LCD_D11 PF3"), - PINCTRL_PIN(TEGRA_PIN_LCD_D12_PF4, "LCD_D12 PF4"), - PINCTRL_PIN(TEGRA_PIN_LCD_D13_PF5, "LCD_D13 PF5"), - PINCTRL_PIN(TEGRA_PIN_LCD_D14_PF6, "LCD_D14 PF6"), - PINCTRL_PIN(TEGRA_PIN_LCD_D15_PF7, "LCD_D15 PF7"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"), - PINCTRL_PIN(TEGRA_PIN_GMI_HIOW_N_PI0, "GMI_HIOW_N PI0"), - PINCTRL_PIN(TEGRA_PIN_GMI_HIOR_N_PI1, "GMI_HIOR_N PI1"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS5_N_PI2, "GMI_CS5_N PI2"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"), - PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"), - PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"), - PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"), - PINCTRL_PIN(TEGRA_PIN_LCD_DE_PJ1, "LCD_DE PJ1"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"), - PINCTRL_PIN(TEGRA_PIN_LCD_HSYNC_PJ3, "LCD_HSYNC PJ3"), - PINCTRL_PIN(TEGRA_PIN_LCD_VSYNC_PJ4, "LCD_VSYNC PJ4"), - PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), - PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD16_PJ7, "GMI_AD16 PJ7"), - PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"), - PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD19_PK7, "GMI_AD19 PK7"), - PINCTRL_PIN(TEGRA_PIN_VI_D2_PL0, "VI_D2 PL0"), - PINCTRL_PIN(TEGRA_PIN_VI_D3_PL1, "VI_D3 PL1"), - PINCTRL_PIN(TEGRA_PIN_VI_D4_PL2, "VI_D4 PL2"), - PINCTRL_PIN(TEGRA_PIN_VI_D5_PL3, "VI_D5 PL3"), - PINCTRL_PIN(TEGRA_PIN_VI_D6_PL4, "VI_D6 PL4"), - PINCTRL_PIN(TEGRA_PIN_VI_D7_PL5, "VI_D7 PL5"), - PINCTRL_PIN(TEGRA_PIN_VI_D8_PL6, "VI_D8 PL6"), - PINCTRL_PIN(TEGRA_PIN_VI_D9_PL7, "VI_D9 PL7"), - PINCTRL_PIN(TEGRA_PIN_LCD_D16_PM0, "LCD_D16 PM0"), - PINCTRL_PIN(TEGRA_PIN_LCD_D17_PM1, "LCD_D17 PM1"), - PINCTRL_PIN(TEGRA_PIN_LCD_D18_PM2, "LCD_D18 PM2"), - PINCTRL_PIN(TEGRA_PIN_LCD_D19_PM3, "LCD_D19 PM3"), - PINCTRL_PIN(TEGRA_PIN_LCD_D20_PM4, "LCD_D20 PM4"), - PINCTRL_PIN(TEGRA_PIN_LCD_D21_PM5, "LCD_D21 PM5"), - PINCTRL_PIN(TEGRA_PIN_LCD_D22_PM6, "LCD_D22 PM6"), - PINCTRL_PIN(TEGRA_PIN_LCD_D23_PM7, "LCD_D23 PM7"), - PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), - PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), - PINCTRL_PIN(TEGRA_PIN_LCD_CS0_N_PN4, "LCD_CS0_N PN4"), - PINCTRL_PIN(TEGRA_PIN_LCD_SDOUT_PN5, "LCD_SDOUT PN5"), - PINCTRL_PIN(TEGRA_PIN_LCD_DC0_PN6, "LCD_DC0 PN6"), - PINCTRL_PIN(TEGRA_PIN_HDMI_INT_N_PN7, "HDMI_INT_N PN7"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), - PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), - PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), - PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), - PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), - PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), - PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), - PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), - PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), - PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), - PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), - PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), - PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), - PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), - PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"), - PINCTRL_PIN(TEGRA_PIN_VI_PCLK_PT0, "VI_PCLK PT0"), - PINCTRL_PIN(TEGRA_PIN_VI_MCLK_PT1, "VI_MCLK PT1"), - PINCTRL_PIN(TEGRA_PIN_VI_D10_PT2, "VD_D10 PT2"), - PINCTRL_PIN(TEGRA_PIN_VI_D11_PT3, "VI_D11 PT3"), - PINCTRL_PIN(TEGRA_PIN_VI_D0_PT4, "VI_D0 PT4"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), - PINCTRL_PIN(TEGRA_PIN_GMI_DPD_PT7, "GMI_DPD PT7"), - /* PU0..6: GPIO only */ - PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), - PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), - PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), - PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), - PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), - PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), - PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), - PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK_PU7, "JTAG_RTCK PU7"), - /* PV0..1: GPIO only */ - PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), - PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), - /* PV2..3: Balls are named after GPIO not function */ - PINCTRL_PIN(TEGRA_PIN_PV2, "PV2"), - PINCTRL_PIN(TEGRA_PIN_PV3, "PV3"), - /* PV4..6: GPIO only */ - PINCTRL_PIN(TEGRA_PIN_PV4, "PV4"), - PINCTRL_PIN(TEGRA_PIN_PV5, "PV5"), - PINCTRL_PIN(TEGRA_PIN_PV6, "PV6"), - PINCTRL_PIN(TEGRA_PIN_LCD_DC1_PV7, "LCD_DC1 PV7"), - PINCTRL_PIN(TEGRA_PIN_LCD_CS1_N_PW0, "LCD_CS1_N PW0"), - PINCTRL_PIN(TEGRA_PIN_LCD_M1_PW1, "LCD_M1 PW1"), - PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_N_PW2, "SPI2_CS1_N PW2"), - PINCTRL_PIN(TEGRA_PIN_SPI2_CS2_N_PW3, "SPI2_CS2_N PW3"), - PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_PW4, "DAP_MCLK1 PW4"), - PINCTRL_PIN(TEGRA_PIN_DAP_MCLK2_PW5, "DAP_MCLK2 PW5"), - PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), - PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), - PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PX0, "SPI2_MOSI PX0"), - PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PX1, "SPI2_MISO PX1"), - PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PX2, "SPI2_SCK PX2"), - PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_N_PX3, "SPI2_CS0_N PX3"), - PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PX4, "SPI1_MOSI PX4"), - PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PX5, "SPI1_SCK PX5"), - PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_N_PX6, "SPI1_CS0_N PX6"), - PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PX7, "SPI1_MISO PX7"), - PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), - PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), - PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), - PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT3_PY4, "SDIO1_DAT3 PY4"), - PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT2_PY5, "SDIO1_DAT2 PY5"), - PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT1_PY6, "SDIO1_DAT1 PY6"), - PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT0_PY7, "SDIO1_DAT0 PY7"), - PINCTRL_PIN(TEGRA_PIN_SDIO1_CLK_PZ0, "SDIO1_CLK PZ0"), - PINCTRL_PIN(TEGRA_PIN_SDIO1_CMD_PZ1, "SDIO1_CMD PZ1"), - PINCTRL_PIN(TEGRA_PIN_LCD_SDIN_PZ2, "LCD_SDIN PZ2"), - PINCTRL_PIN(TEGRA_PIN_LCD_WR_N_PZ3, "LCD_WR_N PZ3"), - PINCTRL_PIN(TEGRA_PIN_LCD_SCK_PZ4, "LCD_SCK PZ4"), - PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD20_PAA0, "GMI_AD20 PAA0"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD21_PAA1, "GMI_AD21 PAA1"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD22_PAA2, "GMI_AD22 PAA2"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD23_PAA3, "GMI_AD23 PAA3"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD24_PAA4, "GMI_AD24 PAA4"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD25_PAA5, "GMI_AD25 PAA5"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD26_PAA6, "GMI_AD26 PAA6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD27_PAA7, "GMI_AD27 PAA7"), - PINCTRL_PIN(TEGRA_PIN_LED_BLINK_PBB0, "LED_BLINK PBB0"), - PINCTRL_PIN(TEGRA_PIN_VI_GP0_PBB1, "VI_GP0 PBB1"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB2, "CAM_I2C_SCL PBB2"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB3, "CAM_I2C_SDA PBB3"), - PINCTRL_PIN(TEGRA_PIN_VI_GP3_PBB4, "VI_GP3 PBB4"), - PINCTRL_PIN(TEGRA_PIN_VI_GP4_PBB5, "VI_GP4 PBB5"), - PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), - PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), - PINCTRL_PIN(TEGRA_PIN_CRT_HSYNC, "CRT_HSYNC"), - PINCTRL_PIN(TEGRA_PIN_CRT_VSYNC, "CRT_VSYNC"), - PINCTRL_PIN(TEGRA_PIN_DDC_SCL, "DDC_SCL"), - PINCTRL_PIN(TEGRA_PIN_DDC_SDA, "DDC_SDA"), - PINCTRL_PIN(TEGRA_PIN_OWC, "OWC"), - PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), - PINCTRL_PIN(TEGRA_PIN_CLK_32_K_IN, "CLK_32_K_IN"), - PINCTRL_PIN(TEGRA_PIN_DDR_COMP_PD, "DDR_COMP_PD"), - PINCTRL_PIN(TEGRA_PIN_DDR_COMP_PU, "DDR_COMP_PU"), - PINCTRL_PIN(TEGRA_PIN_DDR_A0, "DDR_A0"), - PINCTRL_PIN(TEGRA_PIN_DDR_A1, "DDR_A1"), - PINCTRL_PIN(TEGRA_PIN_DDR_A2, "DDR_A2"), - PINCTRL_PIN(TEGRA_PIN_DDR_A3, "DDR_A3"), - PINCTRL_PIN(TEGRA_PIN_DDR_A4, "DDR_A4"), - PINCTRL_PIN(TEGRA_PIN_DDR_A5, "DDR_A5"), - PINCTRL_PIN(TEGRA_PIN_DDR_A6, "DDR_A6"), - PINCTRL_PIN(TEGRA_PIN_DDR_A7, "DDR_A7"), - PINCTRL_PIN(TEGRA_PIN_DDR_A8, "DDR_A8"), - PINCTRL_PIN(TEGRA_PIN_DDR_A9, "DDR_A9"), - PINCTRL_PIN(TEGRA_PIN_DDR_A10, "DDR_A10"), - PINCTRL_PIN(TEGRA_PIN_DDR_A11, "DDR_A11"), - PINCTRL_PIN(TEGRA_PIN_DDR_A12, "DDR_A12"), - PINCTRL_PIN(TEGRA_PIN_DDR_A13, "DDR_A13"), - PINCTRL_PIN(TEGRA_PIN_DDR_A14, "DDR_A14"), - PINCTRL_PIN(TEGRA_PIN_DDR_CAS_N, "DDR_CAS_N"), - PINCTRL_PIN(TEGRA_PIN_DDR_BA0, "DDR_BA0"), - PINCTRL_PIN(TEGRA_PIN_DDR_BA1, "DDR_BA1"), - PINCTRL_PIN(TEGRA_PIN_DDR_BA2, "DDR_BA2"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQS0P, "DDR_DQS0P"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQS0N, "DDR_DQS0N"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQS1P, "DDR_DQS1P"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQS1N, "DDR_DQS1N"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQS2P, "DDR_DQS2P"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQS2N, "DDR_DQS2N"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQS3P, "DDR_DQS3P"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQS3N, "DDR_DQS3N"), - PINCTRL_PIN(TEGRA_PIN_DDR_CKE0, "DDR_CKE0"), - PINCTRL_PIN(TEGRA_PIN_DDR_CKE1, "DDR_CKE1"), - PINCTRL_PIN(TEGRA_PIN_DDR_CLK, "DDR_CLK"), - PINCTRL_PIN(TEGRA_PIN_DDR_CLK_N, "DDR_CLK_N"), - PINCTRL_PIN(TEGRA_PIN_DDR_DM0, "DDR_DM0"), - PINCTRL_PIN(TEGRA_PIN_DDR_DM1, "DDR_DM1"), - PINCTRL_PIN(TEGRA_PIN_DDR_DM2, "DDR_DM2"), - PINCTRL_PIN(TEGRA_PIN_DDR_DM3, "DDR_DM3"), - PINCTRL_PIN(TEGRA_PIN_DDR_ODT, "DDR_ODT"), - PINCTRL_PIN(TEGRA_PIN_DDR_QUSE0, "DDR_QUSE0"), - PINCTRL_PIN(TEGRA_PIN_DDR_QUSE1, "DDR_QUSE1"), - PINCTRL_PIN(TEGRA_PIN_DDR_QUSE2, "DDR_QUSE2"), - PINCTRL_PIN(TEGRA_PIN_DDR_QUSE3, "DDR_QUSE3"), - PINCTRL_PIN(TEGRA_PIN_DDR_RAS_N, "DDR_RAS_N"), - PINCTRL_PIN(TEGRA_PIN_DDR_WE_N, "DDR_WE_N"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ0, "DDR_DQ0"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ1, "DDR_DQ1"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ2, "DDR_DQ2"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ3, "DDR_DQ3"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ4, "DDR_DQ4"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ5, "DDR_DQ5"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ6, "DDR_DQ6"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ7, "DDR_DQ7"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ8, "DDR_DQ8"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ9, "DDR_DQ9"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ10, "DDR_DQ10"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ11, "DDR_DQ11"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ12, "DDR_DQ12"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ13, "DDR_DQ13"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ14, "DDR_DQ14"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ15, "DDR_DQ15"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ16, "DDR_DQ16"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ17, "DDR_DQ17"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ18, "DDR_DQ18"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ19, "DDR_DQ19"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ20, "DDR_DQ20"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ21, "DDR_DQ21"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ22, "DDR_DQ22"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ23, "DDR_DQ23"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ24, "DDR_DQ24"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ25, "DDR_DQ25"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ26, "DDR_DQ26"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ27, "DDR_DQ27"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ28, "DDR_DQ28"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ29, "DDR_DQ29"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ30, "DDR_DQ30"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ31, "DDR_DQ31"), - PINCTRL_PIN(TEGRA_PIN_DDR_CS0_N, "DDR_CS0_N"), - PINCTRL_PIN(TEGRA_PIN_DDR_CS1_N, "DDR_CS1_N"), - PINCTRL_PIN(TEGRA_PIN_SYS_RESET, "SYS_RESET"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TRST_N, "JTAG_TRST_N"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TDO, "JTAG_TDO"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TMS, "JTAG_TMS"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TCK, "JTAG_TCK"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TDI, "JTAG_TDI"), - PINCTRL_PIN(TEGRA_PIN_TEST_MODE_EN, "TEST_MODE_EN"), -}; - -static const unsigned ata_pins[] = { - TEGRA_PIN_GMI_CS6_N_PI3, - TEGRA_PIN_GMI_CS7_N_PI6, - TEGRA_PIN_GMI_RST_N_PI4, -}; - -static const unsigned atb_pins[] = { - TEGRA_PIN_GMI_CS5_N_PI2, - TEGRA_PIN_GMI_DPD_PT7, -}; - -static const unsigned atc_pins[] = { - TEGRA_PIN_GMI_IORDY_PI5, - TEGRA_PIN_GMI_WAIT_PI7, - TEGRA_PIN_GMI_ADV_N_PK0, - TEGRA_PIN_GMI_CLK_PK1, - TEGRA_PIN_GMI_CS2_N_PK3, - TEGRA_PIN_GMI_CS3_N_PK4, - TEGRA_PIN_GMI_CS4_N_PK2, - TEGRA_PIN_GMI_AD0_PG0, - TEGRA_PIN_GMI_AD1_PG1, - TEGRA_PIN_GMI_AD2_PG2, - TEGRA_PIN_GMI_AD3_PG3, - TEGRA_PIN_GMI_AD4_PG4, - TEGRA_PIN_GMI_AD5_PG5, - TEGRA_PIN_GMI_AD6_PG6, - TEGRA_PIN_GMI_AD7_PG7, - TEGRA_PIN_GMI_HIOW_N_PI0, - TEGRA_PIN_GMI_HIOR_N_PI1, -}; - -static const unsigned atd_pins[] = { - TEGRA_PIN_GMI_AD8_PH0, - TEGRA_PIN_GMI_AD9_PH1, - TEGRA_PIN_GMI_AD10_PH2, - TEGRA_PIN_GMI_AD11_PH3, -}; - -static const unsigned ate_pins[] = { - TEGRA_PIN_GMI_AD12_PH4, - TEGRA_PIN_GMI_AD13_PH5, - TEGRA_PIN_GMI_AD14_PH6, - TEGRA_PIN_GMI_AD15_PH7, -}; - -static const unsigned cdev1_pins[] = { - TEGRA_PIN_DAP_MCLK1_PW4, -}; - -static const unsigned cdev2_pins[] = { - TEGRA_PIN_DAP_MCLK2_PW5, -}; - -static const unsigned crtp_pins[] = { - TEGRA_PIN_CRT_HSYNC, - TEGRA_PIN_CRT_VSYNC, -}; - -static const unsigned csus_pins[] = { - TEGRA_PIN_VI_MCLK_PT1, -}; - -static const unsigned dap1_pins[] = { - TEGRA_PIN_DAP1_FS_PN0, - TEGRA_PIN_DAP1_DIN_PN1, - TEGRA_PIN_DAP1_DOUT_PN2, - TEGRA_PIN_DAP1_SCLK_PN3, -}; - -static const unsigned dap2_pins[] = { - TEGRA_PIN_DAP2_FS_PA2, - TEGRA_PIN_DAP2_SCLK_PA3, - TEGRA_PIN_DAP2_DIN_PA4, - TEGRA_PIN_DAP2_DOUT_PA5, -}; - -static const unsigned dap3_pins[] = { - TEGRA_PIN_DAP3_FS_PP0, - TEGRA_PIN_DAP3_DIN_PP1, - TEGRA_PIN_DAP3_DOUT_PP2, - TEGRA_PIN_DAP3_SCLK_PP3, -}; - -static const unsigned dap4_pins[] = { - TEGRA_PIN_DAP4_FS_PP4, - TEGRA_PIN_DAP4_DIN_PP5, - TEGRA_PIN_DAP4_DOUT_PP6, - TEGRA_PIN_DAP4_SCLK_PP7, -}; - -static const unsigned ddc_pins[] = { - TEGRA_PIN_DDC_SCL, - TEGRA_PIN_DDC_SDA, -}; - -static const unsigned dta_pins[] = { - TEGRA_PIN_VI_D0_PT4, - TEGRA_PIN_VI_D1_PD5, -}; - -static const unsigned dtb_pins[] = { - TEGRA_PIN_VI_D10_PT2, - TEGRA_PIN_VI_D11_PT3, -}; - -static const unsigned dtc_pins[] = { - TEGRA_PIN_VI_HSYNC_PD7, - TEGRA_PIN_VI_VSYNC_PD6, -}; - -static const unsigned dtd_pins[] = { - TEGRA_PIN_VI_PCLK_PT0, - TEGRA_PIN_VI_D2_PL0, - TEGRA_PIN_VI_D3_PL1, - TEGRA_PIN_VI_D4_PL2, - TEGRA_PIN_VI_D5_PL3, - TEGRA_PIN_VI_D6_PL4, - TEGRA_PIN_VI_D7_PL5, - TEGRA_PIN_VI_D8_PL6, - TEGRA_PIN_VI_D9_PL7, -}; - -static const unsigned dte_pins[] = { - TEGRA_PIN_VI_GP0_PBB1, - TEGRA_PIN_VI_GP3_PBB4, - TEGRA_PIN_VI_GP4_PBB5, - TEGRA_PIN_VI_GP5_PD2, - TEGRA_PIN_VI_GP6_PA0, -}; - -static const unsigned dtf_pins[] = { - TEGRA_PIN_CAM_I2C_SCL_PBB2, - TEGRA_PIN_CAM_I2C_SDA_PBB3, -}; - -static const unsigned gma_pins[] = { - TEGRA_PIN_GMI_AD20_PAA0, - TEGRA_PIN_GMI_AD21_PAA1, - TEGRA_PIN_GMI_AD22_PAA2, - TEGRA_PIN_GMI_AD23_PAA3, -}; - -static const unsigned gmb_pins[] = { - TEGRA_PIN_GMI_WP_N_PC7, -}; - -static const unsigned gmc_pins[] = { - TEGRA_PIN_GMI_AD16_PJ7, - TEGRA_PIN_GMI_AD17_PB0, - TEGRA_PIN_GMI_AD18_PB1, - TEGRA_PIN_GMI_AD19_PK7, -}; - -static const unsigned gmd_pins[] = { - TEGRA_PIN_GMI_CS0_N_PJ0, - TEGRA_PIN_GMI_CS1_N_PJ2, -}; - -static const unsigned gme_pins[] = { - TEGRA_PIN_GMI_AD24_PAA4, - TEGRA_PIN_GMI_AD25_PAA5, - TEGRA_PIN_GMI_AD26_PAA6, - TEGRA_PIN_GMI_AD27_PAA7, -}; - -static const unsigned gpu_pins[] = { - TEGRA_PIN_PU0, - TEGRA_PIN_PU1, - TEGRA_PIN_PU2, - TEGRA_PIN_PU3, - TEGRA_PIN_PU4, - TEGRA_PIN_PU5, - TEGRA_PIN_PU6, -}; - -static const unsigned gpu7_pins[] = { - TEGRA_PIN_JTAG_RTCK_PU7, -}; - -static const unsigned gpv_pins[] = { - TEGRA_PIN_PV4, - TEGRA_PIN_PV5, - TEGRA_PIN_PV6, -}; - -static const unsigned hdint_pins[] = { - TEGRA_PIN_HDMI_INT_N_PN7, -}; - -static const unsigned i2cp_pins[] = { - TEGRA_PIN_PWR_I2C_SCL_PZ6, - TEGRA_PIN_PWR_I2C_SDA_PZ7, -}; - -static const unsigned irrx_pins[] = { - TEGRA_PIN_UART2_RTS_N_PJ6, -}; - -static const unsigned irtx_pins[] = { - TEGRA_PIN_UART2_CTS_N_PJ5, -}; - -static const unsigned kbca_pins[] = { - TEGRA_PIN_KB_ROW0_PR0, - TEGRA_PIN_KB_ROW1_PR1, - TEGRA_PIN_KB_ROW2_PR2, -}; - -static const unsigned kbcb_pins[] = { - TEGRA_PIN_KB_ROW7_PR7, - TEGRA_PIN_KB_ROW8_PS0, - TEGRA_PIN_KB_ROW9_PS1, - TEGRA_PIN_KB_ROW10_PS2, - TEGRA_PIN_KB_ROW11_PS3, - TEGRA_PIN_KB_ROW12_PS4, - TEGRA_PIN_KB_ROW13_PS5, - TEGRA_PIN_KB_ROW14_PS6, - TEGRA_PIN_KB_ROW15_PS7, -}; - -static const unsigned kbcc_pins[] = { - TEGRA_PIN_KB_COL0_PQ0, - TEGRA_PIN_KB_COL1_PQ1, -}; - -static const unsigned kbcd_pins[] = { - TEGRA_PIN_KB_ROW3_PR3, - TEGRA_PIN_KB_ROW4_PR4, - TEGRA_PIN_KB_ROW5_PR5, - TEGRA_PIN_KB_ROW6_PR6, -}; - -static const unsigned kbce_pins[] = { - TEGRA_PIN_KB_COL7_PQ7, -}; - -static const unsigned kbcf_pins[] = { - TEGRA_PIN_KB_COL2_PQ2, - TEGRA_PIN_KB_COL3_PQ3, - TEGRA_PIN_KB_COL4_PQ4, - TEGRA_PIN_KB_COL5_PQ5, - TEGRA_PIN_KB_COL6_PQ6, -}; - -static const unsigned lcsn_pins[] = { - TEGRA_PIN_LCD_CS0_N_PN4, -}; - -static const unsigned ld0_pins[] = { - TEGRA_PIN_LCD_D0_PE0, -}; - -static const unsigned ld1_pins[] = { - TEGRA_PIN_LCD_D1_PE1, -}; - -static const unsigned ld2_pins[] = { - TEGRA_PIN_LCD_D2_PE2, -}; - -static const unsigned ld3_pins[] = { - TEGRA_PIN_LCD_D3_PE3, -}; - -static const unsigned ld4_pins[] = { - TEGRA_PIN_LCD_D4_PE4, -}; - -static const unsigned ld5_pins[] = { - TEGRA_PIN_LCD_D5_PE5, -}; - -static const unsigned ld6_pins[] = { - TEGRA_PIN_LCD_D6_PE6, -}; - -static const unsigned ld7_pins[] = { - TEGRA_PIN_LCD_D7_PE7, -}; - -static const unsigned ld8_pins[] = { - TEGRA_PIN_LCD_D8_PF0, -}; - -static const unsigned ld9_pins[] = { - TEGRA_PIN_LCD_D9_PF1, -}; - -static const unsigned ld10_pins[] = { - TEGRA_PIN_LCD_D10_PF2, -}; - -static const unsigned ld11_pins[] = { - TEGRA_PIN_LCD_D11_PF3, -}; - -static const unsigned ld12_pins[] = { - TEGRA_PIN_LCD_D12_PF4, -}; - -static const unsigned ld13_pins[] = { - TEGRA_PIN_LCD_D13_PF5, -}; - -static const unsigned ld14_pins[] = { - TEGRA_PIN_LCD_D14_PF6, -}; - -static const unsigned ld15_pins[] = { - TEGRA_PIN_LCD_D15_PF7, -}; - -static const unsigned ld16_pins[] = { - TEGRA_PIN_LCD_D16_PM0, -}; - -static const unsigned ld17_pins[] = { - TEGRA_PIN_LCD_D17_PM1, -}; - -static const unsigned ldc_pins[] = { - TEGRA_PIN_LCD_DC0_PN6, -}; - -static const unsigned ldi_pins[] = { - TEGRA_PIN_LCD_D22_PM6, -}; - -static const unsigned lhp0_pins[] = { - TEGRA_PIN_LCD_D21_PM5, -}; - -static const unsigned lhp1_pins[] = { - TEGRA_PIN_LCD_D18_PM2, -}; - -static const unsigned lhp2_pins[] = { - TEGRA_PIN_LCD_D19_PM3, -}; - -static const unsigned lhs_pins[] = { - TEGRA_PIN_LCD_HSYNC_PJ3, -}; - -static const unsigned lm0_pins[] = { - TEGRA_PIN_LCD_CS1_N_PW0, -}; - -static const unsigned lm1_pins[] = { - TEGRA_PIN_LCD_M1_PW1, -}; - -static const unsigned lpp_pins[] = { - TEGRA_PIN_LCD_D23_PM7, -}; - -static const unsigned lpw0_pins[] = { - TEGRA_PIN_LCD_PWR0_PB2, -}; - -static const unsigned lpw1_pins[] = { - TEGRA_PIN_LCD_PWR1_PC1, -}; - -static const unsigned lpw2_pins[] = { - TEGRA_PIN_LCD_PWR2_PC6, -}; - -static const unsigned lsc0_pins[] = { - TEGRA_PIN_LCD_PCLK_PB3, -}; - -static const unsigned lsc1_pins[] = { - TEGRA_PIN_LCD_WR_N_PZ3, -}; - -static const unsigned lsck_pins[] = { - TEGRA_PIN_LCD_SCK_PZ4, -}; - -static const unsigned lsda_pins[] = { - TEGRA_PIN_LCD_SDOUT_PN5, -}; - -static const unsigned lsdi_pins[] = { - TEGRA_PIN_LCD_SDIN_PZ2, -}; - -static const unsigned lspi_pins[] = { - TEGRA_PIN_LCD_DE_PJ1, -}; - -static const unsigned lvp0_pins[] = { - TEGRA_PIN_LCD_DC1_PV7, -}; - -static const unsigned lvp1_pins[] = { - TEGRA_PIN_LCD_D20_PM4, -}; - -static const unsigned lvs_pins[] = { - TEGRA_PIN_LCD_VSYNC_PJ4, -}; - -static const unsigned ls_pins[] = { - TEGRA_PIN_LCD_PWR0_PB2, - TEGRA_PIN_LCD_PWR1_PC1, - TEGRA_PIN_LCD_PWR2_PC6, - TEGRA_PIN_LCD_SDIN_PZ2, - TEGRA_PIN_LCD_SDOUT_PN5, - TEGRA_PIN_LCD_WR_N_PZ3, - TEGRA_PIN_LCD_CS0_N_PN4, - TEGRA_PIN_LCD_DC0_PN6, - TEGRA_PIN_LCD_SCK_PZ4, -}; - -static const unsigned lc_pins[] = { - TEGRA_PIN_LCD_PCLK_PB3, - TEGRA_PIN_LCD_DE_PJ1, - TEGRA_PIN_LCD_HSYNC_PJ3, - TEGRA_PIN_LCD_VSYNC_PJ4, - TEGRA_PIN_LCD_CS1_N_PW0, - TEGRA_PIN_LCD_M1_PW1, - TEGRA_PIN_LCD_DC1_PV7, - TEGRA_PIN_HDMI_INT_N_PN7, -}; - -static const unsigned ld17_0_pins[] = { - TEGRA_PIN_LCD_D0_PE0, - TEGRA_PIN_LCD_D1_PE1, - TEGRA_PIN_LCD_D2_PE2, - TEGRA_PIN_LCD_D3_PE3, - TEGRA_PIN_LCD_D4_PE4, - TEGRA_PIN_LCD_D5_PE5, - TEGRA_PIN_LCD_D6_PE6, - TEGRA_PIN_LCD_D7_PE7, - TEGRA_PIN_LCD_D8_PF0, - TEGRA_PIN_LCD_D9_PF1, - TEGRA_PIN_LCD_D10_PF2, - TEGRA_PIN_LCD_D11_PF3, - TEGRA_PIN_LCD_D12_PF4, - TEGRA_PIN_LCD_D13_PF5, - TEGRA_PIN_LCD_D14_PF6, - TEGRA_PIN_LCD_D15_PF7, - TEGRA_PIN_LCD_D16_PM0, - TEGRA_PIN_LCD_D17_PM1, -}; - -static const unsigned ld19_18_pins[] = { - TEGRA_PIN_LCD_D18_PM2, - TEGRA_PIN_LCD_D19_PM3, -}; - -static const unsigned ld21_20_pins[] = { - TEGRA_PIN_LCD_D20_PM4, - TEGRA_PIN_LCD_D21_PM5, -}; - -static const unsigned ld23_22_pins[] = { - TEGRA_PIN_LCD_D22_PM6, - TEGRA_PIN_LCD_D23_PM7, -}; - -static const unsigned owc_pins[] = { - TEGRA_PIN_OWC, -}; - -static const unsigned pmc_pins[] = { - TEGRA_PIN_LED_BLINK_PBB0, - TEGRA_PIN_SYS_CLK_REQ_PZ5, - TEGRA_PIN_CORE_PWR_REQ, - TEGRA_PIN_CPU_PWR_REQ, - TEGRA_PIN_PWR_INT_N, -}; - -static const unsigned pta_pins[] = { - TEGRA_PIN_GEN2_I2C_SCL_PT5, - TEGRA_PIN_GEN2_I2C_SDA_PT6, -}; - -static const unsigned rm_pins[] = { - TEGRA_PIN_GEN1_I2C_SCL_PC4, - TEGRA_PIN_GEN1_I2C_SDA_PC5, -}; - -static const unsigned sdb_pins[] = { - TEGRA_PIN_SDIO3_CMD_PA7, -}; - -static const unsigned sdc_pins[] = { - TEGRA_PIN_SDIO3_DAT0_PB7, - TEGRA_PIN_SDIO3_DAT1_PB6, - TEGRA_PIN_SDIO3_DAT2_PB5, - TEGRA_PIN_SDIO3_DAT3_PB4, -}; - -static const unsigned sdd_pins[] = { - TEGRA_PIN_SDIO3_CLK_PA6, -}; - -static const unsigned sdio1_pins[] = { - TEGRA_PIN_SDIO1_CLK_PZ0, - TEGRA_PIN_SDIO1_CMD_PZ1, - TEGRA_PIN_SDIO1_DAT0_PY7, - TEGRA_PIN_SDIO1_DAT1_PY6, - TEGRA_PIN_SDIO1_DAT2_PY5, - TEGRA_PIN_SDIO1_DAT3_PY4, -}; - -static const unsigned slxa_pins[] = { - TEGRA_PIN_SDIO3_DAT4_PD1, -}; - -static const unsigned slxc_pins[] = { - TEGRA_PIN_SDIO3_DAT6_PD3, -}; - -static const unsigned slxd_pins[] = { - TEGRA_PIN_SDIO3_DAT7_PD4, -}; - -static const unsigned slxk_pins[] = { - TEGRA_PIN_SDIO3_DAT5_PD0, -}; - -static const unsigned spdi_pins[] = { - TEGRA_PIN_SPDIF_IN_PK6, -}; - -static const unsigned spdo_pins[] = { - TEGRA_PIN_SPDIF_OUT_PK5, -}; - -static const unsigned spia_pins[] = { - TEGRA_PIN_SPI2_MOSI_PX0, -}; - -static const unsigned spib_pins[] = { - TEGRA_PIN_SPI2_MISO_PX1, -}; - -static const unsigned spic_pins[] = { - TEGRA_PIN_SPI2_CS0_N_PX3, - TEGRA_PIN_SPI2_SCK_PX2, -}; - -static const unsigned spid_pins[] = { - TEGRA_PIN_SPI1_MOSI_PX4, -}; - -static const unsigned spie_pins[] = { - TEGRA_PIN_SPI1_CS0_N_PX6, - TEGRA_PIN_SPI1_SCK_PX5, -}; - -static const unsigned spif_pins[] = { - TEGRA_PIN_SPI1_MISO_PX7, -}; - -static const unsigned spig_pins[] = { - TEGRA_PIN_SPI2_CS1_N_PW2, -}; - -static const unsigned spih_pins[] = { - TEGRA_PIN_SPI2_CS2_N_PW3, -}; - -static const unsigned uaa_pins[] = { - TEGRA_PIN_ULPI_DATA0_PO1, - TEGRA_PIN_ULPI_DATA1_PO2, - TEGRA_PIN_ULPI_DATA2_PO3, - TEGRA_PIN_ULPI_DATA3_PO4, -}; - -static const unsigned uab_pins[] = { - TEGRA_PIN_ULPI_DATA4_PO5, - TEGRA_PIN_ULPI_DATA5_PO6, - TEGRA_PIN_ULPI_DATA6_PO7, - TEGRA_PIN_ULPI_DATA7_PO0, -}; - -static const unsigned uac_pins[] = { - TEGRA_PIN_PV0, - TEGRA_PIN_PV1, - TEGRA_PIN_PV2, - TEGRA_PIN_PV3, -}; - -static const unsigned ck32_pins[] = { - TEGRA_PIN_CLK_32_K_IN, -}; - -static const unsigned uad_pins[] = { - TEGRA_PIN_UART2_RXD_PC3, - TEGRA_PIN_UART2_TXD_PC2, -}; - -static const unsigned uca_pins[] = { - TEGRA_PIN_UART3_RXD_PW7, - TEGRA_PIN_UART3_TXD_PW6, -}; - -static const unsigned ucb_pins[] = { - TEGRA_PIN_UART3_CTS_N_PA1, - TEGRA_PIN_UART3_RTS_N_PC0, -}; - -static const unsigned uda_pins[] = { - TEGRA_PIN_ULPI_CLK_PY0, - TEGRA_PIN_ULPI_DIR_PY1, - TEGRA_PIN_ULPI_NXT_PY2, - TEGRA_PIN_ULPI_STP_PY3, -}; - -static const unsigned ddrc_pins[] = { - TEGRA_PIN_DDR_COMP_PD, - TEGRA_PIN_DDR_COMP_PU, -}; - -static const unsigned pmca_pins[] = { - TEGRA_PIN_LED_BLINK_PBB0, -}; - -static const unsigned pmcb_pins[] = { - TEGRA_PIN_SYS_CLK_REQ_PZ5, -}; - -static const unsigned pmcc_pins[] = { - TEGRA_PIN_CORE_PWR_REQ, -}; - -static const unsigned pmcd_pins[] = { - TEGRA_PIN_CPU_PWR_REQ, -}; - -static const unsigned pmce_pins[] = { - TEGRA_PIN_PWR_INT_N, -}; - -static const unsigned xm2c_pins[] = { - TEGRA_PIN_DDR_A0, - TEGRA_PIN_DDR_A1, - TEGRA_PIN_DDR_A2, - TEGRA_PIN_DDR_A3, - TEGRA_PIN_DDR_A4, - TEGRA_PIN_DDR_A5, - TEGRA_PIN_DDR_A6, - TEGRA_PIN_DDR_A7, - TEGRA_PIN_DDR_A8, - TEGRA_PIN_DDR_A9, - TEGRA_PIN_DDR_A10, - TEGRA_PIN_DDR_A11, - TEGRA_PIN_DDR_A12, - TEGRA_PIN_DDR_A13, - TEGRA_PIN_DDR_A14, - TEGRA_PIN_DDR_CAS_N, - TEGRA_PIN_DDR_BA0, - TEGRA_PIN_DDR_BA1, - TEGRA_PIN_DDR_BA2, - TEGRA_PIN_DDR_DQS0P, - TEGRA_PIN_DDR_DQS0N, - TEGRA_PIN_DDR_DQS1P, - TEGRA_PIN_DDR_DQS1N, - TEGRA_PIN_DDR_DQS2P, - TEGRA_PIN_DDR_DQS2N, - TEGRA_PIN_DDR_DQS3P, - TEGRA_PIN_DDR_DQS3N, - TEGRA_PIN_DDR_CS0_N, - TEGRA_PIN_DDR_CS1_N, - TEGRA_PIN_DDR_CKE0, - TEGRA_PIN_DDR_CKE1, - TEGRA_PIN_DDR_CLK, - TEGRA_PIN_DDR_CLK_N, - TEGRA_PIN_DDR_DM0, - TEGRA_PIN_DDR_DM1, - TEGRA_PIN_DDR_DM2, - TEGRA_PIN_DDR_DM3, - TEGRA_PIN_DDR_ODT, - TEGRA_PIN_DDR_RAS_N, - TEGRA_PIN_DDR_WE_N, - TEGRA_PIN_DDR_QUSE0, - TEGRA_PIN_DDR_QUSE1, - TEGRA_PIN_DDR_QUSE2, - TEGRA_PIN_DDR_QUSE3, -}; - -static const unsigned xm2d_pins[] = { - TEGRA_PIN_DDR_DQ0, - TEGRA_PIN_DDR_DQ1, - TEGRA_PIN_DDR_DQ2, - TEGRA_PIN_DDR_DQ3, - TEGRA_PIN_DDR_DQ4, - TEGRA_PIN_DDR_DQ5, - TEGRA_PIN_DDR_DQ6, - TEGRA_PIN_DDR_DQ7, - TEGRA_PIN_DDR_DQ8, - TEGRA_PIN_DDR_DQ9, - TEGRA_PIN_DDR_DQ10, - TEGRA_PIN_DDR_DQ11, - TEGRA_PIN_DDR_DQ12, - TEGRA_PIN_DDR_DQ13, - TEGRA_PIN_DDR_DQ14, - TEGRA_PIN_DDR_DQ15, - TEGRA_PIN_DDR_DQ16, - TEGRA_PIN_DDR_DQ17, - TEGRA_PIN_DDR_DQ18, - TEGRA_PIN_DDR_DQ19, - TEGRA_PIN_DDR_DQ20, - TEGRA_PIN_DDR_DQ21, - TEGRA_PIN_DDR_DQ22, - TEGRA_PIN_DDR_DQ23, - TEGRA_PIN_DDR_DQ24, - TEGRA_PIN_DDR_DQ25, - TEGRA_PIN_DDR_DQ26, - TEGRA_PIN_DDR_DQ27, - TEGRA_PIN_DDR_DQ28, - TEGRA_PIN_DDR_DQ29, - TEGRA_PIN_DDR_DQ30, - TEGRA_PIN_DDR_DQ31, -}; - -static const unsigned drive_ao1_pins[] = { - TEGRA_PIN_SYS_RESET, - TEGRA_PIN_PWR_I2C_SCL_PZ6, - TEGRA_PIN_PWR_I2C_SDA_PZ7, - TEGRA_PIN_KB_ROW0_PR0, - TEGRA_PIN_KB_ROW1_PR1, - TEGRA_PIN_KB_ROW2_PR2, - TEGRA_PIN_KB_ROW3_PR3, - TEGRA_PIN_KB_ROW4_PR4, - TEGRA_PIN_KB_ROW5_PR5, - TEGRA_PIN_KB_ROW6_PR6, - TEGRA_PIN_KB_ROW7_PR7, -}; - -static const unsigned drive_ao2_pins[] = { - TEGRA_PIN_KB_ROW8_PS0, - TEGRA_PIN_KB_ROW9_PS1, - TEGRA_PIN_KB_ROW10_PS2, - TEGRA_PIN_KB_ROW11_PS3, - TEGRA_PIN_KB_ROW12_PS4, - TEGRA_PIN_KB_ROW13_PS5, - TEGRA_PIN_KB_ROW14_PS6, - TEGRA_PIN_KB_ROW15_PS7, - TEGRA_PIN_KB_COL0_PQ0, - TEGRA_PIN_KB_COL1_PQ1, - TEGRA_PIN_KB_COL2_PQ2, - TEGRA_PIN_KB_COL3_PQ3, - TEGRA_PIN_KB_COL4_PQ4, - TEGRA_PIN_KB_COL5_PQ5, - TEGRA_PIN_KB_COL6_PQ6, - TEGRA_PIN_KB_COL7_PQ7, - TEGRA_PIN_LED_BLINK_PBB0, - TEGRA_PIN_SYS_CLK_REQ_PZ5, - TEGRA_PIN_CORE_PWR_REQ, - TEGRA_PIN_CPU_PWR_REQ, - TEGRA_PIN_PWR_INT_N, - TEGRA_PIN_CLK_32_K_IN, -}; - -static const unsigned drive_at1_pins[] = { - TEGRA_PIN_GMI_IORDY_PI5, - TEGRA_PIN_GMI_AD8_PH0, - TEGRA_PIN_GMI_AD9_PH1, - TEGRA_PIN_GMI_AD10_PH2, - TEGRA_PIN_GMI_AD11_PH3, - TEGRA_PIN_GMI_AD12_PH4, - TEGRA_PIN_GMI_AD13_PH5, - TEGRA_PIN_GMI_AD14_PH6, - TEGRA_PIN_GMI_AD15_PH7, - TEGRA_PIN_GMI_CS7_N_PI6, - TEGRA_PIN_GMI_DPD_PT7, - TEGRA_PIN_GEN2_I2C_SCL_PT5, - TEGRA_PIN_GEN2_I2C_SDA_PT6, -}; - -static const unsigned drive_at2_pins[] = { - TEGRA_PIN_GMI_WAIT_PI7, - TEGRA_PIN_GMI_ADV_N_PK0, - TEGRA_PIN_GMI_CLK_PK1, - TEGRA_PIN_GMI_CS6_N_PI3, - TEGRA_PIN_GMI_CS5_N_PI2, - TEGRA_PIN_GMI_CS4_N_PK2, - TEGRA_PIN_GMI_CS3_N_PK4, - TEGRA_PIN_GMI_CS2_N_PK3, - TEGRA_PIN_GMI_AD0_PG0, - TEGRA_PIN_GMI_AD1_PG1, - TEGRA_PIN_GMI_AD2_PG2, - TEGRA_PIN_GMI_AD3_PG3, - TEGRA_PIN_GMI_AD4_PG4, - TEGRA_PIN_GMI_AD5_PG5, - TEGRA_PIN_GMI_AD6_PG6, - TEGRA_PIN_GMI_AD7_PG7, - TEGRA_PIN_GMI_HIOW_N_PI0, - TEGRA_PIN_GMI_HIOR_N_PI1, - TEGRA_PIN_GMI_RST_N_PI4, -}; - -static const unsigned drive_cdev1_pins[] = { - TEGRA_PIN_DAP_MCLK1_PW4, -}; - -static const unsigned drive_cdev2_pins[] = { - TEGRA_PIN_DAP_MCLK2_PW5, -}; - -static const unsigned drive_csus_pins[] = { - TEGRA_PIN_VI_MCLK_PT1, -}; - -static const unsigned drive_dap1_pins[] = { - TEGRA_PIN_DAP1_FS_PN0, - TEGRA_PIN_DAP1_DIN_PN1, - TEGRA_PIN_DAP1_DOUT_PN2, - TEGRA_PIN_DAP1_SCLK_PN3, - TEGRA_PIN_SPDIF_OUT_PK5, - TEGRA_PIN_SPDIF_IN_PK6, -}; - -static const unsigned drive_dap2_pins[] = { - TEGRA_PIN_DAP2_FS_PA2, - TEGRA_PIN_DAP2_SCLK_PA3, - TEGRA_PIN_DAP2_DIN_PA4, - TEGRA_PIN_DAP2_DOUT_PA5, -}; - -static const unsigned drive_dap3_pins[] = { - TEGRA_PIN_DAP3_FS_PP0, - TEGRA_PIN_DAP3_DIN_PP1, - TEGRA_PIN_DAP3_DOUT_PP2, - TEGRA_PIN_DAP3_SCLK_PP3, -}; - -static const unsigned drive_dap4_pins[] = { - TEGRA_PIN_DAP4_FS_PP4, - TEGRA_PIN_DAP4_DIN_PP5, - TEGRA_PIN_DAP4_DOUT_PP6, - TEGRA_PIN_DAP4_SCLK_PP7, -}; - -static const unsigned drive_dbg_pins[] = { - TEGRA_PIN_PU0, - TEGRA_PIN_PU1, - TEGRA_PIN_PU2, - TEGRA_PIN_PU3, - TEGRA_PIN_PU4, - TEGRA_PIN_PU5, - TEGRA_PIN_PU6, - TEGRA_PIN_JTAG_RTCK_PU7, - TEGRA_PIN_GEN1_I2C_SDA_PC5, - TEGRA_PIN_GEN1_I2C_SCL_PC4, - TEGRA_PIN_JTAG_TRST_N, - TEGRA_PIN_JTAG_TDO, - TEGRA_PIN_JTAG_TMS, - TEGRA_PIN_JTAG_TCK, - TEGRA_PIN_JTAG_TDI, - TEGRA_PIN_TEST_MODE_EN, -}; - -static const unsigned drive_lcd1_pins[] = { - TEGRA_PIN_LCD_PWR1_PC1, - TEGRA_PIN_LCD_PWR2_PC6, - TEGRA_PIN_LCD_SDIN_PZ2, - TEGRA_PIN_LCD_SDOUT_PN5, - TEGRA_PIN_LCD_WR_N_PZ3, - TEGRA_PIN_LCD_CS0_N_PN4, - TEGRA_PIN_LCD_DC0_PN6, - TEGRA_PIN_LCD_SCK_PZ4, -}; - -static const unsigned drive_lcd2_pins[] = { - TEGRA_PIN_LCD_PWR0_PB2, - TEGRA_PIN_LCD_PCLK_PB3, - TEGRA_PIN_LCD_DE_PJ1, - TEGRA_PIN_LCD_HSYNC_PJ3, - TEGRA_PIN_LCD_VSYNC_PJ4, - TEGRA_PIN_LCD_D0_PE0, - TEGRA_PIN_LCD_D1_PE1, - TEGRA_PIN_LCD_D2_PE2, - TEGRA_PIN_LCD_D3_PE3, - TEGRA_PIN_LCD_D4_PE4, - TEGRA_PIN_LCD_D5_PE5, - TEGRA_PIN_LCD_D6_PE6, - TEGRA_PIN_LCD_D7_PE7, - TEGRA_PIN_LCD_D8_PF0, - TEGRA_PIN_LCD_D9_PF1, - TEGRA_PIN_LCD_D10_PF2, - TEGRA_PIN_LCD_D11_PF3, - TEGRA_PIN_LCD_D12_PF4, - TEGRA_PIN_LCD_D13_PF5, - TEGRA_PIN_LCD_D14_PF6, - TEGRA_PIN_LCD_D15_PF7, - TEGRA_PIN_LCD_D16_PM0, - TEGRA_PIN_LCD_D17_PM1, - TEGRA_PIN_LCD_D18_PM2, - TEGRA_PIN_LCD_D19_PM3, - TEGRA_PIN_LCD_D20_PM4, - TEGRA_PIN_LCD_D21_PM5, - TEGRA_PIN_LCD_D22_PM6, - TEGRA_PIN_LCD_D23_PM7, - TEGRA_PIN_LCD_CS1_N_PW0, - TEGRA_PIN_LCD_M1_PW1, - TEGRA_PIN_LCD_DC1_PV7, - TEGRA_PIN_HDMI_INT_N_PN7, -}; - -static const unsigned drive_sdmmc2_pins[] = { - TEGRA_PIN_SDIO3_DAT4_PD1, - TEGRA_PIN_SDIO3_DAT5_PD0, - TEGRA_PIN_SDIO3_DAT6_PD3, - TEGRA_PIN_SDIO3_DAT7_PD4, -}; - -static const unsigned drive_sdmmc3_pins[] = { - TEGRA_PIN_SDIO3_CLK_PA6, - TEGRA_PIN_SDIO3_CMD_PA7, - TEGRA_PIN_SDIO3_DAT0_PB7, - TEGRA_PIN_SDIO3_DAT1_PB6, - TEGRA_PIN_SDIO3_DAT2_PB5, - TEGRA_PIN_SDIO3_DAT3_PB4, - TEGRA_PIN_PV4, - TEGRA_PIN_PV5, - TEGRA_PIN_PV6, -}; - -static const unsigned drive_spi_pins[] = { - TEGRA_PIN_SPI2_MOSI_PX0, - TEGRA_PIN_SPI2_MISO_PX1, - TEGRA_PIN_SPI2_SCK_PX2, - TEGRA_PIN_SPI2_CS0_N_PX3, - TEGRA_PIN_SPI1_MOSI_PX4, - TEGRA_PIN_SPI1_SCK_PX5, - TEGRA_PIN_SPI1_CS0_N_PX6, - TEGRA_PIN_SPI1_MISO_PX7, - TEGRA_PIN_SPI2_CS1_N_PW2, - TEGRA_PIN_SPI2_CS2_N_PW3, -}; - -static const unsigned drive_uaa_pins[] = { - TEGRA_PIN_ULPI_DATA0_PO1, - TEGRA_PIN_ULPI_DATA1_PO2, - TEGRA_PIN_ULPI_DATA2_PO3, - TEGRA_PIN_ULPI_DATA3_PO4, -}; - -static const unsigned drive_uab_pins[] = { - TEGRA_PIN_ULPI_DATA4_PO5, - TEGRA_PIN_ULPI_DATA5_PO6, - TEGRA_PIN_ULPI_DATA6_PO7, - TEGRA_PIN_ULPI_DATA7_PO0, - TEGRA_PIN_PV0, - TEGRA_PIN_PV1, - TEGRA_PIN_PV2, - TEGRA_PIN_PV3, -}; - -static const unsigned drive_uart2_pins[] = { - TEGRA_PIN_UART2_TXD_PC2, - TEGRA_PIN_UART2_RXD_PC3, - TEGRA_PIN_UART2_RTS_N_PJ6, - TEGRA_PIN_UART2_CTS_N_PJ5, -}; - -static const unsigned drive_uart3_pins[] = { - TEGRA_PIN_UART3_TXD_PW6, - TEGRA_PIN_UART3_RXD_PW7, - TEGRA_PIN_UART3_RTS_N_PC0, - TEGRA_PIN_UART3_CTS_N_PA1, -}; - -static const unsigned drive_vi1_pins[] = { - TEGRA_PIN_VI_D0_PT4, - TEGRA_PIN_VI_D1_PD5, - TEGRA_PIN_VI_D2_PL0, - TEGRA_PIN_VI_D3_PL1, - TEGRA_PIN_VI_D4_PL2, - TEGRA_PIN_VI_D5_PL3, - TEGRA_PIN_VI_D6_PL4, - TEGRA_PIN_VI_D7_PL5, - TEGRA_PIN_VI_D8_PL6, - TEGRA_PIN_VI_D9_PL7, - TEGRA_PIN_VI_D10_PT2, - TEGRA_PIN_VI_D11_PT3, - TEGRA_PIN_VI_PCLK_PT0, - TEGRA_PIN_VI_VSYNC_PD6, - TEGRA_PIN_VI_HSYNC_PD7, -}; - -static const unsigned drive_vi2_pins[] = { - TEGRA_PIN_VI_GP0_PBB1, - TEGRA_PIN_CAM_I2C_SCL_PBB2, - TEGRA_PIN_CAM_I2C_SDA_PBB3, - TEGRA_PIN_VI_GP3_PBB4, - TEGRA_PIN_VI_GP4_PBB5, - TEGRA_PIN_VI_GP5_PD2, - TEGRA_PIN_VI_GP6_PA0, -}; - -static const unsigned drive_xm2a_pins[] = { - TEGRA_PIN_DDR_A0, - TEGRA_PIN_DDR_A1, - TEGRA_PIN_DDR_A2, - TEGRA_PIN_DDR_A3, - TEGRA_PIN_DDR_A4, - TEGRA_PIN_DDR_A5, - TEGRA_PIN_DDR_A6, - TEGRA_PIN_DDR_A7, - TEGRA_PIN_DDR_A8, - TEGRA_PIN_DDR_A9, - TEGRA_PIN_DDR_A10, - TEGRA_PIN_DDR_A11, - TEGRA_PIN_DDR_A12, - TEGRA_PIN_DDR_A13, - TEGRA_PIN_DDR_A14, - TEGRA_PIN_DDR_BA0, - TEGRA_PIN_DDR_BA1, - TEGRA_PIN_DDR_BA2, - TEGRA_PIN_DDR_CS0_N, - TEGRA_PIN_DDR_CS1_N, - TEGRA_PIN_DDR_ODT, - TEGRA_PIN_DDR_RAS_N, - TEGRA_PIN_DDR_CAS_N, - TEGRA_PIN_DDR_WE_N, - TEGRA_PIN_DDR_CKE0, - TEGRA_PIN_DDR_CKE1, -}; - -static const unsigned drive_xm2c_pins[] = { - TEGRA_PIN_DDR_DQS0P, - TEGRA_PIN_DDR_DQS0N, - TEGRA_PIN_DDR_DQS1P, - TEGRA_PIN_DDR_DQS1N, - TEGRA_PIN_DDR_DQS2P, - TEGRA_PIN_DDR_DQS2N, - TEGRA_PIN_DDR_DQS3P, - TEGRA_PIN_DDR_DQS3N, - TEGRA_PIN_DDR_QUSE0, - TEGRA_PIN_DDR_QUSE1, - TEGRA_PIN_DDR_QUSE2, - TEGRA_PIN_DDR_QUSE3, -}; - -static const unsigned drive_xm2d_pins[] = { - TEGRA_PIN_DDR_DQ0, - TEGRA_PIN_DDR_DQ1, - TEGRA_PIN_DDR_DQ2, - TEGRA_PIN_DDR_DQ3, - TEGRA_PIN_DDR_DQ4, - TEGRA_PIN_DDR_DQ5, - TEGRA_PIN_DDR_DQ6, - TEGRA_PIN_DDR_DQ7, - TEGRA_PIN_DDR_DQ8, - TEGRA_PIN_DDR_DQ9, - TEGRA_PIN_DDR_DQ10, - TEGRA_PIN_DDR_DQ11, - TEGRA_PIN_DDR_DQ12, - TEGRA_PIN_DDR_DQ13, - TEGRA_PIN_DDR_DQ14, - TEGRA_PIN_DDR_DQ15, - TEGRA_PIN_DDR_DQ16, - TEGRA_PIN_DDR_DQ17, - TEGRA_PIN_DDR_DQ18, - TEGRA_PIN_DDR_DQ19, - TEGRA_PIN_DDR_DQ20, - TEGRA_PIN_DDR_DQ21, - TEGRA_PIN_DDR_DQ22, - TEGRA_PIN_DDR_DQ23, - TEGRA_PIN_DDR_DQ24, - TEGRA_PIN_DDR_DQ25, - TEGRA_PIN_DDR_DQ26, - TEGRA_PIN_DDR_DQ27, - TEGRA_PIN_DDR_DQ28, - TEGRA_PIN_DDR_DQ29, - TEGRA_PIN_DDR_DQ30, - TEGRA_PIN_DDR_DQ31, - TEGRA_PIN_DDR_DM0, - TEGRA_PIN_DDR_DM1, - TEGRA_PIN_DDR_DM2, - TEGRA_PIN_DDR_DM3, -}; - -static const unsigned drive_xm2clk_pins[] = { - TEGRA_PIN_DDR_CLK, - TEGRA_PIN_DDR_CLK_N, -}; - -static const unsigned drive_sdio1_pins[] = { - TEGRA_PIN_SDIO1_CLK_PZ0, - TEGRA_PIN_SDIO1_CMD_PZ1, - TEGRA_PIN_SDIO1_DAT0_PY7, - TEGRA_PIN_SDIO1_DAT1_PY6, - TEGRA_PIN_SDIO1_DAT2_PY5, - TEGRA_PIN_SDIO1_DAT3_PY4, -}; - -static const unsigned drive_crt_pins[] = { - TEGRA_PIN_CRT_HSYNC, - TEGRA_PIN_CRT_VSYNC, -}; - -static const unsigned drive_ddc_pins[] = { - TEGRA_PIN_DDC_SCL, - TEGRA_PIN_DDC_SDA, -}; - -static const unsigned drive_gma_pins[] = { - TEGRA_PIN_GMI_AD20_PAA0, - TEGRA_PIN_GMI_AD21_PAA1, - TEGRA_PIN_GMI_AD22_PAA2, - TEGRA_PIN_GMI_AD23_PAA3, -}; - -static const unsigned drive_gmb_pins[] = { - TEGRA_PIN_GMI_WP_N_PC7, -}; - -static const unsigned drive_gmc_pins[] = { - TEGRA_PIN_GMI_AD16_PJ7, - TEGRA_PIN_GMI_AD17_PB0, - TEGRA_PIN_GMI_AD18_PB1, - TEGRA_PIN_GMI_AD19_PK7, -}; - -static const unsigned drive_gmd_pins[] = { - TEGRA_PIN_GMI_CS0_N_PJ0, - TEGRA_PIN_GMI_CS1_N_PJ2, -}; - -static const unsigned drive_gme_pins[] = { - TEGRA_PIN_GMI_AD24_PAA4, - TEGRA_PIN_GMI_AD25_PAA5, - TEGRA_PIN_GMI_AD26_PAA6, - TEGRA_PIN_GMI_AD27_PAA7, -}; - -static const unsigned drive_owr_pins[] = { - TEGRA_PIN_OWC, -}; - -static const unsigned drive_uda_pins[] = { - TEGRA_PIN_ULPI_CLK_PY0, - TEGRA_PIN_ULPI_DIR_PY1, - TEGRA_PIN_ULPI_NXT_PY2, - TEGRA_PIN_ULPI_STP_PY3, -}; - -enum tegra_mux { - TEGRA_MUX_AHB_CLK, - TEGRA_MUX_APB_CLK, - TEGRA_MUX_AUDIO_SYNC, - TEGRA_MUX_CRT, - TEGRA_MUX_DAP1, - TEGRA_MUX_DAP2, - TEGRA_MUX_DAP3, - TEGRA_MUX_DAP4, - TEGRA_MUX_DAP5, - TEGRA_MUX_DISPLAYA, - TEGRA_MUX_DISPLAYB, - TEGRA_MUX_EMC_TEST0_DLL, - TEGRA_MUX_EMC_TEST1_DLL, - TEGRA_MUX_GMI, - TEGRA_MUX_GMI_INT, - TEGRA_MUX_HDMI, - TEGRA_MUX_I2CP, - TEGRA_MUX_I2C1, - TEGRA_MUX_I2C2, - TEGRA_MUX_I2C3, - TEGRA_MUX_IDE, - TEGRA_MUX_IRDA, - TEGRA_MUX_KBC, - TEGRA_MUX_MIO, - TEGRA_MUX_MIPI_HS, - TEGRA_MUX_NAND, - TEGRA_MUX_OSC, - TEGRA_MUX_OWR, - TEGRA_MUX_PCIE, - TEGRA_MUX_PLLA_OUT, - TEGRA_MUX_PLLC_OUT1, - TEGRA_MUX_PLLM_OUT1, - TEGRA_MUX_PLLP_OUT2, - TEGRA_MUX_PLLP_OUT3, - TEGRA_MUX_PLLP_OUT4, - TEGRA_MUX_PWM, - TEGRA_MUX_PWR_INTR, - TEGRA_MUX_PWR_ON, - TEGRA_MUX_RSVD1, - TEGRA_MUX_RSVD2, - TEGRA_MUX_RSVD3, - TEGRA_MUX_RSVD4, - TEGRA_MUX_RTCK, - TEGRA_MUX_SDIO1, - TEGRA_MUX_SDIO2, - TEGRA_MUX_SDIO3, - TEGRA_MUX_SDIO4, - TEGRA_MUX_SFLASH, - TEGRA_MUX_SPDIF, - TEGRA_MUX_SPI1, - TEGRA_MUX_SPI2, - TEGRA_MUX_SPI2_ALT, - TEGRA_MUX_SPI3, - TEGRA_MUX_SPI4, - TEGRA_MUX_TRACE, - TEGRA_MUX_TWC, - TEGRA_MUX_UARTA, - TEGRA_MUX_UARTB, - TEGRA_MUX_UARTC, - TEGRA_MUX_UARTD, - TEGRA_MUX_UARTE, - TEGRA_MUX_ULPI, - TEGRA_MUX_VI, - TEGRA_MUX_VI_SENSOR_CLK, - TEGRA_MUX_XIO, -}; - -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } - -static struct tegra_function tegra20_functions[] = { - FUNCTION(ahb_clk), - FUNCTION(apb_clk), - FUNCTION(audio_sync), - FUNCTION(crt), - FUNCTION(dap1), - FUNCTION(dap2), - FUNCTION(dap3), - FUNCTION(dap4), - FUNCTION(dap5), - FUNCTION(displaya), - FUNCTION(displayb), - FUNCTION(emc_test0_dll), - FUNCTION(emc_test1_dll), - FUNCTION(gmi), - FUNCTION(gmi_int), - FUNCTION(hdmi), - FUNCTION(i2cp), - FUNCTION(i2c1), - FUNCTION(i2c2), - FUNCTION(i2c3), - FUNCTION(ide), - FUNCTION(irda), - FUNCTION(kbc), - FUNCTION(mio), - FUNCTION(mipi_hs), - FUNCTION(nand), - FUNCTION(osc), - FUNCTION(owr), - FUNCTION(pcie), - FUNCTION(plla_out), - FUNCTION(pllc_out1), - FUNCTION(pllm_out1), - FUNCTION(pllp_out2), - FUNCTION(pllp_out3), - FUNCTION(pllp_out4), - FUNCTION(pwm), - FUNCTION(pwr_intr), - FUNCTION(pwr_on), - FUNCTION(rsvd1), - FUNCTION(rsvd2), - FUNCTION(rsvd3), - FUNCTION(rsvd4), - FUNCTION(rtck), - FUNCTION(sdio1), - FUNCTION(sdio2), - FUNCTION(sdio3), - FUNCTION(sdio4), - FUNCTION(sflash), - FUNCTION(spdif), - FUNCTION(spi1), - FUNCTION(spi2), - FUNCTION(spi2_alt), - FUNCTION(spi3), - FUNCTION(spi4), - FUNCTION(trace), - FUNCTION(twc), - FUNCTION(uarta), - FUNCTION(uartb), - FUNCTION(uartc), - FUNCTION(uartd), - FUNCTION(uarte), - FUNCTION(ulpi), - FUNCTION(vi), - FUNCTION(vi_sensor_clk), - FUNCTION(xio), -}; - -#define TRISTATE_REG_A 0x14 -#define PIN_MUX_CTL_REG_A 0x80 -#define PULLUPDOWN_REG_A 0xa0 -#define PINGROUP_REG_A 0x868 - -/* Pin group with mux control, and typically tri-state and pull-up/down too */ -#define MUX_PG(pg_name, f0, f1, f2, f3, \ - tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b) \ - { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ - .funcs = { \ - TEGRA_MUX_ ## f0, \ - TEGRA_MUX_ ## f1, \ - TEGRA_MUX_ ## f2, \ - TEGRA_MUX_ ## f3, \ - }, \ - .mux_reg = ((mux_r) - PIN_MUX_CTL_REG_A), \ - .mux_bank = 1, \ - .mux_bit = mux_b, \ - .pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A), \ - .pupd_bank = 2, \ - .pupd_bit = pupd_b, \ - .tri_reg = ((tri_r) - TRISTATE_REG_A), \ - .tri_bank = 0, \ - .tri_bit = tri_b, \ - .einput_bit = -1, \ - .odrain_bit = -1, \ - .lock_bit = -1, \ - .ioreset_bit = -1, \ - .rcv_sel_bit = -1, \ - .drv_reg = -1, \ - } - -/* Pin groups with only pull up and pull down control */ -#define PULL_PG(pg_name, pupd_r, pupd_b) \ - { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ - .mux_reg = -1, \ - .pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A), \ - .pupd_bank = 2, \ - .pupd_bit = pupd_b, \ - .drv_reg = -1, \ - } - -/* Pin groups for drive strength registers (configurable version) */ -#define DRV_PG_EXT(pg_name, r, hsm_b, schmitt_b, lpmd_b, \ - drvdn_b, drvup_b, \ - slwr_b, slwr_w, slwf_b, slwf_w) \ - { \ - .name = "drive_" #pg_name, \ - .pins = drive_##pg_name##_pins, \ - .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ - .mux_reg = -1, \ - .pupd_reg = -1, \ - .tri_reg = -1, \ - .drv_reg = ((r) - PINGROUP_REG_A), \ - .drv_bank = 3, \ - .hsm_bit = hsm_b, \ - .schmitt_bit = schmitt_b, \ - .lpmd_bit = lpmd_b, \ - .drvdn_bit = drvdn_b, \ - .drvdn_width = 5, \ - .drvup_bit = drvup_b, \ - .drvup_width = 5, \ - .slwr_bit = slwr_b, \ - .slwr_width = slwr_w, \ - .slwf_bit = slwf_b, \ - .slwf_width = slwf_w, \ - .drvtype_bit = -1, \ - } - -/* Pin groups for drive strength registers (simple version) */ -#define DRV_PG(pg_name, r) \ - DRV_PG_EXT(pg_name, r, 2, 3, 4, 12, 20, 28, 2, 30, 2) - -static const struct tegra_pingroup tegra20_groups[] = { - /* name, f0, f1, f2, f3, tri r/b, mux r/b, pupd r/b */ - MUX_PG(ata, IDE, NAND, GMI, RSVD4, 0x14, 0, 0x80, 24, 0xa0, 0), - MUX_PG(atb, IDE, NAND, GMI, SDIO4, 0x14, 1, 0x80, 16, 0xa0, 2), - MUX_PG(atc, IDE, NAND, GMI, SDIO4, 0x14, 2, 0x80, 22, 0xa0, 4), - MUX_PG(atd, IDE, NAND, GMI, SDIO4, 0x14, 3, 0x80, 20, 0xa0, 6), - MUX_PG(ate, IDE, NAND, GMI, RSVD4, 0x18, 25, 0x80, 12, 0xa0, 8), - MUX_PG(cdev1, OSC, PLLA_OUT, PLLM_OUT1, AUDIO_SYNC, 0x14, 4, 0x88, 2, 0xa8, 0), - MUX_PG(cdev2, OSC, AHB_CLK, APB_CLK, PLLP_OUT4, 0x14, 5, 0x88, 4, 0xa8, 2), - MUX_PG(crtp, CRT, RSVD2, RSVD3, RSVD4, 0x20, 14, 0x98, 20, 0xa4, 24), - MUX_PG(csus, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, 0x14, 6, 0x88, 6, 0xac, 24), - MUX_PG(dap1, DAP1, RSVD2, GMI, SDIO2, 0x14, 7, 0x88, 20, 0xa0, 10), - MUX_PG(dap2, DAP2, TWC, RSVD3, GMI, 0x14, 8, 0x88, 22, 0xa0, 12), - MUX_PG(dap3, DAP3, RSVD2, RSVD3, RSVD4, 0x14, 9, 0x88, 24, 0xa0, 14), - MUX_PG(dap4, DAP4, RSVD2, GMI, RSVD4, 0x14, 10, 0x88, 26, 0xa0, 16), - MUX_PG(ddc, I2C2, RSVD2, RSVD3, RSVD4, 0x18, 31, 0x88, 0, 0xb0, 28), - MUX_PG(dta, RSVD1, SDIO2, VI, RSVD4, 0x14, 11, 0x84, 20, 0xa0, 18), - MUX_PG(dtb, RSVD1, RSVD2, VI, SPI1, 0x14, 12, 0x84, 22, 0xa0, 20), - MUX_PG(dtc, RSVD1, RSVD2, VI, RSVD4, 0x14, 13, 0x84, 26, 0xa0, 22), - MUX_PG(dtd, RSVD1, SDIO2, VI, RSVD4, 0x14, 14, 0x84, 28, 0xa0, 24), - MUX_PG(dte, RSVD1, RSVD2, VI, SPI1, 0x14, 15, 0x84, 30, 0xa0, 26), - MUX_PG(dtf, I2C3, RSVD2, VI, RSVD4, 0x20, 12, 0x98, 30, 0xa0, 28), - MUX_PG(gma, UARTE, SPI3, GMI, SDIO4, 0x14, 28, 0x84, 0, 0xb0, 20), - MUX_PG(gmb, IDE, NAND, GMI, GMI_INT, 0x18, 29, 0x88, 28, 0xb0, 22), - MUX_PG(gmc, UARTD, SPI4, GMI, SFLASH, 0x14, 29, 0x84, 2, 0xb0, 24), - MUX_PG(gmd, RSVD1, NAND, GMI, SFLASH, 0x18, 30, 0x88, 30, 0xb0, 26), - MUX_PG(gme, RSVD1, DAP5, GMI, SDIO4, 0x18, 0, 0x8c, 0, 0xa8, 24), - MUX_PG(gpu, PWM, UARTA, GMI, RSVD4, 0x14, 16, 0x8c, 4, 0xa4, 20), - MUX_PG(gpu7, RTCK, RSVD2, RSVD3, RSVD4, 0x20, 11, 0x98, 28, 0xa4, 6), - MUX_PG(gpv, PCIE, RSVD2, RSVD3, RSVD4, 0x14, 17, 0x8c, 2, 0xa0, 30), - MUX_PG(hdint, HDMI, RSVD2, RSVD3, RSVD4, 0x1c, 23, 0x84, 4, -1, -1), - MUX_PG(i2cp, I2CP, RSVD2, RSVD3, RSVD4, 0x14, 18, 0x88, 8, 0xa4, 2), - MUX_PG(irrx, UARTA, UARTB, GMI, SPI4, 0x14, 20, 0x88, 18, 0xa8, 22), - MUX_PG(irtx, UARTA, UARTB, GMI, SPI4, 0x14, 19, 0x88, 16, 0xa8, 20), - MUX_PG(kbca, KBC, NAND, SDIO2, EMC_TEST0_DLL, 0x14, 22, 0x88, 10, 0xa4, 8), - MUX_PG(kbcb, KBC, NAND, SDIO2, MIO, 0x14, 21, 0x88, 12, 0xa4, 10), - MUX_PG(kbcc, KBC, NAND, TRACE, EMC_TEST1_DLL, 0x18, 26, 0x88, 14, 0xa4, 12), - MUX_PG(kbcd, KBC, NAND, SDIO2, MIO, 0x20, 10, 0x98, 26, 0xa4, 14), - MUX_PG(kbce, KBC, NAND, OWR, RSVD4, 0x14, 26, 0x80, 28, 0xb0, 2), - MUX_PG(kbcf, KBC, NAND, TRACE, MIO, 0x14, 27, 0x80, 26, 0xb0, 0), - MUX_PG(lcsn, DISPLAYA, DISPLAYB, SPI3, RSVD4, 0x1c, 31, 0x90, 12, -1, -1), - MUX_PG(ld0, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 0, 0x94, 0, -1, -1), - MUX_PG(ld1, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 1, 0x94, 2, -1, -1), - MUX_PG(ld2, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 2, 0x94, 4, -1, -1), - MUX_PG(ld3, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 3, 0x94, 6, -1, -1), - MUX_PG(ld4, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 4, 0x94, 8, -1, -1), - MUX_PG(ld5, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 5, 0x94, 10, -1, -1), - MUX_PG(ld6, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 6, 0x94, 12, -1, -1), - MUX_PG(ld7, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 7, 0x94, 14, -1, -1), - MUX_PG(ld8, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 8, 0x94, 16, -1, -1), - MUX_PG(ld9, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 9, 0x94, 18, -1, -1), - MUX_PG(ld10, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 10, 0x94, 20, -1, -1), - MUX_PG(ld11, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 11, 0x94, 22, -1, -1), - MUX_PG(ld12, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 12, 0x94, 24, -1, -1), - MUX_PG(ld13, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 13, 0x94, 26, -1, -1), - MUX_PG(ld14, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 14, 0x94, 28, -1, -1), - MUX_PG(ld15, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 15, 0x94, 30, -1, -1), - MUX_PG(ld16, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 16, 0x98, 0, -1, -1), - MUX_PG(ld17, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 17, 0x98, 2, -1, -1), - MUX_PG(ldc, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 30, 0x90, 14, -1, -1), - MUX_PG(ldi, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x20, 6, 0x98, 16, -1, -1), - MUX_PG(lhp0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 18, 0x98, 10, -1, -1), - MUX_PG(lhp1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 19, 0x98, 4, -1, -1), - MUX_PG(lhp2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 20, 0x98, 6, -1, -1), - MUX_PG(lhs, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x20, 7, 0x90, 22, -1, -1), - MUX_PG(lm0, DISPLAYA, DISPLAYB, SPI3, RSVD4, 0x1c, 24, 0x90, 26, -1, -1), - MUX_PG(lm1, DISPLAYA, DISPLAYB, RSVD3, CRT, 0x1c, 25, 0x90, 28, -1, -1), - MUX_PG(lpp, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x20, 8, 0x98, 14, -1, -1), - MUX_PG(lpw0, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x20, 3, 0x90, 0, -1, -1), - MUX_PG(lpw1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x20, 4, 0x90, 2, -1, -1), - MUX_PG(lpw2, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x20, 5, 0x90, 4, -1, -1), - MUX_PG(lsc0, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 27, 0x90, 18, -1, -1), - MUX_PG(lsc1, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x1c, 28, 0x90, 20, -1, -1), - MUX_PG(lsck, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x1c, 29, 0x90, 16, -1, -1), - MUX_PG(lsda, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x20, 1, 0x90, 8, -1, -1), - MUX_PG(lsdi, DISPLAYA, DISPLAYB, SPI3, RSVD4, 0x20, 2, 0x90, 6, -1, -1), - MUX_PG(lspi, DISPLAYA, DISPLAYB, XIO, HDMI, 0x20, 0, 0x90, 10, -1, -1), - MUX_PG(lvp0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 21, 0x90, 30, -1, -1), - MUX_PG(lvp1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 22, 0x98, 8, -1, -1), - MUX_PG(lvs, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 26, 0x90, 24, -1, -1), - MUX_PG(owc, OWR, RSVD2, RSVD3, RSVD4, 0x14, 31, 0x84, 8, 0xb0, 30), - MUX_PG(pmc, PWR_ON, PWR_INTR, RSVD3, RSVD4, 0x14, 23, 0x98, 18, -1, -1), - MUX_PG(pta, I2C2, HDMI, GMI, RSVD4, 0x14, 24, 0x98, 22, 0xa4, 4), - MUX_PG(rm, I2C1, RSVD2, RSVD3, RSVD4, 0x14, 25, 0x80, 14, 0xa4, 0), - MUX_PG(sdb, UARTA, PWM, SDIO3, SPI2, 0x20, 15, 0x8c, 10, -1, -1), - MUX_PG(sdc, PWM, TWC, SDIO3, SPI3, 0x18, 1, 0x8c, 12, 0xac, 28), - MUX_PG(sdd, UARTA, PWM, SDIO3, SPI3, 0x18, 2, 0x8c, 14, 0xac, 30), - MUX_PG(sdio1, SDIO1, RSVD2, UARTE, UARTA, 0x14, 30, 0x80, 30, 0xb0, 18), - MUX_PG(slxa, PCIE, SPI4, SDIO3, SPI2, 0x18, 3, 0x84, 6, 0xa4, 22), - MUX_PG(slxc, SPDIF, SPI4, SDIO3, SPI2, 0x18, 5, 0x84, 10, 0xa4, 26), - MUX_PG(slxd, SPDIF, SPI4, SDIO3, SPI2, 0x18, 6, 0x84, 12, 0xa4, 28), - MUX_PG(slxk, PCIE, SPI4, SDIO3, SPI2, 0x18, 7, 0x84, 14, 0xa4, 30), - MUX_PG(spdi, SPDIF, RSVD2, I2C1, SDIO2, 0x18, 8, 0x8c, 8, 0xa4, 16), - MUX_PG(spdo, SPDIF, RSVD2, I2C1, SDIO2, 0x18, 9, 0x8c, 6, 0xa4, 18), - MUX_PG(spia, SPI1, SPI2, SPI3, GMI, 0x18, 10, 0x8c, 30, 0xa8, 4), - MUX_PG(spib, SPI1, SPI2, SPI3, GMI, 0x18, 11, 0x8c, 28, 0xa8, 6), - MUX_PG(spic, SPI1, SPI2, SPI3, GMI, 0x18, 12, 0x8c, 26, 0xa8, 8), - MUX_PG(spid, SPI2, SPI1, SPI2_ALT, GMI, 0x18, 13, 0x8c, 24, 0xa8, 10), - MUX_PG(spie, SPI2, SPI1, SPI2_ALT, GMI, 0x18, 14, 0x8c, 22, 0xa8, 12), - MUX_PG(spif, SPI3, SPI1, SPI2, RSVD4, 0x18, 15, 0x8c, 20, 0xa8, 14), - MUX_PG(spig, SPI3, SPI2, SPI2_ALT, I2C1, 0x18, 16, 0x8c, 18, 0xa8, 16), - MUX_PG(spih, SPI3, SPI2, SPI2_ALT, I2C1, 0x18, 17, 0x8c, 16, 0xa8, 18), - MUX_PG(uaa, SPI3, MIPI_HS, UARTA, ULPI, 0x18, 18, 0x80, 0, 0xac, 0), - MUX_PG(uab, SPI2, MIPI_HS, UARTA, ULPI, 0x18, 19, 0x80, 2, 0xac, 2), - MUX_PG(uac, OWR, RSVD2, RSVD3, RSVD4, 0x18, 20, 0x80, 4, 0xac, 4), - MUX_PG(uad, IRDA, SPDIF, UARTA, SPI4, 0x18, 21, 0x80, 6, 0xac, 6), - MUX_PG(uca, UARTC, RSVD2, GMI, RSVD4, 0x18, 22, 0x84, 16, 0xac, 8), - MUX_PG(ucb, UARTC, PWM, GMI, RSVD4, 0x18, 23, 0x84, 18, 0xac, 10), - MUX_PG(uda, SPI1, RSVD2, UARTD, ULPI, 0x20, 13, 0x80, 8, 0xb0, 16), - /* pg_name, pupd_r/b */ - PULL_PG(ck32, 0xb0, 14), - PULL_PG(ddrc, 0xac, 26), - PULL_PG(pmca, 0xb0, 4), - PULL_PG(pmcb, 0xb0, 6), - PULL_PG(pmcc, 0xb0, 8), - PULL_PG(pmcd, 0xb0, 10), - PULL_PG(pmce, 0xb0, 12), - PULL_PG(xm2c, 0xa8, 30), - PULL_PG(xm2d, 0xa8, 28), - PULL_PG(ls, 0xac, 20), - PULL_PG(lc, 0xac, 22), - PULL_PG(ld17_0, 0xac, 12), - PULL_PG(ld19_18, 0xac, 14), - PULL_PG(ld21_20, 0xac, 16), - PULL_PG(ld23_22, 0xac, 18), - /* pg_name, r */ - DRV_PG(ao1, 0x868), - DRV_PG(ao2, 0x86c), - DRV_PG(at1, 0x870), - DRV_PG(at2, 0x874), - DRV_PG(cdev1, 0x878), - DRV_PG(cdev2, 0x87c), - DRV_PG(csus, 0x880), - DRV_PG(dap1, 0x884), - DRV_PG(dap2, 0x888), - DRV_PG(dap3, 0x88c), - DRV_PG(dap4, 0x890), - DRV_PG(dbg, 0x894), - DRV_PG(lcd1, 0x898), - DRV_PG(lcd2, 0x89c), - DRV_PG(sdmmc2, 0x8a0), - DRV_PG(sdmmc3, 0x8a4), - DRV_PG(spi, 0x8a8), - DRV_PG(uaa, 0x8ac), - DRV_PG(uab, 0x8b0), - DRV_PG(uart2, 0x8b4), - DRV_PG(uart3, 0x8b8), - DRV_PG(vi1, 0x8bc), - DRV_PG(vi2, 0x8c0), - /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvup_b, slwr_b, slwr_w, slwf_b, slwf_w */ - DRV_PG_EXT(xm2a, 0x8c4, -1, -1, 4, 14, 19, 24, 4, 28, 4), - DRV_PG_EXT(xm2c, 0x8c8, -1, 3, -1, 14, 19, 24, 4, 28, 4), - DRV_PG_EXT(xm2d, 0x8cc, -1, 3, -1, 14, 19, 24, 4, 28, 4), - DRV_PG_EXT(xm2clk, 0x8d0, -1, -1, -1, 14, 19, 24, 4, 28, 4), - /* pg_name, r */ - DRV_PG(sdio1, 0x8e0), - DRV_PG(crt, 0x8ec), - DRV_PG(ddc, 0x8f0), - DRV_PG(gma, 0x8f4), - DRV_PG(gmb, 0x8f8), - DRV_PG(gmc, 0x8fc), - DRV_PG(gmd, 0x900), - DRV_PG(gme, 0x904), - DRV_PG(owr, 0x908), - DRV_PG(uda, 0x90c), -}; - -static const struct tegra_pinctrl_soc_data tegra20_pinctrl = { - .ngpios = NUM_GPIOS, - .pins = tegra20_pins, - .npins = ARRAY_SIZE(tegra20_pins), - .functions = tegra20_functions, - .nfunctions = ARRAY_SIZE(tegra20_functions), - .groups = tegra20_groups, - .ngroups = ARRAY_SIZE(tegra20_groups), - .hsm_in_mux = false, - .schmitt_in_mux = false, - .drvtype_in_mux = false, -}; - -static int tegra20_pinctrl_probe(struct platform_device *pdev) -{ - return tegra_pinctrl_probe(pdev, &tegra20_pinctrl); -} - -static const struct of_device_id tegra20_pinctrl_of_match[] = { - { .compatible = "nvidia,tegra20-pinmux", }, - { }, -}; - -static struct platform_driver tegra20_pinctrl_driver = { - .driver = { - .name = "tegra20-pinctrl", - .of_match_table = tegra20_pinctrl_of_match, - }, - .probe = tegra20_pinctrl_probe, - .remove = tegra_pinctrl_remove, -}; -module_platform_driver(tegra20_pinctrl_driver); - -MODULE_AUTHOR("Stephen Warren "); -MODULE_DESCRIPTION("NVIDIA Tegra20 pinctrl driver"); -MODULE_LICENSE("GPL v2"); -MODULE_DEVICE_TABLE(of, tegra20_pinctrl_of_match); diff --git a/drivers/pinctrl/pinctrl-tegra210.c b/drivers/pinctrl/pinctrl-tegra210.c deleted file mode 100644 index 252b464901c0..000000000000 --- a/drivers/pinctrl/pinctrl-tegra210.c +++ /dev/null @@ -1,1588 +0,0 @@ -/* - * Pinctrl data for the NVIDIA Tegra210 pinmux - * - * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - */ - -#include -#include -#include -#include -#include - -#include "pinctrl-tegra.h" - -/* - * Most pins affected by the pinmux can also be GPIOs. Define these first. - * These must match how the GPIO driver names/numbers its pins. - */ -#define _GPIO(offset) (offset) - -#define TEGRA_PIN_PEX_L0_RST_N_PA0 _GPIO(0) -#define TEGRA_PIN_PEX_L0_CLKREQ_N_PA1 _GPIO(1) -#define TEGRA_PIN_PEX_WAKE_N_PA2 _GPIO(2) -#define TEGRA_PIN_PEX_L1_RST_N_PA3 _GPIO(3) -#define TEGRA_PIN_PEX_L1_CLKREQ_N_PA4 _GPIO(4) -#define TEGRA_PIN_SATA_LED_ACTIVE_PA5 _GPIO(5) -#define TEGRA_PIN_PA6 _GPIO(6) -#define TEGRA_PIN_DAP1_FS_PB0 _GPIO(8) -#define TEGRA_PIN_DAP1_DIN_PB1 _GPIO(9) -#define TEGRA_PIN_DAP1_DOUT_PB2 _GPIO(10) -#define TEGRA_PIN_DAP1_SCLK_PB3 _GPIO(11) -#define TEGRA_PIN_SPI2_MOSI_PB4 _GPIO(12) -#define TEGRA_PIN_SPI2_MISO_PB5 _GPIO(13) -#define TEGRA_PIN_SPI2_SCK_PB6 _GPIO(14) -#define TEGRA_PIN_SPI2_CS0_PB7 _GPIO(15) -#define TEGRA_PIN_SPI1_MOSI_PC0 _GPIO(16) -#define TEGRA_PIN_SPI1_MISO_PC1 _GPIO(17) -#define TEGRA_PIN_SPI1_SCK_PC2 _GPIO(18) -#define TEGRA_PIN_SPI1_CS0_PC3 _GPIO(19) -#define TEGRA_PIN_SPI1_CS1_PC4 _GPIO(20) -#define TEGRA_PIN_SPI4_SCK_PC5 _GPIO(21) -#define TEGRA_PIN_SPI4_CS0_PC6 _GPIO(22) -#define TEGRA_PIN_SPI4_MOSI_PC7 _GPIO(23) -#define TEGRA_PIN_SPI4_MISO_PD0 _GPIO(24) -#define TEGRA_PIN_UART3_TX_PD1 _GPIO(25) -#define TEGRA_PIN_UART3_RX_PD2 _GPIO(26) -#define TEGRA_PIN_UART3_RTS_PD3 _GPIO(27) -#define TEGRA_PIN_UART3_CTS_PD4 _GPIO(28) -#define TEGRA_PIN_DMIC1_CLK_PE0 _GPIO(32) -#define TEGRA_PIN_DMIC1_DAT_PE1 _GPIO(33) -#define TEGRA_PIN_DMIC2_CLK_PE2 _GPIO(34) -#define TEGRA_PIN_DMIC2_DAT_PE3 _GPIO(35) -#define TEGRA_PIN_DMIC3_CLK_PE4 _GPIO(36) -#define TEGRA_PIN_DMIC3_DAT_PE5 _GPIO(37) -#define TEGRA_PIN_PE6 _GPIO(38) -#define TEGRA_PIN_PE7 _GPIO(39) -#define TEGRA_PIN_GEN3_I2C_SCL_PF0 _GPIO(40) -#define TEGRA_PIN_GEN3_I2C_SDA_PF1 _GPIO(41) -#define TEGRA_PIN_UART2_TX_PG0 _GPIO(48) -#define TEGRA_PIN_UART2_RX_PG1 _GPIO(49) -#define TEGRA_PIN_UART2_RTS_PG2 _GPIO(50) -#define TEGRA_PIN_UART2_CTS_PG3 _GPIO(51) -#define TEGRA_PIN_WIFI_EN_PH0 _GPIO(56) -#define TEGRA_PIN_WIFI_RST_PH1 _GPIO(57) -#define TEGRA_PIN_WIFI_WAKE_AP_PH2 _GPIO(58) -#define TEGRA_PIN_AP_WAKE_BT_PH3 _GPIO(59) -#define TEGRA_PIN_BT_RST_PH4 _GPIO(60) -#define TEGRA_PIN_BT_WAKE_AP_PH5 _GPIO(61) -#define TEGRA_PIN_PH6 _GPIO(62) -#define TEGRA_PIN_AP_WAKE_NFC_PH7 _GPIO(63) -#define TEGRA_PIN_NFC_EN_PI0 _GPIO(64) -#define TEGRA_PIN_NFC_INT_PI1 _GPIO(65) -#define TEGRA_PIN_GPS_EN_PI2 _GPIO(66) -#define TEGRA_PIN_GPS_RST_PI3 _GPIO(67) -#define TEGRA_PIN_UART4_TX_PI4 _GPIO(68) -#define TEGRA_PIN_UART4_RX_PI5 _GPIO(69) -#define TEGRA_PIN_UART4_RTS_PI6 _GPIO(70) -#define TEGRA_PIN_UART4_CTS_PI7 _GPIO(71) -#define TEGRA_PIN_GEN1_I2C_SDA_PJ0 _GPIO(72) -#define TEGRA_PIN_GEN1_I2C_SCL_PJ1 _GPIO(73) -#define TEGRA_PIN_GEN2_I2C_SCL_PJ2 _GPIO(74) -#define TEGRA_PIN_GEN2_I2C_SDA_PJ3 _GPIO(75) -#define TEGRA_PIN_DAP4_FS_PJ4 _GPIO(76) -#define TEGRA_PIN_DAP4_DIN_PJ5 _GPIO(77) -#define TEGRA_PIN_DAP4_DOUT_PJ6 _GPIO(78) -#define TEGRA_PIN_DAP4_SCLK_PJ7 _GPIO(79) -#define TEGRA_PIN_PK0 _GPIO(80) -#define TEGRA_PIN_PK1 _GPIO(81) -#define TEGRA_PIN_PK2 _GPIO(82) -#define TEGRA_PIN_PK3 _GPIO(83) -#define TEGRA_PIN_PK4 _GPIO(84) -#define TEGRA_PIN_PK5 _GPIO(85) -#define TEGRA_PIN_PK6 _GPIO(86) -#define TEGRA_PIN_PK7 _GPIO(87) -#define TEGRA_PIN_PL0 _GPIO(88) -#define TEGRA_PIN_PL1 _GPIO(89) -#define TEGRA_PIN_SDMMC1_CLK_PM0 _GPIO(96) -#define TEGRA_PIN_SDMMC1_CMD_PM1 _GPIO(97) -#define TEGRA_PIN_SDMMC1_DAT3_PM2 _GPIO(98) -#define TEGRA_PIN_SDMMC1_DAT2_PM3 _GPIO(99) -#define TEGRA_PIN_SDMMC1_DAT1_PM4 _GPIO(100) -#define TEGRA_PIN_SDMMC1_DAT0_PM5 _GPIO(101) -#define TEGRA_PIN_SDMMC3_CLK_PP0 _GPIO(120) -#define TEGRA_PIN_SDMMC3_CMD_PP1 _GPIO(121) -#define TEGRA_PIN_SDMMC3_DAT3_PP2 _GPIO(122) -#define TEGRA_PIN_SDMMC3_DAT2_PP3 _GPIO(123) -#define TEGRA_PIN_SDMMC3_DAT1_PP4 _GPIO(124) -#define TEGRA_PIN_SDMMC3_DAT0_PP5 _GPIO(125) -#define TEGRA_PIN_CAM1_MCLK_PS0 _GPIO(144) -#define TEGRA_PIN_CAM2_MCLK_PS1 _GPIO(145) -#define TEGRA_PIN_CAM_I2C_SCL_PS2 _GPIO(146) -#define TEGRA_PIN_CAM_I2C_SDA_PS3 _GPIO(147) -#define TEGRA_PIN_CAM_RST_PS4 _GPIO(148) -#define TEGRA_PIN_CAM_AF_EN_PS5 _GPIO(149) -#define TEGRA_PIN_CAM_FLASH_EN_PS6 _GPIO(150) -#define TEGRA_PIN_CAM1_PWDN_PS7 _GPIO(151) -#define TEGRA_PIN_CAM2_PWDN_PT0 _GPIO(152) -#define TEGRA_PIN_CAM1_STROBE_PT1 _GPIO(153) -#define TEGRA_PIN_UART1_TX_PU0 _GPIO(160) -#define TEGRA_PIN_UART1_RX_PU1 _GPIO(161) -#define TEGRA_PIN_UART1_RTS_PU2 _GPIO(162) -#define TEGRA_PIN_UART1_CTS_PU3 _GPIO(163) -#define TEGRA_PIN_LCD_BL_PWM_PV0 _GPIO(168) -#define TEGRA_PIN_LCD_BL_EN_PV1 _GPIO(169) -#define TEGRA_PIN_LCD_RST_PV2 _GPIO(170) -#define TEGRA_PIN_LCD_GPIO1_PV3 _GPIO(171) -#define TEGRA_PIN_LCD_GPIO2_PV4 _GPIO(172) -#define TEGRA_PIN_AP_READY_PV5 _GPIO(173) -#define TEGRA_PIN_TOUCH_RST_PV6 _GPIO(174) -#define TEGRA_PIN_TOUCH_CLK_PV7 _GPIO(175) -#define TEGRA_PIN_MODEM_WAKE_AP_PX0 _GPIO(184) -#define TEGRA_PIN_TOUCH_INT_PX1 _GPIO(185) -#define TEGRA_PIN_MOTION_INT_PX2 _GPIO(186) -#define TEGRA_PIN_ALS_PROX_INT_PX3 _GPIO(187) -#define TEGRA_PIN_TEMP_ALERT_PX4 _GPIO(188) -#define TEGRA_PIN_BUTTON_POWER_ON_PX5 _GPIO(189) -#define TEGRA_PIN_BUTTON_VOL_UP_PX6 _GPIO(190) -#define TEGRA_PIN_BUTTON_VOL_DOWN_PX7 _GPIO(191) -#define TEGRA_PIN_BUTTON_SLIDE_SW_PY0 _GPIO(192) -#define TEGRA_PIN_BUTTON_HOME_PY1 _GPIO(193) -#define TEGRA_PIN_LCD_TE_PY2 _GPIO(194) -#define TEGRA_PIN_PWR_I2C_SCL_PY3 _GPIO(195) -#define TEGRA_PIN_PWR_I2C_SDA_PY4 _GPIO(196) -#define TEGRA_PIN_CLK_32K_OUT_PY5 _GPIO(197) -#define TEGRA_PIN_PZ0 _GPIO(200) -#define TEGRA_PIN_PZ1 _GPIO(201) -#define TEGRA_PIN_PZ2 _GPIO(202) -#define TEGRA_PIN_PZ3 _GPIO(203) -#define TEGRA_PIN_PZ4 _GPIO(204) -#define TEGRA_PIN_PZ5 _GPIO(205) -#define TEGRA_PIN_DAP2_FS_PAA0 _GPIO(208) -#define TEGRA_PIN_DAP2_SCLK_PAA1 _GPIO(209) -#define TEGRA_PIN_DAP2_DIN_PAA2 _GPIO(210) -#define TEGRA_PIN_DAP2_DOUT_PAA3 _GPIO(211) -#define TEGRA_PIN_AUD_MCLK_PBB0 _GPIO(216) -#define TEGRA_PIN_DVFS_PWM_PBB1 _GPIO(217) -#define TEGRA_PIN_DVFS_CLK_PBB2 _GPIO(218) -#define TEGRA_PIN_GPIO_X1_AUD_PBB3 _GPIO(219) -#define TEGRA_PIN_GPIO_X3_AUD_PBB4 _GPIO(220) -#define TEGRA_PIN_HDMI_CEC_PCC0 _GPIO(224) -#define TEGRA_PIN_HDMI_INT_DP_HPD_PCC1 _GPIO(225) -#define TEGRA_PIN_SPDIF_OUT_PCC2 _GPIO(226) -#define TEGRA_PIN_SPDIF_IN_PCC3 _GPIO(227) -#define TEGRA_PIN_USB_VBUS_EN0_PCC4 _GPIO(228) -#define TEGRA_PIN_USB_VBUS_EN1_PCC5 _GPIO(229) -#define TEGRA_PIN_DP_HPD0_PCC6 _GPIO(230) -#define TEGRA_PIN_PCC7 _GPIO(231) -#define TEGRA_PIN_SPI2_CS1_PDD0 _GPIO(232) -#define TEGRA_PIN_QSPI_SCK_PEE0 _GPIO(240) -#define TEGRA_PIN_QSPI_CS_N_PEE1 _GPIO(241) -#define TEGRA_PIN_QSPI_IO0_PEE2 _GPIO(242) -#define TEGRA_PIN_QSPI_IO1_PEE3 _GPIO(243) -#define TEGRA_PIN_QSPI_IO2_PEE4 _GPIO(244) -#define TEGRA_PIN_QSPI_IO3_PEE5 _GPIO(245) - -/* All non-GPIO pins follow */ -#define NUM_GPIOS (TEGRA_PIN_QSPI_IO3_PEE5 + 1) -#define _PIN(offset) (NUM_GPIOS + (offset)) - -/* Non-GPIO pins */ -#define TEGRA_PIN_CORE_PWR_REQ _PIN(0) -#define TEGRA_PIN_CPU_PWR_REQ _PIN(1) -#define TEGRA_PIN_PWR_INT_N _PIN(2) -#define TEGRA_PIN_CLK_32K_IN _PIN(3) -#define TEGRA_PIN_JTAG_RTCK _PIN(4) -#define TEGRA_PIN_BATT_BCL _PIN(5) -#define TEGRA_PIN_CLK_REQ _PIN(6) -#define TEGRA_PIN_SHUTDOWN _PIN(7) - -static const struct pinctrl_pin_desc tegra210_pins[] = { - PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PA0, "PEX_L0_RST_N PA0"), - PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PA1, "PEX_L0_CLKREQ_N PA1"), - PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PA2, "PEX_WAKE_N PA2"), - PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PA3, "PEX_L1_RST_N PA3"), - PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PA4, "PEX_L1_CLKREQ_N PA4"), - PINCTRL_PIN(TEGRA_PIN_SATA_LED_ACTIVE_PA5, "SATA_LED_ACTIVE PA5"), - PINCTRL_PIN(TEGRA_PIN_PA6, "PA6"), - PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PB0, "DAP1_FS PB0"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PB1, "DAP1_DIN PB1"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PB2, "DAP1_DOUT PB2"), - PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PB3, "DAP1_SCLK PB3"), - PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PB4, "SPI2_MOSI PB4"), - PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PB5, "SPI2_MISO PB5"), - PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PB6, "SPI2_SCK PB6"), - PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_PB7, "SPI2_CS0 PB7"), - PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PC0, "SPI1_MOSI PC0"), - PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PC1, "SPI1_MISO PC1"), - PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PC2, "SPI1_SCK PC2"), - PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_PC3, "SPI1_CS0 PC3"), - PINCTRL_PIN(TEGRA_PIN_SPI1_CS1_PC4, "SPI1_CS1 PC4"), - PINCTRL_PIN(TEGRA_PIN_SPI4_SCK_PC5, "SPI4_SCK PC5"), - PINCTRL_PIN(TEGRA_PIN_SPI4_CS0_PC6, "SPI4_CS0 PC6"), - PINCTRL_PIN(TEGRA_PIN_SPI4_MOSI_PC7, "SPI4_MOSI PC7"), - PINCTRL_PIN(TEGRA_PIN_SPI4_MISO_PD0, "SPI4_MISO PD0"), - PINCTRL_PIN(TEGRA_PIN_UART3_TX_PD1, "UART3_TX PD1"), - PINCTRL_PIN(TEGRA_PIN_UART3_RX_PD2, "UART3_RX PD2"), - PINCTRL_PIN(TEGRA_PIN_UART3_RTS_PD3, "UART3_RTS PD3"), - PINCTRL_PIN(TEGRA_PIN_UART3_CTS_PD4, "UART3_CTS PD4"), - PINCTRL_PIN(TEGRA_PIN_DMIC1_CLK_PE0, "DMIC1_CLK PE0"), - PINCTRL_PIN(TEGRA_PIN_DMIC1_DAT_PE1, "DMIC1_DAT PE1"), - PINCTRL_PIN(TEGRA_PIN_DMIC2_CLK_PE2, "DMIC2_CLK PE2"), - PINCTRL_PIN(TEGRA_PIN_DMIC2_DAT_PE3, "DMIC2_DAT PE3"), - PINCTRL_PIN(TEGRA_PIN_DMIC3_CLK_PE4, "DMIC3_CLK PE4"), - PINCTRL_PIN(TEGRA_PIN_DMIC3_DAT_PE5, "DMIC3_DAT PE5"), - PINCTRL_PIN(TEGRA_PIN_PE6, "PE6"), - PINCTRL_PIN(TEGRA_PIN_PE7, "PE7"), - PINCTRL_PIN(TEGRA_PIN_GEN3_I2C_SCL_PF0, "GEN3_I2C_SCL PF0"), - PINCTRL_PIN(TEGRA_PIN_GEN3_I2C_SDA_PF1, "GEN3_I2C_SDA PF1"), - PINCTRL_PIN(TEGRA_PIN_UART2_TX_PG0, "UART2_TX PG0"), - PINCTRL_PIN(TEGRA_PIN_UART2_RX_PG1, "UART2_RX PG1"), - PINCTRL_PIN(TEGRA_PIN_UART2_RTS_PG2, "UART2_RTS PG2"), - PINCTRL_PIN(TEGRA_PIN_UART2_CTS_PG3, "UART2_CTS PG3"), - PINCTRL_PIN(TEGRA_PIN_WIFI_EN_PH0, "WIFI_EN PH0"), - PINCTRL_PIN(TEGRA_PIN_WIFI_RST_PH1, "WIFI_RST PH1"), - PINCTRL_PIN(TEGRA_PIN_WIFI_WAKE_AP_PH2, "WIFI_WAKE_AP PH2"), - PINCTRL_PIN(TEGRA_PIN_AP_WAKE_BT_PH3, "AP_WAKE_BT PH3"), - PINCTRL_PIN(TEGRA_PIN_BT_RST_PH4, "BT_RST PH4"), - PINCTRL_PIN(TEGRA_PIN_BT_WAKE_AP_PH5, "BT_WAKE_AP PH5"), - PINCTRL_PIN(TEGRA_PIN_PH6, "PH6"), - PINCTRL_PIN(TEGRA_PIN_AP_WAKE_NFC_PH7, "AP_WAKE_NFC PH7"), - PINCTRL_PIN(TEGRA_PIN_NFC_EN_PI0, "NFC_EN PI0"), - PINCTRL_PIN(TEGRA_PIN_NFC_INT_PI1, "NFC_INT PI1"), - PINCTRL_PIN(TEGRA_PIN_GPS_EN_PI2, "GPS_EN PI2"), - PINCTRL_PIN(TEGRA_PIN_GPS_RST_PI3, "GPS_RST PI3"), - PINCTRL_PIN(TEGRA_PIN_UART4_TX_PI4, "UART4_TX PI4"), - PINCTRL_PIN(TEGRA_PIN_UART4_RX_PI5, "UART4_RX PI5"), - PINCTRL_PIN(TEGRA_PIN_UART4_RTS_PI6, "UART4_RTS PI6"), - PINCTRL_PIN(TEGRA_PIN_UART4_CTS_PI7, "UART4_CTS PI7"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PJ0, "GEN1_I2C_SDA PJ0"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PJ1, "GEN1_I2C_SCL PJ1"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PJ2, "GEN2_I2C_SCL PJ2"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PJ3, "GEN2_I2C_SDA PJ3"), - PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PJ4, "DAP4_FS PJ4"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PJ5, "DAP4_DIN PJ5"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PJ6, "DAP4_DOUT PJ6"), - PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PJ7, "DAP4_SCLK PJ7"), - PINCTRL_PIN(TEGRA_PIN_PK0, "PK0"), - PINCTRL_PIN(TEGRA_PIN_PK1, "PK1"), - PINCTRL_PIN(TEGRA_PIN_PK2, "PK2"), - PINCTRL_PIN(TEGRA_PIN_PK3, "PK3"), - PINCTRL_PIN(TEGRA_PIN_PK4, "PK4"), - PINCTRL_PIN(TEGRA_PIN_PK5, "PK5"), - PINCTRL_PIN(TEGRA_PIN_PK6, "PK6"), - PINCTRL_PIN(TEGRA_PIN_PK7, "PK7"), - PINCTRL_PIN(TEGRA_PIN_PL0, "PL0"), - PINCTRL_PIN(TEGRA_PIN_PL1, "PL1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PM0, "SDMMC1_CLK PM0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PM1, "SDMMC1_CMD PM1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PM2, "SDMMC1_DAT3 PM2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PM3, "SDMMC1_DAT2 PM3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PM4, "SDMMC1_DAT1 PM4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PM5, "SDMMC1_DAT0 PM5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PP0, "SDMMC3_CLK PP0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PP1, "SDMMC3_CMD PP1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PP2, "SDMMC3_DAT3 PP2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PP3, "SDMMC3_DAT2 PP3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PP4, "SDMMC3_DAT1 PP4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PP5, "SDMMC3_DAT0 PP5"), - PINCTRL_PIN(TEGRA_PIN_CAM1_MCLK_PS0, "CAM1_MCLK PS0"), - PINCTRL_PIN(TEGRA_PIN_CAM2_MCLK_PS1, "CAM2_MCLK PS1"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PS2, "CAM_I2C_SCL PS2"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PS3, "CAM_I2C_SDA PS3"), - PINCTRL_PIN(TEGRA_PIN_CAM_RST_PS4, "CAM_RST PS4"), - PINCTRL_PIN(TEGRA_PIN_CAM_AF_EN_PS5, "CAM_AF_EN PS5"), - PINCTRL_PIN(TEGRA_PIN_CAM_FLASH_EN_PS6, "CAM_FLASH_EN PS6"), - PINCTRL_PIN(TEGRA_PIN_CAM1_PWDN_PS7, "CAM1_PWDN PS7"), - PINCTRL_PIN(TEGRA_PIN_CAM2_PWDN_PT0, "CAM2_PWDN PT0"), - PINCTRL_PIN(TEGRA_PIN_CAM1_STROBE_PT1, "CAM1_STROBE PT1"), - PINCTRL_PIN(TEGRA_PIN_UART1_TX_PU0, "UART1_TX PU0"), - PINCTRL_PIN(TEGRA_PIN_UART1_RX_PU1, "UART1_RX PU1"), - PINCTRL_PIN(TEGRA_PIN_UART1_RTS_PU2, "UART1_RTS PU2"), - PINCTRL_PIN(TEGRA_PIN_UART1_CTS_PU3, "UART1_CTS PU3"), - PINCTRL_PIN(TEGRA_PIN_LCD_BL_PWM_PV0, "LCD_BL_PWM PV0"), - PINCTRL_PIN(TEGRA_PIN_LCD_BL_EN_PV1, "LCD_BL_EN PV1"), - PINCTRL_PIN(TEGRA_PIN_LCD_RST_PV2, "LCD_RST PV2"), - PINCTRL_PIN(TEGRA_PIN_LCD_GPIO1_PV3, "LCD_GPIO1 PV3"), - PINCTRL_PIN(TEGRA_PIN_LCD_GPIO2_PV4, "LCD_GPIO2 PV4"), - PINCTRL_PIN(TEGRA_PIN_AP_READY_PV5, "AP_READY PV5"), - PINCTRL_PIN(TEGRA_PIN_TOUCH_RST_PV6, "TOUCH_RST PV6"), - PINCTRL_PIN(TEGRA_PIN_TOUCH_CLK_PV7, "TOUCH_CLK PV7"), - PINCTRL_PIN(TEGRA_PIN_MODEM_WAKE_AP_PX0, "MODEM_WAKE_AP PX0"), - PINCTRL_PIN(TEGRA_PIN_TOUCH_INT_PX1, "TOUCH_INT PX1"), - PINCTRL_PIN(TEGRA_PIN_MOTION_INT_PX2, "MOTION_INT PX2"), - PINCTRL_PIN(TEGRA_PIN_ALS_PROX_INT_PX3, "ALS_PROX_INT PX3"), - PINCTRL_PIN(TEGRA_PIN_TEMP_ALERT_PX4, "TEMP_ALERT PX4"), - PINCTRL_PIN(TEGRA_PIN_BUTTON_POWER_ON_PX5, "BUTTON_POWER_ON PX5"), - PINCTRL_PIN(TEGRA_PIN_BUTTON_VOL_UP_PX6, "BUTTON_VOL_UP PX6"), - PINCTRL_PIN(TEGRA_PIN_BUTTON_VOL_DOWN_PX7, "BUTTON_VOL_DOWN PX7"), - PINCTRL_PIN(TEGRA_PIN_BUTTON_SLIDE_SW_PY0, "BUTTON_SLIDE_SW PY0"), - PINCTRL_PIN(TEGRA_PIN_BUTTON_HOME_PY1, "BUTTON_HOME PY1"), - PINCTRL_PIN(TEGRA_PIN_LCD_TE_PY2, "LCD_TE PY2"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PY3, "PWR_I2C_SCL PY3"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PY4, "PWR_I2C_SDA PY4"), - PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PY5, "CLK_32K_OUT PY5"), - PINCTRL_PIN(TEGRA_PIN_PZ0, "PZ0"), - PINCTRL_PIN(TEGRA_PIN_PZ1, "PZ1"), - PINCTRL_PIN(TEGRA_PIN_PZ2, "PZ2"), - PINCTRL_PIN(TEGRA_PIN_PZ3, "PZ3"), - PINCTRL_PIN(TEGRA_PIN_PZ4, "PZ4"), - PINCTRL_PIN(TEGRA_PIN_PZ5, "PZ5"), - PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PAA0, "DAP2_FS PAA0"), - PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PAA1, "DAP2_SCLK PAA1"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PAA2, "DAP2_DIN PAA2"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PAA3, "DAP2_DOUT PAA3"), - PINCTRL_PIN(TEGRA_PIN_AUD_MCLK_PBB0, "AUD_MCLK PBB0"), - PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PBB1, "DVFS_PWM PBB1"), - PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PBB2, "DVFS_CLK PBB2"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PBB3, "GPIO_X1_AUD PBB3"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PBB4, "GPIO_X3_AUD PBB4"), - PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PCC0, "HDMI_CEC PCC0"), - PINCTRL_PIN(TEGRA_PIN_HDMI_INT_DP_HPD_PCC1, "HDMI_INT_DP_HPD PCC1"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PCC2, "SPDIF_OUT PCC2"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PCC3, "SPDIF_IN PCC3"), - PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PCC4, "USB_VBUS_EN0 PCC4"), - PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PCC5, "USB_VBUS_EN1 PCC5"), - PINCTRL_PIN(TEGRA_PIN_DP_HPD0_PCC6, "DP_HPD0 PCC6"), - PINCTRL_PIN(TEGRA_PIN_PCC7, "PCC7"), - PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_PDD0, "SPI2_CS1 PDD0"), - PINCTRL_PIN(TEGRA_PIN_QSPI_SCK_PEE0, "QSPI_SCK PEE0"), - PINCTRL_PIN(TEGRA_PIN_QSPI_CS_N_PEE1, "QSPI_CS_N PEE1"), - PINCTRL_PIN(TEGRA_PIN_QSPI_IO0_PEE2, "QSPI_IO0 PEE2"), - PINCTRL_PIN(TEGRA_PIN_QSPI_IO1_PEE3, "QSPI_IO1 PEE3"), - PINCTRL_PIN(TEGRA_PIN_QSPI_IO2_PEE4, "QSPI_IO2 PEE4"), - PINCTRL_PIN(TEGRA_PIN_QSPI_IO3_PEE5, "QSPI_IO3 PEE5"), - PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), - PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), - PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"), - PINCTRL_PIN(TEGRA_PIN_BATT_BCL, "BATT_BCL"), - PINCTRL_PIN(TEGRA_PIN_CLK_REQ, "CLK_REQ"), - PINCTRL_PIN(TEGRA_PIN_SHUTDOWN, "SHUTDOWN"), -}; - -static const unsigned pex_l0_rst_n_pa0_pins[] = { - TEGRA_PIN_PEX_L0_RST_N_PA0, -}; - -static const unsigned pex_l0_clkreq_n_pa1_pins[] = { - TEGRA_PIN_PEX_L0_CLKREQ_N_PA1, -}; - -static const unsigned pex_wake_n_pa2_pins[] = { - TEGRA_PIN_PEX_WAKE_N_PA2, -}; - -static const unsigned pex_l1_rst_n_pa3_pins[] = { - TEGRA_PIN_PEX_L1_RST_N_PA3, -}; - -static const unsigned pex_l1_clkreq_n_pa4_pins[] = { - TEGRA_PIN_PEX_L1_CLKREQ_N_PA4, -}; - -static const unsigned sata_led_active_pa5_pins[] = { - TEGRA_PIN_SATA_LED_ACTIVE_PA5, -}; - -static const unsigned pa6_pins[] = { - TEGRA_PIN_PA6, -}; - -static const unsigned dap1_fs_pb0_pins[] = { - TEGRA_PIN_DAP1_FS_PB0, -}; - -static const unsigned dap1_din_pb1_pins[] = { - TEGRA_PIN_DAP1_DIN_PB1, -}; - -static const unsigned dap1_dout_pb2_pins[] = { - TEGRA_PIN_DAP1_DOUT_PB2, -}; - -static const unsigned dap1_sclk_pb3_pins[] = { - TEGRA_PIN_DAP1_SCLK_PB3, -}; - -static const unsigned spi2_mosi_pb4_pins[] = { - TEGRA_PIN_SPI2_MOSI_PB4, -}; - -static const unsigned spi2_miso_pb5_pins[] = { - TEGRA_PIN_SPI2_MISO_PB5, -}; - -static const unsigned spi2_sck_pb6_pins[] = { - TEGRA_PIN_SPI2_SCK_PB6, -}; - -static const unsigned spi2_cs0_pb7_pins[] = { - TEGRA_PIN_SPI2_CS0_PB7, -}; - -static const unsigned spi1_mosi_pc0_pins[] = { - TEGRA_PIN_SPI1_MOSI_PC0, -}; - -static const unsigned spi1_miso_pc1_pins[] = { - TEGRA_PIN_SPI1_MISO_PC1, -}; - -static const unsigned spi1_sck_pc2_pins[] = { - TEGRA_PIN_SPI1_SCK_PC2, -}; - -static const unsigned spi1_cs0_pc3_pins[] = { - TEGRA_PIN_SPI1_CS0_PC3, -}; - -static const unsigned spi1_cs1_pc4_pins[] = { - TEGRA_PIN_SPI1_CS1_PC4, -}; - -static const unsigned spi4_sck_pc5_pins[] = { - TEGRA_PIN_SPI4_SCK_PC5, -}; - -static const unsigned spi4_cs0_pc6_pins[] = { - TEGRA_PIN_SPI4_CS0_PC6, -}; - -static const unsigned spi4_mosi_pc7_pins[] = { - TEGRA_PIN_SPI4_MOSI_PC7, -}; - -static const unsigned spi4_miso_pd0_pins[] = { - TEGRA_PIN_SPI4_MISO_PD0, -}; - -static const unsigned uart3_tx_pd1_pins[] = { - TEGRA_PIN_UART3_TX_PD1, -}; - -static const unsigned uart3_rx_pd2_pins[] = { - TEGRA_PIN_UART3_RX_PD2, -}; - -static const unsigned uart3_rts_pd3_pins[] = { - TEGRA_PIN_UART3_RTS_PD3, -}; - -static const unsigned uart3_cts_pd4_pins[] = { - TEGRA_PIN_UART3_CTS_PD4, -}; - -static const unsigned dmic1_clk_pe0_pins[] = { - TEGRA_PIN_DMIC1_CLK_PE0, -}; - -static const unsigned dmic1_dat_pe1_pins[] = { - TEGRA_PIN_DMIC1_DAT_PE1, -}; - -static const unsigned dmic2_clk_pe2_pins[] = { - TEGRA_PIN_DMIC2_CLK_PE2, -}; - -static const unsigned dmic2_dat_pe3_pins[] = { - TEGRA_PIN_DMIC2_DAT_PE3, -}; - -static const unsigned dmic3_clk_pe4_pins[] = { - TEGRA_PIN_DMIC3_CLK_PE4, -}; - -static const unsigned dmic3_dat_pe5_pins[] = { - TEGRA_PIN_DMIC3_DAT_PE5, -}; - -static const unsigned pe6_pins[] = { - TEGRA_PIN_PE6, -}; - -static const unsigned pe7_pins[] = { - TEGRA_PIN_PE7, -}; - -static const unsigned gen3_i2c_scl_pf0_pins[] = { - TEGRA_PIN_GEN3_I2C_SCL_PF0, -}; - -static const unsigned gen3_i2c_sda_pf1_pins[] = { - TEGRA_PIN_GEN3_I2C_SDA_PF1, -}; - -static const unsigned uart2_tx_pg0_pins[] = { - TEGRA_PIN_UART2_TX_PG0, -}; - -static const unsigned uart2_rx_pg1_pins[] = { - TEGRA_PIN_UART2_RX_PG1, -}; - -static const unsigned uart2_rts_pg2_pins[] = { - TEGRA_PIN_UART2_RTS_PG2, -}; - -static const unsigned uart2_cts_pg3_pins[] = { - TEGRA_PIN_UART2_CTS_PG3, -}; - -static const unsigned wifi_en_ph0_pins[] = { - TEGRA_PIN_WIFI_EN_PH0, -}; - -static const unsigned wifi_rst_ph1_pins[] = { - TEGRA_PIN_WIFI_RST_PH1, -}; - -static const unsigned wifi_wake_ap_ph2_pins[] = { - TEGRA_PIN_WIFI_WAKE_AP_PH2, -}; - -static const unsigned ap_wake_bt_ph3_pins[] = { - TEGRA_PIN_AP_WAKE_BT_PH3, -}; - -static const unsigned bt_rst_ph4_pins[] = { - TEGRA_PIN_BT_RST_PH4, -}; - -static const unsigned bt_wake_ap_ph5_pins[] = { - TEGRA_PIN_BT_WAKE_AP_PH5, -}; - -static const unsigned ph6_pins[] = { - TEGRA_PIN_PH6, -}; - -static const unsigned ap_wake_nfc_ph7_pins[] = { - TEGRA_PIN_AP_WAKE_NFC_PH7, -}; - -static const unsigned nfc_en_pi0_pins[] = { - TEGRA_PIN_NFC_EN_PI0, -}; - -static const unsigned nfc_int_pi1_pins[] = { - TEGRA_PIN_NFC_INT_PI1, -}; - -static const unsigned gps_en_pi2_pins[] = { - TEGRA_PIN_GPS_EN_PI2, -}; - -static const unsigned gps_rst_pi3_pins[] = { - TEGRA_PIN_GPS_RST_PI3, -}; - -static const unsigned uart4_tx_pi4_pins[] = { - TEGRA_PIN_UART4_TX_PI4, -}; - -static const unsigned uart4_rx_pi5_pins[] = { - TEGRA_PIN_UART4_RX_PI5, -}; - -static const unsigned uart4_rts_pi6_pins[] = { - TEGRA_PIN_UART4_RTS_PI6, -}; - -static const unsigned uart4_cts_pi7_pins[] = { - TEGRA_PIN_UART4_CTS_PI7, -}; - -static const unsigned gen1_i2c_sda_pj0_pins[] = { - TEGRA_PIN_GEN1_I2C_SDA_PJ0, -}; - -static const unsigned gen1_i2c_scl_pj1_pins[] = { - TEGRA_PIN_GEN1_I2C_SCL_PJ1, -}; - -static const unsigned gen2_i2c_scl_pj2_pins[] = { - TEGRA_PIN_GEN2_I2C_SCL_PJ2, -}; - -static const unsigned gen2_i2c_sda_pj3_pins[] = { - TEGRA_PIN_GEN2_I2C_SDA_PJ3, -}; - -static const unsigned dap4_fs_pj4_pins[] = { - TEGRA_PIN_DAP4_FS_PJ4, -}; - -static const unsigned dap4_din_pj5_pins[] = { - TEGRA_PIN_DAP4_DIN_PJ5, -}; - -static const unsigned dap4_dout_pj6_pins[] = { - TEGRA_PIN_DAP4_DOUT_PJ6, -}; - -static const unsigned dap4_sclk_pj7_pins[] = { - TEGRA_PIN_DAP4_SCLK_PJ7, -}; - -static const unsigned pk0_pins[] = { - TEGRA_PIN_PK0, -}; - -static const unsigned pk1_pins[] = { - TEGRA_PIN_PK1, -}; - -static const unsigned pk2_pins[] = { - TEGRA_PIN_PK2, -}; - -static const unsigned pk3_pins[] = { - TEGRA_PIN_PK3, -}; - -static const unsigned pk4_pins[] = { - TEGRA_PIN_PK4, -}; - -static const unsigned pk5_pins[] = { - TEGRA_PIN_PK5, -}; - -static const unsigned pk6_pins[] = { - TEGRA_PIN_PK6, -}; - -static const unsigned pk7_pins[] = { - TEGRA_PIN_PK7, -}; - -static const unsigned pl0_pins[] = { - TEGRA_PIN_PL0, -}; - -static const unsigned pl1_pins[] = { - TEGRA_PIN_PL1, -}; - -static const unsigned sdmmc1_clk_pm0_pins[] = { - TEGRA_PIN_SDMMC1_CLK_PM0, -}; - -static const unsigned sdmmc1_cmd_pm1_pins[] = { - TEGRA_PIN_SDMMC1_CMD_PM1, -}; - -static const unsigned sdmmc1_dat3_pm2_pins[] = { - TEGRA_PIN_SDMMC1_DAT3_PM2, -}; - -static const unsigned sdmmc1_dat2_pm3_pins[] = { - TEGRA_PIN_SDMMC1_DAT2_PM3, -}; - -static const unsigned sdmmc1_dat1_pm4_pins[] = { - TEGRA_PIN_SDMMC1_DAT1_PM4, -}; - -static const unsigned sdmmc1_dat0_pm5_pins[] = { - TEGRA_PIN_SDMMC1_DAT0_PM5, -}; - -static const unsigned sdmmc3_clk_pp0_pins[] = { - TEGRA_PIN_SDMMC3_CLK_PP0, -}; - -static const unsigned sdmmc3_cmd_pp1_pins[] = { - TEGRA_PIN_SDMMC3_CMD_PP1, -}; - -static const unsigned sdmmc3_dat3_pp2_pins[] = { - TEGRA_PIN_SDMMC3_DAT3_PP2, -}; - -static const unsigned sdmmc3_dat2_pp3_pins[] = { - TEGRA_PIN_SDMMC3_DAT2_PP3, -}; - -static const unsigned sdmmc3_dat1_pp4_pins[] = { - TEGRA_PIN_SDMMC3_DAT1_PP4, -}; - -static const unsigned sdmmc3_dat0_pp5_pins[] = { - TEGRA_PIN_SDMMC3_DAT0_PP5, -}; - -static const unsigned cam1_mclk_ps0_pins[] = { - TEGRA_PIN_CAM1_MCLK_PS0, -}; - -static const unsigned cam2_mclk_ps1_pins[] = { - TEGRA_PIN_CAM2_MCLK_PS1, -}; - -static const unsigned cam_i2c_scl_ps2_pins[] = { - TEGRA_PIN_CAM_I2C_SCL_PS2, -}; - -static const unsigned cam_i2c_sda_ps3_pins[] = { - TEGRA_PIN_CAM_I2C_SDA_PS3, -}; - -static const unsigned cam_rst_ps4_pins[] = { - TEGRA_PIN_CAM_RST_PS4, -}; - -static const unsigned cam_af_en_ps5_pins[] = { - TEGRA_PIN_CAM_AF_EN_PS5, -}; - -static const unsigned cam_flash_en_ps6_pins[] = { - TEGRA_PIN_CAM_FLASH_EN_PS6, -}; - -static const unsigned cam1_pwdn_ps7_pins[] = { - TEGRA_PIN_CAM1_PWDN_PS7, -}; - -static const unsigned cam2_pwdn_pt0_pins[] = { - TEGRA_PIN_CAM2_PWDN_PT0, -}; - -static const unsigned cam1_strobe_pt1_pins[] = { - TEGRA_PIN_CAM1_STROBE_PT1, -}; - -static const unsigned uart1_tx_pu0_pins[] = { - TEGRA_PIN_UART1_TX_PU0, -}; - -static const unsigned uart1_rx_pu1_pins[] = { - TEGRA_PIN_UART1_RX_PU1, -}; - -static const unsigned uart1_rts_pu2_pins[] = { - TEGRA_PIN_UART1_RTS_PU2, -}; - -static const unsigned uart1_cts_pu3_pins[] = { - TEGRA_PIN_UART1_CTS_PU3, -}; - -static const unsigned lcd_bl_pwm_pv0_pins[] = { - TEGRA_PIN_LCD_BL_PWM_PV0, -}; - -static const unsigned lcd_bl_en_pv1_pins[] = { - TEGRA_PIN_LCD_BL_EN_PV1, -}; - -static const unsigned lcd_rst_pv2_pins[] = { - TEGRA_PIN_LCD_RST_PV2, -}; - -static const unsigned lcd_gpio1_pv3_pins[] = { - TEGRA_PIN_LCD_GPIO1_PV3, -}; - -static const unsigned lcd_gpio2_pv4_pins[] = { - TEGRA_PIN_LCD_GPIO2_PV4, -}; - -static const unsigned ap_ready_pv5_pins[] = { - TEGRA_PIN_AP_READY_PV5, -}; - -static const unsigned touch_rst_pv6_pins[] = { - TEGRA_PIN_TOUCH_RST_PV6, -}; - -static const unsigned touch_clk_pv7_pins[] = { - TEGRA_PIN_TOUCH_CLK_PV7, -}; - -static const unsigned modem_wake_ap_px0_pins[] = { - TEGRA_PIN_MODEM_WAKE_AP_PX0, -}; - -static const unsigned touch_int_px1_pins[] = { - TEGRA_PIN_TOUCH_INT_PX1, -}; - -static const unsigned motion_int_px2_pins[] = { - TEGRA_PIN_MOTION_INT_PX2, -}; - -static const unsigned als_prox_int_px3_pins[] = { - TEGRA_PIN_ALS_PROX_INT_PX3, -}; - -static const unsigned temp_alert_px4_pins[] = { - TEGRA_PIN_TEMP_ALERT_PX4, -}; - -static const unsigned button_power_on_px5_pins[] = { - TEGRA_PIN_BUTTON_POWER_ON_PX5, -}; - -static const unsigned button_vol_up_px6_pins[] = { - TEGRA_PIN_BUTTON_VOL_UP_PX6, -}; - -static const unsigned button_vol_down_px7_pins[] = { - TEGRA_PIN_BUTTON_VOL_DOWN_PX7, -}; - -static const unsigned button_slide_sw_py0_pins[] = { - TEGRA_PIN_BUTTON_SLIDE_SW_PY0, -}; - -static const unsigned button_home_py1_pins[] = { - TEGRA_PIN_BUTTON_HOME_PY1, -}; - -static const unsigned lcd_te_py2_pins[] = { - TEGRA_PIN_LCD_TE_PY2, -}; - -static const unsigned pwr_i2c_scl_py3_pins[] = { - TEGRA_PIN_PWR_I2C_SCL_PY3, -}; - -static const unsigned pwr_i2c_sda_py4_pins[] = { - TEGRA_PIN_PWR_I2C_SDA_PY4, -}; - -static const unsigned clk_32k_out_py5_pins[] = { - TEGRA_PIN_CLK_32K_OUT_PY5, -}; - -static const unsigned pz0_pins[] = { - TEGRA_PIN_PZ0, -}; - -static const unsigned pz1_pins[] = { - TEGRA_PIN_PZ1, -}; - -static const unsigned pz2_pins[] = { - TEGRA_PIN_PZ2, -}; - -static const unsigned pz3_pins[] = { - TEGRA_PIN_PZ3, -}; - -static const unsigned pz4_pins[] = { - TEGRA_PIN_PZ4, -}; - -static const unsigned pz5_pins[] = { - TEGRA_PIN_PZ5, -}; - -static const unsigned dap2_fs_paa0_pins[] = { - TEGRA_PIN_DAP2_FS_PAA0, -}; - -static const unsigned dap2_sclk_paa1_pins[] = { - TEGRA_PIN_DAP2_SCLK_PAA1, -}; - -static const unsigned dap2_din_paa2_pins[] = { - TEGRA_PIN_DAP2_DIN_PAA2, -}; - -static const unsigned dap2_dout_paa3_pins[] = { - TEGRA_PIN_DAP2_DOUT_PAA3, -}; - -static const unsigned aud_mclk_pbb0_pins[] = { - TEGRA_PIN_AUD_MCLK_PBB0, -}; - -static const unsigned dvfs_pwm_pbb1_pins[] = { - TEGRA_PIN_DVFS_PWM_PBB1, -}; - -static const unsigned dvfs_clk_pbb2_pins[] = { - TEGRA_PIN_DVFS_CLK_PBB2, -}; - -static const unsigned gpio_x1_aud_pbb3_pins[] = { - TEGRA_PIN_GPIO_X1_AUD_PBB3, -}; - -static const unsigned gpio_x3_aud_pbb4_pins[] = { - TEGRA_PIN_GPIO_X3_AUD_PBB4, -}; - -static const unsigned hdmi_cec_pcc0_pins[] = { - TEGRA_PIN_HDMI_CEC_PCC0, -}; - -static const unsigned hdmi_int_dp_hpd_pcc1_pins[] = { - TEGRA_PIN_HDMI_INT_DP_HPD_PCC1, -}; - -static const unsigned spdif_out_pcc2_pins[] = { - TEGRA_PIN_SPDIF_OUT_PCC2, -}; - -static const unsigned spdif_in_pcc3_pins[] = { - TEGRA_PIN_SPDIF_IN_PCC3, -}; - -static const unsigned usb_vbus_en0_pcc4_pins[] = { - TEGRA_PIN_USB_VBUS_EN0_PCC4, -}; - -static const unsigned usb_vbus_en1_pcc5_pins[] = { - TEGRA_PIN_USB_VBUS_EN1_PCC5, -}; - -static const unsigned dp_hpd0_pcc6_pins[] = { - TEGRA_PIN_DP_HPD0_PCC6, -}; - -static const unsigned pcc7_pins[] = { - TEGRA_PIN_PCC7, -}; - -static const unsigned spi2_cs1_pdd0_pins[] = { - TEGRA_PIN_SPI2_CS1_PDD0, -}; - -static const unsigned qspi_sck_pee0_pins[] = { - TEGRA_PIN_QSPI_SCK_PEE0, -}; - -static const unsigned qspi_cs_n_pee1_pins[] = { - TEGRA_PIN_QSPI_CS_N_PEE1, -}; - -static const unsigned qspi_io0_pee2_pins[] = { - TEGRA_PIN_QSPI_IO0_PEE2, -}; - -static const unsigned qspi_io1_pee3_pins[] = { - TEGRA_PIN_QSPI_IO1_PEE3, -}; - -static const unsigned qspi_io2_pee4_pins[] = { - TEGRA_PIN_QSPI_IO2_PEE4, -}; - -static const unsigned qspi_io3_pee5_pins[] = { - TEGRA_PIN_QSPI_IO3_PEE5, -}; - -static const unsigned core_pwr_req_pins[] = { - TEGRA_PIN_CORE_PWR_REQ, -}; - -static const unsigned cpu_pwr_req_pins[] = { - TEGRA_PIN_CPU_PWR_REQ, -}; - -static const unsigned pwr_int_n_pins[] = { - TEGRA_PIN_PWR_INT_N, -}; - -static const unsigned clk_32k_in_pins[] = { - TEGRA_PIN_CLK_32K_IN, -}; - -static const unsigned jtag_rtck_pins[] = { - TEGRA_PIN_JTAG_RTCK, -}; - -static const unsigned batt_bcl_pins[] = { - TEGRA_PIN_BATT_BCL, -}; - -static const unsigned clk_req_pins[] = { - TEGRA_PIN_CLK_REQ, -}; - -static const unsigned shutdown_pins[] = { - TEGRA_PIN_SHUTDOWN, -}; - -static const unsigned drive_pa6_pins[] = { - TEGRA_PIN_PA6, -}; - -static const unsigned drive_pcc7_pins[] = { - TEGRA_PIN_PCC7, -}; - -static const unsigned drive_pe6_pins[] = { - TEGRA_PIN_PE6, -}; - -static const unsigned drive_pe7_pins[] = { - TEGRA_PIN_PE7, -}; - -static const unsigned drive_ph6_pins[] = { - TEGRA_PIN_PH6, -}; - -static const unsigned drive_pk0_pins[] = { - TEGRA_PIN_PK0, -}; - -static const unsigned drive_pk1_pins[] = { - TEGRA_PIN_PK1, -}; - -static const unsigned drive_pk2_pins[] = { - TEGRA_PIN_PK2, -}; - -static const unsigned drive_pk3_pins[] = { - TEGRA_PIN_PK3, -}; - -static const unsigned drive_pk4_pins[] = { - TEGRA_PIN_PK4, -}; - -static const unsigned drive_pk5_pins[] = { - TEGRA_PIN_PK5, -}; - -static const unsigned drive_pk6_pins[] = { - TEGRA_PIN_PK6, -}; - -static const unsigned drive_pk7_pins[] = { - TEGRA_PIN_PK7, -}; - -static const unsigned drive_pl0_pins[] = { - TEGRA_PIN_PL0, -}; - -static const unsigned drive_pl1_pins[] = { - TEGRA_PIN_PL1, -}; - -static const unsigned drive_pz0_pins[] = { - TEGRA_PIN_PZ0, -}; - -static const unsigned drive_pz1_pins[] = { - TEGRA_PIN_PZ1, -}; - -static const unsigned drive_pz2_pins[] = { - TEGRA_PIN_PZ2, -}; - -static const unsigned drive_pz3_pins[] = { - TEGRA_PIN_PZ3, -}; - -static const unsigned drive_pz4_pins[] = { - TEGRA_PIN_PZ4, -}; - -static const unsigned drive_pz5_pins[] = { - TEGRA_PIN_PZ5, -}; - -static const unsigned drive_sdmmc1_pins[] = { - TEGRA_PIN_SDMMC1_CLK_PM0, - TEGRA_PIN_SDMMC1_CMD_PM1, - TEGRA_PIN_SDMMC1_DAT3_PM2, - TEGRA_PIN_SDMMC1_DAT2_PM3, - TEGRA_PIN_SDMMC1_DAT1_PM4, - TEGRA_PIN_SDMMC1_DAT0_PM5, -}; - -static const unsigned drive_sdmmc2_pins[] = { -}; - -static const unsigned drive_sdmmc3_pins[] = { - TEGRA_PIN_SDMMC3_CLK_PP0, - TEGRA_PIN_SDMMC3_CMD_PP1, - TEGRA_PIN_SDMMC3_DAT3_PP2, - TEGRA_PIN_SDMMC3_DAT2_PP3, - TEGRA_PIN_SDMMC3_DAT1_PP4, - TEGRA_PIN_SDMMC3_DAT0_PP5, -}; - -static const unsigned drive_sdmmc4_pins[] = { -}; - -enum tegra_mux { - TEGRA_MUX_AUD, - TEGRA_MUX_BCL, - TEGRA_MUX_BLINK, - TEGRA_MUX_CCLA, - TEGRA_MUX_CEC, - TEGRA_MUX_CLDVFS, - TEGRA_MUX_CLK, - TEGRA_MUX_CORE, - TEGRA_MUX_CPU, - TEGRA_MUX_DISPLAYA, - TEGRA_MUX_DISPLAYB, - TEGRA_MUX_DMIC1, - TEGRA_MUX_DMIC2, - TEGRA_MUX_DMIC3, - TEGRA_MUX_DP, - TEGRA_MUX_DTV, - TEGRA_MUX_EXTPERIPH3, - TEGRA_MUX_I2C1, - TEGRA_MUX_I2C2, - TEGRA_MUX_I2C3, - TEGRA_MUX_I2CPMU, - TEGRA_MUX_I2CVI, - TEGRA_MUX_I2S1, - TEGRA_MUX_I2S2, - TEGRA_MUX_I2S3, - TEGRA_MUX_I2S4A, - TEGRA_MUX_I2S4B, - TEGRA_MUX_I2S5A, - TEGRA_MUX_I2S5B, - TEGRA_MUX_IQC0, - TEGRA_MUX_IQC1, - TEGRA_MUX_JTAG, - TEGRA_MUX_PE, - TEGRA_MUX_PE0, - TEGRA_MUX_PE1, - TEGRA_MUX_PMI, - TEGRA_MUX_PWM0, - TEGRA_MUX_PWM1, - TEGRA_MUX_PWM2, - TEGRA_MUX_PWM3, - TEGRA_MUX_QSPI, - TEGRA_MUX_RSVD0, - TEGRA_MUX_RSVD1, - TEGRA_MUX_RSVD2, - TEGRA_MUX_RSVD3, - TEGRA_MUX_SATA, - TEGRA_MUX_SDMMC1, - TEGRA_MUX_SDMMC3, - TEGRA_MUX_SHUTDOWN, - TEGRA_MUX_SOC, - TEGRA_MUX_SOR0, - TEGRA_MUX_SOR1, - TEGRA_MUX_SPDIF, - TEGRA_MUX_SPI1, - TEGRA_MUX_SPI2, - TEGRA_MUX_SPI3, - TEGRA_MUX_SPI4, - TEGRA_MUX_SYS, - TEGRA_MUX_TOUCH, - TEGRA_MUX_UART, - TEGRA_MUX_UARTA, - TEGRA_MUX_UARTB, - TEGRA_MUX_UARTC, - TEGRA_MUX_UARTD, - TEGRA_MUX_USB, - TEGRA_MUX_VGP1, - TEGRA_MUX_VGP2, - TEGRA_MUX_VGP3, - TEGRA_MUX_VGP4, - TEGRA_MUX_VGP5, - TEGRA_MUX_VGP6, - TEGRA_MUX_VIMCLK, - TEGRA_MUX_VIMCLK2, -}; - -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } - -static struct tegra_function tegra210_functions[] = { - FUNCTION(aud), - FUNCTION(bcl), - FUNCTION(blink), - FUNCTION(ccla), - FUNCTION(cec), - FUNCTION(cldvfs), - FUNCTION(clk), - FUNCTION(core), - FUNCTION(cpu), - FUNCTION(displaya), - FUNCTION(displayb), - FUNCTION(dmic1), - FUNCTION(dmic2), - FUNCTION(dmic3), - FUNCTION(dp), - FUNCTION(dtv), - FUNCTION(extperiph3), - FUNCTION(i2c1), - FUNCTION(i2c2), - FUNCTION(i2c3), - FUNCTION(i2cpmu), - FUNCTION(i2cvi), - FUNCTION(i2s1), - FUNCTION(i2s2), - FUNCTION(i2s3), - FUNCTION(i2s4a), - FUNCTION(i2s4b), - FUNCTION(i2s5a), - FUNCTION(i2s5b), - FUNCTION(iqc0), - FUNCTION(iqc1), - FUNCTION(jtag), - FUNCTION(pe), - FUNCTION(pe0), - FUNCTION(pe1), - FUNCTION(pmi), - FUNCTION(pwm0), - FUNCTION(pwm1), - FUNCTION(pwm2), - FUNCTION(pwm3), - FUNCTION(qspi), - FUNCTION(rsvd0), - FUNCTION(rsvd1), - FUNCTION(rsvd2), - FUNCTION(rsvd3), - FUNCTION(sata), - FUNCTION(sdmmc1), - FUNCTION(sdmmc3), - FUNCTION(shutdown), - FUNCTION(soc), - FUNCTION(sor0), - FUNCTION(sor1), - FUNCTION(spdif), - FUNCTION(spi1), - FUNCTION(spi2), - FUNCTION(spi3), - FUNCTION(spi4), - FUNCTION(sys), - FUNCTION(touch), - FUNCTION(uart), - FUNCTION(uarta), - FUNCTION(uartb), - FUNCTION(uartc), - FUNCTION(uartd), - FUNCTION(usb), - FUNCTION(vgp1), - FUNCTION(vgp2), - FUNCTION(vgp3), - FUNCTION(vgp4), - FUNCTION(vgp5), - FUNCTION(vgp6), - FUNCTION(vimclk), - FUNCTION(vimclk2), -}; - -#define DRV_PINGROUP_REG_A 0x8d4 /* bank 0 */ -#define PINGROUP_REG_A 0x3000 /* bank 1 */ - -#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A) -#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) - -#define PINGROUP_BIT_Y(b) (b) -#define PINGROUP_BIT_N(b) (-1) - -#define PINGROUP(pg_name, f0, f1, f2, f3, r, hsm, drvtype, e_io_hv, \ - rdrv, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, \ - slwr_w, slwf_b, slwf_w) \ - { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ - .funcs = { \ - TEGRA_MUX_##f0, \ - TEGRA_MUX_##f1, \ - TEGRA_MUX_##f2, \ - TEGRA_MUX_##f3, \ - }, \ - .mux_reg = PINGROUP_REG(r), \ - .mux_bank = 1, \ - .mux_bit = 0, \ - .pupd_reg = PINGROUP_REG(r), \ - .pupd_bank = 1, \ - .pupd_bit = 2, \ - .tri_reg = PINGROUP_REG(r), \ - .tri_bank = 1, \ - .tri_bit = 4, \ - .einput_bit = 6, \ - .odrain_bit = 11, \ - .lock_bit = 7, \ - .ioreset_bit = -1, \ - .rcv_sel_bit = PINGROUP_BIT_##e_io_hv(10), \ - .hsm_bit = PINGROUP_BIT_##hsm(9), \ - .schmitt_bit = 12, \ - .drvtype_bit = PINGROUP_BIT_##drvtype(13), \ - .drv_reg = DRV_PINGROUP_REG(rdrv), \ - .drv_bank = 0, \ - .lpmd_bit = -1, \ - .drvdn_bit = drvdn_b, \ - .drvdn_width = drvdn_w, \ - .drvup_bit = drvup_b, \ - .drvup_width = drvup_w, \ - .slwr_bit = slwr_b, \ - .slwr_width = slwr_w, \ - .slwf_bit = slwf_b, \ - .slwf_width = slwf_w, \ - } - -#define DRV_PINGROUP(pg_name, r, drvdn_b, drvdn_w, drvup_b, drvup_w, \ - slwr_b, slwr_w, slwf_b, slwf_w) \ - { \ - .name = "drive_" #pg_name, \ - .pins = drive_##pg_name##_pins, \ - .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ - .mux_reg = -1, \ - .pupd_reg = -1, \ - .tri_reg = -1, \ - .einput_bit = -1, \ - .odrain_bit = -1, \ - .lock_bit = -1, \ - .ioreset_bit = -1, \ - .rcv_sel_bit = -1, \ - .drv_reg = DRV_PINGROUP_REG(r), \ - .drv_bank = 0, \ - .hsm_bit = -1, \ - .schmitt_bit = -1, \ - .lpmd_bit = -1, \ - .drvdn_bit = drvdn_b, \ - .drvdn_width = drvdn_w, \ - .drvup_bit = drvup_b, \ - .drvup_width = drvup_w, \ - .slwr_bit = slwr_b, \ - .slwr_width = slwr_w, \ - .slwf_bit = slwf_b, \ - .slwf_width = slwf_w, \ - .drvtype_bit = -1, \ - } - -static const struct tegra_pingroup tegra210_groups[] = { - /* pg_name, f0, f1, f2, f3, r, hsm, drvtype, e_io_hv, rdrv, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */ - PINGROUP(sdmmc1_clk_pm0, SDMMC1, RSVD1, RSVD2, RSVD3, 0x3000, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc1_cmd_pm1, SDMMC1, SPI3, RSVD2, RSVD3, 0x3004, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc1_dat3_pm2, SDMMC1, SPI3, RSVD2, RSVD3, 0x3008, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc1_dat2_pm3, SDMMC1, SPI3, RSVD2, RSVD3, 0x300c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc1_dat1_pm4, SDMMC1, SPI3, RSVD2, RSVD3, 0x3010, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc1_dat0_pm5, SDMMC1, RSVD1, RSVD2, RSVD3, 0x3014, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc3_clk_pp0, SDMMC3, RSVD1, RSVD2, RSVD3, 0x301c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc3_cmd_pp1, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3020, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc3_dat0_pp5, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3024, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc3_dat1_pp4, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3028, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc3_dat2_pp3, SDMMC3, RSVD1, RSVD2, RSVD3, 0x302c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc3_dat3_pp2, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3030, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pex_l0_rst_n_pa0, PE0, RSVD1, RSVD2, RSVD3, 0x3038, N, N, Y, 0xa5c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pex_l0_clkreq_n_pa1, PE0, RSVD1, RSVD2, RSVD3, 0x303c, N, N, Y, 0xa58, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pex_wake_n_pa2, PE, RSVD1, RSVD2, RSVD3, 0x3040, N, N, Y, 0xa68, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pex_l1_rst_n_pa3, PE1, RSVD1, RSVD2, RSVD3, 0x3044, N, N, Y, 0xa64, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pex_l1_clkreq_n_pa4, PE1, RSVD1, RSVD2, RSVD3, 0x3048, N, N, Y, 0xa60, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(sata_led_active_pa5, SATA, RSVD1, RSVD2, RSVD3, 0x304c, N, N, N, 0xa94, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(spi1_mosi_pc0, SPI1, RSVD1, RSVD2, RSVD3, 0x3050, Y, Y, N, 0xae0, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi1_miso_pc1, SPI1, RSVD1, RSVD2, RSVD3, 0x3054, Y, Y, N, 0xadc, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi1_sck_pc2, SPI1, RSVD1, RSVD2, RSVD3, 0x3058, Y, Y, N, 0xae4, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi1_cs0_pc3, SPI1, RSVD1, RSVD2, RSVD3, 0x305c, Y, Y, N, 0xad4, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi1_cs1_pc4, SPI1, RSVD1, RSVD2, RSVD3, 0x3060, Y, Y, N, 0xad8, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi2_mosi_pb4, SPI2, DTV, RSVD2, RSVD3, 0x3064, Y, Y, N, 0xaf4, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi2_miso_pb5, SPI2, DTV, RSVD2, RSVD3, 0x3068, Y, Y, N, 0xaf0, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi2_sck_pb6, SPI2, DTV, RSVD2, RSVD3, 0x306c, Y, Y, N, 0xaf8, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi2_cs0_pb7, SPI2, DTV, RSVD2, RSVD3, 0x3070, Y, Y, N, 0xae8, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi2_cs1_pdd0, SPI2, RSVD1, RSVD2, RSVD3, 0x3074, Y, Y, N, 0xaec, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi4_mosi_pc7, SPI4, RSVD1, RSVD2, RSVD3, 0x3078, Y, Y, N, 0xb04, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi4_miso_pd0, SPI4, RSVD1, RSVD2, RSVD3, 0x307c, Y, Y, N, 0xb00, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi4_sck_pc5, SPI4, RSVD1, RSVD2, RSVD3, 0x3080, Y, Y, N, 0xb08, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi4_cs0_pc6, SPI4, RSVD1, RSVD2, RSVD3, 0x3084, Y, Y, N, 0xafc, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(qspi_sck_pee0, QSPI, RSVD1, RSVD2, RSVD3, 0x3088, Y, Y, N, 0xa90, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(qspi_cs_n_pee1, QSPI, RSVD1, RSVD2, RSVD3, 0x308c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(qspi_io0_pee2, QSPI, RSVD1, RSVD2, RSVD3, 0x3090, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(qspi_io1_pee3, QSPI, RSVD1, RSVD2, RSVD3, 0x3094, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(qspi_io2_pee4, QSPI, RSVD1, RSVD2, RSVD3, 0x3098, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(qspi_io3_pee5, QSPI, RSVD1, RSVD2, RSVD3, 0x309c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(dmic1_clk_pe0, DMIC1, I2S3, RSVD2, RSVD3, 0x30a4, N, N, N, 0x984, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dmic1_dat_pe1, DMIC1, I2S3, RSVD2, RSVD3, 0x30a8, N, N, N, 0x988, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dmic2_clk_pe2, DMIC2, I2S3, RSVD2, RSVD3, 0x30ac, N, N, N, 0x98c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dmic2_dat_pe3, DMIC2, I2S3, RSVD2, RSVD3, 0x30b0, N, N, N, 0x990, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dmic3_clk_pe4, DMIC3, I2S5A, RSVD2, RSVD3, 0x30b4, N, N, N, 0x994, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dmic3_dat_pe5, DMIC3, I2S5A, RSVD2, RSVD3, 0x30b8, N, N, N, 0x998, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gen1_i2c_scl_pj1, I2C1, RSVD1, RSVD2, RSVD3, 0x30bc, N, N, Y, 0x9a8, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gen1_i2c_sda_pj0, I2C1, RSVD1, RSVD2, RSVD3, 0x30c0, N, N, Y, 0x9ac, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gen2_i2c_scl_pj2, I2C2, RSVD1, RSVD2, RSVD3, 0x30c4, N, N, Y, 0x9b0, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gen2_i2c_sda_pj3, I2C2, RSVD1, RSVD2, RSVD3, 0x30c8, N, N, Y, 0x9b4, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gen3_i2c_scl_pf0, I2C3, RSVD1, RSVD2, RSVD3, 0x30cc, N, N, Y, 0x9b8, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gen3_i2c_sda_pf1, I2C3, RSVD1, RSVD2, RSVD3, 0x30d0, N, N, Y, 0x9bc, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam_i2c_scl_ps2, I2C3, I2CVI, RSVD2, RSVD3, 0x30d4, N, N, Y, 0x934, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam_i2c_sda_ps3, I2C3, I2CVI, RSVD2, RSVD3, 0x30d8, N, N, Y, 0x938, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pwr_i2c_scl_py3, I2CPMU, RSVD1, RSVD2, RSVD3, 0x30dc, N, N, Y, 0xa6c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pwr_i2c_sda_py4, I2CPMU, RSVD1, RSVD2, RSVD3, 0x30e0, N, N, Y, 0xa70, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart1_tx_pu0, UARTA, RSVD1, RSVD2, RSVD3, 0x30e4, N, N, N, 0xb28, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart1_rx_pu1, UARTA, RSVD1, RSVD2, RSVD3, 0x30e8, N, N, N, 0xb24, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart1_rts_pu2, UARTA, RSVD1, RSVD2, RSVD3, 0x30ec, N, N, N, 0xb20, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart1_cts_pu3, UARTA, RSVD1, RSVD2, RSVD3, 0x30f0, N, N, N, 0xb1c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart2_tx_pg0, UARTB, I2S4A, SPDIF, UART, 0x30f4, N, N, N, 0xb38, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart2_rx_pg1, UARTB, I2S4A, SPDIF, UART, 0x30f8, N, N, N, 0xb34, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart2_rts_pg2, UARTB, I2S4A, RSVD2, UART, 0x30fc, N, N, N, 0xb30, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart2_cts_pg3, UARTB, I2S4A, RSVD2, UART, 0x3100, N, N, N, 0xb2c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart3_tx_pd1, UARTC, SPI4, RSVD2, RSVD3, 0x3104, N, N, N, 0xb48, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart3_rx_pd2, UARTC, SPI4, RSVD2, RSVD3, 0x3108, N, N, N, 0xb44, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart3_rts_pd3, UARTC, SPI4, RSVD2, RSVD3, 0x310c, N, N, N, 0xb40, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart3_cts_pd4, UARTC, SPI4, RSVD2, RSVD3, 0x3110, N, N, N, 0xb3c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart4_tx_pi4, UARTD, UART, RSVD2, RSVD3, 0x3114, N, N, N, 0xb58, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart4_rx_pi5, UARTD, UART, RSVD2, RSVD3, 0x3118, N, N, N, 0xb54, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart4_rts_pi6, UARTD, UART, RSVD2, RSVD3, 0x311c, N, N, N, 0xb50, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart4_cts_pi7, UARTD, UART, RSVD2, RSVD3, 0x3120, N, N, N, 0xb4c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dap1_fs_pb0, I2S1, RSVD1, RSVD2, RSVD3, 0x3124, Y, Y, N, 0x95c, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(dap1_din_pb1, I2S1, RSVD1, RSVD2, RSVD3, 0x3128, Y, Y, N, 0x954, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(dap1_dout_pb2, I2S1, RSVD1, RSVD2, RSVD3, 0x312c, Y, Y, N, 0x958, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(dap1_sclk_pb3, I2S1, RSVD1, RSVD2, RSVD3, 0x3130, Y, Y, N, 0x960, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(dap2_fs_paa0, I2S2, RSVD1, RSVD2, RSVD3, 0x3134, Y, Y, N, 0x96c, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(dap2_din_paa2, I2S2, RSVD1, RSVD2, RSVD3, 0x3138, Y, Y, N, 0x964, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(dap2_dout_paa3, I2S2, RSVD1, RSVD2, RSVD3, 0x313c, Y, Y, N, 0x968, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(dap2_sclk_paa1, I2S2, RSVD1, RSVD2, RSVD3, 0x3140, Y, Y, N, 0x970, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(dap4_fs_pj4, I2S4B, RSVD1, RSVD2, RSVD3, 0x3144, N, N, N, 0x97c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dap4_din_pj5, I2S4B, RSVD1, RSVD2, RSVD3, 0x3148, N, N, N, 0x974, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dap4_dout_pj6, I2S4B, RSVD1, RSVD2, RSVD3, 0x314c, N, N, N, 0x978, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dap4_sclk_pj7, I2S4B, RSVD1, RSVD2, RSVD3, 0x3150, N, N, N, 0x980, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam1_mclk_ps0, EXTPERIPH3, RSVD1, RSVD2, RSVD3, 0x3154, N, N, N, 0x918, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam2_mclk_ps1, EXTPERIPH3, RSVD1, RSVD2, RSVD3, 0x3158, N, N, N, 0x924, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(jtag_rtck, JTAG, RSVD1, RSVD2, RSVD3, 0x315c, N, N, N, 0xa2c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(clk_32k_in, CLK, RSVD1, RSVD2, RSVD3, 0x3160, N, N, N, 0x940, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(clk_32k_out_py5, SOC, BLINK, RSVD2, RSVD3, 0x3164, N, N, N, 0x944, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(batt_bcl, BCL, RSVD1, RSVD2, RSVD3, 0x3168, N, N, Y, 0x8f8, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(clk_req, SYS, RSVD1, RSVD2, RSVD3, 0x316c, N, N, N, 0x948, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cpu_pwr_req, CPU, RSVD1, RSVD2, RSVD3, 0x3170, N, N, N, 0x950, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pwr_int_n, PMI, RSVD1, RSVD2, RSVD3, 0x3174, N, N, N, 0xa74, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(shutdown, SHUTDOWN, RSVD1, RSVD2, RSVD3, 0x3178, N, N, N, 0xac8, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(core_pwr_req, CORE, RSVD1, RSVD2, RSVD3, 0x317c, N, N, N, 0x94c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(aud_mclk_pbb0, AUD, RSVD1, RSVD2, RSVD3, 0x3180, N, N, N, 0x8f4, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dvfs_pwm_pbb1, RSVD0, CLDVFS, SPI3, RSVD3, 0x3184, N, N, N, 0x9a4, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dvfs_clk_pbb2, RSVD0, CLDVFS, SPI3, RSVD3, 0x3188, N, N, N, 0x9a0, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gpio_x1_aud_pbb3, RSVD0, RSVD1, SPI3, RSVD3, 0x318c, N, N, N, 0xa14, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gpio_x3_aud_pbb4, RSVD0, RSVD1, SPI3, RSVD3, 0x3190, N, N, N, 0xa18, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pcc7, RSVD0, RSVD1, RSVD2, RSVD3, 0x3194, N, N, Y, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(hdmi_cec_pcc0, CEC, RSVD1, RSVD2, RSVD3, 0x3198, N, N, Y, 0xa24, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(hdmi_int_dp_hpd_pcc1, DP, RSVD1, RSVD2, RSVD3, 0x319c, N, N, Y, 0xa28, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(spdif_out_pcc2, SPDIF, RSVD1, RSVD2, RSVD3, 0x31a0, N, N, N, 0xad0, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(spdif_in_pcc3, SPDIF, RSVD1, RSVD2, RSVD3, 0x31a4, N, N, N, 0xacc, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(usb_vbus_en0_pcc4, USB, RSVD1, RSVD2, RSVD3, 0x31a8, N, N, Y, 0xb5c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(usb_vbus_en1_pcc5, USB, RSVD1, RSVD2, RSVD3, 0x31ac, N, N, Y, 0xb60, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dp_hpd0_pcc6, DP, RSVD1, RSVD2, RSVD3, 0x31b0, N, N, N, 0x99c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(wifi_en_ph0, RSVD0, RSVD1, RSVD2, RSVD3, 0x31b4, N, N, N, 0xb64, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(wifi_rst_ph1, RSVD0, RSVD1, RSVD2, RSVD3, 0x31b8, N, N, N, 0xb68, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(wifi_wake_ap_ph2, RSVD0, RSVD1, RSVD2, RSVD3, 0x31bc, N, N, N, 0xb6c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(ap_wake_bt_ph3, RSVD0, UARTB, SPDIF, RSVD3, 0x31c0, N, N, N, 0x8ec, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(bt_rst_ph4, RSVD0, UARTB, SPDIF, RSVD3, 0x31c4, N, N, N, 0x8fc, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(bt_wake_ap_ph5, RSVD0, RSVD1, RSVD2, RSVD3, 0x31c8, N, N, N, 0x900, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(ap_wake_nfc_ph7, RSVD0, RSVD1, RSVD2, RSVD3, 0x31cc, N, N, N, 0x8f0, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(nfc_en_pi0, RSVD0, RSVD1, RSVD2, RSVD3, 0x31d0, N, N, N, 0xa50, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(nfc_int_pi1, RSVD0, RSVD1, RSVD2, RSVD3, 0x31d4, N, N, N, 0xa54, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gps_en_pi2, RSVD0, RSVD1, RSVD2, RSVD3, 0x31d8, N, N, N, 0xa1c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gps_rst_pi3, RSVD0, RSVD1, RSVD2, RSVD3, 0x31dc, N, N, N, 0xa20, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam_rst_ps4, VGP1, RSVD1, RSVD2, RSVD3, 0x31e0, N, N, N, 0x93c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam_af_en_ps5, VIMCLK, VGP2, RSVD2, RSVD3, 0x31e4, N, N, N, 0x92c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam_flash_en_ps6, VIMCLK, VGP3, RSVD2, RSVD3, 0x31e8, N, N, N, 0x930, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam1_pwdn_ps7, VGP4, RSVD1, RSVD2, RSVD3, 0x31ec, N, N, N, 0x91c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam2_pwdn_pt0, VGP5, RSVD1, RSVD2, RSVD3, 0x31f0, N, N, N, 0x928, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam1_strobe_pt1, VGP6, RSVD1, RSVD2, RSVD3, 0x31f4, N, N, N, 0x920, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(lcd_te_py2, DISPLAYA, RSVD1, RSVD2, RSVD3, 0x31f8, N, N, N, 0xa44, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(lcd_bl_pwm_pv0, DISPLAYA, PWM0, SOR0, RSVD3, 0x31fc, N, N, N, 0xa34, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(lcd_bl_en_pv1, RSVD0, RSVD1, RSVD2, RSVD3, 0x3200, N, N, N, 0xa30, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(lcd_rst_pv2, RSVD0, RSVD1, RSVD2, RSVD3, 0x3204, N, N, N, 0xa40, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(lcd_gpio1_pv3, DISPLAYB, RSVD1, RSVD2, RSVD3, 0x3208, N, N, N, 0xa38, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(lcd_gpio2_pv4, DISPLAYB, PWM1, RSVD2, SOR1, 0x320c, N, N, N, 0xa3c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(ap_ready_pv5, RSVD0, RSVD1, RSVD2, RSVD3, 0x3210, N, N, N, 0x8e8, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(touch_rst_pv6, RSVD0, RSVD1, RSVD2, RSVD3, 0x3214, N, N, N, 0xb18, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(touch_clk_pv7, TOUCH, RSVD1, RSVD2, RSVD3, 0x3218, N, N, N, 0xb10, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(modem_wake_ap_px0, RSVD0, RSVD1, RSVD2, RSVD3, 0x321c, N, N, N, 0xa48, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(touch_int_px1, RSVD0, RSVD1, RSVD2, RSVD3, 0x3220, N, N, N, 0xb14, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(motion_int_px2, RSVD0, RSVD1, RSVD2, RSVD3, 0x3224, N, N, N, 0xa4c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(als_prox_int_px3, RSVD0, RSVD1, RSVD2, RSVD3, 0x3228, N, N, N, 0x8e4, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(temp_alert_px4, RSVD0, RSVD1, RSVD2, RSVD3, 0x322c, N, N, N, 0xb0c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(button_power_on_px5, RSVD0, RSVD1, RSVD2, RSVD3, 0x3230, N, N, N, 0x908, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(button_vol_up_px6, RSVD0, RSVD1, RSVD2, RSVD3, 0x3234, N, N, N, 0x914, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(button_vol_down_px7, RSVD0, RSVD1, RSVD2, RSVD3, 0x3238, N, N, N, 0x910, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(button_slide_sw_py0, RSVD0, RSVD1, RSVD2, RSVD3, 0x323c, N, N, N, 0x90c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(button_home_py1, RSVD0, RSVD1, RSVD2, RSVD3, 0x3240, N, N, N, 0x904, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pa6, SATA, RSVD1, RSVD2, RSVD3, 0x3244, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pe6, RSVD0, I2S5A, PWM2, RSVD3, 0x3248, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pe7, RSVD0, I2S5A, PWM3, RSVD3, 0x324c, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(ph6, RSVD0, RSVD1, RSVD2, RSVD3, 0x3250, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pk0, IQC0, I2S5B, RSVD2, RSVD3, 0x3254, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pk1, IQC0, I2S5B, RSVD2, RSVD3, 0x3258, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pk2, IQC0, I2S5B, RSVD2, RSVD3, 0x325c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pk3, IQC0, I2S5B, RSVD2, RSVD3, 0x3260, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pk4, IQC1, RSVD1, RSVD2, RSVD3, 0x3264, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pk5, IQC1, RSVD1, RSVD2, RSVD3, 0x3268, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pk6, IQC1, RSVD1, RSVD2, RSVD3, 0x326c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pk7, IQC1, RSVD1, RSVD2, RSVD3, 0x3270, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pl0, RSVD0, RSVD1, RSVD2, RSVD3, 0x3274, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pl1, SOC, RSVD1, RSVD2, RSVD3, 0x3278, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pz0, VIMCLK2, RSVD1, RSVD2, RSVD3, 0x327c, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pz1, VIMCLK2, SDMMC1, RSVD2, RSVD3, 0x3280, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pz2, SDMMC3, CCLA, RSVD2, RSVD3, 0x3284, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pz3, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3288, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pz4, SDMMC1, RSVD1, RSVD2, RSVD3, 0x328c, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pz5, SOC, RSVD1, RSVD2, RSVD3, 0x3290, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - - /* pg_name, r, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */ - DRV_PINGROUP(pa6, 0x9c0, 12, 5, 20, 5, -1, -1, -1, -1), - DRV_PINGROUP(pcc7, 0x9c4, 12, 5, 20, 5, -1, -1, -1, -1), - DRV_PINGROUP(pe6, 0x9c8, 12, 5, 20, 5, -1, -1, -1, -1), - DRV_PINGROUP(pe7, 0x9cc, 12, 5, 20, 5, -1, -1, -1, -1), - DRV_PINGROUP(ph6, 0x9d0, 12, 5, 20, 5, -1, -1, -1, -1), - DRV_PINGROUP(pk0, 0x9d4, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pk1, 0x9d8, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pk2, 0x9dc, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pk3, 0x9e0, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pk4, 0x9e4, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pk5, 0x9e8, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pk6, 0x9ec, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pk7, 0x9f0, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pl0, 0x9f4, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pl1, 0x9f8, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pz0, 0x9fc, 12, 7, 20, 7, -1, -1, -1, -1), - DRV_PINGROUP(pz1, 0xa00, 12, 7, 20, 7, -1, -1, -1, -1), - DRV_PINGROUP(pz2, 0xa04, 12, 7, 20, 7, -1, -1, -1, -1), - DRV_PINGROUP(pz3, 0xa08, 12, 7, 20, 7, -1, -1, -1, -1), - DRV_PINGROUP(pz4, 0xa0c, 12, 7, 20, 7, -1, -1, -1, -1), - DRV_PINGROUP(pz5, 0xa10, 12, 7, 20, 7, -1, -1, -1, -1), - DRV_PINGROUP(sdmmc1, 0xa98, 12, 7, 20, 7, 28, 2, 30, 2), - DRV_PINGROUP(sdmmc2, 0xa9c, 2, 6, 8, 6, 28, 2, 30, 2), - DRV_PINGROUP(sdmmc3, 0xab0, 12, 7, 20, 7, 28, 2, 30, 2), - DRV_PINGROUP(sdmmc4, 0xab4, 2, 6, 8, 6, 28, 2, 30, 2), -}; - -static const struct tegra_pinctrl_soc_data tegra210_pinctrl = { - .ngpios = NUM_GPIOS, - .pins = tegra210_pins, - .npins = ARRAY_SIZE(tegra210_pins), - .functions = tegra210_functions, - .nfunctions = ARRAY_SIZE(tegra210_functions), - .groups = tegra210_groups, - .ngroups = ARRAY_SIZE(tegra210_groups), - .hsm_in_mux = true, - .schmitt_in_mux = true, - .drvtype_in_mux = true, -}; - -static int tegra210_pinctrl_probe(struct platform_device *pdev) -{ - return tegra_pinctrl_probe(pdev, &tegra210_pinctrl); -} - -static const struct of_device_id tegra210_pinctrl_of_match[] = { - { .compatible = "nvidia,tegra210-pinmux", }, - { }, -}; -MODULE_DEVICE_TABLE(of, tegra210_pinctrl_of_match); - -static struct platform_driver tegra210_pinctrl_driver = { - .driver = { - .name = "tegra210-pinctrl", - .of_match_table = tegra210_pinctrl_of_match, - }, - .probe = tegra210_pinctrl_probe, - .remove = tegra_pinctrl_remove, -}; -module_platform_driver(tegra210_pinctrl_driver); - -MODULE_AUTHOR("NVIDIA"); -MODULE_DESCRIPTION("NVIDIA Tegra210 pinctrl driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c deleted file mode 100644 index 47b2fd8bb2e9..000000000000 --- a/drivers/pinctrl/pinctrl-tegra30.c +++ /dev/null @@ -1,2507 +0,0 @@ -/* - * Pinctrl data for the NVIDIA Tegra30 pinmux - * - * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - */ - -#include -#include -#include -#include -#include - -#include "pinctrl-tegra.h" - -/* - * Most pins affected by the pinmux can also be GPIOs. Define these first. - * These must match how the GPIO driver names/numbers its pins. - */ -#define _GPIO(offset) (offset) - -#define TEGRA_PIN_CLK_32K_OUT_PA0 _GPIO(0) -#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) -#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) -#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) -#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) -#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) -#define TEGRA_PIN_SDMMC3_CLK_PA6 _GPIO(6) -#define TEGRA_PIN_SDMMC3_CMD_PA7 _GPIO(7) -#define TEGRA_PIN_GMI_A17_PB0 _GPIO(8) -#define TEGRA_PIN_GMI_A18_PB1 _GPIO(9) -#define TEGRA_PIN_LCD_PWR0_PB2 _GPIO(10) -#define TEGRA_PIN_LCD_PCLK_PB3 _GPIO(11) -#define TEGRA_PIN_SDMMC3_DAT3_PB4 _GPIO(12) -#define TEGRA_PIN_SDMMC3_DAT2_PB5 _GPIO(13) -#define TEGRA_PIN_SDMMC3_DAT1_PB6 _GPIO(14) -#define TEGRA_PIN_SDMMC3_DAT0_PB7 _GPIO(15) -#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) -#define TEGRA_PIN_LCD_PWR1_PC1 _GPIO(17) -#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) -#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) -#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) -#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) -#define TEGRA_PIN_LCD_PWR2_PC6 _GPIO(22) -#define TEGRA_PIN_GMI_WP_N_PC7 _GPIO(23) -#define TEGRA_PIN_SDMMC3_DAT5_PD0 _GPIO(24) -#define TEGRA_PIN_SDMMC3_DAT4_PD1 _GPIO(25) -#define TEGRA_PIN_LCD_DC1_PD2 _GPIO(26) -#define TEGRA_PIN_SDMMC3_DAT6_PD3 _GPIO(27) -#define TEGRA_PIN_SDMMC3_DAT7_PD4 _GPIO(28) -#define TEGRA_PIN_VI_D1_PD5 _GPIO(29) -#define TEGRA_PIN_VI_VSYNC_PD6 _GPIO(30) -#define TEGRA_PIN_VI_HSYNC_PD7 _GPIO(31) -#define TEGRA_PIN_LCD_D0_PE0 _GPIO(32) -#define TEGRA_PIN_LCD_D1_PE1 _GPIO(33) -#define TEGRA_PIN_LCD_D2_PE2 _GPIO(34) -#define TEGRA_PIN_LCD_D3_PE3 _GPIO(35) -#define TEGRA_PIN_LCD_D4_PE4 _GPIO(36) -#define TEGRA_PIN_LCD_D5_PE5 _GPIO(37) -#define TEGRA_PIN_LCD_D6_PE6 _GPIO(38) -#define TEGRA_PIN_LCD_D7_PE7 _GPIO(39) -#define TEGRA_PIN_LCD_D8_PF0 _GPIO(40) -#define TEGRA_PIN_LCD_D9_PF1 _GPIO(41) -#define TEGRA_PIN_LCD_D10_PF2 _GPIO(42) -#define TEGRA_PIN_LCD_D11_PF3 _GPIO(43) -#define TEGRA_PIN_LCD_D12_PF4 _GPIO(44) -#define TEGRA_PIN_LCD_D13_PF5 _GPIO(45) -#define TEGRA_PIN_LCD_D14_PF6 _GPIO(46) -#define TEGRA_PIN_LCD_D15_PF7 _GPIO(47) -#define TEGRA_PIN_GMI_AD0_PG0 _GPIO(48) -#define TEGRA_PIN_GMI_AD1_PG1 _GPIO(49) -#define TEGRA_PIN_GMI_AD2_PG2 _GPIO(50) -#define TEGRA_PIN_GMI_AD3_PG3 _GPIO(51) -#define TEGRA_PIN_GMI_AD4_PG4 _GPIO(52) -#define TEGRA_PIN_GMI_AD5_PG5 _GPIO(53) -#define TEGRA_PIN_GMI_AD6_PG6 _GPIO(54) -#define TEGRA_PIN_GMI_AD7_PG7 _GPIO(55) -#define TEGRA_PIN_GMI_AD8_PH0 _GPIO(56) -#define TEGRA_PIN_GMI_AD9_PH1 _GPIO(57) -#define TEGRA_PIN_GMI_AD10_PH2 _GPIO(58) -#define TEGRA_PIN_GMI_AD11_PH3 _GPIO(59) -#define TEGRA_PIN_GMI_AD12_PH4 _GPIO(60) -#define TEGRA_PIN_GMI_AD13_PH5 _GPIO(61) -#define TEGRA_PIN_GMI_AD14_PH6 _GPIO(62) -#define TEGRA_PIN_GMI_AD15_PH7 _GPIO(63) -#define TEGRA_PIN_GMI_WR_N_PI0 _GPIO(64) -#define TEGRA_PIN_GMI_OE_N_PI1 _GPIO(65) -#define TEGRA_PIN_GMI_DQS_PI2 _GPIO(66) -#define TEGRA_PIN_GMI_CS6_N_PI3 _GPIO(67) -#define TEGRA_PIN_GMI_RST_N_PI4 _GPIO(68) -#define TEGRA_PIN_GMI_IORDY_PI5 _GPIO(69) -#define TEGRA_PIN_GMI_CS7_N_PI6 _GPIO(70) -#define TEGRA_PIN_GMI_WAIT_PI7 _GPIO(71) -#define TEGRA_PIN_GMI_CS0_N_PJ0 _GPIO(72) -#define TEGRA_PIN_LCD_DE_PJ1 _GPIO(73) -#define TEGRA_PIN_GMI_CS1_N_PJ2 _GPIO(74) -#define TEGRA_PIN_LCD_HSYNC_PJ3 _GPIO(75) -#define TEGRA_PIN_LCD_VSYNC_PJ4 _GPIO(76) -#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) -#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) -#define TEGRA_PIN_GMI_A16_PJ7 _GPIO(79) -#define TEGRA_PIN_GMI_ADV_N_PK0 _GPIO(80) -#define TEGRA_PIN_GMI_CLK_PK1 _GPIO(81) -#define TEGRA_PIN_GMI_CS4_N_PK2 _GPIO(82) -#define TEGRA_PIN_GMI_CS2_N_PK3 _GPIO(83) -#define TEGRA_PIN_GMI_CS3_N_PK4 _GPIO(84) -#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) -#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) -#define TEGRA_PIN_GMI_A19_PK7 _GPIO(87) -#define TEGRA_PIN_VI_D2_PL0 _GPIO(88) -#define TEGRA_PIN_VI_D3_PL1 _GPIO(89) -#define TEGRA_PIN_VI_D4_PL2 _GPIO(90) -#define TEGRA_PIN_VI_D5_PL3 _GPIO(91) -#define TEGRA_PIN_VI_D6_PL4 _GPIO(92) -#define TEGRA_PIN_VI_D7_PL5 _GPIO(93) -#define TEGRA_PIN_VI_D8_PL6 _GPIO(94) -#define TEGRA_PIN_VI_D9_PL7 _GPIO(95) -#define TEGRA_PIN_LCD_D16_PM0 _GPIO(96) -#define TEGRA_PIN_LCD_D17_PM1 _GPIO(97) -#define TEGRA_PIN_LCD_D18_PM2 _GPIO(98) -#define TEGRA_PIN_LCD_D19_PM3 _GPIO(99) -#define TEGRA_PIN_LCD_D20_PM4 _GPIO(100) -#define TEGRA_PIN_LCD_D21_PM5 _GPIO(101) -#define TEGRA_PIN_LCD_D22_PM6 _GPIO(102) -#define TEGRA_PIN_LCD_D23_PM7 _GPIO(103) -#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) -#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) -#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) -#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) -#define TEGRA_PIN_LCD_CS0_N_PN4 _GPIO(108) -#define TEGRA_PIN_LCD_SDOUT_PN5 _GPIO(109) -#define TEGRA_PIN_LCD_DC0_PN6 _GPIO(110) -#define TEGRA_PIN_HDMI_INT_PN7 _GPIO(111) -#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) -#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) -#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) -#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) -#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) -#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) -#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) -#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) -#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) -#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) -#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) -#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) -#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) -#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) -#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) -#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) -#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) -#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) -#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) -#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) -#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) -#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) -#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) -#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) -#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) -#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) -#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) -#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) -#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) -#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) -#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) -#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) -#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) -#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) -#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) -#define TEGRA_PIN_KB_ROW11_PS3 _GPIO(147) -#define TEGRA_PIN_KB_ROW12_PS4 _GPIO(148) -#define TEGRA_PIN_KB_ROW13_PS5 _GPIO(149) -#define TEGRA_PIN_KB_ROW14_PS6 _GPIO(150) -#define TEGRA_PIN_KB_ROW15_PS7 _GPIO(151) -#define TEGRA_PIN_VI_PCLK_PT0 _GPIO(152) -#define TEGRA_PIN_VI_MCLK_PT1 _GPIO(153) -#define TEGRA_PIN_VI_D10_PT2 _GPIO(154) -#define TEGRA_PIN_VI_D11_PT3 _GPIO(155) -#define TEGRA_PIN_VI_D0_PT4 _GPIO(156) -#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) -#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) -#define TEGRA_PIN_SDMMC4_CMD_PT7 _GPIO(159) -#define TEGRA_PIN_PU0 _GPIO(160) -#define TEGRA_PIN_PU1 _GPIO(161) -#define TEGRA_PIN_PU2 _GPIO(162) -#define TEGRA_PIN_PU3 _GPIO(163) -#define TEGRA_PIN_PU4 _GPIO(164) -#define TEGRA_PIN_PU5 _GPIO(165) -#define TEGRA_PIN_PU6 _GPIO(166) -#define TEGRA_PIN_JTAG_RTCK_PU7 _GPIO(167) -#define TEGRA_PIN_PV0 _GPIO(168) -#define TEGRA_PIN_PV1 _GPIO(169) -#define TEGRA_PIN_PV2 _GPIO(170) -#define TEGRA_PIN_PV3 _GPIO(171) -#define TEGRA_PIN_DDC_SCL_PV4 _GPIO(172) -#define TEGRA_PIN_DDC_SDA_PV5 _GPIO(173) -#define TEGRA_PIN_CRT_HSYNC_PV6 _GPIO(174) -#define TEGRA_PIN_CRT_VSYNC_PV7 _GPIO(175) -#define TEGRA_PIN_LCD_CS1_N_PW0 _GPIO(176) -#define TEGRA_PIN_LCD_M1_PW1 _GPIO(177) -#define TEGRA_PIN_SPI2_CS1_N_PW2 _GPIO(178) -#define TEGRA_PIN_SPI2_CS2_N_PW3 _GPIO(179) -#define TEGRA_PIN_CLK1_OUT_PW4 _GPIO(180) -#define TEGRA_PIN_CLK2_OUT_PW5 _GPIO(181) -#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) -#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) -#define TEGRA_PIN_SPI2_MOSI_PX0 _GPIO(184) -#define TEGRA_PIN_SPI2_MISO_PX1 _GPIO(185) -#define TEGRA_PIN_SPI2_SCK_PX2 _GPIO(186) -#define TEGRA_PIN_SPI2_CS0_N_PX3 _GPIO(187) -#define TEGRA_PIN_SPI1_MOSI_PX4 _GPIO(188) -#define TEGRA_PIN_SPI1_SCK_PX5 _GPIO(189) -#define TEGRA_PIN_SPI1_CS0_N_PX6 _GPIO(190) -#define TEGRA_PIN_SPI1_MISO_PX7 _GPIO(191) -#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) -#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) -#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) -#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) -#define TEGRA_PIN_SDMMC1_DAT3_PY4 _GPIO(196) -#define TEGRA_PIN_SDMMC1_DAT2_PY5 _GPIO(197) -#define TEGRA_PIN_SDMMC1_DAT1_PY6 _GPIO(198) -#define TEGRA_PIN_SDMMC1_DAT0_PY7 _GPIO(199) -#define TEGRA_PIN_SDMMC1_CLK_PZ0 _GPIO(200) -#define TEGRA_PIN_SDMMC1_CMD_PZ1 _GPIO(201) -#define TEGRA_PIN_LCD_SDIN_PZ2 _GPIO(202) -#define TEGRA_PIN_LCD_WR_N_PZ3 _GPIO(203) -#define TEGRA_PIN_LCD_SCK_PZ4 _GPIO(204) -#define TEGRA_PIN_SYS_CLK_REQ_PZ5 _GPIO(205) -#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) -#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) -#define TEGRA_PIN_SDMMC4_DAT0_PAA0 _GPIO(208) -#define TEGRA_PIN_SDMMC4_DAT1_PAA1 _GPIO(209) -#define TEGRA_PIN_SDMMC4_DAT2_PAA2 _GPIO(210) -#define TEGRA_PIN_SDMMC4_DAT3_PAA3 _GPIO(211) -#define TEGRA_PIN_SDMMC4_DAT4_PAA4 _GPIO(212) -#define TEGRA_PIN_SDMMC4_DAT5_PAA5 _GPIO(213) -#define TEGRA_PIN_SDMMC4_DAT6_PAA6 _GPIO(214) -#define TEGRA_PIN_SDMMC4_DAT7_PAA7 _GPIO(215) -#define TEGRA_PIN_PBB0 _GPIO(216) -#define TEGRA_PIN_CAM_I2C_SCL_PBB1 _GPIO(217) -#define TEGRA_PIN_CAM_I2C_SDA_PBB2 _GPIO(218) -#define TEGRA_PIN_PBB3 _GPIO(219) -#define TEGRA_PIN_PBB4 _GPIO(220) -#define TEGRA_PIN_PBB5 _GPIO(221) -#define TEGRA_PIN_PBB6 _GPIO(222) -#define TEGRA_PIN_PBB7 _GPIO(223) -#define TEGRA_PIN_CAM_MCLK_PCC0 _GPIO(224) -#define TEGRA_PIN_PCC1 _GPIO(225) -#define TEGRA_PIN_PCC2 _GPIO(226) -#define TEGRA_PIN_SDMMC4_RST_N_PCC3 _GPIO(227) -#define TEGRA_PIN_SDMMC4_CLK_PCC4 _GPIO(228) -#define TEGRA_PIN_CLK2_REQ_PCC5 _GPIO(229) -#define TEGRA_PIN_PEX_L2_RST_N_PCC6 _GPIO(230) -#define TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7 _GPIO(231) -#define TEGRA_PIN_PEX_L0_PRSNT_N_PDD0 _GPIO(232) -#define TEGRA_PIN_PEX_L0_RST_N_PDD1 _GPIO(233) -#define TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2 _GPIO(234) -#define TEGRA_PIN_PEX_WAKE_N_PDD3 _GPIO(235) -#define TEGRA_PIN_PEX_L1_PRSNT_N_PDD4 _GPIO(236) -#define TEGRA_PIN_PEX_L1_RST_N_PDD5 _GPIO(237) -#define TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6 _GPIO(238) -#define TEGRA_PIN_PEX_L2_PRSNT_N_PDD7 _GPIO(239) -#define TEGRA_PIN_CLK3_OUT_PEE0 _GPIO(240) -#define TEGRA_PIN_CLK3_REQ_PEE1 _GPIO(241) -#define TEGRA_PIN_CLK1_REQ_PEE2 _GPIO(242) -#define TEGRA_PIN_HDMI_CEC_PEE3 _GPIO(243) -#define TEGRA_PIN_PEE4 _GPIO(244) -#define TEGRA_PIN_PEE5 _GPIO(245) -#define TEGRA_PIN_PEE6 _GPIO(246) -#define TEGRA_PIN_PEE7 _GPIO(247) - -/* All non-GPIO pins follow */ -#define NUM_GPIOS (TEGRA_PIN_PEE7 + 1) -#define _PIN(offset) (NUM_GPIOS + (offset)) - -/* Non-GPIO pins */ -#define TEGRA_PIN_CLK_32K_IN _PIN(0) -#define TEGRA_PIN_CORE_PWR_REQ _PIN(1) -#define TEGRA_PIN_CPU_PWR_REQ _PIN(2) -#define TEGRA_PIN_JTAG_TCK _PIN(3) -#define TEGRA_PIN_JTAG_TDI _PIN(4) -#define TEGRA_PIN_JTAG_TDO _PIN(5) -#define TEGRA_PIN_JTAG_TMS _PIN(6) -#define TEGRA_PIN_JTAG_TRST_N _PIN(7) -#define TEGRA_PIN_OWR _PIN(8) -#define TEGRA_PIN_PWR_INT_N _PIN(9) -#define TEGRA_PIN_SYS_RESET_N _PIN(10) -#define TEGRA_PIN_TEST_MODE_EN _PIN(11) - -static const struct pinctrl_pin_desc tegra30_pins[] = { - PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"), - PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), - PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), - PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"), - PINCTRL_PIN(TEGRA_PIN_GMI_A17_PB0, "GMI_A17 PB0"), - PINCTRL_PIN(TEGRA_PIN_GMI_A18_PB1, "GMI_A18 PB1"), - PINCTRL_PIN(TEGRA_PIN_LCD_PWR0_PB2, "LCD_PWR0 PB2"), - PINCTRL_PIN(TEGRA_PIN_LCD_PCLK_PB3, "LCD_PCLK PB3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"), - PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), - PINCTRL_PIN(TEGRA_PIN_LCD_PWR1_PC1, "LCD_PWR1 PC1"), - PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), - PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), - PINCTRL_PIN(TEGRA_PIN_LCD_PWR2_PC6, "LCD_PWR2 PC6"), - PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT5_PD0, "SDMMC3_DAT5 PD0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT4_PD1, "SDMMC3_DAT4 PD1"), - PINCTRL_PIN(TEGRA_PIN_LCD_DC1_PD2, "LCD_DC1 PD2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT6_PD3, "SDMMC3_DAT6 PD3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT7_PD4, "SDMMC3_DAT7 PD4"), - PINCTRL_PIN(TEGRA_PIN_VI_D1_PD5, "VI_D1 PD5"), - PINCTRL_PIN(TEGRA_PIN_VI_VSYNC_PD6, "VI_VSYNC PD6"), - PINCTRL_PIN(TEGRA_PIN_VI_HSYNC_PD7, "VI_HSYNC PD7"), - PINCTRL_PIN(TEGRA_PIN_LCD_D0_PE0, "LCD_D0 PE0"), - PINCTRL_PIN(TEGRA_PIN_LCD_D1_PE1, "LCD_D1 PE1"), - PINCTRL_PIN(TEGRA_PIN_LCD_D2_PE2, "LCD_D2 PE2"), - PINCTRL_PIN(TEGRA_PIN_LCD_D3_PE3, "LCD_D3 PE3"), - PINCTRL_PIN(TEGRA_PIN_LCD_D4_PE4, "LCD_D4 PE4"), - PINCTRL_PIN(TEGRA_PIN_LCD_D5_PE5, "LCD_D5 PE5"), - PINCTRL_PIN(TEGRA_PIN_LCD_D6_PE6, "LCD_D6 PE6"), - PINCTRL_PIN(TEGRA_PIN_LCD_D7_PE7, "LCD_D7 PE7"), - PINCTRL_PIN(TEGRA_PIN_LCD_D8_PF0, "LCD_D8 PF0"), - PINCTRL_PIN(TEGRA_PIN_LCD_D9_PF1, "LCD_D9 PF1"), - PINCTRL_PIN(TEGRA_PIN_LCD_D10_PF2, "LCD_D10 PF2"), - PINCTRL_PIN(TEGRA_PIN_LCD_D11_PF3, "LCD_D11 PF3"), - PINCTRL_PIN(TEGRA_PIN_LCD_D12_PF4, "LCD_D12 PF4"), - PINCTRL_PIN(TEGRA_PIN_LCD_D13_PF5, "LCD_D13 PF5"), - PINCTRL_PIN(TEGRA_PIN_LCD_D14_PF6, "LCD_D14 PF6"), - PINCTRL_PIN(TEGRA_PIN_LCD_D15_PF7, "LCD_D15 PF7"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"), - PINCTRL_PIN(TEGRA_PIN_GMI_WR_N_PI0, "GMI_WR_N PI0"), - PINCTRL_PIN(TEGRA_PIN_GMI_OE_N_PI1, "GMI_OE_N PI1"), - PINCTRL_PIN(TEGRA_PIN_GMI_DQS_PI2, "GMI_DQS PI2"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"), - PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"), - PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"), - PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"), - PINCTRL_PIN(TEGRA_PIN_LCD_DE_PJ1, "LCD_DE PJ1"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"), - PINCTRL_PIN(TEGRA_PIN_LCD_HSYNC_PJ3, "LCD_HSYNC PJ3"), - PINCTRL_PIN(TEGRA_PIN_LCD_VSYNC_PJ4, "LCD_VSYNC PJ4"), - PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), - PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), - PINCTRL_PIN(TEGRA_PIN_GMI_A16_PJ7, "GMI_A16 PJ7"), - PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"), - PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), - PINCTRL_PIN(TEGRA_PIN_GMI_A19_PK7, "GMI_A19 PK7"), - PINCTRL_PIN(TEGRA_PIN_VI_D2_PL0, "VI_D2 PL0"), - PINCTRL_PIN(TEGRA_PIN_VI_D3_PL1, "VI_D3 PL1"), - PINCTRL_PIN(TEGRA_PIN_VI_D4_PL2, "VI_D4 PL2"), - PINCTRL_PIN(TEGRA_PIN_VI_D5_PL3, "VI_D5 PL3"), - PINCTRL_PIN(TEGRA_PIN_VI_D6_PL4, "VI_D6 PL4"), - PINCTRL_PIN(TEGRA_PIN_VI_D7_PL5, "VI_D7 PL5"), - PINCTRL_PIN(TEGRA_PIN_VI_D8_PL6, "VI_D8 PL6"), - PINCTRL_PIN(TEGRA_PIN_VI_D9_PL7, "VI_D9 PL7"), - PINCTRL_PIN(TEGRA_PIN_LCD_D16_PM0, "LCD_D16 PM0"), - PINCTRL_PIN(TEGRA_PIN_LCD_D17_PM1, "LCD_D17 PM1"), - PINCTRL_PIN(TEGRA_PIN_LCD_D18_PM2, "LCD_D18 PM2"), - PINCTRL_PIN(TEGRA_PIN_LCD_D19_PM3, "LCD_D19 PM3"), - PINCTRL_PIN(TEGRA_PIN_LCD_D20_PM4, "LCD_D20 PM4"), - PINCTRL_PIN(TEGRA_PIN_LCD_D21_PM5, "LCD_D21 PM5"), - PINCTRL_PIN(TEGRA_PIN_LCD_D22_PM6, "LCD_D22 PM6"), - PINCTRL_PIN(TEGRA_PIN_LCD_D23_PM7, "LCD_D23 PM7"), - PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), - PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), - PINCTRL_PIN(TEGRA_PIN_LCD_CS0_N_PN4, "LCD_CS0_N PN4"), - PINCTRL_PIN(TEGRA_PIN_LCD_SDOUT_PN5, "LCD_SDOUT PN5"), - PINCTRL_PIN(TEGRA_PIN_LCD_DC0_PN6, "LCD_DC0 PN6"), - PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), - PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), - PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), - PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), - PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), - PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), - PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), - PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), - PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), - PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), - PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), - PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), - PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), - PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), - PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"), - PINCTRL_PIN(TEGRA_PIN_VI_PCLK_PT0, "VI_PCLK PT0"), - PINCTRL_PIN(TEGRA_PIN_VI_MCLK_PT1, "VI_MCLK PT1"), - PINCTRL_PIN(TEGRA_PIN_VI_D10_PT2, "VI_D10 PT2"), - PINCTRL_PIN(TEGRA_PIN_VI_D11_PT3, "VI_D11 PT3"), - PINCTRL_PIN(TEGRA_PIN_VI_D0_PT4, "VI_D0 PT4"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"), - PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), - PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), - PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), - PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), - PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), - PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), - PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), - PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK_PU7, "JTAG_RTCK PU7"), - PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), - PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), - PINCTRL_PIN(TEGRA_PIN_PV2, "PV2"), - PINCTRL_PIN(TEGRA_PIN_PV3, "PV3"), - PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"), - PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"), - PINCTRL_PIN(TEGRA_PIN_CRT_HSYNC_PV6, "CRT_HSYNC PV6"), - PINCTRL_PIN(TEGRA_PIN_CRT_VSYNC_PV7, "CRT_VSYNC PV7"), - PINCTRL_PIN(TEGRA_PIN_LCD_CS1_N_PW0, "LCD_CS1_N PW0"), - PINCTRL_PIN(TEGRA_PIN_LCD_M1_PW1, "LCD_M1 PW1"), - PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_N_PW2, "SPI2_CS1_N PW2"), - PINCTRL_PIN(TEGRA_PIN_SPI2_CS2_N_PW3, "SPI2_CS2_N PW3"), - PINCTRL_PIN(TEGRA_PIN_CLK1_OUT_PW4, "CLK1_OUT PW4"), - PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"), - PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), - PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), - PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PX0, "SPI2_MOSI PX0"), - PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PX1, "SPI2_MISO PX1"), - PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PX2, "SPI2_SCK PX2"), - PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_N_PX3, "SPI2_CS0_N PX3"), - PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PX4, "SPI1_MOSI PX4"), - PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PX5, "SPI1_SCK PX5"), - PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_N_PX6, "SPI1_CS0_N PX6"), - PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PX7, "SPI1_MISO PX7"), - PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), - PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), - PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"), - PINCTRL_PIN(TEGRA_PIN_LCD_SDIN_PZ2, "LCD_SDIN PZ2"), - PINCTRL_PIN(TEGRA_PIN_LCD_WR_N_PZ3, "LCD_WR_N PZ3"), - PINCTRL_PIN(TEGRA_PIN_LCD_SCK_PZ4, "LCD_SCK PZ4"), - PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"), - PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"), - PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"), - PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"), - PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"), - PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), - PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), - PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"), - PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"), - PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_RST_N_PCC3, "SDMMC4_RST_N PCC3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"), - PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"), - PINCTRL_PIN(TEGRA_PIN_PEX_L2_RST_N_PCC6, "PEX_L2_RST_N PCC6"), - PINCTRL_PIN(TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7, "PEX_L2_CLKREQ_N PCC7"), - PINCTRL_PIN(TEGRA_PIN_PEX_L0_PRSNT_N_PDD0, "PEX_L0_PRSNT_N PDD0"), - PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PDD1, "PEX_L0_RST_N PDD1"), - PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, "PEX_L0_CLKREQ_N PDD2"), - PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PDD3, "PEX_WAKE_N PDD3"), - PINCTRL_PIN(TEGRA_PIN_PEX_L1_PRSNT_N_PDD4, "PEX_L1_PRSNT_N PDD4"), - PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PDD5, "PEX_L1_RST_N PDD5"), - PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, "PEX_L1_CLKREQ_N PDD6"), - PINCTRL_PIN(TEGRA_PIN_PEX_L2_PRSNT_N_PDD7, "PEX_L2_PRSNT_N PDD7"), - PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"), - PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"), - PINCTRL_PIN(TEGRA_PIN_CLK1_REQ_PEE2, "CLK1_REQ PEE2"), - PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"), - PINCTRL_PIN(TEGRA_PIN_PEE4, "PEE4"), - PINCTRL_PIN(TEGRA_PIN_PEE5, "PEE5"), - PINCTRL_PIN(TEGRA_PIN_PEE6, "PEE6"), - PINCTRL_PIN(TEGRA_PIN_PEE7, "PEE7"), - PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), - PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TCK, "JTAG_TCK"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TDI, "JTAG_TDI"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TDO, "JTAG_TDO"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TMS, "JTAG_TMS"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TRST_N, "JTAG_TRST_N"), - PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"), - PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), - PINCTRL_PIN(TEGRA_PIN_SYS_RESET_N, "SYS_RESET_N"), - PINCTRL_PIN(TEGRA_PIN_TEST_MODE_EN, "TEST_MODE_EN"), -}; - -static const unsigned clk_32k_out_pa0_pins[] = { - TEGRA_PIN_CLK_32K_OUT_PA0, -}; - -static const unsigned uart3_cts_n_pa1_pins[] = { - TEGRA_PIN_UART3_CTS_N_PA1, -}; - -static const unsigned dap2_fs_pa2_pins[] = { - TEGRA_PIN_DAP2_FS_PA2, -}; - -static const unsigned dap2_sclk_pa3_pins[] = { - TEGRA_PIN_DAP2_SCLK_PA3, -}; - -static const unsigned dap2_din_pa4_pins[] = { - TEGRA_PIN_DAP2_DIN_PA4, -}; - -static const unsigned dap2_dout_pa5_pins[] = { - TEGRA_PIN_DAP2_DOUT_PA5, -}; - -static const unsigned sdmmc3_clk_pa6_pins[] = { - TEGRA_PIN_SDMMC3_CLK_PA6, -}; - -static const unsigned sdmmc3_cmd_pa7_pins[] = { - TEGRA_PIN_SDMMC3_CMD_PA7, -}; - -static const unsigned gmi_a17_pb0_pins[] = { - TEGRA_PIN_GMI_A17_PB0, -}; - -static const unsigned gmi_a18_pb1_pins[] = { - TEGRA_PIN_GMI_A18_PB1, -}; - -static const unsigned lcd_pwr0_pb2_pins[] = { - TEGRA_PIN_LCD_PWR0_PB2, -}; - -static const unsigned lcd_pclk_pb3_pins[] = { - TEGRA_PIN_LCD_PCLK_PB3, -}; - -static const unsigned sdmmc3_dat3_pb4_pins[] = { - TEGRA_PIN_SDMMC3_DAT3_PB4, -}; - -static const unsigned sdmmc3_dat2_pb5_pins[] = { - TEGRA_PIN_SDMMC3_DAT2_PB5, -}; - -static const unsigned sdmmc3_dat1_pb6_pins[] = { - TEGRA_PIN_SDMMC3_DAT1_PB6, -}; - -static const unsigned sdmmc3_dat0_pb7_pins[] = { - TEGRA_PIN_SDMMC3_DAT0_PB7, -}; - -static const unsigned uart3_rts_n_pc0_pins[] = { - TEGRA_PIN_UART3_RTS_N_PC0, -}; - -static const unsigned lcd_pwr1_pc1_pins[] = { - TEGRA_PIN_LCD_PWR1_PC1, -}; - -static const unsigned uart2_txd_pc2_pins[] = { - TEGRA_PIN_UART2_TXD_PC2, -}; - -static const unsigned uart2_rxd_pc3_pins[] = { - TEGRA_PIN_UART2_RXD_PC3, -}; - -static const unsigned gen1_i2c_scl_pc4_pins[] = { - TEGRA_PIN_GEN1_I2C_SCL_PC4, -}; - -static const unsigned gen1_i2c_sda_pc5_pins[] = { - TEGRA_PIN_GEN1_I2C_SDA_PC5, -}; - -static const unsigned lcd_pwr2_pc6_pins[] = { - TEGRA_PIN_LCD_PWR2_PC6, -}; - -static const unsigned gmi_wp_n_pc7_pins[] = { - TEGRA_PIN_GMI_WP_N_PC7, -}; - -static const unsigned sdmmc3_dat5_pd0_pins[] = { - TEGRA_PIN_SDMMC3_DAT5_PD0, -}; - -static const unsigned sdmmc3_dat4_pd1_pins[] = { - TEGRA_PIN_SDMMC3_DAT4_PD1, -}; - -static const unsigned lcd_dc1_pd2_pins[] = { - TEGRA_PIN_LCD_DC1_PD2, -}; - -static const unsigned sdmmc3_dat6_pd3_pins[] = { - TEGRA_PIN_SDMMC3_DAT6_PD3, -}; - -static const unsigned sdmmc3_dat7_pd4_pins[] = { - TEGRA_PIN_SDMMC3_DAT7_PD4, -}; - -static const unsigned vi_d1_pd5_pins[] = { - TEGRA_PIN_VI_D1_PD5, -}; - -static const unsigned vi_vsync_pd6_pins[] = { - TEGRA_PIN_VI_VSYNC_PD6, -}; - -static const unsigned vi_hsync_pd7_pins[] = { - TEGRA_PIN_VI_HSYNC_PD7, -}; - -static const unsigned lcd_d0_pe0_pins[] = { - TEGRA_PIN_LCD_D0_PE0, -}; - -static const unsigned lcd_d1_pe1_pins[] = { - TEGRA_PIN_LCD_D1_PE1, -}; - -static const unsigned lcd_d2_pe2_pins[] = { - TEGRA_PIN_LCD_D2_PE2, -}; - -static const unsigned lcd_d3_pe3_pins[] = { - TEGRA_PIN_LCD_D3_PE3, -}; - -static const unsigned lcd_d4_pe4_pins[] = { - TEGRA_PIN_LCD_D4_PE4, -}; - -static const unsigned lcd_d5_pe5_pins[] = { - TEGRA_PIN_LCD_D5_PE5, -}; - -static const unsigned lcd_d6_pe6_pins[] = { - TEGRA_PIN_LCD_D6_PE6, -}; - -static const unsigned lcd_d7_pe7_pins[] = { - TEGRA_PIN_LCD_D7_PE7, -}; - -static const unsigned lcd_d8_pf0_pins[] = { - TEGRA_PIN_LCD_D8_PF0, -}; - -static const unsigned lcd_d9_pf1_pins[] = { - TEGRA_PIN_LCD_D9_PF1, -}; - -static const unsigned lcd_d10_pf2_pins[] = { - TEGRA_PIN_LCD_D10_PF2, -}; - -static const unsigned lcd_d11_pf3_pins[] = { - TEGRA_PIN_LCD_D11_PF3, -}; - -static const unsigned lcd_d12_pf4_pins[] = { - TEGRA_PIN_LCD_D12_PF4, -}; - -static const unsigned lcd_d13_pf5_pins[] = { - TEGRA_PIN_LCD_D13_PF5, -}; - -static const unsigned lcd_d14_pf6_pins[] = { - TEGRA_PIN_LCD_D14_PF6, -}; - -static const unsigned lcd_d15_pf7_pins[] = { - TEGRA_PIN_LCD_D15_PF7, -}; - -static const unsigned gmi_ad0_pg0_pins[] = { - TEGRA_PIN_GMI_AD0_PG0, -}; - -static const unsigned gmi_ad1_pg1_pins[] = { - TEGRA_PIN_GMI_AD1_PG1, -}; - -static const unsigned gmi_ad2_pg2_pins[] = { - TEGRA_PIN_GMI_AD2_PG2, -}; - -static const unsigned gmi_ad3_pg3_pins[] = { - TEGRA_PIN_GMI_AD3_PG3, -}; - -static const unsigned gmi_ad4_pg4_pins[] = { - TEGRA_PIN_GMI_AD4_PG4, -}; - -static const unsigned gmi_ad5_pg5_pins[] = { - TEGRA_PIN_GMI_AD5_PG5, -}; - -static const unsigned gmi_ad6_pg6_pins[] = { - TEGRA_PIN_GMI_AD6_PG6, -}; - -static const unsigned gmi_ad7_pg7_pins[] = { - TEGRA_PIN_GMI_AD7_PG7, -}; - -static const unsigned gmi_ad8_ph0_pins[] = { - TEGRA_PIN_GMI_AD8_PH0, -}; - -static const unsigned gmi_ad9_ph1_pins[] = { - TEGRA_PIN_GMI_AD9_PH1, -}; - -static const unsigned gmi_ad10_ph2_pins[] = { - TEGRA_PIN_GMI_AD10_PH2, -}; - -static const unsigned gmi_ad11_ph3_pins[] = { - TEGRA_PIN_GMI_AD11_PH3, -}; - -static const unsigned gmi_ad12_ph4_pins[] = { - TEGRA_PIN_GMI_AD12_PH4, -}; - -static const unsigned gmi_ad13_ph5_pins[] = { - TEGRA_PIN_GMI_AD13_PH5, -}; - -static const unsigned gmi_ad14_ph6_pins[] = { - TEGRA_PIN_GMI_AD14_PH6, -}; - -static const unsigned gmi_ad15_ph7_pins[] = { - TEGRA_PIN_GMI_AD15_PH7, -}; - -static const unsigned gmi_wr_n_pi0_pins[] = { - TEGRA_PIN_GMI_WR_N_PI0, -}; - -static const unsigned gmi_oe_n_pi1_pins[] = { - TEGRA_PIN_GMI_OE_N_PI1, -}; - -static const unsigned gmi_dqs_pi2_pins[] = { - TEGRA_PIN_GMI_DQS_PI2, -}; - -static const unsigned gmi_cs6_n_pi3_pins[] = { - TEGRA_PIN_GMI_CS6_N_PI3, -}; - -static const unsigned gmi_rst_n_pi4_pins[] = { - TEGRA_PIN_GMI_RST_N_PI4, -}; - -static const unsigned gmi_iordy_pi5_pins[] = { - TEGRA_PIN_GMI_IORDY_PI5, -}; - -static const unsigned gmi_cs7_n_pi6_pins[] = { - TEGRA_PIN_GMI_CS7_N_PI6, -}; - -static const unsigned gmi_wait_pi7_pins[] = { - TEGRA_PIN_GMI_WAIT_PI7, -}; - -static const unsigned gmi_cs0_n_pj0_pins[] = { - TEGRA_PIN_GMI_CS0_N_PJ0, -}; - -static const unsigned lcd_de_pj1_pins[] = { - TEGRA_PIN_LCD_DE_PJ1, -}; - -static const unsigned gmi_cs1_n_pj2_pins[] = { - TEGRA_PIN_GMI_CS1_N_PJ2, -}; - -static const unsigned lcd_hsync_pj3_pins[] = { - TEGRA_PIN_LCD_HSYNC_PJ3, -}; - -static const unsigned lcd_vsync_pj4_pins[] = { - TEGRA_PIN_LCD_VSYNC_PJ4, -}; - -static const unsigned uart2_cts_n_pj5_pins[] = { - TEGRA_PIN_UART2_CTS_N_PJ5, -}; - -static const unsigned uart2_rts_n_pj6_pins[] = { - TEGRA_PIN_UART2_RTS_N_PJ6, -}; - -static const unsigned gmi_a16_pj7_pins[] = { - TEGRA_PIN_GMI_A16_PJ7, -}; - -static const unsigned gmi_adv_n_pk0_pins[] = { - TEGRA_PIN_GMI_ADV_N_PK0, -}; - -static const unsigned gmi_clk_pk1_pins[] = { - TEGRA_PIN_GMI_CLK_PK1, -}; - -static const unsigned gmi_cs4_n_pk2_pins[] = { - TEGRA_PIN_GMI_CS4_N_PK2, -}; - -static const unsigned gmi_cs2_n_pk3_pins[] = { - TEGRA_PIN_GMI_CS2_N_PK3, -}; - -static const unsigned gmi_cs3_n_pk4_pins[] = { - TEGRA_PIN_GMI_CS3_N_PK4, -}; - -static const unsigned spdif_out_pk5_pins[] = { - TEGRA_PIN_SPDIF_OUT_PK5, -}; - -static const unsigned spdif_in_pk6_pins[] = { - TEGRA_PIN_SPDIF_IN_PK6, -}; - -static const unsigned gmi_a19_pk7_pins[] = { - TEGRA_PIN_GMI_A19_PK7, -}; - -static const unsigned vi_d2_pl0_pins[] = { - TEGRA_PIN_VI_D2_PL0, -}; - -static const unsigned vi_d3_pl1_pins[] = { - TEGRA_PIN_VI_D3_PL1, -}; - -static const unsigned vi_d4_pl2_pins[] = { - TEGRA_PIN_VI_D4_PL2, -}; - -static const unsigned vi_d5_pl3_pins[] = { - TEGRA_PIN_VI_D5_PL3, -}; - -static const unsigned vi_d6_pl4_pins[] = { - TEGRA_PIN_VI_D6_PL4, -}; - -static const unsigned vi_d7_pl5_pins[] = { - TEGRA_PIN_VI_D7_PL5, -}; - -static const unsigned vi_d8_pl6_pins[] = { - TEGRA_PIN_VI_D8_PL6, -}; - -static const unsigned vi_d9_pl7_pins[] = { - TEGRA_PIN_VI_D9_PL7, -}; - -static const unsigned lcd_d16_pm0_pins[] = { - TEGRA_PIN_LCD_D16_PM0, -}; - -static const unsigned lcd_d17_pm1_pins[] = { - TEGRA_PIN_LCD_D17_PM1, -}; - -static const unsigned lcd_d18_pm2_pins[] = { - TEGRA_PIN_LCD_D18_PM2, -}; - -static const unsigned lcd_d19_pm3_pins[] = { - TEGRA_PIN_LCD_D19_PM3, -}; - -static const unsigned lcd_d20_pm4_pins[] = { - TEGRA_PIN_LCD_D20_PM4, -}; - -static const unsigned lcd_d21_pm5_pins[] = { - TEGRA_PIN_LCD_D21_PM5, -}; - -static const unsigned lcd_d22_pm6_pins[] = { - TEGRA_PIN_LCD_D22_PM6, -}; - -static const unsigned lcd_d23_pm7_pins[] = { - TEGRA_PIN_LCD_D23_PM7, -}; - -static const unsigned dap1_fs_pn0_pins[] = { - TEGRA_PIN_DAP1_FS_PN0, -}; - -static const unsigned dap1_din_pn1_pins[] = { - TEGRA_PIN_DAP1_DIN_PN1, -}; - -static const unsigned dap1_dout_pn2_pins[] = { - TEGRA_PIN_DAP1_DOUT_PN2, -}; - -static const unsigned dap1_sclk_pn3_pins[] = { - TEGRA_PIN_DAP1_SCLK_PN3, -}; - -static const unsigned lcd_cs0_n_pn4_pins[] = { - TEGRA_PIN_LCD_CS0_N_PN4, -}; - -static const unsigned lcd_sdout_pn5_pins[] = { - TEGRA_PIN_LCD_SDOUT_PN5, -}; - -static const unsigned lcd_dc0_pn6_pins[] = { - TEGRA_PIN_LCD_DC0_PN6, -}; - -static const unsigned hdmi_int_pn7_pins[] = { - TEGRA_PIN_HDMI_INT_PN7, -}; - -static const unsigned ulpi_data7_po0_pins[] = { - TEGRA_PIN_ULPI_DATA7_PO0, -}; - -static const unsigned ulpi_data0_po1_pins[] = { - TEGRA_PIN_ULPI_DATA0_PO1, -}; - -static const unsigned ulpi_data1_po2_pins[] = { - TEGRA_PIN_ULPI_DATA1_PO2, -}; - -static const unsigned ulpi_data2_po3_pins[] = { - TEGRA_PIN_ULPI_DATA2_PO3, -}; - -static const unsigned ulpi_data3_po4_pins[] = { - TEGRA_PIN_ULPI_DATA3_PO4, -}; - -static const unsigned ulpi_data4_po5_pins[] = { - TEGRA_PIN_ULPI_DATA4_PO5, -}; - -static const unsigned ulpi_data5_po6_pins[] = { - TEGRA_PIN_ULPI_DATA5_PO6, -}; - -static const unsigned ulpi_data6_po7_pins[] = { - TEGRA_PIN_ULPI_DATA6_PO7, -}; - -static const unsigned dap3_fs_pp0_pins[] = { - TEGRA_PIN_DAP3_FS_PP0, -}; - -static const unsigned dap3_din_pp1_pins[] = { - TEGRA_PIN_DAP3_DIN_PP1, -}; - -static const unsigned dap3_dout_pp2_pins[] = { - TEGRA_PIN_DAP3_DOUT_PP2, -}; - -static const unsigned dap3_sclk_pp3_pins[] = { - TEGRA_PIN_DAP3_SCLK_PP3, -}; - -static const unsigned dap4_fs_pp4_pins[] = { - TEGRA_PIN_DAP4_FS_PP4, -}; - -static const unsigned dap4_din_pp5_pins[] = { - TEGRA_PIN_DAP4_DIN_PP5, -}; - -static const unsigned dap4_dout_pp6_pins[] = { - TEGRA_PIN_DAP4_DOUT_PP6, -}; - -static const unsigned dap4_sclk_pp7_pins[] = { - TEGRA_PIN_DAP4_SCLK_PP7, -}; - -static const unsigned kb_col0_pq0_pins[] = { - TEGRA_PIN_KB_COL0_PQ0, -}; - -static const unsigned kb_col1_pq1_pins[] = { - TEGRA_PIN_KB_COL1_PQ1, -}; - -static const unsigned kb_col2_pq2_pins[] = { - TEGRA_PIN_KB_COL2_PQ2, -}; - -static const unsigned kb_col3_pq3_pins[] = { - TEGRA_PIN_KB_COL3_PQ3, -}; - -static const unsigned kb_col4_pq4_pins[] = { - TEGRA_PIN_KB_COL4_PQ4, -}; - -static const unsigned kb_col5_pq5_pins[] = { - TEGRA_PIN_KB_COL5_PQ5, -}; - -static const unsigned kb_col6_pq6_pins[] = { - TEGRA_PIN_KB_COL6_PQ6, -}; - -static const unsigned kb_col7_pq7_pins[] = { - TEGRA_PIN_KB_COL7_PQ7, -}; - -static const unsigned kb_row0_pr0_pins[] = { - TEGRA_PIN_KB_ROW0_PR0, -}; - -static const unsigned kb_row1_pr1_pins[] = { - TEGRA_PIN_KB_ROW1_PR1, -}; - -static const unsigned kb_row2_pr2_pins[] = { - TEGRA_PIN_KB_ROW2_PR2, -}; - -static const unsigned kb_row3_pr3_pins[] = { - TEGRA_PIN_KB_ROW3_PR3, -}; - -static const unsigned kb_row4_pr4_pins[] = { - TEGRA_PIN_KB_ROW4_PR4, -}; - -static const unsigned kb_row5_pr5_pins[] = { - TEGRA_PIN_KB_ROW5_PR5, -}; - -static const unsigned kb_row6_pr6_pins[] = { - TEGRA_PIN_KB_ROW6_PR6, -}; - -static const unsigned kb_row7_pr7_pins[] = { - TEGRA_PIN_KB_ROW7_PR7, -}; - -static const unsigned kb_row8_ps0_pins[] = { - TEGRA_PIN_KB_ROW8_PS0, -}; - -static const unsigned kb_row9_ps1_pins[] = { - TEGRA_PIN_KB_ROW9_PS1, -}; - -static const unsigned kb_row10_ps2_pins[] = { - TEGRA_PIN_KB_ROW10_PS2, -}; - -static const unsigned kb_row11_ps3_pins[] = { - TEGRA_PIN_KB_ROW11_PS3, -}; - -static const unsigned kb_row12_ps4_pins[] = { - TEGRA_PIN_KB_ROW12_PS4, -}; - -static const unsigned kb_row13_ps5_pins[] = { - TEGRA_PIN_KB_ROW13_PS5, -}; - -static const unsigned kb_row14_ps6_pins[] = { - TEGRA_PIN_KB_ROW14_PS6, -}; - -static const unsigned kb_row15_ps7_pins[] = { - TEGRA_PIN_KB_ROW15_PS7, -}; - -static const unsigned vi_pclk_pt0_pins[] = { - TEGRA_PIN_VI_PCLK_PT0, -}; - -static const unsigned vi_mclk_pt1_pins[] = { - TEGRA_PIN_VI_MCLK_PT1, -}; - -static const unsigned vi_d10_pt2_pins[] = { - TEGRA_PIN_VI_D10_PT2, -}; - -static const unsigned vi_d11_pt3_pins[] = { - TEGRA_PIN_VI_D11_PT3, -}; - -static const unsigned vi_d0_pt4_pins[] = { - TEGRA_PIN_VI_D0_PT4, -}; - -static const unsigned gen2_i2c_scl_pt5_pins[] = { - TEGRA_PIN_GEN2_I2C_SCL_PT5, -}; - -static const unsigned gen2_i2c_sda_pt6_pins[] = { - TEGRA_PIN_GEN2_I2C_SDA_PT6, -}; - -static const unsigned sdmmc4_cmd_pt7_pins[] = { - TEGRA_PIN_SDMMC4_CMD_PT7, -}; - -static const unsigned pu0_pins[] = { - TEGRA_PIN_PU0, -}; - -static const unsigned pu1_pins[] = { - TEGRA_PIN_PU1, -}; - -static const unsigned pu2_pins[] = { - TEGRA_PIN_PU2, -}; - -static const unsigned pu3_pins[] = { - TEGRA_PIN_PU3, -}; - -static const unsigned pu4_pins[] = { - TEGRA_PIN_PU4, -}; - -static const unsigned pu5_pins[] = { - TEGRA_PIN_PU5, -}; - -static const unsigned pu6_pins[] = { - TEGRA_PIN_PU6, -}; - -static const unsigned jtag_rtck_pu7_pins[] = { - TEGRA_PIN_JTAG_RTCK_PU7, -}; - -static const unsigned pv0_pins[] = { - TEGRA_PIN_PV0, -}; - -static const unsigned pv1_pins[] = { - TEGRA_PIN_PV1, -}; - -static const unsigned pv2_pins[] = { - TEGRA_PIN_PV2, -}; - -static const unsigned pv3_pins[] = { - TEGRA_PIN_PV3, -}; - -static const unsigned ddc_scl_pv4_pins[] = { - TEGRA_PIN_DDC_SCL_PV4, -}; - -static const unsigned ddc_sda_pv5_pins[] = { - TEGRA_PIN_DDC_SDA_PV5, -}; - -static const unsigned crt_hsync_pv6_pins[] = { - TEGRA_PIN_CRT_HSYNC_PV6, -}; - -static const unsigned crt_vsync_pv7_pins[] = { - TEGRA_PIN_CRT_VSYNC_PV7, -}; - -static const unsigned lcd_cs1_n_pw0_pins[] = { - TEGRA_PIN_LCD_CS1_N_PW0, -}; - -static const unsigned lcd_m1_pw1_pins[] = { - TEGRA_PIN_LCD_M1_PW1, -}; - -static const unsigned spi2_cs1_n_pw2_pins[] = { - TEGRA_PIN_SPI2_CS1_N_PW2, -}; - -static const unsigned spi2_cs2_n_pw3_pins[] = { - TEGRA_PIN_SPI2_CS2_N_PW3, -}; - -static const unsigned clk1_out_pw4_pins[] = { - TEGRA_PIN_CLK1_OUT_PW4, -}; - -static const unsigned clk2_out_pw5_pins[] = { - TEGRA_PIN_CLK2_OUT_PW5, -}; - -static const unsigned uart3_txd_pw6_pins[] = { - TEGRA_PIN_UART3_TXD_PW6, -}; - -static const unsigned uart3_rxd_pw7_pins[] = { - TEGRA_PIN_UART3_RXD_PW7, -}; - -static const unsigned spi2_mosi_px0_pins[] = { - TEGRA_PIN_SPI2_MOSI_PX0, -}; - -static const unsigned spi2_miso_px1_pins[] = { - TEGRA_PIN_SPI2_MISO_PX1, -}; - -static const unsigned spi2_sck_px2_pins[] = { - TEGRA_PIN_SPI2_SCK_PX2, -}; - -static const unsigned spi2_cs0_n_px3_pins[] = { - TEGRA_PIN_SPI2_CS0_N_PX3, -}; - -static const unsigned spi1_mosi_px4_pins[] = { - TEGRA_PIN_SPI1_MOSI_PX4, -}; - -static const unsigned spi1_sck_px5_pins[] = { - TEGRA_PIN_SPI1_SCK_PX5, -}; - -static const unsigned spi1_cs0_n_px6_pins[] = { - TEGRA_PIN_SPI1_CS0_N_PX6, -}; - -static const unsigned spi1_miso_px7_pins[] = { - TEGRA_PIN_SPI1_MISO_PX7, -}; - -static const unsigned ulpi_clk_py0_pins[] = { - TEGRA_PIN_ULPI_CLK_PY0, -}; - -static const unsigned ulpi_dir_py1_pins[] = { - TEGRA_PIN_ULPI_DIR_PY1, -}; - -static const unsigned ulpi_nxt_py2_pins[] = { - TEGRA_PIN_ULPI_NXT_PY2, -}; - -static const unsigned ulpi_stp_py3_pins[] = { - TEGRA_PIN_ULPI_STP_PY3, -}; - -static const unsigned sdmmc1_dat3_py4_pins[] = { - TEGRA_PIN_SDMMC1_DAT3_PY4, -}; - -static const unsigned sdmmc1_dat2_py5_pins[] = { - TEGRA_PIN_SDMMC1_DAT2_PY5, -}; - -static const unsigned sdmmc1_dat1_py6_pins[] = { - TEGRA_PIN_SDMMC1_DAT1_PY6, -}; - -static const unsigned sdmmc1_dat0_py7_pins[] = { - TEGRA_PIN_SDMMC1_DAT0_PY7, -}; - -static const unsigned sdmmc1_clk_pz0_pins[] = { - TEGRA_PIN_SDMMC1_CLK_PZ0, -}; - -static const unsigned sdmmc1_cmd_pz1_pins[] = { - TEGRA_PIN_SDMMC1_CMD_PZ1, -}; - -static const unsigned lcd_sdin_pz2_pins[] = { - TEGRA_PIN_LCD_SDIN_PZ2, -}; - -static const unsigned lcd_wr_n_pz3_pins[] = { - TEGRA_PIN_LCD_WR_N_PZ3, -}; - -static const unsigned lcd_sck_pz4_pins[] = { - TEGRA_PIN_LCD_SCK_PZ4, -}; - -static const unsigned sys_clk_req_pz5_pins[] = { - TEGRA_PIN_SYS_CLK_REQ_PZ5, -}; - -static const unsigned pwr_i2c_scl_pz6_pins[] = { - TEGRA_PIN_PWR_I2C_SCL_PZ6, -}; - -static const unsigned pwr_i2c_sda_pz7_pins[] = { - TEGRA_PIN_PWR_I2C_SDA_PZ7, -}; - -static const unsigned sdmmc4_dat0_paa0_pins[] = { - TEGRA_PIN_SDMMC4_DAT0_PAA0, -}; - -static const unsigned sdmmc4_dat1_paa1_pins[] = { - TEGRA_PIN_SDMMC4_DAT1_PAA1, -}; - -static const unsigned sdmmc4_dat2_paa2_pins[] = { - TEGRA_PIN_SDMMC4_DAT2_PAA2, -}; - -static const unsigned sdmmc4_dat3_paa3_pins[] = { - TEGRA_PIN_SDMMC4_DAT3_PAA3, -}; - -static const unsigned sdmmc4_dat4_paa4_pins[] = { - TEGRA_PIN_SDMMC4_DAT4_PAA4, -}; - -static const unsigned sdmmc4_dat5_paa5_pins[] = { - TEGRA_PIN_SDMMC4_DAT5_PAA5, -}; - -static const unsigned sdmmc4_dat6_paa6_pins[] = { - TEGRA_PIN_SDMMC4_DAT6_PAA6, -}; - -static const unsigned sdmmc4_dat7_paa7_pins[] = { - TEGRA_PIN_SDMMC4_DAT7_PAA7, -}; - -static const unsigned pbb0_pins[] = { - TEGRA_PIN_PBB0, -}; - -static const unsigned cam_i2c_scl_pbb1_pins[] = { - TEGRA_PIN_CAM_I2C_SCL_PBB1, -}; - -static const unsigned cam_i2c_sda_pbb2_pins[] = { - TEGRA_PIN_CAM_I2C_SDA_PBB2, -}; - -static const unsigned pbb3_pins[] = { - TEGRA_PIN_PBB3, -}; - -static const unsigned pbb4_pins[] = { - TEGRA_PIN_PBB4, -}; - -static const unsigned pbb5_pins[] = { - TEGRA_PIN_PBB5, -}; - -static const unsigned pbb6_pins[] = { - TEGRA_PIN_PBB6, -}; - -static const unsigned pbb7_pins[] = { - TEGRA_PIN_PBB7, -}; - -static const unsigned cam_mclk_pcc0_pins[] = { - TEGRA_PIN_CAM_MCLK_PCC0, -}; - -static const unsigned pcc1_pins[] = { - TEGRA_PIN_PCC1, -}; - -static const unsigned pcc2_pins[] = { - TEGRA_PIN_PCC2, -}; - -static const unsigned sdmmc4_rst_n_pcc3_pins[] = { - TEGRA_PIN_SDMMC4_RST_N_PCC3, -}; - -static const unsigned sdmmc4_clk_pcc4_pins[] = { - TEGRA_PIN_SDMMC4_CLK_PCC4, -}; - -static const unsigned clk2_req_pcc5_pins[] = { - TEGRA_PIN_CLK2_REQ_PCC5, -}; - -static const unsigned pex_l2_rst_n_pcc6_pins[] = { - TEGRA_PIN_PEX_L2_RST_N_PCC6, -}; - -static const unsigned pex_l2_clkreq_n_pcc7_pins[] = { - TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7, -}; - -static const unsigned pex_l0_prsnt_n_pdd0_pins[] = { - TEGRA_PIN_PEX_L0_PRSNT_N_PDD0, -}; - -static const unsigned pex_l0_rst_n_pdd1_pins[] = { - TEGRA_PIN_PEX_L0_RST_N_PDD1, -}; - -static const unsigned pex_l0_clkreq_n_pdd2_pins[] = { - TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, -}; - -static const unsigned pex_wake_n_pdd3_pins[] = { - TEGRA_PIN_PEX_WAKE_N_PDD3, -}; - -static const unsigned pex_l1_prsnt_n_pdd4_pins[] = { - TEGRA_PIN_PEX_L1_PRSNT_N_PDD4, -}; - -static const unsigned pex_l1_rst_n_pdd5_pins[] = { - TEGRA_PIN_PEX_L1_RST_N_PDD5, -}; - -static const unsigned pex_l1_clkreq_n_pdd6_pins[] = { - TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, -}; - -static const unsigned pex_l2_prsnt_n_pdd7_pins[] = { - TEGRA_PIN_PEX_L2_PRSNT_N_PDD7, -}; - -static const unsigned clk3_out_pee0_pins[] = { - TEGRA_PIN_CLK3_OUT_PEE0, -}; - -static const unsigned clk3_req_pee1_pins[] = { - TEGRA_PIN_CLK3_REQ_PEE1, -}; - -static const unsigned clk1_req_pee2_pins[] = { - TEGRA_PIN_CLK1_REQ_PEE2, -}; - -static const unsigned hdmi_cec_pee3_pins[] = { - TEGRA_PIN_HDMI_CEC_PEE3, -}; - -static const unsigned clk_32k_in_pins[] = { - TEGRA_PIN_CLK_32K_IN, -}; - -static const unsigned core_pwr_req_pins[] = { - TEGRA_PIN_CORE_PWR_REQ, -}; - -static const unsigned cpu_pwr_req_pins[] = { - TEGRA_PIN_CPU_PWR_REQ, -}; - -static const unsigned owr_pins[] = { - TEGRA_PIN_OWR, -}; - -static const unsigned pwr_int_n_pins[] = { - TEGRA_PIN_PWR_INT_N, -}; - -static const unsigned drive_ao1_pins[] = { - TEGRA_PIN_KB_ROW0_PR0, - TEGRA_PIN_KB_ROW1_PR1, - TEGRA_PIN_KB_ROW2_PR2, - TEGRA_PIN_KB_ROW3_PR3, - TEGRA_PIN_KB_ROW4_PR4, - TEGRA_PIN_KB_ROW5_PR5, - TEGRA_PIN_KB_ROW6_PR6, - TEGRA_PIN_KB_ROW7_PR7, - TEGRA_PIN_PWR_I2C_SCL_PZ6, - TEGRA_PIN_PWR_I2C_SDA_PZ7, - TEGRA_PIN_SYS_RESET_N, -}; - -static const unsigned drive_ao2_pins[] = { - TEGRA_PIN_CLK_32K_OUT_PA0, - TEGRA_PIN_KB_COL0_PQ0, - TEGRA_PIN_KB_COL1_PQ1, - TEGRA_PIN_KB_COL2_PQ2, - TEGRA_PIN_KB_COL3_PQ3, - TEGRA_PIN_KB_COL4_PQ4, - TEGRA_PIN_KB_COL5_PQ5, - TEGRA_PIN_KB_COL6_PQ6, - TEGRA_PIN_KB_COL7_PQ7, - TEGRA_PIN_KB_ROW8_PS0, - TEGRA_PIN_KB_ROW9_PS1, - TEGRA_PIN_KB_ROW10_PS2, - TEGRA_PIN_KB_ROW11_PS3, - TEGRA_PIN_KB_ROW12_PS4, - TEGRA_PIN_KB_ROW13_PS5, - TEGRA_PIN_KB_ROW14_PS6, - TEGRA_PIN_KB_ROW15_PS7, - TEGRA_PIN_SYS_CLK_REQ_PZ5, - TEGRA_PIN_CLK_32K_IN, - TEGRA_PIN_CORE_PWR_REQ, - TEGRA_PIN_CPU_PWR_REQ, - TEGRA_PIN_PWR_INT_N, -}; - -static const unsigned drive_at1_pins[] = { - TEGRA_PIN_GMI_AD8_PH0, - TEGRA_PIN_GMI_AD9_PH1, - TEGRA_PIN_GMI_AD10_PH2, - TEGRA_PIN_GMI_AD11_PH3, - TEGRA_PIN_GMI_AD12_PH4, - TEGRA_PIN_GMI_AD13_PH5, - TEGRA_PIN_GMI_AD14_PH6, - TEGRA_PIN_GMI_AD15_PH7, - TEGRA_PIN_GMI_IORDY_PI5, - TEGRA_PIN_GMI_CS7_N_PI6, -}; - -static const unsigned drive_at2_pins[] = { - TEGRA_PIN_GMI_AD0_PG0, - TEGRA_PIN_GMI_AD1_PG1, - TEGRA_PIN_GMI_AD2_PG2, - TEGRA_PIN_GMI_AD3_PG3, - TEGRA_PIN_GMI_AD4_PG4, - TEGRA_PIN_GMI_AD5_PG5, - TEGRA_PIN_GMI_AD6_PG6, - TEGRA_PIN_GMI_AD7_PG7, - TEGRA_PIN_GMI_WR_N_PI0, - TEGRA_PIN_GMI_OE_N_PI1, - TEGRA_PIN_GMI_DQS_PI2, - TEGRA_PIN_GMI_CS6_N_PI3, - TEGRA_PIN_GMI_RST_N_PI4, - TEGRA_PIN_GMI_WAIT_PI7, - TEGRA_PIN_GMI_ADV_N_PK0, - TEGRA_PIN_GMI_CLK_PK1, - TEGRA_PIN_GMI_CS4_N_PK2, - TEGRA_PIN_GMI_CS2_N_PK3, - TEGRA_PIN_GMI_CS3_N_PK4, -}; - -static const unsigned drive_at3_pins[] = { - TEGRA_PIN_GMI_WP_N_PC7, - TEGRA_PIN_GMI_CS0_N_PJ0, -}; - -static const unsigned drive_at4_pins[] = { - TEGRA_PIN_GMI_A17_PB0, - TEGRA_PIN_GMI_A18_PB1, - TEGRA_PIN_GMI_CS1_N_PJ2, - TEGRA_PIN_GMI_A16_PJ7, - TEGRA_PIN_GMI_A19_PK7, -}; - -static const unsigned drive_at5_pins[] = { - TEGRA_PIN_GEN2_I2C_SCL_PT5, - TEGRA_PIN_GEN2_I2C_SDA_PT6, -}; - -static const unsigned drive_cdev1_pins[] = { - TEGRA_PIN_CLK1_OUT_PW4, - TEGRA_PIN_CLK1_REQ_PEE2, -}; - -static const unsigned drive_cdev2_pins[] = { - TEGRA_PIN_CLK2_OUT_PW5, - TEGRA_PIN_CLK2_REQ_PCC5, -}; - -static const unsigned drive_cec_pins[] = { - TEGRA_PIN_HDMI_CEC_PEE3, -}; - -static const unsigned drive_crt_pins[] = { - TEGRA_PIN_CRT_HSYNC_PV6, - TEGRA_PIN_CRT_VSYNC_PV7, -}; - -static const unsigned drive_csus_pins[] = { - TEGRA_PIN_VI_MCLK_PT1, -}; - -static const unsigned drive_dap1_pins[] = { - TEGRA_PIN_SPDIF_OUT_PK5, - TEGRA_PIN_SPDIF_IN_PK6, - TEGRA_PIN_DAP1_FS_PN0, - TEGRA_PIN_DAP1_DIN_PN1, - TEGRA_PIN_DAP1_DOUT_PN2, - TEGRA_PIN_DAP1_SCLK_PN3, -}; - -static const unsigned drive_dap2_pins[] = { - TEGRA_PIN_DAP2_FS_PA2, - TEGRA_PIN_DAP2_SCLK_PA3, - TEGRA_PIN_DAP2_DIN_PA4, - TEGRA_PIN_DAP2_DOUT_PA5, -}; - -static const unsigned drive_dap3_pins[] = { - TEGRA_PIN_DAP3_FS_PP0, - TEGRA_PIN_DAP3_DIN_PP1, - TEGRA_PIN_DAP3_DOUT_PP2, - TEGRA_PIN_DAP3_SCLK_PP3, -}; - -static const unsigned drive_dap4_pins[] = { - TEGRA_PIN_DAP4_FS_PP4, - TEGRA_PIN_DAP4_DIN_PP5, - TEGRA_PIN_DAP4_DOUT_PP6, - TEGRA_PIN_DAP4_SCLK_PP7, -}; - -static const unsigned drive_dbg_pins[] = { - TEGRA_PIN_GEN1_I2C_SCL_PC4, - TEGRA_PIN_GEN1_I2C_SDA_PC5, - TEGRA_PIN_PU0, - TEGRA_PIN_PU1, - TEGRA_PIN_PU2, - TEGRA_PIN_PU3, - TEGRA_PIN_PU4, - TEGRA_PIN_PU5, - TEGRA_PIN_PU6, - TEGRA_PIN_JTAG_RTCK_PU7, - TEGRA_PIN_JTAG_TCK, - TEGRA_PIN_JTAG_TDI, - TEGRA_PIN_JTAG_TDO, - TEGRA_PIN_JTAG_TMS, - TEGRA_PIN_JTAG_TRST_N, - TEGRA_PIN_TEST_MODE_EN, -}; - -static const unsigned drive_ddc_pins[] = { - TEGRA_PIN_DDC_SCL_PV4, - TEGRA_PIN_DDC_SDA_PV5, -}; - -static const unsigned drive_dev3_pins[] = { - TEGRA_PIN_CLK3_OUT_PEE0, - TEGRA_PIN_CLK3_REQ_PEE1, -}; - -static const unsigned drive_gma_pins[] = { - TEGRA_PIN_SDMMC4_DAT0_PAA0, - TEGRA_PIN_SDMMC4_DAT1_PAA1, - TEGRA_PIN_SDMMC4_DAT2_PAA2, - TEGRA_PIN_SDMMC4_DAT3_PAA3, - TEGRA_PIN_SDMMC4_RST_N_PCC3, -}; - -static const unsigned drive_gmb_pins[] = { - TEGRA_PIN_SDMMC4_DAT4_PAA4, - TEGRA_PIN_SDMMC4_DAT5_PAA5, - TEGRA_PIN_SDMMC4_DAT6_PAA6, - TEGRA_PIN_SDMMC4_DAT7_PAA7, -}; - -static const unsigned drive_gmc_pins[] = { - TEGRA_PIN_SDMMC4_CLK_PCC4, -}; - -static const unsigned drive_gmd_pins[] = { - TEGRA_PIN_SDMMC4_CMD_PT7, -}; - -static const unsigned drive_gme_pins[] = { - TEGRA_PIN_PBB0, - TEGRA_PIN_CAM_I2C_SCL_PBB1, - TEGRA_PIN_CAM_I2C_SDA_PBB2, - TEGRA_PIN_PBB3, - TEGRA_PIN_PCC2, -}; - -static const unsigned drive_gmf_pins[] = { - TEGRA_PIN_PBB4, - TEGRA_PIN_PBB5, - TEGRA_PIN_PBB6, - TEGRA_PIN_PBB7, -}; - -static const unsigned drive_gmg_pins[] = { - TEGRA_PIN_CAM_MCLK_PCC0, -}; - -static const unsigned drive_gmh_pins[] = { - TEGRA_PIN_PCC1, -}; - -static const unsigned drive_gpv_pins[] = { - TEGRA_PIN_PEX_L2_RST_N_PCC6, - TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7, - TEGRA_PIN_PEX_L0_PRSNT_N_PDD0, - TEGRA_PIN_PEX_L0_RST_N_PDD1, - TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, - TEGRA_PIN_PEX_WAKE_N_PDD3, - TEGRA_PIN_PEX_L1_PRSNT_N_PDD4, - TEGRA_PIN_PEX_L1_RST_N_PDD5, - TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, - TEGRA_PIN_PEX_L2_PRSNT_N_PDD7, -}; - -static const unsigned drive_lcd1_pins[] = { - TEGRA_PIN_LCD_PWR1_PC1, - TEGRA_PIN_LCD_PWR2_PC6, - TEGRA_PIN_LCD_CS0_N_PN4, - TEGRA_PIN_LCD_SDOUT_PN5, - TEGRA_PIN_LCD_DC0_PN6, - TEGRA_PIN_LCD_SDIN_PZ2, - TEGRA_PIN_LCD_WR_N_PZ3, - TEGRA_PIN_LCD_SCK_PZ4, -}; - -static const unsigned drive_lcd2_pins[] = { - TEGRA_PIN_LCD_PWR0_PB2, - TEGRA_PIN_LCD_PCLK_PB3, - TEGRA_PIN_LCD_DC1_PD2, - TEGRA_PIN_LCD_D0_PE0, - TEGRA_PIN_LCD_D1_PE1, - TEGRA_PIN_LCD_D2_PE2, - TEGRA_PIN_LCD_D3_PE3, - TEGRA_PIN_LCD_D4_PE4, - TEGRA_PIN_LCD_D5_PE5, - TEGRA_PIN_LCD_D6_PE6, - TEGRA_PIN_LCD_D7_PE7, - TEGRA_PIN_LCD_D8_PF0, - TEGRA_PIN_LCD_D9_PF1, - TEGRA_PIN_LCD_D10_PF2, - TEGRA_PIN_LCD_D11_PF3, - TEGRA_PIN_LCD_D12_PF4, - TEGRA_PIN_LCD_D13_PF5, - TEGRA_PIN_LCD_D14_PF6, - TEGRA_PIN_LCD_D15_PF7, - TEGRA_PIN_LCD_DE_PJ1, - TEGRA_PIN_LCD_HSYNC_PJ3, - TEGRA_PIN_LCD_VSYNC_PJ4, - TEGRA_PIN_LCD_D16_PM0, - TEGRA_PIN_LCD_D17_PM1, - TEGRA_PIN_LCD_D18_PM2, - TEGRA_PIN_LCD_D19_PM3, - TEGRA_PIN_LCD_D20_PM4, - TEGRA_PIN_LCD_D21_PM5, - TEGRA_PIN_LCD_D22_PM6, - TEGRA_PIN_LCD_D23_PM7, - TEGRA_PIN_HDMI_INT_PN7, - TEGRA_PIN_LCD_CS1_N_PW0, - TEGRA_PIN_LCD_M1_PW1, -}; - -static const unsigned drive_owr_pins[] = { - TEGRA_PIN_OWR, -}; - -static const unsigned drive_sdio1_pins[] = { - TEGRA_PIN_SDMMC1_DAT3_PY4, - TEGRA_PIN_SDMMC1_DAT2_PY5, - TEGRA_PIN_SDMMC1_DAT1_PY6, - TEGRA_PIN_SDMMC1_DAT0_PY7, - TEGRA_PIN_SDMMC1_CLK_PZ0, - TEGRA_PIN_SDMMC1_CMD_PZ1, -}; - -static const unsigned drive_sdio2_pins[] = { - TEGRA_PIN_SDMMC3_DAT5_PD0, - TEGRA_PIN_SDMMC3_DAT4_PD1, - TEGRA_PIN_SDMMC3_DAT6_PD3, - TEGRA_PIN_SDMMC3_DAT7_PD4, -}; - -static const unsigned drive_sdio3_pins[] = { - TEGRA_PIN_SDMMC3_CLK_PA6, - TEGRA_PIN_SDMMC3_CMD_PA7, - TEGRA_PIN_SDMMC3_DAT3_PB4, - TEGRA_PIN_SDMMC3_DAT2_PB5, - TEGRA_PIN_SDMMC3_DAT1_PB6, - TEGRA_PIN_SDMMC3_DAT0_PB7, -}; - -static const unsigned drive_spi_pins[] = { - TEGRA_PIN_SPI2_CS1_N_PW2, - TEGRA_PIN_SPI2_CS2_N_PW3, - TEGRA_PIN_SPI2_MOSI_PX0, - TEGRA_PIN_SPI2_MISO_PX1, - TEGRA_PIN_SPI2_SCK_PX2, - TEGRA_PIN_SPI2_CS0_N_PX3, - TEGRA_PIN_SPI1_MOSI_PX4, - TEGRA_PIN_SPI1_SCK_PX5, - TEGRA_PIN_SPI1_CS0_N_PX6, - TEGRA_PIN_SPI1_MISO_PX7, -}; - -static const unsigned drive_uaa_pins[] = { - TEGRA_PIN_ULPI_DATA0_PO1, - TEGRA_PIN_ULPI_DATA1_PO2, - TEGRA_PIN_ULPI_DATA2_PO3, - TEGRA_PIN_ULPI_DATA3_PO4, -}; - -static const unsigned drive_uab_pins[] = { - TEGRA_PIN_ULPI_DATA7_PO0, - TEGRA_PIN_ULPI_DATA4_PO5, - TEGRA_PIN_ULPI_DATA5_PO6, - TEGRA_PIN_ULPI_DATA6_PO7, - TEGRA_PIN_PV0, - TEGRA_PIN_PV1, - TEGRA_PIN_PV2, - TEGRA_PIN_PV3, -}; - -static const unsigned drive_uart2_pins[] = { - TEGRA_PIN_UART2_TXD_PC2, - TEGRA_PIN_UART2_RXD_PC3, - TEGRA_PIN_UART2_CTS_N_PJ5, - TEGRA_PIN_UART2_RTS_N_PJ6, -}; - -static const unsigned drive_uart3_pins[] = { - TEGRA_PIN_UART3_CTS_N_PA1, - TEGRA_PIN_UART3_RTS_N_PC0, - TEGRA_PIN_UART3_TXD_PW6, - TEGRA_PIN_UART3_RXD_PW7, -}; - -static const unsigned drive_uda_pins[] = { - TEGRA_PIN_ULPI_CLK_PY0, - TEGRA_PIN_ULPI_DIR_PY1, - TEGRA_PIN_ULPI_NXT_PY2, - TEGRA_PIN_ULPI_STP_PY3, -}; - -static const unsigned drive_vi1_pins[] = { - TEGRA_PIN_VI_D1_PD5, - TEGRA_PIN_VI_VSYNC_PD6, - TEGRA_PIN_VI_HSYNC_PD7, - TEGRA_PIN_VI_D2_PL0, - TEGRA_PIN_VI_D3_PL1, - TEGRA_PIN_VI_D4_PL2, - TEGRA_PIN_VI_D5_PL3, - TEGRA_PIN_VI_D6_PL4, - TEGRA_PIN_VI_D7_PL5, - TEGRA_PIN_VI_D8_PL6, - TEGRA_PIN_VI_D9_PL7, - TEGRA_PIN_VI_PCLK_PT0, - TEGRA_PIN_VI_D10_PT2, - TEGRA_PIN_VI_D11_PT3, - TEGRA_PIN_VI_D0_PT4, -}; - -enum tegra_mux { - TEGRA_MUX_BLINK, - TEGRA_MUX_CEC, - TEGRA_MUX_CLK_12M_OUT, - TEGRA_MUX_CLK_32K_IN, - TEGRA_MUX_CORE_PWR_REQ, - TEGRA_MUX_CPU_PWR_REQ, - TEGRA_MUX_CRT, - TEGRA_MUX_DAP, - TEGRA_MUX_DDR, - TEGRA_MUX_DEV3, - TEGRA_MUX_DISPLAYA, - TEGRA_MUX_DISPLAYB, - TEGRA_MUX_DTV, - TEGRA_MUX_EXTPERIPH1, - TEGRA_MUX_EXTPERIPH2, - TEGRA_MUX_EXTPERIPH3, - TEGRA_MUX_GMI, - TEGRA_MUX_GMI_ALT, - TEGRA_MUX_HDA, - TEGRA_MUX_HDCP, - TEGRA_MUX_HDMI, - TEGRA_MUX_HSI, - TEGRA_MUX_I2C1, - TEGRA_MUX_I2C2, - TEGRA_MUX_I2C3, - TEGRA_MUX_I2C4, - TEGRA_MUX_I2CPWR, - TEGRA_MUX_I2S0, - TEGRA_MUX_I2S1, - TEGRA_MUX_I2S2, - TEGRA_MUX_I2S3, - TEGRA_MUX_I2S4, - TEGRA_MUX_INVALID, - TEGRA_MUX_KBC, - TEGRA_MUX_MIO, - TEGRA_MUX_NAND, - TEGRA_MUX_NAND_ALT, - TEGRA_MUX_OWR, - TEGRA_MUX_PCIE, - TEGRA_MUX_PWM0, - TEGRA_MUX_PWM1, - TEGRA_MUX_PWM2, - TEGRA_MUX_PWM3, - TEGRA_MUX_PWR_INT_N, - TEGRA_MUX_RSVD1, - TEGRA_MUX_RSVD2, - TEGRA_MUX_RSVD3, - TEGRA_MUX_RSVD4, - TEGRA_MUX_RTCK, - TEGRA_MUX_SATA, - TEGRA_MUX_SDMMC1, - TEGRA_MUX_SDMMC2, - TEGRA_MUX_SDMMC3, - TEGRA_MUX_SDMMC4, - TEGRA_MUX_SPDIF, - TEGRA_MUX_SPI1, - TEGRA_MUX_SPI2, - TEGRA_MUX_SPI2_ALT, - TEGRA_MUX_SPI3, - TEGRA_MUX_SPI4, - TEGRA_MUX_SPI5, - TEGRA_MUX_SPI6, - TEGRA_MUX_SYSCLK, - TEGRA_MUX_TEST, - TEGRA_MUX_TRACE, - TEGRA_MUX_UARTA, - TEGRA_MUX_UARTB, - TEGRA_MUX_UARTC, - TEGRA_MUX_UARTD, - TEGRA_MUX_UARTE, - TEGRA_MUX_ULPI, - TEGRA_MUX_VGP1, - TEGRA_MUX_VGP2, - TEGRA_MUX_VGP3, - TEGRA_MUX_VGP4, - TEGRA_MUX_VGP5, - TEGRA_MUX_VGP6, - TEGRA_MUX_VI, - TEGRA_MUX_VI_ALT1, - TEGRA_MUX_VI_ALT2, - TEGRA_MUX_VI_ALT3, -}; - -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } - -static struct tegra_function tegra30_functions[] = { - FUNCTION(blink), - FUNCTION(cec), - FUNCTION(clk_12m_out), - FUNCTION(clk_32k_in), - FUNCTION(core_pwr_req), - FUNCTION(cpu_pwr_req), - FUNCTION(crt), - FUNCTION(dap), - FUNCTION(ddr), - FUNCTION(dev3), - FUNCTION(displaya), - FUNCTION(displayb), - FUNCTION(dtv), - FUNCTION(extperiph1), - FUNCTION(extperiph2), - FUNCTION(extperiph3), - FUNCTION(gmi), - FUNCTION(gmi_alt), - FUNCTION(hda), - FUNCTION(hdcp), - FUNCTION(hdmi), - FUNCTION(hsi), - FUNCTION(i2c1), - FUNCTION(i2c2), - FUNCTION(i2c3), - FUNCTION(i2c4), - FUNCTION(i2cpwr), - FUNCTION(i2s0), - FUNCTION(i2s1), - FUNCTION(i2s2), - FUNCTION(i2s3), - FUNCTION(i2s4), - FUNCTION(invalid), - FUNCTION(kbc), - FUNCTION(mio), - FUNCTION(nand), - FUNCTION(nand_alt), - FUNCTION(owr), - FUNCTION(pcie), - FUNCTION(pwm0), - FUNCTION(pwm1), - FUNCTION(pwm2), - FUNCTION(pwm3), - FUNCTION(pwr_int_n), - FUNCTION(rsvd1), - FUNCTION(rsvd2), - FUNCTION(rsvd3), - FUNCTION(rsvd4), - FUNCTION(rtck), - FUNCTION(sata), - FUNCTION(sdmmc1), - FUNCTION(sdmmc2), - FUNCTION(sdmmc3), - FUNCTION(sdmmc4), - FUNCTION(spdif), - FUNCTION(spi1), - FUNCTION(spi2), - FUNCTION(spi2_alt), - FUNCTION(spi3), - FUNCTION(spi4), - FUNCTION(spi5), - FUNCTION(spi6), - FUNCTION(sysclk), - FUNCTION(test), - FUNCTION(trace), - FUNCTION(uarta), - FUNCTION(uartb), - FUNCTION(uartc), - FUNCTION(uartd), - FUNCTION(uarte), - FUNCTION(ulpi), - FUNCTION(vgp1), - FUNCTION(vgp2), - FUNCTION(vgp3), - FUNCTION(vgp4), - FUNCTION(vgp5), - FUNCTION(vgp6), - FUNCTION(vi), - FUNCTION(vi_alt1), - FUNCTION(vi_alt2), - FUNCTION(vi_alt3), -}; - -#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ -#define PINGROUP_REG_A 0x3000 /* bank 1 */ - -#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A) -#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) - -#define PINGROUP_BIT_Y(b) (b) -#define PINGROUP_BIT_N(b) (-1) - -#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior) \ - { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ - .funcs = { \ - TEGRA_MUX_##f0, \ - TEGRA_MUX_##f1, \ - TEGRA_MUX_##f2, \ - TEGRA_MUX_##f3, \ - }, \ - .mux_reg = PINGROUP_REG(r), \ - .mux_bank = 1, \ - .mux_bit = 0, \ - .pupd_reg = PINGROUP_REG(r), \ - .pupd_bank = 1, \ - .pupd_bit = 2, \ - .tri_reg = PINGROUP_REG(r), \ - .tri_bank = 1, \ - .tri_bit = 4, \ - .einput_bit = 5, \ - .odrain_bit = PINGROUP_BIT_##od(6), \ - .lock_bit = 7, \ - .ioreset_bit = PINGROUP_BIT_##ior(8), \ - .rcv_sel_bit = -1, \ - .drv_reg = -1, \ - } - -#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, \ - drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, \ - slwf_b, slwf_w) \ - { \ - .name = "drive_" #pg_name, \ - .pins = drive_##pg_name##_pins, \ - .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ - .mux_reg = -1, \ - .pupd_reg = -1, \ - .tri_reg = -1, \ - .einput_bit = -1, \ - .odrain_bit = -1, \ - .lock_bit = -1, \ - .ioreset_bit = -1, \ - .rcv_sel_bit = -1, \ - .drv_reg = DRV_PINGROUP_REG(r), \ - .drv_bank = 0, \ - .hsm_bit = hsm_b, \ - .schmitt_bit = schmitt_b, \ - .lpmd_bit = lpmd_b, \ - .drvdn_bit = drvdn_b, \ - .drvdn_width = drvdn_w, \ - .drvup_bit = drvup_b, \ - .drvup_width = drvup_w, \ - .slwr_bit = slwr_b, \ - .slwr_width = slwr_w, \ - .slwf_bit = slwf_b, \ - .slwf_width = slwf_w, \ - .drvtype_bit = -1, \ - } - -static const struct tegra_pingroup tegra30_groups[] = { - /* pg_name, f0, f1, f2, f3, r, od, ior */ - PINGROUP(clk_32k_out_pa0, BLINK, RSVD2, RSVD3, RSVD4, 0x331c, N, N), - PINGROUP(uart3_cts_n_pa1, UARTC, RSVD2, GMI, RSVD4, 0x317c, N, N), - PINGROUP(dap2_fs_pa2, I2S1, HDA, RSVD3, GMI, 0x3358, N, N), - PINGROUP(dap2_sclk_pa3, I2S1, HDA, RSVD3, GMI, 0x3364, N, N), - PINGROUP(dap2_din_pa4, I2S1, HDA, RSVD3, GMI, 0x335c, N, N), - PINGROUP(dap2_dout_pa5, I2S1, HDA, RSVD3, GMI, 0x3360, N, N), - PINGROUP(sdmmc3_clk_pa6, UARTA, PWM2, SDMMC3, SPI3, 0x3390, N, N), - PINGROUP(sdmmc3_cmd_pa7, UARTA, PWM3, SDMMC3, SPI2, 0x3394, N, N), - PINGROUP(gmi_a17_pb0, UARTD, SPI4, GMI, DTV, 0x3234, N, N), - PINGROUP(gmi_a18_pb1, UARTD, SPI4, GMI, DTV, 0x3238, N, N), - PINGROUP(lcd_pwr0_pb2, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x3090, N, N), - PINGROUP(lcd_pclk_pb3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3094, N, N), - PINGROUP(sdmmc3_dat3_pb4, RSVD1, PWM0, SDMMC3, SPI3, 0x33a4, N, N), - PINGROUP(sdmmc3_dat2_pb5, RSVD1, PWM1, SDMMC3, SPI3, 0x33a0, N, N), - PINGROUP(sdmmc3_dat1_pb6, RSVD1, RSVD2, SDMMC3, SPI3, 0x339c, N, N), - PINGROUP(sdmmc3_dat0_pb7, RSVD1, RSVD2, SDMMC3, SPI3, 0x3398, N, N), - PINGROUP(uart3_rts_n_pc0, UARTC, PWM0, GMI, RSVD4, 0x3180, N, N), - PINGROUP(lcd_pwr1_pc1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3070, N, N), - PINGROUP(uart2_txd_pc2, UARTB, SPDIF, UARTA, SPI4, 0x3168, N, N), - PINGROUP(uart2_rxd_pc3, UARTB, SPDIF, UARTA, SPI4, 0x3164, N, N), - PINGROUP(gen1_i2c_scl_pc4, I2C1, RSVD2, RSVD3, RSVD4, 0x31a4, Y, N), - PINGROUP(gen1_i2c_sda_pc5, I2C1, RSVD2, RSVD3, RSVD4, 0x31a0, Y, N), - PINGROUP(lcd_pwr2_pc6, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x3074, N, N), - PINGROUP(gmi_wp_n_pc7, RSVD1, NAND, GMI, GMI_ALT, 0x31c0, N, N), - PINGROUP(sdmmc3_dat5_pd0, PWM0, SPI4, SDMMC3, SPI2, 0x33ac, N, N), - PINGROUP(sdmmc3_dat4_pd1, PWM1, SPI4, SDMMC3, SPI2, 0x33a8, N, N), - PINGROUP(lcd_dc1_pd2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x310c, N, N), - PINGROUP(sdmmc3_dat6_pd3, SPDIF, SPI4, SDMMC3, SPI2, 0x33b0, N, N), - PINGROUP(sdmmc3_dat7_pd4, SPDIF, SPI4, SDMMC3, SPI2, 0x33b4, N, N), - PINGROUP(vi_d1_pd5, DDR, SDMMC2, VI, RSVD4, 0x3128, N, Y), - PINGROUP(vi_vsync_pd6, DDR, RSVD2, VI, RSVD4, 0x315c, N, Y), - PINGROUP(vi_hsync_pd7, DDR, RSVD2, VI, RSVD4, 0x3160, N, Y), - PINGROUP(lcd_d0_pe0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30a4, N, N), - PINGROUP(lcd_d1_pe1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30a8, N, N), - PINGROUP(lcd_d2_pe2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30ac, N, N), - PINGROUP(lcd_d3_pe3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30b0, N, N), - PINGROUP(lcd_d4_pe4, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30b4, N, N), - PINGROUP(lcd_d5_pe5, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30b8, N, N), - PINGROUP(lcd_d6_pe6, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30bc, N, N), - PINGROUP(lcd_d7_pe7, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30c0, N, N), - PINGROUP(lcd_d8_pf0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30c4, N, N), - PINGROUP(lcd_d9_pf1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30c8, N, N), - PINGROUP(lcd_d10_pf2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30cc, N, N), - PINGROUP(lcd_d11_pf3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30d0, N, N), - PINGROUP(lcd_d12_pf4, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30d4, N, N), - PINGROUP(lcd_d13_pf5, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30d8, N, N), - PINGROUP(lcd_d14_pf6, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30dc, N, N), - PINGROUP(lcd_d15_pf7, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30e0, N, N), - PINGROUP(gmi_ad0_pg0, RSVD1, NAND, GMI, RSVD4, 0x31f0, N, N), - PINGROUP(gmi_ad1_pg1, RSVD1, NAND, GMI, RSVD4, 0x31f4, N, N), - PINGROUP(gmi_ad2_pg2, RSVD1, NAND, GMI, RSVD4, 0x31f8, N, N), - PINGROUP(gmi_ad3_pg3, RSVD1, NAND, GMI, RSVD4, 0x31fc, N, N), - PINGROUP(gmi_ad4_pg4, RSVD1, NAND, GMI, RSVD4, 0x3200, N, N), - PINGROUP(gmi_ad5_pg5, RSVD1, NAND, GMI, RSVD4, 0x3204, N, N), - PINGROUP(gmi_ad6_pg6, RSVD1, NAND, GMI, RSVD4, 0x3208, N, N), - PINGROUP(gmi_ad7_pg7, RSVD1, NAND, GMI, RSVD4, 0x320c, N, N), - PINGROUP(gmi_ad8_ph0, PWM0, NAND, GMI, RSVD4, 0x3210, N, N), - PINGROUP(gmi_ad9_ph1, PWM1, NAND, GMI, RSVD4, 0x3214, N, N), - PINGROUP(gmi_ad10_ph2, PWM2, NAND, GMI, RSVD4, 0x3218, N, N), - PINGROUP(gmi_ad11_ph3, PWM3, NAND, GMI, RSVD4, 0x321c, N, N), - PINGROUP(gmi_ad12_ph4, RSVD1, NAND, GMI, RSVD4, 0x3220, N, N), - PINGROUP(gmi_ad13_ph5, RSVD1, NAND, GMI, RSVD4, 0x3224, N, N), - PINGROUP(gmi_ad14_ph6, RSVD1, NAND, GMI, RSVD4, 0x3228, N, N), - PINGROUP(gmi_ad15_ph7, RSVD1, NAND, GMI, RSVD4, 0x322c, N, N), - PINGROUP(gmi_wr_n_pi0, RSVD1, NAND, GMI, RSVD4, 0x3240, N, N), - PINGROUP(gmi_oe_n_pi1, RSVD1, NAND, GMI, RSVD4, 0x3244, N, N), - PINGROUP(gmi_dqs_pi2, RSVD1, NAND, GMI, RSVD4, 0x3248, N, N), - PINGROUP(gmi_cs6_n_pi3, NAND, NAND_ALT, GMI, SATA, 0x31e8, N, N), - PINGROUP(gmi_rst_n_pi4, NAND, NAND_ALT, GMI, RSVD4, 0x324c, N, N), - PINGROUP(gmi_iordy_pi5, RSVD1, NAND, GMI, RSVD4, 0x31c4, N, N), - PINGROUP(gmi_cs7_n_pi6, NAND, NAND_ALT, GMI, GMI_ALT, 0x31ec, N, N), - PINGROUP(gmi_wait_pi7, RSVD1, NAND, GMI, RSVD4, 0x31c8, N, N), - PINGROUP(gmi_cs0_n_pj0, RSVD1, NAND, GMI, DTV, 0x31d4, N, N), - PINGROUP(lcd_de_pj1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3098, N, N), - PINGROUP(gmi_cs1_n_pj2, RSVD1, NAND, GMI, DTV, 0x31d8, N, N), - PINGROUP(lcd_hsync_pj3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x309c, N, N), - PINGROUP(lcd_vsync_pj4, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30a0, N, N), - PINGROUP(uart2_cts_n_pj5, UARTA, UARTB, GMI, SPI4, 0x3170, N, N), - PINGROUP(uart2_rts_n_pj6, UARTA, UARTB, GMI, SPI4, 0x316c, N, N), - PINGROUP(gmi_a16_pj7, UARTD, SPI4, GMI, GMI_ALT, 0x3230, N, N), - PINGROUP(gmi_adv_n_pk0, RSVD1, NAND, GMI, RSVD4, 0x31cc, N, N), - PINGROUP(gmi_clk_pk1, RSVD1, NAND, GMI, RSVD4, 0x31d0, N, N), - PINGROUP(gmi_cs4_n_pk2, RSVD1, NAND, GMI, RSVD4, 0x31e4, N, N), - PINGROUP(gmi_cs2_n_pk3, RSVD1, NAND, GMI, RSVD4, 0x31dc, N, N), - PINGROUP(gmi_cs3_n_pk4, RSVD1, NAND, GMI, GMI_ALT, 0x31e0, N, N), - PINGROUP(spdif_out_pk5, SPDIF, RSVD2, I2C1, SDMMC2, 0x3354, N, N), - PINGROUP(spdif_in_pk6, SPDIF, HDA, I2C1, SDMMC2, 0x3350, N, N), - PINGROUP(gmi_a19_pk7, UARTD, SPI4, GMI, RSVD4, 0x323c, N, N), - PINGROUP(vi_d2_pl0, DDR, SDMMC2, VI, RSVD4, 0x312c, N, Y), - PINGROUP(vi_d3_pl1, DDR, SDMMC2, VI, RSVD4, 0x3130, N, Y), - PINGROUP(vi_d4_pl2, DDR, SDMMC2, VI, RSVD4, 0x3134, N, Y), - PINGROUP(vi_d5_pl3, DDR, SDMMC2, VI, RSVD4, 0x3138, N, Y), - PINGROUP(vi_d6_pl4, DDR, SDMMC2, VI, RSVD4, 0x313c, N, Y), - PINGROUP(vi_d7_pl5, DDR, SDMMC2, VI, RSVD4, 0x3140, N, Y), - PINGROUP(vi_d8_pl6, DDR, SDMMC2, VI, RSVD4, 0x3144, N, Y), - PINGROUP(vi_d9_pl7, DDR, SDMMC2, VI, RSVD4, 0x3148, N, Y), - PINGROUP(lcd_d16_pm0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30e4, N, N), - PINGROUP(lcd_d17_pm1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30e8, N, N), - PINGROUP(lcd_d18_pm2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30ec, N, N), - PINGROUP(lcd_d19_pm3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30f0, N, N), - PINGROUP(lcd_d20_pm4, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30f4, N, N), - PINGROUP(lcd_d21_pm5, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30f8, N, N), - PINGROUP(lcd_d22_pm6, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30fc, N, N), - PINGROUP(lcd_d23_pm7, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3100, N, N), - PINGROUP(dap1_fs_pn0, I2S0, HDA, GMI, SDMMC2, 0x3338, N, N), - PINGROUP(dap1_din_pn1, I2S0, HDA, GMI, SDMMC2, 0x333c, N, N), - PINGROUP(dap1_dout_pn2, I2S0, HDA, GMI, SDMMC2, 0x3340, N, N), - PINGROUP(dap1_sclk_pn3, I2S0, HDA, GMI, SDMMC2, 0x3344, N, N), - PINGROUP(lcd_cs0_n_pn4, DISPLAYA, DISPLAYB, SPI5, RSVD4, 0x3084, N, N), - PINGROUP(lcd_sdout_pn5, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x307c, N, N), - PINGROUP(lcd_dc0_pn6, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3088, N, N), - PINGROUP(hdmi_int_pn7, HDMI, RSVD2, RSVD3, RSVD4, 0x3110, N, N), - PINGROUP(ulpi_data7_po0, SPI2, HSI, UARTA, ULPI, 0x301c, N, N), - PINGROUP(ulpi_data0_po1, SPI3, HSI, UARTA, ULPI, 0x3000, N, N), - PINGROUP(ulpi_data1_po2, SPI3, HSI, UARTA, ULPI, 0x3004, N, N), - PINGROUP(ulpi_data2_po3, SPI3, HSI, UARTA, ULPI, 0x3008, N, N), - PINGROUP(ulpi_data3_po4, SPI3, HSI, UARTA, ULPI, 0x300c, N, N), - PINGROUP(ulpi_data4_po5, SPI2, HSI, UARTA, ULPI, 0x3010, N, N), - PINGROUP(ulpi_data5_po6, SPI2, HSI, UARTA, ULPI, 0x3014, N, N), - PINGROUP(ulpi_data6_po7, SPI2, HSI, UARTA, ULPI, 0x3018, N, N), - PINGROUP(dap3_fs_pp0, I2S2, RSVD2, DISPLAYA, DISPLAYB, 0x3030, N, N), - PINGROUP(dap3_din_pp1, I2S2, RSVD2, DISPLAYA, DISPLAYB, 0x3034, N, N), - PINGROUP(dap3_dout_pp2, I2S2, RSVD2, DISPLAYA, DISPLAYB, 0x3038, N, N), - PINGROUP(dap3_sclk_pp3, I2S2, RSVD2, DISPLAYA, DISPLAYB, 0x303c, N, N), - PINGROUP(dap4_fs_pp4, I2S3, RSVD2, GMI, RSVD4, 0x31a8, N, N), - PINGROUP(dap4_din_pp5, I2S3, RSVD2, GMI, RSVD4, 0x31ac, N, N), - PINGROUP(dap4_dout_pp6, I2S3, RSVD2, GMI, RSVD4, 0x31b0, N, N), - PINGROUP(dap4_sclk_pp7, I2S3, RSVD2, GMI, RSVD4, 0x31b4, N, N), - PINGROUP(kb_col0_pq0, KBC, NAND, TRACE, TEST, 0x32fc, N, N), - PINGROUP(kb_col1_pq1, KBC, NAND, TRACE, TEST, 0x3300, N, N), - PINGROUP(kb_col2_pq2, KBC, NAND, TRACE, RSVD4, 0x3304, N, N), - PINGROUP(kb_col3_pq3, KBC, NAND, TRACE, RSVD4, 0x3308, N, N), - PINGROUP(kb_col4_pq4, KBC, NAND, TRACE, RSVD4, 0x330c, N, N), - PINGROUP(kb_col5_pq5, KBC, NAND, TRACE, RSVD4, 0x3310, N, N), - PINGROUP(kb_col6_pq6, KBC, NAND, TRACE, MIO, 0x3314, N, N), - PINGROUP(kb_col7_pq7, KBC, NAND, TRACE, MIO, 0x3318, N, N), - PINGROUP(kb_row0_pr0, KBC, NAND, RSVD3, RSVD4, 0x32bc, N, N), - PINGROUP(kb_row1_pr1, KBC, NAND, RSVD3, RSVD4, 0x32c0, N, N), - PINGROUP(kb_row2_pr2, KBC, NAND, RSVD3, RSVD4, 0x32c4, N, N), - PINGROUP(kb_row3_pr3, KBC, NAND, RSVD3, INVALID, 0x32c8, N, N), - PINGROUP(kb_row4_pr4, KBC, NAND, TRACE, RSVD4, 0x32cc, N, N), - PINGROUP(kb_row5_pr5, KBC, NAND, TRACE, OWR, 0x32d0, N, N), - PINGROUP(kb_row6_pr6, KBC, NAND, SDMMC2, MIO, 0x32d4, N, N), - PINGROUP(kb_row7_pr7, KBC, NAND, SDMMC2, MIO, 0x32d8, N, N), - PINGROUP(kb_row8_ps0, KBC, NAND, SDMMC2, MIO, 0x32dc, N, N), - PINGROUP(kb_row9_ps1, KBC, NAND, SDMMC2, MIO, 0x32e0, N, N), - PINGROUP(kb_row10_ps2, KBC, NAND, SDMMC2, MIO, 0x32e4, N, N), - PINGROUP(kb_row11_ps3, KBC, NAND, SDMMC2, MIO, 0x32e8, N, N), - PINGROUP(kb_row12_ps4, KBC, NAND, SDMMC2, MIO, 0x32ec, N, N), - PINGROUP(kb_row13_ps5, KBC, NAND, SDMMC2, MIO, 0x32f0, N, N), - PINGROUP(kb_row14_ps6, KBC, NAND, SDMMC2, MIO, 0x32f4, N, N), - PINGROUP(kb_row15_ps7, KBC, NAND, SDMMC2, MIO, 0x32f8, N, N), - PINGROUP(vi_pclk_pt0, RSVD1, SDMMC2, VI, RSVD4, 0x3154, N, Y), - PINGROUP(vi_mclk_pt1, VI, VI_ALT1, VI_ALT2, VI_ALT3, 0x3158, N, Y), - PINGROUP(vi_d10_pt2, DDR, RSVD2, VI, RSVD4, 0x314c, N, Y), - PINGROUP(vi_d11_pt3, DDR, RSVD2, VI, RSVD4, 0x3150, N, Y), - PINGROUP(vi_d0_pt4, DDR, RSVD2, VI, RSVD4, 0x3124, N, Y), - PINGROUP(gen2_i2c_scl_pt5, I2C2, HDCP, GMI, RSVD4, 0x3250, Y, N), - PINGROUP(gen2_i2c_sda_pt6, I2C2, HDCP, GMI, RSVD4, 0x3254, Y, N), - PINGROUP(sdmmc4_cmd_pt7, I2C3, NAND, GMI, SDMMC4, 0x325c, N, Y), - PINGROUP(pu0, OWR, UARTA, GMI, RSVD4, 0x3184, N, N), - PINGROUP(pu1, RSVD1, UARTA, GMI, RSVD4, 0x3188, N, N), - PINGROUP(pu2, RSVD1, UARTA, GMI, RSVD4, 0x318c, N, N), - PINGROUP(pu3, PWM0, UARTA, GMI, RSVD4, 0x3190, N, N), - PINGROUP(pu4, PWM1, UARTA, GMI, RSVD4, 0x3194, N, N), - PINGROUP(pu5, PWM2, UARTA, GMI, RSVD4, 0x3198, N, N), - PINGROUP(pu6, PWM3, UARTA, GMI, RSVD4, 0x319c, N, N), - PINGROUP(jtag_rtck_pu7, RTCK, RSVD2, RSVD3, RSVD4, 0x32b0, N, N), - PINGROUP(pv0, RSVD1, RSVD2, RSVD3, RSVD4, 0x3040, N, N), - PINGROUP(pv1, RSVD1, RSVD2, RSVD3, RSVD4, 0x3044, N, N), - PINGROUP(pv2, OWR, RSVD2, RSVD3, RSVD4, 0x3060, N, N), - PINGROUP(pv3, CLK_12M_OUT, RSVD2, RSVD3, RSVD4, 0x3064, N, N), - PINGROUP(ddc_scl_pv4, I2C4, RSVD2, RSVD3, RSVD4, 0x3114, N, N), - PINGROUP(ddc_sda_pv5, I2C4, RSVD2, RSVD3, RSVD4, 0x3118, N, N), - PINGROUP(crt_hsync_pv6, CRT, RSVD2, RSVD3, RSVD4, 0x311c, N, N), - PINGROUP(crt_vsync_pv7, CRT, RSVD2, RSVD3, RSVD4, 0x3120, N, N), - PINGROUP(lcd_cs1_n_pw0, DISPLAYA, DISPLAYB, SPI5, RSVD4, 0x3104, N, N), - PINGROUP(lcd_m1_pw1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3108, N, N), - PINGROUP(spi2_cs1_n_pw2, SPI3, SPI2, SPI2_ALT, I2C1, 0x3388, N, N), - PINGROUP(spi2_cs2_n_pw3, SPI3, SPI2, SPI2_ALT, I2C1, 0x338c, N, N), - PINGROUP(clk1_out_pw4, EXTPERIPH1, RSVD2, RSVD3, RSVD4, 0x334c, N, N), - PINGROUP(clk2_out_pw5, EXTPERIPH2, RSVD2, RSVD3, RSVD4, 0x3068, N, N), - PINGROUP(uart3_txd_pw6, UARTC, RSVD2, GMI, RSVD4, 0x3174, N, N), - PINGROUP(uart3_rxd_pw7, UARTC, RSVD2, GMI, RSVD4, 0x3178, N, N), - PINGROUP(spi2_mosi_px0, SPI6, SPI2, SPI3, GMI, 0x3368, N, N), - PINGROUP(spi2_miso_px1, SPI6, SPI2, SPI3, GMI, 0x336c, N, N), - PINGROUP(spi2_sck_px2, SPI6, SPI2, SPI3, GMI, 0x3374, N, N), - PINGROUP(spi2_cs0_n_px3, SPI6, SPI2, SPI3, GMI, 0x3370, N, N), - PINGROUP(spi1_mosi_px4, SPI2, SPI1, SPI2_ALT, GMI, 0x3378, N, N), - PINGROUP(spi1_sck_px5, SPI2, SPI1, SPI2_ALT, GMI, 0x337c, N, N), - PINGROUP(spi1_cs0_n_px6, SPI2, SPI1, SPI2_ALT, GMI, 0x3380, N, N), - PINGROUP(spi1_miso_px7, SPI3, SPI1, SPI2_ALT, RSVD4, 0x3384, N, N), - PINGROUP(ulpi_clk_py0, SPI1, RSVD2, UARTD, ULPI, 0x3020, N, N), - PINGROUP(ulpi_dir_py1, SPI1, RSVD2, UARTD, ULPI, 0x3024, N, N), - PINGROUP(ulpi_nxt_py2, SPI1, RSVD2, UARTD, ULPI, 0x3028, N, N), - PINGROUP(ulpi_stp_py3, SPI1, RSVD2, UARTD, ULPI, 0x302c, N, N), - PINGROUP(sdmmc1_dat3_py4, SDMMC1, RSVD2, UARTE, UARTA, 0x3050, N, N), - PINGROUP(sdmmc1_dat2_py5, SDMMC1, RSVD2, UARTE, UARTA, 0x3054, N, N), - PINGROUP(sdmmc1_dat1_py6, SDMMC1, RSVD2, UARTE, UARTA, 0x3058, N, N), - PINGROUP(sdmmc1_dat0_py7, SDMMC1, RSVD2, UARTE, UARTA, 0x305c, N, N), - PINGROUP(sdmmc1_clk_pz0, SDMMC1, RSVD2, RSVD3, UARTA, 0x3048, N, N), - PINGROUP(sdmmc1_cmd_pz1, SDMMC1, RSVD2, RSVD3, UARTA, 0x304c, N, N), - PINGROUP(lcd_sdin_pz2, DISPLAYA, DISPLAYB, SPI5, RSVD4, 0x3078, N, N), - PINGROUP(lcd_wr_n_pz3, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x3080, N, N), - PINGROUP(lcd_sck_pz4, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x308c, N, N), - PINGROUP(sys_clk_req_pz5, SYSCLK, RSVD2, RSVD3, RSVD4, 0x3320, N, N), - PINGROUP(pwr_i2c_scl_pz6, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b4, Y, N), - PINGROUP(pwr_i2c_sda_pz7, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b8, Y, N), - PINGROUP(sdmmc4_dat0_paa0, UARTE, SPI3, GMI, SDMMC4, 0x3260, N, Y), - PINGROUP(sdmmc4_dat1_paa1, UARTE, SPI3, GMI, SDMMC4, 0x3264, N, Y), - PINGROUP(sdmmc4_dat2_paa2, UARTE, SPI3, GMI, SDMMC4, 0x3268, N, Y), - PINGROUP(sdmmc4_dat3_paa3, UARTE, SPI3, GMI, SDMMC4, 0x326c, N, Y), - PINGROUP(sdmmc4_dat4_paa4, I2C3, I2S4, GMI, SDMMC4, 0x3270, N, Y), - PINGROUP(sdmmc4_dat5_paa5, VGP3, I2S4, GMI, SDMMC4, 0x3274, N, Y), - PINGROUP(sdmmc4_dat6_paa6, VGP4, I2S4, GMI, SDMMC4, 0x3278, N, Y), - PINGROUP(sdmmc4_dat7_paa7, VGP5, I2S4, GMI, SDMMC4, 0x327c, N, Y), - PINGROUP(pbb0, I2S4, RSVD2, RSVD3, SDMMC4, 0x328c, N, N), - PINGROUP(cam_i2c_scl_pbb1, VGP1, I2C3, RSVD3, SDMMC4, 0x3290, Y, N), - PINGROUP(cam_i2c_sda_pbb2, VGP2, I2C3, RSVD3, SDMMC4, 0x3294, Y, N), - PINGROUP(pbb3, VGP3, DISPLAYA, DISPLAYB, SDMMC4, 0x3298, N, N), - PINGROUP(pbb4, VGP4, DISPLAYA, DISPLAYB, SDMMC4, 0x329c, N, N), - PINGROUP(pbb5, VGP5, DISPLAYA, DISPLAYB, SDMMC4, 0x32a0, N, N), - PINGROUP(pbb6, VGP6, DISPLAYA, DISPLAYB, SDMMC4, 0x32a4, N, N), - PINGROUP(pbb7, I2S4, RSVD2, RSVD3, SDMMC4, 0x32a8, N, N), - PINGROUP(cam_mclk_pcc0, VI, VI_ALT1, VI_ALT3, SDMMC4, 0x3284, N, N), - PINGROUP(pcc1, I2S4, RSVD2, RSVD3, SDMMC4, 0x3288, N, N), - PINGROUP(pcc2, I2S4, RSVD2, RSVD3, RSVD4, 0x32ac, N, N), - PINGROUP(sdmmc4_rst_n_pcc3, VGP6, RSVD2, RSVD3, SDMMC4, 0x3280, N, Y), - PINGROUP(sdmmc4_clk_pcc4, INVALID, NAND, GMI, SDMMC4, 0x3258, N, Y), - PINGROUP(clk2_req_pcc5, DAP, RSVD2, RSVD3, RSVD4, 0x306c, N, N), - PINGROUP(pex_l2_rst_n_pcc6, PCIE, HDA, RSVD3, RSVD4, 0x33d8, N, N), - PINGROUP(pex_l2_clkreq_n_pcc7, PCIE, HDA, RSVD3, RSVD4, 0x33dc, N, N), - PINGROUP(pex_l0_prsnt_n_pdd0, PCIE, HDA, RSVD3, RSVD4, 0x33b8, N, N), - PINGROUP(pex_l0_rst_n_pdd1, PCIE, HDA, RSVD3, RSVD4, 0x33bc, N, N), - PINGROUP(pex_l0_clkreq_n_pdd2, PCIE, HDA, RSVD3, RSVD4, 0x33c0, N, N), - PINGROUP(pex_wake_n_pdd3, PCIE, HDA, RSVD3, RSVD4, 0x33c4, N, N), - PINGROUP(pex_l1_prsnt_n_pdd4, PCIE, HDA, RSVD3, RSVD4, 0x33c8, N, N), - PINGROUP(pex_l1_rst_n_pdd5, PCIE, HDA, RSVD3, RSVD4, 0x33cc, N, N), - PINGROUP(pex_l1_clkreq_n_pdd6, PCIE, HDA, RSVD3, RSVD4, 0x33d0, N, N), - PINGROUP(pex_l2_prsnt_n_pdd7, PCIE, HDA, RSVD3, RSVD4, 0x33d4, N, N), - PINGROUP(clk3_out_pee0, EXTPERIPH3, RSVD2, RSVD3, RSVD4, 0x31b8, N, N), - PINGROUP(clk3_req_pee1, DEV3, RSVD2, RSVD3, RSVD4, 0x31bc, N, N), - PINGROUP(clk1_req_pee2, DAP, HDA, RSVD3, RSVD4, 0x3348, N, N), - PINGROUP(hdmi_cec_pee3, CEC, RSVD2, RSVD3, RSVD4, 0x33e0, Y, N), - PINGROUP(clk_32k_in, CLK_32K_IN, RSVD2, RSVD3, RSVD4, 0x3330, N, N), - PINGROUP(core_pwr_req, CORE_PWR_REQ, RSVD2, RSVD3, RSVD4, 0x3324, N, N), - PINGROUP(cpu_pwr_req, CPU_PWR_REQ, RSVD2, RSVD3, RSVD4, 0x3328, N, N), - PINGROUP(owr, OWR, CEC, RSVD3, RSVD4, 0x3334, N, N), - PINGROUP(pwr_int_n, PWR_INT_N, RSVD2, RSVD3, RSVD4, 0x332c, N, N), - /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */ - DRV_PINGROUP(ao1, 0x868, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(ao2, 0x86c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(at1, 0x870, 2, 3, 4, 14, 5, 19, 5, 24, 2, 28, 2), - DRV_PINGROUP(at2, 0x874, 2, 3, 4, 14, 5, 19, 5, 24, 2, 28, 2), - DRV_PINGROUP(at3, 0x878, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), - DRV_PINGROUP(at4, 0x87c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), - DRV_PINGROUP(at5, 0x880, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), - DRV_PINGROUP(cdev1, 0x884, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(cdev2, 0x888, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(cec, 0x938, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(crt, 0x8f8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(csus, 0x88c, -1, -1, -1, 12, 5, 19, 5, 24, 4, 28, 4), - DRV_PINGROUP(dap1, 0x890, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(dap2, 0x894, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(dap3, 0x898, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(dap4, 0x89c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(dbg, 0x8a0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(ddc, 0x8fc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(dev3, 0x92c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(gma, 0x900, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), - DRV_PINGROUP(gmb, 0x904, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), - DRV_PINGROUP(gmc, 0x908, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), - DRV_PINGROUP(gmd, 0x90c, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), - DRV_PINGROUP(gme, 0x910, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), - DRV_PINGROUP(gmf, 0x914, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), - DRV_PINGROUP(gmg, 0x918, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), - DRV_PINGROUP(gmh, 0x91c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), - DRV_PINGROUP(gpv, 0x928, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(lcd1, 0x8a4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(lcd2, 0x8a8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(owr, 0x920, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(sdio1, 0x8ec, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2), - DRV_PINGROUP(sdio2, 0x8ac, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2), - DRV_PINGROUP(sdio3, 0x8b0, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2), - DRV_PINGROUP(spi, 0x8b4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(uaa, 0x8b8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(uab, 0x8bc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(uart2, 0x8c0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(uart3, 0x8c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(uda, 0x924, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(vi1, 0x8c8, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), -}; - -static const struct tegra_pinctrl_soc_data tegra30_pinctrl = { - .ngpios = NUM_GPIOS, - .pins = tegra30_pins, - .npins = ARRAY_SIZE(tegra30_pins), - .functions = tegra30_functions, - .nfunctions = ARRAY_SIZE(tegra30_functions), - .groups = tegra30_groups, - .ngroups = ARRAY_SIZE(tegra30_groups), - .hsm_in_mux = false, - .schmitt_in_mux = false, - .drvtype_in_mux = false, -}; - -static int tegra30_pinctrl_probe(struct platform_device *pdev) -{ - return tegra_pinctrl_probe(pdev, &tegra30_pinctrl); -} - -static const struct of_device_id tegra30_pinctrl_of_match[] = { - { .compatible = "nvidia,tegra30-pinmux", }, - { }, -}; -MODULE_DEVICE_TABLE(of, tegra30_pinctrl_of_match); - -static struct platform_driver tegra30_pinctrl_driver = { - .driver = { - .name = "tegra30-pinctrl", - .of_match_table = tegra30_pinctrl_of_match, - }, - .probe = tegra30_pinctrl_probe, - .remove = tegra_pinctrl_remove, -}; -module_platform_driver(tegra30_pinctrl_driver); - -MODULE_AUTHOR("Stephen Warren "); -MODULE_DESCRIPTION("NVIDIA Tegra30 pinctrl driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/tegra/Kconfig b/drivers/pinctrl/tegra/Kconfig new file mode 100644 index 000000000000..24e20cc08d5b --- /dev/null +++ b/drivers/pinctrl/tegra/Kconfig @@ -0,0 +1,30 @@ +config PINCTRL_TEGRA + bool + select PINMUX + select PINCONF + +config PINCTRL_TEGRA20 + bool + select PINCTRL_TEGRA + +config PINCTRL_TEGRA30 + bool + select PINCTRL_TEGRA + +config PINCTRL_TEGRA114 + bool + select PINCTRL_TEGRA + +config PINCTRL_TEGRA124 + bool + select PINCTRL_TEGRA + +config PINCTRL_TEGRA210 + bool + select PINCTRL_TEGRA + +config PINCTRL_TEGRA_XUSB + def_bool y if ARCH_TEGRA + select GENERIC_PHY + select PINCONF + select PINMUX diff --git a/drivers/pinctrl/tegra/Makefile b/drivers/pinctrl/tegra/Makefile new file mode 100644 index 000000000000..a927379b6794 --- /dev/null +++ b/drivers/pinctrl/tegra/Makefile @@ -0,0 +1,7 @@ +obj-y += pinctrl-tegra.o +obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o +obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o +obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o +obj-$(CONFIG_PINCTRL_TEGRA124) += pinctrl-tegra124.o +obj-$(CONFIG_PINCTRL_TEGRA210) += pinctrl-tegra210.o +obj-$(CONFIG_PINCTRL_TEGRA_XUSB) += pinctrl-tegra-xusb.o diff --git a/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c b/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c new file mode 100644 index 000000000000..2f06029c9405 --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c @@ -0,0 +1,985 @@ +/* + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../core.h" +#include "../pinctrl-utils.h" + +#define XUSB_PADCTL_ELPG_PROGRAM 0x01c +#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26) +#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25) +#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24) + +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040 +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19) +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12) +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1) + +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044 +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6) +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5) +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4) + +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138 +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27) +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24) +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3) +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1) +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0) + +#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148 +#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1) +#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0) + +struct tegra_xusb_padctl_function { + const char *name; + const char * const *groups; + unsigned int num_groups; +}; + +struct tegra_xusb_padctl_soc { + const struct pinctrl_pin_desc *pins; + unsigned int num_pins; + + const struct tegra_xusb_padctl_function *functions; + unsigned int num_functions; + + const struct tegra_xusb_padctl_lane *lanes; + unsigned int num_lanes; +}; + +struct tegra_xusb_padctl_lane { + const char *name; + + unsigned int offset; + unsigned int shift; + unsigned int mask; + unsigned int iddq; + + const unsigned int *funcs; + unsigned int num_funcs; +}; + +struct tegra_xusb_padctl { + struct device *dev; + void __iomem *regs; + struct mutex lock; + struct reset_control *rst; + + const struct tegra_xusb_padctl_soc *soc; + struct pinctrl_dev *pinctrl; + struct pinctrl_desc desc; + + struct phy_provider *provider; + struct phy *phys[2]; + + unsigned int enable; +}; + +static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value, + unsigned long offset) +{ + writel(value, padctl->regs + offset); +} + +static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl, + unsigned long offset) +{ + return readl(padctl->regs + offset); +} + +static int tegra_xusb_padctl_get_groups_count(struct pinctrl_dev *pinctrl) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + + return padctl->soc->num_pins; +} + +static const char *tegra_xusb_padctl_get_group_name(struct pinctrl_dev *pinctrl, + unsigned int group) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + + return padctl->soc->pins[group].name; +} + +static int tegra_xusb_padctl_get_group_pins(struct pinctrl_dev *pinctrl, + unsigned group, + const unsigned **pins, + unsigned *num_pins) +{ + /* + * For the tegra-xusb pad controller groups are synonomous + * with lanes/pins and there is always one lane/pin per group. + */ + *pins = &pinctrl->desc->pins[group].number; + *num_pins = 1; + + return 0; +} + +enum tegra_xusb_padctl_param { + TEGRA_XUSB_PADCTL_IDDQ, +}; + +static const struct tegra_xusb_padctl_property { + const char *name; + enum tegra_xusb_padctl_param param; +} properties[] = { + { "nvidia,iddq", TEGRA_XUSB_PADCTL_IDDQ }, +}; + +#define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value)) +#define TEGRA_XUSB_PADCTL_UNPACK_PARAM(config) ((config) >> 16) +#define TEGRA_XUSB_PADCTL_UNPACK_VALUE(config) ((config) & 0xffff) + +static int tegra_xusb_padctl_parse_subnode(struct tegra_xusb_padctl *padctl, + struct device_node *np, + struct pinctrl_map **maps, + unsigned int *reserved_maps, + unsigned int *num_maps) +{ + unsigned int i, reserve = 0, num_configs = 0; + unsigned long config, *configs = NULL; + const char *function, *group; + struct property *prop; + int err = 0; + u32 value; + + err = of_property_read_string(np, "nvidia,function", &function); + if (err < 0) { + if (err != -EINVAL) + return err; + + function = NULL; + } + + for (i = 0; i < ARRAY_SIZE(properties); i++) { + err = of_property_read_u32(np, properties[i].name, &value); + if (err < 0) { + if (err == -EINVAL) + continue; + + goto out; + } + + config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, value); + + err = pinctrl_utils_add_config(padctl->pinctrl, &configs, + &num_configs, config); + if (err < 0) + goto out; + } + + if (function) + reserve++; + + if (num_configs) + reserve++; + + err = of_property_count_strings(np, "nvidia,lanes"); + if (err < 0) + goto out; + + reserve *= err; + + err = pinctrl_utils_reserve_map(padctl->pinctrl, maps, reserved_maps, + num_maps, reserve); + if (err < 0) + goto out; + + of_property_for_each_string(np, "nvidia,lanes", prop, group) { + if (function) { + err = pinctrl_utils_add_map_mux(padctl->pinctrl, maps, + reserved_maps, num_maps, group, + function); + if (err < 0) + goto out; + } + + if (num_configs) { + err = pinctrl_utils_add_map_configs(padctl->pinctrl, + maps, reserved_maps, num_maps, group, + configs, num_configs, + PIN_MAP_TYPE_CONFIGS_GROUP); + if (err < 0) + goto out; + } + } + + err = 0; + +out: + kfree(configs); + return err; +} + +static int tegra_xusb_padctl_dt_node_to_map(struct pinctrl_dev *pinctrl, + struct device_node *parent, + struct pinctrl_map **maps, + unsigned int *num_maps) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + unsigned int reserved_maps = 0; + struct device_node *np; + int err; + + *num_maps = 0; + *maps = NULL; + + for_each_child_of_node(parent, np) { + err = tegra_xusb_padctl_parse_subnode(padctl, np, maps, + &reserved_maps, + num_maps); + if (err < 0) { + of_node_put(np); + return err; + } + } + + return 0; +} + +static const struct pinctrl_ops tegra_xusb_padctl_pinctrl_ops = { + .get_groups_count = tegra_xusb_padctl_get_groups_count, + .get_group_name = tegra_xusb_padctl_get_group_name, + .get_group_pins = tegra_xusb_padctl_get_group_pins, + .dt_node_to_map = tegra_xusb_padctl_dt_node_to_map, + .dt_free_map = pinctrl_utils_dt_free_map, +}; + +static int tegra_xusb_padctl_get_functions_count(struct pinctrl_dev *pinctrl) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + + return padctl->soc->num_functions; +} + +static const char * +tegra_xusb_padctl_get_function_name(struct pinctrl_dev *pinctrl, + unsigned int function) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + + return padctl->soc->functions[function].name; +} + +static int tegra_xusb_padctl_get_function_groups(struct pinctrl_dev *pinctrl, + unsigned int function, + const char * const **groups, + unsigned * const num_groups) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + + *num_groups = padctl->soc->functions[function].num_groups; + *groups = padctl->soc->functions[function].groups; + + return 0; +} + +static int tegra_xusb_padctl_pinmux_set(struct pinctrl_dev *pinctrl, + unsigned int function, + unsigned int group) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + const struct tegra_xusb_padctl_lane *lane; + unsigned int i; + u32 value; + + lane = &padctl->soc->lanes[group]; + + for (i = 0; i < lane->num_funcs; i++) + if (lane->funcs[i] == function) + break; + + if (i >= lane->num_funcs) + return -EINVAL; + + value = padctl_readl(padctl, lane->offset); + value &= ~(lane->mask << lane->shift); + value |= i << lane->shift; + padctl_writel(padctl, value, lane->offset); + + return 0; +} + +static const struct pinmux_ops tegra_xusb_padctl_pinmux_ops = { + .get_functions_count = tegra_xusb_padctl_get_functions_count, + .get_function_name = tegra_xusb_padctl_get_function_name, + .get_function_groups = tegra_xusb_padctl_get_function_groups, + .set_mux = tegra_xusb_padctl_pinmux_set, +}; + +static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl, + unsigned int group, + unsigned long *config) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + const struct tegra_xusb_padctl_lane *lane; + enum tegra_xusb_padctl_param param; + u32 value; + + param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(*config); + lane = &padctl->soc->lanes[group]; + + switch (param) { + case TEGRA_XUSB_PADCTL_IDDQ: + /* lanes with iddq == 0 don't support this parameter */ + if (lane->iddq == 0) + return -EINVAL; + + value = padctl_readl(padctl, lane->offset); + + if (value & BIT(lane->iddq)) + value = 0; + else + value = 1; + + *config = TEGRA_XUSB_PADCTL_PACK(param, value); + break; + + default: + dev_err(padctl->dev, "invalid configuration parameter: %04x\n", + param); + return -ENOTSUPP; + } + + return 0; +} + +static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl, + unsigned int group, + unsigned long *configs, + unsigned int num_configs) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + const struct tegra_xusb_padctl_lane *lane; + enum tegra_xusb_padctl_param param; + unsigned long value; + unsigned int i; + u32 regval; + + lane = &padctl->soc->lanes[group]; + + for (i = 0; i < num_configs; i++) { + param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(configs[i]); + value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(configs[i]); + + switch (param) { + case TEGRA_XUSB_PADCTL_IDDQ: + /* lanes with iddq == 0 don't support this parameter */ + if (lane->iddq == 0) + return -EINVAL; + + regval = padctl_readl(padctl, lane->offset); + + if (value) + regval &= ~BIT(lane->iddq); + else + regval |= BIT(lane->iddq); + + padctl_writel(padctl, regval, lane->offset); + break; + + default: + dev_err(padctl->dev, + "invalid configuration parameter: %04x\n", + param); + return -ENOTSUPP; + } + } + + return 0; +} + +#ifdef CONFIG_DEBUG_FS +static const char *strip_prefix(const char *s) +{ + const char *comma = strchr(s, ','); + if (!comma) + return s; + + return comma + 1; +} + +static void +tegra_xusb_padctl_pinconf_group_dbg_show(struct pinctrl_dev *pinctrl, + struct seq_file *s, + unsigned int group) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(properties); i++) { + unsigned long config, value; + int err; + + config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, 0); + + err = tegra_xusb_padctl_pinconf_group_get(pinctrl, group, + &config); + if (err < 0) + continue; + + value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config); + + seq_printf(s, "\n\t%s=%lu\n", strip_prefix(properties[i].name), + value); + } +} + +static void +tegra_xusb_padctl_pinconf_config_dbg_show(struct pinctrl_dev *pinctrl, + struct seq_file *s, + unsigned long config) +{ + enum tegra_xusb_padctl_param param; + const char *name = "unknown"; + unsigned long value; + unsigned int i; + + param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(config); + value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config); + + for (i = 0; i < ARRAY_SIZE(properties); i++) { + if (properties[i].param == param) { + name = properties[i].name; + break; + } + } + + seq_printf(s, "%s=%lu", strip_prefix(name), value); +} +#endif + +static const struct pinconf_ops tegra_xusb_padctl_pinconf_ops = { + .pin_config_group_get = tegra_xusb_padctl_pinconf_group_get, + .pin_config_group_set = tegra_xusb_padctl_pinconf_group_set, +#ifdef CONFIG_DEBUG_FS + .pin_config_group_dbg_show = tegra_xusb_padctl_pinconf_group_dbg_show, + .pin_config_config_dbg_show = tegra_xusb_padctl_pinconf_config_dbg_show, +#endif +}; + +static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) +{ + u32 value; + + mutex_lock(&padctl->lock); + + if (padctl->enable++ > 0) + goto out; + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + + usleep_range(100, 200); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + + usleep_range(100, 200); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + +out: + mutex_unlock(&padctl->lock); + return 0; +} + +static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) +{ + u32 value; + + mutex_lock(&padctl->lock); + + if (WARN_ON(padctl->enable == 0)) + goto out; + + if (--padctl->enable > 0) + goto out; + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + + usleep_range(100, 200); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + + usleep_range(100, 200); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + +out: + mutex_unlock(&padctl->lock); + return 0; +} + +static int tegra_xusb_phy_init(struct phy *phy) +{ + struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); + + return tegra_xusb_padctl_enable(padctl); +} + +static int tegra_xusb_phy_exit(struct phy *phy) +{ + struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); + + return tegra_xusb_padctl_disable(padctl); +} + +static int pcie_phy_power_on(struct phy *phy) +{ + struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); + unsigned long timeout; + int err = -ETIMEDOUT; + u32 value; + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); + value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN | + XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN | + XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + + timeout = jiffies + msecs_to_jiffies(50); + + while (time_before(jiffies, timeout)) { + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) { + err = 0; + break; + } + + usleep_range(100, 200); + } + + return err; +} + +static int pcie_phy_power_off(struct phy *phy) +{ + struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); + u32 value; + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + + return 0; +} + +static const struct phy_ops pcie_phy_ops = { + .init = tegra_xusb_phy_init, + .exit = tegra_xusb_phy_exit, + .power_on = pcie_phy_power_on, + .power_off = pcie_phy_power_off, + .owner = THIS_MODULE, +}; + +static int sata_phy_power_on(struct phy *phy) +{ + struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); + unsigned long timeout; + int err = -ETIMEDOUT; + u32 value; + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); + value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; + value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; + value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + + timeout = jiffies + msecs_to_jiffies(50); + + while (time_before(jiffies, timeout)) { + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) { + err = 0; + break; + } + + usleep_range(100, 200); + } + + return err; +} + +static int sata_phy_power_off(struct phy *phy) +{ + struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); + u32 value; + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; + value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); + value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; + value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); + + return 0; +} + +static const struct phy_ops sata_phy_ops = { + .init = tegra_xusb_phy_init, + .exit = tegra_xusb_phy_exit, + .power_on = sata_phy_power_on, + .power_off = sata_phy_power_off, + .owner = THIS_MODULE, +}; + +static struct phy *tegra_xusb_padctl_xlate(struct device *dev, + struct of_phandle_args *args) +{ + struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev); + unsigned int index = args->args[0]; + + if (args->args_count <= 0) + return ERR_PTR(-EINVAL); + + if (index >= ARRAY_SIZE(padctl->phys)) + return ERR_PTR(-EINVAL); + + return padctl->phys[index]; +} + +#define PIN_OTG_0 0 +#define PIN_OTG_1 1 +#define PIN_OTG_2 2 +#define PIN_ULPI_0 3 +#define PIN_HSIC_0 4 +#define PIN_HSIC_1 5 +#define PIN_PCIE_0 6 +#define PIN_PCIE_1 7 +#define PIN_PCIE_2 8 +#define PIN_PCIE_3 9 +#define PIN_PCIE_4 10 +#define PIN_SATA_0 11 + +static const struct pinctrl_pin_desc tegra124_pins[] = { + PINCTRL_PIN(PIN_OTG_0, "otg-0"), + PINCTRL_PIN(PIN_OTG_1, "otg-1"), + PINCTRL_PIN(PIN_OTG_2, "otg-2"), + PINCTRL_PIN(PIN_ULPI_0, "ulpi-0"), + PINCTRL_PIN(PIN_HSIC_0, "hsic-0"), + PINCTRL_PIN(PIN_HSIC_1, "hsic-1"), + PINCTRL_PIN(PIN_PCIE_0, "pcie-0"), + PINCTRL_PIN(PIN_PCIE_1, "pcie-1"), + PINCTRL_PIN(PIN_PCIE_2, "pcie-2"), + PINCTRL_PIN(PIN_PCIE_3, "pcie-3"), + PINCTRL_PIN(PIN_PCIE_4, "pcie-4"), + PINCTRL_PIN(PIN_SATA_0, "sata-0"), +}; + +static const char * const tegra124_snps_groups[] = { + "otg-0", + "otg-1", + "otg-2", + "ulpi-0", + "hsic-0", + "hsic-1", +}; + +static const char * const tegra124_xusb_groups[] = { + "otg-0", + "otg-1", + "otg-2", + "ulpi-0", + "hsic-0", + "hsic-1", +}; + +static const char * const tegra124_uart_groups[] = { + "otg-0", + "otg-1", + "otg-2", +}; + +static const char * const tegra124_pcie_groups[] = { + "pcie-0", + "pcie-1", + "pcie-2", + "pcie-3", + "pcie-4", +}; + +static const char * const tegra124_usb3_groups[] = { + "pcie-0", + "pcie-1", + "sata-0", +}; + +static const char * const tegra124_sata_groups[] = { + "sata-0", +}; + +static const char * const tegra124_rsvd_groups[] = { + "otg-0", + "otg-1", + "otg-2", + "pcie-0", + "pcie-1", + "pcie-2", + "pcie-3", + "pcie-4", + "sata-0", +}; + +#define TEGRA124_FUNCTION(_name) \ + { \ + .name = #_name, \ + .num_groups = ARRAY_SIZE(tegra124_##_name##_groups), \ + .groups = tegra124_##_name##_groups, \ + } + +static struct tegra_xusb_padctl_function tegra124_functions[] = { + TEGRA124_FUNCTION(snps), + TEGRA124_FUNCTION(xusb), + TEGRA124_FUNCTION(uart), + TEGRA124_FUNCTION(pcie), + TEGRA124_FUNCTION(usb3), + TEGRA124_FUNCTION(sata), + TEGRA124_FUNCTION(rsvd), +}; + +enum tegra124_function { + TEGRA124_FUNC_SNPS, + TEGRA124_FUNC_XUSB, + TEGRA124_FUNC_UART, + TEGRA124_FUNC_PCIE, + TEGRA124_FUNC_USB3, + TEGRA124_FUNC_SATA, + TEGRA124_FUNC_RSVD, +}; + +static const unsigned int tegra124_otg_functions[] = { + TEGRA124_FUNC_SNPS, + TEGRA124_FUNC_XUSB, + TEGRA124_FUNC_UART, + TEGRA124_FUNC_RSVD, +}; + +static const unsigned int tegra124_usb_functions[] = { + TEGRA124_FUNC_SNPS, + TEGRA124_FUNC_XUSB, +}; + +static const unsigned int tegra124_pci_functions[] = { + TEGRA124_FUNC_PCIE, + TEGRA124_FUNC_USB3, + TEGRA124_FUNC_SATA, + TEGRA124_FUNC_RSVD, +}; + +#define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs) \ + { \ + .name = _name, \ + .offset = _offset, \ + .shift = _shift, \ + .mask = _mask, \ + .iddq = _iddq, \ + .num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions), \ + .funcs = tegra124_##_funcs##_functions, \ + } + +static const struct tegra_xusb_padctl_lane tegra124_lanes[] = { + TEGRA124_LANE("otg-0", 0x004, 0, 0x3, 0, otg), + TEGRA124_LANE("otg-1", 0x004, 2, 0x3, 0, otg), + TEGRA124_LANE("otg-2", 0x004, 4, 0x3, 0, otg), + TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb), + TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb), + TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb), + TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci), + TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci), + TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci), + TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci), + TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci), + TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci), +}; + +static const struct tegra_xusb_padctl_soc tegra124_soc = { + .num_pins = ARRAY_SIZE(tegra124_pins), + .pins = tegra124_pins, + .num_functions = ARRAY_SIZE(tegra124_functions), + .functions = tegra124_functions, + .num_lanes = ARRAY_SIZE(tegra124_lanes), + .lanes = tegra124_lanes, +}; + +static const struct of_device_id tegra_xusb_padctl_of_match[] = { + { .compatible = "nvidia,tegra124-xusb-padctl", .data = &tegra124_soc }, + { } +}; +MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match); + +static int tegra_xusb_padctl_probe(struct platform_device *pdev) +{ + struct tegra_xusb_padctl *padctl; + const struct of_device_id *match; + struct resource *res; + struct phy *phy; + int err; + + padctl = devm_kzalloc(&pdev->dev, sizeof(*padctl), GFP_KERNEL); + if (!padctl) + return -ENOMEM; + + platform_set_drvdata(pdev, padctl); + mutex_init(&padctl->lock); + padctl->dev = &pdev->dev; + + match = of_match_node(tegra_xusb_padctl_of_match, pdev->dev.of_node); + padctl->soc = match->data; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + padctl->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(padctl->regs)) + return PTR_ERR(padctl->regs); + + padctl->rst = devm_reset_control_get(&pdev->dev, NULL); + if (IS_ERR(padctl->rst)) + return PTR_ERR(padctl->rst); + + err = reset_control_deassert(padctl->rst); + if (err < 0) + return err; + + memset(&padctl->desc, 0, sizeof(padctl->desc)); + padctl->desc.name = dev_name(padctl->dev); + padctl->desc.pins = tegra124_pins; + padctl->desc.npins = ARRAY_SIZE(tegra124_pins); + padctl->desc.pctlops = &tegra_xusb_padctl_pinctrl_ops; + padctl->desc.pmxops = &tegra_xusb_padctl_pinmux_ops; + padctl->desc.confops = &tegra_xusb_padctl_pinconf_ops; + padctl->desc.owner = THIS_MODULE; + + padctl->pinctrl = pinctrl_register(&padctl->desc, &pdev->dev, padctl); + if (IS_ERR(padctl->pinctrl)) { + dev_err(&pdev->dev, "failed to register pincontrol\n"); + err = PTR_ERR(padctl->pinctrl); + goto reset; + } + + phy = devm_phy_create(&pdev->dev, NULL, &pcie_phy_ops); + if (IS_ERR(phy)) { + err = PTR_ERR(phy); + goto unregister; + } + + padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy; + phy_set_drvdata(phy, padctl); + + phy = devm_phy_create(&pdev->dev, NULL, &sata_phy_ops); + if (IS_ERR(phy)) { + err = PTR_ERR(phy); + goto unregister; + } + + padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy; + phy_set_drvdata(phy, padctl); + + padctl->provider = devm_of_phy_provider_register(&pdev->dev, + tegra_xusb_padctl_xlate); + if (IS_ERR(padctl->provider)) { + err = PTR_ERR(padctl->provider); + dev_err(&pdev->dev, "failed to register PHYs: %d\n", err); + goto unregister; + } + + return 0; + +unregister: + pinctrl_unregister(padctl->pinctrl); +reset: + reset_control_assert(padctl->rst); + return err; +} + +static int tegra_xusb_padctl_remove(struct platform_device *pdev) +{ + struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev); + int err; + + pinctrl_unregister(padctl->pinctrl); + + err = reset_control_assert(padctl->rst); + if (err < 0) + dev_err(&pdev->dev, "failed to assert reset: %d\n", err); + + return err; +} + +static struct platform_driver tegra_xusb_padctl_driver = { + .driver = { + .name = "tegra-xusb-padctl", + .of_match_table = tegra_xusb_padctl_of_match, + }, + .probe = tegra_xusb_padctl_probe, + .remove = tegra_xusb_padctl_remove, +}; +module_platform_driver(tegra_xusb_padctl_driver); + +MODULE_AUTHOR("Thierry Reding "); +MODULE_DESCRIPTION("Tegra 124 XUSB Pad Control driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c new file mode 100644 index 000000000000..49388822c0e9 --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c @@ -0,0 +1,747 @@ +/* + * Driver for the NVIDIA Tegra pinmux + * + * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. + * + * Derived from code: + * Copyright (C) 2010 Google, Inc. + * Copyright (C) 2010 NVIDIA Corporation + * Copyright (C) 2009-2011 ST-Ericsson AB + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../core.h" +#include "../pinctrl-utils.h" +#include "pinctrl-tegra.h" + +struct tegra_pmx { + struct device *dev; + struct pinctrl_dev *pctl; + + const struct tegra_pinctrl_soc_data *soc; + const char **group_pins; + + int nbanks; + void __iomem **regs; +}; + +static inline u32 pmx_readl(struct tegra_pmx *pmx, u32 bank, u32 reg) +{ + return readl(pmx->regs[bank] + reg); +} + +static inline void pmx_writel(struct tegra_pmx *pmx, u32 val, u32 bank, u32 reg) +{ + writel(val, pmx->regs[bank] + reg); +} + +static int tegra_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + + return pmx->soc->ngroups; +} + +static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned group) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + + return pmx->soc->groups[group].name; +} + +static int tegra_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, + unsigned group, + const unsigned **pins, + unsigned *num_pins) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + + *pins = pmx->soc->groups[group].pins; + *num_pins = pmx->soc->groups[group].npins; + + return 0; +} + +#ifdef CONFIG_DEBUG_FS +static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, + unsigned offset) +{ + seq_printf(s, " %s", dev_name(pctldev->dev)); +} +#endif + +static const struct cfg_param { + const char *property; + enum tegra_pinconf_param param; +} cfg_params[] = { + {"nvidia,pull", TEGRA_PINCONF_PARAM_PULL}, + {"nvidia,tristate", TEGRA_PINCONF_PARAM_TRISTATE}, + {"nvidia,enable-input", TEGRA_PINCONF_PARAM_ENABLE_INPUT}, + {"nvidia,open-drain", TEGRA_PINCONF_PARAM_OPEN_DRAIN}, + {"nvidia,lock", TEGRA_PINCONF_PARAM_LOCK}, + {"nvidia,io-reset", TEGRA_PINCONF_PARAM_IORESET}, + {"nvidia,rcv-sel", TEGRA_PINCONF_PARAM_RCV_SEL}, + {"nvidia,io-hv", TEGRA_PINCONF_PARAM_RCV_SEL}, + {"nvidia,high-speed-mode", TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE}, + {"nvidia,schmitt", TEGRA_PINCONF_PARAM_SCHMITT}, + {"nvidia,low-power-mode", TEGRA_PINCONF_PARAM_LOW_POWER_MODE}, + {"nvidia,pull-down-strength", TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH}, + {"nvidia,pull-up-strength", TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH}, + {"nvidia,slew-rate-falling", TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING}, + {"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING}, + {"nvidia,drive-type", TEGRA_PINCONF_PARAM_DRIVE_TYPE}, +}; + +static int tegra_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, + struct device_node *np, + struct pinctrl_map **map, + unsigned *reserved_maps, + unsigned *num_maps) +{ + struct device *dev = pctldev->dev; + int ret, i; + const char *function; + u32 val; + unsigned long config; + unsigned long *configs = NULL; + unsigned num_configs = 0; + unsigned reserve; + struct property *prop; + const char *group; + + ret = of_property_read_string(np, "nvidia,function", &function); + if (ret < 0) { + /* EINVAL=missing, which is fine since it's optional */ + if (ret != -EINVAL) + dev_err(dev, + "could not parse property nvidia,function\n"); + function = NULL; + } + + for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { + ret = of_property_read_u32(np, cfg_params[i].property, &val); + if (!ret) { + config = TEGRA_PINCONF_PACK(cfg_params[i].param, val); + ret = pinctrl_utils_add_config(pctldev, &configs, + &num_configs, config); + if (ret < 0) + goto exit; + /* EINVAL=missing, which is fine since it's optional */ + } else if (ret != -EINVAL) { + dev_err(dev, "could not parse property %s\n", + cfg_params[i].property); + } + } + + reserve = 0; + if (function != NULL) + reserve++; + if (num_configs) + reserve++; + ret = of_property_count_strings(np, "nvidia,pins"); + if (ret < 0) { + dev_err(dev, "could not parse property nvidia,pins\n"); + goto exit; + } + reserve *= ret; + + ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, + num_maps, reserve); + if (ret < 0) + goto exit; + + of_property_for_each_string(np, "nvidia,pins", prop, group) { + if (function) { + ret = pinctrl_utils_add_map_mux(pctldev, map, + reserved_maps, num_maps, group, + function); + if (ret < 0) + goto exit; + } + + if (num_configs) { + ret = pinctrl_utils_add_map_configs(pctldev, map, + reserved_maps, num_maps, group, + configs, num_configs, + PIN_MAP_TYPE_CONFIGS_GROUP); + if (ret < 0) + goto exit; + } + } + + ret = 0; + +exit: + kfree(configs); + return ret; +} + +static int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np_config, + struct pinctrl_map **map, + unsigned *num_maps) +{ + unsigned reserved_maps; + struct device_node *np; + int ret; + + reserved_maps = 0; + *map = NULL; + *num_maps = 0; + + for_each_child_of_node(np_config, np) { + ret = tegra_pinctrl_dt_subnode_to_map(pctldev, np, map, + &reserved_maps, num_maps); + if (ret < 0) { + pinctrl_utils_dt_free_map(pctldev, *map, + *num_maps); + of_node_put(np); + return ret; + } + } + + return 0; +} + +static const struct pinctrl_ops tegra_pinctrl_ops = { + .get_groups_count = tegra_pinctrl_get_groups_count, + .get_group_name = tegra_pinctrl_get_group_name, + .get_group_pins = tegra_pinctrl_get_group_pins, +#ifdef CONFIG_DEBUG_FS + .pin_dbg_show = tegra_pinctrl_pin_dbg_show, +#endif + .dt_node_to_map = tegra_pinctrl_dt_node_to_map, + .dt_free_map = pinctrl_utils_dt_free_map, +}; + +static int tegra_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + + return pmx->soc->nfunctions; +} + +static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev, + unsigned function) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + + return pmx->soc->functions[function].name; +} + +static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, + unsigned function, + const char * const **groups, + unsigned * const num_groups) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + + *groups = pmx->soc->functions[function].groups; + *num_groups = pmx->soc->functions[function].ngroups; + + return 0; +} + +static int tegra_pinctrl_set_mux(struct pinctrl_dev *pctldev, + unsigned function, + unsigned group) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + const struct tegra_pingroup *g; + int i; + u32 val; + + g = &pmx->soc->groups[group]; + + if (WARN_ON(g->mux_reg < 0)) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(g->funcs); i++) { + if (g->funcs[i] == function) + break; + } + if (WARN_ON(i == ARRAY_SIZE(g->funcs))) + return -EINVAL; + + val = pmx_readl(pmx, g->mux_bank, g->mux_reg); + val &= ~(0x3 << g->mux_bit); + val |= i << g->mux_bit; + pmx_writel(pmx, val, g->mux_bank, g->mux_reg); + + return 0; +} + +static const struct pinmux_ops tegra_pinmux_ops = { + .get_functions_count = tegra_pinctrl_get_funcs_count, + .get_function_name = tegra_pinctrl_get_func_name, + .get_function_groups = tegra_pinctrl_get_func_groups, + .set_mux = tegra_pinctrl_set_mux, +}; + +static int tegra_pinconf_reg(struct tegra_pmx *pmx, + const struct tegra_pingroup *g, + enum tegra_pinconf_param param, + bool report_err, + s8 *bank, s16 *reg, s8 *bit, s8 *width) +{ + switch (param) { + case TEGRA_PINCONF_PARAM_PULL: + *bank = g->pupd_bank; + *reg = g->pupd_reg; + *bit = g->pupd_bit; + *width = 2; + break; + case TEGRA_PINCONF_PARAM_TRISTATE: + *bank = g->tri_bank; + *reg = g->tri_reg; + *bit = g->tri_bit; + *width = 1; + break; + case TEGRA_PINCONF_PARAM_ENABLE_INPUT: + *bank = g->mux_bank; + *reg = g->mux_reg; + *bit = g->einput_bit; + *width = 1; + break; + case TEGRA_PINCONF_PARAM_OPEN_DRAIN: + *bank = g->mux_bank; + *reg = g->mux_reg; + *bit = g->odrain_bit; + *width = 1; + break; + case TEGRA_PINCONF_PARAM_LOCK: + *bank = g->mux_bank; + *reg = g->mux_reg; + *bit = g->lock_bit; + *width = 1; + break; + case TEGRA_PINCONF_PARAM_IORESET: + *bank = g->mux_bank; + *reg = g->mux_reg; + *bit = g->ioreset_bit; + *width = 1; + break; + case TEGRA_PINCONF_PARAM_RCV_SEL: + *bank = g->mux_bank; + *reg = g->mux_reg; + *bit = g->rcv_sel_bit; + *width = 1; + break; + case TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE: + if (pmx->soc->hsm_in_mux) { + *bank = g->mux_bank; + *reg = g->mux_reg; + } else { + *bank = g->drv_bank; + *reg = g->drv_reg; + } + *bit = g->hsm_bit; + *width = 1; + break; + case TEGRA_PINCONF_PARAM_SCHMITT: + if (pmx->soc->schmitt_in_mux) { + *bank = g->mux_bank; + *reg = g->mux_reg; + } else { + *bank = g->drv_bank; + *reg = g->drv_reg; + } + *bit = g->schmitt_bit; + *width = 1; + break; + case TEGRA_PINCONF_PARAM_LOW_POWER_MODE: + *bank = g->drv_bank; + *reg = g->drv_reg; + *bit = g->lpmd_bit; + *width = 2; + break; + case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH: + *bank = g->drv_bank; + *reg = g->drv_reg; + *bit = g->drvdn_bit; + *width = g->drvdn_width; + break; + case TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH: + *bank = g->drv_bank; + *reg = g->drv_reg; + *bit = g->drvup_bit; + *width = g->drvup_width; + break; + case TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING: + *bank = g->drv_bank; + *reg = g->drv_reg; + *bit = g->slwf_bit; + *width = g->slwf_width; + break; + case TEGRA_PINCONF_PARAM_SLEW_RATE_RISING: + *bank = g->drv_bank; + *reg = g->drv_reg; + *bit = g->slwr_bit; + *width = g->slwr_width; + break; + case TEGRA_PINCONF_PARAM_DRIVE_TYPE: + if (pmx->soc->drvtype_in_mux) { + *bank = g->mux_bank; + *reg = g->mux_reg; + } else { + *bank = g->drv_bank; + *reg = g->drv_reg; + } + *bit = g->drvtype_bit; + *width = 2; + break; + default: + dev_err(pmx->dev, "Invalid config param %04x\n", param); + return -ENOTSUPP; + } + + if (*reg < 0 || *bit > 31) { + if (report_err) { + const char *prop = "unknown"; + int i; + + for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { + if (cfg_params[i].param == param) { + prop = cfg_params[i].property; + break; + } + } + + dev_err(pmx->dev, + "Config param %04x (%s) not supported on group %s\n", + param, prop, g->name); + } + return -ENOTSUPP; + } + + return 0; +} + +static int tegra_pinconf_get(struct pinctrl_dev *pctldev, + unsigned pin, unsigned long *config) +{ + dev_err(pctldev->dev, "pin_config_get op not supported\n"); + return -ENOTSUPP; +} + +static int tegra_pinconf_set(struct pinctrl_dev *pctldev, + unsigned pin, unsigned long *configs, + unsigned num_configs) +{ + dev_err(pctldev->dev, "pin_config_set op not supported\n"); + return -ENOTSUPP; +} + +static int tegra_pinconf_group_get(struct pinctrl_dev *pctldev, + unsigned group, unsigned long *config) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(*config); + u16 arg; + const struct tegra_pingroup *g; + int ret; + s8 bank, bit, width; + s16 reg; + u32 val, mask; + + g = &pmx->soc->groups[group]; + + ret = tegra_pinconf_reg(pmx, g, param, true, &bank, ®, &bit, + &width); + if (ret < 0) + return ret; + + val = pmx_readl(pmx, bank, reg); + mask = (1 << width) - 1; + arg = (val >> bit) & mask; + + *config = TEGRA_PINCONF_PACK(param, arg); + + return 0; +} + +static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev, + unsigned group, unsigned long *configs, + unsigned num_configs) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + enum tegra_pinconf_param param; + u16 arg; + const struct tegra_pingroup *g; + int ret, i; + s8 bank, bit, width; + s16 reg; + u32 val, mask; + + g = &pmx->soc->groups[group]; + + for (i = 0; i < num_configs; i++) { + param = TEGRA_PINCONF_UNPACK_PARAM(configs[i]); + arg = TEGRA_PINCONF_UNPACK_ARG(configs[i]); + + ret = tegra_pinconf_reg(pmx, g, param, true, &bank, ®, &bit, + &width); + if (ret < 0) + return ret; + + val = pmx_readl(pmx, bank, reg); + + /* LOCK can't be cleared */ + if (param == TEGRA_PINCONF_PARAM_LOCK) { + if ((val & BIT(bit)) && !arg) { + dev_err(pctldev->dev, "LOCK bit cannot be cleared\n"); + return -EINVAL; + } + } + + /* Special-case Boolean values; allow any non-zero as true */ + if (width == 1) + arg = !!arg; + + /* Range-check user-supplied value */ + mask = (1 << width) - 1; + if (arg & ~mask) { + dev_err(pctldev->dev, + "config %lx: %x too big for %d bit register\n", + configs[i], arg, width); + return -EINVAL; + } + + /* Update register */ + val &= ~(mask << bit); + val |= arg << bit; + pmx_writel(pmx, val, bank, reg); + } /* for each config */ + + return 0; +} + +#ifdef CONFIG_DEBUG_FS +static void tegra_pinconf_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned offset) +{ +} + +static const char *strip_prefix(const char *s) +{ + const char *comma = strchr(s, ','); + if (!comma) + return s; + + return comma + 1; +} + +static void tegra_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned group) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + const struct tegra_pingroup *g; + int i, ret; + s8 bank, bit, width; + s16 reg; + u32 val; + + g = &pmx->soc->groups[group]; + + for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { + ret = tegra_pinconf_reg(pmx, g, cfg_params[i].param, false, + &bank, ®, &bit, &width); + if (ret < 0) + continue; + + val = pmx_readl(pmx, bank, reg); + val >>= bit; + val &= (1 << width) - 1; + + seq_printf(s, "\n\t%s=%u", + strip_prefix(cfg_params[i].property), val); + } +} + +static void tegra_pinconf_config_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, + unsigned long config) +{ + enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(config); + u16 arg = TEGRA_PINCONF_UNPACK_ARG(config); + const char *pname = "unknown"; + int i; + + for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { + if (cfg_params[i].param == param) { + pname = cfg_params[i].property; + break; + } + } + + seq_printf(s, "%s=%d", strip_prefix(pname), arg); +} +#endif + +static const struct pinconf_ops tegra_pinconf_ops = { + .pin_config_get = tegra_pinconf_get, + .pin_config_set = tegra_pinconf_set, + .pin_config_group_get = tegra_pinconf_group_get, + .pin_config_group_set = tegra_pinconf_group_set, +#ifdef CONFIG_DEBUG_FS + .pin_config_dbg_show = tegra_pinconf_dbg_show, + .pin_config_group_dbg_show = tegra_pinconf_group_dbg_show, + .pin_config_config_dbg_show = tegra_pinconf_config_dbg_show, +#endif +}; + +static struct pinctrl_gpio_range tegra_pinctrl_gpio_range = { + .name = "Tegra GPIOs", + .id = 0, + .base = 0, +}; + +static struct pinctrl_desc tegra_pinctrl_desc = { + .pctlops = &tegra_pinctrl_ops, + .pmxops = &tegra_pinmux_ops, + .confops = &tegra_pinconf_ops, + .owner = THIS_MODULE, +}; + +static bool gpio_node_has_range(void) +{ + struct device_node *np; + bool has_prop = false; + + np = of_find_compatible_node(NULL, NULL, "nvidia,tegra30-gpio"); + if (!np) + return has_prop; + + has_prop = of_find_property(np, "gpio-ranges", NULL); + + of_node_put(np); + + return has_prop; +} + +int tegra_pinctrl_probe(struct platform_device *pdev, + const struct tegra_pinctrl_soc_data *soc_data) +{ + struct tegra_pmx *pmx; + struct resource *res; + int i; + const char **group_pins; + int fn, gn, gfn; + + pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL); + if (!pmx) { + dev_err(&pdev->dev, "Can't alloc tegra_pmx\n"); + return -ENOMEM; + } + pmx->dev = &pdev->dev; + pmx->soc = soc_data; + + /* + * Each mux group will appear in 4 functions' list of groups. + * This over-allocates slightly, since not all groups are mux groups. + */ + pmx->group_pins = devm_kzalloc(&pdev->dev, + soc_data->ngroups * 4 * sizeof(*pmx->group_pins), + GFP_KERNEL); + if (!pmx->group_pins) + return -ENOMEM; + + group_pins = pmx->group_pins; + for (fn = 0; fn < soc_data->nfunctions; fn++) { + struct tegra_function *func = &soc_data->functions[fn]; + + func->groups = group_pins; + + for (gn = 0; gn < soc_data->ngroups; gn++) { + const struct tegra_pingroup *g = &soc_data->groups[gn]; + + if (g->mux_reg == -1) + continue; + + for (gfn = 0; gfn < 4; gfn++) + if (g->funcs[gfn] == fn) + break; + if (gfn == 4) + continue; + + BUG_ON(group_pins - pmx->group_pins >= + soc_data->ngroups * 4); + *group_pins++ = g->name; + func->ngroups++; + } + } + + tegra_pinctrl_gpio_range.npins = pmx->soc->ngpios; + tegra_pinctrl_desc.name = dev_name(&pdev->dev); + tegra_pinctrl_desc.pins = pmx->soc->pins; + tegra_pinctrl_desc.npins = pmx->soc->npins; + + for (i = 0; ; i++) { + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + if (!res) + break; + } + pmx->nbanks = i; + + pmx->regs = devm_kzalloc(&pdev->dev, pmx->nbanks * sizeof(*pmx->regs), + GFP_KERNEL); + if (!pmx->regs) { + dev_err(&pdev->dev, "Can't alloc regs pointer\n"); + return -ENOMEM; + } + + for (i = 0; i < pmx->nbanks; i++) { + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + pmx->regs[i] = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pmx->regs[i])) + return PTR_ERR(pmx->regs[i]); + } + + pmx->pctl = pinctrl_register(&tegra_pinctrl_desc, &pdev->dev, pmx); + if (IS_ERR(pmx->pctl)) { + dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); + return PTR_ERR(pmx->pctl); + } + + if (!gpio_node_has_range()) + pinctrl_add_gpio_range(pmx->pctl, &tegra_pinctrl_gpio_range); + + platform_set_drvdata(pdev, pmx); + + dev_dbg(&pdev->dev, "Probed Tegra pinctrl driver\n"); + + return 0; +} +EXPORT_SYMBOL_GPL(tegra_pinctrl_probe); + +int tegra_pinctrl_remove(struct platform_device *pdev) +{ + struct tegra_pmx *pmx = platform_get_drvdata(pdev); + + pinctrl_unregister(pmx->pctl); + + return 0; +} +EXPORT_SYMBOL_GPL(tegra_pinctrl_remove); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.h b/drivers/pinctrl/tegra/pinctrl-tegra.h new file mode 100644 index 000000000000..1615db7e3a4b --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra.h @@ -0,0 +1,194 @@ +/* + * Driver for the NVIDIA Tegra pinmux + * + * Copyright (c) 2011, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#ifndef __PINMUX_TEGRA_H__ +#define __PINMUX_TEGRA_H__ + +enum tegra_pinconf_param { + /* argument: tegra_pinconf_pull */ + TEGRA_PINCONF_PARAM_PULL, + /* argument: tegra_pinconf_tristate */ + TEGRA_PINCONF_PARAM_TRISTATE, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_ENABLE_INPUT, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_OPEN_DRAIN, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_LOCK, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_IORESET, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_RCV_SEL, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_SCHMITT, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_LOW_POWER_MODE, + /* argument: Integer, range is HW-dependant */ + TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH, + /* argument: Integer, range is HW-dependant */ + TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH, + /* argument: Integer, range is HW-dependant */ + TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING, + /* argument: Integer, range is HW-dependant */ + TEGRA_PINCONF_PARAM_SLEW_RATE_RISING, + /* argument: Integer, range is HW-dependant */ + TEGRA_PINCONF_PARAM_DRIVE_TYPE, +}; + +enum tegra_pinconf_pull { + TEGRA_PINCONFIG_PULL_NONE, + TEGRA_PINCONFIG_PULL_DOWN, + TEGRA_PINCONFIG_PULL_UP, +}; + +enum tegra_pinconf_tristate { + TEGRA_PINCONFIG_DRIVEN, + TEGRA_PINCONFIG_TRISTATE, +}; + +#define TEGRA_PINCONF_PACK(_param_, _arg_) ((_param_) << 16 | (_arg_)) +#define TEGRA_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16) +#define TEGRA_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff) + +/** + * struct tegra_function - Tegra pinctrl mux function + * @name: The name of the function, exported to pinctrl core. + * @groups: An array of pin groups that may select this function. + * @ngroups: The number of entries in @groups. + */ +struct tegra_function { + const char *name; + const char **groups; + unsigned ngroups; +}; + +/** + * struct tegra_pingroup - Tegra pin group + * @name The name of the pin group. + * @pins An array of pin IDs included in this pin group. + * @npins The number of entries in @pins. + * @funcs The mux functions which can be muxed onto this group. + * @mux_reg: Mux register offset. + * This register contains the mux, einput, odrain, lock, + * ioreset, rcv_sel parameters. + * @mux_bank: Mux register bank. + * @mux_bit: Mux register bit. + * @pupd_reg: Pull-up/down register offset. + * @pupd_bank: Pull-up/down register bank. + * @pupd_bit: Pull-up/down register bit. + * @tri_reg: Tri-state register offset. + * @tri_bank: Tri-state register bank. + * @tri_bit: Tri-state register bit. + * @einput_bit: Enable-input register bit. + * @odrain_bit: Open-drain register bit. + * @lock_bit: Lock register bit. + * @ioreset_bit: IO reset register bit. + * @rcv_sel_bit: Receiver select bit. + * @drv_reg: Drive fields register offset. + * This register contains hsm, schmitt, lpmd, drvdn, + * drvup, slwr, slwf, and drvtype parameters. + * @drv_bank: Drive fields register bank. + * @hsm_bit: High Speed Mode register bit. + * @schmitt_bit: Scmitt register bit. + * @lpmd_bit: Low Power Mode register bit. + * @drvdn_bit: Drive Down register bit. + * @drvdn_width: Drive Down field width. + * @drvup_bit: Drive Up register bit. + * @drvup_width: Drive Up field width. + * @slwr_bit: Slew Rising register bit. + * @slwr_width: Slew Rising field width. + * @slwf_bit: Slew Falling register bit. + * @slwf_width: Slew Falling field width. + * @drvtype_bit: Drive type register bit. + * + * -1 in a *_reg field means that feature is unsupported for this group. + * *_bank and *_reg values are irrelevant when *_reg is -1. + * When *_reg is valid, *_bit may be -1 to indicate an unsupported feature. + * + * A representation of a group of pins (possibly just one pin) in the Tegra + * pin controller. Each group allows some parameter or parameters to be + * configured. The most common is mux function selection. Many others exist + * such as pull-up/down, tri-state, etc. Tegra's pin controller is complex; + * certain groups may only support configuring certain parameters, hence + * each parameter is optional. + */ +struct tegra_pingroup { + const char *name; + const unsigned *pins; + u8 npins; + u8 funcs[4]; + s16 mux_reg; + s16 pupd_reg; + s16 tri_reg; + s16 drv_reg; + u32 mux_bank:2; + u32 pupd_bank:2; + u32 tri_bank:2; + u32 drv_bank:2; + s32 mux_bit:6; + s32 pupd_bit:6; + s32 tri_bit:6; + s32 einput_bit:6; + s32 odrain_bit:6; + s32 lock_bit:6; + s32 ioreset_bit:6; + s32 rcv_sel_bit:6; + s32 hsm_bit:6; + s32 schmitt_bit:6; + s32 lpmd_bit:6; + s32 drvdn_bit:6; + s32 drvup_bit:6; + s32 slwr_bit:6; + s32 slwf_bit:6; + s32 drvtype_bit:6; + s32 drvdn_width:6; + s32 drvup_width:6; + s32 slwr_width:6; + s32 slwf_width:6; +}; + +/** + * struct tegra_pinctrl_soc_data - Tegra pin controller driver configuration + * @ngpios: The number of GPIO pins the pin controller HW affects. + * @pins: An array describing all pins the pin controller affects. + * All pins which are also GPIOs must be listed first within the + * array, and be numbered identically to the GPIO controller's + * numbering. + * @npins: The numbmer of entries in @pins. + * @functions: An array describing all mux functions the SoC supports. + * @nfunctions: The numbmer of entries in @functions. + * @groups: An array describing all pin groups the pin SoC supports. + * @ngroups: The numbmer of entries in @groups. + */ +struct tegra_pinctrl_soc_data { + unsigned ngpios; + const struct pinctrl_pin_desc *pins; + unsigned npins; + struct tegra_function *functions; + unsigned nfunctions; + const struct tegra_pingroup *groups; + unsigned ngroups; + bool hsm_in_mux; + bool schmitt_in_mux; + bool drvtype_in_mux; +}; + +int tegra_pinctrl_probe(struct platform_device *pdev, + const struct tegra_pinctrl_soc_data *soc_data); +int tegra_pinctrl_remove(struct platform_device *pdev); + +#endif diff --git a/drivers/pinctrl/tegra/pinctrl-tegra114.c b/drivers/pinctrl/tegra/pinctrl-tegra114.c new file mode 100644 index 000000000000..05e49d5137ab --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra114.c @@ -0,0 +1,1872 @@ +/* + * Pinctrl data for the NVIDIA Tegra114 pinmux + * + * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#include +#include +#include +#include +#include + +#include "pinctrl-tegra.h" + +/* + * Most pins affected by the pinmux can also be GPIOs. Define these first. + * These must match how the GPIO driver names/numbers its pins. + */ +#define _GPIO(offset) (offset) + +#define TEGRA_PIN_CLK_32K_OUT_PA0 _GPIO(0) +#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) +#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) +#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) +#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) +#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) +#define TEGRA_PIN_SDMMC3_CLK_PA6 _GPIO(6) +#define TEGRA_PIN_SDMMC3_CMD_PA7 _GPIO(7) +#define TEGRA_PIN_GMI_A17_PB0 _GPIO(8) +#define TEGRA_PIN_GMI_A18_PB1 _GPIO(9) +#define TEGRA_PIN_SDMMC3_DAT3_PB4 _GPIO(12) +#define TEGRA_PIN_SDMMC3_DAT2_PB5 _GPIO(13) +#define TEGRA_PIN_SDMMC3_DAT1_PB6 _GPIO(14) +#define TEGRA_PIN_SDMMC3_DAT0_PB7 _GPIO(15) +#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) +#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) +#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) +#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) +#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) +#define TEGRA_PIN_GMI_WP_N_PC7 _GPIO(23) +#define TEGRA_PIN_GMI_AD0_PG0 _GPIO(48) +#define TEGRA_PIN_GMI_AD1_PG1 _GPIO(49) +#define TEGRA_PIN_GMI_AD2_PG2 _GPIO(50) +#define TEGRA_PIN_GMI_AD3_PG3 _GPIO(51) +#define TEGRA_PIN_GMI_AD4_PG4 _GPIO(52) +#define TEGRA_PIN_GMI_AD5_PG5 _GPIO(53) +#define TEGRA_PIN_GMI_AD6_PG6 _GPIO(54) +#define TEGRA_PIN_GMI_AD7_PG7 _GPIO(55) +#define TEGRA_PIN_GMI_AD8_PH0 _GPIO(56) +#define TEGRA_PIN_GMI_AD9_PH1 _GPIO(57) +#define TEGRA_PIN_GMI_AD10_PH2 _GPIO(58) +#define TEGRA_PIN_GMI_AD11_PH3 _GPIO(59) +#define TEGRA_PIN_GMI_AD12_PH4 _GPIO(60) +#define TEGRA_PIN_GMI_AD13_PH5 _GPIO(61) +#define TEGRA_PIN_GMI_AD14_PH6 _GPIO(62) +#define TEGRA_PIN_GMI_AD15_PH7 _GPIO(63) +#define TEGRA_PIN_GMI_WR_N_PI0 _GPIO(64) +#define TEGRA_PIN_GMI_OE_N_PI1 _GPIO(65) +#define TEGRA_PIN_GMI_CS6_N_PI3 _GPIO(67) +#define TEGRA_PIN_GMI_RST_N_PI4 _GPIO(68) +#define TEGRA_PIN_GMI_IORDY_PI5 _GPIO(69) +#define TEGRA_PIN_GMI_CS7_N_PI6 _GPIO(70) +#define TEGRA_PIN_GMI_WAIT_PI7 _GPIO(71) +#define TEGRA_PIN_GMI_CS0_N_PJ0 _GPIO(72) +#define TEGRA_PIN_GMI_CS1_N_PJ2 _GPIO(74) +#define TEGRA_PIN_GMI_DQS_P_PJ3 _GPIO(75) +#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) +#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) +#define TEGRA_PIN_GMI_A16_PJ7 _GPIO(79) +#define TEGRA_PIN_GMI_ADV_N_PK0 _GPIO(80) +#define TEGRA_PIN_GMI_CLK_PK1 _GPIO(81) +#define TEGRA_PIN_GMI_CS4_N_PK2 _GPIO(82) +#define TEGRA_PIN_GMI_CS2_N_PK3 _GPIO(83) +#define TEGRA_PIN_GMI_CS3_N_PK4 _GPIO(84) +#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) +#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) +#define TEGRA_PIN_GMI_A19_PK7 _GPIO(87) +#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) +#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) +#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) +#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) +#define TEGRA_PIN_USB_VBUS_EN0_PN4 _GPIO(108) +#define TEGRA_PIN_USB_VBUS_EN1_PN5 _GPIO(109) +#define TEGRA_PIN_HDMI_INT_PN7 _GPIO(111) +#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) +#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) +#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) +#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) +#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) +#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) +#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) +#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) +#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) +#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) +#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) +#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) +#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) +#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) +#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) +#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) +#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) +#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) +#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) +#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) +#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) +#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) +#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) +#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) +#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) +#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) +#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) +#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) +#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) +#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) +#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) +#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) +#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) +#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) +#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) +#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) +#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) +#define TEGRA_PIN_SDMMC4_CMD_PT7 _GPIO(159) +#define TEGRA_PIN_PU0 _GPIO(160) +#define TEGRA_PIN_PU1 _GPIO(161) +#define TEGRA_PIN_PU2 _GPIO(162) +#define TEGRA_PIN_PU3 _GPIO(163) +#define TEGRA_PIN_PU4 _GPIO(164) +#define TEGRA_PIN_PU5 _GPIO(165) +#define TEGRA_PIN_PU6 _GPIO(166) +#define TEGRA_PIN_PV0 _GPIO(168) +#define TEGRA_PIN_PV1 _GPIO(169) +#define TEGRA_PIN_SDMMC3_CD_N_PV2 _GPIO(170) +#define TEGRA_PIN_SDMMC1_WP_N_PV3 _GPIO(171) +#define TEGRA_PIN_DDC_SCL_PV4 _GPIO(172) +#define TEGRA_PIN_DDC_SDA_PV5 _GPIO(173) +#define TEGRA_PIN_GPIO_W2_AUD_PW2 _GPIO(178) +#define TEGRA_PIN_GPIO_W3_AUD_PW3 _GPIO(179) +#define TEGRA_PIN_CLK1_OUT_PW4 _GPIO(180) +#define TEGRA_PIN_CLK2_OUT_PW5 _GPIO(181) +#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) +#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) +#define TEGRA_PIN_DVFS_PWM_PX0 _GPIO(184) +#define TEGRA_PIN_GPIO_X1_AUD_PX1 _GPIO(185) +#define TEGRA_PIN_DVFS_CLK_PX2 _GPIO(186) +#define TEGRA_PIN_GPIO_X3_AUD_PX3 _GPIO(187) +#define TEGRA_PIN_GPIO_X4_AUD_PX4 _GPIO(188) +#define TEGRA_PIN_GPIO_X5_AUD_PX5 _GPIO(189) +#define TEGRA_PIN_GPIO_X6_AUD_PX6 _GPIO(190) +#define TEGRA_PIN_GPIO_X7_AUD_PX7 _GPIO(191) +#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) +#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) +#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) +#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) +#define TEGRA_PIN_SDMMC1_DAT3_PY4 _GPIO(196) +#define TEGRA_PIN_SDMMC1_DAT2_PY5 _GPIO(197) +#define TEGRA_PIN_SDMMC1_DAT1_PY6 _GPIO(198) +#define TEGRA_PIN_SDMMC1_DAT0_PY7 _GPIO(199) +#define TEGRA_PIN_SDMMC1_CLK_PZ0 _GPIO(200) +#define TEGRA_PIN_SDMMC1_CMD_PZ1 _GPIO(201) +#define TEGRA_PIN_SYS_CLK_REQ_PZ5 _GPIO(205) +#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) +#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) +#define TEGRA_PIN_SDMMC4_DAT0_PAA0 _GPIO(208) +#define TEGRA_PIN_SDMMC4_DAT1_PAA1 _GPIO(209) +#define TEGRA_PIN_SDMMC4_DAT2_PAA2 _GPIO(210) +#define TEGRA_PIN_SDMMC4_DAT3_PAA3 _GPIO(211) +#define TEGRA_PIN_SDMMC4_DAT4_PAA4 _GPIO(212) +#define TEGRA_PIN_SDMMC4_DAT5_PAA5 _GPIO(213) +#define TEGRA_PIN_SDMMC4_DAT6_PAA6 _GPIO(214) +#define TEGRA_PIN_SDMMC4_DAT7_PAA7 _GPIO(215) +#define TEGRA_PIN_PBB0 _GPIO(216) +#define TEGRA_PIN_CAM_I2C_SCL_PBB1 _GPIO(217) +#define TEGRA_PIN_CAM_I2C_SDA_PBB2 _GPIO(218) +#define TEGRA_PIN_PBB3 _GPIO(219) +#define TEGRA_PIN_PBB4 _GPIO(220) +#define TEGRA_PIN_PBB5 _GPIO(221) +#define TEGRA_PIN_PBB6 _GPIO(222) +#define TEGRA_PIN_PBB7 _GPIO(223) +#define TEGRA_PIN_CAM_MCLK_PCC0 _GPIO(224) +#define TEGRA_PIN_PCC1 _GPIO(225) +#define TEGRA_PIN_PCC2 _GPIO(226) +#define TEGRA_PIN_SDMMC4_CLK_PCC4 _GPIO(228) +#define TEGRA_PIN_CLK2_REQ_PCC5 _GPIO(229) +#define TEGRA_PIN_CLK3_OUT_PEE0 _GPIO(240) +#define TEGRA_PIN_CLK3_REQ_PEE1 _GPIO(241) +#define TEGRA_PIN_CLK1_REQ_PEE2 _GPIO(242) +#define TEGRA_PIN_HDMI_CEC_PEE3 _GPIO(243) +#define TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4 _GPIO(244) +#define TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5 _GPIO(245) + +/* All non-GPIO pins follow */ +#define NUM_GPIOS (TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5 + 1) +#define _PIN(offset) (NUM_GPIOS + (offset)) + +/* Non-GPIO pins */ +#define TEGRA_PIN_CORE_PWR_REQ _PIN(0) +#define TEGRA_PIN_CPU_PWR_REQ _PIN(1) +#define TEGRA_PIN_PWR_INT_N _PIN(2) +#define TEGRA_PIN_RESET_OUT_N _PIN(3) +#define TEGRA_PIN_OWR _PIN(4) +#define TEGRA_PIN_JTAG_RTCK _PIN(5) +#define TEGRA_PIN_CLK_32K_IN _PIN(6) +#define TEGRA_PIN_GMI_CLK_LB _PIN(7) + +static const struct pinctrl_pin_desc tegra114_pins[] = { + PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"), + PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), + PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), + PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"), + PINCTRL_PIN(TEGRA_PIN_GMI_A17_PB0, "GMI_A17 PB0"), + PINCTRL_PIN(TEGRA_PIN_GMI_A18_PB1, "GMI_A18 PB1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"), + PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), + PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), + PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), + PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"), + PINCTRL_PIN(TEGRA_PIN_GMI_WR_N_PI0, "GMI_WR_N PI0"), + PINCTRL_PIN(TEGRA_PIN_GMI_OE_N_PI1, "GMI_OE_N PI1"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"), + PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"), + PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"), + PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"), + PINCTRL_PIN(TEGRA_PIN_GMI_DQS_P_PJ3, "GMI_DQS_P PJ3"), + PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), + PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), + PINCTRL_PIN(TEGRA_PIN_GMI_A16_PJ7, "GMI_A16 PJ7"), + PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"), + PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), + PINCTRL_PIN(TEGRA_PIN_GMI_A19_PK7, "GMI_A19 PK7"), + PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), + PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PN4, "USB_VBUS_EN0 PN4"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PN5, "USB_VBUS_EN1 PN5"), + PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), + PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), + PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), + PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), + PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), + PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), + PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), + PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), + PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), + PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), + PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), + PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), + PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"), + PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), + PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), + PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), + PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), + PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), + PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), + PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), + PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), + PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CD_N_PV2, "SDMMC3_CD_N PV2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_WP_N_PV3, "SDMMC1_WP_N PV3"), + PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"), + PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"), + PINCTRL_PIN(TEGRA_PIN_GPIO_W2_AUD_PW2, "GPIO_W2_AUD PW2"), + PINCTRL_PIN(TEGRA_PIN_GPIO_W3_AUD_PW3, "GPIO_W3_AUD PW3"), + PINCTRL_PIN(TEGRA_PIN_CLK1_OUT_PW4, "CLK1_OUT PW4"), + PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"), + PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), + PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), + PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PX0, "DVFS_PWM PX0"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PX1, "GPIO_X1_AUD PX1"), + PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PX2, "DVFS_CLK PX2"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PX3, "GPIO_X3_AUD PX3"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X4_AUD_PX4, "GPIO_X4_AUD PX4"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X5_AUD_PX5, "GPIO_X5_AUD PX5"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X6_AUD_PX6, "GPIO_X6_AUD PX6"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X7_AUD_PX7, "GPIO_X7_AUD PX7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"), + PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"), + PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"), + PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"), + PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"), + PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"), + PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), + PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), + PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"), + PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"), + PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"), + PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"), + PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"), + PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"), + PINCTRL_PIN(TEGRA_PIN_CLK1_REQ_PEE2, "CLK1_REQ PEE2"), + PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, "SDMMC3_CLK_LB_OUT PEE4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, "SDMMC3_CLK_LB_IN PEE5"), + PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), + PINCTRL_PIN(TEGRA_PIN_RESET_OUT_N, "RESET_OUT_N"), + PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"), + PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"), + PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), + PINCTRL_PIN(TEGRA_PIN_GMI_CLK_LB, "GMI_CLK_LB"), +}; + +static const unsigned clk_32k_out_pa0_pins[] = { + TEGRA_PIN_CLK_32K_OUT_PA0, +}; + +static const unsigned uart3_cts_n_pa1_pins[] = { + TEGRA_PIN_UART3_CTS_N_PA1, +}; + +static const unsigned dap2_fs_pa2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, +}; + +static const unsigned dap2_sclk_pa3_pins[] = { + TEGRA_PIN_DAP2_SCLK_PA3, +}; + +static const unsigned dap2_din_pa4_pins[] = { + TEGRA_PIN_DAP2_DIN_PA4, +}; + +static const unsigned dap2_dout_pa5_pins[] = { + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned sdmmc3_clk_pa6_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PA6, +}; + +static const unsigned sdmmc3_cmd_pa7_pins[] = { + TEGRA_PIN_SDMMC3_CMD_PA7, +}; + +static const unsigned gmi_a17_pb0_pins[] = { + TEGRA_PIN_GMI_A17_PB0, +}; + +static const unsigned gmi_a18_pb1_pins[] = { + TEGRA_PIN_GMI_A18_PB1, +}; + +static const unsigned sdmmc3_dat3_pb4_pins[] = { + TEGRA_PIN_SDMMC3_DAT3_PB4, +}; + +static const unsigned sdmmc3_dat2_pb5_pins[] = { + TEGRA_PIN_SDMMC3_DAT2_PB5, +}; + +static const unsigned sdmmc3_dat1_pb6_pins[] = { + TEGRA_PIN_SDMMC3_DAT1_PB6, +}; + +static const unsigned sdmmc3_dat0_pb7_pins[] = { + TEGRA_PIN_SDMMC3_DAT0_PB7, +}; + +static const unsigned uart3_rts_n_pc0_pins[] = { + TEGRA_PIN_UART3_RTS_N_PC0, +}; + +static const unsigned uart2_txd_pc2_pins[] = { + TEGRA_PIN_UART2_TXD_PC2, +}; + +static const unsigned uart2_rxd_pc3_pins[] = { + TEGRA_PIN_UART2_RXD_PC3, +}; + +static const unsigned gen1_i2c_scl_pc4_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PC4, +}; + +static const unsigned gen1_i2c_sda_pc5_pins[] = { + TEGRA_PIN_GEN1_I2C_SDA_PC5, +}; + +static const unsigned gmi_wp_n_pc7_pins[] = { + TEGRA_PIN_GMI_WP_N_PC7, +}; + +static const unsigned gmi_ad0_pg0_pins[] = { + TEGRA_PIN_GMI_AD0_PG0, +}; + +static const unsigned gmi_ad1_pg1_pins[] = { + TEGRA_PIN_GMI_AD1_PG1, +}; + +static const unsigned gmi_ad2_pg2_pins[] = { + TEGRA_PIN_GMI_AD2_PG2, +}; + +static const unsigned gmi_ad3_pg3_pins[] = { + TEGRA_PIN_GMI_AD3_PG3, +}; + +static const unsigned gmi_ad4_pg4_pins[] = { + TEGRA_PIN_GMI_AD4_PG4, +}; + +static const unsigned gmi_ad5_pg5_pins[] = { + TEGRA_PIN_GMI_AD5_PG5, +}; + +static const unsigned gmi_ad6_pg6_pins[] = { + TEGRA_PIN_GMI_AD6_PG6, +}; + +static const unsigned gmi_ad7_pg7_pins[] = { + TEGRA_PIN_GMI_AD7_PG7, +}; + +static const unsigned gmi_ad8_ph0_pins[] = { + TEGRA_PIN_GMI_AD8_PH0, +}; + +static const unsigned gmi_ad9_ph1_pins[] = { + TEGRA_PIN_GMI_AD9_PH1, +}; + +static const unsigned gmi_ad10_ph2_pins[] = { + TEGRA_PIN_GMI_AD10_PH2, +}; + +static const unsigned gmi_ad11_ph3_pins[] = { + TEGRA_PIN_GMI_AD11_PH3, +}; + +static const unsigned gmi_ad12_ph4_pins[] = { + TEGRA_PIN_GMI_AD12_PH4, +}; + +static const unsigned gmi_ad13_ph5_pins[] = { + TEGRA_PIN_GMI_AD13_PH5, +}; + +static const unsigned gmi_ad14_ph6_pins[] = { + TEGRA_PIN_GMI_AD14_PH6, +}; + +static const unsigned gmi_ad15_ph7_pins[] = { + TEGRA_PIN_GMI_AD15_PH7, +}; + +static const unsigned gmi_wr_n_pi0_pins[] = { + TEGRA_PIN_GMI_WR_N_PI0, +}; + +static const unsigned gmi_oe_n_pi1_pins[] = { + TEGRA_PIN_GMI_OE_N_PI1, +}; + +static const unsigned gmi_cs6_n_pi3_pins[] = { + TEGRA_PIN_GMI_CS6_N_PI3, +}; + +static const unsigned gmi_rst_n_pi4_pins[] = { + TEGRA_PIN_GMI_RST_N_PI4, +}; + +static const unsigned gmi_iordy_pi5_pins[] = { + TEGRA_PIN_GMI_IORDY_PI5, +}; + +static const unsigned gmi_cs7_n_pi6_pins[] = { + TEGRA_PIN_GMI_CS7_N_PI6, +}; + +static const unsigned gmi_wait_pi7_pins[] = { + TEGRA_PIN_GMI_WAIT_PI7, +}; + +static const unsigned gmi_cs0_n_pj0_pins[] = { + TEGRA_PIN_GMI_CS0_N_PJ0, +}; + +static const unsigned gmi_cs1_n_pj2_pins[] = { + TEGRA_PIN_GMI_CS1_N_PJ2, +}; + +static const unsigned gmi_dqs_p_pj3_pins[] = { + TEGRA_PIN_GMI_DQS_P_PJ3, +}; + +static const unsigned uart2_cts_n_pj5_pins[] = { + TEGRA_PIN_UART2_CTS_N_PJ5, +}; + +static const unsigned uart2_rts_n_pj6_pins[] = { + TEGRA_PIN_UART2_RTS_N_PJ6, +}; + +static const unsigned gmi_a16_pj7_pins[] = { + TEGRA_PIN_GMI_A16_PJ7, +}; + +static const unsigned gmi_adv_n_pk0_pins[] = { + TEGRA_PIN_GMI_ADV_N_PK0, +}; + +static const unsigned gmi_clk_pk1_pins[] = { + TEGRA_PIN_GMI_CLK_PK1, +}; + +static const unsigned gmi_cs4_n_pk2_pins[] = { + TEGRA_PIN_GMI_CS4_N_PK2, +}; + +static const unsigned gmi_cs2_n_pk3_pins[] = { + TEGRA_PIN_GMI_CS2_N_PK3, +}; + +static const unsigned gmi_cs3_n_pk4_pins[] = { + TEGRA_PIN_GMI_CS3_N_PK4, +}; + +static const unsigned spdif_out_pk5_pins[] = { + TEGRA_PIN_SPDIF_OUT_PK5, +}; + +static const unsigned spdif_in_pk6_pins[] = { + TEGRA_PIN_SPDIF_IN_PK6, +}; + +static const unsigned gmi_a19_pk7_pins[] = { + TEGRA_PIN_GMI_A19_PK7, +}; + +static const unsigned dap1_fs_pn0_pins[] = { + TEGRA_PIN_DAP1_FS_PN0, +}; + +static const unsigned dap1_din_pn1_pins[] = { + TEGRA_PIN_DAP1_DIN_PN1, +}; + +static const unsigned dap1_dout_pn2_pins[] = { + TEGRA_PIN_DAP1_DOUT_PN2, +}; + +static const unsigned dap1_sclk_pn3_pins[] = { + TEGRA_PIN_DAP1_SCLK_PN3, +}; + +static const unsigned usb_vbus_en0_pn4_pins[] = { + TEGRA_PIN_USB_VBUS_EN0_PN4, +}; + +static const unsigned usb_vbus_en1_pn5_pins[] = { + TEGRA_PIN_USB_VBUS_EN1_PN5, +}; + +static const unsigned hdmi_int_pn7_pins[] = { + TEGRA_PIN_HDMI_INT_PN7, +}; + +static const unsigned ulpi_data7_po0_pins[] = { + TEGRA_PIN_ULPI_DATA7_PO0, +}; + +static const unsigned ulpi_data0_po1_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, +}; + +static const unsigned ulpi_data1_po2_pins[] = { + TEGRA_PIN_ULPI_DATA1_PO2, +}; + +static const unsigned ulpi_data2_po3_pins[] = { + TEGRA_PIN_ULPI_DATA2_PO3, +}; + +static const unsigned ulpi_data3_po4_pins[] = { + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned ulpi_data4_po5_pins[] = { + TEGRA_PIN_ULPI_DATA4_PO5, +}; + +static const unsigned ulpi_data5_po6_pins[] = { + TEGRA_PIN_ULPI_DATA5_PO6, +}; + +static const unsigned ulpi_data6_po7_pins[] = { + TEGRA_PIN_ULPI_DATA6_PO7, +}; + +static const unsigned dap3_fs_pp0_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, +}; + +static const unsigned dap3_din_pp1_pins[] = { + TEGRA_PIN_DAP3_DIN_PP1, +}; + +static const unsigned dap3_dout_pp2_pins[] = { + TEGRA_PIN_DAP3_DOUT_PP2, +}; + +static const unsigned dap3_sclk_pp3_pins[] = { + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned dap4_fs_pp4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, +}; + +static const unsigned dap4_din_pp5_pins[] = { + TEGRA_PIN_DAP4_DIN_PP5, +}; + +static const unsigned dap4_dout_pp6_pins[] = { + TEGRA_PIN_DAP4_DOUT_PP6, +}; + +static const unsigned dap4_sclk_pp7_pins[] = { + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned kb_col0_pq0_pins[] = { + TEGRA_PIN_KB_COL0_PQ0, +}; + +static const unsigned kb_col1_pq1_pins[] = { + TEGRA_PIN_KB_COL1_PQ1, +}; + +static const unsigned kb_col2_pq2_pins[] = { + TEGRA_PIN_KB_COL2_PQ2, +}; + +static const unsigned kb_col3_pq3_pins[] = { + TEGRA_PIN_KB_COL3_PQ3, +}; + +static const unsigned kb_col4_pq4_pins[] = { + TEGRA_PIN_KB_COL4_PQ4, +}; + +static const unsigned kb_col5_pq5_pins[] = { + TEGRA_PIN_KB_COL5_PQ5, +}; + +static const unsigned kb_col6_pq6_pins[] = { + TEGRA_PIN_KB_COL6_PQ6, +}; + +static const unsigned kb_col7_pq7_pins[] = { + TEGRA_PIN_KB_COL7_PQ7, +}; + +static const unsigned kb_row0_pr0_pins[] = { + TEGRA_PIN_KB_ROW0_PR0, +}; + +static const unsigned kb_row1_pr1_pins[] = { + TEGRA_PIN_KB_ROW1_PR1, +}; + +static const unsigned kb_row2_pr2_pins[] = { + TEGRA_PIN_KB_ROW2_PR2, +}; + +static const unsigned kb_row3_pr3_pins[] = { + TEGRA_PIN_KB_ROW3_PR3, +}; + +static const unsigned kb_row4_pr4_pins[] = { + TEGRA_PIN_KB_ROW4_PR4, +}; + +static const unsigned kb_row5_pr5_pins[] = { + TEGRA_PIN_KB_ROW5_PR5, +}; + +static const unsigned kb_row6_pr6_pins[] = { + TEGRA_PIN_KB_ROW6_PR6, +}; + +static const unsigned kb_row7_pr7_pins[] = { + TEGRA_PIN_KB_ROW7_PR7, +}; + +static const unsigned kb_row8_ps0_pins[] = { + TEGRA_PIN_KB_ROW8_PS0, +}; + +static const unsigned kb_row9_ps1_pins[] = { + TEGRA_PIN_KB_ROW9_PS1, +}; + +static const unsigned kb_row10_ps2_pins[] = { + TEGRA_PIN_KB_ROW10_PS2, +}; + +static const unsigned gen2_i2c_scl_pt5_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PT5, +}; + +static const unsigned gen2_i2c_sda_pt6_pins[] = { + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned sdmmc4_cmd_pt7_pins[] = { + TEGRA_PIN_SDMMC4_CMD_PT7, +}; + +static const unsigned pu0_pins[] = { + TEGRA_PIN_PU0, +}; + +static const unsigned pu1_pins[] = { + TEGRA_PIN_PU1, +}; + +static const unsigned pu2_pins[] = { + TEGRA_PIN_PU2, +}; + +static const unsigned pu3_pins[] = { + TEGRA_PIN_PU3, +}; + +static const unsigned pu4_pins[] = { + TEGRA_PIN_PU4, +}; + +static const unsigned pu5_pins[] = { + TEGRA_PIN_PU5, +}; + +static const unsigned pu6_pins[] = { + TEGRA_PIN_PU6, +}; + +static const unsigned pv0_pins[] = { + TEGRA_PIN_PV0, +}; + +static const unsigned pv1_pins[] = { + TEGRA_PIN_PV1, +}; + +static const unsigned sdmmc3_cd_n_pv2_pins[] = { + TEGRA_PIN_SDMMC3_CD_N_PV2, +}; + +static const unsigned sdmmc1_wp_n_pv3_pins[] = { + TEGRA_PIN_SDMMC1_WP_N_PV3, +}; + +static const unsigned ddc_scl_pv4_pins[] = { + TEGRA_PIN_DDC_SCL_PV4, +}; + +static const unsigned ddc_sda_pv5_pins[] = { + TEGRA_PIN_DDC_SDA_PV5, +}; + +static const unsigned gpio_w2_aud_pw2_pins[] = { + TEGRA_PIN_GPIO_W2_AUD_PW2, +}; + +static const unsigned gpio_w3_aud_pw3_pins[] = { + TEGRA_PIN_GPIO_W3_AUD_PW3, +}; + +static const unsigned clk1_out_pw4_pins[] = { + TEGRA_PIN_CLK1_OUT_PW4, +}; + +static const unsigned clk2_out_pw5_pins[] = { + TEGRA_PIN_CLK2_OUT_PW5, +}; + +static const unsigned uart3_txd_pw6_pins[] = { + TEGRA_PIN_UART3_TXD_PW6, +}; + +static const unsigned uart3_rxd_pw7_pins[] = { + TEGRA_PIN_UART3_RXD_PW7, +}; + +static const unsigned dvfs_pwm_px0_pins[] = { + TEGRA_PIN_DVFS_PWM_PX0, +}; + +static const unsigned gpio_x1_aud_px1_pins[] = { + TEGRA_PIN_GPIO_X1_AUD_PX1, +}; + +static const unsigned dvfs_clk_px2_pins[] = { + TEGRA_PIN_DVFS_CLK_PX2, +}; + +static const unsigned gpio_x3_aud_px3_pins[] = { + TEGRA_PIN_GPIO_X3_AUD_PX3, +}; + +static const unsigned gpio_x4_aud_px4_pins[] = { + TEGRA_PIN_GPIO_X4_AUD_PX4, +}; + +static const unsigned gpio_x5_aud_px5_pins[] = { + TEGRA_PIN_GPIO_X5_AUD_PX5, +}; + +static const unsigned gpio_x6_aud_px6_pins[] = { + TEGRA_PIN_GPIO_X6_AUD_PX6, +}; + +static const unsigned gpio_x7_aud_px7_pins[] = { + TEGRA_PIN_GPIO_X7_AUD_PX7, +}; + +static const unsigned ulpi_clk_py0_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, +}; + +static const unsigned ulpi_dir_py1_pins[] = { + TEGRA_PIN_ULPI_DIR_PY1, +}; + +static const unsigned ulpi_nxt_py2_pins[] = { + TEGRA_PIN_ULPI_NXT_PY2, +}; + +static const unsigned ulpi_stp_py3_pins[] = { + TEGRA_PIN_ULPI_STP_PY3, +}; + +static const unsigned sdmmc1_dat3_py4_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PY4, +}; + +static const unsigned sdmmc1_dat2_py5_pins[] = { + TEGRA_PIN_SDMMC1_DAT2_PY5, +}; + +static const unsigned sdmmc1_dat1_py6_pins[] = { + TEGRA_PIN_SDMMC1_DAT1_PY6, +}; + +static const unsigned sdmmc1_dat0_py7_pins[] = { + TEGRA_PIN_SDMMC1_DAT0_PY7, +}; + +static const unsigned sdmmc1_clk_pz0_pins[] = { + TEGRA_PIN_SDMMC1_CLK_PZ0, +}; + +static const unsigned sdmmc1_cmd_pz1_pins[] = { + TEGRA_PIN_SDMMC1_CMD_PZ1, +}; + +static const unsigned sys_clk_req_pz5_pins[] = { + TEGRA_PIN_SYS_CLK_REQ_PZ5, +}; + +static const unsigned pwr_i2c_scl_pz6_pins[] = { + TEGRA_PIN_PWR_I2C_SCL_PZ6, +}; + +static const unsigned pwr_i2c_sda_pz7_pins[] = { + TEGRA_PIN_PWR_I2C_SDA_PZ7, +}; + +static const unsigned sdmmc4_dat0_paa0_pins[] = { + TEGRA_PIN_SDMMC4_DAT0_PAA0, +}; + +static const unsigned sdmmc4_dat1_paa1_pins[] = { + TEGRA_PIN_SDMMC4_DAT1_PAA1, +}; + +static const unsigned sdmmc4_dat2_paa2_pins[] = { + TEGRA_PIN_SDMMC4_DAT2_PAA2, +}; + +static const unsigned sdmmc4_dat3_paa3_pins[] = { + TEGRA_PIN_SDMMC4_DAT3_PAA3, +}; + +static const unsigned sdmmc4_dat4_paa4_pins[] = { + TEGRA_PIN_SDMMC4_DAT4_PAA4, +}; + +static const unsigned sdmmc4_dat5_paa5_pins[] = { + TEGRA_PIN_SDMMC4_DAT5_PAA5, +}; + +static const unsigned sdmmc4_dat6_paa6_pins[] = { + TEGRA_PIN_SDMMC4_DAT6_PAA6, +}; + +static const unsigned sdmmc4_dat7_paa7_pins[] = { + TEGRA_PIN_SDMMC4_DAT7_PAA7, +}; + +static const unsigned pbb0_pins[] = { + TEGRA_PIN_PBB0, +}; + +static const unsigned cam_i2c_scl_pbb1_pins[] = { + TEGRA_PIN_CAM_I2C_SCL_PBB1, +}; + +static const unsigned cam_i2c_sda_pbb2_pins[] = { + TEGRA_PIN_CAM_I2C_SDA_PBB2, +}; + +static const unsigned pbb3_pins[] = { + TEGRA_PIN_PBB3, +}; + +static const unsigned pbb4_pins[] = { + TEGRA_PIN_PBB4, +}; + +static const unsigned pbb5_pins[] = { + TEGRA_PIN_PBB5, +}; + +static const unsigned pbb6_pins[] = { + TEGRA_PIN_PBB6, +}; + +static const unsigned pbb7_pins[] = { + TEGRA_PIN_PBB7, +}; + +static const unsigned cam_mclk_pcc0_pins[] = { + TEGRA_PIN_CAM_MCLK_PCC0, +}; + +static const unsigned pcc1_pins[] = { + TEGRA_PIN_PCC1, +}; + +static const unsigned pcc2_pins[] = { + TEGRA_PIN_PCC2, +}; + +static const unsigned sdmmc4_clk_pcc4_pins[] = { + TEGRA_PIN_SDMMC4_CLK_PCC4, +}; + +static const unsigned clk2_req_pcc5_pins[] = { + TEGRA_PIN_CLK2_REQ_PCC5, +}; + +static const unsigned clk3_out_pee0_pins[] = { + TEGRA_PIN_CLK3_OUT_PEE0, +}; + +static const unsigned clk3_req_pee1_pins[] = { + TEGRA_PIN_CLK3_REQ_PEE1, +}; + +static const unsigned clk1_req_pee2_pins[] = { + TEGRA_PIN_CLK1_REQ_PEE2, +}; + +static const unsigned hdmi_cec_pee3_pins[] = { + TEGRA_PIN_HDMI_CEC_PEE3, +}; + +static const unsigned sdmmc3_clk_lb_out_pee4_pins[] = { + TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, +}; + +static const unsigned sdmmc3_clk_lb_in_pee5_pins[] = { + TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, +}; + +static const unsigned core_pwr_req_pins[] = { + TEGRA_PIN_CORE_PWR_REQ, +}; + +static const unsigned cpu_pwr_req_pins[] = { + TEGRA_PIN_CPU_PWR_REQ, +}; + +static const unsigned pwr_int_n_pins[] = { + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned reset_out_n_pins[] = { + TEGRA_PIN_RESET_OUT_N, +}; + +static const unsigned owr_pins[] = { + TEGRA_PIN_OWR, +}; + +static const unsigned jtag_rtck_pins[] = { + TEGRA_PIN_JTAG_RTCK, +}; + +static const unsigned clk_32k_in_pins[] = { + TEGRA_PIN_CLK_32K_IN, +}; + +static const unsigned gmi_clk_lb_pins[] = { + TEGRA_PIN_GMI_CLK_LB, +}; + +static const unsigned drive_ao1_pins[] = { + TEGRA_PIN_KB_ROW0_PR0, + TEGRA_PIN_KB_ROW1_PR1, + TEGRA_PIN_KB_ROW2_PR2, + TEGRA_PIN_KB_ROW3_PR3, + TEGRA_PIN_KB_ROW4_PR4, + TEGRA_PIN_KB_ROW5_PR5, + TEGRA_PIN_KB_ROW6_PR6, + TEGRA_PIN_KB_ROW7_PR7, + TEGRA_PIN_PWR_I2C_SCL_PZ6, + TEGRA_PIN_PWR_I2C_SDA_PZ7, +}; + +static const unsigned drive_ao2_pins[] = { + TEGRA_PIN_CLK_32K_OUT_PA0, + TEGRA_PIN_KB_COL0_PQ0, + TEGRA_PIN_KB_COL1_PQ1, + TEGRA_PIN_KB_COL2_PQ2, + TEGRA_PIN_KB_COL3_PQ3, + TEGRA_PIN_KB_COL4_PQ4, + TEGRA_PIN_KB_COL5_PQ5, + TEGRA_PIN_KB_COL6_PQ6, + TEGRA_PIN_KB_COL7_PQ7, + TEGRA_PIN_KB_ROW8_PS0, + TEGRA_PIN_KB_ROW9_PS1, + TEGRA_PIN_KB_ROW10_PS2, + TEGRA_PIN_SYS_CLK_REQ_PZ5, + TEGRA_PIN_CORE_PWR_REQ, + TEGRA_PIN_CPU_PWR_REQ, + TEGRA_PIN_RESET_OUT_N, +}; + +static const unsigned drive_at1_pins[] = { + TEGRA_PIN_GMI_AD8_PH0, + TEGRA_PIN_GMI_AD9_PH1, + TEGRA_PIN_GMI_AD10_PH2, + TEGRA_PIN_GMI_AD11_PH3, + TEGRA_PIN_GMI_AD12_PH4, + TEGRA_PIN_GMI_AD13_PH5, + TEGRA_PIN_GMI_AD14_PH6, + TEGRA_PIN_GMI_AD15_PH7, + TEGRA_PIN_GMI_IORDY_PI5, + TEGRA_PIN_GMI_CS7_N_PI6, +}; + +static const unsigned drive_at2_pins[] = { + TEGRA_PIN_GMI_AD0_PG0, + TEGRA_PIN_GMI_AD1_PG1, + TEGRA_PIN_GMI_AD2_PG2, + TEGRA_PIN_GMI_AD3_PG3, + TEGRA_PIN_GMI_AD4_PG4, + TEGRA_PIN_GMI_AD5_PG5, + TEGRA_PIN_GMI_AD6_PG6, + TEGRA_PIN_GMI_AD7_PG7, + TEGRA_PIN_GMI_WR_N_PI0, + TEGRA_PIN_GMI_OE_N_PI1, + TEGRA_PIN_GMI_CS6_N_PI3, + TEGRA_PIN_GMI_RST_N_PI4, + TEGRA_PIN_GMI_WAIT_PI7, + TEGRA_PIN_GMI_DQS_P_PJ3, + TEGRA_PIN_GMI_ADV_N_PK0, + TEGRA_PIN_GMI_CLK_PK1, + TEGRA_PIN_GMI_CS4_N_PK2, + TEGRA_PIN_GMI_CS2_N_PK3, + TEGRA_PIN_GMI_CS3_N_PK4, +}; + +static const unsigned drive_at3_pins[] = { + TEGRA_PIN_GMI_WP_N_PC7, + TEGRA_PIN_GMI_CS0_N_PJ0, +}; + +static const unsigned drive_at4_pins[] = { + TEGRA_PIN_GMI_A17_PB0, + TEGRA_PIN_GMI_A18_PB1, + TEGRA_PIN_GMI_CS1_N_PJ2, + TEGRA_PIN_GMI_A16_PJ7, + TEGRA_PIN_GMI_A19_PK7, +}; + +static const unsigned drive_at5_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PT5, + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned drive_cdev1_pins[] = { + TEGRA_PIN_CLK1_OUT_PW4, + TEGRA_PIN_CLK1_REQ_PEE2, +}; + +static const unsigned drive_cdev2_pins[] = { + TEGRA_PIN_CLK2_OUT_PW5, + TEGRA_PIN_CLK2_REQ_PCC5, + TEGRA_PIN_SDMMC1_WP_N_PV3, +}; + +static const unsigned drive_dap1_pins[] = { + TEGRA_PIN_DAP1_FS_PN0, + TEGRA_PIN_DAP1_DIN_PN1, + TEGRA_PIN_DAP1_DOUT_PN2, + TEGRA_PIN_DAP1_SCLK_PN3, +}; + +static const unsigned drive_dap2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, + TEGRA_PIN_DAP2_SCLK_PA3, + TEGRA_PIN_DAP2_DIN_PA4, + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned drive_dap3_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, + TEGRA_PIN_DAP3_DIN_PP1, + TEGRA_PIN_DAP3_DOUT_PP2, + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned drive_dap4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, + TEGRA_PIN_DAP4_DIN_PP5, + TEGRA_PIN_DAP4_DOUT_PP6, + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned drive_dbg_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PC4, + TEGRA_PIN_GEN1_I2C_SDA_PC5, + TEGRA_PIN_PU0, + TEGRA_PIN_PU1, + TEGRA_PIN_PU2, + TEGRA_PIN_PU3, + TEGRA_PIN_PU4, + TEGRA_PIN_PU5, + TEGRA_PIN_PU6, +}; + +static const unsigned drive_sdio3_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PA6, + TEGRA_PIN_SDMMC3_CMD_PA7, + TEGRA_PIN_SDMMC3_DAT3_PB4, + TEGRA_PIN_SDMMC3_DAT2_PB5, + TEGRA_PIN_SDMMC3_DAT1_PB6, + TEGRA_PIN_SDMMC3_DAT0_PB7, + TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, + TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, +}; + +static const unsigned drive_spi_pins[] = { + TEGRA_PIN_DVFS_PWM_PX0, + TEGRA_PIN_GPIO_X1_AUD_PX1, + TEGRA_PIN_DVFS_CLK_PX2, + TEGRA_PIN_GPIO_X3_AUD_PX3, + TEGRA_PIN_GPIO_X4_AUD_PX4, + TEGRA_PIN_GPIO_X5_AUD_PX5, + TEGRA_PIN_GPIO_X6_AUD_PX6, + TEGRA_PIN_GPIO_X7_AUD_PX7, + TEGRA_PIN_GPIO_W2_AUD_PW2, + TEGRA_PIN_GPIO_W3_AUD_PW3, +}; + +static const unsigned drive_uaa_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, + TEGRA_PIN_ULPI_DATA1_PO2, + TEGRA_PIN_ULPI_DATA2_PO3, + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned drive_uab_pins[] = { + TEGRA_PIN_ULPI_DATA7_PO0, + TEGRA_PIN_ULPI_DATA4_PO5, + TEGRA_PIN_ULPI_DATA5_PO6, + TEGRA_PIN_ULPI_DATA6_PO7, + TEGRA_PIN_PV0, + TEGRA_PIN_PV1, +}; + +static const unsigned drive_uart2_pins[] = { + TEGRA_PIN_UART2_TXD_PC2, + TEGRA_PIN_UART2_RXD_PC3, + TEGRA_PIN_UART2_CTS_N_PJ5, + TEGRA_PIN_UART2_RTS_N_PJ6, +}; + +static const unsigned drive_uart3_pins[] = { + TEGRA_PIN_UART3_CTS_N_PA1, + TEGRA_PIN_UART3_RTS_N_PC0, + TEGRA_PIN_UART3_TXD_PW6, + TEGRA_PIN_UART3_RXD_PW7, +}; + +static const unsigned drive_sdio1_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PY4, + TEGRA_PIN_SDMMC1_DAT2_PY5, + TEGRA_PIN_SDMMC1_DAT1_PY6, + TEGRA_PIN_SDMMC1_DAT0_PY7, + TEGRA_PIN_SDMMC1_CLK_PZ0, + TEGRA_PIN_SDMMC1_CMD_PZ1, +}; + +static const unsigned drive_ddc_pins[] = { + TEGRA_PIN_DDC_SCL_PV4, + TEGRA_PIN_DDC_SDA_PV5, +}; + +static const unsigned drive_gma_pins[] = { + TEGRA_PIN_SDMMC4_CLK_PCC4, + TEGRA_PIN_SDMMC4_CMD_PT7, + TEGRA_PIN_SDMMC4_DAT0_PAA0, + TEGRA_PIN_SDMMC4_DAT1_PAA1, + TEGRA_PIN_SDMMC4_DAT2_PAA2, + TEGRA_PIN_SDMMC4_DAT3_PAA3, + TEGRA_PIN_SDMMC4_DAT4_PAA4, + TEGRA_PIN_SDMMC4_DAT5_PAA5, + TEGRA_PIN_SDMMC4_DAT6_PAA6, + TEGRA_PIN_SDMMC4_DAT7_PAA7, +}; + +static const unsigned drive_gme_pins[] = { + TEGRA_PIN_PBB0, + TEGRA_PIN_CAM_I2C_SCL_PBB1, + TEGRA_PIN_CAM_I2C_SDA_PBB2, + TEGRA_PIN_PBB3, + TEGRA_PIN_PCC2, +}; + +static const unsigned drive_gmf_pins[] = { + TEGRA_PIN_PBB4, + TEGRA_PIN_PBB5, + TEGRA_PIN_PBB6, + TEGRA_PIN_PBB7, +}; + +static const unsigned drive_gmg_pins[] = { + TEGRA_PIN_CAM_MCLK_PCC0, +}; + +static const unsigned drive_gmh_pins[] = { + TEGRA_PIN_PCC1, +}; + +static const unsigned drive_owr_pins[] = { + TEGRA_PIN_SDMMC3_CD_N_PV2, +}; + +static const unsigned drive_uda_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, + TEGRA_PIN_ULPI_DIR_PY1, + TEGRA_PIN_ULPI_NXT_PY2, + TEGRA_PIN_ULPI_STP_PY3, +}; + +static const unsigned drive_dev3_pins[] = { +}; + +static const unsigned drive_cec_pins[] = { +}; + +static const unsigned drive_at6_pins[] = { +}; + +static const unsigned drive_dap5_pins[] = { +}; + +static const unsigned drive_usb_vbus_en_pins[] = { +}; + +static const unsigned drive_ao3_pins[] = { +}; + +static const unsigned drive_hv0_pins[] = { +}; + +static const unsigned drive_sdio4_pins[] = { +}; + +static const unsigned drive_ao0_pins[] = { +}; + +enum tegra_mux { + TEGRA_MUX_BLINK, + TEGRA_MUX_CEC, + TEGRA_MUX_CLDVFS, + TEGRA_MUX_CLK, + TEGRA_MUX_CLK12, + TEGRA_MUX_CPU, + TEGRA_MUX_DAP, + TEGRA_MUX_DAP1, + TEGRA_MUX_DAP2, + TEGRA_MUX_DEV3, + TEGRA_MUX_DISPLAYA, + TEGRA_MUX_DISPLAYA_ALT, + TEGRA_MUX_DISPLAYB, + TEGRA_MUX_DTV, + TEGRA_MUX_EMC_DLL, + TEGRA_MUX_EXTPERIPH1, + TEGRA_MUX_EXTPERIPH2, + TEGRA_MUX_EXTPERIPH3, + TEGRA_MUX_GMI, + TEGRA_MUX_GMI_ALT, + TEGRA_MUX_HDA, + TEGRA_MUX_HSI, + TEGRA_MUX_I2C1, + TEGRA_MUX_I2C2, + TEGRA_MUX_I2C3, + TEGRA_MUX_I2C4, + TEGRA_MUX_I2CPWR, + TEGRA_MUX_I2S0, + TEGRA_MUX_I2S1, + TEGRA_MUX_I2S2, + TEGRA_MUX_I2S3, + TEGRA_MUX_I2S4, + TEGRA_MUX_IRDA, + TEGRA_MUX_KBC, + TEGRA_MUX_NAND, + TEGRA_MUX_NAND_ALT, + TEGRA_MUX_OWR, + TEGRA_MUX_PMI, + TEGRA_MUX_PWM0, + TEGRA_MUX_PWM1, + TEGRA_MUX_PWM2, + TEGRA_MUX_PWM3, + TEGRA_MUX_PWRON, + TEGRA_MUX_RESET_OUT_N, + TEGRA_MUX_RSVD1, + TEGRA_MUX_RSVD2, + TEGRA_MUX_RSVD3, + TEGRA_MUX_RSVD4, + TEGRA_MUX_RTCK, + TEGRA_MUX_SDMMC1, + TEGRA_MUX_SDMMC2, + TEGRA_MUX_SDMMC3, + TEGRA_MUX_SDMMC4, + TEGRA_MUX_SOC, + TEGRA_MUX_SPDIF, + TEGRA_MUX_SPI1, + TEGRA_MUX_SPI2, + TEGRA_MUX_SPI3, + TEGRA_MUX_SPI4, + TEGRA_MUX_SPI5, + TEGRA_MUX_SPI6, + TEGRA_MUX_SYSCLK, + TEGRA_MUX_TRACE, + TEGRA_MUX_UARTA, + TEGRA_MUX_UARTB, + TEGRA_MUX_UARTC, + TEGRA_MUX_UARTD, + TEGRA_MUX_ULPI, + TEGRA_MUX_USB, + TEGRA_MUX_VGP1, + TEGRA_MUX_VGP2, + TEGRA_MUX_VGP3, + TEGRA_MUX_VGP4, + TEGRA_MUX_VGP5, + TEGRA_MUX_VGP6, + TEGRA_MUX_VI, + TEGRA_MUX_VI_ALT1, + TEGRA_MUX_VI_ALT3, +}; + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + } + +static struct tegra_function tegra114_functions[] = { + FUNCTION(blink), + FUNCTION(cec), + FUNCTION(cldvfs), + FUNCTION(clk), + FUNCTION(clk12), + FUNCTION(cpu), + FUNCTION(dap), + FUNCTION(dap1), + FUNCTION(dap2), + FUNCTION(dev3), + FUNCTION(displaya), + FUNCTION(displaya_alt), + FUNCTION(displayb), + FUNCTION(dtv), + FUNCTION(emc_dll), + FUNCTION(extperiph1), + FUNCTION(extperiph2), + FUNCTION(extperiph3), + FUNCTION(gmi), + FUNCTION(gmi_alt), + FUNCTION(hda), + FUNCTION(hsi), + FUNCTION(i2c1), + FUNCTION(i2c2), + FUNCTION(i2c3), + FUNCTION(i2c4), + FUNCTION(i2cpwr), + FUNCTION(i2s0), + FUNCTION(i2s1), + FUNCTION(i2s2), + FUNCTION(i2s3), + FUNCTION(i2s4), + FUNCTION(irda), + FUNCTION(kbc), + FUNCTION(nand), + FUNCTION(nand_alt), + FUNCTION(owr), + FUNCTION(pmi), + FUNCTION(pwm0), + FUNCTION(pwm1), + FUNCTION(pwm2), + FUNCTION(pwm3), + FUNCTION(pwron), + FUNCTION(reset_out_n), + FUNCTION(rsvd1), + FUNCTION(rsvd2), + FUNCTION(rsvd3), + FUNCTION(rsvd4), + FUNCTION(rtck), + FUNCTION(sdmmc1), + FUNCTION(sdmmc2), + FUNCTION(sdmmc3), + FUNCTION(sdmmc4), + FUNCTION(soc), + FUNCTION(spdif), + FUNCTION(spi1), + FUNCTION(spi2), + FUNCTION(spi3), + FUNCTION(spi4), + FUNCTION(spi5), + FUNCTION(spi6), + FUNCTION(sysclk), + FUNCTION(trace), + FUNCTION(uarta), + FUNCTION(uartb), + FUNCTION(uartc), + FUNCTION(uartd), + FUNCTION(ulpi), + FUNCTION(usb), + FUNCTION(vgp1), + FUNCTION(vgp2), + FUNCTION(vgp3), + FUNCTION(vgp4), + FUNCTION(vgp5), + FUNCTION(vgp6), + FUNCTION(vi), + FUNCTION(vi_alt1), + FUNCTION(vi_alt3), +}; + +#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ +#define PINGROUP_REG_A 0x3000 /* bank 1 */ + +#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A) +#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) + +#define PINGROUP_BIT_Y(b) (b) +#define PINGROUP_BIT_N(b) (-1) + +#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_##f0, \ + TEGRA_MUX_##f1, \ + TEGRA_MUX_##f2, \ + TEGRA_MUX_##f3, \ + }, \ + .mux_reg = PINGROUP_REG(r), \ + .mux_bank = 1, \ + .mux_bit = 0, \ + .pupd_reg = PINGROUP_REG(r), \ + .pupd_bank = 1, \ + .pupd_bit = 2, \ + .tri_reg = PINGROUP_REG(r), \ + .tri_bank = 1, \ + .tri_bit = 4, \ + .einput_bit = 5, \ + .odrain_bit = PINGROUP_BIT_##od(6), \ + .lock_bit = 7, \ + .ioreset_bit = PINGROUP_BIT_##ior(8), \ + .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9), \ + .drv_reg = -1, \ + } + +#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, \ + drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, \ + slwf_b, slwf_w, drvtype) \ + { \ + .name = "drive_" #pg_name, \ + .pins = drive_##pg_name##_pins, \ + .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ + .mux_reg = -1, \ + .pupd_reg = -1, \ + .tri_reg = -1, \ + .einput_bit = -1, \ + .odrain_bit = -1, \ + .lock_bit = -1, \ + .ioreset_bit = -1, \ + .rcv_sel_bit = -1, \ + .drv_reg = DRV_PINGROUP_REG(r), \ + .drv_bank = 0, \ + .hsm_bit = hsm_b, \ + .schmitt_bit = schmitt_b, \ + .lpmd_bit = lpmd_b, \ + .drvdn_bit = drvdn_b, \ + .drvdn_width = drvdn_w, \ + .drvup_bit = drvup_b, \ + .drvup_width = drvup_w, \ + .slwr_bit = slwr_b, \ + .slwr_width = slwr_w, \ + .slwf_bit = slwf_b, \ + .slwf_width = slwf_w, \ + .drvtype_bit = PINGROUP_BIT_##drvtype(6), \ + } + +static const struct tegra_pingroup tegra114_groups[] = { + /* pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel */ + PINGROUP(ulpi_data0_po1, SPI3, HSI, UARTA, ULPI, 0x3000, N, N, N), + PINGROUP(ulpi_data1_po2, SPI3, HSI, UARTA, ULPI, 0x3004, N, N, N), + PINGROUP(ulpi_data2_po3, SPI3, HSI, UARTA, ULPI, 0x3008, N, N, N), + PINGROUP(ulpi_data3_po4, SPI3, HSI, UARTA, ULPI, 0x300c, N, N, N), + PINGROUP(ulpi_data4_po5, SPI2, HSI, UARTA, ULPI, 0x3010, N, N, N), + PINGROUP(ulpi_data5_po6, SPI2, HSI, UARTA, ULPI, 0x3014, N, N, N), + PINGROUP(ulpi_data6_po7, SPI2, HSI, UARTA, ULPI, 0x3018, N, N, N), + PINGROUP(ulpi_data7_po0, SPI2, HSI, UARTA, ULPI, 0x301c, N, N, N), + PINGROUP(ulpi_clk_py0, SPI1, SPI5, UARTD, ULPI, 0x3020, N, N, N), + PINGROUP(ulpi_dir_py1, SPI1, SPI5, UARTD, ULPI, 0x3024, N, N, N), + PINGROUP(ulpi_nxt_py2, SPI1, SPI5, UARTD, ULPI, 0x3028, N, N, N), + PINGROUP(ulpi_stp_py3, SPI1, SPI5, UARTD, ULPI, 0x302c, N, N, N), + PINGROUP(dap3_fs_pp0, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3030, N, N, N), + PINGROUP(dap3_din_pp1, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3034, N, N, N), + PINGROUP(dap3_dout_pp2, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3038, N, N, N), + PINGROUP(dap3_sclk_pp3, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x303c, N, N, N), + PINGROUP(pv0, USB, RSVD2, RSVD3, RSVD4, 0x3040, N, N, N), + PINGROUP(pv1, RSVD1, RSVD2, RSVD3, RSVD4, 0x3044, N, N, N), + PINGROUP(sdmmc1_clk_pz0, SDMMC1, CLK12, RSVD3, RSVD4, 0x3048, N, N, N), + PINGROUP(sdmmc1_cmd_pz1, SDMMC1, SPDIF, SPI4, UARTA, 0x304c, N, N, N), + PINGROUP(sdmmc1_dat3_py4, SDMMC1, SPDIF, SPI4, UARTA, 0x3050, N, N, N), + PINGROUP(sdmmc1_dat2_py5, SDMMC1, PWM0, SPI4, UARTA, 0x3054, N, N, N), + PINGROUP(sdmmc1_dat1_py6, SDMMC1, PWM1, SPI4, UARTA, 0x3058, N, N, N), + PINGROUP(sdmmc1_dat0_py7, SDMMC1, RSVD2, SPI4, UARTA, 0x305c, N, N, N), + PINGROUP(clk2_out_pw5, EXTPERIPH2, RSVD2, RSVD3, RSVD4, 0x3068, N, N, N), + PINGROUP(clk2_req_pcc5, DAP, RSVD2, RSVD3, RSVD4, 0x306c, N, N, N), + PINGROUP(hdmi_int_pn7, RSVD1, RSVD2, RSVD3, RSVD4, 0x3110, N, N, Y), + PINGROUP(ddc_scl_pv4, I2C4, RSVD2, RSVD3, RSVD4, 0x3114, N, N, Y), + PINGROUP(ddc_sda_pv5, I2C4, RSVD2, RSVD3, RSVD4, 0x3118, N, N, Y), + PINGROUP(uart2_rxd_pc3, IRDA, SPDIF, UARTA, SPI4, 0x3164, N, N, N), + PINGROUP(uart2_txd_pc2, IRDA, SPDIF, UARTA, SPI4, 0x3168, N, N, N), + PINGROUP(uart2_rts_n_pj6, UARTA, UARTB, RSVD3, SPI4, 0x316c, N, N, N), + PINGROUP(uart2_cts_n_pj5, UARTA, UARTB, RSVD3, SPI4, 0x3170, N, N, N), + PINGROUP(uart3_txd_pw6, UARTC, RSVD2, RSVD3, SPI4, 0x3174, N, N, N), + PINGROUP(uart3_rxd_pw7, UARTC, RSVD2, RSVD3, SPI4, 0x3178, N, N, N), + PINGROUP(uart3_cts_n_pa1, UARTC, SDMMC1, DTV, SPI4, 0x317c, N, N, N), + PINGROUP(uart3_rts_n_pc0, UARTC, PWM0, DTV, DISPLAYA, 0x3180, N, N, N), + PINGROUP(pu0, OWR, UARTA, RSVD3, RSVD4, 0x3184, N, N, N), + PINGROUP(pu1, RSVD1, UARTA, RSVD3, RSVD4, 0x3188, N, N, N), + PINGROUP(pu2, RSVD1, UARTA, RSVD3, RSVD4, 0x318c, N, N, N), + PINGROUP(pu3, PWM0, UARTA, DISPLAYA, DISPLAYB, 0x3190, N, N, N), + PINGROUP(pu4, PWM1, UARTA, DISPLAYA, DISPLAYB, 0x3194, N, N, N), + PINGROUP(pu5, PWM2, UARTA, DISPLAYA, DISPLAYB, 0x3198, N, N, N), + PINGROUP(pu6, PWM3, UARTA, USB, DISPLAYB, 0x319c, N, N, N), + PINGROUP(gen1_i2c_sda_pc5, I2C1, RSVD2, RSVD3, RSVD4, 0x31a0, Y, N, N), + PINGROUP(gen1_i2c_scl_pc4, I2C1, RSVD2, RSVD3, RSVD4, 0x31a4, Y, N, N), + PINGROUP(dap4_fs_pp4, I2S3, RSVD2, DTV, RSVD4, 0x31a8, N, N, N), + PINGROUP(dap4_din_pp5, I2S3, RSVD2, RSVD3, RSVD4, 0x31ac, N, N, N), + PINGROUP(dap4_dout_pp6, I2S3, RSVD2, DTV, RSVD4, 0x31b0, N, N, N), + PINGROUP(dap4_sclk_pp7, I2S3, RSVD2, RSVD3, RSVD4, 0x31b4, N, N, N), + PINGROUP(clk3_out_pee0, EXTPERIPH3, RSVD2, RSVD3, RSVD4, 0x31b8, N, N, N), + PINGROUP(clk3_req_pee1, DEV3, RSVD2, RSVD3, RSVD4, 0x31bc, N, N, N), + PINGROUP(gmi_wp_n_pc7, RSVD1, NAND, GMI, GMI_ALT, 0x31c0, N, N, N), + PINGROUP(gmi_iordy_pi5, SDMMC2, RSVD2, GMI, TRACE, 0x31c4, N, N, N), + PINGROUP(gmi_wait_pi7, SPI4, NAND, GMI, DTV, 0x31c8, N, N, N), + PINGROUP(gmi_adv_n_pk0, RSVD1, NAND, GMI, TRACE, 0x31cc, N, N, N), + PINGROUP(gmi_clk_pk1, SDMMC2, NAND, GMI, TRACE, 0x31d0, N, N, N), + PINGROUP(gmi_cs0_n_pj0, RSVD1, NAND, GMI, USB, 0x31d4, N, N, N), + PINGROUP(gmi_cs1_n_pj2, RSVD1, NAND, GMI, SOC, 0x31d8, N, N, N), + PINGROUP(gmi_cs2_n_pk3, SDMMC2, NAND, GMI, TRACE, 0x31dc, N, N, N), + PINGROUP(gmi_cs3_n_pk4, SDMMC2, NAND, GMI, GMI_ALT, 0x31e0, N, N, N), + PINGROUP(gmi_cs4_n_pk2, USB, NAND, GMI, TRACE, 0x31e4, N, N, N), + PINGROUP(gmi_cs6_n_pi3, NAND, NAND_ALT, GMI, SPI4, 0x31e8, N, N, N), + PINGROUP(gmi_cs7_n_pi6, NAND, NAND_ALT, GMI, SDMMC2, 0x31ec, N, N, N), + PINGROUP(gmi_ad0_pg0, RSVD1, NAND, GMI, RSVD4, 0x31f0, N, N, N), + PINGROUP(gmi_ad1_pg1, RSVD1, NAND, GMI, RSVD4, 0x31f4, N, N, N), + PINGROUP(gmi_ad2_pg2, RSVD1, NAND, GMI, RSVD4, 0x31f8, N, N, N), + PINGROUP(gmi_ad3_pg3, RSVD1, NAND, GMI, RSVD4, 0x31fc, N, N, N), + PINGROUP(gmi_ad4_pg4, RSVD1, NAND, GMI, RSVD4, 0x3200, N, N, N), + PINGROUP(gmi_ad5_pg5, RSVD1, NAND, GMI, SPI4, 0x3204, N, N, N), + PINGROUP(gmi_ad6_pg6, RSVD1, NAND, GMI, SPI4, 0x3208, N, N, N), + PINGROUP(gmi_ad7_pg7, RSVD1, NAND, GMI, SPI4, 0x320c, N, N, N), + PINGROUP(gmi_ad8_ph0, PWM0, NAND, GMI, DTV, 0x3210, N, N, N), + PINGROUP(gmi_ad9_ph1, PWM1, NAND, GMI, CLDVFS, 0x3214, N, N, N), + PINGROUP(gmi_ad10_ph2, PWM2, NAND, GMI, CLDVFS, 0x3218, N, N, N), + PINGROUP(gmi_ad11_ph3, PWM3, NAND, GMI, USB, 0x321c, N, N, N), + PINGROUP(gmi_ad12_ph4, SDMMC2, NAND, GMI, RSVD4, 0x3220, N, N, N), + PINGROUP(gmi_ad13_ph5, SDMMC2, NAND, GMI, RSVD4, 0x3224, N, N, N), + PINGROUP(gmi_ad14_ph6, SDMMC2, NAND, GMI, DTV, 0x3228, N, N, N), + PINGROUP(gmi_ad15_ph7, SDMMC2, NAND, GMI, DTV, 0x322c, N, N, N), + PINGROUP(gmi_a16_pj7, UARTD, TRACE, GMI, GMI_ALT, 0x3230, N, N, N), + PINGROUP(gmi_a17_pb0, UARTD, RSVD2, GMI, TRACE, 0x3234, N, N, N), + PINGROUP(gmi_a18_pb1, UARTD, RSVD2, GMI, TRACE, 0x3238, N, N, N), + PINGROUP(gmi_a19_pk7, UARTD, SPI4, GMI, TRACE, 0x323c, N, N, N), + PINGROUP(gmi_wr_n_pi0, RSVD1, NAND, GMI, SPI4, 0x3240, N, N, N), + PINGROUP(gmi_oe_n_pi1, RSVD1, NAND, GMI, SOC, 0x3244, N, N, N), + PINGROUP(gmi_dqs_p_pj3, SDMMC2, NAND, GMI, TRACE, 0x3248, N, N, N), + PINGROUP(gmi_rst_n_pi4, NAND, NAND_ALT, GMI, RSVD4, 0x324c, N, N, N), + PINGROUP(gen2_i2c_scl_pt5, I2C2, RSVD2, GMI, RSVD4, 0x3250, Y, N, N), + PINGROUP(gen2_i2c_sda_pt6, I2C2, RSVD2, GMI, RSVD4, 0x3254, Y, N, N), + PINGROUP(sdmmc4_clk_pcc4, SDMMC4, RSVD2, GMI, RSVD4, 0x3258, N, Y, N), + PINGROUP(sdmmc4_cmd_pt7, SDMMC4, RSVD2, GMI, RSVD4, 0x325c, N, Y, N), + PINGROUP(sdmmc4_dat0_paa0, SDMMC4, SPI3, GMI, RSVD4, 0x3260, N, Y, N), + PINGROUP(sdmmc4_dat1_paa1, SDMMC4, SPI3, GMI, RSVD4, 0x3264, N, Y, N), + PINGROUP(sdmmc4_dat2_paa2, SDMMC4, SPI3, GMI, RSVD4, 0x3268, N, Y, N), + PINGROUP(sdmmc4_dat3_paa3, SDMMC4, SPI3, GMI, RSVD4, 0x326c, N, Y, N), + PINGROUP(sdmmc4_dat4_paa4, SDMMC4, SPI3, GMI, RSVD4, 0x3270, N, Y, N), + PINGROUP(sdmmc4_dat5_paa5, SDMMC4, SPI3, GMI, RSVD4, 0x3274, N, Y, N), + PINGROUP(sdmmc4_dat6_paa6, SDMMC4, SPI3, GMI, RSVD4, 0x3278, N, Y, N), + PINGROUP(sdmmc4_dat7_paa7, SDMMC4, RSVD2, GMI, RSVD4, 0x327c, N, Y, N), + PINGROUP(cam_mclk_pcc0, VI, VI_ALT1, VI_ALT3, RSVD4, 0x3284, N, N, N), + PINGROUP(pcc1, I2S4, RSVD2, RSVD3, RSVD4, 0x3288, N, N, N), + PINGROUP(pbb0, I2S4, VI, VI_ALT1, VI_ALT3, 0x328c, N, N, N), + PINGROUP(cam_i2c_scl_pbb1, VGP1, I2C3, RSVD3, RSVD4, 0x3290, Y, N, N), + PINGROUP(cam_i2c_sda_pbb2, VGP2, I2C3, RSVD3, RSVD4, 0x3294, Y, N, N), + PINGROUP(pbb3, VGP3, DISPLAYA, DISPLAYB, RSVD4, 0x3298, N, N, N), + PINGROUP(pbb4, VGP4, DISPLAYA, DISPLAYB, RSVD4, 0x329c, N, N, N), + PINGROUP(pbb5, VGP5, DISPLAYA, DISPLAYB, RSVD4, 0x32a0, N, N, N), + PINGROUP(pbb6, VGP6, DISPLAYA, DISPLAYB, RSVD4, 0x32a4, N, N, N), + PINGROUP(pbb7, I2S4, RSVD2, RSVD3, RSVD4, 0x32a8, N, N, N), + PINGROUP(pcc2, I2S4, RSVD2, RSVD3, RSVD4, 0x32ac, N, N, N), + PINGROUP(jtag_rtck, RTCK, RSVD2, RSVD3, RSVD4, 0x32b0, N, N, N), + PINGROUP(pwr_i2c_scl_pz6, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b4, Y, N, N), + PINGROUP(pwr_i2c_sda_pz7, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b8, Y, N, N), + PINGROUP(kb_row0_pr0, KBC, RSVD2, RSVD3, RSVD4, 0x32bc, N, N, N), + PINGROUP(kb_row1_pr1, KBC, RSVD2, RSVD3, RSVD4, 0x32c0, N, N, N), + PINGROUP(kb_row2_pr2, KBC, RSVD2, RSVD3, RSVD4, 0x32c4, N, N, N), + PINGROUP(kb_row3_pr3, KBC, DISPLAYA, RSVD3, DISPLAYB, 0x32c8, N, N, N), + PINGROUP(kb_row4_pr4, KBC, DISPLAYA, SPI2, DISPLAYB, 0x32cc, N, N, N), + PINGROUP(kb_row5_pr5, KBC, DISPLAYA, SPI2, DISPLAYB, 0x32d0, N, N, N), + PINGROUP(kb_row6_pr6, KBC, DISPLAYA, DISPLAYA_ALT, DISPLAYB, 0x32d4, N, N, N), + PINGROUP(kb_row7_pr7, KBC, RSVD2, CLDVFS, UARTA, 0x32d8, N, N, N), + PINGROUP(kb_row8_ps0, KBC, RSVD2, CLDVFS, UARTA, 0x32dc, N, N, N), + PINGROUP(kb_row9_ps1, KBC, RSVD2, RSVD3, UARTA, 0x32e0, N, N, N), + PINGROUP(kb_row10_ps2, KBC, RSVD2, RSVD3, UARTA, 0x32e4, N, N, N), + PINGROUP(kb_col0_pq0, KBC, USB, SPI2, EMC_DLL, 0x32fc, N, N, N), + PINGROUP(kb_col1_pq1, KBC, RSVD2, SPI2, EMC_DLL, 0x3300, N, N, N), + PINGROUP(kb_col2_pq2, KBC, RSVD2, SPI2, RSVD4, 0x3304, N, N, N), + PINGROUP(kb_col3_pq3, KBC, DISPLAYA, PWM2, UARTA, 0x3308, N, N, N), + PINGROUP(kb_col4_pq4, KBC, OWR, SDMMC3, UARTA, 0x330c, N, N, N), + PINGROUP(kb_col5_pq5, KBC, RSVD2, SDMMC1, RSVD4, 0x3310, N, N, N), + PINGROUP(kb_col6_pq6, KBC, RSVD2, SPI2, RSVD4, 0x3314, N, N, N), + PINGROUP(kb_col7_pq7, KBC, RSVD2, SPI2, RSVD4, 0x3318, N, N, N), + PINGROUP(clk_32k_out_pa0, BLINK, SOC, RSVD3, RSVD4, 0x331c, N, N, N), + PINGROUP(sys_clk_req_pz5, SYSCLK, RSVD2, RSVD3, RSVD4, 0x3320, N, N, N), + PINGROUP(core_pwr_req, PWRON, RSVD2, RSVD3, RSVD4, 0x3324, N, N, N), + PINGROUP(cpu_pwr_req, CPU, RSVD2, RSVD3, RSVD4, 0x3328, N, N, N), + PINGROUP(pwr_int_n, PMI, RSVD2, RSVD3, RSVD4, 0x332c, N, N, N), + PINGROUP(clk_32k_in, CLK, RSVD2, RSVD3, RSVD4, 0x3330, N, N, N), + PINGROUP(owr, OWR, RSVD2, RSVD3, RSVD4, 0x3334, N, N, Y), + PINGROUP(dap1_fs_pn0, I2S0, HDA, GMI, RSVD4, 0x3338, N, N, N), + PINGROUP(dap1_din_pn1, I2S0, HDA, GMI, RSVD4, 0x333c, N, N, N), + PINGROUP(dap1_dout_pn2, I2S0, HDA, GMI, RSVD4, 0x3340, N, N, N), + PINGROUP(dap1_sclk_pn3, I2S0, HDA, GMI, RSVD4, 0x3344, N, N, N), + PINGROUP(clk1_req_pee2, DAP, DAP1, RSVD3, RSVD4, 0x3348, N, N, N), + PINGROUP(clk1_out_pw4, EXTPERIPH1, DAP2, RSVD3, RSVD4, 0x334c, N, N, N), + PINGROUP(spdif_in_pk6, SPDIF, USB, RSVD3, RSVD4, 0x3350, N, N, N), + PINGROUP(spdif_out_pk5, SPDIF, RSVD2, RSVD3, RSVD4, 0x3354, N, N, N), + PINGROUP(dap2_fs_pa2, I2S1, HDA, RSVD3, RSVD4, 0x3358, N, N, N), + PINGROUP(dap2_din_pa4, I2S1, HDA, RSVD3, RSVD4, 0x335c, N, N, N), + PINGROUP(dap2_dout_pa5, I2S1, HDA, RSVD3, RSVD4, 0x3360, N, N, N), + PINGROUP(dap2_sclk_pa3, I2S1, HDA, RSVD3, RSVD4, 0x3364, N, N, N), + PINGROUP(dvfs_pwm_px0, SPI6, CLDVFS, RSVD3, RSVD4, 0x3368, N, N, N), + PINGROUP(gpio_x1_aud_px1, SPI6, RSVD2, RSVD3, RSVD4, 0x336c, N, N, N), + PINGROUP(gpio_x3_aud_px3, SPI6, SPI1, RSVD3, RSVD4, 0x3370, N, N, N), + PINGROUP(dvfs_clk_px2, SPI6, CLDVFS, RSVD3, RSVD4, 0x3374, N, N, N), + PINGROUP(gpio_x4_aud_px4, RSVD1, SPI1, SPI2, DAP2, 0x3378, N, N, N), + PINGROUP(gpio_x5_aud_px5, RSVD1, SPI1, SPI2, RSVD4, 0x337c, N, N, N), + PINGROUP(gpio_x6_aud_px6, SPI6, SPI1, SPI2, RSVD4, 0x3380, N, N, N), + PINGROUP(gpio_x7_aud_px7, RSVD1, SPI1, SPI2, RSVD4, 0x3384, N, N, N), + PINGROUP(sdmmc3_clk_pa6, SDMMC3, RSVD2, RSVD3, SPI3, 0x3390, N, N, N), + PINGROUP(sdmmc3_cmd_pa7, SDMMC3, PWM3, UARTA, SPI3, 0x3394, N, N, N), + PINGROUP(sdmmc3_dat0_pb7, SDMMC3, RSVD2, RSVD3, SPI3, 0x3398, N, N, N), + PINGROUP(sdmmc3_dat1_pb6, SDMMC3, PWM2, UARTA, SPI3, 0x339c, N, N, N), + PINGROUP(sdmmc3_dat2_pb5, SDMMC3, PWM1, DISPLAYA, SPI3, 0x33a0, N, N, N), + PINGROUP(sdmmc3_dat3_pb4, SDMMC3, PWM0, DISPLAYB, SPI3, 0x33a4, N, N, N), + PINGROUP(hdmi_cec_pee3, CEC, SDMMC3, RSVD3, SOC, 0x33e0, Y, N, N), + PINGROUP(sdmmc1_wp_n_pv3, SDMMC1, CLK12, SPI4, UARTA, 0x33e4, N, N, N), + PINGROUP(sdmmc3_cd_n_pv2, SDMMC3, OWR, RSVD3, RSVD4, 0x33e8, N, N, N), + PINGROUP(gpio_w2_aud_pw2, SPI6, RSVD2, SPI2, I2C1, 0x33ec, N, N, N), + PINGROUP(gpio_w3_aud_pw3, SPI6, SPI1, SPI2, I2C1, 0x33f0, N, N, N), + PINGROUP(usb_vbus_en0_pn4, USB, RSVD2, RSVD3, RSVD4, 0x33f4, Y, N, N), + PINGROUP(usb_vbus_en1_pn5, USB, RSVD2, RSVD3, RSVD4, 0x33f8, Y, N, N), + PINGROUP(sdmmc3_clk_lb_in_pee5, SDMMC3, RSVD2, RSVD3, RSVD4, 0x33fc, N, N, N), + PINGROUP(sdmmc3_clk_lb_out_pee4, SDMMC3, RSVD2, RSVD3, RSVD4, 0x3400, N, N, N), + PINGROUP(gmi_clk_lb, SDMMC2, NAND, GMI, RSVD4, 0x3404, N, N, N), + PINGROUP(reset_out_n, RSVD1, RSVD2, RSVD3, RESET_OUT_N, 0x3408, N, N, N), + + /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w, drvtype */ + DRV_PINGROUP(ao1, 0x868, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(ao2, 0x86c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(at1, 0x870, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at2, 0x874, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at3, 0x878, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at4, 0x87c, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at5, 0x880, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(cdev1, 0x884, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(cdev2, 0x888, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap1, 0x890, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap2, 0x894, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap3, 0x898, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap4, 0x89c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dbg, 0x8a0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(sdio3, 0x8b0, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), + DRV_PINGROUP(spi, 0x8b4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uaa, 0x8b8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uab, 0x8bc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uart2, 0x8c0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uart3, 0x8c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(sdio1, 0x8ec, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), + DRV_PINGROUP(ddc, 0x8fc, 2, 3, -1, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gma, 0x900, 2, 3, -1, 14, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gme, 0x910, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gmf, 0x914, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gmg, 0x918, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gmh, 0x91c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(owr, 0x920, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uda, 0x924, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dev3, 0x92c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(cec, 0x938, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(at6, 0x994, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, Y), + DRV_PINGROUP(dap5, 0x998, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(usb_vbus_en, 0x99c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(ao3, 0x9a0, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), + DRV_PINGROUP(hv0, 0x9a4, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), + DRV_PINGROUP(sdio4, 0x9a8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(ao0, 0x9ac, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), +}; + +static const struct tegra_pinctrl_soc_data tegra114_pinctrl = { + .ngpios = NUM_GPIOS, + .pins = tegra114_pins, + .npins = ARRAY_SIZE(tegra114_pins), + .functions = tegra114_functions, + .nfunctions = ARRAY_SIZE(tegra114_functions), + .groups = tegra114_groups, + .ngroups = ARRAY_SIZE(tegra114_groups), + .hsm_in_mux = false, + .schmitt_in_mux = false, + .drvtype_in_mux = false, +}; + +static int tegra114_pinctrl_probe(struct platform_device *pdev) +{ + return tegra_pinctrl_probe(pdev, &tegra114_pinctrl); +} + +static const struct of_device_id tegra114_pinctrl_of_match[] = { + { .compatible = "nvidia,tegra114-pinmux", }, + { }, +}; +MODULE_DEVICE_TABLE(of, tegra114_pinctrl_of_match); + +static struct platform_driver tegra114_pinctrl_driver = { + .driver = { + .name = "tegra114-pinctrl", + .of_match_table = tegra114_pinctrl_of_match, + }, + .probe = tegra114_pinctrl_probe, + .remove = tegra_pinctrl_remove, +}; +module_platform_driver(tegra114_pinctrl_driver); + +MODULE_AUTHOR("Pritesh Raithatha "); +MODULE_DESCRIPTION("NVIDIA Tegra114 pinctrl driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra124.c b/drivers/pinctrl/tegra/pinctrl-tegra124.c new file mode 100644 index 000000000000..7cd44c7c296d --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra124.c @@ -0,0 +1,2084 @@ +/* + * Pinctrl data for the NVIDIA Tegra124 pinmux + * + * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#include +#include +#include +#include +#include + +#include "pinctrl-tegra.h" + +/* + * Most pins affected by the pinmux can also be GPIOs. Define these first. + * These must match how the GPIO driver names/numbers its pins. + */ +#define _GPIO(offset) (offset) + +#define TEGRA_PIN_CLK_32K_OUT_PA0 _GPIO(0) +#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) +#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) +#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) +#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) +#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) +#define TEGRA_PIN_SDMMC3_CLK_PA6 _GPIO(6) +#define TEGRA_PIN_SDMMC3_CMD_PA7 _GPIO(7) +#define TEGRA_PIN_PB0 _GPIO(8) +#define TEGRA_PIN_PB1 _GPIO(9) +#define TEGRA_PIN_SDMMC3_DAT3_PB4 _GPIO(12) +#define TEGRA_PIN_SDMMC3_DAT2_PB5 _GPIO(13) +#define TEGRA_PIN_SDMMC3_DAT1_PB6 _GPIO(14) +#define TEGRA_PIN_SDMMC3_DAT0_PB7 _GPIO(15) +#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) +#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) +#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) +#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) +#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) +#define TEGRA_PIN_PC7 _GPIO(23) +#define TEGRA_PIN_PG0 _GPIO(48) +#define TEGRA_PIN_PG1 _GPIO(49) +#define TEGRA_PIN_PG2 _GPIO(50) +#define TEGRA_PIN_PG3 _GPIO(51) +#define TEGRA_PIN_PG4 _GPIO(52) +#define TEGRA_PIN_PG5 _GPIO(53) +#define TEGRA_PIN_PG6 _GPIO(54) +#define TEGRA_PIN_PG7 _GPIO(55) +#define TEGRA_PIN_PH0 _GPIO(56) +#define TEGRA_PIN_PH1 _GPIO(57) +#define TEGRA_PIN_PH2 _GPIO(58) +#define TEGRA_PIN_PH3 _GPIO(59) +#define TEGRA_PIN_PH4 _GPIO(60) +#define TEGRA_PIN_PH5 _GPIO(61) +#define TEGRA_PIN_PH6 _GPIO(62) +#define TEGRA_PIN_PH7 _GPIO(63) +#define TEGRA_PIN_PI0 _GPIO(64) +#define TEGRA_PIN_PI1 _GPIO(65) +#define TEGRA_PIN_PI2 _GPIO(66) +#define TEGRA_PIN_PI3 _GPIO(67) +#define TEGRA_PIN_PI4 _GPIO(68) +#define TEGRA_PIN_PI5 _GPIO(69) +#define TEGRA_PIN_PI6 _GPIO(70) +#define TEGRA_PIN_PI7 _GPIO(71) +#define TEGRA_PIN_PJ0 _GPIO(72) +#define TEGRA_PIN_PJ2 _GPIO(74) +#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) +#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) +#define TEGRA_PIN_PJ7 _GPIO(79) +#define TEGRA_PIN_PK0 _GPIO(80) +#define TEGRA_PIN_PK1 _GPIO(81) +#define TEGRA_PIN_PK2 _GPIO(82) +#define TEGRA_PIN_PK3 _GPIO(83) +#define TEGRA_PIN_PK4 _GPIO(84) +#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) +#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) +#define TEGRA_PIN_PK7 _GPIO(87) +#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) +#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) +#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) +#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) +#define TEGRA_PIN_USB_VBUS_EN0_PN4 _GPIO(108) +#define TEGRA_PIN_USB_VBUS_EN1_PN5 _GPIO(109) +#define TEGRA_PIN_HDMI_INT_PN7 _GPIO(111) +#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) +#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) +#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) +#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) +#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) +#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) +#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) +#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) +#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) +#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) +#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) +#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) +#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) +#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) +#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) +#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) +#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) +#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) +#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) +#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) +#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) +#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) +#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) +#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) +#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) +#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) +#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) +#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) +#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) +#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) +#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) +#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) +#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) +#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) +#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) +#define TEGRA_PIN_KB_ROW11_PS3 _GPIO(147) +#define TEGRA_PIN_KB_ROW12_PS4 _GPIO(148) +#define TEGRA_PIN_KB_ROW13_PS5 _GPIO(149) +#define TEGRA_PIN_KB_ROW14_PS6 _GPIO(150) +#define TEGRA_PIN_KB_ROW15_PS7 _GPIO(151) +#define TEGRA_PIN_KB_ROW16_PT0 _GPIO(152) +#define TEGRA_PIN_KB_ROW17_PT1 _GPIO(153) +#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) +#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) +#define TEGRA_PIN_SDMMC4_CMD_PT7 _GPIO(159) +#define TEGRA_PIN_PU0 _GPIO(160) +#define TEGRA_PIN_PU1 _GPIO(161) +#define TEGRA_PIN_PU2 _GPIO(162) +#define TEGRA_PIN_PU3 _GPIO(163) +#define TEGRA_PIN_PU4 _GPIO(164) +#define TEGRA_PIN_PU5 _GPIO(165) +#define TEGRA_PIN_PU6 _GPIO(166) +#define TEGRA_PIN_PV0 _GPIO(168) +#define TEGRA_PIN_PV1 _GPIO(169) +#define TEGRA_PIN_SDMMC3_CD_N_PV2 _GPIO(170) +#define TEGRA_PIN_SDMMC1_WP_N_PV3 _GPIO(171) +#define TEGRA_PIN_DDC_SCL_PV4 _GPIO(172) +#define TEGRA_PIN_DDC_SDA_PV5 _GPIO(173) +#define TEGRA_PIN_GPIO_W2_AUD_PW2 _GPIO(178) +#define TEGRA_PIN_GPIO_W3_AUD_PW3 _GPIO(179) +#define TEGRA_PIN_DAP_MCLK1_PW4 _GPIO(180) +#define TEGRA_PIN_CLK2_OUT_PW5 _GPIO(181) +#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) +#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) +#define TEGRA_PIN_DVFS_PWM_PX0 _GPIO(184) +#define TEGRA_PIN_GPIO_X1_AUD_PX1 _GPIO(185) +#define TEGRA_PIN_DVFS_CLK_PX2 _GPIO(186) +#define TEGRA_PIN_GPIO_X3_AUD_PX3 _GPIO(187) +#define TEGRA_PIN_GPIO_X4_AUD_PX4 _GPIO(188) +#define TEGRA_PIN_GPIO_X5_AUD_PX5 _GPIO(189) +#define TEGRA_PIN_GPIO_X6_AUD_PX6 _GPIO(190) +#define TEGRA_PIN_GPIO_X7_AUD_PX7 _GPIO(191) +#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) +#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) +#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) +#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) +#define TEGRA_PIN_SDMMC1_DAT3_PY4 _GPIO(196) +#define TEGRA_PIN_SDMMC1_DAT2_PY5 _GPIO(197) +#define TEGRA_PIN_SDMMC1_DAT1_PY6 _GPIO(198) +#define TEGRA_PIN_SDMMC1_DAT0_PY7 _GPIO(199) +#define TEGRA_PIN_SDMMC1_CLK_PZ0 _GPIO(200) +#define TEGRA_PIN_SDMMC1_CMD_PZ1 _GPIO(201) +#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) +#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) +#define TEGRA_PIN_SDMMC4_DAT0_PAA0 _GPIO(208) +#define TEGRA_PIN_SDMMC4_DAT1_PAA1 _GPIO(209) +#define TEGRA_PIN_SDMMC4_DAT2_PAA2 _GPIO(210) +#define TEGRA_PIN_SDMMC4_DAT3_PAA3 _GPIO(211) +#define TEGRA_PIN_SDMMC4_DAT4_PAA4 _GPIO(212) +#define TEGRA_PIN_SDMMC4_DAT5_PAA5 _GPIO(213) +#define TEGRA_PIN_SDMMC4_DAT6_PAA6 _GPIO(214) +#define TEGRA_PIN_SDMMC4_DAT7_PAA7 _GPIO(215) +#define TEGRA_PIN_PBB0 _GPIO(216) +#define TEGRA_PIN_CAM_I2C_SCL_PBB1 _GPIO(217) +#define TEGRA_PIN_CAM_I2C_SDA_PBB2 _GPIO(218) +#define TEGRA_PIN_PBB3 _GPIO(219) +#define TEGRA_PIN_PBB4 _GPIO(220) +#define TEGRA_PIN_PBB5 _GPIO(221) +#define TEGRA_PIN_PBB6 _GPIO(222) +#define TEGRA_PIN_PBB7 _GPIO(223) +#define TEGRA_PIN_CAM_MCLK_PCC0 _GPIO(224) +#define TEGRA_PIN_PCC1 _GPIO(225) +#define TEGRA_PIN_PCC2 _GPIO(226) +#define TEGRA_PIN_SDMMC4_CLK_PCC4 _GPIO(228) +#define TEGRA_PIN_CLK2_REQ_PCC5 _GPIO(229) +#define TEGRA_PIN_PEX_L0_RST_N_PDD1 _GPIO(233) +#define TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2 _GPIO(234) +#define TEGRA_PIN_PEX_WAKE_N_PDD3 _GPIO(235) +#define TEGRA_PIN_PEX_L1_RST_N_PDD5 _GPIO(237) +#define TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6 _GPIO(238) +#define TEGRA_PIN_CLK3_OUT_PEE0 _GPIO(240) +#define TEGRA_PIN_CLK3_REQ_PEE1 _GPIO(241) +#define TEGRA_PIN_DAP_MCLK1_REQ_PEE2 _GPIO(242) +#define TEGRA_PIN_HDMI_CEC_PEE3 _GPIO(243) +#define TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4 _GPIO(244) +#define TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5 _GPIO(245) +#define TEGRA_PIN_DP_HPD_PFF0 _GPIO(248) +#define TEGRA_PIN_USB_VBUS_EN2_PFF1 _GPIO(249) +#define TEGRA_PIN_PFF2 _GPIO(250) + +/* All non-GPIO pins follow */ +#define NUM_GPIOS (TEGRA_PIN_PFF2 + 1) +#define _PIN(offset) (NUM_GPIOS + (offset)) + +/* Non-GPIO pins */ +#define TEGRA_PIN_CORE_PWR_REQ _PIN(0) +#define TEGRA_PIN_CPU_PWR_REQ _PIN(1) +#define TEGRA_PIN_PWR_INT_N _PIN(2) +#define TEGRA_PIN_GMI_CLK_LB _PIN(3) +#define TEGRA_PIN_RESET_OUT_N _PIN(4) +#define TEGRA_PIN_OWR _PIN(5) +#define TEGRA_PIN_CLK_32K_IN _PIN(6) +#define TEGRA_PIN_JTAG_RTCK _PIN(7) +#define TEGRA_PIN_DSI_B_CLK_P _PIN(8) +#define TEGRA_PIN_DSI_B_CLK_N _PIN(9) +#define TEGRA_PIN_DSI_B_D0_P _PIN(10) +#define TEGRA_PIN_DSI_B_D0_N _PIN(11) +#define TEGRA_PIN_DSI_B_D1_P _PIN(12) +#define TEGRA_PIN_DSI_B_D1_N _PIN(13) +#define TEGRA_PIN_DSI_B_D2_P _PIN(14) +#define TEGRA_PIN_DSI_B_D2_N _PIN(15) +#define TEGRA_PIN_DSI_B_D3_P _PIN(16) +#define TEGRA_PIN_DSI_B_D3_N _PIN(17) + +static const struct pinctrl_pin_desc tegra124_pins[] = { + PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"), + PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), + PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), + PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"), + PINCTRL_PIN(TEGRA_PIN_PB0, "PB0"), + PINCTRL_PIN(TEGRA_PIN_PB1, "PB1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"), + PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), + PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), + PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), + PINCTRL_PIN(TEGRA_PIN_PC7, "PC7"), + PINCTRL_PIN(TEGRA_PIN_PG0, "PG0"), + PINCTRL_PIN(TEGRA_PIN_PG1, "PG1"), + PINCTRL_PIN(TEGRA_PIN_PG2, "PG2"), + PINCTRL_PIN(TEGRA_PIN_PG3, "PG3"), + PINCTRL_PIN(TEGRA_PIN_PG4, "PG4"), + PINCTRL_PIN(TEGRA_PIN_PG5, "PG5"), + PINCTRL_PIN(TEGRA_PIN_PG6, "PG6"), + PINCTRL_PIN(TEGRA_PIN_PG7, "PG7"), + PINCTRL_PIN(TEGRA_PIN_PH0, "PH0"), + PINCTRL_PIN(TEGRA_PIN_PH1, "PH1"), + PINCTRL_PIN(TEGRA_PIN_PH2, "PH2"), + PINCTRL_PIN(TEGRA_PIN_PH3, "PH3"), + PINCTRL_PIN(TEGRA_PIN_PH4, "PH4"), + PINCTRL_PIN(TEGRA_PIN_PH5, "PH5"), + PINCTRL_PIN(TEGRA_PIN_PH6, "PH6"), + PINCTRL_PIN(TEGRA_PIN_PH7, "PH7"), + PINCTRL_PIN(TEGRA_PIN_PI0, "PI0"), + PINCTRL_PIN(TEGRA_PIN_PI1, "PI1"), + PINCTRL_PIN(TEGRA_PIN_PI2, "PI2"), + PINCTRL_PIN(TEGRA_PIN_PI3, "PI3"), + PINCTRL_PIN(TEGRA_PIN_PI4, "PI4"), + PINCTRL_PIN(TEGRA_PIN_PI5, "PI5"), + PINCTRL_PIN(TEGRA_PIN_PI6, "PI6"), + PINCTRL_PIN(TEGRA_PIN_PI7, "PI7"), + PINCTRL_PIN(TEGRA_PIN_PJ0, "PJ0"), + PINCTRL_PIN(TEGRA_PIN_PJ2, "PJ2"), + PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), + PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), + PINCTRL_PIN(TEGRA_PIN_PJ7, "PJ7"), + PINCTRL_PIN(TEGRA_PIN_PK0, "PK0"), + PINCTRL_PIN(TEGRA_PIN_PK1, "PK1"), + PINCTRL_PIN(TEGRA_PIN_PK2, "PK2"), + PINCTRL_PIN(TEGRA_PIN_PK3, "PK3"), + PINCTRL_PIN(TEGRA_PIN_PK4, "PK4"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), + PINCTRL_PIN(TEGRA_PIN_PK7, "PK7"), + PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), + PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PN4, "USB_VBUS_EN0 PN4"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PN5, "USB_VBUS_EN1 PN5"), + PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), + PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), + PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), + PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), + PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), + PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), + PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), + PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), + PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), + PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), + PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), + PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), + PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW16_PT0, "KB_ROW16 PT0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW17_PT1, "KB_ROW17 PT1"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"), + PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), + PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), + PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), + PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), + PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), + PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), + PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), + PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), + PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CD_N_PV2, "SDMMC3_CD_N PV2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_WP_N_PV3, "SDMMC1_WP_N PV3"), + PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"), + PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"), + PINCTRL_PIN(TEGRA_PIN_GPIO_W2_AUD_PW2, "GPIO_W2_AUD PW2"), + PINCTRL_PIN(TEGRA_PIN_GPIO_W3_AUD_PW3, "GPIO_W3_AUD PW3"), + PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_PW4, "DAP_MCLK1 PW4"), + PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"), + PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), + PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), + PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PX0, "DVFS_PWM PX0"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PX1, "GPIO_X1_AUD PX1"), + PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PX2, "DVFS_CLK PX2"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PX3, "GPIO_X3_AUD PX3"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X4_AUD_PX4, "GPIO_X4_AUD PX4"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X5_AUD_PX5, "GPIO_X5_AUD PX5"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X6_AUD_PX6, "GPIO_X6_AUD PX6"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X7_AUD_PX7, "GPIO_X7_AUD PX7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"), + PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"), + PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"), + PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"), + PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"), + PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), + PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), + PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"), + PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"), + PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"), + PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PDD1, "PEX_L0_RST_N PDD1"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, "PEX_L0_CLKREQ_N PDD2"), + PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PDD3, "PEX_WAKE_N PDD3"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PDD5, "PEX_L1_RST_N PDD5"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, "PEX_L1_CLKREQ_N PDD6"), + PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"), + PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"), + PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_REQ_PEE2, "DAP_MCLK1_REQ PEE2"), + PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, "SDMMC3_CLK_LB_OUT PEE4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, "SDMMC3_CLK_LB_IN PEE5"), + PINCTRL_PIN(TEGRA_PIN_DP_HPD_PFF0, "DP_HPD PFF0"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN2_PFF1, "USB_VBUS_EN2 PFF1"), + PINCTRL_PIN(TEGRA_PIN_PFF2, "PFF2"), + PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), + PINCTRL_PIN(TEGRA_PIN_GMI_CLK_LB, "GMI_CLK_LB"), + PINCTRL_PIN(TEGRA_PIN_RESET_OUT_N, "RESET_OUT_N"), + PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"), + PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), + PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_CLK_P, "DSI_B_CLK_P"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_CLK_N, "DSI_B_CLK_N"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D0_P, "DSI_B_D0_P"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D0_N, "DSI_B_D0_N"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D1_P, "DSI_B_D1_P"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D1_N, "DSI_B_D1_N"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D2_P, "DSI_B_D2_P"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D2_N, "DSI_B_D2_N"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D3_P, "DSI_B_D3_P"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D3_N, "DSI_B_D3_N"), +}; + +static const unsigned clk_32k_out_pa0_pins[] = { + TEGRA_PIN_CLK_32K_OUT_PA0, +}; + +static const unsigned uart3_cts_n_pa1_pins[] = { + TEGRA_PIN_UART3_CTS_N_PA1, +}; + +static const unsigned dap2_fs_pa2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, +}; + +static const unsigned dap2_sclk_pa3_pins[] = { + TEGRA_PIN_DAP2_SCLK_PA3, +}; + +static const unsigned dap2_din_pa4_pins[] = { + TEGRA_PIN_DAP2_DIN_PA4, +}; + +static const unsigned dap2_dout_pa5_pins[] = { + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned sdmmc3_clk_pa6_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PA6, +}; + +static const unsigned sdmmc3_cmd_pa7_pins[] = { + TEGRA_PIN_SDMMC3_CMD_PA7, +}; + +static const unsigned pb0_pins[] = { + TEGRA_PIN_PB0, +}; + +static const unsigned pb1_pins[] = { + TEGRA_PIN_PB1, +}; + +static const unsigned sdmmc3_dat3_pb4_pins[] = { + TEGRA_PIN_SDMMC3_DAT3_PB4, +}; + +static const unsigned sdmmc3_dat2_pb5_pins[] = { + TEGRA_PIN_SDMMC3_DAT2_PB5, +}; + +static const unsigned sdmmc3_dat1_pb6_pins[] = { + TEGRA_PIN_SDMMC3_DAT1_PB6, +}; + +static const unsigned sdmmc3_dat0_pb7_pins[] = { + TEGRA_PIN_SDMMC3_DAT0_PB7, +}; + +static const unsigned uart3_rts_n_pc0_pins[] = { + TEGRA_PIN_UART3_RTS_N_PC0, +}; + +static const unsigned uart2_txd_pc2_pins[] = { + TEGRA_PIN_UART2_TXD_PC2, +}; + +static const unsigned uart2_rxd_pc3_pins[] = { + TEGRA_PIN_UART2_RXD_PC3, +}; + +static const unsigned gen1_i2c_scl_pc4_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PC4, +}; + +static const unsigned gen1_i2c_sda_pc5_pins[] = { + TEGRA_PIN_GEN1_I2C_SDA_PC5, +}; + +static const unsigned pc7_pins[] = { + TEGRA_PIN_PC7, +}; + +static const unsigned pg0_pins[] = { + TEGRA_PIN_PG0, +}; + +static const unsigned pg1_pins[] = { + TEGRA_PIN_PG1, +}; + +static const unsigned pg2_pins[] = { + TEGRA_PIN_PG2, +}; + +static const unsigned pg3_pins[] = { + TEGRA_PIN_PG3, +}; + +static const unsigned pg4_pins[] = { + TEGRA_PIN_PG4, +}; + +static const unsigned pg5_pins[] = { + TEGRA_PIN_PG5, +}; + +static const unsigned pg6_pins[] = { + TEGRA_PIN_PG6, +}; + +static const unsigned pg7_pins[] = { + TEGRA_PIN_PG7, +}; + +static const unsigned ph0_pins[] = { + TEGRA_PIN_PH0, +}; + +static const unsigned ph1_pins[] = { + TEGRA_PIN_PH1, +}; + +static const unsigned ph2_pins[] = { + TEGRA_PIN_PH2, +}; + +static const unsigned ph3_pins[] = { + TEGRA_PIN_PH3, +}; + +static const unsigned ph4_pins[] = { + TEGRA_PIN_PH4, +}; + +static const unsigned ph5_pins[] = { + TEGRA_PIN_PH5, +}; + +static const unsigned ph6_pins[] = { + TEGRA_PIN_PH6, +}; + +static const unsigned ph7_pins[] = { + TEGRA_PIN_PH7, +}; + +static const unsigned pi0_pins[] = { + TEGRA_PIN_PI0, +}; + +static const unsigned pi1_pins[] = { + TEGRA_PIN_PI1, +}; + +static const unsigned pi2_pins[] = { + TEGRA_PIN_PI2, +}; + +static const unsigned pi3_pins[] = { + TEGRA_PIN_PI3, +}; + +static const unsigned pi4_pins[] = { + TEGRA_PIN_PI4, +}; + +static const unsigned pi5_pins[] = { + TEGRA_PIN_PI5, +}; + +static const unsigned pi6_pins[] = { + TEGRA_PIN_PI6, +}; + +static const unsigned pi7_pins[] = { + TEGRA_PIN_PI7, +}; + +static const unsigned pj0_pins[] = { + TEGRA_PIN_PJ0, +}; + +static const unsigned pj2_pins[] = { + TEGRA_PIN_PJ2, +}; + +static const unsigned uart2_cts_n_pj5_pins[] = { + TEGRA_PIN_UART2_CTS_N_PJ5, +}; + +static const unsigned uart2_rts_n_pj6_pins[] = { + TEGRA_PIN_UART2_RTS_N_PJ6, +}; + +static const unsigned pj7_pins[] = { + TEGRA_PIN_PJ7, +}; + +static const unsigned pk0_pins[] = { + TEGRA_PIN_PK0, +}; + +static const unsigned pk1_pins[] = { + TEGRA_PIN_PK1, +}; + +static const unsigned pk2_pins[] = { + TEGRA_PIN_PK2, +}; + +static const unsigned pk3_pins[] = { + TEGRA_PIN_PK3, +}; + +static const unsigned pk4_pins[] = { + TEGRA_PIN_PK4, +}; + +static const unsigned spdif_out_pk5_pins[] = { + TEGRA_PIN_SPDIF_OUT_PK5, +}; + +static const unsigned spdif_in_pk6_pins[] = { + TEGRA_PIN_SPDIF_IN_PK6, +}; + +static const unsigned pk7_pins[] = { + TEGRA_PIN_PK7, +}; + +static const unsigned dap1_fs_pn0_pins[] = { + TEGRA_PIN_DAP1_FS_PN0, +}; + +static const unsigned dap1_din_pn1_pins[] = { + TEGRA_PIN_DAP1_DIN_PN1, +}; + +static const unsigned dap1_dout_pn2_pins[] = { + TEGRA_PIN_DAP1_DOUT_PN2, +}; + +static const unsigned dap1_sclk_pn3_pins[] = { + TEGRA_PIN_DAP1_SCLK_PN3, +}; + +static const unsigned usb_vbus_en0_pn4_pins[] = { + TEGRA_PIN_USB_VBUS_EN0_PN4, +}; + +static const unsigned usb_vbus_en1_pn5_pins[] = { + TEGRA_PIN_USB_VBUS_EN1_PN5, +}; + +static const unsigned hdmi_int_pn7_pins[] = { + TEGRA_PIN_HDMI_INT_PN7, +}; + +static const unsigned ulpi_data7_po0_pins[] = { + TEGRA_PIN_ULPI_DATA7_PO0, +}; + +static const unsigned ulpi_data0_po1_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, +}; + +static const unsigned ulpi_data1_po2_pins[] = { + TEGRA_PIN_ULPI_DATA1_PO2, +}; + +static const unsigned ulpi_data2_po3_pins[] = { + TEGRA_PIN_ULPI_DATA2_PO3, +}; + +static const unsigned ulpi_data3_po4_pins[] = { + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned ulpi_data4_po5_pins[] = { + TEGRA_PIN_ULPI_DATA4_PO5, +}; + +static const unsigned ulpi_data5_po6_pins[] = { + TEGRA_PIN_ULPI_DATA5_PO6, +}; + +static const unsigned ulpi_data6_po7_pins[] = { + TEGRA_PIN_ULPI_DATA6_PO7, +}; + +static const unsigned dap3_fs_pp0_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, +}; + +static const unsigned dap3_din_pp1_pins[] = { + TEGRA_PIN_DAP3_DIN_PP1, +}; + +static const unsigned dap3_dout_pp2_pins[] = { + TEGRA_PIN_DAP3_DOUT_PP2, +}; + +static const unsigned dap3_sclk_pp3_pins[] = { + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned dap4_fs_pp4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, +}; + +static const unsigned dap4_din_pp5_pins[] = { + TEGRA_PIN_DAP4_DIN_PP5, +}; + +static const unsigned dap4_dout_pp6_pins[] = { + TEGRA_PIN_DAP4_DOUT_PP6, +}; + +static const unsigned dap4_sclk_pp7_pins[] = { + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned kb_col0_pq0_pins[] = { + TEGRA_PIN_KB_COL0_PQ0, +}; + +static const unsigned kb_col1_pq1_pins[] = { + TEGRA_PIN_KB_COL1_PQ1, +}; + +static const unsigned kb_col2_pq2_pins[] = { + TEGRA_PIN_KB_COL2_PQ2, +}; + +static const unsigned kb_col3_pq3_pins[] = { + TEGRA_PIN_KB_COL3_PQ3, +}; + +static const unsigned kb_col4_pq4_pins[] = { + TEGRA_PIN_KB_COL4_PQ4, +}; + +static const unsigned kb_col5_pq5_pins[] = { + TEGRA_PIN_KB_COL5_PQ5, +}; + +static const unsigned kb_col6_pq6_pins[] = { + TEGRA_PIN_KB_COL6_PQ6, +}; + +static const unsigned kb_col7_pq7_pins[] = { + TEGRA_PIN_KB_COL7_PQ7, +}; + +static const unsigned kb_row0_pr0_pins[] = { + TEGRA_PIN_KB_ROW0_PR0, +}; + +static const unsigned kb_row1_pr1_pins[] = { + TEGRA_PIN_KB_ROW1_PR1, +}; + +static const unsigned kb_row2_pr2_pins[] = { + TEGRA_PIN_KB_ROW2_PR2, +}; + +static const unsigned kb_row3_pr3_pins[] = { + TEGRA_PIN_KB_ROW3_PR3, +}; + +static const unsigned kb_row4_pr4_pins[] = { + TEGRA_PIN_KB_ROW4_PR4, +}; + +static const unsigned kb_row5_pr5_pins[] = { + TEGRA_PIN_KB_ROW5_PR5, +}; + +static const unsigned kb_row6_pr6_pins[] = { + TEGRA_PIN_KB_ROW6_PR6, +}; + +static const unsigned kb_row7_pr7_pins[] = { + TEGRA_PIN_KB_ROW7_PR7, +}; + +static const unsigned kb_row8_ps0_pins[] = { + TEGRA_PIN_KB_ROW8_PS0, +}; + +static const unsigned kb_row9_ps1_pins[] = { + TEGRA_PIN_KB_ROW9_PS1, +}; + +static const unsigned kb_row10_ps2_pins[] = { + TEGRA_PIN_KB_ROW10_PS2, +}; + +static const unsigned kb_row11_ps3_pins[] = { + TEGRA_PIN_KB_ROW11_PS3, +}; + +static const unsigned kb_row12_ps4_pins[] = { + TEGRA_PIN_KB_ROW12_PS4, +}; + +static const unsigned kb_row13_ps5_pins[] = { + TEGRA_PIN_KB_ROW13_PS5, +}; + +static const unsigned kb_row14_ps6_pins[] = { + TEGRA_PIN_KB_ROW14_PS6, +}; + +static const unsigned kb_row15_ps7_pins[] = { + TEGRA_PIN_KB_ROW15_PS7, +}; + +static const unsigned kb_row16_pt0_pins[] = { + TEGRA_PIN_KB_ROW16_PT0, +}; + +static const unsigned kb_row17_pt1_pins[] = { + TEGRA_PIN_KB_ROW17_PT1, +}; + +static const unsigned gen2_i2c_scl_pt5_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PT5, +}; + +static const unsigned gen2_i2c_sda_pt6_pins[] = { + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned sdmmc4_cmd_pt7_pins[] = { + TEGRA_PIN_SDMMC4_CMD_PT7, +}; + +static const unsigned pu0_pins[] = { + TEGRA_PIN_PU0, +}; + +static const unsigned pu1_pins[] = { + TEGRA_PIN_PU1, +}; + +static const unsigned pu2_pins[] = { + TEGRA_PIN_PU2, +}; + +static const unsigned pu3_pins[] = { + TEGRA_PIN_PU3, +}; + +static const unsigned pu4_pins[] = { + TEGRA_PIN_PU4, +}; + +static const unsigned pu5_pins[] = { + TEGRA_PIN_PU5, +}; + +static const unsigned pu6_pins[] = { + TEGRA_PIN_PU6, +}; + +static const unsigned pv0_pins[] = { + TEGRA_PIN_PV0, +}; + +static const unsigned pv1_pins[] = { + TEGRA_PIN_PV1, +}; + +static const unsigned sdmmc3_cd_n_pv2_pins[] = { + TEGRA_PIN_SDMMC3_CD_N_PV2, +}; + +static const unsigned sdmmc1_wp_n_pv3_pins[] = { + TEGRA_PIN_SDMMC1_WP_N_PV3, +}; + +static const unsigned ddc_scl_pv4_pins[] = { + TEGRA_PIN_DDC_SCL_PV4, +}; + +static const unsigned ddc_sda_pv5_pins[] = { + TEGRA_PIN_DDC_SDA_PV5, +}; + +static const unsigned gpio_w2_aud_pw2_pins[] = { + TEGRA_PIN_GPIO_W2_AUD_PW2, +}; + +static const unsigned gpio_w3_aud_pw3_pins[] = { + TEGRA_PIN_GPIO_W3_AUD_PW3, +}; + +static const unsigned dap_mclk1_pw4_pins[] = { + TEGRA_PIN_DAP_MCLK1_PW4, +}; + +static const unsigned clk2_out_pw5_pins[] = { + TEGRA_PIN_CLK2_OUT_PW5, +}; + +static const unsigned uart3_txd_pw6_pins[] = { + TEGRA_PIN_UART3_TXD_PW6, +}; + +static const unsigned uart3_rxd_pw7_pins[] = { + TEGRA_PIN_UART3_RXD_PW7, +}; + +static const unsigned dvfs_pwm_px0_pins[] = { + TEGRA_PIN_DVFS_PWM_PX0, +}; + +static const unsigned gpio_x1_aud_px1_pins[] = { + TEGRA_PIN_GPIO_X1_AUD_PX1, +}; + +static const unsigned dvfs_clk_px2_pins[] = { + TEGRA_PIN_DVFS_CLK_PX2, +}; + +static const unsigned gpio_x3_aud_px3_pins[] = { + TEGRA_PIN_GPIO_X3_AUD_PX3, +}; + +static const unsigned gpio_x4_aud_px4_pins[] = { + TEGRA_PIN_GPIO_X4_AUD_PX4, +}; + +static const unsigned gpio_x5_aud_px5_pins[] = { + TEGRA_PIN_GPIO_X5_AUD_PX5, +}; + +static const unsigned gpio_x6_aud_px6_pins[] = { + TEGRA_PIN_GPIO_X6_AUD_PX6, +}; + +static const unsigned gpio_x7_aud_px7_pins[] = { + TEGRA_PIN_GPIO_X7_AUD_PX7, +}; + +static const unsigned ulpi_clk_py0_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, +}; + +static const unsigned ulpi_dir_py1_pins[] = { + TEGRA_PIN_ULPI_DIR_PY1, +}; + +static const unsigned ulpi_nxt_py2_pins[] = { + TEGRA_PIN_ULPI_NXT_PY2, +}; + +static const unsigned ulpi_stp_py3_pins[] = { + TEGRA_PIN_ULPI_STP_PY3, +}; + +static const unsigned sdmmc1_dat3_py4_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PY4, +}; + +static const unsigned sdmmc1_dat2_py5_pins[] = { + TEGRA_PIN_SDMMC1_DAT2_PY5, +}; + +static const unsigned sdmmc1_dat1_py6_pins[] = { + TEGRA_PIN_SDMMC1_DAT1_PY6, +}; + +static const unsigned sdmmc1_dat0_py7_pins[] = { + TEGRA_PIN_SDMMC1_DAT0_PY7, +}; + +static const unsigned sdmmc1_clk_pz0_pins[] = { + TEGRA_PIN_SDMMC1_CLK_PZ0, +}; + +static const unsigned sdmmc1_cmd_pz1_pins[] = { + TEGRA_PIN_SDMMC1_CMD_PZ1, +}; + +static const unsigned pwr_i2c_scl_pz6_pins[] = { + TEGRA_PIN_PWR_I2C_SCL_PZ6, +}; + +static const unsigned pwr_i2c_sda_pz7_pins[] = { + TEGRA_PIN_PWR_I2C_SDA_PZ7, +}; + +static const unsigned sdmmc4_dat0_paa0_pins[] = { + TEGRA_PIN_SDMMC4_DAT0_PAA0, +}; + +static const unsigned sdmmc4_dat1_paa1_pins[] = { + TEGRA_PIN_SDMMC4_DAT1_PAA1, +}; + +static const unsigned sdmmc4_dat2_paa2_pins[] = { + TEGRA_PIN_SDMMC4_DAT2_PAA2, +}; + +static const unsigned sdmmc4_dat3_paa3_pins[] = { + TEGRA_PIN_SDMMC4_DAT3_PAA3, +}; + +static const unsigned sdmmc4_dat4_paa4_pins[] = { + TEGRA_PIN_SDMMC4_DAT4_PAA4, +}; + +static const unsigned sdmmc4_dat5_paa5_pins[] = { + TEGRA_PIN_SDMMC4_DAT5_PAA5, +}; + +static const unsigned sdmmc4_dat6_paa6_pins[] = { + TEGRA_PIN_SDMMC4_DAT6_PAA6, +}; + +static const unsigned sdmmc4_dat7_paa7_pins[] = { + TEGRA_PIN_SDMMC4_DAT7_PAA7, +}; + +static const unsigned pbb0_pins[] = { + TEGRA_PIN_PBB0, +}; + +static const unsigned cam_i2c_scl_pbb1_pins[] = { + TEGRA_PIN_CAM_I2C_SCL_PBB1, +}; + +static const unsigned cam_i2c_sda_pbb2_pins[] = { + TEGRA_PIN_CAM_I2C_SDA_PBB2, +}; + +static const unsigned pbb3_pins[] = { + TEGRA_PIN_PBB3, +}; + +static const unsigned pbb4_pins[] = { + TEGRA_PIN_PBB4, +}; + +static const unsigned pbb5_pins[] = { + TEGRA_PIN_PBB5, +}; + +static const unsigned pbb6_pins[] = { + TEGRA_PIN_PBB6, +}; + +static const unsigned pbb7_pins[] = { + TEGRA_PIN_PBB7, +}; + +static const unsigned cam_mclk_pcc0_pins[] = { + TEGRA_PIN_CAM_MCLK_PCC0, +}; + +static const unsigned pcc1_pins[] = { + TEGRA_PIN_PCC1, +}; + +static const unsigned pcc2_pins[] = { + TEGRA_PIN_PCC2, +}; + +static const unsigned sdmmc4_clk_pcc4_pins[] = { + TEGRA_PIN_SDMMC4_CLK_PCC4, +}; + +static const unsigned clk2_req_pcc5_pins[] = { + TEGRA_PIN_CLK2_REQ_PCC5, +}; + +static const unsigned pex_l0_rst_n_pdd1_pins[] = { + TEGRA_PIN_PEX_L0_RST_N_PDD1, +}; + +static const unsigned pex_l0_clkreq_n_pdd2_pins[] = { + TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, +}; + +static const unsigned pex_wake_n_pdd3_pins[] = { + TEGRA_PIN_PEX_WAKE_N_PDD3, +}; + +static const unsigned pex_l1_rst_n_pdd5_pins[] = { + TEGRA_PIN_PEX_L1_RST_N_PDD5, +}; + +static const unsigned pex_l1_clkreq_n_pdd6_pins[] = { + TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, +}; + +static const unsigned clk3_out_pee0_pins[] = { + TEGRA_PIN_CLK3_OUT_PEE0, +}; + +static const unsigned clk3_req_pee1_pins[] = { + TEGRA_PIN_CLK3_REQ_PEE1, +}; + +static const unsigned dap_mclk1_req_pee2_pins[] = { + TEGRA_PIN_DAP_MCLK1_REQ_PEE2, +}; + +static const unsigned hdmi_cec_pee3_pins[] = { + TEGRA_PIN_HDMI_CEC_PEE3, +}; + +static const unsigned sdmmc3_clk_lb_out_pee4_pins[] = { + TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, +}; + +static const unsigned sdmmc3_clk_lb_in_pee5_pins[] = { + TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, +}; + +static const unsigned dp_hpd_pff0_pins[] = { + TEGRA_PIN_DP_HPD_PFF0, +}; + +static const unsigned usb_vbus_en2_pff1_pins[] = { + TEGRA_PIN_USB_VBUS_EN2_PFF1, +}; + +static const unsigned pff2_pins[] = { + TEGRA_PIN_PFF2, +}; + +static const unsigned core_pwr_req_pins[] = { + TEGRA_PIN_CORE_PWR_REQ, +}; + +static const unsigned cpu_pwr_req_pins[] = { + TEGRA_PIN_CPU_PWR_REQ, +}; + +static const unsigned pwr_int_n_pins[] = { + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned gmi_clk_lb_pins[] = { + TEGRA_PIN_GMI_CLK_LB, +}; + +static const unsigned reset_out_n_pins[] = { + TEGRA_PIN_RESET_OUT_N, +}; + +static const unsigned owr_pins[] = { + TEGRA_PIN_OWR, +}; + +static const unsigned clk_32k_in_pins[] = { + TEGRA_PIN_CLK_32K_IN, +}; + +static const unsigned jtag_rtck_pins[] = { + TEGRA_PIN_JTAG_RTCK, +}; + +static const unsigned drive_ao1_pins[] = { + TEGRA_PIN_KB_ROW0_PR0, + TEGRA_PIN_KB_ROW1_PR1, + TEGRA_PIN_KB_ROW2_PR2, + TEGRA_PIN_KB_ROW3_PR3, + TEGRA_PIN_KB_ROW4_PR4, + TEGRA_PIN_KB_ROW5_PR5, + TEGRA_PIN_KB_ROW6_PR6, + TEGRA_PIN_KB_ROW7_PR7, + TEGRA_PIN_PWR_I2C_SCL_PZ6, + TEGRA_PIN_PWR_I2C_SDA_PZ7, +}; + +static const unsigned drive_ao2_pins[] = { + TEGRA_PIN_CLK_32K_OUT_PA0, + TEGRA_PIN_CLK_32K_IN, + TEGRA_PIN_KB_COL0_PQ0, + TEGRA_PIN_KB_COL1_PQ1, + TEGRA_PIN_KB_COL2_PQ2, + TEGRA_PIN_KB_COL3_PQ3, + TEGRA_PIN_KB_COL4_PQ4, + TEGRA_PIN_KB_COL5_PQ5, + TEGRA_PIN_KB_COL6_PQ6, + TEGRA_PIN_KB_COL7_PQ7, + TEGRA_PIN_KB_ROW8_PS0, + TEGRA_PIN_KB_ROW9_PS1, + TEGRA_PIN_KB_ROW10_PS2, + TEGRA_PIN_KB_ROW11_PS3, + TEGRA_PIN_KB_ROW12_PS4, + TEGRA_PIN_KB_ROW13_PS5, + TEGRA_PIN_KB_ROW14_PS6, + TEGRA_PIN_KB_ROW15_PS7, + TEGRA_PIN_KB_ROW16_PT0, + TEGRA_PIN_KB_ROW17_PT1, + TEGRA_PIN_SDMMC3_CD_N_PV2, + TEGRA_PIN_CORE_PWR_REQ, + TEGRA_PIN_CPU_PWR_REQ, + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned drive_at1_pins[] = { + TEGRA_PIN_PH0, + TEGRA_PIN_PH1, + TEGRA_PIN_PH2, + TEGRA_PIN_PH3, +}; + +static const unsigned drive_at2_pins[] = { + TEGRA_PIN_PG0, + TEGRA_PIN_PG1, + TEGRA_PIN_PG2, + TEGRA_PIN_PG3, + TEGRA_PIN_PG4, + TEGRA_PIN_PG5, + TEGRA_PIN_PG6, + TEGRA_PIN_PG7, + TEGRA_PIN_PI0, + TEGRA_PIN_PI1, + TEGRA_PIN_PI3, + TEGRA_PIN_PI4, + TEGRA_PIN_PI7, + TEGRA_PIN_PK0, + TEGRA_PIN_PK2, +}; + +static const unsigned drive_at3_pins[] = { + TEGRA_PIN_PC7, + TEGRA_PIN_PJ0, +}; + +static const unsigned drive_at4_pins[] = { + TEGRA_PIN_PB0, + TEGRA_PIN_PB1, + TEGRA_PIN_PJ0, + TEGRA_PIN_PJ7, + TEGRA_PIN_PK7, +}; + +static const unsigned drive_at5_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PT5, + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned drive_cdev1_pins[] = { + TEGRA_PIN_DAP_MCLK1_PW4, + TEGRA_PIN_DAP_MCLK1_REQ_PEE2, +}; + +static const unsigned drive_cdev2_pins[] = { + TEGRA_PIN_CLK2_OUT_PW5, + TEGRA_PIN_CLK2_REQ_PCC5, +}; + +static const unsigned drive_dap1_pins[] = { + TEGRA_PIN_DAP1_FS_PN0, + TEGRA_PIN_DAP1_DIN_PN1, + TEGRA_PIN_DAP1_DOUT_PN2, + TEGRA_PIN_DAP1_SCLK_PN3, +}; + +static const unsigned drive_dap2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, + TEGRA_PIN_DAP2_SCLK_PA3, + TEGRA_PIN_DAP2_DIN_PA4, + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned drive_dap3_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, + TEGRA_PIN_DAP3_DIN_PP1, + TEGRA_PIN_DAP3_DOUT_PP2, + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned drive_dap4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, + TEGRA_PIN_DAP4_DIN_PP5, + TEGRA_PIN_DAP4_DOUT_PP6, + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned drive_dbg_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PC4, + TEGRA_PIN_GEN1_I2C_SDA_PC5, + TEGRA_PIN_PU0, + TEGRA_PIN_PU1, + TEGRA_PIN_PU2, + TEGRA_PIN_PU3, + TEGRA_PIN_PU4, + TEGRA_PIN_PU5, + TEGRA_PIN_PU6, +}; + +static const unsigned drive_sdio3_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PA6, + TEGRA_PIN_SDMMC3_CMD_PA7, + TEGRA_PIN_SDMMC3_DAT3_PB4, + TEGRA_PIN_SDMMC3_DAT2_PB5, + TEGRA_PIN_SDMMC3_DAT1_PB6, + TEGRA_PIN_SDMMC3_DAT0_PB7, + TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, + TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, +}; + +static const unsigned drive_spi_pins[] = { + TEGRA_PIN_DVFS_PWM_PX0, + TEGRA_PIN_GPIO_X1_AUD_PX1, + TEGRA_PIN_DVFS_CLK_PX2, + TEGRA_PIN_GPIO_X3_AUD_PX3, + TEGRA_PIN_GPIO_X4_AUD_PX4, + TEGRA_PIN_GPIO_X5_AUD_PX5, + TEGRA_PIN_GPIO_X6_AUD_PX6, + TEGRA_PIN_GPIO_X7_AUD_PX7, + TEGRA_PIN_GPIO_W2_AUD_PW2, + TEGRA_PIN_GPIO_W3_AUD_PW3, +}; + +static const unsigned drive_uaa_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, + TEGRA_PIN_ULPI_DATA1_PO2, + TEGRA_PIN_ULPI_DATA2_PO3, + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned drive_uab_pins[] = { + TEGRA_PIN_ULPI_DATA7_PO0, + TEGRA_PIN_ULPI_DATA4_PO5, + TEGRA_PIN_ULPI_DATA5_PO6, + TEGRA_PIN_ULPI_DATA6_PO7, + TEGRA_PIN_PV0, + TEGRA_PIN_PV1, +}; + +static const unsigned drive_uart2_pins[] = { + TEGRA_PIN_UART2_TXD_PC2, + TEGRA_PIN_UART2_RXD_PC3, + TEGRA_PIN_UART2_CTS_N_PJ5, + TEGRA_PIN_UART2_RTS_N_PJ6, +}; + +static const unsigned drive_uart3_pins[] = { + TEGRA_PIN_UART3_CTS_N_PA1, + TEGRA_PIN_UART3_RTS_N_PC0, + TEGRA_PIN_UART3_TXD_PW6, + TEGRA_PIN_UART3_RXD_PW7, +}; + +static const unsigned drive_sdio1_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PY4, + TEGRA_PIN_SDMMC1_DAT2_PY5, + TEGRA_PIN_SDMMC1_DAT1_PY6, + TEGRA_PIN_SDMMC1_DAT0_PY7, + TEGRA_PIN_SDMMC1_CLK_PZ0, + TEGRA_PIN_SDMMC1_CMD_PZ1, +}; + +static const unsigned drive_ddc_pins[] = { + TEGRA_PIN_DDC_SCL_PV4, + TEGRA_PIN_DDC_SDA_PV5, +}; + +static const unsigned drive_gma_pins[] = { + TEGRA_PIN_SDMMC4_CLK_PCC4, + TEGRA_PIN_SDMMC4_CMD_PT7, + TEGRA_PIN_SDMMC4_DAT0_PAA0, + TEGRA_PIN_SDMMC4_DAT1_PAA1, + TEGRA_PIN_SDMMC4_DAT2_PAA2, + TEGRA_PIN_SDMMC4_DAT3_PAA3, + TEGRA_PIN_SDMMC4_DAT4_PAA4, + TEGRA_PIN_SDMMC4_DAT5_PAA5, + TEGRA_PIN_SDMMC4_DAT6_PAA6, + TEGRA_PIN_SDMMC4_DAT7_PAA7, +}; + +static const unsigned drive_gme_pins[] = { + TEGRA_PIN_PBB0, + TEGRA_PIN_CAM_I2C_SCL_PBB1, + TEGRA_PIN_CAM_I2C_SDA_PBB2, + TEGRA_PIN_PBB3, + TEGRA_PIN_PCC2, +}; + +static const unsigned drive_gmf_pins[] = { + TEGRA_PIN_PBB4, + TEGRA_PIN_PBB5, + TEGRA_PIN_PBB6, + TEGRA_PIN_PBB7, +}; + +static const unsigned drive_gmg_pins[] = { + TEGRA_PIN_CAM_MCLK_PCC0, +}; + +static const unsigned drive_gmh_pins[] = { + TEGRA_PIN_PCC1, +}; + +static const unsigned drive_owr_pins[] = { + TEGRA_PIN_SDMMC3_CD_N_PV2, + TEGRA_PIN_OWR, +}; + +static const unsigned drive_uda_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, + TEGRA_PIN_ULPI_DIR_PY1, + TEGRA_PIN_ULPI_NXT_PY2, + TEGRA_PIN_ULPI_STP_PY3, +}; + +static const unsigned drive_gpv_pins[] = { + TEGRA_PIN_PEX_L0_RST_N_PDD1, + TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, + TEGRA_PIN_PEX_WAKE_N_PDD3, + TEGRA_PIN_PEX_L1_RST_N_PDD5, + TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, + TEGRA_PIN_USB_VBUS_EN2_PFF1, + TEGRA_PIN_PFF2, +}; + +static const unsigned drive_dev3_pins[] = { + TEGRA_PIN_CLK3_OUT_PEE0, + TEGRA_PIN_CLK3_REQ_PEE1, +}; + +static const unsigned drive_cec_pins[] = { + TEGRA_PIN_HDMI_CEC_PEE3, +}; + +static const unsigned drive_at6_pins[] = { + TEGRA_PIN_PK1, + TEGRA_PIN_PK3, + TEGRA_PIN_PK4, + TEGRA_PIN_PI2, + TEGRA_PIN_PI5, + TEGRA_PIN_PI6, + TEGRA_PIN_PH4, + TEGRA_PIN_PH5, + TEGRA_PIN_PH6, + TEGRA_PIN_PH7, +}; + +static const unsigned drive_dap5_pins[] = { + TEGRA_PIN_SPDIF_IN_PK6, + TEGRA_PIN_SPDIF_OUT_PK5, + TEGRA_PIN_DP_HPD_PFF0, +}; + +static const unsigned drive_usb_vbus_en_pins[] = { + TEGRA_PIN_USB_VBUS_EN0_PN4, + TEGRA_PIN_USB_VBUS_EN1_PN5, +}; + +static const unsigned drive_ao3_pins[] = { + TEGRA_PIN_RESET_OUT_N, +}; + +static const unsigned drive_ao0_pins[] = { + TEGRA_PIN_JTAG_RTCK, +}; + +static const unsigned drive_hv0_pins[] = { + TEGRA_PIN_HDMI_INT_PN7, +}; + +static const unsigned drive_sdio4_pins[] = { + TEGRA_PIN_SDMMC1_WP_N_PV3, +}; + +static const unsigned drive_ao4_pins[] = { + TEGRA_PIN_JTAG_RTCK, +}; + +static const unsigned mipi_pad_ctrl_dsi_b_pins[] = { + TEGRA_PIN_DSI_B_CLK_P, + TEGRA_PIN_DSI_B_CLK_N, + TEGRA_PIN_DSI_B_D0_P, + TEGRA_PIN_DSI_B_D0_N, + TEGRA_PIN_DSI_B_D1_P, + TEGRA_PIN_DSI_B_D1_N, + TEGRA_PIN_DSI_B_D2_P, + TEGRA_PIN_DSI_B_D2_N, + TEGRA_PIN_DSI_B_D3_P, + TEGRA_PIN_DSI_B_D3_N, +}; + +enum tegra_mux { + TEGRA_MUX_BLINK, + TEGRA_MUX_CCLA, + TEGRA_MUX_CEC, + TEGRA_MUX_CLDVFS, + TEGRA_MUX_CLK, + TEGRA_MUX_CLK12, + TEGRA_MUX_CPU, + TEGRA_MUX_CSI, + TEGRA_MUX_DAP, + TEGRA_MUX_DAP1, + TEGRA_MUX_DAP2, + TEGRA_MUX_DEV3, + TEGRA_MUX_DISPLAYA, + TEGRA_MUX_DISPLAYA_ALT, + TEGRA_MUX_DISPLAYB, + TEGRA_MUX_DP, + TEGRA_MUX_DSI_B, + TEGRA_MUX_DTV, + TEGRA_MUX_EXTPERIPH1, + TEGRA_MUX_EXTPERIPH2, + TEGRA_MUX_EXTPERIPH3, + TEGRA_MUX_GMI, + TEGRA_MUX_GMI_ALT, + TEGRA_MUX_HDA, + TEGRA_MUX_HSI, + TEGRA_MUX_I2C1, + TEGRA_MUX_I2C2, + TEGRA_MUX_I2C3, + TEGRA_MUX_I2C4, + TEGRA_MUX_I2CPWR, + TEGRA_MUX_I2S0, + TEGRA_MUX_I2S1, + TEGRA_MUX_I2S2, + TEGRA_MUX_I2S3, + TEGRA_MUX_I2S4, + TEGRA_MUX_IRDA, + TEGRA_MUX_KBC, + TEGRA_MUX_OWR, + TEGRA_MUX_PE, + TEGRA_MUX_PE0, + TEGRA_MUX_PE1, + TEGRA_MUX_PMI, + TEGRA_MUX_PWM0, + TEGRA_MUX_PWM1, + TEGRA_MUX_PWM2, + TEGRA_MUX_PWM3, + TEGRA_MUX_PWRON, + TEGRA_MUX_RESET_OUT_N, + TEGRA_MUX_RSVD1, + TEGRA_MUX_RSVD2, + TEGRA_MUX_RSVD3, + TEGRA_MUX_RSVD4, + TEGRA_MUX_RTCK, + TEGRA_MUX_SATA, + TEGRA_MUX_SDMMC1, + TEGRA_MUX_SDMMC2, + TEGRA_MUX_SDMMC3, + TEGRA_MUX_SDMMC4, + TEGRA_MUX_SOC, + TEGRA_MUX_SPDIF, + TEGRA_MUX_SPI1, + TEGRA_MUX_SPI2, + TEGRA_MUX_SPI3, + TEGRA_MUX_SPI4, + TEGRA_MUX_SPI5, + TEGRA_MUX_SPI6, + TEGRA_MUX_SYS, + TEGRA_MUX_TMDS, + TEGRA_MUX_TRACE, + TEGRA_MUX_UARTA, + TEGRA_MUX_UARTB, + TEGRA_MUX_UARTC, + TEGRA_MUX_UARTD, + TEGRA_MUX_ULPI, + TEGRA_MUX_USB, + TEGRA_MUX_VGP1, + TEGRA_MUX_VGP2, + TEGRA_MUX_VGP3, + TEGRA_MUX_VGP4, + TEGRA_MUX_VGP5, + TEGRA_MUX_VGP6, + TEGRA_MUX_VI, + TEGRA_MUX_VI_ALT1, + TEGRA_MUX_VI_ALT3, + TEGRA_MUX_VIMCLK2, + TEGRA_MUX_VIMCLK2_ALT, +}; + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + } + +static struct tegra_function tegra124_functions[] = { + FUNCTION(blink), + FUNCTION(ccla), + FUNCTION(cec), + FUNCTION(cldvfs), + FUNCTION(clk), + FUNCTION(clk12), + FUNCTION(cpu), + FUNCTION(csi), + FUNCTION(dap), + FUNCTION(dap1), + FUNCTION(dap2), + FUNCTION(dev3), + FUNCTION(displaya), + FUNCTION(displaya_alt), + FUNCTION(displayb), + FUNCTION(dp), + FUNCTION(dsi_b), + FUNCTION(dtv), + FUNCTION(extperiph1), + FUNCTION(extperiph2), + FUNCTION(extperiph3), + FUNCTION(gmi), + FUNCTION(gmi_alt), + FUNCTION(hda), + FUNCTION(hsi), + FUNCTION(i2c1), + FUNCTION(i2c2), + FUNCTION(i2c3), + FUNCTION(i2c4), + FUNCTION(i2cpwr), + FUNCTION(i2s0), + FUNCTION(i2s1), + FUNCTION(i2s2), + FUNCTION(i2s3), + FUNCTION(i2s4), + FUNCTION(irda), + FUNCTION(kbc), + FUNCTION(owr), + FUNCTION(pe), + FUNCTION(pe0), + FUNCTION(pe1), + FUNCTION(pmi), + FUNCTION(pwm0), + FUNCTION(pwm1), + FUNCTION(pwm2), + FUNCTION(pwm3), + FUNCTION(pwron), + FUNCTION(reset_out_n), + FUNCTION(rsvd1), + FUNCTION(rsvd2), + FUNCTION(rsvd3), + FUNCTION(rsvd4), + FUNCTION(rtck), + FUNCTION(sata), + FUNCTION(sdmmc1), + FUNCTION(sdmmc2), + FUNCTION(sdmmc3), + FUNCTION(sdmmc4), + FUNCTION(soc), + FUNCTION(spdif), + FUNCTION(spi1), + FUNCTION(spi2), + FUNCTION(spi3), + FUNCTION(spi4), + FUNCTION(spi5), + FUNCTION(spi6), + FUNCTION(sys), + FUNCTION(tmds), + FUNCTION(trace), + FUNCTION(uarta), + FUNCTION(uartb), + FUNCTION(uartc), + FUNCTION(uartd), + FUNCTION(ulpi), + FUNCTION(usb), + FUNCTION(vgp1), + FUNCTION(vgp2), + FUNCTION(vgp3), + FUNCTION(vgp4), + FUNCTION(vgp5), + FUNCTION(vgp6), + FUNCTION(vi), + FUNCTION(vi_alt1), + FUNCTION(vi_alt3), + FUNCTION(vimclk2), + FUNCTION(vimclk2_alt), +}; + +#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ +#define PINGROUP_REG_A 0x3000 /* bank 1 */ +#define MIPI_PAD_CTRL_PINGROUP_REG_A 0x820 /* bank 2 */ + +#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A) +#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) +#define MIPI_PAD_CTRL_PINGROUP_REG_Y(r) ((r) - MIPI_PAD_CTRL_PINGROUP_REG_A) + +#define PINGROUP_BIT_Y(b) (b) +#define PINGROUP_BIT_N(b) (-1) + +#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_##f0, \ + TEGRA_MUX_##f1, \ + TEGRA_MUX_##f2, \ + TEGRA_MUX_##f3, \ + }, \ + .mux_reg = PINGROUP_REG(r), \ + .mux_bank = 1, \ + .mux_bit = 0, \ + .pupd_reg = PINGROUP_REG(r), \ + .pupd_bank = 1, \ + .pupd_bit = 2, \ + .tri_reg = PINGROUP_REG(r), \ + .tri_bank = 1, \ + .tri_bit = 4, \ + .einput_bit = 5, \ + .odrain_bit = PINGROUP_BIT_##od(6), \ + .lock_bit = 7, \ + .ioreset_bit = PINGROUP_BIT_##ior(8), \ + .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9), \ + .drv_reg = -1, \ + } + +#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, \ + drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, \ + slwf_b, slwf_w, drvtype) \ + { \ + .name = "drive_" #pg_name, \ + .pins = drive_##pg_name##_pins, \ + .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ + .mux_reg = -1, \ + .pupd_reg = -1, \ + .tri_reg = -1, \ + .einput_bit = -1, \ + .odrain_bit = -1, \ + .lock_bit = -1, \ + .ioreset_bit = -1, \ + .rcv_sel_bit = -1, \ + .drv_reg = DRV_PINGROUP_REG(r), \ + .drv_bank = 0, \ + .hsm_bit = hsm_b, \ + .schmitt_bit = schmitt_b, \ + .lpmd_bit = lpmd_b, \ + .drvdn_bit = drvdn_b, \ + .drvdn_width = drvdn_w, \ + .drvup_bit = drvup_b, \ + .drvup_width = drvup_w, \ + .slwr_bit = slwr_b, \ + .slwr_width = slwr_w, \ + .slwf_bit = slwf_b, \ + .slwf_width = slwf_w, \ + .drvtype_bit = PINGROUP_BIT_##drvtype(6), \ + } + +#define MIPI_PAD_CTRL_PINGROUP(pg_name, r, b, f0, f1) \ + { \ + .name = "mipi_pad_ctrl_" #pg_name, \ + .pins = mipi_pad_ctrl_##pg_name##_pins, \ + .npins = ARRAY_SIZE(mipi_pad_ctrl_##pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_ ## f0, \ + TEGRA_MUX_ ## f1, \ + TEGRA_MUX_RSVD3, \ + TEGRA_MUX_RSVD4, \ + }, \ + .mux_reg = MIPI_PAD_CTRL_PINGROUP_REG_Y(r), \ + .mux_bank = 2, \ + .mux_bit = b, \ + .pupd_reg = -1, \ + .tri_reg = -1, \ + .einput_bit = -1, \ + .odrain_bit = -1, \ + .lock_bit = -1, \ + .ioreset_bit = -1, \ + .rcv_sel_bit = -1, \ + .drv_reg = -1, \ + } + +static const struct tegra_pingroup tegra124_groups[] = { + /* pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel */ + PINGROUP(ulpi_data0_po1, SPI3, HSI, UARTA, ULPI, 0x3000, N, N, N), + PINGROUP(ulpi_data1_po2, SPI3, HSI, UARTA, ULPI, 0x3004, N, N, N), + PINGROUP(ulpi_data2_po3, SPI3, HSI, UARTA, ULPI, 0x3008, N, N, N), + PINGROUP(ulpi_data3_po4, SPI3, HSI, UARTA, ULPI, 0x300c, N, N, N), + PINGROUP(ulpi_data4_po5, SPI2, HSI, UARTA, ULPI, 0x3010, N, N, N), + PINGROUP(ulpi_data5_po6, SPI2, HSI, UARTA, ULPI, 0x3014, N, N, N), + PINGROUP(ulpi_data6_po7, SPI2, HSI, UARTA, ULPI, 0x3018, N, N, N), + PINGROUP(ulpi_data7_po0, SPI2, HSI, UARTA, ULPI, 0x301c, N, N, N), + PINGROUP(ulpi_clk_py0, SPI1, SPI5, UARTD, ULPI, 0x3020, N, N, N), + PINGROUP(ulpi_dir_py1, SPI1, SPI5, UARTD, ULPI, 0x3024, N, N, N), + PINGROUP(ulpi_nxt_py2, SPI1, SPI5, UARTD, ULPI, 0x3028, N, N, N), + PINGROUP(ulpi_stp_py3, SPI1, SPI5, UARTD, ULPI, 0x302c, N, N, N), + PINGROUP(dap3_fs_pp0, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3030, N, N, N), + PINGROUP(dap3_din_pp1, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3034, N, N, N), + PINGROUP(dap3_dout_pp2, I2S2, SPI5, DISPLAYA, RSVD4, 0x3038, N, N, N), + PINGROUP(dap3_sclk_pp3, I2S2, SPI5, RSVD3, DISPLAYB, 0x303c, N, N, N), + PINGROUP(pv0, RSVD1, RSVD2, RSVD3, RSVD4, 0x3040, N, N, N), + PINGROUP(pv1, RSVD1, RSVD2, RSVD3, RSVD4, 0x3044, N, N, N), + PINGROUP(sdmmc1_clk_pz0, SDMMC1, CLK12, RSVD3, RSVD4, 0x3048, N, N, N), + PINGROUP(sdmmc1_cmd_pz1, SDMMC1, SPDIF, SPI4, UARTA, 0x304c, N, N, N), + PINGROUP(sdmmc1_dat3_py4, SDMMC1, SPDIF, SPI4, UARTA, 0x3050, N, N, N), + PINGROUP(sdmmc1_dat2_py5, SDMMC1, PWM0, SPI4, UARTA, 0x3054, N, N, N), + PINGROUP(sdmmc1_dat1_py6, SDMMC1, PWM1, SPI4, UARTA, 0x3058, N, N, N), + PINGROUP(sdmmc1_dat0_py7, SDMMC1, RSVD2, SPI4, UARTA, 0x305c, N, N, N), + PINGROUP(clk2_out_pw5, EXTPERIPH2, RSVD2, RSVD3, RSVD4, 0x3068, N, N, N), + PINGROUP(clk2_req_pcc5, DAP, RSVD2, RSVD3, RSVD4, 0x306c, N, N, N), + PINGROUP(hdmi_int_pn7, RSVD1, RSVD2, RSVD3, RSVD4, 0x3110, N, N, Y), + PINGROUP(ddc_scl_pv4, I2C4, RSVD2, RSVD3, RSVD4, 0x3114, N, N, Y), + PINGROUP(ddc_sda_pv5, I2C4, RSVD2, RSVD3, RSVD4, 0x3118, N, N, Y), + PINGROUP(uart2_rxd_pc3, IRDA, SPDIF, UARTA, SPI4, 0x3164, N, N, N), + PINGROUP(uart2_txd_pc2, IRDA, SPDIF, UARTA, SPI4, 0x3168, N, N, N), + PINGROUP(uart2_rts_n_pj6, UARTA, UARTB, GMI, SPI4, 0x316c, N, N, N), + PINGROUP(uart2_cts_n_pj5, UARTA, UARTB, GMI, SPI4, 0x3170, N, N, N), + PINGROUP(uart3_txd_pw6, UARTC, RSVD2, GMI, SPI4, 0x3174, N, N, N), + PINGROUP(uart3_rxd_pw7, UARTC, RSVD2, GMI, SPI4, 0x3178, N, N, N), + PINGROUP(uart3_cts_n_pa1, UARTC, SDMMC1, DTV, GMI, 0x317c, N, N, N), + PINGROUP(uart3_rts_n_pc0, UARTC, PWM0, DTV, GMI, 0x3180, N, N, N), + PINGROUP(pu0, OWR, UARTA, GMI, RSVD4, 0x3184, N, N, N), + PINGROUP(pu1, RSVD1, UARTA, GMI, RSVD4, 0x3188, N, N, N), + PINGROUP(pu2, RSVD1, UARTA, GMI, RSVD4, 0x318c, N, N, N), + PINGROUP(pu3, PWM0, UARTA, GMI, DISPLAYB, 0x3190, N, N, N), + PINGROUP(pu4, PWM1, UARTA, GMI, DISPLAYB, 0x3194, N, N, N), + PINGROUP(pu5, PWM2, UARTA, GMI, DISPLAYB, 0x3198, N, N, N), + PINGROUP(pu6, PWM3, UARTA, RSVD3, GMI, 0x319c, N, N, N), + PINGROUP(gen1_i2c_sda_pc5, I2C1, RSVD2, RSVD3, RSVD4, 0x31a0, Y, N, N), + PINGROUP(gen1_i2c_scl_pc4, I2C1, RSVD2, RSVD3, RSVD4, 0x31a4, Y, N, N), + PINGROUP(dap4_fs_pp4, I2S3, GMI, DTV, RSVD4, 0x31a8, N, N, N), + PINGROUP(dap4_din_pp5, I2S3, GMI, RSVD3, RSVD4, 0x31ac, N, N, N), + PINGROUP(dap4_dout_pp6, I2S3, GMI, DTV, RSVD4, 0x31b0, N, N, N), + PINGROUP(dap4_sclk_pp7, I2S3, GMI, RSVD3, RSVD4, 0x31b4, N, N, N), + PINGROUP(clk3_out_pee0, EXTPERIPH3, RSVD2, RSVD3, RSVD4, 0x31b8, N, N, N), + PINGROUP(clk3_req_pee1, DEV3, RSVD2, RSVD3, RSVD4, 0x31bc, N, N, N), + PINGROUP(pc7, RSVD1, RSVD2, GMI, GMI_ALT, 0x31c0, N, N, N), + PINGROUP(pi5, SDMMC2, RSVD2, GMI, RSVD4, 0x31c4, N, N, N), + PINGROUP(pi7, RSVD1, TRACE, GMI, DTV, 0x31c8, N, N, N), + PINGROUP(pk0, RSVD1, SDMMC3, GMI, SOC, 0x31cc, N, N, N), + PINGROUP(pk1, SDMMC2, TRACE, GMI, RSVD4, 0x31d0, N, N, N), + PINGROUP(pj0, RSVD1, RSVD2, GMI, USB, 0x31d4, N, N, N), + PINGROUP(pj2, RSVD1, RSVD2, GMI, SOC, 0x31d8, N, N, N), + PINGROUP(pk3, SDMMC2, TRACE, GMI, CCLA, 0x31dc, N, N, N), + PINGROUP(pk4, SDMMC2, RSVD2, GMI, GMI_ALT, 0x31e0, N, N, N), + PINGROUP(pk2, RSVD1, RSVD2, GMI, RSVD4, 0x31e4, N, N, N), + PINGROUP(pi3, RSVD1, RSVD2, GMI, SPI4, 0x31e8, N, N, N), + PINGROUP(pi6, RSVD1, RSVD2, GMI, SDMMC2, 0x31ec, N, N, N), + PINGROUP(pg0, RSVD1, RSVD2, GMI, RSVD4, 0x31f0, N, N, N), + PINGROUP(pg1, RSVD1, RSVD2, GMI, RSVD4, 0x31f4, N, N, N), + PINGROUP(pg2, RSVD1, TRACE, GMI, RSVD4, 0x31f8, N, N, N), + PINGROUP(pg3, RSVD1, TRACE, GMI, RSVD4, 0x31fc, N, N, N), + PINGROUP(pg4, RSVD1, TMDS, GMI, SPI4, 0x3200, N, N, N), + PINGROUP(pg5, RSVD1, RSVD2, GMI, SPI4, 0x3204, N, N, N), + PINGROUP(pg6, RSVD1, RSVD2, GMI, SPI4, 0x3208, N, N, N), + PINGROUP(pg7, RSVD1, RSVD2, GMI, SPI4, 0x320c, N, N, N), + PINGROUP(ph0, PWM0, TRACE, GMI, DTV, 0x3210, N, N, N), + PINGROUP(ph1, PWM1, TMDS, GMI, DISPLAYA, 0x3214, N, N, N), + PINGROUP(ph2, PWM2, TMDS, GMI, CLDVFS, 0x3218, N, N, N), + PINGROUP(ph3, PWM3, SPI4, GMI, CLDVFS, 0x321c, N, N, N), + PINGROUP(ph4, SDMMC2, RSVD2, GMI, RSVD4, 0x3220, N, N, N), + PINGROUP(ph5, SDMMC2, RSVD2, GMI, RSVD4, 0x3224, N, N, N), + PINGROUP(ph6, SDMMC2, TRACE, GMI, DTV, 0x3228, N, N, N), + PINGROUP(ph7, SDMMC2, TRACE, GMI, DTV, 0x322c, N, N, N), + PINGROUP(pj7, UARTD, RSVD2, GMI, GMI_ALT, 0x3230, N, N, N), + PINGROUP(pb0, UARTD, RSVD2, GMI, RSVD4, 0x3234, N, N, N), + PINGROUP(pb1, UARTD, RSVD2, GMI, RSVD4, 0x3238, N, N, N), + PINGROUP(pk7, UARTD, RSVD2, GMI, RSVD4, 0x323c, N, N, N), + PINGROUP(pi0, RSVD1, RSVD2, GMI, RSVD4, 0x3240, N, N, N), + PINGROUP(pi1, RSVD1, RSVD2, GMI, RSVD4, 0x3244, N, N, N), + PINGROUP(pi2, SDMMC2, TRACE, GMI, RSVD4, 0x3248, N, N, N), + PINGROUP(pi4, SPI4, TRACE, GMI, DISPLAYA, 0x324c, N, N, N), + PINGROUP(gen2_i2c_scl_pt5, I2C2, RSVD2, GMI, RSVD4, 0x3250, Y, N, N), + PINGROUP(gen2_i2c_sda_pt6, I2C2, RSVD2, GMI, RSVD4, 0x3254, Y, N, N), + PINGROUP(sdmmc4_clk_pcc4, SDMMC4, RSVD2, GMI, RSVD4, 0x3258, N, Y, N), + PINGROUP(sdmmc4_cmd_pt7, SDMMC4, RSVD2, GMI, RSVD4, 0x325c, N, Y, N), + PINGROUP(sdmmc4_dat0_paa0, SDMMC4, SPI3, GMI, RSVD4, 0x3260, N, Y, N), + PINGROUP(sdmmc4_dat1_paa1, SDMMC4, SPI3, GMI, RSVD4, 0x3264, N, Y, N), + PINGROUP(sdmmc4_dat2_paa2, SDMMC4, SPI3, GMI, RSVD4, 0x3268, N, Y, N), + PINGROUP(sdmmc4_dat3_paa3, SDMMC4, SPI3, GMI, RSVD4, 0x326c, N, Y, N), + PINGROUP(sdmmc4_dat4_paa4, SDMMC4, SPI3, GMI, RSVD4, 0x3270, N, Y, N), + PINGROUP(sdmmc4_dat5_paa5, SDMMC4, SPI3, RSVD3, RSVD4, 0x3274, N, Y, N), + PINGROUP(sdmmc4_dat6_paa6, SDMMC4, SPI3, GMI, RSVD4, 0x3278, N, Y, N), + PINGROUP(sdmmc4_dat7_paa7, SDMMC4, RSVD2, GMI, RSVD4, 0x327c, N, Y, N), + PINGROUP(cam_mclk_pcc0, VI, VI_ALT1, VI_ALT3, SDMMC2, 0x3284, N, N, N), + PINGROUP(pcc1, I2S4, RSVD2, RSVD3, SDMMC2, 0x3288, N, N, N), + PINGROUP(pbb0, VGP6, VIMCLK2, SDMMC2, VIMCLK2_ALT, 0x328c, N, N, N), + PINGROUP(cam_i2c_scl_pbb1, VGP1, I2C3, RSVD3, SDMMC2, 0x3290, Y, N, N), + PINGROUP(cam_i2c_sda_pbb2, VGP2, I2C3, RSVD3, SDMMC2, 0x3294, Y, N, N), + PINGROUP(pbb3, VGP3, DISPLAYA, DISPLAYB, SDMMC2, 0x3298, N, N, N), + PINGROUP(pbb4, VGP4, DISPLAYA, DISPLAYB, SDMMC2, 0x329c, N, N, N), + PINGROUP(pbb5, VGP5, DISPLAYA, RSVD3, SDMMC2, 0x32a0, N, N, N), + PINGROUP(pbb6, I2S4, RSVD2, DISPLAYB, SDMMC2, 0x32a4, N, N, N), + PINGROUP(pbb7, I2S4, RSVD2, RSVD3, SDMMC2, 0x32a8, N, N, N), + PINGROUP(pcc2, I2S4, RSVD2, SDMMC3, SDMMC2, 0x32ac, N, N, N), + PINGROUP(jtag_rtck, RTCK, RSVD2, RSVD3, RSVD4, 0x32b0, N, N, N), + PINGROUP(pwr_i2c_scl_pz6, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b4, Y, N, N), + PINGROUP(pwr_i2c_sda_pz7, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b8, Y, N, N), + PINGROUP(kb_row0_pr0, KBC, RSVD2, RSVD3, RSVD4, 0x32bc, N, N, N), + PINGROUP(kb_row1_pr1, KBC, RSVD2, RSVD3, RSVD4, 0x32c0, N, N, N), + PINGROUP(kb_row2_pr2, KBC, RSVD2, RSVD3, RSVD4, 0x32c4, N, N, N), + PINGROUP(kb_row3_pr3, KBC, DISPLAYA, SYS, DISPLAYB, 0x32c8, N, N, N), + PINGROUP(kb_row4_pr4, KBC, DISPLAYA, RSVD3, DISPLAYB, 0x32cc, N, N, N), + PINGROUP(kb_row5_pr5, KBC, DISPLAYA, RSVD3, DISPLAYB, 0x32d0, N, N, N), + PINGROUP(kb_row6_pr6, KBC, DISPLAYA, DISPLAYA_ALT, DISPLAYB, 0x32d4, N, N, N), + PINGROUP(kb_row7_pr7, KBC, RSVD2, CLDVFS, UARTA, 0x32d8, N, N, N), + PINGROUP(kb_row8_ps0, KBC, RSVD2, CLDVFS, UARTA, 0x32dc, N, N, N), + PINGROUP(kb_row9_ps1, KBC, RSVD2, RSVD3, UARTA, 0x32e0, N, N, N), + PINGROUP(kb_row10_ps2, KBC, RSVD2, RSVD3, UARTA, 0x32e4, N, N, N), + PINGROUP(kb_row11_ps3, KBC, RSVD2, RSVD3, IRDA, 0x32e8, N, N, N), + PINGROUP(kb_row12_ps4, KBC, RSVD2, RSVD3, IRDA, 0x32ec, N, N, N), + PINGROUP(kb_row13_ps5, KBC, RSVD2, SPI2, RSVD4, 0x32f0, N, N, N), + PINGROUP(kb_row14_ps6, KBC, RSVD2, SPI2, RSVD4, 0x32f4, N, N, N), + PINGROUP(kb_row15_ps7, KBC, SOC, RSVD3, RSVD4, 0x32f8, N, N, N), + PINGROUP(kb_col0_pq0, KBC, RSVD2, SPI2, RSVD4, 0x32fc, N, N, N), + PINGROUP(kb_col1_pq1, KBC, RSVD2, SPI2, RSVD4, 0x3300, N, N, N), + PINGROUP(kb_col2_pq2, KBC, RSVD2, SPI2, RSVD4, 0x3304, N, N, N), + PINGROUP(kb_col3_pq3, KBC, DISPLAYA, PWM2, UARTA, 0x3308, N, N, N), + PINGROUP(kb_col4_pq4, KBC, OWR, SDMMC3, UARTA, 0x330c, N, N, N), + PINGROUP(kb_col5_pq5, KBC, RSVD2, SDMMC3, RSVD4, 0x3310, N, N, N), + PINGROUP(kb_col6_pq6, KBC, RSVD2, SPI2, UARTD, 0x3314, N, N, N), + PINGROUP(kb_col7_pq7, KBC, RSVD2, SPI2, UARTD, 0x3318, N, N, N), + PINGROUP(clk_32k_out_pa0, BLINK, SOC, RSVD3, RSVD4, 0x331c, N, N, N), + PINGROUP(core_pwr_req, PWRON, RSVD2, RSVD3, RSVD4, 0x3324, N, N, N), + PINGROUP(cpu_pwr_req, CPU, RSVD2, RSVD3, RSVD4, 0x3328, N, N, N), + PINGROUP(pwr_int_n, PMI, RSVD2, RSVD3, RSVD4, 0x332c, N, N, N), + PINGROUP(clk_32k_in, CLK, RSVD2, RSVD3, RSVD4, 0x3330, N, N, N), + PINGROUP(owr, OWR, RSVD2, RSVD3, RSVD4, 0x3334, N, N, Y), + PINGROUP(dap1_fs_pn0, I2S0, HDA, GMI, RSVD4, 0x3338, N, N, N), + PINGROUP(dap1_din_pn1, I2S0, HDA, GMI, RSVD4, 0x333c, N, N, N), + PINGROUP(dap1_dout_pn2, I2S0, HDA, GMI, SATA, 0x3340, N, N, N), + PINGROUP(dap1_sclk_pn3, I2S0, HDA, GMI, RSVD4, 0x3344, N, N, N), + PINGROUP(dap_mclk1_req_pee2, DAP, DAP1, SATA, RSVD4, 0x3348, N, N, N), + PINGROUP(dap_mclk1_pw4, EXTPERIPH1, DAP2, RSVD3, RSVD4, 0x334c, N, N, N), + PINGROUP(spdif_in_pk6, SPDIF, RSVD2, RSVD3, I2C3, 0x3350, N, N, N), + PINGROUP(spdif_out_pk5, SPDIF, RSVD2, RSVD3, I2C3, 0x3354, N, N, N), + PINGROUP(dap2_fs_pa2, I2S1, HDA, GMI, RSVD4, 0x3358, N, N, N), + PINGROUP(dap2_din_pa4, I2S1, HDA, GMI, RSVD4, 0x335c, N, N, N), + PINGROUP(dap2_dout_pa5, I2S1, HDA, GMI, RSVD4, 0x3360, N, N, N), + PINGROUP(dap2_sclk_pa3, I2S1, HDA, GMI, RSVD4, 0x3364, N, N, N), + PINGROUP(dvfs_pwm_px0, SPI6, CLDVFS, GMI, RSVD4, 0x3368, N, N, N), + PINGROUP(gpio_x1_aud_px1, SPI6, RSVD2, GMI, RSVD4, 0x336c, N, N, N), + PINGROUP(gpio_x3_aud_px3, SPI6, SPI1, GMI, RSVD4, 0x3370, N, N, N), + PINGROUP(dvfs_clk_px2, SPI6, CLDVFS, GMI, RSVD4, 0x3374, N, N, N), + PINGROUP(gpio_x4_aud_px4, GMI, SPI1, SPI2, DAP2, 0x3378, N, N, N), + PINGROUP(gpio_x5_aud_px5, GMI, SPI1, SPI2, RSVD4, 0x337c, N, N, N), + PINGROUP(gpio_x6_aud_px6, SPI6, SPI1, SPI2, GMI, 0x3380, N, N, N), + PINGROUP(gpio_x7_aud_px7, RSVD1, SPI1, SPI2, RSVD4, 0x3384, N, N, N), + PINGROUP(sdmmc3_clk_pa6, SDMMC3, RSVD2, RSVD3, SPI3, 0x3390, N, N, N), + PINGROUP(sdmmc3_cmd_pa7, SDMMC3, PWM3, UARTA, SPI3, 0x3394, N, N, N), + PINGROUP(sdmmc3_dat0_pb7, SDMMC3, RSVD2, RSVD3, SPI3, 0x3398, N, N, N), + PINGROUP(sdmmc3_dat1_pb6, SDMMC3, PWM2, UARTA, SPI3, 0x339c, N, N, N), + PINGROUP(sdmmc3_dat2_pb5, SDMMC3, PWM1, DISPLAYA, SPI3, 0x33a0, N, N, N), + PINGROUP(sdmmc3_dat3_pb4, SDMMC3, PWM0, DISPLAYB, SPI3, 0x33a4, N, N, N), + PINGROUP(pex_l0_rst_n_pdd1, PE0, RSVD2, RSVD3, RSVD4, 0x33bc, N, N, N), + PINGROUP(pex_l0_clkreq_n_pdd2, PE0, RSVD2, RSVD3, RSVD4, 0x33c0, N, N, N), + PINGROUP(pex_wake_n_pdd3, PE, RSVD2, RSVD3, RSVD4, 0x33c4, N, N, N), + PINGROUP(pex_l1_rst_n_pdd5, PE1, RSVD2, RSVD3, RSVD4, 0x33cc, N, N, N), + PINGROUP(pex_l1_clkreq_n_pdd6, PE1, RSVD2, RSVD3, RSVD4, 0x33d0, N, N, N), + PINGROUP(hdmi_cec_pee3, CEC, RSVD2, RSVD3, RSVD4, 0x33e0, Y, N, N), + PINGROUP(sdmmc1_wp_n_pv3, SDMMC1, CLK12, SPI4, UARTA, 0x33e4, N, N, N), + PINGROUP(sdmmc3_cd_n_pv2, SDMMC3, OWR, RSVD3, RSVD4, 0x33e8, N, N, N), + PINGROUP(gpio_w2_aud_pw2, SPI6, RSVD2, SPI2, I2C1, 0x33ec, N, N, N), + PINGROUP(gpio_w3_aud_pw3, SPI6, SPI1, SPI2, I2C1, 0x33f0, N, N, N), + PINGROUP(usb_vbus_en0_pn4, USB, RSVD2, RSVD3, RSVD4, 0x33f4, Y, N, N), + PINGROUP(usb_vbus_en1_pn5, USB, RSVD2, RSVD3, RSVD4, 0x33f8, Y, N, N), + PINGROUP(sdmmc3_clk_lb_in_pee5, SDMMC3, RSVD2, RSVD3, RSVD4, 0x33fc, N, N, N), + PINGROUP(sdmmc3_clk_lb_out_pee4, SDMMC3, RSVD2, RSVD3, RSVD4, 0x3400, N, N, N), + PINGROUP(gmi_clk_lb, SDMMC2, RSVD2, GMI, RSVD4, 0x3404, N, N, N), + PINGROUP(reset_out_n, RSVD1, RSVD2, RSVD3, RESET_OUT_N, 0x3408, N, N, N), + PINGROUP(kb_row16_pt0, KBC, RSVD2, RSVD3, UARTC, 0x340c, N, N, N), + PINGROUP(kb_row17_pt1, KBC, RSVD2, RSVD3, UARTC, 0x3410, N, N, N), + PINGROUP(usb_vbus_en2_pff1, USB, RSVD2, RSVD3, RSVD4, 0x3414, Y, N, N), + PINGROUP(pff2, SATA, RSVD2, RSVD3, RSVD4, 0x3418, Y, N, N), + PINGROUP(dp_hpd_pff0, DP, RSVD2, RSVD3, RSVD4, 0x3430, N, N, N), + + /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w, drvtype */ + DRV_PINGROUP(ao1, 0x868, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(ao2, 0x86c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(at1, 0x870, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at2, 0x874, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at3, 0x878, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at4, 0x87c, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at5, 0x880, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(cdev1, 0x884, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(cdev2, 0x888, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap1, 0x890, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap2, 0x894, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap3, 0x898, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap4, 0x89c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dbg, 0x8a0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(sdio3, 0x8b0, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), + DRV_PINGROUP(spi, 0x8b4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uaa, 0x8b8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uab, 0x8bc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uart2, 0x8c0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uart3, 0x8c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(sdio1, 0x8ec, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), + DRV_PINGROUP(ddc, 0x8fc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gma, 0x900, 2, 3, 4, 14, 5, 20, 5, 28, 2, 30, 2, Y), + DRV_PINGROUP(gme, 0x910, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gmf, 0x914, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gmg, 0x918, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gmh, 0x91c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(owr, 0x920, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uda, 0x924, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gpv, 0x928, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dev3, 0x92c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(cec, 0x938, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(at6, 0x994, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(dap5, 0x998, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(usb_vbus_en, 0x99c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(ao3, 0x9a8, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), + DRV_PINGROUP(ao0, 0x9b0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(hv0, 0x9b4, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), + DRV_PINGROUP(sdio4, 0x9c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(ao4, 0x9c8, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + + /* pg_name, r, b, f0, f1 */ + MIPI_PAD_CTRL_PINGROUP(dsi_b, 0x820, 1, CSI, DSI_B), +}; + +static const struct tegra_pinctrl_soc_data tegra124_pinctrl = { + .ngpios = NUM_GPIOS, + .pins = tegra124_pins, + .npins = ARRAY_SIZE(tegra124_pins), + .functions = tegra124_functions, + .nfunctions = ARRAY_SIZE(tegra124_functions), + .groups = tegra124_groups, + .ngroups = ARRAY_SIZE(tegra124_groups), + .hsm_in_mux = false, + .schmitt_in_mux = false, + .drvtype_in_mux = false, +}; + +static int tegra124_pinctrl_probe(struct platform_device *pdev) +{ + return tegra_pinctrl_probe(pdev, &tegra124_pinctrl); +} + +static const struct of_device_id tegra124_pinctrl_of_match[] = { + { .compatible = "nvidia,tegra124-pinmux", }, + { }, +}; +MODULE_DEVICE_TABLE(of, tegra124_pinctrl_of_match); + +static struct platform_driver tegra124_pinctrl_driver = { + .driver = { + .name = "tegra124-pinctrl", + .of_match_table = tegra124_pinctrl_of_match, + }, + .probe = tegra124_pinctrl_probe, + .remove = tegra_pinctrl_remove, +}; +module_platform_driver(tegra124_pinctrl_driver); + +MODULE_AUTHOR("Ashwini Ghuge "); +MODULE_DESCRIPTION("NVIDIA Tegra124 pinctrl driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra20.c b/drivers/pinctrl/tegra/pinctrl-tegra20.c new file mode 100644 index 000000000000..4833db4433d9 --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra20.c @@ -0,0 +1,2252 @@ +/* + * Pinctrl data for the NVIDIA Tegra20 pinmux + * + * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. + * + * Derived from code: + * Copyright (C) 2010 Google, Inc. + * Copyright (C) 2010 NVIDIA 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, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#include +#include +#include +#include +#include + +#include "pinctrl-tegra.h" + +/* + * Most pins affected by the pinmux can also be GPIOs. Define these first. + * These must match how the GPIO driver names/numbers its pins. + */ +#define _GPIO(offset) (offset) + +#define TEGRA_PIN_VI_GP6_PA0 _GPIO(0) +#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) +#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) +#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) +#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) +#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) +#define TEGRA_PIN_SDIO3_CLK_PA6 _GPIO(6) +#define TEGRA_PIN_SDIO3_CMD_PA7 _GPIO(7) +#define TEGRA_PIN_GMI_AD17_PB0 _GPIO(8) +#define TEGRA_PIN_GMI_AD18_PB1 _GPIO(9) +#define TEGRA_PIN_LCD_PWR0_PB2 _GPIO(10) +#define TEGRA_PIN_LCD_PCLK_PB3 _GPIO(11) +#define TEGRA_PIN_SDIO3_DAT3_PB4 _GPIO(12) +#define TEGRA_PIN_SDIO3_DAT2_PB5 _GPIO(13) +#define TEGRA_PIN_SDIO3_DAT1_PB6 _GPIO(14) +#define TEGRA_PIN_SDIO3_DAT0_PB7 _GPIO(15) +#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) +#define TEGRA_PIN_LCD_PWR1_PC1 _GPIO(17) +#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) +#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) +#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) +#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) +#define TEGRA_PIN_LCD_PWR2_PC6 _GPIO(22) +#define TEGRA_PIN_GMI_WP_N_PC7 _GPIO(23) +#define TEGRA_PIN_SDIO3_DAT5_PD0 _GPIO(24) +#define TEGRA_PIN_SDIO3_DAT4_PD1 _GPIO(25) +#define TEGRA_PIN_VI_GP5_PD2 _GPIO(26) +#define TEGRA_PIN_SDIO3_DAT6_PD3 _GPIO(27) +#define TEGRA_PIN_SDIO3_DAT7_PD4 _GPIO(28) +#define TEGRA_PIN_VI_D1_PD5 _GPIO(29) +#define TEGRA_PIN_VI_VSYNC_PD6 _GPIO(30) +#define TEGRA_PIN_VI_HSYNC_PD7 _GPIO(31) +#define TEGRA_PIN_LCD_D0_PE0 _GPIO(32) +#define TEGRA_PIN_LCD_D1_PE1 _GPIO(33) +#define TEGRA_PIN_LCD_D2_PE2 _GPIO(34) +#define TEGRA_PIN_LCD_D3_PE3 _GPIO(35) +#define TEGRA_PIN_LCD_D4_PE4 _GPIO(36) +#define TEGRA_PIN_LCD_D5_PE5 _GPIO(37) +#define TEGRA_PIN_LCD_D6_PE6 _GPIO(38) +#define TEGRA_PIN_LCD_D7_PE7 _GPIO(39) +#define TEGRA_PIN_LCD_D8_PF0 _GPIO(40) +#define TEGRA_PIN_LCD_D9_PF1 _GPIO(41) +#define TEGRA_PIN_LCD_D10_PF2 _GPIO(42) +#define TEGRA_PIN_LCD_D11_PF3 _GPIO(43) +#define TEGRA_PIN_LCD_D12_PF4 _GPIO(44) +#define TEGRA_PIN_LCD_D13_PF5 _GPIO(45) +#define TEGRA_PIN_LCD_D14_PF6 _GPIO(46) +#define TEGRA_PIN_LCD_D15_PF7 _GPIO(47) +#define TEGRA_PIN_GMI_AD0_PG0 _GPIO(48) +#define TEGRA_PIN_GMI_AD1_PG1 _GPIO(49) +#define TEGRA_PIN_GMI_AD2_PG2 _GPIO(50) +#define TEGRA_PIN_GMI_AD3_PG3 _GPIO(51) +#define TEGRA_PIN_GMI_AD4_PG4 _GPIO(52) +#define TEGRA_PIN_GMI_AD5_PG5 _GPIO(53) +#define TEGRA_PIN_GMI_AD6_PG6 _GPIO(54) +#define TEGRA_PIN_GMI_AD7_PG7 _GPIO(55) +#define TEGRA_PIN_GMI_AD8_PH0 _GPIO(56) +#define TEGRA_PIN_GMI_AD9_PH1 _GPIO(57) +#define TEGRA_PIN_GMI_AD10_PH2 _GPIO(58) +#define TEGRA_PIN_GMI_AD11_PH3 _GPIO(59) +#define TEGRA_PIN_GMI_AD12_PH4 _GPIO(60) +#define TEGRA_PIN_GMI_AD13_PH5 _GPIO(61) +#define TEGRA_PIN_GMI_AD14_PH6 _GPIO(62) +#define TEGRA_PIN_GMI_AD15_PH7 _GPIO(63) +#define TEGRA_PIN_GMI_HIOW_N_PI0 _GPIO(64) +#define TEGRA_PIN_GMI_HIOR_N_PI1 _GPIO(65) +#define TEGRA_PIN_GMI_CS5_N_PI2 _GPIO(66) +#define TEGRA_PIN_GMI_CS6_N_PI3 _GPIO(67) +#define TEGRA_PIN_GMI_RST_N_PI4 _GPIO(68) +#define TEGRA_PIN_GMI_IORDY_PI5 _GPIO(69) +#define TEGRA_PIN_GMI_CS7_N_PI6 _GPIO(70) +#define TEGRA_PIN_GMI_WAIT_PI7 _GPIO(71) +#define TEGRA_PIN_GMI_CS0_N_PJ0 _GPIO(72) +#define TEGRA_PIN_LCD_DE_PJ1 _GPIO(73) +#define TEGRA_PIN_GMI_CS1_N_PJ2 _GPIO(74) +#define TEGRA_PIN_LCD_HSYNC_PJ3 _GPIO(75) +#define TEGRA_PIN_LCD_VSYNC_PJ4 _GPIO(76) +#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) +#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) +#define TEGRA_PIN_GMI_AD16_PJ7 _GPIO(79) +#define TEGRA_PIN_GMI_ADV_N_PK0 _GPIO(80) +#define TEGRA_PIN_GMI_CLK_PK1 _GPIO(81) +#define TEGRA_PIN_GMI_CS4_N_PK2 _GPIO(82) +#define TEGRA_PIN_GMI_CS2_N_PK3 _GPIO(83) +#define TEGRA_PIN_GMI_CS3_N_PK4 _GPIO(84) +#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) +#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) +#define TEGRA_PIN_GMI_AD19_PK7 _GPIO(87) +#define TEGRA_PIN_VI_D2_PL0 _GPIO(88) +#define TEGRA_PIN_VI_D3_PL1 _GPIO(89) +#define TEGRA_PIN_VI_D4_PL2 _GPIO(90) +#define TEGRA_PIN_VI_D5_PL3 _GPIO(91) +#define TEGRA_PIN_VI_D6_PL4 _GPIO(92) +#define TEGRA_PIN_VI_D7_PL5 _GPIO(93) +#define TEGRA_PIN_VI_D8_PL6 _GPIO(94) +#define TEGRA_PIN_VI_D9_PL7 _GPIO(95) +#define TEGRA_PIN_LCD_D16_PM0 _GPIO(96) +#define TEGRA_PIN_LCD_D17_PM1 _GPIO(97) +#define TEGRA_PIN_LCD_D18_PM2 _GPIO(98) +#define TEGRA_PIN_LCD_D19_PM3 _GPIO(99) +#define TEGRA_PIN_LCD_D20_PM4 _GPIO(100) +#define TEGRA_PIN_LCD_D21_PM5 _GPIO(101) +#define TEGRA_PIN_LCD_D22_PM6 _GPIO(102) +#define TEGRA_PIN_LCD_D23_PM7 _GPIO(103) +#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) +#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) +#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) +#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) +#define TEGRA_PIN_LCD_CS0_N_PN4 _GPIO(108) +#define TEGRA_PIN_LCD_SDOUT_PN5 _GPIO(109) +#define TEGRA_PIN_LCD_DC0_PN6 _GPIO(110) +#define TEGRA_PIN_HDMI_INT_N_PN7 _GPIO(111) +#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) +#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) +#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) +#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) +#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) +#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) +#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) +#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) +#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) +#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) +#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) +#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) +#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) +#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) +#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) +#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) +#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) +#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) +#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) +#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) +#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) +#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) +#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) +#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) +#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) +#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) +#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) +#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) +#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) +#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) +#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) +#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) +#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) +#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) +#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) +#define TEGRA_PIN_KB_ROW11_PS3 _GPIO(147) +#define TEGRA_PIN_KB_ROW12_PS4 _GPIO(148) +#define TEGRA_PIN_KB_ROW13_PS5 _GPIO(149) +#define TEGRA_PIN_KB_ROW14_PS6 _GPIO(150) +#define TEGRA_PIN_KB_ROW15_PS7 _GPIO(151) +#define TEGRA_PIN_VI_PCLK_PT0 _GPIO(152) +#define TEGRA_PIN_VI_MCLK_PT1 _GPIO(153) +#define TEGRA_PIN_VI_D10_PT2 _GPIO(154) +#define TEGRA_PIN_VI_D11_PT3 _GPIO(155) +#define TEGRA_PIN_VI_D0_PT4 _GPIO(156) +#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) +#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) +#define TEGRA_PIN_GMI_DPD_PT7 _GPIO(159) +#define TEGRA_PIN_PU0 _GPIO(160) +#define TEGRA_PIN_PU1 _GPIO(161) +#define TEGRA_PIN_PU2 _GPIO(162) +#define TEGRA_PIN_PU3 _GPIO(163) +#define TEGRA_PIN_PU4 _GPIO(164) +#define TEGRA_PIN_PU5 _GPIO(165) +#define TEGRA_PIN_PU6 _GPIO(166) +#define TEGRA_PIN_JTAG_RTCK_PU7 _GPIO(167) +#define TEGRA_PIN_PV0 _GPIO(168) +#define TEGRA_PIN_PV1 _GPIO(169) +#define TEGRA_PIN_PV2 _GPIO(170) +#define TEGRA_PIN_PV3 _GPIO(171) +#define TEGRA_PIN_PV4 _GPIO(172) +#define TEGRA_PIN_PV5 _GPIO(173) +#define TEGRA_PIN_PV6 _GPIO(174) +#define TEGRA_PIN_LCD_DC1_PV7 _GPIO(175) +#define TEGRA_PIN_LCD_CS1_N_PW0 _GPIO(176) +#define TEGRA_PIN_LCD_M1_PW1 _GPIO(177) +#define TEGRA_PIN_SPI2_CS1_N_PW2 _GPIO(178) +#define TEGRA_PIN_SPI2_CS2_N_PW3 _GPIO(179) +#define TEGRA_PIN_DAP_MCLK1_PW4 _GPIO(180) +#define TEGRA_PIN_DAP_MCLK2_PW5 _GPIO(181) +#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) +#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) +#define TEGRA_PIN_SPI2_MOSI_PX0 _GPIO(184) +#define TEGRA_PIN_SPI2_MISO_PX1 _GPIO(185) +#define TEGRA_PIN_SPI2_SCK_PX2 _GPIO(186) +#define TEGRA_PIN_SPI2_CS0_N_PX3 _GPIO(187) +#define TEGRA_PIN_SPI1_MOSI_PX4 _GPIO(188) +#define TEGRA_PIN_SPI1_SCK_PX5 _GPIO(189) +#define TEGRA_PIN_SPI1_CS0_N_PX6 _GPIO(190) +#define TEGRA_PIN_SPI1_MISO_PX7 _GPIO(191) +#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) +#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) +#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) +#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) +#define TEGRA_PIN_SDIO1_DAT3_PY4 _GPIO(196) +#define TEGRA_PIN_SDIO1_DAT2_PY5 _GPIO(197) +#define TEGRA_PIN_SDIO1_DAT1_PY6 _GPIO(198) +#define TEGRA_PIN_SDIO1_DAT0_PY7 _GPIO(199) +#define TEGRA_PIN_SDIO1_CLK_PZ0 _GPIO(200) +#define TEGRA_PIN_SDIO1_CMD_PZ1 _GPIO(201) +#define TEGRA_PIN_LCD_SDIN_PZ2 _GPIO(202) +#define TEGRA_PIN_LCD_WR_N_PZ3 _GPIO(203) +#define TEGRA_PIN_LCD_SCK_PZ4 _GPIO(204) +#define TEGRA_PIN_SYS_CLK_REQ_PZ5 _GPIO(205) +#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) +#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) +#define TEGRA_PIN_GMI_AD20_PAA0 _GPIO(208) +#define TEGRA_PIN_GMI_AD21_PAA1 _GPIO(209) +#define TEGRA_PIN_GMI_AD22_PAA2 _GPIO(210) +#define TEGRA_PIN_GMI_AD23_PAA3 _GPIO(211) +#define TEGRA_PIN_GMI_AD24_PAA4 _GPIO(212) +#define TEGRA_PIN_GMI_AD25_PAA5 _GPIO(213) +#define TEGRA_PIN_GMI_AD26_PAA6 _GPIO(214) +#define TEGRA_PIN_GMI_AD27_PAA7 _GPIO(215) +#define TEGRA_PIN_LED_BLINK_PBB0 _GPIO(216) +#define TEGRA_PIN_VI_GP0_PBB1 _GPIO(217) +#define TEGRA_PIN_CAM_I2C_SCL_PBB2 _GPIO(218) +#define TEGRA_PIN_CAM_I2C_SDA_PBB3 _GPIO(219) +#define TEGRA_PIN_VI_GP3_PBB4 _GPIO(220) +#define TEGRA_PIN_VI_GP4_PBB5 _GPIO(221) +#define TEGRA_PIN_PBB6 _GPIO(222) +#define TEGRA_PIN_PBB7 _GPIO(223) + +/* All non-GPIO pins follow */ +#define NUM_GPIOS (TEGRA_PIN_PBB7 + 1) +#define _PIN(offset) (NUM_GPIOS + (offset)) + +#define TEGRA_PIN_CRT_HSYNC _PIN(30) +#define TEGRA_PIN_CRT_VSYNC _PIN(31) +#define TEGRA_PIN_DDC_SCL _PIN(32) +#define TEGRA_PIN_DDC_SDA _PIN(33) +#define TEGRA_PIN_OWC _PIN(34) +#define TEGRA_PIN_CORE_PWR_REQ _PIN(35) +#define TEGRA_PIN_CPU_PWR_REQ _PIN(36) +#define TEGRA_PIN_PWR_INT_N _PIN(37) +#define TEGRA_PIN_CLK_32_K_IN _PIN(38) +#define TEGRA_PIN_DDR_COMP_PD _PIN(39) +#define TEGRA_PIN_DDR_COMP_PU _PIN(40) +#define TEGRA_PIN_DDR_A0 _PIN(41) +#define TEGRA_PIN_DDR_A1 _PIN(42) +#define TEGRA_PIN_DDR_A2 _PIN(43) +#define TEGRA_PIN_DDR_A3 _PIN(44) +#define TEGRA_PIN_DDR_A4 _PIN(45) +#define TEGRA_PIN_DDR_A5 _PIN(46) +#define TEGRA_PIN_DDR_A6 _PIN(47) +#define TEGRA_PIN_DDR_A7 _PIN(48) +#define TEGRA_PIN_DDR_A8 _PIN(49) +#define TEGRA_PIN_DDR_A9 _PIN(50) +#define TEGRA_PIN_DDR_A10 _PIN(51) +#define TEGRA_PIN_DDR_A11 _PIN(52) +#define TEGRA_PIN_DDR_A12 _PIN(53) +#define TEGRA_PIN_DDR_A13 _PIN(54) +#define TEGRA_PIN_DDR_A14 _PIN(55) +#define TEGRA_PIN_DDR_CAS_N _PIN(56) +#define TEGRA_PIN_DDR_BA0 _PIN(57) +#define TEGRA_PIN_DDR_BA1 _PIN(58) +#define TEGRA_PIN_DDR_BA2 _PIN(59) +#define TEGRA_PIN_DDR_DQS0P _PIN(60) +#define TEGRA_PIN_DDR_DQS0N _PIN(61) +#define TEGRA_PIN_DDR_DQS1P _PIN(62) +#define TEGRA_PIN_DDR_DQS1N _PIN(63) +#define TEGRA_PIN_DDR_DQS2P _PIN(64) +#define TEGRA_PIN_DDR_DQS2N _PIN(65) +#define TEGRA_PIN_DDR_DQS3P _PIN(66) +#define TEGRA_PIN_DDR_DQS3N _PIN(67) +#define TEGRA_PIN_DDR_CKE0 _PIN(68) +#define TEGRA_PIN_DDR_CKE1 _PIN(69) +#define TEGRA_PIN_DDR_CLK _PIN(70) +#define TEGRA_PIN_DDR_CLK_N _PIN(71) +#define TEGRA_PIN_DDR_DM0 _PIN(72) +#define TEGRA_PIN_DDR_DM1 _PIN(73) +#define TEGRA_PIN_DDR_DM2 _PIN(74) +#define TEGRA_PIN_DDR_DM3 _PIN(75) +#define TEGRA_PIN_DDR_ODT _PIN(76) +#define TEGRA_PIN_DDR_QUSE0 _PIN(77) +#define TEGRA_PIN_DDR_QUSE1 _PIN(78) +#define TEGRA_PIN_DDR_QUSE2 _PIN(79) +#define TEGRA_PIN_DDR_QUSE3 _PIN(80) +#define TEGRA_PIN_DDR_RAS_N _PIN(81) +#define TEGRA_PIN_DDR_WE_N _PIN(82) +#define TEGRA_PIN_DDR_DQ0 _PIN(83) +#define TEGRA_PIN_DDR_DQ1 _PIN(84) +#define TEGRA_PIN_DDR_DQ2 _PIN(85) +#define TEGRA_PIN_DDR_DQ3 _PIN(86) +#define TEGRA_PIN_DDR_DQ4 _PIN(87) +#define TEGRA_PIN_DDR_DQ5 _PIN(88) +#define TEGRA_PIN_DDR_DQ6 _PIN(89) +#define TEGRA_PIN_DDR_DQ7 _PIN(90) +#define TEGRA_PIN_DDR_DQ8 _PIN(91) +#define TEGRA_PIN_DDR_DQ9 _PIN(92) +#define TEGRA_PIN_DDR_DQ10 _PIN(93) +#define TEGRA_PIN_DDR_DQ11 _PIN(94) +#define TEGRA_PIN_DDR_DQ12 _PIN(95) +#define TEGRA_PIN_DDR_DQ13 _PIN(96) +#define TEGRA_PIN_DDR_DQ14 _PIN(97) +#define TEGRA_PIN_DDR_DQ15 _PIN(98) +#define TEGRA_PIN_DDR_DQ16 _PIN(99) +#define TEGRA_PIN_DDR_DQ17 _PIN(100) +#define TEGRA_PIN_DDR_DQ18 _PIN(101) +#define TEGRA_PIN_DDR_DQ19 _PIN(102) +#define TEGRA_PIN_DDR_DQ20 _PIN(103) +#define TEGRA_PIN_DDR_DQ21 _PIN(104) +#define TEGRA_PIN_DDR_DQ22 _PIN(105) +#define TEGRA_PIN_DDR_DQ23 _PIN(106) +#define TEGRA_PIN_DDR_DQ24 _PIN(107) +#define TEGRA_PIN_DDR_DQ25 _PIN(108) +#define TEGRA_PIN_DDR_DQ26 _PIN(109) +#define TEGRA_PIN_DDR_DQ27 _PIN(110) +#define TEGRA_PIN_DDR_DQ28 _PIN(111) +#define TEGRA_PIN_DDR_DQ29 _PIN(112) +#define TEGRA_PIN_DDR_DQ30 _PIN(113) +#define TEGRA_PIN_DDR_DQ31 _PIN(114) +#define TEGRA_PIN_DDR_CS0_N _PIN(115) +#define TEGRA_PIN_DDR_CS1_N _PIN(116) +#define TEGRA_PIN_SYS_RESET _PIN(117) +#define TEGRA_PIN_JTAG_TRST_N _PIN(118) +#define TEGRA_PIN_JTAG_TDO _PIN(119) +#define TEGRA_PIN_JTAG_TMS _PIN(120) +#define TEGRA_PIN_JTAG_TCK _PIN(121) +#define TEGRA_PIN_JTAG_TDI _PIN(122) +#define TEGRA_PIN_TEST_MODE_EN _PIN(123) + +static const struct pinctrl_pin_desc tegra20_pins[] = { + PINCTRL_PIN(TEGRA_PIN_VI_GP6_PA0, "VI_GP6 PA0"), + PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), + PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), + PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_CLK_PA6, "SDIO3_CLK PA6"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_CMD_PA7, "SDIO3_CMD PA7"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD17_PB0, "GMI_AD17 PB0"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD18_PB1, "GMI_AD18 PB1"), + PINCTRL_PIN(TEGRA_PIN_LCD_PWR0_PB2, "LCD_PWR0 PB2"), + PINCTRL_PIN(TEGRA_PIN_LCD_PCLK_PB3, "LCD_PCLK PB3"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT3_PB4, "SDIO3_DAT3 PB4"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT2_PB5, "SDIO3_DAT2 PB5"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT1_PB6, "SDIO3_DAT1 PB6"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT0_PB7, "SDIO3_DAT0 PB7"), + PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), + PINCTRL_PIN(TEGRA_PIN_LCD_PWR1_PC1, "LCD_PWR1 PC1"), + PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), + PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), + PINCTRL_PIN(TEGRA_PIN_LCD_PWR2_PC6, "LCD_PWR2 PC6"), + PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT5_PD0, "SDIO3_DAT5 PD0"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT4_PD1, "SDIO3_DAT4 PD1"), + PINCTRL_PIN(TEGRA_PIN_VI_GP5_PD2, "VI_GP5 PD2"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT6_PD3, "SDIO3_DAT6 PD3"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT7_PD4, "SDIO3_DAT7 PD4"), + PINCTRL_PIN(TEGRA_PIN_VI_D1_PD5, "VI_D1 PD5"), + PINCTRL_PIN(TEGRA_PIN_VI_VSYNC_PD6, "VI_VSYNC PD6"), + PINCTRL_PIN(TEGRA_PIN_VI_HSYNC_PD7, "VI_HSYNC PD7"), + PINCTRL_PIN(TEGRA_PIN_LCD_D0_PE0, "LCD_D0 PE0"), + PINCTRL_PIN(TEGRA_PIN_LCD_D1_PE1, "LCD_D1 PE1"), + PINCTRL_PIN(TEGRA_PIN_LCD_D2_PE2, "LCD_D2 PE2"), + PINCTRL_PIN(TEGRA_PIN_LCD_D3_PE3, "LCD_D3 PE3"), + PINCTRL_PIN(TEGRA_PIN_LCD_D4_PE4, "LCD_D4 PE4"), + PINCTRL_PIN(TEGRA_PIN_LCD_D5_PE5, "LCD_D5 PE5"), + PINCTRL_PIN(TEGRA_PIN_LCD_D6_PE6, "LCD_D6 PE6"), + PINCTRL_PIN(TEGRA_PIN_LCD_D7_PE7, "LCD_D7 PE7"), + PINCTRL_PIN(TEGRA_PIN_LCD_D8_PF0, "LCD_D8 PF0"), + PINCTRL_PIN(TEGRA_PIN_LCD_D9_PF1, "LCD_D9 PF1"), + PINCTRL_PIN(TEGRA_PIN_LCD_D10_PF2, "LCD_D10 PF2"), + PINCTRL_PIN(TEGRA_PIN_LCD_D11_PF3, "LCD_D11 PF3"), + PINCTRL_PIN(TEGRA_PIN_LCD_D12_PF4, "LCD_D12 PF4"), + PINCTRL_PIN(TEGRA_PIN_LCD_D13_PF5, "LCD_D13 PF5"), + PINCTRL_PIN(TEGRA_PIN_LCD_D14_PF6, "LCD_D14 PF6"), + PINCTRL_PIN(TEGRA_PIN_LCD_D15_PF7, "LCD_D15 PF7"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"), + PINCTRL_PIN(TEGRA_PIN_GMI_HIOW_N_PI0, "GMI_HIOW_N PI0"), + PINCTRL_PIN(TEGRA_PIN_GMI_HIOR_N_PI1, "GMI_HIOR_N PI1"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS5_N_PI2, "GMI_CS5_N PI2"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"), + PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"), + PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"), + PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"), + PINCTRL_PIN(TEGRA_PIN_LCD_DE_PJ1, "LCD_DE PJ1"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"), + PINCTRL_PIN(TEGRA_PIN_LCD_HSYNC_PJ3, "LCD_HSYNC PJ3"), + PINCTRL_PIN(TEGRA_PIN_LCD_VSYNC_PJ4, "LCD_VSYNC PJ4"), + PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), + PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD16_PJ7, "GMI_AD16 PJ7"), + PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"), + PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD19_PK7, "GMI_AD19 PK7"), + PINCTRL_PIN(TEGRA_PIN_VI_D2_PL0, "VI_D2 PL0"), + PINCTRL_PIN(TEGRA_PIN_VI_D3_PL1, "VI_D3 PL1"), + PINCTRL_PIN(TEGRA_PIN_VI_D4_PL2, "VI_D4 PL2"), + PINCTRL_PIN(TEGRA_PIN_VI_D5_PL3, "VI_D5 PL3"), + PINCTRL_PIN(TEGRA_PIN_VI_D6_PL4, "VI_D6 PL4"), + PINCTRL_PIN(TEGRA_PIN_VI_D7_PL5, "VI_D7 PL5"), + PINCTRL_PIN(TEGRA_PIN_VI_D8_PL6, "VI_D8 PL6"), + PINCTRL_PIN(TEGRA_PIN_VI_D9_PL7, "VI_D9 PL7"), + PINCTRL_PIN(TEGRA_PIN_LCD_D16_PM0, "LCD_D16 PM0"), + PINCTRL_PIN(TEGRA_PIN_LCD_D17_PM1, "LCD_D17 PM1"), + PINCTRL_PIN(TEGRA_PIN_LCD_D18_PM2, "LCD_D18 PM2"), + PINCTRL_PIN(TEGRA_PIN_LCD_D19_PM3, "LCD_D19 PM3"), + PINCTRL_PIN(TEGRA_PIN_LCD_D20_PM4, "LCD_D20 PM4"), + PINCTRL_PIN(TEGRA_PIN_LCD_D21_PM5, "LCD_D21 PM5"), + PINCTRL_PIN(TEGRA_PIN_LCD_D22_PM6, "LCD_D22 PM6"), + PINCTRL_PIN(TEGRA_PIN_LCD_D23_PM7, "LCD_D23 PM7"), + PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), + PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), + PINCTRL_PIN(TEGRA_PIN_LCD_CS0_N_PN4, "LCD_CS0_N PN4"), + PINCTRL_PIN(TEGRA_PIN_LCD_SDOUT_PN5, "LCD_SDOUT PN5"), + PINCTRL_PIN(TEGRA_PIN_LCD_DC0_PN6, "LCD_DC0 PN6"), + PINCTRL_PIN(TEGRA_PIN_HDMI_INT_N_PN7, "HDMI_INT_N PN7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), + PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), + PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), + PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), + PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), + PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), + PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), + PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), + PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), + PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), + PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), + PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), + PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"), + PINCTRL_PIN(TEGRA_PIN_VI_PCLK_PT0, "VI_PCLK PT0"), + PINCTRL_PIN(TEGRA_PIN_VI_MCLK_PT1, "VI_MCLK PT1"), + PINCTRL_PIN(TEGRA_PIN_VI_D10_PT2, "VD_D10 PT2"), + PINCTRL_PIN(TEGRA_PIN_VI_D11_PT3, "VI_D11 PT3"), + PINCTRL_PIN(TEGRA_PIN_VI_D0_PT4, "VI_D0 PT4"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), + PINCTRL_PIN(TEGRA_PIN_GMI_DPD_PT7, "GMI_DPD PT7"), + /* PU0..6: GPIO only */ + PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), + PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), + PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), + PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), + PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), + PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), + PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), + PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK_PU7, "JTAG_RTCK PU7"), + /* PV0..1: GPIO only */ + PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), + PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), + /* PV2..3: Balls are named after GPIO not function */ + PINCTRL_PIN(TEGRA_PIN_PV2, "PV2"), + PINCTRL_PIN(TEGRA_PIN_PV3, "PV3"), + /* PV4..6: GPIO only */ + PINCTRL_PIN(TEGRA_PIN_PV4, "PV4"), + PINCTRL_PIN(TEGRA_PIN_PV5, "PV5"), + PINCTRL_PIN(TEGRA_PIN_PV6, "PV6"), + PINCTRL_PIN(TEGRA_PIN_LCD_DC1_PV7, "LCD_DC1 PV7"), + PINCTRL_PIN(TEGRA_PIN_LCD_CS1_N_PW0, "LCD_CS1_N PW0"), + PINCTRL_PIN(TEGRA_PIN_LCD_M1_PW1, "LCD_M1 PW1"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_N_PW2, "SPI2_CS1_N PW2"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS2_N_PW3, "SPI2_CS2_N PW3"), + PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_PW4, "DAP_MCLK1 PW4"), + PINCTRL_PIN(TEGRA_PIN_DAP_MCLK2_PW5, "DAP_MCLK2 PW5"), + PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), + PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), + PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PX0, "SPI2_MOSI PX0"), + PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PX1, "SPI2_MISO PX1"), + PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PX2, "SPI2_SCK PX2"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_N_PX3, "SPI2_CS0_N PX3"), + PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PX4, "SPI1_MOSI PX4"), + PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PX5, "SPI1_SCK PX5"), + PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_N_PX6, "SPI1_CS0_N PX6"), + PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PX7, "SPI1_MISO PX7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), + PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT3_PY4, "SDIO1_DAT3 PY4"), + PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT2_PY5, "SDIO1_DAT2 PY5"), + PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT1_PY6, "SDIO1_DAT1 PY6"), + PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT0_PY7, "SDIO1_DAT0 PY7"), + PINCTRL_PIN(TEGRA_PIN_SDIO1_CLK_PZ0, "SDIO1_CLK PZ0"), + PINCTRL_PIN(TEGRA_PIN_SDIO1_CMD_PZ1, "SDIO1_CMD PZ1"), + PINCTRL_PIN(TEGRA_PIN_LCD_SDIN_PZ2, "LCD_SDIN PZ2"), + PINCTRL_PIN(TEGRA_PIN_LCD_WR_N_PZ3, "LCD_WR_N PZ3"), + PINCTRL_PIN(TEGRA_PIN_LCD_SCK_PZ4, "LCD_SCK PZ4"), + PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD20_PAA0, "GMI_AD20 PAA0"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD21_PAA1, "GMI_AD21 PAA1"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD22_PAA2, "GMI_AD22 PAA2"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD23_PAA3, "GMI_AD23 PAA3"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD24_PAA4, "GMI_AD24 PAA4"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD25_PAA5, "GMI_AD25 PAA5"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD26_PAA6, "GMI_AD26 PAA6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD27_PAA7, "GMI_AD27 PAA7"), + PINCTRL_PIN(TEGRA_PIN_LED_BLINK_PBB0, "LED_BLINK PBB0"), + PINCTRL_PIN(TEGRA_PIN_VI_GP0_PBB1, "VI_GP0 PBB1"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB2, "CAM_I2C_SCL PBB2"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB3, "CAM_I2C_SDA PBB3"), + PINCTRL_PIN(TEGRA_PIN_VI_GP3_PBB4, "VI_GP3 PBB4"), + PINCTRL_PIN(TEGRA_PIN_VI_GP4_PBB5, "VI_GP4 PBB5"), + PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), + PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), + PINCTRL_PIN(TEGRA_PIN_CRT_HSYNC, "CRT_HSYNC"), + PINCTRL_PIN(TEGRA_PIN_CRT_VSYNC, "CRT_VSYNC"), + PINCTRL_PIN(TEGRA_PIN_DDC_SCL, "DDC_SCL"), + PINCTRL_PIN(TEGRA_PIN_DDC_SDA, "DDC_SDA"), + PINCTRL_PIN(TEGRA_PIN_OWC, "OWC"), + PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), + PINCTRL_PIN(TEGRA_PIN_CLK_32_K_IN, "CLK_32_K_IN"), + PINCTRL_PIN(TEGRA_PIN_DDR_COMP_PD, "DDR_COMP_PD"), + PINCTRL_PIN(TEGRA_PIN_DDR_COMP_PU, "DDR_COMP_PU"), + PINCTRL_PIN(TEGRA_PIN_DDR_A0, "DDR_A0"), + PINCTRL_PIN(TEGRA_PIN_DDR_A1, "DDR_A1"), + PINCTRL_PIN(TEGRA_PIN_DDR_A2, "DDR_A2"), + PINCTRL_PIN(TEGRA_PIN_DDR_A3, "DDR_A3"), + PINCTRL_PIN(TEGRA_PIN_DDR_A4, "DDR_A4"), + PINCTRL_PIN(TEGRA_PIN_DDR_A5, "DDR_A5"), + PINCTRL_PIN(TEGRA_PIN_DDR_A6, "DDR_A6"), + PINCTRL_PIN(TEGRA_PIN_DDR_A7, "DDR_A7"), + PINCTRL_PIN(TEGRA_PIN_DDR_A8, "DDR_A8"), + PINCTRL_PIN(TEGRA_PIN_DDR_A9, "DDR_A9"), + PINCTRL_PIN(TEGRA_PIN_DDR_A10, "DDR_A10"), + PINCTRL_PIN(TEGRA_PIN_DDR_A11, "DDR_A11"), + PINCTRL_PIN(TEGRA_PIN_DDR_A12, "DDR_A12"), + PINCTRL_PIN(TEGRA_PIN_DDR_A13, "DDR_A13"), + PINCTRL_PIN(TEGRA_PIN_DDR_A14, "DDR_A14"), + PINCTRL_PIN(TEGRA_PIN_DDR_CAS_N, "DDR_CAS_N"), + PINCTRL_PIN(TEGRA_PIN_DDR_BA0, "DDR_BA0"), + PINCTRL_PIN(TEGRA_PIN_DDR_BA1, "DDR_BA1"), + PINCTRL_PIN(TEGRA_PIN_DDR_BA2, "DDR_BA2"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQS0P, "DDR_DQS0P"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQS0N, "DDR_DQS0N"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQS1P, "DDR_DQS1P"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQS1N, "DDR_DQS1N"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQS2P, "DDR_DQS2P"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQS2N, "DDR_DQS2N"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQS3P, "DDR_DQS3P"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQS3N, "DDR_DQS3N"), + PINCTRL_PIN(TEGRA_PIN_DDR_CKE0, "DDR_CKE0"), + PINCTRL_PIN(TEGRA_PIN_DDR_CKE1, "DDR_CKE1"), + PINCTRL_PIN(TEGRA_PIN_DDR_CLK, "DDR_CLK"), + PINCTRL_PIN(TEGRA_PIN_DDR_CLK_N, "DDR_CLK_N"), + PINCTRL_PIN(TEGRA_PIN_DDR_DM0, "DDR_DM0"), + PINCTRL_PIN(TEGRA_PIN_DDR_DM1, "DDR_DM1"), + PINCTRL_PIN(TEGRA_PIN_DDR_DM2, "DDR_DM2"), + PINCTRL_PIN(TEGRA_PIN_DDR_DM3, "DDR_DM3"), + PINCTRL_PIN(TEGRA_PIN_DDR_ODT, "DDR_ODT"), + PINCTRL_PIN(TEGRA_PIN_DDR_QUSE0, "DDR_QUSE0"), + PINCTRL_PIN(TEGRA_PIN_DDR_QUSE1, "DDR_QUSE1"), + PINCTRL_PIN(TEGRA_PIN_DDR_QUSE2, "DDR_QUSE2"), + PINCTRL_PIN(TEGRA_PIN_DDR_QUSE3, "DDR_QUSE3"), + PINCTRL_PIN(TEGRA_PIN_DDR_RAS_N, "DDR_RAS_N"), + PINCTRL_PIN(TEGRA_PIN_DDR_WE_N, "DDR_WE_N"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ0, "DDR_DQ0"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ1, "DDR_DQ1"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ2, "DDR_DQ2"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ3, "DDR_DQ3"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ4, "DDR_DQ4"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ5, "DDR_DQ5"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ6, "DDR_DQ6"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ7, "DDR_DQ7"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ8, "DDR_DQ8"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ9, "DDR_DQ9"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ10, "DDR_DQ10"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ11, "DDR_DQ11"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ12, "DDR_DQ12"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ13, "DDR_DQ13"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ14, "DDR_DQ14"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ15, "DDR_DQ15"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ16, "DDR_DQ16"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ17, "DDR_DQ17"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ18, "DDR_DQ18"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ19, "DDR_DQ19"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ20, "DDR_DQ20"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ21, "DDR_DQ21"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ22, "DDR_DQ22"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ23, "DDR_DQ23"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ24, "DDR_DQ24"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ25, "DDR_DQ25"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ26, "DDR_DQ26"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ27, "DDR_DQ27"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ28, "DDR_DQ28"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ29, "DDR_DQ29"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ30, "DDR_DQ30"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ31, "DDR_DQ31"), + PINCTRL_PIN(TEGRA_PIN_DDR_CS0_N, "DDR_CS0_N"), + PINCTRL_PIN(TEGRA_PIN_DDR_CS1_N, "DDR_CS1_N"), + PINCTRL_PIN(TEGRA_PIN_SYS_RESET, "SYS_RESET"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TRST_N, "JTAG_TRST_N"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TDO, "JTAG_TDO"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TMS, "JTAG_TMS"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TCK, "JTAG_TCK"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TDI, "JTAG_TDI"), + PINCTRL_PIN(TEGRA_PIN_TEST_MODE_EN, "TEST_MODE_EN"), +}; + +static const unsigned ata_pins[] = { + TEGRA_PIN_GMI_CS6_N_PI3, + TEGRA_PIN_GMI_CS7_N_PI6, + TEGRA_PIN_GMI_RST_N_PI4, +}; + +static const unsigned atb_pins[] = { + TEGRA_PIN_GMI_CS5_N_PI2, + TEGRA_PIN_GMI_DPD_PT7, +}; + +static const unsigned atc_pins[] = { + TEGRA_PIN_GMI_IORDY_PI5, + TEGRA_PIN_GMI_WAIT_PI7, + TEGRA_PIN_GMI_ADV_N_PK0, + TEGRA_PIN_GMI_CLK_PK1, + TEGRA_PIN_GMI_CS2_N_PK3, + TEGRA_PIN_GMI_CS3_N_PK4, + TEGRA_PIN_GMI_CS4_N_PK2, + TEGRA_PIN_GMI_AD0_PG0, + TEGRA_PIN_GMI_AD1_PG1, + TEGRA_PIN_GMI_AD2_PG2, + TEGRA_PIN_GMI_AD3_PG3, + TEGRA_PIN_GMI_AD4_PG4, + TEGRA_PIN_GMI_AD5_PG5, + TEGRA_PIN_GMI_AD6_PG6, + TEGRA_PIN_GMI_AD7_PG7, + TEGRA_PIN_GMI_HIOW_N_PI0, + TEGRA_PIN_GMI_HIOR_N_PI1, +}; + +static const unsigned atd_pins[] = { + TEGRA_PIN_GMI_AD8_PH0, + TEGRA_PIN_GMI_AD9_PH1, + TEGRA_PIN_GMI_AD10_PH2, + TEGRA_PIN_GMI_AD11_PH3, +}; + +static const unsigned ate_pins[] = { + TEGRA_PIN_GMI_AD12_PH4, + TEGRA_PIN_GMI_AD13_PH5, + TEGRA_PIN_GMI_AD14_PH6, + TEGRA_PIN_GMI_AD15_PH7, +}; + +static const unsigned cdev1_pins[] = { + TEGRA_PIN_DAP_MCLK1_PW4, +}; + +static const unsigned cdev2_pins[] = { + TEGRA_PIN_DAP_MCLK2_PW5, +}; + +static const unsigned crtp_pins[] = { + TEGRA_PIN_CRT_HSYNC, + TEGRA_PIN_CRT_VSYNC, +}; + +static const unsigned csus_pins[] = { + TEGRA_PIN_VI_MCLK_PT1, +}; + +static const unsigned dap1_pins[] = { + TEGRA_PIN_DAP1_FS_PN0, + TEGRA_PIN_DAP1_DIN_PN1, + TEGRA_PIN_DAP1_DOUT_PN2, + TEGRA_PIN_DAP1_SCLK_PN3, +}; + +static const unsigned dap2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, + TEGRA_PIN_DAP2_SCLK_PA3, + TEGRA_PIN_DAP2_DIN_PA4, + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned dap3_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, + TEGRA_PIN_DAP3_DIN_PP1, + TEGRA_PIN_DAP3_DOUT_PP2, + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned dap4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, + TEGRA_PIN_DAP4_DIN_PP5, + TEGRA_PIN_DAP4_DOUT_PP6, + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned ddc_pins[] = { + TEGRA_PIN_DDC_SCL, + TEGRA_PIN_DDC_SDA, +}; + +static const unsigned dta_pins[] = { + TEGRA_PIN_VI_D0_PT4, + TEGRA_PIN_VI_D1_PD5, +}; + +static const unsigned dtb_pins[] = { + TEGRA_PIN_VI_D10_PT2, + TEGRA_PIN_VI_D11_PT3, +}; + +static const unsigned dtc_pins[] = { + TEGRA_PIN_VI_HSYNC_PD7, + TEGRA_PIN_VI_VSYNC_PD6, +}; + +static const unsigned dtd_pins[] = { + TEGRA_PIN_VI_PCLK_PT0, + TEGRA_PIN_VI_D2_PL0, + TEGRA_PIN_VI_D3_PL1, + TEGRA_PIN_VI_D4_PL2, + TEGRA_PIN_VI_D5_PL3, + TEGRA_PIN_VI_D6_PL4, + TEGRA_PIN_VI_D7_PL5, + TEGRA_PIN_VI_D8_PL6, + TEGRA_PIN_VI_D9_PL7, +}; + +static const unsigned dte_pins[] = { + TEGRA_PIN_VI_GP0_PBB1, + TEGRA_PIN_VI_GP3_PBB4, + TEGRA_PIN_VI_GP4_PBB5, + TEGRA_PIN_VI_GP5_PD2, + TEGRA_PIN_VI_GP6_PA0, +}; + +static const unsigned dtf_pins[] = { + TEGRA_PIN_CAM_I2C_SCL_PBB2, + TEGRA_PIN_CAM_I2C_SDA_PBB3, +}; + +static const unsigned gma_pins[] = { + TEGRA_PIN_GMI_AD20_PAA0, + TEGRA_PIN_GMI_AD21_PAA1, + TEGRA_PIN_GMI_AD22_PAA2, + TEGRA_PIN_GMI_AD23_PAA3, +}; + +static const unsigned gmb_pins[] = { + TEGRA_PIN_GMI_WP_N_PC7, +}; + +static const unsigned gmc_pins[] = { + TEGRA_PIN_GMI_AD16_PJ7, + TEGRA_PIN_GMI_AD17_PB0, + TEGRA_PIN_GMI_AD18_PB1, + TEGRA_PIN_GMI_AD19_PK7, +}; + +static const unsigned gmd_pins[] = { + TEGRA_PIN_GMI_CS0_N_PJ0, + TEGRA_PIN_GMI_CS1_N_PJ2, +}; + +static const unsigned gme_pins[] = { + TEGRA_PIN_GMI_AD24_PAA4, + TEGRA_PIN_GMI_AD25_PAA5, + TEGRA_PIN_GMI_AD26_PAA6, + TEGRA_PIN_GMI_AD27_PAA7, +}; + +static const unsigned gpu_pins[] = { + TEGRA_PIN_PU0, + TEGRA_PIN_PU1, + TEGRA_PIN_PU2, + TEGRA_PIN_PU3, + TEGRA_PIN_PU4, + TEGRA_PIN_PU5, + TEGRA_PIN_PU6, +}; + +static const unsigned gpu7_pins[] = { + TEGRA_PIN_JTAG_RTCK_PU7, +}; + +static const unsigned gpv_pins[] = { + TEGRA_PIN_PV4, + TEGRA_PIN_PV5, + TEGRA_PIN_PV6, +}; + +static const unsigned hdint_pins[] = { + TEGRA_PIN_HDMI_INT_N_PN7, +}; + +static const unsigned i2cp_pins[] = { + TEGRA_PIN_PWR_I2C_SCL_PZ6, + TEGRA_PIN_PWR_I2C_SDA_PZ7, +}; + +static const unsigned irrx_pins[] = { + TEGRA_PIN_UART2_RTS_N_PJ6, +}; + +static const unsigned irtx_pins[] = { + TEGRA_PIN_UART2_CTS_N_PJ5, +}; + +static const unsigned kbca_pins[] = { + TEGRA_PIN_KB_ROW0_PR0, + TEGRA_PIN_KB_ROW1_PR1, + TEGRA_PIN_KB_ROW2_PR2, +}; + +static const unsigned kbcb_pins[] = { + TEGRA_PIN_KB_ROW7_PR7, + TEGRA_PIN_KB_ROW8_PS0, + TEGRA_PIN_KB_ROW9_PS1, + TEGRA_PIN_KB_ROW10_PS2, + TEGRA_PIN_KB_ROW11_PS3, + TEGRA_PIN_KB_ROW12_PS4, + TEGRA_PIN_KB_ROW13_PS5, + TEGRA_PIN_KB_ROW14_PS6, + TEGRA_PIN_KB_ROW15_PS7, +}; + +static const unsigned kbcc_pins[] = { + TEGRA_PIN_KB_COL0_PQ0, + TEGRA_PIN_KB_COL1_PQ1, +}; + +static const unsigned kbcd_pins[] = { + TEGRA_PIN_KB_ROW3_PR3, + TEGRA_PIN_KB_ROW4_PR4, + TEGRA_PIN_KB_ROW5_PR5, + TEGRA_PIN_KB_ROW6_PR6, +}; + +static const unsigned kbce_pins[] = { + TEGRA_PIN_KB_COL7_PQ7, +}; + +static const unsigned kbcf_pins[] = { + TEGRA_PIN_KB_COL2_PQ2, + TEGRA_PIN_KB_COL3_PQ3, + TEGRA_PIN_KB_COL4_PQ4, + TEGRA_PIN_KB_COL5_PQ5, + TEGRA_PIN_KB_COL6_PQ6, +}; + +static const unsigned lcsn_pins[] = { + TEGRA_PIN_LCD_CS0_N_PN4, +}; + +static const unsigned ld0_pins[] = { + TEGRA_PIN_LCD_D0_PE0, +}; + +static const unsigned ld1_pins[] = { + TEGRA_PIN_LCD_D1_PE1, +}; + +static const unsigned ld2_pins[] = { + TEGRA_PIN_LCD_D2_PE2, +}; + +static const unsigned ld3_pins[] = { + TEGRA_PIN_LCD_D3_PE3, +}; + +static const unsigned ld4_pins[] = { + TEGRA_PIN_LCD_D4_PE4, +}; + +static const unsigned ld5_pins[] = { + TEGRA_PIN_LCD_D5_PE5, +}; + +static const unsigned ld6_pins[] = { + TEGRA_PIN_LCD_D6_PE6, +}; + +static const unsigned ld7_pins[] = { + TEGRA_PIN_LCD_D7_PE7, +}; + +static const unsigned ld8_pins[] = { + TEGRA_PIN_LCD_D8_PF0, +}; + +static const unsigned ld9_pins[] = { + TEGRA_PIN_LCD_D9_PF1, +}; + +static const unsigned ld10_pins[] = { + TEGRA_PIN_LCD_D10_PF2, +}; + +static const unsigned ld11_pins[] = { + TEGRA_PIN_LCD_D11_PF3, +}; + +static const unsigned ld12_pins[] = { + TEGRA_PIN_LCD_D12_PF4, +}; + +static const unsigned ld13_pins[] = { + TEGRA_PIN_LCD_D13_PF5, +}; + +static const unsigned ld14_pins[] = { + TEGRA_PIN_LCD_D14_PF6, +}; + +static const unsigned ld15_pins[] = { + TEGRA_PIN_LCD_D15_PF7, +}; + +static const unsigned ld16_pins[] = { + TEGRA_PIN_LCD_D16_PM0, +}; + +static const unsigned ld17_pins[] = { + TEGRA_PIN_LCD_D17_PM1, +}; + +static const unsigned ldc_pins[] = { + TEGRA_PIN_LCD_DC0_PN6, +}; + +static const unsigned ldi_pins[] = { + TEGRA_PIN_LCD_D22_PM6, +}; + +static const unsigned lhp0_pins[] = { + TEGRA_PIN_LCD_D21_PM5, +}; + +static const unsigned lhp1_pins[] = { + TEGRA_PIN_LCD_D18_PM2, +}; + +static const unsigned lhp2_pins[] = { + TEGRA_PIN_LCD_D19_PM3, +}; + +static const unsigned lhs_pins[] = { + TEGRA_PIN_LCD_HSYNC_PJ3, +}; + +static const unsigned lm0_pins[] = { + TEGRA_PIN_LCD_CS1_N_PW0, +}; + +static const unsigned lm1_pins[] = { + TEGRA_PIN_LCD_M1_PW1, +}; + +static const unsigned lpp_pins[] = { + TEGRA_PIN_LCD_D23_PM7, +}; + +static const unsigned lpw0_pins[] = { + TEGRA_PIN_LCD_PWR0_PB2, +}; + +static const unsigned lpw1_pins[] = { + TEGRA_PIN_LCD_PWR1_PC1, +}; + +static const unsigned lpw2_pins[] = { + TEGRA_PIN_LCD_PWR2_PC6, +}; + +static const unsigned lsc0_pins[] = { + TEGRA_PIN_LCD_PCLK_PB3, +}; + +static const unsigned lsc1_pins[] = { + TEGRA_PIN_LCD_WR_N_PZ3, +}; + +static const unsigned lsck_pins[] = { + TEGRA_PIN_LCD_SCK_PZ4, +}; + +static const unsigned lsda_pins[] = { + TEGRA_PIN_LCD_SDOUT_PN5, +}; + +static const unsigned lsdi_pins[] = { + TEGRA_PIN_LCD_SDIN_PZ2, +}; + +static const unsigned lspi_pins[] = { + TEGRA_PIN_LCD_DE_PJ1, +}; + +static const unsigned lvp0_pins[] = { + TEGRA_PIN_LCD_DC1_PV7, +}; + +static const unsigned lvp1_pins[] = { + TEGRA_PIN_LCD_D20_PM4, +}; + +static const unsigned lvs_pins[] = { + TEGRA_PIN_LCD_VSYNC_PJ4, +}; + +static const unsigned ls_pins[] = { + TEGRA_PIN_LCD_PWR0_PB2, + TEGRA_PIN_LCD_PWR1_PC1, + TEGRA_PIN_LCD_PWR2_PC6, + TEGRA_PIN_LCD_SDIN_PZ2, + TEGRA_PIN_LCD_SDOUT_PN5, + TEGRA_PIN_LCD_WR_N_PZ3, + TEGRA_PIN_LCD_CS0_N_PN4, + TEGRA_PIN_LCD_DC0_PN6, + TEGRA_PIN_LCD_SCK_PZ4, +}; + +static const unsigned lc_pins[] = { + TEGRA_PIN_LCD_PCLK_PB3, + TEGRA_PIN_LCD_DE_PJ1, + TEGRA_PIN_LCD_HSYNC_PJ3, + TEGRA_PIN_LCD_VSYNC_PJ4, + TEGRA_PIN_LCD_CS1_N_PW0, + TEGRA_PIN_LCD_M1_PW1, + TEGRA_PIN_LCD_DC1_PV7, + TEGRA_PIN_HDMI_INT_N_PN7, +}; + +static const unsigned ld17_0_pins[] = { + TEGRA_PIN_LCD_D0_PE0, + TEGRA_PIN_LCD_D1_PE1, + TEGRA_PIN_LCD_D2_PE2, + TEGRA_PIN_LCD_D3_PE3, + TEGRA_PIN_LCD_D4_PE4, + TEGRA_PIN_LCD_D5_PE5, + TEGRA_PIN_LCD_D6_PE6, + TEGRA_PIN_LCD_D7_PE7, + TEGRA_PIN_LCD_D8_PF0, + TEGRA_PIN_LCD_D9_PF1, + TEGRA_PIN_LCD_D10_PF2, + TEGRA_PIN_LCD_D11_PF3, + TEGRA_PIN_LCD_D12_PF4, + TEGRA_PIN_LCD_D13_PF5, + TEGRA_PIN_LCD_D14_PF6, + TEGRA_PIN_LCD_D15_PF7, + TEGRA_PIN_LCD_D16_PM0, + TEGRA_PIN_LCD_D17_PM1, +}; + +static const unsigned ld19_18_pins[] = { + TEGRA_PIN_LCD_D18_PM2, + TEGRA_PIN_LCD_D19_PM3, +}; + +static const unsigned ld21_20_pins[] = { + TEGRA_PIN_LCD_D20_PM4, + TEGRA_PIN_LCD_D21_PM5, +}; + +static const unsigned ld23_22_pins[] = { + TEGRA_PIN_LCD_D22_PM6, + TEGRA_PIN_LCD_D23_PM7, +}; + +static const unsigned owc_pins[] = { + TEGRA_PIN_OWC, +}; + +static const unsigned pmc_pins[] = { + TEGRA_PIN_LED_BLINK_PBB0, + TEGRA_PIN_SYS_CLK_REQ_PZ5, + TEGRA_PIN_CORE_PWR_REQ, + TEGRA_PIN_CPU_PWR_REQ, + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned pta_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PT5, + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned rm_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PC4, + TEGRA_PIN_GEN1_I2C_SDA_PC5, +}; + +static const unsigned sdb_pins[] = { + TEGRA_PIN_SDIO3_CMD_PA7, +}; + +static const unsigned sdc_pins[] = { + TEGRA_PIN_SDIO3_DAT0_PB7, + TEGRA_PIN_SDIO3_DAT1_PB6, + TEGRA_PIN_SDIO3_DAT2_PB5, + TEGRA_PIN_SDIO3_DAT3_PB4, +}; + +static const unsigned sdd_pins[] = { + TEGRA_PIN_SDIO3_CLK_PA6, +}; + +static const unsigned sdio1_pins[] = { + TEGRA_PIN_SDIO1_CLK_PZ0, + TEGRA_PIN_SDIO1_CMD_PZ1, + TEGRA_PIN_SDIO1_DAT0_PY7, + TEGRA_PIN_SDIO1_DAT1_PY6, + TEGRA_PIN_SDIO1_DAT2_PY5, + TEGRA_PIN_SDIO1_DAT3_PY4, +}; + +static const unsigned slxa_pins[] = { + TEGRA_PIN_SDIO3_DAT4_PD1, +}; + +static const unsigned slxc_pins[] = { + TEGRA_PIN_SDIO3_DAT6_PD3, +}; + +static const unsigned slxd_pins[] = { + TEGRA_PIN_SDIO3_DAT7_PD4, +}; + +static const unsigned slxk_pins[] = { + TEGRA_PIN_SDIO3_DAT5_PD0, +}; + +static const unsigned spdi_pins[] = { + TEGRA_PIN_SPDIF_IN_PK6, +}; + +static const unsigned spdo_pins[] = { + TEGRA_PIN_SPDIF_OUT_PK5, +}; + +static const unsigned spia_pins[] = { + TEGRA_PIN_SPI2_MOSI_PX0, +}; + +static const unsigned spib_pins[] = { + TEGRA_PIN_SPI2_MISO_PX1, +}; + +static const unsigned spic_pins[] = { + TEGRA_PIN_SPI2_CS0_N_PX3, + TEGRA_PIN_SPI2_SCK_PX2, +}; + +static const unsigned spid_pins[] = { + TEGRA_PIN_SPI1_MOSI_PX4, +}; + +static const unsigned spie_pins[] = { + TEGRA_PIN_SPI1_CS0_N_PX6, + TEGRA_PIN_SPI1_SCK_PX5, +}; + +static const unsigned spif_pins[] = { + TEGRA_PIN_SPI1_MISO_PX7, +}; + +static const unsigned spig_pins[] = { + TEGRA_PIN_SPI2_CS1_N_PW2, +}; + +static const unsigned spih_pins[] = { + TEGRA_PIN_SPI2_CS2_N_PW3, +}; + +static const unsigned uaa_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, + TEGRA_PIN_ULPI_DATA1_PO2, + TEGRA_PIN_ULPI_DATA2_PO3, + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned uab_pins[] = { + TEGRA_PIN_ULPI_DATA4_PO5, + TEGRA_PIN_ULPI_DATA5_PO6, + TEGRA_PIN_ULPI_DATA6_PO7, + TEGRA_PIN_ULPI_DATA7_PO0, +}; + +static const unsigned uac_pins[] = { + TEGRA_PIN_PV0, + TEGRA_PIN_PV1, + TEGRA_PIN_PV2, + TEGRA_PIN_PV3, +}; + +static const unsigned ck32_pins[] = { + TEGRA_PIN_CLK_32_K_IN, +}; + +static const unsigned uad_pins[] = { + TEGRA_PIN_UART2_RXD_PC3, + TEGRA_PIN_UART2_TXD_PC2, +}; + +static const unsigned uca_pins[] = { + TEGRA_PIN_UART3_RXD_PW7, + TEGRA_PIN_UART3_TXD_PW6, +}; + +static const unsigned ucb_pins[] = { + TEGRA_PIN_UART3_CTS_N_PA1, + TEGRA_PIN_UART3_RTS_N_PC0, +}; + +static const unsigned uda_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, + TEGRA_PIN_ULPI_DIR_PY1, + TEGRA_PIN_ULPI_NXT_PY2, + TEGRA_PIN_ULPI_STP_PY3, +}; + +static const unsigned ddrc_pins[] = { + TEGRA_PIN_DDR_COMP_PD, + TEGRA_PIN_DDR_COMP_PU, +}; + +static const unsigned pmca_pins[] = { + TEGRA_PIN_LED_BLINK_PBB0, +}; + +static const unsigned pmcb_pins[] = { + TEGRA_PIN_SYS_CLK_REQ_PZ5, +}; + +static const unsigned pmcc_pins[] = { + TEGRA_PIN_CORE_PWR_REQ, +}; + +static const unsigned pmcd_pins[] = { + TEGRA_PIN_CPU_PWR_REQ, +}; + +static const unsigned pmce_pins[] = { + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned xm2c_pins[] = { + TEGRA_PIN_DDR_A0, + TEGRA_PIN_DDR_A1, + TEGRA_PIN_DDR_A2, + TEGRA_PIN_DDR_A3, + TEGRA_PIN_DDR_A4, + TEGRA_PIN_DDR_A5, + TEGRA_PIN_DDR_A6, + TEGRA_PIN_DDR_A7, + TEGRA_PIN_DDR_A8, + TEGRA_PIN_DDR_A9, + TEGRA_PIN_DDR_A10, + TEGRA_PIN_DDR_A11, + TEGRA_PIN_DDR_A12, + TEGRA_PIN_DDR_A13, + TEGRA_PIN_DDR_A14, + TEGRA_PIN_DDR_CAS_N, + TEGRA_PIN_DDR_BA0, + TEGRA_PIN_DDR_BA1, + TEGRA_PIN_DDR_BA2, + TEGRA_PIN_DDR_DQS0P, + TEGRA_PIN_DDR_DQS0N, + TEGRA_PIN_DDR_DQS1P, + TEGRA_PIN_DDR_DQS1N, + TEGRA_PIN_DDR_DQS2P, + TEGRA_PIN_DDR_DQS2N, + TEGRA_PIN_DDR_DQS3P, + TEGRA_PIN_DDR_DQS3N, + TEGRA_PIN_DDR_CS0_N, + TEGRA_PIN_DDR_CS1_N, + TEGRA_PIN_DDR_CKE0, + TEGRA_PIN_DDR_CKE1, + TEGRA_PIN_DDR_CLK, + TEGRA_PIN_DDR_CLK_N, + TEGRA_PIN_DDR_DM0, + TEGRA_PIN_DDR_DM1, + TEGRA_PIN_DDR_DM2, + TEGRA_PIN_DDR_DM3, + TEGRA_PIN_DDR_ODT, + TEGRA_PIN_DDR_RAS_N, + TEGRA_PIN_DDR_WE_N, + TEGRA_PIN_DDR_QUSE0, + TEGRA_PIN_DDR_QUSE1, + TEGRA_PIN_DDR_QUSE2, + TEGRA_PIN_DDR_QUSE3, +}; + +static const unsigned xm2d_pins[] = { + TEGRA_PIN_DDR_DQ0, + TEGRA_PIN_DDR_DQ1, + TEGRA_PIN_DDR_DQ2, + TEGRA_PIN_DDR_DQ3, + TEGRA_PIN_DDR_DQ4, + TEGRA_PIN_DDR_DQ5, + TEGRA_PIN_DDR_DQ6, + TEGRA_PIN_DDR_DQ7, + TEGRA_PIN_DDR_DQ8, + TEGRA_PIN_DDR_DQ9, + TEGRA_PIN_DDR_DQ10, + TEGRA_PIN_DDR_DQ11, + TEGRA_PIN_DDR_DQ12, + TEGRA_PIN_DDR_DQ13, + TEGRA_PIN_DDR_DQ14, + TEGRA_PIN_DDR_DQ15, + TEGRA_PIN_DDR_DQ16, + TEGRA_PIN_DDR_DQ17, + TEGRA_PIN_DDR_DQ18, + TEGRA_PIN_DDR_DQ19, + TEGRA_PIN_DDR_DQ20, + TEGRA_PIN_DDR_DQ21, + TEGRA_PIN_DDR_DQ22, + TEGRA_PIN_DDR_DQ23, + TEGRA_PIN_DDR_DQ24, + TEGRA_PIN_DDR_DQ25, + TEGRA_PIN_DDR_DQ26, + TEGRA_PIN_DDR_DQ27, + TEGRA_PIN_DDR_DQ28, + TEGRA_PIN_DDR_DQ29, + TEGRA_PIN_DDR_DQ30, + TEGRA_PIN_DDR_DQ31, +}; + +static const unsigned drive_ao1_pins[] = { + TEGRA_PIN_SYS_RESET, + TEGRA_PIN_PWR_I2C_SCL_PZ6, + TEGRA_PIN_PWR_I2C_SDA_PZ7, + TEGRA_PIN_KB_ROW0_PR0, + TEGRA_PIN_KB_ROW1_PR1, + TEGRA_PIN_KB_ROW2_PR2, + TEGRA_PIN_KB_ROW3_PR3, + TEGRA_PIN_KB_ROW4_PR4, + TEGRA_PIN_KB_ROW5_PR5, + TEGRA_PIN_KB_ROW6_PR6, + TEGRA_PIN_KB_ROW7_PR7, +}; + +static const unsigned drive_ao2_pins[] = { + TEGRA_PIN_KB_ROW8_PS0, + TEGRA_PIN_KB_ROW9_PS1, + TEGRA_PIN_KB_ROW10_PS2, + TEGRA_PIN_KB_ROW11_PS3, + TEGRA_PIN_KB_ROW12_PS4, + TEGRA_PIN_KB_ROW13_PS5, + TEGRA_PIN_KB_ROW14_PS6, + TEGRA_PIN_KB_ROW15_PS7, + TEGRA_PIN_KB_COL0_PQ0, + TEGRA_PIN_KB_COL1_PQ1, + TEGRA_PIN_KB_COL2_PQ2, + TEGRA_PIN_KB_COL3_PQ3, + TEGRA_PIN_KB_COL4_PQ4, + TEGRA_PIN_KB_COL5_PQ5, + TEGRA_PIN_KB_COL6_PQ6, + TEGRA_PIN_KB_COL7_PQ7, + TEGRA_PIN_LED_BLINK_PBB0, + TEGRA_PIN_SYS_CLK_REQ_PZ5, + TEGRA_PIN_CORE_PWR_REQ, + TEGRA_PIN_CPU_PWR_REQ, + TEGRA_PIN_PWR_INT_N, + TEGRA_PIN_CLK_32_K_IN, +}; + +static const unsigned drive_at1_pins[] = { + TEGRA_PIN_GMI_IORDY_PI5, + TEGRA_PIN_GMI_AD8_PH0, + TEGRA_PIN_GMI_AD9_PH1, + TEGRA_PIN_GMI_AD10_PH2, + TEGRA_PIN_GMI_AD11_PH3, + TEGRA_PIN_GMI_AD12_PH4, + TEGRA_PIN_GMI_AD13_PH5, + TEGRA_PIN_GMI_AD14_PH6, + TEGRA_PIN_GMI_AD15_PH7, + TEGRA_PIN_GMI_CS7_N_PI6, + TEGRA_PIN_GMI_DPD_PT7, + TEGRA_PIN_GEN2_I2C_SCL_PT5, + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned drive_at2_pins[] = { + TEGRA_PIN_GMI_WAIT_PI7, + TEGRA_PIN_GMI_ADV_N_PK0, + TEGRA_PIN_GMI_CLK_PK1, + TEGRA_PIN_GMI_CS6_N_PI3, + TEGRA_PIN_GMI_CS5_N_PI2, + TEGRA_PIN_GMI_CS4_N_PK2, + TEGRA_PIN_GMI_CS3_N_PK4, + TEGRA_PIN_GMI_CS2_N_PK3, + TEGRA_PIN_GMI_AD0_PG0, + TEGRA_PIN_GMI_AD1_PG1, + TEGRA_PIN_GMI_AD2_PG2, + TEGRA_PIN_GMI_AD3_PG3, + TEGRA_PIN_GMI_AD4_PG4, + TEGRA_PIN_GMI_AD5_PG5, + TEGRA_PIN_GMI_AD6_PG6, + TEGRA_PIN_GMI_AD7_PG7, + TEGRA_PIN_GMI_HIOW_N_PI0, + TEGRA_PIN_GMI_HIOR_N_PI1, + TEGRA_PIN_GMI_RST_N_PI4, +}; + +static const unsigned drive_cdev1_pins[] = { + TEGRA_PIN_DAP_MCLK1_PW4, +}; + +static const unsigned drive_cdev2_pins[] = { + TEGRA_PIN_DAP_MCLK2_PW5, +}; + +static const unsigned drive_csus_pins[] = { + TEGRA_PIN_VI_MCLK_PT1, +}; + +static const unsigned drive_dap1_pins[] = { + TEGRA_PIN_DAP1_FS_PN0, + TEGRA_PIN_DAP1_DIN_PN1, + TEGRA_PIN_DAP1_DOUT_PN2, + TEGRA_PIN_DAP1_SCLK_PN3, + TEGRA_PIN_SPDIF_OUT_PK5, + TEGRA_PIN_SPDIF_IN_PK6, +}; + +static const unsigned drive_dap2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, + TEGRA_PIN_DAP2_SCLK_PA3, + TEGRA_PIN_DAP2_DIN_PA4, + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned drive_dap3_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, + TEGRA_PIN_DAP3_DIN_PP1, + TEGRA_PIN_DAP3_DOUT_PP2, + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned drive_dap4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, + TEGRA_PIN_DAP4_DIN_PP5, + TEGRA_PIN_DAP4_DOUT_PP6, + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned drive_dbg_pins[] = { + TEGRA_PIN_PU0, + TEGRA_PIN_PU1, + TEGRA_PIN_PU2, + TEGRA_PIN_PU3, + TEGRA_PIN_PU4, + TEGRA_PIN_PU5, + TEGRA_PIN_PU6, + TEGRA_PIN_JTAG_RTCK_PU7, + TEGRA_PIN_GEN1_I2C_SDA_PC5, + TEGRA_PIN_GEN1_I2C_SCL_PC4, + TEGRA_PIN_JTAG_TRST_N, + TEGRA_PIN_JTAG_TDO, + TEGRA_PIN_JTAG_TMS, + TEGRA_PIN_JTAG_TCK, + TEGRA_PIN_JTAG_TDI, + TEGRA_PIN_TEST_MODE_EN, +}; + +static const unsigned drive_lcd1_pins[] = { + TEGRA_PIN_LCD_PWR1_PC1, + TEGRA_PIN_LCD_PWR2_PC6, + TEGRA_PIN_LCD_SDIN_PZ2, + TEGRA_PIN_LCD_SDOUT_PN5, + TEGRA_PIN_LCD_WR_N_PZ3, + TEGRA_PIN_LCD_CS0_N_PN4, + TEGRA_PIN_LCD_DC0_PN6, + TEGRA_PIN_LCD_SCK_PZ4, +}; + +static const unsigned drive_lcd2_pins[] = { + TEGRA_PIN_LCD_PWR0_PB2, + TEGRA_PIN_LCD_PCLK_PB3, + TEGRA_PIN_LCD_DE_PJ1, + TEGRA_PIN_LCD_HSYNC_PJ3, + TEGRA_PIN_LCD_VSYNC_PJ4, + TEGRA_PIN_LCD_D0_PE0, + TEGRA_PIN_LCD_D1_PE1, + TEGRA_PIN_LCD_D2_PE2, + TEGRA_PIN_LCD_D3_PE3, + TEGRA_PIN_LCD_D4_PE4, + TEGRA_PIN_LCD_D5_PE5, + TEGRA_PIN_LCD_D6_PE6, + TEGRA_PIN_LCD_D7_PE7, + TEGRA_PIN_LCD_D8_PF0, + TEGRA_PIN_LCD_D9_PF1, + TEGRA_PIN_LCD_D10_PF2, + TEGRA_PIN_LCD_D11_PF3, + TEGRA_PIN_LCD_D12_PF4, + TEGRA_PIN_LCD_D13_PF5, + TEGRA_PIN_LCD_D14_PF6, + TEGRA_PIN_LCD_D15_PF7, + TEGRA_PIN_LCD_D16_PM0, + TEGRA_PIN_LCD_D17_PM1, + TEGRA_PIN_LCD_D18_PM2, + TEGRA_PIN_LCD_D19_PM3, + TEGRA_PIN_LCD_D20_PM4, + TEGRA_PIN_LCD_D21_PM5, + TEGRA_PIN_LCD_D22_PM6, + TEGRA_PIN_LCD_D23_PM7, + TEGRA_PIN_LCD_CS1_N_PW0, + TEGRA_PIN_LCD_M1_PW1, + TEGRA_PIN_LCD_DC1_PV7, + TEGRA_PIN_HDMI_INT_N_PN7, +}; + +static const unsigned drive_sdmmc2_pins[] = { + TEGRA_PIN_SDIO3_DAT4_PD1, + TEGRA_PIN_SDIO3_DAT5_PD0, + TEGRA_PIN_SDIO3_DAT6_PD3, + TEGRA_PIN_SDIO3_DAT7_PD4, +}; + +static const unsigned drive_sdmmc3_pins[] = { + TEGRA_PIN_SDIO3_CLK_PA6, + TEGRA_PIN_SDIO3_CMD_PA7, + TEGRA_PIN_SDIO3_DAT0_PB7, + TEGRA_PIN_SDIO3_DAT1_PB6, + TEGRA_PIN_SDIO3_DAT2_PB5, + TEGRA_PIN_SDIO3_DAT3_PB4, + TEGRA_PIN_PV4, + TEGRA_PIN_PV5, + TEGRA_PIN_PV6, +}; + +static const unsigned drive_spi_pins[] = { + TEGRA_PIN_SPI2_MOSI_PX0, + TEGRA_PIN_SPI2_MISO_PX1, + TEGRA_PIN_SPI2_SCK_PX2, + TEGRA_PIN_SPI2_CS0_N_PX3, + TEGRA_PIN_SPI1_MOSI_PX4, + TEGRA_PIN_SPI1_SCK_PX5, + TEGRA_PIN_SPI1_CS0_N_PX6, + TEGRA_PIN_SPI1_MISO_PX7, + TEGRA_PIN_SPI2_CS1_N_PW2, + TEGRA_PIN_SPI2_CS2_N_PW3, +}; + +static const unsigned drive_uaa_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, + TEGRA_PIN_ULPI_DATA1_PO2, + TEGRA_PIN_ULPI_DATA2_PO3, + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned drive_uab_pins[] = { + TEGRA_PIN_ULPI_DATA4_PO5, + TEGRA_PIN_ULPI_DATA5_PO6, + TEGRA_PIN_ULPI_DATA6_PO7, + TEGRA_PIN_ULPI_DATA7_PO0, + TEGRA_PIN_PV0, + TEGRA_PIN_PV1, + TEGRA_PIN_PV2, + TEGRA_PIN_PV3, +}; + +static const unsigned drive_uart2_pins[] = { + TEGRA_PIN_UART2_TXD_PC2, + TEGRA_PIN_UART2_RXD_PC3, + TEGRA_PIN_UART2_RTS_N_PJ6, + TEGRA_PIN_UART2_CTS_N_PJ5, +}; + +static const unsigned drive_uart3_pins[] = { + TEGRA_PIN_UART3_TXD_PW6, + TEGRA_PIN_UART3_RXD_PW7, + TEGRA_PIN_UART3_RTS_N_PC0, + TEGRA_PIN_UART3_CTS_N_PA1, +}; + +static const unsigned drive_vi1_pins[] = { + TEGRA_PIN_VI_D0_PT4, + TEGRA_PIN_VI_D1_PD5, + TEGRA_PIN_VI_D2_PL0, + TEGRA_PIN_VI_D3_PL1, + TEGRA_PIN_VI_D4_PL2, + TEGRA_PIN_VI_D5_PL3, + TEGRA_PIN_VI_D6_PL4, + TEGRA_PIN_VI_D7_PL5, + TEGRA_PIN_VI_D8_PL6, + TEGRA_PIN_VI_D9_PL7, + TEGRA_PIN_VI_D10_PT2, + TEGRA_PIN_VI_D11_PT3, + TEGRA_PIN_VI_PCLK_PT0, + TEGRA_PIN_VI_VSYNC_PD6, + TEGRA_PIN_VI_HSYNC_PD7, +}; + +static const unsigned drive_vi2_pins[] = { + TEGRA_PIN_VI_GP0_PBB1, + TEGRA_PIN_CAM_I2C_SCL_PBB2, + TEGRA_PIN_CAM_I2C_SDA_PBB3, + TEGRA_PIN_VI_GP3_PBB4, + TEGRA_PIN_VI_GP4_PBB5, + TEGRA_PIN_VI_GP5_PD2, + TEGRA_PIN_VI_GP6_PA0, +}; + +static const unsigned drive_xm2a_pins[] = { + TEGRA_PIN_DDR_A0, + TEGRA_PIN_DDR_A1, + TEGRA_PIN_DDR_A2, + TEGRA_PIN_DDR_A3, + TEGRA_PIN_DDR_A4, + TEGRA_PIN_DDR_A5, + TEGRA_PIN_DDR_A6, + TEGRA_PIN_DDR_A7, + TEGRA_PIN_DDR_A8, + TEGRA_PIN_DDR_A9, + TEGRA_PIN_DDR_A10, + TEGRA_PIN_DDR_A11, + TEGRA_PIN_DDR_A12, + TEGRA_PIN_DDR_A13, + TEGRA_PIN_DDR_A14, + TEGRA_PIN_DDR_BA0, + TEGRA_PIN_DDR_BA1, + TEGRA_PIN_DDR_BA2, + TEGRA_PIN_DDR_CS0_N, + TEGRA_PIN_DDR_CS1_N, + TEGRA_PIN_DDR_ODT, + TEGRA_PIN_DDR_RAS_N, + TEGRA_PIN_DDR_CAS_N, + TEGRA_PIN_DDR_WE_N, + TEGRA_PIN_DDR_CKE0, + TEGRA_PIN_DDR_CKE1, +}; + +static const unsigned drive_xm2c_pins[] = { + TEGRA_PIN_DDR_DQS0P, + TEGRA_PIN_DDR_DQS0N, + TEGRA_PIN_DDR_DQS1P, + TEGRA_PIN_DDR_DQS1N, + TEGRA_PIN_DDR_DQS2P, + TEGRA_PIN_DDR_DQS2N, + TEGRA_PIN_DDR_DQS3P, + TEGRA_PIN_DDR_DQS3N, + TEGRA_PIN_DDR_QUSE0, + TEGRA_PIN_DDR_QUSE1, + TEGRA_PIN_DDR_QUSE2, + TEGRA_PIN_DDR_QUSE3, +}; + +static const unsigned drive_xm2d_pins[] = { + TEGRA_PIN_DDR_DQ0, + TEGRA_PIN_DDR_DQ1, + TEGRA_PIN_DDR_DQ2, + TEGRA_PIN_DDR_DQ3, + TEGRA_PIN_DDR_DQ4, + TEGRA_PIN_DDR_DQ5, + TEGRA_PIN_DDR_DQ6, + TEGRA_PIN_DDR_DQ7, + TEGRA_PIN_DDR_DQ8, + TEGRA_PIN_DDR_DQ9, + TEGRA_PIN_DDR_DQ10, + TEGRA_PIN_DDR_DQ11, + TEGRA_PIN_DDR_DQ12, + TEGRA_PIN_DDR_DQ13, + TEGRA_PIN_DDR_DQ14, + TEGRA_PIN_DDR_DQ15, + TEGRA_PIN_DDR_DQ16, + TEGRA_PIN_DDR_DQ17, + TEGRA_PIN_DDR_DQ18, + TEGRA_PIN_DDR_DQ19, + TEGRA_PIN_DDR_DQ20, + TEGRA_PIN_DDR_DQ21, + TEGRA_PIN_DDR_DQ22, + TEGRA_PIN_DDR_DQ23, + TEGRA_PIN_DDR_DQ24, + TEGRA_PIN_DDR_DQ25, + TEGRA_PIN_DDR_DQ26, + TEGRA_PIN_DDR_DQ27, + TEGRA_PIN_DDR_DQ28, + TEGRA_PIN_DDR_DQ29, + TEGRA_PIN_DDR_DQ30, + TEGRA_PIN_DDR_DQ31, + TEGRA_PIN_DDR_DM0, + TEGRA_PIN_DDR_DM1, + TEGRA_PIN_DDR_DM2, + TEGRA_PIN_DDR_DM3, +}; + +static const unsigned drive_xm2clk_pins[] = { + TEGRA_PIN_DDR_CLK, + TEGRA_PIN_DDR_CLK_N, +}; + +static const unsigned drive_sdio1_pins[] = { + TEGRA_PIN_SDIO1_CLK_PZ0, + TEGRA_PIN_SDIO1_CMD_PZ1, + TEGRA_PIN_SDIO1_DAT0_PY7, + TEGRA_PIN_SDIO1_DAT1_PY6, + TEGRA_PIN_SDIO1_DAT2_PY5, + TEGRA_PIN_SDIO1_DAT3_PY4, +}; + +static const unsigned drive_crt_pins[] = { + TEGRA_PIN_CRT_HSYNC, + TEGRA_PIN_CRT_VSYNC, +}; + +static const unsigned drive_ddc_pins[] = { + TEGRA_PIN_DDC_SCL, + TEGRA_PIN_DDC_SDA, +}; + +static const unsigned drive_gma_pins[] = { + TEGRA_PIN_GMI_AD20_PAA0, + TEGRA_PIN_GMI_AD21_PAA1, + TEGRA_PIN_GMI_AD22_PAA2, + TEGRA_PIN_GMI_AD23_PAA3, +}; + +static const unsigned drive_gmb_pins[] = { + TEGRA_PIN_GMI_WP_N_PC7, +}; + +static const unsigned drive_gmc_pins[] = { + TEGRA_PIN_GMI_AD16_PJ7, + TEGRA_PIN_GMI_AD17_PB0, + TEGRA_PIN_GMI_AD18_PB1, + TEGRA_PIN_GMI_AD19_PK7, +}; + +static const unsigned drive_gmd_pins[] = { + TEGRA_PIN_GMI_CS0_N_PJ0, + TEGRA_PIN_GMI_CS1_N_PJ2, +}; + +static const unsigned drive_gme_pins[] = { + TEGRA_PIN_GMI_AD24_PAA4, + TEGRA_PIN_GMI_AD25_PAA5, + TEGRA_PIN_GMI_AD26_PAA6, + TEGRA_PIN_GMI_AD27_PAA7, +}; + +static const unsigned drive_owr_pins[] = { + TEGRA_PIN_OWC, +}; + +static const unsigned drive_uda_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, + TEGRA_PIN_ULPI_DIR_PY1, + TEGRA_PIN_ULPI_NXT_PY2, + TEGRA_PIN_ULPI_STP_PY3, +}; + +enum tegra_mux { + TEGRA_MUX_AHB_CLK, + TEGRA_MUX_APB_CLK, + TEGRA_MUX_AUDIO_SYNC, + TEGRA_MUX_CRT, + TEGRA_MUX_DAP1, + TEGRA_MUX_DAP2, + TEGRA_MUX_DAP3, + TEGRA_MUX_DAP4, + TEGRA_MUX_DAP5, + TEGRA_MUX_DISPLAYA, + TEGRA_MUX_DISPLAYB, + TEGRA_MUX_EMC_TEST0_DLL, + TEGRA_MUX_EMC_TEST1_DLL, + TEGRA_MUX_GMI, + TEGRA_MUX_GMI_INT, + TEGRA_MUX_HDMI, + TEGRA_MUX_I2CP, + TEGRA_MUX_I2C1, + TEGRA_MUX_I2C2, + TEGRA_MUX_I2C3, + TEGRA_MUX_IDE, + TEGRA_MUX_IRDA, + TEGRA_MUX_KBC, + TEGRA_MUX_MIO, + TEGRA_MUX_MIPI_HS, + TEGRA_MUX_NAND, + TEGRA_MUX_OSC, + TEGRA_MUX_OWR, + TEGRA_MUX_PCIE, + TEGRA_MUX_PLLA_OUT, + TEGRA_MUX_PLLC_OUT1, + TEGRA_MUX_PLLM_OUT1, + TEGRA_MUX_PLLP_OUT2, + TEGRA_MUX_PLLP_OUT3, + TEGRA_MUX_PLLP_OUT4, + TEGRA_MUX_PWM, + TEGRA_MUX_PWR_INTR, + TEGRA_MUX_PWR_ON, + TEGRA_MUX_RSVD1, + TEGRA_MUX_RSVD2, + TEGRA_MUX_RSVD3, + TEGRA_MUX_RSVD4, + TEGRA_MUX_RTCK, + TEGRA_MUX_SDIO1, + TEGRA_MUX_SDIO2, + TEGRA_MUX_SDIO3, + TEGRA_MUX_SDIO4, + TEGRA_MUX_SFLASH, + TEGRA_MUX_SPDIF, + TEGRA_MUX_SPI1, + TEGRA_MUX_SPI2, + TEGRA_MUX_SPI2_ALT, + TEGRA_MUX_SPI3, + TEGRA_MUX_SPI4, + TEGRA_MUX_TRACE, + TEGRA_MUX_TWC, + TEGRA_MUX_UARTA, + TEGRA_MUX_UARTB, + TEGRA_MUX_UARTC, + TEGRA_MUX_UARTD, + TEGRA_MUX_UARTE, + TEGRA_MUX_ULPI, + TEGRA_MUX_VI, + TEGRA_MUX_VI_SENSOR_CLK, + TEGRA_MUX_XIO, +}; + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + } + +static struct tegra_function tegra20_functions[] = { + FUNCTION(ahb_clk), + FUNCTION(apb_clk), + FUNCTION(audio_sync), + FUNCTION(crt), + FUNCTION(dap1), + FUNCTION(dap2), + FUNCTION(dap3), + FUNCTION(dap4), + FUNCTION(dap5), + FUNCTION(displaya), + FUNCTION(displayb), + FUNCTION(emc_test0_dll), + FUNCTION(emc_test1_dll), + FUNCTION(gmi), + FUNCTION(gmi_int), + FUNCTION(hdmi), + FUNCTION(i2cp), + FUNCTION(i2c1), + FUNCTION(i2c2), + FUNCTION(i2c3), + FUNCTION(ide), + FUNCTION(irda), + FUNCTION(kbc), + FUNCTION(mio), + FUNCTION(mipi_hs), + FUNCTION(nand), + FUNCTION(osc), + FUNCTION(owr), + FUNCTION(pcie), + FUNCTION(plla_out), + FUNCTION(pllc_out1), + FUNCTION(pllm_out1), + FUNCTION(pllp_out2), + FUNCTION(pllp_out3), + FUNCTION(pllp_out4), + FUNCTION(pwm), + FUNCTION(pwr_intr), + FUNCTION(pwr_on), + FUNCTION(rsvd1), + FUNCTION(rsvd2), + FUNCTION(rsvd3), + FUNCTION(rsvd4), + FUNCTION(rtck), + FUNCTION(sdio1), + FUNCTION(sdio2), + FUNCTION(sdio3), + FUNCTION(sdio4), + FUNCTION(sflash), + FUNCTION(spdif), + FUNCTION(spi1), + FUNCTION(spi2), + FUNCTION(spi2_alt), + FUNCTION(spi3), + FUNCTION(spi4), + FUNCTION(trace), + FUNCTION(twc), + FUNCTION(uarta), + FUNCTION(uartb), + FUNCTION(uartc), + FUNCTION(uartd), + FUNCTION(uarte), + FUNCTION(ulpi), + FUNCTION(vi), + FUNCTION(vi_sensor_clk), + FUNCTION(xio), +}; + +#define TRISTATE_REG_A 0x14 +#define PIN_MUX_CTL_REG_A 0x80 +#define PULLUPDOWN_REG_A 0xa0 +#define PINGROUP_REG_A 0x868 + +/* Pin group with mux control, and typically tri-state and pull-up/down too */ +#define MUX_PG(pg_name, f0, f1, f2, f3, \ + tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_ ## f0, \ + TEGRA_MUX_ ## f1, \ + TEGRA_MUX_ ## f2, \ + TEGRA_MUX_ ## f3, \ + }, \ + .mux_reg = ((mux_r) - PIN_MUX_CTL_REG_A), \ + .mux_bank = 1, \ + .mux_bit = mux_b, \ + .pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A), \ + .pupd_bank = 2, \ + .pupd_bit = pupd_b, \ + .tri_reg = ((tri_r) - TRISTATE_REG_A), \ + .tri_bank = 0, \ + .tri_bit = tri_b, \ + .einput_bit = -1, \ + .odrain_bit = -1, \ + .lock_bit = -1, \ + .ioreset_bit = -1, \ + .rcv_sel_bit = -1, \ + .drv_reg = -1, \ + } + +/* Pin groups with only pull up and pull down control */ +#define PULL_PG(pg_name, pupd_r, pupd_b) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .mux_reg = -1, \ + .pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A), \ + .pupd_bank = 2, \ + .pupd_bit = pupd_b, \ + .drv_reg = -1, \ + } + +/* Pin groups for drive strength registers (configurable version) */ +#define DRV_PG_EXT(pg_name, r, hsm_b, schmitt_b, lpmd_b, \ + drvdn_b, drvup_b, \ + slwr_b, slwr_w, slwf_b, slwf_w) \ + { \ + .name = "drive_" #pg_name, \ + .pins = drive_##pg_name##_pins, \ + .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ + .mux_reg = -1, \ + .pupd_reg = -1, \ + .tri_reg = -1, \ + .drv_reg = ((r) - PINGROUP_REG_A), \ + .drv_bank = 3, \ + .hsm_bit = hsm_b, \ + .schmitt_bit = schmitt_b, \ + .lpmd_bit = lpmd_b, \ + .drvdn_bit = drvdn_b, \ + .drvdn_width = 5, \ + .drvup_bit = drvup_b, \ + .drvup_width = 5, \ + .slwr_bit = slwr_b, \ + .slwr_width = slwr_w, \ + .slwf_bit = slwf_b, \ + .slwf_width = slwf_w, \ + .drvtype_bit = -1, \ + } + +/* Pin groups for drive strength registers (simple version) */ +#define DRV_PG(pg_name, r) \ + DRV_PG_EXT(pg_name, r, 2, 3, 4, 12, 20, 28, 2, 30, 2) + +static const struct tegra_pingroup tegra20_groups[] = { + /* name, f0, f1, f2, f3, tri r/b, mux r/b, pupd r/b */ + MUX_PG(ata, IDE, NAND, GMI, RSVD4, 0x14, 0, 0x80, 24, 0xa0, 0), + MUX_PG(atb, IDE, NAND, GMI, SDIO4, 0x14, 1, 0x80, 16, 0xa0, 2), + MUX_PG(atc, IDE, NAND, GMI, SDIO4, 0x14, 2, 0x80, 22, 0xa0, 4), + MUX_PG(atd, IDE, NAND, GMI, SDIO4, 0x14, 3, 0x80, 20, 0xa0, 6), + MUX_PG(ate, IDE, NAND, GMI, RSVD4, 0x18, 25, 0x80, 12, 0xa0, 8), + MUX_PG(cdev1, OSC, PLLA_OUT, PLLM_OUT1, AUDIO_SYNC, 0x14, 4, 0x88, 2, 0xa8, 0), + MUX_PG(cdev2, OSC, AHB_CLK, APB_CLK, PLLP_OUT4, 0x14, 5, 0x88, 4, 0xa8, 2), + MUX_PG(crtp, CRT, RSVD2, RSVD3, RSVD4, 0x20, 14, 0x98, 20, 0xa4, 24), + MUX_PG(csus, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, 0x14, 6, 0x88, 6, 0xac, 24), + MUX_PG(dap1, DAP1, RSVD2, GMI, SDIO2, 0x14, 7, 0x88, 20, 0xa0, 10), + MUX_PG(dap2, DAP2, TWC, RSVD3, GMI, 0x14, 8, 0x88, 22, 0xa0, 12), + MUX_PG(dap3, DAP3, RSVD2, RSVD3, RSVD4, 0x14, 9, 0x88, 24, 0xa0, 14), + MUX_PG(dap4, DAP4, RSVD2, GMI, RSVD4, 0x14, 10, 0x88, 26, 0xa0, 16), + MUX_PG(ddc, I2C2, RSVD2, RSVD3, RSVD4, 0x18, 31, 0x88, 0, 0xb0, 28), + MUX_PG(dta, RSVD1, SDIO2, VI, RSVD4, 0x14, 11, 0x84, 20, 0xa0, 18), + MUX_PG(dtb, RSVD1, RSVD2, VI, SPI1, 0x14, 12, 0x84, 22, 0xa0, 20), + MUX_PG(dtc, RSVD1, RSVD2, VI, RSVD4, 0x14, 13, 0x84, 26, 0xa0, 22), + MUX_PG(dtd, RSVD1, SDIO2, VI, RSVD4, 0x14, 14, 0x84, 28, 0xa0, 24), + MUX_PG(dte, RSVD1, RSVD2, VI, SPI1, 0x14, 15, 0x84, 30, 0xa0, 26), + MUX_PG(dtf, I2C3, RSVD2, VI, RSVD4, 0x20, 12, 0x98, 30, 0xa0, 28), + MUX_PG(gma, UARTE, SPI3, GMI, SDIO4, 0x14, 28, 0x84, 0, 0xb0, 20), + MUX_PG(gmb, IDE, NAND, GMI, GMI_INT, 0x18, 29, 0x88, 28, 0xb0, 22), + MUX_PG(gmc, UARTD, SPI4, GMI, SFLASH, 0x14, 29, 0x84, 2, 0xb0, 24), + MUX_PG(gmd, RSVD1, NAND, GMI, SFLASH, 0x18, 30, 0x88, 30, 0xb0, 26), + MUX_PG(gme, RSVD1, DAP5, GMI, SDIO4, 0x18, 0, 0x8c, 0, 0xa8, 24), + MUX_PG(gpu, PWM, UARTA, GMI, RSVD4, 0x14, 16, 0x8c, 4, 0xa4, 20), + MUX_PG(gpu7, RTCK, RSVD2, RSVD3, RSVD4, 0x20, 11, 0x98, 28, 0xa4, 6), + MUX_PG(gpv, PCIE, RSVD2, RSVD3, RSVD4, 0x14, 17, 0x8c, 2, 0xa0, 30), + MUX_PG(hdint, HDMI, RSVD2, RSVD3, RSVD4, 0x1c, 23, 0x84, 4, -1, -1), + MUX_PG(i2cp, I2CP, RSVD2, RSVD3, RSVD4, 0x14, 18, 0x88, 8, 0xa4, 2), + MUX_PG(irrx, UARTA, UARTB, GMI, SPI4, 0x14, 20, 0x88, 18, 0xa8, 22), + MUX_PG(irtx, UARTA, UARTB, GMI, SPI4, 0x14, 19, 0x88, 16, 0xa8, 20), + MUX_PG(kbca, KBC, NAND, SDIO2, EMC_TEST0_DLL, 0x14, 22, 0x88, 10, 0xa4, 8), + MUX_PG(kbcb, KBC, NAND, SDIO2, MIO, 0x14, 21, 0x88, 12, 0xa4, 10), + MUX_PG(kbcc, KBC, NAND, TRACE, EMC_TEST1_DLL, 0x18, 26, 0x88, 14, 0xa4, 12), + MUX_PG(kbcd, KBC, NAND, SDIO2, MIO, 0x20, 10, 0x98, 26, 0xa4, 14), + MUX_PG(kbce, KBC, NAND, OWR, RSVD4, 0x14, 26, 0x80, 28, 0xb0, 2), + MUX_PG(kbcf, KBC, NAND, TRACE, MIO, 0x14, 27, 0x80, 26, 0xb0, 0), + MUX_PG(lcsn, DISPLAYA, DISPLAYB, SPI3, RSVD4, 0x1c, 31, 0x90, 12, -1, -1), + MUX_PG(ld0, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 0, 0x94, 0, -1, -1), + MUX_PG(ld1, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 1, 0x94, 2, -1, -1), + MUX_PG(ld2, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 2, 0x94, 4, -1, -1), + MUX_PG(ld3, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 3, 0x94, 6, -1, -1), + MUX_PG(ld4, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 4, 0x94, 8, -1, -1), + MUX_PG(ld5, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 5, 0x94, 10, -1, -1), + MUX_PG(ld6, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 6, 0x94, 12, -1, -1), + MUX_PG(ld7, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 7, 0x94, 14, -1, -1), + MUX_PG(ld8, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 8, 0x94, 16, -1, -1), + MUX_PG(ld9, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 9, 0x94, 18, -1, -1), + MUX_PG(ld10, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 10, 0x94, 20, -1, -1), + MUX_PG(ld11, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 11, 0x94, 22, -1, -1), + MUX_PG(ld12, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 12, 0x94, 24, -1, -1), + MUX_PG(ld13, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 13, 0x94, 26, -1, -1), + MUX_PG(ld14, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 14, 0x94, 28, -1, -1), + MUX_PG(ld15, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 15, 0x94, 30, -1, -1), + MUX_PG(ld16, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 16, 0x98, 0, -1, -1), + MUX_PG(ld17, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 17, 0x98, 2, -1, -1), + MUX_PG(ldc, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 30, 0x90, 14, -1, -1), + MUX_PG(ldi, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x20, 6, 0x98, 16, -1, -1), + MUX_PG(lhp0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 18, 0x98, 10, -1, -1), + MUX_PG(lhp1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 19, 0x98, 4, -1, -1), + MUX_PG(lhp2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 20, 0x98, 6, -1, -1), + MUX_PG(lhs, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x20, 7, 0x90, 22, -1, -1), + MUX_PG(lm0, DISPLAYA, DISPLAYB, SPI3, RSVD4, 0x1c, 24, 0x90, 26, -1, -1), + MUX_PG(lm1, DISPLAYA, DISPLAYB, RSVD3, CRT, 0x1c, 25, 0x90, 28, -1, -1), + MUX_PG(lpp, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x20, 8, 0x98, 14, -1, -1), + MUX_PG(lpw0, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x20, 3, 0x90, 0, -1, -1), + MUX_PG(lpw1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x20, 4, 0x90, 2, -1, -1), + MUX_PG(lpw2, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x20, 5, 0x90, 4, -1, -1), + MUX_PG(lsc0, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 27, 0x90, 18, -1, -1), + MUX_PG(lsc1, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x1c, 28, 0x90, 20, -1, -1), + MUX_PG(lsck, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x1c, 29, 0x90, 16, -1, -1), + MUX_PG(lsda, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x20, 1, 0x90, 8, -1, -1), + MUX_PG(lsdi, DISPLAYA, DISPLAYB, SPI3, RSVD4, 0x20, 2, 0x90, 6, -1, -1), + MUX_PG(lspi, DISPLAYA, DISPLAYB, XIO, HDMI, 0x20, 0, 0x90, 10, -1, -1), + MUX_PG(lvp0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 21, 0x90, 30, -1, -1), + MUX_PG(lvp1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 22, 0x98, 8, -1, -1), + MUX_PG(lvs, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 26, 0x90, 24, -1, -1), + MUX_PG(owc, OWR, RSVD2, RSVD3, RSVD4, 0x14, 31, 0x84, 8, 0xb0, 30), + MUX_PG(pmc, PWR_ON, PWR_INTR, RSVD3, RSVD4, 0x14, 23, 0x98, 18, -1, -1), + MUX_PG(pta, I2C2, HDMI, GMI, RSVD4, 0x14, 24, 0x98, 22, 0xa4, 4), + MUX_PG(rm, I2C1, RSVD2, RSVD3, RSVD4, 0x14, 25, 0x80, 14, 0xa4, 0), + MUX_PG(sdb, UARTA, PWM, SDIO3, SPI2, 0x20, 15, 0x8c, 10, -1, -1), + MUX_PG(sdc, PWM, TWC, SDIO3, SPI3, 0x18, 1, 0x8c, 12, 0xac, 28), + MUX_PG(sdd, UARTA, PWM, SDIO3, SPI3, 0x18, 2, 0x8c, 14, 0xac, 30), + MUX_PG(sdio1, SDIO1, RSVD2, UARTE, UARTA, 0x14, 30, 0x80, 30, 0xb0, 18), + MUX_PG(slxa, PCIE, SPI4, SDIO3, SPI2, 0x18, 3, 0x84, 6, 0xa4, 22), + MUX_PG(slxc, SPDIF, SPI4, SDIO3, SPI2, 0x18, 5, 0x84, 10, 0xa4, 26), + MUX_PG(slxd, SPDIF, SPI4, SDIO3, SPI2, 0x18, 6, 0x84, 12, 0xa4, 28), + MUX_PG(slxk, PCIE, SPI4, SDIO3, SPI2, 0x18, 7, 0x84, 14, 0xa4, 30), + MUX_PG(spdi, SPDIF, RSVD2, I2C1, SDIO2, 0x18, 8, 0x8c, 8, 0xa4, 16), + MUX_PG(spdo, SPDIF, RSVD2, I2C1, SDIO2, 0x18, 9, 0x8c, 6, 0xa4, 18), + MUX_PG(spia, SPI1, SPI2, SPI3, GMI, 0x18, 10, 0x8c, 30, 0xa8, 4), + MUX_PG(spib, SPI1, SPI2, SPI3, GMI, 0x18, 11, 0x8c, 28, 0xa8, 6), + MUX_PG(spic, SPI1, SPI2, SPI3, GMI, 0x18, 12, 0x8c, 26, 0xa8, 8), + MUX_PG(spid, SPI2, SPI1, SPI2_ALT, GMI, 0x18, 13, 0x8c, 24, 0xa8, 10), + MUX_PG(spie, SPI2, SPI1, SPI2_ALT, GMI, 0x18, 14, 0x8c, 22, 0xa8, 12), + MUX_PG(spif, SPI3, SPI1, SPI2, RSVD4, 0x18, 15, 0x8c, 20, 0xa8, 14), + MUX_PG(spig, SPI3, SPI2, SPI2_ALT, I2C1, 0x18, 16, 0x8c, 18, 0xa8, 16), + MUX_PG(spih, SPI3, SPI2, SPI2_ALT, I2C1, 0x18, 17, 0x8c, 16, 0xa8, 18), + MUX_PG(uaa, SPI3, MIPI_HS, UARTA, ULPI, 0x18, 18, 0x80, 0, 0xac, 0), + MUX_PG(uab, SPI2, MIPI_HS, UARTA, ULPI, 0x18, 19, 0x80, 2, 0xac, 2), + MUX_PG(uac, OWR, RSVD2, RSVD3, RSVD4, 0x18, 20, 0x80, 4, 0xac, 4), + MUX_PG(uad, IRDA, SPDIF, UARTA, SPI4, 0x18, 21, 0x80, 6, 0xac, 6), + MUX_PG(uca, UARTC, RSVD2, GMI, RSVD4, 0x18, 22, 0x84, 16, 0xac, 8), + MUX_PG(ucb, UARTC, PWM, GMI, RSVD4, 0x18, 23, 0x84, 18, 0xac, 10), + MUX_PG(uda, SPI1, RSVD2, UARTD, ULPI, 0x20, 13, 0x80, 8, 0xb0, 16), + /* pg_name, pupd_r/b */ + PULL_PG(ck32, 0xb0, 14), + PULL_PG(ddrc, 0xac, 26), + PULL_PG(pmca, 0xb0, 4), + PULL_PG(pmcb, 0xb0, 6), + PULL_PG(pmcc, 0xb0, 8), + PULL_PG(pmcd, 0xb0, 10), + PULL_PG(pmce, 0xb0, 12), + PULL_PG(xm2c, 0xa8, 30), + PULL_PG(xm2d, 0xa8, 28), + PULL_PG(ls, 0xac, 20), + PULL_PG(lc, 0xac, 22), + PULL_PG(ld17_0, 0xac, 12), + PULL_PG(ld19_18, 0xac, 14), + PULL_PG(ld21_20, 0xac, 16), + PULL_PG(ld23_22, 0xac, 18), + /* pg_name, r */ + DRV_PG(ao1, 0x868), + DRV_PG(ao2, 0x86c), + DRV_PG(at1, 0x870), + DRV_PG(at2, 0x874), + DRV_PG(cdev1, 0x878), + DRV_PG(cdev2, 0x87c), + DRV_PG(csus, 0x880), + DRV_PG(dap1, 0x884), + DRV_PG(dap2, 0x888), + DRV_PG(dap3, 0x88c), + DRV_PG(dap4, 0x890), + DRV_PG(dbg, 0x894), + DRV_PG(lcd1, 0x898), + DRV_PG(lcd2, 0x89c), + DRV_PG(sdmmc2, 0x8a0), + DRV_PG(sdmmc3, 0x8a4), + DRV_PG(spi, 0x8a8), + DRV_PG(uaa, 0x8ac), + DRV_PG(uab, 0x8b0), + DRV_PG(uart2, 0x8b4), + DRV_PG(uart3, 0x8b8), + DRV_PG(vi1, 0x8bc), + DRV_PG(vi2, 0x8c0), + /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvup_b, slwr_b, slwr_w, slwf_b, slwf_w */ + DRV_PG_EXT(xm2a, 0x8c4, -1, -1, 4, 14, 19, 24, 4, 28, 4), + DRV_PG_EXT(xm2c, 0x8c8, -1, 3, -1, 14, 19, 24, 4, 28, 4), + DRV_PG_EXT(xm2d, 0x8cc, -1, 3, -1, 14, 19, 24, 4, 28, 4), + DRV_PG_EXT(xm2clk, 0x8d0, -1, -1, -1, 14, 19, 24, 4, 28, 4), + /* pg_name, r */ + DRV_PG(sdio1, 0x8e0), + DRV_PG(crt, 0x8ec), + DRV_PG(ddc, 0x8f0), + DRV_PG(gma, 0x8f4), + DRV_PG(gmb, 0x8f8), + DRV_PG(gmc, 0x8fc), + DRV_PG(gmd, 0x900), + DRV_PG(gme, 0x904), + DRV_PG(owr, 0x908), + DRV_PG(uda, 0x90c), +}; + +static const struct tegra_pinctrl_soc_data tegra20_pinctrl = { + .ngpios = NUM_GPIOS, + .pins = tegra20_pins, + .npins = ARRAY_SIZE(tegra20_pins), + .functions = tegra20_functions, + .nfunctions = ARRAY_SIZE(tegra20_functions), + .groups = tegra20_groups, + .ngroups = ARRAY_SIZE(tegra20_groups), + .hsm_in_mux = false, + .schmitt_in_mux = false, + .drvtype_in_mux = false, +}; + +static int tegra20_pinctrl_probe(struct platform_device *pdev) +{ + return tegra_pinctrl_probe(pdev, &tegra20_pinctrl); +} + +static const struct of_device_id tegra20_pinctrl_of_match[] = { + { .compatible = "nvidia,tegra20-pinmux", }, + { }, +}; + +static struct platform_driver tegra20_pinctrl_driver = { + .driver = { + .name = "tegra20-pinctrl", + .of_match_table = tegra20_pinctrl_of_match, + }, + .probe = tegra20_pinctrl_probe, + .remove = tegra_pinctrl_remove, +}; +module_platform_driver(tegra20_pinctrl_driver); + +MODULE_AUTHOR("Stephen Warren "); +MODULE_DESCRIPTION("NVIDIA Tegra20 pinctrl driver"); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(of, tegra20_pinctrl_of_match); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra210.c b/drivers/pinctrl/tegra/pinctrl-tegra210.c new file mode 100644 index 000000000000..252b464901c0 --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra210.c @@ -0,0 +1,1588 @@ +/* + * Pinctrl data for the NVIDIA Tegra210 pinmux + * + * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#include +#include +#include +#include +#include + +#include "pinctrl-tegra.h" + +/* + * Most pins affected by the pinmux can also be GPIOs. Define these first. + * These must match how the GPIO driver names/numbers its pins. + */ +#define _GPIO(offset) (offset) + +#define TEGRA_PIN_PEX_L0_RST_N_PA0 _GPIO(0) +#define TEGRA_PIN_PEX_L0_CLKREQ_N_PA1 _GPIO(1) +#define TEGRA_PIN_PEX_WAKE_N_PA2 _GPIO(2) +#define TEGRA_PIN_PEX_L1_RST_N_PA3 _GPIO(3) +#define TEGRA_PIN_PEX_L1_CLKREQ_N_PA4 _GPIO(4) +#define TEGRA_PIN_SATA_LED_ACTIVE_PA5 _GPIO(5) +#define TEGRA_PIN_PA6 _GPIO(6) +#define TEGRA_PIN_DAP1_FS_PB0 _GPIO(8) +#define TEGRA_PIN_DAP1_DIN_PB1 _GPIO(9) +#define TEGRA_PIN_DAP1_DOUT_PB2 _GPIO(10) +#define TEGRA_PIN_DAP1_SCLK_PB3 _GPIO(11) +#define TEGRA_PIN_SPI2_MOSI_PB4 _GPIO(12) +#define TEGRA_PIN_SPI2_MISO_PB5 _GPIO(13) +#define TEGRA_PIN_SPI2_SCK_PB6 _GPIO(14) +#define TEGRA_PIN_SPI2_CS0_PB7 _GPIO(15) +#define TEGRA_PIN_SPI1_MOSI_PC0 _GPIO(16) +#define TEGRA_PIN_SPI1_MISO_PC1 _GPIO(17) +#define TEGRA_PIN_SPI1_SCK_PC2 _GPIO(18) +#define TEGRA_PIN_SPI1_CS0_PC3 _GPIO(19) +#define TEGRA_PIN_SPI1_CS1_PC4 _GPIO(20) +#define TEGRA_PIN_SPI4_SCK_PC5 _GPIO(21) +#define TEGRA_PIN_SPI4_CS0_PC6 _GPIO(22) +#define TEGRA_PIN_SPI4_MOSI_PC7 _GPIO(23) +#define TEGRA_PIN_SPI4_MISO_PD0 _GPIO(24) +#define TEGRA_PIN_UART3_TX_PD1 _GPIO(25) +#define TEGRA_PIN_UART3_RX_PD2 _GPIO(26) +#define TEGRA_PIN_UART3_RTS_PD3 _GPIO(27) +#define TEGRA_PIN_UART3_CTS_PD4 _GPIO(28) +#define TEGRA_PIN_DMIC1_CLK_PE0 _GPIO(32) +#define TEGRA_PIN_DMIC1_DAT_PE1 _GPIO(33) +#define TEGRA_PIN_DMIC2_CLK_PE2 _GPIO(34) +#define TEGRA_PIN_DMIC2_DAT_PE3 _GPIO(35) +#define TEGRA_PIN_DMIC3_CLK_PE4 _GPIO(36) +#define TEGRA_PIN_DMIC3_DAT_PE5 _GPIO(37) +#define TEGRA_PIN_PE6 _GPIO(38) +#define TEGRA_PIN_PE7 _GPIO(39) +#define TEGRA_PIN_GEN3_I2C_SCL_PF0 _GPIO(40) +#define TEGRA_PIN_GEN3_I2C_SDA_PF1 _GPIO(41) +#define TEGRA_PIN_UART2_TX_PG0 _GPIO(48) +#define TEGRA_PIN_UART2_RX_PG1 _GPIO(49) +#define TEGRA_PIN_UART2_RTS_PG2 _GPIO(50) +#define TEGRA_PIN_UART2_CTS_PG3 _GPIO(51) +#define TEGRA_PIN_WIFI_EN_PH0 _GPIO(56) +#define TEGRA_PIN_WIFI_RST_PH1 _GPIO(57) +#define TEGRA_PIN_WIFI_WAKE_AP_PH2 _GPIO(58) +#define TEGRA_PIN_AP_WAKE_BT_PH3 _GPIO(59) +#define TEGRA_PIN_BT_RST_PH4 _GPIO(60) +#define TEGRA_PIN_BT_WAKE_AP_PH5 _GPIO(61) +#define TEGRA_PIN_PH6 _GPIO(62) +#define TEGRA_PIN_AP_WAKE_NFC_PH7 _GPIO(63) +#define TEGRA_PIN_NFC_EN_PI0 _GPIO(64) +#define TEGRA_PIN_NFC_INT_PI1 _GPIO(65) +#define TEGRA_PIN_GPS_EN_PI2 _GPIO(66) +#define TEGRA_PIN_GPS_RST_PI3 _GPIO(67) +#define TEGRA_PIN_UART4_TX_PI4 _GPIO(68) +#define TEGRA_PIN_UART4_RX_PI5 _GPIO(69) +#define TEGRA_PIN_UART4_RTS_PI6 _GPIO(70) +#define TEGRA_PIN_UART4_CTS_PI7 _GPIO(71) +#define TEGRA_PIN_GEN1_I2C_SDA_PJ0 _GPIO(72) +#define TEGRA_PIN_GEN1_I2C_SCL_PJ1 _GPIO(73) +#define TEGRA_PIN_GEN2_I2C_SCL_PJ2 _GPIO(74) +#define TEGRA_PIN_GEN2_I2C_SDA_PJ3 _GPIO(75) +#define TEGRA_PIN_DAP4_FS_PJ4 _GPIO(76) +#define TEGRA_PIN_DAP4_DIN_PJ5 _GPIO(77) +#define TEGRA_PIN_DAP4_DOUT_PJ6 _GPIO(78) +#define TEGRA_PIN_DAP4_SCLK_PJ7 _GPIO(79) +#define TEGRA_PIN_PK0 _GPIO(80) +#define TEGRA_PIN_PK1 _GPIO(81) +#define TEGRA_PIN_PK2 _GPIO(82) +#define TEGRA_PIN_PK3 _GPIO(83) +#define TEGRA_PIN_PK4 _GPIO(84) +#define TEGRA_PIN_PK5 _GPIO(85) +#define TEGRA_PIN_PK6 _GPIO(86) +#define TEGRA_PIN_PK7 _GPIO(87) +#define TEGRA_PIN_PL0 _GPIO(88) +#define TEGRA_PIN_PL1 _GPIO(89) +#define TEGRA_PIN_SDMMC1_CLK_PM0 _GPIO(96) +#define TEGRA_PIN_SDMMC1_CMD_PM1 _GPIO(97) +#define TEGRA_PIN_SDMMC1_DAT3_PM2 _GPIO(98) +#define TEGRA_PIN_SDMMC1_DAT2_PM3 _GPIO(99) +#define TEGRA_PIN_SDMMC1_DAT1_PM4 _GPIO(100) +#define TEGRA_PIN_SDMMC1_DAT0_PM5 _GPIO(101) +#define TEGRA_PIN_SDMMC3_CLK_PP0 _GPIO(120) +#define TEGRA_PIN_SDMMC3_CMD_PP1 _GPIO(121) +#define TEGRA_PIN_SDMMC3_DAT3_PP2 _GPIO(122) +#define TEGRA_PIN_SDMMC3_DAT2_PP3 _GPIO(123) +#define TEGRA_PIN_SDMMC3_DAT1_PP4 _GPIO(124) +#define TEGRA_PIN_SDMMC3_DAT0_PP5 _GPIO(125) +#define TEGRA_PIN_CAM1_MCLK_PS0 _GPIO(144) +#define TEGRA_PIN_CAM2_MCLK_PS1 _GPIO(145) +#define TEGRA_PIN_CAM_I2C_SCL_PS2 _GPIO(146) +#define TEGRA_PIN_CAM_I2C_SDA_PS3 _GPIO(147) +#define TEGRA_PIN_CAM_RST_PS4 _GPIO(148) +#define TEGRA_PIN_CAM_AF_EN_PS5 _GPIO(149) +#define TEGRA_PIN_CAM_FLASH_EN_PS6 _GPIO(150) +#define TEGRA_PIN_CAM1_PWDN_PS7 _GPIO(151) +#define TEGRA_PIN_CAM2_PWDN_PT0 _GPIO(152) +#define TEGRA_PIN_CAM1_STROBE_PT1 _GPIO(153) +#define TEGRA_PIN_UART1_TX_PU0 _GPIO(160) +#define TEGRA_PIN_UART1_RX_PU1 _GPIO(161) +#define TEGRA_PIN_UART1_RTS_PU2 _GPIO(162) +#define TEGRA_PIN_UART1_CTS_PU3 _GPIO(163) +#define TEGRA_PIN_LCD_BL_PWM_PV0 _GPIO(168) +#define TEGRA_PIN_LCD_BL_EN_PV1 _GPIO(169) +#define TEGRA_PIN_LCD_RST_PV2 _GPIO(170) +#define TEGRA_PIN_LCD_GPIO1_PV3 _GPIO(171) +#define TEGRA_PIN_LCD_GPIO2_PV4 _GPIO(172) +#define TEGRA_PIN_AP_READY_PV5 _GPIO(173) +#define TEGRA_PIN_TOUCH_RST_PV6 _GPIO(174) +#define TEGRA_PIN_TOUCH_CLK_PV7 _GPIO(175) +#define TEGRA_PIN_MODEM_WAKE_AP_PX0 _GPIO(184) +#define TEGRA_PIN_TOUCH_INT_PX1 _GPIO(185) +#define TEGRA_PIN_MOTION_INT_PX2 _GPIO(186) +#define TEGRA_PIN_ALS_PROX_INT_PX3 _GPIO(187) +#define TEGRA_PIN_TEMP_ALERT_PX4 _GPIO(188) +#define TEGRA_PIN_BUTTON_POWER_ON_PX5 _GPIO(189) +#define TEGRA_PIN_BUTTON_VOL_UP_PX6 _GPIO(190) +#define TEGRA_PIN_BUTTON_VOL_DOWN_PX7 _GPIO(191) +#define TEGRA_PIN_BUTTON_SLIDE_SW_PY0 _GPIO(192) +#define TEGRA_PIN_BUTTON_HOME_PY1 _GPIO(193) +#define TEGRA_PIN_LCD_TE_PY2 _GPIO(194) +#define TEGRA_PIN_PWR_I2C_SCL_PY3 _GPIO(195) +#define TEGRA_PIN_PWR_I2C_SDA_PY4 _GPIO(196) +#define TEGRA_PIN_CLK_32K_OUT_PY5 _GPIO(197) +#define TEGRA_PIN_PZ0 _GPIO(200) +#define TEGRA_PIN_PZ1 _GPIO(201) +#define TEGRA_PIN_PZ2 _GPIO(202) +#define TEGRA_PIN_PZ3 _GPIO(203) +#define TEGRA_PIN_PZ4 _GPIO(204) +#define TEGRA_PIN_PZ5 _GPIO(205) +#define TEGRA_PIN_DAP2_FS_PAA0 _GPIO(208) +#define TEGRA_PIN_DAP2_SCLK_PAA1 _GPIO(209) +#define TEGRA_PIN_DAP2_DIN_PAA2 _GPIO(210) +#define TEGRA_PIN_DAP2_DOUT_PAA3 _GPIO(211) +#define TEGRA_PIN_AUD_MCLK_PBB0 _GPIO(216) +#define TEGRA_PIN_DVFS_PWM_PBB1 _GPIO(217) +#define TEGRA_PIN_DVFS_CLK_PBB2 _GPIO(218) +#define TEGRA_PIN_GPIO_X1_AUD_PBB3 _GPIO(219) +#define TEGRA_PIN_GPIO_X3_AUD_PBB4 _GPIO(220) +#define TEGRA_PIN_HDMI_CEC_PCC0 _GPIO(224) +#define TEGRA_PIN_HDMI_INT_DP_HPD_PCC1 _GPIO(225) +#define TEGRA_PIN_SPDIF_OUT_PCC2 _GPIO(226) +#define TEGRA_PIN_SPDIF_IN_PCC3 _GPIO(227) +#define TEGRA_PIN_USB_VBUS_EN0_PCC4 _GPIO(228) +#define TEGRA_PIN_USB_VBUS_EN1_PCC5 _GPIO(229) +#define TEGRA_PIN_DP_HPD0_PCC6 _GPIO(230) +#define TEGRA_PIN_PCC7 _GPIO(231) +#define TEGRA_PIN_SPI2_CS1_PDD0 _GPIO(232) +#define TEGRA_PIN_QSPI_SCK_PEE0 _GPIO(240) +#define TEGRA_PIN_QSPI_CS_N_PEE1 _GPIO(241) +#define TEGRA_PIN_QSPI_IO0_PEE2 _GPIO(242) +#define TEGRA_PIN_QSPI_IO1_PEE3 _GPIO(243) +#define TEGRA_PIN_QSPI_IO2_PEE4 _GPIO(244) +#define TEGRA_PIN_QSPI_IO3_PEE5 _GPIO(245) + +/* All non-GPIO pins follow */ +#define NUM_GPIOS (TEGRA_PIN_QSPI_IO3_PEE5 + 1) +#define _PIN(offset) (NUM_GPIOS + (offset)) + +/* Non-GPIO pins */ +#define TEGRA_PIN_CORE_PWR_REQ _PIN(0) +#define TEGRA_PIN_CPU_PWR_REQ _PIN(1) +#define TEGRA_PIN_PWR_INT_N _PIN(2) +#define TEGRA_PIN_CLK_32K_IN _PIN(3) +#define TEGRA_PIN_JTAG_RTCK _PIN(4) +#define TEGRA_PIN_BATT_BCL _PIN(5) +#define TEGRA_PIN_CLK_REQ _PIN(6) +#define TEGRA_PIN_SHUTDOWN _PIN(7) + +static const struct pinctrl_pin_desc tegra210_pins[] = { + PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PA0, "PEX_L0_RST_N PA0"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PA1, "PEX_L0_CLKREQ_N PA1"), + PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PA2, "PEX_WAKE_N PA2"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PA3, "PEX_L1_RST_N PA3"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PA4, "PEX_L1_CLKREQ_N PA4"), + PINCTRL_PIN(TEGRA_PIN_SATA_LED_ACTIVE_PA5, "SATA_LED_ACTIVE PA5"), + PINCTRL_PIN(TEGRA_PIN_PA6, "PA6"), + PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PB0, "DAP1_FS PB0"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PB1, "DAP1_DIN PB1"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PB2, "DAP1_DOUT PB2"), + PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PB3, "DAP1_SCLK PB3"), + PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PB4, "SPI2_MOSI PB4"), + PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PB5, "SPI2_MISO PB5"), + PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PB6, "SPI2_SCK PB6"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_PB7, "SPI2_CS0 PB7"), + PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PC0, "SPI1_MOSI PC0"), + PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PC1, "SPI1_MISO PC1"), + PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PC2, "SPI1_SCK PC2"), + PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_PC3, "SPI1_CS0 PC3"), + PINCTRL_PIN(TEGRA_PIN_SPI1_CS1_PC4, "SPI1_CS1 PC4"), + PINCTRL_PIN(TEGRA_PIN_SPI4_SCK_PC5, "SPI4_SCK PC5"), + PINCTRL_PIN(TEGRA_PIN_SPI4_CS0_PC6, "SPI4_CS0 PC6"), + PINCTRL_PIN(TEGRA_PIN_SPI4_MOSI_PC7, "SPI4_MOSI PC7"), + PINCTRL_PIN(TEGRA_PIN_SPI4_MISO_PD0, "SPI4_MISO PD0"), + PINCTRL_PIN(TEGRA_PIN_UART3_TX_PD1, "UART3_TX PD1"), + PINCTRL_PIN(TEGRA_PIN_UART3_RX_PD2, "UART3_RX PD2"), + PINCTRL_PIN(TEGRA_PIN_UART3_RTS_PD3, "UART3_RTS PD3"), + PINCTRL_PIN(TEGRA_PIN_UART3_CTS_PD4, "UART3_CTS PD4"), + PINCTRL_PIN(TEGRA_PIN_DMIC1_CLK_PE0, "DMIC1_CLK PE0"), + PINCTRL_PIN(TEGRA_PIN_DMIC1_DAT_PE1, "DMIC1_DAT PE1"), + PINCTRL_PIN(TEGRA_PIN_DMIC2_CLK_PE2, "DMIC2_CLK PE2"), + PINCTRL_PIN(TEGRA_PIN_DMIC2_DAT_PE3, "DMIC2_DAT PE3"), + PINCTRL_PIN(TEGRA_PIN_DMIC3_CLK_PE4, "DMIC3_CLK PE4"), + PINCTRL_PIN(TEGRA_PIN_DMIC3_DAT_PE5, "DMIC3_DAT PE5"), + PINCTRL_PIN(TEGRA_PIN_PE6, "PE6"), + PINCTRL_PIN(TEGRA_PIN_PE7, "PE7"), + PINCTRL_PIN(TEGRA_PIN_GEN3_I2C_SCL_PF0, "GEN3_I2C_SCL PF0"), + PINCTRL_PIN(TEGRA_PIN_GEN3_I2C_SDA_PF1, "GEN3_I2C_SDA PF1"), + PINCTRL_PIN(TEGRA_PIN_UART2_TX_PG0, "UART2_TX PG0"), + PINCTRL_PIN(TEGRA_PIN_UART2_RX_PG1, "UART2_RX PG1"), + PINCTRL_PIN(TEGRA_PIN_UART2_RTS_PG2, "UART2_RTS PG2"), + PINCTRL_PIN(TEGRA_PIN_UART2_CTS_PG3, "UART2_CTS PG3"), + PINCTRL_PIN(TEGRA_PIN_WIFI_EN_PH0, "WIFI_EN PH0"), + PINCTRL_PIN(TEGRA_PIN_WIFI_RST_PH1, "WIFI_RST PH1"), + PINCTRL_PIN(TEGRA_PIN_WIFI_WAKE_AP_PH2, "WIFI_WAKE_AP PH2"), + PINCTRL_PIN(TEGRA_PIN_AP_WAKE_BT_PH3, "AP_WAKE_BT PH3"), + PINCTRL_PIN(TEGRA_PIN_BT_RST_PH4, "BT_RST PH4"), + PINCTRL_PIN(TEGRA_PIN_BT_WAKE_AP_PH5, "BT_WAKE_AP PH5"), + PINCTRL_PIN(TEGRA_PIN_PH6, "PH6"), + PINCTRL_PIN(TEGRA_PIN_AP_WAKE_NFC_PH7, "AP_WAKE_NFC PH7"), + PINCTRL_PIN(TEGRA_PIN_NFC_EN_PI0, "NFC_EN PI0"), + PINCTRL_PIN(TEGRA_PIN_NFC_INT_PI1, "NFC_INT PI1"), + PINCTRL_PIN(TEGRA_PIN_GPS_EN_PI2, "GPS_EN PI2"), + PINCTRL_PIN(TEGRA_PIN_GPS_RST_PI3, "GPS_RST PI3"), + PINCTRL_PIN(TEGRA_PIN_UART4_TX_PI4, "UART4_TX PI4"), + PINCTRL_PIN(TEGRA_PIN_UART4_RX_PI5, "UART4_RX PI5"), + PINCTRL_PIN(TEGRA_PIN_UART4_RTS_PI6, "UART4_RTS PI6"), + PINCTRL_PIN(TEGRA_PIN_UART4_CTS_PI7, "UART4_CTS PI7"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PJ0, "GEN1_I2C_SDA PJ0"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PJ1, "GEN1_I2C_SCL PJ1"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PJ2, "GEN2_I2C_SCL PJ2"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PJ3, "GEN2_I2C_SDA PJ3"), + PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PJ4, "DAP4_FS PJ4"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PJ5, "DAP4_DIN PJ5"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PJ6, "DAP4_DOUT PJ6"), + PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PJ7, "DAP4_SCLK PJ7"), + PINCTRL_PIN(TEGRA_PIN_PK0, "PK0"), + PINCTRL_PIN(TEGRA_PIN_PK1, "PK1"), + PINCTRL_PIN(TEGRA_PIN_PK2, "PK2"), + PINCTRL_PIN(TEGRA_PIN_PK3, "PK3"), + PINCTRL_PIN(TEGRA_PIN_PK4, "PK4"), + PINCTRL_PIN(TEGRA_PIN_PK5, "PK5"), + PINCTRL_PIN(TEGRA_PIN_PK6, "PK6"), + PINCTRL_PIN(TEGRA_PIN_PK7, "PK7"), + PINCTRL_PIN(TEGRA_PIN_PL0, "PL0"), + PINCTRL_PIN(TEGRA_PIN_PL1, "PL1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PM0, "SDMMC1_CLK PM0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PM1, "SDMMC1_CMD PM1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PM2, "SDMMC1_DAT3 PM2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PM3, "SDMMC1_DAT2 PM3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PM4, "SDMMC1_DAT1 PM4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PM5, "SDMMC1_DAT0 PM5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PP0, "SDMMC3_CLK PP0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PP1, "SDMMC3_CMD PP1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PP2, "SDMMC3_DAT3 PP2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PP3, "SDMMC3_DAT2 PP3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PP4, "SDMMC3_DAT1 PP4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PP5, "SDMMC3_DAT0 PP5"), + PINCTRL_PIN(TEGRA_PIN_CAM1_MCLK_PS0, "CAM1_MCLK PS0"), + PINCTRL_PIN(TEGRA_PIN_CAM2_MCLK_PS1, "CAM2_MCLK PS1"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PS2, "CAM_I2C_SCL PS2"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PS3, "CAM_I2C_SDA PS3"), + PINCTRL_PIN(TEGRA_PIN_CAM_RST_PS4, "CAM_RST PS4"), + PINCTRL_PIN(TEGRA_PIN_CAM_AF_EN_PS5, "CAM_AF_EN PS5"), + PINCTRL_PIN(TEGRA_PIN_CAM_FLASH_EN_PS6, "CAM_FLASH_EN PS6"), + PINCTRL_PIN(TEGRA_PIN_CAM1_PWDN_PS7, "CAM1_PWDN PS7"), + PINCTRL_PIN(TEGRA_PIN_CAM2_PWDN_PT0, "CAM2_PWDN PT0"), + PINCTRL_PIN(TEGRA_PIN_CAM1_STROBE_PT1, "CAM1_STROBE PT1"), + PINCTRL_PIN(TEGRA_PIN_UART1_TX_PU0, "UART1_TX PU0"), + PINCTRL_PIN(TEGRA_PIN_UART1_RX_PU1, "UART1_RX PU1"), + PINCTRL_PIN(TEGRA_PIN_UART1_RTS_PU2, "UART1_RTS PU2"), + PINCTRL_PIN(TEGRA_PIN_UART1_CTS_PU3, "UART1_CTS PU3"), + PINCTRL_PIN(TEGRA_PIN_LCD_BL_PWM_PV0, "LCD_BL_PWM PV0"), + PINCTRL_PIN(TEGRA_PIN_LCD_BL_EN_PV1, "LCD_BL_EN PV1"), + PINCTRL_PIN(TEGRA_PIN_LCD_RST_PV2, "LCD_RST PV2"), + PINCTRL_PIN(TEGRA_PIN_LCD_GPIO1_PV3, "LCD_GPIO1 PV3"), + PINCTRL_PIN(TEGRA_PIN_LCD_GPIO2_PV4, "LCD_GPIO2 PV4"), + PINCTRL_PIN(TEGRA_PIN_AP_READY_PV5, "AP_READY PV5"), + PINCTRL_PIN(TEGRA_PIN_TOUCH_RST_PV6, "TOUCH_RST PV6"), + PINCTRL_PIN(TEGRA_PIN_TOUCH_CLK_PV7, "TOUCH_CLK PV7"), + PINCTRL_PIN(TEGRA_PIN_MODEM_WAKE_AP_PX0, "MODEM_WAKE_AP PX0"), + PINCTRL_PIN(TEGRA_PIN_TOUCH_INT_PX1, "TOUCH_INT PX1"), + PINCTRL_PIN(TEGRA_PIN_MOTION_INT_PX2, "MOTION_INT PX2"), + PINCTRL_PIN(TEGRA_PIN_ALS_PROX_INT_PX3, "ALS_PROX_INT PX3"), + PINCTRL_PIN(TEGRA_PIN_TEMP_ALERT_PX4, "TEMP_ALERT PX4"), + PINCTRL_PIN(TEGRA_PIN_BUTTON_POWER_ON_PX5, "BUTTON_POWER_ON PX5"), + PINCTRL_PIN(TEGRA_PIN_BUTTON_VOL_UP_PX6, "BUTTON_VOL_UP PX6"), + PINCTRL_PIN(TEGRA_PIN_BUTTON_VOL_DOWN_PX7, "BUTTON_VOL_DOWN PX7"), + PINCTRL_PIN(TEGRA_PIN_BUTTON_SLIDE_SW_PY0, "BUTTON_SLIDE_SW PY0"), + PINCTRL_PIN(TEGRA_PIN_BUTTON_HOME_PY1, "BUTTON_HOME PY1"), + PINCTRL_PIN(TEGRA_PIN_LCD_TE_PY2, "LCD_TE PY2"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PY3, "PWR_I2C_SCL PY3"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PY4, "PWR_I2C_SDA PY4"), + PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PY5, "CLK_32K_OUT PY5"), + PINCTRL_PIN(TEGRA_PIN_PZ0, "PZ0"), + PINCTRL_PIN(TEGRA_PIN_PZ1, "PZ1"), + PINCTRL_PIN(TEGRA_PIN_PZ2, "PZ2"), + PINCTRL_PIN(TEGRA_PIN_PZ3, "PZ3"), + PINCTRL_PIN(TEGRA_PIN_PZ4, "PZ4"), + PINCTRL_PIN(TEGRA_PIN_PZ5, "PZ5"), + PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PAA0, "DAP2_FS PAA0"), + PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PAA1, "DAP2_SCLK PAA1"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PAA2, "DAP2_DIN PAA2"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PAA3, "DAP2_DOUT PAA3"), + PINCTRL_PIN(TEGRA_PIN_AUD_MCLK_PBB0, "AUD_MCLK PBB0"), + PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PBB1, "DVFS_PWM PBB1"), + PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PBB2, "DVFS_CLK PBB2"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PBB3, "GPIO_X1_AUD PBB3"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PBB4, "GPIO_X3_AUD PBB4"), + PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PCC0, "HDMI_CEC PCC0"), + PINCTRL_PIN(TEGRA_PIN_HDMI_INT_DP_HPD_PCC1, "HDMI_INT_DP_HPD PCC1"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PCC2, "SPDIF_OUT PCC2"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PCC3, "SPDIF_IN PCC3"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PCC4, "USB_VBUS_EN0 PCC4"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PCC5, "USB_VBUS_EN1 PCC5"), + PINCTRL_PIN(TEGRA_PIN_DP_HPD0_PCC6, "DP_HPD0 PCC6"), + PINCTRL_PIN(TEGRA_PIN_PCC7, "PCC7"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_PDD0, "SPI2_CS1 PDD0"), + PINCTRL_PIN(TEGRA_PIN_QSPI_SCK_PEE0, "QSPI_SCK PEE0"), + PINCTRL_PIN(TEGRA_PIN_QSPI_CS_N_PEE1, "QSPI_CS_N PEE1"), + PINCTRL_PIN(TEGRA_PIN_QSPI_IO0_PEE2, "QSPI_IO0 PEE2"), + PINCTRL_PIN(TEGRA_PIN_QSPI_IO1_PEE3, "QSPI_IO1 PEE3"), + PINCTRL_PIN(TEGRA_PIN_QSPI_IO2_PEE4, "QSPI_IO2 PEE4"), + PINCTRL_PIN(TEGRA_PIN_QSPI_IO3_PEE5, "QSPI_IO3 PEE5"), + PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), + PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), + PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"), + PINCTRL_PIN(TEGRA_PIN_BATT_BCL, "BATT_BCL"), + PINCTRL_PIN(TEGRA_PIN_CLK_REQ, "CLK_REQ"), + PINCTRL_PIN(TEGRA_PIN_SHUTDOWN, "SHUTDOWN"), +}; + +static const unsigned pex_l0_rst_n_pa0_pins[] = { + TEGRA_PIN_PEX_L0_RST_N_PA0, +}; + +static const unsigned pex_l0_clkreq_n_pa1_pins[] = { + TEGRA_PIN_PEX_L0_CLKREQ_N_PA1, +}; + +static const unsigned pex_wake_n_pa2_pins[] = { + TEGRA_PIN_PEX_WAKE_N_PA2, +}; + +static const unsigned pex_l1_rst_n_pa3_pins[] = { + TEGRA_PIN_PEX_L1_RST_N_PA3, +}; + +static const unsigned pex_l1_clkreq_n_pa4_pins[] = { + TEGRA_PIN_PEX_L1_CLKREQ_N_PA4, +}; + +static const unsigned sata_led_active_pa5_pins[] = { + TEGRA_PIN_SATA_LED_ACTIVE_PA5, +}; + +static const unsigned pa6_pins[] = { + TEGRA_PIN_PA6, +}; + +static const unsigned dap1_fs_pb0_pins[] = { + TEGRA_PIN_DAP1_FS_PB0, +}; + +static const unsigned dap1_din_pb1_pins[] = { + TEGRA_PIN_DAP1_DIN_PB1, +}; + +static const unsigned dap1_dout_pb2_pins[] = { + TEGRA_PIN_DAP1_DOUT_PB2, +}; + +static const unsigned dap1_sclk_pb3_pins[] = { + TEGRA_PIN_DAP1_SCLK_PB3, +}; + +static const unsigned spi2_mosi_pb4_pins[] = { + TEGRA_PIN_SPI2_MOSI_PB4, +}; + +static const unsigned spi2_miso_pb5_pins[] = { + TEGRA_PIN_SPI2_MISO_PB5, +}; + +static const unsigned spi2_sck_pb6_pins[] = { + TEGRA_PIN_SPI2_SCK_PB6, +}; + +static const unsigned spi2_cs0_pb7_pins[] = { + TEGRA_PIN_SPI2_CS0_PB7, +}; + +static const unsigned spi1_mosi_pc0_pins[] = { + TEGRA_PIN_SPI1_MOSI_PC0, +}; + +static const unsigned spi1_miso_pc1_pins[] = { + TEGRA_PIN_SPI1_MISO_PC1, +}; + +static const unsigned spi1_sck_pc2_pins[] = { + TEGRA_PIN_SPI1_SCK_PC2, +}; + +static const unsigned spi1_cs0_pc3_pins[] = { + TEGRA_PIN_SPI1_CS0_PC3, +}; + +static const unsigned spi1_cs1_pc4_pins[] = { + TEGRA_PIN_SPI1_CS1_PC4, +}; + +static const unsigned spi4_sck_pc5_pins[] = { + TEGRA_PIN_SPI4_SCK_PC5, +}; + +static const unsigned spi4_cs0_pc6_pins[] = { + TEGRA_PIN_SPI4_CS0_PC6, +}; + +static const unsigned spi4_mosi_pc7_pins[] = { + TEGRA_PIN_SPI4_MOSI_PC7, +}; + +static const unsigned spi4_miso_pd0_pins[] = { + TEGRA_PIN_SPI4_MISO_PD0, +}; + +static const unsigned uart3_tx_pd1_pins[] = { + TEGRA_PIN_UART3_TX_PD1, +}; + +static const unsigned uart3_rx_pd2_pins[] = { + TEGRA_PIN_UART3_RX_PD2, +}; + +static const unsigned uart3_rts_pd3_pins[] = { + TEGRA_PIN_UART3_RTS_PD3, +}; + +static const unsigned uart3_cts_pd4_pins[] = { + TEGRA_PIN_UART3_CTS_PD4, +}; + +static const unsigned dmic1_clk_pe0_pins[] = { + TEGRA_PIN_DMIC1_CLK_PE0, +}; + +static const unsigned dmic1_dat_pe1_pins[] = { + TEGRA_PIN_DMIC1_DAT_PE1, +}; + +static const unsigned dmic2_clk_pe2_pins[] = { + TEGRA_PIN_DMIC2_CLK_PE2, +}; + +static const unsigned dmic2_dat_pe3_pins[] = { + TEGRA_PIN_DMIC2_DAT_PE3, +}; + +static const unsigned dmic3_clk_pe4_pins[] = { + TEGRA_PIN_DMIC3_CLK_PE4, +}; + +static const unsigned dmic3_dat_pe5_pins[] = { + TEGRA_PIN_DMIC3_DAT_PE5, +}; + +static const unsigned pe6_pins[] = { + TEGRA_PIN_PE6, +}; + +static const unsigned pe7_pins[] = { + TEGRA_PIN_PE7, +}; + +static const unsigned gen3_i2c_scl_pf0_pins[] = { + TEGRA_PIN_GEN3_I2C_SCL_PF0, +}; + +static const unsigned gen3_i2c_sda_pf1_pins[] = { + TEGRA_PIN_GEN3_I2C_SDA_PF1, +}; + +static const unsigned uart2_tx_pg0_pins[] = { + TEGRA_PIN_UART2_TX_PG0, +}; + +static const unsigned uart2_rx_pg1_pins[] = { + TEGRA_PIN_UART2_RX_PG1, +}; + +static const unsigned uart2_rts_pg2_pins[] = { + TEGRA_PIN_UART2_RTS_PG2, +}; + +static const unsigned uart2_cts_pg3_pins[] = { + TEGRA_PIN_UART2_CTS_PG3, +}; + +static const unsigned wifi_en_ph0_pins[] = { + TEGRA_PIN_WIFI_EN_PH0, +}; + +static const unsigned wifi_rst_ph1_pins[] = { + TEGRA_PIN_WIFI_RST_PH1, +}; + +static const unsigned wifi_wake_ap_ph2_pins[] = { + TEGRA_PIN_WIFI_WAKE_AP_PH2, +}; + +static const unsigned ap_wake_bt_ph3_pins[] = { + TEGRA_PIN_AP_WAKE_BT_PH3, +}; + +static const unsigned bt_rst_ph4_pins[] = { + TEGRA_PIN_BT_RST_PH4, +}; + +static const unsigned bt_wake_ap_ph5_pins[] = { + TEGRA_PIN_BT_WAKE_AP_PH5, +}; + +static const unsigned ph6_pins[] = { + TEGRA_PIN_PH6, +}; + +static const unsigned ap_wake_nfc_ph7_pins[] = { + TEGRA_PIN_AP_WAKE_NFC_PH7, +}; + +static const unsigned nfc_en_pi0_pins[] = { + TEGRA_PIN_NFC_EN_PI0, +}; + +static const unsigned nfc_int_pi1_pins[] = { + TEGRA_PIN_NFC_INT_PI1, +}; + +static const unsigned gps_en_pi2_pins[] = { + TEGRA_PIN_GPS_EN_PI2, +}; + +static const unsigned gps_rst_pi3_pins[] = { + TEGRA_PIN_GPS_RST_PI3, +}; + +static const unsigned uart4_tx_pi4_pins[] = { + TEGRA_PIN_UART4_TX_PI4, +}; + +static const unsigned uart4_rx_pi5_pins[] = { + TEGRA_PIN_UART4_RX_PI5, +}; + +static const unsigned uart4_rts_pi6_pins[] = { + TEGRA_PIN_UART4_RTS_PI6, +}; + +static const unsigned uart4_cts_pi7_pins[] = { + TEGRA_PIN_UART4_CTS_PI7, +}; + +static const unsigned gen1_i2c_sda_pj0_pins[] = { + TEGRA_PIN_GEN1_I2C_SDA_PJ0, +}; + +static const unsigned gen1_i2c_scl_pj1_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PJ1, +}; + +static const unsigned gen2_i2c_scl_pj2_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PJ2, +}; + +static const unsigned gen2_i2c_sda_pj3_pins[] = { + TEGRA_PIN_GEN2_I2C_SDA_PJ3, +}; + +static const unsigned dap4_fs_pj4_pins[] = { + TEGRA_PIN_DAP4_FS_PJ4, +}; + +static const unsigned dap4_din_pj5_pins[] = { + TEGRA_PIN_DAP4_DIN_PJ5, +}; + +static const unsigned dap4_dout_pj6_pins[] = { + TEGRA_PIN_DAP4_DOUT_PJ6, +}; + +static const unsigned dap4_sclk_pj7_pins[] = { + TEGRA_PIN_DAP4_SCLK_PJ7, +}; + +static const unsigned pk0_pins[] = { + TEGRA_PIN_PK0, +}; + +static const unsigned pk1_pins[] = { + TEGRA_PIN_PK1, +}; + +static const unsigned pk2_pins[] = { + TEGRA_PIN_PK2, +}; + +static const unsigned pk3_pins[] = { + TEGRA_PIN_PK3, +}; + +static const unsigned pk4_pins[] = { + TEGRA_PIN_PK4, +}; + +static const unsigned pk5_pins[] = { + TEGRA_PIN_PK5, +}; + +static const unsigned pk6_pins[] = { + TEGRA_PIN_PK6, +}; + +static const unsigned pk7_pins[] = { + TEGRA_PIN_PK7, +}; + +static const unsigned pl0_pins[] = { + TEGRA_PIN_PL0, +}; + +static const unsigned pl1_pins[] = { + TEGRA_PIN_PL1, +}; + +static const unsigned sdmmc1_clk_pm0_pins[] = { + TEGRA_PIN_SDMMC1_CLK_PM0, +}; + +static const unsigned sdmmc1_cmd_pm1_pins[] = { + TEGRA_PIN_SDMMC1_CMD_PM1, +}; + +static const unsigned sdmmc1_dat3_pm2_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PM2, +}; + +static const unsigned sdmmc1_dat2_pm3_pins[] = { + TEGRA_PIN_SDMMC1_DAT2_PM3, +}; + +static const unsigned sdmmc1_dat1_pm4_pins[] = { + TEGRA_PIN_SDMMC1_DAT1_PM4, +}; + +static const unsigned sdmmc1_dat0_pm5_pins[] = { + TEGRA_PIN_SDMMC1_DAT0_PM5, +}; + +static const unsigned sdmmc3_clk_pp0_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PP0, +}; + +static const unsigned sdmmc3_cmd_pp1_pins[] = { + TEGRA_PIN_SDMMC3_CMD_PP1, +}; + +static const unsigned sdmmc3_dat3_pp2_pins[] = { + TEGRA_PIN_SDMMC3_DAT3_PP2, +}; + +static const unsigned sdmmc3_dat2_pp3_pins[] = { + TEGRA_PIN_SDMMC3_DAT2_PP3, +}; + +static const unsigned sdmmc3_dat1_pp4_pins[] = { + TEGRA_PIN_SDMMC3_DAT1_PP4, +}; + +static const unsigned sdmmc3_dat0_pp5_pins[] = { + TEGRA_PIN_SDMMC3_DAT0_PP5, +}; + +static const unsigned cam1_mclk_ps0_pins[] = { + TEGRA_PIN_CAM1_MCLK_PS0, +}; + +static const unsigned cam2_mclk_ps1_pins[] = { + TEGRA_PIN_CAM2_MCLK_PS1, +}; + +static const unsigned cam_i2c_scl_ps2_pins[] = { + TEGRA_PIN_CAM_I2C_SCL_PS2, +}; + +static const unsigned cam_i2c_sda_ps3_pins[] = { + TEGRA_PIN_CAM_I2C_SDA_PS3, +}; + +static const unsigned cam_rst_ps4_pins[] = { + TEGRA_PIN_CAM_RST_PS4, +}; + +static const unsigned cam_af_en_ps5_pins[] = { + TEGRA_PIN_CAM_AF_EN_PS5, +}; + +static const unsigned cam_flash_en_ps6_pins[] = { + TEGRA_PIN_CAM_FLASH_EN_PS6, +}; + +static const unsigned cam1_pwdn_ps7_pins[] = { + TEGRA_PIN_CAM1_PWDN_PS7, +}; + +static const unsigned cam2_pwdn_pt0_pins[] = { + TEGRA_PIN_CAM2_PWDN_PT0, +}; + +static const unsigned cam1_strobe_pt1_pins[] = { + TEGRA_PIN_CAM1_STROBE_PT1, +}; + +static const unsigned uart1_tx_pu0_pins[] = { + TEGRA_PIN_UART1_TX_PU0, +}; + +static const unsigned uart1_rx_pu1_pins[] = { + TEGRA_PIN_UART1_RX_PU1, +}; + +static const unsigned uart1_rts_pu2_pins[] = { + TEGRA_PIN_UART1_RTS_PU2, +}; + +static const unsigned uart1_cts_pu3_pins[] = { + TEGRA_PIN_UART1_CTS_PU3, +}; + +static const unsigned lcd_bl_pwm_pv0_pins[] = { + TEGRA_PIN_LCD_BL_PWM_PV0, +}; + +static const unsigned lcd_bl_en_pv1_pins[] = { + TEGRA_PIN_LCD_BL_EN_PV1, +}; + +static const unsigned lcd_rst_pv2_pins[] = { + TEGRA_PIN_LCD_RST_PV2, +}; + +static const unsigned lcd_gpio1_pv3_pins[] = { + TEGRA_PIN_LCD_GPIO1_PV3, +}; + +static const unsigned lcd_gpio2_pv4_pins[] = { + TEGRA_PIN_LCD_GPIO2_PV4, +}; + +static const unsigned ap_ready_pv5_pins[] = { + TEGRA_PIN_AP_READY_PV5, +}; + +static const unsigned touch_rst_pv6_pins[] = { + TEGRA_PIN_TOUCH_RST_PV6, +}; + +static const unsigned touch_clk_pv7_pins[] = { + TEGRA_PIN_TOUCH_CLK_PV7, +}; + +static const unsigned modem_wake_ap_px0_pins[] = { + TEGRA_PIN_MODEM_WAKE_AP_PX0, +}; + +static const unsigned touch_int_px1_pins[] = { + TEGRA_PIN_TOUCH_INT_PX1, +}; + +static const unsigned motion_int_px2_pins[] = { + TEGRA_PIN_MOTION_INT_PX2, +}; + +static const unsigned als_prox_int_px3_pins[] = { + TEGRA_PIN_ALS_PROX_INT_PX3, +}; + +static const unsigned temp_alert_px4_pins[] = { + TEGRA_PIN_TEMP_ALERT_PX4, +}; + +static const unsigned button_power_on_px5_pins[] = { + TEGRA_PIN_BUTTON_POWER_ON_PX5, +}; + +static const unsigned button_vol_up_px6_pins[] = { + TEGRA_PIN_BUTTON_VOL_UP_PX6, +}; + +static const unsigned button_vol_down_px7_pins[] = { + TEGRA_PIN_BUTTON_VOL_DOWN_PX7, +}; + +static const unsigned button_slide_sw_py0_pins[] = { + TEGRA_PIN_BUTTON_SLIDE_SW_PY0, +}; + +static const unsigned button_home_py1_pins[] = { + TEGRA_PIN_BUTTON_HOME_PY1, +}; + +static const unsigned lcd_te_py2_pins[] = { + TEGRA_PIN_LCD_TE_PY2, +}; + +static const unsigned pwr_i2c_scl_py3_pins[] = { + TEGRA_PIN_PWR_I2C_SCL_PY3, +}; + +static const unsigned pwr_i2c_sda_py4_pins[] = { + TEGRA_PIN_PWR_I2C_SDA_PY4, +}; + +static const unsigned clk_32k_out_py5_pins[] = { + TEGRA_PIN_CLK_32K_OUT_PY5, +}; + +static const unsigned pz0_pins[] = { + TEGRA_PIN_PZ0, +}; + +static const unsigned pz1_pins[] = { + TEGRA_PIN_PZ1, +}; + +static const unsigned pz2_pins[] = { + TEGRA_PIN_PZ2, +}; + +static const unsigned pz3_pins[] = { + TEGRA_PIN_PZ3, +}; + +static const unsigned pz4_pins[] = { + TEGRA_PIN_PZ4, +}; + +static const unsigned pz5_pins[] = { + TEGRA_PIN_PZ5, +}; + +static const unsigned dap2_fs_paa0_pins[] = { + TEGRA_PIN_DAP2_FS_PAA0, +}; + +static const unsigned dap2_sclk_paa1_pins[] = { + TEGRA_PIN_DAP2_SCLK_PAA1, +}; + +static const unsigned dap2_din_paa2_pins[] = { + TEGRA_PIN_DAP2_DIN_PAA2, +}; + +static const unsigned dap2_dout_paa3_pins[] = { + TEGRA_PIN_DAP2_DOUT_PAA3, +}; + +static const unsigned aud_mclk_pbb0_pins[] = { + TEGRA_PIN_AUD_MCLK_PBB0, +}; + +static const unsigned dvfs_pwm_pbb1_pins[] = { + TEGRA_PIN_DVFS_PWM_PBB1, +}; + +static const unsigned dvfs_clk_pbb2_pins[] = { + TEGRA_PIN_DVFS_CLK_PBB2, +}; + +static const unsigned gpio_x1_aud_pbb3_pins[] = { + TEGRA_PIN_GPIO_X1_AUD_PBB3, +}; + +static const unsigned gpio_x3_aud_pbb4_pins[] = { + TEGRA_PIN_GPIO_X3_AUD_PBB4, +}; + +static const unsigned hdmi_cec_pcc0_pins[] = { + TEGRA_PIN_HDMI_CEC_PCC0, +}; + +static const unsigned hdmi_int_dp_hpd_pcc1_pins[] = { + TEGRA_PIN_HDMI_INT_DP_HPD_PCC1, +}; + +static const unsigned spdif_out_pcc2_pins[] = { + TEGRA_PIN_SPDIF_OUT_PCC2, +}; + +static const unsigned spdif_in_pcc3_pins[] = { + TEGRA_PIN_SPDIF_IN_PCC3, +}; + +static const unsigned usb_vbus_en0_pcc4_pins[] = { + TEGRA_PIN_USB_VBUS_EN0_PCC4, +}; + +static const unsigned usb_vbus_en1_pcc5_pins[] = { + TEGRA_PIN_USB_VBUS_EN1_PCC5, +}; + +static const unsigned dp_hpd0_pcc6_pins[] = { + TEGRA_PIN_DP_HPD0_PCC6, +}; + +static const unsigned pcc7_pins[] = { + TEGRA_PIN_PCC7, +}; + +static const unsigned spi2_cs1_pdd0_pins[] = { + TEGRA_PIN_SPI2_CS1_PDD0, +}; + +static const unsigned qspi_sck_pee0_pins[] = { + TEGRA_PIN_QSPI_SCK_PEE0, +}; + +static const unsigned qspi_cs_n_pee1_pins[] = { + TEGRA_PIN_QSPI_CS_N_PEE1, +}; + +static const unsigned qspi_io0_pee2_pins[] = { + TEGRA_PIN_QSPI_IO0_PEE2, +}; + +static const unsigned qspi_io1_pee3_pins[] = { + TEGRA_PIN_QSPI_IO1_PEE3, +}; + +static const unsigned qspi_io2_pee4_pins[] = { + TEGRA_PIN_QSPI_IO2_PEE4, +}; + +static const unsigned qspi_io3_pee5_pins[] = { + TEGRA_PIN_QSPI_IO3_PEE5, +}; + +static const unsigned core_pwr_req_pins[] = { + TEGRA_PIN_CORE_PWR_REQ, +}; + +static const unsigned cpu_pwr_req_pins[] = { + TEGRA_PIN_CPU_PWR_REQ, +}; + +static const unsigned pwr_int_n_pins[] = { + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned clk_32k_in_pins[] = { + TEGRA_PIN_CLK_32K_IN, +}; + +static const unsigned jtag_rtck_pins[] = { + TEGRA_PIN_JTAG_RTCK, +}; + +static const unsigned batt_bcl_pins[] = { + TEGRA_PIN_BATT_BCL, +}; + +static const unsigned clk_req_pins[] = { + TEGRA_PIN_CLK_REQ, +}; + +static const unsigned shutdown_pins[] = { + TEGRA_PIN_SHUTDOWN, +}; + +static const unsigned drive_pa6_pins[] = { + TEGRA_PIN_PA6, +}; + +static const unsigned drive_pcc7_pins[] = { + TEGRA_PIN_PCC7, +}; + +static const unsigned drive_pe6_pins[] = { + TEGRA_PIN_PE6, +}; + +static const unsigned drive_pe7_pins[] = { + TEGRA_PIN_PE7, +}; + +static const unsigned drive_ph6_pins[] = { + TEGRA_PIN_PH6, +}; + +static const unsigned drive_pk0_pins[] = { + TEGRA_PIN_PK0, +}; + +static const unsigned drive_pk1_pins[] = { + TEGRA_PIN_PK1, +}; + +static const unsigned drive_pk2_pins[] = { + TEGRA_PIN_PK2, +}; + +static const unsigned drive_pk3_pins[] = { + TEGRA_PIN_PK3, +}; + +static const unsigned drive_pk4_pins[] = { + TEGRA_PIN_PK4, +}; + +static const unsigned drive_pk5_pins[] = { + TEGRA_PIN_PK5, +}; + +static const unsigned drive_pk6_pins[] = { + TEGRA_PIN_PK6, +}; + +static const unsigned drive_pk7_pins[] = { + TEGRA_PIN_PK7, +}; + +static const unsigned drive_pl0_pins[] = { + TEGRA_PIN_PL0, +}; + +static const unsigned drive_pl1_pins[] = { + TEGRA_PIN_PL1, +}; + +static const unsigned drive_pz0_pins[] = { + TEGRA_PIN_PZ0, +}; + +static const unsigned drive_pz1_pins[] = { + TEGRA_PIN_PZ1, +}; + +static const unsigned drive_pz2_pins[] = { + TEGRA_PIN_PZ2, +}; + +static const unsigned drive_pz3_pins[] = { + TEGRA_PIN_PZ3, +}; + +static const unsigned drive_pz4_pins[] = { + TEGRA_PIN_PZ4, +}; + +static const unsigned drive_pz5_pins[] = { + TEGRA_PIN_PZ5, +}; + +static const unsigned drive_sdmmc1_pins[] = { + TEGRA_PIN_SDMMC1_CLK_PM0, + TEGRA_PIN_SDMMC1_CMD_PM1, + TEGRA_PIN_SDMMC1_DAT3_PM2, + TEGRA_PIN_SDMMC1_DAT2_PM3, + TEGRA_PIN_SDMMC1_DAT1_PM4, + TEGRA_PIN_SDMMC1_DAT0_PM5, +}; + +static const unsigned drive_sdmmc2_pins[] = { +}; + +static const unsigned drive_sdmmc3_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PP0, + TEGRA_PIN_SDMMC3_CMD_PP1, + TEGRA_PIN_SDMMC3_DAT3_PP2, + TEGRA_PIN_SDMMC3_DAT2_PP3, + TEGRA_PIN_SDMMC3_DAT1_PP4, + TEGRA_PIN_SDMMC3_DAT0_PP5, +}; + +static const unsigned drive_sdmmc4_pins[] = { +}; + +enum tegra_mux { + TEGRA_MUX_AUD, + TEGRA_MUX_BCL, + TEGRA_MUX_BLINK, + TEGRA_MUX_CCLA, + TEGRA_MUX_CEC, + TEGRA_MUX_CLDVFS, + TEGRA_MUX_CLK, + TEGRA_MUX_CORE, + TEGRA_MUX_CPU, + TEGRA_MUX_DISPLAYA, + TEGRA_MUX_DISPLAYB, + TEGRA_MUX_DMIC1, + TEGRA_MUX_DMIC2, + TEGRA_MUX_DMIC3, + TEGRA_MUX_DP, + TEGRA_MUX_DTV, + TEGRA_MUX_EXTPERIPH3, + TEGRA_MUX_I2C1, + TEGRA_MUX_I2C2, + TEGRA_MUX_I2C3, + TEGRA_MUX_I2CPMU, + TEGRA_MUX_I2CVI, + TEGRA_MUX_I2S1, + TEGRA_MUX_I2S2, + TEGRA_MUX_I2S3, + TEGRA_MUX_I2S4A, + TEGRA_MUX_I2S4B, + TEGRA_MUX_I2S5A, + TEGRA_MUX_I2S5B, + TEGRA_MUX_IQC0, + TEGRA_MUX_IQC1, + TEGRA_MUX_JTAG, + TEGRA_MUX_PE, + TEGRA_MUX_PE0, + TEGRA_MUX_PE1, + TEGRA_MUX_PMI, + TEGRA_MUX_PWM0, + TEGRA_MUX_PWM1, + TEGRA_MUX_PWM2, + TEGRA_MUX_PWM3, + TEGRA_MUX_QSPI, + TEGRA_MUX_RSVD0, + TEGRA_MUX_RSVD1, + TEGRA_MUX_RSVD2, + TEGRA_MUX_RSVD3, + TEGRA_MUX_SATA, + TEGRA_MUX_SDMMC1, + TEGRA_MUX_SDMMC3, + TEGRA_MUX_SHUTDOWN, + TEGRA_MUX_SOC, + TEGRA_MUX_SOR0, + TEGRA_MUX_SOR1, + TEGRA_MUX_SPDIF, + TEGRA_MUX_SPI1, + TEGRA_MUX_SPI2, + TEGRA_MUX_SPI3, + TEGRA_MUX_SPI4, + TEGRA_MUX_SYS, + TEGRA_MUX_TOUCH, + TEGRA_MUX_UART, + TEGRA_MUX_UARTA, + TEGRA_MUX_UARTB, + TEGRA_MUX_UARTC, + TEGRA_MUX_UARTD, + TEGRA_MUX_USB, + TEGRA_MUX_VGP1, + TEGRA_MUX_VGP2, + TEGRA_MUX_VGP3, + TEGRA_MUX_VGP4, + TEGRA_MUX_VGP5, + TEGRA_MUX_VGP6, + TEGRA_MUX_VIMCLK, + TEGRA_MUX_VIMCLK2, +}; + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + } + +static struct tegra_function tegra210_functions[] = { + FUNCTION(aud), + FUNCTION(bcl), + FUNCTION(blink), + FUNCTION(ccla), + FUNCTION(cec), + FUNCTION(cldvfs), + FUNCTION(clk), + FUNCTION(core), + FUNCTION(cpu), + FUNCTION(displaya), + FUNCTION(displayb), + FUNCTION(dmic1), + FUNCTION(dmic2), + FUNCTION(dmic3), + FUNCTION(dp), + FUNCTION(dtv), + FUNCTION(extperiph3), + FUNCTION(i2c1), + FUNCTION(i2c2), + FUNCTION(i2c3), + FUNCTION(i2cpmu), + FUNCTION(i2cvi), + FUNCTION(i2s1), + FUNCTION(i2s2), + FUNCTION(i2s3), + FUNCTION(i2s4a), + FUNCTION(i2s4b), + FUNCTION(i2s5a), + FUNCTION(i2s5b), + FUNCTION(iqc0), + FUNCTION(iqc1), + FUNCTION(jtag), + FUNCTION(pe), + FUNCTION(pe0), + FUNCTION(pe1), + FUNCTION(pmi), + FUNCTION(pwm0), + FUNCTION(pwm1), + FUNCTION(pwm2), + FUNCTION(pwm3), + FUNCTION(qspi), + FUNCTION(rsvd0), + FUNCTION(rsvd1), + FUNCTION(rsvd2), + FUNCTION(rsvd3), + FUNCTION(sata), + FUNCTION(sdmmc1), + FUNCTION(sdmmc3), + FUNCTION(shutdown), + FUNCTION(soc), + FUNCTION(sor0), + FUNCTION(sor1), + FUNCTION(spdif), + FUNCTION(spi1), + FUNCTION(spi2), + FUNCTION(spi3), + FUNCTION(spi4), + FUNCTION(sys), + FUNCTION(touch), + FUNCTION(uart), + FUNCTION(uarta), + FUNCTION(uartb), + FUNCTION(uartc), + FUNCTION(uartd), + FUNCTION(usb), + FUNCTION(vgp1), + FUNCTION(vgp2), + FUNCTION(vgp3), + FUNCTION(vgp4), + FUNCTION(vgp5), + FUNCTION(vgp6), + FUNCTION(vimclk), + FUNCTION(vimclk2), +}; + +#define DRV_PINGROUP_REG_A 0x8d4 /* bank 0 */ +#define PINGROUP_REG_A 0x3000 /* bank 1 */ + +#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A) +#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) + +#define PINGROUP_BIT_Y(b) (b) +#define PINGROUP_BIT_N(b) (-1) + +#define PINGROUP(pg_name, f0, f1, f2, f3, r, hsm, drvtype, e_io_hv, \ + rdrv, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, \ + slwr_w, slwf_b, slwf_w) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_##f0, \ + TEGRA_MUX_##f1, \ + TEGRA_MUX_##f2, \ + TEGRA_MUX_##f3, \ + }, \ + .mux_reg = PINGROUP_REG(r), \ + .mux_bank = 1, \ + .mux_bit = 0, \ + .pupd_reg = PINGROUP_REG(r), \ + .pupd_bank = 1, \ + .pupd_bit = 2, \ + .tri_reg = PINGROUP_REG(r), \ + .tri_bank = 1, \ + .tri_bit = 4, \ + .einput_bit = 6, \ + .odrain_bit = 11, \ + .lock_bit = 7, \ + .ioreset_bit = -1, \ + .rcv_sel_bit = PINGROUP_BIT_##e_io_hv(10), \ + .hsm_bit = PINGROUP_BIT_##hsm(9), \ + .schmitt_bit = 12, \ + .drvtype_bit = PINGROUP_BIT_##drvtype(13), \ + .drv_reg = DRV_PINGROUP_REG(rdrv), \ + .drv_bank = 0, \ + .lpmd_bit = -1, \ + .drvdn_bit = drvdn_b, \ + .drvdn_width = drvdn_w, \ + .drvup_bit = drvup_b, \ + .drvup_width = drvup_w, \ + .slwr_bit = slwr_b, \ + .slwr_width = slwr_w, \ + .slwf_bit = slwf_b, \ + .slwf_width = slwf_w, \ + } + +#define DRV_PINGROUP(pg_name, r, drvdn_b, drvdn_w, drvup_b, drvup_w, \ + slwr_b, slwr_w, slwf_b, slwf_w) \ + { \ + .name = "drive_" #pg_name, \ + .pins = drive_##pg_name##_pins, \ + .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ + .mux_reg = -1, \ + .pupd_reg = -1, \ + .tri_reg = -1, \ + .einput_bit = -1, \ + .odrain_bit = -1, \ + .lock_bit = -1, \ + .ioreset_bit = -1, \ + .rcv_sel_bit = -1, \ + .drv_reg = DRV_PINGROUP_REG(r), \ + .drv_bank = 0, \ + .hsm_bit = -1, \ + .schmitt_bit = -1, \ + .lpmd_bit = -1, \ + .drvdn_bit = drvdn_b, \ + .drvdn_width = drvdn_w, \ + .drvup_bit = drvup_b, \ + .drvup_width = drvup_w, \ + .slwr_bit = slwr_b, \ + .slwr_width = slwr_w, \ + .slwf_bit = slwf_b, \ + .slwf_width = slwf_w, \ + .drvtype_bit = -1, \ + } + +static const struct tegra_pingroup tegra210_groups[] = { + /* pg_name, f0, f1, f2, f3, r, hsm, drvtype, e_io_hv, rdrv, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */ + PINGROUP(sdmmc1_clk_pm0, SDMMC1, RSVD1, RSVD2, RSVD3, 0x3000, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc1_cmd_pm1, SDMMC1, SPI3, RSVD2, RSVD3, 0x3004, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc1_dat3_pm2, SDMMC1, SPI3, RSVD2, RSVD3, 0x3008, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc1_dat2_pm3, SDMMC1, SPI3, RSVD2, RSVD3, 0x300c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc1_dat1_pm4, SDMMC1, SPI3, RSVD2, RSVD3, 0x3010, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc1_dat0_pm5, SDMMC1, RSVD1, RSVD2, RSVD3, 0x3014, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc3_clk_pp0, SDMMC3, RSVD1, RSVD2, RSVD3, 0x301c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc3_cmd_pp1, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3020, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc3_dat0_pp5, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3024, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc3_dat1_pp4, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3028, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc3_dat2_pp3, SDMMC3, RSVD1, RSVD2, RSVD3, 0x302c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc3_dat3_pp2, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3030, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pex_l0_rst_n_pa0, PE0, RSVD1, RSVD2, RSVD3, 0x3038, N, N, Y, 0xa5c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pex_l0_clkreq_n_pa1, PE0, RSVD1, RSVD2, RSVD3, 0x303c, N, N, Y, 0xa58, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pex_wake_n_pa2, PE, RSVD1, RSVD2, RSVD3, 0x3040, N, N, Y, 0xa68, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pex_l1_rst_n_pa3, PE1, RSVD1, RSVD2, RSVD3, 0x3044, N, N, Y, 0xa64, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pex_l1_clkreq_n_pa4, PE1, RSVD1, RSVD2, RSVD3, 0x3048, N, N, Y, 0xa60, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(sata_led_active_pa5, SATA, RSVD1, RSVD2, RSVD3, 0x304c, N, N, N, 0xa94, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(spi1_mosi_pc0, SPI1, RSVD1, RSVD2, RSVD3, 0x3050, Y, Y, N, 0xae0, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi1_miso_pc1, SPI1, RSVD1, RSVD2, RSVD3, 0x3054, Y, Y, N, 0xadc, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi1_sck_pc2, SPI1, RSVD1, RSVD2, RSVD3, 0x3058, Y, Y, N, 0xae4, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi1_cs0_pc3, SPI1, RSVD1, RSVD2, RSVD3, 0x305c, Y, Y, N, 0xad4, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi1_cs1_pc4, SPI1, RSVD1, RSVD2, RSVD3, 0x3060, Y, Y, N, 0xad8, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi2_mosi_pb4, SPI2, DTV, RSVD2, RSVD3, 0x3064, Y, Y, N, 0xaf4, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi2_miso_pb5, SPI2, DTV, RSVD2, RSVD3, 0x3068, Y, Y, N, 0xaf0, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi2_sck_pb6, SPI2, DTV, RSVD2, RSVD3, 0x306c, Y, Y, N, 0xaf8, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi2_cs0_pb7, SPI2, DTV, RSVD2, RSVD3, 0x3070, Y, Y, N, 0xae8, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi2_cs1_pdd0, SPI2, RSVD1, RSVD2, RSVD3, 0x3074, Y, Y, N, 0xaec, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi4_mosi_pc7, SPI4, RSVD1, RSVD2, RSVD3, 0x3078, Y, Y, N, 0xb04, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi4_miso_pd0, SPI4, RSVD1, RSVD2, RSVD3, 0x307c, Y, Y, N, 0xb00, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi4_sck_pc5, SPI4, RSVD1, RSVD2, RSVD3, 0x3080, Y, Y, N, 0xb08, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi4_cs0_pc6, SPI4, RSVD1, RSVD2, RSVD3, 0x3084, Y, Y, N, 0xafc, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(qspi_sck_pee0, QSPI, RSVD1, RSVD2, RSVD3, 0x3088, Y, Y, N, 0xa90, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(qspi_cs_n_pee1, QSPI, RSVD1, RSVD2, RSVD3, 0x308c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(qspi_io0_pee2, QSPI, RSVD1, RSVD2, RSVD3, 0x3090, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(qspi_io1_pee3, QSPI, RSVD1, RSVD2, RSVD3, 0x3094, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(qspi_io2_pee4, QSPI, RSVD1, RSVD2, RSVD3, 0x3098, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(qspi_io3_pee5, QSPI, RSVD1, RSVD2, RSVD3, 0x309c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(dmic1_clk_pe0, DMIC1, I2S3, RSVD2, RSVD3, 0x30a4, N, N, N, 0x984, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dmic1_dat_pe1, DMIC1, I2S3, RSVD2, RSVD3, 0x30a8, N, N, N, 0x988, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dmic2_clk_pe2, DMIC2, I2S3, RSVD2, RSVD3, 0x30ac, N, N, N, 0x98c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dmic2_dat_pe3, DMIC2, I2S3, RSVD2, RSVD3, 0x30b0, N, N, N, 0x990, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dmic3_clk_pe4, DMIC3, I2S5A, RSVD2, RSVD3, 0x30b4, N, N, N, 0x994, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dmic3_dat_pe5, DMIC3, I2S5A, RSVD2, RSVD3, 0x30b8, N, N, N, 0x998, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gen1_i2c_scl_pj1, I2C1, RSVD1, RSVD2, RSVD3, 0x30bc, N, N, Y, 0x9a8, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gen1_i2c_sda_pj0, I2C1, RSVD1, RSVD2, RSVD3, 0x30c0, N, N, Y, 0x9ac, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gen2_i2c_scl_pj2, I2C2, RSVD1, RSVD2, RSVD3, 0x30c4, N, N, Y, 0x9b0, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gen2_i2c_sda_pj3, I2C2, RSVD1, RSVD2, RSVD3, 0x30c8, N, N, Y, 0x9b4, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gen3_i2c_scl_pf0, I2C3, RSVD1, RSVD2, RSVD3, 0x30cc, N, N, Y, 0x9b8, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gen3_i2c_sda_pf1, I2C3, RSVD1, RSVD2, RSVD3, 0x30d0, N, N, Y, 0x9bc, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam_i2c_scl_ps2, I2C3, I2CVI, RSVD2, RSVD3, 0x30d4, N, N, Y, 0x934, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam_i2c_sda_ps3, I2C3, I2CVI, RSVD2, RSVD3, 0x30d8, N, N, Y, 0x938, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pwr_i2c_scl_py3, I2CPMU, RSVD1, RSVD2, RSVD3, 0x30dc, N, N, Y, 0xa6c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pwr_i2c_sda_py4, I2CPMU, RSVD1, RSVD2, RSVD3, 0x30e0, N, N, Y, 0xa70, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart1_tx_pu0, UARTA, RSVD1, RSVD2, RSVD3, 0x30e4, N, N, N, 0xb28, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart1_rx_pu1, UARTA, RSVD1, RSVD2, RSVD3, 0x30e8, N, N, N, 0xb24, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart1_rts_pu2, UARTA, RSVD1, RSVD2, RSVD3, 0x30ec, N, N, N, 0xb20, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart1_cts_pu3, UARTA, RSVD1, RSVD2, RSVD3, 0x30f0, N, N, N, 0xb1c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart2_tx_pg0, UARTB, I2S4A, SPDIF, UART, 0x30f4, N, N, N, 0xb38, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart2_rx_pg1, UARTB, I2S4A, SPDIF, UART, 0x30f8, N, N, N, 0xb34, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart2_rts_pg2, UARTB, I2S4A, RSVD2, UART, 0x30fc, N, N, N, 0xb30, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart2_cts_pg3, UARTB, I2S4A, RSVD2, UART, 0x3100, N, N, N, 0xb2c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart3_tx_pd1, UARTC, SPI4, RSVD2, RSVD3, 0x3104, N, N, N, 0xb48, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart3_rx_pd2, UARTC, SPI4, RSVD2, RSVD3, 0x3108, N, N, N, 0xb44, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart3_rts_pd3, UARTC, SPI4, RSVD2, RSVD3, 0x310c, N, N, N, 0xb40, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart3_cts_pd4, UARTC, SPI4, RSVD2, RSVD3, 0x3110, N, N, N, 0xb3c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart4_tx_pi4, UARTD, UART, RSVD2, RSVD3, 0x3114, N, N, N, 0xb58, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart4_rx_pi5, UARTD, UART, RSVD2, RSVD3, 0x3118, N, N, N, 0xb54, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart4_rts_pi6, UARTD, UART, RSVD2, RSVD3, 0x311c, N, N, N, 0xb50, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart4_cts_pi7, UARTD, UART, RSVD2, RSVD3, 0x3120, N, N, N, 0xb4c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dap1_fs_pb0, I2S1, RSVD1, RSVD2, RSVD3, 0x3124, Y, Y, N, 0x95c, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(dap1_din_pb1, I2S1, RSVD1, RSVD2, RSVD3, 0x3128, Y, Y, N, 0x954, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(dap1_dout_pb2, I2S1, RSVD1, RSVD2, RSVD3, 0x312c, Y, Y, N, 0x958, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(dap1_sclk_pb3, I2S1, RSVD1, RSVD2, RSVD3, 0x3130, Y, Y, N, 0x960, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(dap2_fs_paa0, I2S2, RSVD1, RSVD2, RSVD3, 0x3134, Y, Y, N, 0x96c, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(dap2_din_paa2, I2S2, RSVD1, RSVD2, RSVD3, 0x3138, Y, Y, N, 0x964, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(dap2_dout_paa3, I2S2, RSVD1, RSVD2, RSVD3, 0x313c, Y, Y, N, 0x968, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(dap2_sclk_paa1, I2S2, RSVD1, RSVD2, RSVD3, 0x3140, Y, Y, N, 0x970, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(dap4_fs_pj4, I2S4B, RSVD1, RSVD2, RSVD3, 0x3144, N, N, N, 0x97c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dap4_din_pj5, I2S4B, RSVD1, RSVD2, RSVD3, 0x3148, N, N, N, 0x974, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dap4_dout_pj6, I2S4B, RSVD1, RSVD2, RSVD3, 0x314c, N, N, N, 0x978, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dap4_sclk_pj7, I2S4B, RSVD1, RSVD2, RSVD3, 0x3150, N, N, N, 0x980, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam1_mclk_ps0, EXTPERIPH3, RSVD1, RSVD2, RSVD3, 0x3154, N, N, N, 0x918, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam2_mclk_ps1, EXTPERIPH3, RSVD1, RSVD2, RSVD3, 0x3158, N, N, N, 0x924, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(jtag_rtck, JTAG, RSVD1, RSVD2, RSVD3, 0x315c, N, N, N, 0xa2c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(clk_32k_in, CLK, RSVD1, RSVD2, RSVD3, 0x3160, N, N, N, 0x940, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(clk_32k_out_py5, SOC, BLINK, RSVD2, RSVD3, 0x3164, N, N, N, 0x944, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(batt_bcl, BCL, RSVD1, RSVD2, RSVD3, 0x3168, N, N, Y, 0x8f8, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(clk_req, SYS, RSVD1, RSVD2, RSVD3, 0x316c, N, N, N, 0x948, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cpu_pwr_req, CPU, RSVD1, RSVD2, RSVD3, 0x3170, N, N, N, 0x950, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pwr_int_n, PMI, RSVD1, RSVD2, RSVD3, 0x3174, N, N, N, 0xa74, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(shutdown, SHUTDOWN, RSVD1, RSVD2, RSVD3, 0x3178, N, N, N, 0xac8, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(core_pwr_req, CORE, RSVD1, RSVD2, RSVD3, 0x317c, N, N, N, 0x94c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(aud_mclk_pbb0, AUD, RSVD1, RSVD2, RSVD3, 0x3180, N, N, N, 0x8f4, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dvfs_pwm_pbb1, RSVD0, CLDVFS, SPI3, RSVD3, 0x3184, N, N, N, 0x9a4, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dvfs_clk_pbb2, RSVD0, CLDVFS, SPI3, RSVD3, 0x3188, N, N, N, 0x9a0, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gpio_x1_aud_pbb3, RSVD0, RSVD1, SPI3, RSVD3, 0x318c, N, N, N, 0xa14, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gpio_x3_aud_pbb4, RSVD0, RSVD1, SPI3, RSVD3, 0x3190, N, N, N, 0xa18, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pcc7, RSVD0, RSVD1, RSVD2, RSVD3, 0x3194, N, N, Y, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(hdmi_cec_pcc0, CEC, RSVD1, RSVD2, RSVD3, 0x3198, N, N, Y, 0xa24, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(hdmi_int_dp_hpd_pcc1, DP, RSVD1, RSVD2, RSVD3, 0x319c, N, N, Y, 0xa28, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(spdif_out_pcc2, SPDIF, RSVD1, RSVD2, RSVD3, 0x31a0, N, N, N, 0xad0, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(spdif_in_pcc3, SPDIF, RSVD1, RSVD2, RSVD3, 0x31a4, N, N, N, 0xacc, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(usb_vbus_en0_pcc4, USB, RSVD1, RSVD2, RSVD3, 0x31a8, N, N, Y, 0xb5c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(usb_vbus_en1_pcc5, USB, RSVD1, RSVD2, RSVD3, 0x31ac, N, N, Y, 0xb60, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dp_hpd0_pcc6, DP, RSVD1, RSVD2, RSVD3, 0x31b0, N, N, N, 0x99c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(wifi_en_ph0, RSVD0, RSVD1, RSVD2, RSVD3, 0x31b4, N, N, N, 0xb64, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(wifi_rst_ph1, RSVD0, RSVD1, RSVD2, RSVD3, 0x31b8, N, N, N, 0xb68, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(wifi_wake_ap_ph2, RSVD0, RSVD1, RSVD2, RSVD3, 0x31bc, N, N, N, 0xb6c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(ap_wake_bt_ph3, RSVD0, UARTB, SPDIF, RSVD3, 0x31c0, N, N, N, 0x8ec, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(bt_rst_ph4, RSVD0, UARTB, SPDIF, RSVD3, 0x31c4, N, N, N, 0x8fc, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(bt_wake_ap_ph5, RSVD0, RSVD1, RSVD2, RSVD3, 0x31c8, N, N, N, 0x900, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(ap_wake_nfc_ph7, RSVD0, RSVD1, RSVD2, RSVD3, 0x31cc, N, N, N, 0x8f0, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(nfc_en_pi0, RSVD0, RSVD1, RSVD2, RSVD3, 0x31d0, N, N, N, 0xa50, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(nfc_int_pi1, RSVD0, RSVD1, RSVD2, RSVD3, 0x31d4, N, N, N, 0xa54, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gps_en_pi2, RSVD0, RSVD1, RSVD2, RSVD3, 0x31d8, N, N, N, 0xa1c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gps_rst_pi3, RSVD0, RSVD1, RSVD2, RSVD3, 0x31dc, N, N, N, 0xa20, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam_rst_ps4, VGP1, RSVD1, RSVD2, RSVD3, 0x31e0, N, N, N, 0x93c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam_af_en_ps5, VIMCLK, VGP2, RSVD2, RSVD3, 0x31e4, N, N, N, 0x92c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam_flash_en_ps6, VIMCLK, VGP3, RSVD2, RSVD3, 0x31e8, N, N, N, 0x930, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam1_pwdn_ps7, VGP4, RSVD1, RSVD2, RSVD3, 0x31ec, N, N, N, 0x91c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam2_pwdn_pt0, VGP5, RSVD1, RSVD2, RSVD3, 0x31f0, N, N, N, 0x928, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam1_strobe_pt1, VGP6, RSVD1, RSVD2, RSVD3, 0x31f4, N, N, N, 0x920, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(lcd_te_py2, DISPLAYA, RSVD1, RSVD2, RSVD3, 0x31f8, N, N, N, 0xa44, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(lcd_bl_pwm_pv0, DISPLAYA, PWM0, SOR0, RSVD3, 0x31fc, N, N, N, 0xa34, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(lcd_bl_en_pv1, RSVD0, RSVD1, RSVD2, RSVD3, 0x3200, N, N, N, 0xa30, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(lcd_rst_pv2, RSVD0, RSVD1, RSVD2, RSVD3, 0x3204, N, N, N, 0xa40, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(lcd_gpio1_pv3, DISPLAYB, RSVD1, RSVD2, RSVD3, 0x3208, N, N, N, 0xa38, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(lcd_gpio2_pv4, DISPLAYB, PWM1, RSVD2, SOR1, 0x320c, N, N, N, 0xa3c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(ap_ready_pv5, RSVD0, RSVD1, RSVD2, RSVD3, 0x3210, N, N, N, 0x8e8, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(touch_rst_pv6, RSVD0, RSVD1, RSVD2, RSVD3, 0x3214, N, N, N, 0xb18, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(touch_clk_pv7, TOUCH, RSVD1, RSVD2, RSVD3, 0x3218, N, N, N, 0xb10, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(modem_wake_ap_px0, RSVD0, RSVD1, RSVD2, RSVD3, 0x321c, N, N, N, 0xa48, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(touch_int_px1, RSVD0, RSVD1, RSVD2, RSVD3, 0x3220, N, N, N, 0xb14, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(motion_int_px2, RSVD0, RSVD1, RSVD2, RSVD3, 0x3224, N, N, N, 0xa4c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(als_prox_int_px3, RSVD0, RSVD1, RSVD2, RSVD3, 0x3228, N, N, N, 0x8e4, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(temp_alert_px4, RSVD0, RSVD1, RSVD2, RSVD3, 0x322c, N, N, N, 0xb0c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(button_power_on_px5, RSVD0, RSVD1, RSVD2, RSVD3, 0x3230, N, N, N, 0x908, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(button_vol_up_px6, RSVD0, RSVD1, RSVD2, RSVD3, 0x3234, N, N, N, 0x914, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(button_vol_down_px7, RSVD0, RSVD1, RSVD2, RSVD3, 0x3238, N, N, N, 0x910, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(button_slide_sw_py0, RSVD0, RSVD1, RSVD2, RSVD3, 0x323c, N, N, N, 0x90c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(button_home_py1, RSVD0, RSVD1, RSVD2, RSVD3, 0x3240, N, N, N, 0x904, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pa6, SATA, RSVD1, RSVD2, RSVD3, 0x3244, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pe6, RSVD0, I2S5A, PWM2, RSVD3, 0x3248, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pe7, RSVD0, I2S5A, PWM3, RSVD3, 0x324c, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(ph6, RSVD0, RSVD1, RSVD2, RSVD3, 0x3250, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pk0, IQC0, I2S5B, RSVD2, RSVD3, 0x3254, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pk1, IQC0, I2S5B, RSVD2, RSVD3, 0x3258, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pk2, IQC0, I2S5B, RSVD2, RSVD3, 0x325c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pk3, IQC0, I2S5B, RSVD2, RSVD3, 0x3260, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pk4, IQC1, RSVD1, RSVD2, RSVD3, 0x3264, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pk5, IQC1, RSVD1, RSVD2, RSVD3, 0x3268, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pk6, IQC1, RSVD1, RSVD2, RSVD3, 0x326c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pk7, IQC1, RSVD1, RSVD2, RSVD3, 0x3270, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pl0, RSVD0, RSVD1, RSVD2, RSVD3, 0x3274, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pl1, SOC, RSVD1, RSVD2, RSVD3, 0x3278, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pz0, VIMCLK2, RSVD1, RSVD2, RSVD3, 0x327c, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pz1, VIMCLK2, SDMMC1, RSVD2, RSVD3, 0x3280, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pz2, SDMMC3, CCLA, RSVD2, RSVD3, 0x3284, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pz3, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3288, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pz4, SDMMC1, RSVD1, RSVD2, RSVD3, 0x328c, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pz5, SOC, RSVD1, RSVD2, RSVD3, 0x3290, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + + /* pg_name, r, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */ + DRV_PINGROUP(pa6, 0x9c0, 12, 5, 20, 5, -1, -1, -1, -1), + DRV_PINGROUP(pcc7, 0x9c4, 12, 5, 20, 5, -1, -1, -1, -1), + DRV_PINGROUP(pe6, 0x9c8, 12, 5, 20, 5, -1, -1, -1, -1), + DRV_PINGROUP(pe7, 0x9cc, 12, 5, 20, 5, -1, -1, -1, -1), + DRV_PINGROUP(ph6, 0x9d0, 12, 5, 20, 5, -1, -1, -1, -1), + DRV_PINGROUP(pk0, 0x9d4, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pk1, 0x9d8, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pk2, 0x9dc, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pk3, 0x9e0, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pk4, 0x9e4, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pk5, 0x9e8, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pk6, 0x9ec, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pk7, 0x9f0, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pl0, 0x9f4, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pl1, 0x9f8, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pz0, 0x9fc, 12, 7, 20, 7, -1, -1, -1, -1), + DRV_PINGROUP(pz1, 0xa00, 12, 7, 20, 7, -1, -1, -1, -1), + DRV_PINGROUP(pz2, 0xa04, 12, 7, 20, 7, -1, -1, -1, -1), + DRV_PINGROUP(pz3, 0xa08, 12, 7, 20, 7, -1, -1, -1, -1), + DRV_PINGROUP(pz4, 0xa0c, 12, 7, 20, 7, -1, -1, -1, -1), + DRV_PINGROUP(pz5, 0xa10, 12, 7, 20, 7, -1, -1, -1, -1), + DRV_PINGROUP(sdmmc1, 0xa98, 12, 7, 20, 7, 28, 2, 30, 2), + DRV_PINGROUP(sdmmc2, 0xa9c, 2, 6, 8, 6, 28, 2, 30, 2), + DRV_PINGROUP(sdmmc3, 0xab0, 12, 7, 20, 7, 28, 2, 30, 2), + DRV_PINGROUP(sdmmc4, 0xab4, 2, 6, 8, 6, 28, 2, 30, 2), +}; + +static const struct tegra_pinctrl_soc_data tegra210_pinctrl = { + .ngpios = NUM_GPIOS, + .pins = tegra210_pins, + .npins = ARRAY_SIZE(tegra210_pins), + .functions = tegra210_functions, + .nfunctions = ARRAY_SIZE(tegra210_functions), + .groups = tegra210_groups, + .ngroups = ARRAY_SIZE(tegra210_groups), + .hsm_in_mux = true, + .schmitt_in_mux = true, + .drvtype_in_mux = true, +}; + +static int tegra210_pinctrl_probe(struct platform_device *pdev) +{ + return tegra_pinctrl_probe(pdev, &tegra210_pinctrl); +} + +static const struct of_device_id tegra210_pinctrl_of_match[] = { + { .compatible = "nvidia,tegra210-pinmux", }, + { }, +}; +MODULE_DEVICE_TABLE(of, tegra210_pinctrl_of_match); + +static struct platform_driver tegra210_pinctrl_driver = { + .driver = { + .name = "tegra210-pinctrl", + .of_match_table = tegra210_pinctrl_of_match, + }, + .probe = tegra210_pinctrl_probe, + .remove = tegra_pinctrl_remove, +}; +module_platform_driver(tegra210_pinctrl_driver); + +MODULE_AUTHOR("NVIDIA"); +MODULE_DESCRIPTION("NVIDIA Tegra210 pinctrl driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra30.c b/drivers/pinctrl/tegra/pinctrl-tegra30.c new file mode 100644 index 000000000000..47b2fd8bb2e9 --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra30.c @@ -0,0 +1,2507 @@ +/* + * Pinctrl data for the NVIDIA Tegra30 pinmux + * + * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#include +#include +#include +#include +#include + +#include "pinctrl-tegra.h" + +/* + * Most pins affected by the pinmux can also be GPIOs. Define these first. + * These must match how the GPIO driver names/numbers its pins. + */ +#define _GPIO(offset) (offset) + +#define TEGRA_PIN_CLK_32K_OUT_PA0 _GPIO(0) +#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) +#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) +#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) +#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) +#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) +#define TEGRA_PIN_SDMMC3_CLK_PA6 _GPIO(6) +#define TEGRA_PIN_SDMMC3_CMD_PA7 _GPIO(7) +#define TEGRA_PIN_GMI_A17_PB0 _GPIO(8) +#define TEGRA_PIN_GMI_A18_PB1 _GPIO(9) +#define TEGRA_PIN_LCD_PWR0_PB2 _GPIO(10) +#define TEGRA_PIN_LCD_PCLK_PB3 _GPIO(11) +#define TEGRA_PIN_SDMMC3_DAT3_PB4 _GPIO(12) +#define TEGRA_PIN_SDMMC3_DAT2_PB5 _GPIO(13) +#define TEGRA_PIN_SDMMC3_DAT1_PB6 _GPIO(14) +#define TEGRA_PIN_SDMMC3_DAT0_PB7 _GPIO(15) +#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) +#define TEGRA_PIN_LCD_PWR1_PC1 _GPIO(17) +#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) +#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) +#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) +#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) +#define TEGRA_PIN_LCD_PWR2_PC6 _GPIO(22) +#define TEGRA_PIN_GMI_WP_N_PC7 _GPIO(23) +#define TEGRA_PIN_SDMMC3_DAT5_PD0 _GPIO(24) +#define TEGRA_PIN_SDMMC3_DAT4_PD1 _GPIO(25) +#define TEGRA_PIN_LCD_DC1_PD2 _GPIO(26) +#define TEGRA_PIN_SDMMC3_DAT6_PD3 _GPIO(27) +#define TEGRA_PIN_SDMMC3_DAT7_PD4 _GPIO(28) +#define TEGRA_PIN_VI_D1_PD5 _GPIO(29) +#define TEGRA_PIN_VI_VSYNC_PD6 _GPIO(30) +#define TEGRA_PIN_VI_HSYNC_PD7 _GPIO(31) +#define TEGRA_PIN_LCD_D0_PE0 _GPIO(32) +#define TEGRA_PIN_LCD_D1_PE1 _GPIO(33) +#define TEGRA_PIN_LCD_D2_PE2 _GPIO(34) +#define TEGRA_PIN_LCD_D3_PE3 _GPIO(35) +#define TEGRA_PIN_LCD_D4_PE4 _GPIO(36) +#define TEGRA_PIN_LCD_D5_PE5 _GPIO(37) +#define TEGRA_PIN_LCD_D6_PE6 _GPIO(38) +#define TEGRA_PIN_LCD_D7_PE7 _GPIO(39) +#define TEGRA_PIN_LCD_D8_PF0 _GPIO(40) +#define TEGRA_PIN_LCD_D9_PF1 _GPIO(41) +#define TEGRA_PIN_LCD_D10_PF2 _GPIO(42) +#define TEGRA_PIN_LCD_D11_PF3 _GPIO(43) +#define TEGRA_PIN_LCD_D12_PF4 _GPIO(44) +#define TEGRA_PIN_LCD_D13_PF5 _GPIO(45) +#define TEGRA_PIN_LCD_D14_PF6 _GPIO(46) +#define TEGRA_PIN_LCD_D15_PF7 _GPIO(47) +#define TEGRA_PIN_GMI_AD0_PG0 _GPIO(48) +#define TEGRA_PIN_GMI_AD1_PG1 _GPIO(49) +#define TEGRA_PIN_GMI_AD2_PG2 _GPIO(50) +#define TEGRA_PIN_GMI_AD3_PG3 _GPIO(51) +#define TEGRA_PIN_GMI_AD4_PG4 _GPIO(52) +#define TEGRA_PIN_GMI_AD5_PG5 _GPIO(53) +#define TEGRA_PIN_GMI_AD6_PG6 _GPIO(54) +#define TEGRA_PIN_GMI_AD7_PG7 _GPIO(55) +#define TEGRA_PIN_GMI_AD8_PH0 _GPIO(56) +#define TEGRA_PIN_GMI_AD9_PH1 _GPIO(57) +#define TEGRA_PIN_GMI_AD10_PH2 _GPIO(58) +#define TEGRA_PIN_GMI_AD11_PH3 _GPIO(59) +#define TEGRA_PIN_GMI_AD12_PH4 _GPIO(60) +#define TEGRA_PIN_GMI_AD13_PH5 _GPIO(61) +#define TEGRA_PIN_GMI_AD14_PH6 _GPIO(62) +#define TEGRA_PIN_GMI_AD15_PH7 _GPIO(63) +#define TEGRA_PIN_GMI_WR_N_PI0 _GPIO(64) +#define TEGRA_PIN_GMI_OE_N_PI1 _GPIO(65) +#define TEGRA_PIN_GMI_DQS_PI2 _GPIO(66) +#define TEGRA_PIN_GMI_CS6_N_PI3 _GPIO(67) +#define TEGRA_PIN_GMI_RST_N_PI4 _GPIO(68) +#define TEGRA_PIN_GMI_IORDY_PI5 _GPIO(69) +#define TEGRA_PIN_GMI_CS7_N_PI6 _GPIO(70) +#define TEGRA_PIN_GMI_WAIT_PI7 _GPIO(71) +#define TEGRA_PIN_GMI_CS0_N_PJ0 _GPIO(72) +#define TEGRA_PIN_LCD_DE_PJ1 _GPIO(73) +#define TEGRA_PIN_GMI_CS1_N_PJ2 _GPIO(74) +#define TEGRA_PIN_LCD_HSYNC_PJ3 _GPIO(75) +#define TEGRA_PIN_LCD_VSYNC_PJ4 _GPIO(76) +#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) +#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) +#define TEGRA_PIN_GMI_A16_PJ7 _GPIO(79) +#define TEGRA_PIN_GMI_ADV_N_PK0 _GPIO(80) +#define TEGRA_PIN_GMI_CLK_PK1 _GPIO(81) +#define TEGRA_PIN_GMI_CS4_N_PK2 _GPIO(82) +#define TEGRA_PIN_GMI_CS2_N_PK3 _GPIO(83) +#define TEGRA_PIN_GMI_CS3_N_PK4 _GPIO(84) +#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) +#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) +#define TEGRA_PIN_GMI_A19_PK7 _GPIO(87) +#define TEGRA_PIN_VI_D2_PL0 _GPIO(88) +#define TEGRA_PIN_VI_D3_PL1 _GPIO(89) +#define TEGRA_PIN_VI_D4_PL2 _GPIO(90) +#define TEGRA_PIN_VI_D5_PL3 _GPIO(91) +#define TEGRA_PIN_VI_D6_PL4 _GPIO(92) +#define TEGRA_PIN_VI_D7_PL5 _GPIO(93) +#define TEGRA_PIN_VI_D8_PL6 _GPIO(94) +#define TEGRA_PIN_VI_D9_PL7 _GPIO(95) +#define TEGRA_PIN_LCD_D16_PM0 _GPIO(96) +#define TEGRA_PIN_LCD_D17_PM1 _GPIO(97) +#define TEGRA_PIN_LCD_D18_PM2 _GPIO(98) +#define TEGRA_PIN_LCD_D19_PM3 _GPIO(99) +#define TEGRA_PIN_LCD_D20_PM4 _GPIO(100) +#define TEGRA_PIN_LCD_D21_PM5 _GPIO(101) +#define TEGRA_PIN_LCD_D22_PM6 _GPIO(102) +#define TEGRA_PIN_LCD_D23_PM7 _GPIO(103) +#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) +#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) +#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) +#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) +#define TEGRA_PIN_LCD_CS0_N_PN4 _GPIO(108) +#define TEGRA_PIN_LCD_SDOUT_PN5 _GPIO(109) +#define TEGRA_PIN_LCD_DC0_PN6 _GPIO(110) +#define TEGRA_PIN_HDMI_INT_PN7 _GPIO(111) +#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) +#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) +#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) +#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) +#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) +#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) +#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) +#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) +#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) +#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) +#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) +#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) +#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) +#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) +#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) +#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) +#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) +#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) +#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) +#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) +#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) +#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) +#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) +#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) +#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) +#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) +#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) +#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) +#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) +#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) +#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) +#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) +#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) +#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) +#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) +#define TEGRA_PIN_KB_ROW11_PS3 _GPIO(147) +#define TEGRA_PIN_KB_ROW12_PS4 _GPIO(148) +#define TEGRA_PIN_KB_ROW13_PS5 _GPIO(149) +#define TEGRA_PIN_KB_ROW14_PS6 _GPIO(150) +#define TEGRA_PIN_KB_ROW15_PS7 _GPIO(151) +#define TEGRA_PIN_VI_PCLK_PT0 _GPIO(152) +#define TEGRA_PIN_VI_MCLK_PT1 _GPIO(153) +#define TEGRA_PIN_VI_D10_PT2 _GPIO(154) +#define TEGRA_PIN_VI_D11_PT3 _GPIO(155) +#define TEGRA_PIN_VI_D0_PT4 _GPIO(156) +#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) +#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) +#define TEGRA_PIN_SDMMC4_CMD_PT7 _GPIO(159) +#define TEGRA_PIN_PU0 _GPIO(160) +#define TEGRA_PIN_PU1 _GPIO(161) +#define TEGRA_PIN_PU2 _GPIO(162) +#define TEGRA_PIN_PU3 _GPIO(163) +#define TEGRA_PIN_PU4 _GPIO(164) +#define TEGRA_PIN_PU5 _GPIO(165) +#define TEGRA_PIN_PU6 _GPIO(166) +#define TEGRA_PIN_JTAG_RTCK_PU7 _GPIO(167) +#define TEGRA_PIN_PV0 _GPIO(168) +#define TEGRA_PIN_PV1 _GPIO(169) +#define TEGRA_PIN_PV2 _GPIO(170) +#define TEGRA_PIN_PV3 _GPIO(171) +#define TEGRA_PIN_DDC_SCL_PV4 _GPIO(172) +#define TEGRA_PIN_DDC_SDA_PV5 _GPIO(173) +#define TEGRA_PIN_CRT_HSYNC_PV6 _GPIO(174) +#define TEGRA_PIN_CRT_VSYNC_PV7 _GPIO(175) +#define TEGRA_PIN_LCD_CS1_N_PW0 _GPIO(176) +#define TEGRA_PIN_LCD_M1_PW1 _GPIO(177) +#define TEGRA_PIN_SPI2_CS1_N_PW2 _GPIO(178) +#define TEGRA_PIN_SPI2_CS2_N_PW3 _GPIO(179) +#define TEGRA_PIN_CLK1_OUT_PW4 _GPIO(180) +#define TEGRA_PIN_CLK2_OUT_PW5 _GPIO(181) +#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) +#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) +#define TEGRA_PIN_SPI2_MOSI_PX0 _GPIO(184) +#define TEGRA_PIN_SPI2_MISO_PX1 _GPIO(185) +#define TEGRA_PIN_SPI2_SCK_PX2 _GPIO(186) +#define TEGRA_PIN_SPI2_CS0_N_PX3 _GPIO(187) +#define TEGRA_PIN_SPI1_MOSI_PX4 _GPIO(188) +#define TEGRA_PIN_SPI1_SCK_PX5 _GPIO(189) +#define TEGRA_PIN_SPI1_CS0_N_PX6 _GPIO(190) +#define TEGRA_PIN_SPI1_MISO_PX7 _GPIO(191) +#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) +#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) +#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) +#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) +#define TEGRA_PIN_SDMMC1_DAT3_PY4 _GPIO(196) +#define TEGRA_PIN_SDMMC1_DAT2_PY5 _GPIO(197) +#define TEGRA_PIN_SDMMC1_DAT1_PY6 _GPIO(198) +#define TEGRA_PIN_SDMMC1_DAT0_PY7 _GPIO(199) +#define TEGRA_PIN_SDMMC1_CLK_PZ0 _GPIO(200) +#define TEGRA_PIN_SDMMC1_CMD_PZ1 _GPIO(201) +#define TEGRA_PIN_LCD_SDIN_PZ2 _GPIO(202) +#define TEGRA_PIN_LCD_WR_N_PZ3 _GPIO(203) +#define TEGRA_PIN_LCD_SCK_PZ4 _GPIO(204) +#define TEGRA_PIN_SYS_CLK_REQ_PZ5 _GPIO(205) +#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) +#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) +#define TEGRA_PIN_SDMMC4_DAT0_PAA0 _GPIO(208) +#define TEGRA_PIN_SDMMC4_DAT1_PAA1 _GPIO(209) +#define TEGRA_PIN_SDMMC4_DAT2_PAA2 _GPIO(210) +#define TEGRA_PIN_SDMMC4_DAT3_PAA3 _GPIO(211) +#define TEGRA_PIN_SDMMC4_DAT4_PAA4 _GPIO(212) +#define TEGRA_PIN_SDMMC4_DAT5_PAA5 _GPIO(213) +#define TEGRA_PIN_SDMMC4_DAT6_PAA6 _GPIO(214) +#define TEGRA_PIN_SDMMC4_DAT7_PAA7 _GPIO(215) +#define TEGRA_PIN_PBB0 _GPIO(216) +#define TEGRA_PIN_CAM_I2C_SCL_PBB1 _GPIO(217) +#define TEGRA_PIN_CAM_I2C_SDA_PBB2 _GPIO(218) +#define TEGRA_PIN_PBB3 _GPIO(219) +#define TEGRA_PIN_PBB4 _GPIO(220) +#define TEGRA_PIN_PBB5 _GPIO(221) +#define TEGRA_PIN_PBB6 _GPIO(222) +#define TEGRA_PIN_PBB7 _GPIO(223) +#define TEGRA_PIN_CAM_MCLK_PCC0 _GPIO(224) +#define TEGRA_PIN_PCC1 _GPIO(225) +#define TEGRA_PIN_PCC2 _GPIO(226) +#define TEGRA_PIN_SDMMC4_RST_N_PCC3 _GPIO(227) +#define TEGRA_PIN_SDMMC4_CLK_PCC4 _GPIO(228) +#define TEGRA_PIN_CLK2_REQ_PCC5 _GPIO(229) +#define TEGRA_PIN_PEX_L2_RST_N_PCC6 _GPIO(230) +#define TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7 _GPIO(231) +#define TEGRA_PIN_PEX_L0_PRSNT_N_PDD0 _GPIO(232) +#define TEGRA_PIN_PEX_L0_RST_N_PDD1 _GPIO(233) +#define TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2 _GPIO(234) +#define TEGRA_PIN_PEX_WAKE_N_PDD3 _GPIO(235) +#define TEGRA_PIN_PEX_L1_PRSNT_N_PDD4 _GPIO(236) +#define TEGRA_PIN_PEX_L1_RST_N_PDD5 _GPIO(237) +#define TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6 _GPIO(238) +#define TEGRA_PIN_PEX_L2_PRSNT_N_PDD7 _GPIO(239) +#define TEGRA_PIN_CLK3_OUT_PEE0 _GPIO(240) +#define TEGRA_PIN_CLK3_REQ_PEE1 _GPIO(241) +#define TEGRA_PIN_CLK1_REQ_PEE2 _GPIO(242) +#define TEGRA_PIN_HDMI_CEC_PEE3 _GPIO(243) +#define TEGRA_PIN_PEE4 _GPIO(244) +#define TEGRA_PIN_PEE5 _GPIO(245) +#define TEGRA_PIN_PEE6 _GPIO(246) +#define TEGRA_PIN_PEE7 _GPIO(247) + +/* All non-GPIO pins follow */ +#define NUM_GPIOS (TEGRA_PIN_PEE7 + 1) +#define _PIN(offset) (NUM_GPIOS + (offset)) + +/* Non-GPIO pins */ +#define TEGRA_PIN_CLK_32K_IN _PIN(0) +#define TEGRA_PIN_CORE_PWR_REQ _PIN(1) +#define TEGRA_PIN_CPU_PWR_REQ _PIN(2) +#define TEGRA_PIN_JTAG_TCK _PIN(3) +#define TEGRA_PIN_JTAG_TDI _PIN(4) +#define TEGRA_PIN_JTAG_TDO _PIN(5) +#define TEGRA_PIN_JTAG_TMS _PIN(6) +#define TEGRA_PIN_JTAG_TRST_N _PIN(7) +#define TEGRA_PIN_OWR _PIN(8) +#define TEGRA_PIN_PWR_INT_N _PIN(9) +#define TEGRA_PIN_SYS_RESET_N _PIN(10) +#define TEGRA_PIN_TEST_MODE_EN _PIN(11) + +static const struct pinctrl_pin_desc tegra30_pins[] = { + PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"), + PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), + PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), + PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"), + PINCTRL_PIN(TEGRA_PIN_GMI_A17_PB0, "GMI_A17 PB0"), + PINCTRL_PIN(TEGRA_PIN_GMI_A18_PB1, "GMI_A18 PB1"), + PINCTRL_PIN(TEGRA_PIN_LCD_PWR0_PB2, "LCD_PWR0 PB2"), + PINCTRL_PIN(TEGRA_PIN_LCD_PCLK_PB3, "LCD_PCLK PB3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"), + PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), + PINCTRL_PIN(TEGRA_PIN_LCD_PWR1_PC1, "LCD_PWR1 PC1"), + PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), + PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), + PINCTRL_PIN(TEGRA_PIN_LCD_PWR2_PC6, "LCD_PWR2 PC6"), + PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT5_PD0, "SDMMC3_DAT5 PD0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT4_PD1, "SDMMC3_DAT4 PD1"), + PINCTRL_PIN(TEGRA_PIN_LCD_DC1_PD2, "LCD_DC1 PD2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT6_PD3, "SDMMC3_DAT6 PD3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT7_PD4, "SDMMC3_DAT7 PD4"), + PINCTRL_PIN(TEGRA_PIN_VI_D1_PD5, "VI_D1 PD5"), + PINCTRL_PIN(TEGRA_PIN_VI_VSYNC_PD6, "VI_VSYNC PD6"), + PINCTRL_PIN(TEGRA_PIN_VI_HSYNC_PD7, "VI_HSYNC PD7"), + PINCTRL_PIN(TEGRA_PIN_LCD_D0_PE0, "LCD_D0 PE0"), + PINCTRL_PIN(TEGRA_PIN_LCD_D1_PE1, "LCD_D1 PE1"), + PINCTRL_PIN(TEGRA_PIN_LCD_D2_PE2, "LCD_D2 PE2"), + PINCTRL_PIN(TEGRA_PIN_LCD_D3_PE3, "LCD_D3 PE3"), + PINCTRL_PIN(TEGRA_PIN_LCD_D4_PE4, "LCD_D4 PE4"), + PINCTRL_PIN(TEGRA_PIN_LCD_D5_PE5, "LCD_D5 PE5"), + PINCTRL_PIN(TEGRA_PIN_LCD_D6_PE6, "LCD_D6 PE6"), + PINCTRL_PIN(TEGRA_PIN_LCD_D7_PE7, "LCD_D7 PE7"), + PINCTRL_PIN(TEGRA_PIN_LCD_D8_PF0, "LCD_D8 PF0"), + PINCTRL_PIN(TEGRA_PIN_LCD_D9_PF1, "LCD_D9 PF1"), + PINCTRL_PIN(TEGRA_PIN_LCD_D10_PF2, "LCD_D10 PF2"), + PINCTRL_PIN(TEGRA_PIN_LCD_D11_PF3, "LCD_D11 PF3"), + PINCTRL_PIN(TEGRA_PIN_LCD_D12_PF4, "LCD_D12 PF4"), + PINCTRL_PIN(TEGRA_PIN_LCD_D13_PF5, "LCD_D13 PF5"), + PINCTRL_PIN(TEGRA_PIN_LCD_D14_PF6, "LCD_D14 PF6"), + PINCTRL_PIN(TEGRA_PIN_LCD_D15_PF7, "LCD_D15 PF7"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"), + PINCTRL_PIN(TEGRA_PIN_GMI_WR_N_PI0, "GMI_WR_N PI0"), + PINCTRL_PIN(TEGRA_PIN_GMI_OE_N_PI1, "GMI_OE_N PI1"), + PINCTRL_PIN(TEGRA_PIN_GMI_DQS_PI2, "GMI_DQS PI2"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"), + PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"), + PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"), + PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"), + PINCTRL_PIN(TEGRA_PIN_LCD_DE_PJ1, "LCD_DE PJ1"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"), + PINCTRL_PIN(TEGRA_PIN_LCD_HSYNC_PJ3, "LCD_HSYNC PJ3"), + PINCTRL_PIN(TEGRA_PIN_LCD_VSYNC_PJ4, "LCD_VSYNC PJ4"), + PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), + PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), + PINCTRL_PIN(TEGRA_PIN_GMI_A16_PJ7, "GMI_A16 PJ7"), + PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"), + PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), + PINCTRL_PIN(TEGRA_PIN_GMI_A19_PK7, "GMI_A19 PK7"), + PINCTRL_PIN(TEGRA_PIN_VI_D2_PL0, "VI_D2 PL0"), + PINCTRL_PIN(TEGRA_PIN_VI_D3_PL1, "VI_D3 PL1"), + PINCTRL_PIN(TEGRA_PIN_VI_D4_PL2, "VI_D4 PL2"), + PINCTRL_PIN(TEGRA_PIN_VI_D5_PL3, "VI_D5 PL3"), + PINCTRL_PIN(TEGRA_PIN_VI_D6_PL4, "VI_D6 PL4"), + PINCTRL_PIN(TEGRA_PIN_VI_D7_PL5, "VI_D7 PL5"), + PINCTRL_PIN(TEGRA_PIN_VI_D8_PL6, "VI_D8 PL6"), + PINCTRL_PIN(TEGRA_PIN_VI_D9_PL7, "VI_D9 PL7"), + PINCTRL_PIN(TEGRA_PIN_LCD_D16_PM0, "LCD_D16 PM0"), + PINCTRL_PIN(TEGRA_PIN_LCD_D17_PM1, "LCD_D17 PM1"), + PINCTRL_PIN(TEGRA_PIN_LCD_D18_PM2, "LCD_D18 PM2"), + PINCTRL_PIN(TEGRA_PIN_LCD_D19_PM3, "LCD_D19 PM3"), + PINCTRL_PIN(TEGRA_PIN_LCD_D20_PM4, "LCD_D20 PM4"), + PINCTRL_PIN(TEGRA_PIN_LCD_D21_PM5, "LCD_D21 PM5"), + PINCTRL_PIN(TEGRA_PIN_LCD_D22_PM6, "LCD_D22 PM6"), + PINCTRL_PIN(TEGRA_PIN_LCD_D23_PM7, "LCD_D23 PM7"), + PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), + PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), + PINCTRL_PIN(TEGRA_PIN_LCD_CS0_N_PN4, "LCD_CS0_N PN4"), + PINCTRL_PIN(TEGRA_PIN_LCD_SDOUT_PN5, "LCD_SDOUT PN5"), + PINCTRL_PIN(TEGRA_PIN_LCD_DC0_PN6, "LCD_DC0 PN6"), + PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), + PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), + PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), + PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), + PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), + PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), + PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), + PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), + PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), + PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), + PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), + PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), + PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"), + PINCTRL_PIN(TEGRA_PIN_VI_PCLK_PT0, "VI_PCLK PT0"), + PINCTRL_PIN(TEGRA_PIN_VI_MCLK_PT1, "VI_MCLK PT1"), + PINCTRL_PIN(TEGRA_PIN_VI_D10_PT2, "VI_D10 PT2"), + PINCTRL_PIN(TEGRA_PIN_VI_D11_PT3, "VI_D11 PT3"), + PINCTRL_PIN(TEGRA_PIN_VI_D0_PT4, "VI_D0 PT4"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"), + PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), + PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), + PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), + PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), + PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), + PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), + PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), + PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK_PU7, "JTAG_RTCK PU7"), + PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), + PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), + PINCTRL_PIN(TEGRA_PIN_PV2, "PV2"), + PINCTRL_PIN(TEGRA_PIN_PV3, "PV3"), + PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"), + PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"), + PINCTRL_PIN(TEGRA_PIN_CRT_HSYNC_PV6, "CRT_HSYNC PV6"), + PINCTRL_PIN(TEGRA_PIN_CRT_VSYNC_PV7, "CRT_VSYNC PV7"), + PINCTRL_PIN(TEGRA_PIN_LCD_CS1_N_PW0, "LCD_CS1_N PW0"), + PINCTRL_PIN(TEGRA_PIN_LCD_M1_PW1, "LCD_M1 PW1"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_N_PW2, "SPI2_CS1_N PW2"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS2_N_PW3, "SPI2_CS2_N PW3"), + PINCTRL_PIN(TEGRA_PIN_CLK1_OUT_PW4, "CLK1_OUT PW4"), + PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"), + PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), + PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), + PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PX0, "SPI2_MOSI PX0"), + PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PX1, "SPI2_MISO PX1"), + PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PX2, "SPI2_SCK PX2"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_N_PX3, "SPI2_CS0_N PX3"), + PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PX4, "SPI1_MOSI PX4"), + PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PX5, "SPI1_SCK PX5"), + PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_N_PX6, "SPI1_CS0_N PX6"), + PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PX7, "SPI1_MISO PX7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"), + PINCTRL_PIN(TEGRA_PIN_LCD_SDIN_PZ2, "LCD_SDIN PZ2"), + PINCTRL_PIN(TEGRA_PIN_LCD_WR_N_PZ3, "LCD_WR_N PZ3"), + PINCTRL_PIN(TEGRA_PIN_LCD_SCK_PZ4, "LCD_SCK PZ4"), + PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"), + PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"), + PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"), + PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"), + PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"), + PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), + PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), + PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"), + PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"), + PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_RST_N_PCC3, "SDMMC4_RST_N PCC3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"), + PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"), + PINCTRL_PIN(TEGRA_PIN_PEX_L2_RST_N_PCC6, "PEX_L2_RST_N PCC6"), + PINCTRL_PIN(TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7, "PEX_L2_CLKREQ_N PCC7"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_PRSNT_N_PDD0, "PEX_L0_PRSNT_N PDD0"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PDD1, "PEX_L0_RST_N PDD1"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, "PEX_L0_CLKREQ_N PDD2"), + PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PDD3, "PEX_WAKE_N PDD3"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_PRSNT_N_PDD4, "PEX_L1_PRSNT_N PDD4"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PDD5, "PEX_L1_RST_N PDD5"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, "PEX_L1_CLKREQ_N PDD6"), + PINCTRL_PIN(TEGRA_PIN_PEX_L2_PRSNT_N_PDD7, "PEX_L2_PRSNT_N PDD7"), + PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"), + PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"), + PINCTRL_PIN(TEGRA_PIN_CLK1_REQ_PEE2, "CLK1_REQ PEE2"), + PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"), + PINCTRL_PIN(TEGRA_PIN_PEE4, "PEE4"), + PINCTRL_PIN(TEGRA_PIN_PEE5, "PEE5"), + PINCTRL_PIN(TEGRA_PIN_PEE6, "PEE6"), + PINCTRL_PIN(TEGRA_PIN_PEE7, "PEE7"), + PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), + PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TCK, "JTAG_TCK"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TDI, "JTAG_TDI"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TDO, "JTAG_TDO"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TMS, "JTAG_TMS"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TRST_N, "JTAG_TRST_N"), + PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"), + PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), + PINCTRL_PIN(TEGRA_PIN_SYS_RESET_N, "SYS_RESET_N"), + PINCTRL_PIN(TEGRA_PIN_TEST_MODE_EN, "TEST_MODE_EN"), +}; + +static const unsigned clk_32k_out_pa0_pins[] = { + TEGRA_PIN_CLK_32K_OUT_PA0, +}; + +static const unsigned uart3_cts_n_pa1_pins[] = { + TEGRA_PIN_UART3_CTS_N_PA1, +}; + +static const unsigned dap2_fs_pa2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, +}; + +static const unsigned dap2_sclk_pa3_pins[] = { + TEGRA_PIN_DAP2_SCLK_PA3, +}; + +static const unsigned dap2_din_pa4_pins[] = { + TEGRA_PIN_DAP2_DIN_PA4, +}; + +static const unsigned dap2_dout_pa5_pins[] = { + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned sdmmc3_clk_pa6_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PA6, +}; + +static const unsigned sdmmc3_cmd_pa7_pins[] = { + TEGRA_PIN_SDMMC3_CMD_PA7, +}; + +static const unsigned gmi_a17_pb0_pins[] = { + TEGRA_PIN_GMI_A17_PB0, +}; + +static const unsigned gmi_a18_pb1_pins[] = { + TEGRA_PIN_GMI_A18_PB1, +}; + +static const unsigned lcd_pwr0_pb2_pins[] = { + TEGRA_PIN_LCD_PWR0_PB2, +}; + +static const unsigned lcd_pclk_pb3_pins[] = { + TEGRA_PIN_LCD_PCLK_PB3, +}; + +static const unsigned sdmmc3_dat3_pb4_pins[] = { + TEGRA_PIN_SDMMC3_DAT3_PB4, +}; + +static const unsigned sdmmc3_dat2_pb5_pins[] = { + TEGRA_PIN_SDMMC3_DAT2_PB5, +}; + +static const unsigned sdmmc3_dat1_pb6_pins[] = { + TEGRA_PIN_SDMMC3_DAT1_PB6, +}; + +static const unsigned sdmmc3_dat0_pb7_pins[] = { + TEGRA_PIN_SDMMC3_DAT0_PB7, +}; + +static const unsigned uart3_rts_n_pc0_pins[] = { + TEGRA_PIN_UART3_RTS_N_PC0, +}; + +static const unsigned lcd_pwr1_pc1_pins[] = { + TEGRA_PIN_LCD_PWR1_PC1, +}; + +static const unsigned uart2_txd_pc2_pins[] = { + TEGRA_PIN_UART2_TXD_PC2, +}; + +static const unsigned uart2_rxd_pc3_pins[] = { + TEGRA_PIN_UART2_RXD_PC3, +}; + +static const unsigned gen1_i2c_scl_pc4_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PC4, +}; + +static const unsigned gen1_i2c_sda_pc5_pins[] = { + TEGRA_PIN_GEN1_I2C_SDA_PC5, +}; + +static const unsigned lcd_pwr2_pc6_pins[] = { + TEGRA_PIN_LCD_PWR2_PC6, +}; + +static const unsigned gmi_wp_n_pc7_pins[] = { + TEGRA_PIN_GMI_WP_N_PC7, +}; + +static const unsigned sdmmc3_dat5_pd0_pins[] = { + TEGRA_PIN_SDMMC3_DAT5_PD0, +}; + +static const unsigned sdmmc3_dat4_pd1_pins[] = { + TEGRA_PIN_SDMMC3_DAT4_PD1, +}; + +static const unsigned lcd_dc1_pd2_pins[] = { + TEGRA_PIN_LCD_DC1_PD2, +}; + +static const unsigned sdmmc3_dat6_pd3_pins[] = { + TEGRA_PIN_SDMMC3_DAT6_PD3, +}; + +static const unsigned sdmmc3_dat7_pd4_pins[] = { + TEGRA_PIN_SDMMC3_DAT7_PD4, +}; + +static const unsigned vi_d1_pd5_pins[] = { + TEGRA_PIN_VI_D1_PD5, +}; + +static const unsigned vi_vsync_pd6_pins[] = { + TEGRA_PIN_VI_VSYNC_PD6, +}; + +static const unsigned vi_hsync_pd7_pins[] = { + TEGRA_PIN_VI_HSYNC_PD7, +}; + +static const unsigned lcd_d0_pe0_pins[] = { + TEGRA_PIN_LCD_D0_PE0, +}; + +static const unsigned lcd_d1_pe1_pins[] = { + TEGRA_PIN_LCD_D1_PE1, +}; + +static const unsigned lcd_d2_pe2_pins[] = { + TEGRA_PIN_LCD_D2_PE2, +}; + +static const unsigned lcd_d3_pe3_pins[] = { + TEGRA_PIN_LCD_D3_PE3, +}; + +static const unsigned lcd_d4_pe4_pins[] = { + TEGRA_PIN_LCD_D4_PE4, +}; + +static const unsigned lcd_d5_pe5_pins[] = { + TEGRA_PIN_LCD_D5_PE5, +}; + +static const unsigned lcd_d6_pe6_pins[] = { + TEGRA_PIN_LCD_D6_PE6, +}; + +static const unsigned lcd_d7_pe7_pins[] = { + TEGRA_PIN_LCD_D7_PE7, +}; + +static const unsigned lcd_d8_pf0_pins[] = { + TEGRA_PIN_LCD_D8_PF0, +}; + +static const unsigned lcd_d9_pf1_pins[] = { + TEGRA_PIN_LCD_D9_PF1, +}; + +static const unsigned lcd_d10_pf2_pins[] = { + TEGRA_PIN_LCD_D10_PF2, +}; + +static const unsigned lcd_d11_pf3_pins[] = { + TEGRA_PIN_LCD_D11_PF3, +}; + +static const unsigned lcd_d12_pf4_pins[] = { + TEGRA_PIN_LCD_D12_PF4, +}; + +static const unsigned lcd_d13_pf5_pins[] = { + TEGRA_PIN_LCD_D13_PF5, +}; + +static const unsigned lcd_d14_pf6_pins[] = { + TEGRA_PIN_LCD_D14_PF6, +}; + +static const unsigned lcd_d15_pf7_pins[] = { + TEGRA_PIN_LCD_D15_PF7, +}; + +static const unsigned gmi_ad0_pg0_pins[] = { + TEGRA_PIN_GMI_AD0_PG0, +}; + +static const unsigned gmi_ad1_pg1_pins[] = { + TEGRA_PIN_GMI_AD1_PG1, +}; + +static const unsigned gmi_ad2_pg2_pins[] = { + TEGRA_PIN_GMI_AD2_PG2, +}; + +static const unsigned gmi_ad3_pg3_pins[] = { + TEGRA_PIN_GMI_AD3_PG3, +}; + +static const unsigned gmi_ad4_pg4_pins[] = { + TEGRA_PIN_GMI_AD4_PG4, +}; + +static const unsigned gmi_ad5_pg5_pins[] = { + TEGRA_PIN_GMI_AD5_PG5, +}; + +static const unsigned gmi_ad6_pg6_pins[] = { + TEGRA_PIN_GMI_AD6_PG6, +}; + +static const unsigned gmi_ad7_pg7_pins[] = { + TEGRA_PIN_GMI_AD7_PG7, +}; + +static const unsigned gmi_ad8_ph0_pins[] = { + TEGRA_PIN_GMI_AD8_PH0, +}; + +static const unsigned gmi_ad9_ph1_pins[] = { + TEGRA_PIN_GMI_AD9_PH1, +}; + +static const unsigned gmi_ad10_ph2_pins[] = { + TEGRA_PIN_GMI_AD10_PH2, +}; + +static const unsigned gmi_ad11_ph3_pins[] = { + TEGRA_PIN_GMI_AD11_PH3, +}; + +static const unsigned gmi_ad12_ph4_pins[] = { + TEGRA_PIN_GMI_AD12_PH4, +}; + +static const unsigned gmi_ad13_ph5_pins[] = { + TEGRA_PIN_GMI_AD13_PH5, +}; + +static const unsigned gmi_ad14_ph6_pins[] = { + TEGRA_PIN_GMI_AD14_PH6, +}; + +static const unsigned gmi_ad15_ph7_pins[] = { + TEGRA_PIN_GMI_AD15_PH7, +}; + +static const unsigned gmi_wr_n_pi0_pins[] = { + TEGRA_PIN_GMI_WR_N_PI0, +}; + +static const unsigned gmi_oe_n_pi1_pins[] = { + TEGRA_PIN_GMI_OE_N_PI1, +}; + +static const unsigned gmi_dqs_pi2_pins[] = { + TEGRA_PIN_GMI_DQS_PI2, +}; + +static const unsigned gmi_cs6_n_pi3_pins[] = { + TEGRA_PIN_GMI_CS6_N_PI3, +}; + +static const unsigned gmi_rst_n_pi4_pins[] = { + TEGRA_PIN_GMI_RST_N_PI4, +}; + +static const unsigned gmi_iordy_pi5_pins[] = { + TEGRA_PIN_GMI_IORDY_PI5, +}; + +static const unsigned gmi_cs7_n_pi6_pins[] = { + TEGRA_PIN_GMI_CS7_N_PI6, +}; + +static const unsigned gmi_wait_pi7_pins[] = { + TEGRA_PIN_GMI_WAIT_PI7, +}; + +static const unsigned gmi_cs0_n_pj0_pins[] = { + TEGRA_PIN_GMI_CS0_N_PJ0, +}; + +static const unsigned lcd_de_pj1_pins[] = { + TEGRA_PIN_LCD_DE_PJ1, +}; + +static const unsigned gmi_cs1_n_pj2_pins[] = { + TEGRA_PIN_GMI_CS1_N_PJ2, +}; + +static const unsigned lcd_hsync_pj3_pins[] = { + TEGRA_PIN_LCD_HSYNC_PJ3, +}; + +static const unsigned lcd_vsync_pj4_pins[] = { + TEGRA_PIN_LCD_VSYNC_PJ4, +}; + +static const unsigned uart2_cts_n_pj5_pins[] = { + TEGRA_PIN_UART2_CTS_N_PJ5, +}; + +static const unsigned uart2_rts_n_pj6_pins[] = { + TEGRA_PIN_UART2_RTS_N_PJ6, +}; + +static const unsigned gmi_a16_pj7_pins[] = { + TEGRA_PIN_GMI_A16_PJ7, +}; + +static const unsigned gmi_adv_n_pk0_pins[] = { + TEGRA_PIN_GMI_ADV_N_PK0, +}; + +static const unsigned gmi_clk_pk1_pins[] = { + TEGRA_PIN_GMI_CLK_PK1, +}; + +static const unsigned gmi_cs4_n_pk2_pins[] = { + TEGRA_PIN_GMI_CS4_N_PK2, +}; + +static const unsigned gmi_cs2_n_pk3_pins[] = { + TEGRA_PIN_GMI_CS2_N_PK3, +}; + +static const unsigned gmi_cs3_n_pk4_pins[] = { + TEGRA_PIN_GMI_CS3_N_PK4, +}; + +static const unsigned spdif_out_pk5_pins[] = { + TEGRA_PIN_SPDIF_OUT_PK5, +}; + +static const unsigned spdif_in_pk6_pins[] = { + TEGRA_PIN_SPDIF_IN_PK6, +}; + +static const unsigned gmi_a19_pk7_pins[] = { + TEGRA_PIN_GMI_A19_PK7, +}; + +static const unsigned vi_d2_pl0_pins[] = { + TEGRA_PIN_VI_D2_PL0, +}; + +static const unsigned vi_d3_pl1_pins[] = { + TEGRA_PIN_VI_D3_PL1, +}; + +static const unsigned vi_d4_pl2_pins[] = { + TEGRA_PIN_VI_D4_PL2, +}; + +static const unsigned vi_d5_pl3_pins[] = { + TEGRA_PIN_VI_D5_PL3, +}; + +static const unsigned vi_d6_pl4_pins[] = { + TEGRA_PIN_VI_D6_PL4, +}; + +static const unsigned vi_d7_pl5_pins[] = { + TEGRA_PIN_VI_D7_PL5, +}; + +static const unsigned vi_d8_pl6_pins[] = { + TEGRA_PIN_VI_D8_PL6, +}; + +static const unsigned vi_d9_pl7_pins[] = { + TEGRA_PIN_VI_D9_PL7, +}; + +static const unsigned lcd_d16_pm0_pins[] = { + TEGRA_PIN_LCD_D16_PM0, +}; + +static const unsigned lcd_d17_pm1_pins[] = { + TEGRA_PIN_LCD_D17_PM1, +}; + +static const unsigned lcd_d18_pm2_pins[] = { + TEGRA_PIN_LCD_D18_PM2, +}; + +static const unsigned lcd_d19_pm3_pins[] = { + TEGRA_PIN_LCD_D19_PM3, +}; + +static const unsigned lcd_d20_pm4_pins[] = { + TEGRA_PIN_LCD_D20_PM4, +}; + +static const unsigned lcd_d21_pm5_pins[] = { + TEGRA_PIN_LCD_D21_PM5, +}; + +static const unsigned lcd_d22_pm6_pins[] = { + TEGRA_PIN_LCD_D22_PM6, +}; + +static const unsigned lcd_d23_pm7_pins[] = { + TEGRA_PIN_LCD_D23_PM7, +}; + +static const unsigned dap1_fs_pn0_pins[] = { + TEGRA_PIN_DAP1_FS_PN0, +}; + +static const unsigned dap1_din_pn1_pins[] = { + TEGRA_PIN_DAP1_DIN_PN1, +}; + +static const unsigned dap1_dout_pn2_pins[] = { + TEGRA_PIN_DAP1_DOUT_PN2, +}; + +static const unsigned dap1_sclk_pn3_pins[] = { + TEGRA_PIN_DAP1_SCLK_PN3, +}; + +static const unsigned lcd_cs0_n_pn4_pins[] = { + TEGRA_PIN_LCD_CS0_N_PN4, +}; + +static const unsigned lcd_sdout_pn5_pins[] = { + TEGRA_PIN_LCD_SDOUT_PN5, +}; + +static const unsigned lcd_dc0_pn6_pins[] = { + TEGRA_PIN_LCD_DC0_PN6, +}; + +static const unsigned hdmi_int_pn7_pins[] = { + TEGRA_PIN_HDMI_INT_PN7, +}; + +static const unsigned ulpi_data7_po0_pins[] = { + TEGRA_PIN_ULPI_DATA7_PO0, +}; + +static const unsigned ulpi_data0_po1_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, +}; + +static const unsigned ulpi_data1_po2_pins[] = { + TEGRA_PIN_ULPI_DATA1_PO2, +}; + +static const unsigned ulpi_data2_po3_pins[] = { + TEGRA_PIN_ULPI_DATA2_PO3, +}; + +static const unsigned ulpi_data3_po4_pins[] = { + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned ulpi_data4_po5_pins[] = { + TEGRA_PIN_ULPI_DATA4_PO5, +}; + +static const unsigned ulpi_data5_po6_pins[] = { + TEGRA_PIN_ULPI_DATA5_PO6, +}; + +static const unsigned ulpi_data6_po7_pins[] = { + TEGRA_PIN_ULPI_DATA6_PO7, +}; + +static const unsigned dap3_fs_pp0_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, +}; + +static const unsigned dap3_din_pp1_pins[] = { + TEGRA_PIN_DAP3_DIN_PP1, +}; + +static const unsigned dap3_dout_pp2_pins[] = { + TEGRA_PIN_DAP3_DOUT_PP2, +}; + +static const unsigned dap3_sclk_pp3_pins[] = { + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned dap4_fs_pp4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, +}; + +static const unsigned dap4_din_pp5_pins[] = { + TEGRA_PIN_DAP4_DIN_PP5, +}; + +static const unsigned dap4_dout_pp6_pins[] = { + TEGRA_PIN_DAP4_DOUT_PP6, +}; + +static const unsigned dap4_sclk_pp7_pins[] = { + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned kb_col0_pq0_pins[] = { + TEGRA_PIN_KB_COL0_PQ0, +}; + +static const unsigned kb_col1_pq1_pins[] = { + TEGRA_PIN_KB_COL1_PQ1, +}; + +static const unsigned kb_col2_pq2_pins[] = { + TEGRA_PIN_KB_COL2_PQ2, +}; + +static const unsigned kb_col3_pq3_pins[] = { + TEGRA_PIN_KB_COL3_PQ3, +}; + +static const unsigned kb_col4_pq4_pins[] = { + TEGRA_PIN_KB_COL4_PQ4, +}; + +static const unsigned kb_col5_pq5_pins[] = { + TEGRA_PIN_KB_COL5_PQ5, +}; + +static const unsigned kb_col6_pq6_pins[] = { + TEGRA_PIN_KB_COL6_PQ6, +}; + +static const unsigned kb_col7_pq7_pins[] = { + TEGRA_PIN_KB_COL7_PQ7, +}; + +static const unsigned kb_row0_pr0_pins[] = { + TEGRA_PIN_KB_ROW0_PR0, +}; + +static const unsigned kb_row1_pr1_pins[] = { + TEGRA_PIN_KB_ROW1_PR1, +}; + +static const unsigned kb_row2_pr2_pins[] = { + TEGRA_PIN_KB_ROW2_PR2, +}; + +static const unsigned kb_row3_pr3_pins[] = { + TEGRA_PIN_KB_ROW3_PR3, +}; + +static const unsigned kb_row4_pr4_pins[] = { + TEGRA_PIN_KB_ROW4_PR4, +}; + +static const unsigned kb_row5_pr5_pins[] = { + TEGRA_PIN_KB_ROW5_PR5, +}; + +static const unsigned kb_row6_pr6_pins[] = { + TEGRA_PIN_KB_ROW6_PR6, +}; + +static const unsigned kb_row7_pr7_pins[] = { + TEGRA_PIN_KB_ROW7_PR7, +}; + +static const unsigned kb_row8_ps0_pins[] = { + TEGRA_PIN_KB_ROW8_PS0, +}; + +static const unsigned kb_row9_ps1_pins[] = { + TEGRA_PIN_KB_ROW9_PS1, +}; + +static const unsigned kb_row10_ps2_pins[] = { + TEGRA_PIN_KB_ROW10_PS2, +}; + +static const unsigned kb_row11_ps3_pins[] = { + TEGRA_PIN_KB_ROW11_PS3, +}; + +static const unsigned kb_row12_ps4_pins[] = { + TEGRA_PIN_KB_ROW12_PS4, +}; + +static const unsigned kb_row13_ps5_pins[] = { + TEGRA_PIN_KB_ROW13_PS5, +}; + +static const unsigned kb_row14_ps6_pins[] = { + TEGRA_PIN_KB_ROW14_PS6, +}; + +static const unsigned kb_row15_ps7_pins[] = { + TEGRA_PIN_KB_ROW15_PS7, +}; + +static const unsigned vi_pclk_pt0_pins[] = { + TEGRA_PIN_VI_PCLK_PT0, +}; + +static const unsigned vi_mclk_pt1_pins[] = { + TEGRA_PIN_VI_MCLK_PT1, +}; + +static const unsigned vi_d10_pt2_pins[] = { + TEGRA_PIN_VI_D10_PT2, +}; + +static const unsigned vi_d11_pt3_pins[] = { + TEGRA_PIN_VI_D11_PT3, +}; + +static const unsigned vi_d0_pt4_pins[] = { + TEGRA_PIN_VI_D0_PT4, +}; + +static const unsigned gen2_i2c_scl_pt5_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PT5, +}; + +static const unsigned gen2_i2c_sda_pt6_pins[] = { + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned sdmmc4_cmd_pt7_pins[] = { + TEGRA_PIN_SDMMC4_CMD_PT7, +}; + +static const unsigned pu0_pins[] = { + TEGRA_PIN_PU0, +}; + +static const unsigned pu1_pins[] = { + TEGRA_PIN_PU1, +}; + +static const unsigned pu2_pins[] = { + TEGRA_PIN_PU2, +}; + +static const unsigned pu3_pins[] = { + TEGRA_PIN_PU3, +}; + +static const unsigned pu4_pins[] = { + TEGRA_PIN_PU4, +}; + +static const unsigned pu5_pins[] = { + TEGRA_PIN_PU5, +}; + +static const unsigned pu6_pins[] = { + TEGRA_PIN_PU6, +}; + +static const unsigned jtag_rtck_pu7_pins[] = { + TEGRA_PIN_JTAG_RTCK_PU7, +}; + +static const unsigned pv0_pins[] = { + TEGRA_PIN_PV0, +}; + +static const unsigned pv1_pins[] = { + TEGRA_PIN_PV1, +}; + +static const unsigned pv2_pins[] = { + TEGRA_PIN_PV2, +}; + +static const unsigned pv3_pins[] = { + TEGRA_PIN_PV3, +}; + +static const unsigned ddc_scl_pv4_pins[] = { + TEGRA_PIN_DDC_SCL_PV4, +}; + +static const unsigned ddc_sda_pv5_pins[] = { + TEGRA_PIN_DDC_SDA_PV5, +}; + +static const unsigned crt_hsync_pv6_pins[] = { + TEGRA_PIN_CRT_HSYNC_PV6, +}; + +static const unsigned crt_vsync_pv7_pins[] = { + TEGRA_PIN_CRT_VSYNC_PV7, +}; + +static const unsigned lcd_cs1_n_pw0_pins[] = { + TEGRA_PIN_LCD_CS1_N_PW0, +}; + +static const unsigned lcd_m1_pw1_pins[] = { + TEGRA_PIN_LCD_M1_PW1, +}; + +static const unsigned spi2_cs1_n_pw2_pins[] = { + TEGRA_PIN_SPI2_CS1_N_PW2, +}; + +static const unsigned spi2_cs2_n_pw3_pins[] = { + TEGRA_PIN_SPI2_CS2_N_PW3, +}; + +static const unsigned clk1_out_pw4_pins[] = { + TEGRA_PIN_CLK1_OUT_PW4, +}; + +static const unsigned clk2_out_pw5_pins[] = { + TEGRA_PIN_CLK2_OUT_PW5, +}; + +static const unsigned uart3_txd_pw6_pins[] = { + TEGRA_PIN_UART3_TXD_PW6, +}; + +static const unsigned uart3_rxd_pw7_pins[] = { + TEGRA_PIN_UART3_RXD_PW7, +}; + +static const unsigned spi2_mosi_px0_pins[] = { + TEGRA_PIN_SPI2_MOSI_PX0, +}; + +static const unsigned spi2_miso_px1_pins[] = { + TEGRA_PIN_SPI2_MISO_PX1, +}; + +static const unsigned spi2_sck_px2_pins[] = { + TEGRA_PIN_SPI2_SCK_PX2, +}; + +static const unsigned spi2_cs0_n_px3_pins[] = { + TEGRA_PIN_SPI2_CS0_N_PX3, +}; + +static const unsigned spi1_mosi_px4_pins[] = { + TEGRA_PIN_SPI1_MOSI_PX4, +}; + +static const unsigned spi1_sck_px5_pins[] = { + TEGRA_PIN_SPI1_SCK_PX5, +}; + +static const unsigned spi1_cs0_n_px6_pins[] = { + TEGRA_PIN_SPI1_CS0_N_PX6, +}; + +static const unsigned spi1_miso_px7_pins[] = { + TEGRA_PIN_SPI1_MISO_PX7, +}; + +static const unsigned ulpi_clk_py0_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, +}; + +static const unsigned ulpi_dir_py1_pins[] = { + TEGRA_PIN_ULPI_DIR_PY1, +}; + +static const unsigned ulpi_nxt_py2_pins[] = { + TEGRA_PIN_ULPI_NXT_PY2, +}; + +static const unsigned ulpi_stp_py3_pins[] = { + TEGRA_PIN_ULPI_STP_PY3, +}; + +static const unsigned sdmmc1_dat3_py4_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PY4, +}; + +static const unsigned sdmmc1_dat2_py5_pins[] = { + TEGRA_PIN_SDMMC1_DAT2_PY5, +}; + +static const unsigned sdmmc1_dat1_py6_pins[] = { + TEGRA_PIN_SDMMC1_DAT1_PY6, +}; + +static const unsigned sdmmc1_dat0_py7_pins[] = { + TEGRA_PIN_SDMMC1_DAT0_PY7, +}; + +static const unsigned sdmmc1_clk_pz0_pins[] = { + TEGRA_PIN_SDMMC1_CLK_PZ0, +}; + +static const unsigned sdmmc1_cmd_pz1_pins[] = { + TEGRA_PIN_SDMMC1_CMD_PZ1, +}; + +static const unsigned lcd_sdin_pz2_pins[] = { + TEGRA_PIN_LCD_SDIN_PZ2, +}; + +static const unsigned lcd_wr_n_pz3_pins[] = { + TEGRA_PIN_LCD_WR_N_PZ3, +}; + +static const unsigned lcd_sck_pz4_pins[] = { + TEGRA_PIN_LCD_SCK_PZ4, +}; + +static const unsigned sys_clk_req_pz5_pins[] = { + TEGRA_PIN_SYS_CLK_REQ_PZ5, +}; + +static const unsigned pwr_i2c_scl_pz6_pins[] = { + TEGRA_PIN_PWR_I2C_SCL_PZ6, +}; + +static const unsigned pwr_i2c_sda_pz7_pins[] = { + TEGRA_PIN_PWR_I2C_SDA_PZ7, +}; + +static const unsigned sdmmc4_dat0_paa0_pins[] = { + TEGRA_PIN_SDMMC4_DAT0_PAA0, +}; + +static const unsigned sdmmc4_dat1_paa1_pins[] = { + TEGRA_PIN_SDMMC4_DAT1_PAA1, +}; + +static const unsigned sdmmc4_dat2_paa2_pins[] = { + TEGRA_PIN_SDMMC4_DAT2_PAA2, +}; + +static const unsigned sdmmc4_dat3_paa3_pins[] = { + TEGRA_PIN_SDMMC4_DAT3_PAA3, +}; + +static const unsigned sdmmc4_dat4_paa4_pins[] = { + TEGRA_PIN_SDMMC4_DAT4_PAA4, +}; + +static const unsigned sdmmc4_dat5_paa5_pins[] = { + TEGRA_PIN_SDMMC4_DAT5_PAA5, +}; + +static const unsigned sdmmc4_dat6_paa6_pins[] = { + TEGRA_PIN_SDMMC4_DAT6_PAA6, +}; + +static const unsigned sdmmc4_dat7_paa7_pins[] = { + TEGRA_PIN_SDMMC4_DAT7_PAA7, +}; + +static const unsigned pbb0_pins[] = { + TEGRA_PIN_PBB0, +}; + +static const unsigned cam_i2c_scl_pbb1_pins[] = { + TEGRA_PIN_CAM_I2C_SCL_PBB1, +}; + +static const unsigned cam_i2c_sda_pbb2_pins[] = { + TEGRA_PIN_CAM_I2C_SDA_PBB2, +}; + +static const unsigned pbb3_pins[] = { + TEGRA_PIN_PBB3, +}; + +static const unsigned pbb4_pins[] = { + TEGRA_PIN_PBB4, +}; + +static const unsigned pbb5_pins[] = { + TEGRA_PIN_PBB5, +}; + +static const unsigned pbb6_pins[] = { + TEGRA_PIN_PBB6, +}; + +static const unsigned pbb7_pins[] = { + TEGRA_PIN_PBB7, +}; + +static const unsigned cam_mclk_pcc0_pins[] = { + TEGRA_PIN_CAM_MCLK_PCC0, +}; + +static const unsigned pcc1_pins[] = { + TEGRA_PIN_PCC1, +}; + +static const unsigned pcc2_pins[] = { + TEGRA_PIN_PCC2, +}; + +static const unsigned sdmmc4_rst_n_pcc3_pins[] = { + TEGRA_PIN_SDMMC4_RST_N_PCC3, +}; + +static const unsigned sdmmc4_clk_pcc4_pins[] = { + TEGRA_PIN_SDMMC4_CLK_PCC4, +}; + +static const unsigned clk2_req_pcc5_pins[] = { + TEGRA_PIN_CLK2_REQ_PCC5, +}; + +static const unsigned pex_l2_rst_n_pcc6_pins[] = { + TEGRA_PIN_PEX_L2_RST_N_PCC6, +}; + +static const unsigned pex_l2_clkreq_n_pcc7_pins[] = { + TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7, +}; + +static const unsigned pex_l0_prsnt_n_pdd0_pins[] = { + TEGRA_PIN_PEX_L0_PRSNT_N_PDD0, +}; + +static const unsigned pex_l0_rst_n_pdd1_pins[] = { + TEGRA_PIN_PEX_L0_RST_N_PDD1, +}; + +static const unsigned pex_l0_clkreq_n_pdd2_pins[] = { + TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, +}; + +static const unsigned pex_wake_n_pdd3_pins[] = { + TEGRA_PIN_PEX_WAKE_N_PDD3, +}; + +static const unsigned pex_l1_prsnt_n_pdd4_pins[] = { + TEGRA_PIN_PEX_L1_PRSNT_N_PDD4, +}; + +static const unsigned pex_l1_rst_n_pdd5_pins[] = { + TEGRA_PIN_PEX_L1_RST_N_PDD5, +}; + +static const unsigned pex_l1_clkreq_n_pdd6_pins[] = { + TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, +}; + +static const unsigned pex_l2_prsnt_n_pdd7_pins[] = { + TEGRA_PIN_PEX_L2_PRSNT_N_PDD7, +}; + +static const unsigned clk3_out_pee0_pins[] = { + TEGRA_PIN_CLK3_OUT_PEE0, +}; + +static const unsigned clk3_req_pee1_pins[] = { + TEGRA_PIN_CLK3_REQ_PEE1, +}; + +static const unsigned clk1_req_pee2_pins[] = { + TEGRA_PIN_CLK1_REQ_PEE2, +}; + +static const unsigned hdmi_cec_pee3_pins[] = { + TEGRA_PIN_HDMI_CEC_PEE3, +}; + +static const unsigned clk_32k_in_pins[] = { + TEGRA_PIN_CLK_32K_IN, +}; + +static const unsigned core_pwr_req_pins[] = { + TEGRA_PIN_CORE_PWR_REQ, +}; + +static const unsigned cpu_pwr_req_pins[] = { + TEGRA_PIN_CPU_PWR_REQ, +}; + +static const unsigned owr_pins[] = { + TEGRA_PIN_OWR, +}; + +static const unsigned pwr_int_n_pins[] = { + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned drive_ao1_pins[] = { + TEGRA_PIN_KB_ROW0_PR0, + TEGRA_PIN_KB_ROW1_PR1, + TEGRA_PIN_KB_ROW2_PR2, + TEGRA_PIN_KB_ROW3_PR3, + TEGRA_PIN_KB_ROW4_PR4, + TEGRA_PIN_KB_ROW5_PR5, + TEGRA_PIN_KB_ROW6_PR6, + TEGRA_PIN_KB_ROW7_PR7, + TEGRA_PIN_PWR_I2C_SCL_PZ6, + TEGRA_PIN_PWR_I2C_SDA_PZ7, + TEGRA_PIN_SYS_RESET_N, +}; + +static const unsigned drive_ao2_pins[] = { + TEGRA_PIN_CLK_32K_OUT_PA0, + TEGRA_PIN_KB_COL0_PQ0, + TEGRA_PIN_KB_COL1_PQ1, + TEGRA_PIN_KB_COL2_PQ2, + TEGRA_PIN_KB_COL3_PQ3, + TEGRA_PIN_KB_COL4_PQ4, + TEGRA_PIN_KB_COL5_PQ5, + TEGRA_PIN_KB_COL6_PQ6, + TEGRA_PIN_KB_COL7_PQ7, + TEGRA_PIN_KB_ROW8_PS0, + TEGRA_PIN_KB_ROW9_PS1, + TEGRA_PIN_KB_ROW10_PS2, + TEGRA_PIN_KB_ROW11_PS3, + TEGRA_PIN_KB_ROW12_PS4, + TEGRA_PIN_KB_ROW13_PS5, + TEGRA_PIN_KB_ROW14_PS6, + TEGRA_PIN_KB_ROW15_PS7, + TEGRA_PIN_SYS_CLK_REQ_PZ5, + TEGRA_PIN_CLK_32K_IN, + TEGRA_PIN_CORE_PWR_REQ, + TEGRA_PIN_CPU_PWR_REQ, + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned drive_at1_pins[] = { + TEGRA_PIN_GMI_AD8_PH0, + TEGRA_PIN_GMI_AD9_PH1, + TEGRA_PIN_GMI_AD10_PH2, + TEGRA_PIN_GMI_AD11_PH3, + TEGRA_PIN_GMI_AD12_PH4, + TEGRA_PIN_GMI_AD13_PH5, + TEGRA_PIN_GMI_AD14_PH6, + TEGRA_PIN_GMI_AD15_PH7, + TEGRA_PIN_GMI_IORDY_PI5, + TEGRA_PIN_GMI_CS7_N_PI6, +}; + +static const unsigned drive_at2_pins[] = { + TEGRA_PIN_GMI_AD0_PG0, + TEGRA_PIN_GMI_AD1_PG1, + TEGRA_PIN_GMI_AD2_PG2, + TEGRA_PIN_GMI_AD3_PG3, + TEGRA_PIN_GMI_AD4_PG4, + TEGRA_PIN_GMI_AD5_PG5, + TEGRA_PIN_GMI_AD6_PG6, + TEGRA_PIN_GMI_AD7_PG7, + TEGRA_PIN_GMI_WR_N_PI0, + TEGRA_PIN_GMI_OE_N_PI1, + TEGRA_PIN_GMI_DQS_PI2, + TEGRA_PIN_GMI_CS6_N_PI3, + TEGRA_PIN_GMI_RST_N_PI4, + TEGRA_PIN_GMI_WAIT_PI7, + TEGRA_PIN_GMI_ADV_N_PK0, + TEGRA_PIN_GMI_CLK_PK1, + TEGRA_PIN_GMI_CS4_N_PK2, + TEGRA_PIN_GMI_CS2_N_PK3, + TEGRA_PIN_GMI_CS3_N_PK4, +}; + +static const unsigned drive_at3_pins[] = { + TEGRA_PIN_GMI_WP_N_PC7, + TEGRA_PIN_GMI_CS0_N_PJ0, +}; + +static const unsigned drive_at4_pins[] = { + TEGRA_PIN_GMI_A17_PB0, + TEGRA_PIN_GMI_A18_PB1, + TEGRA_PIN_GMI_CS1_N_PJ2, + TEGRA_PIN_GMI_A16_PJ7, + TEGRA_PIN_GMI_A19_PK7, +}; + +static const unsigned drive_at5_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PT5, + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned drive_cdev1_pins[] = { + TEGRA_PIN_CLK1_OUT_PW4, + TEGRA_PIN_CLK1_REQ_PEE2, +}; + +static const unsigned drive_cdev2_pins[] = { + TEGRA_PIN_CLK2_OUT_PW5, + TEGRA_PIN_CLK2_REQ_PCC5, +}; + +static const unsigned drive_cec_pins[] = { + TEGRA_PIN_HDMI_CEC_PEE3, +}; + +static const unsigned drive_crt_pins[] = { + TEGRA_PIN_CRT_HSYNC_PV6, + TEGRA_PIN_CRT_VSYNC_PV7, +}; + +static const unsigned drive_csus_pins[] = { + TEGRA_PIN_VI_MCLK_PT1, +}; + +static const unsigned drive_dap1_pins[] = { + TEGRA_PIN_SPDIF_OUT_PK5, + TEGRA_PIN_SPDIF_IN_PK6, + TEGRA_PIN_DAP1_FS_PN0, + TEGRA_PIN_DAP1_DIN_PN1, + TEGRA_PIN_DAP1_DOUT_PN2, + TEGRA_PIN_DAP1_SCLK_PN3, +}; + +static const unsigned drive_dap2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, + TEGRA_PIN_DAP2_SCLK_PA3, + TEGRA_PIN_DAP2_DIN_PA4, + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned drive_dap3_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, + TEGRA_PIN_DAP3_DIN_PP1, + TEGRA_PIN_DAP3_DOUT_PP2, + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned drive_dap4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, + TEGRA_PIN_DAP4_DIN_PP5, + TEGRA_PIN_DAP4_DOUT_PP6, + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned drive_dbg_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PC4, + TEGRA_PIN_GEN1_I2C_SDA_PC5, + TEGRA_PIN_PU0, + TEGRA_PIN_PU1, + TEGRA_PIN_PU2, + TEGRA_PIN_PU3, + TEGRA_PIN_PU4, + TEGRA_PIN_PU5, + TEGRA_PIN_PU6, + TEGRA_PIN_JTAG_RTCK_PU7, + TEGRA_PIN_JTAG_TCK, + TEGRA_PIN_JTAG_TDI, + TEGRA_PIN_JTAG_TDO, + TEGRA_PIN_JTAG_TMS, + TEGRA_PIN_JTAG_TRST_N, + TEGRA_PIN_TEST_MODE_EN, +}; + +static const unsigned drive_ddc_pins[] = { + TEGRA_PIN_DDC_SCL_PV4, + TEGRA_PIN_DDC_SDA_PV5, +}; + +static const unsigned drive_dev3_pins[] = { + TEGRA_PIN_CLK3_OUT_PEE0, + TEGRA_PIN_CLK3_REQ_PEE1, +}; + +static const unsigned drive_gma_pins[] = { + TEGRA_PIN_SDMMC4_DAT0_PAA0, + TEGRA_PIN_SDMMC4_DAT1_PAA1, + TEGRA_PIN_SDMMC4_DAT2_PAA2, + TEGRA_PIN_SDMMC4_DAT3_PAA3, + TEGRA_PIN_SDMMC4_RST_N_PCC3, +}; + +static const unsigned drive_gmb_pins[] = { + TEGRA_PIN_SDMMC4_DAT4_PAA4, + TEGRA_PIN_SDMMC4_DAT5_PAA5, + TEGRA_PIN_SDMMC4_DAT6_PAA6, + TEGRA_PIN_SDMMC4_DAT7_PAA7, +}; + +static const unsigned drive_gmc_pins[] = { + TEGRA_PIN_SDMMC4_CLK_PCC4, +}; + +static const unsigned drive_gmd_pins[] = { + TEGRA_PIN_SDMMC4_CMD_PT7, +}; + +static const unsigned drive_gme_pins[] = { + TEGRA_PIN_PBB0, + TEGRA_PIN_CAM_I2C_SCL_PBB1, + TEGRA_PIN_CAM_I2C_SDA_PBB2, + TEGRA_PIN_PBB3, + TEGRA_PIN_PCC2, +}; + +static const unsigned drive_gmf_pins[] = { + TEGRA_PIN_PBB4, + TEGRA_PIN_PBB5, + TEGRA_PIN_PBB6, + TEGRA_PIN_PBB7, +}; + +static const unsigned drive_gmg_pins[] = { + TEGRA_PIN_CAM_MCLK_PCC0, +}; + +static const unsigned drive_gmh_pins[] = { + TEGRA_PIN_PCC1, +}; + +static const unsigned drive_gpv_pins[] = { + TEGRA_PIN_PEX_L2_RST_N_PCC6, + TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7, + TEGRA_PIN_PEX_L0_PRSNT_N_PDD0, + TEGRA_PIN_PEX_L0_RST_N_PDD1, + TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, + TEGRA_PIN_PEX_WAKE_N_PDD3, + TEGRA_PIN_PEX_L1_PRSNT_N_PDD4, + TEGRA_PIN_PEX_L1_RST_N_PDD5, + TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, + TEGRA_PIN_PEX_L2_PRSNT_N_PDD7, +}; + +static const unsigned drive_lcd1_pins[] = { + TEGRA_PIN_LCD_PWR1_PC1, + TEGRA_PIN_LCD_PWR2_PC6, + TEGRA_PIN_LCD_CS0_N_PN4, + TEGRA_PIN_LCD_SDOUT_PN5, + TEGRA_PIN_LCD_DC0_PN6, + TEGRA_PIN_LCD_SDIN_PZ2, + TEGRA_PIN_LCD_WR_N_PZ3, + TEGRA_PIN_LCD_SCK_PZ4, +}; + +static const unsigned drive_lcd2_pins[] = { + TEGRA_PIN_LCD_PWR0_PB2, + TEGRA_PIN_LCD_PCLK_PB3, + TEGRA_PIN_LCD_DC1_PD2, + TEGRA_PIN_LCD_D0_PE0, + TEGRA_PIN_LCD_D1_PE1, + TEGRA_PIN_LCD_D2_PE2, + TEGRA_PIN_LCD_D3_PE3, + TEGRA_PIN_LCD_D4_PE4, + TEGRA_PIN_LCD_D5_PE5, + TEGRA_PIN_LCD_D6_PE6, + TEGRA_PIN_LCD_D7_PE7, + TEGRA_PIN_LCD_D8_PF0, + TEGRA_PIN_LCD_D9_PF1, + TEGRA_PIN_LCD_D10_PF2, + TEGRA_PIN_LCD_D11_PF3, + TEGRA_PIN_LCD_D12_PF4, + TEGRA_PIN_LCD_D13_PF5, + TEGRA_PIN_LCD_D14_PF6, + TEGRA_PIN_LCD_D15_PF7, + TEGRA_PIN_LCD_DE_PJ1, + TEGRA_PIN_LCD_HSYNC_PJ3, + TEGRA_PIN_LCD_VSYNC_PJ4, + TEGRA_PIN_LCD_D16_PM0, + TEGRA_PIN_LCD_D17_PM1, + TEGRA_PIN_LCD_D18_PM2, + TEGRA_PIN_LCD_D19_PM3, + TEGRA_PIN_LCD_D20_PM4, + TEGRA_PIN_LCD_D21_PM5, + TEGRA_PIN_LCD_D22_PM6, + TEGRA_PIN_LCD_D23_PM7, + TEGRA_PIN_HDMI_INT_PN7, + TEGRA_PIN_LCD_CS1_N_PW0, + TEGRA_PIN_LCD_M1_PW1, +}; + +static const unsigned drive_owr_pins[] = { + TEGRA_PIN_OWR, +}; + +static const unsigned drive_sdio1_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PY4, + TEGRA_PIN_SDMMC1_DAT2_PY5, + TEGRA_PIN_SDMMC1_DAT1_PY6, + TEGRA_PIN_SDMMC1_DAT0_PY7, + TEGRA_PIN_SDMMC1_CLK_PZ0, + TEGRA_PIN_SDMMC1_CMD_PZ1, +}; + +static const unsigned drive_sdio2_pins[] = { + TEGRA_PIN_SDMMC3_DAT5_PD0, + TEGRA_PIN_SDMMC3_DAT4_PD1, + TEGRA_PIN_SDMMC3_DAT6_PD3, + TEGRA_PIN_SDMMC3_DAT7_PD4, +}; + +static const unsigned drive_sdio3_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PA6, + TEGRA_PIN_SDMMC3_CMD_PA7, + TEGRA_PIN_SDMMC3_DAT3_PB4, + TEGRA_PIN_SDMMC3_DAT2_PB5, + TEGRA_PIN_SDMMC3_DAT1_PB6, + TEGRA_PIN_SDMMC3_DAT0_PB7, +}; + +static const unsigned drive_spi_pins[] = { + TEGRA_PIN_SPI2_CS1_N_PW2, + TEGRA_PIN_SPI2_CS2_N_PW3, + TEGRA_PIN_SPI2_MOSI_PX0, + TEGRA_PIN_SPI2_MISO_PX1, + TEGRA_PIN_SPI2_SCK_PX2, + TEGRA_PIN_SPI2_CS0_N_PX3, + TEGRA_PIN_SPI1_MOSI_PX4, + TEGRA_PIN_SPI1_SCK_PX5, + TEGRA_PIN_SPI1_CS0_N_PX6, + TEGRA_PIN_SPI1_MISO_PX7, +}; + +static const unsigned drive_uaa_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, + TEGRA_PIN_ULPI_DATA1_PO2, + TEGRA_PIN_ULPI_DATA2_PO3, + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned drive_uab_pins[] = { + TEGRA_PIN_ULPI_DATA7_PO0, + TEGRA_PIN_ULPI_DATA4_PO5, + TEGRA_PIN_ULPI_DATA5_PO6, + TEGRA_PIN_ULPI_DATA6_PO7, + TEGRA_PIN_PV0, + TEGRA_PIN_PV1, + TEGRA_PIN_PV2, + TEGRA_PIN_PV3, +}; + +static const unsigned drive_uart2_pins[] = { + TEGRA_PIN_UART2_TXD_PC2, + TEGRA_PIN_UART2_RXD_PC3, + TEGRA_PIN_UART2_CTS_N_PJ5, + TEGRA_PIN_UART2_RTS_N_PJ6, +}; + +static const unsigned drive_uart3_pins[] = { + TEGRA_PIN_UART3_CTS_N_PA1, + TEGRA_PIN_UART3_RTS_N_PC0, + TEGRA_PIN_UART3_TXD_PW6, + TEGRA_PIN_UART3_RXD_PW7, +}; + +static const unsigned drive_uda_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, + TEGRA_PIN_ULPI_DIR_PY1, + TEGRA_PIN_ULPI_NXT_PY2, + TEGRA_PIN_ULPI_STP_PY3, +}; + +static const unsigned drive_vi1_pins[] = { + TEGRA_PIN_VI_D1_PD5, + TEGRA_PIN_VI_VSYNC_PD6, + TEGRA_PIN_VI_HSYNC_PD7, + TEGRA_PIN_VI_D2_PL0, + TEGRA_PIN_VI_D3_PL1, + TEGRA_PIN_VI_D4_PL2, + TEGRA_PIN_VI_D5_PL3, + TEGRA_PIN_VI_D6_PL4, + TEGRA_PIN_VI_D7_PL5, + TEGRA_PIN_VI_D8_PL6, + TEGRA_PIN_VI_D9_PL7, + TEGRA_PIN_VI_PCLK_PT0, + TEGRA_PIN_VI_D10_PT2, + TEGRA_PIN_VI_D11_PT3, + TEGRA_PIN_VI_D0_PT4, +}; + +enum tegra_mux { + TEGRA_MUX_BLINK, + TEGRA_MUX_CEC, + TEGRA_MUX_CLK_12M_OUT, + TEGRA_MUX_CLK_32K_IN, + TEGRA_MUX_CORE_PWR_REQ, + TEGRA_MUX_CPU_PWR_REQ, + TEGRA_MUX_CRT, + TEGRA_MUX_DAP, + TEGRA_MUX_DDR, + TEGRA_MUX_DEV3, + TEGRA_MUX_DISPLAYA, + TEGRA_MUX_DISPLAYB, + TEGRA_MUX_DTV, + TEGRA_MUX_EXTPERIPH1, + TEGRA_MUX_EXTPERIPH2, + TEGRA_MUX_EXTPERIPH3, + TEGRA_MUX_GMI, + TEGRA_MUX_GMI_ALT, + TEGRA_MUX_HDA, + TEGRA_MUX_HDCP, + TEGRA_MUX_HDMI, + TEGRA_MUX_HSI, + TEGRA_MUX_I2C1, + TEGRA_MUX_I2C2, + TEGRA_MUX_I2C3, + TEGRA_MUX_I2C4, + TEGRA_MUX_I2CPWR, + TEGRA_MUX_I2S0, + TEGRA_MUX_I2S1, + TEGRA_MUX_I2S2, + TEGRA_MUX_I2S3, + TEGRA_MUX_I2S4, + TEGRA_MUX_INVALID, + TEGRA_MUX_KBC, + TEGRA_MUX_MIO, + TEGRA_MUX_NAND, + TEGRA_MUX_NAND_ALT, + TEGRA_MUX_OWR, + TEGRA_MUX_PCIE, + TEGRA_MUX_PWM0, + TEGRA_MUX_PWM1, + TEGRA_MUX_PWM2, + TEGRA_MUX_PWM3, + TEGRA_MUX_PWR_INT_N, + TEGRA_MUX_RSVD1, + TEGRA_MUX_RSVD2, + TEGRA_MUX_RSVD3, + TEGRA_MUX_RSVD4, + TEGRA_MUX_RTCK, + TEGRA_MUX_SATA, + TEGRA_MUX_SDMMC1, + TEGRA_MUX_SDMMC2, + TEGRA_MUX_SDMMC3, + TEGRA_MUX_SDMMC4, + TEGRA_MUX_SPDIF, + TEGRA_MUX_SPI1, + TEGRA_MUX_SPI2, + TEGRA_MUX_SPI2_ALT, + TEGRA_MUX_SPI3, + TEGRA_MUX_SPI4, + TEGRA_MUX_SPI5, + TEGRA_MUX_SPI6, + TEGRA_MUX_SYSCLK, + TEGRA_MUX_TEST, + TEGRA_MUX_TRACE, + TEGRA_MUX_UARTA, + TEGRA_MUX_UARTB, + TEGRA_MUX_UARTC, + TEGRA_MUX_UARTD, + TEGRA_MUX_UARTE, + TEGRA_MUX_ULPI, + TEGRA_MUX_VGP1, + TEGRA_MUX_VGP2, + TEGRA_MUX_VGP3, + TEGRA_MUX_VGP4, + TEGRA_MUX_VGP5, + TEGRA_MUX_VGP6, + TEGRA_MUX_VI, + TEGRA_MUX_VI_ALT1, + TEGRA_MUX_VI_ALT2, + TEGRA_MUX_VI_ALT3, +}; + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + } + +static struct tegra_function tegra30_functions[] = { + FUNCTION(blink), + FUNCTION(cec), + FUNCTION(clk_12m_out), + FUNCTION(clk_32k_in), + FUNCTION(core_pwr_req), + FUNCTION(cpu_pwr_req), + FUNCTION(crt), + FUNCTION(dap), + FUNCTION(ddr), + FUNCTION(dev3), + FUNCTION(displaya), + FUNCTION(displayb), + FUNCTION(dtv), + FUNCTION(extperiph1), + FUNCTION(extperiph2), + FUNCTION(extperiph3), + FUNCTION(gmi), + FUNCTION(gmi_alt), + FUNCTION(hda), + FUNCTION(hdcp), + FUNCTION(hdmi), + FUNCTION(hsi), + FUNCTION(i2c1), + FUNCTION(i2c2), + FUNCTION(i2c3), + FUNCTION(i2c4), + FUNCTION(i2cpwr), + FUNCTION(i2s0), + FUNCTION(i2s1), + FUNCTION(i2s2), + FUNCTION(i2s3), + FUNCTION(i2s4), + FUNCTION(invalid), + FUNCTION(kbc), + FUNCTION(mio), + FUNCTION(nand), + FUNCTION(nand_alt), + FUNCTION(owr), + FUNCTION(pcie), + FUNCTION(pwm0), + FUNCTION(pwm1), + FUNCTION(pwm2), + FUNCTION(pwm3), + FUNCTION(pwr_int_n), + FUNCTION(rsvd1), + FUNCTION(rsvd2), + FUNCTION(rsvd3), + FUNCTION(rsvd4), + FUNCTION(rtck), + FUNCTION(sata), + FUNCTION(sdmmc1), + FUNCTION(sdmmc2), + FUNCTION(sdmmc3), + FUNCTION(sdmmc4), + FUNCTION(spdif), + FUNCTION(spi1), + FUNCTION(spi2), + FUNCTION(spi2_alt), + FUNCTION(spi3), + FUNCTION(spi4), + FUNCTION(spi5), + FUNCTION(spi6), + FUNCTION(sysclk), + FUNCTION(test), + FUNCTION(trace), + FUNCTION(uarta), + FUNCTION(uartb), + FUNCTION(uartc), + FUNCTION(uartd), + FUNCTION(uarte), + FUNCTION(ulpi), + FUNCTION(vgp1), + FUNCTION(vgp2), + FUNCTION(vgp3), + FUNCTION(vgp4), + FUNCTION(vgp5), + FUNCTION(vgp6), + FUNCTION(vi), + FUNCTION(vi_alt1), + FUNCTION(vi_alt2), + FUNCTION(vi_alt3), +}; + +#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ +#define PINGROUP_REG_A 0x3000 /* bank 1 */ + +#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A) +#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) + +#define PINGROUP_BIT_Y(b) (b) +#define PINGROUP_BIT_N(b) (-1) + +#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_##f0, \ + TEGRA_MUX_##f1, \ + TEGRA_MUX_##f2, \ + TEGRA_MUX_##f3, \ + }, \ + .mux_reg = PINGROUP_REG(r), \ + .mux_bank = 1, \ + .mux_bit = 0, \ + .pupd_reg = PINGROUP_REG(r), \ + .pupd_bank = 1, \ + .pupd_bit = 2, \ + .tri_reg = PINGROUP_REG(r), \ + .tri_bank = 1, \ + .tri_bit = 4, \ + .einput_bit = 5, \ + .odrain_bit = PINGROUP_BIT_##od(6), \ + .lock_bit = 7, \ + .ioreset_bit = PINGROUP_BIT_##ior(8), \ + .rcv_sel_bit = -1, \ + .drv_reg = -1, \ + } + +#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, \ + drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, \ + slwf_b, slwf_w) \ + { \ + .name = "drive_" #pg_name, \ + .pins = drive_##pg_name##_pins, \ + .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ + .mux_reg = -1, \ + .pupd_reg = -1, \ + .tri_reg = -1, \ + .einput_bit = -1, \ + .odrain_bit = -1, \ + .lock_bit = -1, \ + .ioreset_bit = -1, \ + .rcv_sel_bit = -1, \ + .drv_reg = DRV_PINGROUP_REG(r), \ + .drv_bank = 0, \ + .hsm_bit = hsm_b, \ + .schmitt_bit = schmitt_b, \ + .lpmd_bit = lpmd_b, \ + .drvdn_bit = drvdn_b, \ + .drvdn_width = drvdn_w, \ + .drvup_bit = drvup_b, \ + .drvup_width = drvup_w, \ + .slwr_bit = slwr_b, \ + .slwr_width = slwr_w, \ + .slwf_bit = slwf_b, \ + .slwf_width = slwf_w, \ + .drvtype_bit = -1, \ + } + +static const struct tegra_pingroup tegra30_groups[] = { + /* pg_name, f0, f1, f2, f3, r, od, ior */ + PINGROUP(clk_32k_out_pa0, BLINK, RSVD2, RSVD3, RSVD4, 0x331c, N, N), + PINGROUP(uart3_cts_n_pa1, UARTC, RSVD2, GMI, RSVD4, 0x317c, N, N), + PINGROUP(dap2_fs_pa2, I2S1, HDA, RSVD3, GMI, 0x3358, N, N), + PINGROUP(dap2_sclk_pa3, I2S1, HDA, RSVD3, GMI, 0x3364, N, N), + PINGROUP(dap2_din_pa4, I2S1, HDA, RSVD3, GMI, 0x335c, N, N), + PINGROUP(dap2_dout_pa5, I2S1, HDA, RSVD3, GMI, 0x3360, N, N), + PINGROUP(sdmmc3_clk_pa6, UARTA, PWM2, SDMMC3, SPI3, 0x3390, N, N), + PINGROUP(sdmmc3_cmd_pa7, UARTA, PWM3, SDMMC3, SPI2, 0x3394, N, N), + PINGROUP(gmi_a17_pb0, UARTD, SPI4, GMI, DTV, 0x3234, N, N), + PINGROUP(gmi_a18_pb1, UARTD, SPI4, GMI, DTV, 0x3238, N, N), + PINGROUP(lcd_pwr0_pb2, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x3090, N, N), + PINGROUP(lcd_pclk_pb3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3094, N, N), + PINGROUP(sdmmc3_dat3_pb4, RSVD1, PWM0, SDMMC3, SPI3, 0x33a4, N, N), + PINGROUP(sdmmc3_dat2_pb5, RSVD1, PWM1, SDMMC3, SPI3, 0x33a0, N, N), + PINGROUP(sdmmc3_dat1_pb6, RSVD1, RSVD2, SDMMC3, SPI3, 0x339c, N, N), + PINGROUP(sdmmc3_dat0_pb7, RSVD1, RSVD2, SDMMC3, SPI3, 0x3398, N, N), + PINGROUP(uart3_rts_n_pc0, UARTC, PWM0, GMI, RSVD4, 0x3180, N, N), + PINGROUP(lcd_pwr1_pc1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3070, N, N), + PINGROUP(uart2_txd_pc2, UARTB, SPDIF, UARTA, SPI4, 0x3168, N, N), + PINGROUP(uart2_rxd_pc3, UARTB, SPDIF, UARTA, SPI4, 0x3164, N, N), + PINGROUP(gen1_i2c_scl_pc4, I2C1, RSVD2, RSVD3, RSVD4, 0x31a4, Y, N), + PINGROUP(gen1_i2c_sda_pc5, I2C1, RSVD2, RSVD3, RSVD4, 0x31a0, Y, N), + PINGROUP(lcd_pwr2_pc6, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x3074, N, N), + PINGROUP(gmi_wp_n_pc7, RSVD1, NAND, GMI, GMI_ALT, 0x31c0, N, N), + PINGROUP(sdmmc3_dat5_pd0, PWM0, SPI4, SDMMC3, SPI2, 0x33ac, N, N), + PINGROUP(sdmmc3_dat4_pd1, PWM1, SPI4, SDMMC3, SPI2, 0x33a8, N, N), + PINGROUP(lcd_dc1_pd2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x310c, N, N), + PINGROUP(sdmmc3_dat6_pd3, SPDIF, SPI4, SDMMC3, SPI2, 0x33b0, N, N), + PINGROUP(sdmmc3_dat7_pd4, SPDIF, SPI4, SDMMC3, SPI2, 0x33b4, N, N), + PINGROUP(vi_d1_pd5, DDR, SDMMC2, VI, RSVD4, 0x3128, N, Y), + PINGROUP(vi_vsync_pd6, DDR, RSVD2, VI, RSVD4, 0x315c, N, Y), + PINGROUP(vi_hsync_pd7, DDR, RSVD2, VI, RSVD4, 0x3160, N, Y), + PINGROUP(lcd_d0_pe0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30a4, N, N), + PINGROUP(lcd_d1_pe1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30a8, N, N), + PINGROUP(lcd_d2_pe2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30ac, N, N), + PINGROUP(lcd_d3_pe3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30b0, N, N), + PINGROUP(lcd_d4_pe4, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30b4, N, N), + PINGROUP(lcd_d5_pe5, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30b8, N, N), + PINGROUP(lcd_d6_pe6, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30bc, N, N), + PINGROUP(lcd_d7_pe7, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30c0, N, N), + PINGROUP(lcd_d8_pf0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30c4, N, N), + PINGROUP(lcd_d9_pf1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30c8, N, N), + PINGROUP(lcd_d10_pf2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30cc, N, N), + PINGROUP(lcd_d11_pf3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30d0, N, N), + PINGROUP(lcd_d12_pf4, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30d4, N, N), + PINGROUP(lcd_d13_pf5, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30d8, N, N), + PINGROUP(lcd_d14_pf6, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30dc, N, N), + PINGROUP(lcd_d15_pf7, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30e0, N, N), + PINGROUP(gmi_ad0_pg0, RSVD1, NAND, GMI, RSVD4, 0x31f0, N, N), + PINGROUP(gmi_ad1_pg1, RSVD1, NAND, GMI, RSVD4, 0x31f4, N, N), + PINGROUP(gmi_ad2_pg2, RSVD1, NAND, GMI, RSVD4, 0x31f8, N, N), + PINGROUP(gmi_ad3_pg3, RSVD1, NAND, GMI, RSVD4, 0x31fc, N, N), + PINGROUP(gmi_ad4_pg4, RSVD1, NAND, GMI, RSVD4, 0x3200, N, N), + PINGROUP(gmi_ad5_pg5, RSVD1, NAND, GMI, RSVD4, 0x3204, N, N), + PINGROUP(gmi_ad6_pg6, RSVD1, NAND, GMI, RSVD4, 0x3208, N, N), + PINGROUP(gmi_ad7_pg7, RSVD1, NAND, GMI, RSVD4, 0x320c, N, N), + PINGROUP(gmi_ad8_ph0, PWM0, NAND, GMI, RSVD4, 0x3210, N, N), + PINGROUP(gmi_ad9_ph1, PWM1, NAND, GMI, RSVD4, 0x3214, N, N), + PINGROUP(gmi_ad10_ph2, PWM2, NAND, GMI, RSVD4, 0x3218, N, N), + PINGROUP(gmi_ad11_ph3, PWM3, NAND, GMI, RSVD4, 0x321c, N, N), + PINGROUP(gmi_ad12_ph4, RSVD1, NAND, GMI, RSVD4, 0x3220, N, N), + PINGROUP(gmi_ad13_ph5, RSVD1, NAND, GMI, RSVD4, 0x3224, N, N), + PINGROUP(gmi_ad14_ph6, RSVD1, NAND, GMI, RSVD4, 0x3228, N, N), + PINGROUP(gmi_ad15_ph7, RSVD1, NAND, GMI, RSVD4, 0x322c, N, N), + PINGROUP(gmi_wr_n_pi0, RSVD1, NAND, GMI, RSVD4, 0x3240, N, N), + PINGROUP(gmi_oe_n_pi1, RSVD1, NAND, GMI, RSVD4, 0x3244, N, N), + PINGROUP(gmi_dqs_pi2, RSVD1, NAND, GMI, RSVD4, 0x3248, N, N), + PINGROUP(gmi_cs6_n_pi3, NAND, NAND_ALT, GMI, SATA, 0x31e8, N, N), + PINGROUP(gmi_rst_n_pi4, NAND, NAND_ALT, GMI, RSVD4, 0x324c, N, N), + PINGROUP(gmi_iordy_pi5, RSVD1, NAND, GMI, RSVD4, 0x31c4, N, N), + PINGROUP(gmi_cs7_n_pi6, NAND, NAND_ALT, GMI, GMI_ALT, 0x31ec, N, N), + PINGROUP(gmi_wait_pi7, RSVD1, NAND, GMI, RSVD4, 0x31c8, N, N), + PINGROUP(gmi_cs0_n_pj0, RSVD1, NAND, GMI, DTV, 0x31d4, N, N), + PINGROUP(lcd_de_pj1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3098, N, N), + PINGROUP(gmi_cs1_n_pj2, RSVD1, NAND, GMI, DTV, 0x31d8, N, N), + PINGROUP(lcd_hsync_pj3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x309c, N, N), + PINGROUP(lcd_vsync_pj4, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30a0, N, N), + PINGROUP(uart2_cts_n_pj5, UARTA, UARTB, GMI, SPI4, 0x3170, N, N), + PINGROUP(uart2_rts_n_pj6, UARTA, UARTB, GMI, SPI4, 0x316c, N, N), + PINGROUP(gmi_a16_pj7, UARTD, SPI4, GMI, GMI_ALT, 0x3230, N, N), + PINGROUP(gmi_adv_n_pk0, RSVD1, NAND, GMI, RSVD4, 0x31cc, N, N), + PINGROUP(gmi_clk_pk1, RSVD1, NAND, GMI, RSVD4, 0x31d0, N, N), + PINGROUP(gmi_cs4_n_pk2, RSVD1, NAND, GMI, RSVD4, 0x31e4, N, N), + PINGROUP(gmi_cs2_n_pk3, RSVD1, NAND, GMI, RSVD4, 0x31dc, N, N), + PINGROUP(gmi_cs3_n_pk4, RSVD1, NAND, GMI, GMI_ALT, 0x31e0, N, N), + PINGROUP(spdif_out_pk5, SPDIF, RSVD2, I2C1, SDMMC2, 0x3354, N, N), + PINGROUP(spdif_in_pk6, SPDIF, HDA, I2C1, SDMMC2, 0x3350, N, N), + PINGROUP(gmi_a19_pk7, UARTD, SPI4, GMI, RSVD4, 0x323c, N, N), + PINGROUP(vi_d2_pl0, DDR, SDMMC2, VI, RSVD4, 0x312c, N, Y), + PINGROUP(vi_d3_pl1, DDR, SDMMC2, VI, RSVD4, 0x3130, N, Y), + PINGROUP(vi_d4_pl2, DDR, SDMMC2, VI, RSVD4, 0x3134, N, Y), + PINGROUP(vi_d5_pl3, DDR, SDMMC2, VI, RSVD4, 0x3138, N, Y), + PINGROUP(vi_d6_pl4, DDR, SDMMC2, VI, RSVD4, 0x313c, N, Y), + PINGROUP(vi_d7_pl5, DDR, SDMMC2, VI, RSVD4, 0x3140, N, Y), + PINGROUP(vi_d8_pl6, DDR, SDMMC2, VI, RSVD4, 0x3144, N, Y), + PINGROUP(vi_d9_pl7, DDR, SDMMC2, VI, RSVD4, 0x3148, N, Y), + PINGROUP(lcd_d16_pm0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30e4, N, N), + PINGROUP(lcd_d17_pm1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30e8, N, N), + PINGROUP(lcd_d18_pm2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30ec, N, N), + PINGROUP(lcd_d19_pm3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30f0, N, N), + PINGROUP(lcd_d20_pm4, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30f4, N, N), + PINGROUP(lcd_d21_pm5, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30f8, N, N), + PINGROUP(lcd_d22_pm6, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30fc, N, N), + PINGROUP(lcd_d23_pm7, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3100, N, N), + PINGROUP(dap1_fs_pn0, I2S0, HDA, GMI, SDMMC2, 0x3338, N, N), + PINGROUP(dap1_din_pn1, I2S0, HDA, GMI, SDMMC2, 0x333c, N, N), + PINGROUP(dap1_dout_pn2, I2S0, HDA, GMI, SDMMC2, 0x3340, N, N), + PINGROUP(dap1_sclk_pn3, I2S0, HDA, GMI, SDMMC2, 0x3344, N, N), + PINGROUP(lcd_cs0_n_pn4, DISPLAYA, DISPLAYB, SPI5, RSVD4, 0x3084, N, N), + PINGROUP(lcd_sdout_pn5, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x307c, N, N), + PINGROUP(lcd_dc0_pn6, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3088, N, N), + PINGROUP(hdmi_int_pn7, HDMI, RSVD2, RSVD3, RSVD4, 0x3110, N, N), + PINGROUP(ulpi_data7_po0, SPI2, HSI, UARTA, ULPI, 0x301c, N, N), + PINGROUP(ulpi_data0_po1, SPI3, HSI, UARTA, ULPI, 0x3000, N, N), + PINGROUP(ulpi_data1_po2, SPI3, HSI, UARTA, ULPI, 0x3004, N, N), + PINGROUP(ulpi_data2_po3, SPI3, HSI, UARTA, ULPI, 0x3008, N, N), + PINGROUP(ulpi_data3_po4, SPI3, HSI, UARTA, ULPI, 0x300c, N, N), + PINGROUP(ulpi_data4_po5, SPI2, HSI, UARTA, ULPI, 0x3010, N, N), + PINGROUP(ulpi_data5_po6, SPI2, HSI, UARTA, ULPI, 0x3014, N, N), + PINGROUP(ulpi_data6_po7, SPI2, HSI, UARTA, ULPI, 0x3018, N, N), + PINGROUP(dap3_fs_pp0, I2S2, RSVD2, DISPLAYA, DISPLAYB, 0x3030, N, N), + PINGROUP(dap3_din_pp1, I2S2, RSVD2, DISPLAYA, DISPLAYB, 0x3034, N, N), + PINGROUP(dap3_dout_pp2, I2S2, RSVD2, DISPLAYA, DISPLAYB, 0x3038, N, N), + PINGROUP(dap3_sclk_pp3, I2S2, RSVD2, DISPLAYA, DISPLAYB, 0x303c, N, N), + PINGROUP(dap4_fs_pp4, I2S3, RSVD2, GMI, RSVD4, 0x31a8, N, N), + PINGROUP(dap4_din_pp5, I2S3, RSVD2, GMI, RSVD4, 0x31ac, N, N), + PINGROUP(dap4_dout_pp6, I2S3, RSVD2, GMI, RSVD4, 0x31b0, N, N), + PINGROUP(dap4_sclk_pp7, I2S3, RSVD2, GMI, RSVD4, 0x31b4, N, N), + PINGROUP(kb_col0_pq0, KBC, NAND, TRACE, TEST, 0x32fc, N, N), + PINGROUP(kb_col1_pq1, KBC, NAND, TRACE, TEST, 0x3300, N, N), + PINGROUP(kb_col2_pq2, KBC, NAND, TRACE, RSVD4, 0x3304, N, N), + PINGROUP(kb_col3_pq3, KBC, NAND, TRACE, RSVD4, 0x3308, N, N), + PINGROUP(kb_col4_pq4, KBC, NAND, TRACE, RSVD4, 0x330c, N, N), + PINGROUP(kb_col5_pq5, KBC, NAND, TRACE, RSVD4, 0x3310, N, N), + PINGROUP(kb_col6_pq6, KBC, NAND, TRACE, MIO, 0x3314, N, N), + PINGROUP(kb_col7_pq7, KBC, NAND, TRACE, MIO, 0x3318, N, N), + PINGROUP(kb_row0_pr0, KBC, NAND, RSVD3, RSVD4, 0x32bc, N, N), + PINGROUP(kb_row1_pr1, KBC, NAND, RSVD3, RSVD4, 0x32c0, N, N), + PINGROUP(kb_row2_pr2, KBC, NAND, RSVD3, RSVD4, 0x32c4, N, N), + PINGROUP(kb_row3_pr3, KBC, NAND, RSVD3, INVALID, 0x32c8, N, N), + PINGROUP(kb_row4_pr4, KBC, NAND, TRACE, RSVD4, 0x32cc, N, N), + PINGROUP(kb_row5_pr5, KBC, NAND, TRACE, OWR, 0x32d0, N, N), + PINGROUP(kb_row6_pr6, KBC, NAND, SDMMC2, MIO, 0x32d4, N, N), + PINGROUP(kb_row7_pr7, KBC, NAND, SDMMC2, MIO, 0x32d8, N, N), + PINGROUP(kb_row8_ps0, KBC, NAND, SDMMC2, MIO, 0x32dc, N, N), + PINGROUP(kb_row9_ps1, KBC, NAND, SDMMC2, MIO, 0x32e0, N, N), + PINGROUP(kb_row10_ps2, KBC, NAND, SDMMC2, MIO, 0x32e4, N, N), + PINGROUP(kb_row11_ps3, KBC, NAND, SDMMC2, MIO, 0x32e8, N, N), + PINGROUP(kb_row12_ps4, KBC, NAND, SDMMC2, MIO, 0x32ec, N, N), + PINGROUP(kb_row13_ps5, KBC, NAND, SDMMC2, MIO, 0x32f0, N, N), + PINGROUP(kb_row14_ps6, KBC, NAND, SDMMC2, MIO, 0x32f4, N, N), + PINGROUP(kb_row15_ps7, KBC, NAND, SDMMC2, MIO, 0x32f8, N, N), + PINGROUP(vi_pclk_pt0, RSVD1, SDMMC2, VI, RSVD4, 0x3154, N, Y), + PINGROUP(vi_mclk_pt1, VI, VI_ALT1, VI_ALT2, VI_ALT3, 0x3158, N, Y), + PINGROUP(vi_d10_pt2, DDR, RSVD2, VI, RSVD4, 0x314c, N, Y), + PINGROUP(vi_d11_pt3, DDR, RSVD2, VI, RSVD4, 0x3150, N, Y), + PINGROUP(vi_d0_pt4, DDR, RSVD2, VI, RSVD4, 0x3124, N, Y), + PINGROUP(gen2_i2c_scl_pt5, I2C2, HDCP, GMI, RSVD4, 0x3250, Y, N), + PINGROUP(gen2_i2c_sda_pt6, I2C2, HDCP, GMI, RSVD4, 0x3254, Y, N), + PINGROUP(sdmmc4_cmd_pt7, I2C3, NAND, GMI, SDMMC4, 0x325c, N, Y), + PINGROUP(pu0, OWR, UARTA, GMI, RSVD4, 0x3184, N, N), + PINGROUP(pu1, RSVD1, UARTA, GMI, RSVD4, 0x3188, N, N), + PINGROUP(pu2, RSVD1, UARTA, GMI, RSVD4, 0x318c, N, N), + PINGROUP(pu3, PWM0, UARTA, GMI, RSVD4, 0x3190, N, N), + PINGROUP(pu4, PWM1, UARTA, GMI, RSVD4, 0x3194, N, N), + PINGROUP(pu5, PWM2, UARTA, GMI, RSVD4, 0x3198, N, N), + PINGROUP(pu6, PWM3, UARTA, GMI, RSVD4, 0x319c, N, N), + PINGROUP(jtag_rtck_pu7, RTCK, RSVD2, RSVD3, RSVD4, 0x32b0, N, N), + PINGROUP(pv0, RSVD1, RSVD2, RSVD3, RSVD4, 0x3040, N, N), + PINGROUP(pv1, RSVD1, RSVD2, RSVD3, RSVD4, 0x3044, N, N), + PINGROUP(pv2, OWR, RSVD2, RSVD3, RSVD4, 0x3060, N, N), + PINGROUP(pv3, CLK_12M_OUT, RSVD2, RSVD3, RSVD4, 0x3064, N, N), + PINGROUP(ddc_scl_pv4, I2C4, RSVD2, RSVD3, RSVD4, 0x3114, N, N), + PINGROUP(ddc_sda_pv5, I2C4, RSVD2, RSVD3, RSVD4, 0x3118, N, N), + PINGROUP(crt_hsync_pv6, CRT, RSVD2, RSVD3, RSVD4, 0x311c, N, N), + PINGROUP(crt_vsync_pv7, CRT, RSVD2, RSVD3, RSVD4, 0x3120, N, N), + PINGROUP(lcd_cs1_n_pw0, DISPLAYA, DISPLAYB, SPI5, RSVD4, 0x3104, N, N), + PINGROUP(lcd_m1_pw1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3108, N, N), + PINGROUP(spi2_cs1_n_pw2, SPI3, SPI2, SPI2_ALT, I2C1, 0x3388, N, N), + PINGROUP(spi2_cs2_n_pw3, SPI3, SPI2, SPI2_ALT, I2C1, 0x338c, N, N), + PINGROUP(clk1_out_pw4, EXTPERIPH1, RSVD2, RSVD3, RSVD4, 0x334c, N, N), + PINGROUP(clk2_out_pw5, EXTPERIPH2, RSVD2, RSVD3, RSVD4, 0x3068, N, N), + PINGROUP(uart3_txd_pw6, UARTC, RSVD2, GMI, RSVD4, 0x3174, N, N), + PINGROUP(uart3_rxd_pw7, UARTC, RSVD2, GMI, RSVD4, 0x3178, N, N), + PINGROUP(spi2_mosi_px0, SPI6, SPI2, SPI3, GMI, 0x3368, N, N), + PINGROUP(spi2_miso_px1, SPI6, SPI2, SPI3, GMI, 0x336c, N, N), + PINGROUP(spi2_sck_px2, SPI6, SPI2, SPI3, GMI, 0x3374, N, N), + PINGROUP(spi2_cs0_n_px3, SPI6, SPI2, SPI3, GMI, 0x3370, N, N), + PINGROUP(spi1_mosi_px4, SPI2, SPI1, SPI2_ALT, GMI, 0x3378, N, N), + PINGROUP(spi1_sck_px5, SPI2, SPI1, SPI2_ALT, GMI, 0x337c, N, N), + PINGROUP(spi1_cs0_n_px6, SPI2, SPI1, SPI2_ALT, GMI, 0x3380, N, N), + PINGROUP(spi1_miso_px7, SPI3, SPI1, SPI2_ALT, RSVD4, 0x3384, N, N), + PINGROUP(ulpi_clk_py0, SPI1, RSVD2, UARTD, ULPI, 0x3020, N, N), + PINGROUP(ulpi_dir_py1, SPI1, RSVD2, UARTD, ULPI, 0x3024, N, N), + PINGROUP(ulpi_nxt_py2, SPI1, RSVD2, UARTD, ULPI, 0x3028, N, N), + PINGROUP(ulpi_stp_py3, SPI1, RSVD2, UARTD, ULPI, 0x302c, N, N), + PINGROUP(sdmmc1_dat3_py4, SDMMC1, RSVD2, UARTE, UARTA, 0x3050, N, N), + PINGROUP(sdmmc1_dat2_py5, SDMMC1, RSVD2, UARTE, UARTA, 0x3054, N, N), + PINGROUP(sdmmc1_dat1_py6, SDMMC1, RSVD2, UARTE, UARTA, 0x3058, N, N), + PINGROUP(sdmmc1_dat0_py7, SDMMC1, RSVD2, UARTE, UARTA, 0x305c, N, N), + PINGROUP(sdmmc1_clk_pz0, SDMMC1, RSVD2, RSVD3, UARTA, 0x3048, N, N), + PINGROUP(sdmmc1_cmd_pz1, SDMMC1, RSVD2, RSVD3, UARTA, 0x304c, N, N), + PINGROUP(lcd_sdin_pz2, DISPLAYA, DISPLAYB, SPI5, RSVD4, 0x3078, N, N), + PINGROUP(lcd_wr_n_pz3, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x3080, N, N), + PINGROUP(lcd_sck_pz4, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x308c, N, N), + PINGROUP(sys_clk_req_pz5, SYSCLK, RSVD2, RSVD3, RSVD4, 0x3320, N, N), + PINGROUP(pwr_i2c_scl_pz6, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b4, Y, N), + PINGROUP(pwr_i2c_sda_pz7, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b8, Y, N), + PINGROUP(sdmmc4_dat0_paa0, UARTE, SPI3, GMI, SDMMC4, 0x3260, N, Y), + PINGROUP(sdmmc4_dat1_paa1, UARTE, SPI3, GMI, SDMMC4, 0x3264, N, Y), + PINGROUP(sdmmc4_dat2_paa2, UARTE, SPI3, GMI, SDMMC4, 0x3268, N, Y), + PINGROUP(sdmmc4_dat3_paa3, UARTE, SPI3, GMI, SDMMC4, 0x326c, N, Y), + PINGROUP(sdmmc4_dat4_paa4, I2C3, I2S4, GMI, SDMMC4, 0x3270, N, Y), + PINGROUP(sdmmc4_dat5_paa5, VGP3, I2S4, GMI, SDMMC4, 0x3274, N, Y), + PINGROUP(sdmmc4_dat6_paa6, VGP4, I2S4, GMI, SDMMC4, 0x3278, N, Y), + PINGROUP(sdmmc4_dat7_paa7, VGP5, I2S4, GMI, SDMMC4, 0x327c, N, Y), + PINGROUP(pbb0, I2S4, RSVD2, RSVD3, SDMMC4, 0x328c, N, N), + PINGROUP(cam_i2c_scl_pbb1, VGP1, I2C3, RSVD3, SDMMC4, 0x3290, Y, N), + PINGROUP(cam_i2c_sda_pbb2, VGP2, I2C3, RSVD3, SDMMC4, 0x3294, Y, N), + PINGROUP(pbb3, VGP3, DISPLAYA, DISPLAYB, SDMMC4, 0x3298, N, N), + PINGROUP(pbb4, VGP4, DISPLAYA, DISPLAYB, SDMMC4, 0x329c, N, N), + PINGROUP(pbb5, VGP5, DISPLAYA, DISPLAYB, SDMMC4, 0x32a0, N, N), + PINGROUP(pbb6, VGP6, DISPLAYA, DISPLAYB, SDMMC4, 0x32a4, N, N), + PINGROUP(pbb7, I2S4, RSVD2, RSVD3, SDMMC4, 0x32a8, N, N), + PINGROUP(cam_mclk_pcc0, VI, VI_ALT1, VI_ALT3, SDMMC4, 0x3284, N, N), + PINGROUP(pcc1, I2S4, RSVD2, RSVD3, SDMMC4, 0x3288, N, N), + PINGROUP(pcc2, I2S4, RSVD2, RSVD3, RSVD4, 0x32ac, N, N), + PINGROUP(sdmmc4_rst_n_pcc3, VGP6, RSVD2, RSVD3, SDMMC4, 0x3280, N, Y), + PINGROUP(sdmmc4_clk_pcc4, INVALID, NAND, GMI, SDMMC4, 0x3258, N, Y), + PINGROUP(clk2_req_pcc5, DAP, RSVD2, RSVD3, RSVD4, 0x306c, N, N), + PINGROUP(pex_l2_rst_n_pcc6, PCIE, HDA, RSVD3, RSVD4, 0x33d8, N, N), + PINGROUP(pex_l2_clkreq_n_pcc7, PCIE, HDA, RSVD3, RSVD4, 0x33dc, N, N), + PINGROUP(pex_l0_prsnt_n_pdd0, PCIE, HDA, RSVD3, RSVD4, 0x33b8, N, N), + PINGROUP(pex_l0_rst_n_pdd1, PCIE, HDA, RSVD3, RSVD4, 0x33bc, N, N), + PINGROUP(pex_l0_clkreq_n_pdd2, PCIE, HDA, RSVD3, RSVD4, 0x33c0, N, N), + PINGROUP(pex_wake_n_pdd3, PCIE, HDA, RSVD3, RSVD4, 0x33c4, N, N), + PINGROUP(pex_l1_prsnt_n_pdd4, PCIE, HDA, RSVD3, RSVD4, 0x33c8, N, N), + PINGROUP(pex_l1_rst_n_pdd5, PCIE, HDA, RSVD3, RSVD4, 0x33cc, N, N), + PINGROUP(pex_l1_clkreq_n_pdd6, PCIE, HDA, RSVD3, RSVD4, 0x33d0, N, N), + PINGROUP(pex_l2_prsnt_n_pdd7, PCIE, HDA, RSVD3, RSVD4, 0x33d4, N, N), + PINGROUP(clk3_out_pee0, EXTPERIPH3, RSVD2, RSVD3, RSVD4, 0x31b8, N, N), + PINGROUP(clk3_req_pee1, DEV3, RSVD2, RSVD3, RSVD4, 0x31bc, N, N), + PINGROUP(clk1_req_pee2, DAP, HDA, RSVD3, RSVD4, 0x3348, N, N), + PINGROUP(hdmi_cec_pee3, CEC, RSVD2, RSVD3, RSVD4, 0x33e0, Y, N), + PINGROUP(clk_32k_in, CLK_32K_IN, RSVD2, RSVD3, RSVD4, 0x3330, N, N), + PINGROUP(core_pwr_req, CORE_PWR_REQ, RSVD2, RSVD3, RSVD4, 0x3324, N, N), + PINGROUP(cpu_pwr_req, CPU_PWR_REQ, RSVD2, RSVD3, RSVD4, 0x3328, N, N), + PINGROUP(owr, OWR, CEC, RSVD3, RSVD4, 0x3334, N, N), + PINGROUP(pwr_int_n, PWR_INT_N, RSVD2, RSVD3, RSVD4, 0x332c, N, N), + /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */ + DRV_PINGROUP(ao1, 0x868, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(ao2, 0x86c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(at1, 0x870, 2, 3, 4, 14, 5, 19, 5, 24, 2, 28, 2), + DRV_PINGROUP(at2, 0x874, 2, 3, 4, 14, 5, 19, 5, 24, 2, 28, 2), + DRV_PINGROUP(at3, 0x878, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), + DRV_PINGROUP(at4, 0x87c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), + DRV_PINGROUP(at5, 0x880, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), + DRV_PINGROUP(cdev1, 0x884, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(cdev2, 0x888, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(cec, 0x938, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(crt, 0x8f8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(csus, 0x88c, -1, -1, -1, 12, 5, 19, 5, 24, 4, 28, 4), + DRV_PINGROUP(dap1, 0x890, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(dap2, 0x894, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(dap3, 0x898, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(dap4, 0x89c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(dbg, 0x8a0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(ddc, 0x8fc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(dev3, 0x92c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(gma, 0x900, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), + DRV_PINGROUP(gmb, 0x904, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), + DRV_PINGROUP(gmc, 0x908, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), + DRV_PINGROUP(gmd, 0x90c, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), + DRV_PINGROUP(gme, 0x910, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), + DRV_PINGROUP(gmf, 0x914, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), + DRV_PINGROUP(gmg, 0x918, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), + DRV_PINGROUP(gmh, 0x91c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), + DRV_PINGROUP(gpv, 0x928, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(lcd1, 0x8a4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(lcd2, 0x8a8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(owr, 0x920, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(sdio1, 0x8ec, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2), + DRV_PINGROUP(sdio2, 0x8ac, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2), + DRV_PINGROUP(sdio3, 0x8b0, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2), + DRV_PINGROUP(spi, 0x8b4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(uaa, 0x8b8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(uab, 0x8bc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(uart2, 0x8c0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(uart3, 0x8c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(uda, 0x924, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(vi1, 0x8c8, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), +}; + +static const struct tegra_pinctrl_soc_data tegra30_pinctrl = { + .ngpios = NUM_GPIOS, + .pins = tegra30_pins, + .npins = ARRAY_SIZE(tegra30_pins), + .functions = tegra30_functions, + .nfunctions = ARRAY_SIZE(tegra30_functions), + .groups = tegra30_groups, + .ngroups = ARRAY_SIZE(tegra30_groups), + .hsm_in_mux = false, + .schmitt_in_mux = false, + .drvtype_in_mux = false, +}; + +static int tegra30_pinctrl_probe(struct platform_device *pdev) +{ + return tegra_pinctrl_probe(pdev, &tegra30_pinctrl); +} + +static const struct of_device_id tegra30_pinctrl_of_match[] = { + { .compatible = "nvidia,tegra30-pinmux", }, + { }, +}; +MODULE_DEVICE_TABLE(of, tegra30_pinctrl_of_match); + +static struct platform_driver tegra30_pinctrl_driver = { + .driver = { + .name = "tegra30-pinctrl", + .of_match_table = tegra30_pinctrl_of_match, + }, + .probe = tegra30_pinctrl_probe, + .remove = tegra_pinctrl_remove, +}; +module_platform_driver(tegra30_pinctrl_driver); + +MODULE_AUTHOR("Stephen Warren "); +MODULE_DESCRIPTION("NVIDIA Tegra30 pinctrl driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 8a56736a2f53abe6edd1c67acc4f6161d5c16c07 Mon Sep 17 00:00:00 2001 From: Damien Horsley Date: Mon, 18 Jan 2016 13:12:38 +0000 Subject: reset: img: Add Pistachio reset controller driver Add reset controller driver for Pistachio SoC Signed-off-by: Damien Horsley Signed-off-by: James Hartley Signed-off-by: Philipp Zabel --- drivers/reset/Makefile | 1 + drivers/reset/reset-pistachio.c | 154 +++++++++++++++++++++++++++ include/dt-bindings/reset/pistachio-resets.h | 36 +++++++ 3 files changed, 191 insertions(+) create mode 100644 drivers/reset/reset-pistachio.c create mode 100644 include/dt-bindings/reset/pistachio-resets.h (limited to 'drivers') diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 4d7178e46afa..a1fc8eda79f3 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -2,6 +2,7 @@ obj-y += core.o obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o +obj-$(CONFIG_MACH_PISTACHIO) += reset-pistachio.o obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o obj-$(CONFIG_ARCH_STI) += sti/ obj-$(CONFIG_ARCH_HISI) += hisilicon/ diff --git a/drivers/reset/reset-pistachio.c b/drivers/reset/reset-pistachio.c new file mode 100644 index 000000000000..b31cdb0570fc --- /dev/null +++ b/drivers/reset/reset-pistachio.c @@ -0,0 +1,154 @@ +/* + * Pistachio SoC Reset Controller driver + * + * Copyright (C) 2015 Imagination Technologies Ltd. + * + * Author: Damien Horsley + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define PISTACHIO_SOFT_RESET 0 + +struct pistachio_reset_data { + struct reset_controller_dev rcdev; + struct regmap *periph_regs; +}; + +static inline int pistachio_reset_shift(unsigned long id) +{ + switch (id) { + case PISTACHIO_RESET_I2C0: + case PISTACHIO_RESET_I2C1: + case PISTACHIO_RESET_I2C2: + case PISTACHIO_RESET_I2C3: + case PISTACHIO_RESET_I2S_IN: + case PISTACHIO_RESET_PRL_OUT: + case PISTACHIO_RESET_SPDIF_OUT: + case PISTACHIO_RESET_SPI: + case PISTACHIO_RESET_PWM_PDM: + case PISTACHIO_RESET_UART0: + case PISTACHIO_RESET_UART1: + case PISTACHIO_RESET_QSPI: + case PISTACHIO_RESET_MDC: + case PISTACHIO_RESET_SDHOST: + case PISTACHIO_RESET_ETHERNET: + case PISTACHIO_RESET_IR: + case PISTACHIO_RESET_HASH: + case PISTACHIO_RESET_TIMER: + return id; + case PISTACHIO_RESET_I2S_OUT: + case PISTACHIO_RESET_SPDIF_IN: + case PISTACHIO_RESET_EVT: + return id + 6; + case PISTACHIO_RESET_USB_H: + case PISTACHIO_RESET_USB_PR: + case PISTACHIO_RESET_USB_PHY_PR: + case PISTACHIO_RESET_USB_PHY_PON: + return id + 7; + default: + return -EINVAL; + } +} + +static int pistachio_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct pistachio_reset_data *rd; + u32 mask; + int shift; + + rd = container_of(rcdev, struct pistachio_reset_data, rcdev); + shift = pistachio_reset_shift(id); + if (shift < 0) + return shift; + mask = BIT(shift); + + return regmap_update_bits(rd->periph_regs, PISTACHIO_SOFT_RESET, + mask, mask); +} + +static int pistachio_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct pistachio_reset_data *rd; + u32 mask; + int shift; + + rd = container_of(rcdev, struct pistachio_reset_data, rcdev); + shift = pistachio_reset_shift(id); + if (shift < 0) + return shift; + mask = BIT(shift); + + return regmap_update_bits(rd->periph_regs, PISTACHIO_SOFT_RESET, + mask, 0); +} + +static struct reset_control_ops pistachio_reset_ops = { + .assert = pistachio_reset_assert, + .deassert = pistachio_reset_deassert, +}; + +static int pistachio_reset_probe(struct platform_device *pdev) +{ + struct pistachio_reset_data *rd; + struct device *dev = &pdev->dev; + struct device_node *np = pdev->dev.of_node; + + rd = devm_kzalloc(dev, sizeof(*rd), GFP_KERNEL); + if (!rd) + return -ENOMEM; + + rd->periph_regs = syscon_node_to_regmap(np->parent); + if (IS_ERR(rd->periph_regs)) + return PTR_ERR(rd->periph_regs); + + rd->rcdev.owner = THIS_MODULE; + rd->rcdev.nr_resets = PISTACHIO_RESET_MAX + 1; + rd->rcdev.ops = &pistachio_reset_ops; + rd->rcdev.of_node = np; + + return reset_controller_register(&rd->rcdev); +} + +static int pistachio_reset_remove(struct platform_device *pdev) +{ + struct pistachio_reset_data *data = platform_get_drvdata(pdev); + + reset_controller_unregister(&data->rcdev); + + return 0; +} + +static const struct of_device_id pistachio_reset_dt_ids[] = { + { .compatible = "img,pistachio-reset", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, pistachio_reset_dt_ids); + +static struct platform_driver pistachio_reset_driver = { + .probe = pistachio_reset_probe, + .remove = pistachio_reset_remove, + .driver = { + .name = "pistachio-reset", + .of_match_table = pistachio_reset_dt_ids, + }, +}; +module_platform_driver(pistachio_reset_driver); + +MODULE_AUTHOR("Damien Horsley "); +MODULE_DESCRIPTION("Pistacho Reset Controller Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/dt-bindings/reset/pistachio-resets.h b/include/dt-bindings/reset/pistachio-resets.h new file mode 100644 index 000000000000..60a189b1faef --- /dev/null +++ b/include/dt-bindings/reset/pistachio-resets.h @@ -0,0 +1,36 @@ +/* + * This header provides constants for the reset controller + * present in the Pistachio SoC + */ + +#ifndef _PISTACHIO_RESETS_H +#define _PISTACHIO_RESETS_H + +#define PISTACHIO_RESET_I2C0 0 +#define PISTACHIO_RESET_I2C1 1 +#define PISTACHIO_RESET_I2C2 2 +#define PISTACHIO_RESET_I2C3 3 +#define PISTACHIO_RESET_I2S_IN 4 +#define PISTACHIO_RESET_PRL_OUT 5 +#define PISTACHIO_RESET_SPDIF_OUT 6 +#define PISTACHIO_RESET_SPI 7 +#define PISTACHIO_RESET_PWM_PDM 8 +#define PISTACHIO_RESET_UART0 9 +#define PISTACHIO_RESET_UART1 10 +#define PISTACHIO_RESET_QSPI 11 +#define PISTACHIO_RESET_MDC 12 +#define PISTACHIO_RESET_SDHOST 13 +#define PISTACHIO_RESET_ETHERNET 14 +#define PISTACHIO_RESET_IR 15 +#define PISTACHIO_RESET_HASH 16 +#define PISTACHIO_RESET_TIMER 17 +#define PISTACHIO_RESET_I2S_OUT 18 +#define PISTACHIO_RESET_SPDIF_IN 19 +#define PISTACHIO_RESET_EVT 20 +#define PISTACHIO_RESET_USB_H 21 +#define PISTACHIO_RESET_USB_PR 22 +#define PISTACHIO_RESET_USB_PHY_PR 23 +#define PISTACHIO_RESET_USB_PHY_PON 24 +#define PISTACHIO_RESET_MAX 24 + +#endif -- cgit v1.2.3 From 27ca5aaa3676a135d3767e8ffe1ba1f5ee9ec0bb Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Sun, 17 Jan 2016 15:08:19 +0100 Subject: reset: berlin: drop DT cell size check Now that the DT cell size check has been moved to the core, there is no need to check again. Signed-off-by: Philipp Zabel --- drivers/reset/reset-berlin.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/reset/reset-berlin.c b/drivers/reset/reset-berlin.c index 970b1ad60293..ac017df8858c 100644 --- a/drivers/reset/reset-berlin.c +++ b/drivers/reset/reset-berlin.c @@ -55,9 +55,6 @@ static int berlin_reset_xlate(struct reset_controller_dev *rcdev, { unsigned offset, bit; - if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells)) - return -EINVAL; - offset = reset_spec->args[0]; bit = reset_spec->args[1]; -- cgit v1.2.3 From a3ff9582369e71439ad2bf40e70474b9f1b85c55 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 5 Feb 2016 16:46:26 +0200 Subject: spi: dw-mid: switch to new dmaengine_terminate_* API Convert dmaengine_terminate_all() calls to synchronous versions. Signed-off-by: Andy Shevchenko Signed-off-by: Mark Brown --- drivers/spi/spi-dw-mid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c index 9185f6c08459..e31971f91475 100644 --- a/drivers/spi/spi-dw-mid.c +++ b/drivers/spi/spi-dw-mid.c @@ -89,10 +89,10 @@ static void mid_spi_dma_exit(struct dw_spi *dws) if (!dws->dma_inited) return; - dmaengine_terminate_all(dws->txchan); + dmaengine_terminate_sync(dws->txchan); dma_release_channel(dws->txchan); - dmaengine_terminate_all(dws->rxchan); + dmaengine_terminate_sync(dws->rxchan); dma_release_channel(dws->rxchan); } -- cgit v1.2.3 From 2f6fdefb3503ff0600b5435c0c9ce43cb50d3f1a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 5 Feb 2016 16:54:10 +0200 Subject: spi: dw-mmio: remove message which is handled by core devm_ioremap_resource() validates its parameters and issues an error message if needed. Signed-off-by: Andy Shevchenko Signed-off-by: Mark Brown --- drivers/spi/spi-dw-mmio.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index a6d7029a85ac..447497e9124c 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -47,11 +47,6 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) /* Get basic io resource and map it */ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "no mem resource?\n"); - return -EINVAL; - } - dws->regs = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(dws->regs)) { dev_err(&pdev->dev, "SPI region map failed\n"); -- cgit v1.2.3 From b1353d1c1d4555b7c40066fa2cacc7da266e9904 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 4 Feb 2016 17:13:30 +0100 Subject: spi: Add Analog Devices AXI SPI Engine controller support This patch adds support for the AXI SPI Engine controller which is a FPGA soft-peripheral which is used in some of Analog Devices' reference designs. The AXI SPI Engine controller is part of the SPI Engine framework[1] and allows memory mapped access to the SPI Engine control bus. This allows it to be used as a general purpose software driven SPI controller. The SPI Engine in addition offers some optional advanced acceleration and offloading capabilities, which are not part of this patch though and will be introduced separately. At the core of the SPI Engine framework is a small sort of co-processor that accepts a command stream and turns the commands into low-level SPI transactions. Communication is done through three memory mapped FIFOs in the register map of the AXI SPI Engine peripheral. One FIFO for the command stream and one each for transmit and receive data. The driver translates a spi_message in a command stream and writes it to the peripheral which executes it asynchronously. This allows it to perform very precise timings which are required for some SPI slave devices to achieve maximum performance (e.g. analog-to-digital and digital-to-analog converters). The execution flow is synchronized to the host system by a special synchronize instruction which generates a interrupt. [1] https://wiki.analog.com/resources/fpga/peripherals/spi_engine Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/spi-axi-spi-engine.c | 591 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 600 insertions(+) create mode 100644 drivers/spi/spi-axi-spi-engine.c (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 7caf18cb3e5e..d84adceb9b89 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -83,6 +83,14 @@ config SPI_AU1550 If you say yes to this option, support will be included for the PSC SPI controller found on Au1550, Au1200 and Au1300 series. +config SPI_AXI_SPI_ENGINE + tristate "Analog Devices AXI SPI Engine controller" + depends on HAS_IOMEM + help + This enables support for the Analog Devices AXI SPI Engine SPI controller. + It is part of the SPI Engine framework that is used in some Analog Devices + reference designs for FPGAs. + config SPI_BCM2835 tristate "BCM2835 SPI controller" depends on GPIOLIB diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 8991ffce6e12..7ad880684a85 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_SPI_ALTERA) += spi-altera.o obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o obj-$(CONFIG_SPI_ATH79) += spi-ath79.o obj-$(CONFIG_SPI_AU1550) += spi-au1550.o +obj-$(CONFIG_SPI_AXI_SPI_ENGINE) += spi-axi-spi-engine.o obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o obj-$(CONFIG_SPI_BCM2835AUX) += spi-bcm2835aux.o obj-$(CONFIG_SPI_BCM53XX) += spi-bcm53xx.o diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c new file mode 100644 index 000000000000..c968ab210a51 --- /dev/null +++ b/drivers/spi/spi-axi-spi-engine.c @@ -0,0 +1,591 @@ +/* + * SPI-Engine SPI controller driver + * Copyright 2015 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define SPI_ENGINE_VERSION_MAJOR(x) ((x >> 16) & 0xff) +#define SPI_ENGINE_VERSION_MINOR(x) ((x >> 8) & 0xff) +#define SPI_ENGINE_VERSION_PATCH(x) (x & 0xff) + +#define SPI_ENGINE_REG_VERSION 0x00 + +#define SPI_ENGINE_REG_RESET 0x40 + +#define SPI_ENGINE_REG_INT_ENABLE 0x80 +#define SPI_ENGINE_REG_INT_PENDING 0x84 +#define SPI_ENGINE_REG_INT_SOURCE 0x88 + +#define SPI_ENGINE_REG_SYNC_ID 0xc0 + +#define SPI_ENGINE_REG_CMD_FIFO_ROOM 0xd0 +#define SPI_ENGINE_REG_SDO_FIFO_ROOM 0xd4 +#define SPI_ENGINE_REG_SDI_FIFO_LEVEL 0xd8 + +#define SPI_ENGINE_REG_CMD_FIFO 0xe0 +#define SPI_ENGINE_REG_SDO_DATA_FIFO 0xe4 +#define SPI_ENGINE_REG_SDI_DATA_FIFO 0xe8 +#define SPI_ENGINE_REG_SDI_DATA_FIFO_PEEK 0xec + +#define SPI_ENGINE_INT_CMD_ALMOST_EMPTY BIT(0) +#define SPI_ENGINE_INT_SDO_ALMOST_EMPTY BIT(1) +#define SPI_ENGINE_INT_SDI_ALMOST_FULL BIT(2) +#define SPI_ENGINE_INT_SYNC BIT(3) + +#define SPI_ENGINE_CONFIG_CPHA BIT(0) +#define SPI_ENGINE_CONFIG_CPOL BIT(1) +#define SPI_ENGINE_CONFIG_3WIRE BIT(2) + +#define SPI_ENGINE_INST_TRANSFER 0x0 +#define SPI_ENGINE_INST_ASSERT 0x1 +#define SPI_ENGINE_INST_WRITE 0x2 +#define SPI_ENGINE_INST_MISC 0x3 + +#define SPI_ENGINE_CMD_REG_CLK_DIV 0x0 +#define SPI_ENGINE_CMD_REG_CONFIG 0x1 + +#define SPI_ENGINE_MISC_SYNC 0x0 +#define SPI_ENGINE_MISC_SLEEP 0x1 + +#define SPI_ENGINE_TRANSFER_WRITE 0x1 +#define SPI_ENGINE_TRANSFER_READ 0x2 + +#define SPI_ENGINE_CMD(inst, arg1, arg2) \ + (((inst) << 12) | ((arg1) << 8) | (arg2)) + +#define SPI_ENGINE_CMD_TRANSFER(flags, n) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_TRANSFER, (flags), (n)) +#define SPI_ENGINE_CMD_ASSERT(delay, cs) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_ASSERT, (delay), (cs)) +#define SPI_ENGINE_CMD_WRITE(reg, val) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_WRITE, (reg), (val)) +#define SPI_ENGINE_CMD_SLEEP(delay) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, SPI_ENGINE_MISC_SLEEP, (delay)) +#define SPI_ENGINE_CMD_SYNC(id) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, SPI_ENGINE_MISC_SYNC, (id)) + +struct spi_engine_program { + unsigned int length; + uint16_t instructions[]; +}; + +struct spi_engine { + struct clk *clk; + struct clk *ref_clk; + + spinlock_t lock; + + void __iomem *base; + + struct spi_message *msg; + struct spi_engine_program *p; + unsigned cmd_length; + const uint16_t *cmd_buf; + + struct spi_transfer *tx_xfer; + unsigned int tx_length; + const uint8_t *tx_buf; + + struct spi_transfer *rx_xfer; + unsigned int rx_length; + uint8_t *rx_buf; + + unsigned int sync_id; + unsigned int completed_id; + + unsigned int int_enable; +}; + +static void spi_engine_program_add_cmd(struct spi_engine_program *p, + bool dry, uint16_t cmd) +{ + if (!dry) + p->instructions[p->length] = cmd; + p->length++; +} + +static unsigned int spi_engine_get_config(struct spi_device *spi) +{ + unsigned int config = 0; + + if (spi->mode & SPI_CPOL) + config |= SPI_ENGINE_CONFIG_CPOL; + if (spi->mode & SPI_CPHA) + config |= SPI_ENGINE_CONFIG_CPHA; + if (spi->mode & SPI_3WIRE) + config |= SPI_ENGINE_CONFIG_3WIRE; + + return config; +} + +static unsigned int spi_engine_get_clk_div(struct spi_engine *spi_engine, + struct spi_device *spi, struct spi_transfer *xfer) +{ + unsigned int clk_div; + + clk_div = DIV_ROUND_UP(clk_get_rate(spi_engine->ref_clk), + xfer->speed_hz * 2); + if (clk_div > 255) + clk_div = 255; + else if (clk_div > 0) + clk_div -= 1; + + return clk_div; +} + +static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry, + struct spi_transfer *xfer) +{ + unsigned int len = xfer->len; + + while (len) { + unsigned int n = min(len, 256U); + unsigned int flags = 0; + + if (xfer->tx_buf) + flags |= SPI_ENGINE_TRANSFER_WRITE; + if (xfer->rx_buf) + flags |= SPI_ENGINE_TRANSFER_READ; + + spi_engine_program_add_cmd(p, dry, + SPI_ENGINE_CMD_TRANSFER(flags, n - 1)); + len -= n; + } +} + +static void spi_engine_gen_sleep(struct spi_engine_program *p, bool dry, + struct spi_engine *spi_engine, unsigned int clk_div, unsigned int delay) +{ + unsigned int spi_clk = clk_get_rate(spi_engine->ref_clk); + unsigned int t; + + if (delay == 0) + return; + + t = DIV_ROUND_UP(delay * spi_clk, (clk_div + 1) * 2); + while (t) { + unsigned int n = min(t, 256U); + + spi_engine_program_add_cmd(p, dry, SPI_ENGINE_CMD_SLEEP(n - 1)); + t -= n; + } +} + +static void spi_engine_gen_cs(struct spi_engine_program *p, bool dry, + struct spi_device *spi, bool assert) +{ + unsigned int mask = 0xff; + + if (assert) + mask ^= BIT(spi->chip_select); + + spi_engine_program_add_cmd(p, dry, SPI_ENGINE_CMD_ASSERT(1, mask)); +} + +static int spi_engine_compile_message(struct spi_engine *spi_engine, + struct spi_message *msg, bool dry, struct spi_engine_program *p) +{ + struct spi_device *spi = msg->spi; + struct spi_transfer *xfer; + int clk_div, new_clk_div; + bool cs_change = true; + + clk_div = -1; + + spi_engine_program_add_cmd(p, dry, + SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_CONFIG, + spi_engine_get_config(spi))); + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + new_clk_div = spi_engine_get_clk_div(spi_engine, spi, xfer); + if (new_clk_div != clk_div) { + clk_div = new_clk_div; + spi_engine_program_add_cmd(p, dry, + SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_CLK_DIV, + clk_div)); + } + + if (cs_change) + spi_engine_gen_cs(p, dry, spi, true); + + spi_engine_gen_xfer(p, dry, xfer); + spi_engine_gen_sleep(p, dry, spi_engine, clk_div, + xfer->delay_usecs); + + cs_change = xfer->cs_change; + if (list_is_last(&xfer->transfer_list, &msg->transfers)) + cs_change = !cs_change; + + if (cs_change) + spi_engine_gen_cs(p, dry, spi, false); + } + + return 0; +} + +static void spi_engine_xfer_next(struct spi_engine *spi_engine, + struct spi_transfer **_xfer) +{ + struct spi_message *msg = spi_engine->msg; + struct spi_transfer *xfer = *_xfer; + + if (!xfer) { + xfer = list_first_entry(&msg->transfers, + struct spi_transfer, transfer_list); + } else if (list_is_last(&xfer->transfer_list, &msg->transfers)) { + xfer = NULL; + } else { + xfer = list_next_entry(xfer, transfer_list); + } + + *_xfer = xfer; +} + +static void spi_engine_tx_next(struct spi_engine *spi_engine) +{ + struct spi_transfer *xfer = spi_engine->tx_xfer; + + do { + spi_engine_xfer_next(spi_engine, &xfer); + } while (xfer && !xfer->tx_buf); + + spi_engine->tx_xfer = xfer; + if (xfer) { + spi_engine->tx_length = xfer->len; + spi_engine->tx_buf = xfer->tx_buf; + } else { + spi_engine->tx_buf = NULL; + } +} + +static void spi_engine_rx_next(struct spi_engine *spi_engine) +{ + struct spi_transfer *xfer = spi_engine->rx_xfer; + + do { + spi_engine_xfer_next(spi_engine, &xfer); + } while (xfer && !xfer->rx_buf); + + spi_engine->rx_xfer = xfer; + if (xfer) { + spi_engine->rx_length = xfer->len; + spi_engine->rx_buf = xfer->rx_buf; + } else { + spi_engine->rx_buf = NULL; + } +} + +static bool spi_engine_write_cmd_fifo(struct spi_engine *spi_engine) +{ + void __iomem *addr = spi_engine->base + SPI_ENGINE_REG_CMD_FIFO; + unsigned int n, m, i; + const uint16_t *buf; + + n = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_CMD_FIFO_ROOM); + while (n && spi_engine->cmd_length) { + m = min(n, spi_engine->cmd_length); + buf = spi_engine->cmd_buf; + for (i = 0; i < m; i++) + writel_relaxed(buf[i], addr); + spi_engine->cmd_buf += m; + spi_engine->cmd_length -= m; + n -= m; + } + + return spi_engine->cmd_length != 0; +} + +static bool spi_engine_write_tx_fifo(struct spi_engine *spi_engine) +{ + void __iomem *addr = spi_engine->base + SPI_ENGINE_REG_SDO_DATA_FIFO; + unsigned int n, m, i; + const uint8_t *buf; + + n = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_SDO_FIFO_ROOM); + while (n && spi_engine->tx_length) { + m = min(n, spi_engine->tx_length); + buf = spi_engine->tx_buf; + for (i = 0; i < m; i++) + writel_relaxed(buf[i], addr); + spi_engine->tx_buf += m; + spi_engine->tx_length -= m; + n -= m; + if (spi_engine->tx_length == 0) + spi_engine_tx_next(spi_engine); + } + + return spi_engine->tx_length != 0; +} + +static bool spi_engine_read_rx_fifo(struct spi_engine *spi_engine) +{ + void __iomem *addr = spi_engine->base + SPI_ENGINE_REG_SDI_DATA_FIFO; + unsigned int n, m, i; + uint8_t *buf; + + n = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_SDI_FIFO_LEVEL); + while (n && spi_engine->rx_length) { + m = min(n, spi_engine->rx_length); + buf = spi_engine->rx_buf; + for (i = 0; i < m; i++) + buf[i] = readl_relaxed(addr); + spi_engine->rx_buf += m; + spi_engine->rx_length -= m; + n -= m; + if (spi_engine->rx_length == 0) + spi_engine_rx_next(spi_engine); + } + + return spi_engine->rx_length != 0; +} + +static irqreturn_t spi_engine_irq(int irq, void *devid) +{ + struct spi_master *master = devid; + struct spi_engine *spi_engine = spi_master_get_devdata(master); + unsigned int disable_int = 0; + unsigned int pending; + + pending = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_INT_PENDING); + + if (pending & SPI_ENGINE_INT_SYNC) { + writel_relaxed(SPI_ENGINE_INT_SYNC, + spi_engine->base + SPI_ENGINE_REG_INT_PENDING); + spi_engine->completed_id = readl_relaxed( + spi_engine->base + SPI_ENGINE_REG_SYNC_ID); + } + + spin_lock(&spi_engine->lock); + + if (pending & SPI_ENGINE_INT_CMD_ALMOST_EMPTY) { + if (!spi_engine_write_cmd_fifo(spi_engine)) + disable_int |= SPI_ENGINE_INT_CMD_ALMOST_EMPTY; + } + + if (pending & SPI_ENGINE_INT_SDO_ALMOST_EMPTY) { + if (!spi_engine_write_tx_fifo(spi_engine)) + disable_int |= SPI_ENGINE_INT_SDO_ALMOST_EMPTY; + } + + if (pending & (SPI_ENGINE_INT_SDI_ALMOST_FULL | SPI_ENGINE_INT_SYNC)) { + if (!spi_engine_read_rx_fifo(spi_engine)) + disable_int |= SPI_ENGINE_INT_SDI_ALMOST_FULL; + } + + if (pending & SPI_ENGINE_INT_SYNC) { + if (spi_engine->msg && + spi_engine->completed_id == spi_engine->sync_id) { + struct spi_message *msg = spi_engine->msg; + + kfree(spi_engine->p); + msg->status = 0; + msg->actual_length = msg->frame_length; + spi_engine->msg = NULL; + spi_finalize_current_message(master); + disable_int |= SPI_ENGINE_INT_SYNC; + } + } + + if (disable_int) { + spi_engine->int_enable &= ~disable_int; + writel_relaxed(spi_engine->int_enable, + spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); + } + + spin_unlock(&spi_engine->lock); + + return IRQ_HANDLED; +} + +static int spi_engine_transfer_one_message(struct spi_master *master, + struct spi_message *msg) +{ + struct spi_engine_program p_dry, *p; + struct spi_engine *spi_engine = spi_master_get_devdata(master); + unsigned int int_enable = 0; + unsigned long flags; + size_t size; + + p_dry.length = 0; + spi_engine_compile_message(spi_engine, msg, true, &p_dry); + + size = sizeof(*p->instructions) * (p_dry.length + 1); + p = kzalloc(sizeof(*p) + size, GFP_KERNEL); + if (!p) + return -ENOMEM; + spi_engine_compile_message(spi_engine, msg, false, p); + + spin_lock_irqsave(&spi_engine->lock, flags); + spi_engine->sync_id = (spi_engine->sync_id + 1) & 0xff; + spi_engine_program_add_cmd(p, false, + SPI_ENGINE_CMD_SYNC(spi_engine->sync_id)); + + spi_engine->msg = msg; + spi_engine->p = p; + + spi_engine->cmd_buf = p->instructions; + spi_engine->cmd_length = p->length; + if (spi_engine_write_cmd_fifo(spi_engine)) + int_enable |= SPI_ENGINE_INT_CMD_ALMOST_EMPTY; + + spi_engine_tx_next(spi_engine); + if (spi_engine_write_tx_fifo(spi_engine)) + int_enable |= SPI_ENGINE_INT_SDO_ALMOST_EMPTY; + + spi_engine_rx_next(spi_engine); + if (spi_engine->rx_length != 0) + int_enable |= SPI_ENGINE_INT_SDI_ALMOST_FULL; + + int_enable |= SPI_ENGINE_INT_SYNC; + + writel_relaxed(int_enable, + spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); + spi_engine->int_enable = int_enable; + spin_unlock_irqrestore(&spi_engine->lock, flags); + + return 0; +} + +static int spi_engine_probe(struct platform_device *pdev) +{ + struct spi_engine *spi_engine; + struct spi_master *master; + unsigned int version; + struct resource *res; + int irq; + int ret; + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) + return -ENXIO; + + spi_engine = devm_kzalloc(&pdev->dev, sizeof(*spi_engine), GFP_KERNEL); + if (!spi_engine) + return -ENOMEM; + + master = spi_alloc_master(&pdev->dev, 0); + if (!master) + return -ENOMEM; + + spi_master_set_devdata(master, spi_engine); + + spin_lock_init(&spi_engine->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + spi_engine->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(spi_engine->base)) { + ret = PTR_ERR(spi_engine->base); + goto err_put_master; + } + + version = readl(spi_engine->base + SPI_ENGINE_REG_VERSION); + if (SPI_ENGINE_VERSION_MAJOR(version) != 1) { + dev_err(&pdev->dev, "Unsupported peripheral version %u.%u.%c\n", + SPI_ENGINE_VERSION_MAJOR(version), + SPI_ENGINE_VERSION_MINOR(version), + SPI_ENGINE_VERSION_PATCH(version)); + return -ENODEV; + } + + spi_engine->clk = devm_clk_get(&pdev->dev, "s_axi_aclk"); + if (IS_ERR(spi_engine->clk)) { + ret = PTR_ERR(spi_engine->clk); + goto err_put_master; + } + + spi_engine->ref_clk = devm_clk_get(&pdev->dev, "spi_clk"); + if (IS_ERR(spi_engine->ref_clk)) { + ret = PTR_ERR(spi_engine->ref_clk); + goto err_put_master; + } + + ret = clk_prepare_enable(spi_engine->clk); + if (ret) + goto err_put_master; + + ret = clk_prepare_enable(spi_engine->ref_clk); + if (ret) + goto err_clk_disable; + + writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_RESET); + writel_relaxed(0xff, spi_engine->base + SPI_ENGINE_REG_INT_PENDING); + writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); + + ret = request_irq(irq, spi_engine_irq, 0, pdev->name, master); + if (ret) + goto err_ref_clk_disable; + + master->dev.parent = &pdev->dev; + master->dev.of_node = pdev->dev.of_node; + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_3WIRE; + master->bits_per_word_mask = SPI_BPW_MASK(8); + master->max_speed_hz = clk_get_rate(spi_engine->ref_clk) / 2; + master->transfer_one_message = spi_engine_transfer_one_message; + master->num_chipselect = 8; + + ret = spi_register_master(master); + if (ret) + goto err_free_irq; + + platform_set_drvdata(pdev, master); + + return 0; +err_free_irq: + free_irq(irq, master); +err_ref_clk_disable: + clk_disable_unprepare(spi_engine->ref_clk); +err_clk_disable: + clk_disable_unprepare(spi_engine->clk); +err_put_master: + spi_master_put(master); + return ret; +} + +static int spi_engine_remove(struct platform_device *pdev) +{ + struct spi_master *master = platform_get_drvdata(pdev); + struct spi_engine *spi_engine = spi_master_get_devdata(master); + int irq = platform_get_irq(pdev, 0); + + spi_unregister_master(master); + + free_irq(irq, master); + + writel_relaxed(0xff, spi_engine->base + SPI_ENGINE_REG_INT_PENDING); + writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); + writel_relaxed(0x01, spi_engine->base + SPI_ENGINE_REG_RESET); + + clk_disable_unprepare(spi_engine->ref_clk); + clk_disable_unprepare(spi_engine->clk); + + return 0; +} + +static const struct of_device_id spi_engine_match_table[] = { + { .compatible = "adi,axi-spi-engine-1.00.a" }, + { }, +}; + +static struct platform_driver spi_engine_driver = { + .probe = spi_engine_probe, + .remove = spi_engine_remove, + .driver = { + .name = "spi-engine", + .of_match_table = spi_engine_match_table, + }, +}; +module_platform_driver(spi_engine_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("Analog Devices SPI engine peripheral driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 38c09961048b853afd9429c9b57685a1511bc857 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Fri, 5 Feb 2016 12:33:30 +0800 Subject: regulator: act8945a: add regulator driver for ACT8945A This patch adds new regulator driver to support ACT8945A MFD chip's regulators. The ACT8945A has three step-down DC/DC converters and four low-dropout regulators. Signed-off-by: Wenyou Yang Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 9 ++ drivers/regulator/Makefile | 1 + drivers/regulator/act8945a-regulator.c | 165 +++++++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+) create mode 100644 drivers/regulator/act8945a-regulator.c (limited to 'drivers') diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 8155e80dd3f8..74a6354eaefa 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -78,6 +78,15 @@ config REGULATOR_ACT8865 This driver controls a active-semi act8865 voltage output regulator via I2C bus. +config REGULATOR_ACT8945A + tristate "Active-semi ACT8945A voltage regulator" + depends on MFD_ACT8945A + help + This driver controls a active-semi ACT8945A voltage regulator + via I2C bus. The ACT8945A features three step-down DC/DC converters + and four low-dropout linear regulators, along with a ActivePath + battery charger. + config REGULATOR_AD5398 tristate "Analog Devices AD5398/AD5821 regulators" depends on I2C diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 980b1943fa81..348cfd727350 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o obj-$(CONFIG_REGULATOR_AB8500) += ab8500-ext.o ab8500.o obj-$(CONFIG_REGULATOR_ACT8865) += act8865-regulator.o +obj-$(CONFIG_REGULATOR_ACT8945A) += act8945a-regulator.o obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o diff --git a/drivers/regulator/act8945a-regulator.c b/drivers/regulator/act8945a-regulator.c new file mode 100644 index 000000000000..441864b9fece --- /dev/null +++ b/drivers/regulator/act8945a-regulator.c @@ -0,0 +1,165 @@ +/* + * Voltage regulation driver for active-semi ACT8945A PMIC + * + * Copyright (C) 2015 Atmel Corporation + * + * Author: Wenyou Yang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include + +/** + * ACT8945A Global Register Map. + */ +#define ACT8945A_SYS_MODE 0x00 +#define ACT8945A_SYS_CTRL 0x01 +#define ACT8945A_DCDC1_VSET1 0x20 +#define ACT8945A_DCDC1_VSET2 0x21 +#define ACT8945A_DCDC1_CTRL 0x22 +#define ACT8945A_DCDC2_VSET1 0x30 +#define ACT8945A_DCDC2_VSET2 0x31 +#define ACT8945A_DCDC2_CTRL 0x32 +#define ACT8945A_DCDC3_VSET1 0x40 +#define ACT8945A_DCDC3_VSET2 0x41 +#define ACT8945A_DCDC3_CTRL 0x42 +#define ACT8945A_LDO1_VSET 0x50 +#define ACT8945A_LDO1_CTRL 0x51 +#define ACT8945A_LDO2_VSET 0x54 +#define ACT8945A_LDO2_CTRL 0x55 +#define ACT8945A_LDO3_VSET 0x60 +#define ACT8945A_LDO3_CTRL 0x61 +#define ACT8945A_LDO4_VSET 0x64 +#define ACT8945A_LDO4_CTRL 0x65 + +/** + * Field Definitions. + */ +#define ACT8945A_ENA 0x80 /* ON - [7] */ +#define ACT8945A_VSEL_MASK 0x3F /* VSET - [5:0] */ + +/** + * ACT8945A Voltage Number + */ +#define ACT8945A_VOLTAGE_NUM 64 + +enum { + ACT8945A_ID_DCDC1, + ACT8945A_ID_DCDC2, + ACT8945A_ID_DCDC3, + ACT8945A_ID_LDO1, + ACT8945A_ID_LDO2, + ACT8945A_ID_LDO3, + ACT8945A_ID_LDO4, + ACT8945A_REG_NUM, +}; + +static const struct regulator_linear_range act8945a_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(600000, 0, 23, 25000), + REGULATOR_LINEAR_RANGE(1200000, 24, 47, 50000), + REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000), +}; + +static struct regulator_ops act8945a_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + +#define ACT89xx_REG(_name, _family, _id, _vsel_reg, _supply) \ + [_family##_ID_##_id] = { \ + .name = _name, \ + .supply_name = _supply, \ + .of_match = of_match_ptr("REG_"#_id), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = _family##_ID_##_id, \ + .type = REGULATOR_VOLTAGE, \ + .ops = &act8945a_ops, \ + .n_voltages = ACT8945A_VOLTAGE_NUM, \ + .linear_ranges = act8945a_voltage_ranges, \ + .n_linear_ranges = ARRAY_SIZE(act8945a_voltage_ranges), \ + .vsel_reg = _family##_##_id##_##_vsel_reg, \ + .vsel_mask = ACT8945A_VSEL_MASK, \ + .enable_reg = _family##_##_id##_CTRL, \ + .enable_mask = ACT8945A_ENA, \ + .owner = THIS_MODULE, \ + } + +static const struct regulator_desc act8945a_regulators[] = { + ACT89xx_REG("DCDC_REG1", ACT8945A, DCDC1, VSET1, "vp1"), + ACT89xx_REG("DCDC_REG2", ACT8945A, DCDC2, VSET1, "vp2"), + ACT89xx_REG("DCDC_REG3", ACT8945A, DCDC3, VSET1, "vp3"), + ACT89xx_REG("LDO_REG1", ACT8945A, LDO1, VSET, "inl45"), + ACT89xx_REG("LDO_REG2", ACT8945A, LDO2, VSET, "inl45"), + ACT89xx_REG("LDO_REG3", ACT8945A, LDO3, VSET, "inl67"), + ACT89xx_REG("LDO_REG4", ACT8945A, LDO4, VSET, "inl67"), +}; + +static const struct regulator_desc act8945a_alt_regulators[] = { + ACT89xx_REG("DCDC_REG1", ACT8945A, DCDC1, VSET2, "vp1"), + ACT89xx_REG("DCDC_REG2", ACT8945A, DCDC2, VSET2, "vp2"), + ACT89xx_REG("DCDC_REG3", ACT8945A, DCDC3, VSET2, "vp3"), + ACT89xx_REG("LDO_REG1", ACT8945A, LDO1, VSET, "inl45"), + ACT89xx_REG("LDO_REG2", ACT8945A, LDO2, VSET, "inl45"), + ACT89xx_REG("LDO_REG3", ACT8945A, LDO3, VSET, "inl67"), + ACT89xx_REG("LDO_REG4", ACT8945A, LDO4, VSET, "inl67"), +}; + +static int act8945a_pmic_probe(struct platform_device *pdev) +{ + struct regulator_config config = { }; + const struct regulator_desc *regulators; + struct regulator_dev *rdev; + int i, num_regulators; + bool voltage_select; + + voltage_select = of_property_read_bool(pdev->dev.parent->of_node, + "active-semi,vsel-high"); + + if (voltage_select) { + regulators = act8945a_alt_regulators; + num_regulators = ARRAY_SIZE(act8945a_alt_regulators); + } else { + regulators = act8945a_regulators; + num_regulators = ARRAY_SIZE(act8945a_regulators); + } + + config.dev = &pdev->dev; + config.dev->of_node = pdev->dev.parent->of_node; + for (i = 0; i < num_regulators; i++) { + rdev = devm_regulator_register(&pdev->dev, ®ulators[i], &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, + "failed to register %s regulator\n", + regulators[i].name); + return PTR_ERR(rdev); + } + } + + return 0; +} + +static struct platform_driver act8945a_pmic_driver = { + .driver = { + .name = "act8945a-regulator", + }, + .probe = act8945a_pmic_probe, +}; +module_platform_driver(act8945a_pmic_driver); + +MODULE_DESCRIPTION("Active-semi ACT8945A voltage regulator driver"); +MODULE_AUTHOR("Wenyou Yang "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 690f44badf2f44b8ec09098118b74f789f95e2c8 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 5 Feb 2016 19:42:18 +0100 Subject: regulator: lp872x: Remove warning about invalid DVS GPIO Some devices don't hook the DVS pin to a GPIO but to ground or VCC. In those cases, it is not a problem to have no DVS GPIO provided, as the current code will already switch to software-only DVS selection: When the DVS GPIO is invalid, lp872x_init_dvs jumps to the set_default_dvs_mode label, which instructs the chip not to use the DVS pin at all and do it all in software instead (by clearing the LP8720_EXT_DVS_M bit in the LP872X_GENERAL_CFG register). That is reflected later in the code, when setting the bucks (the DVS pin only applies to the bucks) by checking for the LP8720_EXT_DVS_M bit on the LP872X_GENERAL_CFG register (in lp872x_select_buck_vout_addr) to decide whether to use software or hardware DVS selection. Thus, there is no need to print a warning when the DVS GPIO is invalid. Signed-off-by: Paul Kocialkowski Signed-off-by: Mark Brown --- drivers/regulator/lp872x.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 19d758486553..21c49d871aba 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -738,10 +738,8 @@ static int lp872x_init_dvs(struct lp872x *lp) goto set_default_dvs_mode; gpio = dvs->gpio; - if (!gpio_is_valid(gpio)) { - dev_warn(lp->dev, "invalid gpio: %d\n", gpio); + if (!gpio_is_valid(gpio)) goto set_default_dvs_mode; - } pinstate = dvs->init_state; ret = devm_gpio_request_one(lp->dev, gpio, pinstate, "LP872X DVS"); -- cgit v1.2.3 From 7e6213f4345c3798b7fb7af41d221e2fd77ec6a6 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 5 Feb 2016 19:42:19 +0100 Subject: regulator: lp872x: Add enable GPIO pin support LP872x regulators are made active via the EN pin, which might be hooked to a GPIO. This adds support for driving the GPIO high when the driver is in use. Signed-off-by: Paul Kocialkowski Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/lp872x.txt | 1 + drivers/regulator/lp872x.c | 34 ++++++++++++++++++++++ include/linux/regulator/lp872x.h | 5 ++++ 3 files changed, 40 insertions(+) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/regulator/lp872x.txt b/Documentation/devicetree/bindings/regulator/lp872x.txt index 78183182dad9..ca58a68ffdf1 100644 --- a/Documentation/devicetree/bindings/regulator/lp872x.txt +++ b/Documentation/devicetree/bindings/regulator/lp872x.txt @@ -28,6 +28,7 @@ Optional properties: - ti,dvs-gpio: GPIO specifier for external DVS pin control of LP872x devices. - ti,dvs-vsel: DVS selector. 0 = SEL_V1, 1 = SEL_V2. - ti,dvs-state: initial DVS pin state. 0 = DVS_LOW, 1 = DVS_HIGH. + - enable-gpios: GPIO specifier for EN pin control of LP872x devices. Sub nodes for regulator_init_data LP8720 has maximum 6 nodes. (child name: ldo1 ~ 5 and buck) diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 21c49d871aba..38992112fd6e 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -757,6 +758,33 @@ set_default_dvs_mode: default_dvs_mode[lp->chipid]); } +static int lp872x_hw_enable(struct lp872x *lp) +{ + int ret, gpio; + + if (!lp->pdata) + return -EINVAL; + + gpio = lp->pdata->enable_gpio; + if (!gpio_is_valid(gpio)) + return 0; + + /* Always set enable GPIO high. */ + ret = devm_gpio_request_one(lp->dev, gpio, GPIOF_OUT_INIT_HIGH, "LP872X EN"); + if (ret) { + dev_err(lp->dev, "gpio request err: %d\n", ret); + return ret; + } + + /* Each chip has a different enable delay. */ + if (lp->chipid == LP8720) + usleep_range(LP8720_ENABLE_DELAY, 1.5 * LP8720_ENABLE_DELAY); + else + usleep_range(LP8725_ENABLE_DELAY, 1.5 * LP8725_ENABLE_DELAY); + + return 0; +} + static int lp872x_config(struct lp872x *lp) { struct lp872x_platform_data *pdata = lp->pdata; @@ -875,6 +903,8 @@ static struct lp872x_platform_data of_property_read_u8(np, "ti,dvs-state", &dvs_state); pdata->dvs->init_state = dvs_state ? DVS_HIGH : DVS_LOW; + pdata->enable_gpio = of_get_named_gpio(np, "enable-gpios", 0); + if (of_get_child_count(np) == 0) goto out; @@ -948,6 +978,10 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id) lp->chipid = id->driver_data; i2c_set_clientdata(cl, lp); + ret = lp872x_hw_enable(lp); + if (ret) + return ret; + ret = lp872x_config(lp); if (ret) return ret; diff --git a/include/linux/regulator/lp872x.h b/include/linux/regulator/lp872x.h index 132e05c46661..6029279f4eed 100644 --- a/include/linux/regulator/lp872x.h +++ b/include/linux/regulator/lp872x.h @@ -18,6 +18,9 @@ #define LP872X_MAX_REGULATORS 9 +#define LP8720_ENABLE_DELAY 200 +#define LP8725_ENABLE_DELAY 30000 + enum lp872x_regulator_id { LP8720_ID_BASE, LP8720_ID_LDO1 = LP8720_ID_BASE, @@ -79,12 +82,14 @@ struct lp872x_regulator_data { * @update_config : if LP872X_GENERAL_CFG register is updated, set true * @regulator_data : platform regulator id and init data * @dvs : dvs data for buck voltage control + * @enable_gpio : gpio pin number for enable control */ struct lp872x_platform_data { u8 general_config; bool update_config; struct lp872x_regulator_data regulator_data[LP872X_MAX_REGULATORS]; struct lp872x_dvs *dvs; + int enable_gpio; }; #endif -- cgit v1.2.3 From fd98d89698855f6cf5650c014e5d3fca38783c8b Mon Sep 17 00:00:00 2001 From: Selvin Xavier Date: Fri, 5 Feb 2016 20:06:37 +0530 Subject: RDMA/ocrdma: Initialize stats resources in the driver before ib device registration. In the latest kernel, process_mad hook of the driver can be invoked as soon as device is registered. In this hook, ocrdma driver is issuing a command to get the stats counters from the HW. This is triggering system crash since the statistics command resources are not allocated by the driver. Changing the sequence of initialization to avoid this crash. Signed-off-by: Selvin Xavier Signed-off-by: Doug Ledford --- drivers/infiniband/hw/ocrdma/ocrdma_main.c | 6 ++++++ drivers/infiniband/hw/ocrdma/ocrdma_stats.c | 14 ++++---------- drivers/infiniband/hw/ocrdma/ocrdma_stats.h | 2 ++ 3 files changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c index 573849354cb9..f38743018cb4 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c @@ -228,6 +228,11 @@ static int ocrdma_alloc_resources(struct ocrdma_dev *dev) ocrdma_alloc_pd_pool(dev); + if (!ocrdma_alloc_stats_resources(dev)) { + pr_err("%s: stats resource allocation failed\n", __func__); + goto alloc_err; + } + spin_lock_init(&dev->av_tbl.lock); spin_lock_init(&dev->flush_q_lock); return 0; @@ -238,6 +243,7 @@ alloc_err: static void ocrdma_free_resources(struct ocrdma_dev *dev) { + ocrdma_release_stats_resources(dev); kfree(dev->stag_arr); kfree(dev->qp_tbl); kfree(dev->cq_tbl); diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c index 86c303a620c1..fc02e86849ce 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c @@ -64,10 +64,11 @@ static int ocrdma_add_stat(char *start, char *pcur, return cpy_len; } -static bool ocrdma_alloc_stats_mem(struct ocrdma_dev *dev) +bool ocrdma_alloc_stats_resources(struct ocrdma_dev *dev) { struct stats_mem *mem = &dev->stats_mem; + mutex_init(&dev->stats_lock); /* Alloc mbox command mem*/ mem->size = max_t(u32, sizeof(struct ocrdma_rdma_stats_req), sizeof(struct ocrdma_rdma_stats_resp)); @@ -91,13 +92,14 @@ static bool ocrdma_alloc_stats_mem(struct ocrdma_dev *dev) return true; } -static void ocrdma_release_stats_mem(struct ocrdma_dev *dev) +void ocrdma_release_stats_resources(struct ocrdma_dev *dev) { struct stats_mem *mem = &dev->stats_mem; if (mem->va) dma_free_coherent(&dev->nic_info.pdev->dev, mem->size, mem->va, mem->pa); + mem->va = NULL; kfree(mem->debugfs_mem); } @@ -838,15 +840,9 @@ void ocrdma_add_port_stats(struct ocrdma_dev *dev) &dev->reset_stats, &ocrdma_dbg_ops)) goto err; - /* Now create dma_mem for stats mbx command */ - if (!ocrdma_alloc_stats_mem(dev)) - goto err; - - mutex_init(&dev->stats_lock); return; err: - ocrdma_release_stats_mem(dev); debugfs_remove_recursive(dev->dir); dev->dir = NULL; } @@ -856,8 +852,6 @@ void ocrdma_rem_port_stats(struct ocrdma_dev *dev) if (!dev->dir) return; debugfs_remove(dev->dir); - mutex_destroy(&dev->stats_lock); - ocrdma_release_stats_mem(dev); } void ocrdma_init_debugfs(void) diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_stats.h b/drivers/infiniband/hw/ocrdma/ocrdma_stats.h index c9e58d04c7b8..bba1fec4f11f 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_stats.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_stats.h @@ -65,6 +65,8 @@ enum OCRDMA_STATS_TYPE { void ocrdma_rem_debugfs(void); void ocrdma_init_debugfs(void); +bool ocrdma_alloc_stats_resources(struct ocrdma_dev *dev); +void ocrdma_release_stats_resources(struct ocrdma_dev *dev); void ocrdma_rem_port_stats(struct ocrdma_dev *dev); void ocrdma_add_port_stats(struct ocrdma_dev *dev); int ocrdma_pma_counters(struct ocrdma_dev *dev, -- cgit v1.2.3 From 7d82df1663e8a66961954258f3a99701f0126e73 Mon Sep 17 00:00:00 2001 From: Selvin Xavier Date: Fri, 5 Feb 2016 20:06:38 +0530 Subject: RDMA/ocrdma: populate max_sge_rd in device attributes max_sge_rd is used by some of the ULPs to calculate the maximum number of SGEs that can be used for RDMA READ. Populating this value in the response of query_device verb. Also, avoid checking the max_srq_sge while populating max_sge. Signed-off-by: Selvin Xavier Signed-off-by: Doug Ledford --- drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index d4c687b548d8..7cf1324ad081 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -125,8 +125,8 @@ int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr, IB_DEVICE_SYS_IMAGE_GUID | IB_DEVICE_LOCAL_DMA_LKEY | IB_DEVICE_MEM_MGT_EXTENSIONS; - attr->max_sge = min(dev->attr.max_send_sge, dev->attr.max_srq_sge); - attr->max_sge_rd = 0; + attr->max_sge = dev->attr.max_send_sge; + attr->max_sge_rd = attr->max_sge; attr->max_cq = dev->attr.max_cq; attr->max_cqe = dev->attr.max_cqe; attr->max_mr = dev->attr.max_mr; -- cgit v1.2.3 From aff3ead9fa25b2a472d1a894365f66b28e1e2787 Mon Sep 17 00:00:00 2001 From: Selvin Xavier Date: Fri, 5 Feb 2016 20:06:39 +0530 Subject: RDMA/ocrdma: Fix pkey_index returned by driver in rq work completion Currently returning the pkey value instead of pkey index. pkey index is always zero since ocrdma supports only default pkey. Signed-off-by: Selvin Xavier Signed-off-by: Doug Ledford --- drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index 7cf1324ad081..37620b4baafb 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -2726,8 +2726,7 @@ static int ocrdma_update_ud_rcqe(struct ib_wc *ibwc, struct ocrdma_cqe *cqe) OCRDMA_CQE_UD_STATUS_MASK) >> OCRDMA_CQE_UD_STATUS_SHIFT; ibwc->src_qp = le32_to_cpu(cqe->flags_status_srcqpn) & OCRDMA_CQE_SRCQP_MASK; - ibwc->pkey_index = le32_to_cpu(cqe->ud.rxlen_pkey) & - OCRDMA_CQE_PKEY_MASK; + ibwc->pkey_index = 0; ibwc->wc_flags = IB_WC_GRH; ibwc->byte_len = (le32_to_cpu(cqe->ud.rxlen_pkey) >> OCRDMA_CQE_UD_XFER_LEN_SHIFT); -- cgit v1.2.3 From 7425f410ca6cffe81400906286f80e8e15d9b301 Mon Sep 17 00:00:00 2001 From: Selvin Xavier Date: Fri, 5 Feb 2016 20:06:40 +0530 Subject: RDMA/ocrdma: Fixing ocrdma debugfs directory remove During the ocrdma device remove sequence, the debugfs directory tree of each ocrdma device needs to be removed. Use debugfs_remove_recursive instead of debugfs_remove. Signed-off-by: Selvin Xavier Signed-off-by: Doug Ledford --- drivers/infiniband/hw/ocrdma/ocrdma_stats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c index fc02e86849ce..255f774080a4 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c @@ -851,7 +851,7 @@ void ocrdma_rem_port_stats(struct ocrdma_dev *dev) { if (!dev->dir) return; - debugfs_remove(dev->dir); + debugfs_remove_recursive(dev->dir); } void ocrdma_init_debugfs(void) -- cgit v1.2.3 From 3487c65659088c8205d8ab726b45469912271bbd Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 29 Jan 2016 11:29:31 +0000 Subject: PCI: rcar: Remove PCI_PROBE_ONLY handling The PCIe rcar host driver is not used in system configurations requiring the PCI_PROBE_ONLY flag to be set to prevent resources assignment, therefore the driver code handling the flag can be removed from the kernel. Signed-off-by: Lorenzo Pieralisi Signed-off-by: Bjorn Helgaas Acked-by: Simon Horman Cc: Arnd Bergmann Cc: Phil Edworthy --- drivers/pci/host/pcie-rcar.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index 4edb5181f4e2..35092188039b 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c @@ -390,9 +390,7 @@ static int rcar_pcie_enable(struct rcar_pcie *pcie) rcar_pcie_setup(&res, pcie); - /* Do not reassign resources if probe only */ - if (!pci_has_flag(PCI_PROBE_ONLY)) - pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); + pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); if (IS_ENABLED(CONFIG_PCI_MSI)) bus = pci_scan_root_bus_msi(pcie->dev, pcie->root_bus_nr, @@ -408,13 +406,11 @@ static int rcar_pcie_enable(struct rcar_pcie *pcie) pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); - if (!pci_has_flag(PCI_PROBE_ONLY)) { - pci_bus_size_bridges(bus); - pci_bus_assign_resources(bus); + pci_bus_size_bridges(bus); + pci_bus_assign_resources(bus); - list_for_each_entry(child, &bus->children, node) - pcie_bus_configure_settings(child); - } + list_for_each_entry(child, &bus->children, node) + pcie_bus_configure_settings(child); pci_bus_add_devices(bus); -- cgit v1.2.3 From dbae40b76abef2f8a7e7bf1701f77df9e73def48 Mon Sep 17 00:00:00 2001 From: Yang Shi Date: Wed, 27 Jan 2016 09:32:05 -0800 Subject: PCI: layerscape: Add "fsl,ls2085a-pcie" compatible ID The Layerscape PCI host driver must recognize ls2085a compatible when using firmware with ls2085a compatible property, otherwise the PCI bus won't be detected even though ls2085a compatible is included by the dts. Signed-off-by: Yang Shi Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-layerscape.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c index 3923bed93c7e..c40d8b2ce330 100644 --- a/drivers/pci/host/pci-layerscape.c +++ b/drivers/pci/host/pci-layerscape.c @@ -203,6 +203,7 @@ static const struct of_device_id ls_pcie_of_match[] = { { .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata }, { .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata }, { .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata }, + { .compatible = "fsl,ls2085a-pcie", .data = &ls2080_drvdata }, { }, }; MODULE_DEVICE_TABLE(of, ls_pcie_of_match); -- cgit v1.2.3 From ab1a187bba5c4e5ed8aa6e7bb7dcd7cd7e065aef Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 27 Jan 2016 07:35:07 -0600 Subject: PCI: Check device_attach() return value always Previously we checked the device_attach() return value only when CONFIG_BUG=y. That caused this warning in builds where CONFIG_BUG is not set: drivers/pci/bus.c:237:6: warning: variable 'retval' set but not used [-Wunused-but-set-variable] Check the return value of device_attach() always and clean up after failure. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/pci/bus.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 89b3befc7155..f2187d491475 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -291,7 +291,12 @@ void pci_bus_add_device(struct pci_dev *dev) dev->match_driver = true; retval = device_attach(&dev->dev); - WARN_ON(retval < 0); + if (retval < 0) { + dev_warn(&dev->dev, "device attach failed (%d)\n", retval); + pci_proc_detach_device(dev); + pci_remove_sysfs_dev_files(dev); + return; + } dev->is_added = 1; } -- cgit v1.2.3 From 274008e89d78ded4324c7d81d9d106f62f5d5727 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Sat, 6 Feb 2016 00:13:29 +0530 Subject: drm/i915/bxt: Check BIOS RC6 setup before enabling RC6 RC6 setup is shared between BIOS and Driver. BIOS sets up subset of RC6 setup registers. If those are not setup Driver should not enable RC6. For implementing this, driver can check RC_CTRL0 and RC_CTRL1 values to know if BIOS has enabled HW/SW RC6. This will also enable user to control RC6 using BIOS settings alone. RC6 related instability can be avoided by disabling via BIOS settings till driver fixes it. v2: Had placed logic in gen8 function by mistake. Fixed it. Ensuring RPM is not enabled in case BIOS disabled RC6. v3: Need to disable RPM if RC6 is disabled due to BIOS settings. (Daniel) Runtime PM enabling happens before gen9_enable_rc6. Moved the updation of enable_rc6 parameter in intel_uncore_sanitize. v4: Added elaborate check for BIOS RC6 setup. Prepared check_pctx for bxt. (Imre) v5: Caching reserved stolen base and size in the driver private data. Reorganized RC6 setup check. Moved from gen9_enable_rc6 to intel_uncore_sanitize. (Imre) v6: Rebasing on the patch submitted by Imre that moves gem_init_stolen earlier in the load. v7: Removed PWRCTX_MAXCNT_VCSUNIT1 check as it applies to SKL. (Imre) v8: Fixed formatting and checkpatch issues. Fixed functional issue where RC6 ctx size check was missing. (Imre) Cc: Imre Deak Signed-off-by: Sagar Arun Kamble Signed-off-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/1454697809-22113-1-git-send-email-sagar.a.kamble@intel.com --- drivers/gpu/drm/i915/i915_gem_gtt.h | 2 ++ drivers/gpu/drm/i915/i915_gem_stolen.c | 3 ++ drivers/gpu/drm/i915/i915_reg.h | 11 +++++++ drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 53 ++++++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/intel_uncore.c | 2 ++ 6 files changed, 70 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index f520c90e5377..66a6da2396a2 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -342,6 +342,8 @@ struct i915_gtt { size_t stolen_size; /* Total size of stolen memory */ size_t stolen_usable_size; /* Total size minus BIOS reserved */ + size_t stolen_reserved_base; + size_t stolen_reserved_size; u64 mappable_end; /* End offset that we can CPU map */ struct io_mapping *mappable; /* Mapping to our CPU mappable region */ phys_addr_t mappable_base; /* PA of our GMADR */ diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index c384dc9c8a63..ba1a00d815d3 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -458,6 +458,9 @@ int i915_gem_init_stolen(struct drm_device *dev) return 0; } + dev_priv->gtt.stolen_reserved_base = reserved_base; + dev_priv->gtt.stolen_reserved_size = reserved_size; + /* It is possible for the reserved area to end before the end of stolen * memory, so just consider the start. */ reserved_total = stolen_top - reserved_base; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 6732fc139196..188ad5de020f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6785,6 +6785,16 @@ enum skl_disp_power_wells { #define VLV_PMWGICZ _MMIO(0x1300a4) +#define RC6_LOCATION _MMIO(0xD40) +#define RC6_CTX_IN_DRAM (1 << 0) +#define RC6_CTX_BASE _MMIO(0xD48) +#define RC6_CTX_BASE_MASK 0xFFFFFFF0 +#define PWRCTX_MAXCNT_RCSUNIT _MMIO(0x2054) +#define PWRCTX_MAXCNT_VCSUNIT0 _MMIO(0x12054) +#define PWRCTX_MAXCNT_BCSUNIT _MMIO(0x22054) +#define PWRCTX_MAXCNT_VECSUNIT _MMIO(0x1A054) +#define PWRCTX_MAXCNT_VCSUNIT1 _MMIO(0x1C054) +#define IDLE_TIME_MASK 0xFFFFF #define FORCEWAKE _MMIO(0xA18C) #define FORCEWAKE_VLV _MMIO(0x1300b0) #define FORCEWAKE_ACK_VLV _MMIO(0x1300b4) @@ -6923,6 +6933,7 @@ enum skl_disp_power_wells { #define GEN6_RPDEUC _MMIO(0xA084) #define GEN6_RPDEUCSW _MMIO(0xA088) #define GEN6_RC_STATE _MMIO(0xA094) +#define RC6_STATE (1 << 18) #define GEN6_RC1_WAKE_RATE_LIMIT _MMIO(0xA098) #define GEN6_RC6_WAKE_RATE_LIMIT _MMIO(0xA09C) #define GEN6_RC6pp_WAKE_RATE_LIMIT _MMIO(0xA0A0) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 93ba14a3bb76..1251a7ae4a6a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1566,6 +1566,7 @@ void skl_wm_get_hw_state(struct drm_device *dev); void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, struct skl_ddb_allocation *ddb /* out */); uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config); +int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6); /* intel_sdvo.c */ bool intel_sdvo_init(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3da7935c1665..379eabe093cb 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4562,12 +4562,62 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode) onoff(mode & GEN6_RC_CTL_RC6_ENABLE)); } -static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6) +static bool bxt_check_bios_rc6_setup(const struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + bool enable_rc6 = true; + unsigned long rc6_ctx_base; + + if (!(I915_READ(RC6_LOCATION) & RC6_CTX_IN_DRAM)) { + DRM_DEBUG_KMS("RC6 Base location not set properly.\n"); + enable_rc6 = false; + } + + /* + * The exact context size is not known for BXT, so assume a page size + * for this check. + */ + rc6_ctx_base = I915_READ(RC6_CTX_BASE) & RC6_CTX_BASE_MASK; + if (!((rc6_ctx_base >= dev_priv->gtt.stolen_reserved_base) && + (rc6_ctx_base + PAGE_SIZE <= dev_priv->gtt.stolen_reserved_base + + dev_priv->gtt.stolen_reserved_size))) { + DRM_DEBUG_KMS("RC6 Base address not as expected.\n"); + enable_rc6 = false; + } + + if (!(((I915_READ(PWRCTX_MAXCNT_RCSUNIT) & IDLE_TIME_MASK) > 1) && + ((I915_READ(PWRCTX_MAXCNT_VCSUNIT0) & IDLE_TIME_MASK) > 1) && + ((I915_READ(PWRCTX_MAXCNT_BCSUNIT) & IDLE_TIME_MASK) > 1) && + ((I915_READ(PWRCTX_MAXCNT_VECSUNIT) & IDLE_TIME_MASK) > 1))) { + DRM_DEBUG_KMS("Engine Idle wait time not set properly.\n"); + enable_rc6 = false; + } + + if (!(I915_READ(GEN6_RC_CONTROL) & (GEN6_RC_CTL_RC6_ENABLE | + GEN6_RC_CTL_HW_ENABLE)) && + ((I915_READ(GEN6_RC_CONTROL) & GEN6_RC_CTL_HW_ENABLE) || + !(I915_READ(GEN6_RC_STATE) & RC6_STATE))) { + DRM_DEBUG_KMS("HW/SW RC6 is not enabled by BIOS.\n"); + enable_rc6 = false; + } + + return enable_rc6; +} + +int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6) { /* No RC6 before Ironlake and code is gone for ilk. */ if (INTEL_INFO(dev)->gen < 6) return 0; + if (!enable_rc6) + return 0; + + if (IS_BROXTON(dev) && !bxt_check_bios_rc6_setup(dev)) { + DRM_INFO("RC6 disabled by BIOS\n"); + return 0; + } + /* Respect the kernel parameter if it is set */ if (enable_rc6 >= 0) { int mask; @@ -6057,7 +6107,6 @@ void intel_init_gt_powersave(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6); /* * RPM depends on RC6 to save restore the GT HW context, so make RC6 a * requirement. diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index bfa79e5c214e..436d8f2b8682 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -400,6 +400,8 @@ void intel_uncore_early_sanitize(struct drm_device *dev, bool restore_forcewake) void intel_uncore_sanitize(struct drm_device *dev) { + i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6); + /* BIOS often leaves RC6 enabled, but disable it for hw init */ intel_disable_gt_powersave(dev); } -- cgit v1.2.3 From 4e48fe4148698ffd3935800f4967362e80a7ae92 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 5 Feb 2016 14:57:12 -0600 Subject: PCI/PME: Remove redundant port lookup We've already looked up srv->port a few lines earlier, and there's no need to do it again. Remove the redundant lookup. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki suspend_level = PME_SUSPEND_WAKEUP; } if (!wakeup || ret) { - struct pci_dev *port = srv->port; - pcie_pme_interrupt_enable(port, false); pcie_clear_root_pme_status(port); data->suspend_level = PME_SUSPEND_NOIRQ; -- cgit v1.2.3 From 41ccebaecef50e56f822791a52b7bd9e9608e5e6 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 5 Feb 2016 14:57:19 -0600 Subject: PCI/PME: Restructure pcie_pme_suspend() to prevent compiler warning Previously we had this: if (wakeup) ret = enable_irq_wake(...); if (!wakeup || ret) ... "ret" is only evaluated when "wakeup" is true, and it is always initialized in that case, but gcc isn't smart enough to figure that out and warns: drivers/pci/pcie/pme.c:414:14: warning: 'ret' may be used uninitialized in this function [-Wmaybe-uninitialized] Restructure the code slightly to make it easier for gcc (and maybe for humans as well). Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki port; - bool wakeup; + bool wakeup, wake_irq_enabled = false; int ret; if (device_may_wakeup(&port->dev)) { @@ -409,9 +409,12 @@ static int pcie_pme_suspend(struct pcie_device *srv) spin_lock_irq(&data->lock); if (wakeup) { ret = enable_irq_wake(srv->irq); - data->suspend_level = PME_SUSPEND_WAKEUP; + if (ret == 0) { + data->suspend_level = PME_SUSPEND_WAKEUP; + wake_irq_enabled = true; + } } - if (!wakeup || ret) { + if (!wake_irq_enabled) { pcie_pme_interrupt_enable(port, false); pcie_clear_root_pme_status(port); data->suspend_level = PME_SUSPEND_NOIRQ; -- cgit v1.2.3 From 5bbe029ff7bc8ff82ef31d3480d68c95642a3c7a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 5 Feb 2016 14:57:47 -0600 Subject: PCI: Move pci_set_flags() from asm-generic/pci-bridge.h to linux/pci.h The PCI flag management constants and functions were previously declared in include/asm-generic/pci-bridge.h. But they are not specific to bridges, and arches did not include pci-bridge.h consistently. Move the following interfaces and related constants to include/linux/pci.h and remove pci-bridge.h: pci_set_flags() pci_add_flags() pci_clear_flags() pci_has_flag() This fixes these warnings when building for some arches: drivers/pci/host/pcie-designware.c:562:20: error: 'PCI_PROBE_ONLY' undeclared (first use in this function) drivers/pci/host/pcie-designware.c:562:7: error: implicit declaration of function 'pci_has_flag' [-Werror=implicit-function-declaration] Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 7 +++++ include/asm-generic/pci-bridge.h | 65 ---------------------------------------- include/linux/pci.h | 22 ++++++++++++++ 3 files changed, 29 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 6d7ab9bb0d5a..ead1ac1dc1e3 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1803,6 +1803,13 @@ static int only_one_child(struct pci_bus *bus) return 0; if (pci_pcie_type(parent) == PCI_EXP_TYPE_ROOT_PORT) return 1; + + /* + * PCIe downstream ports are bridges that normally lead to only a + * device 0, but if PCI_SCAN_ALL_PCIE_DEVS is set, scan all + * possible devices, not just device 0. See PCIe spec r3.0, + * sec 7.3.1. + */ if (parent->has_secondary_link && !pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS)) return 1; diff --git a/include/asm-generic/pci-bridge.h b/include/asm-generic/pci-bridge.h index 20db2e5a0a69..1b1d82f66d57 100644 --- a/include/asm-generic/pci-bridge.h +++ b/include/asm-generic/pci-bridge.h @@ -6,69 +6,4 @@ */ #ifndef _ASM_GENERIC_PCI_BRIDGE_H #define _ASM_GENERIC_PCI_BRIDGE_H - -#ifdef __KERNEL__ - -enum { - /* Force re-assigning all resources (ignore firmware - * setup completely) - */ - PCI_REASSIGN_ALL_RSRC = 0x00000001, - - /* Re-assign all bus numbers */ - PCI_REASSIGN_ALL_BUS = 0x00000002, - - /* Do not try to assign, just use existing setup */ - PCI_PROBE_ONLY = 0x00000004, - - /* Don't bother with ISA alignment unless the bridge has - * ISA forwarding enabled - */ - PCI_CAN_SKIP_ISA_ALIGN = 0x00000008, - - /* Enable domain numbers in /proc */ - PCI_ENABLE_PROC_DOMAINS = 0x00000010, - /* ... except for domain 0 */ - PCI_COMPAT_DOMAIN_0 = 0x00000020, - - /* PCIe downstream ports are bridges that normally lead to only a - * device 0, but if this is set, we scan all possible devices, not - * just device 0. - */ - PCI_SCAN_ALL_PCIE_DEVS = 0x00000040, -}; - -#ifdef CONFIG_PCI -extern unsigned int pci_flags; - -static inline void pci_set_flags(int flags) -{ - pci_flags = flags; -} - -static inline void pci_add_flags(int flags) -{ - pci_flags |= flags; -} - -static inline void pci_clear_flags(int flags) -{ - pci_flags &= ~flags; -} - -static inline int pci_has_flag(int flag) -{ - return pci_flags & flag; -} -#else -static inline void pci_set_flags(int flags) { } -static inline void pci_add_flags(int flags) { } -static inline void pci_clear_flags(int flags) { } -static inline int pci_has_flag(int flag) -{ - return 0; -} -#endif /* CONFIG_PCI */ - -#endif /* __KERNEL__ */ #endif /* _ASM_GENERIC_PCI_BRIDGE_H */ diff --git a/include/linux/pci.h b/include/linux/pci.h index 27df4a6585da..3d371c150753 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -746,9 +746,26 @@ struct pci_driver { .vendor = PCI_VENDOR_ID_##vend, .device = (dev), \ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, 0, 0 +enum { + PCI_REASSIGN_ALL_RSRC = 0x00000001, /* ignore firmware setup */ + PCI_REASSIGN_ALL_BUS = 0x00000002, /* reassign all bus numbers */ + PCI_PROBE_ONLY = 0x00000004, /* use existing setup */ + PCI_CAN_SKIP_ISA_ALIGN = 0x00000008, /* don't do ISA alignment */ + PCI_ENABLE_PROC_DOMAINS = 0x00000010, /* enable domains in /proc */ + PCI_COMPAT_DOMAIN_0 = 0x00000020, /* ... except domain 0 */ + PCI_SCAN_ALL_PCIE_DEVS = 0x00000040, /* scan all, not just dev 0 */ +}; + /* these external functions are only available when PCI support is enabled */ #ifdef CONFIG_PCI +extern unsigned int pci_flags; + +static inline void pci_set_flags(int flags) { pci_flags = flags; } +static inline void pci_add_flags(int flags) { pci_flags |= flags; } +static inline void pci_clear_flags(int flags) { pci_flags &= ~flags; } +static inline int pci_has_flag(int flag) { return pci_flags & flag; } + void pcie_bus_configure_settings(struct pci_bus *bus); enum pcie_bus_config_types { @@ -1405,6 +1422,11 @@ void pci_register_set_vga_state(arch_set_vga_state_t func); #else /* CONFIG_PCI is not enabled */ +static inline void pci_set_flags(int flags) { } +static inline void pci_add_flags(int flags) { } +static inline void pci_clear_flags(int flags) { } +static inline int pci_has_flag(int flag) { return 0; } + /* * If the system does not have PCI, clearly these return errors. Define * these as simple inline functions to avoid hair in drivers. -- cgit v1.2.3 From 5bd28338d681dcbde2c4bee4ebea0c4e0dfcd9e4 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 5 Feb 2016 14:57:54 -0600 Subject: PCI: Remove includes of empty asm-generic/pci-bridge.h include/asm-generic/pci-bridge.h is now empty, so remove every #include of it. Signed-off-by: Bjorn Helgaas Acked-by: Will Deacon (arm64) --- arch/alpha/include/asm/pci.h | 1 - arch/arm/include/asm/pci.h | 3 --- arch/arm64/include/asm/pci.h | 1 - arch/mips/include/asm/pci.h | 1 - arch/powerpc/include/asm/pci-bridge.h | 1 - arch/unicore32/include/asm/pci.h | 2 -- arch/x86/pci/common.c | 1 - drivers/of/of_pci.c | 1 - drivers/pci/pci.c | 1 - drivers/pci/probe.c | 1 - drivers/pci/setup-bus.c | 1 - 11 files changed, 14 deletions(-) (limited to 'drivers') diff --git a/arch/alpha/include/asm/pci.h b/arch/alpha/include/asm/pci.h index 98f2eeee8f68..75d8865d763d 100644 --- a/arch/alpha/include/asm/pci.h +++ b/arch/alpha/include/asm/pci.h @@ -7,7 +7,6 @@ #include #include #include -#include /* * The following structure is used to manage multiple PCI busses. diff --git a/arch/arm/include/asm/pci.h b/arch/arm/include/asm/pci.h index a5635444ca41..d7de19a77d51 100644 --- a/arch/arm/include/asm/pci.h +++ b/arch/arm/include/asm/pci.h @@ -3,8 +3,6 @@ #ifdef __KERNEL__ #include -#include - #include /* for pci_sys_data */ extern unsigned long pcibios_min_io; @@ -41,5 +39,4 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) } #endif /* __KERNEL__ */ - #endif diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h index b008a72f8bc0..f75b04e8d732 100644 --- a/arch/arm64/include/asm/pci.h +++ b/arch/arm64/include/asm/pci.h @@ -7,7 +7,6 @@ #include #include -#include #include #define PCIBIOS_MIN_IO 0x1000 diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index 98c31e5d9579..108d19376bb1 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h @@ -102,7 +102,6 @@ static inline void pci_resource_to_user(const struct pci_dev *dev, int bar, #include #include #include -#include struct pci_dev; diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 54843ca5fa2b..78968c1ff931 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -10,7 +10,6 @@ #include #include #include -#include struct device_node; diff --git a/arch/unicore32/include/asm/pci.h b/arch/unicore32/include/asm/pci.h index 38b3f3785c3c..eb9dccecb338 100644 --- a/arch/unicore32/include/asm/pci.h +++ b/arch/unicore32/include/asm/pci.h @@ -14,7 +14,6 @@ #ifdef __KERNEL__ #include -#include #include #include /* for PCIBIOS_MIN_* */ @@ -23,5 +22,4 @@ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine); #endif /* __KERNEL__ */ - #endif diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 2879efc73a96..b4a9f23d77d9 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c index b1449f71601c..13f4fed38048 100644 --- a/drivers/of/of_pci.c +++ b/drivers/of/of_pci.c @@ -5,7 +5,6 @@ #include #include #include -#include static inline int __of_pci_pci_compare(struct device_node *node, unsigned int data) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 602eb4223510..64c0a1215f84 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include "pci.h" diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index ead1ac1dc1e3..5eb378fbe849 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -15,7 +15,6 @@ #include #include #include -#include #include "pci.h" #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 7796d0a5befa..55641a39a3e9 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -25,7 +25,6 @@ #include #include #include -#include #include "pci.h" unsigned int pci_flags; -- cgit v1.2.3 From 952bbcb0781bd1341f6a9f5c96fc32737392c04a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 5 Feb 2016 14:58:12 -0600 Subject: PCI: Remove includes of asm/pci-bridge.h Drivers should include asm/pci-bridge.h only when they need the arch- specific things provided there. Outside of the arch/ directories, the only drivers that actually need things provided by asm/pci-bridge.h are the powerpc RPA hotplug drivers in drivers/pci/hotplug/rpa*. Remove the includes of asm/pci-bridge.h from the other drivers, adding an include of linux/pci.h if necessary. Signed-off-by: Bjorn Helgaas --- drivers/ata/pata_macio.c | 2 +- drivers/char/agp/uninorth-agp.c | 1 - drivers/gpu/drm/radeon/radeon_combios.c | 1 - drivers/ide/pdc202xx_new.c | 1 - drivers/ide/pmac.c | 1 - drivers/macintosh/macio_asic.c | 1 - drivers/misc/cxl/pci.c | 1 - drivers/net/ethernet/sun/sungem.c | 1 - drivers/net/ethernet/toshiba/spider_net.c | 1 - drivers/scsi/mac53c94.c | 2 +- drivers/scsi/mesh.c | 2 +- drivers/usb/core/hcd-pci.c | 1 - drivers/video/fbdev/aty/aty128fb.c | 1 - drivers/video/fbdev/aty/radeon_base.c | 1 - drivers/video/fbdev/imsttfb.c | 1 - drivers/video/fbdev/matrox/matroxfb_base.h | 1 - drivers/video/fbdev/offb.c | 4 ---- sound/ppc/pmac.c | 1 - 18 files changed, 3 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c index e3d4b059fcd1..e347e7acd8ed 100644 --- a/drivers/ata/pata_macio.c +++ b/drivers/ata/pata_macio.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 05755441250c..fdced547ad59 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include "agp.h" diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index a9b01bcf7d0a..432480ff9d22 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -34,7 +34,6 @@ #include #include #include -#include #endif /* CONFIG_PPC_PMAC */ /* from radeon_legacy_encoder.c */ diff --git a/drivers/ide/pdc202xx_new.c b/drivers/ide/pdc202xx_new.c index 9ad014a7afc7..b33646be699c 100644 --- a/drivers/ide/pdc202xx_new.c +++ b/drivers/ide/pdc202xx_new.c @@ -28,7 +28,6 @@ #ifdef CONFIG_PPC_PMAC #include -#include #endif #define DRV_NAME "pdc202xx_new" diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c index 96a345248224..7f0434f7e486 100644 --- a/drivers/ide/pmac.c +++ b/drivers/ide/pmac.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 4f12c6f01fe7..b6819f0fc608 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -31,7 +31,6 @@ #include #include #include -#include #undef DEBUG diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index 4c1903f781fc..a21403238a4a 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -19,7 +19,6 @@ #include #include #include -#include /* for struct pci_controller */ #include #include diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c index e23a642357e7..2437227712dc 100644 --- a/drivers/net/ethernet/sun/sungem.c +++ b/drivers/net/ethernet/sun/sungem.c @@ -51,7 +51,6 @@ #endif #ifdef CONFIG_PPC_PMAC -#include #include #include #include diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c index 3c54a2cae5df..67610270d171 100644 --- a/drivers/net/ethernet/toshiba/spider_net.c +++ b/drivers/net/ethernet/toshiba/spider_net.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include "spider_net.h" diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c index 141226631429..a6682c508c4c 100644 --- a/drivers/scsi/mac53c94.c +++ b/drivers/scsi/mac53c94.c @@ -18,11 +18,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index 555367f00228..1753e42826dd 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,6 @@ #include #include #include -#include #include #include diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 9eb1cff28bd4..c3640f8a8fb3 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -28,7 +28,6 @@ #ifdef CONFIG_PPC_PMAC #include #include -#include #include #endif diff --git a/drivers/video/fbdev/aty/aty128fb.c b/drivers/video/fbdev/aty/aty128fb.c index c42ce2fdfd44..0a4626886b00 100644 --- a/drivers/video/fbdev/aty/aty128fb.c +++ b/drivers/video/fbdev/aty/aty128fb.c @@ -68,7 +68,6 @@ #include #include #include -#include #include "../macmodes.h" #endif diff --git a/drivers/video/fbdev/aty/radeon_base.c b/drivers/video/fbdev/aty/radeon_base.c index ce0b1d05a388..218339a4edaa 100644 --- a/drivers/video/fbdev/aty/radeon_base.c +++ b/drivers/video/fbdev/aty/radeon_base.c @@ -76,7 +76,6 @@ #ifdef CONFIG_PPC -#include #include "../macmodes.h" #ifdef CONFIG_BOOTX_TEXT diff --git a/drivers/video/fbdev/imsttfb.c b/drivers/video/fbdev/imsttfb.c index 9b167f7ef6c6..4363c64d74e8 100644 --- a/drivers/video/fbdev/imsttfb.c +++ b/drivers/video/fbdev/imsttfb.c @@ -33,7 +33,6 @@ #if defined(CONFIG_PPC) #include #include -#include #include "macmodes.h" #endif diff --git a/drivers/video/fbdev/matrox/matroxfb_base.h b/drivers/video/fbdev/matrox/matroxfb_base.h index 09b02cd1eb0e..7a90ea2c4613 100644 --- a/drivers/video/fbdev/matrox/matroxfb_base.h +++ b/drivers/video/fbdev/matrox/matroxfb_base.h @@ -47,7 +47,6 @@ #if defined(CONFIG_PPC_PMAC) #include -#include #include "../macmodes.h" #endif diff --git a/drivers/video/fbdev/offb.c b/drivers/video/fbdev/offb.c index 43a0a52fc527..fb60a8f0cc94 100644 --- a/drivers/video/fbdev/offb.c +++ b/drivers/video/fbdev/offb.c @@ -28,10 +28,6 @@ #include #include -#ifdef CONFIG_PPC64 -#include -#endif - #ifdef CONFIG_PPC32 #include #endif diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 0095a80a997f..a5843fc5ff20 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -34,7 +34,6 @@ #include "pmac.h" #include #include -#include /* fixed frequency table for awacs, screamer, burgundy, DACA (44100 max) */ -- cgit v1.2.3 From 1300568ac129a83f321fdb74e397942f583c8321 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 5 Feb 2016 23:47:13 +0100 Subject: pinctrl: stm32: fix compile error and modernize - Fix the dev->parent assignment compile error - Use gpiochip_get_data() to get the data pointer for the banks Cc: Maxime Coquelin Cc: Patrice Chotard Signed-off-by: Linus Walleij --- drivers/pinctrl/stm32/pinctrl-stm32.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index d25d4a064bad..9a08222ecb72 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -6,7 +6,7 @@ * Heavily based on Mediatek's pinctrl driver */ #include -#include +#include #include #include #include @@ -46,9 +46,6 @@ #define gpio_range_to_bank(chip) \ container_of(chip, struct stm32_gpio_bank, range) -#define gpio_chip_to_bank(chip) \ - container_of(chip, struct stm32_gpio_bank, gpio_chip) - static const char * const stm32_gpio_functions[] = { "gpio", "af0", "af1", "af2", "af3", "af4", @@ -144,7 +141,7 @@ static void stm32_gpio_free(struct gpio_chip *chip, unsigned offset) static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); + struct stm32_gpio_bank *bank = gpiochip_get_data(chip); int ret; clk_enable(bank->clk); @@ -158,7 +155,7 @@ static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset) static void stm32_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); + struct stm32_gpio_bank *bank = gpiochip_get_data(chip); __stm32_gpio_set(bank, offset, value); } @@ -171,7 +168,7 @@ static int stm32_gpio_direction_input(struct gpio_chip *chip, unsigned offset) static int stm32_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { - struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); + struct stm32_gpio_bank *bank = gpiochip_get_data(chip); __stm32_gpio_set(bank, offset, value); pinctrl_gpio_direction_output(chip->base + offset); @@ -689,7 +686,7 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, bank->gpio_chip.base = bank_nr * STM32_GPIO_PINS_PER_BANK; bank->gpio_chip.ngpio = npins; bank->gpio_chip.of_node = np; - bank->gpio_chip.dev = dev; + bank->gpio_chip.parent = dev; spin_lock_init(&bank->lock); of_property_read_string(np, "st,bank-name", &range->name); @@ -699,7 +696,7 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, range->pin_base = range->base = range->id * STM32_GPIO_PINS_PER_BANK; range->npins = bank->gpio_chip.ngpio; range->gc = &bank->gpio_chip; - err = gpiochip_add(&bank->gpio_chip); + err = gpiochip_add_data(&bank->gpio_chip, bank); if (err) { dev_err(dev, "Failed to add gpiochip(%d)!\n", bank_nr); return err; -- cgit v1.2.3 From 2ba384e6c3810733e14e183dedc3406f402a686f Mon Sep 17 00:00:00 2001 From: Joshua Henderson Date: Mon, 1 Feb 2016 15:48:30 -0700 Subject: pinctrl: pinctrl-pic32: Add PIC32 pin control driver Add a driver for the pin controller present on the Microchip PIC32 including the specific variant PIC32MZDA. This driver provides pinmux and pinconfig operations as well as GPIO and IRQ chips for the GPIO banks. Signed-off-by: Joshua Henderson Cc: Ralf Baechle Cc: Linus Walleij Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 17 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-pic32.c | 2312 +++++++++++++++++++++++++++++++++++++++ drivers/pinctrl/pinctrl-pic32.h | 141 +++ 4 files changed, 2471 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-pic32.c create mode 100644 drivers/pinctrl/pinctrl-pic32.h (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 6ba67a619062..a4c07394e313 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -207,6 +207,23 @@ config PINCTRL_PALMAS open drain configuration for the Palmas series devices like TPS65913, TPS80036 etc. +config PINCTRL_PIC32 + bool "Microchip PIC32 pin controller driver" + depends on OF + depends on MACH_PIC32 + select PINMUX + select GENERIC_PINCONF + select GPIOLIB_IRQCHIP + select OF_GPIO + help + This is the pin controller and gpio driver for Microchip PIC32 + microcontrollers. This option is selected automatically when specific + machine and arch are selected to build. + +config PINCTRL_PIC32MZDA + def_bool y if PIC32MZDA + select PINCTRL_PIC32 + config PINCTRL_ZYNQ bool "Pinctrl driver for Xilinx Zynq" depends on ARCH_ZYNQ diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index e4e673e2a448..8adc235e1a96 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_PINCTRL_DIGICOLOR) += pinctrl-digicolor.o obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o obj-$(CONFIG_PINCTRL_MESON) += meson/ obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o +obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o diff --git a/drivers/pinctrl/pinctrl-pic32.c b/drivers/pinctrl/pinctrl-pic32.c new file mode 100644 index 000000000000..0b07d4bdab95 --- /dev/null +++ b/drivers/pinctrl/pinctrl-pic32.c @@ -0,0 +1,2312 @@ +/* + * PIC32 pinctrl driver + * + * Joshua Henderson, + * Copyright (C) 2015 Microchip Technology Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "pinctrl-utils.h" +#include "pinctrl-pic32.h" + +#define PINS_PER_BANK 16 + +#define PIC32_CNCON_EDGE 11 +#define PIC32_CNCON_ON 15 + +#define PIN_CONFIG_MICROCHIP_DIGITAL (PIN_CONFIG_END + 1) +#define PIN_CONFIG_MICROCHIP_ANALOG (PIN_CONFIG_END + 2) + +static const struct pinconf_generic_params pic32_mpp_bindings[] = { + {"microchip,digital", PIN_CONFIG_MICROCHIP_DIGITAL, 0}, + {"microchip,analog", PIN_CONFIG_MICROCHIP_ANALOG, 0}, +}; + +#define GPIO_BANK_START(bank) ((bank) * PINS_PER_BANK) + +struct pic32_function { + const char *name; + const char * const *groups; + unsigned int ngroups; +}; + +struct pic32_pin_group { + const char *name; + unsigned int pin; + struct pic32_desc_function *functions; +}; + +struct pic32_desc_function { + const char *name; + u32 muxreg; + u32 muxval; +}; + +struct pic32_gpio_bank { + void __iomem *reg_base; + struct gpio_chip gpio_chip; + struct irq_chip irq_chip; + struct clk *clk; +}; + +struct pic32_pinctrl { + void __iomem *reg_base; + struct device *dev; + struct pinctrl_dev *pctldev; + const struct pinctrl_pin_desc *pins; + unsigned int npins; + const struct pic32_function *functions; + unsigned int nfunctions; + const struct pic32_pin_group *groups; + unsigned int ngroups; + struct pic32_gpio_bank *gpio_banks; + unsigned int nbanks; + struct clk *clk; +}; + +static const struct pinctrl_pin_desc pic32_pins[] = { + PINCTRL_PIN(0, "A0"), + PINCTRL_PIN(1, "A1"), + PINCTRL_PIN(2, "A2"), + PINCTRL_PIN(3, "A3"), + PINCTRL_PIN(4, "A4"), + PINCTRL_PIN(5, "A5"), + PINCTRL_PIN(6, "A6"), + PINCTRL_PIN(7, "A7"), + PINCTRL_PIN(8, "A8"), + PINCTRL_PIN(9, "A9"), + PINCTRL_PIN(10, "A10"), + PINCTRL_PIN(11, "A11"), + PINCTRL_PIN(12, "A12"), + PINCTRL_PIN(13, "A13"), + PINCTRL_PIN(14, "A14"), + PINCTRL_PIN(15, "A15"), + PINCTRL_PIN(16, "B0"), + PINCTRL_PIN(17, "B1"), + PINCTRL_PIN(18, "B2"), + PINCTRL_PIN(19, "B3"), + PINCTRL_PIN(20, "B4"), + PINCTRL_PIN(21, "B5"), + PINCTRL_PIN(22, "B6"), + PINCTRL_PIN(23, "B7"), + PINCTRL_PIN(24, "B8"), + PINCTRL_PIN(25, "B9"), + PINCTRL_PIN(26, "B10"), + PINCTRL_PIN(27, "B11"), + PINCTRL_PIN(28, "B12"), + PINCTRL_PIN(29, "B13"), + PINCTRL_PIN(30, "B14"), + PINCTRL_PIN(31, "B15"), + PINCTRL_PIN(33, "C1"), + PINCTRL_PIN(34, "C2"), + PINCTRL_PIN(35, "C3"), + PINCTRL_PIN(36, "C4"), + PINCTRL_PIN(44, "C12"), + PINCTRL_PIN(45, "C13"), + PINCTRL_PIN(46, "C14"), + PINCTRL_PIN(47, "C15"), + PINCTRL_PIN(48, "D0"), + PINCTRL_PIN(49, "D1"), + PINCTRL_PIN(50, "D2"), + PINCTRL_PIN(51, "D3"), + PINCTRL_PIN(52, "D4"), + PINCTRL_PIN(53, "D5"), + PINCTRL_PIN(54, "D6"), + PINCTRL_PIN(55, "D7"), + PINCTRL_PIN(57, "D9"), + PINCTRL_PIN(58, "D10"), + PINCTRL_PIN(59, "D11"), + PINCTRL_PIN(60, "D12"), + PINCTRL_PIN(61, "D13"), + PINCTRL_PIN(62, "D14"), + PINCTRL_PIN(63, "D15"), + PINCTRL_PIN(64, "E0"), + PINCTRL_PIN(65, "E1"), + PINCTRL_PIN(66, "E2"), + PINCTRL_PIN(67, "E3"), + PINCTRL_PIN(68, "E4"), + PINCTRL_PIN(69, "E5"), + PINCTRL_PIN(70, "E6"), + PINCTRL_PIN(71, "E7"), + PINCTRL_PIN(72, "E8"), + PINCTRL_PIN(73, "E9"), + PINCTRL_PIN(80, "F0"), + PINCTRL_PIN(81, "F1"), + PINCTRL_PIN(82, "F2"), + PINCTRL_PIN(83, "F3"), + PINCTRL_PIN(84, "F4"), + PINCTRL_PIN(85, "F5"), + PINCTRL_PIN(88, "F8"), + PINCTRL_PIN(92, "F12"), + PINCTRL_PIN(93, "F13"), + PINCTRL_PIN(96, "G0"), + PINCTRL_PIN(97, "G1"), + PINCTRL_PIN(102, "G6"), + PINCTRL_PIN(103, "G7"), + PINCTRL_PIN(104, "G8"), + PINCTRL_PIN(105, "G9"), + PINCTRL_PIN(108, "G12"), + PINCTRL_PIN(109, "G13"), + PINCTRL_PIN(110, "G14"), + PINCTRL_PIN(111, "G15"), + PINCTRL_PIN(112, "H0"), + PINCTRL_PIN(113, "H1"), + PINCTRL_PIN(114, "H2"), + PINCTRL_PIN(115, "H3"), + PINCTRL_PIN(116, "H4"), + PINCTRL_PIN(117, "H5"), + PINCTRL_PIN(118, "H6"), + PINCTRL_PIN(119, "H7"), + PINCTRL_PIN(120, "H8"), + PINCTRL_PIN(121, "H9"), + PINCTRL_PIN(122, "H10"), + PINCTRL_PIN(123, "H11"), + PINCTRL_PIN(124, "H12"), + PINCTRL_PIN(125, "H13"), + PINCTRL_PIN(126, "H14"), + PINCTRL_PIN(127, "H15"), + PINCTRL_PIN(128, "J0"), + PINCTRL_PIN(129, "J1"), + PINCTRL_PIN(130, "J2"), + PINCTRL_PIN(131, "J3"), + PINCTRL_PIN(132, "J4"), + PINCTRL_PIN(133, "J5"), + PINCTRL_PIN(134, "J6"), + PINCTRL_PIN(135, "J7"), + PINCTRL_PIN(136, "J8"), + PINCTRL_PIN(137, "J9"), + PINCTRL_PIN(138, "J10"), + PINCTRL_PIN(139, "J11"), + PINCTRL_PIN(140, "J12"), + PINCTRL_PIN(141, "J13"), + PINCTRL_PIN(142, "J14"), + PINCTRL_PIN(143, "J15"), + PINCTRL_PIN(144, "K0"), + PINCTRL_PIN(145, "K1"), + PINCTRL_PIN(146, "K2"), + PINCTRL_PIN(147, "K3"), + PINCTRL_PIN(148, "K4"), + PINCTRL_PIN(149, "K5"), + PINCTRL_PIN(150, "K6"), + PINCTRL_PIN(151, "K7"), +}; + +static const char * const pic32_input0_group[] = { + "D2", "G8", "F4", "F1", "B9", "B10", "C14", "B5", + "C1", "D14", "G1", "A14", "D6", +}; + +static const char * const pic32_input1_group[] = { + "D3", "G7", "F5", "D11", "F0", "B1", "E5", "C13", + "B3", "C4", "G0", "A15", "D7", +}; + +static const char * const pic32_input2_group[] = { + "D9", "G6", "B8", "B15", "D4", "B0", "E3", "B7", + "F12", "D12", "F8", "C3", "E9", +}; + +static const char * const pic32_input3_group[] = { + "G9", "B14", "D0", "B6", "D5", "B2", "F3", "F13", + "F2", "C2", "E8", +}; + +static const char * const pic32_output0_group[] = { + "D2", "G8", "F4", "D10", "F1", "B9", "B10", "C14", + "B5", "C1", "D14", "G1", "A14", "D6", +}; + +static const char * const pic32_output0_1_group[] = { + "D2", "G8", "F4", "D10", "F1", "B9", "B10", "C14", + "B5", "C1", "D14", "G1", "A14", "D6", + "D3", "G7", "F5", "D11", "F0", "B1", "E5", "C13", + "B3", "C4", "D15", "G0", "A15", "D7", +}; + +static const char *const pic32_output1_group[] = { + "D3", "G7", "F5", "D11", "F0", "B1", "E5", "C13", + "B3", "C4", "D15", "G0", "A15", "D7", +}; + +static const char *const pic32_output1_3_group[] = { + "D3", "G7", "F5", "D11", "F0", "B1", "E5", "C13", + "B3", "C4", "D15", "G0", "A15", "D7", + "G9", "B14", "D0", "B6", "D5", "B2", "F3", "F13", + "C2", "E8", "F2", +}; + +static const char * const pic32_output2_group[] = { + "D9", "G6", "B8", "B15", "D4", "B0", "E3", "B7", + "F12", "D12", "F8", "C3", "E9", +}; + +static const char * const pic32_output2_3_group[] = { + "D9", "G6", "B8", "B15", "D4", "B0", "E3", "B7", + "F12", "D12", "F8", "C3", "E9", + "G9", "B14", "D0", "B6", "D5", "B2", "F3", "F13", + "C2", "E8", "F2", +}; + +static const char * const pic32_output3_group[] = { + "G9", "B14", "D0", "B6", "D5", "B2", "F3", "F13", + "C2", "E8", "F2", +}; + +#define FUNCTION(_name, _gr) \ + { \ + .name = #_name, \ + .groups = pic32_##_gr##_group, \ + .ngroups = ARRAY_SIZE(pic32_##_gr##_group), \ + } + +static const struct pic32_function pic32_functions[] = { + FUNCTION(INT3, input0), + FUNCTION(T2CK, input0), + FUNCTION(T6CK, input0), + FUNCTION(IC3, input0), + FUNCTION(IC7, input0), + FUNCTION(U1RX, input0), + FUNCTION(U2CTS, input0), + FUNCTION(U5RX, input0), + FUNCTION(U6CTS, input0), + FUNCTION(SDI1, input0), + FUNCTION(SDI3, input0), + FUNCTION(SDI5, input0), + FUNCTION(SS6IN, input0), + FUNCTION(REFCLKI1, input0), + FUNCTION(INT4, input1), + FUNCTION(T5CK, input1), + FUNCTION(T7CK, input1), + FUNCTION(IC4, input1), + FUNCTION(IC8, input1), + FUNCTION(U3RX, input1), + FUNCTION(U4CTS, input1), + FUNCTION(SDI2, input1), + FUNCTION(SDI4, input1), + FUNCTION(C1RX, input1), + FUNCTION(REFCLKI4, input1), + FUNCTION(INT2, input2), + FUNCTION(T3CK, input2), + FUNCTION(T8CK, input2), + FUNCTION(IC2, input2), + FUNCTION(IC5, input2), + FUNCTION(IC9, input2), + FUNCTION(U1CTS, input2), + FUNCTION(U2RX, input2), + FUNCTION(U5CTS, input2), + FUNCTION(SS1IN, input2), + FUNCTION(SS3IN, input2), + FUNCTION(SS4IN, input2), + FUNCTION(SS5IN, input2), + FUNCTION(C2RX, input2), + FUNCTION(INT1, input3), + FUNCTION(T4CK, input3), + FUNCTION(T9CK, input3), + FUNCTION(IC1, input3), + FUNCTION(IC6, input3), + FUNCTION(U3CTS, input3), + FUNCTION(U4RX, input3), + FUNCTION(U6RX, input3), + FUNCTION(SS2IN, input3), + FUNCTION(SDI6, input3), + FUNCTION(OCFA, input3), + FUNCTION(REFCLKI3, input3), + FUNCTION(U3TX, output0), + FUNCTION(U4RTS, output0), + FUNCTION(SDO1, output0_1), + FUNCTION(SDO2, output0_1), + FUNCTION(SDO3, output0_1), + FUNCTION(SDO5, output0_1), + FUNCTION(SS6OUT, output0), + FUNCTION(OC3, output0), + FUNCTION(OC6, output0), + FUNCTION(REFCLKO4, output0), + FUNCTION(C2OUT, output0), + FUNCTION(C1TX, output0), + FUNCTION(U1TX, output1), + FUNCTION(U2RTS, output1), + FUNCTION(U5TX, output1), + FUNCTION(U6RTS, output1), + FUNCTION(SDO4, output1_3), + FUNCTION(OC4, output1), + FUNCTION(OC7, output1), + FUNCTION(REFCLKO1, output1), + FUNCTION(U3RTS, output2), + FUNCTION(U4TX, output2), + FUNCTION(U6TX, output2_3), + FUNCTION(SS1OUT, output2), + FUNCTION(SS3OUT, output2), + FUNCTION(SS4OUT, output2), + FUNCTION(SS5OUT, output2), + FUNCTION(SDO6, output2_3), + FUNCTION(OC5, output2), + FUNCTION(OC8, output2), + FUNCTION(C1OUT, output2), + FUNCTION(REFCLKO3, output2), + FUNCTION(U1RTS, output3), + FUNCTION(U2TX, output3), + FUNCTION(U5RTS, output3), + FUNCTION(SS2OUT, output3), + FUNCTION(OC2, output3), + FUNCTION(OC1, output3), + FUNCTION(OC9, output3), + FUNCTION(C2TX, output3), +}; + +#define PIC32_PINCTRL_GROUP(_pin, _name, ...) \ + { \ + .name = #_name, \ + .pin = _pin, \ + .functions = (struct pic32_desc_function[]){ \ + __VA_ARGS__, { } }, \ + } + +#define PIC32_PINCTRL_FUNCTION(_name, _muxreg, _muxval) \ + { \ + .name = #_name, \ + .muxreg = _muxreg, \ + .muxval = _muxval, \ + } + +static const struct pic32_pin_group pic32_groups[] = { + PIC32_PINCTRL_GROUP(14, A14, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 13), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 13), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 13), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 13), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 13), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 13), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 13), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 13), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 13), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 13), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 13), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 13), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 13), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 13), + PIC32_PINCTRL_FUNCTION(U3TX, RPA14R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPA14R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPA14R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPA14R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPA14R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPA14R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPA14R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPA14R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPA14R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPA14R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPA14R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPA14R, 15)), + PIC32_PINCTRL_GROUP(15, A15, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 13), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 13), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 13), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 13), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 13), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 13), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 13), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 13), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 13), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 13), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 13), + PIC32_PINCTRL_FUNCTION(U1TX, RPA15R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPA15R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPA15R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPA15R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPA15R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPA15R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPA15R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPA15R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPA15R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPA15R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPA15R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPA15R, 15)), + PIC32_PINCTRL_GROUP(16, B0, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 5), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 5), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 5), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 5), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 5), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 5), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 5), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 5), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 5), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 5), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 5), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 5), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 5), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 5), + PIC32_PINCTRL_FUNCTION(U3RTS, RPB0R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPB0R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPB0R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPB0R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPB0R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPB0R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPB0R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPB0R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPB0R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPB0R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPB0R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPB0R, 15)), + PIC32_PINCTRL_GROUP(17, B1, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 5), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 5), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 5), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 5), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 5), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 5), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 5), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 5), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 5), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 5), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 5), + PIC32_PINCTRL_FUNCTION(U1TX, RPB1R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPB1R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPB1R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPB1R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPB1R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPB1R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPB1R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPB1R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPB1R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPB1R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPB1R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPB1R, 15)), + PIC32_PINCTRL_GROUP(18, B2, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 7), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 7), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 7), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 7), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 7), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 7), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 7), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 7), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 7), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 7), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 7), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 7), + PIC32_PINCTRL_FUNCTION(U1RTS, RPB2R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPB2R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPB2R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPB2R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPB2R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPB2R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPB2R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPB2R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPB2R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPB2R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPB2R, 15)), + PIC32_PINCTRL_GROUP(19, B3, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 8), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 8), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 8), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 8), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 8), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 8), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 8), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 8), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 8), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 8), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 8), + PIC32_PINCTRL_FUNCTION(U1TX, RPB3R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPB3R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPB3R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPB3R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPB3R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPB3R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPB3R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPB3R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPB3R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPB3R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPB3R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPB3R, 15)), + PIC32_PINCTRL_GROUP(21, B5, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 8), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 8), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 8), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 8), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 8), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 8), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 8), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 8), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 8), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 8), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 8), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 8), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 8), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 8), + PIC32_PINCTRL_FUNCTION(U3TX, RPB5R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPB5R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPB5R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPB5R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPB5R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPB5R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPB5R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPB5R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPB5R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPB5R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPB5R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPB5R, 15)), + PIC32_PINCTRL_GROUP(22, B6, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 4), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 4), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 4), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 4), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 4), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 4), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 4), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 4), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 4), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 4), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 4), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 4), + PIC32_PINCTRL_FUNCTION(U1RTS, RPB6R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPB6R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPB6R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPB6R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPB6R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPB6R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPB6R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPB6R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPB6R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPB6R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPB6R, 15)), + PIC32_PINCTRL_GROUP(23, B7, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 7), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 7), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 7), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 7), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 7), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 7), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 7), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 7), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 7), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 7), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 7), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 7), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 7), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 7), + PIC32_PINCTRL_FUNCTION(U3RTS, RPB7R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPB7R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPB7R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPB7R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPB7R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPB7R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPB7R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPB7R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPB7R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPB7R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPB7R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPB7R, 15)), + PIC32_PINCTRL_GROUP(24, B8, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 2), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 2), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 2), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 2), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 2), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 2), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 2), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 2), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 2), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 2), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 2), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 2), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 2), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 2), + PIC32_PINCTRL_FUNCTION(U3RTS, RPB8R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPB8R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPB8R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPB8R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPB8R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPB8R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPB8R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPB8R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPB8R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPB8R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPB8R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPB8R, 15)), + PIC32_PINCTRL_GROUP(25, B9, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 5), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 5), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 5), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 5), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 5), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 5), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 5), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 5), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 5), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 5), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 5), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 5), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 5), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 5), + PIC32_PINCTRL_FUNCTION(U3TX, RPB9R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPB9R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPB9R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPB9R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPB9R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPB9R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPB9R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPB9R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPB9R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPB9R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPB9R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPB9R, 15)), + PIC32_PINCTRL_GROUP(26, B10, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 6), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 6), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 6), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 6), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 6), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 6), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 6), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 6), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 6), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 6), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 6), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 6), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 6), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 6), + PIC32_PINCTRL_FUNCTION(U3TX, RPB10R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPB10R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPB10R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPB10R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPB10R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPB10R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPB10R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPB10R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPB10R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPB10R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPB10R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPB10R, 15)), + PIC32_PINCTRL_GROUP(30, B14, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 2), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 2), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 2), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 2), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 2), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 2), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 2), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 2), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 2), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 2), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 2), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 2), + PIC32_PINCTRL_FUNCTION(U1RTS, RPB14R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPB14R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPB14R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPB14R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPB14R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPB14R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPB14R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPB14R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPB14R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPB14R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPB14R, 15)), + PIC32_PINCTRL_GROUP(31, B15, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 3), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 3), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 3), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 3), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 3), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 3), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 3), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 3), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 3), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 3), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 3), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 3), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 3), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 3), + PIC32_PINCTRL_FUNCTION(U3RTS, RPB15R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPB15R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPB15R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPB15R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPB15R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPB15R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPB15R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPB15R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPB15R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPB15R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPB15R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPB15R, 15)), + PIC32_PINCTRL_GROUP(33, C1, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 10), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 10), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 10), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 10), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 10), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 10), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 10), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 10), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 10), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 10), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 10), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 10), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 10), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 10), + PIC32_PINCTRL_FUNCTION(U3TX, RPC1R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPC1R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPC1R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPC1R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPC1R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPC1R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPC1R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPC1R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPC1R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPC1R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPC1R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPC1R, 15)), + PIC32_PINCTRL_GROUP(34, C2, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 12), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 12), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 12), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 12), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 12), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 12), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 12), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 12), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 12), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 12), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 12), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 12), + PIC32_PINCTRL_FUNCTION(U1RTS, RPC2R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPC2R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPC2R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPC2R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPC2R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPC2R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPC2R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPC2R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPC2R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPC2R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPC2R, 15)), + PIC32_PINCTRL_GROUP(35, C3, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 12), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 12), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 12), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 12), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 12), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 12), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 12), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 12), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 12), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 12), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 12), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 12), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 12), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 12), + PIC32_PINCTRL_FUNCTION(U3RTS, RPC3R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPC3R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPC3R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPC3R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPC3R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPC3R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPC3R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPC3R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPC3R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPC3R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPC3R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPC3R, 15)), + PIC32_PINCTRL_GROUP(36, C4, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 10), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 10), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 10), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 10), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 10), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 10), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 10), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 10), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 10), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 10), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 10), + PIC32_PINCTRL_FUNCTION(U1TX, RPC4R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPC4R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPC4R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPC4R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPC4R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPC4R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPC4R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPC4R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPC4R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPC4R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPC4R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPC4R, 15)), + PIC32_PINCTRL_GROUP(45, C13, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 7), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 7), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 7), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 7), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 7), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 7), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 7), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 7), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 7), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 7), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 7), + PIC32_PINCTRL_FUNCTION(U1TX, RPC13R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPC13R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPC13R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPC13R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPC13R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPC13R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPC13R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPC13R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPC13R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPC13R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPC13R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPC13R, 15)), + PIC32_PINCTRL_GROUP(46, C14, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 7), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 7), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 7), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 7), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 7), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 7), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 7), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 7), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 7), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 7), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 7), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 7), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 7), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 7), + PIC32_PINCTRL_FUNCTION(U3TX, RPC14R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPC14R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPC14R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPC14R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPC14R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPC14R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPC14R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPC14R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPC14R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPC14R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPC14R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPC14R, 15)), + PIC32_PINCTRL_GROUP(48, D0, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 3), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 3), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 3), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 3), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 3), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 3), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 3), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 3), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 3), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 3), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 3), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 3), + PIC32_PINCTRL_FUNCTION(U1RTS, RPD0R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPD0R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPD0R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPD0R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPD0R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPD0R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPD0R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPD0R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPD0R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPD0R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPD0R, 15)), + PIC32_PINCTRL_GROUP(50, D2, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 0), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 0), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 0), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 0), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 0), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 0), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 0), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 0), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 0), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 0), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 0), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 0), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 0), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 0), + PIC32_PINCTRL_FUNCTION(U3TX, RPD2R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPD2R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPD2R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPD2R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPD2R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPD2R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPD2R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPD2R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPD2R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPD2R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPD2R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPD2R, 15)), + PIC32_PINCTRL_GROUP(51, D3, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 0), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 0), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 0), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 0), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 0), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 0), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 0), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 0), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 0), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 0), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 0), + PIC32_PINCTRL_FUNCTION(U1TX, RPD3R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPD3R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPD3R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPD3R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPD3R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPD3R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPD3R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPD3R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPD3R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPD3R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPD3R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPD3R, 15)), + PIC32_PINCTRL_GROUP(52, D4, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 4), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 4), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 4), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 4), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 4), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 4), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 4), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 4), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 4), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 4), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 4), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 4), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 4), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 4), + PIC32_PINCTRL_FUNCTION(U3RTS, RPD4R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPD4R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPD4R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPD4R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPD4R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPD4R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPD4R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPD4R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPD4R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPD4R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPD4R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPD4R, 15)), + PIC32_PINCTRL_GROUP(53, D5, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 6), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 6), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 6), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 6), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 6), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 6), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 6), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 6), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 6), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 6), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 6), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 6), + PIC32_PINCTRL_FUNCTION(U1RTS, RPD5R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPD5R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPD5R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPD5R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPD5R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPD5R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPD5R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPD5R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPD5R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPD5R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPD5R, 15)), + PIC32_PINCTRL_GROUP(54, D6, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 14), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 14), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 14), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 14), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 14), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 14), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 14), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 14), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 14), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 14), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 14), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 14), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 14), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 14), + PIC32_PINCTRL_FUNCTION(U3TX, RPD6R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPD6R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPD6R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPD6R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPD6R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPD6R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPD6R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPD6R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPD6R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPD6R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPD6R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPD6R, 15)), + PIC32_PINCTRL_GROUP(55, D7, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 14), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 14), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 14), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 14), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 14), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 14), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 14), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 14), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 14), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 14), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 14), + PIC32_PINCTRL_FUNCTION(U1TX, RPD7R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPD7R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPD7R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPD7R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPD7R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPD7R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPD7R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPD7R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPD7R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPD7R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPD7R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPD7R, 15)), + PIC32_PINCTRL_GROUP(57, D9, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 0), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 0), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 0), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 0), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 0), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 0), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 0), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 0), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 0), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 0), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 0), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 0), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 0), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 0), + PIC32_PINCTRL_FUNCTION(U3RTS, RPD9R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPD9R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPD9R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPD9R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPD9R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPD9R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPD9R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPD9R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPD9R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPD9R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPD9R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPD9R, 15)), + PIC32_PINCTRL_GROUP(58, D10, + PIC32_PINCTRL_FUNCTION(U3TX, RPD10R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPD10R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPD10R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPD10R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPD10R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPD10R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPD10R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPD10R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPD10R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPD10R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPD10R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPD10R, 15)), + PIC32_PINCTRL_GROUP(59, D11, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 3), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 3), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 3), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 3), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 3), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 3), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 3), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 3), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 3), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 3), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 3), + PIC32_PINCTRL_FUNCTION(U1TX, RPD11R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPD11R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPD11R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPD11R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPD11R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPD11R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPD11R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPD11R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPD11R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPD11R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPD11R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPD11R, 15)), + PIC32_PINCTRL_GROUP(60, D12, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 10), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 10), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 10), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 10), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 10), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 10), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 10), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 10), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 10), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 10), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 10), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 10), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 10), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 10), + PIC32_PINCTRL_FUNCTION(U3RTS, RPD12R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPD12R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPD12R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPD12R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPD12R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPD12R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPD12R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPD12R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPD12R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPD12R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPD12R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPD12R, 15)), + PIC32_PINCTRL_GROUP(62, D14, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 11), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 11), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 11), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 11), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 11), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 11), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 11), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 11), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 11), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 11), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 11), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 11), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 11), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 11), + PIC32_PINCTRL_FUNCTION(U3TX, RPD14R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPD14R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPD14R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPD14R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPD14R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPD14R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPD14R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPD14R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPD14R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPD14R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPD14R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPD14R, 15)), + PIC32_PINCTRL_GROUP(63, D15, + PIC32_PINCTRL_FUNCTION(U1TX, RPD15R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPD15R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPD15R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPD15R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPD15R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPD15R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPD15R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPD15R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPD15R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPD15R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPD15R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPD15R, 15)), + PIC32_PINCTRL_GROUP(67, E3, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 6), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 6), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 6), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 6), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 6), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 6), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 6), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 6), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 6), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 6), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 6), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 6), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 6), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 6), + PIC32_PINCTRL_FUNCTION(U3RTS, RPE3R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPE3R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPE3R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPE3R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPE3R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPE3R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPE3R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPE3R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPE3R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPE3R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPE3R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPE3R, 15)), + PIC32_PINCTRL_GROUP(69, E5, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 6), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 6), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 6), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 6), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 6), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 6), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 6), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 6), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 6), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 6), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 6), + PIC32_PINCTRL_FUNCTION(U1TX, RPE5R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPE5R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPE5R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPE5R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPE5R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPE5R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPE5R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPE5R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPE5R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPE5R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPE5R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPE5R, 15)), + PIC32_PINCTRL_GROUP(72, E8, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 13), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 13), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 13), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 13), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 13), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 13), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 13), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 13), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 13), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 13), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 13), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 13), + PIC32_PINCTRL_FUNCTION(U1RTS, RPE8R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPE8R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPE8R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPE8R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPE8R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPE8R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPE8R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPE8R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPE8R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPE8R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPE8R, 15)), + PIC32_PINCTRL_GROUP(73, E9, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 13), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 13), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 13), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 13), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 13), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 13), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 13), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 13), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 13), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 13), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 13), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 13), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 13), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 13), + PIC32_PINCTRL_FUNCTION(U3RTS, RPE9R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPE9R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPE9R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPE9R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPE9R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPE9R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPE9R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPE9R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPE9R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPE9R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPE9R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPE9R, 15)), + PIC32_PINCTRL_GROUP(80, F0, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 4), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 4), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 4), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 4), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 4), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 4), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 4), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 4), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 4), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 4), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 4), + PIC32_PINCTRL_FUNCTION(U1TX, RPF0R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPF0R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPF0R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPF0R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPF0R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPF0R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPF0R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPF0R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPF0R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPF0R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPF0R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPF0R, 15)), + PIC32_PINCTRL_GROUP(81, F1, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 4), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 4), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 4), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 4), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 4), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 4), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 4), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 4), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 4), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 4), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 4), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 4), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 4), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 4), + PIC32_PINCTRL_FUNCTION(U3TX, RPF1R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPF1R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPF1R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPF1R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPF1R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPF1R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPF1R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPF1R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPF1R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPF1R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPF1R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPF1R, 15)), + PIC32_PINCTRL_GROUP(82, F2, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 11), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 11), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 11), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 11), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 11), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 11), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 11), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 11), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 11), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 11), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 11), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 11), + PIC32_PINCTRL_FUNCTION(U1RTS, RPF2R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPF2R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPF2R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPF2R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPF2R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPF2R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPF2R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPF2R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPF2R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPF2R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPF2R, 15)), + PIC32_PINCTRL_GROUP(83, F3, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 8), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 8), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 8), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 8), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 8), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 8), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 8), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 8), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 8), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 8), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 8), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 8), + PIC32_PINCTRL_FUNCTION(U1RTS, RPF3R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPF3R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPF3R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPF3R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPF3R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPF3R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPF3R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPF3R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPF3R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPF3R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPF3R, 15)), + PIC32_PINCTRL_GROUP(84, F4, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 2), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 2), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 2), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 2), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 2), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 2), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 2), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 2), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 2), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 2), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 2), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 2), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 2), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 2), + PIC32_PINCTRL_FUNCTION(U3TX, RPF4R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPF4R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPF4R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPF4R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPF4R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPF4R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPF4R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPF4R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPF4R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPF4R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPF4R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPF4R, 15)), + PIC32_PINCTRL_GROUP(85, F5, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 2), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 2), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 2), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 2), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 2), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 2), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 2), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 2), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 2), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 2), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 2), + PIC32_PINCTRL_FUNCTION(U1TX, RPF5R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPF5R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPF5R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPF5R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPF5R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPF5R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPF5R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPF5R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPF5R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPF5R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPF5R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPF5R, 15)), + PIC32_PINCTRL_GROUP(88, F8, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 11), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 11), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 11), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 11), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 11), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 11), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 11), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 11), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 11), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 11), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 11), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 11), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 11), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 11), + PIC32_PINCTRL_FUNCTION(U3RTS, RPF8R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPF8R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPF8R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPF8R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPF8R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPF8R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPF8R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPF8R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPF8R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPF8R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPF8R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPF8R, 15)), + PIC32_PINCTRL_GROUP(92, F12, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 9), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 9), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 9), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 9), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 9), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 9), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 9), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 9), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 9), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 9), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 9), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 9), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 9), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 9), + PIC32_PINCTRL_FUNCTION(U3RTS, RPF12R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPF12R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPF12R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPF12R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPF12R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPF12R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPF12R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPF12R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPF12R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPF12R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPF12R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPF12R, 15)), + PIC32_PINCTRL_GROUP(93, F13, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 9), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 9), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 9), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 9), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 9), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 9), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 9), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 9), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 9), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 9), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 9), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 9), + PIC32_PINCTRL_FUNCTION(U1RTS, RPF13R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPF13R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPF13R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPF13R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPF13R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPF13R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPF13R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPF13R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPF13R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPF13R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPF13R, 15)), + PIC32_PINCTRL_GROUP(96, G0, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 12), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 12), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 12), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 12), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 12), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 12), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 12), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 12), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 12), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 12), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 12), + PIC32_PINCTRL_FUNCTION(U1TX, RPG0R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPG0R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPG0R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPG0R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPG0R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPG0R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPG0R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPG0R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPG0R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPG0R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPG0R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPG0R, 15)), + PIC32_PINCTRL_GROUP(97, G1, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 12), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 12), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 12), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 12), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 12), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 12), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 12), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 12), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 12), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 12), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 12), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 12), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 12), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 12), + PIC32_PINCTRL_FUNCTION(U3TX, RPG1R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPG1R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPG1R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPG1R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPG1R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPG1R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPG1R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPG1R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPG1R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPG1R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPG1R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPG1R, 15)), + PIC32_PINCTRL_GROUP(102, G6, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 1), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 1), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 1), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 1), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 1), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 1), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 1), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 1), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 1), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 1), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 1), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 1), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 1), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 1), + PIC32_PINCTRL_FUNCTION(U3RTS, RPG6R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPG6R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPG6R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPG6R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPG6R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPG6R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPG6R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPG6R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPG6R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPG6R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPG6R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPG6R, 15)), + PIC32_PINCTRL_GROUP(103, G7, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 1), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 1), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 1), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 1), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 1), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 1), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 1), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 1), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 1), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 1), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 1), + PIC32_PINCTRL_FUNCTION(U1TX, RPG7R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPG7R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPG7R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPG7R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPG7R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPG7R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPG7R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPG7R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPG7R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPG7R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPG7R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPG7R, 15)), + PIC32_PINCTRL_GROUP(104, G8, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 1), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 1), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 1), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 1), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 1), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 1), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 1), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 1), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 1), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 1), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 1), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 1), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 1), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 1), + PIC32_PINCTRL_FUNCTION(U3TX, RPG8R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPG8R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPG8R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPG8R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPG8R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPG8R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPG8R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPG8R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPG8R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPG8R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPG8R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPG8R, 15)), + PIC32_PINCTRL_GROUP(105, G9, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 1), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 1), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 1), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 1), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 1), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 1), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 1), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 1), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 1), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 1), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 1), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 1), + PIC32_PINCTRL_FUNCTION(U1RTS, RPG9R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPG9R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPG9R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPG9R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPG9R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPG9R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPG9R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPG9R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPG9R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPG9R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPG9R, 15)), +}; + +static inline struct pic32_gpio_bank *irqd_to_bank(struct irq_data *d) +{ + return gpiochip_get_data(irq_data_get_irq_chip_data(d)); +} + +static inline struct pic32_gpio_bank *pctl_to_bank(struct pic32_pinctrl *pctl, + unsigned pin) +{ + return &pctl->gpio_banks[pin / PINS_PER_BANK]; +} + +static int pic32_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + return pctl->ngroups; +} + +static const char *pic32_pinctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned group) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + return pctl->groups[group].name; +} + +static int pic32_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, + unsigned group, + const unsigned **pins, + unsigned *num_pins) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + *pins = &pctl->groups[group].pin; + *num_pins = 1; + + return 0; +} + +static const struct pinctrl_ops pic32_pinctrl_ops = { + .get_groups_count = pic32_pinctrl_get_groups_count, + .get_group_name = pic32_pinctrl_get_group_name, + .get_group_pins = pic32_pinctrl_get_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, + .dt_free_map = pinctrl_utils_dt_free_map, +}; + +static int pic32_pinmux_get_functions_count(struct pinctrl_dev *pctldev) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + return pctl->nfunctions; +} + +static const char * +pic32_pinmux_get_function_name(struct pinctrl_dev *pctldev, unsigned func) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + return pctl->functions[func].name; +} + +static int pic32_pinmux_get_function_groups(struct pinctrl_dev *pctldev, + unsigned func, + const char * const **groups, + unsigned * const num_groups) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + *groups = pctl->functions[func].groups; + *num_groups = pctl->functions[func].ngroups; + + return 0; +} + +static int pic32_pinmux_enable(struct pinctrl_dev *pctldev, + unsigned func, unsigned group) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + const struct pic32_pin_group *pg = &pctl->groups[group]; + const struct pic32_function *pf = &pctl->functions[func]; + const char *fname = pf->name; + struct pic32_desc_function *functions = pg->functions; + + while (functions->name) { + if (!strcmp(functions->name, fname)) { + dev_dbg(pctl->dev, + "setting function %s reg 0x%x = %d\n", + fname, functions->muxreg, functions->muxval); + + writel(functions->muxval, pctl->reg_base + functions->muxreg); + + return 0; + } + + functions++; + } + + dev_err(pctl->dev, "cannot mux pin %u to function %u\n", group, func); + + return -EINVAL; +} + +static int pic32_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned offset) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct pic32_gpio_bank *bank = gpiochip_get_data(range->gc); + u32 mask = BIT(offset - bank->gpio_chip.base); + + dev_dbg(pctl->dev, "requesting gpio %d in bank %d with mask 0x%x\n", + offset, bank->gpio_chip.base, mask); + + writel(mask, bank->reg_base + PIC32_CLR(ANSEL_REG)); + + return 0; +} + +static int pic32_gpio_direction_input(struct gpio_chip *chip, + unsigned offset) +{ + struct pic32_gpio_bank *bank = gpiochip_get_data(chip); + u32 mask = BIT(offset); + + writel(mask, bank->reg_base + PIC32_SET(TRIS_REG)); + + return 0; +} + +static int pic32_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct pic32_gpio_bank *bank = gpiochip_get_data(chip); + + return !!(readl(bank->reg_base + PORT_REG) & BIT(offset)); +} + +static void pic32_gpio_set(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct pic32_gpio_bank *bank = gpiochip_get_data(chip); + u32 mask = BIT(offset); + + if (value) + writel(mask, bank->reg_base + PIC32_SET(PORT_REG)); + else + writel(mask, bank->reg_base + PIC32_CLR(PORT_REG)); +} + +static int pic32_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct pic32_gpio_bank *bank = gpiochip_get_data(chip); + u32 mask = BIT(offset); + + pic32_gpio_set(chip, offset, value); + writel(mask, bank->reg_base + PIC32_CLR(TRIS_REG)); + + return 0; +} + +static int pic32_gpio_set_direction(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned offset, bool input) +{ + struct gpio_chip *chip = range->gc; + + if (input) + pic32_gpio_direction_input(chip, offset); + else + pic32_gpio_direction_output(chip, offset, 0); + + return 0; +} + +static const struct pinmux_ops pic32_pinmux_ops = { + .get_functions_count = pic32_pinmux_get_functions_count, + .get_function_name = pic32_pinmux_get_function_name, + .get_function_groups = pic32_pinmux_get_function_groups, + .set_mux = pic32_pinmux_enable, + .gpio_request_enable = pic32_gpio_request_enable, + .gpio_set_direction = pic32_gpio_set_direction, +}; + +static int pic32_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *config) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct pic32_gpio_bank *bank = pctl_to_bank(pctl, pin); + unsigned param = pinconf_to_config_param(*config); + u32 mask = BIT(pin - bank->gpio_chip.base); + u32 arg; + + switch (param) { + case PIN_CONFIG_BIAS_PULL_UP: + arg = !!(readl(bank->reg_base + CNPU_REG) & mask); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + arg = !!(readl(bank->reg_base + CNPD_REG) & mask); + break; + case PIN_CONFIG_MICROCHIP_DIGITAL: + arg = !(readl(bank->reg_base + ANSEL_REG) & mask); + break; + case PIN_CONFIG_MICROCHIP_ANALOG: + arg = !!(readl(bank->reg_base + ANSEL_REG) & mask); + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + arg = !!(readl(bank->reg_base + ODCU_REG) & mask); + break; + case PIN_CONFIG_INPUT_ENABLE: + arg = !!(readl(bank->reg_base + TRIS_REG) & mask); + break; + case PIN_CONFIG_OUTPUT: + arg = !(readl(bank->reg_base + TRIS_REG) & mask); + break; + default: + dev_err(pctl->dev, "Property %u not supported\n", param); + return -ENOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + + return 0; +} + +static int pic32_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *configs, unsigned num_configs) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct pic32_gpio_bank *bank = pctl_to_bank(pctl, pin); + unsigned param; + u32 arg; + unsigned int i; + u32 offset = pin - bank->gpio_chip.base; + u32 mask = BIT(offset); + + dev_dbg(pctl->dev, "setting pin %d bank %d mask 0x%x\n", + pin, bank->gpio_chip.base, mask); + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + switch (param) { + case PIN_CONFIG_BIAS_PULL_UP: + dev_dbg(pctl->dev, " pullup\n"); + writel(mask, bank->reg_base +PIC32_SET(CNPU_REG)); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + dev_dbg(pctl->dev, " pulldown\n"); + writel(mask, bank->reg_base + PIC32_SET(CNPD_REG)); + break; + case PIN_CONFIG_MICROCHIP_DIGITAL: + dev_dbg(pctl->dev, " digital\n"); + writel(mask, bank->reg_base + PIC32_CLR(ANSEL_REG)); + break; + case PIN_CONFIG_MICROCHIP_ANALOG: + dev_dbg(pctl->dev, " analog\n"); + writel(mask, bank->reg_base + PIC32_SET(ANSEL_REG)); + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + dev_dbg(pctl->dev, " opendrain\n"); + writel(mask, bank->reg_base + PIC32_SET(ODCU_REG)); + break; + case PIN_CONFIG_INPUT_ENABLE: + pic32_gpio_direction_input(&bank->gpio_chip, offset); + break; + case PIN_CONFIG_OUTPUT: + pic32_gpio_direction_output(&bank->gpio_chip, + offset, arg); + break; + default: + dev_err(pctl->dev, "Property %u not supported\n", + param); + return -ENOTSUPP; + } + } + + return 0; +} + +static const struct pinconf_ops pic32_pinconf_ops = { + .pin_config_get = pic32_pinconf_get, + .pin_config_set = pic32_pinconf_set, + .is_generic = true, +}; + +static struct pinctrl_desc pic32_pinctrl_desc = { + .name = "pic32-pinctrl", + .pctlops = &pic32_pinctrl_ops, + .pmxops = &pic32_pinmux_ops, + .confops = &pic32_pinconf_ops, + .owner = THIS_MODULE, +}; + +static int pic32_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + struct pic32_gpio_bank *bank = gpiochip_get_data(chip); + + return !!(readl(bank->reg_base + TRIS_REG) & BIT(offset)); +} + +static void pic32_gpio_irq_ack(struct irq_data *data) +{ + struct pic32_gpio_bank *bank = irqd_to_bank(data); + + writel(0, bank->reg_base + CNF_REG); +} + +static void pic32_gpio_irq_mask(struct irq_data *data) +{ + struct pic32_gpio_bank *bank = irqd_to_bank(data); + + writel(BIT(PIC32_CNCON_ON), bank->reg_base + PIC32_CLR(CNCON_REG)); +} + +static void pic32_gpio_irq_unmask(struct irq_data *data) +{ + struct pic32_gpio_bank *bank = irqd_to_bank(data); + + writel(BIT(PIC32_CNCON_ON), bank->reg_base + PIC32_SET(CNCON_REG)); +} + +static unsigned int pic32_gpio_irq_startup(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + + pic32_gpio_direction_input(chip, data->hwirq); + pic32_gpio_irq_unmask(data); + + return 0; +} + +static int pic32_gpio_irq_set_type(struct irq_data *data, unsigned int type) +{ + struct pic32_gpio_bank *bank = irqd_to_bank(data); + u32 mask = BIT(data->hwirq); + + switch (type & IRQ_TYPE_SENSE_MASK) { + case IRQ_TYPE_EDGE_RISING: + /* enable RISE */ + writel(mask, bank->reg_base + PIC32_SET(CNEN_REG)); + /* disable FALL */ + writel(mask, bank->reg_base + PIC32_CLR(CNNE_REG)); + /* enable EDGE */ + writel(BIT(PIC32_CNCON_EDGE), bank->reg_base + PIC32_SET(CNCON_REG)); + break; + case IRQ_TYPE_EDGE_FALLING: + /* disable RISE */ + writel(mask, bank->reg_base + PIC32_CLR(CNEN_REG)); + /* enable FALL */ + writel(mask, bank->reg_base + PIC32_SET(CNNE_REG)); + /* enable EDGE */ + writel(BIT(PIC32_CNCON_EDGE), bank->reg_base + PIC32_SET(CNCON_REG)); + break; + case IRQ_TYPE_EDGE_BOTH: + /* enable RISE */ + writel(mask, bank->reg_base + PIC32_SET(CNEN_REG)); + /* enable FALL */ + writel(mask, bank->reg_base + PIC32_SET(CNNE_REG)); + /* enable EDGE */ + writel(BIT(PIC32_CNCON_EDGE), bank->reg_base + PIC32_SET(CNCON_REG)); + break; + default: + return -EINVAL; + } + + irq_set_handler_locked(data, handle_edge_irq); + + return 0; +} + +static u32 pic32_gpio_get_pending(struct gpio_chip *gc, unsigned long status) +{ + struct pic32_gpio_bank *bank = gpiochip_get_data(gc); + u32 pending = 0; + u32 cnen_rise, cnne_fall; + u32 pin; + + cnen_rise = readl(bank->reg_base + CNEN_REG); + cnne_fall = readl(bank->reg_base + CNNE_REG); + + for_each_set_bit(pin, &status, BITS_PER_LONG) { + u32 mask = BIT(pin); + + if ((mask & cnen_rise) || (mask && cnne_fall)) + pending |= mask; + } + + return pending; +} + +static void pic32_gpio_irq_handler(struct irq_desc *desc) +{ + struct gpio_chip *gc = irq_desc_get_handler_data(desc); + struct pic32_gpio_bank *bank = gpiochip_get_data(gc); + struct irq_chip *chip = irq_desc_get_chip(desc); + unsigned long pending; + unsigned int pin; + u32 stat; + + chained_irq_enter(chip, desc); + + stat = readl(bank->reg_base + CNF_REG); + pending = pic32_gpio_get_pending(gc, stat); + + for_each_set_bit(pin, &pending, BITS_PER_LONG) + generic_handle_irq(irq_linear_revmap(gc->irqdomain, pin)); + + chained_irq_exit(chip, desc); +} + +#define GPIO_BANK(_bank, _npins) \ + { \ + .gpio_chip = { \ + .label = "GPIO" #_bank, \ + .request = gpiochip_generic_request, \ + .free = gpiochip_generic_free, \ + .get_direction = pic32_gpio_get_direction, \ + .direction_input = pic32_gpio_direction_input, \ + .direction_output = pic32_gpio_direction_output, \ + .get = pic32_gpio_get, \ + .set = pic32_gpio_set, \ + .ngpio = _npins, \ + .base = GPIO_BANK_START(_bank), \ + .owner = THIS_MODULE, \ + .can_sleep = 0, \ + }, \ + .irq_chip = { \ + .name = "GPIO" #_bank, \ + .irq_startup = pic32_gpio_irq_startup, \ + .irq_ack = pic32_gpio_irq_ack, \ + .irq_mask = pic32_gpio_irq_mask, \ + .irq_unmask = pic32_gpio_irq_unmask, \ + .irq_set_type = pic32_gpio_irq_set_type, \ + }, \ + } + +static struct pic32_gpio_bank pic32_gpio_banks[] = { + GPIO_BANK(0, PINS_PER_BANK), + GPIO_BANK(1, PINS_PER_BANK), + GPIO_BANK(2, PINS_PER_BANK), + GPIO_BANK(3, PINS_PER_BANK), + GPIO_BANK(4, PINS_PER_BANK), + GPIO_BANK(5, PINS_PER_BANK), + GPIO_BANK(6, PINS_PER_BANK), + GPIO_BANK(7, PINS_PER_BANK), + GPIO_BANK(8, PINS_PER_BANK), + GPIO_BANK(9, PINS_PER_BANK), +}; + +static int pic32_pinctrl_probe(struct platform_device *pdev) +{ + struct pic32_pinctrl *pctl; + struct resource *res; + int ret; + + pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL); + if (!pctl) + return -ENOMEM; + pctl->dev = &pdev->dev; + dev_set_drvdata(&pdev->dev, pctl); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pctl->reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pctl->reg_base)) + return PTR_ERR(pctl->reg_base); + + pctl->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(pctl->clk)) { + ret = PTR_ERR(pctl->clk); + dev_err(&pdev->dev, "clk get failed\n"); + return ret; + } + + ret = clk_prepare_enable(pctl->clk); + if (ret) { + dev_err(&pdev->dev, "clk enable failed\n"); + return ret; + } + + pctl->pins = pic32_pins; + pctl->npins = ARRAY_SIZE(pic32_pins); + pctl->functions = pic32_functions; + pctl->nfunctions = ARRAY_SIZE(pic32_functions); + pctl->groups = pic32_groups; + pctl->ngroups = ARRAY_SIZE(pic32_groups); + pctl->gpio_banks = pic32_gpio_banks; + pctl->nbanks = ARRAY_SIZE(pic32_gpio_banks); + + pic32_pinctrl_desc.pins = pctl->pins; + pic32_pinctrl_desc.npins = pctl->npins; + pic32_pinctrl_desc.custom_params = pic32_mpp_bindings; + pic32_pinctrl_desc.num_custom_params = ARRAY_SIZE(pic32_mpp_bindings); + + pctl->pctldev = pinctrl_register(&pic32_pinctrl_desc, &pdev->dev, pctl); + if (IS_ERR(pctl->pctldev)) { + dev_err(&pdev->dev, "Failed to register pinctrl device\n"); + return PTR_ERR(pctl->pctldev); + } + + return 0; +} + +static int pic32_gpio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct pic32_gpio_bank *bank; + u32 id; + int irq, ret; + struct resource *res; + + if (of_property_read_u32(np, "microchip,gpio-bank", &id)) { + dev_err(&pdev->dev, "microchip,gpio-bank property not found\n"); + return -EINVAL; + } + + if (id >= ARRAY_SIZE(pic32_gpio_banks)) { + dev_err(&pdev->dev, "invalid microchip,gpio-bank property\n"); + return -EINVAL; + } + + bank = &pic32_gpio_banks[id]; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + bank->reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(bank->reg_base)) + return PTR_ERR(bank->reg_base); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "irq get failed\n"); + return irq; + } + + bank->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(bank->clk)) { + ret = PTR_ERR(bank->clk); + dev_err(&pdev->dev, "clk get failed\n"); + return ret; + } + + ret = clk_prepare_enable(bank->clk); + if (ret) { + dev_err(&pdev->dev, "clk enable failed\n"); + return ret; + } + + bank->gpio_chip.parent = &pdev->dev; + bank->gpio_chip.of_node = np; + ret = gpiochip_add_data(&bank->gpio_chip, bank); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to add GPIO chip %u: %d\n", + id, ret); + return ret; + } + + ret = gpiochip_irqchip_add(&bank->gpio_chip, &bank->irq_chip, + 0, handle_level_irq, IRQ_TYPE_NONE); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to add IRQ chip %u: %d\n", + id, ret); + gpiochip_remove(&bank->gpio_chip); + return ret; + } + + gpiochip_set_chained_irqchip(&bank->gpio_chip, &bank->irq_chip, + irq, pic32_gpio_irq_handler); + + return 0; +} + +static const struct of_device_id pic32_pinctrl_of_match[] = { + { .compatible = "microchip,pic32mzda-pinctrl", }, + { }, +}; + +static struct platform_driver pic32_pinctrl_driver = { + .driver = { + .name = "pic32-pinctrl", + .of_match_table = pic32_pinctrl_of_match, + .suppress_bind_attrs = true, + }, + .probe = pic32_pinctrl_probe, +}; + +static const struct of_device_id pic32_gpio_of_match[] = { + { .compatible = "microchip,pic32mzda-gpio", }, + { }, +}; + +static struct platform_driver pic32_gpio_driver = { + .driver = { + .name = "pic32-gpio", + .of_match_table = pic32_gpio_of_match, + .suppress_bind_attrs = true, + }, + .probe = pic32_gpio_probe, +}; + +static int __init pic32_gpio_register(void) +{ + return platform_driver_register(&pic32_gpio_driver); +} +arch_initcall(pic32_gpio_register); + +static int __init pic32_pinctrl_register(void) +{ + return platform_driver_register(&pic32_pinctrl_driver); +} +arch_initcall(pic32_pinctrl_register); diff --git a/drivers/pinctrl/pinctrl-pic32.h b/drivers/pinctrl/pinctrl-pic32.h new file mode 100644 index 000000000000..12826267dc96 --- /dev/null +++ b/drivers/pinctrl/pinctrl-pic32.h @@ -0,0 +1,141 @@ +/* + * PIC32 pinctrl driver + * + * Joshua Henderson, + * Copyright (C) 2015 Microchip Technology Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ +#ifndef PINCTRL_PINCTRL_PIC32_H +#define PINCTRL_PINCTRL_PIC32_H + +/* PORT Registers */ +#define ANSEL_REG 0x00 +#define TRIS_REG 0x10 +#define PORT_REG 0x20 +#define LAT_REG 0x30 +#define ODCU_REG 0x40 +#define CNPU_REG 0x50 +#define CNPD_REG 0x60 +#define CNCON_REG 0x70 +#define CNEN_REG 0x80 +#define CNSTAT_REG 0x90 +#define CNNE_REG 0xA0 +#define CNF_REG 0xB0 + +/* Input PPS Registers */ +#define INT1R 0x04 +#define INT2R 0x08 +#define INT3R 0x0C +#define INT4R 0x10 +#define T2CKR 0x18 +#define T3CKR 0x1C +#define T4CKR 0x20 +#define T5CKR 0x24 +#define T6CKR 0x28 +#define T7CKR 0x2C +#define T8CKR 0x30 +#define T9CKR 0x34 +#define IC1R 0x38 +#define IC2R 0x3C +#define IC3R 0x40 +#define IC4R 0x44 +#define IC5R 0x48 +#define IC6R 0x4C +#define IC7R 0x50 +#define IC8R 0x54 +#define IC9R 0x58 +#define OCFAR 0x60 +#define U1RXR 0x68 +#define U1CTSR 0x6C +#define U2RXR 0x70 +#define U2CTSR 0x74 +#define U3RXR 0x78 +#define U3CTSR 0x7C +#define U4RXR 0x80 +#define U4CTSR 0x84 +#define U5RXR 0x88 +#define U5CTSR 0x8C +#define U6RXR 0x90 +#define U6CTSR 0x94 +#define SDI1R 0x9C +#define SS1INR 0xA0 +#define SDI2R 0xA8 +#define SS2INR 0xAC +#define SDI3R 0xB4 +#define SS3INR 0xB8 +#define SDI4R 0xC0 +#define SS4INR 0xC4 +#define SDI5R 0xCC +#define SS5INR 0xD0 +#define SDI6R 0xD8 +#define SS6INR 0xDC +#define C1RXR 0xE0 +#define C2RXR 0xE4 +#define REFCLKI1R 0xE8 +#define REFCLKI3R 0xF0 +#define REFCLKI4R 0xF4 + +/* Output PPS Registers */ +#define RPA14R 0x138 +#define RPA15R 0x13C +#define RPB0R 0x140 +#define RPB1R 0x144 +#define RPB2R 0x148 +#define RPB3R 0x14C +#define RPB5R 0x154 +#define RPB6R 0x158 +#define RPB7R 0x15C +#define RPB8R 0x160 +#define RPB9R 0x164 +#define RPB10R 0x168 +#define RPB14R 0x178 +#define RPB15R 0x17C +#define RPC1R 0x184 +#define RPC2R 0x188 +#define RPC3R 0x18C +#define RPC4R 0x190 +#define RPC13R 0x1B4 +#define RPC14R 0x1B8 +#define RPD0R 0x1C0 +#define RPD1R 0x1C4 +#define RPD2R 0x1C8 +#define RPD3R 0x1CC +#define RPD4R 0x1D0 +#define RPD5R 0x1D4 +#define RPD6R 0x1D8 +#define RPD7R 0x1DC +#define RPD9R 0x1E4 +#define RPD10R 0x1E8 +#define RPD11R 0x1EC +#define RPD12R 0x1F0 +#define RPD14R 0x1F8 +#define RPD15R 0x1FC +#define RPE3R 0x20C +#define RPE5R 0x214 +#define RPE8R 0x220 +#define RPE9R 0x224 +#define RPF0R 0x240 +#define RPF1R 0x244 +#define RPF2R 0x248 +#define RPF3R 0x24C +#define RPF4R 0x250 +#define RPF5R 0x254 +#define RPF8R 0x260 +#define RPF12R 0x270 +#define RPF13R 0x274 +#define RPG0R 0x280 +#define RPG1R 0x284 +#define RPG6R 0x298 +#define RPG7R 0x29C +#define RPG8R 0x2A0 +#define RPG9R 0x2A4 + +#endif /* PINCTRL_PINCTRL_PIC32_H */ -- cgit v1.2.3 From 0f4a943168f31d29a1701908931acaba518b131a Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 19 Jan 2016 15:23:02 -0800 Subject: target: Fix remote-port TMR ABORT + se_cmd fabric stop To address the bug where fabric driver level shutdown of se_cmd occurs at the same time when TMR CMD_T_ABORTED is happening resulting in a -1 ->cmd_kref, this patch adds a CMD_T_FABRIC_STOP bit that is used to determine when TMR + driver I_T nexus shutdown is happening concurrently. It changes target_sess_cmd_list_set_waiting() to obtain se_cmd->cmd_kref + set CMD_T_FABRIC_STOP, and drop local reference in target_wait_for_sess_cmds() and invoke extra target_put_sess_cmd() during Task Aborted Status (TAS) when necessary. Also, it adds a new target_wait_free_cmd() wrapper around transport_wait_for_tasks() for the special case within transport_generic_free_cmd() to set CMD_T_FABRIC_STOP, and is now aware of CMD_T_ABORTED + CMD_T_TAS status bits to know when an extra transport_put_cmd() during TAS is required. Note transport_generic_free_cmd() is expected to block on cmd->cmd_wait_comp in order to follow what iscsi-target expects during iscsi_conn context se_cmd shutdown. Cc: Quinn Tran Cc: Himanshu Madhani Cc: Sagi Grimberg Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Andy Grover Cc: Mike Christie Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_tmr.c | 54 ++++++++---- drivers/target/target_core_transport.c | 145 +++++++++++++++++++++++++-------- include/target/target_core_base.h | 2 + 3 files changed, 150 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 3e0d77a4c7b6..82a663ba9800 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -75,16 +75,18 @@ void core_tmr_release_req(struct se_tmr_req *tmr) kfree(tmr); } -static void core_tmr_handle_tas_abort( - struct se_session *tmr_sess, - struct se_cmd *cmd, - int tas) +static void core_tmr_handle_tas_abort(struct se_cmd *cmd, int tas) { - bool remove = true; + unsigned long flags; + bool remove = true, send_tas; /* * TASK ABORTED status (TAS) bit support */ - if (tmr_sess && tmr_sess != cmd->se_sess && tas) { + spin_lock_irqsave(&cmd->t_state_lock, flags); + send_tas = (cmd->transport_state & CMD_T_TAS); + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + + if (send_tas) { remove = false; transport_send_task_abort(cmd); } @@ -107,7 +109,8 @@ static int target_check_cdb_and_preempt(struct list_head *list, return 1; } -static bool __target_check_io_state(struct se_cmd *se_cmd) +static bool __target_check_io_state(struct se_cmd *se_cmd, + struct se_session *tmr_sess, int tas) { struct se_session *sess = se_cmd->se_sess; @@ -115,21 +118,32 @@ static bool __target_check_io_state(struct se_cmd *se_cmd) WARN_ON_ONCE(!irqs_disabled()); /* * If command already reached CMD_T_COMPLETE state within - * target_complete_cmd(), this se_cmd has been passed to - * fabric driver and will not be aborted. + * target_complete_cmd() or CMD_T_FABRIC_STOP due to shutdown, + * this se_cmd has been passed to fabric driver and will + * not be aborted. * * Otherwise, obtain a local se_cmd->cmd_kref now for TMR * ABORT_TASK + LUN_RESET for CMD_T_ABORTED processing as * long as se_cmd->cmd_kref is still active unless zero. */ spin_lock(&se_cmd->t_state_lock); - if (se_cmd->transport_state & CMD_T_COMPLETE) { - pr_debug("Attempted to abort io tag: %llu already complete," + if (se_cmd->transport_state & (CMD_T_COMPLETE | CMD_T_FABRIC_STOP)) { + pr_debug("Attempted to abort io tag: %llu already complete or" + " fabric stop, skipping\n", se_cmd->tag); + spin_unlock(&se_cmd->t_state_lock); + return false; + } + if (sess->sess_tearing_down || se_cmd->cmd_wait_set) { + pr_debug("Attempted to abort io tag: %llu already shutdown," " skipping\n", se_cmd->tag); spin_unlock(&se_cmd->t_state_lock); return false; } se_cmd->transport_state |= CMD_T_ABORTED; + + if ((tmr_sess != se_cmd->se_sess) && tas) + se_cmd->transport_state |= CMD_T_TAS; + spin_unlock(&se_cmd->t_state_lock); return kref_get_unless_zero(&se_cmd->cmd_kref); @@ -161,7 +175,7 @@ void core_tmr_abort_task( printk("ABORT_TASK: Found referenced %s task_tag: %llu\n", se_cmd->se_tfo->get_fabric_name(), ref_tag); - if (!__target_check_io_state(se_cmd)) { + if (!__target_check_io_state(se_cmd, se_sess, 0)) { spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); target_put_sess_cmd(se_cmd); goto out; @@ -230,7 +244,8 @@ static void core_tmr_drain_tmr_list( spin_lock(&sess->sess_cmd_lock); spin_lock(&cmd->t_state_lock); - if (!(cmd->transport_state & CMD_T_ACTIVE)) { + if (!(cmd->transport_state & CMD_T_ACTIVE) || + (cmd->transport_state & CMD_T_FABRIC_STOP)) { spin_unlock(&cmd->t_state_lock); spin_unlock(&sess->sess_cmd_lock); continue; @@ -240,15 +255,22 @@ static void core_tmr_drain_tmr_list( spin_unlock(&sess->sess_cmd_lock); continue; } + if (sess->sess_tearing_down || cmd->cmd_wait_set) { + spin_unlock(&cmd->t_state_lock); + spin_unlock(&sess->sess_cmd_lock); + continue; + } cmd->transport_state |= CMD_T_ABORTED; spin_unlock(&cmd->t_state_lock); rc = kref_get_unless_zero(&cmd->cmd_kref); - spin_unlock(&sess->sess_cmd_lock); if (!rc) { printk("LUN_RESET TMR: non-zero kref_get_unless_zero\n"); + spin_unlock(&sess->sess_cmd_lock); continue; } + spin_unlock(&sess->sess_cmd_lock); + list_move_tail(&tmr_p->tmr_list, &drain_tmr_list); } spin_unlock_irqrestore(&dev->se_tmr_lock, flags); @@ -325,7 +347,7 @@ static void core_tmr_drain_state_list( continue; spin_lock(&sess->sess_cmd_lock); - rc = __target_check_io_state(cmd); + rc = __target_check_io_state(cmd, tmr_sess, tas); spin_unlock(&sess->sess_cmd_lock); if (!rc) continue; @@ -364,7 +386,7 @@ static void core_tmr_drain_state_list( cancel_work_sync(&cmd->work); transport_wait_for_tasks(cmd); - core_tmr_handle_tas_abort(tmr_sess, cmd, tas); + core_tmr_handle_tas_abort(cmd, tas); target_put_sess_cmd(cmd); } } diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 94e372af9e28..3441b159e306 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2431,18 +2431,33 @@ static void transport_write_pending_qf(struct se_cmd *cmd) } } +static bool +__transport_wait_for_tasks(struct se_cmd *, bool, bool *, bool *, + unsigned long *flags); + +static void target_wait_free_cmd(struct se_cmd *cmd, bool *aborted, bool *tas) +{ + unsigned long flags; + + spin_lock_irqsave(&cmd->t_state_lock, flags); + __transport_wait_for_tasks(cmd, true, aborted, tas, &flags); + spin_unlock_irqrestore(&cmd->t_state_lock, flags); +} + int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks) { int ret = 0; + bool aborted = false, tas = false; if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD)) { if (wait_for_tasks && (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) - transport_wait_for_tasks(cmd); + target_wait_free_cmd(cmd, &aborted, &tas); - ret = transport_put_cmd(cmd); + if (!aborted || tas) + ret = transport_put_cmd(cmd); } else { if (wait_for_tasks) - transport_wait_for_tasks(cmd); + target_wait_free_cmd(cmd, &aborted, &tas); /* * Handle WRITE failure case where transport_generic_new_cmd() * has already added se_cmd to state_list, but fabric has @@ -2454,7 +2469,20 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks) if (cmd->se_lun) transport_lun_remove_cmd(cmd); - ret = transport_put_cmd(cmd); + if (!aborted || tas) + ret = transport_put_cmd(cmd); + } + /* + * If the task has been internally aborted due to TMR ABORT_TASK + * or LUN_RESET, target_core_tmr.c is responsible for performing + * the remaining calls to target_put_sess_cmd(), and not the + * callers of this function. + */ + if (aborted) { + pr_debug("Detected CMD_T_ABORTED for ITT: %llu\n", cmd->tag); + wait_for_completion(&cmd->cmd_wait_comp); + cmd->se_tfo->release_cmd(cmd); + ret = 1; } return ret; } @@ -2509,6 +2537,7 @@ static void target_release_cmd_kref(struct kref *kref) struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref); struct se_session *se_sess = se_cmd->se_sess; unsigned long flags; + bool fabric_stop; spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); if (list_empty(&se_cmd->se_cmd_list)) { @@ -2517,13 +2546,19 @@ static void target_release_cmd_kref(struct kref *kref) se_cmd->se_tfo->release_cmd(se_cmd); return; } - if (se_sess->sess_tearing_down && se_cmd->cmd_wait_set) { + + spin_lock(&se_cmd->t_state_lock); + fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP); + spin_unlock(&se_cmd->t_state_lock); + + if (se_cmd->cmd_wait_set || fabric_stop) { + list_del_init(&se_cmd->se_cmd_list); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); target_free_cmd_mem(se_cmd); complete(&se_cmd->cmd_wait_comp); return; } - list_del(&se_cmd->se_cmd_list); + list_del_init(&se_cmd->se_cmd_list); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); target_free_cmd_mem(se_cmd); @@ -2555,6 +2590,7 @@ void target_sess_cmd_list_set_waiting(struct se_session *se_sess) { struct se_cmd *se_cmd; unsigned long flags; + int rc; spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); if (se_sess->sess_tearing_down) { @@ -2564,8 +2600,15 @@ void target_sess_cmd_list_set_waiting(struct se_session *se_sess) se_sess->sess_tearing_down = 1; list_splice_init(&se_sess->sess_cmd_list, &se_sess->sess_wait_list); - list_for_each_entry(se_cmd, &se_sess->sess_wait_list, se_cmd_list) - se_cmd->cmd_wait_set = 1; + list_for_each_entry(se_cmd, &se_sess->sess_wait_list, se_cmd_list) { + rc = kref_get_unless_zero(&se_cmd->cmd_kref); + if (rc) { + se_cmd->cmd_wait_set = 1; + spin_lock(&se_cmd->t_state_lock); + se_cmd->transport_state |= CMD_T_FABRIC_STOP; + spin_unlock(&se_cmd->t_state_lock); + } + } spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); } @@ -2578,15 +2621,25 @@ void target_wait_for_sess_cmds(struct se_session *se_sess) { struct se_cmd *se_cmd, *tmp_cmd; unsigned long flags; + bool tas; list_for_each_entry_safe(se_cmd, tmp_cmd, &se_sess->sess_wait_list, se_cmd_list) { - list_del(&se_cmd->se_cmd_list); + list_del_init(&se_cmd->se_cmd_list); pr_debug("Waiting for se_cmd: %p t_state: %d, fabric state:" " %d\n", se_cmd, se_cmd->t_state, se_cmd->se_tfo->get_cmd_state(se_cmd)); + spin_lock_irqsave(&se_cmd->t_state_lock, flags); + tas = (se_cmd->transport_state & CMD_T_TAS); + spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); + + if (!target_put_sess_cmd(se_cmd)) { + if (tas) + target_put_sess_cmd(se_cmd); + } + wait_for_completion(&se_cmd->cmd_wait_comp); pr_debug("After cmd_wait_comp: se_cmd: %p t_state: %d" " fabric state: %d\n", se_cmd, se_cmd->t_state, @@ -2608,53 +2661,75 @@ void transport_clear_lun_ref(struct se_lun *lun) wait_for_completion(&lun->lun_ref_comp); } -/** - * transport_wait_for_tasks - wait for completion to occur - * @cmd: command to wait - * - * Called from frontend fabric context to wait for storage engine - * to pause and/or release frontend generated struct se_cmd. - */ -bool transport_wait_for_tasks(struct se_cmd *cmd) +static bool +__transport_wait_for_tasks(struct se_cmd *cmd, bool fabric_stop, + bool *aborted, bool *tas, unsigned long *flags) + __releases(&cmd->t_state_lock) + __acquires(&cmd->t_state_lock) { - unsigned long flags; - spin_lock_irqsave(&cmd->t_state_lock, flags); + assert_spin_locked(&cmd->t_state_lock); + WARN_ON_ONCE(!irqs_disabled()); + + if (fabric_stop) + cmd->transport_state |= CMD_T_FABRIC_STOP; + + if (cmd->transport_state & CMD_T_ABORTED) + *aborted = true; + + if (cmd->transport_state & CMD_T_TAS) + *tas = true; + if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD) && - !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) { - spin_unlock_irqrestore(&cmd->t_state_lock, flags); + !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) return false; - } if (!(cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE) && - !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) { - spin_unlock_irqrestore(&cmd->t_state_lock, flags); + !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) return false; - } - if (!(cmd->transport_state & CMD_T_ACTIVE)) { - spin_unlock_irqrestore(&cmd->t_state_lock, flags); + if (!(cmd->transport_state & CMD_T_ACTIVE)) + return false; + + if (fabric_stop && *aborted) return false; - } cmd->transport_state |= CMD_T_STOP; - pr_debug("wait_for_tasks: Stopping %p ITT: 0x%08llx i_state: %d, t_state: %d, CMD_T_STOP\n", - cmd, cmd->tag, cmd->se_tfo->get_cmd_state(cmd), cmd->t_state); + pr_debug("wait_for_tasks: Stopping %p ITT: 0x%08llx i_state: %d," + " t_state: %d, CMD_T_STOP\n", cmd, cmd->tag, + cmd->se_tfo->get_cmd_state(cmd), cmd->t_state); - spin_unlock_irqrestore(&cmd->t_state_lock, flags); + spin_unlock_irqrestore(&cmd->t_state_lock, *flags); wait_for_completion(&cmd->t_transport_stop_comp); - spin_lock_irqsave(&cmd->t_state_lock, flags); + spin_lock_irqsave(&cmd->t_state_lock, *flags); cmd->transport_state &= ~(CMD_T_ACTIVE | CMD_T_STOP); - pr_debug("wait_for_tasks: Stopped wait_for_completion(&cmd->t_transport_stop_comp) for ITT: 0x%08llx\n", - cmd->tag); + pr_debug("wait_for_tasks: Stopped wait_for_completion(&cmd->" + "t_transport_stop_comp) for ITT: 0x%08llx\n", cmd->tag); + return true; +} + +/** + * transport_wait_for_tasks - wait for completion to occur + * @cmd: command to wait + * + * Called from frontend fabric context to wait for storage engine + * to pause and/or release frontend generated struct se_cmd. + */ +bool transport_wait_for_tasks(struct se_cmd *cmd) +{ + unsigned long flags; + bool ret, aborted = false, tas = false; + + spin_lock_irqsave(&cmd->t_state_lock, flags); + ret = __transport_wait_for_tasks(cmd, false, &aborted, &tas, &flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags); - return true; + return ret; } EXPORT_SYMBOL(transport_wait_for_tasks); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 1a76726c45a2..1579539e5669 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -493,6 +493,8 @@ struct se_cmd { #define CMD_T_DEV_ACTIVE (1 << 7) #define CMD_T_REQUEST_STOP (1 << 8) #define CMD_T_BUSY (1 << 9) +#define CMD_T_TAS (1 << 10) +#define CMD_T_FABRIC_STOP (1 << 11) spinlock_t t_state_lock; struct kref cmd_kref; struct completion t_transport_stop_comp; -- cgit v1.2.3 From d961436c11482e974b702c8324426208f00cd7c4 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Fri, 5 Feb 2016 13:45:12 +0100 Subject: crypto: atmel-sha - fix atmel_sha_remove() Since atmel_sha_probe() uses devm_xxx functions to allocate resources, atmel_sha_remove() should no longer explicitly release them. Cc: stable@vger.kernel.org Signed-off-by: Cyrille Pitchen Fixes: b0e8b3417a62 ("crypto: atmel - use devm_xxx() managed function") Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 20de861aa0ea..b5ab7400008d 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -1483,13 +1483,6 @@ static int atmel_sha_remove(struct platform_device *pdev) if (sha_dd->caps.has_dma) atmel_sha_dma_cleanup(sha_dd); - iounmap(sha_dd->io_base); - - clk_put(sha_dd->iclk); - - if (sha_dd->irq >= 0) - free_irq(sha_dd->irq, sha_dd); - return 0; } -- cgit v1.2.3 From c033042aa8f69894df37dabcaa0231594834a4e4 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Fri, 5 Feb 2016 13:45:13 +0100 Subject: crypto: atmel-sha - remove calls of clk_prepare() from atomic contexts clk_prepare()/clk_unprepare() must not be called within atomic context. This patch calls clk_prepare() once for all from atmel_sha_probe() and clk_unprepare() from atmel_sha_remove(). Then calls of clk_prepare_enable()/clk_disable_unprepare() were replaced by calls of clk_enable()/clk_disable(). Cc: stable@vger.kernel.org Signed-off-by: Cyrille Pitchen Reported-by: Matthias Mayr Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index b5ab7400008d..8bf9914d4d15 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -782,7 +782,7 @@ static void atmel_sha_finish_req(struct ahash_request *req, int err) dd->flags &= ~(SHA_FLAGS_BUSY | SHA_FLAGS_FINAL | SHA_FLAGS_CPU | SHA_FLAGS_DMA_READY | SHA_FLAGS_OUTPUT_READY); - clk_disable_unprepare(dd->iclk); + clk_disable(dd->iclk); if (req->base.complete) req->base.complete(&req->base, err); @@ -795,7 +795,7 @@ static int atmel_sha_hw_init(struct atmel_sha_dev *dd) { int err; - err = clk_prepare_enable(dd->iclk); + err = clk_enable(dd->iclk); if (err) return err; @@ -822,7 +822,7 @@ static void atmel_sha_hw_version_init(struct atmel_sha_dev *dd) dev_info(dd->dev, "version: 0x%x\n", dd->hw_version); - clk_disable_unprepare(dd->iclk); + clk_disable(dd->iclk); } static int atmel_sha_handle_queue(struct atmel_sha_dev *dd, @@ -1410,6 +1410,10 @@ static int atmel_sha_probe(struct platform_device *pdev) goto res_err; } + err = clk_prepare(sha_dd->iclk); + if (err) + goto res_err; + atmel_sha_hw_version_init(sha_dd); atmel_sha_get_cap(sha_dd); @@ -1421,12 +1425,12 @@ static int atmel_sha_probe(struct platform_device *pdev) if (IS_ERR(pdata)) { dev_err(&pdev->dev, "platform data not available\n"); err = PTR_ERR(pdata); - goto res_err; + goto iclk_unprepare; } } if (!pdata->dma_slave) { err = -ENXIO; - goto res_err; + goto iclk_unprepare; } err = atmel_sha_dma_init(sha_dd, pdata); if (err) @@ -1457,6 +1461,8 @@ err_algs: if (sha_dd->caps.has_dma) atmel_sha_dma_cleanup(sha_dd); err_sha_dma: +iclk_unprepare: + clk_unprepare(sha_dd->iclk); res_err: tasklet_kill(&sha_dd->done_task); sha_dd_err: @@ -1483,6 +1489,8 @@ static int atmel_sha_remove(struct platform_device *pdev) if (sha_dd->caps.has_dma) atmel_sha_dma_cleanup(sha_dd); + clk_unprepare(sha_dd->iclk); + return 0; } -- cgit v1.2.3 From 8a3978ad55fb4c0564d285fb2f6cdee2313fce01 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 5 Feb 2016 17:45:48 +0100 Subject: crypto: marvell/cesa - fix test in mv_cesa_dev_dma_init() We are checking twice if dma->cache_pool is not NULL but are never testing dma->padding_pool value. Cc: stable@vger.kernel.org Signed-off-by: Boris Brezillon Signed-off-by: Herbert Xu --- drivers/crypto/marvell/cesa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c index 0643e3366e33..c0656e7f37b5 100644 --- a/drivers/crypto/marvell/cesa.c +++ b/drivers/crypto/marvell/cesa.c @@ -306,7 +306,7 @@ static int mv_cesa_dev_dma_init(struct mv_cesa_dev *cesa) return -ENOMEM; dma->padding_pool = dmam_pool_create("cesa_padding", dev, 72, 1, 0); - if (!dma->cache_pool) + if (!dma->padding_pool) return -ENOMEM; cesa->dma = dma; -- cgit v1.2.3 From 6dae10001e84253992142c7343fdae16a13f3d73 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 1 Feb 2016 21:36:53 +0800 Subject: staging: lustre: Use ahash This patch replaces uses of the long obsolete hash interface with ahash. Signed-off-by: Herbert Xu Acked-by: Greg Kroah-Hartman --- .../lustre/lustre/libcfs/linux/linux-crypto.c | 92 ++++++++++++---------- 1 file changed, 52 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c index 079d50ebfa3a..94c01aad844b 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c @@ -27,7 +27,7 @@ * Copyright (c) 2012, Intel Corporation. */ -#include +#include #include #include "../../../include/linux/libcfs/libcfs.h" #include "linux-crypto.h" @@ -38,9 +38,11 @@ static int cfs_crypto_hash_speeds[CFS_HASH_ALG_MAX]; static int cfs_crypto_hash_alloc(unsigned char alg_id, const struct cfs_crypto_hash_type **type, - struct hash_desc *desc, unsigned char *key, + struct ahash_request **req, + unsigned char *key, unsigned int key_len) { + struct crypto_ahash *tfm; int err = 0; *type = cfs_crypto_hash_type(alg_id); @@ -50,18 +52,23 @@ static int cfs_crypto_hash_alloc(unsigned char alg_id, alg_id, CFS_HASH_ALG_MAX); return -EINVAL; } - desc->tfm = crypto_alloc_hash((*type)->cht_name, 0, 0); + tfm = crypto_alloc_ahash((*type)->cht_name, 0, CRYPTO_ALG_ASYNC); - if (desc->tfm == NULL) - return -EINVAL; - - if (IS_ERR(desc->tfm)) { + if (IS_ERR(tfm)) { CDEBUG(D_INFO, "Failed to alloc crypto hash %s\n", (*type)->cht_name); - return PTR_ERR(desc->tfm); + return PTR_ERR(tfm); } - desc->flags = 0; + *req = ahash_request_alloc(tfm, GFP_KERNEL); + if (!*req) { + CDEBUG(D_INFO, "Failed to alloc ahash_request for %s\n", + (*type)->cht_name); + crypto_free_ahash(tfm); + return -ENOMEM; + } + + ahash_request_set_callback(*req, 0, NULL, NULL); /** Shash have different logic for initialization then digest * shash: crypto_hash_setkey, crypto_hash_init @@ -70,23 +77,27 @@ static int cfs_crypto_hash_alloc(unsigned char alg_id, * cfs_crypto_hash_alloc. */ if (key != NULL) - err = crypto_hash_setkey(desc->tfm, key, key_len); + err = crypto_ahash_setkey(tfm, key, key_len); else if ((*type)->cht_key != 0) - err = crypto_hash_setkey(desc->tfm, + err = crypto_ahash_setkey(tfm, (unsigned char *)&((*type)->cht_key), (*type)->cht_size); if (err != 0) { - crypto_free_hash(desc->tfm); + crypto_free_ahash(tfm); return err; } CDEBUG(D_INFO, "Using crypto hash: %s (%s) speed %d MB/s\n", - (crypto_hash_tfm(desc->tfm))->__crt_alg->cra_name, - (crypto_hash_tfm(desc->tfm))->__crt_alg->cra_driver_name, + crypto_ahash_alg_name(tfm), crypto_ahash_driver_name(tfm), cfs_crypto_hash_speeds[alg_id]); - return crypto_hash_init(desc); + err = crypto_ahash_init(*req); + if (err) { + ahash_request_free(*req); + crypto_free_ahash(tfm); + } + return err; } int cfs_crypto_hash_digest(unsigned char alg_id, @@ -95,27 +106,29 @@ int cfs_crypto_hash_digest(unsigned char alg_id, unsigned char *hash, unsigned int *hash_len) { struct scatterlist sl; - struct hash_desc hdesc; + struct ahash_request *req; int err; const struct cfs_crypto_hash_type *type; if (buf == NULL || buf_len == 0 || hash_len == NULL) return -EINVAL; - err = cfs_crypto_hash_alloc(alg_id, &type, &hdesc, key, key_len); + err = cfs_crypto_hash_alloc(alg_id, &type, &req, key, key_len); if (err != 0) return err; if (hash == NULL || *hash_len < type->cht_size) { *hash_len = type->cht_size; - crypto_free_hash(hdesc.tfm); + crypto_free_ahash(crypto_ahash_reqtfm(req)); + ahash_request_free(req); return -ENOSPC; } sg_init_one(&sl, buf, buf_len); - hdesc.flags = 0; - err = crypto_hash_digest(&hdesc, &sl, sl.length, hash); - crypto_free_hash(hdesc.tfm); + ahash_request_set_crypt(req, &sl, hash, sl.length); + err = crypto_ahash_digest(req); + crypto_free_ahash(crypto_ahash_reqtfm(req)); + ahash_request_free(req); return err; } @@ -125,22 +138,15 @@ struct cfs_crypto_hash_desc * cfs_crypto_hash_init(unsigned char alg_id, unsigned char *key, unsigned int key_len) { - - struct hash_desc *hdesc; + struct ahash_request *req; int err; const struct cfs_crypto_hash_type *type; - hdesc = kmalloc(sizeof(*hdesc), 0); - if (hdesc == NULL) - return ERR_PTR(-ENOMEM); + err = cfs_crypto_hash_alloc(alg_id, &type, &req, key, key_len); - err = cfs_crypto_hash_alloc(alg_id, &type, hdesc, key, key_len); - - if (err) { - kfree(hdesc); + if (err) return ERR_PTR(err); - } - return (struct cfs_crypto_hash_desc *)hdesc; + return (struct cfs_crypto_hash_desc *)req; } EXPORT_SYMBOL(cfs_crypto_hash_init); @@ -148,23 +154,27 @@ int cfs_crypto_hash_update_page(struct cfs_crypto_hash_desc *hdesc, struct page *page, unsigned int offset, unsigned int len) { + struct ahash_request *req = (void *)hdesc; struct scatterlist sl; sg_init_table(&sl, 1); sg_set_page(&sl, page, len, offset & ~CFS_PAGE_MASK); - return crypto_hash_update((struct hash_desc *)hdesc, &sl, sl.length); + ahash_request_set_crypt(req, &sl, NULL, sl.length); + return crypto_ahash_update(req); } EXPORT_SYMBOL(cfs_crypto_hash_update_page); int cfs_crypto_hash_update(struct cfs_crypto_hash_desc *hdesc, const void *buf, unsigned int buf_len) { + struct ahash_request *req = (void *)hdesc; struct scatterlist sl; sg_init_one(&sl, buf, buf_len); - return crypto_hash_update((struct hash_desc *)hdesc, &sl, sl.length); + ahash_request_set_crypt(req, &sl, NULL, sl.length); + return crypto_ahash_update(req); } EXPORT_SYMBOL(cfs_crypto_hash_update); @@ -173,25 +183,27 @@ int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *hdesc, unsigned char *hash, unsigned int *hash_len) { int err; - int size = crypto_hash_digestsize(((struct hash_desc *)hdesc)->tfm); + struct ahash_request *req = (void *)hdesc; + int size = crypto_ahash_digestsize(crypto_ahash_reqtfm(req)); if (hash_len == NULL) { - crypto_free_hash(((struct hash_desc *)hdesc)->tfm); - kfree(hdesc); + crypto_free_ahash(crypto_ahash_reqtfm(req)); + ahash_request_free(req); return 0; } if (hash == NULL || *hash_len < size) { *hash_len = size; return -ENOSPC; } - err = crypto_hash_final((struct hash_desc *) hdesc, hash); + ahash_request_set_crypt(req, NULL, hash, 0); + err = crypto_ahash_final(req); if (err < 0) { /* May be caller can fix error */ return err; } - crypto_free_hash(((struct hash_desc *)hdesc)->tfm); - kfree(hdesc); + crypto_free_ahash(crypto_ahash_reqtfm(req)); + ahash_request_free(req); return err; } EXPORT_SYMBOL(cfs_crypto_hash_final); -- cgit v1.2.3 From f823ab93c518f49c94453bfa9f5c2de6129c9fc6 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 1 Feb 2016 17:39:21 +0000 Subject: crypto: sunxi-ss - prevent compilation on 64-bit The driver for the sunxi-ss crypto engine is not entirely 64-bit safe, compilation on arm64 spits some warnings. The proper fix was deemed to involved [1], so since 64-bit SoCs won't have this IP block we just disable this driver for 64-bit. [1]: http://lists.infradead.org/pipermail/linux-arm-kernel/2016-January/399988.html (and the reply) Signed-off-by: Andre Przywara Acked-by: Corentin LABBE Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 0a6e0b72284b..fed3ffbec4c1 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -488,7 +488,7 @@ config CRYPTO_DEV_IMGTEC_HASH config CRYPTO_DEV_SUN4I_SS tristate "Support for Allwinner Security System cryptographic accelerator" - depends on ARCH_SUNXI + depends on ARCH_SUNXI && !64BIT select CRYPTO_MD5 select CRYPTO_SHA1 select CRYPTO_AES -- cgit v1.2.3 From 53a0bd7144224ba26b326a16e9eaf8bd7f433220 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Mon, 1 Feb 2016 11:17:30 -0800 Subject: crypto: aead - move aead_request_cast helper to aead.h Move the helper function to common header for everybody to use. changes in v2: - move the helper to crypto/internal/aead.h instead of crypto/aead.h Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- drivers/crypto/atmel-aes.c | 6 ------ include/crypto/internal/aead.h | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index 6dd3317ca365..949af89cdac3 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -369,12 +369,6 @@ static inline size_t atmel_aes_padlen(size_t len, size_t block_size) return len ? block_size - len : 0; } -static inline struct aead_request * -aead_request_cast(struct crypto_async_request *req) -{ - return container_of(req, struct aead_request, base); -} - static struct atmel_aes_dev *atmel_aes_find_dev(struct atmel_aes_base_ctx *ctx) { struct atmel_aes_dev *aes_dd = NULL; diff --git a/include/crypto/internal/aead.h b/include/crypto/internal/aead.h index 5554cdd8d6c1..da3864991d4c 100644 --- a/include/crypto/internal/aead.h +++ b/include/crypto/internal/aead.h @@ -80,6 +80,12 @@ static inline u32 aead_request_flags(struct aead_request *req) return req->base.flags; } +static inline struct aead_request *aead_request_cast( + struct crypto_async_request *req) +{ + return container_of(req, struct aead_request, base); +} + static inline void crypto_set_aead_spawn( struct crypto_aead_spawn *spawn, struct crypto_instance *inst) { -- cgit v1.2.3 From b31dde2a5cb1bf764282abf934266b7193c2bc7c Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Tue, 2 Feb 2016 11:38:21 -0600 Subject: crypto: ccp - Don't assume export/import areas are aligned Use a local variable for the exported and imported state so that alignment is not an issue. On export, set a local variable from the request context and then memcpy the contents of the local variable to the export memory area. On import, memcpy the import memory area into a local variable and then use the local variable to set the request context. Cc: # 3.14.x- Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto-aes-cmac.c | 26 ++++++++++++++--------- drivers/crypto/ccp/ccp-crypto-sha.c | 36 +++++++++++++++++++------------- 2 files changed, 37 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c index 6a2d836eb2d9..d095452b8828 100644 --- a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c +++ b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c @@ -223,12 +223,15 @@ static int ccp_aes_cmac_digest(struct ahash_request *req) static int ccp_aes_cmac_export(struct ahash_request *req, void *out) { struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); - struct ccp_aes_cmac_exp_ctx *state = out; + struct ccp_aes_cmac_exp_ctx state; - state->null_msg = rctx->null_msg; - memcpy(state->iv, rctx->iv, sizeof(state->iv)); - state->buf_count = rctx->buf_count; - memcpy(state->buf, rctx->buf, sizeof(state->buf)); + state.null_msg = rctx->null_msg; + memcpy(state.iv, rctx->iv, sizeof(state.iv)); + state.buf_count = rctx->buf_count; + memcpy(state.buf, rctx->buf, sizeof(state.buf)); + + /* 'out' may not be aligned so memcpy from local variable */ + memcpy(out, &state, sizeof(state)); return 0; } @@ -236,12 +239,15 @@ static int ccp_aes_cmac_export(struct ahash_request *req, void *out) static int ccp_aes_cmac_import(struct ahash_request *req, const void *in) { struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); - const struct ccp_aes_cmac_exp_ctx *state = in; + struct ccp_aes_cmac_exp_ctx state; + + /* 'in' may not be aligned so memcpy to local variable */ + memcpy(&state, in, sizeof(state)); - rctx->null_msg = state->null_msg; - memcpy(rctx->iv, state->iv, sizeof(rctx->iv)); - rctx->buf_count = state->buf_count; - memcpy(rctx->buf, state->buf, sizeof(rctx->buf)); + rctx->null_msg = state.null_msg; + memcpy(rctx->iv, state.iv, sizeof(rctx->iv)); + rctx->buf_count = state.buf_count; + memcpy(rctx->buf, state.buf, sizeof(rctx->buf)); return 0; } diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c index a67128a7af23..7002c6b283e5 100644 --- a/drivers/crypto/ccp/ccp-crypto-sha.c +++ b/drivers/crypto/ccp/ccp-crypto-sha.c @@ -210,14 +210,17 @@ static int ccp_sha_digest(struct ahash_request *req) static int ccp_sha_export(struct ahash_request *req, void *out) { struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); - struct ccp_sha_exp_ctx *state = out; + struct ccp_sha_exp_ctx state; - state->type = rctx->type; - state->msg_bits = rctx->msg_bits; - state->first = rctx->first; - memcpy(state->ctx, rctx->ctx, sizeof(state->ctx)); - state->buf_count = rctx->buf_count; - memcpy(state->buf, rctx->buf, sizeof(state->buf)); + state.type = rctx->type; + state.msg_bits = rctx->msg_bits; + state.first = rctx->first; + memcpy(state.ctx, rctx->ctx, sizeof(state.ctx)); + state.buf_count = rctx->buf_count; + memcpy(state.buf, rctx->buf, sizeof(state.buf)); + + /* 'out' may not be aligned so memcpy from local variable */ + memcpy(out, &state, sizeof(state)); return 0; } @@ -225,14 +228,17 @@ static int ccp_sha_export(struct ahash_request *req, void *out) static int ccp_sha_import(struct ahash_request *req, const void *in) { struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); - const struct ccp_sha_exp_ctx *state = in; - - rctx->type = state->type; - rctx->msg_bits = state->msg_bits; - rctx->first = state->first; - memcpy(rctx->ctx, state->ctx, sizeof(rctx->ctx)); - rctx->buf_count = state->buf_count; - memcpy(rctx->buf, state->buf, sizeof(rctx->buf)); + struct ccp_sha_exp_ctx state; + + /* 'in' may not be aligned so memcpy to local variable */ + memcpy(&state, in, sizeof(state)); + + rctx->type = state.type; + rctx->msg_bits = state.msg_bits; + rctx->first = state.first; + memcpy(rctx->ctx, state.ctx, sizeof(rctx->ctx)); + rctx->buf_count = state.buf_count; + memcpy(rctx->buf, state.buf, sizeof(rctx->buf)); return 0; } -- cgit v1.2.3 From 6e56201857fabf0249204704e2a15e6f61d5a05c Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 3 Feb 2016 10:46:50 -0200 Subject: crypto: sahara - remove unneeded mutex in the exported state As pointed out by Herbert Xu we should not include the mutex in the exported state, so let's just get rid of it. Signed-off-by: Fabio Estevam Signed-off-by: Herbert Xu --- drivers/crypto/sahara.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c index 6c4f91c5e6b3..7e8147df6e0d 100644 --- a/drivers/crypto/sahara.c +++ b/drivers/crypto/sahara.c @@ -182,7 +182,6 @@ struct sahara_sha_reqctx { u8 buf[SAHARA_MAX_SHA_BLOCK_SIZE]; u8 rembuf[SAHARA_MAX_SHA_BLOCK_SIZE]; u8 context[SHA256_DIGEST_SIZE + 4]; - struct mutex mutex; unsigned int mode; unsigned int digest_size; unsigned int context_size; @@ -1096,7 +1095,6 @@ static int sahara_sha_enqueue(struct ahash_request *req, int last) if (!req->nbytes && !last) return 0; - mutex_lock(&rctx->mutex); rctx->last = last; if (!rctx->active) { @@ -1109,7 +1107,6 @@ static int sahara_sha_enqueue(struct ahash_request *req, int last) mutex_unlock(&dev->queue_mutex); wake_up_process(dev->kthread); - mutex_unlock(&rctx->mutex); return ret; } @@ -1137,8 +1134,6 @@ static int sahara_sha_init(struct ahash_request *req) rctx->context_size = rctx->digest_size + 4; rctx->active = 0; - mutex_init(&rctx->mutex); - return 0; } -- cgit v1.2.3 From bceab44eed7f37110136860cb2992fbd6702588d Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 3 Feb 2016 10:46:51 -0200 Subject: crypto: sahara - avoid needlessly saving and restoring sahara_ctx Based on commit 434b421241f2d0 ("crypto: caam - avoid needlessly saving and restoring caam_hash_ctx") from Russell King. When exporting and importing the hash state, we will only export and import into hashes which share the same struct crypto_ahash pointer. (See hash_accept->af_alg_accept->hash_accept_parent.) This means that saving the sahara_ctx structure on export, and restoring it on import is a waste of resources. So, remove this code. Signed-off-by: Fabio Estevam Signed-off-by: Herbert Xu --- drivers/crypto/sahara.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c index 7e8147df6e0d..9db09b643a44 100644 --- a/drivers/crypto/sahara.c +++ b/drivers/crypto/sahara.c @@ -1162,26 +1162,18 @@ static int sahara_sha_digest(struct ahash_request *req) static int sahara_sha_export(struct ahash_request *req, void *out) { - struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); - struct sahara_ctx *ctx = crypto_ahash_ctx(ahash); struct sahara_sha_reqctx *rctx = ahash_request_ctx(req); - memcpy(out, ctx, sizeof(struct sahara_ctx)); - memcpy(out + sizeof(struct sahara_sha_reqctx), rctx, - sizeof(struct sahara_sha_reqctx)); + memcpy(out, rctx, sizeof(struct sahara_sha_reqctx)); return 0; } static int sahara_sha_import(struct ahash_request *req, const void *in) { - struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); - struct sahara_ctx *ctx = crypto_ahash_ctx(ahash); struct sahara_sha_reqctx *rctx = ahash_request_ctx(req); - memcpy(ctx, in, sizeof(struct sahara_ctx)); - memcpy(rctx, in + sizeof(struct sahara_sha_reqctx), - sizeof(struct sahara_sha_reqctx)); + memcpy(rctx, in, sizeof(struct sahara_sha_reqctx)); return 0; } -- cgit v1.2.3 From d42cf2f1901e4fafb133d5fb680fc7138b9ba393 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 3 Feb 2016 10:46:52 -0200 Subject: crypto: sahara - fill the statesize field Currently the sahara driver fails to probe: sahara: probe of 63ff8000.crypto failed with error -22 This happens since commit 8996eafdcbad ("crypto: ahash - ensure statesize is non-zero"), which requires statesize to be filled. Pass the statesize members for sha1 and sha256, so we can probe the driver successfully again. Signed-off-by: Fabio Estevam Signed-off-by: Herbert Xu --- drivers/crypto/sahara.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c index 9db09b643a44..c3f3d89e4831 100644 --- a/drivers/crypto/sahara.c +++ b/drivers/crypto/sahara.c @@ -1259,6 +1259,7 @@ static struct ahash_alg sha_v3_algs[] = { .export = sahara_sha_export, .import = sahara_sha_import, .halg.digestsize = SHA1_DIGEST_SIZE, + .halg.statesize = sizeof(struct sahara_sha_reqctx), .halg.base = { .cra_name = "sha1", .cra_driver_name = "sahara-sha1", @@ -1286,6 +1287,7 @@ static struct ahash_alg sha_v4_algs[] = { .export = sahara_sha_export, .import = sahara_sha_import, .halg.digestsize = SHA256_DIGEST_SIZE, + .halg.statesize = sizeof(struct sahara_sha_reqctx), .halg.base = { .cra_name = "sha256", .cra_driver_name = "sahara-sha256", -- cgit v1.2.3 From bb63daf9efb4f2bcb657d7179a53bd808f978dc9 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 1 Feb 2016 18:51:06 -0500 Subject: team: track sum of rx_nohandler for all slaves CC: Jiri Pirko CC: netdev@vger.kernel.org Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/team/team.c | 10 +++++++--- include/linux/if_team.h | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 718ceeab4dbc..00558e139584 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -758,6 +758,8 @@ static rx_handler_result_t team_handle_frame(struct sk_buff **pskb) u64_stats_update_end(&pcpu_stats->syncp); skb->dev = team->dev; + } else if (res == RX_HANDLER_EXACT) { + this_cpu_inc(team->pcpu_stats->rx_nohandler); } else { this_cpu_inc(team->pcpu_stats->rx_dropped); } @@ -1807,7 +1809,7 @@ team_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) struct team *team = netdev_priv(dev); struct team_pcpu_stats *p; u64 rx_packets, rx_bytes, rx_multicast, tx_packets, tx_bytes; - u32 rx_dropped = 0, tx_dropped = 0; + u32 rx_dropped = 0, tx_dropped = 0, rx_nohandler = 0; unsigned int start; int i; @@ -1828,14 +1830,16 @@ team_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) stats->tx_packets += tx_packets; stats->tx_bytes += tx_bytes; /* - * rx_dropped & tx_dropped are u32, updated - * without syncp protection. + * rx_dropped, tx_dropped & rx_nohandler are u32, + * updated without syncp protection. */ rx_dropped += p->rx_dropped; tx_dropped += p->tx_dropped; + rx_nohandler += p->rx_nohandler; } stats->rx_dropped = rx_dropped; stats->tx_dropped = tx_dropped; + stats->rx_nohandler = rx_nohandler; return stats; } diff --git a/include/linux/if_team.h b/include/linux/if_team.h index b84e49c3a738..174f43f43aff 100644 --- a/include/linux/if_team.h +++ b/include/linux/if_team.h @@ -24,6 +24,7 @@ struct team_pcpu_stats { struct u64_stats_sync syncp; u32 rx_dropped; u32 tx_dropped; + u32 rx_nohandler; }; struct team; -- cgit v1.2.3 From f344b0d940d2da88c23b864f818da43081ce300f Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 1 Feb 2016 18:51:07 -0500 Subject: bond: track sum of rx_nohandler for all slaves Sample output with this set applied for an active-backup bond: $ cat /sys/devices/virtual/net/bond0/lower_p7p1/statistics/rx_nohandler 16568 $ cat /sys/devices/virtual/net/bond0/lower_p5p2/statistics/rx_nohandler 16583 $ cat /sys/devices/virtual/net/bond0/statistics/rx_nohandler 33151 CC: Jay Vosburgh CC: Veaceslav Falico CC: Andy Gospodarek CC: netdev@vger.kernel.org Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 56b560558884..6587929b040a 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3309,6 +3309,7 @@ static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev, stats->rx_bytes += sstats->rx_bytes - pstats->rx_bytes; stats->rx_errors += sstats->rx_errors - pstats->rx_errors; stats->rx_dropped += sstats->rx_dropped - pstats->rx_dropped; + stats->rx_nohandler += sstats->rx_nohandler - pstats->rx_nohandler; stats->tx_packets += sstats->tx_packets - pstats->tx_packets;; stats->tx_bytes += sstats->tx_bytes - pstats->tx_bytes; -- cgit v1.2.3 From 387b75f8b31437792e8334390fdf5cf060d1e3da Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 2 Feb 2016 07:47:14 +0100 Subject: bgmac: add helper checking for BCM4707 / BCM53018 chip id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Chipsets with BCM4707 / BCM53018 ID require special handling at a few places in the code. It's likely there will be more IDs to check in the future. To simplify it add this trivial helper. Signed-off-by: Rafał Miłecki Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bgmac.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 06f6cffdfaf5..230f8e6209e5 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -26,6 +26,17 @@ static const struct bcma_device_id bgmac_bcma_tbl[] = { }; MODULE_DEVICE_TABLE(bcma, bgmac_bcma_tbl); +static inline bool bgmac_is_bcm4707_family(struct bgmac *bgmac) +{ + switch (bgmac->core->bus->chipinfo.id) { + case BCMA_CHIP_ID_BCM4707: + case BCMA_CHIP_ID_BCM53018: + return true; + default: + return false; + } +} + static bool bgmac_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value, int timeout) { @@ -987,11 +998,9 @@ static void bgmac_mac_speed(struct bgmac *bgmac) static void bgmac_miiconfig(struct bgmac *bgmac) { struct bcma_device *core = bgmac->core; - struct bcma_chipinfo *ci = &core->bus->chipinfo; u8 imode; - if (ci->id == BCMA_CHIP_ID_BCM4707 || - ci->id == BCMA_CHIP_ID_BCM53018) { + if (bgmac_is_bcm4707_family(bgmac)) { bcma_awrite32(core, BCMA_IOCTL, bcma_aread32(core, BCMA_IOCTL) | 0x40 | BGMAC_BCMA_IOCTL_SW_CLKEN); @@ -1055,9 +1064,7 @@ static void bgmac_chip_reset(struct bgmac *bgmac) } /* Request Misc PLL for corerev > 2 */ - if (core->id.rev > 2 && - ci->id != BCMA_CHIP_ID_BCM4707 && - ci->id != BCMA_CHIP_ID_BCM53018) { + if (core->id.rev > 2 && !bgmac_is_bcm4707_family(bgmac)) { bgmac_set(bgmac, BCMA_CLKCTLST, BGMAC_BCMA_CLKCTLST_MISC_PLL_REQ); bgmac_wait_value(bgmac->core, BCMA_CLKCTLST, @@ -1193,8 +1200,7 @@ static void bgmac_enable(struct bgmac *bgmac) break; } - if (ci->id != BCMA_CHIP_ID_BCM4707 && - ci->id != BCMA_CHIP_ID_BCM53018) { + if (!bgmac_is_bcm4707_family(bgmac)) { rxq_ctl = bgmac_read(bgmac, BGMAC_RXQ_CTL); rxq_ctl &= ~BGMAC_RXQ_CTL_MDP_MASK; bp_clk = bcma_pmu_get_bus_clock(&bgmac->core->bus->drv_cc) / @@ -1472,14 +1478,12 @@ static int bgmac_fixed_phy_register(struct bgmac *bgmac) static int bgmac_mii_register(struct bgmac *bgmac) { - struct bcma_chipinfo *ci = &bgmac->core->bus->chipinfo; struct mii_bus *mii_bus; struct phy_device *phy_dev; char bus_id[MII_BUS_ID_SIZE + 3]; int err = 0; - if (ci->id == BCMA_CHIP_ID_BCM4707 || - ci->id == BCMA_CHIP_ID_BCM53018) + if (bgmac_is_bcm4707_family(bgmac)) return bgmac_fixed_phy_register(bgmac); mii_bus = mdiobus_alloc(); @@ -1539,7 +1543,6 @@ static void bgmac_mii_unregister(struct bgmac *bgmac) /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */ static int bgmac_probe(struct bcma_device *core) { - struct bcma_chipinfo *ci = &core->bus->chipinfo; struct net_device *net_dev; struct bgmac *bgmac; struct ssb_sprom *sprom = &core->bus->sprom; @@ -1620,8 +1623,7 @@ static int bgmac_probe(struct bcma_device *core) bgmac_chip_reset(bgmac); /* For Northstar, we have to take all GMAC core out of reset */ - if (ci->id == BCMA_CHIP_ID_BCM4707 || - ci->id == BCMA_CHIP_ID_BCM53018) { + if (bgmac_is_bcm4707_family(bgmac)) { struct bcma_device *ns_core; int ns_gmac; -- cgit v1.2.3 From c6140a299bdf2425d092383fafaaf2a4a3745989 Mon Sep 17 00:00:00 2001 From: Zhang Shengju Date: Tue, 2 Feb 2016 08:32:55 +0000 Subject: bonding: add slave device name for debug netdev_dbg() will add bond device name, it will be helpful if we print slave device name. Signed-off-by: Zhang Shengju Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6587929b040a..7c9eb6704a7d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -618,8 +618,8 @@ static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active, static void bond_set_dev_addr(struct net_device *bond_dev, struct net_device *slave_dev) { - netdev_dbg(bond_dev, "bond_dev=%p slave_dev=%p slave_dev->addr_len=%d\n", - bond_dev, slave_dev, slave_dev->addr_len); + netdev_dbg(bond_dev, "bond_dev=%p slave_dev=%p slave_dev->name=%s slave_dev->addr_len=%d\n", + bond_dev, slave_dev, slave_dev->name, slave_dev->addr_len); memcpy(bond_dev->dev_addr, slave_dev->dev_addr, slave_dev->addr_len); bond_dev->addr_assign_type = NET_ADDR_STOLEN; call_netdevice_notifiers(NETDEV_CHANGEADDR, bond_dev); -- cgit v1.2.3 From 3647bc35bd427610a70eb83c58c5e834262badfa Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 2 Feb 2016 09:39:02 +0100 Subject: dwc_eth_qos: Reset hardware before PHY start The hardware reset is currently done after phy_start() is called, leading to a race where we can lose the link status if the phy state machine calls dwceqos_adjust_link() before we reset the MAC registers. Acked-by: Lars Persson Signed-off-by: Rabin Vincent Signed-off-by: David S. Miller --- drivers/net/ethernet/synopsys/dwc_eth_qos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/synopsys/dwc_eth_qos.c b/drivers/net/ethernet/synopsys/dwc_eth_qos.c index 70814b7386b3..fc8bbff2d7e3 100644 --- a/drivers/net/ethernet/synopsys/dwc_eth_qos.c +++ b/drivers/net/ethernet/synopsys/dwc_eth_qos.c @@ -1880,9 +1880,9 @@ static int dwceqos_open(struct net_device *ndev) } netdev_reset_queue(ndev); + dwceqos_init_hw(lp); napi_enable(&lp->napi); phy_start(lp->phy_dev); - dwceqos_init_hw(lp); netif_start_queue(ndev); tasklet_enable(&lp->tx_bdreclaim_tasklet); -- cgit v1.2.3 From d76d65fd26951498144029c24852c4d54ee512d9 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 1 Feb 2016 12:58:54 -0600 Subject: rtlwifi: fix broken VHT support When using a 5G-capable device with VHT (802.11ac) rates enabled was not working (packets were not delivered) and the following mac80211 warning was printed: WARNING: CPU: 3 PID: 2253 at net/mac80211/rate.c:625 ieee80211_get_tx_rates+0x22e/0x620 [mac80211]() Modules linked in: rtl8821ae btcoexist rtl_pci rtlwifi fuse drbg ansi_cprng ctr ccm bnep bluetooth af_packet nfs fscache vboxpci(O) vboxnetadp(O) vboxne tflt(O) vboxdrv(O) arc4 snd_hda_codec_generic x86_pkg_temp_thermal rtsx_pci_sdmmc mmc_core rtsx_pci_ms kvm_intel memstick iwlmvm kvm mac80211 snd_hda_intel snd_hda_cod ec snd_hwdep snd_hda_core irqbypass snd_pcm iwlwifi crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel aesni_intel aes_x86_64 snd_timer lrw gf128mul glue_h elper ablk_helper cryptd snd cfg80211 pcspkr serio_raw e1000e rtsx_pci lpc_ich ptp xhci_pci mfd_core pps_core xhci_hcd soundcore toshiba_acpi thermal sparse_keymap wmi toshiba_bluetooth rfkill acpi_cpufreq battery ac processor dm_mod i915 i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm sr_mod cdrom video button sg autofs4 [last unloaded: rtlwifi] CPU: 3 PID: 2253 Comm: Timer Tainted: G W O 4.5.0-rc1-wl+ #79 Hardware name: TOSHIBA TECRA A50-A/TECRA A50-A, BIOS Version 4.20 04/17/2014 ffffffffa05c4be6 ffff8802262036d8 ffffffff813d7912 0000000000000000 ffff880226203710 ffffffff8106bcb6 ffff8800c6831300 ffff8800c6831330 0000000000000000 ffff8800c683133c ffff880065923638 ffff880226203720 Call Trace: [] dump_stack+0x4b/0x79 [] warn_slowpath_common+0x86/0xc0 [] warn_slowpath_null+0x1a/0x20 [] ieee80211_get_tx_rates+0x22e/0x620 [mac80211] [] ? rtl_is_special_data+0x32/0x240 [rtlwifi] [] ? rate_control_get_rate+0xce/0x150 [mac80211] [] ? trace_hardirqs_on+0xd/0x10 [] ? __local_bh_enable_ip+0x65/0xd0 Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rc.c b/drivers/net/wireless/realtek/rtlwifi/rc.c index 74c14ce28238..28f7010e7108 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rc.c +++ b/drivers/net/wireless/realtek/rtlwifi/rc.c @@ -138,6 +138,11 @@ static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv, ((wireless_mode == WIRELESS_MODE_N_5G) || (wireless_mode == WIRELESS_MODE_N_24G))) rate->flags |= IEEE80211_TX_RC_MCS; + if (sta && sta->vht_cap.vht_supported && + (wireless_mode == WIRELESS_MODE_AC_5G || + wireless_mode == WIRELESS_MODE_AC_24G || + wireless_mode == WIRELESS_MODE_AC_ONLY)) + rate->flags |= IEEE80211_TX_RC_VHT_MCS; } } -- cgit v1.2.3 From c89e2e2a0dafde7fb64dfb441a37e93a54cbb844 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 5 Feb 2016 11:32:34 +0100 Subject: staging:iio:ad7606: Consolidate channel specs By slightly reordering the channels in the channel spec array we can reuse the same array for all variant of the chip. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606_core.c | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 2c9d8b7de9f5..263f981da967 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -250,7 +250,8 @@ static const struct attribute_group ad7606_attribute_group_range = { }, \ } -static const struct iio_chan_spec ad7606_8_channels[] = { +static const struct iio_chan_spec ad7606_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(8), AD7606_CHANNEL(0), AD7606_CHANNEL(1), AD7606_CHANNEL(2), @@ -259,25 +260,6 @@ static const struct iio_chan_spec ad7606_8_channels[] = { AD7606_CHANNEL(5), AD7606_CHANNEL(6), AD7606_CHANNEL(7), - IIO_CHAN_SOFT_TIMESTAMP(8), -}; - -static const struct iio_chan_spec ad7606_6_channels[] = { - AD7606_CHANNEL(0), - AD7606_CHANNEL(1), - AD7606_CHANNEL(2), - AD7606_CHANNEL(3), - AD7606_CHANNEL(4), - AD7606_CHANNEL(5), - IIO_CHAN_SOFT_TIMESTAMP(6), -}; - -static const struct iio_chan_spec ad7606_4_channels[] = { - AD7606_CHANNEL(0), - AD7606_CHANNEL(1), - AD7606_CHANNEL(2), - AD7606_CHANNEL(3), - IIO_CHAN_SOFT_TIMESTAMP(4), }; static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { @@ -287,20 +269,20 @@ static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { [ID_AD7606_8] = { .name = "ad7606", .int_vref_mv = 2500, - .channels = ad7606_8_channels, - .num_channels = 8, + .channels = ad7606_channels, + .num_channels = 9, }, [ID_AD7606_6] = { .name = "ad7606-6", .int_vref_mv = 2500, - .channels = ad7606_6_channels, - .num_channels = 6, + .channels = ad7606_channels, + .num_channels = 7, }, [ID_AD7606_4] = { .name = "ad7606-4", .int_vref_mv = 2500, - .channels = ad7606_4_channels, - .num_channels = 4, + .channels = ad7606_channels, + .num_channels = 5, }, }; -- cgit v1.2.3 From 1b3b36b044939b438c4463e8bde8cd644ba82032 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 16 Jan 2016 00:48:32 +0100 Subject: bcma: support identifying MX25L25635F serial flash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's a Macronix 32 MiB flash found on board with BCM47189 SoC. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/driver_chipcommon_sflash.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/bcma/driver_chipcommon_sflash.c b/drivers/bcma/driver_chipcommon_sflash.c index 7e11ef4cb7db..04d706ca5f43 100644 --- a/drivers/bcma/driver_chipcommon_sflash.c +++ b/drivers/bcma/driver_chipcommon_sflash.c @@ -38,6 +38,7 @@ static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { { "M25P32", 0x15, 0x10000, 64, }, { "M25P64", 0x16, 0x10000, 128, }, { "M25FL128", 0x17, 0x10000, 256, }, + { "MX25L25635F", 0x18, 0x10000, 512, }, { NULL }, }; -- cgit v1.2.3 From 7267bcda332e2782e21a559f3b1b859a35b4062d Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 16 Jan 2016 00:48:52 +0100 Subject: bcma: identify bus cores (devices) found on BCM47189 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing defines and print proper names. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/scan.c | 3 +++ include/linux/bcma/bcma.h | 2 ++ 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index df806b9c5490..5ee731132365 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -98,6 +98,9 @@ static const struct bcma_device_id_name bcma_bcm_device_names[] = { { BCMA_CORE_SHIM, "SHIM" }, { BCMA_CORE_PCIE2, "PCIe Gen2" }, { BCMA_CORE_ARM_CR4, "ARM CR4" }, + { BCMA_CORE_GCI, "GCI" }, + { BCMA_CORE_CMEM, "CNDS DDR2/3 memory controller" }, + { BCMA_CORE_ARM_CA7, "ARM CA7" }, { BCMA_CORE_DEFAULT, "Default" }, }; diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 3feb1b2d75d8..991ebb4c2015 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -151,6 +151,8 @@ struct bcma_host_ops { #define BCMA_CORE_PCIE2 0x83C /* PCI Express Gen2 */ #define BCMA_CORE_USB30_DEV 0x83D #define BCMA_CORE_ARM_CR4 0x83E +#define BCMA_CORE_GCI 0x840 +#define BCMA_CORE_CMEM 0x846 /* CNDS DDR2/3 memory controller */ #define BCMA_CORE_ARM_CA7 0x847 #define BCMA_CORE_SYS_MEM 0x849 #define BCMA_CORE_DEFAULT 0xFFF -- cgit v1.2.3 From 0c06f5d43e1f969bae3fa7832a94af46c75db9a7 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 16 Jan 2016 00:48:53 +0100 Subject: bcma: support chipsets with PMU and GCI cores (devices) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both cores are another exceptions. They are not accessed in a standard way and to they don't need or have wrapping addresses. This fixes bus scanning after finding such core. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/scan.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index 5ee731132365..4a2d1b235fb5 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -318,6 +318,8 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, switch (core->id.id) { case BCMA_CORE_4706_MAC_GBIT_COMMON: case BCMA_CORE_NS_CHIPCOMMON_B: + case BCMA_CORE_PMU: + case BCMA_CORE_GCI: /* Not used yet: case BCMA_CORE_OOB_ROUTER: */ break; default: -- cgit v1.2.3 From 67edf354faaf93156646e741483b2313bc756c0f Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 19 Jan 2016 08:45:25 +0100 Subject: bcma: use _PMU_ in all names of PMU registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PMU (Power Management Unit) seems to be a separated piece of hardware, just accessed using ChipCommon core registers. In recent Broadcom chipsets PMU is not bounded to CC but available as separated core. To make code cleaner & easier to review (for a correct R/W access) use clearer names. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/driver_chipcommon_pmu.c | 46 ++++++++++++++--------------- drivers/net/wireless/broadcom/b43/main.c | 8 ++--- include/linux/bcma/bcma_driver_chipcommon.h | 12 ++++---- 3 files changed, 33 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index fe0d48cb1778..472f39dc5a38 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c @@ -15,44 +15,44 @@ u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) { - bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); - return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); + bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); + return bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); } EXPORT_SYMBOL_GPL(bcma_chipco_pll_read); void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) { - bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); - bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value); + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); + bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); } EXPORT_SYMBOL_GPL(bcma_chipco_pll_write); void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, u32 set) { - bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); - bcma_cc_maskset32(cc, BCMA_CC_PLLCTL_DATA, mask, set); + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); + bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); + bcma_cc_maskset32(cc, BCMA_CC_PMU_PLLCTL_DATA, mask, set); } EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset); void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, u32 set) { - bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); - bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL_DATA, mask, set); + bcma_cc_write32(cc, BCMA_CC_PMU_CHIPCTL_ADDR, offset); + bcma_cc_read32(cc, BCMA_CC_PMU_CHIPCTL_ADDR); + bcma_cc_maskset32(cc, BCMA_CC_PMU_CHIPCTL_DATA, mask, set); } EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset); void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, u32 set) { - bcma_cc_write32(cc, BCMA_CC_REGCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_REGCTL_ADDR); - bcma_cc_maskset32(cc, BCMA_CC_REGCTL_DATA, mask, set); + bcma_cc_write32(cc, BCMA_CC_PMU_REGCTL_ADDR, offset); + bcma_cc_read32(cc, BCMA_CC_PMU_REGCTL_ADDR); + bcma_cc_maskset32(cc, BCMA_CC_PMU_REGCTL_DATA, mask, set); } EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); @@ -472,8 +472,8 @@ u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc) static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) { - bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); - bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value); + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); } void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) @@ -497,20 +497,20 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) ? 6 : 0; /* RMW only the P1 divider */ - bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, BCMA_CC_PMU_PLL_CTL0 + phypll_offset); - tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); + tmp = bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); tmp &= (~(BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK)); tmp |= (bcm5357_bcm43236_p1div[spuravoid] << BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT); - bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); /* RMW only the int feedback divider */ - bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, BCMA_CC_PMU_PLL_CTL2 + phypll_offset); - tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); + tmp = bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); tmp &= ~(BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK); tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; - bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); tmp = BCMA_CC_PMU_CTL_PLL_UPD; break; diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c index ec013fbd6a81..c279211e49f9 100644 --- a/drivers/net/wireless/broadcom/b43/main.c +++ b/drivers/net/wireless/broadcom/b43/main.c @@ -1215,10 +1215,10 @@ void b43_wireless_core_phy_pll_reset(struct b43_wldev *dev) case B43_BUS_BCMA: bcma_cc = &dev->dev->bdev->bus->drv_cc; - bcma_cc_write32(bcma_cc, BCMA_CC_CHIPCTL_ADDR, 0); - bcma_cc_mask32(bcma_cc, BCMA_CC_CHIPCTL_DATA, ~0x4); - bcma_cc_set32(bcma_cc, BCMA_CC_CHIPCTL_DATA, 0x4); - bcma_cc_mask32(bcma_cc, BCMA_CC_CHIPCTL_DATA, ~0x4); + bcma_cc_write32(bcma_cc, BCMA_CC_PMU_CHIPCTL_ADDR, 0); + bcma_cc_mask32(bcma_cc, BCMA_CC_PMU_CHIPCTL_DATA, ~0x4); + bcma_cc_set32(bcma_cc, BCMA_CC_PMU_CHIPCTL_DATA, 0x4); + bcma_cc_mask32(bcma_cc, BCMA_CC_PMU_CHIPCTL_DATA, ~0x4); break; #endif #ifdef CONFIG_B43_SSB diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index db51a6ffb7d6..96d8d56f240f 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -351,12 +351,12 @@ #define BCMA_CC_PMU_RES_REQTS 0x0640 /* PMU res req timer sel */ #define BCMA_CC_PMU_RES_REQT 0x0644 /* PMU res req timer */ #define BCMA_CC_PMU_RES_REQM 0x0648 /* PMU res req mask */ -#define BCMA_CC_CHIPCTL_ADDR 0x0650 -#define BCMA_CC_CHIPCTL_DATA 0x0654 -#define BCMA_CC_REGCTL_ADDR 0x0658 -#define BCMA_CC_REGCTL_DATA 0x065C -#define BCMA_CC_PLLCTL_ADDR 0x0660 -#define BCMA_CC_PLLCTL_DATA 0x0664 +#define BCMA_CC_PMU_CHIPCTL_ADDR 0x0650 +#define BCMA_CC_PMU_CHIPCTL_DATA 0x0654 +#define BCMA_CC_PMU_REGCTL_ADDR 0x0658 +#define BCMA_CC_PMU_REGCTL_DATA 0x065C +#define BCMA_CC_PMU_PLLCTL_ADDR 0x0660 +#define BCMA_CC_PMU_PLLCTL_DATA 0x0664 #define BCMA_CC_PMU_STRAPOPT 0x0668 /* (corerev >= 28) */ #define BCMA_CC_PMU_XTAL_FREQ 0x066C /* (pmurev >= 10) */ #define BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK 0x00001FFF -- cgit v1.2.3 From b3c47afbf54d86daa0473895e8ca9e8b663f5c1a Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 19 Jan 2016 08:45:26 +0100 Subject: bcma: support PMU present as separated bus core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On recent Broadcom chipsets PMU is present as separated core and it can't be accessed using ChipCommon anymore as it fails with e.g.: [ 0.000577] Unhandled fault: external abort on non-linefetch (0x1008) at 0xf1000604 Solve it by using a new (PMU) core pointer set to ChipCommon or PMU depending on the hardware capabilities. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/driver_chipcommon.c | 2 +- drivers/bcma/driver_chipcommon_pmu.c | 94 ++++++++++++++++------------- include/linux/bcma/bcma_driver_chipcommon.h | 19 ++++++ 3 files changed, 72 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index b7c8a8d4e6d1..36ee221e298f 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c @@ -185,7 +185,7 @@ u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) ticks = 2; else if (ticks > maxt) ticks = maxt; - bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks); + bcma_pmu_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks); } else { struct bcma_bus *bus = cc->core->bus; diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index 472f39dc5a38..f1eb4d3e1d57 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c @@ -15,44 +15,44 @@ u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) { - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); - return bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); + bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); + return bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); } EXPORT_SYMBOL_GPL(bcma_chipco_pll_read); void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) { - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); + bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); } EXPORT_SYMBOL_GPL(bcma_chipco_pll_write); void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, u32 set) { - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); - bcma_cc_maskset32(cc, BCMA_CC_PMU_PLLCTL_DATA, mask, set); + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); + bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); + bcma_pmu_maskset32(cc, BCMA_CC_PMU_PLLCTL_DATA, mask, set); } EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset); void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, u32 set) { - bcma_cc_write32(cc, BCMA_CC_PMU_CHIPCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_PMU_CHIPCTL_ADDR); - bcma_cc_maskset32(cc, BCMA_CC_PMU_CHIPCTL_DATA, mask, set); + bcma_pmu_write32(cc, BCMA_CC_PMU_CHIPCTL_ADDR, offset); + bcma_pmu_read32(cc, BCMA_CC_PMU_CHIPCTL_ADDR); + bcma_pmu_maskset32(cc, BCMA_CC_PMU_CHIPCTL_DATA, mask, set); } EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset); void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, u32 set) { - bcma_cc_write32(cc, BCMA_CC_PMU_REGCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_PMU_REGCTL_ADDR); - bcma_cc_maskset32(cc, BCMA_CC_PMU_REGCTL_DATA, mask, set); + bcma_pmu_write32(cc, BCMA_CC_PMU_REGCTL_ADDR, offset); + bcma_pmu_read32(cc, BCMA_CC_PMU_REGCTL_ADDR); + bcma_pmu_maskset32(cc, BCMA_CC_PMU_REGCTL_DATA, mask, set); } EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); @@ -60,18 +60,18 @@ static u32 bcma_pmu_xtalfreq(struct bcma_drv_cc *cc) { u32 ilp_ctl, alp_hz; - if (!(bcma_cc_read32(cc, BCMA_CC_PMU_STAT) & + if (!(bcma_pmu_read32(cc, BCMA_CC_PMU_STAT) & BCMA_CC_PMU_STAT_EXT_LPO_AVAIL)) return 0; - bcma_cc_write32(cc, BCMA_CC_PMU_XTAL_FREQ, - BIT(BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT)); + bcma_pmu_write32(cc, BCMA_CC_PMU_XTAL_FREQ, + BIT(BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT)); usleep_range(1000, 2000); - ilp_ctl = bcma_cc_read32(cc, BCMA_CC_PMU_XTAL_FREQ); + ilp_ctl = bcma_pmu_read32(cc, BCMA_CC_PMU_XTAL_FREQ); ilp_ctl &= BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK; - bcma_cc_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 0); + bcma_pmu_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 0); alp_hz = ilp_ctl * 32768 / 4; return (alp_hz + 50000) / 100000 * 100; @@ -127,8 +127,8 @@ static void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq) mask = (u32)~(BCMA_RES_4314_HT_AVAIL | BCMA_RES_4314_MACPHY_CLK_AVAIL); - bcma_cc_mask32(cc, BCMA_CC_PMU_MINRES_MSK, mask); - bcma_cc_mask32(cc, BCMA_CC_PMU_MAXRES_MSK, mask); + bcma_pmu_mask32(cc, BCMA_CC_PMU_MINRES_MSK, mask); + bcma_pmu_mask32(cc, BCMA_CC_PMU_MAXRES_MSK, mask); bcma_wait_value(cc->core, BCMA_CLKCTLST, BCMA_CLKCTLST_HAVEHT, 0, 20000); break; @@ -140,7 +140,7 @@ static void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq) /* Flush */ if (cc->pmu.rev >= 2) - bcma_cc_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD); + bcma_pmu_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD); /* TODO: Do we need to update OTP? */ } @@ -195,9 +195,9 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) /* Set the resource masks. */ if (min_msk) - bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); + bcma_pmu_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); if (max_msk) - bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); + bcma_pmu_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); /* * Add some delay; allow resources to come up and settle. @@ -269,23 +269,33 @@ static void bcma_pmu_workarounds(struct bcma_drv_cc *cc) void bcma_pmu_early_init(struct bcma_drv_cc *cc) { + struct bcma_bus *bus = cc->core->bus; u32 pmucap; - pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP); + if (cc->core->id.rev >= 35 && + cc->capabilities_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) { + cc->pmu.core = bcma_find_core(bus, BCMA_CORE_PMU); + if (!cc->pmu.core) + bcma_warn(bus, "Couldn't find expected PMU core"); + } + if (!cc->pmu.core) + cc->pmu.core = cc->core; + + pmucap = bcma_pmu_read32(cc, BCMA_CC_PMU_CAP); cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION); - bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n", - cc->pmu.rev, pmucap); + bcma_debug(bus, "Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev, + pmucap); } void bcma_pmu_init(struct bcma_drv_cc *cc) { if (cc->pmu.rev == 1) - bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, - ~BCMA_CC_PMU_CTL_NOILPONW); + bcma_pmu_mask32(cc, BCMA_CC_PMU_CTL, + ~BCMA_CC_PMU_CTL_NOILPONW); else - bcma_cc_set32(cc, BCMA_CC_PMU_CTL, - BCMA_CC_PMU_CTL_NOILPONW); + bcma_pmu_set32(cc, BCMA_CC_PMU_CTL, + BCMA_CC_PMU_CTL_NOILPONW); bcma_pmu_pll_init(cc); bcma_pmu_resources_init(cc); @@ -472,8 +482,8 @@ u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc) static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) { - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); } void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) @@ -497,20 +507,20 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) ? 6 : 0; /* RMW only the P1 divider */ - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, BCMA_CC_PMU_PLL_CTL0 + phypll_offset); - tmp = bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); + tmp = bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); tmp &= (~(BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK)); tmp |= (bcm5357_bcm43236_p1div[spuravoid] << BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT); - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); /* RMW only the int feedback divider */ - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, BCMA_CC_PMU_PLL_CTL2 + phypll_offset); - tmp = bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); + tmp = bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); tmp &= ~(BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK); tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); tmp = BCMA_CC_PMU_CTL_PLL_UPD; break; @@ -646,7 +656,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) break; } - tmp |= bcma_cc_read32(cc, BCMA_CC_PMU_CTL); - bcma_cc_write32(cc, BCMA_CC_PMU_CTL, tmp); + tmp |= bcma_pmu_read32(cc, BCMA_CC_PMU_CTL); + bcma_pmu_write32(cc, BCMA_CC_PMU_CTL, tmp); } EXPORT_SYMBOL_GPL(bcma_pmu_spuravoid_pllupdate); diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 96d8d56f240f..700d0c6f7480 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -217,6 +217,11 @@ #define BCMA_CC_CLKDIV_JTAG_SHIFT 8 #define BCMA_CC_CLKDIV_UART 0x000000FF #define BCMA_CC_CAP_EXT 0x00AC /* Capabilities */ +#define BCMA_CC_CAP_EXT_SECI_PRESENT 0x00000001 +#define BCMA_CC_CAP_EXT_GSIO_PRESENT 0x00000002 +#define BCMA_CC_CAP_EXT_GCI_PRESENT 0x00000004 +#define BCMA_CC_CAP_EXT_SECI_PUART_PRESENT 0x00000008 /* UART present */ +#define BCMA_CC_CAP_EXT_AOB_PRESENT 0x00000040 #define BCMA_CC_PLLONDELAY 0x00B0 /* Rev >= 4 only */ #define BCMA_CC_FREFSELDELAY 0x00B4 /* Rev >= 4 only */ #define BCMA_CC_SLOWCLKCTL 0x00B8 /* 6 <= Rev <= 9 only */ @@ -566,6 +571,7 @@ * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) */ struct bcma_chipcommon_pmu { + struct bcma_device *core; /* Can be separated core or just ChipCommon one */ u8 rev; /* PMU revision */ u32 crystalfreq; /* The active crystal frequency (in kHz) */ }; @@ -660,6 +666,19 @@ struct bcma_drv_cc_b { #define bcma_cc_maskset32(cc, offset, mask, set) \ bcma_cc_write32(cc, offset, (bcma_cc_read32(cc, offset) & (mask)) | (set)) +/* PMU registers access */ +#define bcma_pmu_read32(cc, offset) \ + bcma_read32((cc)->pmu.core, offset) +#define bcma_pmu_write32(cc, offset, val) \ + bcma_write32((cc)->pmu.core, offset, val) + +#define bcma_pmu_mask32(cc, offset, mask) \ + bcma_pmu_write32(cc, offset, bcma_pmu_read32(cc, offset) & (mask)) +#define bcma_pmu_set32(cc, offset, set) \ + bcma_pmu_write32(cc, offset, bcma_pmu_read32(cc, offset) | (set)) +#define bcma_pmu_maskset32(cc, offset, mask, set) \ + bcma_pmu_write32(cc, offset, (bcma_pmu_read32(cc, offset) & (mask)) | (set)) + extern u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks); extern u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc); -- cgit v1.2.3 From 36e8072ebeb1981074c7ec1b63bae3ecc3295b4b Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 20 Jan 2016 16:46:04 +0100 Subject: brcmfmac: fix setting primary channel for 80 MHz width MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First of all it changes the way we calculate primary channel offset. If we use e.g. 80 MHz channel with primary frequency 5180 MHz (which means center frequency is 5210 MHz) it makes sense to calculate primary offset as -30 MHz. Then it fixes values we compare primary_offset with. We were comparing offset in MHz against -2 or 2 which was resulting in picking a wrong primary channel. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 23 ++++++++++------------ 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 7b01e4ddb315..d00c5c1d58bf 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -247,7 +247,7 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, brcmf_dbg(TRACE, "chandef: control %d center %d width %d\n", ch->chan->center_freq, ch->center_freq1, ch->width); ch_inf.chnum = ieee80211_frequency_to_channel(ch->center_freq1); - primary_offset = ch->center_freq1 - ch->chan->center_freq; + primary_offset = ch->chan->center_freq - ch->center_freq1; switch (ch->width) { case NL80211_CHAN_WIDTH_20: case NL80211_CHAN_WIDTH_20_NOHT: @@ -256,24 +256,21 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, break; case NL80211_CHAN_WIDTH_40: ch_inf.bw = BRCMU_CHAN_BW_40; - if (primary_offset < 0) + if (primary_offset > 0) ch_inf.sb = BRCMU_CHAN_SB_U; else ch_inf.sb = BRCMU_CHAN_SB_L; break; case NL80211_CHAN_WIDTH_80: ch_inf.bw = BRCMU_CHAN_BW_80; - if (primary_offset < 0) { - if (primary_offset < -CH_10MHZ_APART) - ch_inf.sb = BRCMU_CHAN_SB_UU; - else - ch_inf.sb = BRCMU_CHAN_SB_UL; - } else { - if (primary_offset > CH_10MHZ_APART) - ch_inf.sb = BRCMU_CHAN_SB_LL; - else - ch_inf.sb = BRCMU_CHAN_SB_LU; - } + if (primary_offset == -30) + ch_inf.sb = BRCMU_CHAN_SB_LL; + else if (primary_offset == -10) + ch_inf.sb = BRCMU_CHAN_SB_LU; + else if (primary_offset == 10) + ch_inf.sb = BRCMU_CHAN_SB_UL; + else + ch_inf.sb = BRCMU_CHAN_SB_UU; break; case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_160: -- cgit v1.2.3 From 4c81acab3816c6941900c2abdb412df6cf34bc74 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 22 Jan 2016 18:02:54 +0100 Subject: bcma: init serial console directly from ChipCommon code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UART is connected to and controlled over ChipCommon core. It doesn't have much to do with MIPS core (where we initialize it currently) except just existing on embedded systemms. There isn't point of such cross-core initialization (and we needed #ifdef anyway) so just handle it in ChipCommon. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/bcma_private.h | 1 - drivers/bcma/driver_chipcommon.c | 13 ++++++++++--- drivers/bcma/driver_mips.c | 3 --- 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 38f156745d53..7e4ddfb076d3 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h @@ -48,7 +48,6 @@ void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc); void bcma_core_chipcommon_init(struct bcma_drv_cc *cc); void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable); #ifdef CONFIG_BCMA_DRIVER_MIPS -void bcma_chipco_serial_init(struct bcma_drv_cc *cc); extern struct platform_device bcma_pflash_dev; #endif /* CONFIG_BCMA_DRIVER_MIPS */ diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index 36ee221e298f..bdb73d97da63 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c @@ -15,6 +15,8 @@ #include #include +static void bcma_chipco_serial_init(struct bcma_drv_cc *cc); + static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, u32 mask, u32 value) { @@ -115,6 +117,8 @@ int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc) void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) { + struct bcma_bus *bus = cc->core->bus; + if (cc->early_setup_done) return; @@ -129,6 +133,9 @@ void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) if (cc->capabilities & BCMA_CC_CAP_PMU) bcma_pmu_early_init(cc); + if (IS_BUILTIN(CONFIG_BCM47XX) && bus->hosttype == BCMA_HOSTTYPE_SOC) + bcma_chipco_serial_init(cc); + cc->early_setup_done = true; } @@ -314,9 +321,9 @@ u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value) return res; } -#ifdef CONFIG_BCMA_DRIVER_MIPS -void bcma_chipco_serial_init(struct bcma_drv_cc *cc) +static void bcma_chipco_serial_init(struct bcma_drv_cc *cc) { +#if IS_BUILTIN(CONFIG_BCM47XX) unsigned int irq; u32 baud_base; u32 i; @@ -358,5 +365,5 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc) ports[i].baud_base = baud_base; ports[i].reg_shift = 0; } +#endif /* CONFIG_BCM47XX */ } -#endif /* CONFIG_BCMA_DRIVER_MIPS */ diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c index 24424f3fef96..a40a203314db 100644 --- a/drivers/bcma/driver_mips.c +++ b/drivers/bcma/driver_mips.c @@ -337,12 +337,9 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) { - struct bcma_bus *bus = mcore->core->bus; - if (mcore->early_setup_done) return; - bcma_chipco_serial_init(&bus->drv_cc); bcma_core_mips_flash_detect(mcore); mcore->early_setup_done = true; -- cgit v1.2.3 From 61dba73cdbba8ec5c01b31beaf9e2debc2d2f273 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sun, 24 Jan 2016 16:37:33 +0100 Subject: bcma: add support for BCM47094 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's another SoC with 32 GPIOs and simplified watchdog handling. It was tested on D-Link DIR-885L. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/driver_chipcommon.c | 1 + drivers/bcma/driver_gpio.c | 1 + include/linux/bcma/bcma.h | 1 + 3 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index bdb73d97da63..b0f44a2937b9 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c @@ -197,6 +197,7 @@ u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) struct bcma_bus *bus = cc->core->bus; if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4707 && + bus->chipinfo.id != BCMA_CHIP_ID_BCM47094 && bus->chipinfo.id != BCMA_CHIP_ID_BCM53018) bcma_core_set_clockmode(cc->core, ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC); diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c index 504899a72966..77b0738fbe1b 100644 --- a/drivers/bcma/driver_gpio.c +++ b/drivers/bcma/driver_gpio.c @@ -197,6 +197,7 @@ int bcma_gpio_init(struct bcma_drv_cc *cc) case BCMA_CHIP_ID_BCM4707: case BCMA_CHIP_ID_BCM5357: case BCMA_CHIP_ID_BCM53572: + case BCMA_CHIP_ID_BCM47094: chip->ngpio = 32; break; default: diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 991ebb4c2015..0367c63f5960 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -201,6 +201,7 @@ struct bcma_host_ops { #define BCMA_PKG_ID_BCM4707 1 #define BCMA_PKG_ID_BCM4708 2 #define BCMA_PKG_ID_BCM4709 0 +#define BCMA_CHIP_ID_BCM47094 53030 #define BCMA_CHIP_ID_BCM53018 53018 /* Board types (on PCI usually equals to the subsystem dev id) */ -- cgit v1.2.3 From 515b399c9a204da70d54916d23c1748ff7083fb8 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 26 Jan 2016 17:02:09 +0100 Subject: bcma: claim only 14e4:4365 PCI Dell card with SoftMAC BCM43142 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems 14e4:4365 pattern is too generic as there are two devices: 1) 14e4:4365 1028:0016 with SoftMAC BCM43142 chipset 2) 14e4:4365 14e4:4365 with FullMAC BCM4366 chipset The later one was found in D-Link DIR-885L router and we want to let brcmfmac handle it. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/host_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index 0856189c065f..cae5385cf499 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -294,7 +294,7 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4360) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0016) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a0) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) }, -- cgit v1.2.3 From a4f4abd037c1f8c6a834c95a46a2514d4b350888 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 26 Jan 2016 17:57:01 +0100 Subject: brcmfmac: analyze descriptors of current component only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far we were looking for address descriptors without a check for crossing current component border. In case of dealing with unsupported descriptor or descriptor missing at all the code would incorrectly get data from another component. Consider this binary-described component from BCM4366 EROM: 4bf83b01 TAG==CI CID==0x83b 20080201 TAG==CI PORTS==0+1 WRAPPERS==0+1 18400035 TAG==ADDR SZ_SZD TYPE_SLAVE 00050000 18107085 TAG==ADDR SZ_4K TYPE_SWRAP Driver was assigning invalid base address to this core: brcmfmac: [6 ] core 0x83b:32 base 0x18109000 wrap 0x18107000 which came from totally different component defined in EROM: 43b36701 TAG==CI CID==0x367 00000201 TAG==CI PORTS==0+1 WRAPPERS==0+0 18109005 TAG==ADDR SZ_4K TYPE_SLAVE This change will also allow us to support components without wrapper address in the future. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index 82e4382eb177..e434e2a52098 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -803,7 +803,14 @@ static int brcmf_chip_dmp_get_regaddr(struct brcmf_chip_priv *ci, u32 *eromaddr, *eromaddr -= 4; return -EFAULT; } - } while (desc != DMP_DESC_ADDRESS); + } while (desc != DMP_DESC_ADDRESS && + desc != DMP_DESC_COMPONENT); + + /* stop if we crossed current component border */ + if (desc == DMP_DESC_COMPONENT) { + *eromaddr -= 4; + return 0; + } /* skip upper 32-bit address descriptor */ if (val & DMP_DESC_ADDRSIZE_GT32) -- cgit v1.2.3 From 44977b81823f4801d45d61fb9b278b4483923ae1 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 26 Jan 2016 17:57:02 +0100 Subject: brcmfmac: allow storing PMU core without wrapper address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Separated PMU core can be found in new devices and should be used for accessing PMU registers (which were routed through ChipCommon so far). This core is one of exceptions that doesn't have or need wrapper address to be still safely accessible. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index e434e2a52098..55952d43dfb5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -883,7 +883,8 @@ int brcmf_chip_dmp_erom_scan(struct brcmf_chip_priv *ci) rev = (val & DMP_COMP_REVISION) >> DMP_COMP_REVISION_S; /* need core with ports */ - if (nmw + nsw == 0) + if (nmw + nsw == 0 && + id != BCMA_CORE_PMU) continue; /* try to obtain register address info */ -- cgit v1.2.3 From 9befe9195a17856f8bf5ede7a5c067bd0a281be6 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 26 Jan 2016 17:57:03 +0100 Subject: brcmfmac: read extended capabilities of ChipCommon core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is an extra bitfield with info about some present hardware. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 3 +++ drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h | 2 ++ 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index 55952d43dfb5..f4a4d00cb4a2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -1025,6 +1025,9 @@ static int brcmf_chip_setup(struct brcmf_chip_priv *chip) /* get chipcommon capabilites */ pub->cc_caps = chip->ops->read32(chip->ctx, CORE_CC_REG(base, capabilities)); + pub->cc_caps_ext = chip->ops->read32(chip->ctx, + CORE_CC_REG(base, + capabilities_ext)); /* get pmu caps & rev */ if (pub->cc_caps & CC_CAP_PMU) { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h index f6b5feea23d2..cb9145f1786a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h @@ -27,6 +27,7 @@ * @chip: chip identifier. * @chiprev: chip revision. * @cc_caps: chipcommon core capabilities. + * @cc_caps_ext: chipcommon core extended capabilities. * @pmucaps: PMU capabilities. * @pmurev: PMU revision. * @rambase: RAM base address (only applicable for ARM CR4 chips). @@ -38,6 +39,7 @@ struct brcmf_chip { u32 chip; u32 chiprev; u32 cc_caps; + u32 cc_caps_ext; u32 pmucaps; u32 pmurev; u32 rambase; -- cgit v1.2.3 From e2b397f18cc6423c2dad87f9a633add762d869dd Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 26 Jan 2016 17:57:04 +0100 Subject: brcmfmac: access PMU registers using standalone PMU core if available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On recent Broadcom chipsets PMU is present as separated core and it can't be accessed using ChipCommon anymore as it fails with e.g.: [ 18.198412] Unhandled fault: imprecise external abort (0x1406) at 0xb6da200f Add a new helper function that will return a proper core that should be used for accessing PMU registers. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- .../wireless/broadcom/brcm80211/brcmfmac/chip.c | 30 ++++++++++++++++++---- .../wireless/broadcom/brcm80211/brcmfmac/chip.h | 1 + .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 9 +++---- 3 files changed, 30 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index f4a4d00cb4a2..0e8f2a079907 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -1014,6 +1014,7 @@ static int brcmf_chip_setup(struct brcmf_chip_priv *chip) { struct brcmf_chip *pub; struct brcmf_core_priv *cc; + struct brcmf_core *pmu; u32 base; u32 val; int ret = 0; @@ -1030,9 +1031,10 @@ static int brcmf_chip_setup(struct brcmf_chip_priv *chip) capabilities_ext)); /* get pmu caps & rev */ + pmu = brcmf_chip_get_pmu(pub); /* after reading cc_caps_ext */ if (pub->cc_caps & CC_CAP_PMU) { val = chip->ops->read32(chip->ctx, - CORE_CC_REG(base, pmucapabilities)); + CORE_CC_REG(pmu->base, pmucapabilities)); pub->pmurev = val & PCAP_REV_MASK; pub->pmucaps = val; } @@ -1131,6 +1133,23 @@ struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *pub) return &cc->pub; } +struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub) +{ + struct brcmf_core *cc = brcmf_chip_get_chipcommon(pub); + struct brcmf_core *pmu; + + /* See if there is separated PMU core available */ + if (cc->rev >= 35 && + pub->cc_caps_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) { + pmu = brcmf_chip_get_core(pub, BCMA_CORE_PMU); + if (pmu) + return pmu; + } + + /* Fallback to ChipCommon core for older hardware */ + return cc; +} + bool brcmf_chip_iscoreup(struct brcmf_core *pub) { struct brcmf_core_priv *core; @@ -1301,6 +1320,7 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub) { u32 base, addr, reg, pmu_cc3_mask = ~0; struct brcmf_chip_priv *chip; + struct brcmf_core *pmu = brcmf_chip_get_pmu(pub); brcmf_dbg(TRACE, "Enter\n"); @@ -1320,9 +1340,9 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub) case BRCM_CC_4335_CHIP_ID: case BRCM_CC_4339_CHIP_ID: /* read PMU chipcontrol register 3 */ - addr = CORE_CC_REG(base, chipcontrol_addr); + addr = CORE_CC_REG(pmu->base, chipcontrol_addr); chip->ops->write32(chip->ctx, addr, 3); - addr = CORE_CC_REG(base, chipcontrol_data); + addr = CORE_CC_REG(pmu->base, chipcontrol_data); reg = chip->ops->read32(chip->ctx, addr); return (reg & pmu_cc3_mask) != 0; case BRCM_CC_43430_CHIP_ID: @@ -1330,12 +1350,12 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub) reg = chip->ops->read32(chip->ctx, addr); return reg != 0; default: - addr = CORE_CC_REG(base, pmucapabilities_ext); + addr = CORE_CC_REG(pmu->base, pmucapabilities_ext); reg = chip->ops->read32(chip->ctx, addr); if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0) return false; - addr = CORE_CC_REG(base, retention_ctl); + addr = CORE_CC_REG(pmu->base, retention_ctl); reg = chip->ops->read32(chip->ctx, addr); return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK | PMU_RCTL_LOGIC_DISABLE_MASK)) == 0; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h index cb9145f1786a..dd0ec3eba6a9 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h @@ -85,6 +85,7 @@ struct brcmf_chip *brcmf_chip_attach(void *ctx, void brcmf_chip_detach(struct brcmf_chip *chip); struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *chip, u16 coreid); struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *chip); +struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub); bool brcmf_chip_iscoreup(struct brcmf_core *core); void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset); void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index dd6614332836..80b5d4784645 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -3615,7 +3615,6 @@ brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, const struct sdiod_drive_str *str_tab = NULL; u32 str_mask; u32 str_shift; - u32 base; u32 i; u32 drivestrength_sel = 0; u32 cc_data_temp; @@ -3658,14 +3657,15 @@ brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, } if (str_tab != NULL) { + struct brcmf_core *pmu = brcmf_chip_get_pmu(ci); + for (i = 0; str_tab[i].strength != 0; i++) { if (drivestrength >= str_tab[i].strength) { drivestrength_sel = str_tab[i].sel; break; } } - base = brcmf_chip_get_chipcommon(ci)->base; - addr = CORE_CC_REG(base, chipcontrol_addr); + addr = CORE_CC_REG(pmu->base, chipcontrol_addr); brcmf_sdiod_regwl(sdiodev, addr, 1, NULL); cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL); cc_data_temp &= ~str_mask; @@ -3835,8 +3835,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus) goto fail; /* set PMUControl so a backplane reset does PMU state reload */ - reg_addr = CORE_CC_REG(brcmf_chip_get_chipcommon(bus->ci)->base, - pmucontrol); + reg_addr = CORE_CC_REG(brcmf_chip_get_pmu(bus->ci)->base, pmucontrol); reg_val = brcmf_sdiod_regrl(bus->sdiodev, reg_addr, &err); if (err) goto fail; -- cgit v1.2.3 From f66ab2a7da8ffd78ba26048f8108577ba73a1828 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 26 Jan 2016 17:57:05 +0100 Subject: brcmfmac: add support for 14e4:4365 PCI ID with BCM4366 chipset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Broadcom ARM routers BCM4366 cards are available with 14e4:4365 ID. Unfortunately this ID was already used by Broadcom for cards with BCM43142, a totally different chipset requiring SoftMAC driver. To avoid a conflict between brcmfmac and bcma use more specific ID entry with subvendor and subdevice specified. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 0480b70e3eb8..d5f9ef470447 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -1951,6 +1951,9 @@ static const struct dev_pm_ops brcmf_pciedrvr_pm = { #define BRCMF_PCIE_DEVICE(dev_id) { BRCM_PCIE_VENDOR_ID_BROADCOM, dev_id,\ PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 } +#define BRCMF_PCIE_DEVICE_SUB(dev_id, subvend, subdev) { \ + BRCM_PCIE_VENDOR_ID_BROADCOM, dev_id,\ + subvend, subdev, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 } static struct pci_device_id brcmf_pcie_devid_table[] = { BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID), @@ -1966,6 +1969,7 @@ static struct pci_device_id brcmf_pcie_devid_table[] = { BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID), + BRCMF_PCIE_DEVICE_SUB(0x4365, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4365), BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID), -- cgit v1.2.3 From d1e61b86a2b1b99e5dcd4d41aa23d033b83542a1 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sun, 31 Jan 2016 12:14:34 +0100 Subject: brcmfmac: treat NULL character in NVRAM as separator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Platform NVRAM (stored on a flash partition) has entries separated by a NULL (\0) char. Our parsing code switches from VALUE state to IDLE whenever it meets a NULL (\0). When that happens our IDLE handler should simply consume it and analyze whatever is placed ahead. This fixes harmless warnings spamming debugging output: [ 155.165624] brcmfmac: brcmf_nvram_handle_idle warning: ln=1:col=20: ignoring invalid character [ 155.180806] brcmfmac: brcmf_nvram_handle_idle warning: ln=1:col=44: ignoring invalid character [ 155.195971] brcmfmac: brcmf_nvram_handle_idle warning: ln=1:col=63: ignoring invalid character Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index 1365c12b78fc..7269056d0044 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -93,7 +93,7 @@ static enum nvram_parser_state brcmf_nvram_handle_idle(struct nvram_parser *nvp) c = nvp->data[nvp->pos]; if (c == '\n') return COMMENT; - if (is_whitespace(c)) + if (is_whitespace(c) || c == '\0') goto proceed; if (c == '#') return COMMENT; -- cgit v1.2.3 From 97f1a17109272b9f060cbd6d1d5be41528643000 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Mon, 25 Jan 2016 11:47:29 +0100 Subject: brcmfmac: sdio: Increase the default timeouts a bit On a Radxa Rock2 board with a Ampak AP6335 (Broadcom 4339 core) it seems the card responds very quickly most of the time, unfortunately during initialisation it sometimes seems to take just a bit over 2 seconds to respond. This results intialization failing with message like: brcmf_c_preinit_dcmds: Retreiving cur_etheraddr failed, -52 brcmf_bus_start: failed: -52 brcmf_sdio_firmware_callback: dongle is not responding Increasing the timeout to allow for a bit more headroom allows the card to initialize reliably. A quick search online after diagnosing/fixing this showed that Google has a similar patch in their ChromeOS tree, so this doesn't seem specific to the board I'm using. Signed-off-by: Sjoerd Simons Reviewed-by: Julian Calaby Acked-by: Arend van Spriel Reviewed-by: Douglas Anderson Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 80b5d4784645..6776e45b2958 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -45,8 +45,8 @@ #include "chip.h" #include "firmware.h" -#define DCMD_RESP_TIMEOUT msecs_to_jiffies(2000) -#define CTL_DONE_TIMEOUT msecs_to_jiffies(2000) +#define DCMD_RESP_TIMEOUT msecs_to_jiffies(2500) +#define CTL_DONE_TIMEOUT msecs_to_jiffies(2500) #ifdef DEBUG -- cgit v1.2.3 From 48dc5fb3ba53b20418de8514700f63d88c5de3a3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 28 Jan 2016 22:58:28 +0100 Subject: hostap: avoid uninitialized variable use in hfa384x_get_rid The driver reads a value from hfa384x_from_bap(), which may fail, and then assigns the value to a local variable. gcc detects that in in the failure case, the 'rlen' variable now contains uninitialized data: In file included from ../drivers/net/wireless/intersil/hostap/hostap_pci.c:220:0: drivers/net/wireless/intersil/hostap/hostap_hw.c: In function 'hfa384x_get_rid': drivers/net/wireless/intersil/hostap/hostap_hw.c:842:5: warning: 'rec' may be used uninitialized in this function [-Wmaybe-uninitialized] if (le16_to_cpu(rec.len) == 0) { This restructures the function as suggested by Russell King, to make it more readable and get more reliable error handling, by handling each failure mode using a goto. Signed-off-by: Arnd Bergmann Signed-off-by: Kalle Valo --- drivers/net/wireless/intersil/hostap/hostap_hw.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intersil/hostap/hostap_hw.c b/drivers/net/wireless/intersil/hostap/hostap_hw.c index 6df3ee561d52..515aa3f993f3 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_hw.c +++ b/drivers/net/wireless/intersil/hostap/hostap_hw.c @@ -836,25 +836,30 @@ static int hfa384x_get_rid(struct net_device *dev, u16 rid, void *buf, int len, spin_lock_bh(&local->baplock); res = hfa384x_setup_bap(dev, BAP0, rid, 0); - if (!res) - res = hfa384x_from_bap(dev, BAP0, &rec, sizeof(rec)); + if (res) + goto unlock; + + res = hfa384x_from_bap(dev, BAP0, &rec, sizeof(rec)); + if (res) + goto unlock; if (le16_to_cpu(rec.len) == 0) { /* RID not available */ res = -ENODATA; + goto unlock; } rlen = (le16_to_cpu(rec.len) - 1) * 2; - if (!res && exact_len && rlen != len) { + if (exact_len && rlen != len) { printk(KERN_DEBUG "%s: hfa384x_get_rid - RID len mismatch: " "rid=0x%04x, len=%d (expected %d)\n", dev->name, rid, rlen, len); res = -ENODATA; } - if (!res) - res = hfa384x_from_bap(dev, BAP0, buf, len); + res = hfa384x_from_bap(dev, BAP0, buf, len); +unlock: spin_unlock_bh(&local->baplock); mutex_unlock(&local->rid_bap_mtx); -- cgit v1.2.3 From 44ca509cb9769f27ad8f7d662910e31329eed46f Mon Sep 17 00:00:00 2001 From: Nachiket Kukade Date: Sun, 31 Jan 2016 23:44:46 -0800 Subject: mwifiex: fix bandwidth display problem Instead of using HT info from beacon IEs, use HT info from association response frame to update bandwidth in cfg80211_get_channel handler. Signed-off-by: Nachiket Kukade Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 4 ++-- drivers/net/wireless/marvell/mwifiex/fw.h | 2 +- drivers/net/wireless/marvell/mwifiex/join.c | 15 +++++++++++++++ drivers/net/wireless/marvell/mwifiex/main.h | 2 ++ drivers/net/wireless/marvell/mwifiex/sta_event.c | 3 +++ 5 files changed, 23 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 84615533986c..f2dce81ba36e 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3793,8 +3793,8 @@ static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy, freq = ieee80211_channel_to_frequency(curr_bss->channel, band); chan = ieee80211_get_channel(wiphy, freq); - if (curr_bss->bcn_ht_oper) { - second_chan_offset = curr_bss->bcn_ht_oper->ht_param & + if (priv->ht_param_present) { + second_chan_offset = priv->assoc_resp_ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; chan_type = mwifiex_sec_chan_offset_to_chan_type (second_chan_offset); diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 4af916817bcd..c134cf865291 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -1063,7 +1063,7 @@ struct ieee_types_assoc_rsp { __le16 cap_info_bitmap; __le16 status_code; __le16 a_id; - u8 ie_buffer[1]; + u8 ie_buffer[0]; } __packed; struct host_cmd_ds_802_11_associate_rsp { diff --git a/drivers/net/wireless/marvell/mwifiex/join.c b/drivers/net/wireless/marvell/mwifiex/join.c index cc09a81dbf6a..62211fca91b7 100644 --- a/drivers/net/wireless/marvell/mwifiex/join.c +++ b/drivers/net/wireless/marvell/mwifiex/join.c @@ -644,6 +644,8 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc; bool enable_data = true; u16 cap_info, status_code, aid; + const u8 *ie_ptr; + struct ieee80211_ht_operation *assoc_resp_ht_oper; assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params; @@ -733,6 +735,19 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, = ((bss_desc->wmm_ie.qos_info_bitmap & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) ? 1 : 0); + /* Store the bandwidth information from assoc response */ + ie_ptr = cfg80211_find_ie(WLAN_EID_HT_OPERATION, assoc_rsp->ie_buffer, + priv->assoc_rsp_size + - sizeof(struct ieee_types_assoc_rsp)); + if (ie_ptr) { + assoc_resp_ht_oper = (struct ieee80211_ht_operation *)(ie_ptr + + sizeof(struct ieee_types_header)); + priv->assoc_resp_ht_param = assoc_resp_ht_oper->ht_param; + priv->ht_param_present = true; + } else { + priv->ht_param_present = false; + } + mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_RESP: curr_pkt_filter is %#x\n", priv->curr_pkt_filter); diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index c755be54cc83..89a1576d0a4b 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -674,6 +674,8 @@ struct mwifiex_private { struct mwifiex_ds_mem_rw mem_rw; struct sk_buff_head bypass_txq; struct mwifiex_user_scan_chan hidden_chan[MWIFIEX_USER_SCAN_CHAN_MAX]; + u8 assoc_resp_ht_param; + bool ht_param_present; }; diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c index fd8061c73091..070bce401151 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c @@ -92,6 +92,9 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code) priv->is_data_rate_auto = true; priv->data_rate = 0; + priv->assoc_resp_ht_param = 0; + priv->ht_param_present = false; + if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) && priv->hist_data) mwifiex_hist_data_reset(priv); -- cgit v1.2.3 From efdf0e393e76aa18e9c2ec0ca9b3a71ad410994b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 2 Feb 2016 13:00:05 +0300 Subject: mwifiex: fix a reversed condition The NULL test here is reversed. Fixes: 7d7f07d8c5d3 ('mwifiex: add wowlan net-detect support') Signed-off-by: Dan Carpenter Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index fc8d8ca67453..489f7a911a83 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -2196,7 +2196,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, pmatch = adapter->nd_info->matches[idx]; - if (!pmatch) { + if (pmatch) { memset(pmatch, 0, sizeof(*pmatch)); if (chan_band_tlv) { pmatch->n_channels = 1; -- cgit v1.2.3 From 0a7701b4defcebc7ce461355e6d9478df313b084 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Sat, 30 Jan 2016 18:01:51 +0100 Subject: libertas: fix pointer bugs for PS_MODE commands struct cmd_ds_802_11_ps_mode contains the command header and a pointer to it was initialized with data points to the body which leads to mis-interpretation of the cmd_ds_802_11_ps_mode.action member. cmd[0] contains the header, &cmd[1] points beyond that. cmdnode->cmdbuf is a pointer to the command buffer This piece of code was unused since power saving was not enabled. Signed-off-by: Andreas Kemnade Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/cmd.c | 4 ++-- drivers/net/wireless/marvell/libertas/cmdresp.c | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas/cmd.c b/drivers/net/wireless/marvell/libertas/cmd.c index 0387a5b380c8..40467d646270 100644 --- a/drivers/net/wireless/marvell/libertas/cmd.c +++ b/drivers/net/wireless/marvell/libertas/cmd.c @@ -957,7 +957,7 @@ static void lbs_queue_cmd(struct lbs_private *priv, /* Exit_PS command needs to be queued in the header always. */ if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) { - struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf; + struct cmd_ds_802_11_ps_mode *psm = (void *)cmdnode->cmdbuf; if (psm->action == cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) { if (priv->psstate != PS_STATE_FULL_POWER) @@ -1387,7 +1387,7 @@ int lbs_execute_next_command(struct lbs_private *priv) * PS command. Ignore it if it is not Exit_PS. * otherwise send it down immediately. */ - struct cmd_ds_802_11_ps_mode *psm = (void *)&cmd[1]; + struct cmd_ds_802_11_ps_mode *psm = (void *)cmd; lbs_deb_host( "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n", diff --git a/drivers/net/wireless/marvell/libertas/cmdresp.c b/drivers/net/wireless/marvell/libertas/cmdresp.c index e5442e8956f7..701125f9b060 100644 --- a/drivers/net/wireless/marvell/libertas/cmdresp.c +++ b/drivers/net/wireless/marvell/libertas/cmdresp.c @@ -123,7 +123,10 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) priv->cmd_timed_out = 0; if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) { - struct cmd_ds_802_11_ps_mode *psmode = (void *) &resp[1]; + /* struct cmd_ds_802_11_ps_mode also contains + * the header + */ + struct cmd_ds_802_11_ps_mode *psmode = (void *)resp; u16 action = le16_to_cpu(psmode->action); lbs_deb_host( -- cgit v1.2.3 From fae4f9f78ab11937bc45b0f3625efe2e35aed510 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Sat, 30 Jan 2016 18:01:52 +0100 Subject: libertas: check whether bus can do more than polling If a sdio host does not support sdio irqs, polling is used instead. That has an impact on performance. Some functionality should not be enabled then. This add a variable in libertas_priv to indicate that. Signed-off-by: Andreas Kemnade Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/dev.h | 1 + drivers/net/wireless/marvell/libertas/if_sdio.c | 2 +- drivers/net/wireless/marvell/libertas/if_usb.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas/dev.h b/drivers/net/wireless/marvell/libertas/dev.h index 6bd1608992b0..edf710bc5e77 100644 --- a/drivers/net/wireless/marvell/libertas/dev.h +++ b/drivers/net/wireless/marvell/libertas/dev.h @@ -99,6 +99,7 @@ struct lbs_private { /* Hardware access */ void *card; bool iface_running; + u8 is_polling; /* host has to poll the card irq */ u8 fw_ready; u8 surpriseremoved; u8 setup_fw_on_resume; diff --git a/drivers/net/wireless/marvell/libertas/if_sdio.c b/drivers/net/wireless/marvell/libertas/if_sdio.c index 68fd3a9779bd..13eae9ff8c35 100644 --- a/drivers/net/wireless/marvell/libertas/if_sdio.c +++ b/drivers/net/wireless/marvell/libertas/if_sdio.c @@ -1267,7 +1267,7 @@ static int if_sdio_probe(struct sdio_func *func, priv->reset_card = if_sdio_reset_card; priv->power_save = if_sdio_power_save; priv->power_restore = if_sdio_power_restore; - + priv->is_polling = !(func->card->host->caps & MMC_CAP_SDIO_IRQ); ret = if_sdio_power_on(card); if (ret) goto err_activate_card; diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c index dff08a2896a3..aba0c9995b14 100644 --- a/drivers/net/wireless/marvell/libertas/if_usb.c +++ b/drivers/net/wireless/marvell/libertas/if_usb.c @@ -267,6 +267,7 @@ static int if_usb_probe(struct usb_interface *intf, priv->enter_deep_sleep = NULL; priv->exit_deep_sleep = NULL; priv->reset_deep_sleep_wakeup = NULL; + priv->is_polling = false; #ifdef CONFIG_OLPC if (machine_is_olpc()) priv->reset_card = if_usb_reset_olpc_card; -- cgit v1.2.3 From 57954b94cad77c3253beca805cf493861c7d92b5 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Sat, 30 Jan 2016 18:01:53 +0100 Subject: libertas: do not confirm sleep if commands are pending If the main thread gets one PS AWAKE event and one PS SLEEP event in one iteration over event_fifo there will never be checks for commands to be processed, since psstate will always be PS_STATE_SLEEP or PS_STATE_PRE_SLEEP Signed-off-by: Andreas Kemnade Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/cmdresp.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas/cmdresp.c b/drivers/net/wireless/marvell/libertas/cmdresp.c index 701125f9b060..c95bf6dc9522 100644 --- a/drivers/net/wireless/marvell/libertas/cmdresp.c +++ b/drivers/net/wireless/marvell/libertas/cmdresp.c @@ -257,6 +257,10 @@ int lbs_process_event(struct lbs_private *priv, u32 event) "EVENT: in FULL POWER mode, ignoring PS_SLEEP\n"); break; } + if (!list_empty(&priv->cmdpendingq)) { + lbs_deb_cmd("EVENT: commands in queue, do not sleep\n"); + break; + } priv->psstate = PS_STATE_PRE_SLEEP; lbs_ps_confirm_sleep(priv); -- cgit v1.2.3 From fada24a5477073dd8fa84baf25ead204dc1dcb18 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Sat, 30 Jan 2016 18:01:54 +0100 Subject: libertas: go back to ps mode without commands pending Removes the old todo block and checks only whether ieee powersave mode is requested. We still have to check for being connected as this powersave mode includes logic for regularly waking up and checking for packets which only makes sense when connected. For not being connected, another mode is needed. Signed-off-by: Andreas Kemnade Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/cmd.c | 36 ++++------------------------- 1 file changed, 5 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas/cmd.c b/drivers/net/wireless/marvell/libertas/cmd.c index 40467d646270..4ddd0e5a6b85 100644 --- a/drivers/net/wireless/marvell/libertas/cmd.c +++ b/drivers/net/wireless/marvell/libertas/cmd.c @@ -1428,40 +1428,14 @@ int lbs_execute_next_command(struct lbs_private *priv) * check if in power save mode, if yes, put the device back * to PS mode */ -#ifdef TODO - /* - * This was the old code for libertas+wext. Someone that - * understands this beast should re-code it in a sane way. - * - * I actually don't understand why this is related to WPA - * and to connection status, shouldn't powering should be - * independ of such things? - */ if ((priv->psmode != LBS802_11POWERMODECAM) && (priv->psstate == PS_STATE_FULL_POWER) && - ((priv->connect_status == LBS_CONNECTED) || - lbs_mesh_connected(priv))) { - if (priv->secinfo.WPAenabled || - priv->secinfo.WPA2enabled) { - /* check for valid WPA group keys */ - if (priv->wpa_mcast_key.len || - priv->wpa_unicast_key.len) { - lbs_deb_host( - "EXEC_NEXT_CMD: WPA enabled and GTK_SET" - " go back to PS_SLEEP"); - lbs_set_ps_mode(priv, - PS_MODE_ACTION_ENTER_PS, - false); - } - } else { - lbs_deb_host( - "EXEC_NEXT_CMD: cmdpendingq empty, " - "go back to PS_SLEEP"); - lbs_set_ps_mode(priv, PS_MODE_ACTION_ENTER_PS, - false); - } + (priv->connect_status == LBS_CONNECTED)) { + lbs_deb_host( + "EXEC_NEXT_CMD: cmdpendingq empty, go back to PS_SLEEP"); + lbs_set_ps_mode(priv, PS_MODE_ACTION_ENTER_PS, + false); } -#endif } ret = 0; -- cgit v1.2.3 From 0b8802dc5f59a4517e4130dc3606eb973760928a Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Sat, 30 Jan 2016 18:01:55 +0100 Subject: libertas: fix ps-mode related removal problems When the device is remove e.g. because of going to suspend mode with powersaving enabled, lbs_remove_card tries to exit powersaving state even when already woken up. That command is not processed properly in that situation, since the command processing queue is already stopped, so it waits forever for the command being processed, so disable it. Signed-off-by: Andreas Kemnade Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas/main.c b/drivers/net/wireless/marvell/libertas/main.c index 8079560f4965..b35b8bcce24c 100644 --- a/drivers/net/wireless/marvell/libertas/main.c +++ b/drivers/net/wireless/marvell/libertas/main.c @@ -1060,7 +1060,12 @@ void lbs_remove_card(struct lbs_private *priv) if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { priv->psmode = LBS802_11POWERMODECAM; - lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, true); + /* no need to wakeup if already woken up, + * on suspend, this exit ps command is not processed + * the driver hangs + */ + if (priv->psstate != PS_STATE_FULL_POWER) + lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, true); } if (priv->is_deep_sleep) { -- cgit v1.2.3 From 143e49458424b80fd004963b6ba88ed583ea62da Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Sat, 30 Jan 2016 18:01:56 +0100 Subject: libertas: add an cfg80211 interface for powersaving This patch adds an interface for handling commands like iwconfig wlanX power on/off. Such an interface formerly existed when the driver used wext. While performance with sdio in polling mode without using powersave mode is quite bad, powersaving mode is unusable, so do not enable it under such conditions. Signed-off-by: Andreas Kemnade Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/cfg.c | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas/cfg.c b/drivers/net/wireless/marvell/libertas/cfg.c index 86955c416b30..2eea76a340b7 100644 --- a/drivers/net/wireless/marvell/libertas/cfg.c +++ b/drivers/net/wireless/marvell/libertas/cfg.c @@ -2039,6 +2039,43 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev) +int lbs_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, + bool enabled, int timeout) +{ + struct lbs_private *priv = wiphy_priv(wiphy); + + if (!(priv->fwcapinfo & FW_CAPINFO_PS)) { + if (!enabled) + return 0; + else + return -EINVAL; + } + /* firmware does not work well with too long latency with power saving + * enabled, so do not enable it if there is only polling, no + * interrupts (like in some sdio hosts which can only + * poll for sdio irqs) + */ + if (priv->is_polling) { + if (!enabled) + return 0; + else + return -EINVAL; + } + if (!enabled) { + priv->psmode = LBS802_11POWERMODECAM; + if (priv->psstate != PS_STATE_FULL_POWER) + lbs_set_ps_mode(priv, + PS_MODE_ACTION_EXIT_PS, + true); + return 0; + } + if (priv->psmode != LBS802_11POWERMODECAM) + return 0; + priv->psmode = LBS802_11POWERMODEMAX_PSP; + if (priv->connect_status == LBS_CONNECTED) + lbs_set_ps_mode(priv, PS_MODE_ACTION_ENTER_PS, true); + return 0; +} /* * Initialization @@ -2057,6 +2094,7 @@ static struct cfg80211_ops lbs_cfg80211_ops = { .change_virtual_intf = lbs_change_intf, .join_ibss = lbs_join_ibss, .leave_ibss = lbs_leave_ibss, + .set_power_mgmt = lbs_set_power_mgmt, }; -- cgit v1.2.3 From 478375cedcc0ae5b4cadd29ee5f74c3a5cb5d2ad Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 5 Feb 2016 09:23:32 +0530 Subject: Staging:iio:Remove exceptional & on function name In this file,function names are otherwise used as pointers without &. Found using coccinelle. // @r@ identifier f; @@ f(...) { ... } @@ identifier r.f; @@ - &f + f // Signed-off-by: Bhumika Goyal Signed-off-by: Jonathan Cameron --- drivers/staging/iio/impedance-analyzer/ad5933.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 10c43dda0f5a..d1218d896725 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -558,7 +558,7 @@ out: } static const struct iio_info ad5933_info = { - .read_raw = &ad5933_read_raw, + .read_raw = ad5933_read_raw, .attrs = &ad5933_attribute_group, .driver_module = THIS_MODULE, }; @@ -616,9 +616,9 @@ static int ad5933_ring_postdisable(struct iio_dev *indio_dev) } static const struct iio_buffer_setup_ops ad5933_ring_setup_ops = { - .preenable = &ad5933_ring_preenable, - .postenable = &ad5933_ring_postenable, - .postdisable = &ad5933_ring_postdisable, + .preenable = ad5933_ring_preenable, + .postenable = ad5933_ring_postenable, + .postdisable = ad5933_ring_postdisable, }; static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev) -- cgit v1.2.3 From 1ad1ce9b669095bfe94c32ecd19f2a426837eb93 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Feb 2016 18:50:37 +0200 Subject: iio: pressure: ms5611: Add IIO_CHAN_INFO_SCALE to mask This allows data exported via buffer interface to be converted to standard units in userspace. Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/ms5611_core.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c index 2f3d9b4aca4e..6cf0e55380aa 100644 --- a/drivers/iio/pressure/ms5611_core.c +++ b/drivers/iio/pressure/ms5611_core.c @@ -201,6 +201,18 @@ static int ms5611_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_TEMP: + *val = 10; + return IIO_VAL_INT; + case IIO_PRESSURE: + *val = 0; + *val2 = 1000; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } } return -EINVAL; @@ -218,11 +230,13 @@ static struct ms5611_chip_info chip_info_tbl[] = { static const struct iio_chan_spec ms5611_channels[] = { { .type = IIO_PRESSURE, - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_SCALE), }, { .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_SCALE), } }; -- cgit v1.2.3 From 713bbb4efb9dcda2e96c8338db1f21c68f2d822a Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Feb 2016 18:50:38 +0200 Subject: iio: pressure: ms5611: Add triggered buffer support This will be used together with an external trigger (e.g hrtimer based software trigger). Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/Kconfig | 1 + drivers/iio/pressure/ms5611.h | 1 + drivers/iio/pressure/ms5611_core.c | 74 ++++++++++++++++++++++++++++++++++++-- drivers/iio/pressure/ms5611_i2c.c | 7 ++++ drivers/iio/pressure/ms5611_spi.c | 8 +++++ 5 files changed, 89 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index cf03a43545a1..f15f66d6f527 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -69,6 +69,7 @@ config MPL3115 config MS5611 tristate "Measurement Specialties MS5611 pressure sensor driver" + select IIO_TRIGGERED_BUFFER help Say Y here to build support for the Measurement Specialties MS5611, MS5607 pressure and temperature sensors. diff --git a/drivers/iio/pressure/ms5611.h b/drivers/iio/pressure/ms5611.h index 23b93c797dba..2d70dd6e14b0 100644 --- a/drivers/iio/pressure/ms5611.h +++ b/drivers/iio/pressure/ms5611.h @@ -52,5 +52,6 @@ struct ms5611_state { }; int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, int type); +int ms5611_remove(struct iio_dev *indio_dev); #endif /* _MS5611_H */ diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c index 6cf0e55380aa..c7885f0c819f 100644 --- a/drivers/iio/pressure/ms5611_core.c +++ b/drivers/iio/pressure/ms5611_core.c @@ -17,6 +17,9 @@ #include #include +#include +#include +#include #include "ms5611.h" static bool ms5611_prom_is_valid(u16 *prom, size_t len) @@ -173,6 +176,28 @@ static int ms5611_reset(struct iio_dev *indio_dev) return 0; } +static irqreturn_t ms5611_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct ms5611_state *st = iio_priv(indio_dev); + s32 buf[4]; /* s32 (pressure) + s32 (temp) + 2 * s32 (timestamp) */ + int ret; + + mutex_lock(&st->lock); + ret = ms5611_read_temp_and_pressure(indio_dev, &buf[1], &buf[0]); + mutex_unlock(&st->lock); + if (ret < 0) + goto err; + + iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); + +err: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + static int ms5611_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -218,6 +243,8 @@ static int ms5611_read_raw(struct iio_dev *indio_dev, return -EINVAL; } +static const unsigned long ms5611_scan_masks[] = {0x3, 0}; + static struct ms5611_chip_info chip_info_tbl[] = { [MS5611] = { .temp_and_pressure_compensate = ms5611_temp_and_pressure_compensate, @@ -232,12 +259,27 @@ static const struct iio_chan_spec ms5611_channels[] = { .type = IIO_PRESSURE, .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 32, + .storagebits = 32, + .endianness = IIO_CPU, + }, }, { .type = IIO_TEMP, .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | BIT(IIO_CHAN_INFO_SCALE), - } + .scan_index = 1, + .scan_type = { + .sign = 's', + .realbits = 32, + .storagebits = 32, + .endianness = IIO_CPU, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(2), }; static const struct iio_info ms5611_info = { @@ -269,15 +311,43 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, int type) indio_dev->channels = ms5611_channels; indio_dev->num_channels = ARRAY_SIZE(ms5611_channels); indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->available_scan_masks = ms5611_scan_masks; ret = ms5611_init(indio_dev); if (ret < 0) return ret; - return devm_iio_device_register(dev, indio_dev); + ret = iio_triggered_buffer_setup(indio_dev, NULL, + ms5611_trigger_handler, NULL); + if (ret < 0) { + dev_err(dev, "iio triggered buffer setup failed\n"); + return ret; + } + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(dev, "unable to register iio device\n"); + goto err_buffer_cleanup; + } + + return 0; + +err_buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); + + return ret; } EXPORT_SYMBOL(ms5611_probe); +int ms5611_remove(struct iio_dev *indio_dev) +{ + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + + return 0; +} +EXPORT_SYMBOL(ms5611_remove); + MODULE_AUTHOR("Tomasz Duszynski "); MODULE_DESCRIPTION("MS5611 core driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/pressure/ms5611_i2c.c b/drivers/iio/pressure/ms5611_i2c.c index 245797d1ecf0..42706a89c6ee 100644 --- a/drivers/iio/pressure/ms5611_i2c.c +++ b/drivers/iio/pressure/ms5611_i2c.c @@ -99,6 +99,7 @@ static int ms5611_i2c_probe(struct i2c_client *client, return -ENOMEM; st = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); st->reset = ms5611_i2c_reset; st->read_prom_word = ms5611_i2c_read_prom_word; st->read_adc_temp_and_pressure = ms5611_i2c_read_adc_temp_and_pressure; @@ -107,6 +108,11 @@ static int ms5611_i2c_probe(struct i2c_client *client, return ms5611_probe(indio_dev, &client->dev, id->driver_data); } +static int ms5611_i2c_remove(struct i2c_client *client) +{ + return ms5611_remove(i2c_get_clientdata(client)); +} + static const struct i2c_device_id ms5611_id[] = { { "ms5611", MS5611 }, { "ms5607", MS5607 }, @@ -120,6 +126,7 @@ static struct i2c_driver ms5611_driver = { }, .id_table = ms5611_id, .probe = ms5611_i2c_probe, + .remove = ms5611_i2c_remove, }; module_i2c_driver(ms5611_driver); diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c index aaa0c4ba91a7..c4bf4e8f7c5c 100644 --- a/drivers/iio/pressure/ms5611_spi.c +++ b/drivers/iio/pressure/ms5611_spi.c @@ -90,6 +90,8 @@ static int ms5611_spi_probe(struct spi_device *spi) if (!indio_dev) return -ENOMEM; + spi_set_drvdata(spi, indio_dev); + spi->mode = SPI_MODE_0; spi->max_speed_hz = 20000000; spi->bits_per_word = 8; @@ -107,6 +109,11 @@ static int ms5611_spi_probe(struct spi_device *spi) spi_get_device_id(spi)->driver_data); } +static int ms5611_spi_remove(struct spi_device *spi) +{ + return ms5611_remove(spi_get_drvdata(spi)); +} + static const struct spi_device_id ms5611_id[] = { { "ms5611", MS5611 }, { "ms5607", MS5607 }, @@ -120,6 +127,7 @@ static struct spi_driver ms5611_driver = { }, .id_table = ms5611_id, .probe = ms5611_spi_probe, + .remove = ms5611_spi_remove, }; module_spi_driver(ms5611_driver); -- cgit v1.2.3 From 182b49058e036573ccea37619d90fcaddc983536 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 2 Feb 2016 16:27:24 +0100 Subject: iio: Add helper function for calculating scan index storage size We have the same code for computing the scan index storage size in bytes all over the place. Factor this out into helper functions. Signed-off-by: Lars-Peter Clausen Acked-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 59 +++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 139ae916225f..b976332d45d3 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -512,33 +512,41 @@ static ssize_t iio_buffer_show_enable(struct device *dev, return sprintf(buf, "%d\n", iio_buffer_is_active(indio_dev->buffer)); } +static unsigned int iio_storage_bytes_for_si(struct iio_dev *indio_dev, + unsigned int scan_index) +{ + const struct iio_chan_spec *ch; + unsigned int bytes; + + ch = iio_find_channel_from_si(indio_dev, scan_index); + bytes = ch->scan_type.storagebits / 8; + if (ch->scan_type.repeat > 1) + bytes *= ch->scan_type.repeat; + return bytes; +} + +static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev) +{ + return iio_storage_bytes_for_si(indio_dev, + indio_dev->scan_index_timestamp); +} + static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const unsigned long *mask, bool timestamp) { - const struct iio_chan_spec *ch; unsigned bytes = 0; int length, i; /* How much space will the demuxed element take? */ for_each_set_bit(i, mask, indio_dev->masklength) { - ch = iio_find_channel_from_si(indio_dev, i); - if (ch->scan_type.repeat > 1) - length = ch->scan_type.storagebits / 8 * - ch->scan_type.repeat; - else - length = ch->scan_type.storagebits / 8; + length = iio_storage_bytes_for_si(indio_dev, i); bytes = ALIGN(bytes, length); bytes += length; } + if (timestamp) { - ch = iio_find_channel_from_si(indio_dev, - indio_dev->scan_index_timestamp); - if (ch->scan_type.repeat > 1) - length = ch->scan_type.storagebits / 8 * - ch->scan_type.repeat; - else - length = ch->scan_type.storagebits / 8; + length = iio_storage_bytes_for_timestamp(indio_dev); bytes = ALIGN(bytes, length); bytes += length; } @@ -1288,7 +1296,6 @@ static int iio_buffer_add_demux(struct iio_buffer *buffer, static int iio_buffer_update_demux(struct iio_dev *indio_dev, struct iio_buffer *buffer) { - const struct iio_chan_spec *ch; int ret, in_ind = -1, out_ind, length; unsigned in_loc = 0, out_loc = 0; struct iio_demux_table *p = NULL; @@ -1315,21 +1322,11 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, in_ind = find_next_bit(indio_dev->active_scan_mask, indio_dev->masklength, in_ind + 1); - ch = iio_find_channel_from_si(indio_dev, in_ind); - if (ch->scan_type.repeat > 1) - length = ch->scan_type.storagebits / 8 * - ch->scan_type.repeat; - else - length = ch->scan_type.storagebits / 8; + length = iio_storage_bytes_for_si(indio_dev, in_ind); /* Make sure we are aligned */ in_loc = roundup(in_loc, length) + length; } - ch = iio_find_channel_from_si(indio_dev, in_ind); - if (ch->scan_type.repeat > 1) - length = ch->scan_type.storagebits / 8 * - ch->scan_type.repeat; - else - length = ch->scan_type.storagebits / 8; + length = iio_storage_bytes_for_si(indio_dev, in_ind); out_loc = roundup(out_loc, length); in_loc = roundup(in_loc, length); ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length); @@ -1340,13 +1337,7 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, } /* Relies on scan_timestamp being last */ if (buffer->scan_timestamp) { - ch = iio_find_channel_from_si(indio_dev, - indio_dev->scan_index_timestamp); - if (ch->scan_type.repeat > 1) - length = ch->scan_type.storagebits / 8 * - ch->scan_type.repeat; - else - length = ch->scan_type.storagebits / 8; + length = iio_storage_bytes_for_timestamp(indio_dev); out_loc = roundup(out_loc, length); in_loc = roundup(in_loc, length); ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length); -- cgit v1.2.3 From 3b31b783add21b47bc0314ddf33c9af9247a1d65 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 2 Feb 2016 15:36:39 +0100 Subject: iio: chemical: select IRQ_WORK for ATLAS ph sensor The newly added atlas-ph-sensor driver uses irq_work_queue, which may not always be enabled: ERROR: "irq_work_queue" [drivers/iio/chemical/atlas-ph-sensor.ko] undefined! This adds a 'select' statement to Kconfig to ensure it's there when we need it. Signed-off-by: Arnd Bergmann Fixes: 27dec00ecf2d ("iio: chemical: add Atlas pH-SM sensor support") Reviewed-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/chemical/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig index ce7cd1370f74..f73290f84c90 100644 --- a/drivers/iio/chemical/Kconfig +++ b/drivers/iio/chemical/Kconfig @@ -10,6 +10,7 @@ config ATLAS_PH_SENSOR select REGMAP_I2C select IIO_BUFFER select IIO_TRIGGERED_BUFFER + select IRQ_WORK help Say Y here to build I2C interface support for the Atlas Scientific OEM pH-SM sensor. -- cgit v1.2.3 From b8cc27ca4cce107460fca33acad3f96a8c26e015 Mon Sep 17 00:00:00 2001 From: "Gujulan Elango, Hari Prasath (H.)" Date: Tue, 2 Feb 2016 12:56:32 +0000 Subject: staging: iio: replace clk_get() with devm_clk_get() This patch replaces the clk_get() with devm_clk_get().Accordingly,modified the error paths,rename error labels and removed clk_put() in probe() & remove functions. Signed-off-by: Hari Prasath Gujulan Elango Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/spear_adc.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c index 712cae0e8608..f2c006572783 100644 --- a/drivers/staging/iio/adc/spear_adc.c +++ b/drivers/staging/iio/adc/spear_adc.c @@ -288,7 +288,7 @@ static int spear_adc_probe(struct platform_device *pdev) st->adc_base_spear3xx = (struct adc_regs_spear3xx __iomem *)st->adc_base_spear6xx; - st->clk = clk_get(dev, NULL); + st->clk = devm_clk_get(dev, NULL); if (IS_ERR(st->clk)) { dev_err(dev, "failed getting clock\n"); goto errout1; @@ -297,28 +297,28 @@ static int spear_adc_probe(struct platform_device *pdev) ret = clk_prepare_enable(st->clk); if (ret) { dev_err(dev, "failed enabling clock\n"); - goto errout2; + goto errout1; } irq = platform_get_irq(pdev, 0); if (irq <= 0) { dev_err(dev, "failed getting interrupt resource\n"); ret = -EINVAL; - goto errout3; + goto errout2; } ret = devm_request_irq(dev, irq, spear_adc_isr, 0, SPEAR_ADC_MOD_NAME, st); if (ret < 0) { dev_err(dev, "failed requesting interrupt\n"); - goto errout3; + goto errout2; } if (of_property_read_u32(np, "sampling-frequency", &st->sampling_freq)) { dev_err(dev, "sampling-frequency missing in DT\n"); ret = -EINVAL; - goto errout3; + goto errout2; } /* @@ -348,16 +348,14 @@ static int spear_adc_probe(struct platform_device *pdev) ret = iio_device_register(indio_dev); if (ret) - goto errout3; + goto errout2; dev_info(dev, "SPEAR ADC driver loaded, IRQ %d\n", irq); return 0; -errout3: - clk_disable_unprepare(st->clk); errout2: - clk_put(st->clk); + clk_disable_unprepare(st->clk); errout1: iounmap(st->adc_base_spear6xx); return ret; @@ -370,7 +368,6 @@ static int spear_adc_remove(struct platform_device *pdev) iio_device_unregister(indio_dev); clk_disable_unprepare(st->clk); - clk_put(st->clk); iounmap(st->adc_base_spear6xx); return 0; -- cgit v1.2.3 From 87aec56e27efac98b7a0abe93258687716bf0b1e Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Tue, 2 Feb 2016 11:50:44 -0600 Subject: iio: health: Add driver for the TI AFE4404 heart monitor Add driver for the TI AFE4404 heart rate monitor and pulse oximeter. This device detects reflected LED light fluctuations and presents an ADC value to the user space for further signal processing. Datasheet: http://www.ti.com/product/AFE4404/datasheet Signed-off-by: Andrew F. Davis Signed-off-by: Jonathan Cameron --- .../ABI/testing/sysfs-bus-iio-health-afe440x | 54 ++ drivers/iio/health/Kconfig | 19 +- drivers/iio/health/Makefile | 1 + drivers/iio/health/afe4404.c | 679 +++++++++++++++++++++ drivers/iio/health/afe440x.h | 191 ++++++ 5 files changed, 943 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-health-afe440x create mode 100644 drivers/iio/health/afe4404.c create mode 100644 drivers/iio/health/afe440x.h (limited to 'drivers') diff --git a/Documentation/ABI/testing/sysfs-bus-iio-health-afe440x b/Documentation/ABI/testing/sysfs-bus-iio-health-afe440x new file mode 100644 index 000000000000..3740f253d406 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-health-afe440x @@ -0,0 +1,54 @@ +What: /sys/bus/iio/devices/iio:deviceX/tia_resistanceY + /sys/bus/iio/devices/iio:deviceX/tia_capacitanceY +Date: December 2015 +KernelVersion: +Contact: Andrew F. Davis +Description: + Get and set the resistance and the capacitance settings for the + Transimpedance Amplifier. Y is 1 for Rf1 and Cf1, Y is 2 for + Rf2 and Cf2 values. + +What: /sys/bus/iio/devices/iio:deviceX/tia_separate_en +Date: December 2015 +KernelVersion: +Contact: Andrew F. Davis +Description: + Enable or disable separate settings for the TransImpedance + Amplifier above, when disabled both values are set by the + first channel. + +What: /sys/bus/iio/devices/iio:deviceX/in_intensity_ledY_raw + /sys/bus/iio/devices/iio:deviceX/in_intensity_ledY_ambient_raw +Date: December 2015 +KernelVersion: +Contact: Andrew F. Davis +Description: + Get measured values from the ADC for these stages. Y is the + specific LED number. The values are expressed in 24-bit twos + complement. + +What: /sys/bus/iio/devices/iio:deviceX/in_intensity_ledY-ledY_ambient_raw +Date: December 2015 +KernelVersion: +Contact: Andrew F. Davis +Description: + Get differential values from the ADC for these stages. Y is the + specific LED number. The values are expressed in 24-bit twos + complement for the specified LEDs. + +What: /sys/bus/iio/devices/iio:deviceX/out_current_ledY_offset + /sys/bus/iio/devices/iio:deviceX/out_current_ledY_ambient_offset +Date: December 2015 +KernelVersion: +Contact: Andrew F. Davis +Description: + Get and set the offset cancellation DAC setting for these + stages. The values are expressed in 5-bit sign-magnitude. + +What: /sys/bus/iio/devices/iio:deviceX/out_current_ledY_raw +Date: December 2015 +KernelVersion: +Contact: Andrew F. Davis +Description: + Get and set the LED current for the specified LED. Y is the + specific LED number. diff --git a/drivers/iio/health/Kconfig b/drivers/iio/health/Kconfig index a647679da805..632a14b7dd6f 100644 --- a/drivers/iio/health/Kconfig +++ b/drivers/iio/health/Kconfig @@ -3,7 +3,22 @@ # # When adding new entries keep the list in alphabetical order -menu "Health sensors" +menu "Health Sensors" + +menu "Heart Rate Monitors" + +config AFE4404 + tristate "TI AFE4404 heart rate and pulse oximeter sensor" + depends on I2C + select REGMAP_I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes to choose the Texas Instruments AFE4404 + heart rate monitor and low-cost pulse oximeter. + + To compile this driver as a module, choose M here: the + module will be called afe4404. config MAX30100 tristate "MAX30100 heart rate and pulse oximeter sensor" @@ -19,3 +34,5 @@ config MAX30100 module will be called max30100. endmenu + +endmenu diff --git a/drivers/iio/health/Makefile b/drivers/iio/health/Makefile index 7c475d7faad8..b37c0d5e07b8 100644 --- a/drivers/iio/health/Makefile +++ b/drivers/iio/health/Makefile @@ -4,4 +4,5 @@ # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_AFE4404) += afe4404.o obj-$(CONFIG_MAX30100) += max30100.o diff --git a/drivers/iio/health/afe4404.c b/drivers/iio/health/afe4404.c new file mode 100644 index 000000000000..0759268f37e0 --- /dev/null +++ b/drivers/iio/health/afe4404.c @@ -0,0 +1,679 @@ +/* + * AFE4404 Heart Rate Monitors and Low-Cost Pulse Oximeters + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * 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. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "afe440x.h" + +#define AFE4404_DRIVER_NAME "afe4404" + +/* AFE4404 registers */ +#define AFE4404_TIA_GAIN_SEP 0x20 +#define AFE4404_TIA_GAIN 0x21 +#define AFE4404_PROG_TG_STC 0x34 +#define AFE4404_PROG_TG_ENDC 0x35 +#define AFE4404_LED3LEDSTC 0x36 +#define AFE4404_LED3LEDENDC 0x37 +#define AFE4404_CLKDIV_PRF 0x39 +#define AFE4404_OFFDAC 0x3a +#define AFE4404_DEC 0x3d +#define AFE4404_AVG_LED2_ALED2VAL 0x3f +#define AFE4404_AVG_LED1_ALED1VAL 0x40 + +/* AFE4404 GAIN register fields */ +#define AFE4404_TIA_GAIN_RES_MASK GENMASK(2, 0) +#define AFE4404_TIA_GAIN_RES_SHIFT 0 +#define AFE4404_TIA_GAIN_CAP_MASK GENMASK(5, 3) +#define AFE4404_TIA_GAIN_CAP_SHIFT 3 + +/* AFE4404 LEDCNTRL register fields */ +#define AFE4404_LEDCNTRL_ILED1_MASK GENMASK(5, 0) +#define AFE4404_LEDCNTRL_ILED1_SHIFT 0 +#define AFE4404_LEDCNTRL_ILED2_MASK GENMASK(11, 6) +#define AFE4404_LEDCNTRL_ILED2_SHIFT 6 +#define AFE4404_LEDCNTRL_ILED3_MASK GENMASK(17, 12) +#define AFE4404_LEDCNTRL_ILED3_SHIFT 12 + +/* AFE4404 CONTROL2 register fields */ +#define AFE440X_CONTROL2_ILED_2X_MASK BIT(17) +#define AFE440X_CONTROL2_ILED_2X_SHIFT 17 + +/* AFE4404 CONTROL3 register fields */ +#define AFE440X_CONTROL3_OSC_ENABLE BIT(9) + +/* AFE4404 OFFDAC register current fields */ +#define AFE4404_OFFDAC_CURR_LED1_MASK GENMASK(9, 5) +#define AFE4404_OFFDAC_CURR_LED1_SHIFT 5 +#define AFE4404_OFFDAC_CURR_LED2_MASK GENMASK(19, 15) +#define AFE4404_OFFDAC_CURR_LED2_SHIFT 15 +#define AFE4404_OFFDAC_CURR_LED3_MASK GENMASK(4, 0) +#define AFE4404_OFFDAC_CURR_LED3_SHIFT 0 +#define AFE4404_OFFDAC_CURR_ALED1_MASK GENMASK(14, 10) +#define AFE4404_OFFDAC_CURR_ALED1_SHIFT 10 +#define AFE4404_OFFDAC_CURR_ALED2_MASK GENMASK(4, 0) +#define AFE4404_OFFDAC_CURR_ALED2_SHIFT 0 + +/* AFE4404 NULL fields */ +#define NULL_MASK 0 +#define NULL_SHIFT 0 + +/* AFE4404 TIA_GAIN_CAP values */ +#define AFE4404_TIA_GAIN_CAP_5_P 0x0 +#define AFE4404_TIA_GAIN_CAP_2_5_P 0x1 +#define AFE4404_TIA_GAIN_CAP_10_P 0x2 +#define AFE4404_TIA_GAIN_CAP_7_5_P 0x3 +#define AFE4404_TIA_GAIN_CAP_20_P 0x4 +#define AFE4404_TIA_GAIN_CAP_17_5_P 0x5 +#define AFE4404_TIA_GAIN_CAP_25_P 0x6 +#define AFE4404_TIA_GAIN_CAP_22_5_P 0x7 + +/* AFE4404 TIA_GAIN_RES values */ +#define AFE4404_TIA_GAIN_RES_500_K 0x0 +#define AFE4404_TIA_GAIN_RES_250_K 0x1 +#define AFE4404_TIA_GAIN_RES_100_K 0x2 +#define AFE4404_TIA_GAIN_RES_50_K 0x3 +#define AFE4404_TIA_GAIN_RES_25_K 0x4 +#define AFE4404_TIA_GAIN_RES_10_K 0x5 +#define AFE4404_TIA_GAIN_RES_1_M 0x6 +#define AFE4404_TIA_GAIN_RES_2_M 0x7 + +/** + * struct afe4404_data + * @dev - Device structure + * @regmap - Register map of the device + * @regulator - Pointer to the regulator for the IC + * @trig - IIO trigger for this device + * @irq - ADC_RDY line interrupt number + */ +struct afe4404_data { + struct device *dev; + struct regmap *regmap; + struct regulator *regulator; + struct iio_trigger *trig; + int irq; +}; + +enum afe4404_chan_id { + LED1, + ALED1, + LED2, + ALED2, + LED3, + LED1_ALED1, + LED2_ALED2, + ILED1, + ILED2, + ILED3, +}; + +static const struct afe440x_reg_info afe4404_reg_info[] = { + [LED1] = AFE440X_REG_INFO(AFE440X_LED1VAL, AFE4404_OFFDAC, AFE4404_OFFDAC_CURR_LED1), + [ALED1] = AFE440X_REG_INFO(AFE440X_ALED1VAL, AFE4404_OFFDAC, AFE4404_OFFDAC_CURR_ALED1), + [LED2] = AFE440X_REG_INFO(AFE440X_LED2VAL, AFE4404_OFFDAC, AFE4404_OFFDAC_CURR_LED2), + [ALED2] = AFE440X_REG_INFO(AFE440X_ALED2VAL, AFE4404_OFFDAC, AFE4404_OFFDAC_CURR_ALED2), + [LED3] = AFE440X_REG_INFO(AFE440X_ALED2VAL, 0, NULL), + [LED1_ALED1] = AFE440X_REG_INFO(AFE440X_LED1_ALED1VAL, 0, NULL), + [LED2_ALED2] = AFE440X_REG_INFO(AFE440X_LED2_ALED2VAL, 0, NULL), + [ILED1] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE4404_LEDCNTRL_ILED1), + [ILED2] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE4404_LEDCNTRL_ILED2), + [ILED3] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE4404_LEDCNTRL_ILED3), +}; + +static const struct iio_chan_spec afe4404_channels[] = { + /* ADC values */ + AFE440X_INTENSITY_CHAN(LED1, "led1", BIT(IIO_CHAN_INFO_OFFSET)), + AFE440X_INTENSITY_CHAN(ALED1, "led1_ambient", BIT(IIO_CHAN_INFO_OFFSET)), + AFE440X_INTENSITY_CHAN(LED2, "led2", BIT(IIO_CHAN_INFO_OFFSET)), + AFE440X_INTENSITY_CHAN(ALED2, "led2_ambient", BIT(IIO_CHAN_INFO_OFFSET)), + AFE440X_INTENSITY_CHAN(LED3, "led3", BIT(IIO_CHAN_INFO_OFFSET)), + AFE440X_INTENSITY_CHAN(LED1_ALED1, "led1-led1_ambient", 0), + AFE440X_INTENSITY_CHAN(LED2_ALED2, "led2-led2_ambient", 0), + /* LED current */ + AFE440X_CURRENT_CHAN(ILED1, "led1"), + AFE440X_CURRENT_CHAN(ILED2, "led2"), + AFE440X_CURRENT_CHAN(ILED3, "led3"), +}; + +static const struct afe440x_val_table afe4404_res_table[] = { + { .integer = 500000, .fract = 0 }, + { .integer = 250000, .fract = 0 }, + { .integer = 100000, .fract = 0 }, + { .integer = 50000, .fract = 0 }, + { .integer = 25000, .fract = 0 }, + { .integer = 10000, .fract = 0 }, + { .integer = 1000000, .fract = 0 }, + { .integer = 2000000, .fract = 0 }, +}; +AFE440X_TABLE_ATTR(tia_resistance_available, afe4404_res_table); + +static const struct afe440x_val_table afe4404_cap_table[] = { + { .integer = 0, .fract = 5000 }, + { .integer = 0, .fract = 2500 }, + { .integer = 0, .fract = 10000 }, + { .integer = 0, .fract = 7500 }, + { .integer = 0, .fract = 20000 }, + { .integer = 0, .fract = 17500 }, + { .integer = 0, .fract = 25000 }, + { .integer = 0, .fract = 22500 }, +}; +AFE440X_TABLE_ATTR(tia_capacitance_available, afe4404_cap_table); + +static ssize_t afe440x_show_register(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct afe4404_data *afe = iio_priv(indio_dev); + struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr); + unsigned int reg_val, type; + int vals[2]; + int ret, val_len; + + ret = regmap_read(afe->regmap, afe440x_attr->reg, ®_val); + if (ret) + return ret; + + reg_val &= afe440x_attr->mask; + reg_val >>= afe440x_attr->shift; + + switch (afe440x_attr->type) { + case SIMPLE: + type = IIO_VAL_INT; + val_len = 1; + vals[0] = reg_val; + break; + case RESISTANCE: + case CAPACITANCE: + type = IIO_VAL_INT_PLUS_MICRO; + val_len = 2; + if (reg_val < afe440x_attr->table_size) { + vals[0] = afe440x_attr->val_table[reg_val].integer; + vals[1] = afe440x_attr->val_table[reg_val].fract; + break; + } + return -EINVAL; + default: + return -EINVAL; + } + + return iio_format_value(buf, type, val_len, vals); +} + +static ssize_t afe440x_store_register(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct afe4404_data *afe = iio_priv(indio_dev); + struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr); + int val, integer, fract, ret; + + ret = iio_str_to_fixpoint(buf, 100000, &integer, &fract); + if (ret) + return ret; + + switch (afe440x_attr->type) { + case SIMPLE: + val = integer; + break; + case RESISTANCE: + case CAPACITANCE: + for (val = 0; val < afe440x_attr->table_size; val++) + if (afe440x_attr->val_table[val].integer == integer && + afe440x_attr->val_table[val].fract == fract) + break; + if (val == afe440x_attr->table_size) + return -EINVAL; + break; + default: + return -EINVAL; + } + + ret = regmap_update_bits(afe->regmap, afe440x_attr->reg, + afe440x_attr->mask, + (val << afe440x_attr->shift)); + if (ret) + return ret; + + return count; +} + +static AFE440X_ATTR(tia_separate_en, AFE4404_TIA_GAIN_SEP, AFE440X_TIAGAIN_ENSEPGAIN, SIMPLE, NULL, 0); + +static AFE440X_ATTR(tia_resistance1, AFE4404_TIA_GAIN, AFE4404_TIA_GAIN_RES, RESISTANCE, afe4404_res_table, ARRAY_SIZE(afe4404_res_table)); +static AFE440X_ATTR(tia_capacitance1, AFE4404_TIA_GAIN, AFE4404_TIA_GAIN_CAP, CAPACITANCE, afe4404_cap_table, ARRAY_SIZE(afe4404_cap_table)); + +static AFE440X_ATTR(tia_resistance2, AFE4404_TIA_GAIN_SEP, AFE4404_TIA_GAIN_RES, RESISTANCE, afe4404_res_table, ARRAY_SIZE(afe4404_res_table)); +static AFE440X_ATTR(tia_capacitance2, AFE4404_TIA_GAIN_SEP, AFE4404_TIA_GAIN_CAP, CAPACITANCE, afe4404_cap_table, ARRAY_SIZE(afe4404_cap_table)); + +static struct attribute *afe440x_attributes[] = { + &afe440x_attr_tia_separate_en.dev_attr.attr, + &afe440x_attr_tia_resistance1.dev_attr.attr, + &afe440x_attr_tia_capacitance1.dev_attr.attr, + &afe440x_attr_tia_resistance2.dev_attr.attr, + &afe440x_attr_tia_capacitance2.dev_attr.attr, + &dev_attr_tia_resistance_available.attr, + &dev_attr_tia_capacitance_available.attr, + NULL +}; + +static const struct attribute_group afe440x_attribute_group = { + .attrs = afe440x_attributes +}; + +static int afe4404_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct afe4404_data *afe = iio_priv(indio_dev); + const struct afe440x_reg_info reg_info = afe4404_reg_info[chan->address]; + int ret; + + switch (chan->type) { + case IIO_INTENSITY: + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = regmap_read(afe->regmap, reg_info.reg, val); + if (ret) + return ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_OFFSET: + ret = regmap_read(afe->regmap, reg_info.offreg, + val); + if (ret) + return ret; + *val &= reg_info.mask; + *val >>= reg_info.shift; + return IIO_VAL_INT; + } + break; + case IIO_CURRENT: + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = regmap_read(afe->regmap, reg_info.reg, val); + if (ret) + return ret; + *val &= reg_info.mask; + *val >>= reg_info.shift; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = 800000; + return IIO_VAL_INT_PLUS_MICRO; + } + break; + default: + break; + } + + return -EINVAL; +} + +static int afe4404_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct afe4404_data *afe = iio_priv(indio_dev); + const struct afe440x_reg_info reg_info = afe4404_reg_info[chan->address]; + + switch (chan->type) { + case IIO_INTENSITY: + switch (mask) { + case IIO_CHAN_INFO_OFFSET: + return regmap_update_bits(afe->regmap, + reg_info.offreg, + reg_info.mask, + (val << reg_info.shift)); + } + break; + case IIO_CURRENT: + switch (mask) { + case IIO_CHAN_INFO_RAW: + return regmap_update_bits(afe->regmap, + reg_info.reg, + reg_info.mask, + (val << reg_info.shift)); + } + break; + default: + break; + } + + return -EINVAL; +} + +static const struct iio_info afe4404_iio_info = { + .attrs = &afe440x_attribute_group, + .read_raw = afe4404_read_raw, + .write_raw = afe4404_write_raw, + .driver_module = THIS_MODULE, +}; + +static irqreturn_t afe4404_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct afe4404_data *afe = iio_priv(indio_dev); + int ret, bit, i = 0; + s32 buffer[10]; + + for_each_set_bit(bit, indio_dev->active_scan_mask, + indio_dev->masklength) { + ret = regmap_read(afe->regmap, afe4404_reg_info[bit].reg, + &buffer[i++]); + if (ret) + goto err; + } + + iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp); +err: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static const struct iio_trigger_ops afe4404_trigger_ops = { + .owner = THIS_MODULE, +}; + +/* Default timings from data-sheet */ +#define AFE4404_TIMING_PAIRS \ + { AFE440X_PRPCOUNT, 39999 }, \ + { AFE440X_LED2LEDSTC, 0 }, \ + { AFE440X_LED2LEDENDC, 398 }, \ + { AFE440X_LED2STC, 80 }, \ + { AFE440X_LED2ENDC, 398 }, \ + { AFE440X_ADCRSTSTCT0, 5600 }, \ + { AFE440X_ADCRSTENDCT0, 5606 }, \ + { AFE440X_LED2CONVST, 5607 }, \ + { AFE440X_LED2CONVEND, 6066 }, \ + { AFE4404_LED3LEDSTC, 400 }, \ + { AFE4404_LED3LEDENDC, 798 }, \ + { AFE440X_ALED2STC, 480 }, \ + { AFE440X_ALED2ENDC, 798 }, \ + { AFE440X_ADCRSTSTCT1, 6068 }, \ + { AFE440X_ADCRSTENDCT1, 6074 }, \ + { AFE440X_ALED2CONVST, 6075 }, \ + { AFE440X_ALED2CONVEND, 6534 }, \ + { AFE440X_LED1LEDSTC, 800 }, \ + { AFE440X_LED1LEDENDC, 1198 }, \ + { AFE440X_LED1STC, 880 }, \ + { AFE440X_LED1ENDC, 1198 }, \ + { AFE440X_ADCRSTSTCT2, 6536 }, \ + { AFE440X_ADCRSTENDCT2, 6542 }, \ + { AFE440X_LED1CONVST, 6543 }, \ + { AFE440X_LED1CONVEND, 7003 }, \ + { AFE440X_ALED1STC, 1280 }, \ + { AFE440X_ALED1ENDC, 1598 }, \ + { AFE440X_ADCRSTSTCT3, 7005 }, \ + { AFE440X_ADCRSTENDCT3, 7011 }, \ + { AFE440X_ALED1CONVST, 7012 }, \ + { AFE440X_ALED1CONVEND, 7471 }, \ + { AFE440X_PDNCYCLESTC, 7671 }, \ + { AFE440X_PDNCYCLEENDC, 39199 } + +static const struct reg_sequence afe4404_reg_sequences[] = { + AFE4404_TIMING_PAIRS, + { AFE440X_CONTROL1, AFE440X_CONTROL1_TIMEREN }, + { AFE4404_TIA_GAIN, AFE4404_TIA_GAIN_RES_50_K }, + { AFE440X_LEDCNTRL, (0xf << AFE4404_LEDCNTRL_ILED1_SHIFT) | + (0x3 << AFE4404_LEDCNTRL_ILED2_SHIFT) | + (0x3 << AFE4404_LEDCNTRL_ILED3_SHIFT) }, + { AFE440X_CONTROL2, AFE440X_CONTROL3_OSC_ENABLE }, +}; + +static const struct regmap_range afe4404_yes_ranges[] = { + regmap_reg_range(AFE440X_LED2VAL, AFE440X_LED1_ALED1VAL), + regmap_reg_range(AFE4404_AVG_LED2_ALED2VAL, AFE4404_AVG_LED1_ALED1VAL), +}; + +static const struct regmap_access_table afe4404_volatile_table = { + .yes_ranges = afe4404_yes_ranges, + .n_yes_ranges = ARRAY_SIZE(afe4404_yes_ranges), +}; + +static const struct regmap_config afe4404_regmap_config = { + .reg_bits = 8, + .val_bits = 24, + + .max_register = AFE4404_AVG_LED1_ALED1VAL, + .cache_type = REGCACHE_RBTREE, + .volatile_table = &afe4404_volatile_table, +}; + +#ifdef CONFIG_OF +static const struct of_device_id afe4404_of_match[] = { + { .compatible = "ti,afe4404", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, afe4404_of_match); +#endif + +static int afe4404_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct afe4404_data *afe = iio_priv(indio_dev); + int ret; + + ret = regmap_update_bits(afe->regmap, AFE440X_CONTROL2, + AFE440X_CONTROL2_PDN_AFE, + AFE440X_CONTROL2_PDN_AFE); + if (ret) + return ret; + + ret = regulator_disable(afe->regulator); + if (ret) { + dev_err(dev, "Unable to disable regulator\n"); + return ret; + } + + return 0; +} + +static int afe4404_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct afe4404_data *afe = iio_priv(indio_dev); + int ret; + + ret = regulator_enable(afe->regulator); + if (ret) { + dev_err(dev, "Unable to enable regulator\n"); + return ret; + } + + ret = regmap_update_bits(afe->regmap, AFE440X_CONTROL2, + AFE440X_CONTROL2_PDN_AFE, 0); + if (ret) + return ret; + + return 0; +} + +static SIMPLE_DEV_PM_OPS(afe4404_pm_ops, afe4404_suspend, afe4404_resume); + +static int afe4404_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct afe4404_data *afe; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*afe)); + if (!indio_dev) + return -ENOMEM; + + afe = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + + afe->dev = &client->dev; + afe->irq = client->irq; + + afe->regmap = devm_regmap_init_i2c(client, &afe4404_regmap_config); + if (IS_ERR(afe->regmap)) { + dev_err(afe->dev, "Unable to allocate register map\n"); + return PTR_ERR(afe->regmap); + } + + afe->regulator = devm_regulator_get(afe->dev, "tx_sup"); + if (IS_ERR(afe->regulator)) { + dev_err(afe->dev, "Unable to get regulator\n"); + return PTR_ERR(afe->regulator); + } + ret = regulator_enable(afe->regulator); + if (ret) { + dev_err(afe->dev, "Unable to enable regulator\n"); + return ret; + } + + ret = regmap_write(afe->regmap, AFE440X_CONTROL0, + AFE440X_CONTROL0_SW_RESET); + if (ret) { + dev_err(afe->dev, "Unable to reset device\n"); + goto disable_reg; + } + + ret = regmap_multi_reg_write(afe->regmap, afe4404_reg_sequences, + ARRAY_SIZE(afe4404_reg_sequences)); + if (ret) { + dev_err(afe->dev, "Unable to set register defaults\n"); + goto disable_reg; + } + + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->dev.parent = afe->dev; + indio_dev->channels = afe4404_channels; + indio_dev->num_channels = ARRAY_SIZE(afe4404_channels); + indio_dev->name = AFE4404_DRIVER_NAME; + indio_dev->info = &afe4404_iio_info; + + if (afe->irq > 0) { + afe->trig = devm_iio_trigger_alloc(afe->dev, + "%s-dev%d", + indio_dev->name, + indio_dev->id); + if (!afe->trig) { + dev_err(afe->dev, "Unable to allocate IIO trigger\n"); + ret = -ENOMEM; + goto disable_reg; + } + + iio_trigger_set_drvdata(afe->trig, indio_dev); + + afe->trig->ops = &afe4404_trigger_ops; + afe->trig->dev.parent = afe->dev; + + ret = iio_trigger_register(afe->trig); + if (ret) { + dev_err(afe->dev, "Unable to register IIO trigger\n"); + goto disable_reg; + } + + ret = devm_request_threaded_irq(afe->dev, afe->irq, + iio_trigger_generic_data_rdy_poll, + NULL, IRQF_ONESHOT, + AFE4404_DRIVER_NAME, + afe->trig); + if (ret) { + dev_err(afe->dev, "Unable to request IRQ\n"); + goto disable_reg; + } + } + + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + afe4404_trigger_handler, NULL); + if (ret) { + dev_err(afe->dev, "Unable to setup buffer\n"); + goto unregister_trigger; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(afe->dev, "Unable to register IIO device\n"); + goto unregister_triggered_buffer; + } + + return 0; + +unregister_triggered_buffer: + iio_triggered_buffer_cleanup(indio_dev); +unregister_trigger: + if (afe->irq > 0) + iio_trigger_unregister(afe->trig); +disable_reg: + regulator_disable(afe->regulator); + + return ret; +} + +static int afe4404_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct afe4404_data *afe = iio_priv(indio_dev); + int ret; + + iio_device_unregister(indio_dev); + + iio_triggered_buffer_cleanup(indio_dev); + + if (afe->irq > 0) + iio_trigger_unregister(afe->trig); + + ret = regulator_disable(afe->regulator); + if (ret) { + dev_err(afe->dev, "Unable to disable regulator\n"); + return ret; + } + + return 0; +} + +static const struct i2c_device_id afe4404_ids[] = { + { "afe4404", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(i2c, afe4404_ids); + +static struct i2c_driver afe4404_i2c_driver = { + .driver = { + .name = AFE4404_DRIVER_NAME, + .of_match_table = of_match_ptr(afe4404_of_match), + .pm = &afe4404_pm_ops, + }, + .probe = afe4404_probe, + .remove = afe4404_remove, + .id_table = afe4404_ids, +}; +module_i2c_driver(afe4404_i2c_driver); + +MODULE_AUTHOR("Andrew F. Davis "); +MODULE_DESCRIPTION("TI AFE4404 Heart Rate and Pulse Oximeter"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/health/afe440x.h b/drivers/iio/health/afe440x.h new file mode 100644 index 000000000000..c671ab78a23a --- /dev/null +++ b/drivers/iio/health/afe440x.h @@ -0,0 +1,191 @@ +/* + * AFE440X Heart Rate Monitors and Low-Cost Pulse Oximeters + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * 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. + * + * 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. + */ + +#ifndef _AFE440X_H +#define _AFE440X_H + +/* AFE440X registers */ +#define AFE440X_CONTROL0 0x00 +#define AFE440X_LED2STC 0x01 +#define AFE440X_LED2ENDC 0x02 +#define AFE440X_LED1LEDSTC 0x03 +#define AFE440X_LED1LEDENDC 0x04 +#define AFE440X_ALED2STC 0x05 +#define AFE440X_ALED2ENDC 0x06 +#define AFE440X_LED1STC 0x07 +#define AFE440X_LED1ENDC 0x08 +#define AFE440X_LED2LEDSTC 0x09 +#define AFE440X_LED2LEDENDC 0x0a +#define AFE440X_ALED1STC 0x0b +#define AFE440X_ALED1ENDC 0x0c +#define AFE440X_LED2CONVST 0x0d +#define AFE440X_LED2CONVEND 0x0e +#define AFE440X_ALED2CONVST 0x0f +#define AFE440X_ALED2CONVEND 0x10 +#define AFE440X_LED1CONVST 0x11 +#define AFE440X_LED1CONVEND 0x12 +#define AFE440X_ALED1CONVST 0x13 +#define AFE440X_ALED1CONVEND 0x14 +#define AFE440X_ADCRSTSTCT0 0x15 +#define AFE440X_ADCRSTENDCT0 0x16 +#define AFE440X_ADCRSTSTCT1 0x17 +#define AFE440X_ADCRSTENDCT1 0x18 +#define AFE440X_ADCRSTSTCT2 0x19 +#define AFE440X_ADCRSTENDCT2 0x1a +#define AFE440X_ADCRSTSTCT3 0x1b +#define AFE440X_ADCRSTENDCT3 0x1c +#define AFE440X_PRPCOUNT 0x1d +#define AFE440X_CONTROL1 0x1e +#define AFE440X_LEDCNTRL 0x22 +#define AFE440X_CONTROL2 0x23 +#define AFE440X_ALARM 0x29 +#define AFE440X_LED2VAL 0x2a +#define AFE440X_ALED2VAL 0x2b +#define AFE440X_LED1VAL 0x2c +#define AFE440X_ALED1VAL 0x2d +#define AFE440X_LED2_ALED2VAL 0x2e +#define AFE440X_LED1_ALED1VAL 0x2f +#define AFE440X_CONTROL3 0x31 +#define AFE440X_PDNCYCLESTC 0x32 +#define AFE440X_PDNCYCLEENDC 0x33 + +/* CONTROL0 register fields */ +#define AFE440X_CONTROL0_REG_READ BIT(0) +#define AFE440X_CONTROL0_TM_COUNT_RST BIT(1) +#define AFE440X_CONTROL0_SW_RESET BIT(3) + +/* CONTROL1 register fields */ +#define AFE440X_CONTROL1_TIMEREN BIT(8) + +/* TIAGAIN register fields */ +#define AFE440X_TIAGAIN_ENSEPGAIN_MASK BIT(15) +#define AFE440X_TIAGAIN_ENSEPGAIN_SHIFT 15 + +/* CONTROL2 register fields */ +#define AFE440X_CONTROL2_PDN_AFE BIT(0) +#define AFE440X_CONTROL2_PDN_RX BIT(1) +#define AFE440X_CONTROL2_DYNAMIC4 BIT(3) +#define AFE440X_CONTROL2_DYNAMIC3 BIT(4) +#define AFE440X_CONTROL2_DYNAMIC2 BIT(14) +#define AFE440X_CONTROL2_DYNAMIC1 BIT(20) + +/* CONTROL3 register fields */ +#define AFE440X_CONTROL3_CLKDIV GENMASK(2, 0) + +/* CONTROL0 values */ +#define AFE440X_CONTROL0_WRITE 0x0 +#define AFE440X_CONTROL0_READ 0x1 + +struct afe440x_reg_info { + unsigned int reg; + unsigned int offreg; + unsigned int shift; + unsigned int mask; +}; + +#define AFE440X_REG_INFO(_reg, _offreg, _sm) \ + { \ + .reg = _reg, \ + .offreg = _offreg, \ + .shift = _sm ## _SHIFT, \ + .mask = _sm ## _MASK, \ + } + +#define AFE440X_INTENSITY_CHAN(_index, _name, _mask) \ + { \ + .type = IIO_INTENSITY, \ + .channel = _index, \ + .address = _index, \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 24, \ + .storagebits = 32, \ + .endianness = IIO_CPU, \ + }, \ + .extend_name = _name, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + _mask, \ + } + +#define AFE440X_CURRENT_CHAN(_index, _name) \ + { \ + .type = IIO_CURRENT, \ + .channel = _index, \ + .address = _index, \ + .scan_index = _index, \ + .extend_name = _name, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .output = true, \ + } + +enum afe440x_reg_type { + SIMPLE, + RESISTANCE, + CAPACITANCE, +}; + +struct afe440x_val_table { + int integer; + int fract; +}; + +#define AFE440X_TABLE_ATTR(_name, _table) \ +static ssize_t _name ## _show(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + ssize_t len = 0; \ + int i; \ + \ + for (i = 0; i < ARRAY_SIZE(_table); i++) \ + len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06u ", \ + _table[i].integer, \ + _table[i].fract); \ + \ + buf[len - 1] = '\n'; \ + \ + return len; \ +} \ +static DEVICE_ATTR_RO(_name) + +struct afe440x_attr { + struct device_attribute dev_attr; + unsigned int reg; + unsigned int shift; + unsigned int mask; + enum afe440x_reg_type type; + const struct afe440x_val_table *val_table; + unsigned int table_size; +}; + +#define to_afe440x_attr(_dev_attr) \ + container_of(_dev_attr, struct afe440x_attr, dev_attr) + +#define AFE440X_ATTR(_name, _reg, _field, _type, _table, _size) \ + struct afe440x_attr afe440x_attr_##_name = { \ + .dev_attr = __ATTR(_name, (S_IRUGO | S_IWUSR), \ + afe440x_show_register, \ + afe440x_store_register), \ + .reg = _reg, \ + .shift = _field ## _SHIFT, \ + .mask = _field ## _MASK, \ + .type = _type, \ + .val_table = _table, \ + .table_size = _size, \ + } + +#endif /* _AFE440X_H */ -- cgit v1.2.3 From eec96d1e2d318bc734728111cfe3b203b58943b9 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Sat, 6 Feb 2016 13:35:21 -0600 Subject: iio: health: Add driver for the TI AFE4403 heart monitor Add driver for the TI AFE4403 heart rate monitor and pulse oximeter. This device detects reflected LED light fluctuations and presents an ADC value to the user space for further signal processing. Data sheet located here: http://www.ti.com/product/AFE4403/datasheet Signed-off-by: Andrew F. Davis Signed-off-by: Jonathan Cameron --- drivers/iio/health/Kconfig | 12 + drivers/iio/health/Makefile | 1 + drivers/iio/health/afe4403.c | 708 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 721 insertions(+) create mode 100644 drivers/iio/health/afe4403.c (limited to 'drivers') diff --git a/drivers/iio/health/Kconfig b/drivers/iio/health/Kconfig index 632a14b7dd6f..f0c19779ac27 100644 --- a/drivers/iio/health/Kconfig +++ b/drivers/iio/health/Kconfig @@ -7,6 +7,18 @@ menu "Health Sensors" menu "Heart Rate Monitors" +config AFE4403 + tristate "TI AFE4403 Heart Rate Monitor" + depends on SPI_MASTER + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes to choose the Texas Instruments AFE4403 + heart rate monitor and low-cost pulse oximeter. + + To compile this driver as a module, choose M here: the + module will be called afe4403. + config AFE4404 tristate "TI AFE4404 heart rate and pulse oximeter sensor" depends on I2C diff --git a/drivers/iio/health/Makefile b/drivers/iio/health/Makefile index b37c0d5e07b8..9955a2ae8df1 100644 --- a/drivers/iio/health/Makefile +++ b/drivers/iio/health/Makefile @@ -4,5 +4,6 @@ # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_AFE4403) += afe4403.o obj-$(CONFIG_AFE4404) += afe4404.o obj-$(CONFIG_MAX30100) += max30100.o diff --git a/drivers/iio/health/afe4403.c b/drivers/iio/health/afe4403.c new file mode 100644 index 000000000000..91c046e40d2f --- /dev/null +++ b/drivers/iio/health/afe4403.c @@ -0,0 +1,708 @@ +/* + * AFE4403 Heart Rate Monitors and Low-Cost Pulse Oximeters + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * 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. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "afe440x.h" + +#define AFE4403_DRIVER_NAME "afe4403" + +/* AFE4403 Registers */ +#define AFE4403_TIAGAIN 0x20 +#define AFE4403_TIA_AMB_GAIN 0x21 + +/* AFE4403 GAIN register fields */ +#define AFE4403_TIAGAIN_RES_MASK GENMASK(2, 0) +#define AFE4403_TIAGAIN_RES_SHIFT 0 +#define AFE4403_TIAGAIN_CAP_MASK GENMASK(7, 3) +#define AFE4403_TIAGAIN_CAP_SHIFT 3 + +/* AFE4403 LEDCNTRL register fields */ +#define AFE440X_LEDCNTRL_LED1_MASK GENMASK(15, 8) +#define AFE440X_LEDCNTRL_LED1_SHIFT 8 +#define AFE440X_LEDCNTRL_LED2_MASK GENMASK(7, 0) +#define AFE440X_LEDCNTRL_LED2_SHIFT 0 +#define AFE440X_LEDCNTRL_LED_RANGE_MASK GENMASK(17, 16) +#define AFE440X_LEDCNTRL_LED_RANGE_SHIFT 16 + +/* AFE4403 CONTROL2 register fields */ +#define AFE440X_CONTROL2_PWR_DWN_TX BIT(2) +#define AFE440X_CONTROL2_EN_SLOW_DIAG BIT(8) +#define AFE440X_CONTROL2_DIAG_OUT_TRI BIT(10) +#define AFE440X_CONTROL2_TX_BRDG_MOD BIT(11) +#define AFE440X_CONTROL2_TX_REF_MASK GENMASK(18, 17) +#define AFE440X_CONTROL2_TX_REF_SHIFT 17 + +/* AFE4404 NULL fields */ +#define NULL_MASK 0 +#define NULL_SHIFT 0 + +/* AFE4403 LEDCNTRL values */ +#define AFE440X_LEDCNTRL_RANGE_TX_HALF 0x1 +#define AFE440X_LEDCNTRL_RANGE_TX_FULL 0x2 +#define AFE440X_LEDCNTRL_RANGE_TX_OFF 0x3 + +/* AFE4403 CONTROL2 values */ +#define AFE440X_CONTROL2_TX_REF_025 0x0 +#define AFE440X_CONTROL2_TX_REF_050 0x1 +#define AFE440X_CONTROL2_TX_REF_100 0x2 +#define AFE440X_CONTROL2_TX_REF_075 0x3 + +/* AFE4403 CONTROL3 values */ +#define AFE440X_CONTROL3_CLK_DIV_2 0x0 +#define AFE440X_CONTROL3_CLK_DIV_4 0x2 +#define AFE440X_CONTROL3_CLK_DIV_6 0x3 +#define AFE440X_CONTROL3_CLK_DIV_8 0x4 +#define AFE440X_CONTROL3_CLK_DIV_12 0x5 +#define AFE440X_CONTROL3_CLK_DIV_1 0x7 + +/* AFE4403 TIAGAIN_CAP values */ +#define AFE4403_TIAGAIN_CAP_5_P 0x0 +#define AFE4403_TIAGAIN_CAP_10_P 0x1 +#define AFE4403_TIAGAIN_CAP_20_P 0x2 +#define AFE4403_TIAGAIN_CAP_30_P 0x3 +#define AFE4403_TIAGAIN_CAP_55_P 0x8 +#define AFE4403_TIAGAIN_CAP_155_P 0x10 + +/* AFE4403 TIAGAIN_RES values */ +#define AFE4403_TIAGAIN_RES_500_K 0x0 +#define AFE4403_TIAGAIN_RES_250_K 0x1 +#define AFE4403_TIAGAIN_RES_100_K 0x2 +#define AFE4403_TIAGAIN_RES_50_K 0x3 +#define AFE4403_TIAGAIN_RES_25_K 0x4 +#define AFE4403_TIAGAIN_RES_10_K 0x5 +#define AFE4403_TIAGAIN_RES_1_M 0x6 +#define AFE4403_TIAGAIN_RES_NONE 0x7 + +/** + * struct afe4403_data + * @dev - Device structure + * @spi - SPI device handle + * @regmap - Register map of the device + * @regulator - Pointer to the regulator for the IC + * @trig - IIO trigger for this device + * @irq - ADC_RDY line interrupt number + */ +struct afe4403_data { + struct device *dev; + struct spi_device *spi; + struct regmap *regmap; + struct regulator *regulator; + struct iio_trigger *trig; + int irq; +}; + +enum afe4403_chan_id { + LED1, + ALED1, + LED2, + ALED2, + LED1_ALED1, + LED2_ALED2, + ILED1, + ILED2, +}; + +static const struct afe440x_reg_info afe4403_reg_info[] = { + [LED1] = AFE440X_REG_INFO(AFE440X_LED1VAL, 0, NULL), + [ALED1] = AFE440X_REG_INFO(AFE440X_ALED1VAL, 0, NULL), + [LED2] = AFE440X_REG_INFO(AFE440X_LED2VAL, 0, NULL), + [ALED2] = AFE440X_REG_INFO(AFE440X_ALED2VAL, 0, NULL), + [LED1_ALED1] = AFE440X_REG_INFO(AFE440X_LED1_ALED1VAL, 0, NULL), + [LED2_ALED2] = AFE440X_REG_INFO(AFE440X_LED2_ALED2VAL, 0, NULL), + [ILED1] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE440X_LEDCNTRL_LED1), + [ILED2] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE440X_LEDCNTRL_LED2), +}; + +static const struct iio_chan_spec afe4403_channels[] = { + /* ADC values */ + AFE440X_INTENSITY_CHAN(LED1, "led1", 0), + AFE440X_INTENSITY_CHAN(ALED1, "led1_ambient", 0), + AFE440X_INTENSITY_CHAN(LED2, "led2", 0), + AFE440X_INTENSITY_CHAN(ALED2, "led2_ambient", 0), + AFE440X_INTENSITY_CHAN(LED1_ALED1, "led1-led1_ambient", 0), + AFE440X_INTENSITY_CHAN(LED2_ALED2, "led2-led2_ambient", 0), + /* LED current */ + AFE440X_CURRENT_CHAN(ILED1, "led1"), + AFE440X_CURRENT_CHAN(ILED2, "led2"), +}; + +static const struct afe440x_val_table afe4403_res_table[] = { + { 500000 }, { 250000 }, { 100000 }, { 50000 }, + { 25000 }, { 10000 }, { 1000000 }, { 0 }, +}; +AFE440X_TABLE_ATTR(tia_resistance_available, afe4403_res_table); + +static const struct afe440x_val_table afe4403_cap_table[] = { + { 0, 5000 }, { 0, 10000 }, { 0, 20000 }, { 0, 25000 }, + { 0, 30000 }, { 0, 35000 }, { 0, 45000 }, { 0, 50000 }, + { 0, 55000 }, { 0, 60000 }, { 0, 70000 }, { 0, 75000 }, + { 0, 80000 }, { 0, 85000 }, { 0, 95000 }, { 0, 100000 }, + { 0, 155000 }, { 0, 160000 }, { 0, 170000 }, { 0, 175000 }, + { 0, 180000 }, { 0, 185000 }, { 0, 195000 }, { 0, 200000 }, + { 0, 205000 }, { 0, 210000 }, { 0, 220000 }, { 0, 225000 }, + { 0, 230000 }, { 0, 235000 }, { 0, 245000 }, { 0, 250000 }, +}; +AFE440X_TABLE_ATTR(tia_capacitance_available, afe4403_cap_table); + +static ssize_t afe440x_show_register(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct afe4403_data *afe = iio_priv(indio_dev); + struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr); + unsigned int reg_val, type; + int vals[2]; + int ret, val_len; + + ret = regmap_read(afe->regmap, afe440x_attr->reg, ®_val); + if (ret) + return ret; + + reg_val &= afe440x_attr->mask; + reg_val >>= afe440x_attr->shift; + + switch (afe440x_attr->type) { + case SIMPLE: + type = IIO_VAL_INT; + val_len = 1; + vals[0] = reg_val; + break; + case RESISTANCE: + case CAPACITANCE: + type = IIO_VAL_INT_PLUS_MICRO; + val_len = 2; + if (reg_val < afe440x_attr->table_size) { + vals[0] = afe440x_attr->val_table[reg_val].integer; + vals[1] = afe440x_attr->val_table[reg_val].fract; + break; + } + return -EINVAL; + default: + return -EINVAL; + } + + return iio_format_value(buf, type, val_len, vals); +} + +static ssize_t afe440x_store_register(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct afe4403_data *afe = iio_priv(indio_dev); + struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr); + int val, integer, fract, ret; + + ret = iio_str_to_fixpoint(buf, 100000, &integer, &fract); + if (ret) + return ret; + + switch (afe440x_attr->type) { + case SIMPLE: + val = integer; + break; + case RESISTANCE: + case CAPACITANCE: + for (val = 0; val < afe440x_attr->table_size; val++) + if (afe440x_attr->val_table[val].integer == integer && + afe440x_attr->val_table[val].fract == fract) + break; + if (val == afe440x_attr->table_size) + return -EINVAL; + break; + default: + return -EINVAL; + } + + ret = regmap_update_bits(afe->regmap, afe440x_attr->reg, + afe440x_attr->mask, + (val << afe440x_attr->shift)); + if (ret) + return ret; + + return count; +} + +static AFE440X_ATTR(tia_separate_en, AFE4403_TIAGAIN, AFE440X_TIAGAIN_ENSEPGAIN, SIMPLE, NULL, 0); + +static AFE440X_ATTR(tia_resistance1, AFE4403_TIAGAIN, AFE4403_TIAGAIN_RES, RESISTANCE, afe4403_res_table, ARRAY_SIZE(afe4403_res_table)); +static AFE440X_ATTR(tia_capacitance1, AFE4403_TIAGAIN, AFE4403_TIAGAIN_CAP, CAPACITANCE, afe4403_cap_table, ARRAY_SIZE(afe4403_cap_table)); + +static AFE440X_ATTR(tia_resistance2, AFE4403_TIA_AMB_GAIN, AFE4403_TIAGAIN_RES, RESISTANCE, afe4403_res_table, ARRAY_SIZE(afe4403_res_table)); +static AFE440X_ATTR(tia_capacitance2, AFE4403_TIA_AMB_GAIN, AFE4403_TIAGAIN_RES, CAPACITANCE, afe4403_cap_table, ARRAY_SIZE(afe4403_cap_table)); + +static struct attribute *afe440x_attributes[] = { + &afe440x_attr_tia_separate_en.dev_attr.attr, + &afe440x_attr_tia_resistance1.dev_attr.attr, + &afe440x_attr_tia_capacitance1.dev_attr.attr, + &afe440x_attr_tia_resistance2.dev_attr.attr, + &afe440x_attr_tia_capacitance2.dev_attr.attr, + &dev_attr_tia_resistance_available.attr, + &dev_attr_tia_capacitance_available.attr, + NULL +}; + +static const struct attribute_group afe440x_attribute_group = { + .attrs = afe440x_attributes +}; + +static int afe4403_read(struct afe4403_data *afe, unsigned int reg, u32 *val) +{ + u8 tx[4] = {AFE440X_CONTROL0, 0x0, 0x0, AFE440X_CONTROL0_READ}; + u8 rx[3]; + int ret; + + /* Enable reading from the device */ + ret = spi_write_then_read(afe->spi, tx, 4, NULL, 0); + if (ret) + return ret; + + ret = spi_write_then_read(afe->spi, ®, 1, rx, 3); + if (ret) + return ret; + + *val = (rx[0] << 16) | + (rx[1] << 8) | + (rx[2]); + + /* Disable reading from the device */ + tx[3] = AFE440X_CONTROL0_WRITE; + ret = spi_write_then_read(afe->spi, tx, 4, NULL, 0); + if (ret) + return ret; + + return 0; +} + +static int afe4403_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct afe4403_data *afe = iio_priv(indio_dev); + const struct afe440x_reg_info reg_info = afe4403_reg_info[chan->address]; + int ret; + + switch (chan->type) { + case IIO_INTENSITY: + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = afe4403_read(afe, reg_info.reg, val); + if (ret) + return ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_OFFSET: + ret = regmap_read(afe->regmap, reg_info.offreg, + val); + if (ret) + return ret; + *val &= reg_info.mask; + *val >>= reg_info.shift; + return IIO_VAL_INT; + } + break; + case IIO_CURRENT: + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = regmap_read(afe->regmap, reg_info.reg, val); + if (ret) + return ret; + *val &= reg_info.mask; + *val >>= reg_info.shift; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = 800000; + return IIO_VAL_INT_PLUS_MICRO; + } + break; + default: + break; + } + + return -EINVAL; +} + +static int afe4403_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct afe4403_data *afe = iio_priv(indio_dev); + const struct afe440x_reg_info reg_info = afe4403_reg_info[chan->address]; + + switch (chan->type) { + case IIO_INTENSITY: + switch (mask) { + case IIO_CHAN_INFO_OFFSET: + return regmap_update_bits(afe->regmap, + reg_info.offreg, + reg_info.mask, + (val << reg_info.shift)); + } + break; + case IIO_CURRENT: + switch (mask) { + case IIO_CHAN_INFO_RAW: + return regmap_update_bits(afe->regmap, + reg_info.reg, + reg_info.mask, + (val << reg_info.shift)); + } + break; + default: + break; + } + + return -EINVAL; +} + +static const struct iio_info afe4403_iio_info = { + .attrs = &afe440x_attribute_group, + .read_raw = afe4403_read_raw, + .write_raw = afe4403_write_raw, + .driver_module = THIS_MODULE, +}; + +static irqreturn_t afe4403_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct afe4403_data *afe = iio_priv(indio_dev); + int ret, bit, i = 0; + s32 buffer[8]; + u8 tx[4] = {AFE440X_CONTROL0, 0x0, 0x0, AFE440X_CONTROL0_READ}; + u8 rx[3]; + + /* Enable reading from the device */ + ret = spi_write_then_read(afe->spi, tx, 4, NULL, 0); + if (ret) + goto err; + + for_each_set_bit(bit, indio_dev->active_scan_mask, + indio_dev->masklength) { + ret = spi_write_then_read(afe->spi, + &afe4403_reg_info[bit].reg, 1, + rx, 3); + if (ret) + goto err; + + buffer[i++] = (rx[0] << 16) | + (rx[1] << 8) | + (rx[2]); + } + + /* Disable reading from the device */ + tx[3] = AFE440X_CONTROL0_WRITE; + ret = spi_write_then_read(afe->spi, tx, 4, NULL, 0); + if (ret) + goto err; + + iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp); +err: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static const struct iio_trigger_ops afe4403_trigger_ops = { + .owner = THIS_MODULE, +}; + +#define AFE4403_TIMING_PAIRS \ + { AFE440X_LED2STC, 0x000050 }, \ + { AFE440X_LED2ENDC, 0x0003e7 }, \ + { AFE440X_LED1LEDSTC, 0x0007d0 }, \ + { AFE440X_LED1LEDENDC, 0x000bb7 }, \ + { AFE440X_ALED2STC, 0x000438 }, \ + { AFE440X_ALED2ENDC, 0x0007cf }, \ + { AFE440X_LED1STC, 0x000820 }, \ + { AFE440X_LED1ENDC, 0x000bb7 }, \ + { AFE440X_LED2LEDSTC, 0x000000 }, \ + { AFE440X_LED2LEDENDC, 0x0003e7 }, \ + { AFE440X_ALED1STC, 0x000c08 }, \ + { AFE440X_ALED1ENDC, 0x000f9f }, \ + { AFE440X_LED2CONVST, 0x0003ef }, \ + { AFE440X_LED2CONVEND, 0x0007cf }, \ + { AFE440X_ALED2CONVST, 0x0007d7 }, \ + { AFE440X_ALED2CONVEND, 0x000bb7 }, \ + { AFE440X_LED1CONVST, 0x000bbf }, \ + { AFE440X_LED1CONVEND, 0x009c3f }, \ + { AFE440X_ALED1CONVST, 0x000fa7 }, \ + { AFE440X_ALED1CONVEND, 0x001387 }, \ + { AFE440X_ADCRSTSTCT0, 0x0003e8 }, \ + { AFE440X_ADCRSTENDCT0, 0x0003eb }, \ + { AFE440X_ADCRSTSTCT1, 0x0007d0 }, \ + { AFE440X_ADCRSTENDCT1, 0x0007d3 }, \ + { AFE440X_ADCRSTSTCT2, 0x000bb8 }, \ + { AFE440X_ADCRSTENDCT2, 0x000bbb }, \ + { AFE440X_ADCRSTSTCT3, 0x000fa0 }, \ + { AFE440X_ADCRSTENDCT3, 0x000fa3 }, \ + { AFE440X_PRPCOUNT, 0x009c3f }, \ + { AFE440X_PDNCYCLESTC, 0x001518 }, \ + { AFE440X_PDNCYCLEENDC, 0x00991f } + +static const struct reg_sequence afe4403_reg_sequences[] = { + AFE4403_TIMING_PAIRS, + { AFE440X_CONTROL1, AFE440X_CONTROL1_TIMEREN | 0x000007}, + { AFE4403_TIA_AMB_GAIN, AFE4403_TIAGAIN_RES_1_M }, + { AFE440X_LEDCNTRL, (0x14 << AFE440X_LEDCNTRL_LED1_SHIFT) | + (0x14 << AFE440X_LEDCNTRL_LED2_SHIFT) }, + { AFE440X_CONTROL2, AFE440X_CONTROL2_TX_REF_050 << + AFE440X_CONTROL2_TX_REF_SHIFT }, +}; + +static const struct regmap_range afe4403_yes_ranges[] = { + regmap_reg_range(AFE440X_LED2VAL, AFE440X_LED1_ALED1VAL), +}; + +static const struct regmap_access_table afe4403_volatile_table = { + .yes_ranges = afe4403_yes_ranges, + .n_yes_ranges = ARRAY_SIZE(afe4403_yes_ranges), +}; + +static const struct regmap_config afe4403_regmap_config = { + .reg_bits = 8, + .val_bits = 24, + + .max_register = AFE440X_PDNCYCLEENDC, + .cache_type = REGCACHE_RBTREE, + .volatile_table = &afe4403_volatile_table, +}; + +#ifdef CONFIG_OF +static const struct of_device_id afe4403_of_match[] = { + { .compatible = "ti,afe4403", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, afe4403_of_match); +#endif + +static int afe4403_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct afe4403_data *afe = iio_priv(indio_dev); + int ret; + + ret = regmap_update_bits(afe->regmap, AFE440X_CONTROL2, + AFE440X_CONTROL2_PDN_AFE, + AFE440X_CONTROL2_PDN_AFE); + if (ret) + return ret; + + ret = regulator_disable(afe->regulator); + if (ret) { + dev_err(dev, "Unable to disable regulator\n"); + return ret; + } + + return 0; +} + +static int afe4403_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct afe4403_data *afe = iio_priv(indio_dev); + int ret; + + ret = regulator_enable(afe->regulator); + if (ret) { + dev_err(dev, "Unable to enable regulator\n"); + return ret; + } + + ret = regmap_update_bits(afe->regmap, AFE440X_CONTROL2, + AFE440X_CONTROL2_PDN_AFE, 0); + if (ret) + return ret; + + return 0; +} + +static SIMPLE_DEV_PM_OPS(afe4403_pm_ops, afe4403_suspend, afe4403_resume); + +static int afe4403_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct afe4403_data *afe; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*afe)); + if (!indio_dev) + return -ENOMEM; + + afe = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + + afe->dev = &spi->dev; + afe->spi = spi; + afe->irq = spi->irq; + + afe->regmap = devm_regmap_init_spi(spi, &afe4403_regmap_config); + if (IS_ERR(afe->regmap)) { + dev_err(afe->dev, "Unable to allocate register map\n"); + return PTR_ERR(afe->regmap); + } + + afe->regulator = devm_regulator_get(afe->dev, "tx_sup"); + if (IS_ERR(afe->regulator)) { + dev_err(afe->dev, "Unable to get regulator\n"); + return PTR_ERR(afe->regulator); + } + ret = regulator_enable(afe->regulator); + if (ret) { + dev_err(afe->dev, "Unable to enable regulator\n"); + return ret; + } + + ret = regmap_write(afe->regmap, AFE440X_CONTROL0, + AFE440X_CONTROL0_SW_RESET); + if (ret) { + dev_err(afe->dev, "Unable to reset device\n"); + goto err_disable_reg; + } + + ret = regmap_multi_reg_write(afe->regmap, afe4403_reg_sequences, + ARRAY_SIZE(afe4403_reg_sequences)); + if (ret) { + dev_err(afe->dev, "Unable to set register defaults\n"); + goto err_disable_reg; + } + + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->dev.parent = afe->dev; + indio_dev->channels = afe4403_channels; + indio_dev->num_channels = ARRAY_SIZE(afe4403_channels); + indio_dev->name = AFE4403_DRIVER_NAME; + indio_dev->info = &afe4403_iio_info; + + if (afe->irq > 0) { + afe->trig = devm_iio_trigger_alloc(afe->dev, + "%s-dev%d", + indio_dev->name, + indio_dev->id); + if (!afe->trig) { + dev_err(afe->dev, "Unable to allocate IIO trigger\n"); + ret = -ENOMEM; + goto err_disable_reg; + } + + iio_trigger_set_drvdata(afe->trig, indio_dev); + + afe->trig->ops = &afe4403_trigger_ops; + afe->trig->dev.parent = afe->dev; + + ret = iio_trigger_register(afe->trig); + if (ret) { + dev_err(afe->dev, "Unable to register IIO trigger\n"); + goto err_disable_reg; + } + + ret = devm_request_threaded_irq(afe->dev, afe->irq, + iio_trigger_generic_data_rdy_poll, + NULL, IRQF_ONESHOT, + AFE4403_DRIVER_NAME, + afe->trig); + if (ret) { + dev_err(afe->dev, "Unable to request IRQ\n"); + goto err_trig; + } + } + + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + afe4403_trigger_handler, NULL); + if (ret) { + dev_err(afe->dev, "Unable to setup buffer\n"); + goto err_trig; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(afe->dev, "Unable to register IIO device\n"); + goto err_buff; + } + + return 0; + +err_buff: + iio_triggered_buffer_cleanup(indio_dev); +err_trig: + if (afe->irq > 0) + iio_trigger_unregister(afe->trig); +err_disable_reg: + regulator_disable(afe->regulator); + + return ret; +} + +static int afe4403_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct afe4403_data *afe = iio_priv(indio_dev); + int ret; + + iio_device_unregister(indio_dev); + + iio_triggered_buffer_cleanup(indio_dev); + + if (afe->irq > 0) + iio_trigger_unregister(afe->trig); + + ret = regulator_disable(afe->regulator); + if (ret) { + dev_err(afe->dev, "Unable to disable regulator\n"); + return ret; + } + + return 0; +} + +static const struct spi_device_id afe4403_ids[] = { + { "afe4403", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(spi, afe4403_ids); + +static struct spi_driver afe4403_spi_driver = { + .driver = { + .name = AFE4403_DRIVER_NAME, + .of_match_table = of_match_ptr(afe4403_of_match), + .pm = &afe4403_pm_ops, + }, + .probe = afe4403_probe, + .remove = afe4403_remove, + .id_table = afe4403_ids, +}; +module_spi_driver(afe4403_spi_driver); + +MODULE_AUTHOR("Andrew F. Davis "); +MODULE_DESCRIPTION("TI AFE4403 Heart Rate and Pulse Oximeter"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 09954bad448791ef01202351d437abdd9497a804 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Sat, 6 Feb 2016 23:00:22 +0100 Subject: floppy: refactor open() flags handling In case /dev/fdX is open with O_NDELAY / O_NONBLOCK, floppy_open() immediately succeeds, without performing any further media / controller preparations. That's "correct" wrt. the NODELAY flag, but is hardly correct wrt. the rest of the floppy driver, that is not really O_NONBLOCK ready, at all. Therefore it's not too surprising, that subsequent attempts to work with the filedescriptor produce bad results. Namely, syzkaller tool has been able to livelock mmap() on the returned fd to keep waiting on the page unlock bit forever. Quite frankly, I have trouble defining what non-blocking behavior would be for floppies. Is waiting ages for the driver to actually succeed reading a sector blocking operation? Is waiting for drive motor to start blocking operation? How about in case of virtualized floppies? One option would be returning EWOULDBLOCK in case O_NDLEAY / O_NONBLOCK is being passed to open(). That has a theoretical potential of breaking some arcane and archaic userspace though. Let's take a more conservative aproach, and accept the O_NDLEAY flag, and let the driver behave as usual. While at it, clean up a bit handling of !(mode & (FMODE_READ|FMODE_WRITE)) case and return EINVAL instead of succeeding as well. Spotted by syzkaller tool. Reported-by: Dmitry Vyukov Tested-by: Dmitry Vyukov Signed-off-by: Jiri Kosina --- drivers/block/floppy.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index b206115d761c..84708a5f8c52 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3663,6 +3663,11 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) opened_bdev[drive] = bdev; + if (!(mode & (FMODE_READ|FMODE_WRITE))) { + res = -EINVAL; + goto out; + } + res = -ENXIO; if (!floppy_track_buffer) { @@ -3706,21 +3711,20 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) if (UFDCS->rawcmd == 1) UFDCS->rawcmd = 2; - if (!(mode & FMODE_NDELAY)) { - if (mode & (FMODE_READ|FMODE_WRITE)) { - UDRS->last_checked = 0; - clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); - check_disk_change(bdev); - if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) - goto out; - if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) - goto out; - } - res = -EROFS; - if ((mode & FMODE_WRITE) && - !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags)) - goto out; - } + UDRS->last_checked = 0; + clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); + check_disk_change(bdev); + if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) + goto out; + if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) + goto out; + + res = -EROFS; + + if ((mode & FMODE_WRITE) && + !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags)) + goto out; + mutex_unlock(&open_lock); mutex_unlock(&floppy_mutex); return 0; -- cgit v1.2.3 From 310d3d314be7f0a84011ebdc4bdccbcae9755a87 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 5 Feb 2016 14:51:36 -0800 Subject: target: Fix race with SCF_SEND_DELAYED_TAS handling This patch fixes a race between setting of SCF_SEND_DELAYED_TAS in transport_send_task_abort(), and check of the same bit in transport_check_aborted_status(). It adds a __transport_check_aborted_status() version that is used by target_execute_cmd() when se_cmd->t_state_lock is held, and a transport_check_aborted_status() wrapper for all other existing callers. Also, it handles the case where the check happens before transport_send_task_abort() gets called. For this, go ahead and set SCF_SEND_DELAYED_TAS early when necessary, and have transport_send_task_abort() send the abort. Cc: Quinn Tran Cc: Himanshu Madhani Cc: Sagi Grimberg Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Andy Grover Cc: Mike Christie Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 53 ++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 3441b159e306..2e0b23a3d5c4 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1858,19 +1858,21 @@ static bool target_handle_task_attr(struct se_cmd *cmd) return true; } +static int __transport_check_aborted_status(struct se_cmd *, int); + void target_execute_cmd(struct se_cmd *cmd) { - /* - * If the received CDB has aleady been aborted stop processing it here. - */ - if (transport_check_aborted_status(cmd, 1)) - return; - /* * Determine if frontend context caller is requesting the stopping of * this command for frontend exceptions. + * + * If the received CDB has aleady been aborted stop processing it here. */ spin_lock_irq(&cmd->t_state_lock); + if (__transport_check_aborted_status(cmd, 1)) { + spin_unlock_irq(&cmd->t_state_lock); + return; + } if (cmd->transport_state & CMD_T_STOP) { pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08llx\n", __func__, __LINE__, cmd->tag); @@ -2911,28 +2913,49 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd, } EXPORT_SYMBOL(transport_send_check_condition_and_sense); -int transport_check_aborted_status(struct se_cmd *cmd, int send_status) +static int __transport_check_aborted_status(struct se_cmd *cmd, int send_status) + __releases(&cmd->t_state_lock) + __acquires(&cmd->t_state_lock) { + assert_spin_locked(&cmd->t_state_lock); + WARN_ON_ONCE(!irqs_disabled()); + if (!(cmd->transport_state & CMD_T_ABORTED)) return 0; - /* * If cmd has been aborted but either no status is to be sent or it has * already been sent, just return */ - if (!send_status || !(cmd->se_cmd_flags & SCF_SEND_DELAYED_TAS)) + if (!send_status || !(cmd->se_cmd_flags & SCF_SEND_DELAYED_TAS)) { + if (send_status) + cmd->se_cmd_flags |= SCF_SEND_DELAYED_TAS; return 1; + } - pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB: 0x%02x ITT: 0x%08llx\n", - cmd->t_task_cdb[0], cmd->tag); + pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB:" + " 0x%02x ITT: 0x%08llx\n", cmd->t_task_cdb[0], cmd->tag); cmd->se_cmd_flags &= ~SCF_SEND_DELAYED_TAS; cmd->scsi_status = SAM_STAT_TASK_ABORTED; trace_target_cmd_complete(cmd); + + spin_unlock_irq(&cmd->t_state_lock); cmd->se_tfo->queue_status(cmd); + spin_lock_irq(&cmd->t_state_lock); return 1; } + +int transport_check_aborted_status(struct se_cmd *cmd, int send_status) +{ + int ret; + + spin_lock_irq(&cmd->t_state_lock); + ret = __transport_check_aborted_status(cmd, send_status); + spin_unlock_irq(&cmd->t_state_lock); + + return ret; +} EXPORT_SYMBOL(transport_check_aborted_status); void transport_send_task_abort(struct se_cmd *cmd) @@ -2954,11 +2977,17 @@ void transport_send_task_abort(struct se_cmd *cmd) */ if (cmd->data_direction == DMA_TO_DEVICE) { if (cmd->se_tfo->write_pending_status(cmd) != 0) { - cmd->transport_state |= CMD_T_ABORTED; + spin_lock_irqsave(&cmd->t_state_lock, flags); + if (cmd->se_cmd_flags & SCF_SEND_DELAYED_TAS) { + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + goto send_abort; + } cmd->se_cmd_flags |= SCF_SEND_DELAYED_TAS; + spin_unlock_irqrestore(&cmd->t_state_lock, flags); return; } } +send_abort: cmd->scsi_status = SAM_STAT_TASK_ABORTED; transport_lun_remove_cmd(cmd); -- cgit v1.2.3 From 57dae19065bde296dfdf08b8e46c102a671ff741 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 29 Jan 2016 00:07:25 -0800 Subject: target: Drop legacy se_cmd->task_stop_comp + REQUEST_STOP usage With CMD_T_FABRIC_STOP + se_cmd->cmd_wait_set usage in place, go ahead and drop left-over CMD_T_REQUEST_STOP checks in target_complete_cmd() and unused target_stop_cmd(). Reviewed-by: Christoph Hellwig Cc: Quinn Tran Cc: Himanshu Madhani Cc: Sagi Grimberg Cc: Hannes Reinecke Cc: Andy Grover Cc: Mike Christie Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_internal.h | 1 - drivers/target/target_core_transport.c | 37 ---------------------------------- include/target/target_core_base.h | 4 ---- 3 files changed, 42 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index dae0750c2032..db4412fe6b8a 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -141,7 +141,6 @@ void transport_dump_vpd_proto_id(struct t10_vpd *, unsigned char *, int); int transport_dump_vpd_assoc(struct t10_vpd *, unsigned char *, int); int transport_dump_vpd_ident_type(struct t10_vpd *, unsigned char *, int); int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int); -bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags); void transport_clear_lun_ref(struct se_lun *); void transport_send_task_abort(struct se_cmd *); sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 2e0b23a3d5c4..d92cb644d8f9 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -692,15 +692,6 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) success = 1; } - /* - * See if we are waiting to complete for an exception condition. - */ - if (cmd->transport_state & CMD_T_REQUEST_STOP) { - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - complete(&cmd->task_stop_comp); - return; - } - /* * Check for case where an explicit ABORT_TASK has been received * and transport_wait_for_tasks() will be waiting for completion.. @@ -1202,7 +1193,6 @@ void transport_init_se_cmd( INIT_LIST_HEAD(&cmd->state_list); init_completion(&cmd->t_transport_stop_comp); init_completion(&cmd->cmd_wait_comp); - init_completion(&cmd->task_stop_comp); spin_lock_init(&cmd->t_state_lock); kref_init(&cmd->cmd_kref); cmd->transport_state = CMD_T_DEV_ACTIVE; @@ -1633,33 +1623,6 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess, } EXPORT_SYMBOL(target_submit_tmr); -/* - * If the cmd is active, request it to be stopped and sleep until it - * has completed. - */ -bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags) - __releases(&cmd->t_state_lock) - __acquires(&cmd->t_state_lock) -{ - bool was_active = false; - - if (cmd->transport_state & CMD_T_BUSY) { - cmd->transport_state |= CMD_T_REQUEST_STOP; - spin_unlock_irqrestore(&cmd->t_state_lock, *flags); - - pr_debug("cmd %p waiting to complete\n", cmd); - wait_for_completion(&cmd->task_stop_comp); - pr_debug("cmd %p stopped successfully\n", cmd); - - spin_lock_irqsave(&cmd->t_state_lock, *flags); - cmd->transport_state &= ~CMD_T_REQUEST_STOP; - cmd->transport_state &= ~CMD_T_BUSY; - was_active = true; - } - - return was_active; -} - /* * Handle SAM-esque emulation for generic transport request failures. */ diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 1579539e5669..d71a3ead9e63 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -491,7 +491,6 @@ struct se_cmd { #define CMD_T_SENT (1 << 4) #define CMD_T_STOP (1 << 5) #define CMD_T_DEV_ACTIVE (1 << 7) -#define CMD_T_REQUEST_STOP (1 << 8) #define CMD_T_BUSY (1 << 9) #define CMD_T_TAS (1 << 10) #define CMD_T_FABRIC_STOP (1 << 11) @@ -514,9 +513,6 @@ struct se_cmd { struct list_head state_list; - /* old task stop completion, consider merging with some of the above */ - struct completion task_stop_comp; - /* backend private data */ void *priv; -- cgit v1.2.3 From 0633e123465b61a12a262b742bebf2a9945f7964 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 1 Feb 2016 17:29:45 +0100 Subject: target/user: Fix cast from pointer to phys_addr_t The uio_mem structure has a member that is a phys_addr_t, but can be a number of other types too. The target core driver attempts to assign a pointer from vmalloc() to it, by casting it to phys_addr_t, but that causes a warning when phys_addr_t is longer than a pointer: drivers/target/target_core_user.c: In function 'tcmu_configure_device': drivers/target/target_core_user.c:906:22: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] This adds another cast to uintptr_t to shut up the warning. A nicer fix might be to have additional fields in uio_mem for the different purposes, so we can assign a pointer directly. Signed-off-by: Arnd Bergmann Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index dd600e5ead71..94f5154ac788 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -903,7 +903,7 @@ static int tcmu_configure_device(struct se_device *dev) info->version = __stringify(TCMU_MAILBOX_VERSION); info->mem[0].name = "tcm-user command & data buffer"; - info->mem[0].addr = (phys_addr_t) udev->mb_addr; + info->mem[0].addr = (phys_addr_t)(uintptr_t)udev->mb_addr; info->mem[0].size = TCMU_RING_SIZE; info->mem[0].memtype = UIO_MEM_VIRTUAL; -- cgit v1.2.3 From e9036d0662360cd4c79578565ce422ed5872f301 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 5 Feb 2016 10:49:36 -0800 Subject: tty: Drop krefs for interrupted tty lock When the tty lock is interrupted on attempted re-open, 2 tty krefs are still held. Drop extra kref before returning failure from tty_lock_interruptible(), and drop lookup kref before returning failure from tty_open(). Fixes: 0bfd464d3fdd ("tty: Wait interruptibly for tty lock on reopen") Reported-by: Dmitry Vyukov Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 3 +-- drivers/tty/tty_mutex.c | 7 ++++++- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 5cec01c75691..a7eacef1bd22 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2066,13 +2066,12 @@ retry_open: if (tty) { mutex_unlock(&tty_mutex); retval = tty_lock_interruptible(tty); + tty_kref_put(tty); /* drop kref from tty_driver_lookup_tty() */ if (retval) { if (retval == -EINTR) retval = -ERESTARTSYS; goto err_unref; } - /* safe to drop the kref from tty_driver_lookup_tty() */ - tty_kref_put(tty); retval = tty_reopen(tty); if (retval < 0) { tty_unlock(tty); diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c index d2f3c4cd697f..dfa9ec03fa8e 100644 --- a/drivers/tty/tty_mutex.c +++ b/drivers/tty/tty_mutex.c @@ -21,10 +21,15 @@ EXPORT_SYMBOL(tty_lock); int tty_lock_interruptible(struct tty_struct *tty) { + int ret; + if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty)) return -EIO; tty_kref_get(tty); - return mutex_lock_interruptible(&tty->legacy_mutex); + ret = mutex_lock_interruptible(&tty->legacy_mutex); + if (ret) + tty_kref_put(tty); + return ret; } void __lockfunc tty_unlock(struct tty_struct *tty) -- cgit v1.2.3 From cb43285ff7039fe3c4b0bc476e6d6569c31104f3 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Thu, 4 Feb 2016 11:45:16 -0500 Subject: qla2xxx: Fix stale pointer access. [ Upstream Commit 84e32a06f4f8756ce9ec3c8dc7e97896575f0771 ] Commit 84e32a0 ("qla2xxx: Use pci_enable_msix_range() instead of pci_enable_msix()") introduced a regression when target mode is enabled. In qla24xx_enable_msix(), ha->max_rsp_queues was incorrectly set to a value higher than the number of response queues allocated causing an invalid dereference. Specifically here in qla2x00_init_rings(): *rsp->in_ptr = 0; Add additional check to make sure the pointer is valid. following call stack will be seen ---- 8< ---- RIP: 0010:[] [] qla2x00_init_rings+0xdc/0x320 [qla2xxx] RSP: 0018:ffff880429447dd8 EFLAGS: 00010082 .... Call Trace: [] qla2x00_abort_isp+0x170/0x6b0 [qla2xxx] [] qla2x00_do_dpc+0x357/0x7f0 [qla2xxx] [] ? qla2x00_relogin+0x260/0x260 [qla2xxx] [] kthread+0xc9/0xe0 [] ? flush_kthread_worker+0x90/0x90 [] ret_from_fork+0x3f/0x70 [] ? flush_kthread_worker+0x90/0x90 ---- 8< ---- Cc: Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Nicholas Bellinger --- drivers/scsi/qla2xxx/qla_init.c | 10 +++++----- drivers/scsi/qla2xxx/qla_isr.c | 4 ++-- drivers/scsi/qla2xxx/qla_mid.c | 4 ++-- drivers/scsi/qla2xxx/qla_os.c | 6 ++++++ drivers/scsi/qla2xxx/qla_tmpl.c | 16 ++++++++++++++++ 5 files changed, 31 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 52a87657c7dd..692a7570b5e1 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2204,7 +2204,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha) /* Clear outstanding commands array. */ for (que = 0; que < ha->max_req_queues; que++) { req = ha->req_q_map[que]; - if (!req) + if (!req || !test_bit(que, ha->req_qid_map)) continue; req->out_ptr = (void *)(req->ring + req->length); *req->out_ptr = 0; @@ -2221,7 +2221,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha) for (que = 0; que < ha->max_rsp_queues; que++) { rsp = ha->rsp_q_map[que]; - if (!rsp) + if (!rsp || !test_bit(que, ha->rsp_qid_map)) continue; rsp->in_ptr = (void *)(rsp->ring + rsp->length); *rsp->in_ptr = 0; @@ -4981,7 +4981,7 @@ qla25xx_init_queues(struct qla_hw_data *ha) for (i = 1; i < ha->max_rsp_queues; i++) { rsp = ha->rsp_q_map[i]; - if (rsp) { + if (rsp && test_bit(i, ha->rsp_qid_map)) { rsp->options &= ~BIT_0; ret = qla25xx_init_rsp_que(base_vha, rsp); if (ret != QLA_SUCCESS) @@ -4996,8 +4996,8 @@ qla25xx_init_queues(struct qla_hw_data *ha) } for (i = 1; i < ha->max_req_queues; i++) { req = ha->req_q_map[i]; - if (req) { - /* Clear outstanding commands array. */ + if (req && test_bit(i, ha->req_qid_map)) { + /* Clear outstanding commands array. */ req->options &= ~BIT_0; ret = qla25xx_init_req_que(base_vha, req); if (ret != QLA_SUCCESS) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index d4d65eb0e9b4..4af95479a9db 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -3063,9 +3063,9 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) "MSI-X: Failed to enable support " "-- %d/%d\n Retry with %d vectors.\n", ha->msix_count, ret, ret); + ha->msix_count = ret; + ha->max_rsp_queues = ha->msix_count - 1; } - ha->msix_count = ret; - ha->max_rsp_queues = ha->msix_count - 1; ha->msix_entries = kzalloc(sizeof(struct qla_msix_entry) * ha->msix_count, GFP_KERNEL); if (!ha->msix_entries) { diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index c5dd594f6c31..cf7ba52bae66 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -600,7 +600,7 @@ qla25xx_delete_queues(struct scsi_qla_host *vha) /* Delete request queues */ for (cnt = 1; cnt < ha->max_req_queues; cnt++) { req = ha->req_q_map[cnt]; - if (req) { + if (req && test_bit(cnt, ha->req_qid_map)) { ret = qla25xx_delete_req_que(vha, req); if (ret != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x00ea, @@ -614,7 +614,7 @@ qla25xx_delete_queues(struct scsi_qla_host *vha) /* Delete response queues */ for (cnt = 1; cnt < ha->max_rsp_queues; cnt++) { rsp = ha->rsp_q_map[cnt]; - if (rsp) { + if (rsp && test_bit(cnt, ha->rsp_qid_map)) { ret = qla25xx_delete_rsp_que(vha, rsp); if (ret != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x00eb, diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index f1788db43195..f6c7ce35b542 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -409,6 +409,9 @@ static void qla2x00_free_queues(struct qla_hw_data *ha) int cnt; for (cnt = 0; cnt < ha->max_req_queues; cnt++) { + if (!test_bit(cnt, ha->req_qid_map)) + continue; + req = ha->req_q_map[cnt]; qla2x00_free_req_que(ha, req); } @@ -416,6 +419,9 @@ static void qla2x00_free_queues(struct qla_hw_data *ha) ha->req_q_map = NULL; for (cnt = 0; cnt < ha->max_rsp_queues; cnt++) { + if (!test_bit(cnt, ha->rsp_qid_map)) + continue; + rsp = ha->rsp_q_map[cnt]; qla2x00_free_rsp_que(ha, rsp); } diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c index ddbe2e7ac14d..c3e622524604 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.c +++ b/drivers/scsi/qla2xxx/qla_tmpl.c @@ -395,6 +395,10 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_host *vha, if (ent->t263.queue_type == T263_QUEUE_TYPE_REQ) { for (i = 0; i < vha->hw->max_req_queues; i++) { struct req_que *req = vha->hw->req_q_map[i]; + + if (!test_bit(i, vha->hw->req_qid_map)) + continue; + if (req || !buf) { length = req ? req->length : REQUEST_ENTRY_CNT_24XX; @@ -408,6 +412,10 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_host *vha, } else if (ent->t263.queue_type == T263_QUEUE_TYPE_RSP) { for (i = 0; i < vha->hw->max_rsp_queues; i++) { struct rsp_que *rsp = vha->hw->rsp_q_map[i]; + + if (!test_bit(i, vha->hw->rsp_qid_map)) + continue; + if (rsp || !buf) { length = rsp ? rsp->length : RESPONSE_ENTRY_CNT_MQ; @@ -634,6 +642,10 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_host *vha, if (ent->t274.queue_type == T274_QUEUE_TYPE_REQ_SHAD) { for (i = 0; i < vha->hw->max_req_queues; i++) { struct req_que *req = vha->hw->req_q_map[i]; + + if (!test_bit(i, vha->hw->req_qid_map)) + continue; + if (req || !buf) { qla27xx_insert16(i, buf, len); qla27xx_insert16(1, buf, len); @@ -645,6 +657,10 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_host *vha, } else if (ent->t274.queue_type == T274_QUEUE_TYPE_RSP_SHAD) { for (i = 0; i < vha->hw->max_rsp_queues; i++) { struct rsp_que *rsp = vha->hw->rsp_q_map[i]; + + if (!test_bit(i, vha->hw->rsp_qid_map)) + continue; + if (rsp || !buf) { qla27xx_insert16(i, buf, len); qla27xx_insert16(1, buf, len); -- cgit v1.2.3 From d7236ac368212bd6fc8b45f050136ee53e6a6f2d Mon Sep 17 00:00:00 2001 From: Swapnil Nagle Date: Thu, 4 Feb 2016 11:45:17 -0500 Subject: qla2xxx: Use ATIO type to send correct tmr response The function value inside se_cmd can change if the TMR is cancelled. Use original ATIO Type to correctly determine CTIO response. Signed-off-by: Swapnil Nagle Signed-off-by: Himanshu Madhani Signed-off-by: Nicholas Bellinger --- drivers/scsi/qla2xxx/qla_target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 74eb776d2faa..46c667979411 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1756,7 +1756,7 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd) qlt_send_notify_ack(vha, &mcmd->orig_iocb.imm_ntfy, 0, 0, 0, 0, 0, 0); else { - if (mcmd->se_cmd.se_tmr_req->function == TMR_ABORT_TASK) + if (mcmd->orig_iocb.atio.u.raw.entry_type == ABTS_RECV_24XX) qlt_24xx_send_abts_resp(vha, &mcmd->orig_iocb.abts, mcmd->fc_tm_rsp, false); else -- cgit v1.2.3 From c8e9b92d2957a1d49abc7b81ba3f89ad530d617b Mon Sep 17 00:00:00 2001 From: Kevin Wern Date: Sat, 16 Jan 2016 13:44:41 -0800 Subject: staging/slicoss: Use ethtool_ops instead of module_param. ethtool_ops has attributes in sub struct ethtool_coalesce that correspond to the parameters intagg_delay and dynamic_intagg. It is preferable to set these properties with ethtool rather than module_param, so create these attributes in adapter and set them using ethtool_coalesce's rx_coalesce_usecs and rx_use_adaptive_coalesce. (Outlined in TODO file) Signed-off-by: Kevin Wern Signed-off-by: Greg Kroah-Hartman --- drivers/staging/slicoss/slic.h | 2 ++ drivers/staging/slicoss/slicoss.c | 41 +++++++++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h index c95b3abad646..cc0afeeb68c1 100644 --- a/drivers/staging/slicoss/slic.h +++ b/drivers/staging/slicoss/slic.h @@ -478,6 +478,8 @@ struct adapter { u32 max_isr_xmits; u32 rcv_interrupt_yields; u32 intagg_period; + u32 intagg_delay; + u32 dynamic_intagg; struct inicpm_state *inicpm_info; void *pinicpm_info; struct slic_ifevents if_events; diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index b23a2d1f61a2..c490b7166a8d 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -102,8 +102,7 @@ static char *slic_banner = "Alacritech SLIC Technology(tm) Server and Storage Ac static char *slic_proc_version = "2.0.351 2006/07/14 12:26:00"; static struct base_driver slic_global = { {}, 0, 0, 0, 1, NULL, NULL }; -static int intagg_delay = 100; -static u32 dynamic_intagg; +#define DEFAULT_INTAGG_DELAY 100 static unsigned int rcv_count; #define DRV_NAME "slicoss" @@ -119,17 +118,14 @@ MODULE_AUTHOR(DRV_AUTHOR); MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_LICENSE("Dual BSD/GPL"); -module_param(dynamic_intagg, int, 0); -MODULE_PARM_DESC(dynamic_intagg, "Dynamic Interrupt Aggregation Setting"); -module_param(intagg_delay, int, 0); -MODULE_PARM_DESC(intagg_delay, "uSec Interrupt Aggregation Delay"); - static const struct pci_device_id slic_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH, SLIC_1GB_DEVICE_ID) }, { PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH, SLIC_2GB_DEVICE_ID) }, { 0 } }; +static struct ethtool_ops slic_ethtool_ops; + MODULE_DEVICE_TABLE(pci, slic_pci_tbl); static inline void slic_reg32_write(void __iomem *reg, u32 value, bool flush) @@ -2860,7 +2856,7 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) if (slic_global.dynamic_intagg) slic_intagg_set(adapter, 0); else - slic_intagg_set(adapter, intagg_delay); + slic_intagg_set(adapter, adapter->intagg_delay); /* * Initialize ping status to "ok" @@ -2881,6 +2877,26 @@ card_init_err: return status; } +static int slic_get_coalesce(struct net_device *dev, + struct ethtool_coalesce *coalesce) +{ + struct adapter *adapter = netdev_priv(dev); + + adapter->intagg_delay = coalesce->rx_coalesce_usecs; + adapter->dynamic_intagg = coalesce->use_adaptive_rx_coalesce; + return 0; +} + +static int slic_set_coalesce(struct net_device *dev, + struct ethtool_coalesce *coalesce) +{ + struct adapter *adapter = netdev_priv(dev); + + coalesce->rx_coalesce_usecs = adapter->intagg_delay; + coalesce->use_adaptive_rx_coalesce = adapter->dynamic_intagg; + return 0; +} + static void slic_init_driver(void) { if (slic_first_init) { @@ -3069,8 +3085,6 @@ static int slic_entry_probe(struct pci_dev *pcidev, struct sliccard *card = NULL; int pci_using_dac = 0; - slic_global.dynamic_intagg = dynamic_intagg; - err = pci_enable_device(pcidev); if (err) @@ -3112,12 +3126,14 @@ static int slic_entry_probe(struct pci_dev *pcidev, goto err_out_exit_slic_probe; } + netdev->ethtool_ops = &slic_ethtool_ops; SET_NETDEV_DEV(netdev, &pcidev->dev); pci_set_drvdata(pcidev, netdev); adapter = netdev_priv(netdev); adapter->netdev = netdev; adapter->pcidev = pcidev; + slic_global.dynamic_intagg = adapter->dynamic_intagg; if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; @@ -3204,5 +3220,10 @@ static void __exit slic_module_cleanup(void) pci_unregister_driver(&slic_driver); } +static struct ethtool_ops slic_ethtool_ops = { + .get_coalesce = slic_get_coalesce, + .set_coalesce = slic_set_coalesce +}; + module_init(slic_module_init); module_exit(slic_module_cleanup); -- cgit v1.2.3 From a4b5d606b957c6a58e991de63fe999492de1ab92 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 3 Feb 2016 23:35:23 +0100 Subject: usb: core: rename mutex usb_bus_list_lock to usb_bus_idr_lock Now that usb_bus_list has been removed and switched to idr rename the related mutex accordingly. Signed-off-by: Heiner Kallweit Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devices.c | 6 +++--- drivers/usb/core/hcd.c | 30 +++++++++++++++--------------- drivers/usb/core/hub.c | 4 ++-- drivers/usb/mon/mon_main.c | 4 ++-- include/linux/usb/hcd.h | 2 +- 5 files changed, 23 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 6118a04f0b84..ef04b50e6bbb 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -620,7 +620,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, if (!access_ok(VERIFY_WRITE, buf, nbytes)) return -EFAULT; - mutex_lock(&usb_bus_list_lock); + mutex_lock(&usb_bus_idr_lock); /* print devices for all busses */ idr_for_each_entry(&usb_bus_idr, bus, id) { /* recurse through all children of the root hub */ @@ -631,12 +631,12 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, bus->root_hub, bus, 0, 0, 0); usb_unlock_device(bus->root_hub); if (ret < 0) { - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); return ret; } total_written += ret; } - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); return total_written; } diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index cf3eb22dbeb4..0b8a91004737 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -97,8 +97,8 @@ EXPORT_SYMBOL_GPL (usb_bus_idr); #define USB_MAXBUS 64 /* used when updating list of hcds */ -DEFINE_MUTEX(usb_bus_list_lock); /* exported only for usbfs */ -EXPORT_SYMBOL_GPL (usb_bus_list_lock); +DEFINE_MUTEX(usb_bus_idr_lock); /* exported only for usbfs */ +EXPORT_SYMBOL_GPL (usb_bus_idr_lock); /* used for controlling access to virtual root hubs */ static DEFINE_SPINLOCK(hcd_root_hub_lock); @@ -1014,14 +1014,14 @@ static int usb_register_bus(struct usb_bus *bus) int result = -E2BIG; int busnum; - mutex_lock(&usb_bus_list_lock); + mutex_lock(&usb_bus_idr_lock); busnum = idr_alloc(&usb_bus_idr, bus, 1, USB_MAXBUS, GFP_KERNEL); if (busnum < 0) { pr_err("%s: failed to get bus number\n", usbcore_name); goto error_find_busnum; } bus->busnum = busnum; - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); usb_notify_add_bus(bus); @@ -1030,7 +1030,7 @@ static int usb_register_bus(struct usb_bus *bus) return 0; error_find_busnum: - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); return result; } @@ -1051,9 +1051,9 @@ static void usb_deregister_bus (struct usb_bus *bus) * controller code, as well as having it call this when cleaning * itself up */ - mutex_lock(&usb_bus_list_lock); + mutex_lock(&usb_bus_idr_lock); idr_remove(&usb_bus_idr, bus->busnum); - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); usb_notify_remove_bus(bus); } @@ -1083,12 +1083,12 @@ static int register_root_hub(struct usb_hcd *hcd) set_bit (devnum, usb_dev->bus->devmap.devicemap); usb_set_device_state(usb_dev, USB_STATE_ADDRESS); - mutex_lock(&usb_bus_list_lock); + mutex_lock(&usb_bus_idr_lock); usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); if (retval != sizeof usb_dev->descriptor) { - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); dev_dbg (parent_dev, "can't read %s device descriptor %d\n", dev_name(&usb_dev->dev), retval); return (retval < 0) ? retval : -EMSGSIZE; @@ -1099,7 +1099,7 @@ static int register_root_hub(struct usb_hcd *hcd) if (!retval) { usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev); } else if (usb_dev->speed >= USB_SPEED_SUPER) { - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); dev_dbg(parent_dev, "can't read %s bos descriptor %d\n", dev_name(&usb_dev->dev), retval); return retval; @@ -1119,7 +1119,7 @@ static int register_root_hub(struct usb_hcd *hcd) if (HCD_DEAD(hcd)) usb_hc_died (hcd); /* This time clean up */ } - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); return retval; } @@ -2885,9 +2885,9 @@ error_create_attr_group: #ifdef CONFIG_PM cancel_work_sync(&hcd->wakeup_work); #endif - mutex_lock(&usb_bus_list_lock); + mutex_lock(&usb_bus_idr_lock); usb_disconnect(&rhdev); /* Sets rhdev to NULL */ - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); err_register_root_hub: hcd->rh_pollable = 0; clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); @@ -2954,9 +2954,9 @@ void usb_remove_hcd(struct usb_hcd *hcd) cancel_work_sync(&hcd->wakeup_work); #endif - mutex_lock(&usb_bus_list_lock); + mutex_lock(&usb_bus_idr_lock); usb_disconnect(&rhdev); /* Sets rhdev to NULL */ - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); /* * tasklet_kill() isn't needed here because: diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f912fe6bbc0b..3d46d03a785b 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2145,7 +2145,7 @@ static void hub_disconnect_children(struct usb_device *udev) * Something got disconnected. Get rid of it and all of its children. * * If *pdev is a normal device then the parent hub must already be locked. - * If *pdev is a root hub then the caller must hold the usb_bus_list_lock, + * If *pdev is a root hub then the caller must hold the usb_bus_idr_lock, * which protects the set of root hubs as well as the list of buses. * * Only hub drivers (including virtual root hub drivers for host @@ -2443,7 +2443,7 @@ static void set_usb_port_removable(struct usb_device *udev) * enumerated. The device descriptor is available, but not descriptors * for any device configuration. The caller must have locked either * the parent hub (if udev is a normal device) or else the - * usb_bus_list_lock (if udev is a root hub). The parent's pointer to + * usb_bus_idr_lock (if udev is a root hub). The parent's pointer to * udev has already been installed, but udev is not yet visible through * sysfs or other filesystem code. * diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index 9b87efb0e50d..33ff49c4cea4 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c @@ -365,11 +365,11 @@ static int __init mon_init(void) } // MOD_INC_USE_COUNT(which_module?); - mutex_lock(&usb_bus_list_lock); + mutex_lock(&usb_bus_idr_lock); idr_for_each_entry(&usb_bus_idr, ubus, id) mon_bus_init(ubus); usb_register_notify(&mon_nb); - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); return 0; err_reg: diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index c293dd044599..b98f831dcda3 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -632,7 +632,7 @@ extern void usb_set_device_state(struct usb_device *udev, /* exported only within usbcore */ extern struct idr usb_bus_idr; -extern struct mutex usb_bus_list_lock; +extern struct mutex usb_bus_idr_lock; extern wait_queue_head_t usb_kill_urb_queue; -- cgit v1.2.3 From b1249ab513017efdff646b26b46b5399bd91773b Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 3 Feb 2016 23:36:33 +0100 Subject: usb: r8a66597: add locking to r8a66597_check_detect_child Use mutex usb_bus_idr_lock to protect idr_find. Signed-off-by: Heiner Kallweit Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/r8a66597-hcd.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 1ef887361ac0..bfa7fa3d2eea 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2099,11 +2099,13 @@ static void r8a66597_check_detect_child(struct r8a66597 *r8a66597, memset(now_map, 0, sizeof(now_map)); + mutex_lock(&usb_bus_idr_lock); bus = idr_find(&usb_bus_idr, hcd->self.busnum); if (bus && bus->root_hub) { collect_usb_address_map(bus->root_hub, now_map); update_usb_address_map(r8a66597, bus->root_hub, now_map); } + mutex_unlock(&usb_bus_idr_lock); } static int r8a66597_hub_status_data(struct usb_hcd *hcd, char *buf) -- cgit v1.2.3 From abb4f8addf1d55f3a63ac84e3d9f609f97e5b9a0 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 5 Feb 2016 15:26:54 +0530 Subject: staging: wilc1000: fix build failure allmodconfig build of alpha, m68k, m32r, tilepro has failed with the error: drivers/staging/wilc1000/wilc_wfi_cfgoperations.c: In function 'wilc_create_wiphy': drivers/staging/wilc1000/wilc_wfi_cfgoperations.c:2632:13: error: 'struct wiphy' has no member named 'wowlan' Looking at other drivers wowlan can be only used when CONFIG_PM is defined. Fixes: 73584a40d748 ("staging: wilc1000: add ops resuem/suspend/wakeup in cfg80211") Cc: Glen Lee Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 4eede2b4e661..28a6ffa6d907 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2629,7 +2629,9 @@ struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct device *de sema_init(&(priv->SemHandleUpdateStats), 1); priv->wdev = wdev; wdev->wiphy->max_scan_ssids = MAX_NUM_PROBED_SSID; +#ifdef CONFIG_PM wdev->wiphy->wowlan = &wowlan_support; +#endif wdev->wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS; PRINT_INFO(CFG80211_DBG, "Max number of PMKIDs = %d\n", wdev->wiphy->max_num_pmkids); -- cgit v1.2.3 From 2bcfdc23c6a418b441a1d17f237e9ea347e2fb1f Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 7 Jan 2016 14:46:34 +0200 Subject: mei: bus: remove redundant uuid string in debug messages Remove uuid from the debug messages in bus-fixup.c as this is already part of the device name. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus-fixup.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c index 020de5919c21..b2d2a6ea576c 100644 --- a/drivers/misc/mei/bus-fixup.c +++ b/drivers/misc/mei/bus-fixup.c @@ -48,8 +48,7 @@ static const uuid_le mei_nfc_info_guid = MEI_UUID_NFC_INFO; */ static void number_of_connections(struct mei_cl_device *cldev) { - dev_dbg(&cldev->dev, "running hook %s on %pUl\n", - __func__, mei_me_cl_uuid(cldev->me_cl)); + dev_dbg(&cldev->dev, "running hook %s\n", __func__); if (cldev->me_cl->props.max_number_of_connections > 1) cldev->do_match = 0; @@ -62,8 +61,8 @@ static void number_of_connections(struct mei_cl_device *cldev) */ static void blacklist(struct mei_cl_device *cldev) { - dev_dbg(&cldev->dev, "running hook %s on %pUl\n", - __func__, mei_me_cl_uuid(cldev->me_cl)); + dev_dbg(&cldev->dev, "running hook %s\n", __func__); + cldev->do_match = 0; } @@ -208,8 +207,7 @@ static void mei_nfc(struct mei_cl_device *cldev) bus = cldev->bus; - dev_dbg(bus->dev, "running hook %s: %pUl match=%d\n", - __func__, mei_me_cl_uuid(cldev->me_cl), cldev->do_match); + dev_dbg(&cldev->dev, "running hook %s\n", __func__); mutex_lock(&bus->device_lock); /* we need to connect to INFO GUID */ -- cgit v1.2.3 From 13cf988562b0c7f06e0016bea2b5304358397702 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Thu, 7 Jan 2016 14:46:36 +0200 Subject: mei: prevent queuing new flow control credit. The MEI FW can receive only one flow control for read. Currently the driver only checks if a flow control credit was already sent and read is pending in the rd_pending queue, but it also has to check if flow control credit already queued in the write control queue to prevent sending more than one flow control credits. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index a6c87c713193..72e32615acd9 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1421,6 +1421,25 @@ out: return 0; } +/** + * mei_cl_is_read_fc_cb - check if read cb is waiting for flow control + * for given host client + * + * @cl: host client + * + * Return: true, if found at least one cb. + */ +static bool mei_cl_is_read_fc_cb(struct mei_cl *cl) +{ + struct mei_device *dev = cl->dev; + struct mei_cl_cb *cb; + + list_for_each_entry(cb, &dev->ctrl_wr_list.list, list) + if (cb->fop_type == MEI_FOP_READ && cb->cl == cl) + return true; + return false; +} + /** * mei_cl_read_start - the start read client message function. * @@ -1445,7 +1464,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp) return -ENODEV; /* HW currently supports only one pending read */ - if (!list_empty(&cl->rd_pending)) + if (!list_empty(&cl->rd_pending) || mei_cl_is_read_fc_cb(cl)) return -EBUSY; if (!mei_me_cl_is_active(cl->me_cl)) { -- cgit v1.2.3 From 8b2458f413c429e4c5c4799e02ec2820396aaac4 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Thu, 7 Jan 2016 14:46:37 +0200 Subject: mei: always copy the read buffer if data is ready Copy completed callback content to the user space if we have such callback ready in the beginning of the read. Simplify offset processing logic as byproduct. This is a refinement for: commit 139aacf757fc ("mei: fix read after read scenario") Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/main.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 677d0362f334..36ca15234344 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -159,27 +159,22 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, goto out; } + if (ubuf == NULL) { + rets = -EMSGSIZE; + goto out; + } + if (cl == &dev->iamthif_cl) { rets = mei_amthif_read(dev, file, ubuf, length, offset); goto out; } cb = mei_cl_read_cb(cl, file); - if (cb) { - /* read what left */ - if (cb->buf_idx > *offset) - goto copy_buffer; - /* offset is beyond buf_idx we have no more data return 0 */ - if (cb->buf_idx > 0 && cb->buf_idx <= *offset) { - rets = 0; - goto free; - } - /* Offset needs to be cleaned for contiguous reads*/ - if (cb->buf_idx == 0 && *offset > 0) - *offset = 0; - } else if (*offset > 0) { + if (cb) + goto copy_buffer; + + if (*offset > 0) *offset = 0; - } err = mei_cl_read_start(cl, length, file); if (err && err != -EBUSY) { @@ -231,10 +226,10 @@ copy_buffer: goto free; } - cl_dbg(dev, cl, "buf.size = %d buf.idx = %ld\n", - cb->buf.size, cb->buf_idx); - if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) { - rets = -EMSGSIZE; + cl_dbg(dev, cl, "buf.size = %d buf.idx = %ld offset = %lld\n", + cb->buf.size, cb->buf_idx, *offset); + if (*offset >= cb->buf_idx) { + rets = 0; goto free; } @@ -255,6 +250,7 @@ copy_buffer: free: mei_io_cb_free(cb); + *offset = 0; out: cl_dbg(dev, cl, "end mei read rets = %d\n", rets); -- cgit v1.2.3 From b86d1bd8d1a0f67f12b62e5ee724514f19dc6bf8 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 7 Jan 2016 14:46:39 +0200 Subject: mei: drop nfc leftovers from the mei driver We left few function prototypes in the header file after moving nfc logic to bus. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/mei_dev.h | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 4250555d5e72..b54d9d9cacea 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -649,17 +649,6 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, struct mei_cl_cb *complete_list); int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); -/* - * NFC functions - */ -int mei_nfc_host_init(struct mei_device *dev, struct mei_me_client *me_cl); -void mei_nfc_host_exit(struct mei_device *dev); - -/* - * NFC Client UUID - */ -extern const uuid_le mei_nfc_guid; - int mei_wd_send(struct mei_device *dev); int mei_wd_stop(struct mei_device *dev); int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl); -- cgit v1.2.3 From 8477614d9f7c5ce0e871e1aa200d9060a6b8749e Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:38 -0800 Subject: of: earlycon: of_setup_earlycon() requires CONFIG_OF_EARLY_FLATTREE DT earlycon is only supported for CONFIG_OF_EARLY_FLATTREE=y; exclude of_setup_earlycon() if not defined. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/earlycon.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 3f2423690d01..54419a210dc3 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -204,6 +204,8 @@ static int __init param_setup_earlycon(char *buf) } early_param("earlycon", param_setup_earlycon); +#ifdef CONFIG_OF_EARLY_FLATTREE + int __init of_setup_earlycon(unsigned long addr, int (*setup)(struct earlycon_device *, const char *)) { @@ -227,3 +229,5 @@ int __init of_setup_earlycon(unsigned long addr, register_console(early_console_dev.con); return 0; } + +#endif /* CONFIG_OF_EARLY_FLATTREE */ -- cgit v1.2.3 From 2eaa790989e03900298ad24f77f1086dbbc1aebd Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:39 -0800 Subject: earlycon: Use common framework for earlycon declarations Use a single common table of struct earlycon_id for both command line and devicetree. Re-define OF_EARLYCON_DECLARE() macro to instance a unique earlycon declaration (the declaration is only guaranteed to be unique within a compilation unit; separate compilation units must still use unique earlycon names). The semantics of OF_EARLYCON_DECLARE() is different; it declares an earlycon which can matched either on the command line or by devicetree. EARLYCON_DECLARE() is semantically unchanged; it declares an earlycon which is matched by command line only. Remove redundant instances of EARLYCON_DECLARE(). This enables all earlycons to properly initialize struct console with the appropriate name and index, which improves diagnostics and enables direct earlycon-to-console handoff. Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/of/fdt.c | 14 +++++++------- drivers/tty/serial/amba-pl011.c | 1 - drivers/tty/serial/arc_uart.c | 1 - drivers/tty/serial/earlycon.c | 10 +--------- drivers/tty/serial/msm_serial.c | 2 -- drivers/tty/serial/samsung.c | 6 ------ drivers/tty/serial/sprd_serial.c | 2 -- include/asm-generic/vmlinux.lds.h | 6 ++---- include/linux/serial_core.h | 22 +++++++++++++--------- 9 files changed, 23 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 655f79db7899..168611867611 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -796,14 +796,13 @@ static inline void early_init_dt_check_for_initrd(unsigned long node) #endif /* CONFIG_BLK_DEV_INITRD */ #ifdef CONFIG_SERIAL_EARLYCON -extern struct of_device_id __earlycon_of_table[]; static int __init early_init_dt_scan_chosen_serial(void) { int offset; const char *p; int l; - const struct of_device_id *match = __earlycon_of_table; + const struct earlycon_id *match; const void *fdt = initial_boot_params; offset = fdt_path_offset(fdt, "/chosen"); @@ -826,19 +825,20 @@ static int __init early_init_dt_scan_chosen_serial(void) if (offset < 0) return -ENODEV; - while (match->compatible[0]) { + for (match = __earlycon_table; match < __earlycon_table_end; match++) { u64 addr; - if (fdt_node_check_compatible(fdt, offset, match->compatible)) { - match++; + if (!match->compatible[0]) + continue; + + if (fdt_node_check_compatible(fdt, offset, match->compatible)) continue; - } addr = fdt_translate_address(fdt, offset); if (addr == OF_BAD_ADDR) return -ENXIO; - of_setup_earlycon(addr, match->data); + of_setup_earlycon(addr, match->setup); return 0; } return -ENODEV; diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index c0da0ccbbcf5..de846027ba47 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2327,7 +2327,6 @@ static int __init pl011_early_console_setup(struct earlycon_device *device, device->con->write = pl011_early_write; return 0; } -EARLYCON_DECLARE(pl011, pl011_early_console_setup); OF_EARLYCON_DECLARE(pl011, "arm,pl011", pl011_early_console_setup); #else diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c index 03ebe401fff7..3a1de5c87cb4 100644 --- a/drivers/tty/serial/arc_uart.c +++ b/drivers/tty/serial/arc_uart.c @@ -576,7 +576,6 @@ static int __init arc_early_console_setup(struct earlycon_device *dev, dev->con->write = arc_early_serial_write; return 0; } -EARLYCON_DECLARE(arc_uart, arc_early_console_setup); OF_EARLYCON_DECLARE(arc_uart, "snps,arc-uart", arc_early_console_setup); #endif /* CONFIG_SERIAL_ARC_CONSOLE */ diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 54419a210dc3..d50b70053418 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -19,7 +19,6 @@ #include #include #include -#include #ifdef CONFIG_FIX_EARLYCON_MEM #include @@ -37,13 +36,6 @@ static struct earlycon_device early_console_dev = { .con = &early_con, }; -extern struct earlycon_id __earlycon_table[]; -static const struct earlycon_id __earlycon_table_sentinel - __used __section(__earlycon_table_end); - -static const struct of_device_id __earlycon_of_table_sentinel - __used __section(__earlycon_of_table_end); - static void __iomem * __init earlycon_map(unsigned long paddr, size_t size) { void __iomem *base; @@ -166,7 +158,7 @@ int __init setup_earlycon(char *buf) if (early_con.flags & CON_ENABLED) return -EALREADY; - for (match = __earlycon_table; match->name[0]; match++) { + for (match = __earlycon_table; match < __earlycon_table_end; match++) { size_t len = strlen(match->name); if (strncmp(buf, match->name, len)) diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index dcde955475dc..96d3ce8dc2dc 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -1478,7 +1478,6 @@ msm_serial_early_console_setup(struct earlycon_device *device, const char *opt) device->con->write = msm_serial_early_write; return 0; } -EARLYCON_DECLARE(msm_serial, msm_serial_early_console_setup); OF_EARLYCON_DECLARE(msm_serial, "qcom,msm-uart", msm_serial_early_console_setup); @@ -1500,7 +1499,6 @@ msm_serial_early_console_setup_dm(struct earlycon_device *device, device->con->write = msm_serial_early_write_dm; return 0; } -EARLYCON_DECLARE(msm_serial_dm, msm_serial_early_console_setup_dm); OF_EARLYCON_DECLARE(msm_serial_dm, "qcom,msm-uartdm", msm_serial_early_console_setup_dm); diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index d72cd736bdc6..fd9c47f2f29f 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -2451,7 +2451,6 @@ static int __init s3c2410_early_console_setup(struct earlycon_device *device, } OF_EARLYCON_DECLARE(s3c2410, "samsung,s3c2410-uart", s3c2410_early_console_setup); -EARLYCON_DECLARE(s3c2410, s3c2410_early_console_setup); /* S3C2412, S3C2440, S3C64xx */ static struct samsung_early_console_data s3c2440_early_console_data = { @@ -2470,9 +2469,6 @@ OF_EARLYCON_DECLARE(s3c2440, "samsung,s3c2440-uart", s3c2440_early_console_setup); OF_EARLYCON_DECLARE(s3c6400, "samsung,s3c6400-uart", s3c2440_early_console_setup); -EARLYCON_DECLARE(s3c2412, s3c2440_early_console_setup); -EARLYCON_DECLARE(s3c2440, s3c2440_early_console_setup); -EARLYCON_DECLARE(s3c6400, s3c2440_early_console_setup); /* S5PV210, EXYNOS */ static struct samsung_early_console_data s5pv210_early_console_data = { @@ -2489,8 +2485,6 @@ OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart", s5pv210_early_console_setup); OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart", s5pv210_early_console_setup); -EARLYCON_DECLARE(s5pv210, s5pv210_early_console_setup); -EARLYCON_DECLARE(exynos4210, s5pv210_early_console_setup); #endif MODULE_ALIAS("platform:samsung-uart"); diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c index ef26c4a60be4..18971063f95f 100644 --- a/drivers/tty/serial/sprd_serial.c +++ b/drivers/tty/serial/sprd_serial.c @@ -624,8 +624,6 @@ static int __init sprd_early_console_setup( device->con->write = sprd_early_write; return 0; } - -EARLYCON_DECLARE(sprd_serial, sprd_early_console_setup); OF_EARLYCON_DECLARE(sprd_serial, "sprd,sc9836-uart", sprd_early_console_setup); diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index c4bd0e2c173c..e9a81a6a109f 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -157,7 +157,7 @@ #define EARLYCON_TABLE() STRUCT_ALIGN(); \ VMLINUX_SYMBOL(__earlycon_table) = .; \ *(__earlycon_table) \ - *(__earlycon_table_end) + VMLINUX_SYMBOL(__earlycon_table_end) = .; #else #define EARLYCON_TABLE() #endif @@ -179,7 +179,6 @@ #define RESERVEDMEM_OF_TABLES() OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem) #define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method) #define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method) -#define EARLYCON_OF_TABLES() OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon) #ifdef CONFIG_ACPI #define ACPI_PROBE_TABLE(name) \ @@ -526,8 +525,7 @@ IRQCHIP_OF_MATCH_TABLE() \ ACPI_PROBE_TABLE(irqchip) \ ACPI_PROBE_TABLE(clksrc) \ - EARLYCON_TABLE() \ - EARLYCON_OF_TABLES() + EARLYCON_TABLE() #define INIT_TEXT \ *(.init.text) \ diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index e03d6ba5e5b4..25e05147f379 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -342,22 +342,26 @@ struct earlycon_device { struct earlycon_id { char name[16]; + char compatible[128]; int (*setup)(struct earlycon_device *, const char *options); } __aligned(32); +extern const struct earlycon_id __earlycon_table[]; +extern const struct earlycon_id __earlycon_table_end[]; + +#define OF_EARLYCON_DECLARE(_name, compat, fn) \ + static const struct earlycon_id __UNIQUE_ID(__earlycon_##_name) \ + __used __section(__earlycon_table) \ + = { .name = __stringify(_name), \ + .compatible = compat, \ + .setup = fn } + +#define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn) + extern int setup_earlycon(char *buf); extern int of_setup_earlycon(unsigned long addr, int (*setup)(struct earlycon_device *, const char *)); -#define EARLYCON_DECLARE(_name, func) \ - static const struct earlycon_id __earlycon_##_name \ - __used __section(__earlycon_table) \ - = { .name = __stringify(_name), \ - .setup = func } - -#define OF_EARLYCON_DECLARE(name, compat, fn) \ - _OF_DECLARE(earlycon, name, compat, fn, void *) - struct uart_port *uart_get_console(struct uart_port *ports, int nr, struct console *c); int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr, -- cgit v1.2.3 From cda64e68240265752c6db22a75f28707dfaf6563 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:40 -0800 Subject: serial: earlycon: Fixup earlycon console name and index Properly initialize the struct console 'name' and 'index' fields for the registering earlycon. For earlycons w/o trailing numerals, the index is set to 0; otherwise, the index is set to the value of the trailing numeral. For example, the 'exynos4210' earlycon name == "exynos" and index == 4210. Earlycons with embedded numerals will have all non-trailing numerals as part of the name; for example, the 's3c2412' earlycon name == "s3c" and index == 2412. This ackward scheme was initially added for the uart8250 earlycon; adopt this scheme for the other earlycon "drivers". Introduce earlycon_init() which performs the string scanning and initializes the name and index fields; encapsulate the other console field initializations within. Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/earlycon.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index d50b70053418..90b064faa1c4 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -27,9 +27,9 @@ #include static struct console early_con = { - .name = "uart", /* 8250 console switch requires this name */ + .name = "uart", /* fixed up at earlycon registration */ .flags = CON_PRINTBUFFER | CON_BOOT, - .index = -1, + .index = 0, }; static struct earlycon_device early_console_dev = { @@ -53,6 +53,25 @@ static void __iomem * __init earlycon_map(unsigned long paddr, size_t size) return base; } +static void __init earlycon_init(struct earlycon_device *device, + const char *name) +{ + struct console *earlycon = device->con; + const char *s; + size_t len; + + /* scan backwards from end of string for first non-numeral */ + for (s = name + strlen(name); + s > name && s[-1] >= '0' && s[-1] <= '9'; + s--) + ; + if (*s) + earlycon->index = simple_strtoul(s, NULL, 10); + len = s - name; + strlcpy(earlycon->name, name, min(len + 1, sizeof(earlycon->name))); + earlycon->data = &early_console_dev; +} + static int __init parse_options(struct earlycon_device *device, char *options) { struct uart_port *port = &device->port; @@ -119,7 +138,7 @@ static int __init register_earlycon(char *buf, const struct earlycon_id *match) if (port->mapbase) port->membase = earlycon_map(port->mapbase, 64); - early_console_dev.con->data = &early_console_dev; + earlycon_init(&early_console_dev, match->name); err = match->setup(&early_console_dev, buf); if (err < 0) return err; -- cgit v1.2.3 From 05d961320ba624c98b16d72b32f947307674b341 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:41 -0800 Subject: of: earlycon: Fixup earlycon console name and index Use the console name embedded in the OF earlycon table by the OF_EARLYCON_DECLARE() macro to initialize the struct console 'name' and 'index' fields. Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/of/fdt.c | 2 +- drivers/tty/serial/earlycon.c | 6 +++--- include/linux/serial_core.h | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 168611867611..ec1459517de6 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -838,7 +838,7 @@ static int __init early_init_dt_scan_chosen_serial(void) if (addr == OF_BAD_ADDR) return -ENXIO; - of_setup_earlycon(addr, match->setup); + of_setup_earlycon(addr, match); return 0; } return -ENODEV; diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 90b064faa1c4..47e54deb944b 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -218,7 +218,7 @@ early_param("earlycon", param_setup_earlycon); #ifdef CONFIG_OF_EARLY_FLATTREE int __init of_setup_earlycon(unsigned long addr, - int (*setup)(struct earlycon_device *, const char *)) + const struct earlycon_id *match) { int err; struct uart_port *port = &early_console_dev.port; @@ -229,8 +229,8 @@ int __init of_setup_earlycon(unsigned long addr, port->uartclk = BASE_BAUD * 16; port->membase = earlycon_map(addr, SZ_4K); - early_console_dev.con->data = &early_console_dev; - err = setup(&early_console_dev, NULL); + earlycon_init(&early_console_dev, match->name); + err = match->setup(&early_console_dev, NULL); if (err < 0) return err; if (!early_console_dev.con->write) diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 25e05147f379..63fdb55e4c9d 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -359,8 +359,7 @@ extern const struct earlycon_id __earlycon_table_end[]; #define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn) extern int setup_earlycon(char *buf); -extern int of_setup_earlycon(unsigned long addr, - int (*setup)(struct earlycon_device *, const char *)); +extern int of_setup_earlycon(unsigned long addr, const struct earlycon_id *match); struct uart_port *uart_get_console(struct uart_port *ports, int nr, struct console *c); -- cgit v1.2.3 From 4d118c9a866590850dad8689262a95345d2c6e09 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:42 -0800 Subject: of: earlycon: Add options string handling Pass-through any options string in the 'stdout-path' property to the earlycon "driver" setup. Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/of/fdt.c | 11 ++++++----- drivers/tty/serial/earlycon.c | 9 +++++++-- include/linux/serial_core.h | 3 ++- 3 files changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index ec1459517de6..cfd3b35e8d81 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -800,7 +800,7 @@ static inline void early_init_dt_check_for_initrd(unsigned long node) static int __init early_init_dt_scan_chosen_serial(void) { int offset; - const char *p; + const char *p, *q, *options = NULL; int l; const struct earlycon_id *match; const void *fdt = initial_boot_params; @@ -817,11 +817,12 @@ static int __init early_init_dt_scan_chosen_serial(void) if (!p || !l) return -ENOENT; - /* Remove console options if present */ - l = strchrnul(p, ':') - p; + q = strchrnul(p, ':'); + if (*q != '\0') + options = q + 1; /* Get the node specified by stdout-path */ - offset = fdt_path_offset_namelen(fdt, p, l); + offset = fdt_path_offset_namelen(fdt, p, q - p); if (offset < 0) return -ENODEV; @@ -838,7 +839,7 @@ static int __init early_init_dt_scan_chosen_serial(void) if (addr == OF_BAD_ADDR) return -ENXIO; - of_setup_earlycon(addr, match); + of_setup_earlycon(addr, match, options); return 0; } return -ENODEV; diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 47e54deb944b..7509ee34de28 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -218,7 +218,8 @@ early_param("earlycon", param_setup_earlycon); #ifdef CONFIG_OF_EARLY_FLATTREE int __init of_setup_earlycon(unsigned long addr, - const struct earlycon_id *match) + const struct earlycon_id *match, + const char *options) { int err; struct uart_port *port = &early_console_dev.port; @@ -229,8 +230,12 @@ int __init of_setup_earlycon(unsigned long addr, port->uartclk = BASE_BAUD * 16; port->membase = earlycon_map(addr, SZ_4K); + if (options) { + strlcpy(early_console_dev.options, options, + sizeof(early_console_dev.options)); + } earlycon_init(&early_console_dev, match->name); - err = match->setup(&early_console_dev, NULL); + err = match->setup(&early_console_dev, options); if (err < 0) return err; if (!early_console_dev.con->write) diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 63fdb55e4c9d..62a4df05eaca 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -359,7 +359,8 @@ extern const struct earlycon_id __earlycon_table_end[]; #define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn) extern int setup_earlycon(char *buf); -extern int of_setup_earlycon(unsigned long addr, const struct earlycon_id *match); +extern int of_setup_earlycon(unsigned long addr, const struct earlycon_id *match, + const char *options); struct uart_port *uart_get_console(struct uart_port *ports, int nr, struct console *c); -- cgit v1.2.3 From 088da2a17619cf0113b62a76ad38c6a14470ffa6 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:43 -0800 Subject: of: earlycon: Initialize port fields from DT properties Read the optional "reg-offset", "reg-shift", "reg-io-width" and endianness properties and initialize the respective struct uart_port field if found. NB: These bindings are common to several drivers and the values merely indicate the default value; the registering earlycon setup() method can simply override the values if required. Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/of/fdt.c | 2 +- drivers/tty/serial/earlycon.c | 31 +++++++++++++++++++++++++++++++ include/linux/serial_core.h | 1 + 3 files changed, 33 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index cfd3b35e8d81..e8fd54a30802 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -839,7 +839,7 @@ static int __init early_init_dt_scan_chosen_serial(void) if (addr == OF_BAD_ADDR) return -ENXIO; - of_setup_earlycon(addr, match, options); + of_setup_earlycon(addr, match, offset, options); return 0; } return -ENODEV; diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 7509ee34de28..7089667bde93 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -19,6 +19,7 @@ #include #include #include +#include #ifdef CONFIG_FIX_EARLYCON_MEM #include @@ -219,10 +220,13 @@ early_param("earlycon", param_setup_earlycon); int __init of_setup_earlycon(unsigned long addr, const struct earlycon_id *match, + unsigned long node, const char *options) { int err; struct uart_port *port = &early_console_dev.port; + const __be32 *val; + bool big_endian; spin_lock_init(&port->lock); port->iotype = UPIO_MEM; @@ -230,6 +234,33 @@ int __init of_setup_earlycon(unsigned long addr, port->uartclk = BASE_BAUD * 16; port->membase = earlycon_map(addr, SZ_4K); + val = of_get_flat_dt_prop(node, "reg-offset", NULL); + if (val) + port->mapbase += be32_to_cpu(*val); + val = of_get_flat_dt_prop(node, "reg-shift", NULL); + if (val) + port->regshift = be32_to_cpu(*val); + big_endian = of_get_flat_dt_prop(node, "big-endian", NULL) != NULL || + (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) && + of_get_flat_dt_prop(node, "native-endian", NULL) != NULL); + val = of_get_flat_dt_prop(node, "reg-io-width", NULL); + if (val) { + switch (be32_to_cpu(*val)) { + case 1: + port->iotype = UPIO_MEM; + break; + case 2: + port->iotype = UPIO_MEM16; + break; + case 4: + port->iotype = (big_endian) ? UPIO_MEM32BE : UPIO_MEM32; + break; + default: + pr_warn("[%s] unsupported reg-io-width\n", match->name); + return -EINVAL; + } + } + if (options) { strlcpy(early_console_dev.options, options, sizeof(early_console_dev.options)); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 62a4df05eaca..6d1bed821181 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -360,6 +360,7 @@ extern const struct earlycon_id __earlycon_table_end[]; extern int setup_earlycon(char *buf); extern int of_setup_earlycon(unsigned long addr, const struct earlycon_id *match, + unsigned long node, const char *options); struct uart_port *uart_get_console(struct uart_port *ports, int nr, -- cgit v1.2.3 From c90fe9c0394b068ceca16f66e9f35bcd8d948295 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:44 -0800 Subject: of: earlycon: Move address translation to of_setup_earlycon() Cleanup the early DT/earlycon separation; remove the 'addr' parameter from of_setup_earlycon() and get the uart phys addr directly with a new wrapper function, of_flat_dt_translate_addr(). Limit fdt_translate_address() to file scope. Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/of/fdt.c | 8 +------- drivers/of/fdt_address.c | 11 ++++++++++- drivers/tty/serial/earlycon.c | 12 +++++++++--- include/linux/of_fdt.h | 2 +- include/linux/serial_core.h | 2 +- 5 files changed, 22 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index e8fd54a30802..918809e6f913 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -827,19 +827,13 @@ static int __init early_init_dt_scan_chosen_serial(void) return -ENODEV; for (match = __earlycon_table; match < __earlycon_table_end; match++) { - u64 addr; - if (!match->compatible[0]) continue; if (fdt_node_check_compatible(fdt, offset, match->compatible)) continue; - addr = fdt_translate_address(fdt, offset); - if (addr == OF_BAD_ADDR) - return -ENXIO; - - of_setup_earlycon(addr, match, offset, options); + of_setup_earlycon(match, offset, options); return 0; } return -ENODEV; diff --git a/drivers/of/fdt_address.c b/drivers/of/fdt_address.c index 8d3dc6fbdb7a..dca8f9b93745 100644 --- a/drivers/of/fdt_address.c +++ b/drivers/of/fdt_address.c @@ -161,7 +161,7 @@ static int __init fdt_translate_one(const void *blob, int parent, * that can be mapped to a cpu physical address). This is not really specified * that way, but this is traditionally the way IBM at least do things */ -u64 __init fdt_translate_address(const void *blob, int node_offset) +static u64 __init fdt_translate_address(const void *blob, int node_offset) { int parent, len; const struct of_bus *bus, *pbus; @@ -239,3 +239,12 @@ u64 __init fdt_translate_address(const void *blob, int node_offset) bail: return result; } + +/** + * of_flat_dt_translate_address - translate DT addr into CPU phys addr + * @node: node in the flat blob + */ +u64 __init of_flat_dt_translate_address(unsigned long node) +{ + return fdt_translate_address(initial_boot_params, node); +} diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 7089667bde93..baee9ad59af7 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #ifdef CONFIG_FIX_EARLYCON_MEM @@ -218,8 +219,7 @@ early_param("earlycon", param_setup_earlycon); #ifdef CONFIG_OF_EARLY_FLATTREE -int __init of_setup_earlycon(unsigned long addr, - const struct earlycon_id *match, +int __init of_setup_earlycon(const struct earlycon_id *match, unsigned long node, const char *options) { @@ -227,12 +227,18 @@ int __init of_setup_earlycon(unsigned long addr, struct uart_port *port = &early_console_dev.port; const __be32 *val; bool big_endian; + u64 addr; spin_lock_init(&port->lock); port->iotype = UPIO_MEM; + addr = of_flat_dt_translate_address(node); + if (addr == OF_BAD_ADDR) { + pr_warn("[%s] bad address\n", match->name); + return -ENXIO; + } port->mapbase = addr; port->uartclk = BASE_BAUD * 16; - port->membase = earlycon_map(addr, SZ_4K); + port->membase = earlycon_map(port->mapbase, SZ_4K); val = of_get_flat_dt_prop(node, "reg-offset", NULL); if (val) diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index df9ef3801812..2fbe8682a66f 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -88,7 +88,7 @@ extern void unflatten_device_tree(void); extern void unflatten_and_copy_device_tree(void); extern void early_init_devtree(void *); extern void early_get_first_memblock_info(void *, phys_addr_t *); -extern u64 fdt_translate_address(const void *blob, int node_offset); +extern u64 of_flat_dt_translate_address(unsigned long node); extern void of_fdt_limit_memory(int limit); #else /* CONFIG_OF_FLATTREE */ static inline void early_init_fdt_scan_reserved_mem(void) {} diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 6d1bed821181..cbfcf38e220d 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -359,7 +359,7 @@ extern const struct earlycon_id __earlycon_table_end[]; #define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn) extern int setup_earlycon(char *buf); -extern int of_setup_earlycon(unsigned long addr, const struct earlycon_id *match, +extern int of_setup_earlycon(const struct earlycon_id *match, unsigned long node, const char *options); -- cgit v1.2.3 From 8e7737393c2fb410ce189c4659498722ef5745f0 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:45 -0800 Subject: serial: earlycon: Common log banner for command line and DT Refactor the command line earlycon banner into earlycon_init() so both earlycon startup methods output an info banner. Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/earlycon.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index baee9ad59af7..36b79f1828ab 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -59,6 +59,7 @@ static void __init earlycon_init(struct earlycon_device *device, const char *name) { struct console *earlycon = device->con; + struct uart_port *port = &device->port; const char *s; size_t len; @@ -72,6 +73,19 @@ static void __init earlycon_init(struct earlycon_device *device, len = s - name; strlcpy(earlycon->name, name, min(len + 1, sizeof(earlycon->name))); earlycon->data = &early_console_dev; + + if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM16 || + port->iotype == UPIO_MEM32 || port->iotype == UPIO_MEM32BE) + pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n", + (port->iotype == UPIO_MEM) ? "" : + (port->iotype == UPIO_MEM16) ? "16" : + (port->iotype == UPIO_MEM32) ? "32" : "32be", + (unsigned long long)port->mapbase, + device->options); + else + pr_info("Early serial console at I/O port 0x%lx (options '%s')\n", + port->iobase, + device->options); } static int __init parse_options(struct earlycon_device *device, char *options) @@ -110,19 +124,6 @@ static int __init parse_options(struct earlycon_device *device, char *options) strlcpy(device->options, options, length); } - if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM16 || - port->iotype == UPIO_MEM32 || port->iotype == UPIO_MEM32BE) - pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n", - (port->iotype == UPIO_MEM) ? "" : - (port->iotype == UPIO_MEM16) ? "16" : - (port->iotype == UPIO_MEM32) ? "32" : "32be", - (unsigned long long)port->mapbase, - device->options); - else - pr_info("Early serial console at I/O port 0x%lx (options '%s')\n", - port->iobase, - device->options); - return 0; } -- cgit v1.2.3 From b969398490d940a98cec0aefcafb9877dc122182 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:46 -0800 Subject: serial: earlycon: Show the earlycon "driver" in banner Output the earlycon "driver" from the just-parsed console 'name' and 'index' fields. NB: ->mapbase is a resource_size_t so use %pa format specifier Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/earlycon.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 36b79f1828ab..067783f0523c 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -76,16 +76,16 @@ static void __init earlycon_init(struct earlycon_device *device, if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM16 || port->iotype == UPIO_MEM32 || port->iotype == UPIO_MEM32BE) - pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n", + pr_info("%s%d at MMIO%s %pa (options '%s')\n", + earlycon->name, earlycon->index, (port->iotype == UPIO_MEM) ? "" : (port->iotype == UPIO_MEM16) ? "16" : (port->iotype == UPIO_MEM32) ? "32" : "32be", - (unsigned long long)port->mapbase, - device->options); + &port->mapbase, device->options); else - pr_info("Early serial console at I/O port 0x%lx (options '%s')\n", - port->iobase, - device->options); + pr_info("%s%d at I/O port 0x%lx (options '%s')\n", + earlycon->name, earlycon->index, + port->iobase, device->options); } static int __init parse_options(struct earlycon_device *device, char *options) -- cgit v1.2.3 From dc6b576b283e7bdff552af9c0ce66e121c6b4887 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:47 -0800 Subject: serial: 8250_early: Use port->regshift earlycon initializes struct uart_port::regshift to the correct value for UPIO_MEM32 already. Use the port field rather than hard-coded value. This enables broader support for various i/o access methods in 8250 earlycon (eg., omap8250 earlycon). Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_early.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index af62131af21e..180143ce77ce 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -39,15 +39,17 @@ static unsigned int __init serial8250_early_in(struct uart_port *port, int offset) { + offset <<= port->regshift; + switch (port->iotype) { case UPIO_MEM: return readb(port->membase + offset); case UPIO_MEM16: - return readw(port->membase + (offset << 1)); + return readw(port->membase + offset); case UPIO_MEM32: - return readl(port->membase + (offset << 2)); + return readl(port->membase + offset); case UPIO_MEM32BE: - return ioread32be(port->membase + (offset << 2)); + return ioread32be(port->membase + offset); case UPIO_PORT: return inb(port->iobase + offset); default: @@ -57,18 +59,20 @@ static unsigned int __init serial8250_early_in(struct uart_port *port, int offse static void __init serial8250_early_out(struct uart_port *port, int offset, int value) { + offset <<= port->regshift; + switch (port->iotype) { case UPIO_MEM: writeb(value, port->membase + offset); break; case UPIO_MEM16: - writew(value, port->membase + (offset << 1)); + writew(value, port->membase + offset); break; case UPIO_MEM32: - writel(value, port->membase + (offset << 2)); + writel(value, port->membase + offset); break; case UPIO_MEM32BE: - iowrite32be(value, port->membase + (offset << 2)); + iowrite32be(value, port->membase + offset); break; case UPIO_PORT: outb(value, port->iobase + offset); -- cgit v1.2.3 From 0fcc286f6a952d6ec40f74f26fd9cd5d63c25f9e Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:48 -0800 Subject: of: earlycon: Log more helpful message if stdout-path node not found Earlycon may fail to initialize for a variety of reasons, most of which log the default early param message. If the stdout-path node is not found, log the path which was not found (and suppress the default early param message). Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/of/fdt.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 918809e6f913..e2295b2c9836 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -820,11 +820,14 @@ static int __init early_init_dt_scan_chosen_serial(void) q = strchrnul(p, ':'); if (*q != '\0') options = q + 1; + l = q - p; /* Get the node specified by stdout-path */ - offset = fdt_path_offset_namelen(fdt, p, q - p); - if (offset < 0) - return -ENODEV; + offset = fdt_path_offset_namelen(fdt, p, l); + if (offset < 0) { + pr_warn("earlycon: stdout-path %.*s not found\n", l, p); + return 0; + } for (match = __earlycon_table; match < __earlycon_table_end; match++) { if (!match->compatible[0]) -- cgit v1.2.3 From 75d611bf01737d8456093804377e5cb0a60a9038 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:49 -0800 Subject: serial: 8250_omap: Add omap8250 earlycon Add DT earlycon for 8250_omap driver. This boot console is included for kernels built with CONFIG_SERIAL_EARLYCON=y, CONFIG_OF=y, CONFIG_SERIAL_8250_OMAP=y, and CONFIG_OF_EARLY_FLATTREE=y. This boot console is enabled with the command line option "earlycon" (without "=...") when the DT 'stdout-path' property matches a compatible uart. For example, / { chosen { stdout-path = "serial0:115200"; }; .... aliases { serial0 = &uart0; }; .... ocp : ocp { uart0 : serial@44e09000 { compatible = "ti,omap3-uart"; } }; }; Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_early.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index 180143ce77ce..3b3dbdc1b73e 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -149,3 +149,24 @@ EARLYCON_DECLARE(uart8250, early_serial8250_setup); EARLYCON_DECLARE(uart, early_serial8250_setup); OF_EARLYCON_DECLARE(ns16550, "ns16550", early_serial8250_setup); OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup); + +#ifdef CONFIG_SERIAL_8250_OMAP + +static int __init early_omap8250_setup(struct earlycon_device *device, + const char *options) +{ + struct uart_port *port = &device->port; + + if (!(device->port.membase || device->port.iobase)) + return -ENODEV; + + port->regshift = 2; + device->con->write = early_serial8250_write; + return 0; +} + +OF_EARLYCON_DECLARE(omap8250, "ti,omap2-uart", early_omap8250_setup); +OF_EARLYCON_DECLARE(omap8250, "ti,omap3-uart", early_omap8250_setup); +OF_EARLYCON_DECLARE(omap8250, "ti,omap4-uart", early_omap8250_setup); + +#endif -- cgit v1.2.3 From fdd9b8655933c3eb3154fe1ed351c17b654258bd Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Fri, 8 Jan 2016 00:49:21 +0200 Subject: mei: wd: drop the watchdog code from the core mei driver Instead of integrating the iAMT watchdog in the mei core driver we will create a watchdog device on the mei client bus and create a driver for it. This patch removes the watchdog code from the mei core driver. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/Kconfig | 6 +- drivers/misc/mei/Makefile | 1 - drivers/misc/mei/client.c | 12 +- drivers/misc/mei/client.h | 4 - drivers/misc/mei/init.c | 10 +- drivers/misc/mei/interrupt.c | 15 -- drivers/misc/mei/mei_dev.h | 61 +------ drivers/misc/mei/wd.c | 391 ------------------------------------------- 8 files changed, 9 insertions(+), 491 deletions(-) delete mode 100644 drivers/misc/mei/wd.c (limited to 'drivers') diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig index d23384dde73b..c49e1d2269af 100644 --- a/drivers/misc/mei/Kconfig +++ b/drivers/misc/mei/Kconfig @@ -1,6 +1,6 @@ config INTEL_MEI tristate "Intel Management Engine Interface" - depends on X86 && PCI && WATCHDOG_CORE + depends on X86 && PCI help The Intel Management Engine (Intel ME) provides Manageability, Security and Media services for system containing Intel chipsets. @@ -12,7 +12,7 @@ config INTEL_MEI config INTEL_MEI_ME tristate "ME Enabled Intel Chipsets" select INTEL_MEI - depends on X86 && PCI && WATCHDOG_CORE + depends on X86 && PCI help MEI support for ME Enabled Intel chipsets. @@ -37,7 +37,7 @@ config INTEL_MEI_ME config INTEL_MEI_TXE tristate "Intel Trusted Execution Environment with ME Interface" select INTEL_MEI - depends on X86 && PCI && WATCHDOG_CORE + depends on X86 && PCI help MEI Support for Trusted Execution Environment device on Intel SoCs diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile index 01447ca21c26..59e6b0aede34 100644 --- a/drivers/misc/mei/Makefile +++ b/drivers/misc/mei/Makefile @@ -9,7 +9,6 @@ mei-objs += interrupt.o mei-objs += client.o mei-objs += main.o mei-objs += amthif.o -mei-objs += wd.o mei-objs += bus.o mei-objs += bus-fixup.o mei-$(CONFIG_DEBUG_FS) += debugfs.o diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 72e32615acd9..e069fcaed7aa 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -648,7 +648,7 @@ int mei_cl_unlink(struct mei_cl *cl) if (!cl) return 0; - /* wd and amthif might not be initialized */ + /* amthif might not be initialized */ if (!cl->dev) return 0; @@ -679,17 +679,11 @@ void mei_host_client_init(struct work_struct *work) mutex_lock(&dev->device_lock); - me_cl = mei_me_cl_by_uuid(dev, &mei_amthif_guid); if (me_cl) mei_amthif_host_init(dev, me_cl); mei_me_cl_put(me_cl); - me_cl = mei_me_cl_by_uuid(dev, &mei_wd_guid); - if (me_cl) - mei_wd_host_init(dev, me_cl); - mei_me_cl_put(me_cl); - dev->dev_state = MEI_DEV_ENABLED; dev->reset_count = 0; mutex_unlock(&dev->device_lock); @@ -1153,7 +1147,7 @@ err: * * Return: 1 if mei_flow_ctrl_creds >0, 0 - otherwise. */ -int mei_cl_flow_ctrl_creds(struct mei_cl *cl) +static int mei_cl_flow_ctrl_creds(struct mei_cl *cl) { int rets; @@ -1186,7 +1180,7 @@ int mei_cl_flow_ctrl_creds(struct mei_cl *cl) * 0 on success * -EINVAL when ctrl credits are <= 0 */ -int mei_cl_flow_ctrl_reduce(struct mei_cl *cl) +static int mei_cl_flow_ctrl_reduce(struct mei_cl *cl) { if (WARN_ON(!cl || !cl->me_cl)) return -EINVAL; diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index 04e1aa39243f..2e90a25f896e 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -18,7 +18,6 @@ #define _MEI_CLIENT_H_ #include -#include #include #include @@ -120,9 +119,6 @@ struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length, enum mei_cb_file_ops type, struct file *fp); int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp); -int mei_cl_flow_ctrl_creds(struct mei_cl *cl); - -int mei_cl_flow_ctrl_reduce(struct mei_cl *cl); /* * MEI input output function prototype */ diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 3edafc8d3ad4..46a4302e5524 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -156,8 +156,7 @@ int mei_reset(struct mei_device *dev) mei_cl_all_wakeup(dev); /* remove entry if already in list */ - dev_dbg(dev->dev, "remove iamthif and wd from the file list.\n"); - mei_cl_unlink(&dev->wd_cl); + dev_dbg(dev->dev, "remove iamthif from the file list.\n"); mei_cl_unlink(&dev->iamthif_cl); mei_amthif_reset_params(dev); } @@ -165,7 +164,6 @@ int mei_reset(struct mei_device *dev) mei_hbm_reset(dev); dev->rd_msg_hdr = 0; - dev->wd_pending = false; if (ret) { dev_err(dev->dev, "hw_reset failed ret = %d\n", ret); @@ -335,16 +333,12 @@ void mei_stop(struct mei_device *dev) mutex_lock(&dev->device_lock); - mei_wd_stop(dev); - dev->dev_state = MEI_DEV_POWER_DOWN; mei_reset(dev); /* move device to disabled state unconditionally */ dev->dev_state = MEI_DEV_DISABLED; mutex_unlock(&dev->device_lock); - - mei_watchdog_unregister(dev); } EXPORT_SYMBOL_GPL(mei_stop); @@ -394,7 +388,6 @@ void mei_device_init(struct mei_device *dev, init_waitqueue_head(&dev->wait_hw_ready); init_waitqueue_head(&dev->wait_pg); init_waitqueue_head(&dev->wait_hbm_start); - init_waitqueue_head(&dev->wait_stop_wd); dev->dev_state = MEI_DEV_INITIALIZING; dev->reset_count = 0; @@ -407,7 +400,6 @@ void mei_device_init(struct mei_device *dev, INIT_WORK(&dev->init_work, mei_host_client_init); INIT_WORK(&dev->reset_work, mei_reset_work); - INIT_LIST_HEAD(&dev->wd_cl.link); INIT_LIST_HEAD(&dev->iamthif_cl.link); mei_io_list_init(&dev->amthif_cmd_list); mei_io_list_init(&dev->amthif_rd_complete_list); diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 64b568a0268d..6340dee33052 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -360,21 +360,6 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) list_move_tail(&cb->list, &cmpl_list->list); } - if (dev->wd_state == MEI_WD_STOPPING) { - dev->wd_state = MEI_WD_IDLE; - wake_up(&dev->wait_stop_wd); - } - - if (mei_cl_is_connected(&dev->wd_cl)) { - if (dev->wd_pending && - mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) { - ret = mei_wd_send(dev); - if (ret) - return ret; - dev->wd_pending = false; - } - } - /* complete control write list CB */ dev_dbg(dev->dev, "complete control write list cb.\n"); list_for_each_entry_safe(cb, next, &dev->ctrl_wr_list.list, list) { diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index b54d9d9cacea..da613268480c 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -18,7 +18,7 @@ #define _MEI_DEV_H_ #include -#include +#include #include #include #include @@ -26,33 +26,13 @@ #include "hw.h" #include "hbm.h" -/* - * watch dog definition - */ -#define MEI_WD_HDR_SIZE 4 -#define MEI_WD_STOP_MSG_SIZE MEI_WD_HDR_SIZE -#define MEI_WD_START_MSG_SIZE (MEI_WD_HDR_SIZE + 16) - -#define MEI_WD_DEFAULT_TIMEOUT 120 /* seconds */ -#define MEI_WD_MIN_TIMEOUT 120 /* seconds */ -#define MEI_WD_MAX_TIMEOUT 65535 /* seconds */ - -#define MEI_WD_STOP_TIMEOUT 10 /* msecs */ - -#define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0) - -#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32)) - /* * AMTHI Client UUID */ extern const uuid_le mei_amthif_guid; -/* - * Watchdog Client UUID - */ -extern const uuid_le mei_wd_guid; +#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32)) /* * Number of Maximum MEI Clients @@ -78,7 +58,6 @@ extern const uuid_le mei_wd_guid; */ #define MEI_HOST_CLIENT_ID_ANY (-1) #define MEI_HBM_HOST_CLIENT_ID 0 /* not used, just for documentation */ -#define MEI_WD_HOST_CLIENT_ID 1 #define MEI_IAMTHIF_HOST_CLIENT_ID 2 @@ -123,12 +102,6 @@ enum mei_file_transaction_states { MEI_READ_COMPLETE }; -enum mei_wd_states { - MEI_WD_IDLE, - MEI_WD_RUNNING, - MEI_WD_STOPPING, -}; - /** * enum mei_cb_file_ops - file operation associated with the callback * @MEI_FOP_READ: read @@ -404,7 +377,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); * @wait_hw_ready : wait queue for receive HW ready message form FW * @wait_pg : wait queue for receive PG message from FW * @wait_hbm_start : wait queue for receive HBM start message from FW - * @wait_stop_wd : wait queue for receive WD stop message from FW * * @reset_count : number of consecutive resets * @dev_state : device state @@ -435,12 +407,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); * * @allow_fixed_address: allow user space to connect a fixed client * - * @wd_cl : watchdog client - * @wd_state : watchdog client state - * @wd_pending : watchdog command is pending - * @wd_timeout : watchdog expiration timeout - * @wd_data : watchdog message buffer - * * @amthif_cmd_list : amthif list for cmd waiting * @amthif_rd_complete_list : amthif list for reading completed cmd data * @iamthif_file_object : file for current amthif operation @@ -486,7 +452,6 @@ struct mei_device { wait_queue_head_t wait_hw_ready; wait_queue_head_t wait_pg; wait_queue_head_t wait_hbm_start; - wait_queue_head_t wait_stop_wd; /* * mei device states @@ -531,13 +496,6 @@ struct mei_device { bool allow_fixed_address; - struct mei_cl wd_cl; - enum mei_wd_states wd_state; - bool wd_pending; - u16 wd_timeout; - unsigned char wd_data[MEI_WD_START_MSG_SIZE]; - - /* amthif list for cmd waiting */ struct mei_cl_cb amthif_cmd_list; /* driver managed amthif list for reading completed amthif cmd data */ @@ -649,21 +607,6 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, struct mei_cl_cb *complete_list); int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); -int mei_wd_send(struct mei_device *dev); -int mei_wd_stop(struct mei_device *dev); -int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl); -/* - * mei_watchdog_register - Registering watchdog interface - * once we got connection to the WD Client - * @dev: mei device - */ -int mei_watchdog_register(struct mei_device *dev); -/* - * mei_watchdog_unregister - Unregistering watchdog interface - * @dev: mei device - */ -void mei_watchdog_unregister(struct mei_device *dev); - /* * Register Access Function */ diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c deleted file mode 100644 index b346638833b0..000000000000 --- a/drivers/misc/mei/wd.c +++ /dev/null @@ -1,391 +0,0 @@ -/* - * - * Intel Management Engine Interface (Intel MEI) Linux driver - * Copyright (c) 2003-2012, 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, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - */ -#include -#include -#include -#include -#include -#include - -#include - -#include "mei_dev.h" -#include "hbm.h" -#include "client.h" - -static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; -static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; - -/* - * AMT Watchdog Device - */ -#define INTEL_AMT_WATCHDOG_ID "INTCAMT" - -/* UUIDs for AMT F/W clients */ -const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89, - 0x9D, 0xA9, 0x15, 0x14, 0xCB, - 0x32, 0xAB); - -static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout) -{ - dev_dbg(dev->dev, "wd: set timeout=%d.\n", timeout); - memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE); - memcpy(dev->wd_data + MEI_WD_HDR_SIZE, &timeout, sizeof(u16)); -} - -/** - * mei_wd_host_init - connect to the watchdog client - * - * @dev: the device structure - * @me_cl: me client - * - * Return: -ENOTTY if wd client cannot be found - * -EIO if write has failed - * 0 on success - */ -int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl) -{ - struct mei_cl *cl = &dev->wd_cl; - int ret; - - mei_cl_init(cl, dev); - - dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; - dev->wd_state = MEI_WD_IDLE; - - ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID); - if (ret < 0) { - dev_info(dev->dev, "wd: failed link client\n"); - return ret; - } - - ret = mei_cl_connect(cl, me_cl, NULL); - if (ret) { - dev_err(dev->dev, "wd: failed to connect = %d\n", ret); - mei_cl_unlink(cl); - return ret; - } - - ret = mei_watchdog_register(dev); - if (ret) { - mei_cl_disconnect(cl); - mei_cl_unlink(cl); - } - return ret; -} - -/** - * mei_wd_send - sends watch dog message to fw. - * - * @dev: the device structure - * - * Return: 0 if success, - * -EIO when message send fails - * -EINVAL when invalid message is to be sent - * -ENODEV on flow control failure - */ -int mei_wd_send(struct mei_device *dev) -{ - struct mei_cl *cl = &dev->wd_cl; - struct mei_msg_hdr hdr; - int ret; - - hdr.host_addr = cl->host_client_id; - hdr.me_addr = mei_cl_me_id(cl); - hdr.msg_complete = 1; - hdr.reserved = 0; - hdr.internal = 0; - - if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE)) - hdr.length = MEI_WD_START_MSG_SIZE; - else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE)) - hdr.length = MEI_WD_STOP_MSG_SIZE; - else { - dev_err(dev->dev, "wd: invalid message is to be sent, aborting\n"); - return -EINVAL; - } - - ret = mei_write_message(dev, &hdr, dev->wd_data); - if (ret) { - dev_err(dev->dev, "wd: write message failed\n"); - return ret; - } - - ret = mei_cl_flow_ctrl_reduce(cl); - if (ret) { - dev_err(dev->dev, "wd: flow_ctrl_reduce failed.\n"); - return ret; - } - - return 0; -} - -/** - * mei_wd_stop - sends watchdog stop message to fw. - * - * @dev: the device structure - * - * Return: 0 if success - * on error: - * -EIO when message send fails - * -EINVAL when invalid message is to be sent - * -ETIME on message timeout - */ -int mei_wd_stop(struct mei_device *dev) -{ - struct mei_cl *cl = &dev->wd_cl; - int ret; - - if (!mei_cl_is_connected(cl) || - dev->wd_state != MEI_WD_RUNNING) - return 0; - - memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_STOP_MSG_SIZE); - - dev->wd_state = MEI_WD_STOPPING; - - ret = mei_cl_flow_ctrl_creds(cl); - if (ret < 0) - goto err; - - if (ret && mei_hbuf_acquire(dev)) { - ret = mei_wd_send(dev); - if (ret) - goto err; - dev->wd_pending = false; - } else { - dev->wd_pending = true; - } - - mutex_unlock(&dev->device_lock); - - ret = wait_event_timeout(dev->wait_stop_wd, - dev->wd_state == MEI_WD_IDLE, - msecs_to_jiffies(MEI_WD_STOP_TIMEOUT)); - mutex_lock(&dev->device_lock); - if (dev->wd_state != MEI_WD_IDLE) { - /* timeout */ - ret = -ETIME; - dev_warn(dev->dev, "wd: stop failed to complete ret=%d\n", ret); - goto err; - } - dev_dbg(dev->dev, "wd: stop completed after %u msec\n", - MEI_WD_STOP_TIMEOUT - jiffies_to_msecs(ret)); - return 0; -err: - return ret; -} - -/** - * mei_wd_ops_start - wd start command from the watchdog core. - * - * @wd_dev: watchdog device struct - * - * Return: 0 if success, negative errno code for failure - */ -static int mei_wd_ops_start(struct watchdog_device *wd_dev) -{ - struct mei_device *dev; - struct mei_cl *cl; - int err = -ENODEV; - - dev = watchdog_get_drvdata(wd_dev); - if (!dev) - return -ENODEV; - - cl = &dev->wd_cl; - - mutex_lock(&dev->device_lock); - - if (dev->dev_state != MEI_DEV_ENABLED) { - dev_dbg(dev->dev, "wd: dev_state != MEI_DEV_ENABLED dev_state = %s\n", - mei_dev_state_str(dev->dev_state)); - goto end_unlock; - } - - if (!mei_cl_is_connected(cl)) { - cl_dbg(dev, cl, "MEI Driver is not connected to Watchdog Client\n"); - goto end_unlock; - } - - mei_wd_set_start_timeout(dev, dev->wd_timeout); - - err = 0; -end_unlock: - mutex_unlock(&dev->device_lock); - return err; -} - -/** - * mei_wd_ops_stop - wd stop command from the watchdog core. - * - * @wd_dev: watchdog device struct - * - * Return: 0 if success, negative errno code for failure - */ -static int mei_wd_ops_stop(struct watchdog_device *wd_dev) -{ - struct mei_device *dev; - - dev = watchdog_get_drvdata(wd_dev); - if (!dev) - return -ENODEV; - - mutex_lock(&dev->device_lock); - mei_wd_stop(dev); - mutex_unlock(&dev->device_lock); - - return 0; -} - -/** - * mei_wd_ops_ping - wd ping command from the watchdog core. - * - * @wd_dev: watchdog device struct - * - * Return: 0 if success, negative errno code for failure - */ -static int mei_wd_ops_ping(struct watchdog_device *wd_dev) -{ - struct mei_device *dev; - struct mei_cl *cl; - int ret; - - dev = watchdog_get_drvdata(wd_dev); - if (!dev) - return -ENODEV; - - cl = &dev->wd_cl; - - mutex_lock(&dev->device_lock); - - if (!mei_cl_is_connected(cl)) { - cl_err(dev, cl, "wd: not connected.\n"); - ret = -ENODEV; - goto end; - } - - dev->wd_state = MEI_WD_RUNNING; - - ret = mei_cl_flow_ctrl_creds(cl); - if (ret < 0) - goto end; - - /* Check if we can send the ping to HW*/ - if (ret && mei_hbuf_acquire(dev)) { - dev_dbg(dev->dev, "wd: sending ping\n"); - - ret = mei_wd_send(dev); - if (ret) - goto end; - dev->wd_pending = false; - } else { - dev->wd_pending = true; - } - -end: - mutex_unlock(&dev->device_lock); - return ret; -} - -/** - * mei_wd_ops_set_timeout - wd set timeout command from the watchdog core. - * - * @wd_dev: watchdog device struct - * @timeout: timeout value to set - * - * Return: 0 if success, negative errno code for failure - */ -static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, - unsigned int timeout) -{ - struct mei_device *dev; - - dev = watchdog_get_drvdata(wd_dev); - if (!dev) - return -ENODEV; - - /* Check Timeout value */ - if (timeout < MEI_WD_MIN_TIMEOUT || timeout > MEI_WD_MAX_TIMEOUT) - return -EINVAL; - - mutex_lock(&dev->device_lock); - - dev->wd_timeout = timeout; - wd_dev->timeout = timeout; - mei_wd_set_start_timeout(dev, dev->wd_timeout); - - mutex_unlock(&dev->device_lock); - - return 0; -} - -/* - * Watchdog Device structs - */ -static const struct watchdog_ops wd_ops = { - .owner = THIS_MODULE, - .start = mei_wd_ops_start, - .stop = mei_wd_ops_stop, - .ping = mei_wd_ops_ping, - .set_timeout = mei_wd_ops_set_timeout, -}; -static const struct watchdog_info wd_info = { - .identity = INTEL_AMT_WATCHDOG_ID, - .options = WDIOF_KEEPALIVEPING | - WDIOF_SETTIMEOUT | - WDIOF_ALARMONLY, -}; - -static struct watchdog_device amt_wd_dev = { - .info = &wd_info, - .ops = &wd_ops, - .timeout = MEI_WD_DEFAULT_TIMEOUT, - .min_timeout = MEI_WD_MIN_TIMEOUT, - .max_timeout = MEI_WD_MAX_TIMEOUT, -}; - - -int mei_watchdog_register(struct mei_device *dev) -{ - - int ret; - - amt_wd_dev.parent = dev->dev; - /* unlock to perserve correct locking order */ - mutex_unlock(&dev->device_lock); - ret = watchdog_register_device(&amt_wd_dev); - mutex_lock(&dev->device_lock); - if (ret) { - dev_err(dev->dev, "wd: unable to register watchdog device = %d.\n", - ret); - return ret; - } - - dev_dbg(dev->dev, "wd: successfully register watchdog interface.\n"); - watchdog_set_drvdata(&amt_wd_dev, dev); - return 0; -} - -void mei_watchdog_unregister(struct mei_device *dev) -{ - if (watchdog_get_drvdata(&amt_wd_dev) == NULL) - return; - - watchdog_set_drvdata(&amt_wd_dev, NULL); - watchdog_unregister_device(&amt_wd_dev); -} - -- cgit v1.2.3 From 222818c3d84c1f3190767f5f09f2b9b9a0e0ca7f Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 8 Jan 2016 00:49:22 +0200 Subject: watchdog: mei_wdt: implement MEI iAMT watchdog driver Create a driver with the generic watchdog interface for the MEI iAMT watchdog device. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- Documentation/misc-devices/mei/mei.txt | 12 +- MAINTAINERS | 1 + drivers/watchdog/Kconfig | 15 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/mei_wdt.c | 404 +++++++++++++++++++++++++++++++++ 5 files changed, 427 insertions(+), 6 deletions(-) create mode 100644 drivers/watchdog/mei_wdt.c (limited to 'drivers') diff --git a/Documentation/misc-devices/mei/mei.txt b/Documentation/misc-devices/mei/mei.txt index 91c1fa34f48b..2b80a0cd621f 100644 --- a/Documentation/misc-devices/mei/mei.txt +++ b/Documentation/misc-devices/mei/mei.txt @@ -231,15 +231,15 @@ IT knows when a platform crashes even when there is a hard failure on the host. The Intel AMT Watchdog is composed of two parts: 1) Firmware feature - receives the heartbeats and sends an event when the heartbeats stop. - 2) Intel MEI driver - connects to the watchdog feature, configures the - watchdog and sends the heartbeats. + 2) Intel MEI iAMT watchdog driver - connects to the watchdog feature, + configures the watchdog and sends the heartbeats. -The Intel MEI driver uses the kernel watchdog API to configure the Intel AMT -Watchdog and to send heartbeats to it. The default timeout of the +The Intel iAMT watchdog MEI driver uses the kernel watchdog API to configure +the Intel AMT Watchdog and to send heartbeats to it. The default timeout of the watchdog is 120 seconds. -If the Intel AMT Watchdog feature does not exist (i.e. the connection failed), -the Intel MEI driver will disable the sending of heartbeats. +If the Intel AMT is not enabled in the firmware then the watchdog client won't enumerate +on the me client bus and watchdog devices won't be exposed. Supported Chipsets diff --git a/MAINTAINERS b/MAINTAINERS index 30aca4aa5467..d63b3c773c7d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5751,6 +5751,7 @@ S: Supported F: include/uapi/linux/mei.h F: include/linux/mei_cl_bus.h F: drivers/misc/mei/* +F: drivers/watchdog/mei_wdt.c F: Documentation/misc-devices/mei/* INTEL MIC DRIVERS (mic) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 4f0e7be0da34..57f872122b16 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1212,6 +1212,21 @@ config SBC_EPX_C3_WATCHDOG To compile this driver as a module, choose M here: the module will be called sbc_epx_c3. +config INTEL_MEI_WDT + tristate "Intel MEI iAMT Watchdog" + depends on INTEL_MEI && X86 + select WATCHDOG_CORE + ---help--- + A device driver for the Intel MEI iAMT watchdog. + + The Intel AMT Watchdog is an OS Health (Hang/Crash) watchdog. + Whenever the OS hangs or crashes, iAMT will send an event + to any subscriber to this event. The watchdog doesn't reset the + the platform. + + To compile this driver as a module, choose M here: + the module will be called mei_wdt. + # M32R Architecture # M68K Architecture diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index f566753256ab..efc4f788e0f2 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -126,6 +126,7 @@ obj-$(CONFIG_MACHZ_WDT) += machzwd.o obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o obj-$(CONFIG_INTEL_MID_WATCHDOG) += intel-mid_wdt.o +obj-$(CONFIG_INTEL_MEI_WDT) += mei_wdt.o # M32R Architecture diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c new file mode 100644 index 000000000000..32e3e1d55ef3 --- /dev/null +++ b/drivers/watchdog/mei_wdt.c @@ -0,0 +1,404 @@ +/* + * Intel Management Engine Interface (Intel MEI) Linux driver + * Copyright (c) 2015, 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, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#include +#include +#include +#include + +#include +#include + +/* + * iAMT Watchdog Device + */ +#define INTEL_AMT_WATCHDOG_ID "iamt_wdt" + +#define MEI_WDT_DEFAULT_TIMEOUT 120 /* seconds */ +#define MEI_WDT_MIN_TIMEOUT 120 /* seconds */ +#define MEI_WDT_MAX_TIMEOUT 65535 /* seconds */ + +/* Commands */ +#define MEI_MANAGEMENT_CONTROL 0x02 + +/* MEI Management Control version number */ +#define MEI_MC_VERSION_NUMBER 0x10 + +/* Sub Commands */ +#define MEI_MC_START_WD_TIMER_REQ 0x13 +#define MEI_MC_STOP_WD_TIMER_REQ 0x14 + +/** + * enum mei_wdt_state - internal watchdog state + * + * @MEI_WDT_IDLE: wd is idle and not opened + * @MEI_WDT_START: wd was opened, start was called + * @MEI_WDT_RUNNING: wd is expecting keep alive pings + * @MEI_WDT_STOPPING: wd is stopping and will move to IDLE + */ +enum mei_wdt_state { + MEI_WDT_IDLE, + MEI_WDT_START, + MEI_WDT_RUNNING, + MEI_WDT_STOPPING, +}; + +/** + * struct mei_wdt - mei watchdog driver + * @wdd: watchdog device + * + * @cldev: mei watchdog client device + * @state: watchdog internal state + * @timeout: watchdog current timeout + */ +struct mei_wdt { + struct watchdog_device wdd; + + struct mei_cl_device *cldev; + enum mei_wdt_state state; + u16 timeout; +}; + +/* + * struct mei_mc_hdr - Management Control Command Header + * + * @command: Management Control (0x2) + * @bytecount: Number of bytes in the message beyond this byte + * @subcommand: Management Control Subcommand + * @versionnumber: Management Control Version (0x10) + */ +struct mei_mc_hdr { + u8 command; + u8 bytecount; + u8 subcommand; + u8 versionnumber; +}; + +/** + * struct mei_wdt_start_request watchdog start/ping + * + * @hdr: Management Control Command Header + * @timeout: timeout value + * @reserved: reserved (legacy) + */ +struct mei_wdt_start_request { + struct mei_mc_hdr hdr; + u16 timeout; + u8 reserved[17]; +} __packed; + +/** + * struct mei_wdt_stop_request - watchdog stop + * + * @hdr: Management Control Command Header + */ +struct mei_wdt_stop_request { + struct mei_mc_hdr hdr; +} __packed; + +/** + * mei_wdt_ping - send wd start/ping command + * + * @wdt: mei watchdog device + * + * Return: 0 on success, + * negative errno code on failure + */ +static int mei_wdt_ping(struct mei_wdt *wdt) +{ + struct mei_wdt_start_request req; + const size_t req_len = sizeof(req); + int ret; + + memset(&req, 0, req_len); + req.hdr.command = MEI_MANAGEMENT_CONTROL; + req.hdr.bytecount = req_len - offsetof(struct mei_mc_hdr, subcommand); + req.hdr.subcommand = MEI_MC_START_WD_TIMER_REQ; + req.hdr.versionnumber = MEI_MC_VERSION_NUMBER; + req.timeout = wdt->timeout; + + ret = mei_cldev_send(wdt->cldev, (u8 *)&req, req_len); + if (ret < 0) + return ret; + + return 0; +} + +/** + * mei_wdt_stop - send wd stop command + * + * @wdt: mei watchdog device + * + * Return: 0 on success, + * negative errno code on failure + */ +static int mei_wdt_stop(struct mei_wdt *wdt) +{ + struct mei_wdt_stop_request req; + const size_t req_len = sizeof(req); + int ret; + + memset(&req, 0, req_len); + req.hdr.command = MEI_MANAGEMENT_CONTROL; + req.hdr.bytecount = req_len - offsetof(struct mei_mc_hdr, subcommand); + req.hdr.subcommand = MEI_MC_STOP_WD_TIMER_REQ; + req.hdr.versionnumber = MEI_MC_VERSION_NUMBER; + + ret = mei_cldev_send(wdt->cldev, (u8 *)&req, req_len); + if (ret < 0) + return ret; + + return 0; +} + +/** + * mei_wdt_ops_start - wd start command from the watchdog core. + * + * @wdd: watchdog device + * + * Return: 0 on success or -ENODEV; + */ +static int mei_wdt_ops_start(struct watchdog_device *wdd) +{ + struct mei_wdt *wdt = watchdog_get_drvdata(wdd); + + wdt->state = MEI_WDT_START; + wdd->timeout = wdt->timeout; + return 0; +} + +/** + * mei_wdt_ops_stop - wd stop command from the watchdog core. + * + * @wdd: watchdog device + * + * Return: 0 if success, negative errno code for failure + */ +static int mei_wdt_ops_stop(struct watchdog_device *wdd) +{ + struct mei_wdt *wdt = watchdog_get_drvdata(wdd); + int ret; + + if (wdt->state != MEI_WDT_RUNNING) + return 0; + + wdt->state = MEI_WDT_STOPPING; + + ret = mei_wdt_stop(wdt); + if (ret) + return ret; + + wdt->state = MEI_WDT_IDLE; + + return 0; +} + +/** + * mei_wdt_ops_ping - wd ping command from the watchdog core. + * + * @wdd: watchdog device + * + * Return: 0 if success, negative errno code on failure + */ +static int mei_wdt_ops_ping(struct watchdog_device *wdd) +{ + struct mei_wdt *wdt = watchdog_get_drvdata(wdd); + int ret; + + if (wdt->state != MEI_WDT_START && wdt->state != MEI_WDT_RUNNING) + return 0; + + ret = mei_wdt_ping(wdt); + if (ret) + return ret; + + wdt->state = MEI_WDT_RUNNING; + + return 0; +} + +/** + * mei_wdt_ops_set_timeout - wd set timeout command from the watchdog core. + * + * @wdd: watchdog device + * @timeout: timeout value to set + * + * Return: 0 if success, negative errno code for failure + */ +static int mei_wdt_ops_set_timeout(struct watchdog_device *wdd, + unsigned int timeout) +{ + + struct mei_wdt *wdt = watchdog_get_drvdata(wdd); + + /* valid value is already checked by the caller */ + wdt->timeout = timeout; + wdd->timeout = timeout; + + return 0; +} + +static const struct watchdog_ops wd_ops = { + .owner = THIS_MODULE, + .start = mei_wdt_ops_start, + .stop = mei_wdt_ops_stop, + .ping = mei_wdt_ops_ping, + .set_timeout = mei_wdt_ops_set_timeout, +}; + +/* not const as the firmware_version field need to be retrieved */ +static struct watchdog_info wd_info = { + .identity = INTEL_AMT_WATCHDOG_ID, + .options = WDIOF_KEEPALIVEPING | + WDIOF_SETTIMEOUT | + WDIOF_ALARMONLY, +}; + +/** + * mei_wdt_unregister - unregister from the watchdog subsystem + * + * @wdt: mei watchdog device + */ +static void mei_wdt_unregister(struct mei_wdt *wdt) +{ + watchdog_unregister_device(&wdt->wdd); + watchdog_set_drvdata(&wdt->wdd, NULL); +} + +/** + * mei_wdt_register - register with the watchdog subsystem + * + * @wdt: mei watchdog device + * + * Return: 0 if success, negative errno code for failure + */ +static int mei_wdt_register(struct mei_wdt *wdt) +{ + struct device *dev; + int ret; + + if (!wdt || !wdt->cldev) + return -EINVAL; + + dev = &wdt->cldev->dev; + + wdt->wdd.info = &wd_info; + wdt->wdd.ops = &wd_ops; + wdt->wdd.parent = dev; + wdt->wdd.timeout = MEI_WDT_DEFAULT_TIMEOUT; + wdt->wdd.min_timeout = MEI_WDT_MIN_TIMEOUT; + wdt->wdd.max_timeout = MEI_WDT_MAX_TIMEOUT; + + watchdog_set_drvdata(&wdt->wdd, wdt); + ret = watchdog_register_device(&wdt->wdd); + if (ret) { + dev_err(dev, "unable to register watchdog device = %d.\n", ret); + watchdog_set_drvdata(&wdt->wdd, NULL); + } + + return ret; +} + +static int mei_wdt_probe(struct mei_cl_device *cldev, + const struct mei_cl_device_id *id) +{ + struct mei_wdt *wdt; + int ret; + + wdt = kzalloc(sizeof(struct mei_wdt), GFP_KERNEL); + if (!wdt) + return -ENOMEM; + + wdt->timeout = MEI_WDT_DEFAULT_TIMEOUT; + wdt->state = MEI_WDT_IDLE; + wdt->cldev = cldev; + mei_cldev_set_drvdata(cldev, wdt); + + ret = mei_cldev_enable(cldev); + if (ret < 0) { + dev_err(&cldev->dev, "Could not enable cl device\n"); + goto err_out; + } + + wd_info.firmware_version = mei_cldev_ver(cldev); + + ret = mei_wdt_register(wdt); + if (ret) + goto err_disable; + + return 0; + +err_disable: + mei_cldev_disable(cldev); + +err_out: + kfree(wdt); + + return ret; +} + +static int mei_wdt_remove(struct mei_cl_device *cldev) +{ + struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); + + mei_wdt_unregister(wdt); + + mei_cldev_disable(cldev); + + kfree(wdt); + + return 0; +} + +#define MEI_UUID_WD UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, \ + 0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB) + +static struct mei_cl_device_id mei_wdt_tbl[] = { + { .uuid = MEI_UUID_WD, .version = 0x1}, + /* required last entry */ + { } +}; +MODULE_DEVICE_TABLE(mei, mei_wdt_tbl); + +static struct mei_cl_driver mei_wdt_driver = { + .id_table = mei_wdt_tbl, + .name = KBUILD_MODNAME, + + .probe = mei_wdt_probe, + .remove = mei_wdt_remove, +}; + +static int __init mei_wdt_init(void) +{ + int ret; + + ret = mei_cldev_driver_register(&mei_wdt_driver); + if (ret) { + pr_err(KBUILD_MODNAME ": module registration failed\n"); + return ret; + } + return 0; +} + +static void __exit mei_wdt_exit(void) +{ + mei_cldev_driver_unregister(&mei_wdt_driver); +} + +module_init(mei_wdt_init); +module_exit(mei_wdt_exit); + +MODULE_AUTHOR("Intel Corporation"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Device driver for Intel MEI iAMT watchdog"); -- cgit v1.2.3 From c9cf20ee45602a7a5512b7fbbef5672382790555 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 8 Jan 2016 00:49:23 +0200 Subject: watchdog: mei_wdt: add status debugfs entry Add entry for displaying current watchdog internal state cat /mei_wdt/state IDLE|START|RUNNING|STOPPING Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/watchdog/mei_wdt.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'drivers') diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c index 32e3e1d55ef3..e7e3f144f2b0 100644 --- a/drivers/watchdog/mei_wdt.c +++ b/drivers/watchdog/mei_wdt.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,24 @@ enum mei_wdt_state { MEI_WDT_STOPPING, }; +#if IS_ENABLED(CONFIG_DEBUG_FS) +static const char *mei_wdt_state_str(enum mei_wdt_state state) +{ + switch (state) { + case MEI_WDT_IDLE: + return "IDLE"; + case MEI_WDT_START: + return "START"; + case MEI_WDT_RUNNING: + return "RUNNING"; + case MEI_WDT_STOPPING: + return "STOPPING"; + default: + return "unknown"; + } +} +#endif /* CONFIG_DEBUG_FS */ + /** * struct mei_wdt - mei watchdog driver * @wdd: watchdog device @@ -61,6 +80,8 @@ enum mei_wdt_state { * @cldev: mei watchdog client device * @state: watchdog internal state * @timeout: watchdog current timeout + * + * @dbgfs_dir: debugfs dir entry */ struct mei_wdt { struct watchdog_device wdd; @@ -68,6 +89,10 @@ struct mei_wdt { struct mei_cl_device *cldev; enum mei_wdt_state state; u16 timeout; + +#if IS_ENABLED(CONFIG_DEBUG_FS) + struct dentry *dbgfs_dir; +#endif /* CONFIG_DEBUG_FS */ }; /* @@ -310,6 +335,63 @@ static int mei_wdt_register(struct mei_wdt *wdt) return ret; } +#if IS_ENABLED(CONFIG_DEBUG_FS) + +static ssize_t mei_dbgfs_read_state(struct file *file, char __user *ubuf, + size_t cnt, loff_t *ppos) +{ + struct mei_wdt *wdt = file->private_data; + const size_t bufsz = 32; + char buf[bufsz]; + ssize_t pos; + + pos = scnprintf(buf, bufsz, "state: %s\n", + mei_wdt_state_str(wdt->state)); + + return simple_read_from_buffer(ubuf, cnt, ppos, buf, pos); +} + +static const struct file_operations dbgfs_fops_state = { + .open = simple_open, + .read = mei_dbgfs_read_state, + .llseek = generic_file_llseek, +}; + +static void dbgfs_unregister(struct mei_wdt *wdt) +{ + debugfs_remove_recursive(wdt->dbgfs_dir); + wdt->dbgfs_dir = NULL; +} + +static int dbgfs_register(struct mei_wdt *wdt) +{ + struct dentry *dir, *f; + + dir = debugfs_create_dir(KBUILD_MODNAME, NULL); + if (!dir) + return -ENOMEM; + + wdt->dbgfs_dir = dir; + f = debugfs_create_file("state", S_IRUSR, dir, wdt, &dbgfs_fops_state); + if (!f) + goto err; + + return 0; +err: + dbgfs_unregister(wdt); + return -ENODEV; +} + +#else + +static inline void dbgfs_unregister(struct mei_wdt *wdt) {} + +static inline int dbgfs_register(struct mei_wdt *wdt) +{ + return 0; +} +#endif /* CONFIG_DEBUG_FS */ + static int mei_wdt_probe(struct mei_cl_device *cldev, const struct mei_cl_device_id *id) { @@ -337,6 +419,9 @@ static int mei_wdt_probe(struct mei_cl_device *cldev, if (ret) goto err_disable; + if (dbgfs_register(wdt)) + dev_warn(&cldev->dev, "cannot register debugfs\n"); + return 0; err_disable: @@ -356,6 +441,8 @@ static int mei_wdt_remove(struct mei_cl_device *cldev) mei_cldev_disable(cldev); + dbgfs_unregister(wdt); + kfree(wdt); return 0; -- cgit v1.2.3 From e97cdb303c04bfe60283094bdced68a0d363bd5d Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 8 Jan 2016 00:49:24 +0200 Subject: mei: bus: whitelist the watchdog client The iAMT WD client has to be whitelisted sice it has two connections and is filtered out by number_of_connections fixup. Also the API has changed for BDW and SKL but firmware haven't updated the protocol version. Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus-fixup.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c index b2d2a6ea576c..b87323f4bb14 100644 --- a/drivers/misc/mei/bus-fixup.c +++ b/drivers/misc/mei/bus-fixup.c @@ -35,6 +35,9 @@ static const uuid_le mei_nfc_info_guid = MEI_UUID_NFC_INFO; #define MEI_UUID_NFC_HCI UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50, \ 0x94, 0xd4, 0x50, 0x26, 0x67, 0x23, 0x77, 0x5c) +#define MEI_UUID_WD UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, \ + 0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB) + #define MEI_UUID_ANY NULL_UUID_LE /** @@ -66,6 +69,31 @@ static void blacklist(struct mei_cl_device *cldev) cldev->do_match = 0; } +/** + * mei_wd - wd client on the bus, change protocol version + * as the API has changed. + * + * @cldev: me clients device + */ +#if IS_ENABLED(CONFIG_INTEL_MEI_ME) +#include +#include "hw-me-regs.h" +static void mei_wd(struct mei_cl_device *cldev) +{ + struct pci_dev *pdev = to_pci_dev(cldev->dev.parent); + + dev_dbg(&cldev->dev, "running hook %s\n", __func__); + if (pdev->device == MEI_DEV_ID_WPT_LP || + pdev->device == MEI_DEV_ID_SPT || + pdev->device == MEI_DEV_ID_SPT_H) + cldev->me_cl->props.protocol_version = 0x2; + + cldev->do_match = 1; +} +#else +static inline void mei_wd(struct mei_cl_device *cldev) {} +#endif /* CONFIG_INTEL_MEI_ME */ + struct mei_nfc_cmd { u8 command; u8 status; @@ -280,6 +308,7 @@ static struct mei_fixup { MEI_FIXUP(MEI_UUID_ANY, number_of_connections), MEI_FIXUP(MEI_UUID_NFC_INFO, blacklist), MEI_FIXUP(MEI_UUID_NFC_HCI, mei_nfc), + MEI_FIXUP(MEI_UUID_WD, mei_wd), }; /** -- cgit v1.2.3 From 7326fffb712f09a315bc73cc1ee63843f59b8bd4 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 17 Jan 2016 12:25:01 +0200 Subject: mei: validate request value in client notify request ioctl This patch address a possible security issue: The request field in client notify request ioctl comes from user space as u32 and is downcasted to u8 with out validation. Check request field to have approved values MEI_HBM_NOTIFICATION_STAR/STOP Cc: #4.3+ Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 677d0362f334..80f9afcb1382 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -458,7 +458,11 @@ static int mei_ioctl_client_notify_request(struct file *file, u32 request) { struct mei_cl *cl = file->private_data; - return mei_cl_notify_request(cl, file, request); + if (request != MEI_HBM_NOTIFICATION_START && + request != MEI_HBM_NOTIFICATION_STOP) + return -EINVAL; + + return mei_cl_notify_request(cl, file, (u8)request); } /** -- cgit v1.2.3 From 1fba6a594cfd1ea0f1fc8a97e22f43def1505d74 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:49:32 +0100 Subject: TTY: serial/mpsc, stop leaking mappings When mpsc_routing_base, sdma_intr_base, mpsc_base, sdma_base, and brg_base are mapped, they are never unmapped. The condition in the free paths is always 'if (!XXX_base) { unmap }'. Fix it by inverting the condition. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mpsc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c index cadfd1cfae2b..363772992acc 100644 --- a/drivers/tty/serial/mpsc.c +++ b/drivers/tty/serial/mpsc.c @@ -1870,12 +1870,12 @@ static int mpsc_shared_map_regs(struct platform_device *pd) static void mpsc_shared_unmap_regs(void) { - if (!mpsc_shared_regs.mpsc_routing_base) { + if (mpsc_shared_regs.mpsc_routing_base) { iounmap(mpsc_shared_regs.mpsc_routing_base); release_mem_region(mpsc_shared_regs.mpsc_routing_base_p, MPSC_ROUTING_REG_BLOCK_SIZE); } - if (!mpsc_shared_regs.sdma_intr_base) { + if (mpsc_shared_regs.sdma_intr_base) { iounmap(mpsc_shared_regs.sdma_intr_base); release_mem_region(mpsc_shared_regs.sdma_intr_base_p, MPSC_SDMA_INTR_REG_BLOCK_SIZE); @@ -2011,15 +2011,15 @@ err: static void mpsc_drv_unmap_regs(struct mpsc_port_info *pi) { - if (!pi->mpsc_base) { + if (pi->mpsc_base) { iounmap(pi->mpsc_base); release_mem_region(pi->mpsc_base_p, MPSC_REG_BLOCK_SIZE); } - if (!pi->sdma_base) { + if (pi->sdma_base) { iounmap(pi->sdma_base); release_mem_region(pi->sdma_base_p, MPSC_SDMA_REG_BLOCK_SIZE); } - if (!pi->brg_base) { + if (pi->brg_base) { iounmap(pi->brg_base); release_mem_region(pi->brg_base_p, MPSC_BRG_REG_BLOCK_SIZE); } -- cgit v1.2.3 From bca1481ec4a0014271b7c220f41d7a790654dfbb Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:49:33 +0100 Subject: TTY: serial/mpsc, clean up init/remove functions There is a chain of up to 4 nested ifs in init and remove functions. Instead, make the code linear and use goto's to handle failures. Remove unneeded cast from mpsc_release_port by referencing pi->port directly. And finally, use dev_dbg instead of pr_debug given we have dev->dev node. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mpsc.c | 163 ++++++++++++++++++++++------------------------ 1 file changed, 79 insertions(+), 84 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c index 363772992acc..44a23113f469 100644 --- a/drivers/tty/serial/mpsc.c +++ b/drivers/tty/serial/mpsc.c @@ -1891,44 +1891,39 @@ static void mpsc_shared_unmap_regs(void) static int mpsc_shared_drv_probe(struct platform_device *dev) { struct mpsc_shared_pdata *pdata; - int rc = -ENODEV; - - if (dev->id == 0) { - rc = mpsc_shared_map_regs(dev); - if (!rc) { - pdata = (struct mpsc_shared_pdata *) - dev_get_platdata(&dev->dev); - - mpsc_shared_regs.MPSC_MRR_m = pdata->mrr_val; - mpsc_shared_regs.MPSC_RCRR_m= pdata->rcrr_val; - mpsc_shared_regs.MPSC_TCRR_m= pdata->tcrr_val; - mpsc_shared_regs.SDMA_INTR_CAUSE_m = - pdata->intr_cause_val; - mpsc_shared_regs.SDMA_INTR_MASK_m = - pdata->intr_mask_val; - - rc = 0; - } - } + int rc; - return rc; + if (dev->id != 0) + return -ENODEV; + + rc = mpsc_shared_map_regs(dev); + if (rc) + return rc; + + pdata = dev_get_platdata(&dev->dev); + + mpsc_shared_regs.MPSC_MRR_m = pdata->mrr_val; + mpsc_shared_regs.MPSC_RCRR_m= pdata->rcrr_val; + mpsc_shared_regs.MPSC_TCRR_m= pdata->tcrr_val; + mpsc_shared_regs.SDMA_INTR_CAUSE_m = pdata->intr_cause_val; + mpsc_shared_regs.SDMA_INTR_MASK_m = pdata->intr_mask_val; + + return 0; } static int mpsc_shared_drv_remove(struct platform_device *dev) { - int rc = -ENODEV; + if (dev->id != 0) + return -ENODEV; - if (dev->id == 0) { - mpsc_shared_unmap_regs(); - mpsc_shared_regs.MPSC_MRR_m = 0; - mpsc_shared_regs.MPSC_RCRR_m = 0; - mpsc_shared_regs.MPSC_TCRR_m = 0; - mpsc_shared_regs.SDMA_INTR_CAUSE_m = 0; - mpsc_shared_regs.SDMA_INTR_MASK_m = 0; - rc = 0; - } + mpsc_shared_unmap_regs(); + mpsc_shared_regs.MPSC_MRR_m = 0; + mpsc_shared_regs.MPSC_RCRR_m = 0; + mpsc_shared_regs.MPSC_TCRR_m = 0; + mpsc_shared_regs.SDMA_INTR_CAUSE_m = 0; + mpsc_shared_regs.SDMA_INTR_MASK_m = 0; - return rc; + return 0; } static struct platform_driver mpsc_shared_driver = { @@ -1979,10 +1974,6 @@ static int mpsc_drv_map_regs(struct mpsc_port_info *pi, pi->sdma_base_p = r->start; } else { mpsc_resource_err("SDMA base"); - if (pi->mpsc_base) { - iounmap(pi->mpsc_base); - pi->mpsc_base = NULL; - } goto err; } @@ -1993,19 +1984,19 @@ static int mpsc_drv_map_regs(struct mpsc_port_info *pi, pi->brg_base_p = r->start; } else { mpsc_resource_err("BRG base"); - if (pi->mpsc_base) { - iounmap(pi->mpsc_base); - pi->mpsc_base = NULL; - } - if (pi->sdma_base) { - iounmap(pi->sdma_base); - pi->sdma_base = NULL; - } goto err; } return 0; err: + if (pi->sdma_base) { + iounmap(pi->sdma_base); + pi->sdma_base = NULL; + } + if (pi->mpsc_base) { + iounmap(pi->mpsc_base); + pi->mpsc_base = NULL; + } return -ENOMEM; } @@ -2073,36 +2064,37 @@ static void mpsc_drv_get_platform_data(struct mpsc_port_info *pi, static int mpsc_drv_probe(struct platform_device *dev) { - struct mpsc_port_info *pi; - int rc = -ENODEV; - - pr_debug("mpsc_drv_probe: Adding MPSC %d\n", dev->id); - - if (dev->id < MPSC_NUM_CTLRS) { - pi = &mpsc_ports[dev->id]; - - rc = mpsc_drv_map_regs(pi, dev); - if (!rc) { - mpsc_drv_get_platform_data(pi, dev, dev->id); - pi->port.dev = &dev->dev; - - rc = mpsc_make_ready(pi); - if (!rc) { - spin_lock_init(&pi->tx_lock); - rc = uart_add_one_port(&mpsc_reg, &pi->port); - if (!rc) { - rc = 0; - } else { - mpsc_release_port((struct uart_port *) - pi); - mpsc_drv_unmap_regs(pi); - } - } else { - mpsc_drv_unmap_regs(pi); - } - } - } + struct mpsc_port_info *pi; + int rc; + + dev_dbg(&dev->dev, "mpsc_drv_probe: Adding MPSC %d\n", dev->id); + + if (dev->id >= MPSC_NUM_CTLRS) + return -ENODEV; + + pi = &mpsc_ports[dev->id]; + + rc = mpsc_drv_map_regs(pi, dev); + if (rc) + return rc; + mpsc_drv_get_platform_data(pi, dev, dev->id); + pi->port.dev = &dev->dev; + + rc = mpsc_make_ready(pi); + if (rc) + goto err_unmap; + + spin_lock_init(&pi->tx_lock); + rc = uart_add_one_port(&mpsc_reg, &pi->port); + if (rc) + goto err_relport; + + return 0; +err_relport: + mpsc_release_port(&pi->port); +err_unmap: + mpsc_drv_unmap_regs(pi); return rc; } @@ -2124,19 +2116,22 @@ static int __init mpsc_drv_init(void) memset(&mpsc_shared_regs, 0, sizeof(mpsc_shared_regs)); rc = uart_register_driver(&mpsc_reg); - if (!rc) { - rc = platform_driver_register(&mpsc_shared_driver); - if (!rc) { - rc = platform_driver_register(&mpsc_driver); - if (rc) { - platform_driver_unregister(&mpsc_shared_driver); - uart_unregister_driver(&mpsc_reg); - } - } else { - uart_unregister_driver(&mpsc_reg); - } - } + if (rc) + return rc; + + rc = platform_driver_register(&mpsc_shared_driver); + if (rc) + goto err_unreg_uart; + rc = platform_driver_register(&mpsc_driver); + if (rc) + goto err_unreg_plat; + + return 0; +err_unreg_plat: + platform_driver_unregister(&mpsc_shared_driver); +err_unreg_uart: + uart_unregister_driver(&mpsc_reg); return rc; } device_initcall(mpsc_drv_init); -- cgit v1.2.3 From 6f3689fb5940d0679bcc50bcb47dbb0deae9d5e7 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:49:34 +0100 Subject: TTY: serial/mpsc, remove unused fields c_iflag and c_cflag are set, but unused. Remove. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mpsc.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c index 44a23113f469..4a3021bcc859 100644 --- a/drivers/tty/serial/mpsc.c +++ b/drivers/tty/serial/mpsc.c @@ -137,8 +137,6 @@ struct mpsc_port_info { /* Internal driver state for this ctlr */ u8 ready; u8 rcv_data; - tcflag_t c_iflag; /* save termios->c_iflag */ - tcflag_t c_cflag; /* save termios->c_cflag */ /* Info passed in from platform */ u8 mirror_regs; /* Need to mirror regs? */ @@ -1407,9 +1405,6 @@ static void mpsc_set_termios(struct uart_port *port, struct ktermios *termios, ulong flags; u32 chr_bits, stop_bits, par; - pi->c_iflag = termios->c_iflag; - pi->c_cflag = termios->c_cflag; - switch (termios->c_cflag & CSIZE) { case CS5: chr_bits = MPSC_MPCR_CL_5; -- cgit v1.2.3 From aa3188d017d14e8eddc375ef2cc26fefb0b1ecf6 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:52:48 +0100 Subject: TTY: 8250_pnp, constify tables Make modem_names and base static const. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pnp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index 658b392d1170..e813a874c26f 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -380,16 +380,16 @@ static const struct pnp_device_id pnp_dev_table[] = { MODULE_DEVICE_TABLE(pnp, pnp_dev_table); -static char *modem_names[] = { +static const char *modem_names[] = { "MODEM", "Modem", "modem", "FAX", "Fax", "fax", "56K", "56k", "K56", "33.6", "28.8", "14.4", "33,600", "28,800", "14,400", "33.600", "28.800", "14.400", "33600", "28800", "14400", "V.90", "V.34", "V.32", NULL }; -static int check_name(char *name) +static int check_name(const char *name) { - char **tmp; + const char **tmp; for (tmp = modem_names; *tmp; tmp++) if (strstr(name, *tmp)) @@ -400,7 +400,7 @@ static int check_name(char *name) static int check_resources(struct pnp_dev *dev) { - resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8}; + static const resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8}; int i; for (i = 0; i < ARRAY_SIZE(base); i++) { -- cgit v1.2.3 From 1497f2ce16700b773744b4ec1c12f1acaeafb5ae Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:52:49 +0100 Subject: TTY: 8250_pnp, make checks bool Since check_name and check_resources return only 0/1, switch them to bool/true/false. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pnp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index e813a874c26f..f6332de4e3e3 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -387,28 +387,28 @@ static const char *modem_names[] = { "33600", "28800", "14400", "V.90", "V.34", "V.32", NULL }; -static int check_name(const char *name) +static bool check_name(const char *name) { const char **tmp; for (tmp = modem_names; *tmp; tmp++) if (strstr(name, *tmp)) - return 1; + return true; - return 0; + return false; } -static int check_resources(struct pnp_dev *dev) +static bool check_resources(struct pnp_dev *dev) { static const resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8}; - int i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(base); i++) { if (pnp_possible_config(dev, IORESOURCE_IO, base[i], 8)) - return 1; + return true; } - return 0; + return false; } /* -- cgit v1.2.3 From d4dbe374f430156738d34e4572c58f387d558e83 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:59:06 +0100 Subject: TTY: serial/m32r_sio, disband m32r_sio.h The only needed information from the header is struct old_serial_port. Move it to m32r_sio.c, make it const and anonymous. And kill the rest from the header as it is dead stuff. Given m32r_sio_suspend_port and m32r_sio_resume_port are local to m32r_sio.c and unused, kill them from .c too. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/m32r_sio.c | 37 +++++++++----------------------- drivers/tty/serial/m32r_sio.h | 49 ------------------------------------------- 2 files changed, 10 insertions(+), 76 deletions(-) delete mode 100644 drivers/tty/serial/m32r_sio.h (limited to 'drivers') diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index 0eeb64f2499c..3c76ffc2d10a 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c @@ -47,7 +47,6 @@ #define BAUD_RATE 115200 #include -#include "m32r_sio.h" #include "m32r_sio_reg.h" /* @@ -98,7 +97,16 @@ #endif /* !CONFIG_PLAT_USRV */ -static struct old_serial_port old_serial_port[] = { +static const struct { + unsigned int uart; + unsigned int baud_base; + unsigned int port; + unsigned int irq; + unsigned int flags; + unsigned char io_type; + unsigned char __iomem *iomem_base; + unsigned short iomem_reg_shift; +} old_serial_port[] = { SERIAL_PORT_DFNS }; @@ -1112,28 +1120,6 @@ static struct uart_driver m32r_sio_reg = { .cons = M32R_SIO_CONSOLE, }; -/** - * m32r_sio_suspend_port - suspend one serial port - * @line: serial line number - * - * Suspend one serial port. - */ -void m32r_sio_suspend_port(int line) -{ - uart_suspend_port(&m32r_sio_reg, &m32r_sio_ports[line].port); -} - -/** - * m32r_sio_resume_port - resume one serial port - * @line: serial line number - * - * Resume one serial port. - */ -void m32r_sio_resume_port(int line) -{ - uart_resume_port(&m32r_sio_reg, &m32r_sio_ports[line].port); -} - static int __init m32r_sio_init(void) { int ret, i; @@ -1163,8 +1149,5 @@ static void __exit m32r_sio_exit(void) module_init(m32r_sio_init); module_exit(m32r_sio_exit); -EXPORT_SYMBOL(m32r_sio_suspend_port); -EXPORT_SYMBOL(m32r_sio_resume_port); - MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Generic M32R SIO serial driver"); diff --git a/drivers/tty/serial/m32r_sio.h b/drivers/tty/serial/m32r_sio.h deleted file mode 100644 index 8129824496c6..000000000000 --- a/drivers/tty/serial/m32r_sio.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * m32r_sio.h - * - * Driver for M32R serial ports - * - * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. - * Based on drivers/serial/8250.h. - * - * Copyright (C) 2001 Russell King. - * Copyright (C) 2004 Hirokazu Takata - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -struct m32r_sio_probe { - struct module *owner; - int (*pci_init_one)(struct pci_dev *dev); - void (*pci_remove_one)(struct pci_dev *dev); - void (*pnp_init)(void); -}; - -int m32r_sio_register_probe(struct m32r_sio_probe *probe); -void m32r_sio_unregister_probe(struct m32r_sio_probe *probe); -void m32r_sio_get_irq_map(unsigned int *map); -void m32r_sio_suspend_port(int line); -void m32r_sio_resume_port(int line); - -struct old_serial_port { - unsigned int uart; - unsigned int baud_base; - unsigned int port; - unsigned int irq; - unsigned int flags; - unsigned char io_type; - unsigned char __iomem *iomem_base; - unsigned short iomem_reg_shift; -}; - -#define _INLINE_ inline - -#define PROBE_RSA (1 << 0) -#define PROBE_ANY (~0) - -#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) -- cgit v1.2.3 From c8e7d143d519724b3bf5b86615eca2962b77a826 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:59:07 +0100 Subject: TTY: serial/m32r_sio, simplify old_serial_port The only variables in old_serial_port are port and irq. So make old_serial_port contain only those two and move the initialization of the rest to the place where old_serial_port is actually read. Also get rid of SERIAL_PORT_DFNS. It is ugly and having the initializer where it belongs makes more sense. Finally, use already defined UART_NR in the loop. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/m32r_sio.c | 57 ++++++++++++------------------------------- 1 file changed, 15 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index 3c76ffc2d10a..835b5697a455 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c @@ -66,48 +66,22 @@ #define PASS_LIMIT 256 -#define BASE_BAUD 115200 - /* Standard COM flags */ #define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST) -/* - * SERIAL_PORT_DFNS tells us about built-in ports that have no - * standard enumeration mechanism. Platforms that can find all - * serial ports via mechanisms like ACPI or PCI need not supply it. - */ -#if defined(CONFIG_PLAT_USRV) - -#define SERIAL_PORT_DFNS \ - /* UART CLK PORT IRQ FLAGS */ \ - { 0, BASE_BAUD, 0x3F8, PLD_IRQ_UART0, STD_COM_FLAGS }, /* ttyS0 */ \ - { 0, BASE_BAUD, 0x2F8, PLD_IRQ_UART1, STD_COM_FLAGS }, /* ttyS1 */ - -#else /* !CONFIG_PLAT_USRV */ - -#if defined(CONFIG_SERIAL_M32R_PLDSIO) -#define SERIAL_PORT_DFNS \ - { 0, BASE_BAUD, ((unsigned long)PLD_ESIO0CR), PLD_IRQ_SIO0_RCV, \ - STD_COM_FLAGS }, /* ttyS0 */ -#else -#define SERIAL_PORT_DFNS \ - { 0, BASE_BAUD, M32R_SIO_OFFSET, M32R_IRQ_SIO0_R, \ - STD_COM_FLAGS }, /* ttyS0 */ -#endif - -#endif /* !CONFIG_PLAT_USRV */ - static const struct { - unsigned int uart; - unsigned int baud_base; unsigned int port; unsigned int irq; - unsigned int flags; - unsigned char io_type; - unsigned char __iomem *iomem_base; - unsigned short iomem_reg_shift; } old_serial_port[] = { - SERIAL_PORT_DFNS +#if defined(CONFIG_PLAT_USRV) + /* PORT IRQ FLAGS */ + { 0x3F8, PLD_IRQ_UART0 }, /* ttyS0 */ + { 0x2F8, PLD_IRQ_UART1 }, /* ttyS1 */ +#elif defined(CONFIG_SERIAL_M32R_PLDSIO) + { ((unsigned long)PLD_ESIO0CR), PLD_IRQ_SIO0_RCV }, /* ttyS0 */ +#else + { M32R_SIO_OFFSET, M32R_IRQ_SIO0_R }, /* ttyS0 */ +#endif }; #define UART_NR ARRAY_SIZE(old_serial_port) @@ -959,15 +933,14 @@ static void __init m32r_sio_init_ports(void) return; first = 0; - for (i = 0, up = m32r_sio_ports; i < ARRAY_SIZE(old_serial_port); - i++, up++) { + for (i = 0, up = m32r_sio_ports; i < UART_NR; i++, up++) { up->port.iobase = old_serial_port[i].port; up->port.irq = irq_canonicalize(old_serial_port[i].irq); - up->port.uartclk = old_serial_port[i].baud_base * 16; - up->port.flags = old_serial_port[i].flags; - up->port.membase = old_serial_port[i].iomem_base; - up->port.iotype = old_serial_port[i].io_type; - up->port.regshift = old_serial_port[i].iomem_reg_shift; + up->port.uartclk = BAUD_RATE * 16; + up->port.flags = STD_COM_FLAGS; + up->port.membase = 0; + up->port.iotype = 0; + up->port.regshift = 0; up->port.ops = &m32r_sio_pops; } } -- cgit v1.2.3 From ad245aa2750212a8daae44d6dc2f3d34b94d74c6 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:59:08 +0100 Subject: TTY: serial/m32r_sio, remove debug macros DEBUG_AUTOCONF is unused. Switch DEBUG_INTR to pr_debug. This is only enabled with DEBUG or dynamic debug when explicitly asked for. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/m32r_sio.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index 835b5697a455..6b1303505667 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c @@ -49,21 +49,6 @@ #include #include "m32r_sio_reg.h" -/* - * Debugging. - */ -#if 0 -#define DEBUG_AUTOCONF(fmt...) printk(fmt) -#else -#define DEBUG_AUTOCONF(fmt...) do { } while (0) -#endif - -#if 0 -#define DEBUG_INTR(fmt...) printk(fmt) -#else -#define DEBUG_INTR(fmt...) do { } while (0) -#endif - #define PASS_LIMIT 256 /* Standard COM flags */ @@ -334,7 +319,7 @@ static void receive_chars(struct uart_sio_port *up, int *status) } if (*status & UART_LSR_BI) { - DEBUG_INTR("handling break...."); + pr_debug("handling break....\n"); flag = TTY_BREAK; } else if (*status & UART_LSR_PE) flag = TTY_PARITY; @@ -395,7 +380,7 @@ static void transmit_chars(struct uart_sio_port *up) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&up->port); - DEBUG_INTR("THRE..."); + pr_debug("THRE...\n"); if (uart_circ_empty(xmit)) m32r_sio_stop_tx(&up->port); @@ -407,7 +392,7 @@ static void transmit_chars(struct uart_sio_port *up) static inline void m32r_sio_handle_port(struct uart_sio_port *up, unsigned int status) { - DEBUG_INTR("status = %x...", status); + pr_debug("status = %x...\n", status); if (status & 0x04) receive_chars(up, &status); @@ -435,7 +420,7 @@ static irqreturn_t m32r_sio_interrupt(int irq, void *dev_id) struct list_head *l, *end = NULL; int pass_counter = 0; - DEBUG_INTR("m32r_sio_interrupt(%d)...", irq); + pr_debug("m32r_sio_interrupt(%d)...\n", irq); #ifdef CONFIG_SERIAL_M32R_PLDSIO // if (irq == PLD_IRQ_SIO0_SND) @@ -475,7 +460,7 @@ static irqreturn_t m32r_sio_interrupt(int irq, void *dev_id) spin_unlock(&i->lock); - DEBUG_INTR("end.\n"); + pr_debug("end.\n"); return IRQ_HANDLED; } -- cgit v1.2.3 From b85e5ed5621b3a19f1ca20b30fd64803aa3d5ff8 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:59:09 +0100 Subject: TTY: serial/m32r_sio, remove unused members struct uart_sio_port has a lots of unused members. Some of them are set to some constant but never read. Remove all those. This includes removal of uart_ops->pm handler as we never handle pm (pm was never set). Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/m32r_sio.c | 33 --------------------------------- 1 file changed, 33 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index 6b1303505667..68765f7c2645 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c @@ -75,19 +75,7 @@ struct uart_sio_port { struct uart_port port; struct timer_list timer; /* "no irq" timer */ struct list_head list; /* ports on this IRQ */ - unsigned short rev; - unsigned char acr; unsigned char ier; - unsigned char lcr; - unsigned char mcr_mask; /* mask of user bits */ - unsigned char mcr_force; /* mask of forced bits */ - unsigned char lsr_break_flag; - - /* - * We provide a per-port pm hook. - */ - void (*pm)(struct uart_port *port, - unsigned int state, unsigned int old); }; struct irq_info { @@ -312,12 +300,6 @@ static void receive_chars(struct uart_sio_port *up, int *status) */ *status &= up->port.read_status_mask; - if (up->port.line == up->port.cons->index) { - /* Recover the break flag from console xmit */ - *status |= up->lsr_break_flag; - up->lsr_break_flag = 0; - } - if (*status & UART_LSR_BI) { pr_debug("handling break....\n"); flag = TTY_BREAK; @@ -749,20 +731,9 @@ static void m32r_sio_set_termios(struct uart_port *port, serial_out(up, UART_IER, up->ier); - up->lcr = cval; /* Save LCR */ spin_unlock_irqrestore(&up->port.lock, flags); } -static void m32r_sio_pm(struct uart_port *port, unsigned int state, - unsigned int oldstate) -{ - struct uart_sio_port *up = - container_of(port, struct uart_sio_port, port); - - if (up->pm) - up->pm(port, state, oldstate); -} - /* * Resource handling. This is complicated by the fact that resources * depend on the port type. Maybe we should be claiming the standard @@ -899,7 +870,6 @@ static struct uart_ops m32r_sio_pops = { .startup = m32r_sio_startup, .shutdown = m32r_sio_shutdown, .set_termios = m32r_sio_set_termios, - .pm = m32r_sio_pm, .release_port = m32r_sio_release_port, .request_port = m32r_sio_request_port, .config_port = m32r_sio_config_port, @@ -944,9 +914,6 @@ static void __init m32r_sio_register_ports(struct uart_driver *drv) init_timer(&up->timer); up->timer.function = m32r_sio_timeout; - up->mcr_mask = ~0; - up->mcr_force = 0; - uart_add_one_port(drv, &up->port); } } -- cgit v1.2.3 From a07a70bcb72e4a766c8d3173986a773cef842d30 Mon Sep 17 00:00:00 2001 From: "Matwey V. Kornilov" Date: Mon, 1 Feb 2016 21:09:20 +0300 Subject: tty: Move serial8250_stop_rx() in front of serial8250_start_tx() Software RS485 emultaion is to be added in the following commit. serial8250_start_tx() will need to refer serial8250_stop_rx(). Move serial8250_stop_rx() in front of serial8250_start_tx() in order to avoid function forward declaration. Signed-off-by: Matwey V. Kornilov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 0bd3c6baa300..04681e5745de 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1304,6 +1304,19 @@ static void autoconfig_irq(struct uart_8250_port *up) port->irq = (irq > 0) ? irq : 0; } +static void serial8250_stop_rx(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + serial8250_rpm_get(up); + + up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); + up->port.read_status_mask &= ~UART_LSR_DR; + serial_port_out(port, UART_IER, up->ier); + + serial8250_rpm_put(up); +} + static inline void __stop_tx(struct uart_8250_port *p) { if (p->ier & UART_IER_THRI) { @@ -1371,19 +1384,6 @@ static void serial8250_unthrottle(struct uart_port *port) port->unthrottle(port); } -static void serial8250_stop_rx(struct uart_port *port) -{ - struct uart_8250_port *up = up_to_u8250p(port); - - serial8250_rpm_get(up); - - up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); - up->port.read_status_mask &= ~UART_LSR_DR; - serial_port_out(port, UART_IER, up->ier); - - serial8250_rpm_put(up); -} - static void serial8250_disable_ms(struct uart_port *port) { struct uart_8250_port *up = -- cgit v1.2.3 From e490c9144cfaa8e2242c1e5d5187230928f27417 Mon Sep 17 00:00:00 2001 From: "Matwey V. Kornilov" Date: Mon, 1 Feb 2016 21:09:21 +0300 Subject: tty: Add software emulated RS485 support for 8250 Implementation of software emulation of RS485 direction handling is based on omap_serial driver. Before and after transmission RTS is set to the appropriate value. Note that before calling serial8250_em485_init() the caller has to ensure that UART will interrupt when shift register empty. Otherwise, emultaion cannot be used. Both serial8250_em485_init() and serial8250_em485_destroy() are idempotent functions. Signed-off-by: Matwey V. Kornilov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.h | 2 + drivers/tty/serial/8250/8250_port.c | 223 +++++++++++++++++++++++++++++++++++- include/linux/serial_8250.h | 8 ++ 3 files changed, 229 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index d54dcd87c67e..ce587c03efc3 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -117,6 +117,8 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value) struct uart_8250_port *serial8250_get_port(int line); void serial8250_rpm_get(struct uart_8250_port *p); void serial8250_rpm_put(struct uart_8250_port *p); +int serial8250_em485_init(struct uart_8250_port *p); +void serial8250_em485_destroy(struct uart_8250_port *p); #if defined(__alpha__) && !defined(CONFIG_PCI) /* diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 04681e5745de..01a85a7e7427 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -522,6 +523,20 @@ static void serial8250_clear_fifos(struct uart_8250_port *p) } } +static inline void serial8250_em485_rts_after_send(struct uart_8250_port *p) +{ + unsigned char mcr = serial_in(p, UART_MCR); + + if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND) + mcr |= UART_MCR_RTS; + else + mcr &= ~UART_MCR_RTS; + serial_out(p, UART_MCR, mcr); +} + +static void serial8250_em485_handle_start_tx(unsigned long arg); +static void serial8250_em485_handle_stop_tx(unsigned long arg); + void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p) { serial8250_clear_fifos(p); @@ -546,6 +561,73 @@ void serial8250_rpm_put(struct uart_8250_port *p) } EXPORT_SYMBOL_GPL(serial8250_rpm_put); +/** + * serial8250_em485_init() - put uart_8250_port into rs485 emulating + * @p: uart_8250_port port instance + * + * The function is used to start rs485 software emulating on the + * &struct uart_8250_port* @p. Namely, RTS is switched before/after + * transmission. The function is idempotent, so it is safe to call it + * multiple times. + * + * The caller MUST enable interrupt on empty shift register before + * calling serial8250_em485_init(). This interrupt is not a part of + * 8250 standard, but implementation defined. + * + * The function is supposed to be called from .rs485_config callback + * or from any other callback protected with p->port.lock spinlock. + * + * See also serial8250_em485_destroy() + * + * Return 0 - success, -errno - otherwise + */ +int serial8250_em485_init(struct uart_8250_port *p) +{ + if (p->em485 != NULL) + return 0; + + p->em485 = kmalloc(sizeof(struct uart_8250_em485), GFP_KERNEL); + if (p->em485 == NULL) + return -ENOMEM; + + setup_timer(&p->em485->stop_tx_timer, + serial8250_em485_handle_stop_tx, (unsigned long)p); + setup_timer(&p->em485->start_tx_timer, + serial8250_em485_handle_start_tx, (unsigned long)p); + p->em485->active_timer = NULL; + + serial8250_em485_rts_after_send(p); + + return 0; +} +EXPORT_SYMBOL_GPL(serial8250_em485_init); + +/** + * serial8250_em485_destroy() - put uart_8250_port into normal state + * @p: uart_8250_port port instance + * + * The function is used to stop rs485 software emulating on the + * &struct uart_8250_port* @p. The function is idempotent, so it is safe to + * call it multiple times. + * + * The function is supposed to be called from .rs485_config callback + * or from any other callback protected with p->port.lock spinlock. + * + * See also serial8250_em485_init() + */ +void serial8250_em485_destroy(struct uart_8250_port *p) +{ + if (p->em485 == NULL) + return; + + del_timer(&p->em485->start_tx_timer); + del_timer(&p->em485->stop_tx_timer); + + kfree(p->em485); + p->em485 = NULL; +} +EXPORT_SYMBOL_GPL(serial8250_em485_destroy); + /* * These two wrappers ensure that enable_runtime_pm_tx() can be called more than * once and disable_runtime_pm_tx() will still disable RPM because the fifo is @@ -1317,7 +1399,56 @@ static void serial8250_stop_rx(struct uart_port *port) serial8250_rpm_put(up); } -static inline void __stop_tx(struct uart_8250_port *p) +static void __do_stop_tx_rs485(struct uart_8250_port *p) +{ + if (!p->em485) + return; + + serial8250_em485_rts_after_send(p); + /* + * Empty the RX FIFO, we are not interested in anything + * received during the half-duplex transmission. + */ + if (!(p->port.rs485.flags & SER_RS485_RX_DURING_TX)) + serial8250_clear_fifos(p); +} + +static void serial8250_em485_handle_stop_tx(unsigned long arg) +{ + struct uart_8250_port *p = (struct uart_8250_port *)arg; + struct uart_8250_em485 *em485 = p->em485; + unsigned long flags; + + spin_lock_irqsave(&p->port.lock, flags); + if (em485 && + em485->active_timer == &em485->stop_tx_timer) { + __do_stop_tx_rs485(p); + em485->active_timer = NULL; + } + spin_unlock_irqrestore(&p->port.lock, flags); +} + +static void __stop_tx_rs485(struct uart_8250_port *p) +{ + struct uart_8250_em485 *em485 = p->em485; + + if (!em485) + return; + + /* + * __do_stop_tx_rs485 is going to set RTS according to config + * AND flush RX FIFO if required. + */ + if (p->port.rs485.delay_rts_after_send > 0) { + em485->active_timer = &em485->stop_tx_timer; + mod_timer(&em485->stop_tx_timer, jiffies + + p->port.rs485.delay_rts_after_send * HZ / 1000); + } else { + __do_stop_tx_rs485(p); + } +} + +static inline void __do_stop_tx(struct uart_8250_port *p) { if (p->ier & UART_IER_THRI) { p->ier &= ~UART_IER_THRI; @@ -1326,6 +1457,28 @@ static inline void __stop_tx(struct uart_8250_port *p) } } +static inline void __stop_tx(struct uart_8250_port *p) +{ + struct uart_8250_em485 *em485 = p->em485; + + if (em485) { + unsigned char lsr = serial_in(p, UART_LSR); + /* + * To provide required timeing and allow FIFO transfer, + * __stop_tx_rs485 must be called only when both FIFO and + * shift register are empty. It is for device driver to enable + * interrupt on TEMT. + */ + if ((lsr & BOTH_EMPTY) != BOTH_EMPTY) + return; + + del_timer(&em485->start_tx_timer); + em485->active_timer = NULL; + } + __do_stop_tx(p); + __stop_tx_rs485(p); +} + static void serial8250_stop_tx(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); @@ -1343,12 +1496,10 @@ static void serial8250_stop_tx(struct uart_port *port) serial8250_rpm_put(up); } -static void serial8250_start_tx(struct uart_port *port) +static inline void __start_tx(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); - serial8250_rpm_get_tx(up); - if (up->dma && !up->dma->tx_dma(up)) return; @@ -1374,6 +1525,70 @@ static void serial8250_start_tx(struct uart_port *port) } } +static inline void start_tx_rs485(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + struct uart_8250_em485 *em485 = up->em485; + unsigned char mcr; + + if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) + serial8250_stop_rx(&up->port); + + del_timer(&em485->stop_tx_timer); + em485->active_timer = NULL; + + mcr = serial_in(up, UART_MCR); + if (!!(up->port.rs485.flags & SER_RS485_RTS_ON_SEND) != + !!(mcr & UART_MCR_RTS)) { + if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) + mcr |= UART_MCR_RTS; + else + mcr &= ~UART_MCR_RTS; + serial_out(up, UART_MCR, mcr); + + if (up->port.rs485.delay_rts_before_send > 0) { + em485->active_timer = &em485->start_tx_timer; + mod_timer(&em485->start_tx_timer, jiffies + + up->port.rs485.delay_rts_before_send * HZ / 1000); + return; + } + } + + __start_tx(port); +} + +static void serial8250_em485_handle_start_tx(unsigned long arg) +{ + struct uart_8250_port *p = (struct uart_8250_port *)arg; + struct uart_8250_em485 *em485 = p->em485; + unsigned long flags; + + spin_lock_irqsave(&p->port.lock, flags); + if (em485 && + em485->active_timer == &em485->start_tx_timer) { + __start_tx(&p->port); + em485->active_timer = NULL; + } + spin_unlock_irqrestore(&p->port.lock, flags); +} + +static void serial8250_start_tx(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + struct uart_8250_em485 *em485 = up->em485; + + serial8250_rpm_get_tx(up); + + if (em485 && + em485->active_timer == &em485->start_tx_timer) + return; + + if (em485) + start_tx_rs485(port); + else + __start_tx(port); +} + static void serial8250_throttle(struct uart_port *port) { port->throttle(port); diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index faa0e0370ce7..434879759725 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -76,6 +76,12 @@ struct uart_8250_ops { void (*release_irq)(struct uart_8250_port *); }; +struct uart_8250_em485 { + struct timer_list start_tx_timer; /* "rs485 start tx" timer */ + struct timer_list stop_tx_timer; /* "rs485 stop tx" timer */ + struct timer_list *active_timer; /* pointer to active timer */ +}; + /* * This should be used by drivers which want to register * their own 8250 ports without registering their own @@ -122,6 +128,8 @@ struct uart_8250_port { /* 8250 specific callbacks */ int (*dl_read)(struct uart_8250_port *); void (*dl_write)(struct uart_8250_port *, int); + + struct uart_8250_em485 *em485; }; static inline struct uart_8250_port *up_to_u8250p(struct uart_port *up) -- cgit v1.2.3 From 344cee2470ff70801c95c62ab2762da0834c8c6c Mon Sep 17 00:00:00 2001 From: "Matwey V. Kornilov" Date: Mon, 1 Feb 2016 21:09:22 +0300 Subject: tty: 8250_omap: Use software emulated RS485 direction control Use software emulated RS485 direction control to provide RS485 API existed in omap_serial driver. Note that 8250_omap issues interrupt on shift register empty which is single prerequesite for using software emulated RS485. Signed-off-by: Matwey V. Kornilov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_omap.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index a2c0734c76e2..d710985a2e4f 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -697,6 +697,36 @@ static void omap_8250_throttle(struct uart_port *port) pm_runtime_put_autosuspend(port->dev); } +static int omap_8250_rs485_config(struct uart_port *port, + struct serial_rs485 *rs485) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + /* Clamp the delays to [0, 100ms] */ + rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); + rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U); + + port->rs485 = *rs485; + + /* + * Both serial8250_em485_init and serial8250_em485_destroy + * are idempotent + */ + if (rs485->flags & SER_RS485_ENABLED) { + int ret = serial8250_em485_init(up); + + if (ret) { + rs485->flags &= ~SER_RS485_ENABLED; + port->rs485.flags &= ~SER_RS485_ENABLED; + } + return ret; + } + + serial8250_em485_destroy(up); + + return 0; +} + static void omap_8250_unthrottle(struct uart_port *port) { unsigned long flags; @@ -1146,6 +1176,7 @@ static int omap8250_probe(struct platform_device *pdev) up.port.shutdown = omap_8250_shutdown; up.port.throttle = omap_8250_throttle; up.port.unthrottle = omap_8250_unthrottle; + up.port.rs485_config = omap_8250_rs485_config; if (pdev->dev.of_node) { const struct of_device_id *id; -- cgit v1.2.3 From cdcea058e51008479545f29201b4fa577c59733c Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Sat, 12 Dec 2015 19:18:25 +0200 Subject: serial: 8250_dw: Avoid serial_outx code duplicate with new dw8250_check_lcr() With the help of Heikki we take common code that makes sure LCR write wasn't ignored and put it in new function called dw8250_check_lcr(). This function serves 3 serial_out routines: dw8250_serial_out(), dw8250_serial_out32(), and dw8250_serial_outq(). This patch only brings better code reuse. Signed-off-by: Noam Camus Cc: Heikki Krogerus Cc: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 91 ++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index a5d319e4aae6..ffe5e0cb1f05 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -95,25 +95,43 @@ static void dw8250_force_idle(struct uart_port *p) (void)p->serial_in(p, UART_RX); } -static void dw8250_serial_out(struct uart_port *p, int offset, int value) +static void dw8250_check_lcr(struct uart_port *p, int value) { - writeb(value, p->membase + (offset << p->regshift)); + void __iomem *offset = p->membase + (UART_LCR << p->regshift); + int tries = 1000; /* Make sure LCR write wasn't ignored */ - if (offset == UART_LCR) { - int tries = 1000; - while (tries--) { - unsigned int lcr = p->serial_in(p, UART_LCR); - if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) - return; - dw8250_force_idle(p); - writeb(value, p->membase + (UART_LCR << p->regshift)); - } - /* - * FIXME: this deadlocks if port->lock is already held - * dev_err(p->dev, "Couldn't set LCR to %d\n", value); - */ + while (tries--) { + unsigned int lcr = p->serial_in(p, UART_LCR); + + if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) + return; + + dw8250_force_idle(p); + +#ifdef CONFIG_64BIT + __raw_writeq(value & 0xff, offset); +#else + if (p->iotype == UPIO_MEM32) + writel(value, offset); + else + writeb(value, offset); +#endif } + /* + * FIXME: this deadlocks if port->lock is already held + * dev_err(p->dev, "Couldn't set LCR to %d\n", value); + */ +} + +static void dw8250_serial_out(struct uart_port *p, int offset, int value) +{ + struct dw8250_data *d = p->private_data; + + writeb(value, p->membase + (offset << p->regshift)); + + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); } static unsigned int dw8250_serial_in(struct uart_port *p, int offset) @@ -135,49 +153,26 @@ static unsigned int dw8250_serial_inq(struct uart_port *p, int offset) static void dw8250_serial_outq(struct uart_port *p, int offset, int value) { + struct dw8250_data *d = p->private_data; + value &= 0xff; __raw_writeq(value, p->membase + (offset << p->regshift)); /* Read back to ensure register write ordering. */ __raw_readq(p->membase + (UART_LCR << p->regshift)); - /* Make sure LCR write wasn't ignored */ - if (offset == UART_LCR) { - int tries = 1000; - while (tries--) { - unsigned int lcr = p->serial_in(p, UART_LCR); - if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) - return; - dw8250_force_idle(p); - __raw_writeq(value & 0xff, - p->membase + (UART_LCR << p->regshift)); - } - /* - * FIXME: this deadlocks if port->lock is already held - * dev_err(p->dev, "Couldn't set LCR to %d\n", value); - */ - } + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); } #endif /* CONFIG_64BIT */ static void dw8250_serial_out32(struct uart_port *p, int offset, int value) { + struct dw8250_data *d = p->private_data; + writel(value, p->membase + (offset << p->regshift)); - /* Make sure LCR write wasn't ignored */ - if (offset == UART_LCR) { - int tries = 1000; - while (tries--) { - unsigned int lcr = p->serial_in(p, UART_LCR); - if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) - return; - dw8250_force_idle(p); - writel(value, p->membase + (UART_LCR << p->regshift)); - } - /* - * FIXME: this deadlocks if port->lock is already held - * dev_err(p->dev, "Couldn't set LCR to %d\n", value); - */ - } + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); } static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) @@ -463,10 +458,8 @@ static int dw8250_probe(struct platform_device *pdev) dw8250_quirks(p, data); /* If the Busy Functionality is not implemented, don't handle it */ - if (data->uart_16550_compatible) { - p->serial_out = NULL; + if (data->uart_16550_compatible) p->handle_irq = NULL; - } if (!data->skip_autocfg) dw8250_setup_port(p); -- cgit v1.2.3 From 4625090187768bc776d69dfaa6a1f79b1125debe Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Sat, 12 Dec 2015 19:18:26 +0200 Subject: serial: 8250_dw: Add support for big-endian MMIO accesses Add support for UPIO_MEM32BE in addition to UPIO_MEM32. For big endian we use 2 new accessors similar to little endian, called dw8250_serial_out32be() and dw8250_serial_in32be(). Signed-off-by: Noam Camus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index ffe5e0cb1f05..92c4a9bc2e6d 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -182,6 +182,24 @@ static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) return dw8250_modify_msr(p, offset, value); } +static void dw8250_serial_out32be(struct uart_port *p, int offset, int value) +{ + struct dw8250_data *d = p->private_data; + + iowrite32be(value, p->membase + (offset << p->regshift)); + + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); +} + +static unsigned int dw8250_serial_in32be(struct uart_port *p, int offset) +{ + unsigned int value = ioread32be(p->membase + (offset << p->regshift)); + + return dw8250_modify_msr(p, offset, value); +} + + static int dw8250_handle_irq(struct uart_port *p) { struct dw8250_data *d = p->private_data; @@ -276,6 +294,11 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) data->skip_autocfg = true; } #endif + if (of_device_is_big_endian(p->dev->of_node)) { + p->iotype = UPIO_MEM32BE; + p->serial_in = dw8250_serial_in32be; + p->serial_out = dw8250_serial_out32be; + } } else if (has_acpi_companion(p->dev)) { p->iotype = UPIO_MEM32; p->regshift = 2; -- cgit v1.2.3 From 5a43140cc4a59eda4549cc3b74989efa77973158 Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Sat, 12 Dec 2015 19:18:27 +0200 Subject: serial: 8250_dw: Do not use readl/writel before checking port iotype Direct call to readl()/writel() is checked against iotype and in case of UPIO_MEM32BE we use ioread32be()/iowrite32be() instead of them. Signed-off-by: Noam Camus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 92c4a9bc2e6d..30810acf7f96 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -114,6 +114,8 @@ static void dw8250_check_lcr(struct uart_port *p, int value) #else if (p->iotype == UPIO_MEM32) writel(value, offset); + else if (p->iotype == UPIO_MEM32BE) + iowrite32be(value, offset); else writeb(value, offset); #endif @@ -327,14 +329,20 @@ static void dw8250_setup_port(struct uart_port *p) * If the Component Version Register returns zero, we know that * ADDITIONAL_FEATURES are not enabled. No need to go any further. */ - reg = readl(p->membase + DW_UART_UCV); + if (p->iotype == UPIO_MEM32BE) + reg = ioread32be(p->membase + DW_UART_UCV); + else + reg = readl(p->membase + DW_UART_UCV); if (!reg) return; dev_dbg(p->dev, "Designware UART version %c.%c%c\n", (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff); - reg = readl(p->membase + DW_UART_CPR); + if (p->iotype == UPIO_MEM32BE) + reg = ioread32be(p->membase + DW_UART_CPR); + else + reg = readl(p->membase + DW_UART_CPR); if (!reg) return; -- cgit v1.2.3 From cc74bd1d218053cefc6323721512808d36a1bfb1 Mon Sep 17 00:00:00 2001 From: Aya Mahfouz Date: Tue, 15 Dec 2015 01:45:16 +0200 Subject: tty: serial: constify psc_ops structs Constifies psc_ops structures in tty's serial port driver since they are not modified after their initialization. Detected and found using Coccinelle. Suggested-by: Julia Lawall Signed-off-by: Aya Mahfouz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mpc52xx_uart.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index 8c3e51314470..3970d6a9aaca 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c @@ -346,7 +346,7 @@ static irqreturn_t mpc52xx_psc_handle_irq(struct uart_port *port) return mpc5xxx_uart_process_int(port); } -static struct psc_ops mpc52xx_psc_ops = { +static const struct psc_ops mpc52xx_psc_ops = { .fifo_init = mpc52xx_psc_fifo_init, .raw_rx_rdy = mpc52xx_psc_raw_rx_rdy, .raw_tx_rdy = mpc52xx_psc_raw_tx_rdy, @@ -376,7 +376,7 @@ static struct psc_ops mpc52xx_psc_ops = { .get_mr1 = mpc52xx_psc_get_mr1, }; -static struct psc_ops mpc5200b_psc_ops = { +static const struct psc_ops mpc5200b_psc_ops = { .fifo_init = mpc52xx_psc_fifo_init, .raw_rx_rdy = mpc52xx_psc_raw_rx_rdy, .raw_tx_rdy = mpc52xx_psc_raw_tx_rdy, @@ -969,7 +969,7 @@ static u8 mpc5125_psc_get_mr1(struct uart_port *port) return in_8(&PSC_5125(port)->mr1); } -static struct psc_ops mpc5125_psc_ops = { +static const struct psc_ops mpc5125_psc_ops = { .fifo_init = mpc5125_psc_fifo_init, .raw_rx_rdy = mpc5125_psc_raw_rx_rdy, .raw_tx_rdy = mpc5125_psc_raw_tx_rdy, @@ -1004,7 +1004,7 @@ static struct psc_ops mpc5125_psc_ops = { .get_mr1 = mpc5125_psc_get_mr1, }; -static struct psc_ops mpc512x_psc_ops = { +static const struct psc_ops mpc512x_psc_ops = { .fifo_init = mpc512x_psc_fifo_init, .raw_rx_rdy = mpc512x_psc_raw_rx_rdy, .raw_tx_rdy = mpc512x_psc_raw_tx_rdy, -- cgit v1.2.3 From aaa68c50b28c903a2fa53aad3d5fd17e8cc7f492 Mon Sep 17 00:00:00 2001 From: Frederik Völkel Date: Fri, 18 Dec 2015 12:28:23 +0100 Subject: serial: Remove 68328 driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's old, messy and mostly unmaintained. Remove it as suggested by Peter Hurley and Alan. Signed-off-by: Frederik Völkel Signed-off-by: Lukas Braun Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/68328serial.c | 1309 -------------------------------------- drivers/tty/serial/Kconfig | 11 - drivers/tty/serial/Makefile | 1 - 3 files changed, 1321 deletions(-) delete mode 100644 drivers/tty/serial/68328serial.c (limited to 'drivers') diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c deleted file mode 100644 index 9587ed1242fe..000000000000 --- a/drivers/tty/serial/68328serial.c +++ /dev/null @@ -1,1309 +0,0 @@ -/* 68328serial.c: Serial port driver for 68328 microcontroller - * - * Copyright (C) 1995 David S. Miller - * Copyright (C) 1998 Kenneth Albanowski - * Copyright (C) 1998, 1999 D. Jeff Dionne - * Copyright (C) 1999 Vladimir Gurevich - * Copyright (C) 2002-2003 David McCullough - * Copyright (C) 2002 Greg Ungerer - * - * VZ Support/Fixes Evan Stawnyczy - * Multiple UART support Daniel Potts - * Power management support Daniel Potts - * VZ Second Serial Port enable Phil Wilshire - * 2.4/2.5 port David McCullough - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* (es) */ -/* note: perhaps we can murge these files, so that you can just - * define 1 of them, and they can sort that out for themselves - */ -#if defined(CONFIG_M68EZ328) -#include -#else -#if defined(CONFIG_M68VZ328) -#include -#else -#include -#endif /* CONFIG_M68VZ328 */ -#endif /* CONFIG_M68EZ328 */ - -/* Turn off usage of real serial interrupt code, to "support" Copilot */ -#ifdef CONFIG_XCOPILOT_BUGS -#undef USE_INTS -#else -#define USE_INTS -#endif - -/* - * I believe this is the optimal setting that reduces the number of interrupts. - * At high speeds the output might become a little "bursted" (use USTCNT_TXHE - * if that bothers you), but in most cases it will not, since we try to - * transmit characters every time rs_interrupt is called. Thus, quite often - * you'll see that a receive interrupt occures before the transmit one. - * -- Vladimir Gurevich - */ -#define USTCNT_TX_INTR_MASK (USTCNT_TXEE) - -/* - * 68328 and 68EZ328 UARTS are a little bit different. EZ328 has special - * "Old data interrupt" which occures whenever the data stay in the FIFO - * longer than 30 bits time. This allows us to use FIFO without compromising - * latency. '328 does not have this feature and without the real 328-based - * board I would assume that RXRE is the safest setting. - * - * For EZ328 I use RXHE (Half empty) interrupt to reduce the number of - * interrupts. RXFE (receive queue full) causes the system to lose data - * at least at 115200 baud - * - * If your board is busy doing other stuff, you might consider to use - * RXRE (data ready intrrupt) instead. - * - * The other option is to make these INTR masks run-time configurable, so - * that people can dynamically adapt them according to the current usage. - * -- Vladimir Gurevich - */ - -/* (es) */ -#if defined(CONFIG_M68EZ328) || defined(CONFIG_M68VZ328) -#define USTCNT_RX_INTR_MASK (USTCNT_RXHE | USTCNT_ODEN) -#elif defined(CONFIG_M68328) -#define USTCNT_RX_INTR_MASK (USTCNT_RXRE) -#else -#error Please, define the Rx interrupt events for your CPU -#endif -/* (/es) */ - -/* - * This is our internal structure for each serial port's state. - */ -struct m68k_serial { - struct tty_port tport; - char is_cons; /* Is this our console. */ - int magic; - int baud_base; - int port; - int irq; - int type; /* UART type */ - int custom_divisor; - int x_char; /* xon/xoff character */ - int line; - unsigned char *xmit_buf; - int xmit_head; - int xmit_tail; - int xmit_cnt; -}; - -#define SERIAL_MAGIC 0x5301 - -/* - * Define the number of ports supported and their irqs. - */ -#define NR_PORTS 1 - -static struct m68k_serial m68k_soft[NR_PORTS]; - -static unsigned int uart_irqs[NR_PORTS] = { UART_IRQ_NUM }; - -/* multiple ports are contiguous in memory */ -m68328_uart *uart_addr = (m68328_uart *)USTCNT_ADDR; - -struct tty_driver *serial_driver; - -static void change_speed(struct m68k_serial *info, struct tty_struct *tty); - -/* - * Setup for console. Argument comes from the boot command line. - */ - -/* note: this is messy, but it works, again, perhaps defined somewhere else?*/ -#ifdef CONFIG_M68VZ328 -#define CONSOLE_BAUD_RATE 19200 -#define DEFAULT_CBAUD B19200 -#endif - - -#ifndef CONSOLE_BAUD_RATE -#define CONSOLE_BAUD_RATE 9600 -#define DEFAULT_CBAUD B9600 -#endif - - -static int m68328_console_initted; -static int m68328_console_baud = CONSOLE_BAUD_RATE; -static int m68328_console_cbaud = DEFAULT_CBAUD; - - -static inline int serial_paranoia_check(struct m68k_serial *info, - char *name, const char *routine) -{ -#ifdef SERIAL_PARANOIA_CHECK - static const char *badmagic = - "Warning: bad magic number for serial struct %s in %s\n"; - static const char *badinfo = - "Warning: null m68k_serial for %s in %s\n"; - - if (!info) { - printk(badinfo, name, routine); - return 1; - } - if (info->magic != SERIAL_MAGIC) { - printk(badmagic, name, routine); - return 1; - } -#endif - return 0; -} - -/* - * This is used to figure out the divisor speeds and the timeouts - */ -static int baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 115200, 0 }; - -/* Utility routines */ -static inline int get_baud(struct m68k_serial *ss) -{ - unsigned long result = 115200; - unsigned short int baud = uart_addr[ss->line].ubaud; - if (GET_FIELD(baud, UBAUD_PRESCALER) == 0x38) result = 38400; - result >>= GET_FIELD(baud, UBAUD_DIVIDE); - - return result; -} - -/* - * ------------------------------------------------------------ - * rs_stop() and rs_start() - * - * This routines are called before setting or resetting tty->stopped. - * They enable or disable transmitter interrupts, as necessary. - * ------------------------------------------------------------ - */ -static void rs_stop(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - m68328_uart *uart = &uart_addr[info->line]; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_stop")) - return; - - local_irq_save(flags); - uart->ustcnt &= ~USTCNT_TXEN; - local_irq_restore(flags); -} - -static int rs_put_char(char ch) -{ - unsigned long flags; - int loops = 0; - - local_irq_save(flags); - - while (!(UTX & UTX_TX_AVAIL) && (loops < 1000)) { - loops++; - udelay(5); - } - - UTX_TXDATA = ch; - udelay(5); - local_irq_restore(flags); - return 1; -} - -static void rs_start(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - m68328_uart *uart = &uart_addr[info->line]; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_start")) - return; - - local_irq_save(flags); - if (info->xmit_cnt && info->xmit_buf && !(uart->ustcnt & USTCNT_TXEN)) { -#ifdef USE_INTS - uart->ustcnt |= USTCNT_TXEN | USTCNT_TX_INTR_MASK; -#else - uart->ustcnt |= USTCNT_TXEN; -#endif - } - local_irq_restore(flags); -} - -static void receive_chars(struct m68k_serial *info, unsigned short rx) -{ - m68328_uart *uart = &uart_addr[info->line]; - unsigned char ch, flag; - - /* - * This do { } while() loop will get ALL chars out of Rx FIFO - */ -#ifndef CONFIG_XCOPILOT_BUGS - do { -#endif - ch = GET_FIELD(rx, URX_RXDATA); - - if (info->is_cons) { - if (URX_BREAK & rx) { /* whee, break received */ - return; -#ifdef CONFIG_MAGIC_SYSRQ - } else if (ch == 0x10) { /* ^P */ - show_state(); - show_free_areas(0); - show_buffers(); -/* show_net_buffers(); */ - return; - } else if (ch == 0x12) { /* ^R */ - emergency_restart(); - return; -#endif /* CONFIG_MAGIC_SYSRQ */ - } - } - - flag = TTY_NORMAL; - - if (rx & URX_PARITY_ERROR) - flag = TTY_PARITY; - else if (rx & URX_OVRUN) - flag = TTY_OVERRUN; - else if (rx & URX_FRAME_ERROR) - flag = TTY_FRAME; - - tty_insert_flip_char(&info->tport, ch, flag); -#ifndef CONFIG_XCOPILOT_BUGS - } while ((rx = uart->urx.w) & URX_DATA_READY); -#endif - - tty_schedule_flip(&info->tport); -} - -static void transmit_chars(struct m68k_serial *info, struct tty_struct *tty) -{ - m68328_uart *uart = &uart_addr[info->line]; - - if (info->x_char) { - /* Send next char */ - uart->utx.b.txdata = info->x_char; - info->x_char = 0; - goto clear_and_return; - } - - if ((info->xmit_cnt <= 0) || !tty || tty->stopped) { - /* That's peculiar... TX ints off */ - uart->ustcnt &= ~USTCNT_TX_INTR_MASK; - goto clear_and_return; - } - - /* Send char */ - uart->utx.b.txdata = info->xmit_buf[info->xmit_tail++]; - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt--; - - if (info->xmit_cnt <= 0) { - /* All done for now... TX ints off */ - uart->ustcnt &= ~USTCNT_TX_INTR_MASK; - goto clear_and_return; - } - -clear_and_return: - /* Clear interrupt (should be auto)*/ - return; -} - -/* - * This is the serial driver's generic interrupt routine - */ -irqreturn_t rs_interrupt(int irq, void *dev_id) -{ - struct m68k_serial *info = dev_id; - struct tty_struct *tty = tty_port_tty_get(&info->tport); - m68328_uart *uart; - unsigned short rx; - unsigned short tx; - - uart = &uart_addr[info->line]; - rx = uart->urx.w; - -#ifdef USE_INTS - tx = uart->utx.w; - - if (rx & URX_DATA_READY) - receive_chars(info, rx); - if (tx & UTX_TX_AVAIL) - transmit_chars(info, tty); -#else - receive_chars(info, rx); -#endif - tty_kref_put(tty); - - return IRQ_HANDLED; -} - -static int startup(struct m68k_serial *info, struct tty_struct *tty) -{ - m68328_uart *uart = &uart_addr[info->line]; - unsigned long flags; - - if (info->tport.flags & ASYNC_INITIALIZED) - return 0; - - if (!info->xmit_buf) { - info->xmit_buf = (unsigned char *) __get_free_page(GFP_KERNEL); - if (!info->xmit_buf) - return -ENOMEM; - } - - local_irq_save(flags); - - /* - * Clear the FIFO buffers and disable them - * (they will be reenabled in change_speed()) - */ - - uart->ustcnt = USTCNT_UEN; - uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | USTCNT_TXEN; - (void)uart->urx.w; - - /* - * Finally, enable sequencing and interrupts - */ -#ifdef USE_INTS - uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | - USTCNT_RX_INTR_MASK | USTCNT_TX_INTR_MASK; -#else - uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | USTCNT_RX_INTR_MASK; -#endif - - if (tty) - clear_bit(TTY_IO_ERROR, &tty->flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - - /* - * and set the speed of the serial port - */ - - change_speed(info, tty); - - info->tport.flags |= ASYNC_INITIALIZED; - local_irq_restore(flags); - return 0; -} - -/* - * This routine will shutdown a serial port; interrupts are disabled, and - * DTR is dropped if the hangup on close termio flag is on. - */ -static void shutdown(struct m68k_serial *info, struct tty_struct *tty) -{ - m68328_uart *uart = &uart_addr[info->line]; - unsigned long flags; - - uart->ustcnt = 0; /* All off! */ - if (!(info->tport.flags & ASYNC_INITIALIZED)) - return; - - local_irq_save(flags); - - if (info->xmit_buf) { - free_page((unsigned long) info->xmit_buf); - info->xmit_buf = 0; - } - - if (tty) - set_bit(TTY_IO_ERROR, &tty->flags); - - info->tport.flags &= ~ASYNC_INITIALIZED; - local_irq_restore(flags); -} - -struct { - int divisor, prescale; -} -#ifndef CONFIG_M68VZ328 - hw_baud_table[18] = { - {0, 0}, /* 0 */ - {0, 0}, /* 50 */ - {0, 0}, /* 75 */ - {0, 0}, /* 110 */ - {0, 0}, /* 134 */ - {0, 0}, /* 150 */ - {0, 0}, /* 200 */ - {7, 0x26}, /* 300 */ - {6, 0x26}, /* 600 */ - {5, 0x26}, /* 1200 */ - {0, 0}, /* 1800 */ - {4, 0x26}, /* 2400 */ - {3, 0x26}, /* 4800 */ - {2, 0x26}, /* 9600 */ - {1, 0x26}, /* 19200 */ - {0, 0x26}, /* 38400 */ - {1, 0x38}, /* 57600 */ - {0, 0x38}, /* 115200 */ -}; -#else - hw_baud_table[18] = { - {0, 0}, /* 0 */ - {0, 0}, /* 50 */ - {0, 0}, /* 75 */ - {0, 0}, /* 110 */ - {0, 0}, /* 134 */ - {0, 0}, /* 150 */ - {0, 0}, /* 200 */ - {0, 0}, /* 300 */ - {7, 0x26}, /* 600 */ - {6, 0x26}, /* 1200 */ - {0, 0}, /* 1800 */ - {5, 0x26}, /* 2400 */ - {4, 0x26}, /* 4800 */ - {3, 0x26}, /* 9600 */ - {2, 0x26}, /* 19200 */ - {1, 0x26}, /* 38400 */ - {0, 0x26}, /* 57600 */ - {1, 0x38}, /* 115200 */ -}; -#endif -/* rate = 1036800 / ((65 - prescale) * (1<line]; - unsigned short port; - unsigned short ustcnt; - unsigned cflag; - int i; - - cflag = tty->termios.c_cflag; - port = info->port; - if (!port) - return; - - ustcnt = uart->ustcnt; - uart->ustcnt = ustcnt & ~USTCNT_TXEN; - - i = cflag & CBAUD; - if (i & CBAUDEX) { - i = (i & ~CBAUDEX) + B38400; - } - - uart->ubaud = PUT_FIELD(UBAUD_DIVIDE, hw_baud_table[i].divisor) | - PUT_FIELD(UBAUD_PRESCALER, hw_baud_table[i].prescale); - - ustcnt &= ~(USTCNT_PARITYEN | USTCNT_ODD_EVEN | USTCNT_STOP | USTCNT_8_7); - - if ((cflag & CSIZE) == CS8) - ustcnt |= USTCNT_8_7; - - if (cflag & CSTOPB) - ustcnt |= USTCNT_STOP; - - if (cflag & PARENB) - ustcnt |= USTCNT_PARITYEN; - if (cflag & PARODD) - ustcnt |= USTCNT_ODD_EVEN; - -#ifdef CONFIG_SERIAL_68328_RTS_CTS - if (cflag & CRTSCTS) { - uart->utx.w &= ~UTX_NOCTS; - } else { - uart->utx.w |= UTX_NOCTS; - } -#endif - - ustcnt |= USTCNT_TXEN; - - uart->ustcnt = ustcnt; - return; -} - -/* - * Fair output driver allows a process to speak. - */ -static void rs_fair_output(void) -{ - int left; /* Output no more than that */ - unsigned long flags; - struct m68k_serial *info = &m68k_soft[0]; - char c; - - if (info == NULL) return; - if (info->xmit_buf == NULL) return; - - local_irq_save(flags); - left = info->xmit_cnt; - while (left != 0) { - c = info->xmit_buf[info->xmit_tail]; - info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt--; - local_irq_restore(flags); - - rs_put_char(c); - - local_irq_save(flags); - left = min(info->xmit_cnt, left-1); - } - - /* Last character is being transmitted now (hopefully). */ - udelay(5); - - local_irq_restore(flags); - return; -} - -/* - * m68k_console_print is registered for printk. - */ -void console_print_68328(const char *p) -{ - char c; - - while ((c = *(p++)) != 0) { - if (c == '\n') - rs_put_char('\r'); - rs_put_char(c); - } - - /* Comment this if you want to have a strict interrupt-driven output */ - rs_fair_output(); - - return; -} - -static void rs_set_ldisc(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_set_ldisc")) - return; - - info->is_cons = (tty->termios.c_line == N_TTY); - - printk("ttyS%d console mode %s\n", info->line, info->is_cons ? "on" : "off"); -} - -static void rs_flush_chars(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - m68328_uart *uart = &uart_addr[info->line]; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) - return; -#ifndef USE_INTS - for (;;) { -#endif - - /* Enable transmitter */ - local_irq_save(flags); - - if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf) { - local_irq_restore(flags); - return; - } - -#ifdef USE_INTS - uart->ustcnt |= USTCNT_TXEN | USTCNT_TX_INTR_MASK; -#else - uart->ustcnt |= USTCNT_TXEN; -#endif - -#ifdef USE_INTS - if (uart->utx.w & UTX_TX_AVAIL) { -#else - if (1) { -#endif - /* Send char */ - uart->utx.b.txdata = info->xmit_buf[info->xmit_tail++]; - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt--; - } - -#ifndef USE_INTS - while (!(uart->utx.w & UTX_TX_AVAIL)) udelay(5); - } -#endif - local_irq_restore(flags); -} - -extern void console_printn(const char *b, int count); - -static int rs_write(struct tty_struct *tty, - const unsigned char *buf, int count) -{ - int c, total = 0; - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - m68328_uart *uart = &uart_addr[info->line]; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_write")) - return 0; - - if (!tty || !info->xmit_buf) - return 0; - - local_save_flags(flags); - while (1) { - local_irq_disable(); - c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - local_irq_restore(flags); - - if (c <= 0) - break; - - memcpy(info->xmit_buf + info->xmit_head, buf, c); - - local_irq_disable(); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; - local_irq_restore(flags); - buf += c; - count -= c; - total += c; - } - - if (info->xmit_cnt && !tty->stopped) { - /* Enable transmitter */ - local_irq_disable(); -#ifndef USE_INTS - while (info->xmit_cnt) { -#endif - - uart->ustcnt |= USTCNT_TXEN; -#ifdef USE_INTS - uart->ustcnt |= USTCNT_TX_INTR_MASK; -#else - while (!(uart->utx.w & UTX_TX_AVAIL)) udelay(5); -#endif - if (uart->utx.w & UTX_TX_AVAIL) { - uart->utx.b.txdata = info->xmit_buf[info->xmit_tail++]; - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt--; - } - -#ifndef USE_INTS - } -#endif - local_irq_restore(flags); - } - - return total; -} - -static int rs_write_room(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - int ret; - - if (serial_paranoia_check(info, tty->name, "rs_write_room")) - return 0; - ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; - if (ret < 0) - ret = 0; - return ret; -} - -static int rs_chars_in_buffer(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) - return 0; - return info->xmit_cnt; -} - -static void rs_flush_buffer(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) - return; - local_irq_save(flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - local_irq_restore(flags); - tty_wakeup(tty); -} - -/* - * ------------------------------------------------------------ - * rs_throttle() - * - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - * ------------------------------------------------------------ - */ -static void rs_throttle(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_throttle")) - return; - - if (I_IXOFF(tty)) - info->x_char = STOP_CHAR(tty); - - /* Turn off RTS line (do this atomic) */ -} - -static void rs_unthrottle(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) - return; - - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - info->x_char = START_CHAR(tty); - } - - /* Assert RTS line (do this atomic) */ -} - -/* - * ------------------------------------------------------------ - * rs_ioctl() and friends - * ------------------------------------------------------------ - */ - -static int get_serial_info(struct m68k_serial *info, - struct serial_struct *retinfo) -{ - struct serial_struct tmp; - - if (!retinfo) - return -EFAULT; - memset(&tmp, 0, sizeof(tmp)); - tmp.type = info->type; - tmp.line = info->line; - tmp.port = info->port; - tmp.irq = info->irq; - tmp.flags = info->tport.flags; - tmp.baud_base = info->baud_base; - tmp.close_delay = info->tport.close_delay; - tmp.closing_wait = info->tport.closing_wait; - tmp.custom_divisor = info->custom_divisor; - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - - return 0; -} - -static int set_serial_info(struct m68k_serial *info, struct tty_struct *tty, - struct serial_struct *new_info) -{ - struct tty_port *port = &info->tport; - struct serial_struct new_serial; - struct m68k_serial old_info; - int retval = 0; - - if (!new_info) - return -EFAULT; - if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) - return -EFAULT; - old_info = *info; - - if (!capable(CAP_SYS_ADMIN)) { - if ((new_serial.baud_base != info->baud_base) || - (new_serial.type != info->type) || - (new_serial.close_delay != port->close_delay) || - ((new_serial.flags & ~ASYNC_USR_MASK) != - (port->flags & ~ASYNC_USR_MASK))) - return -EPERM; - port->flags = ((port->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - info->custom_divisor = new_serial.custom_divisor; - goto check_and_exit; - } - - if (port->count > 1) - return -EBUSY; - - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - - info->baud_base = new_serial.baud_base; - port->flags = ((port->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); - info->type = new_serial.type; - port->close_delay = new_serial.close_delay; - port->closing_wait = new_serial.closing_wait; - -check_and_exit: - retval = startup(info, tty); - return retval; -} - -/* - * get_lsr_info - get line status register info - * - * Purpose: Let user call ioctl() to get info when the UART physically - * is emptied. On bus types like RS485, the transmitter must - * release the bus after transmitting. This must be done when - * the transmit shift register is empty, not be done when the - * transmit holding register is empty. This functionality - * allows an RS485 driver to be written in user space. - */ -static int get_lsr_info(struct m68k_serial *info, unsigned int *value) -{ -#ifdef CONFIG_SERIAL_68328_RTS_CTS - m68328_uart *uart = &uart_addr[info->line]; -#endif - unsigned char status; - unsigned long flags; - - local_irq_save(flags); -#ifdef CONFIG_SERIAL_68328_RTS_CTS - status = (uart->utx.w & UTX_CTS_STAT) ? 1 : 0; -#else - status = 0; -#endif - local_irq_restore(flags); - return put_user(status, value); -} - -/* - * This routine sends a break character out the serial port. - */ -static void send_break(struct m68k_serial *info, unsigned int duration) -{ - m68328_uart *uart = &uart_addr[info->line]; - unsigned long flags; - if (!info->port) - return; - local_irq_save(flags); -#ifdef USE_INTS - uart->utx.w |= UTX_SEND_BREAK; - msleep_interruptible(duration); - uart->utx.w &= ~UTX_SEND_BREAK; -#endif - local_irq_restore(flags); -} - -static int rs_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - int retval; - - if (serial_paranoia_check(info, tty->name, "rs_ioctl")) - return -ENODEV; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && - (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - switch (cmd) { - case TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - if (!arg) - send_break(info, 250); /* 1/4 second */ - return 0; - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - send_break(info, arg ? arg*(100) : 250); - return 0; - case TIOCGSERIAL: - return get_serial_info(info, - (struct serial_struct *) arg); - case TIOCSSERIAL: - return set_serial_info(info, tty, - (struct serial_struct *) arg); - case TIOCSERGETLSR: /* Get line status register */ - return get_lsr_info(info, (unsigned int *) arg); - case TIOCSERGSTRUCT: - if (copy_to_user((struct m68k_serial *) arg, - info, sizeof(struct m68k_serial))) - return -EFAULT; - return 0; - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - - change_speed(info, tty); - - if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) - rs_start(tty); -} - -/* - * ------------------------------------------------------------ - * rs_close() - * - * This routine is called when the serial port gets closed. First, we - * wait for the last remaining data to be sent. Then, we unlink its - * S structure from the interrupt chain if necessary, and we free - * that IRQ if nothing is left in the chain. - * ------------------------------------------------------------ - */ -static void rs_close(struct tty_struct *tty, struct file *filp) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - struct tty_port *port = &info->tport; - m68328_uart *uart = &uart_addr[info->line]; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_close")) - return; - - local_irq_save(flags); - - if (tty_hung_up_p(filp)) { - local_irq_restore(flags); - return; - } - - if ((tty->count == 1) && (port->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. Info->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk("rs_close: bad serial port count; tty->count is 1, " - "port->count is %d\n", port->count); - port->count = 1; - } - if (--port->count < 0) { - printk("rs_close: bad serial port count for ttyS%d: %d\n", - info->line, port->count); - port->count = 0; - } - if (port->count) { - local_irq_restore(flags); - return; - } - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, port->closing_wait); - /* - * At this point we stop accepting input. To do this, we - * disable the receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ - - uart->ustcnt &= ~USTCNT_RXEN; - uart->ustcnt &= ~(USTCNT_RXEN | USTCNT_RX_INTR_MASK); - - shutdown(info, tty); - rs_flush_buffer(tty); - - tty_ldisc_flush(tty); - tty->closing = 0; - tty_port_tty_set(&info->tport, NULL); - - if (port->blocked_open) { - if (port->close_delay) - msleep_interruptible(jiffies_to_msecs(port->close_delay)); - wake_up_interruptible(&port->open_wait); - } - port->flags &= ~ASYNC_NORMAL_ACTIVE; - local_irq_restore(flags); -} - -/* - * rs_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -void rs_hangup(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_hangup")) - return; - - rs_flush_buffer(tty); - shutdown(info, tty); - info->tport.count = 0; - info->tport.flags &= ~ASYNC_NORMAL_ACTIVE; - tty_port_tty_set(&info->tport, NULL); - wake_up_interruptible(&info->tport.open_wait); -} - -/* - * This routine is called whenever a serial port is opened. It - * enables interrupts for a serial port, linking in its S structure into - * the IRQ chain. It also performs the serial-specific - * initialization for the tty structure. - */ -int rs_open(struct tty_struct *tty, struct file *filp) -{ - struct m68k_serial *info; - int retval; - - info = &m68k_soft[tty->index]; - - if (serial_paranoia_check(info, tty->name, "rs_open")) - return -ENODEV; - - info->tport.count++; - tty->driver_data = info; - tty_port_tty_set(&info->tport, tty); - - /* - * Start up serial port - */ - retval = startup(info, tty); - if (retval) - return retval; - - return tty_port_block_til_ready(&info->tport, tty, filp); -} - -/* Finally, routines used to initialize the serial driver. */ - -static void show_serial_version(void) -{ - printk("MC68328 serial driver version 1.00\n"); -} - -static const struct tty_operations rs_ops = { - .open = rs_open, - .close = rs_close, - .write = rs_write, - .flush_chars = rs_flush_chars, - .write_room = rs_write_room, - .chars_in_buffer = rs_chars_in_buffer, - .flush_buffer = rs_flush_buffer, - .ioctl = rs_ioctl, - .throttle = rs_throttle, - .unthrottle = rs_unthrottle, - .set_termios = rs_set_termios, - .stop = rs_stop, - .start = rs_start, - .hangup = rs_hangup, - .set_ldisc = rs_set_ldisc, -}; - -static const struct tty_port_operations rs_port_ops = { -}; - -/* rs_init inits the driver */ -static int __init -rs68328_init(void) -{ - unsigned long flags; - int i; - struct m68k_serial *info; - - serial_driver = alloc_tty_driver(NR_PORTS); - if (!serial_driver) - return -ENOMEM; - - show_serial_version(); - - /* Initialize the tty_driver structure */ - /* SPARC: Not all of this is exactly right for us. */ - - serial_driver->name = "ttyS"; - serial_driver->major = TTY_MAJOR; - serial_driver->minor_start = 64; - serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - serial_driver->subtype = SERIAL_TYPE_NORMAL; - serial_driver->init_termios = tty_std_termios; - serial_driver->init_termios.c_cflag = - m68328_console_cbaud | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(serial_driver, &rs_ops); - - local_irq_save(flags); - - for (i = 0; i < NR_PORTS; i++) { - - info = &m68k_soft[i]; - tty_port_init(&info->tport); - info->tport.ops = &rs_port_ops; - info->magic = SERIAL_MAGIC; - info->port = (int) &uart_addr[i]; - info->irq = uart_irqs[i]; - info->custom_divisor = 16; - info->x_char = 0; - info->line = i; - info->is_cons = 1; /* Means shortcuts work */ - - printk("%s%d at 0x%08x (irq = %d)", serial_driver->name, info->line, - info->port, info->irq); - printk(" is a builtin MC68328 UART\n"); - -#ifdef CONFIG_M68VZ328 - if (i > 0) - PJSEL &= 0xCF; /* PSW enable second port output */ -#endif - - if (request_irq(uart_irqs[i], - rs_interrupt, - 0, - "M68328_UART", info)) - panic("Unable to attach 68328 serial interrupt\n"); - - tty_port_link_device(&info->tport, serial_driver, i); - } - local_irq_restore(flags); - - if (tty_register_driver(serial_driver)) { - put_tty_driver(serial_driver); - for (i = 0; i < NR_PORTS; i++) - tty_port_destroy(&m68k_soft[i].tport); - printk(KERN_ERR "Couldn't register serial driver\n"); - return -ENOMEM; - } - - return 0; -} - -module_init(rs68328_init); - - - -static void m68328_set_baud(void) -{ - unsigned short ustcnt; - int i; - - ustcnt = USTCNT; - USTCNT = ustcnt & ~USTCNT_TXEN; - -again: - for (i = 0; i < ARRAY_SIZE(baud_table); i++) - if (baud_table[i] == m68328_console_baud) - break; - if (i >= ARRAY_SIZE(baud_table)) { - m68328_console_baud = 9600; - goto again; - } - - UBAUD = PUT_FIELD(UBAUD_DIVIDE, hw_baud_table[i].divisor) | - PUT_FIELD(UBAUD_PRESCALER, hw_baud_table[i].prescale); - ustcnt &= ~(USTCNT_PARITYEN | USTCNT_ODD_EVEN | USTCNT_STOP | USTCNT_8_7); - ustcnt |= USTCNT_8_7; - ustcnt |= USTCNT_TXEN; - USTCNT = ustcnt; - m68328_console_initted = 1; - return; -} - - -int m68328_console_setup(struct console *cp, char *arg) -{ - int i, n = CONSOLE_BAUD_RATE; - - if (!cp) - return(-1); - - if (arg) - n = simple_strtoul(arg, NULL, 0); - - for (i = 0; i < ARRAY_SIZE(baud_table); i++) - if (baud_table[i] == n) - break; - if (i < ARRAY_SIZE(baud_table)) { - m68328_console_baud = n; - m68328_console_cbaud = 0; - if (i > 15) { - m68328_console_cbaud |= CBAUDEX; - i -= 15; - } - m68328_console_cbaud |= i; - } - - m68328_set_baud(); /* make sure baud rate changes */ - return 0; -} - - -static struct tty_driver *m68328_console_device(struct console *c, int *index) -{ - *index = c->index; - return serial_driver; -} - - -void m68328_console_write (struct console *co, const char *str, - unsigned int count) -{ - if (!m68328_console_initted) - m68328_set_baud(); - while (count--) { - if (*str == '\n') - rs_put_char('\r'); - rs_put_char(*str++); - } -} - - -static struct console m68328_driver = { - .name = "ttyS", - .write = m68328_console_write, - .device = m68328_console_device, - .setup = m68328_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - - -static int __init m68328_console_init(void) -{ - register_console(&m68328_driver); - return 0; -} - -console_initcall(m68328_console_init); diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 39721ec4f415..e5c9250426a8 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -793,17 +793,6 @@ config SERIAL_CORE_CONSOLE config CONSOLE_POLL bool -config SERIAL_68328 - bool "68328 serial support" - depends on M68328 || M68EZ328 || M68VZ328 - help - This driver supports the built-in serial port of the Motorola 68328 - (standard, EZ and VZ varieties). - -config SERIAL_68328_RTS_CTS - bool "Support RTS/CTS on 68328 serial port" - depends on SERIAL_68328 - config SERIAL_MCF bool "Coldfire serial support" depends on COLDFIRE diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index b391c9b31960..ceba33c4ebb4 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -34,7 +34,6 @@ obj-$(CONFIG_SERIAL_MAX3100) += max3100.o obj-$(CONFIG_SERIAL_MAX310X) += max310x.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o obj-$(CONFIG_SERIAL_MUX) += mux.o -obj-$(CONFIG_SERIAL_68328) += 68328serial.o obj-$(CONFIG_SERIAL_MCF) += mcf.o obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o obj-$(CONFIG_SERIAL_HS_LPC32XX) += lpc32xx_hs.o -- cgit v1.2.3 From 0b41ce991052022c030fd868e03877700220b090 Mon Sep 17 00:00:00 2001 From: Sebastian Frias Date: Fri, 18 Dec 2015 17:40:05 +0100 Subject: 8250: use callbacks to access UART_DLL/UART_DLM Some UART HW has a single register combining UART_DLL/UART_DLM (this was probably forgotten in the change that introduced the callbacks, commit b32b19b8ffc05cbd3bf91c65e205f6a912ca15d9) Fixes: b32b19b8ffc0 ("[SERIAL] 8250: set divisor register correctly ...") Signed-off-by: Sebastian Frias Reviewed-by: Peter Hurley Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 01a85a7e7427..c2b650aeb792 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -813,22 +813,16 @@ static int size_fifo(struct uart_8250_port *up) */ static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p) { - unsigned char old_dll, old_dlm, old_lcr; - unsigned int id; + unsigned char old_lcr; + unsigned int id, old_dl; old_lcr = serial_in(p, UART_LCR); serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A); + old_dl = serial_dl_read(p); + serial_dl_write(p, 0); + id = serial_dl_read(p); + serial_dl_write(p, old_dl); - old_dll = serial_in(p, UART_DLL); - old_dlm = serial_in(p, UART_DLM); - - serial_out(p, UART_DLL, 0); - serial_out(p, UART_DLM, 0); - - id = serial_in(p, UART_DLL) | serial_in(p, UART_DLM) << 8; - - serial_out(p, UART_DLL, old_dll); - serial_out(p, UART_DLM, old_dlm); serial_out(p, UART_LCR, old_lcr); return id; -- cgit v1.2.3 From 4b769371fef7e5ad2ec9d7a677bb7001a0c5b213 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 26 Jan 2016 11:26:14 +0100 Subject: serial: atmel: trivial: clean the IP version decoding code No functional change is associated with this patch. A driver property depends on the Atmel serial IP revision. This property is the way the rx timeout is handled: by an hardware or software timer. So, change this property name and setup code so that it's easier to understand and more future proof as the distinction of USART vs. UART is blurrier on newer SoCs. Variable names and debug comments are also adapted to make this code more obvious. Signed-off-by: Nicolas Ferre Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 1c0884d8ef32..a429cfef0286 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -159,8 +159,8 @@ struct atmel_uart_port { u32 rts_high; u32 rts_low; bool ms_irq_enabled; - bool is_usart; /* usart or uart */ - struct timer_list uart_timer; /* uart timer */ + bool has_hw_timer; + struct timer_list uart_timer; bool suspended; unsigned int pending; @@ -1710,19 +1710,19 @@ static void atmel_get_ip_name(struct uart_port *port) struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); int name = atmel_uart_readl(port, ATMEL_US_NAME); u32 version; - int usart, uart; - /* usart and uart ascii */ - usart = 0x55534152; - uart = 0x44424755; + u32 usart, dbgu_uart; + /* ASCII decoding for IP version */ + usart = 0x55534152; /* USAR(T) */ + dbgu_uart = 0x44424755; /* DBGU */ - atmel_port->is_usart = false; + atmel_port->has_hw_timer = false; if (name == usart) { - dev_dbg(port->dev, "This is usart\n"); - atmel_port->is_usart = true; - } else if (name == uart) { - dev_dbg(port->dev, "This is uart\n"); - atmel_port->is_usart = false; + dev_dbg(port->dev, "Usart with hw timer\n"); + atmel_port->has_hw_timer = true; + } else if (name == dbgu_uart) { + dev_dbg(port->dev, "Dbgu or uart without hw timer\n"); + atmel_port->has_hw_timer = false; } else { /* fallback for older SoCs: use version field */ version = atmel_uart_readl(port, ATMEL_US_VERSION); @@ -1730,12 +1730,12 @@ static void atmel_get_ip_name(struct uart_port *port) case 0x302: case 0x10213: dev_dbg(port->dev, "This version is usart\n"); - atmel_port->is_usart = true; + atmel_port->has_hw_timer = true; break; case 0x203: case 0x10202: dev_dbg(port->dev, "This version is uart\n"); - atmel_port->is_usart = false; + atmel_port->has_hw_timer = false; break; default: dev_err(port->dev, "Not supported ip name nor version, set to uart\n"); @@ -1835,7 +1835,7 @@ static int atmel_startup(struct uart_port *port) if (atmel_use_pdc_rx(port)) { /* set UART timeout */ - if (!atmel_port->is_usart) { + if (!atmel_port->has_hw_timer) { mod_timer(&atmel_port->uart_timer, jiffies + uart_poll_timeout(port)); /* set USART timeout */ @@ -1850,7 +1850,7 @@ static int atmel_startup(struct uart_port *port) atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN); } else if (atmel_use_dma_rx(port)) { /* set UART timeout */ - if (!atmel_port->is_usart) { + if (!atmel_port->has_hw_timer) { mod_timer(&atmel_port->uart_timer, jiffies + uart_poll_timeout(port)); /* set USART timeout */ -- cgit v1.2.3 From 1d673fb971d4411e92991ca17ff2b54ce19af3a4 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 26 Jan 2016 11:26:15 +0100 Subject: serial: atmel: add support for new UART version Starting with sama5d2, the new UART revision has an hardware timer. So, add it to the IP detection code and set the "has_hw_timer" property for it. Signed-off-by: Nicolas Ferre Reported-by: David Mosberger Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index a429cfef0286..ede011828727 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -1710,15 +1710,16 @@ static void atmel_get_ip_name(struct uart_port *port) struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); int name = atmel_uart_readl(port, ATMEL_US_NAME); u32 version; - u32 usart, dbgu_uart; + u32 usart, dbgu_uart, new_uart; /* ASCII decoding for IP version */ usart = 0x55534152; /* USAR(T) */ dbgu_uart = 0x44424755; /* DBGU */ + new_uart = 0x55415254; /* UART */ atmel_port->has_hw_timer = false; - if (name == usart) { - dev_dbg(port->dev, "Usart with hw timer\n"); + if (name == usart || name == new_uart) { + dev_dbg(port->dev, "Usart or uart with hw timer\n"); atmel_port->has_hw_timer = true; } else if (name == dbgu_uart) { dev_dbg(port->dev, "Dbgu or uart without hw timer\n"); -- cgit v1.2.3 From b78cd1691404ca26ea7ede3d899b8bd2482da745 Mon Sep 17 00:00:00 2001 From: Jaeden Amero Date: Tue, 26 Jan 2016 12:34:49 +0100 Subject: serial: atmel: Use atmel_port consistently In all functions other than atmel_serial_probe_fifos, atmel_serial_probe, and atmel_console_init, the name "port" is used to refer to an instance of struct uart_port. In many of these functions, "atmel_port" is used to refer to an instance of struct atmel_uart_port. We make the use of the name "port" consistent by making atmel_serial_probe_fifos, atmel_serial_probe, and atmel_console_init use "atmel_port" to refer to an instance of struct atmel_uart_port instead of the previous name of "port". Signed-off-by: Jaeden Amero Signed-off-by: Kyle Roeschley Acked-by: Karthik Manamcheri [nicolas.ferre@atmel.com: fix typo in variable, adapt to newer kernel] Signed-off-by: Nicolas Ferre Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 95 ++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index ede011828727..b30c93f80899 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -2479,13 +2479,13 @@ static int __init atmel_console_init(void) struct atmel_uart_data *pdata = dev_get_platdata(&atmel_default_console_device->dev); int id = pdata->num; - struct atmel_uart_port *port = &atmel_ports[id]; + struct atmel_uart_port *atmel_port = &atmel_ports[id]; - port->backup_imr = 0; - port->uart.line = id; + atmel_port->backup_imr = 0; + atmel_port->uart.line = id; add_preferred_console(ATMEL_DEVICENAME, id, NULL); - ret = atmel_init_port(port, atmel_default_console_device); + ret = atmel_init_port(atmel_port, atmel_default_console_device); if (ret) return ret; register_console(&atmel_console); @@ -2600,23 +2600,23 @@ static int atmel_serial_resume(struct platform_device *pdev) #define atmel_serial_resume NULL #endif -static void atmel_serial_probe_fifos(struct atmel_uart_port *port, +static void atmel_serial_probe_fifos(struct atmel_uart_port *atmel_port, struct platform_device *pdev) { - port->fifo_size = 0; - port->rts_low = 0; - port->rts_high = 0; + atmel_port->fifo_size = 0; + atmel_port->rts_low = 0; + atmel_port->rts_high = 0; if (of_property_read_u32(pdev->dev.of_node, "atmel,fifo-size", - &port->fifo_size)) + &atmel_port->fifo_size)) return; - if (!port->fifo_size) + if (!atmel_port->fifo_size) return; - if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) { - port->fifo_size = 0; + if (atmel_port->fifo_size < ATMEL_MIN_FIFO_SIZE) { + atmel_port->fifo_size = 0; dev_err(&pdev->dev, "Invalid FIFO size\n"); return; } @@ -2629,22 +2629,22 @@ static void atmel_serial_probe_fifos(struct atmel_uart_port *port, * Threshold to a reasonably high value respecting this 16 data * empirical rule when possible. */ - port->rts_high = max_t(int, port->fifo_size >> 1, - port->fifo_size - ATMEL_RTS_HIGH_OFFSET); - port->rts_low = max_t(int, port->fifo_size >> 2, - port->fifo_size - ATMEL_RTS_LOW_OFFSET); + atmel_port->rts_high = max_t(int, atmel_port->fifo_size >> 1, + atmel_port->fifo_size - ATMEL_RTS_HIGH_OFFSET); + atmel_port->rts_low = max_t(int, atmel_port->fifo_size >> 2, + atmel_port->fifo_size - ATMEL_RTS_LOW_OFFSET); dev_info(&pdev->dev, "Using FIFO (%u data)\n", - port->fifo_size); + atmel_port->fifo_size); dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n", - port->rts_high); + atmel_port->rts_high); dev_dbg(&pdev->dev, "RTS Low Threshold : %2u data\n", - port->rts_low); + atmel_port->rts_low); } static int atmel_serial_probe(struct platform_device *pdev) { - struct atmel_uart_port *port; + struct atmel_uart_port *atmel_port; struct device_node *np = pdev->dev.of_node; struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev); void *data; @@ -2675,87 +2675,88 @@ static int atmel_serial_probe(struct platform_device *pdev) goto err; } - port = &atmel_ports[ret]; - port->backup_imr = 0; - port->uart.line = ret; - atmel_serial_probe_fifos(port, pdev); + atmel_port = &atmel_ports[ret]; + atmel_port->backup_imr = 0; + atmel_port->uart.line = ret; + atmel_serial_probe_fifos(atmel_port, pdev); - spin_lock_init(&port->lock_suspended); + spin_lock_init(&atmel_port->lock_suspended); - ret = atmel_init_port(port, pdev); + ret = atmel_init_port(atmel_port, pdev); if (ret) goto err_clear_bit; - port->gpios = mctrl_gpio_init(&port->uart, 0); - if (IS_ERR(port->gpios)) { - ret = PTR_ERR(port->gpios); + atmel_port->gpios = mctrl_gpio_init(&atmel_port->uart, 0); + if (IS_ERR(atmel_port->gpios)) { + ret = PTR_ERR(atmel_port->gpios); goto err_clear_bit; } - if (!atmel_use_pdc_rx(&port->uart)) { + if (!atmel_use_pdc_rx(&atmel_port->uart)) { ret = -ENOMEM; data = kmalloc(sizeof(struct atmel_uart_char) * ATMEL_SERIAL_RINGSIZE, GFP_KERNEL); if (!data) goto err_alloc_ring; - port->rx_ring.buf = data; + atmel_port->rx_ring.buf = data; } - rs485_enabled = port->uart.rs485.flags & SER_RS485_ENABLED; + rs485_enabled = atmel_port->uart.rs485.flags & SER_RS485_ENABLED; - ret = uart_add_one_port(&atmel_uart, &port->uart); + ret = uart_add_one_port(&atmel_uart, &atmel_port->uart); if (ret) goto err_add_port; #ifdef CONFIG_SERIAL_ATMEL_CONSOLE - if (atmel_is_console_port(&port->uart) + if (atmel_is_console_port(&atmel_port->uart) && ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) { /* * The serial core enabled the clock for us, so undo * the clk_prepare_enable() in atmel_console_setup() */ - clk_disable_unprepare(port->clk); + clk_disable_unprepare(atmel_port->clk); } #endif device_init_wakeup(&pdev->dev, 1); - platform_set_drvdata(pdev, port); + platform_set_drvdata(pdev, atmel_port); /* * The peripheral clock has been disabled by atmel_init_port(): * enable it before accessing I/O registers */ - clk_prepare_enable(port->clk); + clk_prepare_enable(atmel_port->clk); if (rs485_enabled) { - atmel_uart_writel(&port->uart, ATMEL_US_MR, + atmel_uart_writel(&atmel_port->uart, ATMEL_US_MR, ATMEL_US_USMODE_NORMAL); - atmel_uart_writel(&port->uart, ATMEL_US_CR, ATMEL_US_RTSEN); + atmel_uart_writel(&atmel_port->uart, ATMEL_US_CR, + ATMEL_US_RTSEN); } /* * Get port name of usart or uart */ - atmel_get_ip_name(&port->uart); + atmel_get_ip_name(&atmel_port->uart); /* * The peripheral clock can now safely be disabled till the port * is used */ - clk_disable_unprepare(port->clk); + clk_disable_unprepare(atmel_port->clk); return 0; err_add_port: - kfree(port->rx_ring.buf); - port->rx_ring.buf = NULL; + kfree(atmel_port->rx_ring.buf); + atmel_port->rx_ring.buf = NULL; err_alloc_ring: - if (!atmel_is_console_port(&port->uart)) { - clk_put(port->clk); - port->clk = NULL; + if (!atmel_is_console_port(&atmel_port->uart)) { + clk_put(atmel_port->clk); + atmel_port->clk = NULL; } err_clear_bit: - clear_bit(port->uart.line, atmel_ports_in_use); + clear_bit(atmel_port->uart.line, atmel_ports_in_use); err: return ret; } -- cgit v1.2.3 From b7ed5161f17a39ed09fd799a919b5f6de688251d Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Sun, 20 Dec 2015 12:55:23 +0800 Subject: sc16is7xx: fix incorrect register bits macro In datasheet, Modem Status Register MSR[4-7] reflect the modem pins CTS/DSR/RI/CD signal state. Signed-off-by: Wills Wang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sc16is7xx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 13f8d5f70272..311e7bc07a24 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -196,14 +196,14 @@ * or (IO6) * - only on 75x/76x */ -#define SC16IS7XX_MSR_CTS_BIT (1 << 0) /* CTS */ -#define SC16IS7XX_MSR_DSR_BIT (1 << 1) /* DSR (IO4) +#define SC16IS7XX_MSR_CTS_BIT (1 << 4) /* CTS */ +#define SC16IS7XX_MSR_DSR_BIT (1 << 5) /* DSR (IO4) * - only on 75x/76x */ -#define SC16IS7XX_MSR_RI_BIT (1 << 2) /* RI (IO7) +#define SC16IS7XX_MSR_RI_BIT (1 << 6) /* RI (IO7) * - only on 75x/76x */ -#define SC16IS7XX_MSR_CD_BIT (1 << 3) /* CD (IO6) +#define SC16IS7XX_MSR_CD_BIT (1 << 7) /* CD (IO6) * - only on 75x/76x */ #define SC16IS7XX_MSR_DELTA_MASK 0x0F /* Any of the delta bits! */ @@ -240,7 +240,7 @@ /* IOControl register bits (Only 750/760) */ #define SC16IS7XX_IOCONTROL_LATCH_BIT (1 << 0) /* Enable input latching */ -#define SC16IS7XX_IOCONTROL_GPIO_BIT (1 << 1) /* Enable GPIO[7:4] */ +#define SC16IS7XX_IOCONTROL_MODEM_BIT (1 << 1) /* Enable GPIO[7:4] as modem pins */ #define SC16IS7XX_IOCONTROL_SRESET_BIT (1 << 3) /* Software Reset */ /* EFCR register bits */ @@ -687,7 +687,7 @@ static void sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno) case SC16IS7XX_IIR_CTSRTS_SRC: msr = sc16is7xx_port_read(port, SC16IS7XX_MSR_REG); uart_handle_cts_change(port, - !!(msr & SC16IS7XX_MSR_CTS_BIT)); + !!(msr & SC16IS7XX_MSR_DCTS_BIT)); break; case SC16IS7XX_IIR_THRI_SRC: sc16is7xx_handle_tx(port); -- cgit v1.2.3 From 2f2fd0894991a04bf3581104d5ea3a8dc9a4f01f Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Fri, 15 Jan 2016 14:32:20 -0600 Subject: serial: amba-pl011: use cpu_relax when polling registers Busy loops that poll on a register should call cpu_relax(). On some architectures, it can lower CPU power consumption or yield to a hyperthreaded twin processor. It also serves as a compiler barrier, so it can replace barrier() calls. Signed-off-by: Timur Tabi Reviewed-by: Dave Martin Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index de846027ba47..618763b2539a 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1167,7 +1167,7 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap) /* Disable RX and TX DMA */ while (pl011_read(uap, REG_FR) & UART01x_FR_BUSY) - barrier(); + cpu_relax(); spin_lock_irq(&uap->port.lock); uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE); @@ -1611,7 +1611,7 @@ static void pl011_put_poll_char(struct uart_port *port, container_of(port, struct uart_amba_port, port); while (pl011_read(uap, REG_FR) & UART01x_FR_TXFF) - barrier(); + cpu_relax(); pl011_write(ch, uap, REG_DR); } @@ -2150,7 +2150,7 @@ static void pl011_console_putchar(struct uart_port *port, int ch) container_of(port, struct uart_amba_port, port); while (pl011_read(uap, REG_FR) & UART01x_FR_TXFF) - barrier(); + cpu_relax(); pl011_write(ch, uap, REG_DR); } @@ -2158,7 +2158,7 @@ static void pl011_console_write(struct console *co, const char *s, unsigned int count) { struct uart_amba_port *uap = amba_ports[co->index]; - unsigned int status, old_cr = 0, new_cr; + unsigned int old_cr = 0, new_cr; unsigned long flags; int locked = 1; @@ -2188,9 +2188,8 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) * Finally, wait for transmitter to become empty * and restore the TCR */ - do { - status = pl011_read(uap, REG_FR); - } while (status & UART01x_FR_BUSY); + while (pl011_read(uap, REG_FR) & UART01x_FR_BUSY) + cpu_relax(); if (!uap->vendor->always_enabled) pl011_write(old_cr, uap, REG_CR); @@ -2302,13 +2301,13 @@ static struct console amba_console = { static void pl011_putc(struct uart_port *port, int c) { while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF) - ; + cpu_relax(); if (port->iotype == UPIO_MEM32) writel(c, port->membase + UART01x_DR); else writeb(c, port->membase + UART01x_DR); while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY) - ; + cpu_relax(); } static void pl011_early_write(struct console *con, const char *s, unsigned n) -- cgit v1.2.3 From ff52a9a0c3c64ae33fe65b94733df3a1a6ce1a70 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 20 Jan 2016 11:40:03 +0100 Subject: serial: amba-pl011: mark vendor_zte as __maybe_unused The pl011 driver has gone back and forth on the definition of the ZTE specific variation of the hardware definitions, but the current state is that the vendor definition is left in place yet unused: drivers/tty/serial/amba-pl011.c:190:27: warning: 'vendor_zte' defined but not used [-Wunused-variable] I don't know what the plan forward is to get this code to work, but the current behavior is a bit annoying as we get a warning whenever we build this driver. This patch does not help us to make it work, but at least shuts up the warning. Signed-off-by: Arnd Bergmann Fixes: 7ec758718920 ("tty: amba-pl011: add support for ZTE UART (EXPERIMENTAL)") Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 618763b2539a..500232ad38f3 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -187,7 +187,7 @@ static const u16 pl011_zte_offsets[REG_ARRAY_SIZE] = { [REG_DMACR] = ZX_UART011_DMACR, }; -static struct vendor_data vendor_zte = { +static struct vendor_data vendor_zte __maybe_unused = { .reg_offset = pl011_zte_offsets, .access_32b = true, .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, -- cgit v1.2.3 From 30c6c352ce4796f8c9815452db84c78805bbbe10 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sun, 27 Dec 2015 22:29:42 +0800 Subject: serial: 8250_pci: use to_pci_dev() Use to_pci_dev() instead of open-coding it. Signed-off-by: Geliang Tang Reviewed-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index e71ec78fc11e..90025e4f3452 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1541,10 +1541,9 @@ pci_brcm_trumanage_setup(struct serial_private *priv, static int pci_fintek_rs485_config(struct uart_port *port, struct serial_rs485 *rs485) { + struct pci_dev *pci_dev = to_pci_dev(port->dev); u8 setting; u8 *index = (u8 *) port->private_data; - struct pci_dev *pci_dev = container_of(port->dev, struct pci_dev, - dev); pci_read_config_byte(pci_dev, 0x40 + 8 * *index + 7, &setting); -- cgit v1.2.3 From 8178a89eb89e025868992aff32ab78503ec5fa1e Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 22 Dec 2015 08:57:06 -0700 Subject: serial/8250_pci: simplify Pericom handling Considering that pci_pericom_setup(()'s only difference to pci_default_setup() is the setting of the uartclk field, and taking into account that this field already gets taken care of by having the base_baud field filled in the pci_boards[] entries, there's no need for both the function and the quirks table entry. Signed-off-by: Jan Beulich Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 33 --------------------------------- 1 file changed, 33 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 90025e4f3452..da501c1390db 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1334,29 +1334,6 @@ static int pci_default_setup(struct serial_private *priv, return setup_port(priv, port, bar, offset, board->reg_shift); } -static int pci_pericom_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) -{ - unsigned int bar, offset = board->first_offset, maxnr; - - bar = FL_GET_BASE(board->flags); - if (board->flags & FL_BASE_BARS) - bar += idx; - else - offset += idx * board->uart_offset; - - maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >> - (board->reg_shift + 3); - - if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr) - return 1; - - port->port.uartclk = 14745600; - - return setup_port(priv, port, bar, offset, board->reg_shift); -} - static int ce4100_serial_setup(struct serial_private *priv, const struct pciserial_board *board, @@ -2243,16 +2220,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .setup = pci_default_setup, .exit = pci_plx9050_exit, }, - /* - * Pericom - */ - { - .vendor = PCI_VENDOR_ID_PERICOM, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, - }, /* * PLX */ -- cgit v1.2.3 From 0b0cced19ab15c9ebbfbc6c4c0d932863e18fbe5 Mon Sep 17 00:00:00 2001 From: Yoshinori Sato Date: Thu, 24 Dec 2015 11:24:48 +0100 Subject: serial: sh-sci: Add CONFIG_SERIAL_EARLYCON support "earlyprintk" is architecture specific option. General "earlycon" option support is much better. Signed-off-by: Yoshinori Sato [uli: preserve other SCSCR bits when asserting RE and TE] Signed-off-by: Ulrich Hecht [geert: rewording, #ifdef rework] Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 6 ++++ drivers/tty/serial/sh-sci.c | 77 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 78 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index e5c9250426a8..54b6f2c15f72 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -745,6 +745,12 @@ config SERIAL_SH_SCI_CONSOLE depends on SERIAL_SH_SCI=y select SERIAL_CORE_CONSOLE +config SERIAL_SH_SCI_EARLYCON + bool "Support for early console on SuperH SCI(F)" + depends on SERIAL_SH_SCI=y + select SERIAL_CORE_CONSOLE + select SERIAL_EARLYCON + config SERIAL_SH_SCI_DMA bool "DMA support" depends on SERIAL_SH_SCI && DMA_ENGINE diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 4646a9f531ad..ec08f1bff753 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -637,7 +637,8 @@ static void sci_clear_SCxSR(struct uart_port *port, unsigned int mask) } } -#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE) +#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE) || \ + defined(CONFIG_SERIAL_SH_SCI_EARLYCON) #ifdef CONFIG_CONSOLE_POLL static int sci_poll_get_char(struct uart_port *port) @@ -678,7 +679,8 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c) serial_port_out(port, SCxTDR, c); sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port)); } -#endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */ +#endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE || + CONFIG_SERIAL_SH_SCI_EARLYCON */ static void sci_init_pins(struct uart_port *port, unsigned int cflag) { @@ -2632,7 +2634,8 @@ static void sci_cleanup_single(struct sci_port *port) pm_runtime_disable(port->port.dev); } -#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE +#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) || \ + defined(CONFIG_SERIAL_SH_SCI_EARLYCON) static void serial_console_putchar(struct uart_port *port, int ch) { sci_poll_put_char(port, ch); @@ -2652,9 +2655,12 @@ static void serial_console_write(struct console *co, const char *s, int locked = 1; local_irq_save(flags); +#if defined(SUPPORT_SYSRQ) if (port->sysrq) locked = 0; - else if (oops_in_progress) + else +#endif + if (oops_in_progress) locked = spin_trylock(&port->lock); else spin_lock(&port->lock); @@ -2764,7 +2770,7 @@ static inline int sci_probe_earlyprintk(struct platform_device *pdev) #define SCI_CONSOLE NULL -#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ +#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE || CONFIG_SERIAL_SH_SCI_EARLYCON */ static const char banner[] __initconst = "SuperH (H)SCI(F) driver initialized"; @@ -2998,6 +3004,67 @@ static void __exit sci_exit(void) early_platform_init_buffer("earlyprintk", &sci_driver, early_serial_buf, ARRAY_SIZE(early_serial_buf)); #endif +#ifdef CONFIG_SERIAL_SH_SCI_EARLYCON +static struct __init plat_sci_port port_cfg; + +static int __init early_console_setup(struct earlycon_device *device, + int type) +{ + if (!device->port.membase) + return -ENODEV; + + device->port.serial_in = sci_serial_in; + device->port.serial_out = sci_serial_out; + device->port.type = type; + memcpy(&sci_ports[0].port, &device->port, sizeof(struct uart_port)); + sci_ports[0].cfg = &port_cfg; + sci_ports[0].cfg->type = type; + sci_probe_regmap(sci_ports[0].cfg); + port_cfg.scscr = sci_serial_in(&sci_ports[0].port, SCSCR) | + SCSCR_RE | SCSCR_TE; + sci_serial_out(&sci_ports[0].port, SCSCR, port_cfg.scscr); + + device->con->write = serial_console_write; + return 0; +} +static int __init sci_early_console_setup(struct earlycon_device *device, + const char *opt) +{ + return early_console_setup(device, PORT_SCI); +} +static int __init scif_early_console_setup(struct earlycon_device *device, + const char *opt) +{ + return early_console_setup(device, PORT_SCIF); +} +static int __init scifa_early_console_setup(struct earlycon_device *device, + const char *opt) +{ + return early_console_setup(device, PORT_SCIFA); +} +static int __init scifb_early_console_setup(struct earlycon_device *device, + const char *opt) +{ + return early_console_setup(device, PORT_SCIFB); +} +static int __init hscif_early_console_setup(struct earlycon_device *device, + const char *opt) +{ + return early_console_setup(device, PORT_HSCIF); +} + +EARLYCON_DECLARE(sci, sci_early_console_setup); +OF_EARLYCON_DECLARE(sci, "renesas,sci", sci_early_console_setup); +EARLYCON_DECLARE(scif, scif_early_console_setup); +OF_EARLYCON_DECLARE(scif, "renesas,scif", scif_early_console_setup); +EARLYCON_DECLARE(scifa, scifa_early_console_setup); +OF_EARLYCON_DECLARE(scifa, "renesas,scifa", scifa_early_console_setup); +EARLYCON_DECLARE(scifb, scifb_early_console_setup); +OF_EARLYCON_DECLARE(scifb, "renesas,scifb", scifb_early_console_setup); +EARLYCON_DECLARE(hscif, hscif_early_console_setup); +OF_EARLYCON_DECLARE(hscif, "renesas,hscif", hscif_early_console_setup); +#endif /* CONFIG_SERIAL_SH_SCI_EARLYCON */ + module_init(sci_init); module_exit(sci_exit); -- cgit v1.2.3 From e3538c37ee383228cb9f89fb9312c417f5eb3bfc Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 26 Dec 2015 02:43:49 -0800 Subject: tty: xuartps: Beautify read-modify writes Non-functional, formatting changes to ease reading the code. Signed-off-by: Soren Brinkmann Reviewed-by: Peter Hurley Reviewed-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 009e0dbc12d2..50d4082d2354 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -515,12 +515,14 @@ static void cdns_uart_start_tx(struct uart_port *port) if (uart_circ_empty(&port->state->xmit) || uart_tx_stopped(port)) return; - status = readl(port->membase + CDNS_UART_CR_OFFSET); - /* Set the TX enable bit and clear the TX disable bit to enable the + /* + * Set the TX enable bit and clear the TX disable bit to enable the * transmitter. */ - writel((status & ~CDNS_UART_CR_TX_DIS) | CDNS_UART_CR_TX_EN, - port->membase + CDNS_UART_CR_OFFSET); + status = readl(port->membase + CDNS_UART_CR_OFFSET); + status &= ~CDNS_UART_CR_TX_DIS; + status |= CDNS_UART_CR_TX_EN; + writel(status, port->membase + CDNS_UART_CR_OFFSET); while (numbytes-- && ((readl(port->membase + CDNS_UART_SR_OFFSET) & CDNS_UART_SR_TXFULL)) != CDNS_UART_SR_TXFULL) { @@ -1123,8 +1125,9 @@ static void cdns_uart_console_write(struct console *co, const char *s, * clear the TX disable bit to enable the transmitter. */ ctrl = readl(port->membase + CDNS_UART_CR_OFFSET); - writel((ctrl & ~CDNS_UART_CR_TX_DIS) | CDNS_UART_CR_TX_EN, - port->membase + CDNS_UART_CR_OFFSET); + ctrl &= ~CDNS_UART_CR_TX_DIS; + ctrl |= CDNS_UART_CR_TX_EN; + writel(ctrl, port->membase + CDNS_UART_CR_OFFSET); uart_console_write(port, s, count, cdns_uart_console_putchar); cdns_uart_console_wait_tx(port); -- cgit v1.2.3 From f0f54a806b2df97485519a7c4ebc45feed08a306 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 26 Dec 2015 02:43:50 -0800 Subject: tty: xuartps: Use spinlock to serialize HW access Instead of disabling the IRQ, use the spin lock to serialize accesses to the HW. This protects the driver from interference of non-IRQ callbacks with each other and makes the driver more consistent in its serialization method. Signed-off-by: Soren Brinkmann Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 50d4082d2354..2c98c357d9a0 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -945,12 +945,10 @@ static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) #ifdef CONFIG_CONSOLE_POLL static int cdns_uart_poll_get_char(struct uart_port *port) { - u32 imr; int c; + unsigned long flags; - /* Disable all interrupts */ - imr = readl(port->membase + CDNS_UART_IMR_OFFSET); - writel(imr, port->membase + CDNS_UART_IDR_OFFSET); + spin_lock_irqsave(&port->lock, flags); /* Check if FIFO is empty */ if (readl(port->membase + CDNS_UART_SR_OFFSET) & CDNS_UART_SR_RXEMPTY) @@ -959,19 +957,16 @@ static int cdns_uart_poll_get_char(struct uart_port *port) c = (unsigned char) readl( port->membase + CDNS_UART_FIFO_OFFSET); - /* Enable interrupts */ - writel(imr, port->membase + CDNS_UART_IER_OFFSET); + spin_unlock_irqrestore(&port->lock, flags); return c; } static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c) { - u32 imr; + unsigned long flags; - /* Disable all interrupts */ - imr = readl(port->membase + CDNS_UART_IMR_OFFSET); - writel(imr, port->membase + CDNS_UART_IDR_OFFSET); + spin_lock_irqsave(&port->lock, flags); /* Wait until FIFO is empty */ while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & @@ -986,8 +981,7 @@ static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c) CDNS_UART_SR_TXEMPTY)) cpu_relax(); - /* Enable interrupts */ - writel(imr, port->membase + CDNS_UART_IER_OFFSET); + spin_unlock_irqrestore(&port->lock, flags); return; } -- cgit v1.2.3 From ea8dd8e585761c2811d0566938983868d89976a8 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 26 Dec 2015 02:43:51 -0800 Subject: tty: xuartps: Don't consider circular buffer when enabling transmitter Restarting the transmitter even if the circ buffer is empty may be necessary to push out remaining data when the port is restarted after being stopped. Cc: Peter Hurley Signed-off-by: Soren Brinkmann Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 2c98c357d9a0..6a7cd4e057ae 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -512,7 +512,7 @@ static void cdns_uart_start_tx(struct uart_port *port) { unsigned int status, numbytes = port->fifosize; - if (uart_circ_empty(&port->state->xmit) || uart_tx_stopped(port)) + if (uart_tx_stopped(port)) return; /* @@ -524,6 +524,9 @@ static void cdns_uart_start_tx(struct uart_port *port) status |= CDNS_UART_CR_TX_EN; writel(status, port->membase + CDNS_UART_CR_OFFSET); + if (uart_circ_empty(&port->state->xmit)) + return; + while (numbytes-- && ((readl(port->membase + CDNS_UART_SR_OFFSET) & CDNS_UART_SR_TXFULL)) != CDNS_UART_SR_TXFULL) { /* Break if no more data available in the UART buffer */ -- cgit v1.2.3 From aea8f3ddcf5de21188b737345fc2f62526350874 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 26 Dec 2015 02:43:52 -0800 Subject: tty: xuartps: Clear interrupt status register in shutdown When shutting down the UART, clear the interrupt status register. Bits in the ISR are cleared by writing them as '1'. Signed-off-by: Soren Brinkmann Reviewed-by: Peter Hurley Reviewed-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 6a7cd4e057ae..ef114d7a0623 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -828,6 +828,7 @@ static void cdns_uart_shutdown(struct uart_port *port) /* Disable interrupts */ status = readl(port->membase + CDNS_UART_IMR_OFFSET); writel(status, port->membase + CDNS_UART_IDR_OFFSET); + writel(0xffffffff, port->membase + CDNS_UART_ISR_OFFSET); /* Disable the TX and RX */ writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS, -- cgit v1.2.3 From 6e14f7c1f2c2e8d783b4bc50e7ac31b468910698 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 26 Dec 2015 02:43:53 -0800 Subject: tty: xuartps: Improve startup function The startup function is supposed to initialize the UART for receiving. Hence, don't enable the TX part. Also, protect HW accesses with the port lock. Signed-off-by: Soren Brinkmann Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index ef114d7a0623..6ffd3bbe3e18 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -758,6 +758,7 @@ static void cdns_uart_set_termios(struct uart_port *port, */ static int cdns_uart_startup(struct uart_port *port) { + unsigned long flags; unsigned int retval = 0, status = 0; retval = request_irq(port->irq, cdns_uart_isr, 0, CDNS_UART_NAME, @@ -765,6 +766,8 @@ static int cdns_uart_startup(struct uart_port *port) if (retval) return retval; + spin_lock_irqsave(&port->lock, flags); + /* Disable the TX and RX */ writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS, port->membase + CDNS_UART_CR_OFFSET); @@ -775,15 +778,14 @@ static int cdns_uart_startup(struct uart_port *port) writel(CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST, port->membase + CDNS_UART_CR_OFFSET); - status = readl(port->membase + CDNS_UART_CR_OFFSET); - - /* Clear the RX disable and TX disable bits and then set the TX enable - * bit and RX enable bit to enable the transmitter and receiver. + /* + * Clear the RX disable bit and then set the RX enable bit to enable + * the receiver. */ - writel((status & ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS)) - | (CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN | - CDNS_UART_CR_STOPBRK), - port->membase + CDNS_UART_CR_OFFSET); + status = readl(port->membase + CDNS_UART_CR_OFFSET); + status &= CDNS_UART_CR_RX_DIS; + status |= CDNS_UART_CR_RX_EN; + writel(status, port->membase + CDNS_UART_CR_OFFSET); /* Set the Mode Register with normal mode,8 data bits,1 stop bit, * no parity. @@ -814,6 +816,8 @@ static int cdns_uart_startup(struct uart_port *port) CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_TOUT, port->membase + CDNS_UART_IER_OFFSET); + spin_unlock_irqrestore(&port->lock, flags); + return retval; } -- cgit v1.2.3 From 4c0b92ed9ebab389cdefd56efe81f8c3d8d458d5 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 26 Dec 2015 02:43:54 -0800 Subject: tty: xuartps: Keep lock for whole ISR The RX path in the interrupt handler released a lock unnecessarily. Signed-off-by: Soren Brinkmann Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 6ffd3bbe3e18..ab3995d00973 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -265,9 +265,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) uart_insert_char(port, isrstatus, CDNS_UART_IXR_OVERRUN, data, status); } - spin_unlock(&port->lock); tty_flip_buffer_push(&port->state->port); - spin_lock(&port->lock); } /* Dispatch an appropriate handler */ -- cgit v1.2.3 From a19eda0f49e5b19c403c5fe33e1e2f46e7b02082 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 26 Dec 2015 02:43:55 -0800 Subject: tty: xuartps: Acquire port lock for shutdown Shutting down the UART port can happen while console operations are in progress. Holding the port lock serializes these operations and avoids the UART HW to be disabled in the middle of console prints. Signed-off-by: Soren Brinkmann Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index ab3995d00973..f3ac69387b0a 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -826,6 +826,9 @@ static int cdns_uart_startup(struct uart_port *port) static void cdns_uart_shutdown(struct uart_port *port) { int status; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); /* Disable interrupts */ status = readl(port->membase + CDNS_UART_IMR_OFFSET); @@ -835,6 +838,9 @@ static void cdns_uart_shutdown(struct uart_port *port) /* Disable the TX and RX */ writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS, port->membase + CDNS_UART_CR_OFFSET); + + spin_unlock_irqrestore(&port->lock, flags); + free_irq(port->irq, port); } -- cgit v1.2.3 From 5ede4a5cde278af46aacecca25470943b8c5a086 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 26 Dec 2015 02:43:56 -0800 Subject: tty: xuartps: Move RX path into helper function Move RX-related IRQ handling into a helper function. Fixes a problem where every char received after a parity or frame error in the current isr will also be tagged as a parity or frame error. Signed-off-by: Soren Brinkmann Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 50 +++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index f3ac69387b0a..db9e23eaf300 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -172,28 +172,8 @@ struct cdns_uart { #define to_cdns_uart(_nb) container_of(_nb, struct cdns_uart, \ clk_rate_change_nb); -/** - * cdns_uart_isr - Interrupt handler - * @irq: Irq number - * @dev_id: Id of the port - * - * Return: IRQHANDLED - */ -static irqreturn_t cdns_uart_isr(int irq, void *dev_id) +static void cdns_uart_handle_rx(struct uart_port *port, unsigned int isrstatus) { - struct uart_port *port = (struct uart_port *)dev_id; - unsigned long flags; - unsigned int isrstatus, numbytes; - unsigned int data; - char status = TTY_NORMAL; - - spin_lock_irqsave(&port->lock, flags); - - /* Read the interrupt status register to determine which - * interrupt(s) is/are active. - */ - isrstatus = readl(port->membase + CDNS_UART_ISR_OFFSET); - /* * There is no hardware break detection, so we interpret framing * error with all-zeros data as a break sequence. Most of the time, @@ -223,6 +203,9 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) /* Receive Timeout Interrupt */ while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & CDNS_UART_SR_RXEMPTY)) { + u32 data; + char status = TTY_NORMAL; + data = readl(port->membase + CDNS_UART_FIFO_OFFSET); /* Non-NULL byte after BREAK is garbage (99%) */ @@ -263,10 +246,33 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) } uart_insert_char(port, isrstatus, CDNS_UART_IXR_OVERRUN, - data, status); + data, status); } tty_flip_buffer_push(&port->state->port); } +} + +/** + * cdns_uart_isr - Interrupt handler + * @irq: Irq number + * @dev_id: Id of the port + * + * Return: IRQHANDLED + */ +static irqreturn_t cdns_uart_isr(int irq, void *dev_id) +{ + struct uart_port *port = (struct uart_port *)dev_id; + unsigned long flags; + unsigned int isrstatus, numbytes; + + spin_lock_irqsave(&port->lock, flags); + + /* Read the interrupt status register to determine which + * interrupt(s) is/are active. + */ + isrstatus = readl(port->membase + CDNS_UART_ISR_OFFSET); + + cdns_uart_handle_rx(port, isrstatus); /* Dispatch an appropriate handler */ if ((isrstatus & CDNS_UART_IXR_TXEMPTY) == CDNS_UART_IXR_TXEMPTY) { -- cgit v1.2.3 From 55861d11c5c804f053411b6e5505d19f561e46a3 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 11 Jan 2016 17:41:36 -0800 Subject: tty: xuartps: Move request_irq to after setting up the HW Request_irq() should be _after_ h/w programming, otherwise an interrupt could be triggered and in-progress before the h/w has been setup. Reported-by: Peter Hurley Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index db9e23eaf300..5da1c51e9e40 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -762,13 +762,9 @@ static void cdns_uart_set_termios(struct uart_port *port, */ static int cdns_uart_startup(struct uart_port *port) { + int ret; unsigned long flags; - unsigned int retval = 0, status = 0; - - retval = request_irq(port->irq, cdns_uart_isr, 0, CDNS_UART_NAME, - (void *)port); - if (retval) - return retval; + unsigned int status = 0; spin_lock_irqsave(&port->lock, flags); @@ -814,15 +810,22 @@ static int cdns_uart_startup(struct uart_port *port) writel(readl(port->membase + CDNS_UART_ISR_OFFSET), port->membase + CDNS_UART_ISR_OFFSET); + spin_unlock_irqrestore(&port->lock, flags); + + ret = request_irq(port->irq, cdns_uart_isr, 0, CDNS_UART_NAME, port); + if (ret) { + dev_err(port->dev, "request_irq '%d' failed with %d\n", + port->irq, ret); + return ret; + } + /* Set the Interrupt Registers with desired interrupts */ writel(CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_PARITY | CDNS_UART_IXR_FRAMING | CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_TOUT, port->membase + CDNS_UART_IER_OFFSET); - spin_unlock_irqrestore(&port->lock, flags); - - return retval; + return 0; } /** -- cgit v1.2.3 From 373e882f9ecfb383fcd3d8878b2eb20e17d45792 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 11 Jan 2016 17:41:37 -0800 Subject: tty: xuartps: Refactor IRQ handling The system could deadlock handling RX IRQs when RX-related IRQ conditions became true while the receiver was disabled. To avoid this, enable/disable the RX/TX IRQs together with the receiver/transmitter. Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 5da1c51e9e40..a0039cbcf812 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -126,6 +126,10 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); #define CDNS_UART_IXR_RXEMPTY 0x00000002 /* RX FIFO empty interrupt. */ #define CDNS_UART_IXR_MASK 0x00001FFF /* Valid bit mask */ +#define CDNS_UART_RX_IRQS (CDNS_UART_IXR_PARITY | CDNS_UART_IXR_FRAMING | \ + CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_RXTRIG | \ + CDNS_UART_IXR_TOUT) + /* Goes in read_status_mask for break detection as the HW doesn't do it*/ #define CDNS_UART_IXR_BRK 0x80000000 @@ -272,7 +276,8 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) */ isrstatus = readl(port->membase + CDNS_UART_ISR_OFFSET); - cdns_uart_handle_rx(port, isrstatus); + if (isrstatus & CDNS_UART_RX_IRQS) + cdns_uart_handle_rx(port, isrstatus); /* Dispatch an appropriate handler */ if ((isrstatus & CDNS_UART_IXR_TXEMPTY) == CDNS_UART_IXR_TXEMPTY) { @@ -580,9 +585,12 @@ static void cdns_uart_stop_rx(struct uart_port *port) { unsigned int regval; + /* Disable RX IRQs */ + writel(CDNS_UART_RX_IRQS, port->membase + CDNS_UART_IDR_OFFSET); + + /* Disable the receiver */ regval = readl(port->membase + CDNS_UART_CR_OFFSET); regval |= CDNS_UART_CR_RX_DIS; - /* Disable the receiver */ writel(regval, port->membase + CDNS_UART_CR_OFFSET); } @@ -820,10 +828,7 @@ static int cdns_uart_startup(struct uart_port *port) } /* Set the Interrupt Registers with desired interrupts */ - writel(CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_PARITY | - CDNS_UART_IXR_FRAMING | CDNS_UART_IXR_OVERRUN | - CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_TOUT, - port->membase + CDNS_UART_IER_OFFSET); + writel(CDNS_UART_RX_IRQS, port->membase + CDNS_UART_IER_OFFSET); return 0; } -- cgit v1.2.3 From 354fb1a7d7e54a79d042f0a92dbd484bd3e900e6 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 11 Jan 2016 17:41:38 -0800 Subject: tty: xuartps: Cleanup: Reformat if-else Convert an if-else into the more common early return on error, reducing the indent level of the happy path. Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 124 ++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index a0039cbcf812..8014dd3c6d55 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -202,58 +202,55 @@ static void cdns_uart_handle_rx(struct uart_port *port, unsigned int isrstatus) isrstatus &= port->read_status_mask; isrstatus &= ~port->ignore_status_mask; - if ((isrstatus & CDNS_UART_IXR_TOUT) || - (isrstatus & CDNS_UART_IXR_RXTRIG)) { - /* Receive Timeout Interrupt */ - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & - CDNS_UART_SR_RXEMPTY)) { - u32 data; - char status = TTY_NORMAL; - - data = readl(port->membase + CDNS_UART_FIFO_OFFSET); - - /* Non-NULL byte after BREAK is garbage (99%) */ - if (data && (port->read_status_mask & - CDNS_UART_IXR_BRK)) { - port->read_status_mask &= ~CDNS_UART_IXR_BRK; - port->icount.brk++; - if (uart_handle_break(port)) - continue; - } + if (!(isrstatus & (CDNS_UART_IXR_TOUT | CDNS_UART_IXR_RXTRIG))) + return; + + while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & + CDNS_UART_SR_RXEMPTY)) { + u32 data; + char status = TTY_NORMAL; + + data = readl(port->membase + CDNS_UART_FIFO_OFFSET); + + /* Non-NULL byte after BREAK is garbage (99%) */ + if (data && (port->read_status_mask & CDNS_UART_IXR_BRK)) { + port->read_status_mask &= ~CDNS_UART_IXR_BRK; + port->icount.brk++; + if (uart_handle_break(port)) + continue; + } #ifdef SUPPORT_SYSRQ - /* - * uart_handle_sysrq_char() doesn't work if - * spinlocked, for some reason - */ - if (port->sysrq) { - spin_unlock(&port->lock); - if (uart_handle_sysrq_char(port, - (unsigned char)data)) { - spin_lock(&port->lock); - continue; - } + /* + * uart_handle_sysrq_char() doesn't work if + * spinlocked, for some reason + */ + if (port->sysrq) { + spin_unlock(&port->lock); + if (uart_handle_sysrq_char(port, data)) { spin_lock(&port->lock); + continue; } + spin_lock(&port->lock); + } #endif - port->icount.rx++; - - if (isrstatus & CDNS_UART_IXR_PARITY) { - port->icount.parity++; - status = TTY_PARITY; - } else if (isrstatus & CDNS_UART_IXR_FRAMING) { - port->icount.frame++; - status = TTY_FRAME; - } else if (isrstatus & CDNS_UART_IXR_OVERRUN) { - port->icount.overrun++; - } + port->icount.rx++; - uart_insert_char(port, isrstatus, CDNS_UART_IXR_OVERRUN, - data, status); + if (isrstatus & CDNS_UART_IXR_PARITY) { + port->icount.parity++; + status = TTY_PARITY; + } else if (isrstatus & CDNS_UART_IXR_FRAMING) { + port->icount.frame++; + status = TTY_FRAME; + } else if (isrstatus & CDNS_UART_IXR_OVERRUN) { + port->icount.overrun++; } - tty_flip_buffer_push(&port->state->port); + + uart_insert_char(port, isrstatus, CDNS_UART_IXR_OVERRUN, + data, status); } + tty_flip_buffer_push(&port->state->port); } /** @@ -1429,27 +1426,30 @@ static int cdns_uart_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Cannot get uart_port structure\n"); rc = -ENODEV; goto err_out_notif_unreg; - } else { - /* Register the port. - * This function also registers this device with the tty layer - * and triggers invocation of the config_port() entry point. - */ - port->mapbase = res->start; - port->irq = irq; - port->dev = &pdev->dev; - port->uartclk = clk_get_rate(cdns_uart_data->uartclk); - port->private_data = cdns_uart_data; - cdns_uart_data->port = port; - platform_set_drvdata(pdev, port); - rc = uart_add_one_port(&cdns_uart_uart_driver, port); - if (rc) { - dev_err(&pdev->dev, - "uart_add_one_port() failed; err=%i\n", rc); - goto err_out_notif_unreg; - } - return 0; } + /* + * Register the port. + * This function also registers this device with the tty layer + * and triggers invocation of the config_port() entry point. + */ + port->mapbase = res->start; + port->irq = irq; + port->dev = &pdev->dev; + port->uartclk = clk_get_rate(cdns_uart_data->uartclk); + port->private_data = cdns_uart_data; + cdns_uart_data->port = port; + platform_set_drvdata(pdev, port); + + rc = uart_add_one_port(&cdns_uart_uart_driver, port); + if (rc) { + dev_err(&pdev->dev, + "uart_add_one_port() failed; err=%i\n", rc); + goto err_out_notif_unreg; + } + + return 0; + err_out_notif_unreg: #ifdef CONFIG_COMMON_CLK clk_notifier_unregister(cdns_uart_data->uartclk, -- cgit v1.2.3 From 74ea66d4ca061a3cd4c0e924e51b60e924644852 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 11 Jan 2016 17:41:39 -0800 Subject: tty: xuartps: Improve sysrq handling Handling magic sysrq included dropping a lock to avoid a deadlock that happened when cdns_uart_console_write tried to acquire a lock in the from the sysrq code path. By making the acquisition of the lock in cdns_uart_console_write depending on port->sysrq, cdns_uart_handle_rx can be simplified to simply call uart_handle_sysrq. Suggested-by: Peter Hurley Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 8014dd3c6d55..0eecba88298f 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -220,20 +220,8 @@ static void cdns_uart_handle_rx(struct uart_port *port, unsigned int isrstatus) continue; } -#ifdef SUPPORT_SYSRQ - /* - * uart_handle_sysrq_char() doesn't work if - * spinlocked, for some reason - */ - if (port->sysrq) { - spin_unlock(&port->lock); - if (uart_handle_sysrq_char(port, data)) { - spin_lock(&port->lock); - continue; - } - spin_lock(&port->lock); - } -#endif + if (uart_handle_sysrq_char(port, data)) + continue; port->icount.rx++; @@ -1128,7 +1116,9 @@ static void cdns_uart_console_write(struct console *co, const char *s, unsigned int imr, ctrl; int locked = 1; - if (oops_in_progress) + if (port->sysrq) + locked = 0; + else if (oops_in_progress) locked = spin_trylock_irqsave(&port->lock, flags); else spin_lock_irqsave(&port->lock, flags); -- cgit v1.2.3 From a8df6a51600a93ce3d13eebbdf81f45bf719cb15 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 11 Jan 2016 17:41:40 -0800 Subject: tty: xuartps: Remove '_OFFSET' suffix from #defines Remove the _OFFSET suffix from all register defines which makes code a little easier to read and avoids a few line breaks. Suggested-by: Peter Hurley Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 221 ++++++++++++++++++------------------- 1 file changed, 106 insertions(+), 115 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 0eecba88298f..3ff6e3c2347c 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -50,24 +50,24 @@ module_param(rx_timeout, uint, S_IRUGO); MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); /* Register offsets for the UART. */ -#define CDNS_UART_CR_OFFSET 0x00 /* Control Register */ -#define CDNS_UART_MR_OFFSET 0x04 /* Mode Register */ -#define CDNS_UART_IER_OFFSET 0x08 /* Interrupt Enable */ -#define CDNS_UART_IDR_OFFSET 0x0C /* Interrupt Disable */ -#define CDNS_UART_IMR_OFFSET 0x10 /* Interrupt Mask */ -#define CDNS_UART_ISR_OFFSET 0x14 /* Interrupt Status */ -#define CDNS_UART_BAUDGEN_OFFSET 0x18 /* Baud Rate Generator */ -#define CDNS_UART_RXTOUT_OFFSET 0x1C /* RX Timeout */ -#define CDNS_UART_RXWM_OFFSET 0x20 /* RX FIFO Trigger Level */ -#define CDNS_UART_MODEMCR_OFFSET 0x24 /* Modem Control */ -#define CDNS_UART_MODEMSR_OFFSET 0x28 /* Modem Status */ -#define CDNS_UART_SR_OFFSET 0x2C /* Channel Status */ -#define CDNS_UART_FIFO_OFFSET 0x30 /* FIFO */ -#define CDNS_UART_BAUDDIV_OFFSET 0x34 /* Baud Rate Divider */ -#define CDNS_UART_FLOWDEL_OFFSET 0x38 /* Flow Delay */ -#define CDNS_UART_IRRX_PWIDTH_OFFSET 0x3C /* IR Min Received Pulse Width */ -#define CDNS_UART_IRTX_PWIDTH_OFFSET 0x40 /* IR Transmitted pulse Width */ -#define CDNS_UART_TXWM_OFFSET 0x44 /* TX FIFO Trigger Level */ +#define CDNS_UART_CR 0x00 /* Control Register */ +#define CDNS_UART_MR 0x04 /* Mode Register */ +#define CDNS_UART_IER 0x08 /* Interrupt Enable */ +#define CDNS_UART_IDR 0x0C /* Interrupt Disable */ +#define CDNS_UART_IMR 0x10 /* Interrupt Mask */ +#define CDNS_UART_ISR 0x14 /* Interrupt Status */ +#define CDNS_UART_BAUDGEN 0x18 /* Baud Rate Generator */ +#define CDNS_UART_RXTOUT 0x1C /* RX Timeout */ +#define CDNS_UART_RXWM 0x20 /* RX FIFO Trigger Level */ +#define CDNS_UART_MODEMCR 0x24 /* Modem Control */ +#define CDNS_UART_MODEMSR 0x28 /* Modem Status */ +#define CDNS_UART_SR 0x2C /* Channel Status */ +#define CDNS_UART_FIFO 0x30 /* FIFO */ +#define CDNS_UART_BAUDDIV 0x34 /* Baud Rate Divider */ +#define CDNS_UART_FLOWDEL 0x38 /* Flow Delay */ +#define CDNS_UART_IRRX_PWIDTH 0x3C /* IR Min Received Pulse Width */ +#define CDNS_UART_IRTX_PWIDTH 0x40 /* IR Transmitted pulse Width */ +#define CDNS_UART_TXWM 0x44 /* TX FIFO Trigger Level */ /* Control Register Bit Definitions */ #define CDNS_UART_CR_STOPBRK 0x00000100 /* Stop TX break */ @@ -184,15 +184,14 @@ static void cdns_uart_handle_rx(struct uart_port *port, unsigned int isrstatus) * there's another non-zero byte at the end of the sequence. */ if (isrstatus & CDNS_UART_IXR_FRAMING) { - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & + while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_RXEMPTY)) { - if (!readl(port->membase + CDNS_UART_FIFO_OFFSET)) { + if (!readl(port->membase + CDNS_UART_FIFO)) { port->read_status_mask |= CDNS_UART_IXR_BRK; isrstatus &= ~CDNS_UART_IXR_FRAMING; } } - writel(CDNS_UART_IXR_FRAMING, - port->membase + CDNS_UART_ISR_OFFSET); + writel(CDNS_UART_IXR_FRAMING, port->membase + CDNS_UART_ISR); } /* drop byte with parity error if IGNPAR specified */ @@ -205,12 +204,11 @@ static void cdns_uart_handle_rx(struct uart_port *port, unsigned int isrstatus) if (!(isrstatus & (CDNS_UART_IXR_TOUT | CDNS_UART_IXR_RXTRIG))) return; - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & - CDNS_UART_SR_RXEMPTY)) { + while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_RXEMPTY)) { u32 data; char status = TTY_NORMAL; - data = readl(port->membase + CDNS_UART_FIFO_OFFSET); + data = readl(port->membase + CDNS_UART_FIFO); /* Non-NULL byte after BREAK is garbage (99%) */ if (data && (port->read_status_mask & CDNS_UART_IXR_BRK)) { @@ -259,7 +257,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) /* Read the interrupt status register to determine which * interrupt(s) is/are active. */ - isrstatus = readl(port->membase + CDNS_UART_ISR_OFFSET); + isrstatus = readl(port->membase + CDNS_UART_ISR); if (isrstatus & CDNS_UART_RX_IRQS) cdns_uart_handle_rx(port, isrstatus); @@ -268,7 +266,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) if ((isrstatus & CDNS_UART_IXR_TXEMPTY) == CDNS_UART_IXR_TXEMPTY) { if (uart_circ_empty(&port->state->xmit)) { writel(CDNS_UART_IXR_TXEMPTY, - port->membase + CDNS_UART_IDR_OFFSET); + port->membase + CDNS_UART_IDR); } else { numbytes = port->fifosize; /* Break if no more data available in the UART buffer */ @@ -281,7 +279,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) */ writel(port->state->xmit.buf[ port->state->xmit.tail], - port->membase + CDNS_UART_FIFO_OFFSET); + port->membase + CDNS_UART_FIFO); port->icount.tx++; @@ -299,7 +297,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) } } - writel(isrstatus, port->membase + CDNS_UART_ISR_OFFSET); + writel(isrstatus, port->membase + CDNS_UART_ISR); /* be sure to release the lock and tty before leaving */ spin_unlock_irqrestore(&port->lock, flags); @@ -389,14 +387,14 @@ static unsigned int cdns_uart_set_baud_rate(struct uart_port *port, &div8); /* Write new divisors to hardware */ - mreg = readl(port->membase + CDNS_UART_MR_OFFSET); + mreg = readl(port->membase + CDNS_UART_MR); if (div8) mreg |= CDNS_UART_MR_CLKSEL; else mreg &= ~CDNS_UART_MR_CLKSEL; - writel(mreg, port->membase + CDNS_UART_MR_OFFSET); - writel(cd, port->membase + CDNS_UART_BAUDGEN_OFFSET); - writel(bdiv, port->membase + CDNS_UART_BAUDDIV_OFFSET); + writel(mreg, port->membase + CDNS_UART_MR); + writel(cd, port->membase + CDNS_UART_BAUDGEN); + writel(bdiv, port->membase + CDNS_UART_BAUDDIV); cdns_uart->baud = baud; return calc_baud; @@ -443,9 +441,9 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb, spin_lock_irqsave(&cdns_uart->port->lock, flags); /* Disable the TX and RX to set baud rate */ - ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET); + ctrl_reg = readl(port->membase + CDNS_UART_CR); ctrl_reg |= CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS; - writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl_reg, port->membase + CDNS_UART_CR); spin_unlock_irqrestore(&cdns_uart->port->lock, flags); @@ -470,11 +468,11 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb, spin_lock_irqsave(&cdns_uart->port->lock, flags); /* Set TX/RX Reset */ - ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET); + ctrl_reg = readl(port->membase + CDNS_UART_CR); ctrl_reg |= CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST; - writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl_reg, port->membase + CDNS_UART_CR); - while (readl(port->membase + CDNS_UART_CR_OFFSET) & + while (readl(port->membase + CDNS_UART_CR) & (CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST)) cpu_relax(); @@ -483,11 +481,11 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb, * enable bit and RX enable bit to enable the transmitter and * receiver. */ - writel(rx_timeout, port->membase + CDNS_UART_RXTOUT_OFFSET); - ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET); + writel(rx_timeout, port->membase + CDNS_UART_RXTOUT); + ctrl_reg = readl(port->membase + CDNS_UART_CR); ctrl_reg &= ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS); ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN; - writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl_reg, port->membase + CDNS_UART_CR); spin_unlock_irqrestore(&cdns_uart->port->lock, flags); @@ -513,15 +511,15 @@ static void cdns_uart_start_tx(struct uart_port *port) * Set the TX enable bit and clear the TX disable bit to enable the * transmitter. */ - status = readl(port->membase + CDNS_UART_CR_OFFSET); + status = readl(port->membase + CDNS_UART_CR); status &= ~CDNS_UART_CR_TX_DIS; status |= CDNS_UART_CR_TX_EN; - writel(status, port->membase + CDNS_UART_CR_OFFSET); + writel(status, port->membase + CDNS_UART_CR); if (uart_circ_empty(&port->state->xmit)) return; - while (numbytes-- && ((readl(port->membase + CDNS_UART_SR_OFFSET) & + while (numbytes-- && ((readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXFULL)) != CDNS_UART_SR_TXFULL) { /* Break if no more data available in the UART buffer */ if (uart_circ_empty(&port->state->xmit)) @@ -531,7 +529,7 @@ static void cdns_uart_start_tx(struct uart_port *port) * write it to the cdns_uart's TX_FIFO register. */ writel(port->state->xmit.buf[port->state->xmit.tail], - port->membase + CDNS_UART_FIFO_OFFSET); + port->membase + CDNS_UART_FIFO); port->icount.tx++; /* Adjust the tail of the UART buffer and wrap @@ -540,9 +538,9 @@ static void cdns_uart_start_tx(struct uart_port *port) port->state->xmit.tail = (port->state->xmit.tail + 1) & (UART_XMIT_SIZE - 1); } - writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR_OFFSET); + writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR); /* Enable the TX Empty interrupt */ - writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IER_OFFSET); + writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IER); if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS) uart_write_wakeup(port); @@ -556,10 +554,10 @@ static void cdns_uart_stop_tx(struct uart_port *port) { unsigned int regval; - regval = readl(port->membase + CDNS_UART_CR_OFFSET); + regval = readl(port->membase + CDNS_UART_CR); regval |= CDNS_UART_CR_TX_DIS; /* Disable the transmitter */ - writel(regval, port->membase + CDNS_UART_CR_OFFSET); + writel(regval, port->membase + CDNS_UART_CR); } /** @@ -571,12 +569,12 @@ static void cdns_uart_stop_rx(struct uart_port *port) unsigned int regval; /* Disable RX IRQs */ - writel(CDNS_UART_RX_IRQS, port->membase + CDNS_UART_IDR_OFFSET); + writel(CDNS_UART_RX_IRQS, port->membase + CDNS_UART_IDR); /* Disable the receiver */ - regval = readl(port->membase + CDNS_UART_CR_OFFSET); + regval = readl(port->membase + CDNS_UART_CR); regval |= CDNS_UART_CR_RX_DIS; - writel(regval, port->membase + CDNS_UART_CR_OFFSET); + writel(regval, port->membase + CDNS_UART_CR); } /** @@ -589,7 +587,7 @@ static unsigned int cdns_uart_tx_empty(struct uart_port *port) { unsigned int status; - status = readl(port->membase + CDNS_UART_SR_OFFSET) & + status = readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXEMPTY; return status ? TIOCSER_TEMT : 0; } @@ -607,15 +605,15 @@ static void cdns_uart_break_ctl(struct uart_port *port, int ctl) spin_lock_irqsave(&port->lock, flags); - status = readl(port->membase + CDNS_UART_CR_OFFSET); + status = readl(port->membase + CDNS_UART_CR); if (ctl == -1) writel(CDNS_UART_CR_STARTBRK | status, - port->membase + CDNS_UART_CR_OFFSET); + port->membase + CDNS_UART_CR); else { if ((status & CDNS_UART_CR_STOPBRK) == 0) writel(CDNS_UART_CR_STOPBRK | status, - port->membase + CDNS_UART_CR_OFFSET); + port->membase + CDNS_UART_CR); } spin_unlock_irqrestore(&port->lock, flags); } @@ -638,18 +636,18 @@ static void cdns_uart_set_termios(struct uart_port *port, spin_lock_irqsave(&port->lock, flags); /* Wait for the transmit FIFO to empty before making changes */ - if (!(readl(port->membase + CDNS_UART_CR_OFFSET) & + if (!(readl(port->membase + CDNS_UART_CR) & CDNS_UART_CR_TX_DIS)) { - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & + while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXEMPTY)) { cpu_relax(); } } /* Disable the TX and RX to set baud rate */ - ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET); + ctrl_reg = readl(port->membase + CDNS_UART_CR); ctrl_reg |= CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS; - writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl_reg, port->membase + CDNS_UART_CR); /* * Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk @@ -668,20 +666,20 @@ static void cdns_uart_set_termios(struct uart_port *port, uart_update_timeout(port, termios->c_cflag, baud); /* Set TX/RX Reset */ - ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET); + ctrl_reg = readl(port->membase + CDNS_UART_CR); ctrl_reg |= CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST; - writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl_reg, port->membase + CDNS_UART_CR); /* * Clear the RX disable and TX disable bits and then set the TX enable * bit and RX enable bit to enable the transmitter and receiver. */ - ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET); + ctrl_reg = readl(port->membase + CDNS_UART_CR); ctrl_reg &= ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS); ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN; - writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl_reg, port->membase + CDNS_UART_CR); - writel(rx_timeout, port->membase + CDNS_UART_RXTOUT_OFFSET); + writel(rx_timeout, port->membase + CDNS_UART_RXTOUT); port->read_status_mask = CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_TOUT; @@ -701,7 +699,7 @@ static void cdns_uart_set_termios(struct uart_port *port, CDNS_UART_IXR_TOUT | CDNS_UART_IXR_PARITY | CDNS_UART_IXR_FRAMING | CDNS_UART_IXR_OVERRUN; - mode_reg = readl(port->membase + CDNS_UART_MR_OFFSET); + mode_reg = readl(port->membase + CDNS_UART_MR); /* Handling Data Size */ switch (termios->c_cflag & CSIZE) { @@ -742,7 +740,7 @@ static void cdns_uart_set_termios(struct uart_port *port, cval |= CDNS_UART_MR_PARITY_NONE; } cval |= mode_reg & 1; - writel(cval, port->membase + CDNS_UART_MR_OFFSET); + writel(cval, port->membase + CDNS_UART_MR); spin_unlock_irqrestore(&port->lock, flags); } @@ -763,45 +761,45 @@ static int cdns_uart_startup(struct uart_port *port) /* Disable the TX and RX */ writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS, - port->membase + CDNS_UART_CR_OFFSET); + port->membase + CDNS_UART_CR); /* Set the Control Register with TX/RX Enable, TX/RX Reset, * no break chars. */ writel(CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST, - port->membase + CDNS_UART_CR_OFFSET); + port->membase + CDNS_UART_CR); /* * Clear the RX disable bit and then set the RX enable bit to enable * the receiver. */ - status = readl(port->membase + CDNS_UART_CR_OFFSET); + status = readl(port->membase + CDNS_UART_CR); status &= CDNS_UART_CR_RX_DIS; status |= CDNS_UART_CR_RX_EN; - writel(status, port->membase + CDNS_UART_CR_OFFSET); + writel(status, port->membase + CDNS_UART_CR); /* Set the Mode Register with normal mode,8 data bits,1 stop bit, * no parity. */ writel(CDNS_UART_MR_CHMODE_NORM | CDNS_UART_MR_STOPMODE_1_BIT | CDNS_UART_MR_PARITY_NONE | CDNS_UART_MR_CHARLEN_8_BIT, - port->membase + CDNS_UART_MR_OFFSET); + port->membase + CDNS_UART_MR); /* * Set the RX FIFO Trigger level to use most of the FIFO, but it * can be tuned with a module parameter */ - writel(rx_trigger_level, port->membase + CDNS_UART_RXWM_OFFSET); + writel(rx_trigger_level, port->membase + CDNS_UART_RXWM); /* * Receive Timeout register is enabled but it * can be tuned with a module parameter */ - writel(rx_timeout, port->membase + CDNS_UART_RXTOUT_OFFSET); + writel(rx_timeout, port->membase + CDNS_UART_RXTOUT); /* Clear out any pending interrupts before enabling them */ - writel(readl(port->membase + CDNS_UART_ISR_OFFSET), - port->membase + CDNS_UART_ISR_OFFSET); + writel(readl(port->membase + CDNS_UART_ISR), + port->membase + CDNS_UART_ISR); spin_unlock_irqrestore(&port->lock, flags); @@ -813,7 +811,7 @@ static int cdns_uart_startup(struct uart_port *port) } /* Set the Interrupt Registers with desired interrupts */ - writel(CDNS_UART_RX_IRQS, port->membase + CDNS_UART_IER_OFFSET); + writel(CDNS_UART_RX_IRQS, port->membase + CDNS_UART_IER); return 0; } @@ -830,13 +828,13 @@ static void cdns_uart_shutdown(struct uart_port *port) spin_lock_irqsave(&port->lock, flags); /* Disable interrupts */ - status = readl(port->membase + CDNS_UART_IMR_OFFSET); - writel(status, port->membase + CDNS_UART_IDR_OFFSET); - writel(0xffffffff, port->membase + CDNS_UART_ISR_OFFSET); + status = readl(port->membase + CDNS_UART_IMR); + writel(status, port->membase + CDNS_UART_IDR); + writel(0xffffffff, port->membase + CDNS_UART_ISR); /* Disable the TX and RX */ writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS, - port->membase + CDNS_UART_CR_OFFSET); + port->membase + CDNS_UART_CR); spin_unlock_irqrestore(&port->lock, flags); @@ -941,7 +939,7 @@ static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) { u32 val; - val = readl(port->membase + CDNS_UART_MODEMCR_OFFSET); + val = readl(port->membase + CDNS_UART_MODEMCR); val &= ~(CDNS_UART_MODEMCR_RTS | CDNS_UART_MODEMCR_DTR); @@ -950,7 +948,7 @@ static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) if (mctrl & TIOCM_DTR) val |= CDNS_UART_MODEMCR_DTR; - writel(val, port->membase + CDNS_UART_MODEMCR_OFFSET); + writel(val, port->membase + CDNS_UART_MODEMCR); } #ifdef CONFIG_CONSOLE_POLL @@ -962,11 +960,10 @@ static int cdns_uart_poll_get_char(struct uart_port *port) spin_lock_irqsave(&port->lock, flags); /* Check if FIFO is empty */ - if (readl(port->membase + CDNS_UART_SR_OFFSET) & CDNS_UART_SR_RXEMPTY) + if (readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_RXEMPTY) c = NO_POLL_CHAR; else /* Read a character */ - c = (unsigned char) readl( - port->membase + CDNS_UART_FIFO_OFFSET); + c = (unsigned char) readl(port->membase + CDNS_UART_FIFO); spin_unlock_irqrestore(&port->lock, flags); @@ -980,16 +977,14 @@ static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c) spin_lock_irqsave(&port->lock, flags); /* Wait until FIFO is empty */ - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & - CDNS_UART_SR_TXEMPTY)) + while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXEMPTY)) cpu_relax(); /* Write a character */ - writel(c, port->membase + CDNS_UART_FIFO_OFFSET); + writel(c, port->membase + CDNS_UART_FIFO); /* Wait until FIFO is empty */ - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & - CDNS_UART_SR_TXEMPTY)) + while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXEMPTY)) cpu_relax(); spin_unlock_irqrestore(&port->lock, flags); @@ -1066,8 +1061,7 @@ static struct uart_port *cdns_uart_get_port(int id) */ static void cdns_uart_console_wait_tx(struct uart_port *port) { - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & - CDNS_UART_SR_TXEMPTY)) + while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXEMPTY)) barrier(); } @@ -1079,7 +1073,7 @@ static void cdns_uart_console_wait_tx(struct uart_port *port) static void cdns_uart_console_putchar(struct uart_port *port, int ch) { cdns_uart_console_wait_tx(port); - writel(ch, port->membase + CDNS_UART_FIFO_OFFSET); + writel(ch, port->membase + CDNS_UART_FIFO); } static void __init cdns_early_write(struct console *con, const char *s, @@ -1124,25 +1118,25 @@ static void cdns_uart_console_write(struct console *co, const char *s, spin_lock_irqsave(&port->lock, flags); /* save and disable interrupt */ - imr = readl(port->membase + CDNS_UART_IMR_OFFSET); - writel(imr, port->membase + CDNS_UART_IDR_OFFSET); + imr = readl(port->membase + CDNS_UART_IMR); + writel(imr, port->membase + CDNS_UART_IDR); /* * Make sure that the tx part is enabled. Set the TX enable bit and * clear the TX disable bit to enable the transmitter. */ - ctrl = readl(port->membase + CDNS_UART_CR_OFFSET); + ctrl = readl(port->membase + CDNS_UART_CR); ctrl &= ~CDNS_UART_CR_TX_DIS; ctrl |= CDNS_UART_CR_TX_EN; - writel(ctrl, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl, port->membase + CDNS_UART_CR); uart_console_write(port, s, count, cdns_uart_console_putchar); cdns_uart_console_wait_tx(port); - writel(ctrl, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl, port->membase + CDNS_UART_CR); /* restore interrupt state */ - writel(imr, port->membase + CDNS_UART_IER_OFFSET); + writel(imr, port->membase + CDNS_UART_IER); if (locked) spin_unlock_irqrestore(&port->lock, flags); @@ -1254,14 +1248,13 @@ static int cdns_uart_suspend(struct device *device) spin_lock_irqsave(&port->lock, flags); /* Empty the receive FIFO 1st before making changes */ - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & + while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_RXEMPTY)) - readl(port->membase + CDNS_UART_FIFO_OFFSET); + readl(port->membase + CDNS_UART_FIFO); /* set RX trigger level to 1 */ - writel(1, port->membase + CDNS_UART_RXWM_OFFSET); + writel(1, port->membase + CDNS_UART_RXWM); /* disable RX timeout interrups */ - writel(CDNS_UART_IXR_TOUT, - port->membase + CDNS_UART_IDR_OFFSET); + writel(CDNS_UART_IXR_TOUT, port->membase + CDNS_UART_IDR); spin_unlock_irqrestore(&port->lock, flags); } @@ -1300,30 +1293,28 @@ static int cdns_uart_resume(struct device *device) spin_lock_irqsave(&port->lock, flags); /* Set TX/RX Reset */ - ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET); + ctrl_reg = readl(port->membase + CDNS_UART_CR); ctrl_reg |= CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST; - writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET); - while (readl(port->membase + CDNS_UART_CR_OFFSET) & + writel(ctrl_reg, port->membase + CDNS_UART_CR); + while (readl(port->membase + CDNS_UART_CR) & (CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST)) cpu_relax(); /* restore rx timeout value */ - writel(rx_timeout, port->membase + CDNS_UART_RXTOUT_OFFSET); + writel(rx_timeout, port->membase + CDNS_UART_RXTOUT); /* Enable Tx/Rx */ - ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET); + ctrl_reg = readl(port->membase + CDNS_UART_CR); ctrl_reg &= ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS); ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN; - writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl_reg, port->membase + CDNS_UART_CR); spin_unlock_irqrestore(&port->lock, flags); } else { spin_lock_irqsave(&port->lock, flags); /* restore original rx trigger level */ - writel(rx_trigger_level, - port->membase + CDNS_UART_RXWM_OFFSET); + writel(rx_trigger_level, port->membase + CDNS_UART_RXWM); /* enable RX timeout interrupt */ - writel(CDNS_UART_IXR_TOUT, - port->membase + CDNS_UART_IER_OFFSET); + writel(CDNS_UART_IXR_TOUT, port->membase + CDNS_UART_IER); spin_unlock_irqrestore(&port->lock, flags); } -- cgit v1.2.3 From 07986580d0ad14433021b709c6c005e2757c5a68 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 11 Jan 2016 17:41:41 -0800 Subject: tty: xuartps: Consolidate TX handling start_tx and the ISR used largely identical code to transmit data. Consolidate that in one place. Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 97 ++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 3ff6e3c2347c..131a3117fbbb 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -239,6 +239,41 @@ static void cdns_uart_handle_rx(struct uart_port *port, unsigned int isrstatus) tty_flip_buffer_push(&port->state->port); } +static void cdns_uart_handle_tx(struct uart_port *port) +{ + unsigned int numbytes; + + if (uart_circ_empty(&port->state->xmit)) { + writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IDR); + return; + } + + numbytes = port->fifosize; + while (numbytes && !uart_circ_empty(&port->state->xmit) && + !(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXFULL)) { + /* + * Get the data from the UART circular buffer + * and write it to the cdns_uart's TX_FIFO + * register. + */ + writel(port->state->xmit.buf[port->state->xmit.tail], + port->membase + CDNS_UART_FIFO); + port->icount.tx++; + + /* + * Adjust the tail of the UART buffer and wrap + * the buffer if it reaches limit. + */ + port->state->xmit.tail = + (port->state->xmit.tail + 1) & (UART_XMIT_SIZE - 1); + + numbytes--; + } + + if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); +} + /** * cdns_uart_isr - Interrupt handler * @irq: Irq number @@ -250,7 +285,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) { struct uart_port *port = (struct uart_port *)dev_id; unsigned long flags; - unsigned int isrstatus, numbytes; + unsigned int isrstatus; spin_lock_irqsave(&port->lock, flags); @@ -262,40 +297,8 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) if (isrstatus & CDNS_UART_RX_IRQS) cdns_uart_handle_rx(port, isrstatus); - /* Dispatch an appropriate handler */ - if ((isrstatus & CDNS_UART_IXR_TXEMPTY) == CDNS_UART_IXR_TXEMPTY) { - if (uart_circ_empty(&port->state->xmit)) { - writel(CDNS_UART_IXR_TXEMPTY, - port->membase + CDNS_UART_IDR); - } else { - numbytes = port->fifosize; - /* Break if no more data available in the UART buffer */ - while (numbytes--) { - if (uart_circ_empty(&port->state->xmit)) - break; - /* Get the data from the UART circular buffer - * and write it to the cdns_uart's TX_FIFO - * register. - */ - writel(port->state->xmit.buf[ - port->state->xmit.tail], - port->membase + CDNS_UART_FIFO); - - port->icount.tx++; - - /* Adjust the tail of the UART buffer and wrap - * the buffer if it reaches limit. - */ - port->state->xmit.tail = - (port->state->xmit.tail + 1) & - (UART_XMIT_SIZE - 1); - } - - if (uart_circ_chars_pending( - &port->state->xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); - } - } + if ((isrstatus & CDNS_UART_IXR_TXEMPTY) == CDNS_UART_IXR_TXEMPTY) + cdns_uart_handle_tx(port); writel(isrstatus, port->membase + CDNS_UART_ISR); @@ -502,7 +505,7 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb, */ static void cdns_uart_start_tx(struct uart_port *port) { - unsigned int status, numbytes = port->fifosize; + unsigned int status; if (uart_tx_stopped(port)) return; @@ -519,31 +522,11 @@ static void cdns_uart_start_tx(struct uart_port *port) if (uart_circ_empty(&port->state->xmit)) return; - while (numbytes-- && ((readl(port->membase + CDNS_UART_SR) & - CDNS_UART_SR_TXFULL)) != CDNS_UART_SR_TXFULL) { - /* Break if no more data available in the UART buffer */ - if (uart_circ_empty(&port->state->xmit)) - break; - - /* Get the data from the UART circular buffer and - * write it to the cdns_uart's TX_FIFO register. - */ - writel(port->state->xmit.buf[port->state->xmit.tail], - port->membase + CDNS_UART_FIFO); - port->icount.tx++; + cdns_uart_handle_tx(port); - /* Adjust the tail of the UART buffer and wrap - * the buffer if it reaches limit. - */ - port->state->xmit.tail = (port->state->xmit.tail + 1) & - (UART_XMIT_SIZE - 1); - } writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR); /* Enable the TX Empty interrupt */ writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IER); - - if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); } /** -- cgit v1.2.3 From 29add68d16474b7e8e3eadd94da4e909533b99d2 Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Tue, 5 Jan 2016 16:53:31 +0100 Subject: serial: imx: Fix suspend / resume. When a non console i.MX UART is enabled in the device tree, system suspend fails due to an unprepared clock: [ 638.794563] PM: Syncing filesystems ... done. [ 638.878902] Freezing user space processes ... (elapsed 0.002 seconds) done. [ 638.888454] Freezing remaining freezable tasks ... (elapsed 0.001 seconds) done. [ 638.996697] PM: suspend of devices complete after 97.200 msecs [ 639.002611] PM: suspend devices took 0.100 seconds [ 639.013020] PM: late suspend of devices complete after 2.288 msecs [ 639.021486] ------------[ cut here ]------------ [ 639.026147] WARNING: CPU: 0 PID: 488 at drivers/clk/clk.c:732 clk_core_enable+0xc0/0x12c() [ 639.034413] Modules linked in: [ 639.037490] CPU: 0 PID: 488 Comm: system_server Tainted: G W 4.4.0-rc5-pknbsp-svn2214-atag-v4.4-rc5-121-gebfd9cb #1304 [ 639.049312] Hardware name: Freescale i.MX53 (Device Tree Support) [ 639.055444] [] (unwind_backtrace) from [] (show_stack+0x20/0x24) [ 639.063199] [] (show_stack) from [] (dump_stack+0x20/0x28) [ 639.070442] [] (dump_stack) from [] (warn_slowpath_common+0x88/0xc0) [ 639.078541] [] (warn_slowpath_common) from [] (warn_slowpath_null+0x2c/0x34) [ 639.087332] [] (warn_slowpath_null) from [] (clk_core_enable+0xc0/0x12c) [ 639.095777] [] (clk_core_enable) from [] (clk_enable+0x2c/0x40) [ 639.103441] [] (clk_enable) from [] (imx_serial_port_suspend_noirq+0x20/0xe0) [ 639.112336] [] (imx_serial_port_suspend_noirq) from [] (dpm_run_callback+0x68/0x16c) [ 639.121825] [] (dpm_run_callback) from [] (__device_suspend_noirq+0xf4/0x22c) [ 639.130705] [] (__device_suspend_noirq) from [] (dpm_suspend_noirq+0x148/0x30c) [ 639.139764] [] (dpm_suspend_noirq) from [] (suspend_devices_and_enter+0x2e8/0x6a4) [ 639.149078] [] (suspend_devices_and_enter) from [] (pm_suspend+0x310/0x4b8) [ 639.157782] [] (pm_suspend) from [] (state_store+0x7c/0xcc) [ 639.165099] [] (state_store) from [] (kobj_attr_store+0x1c/0x28) [ 639.172858] [] (kobj_attr_store) from [] (sysfs_kf_write+0x54/0x58) [ 639.180871] [] (sysfs_kf_write) from [] (kernfs_fop_write+0x100/0x1c8) [ 639.189152] [] (kernfs_fop_write) from [] (__vfs_write+0x3c/0xe8) [ 639.196991] [] (__vfs_write) from [] (vfs_write+0xa4/0x160) [ 639.204307] [] (vfs_write) from [] (SyS_write+0x4c/0x98) [ 639.211363] [] (SyS_write) from [] (ret_fast_syscall+0x0/0x3c) This does not happen for the common case of a single UART used as a console (since imx_console_setup() already does a prepare) Signed-off-by: Martin Fuzzey Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 9362f54c816c..231e7d5caf6c 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -2166,7 +2166,8 @@ static int imx_serial_port_suspend(struct device *dev) uart_suspend_port(&imx_reg, &sport->port); - return 0; + /* Needed to enable clock in suspend_noirq */ + return clk_prepare(sport->clk_ipg); } static int imx_serial_port_resume(struct device *dev) @@ -2179,6 +2180,8 @@ static int imx_serial_port_resume(struct device *dev) uart_resume_port(&imx_reg, &sport->port); + clk_unprepare(sport->clk_ipg); + return 0; } -- cgit v1.2.3 From 95ee05c7adb0b5b7d55cc991b015a62efba21ba5 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 4 Jan 2016 14:45:18 +0100 Subject: serial: sh-sci: Add more Serial Mode Register documentation Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 2 +- drivers/tty/serial/sh-sci.h | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index ec08f1bff753..65f717395086 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2064,7 +2064,7 @@ static void sci_reset(struct uart_port *port) static void sci_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { - unsigned int baud, smr_val = 0, scr_val = 0, i; + unsigned int baud, smr_val = SCSMR_ASYNC, scr_val = 0, i; unsigned int brr = 255, cks = 0, srr = 15, dl = 0, sccks = 0; unsigned int brr1 = 255, cks1 = 0, srr1 = 15, dl1 = 0; struct sci_port *s = to_sci_port(port); diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h index fb1760250421..7a4fa185b93e 100644 --- a/drivers/tty/serial/sh-sci.h +++ b/drivers/tty/serial/sh-sci.h @@ -35,12 +35,27 @@ enum { /* SCSMR (Serial Mode Register) */ +#define SCSMR_C_A BIT(7) /* Communication Mode */ +#define SCSMR_CSYNC BIT(7) /* - Clocked synchronous mode */ +#define SCSMR_ASYNC 0 /* - Asynchronous mode */ #define SCSMR_CHR BIT(6) /* 7-bit Character Length */ #define SCSMR_PE BIT(5) /* Parity Enable */ #define SCSMR_ODD BIT(4) /* Odd Parity */ #define SCSMR_STOP BIT(3) /* Stop Bit Length */ #define SCSMR_CKS 0x0003 /* Clock Select */ +/* Serial Mode Register, SCIFA/SCIFB only bits */ +#define SCSMR_CKEDG BIT(12) /* Transmit/Receive Clock Edge Select */ +#define SCSMR_SRC_MASK 0x0700 /* Sampling Control */ +#define SCSMR_SRC_16 0x0000 /* Sampling rate 1/16 */ +#define SCSMR_SRC_5 0x0100 /* Sampling rate 1/5 */ +#define SCSMR_SRC_7 0x0200 /* Sampling rate 1/7 */ +#define SCSMR_SRC_11 0x0300 /* Sampling rate 1/11 */ +#define SCSMR_SRC_13 0x0400 /* Sampling rate 1/13 */ +#define SCSMR_SRC_17 0x0500 /* Sampling rate 1/17 */ +#define SCSMR_SRC_19 0x0600 /* Sampling rate 1/19 */ +#define SCSMR_SRC_27 0x0700 /* Sampling rate 1/27 */ + /* Serial Control Register, SCIFA/SCIFB only bits */ #define SCSCR_TDRQE BIT(15) /* Tx Data Transfer Request Enable */ #define SCSCR_RDRQE BIT(14) /* Rx Data Transfer Request Enable */ -- cgit v1.2.3 From 3a964abe1ef1cfbe82d0ae832d70c7750d673728 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 4 Jan 2016 14:45:19 +0100 Subject: serial: sh-sci: Preserve SCIFA/SCIFB bit rate config for serial console SCIFA and SCIFB have additional bit rate config bits in the Serial Mode Register. Don't touch them when using the port as a serial console, as we rely on the boot loader to have configured the serial port config. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 65f717395086..b175f8f565d8 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2202,7 +2202,8 @@ done: } else { /* Don't touch the bit rate configuration */ scr_val = s->cfg->scscr & (SCSCR_CKE1 | SCSCR_CKE0); - smr_val |= serial_port_in(port, SCSMR) & SCSMR_CKS; + smr_val |= serial_port_in(port, SCSMR) & + (SCSMR_CKEDG | SCSMR_SRC_MASK | SCSMR_CKS); dev_dbg(port->dev, "SCR 0x%x SMR 0x%x\n", scr_val, smr_val); serial_port_out(port, SCSCR, scr_val); serial_port_out(port, SCSMR, smr_val); -- cgit v1.2.3 From 7b5c0c08f5e895fb92c1d1d5f905c68eca1df5c0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 4 Jan 2016 14:45:20 +0100 Subject: serial: sh-sci: Use premultiplier to handle half sampling rate On SCIx variants different from HSCIF, the bit rate is equal to the sampling clock rate divided by half the sampling rate. Currently this is handled by dividing the sampling rate by two, which was OK as it was always even. Replace halving the sampling rate by premultiplying the base clock frequency by 2, to accommodate odd sampling rates on SCIFA/SCIFB later. Replace the shift value in the BRG divider calculation by a premultiplication of the base clock frequency too, for consistency. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index b175f8f565d8..70f005f37de0 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1907,9 +1907,11 @@ static int sci_sck_calc(struct sci_port *s, unsigned int bps, unsigned int min_sr, max_sr, sr; int err, min_err = INT_MAX; + if (s->port.type != PORT_HSCIF) + freq *= 2; if (s->sampling_rate) { /* SCI(F) has a fixed sampling rate */ - min_sr = max_sr = s->sampling_rate / 2; + min_sr = max_sr = s->sampling_rate; } else { /* HSCIF has a variable 1/(8..32) sampling rate */ min_sr = 8; @@ -1940,9 +1942,11 @@ static int sci_brg_calc(struct sci_port *s, unsigned int bps, unsigned int min_sr, max_sr, sr, dl; int err, min_err = INT_MAX; + if (s->port.type != PORT_HSCIF) + freq *= 2; if (s->sampling_rate) { /* SCIF has a fixed sampling rate */ - min_sr = max_sr = s->sampling_rate / 2; + min_sr = max_sr = s->sampling_rate; } else { /* HSCIF has a variable 1/(8..32) sampling rate */ min_sr = 8; @@ -1975,18 +1979,18 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, unsigned int *brr, unsigned int *srr, unsigned int *cks) { - unsigned int min_sr, max_sr, shift, sr, br, prediv, scrate, c; + unsigned int min_sr, max_sr, sr, br, prediv, scrate, c; unsigned long freq = s->clk_rates[SCI_FCK]; int err, min_err = INT_MAX; + if (s->port.type != PORT_HSCIF) + freq *= 2; if (s->sampling_rate) { min_sr = max_sr = s->sampling_rate; - shift = 0; } else { /* HSCIF has a variable sample rate */ min_sr = 8; max_sr = 32; - shift = 1; } /* @@ -2007,7 +2011,7 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, for (sr = max_sr; sr >= min_sr; sr--) { for (c = 0; c <= 3; c++) { /* integerized formulas from HSCIF documentation */ - prediv = sr * (1 << (2 * c + shift)); + prediv = sr * (1 << (2 * c + 1)); /* * We need to calculate: -- cgit v1.2.3 From 69eee8e9c876eb412282a3b45d998e989d3a8e93 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 4 Jan 2016 14:45:21 +0100 Subject: serial: sh-sci: Use a bitmask to indicate supported sampling rates Replace the single sampling rate and special handling for HSCIF's variable sampling rates by a bitmask and a custom iterator. This prepares for the advent of SCIFA/SCIFB's sparse variable sampling rates. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 66 +++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 70f005f37de0..dbf488b9ae27 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -84,6 +84,18 @@ enum SCI_CLKS { SCI_NUM_CLKS }; +/* Bit x set means sampling rate x + 1 is supported */ +#define SCI_SR(x) BIT((x) - 1) +#define SCI_SR_RANGE(x, y) GENMASK((y) - 1, (x) - 1) + +#define min_sr(_port) ffs((_port)->sampling_rate_mask) +#define max_sr(_port) fls((_port)->sampling_rate_mask) + +/* Iterate over all supported sampling rates, from high to low */ +#define for_each_sr(_sr, _port) \ + for ((_sr) = max_sr(_port); (_sr) >= min_sr(_port); (_sr)--) \ + if ((_port)->sampling_rate_mask & SCI_SR((_sr))) + struct sci_port { struct uart_port port; @@ -93,7 +105,7 @@ struct sci_port { unsigned int overrun_mask; unsigned int error_mask; unsigned int error_clear; - unsigned int sampling_rate; + unsigned int sampling_rate_mask; resource_size_t reg_size; /* Break timer */ @@ -1904,21 +1916,13 @@ static int sci_sck_calc(struct sci_port *s, unsigned int bps, unsigned int *srr) { unsigned long freq = s->clk_rates[SCI_SCK]; - unsigned int min_sr, max_sr, sr; int err, min_err = INT_MAX; + unsigned int sr; if (s->port.type != PORT_HSCIF) freq *= 2; - if (s->sampling_rate) { - /* SCI(F) has a fixed sampling rate */ - min_sr = max_sr = s->sampling_rate; - } else { - /* HSCIF has a variable 1/(8..32) sampling rate */ - min_sr = 8; - max_sr = 32; - } - for (sr = max_sr; sr >= min_sr; sr--) { + for_each_sr(sr, s) { err = DIV_ROUND_CLOSEST(freq, sr) - bps; if (abs(err) >= abs(min_err)) continue; @@ -1939,21 +1943,13 @@ static int sci_brg_calc(struct sci_port *s, unsigned int bps, unsigned long freq, unsigned int *dlr, unsigned int *srr) { - unsigned int min_sr, max_sr, sr, dl; int err, min_err = INT_MAX; + unsigned int sr, dl; if (s->port.type != PORT_HSCIF) freq *= 2; - if (s->sampling_rate) { - /* SCIF has a fixed sampling rate */ - min_sr = max_sr = s->sampling_rate; - } else { - /* HSCIF has a variable 1/(8..32) sampling rate */ - min_sr = 8; - max_sr = 32; - } - for (sr = max_sr; sr >= min_sr; sr--) { + for_each_sr(sr, s) { dl = DIV_ROUND_CLOSEST(freq, sr * bps); dl = clamp(dl, 1U, 65535U); @@ -1979,19 +1975,12 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, unsigned int *brr, unsigned int *srr, unsigned int *cks) { - unsigned int min_sr, max_sr, sr, br, prediv, scrate, c; unsigned long freq = s->clk_rates[SCI_FCK]; + unsigned int sr, br, prediv, scrate, c; int err, min_err = INT_MAX; if (s->port.type != PORT_HSCIF) freq *= 2; - if (s->sampling_rate) { - min_sr = max_sr = s->sampling_rate; - } else { - /* HSCIF has a variable sample rate */ - min_sr = 8; - max_sr = 32; - } /* * Find the combination of sample rate and clock select with the @@ -2008,7 +1997,7 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, * (|D - 0.5| / N * (1 + F))| * NOTE: Usually, treat D for 0.5, F is 0 by this calculation. */ - for (sr = max_sr; sr >= min_sr; sr--) { + for_each_sr(sr, s) { for (c = 0; c <= 3; c++) { /* integerized formulas from HSCIF documentation */ prediv = sr * (1 << (2 * c + 1)); @@ -2102,8 +2091,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, for (i = 0; i < SCI_NUM_CLKS; i++) max_freq = max(max_freq, s->clk_rates[i]); - baud = uart_get_baud_rate(port, termios, old, 0, - max_freq / max(s->sampling_rate, 8U)); + baud = uart_get_baud_rate(port, termios, old, 0, max_freq / min_sr(s)); if (!baud) goto done; @@ -2535,37 +2523,37 @@ static int sci_init_single(struct platform_device *dev, port->fifosize = 256; sci_port->overrun_reg = SCxSR; sci_port->overrun_mask = SCIFA_ORER; - sci_port->sampling_rate = 16; + sci_port->sampling_rate_mask = SCI_SR(16); break; case PORT_HSCIF: port->fifosize = 128; sci_port->overrun_reg = SCLSR; sci_port->overrun_mask = SCLSR_ORER; - sci_port->sampling_rate = 0; + sci_port->sampling_rate_mask = SCI_SR_RANGE(8, 32); break; case PORT_SCIFA: port->fifosize = 64; sci_port->overrun_reg = SCxSR; sci_port->overrun_mask = SCIFA_ORER; - sci_port->sampling_rate = 16; + sci_port->sampling_rate_mask = SCI_SR(16); break; case PORT_SCIF: port->fifosize = 16; if (p->regtype == SCIx_SH7705_SCIF_REGTYPE) { sci_port->overrun_reg = SCxSR; sci_port->overrun_mask = SCIFA_ORER; - sci_port->sampling_rate = 16; + sci_port->sampling_rate_mask = SCI_SR(16); } else { sci_port->overrun_reg = SCLSR; sci_port->overrun_mask = SCLSR_ORER; - sci_port->sampling_rate = 32; + sci_port->sampling_rate_mask = SCI_SR(32); } break; default: port->fifosize = 1; sci_port->overrun_reg = SCxSR; sci_port->overrun_mask = SCI_ORER; - sci_port->sampling_rate = 32; + sci_port->sampling_rate_mask = SCI_SR(32); break; } @@ -2574,7 +2562,7 @@ static int sci_init_single(struct platform_device *dev, * data override the sampling rate for now. */ if (p->sampling_rate) - sci_port->sampling_rate = p->sampling_rate; + sci_port->sampling_rate_mask = SCI_SR(p->sampling_rate); if (!early) { ret = sci_init_clocks(sci_port, &dev->dev); -- cgit v1.2.3 From 92a0574867f3329ca285b51adcf09ed3ee42e7a0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 4 Jan 2016 14:45:22 +0100 Subject: serial: sh-sci: Add support for SCIFA/SCIFB variable sampling rates Add support for sparse variable sampling rates on SCIFA and SCIFB. According to the datasheet, sampling rate 1/5 needs a small quirk to avoid corrupting the first byte received. This increases the range and accuracy of supported baud rates. E.g. on r8a7791/koelsch: - Supports now 134, 150, and standard 500000-4000000 bps, - Perfect match for 134, 150, 500000, 1000000, 2000000, and 4000000 bps, - Accuracy has increased for most standard bps values. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index dbf488b9ae27..4678d8f2dd7d 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -88,6 +88,10 @@ enum SCI_CLKS { #define SCI_SR(x) BIT((x) - 1) #define SCI_SR_RANGE(x, y) GENMASK((y) - 1, (x) - 1) +#define SCI_SR_SCIFAB SCI_SR(5) | SCI_SR(7) | SCI_SR(11) | \ + SCI_SR(13) | SCI_SR(16) | SCI_SR(17) | \ + SCI_SR(19) | SCI_SR(27) + #define min_sr(_port) ffs((_port)->sampling_rate_mask) #define max_sr(_port) fls((_port)->sampling_rate_mask) @@ -2179,6 +2183,17 @@ done: uart_update_timeout(port, termios->c_cflag, baud); if (best_clk >= 0) { + if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) + switch (srr + 1) { + case 5: smr_val |= SCSMR_SRC_5; break; + case 7: smr_val |= SCSMR_SRC_7; break; + case 11: smr_val |= SCSMR_SRC_11; break; + case 13: smr_val |= SCSMR_SRC_13; break; + case 16: smr_val |= SCSMR_SRC_16; break; + case 17: smr_val |= SCSMR_SRC_17; break; + case 19: smr_val |= SCSMR_SRC_19; break; + case 27: smr_val |= SCSMR_SRC_27; break; + } smr_val |= cks; dev_dbg(port->dev, "SCR 0x%x SMR 0x%x BRR %u CKS 0x%x DL %u SRR %u\n", @@ -2227,6 +2242,16 @@ done: scr_val |= s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0); dev_dbg(port->dev, "SCSCR 0x%x\n", scr_val); serial_port_out(port, SCSCR, scr_val); + if ((srr + 1 == 5) && + (port->type == PORT_SCIFA || port->type == PORT_SCIFB)) { + /* + * In asynchronous mode, when the sampling rate is 1/5, first + * received data may become invalid on some SCIFA and SCIFB. + * To avoid this problem wait more than 1 serial data time (1 + * bit time x serial data number) after setting SCSCR.RE = 1. + */ + udelay(DIV_ROUND_UP(10 * 1000000, baud)); + } #ifdef CONFIG_SERIAL_SH_SCI_DMA /* @@ -2523,7 +2548,7 @@ static int sci_init_single(struct platform_device *dev, port->fifosize = 256; sci_port->overrun_reg = SCxSR; sci_port->overrun_mask = SCIFA_ORER; - sci_port->sampling_rate_mask = SCI_SR(16); + sci_port->sampling_rate_mask = SCI_SR_SCIFAB; break; case PORT_HSCIF: port->fifosize = 128; @@ -2535,7 +2560,7 @@ static int sci_init_single(struct platform_device *dev, port->fifosize = 64; sci_port->overrun_reg = SCxSR; sci_port->overrun_mask = SCIFA_ORER; - sci_port->sampling_rate_mask = SCI_SR(16); + sci_port->sampling_rate_mask = SCI_SR_SCIFAB; break; case PORT_SCIF: port->fifosize = 16; -- cgit v1.2.3 From ba47f97a18f2f9c517131fcdaceb3b5a4811dc19 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Mon, 4 Jan 2016 15:54:46 +0800 Subject: serial: core: remove baud_rates when serial console setup Currently, when tring to set up a serial console with a higher baud rate, it would fallback to 921600. Tested-by: Jianqun Xu Signed-off-by: Jeffy Chen Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 33 ++------------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 85829f8568e7..a126a603b083 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1875,26 +1875,6 @@ uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow) } EXPORT_SYMBOL_GPL(uart_parse_options); -struct baud_rates { - unsigned int rate; - unsigned int cflag; -}; - -static const struct baud_rates baud_rates[] = { - { 921600, B921600 }, - { 460800, B460800 }, - { 230400, B230400 }, - { 115200, B115200 }, - { 57600, B57600 }, - { 38400, B38400 }, - { 19200, B19200 }, - { 9600, B9600 }, - { 4800, B4800 }, - { 2400, B2400 }, - { 1200, B1200 }, - { 0, B38400 } -}; - /** * uart_set_options - setup the serial console parameters * @port: pointer to the serial ports uart_port structure @@ -1910,7 +1890,6 @@ uart_set_options(struct uart_port *port, struct console *co, { struct ktermios termios; static struct ktermios dummy; - int i; /* * Ensure that the serial console lock is initialised @@ -1925,16 +1904,8 @@ uart_set_options(struct uart_port *port, struct console *co, memset(&termios, 0, sizeof(struct ktermios)); - termios.c_cflag = CREAD | HUPCL | CLOCAL; - - /* - * Construct a cflag setting. - */ - for (i = 0; baud_rates[i].rate; i++) - if (baud_rates[i].rate <= baud) - break; - - termios.c_cflag |= baud_rates[i].cflag; + termios.c_cflag |= CREAD | HUPCL | CLOCAL; + tty_termios_encode_baud_rate(&termios, baud, baud); if (bits == 7) termios.c_cflag |= CS7; -- cgit v1.2.3 From cafe1ac6402395eb990c936204ff0760af963633 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 7 Jan 2016 13:28:32 -0500 Subject: drivers/tty: make serial 8250_ingenic.c explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/tty/serial/8250/Kconfig:config SERIAL_8250_INGENIC drivers/tty/serial/8250/Kconfig: bool "Support for Ingenic SoC serial ports" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Greg Kroah-Hartman Cc: Jiri Slaby Cc: Matt Redfearn Cc: Masahiro Yamada Cc: Paul Burton Cc: Peter Hurley Cc: linux-serial@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_ingenic.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c index d6e1ec9b4fde..47824887b63f 100644 --- a/drivers/tty/serial/8250/8250_ingenic.c +++ b/drivers/tty/serial/8250/8250_ingenic.c @@ -4,6 +4,8 @@ * * Ingenic SoC UART support * + * Author: Paul Burton + * * 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 @@ -18,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -297,16 +299,6 @@ out: return err; } -static int ingenic_uart_remove(struct platform_device *pdev) -{ - struct ingenic_uart_data *data = platform_get_drvdata(pdev); - - serial8250_unregister_port(data->line); - clk_disable_unprepare(data->clk_module); - clk_disable_unprepare(data->clk_baud); - return 0; -} - static const struct ingenic_uart_config jz4740_uart_config = { .tx_loadsz = 8, .fifosize = 16, @@ -329,19 +321,13 @@ static const struct of_device_id of_match[] = { { .compatible = "ingenic,jz4780-uart", .data = &jz4780_uart_config }, { /* sentinel */ } }; -MODULE_DEVICE_TABLE(of, of_match); static struct platform_driver ingenic_uart_platform_driver = { .driver = { - .name = "ingenic-uart", - .of_match_table = of_match, + .name = "ingenic-uart", + .of_match_table = of_match, + .suppress_bind_attrs = true, }, .probe = ingenic_uart_probe, - .remove = ingenic_uart_remove, }; - -module_platform_driver(ingenic_uart_platform_driver); - -MODULE_AUTHOR("Paul Burton"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Ingenic SoC UART driver"); +builtin_platform_driver(ingenic_uart_platform_driver); -- cgit v1.2.3 From 7cdcc29e4919dc31f494eaf05e46005c28efe832 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 8 Jan 2016 15:34:05 -0500 Subject: serial-uartlite: add earlycon support Microblaze currently uses the old earlyprintk system, rather than the unified earlycon support, to show boot messages on uartlite. Add earlycon support so that other archs using uartlite can benefit from it. The new code in uartlite.c is copied almost verbatim from arch/microblaze/kernel/early_printk.c. Signed-off-by: Rich Felker Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 1 + drivers/tty/serial/uartlite.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 54b6f2c15f72..bdbe1c533c6a 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -610,6 +610,7 @@ config SERIAL_UARTLITE_CONSOLE bool "Support for console on Xilinx uartlite serial port" depends on SERIAL_UARTLITE=y select SERIAL_CORE_CONSOLE + select SERIAL_EARLYCON help Say Y here if you wish to use a Xilinx uartlite as the system console (the system console is the device which receives all kernel diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index b1c6bd3d483f..c249aee887d2 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -519,6 +519,47 @@ static int __init ulite_console_init(void) console_initcall(ulite_console_init); +static void early_uartlite_putc(struct uart_port *port, int c) +{ + /* + * Limit how many times we'll spin waiting for TX FIFO status. + * This will prevent lockups if the base address is incorrectly + * set, or any other issue on the UARTLITE. + * This limit is pretty arbitrary, unless we are at about 10 baud + * we'll never timeout on a working UART. + */ + + unsigned retries = 1000000; + /* read status bit - 0x8 offset */ + while (--retries && (readl(port->membase + 8) & (1 << 3))) + ; + + /* Only attempt the iowrite if we didn't timeout */ + /* write to TX_FIFO - 0x4 offset */ + if (retries) + writel(c & 0xff, port->membase + 4); +} + +static void early_uartlite_write(struct console *console, + const char *s, unsigned n) +{ + struct earlycon_device *device = console->data; + uart_console_write(&device->port, s, n, early_uartlite_putc); +} + +static int __init early_uartlite_setup(struct earlycon_device *device, + const char *options) +{ + if (!device->port.membase) + return -ENODEV; + + device->con->write = early_uartlite_write; + return 0; +} +EARLYCON_DECLARE(uartlite, early_uartlite_setup); +OF_EARLYCON_DECLARE(uartlite_b, "xlnx,opb-uartlite-1.00.b", early_uartlite_setup); +OF_EARLYCON_DECLARE(uartlite_a, "xlnx,xps-uartlite-1.00.a", early_uartlite_setup); + #endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */ static struct uart_driver ulite_uart_driver = { -- cgit v1.2.3 From 9e370d2c9f59a63dda0ced3ecd1b55498d97c449 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 8 Jan 2016 15:33:50 -0500 Subject: serial-uartlite: fix missing locking in isr The uartlite driver suffers from missing/duplicate/corrupted character data when the interrupt handler runs concurrently with access to the device from another cpu. Take the port spinlock to exclude concurrent access. Signed-off-by: Rich Felker Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/uartlite.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index c249aee887d2..ee2e8efdea4a 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -194,7 +194,9 @@ static irqreturn_t ulite_isr(int irq, void *dev_id) { struct uart_port *port = dev_id; int busy, n = 0; + unsigned long flags; + spin_lock_irqsave(&port->lock, flags); do { int stat = uart_in32(ULITE_STATUS, port); busy = ulite_receive(port, stat); @@ -202,6 +204,8 @@ static irqreturn_t ulite_isr(int irq, void *dev_id) n++; } while (busy); + spin_unlock_irqrestore(&port->lock, flags); + /* work done? */ if (n > 1) { tty_flip_buffer_push(&port->state->port); -- cgit v1.2.3 From d56edd7ed0ed46a8043ee3040ededbd190818ccf Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 13 Jan 2016 23:33:59 +0100 Subject: 8250: uniphier: allow modular build with 8250 console The recently added uniphier 8250 port driver supports early console probing, and it supports being built as a module, but the combination of the two fails to link: ERROR: "early_serial8250_setup" [drivers/tty/serial/8250/8250_uniphier.ko] undefined! Given that earlycon support in a loadable module makes no sense, making that code conditional on 'MODULE' is a correct solution. Signed-off-by: Arnd Bergmann Fixes: b8d20e06eaad ("serial: 8250_uniphier: add earlycon support") Acked-by: Masahiro Yamada Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_uniphier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c index bab6b3ae2540..1b7bd26555b7 100644 --- a/drivers/tty/serial/8250/8250_uniphier.c +++ b/drivers/tty/serial/8250/8250_uniphier.c @@ -35,7 +35,7 @@ struct uniphier8250_priv { spinlock_t atomic_write_lock; }; -#ifdef CONFIG_SERIAL_8250_CONSOLE +#if defined(CONFIG_SERIAL_8250_CONSOLE) && !defined(MODULE) static int __init uniphier_early_console_setup(struct earlycon_device *device, const char *options) { -- cgit v1.2.3 From 308bbc9ab838d0ace0298268c7970ba9513e2c65 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Tue, 12 Jan 2016 15:14:46 -0800 Subject: serial: omap: Prevent DoS using unprivileged ioctl(TIOCSRS485) The omap-serial driver emulates RS485 delays using software timers, but neglects to clamp the input values from the unprivileged ioctl(TIOCSRS485). Because the software implementation busy-waits, malicious userspace could stall the cpu for ~49 days. Clamp the input values to < 100ms. Fixes: 4a0ac0f55b18 ("OMAP: add RS485 support") Cc: # 3.12+ Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index b645f9228ed7..27d3b978f16e 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1343,7 +1343,7 @@ static inline void serial_omap_add_console_port(struct uart_omap_port *up) /* Enable or disable the rs485 support */ static int -serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) +serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485) { struct uart_omap_port *up = to_uart_omap_port(port); unsigned int mode; @@ -1356,8 +1356,12 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) up->ier = 0; serial_out(up, UART_IER, 0); + /* Clamp the delays to [0, 100ms] */ + rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); + rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U); + /* store new config */ - port->rs485 = *rs485conf; + port->rs485 = *rs485; /* * Just as a precaution, only allow rs485 -- cgit v1.2.3 From b4a512b8bf7185787e291cddad3b6457b2367120 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 13 Jan 2016 21:59:23 +0100 Subject: serial/omap: mark wait_for_xmitr as __maybe_unused The wait_for_xmitr() function is only used if CONFIG_CONSOLE_POLL or CONFIG_SERIAL_OMAP_CONSOLE are set, but when both are disabled, the compiler warns about it being unused: drivers/tty/serial/omap-serial.c:1168:13: warning: 'wait_for_xmitr' defined but not used [-Wunused-func We could add more #ifdefs to work around it, but adding __maybe_unused seems nicer. Signed-off-by: Arnd Bergmann Fixes: 2172076d2399 ("serial/omap-serial: Deinline wait_for_xmitr, save 165 bytes") Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 27d3b978f16e..fa49eb1e2fa2 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1165,7 +1165,7 @@ serial_omap_type(struct uart_port *port) #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) -static void wait_for_xmitr(struct uart_omap_port *up) +static void __maybe_unused wait_for_xmitr(struct uart_omap_port *up) { unsigned int status, tmout = 10000; -- cgit v1.2.3 From 7dde55787b43a8f2b4021916db38d90c03a2ec64 Mon Sep 17 00:00:00 2001 From: Jeremy McNicoll Date: Tue, 2 Feb 2016 13:00:45 -0800 Subject: tty: Add support for PCIe WCH382 2S multi-IO card WCH382 2S board is a PCIe card with 2 DB9 COM ports detected as Serial controller: Device 1c00:3253 (rev 10) (prog-if 05 [16850]) Signed-off-by: Jeremy McNicoll Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index e71ec78fc11e..7cd6f9a90542 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1941,6 +1941,7 @@ pci_wch_ch38x_setup(struct serial_private *priv, #define PCIE_VENDOR_ID_WCH 0x1c00 #define PCIE_DEVICE_ID_WCH_CH382_2S1P 0x3250 #define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470 +#define PCIE_DEVICE_ID_WCH_CH382_2S 0x3253 #define PCI_VENDOR_ID_PERICOM 0x12D8 #define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951 @@ -2637,6 +2638,14 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .subdevice = PCI_ANY_ID, .setup = pci_wch_ch353_setup, }, + /* WCH CH382 2S card (16850 clone) */ + { + .vendor = PCIE_VENDOR_ID_WCH, + .device = PCIE_DEVICE_ID_WCH_CH382_2S, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_wch_ch38x_setup, + }, /* WCH CH382 2S1P card (16850 clone) */ { .vendor = PCIE_VENDOR_ID_WCH, @@ -2955,6 +2964,7 @@ enum pci_board_num_t { pbn_fintek_4, pbn_fintek_8, pbn_fintek_12, + pbn_wch382_2, pbn_wch384_4, pbn_pericom_PI7C9X7951, pbn_pericom_PI7C9X7952, @@ -3775,6 +3785,13 @@ static struct pciserial_board pci_boards[] = { .base_baud = 115200, .first_offset = 0x40, }, + [pbn_wch382_2] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + .first_offset = 0xC0, + }, [pbn_wch384_4] = { .flags = FL_BASE0, .num_ports = 4, @@ -5574,6 +5591,10 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_2_115200 }, + { PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH382_2S, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, pbn_wch382_2 }, + { PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH384_4S, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_wch384_4 }, -- cgit v1.2.3 From ac2b335e7149e7dd0c8dcbb2b158a17b78c480a1 Mon Sep 17 00:00:00 2001 From: Paul Mcquade Date: Sat, 17 Oct 2015 21:04:39 +0100 Subject: net: wireless: rt2x00: Fixed Spacing issues Removed empty spaces before/after parenthesis Signed-off-by: Paul McQuade Acked-by: Helmut Schaa Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt61pci.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.h b/drivers/net/wireless/ralink/rt2x00/rt61pci.h index 1442075a8382..ab8641547a1f 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt61pci.h +++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.h @@ -138,14 +138,14 @@ #define PAIRWISE_TA_TABLE_BASE 0x1a00 #define SHARED_KEY_ENTRY(__idx) \ - ( SHARED_KEY_TABLE_BASE + \ - ((__idx) * sizeof(struct hw_key_entry)) ) + (SHARED_KEY_TABLE_BASE + \ + ((__idx) * sizeof(struct hw_key_entry))) #define PAIRWISE_KEY_ENTRY(__idx) \ - ( PAIRWISE_KEY_TABLE_BASE + \ - ((__idx) * sizeof(struct hw_key_entry)) ) + (PAIRWISE_KEY_TABLE_BASE + \ + ((__idx) * sizeof(struct hw_key_entry))) #define PAIRWISE_TA_ENTRY(__idx) \ - ( PAIRWISE_TA_TABLE_BASE + \ - ((__idx) * sizeof(struct hw_pairwise_ta_entry)) ) + (PAIRWISE_TA_TABLE_BASE + \ + ((__idx) * sizeof(struct hw_pairwise_ta_entry))) struct hw_key_entry { u8 key[16]; @@ -180,7 +180,7 @@ struct hw_pairwise_ta_entry { #define HW_BEACON_BASE3 0x2f00 #define HW_BEACON_OFFSET(__index) \ - ( HW_BEACON_BASE0 + (__index * 0x0100) ) + (HW_BEACON_BASE0 + (__index * 0x0100)) /* * HOST-MCU shared memory. @@ -1287,9 +1287,9 @@ struct hw_pairwise_ta_entry { /* * DMA descriptor defines. */ -#define TXD_DESC_SIZE ( 16 * sizeof(__le32) ) -#define TXINFO_SIZE ( 6 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 16 * sizeof(__le32) ) +#define TXD_DESC_SIZE (16 * sizeof(__le32)) +#define TXINFO_SIZE (6 * sizeof(__le32)) +#define RXD_DESC_SIZE (16 * sizeof(__le32)) /* * TX descriptor format for TX, PRIO and Beacon Ring. -- cgit v1.2.3 From b2cc2dd8ebb885ad1b2ee4c5d35b40d98db211fa Mon Sep 17 00:00:00 2001 From: Paul Mcquade Date: Sat, 17 Oct 2015 22:06:43 +0100 Subject: net: wireless: rt2x00: Space issue Removed empty spaces before/after parenthesis Signed-off-by: Paul McQuade Acked-by: Helmut Schaa Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2x00.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h index 3282ddb766f4..8c679f2d668d 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h @@ -107,7 +107,7 @@ * amount of bytes needed to move the data. */ #define ALIGN_SIZE(__skb, __header) \ - ( ((unsigned long)((__skb)->data + (__header))) & 3 ) + (((unsigned long)((__skb)->data + (__header))) & 3) /* * Constants for extra TX headroom for alignment purposes. @@ -128,14 +128,14 @@ #define SLOT_TIME 20 #define SHORT_SLOT_TIME 9 #define SIFS 10 -#define PIFS ( SIFS + SLOT_TIME ) -#define SHORT_PIFS ( SIFS + SHORT_SLOT_TIME ) -#define DIFS ( PIFS + SLOT_TIME ) -#define SHORT_DIFS ( SHORT_PIFS + SHORT_SLOT_TIME ) -#define EIFS ( SIFS + DIFS + \ - GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) -#define SHORT_EIFS ( SIFS + SHORT_DIFS + \ - GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) +#define PIFS (SIFS + SLOT_TIME) +#define SHORT_PIFS (SIFS + SHORT_SLOT_TIME) +#define DIFS (PIFS + SLOT_TIME) +#define SHORT_DIFS (SHORT_PIFS + SHORT_SLOT_TIME) +#define EIFS (SIFS + DIFS + \ + GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10)) +#define SHORT_EIFS (SIFS + SHORT_DIFS + \ + GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10)) enum rt2x00_chip_intf { RT2X00_CHIP_INTF_PCI, -- cgit v1.2.3 From 5b451715e94d43fdb8f3cca67d1ec72184f294f9 Mon Sep 17 00:00:00 2001 From: Paul Mcquade Date: Sat, 17 Oct 2015 22:11:23 +0100 Subject: net: wireless: rt2x00: Space Required Space needed before open parenthesis Signed-off-by: Paul McQuade Acked-by: Helmut Schaa Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2x00debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c index 90fdb02b55e7..25ee3cb8e982 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c @@ -629,7 +629,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name, data += sprintf(data, "register\tbase\twords\twordsize\n"); #define RT2X00DEBUGFS_SPRINTF_REGISTER(__name) \ { \ - if(debug->__name.read) \ + if (debug->__name.read) \ data += sprintf(data, __stringify(__name) \ "\t%d\t%d\t%d\n", \ debug->__name.word_base, \ @@ -699,7 +699,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) #define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \ ({ \ - if(debug->__name.read) { \ + if (debug->__name.read) { \ (__intf)->__name##_off_entry = \ debugfs_create_u32(__stringify(__name) "_offset", \ S_IRUSR | S_IWUSR, \ -- cgit v1.2.3 From 1349ba02bf72caafa36a2d6878cdba340d65b2ac Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 21 Jan 2016 09:46:12 +0100 Subject: ARM: OMAP: serial: Rename DRIVER_NAME DRIVER_NAME is too generic to be used in a driver-specific platform data file. Use a name specific to the driver instead, to avoid collisions. Signed-off-by: Jean Delvare Acked-by: Tony Lindgren Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-omap2/serial.c | 2 +- drivers/tty/serial/omap-serial.c | 2 +- include/linux/platform_data/serial-omap.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index f164c6b32ce2..8e072de89fed 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -252,7 +252,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata, info = omap_serial_default_info; oh = uart->oh; - name = DRIVER_NAME; + name = OMAP_SERIAL_DRIVER_NAME; omap_up.dma_enabled = info->dma_enabled; omap_up.uartclk = OMAP24XX_BASE_BAUD * 16; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index b645f9228ed7..1401dc9cde35 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1866,7 +1866,7 @@ static struct platform_driver serial_omap_driver = { .probe = serial_omap_probe, .remove = serial_omap_remove, .driver = { - .name = DRIVER_NAME, + .name = OMAP_SERIAL_DRIVER_NAME, .pm = &serial_omap_dev_pm_ops, .of_match_table = of_match_ptr(omap_serial_of_match), }, diff --git a/include/linux/platform_data/serial-omap.h b/include/linux/platform_data/serial-omap.h index d09275f3cde3..2ba2c34ca3d3 100644 --- a/include/linux/platform_data/serial-omap.h +++ b/include/linux/platform_data/serial-omap.h @@ -21,7 +21,7 @@ #include #include -#define DRIVER_NAME "omap_uart" +#define OMAP_SERIAL_DRIVER_NAME "omap_uart" /* * Use tty device name as ttyO, [O -> OMAP] -- cgit v1.2.3 From 434ba16e86640104faf241eaf34bc4bbea9733a4 Mon Sep 17 00:00:00 2001 From: Wang Dongsheng Date: Thu, 21 Jan 2016 15:59:53 +0800 Subject: serial: 8250: of: Enable suspend/resume for 8250_of driver Suspend/resume functions should work for 8250_of driver. Signed-off-by: Wang Dongsheng Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_of.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 33021c1f7d55..c7ed3d2bc8b2 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -335,6 +335,7 @@ static struct platform_driver of_platform_serial_driver = { .driver = { .name = "of_serial", .of_match_table = of_platform_serial_table, + .pm = &of_serial_pm_ops, }, .probe = of_platform_serial_probe, .remove = of_platform_serial_remove, -- cgit v1.2.3 From bdc5f300958062a766518b81d5378f837149d5c1 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Sun, 17 Jan 2016 12:15:30 +0000 Subject: serial: bcm2835: add driver for bcm2835-aux-uart The bcm2835 SOC contains an auxiliary uart, which is very close to the ns16550 with some differences. The big difference is that the uart HW is not using an internal divider of 16 but 8, which results in an effictive baud-rate being twice the requested baud-rate. This driver handles this device correctly and handles the difference in the HW divider by scaling up the clock by a factor of 2. The approach to write a separate (wrapper) driver instead of using a multiplying clock and "ns16550" as compatibility in the device-tree has been recommended by Stephen Warren. Signed-off-by: Martin Sperl Acked-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_bcm2835aux.c | 146 ++++++++++++++++++++++++++++++ drivers/tty/serial/8250/Kconfig | 24 +++++ drivers/tty/serial/8250/Makefile | 1 + 3 files changed, 171 insertions(+) create mode 100644 drivers/tty/serial/8250/8250_bcm2835aux.c (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c new file mode 100644 index 000000000000..ecf89f13a13b --- /dev/null +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -0,0 +1,146 @@ +/* + * Serial port driver for BCM2835AUX UART + * + * Copyright (C) 2016 Martin Sperl + * + * Based on 8250_lpc18xx.c: + * Copyright (C) 2015 Joachim Eastwood + * + * 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 +#include +#include +#include +#include + +#include "8250.h" + +struct bcm2835aux_data { + struct uart_8250_port uart; + struct clk *clk; + int line; +}; + +static int bcm2835aux_serial_probe(struct platform_device *pdev) +{ + struct bcm2835aux_data *data; + struct resource *res; + int ret; + + /* allocate the custom structure */ + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* initialize data */ + spin_lock_init(&data->uart.port.lock); + data->uart.capabilities = UART_CAP_FIFO; + data->uart.port.dev = &pdev->dev; + data->uart.port.regshift = 2; + data->uart.port.type = PORT_16550; + data->uart.port.iotype = UPIO_MEM; + data->uart.port.fifosize = 8; + data->uart.port.flags = UPF_SHARE_IRQ | + UPF_FIXED_PORT | + UPF_FIXED_TYPE | + UPF_SKIP_TEST; + + /* get the clock - this also enables the HW */ + data->clk = devm_clk_get(&pdev->dev, NULL); + ret = PTR_ERR_OR_ZERO(data->clk); + if (ret) { + dev_err(&pdev->dev, "could not get clk: %d\n", ret); + return ret; + } + + /* get the interrupt */ + data->uart.port.irq = platform_get_irq(pdev, 0); + if (data->uart.port.irq < 0) { + dev_err(&pdev->dev, "irq not found - %i", + data->uart.port.irq); + return data->uart.port.irq; + } + + /* map the main registers */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "memory resource not found"); + return -EINVAL; + } + data->uart.port.membase = devm_ioremap_resource(&pdev->dev, res); + ret = PTR_ERR_OR_ZERO(data->uart.port.membase); + if (ret) + return ret; + + /* Check for a fixed line number */ + ret = of_alias_get_id(pdev->dev.of_node, "serial"); + if (ret >= 0) + data->uart.port.line = ret; + + /* enable the clock as a last step */ + ret = clk_prepare_enable(data->clk); + if (ret) { + dev_err(&pdev->dev, "unable to enable uart clock - %d\n", + ret); + return ret; + } + + /* the HW-clock divider for bcm2835aux is 8, + * but 8250 expects a divider of 16, + * so we have to multiply the actual clock by 2 + * to get identical baudrates. + */ + data->uart.port.uartclk = clk_get_rate(data->clk) * 2; + + /* register the port */ + ret = serial8250_register_8250_port(&data->uart); + if (ret < 0) { + dev_err(&pdev->dev, "unable to register 8250 port - %d\n", + ret); + goto dis_clk; + } + data->line = ret; + + platform_set_drvdata(pdev, data); + + return 0; + +dis_clk: + clk_disable_unprepare(data->clk); + return ret; +} + +static int bcm2835aux_serial_remove(struct platform_device *pdev) +{ + struct bcm2835aux_data *data = platform_get_drvdata(pdev); + + serial8250_unregister_port(data->uart.port.line); + clk_disable_unprepare(data->clk); + + return 0; +} + +static const struct of_device_id bcm2835aux_serial_match[] = { + { .compatible = "brcm,bcm2835-aux-uart" }, + { }, +}; +MODULE_DEVICE_TABLE(of, bcm2835aux_serial_match); + +static struct platform_driver bcm2835aux_serial_driver = { + .driver = { + .name = "bcm2835-aux-uart", + .of_match_table = bcm2835aux_serial_match, + }, + .probe = bcm2835aux_serial_probe, + .remove = bcm2835aux_serial_remove, +}; +module_platform_driver(bcm2835aux_serial_driver); + +MODULE_DESCRIPTION("BCM2835 auxiliar UART driver"); +MODULE_AUTHOR("Martin Sperl "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index b03cb5175113..67ad6b0d595b 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -272,6 +272,30 @@ config SERIAL_8250_ACORN system, say Y to this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N. +config SERIAL_8250_BCM2835AUX + tristate "BCM2835 auxiliar mini UART support" + depends on ARCH_BCM2835 || COMPILE_TEST + depends on SERIAL_8250 && SERIAL_8250_SHARE_IRQ + help + Support for the BCM2835 auxiliar mini UART. + + Features and limitations of the UART are + Registers are similar to 16650 registers, + set bits in the control registers that are unsupported + are ignored and read back as 0 + 7/8 bit operation with 1 start and 1 stop bit + 8 symbols deep fifo for rx and tx + SW controlled RTS and SW readable CTS + Clock rate derived from system clock + Uses 8 times oversampling (compared to 16 times for 16650) + Missing break detection (but break generation) + Missing framing error detection + Missing parity bit + Missing receive time-out interrupt + Missing DCD, DSR, DTR and RI signals + + If unsure, say N. + config SERIAL_8250_FSL bool depends on SERIAL_8250_CONSOLE diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index b9b9bca5b6c3..5c1869fdfd4c 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o +obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o -- cgit v1.2.3 From fff21fac75ccebacd29fc16b56a46a124359917a Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Sat, 30 Jan 2016 09:11:46 +0000 Subject: serial: zs: Fix a transmit lockup in console output Transmit interrupts are disabled and the transmit buffer drained in the course of console output so that polled transmission is possible. That however causes a lost transmit interrupt as the TxIP bit in RR3 is only set on a transmit buffer full-to-empty transition and then iff transmit interrupts are enabled at the same time. Consequently if console output disturbs a regular transmission in progress, the TxIP bit is never set again and the transmission locks up waiting for a transmit interrupt. Fix the problem by restarting transmission manually rather than waiting for a transmit interrupt that will never happen. Signed-off-by: Maciej W. Rozycki Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/zs.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/zs.c b/drivers/tty/serial/zs.c index 2b65bb7ffb8a..eeefd76a30da 100644 --- a/drivers/tty/serial/zs.c +++ b/drivers/tty/serial/zs.c @@ -1181,6 +1181,10 @@ static void zs_console_write(struct console *co, const char *s, if (txint & TxINT_ENAB) { zport->regs[1] |= TxINT_ENAB; write_zsreg(zport, R1, zport->regs[1]); + + /* Resume any transmission as the TxIP bit won't be set. */ + if (!zport->tx_stopped) + zs_raw_transmit_chars(zport); } spin_unlock_irqrestore(&scc->zlock, flags); } -- cgit v1.2.3 From 6970cd446c25a4634f03c1adf0c12c010235bf3e Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 2 Feb 2016 22:05:02 -0800 Subject: mwifiex: display right transmit packet delay drv_pkt_delay_max should be assigned non-zero value, so that packet delay can be accumulate in the right way. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/main.h | 1 + drivers/net/wireless/marvell/mwifiex/wmm.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 89a1576d0a4b..0433977c4e2f 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -298,6 +298,7 @@ struct mwifiex_tid_tbl { #define WMM_HIGHEST_PRIORITY 7 #define HIGH_PRIO_TID 7 #define LOW_PRIO_TID 0 +#define MWIFIEX_WMM_DRV_DELAY_MAX 510 struct mwifiex_wmm_desc { struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID]; diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.c b/drivers/net/wireless/marvell/mwifiex/wmm.c index 499e5a741c62..0eb246502e1d 100644 --- a/drivers/net/wireless/marvell/mwifiex/wmm.c +++ b/drivers/net/wireless/marvell/mwifiex/wmm.c @@ -438,6 +438,7 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) mwifiex_set_ba_params(priv); mwifiex_reset_11n_rx_seq_num(priv); + priv->wmm.drv_pkt_delay_max = MWIFIEX_WMM_DRV_DELAY_MAX; atomic_set(&priv->wmm.tx_pkts_queued, 0); atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); } -- cgit v1.2.3 From af05148392f50490c662dccee6c502d9fcba33e2 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 2 Feb 2016 22:05:03 -0800 Subject: mwifiex: process pcie io memory read failure case It is observed that ioread32 may fail to read pcie register in certain scenarios, this patch handles these cases. Signed-off-by: Xinming Hu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 918e04954afe..b9fe1813cc4f 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -323,6 +323,8 @@ static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data) struct pcie_service_card *card = adapter->card; *data = ioread32(card->pci_mmap1 + reg); + if (*data == 0xffffffff) + return 0xffffffff; return 0; } -- cgit v1.2.3 From 0172404d79ec37e2c7d9dc90f6876dc314dc0fe5 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 2 Feb 2016 22:05:04 -0800 Subject: mwifiex: skip firmware dump when read_regs() fails If we are not able to read registers or PCIe memory, it means PCIe device is in bad state. We will skip firmware dump in this case. Signed-off-by: Xinming Hu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index b9fe1813cc4f..a18d944c2f31 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2366,9 +2366,13 @@ mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag) { int ret, tries; u8 ctrl_data; + u32 fw_status; struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; + if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) + return RDWR_STATUS_FAILURE; + ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, FW_DUMP_HOST_READY); if (ret) { mwifiex_dbg(adapter, ERROR, -- cgit v1.2.3 From 9a86232213b9498e0c0721fc508f760e7a089e59 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 2 Feb 2016 22:05:05 -0800 Subject: mwifiex: keep original structure in decl header file memory_type_mapping strucuture did not refer to other mwifiex specific strture. A better software design method would keep it in decl header file, which does not include other mwifiex header file. Signed-off-by: Xinming Hu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/decl.h | 21 +++++++++++++++++++++ drivers/net/wireless/marvell/mwifiex/main.h | 20 -------------------- drivers/net/wireless/marvell/mwifiex/pcie.h | 1 + 3 files changed, 22 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/decl.h b/drivers/net/wireless/marvell/mwifiex/decl.h index d9c15cd36f12..c744a7030866 100644 --- a/drivers/net/wireless/marvell/mwifiex/decl.h +++ b/drivers/net/wireless/marvell/mwifiex/decl.h @@ -270,4 +270,25 @@ struct mwifiex_11h_intf_state { bool is_11h_enabled; bool is_11h_active; } __packed; + +#define MWIFIEX_FW_DUMP_IDX 0xff +#define MWIFIEX_DRV_INFO_IDX 20 +#define FW_DUMP_MAX_NAME_LEN 8 +#define FW_DUMP_HOST_READY 0xEE +#define FW_DUMP_DONE 0xFF +#define FW_DUMP_READ_DONE 0xFE + +struct memory_type_mapping { + u8 mem_name[FW_DUMP_MAX_NAME_LEN]; + u8 *mem_ptr; + u32 mem_size; + u8 done_flag; +}; + +enum rdwr_status { + RDWR_STATUS_SUCCESS = 0, + RDWR_STATUS_FAILURE = 1, + RDWR_STATUS_DONE = 2 +}; + #endif /* !_MWIFIEX_DECL_H_ */ diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 0433977c4e2f..aea7aee46cf7 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -489,26 +489,6 @@ struct mwifiex_roc_cfg { struct ieee80211_channel chan; }; -#define MWIFIEX_FW_DUMP_IDX 0xff -#define MWIFIEX_DRV_INFO_IDX 20 -#define FW_DUMP_MAX_NAME_LEN 8 -#define FW_DUMP_HOST_READY 0xEE -#define FW_DUMP_DONE 0xFF -#define FW_DUMP_READ_DONE 0xFE - -struct memory_type_mapping { - u8 mem_name[FW_DUMP_MAX_NAME_LEN]; - u8 *mem_ptr; - u32 mem_size; - u8 done_flag; -}; - -enum rdwr_status { - RDWR_STATUS_SUCCESS = 0, - RDWR_STATUS_FAILURE = 1, - RDWR_STATUS_DONE = 2 -}; - enum mwifiex_iface_work_flags { MWIFIEX_IFACE_WORK_DEVICE_DUMP, MWIFIEX_IFACE_WORK_CARD_RESET, diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index 9700ac355e55..8f190c44cb76 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -26,6 +26,7 @@ #include #include +#include "decl.h" #include "main.h" #define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin" -- cgit v1.2.3 From 50632092dfda712dec2232d6ddf75e803c397c70 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 2 Feb 2016 22:05:06 -0800 Subject: mwifiex: use an extensible framework for firmware dump solution This patch apply an extensible firmware dump framework, so that other chipset can be easily added as needed. Signed-off-by: Xinming Hu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 35 ++++++++++++----------------- drivers/net/wireless/marvell/mwifiex/pcie.h | 19 ++++++++++++++++ 2 files changed, 33 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index a18d944c2f31..c94d31e1b525 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -37,17 +37,6 @@ static struct mwifiex_if_ops pcie_ops; static struct semaphore add_remove_card_sem; -static struct memory_type_mapping mem_type_mapping_tbl[] = { - {"ITCM", NULL, 0, 0xF0}, - {"DTCM", NULL, 0, 0xF1}, - {"SQRAM", NULL, 0, 0xF2}, - {"IRAM", NULL, 0, 0xF3}, - {"APU", NULL, 0, 0xF4}, - {"CIU", NULL, 0, 0xF5}, - {"ICU", NULL, 0, 0xF6}, - {"MAC", NULL, 0, 0xF7}, -}; - static int mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, size_t size, int flags) @@ -206,6 +195,8 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev, card->pcie.blksz_fw_dl = data->blksz_fw_dl; card->pcie.tx_buf_size = data->tx_buf_size; card->pcie.can_dump_fw = data->can_dump_fw; + card->pcie.mem_type_mapping_tbl = data->mem_type_mapping_tbl; + card->pcie.num_mem_types = data->num_mem_types; card->pcie.can_ext_scan = data->can_ext_scan; } @@ -2373,7 +2364,8 @@ mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag) if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) return RDWR_STATUS_FAILURE; - ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, FW_DUMP_HOST_READY); + ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, + reg->fw_dump_host_ready); if (ret) { mwifiex_dbg(adapter, ERROR, "PCIE write err\n"); @@ -2386,11 +2378,11 @@ mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag) return RDWR_STATUS_SUCCESS; if (doneflag && ctrl_data == doneflag) return RDWR_STATUS_DONE; - if (ctrl_data != FW_DUMP_HOST_READY) { + if (ctrl_data != reg->fw_dump_host_ready) { mwifiex_dbg(adapter, WARN, "The ctrl reg was changed, re-try again!\n"); ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, - FW_DUMP_HOST_READY); + reg->fw_dump_host_ready); if (ret) { mwifiex_dbg(adapter, ERROR, "PCIE write err\n"); @@ -2418,8 +2410,9 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) if (!card->pcie.can_dump_fw) return; - for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) { - struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx]; + for (idx = 0; idx < adapter->num_mem_types; idx++) { + struct memory_type_mapping *entry = + &adapter->mem_type_mapping_tbl[idx]; if (entry->mem_ptr) { vfree(entry->mem_ptr); @@ -2440,8 +2433,8 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) /* Read the length of every memory which will dump */ for (idx = 0; idx < dump_num; idx++) { - struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx]; - + struct memory_type_mapping *entry = + &adapter->mem_type_mapping_tbl[idx]; stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); if (stat == RDWR_STATUS_FAILURE) return; @@ -2457,7 +2450,7 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) if (memory_size == 0) { mwifiex_dbg(adapter, MSG, "Firmware dump Finished!\n"); ret = mwifiex_write_reg(adapter, creg->fw_dump_ctrl, - FW_DUMP_READ_DONE); + creg->fw_dump_read_done); if (ret) { mwifiex_dbg(adapter, ERROR, "PCIE write err\n"); return; @@ -2762,8 +2755,8 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) return -1; adapter->tx_buf_size = card->pcie.tx_buf_size; - adapter->mem_type_mapping_tbl = mem_type_mapping_tbl; - adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl); + adapter->mem_type_mapping_tbl = card->pcie.mem_type_mapping_tbl; + adapter->num_mem_types = card->pcie.num_mem_types; strcpy(adapter->fw_name, card->pcie.firmware); adapter->ext_scan = card->pcie.can_ext_scan; diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index 8f190c44cb76..8bc4390f0e20 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -136,6 +136,8 @@ struct mwifiex_pcie_card_reg { u16 fw_dump_ctrl; u16 fw_dump_start; u16 fw_dump_end; + u8 fw_dump_host_ready; + u8 fw_dump_read_done; u8 msix_support; }; @@ -203,6 +205,8 @@ static const struct mwifiex_pcie_card_reg mwifiex_reg_8897 = { .fw_dump_ctrl = 0xcf4, .fw_dump_start = 0xcf8, .fw_dump_end = 0xcff, + .fw_dump_host_ready = 0xee, + .fw_dump_read_done = 0xfe, .msix_support = 0, }; @@ -238,12 +242,25 @@ static const struct mwifiex_pcie_card_reg mwifiex_reg_8997 = { .msix_support = 1, }; +static struct memory_type_mapping mem_type_mapping_tbl_w8897[] = { + {"ITCM", NULL, 0, 0xF0}, + {"DTCM", NULL, 0, 0xF1}, + {"SQRAM", NULL, 0, 0xF2}, + {"IRAM", NULL, 0, 0xF3}, + {"APU", NULL, 0, 0xF4}, + {"CIU", NULL, 0, 0xF5}, + {"ICU", NULL, 0, 0xF6}, + {"MAC", NULL, 0, 0xF7}, +}; + struct mwifiex_pcie_device { const char *firmware; const struct mwifiex_pcie_card_reg *reg; u16 blksz_fw_dl; u16 tx_buf_size; bool can_dump_fw; + struct memory_type_mapping *mem_type_mapping_tbl; + u8 num_mem_types; bool can_ext_scan; }; @@ -262,6 +279,8 @@ static const struct mwifiex_pcie_device mwifiex_pcie8897 = { .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, .can_dump_fw = true, + .mem_type_mapping_tbl = mem_type_mapping_tbl_w8897, + .num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl_w8897), .can_ext_scan = true, }; -- cgit v1.2.3 From 56486026c282983c390b264493a4619d997b86f1 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 2 Feb 2016 22:05:07 -0800 Subject: mwifiex: dynamically increase preallocated firmware dump memory size This patch increase firmware dump memory 4K each time, until meet the demand. Signed-off-by: Xinming Hu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/decl.h | 2 ++ drivers/net/wireless/marvell/mwifiex/pcie.c | 21 ++++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/decl.h b/drivers/net/wireless/marvell/mwifiex/decl.h index c744a7030866..a184f9fdfbcb 100644 --- a/drivers/net/wireless/marvell/mwifiex/decl.h +++ b/drivers/net/wireless/marvell/mwifiex/decl.h @@ -122,6 +122,8 @@ #define BLOCK_NUMBER_OFFSET 15 #define SDIO_HEADER_OFFSET 28 +#define MWIFIEX_SIZE_4K 0x4000 + enum mwifiex_bss_type { MWIFIEX_BSS_TYPE_STA = 0, MWIFIEX_BSS_TYPE_UAP = 1, diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index c94d31e1b525..a62a09b028e5 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2402,7 +2402,8 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *creg = card->pcie.reg; unsigned int reg, reg_start, reg_end; - u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0; + u8 *dbg_ptr, *end_ptr, *tmp_ptr, dump_num; + u8 idx, i, read_reg, doneflag = 0; enum rdwr_status stat; u32 memory_size; int ret; @@ -2485,11 +2486,21 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) mwifiex_read_reg_byte(adapter, reg, dbg_ptr); if (dbg_ptr < end_ptr) { dbg_ptr++; - } else { - mwifiex_dbg(adapter, ERROR, - "Allocated buf not enough\n"); - return; + continue; } + mwifiex_dbg(adapter, ERROR, + "pre-allocated buf not enough\n"); + tmp_ptr = + vzalloc(memory_size + MWIFIEX_SIZE_4K); + if (!tmp_ptr) + return; + memcpy(tmp_ptr, entry->mem_ptr, memory_size); + vfree(entry->mem_ptr); + entry->mem_ptr = tmp_ptr; + tmp_ptr = NULL; + dbg_ptr = entry->mem_ptr + memory_size; + memory_size += MWIFIEX_SIZE_4K; + end_ptr = entry->mem_ptr + memory_size; } if (stat != RDWR_STATUS_DONE) -- cgit v1.2.3 From 03f0f7cdebeb0872076817ff835ea812a62b37c6 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Tue, 2 Feb 2016 22:05:08 -0800 Subject: mwifiex: increase the priority of firmware dump message Firmware dump operation takes few seconds. Hence it's important to notify user in dmesg that firmware dump has started or completed. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index a62a09b028e5..14fe31671475 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2422,7 +2422,7 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) entry->mem_size = 0; } - mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump start ==\n"); + mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n"); /* Read the number of the memories which will dump */ stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); @@ -2512,7 +2512,7 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) break; } while (true); } - mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump end ==\n"); + mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n"); } static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter) -- cgit v1.2.3 From 11e70824e75f2cfbad9ae066ca5b29e1c361f19e Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 2 Feb 2016 22:05:09 -0800 Subject: mwifiex: firmware dump support for w8997 chipset Current firmware dump solution support w8897 chipset, this patch extend the exist framework with support for w8997 chipset. Trigger firmware dump using, cat /sys/kernel/debug/mwifiex/mlan0/device_dump, data can be obtain by cat /sys/class/devcoredump/devcd*/data > data.txt after that. Signed-off-by: Xinming Hu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/decl.h | 1 + drivers/net/wireless/marvell/mwifiex/pcie.c | 30 +++++++++++++++++++---------- drivers/net/wireless/marvell/mwifiex/pcie.h | 13 ++++++++++++- 3 files changed, 33 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/decl.h b/drivers/net/wireless/marvell/mwifiex/decl.h index a184f9fdfbcb..bec300b9c2ea 100644 --- a/drivers/net/wireless/marvell/mwifiex/decl.h +++ b/drivers/net/wireless/marvell/mwifiex/decl.h @@ -274,6 +274,7 @@ struct mwifiex_11h_intf_state { } __packed; #define MWIFIEX_FW_DUMP_IDX 0xff +#define MWIFIEX_FW_DUMP_MAX_MEMSIZE 0x160000 #define MWIFIEX_DRV_INFO_IDX 20 #define FW_DUMP_MAX_NAME_LEN 8 #define FW_DUMP_HOST_READY 0xEE diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 14fe31671475..cc072142411a 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2402,7 +2402,7 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *creg = card->pcie.reg; unsigned int reg, reg_start, reg_end; - u8 *dbg_ptr, *end_ptr, *tmp_ptr, dump_num; + u8 *dbg_ptr, *end_ptr, *tmp_ptr, fw_dump_num, dump_num; u8 idx, i, read_reg, doneflag = 0; enum rdwr_status stat; u32 memory_size; @@ -2430,22 +2430,32 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) return; reg = creg->fw_dump_start; - mwifiex_read_reg_byte(adapter, reg, &dump_num); + mwifiex_read_reg_byte(adapter, reg, &fw_dump_num); + + /* W8997 chipset firmware dump will be restore in single region*/ + if (fw_dump_num == 0) + dump_num = 1; + else + dump_num = fw_dump_num; /* Read the length of every memory which will dump */ for (idx = 0; idx < dump_num; idx++) { struct memory_type_mapping *entry = &adapter->mem_type_mapping_tbl[idx]; - stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); - if (stat == RDWR_STATUS_FAILURE) - return; - memory_size = 0; - reg = creg->fw_dump_start; - for (i = 0; i < 4; i++) { - mwifiex_read_reg_byte(adapter, reg, &read_reg); - memory_size |= (read_reg << (i * 8)); + if (fw_dump_num != 0) { + stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); + if (stat == RDWR_STATUS_FAILURE) + return; + + reg = creg->fw_dump_start; + for (i = 0; i < 4; i++) { + mwifiex_read_reg_byte(adapter, reg, &read_reg); + memory_size |= (read_reg << (i * 8)); reg++; + } + } else { + memory_size = MWIFIEX_FW_DUMP_MAX_MEMSIZE; } if (memory_size == 0) { diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index 8bc4390f0e20..29e58ce877e3 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -239,6 +239,11 @@ static const struct mwifiex_pcie_card_reg mwifiex_reg_8997 = { .ring_tx_start_ptr = MWIFIEX_BD_FLAG_TX_START_PTR, .pfu_enabled = 1, .sleep_cookie = 0, + .fw_dump_ctrl = 0xcf4, + .fw_dump_start = 0xcf8, + .fw_dump_end = 0xcff, + .fw_dump_host_ready = 0xcc, + .fw_dump_read_done = 0xdd, .msix_support = 1, }; @@ -253,6 +258,10 @@ static struct memory_type_mapping mem_type_mapping_tbl_w8897[] = { {"MAC", NULL, 0, 0xF7}, }; +static struct memory_type_mapping mem_type_mapping_tbl_w8997[] = { + {"DUMP", NULL, 0, 0xDD}, +}; + struct mwifiex_pcie_device { const char *firmware; const struct mwifiex_pcie_card_reg *reg; @@ -289,7 +298,9 @@ static const struct mwifiex_pcie_device mwifiex_pcie8997 = { .reg = &mwifiex_reg_8997, .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, - .can_dump_fw = false, + .can_dump_fw = true, + .mem_type_mapping_tbl = mem_type_mapping_tbl_w8997, + .num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl_w8997), .can_ext_scan = true, }; -- cgit v1.2.3 From 1a33e342cf35e53c08d76f2f891e48c014a5f34e Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:10 +0100 Subject: tty: serial: 8250: Fix whitespace errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes whitespace errors reported by checkpatch to increase readability. Main focus is on missing spaces after commas in function headers and macros (like foo,bar edited to foo, bar). Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_acorn.c | 2 +- drivers/tty/serial/8250/8250_hub6.c | 2 +- drivers/tty/serial/8250/8250_pci.c | 8 +++-- drivers/tty/serial/8250/8250_port.c | 2 ++ drivers/tty/serial/8250/serial_cs.c | 60 ++++++++++++++++++------------------ 5 files changed, 39 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c index 549aa07c0d27..402dfdd4940e 100644 --- a/drivers/tty/serial/8250/8250_acorn.c +++ b/drivers/tty/serial/8250/8250_acorn.c @@ -70,7 +70,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id) uart.port.regshift = 2; uart.port.dev = &ec->dev; - for (i = 0; i < info->num_ports; i ++) { + for (i = 0; i < info->num_ports; i++) { uart.port.membase = info->vaddr + type->offset[i]; uart.port.mapbase = bus_addr + type->offset[i]; diff --git a/drivers/tty/serial/8250/8250_hub6.c b/drivers/tty/serial/8250/8250_hub6.c index a5c778e83de0..27124e21eb96 100644 --- a/drivers/tty/serial/8250/8250_hub6.c +++ b/drivers/tty/serial/8250/8250_hub6.c @@ -10,7 +10,7 @@ #include #include -#define HUB6(card,port) \ +#define HUB6(card, port) \ { \ .iobase = 0x302, \ .irq = 3, \ diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index da501c1390db..3529302e5689 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1198,8 +1198,9 @@ static int pci_quatech_has_qmcr(struct uart_8250_port *port) static int pci_quatech_test(struct uart_8250_port *port) { - u8 reg; - u8 qopr = pci_quatech_rqopr(port); + u8 reg, qopr; + + qopr = pci_quatech_rqopr(port); pci_quatech_wqopr(port, qopr & QPCR_TEST_FOR1); reg = pci_quatech_rqopr(port) & 0xC0; if (reg != QPCR_TEST_GET1) @@ -1286,6 +1287,7 @@ static int pci_quatech_init(struct pci_dev *dev) unsigned long base = pci_resource_start(dev, 0); if (base) { u32 tmp; + outl(inl(base + 0x38) | 0x00002000, base + 0x38); tmp = inl(base + 0x3c); outl(tmp | 0x01000000, base + 0x3c); @@ -4487,7 +4489,7 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_2_921600 }, { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI958, - PCI_ANY_ID , PCI_ANY_ID, 0, 0, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_8_1152000 }, /* diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index c2b650aeb792..58aa5a126bc2 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1503,6 +1503,7 @@ static inline void __start_tx(struct uart_port *port) if (up->bugs & UART_BUG_TXEN) { unsigned char lsr; + lsr = serial_in(up, UART_LSR); up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; if (lsr & UART_LSR_THRE) @@ -1963,6 +1964,7 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits) /* Wait up to 1s for flow control if necessary */ if (up->port.flags & UPF_CONS_FLOW) { unsigned int tmout; + for (tmout = 1000000; tmout; tmout--) { unsigned int msr = serial_in(up, UART_MSR); up->msr_saved_flags |= msr & MSR_SAVE_FLAGS; diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index 4d180c9423ef..6d7a801a78be 100644 --- a/drivers/tty/serial/8250/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c @@ -28,7 +28,7 @@ and other provisions required by the GPL. If you do not delete the provisions above, a recipient may use your version of this file under either the MPL or the GPL. - + ======================================================================*/ #include @@ -257,7 +257,7 @@ static const struct serial_quirk quirks[] = { }; -static int serial_config(struct pcmcia_device * link); +static int serial_config(struct pcmcia_device *link); static void serial_remove(struct pcmcia_device *link) @@ -309,7 +309,7 @@ static int serial_probe(struct pcmcia_device *link) dev_dbg(&link->dev, "serial_attach()\n"); /* Create new serial device */ - info = kzalloc(sizeof (*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; info->p_dev = link; @@ -339,7 +339,7 @@ static void serial_detach(struct pcmcia_device *link) /*====================================================================*/ -static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, +static int setup_serial(struct pcmcia_device *handle, struct serial_info *info, unsigned int iobase, int irq) { struct uart_8250_port uart; @@ -600,7 +600,7 @@ static int serial_check_for_multi(struct pcmcia_device *p_dev, void *priv_data) } -static int serial_config(struct pcmcia_device * link) +static int serial_config(struct pcmcia_device *link) { struct serial_info *info = link->priv; int i; @@ -701,7 +701,7 @@ static const struct pcmcia_device_id serial_ids[] = { PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58), PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e), PCMCIA_PFC_DEVICE_PROD_ID12(1, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555), - PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064), + PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001", 0x18df0ba0, 0x831b1064), PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9), PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed), PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc), @@ -797,30 +797,30 @@ static const struct pcmcia_device_id serial_ids[] = { PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "cis/COMpad2.cis"), PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "cis/RS-COM-2P.cis"), PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "cis/GLOBETROTTER.cis"), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100 1.00.",0x19ca78af,0xf964f42b), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100",0x19ca78af,0x71d98e83), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232 1.00.",0x19ca78af,0x69fb7490), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232",0x19ca78af,0xb6bc0235), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232",0x63f2e0bd,0xb9e175d3), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232-5",0x63f2e0bd,0xfce33442), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232",0x3beb8cf2,0x171e7190), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232-5",0x3beb8cf2,0x20da4262), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF428",0x3beb8cf2,0xea5dd57d), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF500",0x3beb8cf2,0xd77255fa), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: IC232",0x3beb8cf2,0x6a709903), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: SL232",0x3beb8cf2,0x18430676), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: XL232",0x3beb8cf2,0x6f933767), - PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7), - PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41), - PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029), - PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), - PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc), - PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7), - PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41), - PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029), - PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), - PCMCIA_MFC_DEVICE_PROD_ID12(2,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), - PCMCIA_MFC_DEVICE_PROD_ID12(3,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL100 1.00.", 0x19ca78af, 0xf964f42b), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL100", 0x19ca78af, 0x71d98e83), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL232 1.00.", 0x19ca78af, 0x69fb7490), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL232", 0x19ca78af, 0xb6bc0235), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.", "SERIAL CARD: CF232", 0x63f2e0bd, 0xb9e175d3), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.", "SERIAL CARD: CF232-5", 0x63f2e0bd, 0xfce33442), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: CF232", 0x3beb8cf2, 0x171e7190), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: CF232-5", 0x3beb8cf2, 0x20da4262), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: CF428", 0x3beb8cf2, 0xea5dd57d), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: CF500", 0x3beb8cf2, 0xd77255fa), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: IC232", 0x3beb8cf2, 0x6a709903), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: SL232", 0x3beb8cf2, 0x18430676), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: XL232", 0x3beb8cf2, 0x6f933767), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "Elan", "Serial Port: CF332", 0x3beb8cf2, 0x16dc1ba7), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "Elan", "Serial Port: SL332", 0x3beb8cf2, 0x19816c41), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "Elan", "Serial Port: SL385", 0x3beb8cf2, 0x64112029), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "Elan", "Serial Port: SL432", 0x3beb8cf2, 0x1cce7ac4), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "Elan", "Serial+Parallel Port: SP230", 0x3beb8cf2, 0xdb9e58bc), + PCMCIA_MFC_DEVICE_PROD_ID12(1, "Elan", "Serial Port: CF332", 0x3beb8cf2, 0x16dc1ba7), + PCMCIA_MFC_DEVICE_PROD_ID12(1, "Elan", "Serial Port: SL332", 0x3beb8cf2, 0x19816c41), + PCMCIA_MFC_DEVICE_PROD_ID12(1, "Elan", "Serial Port: SL385", 0x3beb8cf2, 0x64112029), + PCMCIA_MFC_DEVICE_PROD_ID12(1, "Elan", "Serial Port: SL432", 0x3beb8cf2, 0x1cce7ac4), + PCMCIA_MFC_DEVICE_PROD_ID12(2, "Elan", "Serial Port: SL432", 0x3beb8cf2, 0x1cce7ac4), + PCMCIA_MFC_DEVICE_PROD_ID12(3, "Elan", "Serial Port: SL432", 0x3beb8cf2, 0x1cce7ac4), PCMCIA_DEVICE_MANF_CARD(0x0279, 0x950b), /* too generic */ /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */ -- cgit v1.2.3 From 6d7c157fc706c173b720f0bae58e7a88ccfbeb9f Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:11 +0100 Subject: tty: serial: 8250: Replace spaces with tabs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Indentation is changed to match the correct format of using tabs instead of spaces wherever possible. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Reviewed-by: Peter Hurley Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 12 ++++++------ drivers/tty/serial/8250/8250_port.c | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 3529302e5689..4186eb136f02 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -721,7 +721,7 @@ static int pci_ni8430_init(struct pci_dev *dev) */ pcibios_resource_to_bus(dev->bus, ®ion, &dev->resource[bar]); device_window = ((region.start + MITE_IOWBSR1_WIN_OFFSET) & 0xffffff00) - | MITE_IOWBSR1_WENAB | MITE_IOWBSR1_WSIZE; + | MITE_IOWBSR1_WENAB | MITE_IOWBSR1_WSIZE; writel(device_window, p + MITE_IOWBSR1); /* Set window access to go to RAMSEL IO address space */ @@ -1744,7 +1744,7 @@ xr17v35x_has_slave(struct serial_private *priv) const int dev_id = priv->dev->device; return ((dev_id == PCI_DEVICE_ID_EXAR_XR17V4358) || - (dev_id == PCI_DEVICE_ID_EXAR_XR17V8358)); + (dev_id == PCI_DEVICE_ID_EXAR_XR17V8358)); } static int @@ -1844,8 +1844,8 @@ pci_fastcom335_setup(struct serial_private *priv, static int pci_wch_ch353_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) { port->port.flags |= UPF_FIXED_TYPE; port->port.type = PORT_16550A; @@ -1854,8 +1854,8 @@ pci_wch_ch353_setup(struct serial_private *priv, static int pci_wch_ch38x_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) { port->port.flags |= UPF_FIXED_TYPE; port->port.type = PORT_16850; diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 58aa5a126bc2..a35abc19fc18 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -53,7 +53,7 @@ #define DEBUG_AUTOCONF(fmt...) do { } while (0) #endif -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) /* * Here we define the default xmit fifo size used for each type of UART. @@ -2487,7 +2487,7 @@ serial8250_get_baud_rate(struct uart_port *port, struct ktermios *termios, void serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, - struct ktermios *old) + struct ktermios *old) { struct uart_8250_port *up = up_to_u8250p(port); unsigned char cval; -- cgit v1.2.3 From f7941f508d1eabdd1046eef4182d6052d853f09c Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:12 +0100 Subject: tty: serial: 8250: Fix braces after struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes a checkpatch warning by moving an opening curly brace to its correct position. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Reviewed-by: Peter Hurley Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_hp300.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c index 2891958cd842..5e1b464b9e3b 100644 --- a/drivers/tty/serial/8250/8250_hp300.c +++ b/drivers/tty/serial/8250/8250_hp300.c @@ -24,8 +24,7 @@ #endif #ifdef CONFIG_HPAPCI -struct hp300_port -{ +struct hp300_port { struct hp300_port *next; /* next port */ int line; /* line (tty) number */ }; -- cgit v1.2.3 From 740dc2defc476e58f7b6f3f6265d196b1b744c25 Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:13 +0100 Subject: tty: serial: 8250: Fix multiline comment style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Checkpatch outputs some warnings about incorrect comment style, which is fixed by this patch. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_ingenic.c | 12 ++++++++---- drivers/tty/serial/8250/8250_pnp.c | 14 ++++++++------ drivers/tty/serial/8250/8250_port.c | 32 +++++++++++++++++--------------- drivers/tty/serial/8250/serial_cs.c | 26 +++++++++++++++++--------- 4 files changed, 50 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c index 47824887b63f..b4e1d39805b2 100644 --- a/drivers/tty/serial/8250/8250_ingenic.c +++ b/drivers/tty/serial/8250/8250_ingenic.c @@ -156,14 +156,18 @@ static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value) break; case UART_IER: - /* Enable receive timeout interrupt with the - * receive line status interrupt */ + /* + * Enable receive timeout interrupt with the receive line + * status interrupt. + */ value |= (value & 0x4) << 2; break; case UART_MCR: - /* If we have enabled modem status IRQs we should enable modem - * mode. */ + /* + * If we have enabled modem status IRQs we should enable + * modem mode. + */ ier = p->serial_in(p, UART_IER); if (ier & UART_IER_MSI) diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index f6332de4e3e3..38000d6225c3 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -357,8 +357,8 @@ static const struct pnp_device_id pnp_dev_table[] = { /* Fujitsu Wacom 1FGT Tablet PC device */ { "FUJ02E9", 0 }, /* - * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in - * disguise) + * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 + * in disguise). */ { "LTS0001", 0 }, /* Rockwell's (PORALiNK) 33600 INT PNP */ @@ -367,12 +367,14 @@ static const struct pnp_device_id pnp_dev_table[] = { { "PNPCXXX", UNKNOWN_DEV }, /* More unknown PnP modems */ { "PNPDXXX", UNKNOWN_DEV }, - /* Winbond CIR port, should not be probed. We should keep track - of it to prevent the legacy serial driver from probing it */ + /* + * Winbond CIR port, should not be probed. We should keep track of + * it to prevent the legacy serial driver from probing it. + */ { "WEC1022", CIR_PORT }, /* - * SMSC IrCC SIR/FIR port, should not be probed by serial driver - * as well so its own driver can bind to it. + * SMSC IrCC SIR/FIR port, should not be probed by serial driver as + * well so its own driver can bind to it. */ { "SMCF010", CIR_PORT }, { "", 0 } diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index a35abc19fc18..01246b8f8ca3 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -251,9 +251,11 @@ static const struct serial8250_config uart_config[] = { .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, .flags = UART_CAP_FIFO | UART_CAP_AFE, }, -/* tx_loadsz is set to 63-bytes instead of 64-bytes to implement -workaround of errata A-008006 which states that tx_loadsz should be -configured less than Maximum supported fifo bytes */ + /* + * tx_loadsz is set to 63-bytes instead of 64-bytes to implement + * workaround of errata A-008006 which states that tx_loadsz should + * be configured less than Maximum supported fifo bytes. + */ [PORT_16550A_FSL64] = { .name = "16550A_FSL64", .fifo_size = 64, @@ -2198,23 +2200,23 @@ int serial8250_do_startup(struct uart_port *port) serial8250_set_mctrl(port, port->mctrl); - /* Serial over Lan (SoL) hack: - Intel 8257x Gigabit ethernet chips have a - 16550 emulation, to be used for Serial Over Lan. - Those chips take a longer time than a normal - serial device to signalize that a transmission - data was queued. Due to that, the above test generally - fails. One solution would be to delay the reading of - iir. However, this is not reliable, since the timeout - is variable. So, let's just don't test if we receive - TX irq. This way, we'll never enable UART_BUG_TXEN. + /* + * Serial over Lan (SoL) hack: + * Intel 8257x Gigabit ethernet chips have a 16550 emulation, to be + * used for Serial Over Lan. Those chips take a longer time than a + * normal serial device to signalize that a transmission data was + * queued. Due to that, the above test generally fails. One solution + * would be to delay the reading of iir. However, this is not + * reliable, since the timeout is variable. So, let's just don't + * test if we receive TX irq. This way, we'll never enable + * UART_BUG_TXEN. */ if (up->port.flags & UPF_NO_TXEN_TEST) goto dont_test_tx_en; /* - * Do a quick test to see if we receive an - * interrupt when we enable the TX irq. + * Do a quick test to see if we receive an interrupt when we enable + * the TX irq. */ serial_port_out(port, UART_IER, UART_IER_THRI); lsr = serial_port_in(port, UART_LSR); diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index 6d7a801a78be..2b7309d2e6f7 100644 --- a/drivers/tty/serial/8250/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c @@ -441,16 +441,20 @@ static int simple_config(struct pcmcia_device *link) struct serial_info *info = link->priv; int i = -ENODEV, try; - /* First pass: look for a config entry that looks normal. - * Two tries: without IO aliases, then with aliases */ + /* + * First pass: look for a config entry that looks normal. + * Two tries: without IO aliases, then with aliases. + */ link->config_flags |= CONF_AUTO_SET_VPP; for (try = 0; try < 4; try++) if (!pcmcia_loop_config(link, simple_config_check, &try)) goto found_port; - /* Second pass: try to find an entry that isn't picky about - its base address, then try to grab any standard serial port - address, and finally try to get any free port. */ + /* + * Second pass: try to find an entry that isn't picky about + * its base address, then try to grab any standard serial port + * address, and finally try to get any free port. + */ if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL)) goto found_port; @@ -480,8 +484,10 @@ static int multi_config_check(struct pcmcia_device *p_dev, void *priv_data) if (p_dev->resource[1]->end) return -EINVAL; - /* The quad port cards have bad CIS's, so just look for a - window larger than 8 ports and assume it will be right */ + /* + * The quad port cards have bad CIS's, so just look for a + * window larger than 8 ports and assume it will be right. + */ if (p_dev->resource[0]->end <= 8) return -EINVAL; @@ -623,8 +629,10 @@ static int serial_config(struct pcmcia_device *link) break; } - /* Another check for dual-serial cards: look for either serial or - multifunction cards that ask for appropriate IO port ranges */ + /* + * Another check for dual-serial cards: look for either serial or + * multifunction cards that ask for appropriate IO port ranges. + */ if ((info->multi == 0) && (link->has_func_id) && (link->socket->pcmcia_pfc == 0) && -- cgit v1.2.3 From c2f5fde143b47136dc8f8b7a2ce65d9bf6286c12 Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:14 +0100 Subject: tty: serial: 8250: Remove else after return MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes checkpatch warnings about unnecessary else blocks after return statements. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 4186eb136f02..123319738a89 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -805,10 +805,10 @@ static int pci_netmos_9900_numports(struct pci_dev *dev) pi = (c & 0xff); - if (pi == 2) { + if (pi == 2) return 1; - } else if ((pi == 0) && - (dev->device == PCI_DEVICE_ID_NETMOS_9900)) { + + if ((pi == 0) && (dev->device == PCI_DEVICE_ID_NETMOS_9900)) { /* two possibilities: 0x30ps encodes number of parallel and * serial ports, or 0x1000 indicates *something*. This is not * immediately obvious, since the 2s1p+4s configuration seems @@ -816,12 +816,12 @@ static int pci_netmos_9900_numports(struct pci_dev *dev) * advertising the same function 3 as the 4s+2s1p config. */ sub_serports = dev->subsystem_device & 0xf; - if (sub_serports > 0) { + if (sub_serports > 0) return sub_serports; - } else { - dev_err(&dev->dev, "NetMos/Mostech serial driver ignoring port on ambiguous config.\n"); - return 0; - } + + dev_err(&dev->dev, + "NetMos/Mostech serial driver ignoring port on ambiguous config.\n"); + return 0; } moan_device("unknown NetMos/Mostech program interface", dev); -- cgit v1.2.3 From b34f9fafea371a28d7007d7d003396f655c8f60d Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:15 +0100 Subject: tty: serial: 8250: Move EXPORT_SYMBOL to function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch moves EXPORT_SYMBOL macros directly after the definition of the corresponding symbol to remove checkpatch warnings. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Reviewed-by: Peter Hurley Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 8031e428894f..3d9623824b0b 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -768,6 +768,7 @@ void serial8250_suspend_port(int line) uart_suspend_port(&serial8250_reg, port); } +EXPORT_SYMBOL(serial8250_suspend_port); /** * serial8250_resume_port - resume one serial port @@ -793,6 +794,7 @@ void serial8250_resume_port(int line) } uart_resume_port(&serial8250_reg, port); } +EXPORT_SYMBOL(serial8250_resume_port); /* * Register a set of serial devices attached to a platform device. The @@ -1172,9 +1174,6 @@ static void __exit serial8250_exit(void) module_init(serial8250_init); module_exit(serial8250_exit); -EXPORT_SYMBOL(serial8250_suspend_port); -EXPORT_SYMBOL(serial8250_resume_port); - MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Generic 8250/16x50 serial driver"); -- cgit v1.2.3 From 207c28b1c6b5216247317b1222baa777ee87e632 Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:16 +0100 Subject: tty: serial: 8250: Fix line continuation warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed checkpatch warning about an unnecessary line continuation in a multi-line variable assignment. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Reviewed-by: Peter Hurley Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_hp300.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c index 5e1b464b9e3b..cf566bbf8531 100644 --- a/drivers/tty/serial/8250/8250_hp300.c +++ b/drivers/tty/serial/8250/8250_hp300.c @@ -248,8 +248,8 @@ static int __init hp300_8250_init(void) /* Memory mapped I/O */ uart.port.iotype = UPIO_MEM; - uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \ - | UPF_BOOT_AUTOCONF; + uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ + | UPF_BOOT_AUTOCONF; /* XXX - no interrupt support yet */ uart.port.irq = 0; uart.port.uartclk = HPAPCI_BAUD_BASE * 16; -- cgit v1.2.3 From 149a44cc98cfd776b9c17fe10fb8eca12cd5212a Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:17 +0100 Subject: tty: serial: 8250: Add parentheses to macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes a checkpatch warning caused by missing parentheses in the definition of a macro. Furthermore redundant parentheses are removed in an assignment. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 2 +- drivers/tty/serial/8250/8250_pci.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 3d9623824b0b..9947d382cf97 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -691,7 +691,7 @@ static int __init univ8250_console_init(void) } console_initcall(univ8250_console_init); -#define SERIAL8250_CONSOLE &univ8250_console +#define SERIAL8250_CONSOLE (&univ8250_console) #else #define SERIAL8250_CONSOLE NULL #endif diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 123319738a89..ec8a63573fd2 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -803,7 +803,7 @@ static int pci_netmos_9900_numports(struct pci_dev *dev) unsigned int pi; unsigned short sub_serports; - pi = (c & 0xff); + pi = c & 0xff; if (pi == 2) return 1; -- cgit v1.2.3 From 90ad7c442f6e32fa74f2d5e6fd28ace110b5025a Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:18 +0100 Subject: tty: serial: 8250: Fix multi-line strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merged user-visible multi-line strings into a single line according to the Linux Kernel Coding Style, which allows user-visible strings to exceed the maximum line length of 80 characters. The main reason for this is to facilitate grepping for these strings. However, some strings were ignored in this patch, because the use of format specifiers breaks the ability to grep anyway. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 3 +-- drivers/tty/serial/8250/serial_cs.c | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 9947d382cf97..323679cd93d7 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1178,8 +1178,7 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Generic 8250/16x50 serial driver"); module_param(share_irqs, uint, 0644); -MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices" - " (unsafe)"); +MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices (unsafe)"); module_param(nr_uarts, uint, 0644); MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")"); diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index 2b7309d2e6f7..933c2688dd7e 100644 --- a/drivers/tty/serial/8250/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c @@ -533,8 +533,8 @@ static int multi_config(struct pcmcia_device *link) info->multi = 2; if (pcmcia_loop_config(link, multi_config_check_notpicky, &base2)) { - dev_warn(&link->dev, "no usable port range " - "found, giving up\n"); + dev_warn(&link->dev, + "no usable port range found, giving up\n"); return -ENODEV; } } -- cgit v1.2.3 From 9f59fbf0f22f79e11cf74fc19581726e3f118d57 Mon Sep 17 00:00:00 2001 From: Phillip Raffeck Date: Thu, 14 Jan 2016 16:08:19 +0100 Subject: tty: serial: 8250: Suitably replace printk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch replaces printk by the corresponding variant of dev_* in order to fix checkpatch warnings. If no suitable device pointer is present, the corresponding pr_* variant is used. Signed-off-by: Phillip Raffeck Signed-off-by: Anton Würfel Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 5 ++--- drivers/tty/serial/8250/8250_gsc.c | 7 ++++--- drivers/tty/serial/8250/8250_hp300.c | 20 +++++++++++--------- drivers/tty/serial/8250/8250_port.c | 3 +-- 4 files changed, 18 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 323679cd93d7..77752216de0e 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1099,9 +1099,8 @@ static int __init serial8250_init(void) serial8250_isa_init_ports(); - printk(KERN_INFO "Serial: 8250/16550 driver, " - "%d ports, IRQ sharing %sabled\n", nr_uarts, - share_irqs ? "en" : "dis"); + pr_info("Serial: 8250/16550 driver, %d ports, IRQ sharing %sabled\n", + nr_uarts, share_irqs ? "en" : "dis"); #ifdef CONFIG_SPARC ret = sunserial_register_minors(&serial8250_reg, UART_NR); diff --git a/drivers/tty/serial/8250/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c index 2e3ea1a70d7b..b1e6ae9f1ff9 100644 --- a/drivers/tty/serial/8250/8250_gsc.c +++ b/drivers/tty/serial/8250/8250_gsc.c @@ -42,7 +42,7 @@ static int __init serial_init_chip(struct parisc_device *dev) * the user what they're missing. */ if (parisc_parent(dev)->id.hw_type != HPHW_IOA) - printk(KERN_INFO + dev_info(&dev->dev, "Serial: device 0x%llx not configured.\n" "Enable support for Wax, Lasi, Asp or Dino.\n", (unsigned long long)dev->hpa.start); @@ -66,8 +66,9 @@ static int __init serial_init_chip(struct parisc_device *dev) err = serial8250_register_8250_port(&uart); if (err < 0) { - printk(KERN_WARNING - "serial8250_register_8250_port returned error %d\n", err); + dev_warn(&dev->dev, + "serial8250_register_8250_port returned error %d\n", + err); iounmap(uart.port.membase); return err; } diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c index cf566bbf8531..38166db2b824 100644 --- a/drivers/tty/serial/8250/8250_hp300.c +++ b/drivers/tty/serial/8250/8250_hp300.c @@ -110,7 +110,7 @@ int __init hp300_setup_serial_console(void) /* Check for APCI console */ if (scode == 256) { #ifdef CONFIG_HPAPCI - printk(KERN_INFO "Serial console is HP APCI 1\n"); + pr_info("Serial console is HP APCI 1\n"); port.uartclk = HPAPCI_BAUD_BASE * 16; port.mapbase = (FRODO_BASE + FRODO_APCI_OFFSET(1)); @@ -118,7 +118,7 @@ int __init hp300_setup_serial_console(void) port.regshift = 2; add_preferred_console("ttyS", port.line, "9600n8"); #else - printk(KERN_WARNING "Serial console is APCI but support is disabled (CONFIG_HPAPCI)!\n"); + pr_warn("Serial console is APCI but support is disabled (CONFIG_HPAPCI)!\n"); return 0; #endif } else { @@ -127,7 +127,7 @@ int __init hp300_setup_serial_console(void) if (!pa) return 0; - printk(KERN_INFO "Serial console is HP DCA at select code %d\n", scode); + pr_info("Serial console is HP DCA at select code %d\n", scode); port.uartclk = HPDCA_BAUD_BASE * 16; port.mapbase = (pa + UART_OFFSET); @@ -141,13 +141,13 @@ int __init hp300_setup_serial_console(void) if (DIO_ID(pa + DIO_VIRADDRBASE) & 0x80) add_preferred_console("ttyS", port.line, "9600n8"); #else - printk(KERN_WARNING "Serial console is DCA but support is disabled (CONFIG_HPDCA)!\n"); + pr_warn("Serial console is DCA but support is disabled (CONFIG_HPDCA)!\n"); return 0; #endif } if (early_serial_setup(&port) < 0) - printk(KERN_WARNING "hp300_setup_serial_console(): early_serial_setup() failed.\n"); + pr_warn("%s: early_serial_setup() failed.\n", __func__); return 0; } #endif /* CONFIG_SERIAL_8250_CONSOLE */ @@ -179,8 +179,9 @@ static int hpdca_init_one(struct dio_dev *d, line = serial8250_register_8250_port(&uart); if (line < 0) { - printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d" - " irq %d failed\n", d->scode, uart.port.irq); + dev_notice(&d->dev, + "8250_hp300: register_serial() DCA scode %d irq %d failed\n", + d->scode, uart.port.irq); return -ENOMEM; } @@ -260,8 +261,9 @@ static int __init hp300_8250_init(void) line = serial8250_register_8250_port(&uart); if (line < 0) { - printk(KERN_NOTICE "8250_hp300: register_serial() APCI" - " %d irq %d failed\n", i, uart.port.irq); + dev_notice(uart.port.dev, + "8250_hp300: register_serial() APCI %d irq %d failed\n", + i, uart.port.irq); kfree(port); continue; } diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 01246b8f8ca3..dbf08076093c 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1316,8 +1316,7 @@ static void autoconfig(struct uart_8250_port *up) out_lock: spin_unlock_irqrestore(&port->lock, flags); if (up->capabilities != old_capabilities) { - printk(KERN_WARNING - "ttyS%d: detected caps %08x should be %08x\n", + pr_warn("ttyS%d: detected caps %08x should be %08x\n", serial_index(port), old_capabilities, up->capabilities); } -- cgit v1.2.3 From 952773b52b5ef8d6ea4ecbe37424b53d4f0c4704 Mon Sep 17 00:00:00 2001 From: Phillip Raffeck Date: Thu, 14 Jan 2016 16:08:20 +0100 Subject: tty: serial: 8250: Remove SERIAL_DEBUG_PNP macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch removes the macro SERIAL_DEBUG_PNP, which is used to enable debugging at compile time. As SERIAL_DEBUG_PNP is an orphan, the corresponding #ifdef is removed. To keep the ability to enable debugging at compile time, the call to printk(KERN_DEBUG ...) is replaced by a corresponding call to dev_dbg(), which is configurable via CONFIG_DYNAMIC_DEBUG. Signed-off-by: Phillip Raffeck Signed-off-by: Anton Würfel Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pnp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index 38000d6225c3..cad40ff8d641 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -464,11 +464,11 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) } else return -ENODEV; -#ifdef SERIAL_DEBUG_PNP - printk(KERN_DEBUG - "Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n", - uart.port.iobase, uart.port.mapbase, uart.port.irq, uart.port.iotype); -#endif + dev_dbg(&dev->dev, + "Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n", + uart.port.iobase, uart.port.mapbase, + uart.port.irq, uart.port.iotype); + if (flags & CIR_PORT) { uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; uart.port.type = PORT_8250_CIR; -- cgit v1.2.3 From 9faef1cb33d4cc17ae4e85de67aa242eebb64102 Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:21 +0100 Subject: tty: serial: 8250: Correct conversion specifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes compiler warnings about wrong conversion specifiers used in a debug output in 8250_pnp.c. The precise warning is: drivers/tty/serial/8250/8250_pnp.c: In function ‘serial_pnp_probe’: include/linux/dynamic_debug.h:64:16: warning: format ‘%x’ expects argument of [...] drivers/tty/serial/8250/8250_pnp.c:467:2: note: in expansion of macro ‘dev_dbg’ dev_dbg(&dev->dev, ^ include/linux/dynamic_debug.h:64:16: warning: format ‘%lx’ expects argument of [...] drivers/tty/serial/8250/8250_pnp.c:467:2: note: in expansion of macro ‘dev_dbg’ dev_dbg(&dev->dev, ^ Those warnings never got triggered, because the command was nested in an #ifdef, which is removed by a patch of this series. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pnp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index cad40ff8d641..e6bd21967c27 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -465,8 +465,8 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) return -ENODEV; dev_dbg(&dev->dev, - "Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n", - uart.port.iobase, uart.port.mapbase, + "Setup PNP port: port %lx, mem %pa, irq %d, type %d\n", + uart.port.iobase, &uart.port.mapbase, uart.port.irq, uart.port.iotype); if (flags & CIR_PORT) { -- cgit v1.2.3 From 829b0000242e3d2729972a034209afdd2b004456 Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:22 +0100 Subject: tty: serial: 8250: Merge duplicate conditions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch refactors a switch case statement by merging an if condition in the default case into an identical condition right after the switch statement. This comes with a slight change in behaviour: If pci_netmos_9900_numports returns 0, an additional warning is printed. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index ec8a63573fd2..4b1c241e6f75 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -850,13 +850,13 @@ static int pci_netmos_init(struct pci_dev *dev) break; default: - if (num_serial == 0 ) { - moan_device("unknown NetMos/Mostech device", dev); - } + break; } - if (num_serial == 0) + if (num_serial == 0) { + moan_device("unknown NetMos/Mostech device", dev); return -ENODEV; + } return num_serial; } -- cgit v1.2.3 From b3d67936bf1926ae53e969fb4bab4516cdaa9333 Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:23 +0100 Subject: tty: serial: 8250: Fix indentation warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Checkpatch complains about incorrect indentation of switch/case statements. This patch fixes the corresponding warnings. Additionally some indentation is changed to match the correct format specified in the Linux Kernel Coding Style. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 16 ++++++++-------- drivers/tty/serial/8250/8250_pnp.c | 4 ++-- drivers/tty/serial/8250/8250_port.c | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 4b1c241e6f75..1e7beaa20be5 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -842,15 +842,15 @@ static int pci_netmos_init(struct pci_dev *dev) return 0; switch (dev->device) { /* FALLTHROUGH on all */ - case PCI_DEVICE_ID_NETMOS_9904: - case PCI_DEVICE_ID_NETMOS_9912: - case PCI_DEVICE_ID_NETMOS_9922: - case PCI_DEVICE_ID_NETMOS_9900: - num_serial = pci_netmos_9900_numports(dev); - break; + case PCI_DEVICE_ID_NETMOS_9904: + case PCI_DEVICE_ID_NETMOS_9912: + case PCI_DEVICE_ID_NETMOS_9922: + case PCI_DEVICE_ID_NETMOS_9900: + num_serial = pci_netmos_9900_numports(dev); + break; - default: - break; + default: + break; } if (num_serial == 0) { diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index e6bd21967c27..34f05ed78b68 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -427,8 +427,8 @@ static bool check_resources(struct pnp_dev *dev) static int serial_pnp_guess_board(struct pnp_dev *dev) { if (!(check_name(pnp_dev_name(dev)) || - (dev->card && check_name(dev->card->name)))) - return -ENODEV; + (dev->card && check_name(dev->card->name)))) + return -ENODEV; if (check_resources(dev)) return 0; diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index dbf08076093c..e376cfaf8ab7 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2469,9 +2469,9 @@ static void serial8250_set_divisor(struct uart_port *port, unsigned int baud, serial_port_out(port, 0x2, quot_frac); } -static unsigned int -serial8250_get_baud_rate(struct uart_port *port, struct ktermios *termios, - struct ktermios *old) +static unsigned int serial8250_get_baud_rate(struct uart_port *port, + struct ktermios *termios, + struct ktermios *old) { unsigned int tolerance = port->uartclk / 100; -- cgit v1.2.3 From b3bd666807d98d8ea53e578307979f6424175612 Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:24 +0100 Subject: tty: serial: 8250: Add generic port init macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch removes redundant 8250 port initialization macros and replaces them by a single generic base-macro, which is specialized as needed. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.h | 12 ++++++++ drivers/tty/serial/8250/8250_accent.c | 13 ++------- drivers/tty/serial/8250/8250_boca.c | 41 ++++++++++++---------------- drivers/tty/serial/8250/8250_exar_st16c554.c | 17 ++++-------- drivers/tty/serial/8250/8250_fourport.c | 28 ++++++++----------- 5 files changed, 49 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index ce587c03efc3..047a7ba6796a 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -92,6 +92,18 @@ struct serial8250_config { #define SERIAL8250_SHARE_IRQS 0 #endif +#define SERIAL8250_PORT_FLAGS(_base, _irq, _flags) \ + { \ + .iobase = _base, \ + .irq = _irq, \ + .uartclk = 1843200, \ + .iotype = UPIO_PORT, \ + .flags = UPF_BOOT_AUTOCONF | (_flags), \ + } + +#define SERIAL8250_PORT(_base, _irq) SERIAL8250_PORT_FLAGS(_base, _irq, 0) + + static inline int serial_in(struct uart_8250_port *up, int offset) { return up->port.serial_in(&up->port, offset); diff --git a/drivers/tty/serial/8250/8250_accent.c b/drivers/tty/serial/8250/8250_accent.c index 34b51c651192..522aeae05192 100644 --- a/drivers/tty/serial/8250/8250_accent.c +++ b/drivers/tty/serial/8250/8250_accent.c @@ -10,18 +10,11 @@ #include #include -#define PORT(_base,_irq) \ - { \ - .iobase = _base, \ - .irq = _irq, \ - .uartclk = 1843200, \ - .iotype = UPIO_PORT, \ - .flags = UPF_BOOT_AUTOCONF, \ - } +#include "8250.h" static struct plat_serial8250_port accent_data[] = { - PORT(0x330, 4), - PORT(0x338, 4), + SERIAL8250_PORT(0x330, 4), + SERIAL8250_PORT(0x338, 4), { }, }; diff --git a/drivers/tty/serial/8250/8250_boca.c b/drivers/tty/serial/8250/8250_boca.c index d125dc107985..a63b5998e383 100644 --- a/drivers/tty/serial/8250/8250_boca.c +++ b/drivers/tty/serial/8250/8250_boca.c @@ -10,32 +10,25 @@ #include #include -#define PORT(_base,_irq) \ - { \ - .iobase = _base, \ - .irq = _irq, \ - .uartclk = 1843200, \ - .iotype = UPIO_PORT, \ - .flags = UPF_BOOT_AUTOCONF, \ - } +#include "8250.h" static struct plat_serial8250_port boca_data[] = { - PORT(0x100, 12), - PORT(0x108, 12), - PORT(0x110, 12), - PORT(0x118, 12), - PORT(0x120, 12), - PORT(0x128, 12), - PORT(0x130, 12), - PORT(0x138, 12), - PORT(0x140, 12), - PORT(0x148, 12), - PORT(0x150, 12), - PORT(0x158, 12), - PORT(0x160, 12), - PORT(0x168, 12), - PORT(0x170, 12), - PORT(0x178, 12), + SERIAL8250_PORT(0x100, 12), + SERIAL8250_PORT(0x108, 12), + SERIAL8250_PORT(0x110, 12), + SERIAL8250_PORT(0x118, 12), + SERIAL8250_PORT(0x120, 12), + SERIAL8250_PORT(0x128, 12), + SERIAL8250_PORT(0x130, 12), + SERIAL8250_PORT(0x138, 12), + SERIAL8250_PORT(0x140, 12), + SERIAL8250_PORT(0x148, 12), + SERIAL8250_PORT(0x150, 12), + SERIAL8250_PORT(0x158, 12), + SERIAL8250_PORT(0x160, 12), + SERIAL8250_PORT(0x168, 12), + SERIAL8250_PORT(0x170, 12), + SERIAL8250_PORT(0x178, 12), { }, }; diff --git a/drivers/tty/serial/8250/8250_exar_st16c554.c b/drivers/tty/serial/8250/8250_exar_st16c554.c index bf53aabf9b5e..3a7cb8262bb9 100644 --- a/drivers/tty/serial/8250/8250_exar_st16c554.c +++ b/drivers/tty/serial/8250/8250_exar_st16c554.c @@ -13,20 +13,13 @@ #include #include -#define PORT(_base,_irq) \ - { \ - .iobase = _base, \ - .irq = _irq, \ - .uartclk = 1843200, \ - .iotype = UPIO_PORT, \ - .flags = UPF_BOOT_AUTOCONF, \ - } +#include "8250.h" static struct plat_serial8250_port exar_data[] = { - PORT(0x100, 5), - PORT(0x108, 5), - PORT(0x110, 5), - PORT(0x118, 5), + SERIAL8250_PORT(0x100, 5), + SERIAL8250_PORT(0x108, 5), + SERIAL8250_PORT(0x110, 5), + SERIAL8250_PORT(0x118, 5), { }, }; diff --git a/drivers/tty/serial/8250/8250_fourport.c b/drivers/tty/serial/8250/8250_fourport.c index be1582609626..4045180a8cfc 100644 --- a/drivers/tty/serial/8250/8250_fourport.c +++ b/drivers/tty/serial/8250/8250_fourport.c @@ -10,24 +10,20 @@ #include #include -#define PORT(_base,_irq) \ - { \ - .iobase = _base, \ - .irq = _irq, \ - .uartclk = 1843200, \ - .iotype = UPIO_PORT, \ - .flags = UPF_BOOT_AUTOCONF | UPF_FOURPORT, \ - } +#include "8250.h" + +#define SERIAL8250_FOURPORT(_base, _irq) \ + SERIAL8250_PORT_FLAGS(_base, _irq, UPF_FOURPORT) static struct plat_serial8250_port fourport_data[] = { - PORT(0x1a0, 9), - PORT(0x1a8, 9), - PORT(0x1b0, 9), - PORT(0x1b8, 9), - PORT(0x2a0, 5), - PORT(0x2a8, 5), - PORT(0x2b0, 5), - PORT(0x2b8, 5), + SERIAL8250_FOURPORT(0x1a0, 9), + SERIAL8250_FOURPORT(0x1a8, 9), + SERIAL8250_FOURPORT(0x1b0, 9), + SERIAL8250_FOURPORT(0x1b8, 9), + SERIAL8250_FOURPORT(0x2a0, 5), + SERIAL8250_FOURPORT(0x2a8, 5), + SERIAL8250_FOURPORT(0x2b0, 5), + SERIAL8250_FOURPORT(0x2b8, 5), { }, }; -- cgit v1.2.3 From e3c5fc4d47ad2a52924d72e9945e00ec6dd2997b Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 18 Oct 2015 18:21:14 -0400 Subject: drivers/tty: make hvc/hvc_vio.c explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/tty/hvc/Kconfig:config HVC_CONSOLE drivers/tty/hvc/Kconfig: bool "pSeries Hypervisor Virtual Console support" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. We don't replace module.h with init.h since the file already has that. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. Cc: Greg Kroah-Hartman Cc: Jiri Slaby Cc: Michael Ellerman Cc: Anton Blanchard Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Paul Gortmaker Signed-off-by: Greg Kroah-Hartman --- drivers/tty/hvc/hvc_vio.c | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c index f575a9b5ede7..b05dc5086627 100644 --- a/drivers/tty/hvc/hvc_vio.c +++ b/drivers/tty/hvc/hvc_vio.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include @@ -61,7 +60,6 @@ static struct vio_device_id hvc_driver_table[] = { #endif { "", "" } }; -MODULE_DEVICE_TABLE(vio, hvc_driver_table); typedef enum hv_protocol { HV_PROTOCOL_RAW, @@ -363,26 +361,13 @@ static int hvc_vio_probe(struct vio_dev *vdev, return 0; } -static int hvc_vio_remove(struct vio_dev *vdev) -{ - struct hvc_struct *hp = dev_get_drvdata(&vdev->dev); - int rc, termno; - - termno = hp->vtermno; - rc = hvc_remove(hp); - if (rc == 0) { - if (hvterm_privs[termno] != &hvterm_priv0) - kfree(hvterm_privs[termno]); - hvterm_privs[termno] = NULL; - } - return rc; -} - static struct vio_driver hvc_vio_driver = { .id_table = hvc_driver_table, .probe = hvc_vio_probe, - .remove = hvc_vio_remove, .name = hvc_driver_name, + .driver = { + .suppress_bind_attrs = true, + }, }; static int __init hvc_vio_init(void) @@ -394,13 +379,7 @@ static int __init hvc_vio_init(void) return rc; } -module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */ - -static void __exit hvc_vio_exit(void) -{ - vio_unregister_driver(&hvc_vio_driver); -} -module_exit(hvc_vio_exit); +device_initcall(hvc_vio_init); /* after drivers/tty/hvc/hvc_console.c */ void __init hvc_vio_init_early(void) { -- cgit v1.2.3 From fc7f47bf1d0a45304809c42405f82eecfc04fd29 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 18 Oct 2015 18:21:15 -0400 Subject: drivers/tty: make ehv_bytechan.c explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/tty/Kconfig:config PPC_EPAPR_HV_BYTECHAN drivers/tty/Kconfig: bool "ePAPR hypervisor byte channel driver" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Cc: Greg Kroah-Hartman Cc: Jiri Slaby Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Paul Gortmaker Signed-off-by: Greg Kroah-Hartman --- drivers/tty/ehv_bytechan.c | 40 +++------------------------------------- 1 file changed, 3 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c index 342b36b9ad35..7ac9bcdf1e61 100644 --- a/drivers/tty/ehv_bytechan.c +++ b/drivers/tty/ehv_bytechan.c @@ -23,7 +23,6 @@ * byte channel used for the console is designated as the default tty. */ -#include #include #include #include @@ -719,19 +718,6 @@ error: return ret; } -static int ehv_bc_tty_remove(struct platform_device *pdev) -{ - struct ehv_bc_data *bc = dev_get_drvdata(&pdev->dev); - - tty_unregister_device(ehv_bc_driver, bc - bcs); - - tty_port_destroy(&bc->port); - irq_dispose_mapping(bc->tx_irq); - irq_dispose_mapping(bc->rx_irq); - - return 0; -} - static const struct of_device_id ehv_bc_tty_of_ids[] = { { .compatible = "epapr,hv-byte-channel" }, {} @@ -741,15 +727,15 @@ static struct platform_driver ehv_bc_tty_driver = { .driver = { .name = "ehv-bc", .of_match_table = ehv_bc_tty_of_ids, + .suppress_bind_attrs = true, }, .probe = ehv_bc_tty_probe, - .remove = ehv_bc_tty_remove, }; /** * ehv_bc_init - ePAPR hypervisor byte channel driver initialization * - * This function is called when this module is loaded. + * This function is called when this driver is loaded. */ static int __init ehv_bc_init(void) { @@ -814,24 +800,4 @@ error: return ret; } - - -/** - * ehv_bc_exit - ePAPR hypervisor byte channel driver termination - * - * This function is called when this driver is unloaded. - */ -static void __exit ehv_bc_exit(void) -{ - platform_driver_unregister(&ehv_bc_tty_driver); - tty_unregister_driver(ehv_bc_driver); - put_tty_driver(ehv_bc_driver); - kfree(bcs); -} - -module_init(ehv_bc_init); -module_exit(ehv_bc_exit); - -MODULE_AUTHOR("Timur Tabi "); -MODULE_DESCRIPTION("ePAPR hypervisor byte channel driver"); -MODULE_LICENSE("GPL v2"); +device_initcall(ehv_bc_init); -- cgit v1.2.3 From 1051937d465665e3360ea7d9a3d2adfd86f47dd4 Mon Sep 17 00:00:00 2001 From: Saurabh Sengar Date: Wed, 28 Oct 2015 11:56:44 +0530 Subject: tty/vt/keyboard: use memdup_user to simplify code use memdup_user rather than duplicating implementation. found by coccinelle Signed-off-by: Saurabh Sengar Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/keyboard.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 6f0336fff501..f973bfce5d08 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -1706,16 +1706,12 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm) return -EINVAL; if (ct) { - dia = kmalloc(sizeof(struct kbdiacr) * ct, - GFP_KERNEL); - if (!dia) - return -ENOMEM; - if (copy_from_user(dia, a->kbdiacr, - sizeof(struct kbdiacr) * ct)) { - kfree(dia); - return -EFAULT; - } + dia = memdup_user(a->kbdiacr, + sizeof(struct kbdiacr) * ct); + if (IS_ERR(dia)) + return PTR_ERR(dia); + } spin_lock_irqsave(&kbd_event_lock, flags); -- cgit v1.2.3 From b1209983d2c012be8d253ed118f9281ed9f46af6 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Sat, 24 Oct 2015 02:27:43 +0300 Subject: tty: synclinkmp: do not ignore errors in probe() synclinkmp_init_one() ignores all errors and does not release all resources if something fails. The patch adds returned code to device_init() and add_device() and proper error handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/synclinkmp.c | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index 4b314b63a2ed..90da0c712262 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c @@ -549,8 +549,8 @@ static int tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static int set_break(struct tty_struct *tty, int break_state); -static void add_device(SLMP_INFO *info); -static void device_init(int adapter_num, struct pci_dev *pdev); +static int add_device(SLMP_INFO *info); +static int device_init(int adapter_num, struct pci_dev *pdev); static int claim_resources(SLMP_INFO *info); static void release_resources(SLMP_INFO *info); @@ -3688,7 +3688,7 @@ static void release_resources(SLMP_INFO *info) /* Add the specified device instance data structure to the * global linked list of devices and increment the device count. */ -static void add_device(SLMP_INFO *info) +static int add_device(SLMP_INFO *info) { info->next_device = NULL; info->line = synclinkmp_device_count; @@ -3726,7 +3726,9 @@ static void add_device(SLMP_INFO *info) info->max_frame_size ); #if SYNCLINK_GENERIC_HDLC - hdlcdev_init(info); + return hdlcdev_init(info); +#else + return 0; #endif } @@ -3815,10 +3817,10 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) return info; } -static void device_init(int adapter_num, struct pci_dev *pdev) +static int device_init(int adapter_num, struct pci_dev *pdev) { SLMP_INFO *port_array[SCA_MAX_PORTS]; - int port; + int port, rc; /* allocate device instances for up to SCA_MAX_PORTS devices */ for ( port = 0; port < SCA_MAX_PORTS; ++port ) { @@ -3828,14 +3830,16 @@ static void device_init(int adapter_num, struct pci_dev *pdev) tty_port_destroy(&port_array[port]->port); kfree(port_array[port]); } - return; + return -ENOMEM; } } /* give copy of port_array to all ports and add to device list */ for ( port = 0; port < SCA_MAX_PORTS; ++port ) { memcpy(port_array[port]->port_array,port_array,sizeof(port_array)); - add_device( port_array[port] ); + rc = add_device( port_array[port] ); + if (rc) + goto err_add; spin_lock_init(&port_array[port]->lock); } @@ -3855,21 +3859,30 @@ static void device_init(int adapter_num, struct pci_dev *pdev) alloc_dma_bufs(port_array[port]); } - if ( request_irq(port_array[0]->irq_level, + rc = request_irq(port_array[0]->irq_level, synclinkmp_interrupt, port_array[0]->irq_flags, port_array[0]->device_name, - port_array[0]) < 0 ) { + port_array[0]); + if ( rc ) { printk( "%s(%d):%s Can't request interrupt, IRQ=%d\n", __FILE__,__LINE__, port_array[0]->device_name, port_array[0]->irq_level ); + goto err_irq; } - else { - port_array[0]->irq_requested = true; - adapter_test(port_array[0]); - } + port_array[0]->irq_requested = true; + adapter_test(port_array[0]); } + return 0; +err_irq: + release_resources( port_array[0] ); +err_add: + for ( port = 0; port < SCA_MAX_PORTS; ++port ) { + tty_port_destroy(&port_array[port]->port); + kfree(port_array[port]); + } + return rc; } static const struct tty_operations ops = { @@ -5584,8 +5597,7 @@ static int synclinkmp_init_one (struct pci_dev *dev, printk("error enabling pci device %p\n", dev); return -EIO; } - device_init( ++synclinkmp_adapter_count, dev ); - return 0; + return device_init( ++synclinkmp_adapter_count, dev ); } static void synclinkmp_remove_one (struct pci_dev *dev) -- cgit v1.2.3 From e9b736d88af1a143530565929390cadf036dc799 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 26 Nov 2015 19:28:26 +0100 Subject: TTY: n_hdlc, fix lockdep false positive The class of 4 n_hdls buf locks is the same because a single function n_hdlc_buf_list_init is used to init all the locks. But since flush_tx_queue takes n_hdlc->tx_buf_list.spinlock and then calls n_hdlc_buf_put which takes n_hdlc->tx_free_buf_list.spinlock, lockdep emits a warning: ============================================= [ INFO: possible recursive locking detected ] 4.3.0-25.g91e30a7-default #1 Not tainted --------------------------------------------- a.out/1248 is trying to acquire lock: (&(&list->spinlock)->rlock){......}, at: [] n_hdlc_buf_put+0x20/0x60 [n_hdlc] but task is already holding lock: (&(&list->spinlock)->rlock){......}, at: [] n_hdlc_tty_ioctl+0x127/0x1d0 [n_hdlc] other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&(&list->spinlock)->rlock); lock(&(&list->spinlock)->rlock); *** DEADLOCK *** May be due to missing lock nesting notation 2 locks held by a.out/1248: #0: (&tty->ldisc_sem){++++++}, at: [] tty_ldisc_ref_wait+0x20/0x50 #1: (&(&list->spinlock)->rlock){......}, at: [] n_hdlc_tty_ioctl+0x127/0x1d0 [n_hdlc] ... Call Trace: ... [] _raw_spin_lock_irqsave+0x50/0x70 [] n_hdlc_buf_put+0x20/0x60 [n_hdlc] [] n_hdlc_tty_ioctl+0x144/0x1d0 [n_hdlc] [] tty_ioctl+0x3f1/0xe40 ... Fix it by initializing the spin_locks separately. This removes also reduntand memset of a freshly kzallocated space. Signed-off-by: Jiri Slaby Reported-by: Dmitry Vyukov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_hdlc.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index bbc4ce66c2c1..bcaba17688f6 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -159,7 +159,6 @@ struct n_hdlc { /* * HDLC buffer list manipulation functions */ -static void n_hdlc_buf_list_init(struct n_hdlc_buf_list *list); static void n_hdlc_buf_put(struct n_hdlc_buf_list *list, struct n_hdlc_buf *buf); static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *list); @@ -853,10 +852,10 @@ static struct n_hdlc *n_hdlc_alloc(void) if (!n_hdlc) return NULL; - n_hdlc_buf_list_init(&n_hdlc->rx_free_buf_list); - n_hdlc_buf_list_init(&n_hdlc->tx_free_buf_list); - n_hdlc_buf_list_init(&n_hdlc->rx_buf_list); - n_hdlc_buf_list_init(&n_hdlc->tx_buf_list); + spin_lock_init(&n_hdlc->rx_free_buf_list.spinlock); + spin_lock_init(&n_hdlc->tx_free_buf_list.spinlock); + spin_lock_init(&n_hdlc->rx_buf_list.spinlock); + spin_lock_init(&n_hdlc->tx_buf_list.spinlock); /* allocate free rx buffer list */ for(i=0;ispinlock); -} /* end of n_hdlc_buf_list_init() */ - /** * n_hdlc_buf_put - add specified HDLC buffer to tail of specified list * @list - pointer to buffer list -- cgit v1.2.3 From 401879c57f01cbf2da204ad2e8db910525c6dbea Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 17:48:45 -0800 Subject: net: irda: Fix use-after-free in irtty_open() The N_IRDA line discipline may access the previous line discipline's closed and already-fre private data on open [1]. The tty->disc_data field _never_ refers to valid data on entry to the line discipline's open() method. Rather, the ldisc is expected to initialize that field for its own use for the lifetime of the instance (ie. from open() to close() only). [1] ================================================================== BUG: KASAN: use-after-free in irtty_open+0x422/0x550 at addr ffff8800331dd068 Read of size 4 by task a.out/13960 ============================================================================= BUG kmalloc-512 (Tainted: G B ): kasan: bad access detected ----------------------------------------------------------------------------- ... Call Trace: [] __asan_report_load4_noabort+0x3e/0x40 mm/kasan/report.c:279 [] irtty_open+0x422/0x550 drivers/net/irda/irtty-sir.c:436 [] tty_ldisc_open.isra.2+0x60/0xa0 drivers/tty/tty_ldisc.c:447 [] tty_set_ldisc+0x1a0/0x940 drivers/tty/tty_ldisc.c:567 [< inline >] tiocsetd drivers/tty/tty_io.c:2650 [] tty_ioctl+0xace/0x1fd0 drivers/tty/tty_io.c:2883 [< inline >] vfs_ioctl fs/ioctl.c:43 [] do_vfs_ioctl+0x57c/0xe60 fs/ioctl.c:607 [< inline >] SYSC_ioctl fs/ioctl.c:622 [] SyS_ioctl+0x74/0x80 fs/ioctl.c:613 [] entry_SYSCALL_64_fastpath+0x16/0x7a Reported-and-tested-by: Dmitry Vyukov Cc: Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/net/irda/irtty-sir.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 696852eb23c3..7a3f990c1935 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -430,16 +430,6 @@ static int irtty_open(struct tty_struct *tty) /* Module stuff handled via irda_ldisc.owner - Jean II */ - /* First make sure we're not already connected. */ - if (tty->disc_data != NULL) { - priv = tty->disc_data; - if (priv && priv->magic == IRTTY_MAGIC) { - ret = -EEXIST; - goto out; - } - tty->disc_data = NULL; /* ### */ - } - /* stop the underlying driver */ irtty_stop_receiver(tty, TRUE); if (tty->ops->stop) -- cgit v1.2.3 From 9b95d95d5eba5a077283423616b4ec3329d6ab00 Mon Sep 17 00:00:00 2001 From: Aya Mahfouz Date: Tue, 15 Dec 2015 01:50:19 +0200 Subject: char: constify tty_port_operations structs Constifies tty_port_operations structure in the char driver since it is not modified after its initialization. Detected and found using Coccinelle. Suggested-by: Julia Lawall Signed-off-by: Aya Mahfouz Acked-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/char/ttyprintk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index a15ce4ef39cd..b098d2d0b7c4 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -171,7 +171,7 @@ static const struct tty_operations ttyprintk_ops = { .ioctl = tpk_ioctl, }; -static struct tty_port_operations null_ops = { }; +static const struct tty_port_operations null_ops = { }; static struct tty_driver *ttyprintk_driver; -- cgit v1.2.3 From 04b757dfd26cee24bc62ed815cd87efbf10ef2fc Mon Sep 17 00:00:00 2001 From: Aya Mahfouz Date: Tue, 15 Dec 2015 01:53:36 +0200 Subject: tty: constify tty_port_operations structs Constifies tty_port_operations structures in the tty driver since they are not modified after their initialization. Detected and found using Coccinelle. Suggested-by: Julia Lawall Signed-off-by: Aya Mahfouz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/goldfish.c | 2 +- drivers/tty/mxser.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c index 0f82c0b146f6..752232c77503 100644 --- a/drivers/tty/goldfish.c +++ b/drivers/tty/goldfish.c @@ -162,7 +162,7 @@ static int goldfish_tty_console_setup(struct console *co, char *options) return 0; } -static struct tty_port_operations goldfish_port_ops = { +static const struct tty_port_operations goldfish_port_ops = { .activate = goldfish_tty_activate, .shutdown = goldfish_tty_shutdown }; diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 9a0791e523b5..2f12bb9f4336 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -2336,7 +2336,7 @@ static const struct tty_operations mxser_ops = { .get_icount = mxser_get_icount, }; -static struct tty_port_operations mxser_port_ops = { +static const struct tty_port_operations mxser_port_ops = { .carrier_raised = mxser_carrier_raised, .dtr_rts = mxser_dtr_rts, .activate = mxser_activate, -- cgit v1.2.3 From 14b04f28a0a1a5903221fc55c61d231b76abd440 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 2 Feb 2016 17:09:26 -0800 Subject: clk: gpio: Make into a platform driver clk_get() for DT based clks already returns EPROBE_DEFER when the OF clk provider is not present. So having all this code in the clk provider to return EPROBE_DEFER when the gpio isn't ready yet can be replaced with a platform driver that doesn't add the clk provider until the gpio can be requested. Get rid of the OF_CLK_DECLARE and convert this to a platform driver instead. Tested-by: Jyri Sarha Cc: Sergej Sawazki Cc: Russell King Cc: Fabio Estevam Cc: Jon Nettleton Cc: Shawn Guo Signed-off-by: Stephen Boyd --- drivers/clk/clk-gpio.c | 165 ++++++++++++++++--------------------------------- 1 file changed, 52 insertions(+), 113 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c index cbbea2985cc9..fb32a7366ef6 100644 --- a/drivers/clk/clk-gpio.c +++ b/drivers/clk/clk-gpio.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include /** * DOC: basic gpio gated clock which can be enabled and disabled @@ -199,134 +201,71 @@ struct clk *clk_register_gpio_mux(struct device *dev, const char *name, } EXPORT_SYMBOL_GPL(clk_register_gpio_mux); -#ifdef CONFIG_OF -/** - * clk_register_get() has to be delayed, because -EPROBE_DEFER - * can not be handled properly at of_clk_init() call time. - */ - -struct clk_gpio_delayed_register_data { - const char *gpio_name; - int num_parents; - const char **parent_names; - struct device_node *node; - struct mutex lock; - struct clk *clk; - struct clk *(*clk_register_get)(const char *name, - const char * const *parent_names, u8 num_parents, - unsigned gpio, bool active_low); -}; - -static struct clk *of_clk_gpio_delayed_register_get( - struct of_phandle_args *clkspec, void *_data) +static int gpio_clk_driver_probe(struct platform_device *pdev) { - struct clk_gpio_delayed_register_data *data = _data; - struct clk *clk; - int gpio; + struct device_node *node = pdev->dev.of_node; + const char **parent_names, *gpio_name; + int num_parents, gpio; enum of_gpio_flags of_flags; + struct clk *clk; + bool active_low, is_mux; + + num_parents = of_clk_get_parent_count(node); + if (num_parents < 0) + return -EINVAL; - mutex_lock(&data->lock); + if (num_parents) { + parent_names = devm_kcalloc(&pdev->dev, num_parents, + sizeof(char *), GFP_KERNEL); + if (!parent_names) + return -ENOMEM; - if (data->clk) { - mutex_unlock(&data->lock); - return data->clk; + of_clk_parent_fill(node, parent_names, num_parents); + } else { + parent_names = NULL; } - gpio = of_get_named_gpio_flags(data->node, data->gpio_name, 0, - &of_flags); + is_mux = of_device_is_compatible(node, "gpio-mux-clock"); + + gpio_name = is_mux ? "select-gpios" : "enable-gpios"; + gpio = of_get_named_gpio_flags(node, gpio_name, 0, &of_flags); if (gpio < 0) { - mutex_unlock(&data->lock); if (gpio == -EPROBE_DEFER) pr_debug("%s: %s: GPIOs not yet available, retry later\n", - data->node->name, __func__); + node->name, __func__); else pr_err("%s: %s: Can't get '%s' DT property\n", - data->node->name, __func__, - data->gpio_name); - return ERR_PTR(gpio); + node->name, __func__, + gpio_name); + return gpio; } - clk = data->clk_register_get(data->node->name, data->parent_names, - data->num_parents, gpio, of_flags & OF_GPIO_ACTIVE_LOW); - if (IS_ERR(clk)) - goto out; - - data->clk = clk; -out: - mutex_unlock(&data->lock); - - return clk; -} - -static struct clk *of_clk_gpio_gate_delayed_register_get(const char *name, - const char * const *parent_names, u8 num_parents, - unsigned gpio, bool active_low) -{ - return clk_register_gpio_gate(NULL, name, parent_names ? - parent_names[0] : NULL, gpio, active_low, 0); -} - -static struct clk *of_clk_gpio_mux_delayed_register_get(const char *name, - const char * const *parent_names, u8 num_parents, unsigned gpio, - bool active_low) -{ - return clk_register_gpio_mux(NULL, name, parent_names, num_parents, - gpio, active_low, 0); -} - -static void __init of_gpio_clk_setup(struct device_node *node, - const char *gpio_name, - struct clk *(*clk_register_get)(const char *name, - const char * const *parent_names, - u8 num_parents, - unsigned gpio, bool active_low)) -{ - struct clk_gpio_delayed_register_data *data; - const char **parent_names; - int i, num_parents; - - num_parents = of_clk_get_parent_count(node); - if (num_parents < 0) - return; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return; + active_low = of_flags & OF_GPIO_ACTIVE_LOW; - if (num_parents) { - parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL); - if (!parent_names) { - kfree(data); - return; - } - - for (i = 0; i < num_parents; i++) - parent_names[i] = of_clk_get_parent_name(node, i); - } else { - parent_names = NULL; - } - - data->num_parents = num_parents; - data->parent_names = parent_names; - data->node = node; - data->gpio_name = gpio_name; - data->clk_register_get = clk_register_get; - mutex_init(&data->lock); + if (is_mux) + clk = clk_register_gpio_mux(&pdev->dev, node->name, + parent_names, num_parents, gpio, active_low, 0); + else + clk = clk_register_gpio_gate(&pdev->dev, node->name, + parent_names ? parent_names[0] : NULL, gpio, + active_low, 0); + if (IS_ERR(clk)) + return PTR_ERR(clk); - of_clk_add_provider(node, of_clk_gpio_delayed_register_get, data); + return of_clk_add_provider(node, of_clk_src_simple_get, clk); } -static void __init of_gpio_gate_clk_setup(struct device_node *node) -{ - of_gpio_clk_setup(node, "enable-gpios", - of_clk_gpio_gate_delayed_register_get); -} -CLK_OF_DECLARE(gpio_gate_clk, "gpio-gate-clock", of_gpio_gate_clk_setup); +static const struct of_device_id gpio_clk_match_table[] = { + { .compatible = "gpio-mux-clock" }, + { .compatible = "gpio-gate-clock" }, + { } +}; -void __init of_gpio_mux_clk_setup(struct device_node *node) -{ - of_gpio_clk_setup(node, "select-gpios", - of_clk_gpio_mux_delayed_register_get); -} -CLK_OF_DECLARE(gpio_mux_clk, "gpio-mux-clock", of_gpio_mux_clk_setup); -#endif +static struct platform_driver gpio_clk_driver = { + .probe = gpio_clk_driver_probe, + .driver = { + .name = "gpio-clk", + .of_match_table = gpio_clk_match_table, + }, +}; +builtin_platform_driver(gpio_clk_driver); -- cgit v1.2.3 From 47b0eeb3dc8a01848ad62908000b1051d1833eaf Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 2 Feb 2016 17:24:56 -0800 Subject: clk: Deprecate CLK_IS_ROOT We don't use CLK_IS_ROOT but in a few places in the common clk framework core. Let's replace those checks with a check for the number of parents a clk has instead of the flag, freeing up one flag for something else. We don't remove the flag yet so that things keep building, but we'll remove it once all drivers have removed their flag usage. Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 6 +++--- include/linux/clk-provider.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index bb01ed6cc63e..cd8382c83f48 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -385,7 +385,7 @@ static unsigned long clk_core_get_rate_nolock(struct clk_core *core) ret = core->rate; - if (core->flags & CLK_IS_ROOT) + if (!core->num_parents) goto out; if (!core->parent) @@ -2351,7 +2351,7 @@ static int __clk_core_init(struct clk_core *core) /* * Populate core->parent if parent has already been __clk_init'd. If * parent has not yet been __clk_init'd then place clk in the orphan - * list. If clk has set the CLK_IS_ROOT flag then place it in the root + * list. If clk doesn't have any parents then place it in the root * clk list. * * Every time a new clk is clk_init'd then we walk the list of orphan @@ -2362,7 +2362,7 @@ static int __clk_core_init(struct clk_core *core) hlist_add_head(&core->child_node, &core->parent->children); core->orphan = core->parent->orphan; - } else if (core->flags & CLK_IS_ROOT) { + } else if (!core->num_parents) { hlist_add_head(&core->child_node, &clk_root_list); core->orphan = false; } else { diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index fabe5bedbba6..9c3a18c1a984 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -25,7 +25,7 @@ #define CLK_SET_PARENT_GATE BIT(1) /* must be gated across re-parent */ #define CLK_SET_RATE_PARENT BIT(2) /* propagate rate change up one level */ #define CLK_IGNORE_UNUSED BIT(3) /* do not gate even if unused */ -#define CLK_IS_ROOT BIT(4) /* root clk, has no parent */ +#define CLK_IS_ROOT BIT(4) /* Deprecated: Don't use */ #define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */ #define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */ #define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */ -- cgit v1.2.3 From a4f642a8a3c2838ad09fe8313d45db46600e1478 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 22:54:56 +0100 Subject: tty: nozomi: avoid a harmless gcc warning The nozomi wireless data driver has its own helper function to transfer data from a FIFO, doing an extra byte swap on big-endian architectures, presumably to bring the data back into byte-serial order after readw() or readl() perform their implicit byteswap. This helper function is used in the receive_data() function to first read the length into a 32-bit variable, which causes a compile-time warning: drivers/tty/nozomi.c: In function 'receive_data': drivers/tty/nozomi.c:857:9: warning: 'size' may be used uninitialized in this function [-Wmaybe-uninitialized] The problem is that gcc is unsure whether the data was actually read or not. We know that it is at this point, so we can replace it with a single readl() to shut up that warning. I am leaving the byteswap in there, to preserve the existing behavior, even though this seems fishy: Reading the length of the data into a cpu-endian variable should normally not use a second byteswap on big-endian systems, unless the hardware is aware of the CPU endianess. There appears to be a lot more confusion about endianess in this driver, so it probably has not worked on big-endian systems in a long time, if ever, and I have no way to test it. It's well possible that this driver has not been used by anyone in a while, the last patch that looks like it was tested on the hardware is from 2008. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/nozomi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c index 80f9de907563..5cc80b80c82b 100644 --- a/drivers/tty/nozomi.c +++ b/drivers/tty/nozomi.c @@ -823,7 +823,7 @@ static int receive_data(enum port_type index, struct nozomi *dc) struct tty_struct *tty = tty_port_tty_get(&port->port); int i, ret; - read_mem32((u32 *) &size, addr, 4); + size = __le32_to_cpu(readl(addr)); /* DBG1( "%d bytes port: %d", size, index); */ if (tty && test_bit(TTY_THROTTLED, &tty->flags)) { -- cgit v1.2.3 From 05ead49691d245f67bdd1b30cab5d9af522ac884 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 22:54:57 +0100 Subject: tty: cyclades: cyz_interrupt is only used for PCI When CONFIG_PCI is not set, enabling CONFIG_CYZ_INTR has no practical effect other than generating a warning about an unused function: drivers/tty/cyclades.c:1184:20: warning: 'cyz_interrupt' defined but not used [-Wunused-function] static irqreturn_t cyz_interrupt(int irq, void *dev_id) This adds a dependency to avoid that warning. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig index c01f45095877..82c4d2e45319 100644 --- a/drivers/tty/Kconfig +++ b/drivers/tty/Kconfig @@ -226,7 +226,7 @@ config CYCLADES config CYZ_INTR bool "Cyclades-Z interrupt mode operation" - depends on CYCLADES + depends on CYCLADES && PCI help The Cyclades-Z family of multiport cards allows 2 (two) driver op modes: polling and interrupt. In polling mode, the driver will check -- cgit v1.2.3 From e36ae3439936e13c33f5841c7c2c1a9875acbb6d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 22:54:58 +0100 Subject: tty: hvc_xen: hide xen_console_remove when unused xencons_disconnect_backend() is only called from xen_console_remove(), which is conditionally compiled, so we get a harmless warning when CONFIG_HVC_XEN_FRONTEND is unset: hvc/hvc_xen.c:350:12: error: 'xen_console_remove' defined but not used [-Werror=unused-function] This moves the function down into the same #ifdef section to silence the warning. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/hvc/hvc_xen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index fa816b7193b6..11725422dacb 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c @@ -323,6 +323,7 @@ void xen_console_resume(void) } } +#ifdef CONFIG_HVC_XEN_FRONTEND static void xencons_disconnect_backend(struct xencons_info *info) { if (info->irq > 0) @@ -363,7 +364,6 @@ static int xen_console_remove(struct xencons_info *info) return 0; } -#ifdef CONFIG_HVC_XEN_FRONTEND static int xencons_remove(struct xenbus_device *dev) { return xen_console_remove(dev_get_drvdata(&dev->dev)); -- cgit v1.2.3 From e882f7158f102ef148a2d96eb4cb50cc88830c87 Mon Sep 17 00:00:00 2001 From: Melchior FRANZ Date: Sun, 1 Nov 2015 19:48:18 +0100 Subject: tty: vt: initialize softcursor_original correctly add_softcursor() stores the contents of the text buffer position in this variable before drawing the softcursor, whereas hide_softcursor() writes the value back. A value of -1 means that no cursor has been drawn and therefore no character is to be restored. softcursor_original, however, is only implicitly initialized with 0. Therefore, when hide_softcursor is called for the first time (console_init -> con_init -> redraw_screen -> hide_cursor), it wrongly writes 0x0000 in the top left corner of the text buffer. Normally, this is just as black as the rest of the screen (vc_video_erase_char) and can't be seen, but it appears as a black cursor rectangle on non-black backgrounds e.g. with boot option "vt.global_cursor_default=0 vt.color=0xf0". softcursor_original needs to be initialized with -1. Signed-off-by: Melchior FRANZ Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index bd51bdd0a7bf..3e3c7575e92d 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -568,7 +568,7 @@ static void delete_char(struct vc_data *vc, unsigned int nr) vc->vc_cols - vc->vc_x); } -static int softcursor_original; +static int softcursor_original = -1; static void add_softcursor(struct vc_data *vc) { -- cgit v1.2.3 From 2831c89f42dcde440cfdccb9fee9f42d54bbc1ef Mon Sep 17 00:00:00 2001 From: "Herton R. Krzesinski" Date: Mon, 11 Jan 2016 12:07:43 -0200 Subject: pty: fix possible use after free of tty->driver_data This change fixes a bug for a corner case where we have the the last release from a pty master/slave coming from a previously opened /dev/tty file. When this happens, the tty->driver_data can be stale, due to all ptmx or pts/N files having already been closed before (and thus the inode related to these files, which tty->driver_data points to, being already freed/destroyed). The fix here is to keep a reference on the opened master ptmx inode. We maintain the inode referenced until the final pty_unix98_shutdown, and only pass this inode to devpts_kill_index. Signed-off-by: Herton R. Krzesinski Cc: # 2.6.29+ Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index b3110040164a..3b5cde833ee5 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -681,7 +681,14 @@ static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) /* this is called once with whichever end is closed last */ static void pty_unix98_shutdown(struct tty_struct *tty) { - devpts_kill_index(tty->driver_data, tty->index); + struct inode *ptmx_inode; + + if (tty->driver->subtype == PTY_TYPE_MASTER) + ptmx_inode = tty->driver_data; + else + ptmx_inode = tty->link->driver_data; + devpts_kill_index(ptmx_inode, tty->index); + iput(ptmx_inode); /* drop reference we acquired at ptmx_open */ } static const struct tty_operations ptm_unix98_ops = { @@ -773,6 +780,15 @@ static int ptmx_open(struct inode *inode, struct file *filp) set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ tty->driver_data = inode; + /* + * In the case where all references to ptmx inode are dropped and we + * still have /dev/tty opened pointing to the master/slave pair (ptmx + * is closed/released before /dev/tty), we must make sure that the inode + * is still valid when we call the final pty_unix98_shutdown, thus we + * hold an additional reference to the ptmx inode + */ + ihold(inode); + tty_add_file(tty, filp); slave_inode = devpts_pty_new(inode, -- cgit v1.2.3 From 1f55c718c290616889c04946864a13ef30f64929 Mon Sep 17 00:00:00 2001 From: "Herton R. Krzesinski" Date: Thu, 14 Jan 2016 17:56:58 -0200 Subject: pty: make sure super_block is still valid in final /dev/tty close Considering current pty code and multiple devpts instances, it's possible to umount a devpts file system while a program still has /dev/tty opened pointing to a previosuly closed pty pair in that instance. In the case all ptmx and pts/N files are closed, umount can be done. If the program closes /dev/tty after umount is done, devpts_kill_index will use now an invalid super_block, which was already destroyed in the umount operation after running ->kill_sb. This is another "use after free" type of issue, but now related to the allocated super_block instance. To avoid the problem (warning at ida_remove and potential crashes) for this specific case, I added two functions in devpts which grabs additional references to the super_block, which pty code now uses so it makes sure the super block structure is still valid until pty shutdown is done. I also moved the additional inode references to the same functions, which also covered similar case with inode being freed before /dev/tty final close/shutdown. Signed-off-by: Herton R. Krzesinski Cc: stable@vger.kernel.org # 2.6.29+ Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 9 ++++++--- fs/devpts/inode.c | 20 ++++++++++++++++++++ include/linux/devpts_fs.h | 4 ++++ 3 files changed, 30 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 3b5cde833ee5..2348fa613707 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -688,7 +688,7 @@ static void pty_unix98_shutdown(struct tty_struct *tty) else ptmx_inode = tty->link->driver_data; devpts_kill_index(ptmx_inode, tty->index); - iput(ptmx_inode); /* drop reference we acquired at ptmx_open */ + devpts_del_ref(ptmx_inode); } static const struct tty_operations ptm_unix98_ops = { @@ -785,9 +785,12 @@ static int ptmx_open(struct inode *inode, struct file *filp) * still have /dev/tty opened pointing to the master/slave pair (ptmx * is closed/released before /dev/tty), we must make sure that the inode * is still valid when we call the final pty_unix98_shutdown, thus we - * hold an additional reference to the ptmx inode + * hold an additional reference to the ptmx inode. For the same /dev/tty + * last close case, we also need to make sure the super_block isn't + * destroyed (devpts instance unmounted), before /dev/tty is closed and + * on its release devpts_kill_index is called. */ - ihold(inode); + devpts_add_ref(inode); tty_add_file(tty, filp); diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 1f107fd51328..655f21f99160 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -575,6 +575,26 @@ void devpts_kill_index(struct inode *ptmx_inode, int idx) mutex_unlock(&allocated_ptys_lock); } +/* + * pty code needs to hold extra references in case of last /dev/tty close + */ + +void devpts_add_ref(struct inode *ptmx_inode) +{ + struct super_block *sb = pts_sb_from_inode(ptmx_inode); + + atomic_inc(&sb->s_active); + ihold(ptmx_inode); +} + +void devpts_del_ref(struct inode *ptmx_inode) +{ + struct super_block *sb = pts_sb_from_inode(ptmx_inode); + + iput(ptmx_inode); + deactivate_super(sb); +} + /** * devpts_pty_new -- create a new inode in /dev/pts/ * @ptmx_inode: inode of the master diff --git a/include/linux/devpts_fs.h b/include/linux/devpts_fs.h index 251a2090a554..e0ee0b3000b2 100644 --- a/include/linux/devpts_fs.h +++ b/include/linux/devpts_fs.h @@ -19,6 +19,8 @@ int devpts_new_index(struct inode *ptmx_inode); void devpts_kill_index(struct inode *ptmx_inode, int idx); +void devpts_add_ref(struct inode *ptmx_inode); +void devpts_del_ref(struct inode *ptmx_inode); /* mknod in devpts */ struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index, void *priv); @@ -32,6 +34,8 @@ void devpts_pty_kill(struct inode *inode); /* Dummy stubs in the no-pty case */ static inline int devpts_new_index(struct inode *ptmx_inode) { return -EINVAL; } static inline void devpts_kill_index(struct inode *ptmx_inode, int idx) { } +static inline void devpts_add_ref(struct inode *ptmx_inode) { } +static inline void devpts_del_ref(struct inode *ptmx_inode) { } static inline struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index, void *priv) { -- cgit v1.2.3 From 1a8496ba409132afb3b407599061c34847de42d3 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 2 Feb 2016 18:09:14 +0100 Subject: vxlan: consolidate output route calculation The code for output route lookup is duplicated for ndo_start_xmit and ndo_fill_metadata_dst. Move it to a common function. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 77 +++++++++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 65439188c582..d0f7723fd776 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1847,6 +1847,27 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk return 0; } +static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan, + struct sk_buff *skb, int oif, u8 tos, + __be32 daddr, __be32 *saddr) +{ + struct rtable *rt = NULL; + struct flowi4 fl4; + + memset(&fl4, 0, sizeof(fl4)); + fl4.flowi4_oif = oif; + fl4.flowi4_tos = RT_TOS(tos); + fl4.flowi4_mark = skb->mark; + fl4.flowi4_proto = IPPROTO_UDP; + fl4.daddr = daddr; + fl4.saddr = vxlan->cfg.saddr.sin.sin_addr.s_addr; + + rt = ip_route_output_key(vxlan->net, &fl4); + if (!IS_ERR(rt)) + *saddr = fl4.saddr; + return rt; +} + #if IS_ENABLED(CONFIG_IPV6) static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan, struct sk_buff *skb, int oif, @@ -1928,7 +1949,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, struct sock *sk; struct rtable *rt = NULL; const struct iphdr *old_iph; - struct flowi4 fl4; union vxlan_addr *dst; union vxlan_addr remote_ip; struct vxlan_metadata _md; @@ -1995,6 +2015,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, } if (dst->sa.sa_family == AF_INET) { + __be32 saddr; + if (!vxlan->vn4_sock) goto drop; sk = vxlan->vn4_sock->sock->sk; @@ -2009,15 +2031,9 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, flags &= ~VXLAN_F_UDP_CSUM; } - memset(&fl4, 0, sizeof(fl4)); - fl4.flowi4_oif = rdst ? rdst->remote_ifindex : 0; - fl4.flowi4_tos = RT_TOS(tos); - fl4.flowi4_mark = skb->mark; - fl4.flowi4_proto = IPPROTO_UDP; - fl4.daddr = dst->sin.sin_addr.s_addr; - fl4.saddr = vxlan->cfg.saddr.sin.sin_addr.s_addr; - - rt = ip_route_output_key(vxlan->net, &fl4); + rt = vxlan_get_route(vxlan, skb, + rdst ? rdst->remote_ifindex : 0, tos, + dst->sin.sin_addr.s_addr, &saddr); if (IS_ERR(rt)) { netdev_dbg(dev, "no route to %pI4\n", &dst->sin.sin_addr.s_addr); @@ -2049,7 +2065,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, tos = ip_tunnel_ecn_encap(tos, old_iph, skb); ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); - err = vxlan_xmit_skb(rt, sk, skb, fl4.saddr, + err = vxlan_xmit_skb(rt, sk, skb, saddr, dst->sin.sin_addr.s_addr, tos, ttl, df, src_port, dst_port, htonl(vni << 8), md, !net_eq(vxlan->net, dev_net(vxlan->dev)), @@ -2390,31 +2406,6 @@ static int vxlan_change_mtu(struct net_device *dev, int new_mtu) return 0; } -static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb, - struct ip_tunnel_info *info, - __be16 sport, __be16 dport) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - struct rtable *rt; - struct flowi4 fl4; - - memset(&fl4, 0, sizeof(fl4)); - fl4.flowi4_tos = RT_TOS(info->key.tos); - fl4.flowi4_mark = skb->mark; - fl4.flowi4_proto = IPPROTO_UDP; - fl4.daddr = info->key.u.ipv4.dst; - - rt = ip_route_output_key(vxlan->net, &fl4); - if (IS_ERR(rt)) - return PTR_ERR(rt); - ip_rt_put(rt); - - info->key.u.ipv4.src = fl4.saddr; - info->key.tp_src = sport; - info->key.tp_dst = dport; - return 0; -} - static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) { struct vxlan_dev *vxlan = netdev_priv(dev); @@ -2426,9 +2417,16 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) dport = info->key.tp_dst ? : vxlan->cfg.dst_port; if (ip_tunnel_info_af(info) == AF_INET) { + struct rtable *rt; + if (!vxlan->vn4_sock) return -EINVAL; - return egress_ipv4_tun_info(dev, skb, info, sport, dport); + rt = vxlan_get_route(vxlan, skb, 0, info->key.tos, + info->key.u.ipv4.dst, + &info->key.u.ipv4.src); + if (IS_ERR(rt)) + return PTR_ERR(rt); + ip_rt_put(rt); } else { #if IS_ENABLED(CONFIG_IPV6) struct dst_entry *ndst; @@ -2441,13 +2439,12 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) if (IS_ERR(ndst)) return PTR_ERR(ndst); dst_release(ndst); - - info->key.tp_src = sport; - info->key.tp_dst = dport; #else /* !CONFIG_IPV6 */ return -EPFNOSUPPORT; #endif } + info->key.tp_src = sport; + info->key.tp_dst = dport; return 0; } -- cgit v1.2.3 From b4ed5cad24c1072033efbffa680c84c9ba19c798 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 2 Feb 2016 18:09:15 +0100 Subject: vxlan: consolidate csum flag handling The flag for tx checksumming for tunneling over IPv4 and IPv6 is different. Decide whether to do tx checksumming in vxlan_xmit_one and pass it on as a separate flag. This will allow for tx path consolidation in the next patch. Unfortunately, gcc is not clever enough to see that udp_sum is always initialized and gives an uninitialized variable warning. Set it to false to silence the warning. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index d0f7723fd776..fe3fd4808f4d 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1690,12 +1690,13 @@ static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk, struct net_device *dev, struct in6_addr *saddr, struct in6_addr *daddr, __u8 prio, __u8 ttl, __be16 src_port, __be16 dst_port, __be32 vni, - struct vxlan_metadata *md, bool xnet, u32 vxflags) + struct vxlan_metadata *md, bool xnet, u32 vxflags, + bool udp_sum) { struct vxlanhdr *vxh; int min_headroom; int err; - bool udp_sum = !(vxflags & VXLAN_F_UDP_ZERO_CSUM6_TX); + bool nocheck = !udp_sum; int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; u16 hdrlen = sizeof(struct vxlanhdr); @@ -1763,8 +1764,7 @@ static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk, skb_set_inner_protocol(skb, htons(ETH_P_TEB)); udp_tunnel6_xmit_skb(dst, sk, skb, dev, saddr, daddr, prio, - ttl, src_port, dst_port, - !!(vxflags & VXLAN_F_UDP_ZERO_CSUM6_TX)); + ttl, src_port, dst_port, nocheck); return 0; err: dst_release(dst); @@ -1775,12 +1775,13 @@ err: static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb, __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df, __be16 src_port, __be16 dst_port, __be32 vni, - struct vxlan_metadata *md, bool xnet, u32 vxflags) + struct vxlan_metadata *md, bool xnet, u32 vxflags, + bool udp_sum) { struct vxlanhdr *vxh; int min_headroom; int err; - bool udp_sum = !!(vxflags & VXLAN_F_UDP_CSUM); + bool nocheck = !udp_sum; int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; u16 hdrlen = sizeof(struct vxlanhdr); @@ -1842,8 +1843,7 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk skb_set_inner_protocol(skb, htons(ETH_P_TEB)); udp_tunnel_xmit_skb(rt, sk, skb, src, dst, tos, ttl, df, - src_port, dst_port, xnet, - !(vxflags & VXLAN_F_UDP_CSUM)); + src_port, dst_port, xnet, nocheck); return 0; } @@ -1959,6 +1959,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, __u8 tos, ttl; int err; u32 flags = vxlan->flags; + bool udp_sum = false; info = skb_tunnel_info(skb); @@ -2007,6 +2008,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, if (info) { ttl = info->key.ttl; tos = info->key.tos; + udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM); if (info->options_len) md = ip_tunnel_info_opts(info); @@ -2024,11 +2026,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, if (info) { if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT) df = htons(IP_DF); - - if (info->key.tun_flags & TUNNEL_CSUM) - flags |= VXLAN_F_UDP_CSUM; - else - flags &= ~VXLAN_F_UDP_CSUM; + } else { + udp_sum = !!(flags & VXLAN_F_UDP_CSUM); } rt = vxlan_get_route(vxlan, skb, @@ -2069,7 +2068,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, dst->sin.sin_addr.s_addr, tos, ttl, df, src_port, dst_port, htonl(vni << 8), md, !net_eq(vxlan->net, dev_net(vxlan->dev)), - flags); + flags, udp_sum); if (err < 0) { /* skb is already freed. */ skb = NULL; @@ -2119,18 +2118,14 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, return; } - if (info) { - if (info->key.tun_flags & TUNNEL_CSUM) - flags &= ~VXLAN_F_UDP_ZERO_CSUM6_TX; - else - flags |= VXLAN_F_UDP_ZERO_CSUM6_TX; - } + if (!info) + udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX); ttl = ttl ? : ip6_dst_hoplimit(ndst); err = vxlan6_xmit_skb(ndst, sk, skb, dev, &saddr, &dst->sin6.sin6_addr, 0, ttl, src_port, dst_port, htonl(vni << 8), md, !net_eq(vxlan->net, dev_net(vxlan->dev)), - flags); + flags, udp_sum); #endif } -- cgit v1.2.3 From f491e56dba511d318f52efa4c226471bf5943e88 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 2 Feb 2016 18:09:16 +0100 Subject: vxlan: consolidate vxlan_xmit_skb and vxlan6_xmit_skb There's a lot of code duplication. Factor out the duplicate code to a new function shared between IPv4 and IPv6 xmit path. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 137 ++++++++++------------------------------------------ 1 file changed, 26 insertions(+), 111 deletions(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index fe3fd4808f4d..65f52472a52c 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1684,19 +1684,14 @@ static void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, u32 vxflags, gbp->policy_id = htons(md->gbp & VXLAN_GBP_ID_MASK); } -#if IS_ENABLED(CONFIG_IPV6) -static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb, - struct net_device *dev, struct in6_addr *saddr, - struct in6_addr *daddr, __u8 prio, __u8 ttl, - __be16 src_port, __be16 dst_port, __be32 vni, - struct vxlan_metadata *md, bool xnet, u32 vxflags, +static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst, + int iphdr_len, __be32 vni, + struct vxlan_metadata *md, u32 vxflags, bool udp_sum) { struct vxlanhdr *vxh; int min_headroom; int err; - bool nocheck = !udp_sum; int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; u16 hdrlen = sizeof(struct vxlanhdr); @@ -1713,93 +1708,8 @@ static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk, } } - skb_scrub_packet(skb, xnet); - min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len - + VXLAN_HLEN + sizeof(struct ipv6hdr) - + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0); - - /* Need space for new headers (invalidates iph ptr) */ - err = skb_cow_head(skb, min_headroom); - if (unlikely(err)) { - kfree_skb(skb); - goto err; - } - - skb = vlan_hwaccel_push_inside(skb); - if (WARN_ON(!skb)) { - err = -ENOMEM; - goto err; - } - - skb = iptunnel_handle_offloads(skb, udp_sum, type); - if (IS_ERR(skb)) { - err = -EINVAL; - goto err; - } - - vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); - vxh->vx_flags = htonl(VXLAN_HF_VNI); - vxh->vx_vni = vni; - - if (type & SKB_GSO_TUNNEL_REMCSUM) { - u32 data = (skb_checksum_start_offset(skb) - hdrlen) >> - VXLAN_RCO_SHIFT; - - if (skb->csum_offset == offsetof(struct udphdr, check)) - data |= VXLAN_RCO_UDP; - - vxh->vx_vni |= htonl(data); - vxh->vx_flags |= htonl(VXLAN_HF_RCO); - - if (!skb_is_gso(skb)) { - skb->ip_summed = CHECKSUM_NONE; - skb->encapsulation = 0; - } - } - - if (vxflags & VXLAN_F_GBP) - vxlan_build_gbp_hdr(vxh, vxflags, md); - - skb_set_inner_protocol(skb, htons(ETH_P_TEB)); - - udp_tunnel6_xmit_skb(dst, sk, skb, dev, saddr, daddr, prio, - ttl, src_port, dst_port, nocheck); - return 0; -err: - dst_release(dst); - return err; -} -#endif - -static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb, - __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df, - __be16 src_port, __be16 dst_port, __be32 vni, - struct vxlan_metadata *md, bool xnet, u32 vxflags, - bool udp_sum) -{ - struct vxlanhdr *vxh; - int min_headroom; - int err; - bool nocheck = !udp_sum; - int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; - u16 hdrlen = sizeof(struct vxlanhdr); - - if ((vxflags & VXLAN_F_REMCSUM_TX) && - skb->ip_summed == CHECKSUM_PARTIAL) { - int csum_start = skb_checksum_start_offset(skb); - - if (csum_start <= VXLAN_MAX_REMCSUM_START && - !(csum_start & VXLAN_RCO_SHIFT_MASK) && - (skb->csum_offset == offsetof(struct udphdr, check) || - skb->csum_offset == offsetof(struct tcphdr, check))) { - udp_sum = false; - type |= SKB_GSO_TUNNEL_REMCSUM; - } - } - - min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len - + VXLAN_HLEN + sizeof(struct iphdr) + + VXLAN_HLEN + iphdr_len + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0); /* Need space for new headers (invalidates iph ptr) */ @@ -1841,9 +1751,6 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk vxlan_build_gbp_hdr(vxh, vxflags, md); skb_set_inner_protocol(skb, htons(ETH_P_TEB)); - - udp_tunnel_xmit_skb(rt, sk, skb, src, dst, tos, ttl, df, - src_port, dst_port, xnet, nocheck); return 0; } @@ -1960,6 +1867,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, int err; u32 flags = vxlan->flags; bool udp_sum = false; + bool xnet = !net_eq(vxlan->net, dev_net(vxlan->dev)); info = skb_tunnel_info(skb); @@ -2064,16 +1972,14 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, tos = ip_tunnel_ecn_encap(tos, old_iph, skb); ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); - err = vxlan_xmit_skb(rt, sk, skb, saddr, - dst->sin.sin_addr.s_addr, tos, ttl, df, - src_port, dst_port, htonl(vni << 8), md, - !net_eq(vxlan->net, dev_net(vxlan->dev)), - flags, udp_sum); - if (err < 0) { - /* skb is already freed. */ - skb = NULL; - goto rt_tx_error; - } + err = vxlan_build_skb(skb, &rt->dst, sizeof(struct iphdr), + htonl(vni << 8), md, flags, udp_sum); + if (err < 0) + goto xmit_tx_error; + + udp_tunnel_xmit_skb(rt, sk, skb, saddr, + dst->sin.sin_addr.s_addr, tos, ttl, df, + src_port, dst_port, xnet, !udp_sum); #if IS_ENABLED(CONFIG_IPV6) } else { struct dst_entry *ndst; @@ -2122,10 +2028,16 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX); ttl = ttl ? : ip6_dst_hoplimit(ndst); - err = vxlan6_xmit_skb(ndst, sk, skb, dev, &saddr, &dst->sin6.sin6_addr, - 0, ttl, src_port, dst_port, htonl(vni << 8), md, - !net_eq(vxlan->net, dev_net(vxlan->dev)), - flags, udp_sum); + skb_scrub_packet(skb, xnet); + err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr), + htonl(vni << 8), md, flags, udp_sum); + if (err < 0) { + dst_release(ndst); + return; + } + udp_tunnel6_xmit_skb(ndst, sk, skb, dev, + &saddr, &dst->sin6.sin6_addr, + 0, ttl, src_port, dst_port, !udp_sum); #endif } @@ -2135,6 +2047,9 @@ drop: dev->stats.tx_dropped++; goto tx_free; +xmit_tx_error: + /* skb is already freed. */ + skb = NULL; rt_tx_error: ip_rt_put(rt); tx_error: -- cgit v1.2.3 From a5a773a54e59538d03fd1a20facd7214c030b1d3 Mon Sep 17 00:00:00 2001 From: Suresh Reddy Date: Wed, 3 Feb 2016 09:49:16 +0530 Subject: be2net: return error status from be_set_phys_id() be_set_phys_id() returns 0 to ethtool when the command fails in the FW. This patch fixes the set_phys_id() to return -EIO in case the FW cmd fails. Signed-off-by: Suresh Reddy Signed-off-by: Sriharsha Basavapatna Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_ethtool.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index a19ac441336f..2ff691636dac 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -720,29 +720,32 @@ static int be_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) { struct be_adapter *adapter = netdev_priv(netdev); + int status = 0; switch (state) { case ETHTOOL_ID_ACTIVE: - be_cmd_get_beacon_state(adapter, adapter->hba_port_num, - &adapter->beacon_state); - return 1; /* cycle on/off once per second */ + status = be_cmd_get_beacon_state(adapter, adapter->hba_port_num, + &adapter->beacon_state); + if (status) + return be_cmd_status(status); + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_ON: - be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0, - BEACON_STATE_ENABLED); + status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, + 0, 0, BEACON_STATE_ENABLED); break; case ETHTOOL_ID_OFF: - be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0, - BEACON_STATE_DISABLED); + status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, + 0, 0, BEACON_STATE_DISABLED); break; case ETHTOOL_ID_INACTIVE: - be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0, - adapter->beacon_state); + status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, + 0, 0, adapter->beacon_state); } - return 0; + return be_cmd_status(status); } static int be_set_dump(struct net_device *netdev, struct ethtool_dump *dump) -- cgit v1.2.3 From fa5c867d4df275a2c11a455043848574e80a8b32 Mon Sep 17 00:00:00 2001 From: Suresh Reddy Date: Wed, 3 Feb 2016 09:49:17 +0530 Subject: be2net: check for INSUFFICIENT_PRIVILEGES error The driver currently logs the message "VF is not privileged to issue opcode" by checking only the base_status field for UNAUTHORIZED_REQUEST. Add check to look for INSUFFICIENT_PRIVILEGES in the additional status field also as not all cmds fail with that base status. Signed-off-by: Suresh Reddy Signed-off-by: Sriharsha Basavapatna Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_cmds.c | 3 ++- drivers/net/ethernet/emulex/benet/be_cmds.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index b63d8ad2e115..3b665f16d2aa 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -236,7 +236,8 @@ static int be_mcc_compl_process(struct be_adapter *adapter, if (base_status != MCC_STATUS_SUCCESS && !be_skip_err_log(opcode, base_status, addl_status)) { - if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST) { + if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST || + addl_status == MCC_ADDL_STATUS_INSUFFICIENT_PRIVILEGES) { dev_warn(&adapter->pdev->dev, "VF is not privileged to issue opcode %d-%d\n", opcode, subsystem); diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 241819b36ca7..f260ef3329a1 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -68,7 +68,8 @@ enum mcc_addl_status { MCC_ADDL_STATUS_TOO_MANY_INTERFACES = 0x4a, MCC_ADDL_STATUS_INSUFFICIENT_VLANS = 0xab, MCC_ADDL_STATUS_INVALID_SIGNATURE = 0x56, - MCC_ADDL_STATUS_MISSING_SIGNATURE = 0x57 + MCC_ADDL_STATUS_MISSING_SIGNATURE = 0x57, + MCC_ADDL_STATUS_INSUFFICIENT_PRIVILEGES = 0x60 }; #define CQE_BASE_STATUS_MASK 0xFFFF -- cgit v1.2.3 From 41dcdfbd0944a3ef08224a8c9ba3b2fdeae0dd86 Mon Sep 17 00:00:00 2001 From: Sriharsha Basavapatna Date: Wed, 3 Feb 2016 09:49:18 +0530 Subject: be2net: Fix be_vlan_rem_vid() to check vlan id being removed The driver decrements its vlan count without checking if it is really present in its list. This results in an invalid vlan count and impacts subsequent vlan add/rem ops. The function be_vlan_rem_vid() should be updated to fix this. Signed-off-by: Sriharsha Basavapatna Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index f99de3657ce3..09e6f2cdfc90 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1463,6 +1463,9 @@ static int be_vlan_rem_vid(struct net_device *netdev, __be16 proto, u16 vid) if (lancer_chip(adapter) && vid == 0) return 0; + if (!test_bit(vid, adapter->vids)) + return 0; + clear_bit(vid, adapter->vids); adapter->vlans_added--; -- cgit v1.2.3 From ee9ad2802449c0a6811a74af2ce30500895d137b Mon Sep 17 00:00:00 2001 From: Sriharsha Basavapatna Date: Wed, 3 Feb 2016 09:49:19 +0530 Subject: be2net: SRIOV Queue distribution should factor in EQ-count of VFs The SRIOV resource distribution logic for RX/TX queue counts is not optimal when a small number of VFs are enabled. It does not take into account the VF's EQ count while computing the queue counts. Because of this, the VF gets a large number of queues, though it doesn't have sufficient EQs, resulting in wasted queue resources. And the PF gets a smaller share of queues though it has more EQs. Fix this by capping the VF queue count at its EQ count. Signed-off-by: Sriharsha Basavapatna Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 4 ++++ drivers/net/ethernet/emulex/benet/be_main.c | 15 ++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index cf837831304b..de88c30bc029 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -89,6 +89,10 @@ #define BE3_MAX_TX_QS 16 #define BE3_MAX_EVT_QS 16 #define BE3_SRIOV_MAX_EVT_QS 8 +#define SH_VF_MAX_NIC_EQS 3 /* Skyhawk VFs can have a max of 4 EQs + * and at least 1 is granted to either + * SURF/DPDK + */ #define MAX_RSS_IFACES 15 #define MAX_RX_QS 32 diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 09e6f2cdfc90..62f6fbb8b0f1 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -3792,18 +3792,15 @@ static u16 be_calculate_vf_qs(struct be_adapter *adapter, u16 num_vfs) struct be_resources res = adapter->pool_res; u16 num_vf_qs = 1; - /* Distribute the queue resources equally among the PF and it's VFs + /* Distribute the queue resources among the PF and it's VFs * Do not distribute queue resources in multi-channel configuration. */ if (num_vfs && !be_is_mc(adapter)) { - /* If number of VFs requested is 8 less than max supported, - * assign 8 queue pairs to the PF and divide the remaining - * resources evenly among the VFs - */ - if (num_vfs < (be_max_vfs(adapter) - 8)) - num_vf_qs = (res.max_rss_qs - 8) / num_vfs; - else - num_vf_qs = res.max_rss_qs / num_vfs; + /* Divide the qpairs evenly among the VFs and the PF, capped + * at VF-EQ-count. Any remainder qpairs belong to the PF. + */ + num_vf_qs = min(SH_VF_MAX_NIC_EQS, + res.max_rss_qs / (num_vfs + 1)); /* Skyhawk-R chip supports only MAX_RSS_IFACES RSS capable * interfaces per port. Provide RSS on VFs, only if number -- cgit v1.2.3 From 2e365b1b80aa98655a5582dbb9bf6cf8c0ff268c Mon Sep 17 00:00:00 2001 From: Somnath Kotur Date: Wed, 3 Feb 2016 09:49:20 +0530 Subject: be2net: Don't run ethtool self-tests for VFs The CMD_SUBSYSTEM_LOWLEVEL cmds need DEV_CFG Privilege to run which VFs don't have by default. Self-tests need to be issued only for PFs. Signed-off-by: Somnath Kotur Signed-off-by: Sriharsha Basavapatna Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_cmds.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 3b665f16d2aa..7d51d4733890 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -65,7 +65,22 @@ static struct be_cmd_priv_map cmd_priv_map[] = { CMD_SUBSYSTEM_COMMON, BE_PRIV_LNKMGMT | BE_PRIV_VHADM | BE_PRIV_DEVCFG | BE_PRIV_DEVSEC - } + }, + { + OPCODE_LOWLEVEL_HOST_DDR_DMA, + CMD_SUBSYSTEM_LOWLEVEL, + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC + }, + { + OPCODE_LOWLEVEL_LOOPBACK_TEST, + CMD_SUBSYSTEM_LOWLEVEL, + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC + }, + { + OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, + CMD_SUBSYSTEM_LOWLEVEL, + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC + }, }; static bool be_cmd_allowed(struct be_adapter *adapter, u8 opcode, u8 subsystem) @@ -3169,6 +3184,10 @@ int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, struct be_cmd_req_set_lmode *req; int status; + if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, + CMD_SUBSYSTEM_LOWLEVEL)) + return -EPERM; + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); @@ -3214,6 +3233,10 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, struct be_cmd_resp_loopback_test *resp; int status; + if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_LOOPBACK_TEST, + CMD_SUBSYSTEM_LOWLEVEL)) + return -EPERM; + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); @@ -3260,6 +3283,10 @@ int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, int status; int i, j = 0; + if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_HOST_DDR_DMA, + CMD_SUBSYSTEM_LOWLEVEL)) + return -EPERM; + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); -- cgit v1.2.3 From 1babbad46f4aba1c242e43e27c5b36a62311b2d4 Mon Sep 17 00:00:00 2001 From: Padmanabh Ratnakar Date: Wed, 3 Feb 2016 09:49:21 +0530 Subject: be2net: Fix Lancer error recovery After error is detected, wait for adapter to move to ready state before destroying queues and cleanup of other resources. Also skip performing any cleanup for non-Lancer chips and move debug messages to correct routine. Signed-off-by: Padmanabh Ratnakar Signed-off-by: Sriharsha Basavapatna Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 51 +++++++++++++++++++---------- 1 file changed, 34 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 62f6fbb8b0f1..6eb3aba832fc 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4859,21 +4859,27 @@ static int be_resume(struct be_adapter *adapter) static int be_err_recover(struct be_adapter *adapter) { - struct device *dev = &adapter->pdev->dev; int status; + /* Error recovery is supported only Lancer as of now */ + if (!lancer_chip(adapter)) + return -EIO; + + /* Wait for adapter to reach quiescent state before + * destroying queues + */ + status = be_fw_wait_ready(adapter); + if (status) + goto err; + + be_cleanup(adapter); + status = be_resume(adapter); if (status) goto err; - dev_info(dev, "Adapter recovery successful\n"); return 0; err: - if (be_physfn(adapter)) - dev_err(dev, "Adapter recovery failed\n"); - else - dev_err(dev, "Re-trying adapter recovery\n"); - return status; } @@ -4882,21 +4888,32 @@ static void be_err_detection_task(struct work_struct *work) struct be_adapter *adapter = container_of(work, struct be_adapter, be_err_detection_work.work); - int status = 0; + struct device *dev = &adapter->pdev->dev; + int recovery_status; be_detect_error(adapter); - if (be_check_error(adapter, BE_ERROR_HW)) { - be_cleanup(adapter); - - /* As of now error recovery support is in Lancer only */ - if (lancer_chip(adapter)) - status = be_err_recover(adapter); + if (be_check_error(adapter, BE_ERROR_HW)) + recovery_status = be_err_recover(adapter); + else + goto reschedule_task; + + if (!recovery_status) { + dev_info(dev, "Adapter recovery successful\n"); + goto reschedule_task; + } else if (be_virtfn(adapter)) { + /* For VFs, check if PF have allocated resources + * every second. + */ + dev_err(dev, "Re-trying adapter recovery\n"); + goto reschedule_task; + } else { + dev_err(dev, "Adapter recovery failed\n"); } - /* Always attempt recovery on VFs */ - if (!status || be_virtfn(adapter)) - be_schedule_err_detection(adapter); + return; +reschedule_task: + be_schedule_err_detection(adapter); } static void be_log_sfp_info(struct be_adapter *adapter) -- cgit v1.2.3 From 972f37b424e65f9ef1ce143b8658d9ed50db9f42 Mon Sep 17 00:00:00 2001 From: Padmanabh Ratnakar Date: Wed, 3 Feb 2016 09:49:22 +0530 Subject: be2net: Add retry in case of error recovery failure Retry error recovery MAX_ERR_RECOVERY_RETRY_COUNT times in case of failure during error recovery. Signed-off-by: Padmanabh Ratnakar Signed-off-by: Sriharsha Basavapatna Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 5 +++++ drivers/net/ethernet/emulex/benet/be_main.c | 23 +++++++++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index de88c30bc029..515e206589cc 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -397,6 +397,10 @@ enum vf_state { #define BE_UC_PMAC_COUNT 30 #define BE_VF_UC_PMAC_COUNT 2 +#define MAX_ERR_RECOVERY_RETRY_COUNT 3 +#define ERR_DETECTION_DELAY 1000 +#define ERR_RECOVERY_RETRY_DELAY 30000 + /* Ethtool set_dump flags */ #define LANCER_INITIATE_FW_DUMP 0x1 #define LANCER_DELETE_FW_DUMP 0x2 @@ -534,6 +538,7 @@ struct be_adapter { u16 work_counter; struct delayed_work be_err_detection_work; + u8 recovery_retries; u8 err_flags; u32 flags; u32 cmd_privileges; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 6eb3aba832fc..d5286d3c9356 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4265,10 +4265,10 @@ static void be_schedule_worker(struct be_adapter *adapter) adapter->flags |= BE_FLAGS_WORKER_SCHEDULED; } -static void be_schedule_err_detection(struct be_adapter *adapter) +static void be_schedule_err_detection(struct be_adapter *adapter, u32 delay) { schedule_delayed_work(&adapter->be_err_detection_work, - msecs_to_jiffies(1000)); + msecs_to_jiffies(delay)); adapter->flags |= BE_FLAGS_ERR_DETECTION_SCHEDULED; } @@ -4890,6 +4890,7 @@ static void be_err_detection_task(struct work_struct *work) be_err_detection_work.work); struct device *dev = &adapter->pdev->dev; int recovery_status; + int delay = ERR_DETECTION_DELAY; be_detect_error(adapter); @@ -4899,6 +4900,7 @@ static void be_err_detection_task(struct work_struct *work) goto reschedule_task; if (!recovery_status) { + adapter->recovery_retries = 0; dev_info(dev, "Adapter recovery successful\n"); goto reschedule_task; } else if (be_virtfn(adapter)) { @@ -4907,13 +4909,22 @@ static void be_err_detection_task(struct work_struct *work) */ dev_err(dev, "Re-trying adapter recovery\n"); goto reschedule_task; + } else if (adapter->recovery_retries++ < + MAX_ERR_RECOVERY_RETRY_COUNT) { + /* In case of another error during recovery, it takes 30 sec + * for adapter to come out of error. Retry error recovery after + * this time interval. + */ + dev_err(&adapter->pdev->dev, "Re-trying adapter recovery\n"); + delay = ERR_RECOVERY_RETRY_DELAY; + goto reschedule_task; } else { dev_err(dev, "Adapter recovery failed\n"); } return; reschedule_task: - be_schedule_err_detection(adapter); + be_schedule_err_detection(adapter, delay); } static void be_log_sfp_info(struct be_adapter *adapter) @@ -5309,7 +5320,7 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) be_roce_dev_add(adapter); - be_schedule_err_detection(adapter); + be_schedule_err_detection(adapter, ERR_DETECTION_DELAY); /* On Die temperature not supported for VF. */ if (be_physfn(adapter) && IS_ENABLED(CONFIG_BE2NET_HWMON)) { @@ -5376,7 +5387,7 @@ static int be_pci_resume(struct pci_dev *pdev) if (status) return status; - be_schedule_err_detection(adapter); + be_schedule_err_detection(adapter, ERR_DETECTION_DELAY); if (adapter->wol_en) be_setup_wol(adapter, false); @@ -5476,7 +5487,7 @@ static void be_eeh_resume(struct pci_dev *pdev) if (status) goto err; - be_schedule_err_detection(adapter); + be_schedule_err_detection(adapter, ERR_DETECTION_DELAY); return; err: dev_err(&adapter->pdev->dev, "EEH resume failed\n"); -- cgit v1.2.3 From 3c0d49aaa67e1990f4c081892e9bb69070853919 Mon Sep 17 00:00:00 2001 From: Padmanabh Ratnakar Date: Wed, 3 Feb 2016 09:49:23 +0530 Subject: be2net: Fix interval calculation in interrupt moderation Interrupt moderation parameters need to be recalculated only after a time interval of 1 ms. Interval calculation is wrong when there is a rollover of jiffies. Using recommended way of interval calculation using jiffies to fix this. Signed-off-by: Padmanabh Ratnakar Signed-off-by: Sriharsha Basavapatna Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index d5286d3c9356..9c1fc9dcea25 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1917,8 +1917,7 @@ static u32 be_get_eq_delay_mult_enc(struct be_eq_obj *eqo) if (!aic->enable) return 0; - if (time_before_eq(now, aic->jiffies) || - jiffies_to_msecs(now - aic->jiffies) < 1) + if (jiffies_to_msecs(now - aic->jiffies) < 1) eqd = aic->prev_eqd; else eqd = be_get_new_eqd(eqo); -- cgit v1.2.3 From 22fae97d863679994b951799dd4bbe7afd95897b Mon Sep 17 00:00:00 2001 From: Paul Durrant Date: Tue, 2 Feb 2016 11:55:05 +0000 Subject: xen-netback: implement dynamic multicast control My recent patch to the Xen Project documents a protocol for 'dynamic multicast control' in netif.h. This extends the previous multicast control protocol to not require a shared ring reconnection to turn the feature off. Instead the backend watches the "request-multicast-control" key in xenstore and turns the feature off if the key value is written to zero. This patch adds support for dynamic multicast control in xen-netback. Signed-off-by: Paul Durrant Cc: Ian Campbell Cc: Wei Liu Acked-by: Wei Liu Signed-off-by: David S. Miller --- drivers/net/xen-netback/common.h | 1 + drivers/net/xen-netback/xenbus.c | 89 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 82 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 0333ab0fd926..112825200d41 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -251,6 +251,7 @@ struct xenvif { unsigned int stalled_queues; struct xenbus_watch credit_watch; + struct xenbus_watch mcast_ctrl_watch; spinlock_t lock; diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 56ebd8267386..39a303de20dd 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -327,7 +327,7 @@ static int netback_probe(struct xenbus_device *dev, goto abort_transaction; } - /* We support multicast-control. */ + /* We support dynamic multicast-control. */ err = xenbus_printf(xbt, dev->nodename, "feature-multicast-control", "%d", 1); if (err) { @@ -335,6 +335,14 @@ static int netback_probe(struct xenbus_device *dev, goto abort_transaction; } + err = xenbus_printf(xbt, dev->nodename, + "feature-dynamic-multicast-control", + "%d", 1); + if (err) { + message = "writing feature-dynamic-multicast-control"; + goto abort_transaction; + } + err = xenbus_transaction_end(xbt, 0); } while (err == -EAGAIN); @@ -683,7 +691,8 @@ static void xen_net_rate_changed(struct xenbus_watch *watch, } } -static int xen_register_watchers(struct xenbus_device *dev, struct xenvif *vif) +static int xen_register_credit_watch(struct xenbus_device *dev, + struct xenvif *vif) { int err = 0; char *node; @@ -708,7 +717,7 @@ static int xen_register_watchers(struct xenbus_device *dev, struct xenvif *vif) return err; } -static void xen_unregister_watchers(struct xenvif *vif) +static void xen_unregister_credit_watch(struct xenvif *vif) { if (vif->credit_watch.node) { unregister_xenbus_watch(&vif->credit_watch); @@ -717,6 +726,75 @@ static void xen_unregister_watchers(struct xenvif *vif) } } +static void xen_mcast_ctrl_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len) +{ + struct xenvif *vif = container_of(watch, struct xenvif, + mcast_ctrl_watch); + struct xenbus_device *dev = xenvif_to_xenbus_device(vif); + int val; + + if (xenbus_scanf(XBT_NIL, dev->otherend, + "request-multicast-control", "%d", &val) < 0) + val = 0; + vif->multicast_control = !!val; +} + +static int xen_register_mcast_ctrl_watch(struct xenbus_device *dev, + struct xenvif *vif) +{ + int err = 0; + char *node; + unsigned maxlen = strlen(dev->otherend) + + sizeof("/request-multicast-control"); + + if (vif->mcast_ctrl_watch.node) { + pr_err_ratelimited("Watch is already registered\n"); + return -EADDRINUSE; + } + + node = kmalloc(maxlen, GFP_KERNEL); + if (!node) { + pr_err("Failed to allocate memory for watch\n"); + return -ENOMEM; + } + snprintf(node, maxlen, "%s/request-multicast-control", + dev->otherend); + vif->mcast_ctrl_watch.node = node; + vif->mcast_ctrl_watch.callback = xen_mcast_ctrl_changed; + err = register_xenbus_watch(&vif->mcast_ctrl_watch); + if (err) { + pr_err("Failed to set watcher %s\n", + vif->mcast_ctrl_watch.node); + kfree(node); + vif->mcast_ctrl_watch.node = NULL; + vif->mcast_ctrl_watch.callback = NULL; + } + return err; +} + +static void xen_unregister_mcast_ctrl_watch(struct xenvif *vif) +{ + if (vif->mcast_ctrl_watch.node) { + unregister_xenbus_watch(&vif->mcast_ctrl_watch); + kfree(vif->mcast_ctrl_watch.node); + vif->mcast_ctrl_watch.node = NULL; + } +} + +static void xen_register_watchers(struct xenbus_device *dev, + struct xenvif *vif) +{ + xen_register_credit_watch(dev, vif); + xen_register_mcast_ctrl_watch(dev, vif); +} + +static void xen_unregister_watchers(struct xenvif *vif) +{ + xen_unregister_mcast_ctrl_watch(vif); + xen_unregister_credit_watch(vif); +} + static void unregister_hotplug_status_watch(struct backend_info *be) { if (be->have_hotplug_status_watch) { @@ -1030,11 +1108,6 @@ static int read_xenbus_vif_flags(struct backend_info *be) val = 0; vif->ipv6_csum = !!val; - if (xenbus_scanf(XBT_NIL, dev->otherend, "request-multicast-control", - "%d", &val) < 0) - val = 0; - vif->multicast_control = !!val; - return 0; } -- cgit v1.2.3 From 67eb03318bc5fe170ae832423fda7a23b0d801cf Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 2 Feb 2016 07:43:45 -0800 Subject: net: Add support for fill_slave_info to VRF device Allows userspace to have direct access to VRF table association versus looking up master device and its table. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/vrf.c | 21 +++++++++++++++++++++ include/uapi/linux/if_link.h | 8 ++++++++ 2 files changed, 29 insertions(+) (limited to 'drivers') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 66addb7a7911..76e1fc9d8748 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -877,6 +877,24 @@ static int vrf_fillinfo(struct sk_buff *skb, return nla_put_u32(skb, IFLA_VRF_TABLE, vrf->tb_id); } +static size_t vrf_get_slave_size(const struct net_device *bond_dev, + const struct net_device *slave_dev) +{ + return nla_total_size(sizeof(u32)); /* IFLA_VRF_PORT_TABLE */ +} + +static int vrf_fill_slave_info(struct sk_buff *skb, + const struct net_device *vrf_dev, + const struct net_device *slave_dev) +{ + struct net_vrf *vrf = netdev_priv(vrf_dev); + + if (nla_put_u32(skb, IFLA_VRF_PORT_TABLE, vrf->tb_id)) + return -EMSGSIZE; + + return 0; +} + static const struct nla_policy vrf_nl_policy[IFLA_VRF_MAX + 1] = { [IFLA_VRF_TABLE] = { .type = NLA_U32 }, }; @@ -890,6 +908,9 @@ static struct rtnl_link_ops vrf_link_ops __read_mostly = { .validate = vrf_validate, .fill_info = vrf_fillinfo, + .get_slave_size = vrf_get_slave_size, + .fill_slave_info = vrf_fill_slave_info, + .newlink = vrf_newlink, .dellink = vrf_dellink, .setup = vrf_setup, diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index d3e90b91e07e..d452cea59020 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -405,6 +405,14 @@ enum { #define IFLA_VRF_MAX (__IFLA_VRF_MAX - 1) +enum { + IFLA_VRF_PORT_UNSPEC, + IFLA_VRF_PORT_TABLE, + __IFLA_VRF_PORT_MAX +}; + +#define IFLA_VRF_PORT_MAX (__IFLA_VRF_PORT_MAX - 1) + /* IPVLAN section */ enum { IFLA_IPVLAN_UNSPEC, -- cgit v1.2.3 From 365a10289fccbf769ad8b172c30716fac50fa278 Mon Sep 17 00:00:00 2001 From: Sowmini Varadhan Date: Tue, 2 Feb 2016 10:41:56 -0800 Subject: sunvnet: perf tracepoint invocations to trace LDC state machine Use sunvnet perf trace macros to monitor LDC message exchange state. Signed-off-by: Sowmini Varadhan Signed-off-by: David S. Miller --- drivers/net/ethernet/sun/sunvnet.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index 23fa29877f5b..942a95db2061 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c @@ -17,6 +17,8 @@ #include #include #include +#define CREATE_TRACE_POINTS +#include #if IS_ENABLED(CONFIG_IPV6) #include @@ -540,6 +542,8 @@ static int vnet_walk_rx_one(struct vnet_port *port, err = vnet_rx_one(port, desc); if (err == -ECONNRESET) return err; + trace_vnet_rx_one(port->vio._local_sid, port->vio._peer_sid, + index, desc->hdr.ack); desc->hdr.state = VIO_DESC_DONE; err = put_rx_desc(port, dr, desc, index); if (err < 0) @@ -587,9 +591,15 @@ static int vnet_walk_rx(struct vnet_port *port, struct vio_dring_state *dr, ack_start = ack_end = vio_dring_prev(dr, start); if (send_ack) { port->napi_resume = false; + trace_vnet_tx_send_stopped_ack(port->vio._local_sid, + port->vio._peer_sid, + ack_end, *npkts); return vnet_send_ack(port, dr, ack_start, ack_end, VIO_DRING_STOPPED); } else { + trace_vnet_tx_defer_stopped_ack(port->vio._local_sid, + port->vio._peer_sid, + ack_end, *npkts); port->napi_resume = true; port->napi_stop_idx = ack_end; return 1; @@ -663,6 +673,8 @@ static int vnet_ack(struct vnet_port *port, void *msgbuf) /* sync for race conditions with vnet_start_xmit() and tell xmit it * is time to send a trigger. */ + trace_vnet_rx_stopped_ack(port->vio._local_sid, + port->vio._peer_sid, end); dr->cons = vio_dring_next(dr, end); desc = vio_dring_entry(dr, dr->cons); if (desc->hdr.state == VIO_DESC_READY && !port->start_cons) { @@ -886,6 +898,9 @@ static int __vnet_tx_trigger(struct vnet_port *port, u32 start) int retries = 0; if (port->stop_rx) { + trace_vnet_tx_pending_stopped_ack(port->vio._local_sid, + port->vio._peer_sid, + port->stop_rx_idx, -1); err = vnet_send_ack(port, &port->vio.drings[VIO_DRIVER_RX_RING], port->stop_rx_idx, -1, @@ -908,6 +923,8 @@ static int __vnet_tx_trigger(struct vnet_port *port, u32 start) if (retries++ > VNET_MAX_RETRIES) break; } while (err == -EAGAIN); + trace_vnet_tx_trigger(port->vio._local_sid, + port->vio._peer_sid, start, err); return err; } @@ -1414,8 +1431,11 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) * producer to consumer announcement that work is available to the * consumer */ - if (!port->start_cons) - goto ldc_start_done; /* previous trigger suffices */ + if (!port->start_cons) { /* previous trigger suffices */ + trace_vnet_skip_tx_trigger(port->vio._local_sid, + port->vio._peer_sid, dr->cons); + goto ldc_start_done; + } err = __vnet_tx_trigger(port, dr->cons); if (unlikely(err < 0)) { -- cgit v1.2.3 From 16032be56c1f66770da15cb94f0eb366c37aff6e Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Wed, 3 Feb 2016 04:04:37 +0100 Subject: virtio_net: add ethtool support for set and get of settings This patch allows the user to set and retrieve speed and duplex of the virtio_net device via ethtool. Having this functionality is very helpful for simulating different environments and also enables the virtio_net device to participate in operations where proper speed and duplex are required (e.g. currently bonding lacp mode requires full duplex). Custom speed and duplex are not allowed, the user-supplied settings are validated before applying. Example: $ ethtool eth1 Settings for eth1: ... Speed: Unknown! Duplex: Unknown! (255) $ ethtool -s eth1 speed 1000 duplex full $ ethtool eth1 Settings for eth1: ... Speed: 1000Mb/s Duplex: Full Based on a patch by Roopa Prabhu. Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'drivers') diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 767ab11a6e9f..c9fd52a8e6ec 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -146,6 +146,10 @@ struct virtnet_info { virtio_net_ctrl_ack ctrl_status; u8 ctrl_promisc; u8 ctrl_allmulti; + + /* Ethtool settings */ + u8 duplex; + u32 speed; }; struct padded_vnet_hdr { @@ -1376,6 +1380,58 @@ static void virtnet_get_channels(struct net_device *dev, channels->other_count = 0; } +/* Check if the user is trying to change anything besides speed/duplex */ +static bool virtnet_validate_ethtool_cmd(const struct ethtool_cmd *cmd) +{ + struct ethtool_cmd diff1 = *cmd; + struct ethtool_cmd diff2 = {}; + + /* advertising and cmd are usually set, ignore port because we set it */ + ethtool_cmd_speed_set(&diff1, 0); + diff1.advertising = 0; + diff1.duplex = 0; + diff1.port = 0; + diff1.cmd = 0; + + return !memcmp(&diff1, &diff2, sizeof(diff1)); +} + +static int virtnet_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct virtnet_info *vi = netdev_priv(dev); + u32 speed; + + speed = ethtool_cmd_speed(cmd); + /* don't allow custom speed and duplex */ + if (!ethtool_validate_speed(speed) || + !ethtool_validate_duplex(cmd->duplex) || + !virtnet_validate_ethtool_cmd(cmd)) + return -EINVAL; + vi->speed = speed; + vi->duplex = cmd->duplex; + + return 0; +} + +static int virtnet_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct virtnet_info *vi = netdev_priv(dev); + + ethtool_cmd_speed_set(cmd, vi->speed); + cmd->duplex = vi->duplex; + cmd->port = PORT_OTHER; + + return 0; +} + +static void virtnet_init_settings(struct net_device *dev) +{ + struct virtnet_info *vi = netdev_priv(dev); + + vi->speed = SPEED_UNKNOWN; + vi->duplex = DUPLEX_UNKNOWN; +} + static const struct ethtool_ops virtnet_ethtool_ops = { .get_drvinfo = virtnet_get_drvinfo, .get_link = ethtool_op_get_link, @@ -1383,6 +1439,8 @@ static const struct ethtool_ops virtnet_ethtool_ops = { .set_channels = virtnet_set_channels, .get_channels = virtnet_get_channels, .get_ts_info = ethtool_op_get_ts_info, + .get_settings = virtnet_get_settings, + .set_settings = virtnet_set_settings, }; #define MIN_MTU 68 @@ -1855,6 +1913,8 @@ static int virtnet_probe(struct virtio_device *vdev) netif_set_real_num_tx_queues(dev, vi->curr_queue_pairs); netif_set_real_num_rx_queues(dev, vi->curr_queue_pairs); + virtnet_init_settings(dev); + err = register_netdev(dev); if (err) { pr_debug("virtio_net: registering device failed\n"); -- cgit v1.2.3 From 66ad0dd30285e14529566a2f816a0d463f63cf81 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 2 Feb 2016 15:38:52 -0600 Subject: alienware-wmi: Clean up whitespace for ASM100 platform This brings them more in line with the usage of whitespace in other platforms. Signed-off-by: Mario Limonciello Signed-off-by: Darren Hart --- drivers/platform/x86/alienware-wmi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index 1e1e59423889..a8750ed720b8 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c @@ -105,14 +105,14 @@ static const struct dmi_system_id alienware_quirks[] __initconst = { .driver_data = &quirk_x51_family, }, { - .callback = dmi_matched, - .ident = "Alienware ASM100", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), - DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"), - }, - .driver_data = &quirk_asm100, - }, + .callback = dmi_matched, + .ident = "Alienware ASM100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"), + }, + .driver_data = &quirk_asm100, + }, {} }; -- cgit v1.2.3 From 9e503a9d0c18b277f902570a3dfd74a7c86ec9a7 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 2 Feb 2016 15:38:53 -0600 Subject: alienware-wmi: Add support for new platform: X51-R3 The X51-R3 is in the X51 family. It includes 3 internal lighting zones as well as is the first AW desktop that includes support for a graphics amplifier. Signed-off-by: Mario Limonciello Signed-off-by: Darren Hart --- drivers/platform/x86/alienware-wmi.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index a8750ed720b8..8e8ea4f2d59f 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c @@ -69,11 +69,16 @@ static struct quirk_entry quirk_unknown = { .hdmi_mux = 0, }; -static struct quirk_entry quirk_x51_family = { +static struct quirk_entry quirk_x51_r1_r2 = { .num_zones = 3, .hdmi_mux = 0. }; +static struct quirk_entry quirk_x51_r3 = { + .num_zones = 4, + .hdmi_mux = 0, +}; + static struct quirk_entry quirk_asm100 = { .num_zones = 2, .hdmi_mux = 1, @@ -88,12 +93,12 @@ static int __init dmi_matched(const struct dmi_system_id *dmi) static const struct dmi_system_id alienware_quirks[] __initconst = { { .callback = dmi_matched, - .ident = "Alienware X51 R1", + .ident = "Alienware X51 R3", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), - DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R3"), }, - .driver_data = &quirk_x51_family, + .driver_data = &quirk_x51_r3, }, { .callback = dmi_matched, @@ -102,7 +107,16 @@ static const struct dmi_system_id alienware_quirks[] __initconst = { DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R2"), }, - .driver_data = &quirk_x51_family, + .driver_data = &quirk_x51_r1_r2, + }, + { + .callback = dmi_matched, + .ident = "Alienware X51 R1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51"), + }, + .driver_data = &quirk_x51_r1_r2, }, { .callback = dmi_matched, -- cgit v1.2.3 From cbbb50d6038bc093154fb6e209729bbf8bebd614 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 2 Feb 2016 15:38:54 -0600 Subject: alienware-wmi: Add initial support for alienware graphics amplifier. The alienware graphics amplifier is a device that provides external access to a full PCIe slot, USB hub, and additional control zone. This patch enables support for reading status whether the cable is plugged in as well as for setting the colors in the new zone on the amplifier. Signed-off-by: Mario Limonciello [dvhart: minor comment formatting fixes] Signed-off-by: Darren Hart --- drivers/platform/x86/alienware-wmi.c | 107 ++++++++++++++++++++++++++++------- 1 file changed, 88 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index 8e8ea4f2d59f..fa86b7d5d6b5 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c @@ -33,6 +33,7 @@ #define WMAX_METHOD_BRIGHTNESS 0x3 #define WMAX_METHOD_ZONE_CONTROL 0x4 #define WMAX_METHOD_HDMI_CABLE 0x5 +#define WMAX_METHOD_AMPLIFIER_CABLE 0x6 MODULE_AUTHOR("Mario Limonciello "); MODULE_DESCRIPTION("Alienware special feature control"); @@ -60,6 +61,7 @@ enum WMAX_CONTROL_STATES { struct quirk_entry { u8 num_zones; u8 hdmi_mux; + u8 amplifier; }; static struct quirk_entry *quirks; @@ -67,21 +69,25 @@ static struct quirk_entry *quirks; static struct quirk_entry quirk_unknown = { .num_zones = 2, .hdmi_mux = 0, + .amplifier = 0, }; static struct quirk_entry quirk_x51_r1_r2 = { .num_zones = 3, - .hdmi_mux = 0. + .hdmi_mux = 0, + .amplifier = 0, }; static struct quirk_entry quirk_x51_r3 = { .num_zones = 4, .hdmi_mux = 0, + .amplifier = 1, }; static struct quirk_entry quirk_asm100 = { .num_zones = 2, .hdmi_mux = 1, + .amplifier = 0, }; static int __init dmi_matched(const struct dmi_system_id *dmi) @@ -147,7 +153,7 @@ struct wmax_brightness_args { u32 percentage; }; -struct hdmi_args { +struct wmax_basic_args { u8 arg; }; @@ -232,16 +238,16 @@ static int alienware_update_led(struct platform_zone *zone) char *guid; struct acpi_buffer input; struct legacy_led_args legacy_args; - struct wmax_led_args wmax_args; + struct wmax_led_args wmax_basic_args; if (interface == WMAX) { - wmax_args.led_mask = 1 << zone->location; - wmax_args.colors = zone->colors; - wmax_args.state = lighting_control_state; + wmax_basic_args.led_mask = 1 << zone->location; + wmax_basic_args.colors = zone->colors; + wmax_basic_args.state = lighting_control_state; guid = WMAX_CONTROL_GUID; method_id = WMAX_METHOD_ZONE_CONTROL; - input.length = (acpi_size) sizeof(wmax_args); - input.pointer = &wmax_args; + input.length = (acpi_size) sizeof(wmax_basic_args); + input.pointer = &wmax_basic_args; } else { legacy_args.colors = zone->colors; legacy_args.brightness = global_brightness; @@ -449,11 +455,7 @@ static void alienware_zone_exit(struct platform_device *dev) kfree(zone_attrs); } -/* - The HDMI mux sysfs node indicates the status of the HDMI input mux. - It can toggle between standard system GPU output and HDMI input. -*/ -static acpi_status alienware_hdmi_command(struct hdmi_args *in_args, +static acpi_status alienware_wmax_command(struct wmax_basic_args *in_args, u32 command, int *out_data) { acpi_status status; @@ -481,16 +483,20 @@ static acpi_status alienware_hdmi_command(struct hdmi_args *in_args, } +/* + * The HDMI mux sysfs node indicates the status of the HDMI input mux. + * It can toggle between standard system GPU output and HDMI input. + */ static ssize_t show_hdmi_cable(struct device *dev, struct device_attribute *attr, char *buf) { acpi_status status; u32 out_data; - struct hdmi_args in_args = { + struct wmax_basic_args in_args = { .arg = 0, }; status = - alienware_hdmi_command(&in_args, WMAX_METHOD_HDMI_CABLE, + alienware_wmax_command(&in_args, WMAX_METHOD_HDMI_CABLE, (u32 *) &out_data); if (ACPI_SUCCESS(status)) { if (out_data == 0) @@ -509,11 +515,11 @@ static ssize_t show_hdmi_source(struct device *dev, { acpi_status status; u32 out_data; - struct hdmi_args in_args = { + struct wmax_basic_args in_args = { .arg = 0, }; status = - alienware_hdmi_command(&in_args, WMAX_METHOD_HDMI_STATUS, + alienware_wmax_command(&in_args, WMAX_METHOD_HDMI_STATUS, (u32 *) &out_data); if (ACPI_SUCCESS(status)) { @@ -533,7 +539,7 @@ static ssize_t toggle_hdmi_source(struct device *dev, const char *buf, size_t count) { acpi_status status; - struct hdmi_args args; + struct wmax_basic_args args; if (strcmp(buf, "gpu\n") == 0) args.arg = 1; else if (strcmp(buf, "input\n") == 0) @@ -542,7 +548,7 @@ static ssize_t toggle_hdmi_source(struct device *dev, args.arg = 3; pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf); - status = alienware_hdmi_command(&args, WMAX_METHOD_HDMI_SOURCE, NULL); + status = alienware_wmax_command(&args, WMAX_METHOD_HDMI_SOURCE, NULL); if (ACPI_FAILURE(status)) pr_err("alienware-wmi: HDMI toggle failed: results: %u\n", @@ -585,6 +591,62 @@ error_create_hdmi: return ret; } +/* + * Alienware GFX amplifier support + * - Currently supports reading cable status + * - Leaving expansion room to possibly support dock/undock events later + */ +static ssize_t show_amplifier_status(struct device *dev, + struct device_attribute *attr, char *buf) +{ + acpi_status status; + u32 out_data; + struct wmax_basic_args in_args = { + .arg = 0, + }; + status = + alienware_wmax_command(&in_args, WMAX_METHOD_AMPLIFIER_CABLE, + (u32 *) &out_data); + if (ACPI_SUCCESS(status)) { + if (out_data == 0) + return scnprintf(buf, PAGE_SIZE, + "[unconnected] connected unknown\n"); + else if (out_data == 1) + return scnprintf(buf, PAGE_SIZE, + "unconnected [connected] unknown\n"); + } + pr_err("alienware-wmi: unknown amplifier cable status: %d\n", status); + return scnprintf(buf, PAGE_SIZE, "unconnected connected [unknown]\n"); +} + +static DEVICE_ATTR(status, S_IRUGO, show_amplifier_status, NULL); + +static struct attribute *amplifier_attrs[] = { + &dev_attr_status.attr, + NULL, +}; + +static struct attribute_group amplifier_attribute_group = { + .name = "amplifier", + .attrs = amplifier_attrs, +}; + +static void remove_amplifier(struct platform_device *dev) +{ + if (quirks->amplifier > 0) + sysfs_remove_group(&dev->dev.kobj, &lifier_attribute_group); +} + +static int create_amplifier(struct platform_device *dev) +{ + int ret; + + ret = sysfs_create_group(&dev->dev.kobj, &lifier_attribute_group); + if (ret) + remove_amplifier(dev); + return ret; +} + static int __init alienware_wmi_init(void) { int ret; @@ -620,6 +682,12 @@ static int __init alienware_wmi_init(void) goto fail_prep_hdmi; } + if (quirks->amplifier > 0) { + ret = create_amplifier(platform_device); + if (ret) + goto fail_prep_amplifier; + } + ret = alienware_zone_init(platform_device); if (ret) goto fail_prep_zones; @@ -628,6 +696,7 @@ static int __init alienware_wmi_init(void) fail_prep_zones: alienware_zone_exit(platform_device); +fail_prep_amplifier: fail_prep_hdmi: platform_device_del(platform_device); fail_platform_device2: -- cgit v1.2.3 From 8ea81ec67b82fd35e389c3eef395206bac8e2259 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 2 Feb 2016 15:38:55 -0600 Subject: alienware-wmi: Add support for deep sleep control. Allow for user configuration of BIOS settings that allow the system to be turned on via HID devices. The feature requires hardware architectural modifications and can not be supported on existing systems. Signed-off-by: Mario Limonciello [dvhart: comment formatting and line length fixes] Signed-off-by: Darren Hart --- drivers/platform/x86/alienware-wmi.c | 95 ++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index fa86b7d5d6b5..a9f8d3044cd3 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c @@ -34,6 +34,8 @@ #define WMAX_METHOD_ZONE_CONTROL 0x4 #define WMAX_METHOD_HDMI_CABLE 0x5 #define WMAX_METHOD_AMPLIFIER_CABLE 0x6 +#define WMAX_METHOD_DEEP_SLEEP_CONTROL 0x0B +#define WMAX_METHOD_DEEP_SLEEP_STATUS 0x0C MODULE_AUTHOR("Mario Limonciello "); MODULE_DESCRIPTION("Alienware special feature control"); @@ -62,6 +64,7 @@ struct quirk_entry { u8 num_zones; u8 hdmi_mux; u8 amplifier; + u8 deepslp; }; static struct quirk_entry *quirks; @@ -70,24 +73,28 @@ static struct quirk_entry quirk_unknown = { .num_zones = 2, .hdmi_mux = 0, .amplifier = 0, + .deepslp = 0, }; static struct quirk_entry quirk_x51_r1_r2 = { .num_zones = 3, .hdmi_mux = 0, .amplifier = 0, + .deepslp = 0, }; static struct quirk_entry quirk_x51_r3 = { .num_zones = 4, .hdmi_mux = 0, .amplifier = 1, + .deepslp = 0, }; static struct quirk_entry quirk_asm100 = { .num_zones = 2, .hdmi_mux = 1, .amplifier = 0, + .deepslp = 0, }; static int __init dmi_matched(const struct dmi_system_id *dmi) @@ -647,6 +654,87 @@ static int create_amplifier(struct platform_device *dev) return ret; } +/* + * Deep Sleep Control support + * - Modifies BIOS setting for deep sleep control allowing extra wakeup events + */ +static ssize_t show_deepsleep_status(struct device *dev, + struct device_attribute *attr, char *buf) +{ + acpi_status status; + u32 out_data; + struct wmax_basic_args in_args = { + .arg = 0, + }; + status = alienware_wmax_command(&in_args, WMAX_METHOD_DEEP_SLEEP_STATUS, + (u32 *) &out_data); + if (ACPI_SUCCESS(status)) { + if (out_data == 0) + return scnprintf(buf, PAGE_SIZE, + "[disabled] s5 s5_s4\n"); + else if (out_data == 1) + return scnprintf(buf, PAGE_SIZE, + "disabled [s5] s5_s4\n"); + else if (out_data == 2) + return scnprintf(buf, PAGE_SIZE, + "disabled s5 [s5_s4]\n"); + } + pr_err("alienware-wmi: unknown deep sleep status: %d\n", status); + return scnprintf(buf, PAGE_SIZE, "disabled s5 s5_s4 [unknown]\n"); +} + +static ssize_t toggle_deepsleep(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + acpi_status status; + struct wmax_basic_args args; + + if (strcmp(buf, "disabled\n") == 0) + args.arg = 0; + else if (strcmp(buf, "s5\n") == 0) + args.arg = 1; + else + args.arg = 2; + pr_debug("alienware-wmi: setting deep sleep to %d : %s", args.arg, buf); + + status = alienware_wmax_command(&args, WMAX_METHOD_DEEP_SLEEP_CONTROL, + NULL); + + if (ACPI_FAILURE(status)) + pr_err("alienware-wmi: deep sleep control failed: results: %u\n", + status); + return count; +} + +static DEVICE_ATTR(deepsleep, S_IRUGO | S_IWUSR, show_deepsleep_status, toggle_deepsleep); + +static struct attribute *deepsleep_attrs[] = { + &dev_attr_deepsleep.attr, + NULL, +}; + +static struct attribute_group deepsleep_attribute_group = { + .name = "deepsleep", + .attrs = deepsleep_attrs, +}; + +static void remove_deepsleep(struct platform_device *dev) +{ + if (quirks->deepslp > 0) + sysfs_remove_group(&dev->dev.kobj, &deepsleep_attribute_group); +} + +static int create_deepsleep(struct platform_device *dev) +{ + int ret; + + ret = sysfs_create_group(&dev->dev.kobj, &deepsleep_attribute_group); + if (ret) + remove_deepsleep(dev); + return ret; +} + static int __init alienware_wmi_init(void) { int ret; @@ -688,6 +776,12 @@ static int __init alienware_wmi_init(void) goto fail_prep_amplifier; } + if (quirks->deepslp > 0) { + ret = create_deepsleep(platform_device); + if (ret) + goto fail_prep_deepsleep; + } + ret = alienware_zone_init(platform_device); if (ret) goto fail_prep_zones; @@ -696,6 +790,7 @@ static int __init alienware_wmi_init(void) fail_prep_zones: alienware_zone_exit(platform_device); +fail_prep_deepsleep: fail_prep_amplifier: fail_prep_hdmi: platform_device_del(platform_device); -- cgit v1.2.3 From b332f82e3868bc191914adfb1caadcc77c076df2 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 2 Feb 2016 15:38:56 -0600 Subject: alienware-wmi: Add support for two new systems: ASM200 and ASM201. Both of these systems support: * 2 lighting control zones * HDMI mux control * deep sleep control (to enable wakup from controller) The ASM201 also supports the external graphics amplifier. Signed-off-by: Mario Limonciello Signed-off-by: Darren Hart --- drivers/platform/x86/alienware-wmi.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index a9f8d3044cd3..275a56d47e56 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c @@ -97,6 +97,20 @@ static struct quirk_entry quirk_asm100 = { .deepslp = 0, }; +static struct quirk_entry quirk_asm200 = { + .num_zones = 2, + .hdmi_mux = 1, + .amplifier = 0, + .deepslp = 1, +}; + +static struct quirk_entry quirk_asm201 = { + .num_zones = 2, + .hdmi_mux = 1, + .amplifier = 1, + .deepslp = 1, +}; + static int __init dmi_matched(const struct dmi_system_id *dmi) { quirks = dmi->driver_data; @@ -140,6 +154,24 @@ static const struct dmi_system_id alienware_quirks[] __initconst = { }, .driver_data = &quirk_asm100, }, + { + .callback = dmi_matched, + .ident = "Alienware ASM200", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "ASM200"), + }, + .driver_data = &quirk_asm200, + }, + { + .callback = dmi_matched, + .ident = "Alienware ASM201", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "ASM201"), + }, + .driver_data = &quirk_asm201, + }, {} }; -- cgit v1.2.3 From ec5eeadc44bf05a8619627d6882fdf5775c19396 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 2 Feb 2016 15:38:57 -0600 Subject: alienware-wmi: whitespace improvements These were some items that were pointed out in previous patches that weren't caught be previous reviewers, but should be applied to other parts of the driver as well. Signed-off-by: Mario Limonciello [dvhart: reverted a couple incorrect line wrapping changes] Signed-off-by: Darren Hart --- drivers/platform/x86/alienware-wmi.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index 275a56d47e56..005629447b0c 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c @@ -229,7 +229,7 @@ static u8 global_brightness; /* * Helpers used for zone control -*/ + */ static int parse_rgb(const char *buf, struct platform_zone *zone) { long unsigned int rgb; @@ -269,7 +269,7 @@ static struct platform_zone *match_zone(struct device_attribute *attr) /* * Individual RGB zone control -*/ + */ static int alienware_update_led(struct platform_zone *zone) { int method_id; @@ -342,7 +342,7 @@ static ssize_t zone_set(struct device *dev, struct device_attribute *attr, /* * LED Brightness (Global) -*/ + */ static int wmax_brightness(int brightness) { acpi_status status; @@ -386,7 +386,7 @@ static struct led_classdev global_led = { /* * Lighting control state device attribute (Global) -*/ + */ static ssize_t show_control_state(struct device *dev, struct device_attribute *attr, char *buf) { @@ -622,11 +622,7 @@ static int create_hdmi(struct platform_device *dev) ret = sysfs_create_group(&dev->dev.kobj, &hdmi_attribute_group); if (ret) - goto error_create_hdmi; - return 0; - -error_create_hdmi: - remove_hdmi(dev); + remove_hdmi(dev); return ret; } -- cgit v1.2.3 From 7a23f80eaae9c6b5175cd7a96634a91ed9928aff Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 22:46:48 +0200 Subject: watchdog: mei_wdt: register wd device only if required For Intel Broadwell and newer platforms, the ME device can inform the host whether the watchdog functionality is activated or not. If the watchdog functionality is not activated then the watchdog interface can be not registered and eliminate unnecessary pings and hence lower the power consumption by avoiding waking up the device. The feature can be deactivated also without reboot in that case the watchdog device should be unregistered at runtime. The information regarding the deactivation is reported in the ping response command. In runtime case the unregistration has to be run from a worker so that the ping initiated by the watchdog core completes. Otherwise the flow will deadlock on watchdog core mutex which both ping and unregistration acquire. Reviewed-by: Guenter Roeck Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/watchdog/mei_wdt.c | 200 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 191 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c index e7e3f144f2b0..9addf8902f74 100644 --- a/drivers/watchdog/mei_wdt.c +++ b/drivers/watchdog/mei_wdt.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -38,27 +39,35 @@ /* Sub Commands */ #define MEI_MC_START_WD_TIMER_REQ 0x13 +#define MEI_MC_START_WD_TIMER_RES 0x83 +#define MEI_WDT_STATUS_SUCCESS 0 +#define MEI_WDT_WDSTATE_NOT_REQUIRED 0x1 #define MEI_MC_STOP_WD_TIMER_REQ 0x14 /** * enum mei_wdt_state - internal watchdog state * + * @MEI_WDT_PROBE: wd in probing stage * @MEI_WDT_IDLE: wd is idle and not opened * @MEI_WDT_START: wd was opened, start was called * @MEI_WDT_RUNNING: wd is expecting keep alive pings * @MEI_WDT_STOPPING: wd is stopping and will move to IDLE + * @MEI_WDT_NOT_REQUIRED: wd device is not required */ enum mei_wdt_state { + MEI_WDT_PROBE, MEI_WDT_IDLE, MEI_WDT_START, MEI_WDT_RUNNING, MEI_WDT_STOPPING, + MEI_WDT_NOT_REQUIRED, }; -#if IS_ENABLED(CONFIG_DEBUG_FS) static const char *mei_wdt_state_str(enum mei_wdt_state state) { switch (state) { + case MEI_WDT_PROBE: + return "PROBE"; case MEI_WDT_IDLE: return "IDLE"; case MEI_WDT_START: @@ -67,11 +76,12 @@ static const char *mei_wdt_state_str(enum mei_wdt_state state) return "RUNNING"; case MEI_WDT_STOPPING: return "STOPPING"; + case MEI_WDT_NOT_REQUIRED: + return "NOT_REQUIRED"; default: return "unknown"; } } -#endif /* CONFIG_DEBUG_FS */ /** * struct mei_wdt - mei watchdog driver @@ -79,6 +89,10 @@ static const char *mei_wdt_state_str(enum mei_wdt_state state) * * @cldev: mei watchdog client device * @state: watchdog internal state + * @resp_required: ping required response + * @response: ping response completion + * @unregister: unregister worker + * @reg_lock: watchdog device registration lock * @timeout: watchdog current timeout * * @dbgfs_dir: debugfs dir entry @@ -88,6 +102,10 @@ struct mei_wdt { struct mei_cl_device *cldev; enum mei_wdt_state state; + bool resp_required; + struct completion response; + struct work_struct unregister; + struct mutex reg_lock; u16 timeout; #if IS_ENABLED(CONFIG_DEBUG_FS) @@ -123,6 +141,19 @@ struct mei_wdt_start_request { u8 reserved[17]; } __packed; +/** + * struct mei_wdt_start_response watchdog start/ping response + * + * @hdr: Management Control Command Header + * @status: operation status + * @wdstate: watchdog status bit mask + */ +struct mei_wdt_start_response { + struct mei_mc_hdr hdr; + u8 status; + u8 wdstate; +} __packed; + /** * struct mei_wdt_stop_request - watchdog stop * @@ -244,13 +275,18 @@ static int mei_wdt_ops_ping(struct watchdog_device *wdd) if (wdt->state != MEI_WDT_START && wdt->state != MEI_WDT_RUNNING) return 0; + if (wdt->resp_required) + init_completion(&wdt->response); + + wdt->state = MEI_WDT_RUNNING; ret = mei_wdt_ping(wdt); if (ret) return ret; - wdt->state = MEI_WDT_RUNNING; + if (wdt->resp_required) + ret = wait_for_completion_killable(&wdt->response); - return 0; + return ret; } /** @@ -290,6 +326,19 @@ static struct watchdog_info wd_info = { WDIOF_ALARMONLY, }; +/** + * __mei_wdt_is_registered - check if wdt is registered + * + * @wdt: mei watchdog device + * + * Return: true if the wdt is registered with the watchdog subsystem + * Locking: should be called under wdt->reg_lock + */ +static inline bool __mei_wdt_is_registered(struct mei_wdt *wdt) +{ + return !!watchdog_get_drvdata(&wdt->wdd); +} + /** * mei_wdt_unregister - unregister from the watchdog subsystem * @@ -297,8 +346,15 @@ static struct watchdog_info wd_info = { */ static void mei_wdt_unregister(struct mei_wdt *wdt) { - watchdog_unregister_device(&wdt->wdd); - watchdog_set_drvdata(&wdt->wdd, NULL); + mutex_lock(&wdt->reg_lock); + + if (__mei_wdt_is_registered(wdt)) { + watchdog_unregister_device(&wdt->wdd); + watchdog_set_drvdata(&wdt->wdd, NULL); + memset(&wdt->wdd, 0, sizeof(wdt->wdd)); + } + + mutex_unlock(&wdt->reg_lock); } /** @@ -318,6 +374,13 @@ static int mei_wdt_register(struct mei_wdt *wdt) dev = &wdt->cldev->dev; + mutex_lock(&wdt->reg_lock); + + if (__mei_wdt_is_registered(wdt)) { + ret = 0; + goto out; + } + wdt->wdd.info = &wd_info; wdt->wdd.ops = &wd_ops; wdt->wdd.parent = dev; @@ -332,9 +395,106 @@ static int mei_wdt_register(struct mei_wdt *wdt) watchdog_set_drvdata(&wdt->wdd, NULL); } + wdt->state = MEI_WDT_IDLE; + +out: + mutex_unlock(&wdt->reg_lock); return ret; } +static void mei_wdt_unregister_work(struct work_struct *work) +{ + struct mei_wdt *wdt = container_of(work, struct mei_wdt, unregister); + + mei_wdt_unregister(wdt); +} + +/** + * mei_wdt_event_rx - callback for data receive + * + * @cldev: bus device + */ +static void mei_wdt_event_rx(struct mei_cl_device *cldev) +{ + struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); + struct mei_wdt_start_response res; + const size_t res_len = sizeof(res); + int ret; + + ret = mei_cldev_recv(wdt->cldev, (u8 *)&res, res_len); + if (ret < 0) { + dev_err(&cldev->dev, "failure in recv %d\n", ret); + return; + } + + /* Empty response can be sent on stop */ + if (ret == 0) + return; + + if (ret < sizeof(struct mei_mc_hdr)) { + dev_err(&cldev->dev, "recv small data %d\n", ret); + return; + } + + if (res.hdr.command != MEI_MANAGEMENT_CONTROL || + res.hdr.versionnumber != MEI_MC_VERSION_NUMBER) { + dev_err(&cldev->dev, "wrong command received\n"); + return; + } + + if (res.hdr.subcommand != MEI_MC_START_WD_TIMER_RES) { + dev_warn(&cldev->dev, "unsupported command %d :%s[%d]\n", + res.hdr.subcommand, + mei_wdt_state_str(wdt->state), + wdt->state); + return; + } + + /* Run the unregistration in a worker as this can be + * run only after ping completion, otherwise the flow will + * deadlock on watchdog core mutex. + */ + if (wdt->state == MEI_WDT_RUNNING) { + if (res.wdstate & MEI_WDT_WDSTATE_NOT_REQUIRED) { + wdt->state = MEI_WDT_NOT_REQUIRED; + schedule_work(&wdt->unregister); + } + goto out; + } + + if (wdt->state == MEI_WDT_PROBE) { + if (res.wdstate & MEI_WDT_WDSTATE_NOT_REQUIRED) { + wdt->state = MEI_WDT_NOT_REQUIRED; + } else { + /* stop the watchdog and register watchdog device */ + mei_wdt_stop(wdt); + mei_wdt_register(wdt); + } + return; + } + + dev_warn(&cldev->dev, "not in correct state %s[%d]\n", + mei_wdt_state_str(wdt->state), wdt->state); + +out: + if (!completion_done(&wdt->response)) + complete(&wdt->response); +} + +/** + * mei_wdt_event - callback for event receive + * + * @cldev: bus device + * @events: event mask + * @context: callback context + */ +static void mei_wdt_event(struct mei_cl_device *cldev, + u32 events, void *context) +{ + if (events & BIT(MEI_CL_EVENT_RX)) + mei_wdt_event_rx(cldev); +} + #if IS_ENABLED(CONFIG_DEBUG_FS) static ssize_t mei_dbgfs_read_state(struct file *file, char __user *ubuf, @@ -403,8 +563,13 @@ static int mei_wdt_probe(struct mei_cl_device *cldev, return -ENOMEM; wdt->timeout = MEI_WDT_DEFAULT_TIMEOUT; - wdt->state = MEI_WDT_IDLE; + wdt->state = MEI_WDT_PROBE; wdt->cldev = cldev; + wdt->resp_required = mei_cldev_ver(cldev) > 0x1; + mutex_init(&wdt->reg_lock); + init_completion(&wdt->response); + INIT_WORK(&wdt->unregister, mei_wdt_unregister_work); + mei_cldev_set_drvdata(cldev, wdt); ret = mei_cldev_enable(cldev); @@ -413,9 +578,20 @@ static int mei_wdt_probe(struct mei_cl_device *cldev, goto err_out; } + ret = mei_cldev_register_event_cb(wdt->cldev, BIT(MEI_CL_EVENT_RX), + mei_wdt_event, NULL); + if (ret) { + dev_err(&cldev->dev, "Could not register event ret=%d\n", ret); + goto err_disable; + } + wd_info.firmware_version = mei_cldev_ver(cldev); - ret = mei_wdt_register(wdt); + if (wdt->resp_required) + ret = mei_wdt_ping(wdt); + else + ret = mei_wdt_register(wdt); + if (ret) goto err_disable; @@ -437,6 +613,12 @@ static int mei_wdt_remove(struct mei_cl_device *cldev) { struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); + /* Free the caller in case of fw initiated or unexpected reset */ + if (!completion_done(&wdt->response)) + complete(&wdt->response); + + cancel_work_sync(&wdt->unregister); + mei_wdt_unregister(wdt); mei_cldev_disable(cldev); @@ -452,7 +634,7 @@ static int mei_wdt_remove(struct mei_cl_device *cldev) 0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB) static struct mei_cl_device_id mei_wdt_tbl[] = { - { .uuid = MEI_UUID_WD, .version = 0x1}, + { .uuid = MEI_UUID_WD, .version = MEI_CL_VERSION_ANY }, /* required last entry */ { } }; -- cgit v1.2.3 From ad1cd720b18330599a9cabaf970095b74c9c3355 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 22:46:49 +0200 Subject: watchdog: mei_wdt: add activation debugfs entry Add entry for displaying whether the device has activated or deactivated watchdog fw application. cat /mei_wdt/activation activated | deactivated Reviewed-by: Guenter Roeck Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/watchdog/mei_wdt.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers') diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c index 9addf8902f74..b93474ec34a1 100644 --- a/drivers/watchdog/mei_wdt.c +++ b/drivers/watchdog/mei_wdt.c @@ -497,6 +497,28 @@ static void mei_wdt_event(struct mei_cl_device *cldev, #if IS_ENABLED(CONFIG_DEBUG_FS) +static ssize_t mei_dbgfs_read_activation(struct file *file, char __user *ubuf, + size_t cnt, loff_t *ppos) +{ + struct mei_wdt *wdt = file->private_data; + const size_t bufsz = 32; + char buf[32]; + ssize_t pos; + + mutex_lock(&wdt->reg_lock); + pos = scnprintf(buf, bufsz, "%s\n", + __mei_wdt_is_registered(wdt) ? "activated" : "deactivated"); + mutex_unlock(&wdt->reg_lock); + + return simple_read_from_buffer(ubuf, cnt, ppos, buf, pos); +} + +static const struct file_operations dbgfs_fops_activation = { + .open = simple_open, + .read = mei_dbgfs_read_activation, + .llseek = generic_file_llseek, +}; + static ssize_t mei_dbgfs_read_state(struct file *file, char __user *ubuf, size_t cnt, loff_t *ppos) { @@ -536,6 +558,11 @@ static int dbgfs_register(struct mei_wdt *wdt) if (!f) goto err; + f = debugfs_create_file("activation", S_IRUSR, + dir, wdt, &dbgfs_fops_activation); + if (!f) + goto err; + return 0; err: dbgfs_unregister(wdt); -- cgit v1.2.3 From 3a20a5c339cce042e53557be067e121e4e984adf Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 22:46:50 +0200 Subject: watchdog: mei_wdt: re-register device on event For Intel SKL platform the ME device can inform the host via asynchronous notification that the watchdog feature was activated on the device. The activation doesn't require reboot. In that case the driver registers the watchdog device with the kernel. Reviewed-by: Guenter Roeck Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/watchdog/mei_wdt.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c index b93474ec34a1..630bd189f167 100644 --- a/drivers/watchdog/mei_wdt.c +++ b/drivers/watchdog/mei_wdt.c @@ -481,6 +481,21 @@ out: complete(&wdt->response); } +/* + * mei_wdt_notify_event - callback for event notification + * + * @cldev: bus device + */ +static void mei_wdt_notify_event(struct mei_cl_device *cldev) +{ + struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); + + if (wdt->state != MEI_WDT_NOT_REQUIRED) + return; + + mei_wdt_register(wdt); +} + /** * mei_wdt_event - callback for event receive * @@ -493,6 +508,9 @@ static void mei_wdt_event(struct mei_cl_device *cldev, { if (events & BIT(MEI_CL_EVENT_RX)) mei_wdt_event_rx(cldev); + + if (events & BIT(MEI_CL_EVENT_NOTIF)) + mei_wdt_notify_event(cldev); } #if IS_ENABLED(CONFIG_DEBUG_FS) @@ -605,9 +623,15 @@ static int mei_wdt_probe(struct mei_cl_device *cldev, goto err_out; } - ret = mei_cldev_register_event_cb(wdt->cldev, BIT(MEI_CL_EVENT_RX), + ret = mei_cldev_register_event_cb(wdt->cldev, + BIT(MEI_CL_EVENT_RX) | + BIT(MEI_CL_EVENT_NOTIF), mei_wdt_event, NULL); - if (ret) { + + /* on legacy devices notification is not supported + * this doesn't fail the registration for RX event + */ + if (ret && ret != -EOPNOTSUPP) { dev_err(&cldev->dev, "Could not register event ret=%d\n", ret); goto err_disable; } -- cgit v1.2.3 From a96c548291719ae40da1b3c52493f40a63d3dd84 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 22:46:51 +0200 Subject: mei: trace pci configuration space io Use tracing events also for reading and writing pci configuration space /tracing/events/mei/mei_pci_reg_{read,write} Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 10 ++++++++-- drivers/misc/mei/hw-txe.c | 10 ++++++++-- drivers/misc/mei/mei-trace.c | 2 ++ drivers/misc/mei/mei-trace.h | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 25b1997a62cb..e2fb44cc5c37 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -189,8 +189,11 @@ static int mei_me_fw_status(struct mei_device *dev, fw_status->count = fw_src->count; for (i = 0; i < fw_src->count && i < MEI_FW_STATUS_MAX; i++) { - ret = pci_read_config_dword(pdev, - fw_src->status[i], &fw_status->status[i]); + ret = pci_read_config_dword(pdev, fw_src->status[i], + &fw_status->status[i]); + trace_mei_pci_cfg_read(dev->dev, "PCI_CFG_HSF_X", + fw_src->status[i], + fw_status->status[i]); if (ret) return ret; } @@ -215,6 +218,7 @@ static void mei_me_hw_config(struct mei_device *dev) reg = 0; pci_read_config_dword(pdev, PCI_CFG_HFS_1, ®); + trace_mei_pci_cfg_read(dev->dev, "PCI_CFG_HFS_1", PCI_CFG_HFS_1, reg); hw->d0i3_supported = ((reg & PCI_CFG_HFS_1_D0I3_MSK) == PCI_CFG_HFS_1_D0I3_MSK); @@ -1248,6 +1252,7 @@ static bool mei_me_fw_type_nm(struct pci_dev *pdev) u32 reg; pci_read_config_dword(pdev, PCI_CFG_HFS_2, ®); + trace_mei_pci_cfg_read(&pdev->dev, "PCI_CFG_HFS_2", PCI_CFG_HFS_2, reg); /* make sure that bit 9 (NM) is up and bit 10 (DM) is down */ return (reg & 0x600) == 0x200; } @@ -1260,6 +1265,7 @@ static bool mei_me_fw_type_sps(struct pci_dev *pdev) u32 reg; /* Read ME FW Status check for SPS Firmware */ pci_read_config_dword(pdev, PCI_CFG_HFS_1, ®); + trace_mei_pci_cfg_read(&pdev->dev, "PCI_CFG_HFS_1", PCI_CFG_HFS_1, reg); /* if bits [19:16] = 15, running SPS Firmware */ return (reg & 0xf0000) == 0xf0000; } diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c index bae680c648ff..4a6c1b85f11e 100644 --- a/drivers/misc/mei/hw-txe.c +++ b/drivers/misc/mei/hw-txe.c @@ -28,6 +28,9 @@ #include "client.h" #include "hbm.h" +#include "mei-trace.h" + + /** * mei_txe_reg_read - Reads 32bit data from the txe device * @@ -640,8 +643,11 @@ static int mei_txe_fw_status(struct mei_device *dev, fw_status->count = fw_src->count; for (i = 0; i < fw_src->count && i < MEI_FW_STATUS_MAX; i++) { - ret = pci_read_config_dword(pdev, - fw_src->status[i], &fw_status->status[i]); + ret = pci_read_config_dword(pdev, fw_src->status[i], + &fw_status->status[i]); + trace_mei_pci_cfg_read(dev->dev, "PCI_CFG_HSF_X", + fw_src->status[i], + fw_status->status[i]); if (ret) return ret; } diff --git a/drivers/misc/mei/mei-trace.c b/drivers/misc/mei/mei-trace.c index 388efb519138..e19e6acb191b 100644 --- a/drivers/misc/mei/mei-trace.c +++ b/drivers/misc/mei/mei-trace.c @@ -22,4 +22,6 @@ EXPORT_TRACEPOINT_SYMBOL(mei_reg_read); EXPORT_TRACEPOINT_SYMBOL(mei_reg_write); +EXPORT_TRACEPOINT_SYMBOL(mei_pci_cfg_read); +EXPORT_TRACEPOINT_SYMBOL(mei_pci_cfg_write); #endif /* __CHECKER__ */ diff --git a/drivers/misc/mei/mei-trace.h b/drivers/misc/mei/mei-trace.h index 47e1bc6551d4..86e5068837c1 100644 --- a/drivers/misc/mei/mei-trace.h +++ b/drivers/misc/mei/mei-trace.h @@ -64,6 +64,44 @@ TRACE_EVENT(mei_reg_write, __get_str(dev), __entry->reg, __entry->offs, __entry->val) ); +TRACE_EVENT(mei_pci_cfg_read, + TP_PROTO(const struct device *dev, const char *reg, u32 offs, u32 val), + TP_ARGS(dev, reg, offs, val), + TP_STRUCT__entry( + __string(dev, dev_name(dev)) + __field(const char *, reg) + __field(u32, offs) + __field(u32, val) + ), + TP_fast_assign( + __assign_str(dev, dev_name(dev)) + __entry->reg = reg; + __entry->offs = offs; + __entry->val = val; + ), + TP_printk("[%s] pci cfg read %s:[%#x] = %#x", + __get_str(dev), __entry->reg, __entry->offs, __entry->val) +); + +TRACE_EVENT(mei_pci_cfg_write, + TP_PROTO(const struct device *dev, const char *reg, u32 offs, u32 val), + TP_ARGS(dev, reg, offs, val), + TP_STRUCT__entry( + __string(dev, dev_name(dev)) + __field(const char *, reg) + __field(u32, offs) + __field(u32, val) + ), + TP_fast_assign( + __assign_str(dev, dev_name(dev)) + __entry->reg = reg; + __entry->offs = offs; + __entry->val = val; + ), + TP_printk("[%s] pci cfg write %s[%#x] = %#x)", + __get_str(dev), __entry->reg, __entry->offs, __entry->val) +); + #endif /* _MEI_TRACE_H_ */ /* This part must be outside protection */ -- cgit v1.2.3 From 98cb4ab09e772d791b7150c38574a024b9801b47 Mon Sep 17 00:00:00 2001 From: Jakob Østergaard Jensen Date: Sun, 7 Feb 2016 12:36:12 +0100 Subject: tty: serial: jsm_tty: fixed redundant variable issue. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The variable "len" gets assigned once and it's value copied to "n", which is then used for the rest of the function. This patch fixes the unnecessary variable reassignment by using "len" throughout the function instead. Signed-off-by: Jakob Østergaard Jensen Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/jsm/jsm_tty.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c index 00cac10ae75a..c5ddfe542451 100644 --- a/drivers/tty/serial/jsm/jsm_tty.c +++ b/drivers/tty/serial/jsm/jsm_tty.c @@ -529,7 +529,6 @@ void jsm_input(struct jsm_channel *ch) int data_len; unsigned long lock_flags; int len = 0; - int n = 0; int s = 0; int i = 0; @@ -597,16 +596,15 @@ void jsm_input(struct jsm_channel *ch) jsm_dbg(READ, &ch->ch_bd->pci_dev, "start 2\n"); len = tty_buffer_request_room(port, data_len); - n = len; /* - * n now contains the most amount of data we can copy, + * len now contains the most amount of data we can copy, * bounded either by the flip buffer size or the amount * of data the card actually has pending... */ - while (n) { + while (len) { s = ((head >= tail) ? head : RQUEUESIZE) - tail; - s = min(s, n); + s = min(s, len); if (s <= 0) break; @@ -637,7 +635,7 @@ void jsm_input(struct jsm_channel *ch) tty_insert_flip_string(port, ch->ch_rqueue + tail, s); } tail += s; - n -= s; + len -= s; /* Flip queue if needed */ tail &= rmask; } -- cgit v1.2.3 From 26900254827878c4f98c0d169f8ba290099b1ef3 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:17 +0200 Subject: mei: debugfs: adjust active clients print buffer In case of many active host clients clients (41 and more) 1K buffer is not enough for full information print. Calculate buffer size according to real clients number. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/debugfs.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c index a138d8a27ab5..9f5410b98688 100644 --- a/drivers/misc/mei/debugfs.c +++ b/drivers/misc/mei/debugfs.c @@ -50,6 +50,7 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf, } pos += scnprintf(buf + pos, bufsz - pos, HDR); +#undef HDR /* if the driver is not enabled the list won't be consistent */ if (dev->dev_state != MEI_DEV_ENABLED) @@ -90,23 +91,37 @@ static ssize_t mei_dbgfs_read_active(struct file *fp, char __user *ubuf, { struct mei_device *dev = fp->private_data; struct mei_cl *cl; - const size_t bufsz = 1024; + size_t bufsz = 1; char *buf; int i = 0; int pos = 0; int ret; +#define HDR " |me|host|state|rd|wr|\n" + if (!dev) return -ENODEV; + mutex_lock(&dev->device_lock); + + /* + * if the driver is not enabled the list won't be consistent, + * we output empty table + */ + if (dev->dev_state == MEI_DEV_ENABLED) + list_for_each_entry(cl, &dev->file_list, link) + bufsz++; + + bufsz *= sizeof(HDR) + 1; + buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) + if (!buf) { + mutex_unlock(&dev->device_lock); return -ENOMEM; + } - pos += scnprintf(buf + pos, bufsz - pos, - " |me|host|state|rd|wr|\n"); - - mutex_lock(&dev->device_lock); + pos += scnprintf(buf + pos, bufsz - pos, HDR); +#undef HDR /* if the driver is not enabled the list won't be consistent */ if (dev->dev_state != MEI_DEV_ENABLED) @@ -115,7 +130,7 @@ static ssize_t mei_dbgfs_read_active(struct file *fp, char __user *ubuf, list_for_each_entry(cl, &dev->file_list, link) { pos += scnprintf(buf + pos, bufsz - pos, - "%2d|%2d|%4d|%5d|%2d|%2d|\n", + "%3d|%2d|%4d|%5d|%2d|%2d|\n", i, mei_cl_me_id(cl), cl->host_client_id, cl->state, !list_empty(&cl->rd_completed), cl->writing_state); i++; -- cgit v1.2.3 From 439a74b3373dab4214b4191d50dfb1d78be5b18e Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:18 +0200 Subject: mei: debugfs: allow hbm features list dump in earlier stages HBM features list is ready while sending enumerate request and enumerating clients, output it to debugfs in these states too. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/debugfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c index 9f5410b98688..6bdd75424fe8 100644 --- a/drivers/misc/mei/debugfs.c +++ b/drivers/misc/mei/debugfs.c @@ -165,7 +165,8 @@ static ssize_t mei_dbgfs_read_devstate(struct file *fp, char __user *ubuf, pos += scnprintf(buf + pos, bufsz - pos, "hbm: %s\n", mei_hbm_state_str(dev->hbm_state)); - if (dev->hbm_state == MEI_HBM_STARTED) { + if (dev->hbm_state >= MEI_HBM_ENUM_CLIENTS && + dev->hbm_state <= MEI_HBM_STARTED) { pos += scnprintf(buf + pos, bufsz - pos, "hbm features:\n"); pos += scnprintf(buf + pos, bufsz - pos, "\tPG: %01d\n", dev->hbm_f_pg_supported); -- cgit v1.2.3 From f862b6b24f0ffd954633a55f39251a6873b664ca Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 23:35:19 +0200 Subject: mei: fix possible integer overflow issue There is a possible integer overflow following by a buffer overflow when accumulating messages coming from the FW to compose a full payload. Occurrence of wrap around has to be prevented for next message size calculation. For unsigned integer the addition overflow has occurred when the result is smaller than one of the arguments. To simplify the fix, the types of buf.size and buf_idx are set to the same width, namely size_t also to be aligned with the type of length parameter in file read/write ops. Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 5 ++--- drivers/misc/mei/client.c | 2 +- drivers/misc/mei/interrupt.c | 21 ++++++++++++++++----- drivers/misc/mei/main.c | 5 +++-- drivers/misc/mei/mei_dev.h | 4 ++-- 5 files changed, 24 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index cd0403f09267..b753df98b476 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -195,9 +195,8 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, * remove message from deletion list */ - dev_dbg(dev->dev, "amthif cb->buf size - %d\n", - cb->buf.size); - dev_dbg(dev->dev, "amthif cb->buf_idx - %lu\n", cb->buf_idx); + dev_dbg(dev->dev, "amthif cb->buf.size - %zd cb->buf_idx - %zd\n", + cb->buf.size, cb->buf_idx); /* length is being truncated to PAGE_SIZE, however, * the buf_idx may point beyond */ diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index e069fcaed7aa..738f3d703323 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1569,7 +1569,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, return 0; } - cl_dbg(dev, cl, "buf: size = %d idx = %lu\n", + cl_dbg(dev, cl, "buf: size = %zd idx = %zd\n", cb->buf.size, cb->buf_idx); rets = mei_write_message(dev, &mei_hdr, buf->data + cb->buf_idx); diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 6340dee33052..b8aa047ec258 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -104,6 +104,7 @@ int mei_cl_irq_read_msg(struct mei_cl *cl, struct mei_device *dev = cl->dev; struct mei_cl_cb *cb; unsigned char *buffer = NULL; + size_t buf_sz; cb = list_first_entry_or_null(&cl->rd_pending, struct mei_cl_cb, list); if (!cb) { @@ -124,11 +125,21 @@ int mei_cl_irq_read_msg(struct mei_cl *cl, goto out; } - if (cb->buf.size < mei_hdr->length + cb->buf_idx) { - cl_dbg(dev, cl, "message overflow. size %d len %d idx %ld\n", + buf_sz = mei_hdr->length + cb->buf_idx; + /* catch for integer overflow */ + if (buf_sz < cb->buf_idx) { + cl_err(dev, cl, "message is too big len %d idx %ld\n", + mei_hdr->length, cb->buf_idx); + + list_move_tail(&cb->list, &complete_list->list); + cb->status = -EMSGSIZE; + goto out; + } + + if (cb->buf.size < buf_sz) { + cl_dbg(dev, cl, "message overflow. size %zd len %d idx %zd\n", cb->buf.size, mei_hdr->length, cb->buf_idx); - buffer = krealloc(cb->buf.data, mei_hdr->length + cb->buf_idx, - GFP_KERNEL); + buffer = krealloc(cb->buf.data, buf_sz, GFP_KERNEL); if (!buffer) { cb->status = -ENOMEM; @@ -136,7 +147,7 @@ int mei_cl_irq_read_msg(struct mei_cl *cl, goto out; } cb->buf.data = buffer; - cb->buf.size = mei_hdr->length + cb->buf_idx; + cb->buf.size = buf_sz; } buffer = cb->buf.data + cb->buf_idx; diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 36ca15234344..47dc6d9ae655 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -226,7 +226,7 @@ copy_buffer: goto free; } - cl_dbg(dev, cl, "buf.size = %d buf.idx = %ld offset = %lld\n", + cl_dbg(dev, cl, "buf.size = %zd buf.idx = %zd offset = %lld\n", cb->buf.size, cb->buf_idx, *offset); if (*offset >= cb->buf_idx) { rets = 0; @@ -245,7 +245,8 @@ copy_buffer: rets = length; *offset += length; - if ((unsigned long)*offset < cb->buf_idx) + /* not all data was read, keep the cb */ + if (*offset < cb->buf_idx) goto out; free: diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index da613268480c..9b793f87b7d4 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -126,7 +126,7 @@ enum mei_cb_file_ops { * Intel MEI message data struct */ struct mei_msg_data { - u32 size; + size_t size; unsigned char *data; }; @@ -190,7 +190,7 @@ struct mei_cl_cb { struct mei_cl *cl; enum mei_cb_file_ops fop_type; struct mei_msg_data buf; - unsigned long buf_idx; + size_t buf_idx; unsigned long read_time; struct file *file_object; int status; -- cgit v1.2.3 From 1f7e489a285c8b1aca9a7b66a55bbc95eb031721 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:20 +0200 Subject: mei: call stop on failed char device register If registering of character device failed stop the device properly. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/pci-me.c | 4 +++- drivers/misc/mei/pci-txe.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 75fc9c688df8..996344f6c32d 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -210,7 +210,7 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = mei_register(dev, &pdev->dev); if (err) - goto release_irq; + goto stop; pci_set_drvdata(pdev, dev); @@ -231,6 +231,8 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; +stop: + mei_stop(dev); release_irq: mei_cancel_work(dev); mei_disable_interrupts(dev); diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c index 71f8a7475717..30cc30683c07 100644 --- a/drivers/misc/mei/pci-txe.c +++ b/drivers/misc/mei/pci-txe.c @@ -154,7 +154,7 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = mei_register(dev, &pdev->dev); if (err) - goto release_irq; + goto stop; pci_set_drvdata(pdev, dev); @@ -170,6 +170,8 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; +stop: + mei_stop(dev); release_irq: mei_cancel_work(dev); -- cgit v1.2.3 From 5ba0bf476c792b91543da77e0bdec311b0eaa8f7 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:21 +0200 Subject: mei: amthif: don't copy from an empty buffer If empty message come from FW (buf_idx == 0) then the current code will still try to copy data from not filled buffer to the user-space, instead the code should behave the same as when end of a message has been reached, clean resources and return 0 Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index b753df98b476..c3f514027c80 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -185,7 +185,7 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, /* if the whole message will fit remove it from the list */ if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset)) list_del_init(&cb->list); - else if (cb->buf_idx > 0 && cb->buf_idx <= *offset) { + else if (cb->buf_idx <= *offset) { /* end of the message has been reached */ list_del_init(&cb->list); rets = 0; -- cgit v1.2.3 From d0df8dfb8582f50053bde6a771262571daedf5d0 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:22 +0200 Subject: mei: amthif: don't drop read packets on timeout Since the driver now uses a list for storing read packets instead of single variable a pending read is no longer blocking other connections. A pending read will be discarded up the file closure. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 27 --------------------------- drivers/misc/mei/hw.h | 1 - drivers/misc/mei/interrupt.c | 32 -------------------------------- drivers/misc/mei/main.c | 16 ---------------- drivers/misc/mei/mei_dev.h | 4 ---- 5 files changed, 80 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index c3f514027c80..5da1654bc209 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -50,7 +50,6 @@ void mei_amthif_reset_params(struct mei_device *dev) dev->iamthif_current_cb = NULL; dev->iamthif_canceled = false; dev->iamthif_state = MEI_IAMTHIF_IDLE; - dev->iamthif_timer = 0; dev->iamthif_stall_timer = 0; dev->iamthif_open_count = 0; } @@ -124,18 +123,10 @@ struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, int mei_amthif_read(struct mei_device *dev, struct file *file, char __user *ubuf, size_t length, loff_t *offset) { - struct mei_cl *cl = file->private_data; struct mei_cl_cb *cb; - unsigned long timeout; int rets; int wait_ret; - /* Only possible if we are in timeout */ - if (!cl) { - dev_err(dev->dev, "bad file ext.\n"); - return -ETIME; - } - dev_dbg(dev->dev, "checking amthif data\n"); cb = mei_amthif_find_read_list_entry(dev, file); @@ -168,20 +159,6 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, } dev_dbg(dev->dev, "Got amthif data\n"); - dev->iamthif_timer = 0; - - timeout = cb->read_time + - mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER); - dev_dbg(dev->dev, "amthif timeout = %lud\n", - timeout); - - if (time_after(jiffies, timeout)) { - dev_dbg(dev->dev, "amthif Time out\n"); - /* 15 sec for the message has expired */ - list_del_init(&cb->list); - rets = -ETIME; - goto free; - } /* if the whole message will fit remove it from the list */ if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset)) list_del_init(&cb->list); @@ -303,7 +280,6 @@ int mei_amthif_run_next_cmd(struct mei_device *dev) dev->iamthif_canceled = false; dev->iamthif_state = MEI_IAMTHIF_IDLE; - dev->iamthif_timer = 0; dev->iamthif_file_object = NULL; dev_dbg(dev->dev, "complete amthif cmd_list cb.\n"); @@ -462,9 +438,6 @@ void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb) dev->iamthif_stall_timer = 0; list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list); dev_dbg(dev->dev, "amthif read completed\n"); - dev->iamthif_timer = jiffies; - dev_dbg(dev->dev, "dev->iamthif_timer = %ld\n", - dev->iamthif_timer); } else { mei_amthif_run_next_cmd(dev); } diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h index 4cebde85924f..4c5d6cfd79b4 100644 --- a/drivers/misc/mei/hw.h +++ b/drivers/misc/mei/hw.h @@ -29,7 +29,6 @@ #define MEI_CLIENTS_INIT_TIMEOUT 15 /* HPS: Clients Enumeration Timeout */ #define MEI_IAMTHIF_STALL_TIMER 12 /* HPS */ -#define MEI_IAMTHIF_READ_TIMER 10 /* HPS */ #define MEI_PGI_TIMEOUT 1 /* PG Isolation time response 1 sec */ #define MEI_D0I3_TIMEOUT 5 /* D0i3 set/unset max response time */ diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index b8aa047ec258..78978193d19b 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -156,7 +156,6 @@ int mei_cl_irq_read_msg(struct mei_cl *cl, cb->buf_idx += mei_hdr->length; if (mei_hdr->msg_complete) { - cb->read_time = jiffies; cl_dbg(dev, cl, "completed read length = %lu\n", cb->buf_idx); list_move_tail(&cb->list, &complete_list->list); } else { @@ -458,7 +457,6 @@ static void mei_connect_timeout(struct mei_cl *cl) */ void mei_timer(struct work_struct *work) { - unsigned long timeout; struct mei_cl *cl; struct mei_device *dev = container_of(work, @@ -504,7 +502,6 @@ void mei_timer(struct work_struct *work) mei_reset(dev); dev->iamthif_canceled = false; dev->iamthif_state = MEI_IAMTHIF_IDLE; - dev->iamthif_timer = 0; mei_io_cb_free(dev->iamthif_current_cb); dev->iamthif_current_cb = NULL; @@ -514,35 +511,6 @@ void mei_timer(struct work_struct *work) } } - if (dev->iamthif_timer) { - - timeout = dev->iamthif_timer + - mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER); - - dev_dbg(dev->dev, "dev->iamthif_timer = %ld\n", - dev->iamthif_timer); - dev_dbg(dev->dev, "timeout = %ld\n", timeout); - dev_dbg(dev->dev, "jiffies = %ld\n", jiffies); - if (time_after(jiffies, timeout)) { - /* - * User didn't read the AMTHI data on time (15sec) - * freeing AMTHI for other requests - */ - - dev_dbg(dev->dev, "freeing AMTHI for other requests\n"); - - mei_io_list_flush(&dev->amthif_rd_complete_list, - &dev->iamthif_cl); - mei_io_cb_free(dev->iamthif_current_cb); - dev->iamthif_current_cb = NULL; - - dev->iamthif_file_object->private_data = NULL; - dev->iamthif_file_object = NULL; - dev->iamthif_timer = 0; - mei_amthif_run_next_cmd(dev); - - } - } out: if (dev->dev_state != MEI_DEV_DISABLED) schedule_delayed_work(&dev->timer_work, 2 * HZ); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 47dc6d9ae655..5f2b63460d88 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -274,7 +274,6 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, struct mei_cl *cl = file->private_data; struct mei_cl_cb *write_cb = NULL; struct mei_device *dev; - unsigned long timeout = 0; int rets; if (WARN_ON(!cl || !cl->dev)) @@ -310,21 +309,6 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, goto out; } - if (cl == &dev->iamthif_cl) { - write_cb = mei_amthif_find_read_list_entry(dev, file); - - if (write_cb) { - timeout = write_cb->read_time + - mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER); - - if (time_after(jiffies, timeout)) { - *offset = 0; - mei_io_cb_free(write_cb); - write_cb = NULL; - } - } - } - *offset = 0; write_cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, file); if (!write_cb) { diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 9b793f87b7d4..4d0e066703ef 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -179,7 +179,6 @@ struct mei_cl; * @fop_type: file operation type * @buf: buffer for data associated with the callback * @buf_idx: last read index - * @read_time: last read operation time stamp (iamthif) * @file_object: pointer to file structure * @status: io status of the cb * @internal: communication between driver and FW flag @@ -191,7 +190,6 @@ struct mei_cl_cb { enum mei_cb_file_ops fop_type; struct mei_msg_data buf; size_t buf_idx; - unsigned long read_time; struct file *file_object; int status; u32 internal:1; @@ -413,7 +411,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); * @iamthif_cl : amthif host client * @iamthif_current_cb : amthif current operation callback * @iamthif_open_count : number of opened amthif connections - * @iamthif_timer : time stamp of current amthif command completion * @iamthif_stall_timer : timer to detect amthif hang * @iamthif_state : amthif processor state * @iamthif_canceled : current amthif command is canceled @@ -504,7 +501,6 @@ struct mei_device { struct mei_cl iamthif_cl; struct mei_cl_cb *iamthif_current_cb; long iamthif_open_count; - unsigned long iamthif_timer; u32 iamthif_stall_timer; enum iamthif_states iamthif_state; bool iamthif_canceled; -- cgit v1.2.3 From f23e2cc4bb1d8bbbe02dcd3539ed531a3f40277c Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 23:35:23 +0200 Subject: mei: constify struct file pointer The struct file file pointer is used as an opaque handle to for a connected client, for this part the pointer should be immutable and should be set to count. Reviewed-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 6 +++--- drivers/misc/mei/client.c | 12 +++++++----- drivers/misc/mei/client.h | 12 +++++++----- drivers/misc/mei/main.c | 4 ++-- drivers/misc/mei/mei_dev.h | 6 +++--- 5 files changed, 22 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 5da1654bc209..16cceedeed97 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -93,7 +93,7 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl) * Return: returned a list entry on success, NULL on failure. */ struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, - struct file *file) + const struct file *file) { struct mei_cl_cb *cb; @@ -205,7 +205,7 @@ out: * * Return: 0 on success, <0 on failure. */ -static int mei_amthif_read_start(struct mei_cl *cl, struct file *file) +static int mei_amthif_read_start(struct mei_cl *cl, const struct file *file) { struct mei_device *dev = cl->dev; struct mei_cl_cb *cb; @@ -495,7 +495,7 @@ static bool mei_clear_list(struct mei_device *dev, * * Return: true if callback removed from the list, false otherwise */ -static bool mei_clear_lists(struct mei_device *dev, struct file *file) +static bool mei_clear_lists(struct mei_device *dev, const struct file *file) { bool removed = false; diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 738f3d703323..4c23caee04ab 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -359,7 +359,7 @@ void mei_io_cb_free(struct mei_cl_cb *cb) * Return: mei_cl_cb pointer or NULL; */ struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type, - struct file *fp) + const struct file *fp) { struct mei_cl_cb *cb; @@ -455,7 +455,8 @@ int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length) * Return: cb on success and NULL on failure */ struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length, - enum mei_cb_file_ops type, struct file *fp) + enum mei_cb_file_ops type, + const struct file *fp) { struct mei_cl_cb *cb; @@ -1028,7 +1029,7 @@ int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb, * Return: 0 on success, <0 on failure. */ int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl, - struct file *file) + const struct file *file) { struct mei_device *dev; struct mei_cl_cb *cb; @@ -1277,7 +1278,8 @@ int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb, * * Return: 0 on such and error otherwise. */ -int mei_cl_notify_request(struct mei_cl *cl, struct file *file, u8 request) +int mei_cl_notify_request(struct mei_cl *cl, + const struct file *file, u8 request) { struct mei_device *dev; struct mei_cl_cb *cb; @@ -1443,7 +1445,7 @@ static bool mei_cl_is_read_fc_cb(struct mei_cl *cl) * * Return: 0 on success, <0 on failure. */ -int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp) +int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp) { struct mei_device *dev; struct mei_cl_cb *cb; diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index 2e90a25f896e..fdc43279368f 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -83,7 +83,7 @@ static inline u8 mei_me_cl_ver(const struct mei_me_client *me_cl) * MEI IO Functions */ struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type, - struct file *fp); + const struct file *fp); void mei_io_cb_free(struct mei_cl_cb *priv_cb); int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length); @@ -116,7 +116,8 @@ struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl, const struct file *fp); void mei_cl_read_cb_flush(const struct mei_cl *cl, const struct file *fp); struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length, - enum mei_cb_file_ops type, struct file *fp); + enum mei_cb_file_ops type, + const struct file *fp); int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp); /* @@ -213,10 +214,10 @@ void mei_cl_set_disconnected(struct mei_cl *cl); int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list); int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl, - struct file *file); + const struct file *file); int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list); -int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp); +int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp); int mei_cl_irq_read_msg(struct mei_cl *cl, struct mei_msg_hdr *hdr, struct mei_cl_cb *cmpl_list); int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking); @@ -229,7 +230,8 @@ void mei_host_client_init(struct work_struct *work); u8 mei_cl_notify_fop2req(enum mei_cb_file_ops fop); enum mei_cb_file_ops mei_cl_notify_req2fop(u8 request); -int mei_cl_notify_request(struct mei_cl *cl, struct file *file, u8 request); +int mei_cl_notify_request(struct mei_cl *cl, + const struct file *file, u8 request); int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list); int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 5f2b63460d88..03741c456ee4 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -435,7 +435,7 @@ end: * * Return: 0 on success , <0 on error */ -static int mei_ioctl_client_notify_request(struct file *file, u32 request) +static int mei_ioctl_client_notify_request(const struct file *file, u32 request) { struct mei_cl *cl = file->private_data; @@ -450,7 +450,7 @@ static int mei_ioctl_client_notify_request(struct file *file, u32 request) * * Return: 0 on success , <0 on error */ -static int mei_ioctl_client_notify_get(struct file *file, u32 *notify_get) +static int mei_ioctl_client_notify_get(const struct file *file, u32 *notify_get) { struct mei_cl *cl = file->private_data; bool notify_ev; diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 4d0e066703ef..947e0a70577a 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -190,7 +190,7 @@ struct mei_cl_cb { enum mei_cb_file_ops fop_type; struct mei_msg_data buf; size_t buf_idx; - struct file *file_object; + const struct file *file_object; int status; u32 internal:1; u32 completed:1; @@ -497,7 +497,7 @@ struct mei_device { struct mei_cl_cb amthif_cmd_list; /* driver managed amthif list for reading completed amthif cmd data */ struct mei_cl_cb amthif_rd_complete_list; - struct file *iamthif_file_object; + const struct file *iamthif_file_object; struct mei_cl iamthif_cl; struct mei_cl_cb *iamthif_current_cb; long iamthif_open_count; @@ -590,7 +590,7 @@ unsigned int mei_amthif_poll(struct mei_device *dev, int mei_amthif_release(struct mei_device *dev, struct file *file); struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, - struct file *file); + const struct file *file); int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb); int mei_amthif_run_next_cmd(struct mei_device *dev); -- cgit v1.2.3 From 62e8e6ad60975df491d886efaa7fe0aa832947fb Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 23:35:24 +0200 Subject: mei: rename variable names 'file_object' to fp The driver uses three names file, fp, and file_object for struct file type. To improve code clarity and adjust to my taste rename file_object to more common and shorter fp. Reviewed-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 20 ++++++++++---------- drivers/misc/mei/client.c | 8 ++++---- drivers/misc/mei/interrupt.c | 2 +- drivers/misc/mei/mei_dev.h | 8 ++++---- 4 files changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 16cceedeed97..647edc68884f 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -98,7 +98,7 @@ struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, struct mei_cl_cb *cb; list_for_each_entry(cb, &dev->amthif_rd_complete_list.list, list) - if (cb->file_object == file) + if (cb->fp == file) return cb; return NULL; } @@ -224,7 +224,7 @@ static int mei_amthif_read_start(struct mei_cl *cl, const struct file *file) list_add_tail(&cb->list, &dev->ctrl_wr_list.list); dev->iamthif_state = MEI_IAMTHIF_READING; - dev->iamthif_file_object = cb->file_object; + dev->iamthif_fp = cb->fp; dev->iamthif_current_cb = cb; return 0; @@ -253,7 +253,7 @@ static int mei_amthif_send_cmd(struct mei_cl *cl, struct mei_cl_cb *cb) dev->iamthif_state = MEI_IAMTHIF_WRITING; dev->iamthif_current_cb = cb; - dev->iamthif_file_object = cb->file_object; + dev->iamthif_fp = cb->fp; dev->iamthif_canceled = false; ret = mei_cl_write(cl, cb, false); @@ -261,7 +261,7 @@ static int mei_amthif_send_cmd(struct mei_cl *cl, struct mei_cl_cb *cb) return ret; if (cb->completed) - cb->status = mei_amthif_read_start(cl, cb->file_object); + cb->status = mei_amthif_read_start(cl, cb->fp); return 0; } @@ -280,7 +280,7 @@ int mei_amthif_run_next_cmd(struct mei_device *dev) dev->iamthif_canceled = false; dev->iamthif_state = MEI_IAMTHIF_IDLE; - dev->iamthif_file_object = NULL; + dev->iamthif_fp = NULL; dev_dbg(dev->dev, "complete amthif cmd_list cb.\n"); @@ -338,7 +338,7 @@ unsigned int mei_amthif_poll(struct mei_device *dev, poll_wait(file, &dev->iamthif_cl.wait, wait); if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE && - dev->iamthif_file_object == file) { + dev->iamthif_fp == file) { mask |= POLLIN | POLLRDNORM; mei_amthif_run_next_cmd(dev); @@ -368,7 +368,7 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, return ret; if (cb->completed) - cb->status = mei_amthif_read_start(cl, cb->file_object); + cb->status = mei_amthif_read_start(cl, cb->fp); return 0; } @@ -469,7 +469,7 @@ static bool mei_clear_list(struct mei_device *dev, /* list all list member */ list_for_each_entry_safe(cb, next, mei_cb_list, list) { /* check if list member associated with a file */ - if (file == cb->file_object) { + if (file == cb->fp) { /* check if cb equal to current iamthif cb */ if (dev->iamthif_current_cb == cb) { dev->iamthif_current_cb = NULL; @@ -518,7 +518,7 @@ static bool mei_clear_lists(struct mei_device *dev, const struct file *file) /* check if iamthif_current_cb not NULL */ if (dev->iamthif_current_cb && !removed) { /* check file and iamthif current cb association */ - if (dev->iamthif_current_cb->file_object == file) { + if (dev->iamthif_current_cb->fp == file) { /* remove cb */ mei_io_cb_free(dev->iamthif_current_cb); dev->iamthif_current_cb = NULL; @@ -541,7 +541,7 @@ int mei_amthif_release(struct mei_device *dev, struct file *file) if (dev->iamthif_open_count > 0) dev->iamthif_open_count--; - if (dev->iamthif_file_object == file && + if (dev->iamthif_fp == file && dev->iamthif_state != MEI_IAMTHIF_IDLE) { dev_dbg(dev->dev, "amthif canceled iamthif state %d\n", diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 4c23caee04ab..c57ac25ce8db 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -368,7 +368,7 @@ struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type, return NULL; INIT_LIST_HEAD(&cb->list); - cb->file_object = fp; + cb->fp = fp; cb->cl = cl; cb->buf_idx = 0; cb->fop_type = type; @@ -486,7 +486,7 @@ struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl, const struct file *fp) struct mei_cl_cb *cb; list_for_each_entry(cb, &cl->rd_completed, list) - if (!fp || fp == cb->file_object) + if (!fp || fp == cb->fp) return cb; return NULL; @@ -504,12 +504,12 @@ void mei_cl_read_cb_flush(const struct mei_cl *cl, const struct file *fp) struct mei_cl_cb *cb, *next; list_for_each_entry_safe(cb, next, &cl->rd_completed, list) - if (!fp || fp == cb->file_object) + if (!fp || fp == cb->fp) mei_io_cb_free(cb); list_for_each_entry_safe(cb, next, &cl->rd_pending, list) - if (!fp || fp == cb->file_object) + if (!fp || fp == cb->fp) mei_io_cb_free(cb); } diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 78978193d19b..37c8f0e14387 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -506,7 +506,7 @@ void mei_timer(struct work_struct *work) mei_io_cb_free(dev->iamthif_current_cb); dev->iamthif_current_cb = NULL; - dev->iamthif_file_object = NULL; + dev->iamthif_fp = NULL; mei_amthif_run_next_cmd(dev); } } diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 947e0a70577a..3acbbb49d08c 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -179,7 +179,7 @@ struct mei_cl; * @fop_type: file operation type * @buf: buffer for data associated with the callback * @buf_idx: last read index - * @file_object: pointer to file structure + * @fp: pointer to file structure * @status: io status of the cb * @internal: communication between driver and FW flag * @completed: the transfer or reception has completed @@ -190,7 +190,7 @@ struct mei_cl_cb { enum mei_cb_file_ops fop_type; struct mei_msg_data buf; size_t buf_idx; - const struct file *file_object; + const struct file *fp; int status; u32 internal:1; u32 completed:1; @@ -407,7 +407,7 @@ const char *mei_pg_state_str(enum mei_pg_state state); * * @amthif_cmd_list : amthif list for cmd waiting * @amthif_rd_complete_list : amthif list for reading completed cmd data - * @iamthif_file_object : file for current amthif operation + * @iamthif_fp : file for current amthif operation * @iamthif_cl : amthif host client * @iamthif_current_cb : amthif current operation callback * @iamthif_open_count : number of opened amthif connections @@ -497,7 +497,7 @@ struct mei_device { struct mei_cl_cb amthif_cmd_list; /* driver managed amthif list for reading completed amthif cmd data */ struct mei_cl_cb amthif_rd_complete_list; - const struct file *iamthif_file_object; + const struct file *iamthif_fp; struct mei_cl iamthif_cl; struct mei_cl_cb *iamthif_current_cb; long iamthif_open_count; -- cgit v1.2.3 From 5cf8b2a9be0abec35f675bc719ca6eba9e559b1d Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:25 +0200 Subject: mei: amthif: allow only one request at a time A next amthif write can be executed only after the previous one has completed. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 647edc68884f..4383a9ad9208 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -315,6 +315,14 @@ int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb) dev = cl->dev; list_add_tail(&cb->list, &dev->amthif_cmd_list.list); + + /* + * The previous request is still in processing, queue this one. + */ + if (dev->iamthif_state > MEI_IAMTHIF_IDLE && + dev->iamthif_state < MEI_IAMTHIF_READ_COMPLETE) + return 0; + return mei_amthif_run_next_cmd(dev); } -- cgit v1.2.3 From 9abd8b31292497530085156b41746e2a1cd9c934 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 23:35:26 +0200 Subject: mei: amthif: replace amthif_rd_complete_list with rd_completed Now when we have per client rd_completed list we can remove the amthif specific amthif_rd_complete_list. In addition in the function mei_amthif_read do not loop over the rd_completed list like the original code as the code path is unlocked. Reviewed-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 39 +++++++++++---------------------------- drivers/misc/mei/client.c | 1 - drivers/misc/mei/init.c | 1 - drivers/misc/mei/interrupt.c | 2 +- drivers/misc/mei/mei_dev.h | 7 +------ 5 files changed, 13 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 4383a9ad9208..058dd6917805 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -84,26 +84,6 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl) return ret; } -/** - * mei_amthif_find_read_list_entry - finds a amthilist entry for current file - * - * @dev: the device structure - * @file: pointer to file object - * - * Return: returned a list entry on success, NULL on failure. - */ -struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, - const struct file *file) -{ - struct mei_cl_cb *cb; - - list_for_each_entry(cb, &dev->amthif_rd_complete_list.list, list) - if (cb->fp == file) - return cb; - return NULL; -} - - /** * mei_amthif_read - read data from AMTHIF client * @@ -123,12 +103,13 @@ struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, int mei_amthif_read(struct mei_device *dev, struct file *file, char __user *ubuf, size_t length, loff_t *offset) { + struct mei_cl *cl = file->private_data; struct mei_cl_cb *cb; int rets; int wait_ret; dev_dbg(dev->dev, "checking amthif data\n"); - cb = mei_amthif_find_read_list_entry(dev, file); + cb = mei_cl_read_cb(cl, file); /* Check for if we can block or not*/ if (cb == NULL && file->f_flags & O_NONBLOCK) @@ -141,7 +122,7 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, mutex_unlock(&dev->device_lock); wait_ret = wait_event_interruptible(dev->iamthif_cl.wait, - (cb = mei_amthif_find_read_list_entry(dev, file))); + !list_empty(&cl->rd_completed)); /* Locking again the Mutex */ mutex_lock(&dev->device_lock); @@ -149,7 +130,7 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, if (wait_ret) return -ERESTARTSYS; - dev_dbg(dev->dev, "woke up from sleep\n"); + cb = mei_cl_read_cb(cl, file); } if (cb->status) { @@ -420,11 +401,12 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, /** * mei_amthif_complete - complete amthif callback. * - * @dev: the device structure. + * @cl: host client * @cb: callback block. */ -void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb) +void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb) { + struct mei_device *dev = cl->dev; if (cb->fop_type == MEI_FOP_WRITE) { if (!cb->status) { @@ -436,7 +418,7 @@ void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb) * in case of error enqueue the write cb to complete read list * so it can be propagated to the reader */ - list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list); + list_add_tail(&cb->list, &cl->rd_completed); wake_up_interruptible(&dev->iamthif_cl.wait); return; } @@ -444,7 +426,7 @@ void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb) if (!dev->iamthif_canceled) { dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE; dev->iamthif_stall_timer = 0; - list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list); + list_add_tail(&cb->list, &cl->rd_completed); dev_dbg(dev->dev, "amthif read completed\n"); } else { mei_amthif_run_next_cmd(dev); @@ -506,10 +488,11 @@ static bool mei_clear_list(struct mei_device *dev, static bool mei_clear_lists(struct mei_device *dev, const struct file *file) { bool removed = false; + struct mei_cl *cl = &dev->iamthif_cl; /* remove callbacks associated with a file */ mei_clear_list(dev, file, &dev->amthif_cmd_list.list); - if (mei_clear_list(dev, file, &dev->amthif_rd_complete_list.list)) + if (mei_clear_list(dev, file, &cl->rd_completed)) removed = true; mei_clear_list(dev, file, &dev->ctrl_rd_list.list); diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index c57ac25ce8db..32991684563b 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -536,7 +536,6 @@ int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp) mei_io_list_flush(&cl->dev->ctrl_wr_list, cl); mei_io_list_flush(&cl->dev->ctrl_rd_list, cl); mei_io_list_flush(&cl->dev->amthif_cmd_list, cl); - mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl); mei_cl_read_cb_flush(cl, fp); diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 46a4302e5524..a1d978a82806 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -402,7 +402,6 @@ void mei_device_init(struct mei_device *dev, INIT_LIST_HEAD(&dev->iamthif_cl.link); mei_io_list_init(&dev->amthif_cmd_list); - mei_io_list_init(&dev->amthif_rd_complete_list); bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX); dev->open_handle_count = 0; diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 37c8f0e14387..72806ef6efdd 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -48,7 +48,7 @@ void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list) dev_dbg(dev->dev, "completing call back.\n"); if (cl == &dev->iamthif_cl) - mei_amthif_complete(dev, cb); + mei_amthif_complete(cl, cb); else mei_cl_complete(cl, cb); } diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 3acbbb49d08c..81901967911d 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -406,7 +406,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); * @allow_fixed_address: allow user space to connect a fixed client * * @amthif_cmd_list : amthif list for cmd waiting - * @amthif_rd_complete_list : amthif list for reading completed cmd data * @iamthif_fp : file for current amthif operation * @iamthif_cl : amthif host client * @iamthif_current_cb : amthif current operation callback @@ -496,7 +495,6 @@ struct mei_device { /* amthif list for cmd waiting */ struct mei_cl_cb amthif_cmd_list; /* driver managed amthif list for reading completed amthif cmd data */ - struct mei_cl_cb amthif_rd_complete_list; const struct file *iamthif_fp; struct mei_cl iamthif_cl; struct mei_cl_cb *iamthif_current_cb; @@ -589,15 +587,12 @@ unsigned int mei_amthif_poll(struct mei_device *dev, int mei_amthif_release(struct mei_device *dev, struct file *file); -struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, - const struct file *file); - int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb); int mei_amthif_run_next_cmd(struct mei_device *dev); int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list); -void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb); +void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb); int mei_amthif_irq_read_msg(struct mei_cl *cl, struct mei_msg_hdr *mei_hdr, struct mei_cl_cb *complete_list); -- cgit v1.2.3 From 77b007b1b50ef728be8252cbdf3f7e7e45b29bc5 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 23:35:27 +0200 Subject: mei: amthif: drop parameter validation from mei_amthif_write Remove duplicated parameter validation from mei_amthif_write functions, The parameter check is already performed by the caller function mei_write Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 058dd6917805..911b663a8fdb 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -285,15 +285,7 @@ int mei_amthif_run_next_cmd(struct mei_device *dev) int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb) { - struct mei_device *dev; - - if (WARN_ON(!cl || !cl->dev)) - return -ENODEV; - - if (WARN_ON(!cb)) - return -EINVAL; - - dev = cl->dev; + struct mei_device *dev = cl->dev; list_add_tail(&cb->list, &dev->amthif_cmd_list.list); -- cgit v1.2.3 From 4bddf56fc93c6ad7a451f15a69e3d89d49db0747 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:28 +0200 Subject: mei: amthif: use rx_wait queue also for amthif client Switch using cl->rx_wait wait queue also for amthif, there is nothing special about amthif in that matter in Rx flow. The cl->wait is reserved for hbm flows and asynchronous events Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 911b663a8fdb..b98eac389782 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -121,8 +121,8 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, /* unlock the Mutex */ mutex_unlock(&dev->device_lock); - wait_ret = wait_event_interruptible(dev->iamthif_cl.wait, - !list_empty(&cl->rd_completed)); + wait_ret = wait_event_interruptible(cl->rx_wait, + !list_empty(&cl->rd_completed)); /* Locking again the Mutex */ mutex_lock(&dev->device_lock); @@ -316,7 +316,7 @@ unsigned int mei_amthif_poll(struct mei_device *dev, { unsigned int mask = 0; - poll_wait(file, &dev->iamthif_cl.wait, wait); + poll_wait(file, &dev->iamthif_cl.rx_wait, wait); if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE && dev->iamthif_fp == file) { @@ -411,7 +411,7 @@ void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb) * so it can be propagated to the reader */ list_add_tail(&cb->list, &cl->rd_completed); - wake_up_interruptible(&dev->iamthif_cl.wait); + wake_up_interruptible(&cl->rx_wait); return; } @@ -425,7 +425,7 @@ void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb) } dev_dbg(dev->dev, "completing amthif call back.\n"); - wake_up_interruptible(&dev->iamthif_cl.wait); + wake_up_interruptible(&cl->rx_wait); } /** -- cgit v1.2.3 From b74d883138911b110cf8f5b7b94790e16bb56795 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:29 +0200 Subject: mei: amthif: interrupt reader on link reset In case of link reset all waiting readers should be interrupted. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index b98eac389782..ca2efc3602df 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -122,7 +122,8 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, mutex_unlock(&dev->device_lock); wait_ret = wait_event_interruptible(cl->rx_wait, - !list_empty(&cl->rd_completed)); + !list_empty(&cl->rd_completed) || + !mei_cl_is_connected(cl)); /* Locking again the Mutex */ mutex_lock(&dev->device_lock); @@ -130,6 +131,11 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, if (wait_ret) return -ERESTARTSYS; + if (!mei_cl_is_connected(cl)) { + rets = -EBUSY; + goto out; + } + cb = mei_cl_read_cb(cl, file); } -- cgit v1.2.3 From a1f9ae2bd264e3aed95aacd0102bd22a0422b8d1 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 23:35:30 +0200 Subject: mei: bus: fix RX event scheduling In this particular case this more correct and safer to check if the RX event is set in the event mask rather than query waitqueue_active Since the check is already performed in the mei_cl_bus_rx_event function, it is just required to check for its return value. Second, since we don't have exclusive waiter wake_up_interruptible_all is not used correctly here. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 13 +++++++++---- drivers/misc/mei/client.c | 6 ++---- drivers/misc/mei/mei_dev.h | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 0b05aa938799..a40d8e24ecda 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -252,23 +252,28 @@ void mei_cl_bus_notify_event(struct mei_cl *cl) } /** - * mei_cl_bus_rx_event - schedule rx evenet + * mei_cl_bus_rx_event - schedule rx event * * @cl: host client + * + * Return: true if event was scheduled + * false if the client is not waiting for event */ -void mei_cl_bus_rx_event(struct mei_cl *cl) +bool mei_cl_bus_rx_event(struct mei_cl *cl) { struct mei_cl_device *cldev = cl->cldev; if (!cldev || !cldev->event_cb) - return; + return false; if (!(cldev->events_mask & BIT(MEI_CL_EVENT_RX))) - return; + return false; set_bit(MEI_CL_EVENT_RX, &cldev->events); schedule_work(&cldev->event_work); + + return true; } /** diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 32991684563b..574f7394fb2b 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1735,10 +1735,8 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb) case MEI_FOP_READ: list_add_tail(&cb->list, &cl->rd_completed); - if (waitqueue_active(&cl->rx_wait)) - wake_up_interruptible_all(&cl->rx_wait); - else - mei_cl_bus_rx_event(cl); + if (!mei_cl_bus_rx_event(cl)) + wake_up_interruptible(&cl->rx_wait); break; case MEI_FOP_CONNECT: diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 81901967911d..be97b8f2a883 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -316,7 +316,7 @@ void mei_cl_bus_dev_fixup(struct mei_cl_device *dev); ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, bool blocking); ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length); -void mei_cl_bus_rx_event(struct mei_cl *cl); +bool mei_cl_bus_rx_event(struct mei_cl *cl); void mei_cl_bus_notify_event(struct mei_cl *cl); void mei_cl_bus_remove_devices(struct mei_device *bus); int mei_cl_bus_init(void); -- cgit v1.2.3 From 850f8940a6a38563ff401073fd845414ab49c5ed Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 23:35:31 +0200 Subject: mei: bus: fix notification event delivery Call wake_up cl->ev_wait only in case there is no bus client registered to the event notification. Second, since we don't have exclusive waiter wake_up_interruptible_all is not used correctly here. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 13 +++++++++---- drivers/misc/mei/client.c | 4 ++-- drivers/misc/mei/mei_dev.h | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index a40d8e24ecda..990f4f65c35e 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -230,25 +230,30 @@ static void mei_cl_bus_event_work(struct work_struct *work) * mei_cl_bus_notify_event - schedule notify cb on bus client * * @cl: host client + * + * Return: true if event was scheduled + * false if the client is not waiting for event */ -void mei_cl_bus_notify_event(struct mei_cl *cl) +bool mei_cl_bus_notify_event(struct mei_cl *cl) { struct mei_cl_device *cldev = cl->cldev; if (!cldev || !cldev->event_cb) - return; + return false; if (!(cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF))) - return; + return false; if (!cl->notify_ev) - return; + return false; set_bit(MEI_CL_EVENT_NOTIF, &cldev->events); schedule_work(&cldev->event_work); cl->notify_ev = false; + + return true; } /** diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 574f7394fb2b..3fd070a698ce 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1363,12 +1363,12 @@ void mei_cl_notify(struct mei_cl *cl) cl_dbg(dev, cl, "notify event"); cl->notify_ev = true; - wake_up_interruptible_all(&cl->ev_wait); + if (!mei_cl_bus_notify_event(cl)) + wake_up_interruptible(&cl->ev_wait); if (cl->ev_async) kill_fasync(&cl->ev_async, SIGIO, POLL_PRI); - mei_cl_bus_notify_event(cl); } /** diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index be97b8f2a883..70c4da015401 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -317,7 +317,7 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, bool blocking); ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length); bool mei_cl_bus_rx_event(struct mei_cl *cl); -void mei_cl_bus_notify_event(struct mei_cl *cl); +bool mei_cl_bus_notify_event(struct mei_cl *cl); void mei_cl_bus_remove_devices(struct mei_device *bus); int mei_cl_bus_init(void); void mei_cl_bus_exit(void); -- cgit v1.2.3 From 15c13dfcad883a1e76b714480fb27be96247fd82 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:32 +0200 Subject: mei: bus: check if the device is enabled before data transfer The bus data transfer interface was missing the check if the device is in enabled state, this may lead to stack corruption during link reset. Cc: #4.0 Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 990f4f65c35e..83b084558ee5 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -53,6 +53,11 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, bus = cl->dev; mutex_lock(&bus->device_lock); + if (bus->dev_state != MEI_DEV_ENABLED) { + rets = -ENODEV; + goto out; + } + if (!mei_cl_is_connected(cl)) { rets = -ENODEV; goto out; @@ -109,6 +114,10 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length) bus = cl->dev; mutex_lock(&bus->device_lock); + if (bus->dev_state != MEI_DEV_ENABLED) { + rets = -ENODEV; + goto out; + } cb = mei_cl_read_cb(cl, NULL); if (cb) -- cgit v1.2.3 From e8466b336adc20bacb597670e0a89e695626e000 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:33 +0200 Subject: mei: drop superfluous closing bracket from write traces Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/mei-trace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/mei-trace.h b/drivers/misc/mei/mei-trace.h index 86e5068837c1..7d2d5d4a1624 100644 --- a/drivers/misc/mei/mei-trace.h +++ b/drivers/misc/mei/mei-trace.h @@ -60,7 +60,7 @@ TRACE_EVENT(mei_reg_write, __entry->offs = offs; __entry->val = val; ), - TP_printk("[%s] write %s[%#x] = %#x)", + TP_printk("[%s] write %s[%#x] = %#x", __get_str(dev), __entry->reg, __entry->offs, __entry->val) ); @@ -98,7 +98,7 @@ TRACE_EVENT(mei_pci_cfg_write, __entry->offs = offs; __entry->val = val; ), - TP_printk("[%s] pci cfg write %s[%#x] = %#x)", + TP_printk("[%s] pci cfg write %s[%#x] = %#x", __get_str(dev), __entry->reg, __entry->offs, __entry->val) ); -- cgit v1.2.3 From 0faf6a3bbae74ca08c2ecc09e5f6d350ad54c1ab Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:34 +0200 Subject: mei: wake blocked write on link reset In case of link reset all blocked writes should be interrupted. Note, that currently blocking write is used only through bus layer. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 3fd070a698ce..5ddc690752c2 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1691,7 +1691,8 @@ out: mutex_unlock(&dev->device_lock); rets = wait_event_interruptible(cl->tx_wait, - cl->writing_state == MEI_WRITE_COMPLETE); + cl->writing_state == MEI_WRITE_COMPLETE || + (!mei_cl_is_connected(cl))); mutex_lock(&dev->device_lock); /* wait_event_interruptible returns -ERESTARTSYS */ if (rets) { @@ -1699,6 +1700,10 @@ out: rets = -EINTR; goto err; } + if (cl->writing_state != MEI_WRITE_COMPLETE) { + rets = -EFAULT; + goto err; + } } rets = size; -- cgit v1.2.3 From a4307fe45aa9be03d5d7194b317a40b0d0558bee Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:35 +0200 Subject: mei: clean write queues and wake waiters on disconnect Clean write and write_waiting queues in disconnect. Requests in those queues are stale and processing will lead to fat warnings. In multi thread operations on disconnect and in FW disconnect case - write/read/event waiters should end wait and return error. Wake all waiters for disconnecting client to achieve that. Drop wake all and write queue clean on reset, as now we waking all waiters and cleaning write queues on disconnect. No need to do it twice. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 71 ++++++++++++++++++++--------------------------- drivers/misc/mei/client.h | 2 -- drivers/misc/mei/init.c | 5 ---- 3 files changed, 30 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 5ddc690752c2..3a9c656f1425 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -719,6 +719,33 @@ bool mei_hbuf_acquire(struct mei_device *dev) return true; } +/** + * mei_cl_wake_all - wake up readers, writers and event waiters so + * they can be interrupted + * + * @cl: host client + */ +static void mei_cl_wake_all(struct mei_cl *cl) +{ + struct mei_device *dev = cl->dev; + + /* synchronized under device mutex */ + if (waitqueue_active(&cl->rx_wait)) { + cl_dbg(dev, cl, "Waking up reading client!\n"); + wake_up_interruptible(&cl->rx_wait); + } + /* synchronized under device mutex */ + if (waitqueue_active(&cl->tx_wait)) { + cl_dbg(dev, cl, "Waking up writing client!\n"); + wake_up_interruptible(&cl->tx_wait); + } + /* synchronized under device mutex */ + if (waitqueue_active(&cl->ev_wait)) { + cl_dbg(dev, cl, "Waking up waiting for event clients!\n"); + wake_up_interruptible(&cl->ev_wait); + } +} + /** * mei_cl_set_disconnected - set disconnected state and clear * associated states and resources @@ -734,8 +761,11 @@ void mei_cl_set_disconnected(struct mei_cl *cl) return; cl->state = MEI_FILE_DISCONNECTED; + mei_io_list_free(&dev->write_list, cl); + mei_io_list_free(&dev->write_waiting_list, cl); mei_io_list_flush(&dev->ctrl_rd_list, cl); mei_io_list_flush(&dev->ctrl_wr_list, cl); + mei_cl_wake_all(cl); cl->mei_flow_ctrl_creds = 0; cl->timer_count = 0; @@ -1770,44 +1800,3 @@ void mei_cl_all_disconnect(struct mei_device *dev) list_for_each_entry(cl, &dev->file_list, link) mei_cl_set_disconnected(cl); } - - -/** - * mei_cl_all_wakeup - wake up all readers and writers they can be interrupted - * - * @dev: mei device - */ -void mei_cl_all_wakeup(struct mei_device *dev) -{ - struct mei_cl *cl; - - list_for_each_entry(cl, &dev->file_list, link) { - if (waitqueue_active(&cl->rx_wait)) { - cl_dbg(dev, cl, "Waking up reading client!\n"); - wake_up_interruptible(&cl->rx_wait); - } - if (waitqueue_active(&cl->tx_wait)) { - cl_dbg(dev, cl, "Waking up writing client!\n"); - wake_up_interruptible(&cl->tx_wait); - } - - /* synchronized under device mutex */ - if (waitqueue_active(&cl->ev_wait)) { - cl_dbg(dev, cl, "Waking up waiting for event clients!\n"); - wake_up_interruptible(&cl->ev_wait); - } - } -} - -/** - * mei_cl_all_write_clear - clear all pending writes - * - * @dev: mei device - */ -void mei_cl_all_write_clear(struct mei_device *dev) -{ - mei_io_list_free(&dev->write_list, NULL); - mei_io_list_free(&dev->write_waiting_list, NULL); -} - - diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index fdc43279368f..9925cf1a91ef 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -238,8 +238,6 @@ int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev); void mei_cl_notify(struct mei_cl *cl); void mei_cl_all_disconnect(struct mei_device *dev); -void mei_cl_all_wakeup(struct mei_device *dev); -void mei_cl_all_write_clear(struct mei_device *dev); #define MEI_CL_FMT "cl:host=%02d me=%02d " #define MEI_CL_PRM(cl) (cl)->host_client_id, mei_cl_me_id(cl) diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index a1d978a82806..cfcb46da13f1 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -148,13 +148,8 @@ int mei_reset(struct mei_device *dev) state != MEI_DEV_POWER_UP) { /* remove all waiting requests */ - mei_cl_all_write_clear(dev); - mei_cl_all_disconnect(dev); - /* wake up all readers and writers so they can be interrupted */ - mei_cl_all_wakeup(dev); - /* remove entry if already in list */ dev_dbg(dev->dev, "remove iamthif from the file list.\n"); mei_cl_unlink(&dev->iamthif_cl); -- cgit v1.2.3 From 603c53e42adf5f2d29ffdd1ff1edda0c27e400df Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:36 +0200 Subject: mei: discard replies from unconnected fixed address clients A fixed address client in the FW doesn't have a notion of connection and can send message after the file associated with it was already closed. Silently discard such messages. Add inline helpers to detect whether a message is hbm or intended for a fixed address client Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interrupt.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 72806ef6efdd..06b744a503a3 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -239,6 +239,16 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb, return 0; } +static inline bool hdr_is_hbm(struct mei_msg_hdr *mei_hdr) +{ + return mei_hdr->host_addr == 0 && mei_hdr->me_addr == 0; +} + +static inline bool hdr_is_fixed(struct mei_msg_hdr *mei_hdr) +{ + return mei_hdr->host_addr == 0 && mei_hdr->me_addr != 0; +} + /** * mei_irq_read_handler - bottom half read routine after ISR to * handle the read processing. @@ -280,7 +290,7 @@ int mei_irq_read_handler(struct mei_device *dev, } /* HBM message */ - if (mei_hdr->host_addr == 0 && mei_hdr->me_addr == 0) { + if (hdr_is_hbm(mei_hdr)) { ret = mei_hbm_dispatch(dev, mei_hdr); if (ret) { dev_dbg(dev->dev, "mei_hbm_dispatch failed ret = %d\n", @@ -300,6 +310,14 @@ int mei_irq_read_handler(struct mei_device *dev, /* if no recipient cl was found we assume corrupted header */ if (&cl->link == &dev->file_list) { + /* A message for not connected fixed address clients + * should be silently discarded + */ + if (hdr_is_fixed(mei_hdr)) { + mei_irq_discard_msg(dev, mei_hdr); + ret = 0; + goto reset_slots; + } dev_err(dev->dev, "no destination client found 0x%08X\n", dev->rd_msg_hdr); ret = -EBADMSG; -- cgit v1.2.3 From 06ee536bcb15ca12868289467762130fa0a426f3 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:37 +0200 Subject: mei: fill file pointer in read cb for fixed address client The read callback created from a flow control request for a fixed address client have NULL in the file pointer. Fill the file pointer using a data from a write callback. This allows us to drop workaround introduced in: commit eeabfcf5a92a ("mei: connection to fixed address clients from user-space") Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 11 +- drivers/misc/mei/main.c | 5 - drivers/misc/mei/wd.c | 391 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 397 insertions(+), 10 deletions(-) create mode 100644 drivers/misc/mei/wd.c (limited to 'drivers') diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 3a9c656f1425..a27ae2deecb4 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1173,11 +1173,12 @@ err: /** * mei_cl_flow_ctrl_creds - checks flow_control credits for cl. * - * @cl: private data of the file object + * @cl: host client + * @fp: the file pointer associated with the pointer * * Return: 1 if mei_flow_ctrl_creds >0, 0 - otherwise. */ -static int mei_cl_flow_ctrl_creds(struct mei_cl *cl) +static int mei_cl_flow_ctrl_creds(struct mei_cl *cl, const struct file *fp) { int rets; @@ -1188,7 +1189,7 @@ static int mei_cl_flow_ctrl_creds(struct mei_cl *cl) return 1; if (mei_cl_is_fixed_address(cl)) { - rets = mei_cl_read_start(cl, mei_cl_mtu(cl), NULL); + rets = mei_cl_read_start(cl, mei_cl_mtu(cl), fp); if (rets && rets != -EBUSY) return rets; return 1; @@ -1568,7 +1569,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, first_chunk = cb->buf_idx == 0; - rets = first_chunk ? mei_cl_flow_ctrl_creds(cl) : 1; + rets = first_chunk ? mei_cl_flow_ctrl_creds(cl, cb->fp) : 1; if (rets < 0) return rets; @@ -1674,7 +1675,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking) mei_hdr.msg_complete = 0; mei_hdr.internal = cb->internal; - rets = mei_cl_flow_ctrl_creds(cl); + rets = mei_cl_flow_ctrl_creds(cl, cb->fp); if (rets < 0) goto err; diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 03741c456ee4..f1fdd65e9678 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -209,11 +209,6 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, cb = mei_cl_read_cb(cl, file); if (!cb) { - if (mei_cl_is_fixed_address(cl) && dev->allow_fixed_address) { - cb = mei_cl_read_cb(cl, NULL); - if (cb) - goto copy_buffer; - } rets = 0; goto out; } diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c new file mode 100644 index 000000000000..7d9b4ee42f65 --- /dev/null +++ b/drivers/misc/mei/wd.c @@ -0,0 +1,391 @@ +/* + * + * Intel Management Engine Interface (Intel MEI) Linux driver + * Copyright (c) 2003-2012, 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, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + */ +#include +#include +#include +#include +#include +#include + +#include + +#include "mei_dev.h" +#include "hbm.h" +#include "client.h" + +static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; +static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; + +/* + * AMT Watchdog Device + */ +#define INTEL_AMT_WATCHDOG_ID "INTCAMT" + +/* UUIDs for AMT F/W clients */ +const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89, + 0x9D, 0xA9, 0x15, 0x14, 0xCB, + 0x32, 0xAB); + +static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout) +{ + dev_dbg(dev->dev, "wd: set timeout=%d.\n", timeout); + memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE); + memcpy(dev->wd_data + MEI_WD_HDR_SIZE, &timeout, sizeof(u16)); +} + +/** + * mei_wd_host_init - connect to the watchdog client + * + * @dev: the device structure + * @me_cl: me client + * + * Return: -ENOTTY if wd client cannot be found + * -EIO if write has failed + * 0 on success + */ +int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl) +{ + struct mei_cl *cl = &dev->wd_cl; + int ret; + + mei_cl_init(cl, dev); + + dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; + dev->wd_state = MEI_WD_IDLE; + + ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID); + if (ret < 0) { + dev_info(dev->dev, "wd: failed link client\n"); + return ret; + } + + ret = mei_cl_connect(cl, me_cl, NULL); + if (ret) { + dev_err(dev->dev, "wd: failed to connect = %d\n", ret); + mei_cl_unlink(cl); + return ret; + } + + ret = mei_watchdog_register(dev); + if (ret) { + mei_cl_disconnect(cl); + mei_cl_unlink(cl); + } + return ret; +} + +/** + * mei_wd_send - sends watch dog message to fw. + * + * @dev: the device structure + * + * Return: 0 if success, + * -EIO when message send fails + * -EINVAL when invalid message is to be sent + * -ENODEV on flow control failure + */ +int mei_wd_send(struct mei_device *dev) +{ + struct mei_cl *cl = &dev->wd_cl; + struct mei_msg_hdr hdr; + int ret; + + hdr.host_addr = cl->host_client_id; + hdr.me_addr = mei_cl_me_id(cl); + hdr.msg_complete = 1; + hdr.reserved = 0; + hdr.internal = 0; + + if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE)) + hdr.length = MEI_WD_START_MSG_SIZE; + else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE)) + hdr.length = MEI_WD_STOP_MSG_SIZE; + else { + dev_err(dev->dev, "wd: invalid message is to be sent, aborting\n"); + return -EINVAL; + } + + ret = mei_write_message(dev, &hdr, dev->wd_data); + if (ret) { + dev_err(dev->dev, "wd: write message failed\n"); + return ret; + } + + ret = mei_cl_flow_ctrl_reduce(cl); + if (ret) { + dev_err(dev->dev, "wd: flow_ctrl_reduce failed.\n"); + return ret; + } + + return 0; +} + +/** + * mei_wd_stop - sends watchdog stop message to fw. + * + * @dev: the device structure + * + * Return: 0 if success + * on error: + * -EIO when message send fails + * -EINVAL when invalid message is to be sent + * -ETIME on message timeout + */ +int mei_wd_stop(struct mei_device *dev) +{ + struct mei_cl *cl = &dev->wd_cl; + int ret; + + if (!mei_cl_is_connected(cl) || + dev->wd_state != MEI_WD_RUNNING) + return 0; + + memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_STOP_MSG_SIZE); + + dev->wd_state = MEI_WD_STOPPING; + + ret = mei_cl_flow_ctrl_creds(cl, NULL); + if (ret < 0) + goto err; + + if (ret && mei_hbuf_acquire(dev)) { + ret = mei_wd_send(dev); + if (ret) + goto err; + dev->wd_pending = false; + } else { + dev->wd_pending = true; + } + + mutex_unlock(&dev->device_lock); + + ret = wait_event_timeout(dev->wait_stop_wd, + dev->wd_state == MEI_WD_IDLE, + msecs_to_jiffies(MEI_WD_STOP_TIMEOUT)); + mutex_lock(&dev->device_lock); + if (dev->wd_state != MEI_WD_IDLE) { + /* timeout */ + ret = -ETIME; + dev_warn(dev->dev, "wd: stop failed to complete ret=%d\n", ret); + goto err; + } + dev_dbg(dev->dev, "wd: stop completed after %u msec\n", + MEI_WD_STOP_TIMEOUT - jiffies_to_msecs(ret)); + return 0; +err: + return ret; +} + +/** + * mei_wd_ops_start - wd start command from the watchdog core. + * + * @wd_dev: watchdog device struct + * + * Return: 0 if success, negative errno code for failure + */ +static int mei_wd_ops_start(struct watchdog_device *wd_dev) +{ + struct mei_device *dev; + struct mei_cl *cl; + int err = -ENODEV; + + dev = watchdog_get_drvdata(wd_dev); + if (!dev) + return -ENODEV; + + cl = &dev->wd_cl; + + mutex_lock(&dev->device_lock); + + if (dev->dev_state != MEI_DEV_ENABLED) { + dev_dbg(dev->dev, "wd: dev_state != MEI_DEV_ENABLED dev_state = %s\n", + mei_dev_state_str(dev->dev_state)); + goto end_unlock; + } + + if (!mei_cl_is_connected(cl)) { + cl_dbg(dev, cl, "MEI Driver is not connected to Watchdog Client\n"); + goto end_unlock; + } + + mei_wd_set_start_timeout(dev, dev->wd_timeout); + + err = 0; +end_unlock: + mutex_unlock(&dev->device_lock); + return err; +} + +/** + * mei_wd_ops_stop - wd stop command from the watchdog core. + * + * @wd_dev: watchdog device struct + * + * Return: 0 if success, negative errno code for failure + */ +static int mei_wd_ops_stop(struct watchdog_device *wd_dev) +{ + struct mei_device *dev; + + dev = watchdog_get_drvdata(wd_dev); + if (!dev) + return -ENODEV; + + mutex_lock(&dev->device_lock); + mei_wd_stop(dev); + mutex_unlock(&dev->device_lock); + + return 0; +} + +/** + * mei_wd_ops_ping - wd ping command from the watchdog core. + * + * @wd_dev: watchdog device struct + * + * Return: 0 if success, negative errno code for failure + */ +static int mei_wd_ops_ping(struct watchdog_device *wd_dev) +{ + struct mei_device *dev; + struct mei_cl *cl; + int ret; + + dev = watchdog_get_drvdata(wd_dev); + if (!dev) + return -ENODEV; + + cl = &dev->wd_cl; + + mutex_lock(&dev->device_lock); + + if (!mei_cl_is_connected(cl)) { + cl_err(dev, cl, "wd: not connected.\n"); + ret = -ENODEV; + goto end; + } + + dev->wd_state = MEI_WD_RUNNING; + + ret = mei_cl_flow_ctrl_creds(cl, NULL); + if (ret < 0) + goto end; + + /* Check if we can send the ping to HW*/ + if (ret && mei_hbuf_acquire(dev)) { + dev_dbg(dev->dev, "wd: sending ping\n"); + + ret = mei_wd_send(dev); + if (ret) + goto end; + dev->wd_pending = false; + } else { + dev->wd_pending = true; + } + +end: + mutex_unlock(&dev->device_lock); + return ret; +} + +/** + * mei_wd_ops_set_timeout - wd set timeout command from the watchdog core. + * + * @wd_dev: watchdog device struct + * @timeout: timeout value to set + * + * Return: 0 if success, negative errno code for failure + */ +static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, + unsigned int timeout) +{ + struct mei_device *dev; + + dev = watchdog_get_drvdata(wd_dev); + if (!dev) + return -ENODEV; + + /* Check Timeout value */ + if (timeout < MEI_WD_MIN_TIMEOUT || timeout > MEI_WD_MAX_TIMEOUT) + return -EINVAL; + + mutex_lock(&dev->device_lock); + + dev->wd_timeout = timeout; + wd_dev->timeout = timeout; + mei_wd_set_start_timeout(dev, dev->wd_timeout); + + mutex_unlock(&dev->device_lock); + + return 0; +} + +/* + * Watchdog Device structs + */ +static const struct watchdog_ops wd_ops = { + .owner = THIS_MODULE, + .start = mei_wd_ops_start, + .stop = mei_wd_ops_stop, + .ping = mei_wd_ops_ping, + .set_timeout = mei_wd_ops_set_timeout, +}; +static const struct watchdog_info wd_info = { + .identity = INTEL_AMT_WATCHDOG_ID, + .options = WDIOF_KEEPALIVEPING | + WDIOF_SETTIMEOUT | + WDIOF_ALARMONLY, +}; + +static struct watchdog_device amt_wd_dev = { + .info = &wd_info, + .ops = &wd_ops, + .timeout = MEI_WD_DEFAULT_TIMEOUT, + .min_timeout = MEI_WD_MIN_TIMEOUT, + .max_timeout = MEI_WD_MAX_TIMEOUT, +}; + + +int mei_watchdog_register(struct mei_device *dev) +{ + + int ret; + + amt_wd_dev.parent = dev->dev; + /* unlock to perserve correct locking order */ + mutex_unlock(&dev->device_lock); + ret = watchdog_register_device(&amt_wd_dev); + mutex_lock(&dev->device_lock); + if (ret) { + dev_err(dev->dev, "wd: unable to register watchdog device = %d.\n", + ret); + return ret; + } + + dev_dbg(dev->dev, "wd: successfully register watchdog interface.\n"); + watchdog_set_drvdata(&amt_wd_dev, dev); + return 0; +} + +void mei_watchdog_unregister(struct mei_device *dev) +{ + if (watchdog_get_drvdata(&amt_wd_dev) == NULL) + return; + + watchdog_set_drvdata(&amt_wd_dev, NULL); + watchdog_unregister_device(&amt_wd_dev); +} + -- cgit v1.2.3 From f4e06246183f187d1327fdba18a797eb091a7d03 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:38 +0200 Subject: mei: fixed address clients for the new platforms Enable by default connection to fixed address clients from user-space for skylake and newer platform. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/debugfs.c | 31 +++++++++++++++++++++++++++++-- drivers/misc/mei/hbm.c | 4 ++++ drivers/misc/mei/hw.h | 6 ++++++ drivers/misc/mei/main.c | 18 ++++++++++++++---- drivers/misc/mei/mei_dev.h | 4 ++++ 5 files changed, 57 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c index 6bdd75424fe8..8ad406315741 100644 --- a/drivers/misc/mei/debugfs.c +++ b/drivers/misc/mei/debugfs.c @@ -176,6 +176,8 @@ static ssize_t mei_dbgfs_read_devstate(struct file *fp, char __user *ubuf, dev->hbm_f_dot_supported); pos += scnprintf(buf + pos, bufsz - pos, "\tEV: %01d\n", dev->hbm_f_ev_supported); + pos += scnprintf(buf + pos, bufsz - pos, "\tFA: %01d\n", + dev->hbm_f_fa_supported); } pos += scnprintf(buf + pos, bufsz - pos, "pg: %s, %s\n", @@ -191,6 +193,30 @@ static const struct file_operations mei_dbgfs_fops_devstate = { .llseek = generic_file_llseek, }; +static ssize_t mei_dbgfs_write_allow_fa(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct mei_device *dev; + int ret; + + dev = container_of(file->private_data, + struct mei_device, allow_fixed_address); + + ret = debugfs_write_file_bool(file, user_buf, count, ppos); + if (ret < 0) + return ret; + dev->override_fixed_address = true; + return ret; +} + +static const struct file_operations mei_dbgfs_fops_allow_fa = { + .open = simple_open, + .read = debugfs_read_file_bool, + .write = mei_dbgfs_write_allow_fa, + .llseek = generic_file_llseek, +}; + /** * mei_dbgfs_deregister - Remove the debugfs files and directories * @@ -240,8 +266,9 @@ int mei_dbgfs_register(struct mei_device *dev, const char *name) dev_err(dev->dev, "devstate: registration failed\n"); goto err; } - f = debugfs_create_bool("allow_fixed_address", S_IRUSR | S_IWUSR, dir, - &dev->allow_fixed_address); + f = debugfs_create_file("allow_fixed_address", S_IRUSR | S_IWUSR, dir, + &dev->allow_fixed_address, + &mei_dbgfs_fops_allow_fa); if (!f) { dev_err(dev->dev, "allow_fixed_address: registration failed\n"); goto err; diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index e7b7aad0999b..3915b8e8d0f1 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -979,6 +979,10 @@ static void mei_hbm_config_features(struct mei_device *dev) /* Notification Event Support */ if (dev->version.major_version >= HBM_MAJOR_VERSION_EV) dev->hbm_f_ev_supported = 1; + + /* Fixed Address Client Support */ + if (dev->version.major_version >= HBM_MAJOR_VERSION_FA) + dev->hbm_f_fa_supported = 1; } /** diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h index 4c5d6cfd79b4..459ad596df66 100644 --- a/drivers/misc/mei/hw.h +++ b/drivers/misc/mei/hw.h @@ -64,6 +64,12 @@ #define HBM_MINOR_VERSION_EV 0 #define HBM_MAJOR_VERSION_EV 2 +/* + * MEI version with fixed address client support + */ +#define HBM_MINOR_VERSION_FA 0 +#define HBM_MAJOR_VERSION_FA 2 + /* Host bus message command opcode */ #define MEI_HBM_CMD_OP_MSK 0x7f /* Host bus message command RESPONSE */ diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index f1fdd65e9678..58fa2c83ee39 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -369,12 +369,22 @@ static int mei_ioctl_connect_client(struct file *file, /* find ME client we're trying to connect to */ me_cl = mei_me_cl_by_uuid(dev, &data->in_client_uuid); - if (!me_cl || - (me_cl->props.fixed_address && !dev->allow_fixed_address)) { + if (!me_cl) { dev_dbg(dev->dev, "Cannot connect to FW Client UUID = %pUl\n", &data->in_client_uuid); - mei_me_cl_put(me_cl); - return -ENOTTY; + rets = -ENOTTY; + goto end; + } + + if (me_cl->props.fixed_address) { + bool forbidden = dev->override_fixed_address ? + !dev->allow_fixed_address : !dev->hbm_f_fa_supported; + if (forbidden) { + dev_dbg(dev->dev, "Connection forbidden to FW Client UUID = %pUl\n", + &data->in_client_uuid); + rets = -ENOTTY; + goto end; + } } dev_dbg(dev->dev, "Connect to FW Client ID = %d\n", diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 70c4da015401..6d97f3335e22 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -396,6 +396,7 @@ const char *mei_pg_state_str(enum mei_pg_state state); * @hbm_f_dc_supported : hbm feature dynamic clients * @hbm_f_dot_supported : hbm feature disconnect on timeout * @hbm_f_ev_supported : hbm feature event notification + * @hbm_f_fa_supported : hbm feature fixed address client * * @me_clients_rwsem: rw lock over me_clients list * @me_clients : list of FW clients @@ -404,6 +405,7 @@ const char *mei_pg_state_str(enum mei_pg_state state); * @me_client_index : last FW client index in enumeration * * @allow_fixed_address: allow user space to connect a fixed client + * @override_fixed_address: force allow fixed address behavior * * @amthif_cmd_list : amthif list for cmd waiting * @iamthif_fp : file for current amthif operation @@ -483,6 +485,7 @@ struct mei_device { unsigned int hbm_f_dc_supported:1; unsigned int hbm_f_dot_supported:1; unsigned int hbm_f_ev_supported:1; + unsigned int hbm_f_fa_supported:1; struct rw_semaphore me_clients_rwsem; struct list_head me_clients; @@ -491,6 +494,7 @@ struct mei_device { unsigned long me_client_index; bool allow_fixed_address; + bool override_fixed_address; /* amthif list for cmd waiting */ struct mei_cl_cb amthif_cmd_list; -- cgit v1.2.3 From 6938c1923f8ac6eb6d1c99b924d3e377201143ed Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:39 +0200 Subject: mei: hbm: warn about fw-initiated disconnect The FW can initiate client disconnection only because an error condition, hence it make sense to bump the debug message to the warning level to have an entery in the log. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.h | 3 +++ drivers/misc/mei/hbm.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index 9925cf1a91ef..be6929620d61 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -245,6 +245,9 @@ void mei_cl_all_disconnect(struct mei_device *dev); #define cl_dbg(dev, cl, format, arg...) \ dev_dbg((dev)->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg) +#define cl_warn(dev, cl, format, arg...) \ + dev_warn((dev)->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg) + #define cl_err(dev, cl, format, arg...) \ dev_err((dev)->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg) diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index 3915b8e8d0f1..a2f32b0eb649 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -866,7 +866,7 @@ static int mei_hbm_fw_disconnect_req(struct mei_device *dev, cl = mei_hbm_cl_find_by_cmd(dev, disconnect_req); if (cl) { - cl_dbg(dev, cl, "fw disconnect request received\n"); + cl_warn(dev, cl, "fw disconnect request received\n"); cl->state = MEI_FILE_DISCONNECTING; cl->timer_count = 0; -- cgit v1.2.3 From 7851e008703e2f7073802e560293213e93dcdde6 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:40 +0200 Subject: mei: drop reserved host client ids The reserved host clients can be obsoleted now, a portion of the platforms is shipped without iAMT enabled, where the reservation is not relevant and for platforms with iAMT dynamic allocation is sufficient. Dropping reserved ids makes enumeration more flexible and generic Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 2 +- drivers/misc/mei/bus-fixup.c | 2 +- drivers/misc/mei/bus.c | 2 +- drivers/misc/mei/client.c | 15 +++++---------- drivers/misc/mei/client.h | 4 ++-- drivers/misc/mei/main.c | 2 +- drivers/misc/mei/mei_dev.h | 8 -------- 7 files changed, 11 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index ca2efc3602df..de194ef573ee 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -71,7 +71,7 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl) mei_cl_init(cl, dev); - ret = mei_cl_link(cl, MEI_IAMTHIF_HOST_CLIENT_ID); + ret = mei_cl_link(cl); if (ret < 0) { dev_err(dev->dev, "amthif: failed cl_link %d\n", ret); return ret; diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c index b87323f4bb14..e9e6ea3ab73c 100644 --- a/drivers/misc/mei/bus-fixup.c +++ b/drivers/misc/mei/bus-fixup.c @@ -239,7 +239,7 @@ static void mei_nfc(struct mei_cl_device *cldev) mutex_lock(&bus->device_lock); /* we need to connect to INFO GUID */ - cl = mei_cl_alloc_linked(bus, MEI_HOST_CLIENT_ID_ANY); + cl = mei_cl_alloc_linked(bus); if (IS_ERR(cl)) { ret = PTR_ERR(cl); cl = NULL; diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 83b084558ee5..bc18e5519da6 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -417,7 +417,7 @@ int mei_cldev_enable(struct mei_cl_device *cldev) if (!cl) { mutex_lock(&bus->device_lock); - cl = mei_cl_alloc_linked(bus, MEI_HOST_CLIENT_ID_ANY); + cl = mei_cl_alloc_linked(bus); mutex_unlock(&bus->device_lock); if (IS_ERR(cl)) return PTR_ERR(cl); diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index a27ae2deecb4..2890669b81f9 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -587,27 +587,23 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev) * mei_cl_link - allocate host id in the host map * * @cl: host client - * @id: fixed host id or MEI_HOST_CLIENT_ID_ANY (-1) for generic one * * Return: 0 on success * -EINVAL on incorrect values * -EMFILE if open count exceeded. */ -int mei_cl_link(struct mei_cl *cl, int id) +int mei_cl_link(struct mei_cl *cl) { struct mei_device *dev; long open_handle_count; + int id; if (WARN_ON(!cl || !cl->dev)) return -EINVAL; dev = cl->dev; - /* If Id is not assigned get one*/ - if (id == MEI_HOST_CLIENT_ID_ANY) - id = find_first_zero_bit(dev->host_clients_map, - MEI_CLIENTS_MAX); - + id = find_first_zero_bit(dev->host_clients_map, MEI_CLIENTS_MAX); if (id >= MEI_CLIENTS_MAX) { dev_err(dev->dev, "id exceeded %d", MEI_CLIENTS_MAX); return -EMFILE; @@ -1143,11 +1139,10 @@ nortpm: * mei_cl_alloc_linked - allocate and link host client * * @dev: the device structure - * @id: fixed host id or MEI_HOST_CLIENT_ID_ANY (-1) for generic one * * Return: cl on success ERR_PTR on failure */ -struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev, int id) +struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev) { struct mei_cl *cl; int ret; @@ -1158,7 +1153,7 @@ struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev, int id) goto err; } - ret = mei_cl_link(cl, id); + ret = mei_cl_link(cl); if (ret) goto err; diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index be6929620d61..a912ea686d97 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -107,10 +107,10 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev); void mei_cl_init(struct mei_cl *cl, struct mei_device *dev); -int mei_cl_link(struct mei_cl *cl, int id); +int mei_cl_link(struct mei_cl *cl); int mei_cl_unlink(struct mei_cl *cl); -struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev, int id); +struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev); struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl, const struct file *fp); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 58fa2c83ee39..17970163eacc 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -65,7 +65,7 @@ static int mei_open(struct inode *inode, struct file *file) goto err_unlock; } - cl = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY); + cl = mei_cl_alloc_linked(dev); if (IS_ERR(cl)) { err = PTR_ERR(cl); goto err_unlock; diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 6d97f3335e22..320ddae5ee1e 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -53,14 +53,6 @@ extern const uuid_le mei_amthif_guid; */ #define MEI_MAX_OPEN_HANDLE_COUNT (MEI_CLIENTS_MAX - 1) -/* - * Internal Clients Number - */ -#define MEI_HOST_CLIENT_ID_ANY (-1) -#define MEI_HBM_HOST_CLIENT_ID 0 /* not used, just for documentation */ -#define MEI_IAMTHIF_HOST_CLIENT_ID 2 - - /* File state */ enum file_state { MEI_FILE_INITIALIZING = 0, -- cgit v1.2.3 From a816a00ece63d16ade7e9c0ca8b5a7e4c5ea2453 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:41 +0200 Subject: mei: bus: run rescan on me_clients list change Since clients can be now added and removed during runtime we need to run bus rescan whenever me_clients list is modified. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 8 ++++++++ drivers/misc/mei/hbm.c | 8 +++++++- drivers/misc/mei/init.c | 2 ++ drivers/misc/mei/mei_dev.h | 3 +++ 4 files changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index bc18e5519da6..951d32265040 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -977,6 +977,14 @@ void mei_cl_bus_rescan(struct mei_device *bus) dev_dbg(bus->dev, "rescan end"); } +void mei_cl_bus_rescan_work(struct work_struct *work) +{ + struct mei_device *bus = + container_of(work, struct mei_device, bus_rescan_work); + + mei_cl_bus_rescan(bus); +} + int __mei_cldev_driver_register(struct mei_cl_driver *cldrv, struct module *owner) { diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index a2f32b0eb649..0c9310ad6136 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -401,6 +401,9 @@ static int mei_hbm_fw_add_cl_req(struct mei_device *dev, if (ret) status = !MEI_HBMS_SUCCESS; + if (dev->dev_state == MEI_DEV_ENABLED) + schedule_work(&dev->bus_rescan_work); + return mei_hbm_add_cl_resp(dev, req->me_addr, status); } @@ -789,8 +792,11 @@ static void mei_hbm_cl_connect_res(struct mei_device *dev, struct mei_cl *cl, cl->state = MEI_FILE_CONNECTED; else { cl->state = MEI_FILE_DISCONNECT_REPLY; - if (rs->status == MEI_CL_CONN_NOT_FOUND) + if (rs->status == MEI_CL_CONN_NOT_FOUND) { mei_me_cl_del(dev, cl->me_cl); + if (dev->dev_state == MEI_DEV_ENABLED) + schedule_work(&dev->bus_rescan_work); + } } cl->status = mei_cl_conn_status_to_errno(rs->status); } diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index cfcb46da13f1..52fde2b498ef 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -93,6 +93,7 @@ void mei_cancel_work(struct mei_device *dev) { cancel_work_sync(&dev->init_work); cancel_work_sync(&dev->reset_work); + cancel_work_sync(&dev->bus_rescan_work); cancel_delayed_work(&dev->timer_work); } @@ -394,6 +395,7 @@ void mei_device_init(struct mei_device *dev, INIT_DELAYED_WORK(&dev->timer_work, mei_timer); INIT_WORK(&dev->init_work, mei_host_client_init); INIT_WORK(&dev->reset_work, mei_reset_work); + INIT_WORK(&dev->bus_rescan_work, mei_cl_bus_rescan_work); INIT_LIST_HEAD(&dev->iamthif_cl.link); mei_io_list_init(&dev->amthif_cmd_list); diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 320ddae5ee1e..c31adb8a0cff 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -304,6 +304,7 @@ struct mei_hw_ops { /* MEI bus API*/ void mei_cl_bus_rescan(struct mei_device *bus); +void mei_cl_bus_rescan_work(struct work_struct *work); void mei_cl_bus_dev_fixup(struct mei_cl_device *dev); ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, bool blocking); @@ -410,6 +411,7 @@ const char *mei_pg_state_str(enum mei_pg_state state); * * @init_work : work item for the device init * @reset_work : work item for the device reset + * @bus_rescan_work : work item for the bus rescan * * @device_list : mei client bus list * @cl_bus_lock : client bus list lock @@ -501,6 +503,7 @@ struct mei_device { struct work_struct init_work; struct work_struct reset_work; + struct work_struct bus_rescan_work; /* List of bus devices */ struct list_head device_list; -- cgit v1.2.3 From 27f476ea98ed495839662db4e3a76357bbeb1bb3 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:42 +0200 Subject: mei: hbm: send immediate reply flag in enum request Signal the FW that it can send an HBM enumeration answer immediately, without waiting for FW initialization completion, meaning before all the FW clients are ready and registered. Organize enumeration response options to enum as a byproduct. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/debugfs.c | 2 ++ drivers/misc/mei/hbm.c | 8 +++++++- drivers/misc/mei/hw.h | 25 +++++++++++++++++++++---- drivers/misc/mei/mei_dev.h | 2 ++ 4 files changed, 32 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c index 8ad406315741..c6c051b52f55 100644 --- a/drivers/misc/mei/debugfs.c +++ b/drivers/misc/mei/debugfs.c @@ -172,6 +172,8 @@ static ssize_t mei_dbgfs_read_devstate(struct file *fp, char __user *ubuf, dev->hbm_f_pg_supported); pos += scnprintf(buf + pos, bufsz - pos, "\tDC: %01d\n", dev->hbm_f_dc_supported); + pos += scnprintf(buf + pos, bufsz - pos, "\tIE: %01d\n", + dev->hbm_f_ie_supported); pos += scnprintf(buf + pos, bufsz - pos, "\tDOT: %01d\n", dev->hbm_f_dot_supported); pos += scnprintf(buf + pos, bufsz - pos, "\tEV: %01d\n", diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index 0c9310ad6136..d2798d5b0a9d 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -301,7 +301,10 @@ static int mei_hbm_enum_clients_req(struct mei_device *dev) enum_req = (struct hbm_host_enum_request *)dev->wr_msg.data; memset(enum_req, 0, len); enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; - enum_req->allow_add = dev->hbm_f_dc_supported; + enum_req->flags |= dev->hbm_f_dc_supported ? + MEI_HBM_ENUM_F_ALLOW_ADD : 0; + enum_req->flags |= dev->hbm_f_ie_supported ? + MEI_HBM_ENUM_F_IMMEDIATE_ENUM : 0; ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data); if (ret) { @@ -978,6 +981,9 @@ static void mei_hbm_config_features(struct mei_device *dev) if (dev->version.major_version >= HBM_MAJOR_VERSION_DC) dev->hbm_f_dc_supported = 1; + if (dev->version.major_version >= HBM_MAJOR_VERSION_IE) + dev->hbm_f_ie_supported = 1; + /* disconnect on connect timeout instead of link reset */ if (dev->version.major_version >= HBM_MAJOR_VERSION_DOT) dev->hbm_f_dot_supported = 1; diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h index 459ad596df66..9daf3f9aed25 100644 --- a/drivers/misc/mei/hw.h +++ b/drivers/misc/mei/hw.h @@ -52,6 +52,12 @@ #define HBM_MINOR_VERSION_DC 0 #define HBM_MAJOR_VERSION_DC 2 +/* + * MEI version with immediate reply to enum request support + */ +#define HBM_MINOR_VERSION_IE 0 +#define HBM_MAJOR_VERSION_IE 2 + /* * MEI version with disconnect on connection timeout support */ @@ -246,15 +252,26 @@ struct hbm_me_stop_request { } __packed; /** - * struct hbm_host_enum_request - enumeration request from host to fw + * enum hbm_host_enum_flags - enumeration request flags (HBM version >= 2.0) * - * @hbm_cmd: bus message command header - * @allow_add: allow dynamic clients add HBM version >= 2.0 + * @MEI_HBM_ENUM_F_ALLOW_ADD: allow dynamic clients add + * @MEI_HBM_ENUM_F_IMMEDIATE_ENUM: allow FW to send answer immediately + */ +enum hbm_host_enum_flags { + MEI_HBM_ENUM_F_ALLOW_ADD = BIT(0), + MEI_HBM_ENUM_F_IMMEDIATE_ENUM = BIT(1), +}; + +/** + * struct hbm_host_enum_request - enumeration request from host to fw + * + * @hbm_cmd : bus message command header + * @flags : request flags * @reserved: reserved */ struct hbm_host_enum_request { u8 hbm_cmd; - u8 allow_add; + u8 flags; u8 reserved[2]; } __packed; diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index c31adb8a0cff..2b9160e506d7 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -390,6 +390,7 @@ const char *mei_pg_state_str(enum mei_pg_state state); * @hbm_f_dot_supported : hbm feature disconnect on timeout * @hbm_f_ev_supported : hbm feature event notification * @hbm_f_fa_supported : hbm feature fixed address client + * @hbm_f_ie_supported : hbm feature immediate reply to enum request * * @me_clients_rwsem: rw lock over me_clients list * @me_clients : list of FW clients @@ -480,6 +481,7 @@ struct mei_device { unsigned int hbm_f_dot_supported:1; unsigned int hbm_f_ev_supported:1; unsigned int hbm_f_fa_supported:1; + unsigned int hbm_f_ie_supported:1; struct rw_semaphore me_clients_rwsem; struct list_head me_clients; -- cgit v1.2.3 From 025fb792bac33632c19fe12265ba1f6108921300 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:43 +0200 Subject: mei: split amthif client init from end of clients enumeration The amthif FW client can appear after the end of client enumeration. Amthif host client initialization is done now at FW client discovery time. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 5 +++-- drivers/misc/mei/bus.c | 8 ++++++++ drivers/misc/mei/client.c | 17 ++--------------- drivers/misc/mei/client.h | 2 +- drivers/misc/mei/hbm.c | 2 +- drivers/misc/mei/init.c | 2 -- drivers/misc/mei/mei_dev.h | 2 -- 7 files changed, 15 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index de194ef573ee..04525ada9eda 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -67,6 +67,9 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl) struct mei_cl *cl = &dev->iamthif_cl; int ret; + if (mei_cl_is_connected(cl)) + return 0; + dev->iamthif_state = MEI_IAMTHIF_IDLE; mei_cl_init(cl, dev); @@ -79,8 +82,6 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl) ret = mei_cl_connect(cl, me_cl, NULL); - dev->iamthif_state = MEI_IAMTHIF_IDLE; - return ret; } diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 951d32265040..f4cf43b47c7a 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -981,6 +981,14 @@ void mei_cl_bus_rescan_work(struct work_struct *work) { struct mei_device *bus = container_of(work, struct mei_device, bus_rescan_work); + struct mei_me_client *me_cl; + + mutex_lock(&bus->device_lock); + me_cl = mei_me_cl_by_uuid(bus, &mei_amthif_guid); + if (me_cl) + mei_amthif_host_init(bus, me_cl); + mei_me_cl_put(me_cl); + mutex_unlock(&bus->device_lock); mei_cl_bus_rescan(bus); } diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 2890669b81f9..af6816bc268f 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -666,25 +666,12 @@ int mei_cl_unlink(struct mei_cl *cl) return 0; } - -void mei_host_client_init(struct work_struct *work) +void mei_host_client_init(struct mei_device *dev) { - struct mei_device *dev = - container_of(work, struct mei_device, init_work); - struct mei_me_client *me_cl; - - mutex_lock(&dev->device_lock); - - me_cl = mei_me_cl_by_uuid(dev, &mei_amthif_guid); - if (me_cl) - mei_amthif_host_init(dev, me_cl); - mei_me_cl_put(me_cl); - dev->dev_state = MEI_DEV_ENABLED; dev->reset_count = 0; - mutex_unlock(&dev->device_lock); - mei_cl_bus_rescan(dev); + schedule_work(&dev->bus_rescan_work); pm_runtime_mark_last_busy(dev->dev); dev_dbg(dev->dev, "rpm: autosuspend\n"); diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index a912ea686d97..0d7a3a1fef78 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -226,7 +226,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb); -void mei_host_client_init(struct work_struct *work); +void mei_host_client_init(struct mei_device *dev); u8 mei_cl_notify_fop2req(enum mei_cb_file_ops fop); enum mei_cb_file_ops mei_cl_notify_req2fop(u8 request); diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index d2798d5b0a9d..5e305d2605f3 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -549,7 +549,7 @@ static int mei_hbm_prop_req(struct mei_device *dev) /* We got all client properties */ if (next_client_index == MEI_CLIENTS_MAX) { dev->hbm_state = MEI_HBM_STARTED; - schedule_work(&dev->init_work); + mei_host_client_init(dev); return 0; } diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 52fde2b498ef..f7c8dfdb6a12 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -91,7 +91,6 @@ EXPORT_SYMBOL_GPL(mei_fw_status2str); */ void mei_cancel_work(struct mei_device *dev) { - cancel_work_sync(&dev->init_work); cancel_work_sync(&dev->reset_work); cancel_work_sync(&dev->bus_rescan_work); @@ -393,7 +392,6 @@ void mei_device_init(struct mei_device *dev, mei_io_list_init(&dev->ctrl_rd_list); INIT_DELAYED_WORK(&dev->timer_work, mei_timer); - INIT_WORK(&dev->init_work, mei_host_client_init); INIT_WORK(&dev->reset_work, mei_reset_work); INIT_WORK(&dev->bus_rescan_work, mei_cl_bus_rescan_work); diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 2b9160e506d7..db78e6d99456 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -410,7 +410,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); * @iamthif_state : amthif processor state * @iamthif_canceled : current amthif command is canceled * - * @init_work : work item for the device init * @reset_work : work item for the device reset * @bus_rescan_work : work item for the bus rescan * @@ -503,7 +502,6 @@ struct mei_device { enum iamthif_states iamthif_state; bool iamthif_canceled; - struct work_struct init_work; struct work_struct reset_work; struct work_struct bus_rescan_work; -- cgit v1.2.3 From 49a76d7040b466dd92f198ded4aba3cd3569d48f Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sat, 6 Feb 2016 02:01:50 -0500 Subject: staging/lustre/libcfs: Properly handle debugfs read- and write-only files It turns out that unlike procfs, debugfs does not really enforce permissions for root (similar to regular filesystems), so we need to ensure we are not providing ->write() method to read-only files and ->read() method for write-only files at registration. This fixes a couple of crashes on unexpected access. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/module.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c index d5a047bd0180..611607ab92db 100644 --- a/drivers/staging/lustre/lustre/libcfs/module.c +++ b/drivers/staging/lustre/lustre/libcfs/module.c @@ -502,13 +502,36 @@ static ssize_t lnet_debugfs_write(struct file *filp, const char __user *buf, return error; } -static const struct file_operations lnet_debugfs_file_operations = { +static const struct file_operations lnet_debugfs_file_operations_rw = { .open = simple_open, .read = lnet_debugfs_read, .write = lnet_debugfs_write, .llseek = default_llseek, }; +static const struct file_operations lnet_debugfs_file_operations_ro = { + .open = simple_open, + .read = lnet_debugfs_read, + .llseek = default_llseek, +}; + +static const struct file_operations lnet_debugfs_file_operations_wo = { + .open = simple_open, + .write = lnet_debugfs_write, + .llseek = default_llseek, +}; + +static const struct file_operations *lnet_debugfs_fops_select(umode_t mode) +{ + if (!(mode & S_IWUGO)) + return &lnet_debugfs_file_operations_ro; + + if (!(mode & S_IRUGO)) + return &lnet_debugfs_file_operations_wo; + + return &lnet_debugfs_file_operations_rw; +} + void lustre_insert_debugfs(struct ctl_table *table, const struct lnet_debugfs_symlink_def *symlinks) { @@ -525,7 +548,7 @@ void lustre_insert_debugfs(struct ctl_table *table, for (; table->procname; table++) debugfs_create_file(table->procname, table->mode, lnet_debugfs_root, table, - &lnet_debugfs_file_operations); + lnet_debugfs_fops_select(table->mode)); for (; symlinks && symlinks->name; symlinks++) debugfs_create_symlink(symlinks->name, lnet_debugfs_root, -- cgit v1.2.3 From da33f1dd9f69c5a5d23e1254906b027af3362e36 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sat, 6 Feb 2016 02:01:51 -0500 Subject: staging/lustre/obdclass: export debugfs functionality for GPL only. Turns out we mistakenly export some pretty-wide-reaching debugfs functions as EXPORT_SYMBOL instead of EXPORT_SYMBOL_GPL as we should, so this patch rectifies the situation. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/obdclass/lprocfs_status.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index b65ad93eca4b..9a1434d89d57 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -261,7 +261,7 @@ struct dentry *ldebugfs_add_simple(struct dentry *root, } return entry; } -EXPORT_SYMBOL(ldebugfs_add_simple); +EXPORT_SYMBOL_GPL(ldebugfs_add_simple); static struct file_operations lprocfs_generic_fops = { }; @@ -294,14 +294,14 @@ int ldebugfs_add_vars(struct dentry *parent, } return 0; } -EXPORT_SYMBOL(ldebugfs_add_vars); +EXPORT_SYMBOL_GPL(ldebugfs_add_vars); void ldebugfs_remove(struct dentry **entryp) { debugfs_remove_recursive(*entryp); *entryp = NULL; } -EXPORT_SYMBOL(ldebugfs_remove); +EXPORT_SYMBOL_GPL(ldebugfs_remove); struct dentry *ldebugfs_register(const char *name, struct dentry *parent, @@ -327,7 +327,7 @@ struct dentry *ldebugfs_register(const char *name, out: return entry; } -EXPORT_SYMBOL(ldebugfs_register); +EXPORT_SYMBOL_GPL(ldebugfs_register); /* Generic callbacks */ int lprocfs_rd_uint(struct seq_file *m, void *data) @@ -942,7 +942,7 @@ int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list, return rc; } -EXPORT_SYMBOL(lprocfs_obd_setup); +EXPORT_SYMBOL_GPL(lprocfs_obd_setup); int lprocfs_obd_cleanup(struct obd_device *obd) { @@ -957,7 +957,7 @@ int lprocfs_obd_cleanup(struct obd_device *obd) return 0; } -EXPORT_SYMBOL(lprocfs_obd_cleanup); +EXPORT_SYMBOL_GPL(lprocfs_obd_cleanup); int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid) { @@ -1219,7 +1219,7 @@ int ldebugfs_register_stats(struct dentry *parent, const char *name, return 0; } -EXPORT_SYMBOL(ldebugfs_register_stats); +EXPORT_SYMBOL_GPL(ldebugfs_register_stats); void lprocfs_counter_init(struct lprocfs_stats *stats, int index, unsigned conf, const char *name, const char *units) @@ -1446,7 +1446,7 @@ int ldebugfs_seq_create(struct dentry *parent, return 0; } -EXPORT_SYMBOL(ldebugfs_seq_create); +EXPORT_SYMBOL_GPL(ldebugfs_seq_create); int ldebugfs_obd_seq_create(struct obd_device *dev, const char *name, @@ -1457,7 +1457,7 @@ int ldebugfs_obd_seq_create(struct obd_device *dev, return ldebugfs_seq_create(dev->obd_debugfs_entry, name, mode, seq_fops, data); } -EXPORT_SYMBOL(ldebugfs_obd_seq_create); +EXPORT_SYMBOL_GPL(ldebugfs_obd_seq_create); void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value) { -- cgit v1.2.3 From deaf7e1cc65f3562cb47acf3650c64834afaa434 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sat, 6 Feb 2016 02:12:12 -0500 Subject: staging/lustre/lnet: Don't call roundup_pow_of_two on zero in LNetEQAlloc roundup_pow_of_two return when called on a zero argument is undefined, so don't call it like that. This fixes a problem introduced by commit 322489d9d551 ("staging/lustre: Use roundup_pow_of_two() in LNetEQAlloc()") since 0 is a valid count parameter for LNetEQAlloc. Also manifesting itself as an annoying kernel warning: LNet: 3486:0:(lib-eq.c:85:LNetEQAlloc()) EQ callback is guaranteed to get every event, do you still want to set eqcount 1 for polling event which will have locking overhead? Please contact with developer to confirm Signed-off-by: Oleg Drokin CC: Pekka Enberg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/lnet/lib-eq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lnet/lnet/lib-eq.c b/drivers/staging/lustre/lnet/lnet/lib-eq.c index 64f94a690081..bfbc3136fd3b 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-eq.c +++ b/drivers/staging/lustre/lnet/lnet/lib-eq.c @@ -79,7 +79,8 @@ LNetEQAlloc(unsigned int count, lnet_eq_handler_t callback, * overflow, they don't skip entries, so the queue has the same * apparent capacity at all times */ - count = roundup_pow_of_two(count); + if (count) + count = roundup_pow_of_two(count); if (callback != LNET_EQ_HANDLER_NONE && count != 0) CWARN("EQ callback is guaranteed to get every event, do you still want to set eqcount %d for polling event which will have locking overhead? Please contact with developer to confirm\n", count); -- cgit v1.2.3 From f6ab21b546ae2020e16f353a7a3a4c7327887de9 Mon Sep 17 00:00:00 2001 From: CHANG FU CHIAO Date: Sat, 6 Feb 2016 13:57:48 +0800 Subject: staging: lustre: add static declaration this function is only referenced within the file Signed-off-by: CHANG FU CHIAO Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/osc_page.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index 2439d804fe75..8943f0a065b9 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -434,8 +434,8 @@ static void osc_page_delete(const struct lu_env *env, osc_lru_del(osc_cli(obj), opg, true); } -void osc_page_clip(const struct lu_env *env, const struct cl_page_slice *slice, - int from, int to) +static void osc_page_clip(const struct lu_env *env, + const struct cl_page_slice *slice, int from, int to) { struct osc_page *opg = cl2osc_page(slice); struct osc_async_page *oap = &opg->ops_oap; -- cgit v1.2.3 From b330686595279de880d174f9f3d4a6c615adff0d Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:18 +0900 Subject: staging: wilc1000: wilc_set_wfi_drv_handler: add mac index Firmware supports sta/ap concurrency so mac index will be passed to wilc. Remove wilc_set_wfi_drv_handler in scan and connect functions, and call the function in ndo_open which is wilc_mac_open. WID_SET_DRV_HANDLER value has been changed as well. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 11 ++++++----- drivers/staging/wilc1000/host_interface.h | 3 ++- drivers/staging/wilc1000/linux_wlan.c | 19 +++++++++++++++++++ drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 6 ++---- drivers/staging/wilc1000/wilc_wlan_if.h | 2 +- 5 files changed, 30 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index d77e2b2bea3d..7c75d0e1ef5a 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -320,9 +320,9 @@ static s32 handle_set_wfi_drv_handler(struct wilc_vif *vif, struct wid wid; wid.id = (u16)WID_SET_DRV_HANDLER; - wid.type = WID_INT; - wid.val = (s8 *)&hif_drv_handler->handler; - wid.size = sizeof(u32); + wid.type = WID_STR; + wid.val = (s8 *)hif_drv_handler; + wid.size = sizeof(*hif_drv_handler); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, hif_drv_handler->handler); @@ -3557,7 +3557,7 @@ int wilc_wait_msg_queue_idle(void) return result; } -int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index) +int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mac_idx) { int result = 0; struct host_if_msg msg; @@ -3565,6 +3565,7 @@ int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index) memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_SET_WFIDRV_HANDLER; msg.body.drv.handler = index; + msg.body.drv.mac_idx = mac_idx; msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); @@ -3909,7 +3910,7 @@ s32 wilc_deinit(struct wilc_vif *vif) del_timer_sync(&hif_drv->remain_on_ch_timer); - wilc_set_wfi_drv_handler(vif, 0); + wilc_set_wfi_drv_handler(vif, 0, 0); down(&hif_sema_driver); if (hif_drv->usr_scan_req.scan_result) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 4c02e6bbed41..b828791bb81a 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -217,6 +217,7 @@ struct user_conn_req { struct drv_handler { u32 handler; + u8 mac_idx; }; struct op_mode { @@ -363,7 +364,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, void *user_arg); int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id); int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); -int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); +int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mac_idx); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); void wilc_resolve_disconnect_aberration(struct wilc_vif *vif); diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index b368c2d9bf14..2fafcc47b59d 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1024,6 +1024,25 @@ int wilc_mac_open(struct net_device *ndev) for (i = 0; i < wl->vif_num; i++) { if (ndev == wl->vif[i]->ndev) { memcpy(wl->vif[i]->src_addr, mac_add, ETH_ALEN); + if (vif->iftype == AP_MODE) { + wilc_set_wfi_drv_handler(vif, + wilc_get_vif_idx(vif), + 0); + } else if (!wilc_wlan_get_num_conn_ifcs(wilc)) { + wilc_set_wfi_drv_handler(vif, + wilc_get_vif_idx(vif), + wilc->open_ifcs); + } else { + if (memcmp(wilc->vif[i ^ 1]->bssid, + wilc->vif[i ^ 1]->src_addr, 6)) + wilc_set_wfi_drv_handler(vif, + wilc_get_vif_idx(vif), + 0); + else + wilc_set_wfi_drv_handler(vif, + wilc_get_vif_idx(vif), + 1); + } wilc_set_operation_mode(vif, vif->iftype); break; } diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 28a6ffa6d907..6ebe07e80acd 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -633,7 +633,6 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) priv->u32RcvdChCount = 0; - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif)); reset_shadow_found(); priv->bCfgScanning = true; @@ -714,8 +713,6 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, vif = netdev_priv(priv->dev); pstrWFIDrv = (struct host_if_drv *)(priv->hWILCWFIDrv); - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif)); - PRINT_D(CFG80211_DBG, "Connecting to SSID [%s] on netdev [%p] host if [%p]\n", sme->ssid, dev, priv->hWILCWFIDrv); if (!(strncmp(sme->ssid, "DIRECT-", 7))) { PRINT_D(CFG80211_DBG, "Connected to Direct network,OBSS disabled\n"); @@ -2152,7 +2149,8 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, vif->iftype = AP_MODE; if (wl->initialized) { - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif)); + wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), + 0); wilc_set_operation_mode(vif, AP_MODE); wilc_set_power_mgmt(vif, 0, 0); } diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index 618903caff54..d306ec1a8529 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -832,7 +832,6 @@ typedef enum { /* Custom Integer WID list */ WID_GET_INACTIVE_TIME = 0x2084, - WID_SET_DRV_HANDLER = 0X2085, WID_SET_OPERATION_MODE = 0X2086, /* EMAC String WID list */ WID_SSID = 0x3000, @@ -865,6 +864,7 @@ typedef enum { WID_MODEL_NAME = 0x3027, /*Added for CAPI tool */ WID_MODEL_NUM = 0x3028, /*Added for CAPI tool */ WID_DEVICE_NAME = 0x3029, /*Added for CAPI tool */ + WID_SET_DRV_HANDLER = 0x3030, /* NMAC String WID list */ WID_11N_P_ACTION_REQ = 0x3080, -- cgit v1.2.3 From ef54719cabca2b65a84fa07065c55e332467b9d1 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:19 +0900 Subject: staging: wilc1000: remove unused functions This patch removes unused following functions. wilc_del_all_rx_ba_session wilc_flush_join_req wilc_wait_msg_queue_idle wilc_set_mac_address Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 92 ------------------------------- drivers/staging/wilc1000/host_interface.h | 4 -- 2 files changed, 96 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 7c75d0e1ef5a..1dc6af045c86 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3342,25 +3342,6 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr) return result; } -int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) -{ - int result = 0; - struct host_if_msg msg; - - PRINT_D(GENERIC_DBG, "mac addr = %x:%x:%x\n", mac_addr[0], mac_addr[1], mac_addr[2]); - - memset(&msg, 0, sizeof(struct host_if_msg)); - msg.id = HOST_IF_MSG_SET_MAC_ADDRESS; - memcpy(msg.body.set_mac_info.mac_addr, mac_addr, ETH_ALEN); - msg.vif = vif; - - result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); - if (result) - PRINT_ER("Failed to send message queue: Set mac address\n"); - - return result; -} - int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, @@ -3431,32 +3412,6 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, return result; } -int wilc_flush_join_req(struct wilc_vif *vif) -{ - int result = 0; - struct host_if_msg msg; - struct host_if_drv *hif_drv = vif->hif_drv; - - if (!join_req) - return -EFAULT; - - if (!hif_drv) { - PRINT_ER("Driver is null\n"); - return -EFAULT; - } - - msg.id = HOST_IF_MSG_FLUSH_CONNECT; - msg.vif = vif; - - result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); - if (result) { - PRINT_ER("Failed to send message queue: Flush join request\n"); - return -EFAULT; - } - - return result; -} - int wilc_disconnect(struct wilc_vif *vif, u16 reason_code) { int result = 0; @@ -3539,24 +3494,6 @@ int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel) return 0; } -int wilc_wait_msg_queue_idle(void) -{ - int result = 0; - struct host_if_msg msg; - - memset(&msg, 0, sizeof(struct host_if_msg)); - msg.id = HOST_IF_MSG_Q_IDLE; - result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); - if (result) { - PRINT_ER("wilc mq send fail\n"); - result = -EINVAL; - } - - down(&hif_sema_wait_response); - - return result; -} - int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mac_idx) { int result = 0; @@ -4606,35 +4543,6 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo) return (void *)pNewJoinBssParam; } -int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char tid) -{ - int result = 0; - struct host_if_msg msg; - struct ba_session_info *ba_session_info = &msg.body.session_info; - struct host_if_drv *hif_drv = vif->hif_drv; - - if (!hif_drv) { - PRINT_ER("driver is null\n"); - return -EFAULT; - } - - memset(&msg, 0, sizeof(struct host_if_msg)); - - msg.id = HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS; - - memcpy(ba_session_info->bssid, bssid, ETH_ALEN); - ba_session_info->tid = tid; - msg.vif = vif; - - result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); - if (result) - PRINT_ER("wilc_mq_send fail\n"); - - down(&hif_sema_wait_response); - - return result; -} - int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) { int result = 0; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index b828791bb81a..3302a5bb1c6a 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -325,14 +325,11 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, int wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pmkid); int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); -int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); -int wilc_wait_msg_queue_idle(void); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, u8 security, enum AUTHTYPE auth_type, u8 channel, void *join_params); -int wilc_flush_join_req(struct wilc_vif *vif); int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); @@ -356,7 +353,6 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); -int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char tid); int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, wilc_remain_on_chan_expired expired, -- cgit v1.2.3 From ff9d65abc8561d67313cd310dc15d2f496282a92 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:20 +0900 Subject: staging: wilc1000: ignore power save If two interfaces are connected and it is required to enable power save then ignore the request. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 1dc6af045c86..7e1b5a097249 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4341,6 +4341,9 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) return -EFAULT; } + if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled) + return 0; + PRINT_D(HOSTINF_DBG, "Setting Power management message queue params\n"); memset(&msg, 0, sizeof(struct host_if_msg)); -- cgit v1.2.3 From 430e640d6d24cf0c9ff035536fd9daa8f2cc879d Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:21 +0900 Subject: staging: wilc1000: handle connecting error If connection fails, wilc1000_connecting needs to be set false also and return immediately because goto lable 'done' doesn't do anything. Remove lable 'done' as well. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 6ebe07e80acd..744b77120b86 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -757,8 +757,8 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, PRINT_D(CFG80211_DBG, "No Scan results yet\n"); else PRINT_D(CFG80211_DBG, "Required bss not in scan results: Error(%d)\n", s32Error); - - goto done; + wilc_connecting = 0; + return s32Error; } priv->WILC_WFI_wep_default = 0; @@ -845,8 +845,8 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, } else { s32Error = -ENOTSUPP; PRINT_ER("Not supported cipher: Error(%d)\n", s32Error); - - goto done; + wilc_connecting = 0; + return s32Error; } } @@ -912,11 +912,10 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, if (s32Error != 0) { PRINT_ER("wilc_set_join_req(): Error(%d)\n", s32Error); s32Error = -ENOENT; - goto done; + wilc_connecting = 0; + return s32Error; } -done: - return s32Error; } -- cgit v1.2.3 From c6866cc4be96e8c50aad53375f9becacb433a5a1 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:22 +0900 Subject: staging: wilc1000: tcp_process: fix a build warning This patch fixes build warning "flags is used uninitialized" when TCP_ACK_FILTER is defined. Fixes: 562ed3f1f78a ("staging/wilc1000: pass struct wilc to most linux_wlan.c functions") Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 5682581ebcc3..25cf32559be4 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -234,6 +234,7 @@ static inline int tcp_process(struct net_device *dev, struct txq_entry_t *tqe) vif = netdev_priv(dev); wilc = vif->wilc; + spin_lock_irqsave(&wilc->txq_spinlock, flags); eth_hdr_ptr = &buffer[0]; h_proto = ntohs(*((unsigned short *)ð_hdr_ptr[12])); -- cgit v1.2.3 From e9576e96cc601b6ffd5af4895407cc44c3bdef8a Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:23 +0900 Subject: staging: wilc1000: remove define TCP_ACK_FILTER This patch removes define TCP_ACK_FILTER and use it's feature codes. Add argument wilc to wilc_wlan_txq_remove because compile error happens. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/Makefile | 1 - drivers/staging/wilc1000/wilc_wlan.c | 22 ++-------------------- 2 files changed, 2 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/Makefile b/drivers/staging/wilc1000/Makefile index 90c37606f202..acc3f3e8481b 100644 --- a/drivers/staging/wilc1000/Makefile +++ b/drivers/staging/wilc1000/Makefile @@ -4,7 +4,6 @@ ccflags-y += -DFIRMWARE_1002=\"atmel/wilc1002_firmware.bin\" \ -DFIRMWARE_1003=\"atmel/wilc1003_firmware.bin\" ccflags-y += -I$(src)/ -DWILC_ASIC_A0 -DWILC_DEBUGFS -#ccflags-y += -DTCP_ACK_FILTER wilc1000-objs := wilc_wfi_cfgoperations.o linux_wlan.o linux_mon.o \ wilc_msgqueue.o \ diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 25cf32559be4..94420161eb5d 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -36,8 +36,7 @@ static inline void release_bus(struct wilc *wilc, BUS_RELEASE_T release) mutex_unlock(&wilc->hif_cs); } -#ifdef TCP_ACK_FILTER -static void wilc_wlan_txq_remove(struct txq_entry_t *tqe) +static void wilc_wlan_txq_remove(struct wilc *wilc, struct txq_entry_t *tqe) { if (tqe == wilc->txq_head) { @@ -54,7 +53,6 @@ static void wilc_wlan_txq_remove(struct txq_entry_t *tqe) } wilc->txq_entries -= 1; } -#endif static struct txq_entry_t * wilc_wlan_txq_remove_from_head(struct net_device *dev) @@ -146,7 +144,6 @@ static int wilc_wlan_txq_add_to_head(struct wilc *wilc, struct txq_entry_t *tqe) return 0; } -#ifdef TCP_ACK_FILTER struct ack_session_info; struct ack_session_info { u32 seq_num; @@ -308,7 +305,7 @@ static int wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev) pending_acks_info[i].ack_num); tqe = pending_acks_info[i].txqe; if (tqe) { - wilc_wlan_txq_remove(tqe); + wilc_wlan_txq_remove(wilc, tqe); tqe->status = 1; if (tqe->tx_complete_func) tqe->tx_complete_func(tqe->priv, @@ -335,7 +332,6 @@ static int wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev) return 1; } -#endif static bool enabled = false; @@ -344,12 +340,10 @@ void wilc_enable_tcp_ack_filter(bool value) enabled = value; } -#ifdef TCP_ACK_FILTER static bool is_tcp_ack_filter_enabled(void) { return enabled; } -#endif static int wilc_wlan_txq_add_cfg_pkt(struct wilc *wilc, u8 *buffer, u32 buffer_size) { @@ -373,9 +367,7 @@ static int wilc_wlan_txq_add_cfg_pkt(struct wilc *wilc, u8 *buffer, u32 buffer_s tqe->buffer_size = buffer_size; tqe->tx_complete_func = NULL; tqe->priv = NULL; -#ifdef TCP_ACK_FILTER tqe->tcp_pending_ack_idx = NOT_TCP_ACK; -#endif PRINT_D(TX_DBG, "Adding the config packet at the Queue tail\n"); if (wilc_wlan_txq_add_to_head(wilc, tqe)) @@ -406,11 +398,9 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, tqe->priv = priv; PRINT_D(TX_DBG, "Adding mgmt packet at the Queue tail\n"); -#ifdef TCP_ACK_FILTER tqe->tcp_pending_ack_idx = NOT_TCP_ACK; if (is_tcp_ack_filter_enabled()) tcp_process(dev, tqe); -#endif wilc_wlan_txq_add_to_tail(dev, tqe); return wilc->txq_entries; } @@ -436,9 +426,7 @@ int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, tqe->buffer_size = buffer_size; tqe->tx_complete_func = func; tqe->priv = priv; -#ifdef TCP_ACK_FILTER tqe->tcp_pending_ack_idx = NOT_TCP_ACK; -#endif PRINT_D(TX_DBG, "Adding Network packet at the Queue tail\n"); wilc_wlan_txq_add_to_tail(dev, tqe); return 1; @@ -643,9 +631,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) wilc_lock_timeout(wilc, &wilc->txq_add_to_head_cs, CFG_PKTS_TIMEOUT); -#ifdef TCP_ACK_FILTER wilc_wlan_txq_filter_dup_tcp_ack(dev); -#endif PRINT_D(TX_DBG, "Getting the head of the TxQ\n"); tqe = wilc_wlan_txq_get_first(wilc); i = 0; @@ -829,10 +815,8 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) if (tqe->tx_complete_func) tqe->tx_complete_func(tqe->priv, tqe->status); - #ifdef TCP_ACK_FILTER if (tqe->tcp_pending_ack_idx != NOT_TCP_ACK) pending_acks_info[tqe->tcp_pending_ack_idx].txqe = NULL; - #endif kfree(tqe); } else { break; @@ -1564,9 +1548,7 @@ int wilc_wlan_init(struct net_device *dev) ret = -EIO; goto _fail_; } -#ifdef TCP_ACK_FILTER init_tcp_tracking(); -#endif return 1; -- cgit v1.2.3 From 4fd6229147e5c58ecf51d7f07ee5247846d0338d Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:24 +0900 Subject: staging: wilc1000: increase link speed This patch increases throughput by enabling tcp ack filter base on checking statistics and also handling tcp session. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 31 +++++++++++++-------------- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 2 ++ drivers/staging/wilc1000/wilc_wlan.c | 27 ++++++++++++++--------- 3 files changed, 34 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 7e1b5a097249..4bbf38c05940 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -57,6 +57,9 @@ #define BLOCK_ACK_REQ_SIZE 0x14 #define FALSE_FRMWR_CHANNEL 100 +#define TCP_ACK_FILTER_LINK_SPEED_THRESH 54 +#define DEFAULT_LINK_SPEED 72 + struct cfg_param_attr { struct cfg_param_val cfg_attr_info; }; @@ -2187,7 +2190,14 @@ static s32 Handle_GetStatistics(struct wilc_vif *vif, if (result) PRINT_ER("Failed to send scan paramters config packet\n"); - up(&hif_sema_wait_response); + if (pstrStatistics->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH && + pstrStatistics->link_speed != DEFAULT_LINK_SPEED) + wilc_enable_tcp_ack_filter(true); + else if (pstrStatistics->link_speed != DEFAULT_LINK_SPEED) + wilc_enable_tcp_ack_filter(false); + + if (pstrStatistics != &vif->wilc->dummy_statistics) + up(&hif_sema_wait_response); return 0; } @@ -3606,7 +3616,8 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) return -EFAULT; } - down(&hif_sema_wait_response); + if (stats != &vif->wilc->dummy_statistics) + down(&hif_sema_wait_response); return result; } @@ -3698,21 +3709,9 @@ static void GetPeriodicRSSI(unsigned long arg) return; } - if (vif->hif_drv->hif_state == HOST_IF_CONNECTED) { - s32 result = 0; - struct host_if_msg msg; - - memset(&msg, 0, sizeof(struct host_if_msg)); - - msg.id = HOST_IF_MSG_GET_RSSI; - msg.vif = vif; + if (vif->hif_drv->hif_state == HOST_IF_CONNECTED) + wilc_get_statistics(vif, &vif->wilc->dummy_statistics); - result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); - if (result) { - PRINT_ER("Failed to send get host channel param's message queue "); - return; - } - } periodic_rssi.data = (unsigned long)vif; mod_timer(&periodic_rssi, jiffies + msecs_to_jiffies(5000)); } diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 54e762ec815f..9f8c79e3d195 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -217,6 +217,8 @@ struct wilc { struct device *dev; bool suspend_event; + + struct rf_info dummy_statistics; }; struct WILC_WFI_mon_priv { diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 94420161eb5d..04d4c92e3948 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -178,19 +178,21 @@ static inline int init_tcp_tracking(void) static inline int add_tcp_session(u32 src_prt, u32 dst_prt, u32 seq) { - ack_session_info[tcp_session].seq_num = seq; - ack_session_info[tcp_session].bigger_ack_num = 0; - ack_session_info[tcp_session].src_port = src_prt; - ack_session_info[tcp_session].dst_port = dst_prt; - tcp_session++; - + if (tcp_session < 2 * MAX_TCP_SESSION) { + ack_session_info[tcp_session].seq_num = seq; + ack_session_info[tcp_session].bigger_ack_num = 0; + ack_session_info[tcp_session].src_port = src_prt; + ack_session_info[tcp_session].dst_port = dst_prt; + tcp_session++; + } PRINT_D(TCP_ENH, "TCP Session %d to Ack %d\n", tcp_session, seq); return 0; } static inline int update_tcp_session(u32 index, u32 ack) { - if (ack > ack_session_info[index].bigger_ack_num) + if (index < 2 * MAX_TCP_SESSION && + ack > ack_session_info[index].bigger_ack_num) ack_session_info[index].bigger_ack_num = ack; return 0; } @@ -198,7 +200,7 @@ static inline int update_tcp_session(u32 index, u32 ack) static inline int add_tcp_pending_ack(u32 ack, u32 session_index, struct txq_entry_t *txqe) { - if (pending_acks < MAX_PENDING_ACKS) { + if (pending_base + pending_acks < MAX_PENDING_ACKS) { pending_acks_info[pending_base + pending_acks].ack_num = ack; pending_acks_info[pending_base + pending_acks].txqe = txqe; pending_acks_info[pending_base + pending_acks].session_index = session_index; @@ -265,7 +267,8 @@ static inline int tcp_process(struct net_device *dev, struct txq_entry_t *tqe) (u32)tcp_hdr_ptr[11]; for (i = 0; i < tcp_session; i++) { - if (ack_session_info[i].seq_num == seq_no) { + if (i < 2 * MAX_TCP_SESSION && + ack_session_info[i].seq_num == seq_no) { update_tcp_session(i, ack_no); break; } @@ -298,6 +301,9 @@ static int wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev) spin_lock_irqsave(&wilc->txq_spinlock, wilc->txq_spinlock_flags); for (i = pending_base; i < (pending_base + pending_acks); i++) { + if (i >= MAX_PENDING_ACKS || + pending_acks_info[i].session_index >= 2 * MAX_TCP_SESSION) + break; if (pending_acks_info[i].ack_num < ack_session_info[pending_acks_info[i].session_index].bigger_ack_num) { struct txq_entry_t *tqe; @@ -815,7 +821,8 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) if (tqe->tx_complete_func) tqe->tx_complete_func(tqe->priv, tqe->status); - if (tqe->tcp_pending_ack_idx != NOT_TCP_ACK) + if (tqe->tcp_pending_ack_idx != NOT_TCP_ACK && + tqe->tcp_pending_ack_idx < MAX_PENDING_ACKS) pending_acks_info[tqe->tcp_pending_ack_idx].txqe = NULL; kfree(tqe); } else { -- cgit v1.2.3 From cba352a4c10afd609946f6d15bfe82e2a6c421a7 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:25 +0900 Subject: staging: wilc1000: disable power save when AP mode This patch disables power save mode in case of AP mode. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 744b77120b86..e9db04958030 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2203,6 +2203,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, PRINT_ER("Error in setting channel\n"); wilc_wlan_set_bssid(dev, wl->vif[vif->u8IfIdx]->src_addr, AP_MODE); + wilc_set_power_mgmt(vif, 0, 0); s32Error = wilc_add_beacon(vif, settings->beacon_interval, settings->dtim_period, beacon->head_len, -- cgit v1.2.3 From 783d07c1bf8b8e6364aa2e90c83addb8001817e1 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:26 +0900 Subject: staging: wilc1000: fix bug on p2p connection In case of action frame, size -7 is correct, but in this case, size should be used as it is. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index e9db04958030..4038f7db1b35 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1728,7 +1728,7 @@ void WILC_WFI_p2p_rx (struct net_device *dev, u8 *buff, u32 size) } } - cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0); + cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size, 0); } } -- cgit v1.2.3 From 70418790437753faa9a6d7d5c567820e47838e85 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:27 +0900 Subject: staging: wilc1000: add ops tx power in cfg80211 This patch implements set_tx_power and get_tx_power of cfg80211_ops. In addition, Id of HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS is changed with 37. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 88 ++++++++++++++++++++++- drivers/staging/wilc1000/host_interface.h | 2 + drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 35 +++++++++ drivers/staging/wilc1000/wilc_wlan_if.h | 1 + 4 files changed, 125 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 4bbf38c05940..4b1d92cb50d0 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -46,7 +46,9 @@ #define HOST_IF_MSG_DEL_BA_SESSION 34 #define HOST_IF_MSG_Q_IDLE 35 #define HOST_IF_MSG_DEL_ALL_STA 36 -#define HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS 34 +#define HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS 37 +#define HOST_IF_MSG_SET_TX_POWER 38 +#define HOST_IF_MSG_GET_TX_POWER 39 #define HOST_IF_MSG_EXIT 100 #define HOST_IF_SCAN_TIMEOUT 4000 @@ -166,6 +168,10 @@ struct sta_inactive_t { u8 mac[6]; }; +struct tx_power { + u8 tx_pwr; +}; + union message_body { struct scan_attr scan_info; struct connect_attr con_info; @@ -191,6 +197,7 @@ union message_body { struct reg_frame reg_frame; char *data; struct del_all_sta del_all_sta_info; + struct tx_power tx_power; }; struct host_if_msg { @@ -2783,6 +2790,40 @@ static s32 Handle_DelAllRxBASessions(struct wilc_vif *vif, return result; } +static void handle_set_tx_pwr(struct wilc_vif *vif, u8 tx_pwr) +{ + int ret; + struct wid wid; + + wid.id = (u16)WID_TX_POWER; + wid.type = WID_CHAR; + wid.val = &tx_pwr; + wid.size = sizeof(char); + + ret = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + if (ret) + netdev_err(vif->ndev, "Failed to set TX PWR\n"); +} + +static void handle_get_tx_pwr(struct wilc_vif *vif, u8 *tx_pwr) +{ + s32 ret = 0; + struct wid wid; + + wid.id = (u16)WID_TX_POWER; + wid.type = WID_CHAR; + wid.val = (s8 *)tx_pwr; + wid.size = sizeof(char); + + ret = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + if (ret) + netdev_err(vif->ndev, "Failed to get TX PWR\n"); + + up(&hif_sema_wait_response); +} + static int hostIFthread(void *pvArg) { u32 u32Ret; @@ -2986,6 +3027,13 @@ static int hostIFthread(void *pvArg) Handle_DelAllSta(msg.vif, &msg.body.del_all_sta_info); break; + case HOST_IF_MSG_SET_TX_POWER: + handle_set_tx_pwr(msg.vif, msg.body.tx_power.tx_pwr); + break; + + case HOST_IF_MSG_GET_TX_POWER: + handle_get_tx_pwr(msg.vif, &msg.body.tx_power.tx_pwr); + break; default: PRINT_ER("[Host Interface] undefined Received Msg ID\n"); break; @@ -4596,3 +4644,41 @@ static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) return result; } + +int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power) +{ + int ret = 0; + struct host_if_msg msg; + + memset(&msg, 0, sizeof(struct host_if_msg)); + + msg.id = HOST_IF_MSG_SET_TX_POWER; + msg.body.tx_power.tx_pwr = tx_power; + msg.vif = vif; + + ret = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); + if (ret) + netdev_err(vif->ndev, "wilc_mq_send fail\n"); + + return ret; +} + +int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power) +{ + int ret = 0; + struct host_if_msg msg; + + memset(&msg, 0, sizeof(struct host_if_msg)); + + msg.id = HOST_IF_MSG_GET_TX_POWER; + msg.vif = vif; + + ret = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); + if (ret) + netdev_err(vif->ndev, "Failed to get TX PWR\n"); + + down(&hif_sema_wait_response); + *tx_power = msg.body.tx_power.tx_pwr; + + return ret; +} diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 3302a5bb1c6a..69c36a7449c7 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -365,6 +365,8 @@ int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); void wilc_resolve_disconnect_aberration(struct wilc_vif *vif); int wilc_get_vif_idx(struct wilc_vif *vif); +int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power); +int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power); extern bool wilc_optaining_ip; extern u8 wilc_connected_ssid[6]; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 4038f7db1b35..14e1f14256d2 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2504,6 +2504,39 @@ static void wilc_set_wakeup(struct wiphy *wiphy, bool enabled) netdev_info(vif->ndev, "cfg set wake up = %d\n", enabled); } +static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm) +{ + int ret; + s32 tx_power = MBM_TO_DBM(mbm); + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); + + if (tx_power < 0) + tx_power = 0; + else if (tx_power > 18) + tx_power = 18; + ret = wilc_set_tx_power(vif, tx_power); + if (ret) + netdev_err(vif->ndev, "Failed to set tx power\n"); + + return ret; +} + +static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, + int *dbm) +{ + int ret; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); + + ret = wilc_get_tx_power(vif, (u8 *)dbm); + if (ret) + netdev_err(vif->ndev, "Failed to get tx power\n"); + + return ret; +} + static struct cfg80211_ops wilc_cfg80211_ops = { .set_monitor_channel = set_channel, .scan = scan, @@ -2542,6 +2575,8 @@ static struct cfg80211_ops wilc_cfg80211_ops = { .suspend = wilc_suspend, .resume = wilc_resume, .set_wakeup = wilc_set_wakeup, + .set_tx_power = set_tx_power, + .get_tx_power = get_tx_power, }; diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index d306ec1a8529..c446af60dfe8 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -761,6 +761,7 @@ typedef enum { WID_DEL_BEACON = 0x00CA, WID_LOGTerminal_Switch = 0x00CD, + WID_TX_POWER = 0x00CE, /* EMAC Short WID list */ /* RTS Threshold */ /* -- cgit v1.2.3 From ec4504832655e8ebc246d3f96efba4b1ea82ecbe Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:28 +0900 Subject: staging: wilc1000: fix WEP security bug Station cannot connect to soft AP mode wilc when it is configured for WEP security. This patch fixes it by setting the key index within the key value and change the last else condition with DEFAULTKEY action case, and also do not use WILC_WFI_wep_default index to set wep key id. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 27 +++++++++++------------ drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 9 +------- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 1 - 3 files changed, 14 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 4b1d92cb50d0..67bcf889287e 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1737,14 +1737,7 @@ static int Handle_Key(struct wilc_vif *vif, strWIDList[1].size = sizeof(char); strWIDList[1].val = (s8 *)&pstrHostIFkeyAttr->attr.wep.auth_type; - strWIDList[2].id = (u16)WID_KEY_ID; - strWIDList[2].type = WID_CHAR; - - strWIDList[2].val = (s8 *)&pstrHostIFkeyAttr->attr.wep.index; - strWIDList[2].size = sizeof(char); - - pu8keybuf = kmemdup(pstrHostIFkeyAttr->attr.wep.key, - pstrHostIFkeyAttr->attr.wep.key_len, + pu8keybuf = kmalloc(pstrHostIFkeyAttr->attr.wep.key_len + 2, GFP_KERNEL); if (pu8keybuf == NULL) { @@ -1752,15 +1745,21 @@ static int Handle_Key(struct wilc_vif *vif, return -ENOMEM; } + pu8keybuf[0] = pstrHostIFkeyAttr->attr.wep.index; + pu8keybuf[1] = pstrHostIFkeyAttr->attr.wep.key_len; + + memcpy(&pu8keybuf[2], pstrHostIFkeyAttr->attr.wep.key, + pstrHostIFkeyAttr->attr.wep.key_len); + kfree(pstrHostIFkeyAttr->attr.wep.key); - strWIDList[3].id = (u16)WID_WEP_KEY_VALUE; - strWIDList[3].type = WID_STR; - strWIDList[3].size = pstrHostIFkeyAttr->attr.wep.key_len; - strWIDList[3].val = (s8 *)pu8keybuf; + strWIDList[2].id = (u16)WID_WEP_KEY_VALUE; + strWIDList[2].type = WID_STR; + strWIDList[2].size = pstrHostIFkeyAttr->attr.wep.key_len + 2; + strWIDList[2].val = (s8 *)pu8keybuf; result = wilc_send_config_pkt(vif->wilc, SET_CFG, - strWIDList, 4, + strWIDList, 3, wilc_get_vif_idx(vif)); kfree(pu8keybuf); } else if (pstrHostIFkeyAttr->action & ADDKEY) { @@ -1797,7 +1796,7 @@ static int Handle_Key(struct wilc_vif *vif, result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); - } else { + } else if (pstrHostIFkeyAttr->action & DEFAULTKEY) { wid.id = (u16)WID_KEY_ID; wid.type = WID_CHAR; wid.val = (s8 *)&pstrHostIFkeyAttr->attr.wep.index; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 14e1f14256d2..fb940ed4d0ef 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -761,7 +761,6 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, return s32Error; } - priv->WILC_WFI_wep_default = 0; memset(priv->WILC_WFI_wep_key, 0, sizeof(priv->WILC_WFI_wep_key)); memset(priv->WILC_WFI_wep_key_len, 0, sizeof(priv->WILC_WFI_wep_key_len)); @@ -788,7 +787,6 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, for (i = 0; i < sme->key_len; i++) PRINT_D(CORECONFIG_DBG, "WEP Key Value[%d] = %d\n", i, sme->key[i]); } - priv->WILC_WFI_wep_default = sme->key_idx; priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len; memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len); @@ -806,7 +804,6 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, pcgroup_encrypt_val = "WEP104"; pccipher_group = "WLAN_CIPHER_SUITE_WEP104"; - priv->WILC_WFI_wep_default = sme->key_idx; priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len; memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len); @@ -986,7 +983,6 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: if (priv->wdev->iftype == NL80211_IFTYPE_AP) { - priv->WILC_WFI_wep_default = key_index; priv->WILC_WFI_wep_key_len[key_index] = params->key_len; memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len); @@ -1009,7 +1005,6 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, break; } if (memcmp(params->key, priv->WILC_WFI_wep_key[key_index], params->key_len)) { - priv->WILC_WFI_wep_default = key_index; priv->WILC_WFI_wep_key_len[key_index] = params->key_len; memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len); @@ -1336,9 +1331,7 @@ static int set_default_key(struct wiphy *wiphy, struct net_device *netdev, u8 ke PRINT_D(CFG80211_DBG, "Setting default key with idx = %d\n", key_index); - if (key_index != priv->WILC_WFI_wep_default) { - wilc_set_wep_default_keyid(vif, key_index); - } + wilc_set_wep_default_keyid(vif, key_index); return 0; } diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 9f8c79e3d195..07eda4db1dcd 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -124,7 +124,6 @@ struct wilc_priv { struct host_if_drv *hWILCWFIDrv; struct host_if_pmkid_attr pmkid_list; struct WILC_WFI_stats netstats; - u8 WILC_WFI_wep_default; u8 WILC_WFI_wep_key[4][WLAN_KEY_LEN_WEP104]; u8 WILC_WFI_wep_key_len[4]; /* The real interface that the monitor is on */ -- cgit v1.2.3 From 32cee9993c8bccfcf1626b1b192e4ed611a0fcfb Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:29 +0900 Subject: staging: wilc1000: get mac address after setting drv handler This patch moves wilc_get_mac_address and address memcpy function after calling wilc_set_wif_drv_handler to get selected mac address. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 2fafcc47b59d..9de57aeb50d4 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1018,12 +1018,8 @@ int wilc_mac_open(struct net_device *ndev) return ret; } - wilc_get_mac_address(vif, mac_add); - PRINT_D(INIT_DBG, "Mac address: %pM\n", mac_add); - for (i = 0; i < wl->vif_num; i++) { if (ndev == wl->vif[i]->ndev) { - memcpy(wl->vif[i]->src_addr, mac_add, ETH_ALEN); if (vif->iftype == AP_MODE) { wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), @@ -1044,6 +1040,11 @@ int wilc_mac_open(struct net_device *ndev) 1); } wilc_set_operation_mode(vif, vif->iftype); + + wilc_get_mac_address(vif, mac_add); + netdev_dbg(ndev, "Mac address: %pM\n", mac_add); + memcpy(wl->vif[i]->src_addr, mac_add, ETH_ALEN); + break; } } -- cgit v1.2.3 From ef7e012fdc8b5c1d129429cf0cd68ddb0ccc6599 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:30 +0900 Subject: staging: wilc1000: move wilc_send_config_pkt to wilc_wlan.c This patch moves the function wilc_send_config_pkt to wilc_wlan.c which handles transport since the purpose of the function is sending/getting of config information. coreconfiguator.[ch] will be rename with frame.[ch] later. The print codes of the function is removed also and they will be implemented with netdev_xx print format later. struct wid need to be moved to wilc_wlan_if.h which defines configure informations. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 59 ----------------------------- drivers/staging/wilc1000/coreconfigurator.h | 9 ----- drivers/staging/wilc1000/wilc_wlan.c | 39 +++++++++++++++++++ drivers/staging/wilc1000/wilc_wlan.h | 2 + drivers/staging/wilc1000/wilc_wlan_if.h | 7 ++++ 5 files changed, 48 insertions(+), 68 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 49ae9b152654..6f17e2b66673 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -433,62 +433,3 @@ s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *pstrConnectRespInfo) return s32Error; } - -/** - * @brief sends certain Configuration Packet based on the input WIDs pstrWIDs - * using driver config layer - * - * @details - * @param[in] pstrWIDs WIDs to be sent in the configuration packet - * @param[in] u32WIDsCount number of WIDs to be sent in the configuration packet - * @param[out] pu8RxResp The received Packet Response - * @param[out] ps32RxRespLen Length of the received Packet Response - * @return Error code indicating success/failure - * @note - * @author mabubakr - * @date 1 Mar 2012 - * @version 1.0 - */ -s32 wilc_send_config_pkt(struct wilc *wilc, u8 mode, struct wid *wids, - u32 count, u32 drv) -{ - s32 counter = 0, ret = 0; - - if (mode == GET_CFG) { - for (counter = 0; counter < count; counter++) { - PRINT_INFO(CORECONFIG_DBG, "Sending CFG packet [%d][%d]\n", !counter, - (counter == count - 1)); - if (!wilc_wlan_cfg_get(wilc, !counter, - wids[counter].id, - (counter == count - 1), - drv)) { - ret = -ETIMEDOUT; - printk("[Sendconfigpkt]Get Timed out\n"); - break; - } - } - counter = 0; - for (counter = 0; counter < count; counter++) { - wids[counter].size = wilc_wlan_cfg_get_val( - wids[counter].id, - wids[counter].val, - wids[counter].size); - } - } else if (mode == SET_CFG) { - for (counter = 0; counter < count; counter++) { - PRINT_D(CORECONFIG_DBG, "Sending config SET PACKET WID:%x\n", wids[counter].id); - if (!wilc_wlan_cfg_set(wilc, !counter, - wids[counter].id, - wids[counter].val, - wids[counter].size, - (counter == count - 1), - drv)) { - ret = -ETIMEDOUT; - printk("[Sendconfigpkt]Set Timed out\n"); - break; - } - } - } - - return ret; -} diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index fc43d04ca1da..ee107ac915e0 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -70,13 +70,6 @@ typedef enum { CONNECT_STS_FORCE_16_BIT = 0xFFFF } tenuConnectSts; -struct wid { - u16 id; - enum wid_type type; - s32 size; - s8 *val; -}; - typedef struct { u8 u8Full; u8 u8Index; @@ -127,8 +120,6 @@ typedef struct { size_t ie_len; } tstrDisconnectNotifInfo; -s32 wilc_send_config_pkt(struct wilc *wilc, u8 mode, struct wid *wids, - u32 count, u32 drv); s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo); s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo); diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 04d4c92e3948..265ddfe3a924 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1439,6 +1439,45 @@ int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size) return ret; } +s32 wilc_send_config_pkt(struct wilc *wilc, u8 mode, struct wid *wids, + u32 count, u32 drv) +{ + s32 counter = 0, ret = 0; + + if (mode == GET_CFG) { + for (counter = 0; counter < count; counter++) { + if (!wilc_wlan_cfg_get(wilc, !counter, + wids[counter].id, + (counter == count - 1), + drv)) { + ret = -ETIMEDOUT; + break; + } + } + counter = 0; + for (counter = 0; counter < count; counter++) { + wids[counter].size = wilc_wlan_cfg_get_val( + wids[counter].id, + wids[counter].val, + wids[counter].size); + } + } else if (mode == SET_CFG) { + for (counter = 0; counter < count; counter++) { + if (!wilc_wlan_cfg_set(wilc, !counter, + wids[counter].id, + wids[counter].val, + wids[counter].size, + (counter == count - 1), + drv)) { + ret = -ETIMEDOUT; + break; + } + } + } + + return ret; +} + static u32 init_chip(struct net_device *dev) { u32 chipid; diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index 7f046531be01..3ebaf0e3e6bd 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -299,4 +299,6 @@ void host_sleep_notify(struct wilc *wilc); extern bool wilc_enable_ps; void chip_allow_sleep(struct wilc *wilc); void chip_wakeup(struct wilc *wilc); +s32 wilc_send_config_pkt(struct wilc *wilc, u8 mode, struct wid *wids, + u32 count, u32 drv); #endif diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index c446af60dfe8..455a98fb9b20 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -300,6 +300,13 @@ enum wid_type { WID_TYPE_FORCE_32BIT = 0xFFFFFFFF }; +struct wid { + u16 id; + enum wid_type type; + s32 size; + s8 *val; +}; + typedef enum { WID_NIL = 0xffff, -- cgit v1.2.3 From 79df6a490bb0d6d71e97441d4cd3d10d986d5cb3 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:31 +0900 Subject: staging: wilc1000: pass vif to wilc_send_config_pkt This patch passes vif instead of wilc to wilc_send_config_pkt and it's related functions as well, because we need vif which is currently being used and vif has wilc as well. Change custom print with netdev_xxx format if there are custom print inside the functions we have changed. Function parameter of following functions are modified to vif. wilc_send_config_pkt wilc_wlan_cfg_set wilc_wlan_cfg_get wilc_wlan_cfg_commit wilc_wlan_txq_add_cfg_pkt wilc_wlan_txq_add_to_head Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 94 +++++++++++++++---------------- drivers/staging/wilc1000/linux_wlan.c | 88 ++++++++++++++--------------- drivers/staging/wilc1000/wilc_wlan.c | 57 +++++++++++-------- drivers/staging/wilc1000/wilc_wlan.h | 7 ++- 4 files changed, 128 insertions(+), 118 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 67bcf889287e..6f583a4224a6 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -312,7 +312,7 @@ static s32 handle_set_channel(struct wilc_vif *vif, PRINT_D(HOSTINF_DBG, "Setting channel\n"); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -334,7 +334,7 @@ static s32 handle_set_wfi_drv_handler(struct wilc_vif *vif, wid.val = (s8 *)hif_drv_handler; wid.size = sizeof(*hif_drv_handler); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, hif_drv_handler->handler); if (!hif_drv_handler->handler) @@ -359,7 +359,7 @@ static s32 handle_set_operation_mode(struct wilc_vif *vif, wid.val = (s8 *)&hif_op_mode->mode; wid.size = sizeof(u32); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if ((hif_op_mode->mode) == IDLE_MODE) @@ -392,7 +392,7 @@ static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) wid.val = (u8 *)ip_addr; wid.size = IP_ALEN; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); host_int_get_ipaddress(vif, firmware_ip_addr, idx); @@ -417,7 +417,7 @@ static s32 handle_get_ip_address(struct wilc_vif *vif, u8 idx) wid.val = kmalloc(IP_ALEN, GFP_KERNEL); wid.size = IP_ALEN; - result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); PRINT_INFO(HOSTINF_DBG, "%pI4\n", wid.val); @@ -460,7 +460,7 @@ static s32 handle_set_mac_address(struct wilc_vif *vif, wid.size = ETH_ALEN; PRINT_D(GENERIC_DBG, "mac addr = :%pM\n", wid.val); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to set mac address\n"); @@ -482,7 +482,7 @@ static s32 handle_get_mac_address(struct wilc_vif *vif, wid.val = get_mac_addr->mac_addr; wid.size = ETH_ALEN; - result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -778,7 +778,7 @@ static s32 handle_cfg_param(struct wilc_vif *vif, wid_cnt++; } - result = wilc_send_config_pkt(vif->wilc, SET_CFG, wid_list, + result = wilc_send_config_pkt(vif, SET_CFG, wid_list, wid_cnt, wilc_get_vif_idx(vif)); if (result) @@ -902,7 +902,7 @@ static s32 Handle_Scan(struct wilc_vif *vif, else if (hif_drv->hif_state == HOST_IF_IDLE) scan_while_connected = false; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, strWIDList, + result = wilc_send_config_pkt(vif, SET_CFG, strWIDList, u32WidsCount, wilc_get_vif_idx(vif)); @@ -948,7 +948,7 @@ static s32 Handle_ScanDone(struct wilc_vif *vif, wid.val = (s8 *)&u8abort_running_scan; wid.size = sizeof(char); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -1204,7 +1204,7 @@ static s32 Handle_Connect(struct wilc_vif *vif, PRINT_D(GENERIC_DBG, "save bssid = %pM\n", wilc_connected_ssid); } - result = wilc_send_config_pkt(vif->wilc, SET_CFG, strWIDList, + result = wilc_send_config_pkt(vif, SET_CFG, strWIDList, u32WidsCount, wilc_get_vif_idx(vif)); if (result) { @@ -1302,7 +1302,7 @@ static s32 Handle_FlushConnect(struct wilc_vif *vif) u32WidsCount++; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, strWIDList, + result = wilc_send_config_pkt(vif, SET_CFG, strWIDList, u32WidsCount, wilc_get_vif_idx(join_req_vif)); if (result) { @@ -1365,7 +1365,7 @@ static s32 Handle_ConnectTimeout(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Sending disconnect request\n"); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send dissconect config packet\n"); @@ -1758,7 +1758,7 @@ static int Handle_Key(struct wilc_vif *vif, strWIDList[2].size = pstrHostIFkeyAttr->attr.wep.key_len + 2; strWIDList[2].val = (s8 *)pu8keybuf; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, + result = wilc_send_config_pkt(vif, SET_CFG, strWIDList, 3, wilc_get_vif_idx(vif)); kfree(pu8keybuf); @@ -1780,7 +1780,7 @@ static int Handle_Key(struct wilc_vif *vif, wid.val = (s8 *)pu8keybuf; wid.size = pstrHostIFkeyAttr->attr.wep.key_len + 2; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); kfree(pu8keybuf); @@ -1793,7 +1793,7 @@ static int Handle_Key(struct wilc_vif *vif, wid.val = s8idxarray; wid.size = 1; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); } else if (pstrHostIFkeyAttr->action & DEFAULTKEY) { @@ -1804,7 +1804,7 @@ static int Handle_Key(struct wilc_vif *vif, PRINT_D(HOSTINF_DBG, "Setting default key index\n"); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); } @@ -1838,7 +1838,7 @@ static int Handle_Key(struct wilc_vif *vif, strWIDList[1].val = (s8 *)pu8keybuf; strWIDList[1].size = RX_MIC_KEY_MSG_LEN; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, + result = wilc_send_config_pkt(vif, SET_CFG, strWIDList, 2, wilc_get_vif_idx(vif)); @@ -1870,7 +1870,7 @@ static int Handle_Key(struct wilc_vif *vif, wid.val = (s8 *)pu8keybuf; wid.size = RX_MIC_KEY_MSG_LEN; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); @@ -1910,7 +1910,7 @@ _WPARxGtk_end_case_: strWIDList[1].val = (s8 *)pu8keybuf; strWIDList[1].size = PTK_KEY_MSG_LEN + 1; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, + result = wilc_send_config_pkt(vif, SET_CFG, strWIDList, 2, wilc_get_vif_idx(vif)); kfree(pu8keybuf); @@ -1933,7 +1933,7 @@ _WPARxGtk_end_case_: wid.val = (s8 *)pu8keybuf; wid.size = PTK_KEY_MSG_LEN; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); kfree(pu8keybuf); @@ -1969,7 +1969,7 @@ _WPAPtk_end_case_: wid.val = (s8 *)pu8keybuf; wid.size = (pstrHostIFkeyAttr->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); kfree(pu8keybuf); @@ -2002,7 +2002,7 @@ static void Handle_Disconnect(struct wilc_vif *vif) eth_zero_addr(wilc_connected_ssid); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -2093,7 +2093,7 @@ static s32 Handle_GetChnl(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Getting channel value\n"); - result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -2118,7 +2118,7 @@ static void Handle_GetRssi(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Getting RSSI value\n"); - result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to get RSSI value\n"); @@ -2143,7 +2143,7 @@ static void Handle_GetLinkspeed(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Getting LINKSPEED value\n"); - result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to get LINKSPEED value\n"); @@ -2189,7 +2189,7 @@ static s32 Handle_GetStatistics(struct wilc_vif *vif, strWIDList[u32WidsCount].val = (s8 *)&pstrStatistics->tx_fail_cnt; u32WidsCount++; - result = wilc_send_config_pkt(vif->wilc, GET_CFG, strWIDList, + result = wilc_send_config_pkt(vif, GET_CFG, strWIDList, u32WidsCount, wilc_get_vif_idx(vif)); @@ -2225,7 +2225,7 @@ static s32 Handle_Get_InActiveTime(struct wilc_vif *vif, PRINT_D(CFG80211_DBG, "SETING STA inactive time\n"); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -2238,7 +2238,7 @@ static s32 Handle_Get_InActiveTime(struct wilc_vif *vif, wid.val = (s8 *)&inactive_time; wid.size = sizeof(u32); - result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -2297,8 +2297,8 @@ static void Handle_AddBeacon(struct wilc_vif *vif, memcpy(pu8CurrByte, pstrSetBeaconParam->tail, pstrSetBeaconParam->tail_len); pu8CurrByte += pstrSetBeaconParam->tail_len; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send add beacon config packet\n"); @@ -2326,7 +2326,7 @@ static void Handle_DelBeacon(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Deleting BEACON\n"); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send delete beacon config packet\n"); @@ -2399,7 +2399,7 @@ static void Handle_AddStation(struct wilc_vif *vif, pu8CurrByte = wid.val; pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result != 0) PRINT_ER("Failed to send add station config packet\n"); @@ -2441,7 +2441,7 @@ static void Handle_DelAllSta(struct wilc_vif *vif, pu8CurrByte += ETH_ALEN; } - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send add station config packet\n"); @@ -2473,7 +2473,7 @@ static void Handle_DelStation(struct wilc_vif *vif, memcpy(pu8CurrByte, pstrDelStaParam->mac_addr, ETH_ALEN); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send add station config packet\n"); @@ -2501,7 +2501,7 @@ static void Handle_EditStation(struct wilc_vif *vif, pu8CurrByte = wid.val; pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send edit station config packet\n"); @@ -2563,7 +2563,7 @@ static int Handle_RemainOnChan(struct wilc_vif *vif, wid.val[0] = u8remain_on_chan_flag; wid.val[1] = (s8)pstrHostIfRemainOnChan->ch; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result != 0) PRINT_ER("Failed to set remain on channel\n"); @@ -2611,7 +2611,7 @@ static int Handle_RegisterFrame(struct wilc_vif *vif, wid.size = sizeof(u16) + 2; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to frame register config packet\n"); @@ -2646,7 +2646,7 @@ static u32 Handle_ListenStateExpired(struct wilc_vif *vif, wid.val[0] = u8remain_on_chan_flag; wid.val[1] = FALSE_FRMWR_CHANNEL; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result != 0) { PRINT_ER("Failed to set remain on channel\n"); @@ -2704,7 +2704,7 @@ static void Handle_PowerManagement(struct wilc_vif *vif, PRINT_D(HOSTINF_DBG, "Handling Power Management\n"); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send power management config packet\n"); @@ -2741,7 +2741,7 @@ static void Handle_SetMulticastFilter(struct wilc_vif *vif, memcpy(pu8CurrByte, wilc_multicast_mac_addr_list, ((strHostIfSetMulti->cnt) * ETH_ALEN)); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send setup multicast config packet\n"); @@ -2777,7 +2777,7 @@ static s32 Handle_DelAllRxBASessions(struct wilc_vif *vif, *ptr++ = 0; *ptr++ = 32; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) PRINT_D(HOSTINF_DBG, "Couldn't delete BA Session\n"); @@ -2799,8 +2799,8 @@ static void handle_set_tx_pwr(struct wilc_vif *vif, u8 tx_pwr) wid.val = &tx_pwr; wid.size = sizeof(char); - ret = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); if (ret) netdev_err(vif->ndev, "Failed to set TX PWR\n"); } @@ -2815,8 +2815,8 @@ static void handle_get_tx_pwr(struct wilc_vif *vif, u8 *tx_pwr) wid.val = (s8 *)tx_pwr; wid.size = sizeof(char); - ret = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + ret = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); if (ret) netdev_err(vif->ndev, "Failed to get TX PWR\n"); @@ -3513,7 +3513,7 @@ static s32 host_int_get_assoc_res_info(struct wilc_vif *vif, wid.val = pu8AssocRespInfo; wid.size = u32MaxAssocRespInfoLen; - result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { *pu32RcvdAssocRespInfoLen = 0; diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 9de57aeb50d4..a3b4939048d8 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -526,86 +526,86 @@ static int linux_wlan_init_test_config(struct net_device *dev, *(int *)c_val = 1; - if (!wilc_wlan_cfg_set(wilc, 1, WID_SET_DRV_HANDLER, c_val, 4, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 1, WID_SET_DRV_HANDLER, c_val, 4, 0, 0)) goto _fail_; c_val[0] = 0; - if (!wilc_wlan_cfg_set(wilc, 0, WID_PC_TEST_MODE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_PC_TEST_MODE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = INFRASTRUCTURE; - if (!wilc_wlan_cfg_set(wilc, 0, WID_BSS_TYPE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_BSS_TYPE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = RATE_AUTO; - if (!wilc_wlan_cfg_set(wilc, 0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = G_MIXED_11B_2_MODE; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11G_OPERATING_MODE, c_val, 1, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_11G_OPERATING_MODE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 1; - if (!wilc_wlan_cfg_set(wilc, 0, WID_CURRENT_CHANNEL, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_CHANNEL, c_val, 1, 0, 0)) goto _fail_; c_val[0] = G_SHORT_PREAMBLE; - if (!wilc_wlan_cfg_set(wilc, 0, WID_PREAMBLE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_PREAMBLE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = AUTO_PROT; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_PROT_MECH, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_PROT_MECH, c_val, 1, 0, 0)) goto _fail_; c_val[0] = ACTIVE_SCAN; - if (!wilc_wlan_cfg_set(wilc, 0, WID_SCAN_TYPE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_SCAN_TYPE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = SITE_SURVEY_OFF; - if (!wilc_wlan_cfg_set(wilc, 0, WID_SITE_SURVEY, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_SITE_SURVEY, c_val, 1, 0, 0)) goto _fail_; *((int *)c_val) = 0xffff; - if (!wilc_wlan_cfg_set(wilc, 0, WID_RTS_THRESHOLD, c_val, 2, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_RTS_THRESHOLD, c_val, 2, 0, 0)) goto _fail_; *((int *)c_val) = 2346; - if (!wilc_wlan_cfg_set(wilc, 0, WID_FRAG_THRESHOLD, c_val, 2, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_FRAG_THRESHOLD, c_val, 2, 0, 0)) goto _fail_; c_val[0] = 0; - if (!wilc_wlan_cfg_set(wilc, 0, WID_BCAST_SSID, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_BCAST_SSID, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 1; - if (!wilc_wlan_cfg_set(wilc, 0, WID_QOS_ENABLE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_QOS_ENABLE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = NO_POWERSAVE; - if (!wilc_wlan_cfg_set(wilc, 0, WID_POWER_MANAGEMENT, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_POWER_MANAGEMENT, c_val, 1, 0, 0)) goto _fail_; c_val[0] = NO_SECURITY; /* NO_ENCRYPT, 0x79 */ - if (!wilc_wlan_cfg_set(wilc, 0, WID_11I_MODE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_11I_MODE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = OPEN_SYSTEM; - if (!wilc_wlan_cfg_set(wilc, 0, WID_AUTH_TYPE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_AUTH_TYPE, c_val, 1, 0, 0)) goto _fail_; strcpy(c_val, "123456790abcdef1234567890"); - if (!wilc_wlan_cfg_set(wilc, 0, WID_WEP_KEY_VALUE, c_val, + if (!wilc_wlan_cfg_set(vif, 0, WID_WEP_KEY_VALUE, c_val, (strlen(c_val) + 1), 0, 0)) goto _fail_; strcpy(c_val, "12345678"); - if (!wilc_wlan_cfg_set(wilc, 0, WID_11I_PSK, c_val, (strlen(c_val)), 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_11I_PSK, c_val, (strlen(c_val)), 0, 0)) goto _fail_; strcpy(c_val, "password"); - if (!wilc_wlan_cfg_set(wilc, 0, WID_1X_KEY, c_val, (strlen(c_val) + 1), + if (!wilc_wlan_cfg_set(vif, 0, WID_1X_KEY, c_val, (strlen(c_val) + 1), 0, 0)) goto _fail_; @@ -613,106 +613,106 @@ static int linux_wlan_init_test_config(struct net_device *dev, c_val[1] = 168; c_val[2] = 1; c_val[3] = 112; - if (!wilc_wlan_cfg_set(wilc, 0, WID_1X_SERV_ADDR, c_val, 4, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_1X_SERV_ADDR, c_val, 4, 0, 0)) goto _fail_; c_val[0] = 3; - if (!wilc_wlan_cfg_set(wilc, 0, WID_LISTEN_INTERVAL, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_LISTEN_INTERVAL, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 3; - if (!wilc_wlan_cfg_set(wilc, 0, WID_DTIM_PERIOD, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_DTIM_PERIOD, c_val, 1, 0, 0)) goto _fail_; c_val[0] = NORMAL_ACK; - if (!wilc_wlan_cfg_set(wilc, 0, WID_ACK_POLICY, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_ACK_POLICY, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 0; - if (!wilc_wlan_cfg_set(wilc, 0, WID_USER_CONTROL_ON_TX_POWER, c_val, 1, + if (!wilc_wlan_cfg_set(vif, 0, WID_USER_CONTROL_ON_TX_POWER, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 48; - if (!wilc_wlan_cfg_set(wilc, 0, WID_TX_POWER_LEVEL_11A, c_val, 1, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11A, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 28; - if (!wilc_wlan_cfg_set(wilc, 0, WID_TX_POWER_LEVEL_11B, c_val, 1, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11B, c_val, 1, 0, 0)) goto _fail_; *((int *)c_val) = 100; - if (!wilc_wlan_cfg_set(wilc, 0, WID_BEACON_INTERVAL, c_val, 2, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_BEACON_INTERVAL, c_val, 2, 0, 0)) goto _fail_; c_val[0] = REKEY_DISABLE; - if (!wilc_wlan_cfg_set(wilc, 0, WID_REKEY_POLICY, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_POLICY, c_val, 1, 0, 0)) goto _fail_; *((int *)c_val) = 84600; - if (!wilc_wlan_cfg_set(wilc, 0, WID_REKEY_PERIOD, c_val, 4, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PERIOD, c_val, 4, 0, 0)) goto _fail_; *((int *)c_val) = 500; - if (!wilc_wlan_cfg_set(wilc, 0, WID_REKEY_PACKET_COUNT, c_val, 4, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PACKET_COUNT, c_val, 4, 0, 0)) goto _fail_; c_val[0] = 1; - if (!wilc_wlan_cfg_set(wilc, 0, WID_SHORT_SLOT_ALLOWED, c_val, 1, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_SHORT_SLOT_ALLOWED, c_val, 1, 0, 0)) goto _fail_; c_val[0] = G_SELF_CTS_PROT; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_ERP_PROT_TYPE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ERP_PROT_TYPE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 1; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_ENABLE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ENABLE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = HT_MIXED_MODE; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_OPERATING_MODE, c_val, 1, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OPERATING_MODE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 1; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_TXOP_PROT_DISABLE, c_val, 1, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_TXOP_PROT_DISABLE, c_val, 1, 0, 0)) goto _fail_; memcpy(c_val, mac_add, 6); - if (!wilc_wlan_cfg_set(wilc, 0, WID_MAC_ADDR, c_val, 6, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_MAC_ADDR, c_val, 6, 0, 0)) goto _fail_; c_val[0] = DETECT_PROTECT_REPORT; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_OBSS_NONHT_DETECTION, c_val, 1, + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OBSS_NONHT_DETECTION, c_val, 1, 0, 0)) goto _fail_; c_val[0] = RTS_CTS_NONHT_PROT; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_HT_PROT_TYPE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_HT_PROT_TYPE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 0; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_RIFS_PROT_ENABLE, c_val, 1, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_RIFS_PROT_ENABLE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = MIMO_MODE; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_SMPS_MODE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_SMPS_MODE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 7; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_CURRENT_TX_MCS, c_val, 1, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_CURRENT_TX_MCS, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 1; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_IMMEDIATE_BA_ENABLED, c_val, 1, + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_IMMEDIATE_BA_ENABLED, c_val, 1, 1, 1)) goto _fail_; @@ -927,7 +927,7 @@ int wilc1000_wlan_init(struct net_device *dev, struct wilc_vif *vif) goto _fail_irq_enable_; } - if (wilc_wlan_cfg_get(wl, 1, WID_FIRMWARE_VERSION, 1, 0)) { + if (wilc_wlan_cfg_get(vif, 1, WID_FIRMWARE_VERSION, 1, 0)) { int size; char Firmware_ver[20]; diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 265ddfe3a924..392ef162772f 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -113,9 +113,11 @@ static void wilc_wlan_txq_add_to_tail(struct net_device *dev, up(&wilc->txq_event); } -static int wilc_wlan_txq_add_to_head(struct wilc *wilc, struct txq_entry_t *tqe) +static int wilc_wlan_txq_add_to_head(struct wilc_vif *vif, struct txq_entry_t *tqe) { unsigned long flags; + struct wilc *wilc = vif->wilc; + if (wilc_lock_timeout(wilc, &wilc->txq_add_to_head_cs, CFG_PKTS_TIMEOUT)) return -1; @@ -134,12 +136,12 @@ static int wilc_wlan_txq_add_to_head(struct wilc *wilc, struct txq_entry_t *tqe) wilc->txq_head = tqe; } wilc->txq_entries += 1; - PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", wilc->txq_entries); + netdev_dbg(vif->ndev, "Number of entries in TxQ = %d\n", wilc->txq_entries); spin_unlock_irqrestore(&wilc->txq_spinlock, flags); up(&wilc->txq_add_to_head_cs); up(&wilc->txq_event); - PRINT_D(TX_DBG, "Wake up the txq_handler\n"); + netdev_dbg(vif->ndev, "Wake up the txq_handler\n"); return 0; } @@ -351,20 +353,22 @@ static bool is_tcp_ack_filter_enabled(void) return enabled; } -static int wilc_wlan_txq_add_cfg_pkt(struct wilc *wilc, u8 *buffer, u32 buffer_size) +static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer, + u32 buffer_size) { struct txq_entry_t *tqe; + struct wilc *wilc = vif->wilc; - PRINT_D(TX_DBG, "Adding config packet ...\n"); + netdev_dbg(vif->ndev, "Adding config packet ...\n"); if (wilc->quit) { - PRINT_D(TX_DBG, "Return due to clear function\n"); + netdev_dbg(vif->ndev, "Return due to clear function\n"); up(&wilc->cfg_event); return 0; } tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC); if (!tqe) { - PRINT_ER("Failed to allocate memory\n"); + netdev_err(vif->ndev, "Failed to allocate memory\n"); return 0; } @@ -374,9 +378,9 @@ static int wilc_wlan_txq_add_cfg_pkt(struct wilc *wilc, u8 *buffer, u32 buffer_s tqe->tx_complete_func = NULL; tqe->priv = NULL; tqe->tcp_pending_ack_idx = NOT_TCP_ACK; - PRINT_D(TX_DBG, "Adding the config packet at the Queue tail\n"); + netdev_dbg(vif->ndev, "Adding the config packet at the Queue tail\n"); - if (wilc_wlan_txq_add_to_head(wilc, tqe)) + if (wilc_wlan_txq_add_to_head(vif, tqe)) return 0; return 1; } @@ -1326,8 +1330,10 @@ void wilc_wlan_cleanup(struct net_device *dev) wilc->hif_func->hif_deinit(NULL); } -static int wilc_wlan_cfg_commit(struct wilc *wilc, int type, u32 drv_handler) +static int wilc_wlan_cfg_commit(struct wilc_vif *vif, int type, + u32 drv_handler) { + struct wilc *wilc = vif->wilc; struct wilc_cfg_frame *cfg = &wilc->cfg_frame; int total_len = wilc->cfg_frame_offset + 4 + DRIVER_HANDLER_SIZE; int seq_no = wilc->cfg_seq_no % 256; @@ -1346,17 +1352,18 @@ static int wilc_wlan_cfg_commit(struct wilc *wilc, int type, u32 drv_handler) cfg->wid_header[7] = (u8)(driver_handler >> 24); wilc->cfg_seq_no = seq_no; - if (!wilc_wlan_txq_add_cfg_pkt(wilc, &cfg->wid_header[0], total_len)) + if (!wilc_wlan_txq_add_cfg_pkt(vif, &cfg->wid_header[0], total_len)) return -1; return 0; } -int wilc_wlan_cfg_set(struct wilc *wilc, int start, u32 wid, u8 *buffer, +int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u32 wid, u8 *buffer, u32 buffer_size, int commit, u32 drv_handler) { u32 offset; int ret_size; + struct wilc *wilc = vif->wilc; if (wilc->cfg_frame_in_use) return 0; @@ -1371,17 +1378,18 @@ int wilc_wlan_cfg_set(struct wilc *wilc, int start, u32 wid, u8 *buffer, wilc->cfg_frame_offset = offset; if (commit) { - PRINT_D(TX_DBG, "[WILC]PACKET Commit with sequence number %d\n", - wilc->cfg_seq_no); - PRINT_D(RX_DBG, "Processing cfg_set()\n"); + netdev_dbg(vif->ndev, + "[WILC]PACKET Commit with sequence number %d\n", + wilc->cfg_seq_no); + netdev_dbg(vif->ndev, "Processing cfg_set()\n"); wilc->cfg_frame_in_use = 1; - if (wilc_wlan_cfg_commit(wilc, WILC_CFG_SET, drv_handler)) + if (wilc_wlan_cfg_commit(vif, WILC_CFG_SET, drv_handler)) ret_size = 0; if (wilc_lock_timeout(wilc, &wilc->cfg_event, CFG_PKTS_TIMEOUT)) { - PRINT_D(TX_DBG, "Set Timed Out\n"); + netdev_dbg(vif->ndev, "Set Timed Out\n"); ret_size = 0; } wilc->cfg_frame_in_use = 0; @@ -1392,11 +1400,12 @@ int wilc_wlan_cfg_set(struct wilc *wilc, int start, u32 wid, u8 *buffer, return ret_size; } -int wilc_wlan_cfg_get(struct wilc *wilc, int start, u32 wid, int commit, +int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u32 wid, int commit, u32 drv_handler) { u32 offset; int ret_size; + struct wilc *wilc = vif->wilc; if (wilc->cfg_frame_in_use) return 0; @@ -1413,15 +1422,15 @@ int wilc_wlan_cfg_get(struct wilc *wilc, int start, u32 wid, int commit, if (commit) { wilc->cfg_frame_in_use = 1; - if (wilc_wlan_cfg_commit(wilc, WILC_CFG_QUERY, drv_handler)) + if (wilc_wlan_cfg_commit(vif, WILC_CFG_QUERY, drv_handler)) ret_size = 0; if (wilc_lock_timeout(wilc, &wilc->cfg_event, CFG_PKTS_TIMEOUT)) { - PRINT_D(TX_DBG, "Get Timed Out\n"); + netdev_dbg(vif->ndev, "Get Timed Out\n"); ret_size = 0; } - PRINT_D(GENERIC_DBG, "[WILC]Get Response received\n"); + netdev_dbg(vif->ndev, "[WILC]Get Response received\n"); wilc->cfg_frame_in_use = 0; wilc->cfg_frame_offset = 0; wilc->cfg_seq_no += 1; @@ -1439,14 +1448,14 @@ int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size) return ret; } -s32 wilc_send_config_pkt(struct wilc *wilc, u8 mode, struct wid *wids, +s32 wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, u32 count, u32 drv) { s32 counter = 0, ret = 0; if (mode == GET_CFG) { for (counter = 0; counter < count; counter++) { - if (!wilc_wlan_cfg_get(wilc, !counter, + if (!wilc_wlan_cfg_get(vif, !counter, wids[counter].id, (counter == count - 1), drv)) { @@ -1463,7 +1472,7 @@ s32 wilc_send_config_pkt(struct wilc *wilc, u8 mode, struct wid *wids, } } else if (mode == SET_CFG) { for (counter = 0; counter < count; counter++) { - if (!wilc_wlan_cfg_set(wilc, !counter, + if (!wilc_wlan_cfg_set(vif, !counter, wids[counter].id, wids[counter].val, wids[counter].size, diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index 3ebaf0e3e6bd..e913ae7abef7 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -268,6 +268,7 @@ struct wilc_cfg_rsp { }; struct wilc; +struct wilc_vif; int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u32 buffer_size); int wilc_wlan_start(struct wilc *); @@ -277,9 +278,9 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count); void wilc_handle_isr(struct wilc *wilc); void wilc_wlan_cleanup(struct net_device *dev); -int wilc_wlan_cfg_set(struct wilc *wilc, int start, u32 wid, u8 *buffer, +int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u32 wid, u8 *buffer, u32 buffer_size, int commit, u32 drv_handler); -int wilc_wlan_cfg_get(struct wilc *wilc, int start, u32 wid, int commit, +int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u32 wid, int commit, u32 drv_handler); int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size); int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, @@ -299,6 +300,6 @@ void host_sleep_notify(struct wilc *wilc); extern bool wilc_enable_ps; void chip_allow_sleep(struct wilc *wilc); void chip_wakeup(struct wilc *wilc); -s32 wilc_send_config_pkt(struct wilc *wilc, u8 mode, struct wid *wids, +s32 wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, u32 count, u32 drv); #endif -- cgit v1.2.3 From 48b28df99c302cd0e84b099c7333f921fb09ff35 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:32 +0900 Subject: staging: wilc1000: rename hWILCWFIDrv of wilc_priv structure This patch renames hWILCWFIDrv pointer variable of wilc_priv structure to hif_drv to avoid camelcase. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 8 ++++---- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 22 ++++++++++++---------- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index a3b4939048d8..06c79dd0bdd8 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -89,7 +89,7 @@ static int dev_state_ev_handler(struct notifier_block *this, unsigned long event PRINT_D(GENERIC_DBG, "No Wireless Priv\n"); return NOTIFY_DONE; } - hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv; + hif_drv = (struct host_if_drv *)priv->hif_drv; vif = netdev_priv(dev); if (!vif || !hif_drv) { PRINT_D(GENERIC_DBG, "No Wireless Priv\n"); @@ -515,7 +515,7 @@ static int linux_wlan_init_test_config(struct net_device *dev, PRINT_D(TX_DBG, "Start configuring Firmware\n"); priv = wiphy_priv(dev->ieee80211_ptr->wiphy); - hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv; + hif_drv = (struct host_if_drv *)priv->hif_drv; PRINT_D(INIT_DBG, "Host = %p\n", hif_drv); wilc_get_mac_address(vif, mac_add); @@ -1089,7 +1089,7 @@ static void wilc_set_multicast_list(struct net_device *dev) priv = wiphy_priv(dev->ieee80211_ptr->wiphy); vif = netdev_priv(dev); - hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv; + hif_drv = (struct host_if_drv *)priv->hif_drv; if (!dev) return; @@ -1228,7 +1228,7 @@ int wilc_mac_close(struct net_device *ndev) return 0; } - hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv; + hif_drv = (struct host_if_drv *)priv->hif_drv; PRINT_D(GENERIC_DBG, "Mac close\n"); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index fb940ed4d0ef..b8fd6956d4c5 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -512,7 +512,7 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, dev = priv->dev; vif = netdev_priv(dev); wl = vif->wilc; - pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv; + pstrWFIDrv = (struct host_if_drv *)priv->hif_drv; if (enuConnDisconnEvent == CONN_DISCONN_EVENT_CONN_RESP) { u16 u16ConnectStatus; @@ -711,9 +711,11 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, wilc_connecting = 1; priv = wiphy_priv(wiphy); vif = netdev_priv(priv->dev); - pstrWFIDrv = (struct host_if_drv *)(priv->hWILCWFIDrv); + pstrWFIDrv = (struct host_if_drv *)priv->hif_drv; - PRINT_D(CFG80211_DBG, "Connecting to SSID [%s] on netdev [%p] host if [%p]\n", sme->ssid, dev, priv->hWILCWFIDrv); + PRINT_D(CFG80211_DBG, + "Connecting to SSID [%s] on netdev [%p] host if [%p]\n", + sme->ssid, dev, priv->hif_drv); if (!(strncmp(sme->ssid, "DIRECT-", 7))) { PRINT_D(CFG80211_DBG, "Connected to Direct network,OBSS disabled\n"); pstrWFIDrv->p2p_connect = 1; @@ -928,7 +930,7 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_co priv = wiphy_priv(wiphy); vif = netdev_priv(priv->dev); - pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv; + pstrWFIDrv = (struct host_if_drv *)priv->hif_drv; if (!pstrWFIDrv->p2p_connect) wlan_channel = INVALID_CHANNEL; wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE); @@ -1276,7 +1278,7 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev, wilc_remove_wep_key(vif, key_index); } else { PRINT_D(CFG80211_DBG, "Removing all installed keys\n"); - wilc_remove_key(priv->hWILCWFIDrv, mac_addr); + wilc_remove_key(priv->hif_drv, mac_addr); } return 0; @@ -1632,7 +1634,7 @@ void WILC_WFI_p2p_rx (struct net_device *dev, u8 *buff, u32 size) s32 s32Freq; priv = wiphy_priv(dev->ieee80211_ptr->wiphy); - pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv; + pstrWFIDrv = (struct host_if_drv *)priv->hif_drv; memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET); @@ -1844,7 +1846,7 @@ static int mgmt_tx(struct wiphy *wiphy, vif = netdev_priv(wdev->netdev); priv = wiphy_priv(wiphy); - pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv; + pstrWFIDrv = (struct host_if_drv *)priv->hif_drv; *cookie = (unsigned long)buf; priv->u64tx_cookie = *cookie; @@ -1970,7 +1972,7 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy, struct host_if_drv *pstrWFIDrv; priv = wiphy_priv(wiphy); - pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv; + pstrWFIDrv = (struct host_if_drv *)priv->hif_drv; PRINT_D(GENERIC_DBG, "Tx Cancel wait :%lu\n", jiffies); @@ -2070,7 +2072,7 @@ static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, priv = wiphy_priv(wiphy); vif = netdev_priv(priv->dev); - if (!priv->hWILCWFIDrv) { + if (!priv->hif_drv) { PRINT_ER("Driver is NULL\n"); return -EIO; } @@ -2715,7 +2717,7 @@ int wilc_init_host_int(struct net_device *net) priv->bInP2PlistenState = false; sema_init(&(priv->hSemScanReq), 1); - s32Error = wilc_init(net, &priv->hWILCWFIDrv); + s32Error = wilc_init(net, &priv->hif_drv); if (s32Error) PRINT_ER("Error while initializing hostinterface\n"); diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 07eda4db1dcd..64fcb777cc2d 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -121,7 +121,7 @@ struct wilc_priv { spinlock_t lock; struct net_device *dev; struct napi_struct napi; - struct host_if_drv *hWILCWFIDrv; + struct host_if_drv *hif_drv; struct host_if_pmkid_attr pmkid_list; struct WILC_WFI_stats netstats; u8 WILC_WFI_wep_key[4][WLAN_KEY_LEN_WEP104]; -- cgit v1.2.3 From fa8b23c6f25dae2b83882feb1aadceece69d9cdf Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:33 +0900 Subject: staging: wilc1000: fixes missing a blank line after declarations This patch fixes the warnings reported by checkpatch.pl for Missing a blank line after declarations. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 06c79dd0bdd8..5992478015a2 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -853,6 +853,7 @@ static void wlan_deinitialize_threads(struct net_device *dev) { struct wilc_vif *vif; struct wilc *wl; + vif = netdev_priv(dev); wl = vif->wilc; @@ -1472,6 +1473,7 @@ int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, { struct wireless_dev *wdev; + wdev = wilc_create_wiphy(ndev, dev); if (dev) -- cgit v1.2.3 From 5b9f526e79f347faa2fd3f9e09b226da63b95c7f Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:34 +0900 Subject: staging: wilc1000: rename pBssid of tx_complete_data structure This patch renames pBssid variable of tx_complete_data structure to bssid to avoid camelcase. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 2 +- drivers/staging/wilc1000/wilc_wlan.c | 2 +- drivers/staging/wilc1000/wilc_wlan_if.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 5992478015a2..f5f787ef90c0 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1193,7 +1193,7 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) PRINT_D(TX_DBG, "Adding tx packet to TX Queue\n"); vif->netstats.tx_packets++; vif->netstats.tx_bytes += tx_data->size; - tx_data->pBssid = wilc->vif[vif->u8IfIdx]->bssid; + tx_data->bssid = wilc->vif[vif->u8IfIdx]->bssid; queue_count = wilc_wlan_txq_add_net_pkt(ndev, (void *)tx_data, tx_data->buff, tx_data->size, linux_wlan_tx_complete); diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 392ef162772f..ebf38a578694 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -809,7 +809,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) if (tqe->type == WILC_CFG_PKT) { buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET; } else if (tqe->type == WILC_NET_PKT) { - char *bssid = ((struct tx_complete_data *)(tqe->priv))->pBssid; + char *bssid = ((struct tx_complete_data *)(tqe->priv))->bssid; buffer_offset = ETH_ETHERNET_HDR_OFFSET; memcpy(&txb[offset + 4], bssid, 6); diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index 455a98fb9b20..294552dda7b5 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -82,7 +82,7 @@ typedef struct { struct tx_complete_data { int size; void *buff; - u8 *pBssid; + u8 *bssid; struct sk_buff *skb; }; -- cgit v1.2.3 From 885cabccf9e834b4208873a7168f6fef7d0c0104 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:35 +0900 Subject: staging: wilc1000: remove warnings line over 80 characters This patch removes the warnings reported by checkpatch.pl for line over 80 characters. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index f5f787ef90c0..1446b194c4ef 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -25,7 +25,8 @@ #include -static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr); +static int dev_state_ev_handler(struct notifier_block *this, + unsigned long event, void *ptr); static struct notifier_block g_dev_notifier = { .notifier_call = dev_state_ev_handler @@ -57,7 +58,8 @@ static const struct net_device_ops wilc_netdev_ops = { }; -static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr) +static int dev_state_ev_handler(struct notifier_block *this, + unsigned long event, void *ptr) { struct in_ifaddr *dev_iface = (struct in_ifaddr *)ptr; struct wilc_priv *priv; -- cgit v1.2.3 From 1408603c95133c38b950498205c4d9d012a7086a Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:36 +0900 Subject: staging: wilc1000: removes unnecessary debug logs This patch removes unnecessary debug logs. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 154 ++++++---------------------------- 1 file changed, 24 insertions(+), 130 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 1446b194c4ef..13c6cb2b676f 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -70,47 +70,32 @@ static int dev_state_ev_handler(struct notifier_block *this, u8 null_ip[4] = {0}; char wlan_dev_name[5] = "wlan0"; - if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev) { - PRINT_D(GENERIC_DBG, "dev_iface = NULL\n"); + if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev) return NOTIFY_DONE; - } if (memcmp(dev_iface->ifa_label, "wlan0", 5) && - memcmp(dev_iface->ifa_label, "p2p0", 4)) { - PRINT_D(GENERIC_DBG, "Interface is neither WLAN0 nor P2P0\n"); + memcmp(dev_iface->ifa_label, "p2p0", 4)) return NOTIFY_DONE; - } dev = (struct net_device *)dev_iface->ifa_dev->dev; - if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) { - PRINT_D(GENERIC_DBG, "No Wireless registerd\n"); + if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) return NOTIFY_DONE; - } + priv = wiphy_priv(dev->ieee80211_ptr->wiphy); - if (!priv) { - PRINT_D(GENERIC_DBG, "No Wireless Priv\n"); + if (!priv) return NOTIFY_DONE; - } + hif_drv = (struct host_if_drv *)priv->hif_drv; vif = netdev_priv(dev); - if (!vif || !hif_drv) { - PRINT_D(GENERIC_DBG, "No Wireless Priv\n"); + if (!vif || !hif_drv) return NOTIFY_DONE; - } - - PRINT_INFO(GENERIC_DBG, "dev_state_ev_handler +++\n"); switch (event) { case NETDEV_UP: - PRINT_D(GENERIC_DBG, "dev_state_ev_handler event=NETDEV_UP %p\n", dev); - - PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Obtained ===============\n\n"); - if (vif->iftype == STATION_MODE || vif->iftype == CLIENT_MODE) { hif_drv->IFC_UP = 1; wilc_optaining_ip = false; del_timer(&wilc_during_ip_timer); - PRINT_D(GENERIC_DBG, "IP obtained , enable scan\n"); } if (wilc_enable_ps) @@ -127,9 +112,6 @@ static int dev_state_ev_handler(struct notifier_block *this, break; case NETDEV_DOWN: - PRINT_D(GENERIC_DBG, "dev_state_ev_handler event=NETDEV_DOWN %p\n", dev); - - PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Released ===============\n\n"); if (vif->iftype == STATION_MODE || vif->iftype == CLIENT_MODE) { hif_drv->IFC_UP = 0; wilc_optaining_ip = false; @@ -152,9 +134,6 @@ static int dev_state_ev_handler(struct notifier_block *this, break; default: - PRINT_INFO(GENERIC_DBG, "dev_state_ev_handler event=default\n"); - PRINT_INFO(GENERIC_DBG, "[%s] unknown dev event: %lu\n", dev_iface->ifa_label, event); - break; } @@ -169,7 +148,6 @@ static irqreturn_t isr_uh_routine(int irq, void *user_data) vif = netdev_priv(dev); wilc = vif->wilc; - PRINT_D(INT_DBG, "Interrupt received UH\n"); if (wilc->close) { PRINT_ER("Driver is CLOSING: Can't handle UH interrupt\n"); @@ -191,7 +169,6 @@ static irqreturn_t isr_bh_routine(int irq, void *userdata) return IRQ_HANDLED; } - PRINT_D(INT_DBG, "Interrupt received BH\n"); wilc_handle_isr(wilc); return IRQ_HANDLED; @@ -255,12 +232,9 @@ int wilc_lock_timeout(struct wilc *nic, void *vp, u32 timeout) /* FIXME: replace with mutex_lock or wait_for_completion */ int error = -1; - PRINT_D(LOCK_DBG, "Locking %p\n", vp); if (vp) error = down_timeout((struct semaphore *)vp, msecs_to_jiffies(timeout)); - else - PRINT_ER("Failed, mutex is NULL\n"); return error; } @@ -358,28 +332,21 @@ static int linux_wlan_txq_task(void *vp) up(&wl->txq_thread_started); while (1) { - PRINT_D(TX_DBG, "txq_task Taking a nap :)\n"); down(&wl->txq_event); - PRINT_D(TX_DBG, "txq_task Who waked me up :$\n"); if (wl->close) { up(&wl->txq_thread_started); while (!kthread_should_stop()) schedule(); - - PRINT_D(TX_DBG, "TX thread stopped\n"); break; } - PRINT_D(TX_DBG, "txq_task handle the sending packet and let me go to sleep.\n"); #if !defined USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS ret = wilc_wlan_handle_txq(dev, &txq_count); #else do { ret = wilc_wlan_handle_txq(dev, &txq_count); if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) { - PRINT_D(TX_DBG, "Waking up queue\n"); - if (netif_queue_stopped(wl->vif[0]->ndev)) netif_wake_queue(wl->vif[0]->ndev); if (netif_queue_stopped(wl->vif[1]->ndev)) @@ -428,15 +395,11 @@ int wilc_wlan_get_firmware(struct net_device *dev) netdev_info(dev, "loading firmware %s\n", firmware); - if (!vif) { - PRINT_ER("vif is NULL\n"); + if (!vif) goto _fail_; - } - if (!(&vif->ndev->dev)) { - PRINT_ER("&vif->ndev->dev is NULL\n"); + if (!(&vif->ndev->dev)) goto _fail_; - } if (request_firmware(&wilc_firmware, firmware, wilc->dev) != 0) { PRINT_ER("%s - firmare not available\n", firmware); @@ -459,20 +422,13 @@ static int linux_wlan_start_firmware(struct net_device *dev) vif = netdev_priv(dev); wilc = vif->wilc; - PRINT_D(INIT_DBG, "Starting Firmware ...\n"); ret = wilc_wlan_start(wilc); - if (ret < 0) { - PRINT_ER("Failed to start Firmware\n"); + if (ret < 0) return ret; - } - PRINT_D(INIT_DBG, "Waiting for Firmware to get ready ...\n"); ret = wilc_lock_timeout(wilc, &wilc->sync_event, 5000); - if (ret) { - PRINT_D(INIT_DBG, "Firmware start timed out"); + if (ret) return ret; - } - PRINT_D(INIT_DBG, "Firmware successfully started\n"); return 0; } @@ -490,14 +446,12 @@ static int wilc1000_firmware_download(struct net_device *dev) PRINT_ER("Firmware buffer is NULL\n"); return -ENOBUFS; } - PRINT_D(INIT_DBG, "Downloading Firmware ...\n"); + ret = wilc_wlan_firmware_download(wilc, wilc->firmware->data, wilc->firmware->size); if (ret < 0) return ret; - PRINT_D(INIT_DBG, "Freeing FW buffer ...\n"); - PRINT_D(INIT_DBG, "Releasing firmware\n"); release_firmware(wilc->firmware); wilc->firmware = NULL; @@ -740,7 +694,6 @@ void wilc1000_wlan_deinit(struct net_device *dev) if (wl->initialized) { netdev_info(dev, "Deinitializing wilc1000...\n"); - PRINT_D(INIT_DBG, "Disabling IRQ\n"); if (!wl->dev_irq_num && wl->hif_func->disable_interrupt) { mutex_lock(&wl->hif_cs); @@ -750,29 +703,19 @@ void wilc1000_wlan_deinit(struct net_device *dev) if (&wl->txq_event) up(&wl->txq_event); - PRINT_D(INIT_DBG, "Deinitializing Threads\n"); wlan_deinitialize_threads(dev); - - PRINT_D(INIT_DBG, "Deinitializing IRQ\n"); deinit_irq(dev); wilc_wlan_stop(wl); - - PRINT_D(INIT_DBG, "Deinitializing WILC Wlan\n"); wilc_wlan_cleanup(dev); #if defined(PLAT_ALLWINNER_A20) || defined(PLAT_ALLWINNER_A23) || defined(PLAT_ALLWINNER_A31) if (!wl->dev_irq_num && wl->hif_func->disable_interrupt) { - - PRINT_D(INIT_DBG, "Disabling IRQ 2\n"); - mutex_lock(&wl->hif_cs); wl->hif_func->disable_interrupt(wl); mutex_unlock(&wl->hif_cs); } #endif - - PRINT_D(INIT_DBG, "Deinitializing Locks\n"); wlan_deinit_locks(dev); wl->initialized = false; @@ -792,8 +735,6 @@ static int wlan_init_locks(struct net_device *dev) vif = netdev_priv(dev); wl = vif->wilc; - PRINT_D(INIT_DBG, "Initializing Locks ...\n"); - mutex_init(&wl->hif_cs); mutex_init(&wl->rxq_cs); @@ -818,8 +759,6 @@ static int wlan_deinit_locks(struct net_device *dev) vif = netdev_priv(dev); wilc = vif->wilc; - PRINT_D(INIT_DBG, "De-Initializing Locks\n"); - if (&wilc->hif_cs) mutex_destroy(&wilc->hif_cs); @@ -837,8 +776,6 @@ static int wlan_initialize_threads(struct net_device *dev) vif = netdev_priv(dev); wilc = vif->wilc; - PRINT_D(INIT_DBG, "Initializing Threads ...\n"); - PRINT_D(INIT_DBG, "Creating kthread for transmission\n"); wilc->txq_thread = kthread_run(linux_wlan_txq_task, (void *)dev, "K_TXQ_TASK"); if (!wilc->txq_thread) { @@ -860,7 +797,6 @@ static void wlan_deinitialize_threads(struct net_device *dev) wl = vif->wilc; wl->close = 1; - PRINT_D(INIT_DBG, "Deinitializing Threads\n"); if (&wl->txq_event) up(&wl->txq_event); @@ -884,20 +820,17 @@ int wilc1000_wlan_init(struct net_device *dev, struct wilc_vif *vif) ret = wilc_wlan_init(dev); if (ret < 0) { - PRINT_ER("Initializing WILC_Wlan FAILED\n"); ret = -EIO; goto _fail_locks_; } if (wl->gpio >= 0 && init_irq(dev)) { - PRINT_ER("couldn't initialize IRQ\n"); ret = -EIO; goto _fail_locks_; } ret = wlan_initialize_threads(dev); if (ret < 0) { - PRINT_ER("Initializing Threads FAILED\n"); ret = -EIO; goto _fail_wilc_wlan_; } @@ -905,27 +838,23 @@ int wilc1000_wlan_init(struct net_device *dev, struct wilc_vif *vif) if (!wl->dev_irq_num && wl->hif_func->enable_interrupt && wl->hif_func->enable_interrupt(wl)) { - PRINT_ER("couldn't initialize IRQ\n"); ret = -EIO; goto _fail_irq_init_; } if (wilc_wlan_get_firmware(dev)) { - PRINT_ER("Can't get firmware\n"); ret = -EIO; goto _fail_irq_enable_; } ret = wilc1000_firmware_download(dev); if (ret < 0) { - PRINT_ER("Failed to download firmware\n"); ret = -EIO; goto _fail_irq_enable_; } ret = linux_wlan_start_firmware(dev); if (ret < 0) { - PRINT_ER("Failed to start firmware\n"); ret = -EIO; goto _fail_irq_enable_; } @@ -1007,16 +936,11 @@ int wilc_mac_open(struct net_device *ndev) PRINT_D(INIT_DBG, "MAC OPEN[%p]\n", ndev); ret = wilc_init_host_int(ndev); - if (ret < 0) { - PRINT_ER("Failed to initialize host interface\n"); - + if (ret < 0) return ret; - } - PRINT_D(INIT_DBG, "*** re-init ***\n"); ret = wilc1000_wlan_init(ndev, vif); if (ret < 0) { - PRINT_ER("Failed to initialize wilc1000\n"); wilc_deinit_host_int(ndev); return ret; } @@ -1097,23 +1021,16 @@ static void wilc_set_multicast_list(struct net_device *dev) if (!dev) return; - PRINT_D(INIT_DBG, "Setting Multicast List with count = %d.\n", - dev->mc.count); - - if (dev->flags & IFF_PROMISC) { - PRINT_D(INIT_DBG, "Set promiscuous mode ON, retrive all packets\n"); + if (dev->flags & IFF_PROMISC) return; - } if ((dev->flags & IFF_ALLMULTI) || (dev->mc.count) > WILC_MULTICAST_TABLE_SIZE) { - PRINT_D(INIT_DBG, "Disable multicast filter, retrive all multicast packets\n"); wilc_setup_multicast_filter(vif, false, 0); return; } if ((dev->mc.count) == 0) { - PRINT_D(INIT_DBG, "Enable multicast filter, retrive directed packets only.\n"); wilc_setup_multicast_filter(vif, true, 0); return; } @@ -1160,8 +1077,6 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) vif = netdev_priv(ndev); wilc = vif->wilc; - PRINT_D(TX_DBG, "Sending packet just received from TCP/IP\n"); - if (skb->dev != ndev) { PRINT_ER("Packet not destined to this device\n"); return 0; @@ -1169,7 +1084,6 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC); if (!tx_data) { - PRINT_ER("Failed to allocate memory for tx_data structure\n"); dev_kfree_skb(skb); netif_wake_queue(ndev); return 0; @@ -1191,8 +1105,6 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) PRINT_D(GENERIC_DBG, "DHCP Message transmitted, type:%x %x %x\n", udp_buf[248], udp_buf[249], udp_buf[250]); - PRINT_D(TX_DBG, "Sending packet - Size = %d - Address = %p - SKB = %p\n", tx_data->size, tx_data->buff, tx_data->skb); - PRINT_D(TX_DBG, "Adding tx packet to TX Queue\n"); vif->netstats.tx_packets++; vif->netstats.tx_bytes += tx_data->size; tx_data->bssid = wilc->vif[vif->u8IfIdx]->bssid; @@ -1218,39 +1130,29 @@ int wilc_mac_close(struct net_device *ndev) vif = netdev_priv(ndev); if (!vif || !vif->ndev || !vif->ndev->ieee80211_ptr || - !vif->ndev->ieee80211_ptr->wiphy) { - PRINT_ER("vif = NULL\n"); + !vif->ndev->ieee80211_ptr->wiphy) return 0; - } priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy); wl = vif->wilc; - if (!priv) { - PRINT_ER("priv = NULL\n"); + if (!priv) return 0; - } hif_drv = (struct host_if_drv *)priv->hif_drv; PRINT_D(GENERIC_DBG, "Mac close\n"); - if (!wl) { - PRINT_ER("wl = NULL\n"); + if (!wl) return 0; - } - if (!hif_drv) { - PRINT_ER("hif_drv = NULL\n"); + if (!hif_drv) return 0; - } - if ((wl->open_ifcs) > 0) { + if ((wl->open_ifcs) > 0) wl->open_ifcs--; - } else { - PRINT_ER("ERROR: MAC close called while number of opened interfaces is zero\n"); + else return 0; - } if (vif->ndev) { netif_stop_queue(vif->ndev); @@ -1303,8 +1205,6 @@ static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd) if (strncasecmp(buff, "RSSI", length) == 0) { priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy); ret = wilc_get_rssi(vif, &rssi); - if (ret) - PRINT_ER("Failed to send get rssi param's message queue "); PRINT_INFO(GENERIC_DBG, "RSSI :%d\n", rssi); rssi += 5; @@ -1360,10 +1260,9 @@ void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset) buff_to_send = buff; skb = dev_alloc_skb(frame_len); - if (!skb) { - PRINT_ER("Low memory - packet droped\n"); + if (!skb) return; - } + skb->dev = wilc_netdev; memcpy(skb_put(skb, frame_len), buff_to_send, frame_len); @@ -1453,10 +1352,8 @@ int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, for (i = 0; i < NUM_CONCURRENT_IFC; i++) { ndev = alloc_etherdev(sizeof(struct wilc_vif)); - if (!ndev) { - PRINT_ER("Failed to allocate ethernet dev\n"); + if (!ndev) return -1; - } vif = netdev_priv(ndev); memset(vif, 0, sizeof(struct wilc_vif)); @@ -1495,11 +1392,8 @@ int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, vif->netstats.tx_bytes = 0; } - if (register_netdev(ndev)) { - PRINT_ER("Device couldn't be registered - %s\n", - ndev->name); + if (register_netdev(ndev)) return -1; - } vif->iftype = STATION_MODE; vif->mac_opened = 0; -- cgit v1.2.3 From 5ac2442732c32aae692e11f45f7bfcfe238e4631 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:37 +0900 Subject: staging: wilc1000: replaces PRINT_XXX with netdev_xxx This patches replaces PRINT_XXX with netdev_xxx. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 109 +++++++++++++++++----------------- 1 file changed, 54 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 13c6cb2b676f..c16cc4031cfb 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -101,12 +101,12 @@ static int dev_state_ev_handler(struct notifier_block *this, if (wilc_enable_ps) wilc_set_power_mgmt(vif, 1, 0); - PRINT_D(GENERIC_DBG, "[%s] Up IP\n", dev_iface->ifa_label); + netdev_dbg(dev, "[%s] Up IP\n", dev_iface->ifa_label); ip_addr_buf = (char *)&dev_iface->ifa_address; - PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n", - ip_addr_buf[0], ip_addr_buf[1], - ip_addr_buf[2], ip_addr_buf[3]); + netdev_dbg(dev, "IP add=%d:%d:%d:%d\n", + ip_addr_buf[0], ip_addr_buf[1], + ip_addr_buf[2], ip_addr_buf[3]); wilc_setup_ipaddress(vif, ip_addr_buf, vif->u8IfIdx); break; @@ -122,12 +122,12 @@ static int dev_state_ev_handler(struct notifier_block *this, wilc_resolve_disconnect_aberration(vif); - PRINT_D(GENERIC_DBG, "[%s] Down IP\n", dev_iface->ifa_label); + netdev_dbg(dev, "[%s] Down IP\n", dev_iface->ifa_label); ip_addr_buf = null_ip; - PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n", - ip_addr_buf[0], ip_addr_buf[1], - ip_addr_buf[2], ip_addr_buf[3]); + netdev_dbg(dev, "IP add=%d:%d:%d:%d\n", + ip_addr_buf[0], ip_addr_buf[1], + ip_addr_buf[2], ip_addr_buf[3]); wilc_setup_ipaddress(vif, ip_addr_buf, vif->u8IfIdx); @@ -150,7 +150,7 @@ static irqreturn_t isr_uh_routine(int irq, void *user_data) wilc = vif->wilc; if (wilc->close) { - PRINT_ER("Driver is CLOSING: Can't handle UH interrupt\n"); + netdev_err(dev, "Can't handle UH interrupt\n"); return IRQ_HANDLED; } return IRQ_WAKE_THREAD; @@ -160,12 +160,13 @@ static irqreturn_t isr_bh_routine(int irq, void *userdata) { struct wilc_vif *vif; struct wilc *wilc; + struct net_device *dev = (struct net_device *)userdata; vif = netdev_priv(userdata); wilc = vif->wilc; if (wilc->close) { - PRINT_ER("Driver is CLOSING: Can't handle BH interrupt\n"); + netdev_err(dev, "Can't handle BH interrupt\n"); return IRQ_HANDLED; } @@ -188,7 +189,7 @@ static int init_irq(struct net_device *dev) wl->dev_irq_num = gpio_to_irq(wl->gpio); } else { ret = -1; - PRINT_ER("could not obtain gpio for WILC_INTR\n"); + netdev_err(dev, "could not obtain gpio for WILC_INTR\n"); } if (ret != -1 && request_threaded_irq(wl->dev_irq_num, @@ -196,12 +197,13 @@ static int init_irq(struct net_device *dev) isr_bh_routine, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "WILC_IRQ", dev) < 0) { - PRINT_ER("Failed to request IRQ for GPIO: %d\n", wl->gpio); + netdev_err(dev, "Failed to request IRQ GPIO: %d\n", wl->gpio); gpio_free(wl->gpio); ret = -1; } else { - PRINT_D(INIT_DBG, "IRQ request succeeded IRQ-NUM= %d on GPIO: %d\n", - wl->dev_irq_num, wl->gpio); + netdev_dbg(dev, + "IRQ request succeeded IRQ-NUM= %d on GPIO: %d\n", + wl->dev_irq_num, wl->gpio); } return ret; @@ -402,7 +404,7 @@ int wilc_wlan_get_firmware(struct net_device *dev) goto _fail_; if (request_firmware(&wilc_firmware, firmware, wilc->dev) != 0) { - PRINT_ER("%s - firmare not available\n", firmware); + netdev_err(dev, "%s - firmare not available\n", firmware); ret = -1; goto _fail_; } @@ -443,7 +445,7 @@ static int wilc1000_firmware_download(struct net_device *dev) wilc = vif->wilc; if (!wilc->firmware) { - PRINT_ER("Firmware buffer is NULL\n"); + netdev_err(dev, "Firmware buffer is NULL\n"); return -ENOBUFS; } @@ -455,7 +457,7 @@ static int wilc1000_firmware_download(struct net_device *dev) release_firmware(wilc->firmware); wilc->firmware = NULL; - PRINT_D(INIT_DBG, "Download Succeeded\n"); + netdev_dbg(dev, "Download Succeeded\n"); return 0; } @@ -469,15 +471,13 @@ static int linux_wlan_init_test_config(struct net_device *dev, struct wilc_priv *priv; struct host_if_drv *hif_drv; - PRINT_D(TX_DBG, "Start configuring Firmware\n"); + netdev_dbg(dev, "Start configuring Firmware\n"); priv = wiphy_priv(dev->ieee80211_ptr->wiphy); hif_drv = (struct host_if_drv *)priv->hif_drv; - PRINT_D(INIT_DBG, "Host = %p\n", hif_drv); + netdev_dbg(dev, "Host = %p\n", hif_drv); wilc_get_mac_address(vif, mac_add); - PRINT_D(INIT_DBG, "MAC address is : %02x-%02x-%02x-%02x-%02x-%02x\n", - mac_add[0], mac_add[1], mac_add[2], - mac_add[3], mac_add[4], mac_add[5]); + netdev_dbg(dev, "MAC address is : %pM\n", mac_add); wilc_get_chipid(wilc, 0); *(int *)c_val = 1; @@ -720,10 +720,9 @@ void wilc1000_wlan_deinit(struct net_device *dev) wl->initialized = false; - PRINT_D(INIT_DBG, "wilc1000 deinitialization Done\n"); - + netdev_dbg(dev, "wilc1000 deinitialization Done\n"); } else { - PRINT_D(INIT_DBG, "wilc1000 is not initialized\n"); + netdev_dbg(dev, "wilc1000 is not initialized\n"); } } @@ -779,7 +778,7 @@ static int wlan_initialize_threads(struct net_device *dev) wilc->txq_thread = kthread_run(linux_wlan_txq_task, (void *)dev, "K_TXQ_TASK"); if (!wilc->txq_thread) { - PRINT_ER("couldn't create TXQ thread\n"); + netdev_err(dev, "couldn't create TXQ thread\n"); wilc->close = 0; return -ENOBUFS; } @@ -861,18 +860,18 @@ int wilc1000_wlan_init(struct net_device *dev, struct wilc_vif *vif) if (wilc_wlan_cfg_get(vif, 1, WID_FIRMWARE_VERSION, 1, 0)) { int size; - char Firmware_ver[20]; + char firmware_ver[20]; - size = wilc_wlan_cfg_get_val( - WID_FIRMWARE_VERSION, - Firmware_ver, sizeof(Firmware_ver)); - Firmware_ver[size] = '\0'; - PRINT_D(INIT_DBG, "***** Firmware Ver = %s *******\n", Firmware_ver); + size = wilc_wlan_cfg_get_val(WID_FIRMWARE_VERSION, + firmware_ver, + sizeof(firmware_ver)); + firmware_ver[size] = '\0'; + netdev_dbg(dev, "Firmware Ver = %s\n", firmware_ver); } ret = linux_wlan_init_test_config(dev, vif); if (ret < 0) { - PRINT_ER("Failed to configure firmware\n"); + netdev_err(dev, "Failed to configure firmware\n"); ret = -EIO; goto _fail_fw_start_; } @@ -896,9 +895,9 @@ _fail_wilc_wlan_: wilc_wlan_cleanup(dev); _fail_locks_: wlan_deinit_locks(dev); - PRINT_ER("WLAN Iinitialization FAILED\n"); + netdev_err(dev, "WLAN Iinitialization FAILED\n"); } else { - PRINT_D(INIT_DBG, "wilc1000 already initialized\n"); + netdev_dbg(dev, "wilc1000 already initialized\n"); } return ret; } @@ -933,7 +932,7 @@ int wilc_mac_open(struct net_device *ndev) vif = netdev_priv(ndev); wilc = vif->wilc; priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy); - PRINT_D(INIT_DBG, "MAC OPEN[%p]\n", ndev); + netdev_dbg(ndev, "MAC OPEN[%p]\n", ndev); ret = wilc_init_host_int(ndev); if (ret < 0) @@ -979,7 +978,7 @@ int wilc_mac_open(struct net_device *ndev) memcpy(ndev->dev_addr, wl->vif[i]->src_addr, ETH_ALEN); if (!is_valid_ether_addr(ndev->dev_addr)) { - PRINT_ER("Error: Wrong MAC address\n"); + netdev_err(ndev, "Wrong MAC address\n"); wilc_deinit_host_int(ndev); wilc1000_wlan_deinit(ndev); return -EINVAL; @@ -1037,13 +1036,13 @@ static void wilc_set_multicast_list(struct net_device *dev) netdev_for_each_mc_addr(ha, dev) { memcpy(wilc_multicast_mac_addr_list[i], ha->addr, ETH_ALEN); - PRINT_D(INIT_DBG, "Entry[%d]: %x:%x:%x:%x:%x:%x\n", i, - wilc_multicast_mac_addr_list[i][0], - wilc_multicast_mac_addr_list[i][1], - wilc_multicast_mac_addr_list[i][2], - wilc_multicast_mac_addr_list[i][3], - wilc_multicast_mac_addr_list[i][4], - wilc_multicast_mac_addr_list[i][5]); + netdev_dbg(dev, "Entry[%d]: %x:%x:%x:%x:%x:%x\n", i, + wilc_multicast_mac_addr_list[i][0], + wilc_multicast_mac_addr_list[i][1], + wilc_multicast_mac_addr_list[i][2], + wilc_multicast_mac_addr_list[i][3], + wilc_multicast_mac_addr_list[i][4], + wilc_multicast_mac_addr_list[i][5]); i++; } @@ -1078,7 +1077,7 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) wilc = vif->wilc; if (skb->dev != ndev) { - PRINT_ER("Packet not destined to this device\n"); + netdev_err(ndev, "Packet not destined to this device\n"); return 0; } @@ -1095,15 +1094,15 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) eth_h = (struct ethhdr *)(skb->data); if (eth_h->h_proto == 0x8e88) - PRINT_D(INIT_DBG, "EAPOL transmitted\n"); + netdev_dbg(ndev, "EAPOL transmitted\n"); ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr)); udp_buf = (char *)ih + sizeof(struct iphdr); if ((udp_buf[1] == 68 && udp_buf[3] == 67) || (udp_buf[1] == 67 && udp_buf[3] == 68)) - PRINT_D(GENERIC_DBG, "DHCP Message transmitted, type:%x %x %x\n", - udp_buf[248], udp_buf[249], udp_buf[250]); + netdev_dbg(ndev, "DHCP Message transmitted, type:%x %x %x\n", + udp_buf[248], udp_buf[249], udp_buf[250]); vif->netstats.tx_packets++; vif->netstats.tx_bytes += tx_data->size; @@ -1141,7 +1140,7 @@ int wilc_mac_close(struct net_device *ndev) hif_drv = (struct host_if_drv *)priv->hif_drv; - PRINT_D(GENERIC_DBG, "Mac close\n"); + netdev_dbg(ndev, "Mac close\n"); if (!wl) return 0; @@ -1161,7 +1160,7 @@ int wilc_mac_close(struct net_device *ndev) } if (wl->open_ifcs == 0) { - PRINT_D(GENERIC_DBG, "Deinitializing wilc1000\n"); + netdev_dbg(ndev, "Deinitializing wilc1000\n"); wl->close = 1; wilc1000_wlan_deinit(ndev); WILC_WFI_deinit_mon_interface(); @@ -1205,14 +1204,14 @@ static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd) if (strncasecmp(buff, "RSSI", length) == 0) { priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy); ret = wilc_get_rssi(vif, &rssi); - PRINT_INFO(GENERIC_DBG, "RSSI :%d\n", rssi); + netdev_info(ndev, "RSSI :%d\n", rssi); rssi += 5; snprintf(buff, size, "rssi %d", rssi); if (copy_to_user(wrq->u.data.pointer, buff, size)) { - PRINT_ER("%s: failed to copy data to user buffer\n", __func__); + netdev_err(ndev, "failed to copy\n"); ret = -EFAULT; goto done; } @@ -1223,7 +1222,7 @@ static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd) default: { - PRINT_INFO(GENERIC_DBG, "Command - %d - has been received\n", cmd); + netdev_info(ndev, "Command - %d - has been received\n", cmd); ret = -EOPNOTSUPP; goto done; } @@ -1272,7 +1271,7 @@ void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset) vif->netstats.rx_bytes += frame_len; skb->ip_summed = CHECKSUM_UNNECESSARY; stats = netif_rx(skb); - PRINT_D(RX_DBG, "netif_rx ret value is: %d\n", stats); + netdev_dbg(wilc_netdev, "netif_rx ret value is: %d\n", stats); } } @@ -1379,7 +1378,7 @@ int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, SET_NETDEV_DEV(ndev, dev); if (!wdev) { - PRINT_ER("Can't register WILC Wiphy\n"); + netdev_err(ndev, "Can't register WILC Wiphy\n"); return -1; } -- cgit v1.2.3 From b6ba7e899f90597072afef9960b58697b7841257 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:38 +0900 Subject: staging: wilc1000: removes void function return This patch removes the warning reported by checkpatch.pl for void function return statements are not generally useful. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index c16cc4031cfb..5c87105c034a 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1047,8 +1047,6 @@ static void wilc_set_multicast_list(struct net_device *dev) } wilc_setup_multicast_filter(vif, true, (dev->mc.count)); - - return; } static void linux_wlan_tx_complete(void *priv, int status) -- cgit v1.2.3 From 6750140dfc6a6331e4cf98f1fa3cc440cac42fc0 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:39 +0900 Subject: staging: wilc1000: renames u8IfIdx of wilc_vif structure This patch renames u8IfIdx variable of wilc_vif structure to idx to avoid camelcase. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/linux_wlan.c | 8 ++++---- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 +- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 6f583a4224a6..2022deb113c0 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -281,7 +281,7 @@ static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); */ int wilc_get_vif_idx(struct wilc_vif *vif) { - return vif->u8IfIdx + 1; + return vif->idx + 1; } /* We need to minus 1 from idx which is from wilc device to get real index diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 5c87105c034a..9ca335367b86 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -107,7 +107,7 @@ static int dev_state_ev_handler(struct notifier_block *this, netdev_dbg(dev, "IP add=%d:%d:%d:%d\n", ip_addr_buf[0], ip_addr_buf[1], ip_addr_buf[2], ip_addr_buf[3]); - wilc_setup_ipaddress(vif, ip_addr_buf, vif->u8IfIdx); + wilc_setup_ipaddress(vif, ip_addr_buf, vif->idx); break; @@ -129,7 +129,7 @@ static int dev_state_ev_handler(struct notifier_block *this, ip_addr_buf[0], ip_addr_buf[1], ip_addr_buf[2], ip_addr_buf[3]); - wilc_setup_ipaddress(vif, ip_addr_buf, vif->u8IfIdx); + wilc_setup_ipaddress(vif, ip_addr_buf, vif->idx); break; @@ -1104,7 +1104,7 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) vif->netstats.tx_packets++; vif->netstats.tx_bytes += tx_data->size; - tx_data->bssid = wilc->vif[vif->u8IfIdx]->bssid; + tx_data->bssid = wilc->vif[vif->idx]->bssid; queue_count = wilc_wlan_txq_add_net_pkt(ndev, (void *)tx_data, tx_data->buff, tx_data->size, linux_wlan_tx_complete); @@ -1360,7 +1360,7 @@ int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, else strcpy(ndev->name, "p2p%d"); - vif->u8IfIdx = wl->vif_num; + vif->idx = wl->vif_num; vif->wilc = *wilc; wl->vif[i] = vif; wl->vif[wl->vif_num]->ndev = ndev; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index b8fd6956d4c5..cc50225ca844 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2197,7 +2197,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, if (s32Error != 0) PRINT_ER("Error in setting channel\n"); - wilc_wlan_set_bssid(dev, wl->vif[vif->u8IfIdx]->src_addr, AP_MODE); + wilc_wlan_set_bssid(dev, wl->vif[vif->idx]->src_addr, AP_MODE); wilc_set_power_mgmt(vif, 0, 0); s32Error = wilc_add_beacon(vif, settings->beacon_interval, diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 64fcb777cc2d..07a4ff10bb65 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -148,7 +148,7 @@ typedef struct { } struct_frame_reg; struct wilc_vif { - u8 u8IfIdx; + u8 idx; u8 iftype; int monitor_flag; int mac_opened; -- cgit v1.2.3 From bc4b5b3cf7506fbd21dc42d46c53288fcda6632f Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:40 +0900 Subject: staging: wilc1000: fixes variable dereferenced before check This patch fixes the warning reported by smatch. - wilc_wlan_get_firmware() warn: variable dereferenced before check 'vif' - wilc_set_multicast_list() warn: variable dereferenced before check 'dev' Just delete them and no need add null check since they are net_device from ndo_set_rx_mode of net_device_ops and vif of netdev_priv. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 9ca335367b86..22a2f98cc2fe 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -397,9 +397,6 @@ int wilc_wlan_get_firmware(struct net_device *dev) netdev_info(dev, "loading firmware %s\n", firmware); - if (!vif) - goto _fail_; - if (!(&vif->ndev->dev)) goto _fail_; @@ -1017,9 +1014,6 @@ static void wilc_set_multicast_list(struct net_device *dev) vif = netdev_priv(dev); hif_drv = (struct host_if_drv *)priv->hif_drv; - if (!dev) - return; - if (dev->flags & IFF_PROMISC) return; -- cgit v1.2.3 From cdd610644be7b096c5bece4b7a1be07da5fe491c Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:41 +0900 Subject: staging: wilc1000: wilc_parse_network_info(): renames function variables This patch renames to avoid camelcase, changes follow are: - pu8MsgBuffer to msg_buffer - ppstrNetworkInfo to ret_network_info Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 16 ++++++++-------- drivers/staging/wilc1000/coreconfigurator.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 6f17e2b66673..43f0a295fe55 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -270,7 +270,7 @@ static u8 get_current_channel_802_11n(u8 *pu8msa, u16 rx_len) return 0; } -s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo) +s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) { tstrNetworkInfo *pstrNetworkInfo = NULL; u8 u8MsgType = 0; @@ -281,18 +281,18 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo u16 u16WidLen = 0; u8 *pu8WidVal = NULL; - u8MsgType = pu8MsgBuffer[0]; + u8MsgType = msg_buffer[0]; if ('N' != u8MsgType) { PRINT_ER("Received Message format incorrect.\n"); return -EFAULT; } - u8MsgID = pu8MsgBuffer[1]; - u16MsgLen = MAKE_WORD16(pu8MsgBuffer[2], pu8MsgBuffer[3]); - u16WidID = MAKE_WORD16(pu8MsgBuffer[4], pu8MsgBuffer[5]); - u16WidLen = MAKE_WORD16(pu8MsgBuffer[6], pu8MsgBuffer[7]); - pu8WidVal = &pu8MsgBuffer[8]; + u8MsgID = msg_buffer[1]; + u16MsgLen = MAKE_WORD16(msg_buffer[2], msg_buffer[3]); + u16WidID = MAKE_WORD16(msg_buffer[4], msg_buffer[5]); + u16WidLen = MAKE_WORD16(msg_buffer[6], msg_buffer[7]); + pu8WidVal = &msg_buffer[8]; { u8 *pu8msa = NULL; @@ -350,7 +350,7 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo } - *ppstrNetworkInfo = pstrNetworkInfo; + *ret_network_info = pstrNetworkInfo; return 0; } diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index ee107ac915e0..aec0779596be 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -120,7 +120,7 @@ typedef struct { size_t ie_len; } tstrDisconnectNotifInfo; -s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo); +s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info); s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo); s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, -- cgit v1.2.3 From 5fd5e1e15c5e1ad04e891e15cd32d0ca3f212970 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:42 +0900 Subject: staging: wilc1000: wilc_parse_network_info(): renames local variables This patch renames to avoid camelcase, changes follow are: - pstrNetworkInfo to network_info - u8MsgType to msg_type - u8MsgID to msg_id - u16MsgLen to msg_len - u16WidID to wid_id - u16WidLen to wid_len - pu8WidVal to wid_val Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 67 ++++++++++++++--------------- 1 file changed, 33 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 43f0a295fe55..24afeb894b13 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -272,27 +272,27 @@ static u8 get_current_channel_802_11n(u8 *pu8msa, u16 rx_len) s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) { - tstrNetworkInfo *pstrNetworkInfo = NULL; - u8 u8MsgType = 0; - u8 u8MsgID = 0; - u16 u16MsgLen = 0; + tstrNetworkInfo *network_info = NULL; + u8 msg_type = 0; + u8 msg_id = 0; + u16 msg_len = 0; - u16 u16WidID = (u16)WID_NIL; - u16 u16WidLen = 0; - u8 *pu8WidVal = NULL; + u16 wid_id = (u16)WID_NIL; + u16 wid_len = 0; + u8 *wid_val = NULL; - u8MsgType = msg_buffer[0]; + msg_type = msg_buffer[0]; - if ('N' != u8MsgType) { + if ('N' != msg_type) { PRINT_ER("Received Message format incorrect.\n"); return -EFAULT; } - u8MsgID = msg_buffer[1]; - u16MsgLen = MAKE_WORD16(msg_buffer[2], msg_buffer[3]); - u16WidID = MAKE_WORD16(msg_buffer[4], msg_buffer[5]); - u16WidLen = MAKE_WORD16(msg_buffer[6], msg_buffer[7]); - pu8WidVal = &msg_buffer[8]; + msg_id = msg_buffer[1]; + msg_len = MAKE_WORD16(msg_buffer[2], msg_buffer[3]); + wid_id = MAKE_WORD16(msg_buffer[4], msg_buffer[5]); + wid_len = MAKE_WORD16(msg_buffer[6], msg_buffer[7]); + wid_val = &msg_buffer[8]; { u8 *pu8msa = NULL; @@ -304,53 +304,52 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) u32 u32Tsf_Lo; u32 u32Tsf_Hi; - pstrNetworkInfo = kzalloc(sizeof(tstrNetworkInfo), GFP_KERNEL); - if (!pstrNetworkInfo) + network_info = kzalloc(sizeof(tstrNetworkInfo), GFP_KERNEL); + if (!network_info) return -ENOMEM; - pstrNetworkInfo->s8rssi = pu8WidVal[0]; + network_info->s8rssi = wid_val[0]; - pu8msa = &pu8WidVal[1]; + pu8msa = &wid_val[1]; - rx_len = u16WidLen - 1; - pstrNetworkInfo->u16CapInfo = get_cap_info(pu8msa); - pstrNetworkInfo->u32Tsf = get_beacon_timestamp_lo(pu8msa); - PRINT_D(CORECONFIG_DBG, "TSF :%x\n", pstrNetworkInfo->u32Tsf); + rx_len = wid_len - 1; + network_info->u16CapInfo = get_cap_info(pu8msa); + network_info->u32Tsf = get_beacon_timestamp_lo(pu8msa); + PRINT_D(CORECONFIG_DBG, "TSF :%x\n", network_info->u32Tsf); u32Tsf_Lo = get_beacon_timestamp_lo(pu8msa); u32Tsf_Hi = get_beacon_timestamp_hi(pu8msa); - pstrNetworkInfo->u64Tsf = u32Tsf_Lo | ((u64)u32Tsf_Hi << 32); + network_info->u64Tsf = u32Tsf_Lo | ((u64)u32Tsf_Hi << 32); - get_ssid(pu8msa, pstrNetworkInfo->au8ssid, &pstrNetworkInfo->u8SsidLen); - get_BSSID(pu8msa, pstrNetworkInfo->au8bssid); + get_ssid(pu8msa, network_info->au8ssid, &network_info->u8SsidLen); + get_BSSID(pu8msa, network_info->au8bssid); - pstrNetworkInfo->u8channel = get_current_channel_802_11n(pu8msa, + network_info->u8channel = get_current_channel_802_11n(pu8msa, rx_len + FCS_LEN); u8index = MAC_HDR_LEN + TIME_STAMP_LEN; - pstrNetworkInfo->u16BeaconPeriod = get_beacon_period(pu8msa + u8index); + network_info->u16BeaconPeriod = get_beacon_period(pu8msa + u8index); u8index += BEACON_INTERVAL_LEN + CAP_INFO_LEN; pu8TimElm = get_tim_elm(pu8msa, rx_len + FCS_LEN, u8index); if (pu8TimElm) - pstrNetworkInfo->u8DtimPeriod = pu8TimElm[3]; + network_info->u8DtimPeriod = pu8TimElm[3]; pu8IEs = &pu8msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN]; u16IEsLen = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); if (u16IEsLen > 0) { - pstrNetworkInfo->pu8IEs = kmemdup(pu8IEs, u16IEsLen, - GFP_KERNEL); - if (!pstrNetworkInfo->pu8IEs) + network_info->pu8IEs = kmemdup(pu8IEs, u16IEsLen, + GFP_KERNEL); + if (!network_info->pu8IEs) return -ENOMEM; } - pstrNetworkInfo->u16IEsLen = u16IEsLen; - + network_info->u16IEsLen = u16IEsLen; } - *ret_network_info = pstrNetworkInfo; + *ret_network_info = network_info; return 0; } -- cgit v1.2.3 From e509681d195e6ebd6a16407ab3898e151194ee30 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:43 +0900 Subject: staging: wilc1000: wilc_parse_network_info(): renames local inner variables This patch renames to avoid camelcase, changes follow are: - pu8TimElm to tim_elm - pu8IEs to ies - u16IEsLen to ies_len - u32Tsf_Lo to tsf_lo - u32Tsf_Hi to tsf_hi And, remove the prefix variable defined name, below are: - u8index to index - pu8msa to msa Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 54 ++++++++++++++--------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 24afeb894b13..2a4e324397fb 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -295,14 +295,14 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) wid_val = &msg_buffer[8]; { - u8 *pu8msa = NULL; + u8 *msa = NULL; u16 rx_len = 0; - u8 *pu8TimElm = NULL; - u8 *pu8IEs = NULL; - u16 u16IEsLen = 0; - u8 u8index = 0; - u32 u32Tsf_Lo; - u32 u32Tsf_Hi; + u8 *tim_elm = NULL; + u8 *ies = NULL; + u16 ies_len = 0; + u8 index = 0; + u32 tsf_lo; + u32 tsf_hi; network_info = kzalloc(sizeof(tstrNetworkInfo), GFP_KERNEL); if (!network_info) @@ -310,43 +310,43 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) network_info->s8rssi = wid_val[0]; - pu8msa = &wid_val[1]; + msa = &wid_val[1]; rx_len = wid_len - 1; - network_info->u16CapInfo = get_cap_info(pu8msa); - network_info->u32Tsf = get_beacon_timestamp_lo(pu8msa); + network_info->u16CapInfo = get_cap_info(msa); + network_info->u32Tsf = get_beacon_timestamp_lo(msa); PRINT_D(CORECONFIG_DBG, "TSF :%x\n", network_info->u32Tsf); - u32Tsf_Lo = get_beacon_timestamp_lo(pu8msa); - u32Tsf_Hi = get_beacon_timestamp_hi(pu8msa); + tsf_lo = get_beacon_timestamp_lo(msa); + tsf_hi = get_beacon_timestamp_hi(msa); - network_info->u64Tsf = u32Tsf_Lo | ((u64)u32Tsf_Hi << 32); + network_info->u64Tsf = tsf_lo | ((u64)tsf_hi << 32); - get_ssid(pu8msa, network_info->au8ssid, &network_info->u8SsidLen); - get_BSSID(pu8msa, network_info->au8bssid); + get_ssid(msa, network_info->au8ssid, &network_info->u8SsidLen); + get_BSSID(msa, network_info->au8bssid); - network_info->u8channel = get_current_channel_802_11n(pu8msa, + network_info->u8channel = get_current_channel_802_11n(msa, rx_len + FCS_LEN); - u8index = MAC_HDR_LEN + TIME_STAMP_LEN; + index = MAC_HDR_LEN + TIME_STAMP_LEN; - network_info->u16BeaconPeriod = get_beacon_period(pu8msa + u8index); + network_info->u16BeaconPeriod = get_beacon_period(msa + index); - u8index += BEACON_INTERVAL_LEN + CAP_INFO_LEN; + index += BEACON_INTERVAL_LEN + CAP_INFO_LEN; - pu8TimElm = get_tim_elm(pu8msa, rx_len + FCS_LEN, u8index); - if (pu8TimElm) - network_info->u8DtimPeriod = pu8TimElm[3]; - pu8IEs = &pu8msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN]; - u16IEsLen = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); + tim_elm = get_tim_elm(msa, rx_len + FCS_LEN, index); + if (tim_elm) + network_info->u8DtimPeriod = tim_elm[3]; + ies = &msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN]; + ies_len = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); - if (u16IEsLen > 0) { - network_info->pu8IEs = kmemdup(pu8IEs, u16IEsLen, + if (ies_len > 0) { + network_info->pu8IEs = kmemdup(ies, ies_len, GFP_KERNEL); if (!network_info->pu8IEs) return -ENOMEM; } - network_info->u16IEsLen = u16IEsLen; + network_info->u16IEsLen = ies_len; } *ret_network_info = network_info; -- cgit v1.2.3 From 66d77cb5bbfc3b99ea5c4ac1978b577c322cbbae Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:44 +0900 Subject: staging: wilc1000: rename variable s32Error This patch renames variable s32Error to result to avoid CamelCase naming convention. Also, remove the unused variable s32Error and replace with direct return. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 2a4e324397fb..88e5661d31ba 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -356,30 +356,29 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo) { - s32 s32Error = 0; + s32 result = 0; if (pstrNetworkInfo) { if (pstrNetworkInfo->pu8IEs) { kfree(pstrNetworkInfo->pu8IEs); pstrNetworkInfo->pu8IEs = NULL; } else { - s32Error = -EFAULT; + result = -EFAULT; } kfree(pstrNetworkInfo); pstrNetworkInfo = NULL; } else { - s32Error = -EFAULT; + result = -EFAULT; } - return s32Error; + return result; } s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, tstrConnectRespInfo **ppstrConnectRespInfo) { - s32 s32Error = 0; tstrConnectRespInfo *pstrConnectRespInfo = NULL; u16 u16AssocRespLen = 0; u8 *pu8IEs = NULL; @@ -408,27 +407,27 @@ s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, *ppstrConnectRespInfo = pstrConnectRespInfo; - return s32Error; + return 0; } s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *pstrConnectRespInfo) { - s32 s32Error = 0; + s32 result = 0; if (pstrConnectRespInfo) { if (pstrConnectRespInfo->pu8RespIEs) { kfree(pstrConnectRespInfo->pu8RespIEs); pstrConnectRespInfo->pu8RespIEs = NULL; } else { - s32Error = -EFAULT; + result = -EFAULT; } kfree(pstrConnectRespInfo); pstrConnectRespInfo = NULL; } else { - s32Error = -EFAULT; + result = -EFAULT; } - return s32Error; + return result; } -- cgit v1.2.3 From 946a9ddb43706c6f55600c4b2725a7b19f0777d8 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:45 +0900 Subject: staging: wilc1000: wilc_parse_assoc_resp_info(): renames function variables This patch renames to avoid camelcase, changes follow are: - pu8Buffer to buffer - u32BufferLen to buffer_len - ppstrConnectRespInfo to ret_connect_resp_info Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 16 ++++++++-------- drivers/staging/wilc1000/coreconfigurator.h | 5 ++--- 2 files changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 88e5661d31ba..48c8573535de 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -376,8 +376,8 @@ s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo) return result; } -s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, - tstrConnectRespInfo **ppstrConnectRespInfo) +s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, + tstrConnectRespInfo **ret_connect_resp_info) { tstrConnectRespInfo *pstrConnectRespInfo = NULL; u16 u16AssocRespLen = 0; @@ -388,14 +388,14 @@ s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, if (!pstrConnectRespInfo) return -ENOMEM; - u16AssocRespLen = (u16)u32BufferLen; + u16AssocRespLen = (u16)buffer_len; - pstrConnectRespInfo->u16ConnectStatus = get_asoc_status(pu8Buffer); + pstrConnectRespInfo->u16ConnectStatus = get_asoc_status(buffer); if (pstrConnectRespInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE) { - pstrConnectRespInfo->u16capability = get_assoc_resp_cap_info(pu8Buffer); - pstrConnectRespInfo->u16AssocID = get_asoc_id(pu8Buffer); + pstrConnectRespInfo->u16capability = get_assoc_resp_cap_info(buffer); + pstrConnectRespInfo->u16AssocID = get_asoc_id(buffer); - pu8IEs = &pu8Buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN]; + pu8IEs = &buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN]; u16IEsLen = u16AssocRespLen - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN); pstrConnectRespInfo->pu8RespIEs = kmemdup(pu8IEs, u16IEsLen, GFP_KERNEL); @@ -405,7 +405,7 @@ s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, pstrConnectRespInfo->u16RespIEsLen = u16IEsLen; } - *ppstrConnectRespInfo = pstrConnectRespInfo; + *ret_connect_resp_info = pstrConnectRespInfo; return 0; } diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index aec0779596be..6a2c323413ad 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -122,9 +122,8 @@ typedef struct { s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info); s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo); - -s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, - tstrConnectRespInfo **ppstrConnectRespInfo); +s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, + tstrConnectRespInfo **ret_connect_resp_info); s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *pstrConnectRespInfo); void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, u32 u32Length); -- cgit v1.2.3 From ebd7a9b037ec8383cf6e9941bc2efb4520232042 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:46 +0900 Subject: staging: wilc1000: wilc_parse_assoc_resp_info(): renames local variables This patch renames to avoid camelcase, changes follow are: - pstrConnectRespInfo to connect_resp_info - u16AssocRespLen to assoc_resp_len - pu8IEs to ies - u16IEsLen to ies_len Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 34 ++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 48c8573535de..c0be33d0564e 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -379,33 +379,33 @@ s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo) s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, tstrConnectRespInfo **ret_connect_resp_info) { - tstrConnectRespInfo *pstrConnectRespInfo = NULL; - u16 u16AssocRespLen = 0; - u8 *pu8IEs = NULL; - u16 u16IEsLen = 0; + tstrConnectRespInfo *connect_resp_info = NULL; + u16 assoc_resp_len = 0; + u8 *ies = NULL; + u16 ies_len = 0; - pstrConnectRespInfo = kzalloc(sizeof(tstrConnectRespInfo), GFP_KERNEL); - if (!pstrConnectRespInfo) + connect_resp_info = kzalloc(sizeof(tstrConnectRespInfo), GFP_KERNEL); + if (!connect_resp_info) return -ENOMEM; - u16AssocRespLen = (u16)buffer_len; + assoc_resp_len = (u16)buffer_len; - pstrConnectRespInfo->u16ConnectStatus = get_asoc_status(buffer); - if (pstrConnectRespInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE) { - pstrConnectRespInfo->u16capability = get_assoc_resp_cap_info(buffer); - pstrConnectRespInfo->u16AssocID = get_asoc_id(buffer); + connect_resp_info->u16ConnectStatus = get_asoc_status(buffer); + if (connect_resp_info->u16ConnectStatus == SUCCESSFUL_STATUSCODE) { + connect_resp_info->u16capability = get_assoc_resp_cap_info(buffer); + connect_resp_info->u16AssocID = get_asoc_id(buffer); - pu8IEs = &buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN]; - u16IEsLen = u16AssocRespLen - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN); + ies = &buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN]; + ies_len = assoc_resp_len - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN); - pstrConnectRespInfo->pu8RespIEs = kmemdup(pu8IEs, u16IEsLen, GFP_KERNEL); - if (!pstrConnectRespInfo->pu8RespIEs) + connect_resp_info->pu8RespIEs = kmemdup(ies, ies_len, GFP_KERNEL); + if (!connect_resp_info->pu8RespIEs) return -ENOMEM; - pstrConnectRespInfo->u16RespIEsLen = u16IEsLen; + connect_resp_info->u16RespIEsLen = ies_len; } - *ret_connect_resp_info = pstrConnectRespInfo; + *ret_connect_resp_info = connect_resp_info; return 0; } -- cgit v1.2.3 From 9f4970edc5487018ceaf28ab32bd428ff9a9d1ee Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:47 +0900 Subject: staging: wilc1000: wilc_dealloc_assoc_resp_info(): renames function variables This patch renames to avoid camelcase, changes follow are: - pstrConnectRespInfo to connect_resp_info Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 14 +++++++------- drivers/staging/wilc1000/coreconfigurator.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index c0be33d0564e..c78da2c746ac 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -410,20 +410,20 @@ s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, return 0; } -s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *pstrConnectRespInfo) +s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *connect_resp_info) { s32 result = 0; - if (pstrConnectRespInfo) { - if (pstrConnectRespInfo->pu8RespIEs) { - kfree(pstrConnectRespInfo->pu8RespIEs); - pstrConnectRespInfo->pu8RespIEs = NULL; + if (connect_resp_info) { + if (connect_resp_info->pu8RespIEs) { + kfree(connect_resp_info->pu8RespIEs); + connect_resp_info->pu8RespIEs = NULL; } else { result = -EFAULT; } - kfree(pstrConnectRespInfo); - pstrConnectRespInfo = NULL; + kfree(connect_resp_info); + connect_resp_info = NULL; } else { result = -EFAULT; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 6a2c323413ad..ec810b57de98 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -124,7 +124,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info); s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo); s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, tstrConnectRespInfo **ret_connect_resp_info); -s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *pstrConnectRespInfo); +s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *connect_resp_info); void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, u32 u32Length); void wilc_network_info_received(struct wilc *wilc, u8 *pu8Buffer, -- cgit v1.2.3 From c1725aab7cd874e03214504568beb44cffb1e092 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:48 +0900 Subject: staging: wilc1000: wilc_dealloc_network_info(): renames function variables This patch renames to avoid camelcase, changes follow are: - pstrNetworkInfo to network_info Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 14 +++++++------- drivers/staging/wilc1000/coreconfigurator.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index c78da2c746ac..a0b80bf8e009 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -354,20 +354,20 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) return 0; } -s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo) +s32 wilc_dealloc_network_info(tstrNetworkInfo *network_info) { s32 result = 0; - if (pstrNetworkInfo) { - if (pstrNetworkInfo->pu8IEs) { - kfree(pstrNetworkInfo->pu8IEs); - pstrNetworkInfo->pu8IEs = NULL; + if (network_info) { + if (network_info->pu8IEs) { + kfree(network_info->pu8IEs); + network_info->pu8IEs = NULL; } else { result = -EFAULT; } - kfree(pstrNetworkInfo); - pstrNetworkInfo = NULL; + kfree(network_info); + network_info = NULL; } else { result = -EFAULT; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index ec810b57de98..d801e58be8e6 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -121,7 +121,7 @@ typedef struct { } tstrDisconnectNotifInfo; s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info); -s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo); +s32 wilc_dealloc_network_info(tstrNetworkInfo *network_info); s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, tstrConnectRespInfo **ret_connect_resp_info); s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *connect_resp_info); -- cgit v1.2.3 From 4d38a56b3c5e1cefc863757a839483de40e10f35 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:15:49 +0900 Subject: staging: wilc1000: fix warnings for line over 80 characters This patch fixes warnings reported by checkpatch.pl for line over 80 characters Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 33 ++++++++++++++++++++------------- drivers/staging/wilc1000/wilc_wlan.h | 3 ++- 2 files changed, 22 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index ebf38a578694..a6f4e15adef9 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -113,7 +113,8 @@ static void wilc_wlan_txq_add_to_tail(struct net_device *dev, up(&wilc->txq_event); } -static int wilc_wlan_txq_add_to_head(struct wilc_vif *vif, struct txq_entry_t *tqe) +static int wilc_wlan_txq_add_to_head(struct wilc_vif *vif, + struct txq_entry_t *tqe) { unsigned long flags; struct wilc *wilc = vif->wilc; @@ -695,8 +696,9 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) acquire_bus(wilc, ACQUIRE_AND_WAKEUP); counter = 0; do { - ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, - ®); + ret = wilc->hif_func->hif_read_reg(wilc, + WILC_HOST_TX_CTRL, + ®); if (!ret) { wilc_debug(N_ERR, "[wilc txq]: fail can't read reg vmm_tbl_entry..\n"); break; @@ -728,8 +730,9 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) break; } - ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, - 0x2); + ret = wilc->hif_func->hif_write_reg(wilc, + WILC_HOST_VMM_CTL, + 0x2); if (!ret) { wilc_debug(N_ERR, "[wilc txq]: fail can't write reg host_vmm_ctl..\n"); break; @@ -1063,7 +1066,8 @@ void wilc_handle_isr(struct wilc *wilc) } EXPORT_SYMBOL_GPL(wilc_handle_isr); -int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u32 buffer_size) +int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, + u32 buffer_size) { u32 offset; u32 addr, size, size2, blksz; @@ -1096,8 +1100,8 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u32 buffer_ size2 = blksz; memcpy(dma_buffer, &buffer[offset], size2); - ret = wilc->hif_func->hif_block_tx(wilc, addr, dma_buffer, - size2); + ret = wilc->hif_func->hif_block_tx(wilc, addr, + dma_buffer, size2); if (!ret) break; @@ -1233,7 +1237,8 @@ int wilc_wlan_stop(struct wilc *wilc) } do { - ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); + ret = wilc->hif_func->hif_read_reg(wilc, + WILC_GLB_RESET_0, ®); if (!ret) { PRINT_ER("Error while reading reg\n"); release_bus(wilc, RELEASE_ALLOW_SLEEP); @@ -1246,14 +1251,16 @@ int wilc_wlan_stop(struct wilc *wilc) PRINT_D(GENERIC_DBG, "Bit 10 not reset : Retry %d\n", timeout); reg &= ~BIT(10); - ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, - reg); + ret = wilc->hif_func->hif_write_reg(wilc, + WILC_GLB_RESET_0, + reg); timeout--; } else { PRINT_D(GENERIC_DBG, "Bit 10 reset after : Retry %d\n", timeout); - ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, - ®); + ret = wilc->hif_func->hif_read_reg(wilc, + WILC_GLB_RESET_0, + ®); if (!ret) { PRINT_ER("Error while reading reg\n"); release_bus(wilc, RELEASE_ALLOW_SLEEP); diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index e913ae7abef7..d362fa8512cf 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -270,7 +270,8 @@ struct wilc_cfg_rsp { struct wilc; struct wilc_vif; -int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u32 buffer_size); +int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, + u32 buffer_size); int wilc_wlan_start(struct wilc *); int wilc_wlan_stop(struct wilc *); int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, -- cgit v1.2.3 From 133b22d694c7a4753145eb41029d9dec9db84590 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:15:50 +0900 Subject: staging: wilc1000: remove useless log message This patch remove useless log message in wilc_wlan.c file Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 128 ++++++----------------------------- 1 file changed, 22 insertions(+), 106 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index a6f4e15adef9..400d311d587b 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -104,12 +104,9 @@ static void wilc_wlan_txq_add_to_tail(struct net_device *dev, wilc->txq_tail = tqe; } wilc->txq_entries += 1; - PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", wilc->txq_entries); spin_unlock_irqrestore(&wilc->txq_spinlock, flags); - PRINT_D(TX_DBG, "Wake the txq_handling\n"); - up(&wilc->txq_event); } @@ -137,12 +134,10 @@ static int wilc_wlan_txq_add_to_head(struct wilc_vif *vif, wilc->txq_head = tqe; } wilc->txq_entries += 1; - netdev_dbg(vif->ndev, "Number of entries in TxQ = %d\n", wilc->txq_entries); spin_unlock_irqrestore(&wilc->txq_spinlock, flags); up(&wilc->txq_add_to_head_cs); up(&wilc->txq_event); - netdev_dbg(vif->ndev, "Wake up the txq_handler\n"); return 0; } @@ -188,7 +183,6 @@ static inline int add_tcp_session(u32 src_prt, u32 dst_prt, u32 seq) ack_session_info[tcp_session].dst_port = dst_prt; tcp_session++; } - PRINT_D(TCP_ENH, "TCP Session %d to Ack %d\n", tcp_session, seq); return 0; } @@ -310,8 +304,6 @@ static int wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev) if (pending_acks_info[i].ack_num < ack_session_info[pending_acks_info[i].session_index].bigger_ack_num) { struct txq_entry_t *tqe; - PRINT_D(TCP_ENH, "DROP ACK: %u\n", - pending_acks_info[i].ack_num); tqe = pending_acks_info[i].txqe; if (tqe) { wilc_wlan_txq_remove(wilc, tqe); @@ -379,7 +371,6 @@ static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer, tqe->tx_complete_func = NULL; tqe->priv = NULL; tqe->tcp_pending_ack_idx = NOT_TCP_ACK; - netdev_dbg(vif->ndev, "Adding the config packet at the Queue tail\n"); if (wilc_wlan_txq_add_to_head(vif, tqe)) return 0; @@ -408,7 +399,6 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, tqe->tx_complete_func = func; tqe->priv = priv; - PRINT_D(TX_DBG, "Adding mgmt packet at the Queue tail\n"); tqe->tcp_pending_ack_idx = NOT_TCP_ACK; if (is_tcp_ack_filter_enabled()) tcp_process(dev, tqe); @@ -438,7 +428,6 @@ int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, tqe->tx_complete_func = func; tqe->priv = priv; tqe->tcp_pending_ack_idx = NOT_TCP_ACK; - PRINT_D(TX_DBG, "Adding Network packet at the Queue tail\n"); wilc_wlan_txq_add_to_tail(dev, tqe); return 1; } @@ -478,18 +467,15 @@ static int wilc_wlan_rxq_add(struct wilc *wilc, struct rxq_entry_t *rqe) mutex_lock(&wilc->rxq_cs); if (!wilc->rxq_head) { - PRINT_D(RX_DBG, "Add to Queue head\n"); rqe->next = NULL; wilc->rxq_head = rqe; wilc->rxq_tail = rqe; } else { - PRINT_D(RX_DBG, "Add to Queue tail\n"); wilc->rxq_tail->next = rqe; rqe->next = NULL; wilc->rxq_tail = rqe; } wilc->rxq_entries += 1; - PRINT_D(RX_DBG, "Number of queue entries: %d\n", wilc->rxq_entries); mutex_unlock(&wilc->rxq_cs); return wilc->rxq_entries; } @@ -497,7 +483,6 @@ static int wilc_wlan_rxq_add(struct wilc *wilc, struct rxq_entry_t *rqe) static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc) { - PRINT_D(RX_DBG, "Getting rxQ element\n"); if (wilc->rxq_head) { struct rxq_entry_t *rqe; @@ -505,11 +490,9 @@ static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc) rqe = wilc->rxq_head; wilc->rxq_head = wilc->rxq_head->next; wilc->rxq_entries -= 1; - PRINT_D(RX_DBG, "RXQ entries decreased\n"); mutex_unlock(&wilc->rxq_cs); return rqe; } - PRINT_D(RX_DBG, "Nothing to get from Q\n"); return NULL; } @@ -643,7 +626,6 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) wilc_lock_timeout(wilc, &wilc->txq_add_to_head_cs, CFG_PKTS_TIMEOUT); wilc_wlan_txq_filter_dup_tcp_ack(dev); - PRINT_D(TX_DBG, "Getting the head of the TxQ\n"); tqe = wilc_wlan_txq_get_first(wilc); i = 0; sum = 0; @@ -659,27 +641,20 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) vmm_sz = HOST_HDR_OFFSET; vmm_sz += tqe->buffer_size; - PRINT_D(TX_DBG, "VMM Size before alignment = %d\n", vmm_sz); + if (vmm_sz & 0x3) vmm_sz = (vmm_sz + 4) & ~0x3; if ((sum + vmm_sz) > LINUX_TX_SIZE) break; - PRINT_D(TX_DBG, "VMM Size AFTER alignment = %d\n", vmm_sz); vmm_table[i] = vmm_sz / 4; - PRINT_D(TX_DBG, "VMMTable entry size = %d\n", - vmm_table[i]); - - if (tqe->type == WILC_CFG_PKT) { + if (tqe->type == WILC_CFG_PKT) vmm_table[i] |= BIT(10); - PRINT_D(TX_DBG, "VMMTable entry changed for CFG packet = %d\n", vmm_table[i]); - } vmm_table[i] = cpu_to_le32(vmm_table[i]); i++; sum += vmm_sz; - PRINT_D(TX_DBG, "sum = %d\n", sum); tqe = wilc_wlan_txq_get_next(wilc, tqe); } else { break; @@ -699,23 +674,18 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, ®); - if (!ret) { - wilc_debug(N_ERR, "[wilc txq]: fail can't read reg vmm_tbl_entry..\n"); + if (!ret) break; - } if ((reg & 0x1) == 0) { - PRINT_D(TX_DBG, "Writing VMM table ... with Size = %d\n", ((i + 1) * 4)); break; } else { counter++; if (counter > 200) { counter = 0; - PRINT_D(TX_DBG, "Looping in tx ctrl , forcce quit\n"); ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, 0); break; } - PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait...\n"); } } while (!wilc->quit); @@ -725,25 +695,19 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) timeout = 200; do { ret = wilc->hif_func->hif_block_tx(wilc, WILC_VMM_TBL_RX_SHADOW_BASE, (u8 *)vmm_table, ((i + 1) * 4)); - if (!ret) { - wilc_debug(N_ERR, "ERR block TX of VMM table.\n"); + if (!ret) break; - } ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x2); - if (!ret) { - wilc_debug(N_ERR, "[wilc txq]: fail can't write reg host_vmm_ctl..\n"); + if (!ret) break; - } do { ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, ®); - if (!ret) { - wilc_debug(N_ERR, "[wilc txq]: fail can't read reg host_vmm_ctl..\n"); + if (!ret) break; - } if ((reg >> 2) & 0x1) { entries = ((reg >> 3) & 0x3f); break; @@ -763,16 +727,12 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) PRINT_WRN(GENERIC_DBG, "[wilc txq]: no more buffer in the chip (reg: %08x), retry later [[ %d, %x ]]\n", reg, i, vmm_table[i - 1]); ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, ®); - if (!ret) { - wilc_debug(N_ERR, "[wilc txq]: fail can't read reg WILC_HOST_TX_CTRL..\n"); + if (!ret) break; - } reg &= ~BIT(0); ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, reg); - if (!ret) { - wilc_debug(N_ERR, "[wilc txq]: fail can't write reg WILC_HOST_TX_CTRL..\n"); + if (!ret) break; - } break; } else { break; @@ -840,16 +800,12 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) acquire_bus(wilc, ACQUIRE_AND_WAKEUP); ret = wilc->hif_func->hif_clear_int_ext(wilc, ENABLE_TX_VMM); - if (!ret) { - wilc_debug(N_ERR, "[wilc txq]: fail can't start tx VMM ...\n"); + if (!ret) goto _end_; - } ret = wilc->hif_func->hif_block_tx_ext(wilc, 0, txb, offset); - if (!ret) { - wilc_debug(N_ERR, "[wilc txq]: fail can't block tx ext...\n"); + if (!ret) goto _end_; - } _end_: @@ -875,19 +831,15 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) do { if (wilc->quit) { - PRINT_D(RX_DBG, "exit 1st do-while due to Clean_UP function\n"); up(&wilc->cfg_event); break; } rqe = wilc_wlan_rxq_remove(wilc); - if (!rqe) { - PRINT_D(RX_DBG, "nothing in the queue - exit 1st do-while\n"); + if (!rqe) break; - } + buffer = rqe->buffer; size = rqe->buffer_size; - PRINT_D(RX_DBG, "rxQ entery Size = %d - Address = %p\n", - size, buffer); offset = 0; do { @@ -906,10 +858,8 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) tp_len = (header >> 11) & 0x7ff; pkt_len = header & 0x7ff; - if (pkt_len == 0 || tp_len == 0) { - wilc_debug(N_RXQ, "[wilc rxq]: data corrupt, packet len or tp_len is 0 [%d][%d]\n", pkt_len, tp_len); + if (pkt_len == 0 || tp_len == 0) break; - } #define IS_MANAGMEMENT 0x100 #define IS_MANAGMEMENT_CALLBACK 0x080 @@ -935,7 +885,6 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) wilc_wlan_cfg_indicate_rx(wilc, &buffer[pkt_offset + offset], pkt_len, &rsp); if (rsp.type == WILC_CFG_RSP) { - PRINT_D(RX_DBG, "wilc->cfg_seq_no = %d - rsp.seq_no = %d\n", wilc->cfg_seq_no, rsp.seq_no); if (wilc->cfg_seq_no == rsp.seq_no) up(&wilc->cfg_event); } else if (rsp.type == WILC_CFG_RSP_STATUS) { @@ -977,10 +926,8 @@ static void wilc_pllupdate_isr_ext(struct wilc *wilc, u32 int_stats) else mdelay(WILC_PLL_TO_SPI); - while (!(ISWILC1000(wilc_get_chipid(wilc, true)) && --trials)) { - PRINT_D(TX_DBG, "PLL update retrying\n"); + while (!(ISWILC1000(wilc_get_chipid(wilc, true)) && --trials)) mdelay(1); - } } static void wilc_sleeptimer_isr_ext(struct wilc *wilc, u32 int_stats1) @@ -1000,9 +947,6 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status) size = ((int_status & 0x7fff) << 2); while (!size && retries < 10) { - u32 time = 0; - - wilc_debug(N_ERR, "RX Size equal zero ... Trying to read it again for %d time\n", time++); wilc->hif_func->hif_read_size(wilc, &size); size = ((size & 0x7fff) << 2); retries++; @@ -1012,21 +956,17 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status) if (LINUX_RX_SIZE - offset < size) offset = 0; - if (wilc->rx_buffer) { + if (wilc->rx_buffer) buffer = &wilc->rx_buffer[offset]; - } else { - wilc_debug(N_ERR, "[wilc isr]: fail Rx Buffer is NULL...drop the packets (%d)\n", size); + else goto _end_; - } wilc->hif_func->hif_clear_int_ext(wilc, DATA_INT_CLR | ENABLE_RX_VMM); ret = wilc->hif_func->hif_block_rx_ext(wilc, 0, buffer, size); - if (!ret) { - wilc_debug(N_ERR, "[wilc isr]: fail block rx...\n"); + if (!ret) goto _end_; - } _end_: if (ret) { offset += size; @@ -1079,12 +1019,9 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, dma_buffer = kmalloc(blksz, GFP_KERNEL); if (!dma_buffer) { ret = -EIO; - PRINT_ER("Can't allocate buffer for firmware download IO error\n "); goto _fail_1; } - PRINT_D(INIT_DBG, "Downloading firmware size = %d ...\n", buffer_size); - offset = 0; do { memcpy(&addr, &buffer[offset], 4); @@ -1113,7 +1050,6 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, if (!ret) { ret = -EIO; - PRINT_ER("Can't download firmware IO error\n "); goto _fail_; } PRINT_D(INIT_DBG, "Offset = %d\n", offset); @@ -1143,7 +1079,6 @@ int wilc_wlan_start(struct wilc *wilc) acquire_bus(wilc, ACQUIRE_ONLY); ret = wilc->hif_func->hif_write_reg(wilc, WILC_VMM_CORE_CFG, reg); if (!ret) { - wilc_debug(N_ERR, "[wilc start]: fail write reg vmm_core_cfg...\n"); release_bus(wilc, RELEASE_ONLY); ret = -EIO; return ret; @@ -1177,7 +1112,6 @@ int wilc_wlan_start(struct wilc *wilc) ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_1, reg); if (!ret) { - wilc_debug(N_ERR, "[wilc start]: fail write WILC_GP_REG_1 ...\n"); release_bus(wilc, RELEASE_ONLY); ret = -EIO; return ret; @@ -1187,7 +1121,6 @@ int wilc_wlan_start(struct wilc *wilc) ret = wilc->hif_func->hif_read_reg(wilc, 0x1000, &chipid); if (!ret) { - wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1000 ...\n"); release_bus(wilc, RELEASE_ONLY); ret = -EIO; return ret; @@ -1223,7 +1156,6 @@ int wilc_wlan_stop(struct wilc *wilc) ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); if (!ret) { - PRINT_ER("Error while reading reg\n"); release_bus(wilc, RELEASE_ALLOW_SLEEP); return ret; } @@ -1231,7 +1163,6 @@ int wilc_wlan_stop(struct wilc *wilc) reg &= ~BIT(10); ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); if (!ret) { - PRINT_ER("Error while writing reg\n"); release_bus(wilc, RELEASE_ALLOW_SLEEP); return ret; } @@ -1240,34 +1171,24 @@ int wilc_wlan_stop(struct wilc *wilc) ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); if (!ret) { - PRINT_ER("Error while reading reg\n"); release_bus(wilc, RELEASE_ALLOW_SLEEP); return ret; } - PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", - reg, timeout); if ((reg & BIT(10))) { - PRINT_D(GENERIC_DBG, "Bit 10 not reset : Retry %d\n", - timeout); reg &= ~BIT(10); ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); timeout--; } else { - PRINT_D(GENERIC_DBG, "Bit 10 reset after : Retry %d\n", - timeout); ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); if (!ret) { - PRINT_ER("Error while reading reg\n"); release_bus(wilc, RELEASE_ALLOW_SLEEP); return ret; } - PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", - reg, timeout); break; } @@ -1322,17 +1243,14 @@ void wilc_wlan_cleanup(struct net_device *dev) acquire_bus(wilc, ACQUIRE_AND_WAKEUP); ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, ®); - if (!ret) { - PRINT_ER("Error while reading reg\n"); + if (!ret) release_bus(wilc, RELEASE_ALLOW_SLEEP); - } - PRINT_ER("Writing ABORT reg\n"); + ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0, (reg | ABORT_INT)); - if (!ret) { - PRINT_ER("Error while writing reg\n"); + if (!ret) release_bus(wilc, RELEASE_ALLOW_SLEEP); - } + release_bus(wilc, RELEASE_ALLOW_SLEEP); wilc->hif_func->hif_deinit(NULL); } @@ -1437,7 +1355,6 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u32 wid, int commit, netdev_dbg(vif->ndev, "Get Timed Out\n"); ret_size = 0; } - netdev_dbg(vif->ndev, "[WILC]Get Response received\n"); wilc->cfg_frame_in_use = 0; wilc->cfg_frame_offset = 0; wilc->cfg_seq_no += 1; @@ -1589,7 +1506,6 @@ int wilc_wlan_init(struct net_device *dev) if (!wilc->tx_buffer) wilc->tx_buffer = kmalloc(LINUX_TX_SIZE, GFP_KERNEL); - PRINT_D(TX_DBG, "wilc->tx_buffer = %p\n", wilc->tx_buffer); if (!wilc->tx_buffer) { ret = -ENOBUFS; @@ -1599,7 +1515,7 @@ int wilc_wlan_init(struct net_device *dev) if (!wilc->rx_buffer) wilc->rx_buffer = kmalloc(LINUX_RX_SIZE, GFP_KERNEL); - PRINT_D(TX_DBG, "wilc->rx_buffer =%p\n", wilc->rx_buffer); + if (!wilc->rx_buffer) { ret = -ENOBUFS; PRINT_ER("Can't allocate Rx Buffer"); -- cgit v1.2.3 From b2a45eae9ff3538f39cd4cee6569d0a53be54595 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:15:51 +0900 Subject: staging: wilc1000: remove useless function This patch remove useless function remove_TCP_related in wilc_wlan.c file Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 400d311d587b..8618e27ac80e 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -206,15 +206,6 @@ static inline int add_tcp_pending_ack(u32 ack, u32 session_index, } return 0; } -static inline int remove_TCP_related(struct wilc *wilc) -{ - unsigned long flags; - - spin_lock_irqsave(&wilc->txq_spinlock, flags); - - spin_unlock_irqrestore(&wilc->txq_spinlock, flags); - return 0; -} static inline int tcp_process(struct net_device *dev, struct txq_entry_t *tqe) { -- cgit v1.2.3 From f06b9baf8716972a6a65f6eff470b918a9c67254 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:15:52 +0900 Subject: staging: wilc1000: remove unnecessary braces This patch remove warnings reported by checkpatch.pl for unnecessary braces Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 8618e27ac80e..e2c84dbba014 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -984,15 +984,15 @@ void wilc_handle_isr(struct wilc *wilc) if (int_status & PLL_INT_EXT) wilc_pllupdate_isr_ext(wilc, int_status); - if (int_status & DATA_INT_EXT) { + if (int_status & DATA_INT_EXT) wilc_wlan_handle_isr_ext(wilc, int_status); - } + if (int_status & SLEEP_INT_EXT) wilc_sleeptimer_isr_ext(wilc, int_status); - if (!(int_status & (ALL_INT_EXT))) { + if (!(int_status & (ALL_INT_EXT))) wilc_unknown_isr_ext(wilc); - } + release_bus(wilc, RELEASE_ALLOW_SLEEP); } EXPORT_SYMBOL_GPL(wilc_handle_isr); -- cgit v1.2.3 From 20f4e712d1a9c2efce20d5345cc1a4bf7070852b Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:15:53 +0900 Subject: staging: wilc1000: remove warnings missing a blank line after declarations This patch remove warnings reported by checkpatch.pl for missing a blank line after declarations Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index e2c84dbba014..dc2632286756 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1143,6 +1143,7 @@ int wilc_wlan_stop(struct wilc *wilc) u32 reg = 0; int ret; u8 timeout = 10; + acquire_bus(wilc, ACQUIRE_AND_WAKEUP); ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); -- cgit v1.2.3 From 65c3f000133ae375f34772d5e59f8aee28fbac9a Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:15:54 +0900 Subject: staging: wilc1000: Optimize code of wilc_get_chipid function This patch optimize code of wilc_get_chipid function. u8 type changed to boolean type and removed unnecessary if statement. Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 4 ++-- drivers/staging/wilc1000/wilc_wlan.c | 19 +++++++------------ drivers/staging/wilc1000/wilc_wlan_if.h | 2 +- 3 files changed, 10 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 22a2f98cc2fe..9e5dea4b24c5 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -388,7 +388,7 @@ int wilc_wlan_get_firmware(struct net_device *dev) vif = netdev_priv(dev); wilc = vif->wilc; - chip_id = wilc_get_chipid(wilc, 0); + chip_id = wilc_get_chipid(wilc, false); if (chip_id < 0x1003a0) firmware = FIRMWARE_1002; @@ -475,7 +475,7 @@ static int linux_wlan_init_test_config(struct net_device *dev, wilc_get_mac_address(vif, mac_add); netdev_dbg(dev, "MAC address is : %pM\n", mac_add); - wilc_get_chipid(wilc, 0); + wilc_get_chipid(wilc, false); *(int *)c_val = 1; diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index dc2632286756..46087e29fc15 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1441,36 +1441,31 @@ static u32 init_chip(struct net_device *dev) return ret; } -u32 wilc_get_chipid(struct wilc *wilc, u8 update) +u32 wilc_get_chipid(struct wilc *wilc, bool update) { static u32 chipid; u32 tempchipid = 0; - u32 rfrevid; + u32 rfrevid = 0; - if (chipid == 0 || update != 0) { + if (chipid == 0 || update) { wilc->hif_func->hif_read_reg(wilc, 0x1000, &tempchipid); wilc->hif_func->hif_read_reg(wilc, 0x13f4, &rfrevid); if (!ISWILC1000(tempchipid)) { chipid = 0; - goto _fail_; + return chipid; } if (tempchipid == 0x1002a0) { - if (rfrevid == 0x1) { - } else { + if (rfrevid != 0x1) tempchipid = 0x1002a1; - } } else if (tempchipid == 0x1002b0) { - if (rfrevid == 3) { - } else if (rfrevid == 4) { + if (rfrevid == 0x4) tempchipid = 0x1002b1; - } else { + else if (rfrevid != 0x3) tempchipid = 0x1002b2; - } } chipid = tempchipid; } -_fail_: return chipid; } diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index 294552dda7b5..269c56ea147b 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -921,6 +921,6 @@ struct wilc; int wilc_wlan_init(struct net_device *dev); void wilc_bus_set_max_speed(void); void wilc_bus_set_default_speed(void); -u32 wilc_get_chipid(struct wilc *wilc, u8 update); +u32 wilc_get_chipid(struct wilc *wilc, bool update); #endif -- cgit v1.2.3 From 06fb9336acdc388d186e943319d6a211dab06300 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:55 +0900 Subject: staging: wilc1000: wilc_wfi_cfgoperations.c: replaces PRINT_ER with netdev_err This patches replaces PRINT_ER with netdev_err. Removes unnecessary debug logs as well. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 86 ++++++++--------------- 1 file changed, 31 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index cc50225ca844..d8cf6b490e72 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -405,10 +405,8 @@ static void CfgScanResult(enum scan_event scan_event, if (wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC && (((s32)network_info->s8rssi * 100) < 0 || - ((s32)network_info->s8rssi * 100) > 100)) { - PRINT_ER("wiphy signal type fial\n"); + ((s32)network_info->s8rssi * 100) > 100)) return; - } if (network_info) { s32Freq = ieee80211_channel_to_frequency((s32)network_info->u8channel, IEEE80211_BAND_2GHZ); @@ -436,10 +434,6 @@ static void CfgScanResult(enum scan_event scan_event, (size_t)network_info->u16IEsLen, (((s32)network_info->s8rssi) * 100), GFP_KERNEL); cfg80211_put_bss(wiphy, bss); } - - - } else { - PRINT_ER("Discovered networks exceeded the max limit\n"); } } else { u32 i; @@ -531,7 +525,7 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, if (!pstrWFIDrv->p2p_connect) wlan_channel = INVALID_CHANNEL; - PRINT_ER("Unspecified failure: Connection status %d : MAC status = %d\n", u16ConnectStatus, u8MacStatus); + netdev_err(dev, "Unspecified failure\n"); } if (u16ConnectStatus == WLAN_STATUS_SUCCESS) { @@ -572,8 +566,6 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, u16ConnectStatus, GFP_KERNEL); } else if (enuConnDisconnEvent == CONN_DISCONN_EVENT_DISCONN_NOTIF) { wilc_optaining_ip = false; - PRINT_ER("Received MAC_DISCONNECTED from firmware with reason %d on dev [%p]\n", - pstrDisconnectNotifInfo->u16reason, priv->dev); p2p_local_random = 0x01; p2p_recv_random = 0x00; wilc_ie = false; @@ -612,7 +604,7 @@ static int set_channel(struct wiphy *wiphy, result = wilc_set_mac_chnl_num(vif, channelnum); if (result != 0) - PRINT_ER("Error in setting channel %d\n", channelnum); + netdev_err(priv->dev, "Error in setting channel\n"); return result; } @@ -680,8 +672,7 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) (void *)priv, NULL); } } else { - PRINT_ER("Requested num of scanned channels is greater than the max, supported" - " channels\n"); + netdev_err(priv->dev, "Requested scanned channels over\n"); } if (s32Error != 0) { @@ -843,7 +834,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, } else { s32Error = -ENOTSUPP; - PRINT_ER("Not supported cipher: Error(%d)\n", s32Error); + netdev_err(dev, "Not supported cipher\n"); wilc_connecting = 0; return s32Error; } @@ -909,7 +900,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, pstrNetworkInfo->u8channel, pstrNetworkInfo->pJoinParams); if (s32Error != 0) { - PRINT_ER("wilc_set_join_req(): Error(%d)\n", s32Error); + netdev_err(dev, "wilc_set_join_req(): Error\n"); s32Error = -ENOENT; wilc_connecting = 0; return s32Error; @@ -944,7 +935,7 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_co s32Error = wilc_disconnect(vif, reason_code); if (s32Error != 0) { - PRINT_ER("Error in disconnecting: Error(%d)\n", s32Error); + netdev_err(priv->dev, "Error in disconnecting\n"); s32Error = -EINVAL; } @@ -1211,7 +1202,7 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, break; default: - PRINT_ER("Not supported cipher: Error(%d)\n", s32Error); + netdev_err(netdev, "Not supported cipher\n"); s32Error = -ENOTSUPP; } @@ -1362,7 +1353,7 @@ static int get_station(struct wiphy *wiphy, struct net_device *dev, } if (associatedsta == -1) { - PRINT_ER("Station required is not associated\n"); + netdev_err(dev, "sta required is not associated\n"); return -ENOENT; } @@ -1449,8 +1440,7 @@ static int set_wiphy_params(struct wiphy *wiphy, u32 changed) PRINT_D(CFG80211_DBG, "Setting CFG params in the host interface\n"); s32Error = wilc_hif_set_cfg(vif, &pstrCfgParamVal); if (s32Error) - PRINT_ER("Error in setting WIPHY PARAMS\n"); - + netdev_err(priv->dev, "Error in setting WIPHY PARAMS\n"); return s32Error; } @@ -1485,7 +1475,7 @@ static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev, if (!(flag == PMKID_FOUND)) priv->pmkid_list.numpmkid++; } else { - PRINT_ER("Invalid PMKID index\n"); + netdev_err(netdev, "Invalid PMKID index\n"); s32Error = -EINVAL; } @@ -1854,16 +1844,14 @@ static int mgmt_tx(struct wiphy *wiphy, if (ieee80211_is_mgmt(mgmt->frame_control)) { mgmt_tx = kmalloc(sizeof(struct p2p_mgmt_data), GFP_KERNEL); - if (!mgmt_tx) { - PRINT_ER("Failed to allocate memory for mgmt_tx structure\n"); + if (!mgmt_tx) return -EFAULT; - } + mgmt_tx->buff = kmalloc(buf_len, GFP_KERNEL); - if (!mgmt_tx->buff) { - PRINT_ER("Failed to allocate memory for mgmt_tx buff\n"); + if (!mgmt_tx->buff) kfree(mgmt_tx); return -EFAULT; - } + memcpy(mgmt_tx->buff, buf, len); mgmt_tx->size = len; @@ -2072,10 +2060,8 @@ static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, priv = wiphy_priv(wiphy); vif = netdev_priv(priv->dev); - if (!priv->hif_drv) { - PRINT_ER("Driver is NULL\n"); + if (!priv->hif_drv) return -EIO; - } if (wilc_enable_ps) wilc_set_power_mgmt(vif, enabled, timeout); @@ -2168,7 +2154,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, break; default: - PRINT_ER("Unknown interface type= %d\n", type); + netdev_err(dev, "Unknown interface type= %d\n", type); return -EINVAL; } @@ -2195,7 +2181,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, s32Error = set_channel(wiphy, &settings->chandef); if (s32Error != 0) - PRINT_ER("Error in setting channel\n"); + netdev_err(dev, "Error in setting channel\n"); wilc_wlan_set_bssid(dev, wl->vif[vif->idx]->src_addr, AP_MODE); wilc_set_power_mgmt(vif, 0, 0); @@ -2247,7 +2233,7 @@ static int stop_ap(struct wiphy *wiphy, struct net_device *dev) s32Error = wilc_del_beacon(vif); if (s32Error) - PRINT_ER("Host delete beacon fail\n"); + netdev_err(dev, "Host delete beacon fail\n"); return s32Error; } @@ -2317,7 +2303,7 @@ static int add_station(struct wiphy *wiphy, struct net_device *dev, s32Error = wilc_add_station(vif, &strStaParams); if (s32Error) - PRINT_ER("Host add station fail\n"); + netdev_err(dev, "Host add station fail\n"); } return s32Error; @@ -2352,7 +2338,7 @@ static int del_station(struct wiphy *wiphy, struct net_device *dev, s32Error = wilc_del_station(vif, mac); if (s32Error) - PRINT_ER("Host delete station fail\n"); + netdev_err(dev, "Host delete station fail\n"); } return s32Error; } @@ -2424,7 +2410,7 @@ static int change_station(struct wiphy *wiphy, struct net_device *dev, s32Error = wilc_edit_station(vif, &strStaParams); if (s32Error) - PRINT_ER("Host edit station fail\n"); + netdev_err(dev, "Host edit station fail\n"); } return s32Error; } @@ -2457,8 +2443,7 @@ static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy, PRINT_D(HOSTAPD_DBG, "Setting monitor flag in private structure\n"); vif = netdev_priv(priv->wdev->netdev); vif->monitor_flag = 1; - } else - PRINT_ER("Error in initializing monitor interface\n "); + } } return priv->wdev; } @@ -2612,16 +2597,12 @@ static struct wireless_dev *WILC_WFI_CfgAlloc(void) PRINT_D(CFG80211_DBG, "Allocating wireless device\n"); wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); - if (!wdev) { - PRINT_ER("Cannot allocate wireless device\n"); + if (!wdev) goto _fail_; - } wdev->wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(struct wilc_priv)); - if (!wdev->wiphy) { - PRINT_ER("Cannot allocate wiphy\n"); + if (!wdev->wiphy) goto _fail_mem_; - } WILC_WFI_band_2ghz.ht_cap.ht_supported = 1; WILC_WFI_band_2ghz.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); @@ -2649,7 +2630,7 @@ struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct device *de wdev = WILC_WFI_CfgAlloc(); if (!wdev) { - PRINT_ER("CfgAlloc Failed\n"); + netdev_err(net, "wiphy new allocate failed\n"); return NULL; } @@ -2684,11 +2665,10 @@ struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct device *de set_wiphy_dev(wdev->wiphy, dev); s32Error = wiphy_register(wdev->wiphy); - if (s32Error) { - PRINT_ER("Cannot register wiphy device\n"); - } else { + if (s32Error) + netdev_err(net, "Cannot register wiphy device\n"); + else PRINT_D(CFG80211_DBG, "Successful Registering\n"); - } priv->dev = net; return wdev; @@ -2707,10 +2687,6 @@ int wilc_init_host_int(struct net_device *net) setup_timer(&wilc_during_ip_timer, clear_duringIP, 0); } op_ifcs++; - if (s32Error < 0) { - PRINT_ER("Failed to creat refresh Timer\n"); - return s32Error; - } priv->gbAutoRateAdjusted = false; @@ -2719,7 +2695,7 @@ int wilc_init_host_int(struct net_device *net) sema_init(&(priv->hSemScanReq), 1); s32Error = wilc_init(net, &priv->hif_drv); if (s32Error) - PRINT_ER("Error while initializing hostinterface\n"); + netdev_err(net, "Error while initializing hostinterface\n"); return s32Error; } @@ -2748,7 +2724,7 @@ int wilc_deinit_host_int(struct net_device *net) } if (s32Error) - PRINT_ER("Error while deintializing host interface\n"); + netdev_err(net, "Error while deintializing host interface\n"); return s32Error; } -- cgit v1.2.3 From e078ed73669c73306adc9e62de5da055fded290b Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:56 +0900 Subject: staging: wilc1000: wilc_msgqueue.c: removes debug print log This patches removes unnecessary debug print logs. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 5fe85eb40146..780ddd3aa05d 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -60,15 +60,11 @@ int wilc_mq_send(struct message_queue *mq, unsigned long flags; struct message *new_msg = NULL; - if ((!mq) || (send_buf_size == 0) || (!send_buf)) { - PRINT_ER("mq or send_buf is null\n"); + if (!mq || (send_buf_size == 0) || !send_buf) return -EINVAL; - } - if (mq->exiting) { - PRINT_ER("mq fail\n"); + if (mq->exiting) return -EFAULT; - } /* construct a new message */ new_msg = kmalloc(sizeof(*new_msg), GFP_ATOMIC); @@ -107,15 +103,11 @@ int wilc_mq_recv(struct message_queue *mq, struct message *msg; unsigned long flags; - if ((!mq) || (recv_buf_size == 0) || (!recv_buf) || (!recv_len)) { - PRINT_ER("mq or recv_buf is null\n"); + if (!mq || (recv_buf_size == 0) || !recv_buf || !recv_len) return -EINVAL; - } - if (mq->exiting) { - PRINT_ER("mq fail\n"); + if (mq->exiting) return -EFAULT; - } spin_lock_irqsave(&mq->lock, flags); mq->recv_count++; @@ -127,7 +119,6 @@ int wilc_mq_recv(struct message_queue *mq, if (list_empty(&mq->msg_list)) { spin_unlock_irqrestore(&mq->lock, flags); up(&mq->sem); - PRINT_ER("msg is null\n"); return -EFAULT; } /* check buffer size */ @@ -135,7 +126,6 @@ int wilc_mq_recv(struct message_queue *mq, if (recv_buf_size < msg->len) { spin_unlock_irqrestore(&mq->lock, flags); up(&mq->sem); - PRINT_ER("recv_buf_size overflow\n"); return -EOVERFLOW; } -- cgit v1.2.3 From 368949a7c08b0698e56dbe53c9b960b93b4edea9 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:24:03 +0900 Subject: staging: wilc1000: remove unused log message using the CORECONFIG_DBG tag This patch remove unused log messages using the CORECONFIG_DBG tag Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 1 - drivers/staging/wilc1000/linux_wlan_common.h | 2 -- drivers/staging/wilc1000/wilc_debugfs.c | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 20 +------------------- 4 files changed, 2 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index a0b80bf8e009..11e3ce078bad 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -315,7 +315,6 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) rx_len = wid_len - 1; network_info->u16CapInfo = get_cap_info(msa); network_info->u32Tsf = get_beacon_timestamp_lo(msa); - PRINT_D(CORECONFIG_DBG, "TSF :%x\n", network_info->u32Tsf); tsf_lo = get_beacon_timestamp_lo(msa); tsf_hi = get_beacon_timestamp_hi(msa); diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h index 5d40f05124c1..5e1d3ad5bed0 100644 --- a/drivers/staging/wilc1000/linux_wlan_common.h +++ b/drivers/staging/wilc1000/linux_wlan_common.h @@ -6,7 +6,6 @@ enum debug_region { Hostapd_debug, Hostinf_debug, CFG80211_debug, - Coreconfig_debug, Interrupt_debug, TX_debug, RX_debug, @@ -24,7 +23,6 @@ enum debug_region { #define GENERIC_DBG (1 << Generic_debug) #define HOSTAPD_DBG (1 << Hostapd_debug) #define HOSTINF_DBG (1 << Hostinf_debug) -#define CORECONFIG_DBG (1 << Coreconfig_debug) #define CFG80211_DBG (1 << CFG80211_debug) #define INT_DBG (1 << Interrupt_debug) #define TX_DBG (1 << TX_debug) diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index 291e6faa90e9..c7e07758ad7e 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -24,7 +24,7 @@ static struct dentry *wilc_dir; * -------------------------------------------------------------------------------- */ -#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | HOSTINF_DBG | CORECONFIG_DBG | CFG80211_DBG | INT_DBG | TX_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) +#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | HOSTINF_DBG | CFG80211_DBG | INT_DBG | TX_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) #define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR) atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG | FIRM_DBG | HOSTAPD_DBG); EXPORT_SYMBOL_GPL(WILC_REGION); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index d8cf6b490e72..7a5d81953839 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -192,7 +192,6 @@ static void clear_shadow_scan(void) if (op_ifcs == 0) { del_timer_sync(&hAgingTimer); - PRINT_INFO(CORECONFIG_DBG, "destroy aging timer\n"); for (i = 0; i < last_scanned_cnt; i++) { if (last_scanned_shadow[last_scanned_cnt].pu8IEs) { @@ -424,8 +423,6 @@ static void CfgScanResult(enum scan_event scan_event, PRINT_D(CFG80211_DBG, "Network %s found\n", network_info->au8ssid); priv->u32RcvdChCount++; - if (!join_params) - PRINT_INFO(CORECONFIG_DBG, ">> Something really bad happened\n"); add_network_to_shadow(network_info, priv, join_params); if (!(memcmp("DIRECT-", network_info->au8ssid, 7))) { @@ -762,24 +759,14 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, PRINT_INFO(CFG80211_DBG, "sme->crypto.n_ciphers_pairwise=%d\n", sme->crypto.n_ciphers_pairwise); - if (INFO) { - for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++) - PRINT_D(CORECONFIG_DBG, "sme->crypto.ciphers_pairwise[%d]=%x\n", i, sme->crypto.ciphers_pairwise[i]); - } - if (sme->crypto.cipher_group != NO_ENCRYPT) { pcwpa_version = "Default"; - PRINT_D(CORECONFIG_DBG, ">> sme->crypto.wpa_versions: %x\n", sme->crypto.wpa_versions); if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) { u8security = ENCRYPT_ENABLED | WEP; pcgroup_encrypt_val = "WEP40"; pccipher_group = "WLAN_CIPHER_SUITE_WEP40"; PRINT_INFO(CFG80211_DBG, "WEP Default Key Idx = %d\n", sme->key_idx); - if (INFO) { - for (i = 0; i < sme->key_len; i++) - PRINT_D(CORECONFIG_DBG, "WEP Key Value[%d] = %d\n", i, sme->key[i]); - } priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len; memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len); @@ -1386,9 +1373,6 @@ static int get_station(struct wiphy *wiphy, struct net_device *dev, wilc_enable_tcp_ack_filter(true); else if (strStatistics.link_speed != DEFAULT_LINK_SPEED) wilc_enable_tcp_ack_filter(false); - - PRINT_D(CORECONFIG_DBG, "*** stats[%d][%d][%d][%d][%d]\n", sinfo->signal, sinfo->rx_packets, sinfo->tx_packets, - sinfo->tx_failed, sinfo->txrate.legacy); } return 0; } @@ -2718,10 +2702,8 @@ int wilc_deinit_host_int(struct net_device *net) s32Error = wilc_deinit(vif); clear_shadow_scan(); - if (op_ifcs == 0) { - PRINT_D(CORECONFIG_DBG, "destroy during ip\n"); + if (op_ifcs == 0) del_timer_sync(&wilc_during_ip_timer); - } if (s32Error) netdev_err(net, "Error while deintializing host interface\n"); -- cgit v1.2.3 From c4f97526a029fc6c57baf6c2de349ec41fce0e12 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:24:04 +0900 Subject: staging: wilc1000: remove unused log message using the HOSTINF_DBG tag This patch remove unused log message using the HOSTINF_DBG tag Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 198 +--------------------- drivers/staging/wilc1000/linux_wlan_common.h | 2 - drivers/staging/wilc1000/wilc_debugfs.c | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 - 4 files changed, 10 insertions(+), 194 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 2022deb113c0..6e0a4267a8ec 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -310,8 +310,6 @@ static s32 handle_set_channel(struct wilc_vif *vif, wid.val = (char *)&hif_set_ch->set_ch; wid.size = sizeof(char); - PRINT_D(HOSTINF_DBG, "Setting channel\n"); - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); @@ -382,9 +380,6 @@ static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) if (ip_addr[0] < 192) ip_addr[0] = 0; - PRINT_INFO(HOSTINF_DBG, "Indx = %d, Handling set IP = %pI4\n", - idx, ip_addr); - memcpy(set_ip[idx], ip_addr, IP_ALEN); wid.id = (u16)WID_IP_ADDRESS; @@ -402,8 +397,6 @@ static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) return -EINVAL; } - PRINT_INFO(HOSTINF_DBG, "IP address set\n"); - return result; } @@ -420,8 +413,6 @@ static s32 handle_get_ip_address(struct wilc_vif *vif, u8 idx) result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); - PRINT_INFO(HOSTINF_DBG, "%pI4\n", wid.val); - memcpy(get_ip[idx], wid.val, IP_ALEN); kfree(wid.val); @@ -434,10 +425,6 @@ static s32 handle_get_ip_address(struct wilc_vif *vif, u8 idx) return -EINVAL; } - PRINT_INFO(HOSTINF_DBG, "IP address retrieved:: u8IfIdx = %d\n", idx); - PRINT_INFO(HOSTINF_DBG, "%pI4\n", get_ip[idx]); - PRINT_INFO(HOSTINF_DBG, "\n"); - return result; } @@ -504,8 +491,6 @@ static s32 handle_cfg_param(struct wilc_vif *vif, down(&hif_drv->sem_cfg_values); - PRINT_D(HOSTINF_DBG, "Setting CFG params\n"); - if (cfg_param_attr->cfg_attr_info.flag & BSS_TYPE) { if (cfg_param_attr->cfg_attr_info.bss_type < 6) { wid_list[wid_cnt].id = WID_BSS_TYPE; @@ -810,9 +795,6 @@ static s32 Handle_Scan(struct wilc_vif *vif, u8 *pu8HdnNtwrksWidVal = NULL; struct host_if_drv *hif_drv = vif->hif_drv; - PRINT_D(HOSTINF_DBG, "Setting SCAN params\n"); - PRINT_D(HOSTINF_DBG, "Scanning: In [%d] state\n", hif_drv->hif_state); - hif_drv->usr_scan_req.scan_result = pstrHostIFscanAttr->result; hif_drv->usr_scan_req.arg = pstrHostIFscanAttr->arg; @@ -832,8 +814,6 @@ static s32 Handle_Scan(struct wilc_vif *vif, goto ERRORHANDLER; } - PRINT_D(HOSTINF_DBG, "Setting SCAN params\n"); - hif_drv->usr_scan_req.rcvd_ch_cnt = 0; strWIDList[u32WidsCount].id = (u16)WID_SSID_PROBE_REQ; @@ -848,8 +828,6 @@ static s32 Handle_Scan(struct wilc_vif *vif, *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.n_ssids; - PRINT_D(HOSTINF_DBG, "In Handle_ProbeRequest number of ssid %d\n", pstrHostIFscanAttr->hidden_network.n_ssids); - for (i = 0; i < pstrHostIFscanAttr->hidden_network.n_ssids; i++) { *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len; memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.net_info[i].ssid, pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len); @@ -908,8 +886,6 @@ static s32 Handle_Scan(struct wilc_vif *vif, if (result) PRINT_ER("Failed to send scan paramters config packet\n"); - else - PRINT_D(HOSTINF_DBG, "Successfully sent SCAN params config packet\n"); ERRORHANDLER: if (result) { @@ -938,8 +914,6 @@ static s32 Handle_ScanDone(struct wilc_vif *vif, struct wid wid; struct host_if_drv *hif_drv = vif->hif_drv; - PRINT_D(HOSTINF_DBG, "in Handle_ScanDone()\n"); - if (enuEvent == SCAN_EVENT_ABORTED) { PRINT_D(GENERIC_DBG, "Abort running scan\n"); u8abort_running_scan = 1; @@ -990,8 +964,6 @@ static s32 Handle_Connect(struct wilc_vif *vif, return result; } - PRINT_INFO(HOSTINF_DBG, "Saving connection parameters in global structure\n"); - ptstrJoinBssParam = (struct join_bss_param *)pstrHostIFconnectAttr->params; if (!ptstrJoinBssParam) { PRINT_ER("Required BSSID not found\n"); @@ -1067,8 +1039,6 @@ static s32 Handle_Connect(struct wilc_vif *vif, if (memcmp("DIRECT-", pstrHostIFconnectAttr->ssid, 7)) mode_11i = hif_drv->usr_conn_req.u8security; - PRINT_INFO(HOSTINF_DBG, "Encrypt Mode = %x\n", hif_drv->usr_conn_req.u8security); - strWIDList[u32WidsCount].id = (u16)WID_AUTH_TYPE; strWIDList[u32WidsCount].type = WID_CHAR; strWIDList[u32WidsCount].size = sizeof(char); @@ -1078,11 +1048,6 @@ static s32 Handle_Connect(struct wilc_vif *vif, if (memcmp("DIRECT-", pstrHostIFconnectAttr->ssid, 7)) auth_type = (u8)hif_drv->usr_conn_req.auth_type; - PRINT_INFO(HOSTINF_DBG, "Authentication Type = %x\n", - hif_drv->usr_conn_req.auth_type); - PRINT_D(HOSTINF_DBG, "Connecting to network of SSID %s on channel %d\n", - hif_drv->usr_conn_req.pu8ssid, pstrHostIFconnectAttr->ch); - strWIDList[u32WidsCount].id = (u16)WID_JOIN_REQ_EXTENDED; strWIDList[u32WidsCount].type = WID_STR; strWIDList[u32WidsCount].size = 112; @@ -1114,7 +1079,6 @@ static s32 Handle_Connect(struct wilc_vif *vif, } *(pu8CurrByte++) = (ptstrJoinBssParam->cap_info) & 0xFF; *(pu8CurrByte++) = ((ptstrJoinBssParam->cap_info) >> 8) & 0xFF; - PRINT_D(HOSTINF_DBG, "* Cap Info %0x*\n", (*(pu8CurrByte - 2) | ((*(pu8CurrByte - 1)) << 8))); if (pstrHostIFconnectAttr->bssid) memcpy(pu8CurrByte, pstrHostIFconnectAttr->bssid, 6); @@ -1126,26 +1090,20 @@ static s32 Handle_Connect(struct wilc_vif *vif, *(pu8CurrByte++) = (ptstrJoinBssParam->beacon_period) & 0xFF; *(pu8CurrByte++) = ((ptstrJoinBssParam->beacon_period) >> 8) & 0xFF; - PRINT_D(HOSTINF_DBG, "* Beacon Period %d*\n", (*(pu8CurrByte - 2) | ((*(pu8CurrByte - 1)) << 8))); *(pu8CurrByte++) = ptstrJoinBssParam->dtim_period; - PRINT_D(HOSTINF_DBG, "* DTIM Period %d*\n", (*(pu8CurrByte - 1))); memcpy(pu8CurrByte, ptstrJoinBssParam->supp_rates, MAX_RATES_SUPPORTED + 1); pu8CurrByte += (MAX_RATES_SUPPORTED + 1); *(pu8CurrByte++) = ptstrJoinBssParam->wmm_cap; - PRINT_D(HOSTINF_DBG, "* wmm cap%d*\n", (*(pu8CurrByte - 1))); *(pu8CurrByte++) = ptstrJoinBssParam->uapsd_cap; *(pu8CurrByte++) = ptstrJoinBssParam->ht_capable; hif_drv->usr_conn_req.ht_capable = ptstrJoinBssParam->ht_capable; *(pu8CurrByte++) = ptstrJoinBssParam->rsn_found; - PRINT_D(HOSTINF_DBG, "* rsn found %d*\n", *(pu8CurrByte - 1)); *(pu8CurrByte++) = ptstrJoinBssParam->rsn_grp_policy; - PRINT_D(HOSTINF_DBG, "* rsn group policy %0x*\n", (*(pu8CurrByte - 1))); *(pu8CurrByte++) = ptstrJoinBssParam->mode_802_11i; - PRINT_D(HOSTINF_DBG, "* mode_802_11i %d*\n", (*(pu8CurrByte - 1))); memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_pcip_policy, sizeof(ptstrJoinBssParam->rsn_pcip_policy)); pu8CurrByte += sizeof(ptstrJoinBssParam->rsn_pcip_policy); @@ -1160,8 +1118,6 @@ static s32 Handle_Connect(struct wilc_vif *vif, *(pu8CurrByte++) = ptstrJoinBssParam->noa_enabled; if (ptstrJoinBssParam->noa_enabled) { - PRINT_D(HOSTINF_DBG, "NOA present\n"); - *(pu8CurrByte++) = (ptstrJoinBssParam->tsf) & 0xFF; *(pu8CurrByte++) = ((ptstrJoinBssParam->tsf) >> 8) & 0xFF; *(pu8CurrByte++) = ((ptstrJoinBssParam->tsf) >> 16) & 0xFF; @@ -1183,8 +1139,7 @@ static s32 Handle_Connect(struct wilc_vif *vif, memcpy(pu8CurrByte, ptstrJoinBssParam->start_time, sizeof(ptstrJoinBssParam->start_time)); pu8CurrByte += sizeof(ptstrJoinBssParam->start_time); - } else - PRINT_D(HOSTINF_DBG, "NOA not present\n"); + } pu8CurrByte = strWIDList[u32WidsCount].val; u32WidsCount++; @@ -1194,8 +1149,6 @@ static s32 Handle_Connect(struct wilc_vif *vif, join_req_vif = vif; } - PRINT_D(GENERIC_DBG, "send HOST_IF_WAITING_CONN_RESP\n"); - if (pstrHostIFconnectAttr->bssid) { memcpy(wilc_connected_ssid, pstrHostIFconnectAttr->bssid, ETH_ALEN); @@ -1222,8 +1175,6 @@ ERRORHANDLER: del_timer(&hif_drv->connect_timer); - PRINT_D(HOSTINF_DBG, "could not start wilc_connecting to the required network\n"); - memset(&strConnectInfo, 0, sizeof(tstrConnectInfo)); if (pstrHostIFconnectAttr->result) { @@ -1252,7 +1203,6 @@ ERRORHANDLER: } } - PRINT_D(HOSTINF_DBG, "Deallocating connection parameters\n"); kfree(pstrHostIFconnectAttr->bssid); pstrHostIFconnectAttr->bssid = NULL; @@ -1363,8 +1313,6 @@ static s32 Handle_ConnectTimeout(struct wilc_vif *vif) wid.val = (s8 *)&u16DummyReasonCode; wid.size = sizeof(char); - PRINT_D(HOSTINF_DBG, "Sending disconnect request\n"); - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) @@ -1405,10 +1353,8 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, struct host_if_drv *hif_drv = vif->hif_drv; bNewNtwrkFound = true; - PRINT_INFO(HOSTINF_DBG, "Handling received network info\n"); if (hif_drv->usr_scan_req.scan_result) { - PRINT_D(HOSTINF_DBG, "State: Scanning, parsing network information received\n"); wilc_parse_network_info(pstrRcvdNetworkInfo->buffer, &pstrNetworkInfo); if ((!pstrNetworkInfo) || (!hif_drv->usr_scan_req.scan_result)) { @@ -1423,7 +1369,6 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, if (memcmp(hif_drv->usr_scan_req.net_info[i].au8bssid, pstrNetworkInfo->au8bssid, 6) == 0) { if (pstrNetworkInfo->s8rssi <= hif_drv->usr_scan_req.net_info[i].s8rssi) { - PRINT_D(HOSTINF_DBG, "Network previously discovered\n"); goto done; } else { hif_drv->usr_scan_req.net_info[i].s8rssi = pstrNetworkInfo->s8rssi; @@ -1435,8 +1380,6 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, } if (bNewNtwrkFound) { - PRINT_D(HOSTINF_DBG, "New network found\n"); - if (hif_drv->usr_scan_req.rcvd_ch_cnt < MAX_NUM_SCANNED_NETWORKS) { hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].s8rssi = pstrNetworkInfo->s8rssi; @@ -1454,8 +1397,6 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, hif_drv->usr_scan_req.arg, pJoinParams); } - } else { - PRINT_WRN(HOSTINF_DBG, "Discovered networks exceeded max. limit\n"); } } else { pstrNetworkInfo->bNewNetwork = false; @@ -1528,13 +1469,10 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, u8MacStatus = pstrRcvdGnrlAsyncInfo->buffer[7]; u8MacStatusReasonCode = pstrRcvdGnrlAsyncInfo->buffer[8]; u8MacStatusAdditionalInfo = pstrRcvdGnrlAsyncInfo->buffer[9]; - PRINT_INFO(HOSTINF_DBG, "Recieved MAC status = %d with Reason = %d , Info = %d\n", u8MacStatus, u8MacStatusReasonCode, u8MacStatusAdditionalInfo); if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) { u32 u32RcvdAssocRespInfoLen = 0; tstrConnectRespInfo *pstrConnectRespInfo = NULL; - PRINT_D(HOSTINF_DBG, "Recieved MAC status = %d with Reason = %d , Code = %d\n", u8MacStatus, u8MacStatusReasonCode, u8MacStatusAdditionalInfo); - memset(&strConnectInfo, 0, sizeof(tstrConnectInfo)); if (u8MacStatus == MAC_CONNECTED) { @@ -1545,10 +1483,7 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, MAX_ASSOC_RESP_FRAME_SIZE, &u32RcvdAssocRespInfoLen); - PRINT_INFO(HOSTINF_DBG, "Received association response with length = %d\n", u32RcvdAssocRespInfoLen); - if (u32RcvdAssocRespInfoLen != 0) { - PRINT_D(HOSTINF_DBG, "Parsing association response\n"); s32Err = wilc_parse_assoc_resp_info(rcv_assoc_resp, u32RcvdAssocRespInfoLen, &pstrConnectRespInfo); if (s32Err) { @@ -1557,7 +1492,6 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, strConnectInfo.u16ConnectStatus = pstrConnectRespInfo->u16ConnectStatus; if (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE) { - PRINT_INFO(HOSTINF_DBG, "Association response received : Successful connection status\n"); if (pstrConnectRespInfo->pu8RespIEs) { strConnectInfo.u16RespIEsLen = pstrConnectRespInfo->u16RespIEsLen; strConnectInfo.pu8RespIEs = kmalloc(pstrConnectRespInfo->u16RespIEsLen, GFP_KERNEL); @@ -1584,7 +1518,6 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, } if (hif_drv->usr_conn_req.pu8bssid) { - PRINT_D(HOSTINF_DBG, "Retrieving actual BSSID from AP\n"); memcpy(strConnectInfo.au8bssid, hif_drv->usr_conn_req.pu8bssid, 6); if ((u8MacStatus == MAC_CONNECTED) && @@ -1613,7 +1546,6 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE)) { wilc_set_power_mgmt(vif, 0, 0); - PRINT_D(HOSTINF_DBG, "MAC status : CONNECTED and Connect Status : Successful\n"); hif_drv->hif_state = HOST_IF_CONNECTED; PRINT_D(GENERIC_DBG, "Obtaining an IP, Disable Scan\n"); @@ -1621,7 +1553,6 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, mod_timer(&wilc_during_ip_timer, jiffies + msecs_to_jiffies(10000)); } else { - PRINT_D(HOSTINF_DBG, "MAC status : %d and Connect Status : %d\n", u8MacStatus, strConnectInfo.u16ConnectStatus); hif_drv->hif_state = HOST_IF_IDLE; scan_while_connected = false; } @@ -1641,12 +1572,9 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, hif_drv->usr_conn_req.ies = NULL; } else if ((u8MacStatus == MAC_DISCONNECTED) && (hif_drv->hif_state == HOST_IF_CONNECTED)) { - PRINT_D(HOSTINF_DBG, "Received MAC_DISCONNECTED from the FW\n"); - memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo)); if (hif_drv->usr_scan_req.scan_result) { - PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running OBSS Scan >>\n\n"); del_timer(&hif_drv->scan_timer); Handle_ScanDone(vif, SCAN_EVENT_ABORTED); } @@ -1694,9 +1622,6 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, } else if ((u8MacStatus == MAC_DISCONNECTED) && (hif_drv->usr_scan_req.scan_result)) { - PRINT_D(HOSTINF_DBG, "Received MAC_DISCONNECTED from the FW while scanning\n"); - PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running Scan >>\n\n"); - del_timer(&hif_drv->scan_timer); if (hif_drv->usr_scan_req.scan_result) Handle_ScanDone(vif, SCAN_EVENT_ABORTED); @@ -1725,8 +1650,6 @@ static int Handle_Key(struct wilc_vif *vif, case WEP: if (pstrHostIFkeyAttr->action & ADDKEY_AP) { - PRINT_D(HOSTINF_DBG, "Handling WEP key\n"); - PRINT_D(GENERIC_DBG, "ID Hostint is %d\n", pstrHostIFkeyAttr->attr.wep.index); strWIDList[0].id = (u16)WID_11I_MODE; strWIDList[0].type = WID_CHAR; strWIDList[0].size = sizeof(char); @@ -1763,7 +1686,6 @@ static int Handle_Key(struct wilc_vif *vif, wilc_get_vif_idx(vif)); kfree(pu8keybuf); } else if (pstrHostIFkeyAttr->action & ADDKEY) { - PRINT_D(HOSTINF_DBG, "Handling WEP key\n"); pu8keybuf = kmalloc(pstrHostIFkeyAttr->attr.wep.key_len + 2, GFP_KERNEL); if (!pu8keybuf) { PRINT_ER("No buffer to send Key\n"); @@ -1785,7 +1707,6 @@ static int Handle_Key(struct wilc_vif *vif, wilc_get_vif_idx(vif)); kfree(pu8keybuf); } else if (pstrHostIFkeyAttr->action & REMOVEKEY) { - PRINT_D(HOSTINF_DBG, "Removing key\n"); wid.id = (u16)WID_REMOVE_WEP_KEY; wid.type = WID_STR; @@ -1802,8 +1723,6 @@ static int Handle_Key(struct wilc_vif *vif, wid.val = (s8 *)&pstrHostIFkeyAttr->attr.wep.index; wid.size = sizeof(char); - PRINT_D(HOSTINF_DBG, "Setting default key index\n"); - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); @@ -1845,8 +1764,6 @@ static int Handle_Key(struct wilc_vif *vif, kfree(pu8keybuf); up(&hif_drv->sem_test_key_block); } else if (pstrHostIFkeyAttr->action & ADDKEY) { - PRINT_D(HOSTINF_DBG, "Handling group key(Rx) function\n"); - pu8keybuf = kzalloc(RX_MIC_KEY_MSG_LEN, GFP_KERNEL); if (pu8keybuf == NULL) { PRINT_ER("No buffer to send RxGTK Key\n"); @@ -1948,9 +1865,6 @@ _WPAPtk_end_case_: break; case PMKSA: - - PRINT_D(HOSTINF_DBG, "Handling PMKSA key\n"); - pu8keybuf = kmalloc((pstrHostIFkeyAttr->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1, GFP_KERNEL); if (!pu8keybuf) { PRINT_ER("No buffer to send PMKSA Key\n"); @@ -1995,8 +1909,6 @@ static void Handle_Disconnect(struct wilc_vif *vif) wid.val = (s8 *)&u16DummyReasonCode; wid.size = sizeof(char); - PRINT_D(HOSTINF_DBG, "Sending disconnect request\n"); - wilc_optaining_ip = false; wilc_set_power_mgmt(vif, 0, 0); @@ -2026,10 +1938,8 @@ static void Handle_Disconnect(struct wilc_vif *vif) } if (hif_drv->usr_conn_req.conn_result) { - if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) { - PRINT_D(HOSTINF_DBG, "Upper layer requested termination of connection\n"); + if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) del_timer(&hif_drv->connect_timer); - } hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL, @@ -2074,10 +1984,8 @@ void wilc_resolve_disconnect_aberration(struct wilc_vif *vif) if (!vif->hif_drv) return; if ((vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) || - (vif->hif_drv->hif_state == HOST_IF_CONNECTING)) { - PRINT_D(HOSTINF_DBG, "\n\n<< correcting Supplicant state machine >>\n\n"); + (vif->hif_drv->hif_state == HOST_IF_CONNECTING)) wilc_disconnect(vif, 1); - } } static s32 Handle_GetChnl(struct wilc_vif *vif) @@ -2091,8 +1999,6 @@ static s32 Handle_GetChnl(struct wilc_vif *vif) wid.val = (s8 *)&ch_no; wid.size = sizeof(char); - PRINT_D(HOSTINF_DBG, "Getting channel value\n"); - result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); @@ -2116,8 +2022,6 @@ static void Handle_GetRssi(struct wilc_vif *vif) wid.val = &rssi; wid.size = sizeof(char); - PRINT_D(HOSTINF_DBG, "Getting RSSI value\n"); - result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -2141,8 +2045,6 @@ static void Handle_GetLinkspeed(struct wilc_vif *vif) wid.val = &link_speed; wid.size = sizeof(char); - PRINT_D(HOSTINF_DBG, "Getting LINKSPEED value\n"); - result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -2260,8 +2162,6 @@ static void Handle_AddBeacon(struct wilc_vif *vif, struct wid wid; u8 *pu8CurrByte; - PRINT_D(HOSTINF_DBG, "Adding BEACON\n"); - wid.id = (u16)WID_ADD_BEACON; wid.type = WID_BIN; wid.size = pstrSetBeaconParam->head_len + pstrSetBeaconParam->tail_len + 16; @@ -2324,8 +2224,6 @@ static void Handle_DelBeacon(struct wilc_vif *vif) pu8CurrByte = wid.val; - PRINT_D(HOSTINF_DBG, "Deleting BEACON\n"); - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) @@ -2339,7 +2237,6 @@ static u32 WILC_HostIf_PackStaParam(u8 *pu8Buffer, pu8CurrByte = pu8Buffer; - PRINT_D(HOSTINF_DBG, "Packing STA params\n"); memcpy(pu8CurrByte, pstrStationParam->bssid, ETH_ALEN); pu8CurrByte += ETH_ALEN; @@ -2387,7 +2284,6 @@ static void Handle_AddStation(struct wilc_vif *vif, struct wid wid; u8 *pu8CurrByte; - PRINT_D(HOSTINF_DBG, "Handling add station\n"); wid.id = (u16)WID_ADD_STA; wid.type = WID_BIN; wid.size = WILC_ADD_STA_LENGTH + pstrStationParam->rates_len; @@ -2422,8 +2318,6 @@ static void Handle_DelAllSta(struct wilc_vif *vif, wid.type = WID_STR; wid.size = (pstrDelAllStaParam->assoc_sta * ETH_ALEN) + 1; - PRINT_D(HOSTINF_DBG, "Handling delete station\n"); - wid.val = kmalloc((pstrDelAllStaParam->assoc_sta * ETH_ALEN) + 1, GFP_KERNEL); if (!wid.val) goto ERRORHANDLER; @@ -2463,8 +2357,6 @@ static void Handle_DelStation(struct wilc_vif *vif, wid.type = WID_BIN; wid.size = ETH_ALEN; - PRINT_D(HOSTINF_DBG, "Handling delete station\n"); - wid.val = kmalloc(wid.size, GFP_KERNEL); if (!wid.val) goto ERRORHANDLER; @@ -2493,7 +2385,6 @@ static void Handle_EditStation(struct wilc_vif *vif, wid.type = WID_BIN; wid.size = WILC_ADD_STA_LENGTH + pstrStationParam->rates_len; - PRINT_D(HOSTINF_DBG, "Handling edit station\n"); wid.val = kmalloc(wid.size, GFP_KERNEL); if (!wid.val) goto ERRORHANDLER; @@ -2547,9 +2438,6 @@ static int Handle_RemainOnChan(struct wilc_vif *vif, goto ERRORHANDLER; } - PRINT_D(HOSTINF_DBG, "Setting channel :%d\n", - pstrHostIfRemainOnChan->ch); - u8remain_on_chan_flag = true; wid.id = (u16)WID_REMAIN_ON_CHAN; wid.type = WID_STR; @@ -2593,10 +2481,6 @@ static int Handle_RegisterFrame(struct wilc_vif *vif, struct wid wid; u8 *pu8CurrByte; - PRINT_D(HOSTINF_DBG, "Handling frame register : %d FrameType: %d\n", - pstrHostIfRegisterFrame->reg, - pstrHostIfRegisterFrame->frame_type); - wid.id = (u16)WID_REGISTER_FRAME; wid.type = WID_STR; wid.val = kmalloc(sizeof(u16) + 2, GFP_KERNEL); @@ -2629,8 +2513,6 @@ static u32 Handle_ListenStateExpired(struct wilc_vif *vif, s32 result = 0; struct host_if_drv *hif_drv = vif->hif_drv; - PRINT_D(HOSTINF_DBG, "CANCEL REMAIN ON CHAN\n"); - if (P2P_LISTEN_STATE) { u8remain_on_chan_flag = false; wid.id = (u16)WID_REMAIN_ON_CHAN; @@ -2698,12 +2580,10 @@ static void Handle_PowerManagement(struct wilc_vif *vif, s8PowerMode = MIN_FAST_PS; else s8PowerMode = NO_POWERSAVE; - PRINT_D(HOSTINF_DBG, "Handling power mgmt to %d\n", s8PowerMode); + wid.val = &s8PowerMode; wid.size = sizeof(char); - PRINT_D(HOSTINF_DBG, "Handling Power Management\n"); - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) @@ -2717,8 +2597,6 @@ static void Handle_SetMulticastFilter(struct wilc_vif *vif, struct wid wid; u8 *pu8CurrByte; - PRINT_D(HOSTINF_DBG, "Setup Multicast Filter\n"); - wid.id = (u16)WID_SETUP_MULTICAST_FILTER; wid.type = WID_BIN; wid.size = sizeof(struct set_multicast) + ((strHostIfSetMulti->cnt) * ETH_ALEN); @@ -2779,8 +2657,6 @@ static s32 Handle_DelAllRxBASessions(struct wilc_vif *vif, result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); - if (result) - PRINT_D(HOSTINF_DBG, "Couldn't delete BA Session\n"); kfree(wid.val); @@ -2849,7 +2725,6 @@ static int hostIFthread(void *pvArg) if (msg.id == HOST_IF_MSG_CONNECT && vif->hif_drv->usr_scan_req.scan_result) { - PRINT_D(HOSTINF_DBG, "Requeue connect request till scan done received\n"); wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); usleep_range(2 * 1000, 2 * 1000); continue; @@ -2899,7 +2774,6 @@ static int hostIFthread(void *pvArg) case HOST_IF_MSG_RCVD_SCAN_COMPLETE: del_timer(&vif->hif_drv->scan_timer); - PRINT_D(HOSTINF_DBG, "scan completed successfully\n"); if (!wilc_wlan_get_num_conn_ifcs(wilc)) wilc_chip_sleep_manually(wilc); @@ -2954,13 +2828,11 @@ static int hostIFthread(void *pvArg) break; case HOST_IF_MSG_SCAN_TIMER_FIRED: - PRINT_D(HOSTINF_DBG, "Scan Timeout\n"); Handle_ScanDone(msg.vif, SCAN_EVENT_ABORTED); break; case HOST_IF_MSG_CONNECT_TIMER_FIRED: - PRINT_D(HOSTINF_DBG, "Connect Timeout\n"); Handle_ConnectTimeout(msg.vif); break; @@ -2978,14 +2850,12 @@ static int hostIFthread(void *pvArg) break; case HOST_IF_MSG_SET_IPADDRESS: - PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_SET_IPADDRESS\n"); handle_set_ip_address(vif, msg.body.ip_info.ip_addr, msg.body.ip_info.idx); break; case HOST_IF_MSG_GET_IPADDRESS: - PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_SET_IPADDRESS\n"); handle_get_ip_address(vif, msg.body.ip_info.idx); break; @@ -3000,12 +2870,10 @@ static int hostIFthread(void *pvArg) break; case HOST_IF_MSG_REMAIN_ON_CHAN: - PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_REMAIN_ON_CHAN\n"); Handle_RemainOnChan(msg.vif, &msg.body.remain_on_ch); break; case HOST_IF_MSG_REGISTER_FRAME: - PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_REGISTER_FRAME\n"); Handle_RegisterFrame(msg.vif, &msg.body.reg_frame); break; @@ -3014,7 +2882,6 @@ static int hostIFthread(void *pvArg) break; case HOST_IF_MSG_SET_MULTICAST_FILTER: - PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_SET_MULTICAST_FILTER\n"); Handle_SetMulticastFilter(msg.vif, &msg.body.multicast_info); break; @@ -3039,7 +2906,6 @@ static int hostIFthread(void *pvArg) } } - PRINT_D(HOSTINF_DBG, "Releasing thread exit semaphore\n"); up(&hif_sema_thread); return 0; } @@ -3689,9 +3555,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, if (hidden_network) { msg.body.scan_info.hidden_network.net_info = hidden_network->net_info; msg.body.scan_info.hidden_network.n_ssids = hidden_network->n_ssids; - - } else - PRINT_D(HOSTINF_DBG, "hidden_network IS EQUAL TO NULL\n"); + } msg.vif = vif; msg.body.scan_info.src = scan_source; @@ -3717,7 +3581,6 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, return -EINVAL; } - PRINT_D(HOSTINF_DBG, ">> Starting the SCAN timer\n"); hif_drv->scan_timer.data = (unsigned long)vif; mod_timer(&hif_drv->scan_timer, jiffies + msecs_to_jiffies(HOST_IF_SCAN_TIMEOUT)); @@ -3774,8 +3637,6 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) vif = netdev_priv(dev); wilc = vif->wilc; - PRINT_D(HOSTINF_DBG, "Initializing host interface for client %d\n", clients_count + 1); - scan_while_connected = false; sema_init(&hif_sema_wait_response, 0); @@ -3794,7 +3655,6 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) wilc_optaining_ip = false; - PRINT_D(HOSTINF_DBG, "Global handle pointer value=%p\n", hif_drv); if (clients_count == 0) { sema_init(&hif_sema_thread, 0); sema_init(&hif_sema_driver, 0); @@ -3808,8 +3668,6 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) sema_init(&hif_drv->sem_get_chnl, 0); sema_init(&hif_drv->sem_inactive_time, 0); - PRINT_D(HOSTINF_DBG, "INIT: CLIENT COUNT %d\n", clients_count); - if (clients_count == 0) { result = wilc_mq_create(&hif_msg_q); @@ -3847,13 +3705,6 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) hif_drv->p2p_timeout = 0; - PRINT_INFO(HOSTINF_DBG, "Initialization values, Site survey value: %d\n Scan source: %d\n Active scan time: %d\n Passive scan time: %d\nCurrent tx Rate = %d\n", - hif_drv->cfg_values.site_survey_enabled, - hif_drv->cfg_values.scan_source, - hif_drv->cfg_values.active_scan_time, - hif_drv->cfg_values.passive_scan_time, - hif_drv->cfg_values.curr_tx_rate); - up(&hif_drv->sem_cfg_values); clients_count++; @@ -3880,17 +3731,10 @@ s32 wilc_deinit(struct wilc_vif *vif) down(&hif_sema_deinit); terminated_handle = hif_drv; - PRINT_D(HOSTINF_DBG, "De-initializing host interface for client %d\n", clients_count); - - if (del_timer_sync(&hif_drv->scan_timer)) - PRINT_D(HOSTINF_DBG, ">> Scan timer is active\n"); - - if (del_timer_sync(&hif_drv->connect_timer)) - PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n"); - - if (del_timer_sync(&periodic_rssi)) - PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n"); + del_timer_sync(&hif_drv->scan_timer); + del_timer_sync(&hif_drv->connect_timer); + del_timer_sync(&periodic_rssi); del_timer_sync(&hif_drv->remain_on_ch_timer); wilc_set_wfi_drv_handler(vif, 0, 0); @@ -3909,9 +3753,7 @@ s32 wilc_deinit(struct wilc_vif *vif) memset(&msg, 0, sizeof(struct host_if_msg)); if (clients_count == 1) { - if (del_timer_sync(&periodic_rssi)) - PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n"); - + del_timer_sync(&periodic_rssi); msg.id = HOST_IF_MSG_EXIT; msg.vif = vif; @@ -3985,10 +3827,8 @@ void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *pu8Buffer, } hif_drv = vif->hif_drv; - PRINT_D(HOSTINF_DBG, "General asynchronous info packet received\n"); if (!hif_drv || hif_drv == terminated_handle) { - PRINT_D(HOSTINF_DBG, "Wifi driver handler is equal to NULL\n"); up(&hif_sema_deinit); return; } @@ -4123,17 +3963,14 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) msg.id = HOST_IF_MSG_REGISTER_FRAME; switch (frame_type) { case ACTION: - PRINT_D(HOSTINF_DBG, "ACTION\n"); msg.body.reg_frame.reg_id = ACTION_FRM_IDX; break; case PROBE_REQ: - PRINT_D(HOSTINF_DBG, "PROBE REQ\n"); msg.body.reg_frame.reg_id = PROBE_REQ_IDX; break; default: - PRINT_D(HOSTINF_DBG, "Not valid frame type\n"); break; } msg.body.reg_frame.frame_type = frame_type; @@ -4162,8 +3999,6 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, memset(&msg, 0, sizeof(struct host_if_msg)); - PRINT_D(HOSTINF_DBG, "Setting adding beacon message queue params\n"); - msg.id = HOST_IF_MSG_ADD_BEACON; msg.vif = vif; beacon_info->interval = interval; @@ -4213,7 +4048,6 @@ int wilc_del_beacon(struct wilc_vif *vif) msg.id = HOST_IF_MSG_DEL_BEACON; msg.vif = vif; - PRINT_D(HOSTINF_DBG, "Setting deleting beacon message queue params\n"); result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) @@ -4236,8 +4070,6 @@ int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param) memset(&msg, 0, sizeof(struct host_if_msg)); - PRINT_D(HOSTINF_DBG, "Setting adding station message queue params\n"); - msg.id = HOST_IF_MSG_ADD_STATION; msg.vif = vif; @@ -4270,8 +4102,6 @@ int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr) memset(&msg, 0, sizeof(struct host_if_msg)); - PRINT_D(HOSTINF_DBG, "Setting deleting station message queue params\n"); - msg.id = HOST_IF_MSG_DEL_STATION; msg.vif = vif; @@ -4303,8 +4133,6 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) memset(&msg, 0, sizeof(struct host_if_msg)); - PRINT_D(HOSTINF_DBG, "Setting deauthenticating station message queue params\n"); - msg.id = HOST_IF_MSG_DEL_ALL_STA; msg.vif = vif; @@ -4350,8 +4178,6 @@ int wilc_edit_station(struct wilc_vif *vif, return -EFAULT; } - PRINT_D(HOSTINF_DBG, "Setting editing station message queue params\n"); - memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_EDIT_STATION; @@ -4380,8 +4206,6 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) struct power_mgmt_param *pwr_mgmt_info = &msg.body.pwr_mgmt_info; struct host_if_drv *hif_drv = vif->hif_drv; - PRINT_INFO(HOSTINF_DBG, "\n\n>> Setting PS to %d <<\n\n", enabled); - if (!hif_drv) { PRINT_ER("driver is null\n"); return -EFAULT; @@ -4390,8 +4214,6 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled) return 0; - PRINT_D(HOSTINF_DBG, "Setting Power management message queue params\n"); - memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_POWER_MGMT; @@ -4419,8 +4241,6 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, return -EFAULT; } - PRINT_D(HOSTINF_DBG, "Setting Multicast Filter params\n"); - memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_SET_MULTICAST_FILTER; diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h index 5e1d3ad5bed0..5374f36bff62 100644 --- a/drivers/staging/wilc1000/linux_wlan_common.h +++ b/drivers/staging/wilc1000/linux_wlan_common.h @@ -4,7 +4,6 @@ enum debug_region { Generic_debug = 0, Hostapd_debug, - Hostinf_debug, CFG80211_debug, Interrupt_debug, TX_debug, @@ -22,7 +21,6 @@ enum debug_region { #define GENERIC_DBG (1 << Generic_debug) #define HOSTAPD_DBG (1 << Hostapd_debug) -#define HOSTINF_DBG (1 << Hostinf_debug) #define CFG80211_DBG (1 << CFG80211_debug) #define INT_DBG (1 << Interrupt_debug) #define TX_DBG (1 << TX_debug) diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index c7e07758ad7e..4b38c377be79 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -24,7 +24,7 @@ static struct dentry *wilc_dir; * -------------------------------------------------------------------------------- */ -#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | HOSTINF_DBG | CFG80211_DBG | INT_DBG | TX_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) +#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | CFG80211_DBG | INT_DBG | TX_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) #define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR) atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG | FIRM_DBG | HOSTAPD_DBG); EXPORT_SYMBOL_GPL(WILC_REGION); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 7a5d81953839..a40b310072be 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1716,8 +1716,6 @@ static void WILC_WFI_RemainOnChannelReady(void *pUserVoid) priv = (struct wilc_priv *)pUserVoid; - PRINT_D(HOSTINF_DBG, "Remain on channel ready\n"); - priv->bInP2PlistenState = true; cfg80211_ready_on_channel(priv->wdev, -- cgit v1.2.3 From a41047962ac0530bb275bfb656fbc1e348fad23a Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:24:05 +0900 Subject: staging: wilc1000: remove unused log message using the TX_DBG tag This patch remove unused log message using the TX_DBG tag Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 4 ---- drivers/staging/wilc1000/linux_wlan_common.h | 2 -- drivers/staging/wilc1000/wilc_debugfs.c | 2 +- drivers/staging/wilc1000/wilc_wlan.c | 9 +++------ 4 files changed, 4 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 9e5dea4b24c5..202be15b615f 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1047,10 +1047,6 @@ static void linux_wlan_tx_complete(void *priv, int status) { struct tx_complete_data *pv_data = (struct tx_complete_data *)priv; - if (status == 1) - PRINT_D(TX_DBG, "Packet sent successfully - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb); - else - PRINT_D(TX_DBG, "Couldn't send packet - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb); dev_kfree_skb(pv_data->skb); kfree(pv_data); } diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h index 5374f36bff62..617bc5325cd2 100644 --- a/drivers/staging/wilc1000/linux_wlan_common.h +++ b/drivers/staging/wilc1000/linux_wlan_common.h @@ -6,7 +6,6 @@ enum debug_region { Hostapd_debug, CFG80211_debug, Interrupt_debug, - TX_debug, RX_debug, Lock_debug, Tcp_enhance, @@ -23,7 +22,6 @@ enum debug_region { #define HOSTAPD_DBG (1 << Hostapd_debug) #define CFG80211_DBG (1 << CFG80211_debug) #define INT_DBG (1 << Interrupt_debug) -#define TX_DBG (1 << TX_debug) #define RX_DBG (1 << RX_debug) #define LOCK_DBG (1 << Lock_debug) #define TCP_ENH (1 << Tcp_enhance) diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index 4b38c377be79..a3d274bd0820 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -24,7 +24,7 @@ static struct dentry *wilc_dir; * -------------------------------------------------------------------------------- */ -#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | CFG80211_DBG | INT_DBG | TX_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) +#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | CFG80211_DBG | INT_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) #define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR) atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG | FIRM_DBG | HOSTAPD_DBG); EXPORT_SYMBOL_GPL(WILC_REGION); diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 46087e29fc15..dd0c051fedca 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -652,13 +652,11 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) } } while (1); - if (i == 0) { - PRINT_D(TX_DBG, "Nothing in TX-Q\n"); + if (i == 0) break; - } else { - PRINT_D(TX_DBG, "Mark the last entry in VMM table - number of previous entries = %d\n", i); + else vmm_table[i] = 0x0; - } + acquire_bus(wilc, ACQUIRE_AND_WAKEUP); counter = 0; do { @@ -807,7 +805,6 @@ _end_: up(&wilc->txq_add_to_head_cs); wilc->txq_exit = 1; - PRINT_D(TX_DBG, "THREAD: Exiting txq\n"); *txq_count = wilc->txq_entries; return ret; } -- cgit v1.2.3 From d9fb23d72f3f1f4e2209134ab4c9b40d72b21a20 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:06 +0900 Subject: staging: wilc1000: removes function 'wilc_dealloc_network_info()' This patch removes function 'wilc_dealloc_network_info()'. Does not need this function which only free memory. Therefore, this function is removed and changed directly with kfree. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 22 ---------------------- drivers/staging/wilc1000/coreconfigurator.h | 1 - drivers/staging/wilc1000/host_interface.c | 4 ++-- 3 files changed, 2 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 11e3ce078bad..81dd22e9c5f6 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -353,28 +353,6 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) return 0; } -s32 wilc_dealloc_network_info(tstrNetworkInfo *network_info) -{ - s32 result = 0; - - if (network_info) { - if (network_info->pu8IEs) { - kfree(network_info->pu8IEs); - network_info->pu8IEs = NULL; - } else { - result = -EFAULT; - } - - kfree(network_info); - network_info = NULL; - - } else { - result = -EFAULT; - } - - return result; -} - s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, tstrConnectRespInfo **ret_connect_resp_info) { diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index d801e58be8e6..23775e4e0f37 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -121,7 +121,6 @@ typedef struct { } tstrDisconnectNotifInfo; s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info); -s32 wilc_dealloc_network_info(tstrNetworkInfo *network_info); s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, tstrConnectRespInfo **ret_connect_resp_info); s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *connect_resp_info); diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 6e0a4267a8ec..2a1d7e952494 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1410,8 +1410,8 @@ done: pstrRcvdNetworkInfo->buffer = NULL; if (pstrNetworkInfo) { - wilc_dealloc_network_info(pstrNetworkInfo); - pstrNetworkInfo = NULL; + kfree(pstrNetworkInfo->pu8IEs); + kfree(pstrNetworkInfo); } return result; -- cgit v1.2.3 From 5f79c2aebf87a1cbe84a728916ecb77287eaa715 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:07 +0900 Subject: staging: wilc1000: removes function 'wilc_dealloc_assoc_resp_info()' This patch removes function wilc_dealloc_assoc_resp_info()'. Does not need this function which only free memory. Therefore, this function is removed and changed directly with kfree. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 22 ---------------------- drivers/staging/wilc1000/coreconfigurator.h | 1 - drivers/staging/wilc1000/host_interface.c | 4 ++-- 3 files changed, 2 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 81dd22e9c5f6..c86278de8c41 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -386,25 +386,3 @@ s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, return 0; } - -s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *connect_resp_info) -{ - s32 result = 0; - - if (connect_resp_info) { - if (connect_resp_info->pu8RespIEs) { - kfree(connect_resp_info->pu8RespIEs); - connect_resp_info->pu8RespIEs = NULL; - } else { - result = -EFAULT; - } - - kfree(connect_resp_info); - connect_resp_info = NULL; - - } else { - result = -EFAULT; - } - - return result; -} diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 23775e4e0f37..d42f47c8e61d 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -123,7 +123,6 @@ typedef struct { s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info); s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, tstrConnectRespInfo **ret_connect_resp_info); -s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *connect_resp_info); void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, u32 u32Length); void wilc_network_info_received(struct wilc *wilc, u8 *pu8Buffer, diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 2a1d7e952494..30b93d0b7d80 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1501,8 +1501,8 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, } if (pstrConnectRespInfo) { - wilc_dealloc_assoc_resp_info(pstrConnectRespInfo); - pstrConnectRespInfo = NULL; + kfree(pstrConnectRespInfo->pu8RespIEs); + kfree(pstrConnectRespInfo); } } } -- cgit v1.2.3 From 40d96e1d7600b094faeee43cd3de71df0b1ddc52 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:08 +0900 Subject: staging: wilc1000: remove typedef from tstrConnectRespInfo This patch removes typedef from the struct tstrConnectRespInfo and renames it to connect_resp_info. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 6 +++--- drivers/staging/wilc1000/coreconfigurator.h | 6 +++--- drivers/staging/wilc1000/host_interface.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index c86278de8c41..c456a324fddc 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -354,14 +354,14 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) } s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, - tstrConnectRespInfo **ret_connect_resp_info) + struct connect_resp_info **ret_connect_resp_info) { - tstrConnectRespInfo *connect_resp_info = NULL; + struct connect_resp_info *connect_resp_info = NULL; u16 assoc_resp_len = 0; u8 *ies = NULL; u16 ies_len = 0; - connect_resp_info = kzalloc(sizeof(tstrConnectRespInfo), GFP_KERNEL); + connect_resp_info = kzalloc(sizeof(*connect_resp_info), GFP_KERNEL); if (!connect_resp_info) return -ENOMEM; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index d42f47c8e61d..611486bec32d 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -97,13 +97,13 @@ typedef struct { u64 u64Tsf; } tstrNetworkInfo; -typedef struct { +struct connect_resp_info { u16 u16capability; u16 u16ConnectStatus; u16 u16AssocID; u8 *pu8RespIEs; u16 u16RespIEsLen; -} tstrConnectRespInfo; +}; typedef struct { u8 au8bssid[6]; @@ -122,7 +122,7 @@ typedef struct { s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info); s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, - tstrConnectRespInfo **ret_connect_resp_info); + struct connect_resp_info **ret_connect_resp_info); void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, u32 u32Length); void wilc_network_info_received(struct wilc *wilc, u8 *pu8Buffer, diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 30b93d0b7d80..513b1f016177 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1471,7 +1471,7 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, u8MacStatusAdditionalInfo = pstrRcvdGnrlAsyncInfo->buffer[9]; if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) { u32 u32RcvdAssocRespInfoLen = 0; - tstrConnectRespInfo *pstrConnectRespInfo = NULL; + struct connect_resp_info *pstrConnectRespInfo = NULL; memset(&strConnectInfo, 0, sizeof(tstrConnectInfo)); -- cgit v1.2.3 From ba7b6ff52a153ce94def3466e9eb23c7bb9888d5 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:09 +0900 Subject: staging: wilc1000: renames struct connect_resp_info variables This patch renames to avoid camelcase and remove prefix names, changes follow are: - u16capability to capability - u16ConnectStatus to status - u16AssocID to assoc_id - pu8RespIEs to ies - u16RespIEsLen to ies_len Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 14 +++++++------- drivers/staging/wilc1000/coreconfigurator.h | 10 +++++----- drivers/staging/wilc1000/host_interface.c | 14 +++++++------- 3 files changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index c456a324fddc..e9f6262bb0a6 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -367,19 +367,19 @@ s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, assoc_resp_len = (u16)buffer_len; - connect_resp_info->u16ConnectStatus = get_asoc_status(buffer); - if (connect_resp_info->u16ConnectStatus == SUCCESSFUL_STATUSCODE) { - connect_resp_info->u16capability = get_assoc_resp_cap_info(buffer); - connect_resp_info->u16AssocID = get_asoc_id(buffer); + connect_resp_info->status = get_asoc_status(buffer); + if (connect_resp_info->status == SUCCESSFUL_STATUSCODE) { + connect_resp_info->capability = get_assoc_resp_cap_info(buffer); + connect_resp_info->assoc_id = get_asoc_id(buffer); ies = &buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN]; ies_len = assoc_resp_len - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN); - connect_resp_info->pu8RespIEs = kmemdup(ies, ies_len, GFP_KERNEL); - if (!connect_resp_info->pu8RespIEs) + connect_resp_info->ies = kmemdup(ies, ies_len, GFP_KERNEL); + if (!connect_resp_info->ies) return -ENOMEM; - connect_resp_info->u16RespIEsLen = ies_len; + connect_resp_info->ies_len = ies_len; } *ret_connect_resp_info = connect_resp_info; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 611486bec32d..aa9aee68e064 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -98,11 +98,11 @@ typedef struct { } tstrNetworkInfo; struct connect_resp_info { - u16 u16capability; - u16 u16ConnectStatus; - u16 u16AssocID; - u8 *pu8RespIEs; - u16 u16RespIEsLen; + u16 capability; + u16 status; + u16 assoc_id; + u8 *ies; + u16 ies_len; }; typedef struct { diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 513b1f016177..992008b14704 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1489,19 +1489,19 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, if (s32Err) { PRINT_ER("wilc_parse_assoc_resp_info() returned error %d\n", s32Err); } else { - strConnectInfo.u16ConnectStatus = pstrConnectRespInfo->u16ConnectStatus; + strConnectInfo.u16ConnectStatus = pstrConnectRespInfo->status; if (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE) { - if (pstrConnectRespInfo->pu8RespIEs) { - strConnectInfo.u16RespIEsLen = pstrConnectRespInfo->u16RespIEsLen; - strConnectInfo.pu8RespIEs = kmalloc(pstrConnectRespInfo->u16RespIEsLen, GFP_KERNEL); - memcpy(strConnectInfo.pu8RespIEs, pstrConnectRespInfo->pu8RespIEs, - pstrConnectRespInfo->u16RespIEsLen); + if (pstrConnectRespInfo->ies) { + strConnectInfo.u16RespIEsLen = pstrConnectRespInfo->ies_len; + strConnectInfo.pu8RespIEs = kmalloc(pstrConnectRespInfo->ies_len, GFP_KERNEL); + memcpy(strConnectInfo.pu8RespIEs, pstrConnectRespInfo->ies, + pstrConnectRespInfo->ies_len); } } if (pstrConnectRespInfo) { - kfree(pstrConnectRespInfo->pu8RespIEs); + kfree(pstrConnectRespInfo->ies); kfree(pstrConnectRespInfo); } } -- cgit v1.2.3 From 6b5180a0845e3deb7ed70271ca8ac313b05b5d04 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:10 +0900 Subject: staging: wilc1000: remove typedef from pstrNetworkInfo This patch removes typedef from the struct pstrNetworkInfo and renames it to network_info. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 7 ++++--- drivers/staging/wilc1000/coreconfigurator.h | 7 ++++--- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/host_interface.h | 4 ++-- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 14 +++++++------- 5 files changed, 20 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index e9f6262bb0a6..0d0a4ec9a073 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -270,9 +270,10 @@ static u8 get_current_channel_802_11n(u8 *pu8msa, u16 rx_len) return 0; } -s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) +s32 wilc_parse_network_info(u8 *msg_buffer, + struct network_info **ret_network_info) { - tstrNetworkInfo *network_info = NULL; + struct network_info *network_info = NULL; u8 msg_type = 0; u8 msg_id = 0; u16 msg_len = 0; @@ -304,7 +305,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) u32 tsf_lo; u32 tsf_hi; - network_info = kzalloc(sizeof(tstrNetworkInfo), GFP_KERNEL); + network_info = kzalloc(sizeof(*network_info), GFP_KERNEL); if (!network_info) return -ENOMEM; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index aa9aee68e064..214b43b85c5c 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -76,7 +76,7 @@ typedef struct { s8 as8RSSI[NUM_RSSI]; } tstrRSSI; -typedef struct { +struct network_info { s8 s8rssi; u16 u16CapInfo; u8 au8ssid[MAX_SSID_LEN]; @@ -95,7 +95,7 @@ typedef struct { void *pJoinParams; tstrRSSI strRssi; u64 u64Tsf; -} tstrNetworkInfo; +}; struct connect_resp_info { u16 capability; @@ -120,7 +120,8 @@ typedef struct { size_t ie_len; } tstrDisconnectNotifInfo; -s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info); +s32 wilc_parse_network_info(u8 *msg_buffer, + struct network_info **ret_network_info); s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, struct connect_resp_info **ret_connect_resp_info); void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 992008b14704..c0b4f7bf3a82 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -272,7 +272,7 @@ static struct wilc_vif *join_req_vif; #define FLUSHED_JOIN_REQ 1 #define FLUSHED_BYTE_POS 79 -static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo); +static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo); static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); /* The u8IfIdx starts from 0 to NUM_CONCURRENT_IFC -1, but 0 index used as @@ -1348,7 +1348,7 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, u32 i; bool bNewNtwrkFound; s32 result = 0; - tstrNetworkInfo *pstrNetworkInfo = NULL; + struct network_info *pstrNetworkInfo = NULL; void *pJoinParams = NULL; struct host_if_drv *hif_drv = vif->hif_drv; @@ -4255,7 +4255,7 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, return result; } -static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo) +static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) { struct join_bss_param *pNewJoinBssParam = NULL; u8 *pu8IEs; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 69c36a7449c7..c73a5c389297 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -168,8 +168,8 @@ enum KEY_TYPE { PMKSA, }; -typedef void (*wilc_scan_result)(enum scan_event, tstrNetworkInfo *, - void *, void *); +typedef void (*wilc_scan_result)(enum scan_event, struct network_info *, + void *, void *); typedef void (*wilc_connect_result)(enum conn_event, tstrConnectInfo *, diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index a40b310072be..b6a50c6b94c7 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -93,7 +93,7 @@ static const struct wiphy_wowlan_support wowlan_support = { extern int wilc_mac_open(struct net_device *ndev); extern int wilc_mac_close(struct net_device *ndev); -static tstrNetworkInfo last_scanned_shadow[MAX_NUM_SCANNED_NETWORKS_SHADOW]; +static struct network_info last_scanned_shadow[MAX_NUM_SCANNED_NETWORKS_SHADOW]; static u32 last_scanned_cnt; struct timer_list wilc_during_ip_timer; static struct timer_list hAgingTimer; @@ -206,7 +206,7 @@ static void clear_shadow_scan(void) } } -static u32 get_rssi_avg(tstrNetworkInfo *network_info) +static u32 get_rssi_avg(struct network_info *network_info) { u8 i; int rssi_v = 0; @@ -231,7 +231,7 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) wiphy = priv->dev->ieee80211_ptr->wiphy; for (i = 0; i < last_scanned_cnt; i++) { - tstrNetworkInfo *network_info; + struct network_info *network_info; network_info = &last_scanned_shadow[i]; @@ -310,7 +310,7 @@ static void clear_duringIP(unsigned long arg) wilc_optaining_ip = false; } -static int is_network_in_shadow(tstrNetworkInfo *pstrNetworkInfo, +static int is_network_in_shadow(struct network_info *pstrNetworkInfo, void *user_void) { int state = -1; @@ -333,7 +333,7 @@ static int is_network_in_shadow(tstrNetworkInfo *pstrNetworkInfo, return state; } -static void add_network_to_shadow(tstrNetworkInfo *pstrNetworkInfo, +static void add_network_to_shadow(struct network_info *pstrNetworkInfo, void *user_void, void *pJoinParams) { int ap_found = is_network_in_shadow(pstrNetworkInfo, user_void); @@ -384,7 +384,7 @@ static void add_network_to_shadow(tstrNetworkInfo *pstrNetworkInfo, } static void CfgScanResult(enum scan_event scan_event, - tstrNetworkInfo *network_info, + struct network_info *network_info, void *user_void, void *join_params) { @@ -693,7 +693,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, struct wilc_priv *priv; struct host_if_drv *pstrWFIDrv; - tstrNetworkInfo *pstrNetworkInfo = NULL; + struct network_info *pstrNetworkInfo = NULL; struct wilc_vif *vif; wilc_connecting = 1; -- cgit v1.2.3 From 5c23a291450f763e2d45264141617b8c3967c7e7 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:11 +0900 Subject: staging: wilc1000: renames s8rssi of connect_resp_info structure This patch renames s8rssi variable to rssi. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 14 +++++++------- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 0d0a4ec9a073..1e8c56bd73d9 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -309,7 +309,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, if (!network_info) return -ENOMEM; - network_info->s8rssi = wid_val[0]; + network_info->rssi = wid_val[0]; msa = &wid_val[1]; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 214b43b85c5c..e386e85030d9 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -77,7 +77,7 @@ typedef struct { } tstrRSSI; struct network_info { - s8 s8rssi; + s8 rssi; u16 u16CapInfo; u8 au8ssid[MAX_SSID_LEN]; u8 u8SsidLen; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c0b4f7bf3a82..f40b5a7ea8a2 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1368,10 +1368,10 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, (pstrNetworkInfo->au8bssid)) { if (memcmp(hif_drv->usr_scan_req.net_info[i].au8bssid, pstrNetworkInfo->au8bssid, 6) == 0) { - if (pstrNetworkInfo->s8rssi <= hif_drv->usr_scan_req.net_info[i].s8rssi) { + if (pstrNetworkInfo->rssi <= hif_drv->usr_scan_req.net_info[i].s8rssi) { goto done; } else { - hif_drv->usr_scan_req.net_info[i].s8rssi = pstrNetworkInfo->s8rssi; + hif_drv->usr_scan_req.net_info[i].s8rssi = pstrNetworkInfo->rssi; bNewNtwrkFound = false; break; } @@ -1381,7 +1381,7 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, if (bNewNtwrkFound) { if (hif_drv->usr_scan_req.rcvd_ch_cnt < MAX_NUM_SCANNED_NETWORKS) { - hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].s8rssi = pstrNetworkInfo->s8rssi; + hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].s8rssi = pstrNetworkInfo->rssi; if (hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].au8bssid && pstrNetworkInfo->au8bssid) { diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index b6a50c6b94c7..277d82af2e0f 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -351,13 +351,13 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, ap_index = ap_found; } rssi_index = last_scanned_shadow[ap_index].strRssi.u8Index; - last_scanned_shadow[ap_index].strRssi.as8RSSI[rssi_index++] = pstrNetworkInfo->s8rssi; + last_scanned_shadow[ap_index].strRssi.as8RSSI[rssi_index++] = pstrNetworkInfo->rssi; if (rssi_index == NUM_RSSI) { rssi_index = 0; last_scanned_shadow[ap_index].strRssi.u8Full = 1; } last_scanned_shadow[ap_index].strRssi.u8Index = rssi_index; - last_scanned_shadow[ap_index].s8rssi = pstrNetworkInfo->s8rssi; + last_scanned_shadow[ap_index].rssi = pstrNetworkInfo->rssi; last_scanned_shadow[ap_index].u16CapInfo = pstrNetworkInfo->u16CapInfo; last_scanned_shadow[ap_index].u8SsidLen = pstrNetworkInfo->u8SsidLen; memcpy(last_scanned_shadow[ap_index].au8ssid, @@ -403,8 +403,8 @@ static void CfgScanResult(enum scan_event scan_event, return; if (wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC && - (((s32)network_info->s8rssi * 100) < 0 || - ((s32)network_info->s8rssi * 100) > 100)) + (((s32)network_info->rssi * 100) < 0 || + ((s32)network_info->rssi * 100) > 100)) return; if (network_info) { @@ -415,7 +415,7 @@ static void CfgScanResult(enum scan_event scan_event, return; PRINT_INFO(CFG80211_DBG, "Network Info:: CHANNEL Frequency: %d, RSSI: %d, CapabilityInfo: %d," - "BeaconPeriod: %d\n", channel->center_freq, (((s32)network_info->s8rssi) * 100), + "BeaconPeriod: %d\n", channel->center_freq, (((s32)network_info->rssi) * 100), network_info->u16CapInfo, network_info->u16BeaconPeriod); if (network_info->bNewNetwork) { @@ -428,7 +428,7 @@ static void CfgScanResult(enum scan_event scan_event, if (!(memcmp("DIRECT-", network_info->au8ssid, 7))) { bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, network_info->au8bssid, network_info->u64Tsf, network_info->u16CapInfo, network_info->u16BeaconPeriod, (const u8 *)network_info->pu8IEs, - (size_t)network_info->u16IEsLen, (((s32)network_info->s8rssi) * 100), GFP_KERNEL); + (size_t)network_info->u16IEsLen, (((s32)network_info->rssi) * 100), GFP_KERNEL); cfg80211_put_bss(wiphy, bss); } } @@ -439,7 +439,7 @@ static void CfgScanResult(enum scan_event scan_event, if (memcmp(last_scanned_shadow[i].au8bssid, network_info->au8bssid, 6) == 0) { PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", last_scanned_shadow[i].au8ssid); - last_scanned_shadow[i].s8rssi = network_info->s8rssi; + last_scanned_shadow[i].rssi = network_info->rssi; last_scanned_shadow[i].u32TimeRcvdInScan = jiffies; break; } -- cgit v1.2.3 From fa5e2d159fb19f42dc598079ccdd7c385345ac4b Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:12 +0900 Subject: staging: wilc1000: renames u16CapInfo of connect_resp_info structure This patch renames u16CapInfo variable to cap_info. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 42 +++++++++++++++++------ 4 files changed, 35 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 1e8c56bd73d9..6c40d36922f6 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -314,7 +314,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, msa = &wid_val[1]; rx_len = wid_len - 1; - network_info->u16CapInfo = get_cap_info(msa); + network_info->cap_info = get_cap_info(msa); network_info->u32Tsf = get_beacon_timestamp_lo(msa); tsf_lo = get_beacon_timestamp_lo(msa); diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index e386e85030d9..ace50d86d7c6 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -78,7 +78,7 @@ typedef struct { struct network_info { s8 rssi; - u16 u16CapInfo; + u16 cap_info; u8 au8ssid[MAX_SSID_LEN]; u8 u8SsidLen; u8 au8bssid[6]; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index f40b5a7ea8a2..d56a33c20ddd 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4277,7 +4277,7 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) if (pNewJoinBssParam) { pNewJoinBssParam->dtim_period = ptstrNetworkInfo->u8DtimPeriod; pNewJoinBssParam->beacon_period = ptstrNetworkInfo->u16BeaconPeriod; - pNewJoinBssParam->cap_info = ptstrNetworkInfo->u16CapInfo; + pNewJoinBssParam->cap_info = ptstrNetworkInfo->cap_info; memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->au8bssid, 6); memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->au8ssid, ptstrNetworkInfo->u8SsidLen + 1); pNewJoinBssParam->ssid_len = ptstrNetworkInfo->u8SsidLen; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 277d82af2e0f..76768f291f50 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -246,9 +246,17 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) rssi = get_rssi_avg(network_info); if (memcmp("DIRECT-", network_info->au8ssid, 7) || direct_scan) { - bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, network_info->au8bssid, network_info->u64Tsf, network_info->u16CapInfo, - network_info->u16BeaconPeriod, (const u8 *)network_info->pu8IEs, - (size_t)network_info->u16IEsLen, (((s32)rssi) * 100), GFP_KERNEL); + bss = cfg80211_inform_bss(wiphy, + channel, + CFG80211_BSS_FTYPE_UNKNOWN, + network_info->au8bssid, + network_info->u64Tsf, + network_info->cap_info, + network_info->u16BeaconPeriod, + (const u8 *)network_info->pu8IEs, + (size_t)network_info->u16IEsLen, + (s32)rssi * 100, + GFP_KERNEL); cfg80211_put_bss(wiphy, bss); } } @@ -358,7 +366,7 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, } last_scanned_shadow[ap_index].strRssi.u8Index = rssi_index; last_scanned_shadow[ap_index].rssi = pstrNetworkInfo->rssi; - last_scanned_shadow[ap_index].u16CapInfo = pstrNetworkInfo->u16CapInfo; + last_scanned_shadow[ap_index].cap_info = pstrNetworkInfo->cap_info; last_scanned_shadow[ap_index].u8SsidLen = pstrNetworkInfo->u8SsidLen; memcpy(last_scanned_shadow[ap_index].au8ssid, pstrNetworkInfo->au8ssid, pstrNetworkInfo->u8SsidLen); @@ -414,9 +422,15 @@ static void CfgScanResult(enum scan_event scan_event, if (!channel) return; - PRINT_INFO(CFG80211_DBG, "Network Info:: CHANNEL Frequency: %d, RSSI: %d, CapabilityInfo: %d," - "BeaconPeriod: %d\n", channel->center_freq, (((s32)network_info->rssi) * 100), - network_info->u16CapInfo, network_info->u16BeaconPeriod); + PRINT_INFO(CFG80211_DBG, "Network Info::" + "CHANNEL Frequency: %d," + "RSSI: %d," + "Capability Info: %d," + "Beacon Period: %d\n", + channel->center_freq, + (s32)network_info->rssi * 100, + network_info->cap_info, + network_info->u16BeaconPeriod); if (network_info->bNewNetwork) { if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) { @@ -426,9 +440,17 @@ static void CfgScanResult(enum scan_event scan_event, add_network_to_shadow(network_info, priv, join_params); if (!(memcmp("DIRECT-", network_info->au8ssid, 7))) { - bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, network_info->au8bssid, network_info->u64Tsf, network_info->u16CapInfo, - network_info->u16BeaconPeriod, (const u8 *)network_info->pu8IEs, - (size_t)network_info->u16IEsLen, (((s32)network_info->rssi) * 100), GFP_KERNEL); + bss = cfg80211_inform_bss(wiphy, + channel, + CFG80211_BSS_FTYPE_UNKNOWN, + network_info->au8bssid, + network_info->u64Tsf, + network_info->cap_info, + network_info->u16BeaconPeriod, + (const u8 *)network_info->pu8IEs, + (size_t)network_info->u16IEsLen, + (s32)network_info->rssi * 100, + GFP_KERNEL); cfg80211_put_bss(wiphy, bss); } } -- cgit v1.2.3 From 2a3ff58a8a519d58ea0d0c1d3802203345140e98 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:13 +0900 Subject: staging: wilc1000: renames au8ssid of connect_resp_info structure This patch renames au8ssid variable to ssid. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 3 ++- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 19 +++++++++++-------- 4 files changed, 15 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 6c40d36922f6..4dd7c8a9e993 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -322,7 +322,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, network_info->u64Tsf = tsf_lo | ((u64)tsf_hi << 32); - get_ssid(msa, network_info->au8ssid, &network_info->u8SsidLen); + get_ssid(msa, network_info->ssid, &network_info->u8SsidLen); get_BSSID(msa, network_info->au8bssid); network_info->u8channel = get_current_channel_802_11n(msa, diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index ace50d86d7c6..781a65ff369f 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -79,7 +79,7 @@ typedef struct { struct network_info { s8 rssi; u16 cap_info; - u8 au8ssid[MAX_SSID_LEN]; + u8 ssid[MAX_SSID_LEN]; u8 u8SsidLen; u8 au8bssid[6]; u16 u16BeaconPeriod; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index d56a33c20ddd..c31f0b5b021a 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4279,7 +4279,8 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) pNewJoinBssParam->beacon_period = ptstrNetworkInfo->u16BeaconPeriod; pNewJoinBssParam->cap_info = ptstrNetworkInfo->cap_info; memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->au8bssid, 6); - memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->au8ssid, ptstrNetworkInfo->u8SsidLen + 1); + memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->ssid, + ptstrNetworkInfo->u8SsidLen + 1); pNewJoinBssParam->ssid_len = ptstrNetworkInfo->u8SsidLen; memset(pNewJoinBssParam->rsn_pcip_policy, 0xFF, 3); memset(pNewJoinBssParam->rsn_auth_policy, 0xFF, 3); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 76768f291f50..1caeff4e25c2 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -244,7 +244,7 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) channel = ieee80211_get_channel(wiphy, freq); rssi = get_rssi_avg(network_info); - if (memcmp("DIRECT-", network_info->au8ssid, 7) || + if (memcmp("DIRECT-", network_info->ssid, 7) || direct_scan) { bss = cfg80211_inform_bss(wiphy, channel, @@ -288,7 +288,8 @@ static void remove_network_from_shadow(unsigned long arg) for (i = 0; i < last_scanned_cnt; i++) { if (time_after(now, last_scanned_shadow[i].u32TimeRcvdInScan + (unsigned long)(SCAN_RESULT_EXPIRE))) { - PRINT_D(CFG80211_DBG, "Network expired in ScanShadow: %s\n", last_scanned_shadow[i].au8ssid); + PRINT_D(CFG80211_DBG, "Network expired ScanShadow:%s\n", + last_scanned_shadow[i].ssid); kfree(last_scanned_shadow[i].pu8IEs); last_scanned_shadow[i].pu8IEs = NULL; @@ -368,8 +369,8 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, last_scanned_shadow[ap_index].rssi = pstrNetworkInfo->rssi; last_scanned_shadow[ap_index].cap_info = pstrNetworkInfo->cap_info; last_scanned_shadow[ap_index].u8SsidLen = pstrNetworkInfo->u8SsidLen; - memcpy(last_scanned_shadow[ap_index].au8ssid, - pstrNetworkInfo->au8ssid, pstrNetworkInfo->u8SsidLen); + memcpy(last_scanned_shadow[ap_index].ssid, + pstrNetworkInfo->ssid, pstrNetworkInfo->u8SsidLen); memcpy(last_scanned_shadow[ap_index].au8bssid, pstrNetworkInfo->au8bssid, ETH_ALEN); last_scanned_shadow[ap_index].u16BeaconPeriod = pstrNetworkInfo->u16BeaconPeriod; @@ -434,12 +435,14 @@ static void CfgScanResult(enum scan_event scan_event, if (network_info->bNewNetwork) { if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) { - PRINT_D(CFG80211_DBG, "Network %s found\n", network_info->au8ssid); + PRINT_D(CFG80211_DBG, + "Network %s found\n", + network_info->ssid); priv->u32RcvdChCount++; add_network_to_shadow(network_info, priv, join_params); - if (!(memcmp("DIRECT-", network_info->au8ssid, 7))) { + if (!(memcmp("DIRECT-", network_info->ssid, 7))) { bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, @@ -459,7 +462,7 @@ static void CfgScanResult(enum scan_event scan_event, for (i = 0; i < priv->u32RcvdChCount; i++) { if (memcmp(last_scanned_shadow[i].au8bssid, network_info->au8bssid, 6) == 0) { - PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", last_scanned_shadow[i].au8ssid); + PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", last_scanned_shadow[i].ssid); last_scanned_shadow[i].rssi = network_info->rssi; last_scanned_shadow[i].u32TimeRcvdInScan = jiffies; @@ -736,7 +739,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, for (i = 0; i < last_scanned_cnt; i++) { if ((sme->ssid_len == last_scanned_shadow[i].u8SsidLen) && - memcmp(last_scanned_shadow[i].au8ssid, + memcmp(last_scanned_shadow[i].ssid, sme->ssid, sme->ssid_len) == 0) { PRINT_INFO(CFG80211_DBG, "Network with required SSID is found %s\n", sme->ssid); -- cgit v1.2.3 From a36e89e9bbda9e802dce432dffa2daceeca3cc74 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:14 +0900 Subject: staging: wilc1000: renames u8SsidLen of connect_resp_info structure This patch renames u8SsidLen variable to ssid_len. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 4dd7c8a9e993..273fad92e502 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -322,7 +322,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, network_info->u64Tsf = tsf_lo | ((u64)tsf_hi << 32); - get_ssid(msa, network_info->ssid, &network_info->u8SsidLen); + get_ssid(msa, network_info->ssid, &network_info->ssid_len); get_BSSID(msa, network_info->au8bssid); network_info->u8channel = get_current_channel_802_11n(msa, diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 781a65ff369f..39f3691918c8 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -80,7 +80,7 @@ struct network_info { s8 rssi; u16 cap_info; u8 ssid[MAX_SSID_LEN]; - u8 u8SsidLen; + u8 ssid_len; u8 au8bssid[6]; u16 u16BeaconPeriod; u8 u8DtimPeriod; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c31f0b5b021a..f9a8a447c716 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4280,8 +4280,8 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) pNewJoinBssParam->cap_info = ptstrNetworkInfo->cap_info; memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->au8bssid, 6); memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->ssid, - ptstrNetworkInfo->u8SsidLen + 1); - pNewJoinBssParam->ssid_len = ptstrNetworkInfo->u8SsidLen; + ptstrNetworkInfo->ssid_len + 1); + pNewJoinBssParam->ssid_len = ptstrNetworkInfo->ssid_len; memset(pNewJoinBssParam->rsn_pcip_policy, 0xFF, 3); memset(pNewJoinBssParam->rsn_auth_policy, 0xFF, 3); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 1caeff4e25c2..b5a97fd9e8c1 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -368,9 +368,9 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, last_scanned_shadow[ap_index].strRssi.u8Index = rssi_index; last_scanned_shadow[ap_index].rssi = pstrNetworkInfo->rssi; last_scanned_shadow[ap_index].cap_info = pstrNetworkInfo->cap_info; - last_scanned_shadow[ap_index].u8SsidLen = pstrNetworkInfo->u8SsidLen; + last_scanned_shadow[ap_index].ssid_len = pstrNetworkInfo->ssid_len; memcpy(last_scanned_shadow[ap_index].ssid, - pstrNetworkInfo->ssid, pstrNetworkInfo->u8SsidLen); + pstrNetworkInfo->ssid, pstrNetworkInfo->ssid_len); memcpy(last_scanned_shadow[ap_index].au8bssid, pstrNetworkInfo->au8bssid, ETH_ALEN); last_scanned_shadow[ap_index].u16BeaconPeriod = pstrNetworkInfo->u16BeaconPeriod; @@ -738,7 +738,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, PRINT_INFO(CFG80211_DBG, "Required SSID = %s\n , AuthType = %d\n", sme->ssid, sme->auth_type); for (i = 0; i < last_scanned_cnt; i++) { - if ((sme->ssid_len == last_scanned_shadow[i].u8SsidLen) && + if ((sme->ssid_len == last_scanned_shadow[i].ssid_len) && memcmp(last_scanned_shadow[i].ssid, sme->ssid, sme->ssid_len) == 0) { -- cgit v1.2.3 From 38d3bb787824355ea23010e38860888664626f02 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:15 +0900 Subject: staging: wilc1000: renames au8bssid of connect_resp_info structure This patch renames au8bssid variable to bssid. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 10 +++---- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 34 ++++++++++++----------- 4 files changed, 25 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 273fad92e502..4a825765f988 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -323,7 +323,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, network_info->u64Tsf = tsf_lo | ((u64)tsf_hi << 32); get_ssid(msa, network_info->ssid, &network_info->ssid_len); - get_BSSID(msa, network_info->au8bssid); + get_BSSID(msa, network_info->bssid); network_info->u8channel = get_current_channel_802_11n(msa, rx_len + FCS_LEN); diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 39f3691918c8..5404162c5960 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -81,7 +81,7 @@ struct network_info { u16 cap_info; u8 ssid[MAX_SSID_LEN]; u8 ssid_len; - u8 au8bssid[6]; + u8 bssid[6]; u16 u16BeaconPeriod; u8 u8DtimPeriod; u8 u8channel; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index f9a8a447c716..2534c9ac72b1 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1365,9 +1365,9 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, for (i = 0; i < hif_drv->usr_scan_req.rcvd_ch_cnt; i++) { if ((hif_drv->usr_scan_req.net_info[i].au8bssid) && - (pstrNetworkInfo->au8bssid)) { + (pstrNetworkInfo->bssid)) { if (memcmp(hif_drv->usr_scan_req.net_info[i].au8bssid, - pstrNetworkInfo->au8bssid, 6) == 0) { + pstrNetworkInfo->bssid, 6) == 0) { if (pstrNetworkInfo->rssi <= hif_drv->usr_scan_req.net_info[i].s8rssi) { goto done; } else { @@ -1384,9 +1384,9 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].s8rssi = pstrNetworkInfo->rssi; if (hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].au8bssid && - pstrNetworkInfo->au8bssid) { + pstrNetworkInfo->bssid) { memcpy(hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].au8bssid, - pstrNetworkInfo->au8bssid, 6); + pstrNetworkInfo->bssid, 6); hif_drv->usr_scan_req.rcvd_ch_cnt++; @@ -4278,7 +4278,7 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) pNewJoinBssParam->dtim_period = ptstrNetworkInfo->u8DtimPeriod; pNewJoinBssParam->beacon_period = ptstrNetworkInfo->u16BeaconPeriod; pNewJoinBssParam->cap_info = ptstrNetworkInfo->cap_info; - memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->au8bssid, 6); + memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->bssid, 6); memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->ssid, ptstrNetworkInfo->ssid_len + 1); pNewJoinBssParam->ssid_len = ptstrNetworkInfo->ssid_len; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index b5a97fd9e8c1..40287b5593b5 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -249,7 +249,7 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, - network_info->au8bssid, + network_info->bssid, network_info->u64Tsf, network_info->cap_info, network_info->u16BeaconPeriod, @@ -332,8 +332,8 @@ static int is_network_in_shadow(struct network_info *pstrNetworkInfo, state = -1; } else { for (i = 0; i < last_scanned_cnt; i++) { - if (memcmp(last_scanned_shadow[i].au8bssid, - pstrNetworkInfo->au8bssid, 6) == 0) { + if (memcmp(last_scanned_shadow[i].bssid, + pstrNetworkInfo->bssid, 6) == 0) { state = i; break; } @@ -371,8 +371,8 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, last_scanned_shadow[ap_index].ssid_len = pstrNetworkInfo->ssid_len; memcpy(last_scanned_shadow[ap_index].ssid, pstrNetworkInfo->ssid, pstrNetworkInfo->ssid_len); - memcpy(last_scanned_shadow[ap_index].au8bssid, - pstrNetworkInfo->au8bssid, ETH_ALEN); + memcpy(last_scanned_shadow[ap_index].bssid, + pstrNetworkInfo->bssid, ETH_ALEN); last_scanned_shadow[ap_index].u16BeaconPeriod = pstrNetworkInfo->u16BeaconPeriod; last_scanned_shadow[ap_index].u8DtimPeriod = pstrNetworkInfo->u8DtimPeriod; last_scanned_shadow[ap_index].u8channel = pstrNetworkInfo->u8channel; @@ -446,7 +446,7 @@ static void CfgScanResult(enum scan_event scan_event, bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, - network_info->au8bssid, + network_info->bssid, network_info->u64Tsf, network_info->cap_info, network_info->u16BeaconPeriod, @@ -461,7 +461,7 @@ static void CfgScanResult(enum scan_event scan_event, u32 i; for (i = 0; i < priv->u32RcvdChCount; i++) { - if (memcmp(last_scanned_shadow[i].au8bssid, network_info->au8bssid, 6) == 0) { + if (memcmp(last_scanned_shadow[i].bssid, network_info->bssid, 6) == 0) { PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", last_scanned_shadow[i].ssid); last_scanned_shadow[i].rssi = network_info->rssi; @@ -560,8 +560,9 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, for (i = 0; i < last_scanned_cnt; i++) { - if (memcmp(last_scanned_shadow[i].au8bssid, - pstrConnectInfo->au8bssid, ETH_ALEN) == 0) { + if (memcmp(last_scanned_shadow[i].bssid, + pstrConnectInfo->au8bssid, + ETH_ALEN) == 0) { unsigned long now = jiffies; if (time_after(now, @@ -747,7 +748,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, PRINT_INFO(CFG80211_DBG, "BSSID is not passed from the user\n"); break; } else { - if (memcmp(last_scanned_shadow[i].au8bssid, + if (memcmp(last_scanned_shadow[i].bssid, sme->bssid, ETH_ALEN) == 0) { PRINT_INFO(CFG80211_DBG, "BSSID is passed from the user and matched\n"); @@ -762,10 +763,11 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, pstrNetworkInfo = &last_scanned_shadow[i]; - PRINT_INFO(CFG80211_DBG, "network BSSID to be associated: %x%x%x%x%x%x\n", - pstrNetworkInfo->au8bssid[0], pstrNetworkInfo->au8bssid[1], - pstrNetworkInfo->au8bssid[2], pstrNetworkInfo->au8bssid[3], - pstrNetworkInfo->au8bssid[4], pstrNetworkInfo->au8bssid[5]); + PRINT_INFO(CFG80211_DBG, "network BSSID to be associated:" + "%x%x%x%x%x%x\n", + pstrNetworkInfo->bssid[0], pstrNetworkInfo->bssid[1], + pstrNetworkInfo->bssid[2], pstrNetworkInfo->bssid[3], + pstrNetworkInfo->bssid[4], pstrNetworkInfo->bssid[5]); } else { s32Error = -ENOENT; if (last_scanned_cnt == 0) @@ -903,9 +905,9 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, if (!pstrWFIDrv->p2p_connect) wlan_channel = pstrNetworkInfo->u8channel; - wilc_wlan_set_bssid(dev, pstrNetworkInfo->au8bssid, STATION_MODE); + wilc_wlan_set_bssid(dev, pstrNetworkInfo->bssid, STATION_MODE); - s32Error = wilc_set_join_req(vif, pstrNetworkInfo->au8bssid, sme->ssid, + s32Error = wilc_set_join_req(vif, pstrNetworkInfo->bssid, sme->ssid, sme->ssid_len, sme->ie, sme->ie_len, CfgConnectResult, (void *)priv, u8security, tenuAuth_type, -- cgit v1.2.3 From 4b313e915b0cf1f25e4857d8933bfc25d2ce8410 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:16 +0900 Subject: staging: wilc1000: renames u16BeaconPeriod of connect_resp_info structure This patch renames u16BeaconPeriod variable to beacon_period. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 4a825765f988..b4f7ec3c59a5 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -330,7 +330,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, index = MAC_HDR_LEN + TIME_STAMP_LEN; - network_info->u16BeaconPeriod = get_beacon_period(msa + index); + network_info->beacon_period = get_beacon_period(msa + index); index += BEACON_INTERVAL_LEN + CAP_INFO_LEN; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 5404162c5960..2fbffe83d354 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -82,7 +82,7 @@ struct network_info { u8 ssid[MAX_SSID_LEN]; u8 ssid_len; u8 bssid[6]; - u16 u16BeaconPeriod; + u16 beacon_period; u8 u8DtimPeriod; u8 u8channel; unsigned long u32TimeRcvdInScanCached; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 2534c9ac72b1..0ba248b2c216 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4276,7 +4276,7 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) pNewJoinBssParam = kzalloc(sizeof(struct join_bss_param), GFP_KERNEL); if (pNewJoinBssParam) { pNewJoinBssParam->dtim_period = ptstrNetworkInfo->u8DtimPeriod; - pNewJoinBssParam->beacon_period = ptstrNetworkInfo->u16BeaconPeriod; + pNewJoinBssParam->beacon_period = ptstrNetworkInfo->beacon_period; pNewJoinBssParam->cap_info = ptstrNetworkInfo->cap_info; memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->bssid, 6); memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->ssid, diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 40287b5593b5..0938b2dd3d2f 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -252,7 +252,7 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) network_info->bssid, network_info->u64Tsf, network_info->cap_info, - network_info->u16BeaconPeriod, + network_info->beacon_period, (const u8 *)network_info->pu8IEs, (size_t)network_info->u16IEsLen, (s32)rssi * 100, @@ -373,7 +373,7 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, pstrNetworkInfo->ssid, pstrNetworkInfo->ssid_len); memcpy(last_scanned_shadow[ap_index].bssid, pstrNetworkInfo->bssid, ETH_ALEN); - last_scanned_shadow[ap_index].u16BeaconPeriod = pstrNetworkInfo->u16BeaconPeriod; + last_scanned_shadow[ap_index].beacon_period = pstrNetworkInfo->beacon_period; last_scanned_shadow[ap_index].u8DtimPeriod = pstrNetworkInfo->u8DtimPeriod; last_scanned_shadow[ap_index].u8channel = pstrNetworkInfo->u8channel; last_scanned_shadow[ap_index].u16IEsLen = pstrNetworkInfo->u16IEsLen; @@ -431,7 +431,7 @@ static void CfgScanResult(enum scan_event scan_event, channel->center_freq, (s32)network_info->rssi * 100, network_info->cap_info, - network_info->u16BeaconPeriod); + network_info->beacon_period); if (network_info->bNewNetwork) { if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) { @@ -449,7 +449,7 @@ static void CfgScanResult(enum scan_event scan_event, network_info->bssid, network_info->u64Tsf, network_info->cap_info, - network_info->u16BeaconPeriod, + network_info->beacon_period, (const u8 *)network_info->pu8IEs, (size_t)network_info->u16IEsLen, (s32)network_info->rssi * 100, -- cgit v1.2.3 From df340fdf014c1f57a1e297b10307cb2e437a2bcd Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:17 +0900 Subject: staging: wilc1000: renames u8DtimPeriod of connect_resp_info structure This patch renames u8DtimPeriod variable to dtim_period. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index b4f7ec3c59a5..ce3bc29f51fa 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -336,7 +336,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tim_elm = get_tim_elm(msa, rx_len + FCS_LEN, index); if (tim_elm) - network_info->u8DtimPeriod = tim_elm[3]; + network_info->dtim_period = tim_elm[3]; ies = &msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN]; ies_len = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 2fbffe83d354..bbc4b0e583fe 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -83,7 +83,7 @@ struct network_info { u8 ssid_len; u8 bssid[6]; u16 beacon_period; - u8 u8DtimPeriod; + u8 dtim_period; u8 u8channel; unsigned long u32TimeRcvdInScanCached; unsigned long u32TimeRcvdInScan; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 0ba248b2c216..df331971c4b1 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4275,7 +4275,7 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) pNewJoinBssParam = kzalloc(sizeof(struct join_bss_param), GFP_KERNEL); if (pNewJoinBssParam) { - pNewJoinBssParam->dtim_period = ptstrNetworkInfo->u8DtimPeriod; + pNewJoinBssParam->dtim_period = ptstrNetworkInfo->dtim_period; pNewJoinBssParam->beacon_period = ptstrNetworkInfo->beacon_period; pNewJoinBssParam->cap_info = ptstrNetworkInfo->cap_info; memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->bssid, 6); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 0938b2dd3d2f..233b03d191f6 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -374,7 +374,7 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, memcpy(last_scanned_shadow[ap_index].bssid, pstrNetworkInfo->bssid, ETH_ALEN); last_scanned_shadow[ap_index].beacon_period = pstrNetworkInfo->beacon_period; - last_scanned_shadow[ap_index].u8DtimPeriod = pstrNetworkInfo->u8DtimPeriod; + last_scanned_shadow[ap_index].dtim_period = pstrNetworkInfo->dtim_period; last_scanned_shadow[ap_index].u8channel = pstrNetworkInfo->u8channel; last_scanned_shadow[ap_index].u16IEsLen = pstrNetworkInfo->u16IEsLen; last_scanned_shadow[ap_index].u64Tsf = pstrNetworkInfo->u64Tsf; -- cgit v1.2.3 From 405a8c786442a5e493bfa1c44a18cb4902500e2e Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:18 +0900 Subject: staging: wilc1000: renames u8channel of connect_resp_info structure This patch renames u8channel variable to ch. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index ce3bc29f51fa..6c748aaf8d8e 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -325,7 +325,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, get_ssid(msa, network_info->ssid, &network_info->ssid_len); get_BSSID(msa, network_info->bssid); - network_info->u8channel = get_current_channel_802_11n(msa, + network_info->ch = get_current_channel_802_11n(msa, rx_len + FCS_LEN); index = MAC_HDR_LEN + TIME_STAMP_LEN; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index bbc4b0e583fe..2f030a939e98 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -84,7 +84,7 @@ struct network_info { u8 bssid[6]; u16 beacon_period; u8 dtim_period; - u8 u8channel; + u8 ch; unsigned long u32TimeRcvdInScanCached; unsigned long u32TimeRcvdInScan; bool bNewNetwork; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 233b03d191f6..73323157d6cd 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -240,7 +240,7 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) struct ieee80211_channel *channel; if (network_info) { - freq = ieee80211_channel_to_frequency((s32)network_info->u8channel, IEEE80211_BAND_2GHZ); + freq = ieee80211_channel_to_frequency((s32)network_info->ch, IEEE80211_BAND_2GHZ); channel = ieee80211_get_channel(wiphy, freq); rssi = get_rssi_avg(network_info); @@ -375,7 +375,7 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, pstrNetworkInfo->bssid, ETH_ALEN); last_scanned_shadow[ap_index].beacon_period = pstrNetworkInfo->beacon_period; last_scanned_shadow[ap_index].dtim_period = pstrNetworkInfo->dtim_period; - last_scanned_shadow[ap_index].u8channel = pstrNetworkInfo->u8channel; + last_scanned_shadow[ap_index].ch = pstrNetworkInfo->ch; last_scanned_shadow[ap_index].u16IEsLen = pstrNetworkInfo->u16IEsLen; last_scanned_shadow[ap_index].u64Tsf = pstrNetworkInfo->u64Tsf; if (ap_found != -1) @@ -417,7 +417,7 @@ static void CfgScanResult(enum scan_event scan_event, return; if (network_info) { - s32Freq = ieee80211_channel_to_frequency((s32)network_info->u8channel, IEEE80211_BAND_2GHZ); + s32Freq = ieee80211_channel_to_frequency((s32)network_info->ch, IEEE80211_BAND_2GHZ); channel = ieee80211_get_channel(wiphy, s32Freq); if (!channel) @@ -895,15 +895,15 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, } - PRINT_INFO(CFG80211_DBG, "Required Channel = %d\n", pstrNetworkInfo->u8channel); + PRINT_INFO(CFG80211_DBG, "Required Ch = %d\n", pstrNetworkInfo->ch); PRINT_INFO(CFG80211_DBG, "Group encryption value = %s\n Cipher Group = %s\n WPA version = %s\n", pcgroup_encrypt_val, pccipher_group, pcwpa_version); - curr_channel = pstrNetworkInfo->u8channel; + curr_channel = pstrNetworkInfo->ch; if (!pstrWFIDrv->p2p_connect) - wlan_channel = pstrNetworkInfo->u8channel; + wlan_channel = pstrNetworkInfo->ch; wilc_wlan_set_bssid(dev, pstrNetworkInfo->bssid, STATION_MODE); @@ -911,7 +911,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, sme->ssid_len, sme->ie, sme->ie_len, CfgConnectResult, (void *)priv, u8security, tenuAuth_type, - pstrNetworkInfo->u8channel, + pstrNetworkInfo->ch, pstrNetworkInfo->pJoinParams); if (s32Error != 0) { netdev_err(dev, "wilc_set_join_req(): Error\n"); -- cgit v1.2.3 From 264d70f4dece6a3b146194b96780c1eb6f268600 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:19 +0900 Subject: staging: wilc1000: renames struct connect_resp_info variables This patch renames to avoid camelcase changes follow are: - u32TimeRcvdInScanCached to time_scan_cached - u32TimeRcvdInScan to time_scan Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.h | 4 ++-- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 2f030a939e98..0e10c7502eeb 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -85,8 +85,8 @@ struct network_info { u16 beacon_period; u8 dtim_period; u8 ch; - unsigned long u32TimeRcvdInScanCached; - unsigned long u32TimeRcvdInScan; + unsigned long time_scan_cached; + unsigned long time_scan; bool bNewNetwork; u8 u8Found; u32 u32Tsf; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 73323157d6cd..d7b4a2dab2bf 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -277,7 +277,7 @@ static void update_scan_time(void) int i; for (i = 0; i < last_scanned_cnt; i++) - last_scanned_shadow[i].u32TimeRcvdInScan = jiffies; + last_scanned_shadow[i].time_scan = jiffies; } static void remove_network_from_shadow(unsigned long arg) @@ -287,7 +287,8 @@ static void remove_network_from_shadow(unsigned long arg) for (i = 0; i < last_scanned_cnt; i++) { - if (time_after(now, last_scanned_shadow[i].u32TimeRcvdInScan + (unsigned long)(SCAN_RESULT_EXPIRE))) { + if (time_after(now, last_scanned_shadow[i].time_scan + + (unsigned long)(SCAN_RESULT_EXPIRE))) { PRINT_D(CFG80211_DBG, "Network expired ScanShadow:%s\n", last_scanned_shadow[i].ssid); @@ -384,8 +385,8 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, kmalloc(pstrNetworkInfo->u16IEsLen, GFP_KERNEL); memcpy(last_scanned_shadow[ap_index].pu8IEs, pstrNetworkInfo->pu8IEs, pstrNetworkInfo->u16IEsLen); - last_scanned_shadow[ap_index].u32TimeRcvdInScan = jiffies; - last_scanned_shadow[ap_index].u32TimeRcvdInScanCached = jiffies; + last_scanned_shadow[ap_index].time_scan = jiffies; + last_scanned_shadow[ap_index].time_scan_cached = jiffies; last_scanned_shadow[ap_index].u8Found = 1; if (ap_found != -1) kfree(last_scanned_shadow[ap_index].pJoinParams); @@ -465,7 +466,7 @@ static void CfgScanResult(enum scan_event scan_event, PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", last_scanned_shadow[i].ssid); last_scanned_shadow[i].rssi = network_info->rssi; - last_scanned_shadow[i].u32TimeRcvdInScan = jiffies; + last_scanned_shadow[i].time_scan = jiffies; break; } } @@ -566,9 +567,9 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, unsigned long now = jiffies; if (time_after(now, - last_scanned_shadow[i].u32TimeRcvdInScanCached + (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ)))) { + last_scanned_shadow[i].time_scan_cached + + (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ)))) bNeedScanRefresh = true; - } break; } -- cgit v1.2.3 From d40207637a62dab0f0607e066aaea99eb6257afa Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:20 +0900 Subject: staging: wilc1000: renames bNewNetwork of connect_resp_info structure This patch renames bNewNetwork variable to new_network. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 0e10c7502eeb..fd3b5d400d93 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -87,7 +87,7 @@ struct network_info { u8 ch; unsigned long time_scan_cached; unsigned long time_scan; - bool bNewNetwork; + bool new_network; u8 u8Found; u32 u32Tsf; u8 *pu8IEs; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index df331971c4b1..c0171f987844 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1390,7 +1390,7 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, hif_drv->usr_scan_req.rcvd_ch_cnt++; - pstrNetworkInfo->bNewNetwork = true; + pstrNetworkInfo->new_network = true; pJoinParams = host_int_ParseJoinBssParam(pstrNetworkInfo); hif_drv->usr_scan_req.scan_result(SCAN_EVENT_NETWORK_FOUND, pstrNetworkInfo, @@ -1399,7 +1399,7 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, } } } else { - pstrNetworkInfo->bNewNetwork = false; + pstrNetworkInfo->new_network = false; hif_drv->usr_scan_req.scan_result(SCAN_EVENT_NETWORK_FOUND, pstrNetworkInfo, hif_drv->usr_scan_req.arg, NULL); } diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index d7b4a2dab2bf..5d29f761ad9b 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -434,7 +434,7 @@ static void CfgScanResult(enum scan_event scan_event, network_info->cap_info, network_info->beacon_period); - if (network_info->bNewNetwork) { + if (network_info->new_network) { if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) { PRINT_D(CFG80211_DBG, "Network %s found\n", -- cgit v1.2.3 From a35d6e2ded29f790ce03bf4296463a6ce12520a6 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:21 +0900 Subject: staging: wilc1000: renames u8Found of connect_resp_info structure This patch renames u8Found variable to found. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index fd3b5d400d93..27c35d7867d0 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -88,7 +88,7 @@ struct network_info { unsigned long time_scan_cached; unsigned long time_scan; bool new_network; - u8 u8Found; + u8 found; u32 u32Tsf; u8 *pu8IEs; u16 u16IEsLen; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 5d29f761ad9b..c856f4f21bbc 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -235,7 +235,7 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) network_info = &last_scanned_shadow[i]; - if (!network_info->u8Found || all) { + if (!network_info->found || all) { s32 freq; struct ieee80211_channel *channel; @@ -269,7 +269,7 @@ static void reset_shadow_found(void) int i; for (i = 0; i < last_scanned_cnt; i++) - last_scanned_shadow[i].u8Found = 0; + last_scanned_shadow[i].found = 0; } static void update_scan_time(void) @@ -387,7 +387,7 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, pstrNetworkInfo->pu8IEs, pstrNetworkInfo->u16IEsLen); last_scanned_shadow[ap_index].time_scan = jiffies; last_scanned_shadow[ap_index].time_scan_cached = jiffies; - last_scanned_shadow[ap_index].u8Found = 1; + last_scanned_shadow[ap_index].found = 1; if (ap_found != -1) kfree(last_scanned_shadow[ap_index].pJoinParams); last_scanned_shadow[ap_index].pJoinParams = pJoinParams; -- cgit v1.2.3 From afb706539b1d61f9d4fa82fa4cd759ad2b9b848a Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:22 +0900 Subject: staging: wilc1000: renames u32Tsf of connect_resp_info structure This patch renames u32Tsf variable to tsf_lo. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 6c748aaf8d8e..3e1e1f52a5b0 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -315,7 +315,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, rx_len = wid_len - 1; network_info->cap_info = get_cap_info(msa); - network_info->u32Tsf = get_beacon_timestamp_lo(msa); + network_info->tsf_lo = get_beacon_timestamp_lo(msa); tsf_lo = get_beacon_timestamp_lo(msa); tsf_hi = get_beacon_timestamp_hi(msa); diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 27c35d7867d0..07a2ef0543e8 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -89,7 +89,7 @@ struct network_info { unsigned long time_scan; bool new_network; u8 found; - u32 u32Tsf; + u32 tsf_lo; u8 *pu8IEs; u16 u16IEsLen; void *pJoinParams; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c0171f987844..fa6ee92de054 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4330,7 +4330,7 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) (pu8IEs[index + 5] == 0x09) && (pu8IEs[index + 6] == 0x0c)) { u16 u16P2P_count; - pNewJoinBssParam->tsf = ptstrNetworkInfo->u32Tsf; + pNewJoinBssParam->tsf = ptstrNetworkInfo->tsf_lo; pNewJoinBssParam->noa_enabled = 1; pNewJoinBssParam->idx = pu8IEs[index + 9]; -- cgit v1.2.3 From 390b6db00d8c9333fad997f2f31367df6d34b4ff Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:23 +0900 Subject: staging: wilc1000: renames struct connect_resp_info variables This patch renames to avoid camelcase changes follow are: - pu8IEs to ies - u16IEsLen to ies_len Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 7 +++--- drivers/staging/wilc1000/coreconfigurator.h | 4 +-- drivers/staging/wilc1000/host_interface.c | 6 ++--- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 30 +++++++++++------------ 4 files changed, 23 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 3e1e1f52a5b0..cbca6a0f7bc6 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -341,12 +341,11 @@ s32 wilc_parse_network_info(u8 *msg_buffer, ies_len = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); if (ies_len > 0) { - network_info->pu8IEs = kmemdup(ies, ies_len, - GFP_KERNEL); - if (!network_info->pu8IEs) + network_info->ies = kmemdup(ies, ies_len, GFP_KERNEL); + if (!network_info->ies) return -ENOMEM; } - network_info->u16IEsLen = ies_len; + network_info->ies_len = ies_len; } *ret_network_info = network_info; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 07a2ef0543e8..3dca84018a72 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -90,8 +90,8 @@ struct network_info { bool new_network; u8 found; u32 tsf_lo; - u8 *pu8IEs; - u16 u16IEsLen; + u8 *ies; + u16 ies_len; void *pJoinParams; tstrRSSI strRssi; u64 u64Tsf; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index fa6ee92de054..781063dc9868 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1410,7 +1410,7 @@ done: pstrRcvdNetworkInfo->buffer = NULL; if (pstrNetworkInfo) { - kfree(pstrNetworkInfo->pu8IEs); + kfree(pstrNetworkInfo->ies); kfree(pstrNetworkInfo); } @@ -4270,8 +4270,8 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) u8 authTotalCount = 0; u8 i, j; - pu8IEs = ptstrNetworkInfo->pu8IEs; - u16IEsLen = ptstrNetworkInfo->u16IEsLen; + pu8IEs = ptstrNetworkInfo->ies; + u16IEsLen = ptstrNetworkInfo->ies_len; pNewJoinBssParam = kzalloc(sizeof(struct join_bss_param), GFP_KERNEL); if (pNewJoinBssParam) { diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index c856f4f21bbc..d150f4692a37 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -194,9 +194,9 @@ static void clear_shadow_scan(void) del_timer_sync(&hAgingTimer); for (i = 0; i < last_scanned_cnt; i++) { - if (last_scanned_shadow[last_scanned_cnt].pu8IEs) { - kfree(last_scanned_shadow[i].pu8IEs); - last_scanned_shadow[last_scanned_cnt].pu8IEs = NULL; + if (last_scanned_shadow[last_scanned_cnt].ies) { + kfree(last_scanned_shadow[i].ies); + last_scanned_shadow[last_scanned_cnt].ies = NULL; } kfree(last_scanned_shadow[i].pJoinParams); @@ -253,8 +253,8 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) network_info->u64Tsf, network_info->cap_info, network_info->beacon_period, - (const u8 *)network_info->pu8IEs, - (size_t)network_info->u16IEsLen, + (const u8 *)network_info->ies, + (size_t)network_info->ies_len, (s32)rssi * 100, GFP_KERNEL); cfg80211_put_bss(wiphy, bss); @@ -292,8 +292,8 @@ static void remove_network_from_shadow(unsigned long arg) PRINT_D(CFG80211_DBG, "Network expired ScanShadow:%s\n", last_scanned_shadow[i].ssid); - kfree(last_scanned_shadow[i].pu8IEs); - last_scanned_shadow[i].pu8IEs = NULL; + kfree(last_scanned_shadow[i].ies); + last_scanned_shadow[i].ies = NULL; kfree(last_scanned_shadow[i].pJoinParams); @@ -377,14 +377,14 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, last_scanned_shadow[ap_index].beacon_period = pstrNetworkInfo->beacon_period; last_scanned_shadow[ap_index].dtim_period = pstrNetworkInfo->dtim_period; last_scanned_shadow[ap_index].ch = pstrNetworkInfo->ch; - last_scanned_shadow[ap_index].u16IEsLen = pstrNetworkInfo->u16IEsLen; + last_scanned_shadow[ap_index].ies_len = pstrNetworkInfo->ies_len; last_scanned_shadow[ap_index].u64Tsf = pstrNetworkInfo->u64Tsf; if (ap_found != -1) - kfree(last_scanned_shadow[ap_index].pu8IEs); - last_scanned_shadow[ap_index].pu8IEs = - kmalloc(pstrNetworkInfo->u16IEsLen, GFP_KERNEL); - memcpy(last_scanned_shadow[ap_index].pu8IEs, - pstrNetworkInfo->pu8IEs, pstrNetworkInfo->u16IEsLen); + kfree(last_scanned_shadow[ap_index].ies); + last_scanned_shadow[ap_index].ies = kmalloc(pstrNetworkInfo->ies_len, + GFP_KERNEL); + memcpy(last_scanned_shadow[ap_index].ies, + pstrNetworkInfo->ies, pstrNetworkInfo->ies_len); last_scanned_shadow[ap_index].time_scan = jiffies; last_scanned_shadow[ap_index].time_scan_cached = jiffies; last_scanned_shadow[ap_index].found = 1; @@ -451,8 +451,8 @@ static void CfgScanResult(enum scan_event scan_event, network_info->u64Tsf, network_info->cap_info, network_info->beacon_period, - (const u8 *)network_info->pu8IEs, - (size_t)network_info->u16IEsLen, + (const u8 *)network_info->ies, + (size_t)network_info->ies_len, (s32)network_info->rssi * 100, GFP_KERNEL); cfg80211_put_bss(wiphy, bss); -- cgit v1.2.3 From cb64de7c362103847fa30ac720edcab8b92650b1 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:24 +0900 Subject: staging: wilc1000: renames pJoinParams of connect_resp_info structure This patch renames pJoinParams variable to join_params. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 3dca84018a72..f154e39c47a2 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -92,7 +92,7 @@ struct network_info { u32 tsf_lo; u8 *ies; u16 ies_len; - void *pJoinParams; + void *join_params; tstrRSSI strRssi; u64 u64Tsf; }; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index d150f4692a37..15f334af026c 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -199,8 +199,8 @@ static void clear_shadow_scan(void) last_scanned_shadow[last_scanned_cnt].ies = NULL; } - kfree(last_scanned_shadow[i].pJoinParams); - last_scanned_shadow[i].pJoinParams = NULL; + kfree(last_scanned_shadow[i].join_params); + last_scanned_shadow[i].join_params = NULL; } last_scanned_cnt = 0; } @@ -295,7 +295,7 @@ static void remove_network_from_shadow(unsigned long arg) kfree(last_scanned_shadow[i].ies); last_scanned_shadow[i].ies = NULL; - kfree(last_scanned_shadow[i].pJoinParams); + kfree(last_scanned_shadow[i].join_params); for (j = i; (j < last_scanned_cnt - 1); j++) last_scanned_shadow[j] = last_scanned_shadow[j + 1]; @@ -389,8 +389,8 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, last_scanned_shadow[ap_index].time_scan_cached = jiffies; last_scanned_shadow[ap_index].found = 1; if (ap_found != -1) - kfree(last_scanned_shadow[ap_index].pJoinParams); - last_scanned_shadow[ap_index].pJoinParams = pJoinParams; + kfree(last_scanned_shadow[ap_index].join_params); + last_scanned_shadow[ap_index].join_params = pJoinParams; } static void CfgScanResult(enum scan_event scan_event, @@ -913,7 +913,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, CfgConnectResult, (void *)priv, u8security, tenuAuth_type, pstrNetworkInfo->ch, - pstrNetworkInfo->pJoinParams); + pstrNetworkInfo->join_params); if (s32Error != 0) { netdev_err(dev, "wilc_set_join_req(): Error\n"); s32Error = -ENOENT; -- cgit v1.2.3 From f2050a189680a6b26c38d96958917721cc2f82a4 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:25 +0900 Subject: staging: wilc1000: renames strRssi of connect_resp_info structure This patch renames strRssi variable to str_rssi. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index f154e39c47a2..18c785b0769b 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -93,7 +93,7 @@ struct network_info { u8 *ies; u16 ies_len; void *join_params; - tstrRSSI strRssi; + tstrRSSI str_rssi; u64 u64Tsf; }; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 15f334af026c..30b163402e05 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -210,10 +210,11 @@ static u32 get_rssi_avg(struct network_info *network_info) { u8 i; int rssi_v = 0; - u8 num_rssi = (network_info->strRssi.u8Full) ? NUM_RSSI : (network_info->strRssi.u8Index); + u8 num_rssi = (network_info->str_rssi.u8Full) ? + NUM_RSSI : (network_info->str_rssi.u8Index); for (i = 0; i < num_rssi; i++) - rssi_v += network_info->strRssi.as8RSSI[i]; + rssi_v += network_info->str_rssi.as8RSSI[i]; rssi_v /= num_rssi; return rssi_v; @@ -360,13 +361,13 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, } else { ap_index = ap_found; } - rssi_index = last_scanned_shadow[ap_index].strRssi.u8Index; - last_scanned_shadow[ap_index].strRssi.as8RSSI[rssi_index++] = pstrNetworkInfo->rssi; + rssi_index = last_scanned_shadow[ap_index].str_rssi.u8Index; + last_scanned_shadow[ap_index].str_rssi.as8RSSI[rssi_index++] = pstrNetworkInfo->rssi; if (rssi_index == NUM_RSSI) { rssi_index = 0; - last_scanned_shadow[ap_index].strRssi.u8Full = 1; + last_scanned_shadow[ap_index].str_rssi.u8Full = 1; } - last_scanned_shadow[ap_index].strRssi.u8Index = rssi_index; + last_scanned_shadow[ap_index].str_rssi.u8Index = rssi_index; last_scanned_shadow[ap_index].rssi = pstrNetworkInfo->rssi; last_scanned_shadow[ap_index].cap_info = pstrNetworkInfo->cap_info; last_scanned_shadow[ap_index].ssid_len = pstrNetworkInfo->ssid_len; -- cgit v1.2.3 From 17d2f2b36f0b7cb309124ef714cb97e792c9a94b Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:26 +0900 Subject: staging: wilc1000: renames u64Tsf of connect_resp_info structure This patch renames u64Tsf variable to tsf_hi. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index cbca6a0f7bc6..d481719a97db 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -320,7 +320,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tsf_lo = get_beacon_timestamp_lo(msa); tsf_hi = get_beacon_timestamp_hi(msa); - network_info->u64Tsf = tsf_lo | ((u64)tsf_hi << 32); + network_info->tsf_hi = tsf_lo | ((u64)tsf_hi << 32); get_ssid(msa, network_info->ssid, &network_info->ssid_len); get_BSSID(msa, network_info->bssid); diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 18c785b0769b..748199d4439a 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -94,7 +94,7 @@ struct network_info { u16 ies_len; void *join_params; tstrRSSI str_rssi; - u64 u64Tsf; + u64 tsf_hi; }; struct connect_resp_info { diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 30b163402e05..35c39c66af4d 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -251,7 +251,7 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) channel, CFG80211_BSS_FTYPE_UNKNOWN, network_info->bssid, - network_info->u64Tsf, + network_info->tsf_hi, network_info->cap_info, network_info->beacon_period, (const u8 *)network_info->ies, @@ -379,7 +379,7 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, last_scanned_shadow[ap_index].dtim_period = pstrNetworkInfo->dtim_period; last_scanned_shadow[ap_index].ch = pstrNetworkInfo->ch; last_scanned_shadow[ap_index].ies_len = pstrNetworkInfo->ies_len; - last_scanned_shadow[ap_index].u64Tsf = pstrNetworkInfo->u64Tsf; + last_scanned_shadow[ap_index].tsf_hi = pstrNetworkInfo->tsf_hi; if (ap_found != -1) kfree(last_scanned_shadow[ap_index].ies); last_scanned_shadow[ap_index].ies = kmalloc(pstrNetworkInfo->ies_len, @@ -449,7 +449,7 @@ static void CfgScanResult(enum scan_event scan_event, channel, CFG80211_BSS_FTYPE_UNKNOWN, network_info->bssid, - network_info->u64Tsf, + network_info->tsf_hi, network_info->cap_info, network_info->beacon_period, (const u8 *)network_info->ies, -- cgit v1.2.3 From 5b3b744a4cb2613dc792c74421a0846c7223fb39 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:24:27 +0900 Subject: staging: wilc1000: remove unnecessary wilc_rx_complete function This patch remove unnecessary wilc_rx_complete function because this function only print unused log message. remove unused has_packet variable nomore. Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 5 ----- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 1 - drivers/staging/wilc1000/wilc_wlan.c | 7 +------ 3 files changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 202be15b615f..e702020b8e9d 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -372,11 +372,6 @@ static int linux_wlan_txq_task(void *vp) return 0; } -void wilc_rx_complete(struct wilc *nic) -{ - PRINT_D(RX_DBG, "RX completed\n"); -} - int wilc_wlan_get_firmware(struct net_device *dev) { struct wilc_vif *vif; diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 07a4ff10bb65..3077f5d416c7 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -228,7 +228,6 @@ int wilc1000_wlan_init(struct net_device *dev, struct wilc_vif *vif); void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset); void wilc_mac_indicate(struct wilc *wilc, int flag); -void wilc_rx_complete(struct wilc *wilc); void wilc_dbg(u8 *buff); int wilc_lock_timeout(struct wilc *wilc, void *, u32 timeout); diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index dd0c051fedca..98527f6f0394 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -811,7 +811,7 @@ _end_: static void wilc_wlan_handle_rxq(struct wilc *wilc) { - int offset = 0, size, has_packet = 0; + int offset = 0, size; u8 *buffer; struct rxq_entry_t *rqe; @@ -866,7 +866,6 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) &buffer[offset], pkt_len, pkt_offset); - has_packet = 1; } } else { struct wilc_cfg_rsp rsp; @@ -888,10 +887,6 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) break; } while (1); kfree(rqe); - - if (has_packet) - wilc_rx_complete(wilc); - } while (1); wilc->rxq_exit = 1; -- cgit v1.2.3 From eef2679b090ef149e93919aa0dde3432485e8d7e Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:24:28 +0900 Subject: staging: wilc1000: remove unused log message using the RX_DBG tag This patch remove unused log message using the RX_DBG tag Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan_common.h | 2 -- drivers/staging/wilc1000/wilc_debugfs.c | 2 +- drivers/staging/wilc1000/wilc_wlan.c | 5 ----- drivers/staging/wilc1000/wilc_wlan_cfg.c | 5 ----- 4 files changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h index 617bc5325cd2..63d0ec523129 100644 --- a/drivers/staging/wilc1000/linux_wlan_common.h +++ b/drivers/staging/wilc1000/linux_wlan_common.h @@ -6,7 +6,6 @@ enum debug_region { Hostapd_debug, CFG80211_debug, Interrupt_debug, - RX_debug, Lock_debug, Tcp_enhance, Spin_debug, @@ -22,7 +21,6 @@ enum debug_region { #define HOSTAPD_DBG (1 << Hostapd_debug) #define CFG80211_DBG (1 << CFG80211_debug) #define INT_DBG (1 << Interrupt_debug) -#define RX_DBG (1 << RX_debug) #define LOCK_DBG (1 << Lock_debug) #define TCP_ENH (1 << Tcp_enhance) #define SPIN_DEBUG (1 << Spin_debug) diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index a3d274bd0820..9c85bdd502f7 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -24,7 +24,7 @@ static struct dentry *wilc_dir; * -------------------------------------------------------------------------------- */ -#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | CFG80211_DBG | INT_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) +#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | CFG80211_DBG | INT_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) #define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR) atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG | FIRM_DBG | HOSTAPD_DBG); EXPORT_SYMBOL_GPL(WILC_REGION); diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 98527f6f0394..46e66475dbc8 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -835,11 +835,8 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) u32 pkt_len, pkt_offset, tp_len; int is_cfg_packet; - PRINT_D(RX_DBG, "In the 2nd do-while\n"); memcpy(&header, &buffer[offset], 4); header = cpu_to_le32(header); - PRINT_D(RX_DBG, "Header = %04x - Offset = %d\n", - header, offset); is_cfg_packet = (header >> 31) & 0x1; pkt_offset = (header >> 22) & 0x1ff; @@ -890,7 +887,6 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) } while (1); wilc->rxq_exit = 1; - PRINT_D(RX_DBG, "THREAD: Exiting RX thread\n"); } static void wilc_unknown_isr_ext(struct wilc *wilc) @@ -958,7 +954,6 @@ _end_: if (rqe) { rqe->buffer = buffer; rqe->buffer_size = size; - PRINT_D(RX_DBG, "rxq entery Size= %d - Address = %p\n", rqe->buffer_size, rqe->buffer); wilc_wlan_rxq_add(wilc, rqe); } } diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c index b72c77bb35f1..3b3065b4d734 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.c +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c @@ -522,7 +522,6 @@ int wilc_wlan_cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size, rsp->type = wilc_wlan_parse_info_frame(frame, size); rsp->seq_no = msg_id; /*call host interface info parse as well*/ - PRINT_INFO(RX_DBG, "Info message received\n"); wilc_gnrl_async_info_received(wilc, frame - 4, size + 4); break; @@ -532,14 +531,10 @@ int wilc_wlan_cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size, break; case 'S': - PRINT_INFO(RX_DBG, "Scan Notification Received\n"); wilc_scan_complete_received(wilc, frame - 4, size + 4); break; default: - PRINT_INFO(RX_DBG, "Receive unknown message type[%d-%d-%d-%d-%d-%d-%d-%d]\n", - frame[0], frame[1], frame[2], frame[3], frame[4], - frame[5], frame[6], frame[7]); rsp->type = 0; rsp->seq_no = msg_id; ret = 0; -- cgit v1.2.3 From c9f75c3071a469a0a4cac0c5d32c47873bca9bf5 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:24:29 +0900 Subject: staging: wilc1000: remove unused debug tag This patch remove unused debug tag INT_DBG, LOCK_DBG, BUS_DBG, MEM_DBG and FIRM_DBG Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan_common.h | 15 --------------- drivers/staging/wilc1000/wilc_debugfs.c | 5 +++-- 2 files changed, 3 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h index 63d0ec523129..758633e73488 100644 --- a/drivers/staging/wilc1000/linux_wlan_common.h +++ b/drivers/staging/wilc1000/linux_wlan_common.h @@ -5,29 +5,14 @@ enum debug_region { Generic_debug = 0, Hostapd_debug, CFG80211_debug, - Interrupt_debug, - Lock_debug, - Tcp_enhance, - Spin_debug, - Init_debug, - Bus_debug, - Mem_debug, - Firmware_debug, COMP = 0xFFFFFFFF, }; #define GENERIC_DBG (1 << Generic_debug) #define HOSTAPD_DBG (1 << Hostapd_debug) #define CFG80211_DBG (1 << CFG80211_debug) -#define INT_DBG (1 << Interrupt_debug) -#define LOCK_DBG (1 << Lock_debug) -#define TCP_ENH (1 << Tcp_enhance) -#define SPIN_DEBUG (1 << Spin_debug) #define INIT_DBG (1 << Init_debug) -#define BUS_DBG (1 << Bus_debug) -#define MEM_DBG (1 << Mem_debug) -#define FIRM_DBG (1 << Firmware_debug) #if defined (WILC_DEBUGFS) extern atomic_t WILC_REGION; diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index 9c85bdd502f7..8d088249ea44 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -24,9 +24,10 @@ static struct dentry *wilc_dir; * -------------------------------------------------------------------------------- */ -#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | CFG80211_DBG | INT_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) +#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | CFG80211_DBG | INIT_DBG) #define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR) -atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG | FIRM_DBG | HOSTAPD_DBG); +atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG | + HOSTAPD_DBG); EXPORT_SYMBOL_GPL(WILC_REGION); atomic_t WILC_DEBUG_LEVEL = ATOMIC_INIT(ERR); EXPORT_SYMBOL_GPL(WILC_DEBUG_LEVEL); -- cgit v1.2.3 From e3f16965c9d47318f598163ac2d9788b80114219 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:24:30 +0900 Subject: staging: wilc1000: remove unnecessary log message using GENERIC_DBG tag This patch remove unnecessary log message using GENERIC_DBG tag. Needed log messages has changed netdev_dbg from PRINT_D. And removes variables that were used to log message. Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 42 +------------ drivers/staging/wilc1000/linux_wlan.c | 2 - drivers/staging/wilc1000/linux_wlan_common.h | 4 +- drivers/staging/wilc1000/wilc_debugfs.c | 6 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 76 +++-------------------- drivers/staging/wilc1000/wilc_wlan.c | 2 - drivers/staging/wilc1000/wilc_wlan_cfg.c | 11 +--- 7 files changed, 18 insertions(+), 125 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 781063dc9868..abb20fb22963 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -445,7 +445,6 @@ static s32 handle_set_mac_address(struct wilc_vif *vif, wid.type = WID_STR; wid.val = mac_buf; wid.size = ETH_ALEN; - PRINT_D(GENERIC_DBG, "mac addr = :%pM\n", wid.val); result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); @@ -800,15 +799,12 @@ static s32 Handle_Scan(struct wilc_vif *vif, if ((hif_drv->hif_state >= HOST_IF_SCANNING) && (hif_drv->hif_state < HOST_IF_CONNECTED)) { - PRINT_D(GENERIC_DBG, "Don't scan already in [%d] state\n", - hif_drv->hif_state); PRINT_ER("Already scan\n"); result = -EBUSY; goto ERRORHANDLER; } if (wilc_optaining_ip || wilc_connecting) { - PRINT_D(GENERIC_DBG, "[handle_scan]: Don't do obss scan until IP adresss is obtained\n"); PRINT_ER("Don't do obss scan\n"); result = -EBUSY; goto ERRORHANDLER; @@ -915,7 +911,6 @@ static s32 Handle_ScanDone(struct wilc_vif *vif, struct host_if_drv *hif_drv = vif->hif_drv; if (enuEvent == SCAN_EVENT_ABORTED) { - PRINT_D(GENERIC_DBG, "Abort running scan\n"); u8abort_running_scan = 1; wid.id = (u16)WID_ABORT_RUNNING_SCAN; wid.type = WID_CHAR; @@ -956,8 +951,6 @@ static s32 Handle_Connect(struct wilc_vif *vif, struct join_bss_param *ptstrJoinBssParam; struct host_if_drv *hif_drv = vif->hif_drv; - PRINT_D(GENERIC_DBG, "Handling connect request\n"); - if (memcmp(pstrHostIFconnectAttr->bssid, wilc_connected_ssid, ETH_ALEN) == 0) { result = 0; PRINT_ER("Trying to connect to an already connected AP, Discard connect request\n"); @@ -1149,13 +1142,9 @@ static s32 Handle_Connect(struct wilc_vif *vif, join_req_vif = vif; } - if (pstrHostIFconnectAttr->bssid) { + if (pstrHostIFconnectAttr->bssid) memcpy(wilc_connected_ssid, pstrHostIFconnectAttr->bssid, ETH_ALEN); - PRINT_D(GENERIC_DBG, "save Bssid = %pM\n", - pstrHostIFconnectAttr->bssid); - PRINT_D(GENERIC_DBG, "save bssid = %pM\n", wilc_connected_ssid); - } result = wilc_send_config_pkt(vif, SET_CFG, strWIDList, u32WidsCount, @@ -1165,7 +1154,6 @@ static s32 Handle_Connect(struct wilc_vif *vif, result = -EFAULT; goto ERRORHANDLER; } else { - PRINT_D(GENERIC_DBG, "set HOST_IF_WAITING_CONN_RESP\n"); hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP; } @@ -1443,8 +1431,6 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, PRINT_ER("Driver handler is NULL\n"); return -ENODEV; } - PRINT_D(GENERIC_DBG, "Current State = %d,Received state = %d\n", - hif_drv->hif_state, pstrRcvdGnrlAsyncInfo->buffer[7]); if ((hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) || (hif_drv->hif_state == HOST_IF_CONNECTED) || @@ -1548,7 +1534,6 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, hif_drv->hif_state = HOST_IF_CONNECTED; - PRINT_D(GENERIC_DBG, "Obtaining an IP, Disable Scan\n"); wilc_optaining_ip = true; mod_timer(&wilc_during_ip_timer, jiffies + msecs_to_jiffies(10000)); @@ -2421,19 +2406,16 @@ static int Handle_RemainOnChan(struct wilc_vif *vif, } if (hif_drv->usr_scan_req.scan_result) { - PRINT_INFO(GENERIC_DBG, "Required to remain on chan while scanning return\n"); hif_drv->remain_on_ch_pending = 1; result = -EBUSY; goto ERRORHANDLER; } if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) { - PRINT_INFO(GENERIC_DBG, "Required to remain on chan while connecting return\n"); result = -EBUSY; goto ERRORHANDLER; } if (wilc_optaining_ip || wilc_connecting) { - PRINT_D(GENERIC_DBG, "[handle_scan]: Don't do obss scan until IP adresss is obtained\n"); result = -EBUSY; goto ERRORHANDLER; } @@ -2541,7 +2523,7 @@ static u32 Handle_ListenStateExpired(struct wilc_vif *vif, } P2P_LISTEN_STATE = 0; } else { - PRINT_D(GENERIC_DBG, "Not in listen state\n"); + netdev_dbg(vif->ndev, "Not in listen state\n"); result = -EFAULT; } @@ -2635,12 +2617,6 @@ static s32 Handle_DelAllRxBASessions(struct wilc_vif *vif, struct wid wid; char *ptr = NULL; - PRINT_D(GENERIC_DBG, "Delete Block Ack session with\nBSSID = %.2x:%.2x:%.2x\nTID=%d\n", - strHostIfBASessionInfo->bssid[0], - strHostIfBASessionInfo->bssid[1], - strHostIfBASessionInfo->bssid[2], - strHostIfBASessionInfo->tid); - wid.id = (u16)WID_DEL_ALL_RX_BA; wid.type = WID_STR; wid.val = kmalloc(BLOCK_ACK_REQ_SIZE, GFP_KERNEL); @@ -2711,13 +2687,10 @@ static int hostIFthread(void *pvArg) while (1) { wilc_mq_recv(&hif_msg_q, &msg, sizeof(struct host_if_msg), &u32Ret); vif = msg.vif; - if (msg.id == HOST_IF_MSG_EXIT) { - PRINT_D(GENERIC_DBG, "THREAD: Exiting HostIfThread\n"); + if (msg.id == HOST_IF_MSG_EXIT) break; - } if ((!wilc_initialized)) { - PRINT_D(GENERIC_DBG, "--WAIT--"); usleep_range(200 * 1000, 200 * 1000); wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); continue; @@ -3318,9 +3291,6 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, } if (hif_drv->hif_state < HOST_IF_CONNECTING) hif_drv->hif_state = HOST_IF_CONNECTING; - else - PRINT_D(GENERIC_DBG, "Don't set state to 'connecting' : %d\n", - hif_drv->hif_state); result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) { @@ -3870,8 +3840,6 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, return; hif_drv = vif->hif_drv; - PRINT_D(GENERIC_DBG, "Scan notification received %p\n", hif_drv); - if (!hif_drv || hif_drv == terminated_handle) return; @@ -4341,10 +4309,6 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) pNewJoinBssParam->opp_enabled = 0; } - PRINT_D(GENERIC_DBG, "P2P Dump\n"); - for (i = 0; i < pu8IEs[index + 7]; i++) - PRINT_D(GENERIC_DBG, " %x\n", pu8IEs[index + 9 + i]); - pNewJoinBssParam->cnt = pu8IEs[index + 11]; u16P2P_count = index + 12; diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index e702020b8e9d..c11830f71f38 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -253,8 +253,6 @@ void wilc_mac_indicate(struct wilc *wilc, int flag) } else { wilc->mac_status = status; } - } else if (flag == WILC_MAC_INDICATE_SCAN) { - PRINT_D(GENERIC_DBG, "Scanning ...\n"); } } diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h index 758633e73488..44573e2ea0ee 100644 --- a/drivers/staging/wilc1000/linux_wlan_common.h +++ b/drivers/staging/wilc1000/linux_wlan_common.h @@ -2,14 +2,12 @@ #define LINUX_WLAN_COMMON_H enum debug_region { - Generic_debug = 0, - Hostapd_debug, + Hostapd_debug = 0, CFG80211_debug, Init_debug, COMP = 0xFFFFFFFF, }; -#define GENERIC_DBG (1 << Generic_debug) #define HOSTAPD_DBG (1 << Hostapd_debug) #define CFG80211_DBG (1 << CFG80211_debug) #define INIT_DBG (1 << Init_debug) diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index 8d088249ea44..c5c8cc905630 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -24,9 +24,9 @@ static struct dentry *wilc_dir; * -------------------------------------------------------------------------------- */ -#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | CFG80211_DBG | INIT_DBG) +#define DBG_REGION_ALL (HOSTAPD_DBG | CFG80211_DBG | INIT_DBG) #define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR) -atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG | +atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | CFG80211_DBG | HOSTAPD_DBG); EXPORT_SYMBOL_GPL(WILC_REGION); atomic_t WILC_DEBUG_LEVEL = ATOMIC_INIT(ERR); @@ -136,7 +136,7 @@ struct wilc_debugfs_info_t { static struct wilc_debugfs_info_t debugfs_info[] = { { "wilc_debug_level", 0666, (DEBUG | ERR), FOPS(NULL, wilc_debug_level_read, wilc_debug_level_write, NULL), }, - { "wilc_debug_region", 0666, (INIT_DBG | GENERIC_DBG | CFG80211_DBG), FOPS(NULL, wilc_debug_region_read, wilc_debug_region_write, NULL), }, + { "wilc_debug_region", 0666, (INIT_DBG | CFG80211_DBG), FOPS(NULL, wilc_debug_region_read, wilc_debug_region_write, NULL), }, }; static int __init wilc_debugfs_init(void) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 35c39c66af4d..bf264d3657be 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -317,7 +317,6 @@ static void remove_network_from_shadow(unsigned long arg) static void clear_duringIP(unsigned long arg) { - PRINT_D(GENERIC_DBG, "GO:IP Obtained , enable scan\n"); wilc_optaining_ip = false; } @@ -1567,7 +1566,6 @@ static void WILC_WFI_CfgParseRxAction(u8 *buf, u32 len) } if (wlan_channel != INVALID_CHANNEL) { if (channel_list_attr_index) { - PRINT_D(GENERIC_DBG, "Modify channel list attribute\n"); for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) { if (buf[i] == 0x51) { for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) { @@ -1579,7 +1577,6 @@ static void WILC_WFI_CfgParseRxAction(u8 *buf, u32 len) } if (op_channel_attr_index) { - PRINT_D(GENERIC_DBG, "Modify operating channel attribute\n"); buf[op_channel_attr_index + 6] = 0x51; buf[op_channel_attr_index + 7] = wlan_channel; } @@ -1609,7 +1606,6 @@ static void WILC_WFI_CfgParseTxAction(u8 *buf, u32 len, bool bOperChan, u8 iftyp } if (wlan_channel != INVALID_CHANNEL && bOperChan) { if (channel_list_attr_index) { - PRINT_D(GENERIC_DBG, "Modify channel list attribute\n"); for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) { if (buf[i] == 0x51) { for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) { @@ -1621,7 +1617,6 @@ static void WILC_WFI_CfgParseTxAction(u8 *buf, u32 len, bool bOperChan, u8 iftyp } if (op_channel_attr_index) { - PRINT_D(GENERIC_DBG, "Modify operating channel attribute\n"); buf[op_channel_attr_index + 6] = 0x51; buf[op_channel_attr_index + 7] = wlan_channel; } @@ -1645,41 +1640,29 @@ void WILC_WFI_p2p_rx (struct net_device *dev, u8 *buff, u32 size) if (pkt_offset & IS_MANAGMEMENT_CALLBACK) { if (buff[FRAME_TYPE_ID] == IEEE80211_STYPE_PROBE_RESP) { - PRINT_D(GENERIC_DBG, "Probe response ACK\n"); cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL); return; } else { - if (pkt_offset & IS_MGMT_STATUS_SUCCES) { - PRINT_D(GENERIC_DBG, "Success Ack - Action frame category: %x Action Subtype: %d Dialog T: %x OR %x\n", buff[ACTION_CAT_ID], buff[ACTION_SUBTYPE_ID], - buff[ACTION_SUBTYPE_ID + 1], buff[P2P_PUB_ACTION_SUBTYPE + 1]); + if (pkt_offset & IS_MGMT_STATUS_SUCCES) cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL); - } else { - PRINT_D(GENERIC_DBG, "Fail Ack - Action frame category: %x Action Subtype: %d Dialog T: %x OR %x\n", buff[ACTION_CAT_ID], buff[ACTION_SUBTYPE_ID], - buff[ACTION_SUBTYPE_ID + 1], buff[P2P_PUB_ACTION_SUBTYPE + 1]); + else cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, false, GFP_KERNEL); - } return; } } else { - PRINT_D(GENERIC_DBG, "Rx Frame Type:%x\n", buff[FRAME_TYPE_ID]); - s32Freq = ieee80211_channel_to_frequency(curr_channel, IEEE80211_BAND_2GHZ); if (ieee80211_is_action(buff[FRAME_TYPE_ID])) { - PRINT_D(GENERIC_DBG, "Rx Action Frame Type: %x %x\n", buff[ACTION_SUBTYPE_ID], buff[P2P_PUB_ACTION_SUBTYPE]); - if (priv->bCfgScanning && time_after_eq(jiffies, (unsigned long)pstrWFIDrv->p2p_timeout)) { - PRINT_D(GENERIC_DBG, "Receiving action frames from wrong channels\n"); + netdev_dbg(dev, "Receiving action wrong ch\n"); return; } if (buff[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) { switch (buff[ACTION_SUBTYPE_ID]) { case GAS_INTIAL_REQ: - PRINT_D(GENERIC_DBG, "GAS INITIAL REQ %x\n", buff[ACTION_SUBTYPE_ID]); break; case GAS_INTIAL_RSP: - PRINT_D(GENERIC_DBG, "GAS INITIAL RSP %x\n", buff[ACTION_SUBTYPE_ID]); break; case PUBLIC_ACT_VENDORSPEC: @@ -1690,7 +1673,6 @@ void WILC_WFI_p2p_rx (struct net_device *dev, u8 *buff, u32 size) if (!memcmp(p2p_vendor_spec, &buff[i], 6)) { p2p_recv_random = buff[i + 6]; wilc_ie = true; - PRINT_D(GENERIC_DBG, "WILC Vendor specific IE:%02x\n", p2p_recv_random); break; } } @@ -1707,20 +1689,19 @@ void WILC_WFI_p2p_rx (struct net_device *dev, u8 *buff, u32 size) } } } else { - PRINT_D(GENERIC_DBG, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random); + netdev_dbg(dev, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random); } } if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP) && (wilc_ie)) { - PRINT_D(GENERIC_DBG, "Sending P2P to host without extra elemnt\n"); cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0); return; } break; default: - PRINT_D(GENERIC_DBG, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buff[ACTION_SUBTYPE_ID]); + netdev_dbg(dev, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buff[ACTION_SUBTYPE_ID]); break; } } @@ -1761,17 +1742,12 @@ static void WILC_WFI_RemainOnChannelExpired(void *pUserVoid, u32 u32SessionID) priv = (struct wilc_priv *)pUserVoid; if (u32SessionID == priv->strRemainOnChanParams.u32ListenSessionID) { - PRINT_D(GENERIC_DBG, "Remain on channel expired\n"); - priv->bInP2PlistenState = false; cfg80211_remain_on_channel_expired(priv->wdev, priv->strRemainOnChanParams.u64ListenCookie, priv->strRemainOnChanParams.pstrListenChan, GFP_KERNEL); - } else { - PRINT_D(GENERIC_DBG, "Received ID 0x%x Expected ID 0x%x (No match)\n", u32SessionID - , priv->strRemainOnChanParams.u32ListenSessionID); } } @@ -1787,11 +1763,8 @@ static int remain_on_channel(struct wiphy *wiphy, priv = wiphy_priv(wiphy); vif = netdev_priv(priv->dev); - PRINT_D(GENERIC_DBG, "Remaining on channel %d\n", chan->hw_value); - - if (wdev->iftype == NL80211_IFTYPE_AP) { - PRINT_D(GENERIC_DBG, "Required remain-on-channel while in AP mode"); + netdev_dbg(vif->ndev, "Required while in AP mode\n"); return s32Error; } @@ -1868,34 +1841,22 @@ static int mgmt_tx(struct wiphy *wiphy, if (ieee80211_is_probe_resp(mgmt->frame_control)) { - PRINT_D(GENERIC_DBG, "TX: Probe Response\n"); - PRINT_D(GENERIC_DBG, "Setting channel: %d\n", chan->hw_value); wilc_set_mac_chnl_num(vif, chan->hw_value); curr_channel = chan->hw_value; } else if (ieee80211_is_action(mgmt->frame_control)) { - PRINT_D(GENERIC_DBG, "ACTION FRAME:%x\n", (u16)mgmt->frame_control); - - if (buf[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) { if (buf[ACTION_SUBTYPE_ID] != PUBLIC_ACT_VENDORSPEC || buf[P2P_PUB_ACTION_SUBTYPE] != GO_NEG_CONF) { - PRINT_D(GENERIC_DBG, "Setting channel: %d\n", chan->hw_value); wilc_set_mac_chnl_num(vif, chan->hw_value); curr_channel = chan->hw_value; } switch (buf[ACTION_SUBTYPE_ID]) { case GAS_INTIAL_REQ: - { - PRINT_D(GENERIC_DBG, "GAS INITIAL REQ %x\n", buf[ACTION_SUBTYPE_ID]); break; - } case GAS_INTIAL_RSP: - { - PRINT_D(GENERIC_DBG, "GAS INITIAL RSP %x\n", buf[ACTION_SUBTYPE_ID]); break; - } case PUBLIC_ACT_VENDORSPEC: { @@ -1910,8 +1871,6 @@ static int mgmt_tx(struct wiphy *wiphy, if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) { if (p2p_local_random > p2p_recv_random) { - PRINT_D(GENERIC_DBG, "LOCAL WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random); - for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < len; i++) { if (buf[i] == P2PELEM_ATTR_ID && !(memcmp(p2p_oui, &buf[i + 2], 4))) { if (buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP) @@ -1927,13 +1886,11 @@ static int mgmt_tx(struct wiphy *wiphy, mgmt_tx->buff[len + sizeof(p2p_vendor_spec)] = p2p_local_random; mgmt_tx->size = buf_len; } - } else { - PRINT_D(GENERIC_DBG, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random); } } } else { - PRINT_D(GENERIC_DBG, "Not a P2P public action frame\n"); + netdev_dbg(vif->ndev, "Not a P2P public action frame\n"); } break; @@ -1941,24 +1898,18 @@ static int mgmt_tx(struct wiphy *wiphy, default: { - PRINT_D(GENERIC_DBG, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buf[ACTION_SUBTYPE_ID]); + netdev_dbg(vif->ndev, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buf[ACTION_SUBTYPE_ID]); break; } } } - PRINT_D(GENERIC_DBG, "TX: ACTION FRAME Type:%x : Chan:%d\n", buf[ACTION_SUBTYPE_ID], chan->hw_value); pstrWFIDrv->p2p_timeout = (jiffies + msecs_to_jiffies(wait)); - - PRINT_D(GENERIC_DBG, "Current Jiffies: %lu Timeout:%llu\n", - jiffies, pstrWFIDrv->p2p_timeout); } wilc_wlan_txq_add_mgmt_pkt(wdev->netdev, mgmt_tx, mgmt_tx->buff, mgmt_tx->size, WILC_WFI_mgmt_tx_complete); - } else { - PRINT_D(GENERIC_DBG, "This function transmits only management frames\n"); } return 0; } @@ -1972,9 +1923,6 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy, priv = wiphy_priv(wiphy); pstrWFIDrv = (struct host_if_drv *)priv->hif_drv; - - - PRINT_D(GENERIC_DBG, "Tx Cancel wait :%lu\n", jiffies); pstrWFIDrv->p2p_timeout = jiffies; if (!priv->bInP2PlistenState) { @@ -2001,7 +1949,6 @@ void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, if (!frame_type) return; - PRINT_D(GENERIC_DBG, "Frame registering Frame Type: %x: Boolean: %d\n", frame_type, reg); switch (frame_type) { case PROBE_REQ: { @@ -2023,10 +1970,8 @@ void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, } } - if (!wl->initialized) { - PRINT_D(GENERIC_DBG, "Return since mac is closed\n"); + if (!wl->initialized) return; - } wilc_frame_register(vif, frame_type, reg); } @@ -2099,7 +2044,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, wilc_ie = false; wilc_optaining_ip = false; del_timer(&wilc_during_ip_timer); - PRINT_D(GENERIC_DBG, "Changing virtual interface, enable scan\n"); switch (type) { case NL80211_IFTYPE_STATION: @@ -2148,8 +2092,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, break; case NL80211_IFTYPE_P2P_GO: - PRINT_D(GENERIC_DBG, "start duringIP timer\n"); - wilc_optaining_ip = true; mod_timer(&wilc_during_ip_timer, jiffies + msecs_to_jiffies(during_ip_time)); diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 46e66475dbc8..98b21d492720 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -713,8 +713,6 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) break; if (entries == 0) { - PRINT_WRN(GENERIC_DBG, "[wilc txq]: no more buffer in the chip (reg: %08x), retry later [[ %d, %x ]]\n", reg, i, vmm_table[i - 1]); - ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, ®); if (!ret) break; diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c index 3b3065b4d734..2bb684a3e23b 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.c +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c @@ -270,13 +270,12 @@ static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size) static void wilc_wlan_parse_response_frame(u8 *info, int size) { u32 wid, len = 0, i = 0; - static int seq; while (size > 0) { i = 0; wid = info[0] | (info[1] << 8); wid = cpu_to_le32(wid); - PRINT_INFO(GENERIC_DBG, "Processing response for %d seq %d\n", wid, seq++); + switch ((wid >> 12) & 0x7) { case WID_CHAR: do { @@ -329,10 +328,6 @@ static void wilc_wlan_parse_response_frame(u8 *info, int size) if (wid == WID_SITE_SURVEY_RESULTS) { static int toggle; - PRINT_INFO(GENERIC_DBG, "Site survey results received[%d]\n", - size); - - PRINT_INFO(GENERIC_DBG, "Site survey results value[%d]toggle[%d]\n", size, toggle); i += toggle; toggle ^= 1; } @@ -361,7 +356,7 @@ static int wilc_wlan_parse_info_frame(u8 *info, int size) wid = info[0] | (info[1] << 8); len = info[2]; - PRINT_INFO(GENERIC_DBG, "Status Len = %d Id= %d\n", len, wid); + if ((len == 1) && (wid == WID_STATUS)) { pd->mac_status = info[3]; type = WILC_CFG_RSP_STATUS; @@ -475,8 +470,6 @@ int wilc_wlan_cfg_get_wid_value(u16 wid, u8 *buffer, u32 buffer_size) if (g_cfg_str[i].id == WID_SITE_SURVEY_RESULTS) { static int toggle; - PRINT_INFO(GENERIC_DBG, "Site survey results value[%d]\n", - size); i += toggle; toggle ^= 1; -- cgit v1.2.3 From e0990c159f658db3fb6e32b76c449d33e718ed24 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:31 +0900 Subject: staging: wilc1000: remove warnings line over 80 characters This patch removes the warnings reported by checkpatch.pl for line over 80 characters. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index d481719a97db..3a7658617014 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -4,7 +4,7 @@ #include #include #define TAG_PARAM_OFFSET (MAC_HDR_LEN + TIME_STAMP_LEN + \ - BEACON_INTERVAL_LEN + CAP_INFO_LEN) + BEACON_INTERVAL_LEN + CAP_INFO_LEN) enum basic_frame_type { FRAME_TYPE_CONTROL = 0x04, @@ -337,8 +337,10 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tim_elm = get_tim_elm(msa, rx_len + FCS_LEN, index); if (tim_elm) network_info->dtim_period = tim_elm[3]; - ies = &msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN]; - ies_len = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); + ies = &msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + + CAP_INFO_LEN]; + ies_len = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN + + BEACON_INTERVAL_LEN + CAP_INFO_LEN); if (ies_len > 0) { network_info->ies = kmemdup(ies, ies_len, GFP_KERNEL); @@ -373,7 +375,8 @@ s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, connect_resp_info->assoc_id = get_asoc_id(buffer); ies = &buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN]; - ies_len = assoc_resp_len - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN); + ies_len = assoc_resp_len - (CAP_INFO_LEN + STATUS_CODE_LEN + + AID_LEN); connect_resp_info->ies = kmemdup(ies, ies_len, GFP_KERNEL); if (!connect_resp_info->ies) -- cgit v1.2.3 From 4168da71875c8aca823a78fa33f5481efa7dc36e Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 5 Feb 2016 10:35:11 +0900 Subject: staging: wilc1000: fix return type of wilc_hif_set_cfg This patch changes return type of wilc_hif_set_cfg from s32 to int. The result variable gets return value from wilc_mq_send that has data type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index abb20fb22963..e20621d29ea6 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3558,10 +3558,10 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, return result; } -s32 wilc_hif_set_cfg(struct wilc_vif *vif, +int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index c73a5c389297..395b68169363 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -337,7 +337,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t ies_len, wilc_scan_result scan_result, void *user_arg, struct hidden_network *hidden_network); -s32 wilc_hif_set_cfg(struct wilc_vif *vif, +int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler); s32 wilc_deinit(struct wilc_vif *vif); -- cgit v1.2.3 From 483ab2aa00c0570084abec6147d5165fcffd1ac4 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 5 Feb 2016 10:35:12 +0900 Subject: staging: wilc1000: rename pstrCfgParamVal in wilc_hif_set_cfg This patch renames pstrCfgParamVal to cfg_param to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index e20621d29ea6..2c64659b1aa7 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3559,7 +3559,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, } int wilc_hif_set_cfg(struct wilc_vif *vif, - struct cfg_param_val *pstrCfgParamVal) + struct cfg_param_val *cfg_param) { int result = 0; struct host_if_msg msg; @@ -3572,7 +3572,7 @@ int wilc_hif_set_cfg(struct wilc_vif *vif, memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_CFG_PARAMS; - msg.body.cfg_info.cfg_attr_info = *pstrCfgParamVal; + msg.body.cfg_info.cfg_attr_info = *cfg_param; msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 395b68169363..f08f115fb3dd 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -338,7 +338,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, size_t ies_len, wilc_scan_result scan_result, void *user_arg, struct hidden_network *hidden_network); int wilc_hif_set_cfg(struct wilc_vif *vif, - struct cfg_param_val *pstrCfgParamVal); + struct cfg_param_val *cfg_param); int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler); s32 wilc_deinit(struct wilc_vif *vif); int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, -- cgit v1.2.3 From 127a27c3fbe01b8b35e658b0b6f655be43290f95 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 5 Feb 2016 10:35:13 +0900 Subject: staging: wilc1000: fix return type of wilc_deinit This patch changes return type of wilc_deinit from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 2c64659b1aa7..ef7c90ff3af9 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3687,9 +3687,9 @@ _fail_: return result; } -s32 wilc_deinit(struct wilc_vif *vif) +int wilc_deinit(struct wilc_vif *vif) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index f08f115fb3dd..bfa4a41264f1 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -340,7 +340,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *cfg_param); int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler); -s32 wilc_deinit(struct wilc_vif *vif); +int wilc_deinit(struct wilc_vif *vif); int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, u32 head_len, u8 *head, u32 tail_len, u8 *tail); int wilc_del_beacon(struct wilc_vif *vif); -- cgit v1.2.3 From 8eb62f3f6d8e58ec1b0eedee73ddd371a80a1bd3 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 5 Feb 2016 10:35:14 +0900 Subject: staging: wilc1000: fix return error code of wilc_deinit It should be returned error code as -EFAULT instead of 0 when hif_drv is NULL. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index ef7c90ff3af9..c42286a7bab9 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3695,7 +3695,7 @@ int wilc_deinit(struct wilc_vif *vif) if (!hif_drv) { PRINT_ER("hif_drv = NULL\n"); - return 0; + return -EFAULT; } down(&hif_sema_deinit); -- cgit v1.2.3 From 6bb871b61e48fbfca36989a15da4fd599395c598 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Mon, 7 Dec 2015 10:58:37 -0500 Subject: staging: unisys: fix parenthesis in toolaction_show() Fix the only fixable parenthesis alignment issue in visorchipset.c. The rest are unworkable because of the length of the symbol names used. Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 07594f43853d..b29832657c7b 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -537,8 +537,8 @@ static ssize_t toolaction_show(struct device *dev, u8 tool_action; visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - tool_action), &tool_action, sizeof(u8)); + offsetof(struct spar_controlvm_channel_protocol, + tool_action), &tool_action, sizeof(u8)); return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action); } -- cgit v1.2.3 From 61dd330a284b7164eda3549ea3ec1bb53598a21e Mon Sep 17 00:00:00 2001 From: David Kershner Date: Fri, 15 Jan 2016 11:19:05 -0500 Subject: staging: unisys: Only process up to budget amount of responses >From napi documentation you should only process the amount your budget allows, if you go over it just wait for the next napi poll to continue. Signed-off-by: David Kershner Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visornic/visornic_main.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 05194707278a..2d51299825cf 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -36,6 +36,7 @@ * = 163840 bytes */ #define MAX_BUF 163840 +#define NAPI_WEIGHT 64 static int visornic_probe(struct visor_device *dev); static void visornic_remove(struct visor_device *dev); @@ -1613,14 +1614,12 @@ drain_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata) */ static void service_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata, - int *rx_work_done) + int *rx_work_done, int budget) { unsigned long flags; struct net_device *netdev; - /* TODO: CLIENT ACQUIRE -- Don't really need this at the - * moment */ - for (;;) { + while (*rx_work_done < budget) { if (!visorchannel_signalremove(devdata->dev->visorchannel, IOCHAN_FROM_IOPART, cmdrsp)) @@ -1709,7 +1708,7 @@ static int visornic_poll(struct napi_struct *napi, int budget) int rx_count = 0; send_rcv_posts_if_needed(devdata); - service_resp_queue(devdata->cmdrsp, devdata, &rx_count); + service_resp_queue(devdata->cmdrsp, devdata, &rx_count, budget); /* * If there aren't any more packets to receive @@ -1893,6 +1892,16 @@ static int visornic_probe(struct visor_device *dev) goto cleanup_napi_add; } + /* Let's start our threads to get responses */ + netif_napi_add(netdev, &devdata->napi, visornic_poll, NAPI_WEIGHT); + + /* + * Note: Interupts have to be enable before the while + * loop below because the napi routine is responsible for + * setting enab_dis_acked + */ + visorbus_enable_channel_interrupts(dev); + err = register_netdev(netdev); if (err) { dev_err(&dev->device, -- cgit v1.2.3 From 2c7e1d4e4b1dd8f843f2acce1ba879bef9b78f22 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Wed, 9 Dec 2015 20:57:05 +0530 Subject: staging: unisys: visorchipset.c fixed spacing around operator This patch fixes checkpatch.pl warning for visorchipset.c CHECK: spaces preferred around that '*' (ctx:VxV) +#define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128) Signed-off-by: Bhaktipriya Shridhar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index b29832657c7b..95a923e2b201 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -43,7 +43,7 @@ #define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1 #define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100 -#define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128) +#define MAX_CONTROLVM_PAYLOAD_BYTES (1024 * 128) #define VISORCHIPSET_MMAP_CONTROLCHANOFFSET 0x00000000 -- cgit v1.2.3 From 58e1e5425f0dea78dcd9ae56c0330fa4ada6c792 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 8 Dec 2015 13:07:01 -0800 Subject: Staging: unisys: fix potential format string leak Since "name" is always used directly, force "%s" for the kthread format string to avoid any potential format string leaks. Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorhba/visorhba_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index d5178b44ba8c..202bfabfec6c 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -167,7 +167,7 @@ static int visor_thread_start(struct visor_thread_info *thrinfo, { /* used to stop the thread */ init_completion(&thrinfo->has_stopped); - thrinfo->task = kthread_run(threadfn, thrcontext, name); + thrinfo->task = kthread_run(threadfn, thrcontext, "%s", name); if (IS_ERR(thrinfo->task)) { thrinfo->id = 0; return PTR_ERR(thrinfo->task); -- cgit v1.2.3 From 3025ee74cc56f76b04b264777888cdccb673104c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 7 Jan 2016 12:34:13 +0300 Subject: staging: unisys: remove some dead code queue_delayed_work() returns bool, not negative error codes. It returns false if the work has already been queued or true otherwise. Since we don't care about that, we can just remove the test. Signed-off-by: Dan Carpenter Signed-off-by: Benjamin Romer Acked-by: Don Zickus Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 95a923e2b201..f4c37dab9999 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -2310,13 +2310,8 @@ visorchipset_init(struct acpi_device *acpi_device) } most_recent_message_jiffies = jiffies; poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; - rc = queue_delayed_work(periodic_controlvm_workqueue, - &periodic_controlvm_work, poll_jiffies); - if (rc < 0) { - POSTCODE_LINUX_2(QUEUE_DELAYED_WORK_PC, - DIAG_SEVERITY_ERR); - goto cleanup; - } + queue_delayed_work(periodic_controlvm_workqueue, + &periodic_controlvm_work, poll_jiffies); visorchipset_platform_device.dev.devt = major_dev; if (platform_device_register(&visorchipset_platform_device) < 0) { -- cgit v1.2.3 From 9305b0fe0985eb2d277df29f3a962828b00dd7cc Mon Sep 17 00:00:00 2001 From: Hugo Camboulive Date: Mon, 25 Jan 2016 20:22:16 +0000 Subject: staging: unisys: visornic: remove useless memset alloc_etherdev() calls alloc_netdev_mqs(), which already uses kzalloc/vzalloc. This clears a sparse warning : drivers/staging/unisys/visornic/visornic_main.c:1366:15: warning: memset with byte count of 1460112 Signed-off-by: Hugo Camboulive Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visornic/visornic_main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 2d51299825cf..9b3eb95ed183 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -1364,7 +1364,6 @@ devdata_initialize(struct visornic_devdata *devdata, struct visor_device *dev) { if (!devdata) return NULL; - memset(devdata, '\0', sizeof(struct visornic_devdata)); devdata->dev = dev; devdata->incarnation_id = get_jiffies_64(); return devdata; -- cgit v1.2.3 From a191176441cdb4e34e3b84d76bf3ee6f3756954e Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:42 +0100 Subject: staging: most: remove unnecessary keep_mbo variable The MBO pointer stacked_mbo and the boolean variable keep_mbo are always changed together and therefore provide the same information. This patch removes keep_mbo and uses stacked_mbo instead. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index dc3fb25b52aa..6f70ed715064 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -39,7 +39,6 @@ struct aim_channel { struct most_channel_config *cfg; unsigned int channel_id; dev_t devno; - bool keep_mbo; unsigned int mbo_offs; struct mbo *stacked_mbo; DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *)); @@ -136,7 +135,7 @@ static int aim_close(struct inode *inode, struct file *filp) while (kfifo_out((struct kfifo *)&channel->fifo, &mbo, 1)) most_put_mbo(mbo); - if (channel->keep_mbo) + if (channel->stacked_mbo) most_put_mbo(channel->stacked_mbo); ret = most_stop_channel(channel->iface, channel->channel_id, &cdev_aim); atomic_dec(&channel->access_ref); @@ -227,9 +226,8 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) struct mbo *mbo; struct aim_channel *channel = filp->private_data; - if (channel->keep_mbo) { + if (channel->stacked_mbo) { mbo = channel->stacked_mbo; - channel->keep_mbo = false; goto start_copy; } while ((!kfifo_out(&channel->fifo, &mbo, 1)) && (channel->dev)) { @@ -249,9 +247,6 @@ start_copy: return -EIO; } - if (count < mbo->processed_length) - channel->keep_mbo = true; - proc_len = min((int)count, (int)(mbo->processed_length - channel->mbo_offs)); @@ -261,12 +256,13 @@ start_copy: retval = not_copied ? proc_len - not_copied : proc_len; - if (channel->keep_mbo) { + if (count < mbo->processed_length) { channel->mbo_offs = retval; channel->stacked_mbo = mbo; } else { most_put_mbo(mbo); channel->mbo_offs = 0; + channel->stacked_mbo = NULL; } mutex_unlock(&channel->io_mutex); return retval; -- cgit v1.2.3 From f9f24870d84d4c77cbb330df1e1112fd97a9e12c Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:43 +0100 Subject: staging: most: rename variables This patch renames some variables for better readability. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 6f70ed715064..bff891fc0a5d 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -221,8 +221,8 @@ error: static ssize_t aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) { - ssize_t retval; - size_t not_copied, proc_len; + ssize_t copied; + size_t to_copy, not_copied; struct mbo *mbo; struct aim_channel *channel = filp->private_data; @@ -247,17 +247,17 @@ start_copy: return -EIO; } - proc_len = min((int)count, - (int)(mbo->processed_length - channel->mbo_offs)); + to_copy = min((int)count, + (int)(mbo->processed_length - channel->mbo_offs)); not_copied = copy_to_user(buf, mbo->virt_address + channel->mbo_offs, - proc_len); + to_copy); - retval = not_copied ? proc_len - not_copied : proc_len; + copied = not_copied ? to_copy - not_copied : to_copy; if (count < mbo->processed_length) { - channel->mbo_offs = retval; + channel->mbo_offs = copied; channel->stacked_mbo = mbo; } else { most_put_mbo(mbo); @@ -265,7 +265,7 @@ start_copy: channel->stacked_mbo = NULL; } mutex_unlock(&channel->io_mutex); - return retval; + return copied; } static inline bool __must_check IS_ERR_OR_FALSE(int x) -- cgit v1.2.3 From 4aa575a91e637ab1c5e89c91bb59e91e518cb5f6 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:44 +0100 Subject: staging: most: simplify expression This patch replaces the ternary ?-operator with a way simpler subtraction. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index bff891fc0a5d..b29307820eda 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -254,7 +254,7 @@ start_copy: mbo->virt_address + channel->mbo_offs, to_copy); - copied = not_copied ? to_copy - not_copied : to_copy; + copied = to_copy - not_copied; if (count < mbo->processed_length) { channel->mbo_offs = copied; -- cgit v1.2.3 From 06e7ecf287e7d2414c381d5312d6c81e79a7520d Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:45 +0100 Subject: staging: most: unify types This patch unifies variable types to get less castings. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index b29307820eda..4bf0322a99eb 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -39,7 +39,7 @@ struct aim_channel { struct most_channel_config *cfg; unsigned int channel_id; dev_t devno; - unsigned int mbo_offs; + size_t mbo_offs; struct mbo *stacked_mbo; DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *)); atomic_t access_ref; @@ -221,8 +221,7 @@ error: static ssize_t aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) { - ssize_t copied; - size_t to_copy, not_copied; + size_t to_copy, not_copied, copied; struct mbo *mbo; struct aim_channel *channel = filp->private_data; @@ -247,8 +246,7 @@ start_copy: return -EIO; } - to_copy = min((int)count, - (int)(mbo->processed_length - channel->mbo_offs)); + to_copy = min(count, (size_t)mbo->processed_length - channel->mbo_offs); not_copied = copy_to_user(buf, mbo->virt_address + channel->mbo_offs, -- cgit v1.2.3 From e6d6cbe303c5cfa581842ce4ba4899ba313931ab Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:46 +0100 Subject: staging: most: use min_t This patch replaces min with min_t. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 4bf0322a99eb..6ee4eb2177bd 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -246,7 +246,9 @@ start_copy: return -EIO; } - to_copy = min(count, (size_t)mbo->processed_length - channel->mbo_offs); + to_copy = min_t(size_t, + count, + mbo->processed_length - channel->mbo_offs); not_copied = copy_to_user(buf, mbo->virt_address + channel->mbo_offs, -- cgit v1.2.3 From 8a742f785bbda4a60288325e42953515c2320b50 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:47 +0100 Subject: staging: most: fix mbo leak This patch fixes a potential MBO leak in case function aim_read() exits right after the MBO has been fetched from kfifo and before it has been saved to the variable stacked_mbo. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 6ee4eb2177bd..86194ce51472 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -237,6 +237,7 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) (!channel->dev)))) return -ERESTARTSYS; } + channel->stacked_mbo = mbo; start_copy: /* make sure we don't submit to gone devices */ @@ -258,7 +259,6 @@ start_copy: if (count < mbo->processed_length) { channel->mbo_offs = copied; - channel->stacked_mbo = mbo; } else { most_put_mbo(mbo); channel->mbo_offs = 0; -- cgit v1.2.3 From 9e2f2c4fb93a12e20f6bd82e1b9bf3df36236198 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:48 +0100 Subject: staging: most: fix tracking of MBO offset This patch increments mbo_offs by the number of bytes that have been copied and resets it in case a complete mbo has been transferred to user buffer. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 86194ce51472..0141293b4bf5 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -257,9 +257,8 @@ start_copy: copied = to_copy - not_copied; - if (count < mbo->processed_length) { - channel->mbo_offs = copied; - } else { + channel->mbo_offs += copied; + if (channel->mbo_offs >= mbo->processed_length) { most_put_mbo(mbo); channel->mbo_offs = 0; channel->stacked_mbo = NULL; -- cgit v1.2.3 From 560dca25cd038ae932c8f2d42bf991968faf258a Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:49 +0100 Subject: staging: most: use readl and writel functions This patch makes use of functions readl and writel instead of the __raw_* variants. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/hdm-dim2/dim2_hdm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index 327d738c7194..48ce7ab1bb03 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -140,7 +140,7 @@ bool dim2_sysfs_get_state_cb(void) */ u32 dimcb_io_read(u32 *ptr32) { - return __raw_readl(ptr32); + return readl(ptr32); } /** @@ -150,7 +150,7 @@ u32 dimcb_io_read(u32 *ptr32) */ void dimcb_io_write(u32 *ptr32, u32 value) { - __raw_writel(value, ptr32); + writel(value, ptr32); } /** -- cgit v1.2.3 From 9ce039a08add9c4212539d303134b579064a2be5 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:50 +0100 Subject: staging: most: remove function destroy_most_c_obj This patch removes the function destroy_most_c_obj and executes its code within function destroy_most_inst_obj. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 38 +++++++++++++----------------------- 1 file changed, 14 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index ed1ed25b6d1d..8be6cdcf4008 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -551,29 +551,6 @@ create_most_c_obj(const char *name, struct kobject *parent) return c; } -/** - * destroy_most_c_obj - channel release function - * @c: pointer to channel object - * - * This decrements the reference counter of the channel object. - * If the reference count turns zero, its release function is called. - */ -static void destroy_most_c_obj(struct most_c_obj *c) -{ - if (c->aim0.ptr) - c->aim0.ptr->disconnect_channel(c->iface, c->channel_id); - if (c->aim1.ptr) - c->aim1.ptr->disconnect_channel(c->iface, c->channel_id); - c->aim0.ptr = NULL; - c->aim1.ptr = NULL; - - mutex_lock(&deregister_mutex); - flush_trash_fifo(c); - flush_channel_fifos(c); - mutex_unlock(&deregister_mutex); - kobject_put(&c->kobj); -} - /* ___ ___ * ___I N S T A N C E___ */ @@ -766,7 +743,20 @@ static void destroy_most_inst_obj(struct most_inst_obj *inst) * reference count of the inst->kobj */ list_for_each_entry_safe(c, tmp, &inst->channel_list, list) { - destroy_most_c_obj(c); + if (c->aim0.ptr) + c->aim0.ptr->disconnect_channel(c->iface, + c->channel_id); + if (c->aim1.ptr) + c->aim1.ptr->disconnect_channel(c->iface, + c->channel_id); + c->aim0.ptr = NULL; + c->aim1.ptr = NULL; + + mutex_lock(&deregister_mutex); + flush_trash_fifo(c); + flush_channel_fifos(c); + mutex_unlock(&deregister_mutex); + kobject_put(&c->kobj); } kobject_put(&inst->kobj); } -- cgit v1.2.3 From b7382d44a530cd8c1bc156ddc123e3f09ae68746 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:51 +0100 Subject: staging: most: add missing call to ida_simple_remove This patch adds two missing calls to function ida_simpel_remove. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 8be6cdcf4008..995987d352a8 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -1752,6 +1752,7 @@ struct kobject *most_register_interface(struct most_interface *iface) inst = create_most_inst_obj(name); if (!inst) { pr_info("Failed to allocate interface instance\n"); + ida_simple_remove(&mdev_id, id); return ERR_PTR(-ENOMEM); } @@ -1808,6 +1809,7 @@ struct kobject *most_register_interface(struct most_interface *iface) free_instance: pr_info("Failed allocate channel(s)\n"); list_del(&inst->list); + ida_simple_remove(&mdev_id, id); destroy_most_inst_obj(inst); return ERR_PTR(-ENOMEM); } -- cgit v1.2.3 From 44fe57818b8038ece1d6089c5075a5c73ad7e18a Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:52 +0100 Subject: staging: most: move call to disconnect_channel callback This patch invokes AIM's disconnect_channel callback before the corresponding pointers are re-initialized to NULL. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 995987d352a8..d5ef61df1f9b 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -1046,12 +1046,12 @@ static ssize_t store_remove_link(struct most_aim_obj *aim_obj, if (IS_ERR(c)) return -ENODEV; + if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id)) + return -EIO; if (c->aim0.ptr == aim_obj->driver) c->aim0.ptr = NULL; if (c->aim1.ptr == aim_obj->driver) c->aim1.ptr = NULL; - if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id)) - return -EIO; return len; } -- cgit v1.2.3 From 42e252a65d3bbd36106b3e243cb1e11136cecdf4 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:53 +0100 Subject: staging: most: move initialization of pointer This patch makes function store_add_link initialize the pointer to an AIM right before the channel is probed. It is needed, the AIM may already call most_start_channel while probe_channel is still running. At this point the pointer to the AIM must not be NULL. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index d5ef61df1f9b..21c550ccfe78 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -996,11 +996,14 @@ static ssize_t store_add_link(struct most_aim_obj *aim_obj, else return -ENOSPC; + *aim_ptr = aim_obj->driver; ret = aim_obj->driver->probe_channel(c->iface, c->channel_id, &c->cfg, &c->kobj, mdev_devnod); - if (ret) + if (ret) { + *aim_ptr = NULL; return ret; - *aim_ptr = aim_obj->driver; + } + return len; } -- cgit v1.2.3 From 245dc23d2368beada77d9bc26f3292fa34931655 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:54 +0100 Subject: staging: most: move mutex This patch removes mutex from code that doesn't need any locking. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 21c550ccfe78..ae1b5778b24b 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -1830,15 +1830,14 @@ void most_deregister_interface(struct most_interface *iface) struct most_inst_obj *i = iface->priv; struct most_c_obj *c; - mutex_lock(&deregister_mutex); if (unlikely(!i)) { pr_info("Bad Interface\n"); - mutex_unlock(&deregister_mutex); return; } pr_info("deregistering MOST device %s (%s)\n", i->kobj.name, iface->description); + mutex_lock(&deregister_mutex); atomic_set(&i->tainted, 1); mutex_unlock(&deregister_mutex); -- cgit v1.2.3 From a0fceb1fb853585dcc7419944eb0ca385bdc497e Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:55 +0100 Subject: staging: most: move channel disconnect to function most_deregister_interface This patch moves the code that disconnects linked channels. It is needed to have cleaning things up done right. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index ae1b5778b24b..782747a50477 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -738,20 +738,7 @@ static void destroy_most_inst_obj(struct most_inst_obj *inst) { struct most_c_obj *c, *tmp; - /* need to destroy channels first, since - * each channel incremented the - * reference count of the inst->kobj - */ list_for_each_entry_safe(c, tmp, &inst->channel_list, list) { - if (c->aim0.ptr) - c->aim0.ptr->disconnect_channel(c->iface, - c->channel_id); - if (c->aim1.ptr) - c->aim1.ptr->disconnect_channel(c->iface, - c->channel_id); - c->aim0.ptr = NULL; - c->aim1.ptr = NULL; - mutex_lock(&deregister_mutex); flush_trash_fifo(c); flush_channel_fifos(c); @@ -1837,6 +1824,17 @@ void most_deregister_interface(struct most_interface *iface) pr_info("deregistering MOST device %s (%s)\n", i->kobj.name, iface->description); + list_for_each_entry(c, &i->channel_list, list) { + if (c->aim0.ptr) + c->aim0.ptr->disconnect_channel(c->iface, + c->channel_id); + if (c->aim1.ptr) + c->aim1.ptr->disconnect_channel(c->iface, + c->channel_id); + c->aim0.ptr = NULL; + c->aim1.ptr = NULL; + } + mutex_lock(&deregister_mutex); atomic_set(&i->tainted, 1); mutex_unlock(&deregister_mutex); -- cgit v1.2.3 From 6ed90e3622d1b3eff2433cc0c31fdcfc3cd2a23f Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:56 +0100 Subject: staging: most: remove tainted flag This patch removes the atomic tainted flag. It is needed to get rid of logical overhead. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 782747a50477..58e288b74b1b 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -74,7 +74,6 @@ struct most_c_obj { struct most_inst_obj { int dev_id; - atomic_t tainted; struct most_interface *iface; struct list_head channel_list; struct most_c_obj *channel[MAX_CHANNELS]; @@ -1299,18 +1298,10 @@ _exit: */ int most_submit_mbo(struct mbo *mbo) { - struct most_c_obj *c; - struct most_inst_obj *i; - if (unlikely((!mbo) || (!mbo->context))) { pr_err("Bad MBO or missing channel reference\n"); return -EINVAL; } - c = mbo->context; - i = c->inst; - - if (unlikely(atomic_read(&i->tainted))) - return -ENODEV; nq_hdm_mbo(mbo); return 0; @@ -1436,17 +1427,8 @@ EXPORT_SYMBOL_GPL(most_get_mbo); */ void most_put_mbo(struct mbo *mbo) { - struct most_c_obj *c; - struct most_inst_obj *i; - - c = mbo->context; - i = c->inst; + struct most_c_obj *c = mbo->context; - if (unlikely(atomic_read(&i->tainted))) { - mbo->status = MBO_E_CLOSE; - trash_mbo(mbo); - return; - } if (c->cfg.direction == MOST_CH_TX) { arm_mbo(mbo); return; @@ -1602,14 +1584,6 @@ int most_stop_channel(struct most_interface *iface, int id, c->hdm_enqueue_task = NULL; mutex_unlock(&c->stop_task_mutex); - mutex_lock(&deregister_mutex); - if (atomic_read(&c->inst->tainted)) { - mutex_unlock(&deregister_mutex); - mutex_unlock(&c->start_mutex); - return -ENODEV; - } - mutex_unlock(&deregister_mutex); - if (iface->mod && modref) { module_put(iface->mod); modref--; @@ -1750,7 +1724,6 @@ struct kobject *most_register_interface(struct most_interface *iface) INIT_LIST_HEAD(&inst->channel_list); inst->iface = iface; inst->dev_id = id; - atomic_set(&inst->tainted, 0); list_add_tail(&inst->list, &instance_list); for (i = 0; i < iface->num_channels; i++) { @@ -1835,10 +1808,6 @@ void most_deregister_interface(struct most_interface *iface) c->aim1.ptr = NULL; } - mutex_lock(&deregister_mutex); - atomic_set(&i->tainted, 1); - mutex_unlock(&deregister_mutex); - while (modref) { if (iface->mod && modref) module_put(iface->mod); -- cgit v1.2.3 From 9cda3007ab9c87d3977fc84e7db73e021ba048ac Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:57 +0100 Subject: staging: most: remove reference counter This patch removes the unnecessary reference conter mod_ref. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 58e288b74b1b..daae42d0238c 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -35,7 +35,6 @@ static struct class *most_class; static struct device *class_glue_dir; static struct ida mdev_id; -static int modref; static int dummy_num_buffers; struct most_c_aim_obj { @@ -1508,7 +1507,6 @@ int most_start_channel(struct most_interface *iface, int id, mutex_unlock(&c->start_mutex); return -ENOLCK; } - modref++; c->cfg.extra_len = 0; if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) { @@ -1550,7 +1548,6 @@ out: error: module_put(iface->mod); - modref--; mutex_unlock(&c->start_mutex); return ret; } @@ -1584,10 +1581,8 @@ int most_stop_channel(struct most_interface *iface, int id, c->hdm_enqueue_task = NULL; mutex_unlock(&c->stop_task_mutex); - if (iface->mod && modref) { + if (iface->mod) module_put(iface->mod); - modref--; - } c->is_poisoned = true; if (c->iface->poison_channel(c->iface, c->channel_id)) { @@ -1808,12 +1803,6 @@ void most_deregister_interface(struct most_interface *iface) c->aim1.ptr = NULL; } - while (modref) { - if (iface->mod && modref) - module_put(iface->mod); - modref--; - } - list_for_each_entry(c, &i->channel_list, list) { if (c->aim0.refs + c->aim1.refs <= 0) continue; -- cgit v1.2.3 From b522e61fb6329b68e6da8f237f21fc83a1d8ace2 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:58 +0100 Subject: staging: most: remove code to destroy channel This patch removes unnecessary code to destroy channel objects. It is needed, because function most_stop_channel, which is indirectly triggered by function most_deregister_interface, already destroys the channels. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index daae42d0238c..31ea3a5e485e 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -1803,19 +1803,6 @@ void most_deregister_interface(struct most_interface *iface) c->aim1.ptr = NULL; } - list_for_each_entry(c, &i->channel_list, list) { - if (c->aim0.refs + c->aim1.refs <= 0) - continue; - - mutex_lock(&c->stop_task_mutex); - if (c->hdm_enqueue_task) - kthread_stop(c->hdm_enqueue_task); - c->hdm_enqueue_task = NULL; - mutex_unlock(&c->stop_task_mutex); - - if (iface->poison_channel(iface, c->channel_id)) - pr_err("Can't poison channel %d\n", c->channel_id); - } ida_simple_remove(&mdev_id, i->dev_id); list_del(&i->list); destroy_most_inst_obj(i); -- cgit v1.2.3 From 61f6bfcbaee6b49f3147ba5a3fd8d9803272b433 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:59 +0100 Subject: staging: most: remove redundant mutexes This patch removes the mutexes stop_task_mutex and deregister mutex, since they can safely be left out. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 31ea3a5e485e..b085f0ac5b8c 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -65,7 +65,6 @@ struct most_c_obj { struct most_c_aim_obj aim1; struct list_head trash_fifo; struct task_struct *hdm_enqueue_task; - struct mutex stop_task_mutex; wait_queue_head_t hdm_fifo_wq; }; @@ -93,8 +92,6 @@ struct most_inst_obj { _mbo; \ }) -static struct mutex deregister_mutex; - /* ___ ___ * ___C H A N N E L___ */ @@ -737,10 +734,8 @@ static void destroy_most_inst_obj(struct most_inst_obj *inst) struct most_c_obj *c, *tmp; list_for_each_entry_safe(c, tmp, &inst->channel_list, list) { - mutex_lock(&deregister_mutex); flush_trash_fifo(c); flush_channel_fifos(c); - mutex_unlock(&deregister_mutex); kobject_put(&c->kobj); } kobject_put(&inst->kobj); @@ -1575,11 +1570,9 @@ int most_stop_channel(struct most_interface *iface, int id, if (c->aim0.refs + c->aim1.refs >= 2) goto out; - mutex_lock(&c->stop_task_mutex); if (c->hdm_enqueue_task) kthread_stop(c->hdm_enqueue_task); c->hdm_enqueue_task = NULL; - mutex_unlock(&c->stop_task_mutex); if (iface->mod) module_put(iface->mod); @@ -1757,7 +1750,6 @@ struct kobject *most_register_interface(struct most_interface *iface) init_completion(&c->cleanup); atomic_set(&c->mbo_ref, 0); mutex_init(&c->start_mutex); - mutex_init(&c->stop_task_mutex); list_add_tail(&c->list, &inst->channel_list); } pr_info("registered new MOST device mdev%d (%s)\n", @@ -1853,7 +1845,6 @@ static int __init most_init(void) pr_info("init()\n"); INIT_LIST_HEAD(&instance_list); INIT_LIST_HEAD(&aim_list); - mutex_init(&deregister_mutex); ida_init(&mdev_id); if (bus_register(&most_bus)) { -- cgit v1.2.3 From 0ccaa6de8edb0053efd4dcc49e8f053bf5ff7595 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:00 +0100 Subject: staging: most: remove redundant call to wake_up_interruptible This patch prevents the cdev module from rousing the channel wait queue in case the channel is about to be closed. It is safe to do so, because the application can not be waiting within read or write and at the same time be calling close. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 0141293b4bf5..fd2ac898628e 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -127,7 +127,6 @@ static int aim_close(struct inode *inode, struct file *filp) kfifo_free(&channel->fifo); list_del(&channel->list); ida_simple_remove(&minor_id, MINOR(channel->devno)); - wake_up_interruptible(&channel->wq); kfree(channel); return 0; } @@ -139,7 +138,6 @@ static int aim_close(struct inode *inode, struct file *filp) most_put_mbo(channel->stacked_mbo); ret = most_stop_channel(channel->iface, channel->channel_id, &cdev_aim); atomic_dec(&channel->access_ref); - wake_up_interruptible(&channel->wq); return ret; } -- cgit v1.2.3 From 5f858a61a8b4f5fec7b3c0618646ed6f7bfcd3a7 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:01 +0100 Subject: staging: most: encapsulate shared code This patch encapsulates shared code. It therefore creates the new functions stop_channel and destroy_cdev. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 55 +++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index fd2ac898628e..533e2900ad63 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -69,6 +69,30 @@ static struct aim_channel *get_channel(struct most_interface *iface, int id) return channel; } +static void stop_channel(struct aim_channel *c) +{ + struct mbo *mbo; + + while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1)) + most_put_mbo(mbo); + if (c->stacked_mbo) + most_put_mbo(c->stacked_mbo); + most_stop_channel(c->iface, c->channel_id, &cdev_aim); +} + +static void destroy_cdev(struct aim_channel *c) +{ + unsigned long flags; + + device_destroy(aim_class, c->devno); + cdev_del(&c->cdev); + kfifo_free(&c->fifo); + spin_lock_irqsave(&ch_list_lock, flags); + list_del(&c->list); + spin_unlock_irqrestore(&ch_list_lock, flags); + ida_simple_remove(&minor_id, MINOR(c->devno)); +} + /** * aim_open - implements the syscall to open the device * @inode: inode pointer @@ -114,31 +138,21 @@ static int aim_open(struct inode *inode, struct file *filp) */ static int aim_close(struct inode *inode, struct file *filp) { - int ret; - struct mbo *mbo; struct aim_channel *channel = to_channel(inode->i_cdev); mutex_lock(&channel->io_mutex); if (!channel->dev) { mutex_unlock(&channel->io_mutex); atomic_dec(&channel->access_ref); - device_destroy(aim_class, channel->devno); - cdev_del(&channel->cdev); - kfifo_free(&channel->fifo); - list_del(&channel->list); - ida_simple_remove(&minor_id, MINOR(channel->devno)); + destroy_cdev(channel); kfree(channel); return 0; } mutex_unlock(&channel->io_mutex); - while (kfifo_out((struct kfifo *)&channel->fifo, &mbo, 1)) - most_put_mbo(mbo); - if (channel->stacked_mbo) - most_put_mbo(channel->stacked_mbo); - ret = most_stop_channel(channel->iface, channel->channel_id, &cdev_aim); + stop_channel(channel); atomic_dec(&channel->access_ref); - return ret; + return 0; } /** @@ -310,7 +324,6 @@ static const struct file_operations channel_fops = { static int aim_disconnect_channel(struct most_interface *iface, int channel_id) { struct aim_channel *channel; - unsigned long flags; if (!iface) { pr_info("Bad interface pointer\n"); @@ -326,13 +339,7 @@ static int aim_disconnect_channel(struct most_interface *iface, int channel_id) mutex_unlock(&channel->io_mutex); if (atomic_read(&channel->access_ref)) { - device_destroy(aim_class, channel->devno); - cdev_del(&channel->cdev); - kfifo_free(&channel->fifo); - ida_simple_remove(&minor_id, MINOR(channel->devno)); - spin_lock_irqsave(&ch_list_lock, flags); - list_del(&channel->list); - spin_unlock_irqrestore(&ch_list_lock, flags); + destroy_cdev(channel); kfree(channel); } else { wake_up_interruptible(&channel->wq); @@ -526,11 +533,7 @@ static void __exit mod_exit(void) most_deregister_aim(&cdev_aim); list_for_each_entry_safe(channel, tmp, &channel_list, list) { - device_destroy(aim_class, channel->devno); - cdev_del(&channel->cdev); - kfifo_free(&channel->fifo); - list_del(&channel->list); - ida_simple_remove(&minor_id, MINOR(channel->devno)); + destroy_cdev(channel); kfree(channel); } class_destroy(aim_class); -- cgit v1.2.3 From cdc293d58945527f36b13771822be69277c21bd6 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 12 Jan 2016 14:00:03 +0100 Subject: staging: most: fix retrieval of buffer availability This patch fixes the function channel_has_mbo that delivers the false information in case two AIMs are using the same tx channel. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 12 ++++++------ drivers/staging/most/mostcore/core.c | 7 ++++++- drivers/staging/most/mostcore/mostcore.h | 3 ++- 3 files changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 533e2900ad63..c4bbf7d296e8 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -50,6 +50,11 @@ struct aim_channel { static struct list_head channel_list; static spinlock_t ch_list_lock; +static inline bool ch_has_mbo(struct aim_channel *c) +{ + return channel_has_mbo(c->iface, c->channel_id, &cdev_aim) > 0; +} + static struct aim_channel *get_channel(struct most_interface *iface, int id) { struct aim_channel *channel, *tmp; @@ -279,11 +284,6 @@ start_copy: return copied; } -static inline bool __must_check IS_ERR_OR_FALSE(int x) -{ - return x <= 0; -} - static unsigned int aim_poll(struct file *filp, poll_table *wait) { struct aim_channel *c = filp->private_data; @@ -295,7 +295,7 @@ static unsigned int aim_poll(struct file *filp, poll_table *wait) if (!kfifo_is_empty(&c->fifo)) mask |= POLLIN | POLLRDNORM; } else { - if (!IS_ERR_OR_FALSE(channel_has_mbo(c->iface, c->channel_id))) + if (ch_has_mbo(c)) mask |= POLLOUT | POLLWRNORM; } return mask; diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index b085f0ac5b8c..09a5a1a1138e 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -1352,7 +1352,7 @@ most_c_obj *get_channel_by_iface(struct most_interface *iface, int id) return i->channel[id]; } -int channel_has_mbo(struct most_interface *iface, int id) +int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim) { struct most_c_obj *c = get_channel_by_iface(iface, id); unsigned long flags; @@ -1361,6 +1361,11 @@ int channel_has_mbo(struct most_interface *iface, int id) if (unlikely(!c)) return -EINVAL; + if (c->aim0.refs && c->aim1.refs && + ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) || + (aim == c->aim1.ptr && c->aim1.num_buffers <= 0))) + return 0; + spin_lock_irqsave(&c->fifo_lock, flags); empty = list_empty(&c->fifo); spin_unlock_irqrestore(&c->fifo_lock, flags); diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h index bda3850d5435..60e018e499ef 100644 --- a/drivers/staging/most/mostcore/mostcore.h +++ b/drivers/staging/most/mostcore/mostcore.h @@ -310,7 +310,8 @@ int most_deregister_aim(struct most_aim *aim); struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx, struct most_aim *); void most_put_mbo(struct mbo *mbo); -int channel_has_mbo(struct most_interface *iface, int channel_idx); +int channel_has_mbo(struct most_interface *iface, int channel_idx, + struct most_aim *aim); int most_start_channel(struct most_interface *iface, int channel_idx, struct most_aim *); int most_stop_channel(struct most_interface *iface, int channel_idx, -- cgit v1.2.3 From d8b082e6c625cba59ecfb80e4506c8f30bed24ea Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:03 +0100 Subject: staging: most: rename variable channel This patch renames the variable 'channel' to 'c'. This is needed to have the code look more homogeneous and to prevent format violations. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 216 +++++++++++++++++------------------ 1 file changed, 108 insertions(+), 108 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index c4bbf7d296e8..50651395a0ae 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -57,13 +57,13 @@ static inline bool ch_has_mbo(struct aim_channel *c) static struct aim_channel *get_channel(struct most_interface *iface, int id) { - struct aim_channel *channel, *tmp; + struct aim_channel *c, *tmp; unsigned long flags; int found_channel = 0; spin_lock_irqsave(&ch_list_lock, flags); - list_for_each_entry_safe(channel, tmp, &channel_list, list) { - if ((channel->iface == iface) && (channel->channel_id == id)) { + list_for_each_entry_safe(c, tmp, &channel_list, list) { + if ((c->iface == iface) && (c->channel_id == id)) { found_channel = 1; break; } @@ -71,7 +71,7 @@ static struct aim_channel *get_channel(struct most_interface *iface, int id) spin_unlock_irqrestore(&ch_list_lock, flags); if (!found_channel) return NULL; - return channel; + return c; } static void stop_channel(struct aim_channel *c) @@ -108,29 +108,29 @@ static void destroy_cdev(struct aim_channel *c) */ static int aim_open(struct inode *inode, struct file *filp) { - struct aim_channel *channel; + struct aim_channel *c; int ret; - channel = to_channel(inode->i_cdev); - filp->private_data = channel; + c = to_channel(inode->i_cdev); + filp->private_data = c; - if (((channel->cfg->direction == MOST_CH_RX) && + if (((c->cfg->direction == MOST_CH_RX) && ((filp->f_flags & O_ACCMODE) != O_RDONLY)) || - ((channel->cfg->direction == MOST_CH_TX) && + ((c->cfg->direction == MOST_CH_TX) && ((filp->f_flags & O_ACCMODE) != O_WRONLY))) { pr_info("WARN: Access flags mismatch\n"); return -EACCES; } - if (!atomic_inc_and_test(&channel->access_ref)) { + if (!atomic_inc_and_test(&c->access_ref)) { pr_info("WARN: Device is busy\n"); - atomic_dec(&channel->access_ref); + atomic_dec(&c->access_ref); return -EBUSY; } - ret = most_start_channel(channel->iface, channel->channel_id, + ret = most_start_channel(c->iface, c->channel_id, &cdev_aim); if (ret) - atomic_dec(&channel->access_ref); + atomic_dec(&c->access_ref); return ret; } @@ -143,20 +143,20 @@ static int aim_open(struct inode *inode, struct file *filp) */ static int aim_close(struct inode *inode, struct file *filp) { - struct aim_channel *channel = to_channel(inode->i_cdev); - - mutex_lock(&channel->io_mutex); - if (!channel->dev) { - mutex_unlock(&channel->io_mutex); - atomic_dec(&channel->access_ref); - destroy_cdev(channel); - kfree(channel); + struct aim_channel *c = to_channel(inode->i_cdev); + + mutex_lock(&c->io_mutex); + if (!c->dev) { + mutex_unlock(&c->io_mutex); + atomic_dec(&c->access_ref); + destroy_cdev(c); + kfree(c); return 0; } - mutex_unlock(&channel->io_mutex); + mutex_unlock(&c->io_mutex); - stop_channel(channel); - atomic_dec(&channel->access_ref); + stop_channel(c); + atomic_dec(&c->access_ref); return 0; } @@ -175,38 +175,38 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, size_t max_len = 0; ssize_t retval; struct mbo *mbo; - struct aim_channel *channel = filp->private_data; + struct aim_channel *c = filp->private_data; - mutex_lock(&channel->io_mutex); - if (unlikely(!channel->dev)) { - mutex_unlock(&channel->io_mutex); + mutex_lock(&c->io_mutex); + if (unlikely(!c->dev)) { + mutex_unlock(&c->io_mutex); return -EPIPE; } - mutex_unlock(&channel->io_mutex); + mutex_unlock(&c->io_mutex); - mbo = most_get_mbo(channel->iface, channel->channel_id, &cdev_aim); + mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim); if (!mbo) { if ((filp->f_flags & O_NONBLOCK)) return -EAGAIN; if (wait_event_interruptible( - channel->wq, - (mbo = most_get_mbo(channel->iface, - channel->channel_id, + c->wq, + (mbo = most_get_mbo(c->iface, + c->channel_id, &cdev_aim)) || - (!channel->dev))) + (!c->dev))) return -ERESTARTSYS; } - mutex_lock(&channel->io_mutex); - if (unlikely(!channel->dev)) { - mutex_unlock(&channel->io_mutex); + mutex_lock(&c->io_mutex); + if (unlikely(!c->dev)) { + mutex_unlock(&c->io_mutex); err = -EPIPE; goto error; } - mutex_unlock(&channel->io_mutex); + mutex_unlock(&c->io_mutex); - max_len = channel->cfg->buffer_size; + max_len = c->cfg->buffer_size; actual_len = min(count, max_len); mbo->buffer_length = actual_len; @@ -240,47 +240,47 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) { size_t to_copy, not_copied, copied; struct mbo *mbo; - struct aim_channel *channel = filp->private_data; + struct aim_channel *c = filp->private_data; - if (channel->stacked_mbo) { - mbo = channel->stacked_mbo; + if (c->stacked_mbo) { + mbo = c->stacked_mbo; goto start_copy; } - while ((!kfifo_out(&channel->fifo, &mbo, 1)) && (channel->dev)) { + while ((!kfifo_out(&c->fifo, &mbo, 1)) && (c->dev)) { if (filp->f_flags & O_NONBLOCK) return -EAGAIN; - if (wait_event_interruptible(channel->wq, - (!kfifo_is_empty(&channel->fifo) || - (!channel->dev)))) + if (wait_event_interruptible(c->wq, + (!kfifo_is_empty(&c->fifo) || + (!c->dev)))) return -ERESTARTSYS; } - channel->stacked_mbo = mbo; + c->stacked_mbo = mbo; start_copy: /* make sure we don't submit to gone devices */ - mutex_lock(&channel->io_mutex); - if (unlikely(!channel->dev)) { - mutex_unlock(&channel->io_mutex); + mutex_lock(&c->io_mutex); + if (unlikely(!c->dev)) { + mutex_unlock(&c->io_mutex); return -EIO; } to_copy = min_t(size_t, count, - mbo->processed_length - channel->mbo_offs); + mbo->processed_length - c->mbo_offs); not_copied = copy_to_user(buf, - mbo->virt_address + channel->mbo_offs, + mbo->virt_address + c->mbo_offs, to_copy); copied = to_copy - not_copied; - channel->mbo_offs += copied; - if (channel->mbo_offs >= mbo->processed_length) { + c->mbo_offs += copied; + if (c->mbo_offs >= mbo->processed_length) { most_put_mbo(mbo); - channel->mbo_offs = 0; - channel->stacked_mbo = NULL; + c->mbo_offs = 0; + c->stacked_mbo = NULL; } - mutex_unlock(&channel->io_mutex); + mutex_unlock(&c->io_mutex); return copied; } @@ -323,26 +323,26 @@ static const struct file_operations channel_fops = { */ static int aim_disconnect_channel(struct most_interface *iface, int channel_id) { - struct aim_channel *channel; + struct aim_channel *c; if (!iface) { pr_info("Bad interface pointer\n"); return -EINVAL; } - channel = get_channel(iface, channel_id); - if (!channel) + c = get_channel(iface, channel_id); + if (!c) return -ENXIO; - mutex_lock(&channel->io_mutex); - channel->dev = NULL; - mutex_unlock(&channel->io_mutex); + mutex_lock(&c->io_mutex); + c->dev = NULL; + mutex_unlock(&c->io_mutex); - if (atomic_read(&channel->access_ref)) { - destroy_cdev(channel); - kfree(channel); + if (atomic_read(&c->access_ref)) { + destroy_cdev(c); + kfree(c); } else { - wake_up_interruptible(&channel->wq); + wake_up_interruptible(&c->wq); } return 0; } @@ -356,21 +356,21 @@ static int aim_disconnect_channel(struct most_interface *iface, int channel_id) */ static int aim_rx_completion(struct mbo *mbo) { - struct aim_channel *channel; + struct aim_channel *c; if (!mbo) return -EINVAL; - channel = get_channel(mbo->ifp, mbo->hdm_channel_id); - if (!channel) + c = get_channel(mbo->ifp, mbo->hdm_channel_id); + if (!c) return -ENXIO; - kfifo_in(&channel->fifo, &mbo, 1); + kfifo_in(&c->fifo, &mbo, 1); #ifdef DEBUG_MESG - if (kfifo_is_full(&channel->fifo)) + if (kfifo_is_full(&c->fifo)) pr_info("WARN: Fifo is full\n"); #endif - wake_up_interruptible(&channel->wq); + wake_up_interruptible(&c->wq); return 0; } @@ -383,7 +383,7 @@ static int aim_rx_completion(struct mbo *mbo) */ static int aim_tx_completion(struct most_interface *iface, int channel_id) { - struct aim_channel *channel; + struct aim_channel *c; if (!iface) { pr_info("Bad interface pointer\n"); @@ -394,10 +394,10 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id) return -EINVAL; } - channel = get_channel(iface, channel_id); - if (!channel) + c = get_channel(iface, channel_id); + if (!c) return -ENXIO; - wake_up_interruptible(&channel->wq); + wake_up_interruptible(&c->wq); return 0; } @@ -419,7 +419,7 @@ static int aim_probe(struct most_interface *iface, int channel_id, struct most_channel_config *cfg, struct kobject *parent, char *name) { - struct aim_channel *channel; + struct aim_channel *c; unsigned long cl_flags; int retval; int current_minor; @@ -428,60 +428,60 @@ static int aim_probe(struct most_interface *iface, int channel_id, pr_info("Probing AIM with bad arguments"); return -EINVAL; } - channel = get_channel(iface, channel_id); - if (channel) + c = get_channel(iface, channel_id); + if (c) return -EEXIST; current_minor = ida_simple_get(&minor_id, 0, 0, GFP_KERNEL); if (current_minor < 0) return current_minor; - channel = kzalloc(sizeof(*channel), GFP_KERNEL); - if (!channel) { + c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) { retval = -ENOMEM; goto error_alloc_channel; } - channel->devno = MKDEV(major, current_minor); - cdev_init(&channel->cdev, &channel_fops); - channel->cdev.owner = THIS_MODULE; - cdev_add(&channel->cdev, channel->devno, 1); - channel->iface = iface; - channel->cfg = cfg; - channel->channel_id = channel_id; - channel->mbo_offs = 0; - atomic_set(&channel->access_ref, -1); - INIT_KFIFO(channel->fifo); - retval = kfifo_alloc(&channel->fifo, cfg->num_buffers, GFP_KERNEL); + c->devno = MKDEV(major, current_minor); + cdev_init(&c->cdev, &channel_fops); + c->cdev.owner = THIS_MODULE; + cdev_add(&c->cdev, c->devno, 1); + c->iface = iface; + c->cfg = cfg; + c->channel_id = channel_id; + c->mbo_offs = 0; + atomic_set(&c->access_ref, -1); + INIT_KFIFO(c->fifo); + retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL); if (retval) { pr_info("failed to alloc channel kfifo"); goto error_alloc_kfifo; } - init_waitqueue_head(&channel->wq); - mutex_init(&channel->io_mutex); + init_waitqueue_head(&c->wq); + mutex_init(&c->io_mutex); spin_lock_irqsave(&ch_list_lock, cl_flags); - list_add_tail(&channel->list, &channel_list); + list_add_tail(&c->list, &channel_list); spin_unlock_irqrestore(&ch_list_lock, cl_flags); - channel->dev = device_create(aim_class, + c->dev = device_create(aim_class, NULL, - channel->devno, + c->devno, NULL, "%s", name); - retval = IS_ERR(channel->dev); + retval = IS_ERR(c->dev); if (retval) { pr_info("failed to create new device node %s\n", name); goto error_create_device; } - kobject_uevent(&channel->dev->kobj, KOBJ_ADD); + kobject_uevent(&c->dev->kobj, KOBJ_ADD); return 0; error_create_device: - kfifo_free(&channel->fifo); - list_del(&channel->list); + kfifo_free(&c->fifo); + list_del(&c->list); error_alloc_kfifo: - cdev_del(&channel->cdev); - kfree(channel); + cdev_del(&c->cdev); + kfree(c); error_alloc_channel: ida_simple_remove(&minor_id, current_minor); return retval; @@ -526,15 +526,15 @@ free_cdev: static void __exit mod_exit(void) { - struct aim_channel *channel, *tmp; + struct aim_channel *c, *tmp; pr_info("exit module\n"); most_deregister_aim(&cdev_aim); - list_for_each_entry_safe(channel, tmp, &channel_list, list) { - destroy_cdev(channel); - kfree(channel); + list_for_each_entry_safe(c, tmp, &channel_list, list) { + destroy_cdev(c); + kfree(c); } class_destroy(aim_class); unregister_chrdev_region(aim_devno, 1); -- cgit v1.2.3 From fa96b8ed9cc562827b27181de7285c8fba54f395 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:04 +0100 Subject: staging: most: fix race conditions This patch fixes race conditions that might emerge from functions aim_open, aim_close, aim_read, aim_write and aim_disconnect_channel within module cdev. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 89 ++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 50651395a0ae..ade7808e9d1c 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -32,6 +32,7 @@ static struct most_aim cdev_aim; struct aim_channel { wait_queue_head_t wq; + spinlock_t unlink; /* synchronization lock to unlink channels */ struct cdev cdev; struct device *dev; struct mutex io_mutex; @@ -55,6 +56,12 @@ static inline bool ch_has_mbo(struct aim_channel *c) return channel_has_mbo(c->iface, c->channel_id, &cdev_aim) > 0; } +static inline bool ch_get_mbo(struct aim_channel *c, struct mbo **mbo) +{ + *mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim); + return *mbo; +} + static struct aim_channel *get_channel(struct most_interface *iface, int id) { struct aim_channel *c, *tmp; @@ -82,6 +89,7 @@ static void stop_channel(struct aim_channel *c) most_put_mbo(mbo); if (c->stacked_mbo) most_put_mbo(c->stacked_mbo); + c->stacked_mbo = NULL; most_stop_channel(c->iface, c->channel_id, &cdev_aim); } @@ -121,16 +129,25 @@ static int aim_open(struct inode *inode, struct file *filp) pr_info("WARN: Access flags mismatch\n"); return -EACCES; } + + mutex_lock(&c->io_mutex); + if (!c->dev) { + pr_info("WARN: Device is destroyed\n"); + mutex_unlock(&c->io_mutex); + return -EBUSY; + } + if (!atomic_inc_and_test(&c->access_ref)) { pr_info("WARN: Device is busy\n"); atomic_dec(&c->access_ref); + mutex_unlock(&c->io_mutex); return -EBUSY; } - ret = most_start_channel(c->iface, c->channel_id, - &cdev_aim); + ret = most_start_channel(c->iface, c->channel_id, &cdev_aim); if (ret) atomic_dec(&c->access_ref); + mutex_unlock(&c->io_mutex); return ret; } @@ -146,17 +163,17 @@ static int aim_close(struct inode *inode, struct file *filp) struct aim_channel *c = to_channel(inode->i_cdev); mutex_lock(&c->io_mutex); - if (!c->dev) { + spin_lock(&c->unlink); + atomic_dec(&c->access_ref); + spin_unlock(&c->unlink); + if (c->dev) { + stop_channel(c); mutex_unlock(&c->io_mutex); - atomic_dec(&c->access_ref); + } else { destroy_cdev(c); + mutex_unlock(&c->io_mutex); kfree(c); - return 0; } - mutex_unlock(&c->io_mutex); - - stop_channel(c); - atomic_dec(&c->access_ref); return 0; } @@ -171,40 +188,27 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, size_t count, loff_t *offset) { int ret, err; - size_t actual_len = 0; - size_t max_len = 0; + size_t actual_len; + size_t max_len; ssize_t retval; - struct mbo *mbo; + struct mbo *mbo = NULL; struct aim_channel *c = filp->private_data; mutex_lock(&c->io_mutex); - if (unlikely(!c->dev)) { + while (c->dev && !ch_get_mbo(c, &mbo)) { mutex_unlock(&c->io_mutex); - return -EPIPE; - } - mutex_unlock(&c->io_mutex); - - mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim); - if (!mbo) { if ((filp->f_flags & O_NONBLOCK)) return -EAGAIN; - if (wait_event_interruptible( - c->wq, - (mbo = most_get_mbo(c->iface, - c->channel_id, - &cdev_aim)) || - (!c->dev))) + if (wait_event_interruptible(c->wq, ch_has_mbo(c) || !c->dev)) return -ERESTARTSYS; + mutex_lock(&c->io_mutex); } - mutex_lock(&c->io_mutex); if (unlikely(!c->dev)) { - mutex_unlock(&c->io_mutex); err = -EPIPE; goto error; } - mutex_unlock(&c->io_mutex); max_len = c->cfg->buffer_size; actual_len = min(count, max_len); @@ -222,9 +226,12 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, err = ret; goto error; } + mutex_unlock(&c->io_mutex); return actual_len - retval; error: - most_put_mbo(mbo); + if (mbo) + most_put_mbo(mbo); + mutex_unlock(&c->io_mutex); return err; } @@ -242,23 +249,25 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) struct mbo *mbo; struct aim_channel *c = filp->private_data; + mutex_lock(&c->io_mutex); if (c->stacked_mbo) { mbo = c->stacked_mbo; goto start_copy; } while ((!kfifo_out(&c->fifo, &mbo, 1)) && (c->dev)) { + mutex_unlock(&c->io_mutex); if (filp->f_flags & O_NONBLOCK) return -EAGAIN; if (wait_event_interruptible(c->wq, (!kfifo_is_empty(&c->fifo) || (!c->dev)))) return -ERESTARTSYS; + mutex_lock(&c->io_mutex); } c->stacked_mbo = mbo; start_copy: /* make sure we don't submit to gone devices */ - mutex_lock(&c->io_mutex); if (unlikely(!c->dev)) { mutex_unlock(&c->io_mutex); return -EIO; @@ -335,14 +344,17 @@ static int aim_disconnect_channel(struct most_interface *iface, int channel_id) return -ENXIO; mutex_lock(&c->io_mutex); + spin_lock(&c->unlink); c->dev = NULL; - mutex_unlock(&c->io_mutex); - - if (atomic_read(&c->access_ref)) { + spin_unlock(&c->unlink); + if (!atomic_read(&c->access_ref)) { + stop_channel(c); + wake_up_interruptible(&c->wq); + mutex_unlock(&c->io_mutex); + } else { destroy_cdev(c); + mutex_unlock(&c->io_mutex); kfree(c); - } else { - wake_up_interruptible(&c->wq); } return 0; } @@ -365,7 +377,13 @@ static int aim_rx_completion(struct mbo *mbo) if (!c) return -ENXIO; + spin_lock(&c->unlink); + if (atomic_read(&c->access_ref) || !c->dev) { + spin_unlock(&c->unlink); + return -EFAULT; + } kfifo_in(&c->fifo, &mbo, 1); + spin_unlock(&c->unlink); #ifdef DEBUG_MESG if (kfifo_is_full(&c->fifo)) pr_info("WARN: Fifo is full\n"); @@ -451,6 +469,7 @@ static int aim_probe(struct most_interface *iface, int channel_id, c->channel_id = channel_id; c->mbo_offs = 0; atomic_set(&c->access_ref, -1); + spin_lock_init(&c->unlink); INIT_KFIFO(c->fifo); retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL); if (retval) { -- cgit v1.2.3 From b3c9f3c56c41cbebe7804b48ba8e6e484509c2c0 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:05 +0100 Subject: staging: most: change type of access_ref This patch changes the type of the access reference from atomit_t to int. It is needed, because the reference variable is secured by synchronization locks and does not need to be atomic anymore. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index ade7808e9d1c..d9c3f561c7a7 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -43,7 +43,7 @@ struct aim_channel { size_t mbo_offs; struct mbo *stacked_mbo; DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *)); - atomic_t access_ref; + int access_ref; struct list_head list; }; @@ -137,16 +137,15 @@ static int aim_open(struct inode *inode, struct file *filp) return -EBUSY; } - if (!atomic_inc_and_test(&c->access_ref)) { + if (c->access_ref) { pr_info("WARN: Device is busy\n"); - atomic_dec(&c->access_ref); mutex_unlock(&c->io_mutex); return -EBUSY; } ret = most_start_channel(c->iface, c->channel_id, &cdev_aim); - if (ret) - atomic_dec(&c->access_ref); + if (!ret) + c->access_ref = 1; mutex_unlock(&c->io_mutex); return ret; } @@ -164,7 +163,7 @@ static int aim_close(struct inode *inode, struct file *filp) mutex_lock(&c->io_mutex); spin_lock(&c->unlink); - atomic_dec(&c->access_ref); + c->access_ref = 0; spin_unlock(&c->unlink); if (c->dev) { stop_channel(c); @@ -347,7 +346,7 @@ static int aim_disconnect_channel(struct most_interface *iface, int channel_id) spin_lock(&c->unlink); c->dev = NULL; spin_unlock(&c->unlink); - if (!atomic_read(&c->access_ref)) { + if (c->access_ref) { stop_channel(c); wake_up_interruptible(&c->wq); mutex_unlock(&c->io_mutex); @@ -378,7 +377,7 @@ static int aim_rx_completion(struct mbo *mbo) return -ENXIO; spin_lock(&c->unlink); - if (atomic_read(&c->access_ref) || !c->dev) { + if (!c->access_ref || !c->dev) { spin_unlock(&c->unlink); return -EFAULT; } @@ -468,7 +467,7 @@ static int aim_probe(struct most_interface *iface, int channel_id, c->cfg = cfg; c->channel_id = channel_id; c->mbo_offs = 0; - atomic_set(&c->access_ref, -1); + c->access_ref = 0; spin_lock_init(&c->unlink); INIT_KFIFO(c->fifo); retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL); -- cgit v1.2.3 From f45b0fba43f415f69982df743dfa9b5d1b57785e Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:06 +0100 Subject: staging: most: remove stacked_mbo This patch makes use of kfifo_peek and kfifo_skip, which renders the variable stacked_mbo useless. It is therefore removed. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index d9c3f561c7a7..0ee2f085848f 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -41,7 +41,6 @@ struct aim_channel { unsigned int channel_id; dev_t devno; size_t mbo_offs; - struct mbo *stacked_mbo; DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *)); int access_ref; struct list_head list; @@ -87,9 +86,6 @@ static void stop_channel(struct aim_channel *c) while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1)) most_put_mbo(mbo); - if (c->stacked_mbo) - most_put_mbo(c->stacked_mbo); - c->stacked_mbo = NULL; most_stop_channel(c->iface, c->channel_id, &cdev_aim); } @@ -143,6 +139,7 @@ static int aim_open(struct inode *inode, struct file *filp) return -EBUSY; } + c->mbo_offs = 0; ret = most_start_channel(c->iface, c->channel_id, &cdev_aim); if (!ret) c->access_ref = 1; @@ -249,11 +246,7 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) struct aim_channel *c = filp->private_data; mutex_lock(&c->io_mutex); - if (c->stacked_mbo) { - mbo = c->stacked_mbo; - goto start_copy; - } - while ((!kfifo_out(&c->fifo, &mbo, 1)) && (c->dev)) { + while (c->dev && !kfifo_peek(&c->fifo, &mbo)) { mutex_unlock(&c->io_mutex); if (filp->f_flags & O_NONBLOCK) return -EAGAIN; @@ -263,9 +256,7 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) return -ERESTARTSYS; mutex_lock(&c->io_mutex); } - c->stacked_mbo = mbo; -start_copy: /* make sure we don't submit to gone devices */ if (unlikely(!c->dev)) { mutex_unlock(&c->io_mutex); @@ -284,9 +275,9 @@ start_copy: c->mbo_offs += copied; if (c->mbo_offs >= mbo->processed_length) { + kfifo_skip(&c->fifo); most_put_mbo(mbo); c->mbo_offs = 0; - c->stacked_mbo = NULL; } mutex_unlock(&c->io_mutex); return copied; @@ -466,7 +457,6 @@ static int aim_probe(struct most_interface *iface, int channel_id, c->iface = iface; c->cfg = cfg; c->channel_id = channel_id; - c->mbo_offs = 0; c->access_ref = 0; spin_lock_init(&c->unlink); INIT_KFIFO(c->fifo); -- cgit v1.2.3 From 5adf5dc5682fa7968370a8bea773d98f1beeeddc Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:07 +0100 Subject: staging: most: rearrange function aim_write This patch straightens and rearranges the code of function aim_write() of module aim-cdev. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 0ee2f085848f..c3f32716168b 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -183,10 +183,9 @@ static int aim_close(struct inode *inode, struct file *filp) static ssize_t aim_write(struct file *filp, const char __user *buf, size_t count, loff_t *offset) { - int ret, err; + int ret; size_t actual_len; size_t max_len; - ssize_t retval; struct mbo *mbo = NULL; struct aim_channel *c = filp->private_data; @@ -202,33 +201,30 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, } if (unlikely(!c->dev)) { - err = -EPIPE; - goto error; + ret = -EPIPE; + goto unlock; } max_len = c->cfg->buffer_size; actual_len = min(count, max_len); mbo->buffer_length = actual_len; - retval = copy_from_user(mbo->virt_address, buf, mbo->buffer_length); - if (retval) { - err = -EIO; - goto error; + if (copy_from_user(mbo->virt_address, buf, mbo->buffer_length)) { + ret = -EFAULT; + goto put_mbo; } ret = most_submit_mbo(mbo); - if (ret) { - pr_info("submitting MBO to core failed\n"); - err = ret; - goto error; - } + if (ret) + goto put_mbo; + mutex_unlock(&c->io_mutex); - return actual_len - retval; -error: - if (mbo) - most_put_mbo(mbo); + return actual_len; +put_mbo: + most_put_mbo(mbo); +unlock: mutex_unlock(&c->io_mutex); - return err; + return ret; } /** -- cgit v1.2.3 From 1c55d30b1da6bd4f3b0dbd64e660fad44b8958d8 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:08 +0100 Subject: staging: most: add statistics for dropped packets This patch adds a counter for dropped packets. It needed for statistical analysis. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-network/networking.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c index 3c7beb03871d..2f42de44d051 100644 --- a/drivers/staging/most/aim-network/networking.c +++ b/drivers/staging/most/aim-network/networking.c @@ -431,6 +431,7 @@ static int aim_rx_data(struct mbo *mbo) u32 len = mbo->processed_length; struct sk_buff *skb; struct net_device *dev; + unsigned int skb_len; nd = get_net_dev_context(mbo->ifp); if (!nd || !nd->channels_opened || nd->rx.ch_id != mbo->hdm_channel_id) @@ -482,9 +483,13 @@ static int aim_rx_data(struct mbo *mbo) memcpy(skb_put(skb, len), buf, len); skb->protocol = eth_type_trans(skb, dev); - dev->stats.rx_packets++; - dev->stats.rx_bytes += skb->len; - netif_rx(skb); + skb_len = skb->len; + if (netif_rx(skb) == NET_RX_SUCCESS) { + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb_len; + } else { + dev->stats.rx_dropped++; + } out: most_put_mbo(mbo); -- cgit v1.2.3 From 0833ac7db0034b64669ea3fc3dc36d7c9e7905b8 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:09 +0100 Subject: staging: most: remove 2nd forward declaration of struct most_aim This patch removes the second forwared declaration of struct most_aim. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index c3f32716168b..3a2dbf1490c6 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -405,8 +405,6 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id) return 0; } -static struct most_aim cdev_aim; - /** * aim_probe - probe function of the driver module * @iface: pointer to interface instance -- cgit v1.2.3 From 17ac98ac7339bdf867633d788e1bde32349012f2 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Sun, 22 Nov 2015 22:30:54 +0530 Subject: staging: most: fix error comparison device_create() returns ERR_PTR on error, it does not return NULL. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 09a5a1a1138e..e4797fdb10dd 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -1869,7 +1869,7 @@ static int __init most_init(void) class_glue_dir = device_create(most_class, NULL, 0, NULL, "mostcore"); - if (!class_glue_dir) + if (IS_ERR(class_glue_dir)) goto exit_driver; most_aim_kset = -- cgit v1.2.3 From e7f2b70fd3a98951e4f09b7c7a084b268c924ad8 Mon Sep 17 00:00:00 2001 From: Hari Prasath Gujulan Elango Date: Mon, 28 Dec 2015 08:55:37 +0000 Subject: staging: most: replace multiple if..else with table lookup Replace multiple if..else if..statements with simple table lookup in two functions. Signed-off-by: Hari Prasath Gujulan Elango Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 41 +++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index e4797fdb10dd..ab4c32d78d9f 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -79,6 +79,14 @@ struct most_inst_obj { struct list_head list; }; +static const struct { + int most_ch_data_type; + char *name; +} ch_data_type[] = { { MOST_CH_CONTROL, "control\n" }, + { MOST_CH_ASYNC, "async\n" }, + { MOST_CH_SYNC, "sync\n" }, + { MOST_CH_ISOC_AVP, "isoc_avp\n"} }; + #define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj) /** @@ -409,14 +417,12 @@ static ssize_t show_set_datatype(struct most_c_obj *c, struct most_c_attr *attr, char *buf) { - if (c->cfg.data_type & MOST_CH_CONTROL) - return snprintf(buf, PAGE_SIZE, "control\n"); - else if (c->cfg.data_type & MOST_CH_ASYNC) - return snprintf(buf, PAGE_SIZE, "async\n"); - else if (c->cfg.data_type & MOST_CH_SYNC) - return snprintf(buf, PAGE_SIZE, "sync\n"); - else if (c->cfg.data_type & MOST_CH_ISOC_AVP) - return snprintf(buf, PAGE_SIZE, "isoc_avp\n"); + int i; + + for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { + if (c->cfg.data_type & ch_data_type[i].most_ch_data_type) + return snprintf(buf, PAGE_SIZE, ch_data_type[i].name); + } return snprintf(buf, PAGE_SIZE, "unconfigured\n"); } @@ -425,15 +431,16 @@ static ssize_t store_set_datatype(struct most_c_obj *c, const char *buf, size_t count) { - if (!strcmp(buf, "control\n")) { - c->cfg.data_type = MOST_CH_CONTROL; - } else if (!strcmp(buf, "async\n")) { - c->cfg.data_type = MOST_CH_ASYNC; - } else if (!strcmp(buf, "sync\n")) { - c->cfg.data_type = MOST_CH_SYNC; - } else if (!strcmp(buf, "isoc_avp\n")) { - c->cfg.data_type = MOST_CH_ISOC_AVP; - } else { + int i; + + for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { + if (!strcmp(buf, ch_data_type[i].name)) { + c->cfg.data_type = ch_data_type[i].most_ch_data_type; + break; + } + } + + if (i == ARRAY_SIZE(ch_data_type)) { pr_info("WARN: invalid attribute settings\n"); return -EINVAL; } -- cgit v1.2.3 From 092c78f24a89c0ef837cc905fb40f67db39ba257 Mon Sep 17 00:00:00 2001 From: Hugo Camboulive Date: Sat, 2 Jan 2016 22:33:26 +0000 Subject: staging: most: add __iomem for io_base and registers This removes a few Sparse warnings. Signed-off-by: Hugo Camboulive Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/hdm-dim2/dim2_hal.c | 4 ++-- drivers/staging/most/hdm-dim2/dim2_hal.h | 7 ++++--- drivers/staging/most/hdm-dim2/dim2_hdm.c | 6 +++--- drivers/staging/most/hdm-dim2/dim2_hdm.h | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c index 172257596f1f..3c524506ee22 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.c +++ b/drivers/staging/most/hdm-dim2/dim2_hal.c @@ -84,7 +84,7 @@ static inline bool dim_on_error(u8 error_id, const char *error_message) struct lld_global_vars_t { bool dim_is_initialized; bool mcm_is_initialized; - struct dim2_regs *dim2; /* DIM2 core base address */ + struct dim2_regs __iomem *dim2; /* DIM2 core base address */ u32 dbr_map[DBR_MAP_SIZE]; }; @@ -650,7 +650,7 @@ static bool channel_detach_buffers(struct dim_channel *ch, u16 buffers_number) /* -------------------------------------------------------------------------- */ /* API */ -u8 dim_startup(void *dim_base_address, u32 mlb_clock) +u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock) { g.dim_is_initialized = false; diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h index 48cdd9c8cde1..fc73d4f97734 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.h +++ b/drivers/staging/most/hdm-dim2/dim2_hal.h @@ -16,6 +16,7 @@ #define _DIM2_HAL_H #include +#include "dim2_reg.h" #ifdef __cplusplus extern "C" { @@ -65,7 +66,7 @@ struct dim_channel { u16 done_sw_buffers_number; /*< Done software buffers number. */ }; -u8 dim_startup(void *dim_base_address, u32 mlb_clock); +u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock); void dim_shutdown(void); @@ -103,9 +104,9 @@ bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr, bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number); -u32 dimcb_io_read(u32 *ptr32); +u32 dimcb_io_read(u32 __iomem *ptr32); -void dimcb_io_write(u32 *ptr32, u32 value); +void dimcb_io_write(u32 __iomem *ptr32, u32 value); void dimcb_on_error(u8 error_id, const char *error_message); diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index 48ce7ab1bb03..6296aa5b6d8e 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -99,7 +99,7 @@ struct dim2_hdm { struct most_channel_capability capabilities[DMA_CHANNELS]; struct most_interface most_iface; char name[16 + sizeof "dim2-"]; - void *io_base; + void __iomem *io_base; unsigned int irq_ahb0; int clk_speed; struct task_struct *netinfo_task; @@ -138,7 +138,7 @@ bool dim2_sysfs_get_state_cb(void) * dimcb_io_read - callback from HAL to read an I/O register * @ptr32: register address */ -u32 dimcb_io_read(u32 *ptr32) +u32 dimcb_io_read(u32 __iomem *ptr32) { return readl(ptr32); } @@ -148,7 +148,7 @@ u32 dimcb_io_read(u32 *ptr32) * @ptr32: register address * @value: value to write */ -void dimcb_io_write(u32 *ptr32, u32 value) +void dimcb_io_write(u32 __iomem *ptr32, u32 value) { writel(value, ptr32); } diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.h b/drivers/staging/most/hdm-dim2/dim2_hdm.h index 1c94e3355fcc..4050e7c764ed 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.h +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.h @@ -18,7 +18,7 @@ struct device; /* platform dependent data for dim2 interface */ struct dim2_platform_data { - int (*init)(struct dim2_platform_data *pd, void *io_base, + int (*init)(struct dim2_platform_data *pd, void __iomem *io_base, int clk_speed); void (*destroy)(struct dim2_platform_data *pd); void *priv; -- cgit v1.2.3 From 18e77054de741ef3ed2a2489bc9bf82a318b2d5e Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Fri, 29 Jan 2016 22:07:30 -0800 Subject: staging: ashmem: Avoid deadlock with mmap/shrink Both ashmem_mmap and ashmem_shrink take the ashmem_lock. It may be possible for ashmem_mmap to invoke ashmem_shrink: -000|mutex_lock(lock = 0x0) -001|ashmem_shrink(?, sc = 0x0) <--- try to take ashmem_mutex again -002|shrink_slab(shrink = 0xDA5F1CC0, nr_pages_scanned = 0, lru_pages -002|= -002|124) -003|try_to_free_pages(zonelist = 0x0, ?, ?, ?) -004|__alloc_pages_nodemask(gfp_mask = 21200, order = 1, zonelist = -004|0xC11D0940, -005|new_slab(s = 0xE4841E80, ?, node = -1) -006|__slab_alloc.isra.43.constprop.50(s = 0xE4841E80, gfpflags = -006|2148925462, ad -007|kmem_cache_alloc(s = 0xE4841E80, gfpflags = 208) -008|shmem_alloc_inode(?) -009|alloc_inode(sb = 0xE480E800) -010|new_inode_pseudo(?) -011|new_inode(?) -012|shmem_get_inode(sb = 0xE480E800, dir = 0x0, ?, dev = 0, flags = -012|187) -013|shmem_file_setup(?, ?, flags = 187) -014|ashmem_mmap(?, vma = 0xC5D64210) <---- Acquire ashmem_mutex -015|mmap_region(file = 0xDF8E2C00, addr = 1772974080, len = 233472, -015|flags = 57, -016|sys_mmap_pgoff(addr = 0, len = 230400, prot = 3, flags = 1, fd = -016|157, pgoff -017|ret_fast_syscall(asm) -->|exception -018|NUR:0x40097508(asm) ---|end of frame Avoid this deadlock by using mutex_trylock in ashmem_shrink; if the mutex is already held, do not attempt to shrink. Cc: Greg KH Cc: Android Kernel Team Reported-by: Matt Wagantall Reported-by: Syed Rameez Mustafa Reported-by: Osvaldo Banuelos Reported-by: Subbaraman Narayanamurthy Signed-off-by: Laura Abbott [jstultz: Minor commit message tweaks] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ashmem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 5bb1283d19cd..8ae130827c56 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -441,7 +441,9 @@ ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) if (!(sc->gfp_mask & __GFP_FS)) return SHRINK_STOP; - mutex_lock(&ashmem_mutex); + if (!mutex_trylock(&ashmem_mutex)) + return -1; + list_for_each_entry_safe(range, next, &ashmem_lru_list, lru) { loff_t start = range->pgstart * PAGE_SIZE; loff_t end = (range->pgend + 1) * PAGE_SIZE; -- cgit v1.2.3 From 90a2f171383b5ae43b33ab4d9d566b9765622ac7 Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Fri, 29 Jan 2016 22:07:31 -0800 Subject: staging: ashmem: Add missing include Include into ashmem.h to ensure referenced types are defined Cc: Android Kernel Team Cc: Greg KH Signed-off-by: Rom Lemarchand [jstultz: Minor commit message tweaks] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/uapi/ashmem.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/android/uapi/ashmem.h b/drivers/staging/android/uapi/ashmem.h index ba4743c71d6b..13df42d200b7 100644 --- a/drivers/staging/android/uapi/ashmem.h +++ b/drivers/staging/android/uapi/ashmem.h @@ -13,6 +13,7 @@ #define _UAPI_LINUX_ASHMEM_H #include +#include #define ASHMEM_NAME_LEN 256 -- cgit v1.2.3 From cc635da2e2e04efe32bbabc4e390c497d593c97d Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 29 Jan 2016 22:07:33 -0800 Subject: staging: lowmemorykiller: Make default lowmemorykiller debug message useful lowmemorykiller debug messages are inscrutable and mostly useful for debugging the lowmemorykiller, not explaining why a process was killed. Make the messages more useful by prefixing them with "lowmemorykiller: " and explaining in more readable terms what was killed, who it was killed for, and why it was killed. The messages now look like: [ 76.997631] lowmemorykiller: Killing 'droid.gallery3d' (2172), adj 1000, [ 76.997635] to free 27436kB on behalf of 'kswapd0' (29) because [ 76.997638] cache 122624kB is below limit 122880kB for oom_score_adj 1000 [ 76.997641] Free memory is -53356kB above reserved A negative number for free memory above reserved means some of the reserved memory has been used and is being regenerated by kswapd, which is likely what called the shrinkers. Cc: Android Kernel Team Cc: Greg KH Signed-off-by: Colin Cross [jstultz: Minor checkpatch tweaks] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/lowmemorykiller.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 8b5a4a82d8b8..4b8a56cda6ca 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -84,6 +84,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) int tasksize; int i; short min_score_adj = OOM_SCORE_ADJ_MAX + 1; + int minfree = 0; int selected_tasksize = 0; short selected_oom_score_adj; int array_size = ARRAY_SIZE(lowmem_adj); @@ -97,8 +98,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) if (lowmem_minfree_size < array_size) array_size = lowmem_minfree_size; for (i = 0; i < array_size; i++) { - if (other_free < lowmem_minfree[i] && - other_file < lowmem_minfree[i]) { + minfree = lowmem_minfree[i]; + if (other_free < minfree && other_file < minfree) { min_score_adj = lowmem_adj[i]; break; } @@ -153,8 +154,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) selected = p; selected_tasksize = tasksize; selected_oom_score_adj = oom_score_adj; - lowmem_print(2, "select %d (%s), adj %hd, size %d, to kill\n", - p->pid, p->comm, oom_score_adj, tasksize); + lowmem_print(2, "select '%s' (%d), adj %hd, size %d, to kill\n", + p->comm, p->pid, oom_score_adj, tasksize); } if (selected) { task_lock(selected); @@ -167,9 +168,18 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) if (selected->mm) mark_oom_victim(selected); task_unlock(selected); - lowmem_print(1, "send sigkill to %d (%s), adj %hd, size %d\n", - selected->pid, selected->comm, - selected_oom_score_adj, selected_tasksize); + lowmem_print(1, "Killing '%s' (%d), adj %hd,\n" + " to free %ldkB on behalf of '%s' (%d) because\n" + " cache %ldkB is below limit %ldkB for oom_score_adj %hd\n" + " Free memory is %ldkB above reserved\n", + selected->comm, selected->pid, + selected_oom_score_adj, + selected_tasksize * (long)(PAGE_SIZE / 1024), + current->comm, current->pid, + other_file * (long)(PAGE_SIZE / 1024), + minfree * (long)(PAGE_SIZE / 1024), + min_score_adj, + other_free * (long)(PAGE_SIZE / 1024)); lowmem_deathpending_timeout = jiffies + HZ; rem += selected_tasksize; } -- cgit v1.2.3 From 1328d8efef17d5e16bd6e9cfe59130a833674534 Mon Sep 17 00:00:00 2001 From: Rajmal Menariya Date: Fri, 29 Jan 2016 22:07:35 -0800 Subject: staging: ion: Set minimum carveout heap allocation order to PAGE_SHIFT In carveout heap, change minimum allocation order from 12 to PAGE_SHIFT. After this change each bit in bitmap (genalloc - General purpose special memory pool) represents one page size memory. Cc: sprd-ind-kernel-group@googlegroups.com Cc: sanjeev.yadav@spreadtrum.com Cc: Colin Cross Cc: Android Kernel Team Cc: Greg KH Cc: Sumit Semwal Signed-off-by: Rajmal Menariya [jstultz: Reworked commit message] Signed-off-by: John Stultz Acked-by: Laura Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_carveout_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 9156d8238c97..e702ce6461fc 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -167,7 +167,7 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) if (!carveout_heap) return ERR_PTR(-ENOMEM); - carveout_heap->pool = gen_pool_create(12, -1); + carveout_heap->pool = gen_pool_create(PAGE_SHIFT, -1); if (!carveout_heap->pool) { kfree(carveout_heap); return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From cd572182bd3d82e270d273b241f29d40b4213111 Mon Sep 17 00:00:00 2001 From: Bopamo Osaisai Date: Fri, 8 Jan 2016 09:15:31 -0800 Subject: Staging: android: Fix brace coding style warning in sync_debug.c This is a patch to the sync_debug.c file that rectifies a brace warning that was found with the checkpatch.pl tool Signed-off-by: Bopamo Osaisai Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync_debug.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index f45d13cdd42b..02a1649a1bd9 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -158,9 +158,8 @@ static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) seq_printf(s, "[%p] %s: %s\n", fence, fence->name, sync_status_str(atomic_read(&fence->status))); - for (i = 0; i < fence->num_fences; ++i) { + for (i = 0; i < fence->num_fences; ++i) sync_print_pt(s, fence->cbs[i].sync_pt, true); - } spin_lock_irqsave(&fence->wq.lock, flags); list_for_each_entry(pos, &fence->wq.task_list, task_list) { -- cgit v1.2.3 From 2ef230531ee171a475fc3ddad5516dd7e09a8a77 Mon Sep 17 00:00:00 2001 From: Chen Feng Date: Fri, 15 Jan 2016 10:38:19 +0800 Subject: staging: ion : Donnot wakeup kswapd in ion system alloc Since ion alloc can be called by userspace,eg gralloc. When it is called frequently, the efficiency of kswapd is to low. And the reclaimed memory is too lower. In this way, the kswapd can use to much cpu resources. With 3.5GB DMA Zone and 0.5 Normal Zone. pgsteal_kswapd_dma 9364140 pgsteal_kswapd_normal 7071043 pgscan_kswapd_dma 10428250 pgscan_kswapd_normal 37840094 With this change the reclaim ratio has greatly improved 18.9% -> 72.5% Signed-off-by: Chen Feng Signed-off-by: Lu bing Reviewed-by: Laura Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index d4c3e5512dd5..b69dfc706440 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -27,7 +27,7 @@ #include "ion_priv.h" static gfp_t high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN | - __GFP_NORETRY) & ~__GFP_DIRECT_RECLAIM; + __GFP_NORETRY) & ~__GFP_RECLAIM; static gfp_t low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN); static const unsigned int orders[] = {8, 4, 0}; static const int num_orders = ARRAY_SIZE(orders); -- cgit v1.2.3 From 70bc916b2c80913753fb188d4daee50a64d21ba0 Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Thu, 21 Jan 2016 11:57:47 +0000 Subject: staging: android: ion: Set the length of the DMA sg entries in buffer ion_buffer_create() will allocate a buffer and then create a DMA mapping for it, but it forgot to set the length of the page entries. Signed-off-by: Liviu Dudau Signed-off-by: Jon Medhurst Acked-by: Laura Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index e237e9f3312d..df560216d702 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -251,8 +251,10 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, * memory coming from the heaps is ready for dma, ie if it has a * cached mapping that mapping has been invalidated */ - for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) + for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) { sg_dma_address(sg) = sg_phys(sg); + sg_dma_len(sg) = sg->length; + } mutex_lock(&dev->buffer_lock); ion_buffer_add(dev, buffer); mutex_unlock(&dev->buffer_lock); -- cgit v1.2.3 From a906d6931f3ccaf7de805643190765ddd7378e27 Mon Sep 17 00:00:00 2001 From: Chen Feng Date: Mon, 1 Feb 2016 14:04:02 +0800 Subject: android: binder: Sanity check at binder ioctl Sanity check at binder ioctl function, Only allow the shared mm_struct to use the same binder-object to do binder operate. And add proc->vma_vm_mm = current->mm at the open function. The libbinder do ioctl before mmap called. V2: Fix compile error for error commit V3: Change the condition to proc->vma_vm_mm Signed-off-by: Chen Feng Signed-off-by: Wei Dong Signed-off-by: Junmin Zhao Reviewed-by: Zhuangluan Su Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index a39e85f9efa9..f080a8b7659b 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2737,6 +2737,10 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /*pr_info("binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/ + if (unlikely(current->mm != proc->vma_vm_mm)) { + pr_err("current mm mismatch proc mm\n"); + return -EINVAL; + } trace_binder_ioctl(cmd, arg); ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); @@ -2951,6 +2955,7 @@ static int binder_open(struct inode *nodp, struct file *filp) return -ENOMEM; get_task_struct(current); proc->tsk = current; + proc->vma_vm_mm = current->mm; INIT_LIST_HEAD(&proc->todo); init_waitqueue_head(&proc->wait); proc->default_priority = task_nice(current); -- cgit v1.2.3 From 9b32381ca50f5268edae8eac009a74b55df608d2 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:14 -0200 Subject: staging/android: fix sync framework documentation Updates comments about functions and structures. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.h | 45 ++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index afa0752275a7..7a4d8209bb0b 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -110,15 +110,9 @@ struct sync_timeline { /** * struct sync_pt - sync point - * @fence: base fence class + * @base: base fence class * @child_list: membership in sync_timeline.child_list_head * @active_list: membership in sync_timeline.active_list_head - * @signaled_list: membership in temporary signaled_list on stack - * @fence: sync_fence to which the sync_pt belongs - * @pt_list: membership in sync_fence.pt_list_head - * @status: 1: signaled, 0:active, <0: error - * @timestamp: time which sync_pt status transitioned from active to - * signaled or error. */ struct sync_pt { struct fence base; @@ -144,12 +138,11 @@ struct sync_fence_cb { * @file: file representing this fence * @kref: reference count on fence. * @name: name of sync_fence. Useful for debugging - * @pt_list_head: list of sync_pts in the fence. immutable once fence - * is created - * @status: 0: signaled, >0:active, <0: error - * - * @wq: wait queue for fence signaling * @sync_fence_list: membership in global fence list + * @num_fences number of sync_pts in the fence + * @wq: wait queue for fence signaling + * @status: 0: signaled, >0:active, <0: error + * @cbs: sync_pts callback information */ struct sync_fence { struct file *file; @@ -172,9 +165,8 @@ typedef void (*sync_callback_t)(struct sync_fence *fence, /** * struct sync_fence_waiter - metadata for asynchronous waiter on a fence - * @waiter_list: membership in sync_fence.waiter_list_head + * @work: wait_queue for the fence waiter * @callback: function pointer to call when fence signals - * @callback_data: pointer to pass to @callback */ struct sync_fence_waiter { wait_queue_t work; @@ -200,7 +192,8 @@ static inline void sync_fence_waiter_init(struct sync_fence_waiter *waiter, * * Creates a new sync_timeline which will use the implementation specified by * @ops. @size bytes will be allocated allowing for implementation specific - * data to be kept after the generic sync_timeline struct. + * data to be kept after the generic sync_timeline struct. Returns the + * sync_timeline object or NULL in case of error. */ struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops, int size, const char *name); @@ -231,7 +224,8 @@ void sync_timeline_signal(struct sync_timeline *obj); * * Creates a new sync_pt as a child of @parent. @size bytes will be * allocated allowing for implementation specific data to be kept after - * the generic sync_timeline struct. + * the generic sync_timeline struct. Returns the sync_pt object or + * NULL in case of error. */ struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size); @@ -275,7 +269,8 @@ struct sync_fence *sync_fence_create_dma(const char *name, struct fence *pt); * @b: fence b * * Creates a new fence which contains copies of all the sync_pts in both - * @a and @b. @a and @b remain valid, independent fences. + * @a and @b. @a and @b remain valid, independent fences. Returns the + * new merged fence or NULL in case of error. */ struct sync_fence *sync_fence_merge(const char *name, struct sync_fence *a, struct sync_fence *b); @@ -285,7 +280,7 @@ struct sync_fence *sync_fence_merge(const char *name, * @fd: fd referencing a fence * * Ensures @fd references a valid fence, increments the refcount of the backing - * file, and returns the fence. + * file, and returns the fence. Returns the fence or NULL in case of error. */ struct sync_fence *sync_fence_fdget(int fd); @@ -313,10 +308,10 @@ void sync_fence_install(struct sync_fence *fence, int fd); * @fence: fence to wait on * @waiter: waiter callback struck * - * Returns 1 if @fence has already signaled. - * * Registers a callback to be called when @fence signals or has an error. * @waiter should be initialized with sync_fence_waiter_init(). + * + * Returns 1 if @fence has already signaled, 0 if not or <0 if error. */ int sync_fence_wait_async(struct sync_fence *fence, struct sync_fence_waiter *waiter); @@ -326,11 +321,11 @@ int sync_fence_wait_async(struct sync_fence *fence, * @fence: fence to wait on * @waiter: waiter callback struck * - * returns 0 if waiter was removed from fence's async waiter list. - * returns -ENOENT if waiter was not found on fence's async waiter list. - * * Cancels a previously registered async wait. Will fail gracefully if * @waiter was never registered or if @fence has already signaled @waiter. + * + * Returns 0 if waiter was removed from fence's async waiter list. + * Returns -ENOENT if waiter was not found on fence's async waiter list. */ int sync_fence_cancel_async(struct sync_fence *fence, struct sync_fence_waiter *waiter); @@ -341,7 +336,9 @@ int sync_fence_cancel_async(struct sync_fence *fence, * @tiemout: timeout in ms * * Wait for @fence to be signaled or have an error. Waits indefinitely - * if @timeout < 0 + * if @timeout < 0. + * + * Returns 0 if fence signaled, > 0 if it is still active and <0 on error */ int sync_fence_wait(struct sync_fence *fence, long timeout); -- cgit v1.2.3 From 3179dd927a9338e01ed0261e0bba080b6b8bdbaa Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:15 -0200 Subject: staging/android: sync: remove interfaces that are not used These interfaces are not used nor have plans to be used in the near future so remove them for a cleaner solution before de-staging the sync framework. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 56 ------------------------------------ drivers/staging/android/sync.h | 50 -------------------------------- drivers/staging/android/sync_debug.c | 15 ---------- 3 files changed, 121 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index ed43796b5b58..7a84f8853a8e 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -317,62 +317,6 @@ struct sync_fence *sync_fence_merge(const char *name, } EXPORT_SYMBOL(sync_fence_merge); -int sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode, - int wake_flags, void *key) -{ - struct sync_fence_waiter *wait; - - wait = container_of(curr, struct sync_fence_waiter, work); - list_del_init(&wait->work.task_list); - - wait->callback(wait->work.private, wait); - return 1; -} - -int sync_fence_wait_async(struct sync_fence *fence, - struct sync_fence_waiter *waiter) -{ - int err = atomic_read(&fence->status); - unsigned long flags; - - if (err < 0) - return err; - - if (!err) - return 1; - - init_waitqueue_func_entry(&waiter->work, sync_fence_wake_up_wq); - waiter->work.private = fence; - - spin_lock_irqsave(&fence->wq.lock, flags); - err = atomic_read(&fence->status); - if (err > 0) - __add_wait_queue_tail(&fence->wq, &waiter->work); - spin_unlock_irqrestore(&fence->wq.lock, flags); - - if (err < 0) - return err; - - return !err; -} -EXPORT_SYMBOL(sync_fence_wait_async); - -int sync_fence_cancel_async(struct sync_fence *fence, - struct sync_fence_waiter *waiter) -{ - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&fence->wq.lock, flags); - if (!list_empty(&waiter->work.task_list)) - list_del_init(&waiter->work.task_list); - else - ret = -ENOENT; - spin_unlock_irqrestore(&fence->wq.lock, flags); - return ret; -} -EXPORT_SYMBOL(sync_fence_cancel_async); - int sync_fence_wait(struct sync_fence *fence, long timeout) { long ret; diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index 7a4d8209bb0b..e0865b94c8f7 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -159,27 +159,6 @@ struct sync_fence { struct sync_fence_cb cbs[]; }; -struct sync_fence_waiter; -typedef void (*sync_callback_t)(struct sync_fence *fence, - struct sync_fence_waiter *waiter); - -/** - * struct sync_fence_waiter - metadata for asynchronous waiter on a fence - * @work: wait_queue for the fence waiter - * @callback: function pointer to call when fence signals - */ -struct sync_fence_waiter { - wait_queue_t work; - sync_callback_t callback; -}; - -static inline void sync_fence_waiter_init(struct sync_fence_waiter *waiter, - sync_callback_t callback) -{ - INIT_LIST_HEAD(&waiter->work.task_list); - waiter->callback = callback; -} - /* * API for sync_timeline implementers */ @@ -303,33 +282,6 @@ void sync_fence_put(struct sync_fence *fence); */ void sync_fence_install(struct sync_fence *fence, int fd); -/** - * sync_fence_wait_async() - registers and async wait on the fence - * @fence: fence to wait on - * @waiter: waiter callback struck - * - * Registers a callback to be called when @fence signals or has an error. - * @waiter should be initialized with sync_fence_waiter_init(). - * - * Returns 1 if @fence has already signaled, 0 if not or <0 if error. - */ -int sync_fence_wait_async(struct sync_fence *fence, - struct sync_fence_waiter *waiter); - -/** - * sync_fence_cancel_async() - cancels an async wait - * @fence: fence to wait on - * @waiter: waiter callback struck - * - * Cancels a previously registered async wait. Will fail gracefully if - * @waiter was never registered or if @fence has already signaled @waiter. - * - * Returns 0 if waiter was removed from fence's async waiter list. - * Returns -ENOENT if waiter was not found on fence's async waiter list. - */ -int sync_fence_cancel_async(struct sync_fence *fence, - struct sync_fence_waiter *waiter); - /** * sync_fence_wait() - wait on fence * @fence: fence to wait on @@ -357,7 +309,5 @@ void sync_dump(void); # define sync_fence_debug_remove(fence) # define sync_dump() #endif -int sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode, - int wake_flags, void *key); #endif /* _LINUX_SYNC_H */ diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index 02a1649a1bd9..c7ee98f3b851 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -151,8 +151,6 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) { - wait_queue_t *pos; - unsigned long flags; int i; seq_printf(s, "[%p] %s: %s\n", fence, fence->name, @@ -160,19 +158,6 @@ static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) for (i = 0; i < fence->num_fences; ++i) sync_print_pt(s, fence->cbs[i].sync_pt, true); - - spin_lock_irqsave(&fence->wq.lock, flags); - list_for_each_entry(pos, &fence->wq.task_list, task_list) { - struct sync_fence_waiter *waiter; - - if (pos->func != &sync_fence_wake_up_wq) - continue; - - waiter = container_of(pos, struct sync_fence_waiter, work); - - seq_printf(s, "waiter %pF\n", waiter->callback); - } - spin_unlock_irqrestore(&fence->wq.lock, flags); } static int sync_debugfs_show(struct seq_file *s, void *unused) -- cgit v1.2.3 From 27e3917ab996cfcf68d0261006bd3d116e969402 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:16 -0200 Subject: staging/android: remove not used sync_timeline ops .dup and .compare are not used by the sync framework, so remove them from sw_sync. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sw_sync.c | 29 +---------------------------- drivers/staging/android/sync.c | 6 ------ drivers/staging/android/sync.h | 19 ------------------- 3 files changed, 1 insertion(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c index c4ff1679ebbc..566dcdc7e236 100644 --- a/drivers/staging/android/sw_sync.c +++ b/drivers/staging/android/sw_sync.c @@ -25,14 +25,6 @@ #include "sw_sync.h" -static int sw_sync_cmp(u32 a, u32 b) -{ - if (a == b) - return 0; - - return ((s32)a - (s32)b) < 0 ? -1 : 1; -} - struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value) { struct sw_sync_pt *pt; @@ -46,30 +38,13 @@ struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value) } EXPORT_SYMBOL(sw_sync_pt_create); -static struct sync_pt *sw_sync_pt_dup(struct sync_pt *sync_pt) -{ - struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt; - struct sw_sync_timeline *obj = - (struct sw_sync_timeline *)sync_pt_parent(sync_pt); - - return (struct sync_pt *)sw_sync_pt_create(obj, pt->value); -} - static int sw_sync_pt_has_signaled(struct sync_pt *sync_pt) { struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt; struct sw_sync_timeline *obj = (struct sw_sync_timeline *)sync_pt_parent(sync_pt); - return sw_sync_cmp(obj->value, pt->value) >= 0; -} - -static int sw_sync_pt_compare(struct sync_pt *a, struct sync_pt *b) -{ - struct sw_sync_pt *pt_a = (struct sw_sync_pt *)a; - struct sw_sync_pt *pt_b = (struct sw_sync_pt *)b; - - return sw_sync_cmp(pt_a->value, pt_b->value); + return (pt->value > obj->value) ? 0 : 1; } static int sw_sync_fill_driver_data(struct sync_pt *sync_pt, @@ -103,9 +78,7 @@ static void sw_sync_pt_value_str(struct sync_pt *sync_pt, static struct sync_timeline_ops sw_sync_timeline_ops = { .driver_name = "sw_sync", - .dup = sw_sync_pt_dup, .has_signaled = sw_sync_pt_has_signaled, - .compare = sw_sync_pt_compare, .fill_driver_data = sw_sync_fill_driver_data, .timeline_value_str = sw_sync_timeline_value_str, .pt_value_str = sw_sync_pt_value_str, diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 7a84f8853a8e..f4d9bcddb6f8 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -68,9 +68,6 @@ static void sync_timeline_free(struct kref *kref) sync_timeline_debug_remove(obj); - if (obj->ops->release_obj) - obj->ops->release_obj(obj); - kfree(obj); } @@ -383,9 +380,6 @@ static void android_fence_release(struct fence *fence) list_del(&pt->active_list); spin_unlock_irqrestore(fence->lock, flags); - if (parent->ops->free_pt) - parent->ops->free_pt(pt); - sync_timeline_put(parent); fence_free(&pt->base); } diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index e0865b94c8f7..b47058fbe8af 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -30,17 +30,10 @@ struct sync_fence; /** * struct sync_timeline_ops - sync object implementation ops * @driver_name: name of the implementation - * @dup: duplicate a sync_pt * @has_signaled: returns: * 1 if pt has signaled * 0 if pt has not signaled * <0 on error - * @compare: returns: - * 1 if b will signal before a - * 0 if a and b will signal at the same time - * -1 if a will signal before b - * @free_pt: called before sync_pt is freed - * @release_obj: called before sync_timeline is freed * @fill_driver_data: write implementation specific driver data to data. * should return an error if there is not enough room * as specified by size. This information is returned @@ -51,21 +44,9 @@ struct sync_fence; struct sync_timeline_ops { const char *driver_name; - /* required */ - struct sync_pt * (*dup)(struct sync_pt *pt); - /* required */ int (*has_signaled)(struct sync_pt *pt); - /* required */ - int (*compare)(struct sync_pt *a, struct sync_pt *b); - - /* optional */ - void (*free_pt)(struct sync_pt *sync_pt); - - /* optional */ - void (*release_obj)(struct sync_timeline *sync_timeline); - /* optional */ int (*fill_driver_data)(struct sync_pt *syncpt, void *data, int size); -- cgit v1.2.3 From 8a0044846115e74552b671a7073cffeec14b9316 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:17 -0200 Subject: staging/android: create a 'sync' dir for debugfs information Creates the 'sync' dir on debugfs root dir and move the 'sync' file to sync/info. This is the preparation to add more debug info and control. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync_debug.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index c7ee98f3b851..4dc6e03d6487 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -30,6 +31,8 @@ #ifdef CONFIG_DEBUG_FS +static struct dentry *dbgfs; + static LIST_HEAD(sync_timeline_list_head); static DEFINE_SPINLOCK(sync_timeline_list_lock); static LIST_HEAD(sync_fence_list_head); @@ -192,13 +195,13 @@ static int sync_debugfs_show(struct seq_file *s, void *unused) return 0; } -static int sync_debugfs_open(struct inode *inode, struct file *file) +static int sync_info_debugfs_open(struct inode *inode, struct file *file) { return single_open(file, sync_debugfs_show, inode->i_private); } -static const struct file_operations sync_debugfs_fops = { - .open = sync_debugfs_open, +static const struct file_operations sync_info_debugfs_fops = { + .open = sync_info_debugfs_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, @@ -206,11 +209,21 @@ static const struct file_operations sync_debugfs_fops = { static __init int sync_debugfs_init(void) { - debugfs_create_file("sync", S_IRUGO, NULL, NULL, &sync_debugfs_fops); + dbgfs = debugfs_create_dir("sync", NULL); + + debugfs_create_file("info", 0444, dbgfs, NULL, &sync_info_debugfs_fops); + return 0; } late_initcall(sync_debugfs_init); +static __exit void sync_debugfs_exit(void) +{ + if (dbgfs) + debugfs_remove_recursive(dbgfs); +} +module_exit(sync_debugfs_exit); + #define DUMP_CHUNK 256 static char sync_dump_buf[64 * 1024]; void sync_dump(void) -- cgit v1.2.3 From a44eb74cd413fa62733d7df89942eabaf26176eb Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:18 -0200 Subject: staging/android: move SW_SYNC_USER to a debugfs file This remove CONFIG_SW_SYNC_USER and instead compile the sw_sync file into debugpfs under /sync/sw_sync. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/Kconfig | 9 --- drivers/staging/android/sw_sync.c | 129 ----------------------------------- drivers/staging/android/sync_debug.c | 118 +++++++++++++++++++++++++++++++- 3 files changed, 117 insertions(+), 139 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 42b15126aa06..bd90d2002afb 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -57,15 +57,6 @@ config SW_SYNC synchronization. Useful when there is no hardware primitive backing the synchronization. -config SW_SYNC_USER - bool "Userspace API for SW_SYNC" - default n - depends on SW_SYNC - ---help--- - Provides a user space API to the sw sync object. - *WARNING* improper use of this can result in deadlocking kernel - drivers from userspace. - source "drivers/staging/android/ion/Kconfig" endif # if ANDROID diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c index 566dcdc7e236..f491dbce5696 100644 --- a/drivers/staging/android/sw_sync.c +++ b/drivers/staging/android/sw_sync.c @@ -102,132 +102,3 @@ void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc) sync_timeline_signal(&obj->obj); } EXPORT_SYMBOL(sw_sync_timeline_inc); - -#ifdef CONFIG_SW_SYNC_USER -/* *WARNING* - * - * improper use of this can result in deadlocking kernel drivers from userspace. - */ - -/* opening sw_sync create a new sync obj */ -static int sw_sync_open(struct inode *inode, struct file *file) -{ - struct sw_sync_timeline *obj; - char task_comm[TASK_COMM_LEN]; - - get_task_comm(task_comm, current); - - obj = sw_sync_timeline_create(task_comm); - if (!obj) - return -ENOMEM; - - file->private_data = obj; - - return 0; -} - -static int sw_sync_release(struct inode *inode, struct file *file) -{ - struct sw_sync_timeline *obj = file->private_data; - - sync_timeline_destroy(&obj->obj); - return 0; -} - -static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, - unsigned long arg) -{ - int fd = get_unused_fd_flags(O_CLOEXEC); - int err; - struct sync_pt *pt; - struct sync_fence *fence; - struct sw_sync_create_fence_data data; - - if (fd < 0) - return fd; - - if (copy_from_user(&data, (void __user *)arg, sizeof(data))) { - err = -EFAULT; - goto err; - } - - pt = sw_sync_pt_create(obj, data.value); - if (!pt) { - err = -ENOMEM; - goto err; - } - - data.name[sizeof(data.name) - 1] = '\0'; - fence = sync_fence_create(data.name, pt); - if (!fence) { - sync_pt_free(pt); - err = -ENOMEM; - goto err; - } - - data.fence = fd; - if (copy_to_user((void __user *)arg, &data, sizeof(data))) { - sync_fence_put(fence); - err = -EFAULT; - goto err; - } - - sync_fence_install(fence, fd); - - return 0; - -err: - put_unused_fd(fd); - return err; -} - -static long sw_sync_ioctl_inc(struct sw_sync_timeline *obj, unsigned long arg) -{ - u32 value; - - if (copy_from_user(&value, (void __user *)arg, sizeof(value))) - return -EFAULT; - - sw_sync_timeline_inc(obj, value); - - return 0; -} - -static long sw_sync_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct sw_sync_timeline *obj = file->private_data; - - switch (cmd) { - case SW_SYNC_IOC_CREATE_FENCE: - return sw_sync_ioctl_create_fence(obj, arg); - - case SW_SYNC_IOC_INC: - return sw_sync_ioctl_inc(obj, arg); - - default: - return -ENOTTY; - } -} - -static const struct file_operations sw_sync_fops = { - .owner = THIS_MODULE, - .open = sw_sync_open, - .release = sw_sync_release, - .unlocked_ioctl = sw_sync_ioctl, - .compat_ioctl = sw_sync_ioctl, -}; - -static struct miscdevice sw_sync_dev = { - .minor = MISC_DYNAMIC_MINOR, - .name = "sw_sync", - .fops = &sw_sync_fops, -}; - -static int __init sw_sync_device_init(void) -{ - return misc_register(&sw_sync_dev); -} -device_initcall(sw_sync_device_init); - -#endif /* CONFIG_SW_SYNC_USER */ diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index 4dc6e03d6487..33dec4219e99 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -27,7 +27,7 @@ #include #include #include -#include "sync.h" +#include "sw_sync.h" #ifdef CONFIG_DEBUG_FS @@ -207,11 +207,127 @@ static const struct file_operations sync_info_debugfs_fops = { .release = single_release, }; +/* + * *WARNING* + * + * improper use of this can result in deadlocking kernel drivers from userspace. + */ + +/* opening sw_sync create a new sync obj */ +static int sw_sync_debugfs_open(struct inode *inode, struct file *file) +{ + struct sw_sync_timeline *obj; + char task_comm[TASK_COMM_LEN]; + + get_task_comm(task_comm, current); + + obj = sw_sync_timeline_create(task_comm); + if (!obj) + return -ENOMEM; + + file->private_data = obj; + + return 0; +} + +static int sw_sync_debugfs_release(struct inode *inode, struct file *file) +{ + struct sw_sync_timeline *obj = file->private_data; + + sync_timeline_destroy(&obj->obj); + return 0; +} + +static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, + unsigned long arg) +{ + int fd = get_unused_fd_flags(O_CLOEXEC); + int err; + struct sync_pt *pt; + struct sync_fence *fence; + struct sw_sync_create_fence_data data; + + if (fd < 0) + return fd; + + if (copy_from_user(&data, (void __user *)arg, sizeof(data))) { + err = -EFAULT; + goto err; + } + + pt = sw_sync_pt_create(obj, data.value); + if (!pt) { + err = -ENOMEM; + goto err; + } + + data.name[sizeof(data.name) - 1] = '\0'; + fence = sync_fence_create(data.name, pt); + if (!fence) { + sync_pt_free(pt); + err = -ENOMEM; + goto err; + } + + data.fence = fd; + if (copy_to_user((void __user *)arg, &data, sizeof(data))) { + sync_fence_put(fence); + err = -EFAULT; + goto err; + } + + sync_fence_install(fence, fd); + + return 0; + +err: + put_unused_fd(fd); + return err; +} + +static long sw_sync_ioctl_inc(struct sw_sync_timeline *obj, unsigned long arg) +{ + u32 value; + + if (copy_from_user(&value, (void __user *)arg, sizeof(value))) + return -EFAULT; + + sw_sync_timeline_inc(obj, value); + + return 0; +} + +static long sw_sync_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct sw_sync_timeline *obj = file->private_data; + + switch (cmd) { + case SW_SYNC_IOC_CREATE_FENCE: + return sw_sync_ioctl_create_fence(obj, arg); + + case SW_SYNC_IOC_INC: + return sw_sync_ioctl_inc(obj, arg); + + default: + return -ENOTTY; + } +} + +static const struct file_operations sw_sync_debugfs_fops = { + .open = sw_sync_debugfs_open, + .release = sw_sync_debugfs_release, + .unlocked_ioctl = sw_sync_ioctl, + .compat_ioctl = sw_sync_ioctl, +}; + static __init int sync_debugfs_init(void) { dbgfs = debugfs_create_dir("sync", NULL); debugfs_create_file("info", 0444, dbgfs, NULL, &sync_info_debugfs_fops); + debugfs_create_file("sw_sync", 0644, dbgfs, NULL, + &sw_sync_debugfs_fops); return 0; } -- cgit v1.2.3 From d7fdb0ae9d115fa14ff3a5382c8a62de41c7786a Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:19 -0200 Subject: staging/android: rename sync_fence to sync_file sync_file has a more close meaning to what a sync_fence really, a struct that represent a file that can be used by userspace to get information on a fence, or wait for it to be signaled. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 254 ++++++++++++++++++----------------- drivers/staging/android/sync.h | 98 +++++++------- drivers/staging/android/sync_debug.c | 59 ++++---- drivers/staging/android/trace/sync.h | 10 +- drivers/staging/android/uapi/sync.h | 14 +- 5 files changed, 221 insertions(+), 214 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index f4d9bcddb6f8..8cccdf94ce77 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -32,7 +32,7 @@ #include "trace/sync.h" static const struct fence_ops android_fence_ops; -static const struct file_operations sync_fence_fops; +static const struct file_operations sync_file_fops; struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops, int size, const char *name) @@ -147,80 +147,81 @@ void sync_pt_free(struct sync_pt *pt) } EXPORT_SYMBOL(sync_pt_free); -static struct sync_fence *sync_fence_alloc(int size, const char *name) +static struct sync_file *sync_file_alloc(int size, const char *name) { - struct sync_fence *fence; + struct sync_file *sync_file; - fence = kzalloc(size, GFP_KERNEL); - if (!fence) + sync_file = kzalloc(size, GFP_KERNEL); + if (!sync_file) return NULL; - fence->file = anon_inode_getfile("sync_fence", &sync_fence_fops, - fence, 0); - if (IS_ERR(fence->file)) + sync_file->file = anon_inode_getfile("sync_file", &sync_file_fops, + sync_file, 0); + if (IS_ERR(sync_file->file)) goto err; - kref_init(&fence->kref); - strlcpy(fence->name, name, sizeof(fence->name)); + kref_init(&sync_file->kref); + strlcpy(sync_file->name, name, sizeof(sync_file->name)); - init_waitqueue_head(&fence->wq); + init_waitqueue_head(&sync_file->wq); - return fence; + return sync_file; err: - kfree(fence); + kfree(sync_file); return NULL; } static void fence_check_cb_func(struct fence *f, struct fence_cb *cb) { - struct sync_fence_cb *check; - struct sync_fence *fence; + struct sync_file_cb *check; + struct sync_file *sync_file; - check = container_of(cb, struct sync_fence_cb, cb); - fence = check->fence; + check = container_of(cb, struct sync_file_cb, cb); + sync_file = check->sync_file; - if (atomic_dec_and_test(&fence->status)) - wake_up_all(&fence->wq); + if (atomic_dec_and_test(&sync_file->status)) + wake_up_all(&sync_file->wq); } /* TODO: implement a create which takes more that one sync_pt */ -struct sync_fence *sync_fence_create_dma(const char *name, struct fence *pt) +struct sync_file *sync_file_create_dma(const char *name, struct fence *pt) { - struct sync_fence *fence; + struct sync_file *sync_file; - fence = sync_fence_alloc(offsetof(struct sync_fence, cbs[1]), name); - if (!fence) + sync_file = sync_file_alloc(offsetof(struct sync_file, cbs[1]), + name); + if (!sync_file) return NULL; - fence->num_fences = 1; - atomic_set(&fence->status, 1); + sync_file->num_fences = 1; + atomic_set(&sync_file->status, 1); - fence->cbs[0].sync_pt = pt; - fence->cbs[0].fence = fence; - if (fence_add_callback(pt, &fence->cbs[0].cb, fence_check_cb_func)) - atomic_dec(&fence->status); + sync_file->cbs[0].sync_pt = pt; + sync_file->cbs[0].sync_file = sync_file; + if (fence_add_callback(pt, &sync_file->cbs[0].cb, fence_check_cb_func)) + atomic_dec(&sync_file->status); - sync_fence_debug_add(fence); + sync_file_debug_add(sync_file); - return fence; + return sync_file; } -EXPORT_SYMBOL(sync_fence_create_dma); +EXPORT_SYMBOL(sync_file_create_dma); -struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt) +struct sync_file *sync_file_create(const char *name, struct sync_pt *pt) { - return sync_fence_create_dma(name, &pt->base); + return sync_file_create_dma(name, &pt->base); } -EXPORT_SYMBOL(sync_fence_create); +EXPORT_SYMBOL(sync_file_create); -struct sync_fence *sync_fence_fdget(int fd) +struct sync_file *sync_file_fdget(int fd) { struct file *file = fget(fd); if (!file) return NULL; - if (file->f_op != &sync_fence_fops) + if (file->f_op != &sync_file_fops) goto err; return file->private_data; @@ -229,70 +230,71 @@ err: fput(file); return NULL; } -EXPORT_SYMBOL(sync_fence_fdget); +EXPORT_SYMBOL(sync_file_fdget); -void sync_fence_put(struct sync_fence *fence) +void sync_file_put(struct sync_file *sync_file) { - fput(fence->file); + fput(sync_file->file); } -EXPORT_SYMBOL(sync_fence_put); +EXPORT_SYMBOL(sync_file_put); -void sync_fence_install(struct sync_fence *fence, int fd) +void sync_file_install(struct sync_file *sync_file, int fd) { - fd_install(fd, fence->file); + fd_install(fd, sync_file->file); } -EXPORT_SYMBOL(sync_fence_install); +EXPORT_SYMBOL(sync_file_install); -static void sync_fence_add_pt(struct sync_fence *fence, - int *i, struct fence *pt) +static void sync_file_add_pt(struct sync_file *sync_file, int *i, + struct fence *pt) { - fence->cbs[*i].sync_pt = pt; - fence->cbs[*i].fence = fence; + sync_file->cbs[*i].sync_pt = pt; + sync_file->cbs[*i].sync_file = sync_file; - if (!fence_add_callback(pt, &fence->cbs[*i].cb, fence_check_cb_func)) { + if (!fence_add_callback(pt, &sync_file->cbs[*i].cb, + fence_check_cb_func)) { fence_get(pt); (*i)++; } } -struct sync_fence *sync_fence_merge(const char *name, - struct sync_fence *a, struct sync_fence *b) +struct sync_file *sync_file_merge(const char *name, + struct sync_file *a, struct sync_file *b) { int num_fences = a->num_fences + b->num_fences; - struct sync_fence *fence; + struct sync_file *sync_file; int i, i_a, i_b; - unsigned long size = offsetof(struct sync_fence, cbs[num_fences]); + unsigned long size = offsetof(struct sync_file, cbs[num_fences]); - fence = sync_fence_alloc(size, name); - if (!fence) + sync_file = sync_file_alloc(size, name); + if (!sync_file) return NULL; - atomic_set(&fence->status, num_fences); + atomic_set(&sync_file->status, num_fences); /* - * Assume sync_fence a and b are both ordered and have no + * Assume sync_file a and b are both ordered and have no * duplicates with the same context. * - * If a sync_fence can only be created with sync_fence_merge - * and sync_fence_create, this is a reasonable assumption. + * If a sync_file can only be created with sync_file_merge + * and sync_file_create, this is a reasonable assumption. */ for (i = i_a = i_b = 0; i_a < a->num_fences && i_b < b->num_fences; ) { struct fence *pt_a = a->cbs[i_a].sync_pt; struct fence *pt_b = b->cbs[i_b].sync_pt; if (pt_a->context < pt_b->context) { - sync_fence_add_pt(fence, &i, pt_a); + sync_file_add_pt(sync_file, &i, pt_a); i_a++; } else if (pt_a->context > pt_b->context) { - sync_fence_add_pt(fence, &i, pt_b); + sync_file_add_pt(sync_file, &i, pt_b); i_b++; } else { if (pt_a->seqno - pt_b->seqno <= INT_MAX) - sync_fence_add_pt(fence, &i, pt_a); + sync_file_add_pt(sync_file, &i, pt_a); else - sync_fence_add_pt(fence, &i, pt_b); + sync_file_add_pt(sync_file, &i, pt_b); i_a++; i_b++; @@ -300,21 +302,21 @@ struct sync_fence *sync_fence_merge(const char *name, } for (; i_a < a->num_fences; i_a++) - sync_fence_add_pt(fence, &i, a->cbs[i_a].sync_pt); + sync_file_add_pt(sync_file, &i, a->cbs[i_a].sync_pt); for (; i_b < b->num_fences; i_b++) - sync_fence_add_pt(fence, &i, b->cbs[i_b].sync_pt); + sync_file_add_pt(sync_file, &i, b->cbs[i_b].sync_pt); if (num_fences > i) - atomic_sub(num_fences - i, &fence->status); - fence->num_fences = i; + atomic_sub(num_fences - i, &sync_file->status); + sync_file->num_fences = i; - sync_fence_debug_add(fence); - return fence; + sync_file_debug_add(sync_file); + return sync_file; } -EXPORT_SYMBOL(sync_fence_merge); +EXPORT_SYMBOL(sync_file_merge); -int sync_fence_wait(struct sync_fence *fence, long timeout) +int sync_file_wait(struct sync_file *sync_file, long timeout) { long ret; int i; @@ -324,33 +326,33 @@ int sync_fence_wait(struct sync_fence *fence, long timeout) else timeout = msecs_to_jiffies(timeout); - trace_sync_wait(fence, 1); - for (i = 0; i < fence->num_fences; ++i) - trace_sync_pt(fence->cbs[i].sync_pt); - ret = wait_event_interruptible_timeout(fence->wq, - atomic_read(&fence->status) <= 0, + trace_sync_wait(sync_file, 1); + for (i = 0; i < sync_file->num_fences; ++i) + trace_sync_pt(sync_file->cbs[i].sync_pt); + ret = wait_event_interruptible_timeout(sync_file->wq, + atomic_read(&sync_file->status) <= 0, timeout); - trace_sync_wait(fence, 0); + trace_sync_wait(sync_file, 0); if (ret < 0) { return ret; } else if (ret == 0) { if (timeout) { - pr_info("fence timeout on [%p] after %dms\n", fence, - jiffies_to_msecs(timeout)); + pr_info("sync_file timeout on [%p] after %dms\n", + sync_file, jiffies_to_msecs(timeout)); sync_dump(); } return -ETIME; } - ret = atomic_read(&fence->status); + ret = atomic_read(&sync_file->status); if (ret) { - pr_info("fence error %ld on [%p]\n", ret, fence); + pr_info("sync_file error %ld on [%p]\n", ret, sync_file); sync_dump(); } return ret; } -EXPORT_SYMBOL(sync_fence_wait); +EXPORT_SYMBOL(sync_file_wait); static const char *android_fence_get_driver_name(struct fence *fence) { @@ -459,37 +461,39 @@ static const struct fence_ops android_fence_ops = { .timeline_value_str = android_fence_timeline_value_str, }; -static void sync_fence_free(struct kref *kref) +static void sync_file_free(struct kref *kref) { - struct sync_fence *fence = container_of(kref, struct sync_fence, kref); + struct sync_file *sync_file = container_of(kref, struct sync_file, + kref); int i; - for (i = 0; i < fence->num_fences; ++i) { - fence_remove_callback(fence->cbs[i].sync_pt, &fence->cbs[i].cb); - fence_put(fence->cbs[i].sync_pt); + for (i = 0; i < sync_file->num_fences; ++i) { + fence_remove_callback(sync_file->cbs[i].sync_pt, + &sync_file->cbs[i].cb); + fence_put(sync_file->cbs[i].sync_pt); } - kfree(fence); + kfree(sync_file); } -static int sync_fence_release(struct inode *inode, struct file *file) +static int sync_file_release(struct inode *inode, struct file *file) { - struct sync_fence *fence = file->private_data; + struct sync_file *sync_file = file->private_data; - sync_fence_debug_remove(fence); + sync_file_debug_remove(sync_file); - kref_put(&fence->kref, sync_fence_free); + kref_put(&sync_file->kref, sync_file_free); return 0; } -static unsigned int sync_fence_poll(struct file *file, poll_table *wait) +static unsigned int sync_file_poll(struct file *file, poll_table *wait) { - struct sync_fence *fence = file->private_data; + struct sync_file *sync_file = file->private_data; int status; - poll_wait(file, &fence->wq, wait); + poll_wait(file, &sync_file->wq, wait); - status = atomic_read(&fence->status); + status = atomic_read(&sync_file->status); if (!status) return POLLIN; @@ -498,21 +502,23 @@ static unsigned int sync_fence_poll(struct file *file, poll_table *wait) return 0; } -static long sync_fence_ioctl_wait(struct sync_fence *fence, unsigned long arg) +static long sync_file_ioctl_wait(struct sync_file *sync_file, + unsigned long arg) { __s32 value; if (copy_from_user(&value, (void __user *)arg, sizeof(value))) return -EFAULT; - return sync_fence_wait(fence, value); + return sync_file_wait(sync_file, value); } -static long sync_fence_ioctl_merge(struct sync_fence *fence, unsigned long arg) +static long sync_file_ioctl_merge(struct sync_file *sync_file, + unsigned long arg) { int fd = get_unused_fd_flags(O_CLOEXEC); int err; - struct sync_fence *fence2, *fence3; + struct sync_file *fence2, *fence3; struct sync_merge_data data; if (fd < 0) @@ -523,14 +529,14 @@ static long sync_fence_ioctl_merge(struct sync_fence *fence, unsigned long arg) goto err_put_fd; } - fence2 = sync_fence_fdget(data.fd2); + fence2 = sync_file_fdget(data.fd2); if (!fence2) { err = -ENOENT; goto err_put_fd; } data.name[sizeof(data.name) - 1] = '\0'; - fence3 = sync_fence_merge(data.name, fence, fence2); + fence3 = sync_file_merge(data.name, sync_file, fence2); if (!fence3) { err = -ENOMEM; goto err_put_fence2; @@ -542,15 +548,15 @@ static long sync_fence_ioctl_merge(struct sync_fence *fence, unsigned long arg) goto err_put_fence3; } - sync_fence_install(fence3, fd); - sync_fence_put(fence2); + sync_file_install(fence3, fd); + sync_file_put(fence2); return 0; err_put_fence3: - sync_fence_put(fence3); + sync_file_put(fence3); err_put_fence2: - sync_fence_put(fence2); + sync_file_put(fence2); err_put_fd: put_unused_fd(fd); @@ -589,10 +595,10 @@ static int sync_fill_pt_info(struct fence *fence, void *data, int size) return info->len; } -static long sync_fence_ioctl_fence_info(struct sync_fence *fence, +static long sync_file_ioctl_fence_info(struct sync_file *sync_file, unsigned long arg) { - struct sync_fence_info_data *data; + struct sync_file_info_data *data; __u32 size; __u32 len = 0; int ret, i; @@ -600,7 +606,7 @@ static long sync_fence_ioctl_fence_info(struct sync_fence *fence, if (copy_from_user(&size, (void __user *)arg, sizeof(size))) return -EFAULT; - if (size < sizeof(struct sync_fence_info_data)) + if (size < sizeof(struct sync_file_info_data)) return -EINVAL; if (size > 4096) @@ -610,15 +616,15 @@ static long sync_fence_ioctl_fence_info(struct sync_fence *fence, if (!data) return -ENOMEM; - strlcpy(data->name, fence->name, sizeof(data->name)); - data->status = atomic_read(&fence->status); + strlcpy(data->name, sync_file->name, sizeof(data->name)); + data->status = atomic_read(&sync_file->status); if (data->status >= 0) data->status = !data->status; - len = sizeof(struct sync_fence_info_data); + len = sizeof(struct sync_file_info_data); - for (i = 0; i < fence->num_fences; ++i) { - struct fence *pt = fence->cbs[i].sync_pt; + for (i = 0; i < sync_file->num_fences; ++i) { + struct fence *pt = sync_file->cbs[i].sync_pt; ret = sync_fill_pt_info(pt, (u8 *)data + len, size - len); @@ -641,30 +647,30 @@ out: return ret; } -static long sync_fence_ioctl(struct file *file, unsigned int cmd, +static long sync_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct sync_fence *fence = file->private_data; + struct sync_file *sync_file = file->private_data; switch (cmd) { case SYNC_IOC_WAIT: - return sync_fence_ioctl_wait(fence, arg); + return sync_file_ioctl_wait(sync_file, arg); case SYNC_IOC_MERGE: - return sync_fence_ioctl_merge(fence, arg); + return sync_file_ioctl_merge(sync_file, arg); case SYNC_IOC_FENCE_INFO: - return sync_fence_ioctl_fence_info(fence, arg); + return sync_file_ioctl_fence_info(sync_file, arg); default: return -ENOTTY; } } -static const struct file_operations sync_fence_fops = { - .release = sync_fence_release, - .poll = sync_fence_poll, - .unlocked_ioctl = sync_fence_ioctl, - .compat_ioctl = sync_fence_ioctl, +static const struct file_operations sync_file_fops = { + .release = sync_file_release, + .poll = sync_file_poll, + .unlocked_ioctl = sync_file_ioctl, + .compat_ioctl = sync_file_ioctl, }; diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index b47058fbe8af..bec62c37ec7c 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -25,7 +25,7 @@ struct sync_timeline; struct sync_pt; -struct sync_fence; +struct sync_file; /** * struct sync_timeline_ops - sync object implementation ops @@ -108,36 +108,36 @@ static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt) child_list_lock); } -struct sync_fence_cb { +struct sync_file_cb { struct fence_cb cb; struct fence *sync_pt; - struct sync_fence *fence; + struct sync_file *sync_file; }; /** - * struct sync_fence - sync fence + * struct sync_file - sync file to export to the userspace * @file: file representing this fence * @kref: reference count on fence. - * @name: name of sync_fence. Useful for debugging - * @sync_fence_list: membership in global fence list + * @name: name of sync_file. Useful for debugging + * @sync_file_list: membership in global file list * @num_fences number of sync_pts in the fence * @wq: wait queue for fence signaling * @status: 0: signaled, >0:active, <0: error * @cbs: sync_pts callback information */ -struct sync_fence { +struct sync_file { struct file *file; struct kref kref; char name[32]; #ifdef CONFIG_DEBUG_FS - struct list_head sync_fence_list; + struct list_head sync_file_list; #endif int num_fences; wait_queue_head_t wq; atomic_t status; - struct sync_fence_cb cbs[]; + struct sync_file_cb cbs[]; }; /* @@ -199,95 +199,95 @@ struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size); void sync_pt_free(struct sync_pt *pt); /** - * sync_fence_create() - creates a sync fence - * @name: name of fence to create - * @pt: sync_pt to add to the fence + * sync_file_create() - creates a sync file + * @name: name of file to create + * @pt: sync_pt to add to the file * - * Creates a fence containg @pt. Once this is called, the fence takes + * Creates a sync_file containg @pt. Once this is called, the sync_file takes * ownership of @pt. */ -struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt); +struct sync_file *sync_file_create(const char *name, struct sync_pt *pt); /** - * sync_fence_create_dma() - creates a sync fence from dma-fence - * @name: name of fence to create - * @pt: dma-fence to add to the fence + * sync_file_create_dma() - creates a sync file from dma-fence + * @name: name of file to create + * @pt: dma-fence to add to the file * - * Creates a fence containg @pt. Once this is called, the fence takes + * Creates a sync_file containg @pt. Once this is called, the fence takes * ownership of @pt. */ -struct sync_fence *sync_fence_create_dma(const char *name, struct fence *pt); +struct sync_file *sync_file_create_dma(const char *name, struct fence *pt); /* - * API for sync_fence consumers + * API for sync_file consumers */ /** - * sync_fence_merge() - merge two fences + * sync_file_merge() - merge two sync_files * @name: name of new fence - * @a: fence a - * @b: fence b + * @a: sync_file a + * @b: sync_file b * - * Creates a new fence which contains copies of all the sync_pts in both - * @a and @b. @a and @b remain valid, independent fences. Returns the - * new merged fence or NULL in case of error. + * Creates a new sync_file which contains copies of all the sync_pts in both + * @a and @b. @a and @b remain valid, independent sync_file. Returns the + * new merged sync_file or NULL in case of error. */ -struct sync_fence *sync_fence_merge(const char *name, - struct sync_fence *a, struct sync_fence *b); +struct sync_file *sync_file_merge(const char *name, + struct sync_file *a, struct sync_file *b); /** - * sync_fence_fdget() - get a fence from an fd + * sync_file_fdget() - get a sync_file from an fd * @fd: fd referencing a fence * - * Ensures @fd references a valid fence, increments the refcount of the backing - * file, and returns the fence. Returns the fence or NULL in case of error. + * Ensures @fd references a valid sync_file, increments the refcount of the + * backing file. Returns the sync_file or NULL in case of error. */ -struct sync_fence *sync_fence_fdget(int fd); +struct sync_file *sync_file_fdget(int fd); /** - * sync_fence_put() - puts a reference of a sync fence - * @fence: fence to put + * sync_file_put() - puts a reference of a sync_file + * @sync_file: sync_file to put * - * Puts a reference on @fence. If this is the last reference, the fence and - * all it's sync_pts will be freed + * Puts a reference on @sync_fence. If this is the last reference, the + * sync_fil and all it's sync_pts will be freed */ -void sync_fence_put(struct sync_fence *fence); +void sync_file_put(struct sync_file *sync_file); /** - * sync_fence_install() - installs a fence into a file descriptor - * @fence: fence to install + * sync_file_install() - installs a sync_file into a file descriptor + * @sync_file: sync_file to install * @fd: file descriptor in which to install the fence * - * Installs @fence into @fd. @fd's should be acquired through + * Installs @sync_file into @fd. @fd's should be acquired through * get_unused_fd_flags(O_CLOEXEC). */ -void sync_fence_install(struct sync_fence *fence, int fd); +void sync_file_install(struct sync_file *sync_file, int fd); /** - * sync_fence_wait() - wait on fence - * @fence: fence to wait on + * sync_file_wait() - wait on sync file + * @sync_file: file to wait on * @tiemout: timeout in ms * - * Wait for @fence to be signaled or have an error. Waits indefinitely + * Wait for @sync_file to be signaled or have an error. Waits indefinitely * if @timeout < 0. * * Returns 0 if fence signaled, > 0 if it is still active and <0 on error */ -int sync_fence_wait(struct sync_fence *fence, long timeout); +int sync_file_wait(struct sync_file *sync_file, long timeout); #ifdef CONFIG_DEBUG_FS void sync_timeline_debug_add(struct sync_timeline *obj); void sync_timeline_debug_remove(struct sync_timeline *obj); -void sync_fence_debug_add(struct sync_fence *fence); -void sync_fence_debug_remove(struct sync_fence *fence); +void sync_file_debug_add(struct sync_file *fence); +void sync_file_debug_remove(struct sync_file *fence); void sync_dump(void); #else # define sync_timeline_debug_add(obj) # define sync_timeline_debug_remove(obj) -# define sync_fence_debug_add(fence) -# define sync_fence_debug_remove(fence) +# define sync_file_debug_add(fence) +# define sync_file_debug_remove(fence) # define sync_dump() #endif diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index 33dec4219e99..f1880240973d 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -35,8 +35,8 @@ static struct dentry *dbgfs; static LIST_HEAD(sync_timeline_list_head); static DEFINE_SPINLOCK(sync_timeline_list_lock); -static LIST_HEAD(sync_fence_list_head); -static DEFINE_SPINLOCK(sync_fence_list_lock); +static LIST_HEAD(sync_file_list_head); +static DEFINE_SPINLOCK(sync_file_list_lock); void sync_timeline_debug_add(struct sync_timeline *obj) { @@ -56,22 +56,22 @@ void sync_timeline_debug_remove(struct sync_timeline *obj) spin_unlock_irqrestore(&sync_timeline_list_lock, flags); } -void sync_fence_debug_add(struct sync_fence *fence) +void sync_file_debug_add(struct sync_file *sync_file) { unsigned long flags; - spin_lock_irqsave(&sync_fence_list_lock, flags); - list_add_tail(&fence->sync_fence_list, &sync_fence_list_head); - spin_unlock_irqrestore(&sync_fence_list_lock, flags); + spin_lock_irqsave(&sync_file_list_lock, flags); + list_add_tail(&sync_file->sync_file_list, &sync_file_list_head); + spin_unlock_irqrestore(&sync_file_list_lock, flags); } -void sync_fence_debug_remove(struct sync_fence *fence) +void sync_file_debug_remove(struct sync_file *sync_file) { unsigned long flags; - spin_lock_irqsave(&sync_fence_list_lock, flags); - list_del(&fence->sync_fence_list); - spin_unlock_irqrestore(&sync_fence_list_lock, flags); + spin_lock_irqsave(&sync_file_list_lock, flags); + list_del(&sync_file->sync_file_list); + spin_unlock_irqrestore(&sync_file_list_lock, flags); } static const char *sync_status_str(int status) @@ -152,17 +152,18 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) spin_unlock_irqrestore(&obj->child_list_lock, flags); } -static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) -{ +static void sync_print_sync_file(struct seq_file *s, + struct sync_file *sync_file) + { int i; - seq_printf(s, "[%p] %s: %s\n", fence, fence->name, - sync_status_str(atomic_read(&fence->status))); - - for (i = 0; i < fence->num_fences; ++i) - sync_print_pt(s, fence->cbs[i].sync_pt, true); -} + seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name, + sync_status_str(atomic_read(&sync_file->status))); + for (i = 0; i < sync_file->num_fences; ++i) + sync_print_pt(s, sync_file->cbs[i].sync_pt, true); + } + static int sync_debugfs_show(struct seq_file *s, void *unused) { unsigned long flags; @@ -183,15 +184,15 @@ static int sync_debugfs_show(struct seq_file *s, void *unused) seq_puts(s, "fences:\n--------------\n"); - spin_lock_irqsave(&sync_fence_list_lock, flags); - list_for_each(pos, &sync_fence_list_head) { - struct sync_fence *fence = - container_of(pos, struct sync_fence, sync_fence_list); + spin_lock_irqsave(&sync_file_list_lock, flags); + list_for_each(pos, &sync_file_list_head) { + struct sync_file *sync_file = + container_of(pos, struct sync_file, sync_file_list); - sync_print_fence(s, fence); + sync_print_sync_file(s, sync_file); seq_puts(s, "\n"); } - spin_unlock_irqrestore(&sync_fence_list_lock, flags); + spin_unlock_irqrestore(&sync_file_list_lock, flags); return 0; } @@ -244,7 +245,7 @@ static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, int fd = get_unused_fd_flags(O_CLOEXEC); int err; struct sync_pt *pt; - struct sync_fence *fence; + struct sync_file *sync_file; struct sw_sync_create_fence_data data; if (fd < 0) @@ -262,8 +263,8 @@ static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, } data.name[sizeof(data.name) - 1] = '\0'; - fence = sync_fence_create(data.name, pt); - if (!fence) { + sync_file = sync_file_create(data.name, pt); + if (!sync_file) { sync_pt_free(pt); err = -ENOMEM; goto err; @@ -271,12 +272,12 @@ static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, data.fence = fd; if (copy_to_user((void __user *)arg, &data, sizeof(data))) { - sync_fence_put(fence); + sync_file_put(sync_file); err = -EFAULT; goto err; } - sync_fence_install(fence, fd); + sync_file_install(sync_file, fd); return 0; diff --git a/drivers/staging/android/trace/sync.h b/drivers/staging/android/trace/sync.h index 77edb977a7bf..80f5da4f2aa5 100644 --- a/drivers/staging/android/trace/sync.h +++ b/drivers/staging/android/trace/sync.h @@ -33,19 +33,19 @@ TRACE_EVENT(sync_timeline, ); TRACE_EVENT(sync_wait, - TP_PROTO(struct sync_fence *fence, int begin), + TP_PROTO(struct sync_file *sync_file, int begin), - TP_ARGS(fence, begin), + TP_ARGS(sync_file, begin), TP_STRUCT__entry( - __string(name, fence->name) + __string(name, sync_file->name) __field(s32, status) __field(u32, begin) ), TP_fast_assign( - __assign_str(name, fence->name); - __entry->status = atomic_read(&fence->status); + __assign_str(name, sync_file->name); + __entry->status = atomic_read(&sync_file->status); __entry->begin = begin; ), diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h index e964c751f6b8..73deb6907ce1 100644 --- a/drivers/staging/android/uapi/sync.h +++ b/drivers/staging/android/uapi/sync.h @@ -46,15 +46,15 @@ struct sync_pt_info { }; /** - * struct sync_fence_info_data - data returned from fence info ioctl + * struct sync_file_info_data - data returned from fence info ioctl * @len: ioctl caller writes the size of the buffer its passing in. - * ioctl returns length of sync_fence_data returned to userspace - * including pt_info. + * ioctl returns length of sync_file_info_data returned to + * userspace including pt_info. * @name: name of fence * @status: status of fence. 1: signaled 0:active <0:error * @pt_info: a sync_pt_info struct for every sync_pt in the fence */ -struct sync_fence_info_data { +struct sync_file_info_data { __u32 len; char name[32]; __s32 status; @@ -83,15 +83,15 @@ struct sync_fence_info_data { /** * DOC: SYNC_IOC_FENCE_INFO - get detailed information on a fence * - * Takes a struct sync_fence_info_data with extra space allocated for pt_info. + * Takes a struct sync_file_info_data with extra space allocated for pt_info. * Caller should write the size of the buffer into len. On return, len is - * updated to reflect the total size of the sync_fence_info_data including + * updated to reflect the total size of the sync_file_info_data including * pt_info. * * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence. * To iterate over the sync_pt_infos, use the sync_pt_info.len field. */ #define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2,\ - struct sync_fence_info_data) + struct sync_file_info_data) #endif /* _UAPI_LINUX_SYNC_H */ -- cgit v1.2.3 From c88b26dd8eda48758967c87b4ef89ae8e35f1e71 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:20 -0200 Subject: staging/android: rename 'sync_pt' to 'fence' in struct sync_fence_cb 'sync_pt' is actually declared as struct fence so to make the name means its type we rename it to 'fence'. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 20 ++++++++++---------- drivers/staging/android/sync.h | 2 +- drivers/staging/android/sync_debug.c | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 8cccdf94ce77..22b1d9b03fd6 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -197,7 +197,7 @@ struct sync_file *sync_file_create_dma(const char *name, struct fence *pt) sync_file->num_fences = 1; atomic_set(&sync_file->status, 1); - sync_file->cbs[0].sync_pt = pt; + sync_file->cbs[0].fence = pt; sync_file->cbs[0].sync_file = sync_file; if (fence_add_callback(pt, &sync_file->cbs[0].cb, fence_check_cb_func)) atomic_dec(&sync_file->status); @@ -247,7 +247,7 @@ EXPORT_SYMBOL(sync_file_install); static void sync_file_add_pt(struct sync_file *sync_file, int *i, struct fence *pt) { - sync_file->cbs[*i].sync_pt = pt; + sync_file->cbs[*i].fence = pt; sync_file->cbs[*i].sync_file = sync_file; if (!fence_add_callback(pt, &sync_file->cbs[*i].cb, @@ -279,8 +279,8 @@ struct sync_file *sync_file_merge(const char *name, * and sync_file_create, this is a reasonable assumption. */ for (i = i_a = i_b = 0; i_a < a->num_fences && i_b < b->num_fences; ) { - struct fence *pt_a = a->cbs[i_a].sync_pt; - struct fence *pt_b = b->cbs[i_b].sync_pt; + struct fence *pt_a = a->cbs[i_a].fence; + struct fence *pt_b = b->cbs[i_b].fence; if (pt_a->context < pt_b->context) { sync_file_add_pt(sync_file, &i, pt_a); @@ -302,10 +302,10 @@ struct sync_file *sync_file_merge(const char *name, } for (; i_a < a->num_fences; i_a++) - sync_file_add_pt(sync_file, &i, a->cbs[i_a].sync_pt); + sync_file_add_pt(sync_file, &i, a->cbs[i_a].fence); for (; i_b < b->num_fences; i_b++) - sync_file_add_pt(sync_file, &i, b->cbs[i_b].sync_pt); + sync_file_add_pt(sync_file, &i, b->cbs[i_b].fence); if (num_fences > i) atomic_sub(num_fences - i, &sync_file->status); @@ -328,7 +328,7 @@ int sync_file_wait(struct sync_file *sync_file, long timeout) trace_sync_wait(sync_file, 1); for (i = 0; i < sync_file->num_fences; ++i) - trace_sync_pt(sync_file->cbs[i].sync_pt); + trace_sync_pt(sync_file->cbs[i].fence); ret = wait_event_interruptible_timeout(sync_file->wq, atomic_read(&sync_file->status) <= 0, timeout); @@ -468,9 +468,9 @@ static void sync_file_free(struct kref *kref) int i; for (i = 0; i < sync_file->num_fences; ++i) { - fence_remove_callback(sync_file->cbs[i].sync_pt, + fence_remove_callback(sync_file->cbs[i].fence, &sync_file->cbs[i].cb); - fence_put(sync_file->cbs[i].sync_pt); + fence_put(sync_file->cbs[i].fence); } kfree(sync_file); @@ -624,7 +624,7 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, len = sizeof(struct sync_file_info_data); for (i = 0; i < sync_file->num_fences; ++i) { - struct fence *pt = sync_file->cbs[i].sync_pt; + struct fence *pt = sync_file->cbs[i].fence; ret = sync_fill_pt_info(pt, (u8 *)data + len, size - len); diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index bec62c37ec7c..a18d1e3365fb 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -110,7 +110,7 @@ static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt) struct sync_file_cb { struct fence_cb cb; - struct fence *sync_pt; + struct fence *fence; struct sync_file *sync_file; }; diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index f1880240973d..85ae98a63a1e 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -161,7 +161,7 @@ static void sync_print_sync_file(struct seq_file *s, sync_status_str(atomic_read(&sync_file->status))); for (i = 0; i < sync_file->num_fences; ++i) - sync_print_pt(s, sync_file->cbs[i].sync_pt, true); + sync_print_pt(s, sync_file->cbs[i].fence, true); } static int sync_debugfs_show(struct seq_file *s, void *unused) -- cgit v1.2.3 From b55b54b5db330e36cd465adb3fbe274ffb1061d3 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:21 -0200 Subject: staging/android: remove struct sync_pt struct sync_pt was just wrapping around struct fence and creating an extra abstraction layer. The only two members of struct sync_pt, child_list and active_list, were moved to struct fence in an earlier commit. After removing those two members struct sync_pt is nothing more than struct fence, so remove it all and use struct fence directly. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sw_sync.c | 23 ++++---- drivers/staging/android/sw_sync.h | 8 +-- drivers/staging/android/sync.c | 101 +++++++++++++++-------------------- drivers/staging/android/sync.h | 63 +++++++--------------- drivers/staging/android/sync_debug.c | 49 ++++++++--------- drivers/staging/android/trace/sync.h | 14 ++--- include/linux/fence.h | 2 + 7 files changed, 113 insertions(+), 147 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c index f491dbce5696..3bee959b41d8 100644 --- a/drivers/staging/android/sw_sync.c +++ b/drivers/staging/android/sw_sync.c @@ -25,7 +25,7 @@ #include "sw_sync.h" -struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value) +struct fence *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value) { struct sw_sync_pt *pt; @@ -34,23 +34,23 @@ struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value) pt->value = value; - return (struct sync_pt *)pt; + return (struct fence *)pt; } EXPORT_SYMBOL(sw_sync_pt_create); -static int sw_sync_pt_has_signaled(struct sync_pt *sync_pt) +static int sw_sync_fence_has_signaled(struct fence *fence) { - struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt; + struct sw_sync_pt *pt = (struct sw_sync_pt *)fence; struct sw_sync_timeline *obj = - (struct sw_sync_timeline *)sync_pt_parent(sync_pt); + (struct sw_sync_timeline *)fence_parent(fence); return (pt->value > obj->value) ? 0 : 1; } -static int sw_sync_fill_driver_data(struct sync_pt *sync_pt, +static int sw_sync_fill_driver_data(struct fence *fence, void *data, int size) { - struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt; + struct sw_sync_pt *pt = (struct sw_sync_pt *)fence; if (size < sizeof(pt->value)) return -ENOMEM; @@ -68,20 +68,19 @@ static void sw_sync_timeline_value_str(struct sync_timeline *sync_timeline, snprintf(str, size, "%d", timeline->value); } -static void sw_sync_pt_value_str(struct sync_pt *sync_pt, - char *str, int size) +static void sw_sync_fence_value_str(struct fence *fence, char *str, int size) { - struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt; + struct sw_sync_pt *pt = (struct sw_sync_pt *)fence; snprintf(str, size, "%d", pt->value); } static struct sync_timeline_ops sw_sync_timeline_ops = { .driver_name = "sw_sync", - .has_signaled = sw_sync_pt_has_signaled, + .has_signaled = sw_sync_fence_has_signaled, .fill_driver_data = sw_sync_fill_driver_data, .timeline_value_str = sw_sync_timeline_value_str, - .pt_value_str = sw_sync_pt_value_str, + .fence_value_str = sw_sync_fence_value_str, }; struct sw_sync_timeline *sw_sync_timeline_create(const char *name) diff --git a/drivers/staging/android/sw_sync.h b/drivers/staging/android/sw_sync.h index c87ae9ebf267..e18667bfb0ca 100644 --- a/drivers/staging/android/sw_sync.h +++ b/drivers/staging/android/sw_sync.h @@ -29,7 +29,7 @@ struct sw_sync_timeline { }; struct sw_sync_pt { - struct sync_pt pt; + struct fence pt; u32 value; }; @@ -38,7 +38,7 @@ struct sw_sync_pt { struct sw_sync_timeline *sw_sync_timeline_create(const char *name); void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc); -struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value); +struct fence *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value); #else static inline struct sw_sync_timeline *sw_sync_timeline_create(const char *name) { @@ -49,8 +49,8 @@ static inline void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc) { } -static inline struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, - u32 value) +static inline struct fence *sw_sync_pt_create(struct sw_sync_timeline *obj, + u32 value) { return NULL; } diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 22b1d9b03fd6..3c2c8d07df62 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -102,51 +102,45 @@ void sync_timeline_signal(struct sync_timeline *obj) { unsigned long flags; LIST_HEAD(signaled_pts); - struct sync_pt *pt, *next; + struct fence *fence, *next; trace_sync_timeline(obj); spin_lock_irqsave(&obj->child_list_lock, flags); - list_for_each_entry_safe(pt, next, &obj->active_list_head, + list_for_each_entry_safe(fence, next, &obj->active_list_head, active_list) { - if (fence_is_signaled_locked(&pt->base)) - list_del_init(&pt->active_list); + if (fence_is_signaled_locked(fence)) + list_del_init(&fence->active_list); } spin_unlock_irqrestore(&obj->child_list_lock, flags); } EXPORT_SYMBOL(sync_timeline_signal); -struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size) +struct fence *sync_pt_create(struct sync_timeline *obj, int size) { unsigned long flags; - struct sync_pt *pt; + struct fence *fence; - if (size < sizeof(struct sync_pt)) + if (size < sizeof(*fence)) return NULL; - pt = kzalloc(size, GFP_KERNEL); - if (!pt) + fence = kzalloc(size, GFP_KERNEL); + if (!fence) return NULL; spin_lock_irqsave(&obj->child_list_lock, flags); sync_timeline_get(obj); - fence_init(&pt->base, &android_fence_ops, &obj->child_list_lock, + fence_init(fence, &android_fence_ops, &obj->child_list_lock, obj->context, ++obj->value); - list_add_tail(&pt->child_list, &obj->child_list_head); - INIT_LIST_HEAD(&pt->active_list); + list_add_tail(&fence->child_list, &obj->child_list_head); + INIT_LIST_HEAD(&fence->active_list); spin_unlock_irqrestore(&obj->child_list_lock, flags); - return pt; + return fence; } EXPORT_SYMBOL(sync_pt_create); -void sync_pt_free(struct sync_pt *pt) -{ - fence_put(&pt->base); -} -EXPORT_SYMBOL(sync_pt_free); - static struct sync_file *sync_file_alloc(int size, const char *name) { struct sync_file *sync_file; @@ -184,8 +178,8 @@ static void fence_check_cb_func(struct fence *f, struct fence_cb *cb) wake_up_all(&sync_file->wq); } -/* TODO: implement a create which takes more that one sync_pt */ -struct sync_file *sync_file_create_dma(const char *name, struct fence *pt) +/* TODO: implement a create which takes more that one fence */ +struct sync_file *sync_file_create_dma(const char *name, struct fence *fence) { struct sync_file *sync_file; @@ -197,9 +191,10 @@ struct sync_file *sync_file_create_dma(const char *name, struct fence *pt) sync_file->num_fences = 1; atomic_set(&sync_file->status, 1); - sync_file->cbs[0].fence = pt; + sync_file->cbs[0].fence = fence; sync_file->cbs[0].sync_file = sync_file; - if (fence_add_callback(pt, &sync_file->cbs[0].cb, fence_check_cb_func)) + if (fence_add_callback(fence, &sync_file->cbs[0].cb, + fence_check_cb_func)) atomic_dec(&sync_file->status); sync_file_debug_add(sync_file); @@ -208,9 +203,9 @@ struct sync_file *sync_file_create_dma(const char *name, struct fence *pt) } EXPORT_SYMBOL(sync_file_create_dma); -struct sync_file *sync_file_create(const char *name, struct sync_pt *pt) +struct sync_file *sync_file_create(const char *name, struct fence *fence) { - return sync_file_create_dma(name, &pt->base); + return sync_file_create_dma(name, fence); } EXPORT_SYMBOL(sync_file_create); @@ -245,14 +240,14 @@ void sync_file_install(struct sync_file *sync_file, int fd) EXPORT_SYMBOL(sync_file_install); static void sync_file_add_pt(struct sync_file *sync_file, int *i, - struct fence *pt) + struct fence *fence) { - sync_file->cbs[*i].fence = pt; + sync_file->cbs[*i].fence = fence; sync_file->cbs[*i].sync_file = sync_file; - if (!fence_add_callback(pt, &sync_file->cbs[*i].cb, + if (!fence_add_callback(fence, &sync_file->cbs[*i].cb, fence_check_cb_func)) { - fence_get(pt); + fence_get(fence); (*i)++; } } @@ -328,7 +323,7 @@ int sync_file_wait(struct sync_file *sync_file, long timeout) trace_sync_wait(sync_file, 1); for (i = 0; i < sync_file->num_fences; ++i) - trace_sync_pt(sync_file->cbs[i].fence); + trace_fence(sync_file->cbs[i].fence); ret = wait_event_interruptible_timeout(sync_file->wq, atomic_read(&sync_file->status) <= 0, timeout); @@ -356,43 +351,39 @@ EXPORT_SYMBOL(sync_file_wait); static const char *android_fence_get_driver_name(struct fence *fence) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); return parent->ops->driver_name; } static const char *android_fence_get_timeline_name(struct fence *fence) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); return parent->name; } static void android_fence_release(struct fence *fence) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); unsigned long flags; spin_lock_irqsave(fence->lock, flags); - list_del(&pt->child_list); - if (WARN_ON_ONCE(!list_empty(&pt->active_list))) - list_del(&pt->active_list); + list_del(&fence->child_list); + if (WARN_ON_ONCE(!list_empty(&fence->active_list))) + list_del(&fence->active_list); spin_unlock_irqrestore(fence->lock, flags); sync_timeline_put(parent); - fence_free(&pt->base); + fence_free(fence); } static bool android_fence_signaled(struct fence *fence) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); int ret; - ret = parent->ops->has_signaled(pt); + ret = parent->ops->has_signaled(fence); if (ret < 0) fence->status = ret; return ret; @@ -400,46 +391,42 @@ static bool android_fence_signaled(struct fence *fence) static bool android_fence_enable_signaling(struct fence *fence) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); if (android_fence_signaled(fence)) return false; - list_add_tail(&pt->active_list, &parent->active_list_head); + list_add_tail(&fence->active_list, &parent->active_list_head); return true; } static int android_fence_fill_driver_data(struct fence *fence, void *data, int size) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); if (!parent->ops->fill_driver_data) return 0; - return parent->ops->fill_driver_data(pt, data, size); + return parent->ops->fill_driver_data(fence, data, size); } static void android_fence_value_str(struct fence *fence, char *str, int size) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); - if (!parent->ops->pt_value_str) { + if (!parent->ops->fence_value_str) { if (size) *str = 0; return; } - parent->ops->pt_value_str(pt, str, size); + parent->ops->fence_value_str(fence, str, size); } static void android_fence_timeline_value_str(struct fence *fence, char *str, int size) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); if (!parent->ops->timeline_value_str) { if (size) @@ -624,9 +611,9 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, len = sizeof(struct sync_file_info_data); for (i = 0; i < sync_file->num_fences; ++i) { - struct fence *pt = sync_file->cbs[i].fence; + struct fence *fence = sync_file->cbs[i].fence; - ret = sync_fill_pt_info(pt, (u8 *)data + len, size - len); + ret = sync_fill_pt_info(fence, (u8 *)data + len, size - len); if (ret < 0) goto out; diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index a18d1e3365fb..8cdac1a12e4f 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -24,7 +24,6 @@ #include "uapi/sync.h" struct sync_timeline; -struct sync_pt; struct sync_file; /** @@ -39,23 +38,23 @@ struct sync_file; * as specified by size. This information is returned * to userspace by SYNC_IOC_FENCE_INFO. * @timeline_value_str: fill str with the value of the sync_timeline's counter - * @pt_value_str: fill str with the value of the sync_pt + * @fence_value_str: fill str with the value of the fence */ struct sync_timeline_ops { const char *driver_name; /* required */ - int (*has_signaled)(struct sync_pt *pt); + int (*has_signaled)(struct fence *fence); /* optional */ - int (*fill_driver_data)(struct sync_pt *syncpt, void *data, int size); + int (*fill_driver_data)(struct fence *fence, void *data, int size); /* optional */ void (*timeline_value_str)(struct sync_timeline *timeline, char *str, int size); /* optional */ - void (*pt_value_str)(struct sync_pt *pt, char *str, int size); + void (*fence_value_str)(struct fence *fence, char *str, int size); }; /** @@ -66,7 +65,7 @@ struct sync_timeline_ops { * @destroyed: set when sync_timeline is destroyed * @child_list_head: list of children sync_pts for this sync_timeline * @child_list_lock: lock protecting @child_list_head, destroyed, and - * sync_pt.status + * fence.status * @active_list_head: list of active (unsignaled/errored) sync_pts * @sync_timeline_list: membership in global sync_timeline_list */ @@ -89,22 +88,9 @@ struct sync_timeline { #endif }; -/** - * struct sync_pt - sync point - * @base: base fence class - * @child_list: membership in sync_timeline.child_list_head - * @active_list: membership in sync_timeline.active_list_head - */ -struct sync_pt { - struct fence base; - - struct list_head child_list; - struct list_head active_list; -}; - -static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt) +static inline struct sync_timeline *fence_parent(struct fence *fence) { - return container_of(pt->base.lock, struct sync_timeline, + return container_of(fence->lock, struct sync_timeline, child_list_lock); } @@ -164,7 +150,7 @@ struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops, * * A sync implementation should call this when the @obj is going away * (i.e. module unload.) @obj won't actually be freed until all its children - * sync_pts are freed. + * fences are freed. */ void sync_timeline_destroy(struct sync_timeline *obj); @@ -172,41 +158,32 @@ void sync_timeline_destroy(struct sync_timeline *obj); * sync_timeline_signal() - signal a status change on a sync_timeline * @obj: sync_timeline to signal * - * A sync implementation should call this any time one of it's sync_pts + * A sync implementation should call this any time one of it's fences * has signaled or has an error condition. */ void sync_timeline_signal(struct sync_timeline *obj); /** * sync_pt_create() - creates a sync pt - * @parent: sync_pt's parent sync_timeline + * @parent: fence's parent sync_timeline * @size: size to allocate for this pt * - * Creates a new sync_pt as a child of @parent. @size bytes will be + * Creates a new fence as a child of @parent. @size bytes will be * allocated allowing for implementation specific data to be kept after - * the generic sync_timeline struct. Returns the sync_pt object or + * the generic sync_timeline struct. Returns the fence object or * NULL in case of error. */ -struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size); +struct fence *sync_pt_create(struct sync_timeline *parent, int size); /** - * sync_pt_free() - frees a sync pt - * @pt: sync_pt to free + * sync_fence_create() - creates a sync fence + * @name: name of fence to create + * @fence: fence to add to the sync_fence * - * This should only be called on sync_pts which have been created but - * not added to a fence. - */ -void sync_pt_free(struct sync_pt *pt); - -/** - * sync_file_create() - creates a sync file - * @name: name of file to create - * @pt: sync_pt to add to the file - * - * Creates a sync_file containg @pt. Once this is called, the sync_file takes - * ownership of @pt. + * Creates a sync_file containg @fence. Once this is called, the sync_file + * takes ownership of @fence. */ -struct sync_file *sync_file_create(const char *name, struct sync_pt *pt); +struct sync_file *sync_file_create(const char *name, struct fence *fence); /** * sync_file_create_dma() - creates a sync file from dma-fence @@ -228,7 +205,7 @@ struct sync_file *sync_file_create_dma(const char *name, struct fence *pt); * @a: sync_file a * @b: sync_file b * - * Creates a new sync_file which contains copies of all the sync_pts in both + * Creates a new sync_file which contains copies of all the fences in both * @a and @b. @a and @b remain valid, independent sync_file. Returns the * new merged sync_file or NULL in case of error. */ diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index 85ae98a63a1e..fd13f1e885e5 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -85,39 +85,40 @@ static const char *sync_status_str(int status) return "error"; } -static void sync_print_pt(struct seq_file *s, struct fence *pt, bool fence) +static void sync_print_fence(struct seq_file *s, struct fence *fence, bool show) { int status = 1; + struct sync_timeline *parent = fence_parent(fence); - if (fence_is_signaled_locked(pt)) - status = pt->status; + if (fence_is_signaled_locked(fence)) + status = fence->status; - seq_printf(s, " %s%spt %s", - fence && pt->ops->get_timeline_name ? - pt->ops->get_timeline_name(pt) : "", - fence ? "_" : "", + seq_printf(s, " %s%sfence %s", + show ? parent->name : "", + show ? "_" : "", sync_status_str(status)); if (status <= 0) { struct timespec64 ts64 = - ktime_to_timespec64(pt->timestamp); + ktime_to_timespec64(fence->timestamp); seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec); } - if ((!fence || pt->ops->timeline_value_str) && - pt->ops->fence_value_str) { + if ((!fence || fence->ops->timeline_value_str) && + fence->ops->fence_value_str) { char value[64]; bool success; - pt->ops->fence_value_str(pt, value, sizeof(value)); + fence->ops->fence_value_str(fence, value, sizeof(value)); success = strlen(value); if (success) seq_printf(s, ": %s", value); if (success && fence) { - pt->ops->timeline_value_str(pt, value, sizeof(value)); + fence->ops->timeline_value_str(fence, value, + sizeof(value)); if (strlen(value)) seq_printf(s, " / %s", value); @@ -145,25 +146,25 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) spin_lock_irqsave(&obj->child_list_lock, flags); list_for_each(pos, &obj->child_list_head) { - struct sync_pt *pt = - container_of(pos, struct sync_pt, child_list); - sync_print_pt(s, &pt->base, false); + struct fence *fence = + container_of(pos, struct fence, child_list); + sync_print_fence(s, fence, false); } spin_unlock_irqrestore(&obj->child_list_lock, flags); } static void sync_print_sync_file(struct seq_file *s, struct sync_file *sync_file) - { +{ int i; seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name, sync_status_str(atomic_read(&sync_file->status))); for (i = 0; i < sync_file->num_fences; ++i) - sync_print_pt(s, sync_file->cbs[i].fence, true); - } - + sync_print_fence(s, sync_file->cbs[i].fence, true); +} + static int sync_debugfs_show(struct seq_file *s, void *unused) { unsigned long flags; @@ -244,7 +245,7 @@ static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, { int fd = get_unused_fd_flags(O_CLOEXEC); int err; - struct sync_pt *pt; + struct fence *fence; struct sync_file *sync_file; struct sw_sync_create_fence_data data; @@ -256,16 +257,16 @@ static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, goto err; } - pt = sw_sync_pt_create(obj, data.value); - if (!pt) { + fence = sw_sync_pt_create(obj, data.value); + if (!fence) { err = -ENOMEM; goto err; } data.name[sizeof(data.name) - 1] = '\0'; - sync_file = sync_file_create(data.name, pt); + sync_file = sync_file_create(data.name, fence); if (!sync_file) { - sync_pt_free(pt); + fence_put(fence); err = -ENOMEM; goto err; } diff --git a/drivers/staging/android/trace/sync.h b/drivers/staging/android/trace/sync.h index 80f5da4f2aa5..87c60e9f584e 100644 --- a/drivers/staging/android/trace/sync.h +++ b/drivers/staging/android/trace/sync.h @@ -53,20 +53,20 @@ TRACE_EVENT(sync_wait, __get_str(name), __entry->status) ); -TRACE_EVENT(sync_pt, - TP_PROTO(struct fence *pt), +TRACE_EVENT(fence, + TP_PROTO(struct fence *fence), - TP_ARGS(pt), + TP_ARGS(fence), TP_STRUCT__entry( - __string(timeline, pt->ops->get_timeline_name(pt)) + __string(timeline, fence->ops->get_timeline_name(fence)) __array(char, value, 32) ), TP_fast_assign( - __assign_str(timeline, pt->ops->get_timeline_name(pt)); - if (pt->ops->fence_value_str) { - pt->ops->fence_value_str(pt, __entry->value, + __assign_str(timeline, fence->ops->get_timeline_name(fence)); + if (fence->ops->fence_value_str) { + fence->ops->fence_value_str(fence, __entry->value, sizeof(__entry->value)); } else { __entry->value[0] = '\0'; diff --git a/include/linux/fence.h b/include/linux/fence.h index bb522011383b..605bd88246a6 100644 --- a/include/linux/fence.h +++ b/include/linux/fence.h @@ -79,6 +79,8 @@ struct fence { unsigned long flags; ktime_t timestamp; int status; + struct list_head child_list; + struct list_head active_list; }; enum fence_flag_bits { -- cgit v1.2.3 From e6a0cb4819d082b60ce47e432bfcac16fdf93767 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:22 -0200 Subject: staging/android: remove unused var from sync_timeline_signal() signaled_pts is not used in this function. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 3c2c8d07df62..9ec55ef16eb1 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -101,7 +101,6 @@ EXPORT_SYMBOL(sync_timeline_destroy); void sync_timeline_signal(struct sync_timeline *obj) { unsigned long flags; - LIST_HEAD(signaled_pts); struct fence *fence, *next; trace_sync_timeline(obj); -- cgit v1.2.3 From 84288db5ca3fdac8d5a4bc730cc0b20144ddaa46 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:23 -0200 Subject: staging/android: remove pointless sync_timeline_signal at destroy phase All changes to timeline value come through the user via sync_timeline_signal() calls. When sync_timeline_destroy() is called no changes on timeline->value happens hence call sync_timeline_signal() with no increment is pointless. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 9ec55ef16eb1..b9f167ffdff5 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -90,10 +90,6 @@ void sync_timeline_destroy(struct sync_timeline *obj) */ smp_wmb(); - /* - * signal any children that their parent is going away. - */ - sync_timeline_signal(obj); sync_timeline_put(obj); } EXPORT_SYMBOL(sync_timeline_destroy); -- cgit v1.2.3 From d52ef2cef99cc200d828f39d1584e4b190fc2442 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:24 -0200 Subject: staging/android: remove sync_fence_create_dma() With the removal of struct sync_pt sync_fence_create_dma() now takes the same arguments as sync_fence_create() so let's keep only sync_fence_create(). Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 8 +------- drivers/staging/android/sync.h | 10 ---------- 2 files changed, 1 insertion(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index b9f167ffdff5..5fa4779a1956 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -174,7 +174,7 @@ static void fence_check_cb_func(struct fence *f, struct fence_cb *cb) } /* TODO: implement a create which takes more that one fence */ -struct sync_file *sync_file_create_dma(const char *name, struct fence *fence) +struct sync_file *sync_file_create(const char *name, struct fence *fence) { struct sync_file *sync_file; @@ -196,12 +196,6 @@ struct sync_file *sync_file_create_dma(const char *name, struct fence *fence) return sync_file; } -EXPORT_SYMBOL(sync_file_create_dma); - -struct sync_file *sync_file_create(const char *name, struct fence *fence) -{ - return sync_file_create_dma(name, fence); -} EXPORT_SYMBOL(sync_file_create); struct sync_file *sync_file_fdget(int fd) diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index 8cdac1a12e4f..8980b5580fb3 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -185,16 +185,6 @@ struct fence *sync_pt_create(struct sync_timeline *parent, int size); */ struct sync_file *sync_file_create(const char *name, struct fence *fence); -/** - * sync_file_create_dma() - creates a sync file from dma-fence - * @name: name of file to create - * @pt: dma-fence to add to the file - * - * Creates a sync_file containg @pt. Once this is called, the fence takes - * ownership of @pt. - */ -struct sync_file *sync_file_create_dma(const char *name, struct fence *pt); - /* * API for sync_file consumers */ -- cgit v1.2.3 From 8fb78ad6e55d8456de9202279b8463f26b012088 Mon Sep 17 00:00:00 2001 From: Ben Marsh Date: Mon, 1 Feb 2016 14:12:32 +0100 Subject: Staging: Android: memory allocation style change in ion_page_pool.c This is a patch to ion_page_pool.c that changes a memory allocation style issue as found by checkpatch.pl. Signed-off-by: Ben Marsh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_page_pool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index fd7e23e0c06e..1fe80165a462 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -149,8 +149,8 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) { - struct ion_page_pool *pool = kmalloc(sizeof(struct ion_page_pool), - GFP_KERNEL); + struct ion_page_pool *pool = kmalloc(sizeof(*pool), GFP_KERNEL); + if (!pool) return NULL; pool->high_count = 0; -- cgit v1.2.3 From 84013bb4651e568d543f4cd3fa65c7931943da73 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Wed, 3 Feb 2016 11:25:30 -0200 Subject: staging/android: remove SYNC_WAIT ioctl This ioctl is replicating the work of poll() syscall so let's take the opportunity that this is still on staging tree and remove the duplication and force new users to use the poll() standard interface. Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 52 ------------------------------------ drivers/staging/android/sync.h | 13 --------- drivers/staging/android/trace/sync.h | 44 ------------------------------ drivers/staging/android/uapi/sync.h | 7 ----- 4 files changed, 116 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 5fa4779a1956..381209a9dc2d 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -300,44 +300,6 @@ struct sync_file *sync_file_merge(const char *name, } EXPORT_SYMBOL(sync_file_merge); -int sync_file_wait(struct sync_file *sync_file, long timeout) -{ - long ret; - int i; - - if (timeout < 0) - timeout = MAX_SCHEDULE_TIMEOUT; - else - timeout = msecs_to_jiffies(timeout); - - trace_sync_wait(sync_file, 1); - for (i = 0; i < sync_file->num_fences; ++i) - trace_fence(sync_file->cbs[i].fence); - ret = wait_event_interruptible_timeout(sync_file->wq, - atomic_read(&sync_file->status) <= 0, - timeout); - trace_sync_wait(sync_file, 0); - - if (ret < 0) { - return ret; - } else if (ret == 0) { - if (timeout) { - pr_info("sync_file timeout on [%p] after %dms\n", - sync_file, jiffies_to_msecs(timeout)); - sync_dump(); - } - return -ETIME; - } - - ret = atomic_read(&sync_file->status); - if (ret) { - pr_info("sync_file error %ld on [%p]\n", ret, sync_file); - sync_dump(); - } - return ret; -} -EXPORT_SYMBOL(sync_file_wait); - static const char *android_fence_get_driver_name(struct fence *fence) { struct sync_timeline *parent = fence_parent(fence); @@ -478,17 +440,6 @@ static unsigned int sync_file_poll(struct file *file, poll_table *wait) return 0; } -static long sync_file_ioctl_wait(struct sync_file *sync_file, - unsigned long arg) -{ - __s32 value; - - if (copy_from_user(&value, (void __user *)arg, sizeof(value))) - return -EFAULT; - - return sync_file_wait(sync_file, value); -} - static long sync_file_ioctl_merge(struct sync_file *sync_file, unsigned long arg) { @@ -629,9 +580,6 @@ static long sync_file_ioctl(struct file *file, unsigned int cmd, struct sync_file *sync_file = file->private_data; switch (cmd) { - case SYNC_IOC_WAIT: - return sync_file_ioctl_wait(sync_file, arg); - case SYNC_IOC_MERGE: return sync_file_ioctl_merge(sync_file, arg); diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index 8980b5580fb3..af1af998949c 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -18,7 +18,6 @@ #include #include #include -#include #include #include "uapi/sync.h" @@ -230,18 +229,6 @@ void sync_file_put(struct sync_file *sync_file); */ void sync_file_install(struct sync_file *sync_file, int fd); -/** - * sync_file_wait() - wait on sync file - * @sync_file: file to wait on - * @tiemout: timeout in ms - * - * Wait for @sync_file to be signaled or have an error. Waits indefinitely - * if @timeout < 0. - * - * Returns 0 if fence signaled, > 0 if it is still active and <0 on error - */ -int sync_file_wait(struct sync_file *sync_file, long timeout); - #ifdef CONFIG_DEBUG_FS void sync_timeline_debug_add(struct sync_timeline *obj); diff --git a/drivers/staging/android/trace/sync.h b/drivers/staging/android/trace/sync.h index 87c60e9f584e..a0f80f41677e 100644 --- a/drivers/staging/android/trace/sync.h +++ b/drivers/staging/android/trace/sync.h @@ -32,50 +32,6 @@ TRACE_EVENT(sync_timeline, TP_printk("name=%s value=%s", __get_str(name), __entry->value) ); -TRACE_EVENT(sync_wait, - TP_PROTO(struct sync_file *sync_file, int begin), - - TP_ARGS(sync_file, begin), - - TP_STRUCT__entry( - __string(name, sync_file->name) - __field(s32, status) - __field(u32, begin) - ), - - TP_fast_assign( - __assign_str(name, sync_file->name); - __entry->status = atomic_read(&sync_file->status); - __entry->begin = begin; - ), - - TP_printk("%s name=%s state=%d", __entry->begin ? "begin" : "end", - __get_str(name), __entry->status) -); - -TRACE_EVENT(fence, - TP_PROTO(struct fence *fence), - - TP_ARGS(fence), - - TP_STRUCT__entry( - __string(timeline, fence->ops->get_timeline_name(fence)) - __array(char, value, 32) - ), - - TP_fast_assign( - __assign_str(timeline, fence->ops->get_timeline_name(fence)); - if (fence->ops->fence_value_str) { - fence->ops->fence_value_str(fence, __entry->value, - sizeof(__entry->value)); - } else { - __entry->value[0] = '\0'; - } - ), - - TP_printk("name=%s value=%s", __get_str(timeline), __entry->value) -); - #endif /* if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) */ /* This part must be outside protection */ diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h index 73deb6907ce1..6c88c8080d1e 100644 --- a/drivers/staging/android/uapi/sync.h +++ b/drivers/staging/android/uapi/sync.h @@ -64,13 +64,6 @@ struct sync_file_info_data { #define SYNC_IOC_MAGIC '>' -/** - * DOC: SYNC_IOC_WAIT - wait for a fence to signal - * - * pass timeout in milliseconds. Waits indefinitely timeout < 0. - */ -#define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32) - /** * DOC: SYNC_IOC_MERGE - merge two fences * -- cgit v1.2.3 From e1786348e4e5442e82b4b35f8ade6f4d0f434e18 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Wed, 3 Feb 2016 11:25:31 -0200 Subject: staging/android: rename sync_pt_info to sync_fence_info As struct sync_pt doesn't exist anymore it is a good idea remove any reference to it in the sync_framework. sync_pts were replaced directly by fences and here we rename it to sync_fence_info to let the fence namespace clean. v2: rename fence_info to sync_fence_info (Maarten) Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 10 +++++----- drivers/staging/android/uapi/sync.h | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 381209a9dc2d..f6ffb109b483 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -490,15 +490,15 @@ err_put_fd: return err; } -static int sync_fill_pt_info(struct fence *fence, void *data, int size) +static int sync_fill_fence_info(struct fence *fence, void *data, int size) { - struct sync_pt_info *info = data; + struct sync_fence_info *info = data; int ret; - if (size < sizeof(struct sync_pt_info)) + if (size < sizeof(*info)) return -ENOMEM; - info->len = sizeof(struct sync_pt_info); + info->len = sizeof(*info); if (fence->ops->fill_driver_data) { ret = fence->ops->fill_driver_data(fence, info->driver_data, @@ -553,7 +553,7 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, for (i = 0; i < sync_file->num_fences; ++i) { struct fence *fence = sync_file->cbs[i].fence; - ret = sync_fill_pt_info(fence, (u8 *)data + len, size - len); + ret = sync_fill_fence_info(fence, (u8 *)data + len, size - len); if (ret < 0) goto out; diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h index 6c88c8080d1e..9a0c3cd2ced0 100644 --- a/drivers/staging/android/uapi/sync.h +++ b/drivers/staging/android/uapi/sync.h @@ -27,15 +27,15 @@ struct sync_merge_data { }; /** - * struct sync_pt_info - detailed sync_pt information - * @len: length of sync_pt_info including any driver_data + * struct sync_fence_info - detailed fence information + * @len: length of sync_fence_info including any driver_data * @obj_name: name of parent sync_timeline * @driver_name: name of driver implementing the parent - * @status: status of the sync_pt 0:active 1:signaled <0:error + * @status: status of the fence 0:active 1:signaled <0:error * @timestamp_ns: timestamp of status change in nanoseconds * @driver_data: any driver dependent data */ -struct sync_pt_info { +struct sync_fence_info { __u32 len; char obj_name[32]; char driver_name[32]; @@ -52,14 +52,14 @@ struct sync_pt_info { * userspace including pt_info. * @name: name of fence * @status: status of fence. 1: signaled 0:active <0:error - * @pt_info: a sync_pt_info struct for every sync_pt in the fence + * @sync_fence_info: array of sync_fence_info for every fence in the sync_file */ struct sync_file_info_data { __u32 len; char name[32]; __s32 status; - __u8 pt_info[0]; + __u8 sync_fence_info[0]; }; #define SYNC_IOC_MAGIC '>' -- cgit v1.2.3 From b5b24ac57af99b6b580eb52118167702e442da02 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Wed, 3 Feb 2016 11:25:32 -0200 Subject: staging/android: rename sync_file_info_data to sync_file_info info_data is a bit redundant, let's keep it as only sync_file_info. It is also smaller. Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 26 +++++++++++++------------- drivers/staging/android/uapi/sync.h | 9 ++++----- 2 files changed, 17 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index f6ffb109b483..85a0e87b9119 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -525,7 +525,7 @@ static int sync_fill_fence_info(struct fence *fence, void *data, int size) static long sync_file_ioctl_fence_info(struct sync_file *sync_file, unsigned long arg) { - struct sync_file_info_data *data; + struct sync_file_info *info; __u32 size; __u32 len = 0; int ret, i; @@ -533,27 +533,27 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, if (copy_from_user(&size, (void __user *)arg, sizeof(size))) return -EFAULT; - if (size < sizeof(struct sync_file_info_data)) + if (size < sizeof(struct sync_file_info)) return -EINVAL; if (size > 4096) size = 4096; - data = kzalloc(size, GFP_KERNEL); - if (!data) + info = kzalloc(size, GFP_KERNEL); + if (!info) return -ENOMEM; - strlcpy(data->name, sync_file->name, sizeof(data->name)); - data->status = atomic_read(&sync_file->status); - if (data->status >= 0) - data->status = !data->status; + strlcpy(info->name, sync_file->name, sizeof(info->name)); + info->status = atomic_read(&sync_file->status); + if (info->status >= 0) + info->status = !info->status; - len = sizeof(struct sync_file_info_data); + len = sizeof(struct sync_file_info); for (i = 0; i < sync_file->num_fences; ++i) { struct fence *fence = sync_file->cbs[i].fence; - ret = sync_fill_fence_info(fence, (u8 *)data + len, size - len); + ret = sync_fill_fence_info(fence, (u8 *)info + len, size - len); if (ret < 0) goto out; @@ -561,15 +561,15 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, len += ret; } - data->len = len; + info->len = len; - if (copy_to_user((void __user *)arg, data, len)) + if (copy_to_user((void __user *)arg, info, len)) ret = -EFAULT; else ret = 0; out: - kfree(data); + kfree(info); return ret; } diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h index 9a0c3cd2ced0..fcc0b3c5b6da 100644 --- a/drivers/staging/android/uapi/sync.h +++ b/drivers/staging/android/uapi/sync.h @@ -46,15 +46,15 @@ struct sync_fence_info { }; /** - * struct sync_file_info_data - data returned from fence info ioctl + * struct sync_file_info - data returned from fence info ioctl * @len: ioctl caller writes the size of the buffer its passing in. - * ioctl returns length of sync_file_info_data returned to + * ioctl returns length of sync_file_info returned to * userspace including pt_info. * @name: name of fence * @status: status of fence. 1: signaled 0:active <0:error * @sync_fence_info: array of sync_fence_info for every fence in the sync_file */ -struct sync_file_info_data { +struct sync_file_info { __u32 len; char name[32]; __s32 status; @@ -84,7 +84,6 @@ struct sync_file_info_data { * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence. * To iterate over the sync_pt_infos, use the sync_pt_info.len field. */ -#define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2,\ - struct sync_file_info_data) +#define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2, struct sync_file_info) #endif /* _UAPI_LINUX_SYNC_H */ -- cgit v1.2.3 From c7434b8436f9fb79855f0a52e4e9665becb77aea Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Wed, 3 Feb 2016 11:25:33 -0200 Subject: staging/android: remove driver_data from struct sync_fence_info It is unclear in what situations driver_data should be used thus better do not upstream it for now. If a need arises in the future a discussion can be started to re-add it. Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sw_sync.c | 14 -------------- drivers/staging/android/sync.c | 21 --------------------- drivers/staging/android/sync.h | 7 ------- drivers/staging/android/uapi/sync.h | 5 +---- 4 files changed, 1 insertion(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c index 3bee959b41d8..af39ff58fa33 100644 --- a/drivers/staging/android/sw_sync.c +++ b/drivers/staging/android/sw_sync.c @@ -47,19 +47,6 @@ static int sw_sync_fence_has_signaled(struct fence *fence) return (pt->value > obj->value) ? 0 : 1; } -static int sw_sync_fill_driver_data(struct fence *fence, - void *data, int size) -{ - struct sw_sync_pt *pt = (struct sw_sync_pt *)fence; - - if (size < sizeof(pt->value)) - return -ENOMEM; - - memcpy(data, &pt->value, sizeof(pt->value)); - - return sizeof(pt->value); -} - static void sw_sync_timeline_value_str(struct sync_timeline *sync_timeline, char *str, int size) { @@ -78,7 +65,6 @@ static void sw_sync_fence_value_str(struct fence *fence, char *str, int size) static struct sync_timeline_ops sw_sync_timeline_ops = { .driver_name = "sw_sync", .has_signaled = sw_sync_fence_has_signaled, - .fill_driver_data = sw_sync_fill_driver_data, .timeline_value_str = sw_sync_timeline_value_str, .fence_value_str = sw_sync_fence_value_str, }; diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 85a0e87b9119..d527878c7488 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -351,16 +351,6 @@ static bool android_fence_enable_signaling(struct fence *fence) return true; } -static int android_fence_fill_driver_data(struct fence *fence, - void *data, int size) -{ - struct sync_timeline *parent = fence_parent(fence); - - if (!parent->ops->fill_driver_data) - return 0; - return parent->ops->fill_driver_data(fence, data, size); -} - static void android_fence_value_str(struct fence *fence, char *str, int size) { @@ -394,7 +384,6 @@ static const struct fence_ops android_fence_ops = { .signaled = android_fence_signaled, .wait = fence_default_wait, .release = android_fence_release, - .fill_driver_data = android_fence_fill_driver_data, .fence_value_str = android_fence_value_str, .timeline_value_str = android_fence_timeline_value_str, }; @@ -493,22 +482,12 @@ err_put_fd: static int sync_fill_fence_info(struct fence *fence, void *data, int size) { struct sync_fence_info *info = data; - int ret; if (size < sizeof(*info)) return -ENOMEM; info->len = sizeof(*info); - if (fence->ops->fill_driver_data) { - ret = fence->ops->fill_driver_data(fence, info->driver_data, - size - sizeof(*info)); - if (ret < 0) - return ret; - - info->len += ret; - } - strlcpy(info->obj_name, fence->ops->get_timeline_name(fence), sizeof(info->obj_name)); strlcpy(info->driver_name, fence->ops->get_driver_name(fence), diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index af1af998949c..d2a173433a7d 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -32,10 +32,6 @@ struct sync_file; * 1 if pt has signaled * 0 if pt has not signaled * <0 on error - * @fill_driver_data: write implementation specific driver data to data. - * should return an error if there is not enough room - * as specified by size. This information is returned - * to userspace by SYNC_IOC_FENCE_INFO. * @timeline_value_str: fill str with the value of the sync_timeline's counter * @fence_value_str: fill str with the value of the fence */ @@ -45,9 +41,6 @@ struct sync_timeline_ops { /* required */ int (*has_signaled)(struct fence *fence); - /* optional */ - int (*fill_driver_data)(struct fence *fence, void *data, int size); - /* optional */ void (*timeline_value_str)(struct sync_timeline *timeline, char *str, int size); diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h index fcc0b3c5b6da..4d8cf0062f04 100644 --- a/drivers/staging/android/uapi/sync.h +++ b/drivers/staging/android/uapi/sync.h @@ -28,12 +28,11 @@ struct sync_merge_data { /** * struct sync_fence_info - detailed fence information - * @len: length of sync_fence_info including any driver_data + * @len: length of sync_fence_info * @obj_name: name of parent sync_timeline * @driver_name: name of driver implementing the parent * @status: status of the fence 0:active 1:signaled <0:error * @timestamp_ns: timestamp of status change in nanoseconds - * @driver_data: any driver dependent data */ struct sync_fence_info { __u32 len; @@ -41,8 +40,6 @@ struct sync_fence_info { char driver_name[32]; __s32 status; __u64 timestamp_ns; - - __u8 driver_data[0]; }; /** -- cgit v1.2.3 From 323de43f79c5055af71c2db44f34e060ac15e1df Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Wed, 3 Feb 2016 11:25:34 -0200 Subject: staging/android: remove len field from struct sync_fence_info After removing driver_data struct sync_fence_info has now a fixed size, thus it doesn't need any field to tell its size, it is already known. Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 4 +--- drivers/staging/android/uapi/sync.h | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index d527878c7488..2ab0c208088d 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -486,8 +486,6 @@ static int sync_fill_fence_info(struct fence *fence, void *data, int size) if (size < sizeof(*info)) return -ENOMEM; - info->len = sizeof(*info); - strlcpy(info->obj_name, fence->ops->get_timeline_name(fence), sizeof(info->obj_name)); strlcpy(info->driver_name, fence->ops->get_driver_name(fence), @@ -498,7 +496,7 @@ static int sync_fill_fence_info(struct fence *fence, void *data, int size) info->status = 0; info->timestamp_ns = ktime_to_ns(fence->timestamp); - return info->len; + return sizeof(*info); } static long sync_file_ioctl_fence_info(struct sync_file *sync_file, diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h index 4d8cf0062f04..a0cf357e598d 100644 --- a/drivers/staging/android/uapi/sync.h +++ b/drivers/staging/android/uapi/sync.h @@ -28,14 +28,12 @@ struct sync_merge_data { /** * struct sync_fence_info - detailed fence information - * @len: length of sync_fence_info * @obj_name: name of parent sync_timeline * @driver_name: name of driver implementing the parent * @status: status of the fence 0:active 1:signaled <0:error * @timestamp_ns: timestamp of status change in nanoseconds */ struct sync_fence_info { - __u32 len; char obj_name[32]; char driver_name[32]; __s32 status; -- cgit v1.2.3 From 9f90381b3ec8ad5056348642333f0220c95def27 Mon Sep 17 00:00:00 2001 From: Rohit kumar Date: Tue, 12 Jan 2016 09:31:46 +0530 Subject: staging/ion: Add support to get ion handle from dma buf Currently we can only import dma buf fd's to get ion_handle. Adding support to import dma buf handles to support kernel specific use cases. An example use case is in linux platforms such as Tizen, in which DRM-GEM is used for buffer management for graphics. It has gem_handle corresponding to a buffer and uses gem_name for sharing the buffer with other processes. However,it also uses dma_buf fd for 3d operations. For wayland, there are multiple calls for gem_handle to dma_buf fd conversion. So, we store dma_buf associated with buffer. But, there is no api for getting ion_handle from dma_buf. This patch exposes api to retrieve the ion handle from dma_buf for similar use cases. With this patch, we can integrate ION within DRM-GEM for buffer management and dma_buf sharing. Signed-off-by: Rohit kumar Reviewed-by: Laura Abbott Reviewed-by: Sumit Semwal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 26 ++++++++++++++++++-------- drivers/staging/android/ion/ion.h | 20 ++++++++++++++++---- 2 files changed, 34 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index df560216d702..d6698483e152 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1153,22 +1153,18 @@ int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle) } EXPORT_SYMBOL(ion_share_dma_buf_fd); -struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) +struct ion_handle *ion_import_dma_buf(struct ion_client *client, + struct dma_buf *dmabuf) { - struct dma_buf *dmabuf; struct ion_buffer *buffer; struct ion_handle *handle; int ret; - dmabuf = dma_buf_get(fd); - if (IS_ERR(dmabuf)) - return ERR_CAST(dmabuf); /* if this memory came from ion */ if (dmabuf->ops != &dma_buf_ops) { pr_err("%s: can not import dmabuf from another exporter\n", __func__); - dma_buf_put(dmabuf); return ERR_PTR(-EINVAL); } buffer = dmabuf->priv; @@ -1196,11 +1192,25 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) } end: - dma_buf_put(dmabuf); return handle; } EXPORT_SYMBOL(ion_import_dma_buf); +struct ion_handle *ion_import_dma_buf_fd(struct ion_client *client, int fd) +{ + struct dma_buf *dmabuf; + struct ion_handle *handle; + + dmabuf = dma_buf_get(fd); + if (IS_ERR(dmabuf)) + return ERR_CAST(dmabuf); + + handle = ion_import_dma_buf(client, dmabuf); + dma_buf_put(dmabuf); + return handle; +} +EXPORT_SYMBOL(ion_import_dma_buf_fd); + static int ion_sync_for_device(struct ion_client *client, int fd) { struct dma_buf *dmabuf; @@ -1308,7 +1318,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct ion_handle *handle; - handle = ion_import_dma_buf(client, data.fd.fd); + handle = ion_import_dma_buf_fd(client, data.fd.fd); if (IS_ERR(handle)) ret = PTR_ERR(handle); else diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index b860c5f579f5..a1331fc169a1 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -192,14 +192,26 @@ struct dma_buf *ion_share_dma_buf(struct ion_client *client, int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle); /** - * ion_import_dma_buf() - given an dma-buf fd from the ion exporter get handle + * ion_import_dma_buf() - get ion_handle from dma-buf + * @client: the client + * @dmabuf: the dma-buf + * + * Get the ion_buffer associated with the dma-buf and return the ion_handle. + * If no ion_handle exists for this buffer, return newly created ion_handle. + * If dma-buf from another exporter is passed, return ERR_PTR(-EINVAL) + */ +struct ion_handle *ion_import_dma_buf(struct ion_client *client, + struct dma_buf *dmabuf); + +/** + * ion_import_dma_buf_fd() - given a dma-buf fd from the ion exporter get handle * @client: the client * @fd: the dma-buf fd * - * Given an dma-buf fd that was allocated through ion via ion_share_dma_buf, - * import that fd and return a handle representing it. If a dma-buf from + * Given an dma-buf fd that was allocated through ion via ion_share_dma_buf_fd, + * import that fd and return a handle representing it. If a dma-buf from * another exporter is passed in this function will return ERR_PTR(-EINVAL) */ -struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd); +struct ion_handle *ion_import_dma_buf_fd(struct ion_client *client, int fd); #endif /* _LINUX_ION_H */ -- cgit v1.2.3 From 948c4db4ee10d85fe78ed3755dcaeb85cd37a148 Mon Sep 17 00:00:00 2001 From: Neil Zhang Date: Tue, 26 Jan 2016 17:39:06 +0800 Subject: ion:synchronize debugfs callback and ion_client_destroy There are race condition B/T ion_client_destroy and debugfs callbacks. Let's use a mutex to synchronize them. Signed-off-by: Neil Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index d6698483e152..7ff2a7ec871f 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -677,6 +677,34 @@ void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle) } EXPORT_SYMBOL(ion_unmap_kernel); +static struct mutex debugfs_mutex; +static struct rb_root *ion_root_client; +static int is_client_alive(struct ion_client *client) +{ + struct rb_node *node; + struct ion_client *tmp; + struct ion_device *dev; + + node = ion_root_client->rb_node; + dev = container_of(ion_root_client, struct ion_device, clients); + + down_read(&dev->lock); + while (node) { + tmp = rb_entry(node, struct ion_client, node); + if (client < tmp) { + node = node->rb_left; + } else if (client > tmp) { + node = node->rb_right; + } else { + up_read(&dev->lock); + return 1; + } + } + + up_read(&dev->lock); + return 0; +} + static int ion_debug_client_show(struct seq_file *s, void *unused) { struct ion_client *client = s->private; @@ -685,6 +713,14 @@ static int ion_debug_client_show(struct seq_file *s, void *unused) const char *names[ION_NUM_HEAP_IDS] = {NULL}; int i; + mutex_lock(&debugfs_mutex); + if (!is_client_alive(client)) { + seq_printf(s, "ion_client 0x%p dead, can't dump its buffers\n", + client); + mutex_unlock(&debugfs_mutex); + return 0; + } + mutex_lock(&client->lock); for (n = rb_first(&client->handles); n; n = rb_next(n)) { struct ion_handle *handle = rb_entry(n, struct ion_handle, @@ -696,6 +732,7 @@ static int ion_debug_client_show(struct seq_file *s, void *unused) sizes[id] += handle->buffer->size; } mutex_unlock(&client->lock); + mutex_unlock(&debugfs_mutex); seq_printf(s, "%16.16s: %16.16s\n", "heap_name", "size_in_bytes"); for (i = 0; i < ION_NUM_HEAP_IDS; i++) { @@ -832,6 +869,7 @@ void ion_client_destroy(struct ion_client *client) struct rb_node *n; pr_debug("%s: %d\n", __func__, __LINE__); + mutex_lock(&debugfs_mutex); while ((n = rb_first(&client->handles))) { struct ion_handle *handle = rb_entry(n, struct ion_handle, node); @@ -850,6 +888,7 @@ void ion_client_destroy(struct ion_client *client) kfree(client->display_name); kfree(client->name); kfree(client); + mutex_unlock(&debugfs_mutex); } EXPORT_SYMBOL(ion_client_destroy); @@ -1415,6 +1454,7 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) seq_printf(s, "%16s %16s %16s\n", "client", "pid", "size"); seq_puts(s, "----------------------------------------------------\n"); + mutex_lock(&debugfs_mutex); for (n = rb_first(&dev->clients); n; n = rb_next(n)) { struct ion_client *client = rb_entry(n, struct ion_client, node); @@ -1433,6 +1473,8 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) client->pid, size); } } + mutex_unlock(&debugfs_mutex); + seq_puts(s, "----------------------------------------------------\n"); seq_puts(s, "orphaned allocations (info is from last known client):\n"); mutex_lock(&dev->buffer_lock); @@ -1617,6 +1659,8 @@ debugfs_done: init_rwsem(&idev->lock); plist_head_init(&idev->heaps); idev->clients = RB_ROOT; + ion_root_client = &idev->clients; + mutex_init(&debugfs_mutex); return idev; } EXPORT_SYMBOL(ion_device_create); -- cgit v1.2.3 From c8053b58762745d93930826b60a4073854a15ce5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 7 Feb 2016 18:22:54 -0800 Subject: Revert "8250: uniphier: allow modular build with 8250 console" This reverts commit d56edd7ed0ed46a8043ee3040ededbd190818ccf, it shouldn't have been applied, it was fixed properly with commit 71f50c6d9a2276f3ec85384bffe2aee1962f4669 ("of: drop symbols declared by _OF_DECLARE() from modules") Reported-by: Masahiro Yamada Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_uniphier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c index 1b7bd26555b7..bab6b3ae2540 100644 --- a/drivers/tty/serial/8250/8250_uniphier.c +++ b/drivers/tty/serial/8250/8250_uniphier.c @@ -35,7 +35,7 @@ struct uniphier8250_priv { spinlock_t atomic_write_lock; }; -#if defined(CONFIG_SERIAL_8250_CONSOLE) && !defined(MODULE) +#ifdef CONFIG_SERIAL_8250_CONSOLE static int __init uniphier_early_console_setup(struct earlycon_device *device, const char *options) { -- cgit v1.2.3 From b0e302b40873c0418aacaad2aa455bf867c9d1a2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 1 Feb 2016 11:33:00 +0100 Subject: staging: goldfish: use div64_s64 instead of do_div The goldfish nand driver divides a signed 64-bit number (loff_t) in multiple places using the do_div() function. This has always been unreliable but now produces a compiler warning (since 4.5-rc1): goldfish/goldfish_nand.c: In function 'goldfish_nand_erase': goldfish/goldfish_nand.c:107:91: error: comparison of distinct pointer types lacks a cast [-Werror] goldfish/goldfish_nand.c: In function 'goldfish_nand_read_oob': goldfish/goldfish_nand.c:145:91: error: comparison of distinct pointer types lacks a cast [-Werror] This changes the code to the equivalent div_s64{,_rem} that works correctly for negative numbers (which we should never get here). The warning has shown up on ARM allmodconfig builds after the goldfish bus driver has become visible on ARM. Signed-off-by: Arnd Bergmann Fixes: bd2f348db503 ("goldfish: refactor goldfish platform configs") Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/staging/goldfish/goldfish_nand.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/goldfish/goldfish_nand.c b/drivers/staging/goldfish/goldfish_nand.c index f223b3a5a428..76d60eed1490 100644 --- a/drivers/staging/goldfish/goldfish_nand.c +++ b/drivers/staging/goldfish/goldfish_nand.c @@ -100,11 +100,11 @@ static int goldfish_nand_erase(struct mtd_info *mtd, struct erase_info *instr) { loff_t ofs = instr->addr; u32 len = instr->len; - u32 rem; + s32 rem; if (ofs + len > mtd->size) goto invalid_arg; - rem = do_div(ofs, mtd->writesize); + ofs = div_s64_rem(ofs, mtd->writesize, &rem); if (rem) goto invalid_arg; ofs *= (mtd->writesize + mtd->oobsize); @@ -133,7 +133,7 @@ invalid_arg: static int goldfish_nand_read_oob(struct mtd_info *mtd, loff_t ofs, struct mtd_oob_ops *ops) { - u32 rem; + s32 rem; if (ofs + ops->len > mtd->size) goto invalid_arg; @@ -142,7 +142,7 @@ static int goldfish_nand_read_oob(struct mtd_info *mtd, loff_t ofs, if (ops->ooblen + ops->ooboffs > mtd->oobsize) goto invalid_arg; - rem = do_div(ofs, mtd->writesize); + ofs = div_s64_rem(ofs, mtd->writesize, &rem); if (rem) goto invalid_arg; ofs *= (mtd->writesize + mtd->oobsize); @@ -165,7 +165,7 @@ invalid_arg: static int goldfish_nand_write_oob(struct mtd_info *mtd, loff_t ofs, struct mtd_oob_ops *ops) { - u32 rem; + s32 rem; if (ofs + ops->len > mtd->size) goto invalid_arg; @@ -174,7 +174,7 @@ static int goldfish_nand_write_oob(struct mtd_info *mtd, loff_t ofs, if (ops->ooblen + ops->ooboffs > mtd->oobsize) goto invalid_arg; - rem = do_div(ofs, mtd->writesize); + ofs = div_s64_rem(ofs, mtd->writesize, &rem); if (rem) goto invalid_arg; ofs *= (mtd->writesize + mtd->oobsize); @@ -197,12 +197,12 @@ invalid_arg: static int goldfish_nand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { - u32 rem; + s32 rem; if (from + len > mtd->size) goto invalid_arg; - rem = do_div(from, mtd->writesize); + from = div_s64_rem(from, mtd->writesize, &rem); if (rem) goto invalid_arg; from *= (mtd->writesize + mtd->oobsize); @@ -219,12 +219,12 @@ invalid_arg: static int goldfish_nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { - u32 rem; + s32 rem; if (to + len > mtd->size) goto invalid_arg; - rem = do_div(to, mtd->writesize); + to = div_s64_rem(to, mtd->writesize, &rem); if (rem) goto invalid_arg; to *= (mtd->writesize + mtd->oobsize); @@ -240,12 +240,12 @@ invalid_arg: static int goldfish_nand_block_isbad(struct mtd_info *mtd, loff_t ofs) { - u32 rem; + s32 rem; if (ofs >= mtd->size) goto invalid_arg; - rem = do_div(ofs, mtd->erasesize); + ofs = div_s64_rem(ofs, mtd->writesize, &rem); if (rem) goto invalid_arg; ofs *= mtd->erasesize / mtd->writesize; @@ -261,12 +261,12 @@ invalid_arg: static int goldfish_nand_block_markbad(struct mtd_info *mtd, loff_t ofs) { - u32 rem; + s32 rem; if (ofs >= mtd->size) goto invalid_arg; - rem = do_div(ofs, mtd->erasesize); + ofs = div_s64_rem(ofs, mtd->writesize, &rem); if (rem) goto invalid_arg; ofs *= mtd->erasesize / mtd->writesize; @@ -321,7 +321,7 @@ static int goldfish_nand_init_device(struct platform_device *pdev, mtd->oobavail = mtd->oobsize; mtd->erasesize = readl(base + NAND_DEV_ERASE_SIZE) / (mtd->writesize + mtd->oobsize) * mtd->writesize; - do_div(mtd->size, mtd->writesize + mtd->oobsize); + mtd->size = div_s64(mtd->size, mtd->writesize + mtd->oobsize); mtd->size *= mtd->writesize; dev_dbg(&pdev->dev, "goldfish nand dev%d: size %llx, page %d, extra %d, erase %d\n", -- cgit v1.2.3 From 2ce601b033376905d585e0825d5499616a22b565 Mon Sep 17 00:00:00 2001 From: Christian Colic Date: Thu, 19 Nov 2015 09:38:21 +0100 Subject: staging: goldfish: (coding style) Add spaces around the "+" to conform to checkpatch Added a space around the "+" at: "reg_base+addr2" to clear up a checkpatch check. Signed-off-by: Christian Colic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/goldfish/goldfish_audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/goldfish/goldfish_audio.c b/drivers/staging/goldfish/goldfish_audio.c index b0927e49d0a8..f1e18386e34d 100644 --- a/drivers/staging/goldfish/goldfish_audio.c +++ b/drivers/staging/goldfish/goldfish_audio.c @@ -63,7 +63,7 @@ struct goldfish_audio { #define AUDIO_READ(data, addr) (readl(data->reg_base + addr)) #define AUDIO_WRITE(data, addr, x) (writel(x, data->reg_base + addr)) #define AUDIO_WRITE64(data, addr, addr2, x) \ - (gf_write_dma_addr((x), data->reg_base + addr, data->reg_base+addr2)) + (gf_write_dma_addr((x), data->reg_base + addr, data->reg_base + addr2)) /* * temporary variable used between goldfish_audio_probe() and -- cgit v1.2.3 From 269ad6e018146dafb70c9a40e546f73752d44db2 Mon Sep 17 00:00:00 2001 From: Christian Colic Date: Thu, 19 Nov 2015 09:47:24 +0100 Subject: staging: goldfish: (coding style) Rewrite comparisons to NULL as "!data->reg_base" Rewrite comparisons to NULL "data->reg_base == NULL" as "!data->reg_base" to conform to checkpatch. Signed-off-by: Christian Colic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/goldfish/goldfish_audio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/goldfish/goldfish_audio.c b/drivers/staging/goldfish/goldfish_audio.c index f1e18386e34d..364fdcdd3a06 100644 --- a/drivers/staging/goldfish/goldfish_audio.c +++ b/drivers/staging/goldfish/goldfish_audio.c @@ -280,12 +280,12 @@ static int goldfish_audio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (r == NULL) { + if (!r) { dev_err(&pdev->dev, "platform_get_resource failed\n"); return -ENODEV; } data->reg_base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE); - if (data->reg_base == NULL) + if (!data->reg_base) return -ENOMEM; data->irq = platform_get_irq(pdev, 0); @@ -295,7 +295,7 @@ static int goldfish_audio_probe(struct platform_device *pdev) } data->buffer_virt = dmam_alloc_coherent(&pdev->dev, COMBINED_BUFFER_SIZE, &buf_addr, GFP_KERNEL); - if (data->buffer_virt == NULL) { + if (!data->buffer_virt) { dev_err(&pdev->dev, "allocate buffer failed\n"); return -ENOMEM; } -- cgit v1.2.3 From 65dc15079604b6a96194513f36425b9df6629c79 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Mon, 11 Jan 2016 21:34:28 +0530 Subject: staging: comedi: dt2801: Prefer using the BIT macro As suggested by checkpatch.pl, this patch replaces bit shifting on 1 with the BIT(x) macro. Signed-off-by: Bhaktipriya Shridhar Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2801.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 80e38dedd359..6c7b4d27c27c 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -68,17 +68,17 @@ Configuration options: /* Command modifiers (only used with read/write), EXTTRIG can be used with some other commands. */ -#define DT_MOD_DMA (1<<4) -#define DT_MOD_CONT (1<<5) -#define DT_MOD_EXTCLK (1<<6) -#define DT_MOD_EXTTRIG (1<<7) +#define DT_MOD_DMA BIT(4) +#define DT_MOD_CONT BIT(5) +#define DT_MOD_EXTCLK BIT(6) +#define DT_MOD_EXTTRIG BIT(7) /* Bits in status register */ -#define DT_S_DATA_OUT_READY (1<<0) -#define DT_S_DATA_IN_FULL (1<<1) -#define DT_S_READY (1<<2) -#define DT_S_COMMAND (1<<3) -#define DT_S_COMPOSITE_ERROR (1<<7) +#define DT_S_DATA_OUT_READY BIT(0) +#define DT_S_DATA_IN_FULL BIT(1) +#define DT_S_READY BIT(2) +#define DT_S_COMMAND BIT(3) +#define DT_S_COMPOSITE_ERROR BIT(7) /* registers */ #define DT2801_DATA 0 -- cgit v1.2.3 From d4631301225a44d36b98ce39a2e3d6e00f59d8fb Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Mon, 11 Jan 2016 23:29:33 -0700 Subject: staging: comedi: ni_pcimio: Adds PXI-6251 to supported boards Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_pcimio.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index 30a5a75d1fe7..231e37d6b7c6 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -26,7 +26,8 @@ Devices: [National Instruments] PCI-MIO-16XE-50 (ni_pcimio), PXI-6040E, PCI-6030E, PCI-6031E, PCI-6032E, PCI-6033E, PCI-6071E, PCI-6023E, PCI-6024E, PCI-6025E, PXI-6025E, PCI-6034E, PCI-6035E, PCI-6052E, PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224, - PCI-6225, PXI-6225, PCI-6229, PCI-6250, PCI-6251, PCIe-6251, PXIe-6251, + PCI-6225, PXI-6225, PCI-6229, PCI-6250, + PCI-6251, PXI-6251, PCIe-6251, PXIe-6251, PCI-6254, PCI-6259, PCIe-6259, PCI-6280, PCI-6281, PXI-6281, PCI-6284, PCI-6289, PCI-6711, PXI-6711, PCI-6713, PXI-6713, @@ -193,6 +194,7 @@ enum ni_pcimio_boardid { BOARD_PCI6229, BOARD_PCI6250, BOARD_PCI6251, + BOARD_PXI6251, BOARD_PCIE6251, BOARD_PXIE6251, BOARD_PCI6254, @@ -811,6 +813,21 @@ static const struct ni_board_struct ni_boards[] = { .ao_speed = 350, .caldac = { caldac_none }, }, + [BOARD_PXI6251] = { + .name = "pxi-6251", + .n_adchan = 16, + .ai_maxdata = 0xffff, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_628x, + .ai_speed = 800, + .n_aochan = 2, + .ao_maxdata = 0xffff, + .ao_fifo_depth = 8191, + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_speed = 350, + .caldac = { caldac_none }, + }, [BOARD_PCIE6251] = { .name = "pcie-6251", .n_adchan = 16, @@ -1290,6 +1307,7 @@ static const struct pci_device_id ni_pcimio_pci_table[] = { { PCI_VDEVICE(NI, 0x71bc), BOARD_PCI6221_37PIN }, { PCI_VDEVICE(NI, 0x717d), BOARD_PCIE6251 }, { PCI_VDEVICE(NI, 0x72e8), BOARD_PXIE6251 }, + { PCI_VDEVICE(NI, 0x70ad), BOARD_PXI6251 }, { 0 } }; MODULE_DEVICE_TABLE(pci, ni_pcimio_pci_table); -- cgit v1.2.3 From 1fd24a4702d2af0ea4d5845126cf57d4d1796216 Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Tue, 12 Jan 2016 10:33:18 -0700 Subject: staging: comedi: ni_tiocmd: change mistaken use of start_src for start_arg This fixes a bug in function ni_tio_input_inttrig(). The trigger number should be compared to cmd->start_arg, not cmd->start_src. Fixes: 6a760394d7eb ("staging: comedi: ni_tiocmd: clarify the cmd->start_arg validation and use") Cc: # 3.17+ Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tiocmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index 437f723bb34d..823e47910004 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -92,7 +92,7 @@ static int ni_tio_input_inttrig(struct comedi_device *dev, unsigned long flags; int ret = 0; - if (trig_num != cmd->start_src) + if (trig_num != cmd->start_arg) return -EINVAL; spin_lock_irqsave(&counter->lock, flags); -- cgit v1.2.3 From f08a28e65cbdf80b4b4da7e423c45ee7c3ef35ac Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Tue, 12 Jan 2016 11:05:10 -0700 Subject: staging: comedi: ni_mio_common: use CR_CHAN more consistently Generally, the CR_CHAN macro is/should be used to access the relevant bits for channel identification in cmd->*_arg when the corresponding cmd->*_src==TRIG_EXT, including cmd->convert_arg in this case. This patch does not fix a bug per se, as NISTC_AI_MODE1_CONVERT_SRC() already masks the value sufficiently, but using CR_CHAN() here makes the code clearer as it avoids passing some irrelevant bits to NISTC_AI_MODE1_CONVERT_SRC() in the first place. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 5e8130a7d670..1978d65636fd 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -2428,7 +2428,8 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); break; case TRIG_EXT: - mode1 |= NISTC_AI_MODE1_CONVERT_SRC(1 + cmd->convert_arg); + mode1 |= NISTC_AI_MODE1_CONVERT_SRC(1 + + CR_CHAN(cmd->convert_arg)); if ((cmd->convert_arg & CR_INVERT) == 0) mode1 |= NISTC_AI_MODE1_CONVERT_POLARITY; ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG); -- cgit v1.2.3 From 5b293beb2ef0c45cd3c0e00ce67930b5d3471c13 Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Wed, 27 Jan 2016 14:28:24 -0700 Subject: staging: comedi: mite: enable continuous regeneration of finite samples This change enables the mite DMA controller to only transfer the amount of data needed by a command. By default, the old behavior of transferring the entire comedi DMA data buffer is still in effect. These changes allow a command to only transmit a limited portion of that data buffer as needed. This patch begins to reinterprets stop_arg when stop_src == TRIG_NONE to allow the user to specify the length of the buffer that should be repeated. The intent is to allow a user to have a specific buffer repeated as-is indefinitely. The contents of the DMA buffer can be left static or changed by the user via mmap access to the DMA buffer. If the contents are changed by the user, additional munging is not performed by the driver and only a single call to comedi_mark_buffer_written should be done. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/mite.c | 72 ++++++++++++++++++++++++++++++----- drivers/staging/comedi/drivers/mite.h | 3 ++ 2 files changed, 66 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index fa7ae2c04556..8f24702c3380 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -297,7 +297,6 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, { struct comedi_async *async = s->async; unsigned int n_links; - int i; if (ring->descriptors) { dma_free_coherent(ring->hw_dev, @@ -326,17 +325,58 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, } ring->n_links = n_links; - for (i = 0; i < n_links; i++) { + return mite_init_ring_descriptors(ring, s, n_links << PAGE_SHIFT); +} +EXPORT_SYMBOL_GPL(mite_buf_change); + +/* + * initializes the ring buffer descriptors to provide correct DMA transfer links + * to the exact amount of memory required. When the ring buffer is allocated in + * mite_buf_change, the default is to initialize the ring to refer to the entire + * DMA data buffer. A command may call this function later to re-initialize and + * shorten the amount of memory that will be transferred. + */ +int mite_init_ring_descriptors(struct mite_dma_descriptor_ring *ring, + struct comedi_subdevice *s, + unsigned int nbytes) +{ + struct comedi_async *async = s->async; + unsigned int n_full_links = nbytes >> PAGE_SHIFT; + unsigned int remainder = nbytes % PAGE_SIZE; + int i; + + dev_dbg(s->device->class_dev, + "mite: init ring buffer to %u bytes\n", nbytes); + + if ((n_full_links + (remainder > 0 ? 1 : 0)) > ring->n_links) { + dev_err(s->device->class_dev, + "mite: ring buffer too small for requested init\n"); + return -ENOMEM; + } + + /* We set the descriptors for all full links. */ + for (i = 0; i < n_full_links; ++i) { ring->descriptors[i].count = cpu_to_le32(PAGE_SIZE); ring->descriptors[i].addr = cpu_to_le32(async->buf_map->page_list[i].dma_addr); ring->descriptors[i].next = - cpu_to_le32(ring->descriptors_dma_addr + (i + - 1) * - sizeof(struct mite_dma_descriptor)); + cpu_to_le32(ring->descriptors_dma_addr + + (i + 1) * sizeof(struct mite_dma_descriptor)); } - ring->descriptors[n_links - 1].next = - cpu_to_le32(ring->descriptors_dma_addr); + + /* the last link is either a remainder or was a full link. */ + if (remainder > 0) { + /* set the lesser count for the remainder link */ + ring->descriptors[i].count = cpu_to_le32(remainder); + ring->descriptors[i].addr = + cpu_to_le32(async->buf_map->page_list[i].dma_addr); + /* increment i so that assignment below refs last link */ + ++i; + } + + /* Assign the last link->next to point back to the head of the list. */ + ring->descriptors[i - 1].next = cpu_to_le32(ring->descriptors_dma_addr); + /* * barrier is meant to insure that all the writes to the dma descriptors * have completed before the dma controller is commanded to read them @@ -344,7 +384,7 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, smp_wmb(); return 0; } -EXPORT_SYMBOL_GPL(mite_buf_change); +EXPORT_SYMBOL_GPL(mite_init_ring_descriptors); void mite_prep_dma(struct mite_channel *mite_chan, unsigned int num_device_bits, unsigned int num_memory_bits) @@ -552,6 +592,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan, unsigned int old_alloc_count = async->buf_read_alloc_count; u32 nbytes_ub, nbytes_lb; int count; + bool finite_regen = (cmd->stop_src == TRIG_NONE && stop_count != 0); /* read alloc as much as we can */ comedi_buf_read_alloc(s, async->prealloc_bufsz); @@ -561,11 +602,24 @@ int mite_sync_output_dma(struct mite_channel *mite_chan, nbytes_ub = mite_bytes_read_from_memory_ub(mite_chan); if (cmd->stop_src == TRIG_COUNT && (int)(nbytes_ub - stop_count) > 0) nbytes_ub = stop_count; - if ((int)(nbytes_ub - old_alloc_count) > 0) { + + if ((!finite_regen || stop_count > old_alloc_count) && + ((int)(nbytes_ub - old_alloc_count) > 0)) { dev_warn(s->device->class_dev, "mite: DMA underrun\n"); async->events |= COMEDI_CB_OVERFLOW; return -1; } + + if (finite_regen) { + /* + * This is a special case where we continuously output a finite + * buffer. In this case, we do not free any of the memory, + * hence we expect that old_alloc_count will reach a maximum of + * stop_count bytes. + */ + return 0; + } + count = nbytes_lb - async->buf_read_count; if (count <= 0) return 0; diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h index c32d4e4ddccc..87534b07ec81 100644 --- a/drivers/staging/comedi/drivers/mite.h +++ b/drivers/staging/comedi/drivers/mite.h @@ -110,6 +110,9 @@ void mite_prep_dma(struct mite_channel *mite_chan, unsigned int num_device_bits, unsigned int num_memory_bits); int mite_buf_change(struct mite_dma_descriptor_ring *ring, struct comedi_subdevice *s); +int mite_init_ring_descriptors(struct mite_dma_descriptor_ring *ring, + struct comedi_subdevice *s, + unsigned int nbytes); enum mite_registers { /* -- cgit v1.2.3 From 5c93736c208d89c7832624b8f3a2ce616473ab65 Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Wed, 27 Jan 2016 14:28:25 -0700 Subject: staging: comedi: ni_mio_common: Cleans up/clarifies ni_ao_reset This patch implements ni_ao_reset much more closely organized like NI MHDDK examples and DAQ-STC pseudo-code. Adds comments with some more specific references to the DAQ-STC. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 70 +++++++++++++++++--------- 1 file changed, 46 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 1978d65636fd..7d2091d8b72b 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -3215,48 +3215,70 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s) { + /* See 3.6.1.2 "Resetting", of DAQ-STC Technical Reference Manual */ + + /* + * In the following, the "--sync" comments are meant to denote + * asynchronous boundaries for setting the registers as described in the + * DAQ-STC mostly in the order also described in the DAQ-STC. + */ + struct ni_private *devpriv = dev->private; ni_release_ao_mite_channel(dev); + /* --sync (reset AO) */ + if (devpriv->is_m_series) + /* following example in mhddk for m-series */ + ni_stc_writew(dev, NISTC_RESET_AO, NISTC_RESET_REG); + + /*--sync (start config) */ ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); + + /*--sync (Disarm) */ ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG); - ni_set_bits(dev, NISTC_INTB_ENA_REG, ~0, 0); - ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL, NISTC_AO_PERSONAL_REG); - ni_stc_writew(dev, NISTC_INTB_ACK_AO_ALL, NISTC_INTB_ACK_REG); - ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL | - NISTC_AO_PERSONAL_UPDATE_PW | - NISTC_AO_PERSONAL_TMRDACWR_PW, - NISTC_AO_PERSONAL_REG); - ni_stc_writew(dev, 0, NISTC_AO_OUT_CTRL_REG); - ni_stc_writew(dev, 0, NISTC_AO_START_SEL_REG); - devpriv->ao_cmd1 = 0; - ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG); - devpriv->ao_cmd2 = 0; - ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG); + + /* + * --sync + * (clear bunch of registers--mseries mhddk examples do not include + * this) + */ + devpriv->ao_cmd1 = 0; + devpriv->ao_cmd2 = 0; devpriv->ao_mode1 = 0; - ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); devpriv->ao_mode2 = 0; - ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); if (devpriv->is_m_series) devpriv->ao_mode3 = NISTC_AO_MODE3_LAST_GATE_DISABLE; else devpriv->ao_mode3 = 0; - ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); devpriv->ao_trigger_select = 0; - ni_stc_writew(dev, devpriv->ao_trigger_select, - NISTC_AO_TRIG_SEL_REG); - if (devpriv->is_6xxx) { - unsigned immediate_bits = 0; - unsigned i; - for (i = 0; i < s->n_chan; ++i) - immediate_bits |= 1 << i; - ni_ao_win_outw(dev, immediate_bits, NI671X_AO_IMMEDIATE_REG); + ni_stc_writew(dev, 0, NISTC_AO_PERSONAL_REG); + ni_stc_writew(dev, 0, NISTC_AO_CMD1_REG); + ni_stc_writew(dev, 0, NISTC_AO_CMD2_REG); + ni_stc_writew(dev, 0, NISTC_AO_MODE1_REG); + ni_stc_writew(dev, 0, NISTC_AO_MODE2_REG); + ni_stc_writew(dev, 0, NISTC_AO_OUT_CTRL_REG); + ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); + ni_stc_writew(dev, 0, NISTC_AO_START_SEL_REG); + ni_stc_writew(dev, 0, NISTC_AO_TRIG_SEL_REG); + + /*--sync (disable interrupts) */ + ni_set_bits(dev, NISTC_INTB_ENA_REG, ~0, 0); + + /*--sync (ack) */ + ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL, NISTC_AO_PERSONAL_REG); + ni_stc_writew(dev, NISTC_INTB_ACK_AO_ALL, NISTC_INTB_ACK_REG); + + /*--not in DAQ-STC. which doc? */ + if (devpriv->is_6xxx) { + ni_ao_win_outw(dev, (1u << s->n_chan) - 1u, + NI671X_AO_IMMEDIATE_REG); ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG, NI611X_AO_MISC_REG); } ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); + /*--end */ return 0; } -- cgit v1.2.3 From d2a6c32a2209ac79cb52b56e46ec37fdc1df6ce1 Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Wed, 27 Jan 2016 14:28:26 -0700 Subject: staging: comedi: ni_mio_common: make more bits in ao_cmd1 reg be stateful Bits NISTC_AO_CMD1_DAC0_UPDATE_MODE and NISTC_AO_CMD1_DAC1_UPDATE_MODE are now saved in the local copy of the AO_CMD1 register. This is more appropriate than prior methods of setting these bits specifically _both_ in the ni_ao_cmd configuration function _and_ the ni_ao_inttrig trigger function. With this patch, the bits are only specifically called out now in the ni_ao_cmd configuration function. In the ni_ao_inttrig trigger function, only the UI_ARM, UC_ARM, BC_ARM bits of the ao_cmd1 register are specifically called out. Each of these bits is a strobe bit, while the DAC[0-1]_UPDATE_MODE bits are simple write bits. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 7d2091d8b72b..9df20d922d32 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -2903,8 +2903,6 @@ static int ni_ao_inttrig(struct comedi_device *dev, ni_stc_writew(dev, NISTC_AO_CMD1_UI_ARM | NISTC_AO_CMD1_UC_ARM | NISTC_AO_CMD1_BC_ARM | - NISTC_AO_CMD1_DAC1_UPDATE_MODE | - NISTC_AO_CMD1_DAC0_UPDATE_MODE | devpriv->ao_cmd1, NISTC_AO_CMD1_REG); @@ -3081,9 +3079,11 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); - ni_stc_writew(dev, NISTC_AO_CMD1_DAC1_UPDATE_MODE | - NISTC_AO_CMD1_DAC0_UPDATE_MODE, - NISTC_AO_CMD1_REG); + /* Configure DAQ-STC for Timed update mode */ + devpriv->ao_cmd1 |= NISTC_AO_CMD1_DAC1_UPDATE_MODE | + NISTC_AO_CMD1_DAC0_UPDATE_MODE; + /* We are not using UPDATE2-->don't have to set DACx_Source_Select */ + ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG); devpriv->ao_mode3 |= NISTC_AO_MODE3_STOP_ON_OVERRUN_ERR; ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); -- cgit v1.2.3 From 080e6795cba316663a5eb4f49500937eca4f32cd Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Wed, 27 Jan 2016 14:28:27 -0700 Subject: staging: comedi: ni_mio_common: Cleans up/clarifies ni_ao_cmd This patch implements ni_ao_cmd much more closely organized like NI MHDDK examples and DAQ-STC pseudo-code. Adds comments with some more specific references to the DAQ-STC. For stop_src==TRIG_NONE (continuous output mode of entire buffer), the count for the UC counter was corrected to represent the maximum count possible (0xffffff). Prior behavior for stop_src=TRIG_NONE did not actually follow the DAQ-STC. Furthermore, stop_src==TRIG_NONE now correctly uses code specialized for either m-series or e-series devices. It should be noted that stop_src==TRIG_NONE does _not_ with this patch (or with prior behavior in ni_mio_common) actually implement true continuous output. Rather, the output is simply configured to operate as a single buffer output, but where the buffer is as large as is possible with NI-STC hardware. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 443 ++++++++++++++++++------- 1 file changed, 318 insertions(+), 125 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 9df20d922d32..8f0fe3a26c73 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -2912,42 +2912,68 @@ static int ni_ao_inttrig(struct comedi_device *dev, return 0; } -static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) +/* + * begin ni_ao_cmd. + * Organized similar to NI-STC and MHDDK examples. + * ni_ao_cmd is broken out into configuration sub-routines for clarity. + */ + +static void ni_ao_cmd_personalize(struct comedi_device *dev, + const struct comedi_cmd *cmd) { const struct ni_board_struct *board = dev->board_ptr; - struct ni_private *devpriv = dev->private; - const struct comedi_cmd *cmd = &s->async->cmd; - int bits; - int i; - unsigned trigvar; - unsigned val; - - if (dev->irq == 0) { - dev_err(dev->class_dev, "cannot run command without an irq\n"); - return -EIO; - } + unsigned bits; ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); - ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG); + bits = + /* fast CPU interface--only eseries */ + /* ((slow CPU interface) ? 0 : AO_Fast_CPU) | */ + NISTC_AO_PERSONAL_BC_SRC_SEL | + 0 /* (use_original_pulse ? 0 : NISTC_AO_PERSONAL_UPDATE_TIMEBASE) */ | + /* + * FIXME: start setting following bit when appropriate. Need to + * determine whether board is E4 or E1. + * FROM MHHDK: + * if board is E4 or E1 + * Set bit "NISTC_AO_PERSONAL_UPDATE_PW" to 0 + * else + * set it to 1 + */ + NISTC_AO_PERSONAL_UPDATE_PW | + /* FIXME: when should we set following bit to zero? */ + NISTC_AO_PERSONAL_TMRDACWR_PW | + (board->ao_fifo_depth ? + NISTC_AO_PERSONAL_FIFO_ENA : NISTC_AO_PERSONAL_DMA_PIO_CTRL) + ; +#if 0 + /* + * FIXME: + * add something like ".has_individual_dacs = 0" to ni_board_struct + * since, as F Hess pointed out, not all in m series have singles. not + * sure if e-series all have duals... + */ - if (devpriv->is_6xxx) { - ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG, - NI611X_AO_MISC_REG); + /* + * F Hess: windows driver does not set NISTC_AO_PERSONAL_NUM_DAC bit for + * 6281, verified with bus analyzer. + */ + if (devpriv->is_m_series) + bits |= NISTC_AO_PERSONAL_NUM_DAC; +#endif + ni_stc_writew(dev, bits, NISTC_AO_PERSONAL_REG); - bits = 0; - for (i = 0; i < cmd->chanlist_len; i++) { - int chan; + ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); +} - chan = CR_CHAN(cmd->chanlist[i]); - bits |= 1 << chan; - ni_ao_win_outw(dev, chan, NI611X_AO_WAVEFORM_GEN_REG); - } - ni_ao_win_outw(dev, bits, NI611X_AO_TIMED_REG); - } +static void ni_ao_cmd_set_trigger(struct comedi_device *dev, + const struct comedi_cmd *cmd) +{ + struct ni_private *devpriv = dev->private; - ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1); + ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); + /* sync */ if (cmd->stop_src == TRIG_NONE) { devpriv->ao_mode1 |= NISTC_AO_MODE1_CONTINUOUS; devpriv->ao_mode1 &= ~NISTC_AO_MODE1_TRIGGER_ONCE; @@ -2957,179 +2983,346 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); - val = devpriv->ao_trigger_select; - switch (cmd->start_src) { - case TRIG_INT: - case TRIG_NOW: - val &= ~(NISTC_AO_TRIG_START1_POLARITY | - NISTC_AO_TRIG_START1_SEL_MASK); - val |= NISTC_AO_TRIG_START1_EDGE | - NISTC_AO_TRIG_START1_SYNC; - break; - case TRIG_EXT: - val = NISTC_AO_TRIG_START1_SEL(CR_CHAN(cmd->start_arg) + 1); - if (cmd->start_arg & CR_INVERT) { - /* 0=active high, 1=active low. see daq-stc 3-24 (p186) */ - val |= NISTC_AO_TRIG_START1_POLARITY; - } - if (cmd->start_arg & CR_EDGE) { - /* 0=edge detection disabled, 1=enabled */ - val |= NISTC_AO_TRIG_START1_EDGE; + { + unsigned int trigsel = devpriv->ao_trigger_select; + + switch (cmd->start_src) { + case TRIG_INT: + case TRIG_NOW: + trigsel &= ~(NISTC_AO_TRIG_START1_POLARITY | + NISTC_AO_TRIG_START1_SEL_MASK); + trigsel |= NISTC_AO_TRIG_START1_EDGE | + NISTC_AO_TRIG_START1_SYNC; + break; + case TRIG_EXT: + trigsel = NISTC_AO_TRIG_START1_SEL( + CR_CHAN(cmd->start_arg) + 1); + if (cmd->start_arg & CR_INVERT) + /* + * 0=active high, 1=active low. + * see daq-stc 3-24 (p186) + */ + trigsel |= NISTC_AO_TRIG_START1_POLARITY; + if (cmd->start_arg & CR_EDGE) + /* 0=edge detection disabled, 1=enabled */ + trigsel |= NISTC_AO_TRIG_START1_EDGE; + break; + default: + BUG(); + break; } + + devpriv->ao_trigger_select = trigsel; ni_stc_writew(dev, devpriv->ao_trigger_select, NISTC_AO_TRIG_SEL_REG); - break; - default: - BUG(); - break; } - devpriv->ao_trigger_select = val; - ni_stc_writew(dev, devpriv->ao_trigger_select, NISTC_AO_TRIG_SEL_REG); + /* AO_Delayed_START1 = 0, we do not support delayed start...yet */ + /* sync */ + /* select DA_START1 as PFI6/AO_START1 when configured as an output */ devpriv->ao_mode3 &= ~NISTC_AO_MODE3_TRIG_LEN; ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); + ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); +} + +static void ni_ao_cmd_set_counters(struct comedi_device *dev, + const struct comedi_cmd *cmd) +{ + struct ni_private *devpriv = dev->private; + /* Not supporting 'waveform staging' or 'local buffer with pauses' */ + + ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); + /* + * This relies on ao_mode1/(Trigger_Once | Continuous) being set in + * set_trigger above. It is unclear whether we really need to re-write + * this register with these values. The mhddk examples for e-series + * show writing this in both places, but the examples for m-series show + * a single write in the set_counters function (here). + */ ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); + + /* sync (upload number of buffer iterations -1) */ + /* indicate that we want to use BC_Load_A_Register as the source */ devpriv->ao_mode2 &= ~NISTC_AO_MODE2_BC_INIT_LOAD_SRC; ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); - if (cmd->stop_src == TRIG_NONE) - ni_stc_writel(dev, 0xffffff, NISTC_AO_BC_LOADA_REG); - else - ni_stc_writel(dev, 0, NISTC_AO_BC_LOADA_REG); + + /* + * if the BC_TC interrupt is still issued in spite of UC, BC, UI + * ignoring BC_TC, then we will need to find a way to ignore that + * interrupt in continuous mode. + */ + ni_stc_writel(dev, 0, NISTC_AO_BC_LOADA_REG); /* iter once */ + + /* sync (issue command to load number of buffer iterations -1) */ ni_stc_writew(dev, NISTC_AO_CMD1_BC_LOAD, NISTC_AO_CMD1_REG); + + /* sync (upload number of updates in buffer) */ + /* indicate that we want to use UC_Load_A_Register as the source */ devpriv->ao_mode2 &= ~NISTC_AO_MODE2_UC_INIT_LOAD_SRC; ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); - switch (cmd->stop_src) { - case TRIG_COUNT: + + { + /* + * Current behavior is to configure the maximum update count + * possible when continuous output mode is requested. + */ + unsigned int stop_arg = cmd->stop_src == TRIG_COUNT ? + (cmd->stop_arg & 0xffffff) : 0xffffff; + if (devpriv->is_m_series) { - /* this is how the NI example code does it for m-series boards, verified correct with 6259 */ - ni_stc_writel(dev, cmd->stop_arg - 1, - NISTC_AO_UC_LOADA_REG); + /* + * this is how the NI example code does it for m-series + * boards, verified correct with 6259 + */ + ni_stc_writel(dev, stop_arg - 1, NISTC_AO_UC_LOADA_REG); + + /* sync (issue cmd to load number of updates in MISB) */ ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG); } else { - ni_stc_writel(dev, cmd->stop_arg, - NISTC_AO_UC_LOADA_REG); + ni_stc_writel(dev, stop_arg, NISTC_AO_UC_LOADA_REG); + + /* sync (issue cmd to load number of updates in MISB) */ ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG); - ni_stc_writel(dev, cmd->stop_arg - 1, - NISTC_AO_UC_LOADA_REG); + + /* + * sync (upload number of updates-1 in MISB) + * --eseries only? + */ + ni_stc_writel(dev, stop_arg - 1, NISTC_AO_UC_LOADA_REG); } - break; - case TRIG_NONE: - ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG); - ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG); - ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG); - break; - default: - ni_stc_writel(dev, 0, NISTC_AO_UC_LOADA_REG); - ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG); - ni_stc_writel(dev, cmd->stop_arg, NISTC_AO_UC_LOADA_REG); } - devpriv->ao_mode1 &= ~(NISTC_AO_MODE1_UPDATE_SRC_MASK | - NISTC_AO_MODE1_UI_SRC_MASK | - NISTC_AO_MODE1_UPDATE_SRC_POLARITY | - NISTC_AO_MODE1_UI_SRC_POLARITY); + ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); +} + +static void ni_ao_cmd_set_update(struct comedi_device *dev, + const struct comedi_cmd *cmd) +{ + struct ni_private *devpriv = dev->private; + + ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); + + /* + * zero out these bit fields to be set below. Does an ao-reset do this + * automatically? + */ + devpriv->ao_mode1 &= ~( + NISTC_AO_MODE1_UI_SRC_MASK | + NISTC_AO_MODE1_UI_SRC_POLARITY | + NISTC_AO_MODE1_UPDATE_SRC_MASK | + NISTC_AO_MODE1_UPDATE_SRC_POLARITY + ); + switch (cmd->scan_begin_src) { case TRIG_TIMER: - devpriv->ao_cmd2 &= ~NISTC_AO_CMD2_BC_GATE_ENA; - trigvar = - ni_ns_to_timer(dev, cmd->scan_begin_arg, - CMDF_ROUND_NEAREST); - ni_stc_writel(dev, 1, NISTC_AO_UI_LOADA_REG); - ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD, NISTC_AO_CMD1_REG); - ni_stc_writel(dev, trigvar, NISTC_AO_UI_LOADA_REG); + devpriv->ao_cmd2 &= ~NISTC_AO_CMD2_BC_GATE_ENA; + + /* + * NOTE: there are several other ways of configuring internal + * updates, but we'll only support one for now: using + * AO_IN_TIMEBASE, w/o waveform staging, w/o a delay between + * START1 and first update, and also w/o local buffer mode w/ + * pauses. + */ + + /* + * This is already done above: + * devpriv->ao_mode1 &= ~( + * // set UPDATE_Source to UI_TC: + * NISTC_AO_MODE1_UPDATE_SRC_MASK | + * // set UPDATE_Source_Polarity to rising (required?) + * NISTC_AO_MODE1_UPDATE_SRC_POLARITY | + * // set UI_Source to AO_IN_TIMEBASE1: + * NISTC_AO_MODE1_UI_SRC_MASK | + * // set UI_Source_Polarity to rising (required?) + * NISTC_AO_MODE1_UI_SRC_POLARITY + * ); + */ + + /* + * TODO: use ao_ui_clock_source to allow all possible signals + * to be routed to UI_Source_Select. See tSTC.h for + * eseries/ni67xx and tMSeries.h for mseries. + */ + + { + unsigned trigvar = ni_ns_to_timer(dev, + cmd->scan_begin_arg, + CMDF_ROUND_NEAREST); + + /* + * Wait N TB3 ticks after the start trigger before + * clocking(N must be >=2). + */ + /* following line: 2-1 per STC */ + ni_stc_writel(dev, 1, NISTC_AO_UI_LOADA_REG); + ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD, + NISTC_AO_CMD1_REG); + /* following line: N-1 per STC */ + ni_stc_writel(dev, trigvar - 1, NISTC_AO_UI_LOADA_REG); + } break; case TRIG_EXT: - devpriv->ao_mode1 |= - NISTC_AO_MODE1_UPDATE_SRC(cmd->scan_begin_arg); + /* FIXME: assert scan_begin_arg != 0, ret failure otherwise */ + devpriv->ao_cmd2 |= NISTC_AO_CMD2_BC_GATE_ENA; + devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC( + CR_CHAN(cmd->scan_begin_arg)); if (cmd->scan_begin_arg & CR_INVERT) devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC_POLARITY; - devpriv->ao_cmd2 |= NISTC_AO_CMD2_BC_GATE_ENA; break; default: BUG(); break; } + ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG); ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); devpriv->ao_mode2 &= ~(NISTC_AO_MODE2_UI_RELOAD_MODE(3) | NISTC_AO_MODE2_UI_INIT_LOAD_SRC); ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); + /* Configure DAQ-STC for Timed update mode */ + devpriv->ao_cmd1 |= NISTC_AO_CMD1_DAC1_UPDATE_MODE | + NISTC_AO_CMD1_DAC0_UPDATE_MODE; + /* We are not using UPDATE2-->don't have to set DACx_Source_Select */ + ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG); + + ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); +} + +static void ni_ao_cmd_set_channels(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct ni_private *devpriv = dev->private; + const struct comedi_cmd *cmd = &s->async->cmd; + unsigned bits = 0; + + ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); + + if (devpriv->is_6xxx) { + unsigned int i; + + bits = 0; + for (i = 0; i < cmd->chanlist_len; ++i) { + int chan = CR_CHAN(cmd->chanlist[i]); + + bits |= 1 << chan; + ni_ao_win_outw(dev, chan, NI611X_AO_WAVEFORM_GEN_REG); + } + ni_ao_win_outw(dev, bits, NI611X_AO_TIMED_REG); + } + + ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1); + if (cmd->scan_end_arg > 1) { devpriv->ao_mode1 |= NISTC_AO_MODE1_MULTI_CHAN; - ni_stc_writew(dev, - NISTC_AO_OUT_CTRL_CHANS(cmd->scan_end_arg - 1) | - NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ, - NISTC_AO_OUT_CTRL_REG); - } else { - unsigned bits; + bits = NISTC_AO_OUT_CTRL_CHANS(cmd->scan_end_arg - 1) + | NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ; + } else { devpriv->ao_mode1 &= ~NISTC_AO_MODE1_MULTI_CHAN; bits = NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ; - if (devpriv->is_m_series || devpriv->is_6xxx) { + if (devpriv->is_m_series | devpriv->is_6xxx) bits |= NISTC_AO_OUT_CTRL_CHANS(0); - } else { - bits |= - NISTC_AO_OUT_CTRL_CHANS(CR_CHAN(cmd->chanlist[0])); - } - ni_stc_writew(dev, bits, NISTC_AO_OUT_CTRL_REG); + else + bits |= NISTC_AO_OUT_CTRL_CHANS( + CR_CHAN(cmd->chanlist[0])); } + ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); + ni_stc_writew(dev, bits, NISTC_AO_OUT_CTRL_REG); - /* Configure DAQ-STC for Timed update mode */ - devpriv->ao_cmd1 |= NISTC_AO_CMD1_DAC1_UPDATE_MODE | - NISTC_AO_CMD1_DAC0_UPDATE_MODE; - /* We are not using UPDATE2-->don't have to set DACx_Source_Select */ - ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG); + ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); +} + +static void ni_ao_cmd_set_stop_conditions(struct comedi_device *dev, + const struct comedi_cmd *cmd) +{ + struct ni_private *devpriv = dev->private; + + ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); devpriv->ao_mode3 |= NISTC_AO_MODE3_STOP_ON_OVERRUN_ERR; ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); + /* + * Since we are not supporting waveform staging, we ignore these errors: + * NISTC_AO_MODE3_STOP_ON_BC_TC_ERR, + * NISTC_AO_MODE3_STOP_ON_BC_TC_TRIG_ERR + */ + + ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); +} + +static void ni_ao_cmd_set_fifo_mode(struct comedi_device *dev) +{ + struct ni_private *devpriv = dev->private; + + ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); + devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_MODE_MASK; #ifdef PCIDMA devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF_F; #else devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF; #endif + /* NOTE: this is where use_onboard_memory=True would be implemented */ devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_REXMIT_ENA; ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); - bits = NISTC_AO_PERSONAL_BC_SRC_SEL | - NISTC_AO_PERSONAL_UPDATE_PW | - NISTC_AO_PERSONAL_TMRDACWR_PW; - if (board->ao_fifo_depth) - bits |= NISTC_AO_PERSONAL_FIFO_ENA; - else - bits |= NISTC_AO_PERSONAL_DMA_PIO_CTRL; -#if 0 - /* - * F Hess: windows driver does not set NISTC_AO_PERSONAL_NUM_DAC bit - * for 6281, verified with bus analyzer. - */ - if (devpriv->is_m_series) - bits |= NISTC_AO_PERSONAL_NUM_DAC; -#endif - ni_stc_writew(dev, bits, NISTC_AO_PERSONAL_REG); - /* enable sending of ao dma requests */ + /* enable sending of ao fifo requests (dma request) */ ni_stc_writew(dev, NISTC_AO_START_AOFREQ_ENA, NISTC_AO_START_SEL_REG); ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); - if (cmd->stop_src == TRIG_COUNT) { - ni_stc_writew(dev, NISTC_INTB_ACK_AO_BC_TC, - NISTC_INTB_ACK_REG); + /* we are not supporting boards with virtual fifos */ +} + +static void ni_ao_cmd_set_interrupts(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + if (s->async->cmd.stop_src == TRIG_COUNT) ni_set_bits(dev, NISTC_INTB_ENA_REG, NISTC_INTB_ENA_AO_BC_TC, 1); - } s->async->inttrig = ni_ao_inttrig; +} +static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) +{ + struct ni_private *devpriv = dev->private; + const struct comedi_cmd *cmd = &s->async->cmd; + + if (dev->irq == 0) { + dev_err(dev->class_dev, "cannot run command without an irq"); + return -EIO; + } + + /* ni_ao_reset should have already been done */ + ni_ao_cmd_personalize(dev, cmd); + /* clearing fifo and preload happens elsewhere */ + + ni_ao_cmd_set_trigger(dev, cmd); + ni_ao_cmd_set_counters(dev, cmd); + ni_ao_cmd_set_update(dev, cmd); + ni_ao_cmd_set_channels(dev, s); + ni_ao_cmd_set_stop_conditions(dev, cmd); + ni_ao_cmd_set_fifo_mode(dev); + ni_ao_cmd_set_interrupts(dev, s); + + /* + * arm(ing) and star(ting) happen in ni_ao_inttrig, which _must_ be + * called for ao commands since 1) TRIG_NOW is not supported and 2) DMA + * must be setup and initially written to before arm/start happen. + */ return 0; } +/* end ni_ao_cmd */ + static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { -- cgit v1.2.3 From 6aab7fee7a24395db1b556a5e5cf30aa2627c2be Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Wed, 27 Jan 2016 14:28:28 -0700 Subject: staging: comedi: ni_mio_common: adds finite regeneration to AO output This patch implements for analog output the reinterpretation of stop_arg when stop_src == TRIG_NONE to allow the user to specify the length of the buffer that should be repeated. The intent is to allow a user to have a specific buffer repeated as-is indefinitely. The contents of the DMA buffer can be left static or changed by the user via mmap access to the DMA buffer. If the contents are changed by the user, additional munging is not performed by the driver and only a single call to comedi_mark_buffer_written should be done. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 61 +++++++++++++++++++------- 1 file changed, 46 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 8f0fe3a26c73..1a22c79c2817 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -1500,7 +1500,8 @@ static void handle_b_interrupt(struct comedi_device *dev, s->async->events |= COMEDI_CB_OVERFLOW; } - if (b_status & NISTC_AO_STATUS1_BC_TC) + if (s->async->cmd.stop_src != TRIG_NONE && + b_status & NISTC_AO_STATUS1_BC_TC) s->async->events |= COMEDI_CB_EOA; #ifndef PCIDMA @@ -2073,6 +2074,37 @@ static unsigned ni_timer_to_ns(const struct comedi_device *dev, int timer) return devpriv->clock_ns * (timer + 1); } +static void ni_cmd_set_mite_transfer(struct mite_dma_descriptor_ring *ring, + struct comedi_subdevice *sdev, + const struct comedi_cmd *cmd, + unsigned int max_count) { +#ifdef PCIDMA + unsigned int nbytes = max_count; + + if (cmd->stop_arg > 0 && cmd->stop_arg < max_count) + nbytes = cmd->stop_arg; + nbytes *= comedi_bytes_per_scan(sdev); + + if (nbytes > sdev->async->prealloc_bufsz) { + if (cmd->stop_arg > 0) + dev_err(sdev->device->class_dev, + "ni_cmd_set_mite_transfer: tried exact data transfer limits greater than buffer size\n"); + + /* + * we can only transfer up to the size of the buffer. In this + * case, the user is expected to continue to write into the + * comedi buffer (already implemented as a ring buffer). + */ + nbytes = sdev->async->prealloc_bufsz; + } + + mite_init_ring_descriptors(ring, sdev, nbytes); +#else + dev_err(sdev->device->class_dev, + "ni_cmd_set_mite_transfer: exact data transfer limits not implemented yet without DMA\n"); +#endif +} + static unsigned ni_min_ai_scan_period_ns(struct comedi_device *dev, unsigned num_channels) { @@ -3062,12 +3094,16 @@ static void ni_ao_cmd_set_counters(struct comedi_device *dev, devpriv->ao_mode2 &= ~NISTC_AO_MODE2_UC_INIT_LOAD_SRC; ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); + /* + * if a user specifies '0', this automatically assumes the entire 24bit + * address space is available for the (multiple iterations of single + * buffer) MISB. Otherwise, stop_arg specifies the MISB length that + * will be used, regardless of whether we are in continuous mode or not. + * In continuous mode, the output will just iterate indefinitely over + * the MISB. + */ { - /* - * Current behavior is to configure the maximum update count - * possible when continuous output mode is requested. - */ - unsigned int stop_arg = cmd->stop_src == TRIG_COUNT ? + unsigned int stop_arg = cmd->stop_arg > 0 ? (cmd->stop_arg & 0xffffff) : 0xffffff; if (devpriv->is_m_series) { @@ -3311,6 +3347,7 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ni_ao_cmd_set_channels(dev, s); ni_ao_cmd_set_stop_conditions(dev, cmd); ni_ao_cmd_set_fifo_mode(dev); + ni_cmd_set_mite_transfer(devpriv->ao_mite_ring, s, cmd, 0x00ffffff); ni_ao_cmd_set_interrupts(dev, s); /* @@ -3381,11 +3418,7 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0); err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); - - if (cmd->stop_src == TRIG_COUNT) - err |= comedi_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff); - else /* TRIG_NONE */ - err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); + err |= comedi_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff); if (err) return 3; @@ -5240,7 +5273,6 @@ static irqreturn_t ni_E_interrupt(int irq, void *d) unsigned long flags; #ifdef PCIDMA struct ni_private *devpriv = dev->private; - struct mite_struct *mite = devpriv->mite; #endif if (!dev->attached) @@ -5252,8 +5284,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d) a_status = ni_stc_readw(dev, NISTC_AI_STATUS1_REG); b_status = ni_stc_readw(dev, NISTC_AO_STATUS1_REG); #ifdef PCIDMA - if (mite) { - struct ni_private *devpriv = dev->private; + if (devpriv->mite) { unsigned long flags_too; spin_lock_irqsave(&devpriv->mite_channel_lock, flags_too); @@ -5269,7 +5300,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d) ao_mite_status = mite_get_status(devpriv->ao_mite_chan); if (ao_mite_status & CHSR_LINKC) writel(CHOR_CLRLC, - mite->mite_io_addr + + devpriv->mite->mite_io_addr + MITE_CHOR(devpriv-> ao_mite_chan->channel)); } -- cgit v1.2.3 From f164cbf98fa8692ecbe1f870c50522985d34d1c2 Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Wed, 27 Jan 2016 14:28:29 -0700 Subject: staging: comedi: ni_mio_common: add finite regeneration to dio output This patch continues the implementation of reinterpreting stop_arg when stop_src == TRIG_NONE for national instruments cdio output on e/m-series devices. This is part of a series of patches that allow a user to have a specific buffer repeated as-is indefinitely. The contents of the DMA buffer can be left static or changed by the user via mmap access to the DMA buffer. If the contents are changed by the user, additional munging is not performed by the driver and only a single call to comedi_mark_buffer_written should be done. The original behavior is preserved when stop_arg == 0, as would be the prior use case. As opposed to analog output, this patch is relatively simple. First, the digital output capabilities are much more limited/simple as compared to the analog output device on NI e/m-series hardware, and second, this patch relies on changes made with the earlier patch to accomplish limiting the DMA buffer transfer. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 1a22c79c2817..929389b52572 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -3630,7 +3630,9 @@ static int ni_cdio_cmdtest(struct comedi_device *dev, err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0); err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); - err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); + err |= comedi_check_trigger_arg_max(&cmd->stop_arg, + s->async->prealloc_bufsz / + comedi_bytes_per_scan(s)); if (err) return 3; @@ -3707,6 +3709,7 @@ static int ni_cdo_inttrig(struct comedi_device *dev, static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + struct ni_private *devpriv = dev->private; const struct comedi_cmd *cmd = &s->async->cmd; unsigned cdo_mode_bits; int retval; @@ -3731,6 +3734,10 @@ static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (retval < 0) return retval; + ni_cmd_set_mite_transfer(devpriv->cdo_mite_ring, s, cmd, + s->async->prealloc_bufsz / + comedi_bytes_per_scan(s)); + s->async->inttrig = ni_cdo_inttrig; return 0; -- cgit v1.2.3 From b9491eab37e224b82d12c723e55c5b3b49396773 Mon Sep 17 00:00:00 2001 From: "Pablo G. Gallardo" Date: Thu, 4 Feb 2016 21:43:13 -0200 Subject: STAGING: COMEDI: Remove unnecessary typecast of c90 int constant This patch removes unnecessary typecast of c90 int constant. Signed-off-by: Pablo G. Gallardo Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index 83bd309d011b..f0d1b15f3c5a 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -516,7 +516,7 @@ struct comedi_bufinfo { #define UNIT_mA 1 #define UNIT_none 2 -#define COMEDI_MIN_SPEED ((unsigned int)0xffffffff) +#define COMEDI_MIN_SPEED 0xffffffffu /**********************************************************/ /* everything after this line is ALPHA */ -- cgit v1.2.3 From 0e05c0273587677160c30effff2ac12b090791a0 Mon Sep 17 00:00:00 2001 From: "Pablo G. Gallardo" Date: Thu, 4 Feb 2016 21:43:14 -0200 Subject: STAGING: COMEDI: Wrap line over 80 characters This patch wraps lines over 80 characters. Signed-off-by: Pablo G. Gallardo Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_pcmcia.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_pcmcia.h b/drivers/staging/comedi/comedi_pcmcia.h index 5d3db2b9b4a1..5a572c200a8b 100644 --- a/drivers/staging/comedi/comedi_pcmcia.h +++ b/drivers/staging/comedi/comedi_pcmcia.h @@ -39,7 +39,8 @@ void comedi_pcmcia_driver_unregister(struct comedi_driver *, struct pcmcia_driver *); /** - * module_comedi_pcmcia_driver() - Helper macro for registering a comedi PCMCIA driver + * module_comedi_pcmcia_driver() - Helper macro for registering a comedi + * PCMCIA driver * @__comedi_driver: comedi_driver struct * @__pcmcia_driver: pcmcia_driver struct * -- cgit v1.2.3 From e223da96bf16bee7f6c4c3aed1ade44a48aff0d3 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 16 Nov 2015 19:58:49 -0500 Subject: staging: drop kbuild workaround dummy module from top dir This is essentially a revert of 86f69fe9c069dd8608d238581eea259caa1dfc99 ("Staging: workaround build system bug"), but to call it a revert would imply it was wrong -- rather it seems more like it is just no longer required anymore. It doesn't list the full details of the failing use case, but the most obvious would appear to be a "make allnoconfig" that subsequently had set just CONFIG_STAGING=y in the .config file, to give: paul@builder:~/git/linux-head$ grep STAGING ../staging-allno/.config CONFIG_STAGING=y # CONFIG_STAGING_MEDIA is not set # CONFIG_STAGING_BOARD is not set paul@builder:~/git/linux-head$ After building this .config (on ARM, just to be different), we see that built-in.o is created, and the final vmlinux links OK: paul@builder:~/git/linux-head$ ls -l ../staging-allno/drivers/staging/built-in.o -rw-rw-r-- 1 paul paul 257 Nov 16 18:06 ../staging-allno/drivers/staging/built-in.o paul@builder:~/git/linux-head$ file ../staging-allno/drivers/staging/built-in.o ../staging-allno/drivers/staging/built-in.o: ELF 32-bit LSB relocatable, ARM, version 1, not stripped paul@builder:~/git/linux-head$ nm ../staging-allno/drivers/staging/built-in.o nm: ../staging-allno/drivers/staging/built-in.o: no symbols paul@builder:~/git/linux-head$ ls -l ../staging-allno/vmlinux -rwxrwxr-x 1 paul paul 1236326 Nov 16 18:07 ../staging-allno/vmlinux paul@builder:~/git/linux-head$ I also tested an "allmodconfig" and did not see any problems there either. Switching back to x86-64 and testing several things there didn't show any issues either. So it appears we do not need to carry the workaround in tree any longer. Cc: linux-kbuild@vger.kernel.org Signed-off-by: Paul Gortmaker Acked-by: Michal Marek Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Makefile | 3 --- drivers/staging/staging.c | 19 ------------------- 2 files changed, 22 deletions(-) delete mode 100644 drivers/staging/staging.c (limited to 'drivers') diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index dbab17e9d45c..b3920c224013 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -1,8 +1,5 @@ # Makefile for staging directory -# fix for build system bug... -obj-$(CONFIG_STAGING) += staging.o - obj-y += media/ obj-$(CONFIG_SLICOSS) += slicoss/ obj-$(CONFIG_PRISM2_USB) += wlan-ng/ diff --git a/drivers/staging/staging.c b/drivers/staging/staging.c deleted file mode 100644 index 233e589c0932..000000000000 --- a/drivers/staging/staging.c +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include -#include - -static int __init staging_init(void) -{ - return 0; -} - -static void __exit staging_exit(void) -{ -} - -module_init(staging_init); -module_exit(staging_exit); - -MODULE_AUTHOR("Greg Kroah-Hartman"); -MODULE_DESCRIPTION("Staging Core"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 14d88ec50ea668cc20efb622a13c664f056aee97 Mon Sep 17 00:00:00 2001 From: Dean Luick Date: Mon, 21 Dec 2015 20:31:53 -0500 Subject: staging/rdma/hfi1: set Gen3 half-swing for integrated devices Correctly set half-swing for integrated devices. A0 needs all fields set for CcePcieCtrl. B0 and later only need a few fields set. Reviewed-by: Stuart Summers Signed-off-by: Dean Luick Signed-off-by: Ira Weiny Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rdma/hfi1/chip_registers.h | 11 ++++ drivers/staging/rdma/hfi1/pcie.c | 82 ++++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rdma/hfi1/chip_registers.h b/drivers/staging/rdma/hfi1/chip_registers.h index 701e9e1012a6..014d7a609ea0 100644 --- a/drivers/staging/rdma/hfi1/chip_registers.h +++ b/drivers/staging/rdma/hfi1/chip_registers.h @@ -551,6 +551,17 @@ #define CCE_MSIX_TABLE_UPPER (CCE + 0x000000100008) #define CCE_MSIX_TABLE_UPPER_RESETCSR 0x0000000100000000ull #define CCE_MSIX_VEC_CLR_WITHOUT_INT (CCE + 0x000000110400) +#define CCE_PCIE_CTRL (CCE + 0x0000000000C0) +#define CCE_PCIE_CTRL_PCIE_LANE_BUNDLE_MASK 0x3ull +#define CCE_PCIE_CTRL_PCIE_LANE_BUNDLE_SHIFT 0 +#define CCE_PCIE_CTRL_PCIE_LANE_DELAY_MASK 0xFull +#define CCE_PCIE_CTRL_PCIE_LANE_DELAY_SHIFT 2 +#define CCE_PCIE_CTRL_XMT_MARGIN_OVERWRITE_ENABLE_SHIFT 8 +#define CCE_PCIE_CTRL_XMT_MARGIN_SHIFT 9 +#define CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_OVERWRITE_ENABLE_MASK 0x1ull +#define CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_OVERWRITE_ENABLE_SHIFT 12 +#define CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_MASK 0x7ull +#define CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_SHIFT 13 #define CCE_REVISION (CCE + 0x000000000000) #define CCE_REVISION2 (CCE + 0x000000000008) #define CCE_REVISION2_HFI_ID_MASK 0x1ull diff --git a/drivers/staging/rdma/hfi1/pcie.c b/drivers/staging/rdma/hfi1/pcie.c index 8317b07d722a..9917faff823c 100644 --- a/drivers/staging/rdma/hfi1/pcie.c +++ b/drivers/staging/rdma/hfi1/pcie.c @@ -866,6 +866,83 @@ static void arm_gasket_logic(struct hfi1_devdata *dd) read_csr(dd, ASIC_PCIE_SD_HOST_CMD); } +/* + * CCE_PCIE_CTRL long name helpers + * We redefine these shorter macros to use in the code while leaving + * chip_registers.h to be autogenerated from the hardware spec. + */ +#define LANE_BUNDLE_MASK CCE_PCIE_CTRL_PCIE_LANE_BUNDLE_MASK +#define LANE_BUNDLE_SHIFT CCE_PCIE_CTRL_PCIE_LANE_BUNDLE_SHIFT +#define LANE_DELAY_MASK CCE_PCIE_CTRL_PCIE_LANE_DELAY_MASK +#define LANE_DELAY_SHIFT CCE_PCIE_CTRL_PCIE_LANE_DELAY_SHIFT +#define MARGIN_OVERWRITE_ENABLE_SHIFT CCE_PCIE_CTRL_XMT_MARGIN_OVERWRITE_ENABLE_SHIFT +#define MARGIN_SHIFT CCE_PCIE_CTRL_XMT_MARGIN_SHIFT +#define MARGIN_G1_G2_OVERWRITE_MASK CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_OVERWRITE_ENABLE_MASK +#define MARGIN_G1_G2_OVERWRITE_SHIFT CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_OVERWRITE_ENABLE_SHIFT +#define MARGIN_GEN1_GEN2_MASK CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_MASK +#define MARGIN_GEN1_GEN2_SHIFT CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_SHIFT + + /* + * Write xmt_margin for full-swing (WFR-B) or half-swing (WFR-C). + */ +static void write_xmt_margin(struct hfi1_devdata *dd, const char *fname) +{ + u64 pcie_ctrl; + u64 xmt_margin; + u64 xmt_margin_oe; + u64 lane_delay; + u64 lane_bundle; + + pcie_ctrl = read_csr(dd, CCE_PCIE_CTRL); + + /* + * For Discrete, use full-swing. + * - PCIe TX defaults to full-swing. + * Leave this register as default. + * For Integrated, use half-swing + * - Copy xmt_margin and xmt_margin_oe + * from Gen1/Gen2 to Gen3. + */ + if (dd->pcidev->device == PCI_DEVICE_ID_INTEL1) { /* integrated */ + /* extract initial fields */ + xmt_margin = (pcie_ctrl >> MARGIN_GEN1_GEN2_SHIFT) + & MARGIN_GEN1_GEN2_MASK; + xmt_margin_oe = (pcie_ctrl >> MARGIN_G1_G2_OVERWRITE_SHIFT) + & MARGIN_G1_G2_OVERWRITE_MASK; + lane_delay = (pcie_ctrl >> LANE_DELAY_SHIFT) & LANE_DELAY_MASK; + lane_bundle = (pcie_ctrl >> LANE_BUNDLE_SHIFT) + & LANE_BUNDLE_MASK; + + /* + * For A0, EFUSE values are not set. Override with the + * correct values. + */ + if (is_ax(dd)) { + /* + * xmt_margin and OverwiteEnabel should be the + * same for Gen1/Gen2 and Gen3 + */ + xmt_margin = 0x5; + xmt_margin_oe = 0x1; + lane_delay = 0xF; /* Delay 240ns. */ + lane_bundle = 0x0; /* Set to 1 lane. */ + } + + /* overwrite existing values */ + pcie_ctrl = (xmt_margin << MARGIN_GEN1_GEN2_SHIFT) + | (xmt_margin_oe << MARGIN_G1_G2_OVERWRITE_SHIFT) + | (xmt_margin << MARGIN_SHIFT) + | (xmt_margin_oe << MARGIN_OVERWRITE_ENABLE_SHIFT) + | (lane_delay << LANE_DELAY_SHIFT) + | (lane_bundle << LANE_BUNDLE_SHIFT); + + write_csr(dd, CCE_PCIE_CTRL, pcie_ctrl); + } + + dd_dev_dbg(dd, "%s: program XMT margin, CcePcieCtrl 0x%llx\n", + fname, pcie_ctrl); +} + /* * Do all the steps needed to transition the PCIe link to Gen3 speed. */ @@ -1064,11 +1141,8 @@ retry: /* * step 5d: program XMT margin - * Right now, leave the default alone. To change, do a - * read-modify-write of: - * CcePcieCtrl.XmtMargin - * CcePcieCtrl.XmitMarginOverwriteEnable */ + write_xmt_margin(dd, __func__); /* step 5e: disable active state power management (ASPM) */ dd_dev_info(dd, "%s: clearing ASPM\n", __func__); -- cgit v1.2.3 From 568dcc883abcbb5ef7daf8ddcfea1b533324b4a6 Mon Sep 17 00:00:00 2001 From: Ira Weiny Date: Mon, 21 Dec 2015 20:31:52 -0500 Subject: staging/rdma/hfi1: add dd_dev_dbg To be used in future patches add dd_dev_dbg. dd_* functions properly decode the hfi1_devdata structure used throughout the driver Signed-off-by: Ira Weiny Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rdma/hfi1/hfi.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/rdma/hfi1/hfi.h b/drivers/staging/rdma/hfi1/hfi.h index 2611bb2e764d..f14ed1e4001b 100644 --- a/drivers/staging/rdma/hfi1/hfi.h +++ b/drivers/staging/rdma/hfi1/hfi.h @@ -1794,6 +1794,10 @@ static inline u64 hfi1_pkt_base_sdma_integrity(struct hfi1_devdata *dd) dev_info(&(dd)->pcidev->dev, "%s: " fmt, \ get_unit_name((dd)->unit), ##__VA_ARGS__) +#define dd_dev_dbg(dd, fmt, ...) \ + dev_dbg(&(dd)->pcidev->dev, "%s: " fmt, \ + get_unit_name((dd)->unit), ##__VA_ARGS__) + #define hfi1_dev_porterr(dd, port, fmt, ...) \ dev_err(&(dd)->pcidev->dev, "%s: IB%u:%u " fmt, \ get_unit_name((dd)->unit), (dd)->unit, (port), \ -- cgit v1.2.3 From 480fd015ec5c9109c55e39057f3df60278851432 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 23 Dec 2015 21:42:57 +0100 Subject: staging: rdma: hfi1: diag: constify hfi1_filter_array structure The hfi1_filter_array structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Acked-by: Mike Marciniszyn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rdma/hfi1/diag.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rdma/hfi1/diag.c b/drivers/staging/rdma/hfi1/diag.c index 0c8831705664..e41159fe6889 100644 --- a/drivers/staging/rdma/hfi1/diag.c +++ b/drivers/staging/rdma/hfi1/diag.c @@ -257,7 +257,7 @@ static int hfi1_filter_ib_service_level(void *ibhdr, void *packet_data, static int hfi1_filter_ib_pkey(void *ibhdr, void *packet_data, void *value); static int hfi1_filter_direction(void *ibhdr, void *packet_data, void *value); -static struct hfi1_filter_array hfi1_filters[] = { +static const struct hfi1_filter_array hfi1_filters[] = { { hfi1_filter_lid }, { hfi1_filter_dlid }, { hfi1_filter_mad_mgmt_class }, -- cgit v1.2.3 From 80e4898e82e39618397d66ef5cc49529555c17ce Mon Sep 17 00:00:00 2001 From: Edward Mascarenhas Date: Mon, 21 Dec 2015 21:57:44 -0500 Subject: staging/rdma/hfi1: Clean up comments Clean up comments by deleting numbering and terms internal to Intel. The information on the actual bugs is not deleted. Reviewed-by: Mike Marciniszyn Signed-off-by: Edward Mascarenhas Signed-off-by: Jubin John Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rdma/hfi1/chip.c | 1 - drivers/staging/rdma/hfi1/driver.c | 2 +- drivers/staging/rdma/hfi1/hfi.h | 4 ++-- drivers/staging/rdma/hfi1/pcie.c | 2 +- drivers/staging/rdma/hfi1/ud.c | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rdma/hfi1/chip.c b/drivers/staging/rdma/hfi1/chip.c index bbe5ad85cec0..02ba78ff5ca0 100644 --- a/drivers/staging/rdma/hfi1/chip.c +++ b/drivers/staging/rdma/hfi1/chip.c @@ -13537,7 +13537,6 @@ int hfi1_set_ctxt_jkey(struct hfi1_devdata *dd, unsigned ctxt, u16 jkey) write_kctxt_csr(dd, sctxt, SEND_CTXT_CHECK_JOB_KEY, reg); /* * Enable send-side J_KEY integrity check, unless this is A0 h/w - * (due to A0 erratum). */ if (!is_ax(dd)) { reg = read_kctxt_csr(dd, sctxt, SEND_CTXT_CHECK_ENABLE); diff --git a/drivers/staging/rdma/hfi1/driver.c b/drivers/staging/rdma/hfi1/driver.c index 8485de1fce08..321852060213 100644 --- a/drivers/staging/rdma/hfi1/driver.c +++ b/drivers/staging/rdma/hfi1/driver.c @@ -368,7 +368,7 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd, if (opcode == IB_OPCODE_CNP) { /* * Only in pre-B0 h/w is the CNP_OPCODE handled - * via this code path (errata 291394). + * via this code path. */ struct hfi1_qp *qp = NULL; u32 lqpn, rqpn; diff --git a/drivers/staging/rdma/hfi1/hfi.h b/drivers/staging/rdma/hfi1/hfi.h index f14ed1e4001b..d4826a9ab8d3 100644 --- a/drivers/staging/rdma/hfi1/hfi.h +++ b/drivers/staging/rdma/hfi1/hfi.h @@ -1730,7 +1730,7 @@ static inline u64 hfi1_pkt_default_send_ctxt_mask(struct hfi1_devdata *dd, base_sc_integrity |= HFI1_PKT_KERNEL_SC_INTEGRITY; if (is_ax(dd)) - /* turn off send-side job key checks - A0 erratum */ + /* turn off send-side job key checks - A0 */ return base_sc_integrity & ~SEND_CTXT_CHECK_ENABLE_CHECK_JOB_KEY_SMASK; return base_sc_integrity; @@ -1757,7 +1757,7 @@ static inline u64 hfi1_pkt_base_sdma_integrity(struct hfi1_devdata *dd) | SEND_DMA_CHECK_ENABLE_CHECK_ENABLE_SMASK; if (is_ax(dd)) - /* turn off send-side job key checks - A0 erratum */ + /* turn off send-side job key checks - A0 */ return base_sdma_integrity & ~SEND_DMA_CHECK_ENABLE_CHECK_JOB_KEY_SMASK; return base_sdma_integrity; diff --git a/drivers/staging/rdma/hfi1/pcie.c b/drivers/staging/rdma/hfi1/pcie.c index 9917faff823c..b2f553d86042 100644 --- a/drivers/staging/rdma/hfi1/pcie.c +++ b/drivers/staging/rdma/hfi1/pcie.c @@ -1063,7 +1063,7 @@ retry: * PcieCfgRegPl100 - Gen3 Control * * turn off PcieCfgRegPl100.Gen3ZRxDcNonCompl - * turn on PcieCfgRegPl100.EqEieosCnt (erratum) + * turn on PcieCfgRegPl100.EqEieosCnt * Everything else zero. */ reg32 = PCIE_CFG_REG_PL100_EQ_EIEOS_CNT_SMASK; diff --git a/drivers/staging/rdma/hfi1/ud.c b/drivers/staging/rdma/hfi1/ud.c index bd1b402c1e14..25e6053c38db 100644 --- a/drivers/staging/rdma/hfi1/ud.c +++ b/drivers/staging/rdma/hfi1/ud.c @@ -671,7 +671,7 @@ void hfi1_ud_rcv(struct hfi1_packet *packet) if (unlikely(bth1 & HFI1_BECN_SMASK)) { /* * In pre-B0 h/w the CNP_OPCODE is handled via an - * error path (errata 291394). + * error path. */ struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); u32 lqpn = be32_to_cpu(ohdr->bth[1]) & HFI1_QPN_MASK; -- cgit v1.2.3 From d9d3e025c0f68a1ec99ee13209d31d2a766ac56f Mon Sep 17 00:00:00 2001 From: Ira Weiny Date: Mon, 21 Dec 2015 21:57:45 -0500 Subject: staging/rdma/hfi1: Fix Xmit Wait calculation Total XMIT wait needs to sum the xmit wait values of all the VLs not just those requested in the query. Also, make the algorithm used for both PortStatus and PortDataCounters the same. Reviewed-by: Arthur Kepner Reviewed-by: Breyer, Scott J Signed-off-by: Ira Weiny Signed-off-by: Jubin John Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rdma/hfi1/mad.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rdma/hfi1/mad.c b/drivers/staging/rdma/hfi1/mad.c index 4f5dbd14b5de..bee1c0e5c2e3 100644 --- a/drivers/staging/rdma/hfi1/mad.c +++ b/drivers/staging/rdma/hfi1/mad.c @@ -2279,17 +2279,23 @@ static void a0_portstatus(struct hfi1_pportdata *ppd, { if (!is_bx(ppd->dd)) { unsigned long vl; - u64 max_vl_xmit_wait = 0, tmp; + u64 sum_vl_xmit_wait = 0; u32 vl_all_mask = VL_MASK_ALL; for_each_set_bit(vl, (unsigned long *)&(vl_all_mask), 8 * sizeof(vl_all_mask)) { - tmp = read_port_cntr(ppd, C_TX_WAIT_VL, - idx_from_vl(vl)); - if (tmp > max_vl_xmit_wait) - max_vl_xmit_wait = tmp; + u64 tmp = sum_vl_xmit_wait + + read_port_cntr(ppd, C_TX_WAIT_VL, + idx_from_vl(vl)); + if (tmp < sum_vl_xmit_wait) { + /* we wrapped */ + sum_vl_xmit_wait = (u64)~0; + break; + } + sum_vl_xmit_wait = tmp; } - rsp->port_xmit_wait = cpu_to_be64(max_vl_xmit_wait); + if (be64_to_cpu(rsp->port_xmit_wait) > sum_vl_xmit_wait) + rsp->port_xmit_wait = cpu_to_be64(sum_vl_xmit_wait); } } @@ -2491,18 +2497,19 @@ static u64 get_error_counter_summary(struct ib_device *ibdev, u8 port, return error_counter_summary; } -static void a0_datacounters(struct hfi1_devdata *dd, struct _port_dctrs *rsp, +static void a0_datacounters(struct hfi1_pportdata *ppd, struct _port_dctrs *rsp, u32 vl_select_mask) { - if (!is_bx(dd)) { + if (!is_bx(ppd->dd)) { unsigned long vl; - int vfi = 0; u64 sum_vl_xmit_wait = 0; + u32 vl_all_mask = VL_MASK_ALL; - for_each_set_bit(vl, (unsigned long *)&(vl_select_mask), - 8 * sizeof(vl_select_mask)) { + for_each_set_bit(vl, (unsigned long *)&(vl_all_mask), + 8 * sizeof(vl_all_mask)) { u64 tmp = sum_vl_xmit_wait + - be64_to_cpu(rsp->vls[vfi++].port_vl_xmit_wait); + read_port_cntr(ppd, C_TX_WAIT_VL, + idx_from_vl(vl)); if (tmp < sum_vl_xmit_wait) { /* we wrapped */ sum_vl_xmit_wait = (u64) ~0; @@ -2665,7 +2672,7 @@ static int pma_get_opa_datacounters(struct opa_pma_mad *pmp, vfi++; } - a0_datacounters(dd, rsp, vl_select_mask); + a0_datacounters(ppd, rsp, vl_select_mask); if (resp_len) *resp_len += response_data_size; -- cgit v1.2.3 From 0fbc7c505680ca6efe2486afb34866602781c980 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 19:59:49 +0200 Subject: staging: sm750fb: disable PCI device if lynxfb_pci_probe fails In case of error during lynxfb_pci_probe, the function returned without calling pci_disable_device. Fix it by adding pci_disable_device on the error cleanup path. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index c78421b5b0e7..c80b11c387ad 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1132,6 +1132,7 @@ err_info0_alloc: err_map: kfree(sm750_dev); err_share: + pci_disable_device(pdev); err_enable: return -ENODEV; } -- cgit v1.2.3 From baf24530a48c991144aaf82007d4f5e21eb47aa8 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 19:59:50 +0200 Subject: staging: sm750fb: lynxfb_pci_probe: return actual errors The lynxfb_pci_probe always returned -ENODEV in case of error. Modify it so that actual error code will be propogated to the caller. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index c80b11c387ad..7eb386881964 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1006,18 +1006,17 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, struct fb_info *info[] = {NULL, NULL}; struct sm750_dev *sm750_dev = NULL; int fbidx; + int err; /* enable device */ - if (pci_enable_device(pdev)) { - pr_err("can not enable device.\n"); - goto err_enable; - } + err = pci_enable_device(pdev); + if (err) + return err; + err = -ENOMEM; sm750_dev = kzalloc(sizeof(*sm750_dev), GFP_KERNEL); - if (!sm750_dev) { - pr_err("Could not allocate memory for share.\n"); - goto err_share; - } + if (!sm750_dev) + goto disable_pci; sm750_dev->fbinfo[0] = sm750_dev->fbinfo[1] = NULL; sm750_dev->devid = pdev->device; @@ -1051,10 +1050,9 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, sm750fb_setup(sm750_dev, g_settings); /* call chip specific mmap routine */ - if (hw_sm750_map(sm750_dev, pdev)) { - pr_err("Memory map failed\n"); - goto err_map; - } + err = hw_sm750_map(sm750_dev, pdev); + if (err) + goto free_sm750_dev; if (!sm750_dev->mtrr_off) sm750_dev->mtrr.vram = arch_phys_wc_add(sm750_dev->vidmem_start, @@ -1073,6 +1071,7 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, /* allocate frame buffer info structor according to g_dualview */ fbidx = 0; ALLOC_FB: + err = -ENOMEM; info[fbidx] = framebuffer_alloc(sizeof(struct lynxfb_par), &pdev->dev); if (!info[fbidx]) { pr_err("Could not allocate framebuffer #%d.\n", fbidx); @@ -1082,7 +1081,6 @@ ALLOC_FB: goto err_info1_alloc; } else { struct lynxfb_par *par; - int errno; pr_info("framebuffer #%d alloc okay\n", fbidx); sm750_dev->fbinfo[fbidx] = info[fbidx]; @@ -1100,11 +1098,11 @@ ALLOC_FB: /* register frame buffer */ pr_info("Ready to register framebuffer #%d.\n", fbidx); - errno = register_framebuffer(info[fbidx]); - if (errno < 0) { + err = register_framebuffer(info[fbidx]); + if (err < 0) { pr_err("Failed to register fb_info #%d. err %d\n", fbidx, - errno); + err); if (fbidx == 0) goto err_register0; else @@ -1129,12 +1127,11 @@ err_register0: err_info0_set: framebuffer_release(info[0]); err_info0_alloc: -err_map: +free_sm750_dev: kfree(sm750_dev); -err_share: +disable_pci: pci_disable_device(pdev); -err_enable: - return -ENODEV; + return err; } static void lynxfb_pci_remove(struct pci_dev *pdev) -- cgit v1.2.3 From 473baa2df6833c53c74f13eb812de5c57287ffd4 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 19:59:51 +0200 Subject: staging: sm750fb: lynxfb_pci_remove: remove unused variable The par variable in lynxfb_pci_remove is only assigned a value and never used afterwards. Remove it. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index 7eb386881964..6ed4478ed65a 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1138,7 +1138,6 @@ static void lynxfb_pci_remove(struct pci_dev *pdev) { struct fb_info *info; struct sm750_dev *sm750_dev; - struct lynxfb_par *par; int cnt; cnt = 2; @@ -1148,7 +1147,6 @@ static void lynxfb_pci_remove(struct pci_dev *pdev) info = sm750_dev->fbinfo[cnt]; if (!info) continue; - par = info->par; unregister_framebuffer(info); /* release frame buffer */ -- cgit v1.2.3 From a3f92cc94c6126d243d1cfc4f198e101f89bd46b Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 19:59:52 +0200 Subject: staging: sm750fb: replace dual member of sm750_dev with fb_count Will be used in futher refactoring of driver _probe and _remove methods. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 24 +++++++++++++----------- drivers/staging/sm750fb/sm750.h | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index 6ed4478ed65a..1b3ab04d8f06 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -189,7 +189,7 @@ static void lynxfb_ops_fillrect(struct fb_info *info, * If not use spin_lock,system will die if user load driver * and immediately unload driver frequently (dual) */ - if (sm750_dev->dual) + if (sm750_dev->fb_count > 1) spin_lock(&sm750_dev->slock); sm750_dev->accel.de_fillrect(&sm750_dev->accel, @@ -197,7 +197,7 @@ static void lynxfb_ops_fillrect(struct fb_info *info, region->dx, region->dy, region->width, region->height, color, rop); - if (sm750_dev->dual) + if (sm750_dev->fb_count > 1) spin_unlock(&sm750_dev->slock); } @@ -223,7 +223,7 @@ static void lynxfb_ops_copyarea(struct fb_info *info, * If not use spin_lock, system will die if user load driver * and immediately unload driver frequently (dual) */ - if (sm750_dev->dual) + if (sm750_dev->fb_count > 1) spin_lock(&sm750_dev->slock); sm750_dev->accel.de_copyarea(&sm750_dev->accel, @@ -231,7 +231,7 @@ static void lynxfb_ops_copyarea(struct fb_info *info, base, pitch, Bpp, region->dx, region->dy, region->width, region->height, HW_ROP2_COPY); - if (sm750_dev->dual) + if (sm750_dev->fb_count > 1) spin_unlock(&sm750_dev->slock); } @@ -272,7 +272,7 @@ static void lynxfb_ops_imageblit(struct fb_info *info, * If not use spin_lock, system will die if user load driver * and immediately unload driver frequently (dual) */ - if (sm750_dev->dual) + if (sm750_dev->fb_count > 1) spin_lock(&sm750_dev->slock); sm750_dev->accel.de_imageblit(&sm750_dev->accel, @@ -281,7 +281,7 @@ static void lynxfb_ops_imageblit(struct fb_info *info, image->dx, image->dy, image->width, image->height, fgcol, bgcol, HW_ROP2_COPY); - if (sm750_dev->dual) + if (sm750_dev->fb_count > 1) spin_unlock(&sm750_dev->slock); } @@ -650,8 +650,10 @@ static int sm750fb_set_drv(struct lynxfb_par *par) output = &par->output; crtc = &par->crtc; - crtc->vidmem_size = (sm750_dev->dual) ? sm750_dev->vidmem_size >> 1 : - sm750_dev->vidmem_size; + crtc->vidmem_size = sm750_dev->vidmem_size; + if (sm750_dev->fb_count > 1) + crtc->vidmem_size >>= 1; + /* setup crtc and output member */ sm750_dev->hwCursor = g_hwcursor; @@ -981,7 +983,7 @@ static void sm750fb_setup(struct sm750_dev *sm750_dev, char *src) NO_PARAM: if (sm750_dev->revid != SM750LE_REVISION_ID) { - if (sm750_dev->dual) { + if (sm750_dev->fb_count > 1) { if (swap) sm750_dev->dataflow = sm750_dual_swap; else @@ -1027,7 +1029,6 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, sm750_dev->mtrr_off = g_nomtrr; sm750_dev->mtrr.vram = 0; sm750_dev->accel_off = g_noaccel; - sm750_dev->dual = g_dualview; spin_lock_init(&sm750_dev->slock); if (!sm750_dev->accel_off) { @@ -1113,7 +1114,8 @@ ALLOC_FB: /* no dual view by far */ fbidx++; - if (sm750_dev->dual && fbidx < 2) + sm750_dev->fb_count++; + if (g_dualview && fbidx < 2) goto ALLOC_FB; return 0; diff --git a/drivers/staging/sm750fb/sm750.h b/drivers/staging/sm750fb/sm750.h index b0a93cdc7292..fddffac6930f 100644 --- a/drivers/staging/sm750fb/sm750.h +++ b/drivers/staging/sm750fb/sm750.h @@ -79,7 +79,7 @@ struct sm750_dev { struct fb_info *fbinfo[2]; struct lynx_accel accel; int accel_off; - int dual; + int fb_count; int mtrr_off; struct{ int vram; -- cgit v1.2.3 From 9324f9193bc3ba7a07e70ac6e01b3257fb17f390 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 19:59:53 +0200 Subject: staging: sm750fb: introduce sm750fb_frambuffer_release Use a function to unregister framebuffer info and release its resources. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index 1b3ab04d8f06..88a640507d7f 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1002,6 +1002,18 @@ NO_PARAM: } } +static void sm750fb_frambuffer_release(struct sm750_dev *sm750_dev) +{ + struct fb_info *fb_info; + + while (sm750_dev->fb_count) { + fb_info = sm750_dev->fbinfo[sm750_dev->fb_count - 1]; + unregister_framebuffer(fb_info); + framebuffer_release(fb_info); + sm750_dev->fb_count--; + } +} + static int lynxfb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -1138,22 +1150,11 @@ disable_pci: static void lynxfb_pci_remove(struct pci_dev *pdev) { - struct fb_info *info; struct sm750_dev *sm750_dev; - int cnt; - cnt = 2; sm750_dev = pci_get_drvdata(pdev); - while (cnt-- > 0) { - info = sm750_dev->fbinfo[cnt]; - if (!info) - continue; - - unregister_framebuffer(info); - /* release frame buffer */ - framebuffer_release(info); - } + sm750fb_frambuffer_release(sm750_dev); arch_phys_wc_del(sm750_dev->mtrr.vram); iounmap(sm750_dev->pvReg); -- cgit v1.2.3 From a50bc32d325831f2365333298c2808adac18a219 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 19:59:54 +0200 Subject: staging: sm750fb: introduce sm750fb_frambuffer_alloc Split framebuffer allocation and registration into a dedicated function to simplify lynxfb_pci_probe Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 98 +++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index 88a640507d7f..c33c7ffb8557 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1014,11 +1014,43 @@ static void sm750fb_frambuffer_release(struct sm750_dev *sm750_dev) } } +static int sm750fb_frambuffer_alloc(struct sm750_dev *sm750_dev, int fbidx) +{ + struct fb_info *fb_info; + struct lynxfb_par *par; + int err; + + fb_info = framebuffer_alloc(sizeof(struct lynxfb_par), + &sm750_dev->pdev->dev); + if (!fb_info) + return -ENOMEM; + + sm750_dev->fbinfo[fbidx] = fb_info; + par = fb_info->par; + par->dev = sm750_dev; + + err = lynxfb_set_fbinfo(fb_info, fbidx); + if (err) + goto release_fb; + + err = register_framebuffer(fb_info); + if (err < 0) + goto release_fb; + + sm750_dev->fb_count++; + + return 0; + +release_fb: + framebuffer_release(fb_info); + return err; +} + static int lynxfb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct fb_info *info[] = {NULL, NULL}; struct sm750_dev *sm750_dev = NULL; + int max_fb; int fbidx; int err; @@ -1081,66 +1113,18 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, /* call chipInit routine */ hw_sm750_inithw(sm750_dev, pdev); - /* allocate frame buffer info structor according to g_dualview */ - fbidx = 0; -ALLOC_FB: - err = -ENOMEM; - info[fbidx] = framebuffer_alloc(sizeof(struct lynxfb_par), &pdev->dev); - if (!info[fbidx]) { - pr_err("Could not allocate framebuffer #%d.\n", fbidx); - if (fbidx == 0) - goto err_info0_alloc; - else - goto err_info1_alloc; - } else { - struct lynxfb_par *par; - - pr_info("framebuffer #%d alloc okay\n", fbidx); - sm750_dev->fbinfo[fbidx] = info[fbidx]; - par = info[fbidx]->par; - par->dev = sm750_dev; - - /* set fb_info structure */ - if (lynxfb_set_fbinfo(info[fbidx], fbidx)) { - pr_err("Failed to initial fb_info #%d.\n", fbidx); - if (fbidx == 0) - goto err_info0_set; - else - goto err_info1_set; - } - - /* register frame buffer */ - pr_info("Ready to register framebuffer #%d.\n", fbidx); - err = register_framebuffer(info[fbidx]); - if (err < 0) { - pr_err("Failed to register fb_info #%d. err %d\n", - fbidx, - err); - if (fbidx == 0) - goto err_register0; - else - goto err_register1; - } - pr_info("Accomplished register framebuffer #%d.\n", fbidx); + /* allocate frame buffer info structures according to g_dualview */ + max_fb = g_dualview ? 2 : 1; + for (fbidx = 0; fbidx < max_fb; fbidx++) { + err = sm750fb_frambuffer_alloc(sm750_dev, fbidx); + if (err) + goto release_fb; } - /* no dual view by far */ - fbidx++; - sm750_dev->fb_count++; - if (g_dualview && fbidx < 2) - goto ALLOC_FB; - return 0; -err_register1: -err_info1_set: - framebuffer_release(info[1]); -err_info1_alloc: - unregister_framebuffer(info[0]); -err_register0: -err_info0_set: - framebuffer_release(info[0]); -err_info0_alloc: +release_fb: + sm750fb_frambuffer_release(sm750_dev); free_sm750_dev: kfree(sm750_dev); disable_pci: -- cgit v1.2.3 From 61da1a12d80f02c42a5f8d8865da94751e077735 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 19:59:55 +0200 Subject: staging: sm750fb: lynxfb_pci_probe: remove some pr_info Several pr_info statements in lynxfb_pci_probe seem like debug leftovers and may be removed. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index c33c7ffb8557..2ae2a522136f 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1067,8 +1067,6 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, sm750_dev->fbinfo[0] = sm750_dev->fbinfo[1] = NULL; sm750_dev->devid = pdev->device; sm750_dev->revid = pdev->revision; - - pr_info("share->revid = %02x\n", sm750_dev->revid); sm750_dev->pdev = pdev; sm750_dev->mtrr_off = g_nomtrr; sm750_dev->mtrr.vram = 0; @@ -1086,9 +1084,6 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, sm750_dev->accel.de_fillrect = hw_fillrect; sm750_dev->accel.de_copyarea = hw_copyarea; sm750_dev->accel.de_imageblit = hw_imageblit; - pr_info("enable 2d acceleration\n"); - } else { - pr_info("disable 2d acceleration\n"); } /* call chip specific setup routine */ @@ -1105,9 +1100,6 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, memset_io(sm750_dev->pvMem, 0, sm750_dev->vidmem_size); - pr_info("sm%3x mmio address = %p\n", sm750_dev->devid, - sm750_dev->pvReg); - pci_set_drvdata(pdev, sm750_dev); /* call chipInit routine */ -- cgit v1.2.3 From 9eced7438d864c33e6de781bb47f0f21a784c8c5 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:14 +0200 Subject: staging: sm750fb: hw_sm750(le)_deWait: rename dwVal to val Remove HungarianCamelCase notation Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750_hw.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 41822c6c0380..f9908d942c63 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -495,11 +495,11 @@ int hw_sm750le_deWait(void) int i = 0x10000000; while (i--) { - unsigned int dwVal = PEEK32(DE_STATE2); + unsigned int val = PEEK32(DE_STATE2); - if ((FIELD_GET(dwVal, DE_STATE2, DE_STATUS) == DE_STATE2_DE_STATUS_IDLE) && - (FIELD_GET(dwVal, DE_STATE2, DE_FIFO) == DE_STATE2_DE_FIFO_EMPTY) && - (FIELD_GET(dwVal, DE_STATE2, DE_MEM_FIFO) == DE_STATE2_DE_MEM_FIFO_EMPTY)) { + if ((FIELD_GET(val, DE_STATE2, DE_STATUS) == DE_STATE2_DE_STATUS_IDLE) && + (FIELD_GET(val, DE_STATE2, DE_FIFO) == DE_STATE2_DE_FIFO_EMPTY) && + (FIELD_GET(val, DE_STATE2, DE_MEM_FIFO) == DE_STATE2_DE_MEM_FIFO_EMPTY)) { return 0; } } @@ -513,11 +513,11 @@ int hw_sm750_deWait(void) int i = 0x10000000; while (i--) { - unsigned int dwVal = PEEK32(SYSTEM_CTRL); + unsigned int val = PEEK32(SYSTEM_CTRL); - if ((FIELD_GET(dwVal, SYSTEM_CTRL, DE_STATUS) == SYSTEM_CTRL_DE_STATUS_IDLE) && - (FIELD_GET(dwVal, SYSTEM_CTRL, DE_FIFO) == SYSTEM_CTRL_DE_FIFO_EMPTY) && - (FIELD_GET(dwVal, SYSTEM_CTRL, DE_MEM_FIFO) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) { + if ((FIELD_GET(val, SYSTEM_CTRL, DE_STATUS) == SYSTEM_CTRL_DE_STATUS_IDLE) && + (FIELD_GET(val, SYSTEM_CTRL, DE_FIFO) == SYSTEM_CTRL_DE_FIFO_EMPTY) && + (FIELD_GET(val, SYSTEM_CTRL, DE_MEM_FIFO) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) { return 0; } } -- cgit v1.2.3 From c808d6ce4a2a2d923fbf29e054ff08c0141703c0 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:15 +0200 Subject: staging: sm750fb: use BIT macro for DE_STATE1 single-bit field Replace complex definition of DE_STATE1 field and usage of FIELD_SET with BIT() macro and open-coded register value modifications Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 4 +--- drivers/staging/sm750fb/sm750_hw.c | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 16a01c25442c..7bbe53a12808 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -3,9 +3,7 @@ /* New register for SM750LE */ #define DE_STATE1 0x100054 -#define DE_STATE1_DE_ABORT 0:0 -#define DE_STATE1_DE_ABORT_OFF 0 -#define DE_STATE1_DE_ABORT_ON 1 +#define DE_STATE1_DE_ABORT BIT(0) #define DE_STATE2 0x100058 #define DE_STATE2_DE_FIFO 3:3 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index f9908d942c63..5754af5b9ddf 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -468,11 +468,11 @@ void hw_sm750_initAccel(struct sm750_dev *sm750_dev) if (getChipType() == SM750LE) { reg = PEEK32(DE_STATE1); - reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, ON); + reg |= DE_STATE1_DE_ABORT; POKE32(DE_STATE1, reg); reg = PEEK32(DE_STATE1); - reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, OFF); + reg &= ~DE_STATE1_DE_ABORT; POKE32(DE_STATE1, reg); } else { -- cgit v1.2.3 From ae6061dbfcb2f49cd717fb235b5d0633e99f2596 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:16 +0200 Subject: staging: sm750fb: use BIT macro for DE_STATE2 single-bit fields Replace complex definition of DE_STATE1 fields and usage of FIELD_GET with BIT() macro and open-coded register value modifications Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 12 +++--------- drivers/staging/sm750fb/sm750_hw.c | 8 ++++---- 2 files changed, 7 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 7bbe53a12808..db13bdf6a1dc 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -6,15 +6,9 @@ #define DE_STATE1_DE_ABORT BIT(0) #define DE_STATE2 0x100058 -#define DE_STATE2_DE_FIFO 3:3 -#define DE_STATE2_DE_FIFO_NOTEMPTY 0 -#define DE_STATE2_DE_FIFO_EMPTY 1 -#define DE_STATE2_DE_STATUS 2:2 -#define DE_STATE2_DE_STATUS_IDLE 0 -#define DE_STATE2_DE_STATUS_BUSY 1 -#define DE_STATE2_DE_MEM_FIFO 1:1 -#define DE_STATE2_DE_MEM_FIFO_NOTEMPTY 0 -#define DE_STATE2_DE_MEM_FIFO_EMPTY 1 +#define DE_STATE2_DE_FIFO_EMPTY BIT(3) +#define DE_STATE2_DE_STATUS_BUSY BIT(2) +#define DE_STATE2_DE_MEM_FIFO_EMPTY BIT(1) #define DE_STATE2_DE_RESERVED 0:0 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 5754af5b9ddf..425bec886078 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -493,15 +493,15 @@ void hw_sm750_initAccel(struct sm750_dev *sm750_dev) int hw_sm750le_deWait(void) { int i = 0x10000000; + unsigned int mask = DE_STATE2_DE_STATUS_BUSY | DE_STATE2_DE_FIFO_EMPTY | + DE_STATE2_DE_MEM_FIFO_EMPTY; while (i--) { unsigned int val = PEEK32(DE_STATE2); - if ((FIELD_GET(val, DE_STATE2, DE_STATUS) == DE_STATE2_DE_STATUS_IDLE) && - (FIELD_GET(val, DE_STATE2, DE_FIFO) == DE_STATE2_DE_FIFO_EMPTY) && - (FIELD_GET(val, DE_STATE2, DE_MEM_FIFO) == DE_STATE2_DE_MEM_FIFO_EMPTY)) { + if ((val & mask) == + (DE_STATE2_DE_FIFO_EMPTY | DE_STATE2_DE_MEM_FIFO_EMPTY)) return 0; - } } /* timeout error */ return -1; -- cgit v1.2.3 From 1c3ad306884300a07822e91ac8e8dd8650c863a1 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:17 +0200 Subject: staging: sm750fb: remove unused DE_STATE2_DE_RESERVED Definition of reserved fields in a register is not interesting Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index db13bdf6a1dc..38ebe95338db 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -9,9 +9,6 @@ #define DE_STATE2_DE_FIFO_EMPTY BIT(3) #define DE_STATE2_DE_STATUS_BUSY BIT(2) #define DE_STATE2_DE_MEM_FIFO_EMPTY BIT(1) -#define DE_STATE2_DE_RESERVED 0:0 - - #define SYSTEM_CTRL 0x000000 #define SYSTEM_CTRL_DPMS 31:30 -- cgit v1.2.3 From 410c756d41ef57fd0252de652c635f247cc16474 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:18 +0200 Subject: staging: sm750fb: use BIT macro for SYSTEM_CTRL single-bit fields Replace complex definition of SYSTEM_CTRL fields and usage of FIELD_GET/SET with BIT() macro and open-coded register value modifications Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_display.c | 24 ++++------ drivers/staging/sm750fb/ddk750_reg.h | 76 ++++++++------------------------ drivers/staging/sm750fb/sm750_hw.c | 15 ++++--- 3 files changed, 35 insertions(+), 80 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index 84f6e8b8c0e2..1a29ae037ee3 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -136,17 +136,13 @@ static void waitNextVerticalSync(int ctrl, int delay) while (delay-- > 0) { /* Wait for end of vsync. */ do { - status = FIELD_GET(PEEK32(SYSTEM_CTRL), - SYSTEM_CTRL, - PANEL_VSYNC); - } while (status == SYSTEM_CTRL_PANEL_VSYNC_ACTIVE); + status = PEEK32(SYSTEM_CTRL); + } while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE); /* Wait for start of vsync. */ do { - status = FIELD_GET(PEEK32(SYSTEM_CTRL), - SYSTEM_CTRL, - PANEL_VSYNC); - } while (status == SYSTEM_CTRL_PANEL_VSYNC_INACTIVE); + status = PEEK32(SYSTEM_CTRL); + } while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE)); } } else { @@ -163,17 +159,13 @@ static void waitNextVerticalSync(int ctrl, int delay) while (delay-- > 0) { /* Wait for end of vsync. */ do { - status = FIELD_GET(PEEK32(SYSTEM_CTRL), - SYSTEM_CTRL, - CRT_VSYNC); - } while (status == SYSTEM_CTRL_CRT_VSYNC_ACTIVE); + status = PEEK32(SYSTEM_CTRL); + } while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE); /* Wait for start of vsync. */ do { - status = FIELD_GET(PEEK32(SYSTEM_CTRL), - SYSTEM_CTRL, - CRT_VSYNC); - } while (status == SYSTEM_CTRL_CRT_VSYNC_INACTIVE); + status = PEEK32(SYSTEM_CTRL); + } while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE)); } } } diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 38ebe95338db..351a1dc67900 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -16,68 +16,30 @@ #define SYSTEM_CTRL_DPMS_VPHN 1 #define SYSTEM_CTRL_DPMS_VNHP 2 #define SYSTEM_CTRL_DPMS_VNHN 3 -#define SYSTEM_CTRL_PCI_BURST 29:29 -#define SYSTEM_CTRL_PCI_BURST_OFF 0 -#define SYSTEM_CTRL_PCI_BURST_ON 1 -#define SYSTEM_CTRL_PCI_MASTER 25:25 -#define SYSTEM_CTRL_PCI_MASTER_OFF 0 -#define SYSTEM_CTRL_PCI_MASTER_ON 1 -#define SYSTEM_CTRL_LATENCY_TIMER 24:24 -#define SYSTEM_CTRL_LATENCY_TIMER_ON 0 -#define SYSTEM_CTRL_LATENCY_TIMER_OFF 1 -#define SYSTEM_CTRL_DE_FIFO 23:23 -#define SYSTEM_CTRL_DE_FIFO_NOTEMPTY 0 -#define SYSTEM_CTRL_DE_FIFO_EMPTY 1 -#define SYSTEM_CTRL_DE_STATUS 22:22 -#define SYSTEM_CTRL_DE_STATUS_IDLE 0 -#define SYSTEM_CTRL_DE_STATUS_BUSY 1 -#define SYSTEM_CTRL_DE_MEM_FIFO 21:21 -#define SYSTEM_CTRL_DE_MEM_FIFO_NOTEMPTY 0 -#define SYSTEM_CTRL_DE_MEM_FIFO_EMPTY 1 -#define SYSTEM_CTRL_CSC_STATUS 20:20 -#define SYSTEM_CTRL_CSC_STATUS_IDLE 0 -#define SYSTEM_CTRL_CSC_STATUS_BUSY 1 -#define SYSTEM_CTRL_CRT_VSYNC 19:19 -#define SYSTEM_CTRL_CRT_VSYNC_INACTIVE 0 -#define SYSTEM_CTRL_CRT_VSYNC_ACTIVE 1 -#define SYSTEM_CTRL_PANEL_VSYNC 18:18 -#define SYSTEM_CTRL_PANEL_VSYNC_INACTIVE 0 -#define SYSTEM_CTRL_PANEL_VSYNC_ACTIVE 1 -#define SYSTEM_CTRL_CURRENT_BUFFER 17:17 -#define SYSTEM_CTRL_CURRENT_BUFFER_NORMAL 0 -#define SYSTEM_CTRL_CURRENT_BUFFER_FLIP_PENDING 1 -#define SYSTEM_CTRL_DMA_STATUS 16:16 -#define SYSTEM_CTRL_DMA_STATUS_IDLE 0 -#define SYSTEM_CTRL_DMA_STATUS_BUSY 1 -#define SYSTEM_CTRL_PCI_BURST_READ 15:15 -#define SYSTEM_CTRL_PCI_BURST_READ_OFF 0 -#define SYSTEM_CTRL_PCI_BURST_READ_ON 1 -#define SYSTEM_CTRL_DE_ABORT 13:13 -#define SYSTEM_CTRL_DE_ABORT_OFF 0 -#define SYSTEM_CTRL_DE_ABORT_ON 1 -#define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK 11:11 -#define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK_OFF 0 -#define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK_ON 1 -#define SYSTEM_CTRL_PCI_RETRY 7:7 -#define SYSTEM_CTRL_PCI_RETRY_ON 0 -#define SYSTEM_CTRL_PCI_RETRY_OFF 1 +#define SYSTEM_CTRL_PCI_BURST BIT(29) +#define SYSTEM_CTRL_PCI_MASTER BIT(25) +#define SYSTEM_CTRL_LATENCY_TIMER_OFF BIT(24) +#define SYSTEM_CTRL_DE_FIFO_EMPTY BIT(23) +#define SYSTEM_CTRL_DE_STATUS_BUSY BIT(22) +#define SYSTEM_CTRL_DE_MEM_FIFO_EMPTY BIT(21) +#define SYSTEM_CTRL_CSC_STATUS_BUSY BIT(20) +#define SYSTEM_CTRL_CRT_VSYNC_ACTIVE BIT(19) +#define SYSTEM_CTRL_PANEL_VSYNC_ACTIVE BIT(18) +#define SYSTEM_CTRL_CURRENT_BUFFER_FLIP_PENDING BIT(17) +#define SYSTEM_CTRL_DMA_STATUS_BUSY BIT(16) +#define SYSTEM_CTRL_PCI_BURST_READ BIT(15) +#define SYSTEM_CTRL_DE_ABORT BIT(13) +#define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK BIT(11) +#define SYSTEM_CTRL_PCI_RETRY_OFF BIT(7) #define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE 5:4 #define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_1 0 #define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_2 1 #define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_4 2 #define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_8 3 -#define SYSTEM_CTRL_CRT_TRISTATE 3:3 -#define SYSTEM_CTRL_CRT_TRISTATE_OFF 0 -#define SYSTEM_CTRL_CRT_TRISTATE_ON 1 -#define SYSTEM_CTRL_PCIMEM_TRISTATE 2:2 -#define SYSTEM_CTRL_PCIMEM_TRISTATE_OFF 0 -#define SYSTEM_CTRL_PCIMEM_TRISTATE_ON 1 -#define SYSTEM_CTRL_LOCALMEM_TRISTATE 1:1 -#define SYSTEM_CTRL_LOCALMEM_TRISTATE_OFF 0 -#define SYSTEM_CTRL_LOCALMEM_TRISTATE_ON 1 -#define SYSTEM_CTRL_PANEL_TRISTATE 0:0 -#define SYSTEM_CTRL_PANEL_TRISTATE_OFF 0 -#define SYSTEM_CTRL_PANEL_TRISTATE_ON 1 +#define SYSTEM_CTRL_CRT_TRISTATE BIT(3) +#define SYSTEM_CTRL_PCIMEM_TRISTATE BIT(2) +#define SYSTEM_CTRL_LOCALMEM_TRISTATE BIT(1) +#define SYSTEM_CTRL_PANEL_TRISTATE BIT(0) #define MISC_CTRL 0x000004 #define MISC_CTRL_DRAM_RERESH_COUNT 27:27 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 425bec886078..59adeb669644 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -108,7 +108,7 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) /* for sm718,open pci burst */ if (sm750_dev->devid == 0x718) { POKE32(SYSTEM_CTRL, - FIELD_SET(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, PCI_BURST, ON)); + PEEK32(SYSTEM_CTRL) | SYSTEM_CTRL_PCI_BURST); } if (getChipType() != SM750LE) { @@ -478,11 +478,11 @@ void hw_sm750_initAccel(struct sm750_dev *sm750_dev) } else { /* engine reset */ reg = PEEK32(SYSTEM_CTRL); - reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT, ON); + reg |= SYSTEM_CTRL_DE_ABORT; POKE32(SYSTEM_CTRL, reg); reg = PEEK32(SYSTEM_CTRL); - reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT, OFF); + reg &= ~SYSTEM_CTRL_DE_ABORT; POKE32(SYSTEM_CTRL, reg); } @@ -511,15 +511,16 @@ int hw_sm750le_deWait(void) int hw_sm750_deWait(void) { int i = 0x10000000; + unsigned int mask = SYSTEM_CTRL_DE_STATUS_BUSY | + SYSTEM_CTRL_DE_FIFO_EMPTY | + SYSTEM_CTRL_DE_MEM_FIFO_EMPTY; while (i--) { unsigned int val = PEEK32(SYSTEM_CTRL); - if ((FIELD_GET(val, SYSTEM_CTRL, DE_STATUS) == SYSTEM_CTRL_DE_STATUS_IDLE) && - (FIELD_GET(val, SYSTEM_CTRL, DE_FIFO) == SYSTEM_CTRL_DE_FIFO_EMPTY) && - (FIELD_GET(val, SYSTEM_CTRL, DE_MEM_FIFO) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) { + if ((val & mask) == + (SYSTEM_CTRL_DE_FIFO_EMPTY | SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) return 0; - } } /* timeout error */ return -1; -- cgit v1.2.3 From a8856ff88ee8b6026782c70f71f0c95c45c57992 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:19 +0200 Subject: staging: sm750fb: change definition of SYSTEM_CTRL multi-bit fields Use more straight-forward definitions for multi-bit fields of SYSTEM_CTRL register and replace FIELD_GET/SET for these fields with open-coded implementation. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_power.c | 2 +- drivers/staging/sm750fb/ddk750_reg.h | 20 ++++++++++---------- drivers/staging/sm750fb/sm750_hw.c | 18 +++++++++--------- 3 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index 667e4f822544..1c5001c0a44e 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -12,7 +12,7 @@ void ddk750_setDPMS(DPMS_t state) DPMS, state)); } else { value = PEEK32(SYSTEM_CTRL); - value = FIELD_VALUE(value, SYSTEM_CTRL, DPMS, state); + value = (value & ~SYSTEM_CTRL_DPMS_MASK) | state; POKE32(SYSTEM_CTRL, value); } } diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 351a1dc67900..75a20e70ebc3 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -11,11 +11,11 @@ #define DE_STATE2_DE_MEM_FIFO_EMPTY BIT(1) #define SYSTEM_CTRL 0x000000 -#define SYSTEM_CTRL_DPMS 31:30 -#define SYSTEM_CTRL_DPMS_VPHP 0 -#define SYSTEM_CTRL_DPMS_VPHN 1 -#define SYSTEM_CTRL_DPMS_VNHP 2 -#define SYSTEM_CTRL_DPMS_VNHN 3 +#define SYSTEM_CTRL_DPMS_MASK (0x3 << 30) +#define SYSTEM_CTRL_DPMS_VPHP (0x0 << 30) +#define SYSTEM_CTRL_DPMS_VPHN (0x1 << 30) +#define SYSTEM_CTRL_DPMS_VNHP (0x2 << 30) +#define SYSTEM_CTRL_DPMS_VNHN (0x3 << 30) #define SYSTEM_CTRL_PCI_BURST BIT(29) #define SYSTEM_CTRL_PCI_MASTER BIT(25) #define SYSTEM_CTRL_LATENCY_TIMER_OFF BIT(24) @@ -31,11 +31,11 @@ #define SYSTEM_CTRL_DE_ABORT BIT(13) #define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK BIT(11) #define SYSTEM_CTRL_PCI_RETRY_OFF BIT(7) -#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE 5:4 -#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_1 0 -#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_2 1 -#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_4 2 -#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_8 3 +#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_MASK (0x3 << 4) +#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_1 (0x0 << 4) +#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_2 (0x1 << 4) +#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_4 (0x2 << 4) +#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_8 (0x3 << 4) #define SYSTEM_CTRL_CRT_TRISTATE BIT(3) #define SYSTEM_CTRL_PCIMEM_TRISTATE BIT(2) #define SYSTEM_CTRL_LOCALMEM_TRISTATE BIT(1) diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 59adeb669644..357ee5654d4d 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -112,6 +112,7 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) } if (getChipType() != SM750LE) { + unsigned int val; /* does user need CRT ?*/ if (sm750_dev->nocrt) { POKE32(MISC_CTRL, @@ -119,20 +120,18 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) MISC_CTRL, DAC_POWER, OFF)); /* shut off dpms */ - POKE32(SYSTEM_CTRL, - FIELD_SET(PEEK32(SYSTEM_CTRL), - SYSTEM_CTRL, - DPMS, VNHN)); + val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK; + val |= SYSTEM_CTRL_DPMS_VPHN; + POKE32(SYSTEM_CTRL, val); } else { POKE32(MISC_CTRL, FIELD_SET(PEEK32(MISC_CTRL), MISC_CTRL, DAC_POWER, ON)); /* turn on dpms */ - POKE32(SYSTEM_CTRL, - FIELD_SET(PEEK32(SYSTEM_CTRL), - SYSTEM_CTRL, - DPMS, VPHP)); + val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK; + val |= SYSTEM_CTRL_DPMS_VPHP; + POKE32(SYSTEM_CTRL, val); } switch (sm750_dev->pnltype) { @@ -448,8 +447,9 @@ int hw_sm750_setBLANK(struct lynxfb_output *output, int blank) } if (output->paths & sm750_crt) { + unsigned int val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK; - POKE32(SYSTEM_CTRL, FIELD_VALUE(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, DPMS, dpms)); + POKE32(SYSTEM_CTRL, val | dpms); POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb)); } -- cgit v1.2.3 From 8bc728cf0125ad1e420b2097b28488c23dc0cab2 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:20 +0200 Subject: staging: sm750fb: ddk750_initHw: rename ulReg to reg Remove HungarianCamelCase notation Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 52 +++++++++++++++++------------------ 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 0331d34458ae..905c1a86fd80 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -197,24 +197,24 @@ unsigned int ddk750_getVMSize(void) int ddk750_initHw(initchip_param_t *pInitParam) { - unsigned int ulReg; + unsigned int reg; if (pInitParam->powerMode != 0) pInitParam->powerMode = 0; setPowerMode(pInitParam->powerMode); /* Enable display power gate & LOCALMEM power gate*/ - ulReg = PEEK32(CURRENT_GATE); - ulReg = FIELD_SET(ulReg, CURRENT_GATE, DISPLAY, ON); - ulReg = FIELD_SET(ulReg, CURRENT_GATE, LOCALMEM, ON); - setCurrentGate(ulReg); + reg = PEEK32(CURRENT_GATE); + reg = FIELD_SET(reg, CURRENT_GATE, DISPLAY, ON); + reg = FIELD_SET(reg, CURRENT_GATE, LOCALMEM, ON); + setCurrentGate(reg); if (getChipType() != SM750LE) { /* set panel pll and graphic mode via mmio_88 */ - ulReg = PEEK32(VGA_CONFIGURATION); - ulReg = FIELD_SET(ulReg, VGA_CONFIGURATION, PLL, PANEL); - ulReg = FIELD_SET(ulReg, VGA_CONFIGURATION, MODE, GRAPHIC); - POKE32(VGA_CONFIGURATION, ulReg); + reg = PEEK32(VGA_CONFIGURATION); + reg = FIELD_SET(reg, VGA_CONFIGURATION, PLL, PANEL); + reg = FIELD_SET(reg, VGA_CONFIGURATION, MODE, GRAPHIC); + POKE32(VGA_CONFIGURATION, reg); } else { #if defined(__i386__) || defined(__x86_64__) /* set graphic mode via IO method */ @@ -238,36 +238,36 @@ int ddk750_initHw(initchip_param_t *pInitParam) The memory should be resetted after changing the MXCLK. */ if (pInitParam->resetMemory == 1) { - ulReg = PEEK32(MISC_CTRL); - ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, RESET); - POKE32(MISC_CTRL, ulReg); + reg = PEEK32(MISC_CTRL); + reg = FIELD_SET(reg, MISC_CTRL, LOCALMEM_RESET, RESET); + POKE32(MISC_CTRL, reg); - ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, NORMAL); - POKE32(MISC_CTRL, ulReg); + reg = FIELD_SET(reg, MISC_CTRL, LOCALMEM_RESET, NORMAL); + POKE32(MISC_CTRL, reg); } if (pInitParam->setAllEngOff == 1) { enable2DEngine(0); /* Disable Overlay, if a former application left it on */ - ulReg = PEEK32(VIDEO_DISPLAY_CTRL); - ulReg = FIELD_SET(ulReg, VIDEO_DISPLAY_CTRL, PLANE, DISABLE); - POKE32(VIDEO_DISPLAY_CTRL, ulReg); + reg = PEEK32(VIDEO_DISPLAY_CTRL); + reg = FIELD_SET(reg, VIDEO_DISPLAY_CTRL, PLANE, DISABLE); + POKE32(VIDEO_DISPLAY_CTRL, reg); /* Disable video alpha, if a former application left it on */ - ulReg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL); - ulReg = FIELD_SET(ulReg, VIDEO_ALPHA_DISPLAY_CTRL, PLANE, DISABLE); - POKE32(VIDEO_ALPHA_DISPLAY_CTRL, ulReg); + reg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL); + reg = FIELD_SET(reg, VIDEO_ALPHA_DISPLAY_CTRL, PLANE, DISABLE); + POKE32(VIDEO_ALPHA_DISPLAY_CTRL, reg); /* Disable alpha plane, if a former application left it on */ - ulReg = PEEK32(ALPHA_DISPLAY_CTRL); - ulReg = FIELD_SET(ulReg, ALPHA_DISPLAY_CTRL, PLANE, DISABLE); - POKE32(ALPHA_DISPLAY_CTRL, ulReg); + reg = PEEK32(ALPHA_DISPLAY_CTRL); + reg = FIELD_SET(reg, ALPHA_DISPLAY_CTRL, PLANE, DISABLE); + POKE32(ALPHA_DISPLAY_CTRL, reg); /* Disable DMA Channel, if a former application left it on */ - ulReg = PEEK32(DMA_ABORT_INTERRUPT); - ulReg = FIELD_SET(ulReg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT); - POKE32(DMA_ABORT_INTERRUPT, ulReg); + reg = PEEK32(DMA_ABORT_INTERRUPT); + reg = FIELD_SET(reg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT); + POKE32(DMA_ABORT_INTERRUPT, reg); /* Disable DMA Power, if a former application left it on */ enableDMA(0); -- cgit v1.2.3 From 5372350be30abf9f84e676d1f28260d3a3b5e629 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:21 +0200 Subject: staging: sm750fb: use BIT macro for MISC_CTRL single-bit fields Replace complex definition of MISC_CTRL register fields with BIT() macro and use open-coded implementation for register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 4 +- drivers/staging/sm750fb/ddk750_power.h | 11 ++---- drivers/staging/sm750fb/ddk750_reg.h | 68 +++++++++------------------------- drivers/staging/sm750fb/sm750_hw.c | 8 +--- 4 files changed, 25 insertions(+), 66 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 905c1a86fd80..08b490578b06 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -239,10 +239,10 @@ int ddk750_initHw(initchip_param_t *pInitParam) */ if (pInitParam->resetMemory == 1) { reg = PEEK32(MISC_CTRL); - reg = FIELD_SET(reg, MISC_CTRL, LOCALMEM_RESET, RESET); + reg &= ~MISC_CTRL_LOCALMEM_RESET; POKE32(MISC_CTRL, reg); - reg = FIELD_SET(reg, MISC_CTRL, LOCALMEM_RESET, NORMAL); + reg |= MISC_CTRL_LOCALMEM_RESET; POKE32(MISC_CTRL, reg); } diff --git a/drivers/staging/sm750fb/ddk750_power.h b/drivers/staging/sm750fb/ddk750_power.h index 6e804d990cff..5963691f9a68 100644 --- a/drivers/staging/sm750fb/ddk750_power.h +++ b/drivers/staging/sm750fb/ddk750_power.h @@ -9,13 +9,10 @@ typedef enum _DPMS_t { } DPMS_t; -#define setDAC(off) \ - { \ - POKE32(MISC_CTRL, FIELD_VALUE(PEEK32(MISC_CTRL), \ - MISC_CTRL, \ - DAC_POWER, \ - off)); \ - } +#define setDAC(off) { \ + POKE32(MISC_CTRL, \ + (PEEK32(MISC_CTRL) & ~MISC_CTRL_DAC_POWER_OFF) | (off)); \ +} void ddk750_setDPMS(DPMS_t); diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 75a20e70ebc3..6fef904f3de1 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -42,26 +42,16 @@ #define SYSTEM_CTRL_PANEL_TRISTATE BIT(0) #define MISC_CTRL 0x000004 -#define MISC_CTRL_DRAM_RERESH_COUNT 27:27 -#define MISC_CTRL_DRAM_RERESH_COUNT_1ROW 0 -#define MISC_CTRL_DRAM_RERESH_COUNT_3ROW 1 +#define MISC_CTRL_DRAM_RERESH_COUNT BIT(27) #define MISC_CTRL_DRAM_REFRESH_TIME 26:25 #define MISC_CTRL_DRAM_REFRESH_TIME_8 0 #define MISC_CTRL_DRAM_REFRESH_TIME_16 1 #define MISC_CTRL_DRAM_REFRESH_TIME_32 2 #define MISC_CTRL_DRAM_REFRESH_TIME_64 3 -#define MISC_CTRL_INT_OUTPUT 24:24 -#define MISC_CTRL_INT_OUTPUT_NORMAL 0 -#define MISC_CTRL_INT_OUTPUT_INVERT 1 -#define MISC_CTRL_PLL_CLK_COUNT 23:23 -#define MISC_CTRL_PLL_CLK_COUNT_OFF 0 -#define MISC_CTRL_PLL_CLK_COUNT_ON 1 -#define MISC_CTRL_DAC_POWER 20:20 -#define MISC_CTRL_DAC_POWER_ON 0 -#define MISC_CTRL_DAC_POWER_OFF 1 -#define MISC_CTRL_CLK_SELECT 16:16 -#define MISC_CTRL_CLK_SELECT_OSC 0 -#define MISC_CTRL_CLK_SELECT_TESTCLK 1 +#define MISC_CTRL_INT_OUTPUT_INVERT BIT(24) +#define MISC_CTRL_PLL_CLK_COUNT BIT(23) +#define MISC_CTRL_DAC_POWER_OFF BIT(20) +#define MISC_CTRL_CLK_SELECT_TESTCLK BIT(16) #define MISC_CTRL_DRAM_COLUMN_SIZE 15:14 #define MISC_CTRL_DRAM_COLUMN_SIZE_256 0 #define MISC_CTRL_DRAM_COLUMN_SIZE_512 1 @@ -71,42 +61,18 @@ #define MISC_CTRL_LOCALMEM_SIZE_16M 0 #define MISC_CTRL_LOCALMEM_SIZE_32M 1 #define MISC_CTRL_LOCALMEM_SIZE_64M 2 -#define MISC_CTRL_DRAM_TWTR 11:11 -#define MISC_CTRL_DRAM_TWTR_2CLK 0 -#define MISC_CTRL_DRAM_TWTR_1CLK 1 -#define MISC_CTRL_DRAM_TWR 10:10 -#define MISC_CTRL_DRAM_TWR_3CLK 0 -#define MISC_CTRL_DRAM_TWR_2CLK 1 -#define MISC_CTRL_DRAM_TRP 9:9 -#define MISC_CTRL_DRAM_TRP_3CLK 0 -#define MISC_CTRL_DRAM_TRP_4CLK 1 -#define MISC_CTRL_DRAM_TRFC 8:8 -#define MISC_CTRL_DRAM_TRFC_12CLK 0 -#define MISC_CTRL_DRAM_TRFC_14CLK 1 -#define MISC_CTRL_DRAM_TRAS 7:7 -#define MISC_CTRL_DRAM_TRAS_7CLK 0 -#define MISC_CTRL_DRAM_TRAS_8CLK 1 -#define MISC_CTRL_LOCALMEM_RESET 6:6 -#define MISC_CTRL_LOCALMEM_RESET_RESET 0 -#define MISC_CTRL_LOCALMEM_RESET_NORMAL 1 -#define MISC_CTRL_LOCALMEM_STATE 5:5 -#define MISC_CTRL_LOCALMEM_STATE_ACTIVE 0 -#define MISC_CTRL_LOCALMEM_STATE_INACTIVE 1 -#define MISC_CTRL_CPU_CAS_LATENCY 4:4 -#define MISC_CTRL_CPU_CAS_LATENCY_2CLK 0 -#define MISC_CTRL_CPU_CAS_LATENCY_3CLK 1 -#define MISC_CTRL_DLL 3:3 -#define MISC_CTRL_DLL_ON 0 -#define MISC_CTRL_DLL_OFF 1 -#define MISC_CTRL_DRAM_OUTPUT 2:2 -#define MISC_CTRL_DRAM_OUTPUT_LOW 0 -#define MISC_CTRL_DRAM_OUTPUT_HIGH 1 -#define MISC_CTRL_LOCALMEM_BUS_SIZE 1:1 -#define MISC_CTRL_LOCALMEM_BUS_SIZE_32 0 -#define MISC_CTRL_LOCALMEM_BUS_SIZE_64 1 -#define MISC_CTRL_EMBEDDED_LOCALMEM 0:0 -#define MISC_CTRL_EMBEDDED_LOCALMEM_ON 0 -#define MISC_CTRL_EMBEDDED_LOCALMEM_OFF 1 +#define MISC_CTRL_DRAM_TWTR BIT(11) +#define MISC_CTRL_DRAM_TWR BIT(10) +#define MISC_CTRL_DRAM_TRP BIT(9) +#define MISC_CTRL_DRAM_TRFC BIT(8) +#define MISC_CTRL_DRAM_TRAS BIT(7) +#define MISC_CTRL_LOCALMEM_RESET BIT(6) +#define MISC_CTRL_LOCALMEM_STATE_INACTIVE BIT(5) +#define MISC_CTRL_CPU_CAS_LATENCY BIT(4) +#define MISC_CTRL_DLL_OFF BIT(3) +#define MISC_CTRL_DRAM_OUTPUT_HIGH BIT(2) +#define MISC_CTRL_LOCALMEM_BUS_SIZE BIT(1) +#define MISC_CTRL_EMBEDDED_LOCALMEM_OFF BIT(0) #define GPIO_MUX 0x000008 #define GPIO_MUX_31 31:31 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 357ee5654d4d..b33ec076f3f5 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -116,18 +116,14 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) /* does user need CRT ?*/ if (sm750_dev->nocrt) { POKE32(MISC_CTRL, - FIELD_SET(PEEK32(MISC_CTRL), - MISC_CTRL, - DAC_POWER, OFF)); + PEEK32(MISC_CTRL) | MISC_CTRL_DAC_POWER_OFF); /* shut off dpms */ val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK; val |= SYSTEM_CTRL_DPMS_VPHN; POKE32(SYSTEM_CTRL, val); } else { POKE32(MISC_CTRL, - FIELD_SET(PEEK32(MISC_CTRL), - MISC_CTRL, - DAC_POWER, ON)); + PEEK32(MISC_CTRL) & ~MISC_CTRL_DAC_POWER_OFF); /* turn on dpms */ val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK; val |= SYSTEM_CTRL_DPMS_VPHP; -- cgit v1.2.3 From 9a357143bcddcbba4e57839694240ad44714279d Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:22 +0200 Subject: staging: sm750fb: ddk750_sii164: fix defines for i2c{Read, Write}reg For case when USE_HW_I2C is not defined, i2c{Read,Write}reg was wrongly defined to use old function names. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_sii164.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_sii164.c b/drivers/staging/sm750fb/ddk750_sii164.c index 241b77b927ee..9fd6afb009c2 100644 --- a/drivers/staging/sm750fb/ddk750_sii164.c +++ b/drivers/staging/sm750fb/ddk750_sii164.c @@ -14,8 +14,8 @@ #define i2cWriteReg sm750_hw_i2c_write_reg #define i2cReadReg sm750_hw_i2c_read_reg #else - #define i2cWriteReg swI2CWriteReg - #define i2cReadReg swI2CReadReg + #define i2cWriteReg sm750_sw_i2c_write_reg + #define i2cReadReg sm750_sw_i2c_read_reg #endif /* SII164 Vendor and Device ID */ -- cgit v1.2.3 From 2a5149e0a20f451c0c39e4fc90511f13615e80c9 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:23 +0200 Subject: staging: sm750fb: use BIT macro for GPIO_MUX single-bit fields Replace complex definition of GPIO_MUX register fields with BIT() macro and use open-coded implementation for register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_hwi2c.c | 7 +- drivers/staging/sm750fb/ddk750_reg.h | 128 +++++++++------------------------ 2 files changed, 35 insertions(+), 100 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_hwi2c.c b/drivers/staging/sm750fb/ddk750_hwi2c.c index 7be2111284f4..b824681e55a7 100644 --- a/drivers/staging/sm750fb/ddk750_hwi2c.c +++ b/drivers/staging/sm750fb/ddk750_hwi2c.c @@ -17,8 +17,7 @@ unsigned char bus_speed_mode /* Enable GPIO 30 & 31 as IIC clock & data */ value = PEEK32(GPIO_MUX); - value = FIELD_SET(value, GPIO_MUX, 30, I2C) | - FIELD_SET(0, GPIO_MUX, 31, I2C); + value |= (GPIO_MUX_30 | GPIO_MUX_31); POKE32(GPIO_MUX, value); /* Enable Hardware I2C power. @@ -52,8 +51,8 @@ void sm750_hw_i2c_close(void) /* Set GPIO 30 & 31 back as GPIO pins */ value = PEEK32(GPIO_MUX); - value = FIELD_SET(value, GPIO_MUX, 30, GPIO); - value = FIELD_SET(value, GPIO_MUX, 31, GPIO); + value &= ~GPIO_MUX_30; + value &= ~GPIO_MUX_31; POKE32(GPIO_MUX, value); } diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 6fef904f3de1..6df50769746e 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -75,102 +75,38 @@ #define MISC_CTRL_EMBEDDED_LOCALMEM_OFF BIT(0) #define GPIO_MUX 0x000008 -#define GPIO_MUX_31 31:31 -#define GPIO_MUX_31_GPIO 0 -#define GPIO_MUX_31_I2C 1 -#define GPIO_MUX_30 30:30 -#define GPIO_MUX_30_GPIO 0 -#define GPIO_MUX_30_I2C 1 -#define GPIO_MUX_29 29:29 -#define GPIO_MUX_29_GPIO 0 -#define GPIO_MUX_29_SSP1 1 -#define GPIO_MUX_28 28:28 -#define GPIO_MUX_28_GPIO 0 -#define GPIO_MUX_28_SSP1 1 -#define GPIO_MUX_27 27:27 -#define GPIO_MUX_27_GPIO 0 -#define GPIO_MUX_27_SSP1 1 -#define GPIO_MUX_26 26:26 -#define GPIO_MUX_26_GPIO 0 -#define GPIO_MUX_26_SSP1 1 -#define GPIO_MUX_25 25:25 -#define GPIO_MUX_25_GPIO 0 -#define GPIO_MUX_25_SSP1 1 -#define GPIO_MUX_24 24:24 -#define GPIO_MUX_24_GPIO 0 -#define GPIO_MUX_24_SSP0 1 -#define GPIO_MUX_23 23:23 -#define GPIO_MUX_23_GPIO 0 -#define GPIO_MUX_23_SSP0 1 -#define GPIO_MUX_22 22:22 -#define GPIO_MUX_22_GPIO 0 -#define GPIO_MUX_22_SSP0 1 -#define GPIO_MUX_21 21:21 -#define GPIO_MUX_21_GPIO 0 -#define GPIO_MUX_21_SSP0 1 -#define GPIO_MUX_20 20:20 -#define GPIO_MUX_20_GPIO 0 -#define GPIO_MUX_20_SSP0 1 -#define GPIO_MUX_19 19:19 -#define GPIO_MUX_19_GPIO 0 -#define GPIO_MUX_19_PWM 1 -#define GPIO_MUX_18 18:18 -#define GPIO_MUX_18_GPIO 0 -#define GPIO_MUX_18_PWM 1 -#define GPIO_MUX_17 17:17 -#define GPIO_MUX_17_GPIO 0 -#define GPIO_MUX_17_PWM 1 -#define GPIO_MUX_16 16:16 -#define GPIO_MUX_16_GPIO_ZVPORT 0 -#define GPIO_MUX_16_TEST_DATA 1 -#define GPIO_MUX_15 15:15 -#define GPIO_MUX_15_GPIO_ZVPORT 0 -#define GPIO_MUX_15_TEST_DATA 1 -#define GPIO_MUX_14 14:14 -#define GPIO_MUX_14_GPIO_ZVPORT 0 -#define GPIO_MUX_14_TEST_DATA 1 -#define GPIO_MUX_13 13:13 -#define GPIO_MUX_13_GPIO_ZVPORT 0 -#define GPIO_MUX_13_TEST_DATA 1 -#define GPIO_MUX_12 12:12 -#define GPIO_MUX_12_GPIO_ZVPORT 0 -#define GPIO_MUX_12_TEST_DATA 1 -#define GPIO_MUX_11 11:11 -#define GPIO_MUX_11_GPIO_ZVPORT 0 -#define GPIO_MUX_11_TEST_DATA 1 -#define GPIO_MUX_10 10:10 -#define GPIO_MUX_10_GPIO_ZVPORT 0 -#define GPIO_MUX_10_TEST_DATA 1 -#define GPIO_MUX_9 9:9 -#define GPIO_MUX_9_GPIO_ZVPORT 0 -#define GPIO_MUX_9_TEST_DATA 1 -#define GPIO_MUX_8 8:8 -#define GPIO_MUX_8_GPIO_ZVPORT 0 -#define GPIO_MUX_8_TEST_DATA 1 -#define GPIO_MUX_7 7:7 -#define GPIO_MUX_7_GPIO_ZVPORT 0 -#define GPIO_MUX_7_TEST_DATA 1 -#define GPIO_MUX_6 6:6 -#define GPIO_MUX_6_GPIO_ZVPORT 0 -#define GPIO_MUX_6_TEST_DATA 1 -#define GPIO_MUX_5 5:5 -#define GPIO_MUX_5_GPIO_ZVPORT 0 -#define GPIO_MUX_5_TEST_DATA 1 -#define GPIO_MUX_4 4:4 -#define GPIO_MUX_4_GPIO_ZVPORT 0 -#define GPIO_MUX_4_TEST_DATA 1 -#define GPIO_MUX_3 3:3 -#define GPIO_MUX_3_GPIO_ZVPORT 0 -#define GPIO_MUX_3_TEST_DATA 1 -#define GPIO_MUX_2 2:2 -#define GPIO_MUX_2_GPIO_ZVPORT 0 -#define GPIO_MUX_2_TEST_DATA 1 -#define GPIO_MUX_1 1:1 -#define GPIO_MUX_1_GPIO_ZVPORT 0 -#define GPIO_MUX_1_TEST_DATA 1 -#define GPIO_MUX_0 0:0 -#define GPIO_MUX_0_GPIO_ZVPORT 0 -#define GPIO_MUX_0_TEST_DATA 1 +#define GPIO_MUX_31 BIT(31) +#define GPIO_MUX_30 BIT(30) +#define GPIO_MUX_29 BIT(29) +#define GPIO_MUX_28 BIT(28) +#define GPIO_MUX_27 BIT(27) +#define GPIO_MUX_26 BIT(26) +#define GPIO_MUX_25 BIT(25) +#define GPIO_MUX_24 BIT(24) +#define GPIO_MUX_23 BIT(23) +#define GPIO_MUX_22 BIT(22) +#define GPIO_MUX_21 BIT(21) +#define GPIO_MUX_20 BIT(20) +#define GPIO_MUX_19 BIT(19) +#define GPIO_MUX_18 BIT(18) +#define GPIO_MUX_17 BIT(17) +#define GPIO_MUX_16 BIT(16) +#define GPIO_MUX_15 BIT(15) +#define GPIO_MUX_14 BIT(14) +#define GPIO_MUX_13 BIT(13) +#define GPIO_MUX_12 BIT(12) +#define GPIO_MUX_11 BIT(11) +#define GPIO_MUX_10 BIT(10) +#define GPIO_MUX_9 BIT(9) +#define GPIO_MUX_8 BIT(8) +#define GPIO_MUX_7 BIT(7) +#define GPIO_MUX_6 BIT(6) +#define GPIO_MUX_5 BIT(5) +#define GPIO_MUX_4 BIT(4) +#define GPIO_MUX_3 BIT(3) +#define GPIO_MUX_2 BIT(2) +#define GPIO_MUX_1 BIT(1) +#define GPIO_MUX_0 BIT(0) #define LOCALMEM_ARBITRATION 0x00000C #define LOCALMEM_ARBITRATION_ROTATE 28:28 -- cgit v1.2.3 From 5538d5c8bd1681dbf6e5684de24acffa69e2bf9f Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:24 +0200 Subject: staging: sm750fb: change definition of MISC_CTRL multi-bit fields Use more straight-forward definitions for multi-bit fields of MISC_CTRL register and use open-coded implementation for register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 2 +- drivers/staging/sm750fb/ddk750_reg.h | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 08b490578b06..36c2e50ef661 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -178,7 +178,7 @@ unsigned int ddk750_getVMSize(void) POKE32(MODE0_GATE, reg); /* get frame buffer size from GPIO */ - reg = FIELD_GET(PEEK32(MISC_CTRL), MISC_CTRL, LOCALMEM_SIZE); + reg = PEEK32(MISC_CTRL) & MISC_CTRL_LOCALMEM_SIZE_MASK; switch (reg) { case MISC_CTRL_LOCALMEM_SIZE_8M: data = SZ_8M; break; /* 8 Mega byte */ diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 6df50769746e..72eaf1920bd0 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -43,24 +43,24 @@ #define MISC_CTRL 0x000004 #define MISC_CTRL_DRAM_RERESH_COUNT BIT(27) -#define MISC_CTRL_DRAM_REFRESH_TIME 26:25 -#define MISC_CTRL_DRAM_REFRESH_TIME_8 0 -#define MISC_CTRL_DRAM_REFRESH_TIME_16 1 -#define MISC_CTRL_DRAM_REFRESH_TIME_32 2 -#define MISC_CTRL_DRAM_REFRESH_TIME_64 3 +#define MISC_CTRL_DRAM_REFRESH_TIME_MASK (0x3 << 25) +#define MISC_CTRL_DRAM_REFRESH_TIME_8 (0x0 << 25) +#define MISC_CTRL_DRAM_REFRESH_TIME_16 (0x1 << 25) +#define MISC_CTRL_DRAM_REFRESH_TIME_32 (0x2 << 25) +#define MISC_CTRL_DRAM_REFRESH_TIME_64 (0x3 << 25) #define MISC_CTRL_INT_OUTPUT_INVERT BIT(24) #define MISC_CTRL_PLL_CLK_COUNT BIT(23) #define MISC_CTRL_DAC_POWER_OFF BIT(20) #define MISC_CTRL_CLK_SELECT_TESTCLK BIT(16) -#define MISC_CTRL_DRAM_COLUMN_SIZE 15:14 -#define MISC_CTRL_DRAM_COLUMN_SIZE_256 0 -#define MISC_CTRL_DRAM_COLUMN_SIZE_512 1 -#define MISC_CTRL_DRAM_COLUMN_SIZE_1024 2 -#define MISC_CTRL_LOCALMEM_SIZE 13:12 -#define MISC_CTRL_LOCALMEM_SIZE_8M 3 -#define MISC_CTRL_LOCALMEM_SIZE_16M 0 -#define MISC_CTRL_LOCALMEM_SIZE_32M 1 -#define MISC_CTRL_LOCALMEM_SIZE_64M 2 +#define MISC_CTRL_DRAM_COLUMN_SIZE_MASK (0x3 << 14) +#define MISC_CTRL_DRAM_COLUMN_SIZE_256 (0x0 << 14) +#define MISC_CTRL_DRAM_COLUMN_SIZE_512 (0x1 << 14) +#define MISC_CTRL_DRAM_COLUMN_SIZE_1024 (0x2 << 14) +#define MISC_CTRL_LOCALMEM_SIZE_MASK (0x3 << 12) +#define MISC_CTRL_LOCALMEM_SIZE_8M (0x3 << 12) +#define MISC_CTRL_LOCALMEM_SIZE_16M (0x0 << 12) +#define MISC_CTRL_LOCALMEM_SIZE_32M (0x1 << 12) +#define MISC_CTRL_LOCALMEM_SIZE_64M (0x2 << 12) #define MISC_CTRL_DRAM_TWTR BIT(11) #define MISC_CTRL_DRAM_TWR BIT(10) #define MISC_CTRL_DRAM_TRP BIT(9) -- cgit v1.2.3 From 90946e5293af9ff1253bc038e2afa4aa0844b75a Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:25 +0200 Subject: staging: sm750fb: use BIT macro for CURRENT_GATE single-bit fields Replace complex definition of CURRENT_GATE register fields with BIT() macro and use open-coded implementation for register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 3 +-- drivers/staging/sm750fb/ddk750_power.c | 18 +++++++------- drivers/staging/sm750fb/ddk750_reg.h | 44 +++++++++------------------------- 3 files changed, 20 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 36c2e50ef661..b11231ca1894 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -205,8 +205,7 @@ int ddk750_initHw(initchip_param_t *pInitParam) /* Enable display power gate & LOCALMEM power gate*/ reg = PEEK32(CURRENT_GATE); - reg = FIELD_SET(reg, CURRENT_GATE, DISPLAY, ON); - reg = FIELD_SET(reg, CURRENT_GATE, LOCALMEM, ON); + reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM); setCurrentGate(reg); if (getChipType() != SM750LE) { diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index 1c5001c0a44e..417702548f0f 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -112,11 +112,9 @@ void enable2DEngine(unsigned int enable) gate = PEEK32(CURRENT_GATE); if (enable) { - gate = FIELD_SET(gate, CURRENT_GATE, DE, ON); - gate = FIELD_SET(gate, CURRENT_GATE, CSC, ON); + gate |= (CURRENT_GATE_DE | CURRENT_GATE_CSC); } else { - gate = FIELD_SET(gate, CURRENT_GATE, DE, OFF); - gate = FIELD_SET(gate, CURRENT_GATE, CSC, OFF); + gate &= ~(CURRENT_GATE_DE | CURRENT_GATE_CSC); } setCurrentGate(gate); @@ -129,9 +127,9 @@ void enableDMA(unsigned int enable) /* Enable DMA Gate */ gate = PEEK32(CURRENT_GATE); if (enable) - gate = FIELD_SET(gate, CURRENT_GATE, DMA, ON); + gate |= CURRENT_GATE_DMA; else - gate = FIELD_SET(gate, CURRENT_GATE, DMA, OFF); + gate &= ~CURRENT_GATE_DMA; setCurrentGate(gate); } @@ -146,9 +144,9 @@ void enableGPIO(unsigned int enable) /* Enable GPIO Gate */ gate = PEEK32(CURRENT_GATE); if (enable) - gate = FIELD_SET(gate, CURRENT_GATE, GPIO, ON); + gate |= CURRENT_GATE_GPIO; else - gate = FIELD_SET(gate, CURRENT_GATE, GPIO, OFF); + gate &= ~CURRENT_GATE_GPIO; setCurrentGate(gate); } @@ -163,9 +161,9 @@ void enableI2C(unsigned int enable) /* Enable I2C Gate */ gate = PEEK32(CURRENT_GATE); if (enable) - gate = FIELD_SET(gate, CURRENT_GATE, I2C, ON); + gate |= CURRENT_GATE_I2C; else - gate = FIELD_SET(gate, CURRENT_GATE, I2C, OFF); + gate &= ~CURRENT_GATE_I2C; setCurrentGate(gate); } diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 72eaf1920bd0..e3ca8326f96f 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -415,39 +415,17 @@ #define CURRENT_GATE_M2XCLK_DIV_3 2 #define CURRENT_GATE_M2XCLK_DIV_4 3 #endif -#define CURRENT_GATE_VGA 10:10 -#define CURRENT_GATE_VGA_OFF 0 -#define CURRENT_GATE_VGA_ON 1 -#define CURRENT_GATE_PWM 9:9 -#define CURRENT_GATE_PWM_OFF 0 -#define CURRENT_GATE_PWM_ON 1 -#define CURRENT_GATE_I2C 8:8 -#define CURRENT_GATE_I2C_OFF 0 -#define CURRENT_GATE_I2C_ON 1 -#define CURRENT_GATE_SSP 7:7 -#define CURRENT_GATE_SSP_OFF 0 -#define CURRENT_GATE_SSP_ON 1 -#define CURRENT_GATE_GPIO 6:6 -#define CURRENT_GATE_GPIO_OFF 0 -#define CURRENT_GATE_GPIO_ON 1 -#define CURRENT_GATE_ZVPORT 5:5 -#define CURRENT_GATE_ZVPORT_OFF 0 -#define CURRENT_GATE_ZVPORT_ON 1 -#define CURRENT_GATE_CSC 4:4 -#define CURRENT_GATE_CSC_OFF 0 -#define CURRENT_GATE_CSC_ON 1 -#define CURRENT_GATE_DE 3:3 -#define CURRENT_GATE_DE_OFF 0 -#define CURRENT_GATE_DE_ON 1 -#define CURRENT_GATE_DISPLAY 2:2 -#define CURRENT_GATE_DISPLAY_OFF 0 -#define CURRENT_GATE_DISPLAY_ON 1 -#define CURRENT_GATE_LOCALMEM 1:1 -#define CURRENT_GATE_LOCALMEM_OFF 0 -#define CURRENT_GATE_LOCALMEM_ON 1 -#define CURRENT_GATE_DMA 0:0 -#define CURRENT_GATE_DMA_OFF 0 -#define CURRENT_GATE_DMA_ON 1 +#define CURRENT_GATE_VGA BIT(10) +#define CURRENT_GATE_PWM BIT(9) +#define CURRENT_GATE_I2C BIT(8) +#define CURRENT_GATE_SSP BIT(7) +#define CURRENT_GATE_GPIO BIT(6) +#define CURRENT_GATE_ZVPORT BIT(5) +#define CURRENT_GATE_CSC BIT(4) +#define CURRENT_GATE_DE BIT(3) +#define CURRENT_GATE_DISPLAY BIT(2) +#define CURRENT_GATE_LOCALMEM BIT(1) +#define CURRENT_GATE_DMA BIT(0) #define MODE0_GATE 0x000044 #define MODE0_GATE_MCLK 15:14 -- cgit v1.2.3 From 19aa211387d195ff77699895d017688954402e6a Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:26 +0200 Subject: staging: sm750fb: set{Memory, Master}Clock: rename ulReg to reg Remove HungarianCamelCase notation Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index b11231ca1894..37c52a3f2d81 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -79,7 +79,7 @@ static void setChipClock(unsigned int frequency) static void setMemoryClock(unsigned int frequency) { - unsigned int ulReg, divisor; + unsigned int reg, divisor; /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */ if (getChipType() == SM750LE) @@ -95,24 +95,24 @@ static void setMemoryClock(unsigned int frequency) divisor = roundedDiv(get_mxclk_freq(), frequency); /* Set the corresponding divisor in the register. */ - ulReg = PEEK32(CURRENT_GATE); + reg = PEEK32(CURRENT_GATE); switch (divisor) { default: case 1: - ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_1); + reg = FIELD_SET(reg, CURRENT_GATE, M2XCLK, DIV_1); break; case 2: - ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_2); + reg = FIELD_SET(reg, CURRENT_GATE, M2XCLK, DIV_2); break; case 3: - ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_3); + reg = FIELD_SET(reg, CURRENT_GATE, M2XCLK, DIV_3); break; case 4: - ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_4); + reg = FIELD_SET(reg, CURRENT_GATE, M2XCLK, DIV_4); break; } - setCurrentGate(ulReg); + setCurrentGate(reg); } } @@ -126,7 +126,7 @@ static void setMemoryClock(unsigned int frequency) */ static void setMasterClock(unsigned int frequency) { - unsigned int ulReg, divisor; + unsigned int reg, divisor; /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */ if (getChipType() == SM750LE) @@ -142,24 +142,24 @@ static void setMasterClock(unsigned int frequency) divisor = roundedDiv(get_mxclk_freq(), frequency); /* Set the corresponding divisor in the register. */ - ulReg = PEEK32(CURRENT_GATE); + reg = PEEK32(CURRENT_GATE); switch (divisor) { default: case 3: - ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_3); + reg = FIELD_SET(reg, CURRENT_GATE, MCLK, DIV_3); break; case 4: - ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_4); + reg = FIELD_SET(reg, CURRENT_GATE, MCLK, DIV_4); break; case 6: - ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_6); + reg = FIELD_SET(reg, CURRENT_GATE, MCLK, DIV_6); break; case 8: - ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_8); + reg = FIELD_SET(reg, CURRENT_GATE, MCLK, DIV_8); break; } - setCurrentGate(ulReg); + setCurrentGate(reg); } } -- cgit v1.2.3 From 6e8aa4a1362f893ffd592a8d738d637d01d57261 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:27 +0200 Subject: staging: sm750fb: change definition of CURRENT_GATE multi-bit fields Use more straight-forward definitions for multi-bit fields of CURRENT_GATE register and use open-coded implementation for register manipulation. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 20 +++++++++---------- drivers/staging/sm750fb/ddk750_reg.h | 36 +++++++++++++++++------------------ 2 files changed, 28 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 37c52a3f2d81..1cf9d9a189e0 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -95,20 +95,20 @@ static void setMemoryClock(unsigned int frequency) divisor = roundedDiv(get_mxclk_freq(), frequency); /* Set the corresponding divisor in the register. */ - reg = PEEK32(CURRENT_GATE); + reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK; switch (divisor) { default: case 1: - reg = FIELD_SET(reg, CURRENT_GATE, M2XCLK, DIV_1); + reg |= CURRENT_GATE_M2XCLK_DIV_1; break; case 2: - reg = FIELD_SET(reg, CURRENT_GATE, M2XCLK, DIV_2); + reg |= CURRENT_GATE_M2XCLK_DIV_2; break; case 3: - reg = FIELD_SET(reg, CURRENT_GATE, M2XCLK, DIV_3); + reg |= CURRENT_GATE_M2XCLK_DIV_3; break; case 4: - reg = FIELD_SET(reg, CURRENT_GATE, M2XCLK, DIV_4); + reg |= CURRENT_GATE_M2XCLK_DIV_4; break; } @@ -142,20 +142,20 @@ static void setMasterClock(unsigned int frequency) divisor = roundedDiv(get_mxclk_freq(), frequency); /* Set the corresponding divisor in the register. */ - reg = PEEK32(CURRENT_GATE); + reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK; switch (divisor) { default: case 3: - reg = FIELD_SET(reg, CURRENT_GATE, MCLK, DIV_3); + reg |= CURRENT_GATE_MCLK_DIV_3; break; case 4: - reg = FIELD_SET(reg, CURRENT_GATE, MCLK, DIV_4); + reg |= CURRENT_GATE_MCLK_DIV_4; break; case 6: - reg = FIELD_SET(reg, CURRENT_GATE, MCLK, DIV_6); + reg |= CURRENT_GATE_MCLK_DIV_6; break; case 8: - reg = FIELD_SET(reg, CURRENT_GATE, MCLK, DIV_8); + reg |= CURRENT_GATE_MCLK_DIV_8; break; } diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index e3ca8326f96f..b4149cadc07d 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -391,29 +391,29 @@ #define INT_MASK_VGA_VSYNC_ENABLE 1 #define CURRENT_GATE 0x000040 -#define CURRENT_GATE_MCLK 15:14 +#define CURRENT_GATE_MCLK_MASK (0x3 << 14) #ifdef VALIDATION_CHIP - #define CURRENT_GATE_MCLK_112MHZ 0 - #define CURRENT_GATE_MCLK_84MHZ 1 - #define CURRENT_GATE_MCLK_56MHZ 2 - #define CURRENT_GATE_MCLK_42MHZ 3 + #define CURRENT_GATE_MCLK_112MHZ (0x0 << 14) + #define CURRENT_GATE_MCLK_84MHZ (0x1 << 14) + #define CURRENT_GATE_MCLK_56MHZ (0x2 << 14) + #define CURRENT_GATE_MCLK_42MHZ (0x3 << 14) #else - #define CURRENT_GATE_MCLK_DIV_3 0 - #define CURRENT_GATE_MCLK_DIV_4 1 - #define CURRENT_GATE_MCLK_DIV_6 2 - #define CURRENT_GATE_MCLK_DIV_8 3 + #define CURRENT_GATE_MCLK_DIV_3 (0x0 << 14) + #define CURRENT_GATE_MCLK_DIV_4 (0x1 << 14) + #define CURRENT_GATE_MCLK_DIV_6 (0x2 << 14) + #define CURRENT_GATE_MCLK_DIV_8 (0x3 << 14) #endif -#define CURRENT_GATE_M2XCLK 13:12 +#define CURRENT_GATE_M2XCLK_MASK (0x3 << 12) #ifdef VALIDATION_CHIP - #define CURRENT_GATE_M2XCLK_336MHZ 0 - #define CURRENT_GATE_M2XCLK_168MHZ 1 - #define CURRENT_GATE_M2XCLK_112MHZ 2 - #define CURRENT_GATE_M2XCLK_84MHZ 3 + #define CURRENT_GATE_M2XCLK_336MHZ (0x0 << 12) + #define CURRENT_GATE_M2XCLK_168MHZ (0x1 << 12) + #define CURRENT_GATE_M2XCLK_112MHZ (0x2 << 12) + #define CURRENT_GATE_M2XCLK_84MHZ (0x3 << 12) #else - #define CURRENT_GATE_M2XCLK_DIV_1 0 - #define CURRENT_GATE_M2XCLK_DIV_2 1 - #define CURRENT_GATE_M2XCLK_DIV_3 2 - #define CURRENT_GATE_M2XCLK_DIV_4 3 + #define CURRENT_GATE_M2XCLK_DIV_1 (0x0 << 12) + #define CURRENT_GATE_M2XCLK_DIV_2 (0x1 << 12) + #define CURRENT_GATE_M2XCLK_DIV_3 (0x2 << 12) + #define CURRENT_GATE_M2XCLK_DIV_4 (0x3 << 12) #endif #define CURRENT_GATE_VGA BIT(10) #define CURRENT_GATE_PWM BIT(9) -- cgit v1.2.3 From 05e9d9ea4474a082b5abe753bab72d43aaf0592d Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:28 +0200 Subject: staging: sm750fb: use BIT macro for MODE0_GATE single-bit fields Replace complex definition of MODE0_GATE register fields with BIT() macro and use open-coded implementation for register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 2 +- drivers/staging/sm750fb/ddk750_reg.h | 44 +++++++++-------------------------- 2 files changed, 12 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 1cf9d9a189e0..a9a8884bbcfd 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -174,7 +174,7 @@ unsigned int ddk750_getVMSize(void) /* for 750,always use power mode0*/ reg = PEEK32(MODE0_GATE); - reg = FIELD_SET(reg, MODE0_GATE, GPIO, ON); + reg |= MODE0_GATE_GPIO; POKE32(MODE0_GATE, reg); /* get frame buffer size from GPIO */ diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index b4149cadc07d..70b1567fba23 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -438,39 +438,17 @@ #define MODE0_GATE_M2XCLK_168MHZ 1 #define MODE0_GATE_M2XCLK_112MHZ 2 #define MODE0_GATE_M2XCLK_84MHZ 3 -#define MODE0_GATE_VGA 10:10 -#define MODE0_GATE_VGA_OFF 0 -#define MODE0_GATE_VGA_ON 1 -#define MODE0_GATE_PWM 9:9 -#define MODE0_GATE_PWM_OFF 0 -#define MODE0_GATE_PWM_ON 1 -#define MODE0_GATE_I2C 8:8 -#define MODE0_GATE_I2C_OFF 0 -#define MODE0_GATE_I2C_ON 1 -#define MODE0_GATE_SSP 7:7 -#define MODE0_GATE_SSP_OFF 0 -#define MODE0_GATE_SSP_ON 1 -#define MODE0_GATE_GPIO 6:6 -#define MODE0_GATE_GPIO_OFF 0 -#define MODE0_GATE_GPIO_ON 1 -#define MODE0_GATE_ZVPORT 5:5 -#define MODE0_GATE_ZVPORT_OFF 0 -#define MODE0_GATE_ZVPORT_ON 1 -#define MODE0_GATE_CSC 4:4 -#define MODE0_GATE_CSC_OFF 0 -#define MODE0_GATE_CSC_ON 1 -#define MODE0_GATE_DE 3:3 -#define MODE0_GATE_DE_OFF 0 -#define MODE0_GATE_DE_ON 1 -#define MODE0_GATE_DISPLAY 2:2 -#define MODE0_GATE_DISPLAY_OFF 0 -#define MODE0_GATE_DISPLAY_ON 1 -#define MODE0_GATE_LOCALMEM 1:1 -#define MODE0_GATE_LOCALMEM_OFF 0 -#define MODE0_GATE_LOCALMEM_ON 1 -#define MODE0_GATE_DMA 0:0 -#define MODE0_GATE_DMA_OFF 0 -#define MODE0_GATE_DMA_ON 1 +#define MODE0_GATE_VGA BIT(10) +#define MODE0_GATE_PWM BIT(9) +#define MODE0_GATE_I2C BIT(8) +#define MODE0_GATE_SSP BIT(7) +#define MODE0_GATE_GPIO BIT(6) +#define MODE0_GATE_ZVPORT BIT(5) +#define MODE0_GATE_CSC BIT(4) +#define MODE0_GATE_DE BIT(3) +#define MODE0_GATE_DISPLAY BIT(2) +#define MODE0_GATE_LOCALMEM BIT(1) +#define MODE0_GATE_DMA BIT(0) #define MODE1_GATE 0x000048 #define MODE1_GATE_MCLK 15:14 -- cgit v1.2.3 From a941245109ff133f715af9a9b9a55be09e89dda1 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:29 +0200 Subject: staging: sm750fb: change definition of MODE0_GATE multi-bit fields Use more straight-forward definitions for multi-bit fields of MODE0_GATE register. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 70b1567fba23..d97859a0fa7b 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -428,16 +428,16 @@ #define CURRENT_GATE_DMA BIT(0) #define MODE0_GATE 0x000044 -#define MODE0_GATE_MCLK 15:14 -#define MODE0_GATE_MCLK_112MHZ 0 -#define MODE0_GATE_MCLK_84MHZ 1 -#define MODE0_GATE_MCLK_56MHZ 2 -#define MODE0_GATE_MCLK_42MHZ 3 -#define MODE0_GATE_M2XCLK 13:12 -#define MODE0_GATE_M2XCLK_336MHZ 0 -#define MODE0_GATE_M2XCLK_168MHZ 1 -#define MODE0_GATE_M2XCLK_112MHZ 2 -#define MODE0_GATE_M2XCLK_84MHZ 3 +#define MODE0_GATE_MCLK_MASK (0x3 << 14) +#define MODE0_GATE_MCLK_112MHZ (0x0 << 14) +#define MODE0_GATE_MCLK_84MHZ (0x1 << 14) +#define MODE0_GATE_MCLK_56MHZ (0x2 << 14) +#define MODE0_GATE_MCLK_42MHZ (0x3 << 14) +#define MODE0_GATE_M2XCLK_MASK (0x3 << 12) +#define MODE0_GATE_M2XCLK_336MHZ (0x0 << 12) +#define MODE0_GATE_M2XCLK_168MHZ (0x1 << 12) +#define MODE0_GATE_M2XCLK_112MHZ (0x2 << 12) +#define MODE0_GATE_M2XCLK_84MHZ (0x3 << 12) #define MODE0_GATE_VGA BIT(10) #define MODE0_GATE_PWM BIT(9) #define MODE0_GATE_I2C BIT(8) -- cgit v1.2.3 From 776980cf0f8cd3c8e5863ec92bccb8e670e3efa1 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:30 +0200 Subject: staging: sm750fb: use BIT macro for POWER_MODE_CTRL single-bit fields Replace complex definition of POWER_MODE_CTRL register fields with BIT() macro and use open-coded implementation for register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_power.c | 10 ++++------ drivers/staging/sm750fb/ddk750_reg.h | 12 +++--------- 2 files changed, 7 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index 417702548f0f..4959482cbeb5 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -60,17 +60,15 @@ void setPowerMode(unsigned int powerMode) /* Set up other fields in Power Control Register */ if (powerMode == POWER_MODE_CTRL_MODE_SLEEP) { - control_value = + control_value &= ~POWER_MODE_CTRL_OSC_INPUT; #ifdef VALIDATION_CHIP - FIELD_SET(control_value, POWER_MODE_CTRL, 336CLK, OFF) | + control_value &= ~POWER_MODE_CTRL_336CLK; #endif - FIELD_SET(control_value, POWER_MODE_CTRL, OSC_INPUT, OFF); } else { - control_value = + control_value |= POWER_MODE_CTRL_OSC_INPUT; #ifdef VALIDATION_CHIP - FIELD_SET(control_value, POWER_MODE_CTRL, 336CLK, ON) | + control_value |= POWER_MODE_CTRL_336CLK; #endif - FIELD_SET(control_value, POWER_MODE_CTRL, OSC_INPUT, ON); } /* Program new power mode. */ diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index d97859a0fa7b..bc49b44c611d 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -497,16 +497,10 @@ #define POWER_MODE_CTRL 0x00004C #ifdef VALIDATION_CHIP - #define POWER_MODE_CTRL_336CLK 4:4 - #define POWER_MODE_CTRL_336CLK_OFF 0 - #define POWER_MODE_CTRL_336CLK_ON 1 + #define POWER_MODE_CTRL_336CLK BIT(4) #endif -#define POWER_MODE_CTRL_OSC_INPUT 3:3 -#define POWER_MODE_CTRL_OSC_INPUT_OFF 0 -#define POWER_MODE_CTRL_OSC_INPUT_ON 1 -#define POWER_MODE_CTRL_ACPI 2:2 -#define POWER_MODE_CTRL_ACPI_OFF 0 -#define POWER_MODE_CTRL_ACPI_ON 1 +#define POWER_MODE_CTRL_OSC_INPUT BIT(3) +#define POWER_MODE_CTRL_ACPI BIT(2) #define POWER_MODE_CTRL_MODE 1:0 #define POWER_MODE_CTRL_MODE_MODE0 0 #define POWER_MODE_CTRL_MODE_MODE1 1 -- cgit v1.2.3 From f41b17fc3f124729e0778f64ba2039f4b71b0fc6 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:31 +0200 Subject: staging: sm750fb: change definition of POWER_MODE_CTRL multi-bit field Use more straight-forward definitions for multi-bit field of POWER_MODE_CTRL register and use open-coded implementation for register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_power.c | 13 +++++-------- drivers/staging/sm750fb/ddk750_reg.h | 8 ++++---- 2 files changed, 9 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index 4959482cbeb5..c85dfc509b04 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -21,7 +21,7 @@ static unsigned int getPowerMode(void) { if (getChipType() == SM750LE) return 0; - return FIELD_GET(PEEK32(POWER_MODE_CTRL), POWER_MODE_CTRL, MODE); + return PEEK32(POWER_MODE_CTRL) & POWER_MODE_CTRL_MODE_MASK; } @@ -33,25 +33,22 @@ void setPowerMode(unsigned int powerMode) { unsigned int control_value = 0; - control_value = PEEK32(POWER_MODE_CTRL); + control_value = PEEK32(POWER_MODE_CTRL) & ~POWER_MODE_CTRL_MODE_MASK; if (getChipType() == SM750LE) return; switch (powerMode) { case POWER_MODE_CTRL_MODE_MODE0: - control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, - MODE0); + control_value |= POWER_MODE_CTRL_MODE_MODE0; break; case POWER_MODE_CTRL_MODE_MODE1: - control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, - MODE1); + control_value |= POWER_MODE_CTRL_MODE_MODE1; break; case POWER_MODE_CTRL_MODE_SLEEP: - control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, - SLEEP); + control_value |= POWER_MODE_CTRL_MODE_SLEEP; break; default: diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index bc49b44c611d..a90b56f55f1e 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -501,10 +501,10 @@ #endif #define POWER_MODE_CTRL_OSC_INPUT BIT(3) #define POWER_MODE_CTRL_ACPI BIT(2) -#define POWER_MODE_CTRL_MODE 1:0 -#define POWER_MODE_CTRL_MODE_MODE0 0 -#define POWER_MODE_CTRL_MODE_MODE1 1 -#define POWER_MODE_CTRL_MODE_SLEEP 2 +#define POWER_MODE_CTRL_MODE_MASK (0x3 << 0) +#define POWER_MODE_CTRL_MODE_MODE0 (0x0 << 0) +#define POWER_MODE_CTRL_MODE_MODE1 (0x1 << 0) +#define POWER_MODE_CTRL_MODE_SLEEP (0x2 << 0) #define PCI_MASTER_BASE 0x000050 #define PCI_MASTER_BASE_ADDRESS 7:0 -- cgit v1.2.3 From 04c73f28967423f2b68f80df1149cf5d2e85c1f5 Mon Sep 17 00:00:00 2001 From: Othmar Pasteka Date: Sun, 8 Nov 2015 11:58:51 +0100 Subject: staging: sm750fb: fix style for if clause Fix for checkpatch.pl complaints: ERROR: that open brace { should be on the previous line CHECK: spaces preferred around that '+' (ctx:VxV) Signed-off-by: Othmar Pasteka Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750_cursor.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/sm750_cursor.c b/drivers/staging/sm750fb/sm750_cursor.c index 3b7ce9275f51..0a41585535a6 100644 --- a/drivers/staging/sm750fb/sm750_cursor.c +++ b/drivers/staging/sm750fb/sm750_cursor.c @@ -143,8 +143,7 @@ void hw_cursor_setData(struct lynx_cursor *cursor, iowrite16(data, pbuffer); /* assume pitch is 1,2,4,8,...*/ - if ((i+1) % pitch == 0) - { + if ((i + 1) % pitch == 0) { /* need a return */ pstart += offset; pbuffer = pstart; -- cgit v1.2.3 From fe7185908a4e981ae484043806a4f24d6cf09e91 Mon Sep 17 00:00:00 2001 From: Bogicevic Sasa Date: Wed, 25 Nov 2015 22:56:30 +0100 Subject: drivers:staging:sm750fb Fix all space preferred around messages This fixes all messages from checkpatch.pl about space preferred Signed-off-by: Bogicevic Sasa Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_mode.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index fa35926680ab..0fd34fa93a41 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -30,8 +30,8 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, | FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, LEFT, 0)); POKE32(CRT_AUTO_CENTERING_BR, - FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, BOTTOM, y-1) - | FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, RIGHT, x-1)); + FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, BOTTOM, y - 1) + | FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, RIGHT, x - 1)); /* Assume common fields in dispControl have been properly set before calling this function. @@ -101,9 +101,9 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) | FIELD_VALUE(0, CRT_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1)); - ulTmpValue = FIELD_VALUE(0, CRT_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity)| - FIELD_VALUE(0, CRT_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity)| - FIELD_SET(0, CRT_DISPLAY_CTRL, TIMING, ENABLE)| + ulTmpValue = FIELD_VALUE(0, CRT_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity) | + FIELD_VALUE(0, CRT_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity) | + FIELD_SET(0, CRT_DISPLAY_CTRL, TIMING, ENABLE) | FIELD_SET(0, CRT_DISPLAY_CTRL, PLANE, ENABLE); @@ -116,7 +116,7 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) & FIELD_CLEAR(CRT_DISPLAY_CTRL, TIMING) & FIELD_CLEAR(CRT_DISPLAY_CTRL, PLANE); - POKE32(CRT_DISPLAY_CTRL, ulTmpValue|ulReg); + POKE32(CRT_DISPLAY_CTRL, ulTmpValue | ulReg); } } else if (pll->clockType == PRIMARY_PLL) { @@ -140,15 +140,15 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) FIELD_VALUE(0, PANEL_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height) | FIELD_VALUE(0, PANEL_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1)); - ulTmpValue = FIELD_VALUE(0, PANEL_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity)| - FIELD_VALUE(0, PANEL_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity)| - FIELD_VALUE(0, PANEL_DISPLAY_CTRL, CLOCK_PHASE, pModeParam->clock_phase_polarity)| - FIELD_SET(0, PANEL_DISPLAY_CTRL, TIMING, ENABLE)| + ulTmpValue = FIELD_VALUE(0, PANEL_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity) | + FIELD_VALUE(0, PANEL_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity) | + FIELD_VALUE(0, PANEL_DISPLAY_CTRL, CLOCK_PHASE, pModeParam->clock_phase_polarity) | + FIELD_SET(0, PANEL_DISPLAY_CTRL, TIMING, ENABLE) | FIELD_SET(0, PANEL_DISPLAY_CTRL, PLANE, ENABLE); ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) | FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) | - FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE)| + FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE) | FIELD_SET(0, PANEL_DISPLAY_CTRL, VSYNC, ACTIVE_LOW); ulReg = (PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) @@ -167,13 +167,13 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) * next vertical sync to turn on/off the plane. */ - POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg); + POKE32(PANEL_DISPLAY_CTRL, ulTmpValue | ulReg); - while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg)) { + while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue | ulReg)) { cnt++; if (cnt > 1000) break; - POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg); + POKE32(PANEL_DISPLAY_CTRL, ulTmpValue | ulReg); } } else { ret = -1; -- cgit v1.2.3 From fbb8c963573926bceb5c59e2a7d74e5ce7669e78 Mon Sep 17 00:00:00 2001 From: Matej Vasek Date: Mon, 25 Jan 2016 16:02:33 +0100 Subject: staging: sm750fb, fix typos The code contained typos like "structur", "fointers", etc. Fix that. No code change, only comments. Signed-off-by: Matej Vasek Cc: Sudip Mukherjee Cc: Teddy Wang Cc: Greg Kroah-Hartman Cc: Cc: Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_hwi2c.c | 4 ++-- drivers/staging/sm750fb/ddk750_mode.c | 2 +- drivers/staging/sm750fb/ddk750_sii164.h | 5 ++++- drivers/staging/sm750fb/sm750.c | 2 +- drivers/staging/sm750fb/sm750.h | 2 +- drivers/staging/sm750fb/sm750_accel.c | 4 ++-- drivers/staging/sm750fb/sm750_accel.h | 2 +- drivers/staging/sm750fb/sm750_hw.c | 2 +- 8 files changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/ddk750_hwi2c.c b/drivers/staging/sm750fb/ddk750_hwi2c.c index b824681e55a7..40253bd8cf2a 100644 --- a/drivers/staging/sm750fb/ddk750_hwi2c.c +++ b/drivers/staging/sm750fb/ddk750_hwi2c.c @@ -127,7 +127,7 @@ static unsigned int hw_i2c_write_data( if (hw_i2c_wait_tx_done() != 0) break; - /* Substract length */ + /* Subtract length */ length -= (count + 1); /* Total byte written */ @@ -194,7 +194,7 @@ static unsigned int hw_i2c_read_data( for (i = 0; i <= count; i++) *buf++ = PEEK32(I2C_DATA0 + i); - /* Substract length by 16 */ + /* Subtract length by 16 */ length -= (count + 1); /* Number of bytes read. */ diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index 0fd34fa93a41..d0e3935654ff 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -42,7 +42,7 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, dispControl &= FIELD_CLEAR(CRT_DISPLAY_CTRL, CLK); /* Set bit 29:27 of display control register for the right clock */ - /* Note that SM750LE only need to supported 7 resoluitons. */ + /* Note that SM750LE only need to supported 7 resolutions. */ if (x == 800 && y == 600) dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL41); else if (x == 1024 && y == 768) diff --git a/drivers/staging/sm750fb/ddk750_sii164.h b/drivers/staging/sm750fb/ddk750_sii164.h index f2610c90eeb4..664ad089f753 100644 --- a/drivers/staging/sm750fb/ddk750_sii164.h +++ b/drivers/staging/sm750fb/ddk750_sii164.h @@ -39,7 +39,10 @@ unsigned char sii164IsConnected(void); unsigned char sii164CheckInterrupt(void); void sii164ClearInterrupt(void); #endif -/* below register definination is used for Silicon Image SiI164 DVI controller chip */ +/* + * below register definition is used for + * Silicon Image SiI164 DVI controller chip + */ /* * Vendor ID registers */ diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index 2ae2a522136f..c9d4871cd62d 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -319,7 +319,7 @@ static int lynxfb_ops_set_par(struct fb_info *info) var = &info->var; fix = &info->fix; - /* fix structur is not so FIX ... */ + /* fix structure is not so FIX ... */ line_length = var->xres_virtual * var->bits_per_pixel / 8; line_length = ALIGN(line_length, crtc->line_pad); fix->line_length = line_length; diff --git a/drivers/staging/sm750fb/sm750.h b/drivers/staging/sm750fb/sm750.h index fddffac6930f..8e70ce0d6da4 100644 --- a/drivers/staging/sm750fb/sm750.h +++ b/drivers/staging/sm750fb/sm750.h @@ -53,7 +53,7 @@ struct lynx_accel { /* base virtual address of de data port */ volatile unsigned char __iomem *dpPortBase; - /* function fointers */ + /* function pointers */ void (*de_init)(struct lynx_accel *); int (*de_wait)(void);/* see if hardware ready to work */ diff --git a/drivers/staging/sm750fb/sm750_accel.c b/drivers/staging/sm750fb/sm750_accel.c index 43e59725920c..e150680a8cd1 100644 --- a/drivers/staging/sm750fb/sm750_accel.c +++ b/drivers/staging/sm750fb/sm750_accel.c @@ -53,7 +53,7 @@ void hw_de_init(struct lynx_accel *accel) FIELD_CLEAR(DE_STRETCH_FORMAT, ADDRESSING)& FIELD_CLEAR(DE_STRETCH_FORMAT, SOURCE_HEIGHT); - /* DE_STRETCH bpp format need be initilized in setMode routine */ + /* DE_STRETCH bpp format need be initialized in setMode routine */ write_dpr(accel, DE_STRETCH_FORMAT, (read_dpr(accel, DE_STRETCH_FORMAT) & clr) | reg); /* disable clipping and transparent */ @@ -305,7 +305,7 @@ int hw_imageblit(struct lynx_accel *accel, u32 dx, u32 dy, /* Starting coordinate of destination surface */ u32 width, - u32 height, /* width and height of rectange in pixel value */ + u32 height, /* width and height of rectangle in pixel value */ u32 fColor, /* Foreground color (corresponding to a 1 in the monochrome data */ u32 bColor, /* Background color (corresponding to a 0 in the monochrome data */ u32 rop2) /* ROP value */ diff --git a/drivers/staging/sm750fb/sm750_accel.h b/drivers/staging/sm750fb/sm750_accel.h index f252e47d5ee9..1ec66d28f456 100644 --- a/drivers/staging/sm750fb/sm750_accel.h +++ b/drivers/staging/sm750fb/sm750_accel.h @@ -268,7 +268,7 @@ int hw_imageblit(struct lynx_accel *accel, u32 dx, u32 dy, /* Starting coordinate of destination surface */ u32 width, - u32 height, /* width and height of rectange in pixel value */ + u32 height, /* width and height of rectangle in pixel value */ u32 fColor, /* Foreground color (corresponding to a 1 in the monochrome data */ u32 bColor, /* Background color (corresponding to a 0 in the monochrome data */ u32 rop2); diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index b33ec076f3f5..c0c2f1c4de82 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -142,7 +142,7 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) break; } } else { - /* for 750LE ,no DVI chip initilization makes Monitor no signal */ + /* for 750LE ,no DVI chip initialization makes Monitor no signal */ /* Set up GPIO for software I2C to program DVI chip in the Xilinx SP605 board, in order to have video signal. */ -- cgit v1.2.3 From 8891bcac17da0a7233a46266c57cf9934d39f919 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 2 Dec 2015 22:54:00 +0100 Subject: staging: rtl8188eu: add spaces around binary '*' Fix checkpatch issue: CHECK: spaces preferred around that '*' (ctx:VxV) Signed-off-by: Luca Ceresoli Cc: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_efuse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index 2320fb11af24..169bb693b75f 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -500,8 +500,8 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) if (offset > max_section) return false; - memset((void *)data, 0xff, sizeof(u8)*PGPKT_DATA_SIZE); - memset((void *)tmpdata, 0xff, sizeof(u8)*PGPKT_DATA_SIZE); + memset((void *)data, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); + memset((void *)tmpdata, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); /* Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */ /* Skip dummy parts to prevent unexpected data read from Efuse. */ -- cgit v1.2.3 From d0beccb04e9670d97ef91c1141bfad8f41801183 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 2 Dec 2015 22:54:01 +0100 Subject: staging: rtl8188eu: don't cast to void* when calling memset() The first argument to memset() is (void *), the explicit typecasts are not needed. They just make code less readable. Signed-off-by: Luca Ceresoli Cc: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_ap.c | 4 ++-- drivers/staging/rtl8188eu/core/rtw_efuse.c | 8 ++++---- drivers/staging/rtl8188eu/core/rtw_security.c | 28 +++++++++++++-------------- 3 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index e5d29fe9d446..79d326ae18fe 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -569,7 +569,7 @@ static void update_bmc_sta(struct adapter *padapter) psta->ieee8021x_blocked = 0; - memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); + memset(&psta->sta_stats, 0, sizeof(struct stainfo_stats)); /* prepare for add_RATid */ supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->SupportedRates); @@ -692,7 +692,7 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta) /* todo: init other variables */ - memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); + memset(&psta->sta_stats, 0, sizeof(struct stainfo_stats)); spin_lock_bh(&psta->lock); psta->state |= _FW_LINKED; diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index 169bb693b75f..fd8cf472e8dc 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -394,7 +394,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e u8 badworden = 0x0F; u8 tmpdata[8]; - memset((void *)tmpdata, 0xff, PGPKT_DATA_SIZE); + memset(tmpdata, 0xff, PGPKT_DATA_SIZE); if (!(word_en & BIT(0))) { tmpaddr = start_addr; @@ -500,8 +500,8 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) if (offset > max_section) return false; - memset((void *)data, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); - memset((void *)tmpdata, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); + memset(data, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); + memset(tmpdata, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); /* Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */ /* Skip dummy parts to prevent unexpected data read from Efuse. */ @@ -572,7 +572,7 @@ static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, st u16 efuse_addr = *pAddr; u32 PgWriteSuccess = 0; - memset((void *)originaldata, 0xff, 8); + memset(originaldata, 0xff, 8); if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata)) { /* check if data exist */ diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c index 22839d57dc8c..b781ccf45bc0 100644 --- a/drivers/staging/rtl8188eu/core/rtw_security.c +++ b/drivers/staging/rtl8188eu/core/rtw_security.c @@ -1081,13 +1081,13 @@ static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen) frsubtype >>= 4; - memset((void *)mic_iv, 0, 16); - memset((void *)mic_header1, 0, 16); - memset((void *)mic_header2, 0, 16); - memset((void *)ctr_preload, 0, 16); - memset((void *)chain_buffer, 0, 16); - memset((void *)aes_out, 0, 16); - memset((void *)padded_buffer, 0, 16); + memset(mic_iv, 0, 16); + memset(mic_header1, 0, 16); + memset(mic_header2, 0, 16); + memset(ctr_preload, 0, 16); + memset(chain_buffer, 0, 16); + memset(aes_out, 0, 16); + memset(padded_buffer, 0, 16); if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN)) a4_exists = 0; @@ -1279,13 +1279,13 @@ static int aes_decipher(u8 *key, uint hdrlen, uint frsubtype = GetFrameSubType(pframe); frsubtype >>= 4; - memset((void *)mic_iv, 0, 16); - memset((void *)mic_header1, 0, 16); - memset((void *)mic_header2, 0, 16); - memset((void *)ctr_preload, 0, 16); - memset((void *)chain_buffer, 0, 16); - memset((void *)aes_out, 0, 16); - memset((void *)padded_buffer, 0, 16); + memset(mic_iv, 0, 16); + memset(mic_header1, 0, 16); + memset(mic_header2, 0, 16); + memset(ctr_preload, 0, 16); + memset(chain_buffer, 0, 16); + memset(aes_out, 0, 16); + memset(padded_buffer, 0, 16); /* start to decrypt the payload */ -- cgit v1.2.3 From 329862549c0f2b8df352b3f23fef0fe1760ffbc5 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 2 Dec 2015 22:54:02 +0100 Subject: staging: rtl8188eu: rtw_mlme_ext.c: remove commented code This line is connented since the initial import in commit 7b464c9fa5cc ("staging: r8188eu: Add files for new driver - part 4") and there's no comment stating how it could ever be useful. Signed-off-by: Luca Ceresoli Cc: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 3eca6874b6df..09092bdcf7e4 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -1673,7 +1673,6 @@ static void issue_action_BA(struct adapter *padapter, unsigned char *raddr, fctrl = &(pwlanhdr->frame_ctl); *(fctrl) = 0; - /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */ memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); -- cgit v1.2.3 From f0f17bed9a06edb82714ed2400aa511e66290ee9 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 2 Dec 2015 22:54:03 +0100 Subject: staging: rtl8188eu: remove useless variable rtw_AcceptAddbaReq rtw_AcceptAddbaReq is a static variable, it is set once and never modified. It is referenced only once, to assign its value to a member of struct registry_priv with practically the same name. Get rid of the variable, and move the meaningful part of the comment near the declaration of the relevant field of struct registry_priv. Raises a new checkpatch issue, which is fixed in a later commit: CHECK: Avoid CamelCase: Signed-off-by: Luca Ceresoli Cc: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/include/drv_types.h | 2 +- drivers/staging/rtl8188eu/os_dep/os_intfs.c | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 0729bd40b02a..65e82aa04119 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -110,7 +110,7 @@ struct registry_priv { u8 wifi_spec;/* !turbo_mode */ u8 channel_plan; - bool bAcceptAddbaReq; + bool bAcceptAddbaReq; /* true = accept AP's Add BA req */ u8 antdiv_cfg; u8 antdiv_type; diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 9201b94d017c..90b5ea233e84 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -101,8 +101,6 @@ static int rtw_rf_config = RF_819X_MAX_TYPE; /* auto */ static int rtw_low_power; static int rtw_wifi_spec; static int rtw_channel_plan = RT_CHANNEL_DOMAIN_MAX; -/* 0:Reject AP's Add BA req, 1:Accept AP's Add BA req. */ -static int rtw_AcceptAddbaReq = true; static int rtw_antdiv_cfg = 2; /* 0:OFF , 1:ON, 2:decide by Efuse config */ @@ -593,7 +591,7 @@ static void loadparam(struct adapter *padapter, struct net_device *pnetdev) registry_par->low_power = (u8)rtw_low_power; registry_par->wifi_spec = (u8)rtw_wifi_spec; registry_par->channel_plan = (u8)rtw_channel_plan; - registry_par->bAcceptAddbaReq = (u8)rtw_AcceptAddbaReq; + registry_par->bAcceptAddbaReq = true; registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg; registry_par->antdiv_type = (u8)rtw_antdiv_type; registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode; -- cgit v1.2.3 From d6c6ad96119d8bcb3020ef33ec99179b74423cea Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 2 Dec 2015 22:54:04 +0100 Subject: staging: rtl8188eu: rename camelcase bAcceptAddbaReq There is such a field both in struct mlme_ext_info and in struct registry_priv. Rename both. Also fix checkpatch issue in the lines touched: WARNING: line over 80 characters Signed-off-by: Luca Ceresoli Cc: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 4 ++-- drivers/staging/rtl8188eu/core/rtw_wlan_util.c | 3 ++- drivers/staging/rtl8188eu/include/drv_types.h | 2 +- drivers/staging/rtl8188eu/include/rtw_mlme_ext.h | 2 +- drivers/staging/rtl8188eu/os_dep/os_intfs.c | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 09092bdcf7e4..31faa266bf6b 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -3739,7 +3739,7 @@ static unsigned int OnAction_back(struct adapter *padapter, memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request)); process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr); - if (pmlmeinfo->bAcceptAddbaReq) + if (pmlmeinfo->accept_addba_req) issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0); else issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */ @@ -4149,7 +4149,7 @@ int init_mlme_ext_priv(struct adapter *padapter) pmlmeext->padapter = padapter; init_mlme_ext_priv_value(padapter); - pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq; + pmlmeinfo->accept_addba_req = pregistrypriv->accept_addba_req; init_mlme_ext_timer(padapter); diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 59b443255a90..7d85ad1d7e02 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -1579,7 +1579,8 @@ void process_addba_req(struct adapter *padapter, u8 *paddba_req, u8 *addr) tid = (param>>2)&0x0f; preorder_ctrl = &psta->recvreorder_ctrl[tid]; preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->enable = (pmlmeinfo->bAcceptAddbaReq) ? true : false; + preorder_ctrl->enable = (pmlmeinfo->accept_addba_req) ? true + : false; } } diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 65e82aa04119..aeaf5f7e1f01 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -110,7 +110,7 @@ struct registry_priv { u8 wifi_spec;/* !turbo_mode */ u8 channel_plan; - bool bAcceptAddbaReq; /* true = accept AP's Add BA req */ + bool accept_addba_req; /* true = accept AP's Add BA req */ u8 antdiv_cfg; u8 antdiv_type; diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index 9093a5f94d32..44711332b90c 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -348,7 +348,7 @@ struct mlme_ext_info { u8 candidate_tid_bitmap; u8 dialogToken; /* Accept ADDBA Request */ - bool bAcceptAddbaReq; + bool accept_addba_req; u8 bwmode_updated; u8 hidden_ssid_mode; diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 90b5ea233e84..3b25acf882a3 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -591,7 +591,7 @@ static void loadparam(struct adapter *padapter, struct net_device *pnetdev) registry_par->low_power = (u8)rtw_low_power; registry_par->wifi_spec = (u8)rtw_wifi_spec; registry_par->channel_plan = (u8)rtw_channel_plan; - registry_par->bAcceptAddbaReq = true; + registry_par->accept_addba_req = true; registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg; registry_par->antdiv_type = (u8)rtw_antdiv_type; registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode; -- cgit v1.2.3 From 35ad45a1992d43920968718f606a1ce3d9a86074 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 2 Dec 2015 22:54:05 +0100 Subject: staging: rtl8188eu: rtw_mlme_ext.c: simplify call to issue_action_BA() Using the ternary operator allows to more concisely write the same code, and to stay within 80 characters without even increasing the number of lines. Signed-off-by: Luca Ceresoli Cc: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 31faa266bf6b..e6020265d6de 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -3739,10 +3739,10 @@ static unsigned int OnAction_back(struct adapter *padapter, memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request)); process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr); - if (pmlmeinfo->accept_addba_req) - issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0); - else - issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */ + /* 37 = reject ADDBA Req */ + issue_action_BA(padapter, addr, + RTW_WLAN_ACTION_ADDBA_RESP, + pmlmeinfo->accept_addba_req ? 0 : 37); break; case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */ status = get_unaligned_le16(&frame_body[3]); -- cgit v1.2.3 From b0800a4bd9f366ebac393fe3982f0140ca120487 Mon Sep 17 00:00:00 2001 From: Alexey Tulia Date: Sat, 21 Nov 2015 13:06:37 +0300 Subject: staging: rtl8188eu: remove an extra space drivers/staging/rtl8188eu/core/rtw_wlan_util.c:1377 check_assoc_AP() warn: inconsistent indenting Signed-off-by: Alexey Tulia Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_wlan_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 7d85ad1d7e02..83096696cd5b 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -1374,7 +1374,7 @@ unsigned char check_assoc_AP(u8 *pframe, uint len) epigram_vendor_flag = 1; if (ralink_vendor_flag) { DBG_88E("link to Tenda W311R AP\n"); - return HT_IOT_PEER_TENDA; + return HT_IOT_PEER_TENDA; } else { DBG_88E("Capture EPIGRAM_OUI\n"); } -- cgit v1.2.3 From 5fa0e06d7ae2a0f62886bfe65273638951ee796a Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Mon, 7 Dec 2015 22:02:27 +0000 Subject: Staging: rtl8188eu: core: rtw_debug: fixed a parentheses coding style issue Removed unnecessary parentheses. Signed-off-by: Chris Elliott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_debug.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_debug.c b/drivers/staging/rtl8188eu/core/rtw_debug.c index 2c4afb80fc64..93e898d598fe 100644 --- a/drivers/staging/rtl8188eu/core/rtw_debug.c +++ b/drivers/staging/rtl8188eu/core/rtw_debug.c @@ -149,7 +149,7 @@ int proc_get_fwstate(char *page, char **start, { struct net_device *dev = data; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; int len = 0; @@ -184,7 +184,7 @@ int proc_get_mlmext_state(char *page, char **start, struct net_device *dev = data; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; int len = 0; @@ -200,7 +200,7 @@ int proc_get_qos_option(char *page, char **start, { struct net_device *dev = data; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; int len = 0; @@ -216,7 +216,7 @@ int proc_get_ht_option(char *page, char **start, { struct net_device *dev = data; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; int len = 0; @@ -247,9 +247,9 @@ int proc_get_ap_info(char *page, char **start, struct sta_info *psta; struct net_device *dev = data; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wlan_network *cur_network = &(pmlmepriv->cur_network); + struct wlan_network *cur_network = &pmlmepriv->cur_network; struct sta_priv *pstapriv = &padapter->stapriv; int len = 0; @@ -851,7 +851,7 @@ int proc_get_all_sta_info(char *page, char **start, spin_lock_bh(&pstapriv->sta_hash_lock); for (i = 0; i < NUM_STA; i++) { - phead = &(pstapriv->sta_hash[i]); + phead = &pstapriv->sta_hash[i]; plist = phead->next; while (phead != plist) { -- cgit v1.2.3 From 6d7b2801446b5e6e52606eac715db9a337fb899e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 10 Dec 2015 17:43:53 +0200 Subject: staging: rtl8188eu: provide an absolute path to include folder Otherwise compiler will complain as follows CC [M] drivers/staging/rtl8188eu/core/rtw_ap.o cc1: warning: drivers/staging/rtl8188eu/include: No such file or directory [-Wmissing-include-dirs] Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/Makefile b/drivers/staging/rtl8188eu/Makefile index ed723585b502..29b9834870fd 100644 --- a/drivers/staging/rtl8188eu/Makefile +++ b/drivers/staging/rtl8188eu/Makefile @@ -53,4 +53,4 @@ r8188eu-y := \ obj-$(CONFIG_R8188EU) := r8188eu.o -ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/include +ccflags-y += -D__CHECK_ENDIAN__ -I$(srctree)/$(src)/include -- cgit v1.2.3 From fb27e19c08f89426112dad291412bf89c287a68c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 10 Dec 2015 17:43:54 +0200 Subject: staging: rtl8188eu: replace open-coded print_hex_dump() No need to reinvent a wheel, i.e. print_hex_dump(). Replace an open-coded variant by generic kernel helper. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_recv.c | 39 +++++++++++++------------------ 1 file changed, 16 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 110b8c0b6cd7..3f03999b4d22 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -1274,32 +1274,25 @@ static int validate_recv_frame(struct adapter *adapter, /* Dump rx packets */ rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt)); if (bDumpRxPkt == 1) {/* dump all rx packets */ - int i; - DBG_88E("#############################\n"); - - for (i = 0; i < 64; i += 8) - DBG_88E("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i), - *(ptr+i+1), *(ptr+i+2), *(ptr+i+3), *(ptr+i+4), *(ptr+i+5), *(ptr+i+6), *(ptr+i+7)); - DBG_88E("#############################\n"); + if (_drv_err_ <= GlobalDebugLevel) { + pr_info(DRIVER_PREFIX "#############################\n"); + print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE, + 16, 1, ptr, 64, false); + pr_info(DRIVER_PREFIX "#############################\n"); + } } else if (bDumpRxPkt == 2) { - if (type == WIFI_MGT_TYPE) { - int i; - DBG_88E("#############################\n"); - - for (i = 0; i < 64; i += 8) - DBG_88E("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i), - *(ptr+i+1), *(ptr+i+2), *(ptr+i+3), *(ptr+i+4), *(ptr+i+5), *(ptr+i+6), *(ptr+i+7)); - DBG_88E("#############################\n"); + if ((_drv_err_ <= GlobalDebugLevel) && (type == WIFI_MGT_TYPE)) { + pr_info(DRIVER_PREFIX "#############################\n"); + print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE, + 16, 1, ptr, 64, false); + pr_info(DRIVER_PREFIX "#############################\n"); } } else if (bDumpRxPkt == 3) { - if (type == WIFI_DATA_TYPE) { - int i; - DBG_88E("#############################\n"); - - for (i = 0; i < 64; i += 8) - DBG_88E("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i), - *(ptr+i+1), *(ptr+i+2), *(ptr+i+3), *(ptr+i+4), *(ptr+i+5), *(ptr+i+6), *(ptr+i+7)); - DBG_88E("#############################\n"); + if ((_drv_err_ <= GlobalDebugLevel) && (type == WIFI_DATA_TYPE)) { + pr_info(DRIVER_PREFIX "#############################\n"); + print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE, + 16, 1, ptr, 64, false); + pr_info(DRIVER_PREFIX "#############################\n"); } } switch (type) { -- cgit v1.2.3 From a67080ee826467cbcb9691418126607bb0d1e33e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 10 Dec 2015 17:43:55 +0200 Subject: staging: rtl8188eu: print OUI with %*ph There is no need to pass each byte as a parameter when printing values in hex format. We rather use %*ph specifier for that. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_ieee80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index 742b29c590df..aa7f5711a147 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -935,8 +935,8 @@ static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen, } break; default: - DBG_88E("unknown vendor specific information element ignored (vendor OUI %02x:%02x:%02x len=%lu)\n", - pos[0], pos[1], pos[2], (unsigned long)elen); + DBG_88E("unknown vendor specific information element ignored (vendor OUI %3phC len=%lu)\n", + pos, (unsigned long)elen); return -1; } return 0; -- cgit v1.2.3 From b9f1c275b695ff9339cfd0c2ea841f53d4205611 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Mon, 1 Feb 2016 22:37:13 +0800 Subject: staging: rtl8188eu: use list_first_entry_or_null() Use list_first_entry_or_null() instead of list_empty() + container_of() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_cmd.c | 12 +--- drivers/staging/rtl8188eu/core/rtw_mlme.c | 19 +++---- drivers/staging/rtl8188eu/core/rtw_recv.c | 15 ++--- drivers/staging/rtl8188eu/core/rtw_sta_mgt.c | 23 +++----- drivers/staging/rtl8188eu/core/rtw_xmit.c | 84 ++++++++-------------------- 5 files changed, 48 insertions(+), 105 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index 433b926ceae7..1de792905e82 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -69,23 +69,17 @@ exit: return _SUCCESS; } -struct cmd_obj *rtw_dequeue_cmd(struct __queue *queue) +struct cmd_obj *rtw_dequeue_cmd(struct __queue *queue) { unsigned long irqL; struct cmd_obj *obj; - spin_lock_irqsave(&queue->lock, irqL); - if (list_empty(&(queue->queue))) { - obj = NULL; - } else { - obj = container_of((&queue->queue)->next, struct cmd_obj, list); + obj = list_first_entry_or_null(&queue->queue, struct cmd_obj, list); + if (obj) list_del_init(&obj->list); - } - spin_unlock_irqrestore(&queue->lock, irqL); - return obj; } diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index abab854e6889..9c2e65904c0f 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -128,25 +128,22 @@ void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv) } } -struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv)/* _queue *free_queue) */ +struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv) + /* _queue *free_queue) */ { - struct wlan_network *pnetwork; + struct wlan_network *pnetwork; struct __queue *free_queue = &pmlmepriv->free_bss_pool; - struct list_head *plist = NULL; spin_lock_bh(&free_queue->lock); - - if (list_empty(&free_queue->queue)) { - pnetwork = NULL; + pnetwork = list_first_entry_or_null(&free_queue->queue, + struct wlan_network, list); + if (!pnetwork) goto exit; - } - plist = free_queue->queue.next; - - pnetwork = container_of(plist, struct wlan_network, list); list_del_init(&pnetwork->list); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("_rtw_alloc_network: ptr=%p\n", plist)); + RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, + ("_rtw_alloc_network: ptr=%p\n", &pnetwork->list)); pnetwork->network_type = 0; pnetwork->fixed = false; pnetwork->last_scanned = jiffies; diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 3f03999b4d22..c81639cae1ea 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -127,22 +127,15 @@ void _rtw_free_recv_priv(struct recv_priv *precvpriv) struct recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue) { struct recv_frame *hdr; - struct list_head *plist, *phead; struct adapter *padapter; struct recv_priv *precvpriv; - if (list_empty(&pfree_recv_queue->queue)) { - hdr = NULL; - } else { - phead = get_list_head(pfree_recv_queue); - - plist = phead->next; - - hdr = container_of(plist, struct recv_frame, list); - + hdr = list_first_entry_or_null(&pfree_recv_queue->queue, + struct recv_frame, list); + if (hdr) { list_del_init(&hdr->list); padapter = hdr->adapter; - if (padapter != NULL) { + if (padapter) { precvpriv = &padapter->recvpriv; if (pfree_recv_queue == &precvpriv->free_recv_queue) precvpriv->free_recvframe_cnt--; diff --git a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c index 1beeac46bfe7..ce655b6d9a23 100644 --- a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c +++ b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c @@ -179,9 +179,9 @@ u32 _rtw_free_sta_priv(struct sta_priv *pstapriv) return _SUCCESS; } -struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) +struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) { - s32 index; + s32 index; struct list_head *phash_list; struct sta_info *psta; struct __queue *pfree_sta_queue; @@ -189,17 +189,15 @@ struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) int i = 0; u16 wRxSeqInitialValue = 0xffff; - pfree_sta_queue = &pstapriv->free_sta_queue; - spin_lock_bh(&(pfree_sta_queue->lock)); - - if (list_empty(&pfree_sta_queue->queue)) { + spin_lock_bh(&pfree_sta_queue->lock); + psta = list_first_entry_or_null(&pfree_sta_queue->queue, + struct sta_info, list); + if (!psta) { spin_unlock_bh(&pfree_sta_queue->lock); - psta = NULL; } else { - psta = container_of((&pfree_sta_queue->queue)->next, struct sta_info, list); - list_del_init(&(psta->list)); + list_del_init(&psta->list); spin_unlock_bh(&pfree_sta_queue->lock); _rtw_init_stainfo(psta); memcpy(psta->hwaddr, hwaddr, ETH_ALEN); @@ -210,14 +208,11 @@ struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) psta = NULL; goto exit; } - phash_list = &(pstapriv->sta_hash[index]); - - spin_lock_bh(&(pstapriv->sta_hash_lock)); + phash_list = &pstapriv->sta_hash[index]; + spin_lock_bh(&pstapriv->sta_hash_lock); list_add_tail(&psta->hash_list, phash_list); - pstapriv->asoc_sta_count++; - spin_unlock_bh(&pstapriv->sta_hash_lock); /* Commented by Albert 2009/08/13 */ diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index e778132b73dc..d5ce1e2a1658 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -1216,40 +1216,24 @@ void rtw_count_tx_stats(struct adapter *padapter, struct xmit_frame *pxmitframe, struct xmit_buf *rtw_alloc_xmitbuf_ext(struct xmit_priv *pxmitpriv) { unsigned long irql; - struct xmit_buf *pxmitbuf = NULL; - struct list_head *plist, *phead; + struct xmit_buf *pxmitbuf; struct __queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue; - spin_lock_irqsave(&pfree_queue->lock, irql); - - if (list_empty(&pfree_queue->queue)) { - pxmitbuf = NULL; - } else { - phead = get_list_head(pfree_queue); - - plist = phead->next; - - pxmitbuf = container_of(plist, struct xmit_buf, list); - - list_del_init(&(pxmitbuf->list)); - } - - if (pxmitbuf != NULL) { + pxmitbuf = list_first_entry_or_null(&pfree_queue->queue, + struct xmit_buf, list); + if (pxmitbuf) { + list_del_init(&pxmitbuf->list); pxmitpriv->free_xmit_extbuf_cnt--; - pxmitbuf->priv_data = NULL; /* pxmitbuf->ext_tag = true; */ - if (pxmitbuf->sctx) { DBG_88E("%s pxmitbuf->sctx is not NULL\n", __func__); rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC); } } - spin_unlock_irqrestore(&pfree_queue->lock, irql); - return pxmitbuf; } @@ -1278,28 +1262,16 @@ s32 rtw_free_xmitbuf_ext(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv) { unsigned long irql; - struct xmit_buf *pxmitbuf = NULL; - struct list_head *plist, *phead; + struct xmit_buf *pxmitbuf; struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; - /* DBG_88E("+rtw_alloc_xmitbuf\n"); */ spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irql); - - if (list_empty(&pfree_xmitbuf_queue->queue)) { - pxmitbuf = NULL; - } else { - phead = get_list_head(pfree_xmitbuf_queue); - - plist = phead->next; - - pxmitbuf = container_of(plist, struct xmit_buf, list); - - list_del_init(&(pxmitbuf->list)); - } - - if (pxmitbuf != NULL) { + pxmitbuf = list_first_entry_or_null(&pfree_xmitbuf_queue->queue, + struct xmit_buf, list); + if (pxmitbuf) { + list_del_init(&pxmitbuf->list); pxmitpriv->free_xmitbuf_cnt--; pxmitbuf->priv_data = NULL; if (pxmitbuf->sctx) { @@ -1309,7 +1281,6 @@ struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv) } spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irql); - return pxmitbuf; } @@ -1355,38 +1326,33 @@ Must be very very cautious... */ -struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)/* _queue *pfree_xmit_queue) */ +struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv) + /* _queue *pfree_xmit_queue) */ { /* Please remember to use all the osdep_service api, and lock/unlock or _enter/_exit critical to protect pfree_xmit_queue */ - - struct xmit_frame *pxframe = NULL; - struct list_head *plist, *phead; + struct xmit_frame *pxframe; struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue; - spin_lock_bh(&pfree_xmit_queue->lock); - - if (list_empty(&pfree_xmit_queue->queue)) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe:%d\n", pxmitpriv->free_xmitframe_cnt)); - pxframe = NULL; + pxframe = list_first_entry_or_null(&pfree_xmit_queue->queue, + struct xmit_frame, list); + if (!pxframe) { + RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, + ("rtw_alloc_xmitframe:%d\n", + pxmitpriv->free_xmitframe_cnt)); } else { - phead = get_list_head(pfree_xmit_queue); - - plist = phead->next; - - pxframe = container_of(plist, struct xmit_frame, list); + list_del_init(&pxframe->list); - list_del_init(&(pxframe->list)); - } - - if (pxframe != NULL) { /* default value setting */ + /* default value setting */ pxmitpriv->free_xmitframe_cnt--; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe():free_xmitframe_cnt=%d\n", pxmitpriv->free_xmitframe_cnt)); + RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, + ("rtw_alloc_xmitframe():free_xmitframe_cnt=%d\n", + pxmitpriv->free_xmitframe_cnt)); pxframe->buf_addr = NULL; pxframe->pxmitbuf = NULL; @@ -1402,10 +1368,8 @@ struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)/* _queue *pf pxframe->agg_num = 1; pxframe->ack_report = 0; } - spin_unlock_bh(&pfree_xmit_queue->lock); - return pxframe; } -- cgit v1.2.3 From a3124e7b72bc3d9b915c690561bafe3ad8807696 Mon Sep 17 00:00:00 2001 From: Hari Prasath Gujulan Elango Date: Wed, 20 Jan 2016 12:52:58 +0000 Subject: staging: rtl8188eu: use eth_broadcast_addr() in place of memset Replace the memset of array to broadcast address 0xFF by using the eth_broadcast_addr() API Signed-off-by: Hari Prasath Gujulan Elango Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/ioctl_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index a076ede50b22..aec20bb28ca0 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -1907,7 +1907,7 @@ static int rtw_wx_set_enc_ext(struct net_device *dev, memset(param, 0, param_len); param->cmd = IEEE_CMD_SET_ENCRYPTION; - memset(param->sta_addr, 0xff, ETH_ALEN); + eth_broadcast_addr(param->sta_addr); switch (pext->alg) { case IW_ENCODE_ALG_NONE: -- cgit v1.2.3 From 35eb8ecd35df8d880b65789282cf97eb1dd8481c Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 22 Nov 2015 09:07:15 +0000 Subject: staging: vt6655: channel.c replace pDevice with priv Removing camel case. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/channel.c | 58 ++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index 7a717828fa09..6edccb42231e 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -176,62 +176,62 @@ void vnt_init_bands(struct vnt_private *priv) */ bool set_channel(void *pDeviceHandler, struct ieee80211_channel *ch) { - struct vnt_private *pDevice = pDeviceHandler; + struct vnt_private *priv = pDeviceHandler; bool bResult = true; - if (pDevice->byCurrentCh == ch->hw_value) + if (priv->byCurrentCh == ch->hw_value) return bResult; /* Set VGA to max sensitivity */ - if (pDevice->bUpdateBBVGA && - pDevice->byBBVGACurrent != pDevice->abyBBVGA[0]) { - pDevice->byBBVGACurrent = pDevice->abyBBVGA[0]; + if (priv->bUpdateBBVGA && + priv->byBBVGACurrent != priv->abyBBVGA[0]) { + priv->byBBVGACurrent = priv->abyBBVGA[0]; - BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent); + BBvSetVGAGainOffset(priv, priv->byBBVGACurrent); } /* clear NAV */ - MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MACCR, MACCR_CLRNAV); + MACvRegBitsOn(priv->PortOffset, MAC_REG_MACCR, MACCR_CLRNAV); /* TX_PE will reserve 3 us for MAX2829 A mode only, it is for better TX throughput */ - if (pDevice->byRFType == RF_AIROHA7230) - RFbAL7230SelectChannelPostProcess(pDevice, pDevice->byCurrentCh, + if (priv->byRFType == RF_AIROHA7230) + RFbAL7230SelectChannelPostProcess(priv, priv->byCurrentCh, ch->hw_value); - pDevice->byCurrentCh = ch->hw_value; - bResult &= RFbSelectChannel(pDevice, pDevice->byRFType, + priv->byCurrentCh = ch->hw_value; + bResult &= RFbSelectChannel(priv, priv->byRFType, ch->hw_value); /* Init Synthesizer Table */ - if (pDevice->bEnablePSMode) - RFvWriteWakeProgSyn(pDevice, pDevice->byRFType, ch->hw_value); + if (priv->bEnablePSMode) + RFvWriteWakeProgSyn(priv, priv->byRFType, ch->hw_value); - BBvSoftwareReset(pDevice); + BBvSoftwareReset(priv); - if (pDevice->byLocalID > REV_ID_VT3253_B1) { + if (priv->byLocalID > REV_ID_VT3253_B1) { unsigned long flags; - spin_lock_irqsave(&pDevice->lock, flags); + spin_lock_irqsave(&priv->lock, flags); /* set HW default power register */ - MACvSelectPage1(pDevice->PortOffset); - RFbSetPower(pDevice, RATE_1M, pDevice->byCurrentCh); - VNSvOutPortB(pDevice->PortOffset + MAC_REG_PWRCCK, - pDevice->byCurPwr); - RFbSetPower(pDevice, RATE_6M, pDevice->byCurrentCh); - VNSvOutPortB(pDevice->PortOffset + MAC_REG_PWROFDM, - pDevice->byCurPwr); - MACvSelectPage0(pDevice->PortOffset); - - spin_unlock_irqrestore(&pDevice->lock, flags); + MACvSelectPage1(priv->PortOffset); + RFbSetPower(priv, RATE_1M, priv->byCurrentCh); + VNSvOutPortB(priv->PortOffset + MAC_REG_PWRCCK, + priv->byCurPwr); + RFbSetPower(priv, RATE_6M, priv->byCurrentCh); + VNSvOutPortB(priv->PortOffset + MAC_REG_PWROFDM, + priv->byCurPwr); + MACvSelectPage0(priv->PortOffset); + + spin_unlock_irqrestore(&priv->lock, flags); } - if (pDevice->byBBType == BB_TYPE_11B) - RFbSetPower(pDevice, RATE_1M, pDevice->byCurrentCh); + if (priv->byBBType == BB_TYPE_11B) + RFbSetPower(priv, RATE_1M, priv->byCurrentCh); else - RFbSetPower(pDevice, RATE_6M, pDevice->byCurrentCh); + RFbSetPower(priv, RATE_6M, priv->byCurrentCh); return bResult; } -- cgit v1.2.3 From cea57ee6be0a94ff9f9a73e99800b5d25e7229d1 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 22 Nov 2015 09:07:16 +0000 Subject: staging: vt6655: set_channel replace void handler. Replace with struct vnt_private. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/channel.c | 3 +-- drivers/staging/vt6655/channel.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index 6edccb42231e..d1c91165f769 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -174,9 +174,8 @@ void vnt_init_bands(struct vnt_private *priv) * Return Value: true if succeeded; false if failed. * */ -bool set_channel(void *pDeviceHandler, struct ieee80211_channel *ch) +bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch) { - struct vnt_private *priv = pDeviceHandler; bool bResult = true; if (priv->byCurrentCh == ch->hw_value) diff --git a/drivers/staging/vt6655/channel.h b/drivers/staging/vt6655/channel.h index e2be6fca5f26..2d613e7f169c 100644 --- a/drivers/staging/vt6655/channel.h +++ b/drivers/staging/vt6655/channel.h @@ -27,6 +27,6 @@ void vnt_init_bands(struct vnt_private *); -bool set_channel(void *pDeviceHandler, struct ieee80211_channel *); +bool set_channel(struct vnt_private *, struct ieee80211_channel *); #endif /* _CHANNEL_H_ */ -- cgit v1.2.3 From b379916559b09caa64b9c4bff36ac139a42c6c7b Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 22 Nov 2015 09:07:17 +0000 Subject: staging: vt6655: set_channel replace bResult with ret Removing camel case. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/channel.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index d1c91165f769..9ac1ef9d0d51 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -176,10 +176,10 @@ void vnt_init_bands(struct vnt_private *priv) */ bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch) { - bool bResult = true; + bool ret = true; if (priv->byCurrentCh == ch->hw_value) - return bResult; + return ret; /* Set VGA to max sensitivity */ if (priv->bUpdateBBVGA && @@ -200,8 +200,8 @@ bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch) ch->hw_value); priv->byCurrentCh = ch->hw_value; - bResult &= RFbSelectChannel(priv, priv->byRFType, - ch->hw_value); + ret &= RFbSelectChannel(priv, priv->byRFType, + ch->hw_value); /* Init Synthesizer Table */ if (priv->bEnablePSMode) @@ -232,5 +232,5 @@ bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch) else RFbSetPower(priv, RATE_6M, priv->byCurrentCh); - return bResult; + return ret; } -- cgit v1.2.3 From 9a012c4297322c228191e2c8c5632142c9f9a55a Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 22 Nov 2015 09:07:18 +0000 Subject: staging: vt6655: rf.c rename bResult ret. Removing camel case and reflecting return value. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/rf.c | 138 ++++++++++++++++++++++---------------------- 1 file changed, 69 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index 4c22bb318c79..1c0691d18583 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -420,9 +420,9 @@ static bool s_bAL7230Init(struct vnt_private *priv) { void __iomem *dwIoBase = priv->PortOffset; int ii; - bool bResult; + bool ret; - bResult = true; + ret = true; /* 3-wire control for normal mode */ VNSvOutPortB(dwIoBase + MAC_REG_SOFTPWRCTL, 0); @@ -432,7 +432,7 @@ static bool s_bAL7230Init(struct vnt_private *priv) BBvPowerSaveModeOFF(priv); /* RobertYu:20050106, have DC value for Calibration */ for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++) - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[ii]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[ii]); /* PLL On */ MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); @@ -440,13 +440,13 @@ static bool s_bAL7230Init(struct vnt_private *priv) /* Calibration */ MACvTimer0MicroSDelay(dwIoBase, 150);/* 150us */ /* TXDCOC:active, RCK:disable */ - bResult &= IFRFbWriteEmbedded(priv, (0x9ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); + ret &= IFRFbWriteEmbedded(priv, (0x9ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */ /* TXDCOC:disable, RCK:active */ - bResult &= IFRFbWriteEmbedded(priv, (0x3ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); + ret &= IFRFbWriteEmbedded(priv, (0x3ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */ /* TXDCOC:disable, RCK:disable */ - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]); MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 | SOFTPWRCTL_SWPE2 | @@ -459,7 +459,7 @@ static bool s_bAL7230Init(struct vnt_private *priv) /* 3-wire control for power saving mode */ VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); /* 1100 0000 */ - return bResult; + return ret; } /* Need to Pull PLLON low when writing channel registers through @@ -467,16 +467,16 @@ static bool s_bAL7230Init(struct vnt_private *priv) static bool s_bAL7230SelectChannel(struct vnt_private *priv, unsigned char byChannel) { void __iomem *dwIoBase = priv->PortOffset; - bool bResult; + bool ret; - bResult = true; + ret = true; /* PLLON Off */ MACvWordRegBitsOff(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable0[byChannel - 1]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable1[byChannel - 1]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable2[byChannel - 1]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable0[byChannel - 1]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable1[byChannel - 1]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable2[byChannel - 1]); /* PLLOn On */ MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); @@ -487,7 +487,7 @@ static bool s_bAL7230SelectChannel(struct vnt_private *priv, unsigned char byCha /* Set Channel[7] = 1 to tell H/W channel change is done. */ VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80)); - return bResult; + return ret; } /* @@ -540,9 +540,9 @@ static bool RFbAL2230Init(struct vnt_private *priv) { void __iomem *dwIoBase = priv->PortOffset; int ii; - bool bResult; + bool ret; - bResult = true; + ret = true; /* 3-wire control for normal mode */ VNSvOutPortB(dwIoBase + MAC_REG_SOFTPWRCTL, 0); @@ -556,18 +556,18 @@ static bool RFbAL2230Init(struct vnt_private *priv) IFRFbWriteEmbedded(priv, (0x07168700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++) - bResult &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[ii]); + ret &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[ii]); MACvTimer0MicroSDelay(dwIoBase, 30); /* delay 30 us */ /* PLL On */ MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); MACvTimer0MicroSDelay(dwIoBase, 150);/* 150us */ - bResult &= IFRFbWriteEmbedded(priv, (0x00d80f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); + ret &= IFRFbWriteEmbedded(priv, (0x00d80f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */ - bResult &= IFRFbWriteEmbedded(priv, (0x00780f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); + ret &= IFRFbWriteEmbedded(priv, (0x00780f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */ - bResult &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]); + ret &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]); MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 | SOFTPWRCTL_SWPE2 | @@ -577,18 +577,18 @@ static bool RFbAL2230Init(struct vnt_private *priv) /* 3-wire control for power saving mode */ VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); /* 1100 0000 */ - return bResult; + return ret; } static bool RFbAL2230SelectChannel(struct vnt_private *priv, unsigned char byChannel) { void __iomem *dwIoBase = priv->PortOffset; - bool bResult; + bool ret; - bResult = true; + ret = true; - bResult &= IFRFbWriteEmbedded(priv, dwAL2230ChannelTable0[byChannel - 1]); - bResult &= IFRFbWriteEmbedded(priv, dwAL2230ChannelTable1[byChannel - 1]); + ret &= IFRFbWriteEmbedded(priv, dwAL2230ChannelTable0[byChannel - 1]); + ret &= IFRFbWriteEmbedded(priv, dwAL2230ChannelTable1[byChannel - 1]); /* Set Channel[7] = 0 to tell H/W channel is changing now. */ VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F)); @@ -596,7 +596,7 @@ static bool RFbAL2230SelectChannel(struct vnt_private *priv, unsigned char byCha /* Set Channel[7] = 1 to tell H/W channel change is done. */ VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80)); - return bResult; + return ret; } /* @@ -616,26 +616,26 @@ bool RFbInit( struct vnt_private *priv ) { - bool bResult = true; + bool ret = true; switch (priv->byRFType) { case RF_AIROHA: case RF_AL2230S: priv->byMaxPwrLevel = AL2230_PWR_IDX_LEN; - bResult = RFbAL2230Init(priv); + ret = RFbAL2230Init(priv); break; case RF_AIROHA7230: priv->byMaxPwrLevel = AL7230_PWR_IDX_LEN; - bResult = s_bAL7230Init(priv); + ret = s_bAL7230Init(priv); break; case RF_NOTHING: - bResult = true; + ret = true; break; default: - bResult = false; + ret = false; break; } - return bResult; + return ret; } /* @@ -654,26 +654,26 @@ bool RFbInit( bool RFbSelectChannel(struct vnt_private *priv, unsigned char byRFType, u16 byChannel) { - bool bResult = true; + bool ret = true; switch (byRFType) { case RF_AIROHA: case RF_AL2230S: - bResult = RFbAL2230SelectChannel(priv, byChannel); + ret = RFbAL2230SelectChannel(priv, byChannel); break; /*{{ RobertYu: 20050104 */ case RF_AIROHA7230: - bResult = s_bAL7230SelectChannel(priv, byChannel); + ret = s_bAL7230SelectChannel(priv, byChannel); break; /*}} RobertYu */ case RF_NOTHING: - bResult = true; + ret = true; break; default: - bResult = false; + ret = false; break; } - return bResult; + return ret; } /* @@ -772,7 +772,7 @@ bool RFbSetPower( u16 uCH ) { - bool bResult = true; + bool ret = true; unsigned char byPwr = 0; unsigned char byDec = 0; @@ -818,11 +818,11 @@ bool RFbSetPower( if (priv->byCurPwr == byPwr) return true; - bResult = RFbRawSetPower(priv, byPwr, rate); - if (bResult) + ret = RFbRawSetPower(priv, byPwr, rate); + if (ret) priv->byCurPwr = byPwr; - return bResult; + return ret; } /* @@ -845,7 +845,7 @@ bool RFbRawSetPower( unsigned int rate ) { - bool bResult = true; + bool ret = true; unsigned long dwMax7230Pwr = 0; if (byPwr >= priv->byMaxPwrLevel) @@ -853,22 +853,22 @@ bool RFbRawSetPower( switch (priv->byRFType) { case RF_AIROHA: - bResult &= IFRFbWriteEmbedded(priv, dwAL2230PowerTable[byPwr]); + ret &= IFRFbWriteEmbedded(priv, dwAL2230PowerTable[byPwr]); if (rate <= RATE_11M) - bResult &= IFRFbWriteEmbedded(priv, 0x0001B400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x0001B400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); else - bResult &= IFRFbWriteEmbedded(priv, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); break; case RF_AL2230S: - bResult &= IFRFbWriteEmbedded(priv, dwAL2230PowerTable[byPwr]); + ret &= IFRFbWriteEmbedded(priv, dwAL2230PowerTable[byPwr]); if (rate <= RATE_11M) { - bResult &= IFRFbWriteEmbedded(priv, 0x040C1400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); - bResult &= IFRFbWriteEmbedded(priv, 0x00299B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x040C1400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x00299B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); } else { - bResult &= IFRFbWriteEmbedded(priv, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); - bResult &= IFRFbWriteEmbedded(priv, 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); } break; @@ -879,13 +879,13 @@ bool RFbRawSetPower( dwMax7230Pwr = 0x080C0B00 | ((byPwr) << 12) | (BY_AL7230_REG_LEN << 3) | IFREGCTL_REGW; - bResult &= IFRFbWriteEmbedded(priv, dwMax7230Pwr); + ret &= IFRFbWriteEmbedded(priv, dwMax7230Pwr); break; default: break; } - return bResult; + return ret; } /*+ @@ -934,32 +934,32 @@ bool RFbAL7230SelectChannelPostProcess(struct vnt_private *priv, u16 byOldChannel, u16 byNewChannel) { - bool bResult; + bool ret; - bResult = true; + ret = true; /* if change between 11 b/g and 11a need to update the following * register * Channel Index 1~14 */ if ((byOldChannel <= CB_MAX_CHANNEL_24G) && (byNewChannel > CB_MAX_CHANNEL_24G)) { /* Change from 2.4G to 5G [Reg] */ - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[2]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[3]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[5]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[7]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[10]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[12]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[15]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[2]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[3]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[5]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[7]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[10]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[12]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[15]); } else if ((byOldChannel > CB_MAX_CHANNEL_24G) && (byNewChannel <= CB_MAX_CHANNEL_24G)) { /* Change from 5G to 2.4G [Reg] */ - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[2]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[3]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[5]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[7]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[10]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[12]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[15]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[2]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[3]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[5]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[7]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[10]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[12]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[15]); } - return bResult; + return ret; } -- cgit v1.2.3 From 16d56de650b6ef0756195f4beb449e250ba97cb5 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 22 Nov 2015 09:07:19 +0000 Subject: staging: vt6655: power.c replace pDevice with priv Removing camel case. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/power.c | 56 +++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index 06e6b9d871c4..e58afbd8c89e 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -68,40 +68,40 @@ PSvEnablePowerSaving( unsigned short wListenInterval ) { - struct vnt_private *pDevice = hDeviceContext; - u16 wAID = pDevice->current_aid | BIT(14) | BIT(15); + struct vnt_private *priv = hDeviceContext; + u16 wAID = priv->current_aid | BIT(14) | BIT(15); /* set period of power up before TBTT */ - VNSvOutPortW(pDevice->PortOffset + MAC_REG_PWBT, C_PWBT); - if (pDevice->op_mode != NL80211_IFTYPE_ADHOC) { + VNSvOutPortW(priv->PortOffset + MAC_REG_PWBT, C_PWBT); + if (priv->op_mode != NL80211_IFTYPE_ADHOC) { /* set AID */ - VNSvOutPortW(pDevice->PortOffset + MAC_REG_AIDATIM, wAID); + VNSvOutPortW(priv->PortOffset + MAC_REG_AIDATIM, wAID); } else { /* set ATIM Window */ #if 0 /* TODO atim window */ - MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow); + MACvWriteATIMW(priv->PortOffset, pMgmt->wCurrATIMWindow); #endif } /* Set AutoSleep */ - MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); + MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); /* Set HWUTSF */ - MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); + MACvRegBitsOn(priv->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); if (wListenInterval >= 2) { /* clear always listen beacon */ - MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); + MACvRegBitsOff(priv->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); /* first time set listen next beacon */ - MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN); + MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN); } else { /* always listen beacon */ - MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); + MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); } /* enable power saving hw function */ - MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN); - pDevice->bEnablePSMode = true; + MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN); + priv->bEnablePSMode = true; - pDevice->bPWBitOn = true; + priv->bPWBitOn = true; pr_debug("PS:Power Saving Mode Enable...\n"); } @@ -120,20 +120,20 @@ PSvDisablePowerSaving( void *hDeviceContext ) { - struct vnt_private *pDevice = hDeviceContext; + struct vnt_private *priv = hDeviceContext; /* disable power saving hw function */ - MACbPSWakeup(pDevice->PortOffset); + MACbPSWakeup(priv->PortOffset); /* clear AutoSleep */ - MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); + MACvRegBitsOff(priv->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); /* clear HWUTSF */ - MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); + MACvRegBitsOff(priv->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); /* set always listen beacon */ - MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); + MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); - pDevice->bEnablePSMode = false; + priv->bEnablePSMode = false; - pDevice->bPWBitOn = false; + priv->bPWBitOn = false; } @@ -152,20 +152,20 @@ PSbIsNextTBTTWakeUp( void *hDeviceContext ) { - struct vnt_private *pDevice = hDeviceContext; - struct ieee80211_hw *hw = pDevice->hw; + struct vnt_private *priv = hDeviceContext; + struct ieee80211_hw *hw = priv->hw; struct ieee80211_conf *conf = &hw->conf; bool bWakeUp = false; if (conf->listen_interval > 1) { - if (!pDevice->wake_up_count) - pDevice->wake_up_count = conf->listen_interval; + if (!priv->wake_up_count) + priv->wake_up_count = conf->listen_interval; - --pDevice->wake_up_count; + --priv->wake_up_count; - if (pDevice->wake_up_count == 1) { + if (priv->wake_up_count == 1) { /* Turn on wake up to listen next beacon */ - MACvRegBitsOn(pDevice->PortOffset, + MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN); bWakeUp = true; } -- cgit v1.2.3 From c30ab9303f8c6e92d48afe1740a8483b431c195f Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 22 Nov 2015 09:07:20 +0000 Subject: staging: vt6655: rf.c/h Replace DeviceContext with vnt_private Removing void and including device.h for power.h Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/power.c | 10 +++------- drivers/staging/vt6655/power.h | 8 +++++--- 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index e58afbd8c89e..ad44746d4ff4 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -64,11 +64,10 @@ void PSvEnablePowerSaving( - void *hDeviceContext, + struct vnt_private *priv, unsigned short wListenInterval ) { - struct vnt_private *priv = hDeviceContext; u16 wAID = priv->current_aid | BIT(14) | BIT(15); /* set period of power up before TBTT */ @@ -117,11 +116,9 @@ PSvEnablePowerSaving( void PSvDisablePowerSaving( - void *hDeviceContext + struct vnt_private *priv ) { - struct vnt_private *priv = hDeviceContext; - /* disable power saving hw function */ MACbPSWakeup(priv->PortOffset); /* clear AutoSleep */ @@ -149,10 +146,9 @@ PSvDisablePowerSaving( bool PSbIsNextTBTTWakeUp( - void *hDeviceContext + struct vnt_private *priv ) { - struct vnt_private *priv = hDeviceContext; struct ieee80211_hw *hw = priv->hw; struct ieee80211_conf *conf = &hw->conf; bool bWakeUp = false; diff --git a/drivers/staging/vt6655/power.h b/drivers/staging/vt6655/power.h index 538e68507bb0..d82dd8d6d68b 100644 --- a/drivers/staging/vt6655/power.h +++ b/drivers/staging/vt6655/power.h @@ -29,25 +29,27 @@ #ifndef __POWER_H__ #define __POWER_H__ +#include "device.h" + #define C_PWBT 1000 /* micro sec. power up before TBTT */ #define PS_FAST_INTERVAL 1 /* Fast power saving listen interval */ #define PS_MAX_INTERVAL 4 /* MAX power saving listen interval */ void PSvDisablePowerSaving( - void *hDeviceContext + struct vnt_private * ); void PSvEnablePowerSaving( - void *hDeviceContext, + struct vnt_private *, unsigned short wListenInterval ); bool PSbIsNextTBTTWakeUp( - void *hDeviceContext + struct vnt_private * ); #endif /* __POWER_H__ */ -- cgit v1.2.3 From a977551be94337e8c58331b7e43f8238dcc827bf Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 22 Nov 2015 09:07:21 +0000 Subject: staging: vt6655: PSbIsNextTBTTWakeUp Rename bWakeUp wake_up Removing camel case. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/power.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index ad44746d4ff4..5e968c9340d7 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -151,7 +151,7 @@ PSbIsNextTBTTWakeUp( { struct ieee80211_hw *hw = priv->hw; struct ieee80211_conf *conf = &hw->conf; - bool bWakeUp = false; + bool wake_up = false; if (conf->listen_interval > 1) { if (!priv->wake_up_count) @@ -163,9 +163,9 @@ PSbIsNextTBTTWakeUp( /* Turn on wake up to listen next beacon */ MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN); - bWakeUp = true; + wake_up = true; } } - return bWakeUp; + return wake_up; } -- cgit v1.2.3 From f9f853af84c9205ba9dbc461da0f11da1f4abb53 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 22 Nov 2015 09:07:22 +0000 Subject: staging: vt6655: mac.c replace void __iomem * with struct vnt_private Moving void __iomem down one level in the following functions MACbIsRegBitsOn MACbIsRegBitsOff MACbIsIntDisable MACvSetShortRetryLimit MACvSetLongRetryLimit MACvGetLongRetryLimit MACvSetLoopbackMode MACvSaveContext MACvRestoreContext MACbSoftwareReset MACbSafeSoftwareReset MACbSafeRxOff MACbSafeTxOff MACbSafeStop MACbShutdown MACvInitialize MACvSetCurrRx0DescAddr MACvSetCurrRx1DescAddr MACvSetCurrTXDescAddr MACvSetCurrTx0DescAddrEx MACvSetCurrAC0DescAddrEx MACvSetCurrSyncDescAddrEx MACvSetCurrATIMDescAddrEx MACvTimer0MicroSDelay MACvOneShotTimer1MicroSec MACvSetMISCFifo MACbPSWakeup MACvSetKeyEntry MACvDisableKeyEntry Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/card.c | 18 ++---- drivers/staging/vt6655/device_main.c | 24 ++++---- drivers/staging/vt6655/key.c | 8 +-- drivers/staging/vt6655/mac.c | 108 ++++++++++++++++++++++------------- drivers/staging/vt6655/mac.h | 58 +++++++++---------- drivers/staging/vt6655/power.c | 2 +- drivers/staging/vt6655/rf.c | 36 ++++++------ 7 files changed, 137 insertions(+), 117 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index b6730a8068fd..6c1b973a675f 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -535,11 +535,9 @@ CARDvSafeResetTx( } /* set MAC TD pointer */ - MACvSetCurrTXDescAddr(TYPE_TXDMA0, priv->PortOffset, - (priv->td0_pool_dma)); + MACvSetCurrTXDescAddr(TYPE_TXDMA0, priv, priv->td0_pool_dma); - MACvSetCurrTXDescAddr(TYPE_AC0DMA, priv->PortOffset, - (priv->td1_pool_dma)); + MACvSetCurrTXDescAddr(TYPE_AC0DMA, priv, priv->td1_pool_dma); /* set MAC Beacon TX pointer */ MACvSetCurrBCNTxDescAddr(priv->PortOffset, @@ -590,11 +588,9 @@ CARDvSafeResetRx( MACvRx0PerPktMode(priv->PortOffset); MACvRx1PerPktMode(priv->PortOffset); /* set MAC RD pointer */ - MACvSetCurrRx0DescAddr(priv->PortOffset, - priv->rd0_pool_dma); + MACvSetCurrRx0DescAddr(priv, priv->rd0_pool_dma); - MACvSetCurrRx1DescAddr(priv->PortOffset, - priv->rd1_pool_dma); + MACvSetCurrRx1DescAddr(priv, priv->rd1_pool_dma); } /* @@ -839,8 +835,6 @@ unsigned char CARDbyGetPktType(struct vnt_private *priv) */ void CARDvSetLoopbackMode(struct vnt_private *priv, unsigned short wLoopbackMode) { - void __iomem *dwIoBase = priv->PortOffset; - switch (wLoopbackMode) { case CARD_LB_NONE: case CARD_LB_MAC: @@ -850,7 +844,7 @@ void CARDvSetLoopbackMode(struct vnt_private *priv, unsigned short wLoopbackMode break; } /* set MAC loopback */ - MACvSetLoopbackMode(dwIoBase, LOBYTE(wLoopbackMode)); + MACvSetLoopbackMode(priv, LOBYTE(wLoopbackMode)); /* set Baseband loopback */ } @@ -869,7 +863,7 @@ bool CARDbSoftwareReset(struct vnt_private *priv) { /* reset MAC */ - if (!MACbSafeSoftwareReset(priv->PortOffset)) + if (!MACbSafeSoftwareReset(priv)) return false; return true; diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index fefbf826c622..ad0fb84e5096 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -211,11 +211,11 @@ static void device_init_registers(struct vnt_private *priv) unsigned char byCCKPwrdBm = 0; unsigned char byOFDMPwrdBm = 0; - MACbShutdown(priv->PortOffset); + MACbShutdown(priv); BBvSoftwareReset(priv); /* Do MACbSoftwareReset in MACvInitialize */ - MACbSoftwareReset(priv->PortOffset); + MACbSoftwareReset(priv); priv->bAES = false; @@ -229,7 +229,7 @@ static void device_init_registers(struct vnt_private *priv) priv->byTopCCKBasicRate = RATE_1M; /* init MAC */ - MACvInitialize(priv->PortOffset); + MACvInitialize(priv); /* Get Local ID */ VNSvInPortB(priv->PortOffset + MAC_REG_LOCALID, &priv->byLocalID); @@ -357,8 +357,8 @@ static void device_init_registers(struct vnt_private *priv) MAC_REG_CFG, (CFG_TKIPOPT | CFG_NOTXTIMEOUT)); /* set performance parameter by registry */ - MACvSetShortRetryLimit(priv->PortOffset, priv->byShortRetryLimit); - MACvSetLongRetryLimit(priv->PortOffset, priv->byLongRetryLimit); + MACvSetShortRetryLimit(priv, priv->byShortRetryLimit); + MACvSetLongRetryLimit(priv, priv->byLongRetryLimit); /* reset TSF counter */ VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); @@ -884,7 +884,7 @@ static void device_error(struct vnt_private *priv, unsigned short status) if (status & ISR_FETALERR) { dev_err(&priv->pcid->dev, "Hardware fatal error\n"); - MACbShutdown(priv->PortOffset); + MACbShutdown(priv); return; } } @@ -1012,7 +1012,7 @@ static void vnt_interrupt_process(struct vnt_private *priv) if ((priv->op_mode == NL80211_IFTYPE_AP || priv->op_mode == NL80211_IFTYPE_ADHOC) && priv->vif->bss_conf.enable_beacon) { - MACvOneShotTimer1MicroSec(priv->PortOffset, + MACvOneShotTimer1MicroSec(priv, (priv->vif->bss_conf.beacon_int - MAKE_BEACON_RESERVED) << 10); } @@ -1197,8 +1197,8 @@ static void vnt_stop(struct ieee80211_hw *hw) cancel_work_sync(&priv->interrupt_work); - MACbShutdown(priv->PortOffset); - MACbSoftwareReset(priv->PortOffset); + MACbShutdown(priv); + MACbSoftwareReset(priv); CARDbRadioPowerOff(priv); device_free_td0_ring(priv); @@ -1636,13 +1636,13 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) INIT_WORK(&priv->interrupt_work, vnt_interrupt_work); /* do reset */ - if (!MACbSoftwareReset(priv->PortOffset)) { + if (!MACbSoftwareReset(priv)) { dev_err(&pcid->dev, ": Failed to access MAC hardware..\n"); device_free_info(priv); return -ENODEV; } /* initial to reload eeprom */ - MACvInitialize(priv->PortOffset); + MACvInitialize(priv); MACvReadEtherAddress(priv->PortOffset, priv->abyCurrentNetAddr); /* Get RFType */ @@ -1690,7 +1690,7 @@ static int vt6655_suspend(struct pci_dev *pcid, pm_message_t state) pci_save_state(pcid); - MACbShutdown(priv->PortOffset); + MACbShutdown(priv); pci_disable_device(pcid); pci_set_power_state(pcid, pci_choose_state(pcid, state)); diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c index f2b3fea90533..ffcaf25fdd8b 100644 --- a/drivers/staging/vt6655/key.c +++ b/drivers/staging/vt6655/key.c @@ -36,7 +36,7 @@ int vnt_key_init_table(struct vnt_private *priv) u32 i; for (i = 0; i < MAX_KEY_TABLE; i++) - MACvDisableKeyEntry(priv->PortOffset, i); + MACvDisableKeyEntry(priv, i); return 0; } @@ -104,7 +104,7 @@ static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr, key->key[15] |= 0x80; } - MACvSetKeyEntry(priv->PortOffset, key_mode, entry, key_inx, + MACvSetKeyEntry(priv, key_mode, entry, key_inx, bssid, (u32 *)key->key, priv->byLocalID); return 0; @@ -126,13 +126,13 @@ int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, switch (key->cipher) { case 0: for (u = 0 ; u < MAX_KEY_TABLE; u++) - MACvDisableKeyEntry(priv->PortOffset, u); + MACvDisableKeyEntry(priv, u); return ret; case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: for (u = 0; u < MAX_KEY_TABLE; u++) - MACvDisableKeyEntry(priv->PortOffset, u); + MACvDisableKeyEntry(priv, u); vnt_set_keymode(hw, mac_addr, key, VNT_KEY_DEFAULTKEY, KEY_CTL_WEP, true); diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index 688c3be168d1..e74782aa6475 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -70,9 +70,10 @@ * Return Value: true if all test bits On; otherwise false * */ -bool MACbIsRegBitsOn(void __iomem *dwIoBase, unsigned char byRegOfs, +bool MACbIsRegBitsOn(struct vnt_private *priv, unsigned char byRegOfs, unsigned char byTestBits) { + void __iomem *dwIoBase = priv->PortOffset; unsigned char byData; VNSvInPortB(dwIoBase + byRegOfs, &byData); @@ -94,9 +95,10 @@ bool MACbIsRegBitsOn(void __iomem *dwIoBase, unsigned char byRegOfs, * Return Value: true if all test bits Off; otherwise false * */ -bool MACbIsRegBitsOff(void __iomem *dwIoBase, unsigned char byRegOfs, +bool MACbIsRegBitsOff(struct vnt_private *priv, unsigned char byRegOfs, unsigned char byTestBits) { + void __iomem *dwIoBase = priv->PortOffset; unsigned char byData; VNSvInPortB(dwIoBase + byRegOfs, &byData); @@ -116,8 +118,9 @@ bool MACbIsRegBitsOff(void __iomem *dwIoBase, unsigned char byRegOfs, * Return Value: true if interrupt is disable; otherwise false * */ -bool MACbIsIntDisable(void __iomem *dwIoBase) +bool MACbIsIntDisable(struct vnt_private *priv) { + void __iomem *dwIoBase = priv->PortOffset; unsigned long dwData; VNSvInPortD(dwIoBase + MAC_REG_IMR, &dwData); @@ -141,8 +144,9 @@ bool MACbIsIntDisable(void __iomem *dwIoBase) * Return Value: none * */ -void MACvSetShortRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit) +void MACvSetShortRetryLimit(struct vnt_private *priv, unsigned char byRetryLimit) { + void __iomem *dwIoBase = priv->PortOffset; /* set SRT */ VNSvOutPortB(dwIoBase + MAC_REG_SRT, byRetryLimit); } @@ -162,8 +166,9 @@ void MACvSetShortRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit) * Return Value: none * */ -void MACvSetLongRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit) +void MACvSetLongRetryLimit(struct vnt_private *priv, unsigned char byRetryLimit) { + void __iomem *dwIoBase = priv->PortOffset; /* set LRT */ VNSvOutPortB(dwIoBase + MAC_REG_LRT, byRetryLimit); } @@ -182,8 +187,9 @@ void MACvSetLongRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit) * Return Value: none * */ -void MACvSetLoopbackMode(void __iomem *dwIoBase, unsigned char byLoopbackMode) +void MACvSetLoopbackMode(struct vnt_private *priv, unsigned char byLoopbackMode) { + void __iomem *dwIoBase = priv->PortOffset; unsigned char byOrgValue; byLoopbackMode <<= 6; @@ -207,8 +213,9 @@ void MACvSetLoopbackMode(void __iomem *dwIoBase, unsigned char byLoopbackMode) * Return Value: none * */ -void MACvSaveContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf) +void MACvSaveContext(struct vnt_private *priv, unsigned char *pbyCxtBuf) { + void __iomem *dwIoBase = priv->PortOffset; int ii; /* read page0 register */ @@ -239,8 +246,9 @@ void MACvSaveContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf) * Return Value: none * */ -void MACvRestoreContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf) +void MACvRestoreContext(struct vnt_private *priv, unsigned char *pbyCxtBuf) { + void __iomem *dwIoBase = priv->PortOffset; int ii; MACvSelectPage1(dwIoBase); @@ -293,8 +301,9 @@ void MACvRestoreContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf) * Return Value: true if Reset Success; otherwise false * */ -bool MACbSoftwareReset(void __iomem *dwIoBase) +bool MACbSoftwareReset(struct vnt_private *priv) { + void __iomem *dwIoBase = priv->PortOffset; unsigned char byData; unsigned short ww; @@ -324,7 +333,7 @@ bool MACbSoftwareReset(void __iomem *dwIoBase) * Return Value: true if success; otherwise false * */ -bool MACbSafeSoftwareReset(void __iomem *dwIoBase) +bool MACbSafeSoftwareReset(struct vnt_private *priv) { unsigned char abyTmpRegData[MAC_MAX_CONTEXT_SIZE_PAGE0+MAC_MAX_CONTEXT_SIZE_PAGE1]; bool bRetVal; @@ -334,11 +343,11 @@ bool MACbSafeSoftwareReset(void __iomem *dwIoBase) * reset, then restore register's value */ /* save MAC context */ - MACvSaveContext(dwIoBase, abyTmpRegData); + MACvSaveContext(priv, abyTmpRegData); /* do reset */ - bRetVal = MACbSoftwareReset(dwIoBase); + bRetVal = MACbSoftwareReset(priv); /* restore MAC context, except CR0 */ - MACvRestoreContext(dwIoBase, abyTmpRegData); + MACvRestoreContext(priv, abyTmpRegData); return bRetVal; } @@ -356,8 +365,9 @@ bool MACbSafeSoftwareReset(void __iomem *dwIoBase) * Return Value: true if success; otherwise false * */ -bool MACbSafeRxOff(void __iomem *dwIoBase) +bool MACbSafeRxOff(struct vnt_private *priv) { + void __iomem *dwIoBase = priv->PortOffset; unsigned short ww; unsigned long dwData; unsigned char byData; @@ -414,8 +424,9 @@ bool MACbSafeRxOff(void __iomem *dwIoBase) * Return Value: true if success; otherwise false * */ -bool MACbSafeTxOff(void __iomem *dwIoBase) +bool MACbSafeTxOff(struct vnt_private *priv) { + void __iomem *dwIoBase = priv->PortOffset; unsigned short ww; unsigned long dwData; unsigned char byData; @@ -474,18 +485,19 @@ bool MACbSafeTxOff(void __iomem *dwIoBase) * Return Value: true if success; otherwise false * */ -bool MACbSafeStop(void __iomem *dwIoBase) +bool MACbSafeStop(struct vnt_private *priv) { + void __iomem *dwIoBase = priv->PortOffset; MACvRegBitsOff(dwIoBase, MAC_REG_TCR, TCR_AUTOBCNTX); - if (!MACbSafeRxOff(dwIoBase)) { + if (!MACbSafeRxOff(priv)) { pr_debug(" MACbSafeRxOff == false)\n"); - MACbSafeSoftwareReset(dwIoBase); + MACbSafeSoftwareReset(priv); return false; } - if (!MACbSafeTxOff(dwIoBase)) { + if (!MACbSafeTxOff(priv)) { pr_debug(" MACbSafeTxOff == false)\n"); - MACbSafeSoftwareReset(dwIoBase); + MACbSafeSoftwareReset(priv); return false; } @@ -507,17 +519,18 @@ bool MACbSafeStop(void __iomem *dwIoBase) * Return Value: true if success; otherwise false * */ -bool MACbShutdown(void __iomem *dwIoBase) +bool MACbShutdown(struct vnt_private *priv) { + void __iomem *dwIoBase = priv->PortOffset; /* disable MAC IMR */ MACvIntDisable(dwIoBase); - MACvSetLoopbackMode(dwIoBase, MAC_LB_INTERNAL); + MACvSetLoopbackMode(priv, MAC_LB_INTERNAL); /* stop the adapter */ - if (!MACbSafeStop(dwIoBase)) { - MACvSetLoopbackMode(dwIoBase, MAC_LB_NONE); + if (!MACbSafeStop(priv)) { + MACvSetLoopbackMode(priv, MAC_LB_NONE); return false; } - MACvSetLoopbackMode(dwIoBase, MAC_LB_NONE); + MACvSetLoopbackMode(priv, MAC_LB_NONE); return true; } @@ -534,8 +547,9 @@ bool MACbShutdown(void __iomem *dwIoBase) * Return Value: none * */ -void MACvInitialize(void __iomem *dwIoBase) +void MACvInitialize(struct vnt_private *priv) { + void __iomem *dwIoBase = priv->PortOffset; /* clear sticky bits */ MACvClearStckDS(dwIoBase); /* disable force PME-enable */ @@ -543,7 +557,7 @@ void MACvInitialize(void __iomem *dwIoBase) /* only 3253 A */ /* do reset */ - MACbSoftwareReset(dwIoBase); + MACbSoftwareReset(priv); /* reset TSF counter */ VNSvOutPortB(dwIoBase + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); @@ -565,8 +579,9 @@ void MACvInitialize(void __iomem *dwIoBase) * Return Value: none * */ -void MACvSetCurrRx0DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr) +void MACvSetCurrRx0DescAddr(struct vnt_private *priv, unsigned long dwCurrDescAddr) { + void __iomem *dwIoBase = priv->PortOffset; unsigned short ww; unsigned char byData; unsigned char byOrgDMACtl; @@ -600,8 +615,9 @@ void MACvSetCurrRx0DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr * Return Value: none * */ -void MACvSetCurrRx1DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr) +void MACvSetCurrRx1DescAddr(struct vnt_private *priv, unsigned long dwCurrDescAddr) { + void __iomem *dwIoBase = priv->PortOffset; unsigned short ww; unsigned char byData; unsigned char byOrgDMACtl; @@ -636,9 +652,10 @@ void MACvSetCurrRx1DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr * Return Value: none * */ -void MACvSetCurrTx0DescAddrEx(void __iomem *dwIoBase, +void MACvSetCurrTx0DescAddrEx(struct vnt_private *priv, unsigned long dwCurrDescAddr) { + void __iomem *dwIoBase = priv->PortOffset; unsigned short ww; unsigned char byData; unsigned char byOrgDMACtl; @@ -673,9 +690,10 @@ void MACvSetCurrTx0DescAddrEx(void __iomem *dwIoBase, * */ /* TxDMA1 = AC0DMA */ -void MACvSetCurrAC0DescAddrEx(void __iomem *dwIoBase, +void MACvSetCurrAC0DescAddrEx(struct vnt_private *priv, unsigned long dwCurrDescAddr) { + void __iomem *dwIoBase = priv->PortOffset; unsigned short ww; unsigned char byData; unsigned char byOrgDMACtl; @@ -696,13 +714,13 @@ void MACvSetCurrAC0DescAddrEx(void __iomem *dwIoBase, VNSvOutPortB(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_RUN); } -void MACvSetCurrTXDescAddr(int iTxType, void __iomem *dwIoBase, +void MACvSetCurrTXDescAddr(int iTxType, struct vnt_private *priv, unsigned long dwCurrDescAddr) { if (iTxType == TYPE_AC0DMA) - MACvSetCurrAC0DescAddrEx(dwIoBase, dwCurrDescAddr); + MACvSetCurrAC0DescAddrEx(priv, dwCurrDescAddr); else if (iTxType == TYPE_TXDMA0) - MACvSetCurrTx0DescAddrEx(dwIoBase, dwCurrDescAddr); + MACvSetCurrTx0DescAddrEx(priv, dwCurrDescAddr); } /* @@ -719,8 +737,9 @@ void MACvSetCurrTXDescAddr(int iTxType, void __iomem *dwIoBase, * Return Value: none * */ -void MACvTimer0MicroSDelay(void __iomem *dwIoBase, unsigned int uDelay) +void MACvTimer0MicroSDelay(struct vnt_private *priv, unsigned int uDelay) { + void __iomem *dwIoBase = priv->PortOffset; unsigned char byValue; unsigned int uu, ii; @@ -754,16 +773,20 @@ void MACvTimer0MicroSDelay(void __iomem *dwIoBase, unsigned int uDelay) * Return Value: none * */ -void MACvOneShotTimer1MicroSec(void __iomem *dwIoBase, unsigned int uDelayTime) +void MACvOneShotTimer1MicroSec(struct vnt_private *priv, unsigned int uDelayTime) { + void __iomem *dwIoBase = priv->PortOffset; + VNSvOutPortB(dwIoBase + MAC_REG_TMCTL1, 0); VNSvOutPortD(dwIoBase + MAC_REG_TMDATA1, uDelayTime); VNSvOutPortB(dwIoBase + MAC_REG_TMCTL1, (TMCTL_TMD | TMCTL_TE)); } -void MACvSetMISCFifo(void __iomem *dwIoBase, unsigned short wOffset, +void MACvSetMISCFifo(struct vnt_private *priv, unsigned short wOffset, unsigned long dwData) { + void __iomem *dwIoBase = priv->PortOffset; + if (wOffset > 273) return; VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); @@ -771,12 +794,13 @@ void MACvSetMISCFifo(void __iomem *dwIoBase, unsigned short wOffset, VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); } -bool MACbPSWakeup(void __iomem *dwIoBase) +bool MACbPSWakeup(struct vnt_private *priv) { + void __iomem *dwIoBase = priv->PortOffset; unsigned char byOrgValue; unsigned int ww; /* Read PSCTL */ - if (MACbIsRegBitsOff(dwIoBase, MAC_REG_PSCTL, PSCTL_PS)) + if (MACbIsRegBitsOff(priv, MAC_REG_PSCTL, PSCTL_PS)) return true; /* Disable PS */ @@ -810,11 +834,12 @@ bool MACbPSWakeup(void __iomem *dwIoBase) * */ -void MACvSetKeyEntry(void __iomem *dwIoBase, unsigned short wKeyCtl, +void MACvSetKeyEntry(struct vnt_private *priv, unsigned short wKeyCtl, unsigned int uEntryIdx, unsigned int uKeyIdx, unsigned char *pbyAddr, u32 *pdwKey, unsigned char byLocalID) { + void __iomem *dwIoBase = priv->PortOffset; unsigned short wOffset; u32 dwData; int ii; @@ -878,8 +903,9 @@ void MACvSetKeyEntry(void __iomem *dwIoBase, unsigned short wKeyCtl, * Return Value: none * */ -void MACvDisableKeyEntry(void __iomem *dwIoBase, unsigned int uEntryIdx) +void MACvDisableKeyEntry(struct vnt_private *priv, unsigned int uEntryIdx) { + void __iomem *dwIoBase = priv->PortOffset; unsigned short wOffset; wOffset = MISCFIFO_KEYETRY0; diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index 8e0200a78b19..192f4666539b 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -890,57 +890,57 @@ do { \ #define MACvSetRFLE_LatchBase(dwIoBase) \ MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_RFLEOPT) -bool MACbIsRegBitsOn(void __iomem *dwIoBase, unsigned char byRegOfs, +bool MACbIsRegBitsOn(struct vnt_private *, unsigned char byRegOfs, unsigned char byTestBits); -bool MACbIsRegBitsOff(void __iomem *dwIoBase, unsigned char byRegOfs, +bool MACbIsRegBitsOff(struct vnt_private *, unsigned char byRegOfs, unsigned char byTestBits); -bool MACbIsIntDisable(void __iomem *dwIoBase); +bool MACbIsIntDisable(struct vnt_private *); -void MACvSetShortRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit); +void MACvSetShortRetryLimit(struct vnt_private *, unsigned char byRetryLimit); -void MACvSetLongRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit); -void MACvGetLongRetryLimit(void __iomem *dwIoBase, +void MACvSetLongRetryLimit(struct vnt_private *, unsigned char byRetryLimit); +void MACvGetLongRetryLimit(struct vnt_private *, unsigned char *pbyRetryLimit); -void MACvSetLoopbackMode(void __iomem *dwIoBase, unsigned char byLoopbackMode); +void MACvSetLoopbackMode(struct vnt_private *, unsigned char byLoopbackMode); -void MACvSaveContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf); -void MACvRestoreContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf); +void MACvSaveContext(struct vnt_private *, unsigned char *pbyCxtBuf); +void MACvRestoreContext(struct vnt_private *, unsigned char *pbyCxtBuf); -bool MACbSoftwareReset(void __iomem *dwIoBase); -bool MACbSafeSoftwareReset(void __iomem *dwIoBase); -bool MACbSafeRxOff(void __iomem *dwIoBase); -bool MACbSafeTxOff(void __iomem *dwIoBase); -bool MACbSafeStop(void __iomem *dwIoBase); -bool MACbShutdown(void __iomem *dwIoBase); -void MACvInitialize(void __iomem *dwIoBase); -void MACvSetCurrRx0DescAddr(void __iomem *dwIoBase, +bool MACbSoftwareReset(struct vnt_private *); +bool MACbSafeSoftwareReset(struct vnt_private *); +bool MACbSafeRxOff(struct vnt_private *); +bool MACbSafeTxOff(struct vnt_private *); +bool MACbSafeStop(struct vnt_private *); +bool MACbShutdown(struct vnt_private *); +void MACvInitialize(struct vnt_private *); +void MACvSetCurrRx0DescAddr(struct vnt_private *, unsigned long dwCurrDescAddr); -void MACvSetCurrRx1DescAddr(void __iomem *dwIoBase, +void MACvSetCurrRx1DescAddr(struct vnt_private *, unsigned long dwCurrDescAddr); -void MACvSetCurrTXDescAddr(int iTxType, void __iomem *dwIoBase, +void MACvSetCurrTXDescAddr(int iTxType, struct vnt_private *, unsigned long dwCurrDescAddr); -void MACvSetCurrTx0DescAddrEx(void __iomem *dwIoBase, +void MACvSetCurrTx0DescAddrEx(struct vnt_private *, unsigned long dwCurrDescAddr); -void MACvSetCurrAC0DescAddrEx(void __iomem *dwIoBase, +void MACvSetCurrAC0DescAddrEx(struct vnt_private *, unsigned long dwCurrDescAddr); -void MACvSetCurrSyncDescAddrEx(void __iomem *dwIoBase, +void MACvSetCurrSyncDescAddrEx(struct vnt_private *, unsigned long dwCurrDescAddr); -void MACvSetCurrATIMDescAddrEx(void __iomem *dwIoBase, +void MACvSetCurrATIMDescAddrEx(struct vnt_private *, unsigned long dwCurrDescAddr); -void MACvTimer0MicroSDelay(void __iomem *dwIoBase, unsigned int uDelay); -void MACvOneShotTimer1MicroSec(void __iomem *dwIoBase, unsigned int uDelayTime); +void MACvTimer0MicroSDelay(struct vnt_private *, unsigned int uDelay); +void MACvOneShotTimer1MicroSec(struct vnt_private *, unsigned int uDelayTime); -void MACvSetMISCFifo(void __iomem *dwIoBase, unsigned short wOffset, +void MACvSetMISCFifo(struct vnt_private *, unsigned short wOffset, unsigned long dwData); -bool MACbPSWakeup(void __iomem *dwIoBase); +bool MACbPSWakeup(struct vnt_private *); -void MACvSetKeyEntry(void __iomem *dwIoBase, unsigned short wKeyCtl, +void MACvSetKeyEntry(struct vnt_private *, unsigned short wKeyCtl, unsigned int uEntryIdx, unsigned int uKeyIdx, unsigned char *pbyAddr, u32 *pdwKey, unsigned char byLocalID); -void MACvDisableKeyEntry(void __iomem *dwIoBase, unsigned int uEntryIdx); +void MACvDisableKeyEntry(struct vnt_private *, unsigned int uEntryIdx); #endif /* __MAC_H__ */ diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index 5e968c9340d7..bc8ca981a629 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -120,7 +120,7 @@ PSvDisablePowerSaving( ) { /* disable power saving hw function */ - MACbPSWakeup(priv->PortOffset); + MACbPSWakeup(priv); /* clear AutoSleep */ MACvRegBitsOff(priv->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); /* clear HWUTSF */ diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index 1c0691d18583..3df430bf0a80 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -438,13 +438,13 @@ static bool s_bAL7230Init(struct vnt_private *priv) MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); /* Calibration */ - MACvTimer0MicroSDelay(dwIoBase, 150);/* 150us */ + MACvTimer0MicroSDelay(priv, 150);/* 150us */ /* TXDCOC:active, RCK:disable */ ret &= IFRFbWriteEmbedded(priv, (0x9ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); - MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */ + MACvTimer0MicroSDelay(priv, 30);/* 30us */ /* TXDCOC:disable, RCK:active */ ret &= IFRFbWriteEmbedded(priv, (0x3ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); - MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */ + MACvTimer0MicroSDelay(priv, 30);/* 30us */ /* TXDCOC:disable, RCK:disable */ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]); @@ -483,7 +483,7 @@ static bool s_bAL7230SelectChannel(struct vnt_private *priv, unsigned char byCha /* Set Channel[7] = 0 to tell H/W channel is changing now. */ VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F)); - MACvTimer0MicroSDelay(dwIoBase, SWITCH_CHANNEL_DELAY_AL7230); + MACvTimer0MicroSDelay(priv, SWITCH_CHANNEL_DELAY_AL7230); /* Set Channel[7] = 1 to tell H/W channel change is done. */ VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80)); @@ -557,16 +557,16 @@ static bool RFbAL2230Init(struct vnt_private *priv) for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++) ret &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[ii]); - MACvTimer0MicroSDelay(dwIoBase, 30); /* delay 30 us */ + MACvTimer0MicroSDelay(priv, 30); /* delay 30 us */ /* PLL On */ MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); - MACvTimer0MicroSDelay(dwIoBase, 150);/* 150us */ + MACvTimer0MicroSDelay(priv, 150);/* 150us */ ret &= IFRFbWriteEmbedded(priv, (0x00d80f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); - MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */ + MACvTimer0MicroSDelay(priv, 30);/* 30us */ ret &= IFRFbWriteEmbedded(priv, (0x00780f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); - MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */ + MACvTimer0MicroSDelay(priv, 30);/* 30us */ ret &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]); MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 | @@ -592,7 +592,7 @@ static bool RFbAL2230SelectChannel(struct vnt_private *priv, unsigned char byCha /* Set Channel[7] = 0 to tell H/W channel is changing now. */ VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F)); - MACvTimer0MicroSDelay(dwIoBase, SWITCH_CHANNEL_DELAY_AL2230); + MACvTimer0MicroSDelay(priv, SWITCH_CHANNEL_DELAY_AL2230); /* Set Channel[7] = 1 to tell H/W channel change is done. */ VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80)); @@ -711,11 +711,11 @@ bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, return false; for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++) - MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230InitTable[ii]); + MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230InitTable[ii]); - MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable0[uChannel-1]); + MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable0[uChannel-1]); ii++; - MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable1[uChannel-1]); + MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable1[uChannel-1]); break; /* Need to check, PLLON need to be low for channel setting */ @@ -728,17 +728,17 @@ bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, if (uChannel <= CB_MAX_CHANNEL_24G) { for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++) - MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTable[ii]); + MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTable[ii]); } else { for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++) - MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTableAMode[ii]); + MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTableAMode[ii]); } - MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable0[uChannel-1]); + MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable0[uChannel-1]); ii++; - MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable1[uChannel-1]); + MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable1[uChannel-1]); ii++; - MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable2[uChannel-1]); + MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable2[uChannel-1]); break; case RF_NOTHING: @@ -748,7 +748,7 @@ bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, return false; } - MACvSetMISCFifo(dwIoBase, MISCFIFO_SYNINFO_IDX, (unsigned long)MAKEWORD(bySleepCount, byInitCount)); + MACvSetMISCFifo(priv, MISCFIFO_SYNINFO_IDX, (unsigned long)MAKEWORD(bySleepCount, byInitCount)); return true; } -- cgit v1.2.3 From e7bda76fa4f54df7021e1014a9d20c5a050ca919 Mon Sep 17 00:00:00 2001 From: Alexey Tulia Date: Sat, 21 Nov 2015 15:36:47 +0300 Subject: staging: vt6656: fix definitions of DEVICE_FLAGS_* flags test_bit and set_bit take the bit number to operate on, rather than a mask. This patch fixes the DEVICE_FLAGS_* definitions so that they represent the bit index in priv->flags as opposed to the mask returned by the BIT macro. Signed-off-by: Alexey Tulia Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/device.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 76b5f4127f95..4832666cc580 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -259,8 +259,8 @@ enum { }; /* flags for options */ -#define DEVICE_FLAGS_UNPLUG BIT(0) -#define DEVICE_FLAGS_DISCONNECTED BIT(1) +#define DEVICE_FLAGS_UNPLUG 0 +#define DEVICE_FLAGS_DISCONNECTED 1 struct vnt_private { /* mac80211 */ -- cgit v1.2.3 From 1eba248ae125f66f6c21d99b9d33f766924e4944 Mon Sep 17 00:00:00 2001 From: Sergey Lysanov Date: Fri, 18 Dec 2015 11:06:24 +0300 Subject: drivers:staging:vt6656: Fix coding style issues This patch fixes the following issues reported by checkpatch.pl: - code indent should use tabs where possible Signed-off-by: Sergey Lysanov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c index c025dab0f62c..e322b7d8c617 100644 --- a/drivers/staging/vt6656/power.c +++ b/drivers/staging/vt6656/power.c @@ -103,7 +103,7 @@ void vnt_disable_power_saving(struct vnt_private *priv) /* disable power saving hw function */ vnt_control_out(priv, MESSAGE_TYPE_DISABLE_PS, 0, - 0, 0, NULL); + 0, 0, NULL); /* clear AutoSleep */ vnt_mac_reg_bits_off(priv, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); -- cgit v1.2.3 From d2713e51ebc4c4684afdcc6a0ec76c2142480540 Mon Sep 17 00:00:00 2001 From: maomao xu Date: Thu, 31 Dec 2015 15:20:53 +0800 Subject: Staging: vt6656: Fixed multiple commenting codig style issues. Fixed multiple comment blocks that didn't comply with the kernels coding style. Signed-off-by: maomao xu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/main_usb.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index ee8d1e1a24c2..a2f23aefb35d 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -74,10 +74,10 @@ MODULE_PARM_DESC(tx_buffers, "Number of receive usb tx buffers"); #define LONG_RETRY_DEF 4 /* BasebandType[] baseband type selected - 0: indicate 802.11a type - 1: indicate 802.11b type - 2: indicate 802.11g type -*/ + * 0: indicate 802.11a type + * 1: indicate 802.11b type + * 2: indicate 802.11g type + */ #define BBP_TYPE_DEF 2 @@ -284,7 +284,8 @@ static int vnt_init_registers(struct vnt_private *priv) calib_rx_iq = priv->eeprom[EEP_OFS_CALIB_RX_IQ]; if (calib_tx_iq || calib_tx_dc || calib_rx_iq) { /* CR255, enable TX/RX IQ and - DC compensation mode */ + * DC compensation mode + */ vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0xff, @@ -306,7 +307,8 @@ static int vnt_init_registers(struct vnt_private *priv) calib_rx_iq); } else { /* CR255, turn off - BB Calibration compensation */ + * BB Calibration compensation + */ vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0xff, -- cgit v1.2.3 From 4a55218e0ffb65826f57121e9f0abae72f6c3e52 Mon Sep 17 00:00:00 2001 From: Pranjal Bhor Date: Tue, 19 Jan 2016 01:03:49 +0530 Subject: staging: wlan-ng: Fixed block comments coding style issue All block comment lines now begin with "*" and end with "*/" on a new line. Signed-off-by: Pranjal Bhor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 1b02cdf9d1fa..3121e1dcf793 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -49,7 +49,8 @@ * * -------------------------------------------------------------------- * -*================================================================ */ +*================================================================ +*/ #include #include @@ -101,7 +102,8 @@ static u8 oui_8021h[] = { 0x00, 0x00, 0xf8 }; * * Call context: * May be called in interrupt or non-interrupt context -----------------------------------------------------------------*/ +*---------------------------------------------------------------- +*/ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep) @@ -238,7 +240,8 @@ static void orinoco_spy_gather(wlandevice_t *wlandev, char *mac, int i; /* Gather wireless spy statistics: for each packet, compare the - * source address with out list, and if match, get the stats... */ + * source address with out list, and if match, get the stats... + */ for (i = 0; i < wlandev->spy_number; i++) { @@ -273,7 +276,8 @@ static void orinoco_spy_gather(wlandevice_t *wlandev, char *mac, * * Call context: * May be called in interrupt or non-interrupt context -----------------------------------------------------------------*/ +*---------------------------------------------------------------- +*/ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb) { @@ -421,7 +425,8 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, && (e_llc->ctl == 0x03)) { pr_debug("802.1h/RFC1042 len: %d\n", payload_length); /* it's an 802.1h frame || (an RFC1042 && protocol not in STT) - build a DIXII + RFC894 */ + * build a DIXII + RFC894 + */ /* Test for an overlength frame */ if ((payload_length - sizeof(struct wlan_llc) - @@ -521,14 +526,15 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, * * Call context: * May be called in interrupt or non-interrupt context -----------------------------------------------------------------*/ +*---------------------------------------------------------------- +*/ int p80211_stt_findproto(u16 proto) { /* Always return found for now. This is the behavior used by the */ - /* Zoom Win95 driver when 802.1h mode is selected */ + /* Zoom Win95 driver when 802.1h mode is selected */ /* TODO: If necessary, add an actual search we'll probably - need this to match the CMAC's way of doing things. - Need to do some testing to confirm. + * need this to match the CMAC's way of doing things. + * Need to do some testing to confirm. */ if (proto == ETH_P_AARP) /* APPLETALK */ @@ -551,7 +557,8 @@ int p80211_stt_findproto(u16 proto) * * Call context: * May be called in interrupt or non-interrupt context -----------------------------------------------------------------*/ +*---------------------------------------------------------------- +*/ void p80211skb_rxmeta_detach(struct sk_buff *skb) { struct p80211_rxmeta *rxmeta; @@ -595,7 +602,8 @@ void p80211skb_rxmeta_detach(struct sk_buff *skb) * * Call context: * May be called in interrupt or non-interrupt context -----------------------------------------------------------------*/ +*---------------------------------------------------------------- +*/ int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb) { int result = 0; @@ -648,7 +656,8 @@ exit: * * Call context: * May be called in interrupt or non-interrupt context -----------------------------------------------------------------*/ +*---------------------------------------------------------------- +*/ void p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb) { struct p80211_frmmeta *meta; -- cgit v1.2.3 From 2584538807926344e713548e5210bded8ed22011 Mon Sep 17 00:00:00 2001 From: Pranjal Bhor Date: Tue, 19 Jan 2016 01:04:09 +0530 Subject: staging: wlan-ng: Logical continuation fixes Logical continuation coding style issues fixed while condition checking Signed-off-by: Pranjal Bhor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.c | 47 ++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 3121e1dcf793..81f36241be03 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -153,8 +153,8 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, (struct wlan_snap *) skb_push(skb, sizeof(struct wlan_snap)); e_snap->type = htons(proto); - if (ethconv == WLAN_ETHCONV_8021h - && p80211_stt_findproto(proto)) { + if (ethconv == WLAN_ETHCONV_8021h && + p80211_stt_findproto(proto)) { memcpy(e_snap->oui, oui_8021h, WLAN_IEEE_OUI_LEN); } else { @@ -204,8 +204,8 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, p80211_wep->data = NULL; - if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) - && (wlandev->hostwep & HOSTWEP_ENCRYPT)) { + if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && + (wlandev->hostwep & HOSTWEP_ENCRYPT)) { /* XXXX need to pick keynum other than default? */ p80211_wep->data = kmalloc(skb->len, GFP_ATOMIC); @@ -304,12 +304,12 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, if ((WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 0)) { ether_addr_copy(daddr, w_hdr->a3.a1); ether_addr_copy(saddr, w_hdr->a3.a2); - } else if ((WLAN_GET_FC_TODS(fc) == 0) - && (WLAN_GET_FC_FROMDS(fc) == 1)) { + } else if ((WLAN_GET_FC_TODS(fc) == 0) && + (WLAN_GET_FC_FROMDS(fc) == 1)) { ether_addr_copy(daddr, w_hdr->a3.a1); ether_addr_copy(saddr, w_hdr->a3.a3); - } else if ((WLAN_GET_FC_TODS(fc) == 1) - && (WLAN_GET_FC_FROMDS(fc) == 0)) { + } else if ((WLAN_GET_FC_TODS(fc) == 1) && + (WLAN_GET_FC_FROMDS(fc) == 0)) { ether_addr_copy(daddr, w_hdr->a3.a3); ether_addr_copy(saddr, w_hdr->a3.a2); } else { @@ -324,8 +324,9 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, } /* perform de-wep if necessary.. */ - if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && WLAN_GET_FC_ISWEP(fc) - && (wlandev->hostwep & HOSTWEP_DECRYPT)) { + if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && + WLAN_GET_FC_ISWEP(fc) && + (wlandev->hostwep & HOSTWEP_DECRYPT)) { if (payload_length <= 8) { netdev_err(netdev, "WEP frame too short (%u).\n", skb->len); @@ -383,15 +384,15 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, skb_trim(skb, skb->len - WLAN_CRC_LEN); } else if ((payload_length >= sizeof(struct wlan_llc) + - sizeof(struct wlan_snap)) - && (e_llc->dsap == 0xaa) - && (e_llc->ssap == 0xaa) - && (e_llc->ctl == 0x03) - && - (((memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) == 0) - && (ethconv == WLAN_ETHCONV_8021h) - && (p80211_stt_findproto(le16_to_cpu(e_snap->type)))) - || (memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) != + sizeof(struct wlan_snap)) && + (e_llc->dsap == 0xaa) && + (e_llc->ssap == 0xaa) && + (e_llc->ctl == 0x03) && + (((memcmp(e_snap->oui, oui_rfc1042, + WLAN_IEEE_OUI_LEN) == 0) && + (ethconv == WLAN_ETHCONV_8021h) && + (p80211_stt_findproto(le16_to_cpu(e_snap->type)))) || + (memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) != 0))) { pr_debug("SNAP+RFC1042 len: %d\n", payload_length); /* it's a SNAP + RFC1042 frame && protocol is in STT */ @@ -419,10 +420,10 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, skb_trim(skb, skb->len - WLAN_CRC_LEN); } else if ((payload_length >= sizeof(struct wlan_llc) + - sizeof(struct wlan_snap)) - && (e_llc->dsap == 0xaa) - && (e_llc->ssap == 0xaa) - && (e_llc->ctl == 0x03)) { + sizeof(struct wlan_snap)) && + (e_llc->dsap == 0xaa) && + (e_llc->ssap == 0xaa) && + (e_llc->ctl == 0x03)) { pr_debug("802.1h/RFC1042 len: %d\n", payload_length); /* it's an 802.1h frame || (an RFC1042 && protocol not in STT) * build a DIXII + RFC894 -- cgit v1.2.3 From 3c3424d2484d1fe5856d29189424893926cf7d23 Mon Sep 17 00:00:00 2001 From: Pranjal Bhor Date: Tue, 19 Jan 2016 01:04:25 +0530 Subject: staging: wlan-ng: Removed blank lines after braces Blank lines before closing braces and after opening braces have been removed. Signed-off-by: Pranjal Bhor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 81f36241be03..00d82e25c250 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -108,7 +108,6 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep) { - __le16 fc; u16 proto; struct wlan_ethhdr e_hdr; @@ -169,7 +168,6 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, e_llc->dsap = 0xAA; /* SNAP, see IEEE 802 */ e_llc->ssap = 0xAA; e_llc->ctl = 0x03; - } } @@ -244,7 +242,6 @@ static void orinoco_spy_gather(wlandevice_t *wlandev, char *mac, */ for (i = 0; i < wlandev->spy_number; i++) { - if (!memcmp(wlandev->spy_address[i], mac, ETH_ALEN)) { memcpy(wlandev->spy_address[i], mac, ETH_ALEN); wlandev->spy_stat[i].level = rxmeta->signal; @@ -486,7 +483,6 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, /* chop off the 802.11 CRC */ skb_trim(skb, skb->len - WLAN_CRC_LEN); - } /* -- cgit v1.2.3 From 40defde4a4025cd7aae3afcb54c0b9588d96cb8d Mon Sep 17 00:00:00 2001 From: Pranjal Bhor Date: Tue, 19 Jan 2016 01:04:41 +0530 Subject: staging: wlan-ng: Coding style fix for casting operation Removed spaces after casting operating Signed-off-by: Pranjal Bhor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 00d82e25c250..c4fd5b211cd7 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -149,7 +149,7 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, /* tack on SNAP */ e_snap = - (struct wlan_snap *) skb_push(skb, + (struct wlan_snap *)skb_push(skb, sizeof(struct wlan_snap)); e_snap->type = htons(proto); if (ethconv == WLAN_ETHCONV_8021h && @@ -163,7 +163,7 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, /* tack on llc */ e_llc = - (struct wlan_llc *) skb_push(skb, + (struct wlan_llc *)skb_push(skb, sizeof(struct wlan_llc)); e_llc->dsap = 0xAA; /* SNAP, see IEEE 802 */ e_llc->ssap = 0xAA; @@ -294,7 +294,7 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, payload_length = skb->len - WLAN_HDR_A3_LEN - WLAN_CRC_LEN; payload_offset = WLAN_HDR_A3_LEN; - w_hdr = (union p80211_hdr *) skb->data; + w_hdr = (union p80211_hdr *)skb->data; /* setup some vars for convenience */ fc = le16_to_cpu(w_hdr->a3.fc); @@ -352,11 +352,11 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, wlandev->rx.decrypt++; } - e_hdr = (struct wlan_ethhdr *) (skb->data + payload_offset); + e_hdr = (struct wlan_ethhdr *)(skb->data + payload_offset); - e_llc = (struct wlan_llc *) (skb->data + payload_offset); + e_llc = (struct wlan_llc *)(skb->data + payload_offset); e_snap = - (struct wlan_snap *) (skb->data + payload_offset + + (struct wlan_snap *)(skb->data + payload_offset + sizeof(struct wlan_llc)); /* Test for the various encodings */ @@ -631,7 +631,7 @@ int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb) /* Overlay a frmmeta_t onto skb->cb */ memset(skb->cb, 0, sizeof(struct p80211_frmmeta)); - frmmeta = (struct p80211_frmmeta *) (skb->cb); + frmmeta = (struct p80211_frmmeta *)(skb->cb); frmmeta->magic = P80211_FRMMETA_MAGIC; frmmeta->rx = rxmeta; exit: -- cgit v1.2.3 From 64ddba5275c397e34899a1d77e2ca0ee8e169e4b Mon Sep 17 00:00:00 2001 From: Pranjal Bhor Date: Tue, 19 Jan 2016 01:04:56 +0530 Subject: staging: wlan-ng: Open parenthesis alignment style fix Alignment of lines matched with open parenthesis Signed-off-by: Pranjal Bhor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index c4fd5b211cd7..81f0f06eb597 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -215,8 +215,8 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, p80211_wep->iv, p80211_wep->icv); if (foo) { netdev_warn(wlandev->netdev, - "Host en-WEP failed, dropping frame (%d).\n", - foo); + "Host en-WEP failed, dropping frame (%d).\n", + foo); return 2; } fc |= cpu_to_le16(WLAN_SET_FC_ISWEP(1)); @@ -330,10 +330,10 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, return 1; } foo = wep_decrypt(wlandev, skb->data + payload_offset + 4, - payload_length - 8, -1, - skb->data + payload_offset, - skb->data + payload_offset + - payload_length - 4); + payload_length - 8, -1, + skb->data + payload_offset, + skb->data + payload_offset + + payload_length - 4); if (foo) { /* de-wep failed, drop skb. */ pr_debug("Host de-WEP failed, dropping frame (%d).\n", @@ -371,7 +371,7 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, /* A bogus length ethfrm has been encap'd. */ /* Is someone trying an oflow attack? */ netdev_err(netdev, "ENCAP frame too large (%d > %d)\n", - payload_length, netdev->mtu + ETH_HLEN); + payload_length, netdev->mtu + ETH_HLEN); return 1; } @@ -400,7 +400,7 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, /* A bogus length ethfrm has been sent. */ /* Is someone trying an oflow attack? */ netdev_err(netdev, "SNAP frame too large (%d > %d)\n", - payload_length, netdev->mtu); + payload_length, netdev->mtu); return 1; } @@ -433,9 +433,9 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, /* A bogus length ethfrm has been sent. */ /* Is someone trying an oflow attack? */ netdev_err(netdev, "DIXII frame too large (%ld > %d)\n", - (long int)(payload_length - - sizeof(struct wlan_llc) - - sizeof(struct wlan_snap)), netdev->mtu); + (long int)(payload_length - + sizeof(struct wlan_llc) - + sizeof(struct wlan_snap)), netdev->mtu); return 1; } @@ -468,7 +468,7 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, /* A bogus length ethfrm has been sent. */ /* Is someone trying an oflow attack? */ netdev_err(netdev, "OTHER frame too large (%d > %d)\n", - payload_length, netdev->mtu); + payload_length, netdev->mtu); return 1; } -- cgit v1.2.3 From d23054350d0fafdc4a6f8d68b18cd70ec581c95d Mon Sep 17 00:00:00 2001 From: Pranjal Bhor Date: Tue, 19 Jan 2016 01:05:13 +0530 Subject: staging: wlan-ng: NULL comparisons made elegant Elegance added for NULL comparisons Signed-off-by: Pranjal Bhor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 81f0f06eb597..0a8f3960d465 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -562,17 +562,17 @@ void p80211skb_rxmeta_detach(struct sk_buff *skb) struct p80211_frmmeta *frmmeta; /* Sanity checks */ - if (skb == NULL) { /* bad skb */ + if (!skb) { /* bad skb */ pr_debug("Called w/ null skb.\n"); return; } frmmeta = P80211SKB_FRMMETA(skb); - if (frmmeta == NULL) { /* no magic */ + if (!frmmeta) { /* no magic */ pr_debug("Called w/ bad frmmeta magic.\n"); return; } rxmeta = frmmeta->rx; - if (rxmeta == NULL) { /* bad meta ptr */ + if (!rxmeta) { /* bad meta ptr */ pr_debug("Called w/ bad rxmeta ptr.\n"); return; } @@ -608,7 +608,7 @@ int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb) struct p80211_frmmeta *frmmeta; /* If these already have metadata, we error out! */ - if (P80211SKB_RXMETA(skb) != NULL) { + if (P80211SKB_RXMETA(skb)) { netdev_err(wlandev->netdev, "%s: RXmeta already attached!\n", wlandev->name); result = 0; @@ -618,7 +618,7 @@ int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb) /* Allocate the rxmeta */ rxmeta = kzalloc(sizeof(struct p80211_rxmeta), GFP_ATOMIC); - if (rxmeta == NULL) { + if (!rxmeta) { netdev_err(wlandev->netdev, "%s: Failed to allocate rxmeta.\n", wlandev->name); result = 1; -- cgit v1.2.3 From 3efaf2a9a053bce452cec8d4c14f7ad6912215c9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 29 Jan 2016 16:27:07 +0200 Subject: dmaengine: dw: pci: add ID for WildcatPoint PCH WildcatPoint PCH as seen on MacBook 12-inch (Early 2015) has PCI enabled DesignWare DMA controller. Enable it by adding its ID to the corresponding driver. Reported-by: Leif Liddy BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=110901 Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/dw/pci.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/dw/pci.c b/drivers/dma/dw/pci.c index 4c30fdd092b3..358f9689a3f5 100644 --- a/drivers/dma/dw/pci.c +++ b/drivers/dma/dw/pci.c @@ -108,6 +108,10 @@ static const struct pci_device_id dw_pci_id_table[] = { /* Haswell */ { PCI_VDEVICE(INTEL, 0x9c60) }, + + /* Broadwell */ + { PCI_VDEVICE(INTEL, 0x9ce0) }, + { } }; MODULE_DEVICE_TABLE(pci, dw_pci_id_table); -- cgit v1.2.3 From ea37066d0ee992728c06e8d91f73b34c3982e564 Mon Sep 17 00:00:00 2001 From: Gavin O'Leary Date: Sun, 8 Nov 2015 22:44:20 -0800 Subject: Staging: wlan-ng: p80211wep: fixed a block comment style issue Fixed a comment style issue. Signed-off-by: Gavin O'Leary Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211wep.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c index c363456d93a3..e9f990a52cad 100644 --- a/drivers/staging/wlan-ng/p80211wep.c +++ b/drivers/staging/wlan-ng/p80211wep.c @@ -140,8 +140,8 @@ int wep_change_key(wlandevice_t *wlandev, int keynum, u8 *key, int keylen) } /* - 4-byte IV at start of buffer, 4-byte ICV at end of buffer. - if successful, buf start is payload begin, length -= 8; + * 4-byte IV at start of buffer, 4-byte ICV at end of buffer. + * if successful, buf start is payload begin, length -= 8; */ int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, u8 *iv, u8 *icv) -- cgit v1.2.3 From 1534bc2c0d529cba7f67729d508e3230353c7abc Mon Sep 17 00:00:00 2001 From: Christian Colic Date: Mon, 23 Nov 2015 14:25:05 +0100 Subject: staging: wlan-ng: (coding style) remove unnecessary blank line before "}" Fix checkpatch checks: "Blank lines aren't necessary before a close brace '}' " Remove two unnecessary blank lines. Signed-off-by: Christian Colic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/cfg80211.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 8c1e3f06a215..497e3c987239 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -558,7 +558,6 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, (u8 *)sme->key); if (result) goto exit; - } /* Assume we should set privacy invoked and exclude unencrypted @@ -590,7 +589,6 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, P80211ENUM_truth_false); if (result) goto exit; - } /* Now do the actual join. Note there is no way that I can -- cgit v1.2.3 From 4f9de774a6fea88c1605b58733d7946d9339b0bf Mon Sep 17 00:00:00 2001 From: Gavin O'Leary Date: Mon, 23 Nov 2015 09:08:18 -0800 Subject: staging: wlan-ng: fixed a comment Fixed a comment style issue. Signed-off-by: Gavin O'Leary Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/cfg80211.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 497e3c987239..cdbdcdd85ac0 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -592,7 +592,8 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, } /* Now do the actual join. Note there is no way that I can - see to request a specific bssid */ + * see to request a specific bssid + */ msg_join.msgcode = DIDmsg_lnxreq_autojoin; memcpy(msg_join.ssid.data.data, sme->ssid, length); -- cgit v1.2.3 From 35028fe1a604657d41e51f76e5b4eaecc42d551a Mon Sep 17 00:00:00 2001 From: Gavin O'Leary Date: Mon, 23 Nov 2015 09:23:36 -0800 Subject: staging: wlan-ng: Fixed more comments Fixed more comment issues Signed-off-by: Gavin O'Leary Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/cfg80211.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index cdbdcdd85ac0..4712da1125fa 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -239,7 +239,9 @@ static int prism2_del_key(struct wiphy *wiphy, struct net_device *dev, int result = 0; /* There is no direct way in the hardware (AFAIK) of removing - a key, so we will cheat by setting the key to a bogus value */ + * a key, so we will cheat by setting the key to a bogus value + */ + /* send key to driver */ switch (key_index) { case 0: @@ -561,8 +563,9 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, } /* Assume we should set privacy invoked and exclude unencrypted - We could possibly use sme->privacy here, but the assumption - seems reasonable anyway */ + * We could possible use sme->privacy here, but the assumption + * seems reasonable anyways + */ result = prism2_domibset_uint32(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true); @@ -577,7 +580,8 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, } else { /* Assume we should unset privacy invoked - and exclude unencrypted */ + * and exclude unencrypted + */ result = prism2_domibset_uint32(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false); -- cgit v1.2.3 From 0adf62bfa72a7f526a657db6a8420ba4de2d0205 Mon Sep 17 00:00:00 2001 From: Bogicevic Sasa Date: Mon, 14 Dec 2015 06:11:18 -0800 Subject: drivers:staging:wlan-ng Fix all no space necesarry after a cast This fixes all messages "no space necesarry after a cast" in cfg80211.c file Signed-off-by: Bogicevic Sasa Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/cfg80211.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 4712da1125fa..8bad018eda47 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -73,13 +73,13 @@ static int prism2_domibset_uint32(wlandevice_t *wlandev, u32 did, u32 data) { struct p80211msg_dot11req_mibset msg; p80211item_uint32_t *mibitem = - (p80211item_uint32_t *) &msg.mibattribute.data; + (p80211item_uint32_t *)&msg.mibattribute.data; msg.msgcode = DIDmsg_dot11req_mibset; mibitem->did = did; mibitem->data = data; - return p80211req_dorequest(wlandev, (u8 *) &msg); + return p80211req_dorequest(wlandev, (u8 *)&msg); } static int prism2_domibset_pstr32(wlandevice_t *wlandev, @@ -87,14 +87,14 @@ static int prism2_domibset_pstr32(wlandevice_t *wlandev, { struct p80211msg_dot11req_mibset msg; p80211item_pstr32_t *mibitem = - (p80211item_pstr32_t *) &msg.mibattribute.data; + (p80211item_pstr32_t *)&msg.mibattribute.data; msg.msgcode = DIDmsg_dot11req_mibset; mibitem->did = did; mibitem->data.len = len; memcpy(mibitem->data.data, data, len); - return p80211req_dorequest(wlandev, (u8 *) &msg); + return p80211req_dorequest(wlandev, (u8 *)&msg); } /* The interface functions, called by the cfg80211 layer */ @@ -317,7 +317,7 @@ static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, if (wlandev->mlmerequest == NULL) return -EOPNOTSUPP; - result = wlandev->mlmerequest(wlandev, (struct p80211msg *) &quality); + result = wlandev->mlmerequest(wlandev, (struct p80211msg *)&quality); if (result == 0) { sinfo->txrate.legacy = quality.txrate.data; @@ -389,7 +389,7 @@ static int prism2_scan(struct wiphy *wiphy, msg1.maxchanneltime.data = 250; msg1.minchanneltime.data = 200; - result = p80211req_dorequest(wlandev, (u8 *) &msg1); + result = p80211req_dorequest(wlandev, (u8 *)&msg1); if (result) { err = prism2_result2err(msg1.resultcode.data); goto exit; @@ -404,7 +404,7 @@ static int prism2_scan(struct wiphy *wiphy, msg2.msgcode = DIDmsg_dot11req_scan_results; msg2.bssindex.data = i; - result = p80211req_dorequest(wlandev, (u8 *) &msg2); + result = p80211req_dorequest(wlandev, (u8 *)&msg2); if ((result != 0) || (msg2.resultcode.data != P80211ENUM_resultcode_success)) { break; @@ -419,7 +419,7 @@ static int prism2_scan(struct wiphy *wiphy, bss = cfg80211_inform_bss(wiphy, ieee80211_get_channel(wiphy, freq), CFG80211_BSS_FTYPE_UNKNOWN, - (const u8 *) &(msg2.bssid.data.data), + (const u8 *)&(msg2.bssid.data.data), msg2.timestamp.data, msg2.capinfo.data, msg2.beaconperiod.data, ie_buf, @@ -603,7 +603,7 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, memcpy(msg_join.ssid.data.data, sme->ssid, length); msg_join.ssid.data.len = length; - result = p80211req_dorequest(wlandev, (u8 *) &msg_join); + result = p80211req_dorequest(wlandev, (u8 *)&msg_join); exit: if (result) @@ -626,7 +626,7 @@ static int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev, memcpy(msg_join.ssid.data.data, "---", 3); msg_join.ssid.data.len = 3; - result = p80211req_dorequest(wlandev, (u8 *) &msg_join); + result = p80211req_dorequest(wlandev, (u8 *)&msg_join); if (result) err = -EFAULT; @@ -682,12 +682,12 @@ static int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, int result; int err = 0; - mibitem = (p80211item_uint32_t *) &msg.mibattribute.data; + mibitem = (p80211item_uint32_t *)&msg.mibattribute.data; msg.msgcode = DIDmsg_dot11req_mibget; mibitem->did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel; - result = p80211req_dorequest(wlandev, (u8 *) &msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; -- cgit v1.2.3 From 6c37e1f957be5f67b520e004e196b0e6a9ec2950 Mon Sep 17 00:00:00 2001 From: Bogicevic Sasa Date: Mon, 14 Dec 2015 06:25:59 -0800 Subject: drivers:staging:wlan-ng Fix space preferred around that messages This fixes all "space preferred around that ..." messages from checkpatch.pl Signed-off-by: Bogicevic Sasa Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 7551ac25d89d..a5626df2bebc 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -145,11 +145,11 @@ enum cmd_mode { DOASYNC }; -#define THROTTLE_JIFFIES (HZ/8) +#define THROTTLE_JIFFIES (HZ / 8) #define URB_ASYNC_UNLINK 0 #define USB_QUEUE_BULK 0 -#define ROUNDUP64(a) (((a)+63)&~63) +#define ROUNDUP64(a) (((a) + 63) & ~63) #ifdef DEBUG_USB static void dbprint_urb(struct urb *urb); @@ -3985,8 +3985,7 @@ static void hfa384x_usb_throttlefn(unsigned long data) pr_debug("flags=0x%lx\n", hw->usb_flags); if (!hw->wlandev->hwremoved && ((test_and_clear_bit(THROTTLE_RX, &hw->usb_flags) && - !test_and_set_bit(WORK_RX_RESUME, &hw->usb_flags)) - | + !test_and_set_bit(WORK_RX_RESUME, &hw->usb_flags)) | (test_and_clear_bit(THROTTLE_TX, &hw->usb_flags) && !test_and_set_bit(WORK_TX_RESUME, &hw->usb_flags)) )) { -- cgit v1.2.3 From 57477bf0d9c2d311afe5a4e6b75040aabb3a426e Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Tue, 15 Dec 2015 23:29:32 +0800 Subject: staging: wlan-ng: use list_for_each_entry* Use list_for_each_entry*() instead of list_for_each*() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 17 ++++------------- drivers/staging/wlan-ng/prism2usb.c | 15 +++------------ 2 files changed, 7 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index a5626df2bebc..682de77e7561 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -2810,8 +2810,7 @@ void hfa384x_tx_timeout(wlandevice_t *wlandev) static void hfa384x_usbctlx_reaper_task(unsigned long data) { hfa384x_t *hw = (hfa384x_t *)data; - struct list_head *entry; - struct list_head *temp; + hfa384x_usbctlx_t *ctlx, *temp; unsigned long flags; spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -2819,10 +2818,7 @@ static void hfa384x_usbctlx_reaper_task(unsigned long data) /* This list is guaranteed to be empty if someone * has unplugged the adapter. */ - list_for_each_safe(entry, temp, &hw->ctlxq.reapable) { - hfa384x_usbctlx_t *ctlx; - - ctlx = list_entry(entry, hfa384x_usbctlx_t, list); + list_for_each_entry_safe(ctlx, temp, &hw->ctlxq.reapable, list) { list_del(&ctlx->list); kfree(ctlx); } @@ -2847,8 +2843,7 @@ static void hfa384x_usbctlx_reaper_task(unsigned long data) static void hfa384x_usbctlx_completion_task(unsigned long data) { hfa384x_t *hw = (hfa384x_t *)data; - struct list_head *entry; - struct list_head *temp; + hfa384x_usbctlx_t *ctlx, *temp; unsigned long flags; int reap = 0; @@ -2858,11 +2853,7 @@ static void hfa384x_usbctlx_completion_task(unsigned long data) /* This list is guaranteed to be empty if someone * has unplugged the adapter ... */ - list_for_each_safe(entry, temp, &hw->ctlxq.completing) { - hfa384x_usbctlx_t *ctlx; - - ctlx = list_entry(entry, hfa384x_usbctlx_t, list); - + list_for_each_entry_safe(ctlx, temp, &hw->ctlxq.completing, list) { /* Call the completion function that this * command was assigned, assuming it has one. */ diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c index 8abf3f87a2d5..194f67e0fc06 100644 --- a/drivers/staging/wlan-ng/prism2usb.c +++ b/drivers/staging/wlan-ng/prism2usb.c @@ -139,8 +139,7 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface) wlandev = (wlandevice_t *)usb_get_intfdata(interface); if (wlandev != NULL) { LIST_HEAD(cleanlist); - struct list_head *entry; - struct list_head *temp; + hfa384x_usbctlx_t *ctlx, *temp; unsigned long flags; hfa384x_t *hw = wlandev->priv; @@ -184,12 +183,8 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface) * and tell everyone who is waiting for their * responses that we have shut down. */ - list_for_each(entry, &cleanlist) { - hfa384x_usbctlx_t *ctlx; - - ctlx = list_entry(entry, hfa384x_usbctlx_t, list); + list_for_each_entry(ctlx, &cleanlist, list) complete(&ctlx->done); - } /* Give any outstanding synchronous commands * a chance to complete. All they need to do @@ -199,12 +194,8 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface) msleep(100); /* Now delete the CTLXs, because no-one else can now. */ - list_for_each_safe(entry, temp, &cleanlist) { - hfa384x_usbctlx_t *ctlx; - - ctlx = list_entry(entry, hfa384x_usbctlx_t, list); + list_for_each_entry_safe(ctlx, temp, &cleanlist, list) kfree(ctlx); - } /* Unhook the wlandev */ unregister_wlandev(wlandev); -- cgit v1.2.3 From 78f5d21018f65d2208c645c84228bcdc3eb68367 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 2 Feb 2016 01:01:28 +0530 Subject: Staging:speakup:add space around '|' Fix checkpatch.pl check:CHECK: spaces preferred around that '|'. Add spaces around operands to fix these warnings. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/speakup_decext.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/speakup/speakup_decext.c b/drivers/staging/speakup/speakup_decext.c index fdd7488f554c..1a5cf3d0a559 100644 --- a/drivers/staging/speakup/speakup_decext.c +++ b/drivers/staging/speakup/speakup_decext.c @@ -67,30 +67,30 @@ static struct var_t vars[] = { * These attributes will appear in /sys/accessibility/speakup/decext. */ static struct kobj_attribute caps_start_attribute = - __ATTR(caps_start, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(caps_start, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute caps_stop_attribute = - __ATTR(caps_stop, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(caps_stop, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute pitch_attribute = - __ATTR(pitch, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(pitch, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute punct_attribute = - __ATTR(punct, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(punct, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute rate_attribute = - __ATTR(rate, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(rate, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute voice_attribute = - __ATTR(voice, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(voice, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute vol_attribute = - __ATTR(vol, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(vol, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute delay_time_attribute = - __ATTR(delay_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(delay_time, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute direct_attribute = - __ATTR(direct, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(direct, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute full_time_attribute = - __ATTR(full_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(full_time, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute jiffy_delta_attribute = - __ATTR(jiffy_delta, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(jiffy_delta, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute trigger_time_attribute = - __ATTR(trigger_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(trigger_time, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); /* * Create a group of attributes so that we can create and destroy them all -- cgit v1.2.3 From 679c2c758c501c833a271a08aa4adbb601c42f63 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:21 -0600 Subject: staging: fsl-mc: Added generic MSI support for FSL-MC devices Created an MSI domain for the fsl-mc bus-- including functions to create a domain, find a domain, alloc/free domain irqs, and bus specific overrides for domain and irq_chip ops. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/Kconfig | 1 + drivers/staging/fsl-mc/bus/Makefile | 1 + drivers/staging/fsl-mc/bus/mc-msi.c | 276 ++++++++++++++++++++++++++++ drivers/staging/fsl-mc/include/dprc.h | 2 +- drivers/staging/fsl-mc/include/mc-private.h | 17 ++ drivers/staging/fsl-mc/include/mc.h | 17 ++ 6 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 drivers/staging/fsl-mc/bus/mc-msi.c (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/Kconfig b/drivers/staging/fsl-mc/bus/Kconfig index 0d779d9ccbd8..c498ac6a72d5 100644 --- a/drivers/staging/fsl-mc/bus/Kconfig +++ b/drivers/staging/fsl-mc/bus/Kconfig @@ -9,6 +9,7 @@ config FSL_MC_BUS tristate "Freescale Management Complex (MC) bus driver" depends on OF && ARM64 + select GENERIC_MSI_IRQ_DOMAIN help Driver to enable the bus infrastructure for the Freescale QorIQ Management Complex (fsl-mc). The fsl-mc is a hardware diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile index 25433a998478..a5f2ba4e6bf7 100644 --- a/drivers/staging/fsl-mc/bus/Makefile +++ b/drivers/staging/fsl-mc/bus/Makefile @@ -13,5 +13,6 @@ mc-bus-driver-objs := mc-bus.o \ dpmng.o \ dprc-driver.o \ mc-allocator.o \ + mc-msi.o \ dpmcp.o \ dpbp.o diff --git a/drivers/staging/fsl-mc/bus/mc-msi.c b/drivers/staging/fsl-mc/bus/mc-msi.c new file mode 100644 index 000000000000..3a8258ff4426 --- /dev/null +++ b/drivers/staging/fsl-mc/bus/mc-msi.c @@ -0,0 +1,276 @@ +/* + * Freescale Management Complex (MC) bus driver MSI support + * + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Author: German Rivera + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include "../include/mc-private.h" +#include +#include +#include +#include +#include +#include +#include +#include "../include/mc-sys.h" +#include "dprc-cmd.h" + +static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg, + struct msi_desc *desc) +{ + arg->desc = desc; + arg->hwirq = (irq_hw_number_t)desc->fsl_mc.msi_index; +} + +static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info) +{ + struct msi_domain_ops *ops = info->ops; + + if (WARN_ON(!ops)) + return; + + /* + * set_desc should not be set by the caller + */ + if (WARN_ON(ops->set_desc)) + return; + + ops->set_desc = fsl_mc_msi_set_desc; +} + +static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev, + struct fsl_mc_device_irq *mc_dev_irq) +{ + int error; + struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev; + struct msi_desc *msi_desc = mc_dev_irq->msi_desc; + struct dprc_irq_cfg irq_cfg; + + /* + * msi_desc->msg.address is 0x0 when this function is invoked in + * the free_irq() code path. In this case, for the MC, we don't + * really need to "unprogram" the MSI, so we just return. + */ + if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0) + return; + + if (WARN_ON(!owner_mc_dev)) + return; + + irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) | + msi_desc->msg.address_lo; + irq_cfg.val = msi_desc->msg.data; + irq_cfg.user_irq_id = msi_desc->irq; + + if (owner_mc_dev == mc_bus_dev) { + /* + * IRQ is for the mc_bus_dev's DPRC itself + */ + error = dprc_set_irq(mc_bus_dev->mc_io, + MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, + mc_bus_dev->mc_handle, + mc_dev_irq->dev_irq_index, + &irq_cfg); + if (error < 0) { + dev_err(&owner_mc_dev->dev, + "dprc_set_irq() failed: %d\n", error); + } + } else { + /* + * IRQ is for for a child device of mc_bus_dev + */ + error = dprc_set_obj_irq(mc_bus_dev->mc_io, + MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, + mc_bus_dev->mc_handle, + owner_mc_dev->obj_desc.type, + owner_mc_dev->obj_desc.id, + mc_dev_irq->dev_irq_index, + &irq_cfg); + if (error < 0) { + dev_err(&owner_mc_dev->dev, + "dprc_obj_set_irq() failed: %d\n", error); + } + } +} + +/* + * NOTE: This function is invoked with interrupts disabled + */ +static void fsl_mc_msi_write_msg(struct irq_data *irq_data, + struct msi_msg *msg) +{ + struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data); + struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev); + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); + struct fsl_mc_device_irq *mc_dev_irq = + &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index]; + + WARN_ON(mc_dev_irq->msi_desc != msi_desc); + msi_desc->msg = *msg; + + /* + * Program the MSI (paddr, value) pair in the device: + */ + __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq); +} + +static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info) +{ + struct irq_chip *chip = info->chip; + + if (WARN_ON((!chip))) + return; + + /* + * irq_write_msi_msg should not be set by the caller + */ + if (WARN_ON(chip->irq_write_msi_msg)) + return; + + chip->irq_write_msi_msg = fsl_mc_msi_write_msg; +} + +/** + * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain + * @np: Optional device-tree node of the interrupt controller + * @info: MSI domain info + * @parent: Parent irq domain + * + * Updates the domain and chip ops and creates a fsl-mc MSI + * interrupt domain. + * + * Returns: + * A domain pointer or NULL in case of failure. + */ +struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, + struct msi_domain_info *info, + struct irq_domain *parent) +{ + struct irq_domain *domain; + + if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) + fsl_mc_msi_update_dom_ops(info); + if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) + fsl_mc_msi_update_chip_ops(info); + + domain = msi_create_irq_domain(fwnode, info, parent); + if (domain) + domain->bus_token = DOMAIN_BUS_FSL_MC_MSI; + + return domain; +} + +int fsl_mc_find_msi_domain(struct device *mc_platform_dev, + struct irq_domain **mc_msi_domain) +{ + struct irq_domain *msi_domain; + struct device_node *mc_of_node = mc_platform_dev->of_node; + + msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node, + DOMAIN_BUS_FSL_MC_MSI); + if (!msi_domain) { + pr_err("Unable to find fsl-mc MSI domain for %s\n", + mc_of_node->full_name); + + return -ENOENT; + } + + *mc_msi_domain = msi_domain; + return 0; +} + +static void fsl_mc_msi_free_descs(struct device *dev) +{ + struct msi_desc *desc, *tmp; + + list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) { + list_del(&desc->list); + free_msi_entry(desc); + } +} + +static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count) + +{ + unsigned int i; + int error; + struct msi_desc *msi_desc; + + for (i = 0; i < irq_count; i++) { + msi_desc = alloc_msi_entry(dev); + if (!msi_desc) { + dev_err(dev, "Failed to allocate msi entry\n"); + error = -ENOMEM; + goto cleanup_msi_descs; + } + + msi_desc->fsl_mc.msi_index = i; + msi_desc->nvec_used = 1; + INIT_LIST_HEAD(&msi_desc->list); + list_add_tail(&msi_desc->list, dev_to_msi_list(dev)); + } + + return 0; + +cleanup_msi_descs: + fsl_mc_msi_free_descs(dev); + return error; +} + +int fsl_mc_msi_domain_alloc_irqs(struct device *dev, + unsigned int irq_count) +{ + struct irq_domain *msi_domain; + int error; + + if (WARN_ON(!list_empty(dev_to_msi_list(dev)))) + return -EINVAL; + + error = fsl_mc_msi_alloc_descs(dev, irq_count); + if (error < 0) + return error; + + msi_domain = dev_get_msi_domain(dev); + if (WARN_ON(!msi_domain)) { + error = -EINVAL; + goto cleanup_msi_descs; + } + + /* + * NOTE: Calling this function will trigger the invocation of the + * its_fsl_mc_msi_prepare() callback + */ + error = msi_domain_alloc_irqs(msi_domain, dev, irq_count); + + if (error) { + dev_err(dev, "Failed to allocate IRQs\n"); + goto cleanup_msi_descs; + } + + return 0; + +cleanup_msi_descs: + fsl_mc_msi_free_descs(dev); + return error; +} + +void fsl_mc_msi_domain_free_irqs(struct device *dev) +{ + struct irq_domain *msi_domain; + + msi_domain = dev_get_msi_domain(dev); + if (WARN_ON(!msi_domain)) + return; + + msi_domain_free_irqs(msi_domain, dev); + + if (WARN_ON(list_empty(dev_to_msi_list(dev)))) + return; + + fsl_mc_msi_free_descs(dev); +} diff --git a/drivers/staging/fsl-mc/include/dprc.h b/drivers/staging/fsl-mc/include/dprc.h index c3152f677ff1..94c492706315 100644 --- a/drivers/staging/fsl-mc/include/dprc.h +++ b/drivers/staging/fsl-mc/include/dprc.h @@ -176,7 +176,7 @@ int dprc_reset_container(struct fsl_mc_io *mc_io, * @user_irq_id: A user defined number associated with this IRQ */ struct dprc_irq_cfg { - u64 paddr; + phys_addr_t paddr; u32 val; int user_irq_id; }; diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h index c706f778626e..36b418c23fd7 100644 --- a/drivers/staging/fsl-mc/include/mc-private.h +++ b/drivers/staging/fsl-mc/include/mc-private.h @@ -26,6 +26,9 @@ strcmp(_obj_type, "dpmcp") == 0 || \ strcmp(_obj_type, "dpcon") == 0) +struct irq_domain; +struct msi_domain_info; + /** * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device * @root_mc_bus_dev: MC object device representing the root DPRC @@ -79,11 +82,13 @@ struct fsl_mc_resource_pool { * @resource_pools: array of resource pools (one pool per resource type) * for this MC bus. These resources represent allocatable entities * from the physical DPRC. + * @irq_resources: Pointer to array of IRQ objects for the IRQ pool * @scan_mutex: Serializes bus scanning */ struct fsl_mc_bus { struct fsl_mc_device mc_dev; struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES]; + struct fsl_mc_device_irq *irq_resources; struct mutex scan_mutex; /* serializes bus scanning */ }; @@ -116,4 +121,16 @@ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, void fsl_mc_resource_free(struct fsl_mc_resource *resource); +struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, + struct msi_domain_info *info, + struct irq_domain *parent); + +int fsl_mc_find_msi_domain(struct device *mc_platform_dev, + struct irq_domain **mc_msi_domain); + +int fsl_mc_msi_domain_alloc_irqs(struct device *dev, + unsigned int irq_count); + +void fsl_mc_msi_domain_free_irqs(struct device *dev); + #endif /* _FSL_MC_PRIVATE_H_ */ diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h index a933291e400a..1c1d6ae64996 100644 --- a/drivers/staging/fsl-mc/include/mc.h +++ b/drivers/staging/fsl-mc/include/mc.h @@ -103,6 +103,23 @@ struct fsl_mc_resource { struct list_head node; }; +/** + * struct fsl_mc_device_irq - MC object device message-based interrupt + * @msi_desc: pointer to MSI descriptor allocated by fsl_mc_msi_alloc_descs() + * @mc_dev: MC object device that owns this interrupt + * @dev_irq_index: device-relative IRQ index + * @resource: MC generic resource associated with the interrupt + */ +struct fsl_mc_device_irq { + struct msi_desc *msi_desc; + struct fsl_mc_device *mc_dev; + u8 dev_irq_index; + struct fsl_mc_resource resource; +}; + +#define to_fsl_mc_irq(_mc_resource) \ + container_of(_mc_resource, struct fsl_mc_device_irq, resource) + /** * Bit masks for a MC object device (struct fsl_mc_device) flags */ -- cgit v1.2.3 From 3a288fd51b41a2998195c321d8dd4a229176e6f7 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:22 -0600 Subject: staging: fsl-mc: Added GICv3-ITS support for FSL-MC MSIs Added platform-specific MSI support layer for FSL-MC devices. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/Makefile | 1 + .../staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c | 127 +++++++++++++++++++++ drivers/staging/fsl-mc/include/mc-private.h | 4 + 3 files changed, 132 insertions(+) create mode 100644 drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile index a5f2ba4e6bf7..e7315170b7a3 100644 --- a/drivers/staging/fsl-mc/bus/Makefile +++ b/drivers/staging/fsl-mc/bus/Makefile @@ -14,5 +14,6 @@ mc-bus-driver-objs := mc-bus.o \ dprc-driver.o \ mc-allocator.o \ mc-msi.o \ + irq-gic-v3-its-fsl-mc-msi.o \ dpmcp.o \ dpbp.o diff --git a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c new file mode 100644 index 000000000000..4e8e822da51d --- /dev/null +++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c @@ -0,0 +1,127 @@ +/* + * Freescale Management Complex (MC) bus driver MSI support + * + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Author: German Rivera + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include "../include/mc-private.h" +#include +#include +#include +#include +#include +#include +#include +#include "../include/mc-sys.h" +#include "dprc-cmd.h" + +static struct irq_chip its_msi_irq_chip = { + .name = "fsl-mc-bus-msi", + .irq_mask = irq_chip_mask_parent, + .irq_unmask = irq_chip_unmask_parent, + .irq_eoi = irq_chip_eoi_parent, + .irq_set_affinity = msi_domain_set_affinity +}; + +static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain, + struct device *dev, + int nvec, msi_alloc_info_t *info) +{ + struct fsl_mc_device *mc_bus_dev; + struct msi_domain_info *msi_info; + + if (WARN_ON(dev->bus != &fsl_mc_bus_type)) + return -EINVAL; + + mc_bus_dev = to_fsl_mc_device(dev); + if (WARN_ON(!(mc_bus_dev->flags & FSL_MC_IS_DPRC))) + return -EINVAL; + + /* + * Set the device Id to be passed to the GIC-ITS: + * + * NOTE: This device id corresponds to the IOMMU stream ID + * associated with the DPRC object (ICID). + */ + info->scratchpad[0].ul = mc_bus_dev->icid; + msi_info = msi_get_domain_info(msi_domain->parent); + return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info); +} + +static struct msi_domain_ops its_fsl_mc_msi_ops = { + .msi_prepare = its_fsl_mc_msi_prepare, +}; + +static struct msi_domain_info its_fsl_mc_msi_domain_info = { + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS), + .ops = &its_fsl_mc_msi_ops, + .chip = &its_msi_irq_chip, +}; + +static const struct of_device_id its_device_id[] = { + { .compatible = "arm,gic-v3-its", }, + {}, +}; + +int __init its_fsl_mc_msi_init(void) +{ + struct device_node *np; + struct irq_domain *parent; + struct irq_domain *mc_msi_domain; + + for (np = of_find_matching_node(NULL, its_device_id); np; + np = of_find_matching_node(np, its_device_id)) { + if (!of_property_read_bool(np, "msi-controller")) + continue; + + parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS); + if (!parent || !msi_get_domain_info(parent)) { + pr_err("%s: unable to locate ITS domain\n", + np->full_name); + continue; + } + + mc_msi_domain = fsl_mc_msi_create_irq_domain( + of_node_to_fwnode(np), + &its_fsl_mc_msi_domain_info, + parent); + if (!mc_msi_domain) { + pr_err("%s: unable to create fsl-mc domain\n", + np->full_name); + continue; + } + + WARN_ON(mc_msi_domain-> + host_data != &its_fsl_mc_msi_domain_info); + + pr_info("fsl-mc MSI: %s domain created\n", np->full_name); + } + + return 0; +} + +void its_fsl_mc_msi_cleanup(void) +{ + struct device_node *np; + + for (np = of_find_matching_node(NULL, its_device_id); np; + np = of_find_matching_node(np, its_device_id)) { + struct irq_domain *mc_msi_domain = irq_find_matching_host( + np, + DOMAIN_BUS_FSL_MC_MSI); + + if (!of_property_read_bool(np, "msi-controller")) + continue; + + mc_msi_domain = irq_find_matching_host(np, + DOMAIN_BUS_FSL_MC_MSI); + if (mc_msi_domain && + mc_msi_domain->host_data == &its_fsl_mc_msi_domain_info) + irq_domain_remove(mc_msi_domain); + } +} diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h index 36b418c23fd7..28c8d322b2a3 100644 --- a/drivers/staging/fsl-mc/include/mc-private.h +++ b/drivers/staging/fsl-mc/include/mc-private.h @@ -133,4 +133,8 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev, void fsl_mc_msi_domain_free_irqs(struct device *dev); +int __init its_fsl_mc_msi_init(void); + +void its_fsl_mc_msi_cleanup(void); + #endif /* _FSL_MC_PRIVATE_H_ */ -- cgit v1.2.3 From 89f067df928b9bfc53430b09aa4ac894f34f7340 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:23 -0600 Subject: staging: fsl-mc: Extended MC bus allocator to include IRQs All the IRQs for DPAA2 objects in the same DPRC must use the ICID of that DPRC, as their device Id in the GIC-ITS. Thus, all these IRQs must share the same ITT table in the GIC. As a result, a pool of IRQs with the same device Id must be preallocated per DPRC (fsl-mc bus instance). So, the fsl-mc bus object allocator is extended to also provide services to allocate IRQs to DPAA2 devices, from their parent fsl-mc bus IRQ pool. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/mc-allocator.c | 199 ++++++++++++++++++++++++++++ drivers/staging/fsl-mc/include/mc-private.h | 15 +++ drivers/staging/fsl-mc/include/mc.h | 9 ++ 3 files changed, 223 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/mc-allocator.c b/drivers/staging/fsl-mc/bus/mc-allocator.c index 88d1857521a5..c5fa628411ec 100644 --- a/drivers/staging/fsl-mc/bus/mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/mc-allocator.c @@ -15,6 +15,7 @@ #include "../include/dpcon-cmd.h" #include "dpmcp-cmd.h" #include "dpmcp.h" +#include /** * fsl_mc_resource_pool_add_device - add allocatable device to a resource @@ -160,6 +161,7 @@ static const char *const fsl_mc_pool_type_strings[] = { [FSL_MC_POOL_DPMCP] = "dpmcp", [FSL_MC_POOL_DPBP] = "dpbp", [FSL_MC_POOL_DPCON] = "dpcon", + [FSL_MC_POOL_IRQ] = "irq", }; static int __must_check object_type_to_pool_type(const char *object_type, @@ -465,6 +467,203 @@ void fsl_mc_object_free(struct fsl_mc_device *mc_adev) } EXPORT_SYMBOL_GPL(fsl_mc_object_free); +/* + * Initialize the interrupt pool associated with a MC bus. + * It allocates a block of IRQs from the GIC-ITS + */ +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, + unsigned int irq_count) +{ + unsigned int i; + struct msi_desc *msi_desc; + struct fsl_mc_device_irq *irq_resources; + struct fsl_mc_device_irq *mc_dev_irq; + int error; + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; + struct fsl_mc_resource_pool *res_pool = + &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; + + if (WARN_ON(irq_count == 0 || + irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)) + return -EINVAL; + + error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count); + if (error < 0) + return error; + + irq_resources = devm_kzalloc(&mc_bus_dev->dev, + sizeof(*irq_resources) * irq_count, + GFP_KERNEL); + if (!irq_resources) { + error = -ENOMEM; + goto cleanup_msi_irqs; + } + + for (i = 0; i < irq_count; i++) { + mc_dev_irq = &irq_resources[i]; + + /* + * NOTE: This mc_dev_irq's MSI addr/value pair will be set + * by the fsl_mc_msi_write_msg() callback + */ + mc_dev_irq->resource.type = res_pool->type; + mc_dev_irq->resource.data = mc_dev_irq; + mc_dev_irq->resource.parent_pool = res_pool; + INIT_LIST_HEAD(&mc_dev_irq->resource.node); + list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list); + } + + for_each_msi_entry(msi_desc, &mc_bus_dev->dev) { + mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index]; + mc_dev_irq->msi_desc = msi_desc; + mc_dev_irq->resource.id = msi_desc->irq; + } + + res_pool->max_count = irq_count; + res_pool->free_count = irq_count; + mc_bus->irq_resources = irq_resources; + return 0; + +cleanup_msi_irqs: + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); + return error; +} +EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); + +/** + * Teardown the interrupt pool associated with an MC bus. + * It frees the IRQs that were allocated to the pool, back to the GIC-ITS. + */ +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) +{ + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; + struct fsl_mc_resource_pool *res_pool = + &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; + + if (WARN_ON(!mc_bus->irq_resources)) + return; + + if (WARN_ON(res_pool->max_count == 0)) + return; + + if (WARN_ON(res_pool->free_count != res_pool->max_count)) + return; + + INIT_LIST_HEAD(&res_pool->free_list); + res_pool->max_count = 0; + res_pool->free_count = 0; + mc_bus->irq_resources = NULL; + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); +} +EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool); + +/** + * It allocates the IRQs required by a given MC object device. The + * IRQs are allocated from the interrupt pool associated with the + * MC bus that contains the device, if the device is not a DPRC device. + * Otherwise, the IRQs are allocated from the interrupt pool associated + * with the MC bus that represents the DPRC device itself. + */ +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) +{ + int i; + int irq_count; + int res_allocated_count = 0; + int error = -EINVAL; + struct fsl_mc_device_irq **irqs = NULL; + struct fsl_mc_bus *mc_bus; + struct fsl_mc_resource_pool *res_pool; + + if (WARN_ON(mc_dev->irqs)) + return -EINVAL; + + irq_count = mc_dev->obj_desc.irq_count; + if (WARN_ON(irq_count == 0)) + return -EINVAL; + + if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) + mc_bus = to_fsl_mc_bus(mc_dev); + else + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); + + if (WARN_ON(!mc_bus->irq_resources)) + return -EINVAL; + + res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; + if (res_pool->free_count < irq_count) { + dev_err(&mc_dev->dev, + "Not able to allocate %u irqs for device\n", irq_count); + return -ENOSPC; + } + + irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]), + GFP_KERNEL); + if (!irqs) + return -ENOMEM; + + for (i = 0; i < irq_count; i++) { + struct fsl_mc_resource *resource; + + error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ, + &resource); + if (error < 0) + goto error_resource_alloc; + + irqs[i] = to_fsl_mc_irq(resource); + res_allocated_count++; + + WARN_ON(irqs[i]->mc_dev); + irqs[i]->mc_dev = mc_dev; + irqs[i]->dev_irq_index = i; + } + + mc_dev->irqs = irqs; + return 0; + +error_resource_alloc: + for (i = 0; i < res_allocated_count; i++) { + irqs[i]->mc_dev = NULL; + fsl_mc_resource_free(&irqs[i]->resource); + } + + return error; +} +EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs); + +/* + * It frees the IRQs that were allocated for a MC object device, by + * returning them to the corresponding interrupt pool. + */ +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) +{ + int i; + int irq_count; + struct fsl_mc_bus *mc_bus; + struct fsl_mc_device_irq **irqs = mc_dev->irqs; + + if (WARN_ON(!irqs)) + return; + + irq_count = mc_dev->obj_desc.irq_count; + + if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) + mc_bus = to_fsl_mc_bus(mc_dev); + else + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); + + if (WARN_ON(!mc_bus->irq_resources)) + return; + + for (i = 0; i < irq_count; i++) { + WARN_ON(!irqs[i]->mc_dev); + irqs[i]->mc_dev = NULL; + fsl_mc_resource_free(&irqs[i]->resource); + } + + mc_dev->irqs = NULL; +} +EXPORT_SYMBOL_GPL(fsl_mc_free_irqs); + /** * fsl_mc_allocator_probe - callback invoked when an allocatable device is * being added to the system diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h index 28c8d322b2a3..3babe92d8abc 100644 --- a/drivers/staging/fsl-mc/include/mc-private.h +++ b/drivers/staging/fsl-mc/include/mc-private.h @@ -29,6 +29,16 @@ struct irq_domain; struct msi_domain_info; +/** + * Maximum number of total IRQs that can be pre-allocated for an MC bus' + * IRQ pool + */ +#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256 + +struct device_node; +struct irq_domain; +struct msi_domain_info; + /** * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device * @root_mc_bus_dev: MC object device representing the root DPRC @@ -137,4 +147,9 @@ int __init its_fsl_mc_msi_init(void); void its_fsl_mc_msi_cleanup(void); +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, + unsigned int irq_count); + +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus); + #endif /* _FSL_MC_PRIVATE_H_ */ diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h index 1c1d6ae64996..ac7c1ce68c03 100644 --- a/drivers/staging/fsl-mc/include/mc.h +++ b/drivers/staging/fsl-mc/include/mc.h @@ -14,12 +14,14 @@ #include #include #include +#include #include "../include/dprc.h" #define FSL_MC_VENDOR_FREESCALE 0x1957 struct fsl_mc_device; struct fsl_mc_io; +struct fsl_mc_bus; /** * struct fsl_mc_driver - MC object device driver object @@ -75,6 +77,7 @@ enum fsl_mc_pool_type { FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */ FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */ FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */ + FSL_MC_POOL_IRQ, /* * NOTE: New resource pool types must be added before this entry @@ -141,6 +144,7 @@ struct fsl_mc_device_irq { * NULL if none. * @obj_desc: MC description of the DPAA device * @regions: pointer to array of MMIO region entries + * @irqs: pointer to array of pointers to interrupts allocated to this device * @resource: generic resource associated with this MC object device, if any. * * Generic device object for MC object devices that are "attached" to a @@ -172,6 +176,7 @@ struct fsl_mc_device { struct fsl_mc_io *mc_io; struct dprc_obj_desc obj_desc; struct resource *regions; + struct fsl_mc_device_irq **irqs; struct fsl_mc_resource *resource; }; @@ -215,6 +220,10 @@ int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, void fsl_mc_object_free(struct fsl_mc_device *mc_adev); +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev); + +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev); + extern struct bus_type fsl_mc_bus_type; #endif /* _FSL_MC_H_ */ -- cgit v1.2.3 From 1129cde59d08afd91fb2baed66824eb2dbd079aa Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:24 -0600 Subject: staging: fsl-mc: Changed DPRC built-in portal's mc_io to be atomic The DPRC built-in portal's mc_io is used to send commands to the MC to program MSIs for MC objects. This is done by the fsl_mc_msi_write_msg() callback, which is invoked by the generic MSI layer with interrupts disabled. As a result, the mc_io used in fsl_mc_msi_write_msg needs to be an atomic mc_io. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dprc-driver.c | 4 +++- drivers/staging/fsl-mc/bus/mc-bus.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 2c4cd70b4cbb..767d437837e7 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -396,7 +396,9 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) error = fsl_create_mc_io(&mc_dev->dev, mc_dev->regions[0].start, region_size, - NULL, 0, &mc_dev->mc_io); + NULL, + FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, + &mc_dev->mc_io); if (error < 0) return error; } diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c index 84db55b4dda5..d34f1af39746 100644 --- a/drivers/staging/fsl-mc/bus/mc-bus.c +++ b/drivers/staging/fsl-mc/bus/mc-bus.c @@ -702,7 +702,8 @@ static int fsl_mc_bus_probe(struct platform_device *pdev) mc_portal_phys_addr = res.start; mc_portal_size = resource_size(&res); error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr, - mc_portal_size, NULL, 0, &mc_io); + mc_portal_size, NULL, + FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io); if (error < 0) return error; -- cgit v1.2.3 From 1e4aa42aa9a16d3ec2bbbf7e7d946603b52217de Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:25 -0600 Subject: staging: fsl-mc: Populate the IRQ pool for an MC bus instance Scan the corresponding DPRC container to get total count of IRQs needed by all its child DPAA2 objects. Then, preallocate a set of MSI IRQs with the DPRC's ICID (GIT-ITS device Id) to populate the the DPRC's IRQ pool. Each child DPAA2 object in the DPRC and the DPRC object itself will allocate their necessary MSI IRQs from the DPRC's IRQ pool, in their driver probe function. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dprc-driver.c | 24 ++++++++++++++++++++++-- drivers/staging/fsl-mc/include/mc-private.h | 3 ++- 2 files changed, 24 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 767d437837e7..ef1bb9315c4c 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -241,6 +241,7 @@ static void dprc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) * dprc_scan_objects - Discover objects in a DPRC * * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object + * @total_irq_count: total number of IRQs needed by objects in the DPRC. * * Detects objects added and removed from a DPRC and synchronizes the * state of the Linux bus driver, MC by adding and removing @@ -254,11 +255,13 @@ static void dprc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) * populated before they can get allocation requests from probe callbacks * of the device drivers for the non-allocatable devices. */ -int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev) +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, + unsigned int *total_irq_count) { int num_child_objects; int dprc_get_obj_failures; int error; + unsigned int irq_count = mc_bus_dev->obj_desc.irq_count; struct dprc_obj_desc *child_obj_desc_array = NULL; error = dprc_get_obj_count(mc_bus_dev->mc_io, @@ -307,6 +310,7 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev) continue; } + irq_count += obj_desc->irq_count; dev_dbg(&mc_bus_dev->dev, "Discovered object: type %s, id %d\n", obj_desc->type, obj_desc->id); @@ -319,6 +323,7 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev) } } + *total_irq_count = irq_count; dprc_remove_devices(mc_bus_dev, child_obj_desc_array, num_child_objects); @@ -344,6 +349,7 @@ EXPORT_SYMBOL_GPL(dprc_scan_objects); int dprc_scan_container(struct fsl_mc_device *mc_bus_dev) { int error; + unsigned int irq_count; struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); dprc_init_all_resource_pools(mc_bus_dev); @@ -352,11 +358,25 @@ int dprc_scan_container(struct fsl_mc_device *mc_bus_dev) * Discover objects in the DPRC: */ mutex_lock(&mc_bus->scan_mutex); - error = dprc_scan_objects(mc_bus_dev); + error = dprc_scan_objects(mc_bus_dev, &irq_count); mutex_unlock(&mc_bus->scan_mutex); if (error < 0) goto error; + if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) { + if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { + dev_warn(&mc_bus_dev->dev, + "IRQs needed (%u) exceed IRQs preallocated (%u)\n", + irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); + } + + error = fsl_mc_populate_irq_pool( + mc_bus, + FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); + if (error < 0) + goto error; + } + return 0; error: dprc_cleanup_all_resource_pools(mc_bus_dev); diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h index 3babe92d8abc..be72a44ba064 100644 --- a/drivers/staging/fsl-mc/include/mc-private.h +++ b/drivers/staging/fsl-mc/include/mc-private.h @@ -114,7 +114,8 @@ void fsl_mc_device_remove(struct fsl_mc_device *mc_dev); int dprc_scan_container(struct fsl_mc_device *mc_bus_dev); -int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev); +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, + unsigned int *total_irq_count); int __init dprc_driver_init(void); -- cgit v1.2.3 From 232ae8f2494e3ba445e7f07705f5c3296102bb4c Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:26 -0600 Subject: staging: fsl-mc: set MSI domain for DPRC objects THE MSI domain associated with a root DPRC object is obtained form the device tree. Child DPRCs inherit the parent DPRC MSI domain. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dprc-driver.c | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index ef1bb9315c4c..38fc404fde4f 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -13,6 +13,7 @@ #include "../include/mc-sys.h" #include #include +#include #include "dprc-cmd.h" struct dprc_child_objs { @@ -398,11 +399,16 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) { int error; size_t region_size; + struct device *parent_dev = mc_dev->dev.parent; struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); + bool msi_domain_set = false; if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) return -EINVAL; + if (WARN_ON(dev_get_msi_domain(&mc_dev->dev))) + return -EINVAL; + if (!mc_dev->mc_io) { /* * This is a child DPRC: @@ -421,6 +427,30 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) &mc_dev->mc_io); if (error < 0) return error; + /* + * Inherit parent MSI domain: + */ + dev_set_msi_domain(&mc_dev->dev, + dev_get_msi_domain(parent_dev)); + msi_domain_set = true; + } else { + /* + * This is a root DPRC + */ + struct irq_domain *mc_msi_domain; + + if (WARN_ON(parent_dev->bus == &fsl_mc_bus_type)) + return -EINVAL; + + error = fsl_mc_find_msi_domain(parent_dev, + &mc_msi_domain); + if (error < 0) { + dev_warn(&mc_dev->dev, + "WARNING: MC bus without interrupt support\n"); + } else { + dev_set_msi_domain(&mc_dev->dev, mc_msi_domain); + msi_domain_set = true; + } } error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id, @@ -446,6 +476,9 @@ error_cleanup_open: (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); error_cleanup_mc_io: + if (msi_domain_set) + dev_set_msi_domain(&mc_dev->dev, NULL); + fsl_destroy_mc_io(mc_dev->mc_io); return error; } @@ -463,6 +496,7 @@ error_cleanup_mc_io: static int dprc_remove(struct fsl_mc_device *mc_dev) { int error; + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) return -EINVAL; @@ -475,6 +509,11 @@ static int dprc_remove(struct fsl_mc_device *mc_dev) if (error < 0) dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error); + if (dev_get_msi_domain(&mc_dev->dev)) { + fsl_mc_cleanup_irq_pool(mc_bus); + dev_set_msi_domain(&mc_dev->dev, NULL); + } + dev_info(&mc_dev->dev, "DPRC device unbound from driver"); return 0; } -- cgit v1.2.3 From 8804f9fc5cf38c29c56f041341685edfc623f427 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:27 -0600 Subject: staging: fsl-mc: Fixed bug in dprc_probe() error path Destroy mc_io in error path in dprc_probe() only if the mc_io was created in this function. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dprc-driver.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 38fc404fde4f..42b249404632 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -401,6 +401,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) size_t region_size; struct device *parent_dev = mc_dev->dev.parent; struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); + bool mc_io_created = false; bool msi_domain_set = false; if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) @@ -413,6 +414,9 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) /* * This is a child DPRC: */ + if (WARN_ON(parent_dev->bus != &fsl_mc_bus_type)) + return -EINVAL; + if (WARN_ON(mc_dev->obj_desc.region_count == 0)) return -EINVAL; @@ -427,6 +431,9 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) &mc_dev->mc_io); if (error < 0) return error; + + mc_io_created = true; + /* * Inherit parent MSI domain: */ @@ -457,7 +464,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) &mc_dev->mc_handle); if (error < 0) { dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error); - goto error_cleanup_mc_io; + goto error_cleanup_msi_domain; } mutex_init(&mc_bus->scan_mutex); @@ -475,11 +482,15 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) error_cleanup_open: (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); -error_cleanup_mc_io: +error_cleanup_msi_domain: if (msi_domain_set) dev_set_msi_domain(&mc_dev->dev, NULL); - fsl_destroy_mc_io(mc_dev->mc_io); + if (mc_io_created) { + fsl_destroy_mc_io(mc_dev->mc_io); + mc_dev->mc_io = NULL; + } + return error; } -- cgit v1.2.3 From f52dee5ccdf57364299448c88787ff92656d1ed2 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:28 -0600 Subject: staging: fsl-mc: Added DPRC interrupt handler The interrupt handler for DPRC IRQs is added. DPRC IRQs are generated for hot plug events related to DPAA2 objects in a given DPRC. These events include, creating/destroying DPAA2 objects in the DPRC, changing the "plugged" state of DPAA2 objects and moving objects between DPRCs. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dprc-driver.c | 247 +++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 42b249404632..52c6fce0fd29 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "dprc-cmd.h" struct dprc_child_objs { @@ -385,6 +386,230 @@ error: } EXPORT_SYMBOL_GPL(dprc_scan_container); +/** + * dprc_irq0_handler - Regular ISR for DPRC interrupt 0 + * + * @irq: IRQ number of the interrupt being handled + * @arg: Pointer to device structure + */ +static irqreturn_t dprc_irq0_handler(int irq_num, void *arg) +{ + return IRQ_WAKE_THREAD; +} + +/** + * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0 + * + * @irq: IRQ number of the interrupt being handled + * @arg: Pointer to device structure + */ +static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg) +{ + int error; + u32 status; + struct device *dev = (struct device *)arg; + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); + struct fsl_mc_io *mc_io = mc_dev->mc_io; + struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc; + + dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n", + irq_num, smp_processor_id()); + + if (WARN_ON(!(mc_dev->flags & FSL_MC_IS_DPRC))) + return IRQ_HANDLED; + + mutex_lock(&mc_bus->scan_mutex); + if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num)) + goto out; + + error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0, + &status); + if (error < 0) { + dev_err(dev, + "dprc_get_irq_status() failed: %d\n", error); + goto out; + } + + error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, + status); + if (error < 0) { + dev_err(dev, + "dprc_clear_irq_status() failed: %d\n", error); + goto out; + } + + if (status & (DPRC_IRQ_EVENT_OBJ_ADDED | + DPRC_IRQ_EVENT_OBJ_REMOVED | + DPRC_IRQ_EVENT_CONTAINER_DESTROYED | + DPRC_IRQ_EVENT_OBJ_DESTROYED | + DPRC_IRQ_EVENT_OBJ_CREATED)) { + unsigned int irq_count; + + error = dprc_scan_objects(mc_dev, &irq_count); + if (error < 0) { + /* + * If the error is -ENXIO, we ignore it, as it indicates + * that the object scan was aborted, as we detected that + * an object was removed from the DPRC in the MC, while + * we were scanning the DPRC. + */ + if (error != -ENXIO) { + dev_err(dev, "dprc_scan_objects() failed: %d\n", + error); + } + + goto out; + } + + if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { + dev_warn(dev, + "IRQs needed (%u) exceed IRQs preallocated (%u)\n", + irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); + } + } + +out: + mutex_unlock(&mc_bus->scan_mutex); + return IRQ_HANDLED; +} + +/* + * Disable and clear interrupt for a given DPRC object + */ +static int disable_dprc_irq(struct fsl_mc_device *mc_dev) +{ + int error; + struct fsl_mc_io *mc_io = mc_dev->mc_io; + + WARN_ON(mc_dev->obj_desc.irq_count != 1); + + /* + * Disable generation of interrupt, while we configure it: + */ + error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0); + if (error < 0) { + dev_err(&mc_dev->dev, + "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", + error); + return error; + } + + /* + * Disable all interrupt causes for the interrupt: + */ + error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0); + if (error < 0) { + dev_err(&mc_dev->dev, + "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", + error); + return error; + } + + /* + * Clear any leftover interrupts: + */ + error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U); + if (error < 0) { + dev_err(&mc_dev->dev, + "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n", + error); + return error; + } + + return 0; +} + +static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev) +{ + int error; + struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; + + WARN_ON(mc_dev->obj_desc.irq_count != 1); + + /* + * NOTE: devm_request_threaded_irq() invokes the device-specific + * function that programs the MSI physically in the device + */ + error = devm_request_threaded_irq(&mc_dev->dev, + irq->msi_desc->irq, + dprc_irq0_handler, + dprc_irq0_handler_thread, + IRQF_NO_SUSPEND | IRQF_ONESHOT, + "FSL MC DPRC irq0", + &mc_dev->dev); + if (error < 0) { + dev_err(&mc_dev->dev, + "devm_request_threaded_irq() failed: %d\n", + error); + return error; + } + + return 0; +} + +static int enable_dprc_irq(struct fsl_mc_device *mc_dev) +{ + int error; + + /* + * Enable all interrupt causes for the interrupt: + */ + error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, + ~0x0u); + if (error < 0) { + dev_err(&mc_dev->dev, + "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", + error); + + return error; + } + + /* + * Enable generation of the interrupt: + */ + error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1); + if (error < 0) { + dev_err(&mc_dev->dev, + "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", + error); + + return error; + } + + return 0; +} + +/* + * Setup interrupt for a given DPRC device + */ +static int dprc_setup_irq(struct fsl_mc_device *mc_dev) +{ + int error; + + error = fsl_mc_allocate_irqs(mc_dev); + if (error < 0) + return error; + + error = disable_dprc_irq(mc_dev); + if (error < 0) + goto error_free_irqs; + + error = register_dprc_irq_handler(mc_dev); + if (error < 0) + goto error_free_irqs; + + error = enable_dprc_irq(mc_dev); + if (error < 0) + goto error_free_irqs; + + return 0; + +error_free_irqs: + fsl_mc_free_irqs(mc_dev); + return error; +} + /** * dprc_probe - callback invoked when a DPRC is being bound to this driver * @@ -476,6 +701,13 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) if (error < 0) goto error_cleanup_open; + /* + * Configure interrupt for the DPRC object associated with this MC bus: + */ + error = dprc_setup_irq(mc_dev); + if (error < 0) + goto error_cleanup_open; + dev_info(&mc_dev->dev, "DPRC device bound to driver"); return 0; @@ -494,6 +726,15 @@ error_cleanup_msi_domain: return error; } +/* + * Tear down interrupt for a given DPRC object + */ +static void dprc_teardown_irq(struct fsl_mc_device *mc_dev) +{ + (void)disable_dprc_irq(mc_dev); + fsl_mc_free_irqs(mc_dev); +} + /** * dprc_remove - callback invoked when a DPRC is being unbound from this driver * @@ -514,6 +755,12 @@ static int dprc_remove(struct fsl_mc_device *mc_dev) if (WARN_ON(!mc_dev->mc_io)) return -EINVAL; + if (WARN_ON(!mc_bus->irq_resources)) + return -EINVAL; + + if (dev_get_msi_domain(&mc_dev->dev)) + dprc_teardown_irq(mc_dev); + device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove); dprc_cleanup_all_resource_pools(mc_dev); error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); -- cgit v1.2.3 From 660a24bf60821ce9f5799b0772a0a82c922c72c1 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:29 -0600 Subject: staging: fsl-mc: Added MSI support to the MC bus driver Initialize/Cleanup ITS-MSI support for the MC bus driver at driver init/exit time. Associate an MSI domain with each DPAA2 child device. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/mc-bus.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c index d34f1af39746..9317561973b1 100644 --- a/drivers/staging/fsl-mc/bus/mc-bus.c +++ b/drivers/staging/fsl-mc/bus/mc-bus.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include "../include/dpmng.h" #include "../include/mc-sys.h" #include "dprc-cmd.h" @@ -472,6 +474,8 @@ int fsl_mc_device_add(struct dprc_obj_desc *obj_desc, mc_dev->icid = parent_mc_dev->icid; mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK; mc_dev->dev.dma_mask = &mc_dev->dma_mask; + dev_set_msi_domain(&mc_dev->dev, + dev_get_msi_domain(&parent_mc_dev->dev)); } /* @@ -833,8 +837,15 @@ static int __init fsl_mc_bus_driver_init(void) if (error < 0) goto error_cleanup_dprc_driver; + error = its_fsl_mc_msi_init(); + if (error < 0) + goto error_cleanup_mc_allocator; + return 0; +error_cleanup_mc_allocator: + fsl_mc_allocator_driver_exit(); + error_cleanup_dprc_driver: dprc_driver_exit(); @@ -856,6 +867,7 @@ static void __exit fsl_mc_bus_driver_exit(void) if (WARN_ON(!mc_dev_cache)) return; + its_fsl_mc_msi_cleanup(); fsl_mc_allocator_driver_exit(); dprc_driver_exit(); platform_driver_unregister(&fsl_mc_bus_driver); -- cgit v1.2.3 From 4ac31d18e4125eb2970e69069a15308cbb8e4486 Mon Sep 17 00:00:00 2001 From: John Ogness Date: Thu, 28 Jan 2016 11:29:08 +0100 Subject: dmaengine: edma: fix residue race for cyclic When retrieving the residue value, the SRC/DST fields of the active PaRAM are read to determine the current position of the DMA engine. However, the AM335x Technical Reference Manual states: 11.3.3.6 Parameter Set Updates After the TR is read from the PaRAM (and is in the process of being submitted to the EDMA3TC), the following fields are updated as needed: ... SRC DST This means SRC/DST is incremented even though the DMA transfer may not have started yet or is in progress. Thus if the reader of the residue accesses the DMA buffer too quickly, the CPU is misinformed about the data that has been successfully processed. The CCSTAT.ACTV register is a boolean that is set if any TR is being processed by either the EMDA3CC or EDMA3TC. By polling this register it is possible to ensure that the residue value returned is valid for immediate processing. However, since the DMA engine may be active, polling may never hit a moment where no TR is being processed. To handle this, the SRC/DST is also polled to see if it changes. And as a last resort, a max loop count for the busy waiting exists to avoid an infinite loop. Signed-off-by: John Ogness Acked-by: Peter Ujfalusi Signed-off-by: Vinod Koul --- drivers/dma/edma.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c index d92d65549406..e3d7fcb69b4c 100644 --- a/drivers/dma/edma.c +++ b/drivers/dma/edma.c @@ -113,6 +113,9 @@ #define GET_NUM_REGN(x) ((x & 0x300000) >> 20) /* bits 20-21 */ #define CHMAP_EXIST BIT(24) +/* CCSTAT register */ +#define EDMA_CCSTAT_ACTV BIT(4) + /* * Max of 20 segments per channel to conserve PaRAM slots * Also note that MAX_NR_SG should be atleast the no.of periods @@ -1680,9 +1683,20 @@ static void edma_issue_pending(struct dma_chan *chan) spin_unlock_irqrestore(&echan->vchan.lock, flags); } +/* + * This limit exists to avoid a possible infinite loop when waiting for proof + * that a particular transfer is completed. This limit can be hit if there + * are large bursts to/from slow devices or the CPU is never able to catch + * the DMA hardware idle. On an AM335x transfering 48 bytes from the UART + * RX-FIFO, as many as 55 loops have been seen. + */ +#define EDMA_MAX_TR_WAIT_LOOPS 1000 + static u32 edma_residue(struct edma_desc *edesc) { bool dst = edesc->direction == DMA_DEV_TO_MEM; + int loop_count = EDMA_MAX_TR_WAIT_LOOPS; + struct edma_chan *echan = edesc->echan; struct edma_pset *pset = edesc->pset; dma_addr_t done, pos; int i; @@ -1691,7 +1705,32 @@ static u32 edma_residue(struct edma_desc *edesc) * We always read the dst/src position from the first RamPar * pset. That's the one which is active now. */ - pos = edma_get_position(edesc->echan->ecc, edesc->echan->slot[0], dst); + pos = edma_get_position(echan->ecc, echan->slot[0], dst); + + /* + * "pos" may represent a transfer request that is still being + * processed by the EDMACC or EDMATC. We will busy wait until + * any one of the situations occurs: + * 1. the DMA hardware is idle + * 2. a new transfer request is setup + * 3. we hit the loop limit + */ + while (edma_read(echan->ecc, EDMA_CCSTAT) & EDMA_CCSTAT_ACTV) { + /* check if a new transfer request is setup */ + if (edma_get_position(echan->ecc, + echan->slot[0], dst) != pos) { + break; + } + + if (!--loop_count) { + dev_dbg_ratelimited(echan->vchan.chan.device->dev, + "%s: timeout waiting for PaRAM update\n", + __func__); + break; + } + + cpu_relax(); + } /* * Cyclic is simple. Just subtract pset[0].addr from pos. -- cgit v1.2.3 From 5c229d00a58df469550dbc1f4e3a360eb8958661 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 3 Feb 2016 11:55:34 +0100 Subject: dmaengine: sh: Use ARCH_RENESAS Make use of ARCH_RENESAS in place of ARCH_SHMOBILE. This is part of an ongoing process to migrate from ARCH_SHMOBILE to ARCH_RENESAS the motivation for which being that RENESAS seems to be a more appropriate name than SHMOBILE for the majority of Renesas ARM based SoCs. Signed-off-by: Simon Horman Signed-off-by: Vinod Koul --- drivers/dma/sh/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/sh/Kconfig b/drivers/dma/sh/Kconfig index f32c430eb16c..6e0685f1a838 100644 --- a/drivers/dma/sh/Kconfig +++ b/drivers/dma/sh/Kconfig @@ -12,7 +12,7 @@ config RENESAS_DMA config SH_DMAE_BASE bool "Renesas SuperH DMA Engine support" - depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST + depends on SUPERH || ARCH_RENESAS || COMPILE_TEST depends on !SUPERH || SH_DMA depends on !SH_DMA_API default y @@ -41,7 +41,7 @@ endif config RCAR_DMAC tristate "Renesas R-Car Gen2 DMA Controller" - depends on ARCH_SHMOBILE || COMPILE_TEST + depends on ARCH_RENESAS || COMPILE_TEST select RENESAS_DMA help This driver supports the general purpose DMA controller found in the @@ -49,7 +49,7 @@ config RCAR_DMAC config RENESAS_USB_DMAC tristate "Renesas USB-DMA Controller" - depends on ARCH_SHMOBILE || COMPILE_TEST + depends on ARCH_RENESAS || COMPILE_TEST select RENESAS_DMA select DMA_VIRTUAL_CHANNELS help -- cgit v1.2.3 From 5a89a875c96a9d038715c42f5f712002ce5124d0 Mon Sep 17 00:00:00 2001 From: Hamish Martin Date: Tue, 22 Dec 2015 10:23:58 +1300 Subject: staging: octeon-ethernet: fix TCP/UDP checksum calc If the network portion of a frame is preceded by more than 14 bytes of data, the checksum calculated in the HW is done over the wrong data and is put in the wrong place. In our use case an Octeon ethernet controller is connected to a Broadcom switch chip. Extra data is included in the frame prior to egressing the Octeon ethernet (i.e. 4 bytes of an 802.1Q tag, 4 bytes of a proprietary BCM tag later stripped by the switch chip). This extra data causes the checksum calculation to be incorrect. The fix in this patch is to make use of the network header offset of the skb. This enables the checksum to be calculated correctly. This has been tested in both the configuration with the switch chip in the egress path (as described above) and in a simple connection direct to the wire. Reviewed-by: Richard Laing Reviewed-by: Tim Beale Reviewed-by: Chris Packham Signed-off-by: Hamish Martin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index c053c4a47a7e..5611a0269aa8 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -403,7 +403,7 @@ dont_put_skbuff_in_hw: ((ip_hdr(skb)->protocol == IPPROTO_TCP) || (ip_hdr(skb)->protocol == IPPROTO_UDP))) { /* Use hardware checksum calc */ - pko_command.s.ipoffp1 = sizeof(struct ethhdr) + 1; + pko_command.s.ipoffp1 = skb_network_offset(skb) + 1; } if (USE_ASYNC_IOBDMA) { -- cgit v1.2.3 From 7c0b6bce6e848a59cd15d1ade9db346d34d90c5a Mon Sep 17 00:00:00 2001 From: Luuk Paulussen Date: Wed, 23 Dec 2015 09:51:14 +1300 Subject: staging: octeon: Fix logic for waking octeon ethernet tx queue. Only wake tx queue when driver queue is back within bounds. The logic here was just reenabling the queue when any buffers had been freed. the queue was stopped whenever the length exceeded 1000 (MAX_OUT_QUEUE_DEPTH), but then was essentially immediately started again. On a congested link, the queue length would just keep increasing up to around 8000 (for average size packets), at which point the hardware would start refusing the packets and they would begin to be dropped. This prevented the qdisc layer from effectively managing and prioritising packets, as essentially all packets were being allowed into the driver queue and then were being dropped by the hardware. This change only restarts the queue if the length is less than 1000 (MAX_OUT_QUEUE_DEPTH). Reviewed-by: Kyeong Yoo Reviewed-by: Chris Packham Reviewed-by: Richard Laing Signed-off-by: Luuk Paulussen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index 5611a0269aa8..82abaeca27a7 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -126,7 +126,7 @@ static void cvm_oct_free_tx_skbs(struct net_device *dev) } total_remaining += skb_queue_len(&priv->tx_free_list[qos]); } - if (total_freed >= 0 && netif_queue_stopped(dev)) + if (total_remaining < MAX_OUT_QUEUE_DEPTH && netif_queue_stopped(dev)) netif_wake_queue(dev); if (total_remaining) cvm_oct_kick_tx_poll_watchdog(); -- cgit v1.2.3 From edb0d9d4a3fe65cb08dab750b4ad6c2ae5d65d50 Mon Sep 17 00:00:00 2001 From: Saatvik Arya Date: Sun, 3 Jan 2016 22:42:40 +0530 Subject: drivers: staging: octeon-usb: octeon-hcd.c: fixed coding style related warnings fixed coding style warnings related to comment blocks Signed-off-by: Saatvik Arya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/octeon-hcd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 6f2871784ba5..16d45879d0c4 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -2006,7 +2006,8 @@ static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb, urb->hcpriv = NULL; /* For Isochronous transactions we need to update the URB packet status - list from data in our private copy */ + * list from data in our private copy + */ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { int i; /* -- cgit v1.2.3 From a6fccdb5078e1d78df0066b7746cd06c32bc2cb8 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Wed, 3 Feb 2016 01:08:03 +0530 Subject: Staging:octeon:removed blank line after { Removed blank line after curly braces. Found using checkpatch.pl. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-rgmii.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index 1055ee14b66a..9353796af0b6 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -247,9 +247,7 @@ int cvm_oct_rgmii_init(struct net_device *dev) if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) && (priv->port == 0)) || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { - if (!octeon_is_simulation()) { - union cvmx_gmxx_rxx_int_en gmx_rx_int_en; int interface = INTERFACE(priv->port); int index = INDEX(priv->port); @@ -283,9 +281,7 @@ void cvm_oct_rgmii_uninit(struct net_device *dev) if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) && (priv->port == 0)) || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { - if (!octeon_is_simulation()) { - union cvmx_gmxx_rxx_int_en gmx_rx_int_en; int interface = INTERFACE(priv->port); int index = INDEX(priv->port); -- cgit v1.2.3 From 3dd0af86a05d112c72cf4d9353ed725202ed67db Mon Sep 17 00:00:00 2001 From: Bogicevic Sasa Date: Fri, 13 Nov 2015 14:55:47 +0100 Subject: drivers:staging:fwserial Fix No space is necessary after a cast This fixes all "No space is necessary after a cast" messages Signed-off-by: Bogicevic Sasa Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fwserial/fwserial.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index e481d3230f86..9b23b5c95f5e 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c @@ -1464,9 +1464,9 @@ static void fwtty_debugfs_show_peer(struct seq_file *m, struct fwtty_peer *peer) seq_printf(m, " %s:", dev_name(&peer->unit->device)); seq_printf(m, " node:%04x gen:%d", peer->node_id, generation); seq_printf(m, " sp:%d max:%d guid:%016llx", peer->speed, - peer->max_payload, (unsigned long long) peer->guid); - seq_printf(m, " mgmt:%012llx", (unsigned long long) peer->mgmt_addr); - seq_printf(m, " addr:%012llx", (unsigned long long) peer->status_addr); + peer->max_payload, (unsigned long long)peer->guid); + seq_printf(m, " mgmt:%012llx", (unsigned long long)peer->mgmt_addr); + seq_printf(m, " addr:%012llx", (unsigned long long)peer->status_addr); seq_putc(m, '\n'); } @@ -1513,7 +1513,7 @@ static int fwtty_debugfs_peers_show(struct seq_file *m, void *v) rcu_read_lock(); seq_printf(m, "card: %s guid: %016llx\n", dev_name(serial->card->device), - (unsigned long long) serial->card->guid); + (unsigned long long)serial->card->guid); list_for_each_entry_rcu(peer, &serial->peer_list, list) fwtty_debugfs_show_peer(m, peer); rcu_read_unlock(); @@ -1985,7 +1985,7 @@ static struct fwtty_peer *__fwserial_peer_by_node_id(struct fw_card *card, * been probed for any unit devices... */ fwtty_err(card, "unknown card (guid %016llx)\n", - (unsigned long long) card->guid); + (unsigned long long)card->guid); return NULL; } @@ -2015,7 +2015,7 @@ static void __dump_peer_list(struct fw_card *card) smp_rmb(); fwtty_dbg(card, "peer(%d:%x) guid: %016llx\n", - g, peer->node_id, (unsigned long long) peer->guid); + g, peer->node_id, (unsigned long long)peer->guid); } } #else @@ -2312,7 +2312,7 @@ static int fwserial_create(struct fw_unit *unit) list_add_rcu(&serial->list, &fwserial_list); fwtty_notice(&unit, "TTY over FireWire on device %s (guid %016llx)\n", - dev_name(card->device), (unsigned long long) card->guid); + dev_name(card->device), (unsigned long long)card->guid); err = fwserial_add_peer(serial, unit); if (!err) -- cgit v1.2.3 From de593dca1b6b4a932d465214dab311d5daacfa76 Mon Sep 17 00:00:00 2001 From: Christian Colic Date: Tue, 17 Nov 2015 13:56:31 +0100 Subject: staging: fwserial: (coding-style) rewrite comparisons to NULL as "!fifo->data" Rewrite multiple comparisons to NULL as "!fifo->data" to fix the last coding style problems of this file. Signed-off-by: Christian Colic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fwserial/dma_fifo.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fwserial/dma_fifo.c b/drivers/staging/fwserial/dma_fifo.c index 7a3347c3d02b..4cd3ed3ee141 100644 --- a/drivers/staging/fwserial/dma_fifo.c +++ b/drivers/staging/fwserial/dma_fifo.c @@ -106,7 +106,7 @@ void dma_fifo_free(struct dma_fifo *fifo) { struct dma_pending *pending, *next; - if (fifo->data == NULL) + if (!fifo->data) return; list_for_each_entry_safe(pending, next, &fifo->pending, link) @@ -123,7 +123,7 @@ void dma_fifo_reset(struct dma_fifo *fifo) { struct dma_pending *pending, *next; - if (fifo->data == NULL) + if (!fifo->data) return; list_for_each_entry_safe(pending, next, &fifo->pending, link) @@ -149,7 +149,7 @@ int dma_fifo_in(struct dma_fifo *fifo, const void *src, int n) { int ofs, l; - if (fifo->data == NULL) + if (!fifo->data) return -ENOENT; if (fifo->corrupt) return -ENXIO; @@ -192,7 +192,7 @@ int dma_fifo_out_pend(struct dma_fifo *fifo, struct dma_pending *pended) { unsigned len, n, ofs, l, limit; - if (fifo->data == NULL) + if (!fifo->data) return -ENOENT; if (fifo->corrupt) return -ENXIO; @@ -252,7 +252,7 @@ int dma_fifo_out_complete(struct dma_fifo *fifo, struct dma_pending *complete) { struct dma_pending *pending, *next, *tmp; - if (fifo->data == NULL) + if (!fifo->data) return -ENOENT; if (fifo->corrupt) return -ENXIO; -- cgit v1.2.3 From 2fe9f8caadff1e5d3069e93192a544613d4ecbf3 Mon Sep 17 00:00:00 2001 From: Nizam Haider Date: Sun, 22 Nov 2015 09:39:26 +0530 Subject: Staging: fbtft: fbtft-core: Removed unnecessary checks The driver core clears the driver data to NULL after device_release or on probe failure. Signed-off-by: Nizam Haider Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fbtft-core.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index b1e45161eefc..6824d5ff2d8c 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -989,8 +989,6 @@ reg_fail: par->fbtftops.unregister_backlight(par); if (spi) spi_set_drvdata(spi, NULL); - if (par->pdev) - platform_set_drvdata(par->pdev, NULL); return ret; } @@ -1012,8 +1010,6 @@ int fbtft_unregister_framebuffer(struct fb_info *fb_info) if (spi) spi_set_drvdata(spi, NULL); - if (par->pdev) - platform_set_drvdata(par->pdev, NULL); if (par->fbtftops.unregister_backlight) par->fbtftops.unregister_backlight(par); fbtft_sysfs_exit(par); -- cgit v1.2.3 From fd59f106f431e1a9ffc77ec0bbe7032249998699 Mon Sep 17 00:00:00 2001 From: Ben Gilbert Date: Mon, 14 Dec 2015 19:32:21 +0000 Subject: Staging: fbtft: Removed commented out/dead code Deleted various commented out lines that have been replaced by write_reg() Signed-off-by: Ben Gilbert Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_uc1701.c | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fbtft/fb_uc1701.c b/drivers/staging/fbtft/fb_uc1701.c index 212908e39277..b78045fe5393 100644 --- a/drivers/staging/fbtft/fb_uc1701.c +++ b/drivers/staging/fbtft/fb_uc1701.c @@ -78,11 +78,11 @@ static int init_display(struct fbtft_par *par) mdelay(10); /* set startpoint */ - /* LCD_START_LINE | (pos & 0x3F) */ write_reg(par, LCD_START_LINE); /* select orientation BOTTOMVIEW */ write_reg(par, LCD_BOTTOMVIEW | 1); + /* output mode select (turns display upside-down) */ write_reg(par, LCD_SCAN_DIR | 0x00); @@ -96,20 +96,14 @@ static int init_display(struct fbtft_par *par) write_reg(par, LCD_BIAS | 0); /* power control mode: all features on */ - /* LCD_POWER_CONTROL | (val&0x07) */ write_reg(par, LCD_POWER_CONTROL | 0x07); /* set voltage regulator R/R */ - /* LCD_VOLTAGE | (val&0x07) */ write_reg(par, LCD_VOLTAGE | 0x07); /* volume mode set */ - /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */ write_reg(par, LCD_VOLUME_MODE); - /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */ write_reg(par, 0x09); - /* ???? */ - /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */ write_reg(par, LCD_NO_OP); /* advanced program control */ @@ -125,17 +119,8 @@ static int init_display(struct fbtft_par *par) static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) { /* goto address */ - /* LCD_PAGE_ADDRESS | ((page) & 0x1F), - (((col)+SHIFT_ADDR_NORMAL) & 0x0F), - LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ write_reg(par, LCD_PAGE_ADDRESS); - /* LCD_PAGE_ADDRESS | ((page) & 0x1F), - (((col)+SHIFT_ADDR_NORMAL) & 0x0F), - LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ write_reg(par, 0x00); - /* LCD_PAGE_ADDRESS | ((page) & 0x1F), - (((col)+SHIFT_ADDR_NORMAL) & 0x0F), - LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ write_reg(par, LCD_COL_ADDRESS); } @@ -156,17 +141,9 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) 1 : 0) << i; buf++; } - /* LCD_PAGE_ADDRESS | ((page) & 0x1F), - (((col)+SHIFT_ADDR_NORMAL) & 0x0F), - LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ + write_reg(par, LCD_PAGE_ADDRESS | (u8)y); - /* LCD_PAGE_ADDRESS | ((page) & 0x1F), - (((col)+SHIFT_ADDR_NORMAL) & 0x0F), - LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ write_reg(par, 0x00); - /* LCD_PAGE_ADDRESS | ((page) & 0x1F), - (((col)+SHIFT_ADDR_NORMAL) & 0x0F), - LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ write_reg(par, LCD_COL_ADDRESS); gpio_set_value(par->gpio.dc, 1); ret = par->fbtftops.write(par, par->txbuf.buf, WIDTH); -- cgit v1.2.3 From fbf461d176c5ee0e4889dc826a79a245f32426f7 Mon Sep 17 00:00:00 2001 From: Priit Laes Date: Sun, 20 Dec 2015 20:35:56 +0200 Subject: staging: fbtft: Use standard MIPI DCS command defines for hx8353d This patch makes use of the standard MIPI Display Command Set to remove some of the magic constants found in source code. Signed-off-by: Priit Laes Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_hx8353d.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fbtft/fb_hx8353d.c b/drivers/staging/fbtft/fb_hx8353d.c index 8552411695fa..064ae61a86b2 100644 --- a/drivers/staging/fbtft/fb_hx8353d.c +++ b/drivers/staging/fbtft/fb_hx8353d.c @@ -19,6 +19,7 @@ #include #include #include +#include Public constants +!Finclude/linux/vga_switcheroo.h vga_switcheroo_handler_flags_t !Finclude/linux/vga_switcheroo.h vga_switcheroo_client_id !Finclude/linux/vga_switcheroo.h vga_switcheroo_state diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c index 3c895863fcf5..fa948dcbdd5d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c @@ -552,13 +552,14 @@ static bool amdgpu_atpx_detect(void) void amdgpu_register_atpx_handler(void) { bool r; + enum vga_switcheroo_handler_flags_t handler_flags = 0; /* detect if we have any ATPX + 2 VGA in the system */ r = amdgpu_atpx_detect(); if (!r) return; - vga_switcheroo_register_handler(&amdgpu_atpx_handler); + vga_switcheroo_register_handler(&amdgpu_atpx_handler, handler_flags); } /** diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index d5e6938cc6bc..cdf522770cfa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -314,7 +314,7 @@ void nouveau_register_dsm_handler(void) if (!r) return; - vga_switcheroo_register_handler(&nouveau_dsm_handler); + vga_switcheroo_register_handler(&nouveau_dsm_handler, 0); } /* Must be called for Optimus models before the card can be turned off */ diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index c4b4f298a283..56482e35d43e 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -551,13 +551,14 @@ static bool radeon_atpx_detect(void) void radeon_register_atpx_handler(void) { bool r; + enum vga_switcheroo_handler_flags_t handler_flags = 0; /* detect if we have any ATPX + 2 VGA in the system */ r = radeon_atpx_detect(); if (!r) return; - vga_switcheroo_register_handler(&radeon_atpx_handler); + vga_switcheroo_register_handler(&radeon_atpx_handler, handler_flags); } /** diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index 665ab9fd0e01..e89f6ad5d83e 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -126,6 +126,7 @@ static DEFINE_MUTEX(vgasr_mutex); * (counting only vga clients, not audio clients) * @clients: list of registered clients * @handler: registered handler + * @handler_flags: flags of registered handler * * vga_switcheroo private data. Currently only one vga_switcheroo instance * per system is supported. @@ -142,6 +143,7 @@ struct vgasr_priv { struct list_head clients; const struct vga_switcheroo_handler *handler; + enum vga_switcheroo_handler_flags_t handler_flags; }; #define ID_BIT_AUDIO 0x100 @@ -190,13 +192,15 @@ static void vga_switcheroo_enable(void) /** * vga_switcheroo_register_handler() - register handler * @handler: handler callbacks + * @handler_flags: handler flags * * Register handler. Enable vga_switcheroo if two vga clients have already * registered. * * Return: 0 on success, -EINVAL if a handler was already registered. */ -int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler) +int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler, + enum vga_switcheroo_handler_flags_t handler_flags) { mutex_lock(&vgasr_mutex); if (vgasr_priv.handler) { @@ -205,6 +209,7 @@ int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler } vgasr_priv.handler = handler; + vgasr_priv.handler_flags = handler_flags; if (vga_switcheroo_ready()) { pr_info("enabled\n"); vga_switcheroo_enable(); @@ -222,6 +227,7 @@ EXPORT_SYMBOL(vga_switcheroo_register_handler); void vga_switcheroo_unregister_handler(void) { mutex_lock(&vgasr_mutex); + vgasr_priv.handler_flags = 0; vgasr_priv.handler = NULL; if (vgasr_priv.active) { pr_info("disabled\n"); @@ -232,6 +238,20 @@ void vga_switcheroo_unregister_handler(void) } EXPORT_SYMBOL(vga_switcheroo_unregister_handler); +/** + * vga_switcheroo_handler_flags() - obtain handler flags + * + * Helper for clients to obtain the handler flags bitmask. + * + * Return: Handler flags. A value of 0 means that no handler is registered + * or that the handler has no special capabilities. + */ +enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(void) +{ + return vgasr_priv.handler_flags; +} +EXPORT_SYMBOL(vga_switcheroo_handler_flags); + static int register_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, enum vga_switcheroo_client_id id, bool active, diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index f236250ac106..c401d4936b65 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -705,7 +705,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) init_completion(&gmux_data->powerchange_done); gmux_enable_interrupts(gmux_data); - if (vga_switcheroo_register_handler(&gmux_handler)) { + if (vga_switcheroo_register_handler(&gmux_handler, 0)) { ret = -ENODEV; goto err_register_handler; } diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index 69e1d4a1f1b3..a745f4f0f729 100644 --- a/include/linux/vga_switcheroo.h +++ b/include/linux/vga_switcheroo.h @@ -35,6 +35,26 @@ struct pci_dev; +/** + * enum vga_switcheroo_handler_flags_t - handler flags bitmask + * @VGA_SWITCHEROO_CAN_SWITCH_DDC: whether the handler is able to switch the + * DDC lines separately. This signals to clients that they should call + * drm_get_edid_switcheroo() to probe the EDID + * @VGA_SWITCHEROO_NEEDS_EDP_CONFIG: whether the handler is unable to switch + * the AUX channel separately. This signals to clients that the active + * GPU needs to train the link and communicate the link parameters to the + * inactive GPU (mediated by vga_switcheroo). The inactive GPU may then + * skip the AUX handshake and set up its output with these pre-calibrated + * values (DisplayPort specification v1.1a, section 2.5.3.3) + * + * Handler flags bitmask. Used by handlers to declare their capabilities upon + * registering with vga_switcheroo. + */ +enum vga_switcheroo_handler_flags_t { + VGA_SWITCHEROO_CAN_SWITCH_DDC = (1 << 0), + VGA_SWITCHEROO_NEEDS_EDP_CONFIG = (1 << 1), +}; + /** * enum vga_switcheroo_state - client power state * @VGA_SWITCHEROO_OFF: off @@ -132,8 +152,10 @@ int vga_switcheroo_register_audio_client(struct pci_dev *pdev, void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info); -int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler); +int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler, + enum vga_switcheroo_handler_flags_t handler_flags); void vga_switcheroo_unregister_handler(void); +enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(void); int vga_switcheroo_process_delayed_switch(void); @@ -150,11 +172,13 @@ static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {} static inline int vga_switcheroo_register_client(struct pci_dev *dev, const struct vga_switcheroo_client_ops *ops, bool driver_power_control) { return 0; } static inline void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info) {} -static inline int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler) { return 0; } +static inline int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler, + enum vga_switcheroo_handler_flags_t handler_flags) { return 0; } static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, enum vga_switcheroo_client_id id) { return 0; } static inline void vga_switcheroo_unregister_handler(void) {} +static inline enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(void) { return 0; } static inline int vga_switcheroo_process_delayed_switch(void) { return 0; } static inline enum vga_switcheroo_state vga_switcheroo_get_client_state(struct pci_dev *dev) { return VGA_SWITCHEROO_ON; } -- cgit v1.2.3 From e4cb81d7e49c806fa557cf0ff4f3f40bd7a9cb7c Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Mon, 11 Jan 2016 20:09:20 +0100 Subject: vga_switcheroo: Add support for switching only the DDC Originally by Seth Forshee , 2012-10-04: During graphics driver initialization it's useful to be able to mux only the DDC to the inactive client in order to read the EDID. Add a switch_ddc callback to allow capable handlers to provide this functionality, and add vga_switcheroo_switch_ddc() to allow DRM to mux only the DDC. Modified by Dave Airlie , 2012-12-22: I can't figure out why I didn't like this, but I rewrote this [...] to lock/unlock the ddc lines [...]. I think I'd prefer something like that otherwise the interface got really ugly. Modified by Lukas Wunner , 2015-04 - 2015-10: Change semantics of ->switch_ddc handler callback to return previous DDC owner. Original version tried to determine previous DDC owner with find_active_client() but this fails if the inactive client registers before the active client. Don't lock vgasr_mutex in _lock_ddc() / _unlock_ddc(), it can cause deadlocks because (a) during switch (with vgasr_mutex already held), GPU is woken and probes its outputs, tries to re-acquire vgasr_mutex to lock DDC lines; (b) Likewise during switch, GPU is suspended and calls cancel_delayed_work_sync() to stop output polling, if poll task is running at this moment we may wait forever for it to finish. Instead, lock mux_hw_lock when unregistering the handler because the only reason why we'd want to lock vgasr_mutex in _lock_ddc() / _unlock_ddc() is to block the handler from disappearing while DDC lines are switched. Also acquire mux_hw_lock in stage2 to avoid race condition where reading the EDID and switching happens simultaneously. Likewise on MIGD / MDIS commands and on runtime suspend. v2.1: Overhaul locking, squash commits (Daniel Vetter) v2.2: Readability improvements (Thierry Reding) v2.3: Overhaul locking once more v2.4: Retain semantics of ->switchto handler callback to switch all pins, including DDC (Daniel Vetter) v5: Rename ddc_lock to mux_hw_lock: Since we acquire this both when calling ->switch_ddc and ->switchto, it protects not just access to the DDC lines but to the mux in general. This is in line with the DRM convention to use low-level locks to avoid concurrent hw access (e.g. i2c, dp_aux) which are often called hw_lock (Daniel Vetter) Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=88861 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115 Tested-by: Lukas Wunner [MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina 15"] Cc: Seth Forshee Cc: Dave Airlie Signed-off-by: Lukas Wunner Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/e81ae9722b84c5ed591805fee3ea6dbf5dc6c4b3.1452525860.git.lukas@wunner.de --- drivers/gpu/vga/vga_switcheroo.c | 97 +++++++++++++++++++++++++++++++++++++++- include/linux/vga_switcheroo.h | 8 ++++ 2 files changed, 103 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index e89f6ad5d83e..cbd7c986d926 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -74,9 +74,17 @@ * there can thus be up to three clients: Two vga clients (GPUs) and one audio * client (on the discrete GPU). The code is mostly prepared to support * machines with more than two GPUs should they become available. + * * The GPU to which the outputs are currently switched is called the * active client in vga_switcheroo parlance. The GPU not in use is the - * inactive client. + * inactive client. When the inactive client's DRM driver is loaded, + * it will be unable to probe the panel's EDID and hence depends on + * VBIOS to provide its display modes. If the VBIOS modes are bogus or + * if there is no VBIOS at all (which is common on the MacBook Pro), + * a client may alternatively request that the DDC lines are temporarily + * switched to it, provided that the handler supports this. Switching + * only the DDC lines and not the entire output avoids unnecessary + * flickering. */ /** @@ -127,6 +135,9 @@ static DEFINE_MUTEX(vgasr_mutex); * @clients: list of registered clients * @handler: registered handler * @handler_flags: flags of registered handler + * @mux_hw_lock: protects mux state + * (in particular while DDC lines are temporarily switched) + * @old_ddc_owner: client to which DDC lines will be switched back on unlock * * vga_switcheroo private data. Currently only one vga_switcheroo instance * per system is supported. @@ -144,6 +155,8 @@ struct vgasr_priv { const struct vga_switcheroo_handler *handler; enum vga_switcheroo_handler_flags_t handler_flags; + struct mutex mux_hw_lock; + int old_ddc_owner; }; #define ID_BIT_AUDIO 0x100 @@ -158,6 +171,7 @@ static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv); /* only one switcheroo per system */ static struct vgasr_priv vgasr_priv = { .clients = LIST_HEAD_INIT(vgasr_priv.clients), + .mux_hw_lock = __MUTEX_INITIALIZER(vgasr_priv.mux_hw_lock), }; static bool vga_switcheroo_ready(void) @@ -227,6 +241,7 @@ EXPORT_SYMBOL(vga_switcheroo_register_handler); void vga_switcheroo_unregister_handler(void) { mutex_lock(&vgasr_mutex); + mutex_lock(&vgasr_priv.mux_hw_lock); vgasr_priv.handler_flags = 0; vgasr_priv.handler = NULL; if (vgasr_priv.active) { @@ -234,6 +249,7 @@ void vga_switcheroo_unregister_handler(void) vga_switcheroo_debugfs_fini(&vgasr_priv); vgasr_priv.active = false; } + mutex_unlock(&vgasr_priv.mux_hw_lock); mutex_unlock(&vgasr_mutex); } EXPORT_SYMBOL(vga_switcheroo_unregister_handler); @@ -432,6 +448,76 @@ void vga_switcheroo_client_fb_set(struct pci_dev *pdev, } EXPORT_SYMBOL(vga_switcheroo_client_fb_set); +/** + * vga_switcheroo_lock_ddc() - temporarily switch DDC lines to a given client + * @pdev: client pci device + * + * Temporarily switch DDC lines to the client identified by @pdev + * (but leave the outputs otherwise switched to where they are). + * This allows the inactive client to probe EDID. The DDC lines must + * afterwards be switched back by calling vga_switcheroo_unlock_ddc(), + * even if this function returns an error. + * + * Return: Previous DDC owner on success or a negative int on error. + * Specifically, %-ENODEV if no handler has registered or if the handler + * does not support switching the DDC lines. Also, a negative value + * returned by the handler is propagated back to the caller. + * The return value has merely an informational purpose for any caller + * which might be interested in it. It is acceptable to ignore the return + * value and simply rely on the result of the subsequent EDID probe, + * which will be %NULL if DDC switching failed. + */ +int vga_switcheroo_lock_ddc(struct pci_dev *pdev) +{ + enum vga_switcheroo_client_id id; + + mutex_lock(&vgasr_priv.mux_hw_lock); + if (!vgasr_priv.handler || !vgasr_priv.handler->switch_ddc) { + vgasr_priv.old_ddc_owner = -ENODEV; + return -ENODEV; + } + + id = vgasr_priv.handler->get_client_id(pdev); + vgasr_priv.old_ddc_owner = vgasr_priv.handler->switch_ddc(id); + return vgasr_priv.old_ddc_owner; +} +EXPORT_SYMBOL(vga_switcheroo_lock_ddc); + +/** + * vga_switcheroo_unlock_ddc() - switch DDC lines back to previous owner + * @pdev: client pci device + * + * Switch DDC lines back to the previous owner after calling + * vga_switcheroo_lock_ddc(). This must be called even if + * vga_switcheroo_lock_ddc() returned an error. + * + * Return: Previous DDC owner on success (i.e. the client identifier of @pdev) + * or a negative int on error. + * Specifically, %-ENODEV if no handler has registered or if the handler + * does not support switching the DDC lines. Also, a negative value + * returned by the handler is propagated back to the caller. + * Finally, invoking this function without calling vga_switcheroo_lock_ddc() + * first is not allowed and will result in %-EINVAL. + */ +int vga_switcheroo_unlock_ddc(struct pci_dev *pdev) +{ + enum vga_switcheroo_client_id id; + int ret = vgasr_priv.old_ddc_owner; + + if (WARN_ON_ONCE(!mutex_is_locked(&vgasr_priv.mux_hw_lock))) + return -EINVAL; + + if (vgasr_priv.old_ddc_owner >= 0) { + id = vgasr_priv.handler->get_client_id(pdev); + if (vgasr_priv.old_ddc_owner != id) + ret = vgasr_priv.handler->switch_ddc( + vgasr_priv.old_ddc_owner); + } + mutex_unlock(&vgasr_priv.mux_hw_lock); + return ret; +} +EXPORT_SYMBOL(vga_switcheroo_unlock_ddc); + /** * DOC: Manual switching and manual power control * @@ -569,7 +655,9 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) console_unlock(); } + mutex_lock(&vgasr_priv.mux_hw_lock); ret = vgasr_priv.handler->switchto(new_client->id); + mutex_unlock(&vgasr_priv.mux_hw_lock); if (ret) return ret; @@ -684,7 +772,9 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf, vgasr_priv.delayed_switch_active = false; if (just_mux) { + mutex_lock(&vgasr_priv.mux_hw_lock); ret = vgasr_priv.handler->switchto(client_id); + mutex_unlock(&vgasr_priv.mux_hw_lock); goto out; } @@ -896,8 +986,11 @@ static int vga_switcheroo_runtime_suspend(struct device *dev) if (ret) return ret; mutex_lock(&vgasr_mutex); - if (vgasr_priv.handler->switchto) + if (vgasr_priv.handler->switchto) { + mutex_lock(&vgasr_priv.mux_hw_lock); vgasr_priv.handler->switchto(VGA_SWITCHEROO_IGD); + mutex_unlock(&vgasr_priv.mux_hw_lock); + } vga_switcheroo_power_switch(pdev, VGA_SWITCHEROO_OFF); mutex_unlock(&vgasr_mutex); return 0; diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index a745f4f0f729..b39a5f3153bd 100644 --- a/include/linux/vga_switcheroo.h +++ b/include/linux/vga_switcheroo.h @@ -102,6 +102,9 @@ enum vga_switcheroo_client_id { * Mandatory. For muxless machines this should be a no-op. Returning 0 * denotes success, anything else failure (in which case the switch is * aborted) + * @switch_ddc: switch DDC lines to given client. + * Optional. Should return the previous DDC owner on success or a + * negative int on failure * @power_state: cut or reinstate power of given client. * Optional. The return value is ignored * @get_client_id: determine if given pci device is integrated or discrete GPU. @@ -113,6 +116,7 @@ enum vga_switcheroo_client_id { struct vga_switcheroo_handler { int (*init)(void); int (*switchto)(enum vga_switcheroo_client_id id); + int (*switch_ddc)(enum vga_switcheroo_client_id id); int (*power_state)(enum vga_switcheroo_client_id id, enum vga_switcheroo_state state); enum vga_switcheroo_client_id (*get_client_id)(struct pci_dev *pdev); @@ -156,6 +160,8 @@ int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler enum vga_switcheroo_handler_flags_t handler_flags); void vga_switcheroo_unregister_handler(void); enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(void); +int vga_switcheroo_lock_ddc(struct pci_dev *pdev); +int vga_switcheroo_unlock_ddc(struct pci_dev *pdev); int vga_switcheroo_process_delayed_switch(void); @@ -179,6 +185,8 @@ static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev, enum vga_switcheroo_client_id id) { return 0; } static inline void vga_switcheroo_unregister_handler(void) {} static inline enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(void) { return 0; } +static inline int vga_switcheroo_lock_ddc(struct pci_dev *pdev) { return -ENODEV; } +static inline int vga_switcheroo_unlock_ddc(struct pci_dev *pdev) { return -ENODEV; } static inline int vga_switcheroo_process_delayed_switch(void) { return 0; } static inline enum vga_switcheroo_state vga_switcheroo_get_client_state(struct pci_dev *dev) { return VGA_SWITCHEROO_ON; } -- cgit v1.2.3 From 3e46304e74d2780dc7d909ec26c454b87feeda2a Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Mon, 11 Jan 2016 20:09:20 +0100 Subject: apple-gmux: Track switch state gmux has 3 switch registers: * GMUX_PORT_SWITCH_DISPLAY switches the panel * GMUX_PORT_SWITCH_DDC switches the panel's DDC lines (only on pre-retinas; on retinas this is a no-op) * GMUX_PORT_SWITCH_EXTERNAL switches the external DP port(s) (only on models without Thunderbolt, i.e. introduced before 2011; those with Thunderbolt switch only HPD/AUX, not the main link) Currently we switch all 3 registers in unison. gmux does not preserve the switch state during suspend, so we currently read GMUX_PORT_SWITCH_DISPLAY before suspend and restore all 3 registers to this value on resume. With the upcoming ->switch_ddc callback, GMUX_PORT_SWITCH_DDC may temporarily contain a different value than the other 2 registers. If we happen to suspend at this moment, we'll write an incorrect value to GMUX_PORT_SWITCH_DDC on resume. Also, on models with Thunderbolt the integrated GPU is unable to drive the external DP port(s), so we want to keep GMUX_PORT_SWITCH_EXTERNAL permanently switched to the discrete GPU on those machines. Consequently we can no longer assume that GMUX_PORT_SWITCH_DISPLAY represents the correct value for all 3 registers on suspend. Track the state of all 3 registers: Add gmux_read_switch_state() and gmux_write_switch_state(). Instead of reading the switch state on every suspend, read it once on driver initialization so that we know the current switch state all the time. (This allows us to use some optimizations and shortcuts, e.g. we can skip switching DDC if we know that it's already switched to the requested GPU.) Change the ->switchto callback to use gmux_write_switch_state(). Tested-by: Lukas Wunner [MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina 15"] Signed-off-by: Lukas Wunner Reviewed-by: Darren Hart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/5679f414cb0ddf1654dcc359571f3764b275edf0.1452525860.git.lukas@wunner.de --- drivers/platform/x86/apple-gmux.c | 67 +++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index c401d4936b65..5c6c708e56b8 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -57,7 +57,9 @@ struct apple_gmux_data { /* switcheroo data */ acpi_handle dhandle; int gpe; - enum vga_switcheroo_client_id resume_client_id; + enum vga_switcheroo_client_id switch_state_display; + enum vga_switcheroo_client_id switch_state_ddc; + enum vga_switcheroo_client_id switch_state_external; enum vga_switcheroo_state power_state; struct completion powerchange_done; }; @@ -368,17 +370,49 @@ static const struct backlight_ops gmux_bl_ops = { * for the selected GPU. */ +static void gmux_read_switch_state(struct apple_gmux_data *gmux_data) +{ + if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_DDC) == 1) + gmux_data->switch_state_ddc = VGA_SWITCHEROO_IGD; + else + gmux_data->switch_state_ddc = VGA_SWITCHEROO_DIS; + + if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_DISPLAY) == 2) + gmux_data->switch_state_display = VGA_SWITCHEROO_IGD; + else + gmux_data->switch_state_display = VGA_SWITCHEROO_DIS; + + if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL) == 2) + gmux_data->switch_state_external = VGA_SWITCHEROO_IGD; + else + gmux_data->switch_state_external = VGA_SWITCHEROO_DIS; +} + +static void gmux_write_switch_state(struct apple_gmux_data *gmux_data) +{ + if (gmux_data->switch_state_ddc == VGA_SWITCHEROO_IGD) + gmux_write8(gmux_data, GMUX_PORT_SWITCH_DDC, 1); + else + gmux_write8(gmux_data, GMUX_PORT_SWITCH_DDC, 2); + + if (gmux_data->switch_state_display == VGA_SWITCHEROO_IGD) + gmux_write8(gmux_data, GMUX_PORT_SWITCH_DISPLAY, 2); + else + gmux_write8(gmux_data, GMUX_PORT_SWITCH_DISPLAY, 3); + + if (gmux_data->switch_state_external == VGA_SWITCHEROO_IGD) + gmux_write8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 2); + else + gmux_write8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3); +} + static int gmux_switchto(enum vga_switcheroo_client_id id) { - if (id == VGA_SWITCHEROO_IGD) { - gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1); - gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 2); - gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 2); - } else { - gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2); - gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 3); - gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3); - } + apple_gmux_data->switch_state_ddc = id; + apple_gmux_data->switch_state_display = id; + apple_gmux_data->switch_state_external = id; + + gmux_write_switch_state(apple_gmux_data); return 0; } @@ -440,15 +474,6 @@ static int gmux_get_client_id(struct pci_dev *pdev) return VGA_SWITCHEROO_DIS; } -static enum vga_switcheroo_client_id -gmux_active_client(struct apple_gmux_data *gmux_data) -{ - if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_DISPLAY) == 2) - return VGA_SWITCHEROO_IGD; - - return VGA_SWITCHEROO_DIS; -} - static const struct vga_switcheroo_handler gmux_handler = { .switchto = gmux_switchto, .power_state = gmux_set_power_state, @@ -513,7 +538,6 @@ static int gmux_suspend(struct device *dev) struct pnp_dev *pnp = to_pnp_dev(dev); struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); - gmux_data->resume_client_id = gmux_active_client(gmux_data); gmux_disable_interrupts(gmux_data); return 0; } @@ -524,7 +548,7 @@ static int gmux_resume(struct device *dev) struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); gmux_enable_interrupts(gmux_data); - gmux_switchto(gmux_data->resume_client_id); + gmux_write_switch_state(gmux_data); if (gmux_data->power_state == VGA_SWITCHEROO_OFF) gmux_set_discrete_state(gmux_data, gmux_data->power_state); return 0; @@ -704,6 +728,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) apple_gmux_data = gmux_data; init_completion(&gmux_data->powerchange_done); gmux_enable_interrupts(gmux_data); + gmux_read_switch_state(gmux_data); if (vga_switcheroo_register_handler(&gmux_handler, 0)) { ret = -ENODEV; -- cgit v1.2.3 From f798d9652874bfb3cdbcafa865964c0784ab2a0f Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Mon, 11 Jan 2016 20:09:20 +0100 Subject: apple-gmux: Add switch_ddc support Originally by Seth Forshee , 2012-10-04: The gmux allows muxing the DDC independently from the display, so support this functionality. This will allow reading the EDID for the inactive GPU, fixing issues with machines that either don't have a VBT or have invalid mode data in the VBT. Modified by Lukas Wunner , 2015-04 - 2015-12: Change semantics of ->switch_ddc handler callback to return previous DDC owner. Original version tried to determine previous DDC owner with find_active_client() in vga_switcheroo but this fails if the inactive client registers before the active client. v2.4: Retain semantics of ->switchto handler callback to switch all pins, including DDC (Daniel Vetter) v4: Advertise ->switch_ddc handler callback only on the pre-retina Macbook Pro. The retina uses eDP instead of LVDS and gmux no longer does the muxing itself but merely controls an external mux. That mux is incapable of switching the AUX channel separately from the main link. It's an NXP CBTL06142 (alternate parts: TI HD3SS212, Pericom PI3VDP12412, see datasheets below). v5: Rebase on "apple-gmux: Track switch state". Rebase on "vga_switcheroo: Add handler flags infrastructure". Rebase on 5d170139eb10 ("Constify vga_switcheroo_handler"), requires 2 structs, 1x with ->switchto for pre-retinas, 1x without for retinas). Add error message if handler registration with vga_switcheroo fails. Teardowns identifying the mux: http://www.electronicproducts.com/-whatsinside_text-145.aspx http://slideshare.net/jjwu6266/apple-2012-wwdc-apple-macbook-pro-with-retina-display http://www.techrepublic.com/blog/cracking-open/teardown-shows-retina-macbook-pro-is-nearly-impossible-to-upgrade-difficult-to-work-on/ Mux Datasheets: http://www.nxp.com/documents/data_sheet/CBTL06141.pdf http://www.ti.com/lit/ds/symlink/hd3ss212.pdf https://www.pericom.com/assets/Datasheets/PI3VDP12412.pdf Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=88861 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115 Tested-by: Lukas Wunner [MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina 15"] Cc: Seth Forshee Signed-off-by: Lukas Wunner Reviewed-by: Darren Hart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/17fe8bfb0415d713bb4174f84ac9aae5d7d9a5f8.1452525860.git.lukas@wunner.de --- drivers/platform/x86/apple-gmux.c | 45 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 5c6c708e56b8..1384a393f2f7 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -417,6 +417,25 @@ static int gmux_switchto(enum vga_switcheroo_client_id id) return 0; } +static int gmux_switch_ddc(enum vga_switcheroo_client_id id) +{ + enum vga_switcheroo_client_id old_ddc_owner = + apple_gmux_data->switch_state_ddc; + + if (id == old_ddc_owner) + return id; + + pr_debug("Switching DDC from %d to %d\n", old_ddc_owner, id); + apple_gmux_data->switch_state_ddc = id; + + if (id == VGA_SWITCHEROO_IGD) + gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1); + else + gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2); + + return old_ddc_owner; +} + /** * DOC: Power control * @@ -474,12 +493,19 @@ static int gmux_get_client_id(struct pci_dev *pdev) return VGA_SWITCHEROO_DIS; } -static const struct vga_switcheroo_handler gmux_handler = { +static const struct vga_switcheroo_handler gmux_handler_indexed = { .switchto = gmux_switchto, .power_state = gmux_set_power_state, .get_client_id = gmux_get_client_id, }; +static const struct vga_switcheroo_handler gmux_handler_classic = { + .switchto = gmux_switchto, + .switch_ddc = gmux_switch_ddc, + .power_state = gmux_set_power_state, + .get_client_id = gmux_get_client_id, +}; + /** * DOC: Interrupt * @@ -730,8 +756,21 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) gmux_enable_interrupts(gmux_data); gmux_read_switch_state(gmux_data); - if (vga_switcheroo_register_handler(&gmux_handler, 0)) { - ret = -ENODEV; + /* + * Retina MacBook Pros cannot switch the panel's AUX separately + * and need eDP pre-calibration. They are distinguishable from + * pre-retinas by having an "indexed" gmux. + * + * Pre-retina MacBook Pros can switch the panel's DDC separately. + */ + if (gmux_data->indexed) + ret = vga_switcheroo_register_handler(&gmux_handler_indexed, + VGA_SWITCHEROO_NEEDS_EDP_CONFIG); + else + ret = vga_switcheroo_register_handler(&gmux_handler_classic, + VGA_SWITCHEROO_CAN_SWITCH_DDC); + if (ret) { + pr_err("Failed to register vga_switcheroo handler\n"); goto err_register_handler; } -- cgit v1.2.3 From 5cb8eaa227d1870a68fc99a90edc8be0dbacca41 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Mon, 11 Jan 2016 20:09:20 +0100 Subject: drm/edid: Switch DDC when reading the EDID Originally by Seth Forshee , 2012-10-04: Some dual graphics machines support muxing the DDC separately from the display, so make use of this functionality when reading the EDID on the inactive GPU. Also serialize drm_get_edid() with a mutex to avoid races on the DDC mux state. Modified by Dave Airlie , 2012-12-22: I can't figure out why I didn't like this, but I rewrote this [...] to lock/unlock the ddc lines [...]. I think I'd prefer something like that otherwise the interface got really ugly. Modified by Lukas Wunner , 2015-04 - 2015-09: v3: Move vga_switcheroo calls to a wrapper around drm_get_edid() which drivers can call on muxed machines. This avoids other drivers having to go through the vga_switcheroo motions even though they are never used on a muxed platform (Thierry Reding, Daniel Vetter, Alex Deucher) Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=88861 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115 Tested-by: Pierre Moreau [MBP 5,3 2009 nvidia MCP79 + G96 pre-retina 15"] Tested-by: William Brown [MBP 8,2 2011 intel SNB + amd turks pre-retina 15"] Tested-by: Lukas Wunner [MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina 15"] Cc: Seth Forshee Cc: Dave Airlie Signed-off-by: Lukas Wunner Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/b898d0da4c134f2642d0122479006863e1830723.1452525860.git.lukas@wunner.de --- drivers/gpu/drm/drm_edid.c | 26 ++++++++++++++++++++++++++ include/drm/drm_crtc.h | 2 ++ 2 files changed, 28 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 04cb4877fabd..fdb1eb014586 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -1394,6 +1395,31 @@ struct edid *drm_get_edid(struct drm_connector *connector, } EXPORT_SYMBOL(drm_get_edid); +/** + * drm_get_edid_switcheroo - get EDID data for a vga_switcheroo output + * @connector: connector we're probing + * @adapter: I2C adapter to use for DDC + * + * Wrapper around drm_get_edid() for laptops with dual GPUs using one set of + * outputs. The wrapper adds the requisite vga_switcheroo calls to temporarily + * switch DDC to the GPU which is retrieving EDID. + * + * Return: Pointer to valid EDID or %NULL if we couldn't find any. + */ +struct edid *drm_get_edid_switcheroo(struct drm_connector *connector, + struct i2c_adapter *adapter) +{ + struct pci_dev *pdev = connector->dev->pdev; + struct edid *edid; + + vga_switcheroo_lock_ddc(pdev); + edid = drm_get_edid(connector, adapter); + vga_switcheroo_unlock_ddc(pdev); + + return edid; +} +EXPORT_SYMBOL(drm_get_edid_switcheroo); + /** * drm_edid_duplicate - duplicate an EDID and the extensions * @edid: EDID to duplicate diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 51287f36b214..ad53d2ffd48c 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -2296,6 +2296,8 @@ extern void drm_property_destroy_user_blobs(struct drm_device *dev, extern bool drm_probe_ddc(struct i2c_adapter *adapter); extern struct edid *drm_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter); +extern struct edid *drm_get_edid_switcheroo(struct drm_connector *connector, + struct i2c_adapter *adapter); extern struct edid *drm_edid_duplicate(const struct edid *edid); extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); extern void drm_mode_config_init(struct drm_device *dev); -- cgit v1.2.3 From 4eddaeecf92341bf94ce1bf9dd98bb2cee267b14 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Mon, 11 Jan 2016 20:09:20 +0100 Subject: drm/i915: Switch DDC when reading the EDID The pre-retina MacBook Pro uses an LVDS panel and a gmux controller to switch the panel between its two GPUs. The panel mode in VBIOS is notoriously bogus on these machines and some models have no VBIOS at all. Use drm_get_edid_switcheroo() in lieu of drm_get_edid() on LVDS if the vga_switcheroo handler is capable of temporarily switching the panel's DDC lines to the integrated GPU. This allows us to retrieve the EDID if the panel is currently muxed to the discrete GPU. This only enables EDID probing on the pre-retina MBP (2008 - 2013). The retina MBP (2012 - present) uses eDP and gmux is not capable of switching AUX separately from the main link on these models. This will be addressed in later patches. List of pre-retina MBPs with dual GPUs, one of them Intel: [MBP 6,2 2010 intel ILK + nvidia GT216 pre-retina 15"] [MBP 6,1 2010 intel ILK + nvidia GT216 pre-retina 17"] [MBP 8,2 2011 intel SNB + amd turks pre-retina 15"] [MBP 8,3 2011 intel SNB + amd turks pre-retina 17"] [MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina 15"] v3: Commit newly added due to introduction of drm_get_edid_switcheroo() wrapper which drivers need to opt-in to. v5: Rebase on "vga_switcheroo: Add handler flags infrastructure", i.e. call drm_get_edid_switcheroo() only if the handler indicates that DDC is switchable. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=88861 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115 Tested-by: Lukas Wunner [MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina 15"] Signed-off-by: Lukas Wunner Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/bb095e14a2259be7fdd10092f9d6874a9be8f27b.1452525860.git.lukas@wunner.de --- drivers/gpu/drm/i915/intel_lvds.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 0da0240caf81..811ddf7799f0 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1080,7 +1081,12 @@ void intel_lvds_init(struct drm_device *dev) * preferred mode is the right one. */ mutex_lock(&dev->mode_config.mutex); - edid = drm_get_edid(connector, intel_gmbus_get_adapter(dev_priv, pin)); + if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC) + edid = drm_get_edid_switcheroo(connector, + intel_gmbus_get_adapter(dev_priv, pin)); + else + edid = drm_get_edid(connector, + intel_gmbus_get_adapter(dev_priv, pin)); if (edid) { if (drm_add_edid_modes(connector, edid)) { drm_mode_connector_update_edid_property(connector, -- cgit v1.2.3 From 39c1c9011c44e4cf1db80e83abf24958f5902289 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Mon, 11 Jan 2016 20:09:20 +0100 Subject: drm/nouveau: Switch DDC when reading the EDID The pre-retina MacBook Pro uses an LVDS panel and a gmux controller to switch the panel between its two GPUs. The panel mode in VBIOS is notoriously bogus on these machines. Use drm_get_edid_switcheroo() in lieu of drm_get_edid() on LVDS if the vga_switcheroo handler is capable of temporarily switching the panel's DDC lines to the discrete GPU. This allows us to retrieve the EDID if the panel is currently muxed to the integrated GPU. Likewise, ask vga_switcheroo to switch DDC before probing LVDS connectors. This only enables EDID probing on the pre-retina MBP (2008 - 2013). The retina MBP (2012 - present) uses eDP and gmux is not capable of switching AUX separately from the main link on these models. This will be addressed in later patches. List of pre-retina MBPs with dual GPUs, either or both Nvidia: [MBP 5,1 2008 nvidia MCP79 + G96 pre-retina 15"] [MBP 5,2 2009 nvidia MCP79 + G96 pre-retina 17"] [MBP 5,3 2009 nvidia MCP79 + G96 pre-retina 15"] [MBP 6,2 2010 intel ILK + nvidia GT216 pre-retina 15"] [MBP 6,1 2010 intel ILK + nvidia GT216 pre-retina 17"] [MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina 15"] v3: Commit newly added due to introduction of drm_get_edid_switcheroo() wrapper which drivers need to opt-in to. v5: Rebase on "vga_switcheroo: Add handler flags infrastructure", i.e. call drm_get_edid_switcheroo() only if the handler indicates that DDC is switchable. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=88861 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115 Tested-by: Lukas Wunner [MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina 15"] Signed-off-by: Lukas Wunner Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/e9466eb3d66b5b30f1e93c3b3da79d8b9ad0830f.1452525860.git.lukas@wunner.de --- drivers/gpu/drm/nouveau/nouveau_connector.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index fcebfae5d426..ae96ebc490fb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -153,6 +154,17 @@ nouveau_connector_ddc_detect(struct drm_connector *connector) if (ret == 0) break; } else + if ((vga_switcheroo_handler_flags() & + VGA_SWITCHEROO_CAN_SWITCH_DDC) && + nv_encoder->dcb->type == DCB_OUTPUT_LVDS && + nv_encoder->i2c) { + int ret; + vga_switcheroo_lock_ddc(dev->pdev); + ret = nvkm_probe_i2c(nv_encoder->i2c, 0x50); + vga_switcheroo_unlock_ddc(dev->pdev); + if (ret) + break; + } else if (nv_encoder->i2c) { if (nvkm_probe_i2c(nv_encoder->i2c, 0x50)) break; @@ -265,7 +277,14 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) nv_encoder = nouveau_connector_ddc_detect(connector); if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) { - nv_connector->edid = drm_get_edid(connector, i2c); + if ((vga_switcheroo_handler_flags() & + VGA_SWITCHEROO_CAN_SWITCH_DDC) && + nv_connector->type == DCB_CONNECTOR_LVDS) + nv_connector->edid = drm_get_edid_switcheroo(connector, + i2c); + else + nv_connector->edid = drm_get_edid(connector, i2c); + drm_mode_connector_update_edid_property(connector, nv_connector->edid); if (!nv_connector->edid) { -- cgit v1.2.3 From 47eb8f739e6910a157962d2e6e8ce5eb06374e83 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Mon, 11 Jan 2016 20:09:20 +0100 Subject: drm/radeon: Switch DDC when reading the EDID The pre-retina MacBook Pro uses an LVDS panel and a gmux controller to switch the panel between its two GPUs. The panel mode in VBIOS is notoriously bogus on these machines. Use drm_get_edid_switcheroo() in lieu of drm_get_edid() on LVDS if the vga_switcheroo handler is capable of temporarily switching the panel's DDC lines to the discrete GPU. This allows us to retrieve the EDID if the panel is currently muxed to the integrated GPU. This only enables EDID probing on the pre-retina MBP (2008 - 2013). The retina MBP (2012 - present) uses eDP and gmux is not capable of switching AUX separately from the main link on these models. This will be addressed in later patches. List of pre-retina MBPs with dual GPUs, one of them AMD: [MBP 8,2 2011 intel SNB + amd turks pre-retina 15"] [MBP 8,3 2011 intel SNB + amd turks pre-retina 17"] v3: Commit newly added due to introduction of drm_get_edid_switcheroo() wrapper which drivers need to opt-in to. v5: Rebase on "vga_switcheroo: Add handler flags infrastructure", i.e. call drm_get_edid_switcheroo() only if the handler indicates that DDC is switchable. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115 Signed-off-by: Lukas Wunner Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/dae71655e8c484fbef492d3389c157975f9622c9.1452525860.git.lukas@wunner.de --- drivers/gpu/drm/radeon/radeon_connectors.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 340f3f549f29..cfcc099c537d 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -34,6 +34,7 @@ #include "atom.h" #include +#include static int radeon_dp_handle_hpd(struct drm_connector *connector) { @@ -344,6 +345,11 @@ static void radeon_connector_get_edid(struct drm_connector *connector) else if (radeon_connector->ddc_bus) radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); + } else if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC && + connector->connector_type == DRM_MODE_CONNECTOR_LVDS && + radeon_connector->ddc_bus) { + radeon_connector->edid = drm_get_edid_switcheroo(&radeon_connector->base, + &radeon_connector->ddc_bus->adapter); } else if (radeon_connector->ddc_bus) { radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); -- cgit v1.2.3 From 2413306c2566b729a9d17a81e9d1181e6f354d6a Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Mon, 11 Jan 2016 20:09:20 +0100 Subject: apple-gmux: Add helper for presence detect Centralize gmux' ACPI HID in a header file and add apple_gmux_present(). This can be used by other drivers to activate quirks specific to dual GPU MacBook Pros & Mac Pros. The alternative would be to hardcode DMI or PCI IDs and amend them whenever Apple introduces a new machine. Tested-by: Lukas Wunner [MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina 15"] Signed-off-by: Lukas Wunner Reviewed-by: Darren Hart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/89c23769058a340e5e11d4a7102f3793d3b0c94c.1452525860.git.lukas@wunner.de --- Documentation/DocBook/gpu.tmpl | 4 ++++ drivers/platform/x86/apple-gmux.c | 3 ++- include/linux/apple-gmux.h | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 include/linux/apple-gmux.h (limited to 'drivers') diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl index d6579d8c1341..fe6b36a2fd98 100644 --- a/Documentation/DocBook/gpu.tmpl +++ b/Documentation/DocBook/gpu.tmpl @@ -3451,6 +3451,10 @@ int num_ioctls; Backlight control !Pdrivers/platform/x86/apple-gmux.c Backlight control + + Public functions +!Iinclude/linux/apple-gmux.h + diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 1384a393f2f7..4034d2d4c507 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -828,7 +829,7 @@ static void gmux_remove(struct pnp_dev *pnp) } static const struct pnp_device_id gmux_device_ids[] = { - {"APP000B", 0}, + {GMUX_ACPI_HID, 0}, {"", 0} }; diff --git a/include/linux/apple-gmux.h b/include/linux/apple-gmux.h new file mode 100644 index 000000000000..feebc2840462 --- /dev/null +++ b/include/linux/apple-gmux.h @@ -0,0 +1,39 @@ +/* + * apple-gmux.h - microcontroller built into dual GPU MacBook Pro & Mac Pro + * Copyright (C) 2015 Lukas Wunner + * + * 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. + * + * 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, see . + */ + +#ifndef LINUX_APPLE_GMUX_H +#define LINUX_APPLE_GMUX_H + +#include + +#define GMUX_ACPI_HID "APP000B" + +/** + * apple_gmux_present() - detect if gmux is built into the machine + * + * Drivers may use this to activate quirks specific to dual GPU MacBook Pros + * and Mac Pros, e.g. for deferred probing, runtime pm and backlight. + * + * Return: %true if gmux is present and the kernel was configured + * with CONFIG_APPLE_GMUX, %false otherwise. + */ +static inline bool apple_gmux_present(void) +{ + return IS_ENABLED(CONFIG_APPLE_GMUX) && acpi_dev_present(GMUX_ACPI_HID); +} + +#endif /* LINUX_APPLE_GMUX_H */ -- cgit v1.2.3 From 704ab614ec1201138032003c03113a81526638ab Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Mon, 11 Jan 2016 20:09:20 +0100 Subject: drm/i915: Defer probe if gmux is present but its driver isn't gmux is a microcontroller built into dual GPU MacBook Pros. On pre-retina MBPs, if we're the inactive GPU, we need apple-gmux to temporarily switch DDC so that we can probe the panel's EDID. The checks for CONFIG_VGA_ARB and CONFIG_VGA_SWITCHEROO are necessary because if either of them is disabled but gmux is present, the driver would never load, even if we're the active GPU. (vga_default_device() would evaluate to NULL and vga_switcheroo_handler_flags() would evaluate to 0.) Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=88861 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115 Tested-by: Lukas Wunner [MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina 15"] Signed-off-by: Lukas Wunner Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/f56ee6a0600a3e1bb5bed4d0db4ed9ade7445c47.1452525860.git.lukas@wunner.de --- drivers/gpu/drm/i915/i915_drv.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 11d8414edbbe..44912ecebc1a 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -35,9 +35,12 @@ #include "i915_trace.h" #include "intel_drv.h" +#include #include #include #include +#include +#include #include static struct drm_driver driver; @@ -969,6 +972,15 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (PCI_FUNC(pdev->devfn)) return -ENODEV; + /* + * apple-gmux is needed on dual GPU MacBook Pro + * to probe the panel if we're the inactive GPU. + */ + if (IS_ENABLED(CONFIG_VGA_ARB) && IS_ENABLED(CONFIG_VGA_SWITCHEROO) && + apple_gmux_present() && pdev != vga_default_device() && + !vga_switcheroo_handler_flags()) + return -EPROBE_DEFER; + return drm_get_pci_dev(pdev, ent, &driver); } -- cgit v1.2.3 From 98b3a3402eb6e38c3bf5dd4281e60e1f186f0041 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Mon, 11 Jan 2016 20:09:20 +0100 Subject: drm/nouveau: Defer probe if gmux is present but its driver isn't gmux is a microcontroller built into dual GPU MacBook Pros. On pre-retina MBPs, if we're the inactive GPU, we need apple-gmux to temporarily switch DDC so that we can probe the panel's EDID. The checks for CONFIG_VGA_ARB and CONFIG_VGA_SWITCHEROO are necessary because if either of them is disabled but gmux is present, the driver would never load, even if we're the active GPU. (vga_default_device() would evaluate to NULL and vga_switcheroo_handler_flags() would evaluate to 0.) Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=88861 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115 Tested-by: Lukas Wunner [MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina 15"] Signed-off-by: Lukas Wunner Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/d9542ca5041178165d3ff286c90cc99634f7d2ce.1452525860.git.lukas@wunner.de --- drivers/gpu/drm/nouveau/nouveau_drm.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 2f2f252e3fb6..bb8498c9b13e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -22,11 +22,13 @@ * Authors: Ben Skeggs */ +#include #include #include #include #include #include +#include #include #include "drmP.h" @@ -312,6 +314,15 @@ static int nouveau_drm_probe(struct pci_dev *pdev, bool boot = false; int ret; + /* + * apple-gmux is needed on dual GPU MacBook Pro + * to probe the panel if we're the inactive GPU. + */ + if (IS_ENABLED(CONFIG_VGA_ARB) && IS_ENABLED(CONFIG_VGA_SWITCHEROO) && + apple_gmux_present() && pdev != vga_default_device() && + !vga_switcheroo_handler_flags()) + return -EPROBE_DEFER; + /* remove conflicting drivers (vesafb, efifb etc) */ aper = alloc_apertures(3); if (!aper) -- cgit v1.2.3 From 14d2000182ed1cb6baf0fe8dc60a3664a832fc01 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Mon, 11 Jan 2016 20:09:20 +0100 Subject: drm/radeon: Defer probe if gmux is present but its driver isn't gmux is a microcontroller built into dual GPU MacBook Pros. On pre-retina MBPs, if we're the inactive GPU, we need apple-gmux to temporarily switch DDC so that we can probe the panel's EDID. The checks for CONFIG_VGA_ARB and CONFIG_VGA_SWITCHEROO are necessary because if either of them is disabled but gmux is present, the driver would never load, even if we're the active GPU. (vga_default_device() would evaluate to NULL and vga_switcheroo_handler_flags() would evaluate to 0.) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115 Signed-off-by: Lukas Wunner Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/552da6d85a82092146af7b0693595fa2a9ea376b.1452525860.git.lukas@wunner.de --- drivers/gpu/drm/radeon/radeon_drv.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index e266ffc520d2..cad25557650f 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -34,9 +34,11 @@ #include "radeon_drv.h" #include +#include #include #include #include +#include #include #include @@ -319,6 +321,15 @@ static int radeon_pci_probe(struct pci_dev *pdev, { int ret; + /* + * apple-gmux is needed on dual GPU MacBook Pro + * to probe the panel if we're the inactive GPU. + */ + if (IS_ENABLED(CONFIG_VGA_ARB) && IS_ENABLED(CONFIG_VGA_SWITCHEROO) && + apple_gmux_present() && pdev != vga_default_device() && + !vga_switcheroo_handler_flags()) + return -EPROBE_DEFER; + /* Get rid of things like offb */ ret = radeon_kick_out_firmware_fb(pdev); if (ret) -- cgit v1.2.3 From f5a952c08e842cb06eb5c65947ced9b5128a62ee Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 3 Feb 2016 21:35:29 +0200 Subject: of: of_mdio: Add marvell, 88e1145 to whitelist of PHY compatibilities. Commit ae461131960b ("of: of_mdio: Add a whitelist of PHY compatibilities.") missed one compatible string used in in-tree DTBs: in OCTEON, for selected boards, the kernel DTB pruning code will overwrite the DTB compatible string with "marvell,88e1145", which is missing from the whitelist. Add it. The patch fixes broken networking on EdgeRouter Lite. Fixes: ae461131960b ("of: of_mdio: Add a whitelist of PHY compatibilities.") Signed-off-by: Aaro Koskinen Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/of/of_mdio.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 5648317d355f..39c4be41ef83 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -154,6 +154,7 @@ static const struct of_device_id whitelist_phys[] = { { .compatible = "marvell,88E1111", }, { .compatible = "marvell,88e1116", }, { .compatible = "marvell,88e1118", }, + { .compatible = "marvell,88e1145", }, { .compatible = "marvell,88e1149r", }, { .compatible = "marvell,88e1310", }, { .compatible = "marvell,88E1510", }, -- cgit v1.2.3 From c6b90653f1f7ea383734f8ce9e8df285a0c23f5b Mon Sep 17 00:00:00 2001 From: Dirk Behme Date: Thu, 4 Feb 2016 18:06:10 +0100 Subject: drivers/perf: arm_pmu: make info messages more verbose On a big.LITTLE system e.g. with Cortex A57 and A53 in case not all cores are online at PMU probe time we might get hw perfevents: failed to probe PMU! hw perfevents: failed to register PMU devices! making it unclear which cores failed, here. Add the device tree full name which failed and the error value resulting in a more verbose and helpful message like hw perfevents: /soc/pmu_a53: failed to probe PMU! Error -6 hw perfevents: /soc/pmu_a53: failed to register PMU devices! Error -6 Signed-off-by: Dirk Behme Signed-off-by: Will Deacon --- drivers/perf/arm_pmu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c index eb5bee07526b..ca63a452393a 100644 --- a/drivers/perf/arm_pmu.c +++ b/drivers/perf/arm_pmu.c @@ -907,7 +907,8 @@ int arm_pmu_device_probe(struct platform_device *pdev, } if (ret) { - pr_info("failed to probe PMU!\n"); + pr_info("%s: failed to probe PMU! Error %i\n", + node->full_name, ret); goto out_free; } @@ -927,7 +928,8 @@ int arm_pmu_device_probe(struct platform_device *pdev, out_destroy: cpu_pmu_destroy(pmu); out_free: - pr_info("failed to register PMU devices!\n"); + pr_info("%s: failed to register PMU devices! Error %i\n", + node->full_name, ret); kfree(pmu); return ret; } -- cgit v1.2.3 From af3997b569dbd2ff50318c874fa4618d8b628fb0 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Fri, 5 Feb 2016 13:29:28 +0200 Subject: drm/i915: Skip DDI PLL selection for DSI Skip DDI PLL selection if display type is DSI/MIPI. Signed-off-by: Mika Kahola Reviewed-by: Sivakumar Thulasimani Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1454671768-27062-1-git-send-email-mika.kahola@intel.com --- drivers/gpu/drm/i915/intel_display.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5bc9a364b04a..76421c962216 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9848,8 +9848,13 @@ static void broadwell_modeset_commit_cdclk(struct drm_atomic_state *old_state) static int haswell_crtc_compute_clock(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) { - if (!intel_ddi_pll_select(crtc, crtc_state)) - return -EINVAL; + struct intel_encoder *intel_encoder = + intel_ddi_get_crtc_new_encoder(crtc_state); + + if (intel_encoder->type != INTEL_OUTPUT_DSI) { + if (!intel_ddi_pll_select(crtc, crtc_state)) + return -EINVAL; + } crtc->lowfreq_avail = false; -- cgit v1.2.3 From 44084efc2fd804e3b40159a19e1c4874f56f73ab Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Thu, 28 Jan 2016 18:54:36 -0500 Subject: ch7006: correctly handling failed allocation Since drm_property_create_range can be failed in memory pressure, it needs to be checked and return -ENOMEM. Signed-off-by: Insu Yun Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1454025276-13465-1-git-send-email-wuninsu@gmail.com --- drivers/gpu/drm/i2c/ch7006_drv.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c index 90db5f4dcce5..0594c45f7164 100644 --- a/drivers/gpu/drm/i2c/ch7006_drv.c +++ b/drivers/gpu/drm/i2c/ch7006_drv.c @@ -253,6 +253,8 @@ static int ch7006_encoder_create_resources(struct drm_encoder *encoder, drm_mode_create_tv_properties(dev, NUM_TV_NORMS, ch7006_tv_norm_names); priv->scale_property = drm_property_create_range(dev, 0, "scale", 0, 2); + if (!priv->scale_property) + return -ENOMEM; drm_object_attach_property(&connector->base, conf->tv_select_subconnector_property, priv->select_subconnector); -- cgit v1.2.3 From 67fe85dd6df202d66a46054486d2b339ebed84c4 Mon Sep 17 00:00:00 2001 From: LABBE Corentin Date: Thu, 4 Feb 2016 15:03:52 +0100 Subject: drm: modes: add missing [drm] to message printing The warning message in drm_mode_parse_command_line_for_connector miss the [drm] at beginning. This patch add it and take the opportunity to convert printk(KERN_WARNING to pr_warn() Signed-off-by: LABBE Corentin Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1454594633-15100-1-git-send-email-clabbe.montjoie@gmail.com --- drivers/gpu/drm/drm_modes.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 20775c05235a..f7448a5e95a9 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1371,8 +1371,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, } done: if (i >= 0) { - printk(KERN_WARNING - "parse error at position %i in video mode '%s'\n", + pr_warn("[drm] parse error at position %i in video mode '%s'\n", i, name); mode->specified = false; return false; -- cgit v1.2.3 From e9f8250f2f92b0e087aef84a33014372375c73db Mon Sep 17 00:00:00 2001 From: Haixia Shi Date: Fri, 5 Feb 2016 13:57:43 -0800 Subject: drm/msm: remove the drm_device_is_unplugged check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This flag is only used for drm/udl. Signed-off-by: Haixia Shi Reviewed-by: Stéphane Marchesin Reviewed-by: David Herrmann Acked-by: Rob Clark Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1454709464-2536-1-git-send-email-hshi@chromium.org --- drivers/gpu/drm/msm/msm_fbdev.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index d95af6eba602..e119c2979509 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c @@ -65,9 +65,6 @@ static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma) struct drm_device *dev = helper->dev; int ret = 0; - if (drm_device_is_unplugged(dev)) - return -ENODEV; - ret = drm_gem_mmap_obj(drm_obj, drm_obj->size, vma); if (ret) { pr_err("%s:drm_gem_mmap_obj fail\n", __func__); -- cgit v1.2.3 From 4c61716c2bfaaf1b8837a67775662008b4f42225 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 9 Feb 2016 17:29:44 +0200 Subject: drm: Add drm_format_plane_width() and drm_format_plane_height() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a few helpers to get the dimensions of the chroma plane(s). v2: Add kernel-doc (Daniel) v3: Fix kerneldoc "Returns:" style (Daniel) Uninline the functions and check for num_planes (Daniel) v4: Add the required EXPORT_SYMBOL()s Cc: dri-devel@lists.freedesktop.org Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1455031784-10941-1-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_crtc.c | 42 ++++++++++++++++++++++++++++++++++++++++++ include/drm/drm_crtc.h | 2 ++ 2 files changed, 44 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4132d58dab93..65258acddb90 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -5737,6 +5737,48 @@ int drm_format_vert_chroma_subsampling(uint32_t format) } EXPORT_SYMBOL(drm_format_vert_chroma_subsampling); +/** + * drm_format_plane_width - width of the plane given the first plane + * @width: width of the first plane + * @format: pixel format + * @plane: plane index + * + * Returns: + * The width of @plane, given that the width of the first plane is @width. + */ +int drm_format_plane_width(int width, uint32_t format, int plane) +{ + if (plane >= drm_format_num_planes(format)) + return 0; + + if (plane == 0) + return width; + + return width / drm_format_horz_chroma_subsampling(format); +} +EXPORT_SYMBOL(drm_format_plane_width); + +/** + * drm_format_plane_height - height of the plane given the first plane + * @height: height of the first plane + * @format: pixel format + * @plane: plane index + * + * Returns: + * The height of @plane, given that the height of the first plane is @height. + */ +int drm_format_plane_height(int height, uint32_t format, int plane) +{ + if (plane >= drm_format_num_planes(format)) + return 0; + + if (plane == 0) + return height; + + return height / drm_format_vert_chroma_subsampling(format); +} +EXPORT_SYMBOL(drm_format_plane_height); + /** * drm_rotation_simplify() - Try to simplify the rotation * @rotation: Rotation to be simplified diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index ad53d2ffd48c..8c7fb3d0f9d0 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -2498,6 +2498,8 @@ extern int drm_format_num_planes(uint32_t format); extern int drm_format_plane_cpp(uint32_t format, int plane); extern int drm_format_horz_chroma_subsampling(uint32_t format); extern int drm_format_vert_chroma_subsampling(uint32_t format); +extern int drm_format_plane_width(int width, uint32_t format, int plane); +extern int drm_format_plane_height(int height, uint32_t format, int plane); extern const char *drm_get_format_name(uint32_t format); extern struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, unsigned int supported_rotations); -- cgit v1.2.3 From 46189518d73080f4e4ea269a3b0f4b8583f486bd Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Tue, 9 Feb 2016 17:58:22 +0530 Subject: regmap: irq: dispose all virtual irq before removing domain It is require to dispose all virtual irq of hwirq on chip created on given irq domain before removing this irq domain. Hence dispose all mapped irqs before deleting the irq domains in regmap_del_irq_chip(); Signed-off-by: Laxman Dewangan Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-irq.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index 9b0d202414d0..7e1e9e86c70b 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -655,13 +655,34 @@ EXPORT_SYMBOL_GPL(regmap_add_irq_chip); * * @irq: Primary IRQ for the device * @d: regmap_irq_chip_data allocated by regmap_add_irq_chip() + * + * This function also dispose all mapped irq on chip. */ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d) { + unsigned int virq; + int hwirq; + if (!d) return; free_irq(irq, d); + + /* Dispose all virtual irq from irq domain before removing it */ + for (hwirq = 0; hwirq < d->chip->num_irqs; hwirq++) { + /* Ignore hwirq if holes in the IRQ list */ + if (!d->chip->irqs[hwirq].mask) + continue; + + /* + * Find the virtual irq of hwirq on chip and if it is + * there then dispose it + */ + virq = irq_find_mapping(d->domain, hwirq); + if (virq) + irq_dispose_mapping(virq); + } + irq_domain_remove(d->domain); kfree(d->type_buf); kfree(d->type_buf_def); -- cgit v1.2.3 From 21d147880e4895e645f890904784b079f1ba76f4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Feb 2016 10:21:22 -0700 Subject: nvme: fix Kconfig description for BLK_DEV_NVME_SCSI Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/nvme/host/Kconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig index 5d6237391dcd..b586d84f2518 100644 --- a/drivers/nvme/host/Kconfig +++ b/drivers/nvme/host/Kconfig @@ -17,5 +17,6 @@ config BLK_DEV_NVME_SCSI and block devices nodes, as well a a translation for a small number of selected SCSI commands to NVMe commands to the NVMe driver. If you don't know what this means you probably want - to say N here, and if you know what it means you probably - want to say N as well. + to say N here, unless you run a distro that abuses the SCSI + emulation to provide stable device names for mount by id, like + some OpenSuSE and SLES versions. -- cgit v1.2.3 From 2430a94d1e719b7b4af2a65b781a4c036eb22e64 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 9 Feb 2016 20:19:14 +0900 Subject: clk: fix __clk_init_parent() for single parent clocks Before commit b3d192d5121f ("clk: simplify __clk_init_parent()"), __clk_init_parent() called .get_parent() only for multi-parent clocks. That commit changed the behavior to call .get_parent() if available even for single-parent clocks and root clocks. It turned out a problem because there are some single-parent clocks that implement .get_parent() callback and return non-zero index. The SOCFPGA clock is the case; the commit broke the SOCFPGA boards. To keep the original behavior, invoke .get_parent() only when num_parents is greater than 1. Fixes: b3d192d5121f ("clk: simplify __clk_init_parent()") Signed-off-by: Masahiro Yamada Reported-by: Dinh Nguyen Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index cd8382c83f48..67cd2f116c3b 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1662,7 +1662,7 @@ static struct clk_core *__clk_init_parent(struct clk_core *core) { u8 index = 0; - if (core->ops->get_parent) + if (core->num_parents > 1 && core->ops->get_parent) index = core->ops->get_parent(core->hw); return clk_core_get_parent_by_index(core, index); -- cgit v1.2.3 From a0a90718f18264dc904d34a580f332006f5561e9 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 8 Feb 2016 17:14:28 +0200 Subject: spi: Let drivers translate ACPI DeviceSelection to suitable Linux chip select In Windows it is up to the SPI host controller driver to handle the ACPI DeviceSelection as it likes. The SPI core does not take any part in it. This is different in Linux because we always expect to have chip select in range of 0 .. master->num_chipselect - 1. In order to support this in Linux we need a way to allow the driver to translate between ACPI DeviceSelection field and Linux chip select number so provide a new optional hook ->fw_translate_cs() that can be used by a driver to handle translation and call this hook if set during SPI slave ACPI enumeration. Signed-off-by: Mika Westerberg Reviewed-by: Jarkko Nikula Signed-off-by: Mark Brown --- drivers/spi/spi.c | 19 ++++++++++++++++++- include/linux/spi/spi.h | 5 +++++ 2 files changed, 23 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 47eff8012a77..2c0c26a57f03 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1581,13 +1581,30 @@ static void of_register_spi_devices(struct spi_master *master) { } static int acpi_spi_add_resource(struct acpi_resource *ares, void *data) { struct spi_device *spi = data; + struct spi_master *master = spi->master; if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { struct acpi_resource_spi_serialbus *sb; sb = &ares->data.spi_serial_bus; if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_SPI) { - spi->chip_select = sb->device_selection; + /* + * ACPI DeviceSelection numbering is handled by the + * host controller driver in Windows and can vary + * from driver to driver. In Linux we always expect + * 0 .. max - 1 so we need to ask the driver to + * translate between the two schemes. + */ + if (master->fw_translate_cs) { + int cs = master->fw_translate_cs(master, + sb->device_selection); + if (cs < 0) + return cs; + spi->chip_select = cs; + } else { + spi->chip_select = sb->device_selection; + } + spi->max_speed_hz = sb->connection_speed; if (sb->clock_phase == ACPI_SPI_SECOND_PHASE) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 53be3a4c60cb..8a25e6c2fb56 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -369,6 +369,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * @dma_rx: DMA receive channel * @dummy_rx: dummy receive buffer for full-duplex devices * @dummy_tx: dummy transmit buffer for full-duplex devices + * @fw_translate_cs: If the boot firmware uses different numbering scheme + * what Linux expects, this optional hook can be used to translate + * between the two. * * Each SPI master controller can communicate with one or more @spi_device * children. These make a small bus, sharing MOSI, MISO and SCK signals @@ -537,6 +540,8 @@ struct spi_master { /* dummy data for full duplex devices */ void *dummy_rx; void *dummy_tx; + + int (*fw_translate_cs)(struct spi_master *master, unsigned cs); }; static inline void *spi_master_get_devdata(struct spi_master *master) -- cgit v1.2.3 From dd193929d91e1b44b90f81509feeff10c94ddc4d Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Thu, 7 Jan 2016 14:12:38 +0800 Subject: PCI: designware: Explain why we don't program ATU for some platforms Some platforms don't support ATU, e.g., pci-keystone.c. These platforms use their own address translation component rather than ATU, and they provide the rd_other_conf and wr_other_conf methods to program the translation component and perform the access. Add a comment to explain why we don't program the ATU for these platforms. [bhelgaas: changelog] Signed-off-by: Jisheng Zhang Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pcie-designware.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 21716827847a..8bcaed18f0dd 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -517,6 +517,11 @@ int dw_pcie_host_init(struct pcie_port *pp) if (pp->ops->host_init) pp->ops->host_init(pp); + /* + * If the platform provides ->rd_other_conf, it means the platform + * uses its own address translation component rather than ATU, so + * we should not program the ATU here. + */ if (!pp->ops->rd_other_conf) dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1, PCIE_ATU_TYPE_MEM, pp->mem_base, -- cgit v1.2.3 From ed00c83cd4909dc268cc0639bf16804444ed8c79 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 29 Jan 2016 11:29:32 +0000 Subject: PCI: designware: Remove PCI_PROBE_ONLY handling The PCIe designware host driver is not used in system configurations requiring the PCI_PROBE_ONLY flag to be set to prevent resources assignment, therefore the driver code handling the flag can be removed from the kernel. Signed-off-by: Lorenzo Pieralisi Signed-off-by: Bjorn Helgaas Acked-by: Pratyush Anand Acked-by: Jingoo Han Jingoo Han Cc: Arnd Bergmann Cc: Gabriele Paoloni Cc: Zhou Wang --- drivers/pci/host/pcie-designware.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 8bcaed18f0dd..f85f10d22049 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -556,13 +556,11 @@ int dw_pcie_host_init(struct pcie_port *pp) pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); #endif - if (!pci_has_flag(PCI_PROBE_ONLY)) { - pci_bus_size_bridges(bus); - pci_bus_assign_resources(bus); + pci_bus_size_bridges(bus); + pci_bus_assign_resources(bus); - list_for_each_entry(child, &bus->children, node) - pcie_bus_configure_settings(child); - } + list_for_each_entry(child, &bus->children, node) + pcie_bus_configure_settings(child); pci_bus_add_devices(bus); return 0; -- cgit v1.2.3 From 0c27d9cf7245d832d3d34f289c1bcd4f7f3fbd30 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 8 Feb 2016 17:14:29 +0200 Subject: spi: pxa2xx: Translate ACPI DeviceSelection to Linux chip select on Baytrail The Windows Baytrail SPI host controller driver uses 1 as the first (and only) value for ACPI DeviceSelection like can be seen in DSDT taken from Lenovo Thinkpad 10: Device (FPNT) { ... Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings { Name (UBUF, ResourceTemplate () { SpiSerialBus (0x0001, // DeviceSelection PolarityLow, FourWireMode, 0x08, ControllerInitiated, 0x007A1200, ClockPolarityLow, ClockPhaseFirst, "\\_SB.SPI1", 0x00, ResourceConsumer,,) This will fail to enumerate in Linux with following error: [ 0.241296] pxa2xx-spi 80860F0E:00: cs1 >= max 1 [ 0.241312] spi_master spi32766: failed to add SPI device VFSI6101:00 from ACPI To make the Linux SPI core successfully enumerate the device we provide a custom version of ->fw_translate_cs() that translates DeviceSelection correctly. Signed-off-by: Mika Westerberg Reviewed-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index ce66cf44bba5..7d6d3b74d25b 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1445,6 +1445,28 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev) } #endif +static int pxa2xx_spi_fw_translate_cs(struct spi_master *master, unsigned cs) +{ + struct driver_data *drv_data = spi_master_get_devdata(master); + + if (has_acpi_companion(&drv_data->pdev->dev)) { + switch (drv_data->ssp_type) { + /* + * For Atoms the ACPI DeviceSelection used by the Windows + * driver starts from 1 instead of 0 so translate it here + * to match what Linux expects. + */ + case LPSS_BYT_SSP: + return cs - 1; + + default: + break; + } + } + + return cs; +} + static int pxa2xx_spi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1497,6 +1519,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) master->setup = setup; master->transfer_one_message = pxa2xx_spi_transfer_one_message; master->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer; + master->fw_translate_cs = pxa2xx_spi_fw_translate_cs; master->auto_runtime_pm = true; drv_data->ssp_type = ssp->type; -- cgit v1.2.3 From c1e4a53c6b8161ded3a44e3352ef38206d0967ea Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 8 Feb 2016 17:14:30 +0200 Subject: spi: pxa2xx: Move chip select control bits into lpss_config structure Some Intel LPSS SPI controllers, like the one in Braswell has these bits in a different location so move these bits to be part of the LPSS configuration. Since not all LPSS SPI controllers support multiple native chip selects we refactor selecting chip select to its own function and check control->cs_sel_mask before switching to another chip select. Signed-off-by: Mika Westerberg Reviewed-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 64 ++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 7d6d3b74d25b..81d68e01046a 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -65,8 +65,6 @@ MODULE_ALIAS("platform:pxa2xx-spi"); #define LPSS_GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24) #define LPSS_CS_CONTROL_SW_MODE BIT(0) #define LPSS_CS_CONTROL_CS_HIGH BIT(1) -#define LPSS_CS_CONTROL_CS_SEL_SHIFT 8 -#define LPSS_CS_CONTROL_CS_SEL_MASK (3 << LPSS_CS_CONTROL_CS_SEL_SHIFT) #define LPSS_CAPS_CS_EN_SHIFT 9 #define LPSS_CAPS_CS_EN_MASK (0xf << LPSS_CAPS_CS_EN_SHIFT) @@ -82,6 +80,9 @@ struct lpss_config { u32 rx_threshold; u32 tx_threshold_lo; u32 tx_threshold_hi; + /* Chip select control */ + unsigned cs_sel_shift; + unsigned cs_sel_mask; }; /* Keep these sorted with enum pxa_ssp_type */ @@ -125,6 +126,8 @@ static const struct lpss_config lpss_platforms[] = { .rx_threshold = 1, .tx_threshold_lo = 16, .tx_threshold_hi = 48, + .cs_sel_shift = 8, + .cs_sel_mask = 3 << 8, }, }; @@ -288,37 +291,50 @@ static void lpss_ssp_setup(struct driver_data *drv_data) } } +static void lpss_ssp_select_cs(struct driver_data *drv_data, + const struct lpss_config *config) +{ + u32 value, cs; + + if (!config->cs_sel_mask) + return; + + value = __lpss_ssp_read_priv(drv_data, config->reg_cs_ctrl); + + cs = drv_data->cur_msg->spi->chip_select; + cs <<= config->cs_sel_shift; + if (cs != (value & config->cs_sel_mask)) { + /* + * When switching another chip select output active the + * output must be selected first and wait 2 ssp_clk cycles + * before changing state to active. Otherwise a short + * glitch will occur on the previous chip select since + * output select is latched but state control is not. + */ + value &= ~config->cs_sel_mask; + value |= cs; + __lpss_ssp_write_priv(drv_data, + config->reg_cs_ctrl, value); + ndelay(1000000000 / + (drv_data->master->max_speed_hz / 2)); + } +} + static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable) { const struct lpss_config *config; - u32 value, cs; + u32 value; config = lpss_get_config(drv_data); + if (enable) + lpss_ssp_select_cs(drv_data, config); + value = __lpss_ssp_read_priv(drv_data, config->reg_cs_ctrl); - if (enable) { - cs = drv_data->cur_msg->spi->chip_select; - cs <<= LPSS_CS_CONTROL_CS_SEL_SHIFT; - if (cs != (value & LPSS_CS_CONTROL_CS_SEL_MASK)) { - /* - * When switching another chip select output active - * the output must be selected first and wait 2 ssp_clk - * cycles before changing state to active. Otherwise - * a short glitch will occur on the previous chip - * select since output select is latched but state - * control is not. - */ - value &= ~LPSS_CS_CONTROL_CS_SEL_MASK; - value |= cs; - __lpss_ssp_write_priv(drv_data, - config->reg_cs_ctrl, value); - ndelay(1000000000 / - (drv_data->master->max_speed_hz / 2)); - } + if (enable) value &= ~LPSS_CS_CONTROL_CS_HIGH; - } else { + else value |= LPSS_CS_CONTROL_CS_HIGH; - } __lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value); } -- cgit v1.2.3 From 30f3a6ab44d8d06bb3d94f6320e4aa76df59d025 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 8 Feb 2016 17:14:31 +0200 Subject: spi: pxa2xx: Add support for both chip selects on Intel Braswell Intel Braswell LPSS SPI controller actually has two chip selects and there is no capabilities register where this could be found out. These two chip selects are controlled by bits which are in slightly differrent location than Broxton has. Braswell Windows driver also starts chip select (ACPI DeviceSelection) numbering from 1 so translate it to be suitable for Linux as well. Signed-off-by: Mika Westerberg Reviewed-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 21 ++++++++++++++++++++- include/linux/pxa2xx_ssp.h | 1 + 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 81d68e01046a..0eb79368eabc 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -83,6 +83,7 @@ struct lpss_config { /* Chip select control */ unsigned cs_sel_shift; unsigned cs_sel_mask; + unsigned cs_num; }; /* Keep these sorted with enum pxa_ssp_type */ @@ -107,6 +108,19 @@ static const struct lpss_config lpss_platforms[] = { .tx_threshold_lo = 160, .tx_threshold_hi = 224, }, + { /* LPSS_BSW_SSP */ + .offset = 0x400, + .reg_general = 0x08, + .reg_ssp = 0x0c, + .reg_cs_ctrl = 0x18, + .reg_capabilities = -1, + .rx_threshold = 64, + .tx_threshold_lo = 160, + .tx_threshold_hi = 224, + .cs_sel_shift = 2, + .cs_sel_mask = 1 << 2, + .cs_num = 2, + }, { /* LPSS_SPT_SSP */ .offset = 0x200, .reg_general = -1, @@ -142,6 +156,7 @@ static bool is_lpss_ssp(const struct driver_data *drv_data) switch (drv_data->ssp_type) { case LPSS_LPT_SSP: case LPSS_BYT_SSP: + case LPSS_BSW_SSP: case LPSS_SPT_SSP: case LPSS_BXT_SSP: return true; @@ -1189,6 +1204,7 @@ static int setup(struct spi_device *spi) break; case LPSS_LPT_SSP: case LPSS_BYT_SSP: + case LPSS_BSW_SSP: case LPSS_SPT_SSP: case LPSS_BXT_SSP: config = lpss_get_config(drv_data); @@ -1336,7 +1352,7 @@ static const struct acpi_device_id pxa2xx_spi_acpi_match[] = { { "INT3430", LPSS_LPT_SSP }, { "INT3431", LPSS_LPT_SSP }, { "80860F0E", LPSS_BYT_SSP }, - { "8086228E", LPSS_BYT_SSP }, + { "8086228E", LPSS_BSW_SSP }, { }, }; MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match); @@ -1473,6 +1489,7 @@ static int pxa2xx_spi_fw_translate_cs(struct spi_master *master, unsigned cs) * to match what Linux expects. */ case LPSS_BYT_SSP: + case LPSS_BSW_SSP: return cs - 1; default: @@ -1622,6 +1639,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) tmp &= LPSS_CAPS_CS_EN_MASK; tmp >>= LPSS_CAPS_CS_EN_SHIFT; platform_info->num_chipselect = ffz(tmp); + } else if (config->cs_num) { + platform_info->num_chipselect = config->cs_num; } } master->num_chipselect = platform_info->num_chipselect; diff --git a/include/linux/pxa2xx_ssp.h b/include/linux/pxa2xx_ssp.h index c2f2574ff61c..2a097d176ba9 100644 --- a/include/linux/pxa2xx_ssp.h +++ b/include/linux/pxa2xx_ssp.h @@ -197,6 +197,7 @@ enum pxa_ssp_type { QUARK_X1000_SSP, LPSS_LPT_SSP, /* Keep LPSS types sorted with lpss_platforms[] */ LPSS_BYT_SSP, + LPSS_BSW_SSP, LPSS_SPT_SSP, LPSS_BXT_SSP, }; -- cgit v1.2.3 From d780c3711d9df9bacd56b71cf23443b895a331ca Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 14 Dec 2015 15:20:18 +0000 Subject: spi: core: added spi_resource management SPI resource management framework used while processing a spi_message via the spi-core. The basic idea is taken from devres, but as the allocation may happen fairly frequently, some provisioning (in the form of an unused spi_device pointer argument to spi_res_alloc) has been made so that at a later stage we may implement reuse objects allocated earlier avoiding the repeated allocation by keeping a cache of objects that we can reuse. This framework can get used for: * rewriting spi_messages * to fullfill alignment requirements of the spi_master HW * to fullfill transfer length requirements (e.g: transfers need to be less than 64k) * consolidate spi_messages with multiple transfers into a single transfer when the total transfer length is below a threshold. * reimplement spi_unmap_buf without explicitly needing to check if it has been mapped Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/spi/spi.h | 36 +++++++++++++++++++ 2 files changed, 127 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 47eff8012a77..894ed0357dd7 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1024,6 +1024,8 @@ out: if (msg->status && master->handle_err) master->handle_err(master, msg); + spi_res_release(master, msg); + spi_finalize_current_message(master); return ret; @@ -2013,6 +2015,95 @@ struct spi_master *spi_busnum_to_master(u16 bus_num) } EXPORT_SYMBOL_GPL(spi_busnum_to_master); +/*-------------------------------------------------------------------------*/ + +/* Core methods for SPI resource management */ + +/** + * spi_res_alloc - allocate a spi resource that is life-cycle managed + * during the processing of a spi_message while using + * spi_transfer_one + * @spi: the spi device for which we allocate memory + * @release: the release code to execute for this resource + * @size: size to alloc and return + * @gfp: GFP allocation flags + * + * Return: the pointer to the allocated data + * + * This may get enhanced in the future to allocate from a memory pool + * of the @spi_device or @spi_master to avoid repeated allocations. + */ +void *spi_res_alloc(struct spi_device *spi, + spi_res_release_t release, + size_t size, gfp_t gfp) +{ + struct spi_res *sres; + + sres = kzalloc(sizeof(*sres) + size, gfp); + if (!sres) + return NULL; + + INIT_LIST_HEAD(&sres->entry); + sres->release = release; + + return sres->data; +} +EXPORT_SYMBOL_GPL(spi_res_alloc); + +/** + * spi_res_free - free an spi resource + * @res: pointer to the custom data of a resource + * + */ +void spi_res_free(void *res) +{ + struct spi_res *sres = container_of(res, struct spi_res, data); + + if (!res) + return; + + WARN_ON(!list_empty(&sres->entry)); + kfree(sres); +} +EXPORT_SYMBOL_GPL(spi_res_free); + +/** + * spi_res_add - add a spi_res to the spi_message + * @message: the spi message + * @res: the spi_resource + */ +void spi_res_add(struct spi_message *message, void *res) +{ + struct spi_res *sres = container_of(res, struct spi_res, data); + + WARN_ON(!list_empty(&sres->entry)); + list_add_tail(&sres->entry, &message->resources); +} +EXPORT_SYMBOL_GPL(spi_res_add); + +/** + * spi_res_release - release all spi resources for this message + * @master: the @spi_master + * @message: the @spi_message + */ +void spi_res_release(struct spi_master *master, + struct spi_message *message) +{ + struct spi_res *res; + + while (!list_empty(&message->resources)) { + res = list_last_entry(&message->resources, + struct spi_res, entry); + + if (res->release) + res->release(master, message, res->data); + + list_del(&res->entry); + + kfree(res); + } +} +EXPORT_SYMBOL_GPL(spi_res_release); /*-------------------------------------------------------------------------*/ diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 53be3a4c60cb..38204b584dc5 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -582,6 +582,37 @@ extern void spi_unregister_master(struct spi_master *master); extern struct spi_master *spi_busnum_to_master(u16 busnum); +/* + * SPI resource management while processing a SPI message + */ + +/** + * struct spi_res - spi resource management structure + * @entry: list entry + * @release: release code called prior to freeing this resource + * @data: extra data allocated for the specific use-case + * + * this is based on ideas from devres, but focused on life-cycle + * management during spi_message processing + */ +typedef void (*spi_res_release_t)(struct spi_master *master, + struct spi_message *msg, + void *res); +struct spi_res { + struct list_head entry; + spi_res_release_t release; + unsigned long long data[]; /* guarantee ull alignment */ +}; + +extern void *spi_res_alloc(struct spi_device *spi, + spi_res_release_t release, + size_t size, gfp_t gfp); +extern void spi_res_add(struct spi_message *message, void *res); +extern void spi_res_free(void *res); + +extern void spi_res_release(struct spi_master *master, + struct spi_message *message); + /*---------------------------------------------------------------------------*/ /* @@ -720,6 +751,7 @@ struct spi_transfer { * @status: zero for success, else negative errno * @queue: for use by whichever driver currently owns the message * @state: for use by whichever driver currently owns the message + * @resources: for resource management when the spi message is processed * * A @spi_message is used to execute an atomic sequence of data transfers, * each represented by a struct spi_transfer. The sequence is "atomic" @@ -766,11 +798,15 @@ struct spi_message { */ struct list_head queue; void *state; + + /* list of spi_res reources when the spi message is processed */ + struct list_head resources; }; static inline void spi_message_init_no_memset(struct spi_message *m) { INIT_LIST_HEAD(&m->transfers); + INIT_LIST_HEAD(&m->resources); } static inline void spi_message_init(struct spi_message *m) -- cgit v1.2.3 From 523baf5a0609690cb742b3662b7ccac0ea0b2ef2 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 14 Dec 2015 15:20:19 +0000 Subject: spi: core: add spi_replace_transfers method Add the spi_replace_transfers method that can get used to replace some spi_transfers from a spi_message with other transfers. Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/spi/spi.h | 45 +++++++++++++++++ 2 files changed, 177 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 894ed0357dd7..2ec8e66a8098 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2107,6 +2107,138 @@ EXPORT_SYMBOL_GPL(spi_res_release); /*-------------------------------------------------------------------------*/ +/* Core methods for spi_message alterations */ + +static void __spi_replace_transfers_release(struct spi_master *master, + struct spi_message *msg, + void *res) +{ + struct spi_replaced_transfers *rxfer = res; + size_t i; + + /* call extra callback if requested */ + if (rxfer->release) + rxfer->release(master, msg, res); + + /* insert replaced transfers back into the message */ + list_splice(&rxfer->replaced_transfers, rxfer->replaced_after); + + /* remove the formerly inserted entries */ + for (i = 0; i < rxfer->inserted; i++) + list_del(&rxfer->inserted_transfers[i].transfer_list); +} + +/** + * spi_replace_transfers - replace transfers with several transfers + * and register change with spi_message.resources + * @msg: the spi_message we work upon + * @xfer_first: the first spi_transfer we want to replace + * @remove: number of transfers to remove + * @insert: the number of transfers we want to insert instead + * @release: extra release code necessary in some circumstances + * @extradatasize: extra data to allocate (with alignment guarantees + * of struct @spi_transfer) + * + * Returns: pointer to @spi_replaced_transfers, + * PTR_ERR(...) in case of errors. + */ +struct spi_replaced_transfers *spi_replace_transfers( + struct spi_message *msg, + struct spi_transfer *xfer_first, + size_t remove, + size_t insert, + spi_replaced_release_t release, + size_t extradatasize, + gfp_t gfp) +{ + struct spi_replaced_transfers *rxfer; + struct spi_transfer *xfer; + size_t i; + + /* allocate the structure using spi_res */ + rxfer = spi_res_alloc(msg->spi, __spi_replace_transfers_release, + insert * sizeof(struct spi_transfer) + + sizeof(struct spi_replaced_transfers) + + extradatasize, + gfp); + if (!rxfer) + return ERR_PTR(-ENOMEM); + + /* the release code to invoke before running the generic release */ + rxfer->release = release; + + /* assign extradata */ + if (extradatasize) + rxfer->extradata = + &rxfer->inserted_transfers[insert]; + + /* init the replaced_transfers list */ + INIT_LIST_HEAD(&rxfer->replaced_transfers); + + /* assign the list_entry after which we should reinsert + * the @replaced_transfers - it may be spi_message.messages! + */ + rxfer->replaced_after = xfer_first->transfer_list.prev; + + /* remove the requested number of transfers */ + for (i = 0; i < remove; i++) { + /* if the entry after replaced_after it is msg->transfers + * then we have been requested to remove more transfers + * than are in the list + */ + if (rxfer->replaced_after->next == &msg->transfers) { + dev_err(&msg->spi->dev, + "requested to remove more spi_transfers than are available\n"); + /* insert replaced transfers back into the message */ + list_splice(&rxfer->replaced_transfers, + rxfer->replaced_after); + + /* free the spi_replace_transfer structure */ + spi_res_free(rxfer); + + /* and return with an error */ + return ERR_PTR(-EINVAL); + } + + /* remove the entry after replaced_after from list of + * transfers and add it to list of replaced_transfers + */ + list_move_tail(rxfer->replaced_after->next, + &rxfer->replaced_transfers); + } + + /* create copy of the given xfer with identical settings + * based on the first transfer to get removed + */ + for (i = 0; i < insert; i++) { + /* we need to run in reverse order */ + xfer = &rxfer->inserted_transfers[insert - 1 - i]; + + /* copy all spi_transfer data */ + memcpy(xfer, xfer_first, sizeof(*xfer)); + + /* add to list */ + list_add(&xfer->transfer_list, rxfer->replaced_after); + + /* clear cs_change and delay_usecs for all but the last */ + if (i) { + xfer->cs_change = false; + xfer->delay_usecs = 0; + } + } + + /* set up inserted */ + rxfer->inserted = insert; + + /* and register it with spi_res/spi_message */ + spi_res_add(msg, rxfer); + + return rxfer; +} +EXPORT_SYMBOL_GPL(spi_replace_transfers); + +/*-------------------------------------------------------------------------*/ + /* Core methods for SPI master protocol drivers. Some of the * other core methods are currently defined as inline functions. */ diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 38204b584dc5..d71385756fee 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -890,6 +890,51 @@ spi_max_transfer_size(struct spi_device *spi) /*---------------------------------------------------------------------------*/ +/* SPI transfer replacement methods which make use of spi_res */ + +/** + * struct spi_replaced_transfers - structure describing the spi_transfer + * replacements that have occurred + * so that they can get reverted + * @release: some extra release code to get executed prior to + * relasing this structure + * @extradata: pointer to some extra data if requested or NULL + * @replaced_transfers: transfers that have been replaced and which need + * to get restored + * @replaced_after: the transfer after which the @replaced_transfers + * are to get re-inserted + * @inserted: number of transfers inserted + * @inserted_transfers: array of spi_transfers of array-size @inserted, + * that have been replacing replaced_transfers + * + * note: that @extradata will point to @inserted_transfers[@inserted] + * if some extra allocation is requested, so alignment will be the same + * as for spi_transfers + */ +struct spi_replaced_transfers; +typedef void (*spi_replaced_release_t)(struct spi_master *master, + struct spi_message *msg, + struct spi_replaced_transfers *res); +struct spi_replaced_transfers { + spi_replaced_release_t release; + void *extradata; + struct list_head replaced_transfers; + struct list_head *replaced_after; + size_t inserted; + struct spi_transfer inserted_transfers[]; +}; + +extern struct spi_replaced_transfers *spi_replace_transfers( + struct spi_message *msg, + struct spi_transfer *xfer_first, + size_t remove, + size_t insert, + spi_replaced_release_t release, + size_t extradatasize, + gfp_t gfp); + +/*---------------------------------------------------------------------------*/ + /* All these synchronous SPI transfer routines are utilities layered * over the core async transfer primitive. Here, "synchronous" means * they will sleep uninterruptibly until the async transfer completes. -- cgit v1.2.3 From d9f1212272818420fcde611a940c1ad611a8b785 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Mon, 14 Dec 2015 15:20:20 +0000 Subject: spi: core: add spi_split_transfers_maxsize Add spi_split_transfers_maxsize method that splits spi_transfers transparently into multiple transfers that are below the given max-size. This makes use of the spi_res framework via spi_replace_transfers to allocate/free the extra transfers as well as reverting back the changes applied while processing the spi_message. Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/spi/spi.h | 15 +++++++ 2 files changed, 126 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 2ec8e66a8098..34e3741504f9 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -144,6 +144,8 @@ SPI_STATISTICS_TRANSFER_BYTES_HISTO(14, "16384-32767"); SPI_STATISTICS_TRANSFER_BYTES_HISTO(15, "32768-65535"); SPI_STATISTICS_TRANSFER_BYTES_HISTO(16, "65536+"); +SPI_STATISTICS_SHOW(transfers_split_maxsize, "%lu"); + static struct attribute *spi_dev_attrs[] = { &dev_attr_modalias.attr, NULL, @@ -181,6 +183,7 @@ static struct attribute *spi_device_statistics_attrs[] = { &dev_attr_spi_device_transfer_bytes_histo14.attr, &dev_attr_spi_device_transfer_bytes_histo15.attr, &dev_attr_spi_device_transfer_bytes_histo16.attr, + &dev_attr_spi_device_transfers_split_maxsize.attr, NULL, }; @@ -223,6 +226,7 @@ static struct attribute *spi_master_statistics_attrs[] = { &dev_attr_spi_master_transfer_bytes_histo14.attr, &dev_attr_spi_master_transfer_bytes_histo15.attr, &dev_attr_spi_master_transfer_bytes_histo16.attr, + &dev_attr_spi_master_transfers_split_maxsize.attr, NULL, }; @@ -2237,6 +2241,113 @@ struct spi_replaced_transfers *spi_replace_transfers( } EXPORT_SYMBOL_GPL(spi_replace_transfers); +int __spi_split_transfer_maxsize(struct spi_master *master, + struct spi_message *msg, + struct spi_transfer **xferp, + size_t maxsize, + gfp_t gfp) +{ + struct spi_transfer *xfer = *xferp, *xfers; + struct spi_replaced_transfers *srt; + size_t offset; + size_t count, i; + + /* warn once about this fact that we are splitting a transfer */ + dev_warn_once(&msg->spi->dev, + "spi_transfer of length %i exceed max length of %i - needed to split transfers\n", + xfer->len, maxsize); + + /* calculate how many we have to replace */ + count = DIV_ROUND_UP(xfer->len, maxsize); + + /* create replacement */ + srt = spi_replace_transfers(msg, xfer, 1, count, NULL, 0, gfp); + if (!srt) + return -ENOMEM; + xfers = srt->inserted_transfers; + + /* now handle each of those newly inserted spi_transfers + * note that the replacements spi_transfers all are preset + * to the same values as *xferp, so tx_buf, rx_buf and len + * are all identical (as well as most others) + * so we just have to fix up len and the pointers. + * + * this also includes support for the depreciated + * spi_message.is_dma_mapped interface + */ + + /* the first transfer just needs the length modified, so we + * run it outside the loop + */ + xfers[0].len = min(maxsize, xfer[0].len); + + /* all the others need rx_buf/tx_buf also set */ + for (i = 1, offset = maxsize; i < count; offset += maxsize, i++) { + /* update rx_buf, tx_buf and dma */ + if (xfers[i].rx_buf) + xfers[i].rx_buf += offset; + if (xfers[i].rx_dma) + xfers[i].rx_dma += offset; + if (xfers[i].tx_buf) + xfers[i].tx_buf += offset; + if (xfers[i].tx_dma) + xfers[i].tx_dma += offset; + + /* update length */ + xfers[i].len = min(maxsize, xfers[i].len - offset); + } + + /* we set up xferp to the last entry we have inserted, + * so that we skip those already split transfers + */ + *xferp = &xfers[count - 1]; + + /* increment statistics counters */ + SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, + transfers_split_maxsize); + SPI_STATISTICS_INCREMENT_FIELD(&msg->spi->statistics, + transfers_split_maxsize); + + return 0; +} + +/** + * spi_split_tranfers_maxsize - split spi transfers into multiple transfers + * when an individual transfer exceeds a + * certain size + * @master: the @spi_master for this transfer + * @message: the @spi_message to transform + * @max_size: the maximum when to apply this + * + * Return: status of transformation + */ +int spi_split_transfers_maxsize(struct spi_master *master, + struct spi_message *msg, + size_t maxsize, + gfp_t gfp) +{ + struct spi_transfer *xfer; + int ret; + + /* iterate over the transfer_list, + * but note that xfer is advanced to the last transfer inserted + * to avoid checking sizes again unnecessarily (also xfer does + * potentiall belong to a different list by the time the + * replacement has happened + */ + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + if (xfer->len > maxsize) { + ret = __spi_split_transfer_maxsize( + master, msg, &xfer, maxsize, gfp); + if (ret) + return ret; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(spi_split_transfers_maxsize); + /*-------------------------------------------------------------------------*/ /* Core methods for SPI master protocol drivers. Some of the diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index d71385756fee..3c02b4d06268 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -53,6 +53,10 @@ extern struct bus_type spi_bus_type; * * @transfer_bytes_histo: * transfer bytes histogramm + * + * @transfers_split_maxsize: + * number of transfers that have been split because of + * maxsize limit */ struct spi_statistics { spinlock_t lock; /* lock for the whole structure */ @@ -72,6 +76,8 @@ struct spi_statistics { #define SPI_STATISTICS_HISTO_SIZE 17 unsigned long transfer_bytes_histo[SPI_STATISTICS_HISTO_SIZE]; + + unsigned long transfers_split_maxsize; }; void spi_statistics_add_transfer_stats(struct spi_statistics *stats, @@ -935,6 +941,15 @@ extern struct spi_replaced_transfers *spi_replace_transfers( /*---------------------------------------------------------------------------*/ +/* SPI transfer transformation methods */ + +extern int spi_split_transfers_maxsize(struct spi_master *master, + struct spi_message *msg, + size_t maxsize, + gfp_t gfp); + +/*---------------------------------------------------------------------------*/ + /* All these synchronous SPI transfer routines are utilities layered * over the core async transfer primitive. Here, "synchronous" means * they will sleep uninterruptibly until the async transfer completes. -- cgit v1.2.3 From 556351f14e74db4cd3ddde386457edce7bf0b27f Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Fri, 11 Dec 2015 09:39:56 +0530 Subject: spi: introduce accelerated read support for spi flash devices In addition to providing direct access to SPI bus, some spi controller hardwares (like ti-qspi) provide special port (like memory mapped port) that are optimized to improve SPI flash read performance. This means the controller can automatically send the SPI signals required to read data from the SPI flash device. For this, SPI controller needs to know flash specific information like read command to use, dummy bytes and address width. Introduce spi_flash_read() interface to support accelerated read over SPI flash devices. SPI master drivers can implement this callback to support interfaces such as memory mapped read etc. m25p80 flash driver and other flash drivers can call this make use of such interfaces. The interface should only be used with SPI flashes and cannot be used with other SPI devices. Signed-off-by: Vignesh R Signed-off-by: Mark Brown --- drivers/spi/spi.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/spi/spi.h | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 47eff8012a77..dcc6f6e92668 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1152,6 +1152,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) } } + mutex_lock(&master->bus_lock_mutex); trace_spi_message_start(master->cur_msg); if (master->prepare_message) { @@ -1161,6 +1162,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) "failed to prepare message: %d\n", ret); master->cur_msg->status = ret; spi_finalize_current_message(master); + mutex_unlock(&master->bus_lock_mutex); return; } master->cur_msg_prepared = true; @@ -1170,6 +1172,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) if (ret) { master->cur_msg->status = ret; spi_finalize_current_message(master); + mutex_unlock(&master->bus_lock_mutex); return; } @@ -1177,8 +1180,10 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) if (ret) { dev_err(&master->dev, "failed to transfer one message from queue\n"); + mutex_unlock(&master->bus_lock_mutex); return; } + mutex_unlock(&master->bus_lock_mutex); } /** @@ -2351,6 +2356,46 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message) EXPORT_SYMBOL_GPL(spi_async_locked); +int spi_flash_read(struct spi_device *spi, + struct spi_flash_read_message *msg) + +{ + struct spi_master *master = spi->master; + int ret; + + if ((msg->opcode_nbits == SPI_NBITS_DUAL || + msg->addr_nbits == SPI_NBITS_DUAL) && + !(spi->mode & (SPI_TX_DUAL | SPI_TX_QUAD))) + return -EINVAL; + if ((msg->opcode_nbits == SPI_NBITS_QUAD || + msg->addr_nbits == SPI_NBITS_QUAD) && + !(spi->mode & SPI_TX_QUAD)) + return -EINVAL; + if (msg->data_nbits == SPI_NBITS_DUAL && + !(spi->mode & (SPI_RX_DUAL | SPI_RX_QUAD))) + return -EINVAL; + if (msg->data_nbits == SPI_NBITS_QUAD && + !(spi->mode & SPI_RX_QUAD)) + return -EINVAL; + + if (master->auto_runtime_pm) { + ret = pm_runtime_get_sync(master->dev.parent); + if (ret < 0) { + dev_err(&master->dev, "Failed to power device: %d\n", + ret); + return ret; + } + } + mutex_lock(&master->bus_lock_mutex); + ret = master->spi_flash_read(spi, msg); + mutex_unlock(&master->bus_lock_mutex); + if (master->auto_runtime_pm) + pm_runtime_put(master->dev.parent); + + return ret; +} +EXPORT_SYMBOL_GPL(spi_flash_read); + /*-------------------------------------------------------------------------*/ /* Utility methods for SPI master protocol drivers, layered on diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 53be3a4c60cb..ba0dee9d05a3 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -25,6 +25,7 @@ struct dma_chan; struct spi_master; struct spi_transfer; +struct spi_flash_read_message; /* * INTERFACES between SPI master-side drivers and SPI infrastructure. @@ -361,6 +362,8 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * @handle_err: the subsystem calls the driver to handle an error that occurs * in the generic implementation of transfer_one_message(). * @unprepare_message: undo any work done by prepare_message(). + * @spi_flash_read: to support spi-controller hardwares that provide + * accelerated interface to read from flash devices. * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS * number. Any individual value may be -ENOENT for CS lines that * are not GPIOs (driven by the SPI controller itself). @@ -513,6 +516,8 @@ struct spi_master { struct spi_message *message); int (*unprepare_message)(struct spi_master *master, struct spi_message *message); + int (*spi_flash_read)(struct spi_device *spi, + struct spi_flash_read_message *msg); /* * These hooks are for drivers that use a generic implementation @@ -1019,6 +1024,42 @@ static inline ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd) return be16_to_cpu(result); } +/** + * struct spi_flash_read_message - flash specific information for + * spi-masters that provide accelerated flash read interfaces + * @buf: buffer to read data + * @from: offset within the flash from where data is to be read + * @len: length of data to be read + * @retlen: actual length of data read + * @read_opcode: read_opcode to be used to communicate with flash + * @addr_width: number of address bytes + * @dummy_bytes: number of dummy bytes + * @opcode_nbits: number of lines to send opcode + * @addr_nbits: number of lines to send address + * @data_nbits: number of lines for data + */ +struct spi_flash_read_message { + void *buf; + loff_t from; + size_t len; + size_t retlen; + u8 read_opcode; + u8 addr_width; + u8 dummy_bytes; + u8 opcode_nbits; + u8 addr_nbits; + u8 data_nbits; +}; + +/* SPI core interface for flash read support */ +static inline bool spi_flash_read_supported(struct spi_device *spi) +{ + return spi->master->spi_flash_read ? true : false; +} + +int spi_flash_read(struct spi_device *spi, + struct spi_flash_read_message *msg); + /*---------------------------------------------------------------------------*/ /* -- cgit v1.2.3 From 4dea6c9b0b64fc4cbd543b5a3b6320218be8ca9c Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Fri, 11 Dec 2015 09:39:57 +0530 Subject: spi: spi-ti-qspi: add mmap mode read support ti-qspi controller provides mmap port to read data from SPI flashes. mmap port is enabled in QSPI_SPI_SWITCH_REG. ctrl module register may also need to be accessed for some SoCs. The QSPI_SPI_SETUP_REGx needs to be populated with flash specific information like read opcode, read mode(quad, dual, normal), address width and dummy bytes. Once, controller is in mmap mode, the whole flash memory is available as a memory region at SoC specific address. This region can be accessed using normal memcpy() (or mem-to-mem dma copy). The ti-qspi controller hardware will internally communicate with SPI flash over SPI bus and get the requested data. Implement spi_flash_read() callback to support mmap read over SPI flash devices. With this, the read throughput increases from ~100kB/s to ~2.5 MB/s. Signed-off-by: Vignesh R Signed-off-by: Mark Brown --- drivers/spi/spi-ti-qspi.c | 139 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 110 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 64318fcfacf2..eac3c960b2de 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include @@ -44,8 +46,9 @@ struct ti_qspi { struct spi_master *master; void __iomem *base; - void __iomem *ctrl_base; void __iomem *mmap_base; + struct regmap *ctrl_base; + unsigned int ctrl_reg; struct clk *fclk; struct device *dev; @@ -55,7 +58,7 @@ struct ti_qspi { u32 cmd; u32 dc; - bool ctrl_mod; + bool mmap_enabled; }; #define QSPI_PID (0x0) @@ -65,11 +68,8 @@ struct ti_qspi { #define QSPI_SPI_CMD_REG (0x48) #define QSPI_SPI_STATUS_REG (0x4c) #define QSPI_SPI_DATA_REG (0x50) -#define QSPI_SPI_SETUP0_REG (0x54) +#define QSPI_SPI_SETUP_REG(n) ((0x54 + 4 * n)) #define QSPI_SPI_SWITCH_REG (0x64) -#define QSPI_SPI_SETUP1_REG (0x58) -#define QSPI_SPI_SETUP2_REG (0x5c) -#define QSPI_SPI_SETUP3_REG (0x60) #define QSPI_SPI_DATA_REG_1 (0x68) #define QSPI_SPI_DATA_REG_2 (0x6c) #define QSPI_SPI_DATA_REG_3 (0x70) @@ -109,6 +109,17 @@ struct ti_qspi { #define QSPI_AUTOSUSPEND_TIMEOUT 2000 +#define MEM_CS_EN(n) ((n + 1) << 8) +#define MEM_CS_MASK (7 << 8) + +#define MM_SWITCH 0x1 + +#define QSPI_SETUP_RD_NORMAL (0x0 << 12) +#define QSPI_SETUP_RD_DUAL (0x1 << 12) +#define QSPI_SETUP_RD_QUAD (0x3 << 12) +#define QSPI_SETUP_ADDR_SHIFT 8 +#define QSPI_SETUP_DUMMY_SHIFT 10 + static inline unsigned long ti_qspi_read(struct ti_qspi *qspi, unsigned long reg) { @@ -366,6 +377,72 @@ static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t) return 0; } +static void ti_qspi_enable_memory_map(struct spi_device *spi) +{ + struct ti_qspi *qspi = spi_master_get_devdata(spi->master); + + ti_qspi_write(qspi, MM_SWITCH, QSPI_SPI_SWITCH_REG); + if (qspi->ctrl_base) { + regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg, + MEM_CS_EN(spi->chip_select), + MEM_CS_MASK); + } + qspi->mmap_enabled = true; +} + +static void ti_qspi_disable_memory_map(struct spi_device *spi) +{ + struct ti_qspi *qspi = spi_master_get_devdata(spi->master); + + ti_qspi_write(qspi, 0, QSPI_SPI_SWITCH_REG); + if (qspi->ctrl_base) + regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg, + 0, MEM_CS_MASK); + qspi->mmap_enabled = false; +} + +static void ti_qspi_setup_mmap_read(struct spi_device *spi, + struct spi_flash_read_message *msg) +{ + struct ti_qspi *qspi = spi_master_get_devdata(spi->master); + u32 memval = msg->read_opcode; + + switch (msg->data_nbits) { + case SPI_NBITS_QUAD: + memval |= QSPI_SETUP_RD_QUAD; + break; + case SPI_NBITS_DUAL: + memval |= QSPI_SETUP_RD_DUAL; + break; + default: + memval |= QSPI_SETUP_RD_NORMAL; + break; + } + memval |= ((msg->addr_width - 1) << QSPI_SETUP_ADDR_SHIFT | + msg->dummy_bytes << QSPI_SETUP_DUMMY_SHIFT); + ti_qspi_write(qspi, memval, + QSPI_SPI_SETUP_REG(spi->chip_select)); +} + +static int ti_qspi_spi_flash_read(struct spi_device *spi, + struct spi_flash_read_message *msg) +{ + struct ti_qspi *qspi = spi_master_get_devdata(spi->master); + int ret = 0; + + mutex_lock(&qspi->list_lock); + + if (!qspi->mmap_enabled) + ti_qspi_enable_memory_map(spi); + ti_qspi_setup_mmap_read(spi, msg); + memcpy_fromio(msg->buf, qspi->mmap_base + msg->from, msg->len); + msg->retlen = msg->len; + + mutex_unlock(&qspi->list_lock); + + return ret; +} + static int ti_qspi_start_transfer_one(struct spi_master *master, struct spi_message *m) { @@ -398,6 +475,9 @@ static int ti_qspi_start_transfer_one(struct spi_master *master, mutex_lock(&qspi->list_lock); + if (qspi->mmap_enabled) + ti_qspi_disable_memory_map(spi); + list_for_each_entry(t, &m->transfers, transfer_list) { qspi->cmd |= QSPI_WLEN(t->bits_per_word); @@ -441,7 +521,7 @@ static int ti_qspi_probe(struct platform_device *pdev) { struct ti_qspi *qspi; struct spi_master *master; - struct resource *r, *res_ctrl, *res_mmap; + struct resource *r, *res_mmap; struct device_node *np = pdev->dev.of_node; u32 max_freq; int ret = 0, num_cs, irq; @@ -487,16 +567,6 @@ static int ti_qspi_probe(struct platform_device *pdev) } } - res_ctrl = platform_get_resource_byname(pdev, - IORESOURCE_MEM, "qspi_ctrlmod"); - if (res_ctrl == NULL) { - res_ctrl = platform_get_resource(pdev, IORESOURCE_MEM, 2); - if (res_ctrl == NULL) { - dev_dbg(&pdev->dev, - "control module resources not required\n"); - } - } - irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "no irq resource?\n"); @@ -511,20 +581,31 @@ static int ti_qspi_probe(struct platform_device *pdev) goto free_master; } - if (res_ctrl) { - qspi->ctrl_mod = true; - qspi->ctrl_base = devm_ioremap_resource(&pdev->dev, res_ctrl); - if (IS_ERR(qspi->ctrl_base)) { - ret = PTR_ERR(qspi->ctrl_base); - goto free_master; - } - } - if (res_mmap) { - qspi->mmap_base = devm_ioremap_resource(&pdev->dev, res_mmap); + qspi->mmap_base = devm_ioremap_resource(&pdev->dev, + res_mmap); + master->spi_flash_read = ti_qspi_spi_flash_read; if (IS_ERR(qspi->mmap_base)) { - ret = PTR_ERR(qspi->mmap_base); - goto free_master; + dev_err(&pdev->dev, + "falling back to PIO mode\n"); + master->spi_flash_read = NULL; + } + } + qspi->mmap_enabled = false; + + if (of_property_read_bool(np, "syscon-chipselects")) { + qspi->ctrl_base = + syscon_regmap_lookup_by_phandle(np, + "syscon-chipselects"); + if (IS_ERR(qspi->ctrl_base)) + return PTR_ERR(qspi->ctrl_base); + ret = of_property_read_u32_index(np, + "syscon-chipselects", + 1, &qspi->ctrl_reg); + if (ret) { + dev_err(&pdev->dev, + "couldn't get ctrl_mod reg index\n"); + return ret; } } -- cgit v1.2.3 From 949928c1c731417cc0f070912c63878b62b544f4 Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Thu, 17 Dec 2015 17:08:15 -0700 Subject: NVMe: Fix possible queue use after freed This notifies blk-mq when the tag set contains a different number of queues prior to freeing unused ones that the request queue points to. Signed-off-by: Keith Busch Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/nvme/host/pci.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 72ef8322d32a..08791338ce75 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1381,7 +1381,7 @@ static int nvme_kthread(void *data) static int nvme_create_io_queues(struct nvme_dev *dev) { - unsigned i; + unsigned i, max; int ret = 0; for (i = dev->queue_count; i <= dev->max_qid; i++) { @@ -1391,7 +1391,8 @@ static int nvme_create_io_queues(struct nvme_dev *dev) } } - for (i = dev->online_queues; i <= dev->queue_count - 1; i++) { + max = min(dev->max_qid, dev->queue_count - 1); + for (i = dev->online_queues; i <= max; i++) { ret = nvme_create_queue(dev->queues[i], i); if (ret) { nvme_free_queues(dev, i); @@ -1548,9 +1549,6 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) adminq->cq_vector = -1; goto free_queues; } - - /* Free previously allocated queues that are no longer usable */ - nvme_free_queues(dev, nr_io_queues + 1); return nvme_create_io_queues(dev); free_queues: @@ -1684,7 +1682,13 @@ static int nvme_dev_add(struct nvme_dev *dev) if (blk_mq_alloc_tag_set(&dev->tagset)) return 0; dev->ctrl.tagset = &dev->tagset; + } else { + blk_mq_update_nr_hw_queues(&dev->tagset, dev->online_queues - 1); + + /* Free previously allocated queues that are no longer usable */ + nvme_free_queues(dev, dev->online_queues); } + queue_work(nvme_workq, &dev->scan_work); return 0; } -- cgit v1.2.3 From f4f0f63e6f01055dfbdb7bc5e83935e1bdfa1980 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Feb 2016 12:44:03 -0700 Subject: nvme: fix drvdata setup for the nvme device Pass the right private data to device_create_with_groups from the beginning, and remove the superflous call to dev_set_drvdata. Signed-off-by: Christoph Hellwig Reviewed-by: Jon Derrick Signed-off-by: Jens Axboe --- drivers/nvme/host/core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index c5bf001af559..c326931d9b4d 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1383,14 +1383,13 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev, ctrl->device = device_create_with_groups(nvme_class, ctrl->dev, MKDEV(nvme_char_major, ctrl->instance), - dev, nvme_dev_attr_groups, + ctrl, nvme_dev_attr_groups, "nvme%d", ctrl->instance); if (IS_ERR(ctrl->device)) { ret = PTR_ERR(ctrl->device); goto out_release_instance; } get_device(ctrl->device); - dev_set_drvdata(ctrl->device, ctrl); spin_lock(&dev_list_lock); list_add_tail(&ctrl->node, &nvme_ctrl_list); -- cgit v1.2.3 From 9d452184fc9d9c3a0e6df5910857c6017865e3c0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 8 Feb 2016 18:51:58 +0100 Subject: iio: buffer-dmaengine: Use dmaengine_terminate_sync() The DMAengine framework gained support for synchronized transfer termination. Use the new dmaengine_terminate_sync() function instead of dmaengine_terminate_all(), this avoids a potential race condition when disabling the buffer. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/buffer/industrialio-buffer-dmaengine.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c index ebdb838d3a1c..9fabed47053d 100644 --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c @@ -93,12 +93,7 @@ static void iio_dmaengine_buffer_abort(struct iio_dma_buffer_queue *queue) struct dmaengine_buffer *dmaengine_buffer = iio_buffer_to_dmaengine_buffer(&queue->buffer); - dmaengine_terminate_all(dmaengine_buffer->chan); - /* FIXME: There is a slight chance of a race condition here. - * dmaengine_terminate_all() does not guarantee that all transfer - * callbacks have finished running. Need to introduce a - * dmaengine_terminate_all_sync(). - */ + dmaengine_terminate_sync(dmaengine_buffer->chan); iio_dma_buffer_block_list_abort(queue, &dmaengine_buffer->active); } -- cgit v1.2.3 From 42bbe400fbef6283a28227ea262a1145b27e957f Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 8 Feb 2016 18:58:34 +0530 Subject: thermal: of: use for_each_available_child_of_node for child iterator Use for_each_available_child_of_node() for iterating over each available child instead of iterating over each child and then checking their status. Signed-off-by: Laxman Dewangan Signed-off-by: Eduardo Valentin --- drivers/thermal/of-thermal.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c index be4eedcb839a..9043f8f91852 100644 --- a/drivers/thermal/of-thermal.c +++ b/drivers/thermal/of-thermal.c @@ -475,14 +475,10 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data, sensor_np = of_node_get(dev->of_node); - for_each_child_of_node(np, child) { + for_each_available_child_of_node(np, child) { struct of_phandle_args sensor_specs; int ret, id; - /* Check whether child is enabled or not */ - if (!of_device_is_available(child)) - continue; - /* For now, thermal framework supports only 1 sensor per zone */ ret = of_parse_phandle_with_args(child, "thermal-sensors", "#thermal-sensor-cells", @@ -881,16 +877,12 @@ int __init of_parse_thermal_zones(void) return 0; /* Run successfully on systems without thermal DT */ } - for_each_child_of_node(np, child) { + for_each_available_child_of_node(np, child) { struct thermal_zone_device *zone; struct thermal_zone_params *tzp; int i, mask = 0; u32 prop; - /* Check whether child is enabled or not */ - if (!of_device_is_available(child)) - continue; - tz = thermal_of_build_thermal_zone(child); if (IS_ERR(tz)) { pr_err("failed to build thermal zone %s: %ld\n", @@ -968,13 +960,9 @@ void of_thermal_destroy_zones(void) return; } - for_each_child_of_node(np, child) { + for_each_available_child_of_node(np, child) { struct thermal_zone_device *zone; - /* Check whether child is enabled or not */ - if (!of_device_is_available(child)) - continue; - zone = thermal_zone_get_zone_by_name(child->name); if (IS_ERR(zone)) continue; -- cgit v1.2.3 From d69051b401d12c406831c18718ceb0cb73a45f3a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 8 Feb 2016 11:45:04 +0100 Subject: staging:iio:ad7192: Add support for the AD7193 The AD7193 is mostly register map compatible to the AD7192. The main difference is that it has 8 instead of 4 inputs, so the way the input channels are selected is slightly different. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/Kconfig | 4 +-- drivers/staging/iio/adc/ad7192.c | 76 ++++++++++++++++++++++++++++++++-------- 2 files changed, 63 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index 58d4517e1836..a700f1951cd9 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -58,12 +58,12 @@ config AD7816 temperature sensors and ADC. config AD7192 - tristate "Analog Devices AD7190 AD7192 AD7195 ADC driver" + tristate "Analog Devices AD7190 AD7192 AD7193 AD7195 ADC driver" depends on SPI select AD_SIGMA_DELTA help Say yes here to build support for Analog Devices AD7190, - AD7192 or AD7195 SPI analog to digital converters (ADC). + AD7192, AD7193 or AD7195 SPI analog to digital converters (ADC). If unsure, say N (but it's safe to say "Y"). To compile this driver as a module, choose M here: the diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 92f2b72cce30..f843f19cf675 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -1,7 +1,7 @@ /* - * AD7190 AD7192 AD7195 SPI ADC driver + * AD7190 AD7192 AD7193 AD7195 SPI ADC driver * - * Copyright 2011-2012 Analog Devices Inc. + * Copyright 2011-2015 Analog Devices Inc. * * Licensed under the GPL-2. */ @@ -92,26 +92,43 @@ #define AD7192_CONF_CHOP BIT(23) /* CHOP enable */ #define AD7192_CONF_REFSEL BIT(20) /* REFIN1/REFIN2 Reference Select */ -#define AD7192_CONF_CHAN(x) (((1 << (x)) & 0xFF) << 8) /* Channel select */ -#define AD7192_CONF_CHAN_MASK (0xFF << 8) /* Channel select mask */ +#define AD7192_CONF_CHAN(x) ((x) << 8) /* Channel select */ +#define AD7192_CONF_CHAN_MASK (0x7FF << 8) /* Channel select mask */ #define AD7192_CONF_BURN BIT(7) /* Burnout current enable */ #define AD7192_CONF_REFDET BIT(6) /* Reference detect enable */ #define AD7192_CONF_BUF BIT(4) /* Buffered Mode Enable */ #define AD7192_CONF_UNIPOLAR BIT(3) /* Unipolar/Bipolar Enable */ #define AD7192_CONF_GAIN(x) ((x) & 0x7) /* Gain Select */ -#define AD7192_CH_AIN1P_AIN2M 0 /* AIN1(+) - AIN2(-) */ -#define AD7192_CH_AIN3P_AIN4M 1 /* AIN3(+) - AIN4(-) */ -#define AD7192_CH_TEMP 2 /* Temp Sensor */ -#define AD7192_CH_AIN2P_AIN2M 3 /* AIN2(+) - AIN2(-) */ -#define AD7192_CH_AIN1 4 /* AIN1 - AINCOM */ -#define AD7192_CH_AIN2 5 /* AIN2 - AINCOM */ -#define AD7192_CH_AIN3 6 /* AIN3 - AINCOM */ -#define AD7192_CH_AIN4 7 /* AIN4 - AINCOM */ +#define AD7192_CH_AIN1P_AIN2M BIT(0) /* AIN1(+) - AIN2(-) */ +#define AD7192_CH_AIN3P_AIN4M BIT(1) /* AIN3(+) - AIN4(-) */ +#define AD7192_CH_TEMP BIT(2) /* Temp Sensor */ +#define AD7192_CH_AIN2P_AIN2M BIT(3) /* AIN2(+) - AIN2(-) */ +#define AD7192_CH_AIN1 BIT(4) /* AIN1 - AINCOM */ +#define AD7192_CH_AIN2 BIT(5) /* AIN2 - AINCOM */ +#define AD7192_CH_AIN3 BIT(6) /* AIN3 - AINCOM */ +#define AD7192_CH_AIN4 BIT(7) /* AIN4 - AINCOM */ + +#define AD7193_CH_AIN1P_AIN2M 0x000 /* AIN1(+) - AIN2(-) */ +#define AD7193_CH_AIN3P_AIN4M 0x001 /* AIN3(+) - AIN4(-) */ +#define AD7193_CH_AIN5P_AIN6M 0x002 /* AIN5(+) - AIN6(-) */ +#define AD7193_CH_AIN7P_AIN8M 0x004 /* AIN7(+) - AIN8(-) */ +#define AD7193_CH_TEMP 0x100 /* Temp senseor */ +#define AD7193_CH_AIN2P_AIN2M 0x200 /* AIN2(+) - AIN2(-) */ +#define AD7193_CH_AIN1 0x401 /* AIN1 - AINCOM */ +#define AD7193_CH_AIN2 0x402 /* AIN2 - AINCOM */ +#define AD7193_CH_AIN3 0x404 /* AIN3 - AINCOM */ +#define AD7193_CH_AIN4 0x408 /* AIN4 - AINCOM */ +#define AD7193_CH_AIN5 0x410 /* AIN5 - AINCOM */ +#define AD7193_CH_AIN6 0x420 /* AIN6 - AINCOM */ +#define AD7193_CH_AIN7 0x440 /* AIN7 - AINCOM */ +#define AD7193_CH_AIN8 0x480 /* AIN7 - AINCOM */ +#define AD7193_CH_AINCOM 0x600 /* AINCOM - AINCOM */ /* ID Register Bit Designations (AD7192_REG_ID) */ #define ID_AD7190 0x4 #define ID_AD7192 0x0 +#define ID_AD7193 0x2 #define ID_AD7195 0x6 #define AD7192_ID_MASK 0x0F @@ -607,6 +624,24 @@ static const struct iio_chan_spec ad7192_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(8), }; +static const struct iio_chan_spec ad7193_channels[] = { + AD_SD_DIFF_CHANNEL(0, 1, 2, AD7193_CH_AIN1P_AIN2M, 24, 32, 0), + AD_SD_DIFF_CHANNEL(1, 3, 4, AD7193_CH_AIN3P_AIN4M, 24, 32, 0), + AD_SD_DIFF_CHANNEL(2, 5, 6, AD7193_CH_AIN5P_AIN6M, 24, 32, 0), + AD_SD_DIFF_CHANNEL(3, 7, 8, AD7193_CH_AIN7P_AIN8M, 24, 32, 0), + AD_SD_TEMP_CHANNEL(4, AD7193_CH_TEMP, 24, 32, 0), + AD_SD_SHORTED_CHANNEL(5, 2, AD7193_CH_AIN2P_AIN2M, 24, 32, 0), + AD_SD_CHANNEL(6, 1, AD7193_CH_AIN1, 24, 32, 0), + AD_SD_CHANNEL(7, 2, AD7193_CH_AIN2, 24, 32, 0), + AD_SD_CHANNEL(8, 3, AD7193_CH_AIN3, 24, 32, 0), + AD_SD_CHANNEL(9, 4, AD7193_CH_AIN4, 24, 32, 0), + AD_SD_CHANNEL(10, 5, AD7193_CH_AIN5, 24, 32, 0), + AD_SD_CHANNEL(11, 6, AD7193_CH_AIN6, 24, 32, 0), + AD_SD_CHANNEL(12, 7, AD7193_CH_AIN7, 24, 32, 0), + AD_SD_CHANNEL(13, 8, AD7193_CH_AIN8, 24, 32, 0), + IIO_CHAN_SOFT_TIMESTAMP(14), +}; + static int ad7192_probe(struct spi_device *spi) { const struct ad7192_platform_data *pdata = dev_get_platdata(&spi->dev); @@ -651,8 +686,18 @@ static int ad7192_probe(struct spi_device *spi) indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = ad7192_channels; - indio_dev->num_channels = ARRAY_SIZE(ad7192_channels); + + switch (st->devid) { + case ID_AD7193: + indio_dev->channels = ad7193_channels; + indio_dev->num_channels = ARRAY_SIZE(ad7193_channels); + break; + default: + indio_dev->channels = ad7192_channels; + indio_dev->num_channels = ARRAY_SIZE(ad7192_channels); + break; + } + if (st->devid == ID_AD7195) indio_dev->info = &ad7195_info; else @@ -699,6 +744,7 @@ static int ad7192_remove(struct spi_device *spi) static const struct spi_device_id ad7192_id[] = { {"ad7190", ID_AD7190}, {"ad7192", ID_AD7192}, + {"ad7193", ID_AD7193}, {"ad7195", ID_AD7195}, {} }; @@ -715,5 +761,5 @@ static struct spi_driver ad7192_driver = { module_spi_driver(ad7192_driver); MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("Analog Devices AD7190, AD7192, AD7195 ADC"); +MODULE_DESCRIPTION("Analog Devices AD7190, AD7192, AD7193, AD7195 ADC"); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 8b477ea56383dc8b838f1f8b506e4571c14ceb30 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 Jan 2016 02:45:08 +0000 Subject: thermal: rcar: enable to use thermal-zone on DT This patch enables to use thermal-zone on DT if it was calles as "renesas,rcar-thermal-gen2". Previous style (= non thermal-zone) is still supported by "renesas,rcar-thermal" to keep compatibility for "git bisect". Signed-off-by: Kuninori Morimoto Signed-off-by: Eduardo Valentin --- .../devicetree/bindings/thermal/rcar-thermal.txt | 37 +++++++++++++++++- drivers/thermal/rcar_thermal.c | 45 +++++++++++++++++++--- 2 files changed, 75 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/thermal/rcar-thermal.txt b/Documentation/devicetree/bindings/thermal/rcar-thermal.txt index 332e625f6ed0..e5ee3f159893 100644 --- a/Documentation/devicetree/bindings/thermal/rcar-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/rcar-thermal.txt @@ -1,8 +1,9 @@ * Renesas R-Car Thermal Required properties: -- compatible : "renesas,thermal-", "renesas,rcar-thermal" - as fallback. +- compatible : "renesas,thermal-", + "renesas,rcar-gen2-thermal" (with thermal-zone) or + "renesas,rcar-thermal" (without thermal-zone) as fallback. Examples with soctypes are: - "renesas,thermal-r8a73a4" (R-Mobile APE6) - "renesas,thermal-r8a7779" (R-Car H1) @@ -36,3 +37,35 @@ thermal@e61f0000 { 0xe61f0300 0x38>; interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>; }; + +Example (with thermal-zone): + +thermal-zones { + cpu_thermal: cpu-thermal { + polling-delay-passive = <1000>; + polling-delay = <5000>; + + thermal-sensors = <&thermal>; + + trips { + cpu-crit { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + cooling-maps { + }; + }; +}; + +thermal: thermal@e61f0000 { + compatible = "renesas,thermal-r8a7790", + "renesas,rcar-gen2-thermal", + "renesas,rcar-thermal"; + reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>; + interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp5_clks R8A7790_CLK_THERMAL>; + power-domains = <&cpg_clocks>; + #thermal-sensor-cells = <0>; +}; diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 44b9c485157d..0e735acea33a 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -75,8 +76,10 @@ struct rcar_thermal_priv { #define rcar_has_irq_support(priv) ((priv)->common->base) #define rcar_id_to_shift(priv) ((priv)->id * 8) +#define USE_OF_THERMAL 1 static const struct of_device_id rcar_thermal_dt_ids[] = { { .compatible = "renesas,rcar-thermal", }, + { .compatible = "renesas,rcar-gen2-thermal", .data = (void *)USE_OF_THERMAL }, {}, }; MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids); @@ -200,9 +203,9 @@ err_out_unlock: return ret; } -static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp) +static int rcar_thermal_get_current_temp(struct rcar_thermal_priv *priv, + int *temp) { - struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone); int tmp; int ret; @@ -226,6 +229,20 @@ static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp) return 0; } +static int rcar_thermal_of_get_temp(void *data, int *temp) +{ + struct rcar_thermal_priv *priv = data; + + return rcar_thermal_get_current_temp(priv, temp); +} + +static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp) +{ + struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone); + + return rcar_thermal_get_current_temp(priv, temp); +} + static int rcar_thermal_get_trip_type(struct thermal_zone_device *zone, int trip, enum thermal_trip_type *type) { @@ -282,6 +299,10 @@ static int rcar_thermal_notify(struct thermal_zone_device *zone, return 0; } +static const struct thermal_zone_of_device_ops rcar_thermal_zone_of_ops = { + .get_temp = rcar_thermal_of_get_temp, +}; + static struct thermal_zone_device_ops rcar_thermal_zone_ops = { .get_temp = rcar_thermal_get_temp, .get_trip_type = rcar_thermal_get_trip_type, @@ -318,14 +339,20 @@ static void rcar_thermal_work(struct work_struct *work) priv = container_of(work, struct rcar_thermal_priv, work.work); - rcar_thermal_get_temp(priv->zone, &cctemp); + ret = rcar_thermal_get_current_temp(priv, &cctemp); + if (ret < 0) + return; + ret = rcar_thermal_update_temp(priv); if (ret < 0) return; rcar_thermal_irq_enable(priv); - rcar_thermal_get_temp(priv->zone, &nctemp); + ret = rcar_thermal_get_current_temp(priv, &nctemp); + if (ret < 0) + return; + if (nctemp != cctemp) thermal_zone_device_update(priv->zone); } @@ -403,6 +430,8 @@ static int rcar_thermal_probe(struct platform_device *pdev) struct rcar_thermal_priv *priv; struct device *dev = &pdev->dev; struct resource *res, *irq; + const struct of_device_id *of_id = of_match_device(rcar_thermal_dt_ids, dev); + unsigned long of_data = (unsigned long)of_id->data; int mres = 0; int i; int ret = -ENODEV; @@ -463,7 +492,13 @@ static int rcar_thermal_probe(struct platform_device *pdev) if (ret < 0) goto error_unregister; - priv->zone = thermal_zone_device_register("rcar_thermal", + if (of_data == USE_OF_THERMAL) + priv->zone = thermal_zone_of_sensor_register( + dev, i, priv, + &rcar_thermal_zone_of_ops); + else + priv->zone = thermal_zone_device_register( + "rcar_thermal", 1, 0, priv, &rcar_thermal_zone_ops, NULL, 0, idle); -- cgit v1.2.3 From c099225f0a248c395509606932e3ca2cf6c65932 Mon Sep 17 00:00:00 2001 From: Cristina Moraru Date: Mon, 8 Feb 2016 00:21:48 +0200 Subject: iio: hmc5843: Swap suspend and resume implementations Swap implementations of hmc5843_common_suspend and hmc5843_common_resume functions for they have been inversed. Device should go on SLEEP mode on suspend and on CONTINUOUS mode on resume. Signed-off-by: Cristina Moraru Signed-off-by: Jonathan Cameron --- drivers/staging/iio/magnetometer/hmc5843_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/magnetometer/hmc5843_core.c b/drivers/staging/iio/magnetometer/hmc5843_core.c index 394bc141a1b0..94897993793e 100644 --- a/drivers/staging/iio/magnetometer/hmc5843_core.c +++ b/drivers/staging/iio/magnetometer/hmc5843_core.c @@ -565,14 +565,14 @@ static const unsigned long hmc5843_scan_masks[] = {0x7, 0}; int hmc5843_common_suspend(struct device *dev) { return hmc5843_set_mode(iio_priv(dev_get_drvdata(dev)), - HMC5843_MODE_CONVERSION_CONTINUOUS); + HMC5843_MODE_SLEEP); } EXPORT_SYMBOL(hmc5843_common_suspend); int hmc5843_common_resume(struct device *dev) { return hmc5843_set_mode(iio_priv(dev_get_drvdata(dev)), - HMC5843_MODE_SLEEP); + HMC5843_MODE_CONVERSION_CONTINUOUS); } EXPORT_SYMBOL(hmc5843_common_resume); -- cgit v1.2.3 From d612c64d1f4d6b2464993dfeafd9ec319f774188 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 17:44:10 +0100 Subject: thermal: spear: use __maybe_unused for PM functions The spear thermal driver hides its suspend/resume function conditionally based on CONFIG_PM, but references them based on CONFIG_PM_SLEEP, so we get a warning if the former is set but the latter is not: thermal/spear_thermal.c:58:12: warning: 'spear_thermal_suspend' defined but not used [-Wunused-function] thermal/spear_thermal.c:75:12: warning: 'spear_thermal_resume' defined but not used [-Wunused-function] This removes the #ifdef and instead uses a __maybe_uninitialized annotation to avoid the warning and improve compile-time coverage. Signed-off-by: Arnd Bergmann Signed-off-by: Eduardo Valentin --- drivers/thermal/spear_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c index 534dd9136662..81b35aace9de 100644 --- a/drivers/thermal/spear_thermal.c +++ b/drivers/thermal/spear_thermal.c @@ -54,8 +54,7 @@ static struct thermal_zone_device_ops ops = { .get_temp = thermal_get_temp, }; -#ifdef CONFIG_PM -static int spear_thermal_suspend(struct device *dev) +static int __maybe_unused spear_thermal_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev); @@ -72,7 +71,7 @@ static int spear_thermal_suspend(struct device *dev) return 0; } -static int spear_thermal_resume(struct device *dev) +static int __maybe_unused spear_thermal_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev); @@ -94,7 +93,6 @@ static int spear_thermal_resume(struct device *dev) return 0; } -#endif static SIMPLE_DEV_PM_OPS(spear_thermal_pm_ops, spear_thermal_suspend, spear_thermal_resume); -- cgit v1.2.3 From 4d2f1794c07aae55b8f25f4d8aebcafc0d3e501d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 17:44:11 +0100 Subject: thermal: allow spear-thermal driver to be a module When the thermal subsystem is a loadable module, the spear driver fails to build: drivers/thermal/built-in.o: In function `spear_thermal_exit': spear_thermal.c:(.text+0xf8): undefined reference to `thermal_zone_device_unregister' drivers/thermal/built-in.o: In function `spear_thermal_probe': spear_thermal.c:(.text+0x230): undefined reference to `thermal_zone_device_register' This changes the symbol to a tristate, so Kconfig can track the dependency correctly. Signed-off-by: Arnd Bergmann Signed-off-by: Eduardo Valentin --- drivers/thermal/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 8cc4ac64a91c..0852fd028dc9 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -195,7 +195,7 @@ config IMX_THERMAL passive trip is crossed. config SPEAR_THERMAL - bool "SPEAr thermal sensor driver" + tristate "SPEAr thermal sensor driver" depends on PLAT_SPEAR || COMPILE_TEST depends on OF help -- cgit v1.2.3 From 4630adb8ec5a89dca07bf39c341256803c4f1a46 Mon Sep 17 00:00:00 2001 From: Cristina Moraru Date: Mon, 8 Feb 2016 00:21:50 +0200 Subject: iio: hmc5843: Fix comment style warnings Fix comment style warnings in order to comply with Coding Style standard provided by Documentation/CodingStyle. This patch solves following issue found with checkpatch: WARNING: Block comments use a trailing */ on a separate line Signed-off-by: Cristina Moraru Signed-off-by: Jonathan Cameron --- drivers/staging/iio/magnetometer/hmc5843.h | 5 ++--- drivers/staging/iio/magnetometer/hmc5843_i2c.c | 3 +-- drivers/staging/iio/magnetometer/hmc5843_spi.c | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/magnetometer/hmc5843.h b/drivers/staging/iio/magnetometer/hmc5843.h index 06f35d3828e4..76a5d7484d8d 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.h +++ b/drivers/staging/iio/magnetometer/hmc5843.h @@ -7,8 +7,7 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * - * */ + */ #ifndef HMC5843_CORE_H #define HMC5843_CORE_H @@ -38,7 +37,7 @@ enum hmc5843_ids { * @regmap: hardware access register maps * @variant: describe chip variants * @buffer: 3x 16-bit channels + padding + 64-bit timestamp - **/ + */ struct hmc5843_data { struct device *dev; struct mutex lock; diff --git a/drivers/staging/iio/magnetometer/hmc5843_i2c.c b/drivers/staging/iio/magnetometer/hmc5843_i2c.c index 3e06ceb32059..3de7f4426ac4 100644 --- a/drivers/staging/iio/magnetometer/hmc5843_i2c.c +++ b/drivers/staging/iio/magnetometer/hmc5843_i2c.c @@ -7,8 +7,7 @@ * 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 #include diff --git a/drivers/staging/iio/magnetometer/hmc5843_spi.c b/drivers/staging/iio/magnetometer/hmc5843_spi.c index 8be198058ea2..535f03a70d63 100644 --- a/drivers/staging/iio/magnetometer/hmc5843_spi.c +++ b/drivers/staging/iio/magnetometer/hmc5843_spi.c @@ -6,8 +6,7 @@ * 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 #include -- cgit v1.2.3 From 26716ce124fce88f288f07738ef685d5dfe5c13f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 17:44:12 +0100 Subject: thermal: allow u8500-thermal driver to be a module When the thermal subsystem is a loadable module, the u8500 driver fails to build: drivers/thermal/built-in.o: In function `db8500_thermal_probe': db8500_thermal.c:(.text+0x96c): undefined reference to `thermal_zone_device_register' drivers/thermal/built-in.o: In function `db8500_thermal_work': db8500_thermal.c:(.text+0xab4): undefined reference to `thermal_zone_device_update' This changes the symbol to a tristate, so Kconfig can track the dependency correctly. Signed-off-by: Arnd Bergmann Signed-off-by: Eduardo Valentin --- drivers/mfd/db8500-prcmu.c | 3 +++ drivers/thermal/Kconfig | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index e6e4bacb09ee..12099b09a9a7 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -2048,6 +2048,7 @@ int db8500_prcmu_config_hotmon(u8 low, u8 high) return 0; } +EXPORT_SYMBOL_GPL(db8500_prcmu_config_hotmon); static int config_hot_period(u16 val) { @@ -2074,11 +2075,13 @@ int db8500_prcmu_start_temp_sense(u16 cycles32k) return config_hot_period(cycles32k); } +EXPORT_SYMBOL_GPL(db8500_prcmu_start_temp_sense); int db8500_prcmu_stop_temp_sense(void) { return config_hot_period(0xFFFF); } +EXPORT_SYMBOL_GPL(db8500_prcmu_stop_temp_sense); static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3) { diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 0852fd028dc9..7c92c09be213 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -237,8 +237,8 @@ config DOVE_THERMAL framework. config DB8500_THERMAL - bool "DB8500 thermal management" - depends on ARCH_U8500 + tristate "DB8500 thermal management" + depends on MFD_DB8500_PRCMU default y help Adds DB8500 thermal management implementation according to the thermal -- cgit v1.2.3 From efc945fb729c9b858bb8ab3cf01a3079f32dabc5 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 7 Feb 2016 18:14:16 +0900 Subject: iio: adc: add support for ADC0831/ADC0832/ADC0834/ADC0838 chips This adds ADC0831/ADC0832/ADC0834/ADC0838 8-bit ADC driver. I have tested with ADC0831 and ADC0832. The remaining ADC0834 and ADC0838 are very similar to ADC0832. Signed-off-by: Akinobu Mita Cc: Jonathan Cameron Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/adc/ti-adc0832.txt | 19 ++ drivers/iio/adc/Kconfig | 10 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/ti-adc0832.c | 288 +++++++++++++++++++++ 4 files changed, 318 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/ti-adc0832.txt create mode 100644 drivers/iio/adc/ti-adc0832.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/iio/adc/ti-adc0832.txt b/Documentation/devicetree/bindings/iio/adc/ti-adc0832.txt new file mode 100644 index 000000000000..d91130587d01 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti-adc0832.txt @@ -0,0 +1,19 @@ +* Texas Instruments' ADC0831/ADC0832/ADC0832/ADC0838 + +Required properties: + - compatible: Should be one of + * "ti,adc0831" + * "ti,adc0832" + * "ti,adc0834" + * "ti,adc0838" + - reg: spi chip select number for the device + - vref-supply: The regulator supply for ADC reference voltage + - spi-max-frequency: Max SPI frequency to use (< 400000) + +Example: +adc@0 { + compatible = "ti,adc0832"; + reg = <0>; + vref-supply = <&vdd_supply>; + spi-max-frequency = <200000>; +}; diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 60673b40f2c3..fd8b53e37bf0 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -360,6 +360,16 @@ config TI_ADC081C This driver can also be built as a module. If so, the module will be called ti-adc081c. +config TI_ADC0832 + tristate "Texas Instruments ADC0831/ADC0832/ADC0834/ADC0838" + depends on SPI + help + If you say yes here you get support for Texas Instruments ADC0831, + ADC0832, ADC0834, ADC0838 ADC chips. + + This driver can also be built as a module. If so, the module will be + called ti-adc0832. + config TI_ADC128S052 tristate "Texas Instruments ADC128S052/ADC122S021/ADC124S021" depends on SPI diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index fb57e12dbde2..a3820fa54004 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o +obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o diff --git a/drivers/iio/adc/ti-adc0832.c b/drivers/iio/adc/ti-adc0832.c new file mode 100644 index 000000000000..0afeac0c9bad --- /dev/null +++ b/drivers/iio/adc/ti-adc0832.c @@ -0,0 +1,288 @@ +/* + * ADC0831/ADC0832/ADC0834/ADC0838 8-bit ADC driver + * + * Copyright (c) 2016 Akinobu Mita + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * Datasheet: http://www.ti.com/lit/ds/symlink/adc0832-n.pdf + */ + +#include +#include +#include +#include + +enum { + adc0831, + adc0832, + adc0834, + adc0838, +}; + +struct adc0832 { + struct spi_device *spi; + struct regulator *reg; + struct mutex lock; + u8 mux_bits; + + u8 tx_buf[2] ____cacheline_aligned; + u8 rx_buf[2]; +}; + +#define ADC0832_VOLTAGE_CHANNEL(chan) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = chan, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ + } + +#define ADC0832_VOLTAGE_CHANNEL_DIFF(chan1, chan2) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (chan1), \ + .channel2 = (chan2), \ + .differential = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ + } + +static const struct iio_chan_spec adc0831_channels[] = { + ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1), +}; + +static const struct iio_chan_spec adc0832_channels[] = { + ADC0832_VOLTAGE_CHANNEL(0), + ADC0832_VOLTAGE_CHANNEL(1), + ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1), + ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0), +}; + +static const struct iio_chan_spec adc0834_channels[] = { + ADC0832_VOLTAGE_CHANNEL(0), + ADC0832_VOLTAGE_CHANNEL(1), + ADC0832_VOLTAGE_CHANNEL(2), + ADC0832_VOLTAGE_CHANNEL(3), + ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1), + ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0), + ADC0832_VOLTAGE_CHANNEL_DIFF(2, 3), + ADC0832_VOLTAGE_CHANNEL_DIFF(3, 2), +}; + +static const struct iio_chan_spec adc0838_channels[] = { + ADC0832_VOLTAGE_CHANNEL(0), + ADC0832_VOLTAGE_CHANNEL(1), + ADC0832_VOLTAGE_CHANNEL(2), + ADC0832_VOLTAGE_CHANNEL(3), + ADC0832_VOLTAGE_CHANNEL(4), + ADC0832_VOLTAGE_CHANNEL(5), + ADC0832_VOLTAGE_CHANNEL(6), + ADC0832_VOLTAGE_CHANNEL(7), + ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1), + ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0), + ADC0832_VOLTAGE_CHANNEL_DIFF(2, 3), + ADC0832_VOLTAGE_CHANNEL_DIFF(3, 2), + ADC0832_VOLTAGE_CHANNEL_DIFF(4, 5), + ADC0832_VOLTAGE_CHANNEL_DIFF(5, 4), + ADC0832_VOLTAGE_CHANNEL_DIFF(6, 7), + ADC0832_VOLTAGE_CHANNEL_DIFF(7, 6), +}; + +static int adc0831_adc_conversion(struct adc0832 *adc) +{ + struct spi_device *spi = adc->spi; + int ret; + + ret = spi_read(spi, &adc->rx_buf, 2); + if (ret) + return ret; + + /* + * Skip TRI-STATE and a leading zero + */ + return (adc->rx_buf[0] << 2 & 0xff) | (adc->rx_buf[1] >> 6); +} + +static int adc0832_adc_conversion(struct adc0832 *adc, int channel, + bool differential) +{ + struct spi_device *spi = adc->spi; + struct spi_transfer xfer = { + .tx_buf = adc->tx_buf, + .rx_buf = adc->rx_buf, + .len = 2, + }; + int ret; + + if (!adc->mux_bits) + return adc0831_adc_conversion(adc); + + /* start bit */ + adc->tx_buf[0] = 1 << (adc->mux_bits + 1); + /* single-ended or differential */ + adc->tx_buf[0] |= differential ? 0 : (1 << adc->mux_bits); + /* odd / sign */ + adc->tx_buf[0] |= (channel % 2) << (adc->mux_bits - 1); + /* select */ + if (adc->mux_bits > 1) + adc->tx_buf[0] |= channel / 2; + + /* align Data output BIT7 (MSB) to 8-bit boundary */ + adc->tx_buf[0] <<= 1; + + ret = spi_sync_transfer(spi, &xfer, 1); + if (ret) + return ret; + + return adc->rx_buf[1]; +} + +static int adc0832_read_raw(struct iio_dev *iio, + struct iio_chan_spec const *channel, int *value, + int *shift, long mask) +{ + struct adc0832 *adc = iio_priv(iio); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&adc->lock); + *value = adc0832_adc_conversion(adc, channel->channel, + channel->differential); + mutex_unlock(&adc->lock); + if (*value < 0) + return *value; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *value = regulator_get_voltage(adc->reg); + if (*value < 0) + return *value; + + /* convert regulator output voltage to mV */ + *value /= 1000; + *shift = 8; + + return IIO_VAL_FRACTIONAL_LOG2; + } + + return -EINVAL; +} + +static const struct iio_info adc0832_info = { + .read_raw = adc0832_read_raw, + .driver_module = THIS_MODULE, +}; + +static int adc0832_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct adc0832 *adc; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc)); + if (!indio_dev) + return -ENOMEM; + + adc = iio_priv(indio_dev); + adc->spi = spi; + mutex_init(&adc->lock); + + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->dev.parent = &spi->dev; + indio_dev->info = &adc0832_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + switch (spi_get_device_id(spi)->driver_data) { + case adc0831: + adc->mux_bits = 0; + indio_dev->channels = adc0831_channels; + indio_dev->num_channels = ARRAY_SIZE(adc0831_channels); + break; + case adc0832: + adc->mux_bits = 1; + indio_dev->channels = adc0832_channels; + indio_dev->num_channels = ARRAY_SIZE(adc0832_channels); + break; + case adc0834: + adc->mux_bits = 2; + indio_dev->channels = adc0834_channels; + indio_dev->num_channels = ARRAY_SIZE(adc0834_channels); + break; + case adc0838: + adc->mux_bits = 3; + indio_dev->channels = adc0838_channels; + indio_dev->num_channels = ARRAY_SIZE(adc0838_channels); + break; + default: + return -EINVAL; + } + + adc->reg = devm_regulator_get(&spi->dev, "vref"); + if (IS_ERR(adc->reg)) + return PTR_ERR(adc->reg); + + ret = regulator_enable(adc->reg); + if (ret) + return ret; + + spi_set_drvdata(spi, indio_dev); + + ret = iio_device_register(indio_dev); + if (ret) + regulator_disable(adc->reg); + + return ret; +} + +static int adc0832_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct adc0832 *adc = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + regulator_disable(adc->reg); + + return 0; +} + +#ifdef CONFIG_OF + +static const struct of_device_id adc0832_dt_ids[] = { + { .compatible = "ti,adc0831", }, + { .compatible = "ti,adc0832", }, + { .compatible = "ti,adc0834", }, + { .compatible = "ti,adc0838", }, + {} +}; +MODULE_DEVICE_TABLE(of, adc0832_dt_ids); + +#endif + +static const struct spi_device_id adc0832_id[] = { + { "adc0831", adc0831 }, + { "adc0832", adc0832 }, + { "adc0834", adc0834 }, + { "adc0838", adc0838 }, + {} +}; +MODULE_DEVICE_TABLE(spi, adc0832_id); + +static struct spi_driver adc0832_driver = { + .driver = { + .name = "adc0832", + .of_match_table = of_match_ptr(adc0832_dt_ids), + }, + .probe = adc0832_probe, + .remove = adc0832_remove, + .id_table = adc0832_id, +}; +module_spi_driver(adc0832_driver); + +MODULE_AUTHOR("Akinobu Mita "); +MODULE_DESCRIPTION("ADC0831/ADC0832/ADC0834/ADC0838 driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 1261d013daead425ee03c977a5b8dbe8016e25a6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Feb 2016 10:33:40 -0800 Subject: Input: Allow compile test of Goodix and Colibri VF50 if !GPIOLIB The GPIO subsystem provides dummy GPIO consumer functions if GPIOLIB is not enabled. Hence drivers that depend on GPIOLIB, but use GPIO consumer functionality only, can still be compiled if GPIOLIB is not enabled. If COMPILE_TEST is enabled, relax the dependency on GPIOLIB for the recently introduced or relaxed symbols TOUCHSCREEN_GOODIX and TOUCHSCREEN_COLIBRI_VF50. Signed-off-by: Geert Uytterhoeven Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 53a97b379c9f..f4e53b4a6062 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -334,7 +334,7 @@ config TOUCHSCREEN_FUJITSU config TOUCHSCREEN_GOODIX tristate "Goodix I2C touchscreen" depends on I2C - depends on GPIOLIB + depends on GPIOLIB || COMPILE_TEST help Say Y here if you have the Goodix touchscreen (such as one installed in Onda v975w tablets) connected to your @@ -1112,7 +1112,8 @@ config TOUCHSCREEN_ZFORCE config TOUCHSCREEN_COLIBRI_VF50 tristate "Toradex Colibri on board touchscreen driver" - depends on GPIOLIB && IIO && VF610_ADC + depends on IIO && VF610_ADC + depends on GPIOLIB || COMPILE_TEST help Say Y here if you have a Colibri VF50 and plan to use the on-board provided 4-wire touchscreen driver. -- cgit v1.2.3 From dc262dfaaeda7617ae0b15b5ce1252a6cd102b19 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 9 Feb 2016 09:32:42 -0800 Subject: Input: edt-ft5x06 - fix setting gain, offset, and threshold via device tree A recent patch broke parsing the gain, offset, and threshold parameters from device tree. Instead of setting the cached values and writing them to the correct registers during probe, it would write the values from DT into the register address variables and never write them to the chip during normal operation. Fixes: 2e23b7a96372 ("Input: edt-ft5x06 - use generic properties API") Signed-off-by: Philipp Zabel Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/edt-ft5x06.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 0b0f8c17f3f7..23fbe382da8b 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -822,16 +822,22 @@ static void edt_ft5x06_ts_get_defaults(struct device *dev, int error; error = device_property_read_u32(dev, "threshold", &val); - if (!error) - reg_addr->reg_threshold = val; + if (!error) { + edt_ft5x06_register_write(tsdata, reg_addr->reg_threshold, val); + tsdata->threshold = val; + } error = device_property_read_u32(dev, "gain", &val); - if (!error) - reg_addr->reg_gain = val; + if (!error) { + edt_ft5x06_register_write(tsdata, reg_addr->reg_gain, val); + tsdata->gain = val; + } error = device_property_read_u32(dev, "offset", &val); - if (!error) - reg_addr->reg_offset = val; + if (!error) { + edt_ft5x06_register_write(tsdata, reg_addr->reg_offset, val); + tsdata->offset = val; + } } static void -- cgit v1.2.3 From 7008dafb02c858411d70b82c3aeb40f93b93c67a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 9 Feb 2016 09:35:33 -0800 Subject: Input: adp5589 - fix row 5 handling for adp5589 The adp5589 has row 5, don't skip it when creating the GPIO mapping. Otherwise the pin gets reserved as used and it is not possible to use it as a GPIO. Signed-off-by: Lars-Peter Clausen Acked-by: Michael Hennerich Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/adp5589-keys.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index 4d446d5085aa..c01a1d648f9f 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -235,7 +235,7 @@ struct adp5589_kpad { unsigned short gpimapsize; unsigned extend_cfg; bool is_adp5585; - bool adp5585_support_row5; + bool support_row5; #ifdef CONFIG_GPIOLIB unsigned char gpiomap[ADP5589_MAXGPIO]; bool export_gpio; @@ -485,7 +485,7 @@ static int adp5589_build_gpiomap(struct adp5589_kpad *kpad, if (kpad->extend_cfg & C4_EXTEND_CFG) pin_used[kpad->var->c4_extend_cfg] = true; - if (!kpad->adp5585_support_row5) + if (!kpad->support_row5) pin_used[5] = true; for (i = 0; i < kpad->var->maxgpio; i++) @@ -884,12 +884,13 @@ static int adp5589_probe(struct i2c_client *client, switch (id->driver_data) { case ADP5585_02: - kpad->adp5585_support_row5 = true; + kpad->support_row5 = true; case ADP5585_01: kpad->is_adp5585 = true; kpad->var = &const_adp5585; break; case ADP5589: + kpad->support_row5 = true; kpad->var = &const_adp5589; break; } -- cgit v1.2.3 From ff84dabe3c6ebba517086e1161145d70ff129665 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Feb 2016 10:32:53 -0800 Subject: Input: colibri-vf50-ts - add missing #include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/input/touchscreen/colibri-vf50-ts.c: In function ‘vf50_ts_probe’: drivers/input/touchscreen/colibri-vf50-ts.c:302: error: implicit declaration of function ‘of_property_read_u32’ Signed-off-by: Geert Uytterhoeven Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/colibri-vf50-ts.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/input/touchscreen/colibri-vf50-ts.c b/drivers/input/touchscreen/colibri-vf50-ts.c index 5d4903a402cc..69828d015d45 100644 --- a/drivers/input/touchscreen/colibri-vf50-ts.c +++ b/drivers/input/touchscreen/colibri-vf50-ts.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 9f8ea969d5cfdd4353d2adb004e8e2286b984369 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 9 Feb 2016 10:30:33 +0530 Subject: PM / OPP: get/put regulators from OPP core This allows the OPP core to request/free the regulator resource, attached to a device OPP. The regulator device is fetched using the name provided by the driver, while calling: dev_pm_opp_set_regulator(). This will work for both OPP-v1 and v2 bindings. This is a preliminary step for moving the OPP switching logic into the OPP core. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp/core.c | 111 ++++++++++++++++++++++++++++++++++++++++++ drivers/base/power/opp/opp.h | 4 ++ include/linux/pm_opp.h | 9 ++++ 3 files changed, 124 insertions(+) (limited to 'drivers') diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index cf351d3dab1c..1e22b71abf1e 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "opp.h" @@ -565,6 +566,9 @@ static void _remove_device_opp(struct device_opp *dev_opp) if (dev_opp->prop_name) return; + if (!IS_ERR_OR_NULL(dev_opp->regulator)) + return; + list_dev = list_first_entry(&dev_opp->dev_list, struct device_list_opp, node); @@ -1085,6 +1089,113 @@ unlock: } EXPORT_SYMBOL_GPL(dev_pm_opp_put_prop_name); +/** + * dev_pm_opp_set_regulator() - Set regulator name for the device + * @dev: Device for which regulator name is being set. + * @name: Name of the regulator. + * + * In order to support OPP switching, OPP layer needs to know the name of the + * device's regulator, as the core would be required to switch voltages as well. + * + * This must be called before any OPPs are initialized for the device. + * + * Locking: The internal device_opp and opp structures are RCU protected. + * Hence this function internally uses RCU updater strategy with mutex locks + * to keep the integrity of the internal data structures. Callers should ensure + * that this function is *NOT* called under RCU protection or in contexts where + * mutex cannot be locked. + */ +int dev_pm_opp_set_regulator(struct device *dev, const char *name) +{ + struct device_opp *dev_opp; + struct regulator *reg; + int ret; + + mutex_lock(&dev_opp_list_lock); + + dev_opp = _add_device_opp(dev); + if (!dev_opp) { + ret = -ENOMEM; + goto unlock; + } + + /* This should be called before OPPs are initialized */ + if (WARN_ON(!list_empty(&dev_opp->opp_list))) { + ret = -EBUSY; + goto err; + } + + /* Already have a regulator set */ + if (WARN_ON(!IS_ERR_OR_NULL(dev_opp->regulator))) { + ret = -EBUSY; + goto err; + } + /* Allocate the regulator */ + reg = regulator_get_optional(dev, name); + if (IS_ERR(reg)) { + ret = PTR_ERR(reg); + if (ret != -EPROBE_DEFER) + dev_err(dev, "%s: no regulator (%s) found: %d\n", + __func__, name, ret); + goto err; + } + + dev_opp->regulator = reg; + + mutex_unlock(&dev_opp_list_lock); + return 0; + +err: + _remove_device_opp(dev_opp); +unlock: + mutex_unlock(&dev_opp_list_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(dev_pm_opp_set_regulator); + +/** + * dev_pm_opp_put_regulator() - Releases resources blocked for regulator + * @dev: Device for which regulator was set. + * + * Locking: The internal device_opp and opp structures are RCU protected. + * Hence this function internally uses RCU updater strategy with mutex locks + * to keep the integrity of the internal data structures. Callers should ensure + * that this function is *NOT* called under RCU protection or in contexts where + * mutex cannot be locked. + */ +void dev_pm_opp_put_regulator(struct device *dev) +{ + struct device_opp *dev_opp; + + mutex_lock(&dev_opp_list_lock); + + /* Check for existing list for 'dev' first */ + dev_opp = _find_device_opp(dev); + if (IS_ERR(dev_opp)) { + dev_err(dev, "Failed to find dev_opp: %ld\n", PTR_ERR(dev_opp)); + goto unlock; + } + + if (IS_ERR_OR_NULL(dev_opp->regulator)) { + dev_err(dev, "%s: Doesn't have regulator set\n", __func__); + goto unlock; + } + + /* Make sure there are no concurrent readers while updating dev_opp */ + WARN_ON(!list_empty(&dev_opp->opp_list)); + + regulator_put(dev_opp->regulator); + dev_opp->regulator = ERR_PTR(-EINVAL); + + /* Try freeing device_opp if this was the last blocking resource */ + _remove_device_opp(dev_opp); + +unlock: + mutex_unlock(&dev_opp_list_lock); +} +EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulator); + static bool _opp_is_supported(struct device *dev, struct device_opp *dev_opp, struct device_node *np) { diff --git a/drivers/base/power/opp/opp.h b/drivers/base/power/opp/opp.h index 690638ef36ee..416293b7da23 100644 --- a/drivers/base/power/opp/opp.h +++ b/drivers/base/power/opp/opp.h @@ -22,6 +22,8 @@ #include #include +struct regulator; + /* Lock to allow exclusive modification to the device and opp lists */ extern struct mutex dev_opp_list_lock; @@ -132,6 +134,7 @@ struct device_list_opp { * @supported_hw: Array of version number to support. * @supported_hw_count: Number of elements in supported_hw array. * @prop_name: A name to postfix to many DT properties, while parsing them. + * @regulator: Supply regulator * @dentry: debugfs dentry pointer of the real device directory (not links). * @dentry_name: Name of the real dentry. * @@ -159,6 +162,7 @@ struct device_opp { unsigned int *supported_hw; unsigned int supported_hw_count; const char *prop_name; + struct regulator *regulator; #ifdef CONFIG_DEBUG_FS struct dentry *dentry; diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index 95403d2ccaf5..c70a18ac9c8a 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -60,6 +60,8 @@ int dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions, void dev_pm_opp_put_supported_hw(struct device *dev); int dev_pm_opp_set_prop_name(struct device *dev, const char *name); void dev_pm_opp_put_prop_name(struct device *dev); +int dev_pm_opp_set_regulator(struct device *dev, const char *name); +void dev_pm_opp_put_regulator(struct device *dev); #else static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp) { @@ -151,6 +153,13 @@ static inline int dev_pm_opp_set_prop_name(struct device *dev, const char *name) static inline void dev_pm_opp_put_prop_name(struct device *dev) {} +static inline int dev_pm_opp_set_regulator(struct device *dev, const char *name) +{ + return -EINVAL; +} + +static inline void dev_pm_opp_put_regulator(struct device *dev) {} + #endif /* CONFIG_PM_OPP */ #if defined(CONFIG_PM_OPP) && defined(CONFIG_OF) -- cgit v1.2.3 From 7d34d56ef3349cd5f29cf7aab6650f3414fa81b9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 9 Feb 2016 10:30:34 +0530 Subject: PM / OPP: Disable OPPs that aren't supported by the regulator Disable any OPPs where the connected regulator isn't able to provide the specified voltage. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp/core.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index 1e22b71abf1e..71545becfca1 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -687,6 +687,22 @@ static struct dev_pm_opp *_allocate_opp(struct device *dev, return opp; } +static bool _opp_supported_by_regulators(struct dev_pm_opp *opp, + struct device_opp *dev_opp) +{ + struct regulator *reg = dev_opp->regulator; + + if (!IS_ERR(reg) && + !regulator_is_supported_voltage(reg, opp->u_volt_min, + opp->u_volt_max)) { + pr_warn("%s: OPP minuV: %lu maxuV: %lu, not supported by regulator\n", + __func__, opp->u_volt_min, opp->u_volt_max); + return false; + } + + return true; +} + static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct device_opp *dev_opp) { @@ -728,6 +744,12 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, dev_err(dev, "%s: Failed to register opp to debugfs (%d)\n", __func__, ret); + if (!_opp_supported_by_regulators(new_opp, dev_opp)) { + new_opp->available = false; + dev_warn(dev, "%s: OPP not supported by regulators (%lu)\n", + __func__, new_opp->rate); + } + return 0; } -- cgit v1.2.3 From 655c9df961751ce21466f6e97e8033932c27a675 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 9 Feb 2016 10:30:35 +0530 Subject: PM / OPP: Introduce dev_pm_opp_get_max_volt_latency() In few use cases (like: cpufreq), it is desired to get the maximum voltage latency for changing OPPs. Add support for that. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp/core.c | 59 +++++++++++++++++++++++++++++++++++++++++++ include/linux/pm_opp.h | 6 +++++ 2 files changed, 65 insertions(+) (limited to 'drivers') diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index 71545becfca1..ffe2406af882 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -230,6 +230,65 @@ unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev) } EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency); +/** + * dev_pm_opp_get_max_volt_latency() - Get max voltage latency in nanoseconds + * @dev: device for which we do this operation + * + * Return: This function returns the max voltage latency in nanoseconds. + * + * Locking: This function takes rcu_read_lock(). + */ +unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev) +{ + struct device_opp *dev_opp; + struct dev_pm_opp *opp; + struct regulator *reg; + unsigned long latency_ns = 0; + unsigned long min_uV = ~0, max_uV = 0; + int ret; + + rcu_read_lock(); + + dev_opp = _find_device_opp(dev); + if (IS_ERR(dev_opp)) { + rcu_read_unlock(); + return 0; + } + + reg = dev_opp->regulator; + if (IS_ERR_OR_NULL(reg)) { + /* Regulator may not be required for device */ + if (reg) + dev_err(dev, "%s: Invalid regulator (%ld)\n", __func__, + PTR_ERR(reg)); + rcu_read_unlock(); + return 0; + } + + list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) { + if (!opp->available) + continue; + + if (opp->u_volt_min < min_uV) + min_uV = opp->u_volt_min; + if (opp->u_volt_max > max_uV) + max_uV = opp->u_volt_max; + } + + rcu_read_unlock(); + + /* + * The caller needs to ensure that dev_opp (and hence the regulator) + * isn't freed, while we are executing this routine. + */ + ret = regulator_set_voltage_time(reg, min_uV, max_uV); + if (ret > 0) + latency_ns = ret * 1000; + + return latency_ns; +} +EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_volt_latency); + /** * dev_pm_opp_get_suspend_opp() - Get suspend opp * @dev: device for which we do this operation diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index c70a18ac9c8a..5daa43058ac1 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -34,6 +34,7 @@ bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp); int dev_pm_opp_get_opp_count(struct device *dev); unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev); +unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev); struct dev_pm_opp *dev_pm_opp_get_suspend_opp(struct device *dev); struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, @@ -88,6 +89,11 @@ static inline unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev) return 0; } +static inline unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev) +{ + return 0; +} + static inline struct dev_pm_opp *dev_pm_opp_get_suspend_opp(struct device *dev) { return NULL; -- cgit v1.2.3 From 2174344765f472895c076d703c9cdc58215e1393 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 9 Feb 2016 10:30:36 +0530 Subject: PM / OPP: Introduce dev_pm_opp_get_max_transition_latency() In few use cases (like: cpufreq), it is desired to get the maximum latency for changing OPPs. Add support for that. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp/core.c | 17 +++++++++++++++++ include/linux/pm_opp.h | 6 ++++++ 2 files changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index ffe2406af882..b0f5c72f0fc3 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -289,6 +289,23 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev) } EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_volt_latency); +/** + * dev_pm_opp_get_max_transition_latency() - Get max transition latency in + * nanoseconds + * @dev: device for which we do this operation + * + * Return: This function returns the max transition latency, in nanoseconds, to + * switch from one OPP to other. + * + * Locking: This function takes rcu_read_lock(). + */ +unsigned long dev_pm_opp_get_max_transition_latency(struct device *dev) +{ + return dev_pm_opp_get_max_volt_latency(dev) + + dev_pm_opp_get_max_clock_latency(dev); +} +EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_transition_latency); + /** * dev_pm_opp_get_suspend_opp() - Get suspend opp * @dev: device for which we do this operation diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index 5daa43058ac1..59da3d9e11ea 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -35,6 +35,7 @@ bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp); int dev_pm_opp_get_opp_count(struct device *dev); unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev); unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev); +unsigned long dev_pm_opp_get_max_transition_latency(struct device *dev); struct dev_pm_opp *dev_pm_opp_get_suspend_opp(struct device *dev); struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, @@ -94,6 +95,11 @@ static inline unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev) return 0; } +static inline unsigned long dev_pm_opp_get_max_transition_latency(struct device *dev) +{ + return 0; +} + static inline struct dev_pm_opp *dev_pm_opp_get_suspend_opp(struct device *dev) { return NULL; -- cgit v1.2.3 From 50f8cfbd5897ca182d43f4caf19937153f17a604 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 9 Feb 2016 10:30:37 +0530 Subject: PM / OPP: Parse clock-latency and voltage-tolerance for v1 bindings V2 bindings have better support for clock-latency and voltage-tolerance and doesn't need special care. To use callbacks, like dev_pm_opp_get_max_{transition|volt}_latency(), irrespective of the bindings, the core needs to know clock-latency/voltage-tolerance for the earlier bindings. This patch reads clock-latency/voltage-tolerance from the device node, irrespective of the bindings (to keep it simple) and use them only for V1 bindings. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp/core.c | 20 ++++++++++++++++++++ drivers/base/power/opp/opp.h | 6 ++++++ 2 files changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index b0f5c72f0fc3..4fafa733a1c7 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -582,6 +582,7 @@ static struct device_opp *_add_device_opp(struct device *dev) { struct device_opp *dev_opp; struct device_list_opp *list_dev; + struct device_node *np; /* Check for existing list for 'dev' first */ dev_opp = _find_device_opp(dev); @@ -604,6 +605,21 @@ static struct device_opp *_add_device_opp(struct device *dev) return NULL; } + /* + * Only required for backward compatibility with v1 bindings, but isn't + * harmful for other cases. And so we do it unconditionally. + */ + np = of_node_get(dev->of_node); + if (np) { + u32 val; + + if (!of_property_read_u32(np, "clock-latency", &val)) + dev_opp->clock_latency_ns_max = val; + of_property_read_u32(np, "voltage-tolerance", + &dev_opp->voltage_tolerance_v1); + of_node_put(np); + } + srcu_init_notifier_head(&dev_opp->srcu_head); INIT_LIST_HEAD(&dev_opp->opp_list); @@ -861,6 +877,7 @@ static int _opp_add_v1(struct device *dev, unsigned long freq, long u_volt, { struct device_opp *dev_opp; struct dev_pm_opp *new_opp; + unsigned long tol; int ret; /* Hold our list modification lock here */ @@ -874,7 +891,10 @@ static int _opp_add_v1(struct device *dev, unsigned long freq, long u_volt, /* populate the opp table */ new_opp->rate = freq; + tol = u_volt * dev_opp->voltage_tolerance_v1 / 100; new_opp->u_volt = u_volt; + new_opp->u_volt_min = u_volt - tol; + new_opp->u_volt_max = u_volt + tol; new_opp->available = true; new_opp->dynamic = dynamic; diff --git a/drivers/base/power/opp/opp.h b/drivers/base/power/opp/opp.h index 416293b7da23..fe44beb404ba 100644 --- a/drivers/base/power/opp/opp.h +++ b/drivers/base/power/opp/opp.h @@ -138,6 +138,8 @@ struct device_list_opp { * @dentry: debugfs dentry pointer of the real device directory (not links). * @dentry_name: Name of the real dentry. * + * @voltage_tolerance_v1: In percentage, for v1 bindings only. + * * This is an internal data structure maintaining the link to opps attached to * a device. This structure is not meant to be shared to users as it is * meant for book keeping and private to OPP library. @@ -156,6 +158,10 @@ struct device_opp { struct device_node *np; unsigned long clock_latency_ns_max; + + /* For backward compatibility with v1 bindings */ + unsigned int voltage_tolerance_v1; + bool shared_opp; struct dev_pm_opp *suspend_opp; -- cgit v1.2.3 From d54974c2513f487e9e70fbdc79c5da51c53e23da Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 9 Feb 2016 10:30:38 +0530 Subject: PM / OPP: Manage device clk OPP core has got almost everything now to manage device's OPP transitions, the only thing left is device's clk. Get that as well. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp/core.c | 15 +++++++++++++++ drivers/base/power/opp/opp.h | 3 +++ 2 files changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index 4fafa733a1c7..7d7749ce1ce4 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -13,6 +13,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -583,6 +584,7 @@ static struct device_opp *_add_device_opp(struct device *dev) struct device_opp *dev_opp; struct device_list_opp *list_dev; struct device_node *np; + int ret; /* Check for existing list for 'dev' first */ dev_opp = _find_device_opp(dev); @@ -620,6 +622,15 @@ static struct device_opp *_add_device_opp(struct device *dev) of_node_put(np); } + /* Find clk for the device */ + dev_opp->clk = clk_get(dev, NULL); + if (IS_ERR(dev_opp->clk)) { + ret = PTR_ERR(dev_opp->clk); + if (ret != -EPROBE_DEFER) + dev_dbg(dev, "%s: Couldn't find clock: %d\n", __func__, + ret); + } + srcu_init_notifier_head(&dev_opp->srcu_head); INIT_LIST_HEAD(&dev_opp->opp_list); @@ -661,6 +672,10 @@ static void _remove_device_opp(struct device_opp *dev_opp) if (!IS_ERR_OR_NULL(dev_opp->regulator)) return; + /* Release clk */ + if (!IS_ERR(dev_opp->clk)) + clk_put(dev_opp->clk); + list_dev = list_first_entry(&dev_opp->dev_list, struct device_list_opp, node); diff --git a/drivers/base/power/opp/opp.h b/drivers/base/power/opp/opp.h index fe44beb404ba..4f1bdfc7da03 100644 --- a/drivers/base/power/opp/opp.h +++ b/drivers/base/power/opp/opp.h @@ -22,6 +22,7 @@ #include #include +struct clk; struct regulator; /* Lock to allow exclusive modification to the device and opp lists */ @@ -134,6 +135,7 @@ struct device_list_opp { * @supported_hw: Array of version number to support. * @supported_hw_count: Number of elements in supported_hw array. * @prop_name: A name to postfix to many DT properties, while parsing them. + * @clk: Device's clock handle * @regulator: Supply regulator * @dentry: debugfs dentry pointer of the real device directory (not links). * @dentry_name: Name of the real dentry. @@ -168,6 +170,7 @@ struct device_opp { unsigned int *supported_hw; unsigned int supported_hw_count; const char *prop_name; + struct clk *clk; struct regulator *regulator; #ifdef CONFIG_DEBUG_FS -- cgit v1.2.3 From 6a0712f6f199e737aa5913d28ec4bd3a25de9660 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 9 Feb 2016 10:30:39 +0530 Subject: PM / OPP: Add dev_pm_opp_set_rate() This adds a routine, dev_pm_opp_set_rate(), responsible for configuring power-supply and clock source for an OPP. The OPP is found by matching against the target_freq passed to the routine. This shall replace similar code present in most of the OPP users and help simplify them a lot. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp/core.c | 176 ++++++++++++++++++++++++++++++++++++++++++ include/linux/pm_opp.h | 6 ++ 2 files changed, 182 insertions(+) (limited to 'drivers') diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index 7d7749ce1ce4..ab711c2c3e00 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -529,6 +529,182 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, } EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor); +/* + * The caller needs to ensure that device_opp (and hence the clk) isn't freed, + * while clk returned here is used. + */ +static struct clk *_get_opp_clk(struct device *dev) +{ + struct device_opp *dev_opp; + struct clk *clk; + + rcu_read_lock(); + + dev_opp = _find_device_opp(dev); + if (IS_ERR(dev_opp)) { + dev_err(dev, "%s: device opp doesn't exist\n", __func__); + clk = ERR_CAST(dev_opp); + goto unlock; + } + + clk = dev_opp->clk; + if (IS_ERR(clk)) + dev_err(dev, "%s: No clock available for the device\n", + __func__); + +unlock: + rcu_read_unlock(); + return clk; +} + +static int _set_opp_voltage(struct device *dev, struct regulator *reg, + unsigned long u_volt, unsigned long u_volt_min, + unsigned long u_volt_max) +{ + int ret; + + /* Regulator not available for device */ + if (IS_ERR(reg)) { + dev_dbg(dev, "%s: regulator not available: %ld\n", __func__, + PTR_ERR(reg)); + return 0; + } + + dev_dbg(dev, "%s: voltages (mV): %lu %lu %lu\n", __func__, u_volt_min, + u_volt, u_volt_max); + + ret = regulator_set_voltage_triplet(reg, u_volt_min, u_volt, + u_volt_max); + if (ret) + dev_err(dev, "%s: failed to set voltage (%lu %lu %lu mV): %d\n", + __func__, u_volt_min, u_volt, u_volt_max, ret); + + return ret; +} + +/** + * dev_pm_opp_set_rate() - Configure new OPP based on frequency + * @dev: device for which we do this operation + * @target_freq: frequency to achieve + * + * This configures the power-supplies and clock source to the levels specified + * by the OPP corresponding to the target_freq. + * + * Locking: This function takes rcu_read_lock(). + */ +int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) +{ + struct device_opp *dev_opp; + struct dev_pm_opp *old_opp, *opp; + struct regulator *reg; + struct clk *clk; + unsigned long freq, old_freq; + unsigned long u_volt, u_volt_min, u_volt_max; + unsigned long ou_volt, ou_volt_min, ou_volt_max; + int ret; + + if (unlikely(!target_freq)) { + dev_err(dev, "%s: Invalid target frequency %lu\n", __func__, + target_freq); + return -EINVAL; + } + + clk = _get_opp_clk(dev); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + freq = clk_round_rate(clk, target_freq); + if ((long)freq <= 0) + freq = target_freq; + + old_freq = clk_get_rate(clk); + + /* Return early if nothing to do */ + if (old_freq == freq) { + dev_dbg(dev, "%s: old/new frequencies (%lu Hz) are same, nothing to do\n", + __func__, freq); + return 0; + } + + rcu_read_lock(); + + dev_opp = _find_device_opp(dev); + if (IS_ERR(dev_opp)) { + dev_err(dev, "%s: device opp doesn't exist\n", __func__); + rcu_read_unlock(); + return PTR_ERR(dev_opp); + } + + old_opp = dev_pm_opp_find_freq_ceil(dev, &old_freq); + if (!IS_ERR(old_opp)) { + ou_volt = old_opp->u_volt; + ou_volt_min = old_opp->u_volt_min; + ou_volt_max = old_opp->u_volt_max; + } else { + dev_err(dev, "%s: failed to find current OPP for freq %lu (%ld)\n", + __func__, old_freq, PTR_ERR(old_opp)); + } + + opp = dev_pm_opp_find_freq_ceil(dev, &freq); + if (IS_ERR(opp)) { + ret = PTR_ERR(opp); + dev_err(dev, "%s: failed to find OPP for freq %lu (%d)\n", + __func__, freq, ret); + rcu_read_unlock(); + return ret; + } + + u_volt = opp->u_volt; + u_volt_min = opp->u_volt_min; + u_volt_max = opp->u_volt_max; + + reg = dev_opp->regulator; + + rcu_read_unlock(); + + /* Scaling up? Scale voltage before frequency */ + if (freq > old_freq) { + ret = _set_opp_voltage(dev, reg, u_volt, u_volt_min, + u_volt_max); + if (ret) + goto restore_voltage; + } + + /* Change frequency */ + + dev_dbg(dev, "%s: switching OPP: %lu Hz --> %lu Hz\n", + __func__, old_freq, freq); + + ret = clk_set_rate(clk, freq); + if (ret) { + dev_err(dev, "%s: failed to set clock rate: %d\n", __func__, + ret); + goto restore_voltage; + } + + /* Scaling down? Scale voltage after frequency */ + if (freq < old_freq) { + ret = _set_opp_voltage(dev, reg, u_volt, u_volt_min, + u_volt_max); + if (ret) + goto restore_freq; + } + + return 0; + +restore_freq: + if (clk_set_rate(clk, old_freq)) + dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n", + __func__, old_freq); +restore_voltage: + /* This shouldn't harm even if the voltages weren't updated earlier */ + if (!IS_ERR(old_opp)) + _set_opp_voltage(dev, reg, ou_volt, ou_volt_min, ou_volt_max); + + return ret; +} +EXPORT_SYMBOL_GPL(dev_pm_opp_set_rate); + /* List-dev Helpers */ static void _kfree_list_dev_rcu(struct rcu_head *head) { diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index 59da3d9e11ea..cccaf4a29e9f 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -64,6 +64,7 @@ int dev_pm_opp_set_prop_name(struct device *dev, const char *name); void dev_pm_opp_put_prop_name(struct device *dev); int dev_pm_opp_set_regulator(struct device *dev, const char *name); void dev_pm_opp_put_regulator(struct device *dev); +int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq); #else static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp) { @@ -172,6 +173,11 @@ static inline int dev_pm_opp_set_regulator(struct device *dev, const char *name) static inline void dev_pm_opp_put_regulator(struct device *dev) {} +static inline int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) +{ + return -EINVAL; +} + #endif /* CONFIG_PM_OPP */ #if defined(CONFIG_PM_OPP) && defined(CONFIG_OF) -- cgit v1.2.3 From 4db9a9ba602b38bd1fd80c4b3851dd15740a4fad Mon Sep 17 00:00:00 2001 From: Sylvain Lemieux Date: Tue, 9 Feb 2016 13:29:10 -0500 Subject: clk: lpc32xx: do not register clock "0" The following errors are display in the console during the power-on: [ 0.000000] lpc32xx_usb_clk_init: failed to register (null) clock: -12 [ 0.000000] lpc32xx_clk_init: failed to register (null) clock: -12 There is no need to register clock "0"; the first clock used is 1; Signed-off-by: Sylvain Lemieux Acked-by: Vladimir Zapolskiy [sboyd@codeaurora.org: s/prepare/register/] Signed-off-by: Stephen Boyd --- drivers/clk/nxp/clk-lpc32xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c index 10dd0fdaa474..981ff0dd88b4 100644 --- a/drivers/clk/nxp/clk-lpc32xx.c +++ b/drivers/clk/nxp/clk-lpc32xx.c @@ -1515,7 +1515,7 @@ static void __init lpc32xx_clk_init(struct device_node *np) return; } - for (i = 0; i < LPC32XX_CLK_MAX; i++) { + for (i = 1; i < LPC32XX_CLK_MAX; i++) { clk[i] = lpc32xx_clk_register(i); if (IS_ERR(clk[i])) { pr_err("failed to register %s clock: %ld\n", @@ -1555,7 +1555,7 @@ static void __init lpc32xx_usb_clk_init(struct device_node *np) return; } - for (i = 0; i < LPC32XX_USB_CLK_MAX; i++) { + for (i = 1; i < LPC32XX_USB_CLK_MAX; i++) { usb_clk[i] = lpc32xx_clk_register(i + LPC32XX_CLK_USB_OFFSET); if (IS_ERR(usb_clk[i])) { pr_err("failed to register %s clock: %ld\n", -- cgit v1.2.3 From 54573c4a073ff510d028f423ed3074573c7d9437 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 30 Dec 2015 11:28:02 +0100 Subject: xen/hvc: constify hv_ops structures These hv_ops structures are never modified, so declare them as const. Most were const already. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/tty/hvc/hvc_xen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index 11725422dacb..f417fa1ee47c 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c @@ -162,7 +162,7 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len) return recv; } -static struct hv_ops domU_hvc_ops = { +static const struct hv_ops domU_hvc_ops = { .get_chars = domU_read_console, .put_chars = domU_write_console, .notifier_add = notifier_add_irq, @@ -188,7 +188,7 @@ static int dom0_write_console(uint32_t vtermno, const char *str, int len) return len; } -static struct hv_ops dom0_hvc_ops = { +static const struct hv_ops dom0_hvc_ops = { .get_chars = dom0_read_console, .put_chars = dom0_write_console, .notifier_add = notifier_add_irq, -- cgit v1.2.3 From a44007a42dfd8e487537c7b1f8045577b28a4d95 Mon Sep 17 00:00:00 2001 From: Saurabh Sengar Date: Mon, 26 Oct 2015 09:25:36 +0530 Subject: drivers: usb: removed assignment of 0 to static variables fixing the error reported by script checkpatch.pl static variables blinkenlights and old_scheme_first were initialised to 0, correcting it. Signed-off-by: Saurabh Sengar Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 3d46d03a785b..681036d00528 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -49,7 +49,7 @@ static void hub_event(struct work_struct *work); DEFINE_MUTEX(usb_port_peer_mutex); /* cycle leds on hubs that aren't blinking for attention */ -static bool blinkenlights = 0; +static bool blinkenlights; module_param(blinkenlights, bool, S_IRUGO); MODULE_PARM_DESC(blinkenlights, "true to cycle leds on hubs"); @@ -78,7 +78,7 @@ MODULE_PARM_DESC(initial_descriptor_timeout, * otherwise the new scheme is used. If that fails and "use_both_schemes" * is set, then the driver will make another attempt, using the other scheme. */ -static bool old_scheme_first = 0; +static bool old_scheme_first; module_param(old_scheme_first, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(old_scheme_first, "start with the old device initialization scheme"); -- cgit v1.2.3 From 4c62785e670e978294222a42200346f0538e19e7 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Tue, 5 Jan 2016 23:03:37 +0800 Subject: driver core: bus: use list_for_each_entry* Use list_for_each_entry*() instead of list_for_each*() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 500592486e88..4bee6b0f9ea4 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -1019,13 +1019,11 @@ static void device_insertion_sort_klist(struct device *a, struct list_head *list int (*compare)(const struct device *a, const struct device *b)) { - struct list_head *pos; struct klist_node *n; struct device_private *dev_prv; struct device *b; - list_for_each(pos, list) { - n = container_of(pos, struct klist_node, n_node); + list_for_each_entry(n, list, n_node) { dev_prv = to_device_private_bus(n); b = dev_prv->device; if (compare(a, b) <= 0) { @@ -1042,8 +1040,7 @@ void bus_sort_breadthfirst(struct bus_type *bus, const struct device *b)) { LIST_HEAD(sorted_devices); - struct list_head *pos, *tmp; - struct klist_node *n; + struct klist_node *n, *tmp; struct device_private *dev_prv; struct device *dev; struct klist *device_klist; @@ -1051,8 +1048,7 @@ void bus_sort_breadthfirst(struct bus_type *bus, device_klist = bus_get_device_klist(bus); spin_lock(&device_klist->k_lock); - list_for_each_safe(pos, tmp, &device_klist->k_list) { - n = container_of(pos, struct klist_node, n_node); + list_for_each_entry_safe(n, tmp, &device_klist->k_list, n_node) { dev_prv = to_device_private_bus(n); dev = dev_prv->device; device_insertion_sort_klist(dev, &sorted_devices, compare); -- cgit v1.2.3 From 371fd7a2c438a56e00c18a83178555a7918329a2 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Tue, 5 Jan 2016 23:03:38 +0800 Subject: driver core: bus: use to_subsys_private and to_device_private_bus Use to_subsys_private() and to_device_private_bus() instead of open-coding. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 4bee6b0f9ea4..6470eb8088f4 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -149,8 +149,7 @@ EXPORT_SYMBOL_GPL(bus_remove_file); static void bus_release(struct kobject *kobj) { - struct subsys_private *priv = - container_of(kobj, typeof(*priv), subsys.kobj); + struct subsys_private *priv = to_subsys_private(kobj); struct bus_type *bus = priv->bus; kfree(priv); @@ -1103,7 +1102,7 @@ struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter) knode = klist_next(&iter->ki); if (!knode) return NULL; - dev = container_of(knode, struct device_private, knode_bus)->device; + dev = to_device_private_bus(knode)->device; if (!iter->type || iter->type == dev->type) return dev; } -- cgit v1.2.3 From cb54ad6cddb606add2481b82901d69670b480d1b Mon Sep 17 00:00:00 2001 From: Cory Tusar Date: Wed, 6 Jan 2016 22:55:00 -0500 Subject: misc: eeprom_93xx46: Fix 16-bit read and write accesses. Compatible at93xx46 devices from both Microchip and Atmel expect a word-based address, regardless of whether the device is strapped for 8- or 16-bit operation. However, the offset parameter passed in when reading or writing at a specific location is always specified in terms of bytes. This commit fixes 16-bit read and write accesses by shifting the offset parameter to account for this difference between a byte offset and a word-based address. Signed-off-by: Cory Tusar Tested-by: Chris Healy Signed-off-by: Greg Kroah-Hartman --- drivers/misc/eeprom/eeprom_93xx46.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index 473aa0a2eaf6..da3c081c2639 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -54,7 +54,7 @@ eeprom_93xx46_bin_read(struct file *filp, struct kobject *kobj, cmd_addr |= off & 0x7f; bits = 10; } else { - cmd_addr |= off & 0x3f; + cmd_addr |= (off >> 1) & 0x3f; bits = 9; } @@ -155,7 +155,7 @@ eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev, bits = 10; data_len = 1; } else { - cmd_addr |= off & 0x3f; + cmd_addr |= (off >> 1) & 0x3f; bits = 9; data_len = 2; } -- cgit v1.2.3 From c074abe02e5e3479b2dfd109fa2620d22d351c34 Mon Sep 17 00:00:00 2001 From: Cory Tusar Date: Wed, 6 Jan 2016 22:55:02 -0500 Subject: misc: eeprom_93xx46: Implement eeprom_93xx46 DT bindings. This commit implements bindings in the eeprom_93xx46 driver allowing device word size and read-only attributes to be specified via devicetree. Signed-off-by: Cory Tusar Tested-by: Chris Healy Reviewed-by: Vladimir Zapolskiy Signed-off-by: Greg Kroah-Hartman --- drivers/misc/eeprom/eeprom_93xx46.c | 49 +++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index da3c081c2639..f0c30b366218 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include #include @@ -294,12 +296,58 @@ static ssize_t eeprom_93xx46_store_erase(struct device *dev, } static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase); +static const struct of_device_id eeprom_93xx46_of_table[] = { + { .compatible = "eeprom-93xx46", }, + {} +}; +MODULE_DEVICE_TABLE(of, eeprom_93xx46_of_table); + +static int eeprom_93xx46_probe_dt(struct spi_device *spi) +{ + struct device_node *np = spi->dev.of_node; + struct eeprom_93xx46_platform_data *pd; + u32 tmp; + int ret; + + pd = devm_kzalloc(&spi->dev, sizeof(*pd), GFP_KERNEL); + if (!pd) + return -ENOMEM; + + ret = of_property_read_u32(np, "data-size", &tmp); + if (ret < 0) { + dev_err(&spi->dev, "data-size property not found\n"); + return ret; + } + + if (tmp == 8) { + pd->flags |= EE_ADDR8; + } else if (tmp == 16) { + pd->flags |= EE_ADDR16; + } else { + dev_err(&spi->dev, "invalid data-size (%d)\n", tmp); + return -EINVAL; + } + + if (of_property_read_bool(np, "read-only")) + pd->flags |= EE_READONLY; + + spi->dev.platform_data = pd; + + return 0; +} + static int eeprom_93xx46_probe(struct spi_device *spi) { struct eeprom_93xx46_platform_data *pd; struct eeprom_93xx46_dev *edev; int err; + if (spi->dev.of_node) { + err = eeprom_93xx46_probe_dt(spi); + if (err < 0) + return err; + } + pd = spi->dev.platform_data; if (!pd) { dev_err(&spi->dev, "missing platform data\n"); @@ -370,6 +418,7 @@ static int eeprom_93xx46_remove(struct spi_device *spi) static struct spi_driver eeprom_93xx46_driver = { .driver = { .name = "93xx46", + .of_match_table = of_match_ptr(eeprom_93xx46_of_table), }, .probe = eeprom_93xx46_probe, .remove = eeprom_93xx46_remove, -- cgit v1.2.3 From ececdc021ba8f48ce87f476dd412e2ed50f9cd8e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 8 Feb 2016 15:34:21 +0100 Subject: lkdtm: mark execute_location as noinline The kernel sometimes fails to link when lkdrm is built-in and compiled with clang: relocation truncated to fit: R_ARM_THM_CALL against `.bss' The reason here is that a relocation from .text to .bss fails to generate a trampoline because .bss is not an executable section. Marking the function 'noinline' turns the relative branch to .bss into an absolute branch to the function argument, and that works fine. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/misc/lkdtm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 11fdadc68e53..5c1351b19029 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c @@ -335,7 +335,7 @@ static noinline void corrupt_stack(void) memset((void *)data, 0, 64); } -static void execute_location(void *dst) +static void noinline execute_location(void *dst) { void (*func)(void) = dst; -- cgit v1.2.3 From 4ddbdbb90d2ec7d7db93c98936faf3dad75f479b Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 9 Feb 2016 00:00:17 +0200 Subject: mei: wd: drop AGAIN the watchdog code from the core mei driver The file wd.c was remove from the driver by commit commit fdd9b8655933 ("mei: wd: drop the watchdog code from the core mei driver") Unfortunately it came back by mistake in rebasing in the commit commit 06ee536bcb15 ("mei: fill file pointer in read cb for fixed address client") Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/wd.c | 391 -------------------------------------------------- 1 file changed, 391 deletions(-) delete mode 100644 drivers/misc/mei/wd.c (limited to 'drivers') diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c deleted file mode 100644 index 7d9b4ee42f65..000000000000 --- a/drivers/misc/mei/wd.c +++ /dev/null @@ -1,391 +0,0 @@ -/* - * - * Intel Management Engine Interface (Intel MEI) Linux driver - * Copyright (c) 2003-2012, 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, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - */ -#include -#include -#include -#include -#include -#include - -#include - -#include "mei_dev.h" -#include "hbm.h" -#include "client.h" - -static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; -static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; - -/* - * AMT Watchdog Device - */ -#define INTEL_AMT_WATCHDOG_ID "INTCAMT" - -/* UUIDs for AMT F/W clients */ -const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89, - 0x9D, 0xA9, 0x15, 0x14, 0xCB, - 0x32, 0xAB); - -static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout) -{ - dev_dbg(dev->dev, "wd: set timeout=%d.\n", timeout); - memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE); - memcpy(dev->wd_data + MEI_WD_HDR_SIZE, &timeout, sizeof(u16)); -} - -/** - * mei_wd_host_init - connect to the watchdog client - * - * @dev: the device structure - * @me_cl: me client - * - * Return: -ENOTTY if wd client cannot be found - * -EIO if write has failed - * 0 on success - */ -int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl) -{ - struct mei_cl *cl = &dev->wd_cl; - int ret; - - mei_cl_init(cl, dev); - - dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; - dev->wd_state = MEI_WD_IDLE; - - ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID); - if (ret < 0) { - dev_info(dev->dev, "wd: failed link client\n"); - return ret; - } - - ret = mei_cl_connect(cl, me_cl, NULL); - if (ret) { - dev_err(dev->dev, "wd: failed to connect = %d\n", ret); - mei_cl_unlink(cl); - return ret; - } - - ret = mei_watchdog_register(dev); - if (ret) { - mei_cl_disconnect(cl); - mei_cl_unlink(cl); - } - return ret; -} - -/** - * mei_wd_send - sends watch dog message to fw. - * - * @dev: the device structure - * - * Return: 0 if success, - * -EIO when message send fails - * -EINVAL when invalid message is to be sent - * -ENODEV on flow control failure - */ -int mei_wd_send(struct mei_device *dev) -{ - struct mei_cl *cl = &dev->wd_cl; - struct mei_msg_hdr hdr; - int ret; - - hdr.host_addr = cl->host_client_id; - hdr.me_addr = mei_cl_me_id(cl); - hdr.msg_complete = 1; - hdr.reserved = 0; - hdr.internal = 0; - - if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE)) - hdr.length = MEI_WD_START_MSG_SIZE; - else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE)) - hdr.length = MEI_WD_STOP_MSG_SIZE; - else { - dev_err(dev->dev, "wd: invalid message is to be sent, aborting\n"); - return -EINVAL; - } - - ret = mei_write_message(dev, &hdr, dev->wd_data); - if (ret) { - dev_err(dev->dev, "wd: write message failed\n"); - return ret; - } - - ret = mei_cl_flow_ctrl_reduce(cl); - if (ret) { - dev_err(dev->dev, "wd: flow_ctrl_reduce failed.\n"); - return ret; - } - - return 0; -} - -/** - * mei_wd_stop - sends watchdog stop message to fw. - * - * @dev: the device structure - * - * Return: 0 if success - * on error: - * -EIO when message send fails - * -EINVAL when invalid message is to be sent - * -ETIME on message timeout - */ -int mei_wd_stop(struct mei_device *dev) -{ - struct mei_cl *cl = &dev->wd_cl; - int ret; - - if (!mei_cl_is_connected(cl) || - dev->wd_state != MEI_WD_RUNNING) - return 0; - - memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_STOP_MSG_SIZE); - - dev->wd_state = MEI_WD_STOPPING; - - ret = mei_cl_flow_ctrl_creds(cl, NULL); - if (ret < 0) - goto err; - - if (ret && mei_hbuf_acquire(dev)) { - ret = mei_wd_send(dev); - if (ret) - goto err; - dev->wd_pending = false; - } else { - dev->wd_pending = true; - } - - mutex_unlock(&dev->device_lock); - - ret = wait_event_timeout(dev->wait_stop_wd, - dev->wd_state == MEI_WD_IDLE, - msecs_to_jiffies(MEI_WD_STOP_TIMEOUT)); - mutex_lock(&dev->device_lock); - if (dev->wd_state != MEI_WD_IDLE) { - /* timeout */ - ret = -ETIME; - dev_warn(dev->dev, "wd: stop failed to complete ret=%d\n", ret); - goto err; - } - dev_dbg(dev->dev, "wd: stop completed after %u msec\n", - MEI_WD_STOP_TIMEOUT - jiffies_to_msecs(ret)); - return 0; -err: - return ret; -} - -/** - * mei_wd_ops_start - wd start command from the watchdog core. - * - * @wd_dev: watchdog device struct - * - * Return: 0 if success, negative errno code for failure - */ -static int mei_wd_ops_start(struct watchdog_device *wd_dev) -{ - struct mei_device *dev; - struct mei_cl *cl; - int err = -ENODEV; - - dev = watchdog_get_drvdata(wd_dev); - if (!dev) - return -ENODEV; - - cl = &dev->wd_cl; - - mutex_lock(&dev->device_lock); - - if (dev->dev_state != MEI_DEV_ENABLED) { - dev_dbg(dev->dev, "wd: dev_state != MEI_DEV_ENABLED dev_state = %s\n", - mei_dev_state_str(dev->dev_state)); - goto end_unlock; - } - - if (!mei_cl_is_connected(cl)) { - cl_dbg(dev, cl, "MEI Driver is not connected to Watchdog Client\n"); - goto end_unlock; - } - - mei_wd_set_start_timeout(dev, dev->wd_timeout); - - err = 0; -end_unlock: - mutex_unlock(&dev->device_lock); - return err; -} - -/** - * mei_wd_ops_stop - wd stop command from the watchdog core. - * - * @wd_dev: watchdog device struct - * - * Return: 0 if success, negative errno code for failure - */ -static int mei_wd_ops_stop(struct watchdog_device *wd_dev) -{ - struct mei_device *dev; - - dev = watchdog_get_drvdata(wd_dev); - if (!dev) - return -ENODEV; - - mutex_lock(&dev->device_lock); - mei_wd_stop(dev); - mutex_unlock(&dev->device_lock); - - return 0; -} - -/** - * mei_wd_ops_ping - wd ping command from the watchdog core. - * - * @wd_dev: watchdog device struct - * - * Return: 0 if success, negative errno code for failure - */ -static int mei_wd_ops_ping(struct watchdog_device *wd_dev) -{ - struct mei_device *dev; - struct mei_cl *cl; - int ret; - - dev = watchdog_get_drvdata(wd_dev); - if (!dev) - return -ENODEV; - - cl = &dev->wd_cl; - - mutex_lock(&dev->device_lock); - - if (!mei_cl_is_connected(cl)) { - cl_err(dev, cl, "wd: not connected.\n"); - ret = -ENODEV; - goto end; - } - - dev->wd_state = MEI_WD_RUNNING; - - ret = mei_cl_flow_ctrl_creds(cl, NULL); - if (ret < 0) - goto end; - - /* Check if we can send the ping to HW*/ - if (ret && mei_hbuf_acquire(dev)) { - dev_dbg(dev->dev, "wd: sending ping\n"); - - ret = mei_wd_send(dev); - if (ret) - goto end; - dev->wd_pending = false; - } else { - dev->wd_pending = true; - } - -end: - mutex_unlock(&dev->device_lock); - return ret; -} - -/** - * mei_wd_ops_set_timeout - wd set timeout command from the watchdog core. - * - * @wd_dev: watchdog device struct - * @timeout: timeout value to set - * - * Return: 0 if success, negative errno code for failure - */ -static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, - unsigned int timeout) -{ - struct mei_device *dev; - - dev = watchdog_get_drvdata(wd_dev); - if (!dev) - return -ENODEV; - - /* Check Timeout value */ - if (timeout < MEI_WD_MIN_TIMEOUT || timeout > MEI_WD_MAX_TIMEOUT) - return -EINVAL; - - mutex_lock(&dev->device_lock); - - dev->wd_timeout = timeout; - wd_dev->timeout = timeout; - mei_wd_set_start_timeout(dev, dev->wd_timeout); - - mutex_unlock(&dev->device_lock); - - return 0; -} - -/* - * Watchdog Device structs - */ -static const struct watchdog_ops wd_ops = { - .owner = THIS_MODULE, - .start = mei_wd_ops_start, - .stop = mei_wd_ops_stop, - .ping = mei_wd_ops_ping, - .set_timeout = mei_wd_ops_set_timeout, -}; -static const struct watchdog_info wd_info = { - .identity = INTEL_AMT_WATCHDOG_ID, - .options = WDIOF_KEEPALIVEPING | - WDIOF_SETTIMEOUT | - WDIOF_ALARMONLY, -}; - -static struct watchdog_device amt_wd_dev = { - .info = &wd_info, - .ops = &wd_ops, - .timeout = MEI_WD_DEFAULT_TIMEOUT, - .min_timeout = MEI_WD_MIN_TIMEOUT, - .max_timeout = MEI_WD_MAX_TIMEOUT, -}; - - -int mei_watchdog_register(struct mei_device *dev) -{ - - int ret; - - amt_wd_dev.parent = dev->dev; - /* unlock to perserve correct locking order */ - mutex_unlock(&dev->device_lock); - ret = watchdog_register_device(&amt_wd_dev); - mutex_lock(&dev->device_lock); - if (ret) { - dev_err(dev->dev, "wd: unable to register watchdog device = %d.\n", - ret); - return ret; - } - - dev_dbg(dev->dev, "wd: successfully register watchdog interface.\n"); - watchdog_set_drvdata(&amt_wd_dev, dev); - return 0; -} - -void mei_watchdog_unregister(struct mei_device *dev) -{ - if (watchdog_get_drvdata(&amt_wd_dev) == NULL) - return; - - watchdog_set_drvdata(&amt_wd_dev, NULL); - watchdog_unregister_device(&amt_wd_dev); -} - -- cgit v1.2.3 From ef39830c35838696013a2f6c16f6728c4a9dcefd Mon Sep 17 00:00:00 2001 From: Sudeep Dutt Date: Mon, 8 Feb 2016 15:48:11 -0800 Subject: misc: mic: Remove MIC X100 host virtio functionality This patch deletes the virtio functionality from the MIC X100 host driver. A subsequent patch will re-enable this functionality by consolidating the hardware independent logic in a new Virtio over PCIe (VOP) driver. Reviewed-by: Ashutosh Dixit Signed-off-by: Sudeep Dutt Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/host/Makefile | 2 - drivers/misc/mic/host/mic_boot.c | 2 - drivers/misc/mic/host/mic_debugfs.c | 190 --------- drivers/misc/mic/host/mic_device.h | 6 - drivers/misc/mic/host/mic_fops.c | 222 ---------- drivers/misc/mic/host/mic_fops.h | 32 -- drivers/misc/mic/host/mic_main.c | 48 +-- drivers/misc/mic/host/mic_virtio.c | 811 ------------------------------------ drivers/misc/mic/host/mic_virtio.h | 155 ------- 9 files changed, 4 insertions(+), 1464 deletions(-) delete mode 100644 drivers/misc/mic/host/mic_fops.c delete mode 100644 drivers/misc/mic/host/mic_fops.h delete mode 100644 drivers/misc/mic/host/mic_virtio.c delete mode 100644 drivers/misc/mic/host/mic_virtio.h (limited to 'drivers') diff --git a/drivers/misc/mic/host/Makefile b/drivers/misc/mic/host/Makefile index 004d3db0f990..f3b502333ded 100644 --- a/drivers/misc/mic/host/Makefile +++ b/drivers/misc/mic/host/Makefile @@ -9,5 +9,3 @@ mic_host-objs += mic_smpt.o mic_host-objs += mic_intr.o mic_host-objs += mic_boot.o mic_host-objs += mic_debugfs.o -mic_host-objs += mic_fops.o -mic_host-objs += mic_virtio.o diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c index 7845564dff64..3df305f6282c 100644 --- a/drivers/misc/mic/host/mic_boot.c +++ b/drivers/misc/mic/host/mic_boot.c @@ -28,7 +28,6 @@ #include "../common/mic_dev.h" #include "mic_device.h" #include "mic_smpt.h" -#include "mic_virtio.h" static inline struct mic_device *scdev_to_mdev(struct scif_hw_dev *scdev) { @@ -423,7 +422,6 @@ static void _mic_stop(struct cosm_device *cdev, bool force) * will be the first to be registered and the last to be * unregistered. */ - mic_virtio_reset_devices(mdev); scif_unregister_device(mdev->scdev); mic_free_dma_chans(mdev); mbus_unregister_device(mdev->dma_mbdev); diff --git a/drivers/misc/mic/host/mic_debugfs.c b/drivers/misc/mic/host/mic_debugfs.c index 10581600777a..0a9daba8bb5d 100644 --- a/drivers/misc/mic/host/mic_debugfs.c +++ b/drivers/misc/mic/host/mic_debugfs.c @@ -26,7 +26,6 @@ #include "../common/mic_dev.h" #include "mic_device.h" #include "mic_smpt.h" -#include "mic_virtio.h" /* Debugfs parent dir */ static struct dentry *mic_dbg; @@ -100,190 +99,6 @@ static const struct file_operations post_code_ops = { .release = mic_post_code_debug_release }; -static int mic_dp_show(struct seq_file *s, void *pos) -{ - struct mic_device *mdev = s->private; - struct mic_device_desc *d; - struct mic_device_ctrl *dc; - struct mic_vqconfig *vqconfig; - __u32 *features; - __u8 *config; - struct mic_bootparam *bootparam = mdev->dp; - int i, j; - - seq_printf(s, "Bootparam: magic 0x%x\n", - bootparam->magic); - seq_printf(s, "Bootparam: h2c_config_db %d\n", - bootparam->h2c_config_db); - seq_printf(s, "Bootparam: node_id %d\n", - bootparam->node_id); - seq_printf(s, "Bootparam: c2h_scif_db %d\n", - bootparam->c2h_scif_db); - seq_printf(s, "Bootparam: h2c_scif_db %d\n", - bootparam->h2c_scif_db); - seq_printf(s, "Bootparam: scif_host_dma_addr 0x%llx\n", - bootparam->scif_host_dma_addr); - seq_printf(s, "Bootparam: scif_card_dma_addr 0x%llx\n", - bootparam->scif_card_dma_addr); - - - for (i = sizeof(*bootparam); i < MIC_DP_SIZE; - i += mic_total_desc_size(d)) { - d = mdev->dp + i; - dc = (void *)d + mic_aligned_desc_size(d); - - /* end of list */ - if (d->type == 0) - break; - - if (d->type == -1) - continue; - - seq_printf(s, "Type %d ", d->type); - seq_printf(s, "Num VQ %d ", d->num_vq); - seq_printf(s, "Feature Len %d\n", d->feature_len); - seq_printf(s, "Config Len %d ", d->config_len); - seq_printf(s, "Shutdown Status %d\n", d->status); - - for (j = 0; j < d->num_vq; j++) { - vqconfig = mic_vq_config(d) + j; - seq_printf(s, "vqconfig[%d]: ", j); - seq_printf(s, "address 0x%llx ", vqconfig->address); - seq_printf(s, "num %d ", vqconfig->num); - seq_printf(s, "used address 0x%llx\n", - vqconfig->used_address); - } - - features = (__u32 *)mic_vq_features(d); - seq_printf(s, "Features: Host 0x%x ", features[0]); - seq_printf(s, "Guest 0x%x\n", features[1]); - - config = mic_vq_configspace(d); - for (j = 0; j < d->config_len; j++) - seq_printf(s, "config[%d]=%d\n", j, config[j]); - - seq_puts(s, "Device control:\n"); - seq_printf(s, "Config Change %d ", dc->config_change); - seq_printf(s, "Vdev reset %d\n", dc->vdev_reset); - seq_printf(s, "Guest Ack %d ", dc->guest_ack); - seq_printf(s, "Host ack %d\n", dc->host_ack); - seq_printf(s, "Used address updated %d ", - dc->used_address_updated); - seq_printf(s, "Vdev 0x%llx\n", dc->vdev); - seq_printf(s, "c2h doorbell %d ", dc->c2h_vdev_db); - seq_printf(s, "h2c doorbell %d\n", dc->h2c_vdev_db); - } - - return 0; -} - -static int mic_dp_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, mic_dp_show, inode->i_private); -} - -static int mic_dp_debug_release(struct inode *inode, struct file *file) -{ - return single_release(inode, file); -} - -static const struct file_operations dp_ops = { - .owner = THIS_MODULE, - .open = mic_dp_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = mic_dp_debug_release -}; - -static int mic_vdev_info_show(struct seq_file *s, void *unused) -{ - struct mic_device *mdev = s->private; - struct list_head *pos, *tmp; - struct mic_vdev *mvdev; - int i, j; - - mutex_lock(&mdev->mic_mutex); - list_for_each_safe(pos, tmp, &mdev->vdev_list) { - mvdev = list_entry(pos, struct mic_vdev, list); - seq_printf(s, "VDEV type %d state %s in %ld out %ld\n", - mvdev->virtio_id, - mic_vdevup(mvdev) ? "UP" : "DOWN", - mvdev->in_bytes, - mvdev->out_bytes); - for (i = 0; i < MIC_MAX_VRINGS; i++) { - struct vring_desc *desc; - struct vring_avail *avail; - struct vring_used *used; - struct mic_vringh *mvr = &mvdev->mvr[i]; - struct vringh *vrh = &mvr->vrh; - int num = vrh->vring.num; - if (!num) - continue; - desc = vrh->vring.desc; - seq_printf(s, "vring i %d avail_idx %d", - i, mvr->vring.info->avail_idx & (num - 1)); - seq_printf(s, " vring i %d avail_idx %d\n", - i, mvr->vring.info->avail_idx); - seq_printf(s, "vrh i %d weak_barriers %d", - i, vrh->weak_barriers); - seq_printf(s, " last_avail_idx %d last_used_idx %d", - vrh->last_avail_idx, vrh->last_used_idx); - seq_printf(s, " completed %d\n", vrh->completed); - for (j = 0; j < num; j++) { - seq_printf(s, "desc[%d] addr 0x%llx len %d", - j, desc->addr, desc->len); - seq_printf(s, " flags 0x%x next %d\n", - desc->flags, desc->next); - desc++; - } - avail = vrh->vring.avail; - seq_printf(s, "avail flags 0x%x idx %d\n", - vringh16_to_cpu(vrh, avail->flags), - vringh16_to_cpu(vrh, avail->idx) & (num - 1)); - seq_printf(s, "avail flags 0x%x idx %d\n", - vringh16_to_cpu(vrh, avail->flags), - vringh16_to_cpu(vrh, avail->idx)); - for (j = 0; j < num; j++) - seq_printf(s, "avail ring[%d] %d\n", - j, avail->ring[j]); - used = vrh->vring.used; - seq_printf(s, "used flags 0x%x idx %d\n", - vringh16_to_cpu(vrh, used->flags), - vringh16_to_cpu(vrh, used->idx) & (num - 1)); - seq_printf(s, "used flags 0x%x idx %d\n", - vringh16_to_cpu(vrh, used->flags), - vringh16_to_cpu(vrh, used->idx)); - for (j = 0; j < num; j++) - seq_printf(s, "used ring[%d] id %d len %d\n", - j, vringh32_to_cpu(vrh, - used->ring[j].id), - vringh32_to_cpu(vrh, - used->ring[j].len)); - } - } - mutex_unlock(&mdev->mic_mutex); - - return 0; -} - -static int mic_vdev_info_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, mic_vdev_info_show, inode->i_private); -} - -static int mic_vdev_info_debug_release(struct inode *inode, struct file *file) -{ - return single_release(inode, file); -} - -static const struct file_operations vdev_info_ops = { - .owner = THIS_MODULE, - .open = mic_vdev_info_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = mic_vdev_info_debug_release -}; - static int mic_msi_irq_info_show(struct seq_file *s, void *pos) { struct mic_device *mdev = s->private; @@ -367,11 +182,6 @@ void mic_create_debug_dir(struct mic_device *mdev) debugfs_create_file("post_code", 0444, mdev->dbg_dir, mdev, &post_code_ops); - debugfs_create_file("dp", 0444, mdev->dbg_dir, mdev, &dp_ops); - - debugfs_create_file("vdev_info", 0444, mdev->dbg_dir, mdev, - &vdev_info_ops); - debugfs_create_file("msi_irq_info", 0444, mdev->dbg_dir, mdev, &msi_irq_info_ops); } diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h index 461184a12fbb..8460de122929 100644 --- a/drivers/misc/mic/host/mic_device.h +++ b/drivers/misc/mic/host/mic_device.h @@ -64,9 +64,6 @@ extern struct cosm_hw_ops cosm_hw_ops; * @bootaddr: MIC boot address. * @dp: virtio device page * @dp_dma_addr: virtio device page DMA address. - * @name: name for the misc char device - * @miscdev: registered misc char device - * @vdev_list: list of virtio devices. * @dma_mbdev: MIC BUS DMA device. * @dma_ch - Array of DMA channels * @num_dma_ch - Number of DMA channels available @@ -91,9 +88,6 @@ struct mic_device { u32 bootaddr; void *dp; dma_addr_t dp_dma_addr; - char name[16]; - struct miscdevice miscdev; - struct list_head vdev_list; struct mbus_device *dma_mbdev; struct dma_chan *dma_ch[MIC_MAX_DMA_CHAN]; int num_dma_ch; diff --git a/drivers/misc/mic/host/mic_fops.c b/drivers/misc/mic/host/mic_fops.c deleted file mode 100644 index 8cc1d90cd949..000000000000 --- a/drivers/misc/mic/host/mic_fops.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Intel MIC Platform Software Stack (MPSS) - * - * Copyright(c) 2013 Intel Corporation. - * - * 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. - * - * 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. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Intel MIC Host driver. - * - */ -#include -#include - -#include -#include "../common/mic_dev.h" -#include "mic_device.h" -#include "mic_fops.h" -#include "mic_virtio.h" - -int mic_open(struct inode *inode, struct file *f) -{ - struct mic_vdev *mvdev; - struct mic_device *mdev = container_of(f->private_data, - struct mic_device, miscdev); - - mvdev = kzalloc(sizeof(*mvdev), GFP_KERNEL); - if (!mvdev) - return -ENOMEM; - - init_waitqueue_head(&mvdev->waitq); - INIT_LIST_HEAD(&mvdev->list); - mvdev->mdev = mdev; - mvdev->virtio_id = -1; - - f->private_data = mvdev; - return 0; -} - -int mic_release(struct inode *inode, struct file *f) -{ - struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data; - - if (-1 != mvdev->virtio_id) - mic_virtio_del_device(mvdev); - f->private_data = NULL; - kfree(mvdev); - return 0; -} - -long mic_ioctl(struct file *f, unsigned int cmd, unsigned long arg) -{ - struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data; - void __user *argp = (void __user *)arg; - int ret; - - switch (cmd) { - case MIC_VIRTIO_ADD_DEVICE: - { - ret = mic_virtio_add_device(mvdev, argp); - if (ret < 0) { - dev_err(mic_dev(mvdev), - "%s %d errno ret %d\n", - __func__, __LINE__, ret); - return ret; - } - break; - } - case MIC_VIRTIO_COPY_DESC: - { - struct mic_copy_desc copy; - - ret = mic_vdev_inited(mvdev); - if (ret) - return ret; - - if (copy_from_user(©, argp, sizeof(copy))) - return -EFAULT; - - dev_dbg(mic_dev(mvdev), - "%s %d === iovcnt 0x%x vr_idx 0x%x update_used %d\n", - __func__, __LINE__, copy.iovcnt, copy.vr_idx, - copy.update_used); - - ret = mic_virtio_copy_desc(mvdev, ©); - if (ret < 0) { - dev_err(mic_dev(mvdev), - "%s %d errno ret %d\n", - __func__, __LINE__, ret); - return ret; - } - if (copy_to_user( - &((struct mic_copy_desc __user *)argp)->out_len, - ©.out_len, sizeof(copy.out_len))) { - dev_err(mic_dev(mvdev), "%s %d errno ret %d\n", - __func__, __LINE__, -EFAULT); - return -EFAULT; - } - break; - } - case MIC_VIRTIO_CONFIG_CHANGE: - { - ret = mic_vdev_inited(mvdev); - if (ret) - return ret; - - ret = mic_virtio_config_change(mvdev, argp); - if (ret < 0) { - dev_err(mic_dev(mvdev), - "%s %d errno ret %d\n", - __func__, __LINE__, ret); - return ret; - } - break; - } - default: - return -ENOIOCTLCMD; - }; - return 0; -} - -/* - * We return POLLIN | POLLOUT from poll when new buffers are enqueued, and - * not when previously enqueued buffers may be available. This means that - * in the card->host (TX) path, when userspace is unblocked by poll it - * must drain all available descriptors or it can stall. - */ -unsigned int mic_poll(struct file *f, poll_table *wait) -{ - struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data; - int mask = 0; - - poll_wait(f, &mvdev->waitq, wait); - - if (mic_vdev_inited(mvdev)) { - mask = POLLERR; - } else if (mvdev->poll_wake) { - mvdev->poll_wake = 0; - mask = POLLIN | POLLOUT; - } - - return mask; -} - -static inline int -mic_query_offset(struct mic_vdev *mvdev, unsigned long offset, - unsigned long *size, unsigned long *pa) -{ - struct mic_device *mdev = mvdev->mdev; - unsigned long start = MIC_DP_SIZE; - int i; - - /* - * MMAP interface is as follows: - * offset region - * 0x0 virtio device_page - * 0x1000 first vring - * 0x1000 + size of 1st vring second vring - * .... - */ - if (!offset) { - *pa = virt_to_phys(mdev->dp); - *size = MIC_DP_SIZE; - return 0; - } - - for (i = 0; i < mvdev->dd->num_vq; i++) { - struct mic_vringh *mvr = &mvdev->mvr[i]; - if (offset == start) { - *pa = virt_to_phys(mvr->vring.va); - *size = mvr->vring.len; - return 0; - } - start += mvr->vring.len; - } - return -1; -} - -/* - * Maps the device page and virtio rings to user space for readonly access. - */ -int -mic_mmap(struct file *f, struct vm_area_struct *vma) -{ - struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data; - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - unsigned long pa, size = vma->vm_end - vma->vm_start, size_rem = size; - int i, err; - - err = mic_vdev_inited(mvdev); - if (err) - return err; - - if (vma->vm_flags & VM_WRITE) - return -EACCES; - - while (size_rem) { - i = mic_query_offset(mvdev, offset, &size, &pa); - if (i < 0) - return -EINVAL; - err = remap_pfn_range(vma, vma->vm_start + offset, - pa >> PAGE_SHIFT, size, vma->vm_page_prot); - if (err) - return err; - dev_dbg(mic_dev(mvdev), - "%s %d type %d size 0x%lx off 0x%lx pa 0x%lx vma 0x%lx\n", - __func__, __LINE__, mvdev->virtio_id, size, offset, - pa, vma->vm_start + offset); - size_rem -= size; - offset += size; - } - return 0; -} diff --git a/drivers/misc/mic/host/mic_fops.h b/drivers/misc/mic/host/mic_fops.h deleted file mode 100644 index dc3893dff667..000000000000 --- a/drivers/misc/mic/host/mic_fops.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Intel MIC Platform Software Stack (MPSS) - * - * Copyright(c) 2013 Intel Corporation. - * - * 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. - * - * 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. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Intel MIC Host driver. - * - */ -#ifndef _MIC_FOPS_H_ -#define _MIC_FOPS_H_ - -int mic_open(struct inode *inode, struct file *filp); -int mic_release(struct inode *inode, struct file *filp); -ssize_t mic_read(struct file *filp, char __user *buf, - size_t count, loff_t *pos); -long mic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -int mic_mmap(struct file *f, struct vm_area_struct *vma); -unsigned int mic_poll(struct file *f, poll_table *wait); - -#endif diff --git a/drivers/misc/mic/host/mic_main.c b/drivers/misc/mic/host/mic_main.c index 153894e7ed5b..400def2106e7 100644 --- a/drivers/misc/mic/host/mic_main.c +++ b/drivers/misc/mic/host/mic_main.c @@ -27,8 +27,6 @@ #include "mic_device.h" #include "mic_x100.h" #include "mic_smpt.h" -#include "mic_fops.h" -#include "mic_virtio.h" static const char mic_driver_name[] = "mic"; @@ -57,17 +55,6 @@ MODULE_DEVICE_TABLE(pci, mic_pci_tbl); /* ID allocator for MIC devices */ static struct ida g_mic_ida; -/* Base device node number for MIC devices */ -static dev_t g_mic_devno; - -static const struct file_operations mic_fops = { - .open = mic_open, - .release = mic_release, - .unlocked_ioctl = mic_ioctl, - .poll = mic_poll, - .mmap = mic_mmap, - .owner = THIS_MODULE, -}; /* Initialize the device page */ static int mic_dp_init(struct mic_device *mdev) @@ -169,7 +156,6 @@ mic_device_init(struct mic_device *mdev, struct pci_dev *pdev) mic_ops_init(mdev); mutex_init(&mdev->mic_mutex); mdev->irq_info.next_avail_src = 0; - INIT_LIST_HEAD(&mdev->vdev_list); } /** @@ -259,30 +245,15 @@ static int mic_probe(struct pci_dev *pdev, goto smpt_uninit; } mic_bootparam_init(mdev); - mic_create_debug_dir(mdev); - mdev->miscdev.minor = MISC_DYNAMIC_MINOR; - snprintf(mdev->name, sizeof(mdev->name), "mic%d", mdev->id); - mdev->miscdev.name = mdev->name; - mdev->miscdev.fops = &mic_fops; - mdev->miscdev.parent = &mdev->pdev->dev; - rc = misc_register(&mdev->miscdev); - if (rc) { - dev_err(&pdev->dev, "misc_register err id %d rc %d\n", - mdev->id, rc); - goto cleanup_debug_dir; - } - mdev->cosm_dev = cosm_register_device(&mdev->pdev->dev, &cosm_hw_ops); if (IS_ERR(mdev->cosm_dev)) { rc = PTR_ERR(mdev->cosm_dev); dev_err(&pdev->dev, "cosm_add_device failed rc %d\n", rc); - goto misc_dereg; + goto cleanup_debug_dir; } return 0; -misc_dereg: - misc_deregister(&mdev->miscdev); cleanup_debug_dir: mic_delete_debug_dir(mdev); mic_dp_uninit(mdev); @@ -323,7 +294,6 @@ static void mic_remove(struct pci_dev *pdev) return; cosm_unregister_device(mdev->cosm_dev); - misc_deregister(&mdev->miscdev); mic_delete_debug_dir(mdev); mic_dp_uninit(mdev); mic_smpt_uninit(mdev); @@ -347,26 +317,17 @@ static int __init mic_init(void) { int ret; - ret = alloc_chrdev_region(&g_mic_devno, 0, - MIC_MAX_NUM_DEVS, mic_driver_name); - if (ret) { - pr_err("alloc_chrdev_region failed ret %d\n", ret); - goto error; - } - mic_init_debugfs(); ida_init(&g_mic_ida); ret = pci_register_driver(&mic_driver); if (ret) { pr_err("pci_register_driver failed ret %d\n", ret); - goto cleanup_chrdev; + goto cleanup_debugfs; } - return ret; -cleanup_chrdev: + return 0; +cleanup_debugfs: ida_destroy(&g_mic_ida); mic_exit_debugfs(); - unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS); -error: return ret; } @@ -375,7 +336,6 @@ static void __exit mic_exit(void) pci_unregister_driver(&mic_driver); ida_destroy(&g_mic_ida); mic_exit_debugfs(); - unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS); } module_init(mic_init); diff --git a/drivers/misc/mic/host/mic_virtio.c b/drivers/misc/mic/host/mic_virtio.c deleted file mode 100644 index 58b107a24a8b..000000000000 --- a/drivers/misc/mic/host/mic_virtio.c +++ /dev/null @@ -1,811 +0,0 @@ -/* - * Intel MIC Platform Software Stack (MPSS) - * - * Copyright(c) 2013 Intel Corporation. - * - * 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. - * - * 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. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Intel MIC Host driver. - * - */ -#include -#include -#include -#include -#include -#include "../common/mic_dev.h" -#include "mic_device.h" -#include "mic_smpt.h" -#include "mic_virtio.h" - -/* - * Size of the internal buffer used during DMA's as an intermediate buffer - * for copy to/from user. - */ -#define MIC_INT_DMA_BUF_SIZE PAGE_ALIGN(64 * 1024ULL) - -static int mic_sync_dma(struct mic_device *mdev, dma_addr_t dst, - dma_addr_t src, size_t len) -{ - int err = 0; - struct dma_async_tx_descriptor *tx; - struct dma_chan *mic_ch = mdev->dma_ch[0]; - - if (!mic_ch) { - err = -EBUSY; - goto error; - } - - tx = mic_ch->device->device_prep_dma_memcpy(mic_ch, dst, src, len, - DMA_PREP_FENCE); - if (!tx) { - err = -ENOMEM; - goto error; - } else { - dma_cookie_t cookie = tx->tx_submit(tx); - - err = dma_submit_error(cookie); - if (err) - goto error; - err = dma_sync_wait(mic_ch, cookie); - } -error: - if (err) - dev_err(&mdev->pdev->dev, "%s %d err %d\n", - __func__, __LINE__, err); - return err; -} - -/* - * Initiates the copies across the PCIe bus from card memory to a user - * space buffer. When transfers are done using DMA, source/destination - * addresses and transfer length must follow the alignment requirements of - * the MIC DMA engine. - */ -static int mic_virtio_copy_to_user(struct mic_vdev *mvdev, void __user *ubuf, - size_t len, u64 daddr, size_t dlen, - int vr_idx) -{ - struct mic_device *mdev = mvdev->mdev; - void __iomem *dbuf = mdev->aper.va + daddr; - struct mic_vringh *mvr = &mvdev->mvr[vr_idx]; - size_t dma_alignment = 1 << mdev->dma_ch[0]->device->copy_align; - size_t dma_offset; - size_t partlen; - int err; - - dma_offset = daddr - round_down(daddr, dma_alignment); - daddr -= dma_offset; - len += dma_offset; - - while (len) { - partlen = min_t(size_t, len, MIC_INT_DMA_BUF_SIZE); - - err = mic_sync_dma(mdev, mvr->buf_da, daddr, - ALIGN(partlen, dma_alignment)); - if (err) - goto err; - - if (copy_to_user(ubuf, mvr->buf + dma_offset, - partlen - dma_offset)) { - err = -EFAULT; - goto err; - } - daddr += partlen; - ubuf += partlen; - dbuf += partlen; - mvdev->in_bytes_dma += partlen; - mvdev->in_bytes += partlen; - len -= partlen; - dma_offset = 0; - } - return 0; -err: - dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, err); - return err; -} - -/* - * Initiates copies across the PCIe bus from a user space buffer to card - * memory. When transfers are done using DMA, source/destination addresses - * and transfer length must follow the alignment requirements of the MIC - * DMA engine. - */ -static int mic_virtio_copy_from_user(struct mic_vdev *mvdev, void __user *ubuf, - size_t len, u64 daddr, size_t dlen, - int vr_idx) -{ - struct mic_device *mdev = mvdev->mdev; - void __iomem *dbuf = mdev->aper.va + daddr; - struct mic_vringh *mvr = &mvdev->mvr[vr_idx]; - size_t dma_alignment = 1 << mdev->dma_ch[0]->device->copy_align; - size_t partlen; - int err; - - if (daddr & (dma_alignment - 1)) { - mvdev->tx_dst_unaligned += len; - goto memcpy; - } else if (ALIGN(len, dma_alignment) > dlen) { - mvdev->tx_len_unaligned += len; - goto memcpy; - } - - while (len) { - partlen = min_t(size_t, len, MIC_INT_DMA_BUF_SIZE); - - if (copy_from_user(mvr->buf, ubuf, partlen)) { - err = -EFAULT; - goto err; - } - err = mic_sync_dma(mdev, daddr, mvr->buf_da, - ALIGN(partlen, dma_alignment)); - if (err) - goto err; - daddr += partlen; - ubuf += partlen; - dbuf += partlen; - mvdev->out_bytes_dma += partlen; - mvdev->out_bytes += partlen; - len -= partlen; - } -memcpy: - /* - * We are copying to IO below and should ideally use something - * like copy_from_user_toio(..) if it existed. - */ - if (copy_from_user((void __force *)dbuf, ubuf, len)) { - err = -EFAULT; - goto err; - } - mvdev->out_bytes += len; - return 0; -err: - dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, err); - return err; -} - -#define MIC_VRINGH_READ true - -/* The function to call to notify the card about added buffers */ -static void mic_notify(struct vringh *vrh) -{ - struct mic_vringh *mvrh = container_of(vrh, struct mic_vringh, vrh); - struct mic_vdev *mvdev = mvrh->mvdev; - s8 db = mvdev->dc->h2c_vdev_db; - - if (db != -1) - mvdev->mdev->ops->send_intr(mvdev->mdev, db); -} - -/* Determine the total number of bytes consumed in a VRINGH KIOV */ -static inline u32 mic_vringh_iov_consumed(struct vringh_kiov *iov) -{ - int i; - u32 total = iov->consumed; - - for (i = 0; i < iov->i; i++) - total += iov->iov[i].iov_len; - return total; -} - -/* - * Traverse the VRINGH KIOV and issue the APIs to trigger the copies. - * This API is heavily based on the vringh_iov_xfer(..) implementation - * in vringh.c. The reason we cannot reuse vringh_iov_pull_kern(..) - * and vringh_iov_push_kern(..) directly is because there is no - * way to override the VRINGH xfer(..) routines as of v3.10. - */ -static int mic_vringh_copy(struct mic_vdev *mvdev, struct vringh_kiov *iov, - void __user *ubuf, size_t len, bool read, int vr_idx, - size_t *out_len) -{ - int ret = 0; - size_t partlen, tot_len = 0; - - while (len && iov->i < iov->used) { - partlen = min(iov->iov[iov->i].iov_len, len); - if (read) - ret = mic_virtio_copy_to_user(mvdev, ubuf, partlen, - (u64)iov->iov[iov->i].iov_base, - iov->iov[iov->i].iov_len, - vr_idx); - else - ret = mic_virtio_copy_from_user(mvdev, ubuf, partlen, - (u64)iov->iov[iov->i].iov_base, - iov->iov[iov->i].iov_len, - vr_idx); - if (ret) { - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, ret); - break; - } - len -= partlen; - ubuf += partlen; - tot_len += partlen; - iov->consumed += partlen; - iov->iov[iov->i].iov_len -= partlen; - iov->iov[iov->i].iov_base += partlen; - if (!iov->iov[iov->i].iov_len) { - /* Fix up old iov element then increment. */ - iov->iov[iov->i].iov_len = iov->consumed; - iov->iov[iov->i].iov_base -= iov->consumed; - - iov->consumed = 0; - iov->i++; - } - } - *out_len = tot_len; - return ret; -} - -/* - * Use the standard VRINGH infrastructure in the kernel to fetch new - * descriptors, initiate the copies and update the used ring. - */ -static int _mic_virtio_copy(struct mic_vdev *mvdev, - struct mic_copy_desc *copy) -{ - int ret = 0; - u32 iovcnt = copy->iovcnt; - struct iovec iov; - struct iovec __user *u_iov = copy->iov; - void __user *ubuf = NULL; - struct mic_vringh *mvr = &mvdev->mvr[copy->vr_idx]; - struct vringh_kiov *riov = &mvr->riov; - struct vringh_kiov *wiov = &mvr->wiov; - struct vringh *vrh = &mvr->vrh; - u16 *head = &mvr->head; - struct mic_vring *vr = &mvr->vring; - size_t len = 0, out_len; - - copy->out_len = 0; - /* Fetch a new IOVEC if all previous elements have been processed */ - if (riov->i == riov->used && wiov->i == wiov->used) { - ret = vringh_getdesc_kern(vrh, riov, wiov, - head, GFP_KERNEL); - /* Check if there are available descriptors */ - if (ret <= 0) - return ret; - } - while (iovcnt) { - if (!len) { - /* Copy over a new iovec from user space. */ - ret = copy_from_user(&iov, u_iov, sizeof(*u_iov)); - if (ret) { - ret = -EINVAL; - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, ret); - break; - } - len = iov.iov_len; - ubuf = iov.iov_base; - } - /* Issue all the read descriptors first */ - ret = mic_vringh_copy(mvdev, riov, ubuf, len, MIC_VRINGH_READ, - copy->vr_idx, &out_len); - if (ret) { - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, ret); - break; - } - len -= out_len; - ubuf += out_len; - copy->out_len += out_len; - /* Issue the write descriptors next */ - ret = mic_vringh_copy(mvdev, wiov, ubuf, len, !MIC_VRINGH_READ, - copy->vr_idx, &out_len); - if (ret) { - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, ret); - break; - } - len -= out_len; - ubuf += out_len; - copy->out_len += out_len; - if (!len) { - /* One user space iovec is now completed */ - iovcnt--; - u_iov++; - } - /* Exit loop if all elements in KIOVs have been processed. */ - if (riov->i == riov->used && wiov->i == wiov->used) - break; - } - /* - * Update the used ring if a descriptor was available and some data was - * copied in/out and the user asked for a used ring update. - */ - if (*head != USHRT_MAX && copy->out_len && copy->update_used) { - u32 total = 0; - - /* Determine the total data consumed */ - total += mic_vringh_iov_consumed(riov); - total += mic_vringh_iov_consumed(wiov); - vringh_complete_kern(vrh, *head, total); - *head = USHRT_MAX; - if (vringh_need_notify_kern(vrh) > 0) - vringh_notify(vrh); - vringh_kiov_cleanup(riov); - vringh_kiov_cleanup(wiov); - /* Update avail idx for user space */ - vr->info->avail_idx = vrh->last_avail_idx; - } - return ret; -} - -static inline int mic_verify_copy_args(struct mic_vdev *mvdev, - struct mic_copy_desc *copy) -{ - if (copy->vr_idx >= mvdev->dd->num_vq) { - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, -EINVAL); - return -EINVAL; - } - return 0; -} - -/* Copy a specified number of virtio descriptors in a chain */ -int mic_virtio_copy_desc(struct mic_vdev *mvdev, - struct mic_copy_desc *copy) -{ - int err; - struct mic_vringh *mvr = &mvdev->mvr[copy->vr_idx]; - - err = mic_verify_copy_args(mvdev, copy); - if (err) - return err; - - mutex_lock(&mvr->vr_mutex); - if (!mic_vdevup(mvdev)) { - err = -ENODEV; - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, err); - goto err; - } - err = _mic_virtio_copy(mvdev, copy); - if (err) { - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, err); - } -err: - mutex_unlock(&mvr->vr_mutex); - return err; -} - -static void mic_virtio_init_post(struct mic_vdev *mvdev) -{ - struct mic_vqconfig *vqconfig = mic_vq_config(mvdev->dd); - int i; - - for (i = 0; i < mvdev->dd->num_vq; i++) { - if (!le64_to_cpu(vqconfig[i].used_address)) { - dev_warn(mic_dev(mvdev), "used_address zero??\n"); - continue; - } - mvdev->mvr[i].vrh.vring.used = - (void __force *)mvdev->mdev->aper.va + - le64_to_cpu(vqconfig[i].used_address); - } - - mvdev->dc->used_address_updated = 0; - - dev_dbg(mic_dev(mvdev), "%s: device type %d LINKUP\n", - __func__, mvdev->virtio_id); -} - -static inline void mic_virtio_device_reset(struct mic_vdev *mvdev) -{ - int i; - - dev_dbg(mic_dev(mvdev), "%s: status %d device type %d RESET\n", - __func__, mvdev->dd->status, mvdev->virtio_id); - - for (i = 0; i < mvdev->dd->num_vq; i++) - /* - * Avoid lockdep false positive. The + 1 is for the mic - * mutex which is held in the reset devices code path. - */ - mutex_lock_nested(&mvdev->mvr[i].vr_mutex, i + 1); - - /* 0 status means "reset" */ - mvdev->dd->status = 0; - mvdev->dc->vdev_reset = 0; - mvdev->dc->host_ack = 1; - - for (i = 0; i < mvdev->dd->num_vq; i++) { - struct vringh *vrh = &mvdev->mvr[i].vrh; - mvdev->mvr[i].vring.info->avail_idx = 0; - vrh->completed = 0; - vrh->last_avail_idx = 0; - vrh->last_used_idx = 0; - } - - for (i = 0; i < mvdev->dd->num_vq; i++) - mutex_unlock(&mvdev->mvr[i].vr_mutex); -} - -void mic_virtio_reset_devices(struct mic_device *mdev) -{ - struct list_head *pos, *tmp; - struct mic_vdev *mvdev; - - dev_dbg(&mdev->pdev->dev, "%s\n", __func__); - - list_for_each_safe(pos, tmp, &mdev->vdev_list) { - mvdev = list_entry(pos, struct mic_vdev, list); - mic_virtio_device_reset(mvdev); - mvdev->poll_wake = 1; - wake_up(&mvdev->waitq); - } -} - -void mic_bh_handler(struct work_struct *work) -{ - struct mic_vdev *mvdev = container_of(work, struct mic_vdev, - virtio_bh_work); - - if (mvdev->dc->used_address_updated) - mic_virtio_init_post(mvdev); - - if (mvdev->dc->vdev_reset) - mic_virtio_device_reset(mvdev); - - mvdev->poll_wake = 1; - wake_up(&mvdev->waitq); -} - -static irqreturn_t mic_virtio_intr_handler(int irq, void *data) -{ - struct mic_vdev *mvdev = data; - struct mic_device *mdev = mvdev->mdev; - - mdev->ops->intr_workarounds(mdev); - schedule_work(&mvdev->virtio_bh_work); - return IRQ_HANDLED; -} - -int mic_virtio_config_change(struct mic_vdev *mvdev, - void __user *argp) -{ - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); - int ret = 0, retry, i; - struct mic_bootparam *bootparam = mvdev->mdev->dp; - s8 db = bootparam->h2c_config_db; - - mutex_lock(&mvdev->mdev->mic_mutex); - for (i = 0; i < mvdev->dd->num_vq; i++) - mutex_lock_nested(&mvdev->mvr[i].vr_mutex, i + 1); - - if (db == -1 || mvdev->dd->type == -1) { - ret = -EIO; - goto exit; - } - - if (copy_from_user(mic_vq_configspace(mvdev->dd), - argp, mvdev->dd->config_len)) { - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, -EFAULT); - ret = -EFAULT; - goto exit; - } - mvdev->dc->config_change = MIC_VIRTIO_PARAM_CONFIG_CHANGED; - mvdev->mdev->ops->send_intr(mvdev->mdev, db); - - for (retry = 100; retry--;) { - ret = wait_event_timeout(wake, - mvdev->dc->guest_ack, msecs_to_jiffies(100)); - if (ret) - break; - } - - dev_dbg(mic_dev(mvdev), - "%s %d retry: %d\n", __func__, __LINE__, retry); - mvdev->dc->config_change = 0; - mvdev->dc->guest_ack = 0; -exit: - for (i = 0; i < mvdev->dd->num_vq; i++) - mutex_unlock(&mvdev->mvr[i].vr_mutex); - mutex_unlock(&mvdev->mdev->mic_mutex); - return ret; -} - -static int mic_copy_dp_entry(struct mic_vdev *mvdev, - void __user *argp, - __u8 *type, - struct mic_device_desc **devpage) -{ - struct mic_device *mdev = mvdev->mdev; - struct mic_device_desc dd, *dd_config, *devp; - struct mic_vqconfig *vqconfig; - int ret = 0, i; - bool slot_found = false; - - if (copy_from_user(&dd, argp, sizeof(dd))) { - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, -EFAULT); - return -EFAULT; - } - - if (mic_aligned_desc_size(&dd) > MIC_MAX_DESC_BLK_SIZE || - dd.num_vq > MIC_MAX_VRINGS) { - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, -EINVAL); - return -EINVAL; - } - - dd_config = kmalloc(mic_desc_size(&dd), GFP_KERNEL); - if (dd_config == NULL) { - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, -ENOMEM); - return -ENOMEM; - } - if (copy_from_user(dd_config, argp, mic_desc_size(&dd))) { - ret = -EFAULT; - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, ret); - goto exit; - } - - vqconfig = mic_vq_config(dd_config); - for (i = 0; i < dd.num_vq; i++) { - if (le16_to_cpu(vqconfig[i].num) > MIC_MAX_VRING_ENTRIES) { - ret = -EINVAL; - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, ret); - goto exit; - } - } - - /* Find the first free device page entry */ - for (i = sizeof(struct mic_bootparam); - i < MIC_DP_SIZE - mic_total_desc_size(dd_config); - i += mic_total_desc_size(devp)) { - devp = mdev->dp + i; - if (devp->type == 0 || devp->type == -1) { - slot_found = true; - break; - } - } - if (!slot_found) { - ret = -EINVAL; - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, ret); - goto exit; - } - /* - * Save off the type before doing the memcpy. Type will be set in the - * end after completing all initialization for the new device. - */ - *type = dd_config->type; - dd_config->type = 0; - memcpy(devp, dd_config, mic_desc_size(dd_config)); - - *devpage = devp; -exit: - kfree(dd_config); - return ret; -} - -static void mic_init_device_ctrl(struct mic_vdev *mvdev, - struct mic_device_desc *devpage) -{ - struct mic_device_ctrl *dc; - - dc = (void *)devpage + mic_aligned_desc_size(devpage); - - dc->config_change = 0; - dc->guest_ack = 0; - dc->vdev_reset = 0; - dc->host_ack = 0; - dc->used_address_updated = 0; - dc->c2h_vdev_db = -1; - dc->h2c_vdev_db = -1; - mvdev->dc = dc; -} - -int mic_virtio_add_device(struct mic_vdev *mvdev, - void __user *argp) -{ - struct mic_device *mdev = mvdev->mdev; - struct mic_device_desc *dd = NULL; - struct mic_vqconfig *vqconfig; - int vr_size, i, j, ret; - u8 type = 0; - s8 db; - char irqname[10]; - struct mic_bootparam *bootparam = mdev->dp; - u16 num; - dma_addr_t vr_addr; - - mutex_lock(&mdev->mic_mutex); - - ret = mic_copy_dp_entry(mvdev, argp, &type, &dd); - if (ret) { - mutex_unlock(&mdev->mic_mutex); - return ret; - } - - mic_init_device_ctrl(mvdev, dd); - - mvdev->dd = dd; - mvdev->virtio_id = type; - vqconfig = mic_vq_config(dd); - INIT_WORK(&mvdev->virtio_bh_work, mic_bh_handler); - - for (i = 0; i < dd->num_vq; i++) { - struct mic_vringh *mvr = &mvdev->mvr[i]; - struct mic_vring *vr = &mvdev->mvr[i].vring; - num = le16_to_cpu(vqconfig[i].num); - mutex_init(&mvr->vr_mutex); - vr_size = PAGE_ALIGN(vring_size(num, MIC_VIRTIO_RING_ALIGN) + - sizeof(struct _mic_vring_info)); - vr->va = (void *) - __get_free_pages(GFP_KERNEL | __GFP_ZERO, - get_order(vr_size)); - if (!vr->va) { - ret = -ENOMEM; - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, ret); - goto err; - } - vr->len = vr_size; - vr->info = vr->va + vring_size(num, MIC_VIRTIO_RING_ALIGN); - vr->info->magic = cpu_to_le32(MIC_MAGIC + mvdev->virtio_id + i); - vr_addr = mic_map_single(mdev, vr->va, vr_size); - if (mic_map_error(vr_addr)) { - free_pages((unsigned long)vr->va, get_order(vr_size)); - ret = -ENOMEM; - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, ret); - goto err; - } - vqconfig[i].address = cpu_to_le64(vr_addr); - - vring_init(&vr->vr, num, vr->va, MIC_VIRTIO_RING_ALIGN); - ret = vringh_init_kern(&mvr->vrh, - *(u32 *)mic_vq_features(mvdev->dd), num, false, - vr->vr.desc, vr->vr.avail, vr->vr.used); - if (ret) { - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, ret); - goto err; - } - vringh_kiov_init(&mvr->riov, NULL, 0); - vringh_kiov_init(&mvr->wiov, NULL, 0); - mvr->head = USHRT_MAX; - mvr->mvdev = mvdev; - mvr->vrh.notify = mic_notify; - dev_dbg(&mdev->pdev->dev, - "%s %d index %d va %p info %p vr_size 0x%x\n", - __func__, __LINE__, i, vr->va, vr->info, vr_size); - mvr->buf = (void *)__get_free_pages(GFP_KERNEL, - get_order(MIC_INT_DMA_BUF_SIZE)); - mvr->buf_da = mic_map_single(mvdev->mdev, mvr->buf, - MIC_INT_DMA_BUF_SIZE); - } - - snprintf(irqname, sizeof(irqname), "mic%dvirtio%d", mdev->id, - mvdev->virtio_id); - mvdev->virtio_db = mic_next_db(mdev); - mvdev->virtio_cookie = mic_request_threaded_irq(mdev, - mic_virtio_intr_handler, - NULL, irqname, mvdev, - mvdev->virtio_db, MIC_INTR_DB); - if (IS_ERR(mvdev->virtio_cookie)) { - ret = PTR_ERR(mvdev->virtio_cookie); - dev_dbg(&mdev->pdev->dev, "request irq failed\n"); - goto err; - } - - mvdev->dc->c2h_vdev_db = mvdev->virtio_db; - - list_add_tail(&mvdev->list, &mdev->vdev_list); - /* - * Order the type update with previous stores. This write barrier - * is paired with the corresponding read barrier before the uncached - * system memory read of the type, on the card while scanning the - * device page. - */ - smp_wmb(); - dd->type = type; - - dev_dbg(&mdev->pdev->dev, "Added virtio device id %d\n", dd->type); - - db = bootparam->h2c_config_db; - if (db != -1) - mdev->ops->send_intr(mdev, db); - mutex_unlock(&mdev->mic_mutex); - return 0; -err: - vqconfig = mic_vq_config(dd); - for (j = 0; j < i; j++) { - struct mic_vringh *mvr = &mvdev->mvr[j]; - mic_unmap_single(mdev, le64_to_cpu(vqconfig[j].address), - mvr->vring.len); - free_pages((unsigned long)mvr->vring.va, - get_order(mvr->vring.len)); - } - mutex_unlock(&mdev->mic_mutex); - return ret; -} - -void mic_virtio_del_device(struct mic_vdev *mvdev) -{ - struct list_head *pos, *tmp; - struct mic_vdev *tmp_mvdev; - struct mic_device *mdev = mvdev->mdev; - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); - int i, ret, retry; - struct mic_vqconfig *vqconfig; - struct mic_bootparam *bootparam = mdev->dp; - s8 db; - - mutex_lock(&mdev->mic_mutex); - db = bootparam->h2c_config_db; - if (db == -1) - goto skip_hot_remove; - dev_dbg(&mdev->pdev->dev, - "Requesting hot remove id %d\n", mvdev->virtio_id); - mvdev->dc->config_change = MIC_VIRTIO_PARAM_DEV_REMOVE; - mdev->ops->send_intr(mdev, db); - for (retry = 100; retry--;) { - ret = wait_event_timeout(wake, - mvdev->dc->guest_ack, msecs_to_jiffies(100)); - if (ret) - break; - } - dev_dbg(&mdev->pdev->dev, - "Device id %d config_change %d guest_ack %d retry %d\n", - mvdev->virtio_id, mvdev->dc->config_change, - mvdev->dc->guest_ack, retry); - mvdev->dc->config_change = 0; - mvdev->dc->guest_ack = 0; -skip_hot_remove: - mic_free_irq(mdev, mvdev->virtio_cookie, mvdev); - flush_work(&mvdev->virtio_bh_work); - vqconfig = mic_vq_config(mvdev->dd); - for (i = 0; i < mvdev->dd->num_vq; i++) { - struct mic_vringh *mvr = &mvdev->mvr[i]; - - mic_unmap_single(mvdev->mdev, mvr->buf_da, - MIC_INT_DMA_BUF_SIZE); - free_pages((unsigned long)mvr->buf, - get_order(MIC_INT_DMA_BUF_SIZE)); - vringh_kiov_cleanup(&mvr->riov); - vringh_kiov_cleanup(&mvr->wiov); - mic_unmap_single(mdev, le64_to_cpu(vqconfig[i].address), - mvr->vring.len); - free_pages((unsigned long)mvr->vring.va, - get_order(mvr->vring.len)); - } - - list_for_each_safe(pos, tmp, &mdev->vdev_list) { - tmp_mvdev = list_entry(pos, struct mic_vdev, list); - if (tmp_mvdev == mvdev) { - list_del(pos); - dev_dbg(&mdev->pdev->dev, - "Removing virtio device id %d\n", - mvdev->virtio_id); - break; - } - } - /* - * Order the type update with previous stores. This write barrier - * is paired with the corresponding read barrier before the uncached - * system memory read of the type, on the card while scanning the - * device page. - */ - smp_wmb(); - mvdev->dd->type = -1; - mutex_unlock(&mdev->mic_mutex); -} diff --git a/drivers/misc/mic/host/mic_virtio.h b/drivers/misc/mic/host/mic_virtio.h deleted file mode 100644 index a80631f2790d..000000000000 --- a/drivers/misc/mic/host/mic_virtio.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Intel MIC Platform Software Stack (MPSS) - * - * Copyright(c) 2013 Intel Corporation. - * - * 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. - * - * 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. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Intel MIC Host driver. - * - */ -#ifndef MIC_VIRTIO_H -#define MIC_VIRTIO_H - -#include -#include - -/* - * Note on endianness. - * 1. Host can be both BE or LE - * 2. Guest/card is LE. Host uses le_to_cpu to access desc/avail - * rings and ioreadXX/iowriteXX to access used ring. - * 3. Device page exposed by host to guest contains LE values. Guest - * accesses these using ioreadXX/iowriteXX etc. This way in general we - * obey the virtio spec according to which guest works with native - * endianness and host is aware of guest endianness and does all - * required endianness conversion. - * 4. Data provided from user space to guest (in ADD_DEVICE and - * CONFIG_CHANGE ioctl's) is not interpreted by the driver and should be - * in guest endianness. - */ - -/** - * struct mic_vringh - Virtio ring host information. - * - * @vring: The MIC vring used for setting up user space mappings. - * @vrh: The host VRINGH used for accessing the card vrings. - * @riov: The VRINGH read kernel IOV. - * @wiov: The VRINGH write kernel IOV. - * @vr_mutex: Mutex for synchronizing access to the VRING. - * @buf: Temporary kernel buffer used to copy in/out data - * from/to the card via DMA. - * @buf_da: dma address of buf. - * @mvdev: Back pointer to MIC virtio device for vringh_notify(..). - * @head: The VRINGH head index address passed to vringh_getdesc_kern(..). - */ -struct mic_vringh { - struct mic_vring vring; - struct vringh vrh; - struct vringh_kiov riov; - struct vringh_kiov wiov; - struct mutex vr_mutex; - void *buf; - dma_addr_t buf_da; - struct mic_vdev *mvdev; - u16 head; -}; - -/** - * struct mic_vdev - Host information for a card Virtio device. - * - * @virtio_id - Virtio device id. - * @waitq - Waitqueue to allow ring3 apps to poll. - * @mdev - Back pointer to host MIC device. - * @poll_wake - Used for waking up threads blocked in poll. - * @out_bytes - Debug stats for number of bytes copied from host to card. - * @in_bytes - Debug stats for number of bytes copied from card to host. - * @out_bytes_dma - Debug stats for number of bytes copied from host to card - * using DMA. - * @in_bytes_dma - Debug stats for number of bytes copied from card to host - * using DMA. - * @tx_len_unaligned - Debug stats for number of bytes copied to the card where - * the transfer length did not have the required DMA alignment. - * @tx_dst_unaligned - Debug stats for number of bytes copied where the - * destination address on the card did not have the required DMA alignment. - * @mvr - Store per VRING data structures. - * @virtio_bh_work - Work struct used to schedule virtio bottom half handling. - * @dd - Virtio device descriptor. - * @dc - Virtio device control fields. - * @list - List of Virtio devices. - * @virtio_db - The doorbell used by the card to interrupt the host. - * @virtio_cookie - The cookie returned while requesting interrupts. - */ -struct mic_vdev { - int virtio_id; - wait_queue_head_t waitq; - struct mic_device *mdev; - int poll_wake; - unsigned long out_bytes; - unsigned long in_bytes; - unsigned long out_bytes_dma; - unsigned long in_bytes_dma; - unsigned long tx_len_unaligned; - unsigned long tx_dst_unaligned; - struct mic_vringh mvr[MIC_MAX_VRINGS]; - struct work_struct virtio_bh_work; - struct mic_device_desc *dd; - struct mic_device_ctrl *dc; - struct list_head list; - int virtio_db; - struct mic_irq *virtio_cookie; -}; - -void mic_virtio_uninit(struct mic_device *mdev); -int mic_virtio_add_device(struct mic_vdev *mvdev, - void __user *argp); -void mic_virtio_del_device(struct mic_vdev *mvdev); -int mic_virtio_config_change(struct mic_vdev *mvdev, - void __user *argp); -int mic_virtio_copy_desc(struct mic_vdev *mvdev, - struct mic_copy_desc *request); -void mic_virtio_reset_devices(struct mic_device *mdev); -void mic_bh_handler(struct work_struct *work); - -/* Helper API to obtain the MIC PCIe device */ -static inline struct device *mic_dev(struct mic_vdev *mvdev) -{ - return &mvdev->mdev->pdev->dev; -} - -/* Helper API to check if a virtio device is initialized */ -static inline int mic_vdev_inited(struct mic_vdev *mvdev) -{ - /* Device has not been created yet */ - if (!mvdev->dd || !mvdev->dd->type) { - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, -EINVAL); - return -EINVAL; - } - - /* Device has been removed/deleted */ - if (mvdev->dd->type == -1) { - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, -ENODEV); - return -ENODEV; - } - - return 0; -} - -/* Helper API to check if a virtio device is running */ -static inline bool mic_vdevup(struct mic_vdev *mvdev) -{ - return !!mvdev->dd->status; -} -#endif -- cgit v1.2.3 From b73c295833cc660c1acdf2601920e2abdb6a29c8 Mon Sep 17 00:00:00 2001 From: Sudeep Dutt Date: Mon, 8 Feb 2016 15:48:12 -0800 Subject: misc: mic: Remove MIC X100 card virtio functionality This patch deletes the virtio functionality from the MIC X100 card driver. A subsequent patch will re-enable this functionality by consolidating the hardware independent logic in a new Virtio over PCIe (VOP) driver. Reviewed-by: Ashutosh Dixit Signed-off-by: Sudeep Dutt Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/card/Makefile | 1 - drivers/misc/mic/card/mic_device.c | 9 +- drivers/misc/mic/card/mic_virtio.c | 634 ------------------------------------- drivers/misc/mic/card/mic_virtio.h | 76 ----- 4 files changed, 1 insertion(+), 719 deletions(-) delete mode 100644 drivers/misc/mic/card/mic_virtio.c delete mode 100644 drivers/misc/mic/card/mic_virtio.h (limited to 'drivers') diff --git a/drivers/misc/mic/card/Makefile b/drivers/misc/mic/card/Makefile index 69d58bef92ce..6e9675e12a09 100644 --- a/drivers/misc/mic/card/Makefile +++ b/drivers/misc/mic/card/Makefile @@ -8,4 +8,3 @@ obj-$(CONFIG_INTEL_MIC_CARD) += mic_card.o mic_card-y += mic_x100.o mic_card-y += mic_device.o mic_card-y += mic_debugfs.o -mic_card-y += mic_virtio.o diff --git a/drivers/misc/mic/card/mic_device.c b/drivers/misc/mic/card/mic_device.c index d0edaf7e0cd5..ff03c633541c 100644 --- a/drivers/misc/mic/card/mic_device.c +++ b/drivers/misc/mic/card/mic_device.c @@ -34,7 +34,6 @@ #include #include "../common/mic_dev.h" #include "mic_device.h" -#include "mic_virtio.h" static struct mic_driver *g_drv; @@ -309,9 +308,6 @@ int __init mic_driver_init(struct mic_driver *mdrv) rc = -ENODEV; goto irq_uninit; } - rc = mic_devices_init(mdrv); - if (rc) - goto dma_free; bootparam = mdrv->dp; node_id = ioread8(&bootparam->node_id); mdrv->scdev = scif_register_device(mdrv->dev, MIC_SCIF_DEV, @@ -321,13 +317,11 @@ int __init mic_driver_init(struct mic_driver *mdrv) mdrv->num_dma_ch, true); if (IS_ERR(mdrv->scdev)) { rc = PTR_ERR(mdrv->scdev); - goto device_uninit; + goto dma_free; } mic_create_card_debug_dir(mdrv); done: return rc; -device_uninit: - mic_devices_uninit(mdrv); dma_free: mic_free_dma_chans(mdrv); irq_uninit: @@ -348,7 +342,6 @@ void mic_driver_uninit(struct mic_driver *mdrv) { mic_delete_card_debug_dir(mdrv); scif_unregister_device(mdrv->scdev); - mic_devices_uninit(mdrv); mic_free_dma_chans(mdrv); mic_uninit_irq(); mic_dp_uninit(); diff --git a/drivers/misc/mic/card/mic_virtio.c b/drivers/misc/mic/card/mic_virtio.c deleted file mode 100644 index 17764b2fbee5..000000000000 --- a/drivers/misc/mic/card/mic_virtio.c +++ /dev/null @@ -1,634 +0,0 @@ -/* - * Intel MIC Platform Software Stack (MPSS) - * - * Copyright(c) 2013 Intel Corporation. - * - * 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. - * - * 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. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Disclaimer: The codes contained in these modules may be specific to - * the Intel Software Development Platform codenamed: Knights Ferry, and - * the Intel product codenamed: Knights Corner, and are not backward - * compatible with other Intel products. Additionally, Intel will NOT - * support the codes or instruction set in future products. - * - * Adapted from: - * - * virtio for kvm on s390 - * - * Copyright IBM Corp. 2008 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License (version 2 only) - * as published by the Free Software Foundation. - * - * Author(s): Christian Borntraeger - * - * Intel MIC Card driver. - * - */ -#include -#include -#include - -#include "../common/mic_dev.h" -#include "mic_virtio.h" - -#define VIRTIO_SUBCODE_64 0x0D00 - -#define MIC_MAX_VRINGS 4 -struct mic_vdev { - struct virtio_device vdev; - struct mic_device_desc __iomem *desc; - struct mic_device_ctrl __iomem *dc; - struct mic_device *mdev; - void __iomem *vr[MIC_MAX_VRINGS]; - int used_size[MIC_MAX_VRINGS]; - struct completion reset_done; - struct mic_irq *virtio_cookie; - int c2h_vdev_db; -}; - -static struct mic_irq *virtio_config_cookie; -#define to_micvdev(vd) container_of(vd, struct mic_vdev, vdev) - -/* Helper API to obtain the parent of the virtio device */ -static inline struct device *mic_dev(struct mic_vdev *mvdev) -{ - return mvdev->vdev.dev.parent; -} - -/* This gets the device's feature bits. */ -static u64 mic_get_features(struct virtio_device *vdev) -{ - unsigned int i, bits; - u32 features = 0; - struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc; - u8 __iomem *in_features = mic_vq_features(desc); - int feature_len = ioread8(&desc->feature_len); - - bits = min_t(unsigned, feature_len, sizeof(features)) * 8; - for (i = 0; i < bits; i++) - if (ioread8(&in_features[i / 8]) & (BIT(i % 8))) - features |= BIT(i); - - return features; -} - -static int mic_finalize_features(struct virtio_device *vdev) -{ - unsigned int i, bits; - struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc; - u8 feature_len = ioread8(&desc->feature_len); - /* Second half of bitmap is features we accept. */ - u8 __iomem *out_features = - mic_vq_features(desc) + feature_len; - - /* Give virtio_ring a chance to accept features. */ - vring_transport_features(vdev); - - /* Make sure we don't have any features > 32 bits! */ - BUG_ON((u32)vdev->features != vdev->features); - - memset_io(out_features, 0, feature_len); - bits = min_t(unsigned, feature_len, - sizeof(vdev->features)) * 8; - for (i = 0; i < bits; i++) { - if (__virtio_test_bit(vdev, i)) - iowrite8(ioread8(&out_features[i / 8]) | (1 << (i % 8)), - &out_features[i / 8]); - } - - return 0; -} - -/* - * Reading and writing elements in config space - */ -static void mic_get(struct virtio_device *vdev, unsigned int offset, - void *buf, unsigned len) -{ - struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc; - - if (offset + len > ioread8(&desc->config_len)) - return; - memcpy_fromio(buf, mic_vq_configspace(desc) + offset, len); -} - -static void mic_set(struct virtio_device *vdev, unsigned int offset, - const void *buf, unsigned len) -{ - struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc; - - if (offset + len > ioread8(&desc->config_len)) - return; - memcpy_toio(mic_vq_configspace(desc) + offset, buf, len); -} - -/* - * The operations to get and set the status word just access the status - * field of the device descriptor. set_status also interrupts the host - * to tell about status changes. - */ -static u8 mic_get_status(struct virtio_device *vdev) -{ - return ioread8(&to_micvdev(vdev)->desc->status); -} - -static void mic_set_status(struct virtio_device *vdev, u8 status) -{ - struct mic_vdev *mvdev = to_micvdev(vdev); - if (!status) - return; - iowrite8(status, &mvdev->desc->status); - mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db); -} - -/* Inform host on a virtio device reset and wait for ack from host */ -static void mic_reset_inform_host(struct virtio_device *vdev) -{ - struct mic_vdev *mvdev = to_micvdev(vdev); - struct mic_device_ctrl __iomem *dc = mvdev->dc; - int retry; - - iowrite8(0, &dc->host_ack); - iowrite8(1, &dc->vdev_reset); - mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db); - - /* Wait till host completes all card accesses and acks the reset */ - for (retry = 100; retry--;) { - if (ioread8(&dc->host_ack)) - break; - msleep(100); - }; - - dev_dbg(mic_dev(mvdev), "%s: retry: %d\n", __func__, retry); - - /* Reset status to 0 in case we timed out */ - iowrite8(0, &mvdev->desc->status); -} - -static void mic_reset(struct virtio_device *vdev) -{ - struct mic_vdev *mvdev = to_micvdev(vdev); - - dev_dbg(mic_dev(mvdev), "%s: virtio id %d\n", - __func__, vdev->id.device); - - mic_reset_inform_host(vdev); - complete_all(&mvdev->reset_done); -} - -/* - * The virtio_ring code calls this API when it wants to notify the Host. - */ -static bool mic_notify(struct virtqueue *vq) -{ - struct mic_vdev *mvdev = vq->priv; - - mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db); - return true; -} - -static void mic_del_vq(struct virtqueue *vq, int n) -{ - struct mic_vdev *mvdev = to_micvdev(vq->vdev); - struct vring *vr = (struct vring *)(vq + 1); - - free_pages((unsigned long) vr->used, get_order(mvdev->used_size[n])); - vring_del_virtqueue(vq); - mic_card_unmap(mvdev->mdev, mvdev->vr[n]); - mvdev->vr[n] = NULL; -} - -static void mic_del_vqs(struct virtio_device *vdev) -{ - struct mic_vdev *mvdev = to_micvdev(vdev); - struct virtqueue *vq, *n; - int idx = 0; - - dev_dbg(mic_dev(mvdev), "%s\n", __func__); - - list_for_each_entry_safe(vq, n, &vdev->vqs, list) - mic_del_vq(vq, idx++); -} - -/* - * This routine will assign vring's allocated in host/io memory. Code in - * virtio_ring.c however continues to access this io memory as if it were local - * memory without io accessors. - */ -static struct virtqueue *mic_find_vq(struct virtio_device *vdev, - unsigned index, - void (*callback)(struct virtqueue *vq), - const char *name) -{ - struct mic_vdev *mvdev = to_micvdev(vdev); - struct mic_vqconfig __iomem *vqconfig; - struct mic_vqconfig config; - struct virtqueue *vq; - void __iomem *va; - struct _mic_vring_info __iomem *info; - void *used; - int vr_size, _vr_size, err, magic; - struct vring *vr; - u8 type = ioread8(&mvdev->desc->type); - - if (index >= ioread8(&mvdev->desc->num_vq)) - return ERR_PTR(-ENOENT); - - if (!name) - return ERR_PTR(-ENOENT); - - /* First assign the vring's allocated in host memory */ - vqconfig = mic_vq_config(mvdev->desc) + index; - memcpy_fromio(&config, vqconfig, sizeof(config)); - _vr_size = vring_size(le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN); - vr_size = PAGE_ALIGN(_vr_size + sizeof(struct _mic_vring_info)); - va = mic_card_map(mvdev->mdev, le64_to_cpu(config.address), vr_size); - if (!va) - return ERR_PTR(-ENOMEM); - mvdev->vr[index] = va; - memset_io(va, 0x0, _vr_size); - vq = vring_new_virtqueue(index, le16_to_cpu(config.num), - MIC_VIRTIO_RING_ALIGN, vdev, false, - (void __force *)va, mic_notify, callback, - name); - if (!vq) { - err = -ENOMEM; - goto unmap; - } - info = va + _vr_size; - magic = ioread32(&info->magic); - - if (WARN(magic != MIC_MAGIC + type + index, "magic mismatch")) { - err = -EIO; - goto unmap; - } - - /* Allocate and reassign used ring now */ - mvdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 + - sizeof(struct vring_used_elem) * - le16_to_cpu(config.num)); - used = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, - get_order(mvdev->used_size[index])); - if (!used) { - err = -ENOMEM; - dev_err(mic_dev(mvdev), "%s %d err %d\n", - __func__, __LINE__, err); - goto del_vq; - } - iowrite64(virt_to_phys(used), &vqconfig->used_address); - - /* - * To reassign the used ring here we are directly accessing - * struct vring_virtqueue which is a private data structure - * in virtio_ring.c. At the minimum, a BUILD_BUG_ON() in - * vring_new_virtqueue() would ensure that - * (&vq->vring == (struct vring *) (&vq->vq + 1)); - */ - vr = (struct vring *)(vq + 1); - vr->used = used; - - vq->priv = mvdev; - return vq; -del_vq: - vring_del_virtqueue(vq); -unmap: - mic_card_unmap(mvdev->mdev, mvdev->vr[index]); - return ERR_PTR(err); -} - -static int mic_find_vqs(struct virtio_device *vdev, unsigned nvqs, - struct virtqueue *vqs[], - vq_callback_t *callbacks[], - const char * const names[]) -{ - struct mic_vdev *mvdev = to_micvdev(vdev); - struct mic_device_ctrl __iomem *dc = mvdev->dc; - int i, err, retry; - - /* We must have this many virtqueues. */ - if (nvqs > ioread8(&mvdev->desc->num_vq)) - return -ENOENT; - - for (i = 0; i < nvqs; ++i) { - dev_dbg(mic_dev(mvdev), "%s: %d: %s\n", - __func__, i, names[i]); - vqs[i] = mic_find_vq(vdev, i, callbacks[i], names[i]); - if (IS_ERR(vqs[i])) { - err = PTR_ERR(vqs[i]); - goto error; - } - } - - iowrite8(1, &dc->used_address_updated); - /* - * Send an interrupt to the host to inform it that used - * rings have been re-assigned. - */ - mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db); - for (retry = 100; --retry;) { - if (!ioread8(&dc->used_address_updated)) - break; - msleep(100); - }; - - dev_dbg(mic_dev(mvdev), "%s: retry: %d\n", __func__, retry); - if (!retry) { - err = -ENODEV; - goto error; - } - - return 0; -error: - mic_del_vqs(vdev); - return err; -} - -/* - * The config ops structure as defined by virtio config - */ -static struct virtio_config_ops mic_vq_config_ops = { - .get_features = mic_get_features, - .finalize_features = mic_finalize_features, - .get = mic_get, - .set = mic_set, - .get_status = mic_get_status, - .set_status = mic_set_status, - .reset = mic_reset, - .find_vqs = mic_find_vqs, - .del_vqs = mic_del_vqs, -}; - -static irqreturn_t -mic_virtio_intr_handler(int irq, void *data) -{ - struct mic_vdev *mvdev = data; - struct virtqueue *vq; - - mic_ack_interrupt(mvdev->mdev); - list_for_each_entry(vq, &mvdev->vdev.vqs, list) - vring_interrupt(0, vq); - - return IRQ_HANDLED; -} - -static void mic_virtio_release_dev(struct device *_d) -{ - /* - * No need for a release method similar to virtio PCI. - * Provide an empty one to avoid getting a warning from core. - */ -} - -/* - * adds a new device and register it with virtio - * appropriate drivers are loaded by the device model - */ -static int mic_add_device(struct mic_device_desc __iomem *d, - unsigned int offset, struct mic_driver *mdrv) -{ - struct mic_vdev *mvdev; - int ret; - int virtio_db; - u8 type = ioread8(&d->type); - - mvdev = kzalloc(sizeof(*mvdev), GFP_KERNEL); - if (!mvdev) { - dev_err(mdrv->dev, "Cannot allocate mic dev %u type %u\n", - offset, type); - return -ENOMEM; - } - - mvdev->mdev = &mdrv->mdev; - mvdev->vdev.dev.parent = mdrv->dev; - mvdev->vdev.dev.release = mic_virtio_release_dev; - mvdev->vdev.id.device = type; - mvdev->vdev.config = &mic_vq_config_ops; - mvdev->desc = d; - mvdev->dc = (void __iomem *)d + mic_aligned_desc_size(d); - init_completion(&mvdev->reset_done); - - virtio_db = mic_next_card_db(); - mvdev->virtio_cookie = mic_request_card_irq(mic_virtio_intr_handler, - NULL, "virtio intr", mvdev, virtio_db); - if (IS_ERR(mvdev->virtio_cookie)) { - ret = PTR_ERR(mvdev->virtio_cookie); - goto kfree; - } - iowrite8((u8)virtio_db, &mvdev->dc->h2c_vdev_db); - mvdev->c2h_vdev_db = ioread8(&mvdev->dc->c2h_vdev_db); - - ret = register_virtio_device(&mvdev->vdev); - if (ret) { - dev_err(mic_dev(mvdev), - "Failed to register mic device %u type %u\n", - offset, type); - goto free_irq; - } - iowrite64((u64)mvdev, &mvdev->dc->vdev); - dev_dbg(mic_dev(mvdev), "%s: registered mic device %u type %u mvdev %p\n", - __func__, offset, type, mvdev); - - return 0; - -free_irq: - mic_free_card_irq(mvdev->virtio_cookie, mvdev); -kfree: - kfree(mvdev); - return ret; -} - -/* - * match for a mic device with a specific desc pointer - */ -static int mic_match_desc(struct device *dev, void *data) -{ - struct virtio_device *vdev = dev_to_virtio(dev); - struct mic_vdev *mvdev = to_micvdev(vdev); - - return mvdev->desc == (void __iomem *)data; -} - -static void mic_handle_config_change(struct mic_device_desc __iomem *d, - unsigned int offset, struct mic_driver *mdrv) -{ - struct mic_device_ctrl __iomem *dc - = (void __iomem *)d + mic_aligned_desc_size(d); - struct mic_vdev *mvdev = (struct mic_vdev *)ioread64(&dc->vdev); - - if (ioread8(&dc->config_change) != MIC_VIRTIO_PARAM_CONFIG_CHANGED) - return; - - dev_dbg(mdrv->dev, "%s %d\n", __func__, __LINE__); - virtio_config_changed(&mvdev->vdev); - iowrite8(1, &dc->guest_ack); -} - -/* - * removes a virtio device if a hot remove event has been - * requested by the host. - */ -static int mic_remove_device(struct mic_device_desc __iomem *d, - unsigned int offset, struct mic_driver *mdrv) -{ - struct mic_device_ctrl __iomem *dc - = (void __iomem *)d + mic_aligned_desc_size(d); - struct mic_vdev *mvdev = (struct mic_vdev *)ioread64(&dc->vdev); - u8 status; - int ret = -1; - - if (ioread8(&dc->config_change) == MIC_VIRTIO_PARAM_DEV_REMOVE) { - dev_dbg(mdrv->dev, - "%s %d config_change %d type %d mvdev %p\n", - __func__, __LINE__, - ioread8(&dc->config_change), ioread8(&d->type), mvdev); - - status = ioread8(&d->status); - reinit_completion(&mvdev->reset_done); - unregister_virtio_device(&mvdev->vdev); - mic_free_card_irq(mvdev->virtio_cookie, mvdev); - if (status & VIRTIO_CONFIG_S_DRIVER_OK) - wait_for_completion(&mvdev->reset_done); - kfree(mvdev); - iowrite8(1, &dc->guest_ack); - dev_dbg(mdrv->dev, "%s %d guest_ack %d\n", - __func__, __LINE__, ioread8(&dc->guest_ack)); - ret = 0; - } - - return ret; -} - -#define REMOVE_DEVICES true - -static void mic_scan_devices(struct mic_driver *mdrv, bool remove) -{ - s8 type; - unsigned int i; - struct mic_device_desc __iomem *d; - struct mic_device_ctrl __iomem *dc; - struct device *dev; - int ret; - - for (i = sizeof(struct mic_bootparam); i < MIC_DP_SIZE; - i += mic_total_desc_size(d)) { - d = mdrv->dp + i; - dc = (void __iomem *)d + mic_aligned_desc_size(d); - /* - * This read barrier is paired with the corresponding write - * barrier on the host which is inserted before adding or - * removing a virtio device descriptor, by updating the type. - */ - rmb(); - type = ioread8(&d->type); - - /* end of list */ - if (type == 0) - break; - - if (type == -1) - continue; - - /* device already exists */ - dev = device_find_child(mdrv->dev, (void __force *)d, - mic_match_desc); - if (dev) { - if (remove) - iowrite8(MIC_VIRTIO_PARAM_DEV_REMOVE, - &dc->config_change); - put_device(dev); - mic_handle_config_change(d, i, mdrv); - ret = mic_remove_device(d, i, mdrv); - if (!ret && !remove) - iowrite8(-1, &d->type); - if (remove) { - iowrite8(0, &dc->config_change); - iowrite8(0, &dc->guest_ack); - } - continue; - } - - /* new device */ - dev_dbg(mdrv->dev, "%s %d Adding new virtio device %p\n", - __func__, __LINE__, d); - if (!remove) - mic_add_device(d, i, mdrv); - } -} - -/* - * mic_hotplug_device tries to find changes in the device page. - */ -static void mic_hotplug_devices(struct work_struct *work) -{ - struct mic_driver *mdrv = container_of(work, - struct mic_driver, hotplug_work); - - mic_scan_devices(mdrv, !REMOVE_DEVICES); -} - -/* - * Interrupt handler for hot plug/config changes etc. - */ -static irqreturn_t -mic_extint_handler(int irq, void *data) -{ - struct mic_driver *mdrv = (struct mic_driver *)data; - - dev_dbg(mdrv->dev, "%s %d hotplug work\n", - __func__, __LINE__); - mic_ack_interrupt(&mdrv->mdev); - schedule_work(&mdrv->hotplug_work); - return IRQ_HANDLED; -} - -/* - * Init function for virtio - */ -int mic_devices_init(struct mic_driver *mdrv) -{ - int rc; - struct mic_bootparam __iomem *bootparam; - int config_db; - - INIT_WORK(&mdrv->hotplug_work, mic_hotplug_devices); - mic_scan_devices(mdrv, !REMOVE_DEVICES); - - config_db = mic_next_card_db(); - virtio_config_cookie = mic_request_card_irq(mic_extint_handler, NULL, - "virtio_config_intr", mdrv, - config_db); - if (IS_ERR(virtio_config_cookie)) { - rc = PTR_ERR(virtio_config_cookie); - goto exit; - } - - bootparam = mdrv->dp; - iowrite8(config_db, &bootparam->h2c_config_db); - return 0; -exit: - return rc; -} - -/* - * Uninit function for virtio - */ -void mic_devices_uninit(struct mic_driver *mdrv) -{ - struct mic_bootparam __iomem *bootparam = mdrv->dp; - iowrite8(-1, &bootparam->h2c_config_db); - mic_free_card_irq(virtio_config_cookie, mdrv); - flush_work(&mdrv->hotplug_work); - mic_scan_devices(mdrv, REMOVE_DEVICES); -} diff --git a/drivers/misc/mic/card/mic_virtio.h b/drivers/misc/mic/card/mic_virtio.h deleted file mode 100644 index d0407ba53bb7..000000000000 --- a/drivers/misc/mic/card/mic_virtio.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Intel MIC Platform Software Stack (MPSS) - * - * Copyright(c) 2013 Intel Corporation. - * - * 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. - * - * 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. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Disclaimer: The codes contained in these modules may be specific to - * the Intel Software Development Platform codenamed: Knights Ferry, and - * the Intel product codenamed: Knights Corner, and are not backward - * compatible with other Intel products. Additionally, Intel will NOT - * support the codes or instruction set in future products. - * - * Intel MIC Card driver. - * - */ -#ifndef __MIC_CARD_VIRTIO_H -#define __MIC_CARD_VIRTIO_H - -#include -#include "mic_device.h" - -/* - * 64 bit I/O access - */ -#ifndef ioread64 -#define ioread64 readq -#endif -#ifndef iowrite64 -#define iowrite64 writeq -#endif - -static inline unsigned mic_desc_size(struct mic_device_desc __iomem *desc) -{ - return sizeof(*desc) - + ioread8(&desc->num_vq) * sizeof(struct mic_vqconfig) - + ioread8(&desc->feature_len) * 2 - + ioread8(&desc->config_len); -} - -static inline struct mic_vqconfig __iomem * -mic_vq_config(struct mic_device_desc __iomem *desc) -{ - return (struct mic_vqconfig __iomem *)(desc + 1); -} - -static inline __u8 __iomem * -mic_vq_features(struct mic_device_desc __iomem *desc) -{ - return (__u8 __iomem *)(mic_vq_config(desc) + ioread8(&desc->num_vq)); -} - -static inline __u8 __iomem * -mic_vq_configspace(struct mic_device_desc __iomem *desc) -{ - return mic_vq_features(desc) + ioread8(&desc->feature_len) * 2; -} -static inline unsigned mic_total_desc_size(struct mic_device_desc __iomem *desc) -{ - return mic_aligned_desc_size(desc) + sizeof(struct mic_device_ctrl); -} - -int mic_devices_init(struct mic_driver *mdrv); -void mic_devices_uninit(struct mic_driver *mdrv); - -#endif -- cgit v1.2.3 From a19ddd6fd260d6b92de38acb1b87940045697627 Mon Sep 17 00:00:00 2001 From: Sudeep Dutt Date: Mon, 8 Feb 2016 15:48:13 -0800 Subject: misc: mic: MIC VOP Bus The Virtio Over PCIe (VOP) bus abstracts the low level hardware details like interrupts and mapping remote memory so that the same VOP driver can work without changes with different MIC host or card drivers as long as the hardware bus operations are implemented. The VOP driver registers itself on the VOP bus. The base PCIe drivers implement the bus ops and register VOP devices on the bus, resulting in the VOP driver being probed with the VOP devices. This allows the VOP functionality to be shared between multiple generations of Intel MIC products. Reviewed-by: Ashutosh Dixit Signed-off-by: Sudeep Dutt Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/Kconfig | 17 ++++ drivers/misc/mic/bus/Makefile | 1 + drivers/misc/mic/bus/vop_bus.c | 203 +++++++++++++++++++++++++++++++++++++++++ drivers/misc/mic/bus/vop_bus.h | 140 ++++++++++++++++++++++++++++ 4 files changed, 361 insertions(+) create mode 100644 drivers/misc/mic/bus/vop_bus.c create mode 100644 drivers/misc/mic/bus/vop_bus.h (limited to 'drivers') diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig index 40677df7f996..840f7ef1a141 100644 --- a/drivers/misc/mic/Kconfig +++ b/drivers/misc/mic/Kconfig @@ -32,6 +32,23 @@ config SCIF_BUS OS and tools for MIC to use with this driver are available from . +comment "VOP Bus Driver" + +config VOP_BUS + tristate "VOP Bus Driver" + depends on 64BIT && PCI && X86 && X86_DEV_DMA_OPS + help + This option is selected by any driver which registers a + device or driver on the VOP Bus, such as CONFIG_INTEL_MIC_HOST + and CONFIG_INTEL_MIC_CARD. + + If you are building a host/card kernel with an Intel MIC device + then say M (recommended) or Y, else say N. If unsure say N. + + More information about the Intel MIC family as well as the Linux + OS and tools for MIC to use with this driver are available from + . + comment "Intel MIC Host Driver" config INTEL_MIC_HOST diff --git a/drivers/misc/mic/bus/Makefile b/drivers/misc/mic/bus/Makefile index 761842b0d0bb..8758a7daa52c 100644 --- a/drivers/misc/mic/bus/Makefile +++ b/drivers/misc/mic/bus/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_INTEL_MIC_BUS) += mic_bus.o obj-$(CONFIG_SCIF_BUS) += scif_bus.o obj-$(CONFIG_MIC_COSM) += cosm_bus.o +obj-$(CONFIG_VOP_BUS) += vop_bus.o diff --git a/drivers/misc/mic/bus/vop_bus.c b/drivers/misc/mic/bus/vop_bus.c new file mode 100644 index 000000000000..303da222f5b6 --- /dev/null +++ b/drivers/misc/mic/bus/vop_bus.c @@ -0,0 +1,203 @@ +/* + * Intel MIC Platform Software Stack (MPSS) + * + * Copyright(c) 2016 Intel Corporation. + * + * 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. + * + * 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. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Intel Virtio Over PCIe (VOP) Bus driver. + */ +#include +#include +#include +#include + +#include "vop_bus.h" + +static ssize_t device_show(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct vop_device *dev = dev_to_vop(d); + + return sprintf(buf, "0x%04x\n", dev->id.device); +} +static DEVICE_ATTR_RO(device); + +static ssize_t vendor_show(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct vop_device *dev = dev_to_vop(d); + + return sprintf(buf, "0x%04x\n", dev->id.vendor); +} +static DEVICE_ATTR_RO(vendor); + +static ssize_t modalias_show(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct vop_device *dev = dev_to_vop(d); + + return sprintf(buf, "vop:d%08Xv%08X\n", + dev->id.device, dev->id.vendor); +} +static DEVICE_ATTR_RO(modalias); + +static struct attribute *vop_dev_attrs[] = { + &dev_attr_device.attr, + &dev_attr_vendor.attr, + &dev_attr_modalias.attr, + NULL, +}; +ATTRIBUTE_GROUPS(vop_dev); + +static inline int vop_id_match(const struct vop_device *dev, + const struct vop_device_id *id) +{ + if (id->device != dev->id.device && id->device != VOP_DEV_ANY_ID) + return 0; + + return id->vendor == VOP_DEV_ANY_ID || id->vendor == dev->id.vendor; +} + +/* + * This looks through all the IDs a driver claims to support. If any of them + * match, we return 1 and the kernel will call vop_dev_probe(). + */ +static int vop_dev_match(struct device *dv, struct device_driver *dr) +{ + unsigned int i; + struct vop_device *dev = dev_to_vop(dv); + const struct vop_device_id *ids; + + ids = drv_to_vop(dr)->id_table; + for (i = 0; ids[i].device; i++) + if (vop_id_match(dev, &ids[i])) + return 1; + return 0; +} + +static int vop_uevent(struct device *dv, struct kobj_uevent_env *env) +{ + struct vop_device *dev = dev_to_vop(dv); + + return add_uevent_var(env, "MODALIAS=vop:d%08Xv%08X", + dev->id.device, dev->id.vendor); +} + +static int vop_dev_probe(struct device *d) +{ + struct vop_device *dev = dev_to_vop(d); + struct vop_driver *drv = drv_to_vop(dev->dev.driver); + + return drv->probe(dev); +} + +static int vop_dev_remove(struct device *d) +{ + struct vop_device *dev = dev_to_vop(d); + struct vop_driver *drv = drv_to_vop(dev->dev.driver); + + drv->remove(dev); + return 0; +} + +static struct bus_type vop_bus = { + .name = "vop_bus", + .match = vop_dev_match, + .dev_groups = vop_dev_groups, + .uevent = vop_uevent, + .probe = vop_dev_probe, + .remove = vop_dev_remove, +}; + +int vop_register_driver(struct vop_driver *driver) +{ + driver->driver.bus = &vop_bus; + return driver_register(&driver->driver); +} +EXPORT_SYMBOL_GPL(vop_register_driver); + +void vop_unregister_driver(struct vop_driver *driver) +{ + driver_unregister(&driver->driver); +} +EXPORT_SYMBOL_GPL(vop_unregister_driver); + +static void vop_release_dev(struct device *d) +{ + put_device(d); +} + +struct vop_device * +vop_register_device(struct device *pdev, int id, + const struct dma_map_ops *dma_ops, + struct vop_hw_ops *hw_ops, u8 dnode, struct mic_mw *aper, + struct dma_chan *chan) +{ + int ret; + struct vop_device *vdev; + + vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); + if (!vdev) + return ERR_PTR(-ENOMEM); + + vdev->dev.parent = pdev; + vdev->id.device = id; + vdev->id.vendor = VOP_DEV_ANY_ID; + vdev->dev.archdata.dma_ops = (struct dma_map_ops *)dma_ops; + vdev->dev.dma_mask = &vdev->dev.coherent_dma_mask; + dma_set_mask(&vdev->dev, DMA_BIT_MASK(64)); + vdev->dev.release = vop_release_dev; + vdev->hw_ops = hw_ops; + vdev->dev.bus = &vop_bus; + vdev->dnode = dnode; + vdev->aper = aper; + vdev->dma_ch = chan; + vdev->index = dnode - 1; + dev_set_name(&vdev->dev, "vop-dev%u", vdev->index); + /* + * device_register() causes the bus infrastructure to look for a + * matching driver. + */ + ret = device_register(&vdev->dev); + if (ret) + goto free_vdev; + return vdev; +free_vdev: + kfree(vdev); + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(vop_register_device); + +void vop_unregister_device(struct vop_device *dev) +{ + device_unregister(&dev->dev); +} +EXPORT_SYMBOL_GPL(vop_unregister_device); + +static int __init vop_init(void) +{ + return bus_register(&vop_bus); +} + +static void __exit vop_exit(void) +{ + bus_unregister(&vop_bus); +} + +core_initcall(vop_init); +module_exit(vop_exit); + +MODULE_AUTHOR("Intel Corporation"); +MODULE_DESCRIPTION("Intel(R) VOP Bus driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/misc/mic/bus/vop_bus.h b/drivers/misc/mic/bus/vop_bus.h new file mode 100644 index 000000000000..fff7a865d721 --- /dev/null +++ b/drivers/misc/mic/bus/vop_bus.h @@ -0,0 +1,140 @@ +/* + * Intel MIC Platform Software Stack (MPSS) + * + * Copyright(c) 2016 Intel Corporation. + * + * 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. + * + * 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. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Intel Virtio over PCIe Bus driver. + */ +#ifndef _VOP_BUS_H_ +#define _VOP_BUS_H_ +/* + * Everything a vop driver needs to work with any particular vop + * implementation. + */ +#include +#include + +#include "../common/mic_dev.h" + +struct vop_device_id { + u32 device; + u32 vendor; +}; + +#define VOP_DEV_TRNSP 1 +#define VOP_DEV_ANY_ID 0xffffffff +/* + * Size of the internal buffer used during DMA's as an intermediate buffer + * for copy to/from user. Must be an integral number of pages. + */ +#define VOP_INT_DMA_BUF_SIZE PAGE_ALIGN(64 * 1024ULL) + +/** + * vop_device - representation of a device using vop + * @hw_ops: the hardware ops supported by this device. + * @id: the device type identification (used to match it with a driver). + * @dev: underlying device. + * @dnode - The destination node which this device will communicate with. + * @aper: Aperture memory window + * @dma_ch - DMA channel + * @index: unique position on the vop bus + */ +struct vop_device { + struct vop_hw_ops *hw_ops; + struct vop_device_id id; + struct device dev; + u8 dnode; + struct mic_mw *aper; + struct dma_chan *dma_ch; + int index; +}; + +/** + * vop_driver - operations for a vop I/O driver + * @driver: underlying device driver (populate name and owner). + * @id_table: the ids serviced by this driver. + * @probe: the function to call when a device is found. Returns 0 or -errno. + * @remove: the function to call when a device is removed. + */ +struct vop_driver { + struct device_driver driver; + const struct vop_device_id *id_table; + int (*probe)(struct vop_device *dev); + void (*remove)(struct vop_device *dev); +}; + +/** + * vop_hw_ops - Hardware operations for accessing a VOP device on the VOP bus. + * + * @next_db: Obtain the next available doorbell. + * @request_irq: Request an interrupt on a particular doorbell. + * @free_irq: Free an interrupt requested previously. + * @ack_interrupt: acknowledge an interrupt in the ISR. + * @get_remote_dp: Get access to the virtio device page used by the remote + * node to add/remove/configure virtio devices. + * @get_dp: Get access to the virtio device page used by the self + * node to add/remove/configure virtio devices. + * @send_intr: Send an interrupt to the peer node on a specified doorbell. + * @ioremap: Map a buffer with the specified DMA address and length. + * @iounmap: Unmap a buffer previously mapped. + * @dma_filter: The DMA filter function to use for obtaining access to + * a DMA channel on the peer node. + */ +struct vop_hw_ops { + int (*next_db)(struct vop_device *vpdev); + struct mic_irq *(*request_irq)(struct vop_device *vpdev, + irqreturn_t (*func)(int irq, void *data), + const char *name, void *data, + int intr_src); + void (*free_irq)(struct vop_device *vpdev, + struct mic_irq *cookie, void *data); + void (*ack_interrupt)(struct vop_device *vpdev, int num); + void __iomem * (*get_remote_dp)(struct vop_device *vpdev); + void * (*get_dp)(struct vop_device *vpdev); + void (*send_intr)(struct vop_device *vpdev, int db); + void __iomem * (*ioremap)(struct vop_device *vpdev, + dma_addr_t pa, size_t len); + void (*iounmap)(struct vop_device *vpdev, void __iomem *va); +}; + +struct vop_device * +vop_register_device(struct device *pdev, int id, + const struct dma_map_ops *dma_ops, + struct vop_hw_ops *hw_ops, u8 dnode, struct mic_mw *aper, + struct dma_chan *chan); +void vop_unregister_device(struct vop_device *dev); +int vop_register_driver(struct vop_driver *drv); +void vop_unregister_driver(struct vop_driver *drv); + +/* + * module_vop_driver() - Helper macro for drivers that don't do + * anything special in module init/exit. This eliminates a lot of + * boilerplate. Each module may only use this macro once, and + * calling it replaces module_init() and module_exit() + */ +#define module_vop_driver(__vop_driver) \ + module_driver(__vop_driver, vop_register_driver, \ + vop_unregister_driver) + +static inline struct vop_device *dev_to_vop(struct device *dev) +{ + return container_of(dev, struct vop_device, dev); +} + +static inline struct vop_driver *drv_to_vop(struct device_driver *drv) +{ + return container_of(drv, struct vop_driver, driver); +} +#endif /* _VOP_BUS_H */ -- cgit v1.2.3 From 26909e26f4b51a9f7f8838eee775a65563388c0d Mon Sep 17 00:00:00 2001 From: Sudeep Dutt Date: Mon, 8 Feb 2016 15:48:14 -0800 Subject: misc: mic: Add data structures for the VOP driver This patch adds VOP driver data structures used in subsequent patches. These data structures are refactored from similar data structures used in the virtio parts of previous MIC host and card drivers. Signed-off-by: Ashutosh Dixit Signed-off-by: Sudeep Dutt Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/vop/vop_main.h | 170 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 drivers/misc/mic/vop/vop_main.h (limited to 'drivers') diff --git a/drivers/misc/mic/vop/vop_main.h b/drivers/misc/mic/vop/vop_main.h new file mode 100644 index 000000000000..ba47ec7a6386 --- /dev/null +++ b/drivers/misc/mic/vop/vop_main.h @@ -0,0 +1,170 @@ +/* + * Intel MIC Platform Software Stack (MPSS) + * + * Copyright(c) 2016 Intel Corporation. + * + * 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. + * + * 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. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Intel Virtio Over PCIe (VOP) driver. + * + */ +#ifndef _VOP_MAIN_H_ +#define _VOP_MAIN_H_ + +#include +#include +#include +#include + +#include +#include "../common/mic_dev.h" + +#include "../bus/vop_bus.h" + +/* + * Note on endianness. + * 1. Host can be both BE or LE + * 2. Guest/card is LE. Host uses le_to_cpu to access desc/avail + * rings and ioreadXX/iowriteXX to access used ring. + * 3. Device page exposed by host to guest contains LE values. Guest + * accesses these using ioreadXX/iowriteXX etc. This way in general we + * obey the virtio spec according to which guest works with native + * endianness and host is aware of guest endianness and does all + * required endianness conversion. + * 4. Data provided from user space to guest (in ADD_DEVICE and + * CONFIG_CHANGE ioctl's) is not interpreted by the driver and should be + * in guest endianness. + */ + +/* + * vop_info - Allocated per invocation of VOP probe + * + * @vpdev: VOP device + * @hotplug_work: Handle virtio device creation, deletion and configuration + * @cookie: Cookie received upon requesting a virtio configuration interrupt + * @h2c_config_db: The doorbell used by the peer to indicate a config change + * @vdev_list: List of "active" virtio devices injected in the peer node + * @vop_mutex: Synchronize access to the device page as well as serialize + * creation/deletion of virtio devices on the peer node + * @dp: Peer device page information + * @dbg: Debugfs entry + * @dma_ch: The DMA channel used by this transport for data transfers. + * @name: Name for this transport used in misc device creation. + * @miscdev: The misc device registered. + */ +struct vop_info { + struct vop_device *vpdev; + struct work_struct hotplug_work; + struct mic_irq *cookie; + int h2c_config_db; + struct list_head vdev_list; + struct mutex vop_mutex; + void __iomem *dp; + struct dentry *dbg; + struct dma_chan *dma_ch; + char name[16]; + struct miscdevice miscdev; +}; + +/** + * struct vop_vringh - Virtio ring host information. + * + * @vring: The VOP vring used for setting up user space mappings. + * @vrh: The host VRINGH used for accessing the card vrings. + * @riov: The VRINGH read kernel IOV. + * @wiov: The VRINGH write kernel IOV. + * @head: The VRINGH head index address passed to vringh_getdesc_kern(..). + * @vr_mutex: Mutex for synchronizing access to the VRING. + * @buf: Temporary kernel buffer used to copy in/out data + * from/to the card via DMA. + * @buf_da: dma address of buf. + * @vdev: Back pointer to VOP virtio device for vringh_notify(..). + */ +struct vop_vringh { + struct mic_vring vring; + struct vringh vrh; + struct vringh_kiov riov; + struct vringh_kiov wiov; + u16 head; + struct mutex vr_mutex; + void *buf; + dma_addr_t buf_da; + struct vop_vdev *vdev; +}; + +/** + * struct vop_vdev - Host information for a card Virtio device. + * + * @virtio_id - Virtio device id. + * @waitq - Waitqueue to allow ring3 apps to poll. + * @vpdev - pointer to VOP bus device. + * @poll_wake - Used for waking up threads blocked in poll. + * @out_bytes - Debug stats for number of bytes copied from host to card. + * @in_bytes - Debug stats for number of bytes copied from card to host. + * @out_bytes_dma - Debug stats for number of bytes copied from host to card + * using DMA. + * @in_bytes_dma - Debug stats for number of bytes copied from card to host + * using DMA. + * @tx_len_unaligned - Debug stats for number of bytes copied to the card where + * the transfer length did not have the required DMA alignment. + * @tx_dst_unaligned - Debug stats for number of bytes copied where the + * destination address on the card did not have the required DMA alignment. + * @vvr - Store per VRING data structures. + * @virtio_bh_work - Work struct used to schedule virtio bottom half handling. + * @dd - Virtio device descriptor. + * @dc - Virtio device control fields. + * @list - List of Virtio devices. + * @virtio_db - The doorbell used by the card to interrupt the host. + * @virtio_cookie - The cookie returned while requesting interrupts. + * @vi: Transport information. + * @vdev_mutex: Mutex synchronizing virtio device injection, + * removal and data transfers. + * @destroy: Track if a virtio device is being destroyed. + * @deleted: The virtio device has been deleted. + */ +struct vop_vdev { + int virtio_id; + wait_queue_head_t waitq; + struct vop_device *vpdev; + int poll_wake; + unsigned long out_bytes; + unsigned long in_bytes; + unsigned long out_bytes_dma; + unsigned long in_bytes_dma; + unsigned long tx_len_unaligned; + unsigned long tx_dst_unaligned; + unsigned long rx_dst_unaligned; + struct vop_vringh vvr[MIC_MAX_VRINGS]; + struct work_struct virtio_bh_work; + struct mic_device_desc *dd; + struct mic_device_ctrl *dc; + struct list_head list; + int virtio_db; + struct mic_irq *virtio_cookie; + struct vop_info *vi; + struct mutex vdev_mutex; + struct completion destroy; + bool deleted; +}; + +/* Helper API to check if a virtio device is running */ +static inline bool vop_vdevup(struct vop_vdev *vdev) +{ + return !!vdev->dd->status; +} + +void vop_init_debugfs(struct vop_info *vi); +void vop_exit_debugfs(struct vop_info *vi); +int vop_host_init(struct vop_info *vi); +void vop_host_uninit(struct vop_info *vi); +#endif -- cgit v1.2.3 From 61e9c905df78c253752971e200f0ac6d8667dda6 Mon Sep 17 00:00:00 2001 From: Sudeep Dutt Date: Mon, 8 Feb 2016 15:48:15 -0800 Subject: misc: mic: Enable VOP host side functionality This patch moves virtio functionality from the MIC host driver into a separate hardware independent Virtio Over PCIe (VOP) driver. This functionality was introduced in commit f69bcbf3b4c4 ("Intel MIC Host Driver Changes for Virtio Devices.") in drivers/misc/mic/host/mic_virtio.c. Apart from being moved into a separate driver the functionality is essentially unchanged. See the above mentioned commit for a description of this functionality. Signed-off-by: Ashutosh Dixit Signed-off-by: Sudeep Dutt Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/vop/vop_vringh.c | 1164 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1164 insertions(+) create mode 100644 drivers/misc/mic/vop/vop_vringh.c (limited to 'drivers') diff --git a/drivers/misc/mic/vop/vop_vringh.c b/drivers/misc/mic/vop/vop_vringh.c new file mode 100644 index 000000000000..c1dd000f042b --- /dev/null +++ b/drivers/misc/mic/vop/vop_vringh.c @@ -0,0 +1,1164 @@ +/* + * Intel MIC Platform Software Stack (MPSS) + * + * Copyright(c) 2016 Intel Corporation. + * + * 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. + * + * 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. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Intel Virtio Over PCIe (VOP) driver. + * + */ +#include +#include +#include + +#include +#include "../common/mic_dev.h" + +#include +#include "vop_main.h" + +/* Helper API to obtain the VOP PCIe device */ +static inline struct device *vop_dev(struct vop_vdev *vdev) +{ + return vdev->vpdev->dev.parent; +} + +/* Helper API to check if a virtio device is initialized */ +static inline int vop_vdev_inited(struct vop_vdev *vdev) +{ + if (!vdev) + return -EINVAL; + /* Device has not been created yet */ + if (!vdev->dd || !vdev->dd->type) { + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, -EINVAL); + return -EINVAL; + } + /* Device has been removed/deleted */ + if (vdev->dd->type == -1) { + dev_dbg(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, -ENODEV); + return -ENODEV; + } + return 0; +} + +static void _vop_notify(struct vringh *vrh) +{ + struct vop_vringh *vvrh = container_of(vrh, struct vop_vringh, vrh); + struct vop_vdev *vdev = vvrh->vdev; + struct vop_device *vpdev = vdev->vpdev; + s8 db = vdev->dc->h2c_vdev_db; + + if (db != -1) + vpdev->hw_ops->send_intr(vpdev, db); +} + +static void vop_virtio_init_post(struct vop_vdev *vdev) +{ + struct mic_vqconfig *vqconfig = mic_vq_config(vdev->dd); + struct vop_device *vpdev = vdev->vpdev; + int i, used_size; + + for (i = 0; i < vdev->dd->num_vq; i++) { + used_size = PAGE_ALIGN(sizeof(u16) * 3 + + sizeof(struct vring_used_elem) * + le16_to_cpu(vqconfig->num)); + if (!le64_to_cpu(vqconfig[i].used_address)) { + dev_warn(vop_dev(vdev), "used_address zero??\n"); + continue; + } + vdev->vvr[i].vrh.vring.used = + (void __force *)vpdev->hw_ops->ioremap( + vpdev, + le64_to_cpu(vqconfig[i].used_address), + used_size); + } + + vdev->dc->used_address_updated = 0; + + dev_info(vop_dev(vdev), "%s: device type %d LINKUP\n", + __func__, vdev->virtio_id); +} + +static inline void vop_virtio_device_reset(struct vop_vdev *vdev) +{ + int i; + + dev_dbg(vop_dev(vdev), "%s: status %d device type %d RESET\n", + __func__, vdev->dd->status, vdev->virtio_id); + + for (i = 0; i < vdev->dd->num_vq; i++) + /* + * Avoid lockdep false positive. The + 1 is for the vop + * mutex which is held in the reset devices code path. + */ + mutex_lock_nested(&vdev->vvr[i].vr_mutex, i + 1); + + /* 0 status means "reset" */ + vdev->dd->status = 0; + vdev->dc->vdev_reset = 0; + vdev->dc->host_ack = 1; + + for (i = 0; i < vdev->dd->num_vq; i++) { + struct vringh *vrh = &vdev->vvr[i].vrh; + + vdev->vvr[i].vring.info->avail_idx = 0; + vrh->completed = 0; + vrh->last_avail_idx = 0; + vrh->last_used_idx = 0; + } + + for (i = 0; i < vdev->dd->num_vq; i++) + mutex_unlock(&vdev->vvr[i].vr_mutex); +} + +static void vop_virtio_reset_devices(struct vop_info *vi) +{ + struct list_head *pos, *tmp; + struct vop_vdev *vdev; + + list_for_each_safe(pos, tmp, &vi->vdev_list) { + vdev = list_entry(pos, struct vop_vdev, list); + vop_virtio_device_reset(vdev); + vdev->poll_wake = 1; + wake_up(&vdev->waitq); + } +} + +static void vop_bh_handler(struct work_struct *work) +{ + struct vop_vdev *vdev = container_of(work, struct vop_vdev, + virtio_bh_work); + + if (vdev->dc->used_address_updated) + vop_virtio_init_post(vdev); + + if (vdev->dc->vdev_reset) + vop_virtio_device_reset(vdev); + + vdev->poll_wake = 1; + wake_up(&vdev->waitq); +} + +static irqreturn_t _vop_virtio_intr_handler(int irq, void *data) +{ + struct vop_vdev *vdev = data; + struct vop_device *vpdev = vdev->vpdev; + + vpdev->hw_ops->ack_interrupt(vpdev, vdev->virtio_db); + schedule_work(&vdev->virtio_bh_work); + return IRQ_HANDLED; +} + +static int vop_virtio_config_change(struct vop_vdev *vdev, void *argp) +{ + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); + int ret = 0, retry, i; + struct vop_device *vpdev = vdev->vpdev; + struct vop_info *vi = dev_get_drvdata(&vpdev->dev); + struct mic_bootparam *bootparam = vpdev->hw_ops->get_dp(vpdev); + s8 db = bootparam->h2c_config_db; + + mutex_lock(&vi->vop_mutex); + for (i = 0; i < vdev->dd->num_vq; i++) + mutex_lock_nested(&vdev->vvr[i].vr_mutex, i + 1); + + if (db == -1 || vdev->dd->type == -1) { + ret = -EIO; + goto exit; + } + + memcpy(mic_vq_configspace(vdev->dd), argp, vdev->dd->config_len); + vdev->dc->config_change = MIC_VIRTIO_PARAM_CONFIG_CHANGED; + vpdev->hw_ops->send_intr(vpdev, db); + + for (retry = 100; retry--;) { + ret = wait_event_timeout(wake, vdev->dc->guest_ack, + msecs_to_jiffies(100)); + if (ret) + break; + } + + dev_dbg(vop_dev(vdev), + "%s %d retry: %d\n", __func__, __LINE__, retry); + vdev->dc->config_change = 0; + vdev->dc->guest_ack = 0; +exit: + for (i = 0; i < vdev->dd->num_vq; i++) + mutex_unlock(&vdev->vvr[i].vr_mutex); + mutex_unlock(&vi->vop_mutex); + return ret; +} + +static int vop_copy_dp_entry(struct vop_vdev *vdev, + struct mic_device_desc *argp, __u8 *type, + struct mic_device_desc **devpage) +{ + struct vop_device *vpdev = vdev->vpdev; + struct mic_device_desc *devp; + struct mic_vqconfig *vqconfig; + int ret = 0, i; + bool slot_found = false; + + vqconfig = mic_vq_config(argp); + for (i = 0; i < argp->num_vq; i++) { + if (le16_to_cpu(vqconfig[i].num) > MIC_MAX_VRING_ENTRIES) { + ret = -EINVAL; + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, ret); + goto exit; + } + } + + /* Find the first free device page entry */ + for (i = sizeof(struct mic_bootparam); + i < MIC_DP_SIZE - mic_total_desc_size(argp); + i += mic_total_desc_size(devp)) { + devp = vpdev->hw_ops->get_dp(vpdev) + i; + if (devp->type == 0 || devp->type == -1) { + slot_found = true; + break; + } + } + if (!slot_found) { + ret = -EINVAL; + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, ret); + goto exit; + } + /* + * Save off the type before doing the memcpy. Type will be set in the + * end after completing all initialization for the new device. + */ + *type = argp->type; + argp->type = 0; + memcpy(devp, argp, mic_desc_size(argp)); + + *devpage = devp; +exit: + return ret; +} + +static void vop_init_device_ctrl(struct vop_vdev *vdev, + struct mic_device_desc *devpage) +{ + struct mic_device_ctrl *dc; + + dc = (void *)devpage + mic_aligned_desc_size(devpage); + + dc->config_change = 0; + dc->guest_ack = 0; + dc->vdev_reset = 0; + dc->host_ack = 0; + dc->used_address_updated = 0; + dc->c2h_vdev_db = -1; + dc->h2c_vdev_db = -1; + vdev->dc = dc; +} + +static int vop_virtio_add_device(struct vop_vdev *vdev, + struct mic_device_desc *argp) +{ + struct vop_info *vi = vdev->vi; + struct vop_device *vpdev = vi->vpdev; + struct mic_device_desc *dd = NULL; + struct mic_vqconfig *vqconfig; + int vr_size, i, j, ret; + u8 type = 0; + s8 db = -1; + char irqname[16]; + struct mic_bootparam *bootparam; + u16 num; + dma_addr_t vr_addr; + + bootparam = vpdev->hw_ops->get_dp(vpdev); + init_waitqueue_head(&vdev->waitq); + INIT_LIST_HEAD(&vdev->list); + vdev->vpdev = vpdev; + + ret = vop_copy_dp_entry(vdev, argp, &type, &dd); + if (ret) { + kfree(vdev); + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, ret); + return ret; + } + + vop_init_device_ctrl(vdev, dd); + + vdev->dd = dd; + vdev->virtio_id = type; + vqconfig = mic_vq_config(dd); + INIT_WORK(&vdev->virtio_bh_work, vop_bh_handler); + + for (i = 0; i < dd->num_vq; i++) { + struct vop_vringh *vvr = &vdev->vvr[i]; + struct mic_vring *vr = &vdev->vvr[i].vring; + + num = le16_to_cpu(vqconfig[i].num); + mutex_init(&vvr->vr_mutex); + vr_size = PAGE_ALIGN(vring_size(num, MIC_VIRTIO_RING_ALIGN) + + sizeof(struct _mic_vring_info)); + vr->va = (void *) + __get_free_pages(GFP_KERNEL | __GFP_ZERO, + get_order(vr_size)); + if (!vr->va) { + ret = -ENOMEM; + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, ret); + goto err; + } + vr->len = vr_size; + vr->info = vr->va + vring_size(num, MIC_VIRTIO_RING_ALIGN); + vr->info->magic = cpu_to_le32(MIC_MAGIC + vdev->virtio_id + i); + vr_addr = dma_map_single(&vpdev->dev, vr->va, vr_size, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(&vpdev->dev, vr_addr)) { + free_pages((unsigned long)vr->va, get_order(vr_size)); + ret = -ENOMEM; + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, ret); + goto err; + } + vqconfig[i].address = cpu_to_le64(vr_addr); + + vring_init(&vr->vr, num, vr->va, MIC_VIRTIO_RING_ALIGN); + ret = vringh_init_kern(&vvr->vrh, + *(u32 *)mic_vq_features(vdev->dd), + num, false, vr->vr.desc, vr->vr.avail, + vr->vr.used); + if (ret) { + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, ret); + goto err; + } + vringh_kiov_init(&vvr->riov, NULL, 0); + vringh_kiov_init(&vvr->wiov, NULL, 0); + vvr->head = USHRT_MAX; + vvr->vdev = vdev; + vvr->vrh.notify = _vop_notify; + dev_dbg(&vpdev->dev, + "%s %d index %d va %p info %p vr_size 0x%x\n", + __func__, __LINE__, i, vr->va, vr->info, vr_size); + vvr->buf = (void *)__get_free_pages(GFP_KERNEL, + get_order(VOP_INT_DMA_BUF_SIZE)); + vvr->buf_da = dma_map_single(&vpdev->dev, + vvr->buf, VOP_INT_DMA_BUF_SIZE, + DMA_BIDIRECTIONAL); + } + + snprintf(irqname, sizeof(irqname), "vop%dvirtio%d", vpdev->index, + vdev->virtio_id); + vdev->virtio_db = vpdev->hw_ops->next_db(vpdev); + vdev->virtio_cookie = vpdev->hw_ops->request_irq(vpdev, + _vop_virtio_intr_handler, irqname, vdev, + vdev->virtio_db); + if (IS_ERR(vdev->virtio_cookie)) { + ret = PTR_ERR(vdev->virtio_cookie); + dev_dbg(&vpdev->dev, "request irq failed\n"); + goto err; + } + + vdev->dc->c2h_vdev_db = vdev->virtio_db; + + /* + * Order the type update with previous stores. This write barrier + * is paired with the corresponding read barrier before the uncached + * system memory read of the type, on the card while scanning the + * device page. + */ + smp_wmb(); + dd->type = type; + argp->type = type; + + if (bootparam) { + db = bootparam->h2c_config_db; + if (db != -1) + vpdev->hw_ops->send_intr(vpdev, db); + } + dev_dbg(&vpdev->dev, "Added virtio id %d db %d\n", dd->type, db); + return 0; +err: + vqconfig = mic_vq_config(dd); + for (j = 0; j < i; j++) { + struct vop_vringh *vvr = &vdev->vvr[j]; + + dma_unmap_single(&vpdev->dev, le64_to_cpu(vqconfig[j].address), + vvr->vring.len, DMA_BIDIRECTIONAL); + free_pages((unsigned long)vvr->vring.va, + get_order(vvr->vring.len)); + } + return ret; +} + +static void vop_dev_remove(struct vop_info *pvi, struct mic_device_ctrl *devp, + struct vop_device *vpdev) +{ + struct mic_bootparam *bootparam = vpdev->hw_ops->get_dp(vpdev); + s8 db; + int ret, retry; + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); + + devp->config_change = MIC_VIRTIO_PARAM_DEV_REMOVE; + db = bootparam->h2c_config_db; + if (db != -1) + vpdev->hw_ops->send_intr(vpdev, db); + else + goto done; + for (retry = 15; retry--;) { + ret = wait_event_timeout(wake, devp->guest_ack, + msecs_to_jiffies(1000)); + if (ret) + break; + } +done: + devp->config_change = 0; + devp->guest_ack = 0; +} + +static void vop_virtio_del_device(struct vop_vdev *vdev) +{ + struct vop_info *vi = vdev->vi; + struct vop_device *vpdev = vdev->vpdev; + int i; + struct mic_vqconfig *vqconfig; + struct mic_bootparam *bootparam = vpdev->hw_ops->get_dp(vpdev); + + if (!bootparam) + goto skip_hot_remove; + vop_dev_remove(vi, vdev->dc, vpdev); +skip_hot_remove: + vpdev->hw_ops->free_irq(vpdev, vdev->virtio_cookie, vdev); + flush_work(&vdev->virtio_bh_work); + vqconfig = mic_vq_config(vdev->dd); + for (i = 0; i < vdev->dd->num_vq; i++) { + struct vop_vringh *vvr = &vdev->vvr[i]; + + dma_unmap_single(&vpdev->dev, + vvr->buf_da, VOP_INT_DMA_BUF_SIZE, + DMA_BIDIRECTIONAL); + free_pages((unsigned long)vvr->buf, + get_order(VOP_INT_DMA_BUF_SIZE)); + vringh_kiov_cleanup(&vvr->riov); + vringh_kiov_cleanup(&vvr->wiov); + dma_unmap_single(&vpdev->dev, le64_to_cpu(vqconfig[i].address), + vvr->vring.len, DMA_BIDIRECTIONAL); + free_pages((unsigned long)vvr->vring.va, + get_order(vvr->vring.len)); + } + /* + * Order the type update with previous stores. This write barrier + * is paired with the corresponding read barrier before the uncached + * system memory read of the type, on the card while scanning the + * device page. + */ + smp_wmb(); + vdev->dd->type = -1; +} + +/* + * vop_sync_dma - Wrapper for synchronous DMAs. + * + * @dev - The address of the pointer to the device instance used + * for DMA registration. + * @dst - destination DMA address. + * @src - source DMA address. + * @len - size of the transfer. + * + * Return DMA_SUCCESS on success + */ +static int vop_sync_dma(struct vop_vdev *vdev, dma_addr_t dst, dma_addr_t src, + size_t len) +{ + int err = 0; + struct dma_device *ddev; + struct dma_async_tx_descriptor *tx; + struct vop_info *vi = dev_get_drvdata(&vdev->vpdev->dev); + struct dma_chan *vop_ch = vi->dma_ch; + + if (!vop_ch) { + err = -EBUSY; + goto error; + } + ddev = vop_ch->device; + tx = ddev->device_prep_dma_memcpy(vop_ch, dst, src, len, + DMA_PREP_FENCE); + if (!tx) { + err = -ENOMEM; + goto error; + } else { + dma_cookie_t cookie; + + cookie = tx->tx_submit(tx); + if (dma_submit_error(cookie)) { + err = -ENOMEM; + goto error; + } + dma_async_issue_pending(vop_ch); + err = dma_sync_wait(vop_ch, cookie); + } +error: + if (err) + dev_err(&vi->vpdev->dev, "%s %d err %d\n", + __func__, __LINE__, err); + return err; +} + +#define VOP_USE_DMA true + +/* + * Initiates the copies across the PCIe bus from card memory to a user + * space buffer. When transfers are done using DMA, source/destination + * addresses and transfer length must follow the alignment requirements of + * the MIC DMA engine. + */ +static int vop_virtio_copy_to_user(struct vop_vdev *vdev, void __user *ubuf, + size_t len, u64 daddr, size_t dlen, + int vr_idx) +{ + struct vop_device *vpdev = vdev->vpdev; + void __iomem *dbuf = vpdev->hw_ops->ioremap(vpdev, daddr, len); + struct vop_vringh *vvr = &vdev->vvr[vr_idx]; + struct vop_info *vi = dev_get_drvdata(&vpdev->dev); + size_t dma_alignment = 1 << vi->dma_ch->device->copy_align; + bool x200 = is_dma_copy_aligned(vi->dma_ch->device, 1, 1, 1); + size_t dma_offset, partlen; + int err; + + if (!VOP_USE_DMA) { + if (copy_to_user(ubuf, (void __force *)dbuf, len)) { + err = -EFAULT; + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, err); + goto err; + } + vdev->in_bytes += len; + err = 0; + goto err; + } + + dma_offset = daddr - round_down(daddr, dma_alignment); + daddr -= dma_offset; + len += dma_offset; + /* + * X100 uses DMA addresses as seen by the card so adding + * the aperture base is not required for DMA. However x200 + * requires DMA addresses to be an offset into the bar so + * add the aperture base for x200. + */ + if (x200) + daddr += vpdev->aper->pa; + while (len) { + partlen = min_t(size_t, len, VOP_INT_DMA_BUF_SIZE); + err = vop_sync_dma(vdev, vvr->buf_da, daddr, + ALIGN(partlen, dma_alignment)); + if (err) { + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, err); + goto err; + } + if (copy_to_user(ubuf, vvr->buf + dma_offset, + partlen - dma_offset)) { + err = -EFAULT; + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, err); + goto err; + } + daddr += partlen; + ubuf += partlen; + dbuf += partlen; + vdev->in_bytes_dma += partlen; + vdev->in_bytes += partlen; + len -= partlen; + dma_offset = 0; + } + err = 0; +err: + vpdev->hw_ops->iounmap(vpdev, dbuf); + dev_dbg(vop_dev(vdev), + "%s: ubuf %p dbuf %p len 0x%lx vr_idx 0x%x\n", + __func__, ubuf, dbuf, len, vr_idx); + return err; +} + +/* + * Initiates copies across the PCIe bus from a user space buffer to card + * memory. When transfers are done using DMA, source/destination addresses + * and transfer length must follow the alignment requirements of the MIC + * DMA engine. + */ +static int vop_virtio_copy_from_user(struct vop_vdev *vdev, void __user *ubuf, + size_t len, u64 daddr, size_t dlen, + int vr_idx) +{ + struct vop_device *vpdev = vdev->vpdev; + void __iomem *dbuf = vpdev->hw_ops->ioremap(vpdev, daddr, len); + struct vop_vringh *vvr = &vdev->vvr[vr_idx]; + struct vop_info *vi = dev_get_drvdata(&vdev->vpdev->dev); + size_t dma_alignment = 1 << vi->dma_ch->device->copy_align; + bool x200 = is_dma_copy_aligned(vi->dma_ch->device, 1, 1, 1); + size_t partlen; + bool dma = VOP_USE_DMA; + int err = 0; + + if (daddr & (dma_alignment - 1)) { + vdev->tx_dst_unaligned += len; + dma = false; + } else if (ALIGN(len, dma_alignment) > dlen) { + vdev->tx_len_unaligned += len; + dma = false; + } + + if (!dma) + goto memcpy; + + /* + * X100 uses DMA addresses as seen by the card so adding + * the aperture base is not required for DMA. However x200 + * requires DMA addresses to be an offset into the bar so + * add the aperture base for x200. + */ + if (x200) + daddr += vpdev->aper->pa; + while (len) { + partlen = min_t(size_t, len, VOP_INT_DMA_BUF_SIZE); + + if (copy_from_user(vvr->buf, ubuf, partlen)) { + err = -EFAULT; + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, err); + goto err; + } + err = vop_sync_dma(vdev, daddr, vvr->buf_da, + ALIGN(partlen, dma_alignment)); + if (err) { + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, err); + goto err; + } + daddr += partlen; + ubuf += partlen; + dbuf += partlen; + vdev->out_bytes_dma += partlen; + vdev->out_bytes += partlen; + len -= partlen; + } +memcpy: + /* + * We are copying to IO below and should ideally use something + * like copy_from_user_toio(..) if it existed. + */ + if (copy_from_user((void __force *)dbuf, ubuf, len)) { + err = -EFAULT; + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, err); + goto err; + } + vdev->out_bytes += len; + err = 0; +err: + vpdev->hw_ops->iounmap(vpdev, dbuf); + dev_dbg(vop_dev(vdev), + "%s: ubuf %p dbuf %p len 0x%lx vr_idx 0x%x\n", + __func__, ubuf, dbuf, len, vr_idx); + return err; +} + +#define MIC_VRINGH_READ true + +/* Determine the total number of bytes consumed in a VRINGH KIOV */ +static inline u32 vop_vringh_iov_consumed(struct vringh_kiov *iov) +{ + int i; + u32 total = iov->consumed; + + for (i = 0; i < iov->i; i++) + total += iov->iov[i].iov_len; + return total; +} + +/* + * Traverse the VRINGH KIOV and issue the APIs to trigger the copies. + * This API is heavily based on the vringh_iov_xfer(..) implementation + * in vringh.c. The reason we cannot reuse vringh_iov_pull_kern(..) + * and vringh_iov_push_kern(..) directly is because there is no + * way to override the VRINGH xfer(..) routines as of v3.10. + */ +static int vop_vringh_copy(struct vop_vdev *vdev, struct vringh_kiov *iov, + void __user *ubuf, size_t len, bool read, int vr_idx, + size_t *out_len) +{ + int ret = 0; + size_t partlen, tot_len = 0; + + while (len && iov->i < iov->used) { + struct kvec *kiov = &iov->iov[iov->i]; + + partlen = min(kiov->iov_len, len); + if (read) + ret = vop_virtio_copy_to_user(vdev, ubuf, partlen, + (u64)kiov->iov_base, + kiov->iov_len, + vr_idx); + else + ret = vop_virtio_copy_from_user(vdev, ubuf, partlen, + (u64)kiov->iov_base, + kiov->iov_len, + vr_idx); + if (ret) { + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, ret); + break; + } + len -= partlen; + ubuf += partlen; + tot_len += partlen; + iov->consumed += partlen; + kiov->iov_len -= partlen; + kiov->iov_base += partlen; + if (!kiov->iov_len) { + /* Fix up old iov element then increment. */ + kiov->iov_len = iov->consumed; + kiov->iov_base -= iov->consumed; + + iov->consumed = 0; + iov->i++; + } + } + *out_len = tot_len; + return ret; +} + +/* + * Use the standard VRINGH infrastructure in the kernel to fetch new + * descriptors, initiate the copies and update the used ring. + */ +static int _vop_virtio_copy(struct vop_vdev *vdev, struct mic_copy_desc *copy) +{ + int ret = 0; + u32 iovcnt = copy->iovcnt; + struct iovec iov; + struct iovec __user *u_iov = copy->iov; + void __user *ubuf = NULL; + struct vop_vringh *vvr = &vdev->vvr[copy->vr_idx]; + struct vringh_kiov *riov = &vvr->riov; + struct vringh_kiov *wiov = &vvr->wiov; + struct vringh *vrh = &vvr->vrh; + u16 *head = &vvr->head; + struct mic_vring *vr = &vvr->vring; + size_t len = 0, out_len; + + copy->out_len = 0; + /* Fetch a new IOVEC if all previous elements have been processed */ + if (riov->i == riov->used && wiov->i == wiov->used) { + ret = vringh_getdesc_kern(vrh, riov, wiov, + head, GFP_KERNEL); + /* Check if there are available descriptors */ + if (ret <= 0) + return ret; + } + while (iovcnt) { + if (!len) { + /* Copy over a new iovec from user space. */ + ret = copy_from_user(&iov, u_iov, sizeof(*u_iov)); + if (ret) { + ret = -EINVAL; + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, ret); + break; + } + len = iov.iov_len; + ubuf = iov.iov_base; + } + /* Issue all the read descriptors first */ + ret = vop_vringh_copy(vdev, riov, ubuf, len, + MIC_VRINGH_READ, copy->vr_idx, &out_len); + if (ret) { + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, ret); + break; + } + len -= out_len; + ubuf += out_len; + copy->out_len += out_len; + /* Issue the write descriptors next */ + ret = vop_vringh_copy(vdev, wiov, ubuf, len, + !MIC_VRINGH_READ, copy->vr_idx, &out_len); + if (ret) { + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, ret); + break; + } + len -= out_len; + ubuf += out_len; + copy->out_len += out_len; + if (!len) { + /* One user space iovec is now completed */ + iovcnt--; + u_iov++; + } + /* Exit loop if all elements in KIOVs have been processed. */ + if (riov->i == riov->used && wiov->i == wiov->used) + break; + } + /* + * Update the used ring if a descriptor was available and some data was + * copied in/out and the user asked for a used ring update. + */ + if (*head != USHRT_MAX && copy->out_len && copy->update_used) { + u32 total = 0; + + /* Determine the total data consumed */ + total += vop_vringh_iov_consumed(riov); + total += vop_vringh_iov_consumed(wiov); + vringh_complete_kern(vrh, *head, total); + *head = USHRT_MAX; + if (vringh_need_notify_kern(vrh) > 0) + vringh_notify(vrh); + vringh_kiov_cleanup(riov); + vringh_kiov_cleanup(wiov); + /* Update avail idx for user space */ + vr->info->avail_idx = vrh->last_avail_idx; + } + return ret; +} + +static inline int vop_verify_copy_args(struct vop_vdev *vdev, + struct mic_copy_desc *copy) +{ + if (!vdev || copy->vr_idx >= vdev->dd->num_vq) + return -EINVAL; + return 0; +} + +/* Copy a specified number of virtio descriptors in a chain */ +static int vop_virtio_copy_desc(struct vop_vdev *vdev, + struct mic_copy_desc *copy) +{ + int err; + struct vop_vringh *vvr = &vdev->vvr[copy->vr_idx]; + + err = vop_verify_copy_args(vdev, copy); + if (err) + return err; + + mutex_lock(&vvr->vr_mutex); + if (!vop_vdevup(vdev)) { + err = -ENODEV; + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, err); + goto err; + } + err = _vop_virtio_copy(vdev, copy); + if (err) { + dev_err(vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, err); + } +err: + mutex_unlock(&vvr->vr_mutex); + return err; +} + +static int vop_open(struct inode *inode, struct file *f) +{ + struct vop_vdev *vdev; + struct vop_info *vi = container_of(f->private_data, + struct vop_info, miscdev); + + vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); + if (!vdev) + return -ENOMEM; + vdev->vi = vi; + mutex_init(&vdev->vdev_mutex); + f->private_data = vdev; + init_completion(&vdev->destroy); + complete(&vdev->destroy); + return 0; +} + +static int vop_release(struct inode *inode, struct file *f) +{ + struct vop_vdev *vdev = f->private_data, *vdev_tmp; + struct vop_info *vi = vdev->vi; + struct list_head *pos, *tmp; + bool found = false; + + mutex_lock(&vdev->vdev_mutex); + if (vdev->deleted) + goto unlock; + mutex_lock(&vi->vop_mutex); + list_for_each_safe(pos, tmp, &vi->vdev_list) { + vdev_tmp = list_entry(pos, struct vop_vdev, list); + if (vdev == vdev_tmp) { + vop_virtio_del_device(vdev); + list_del(pos); + found = true; + break; + } + } + mutex_unlock(&vi->vop_mutex); +unlock: + mutex_unlock(&vdev->vdev_mutex); + if (!found) + wait_for_completion(&vdev->destroy); + f->private_data = NULL; + kfree(vdev); + return 0; +} + +static long vop_ioctl(struct file *f, unsigned int cmd, unsigned long arg) +{ + struct vop_vdev *vdev = f->private_data; + struct vop_info *vi = vdev->vi; + void __user *argp = (void __user *)arg; + int ret; + + switch (cmd) { + case MIC_VIRTIO_ADD_DEVICE: + { + struct mic_device_desc dd, *dd_config; + + if (copy_from_user(&dd, argp, sizeof(dd))) + return -EFAULT; + + if (mic_aligned_desc_size(&dd) > MIC_MAX_DESC_BLK_SIZE || + dd.num_vq > MIC_MAX_VRINGS) + return -EINVAL; + + dd_config = kzalloc(mic_desc_size(&dd), GFP_KERNEL); + if (!dd_config) + return -ENOMEM; + if (copy_from_user(dd_config, argp, mic_desc_size(&dd))) { + ret = -EFAULT; + goto free_ret; + } + mutex_lock(&vdev->vdev_mutex); + mutex_lock(&vi->vop_mutex); + ret = vop_virtio_add_device(vdev, dd_config); + if (ret) + goto unlock_ret; + list_add_tail(&vdev->list, &vi->vdev_list); +unlock_ret: + mutex_unlock(&vi->vop_mutex); + mutex_unlock(&vdev->vdev_mutex); +free_ret: + kfree(dd_config); + return ret; + } + case MIC_VIRTIO_COPY_DESC: + { + struct mic_copy_desc copy; + + mutex_lock(&vdev->vdev_mutex); + ret = vop_vdev_inited(vdev); + if (ret) + goto _unlock_ret; + + if (copy_from_user(©, argp, sizeof(copy))) { + ret = -EFAULT; + goto _unlock_ret; + } + + ret = vop_virtio_copy_desc(vdev, ©); + if (ret < 0) + goto _unlock_ret; + if (copy_to_user( + &((struct mic_copy_desc __user *)argp)->out_len, + ©.out_len, sizeof(copy.out_len))) + ret = -EFAULT; +_unlock_ret: + mutex_unlock(&vdev->vdev_mutex); + return ret; + } + case MIC_VIRTIO_CONFIG_CHANGE: + { + void *buf; + + mutex_lock(&vdev->vdev_mutex); + ret = vop_vdev_inited(vdev); + if (ret) + goto __unlock_ret; + buf = kzalloc(vdev->dd->config_len, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto __unlock_ret; + } + if (copy_from_user(buf, argp, vdev->dd->config_len)) { + ret = -EFAULT; + goto done; + } + ret = vop_virtio_config_change(vdev, buf); +done: + kfree(buf); +__unlock_ret: + mutex_unlock(&vdev->vdev_mutex); + return ret; + } + default: + return -ENOIOCTLCMD; + }; + return 0; +} + +/* + * We return POLLIN | POLLOUT from poll when new buffers are enqueued, and + * not when previously enqueued buffers may be available. This means that + * in the card->host (TX) path, when userspace is unblocked by poll it + * must drain all available descriptors or it can stall. + */ +static unsigned int vop_poll(struct file *f, poll_table *wait) +{ + struct vop_vdev *vdev = f->private_data; + int mask = 0; + + mutex_lock(&vdev->vdev_mutex); + if (vop_vdev_inited(vdev)) { + mask = POLLERR; + goto done; + } + poll_wait(f, &vdev->waitq, wait); + if (vop_vdev_inited(vdev)) { + mask = POLLERR; + } else if (vdev->poll_wake) { + vdev->poll_wake = 0; + mask = POLLIN | POLLOUT; + } +done: + mutex_unlock(&vdev->vdev_mutex); + return mask; +} + +static inline int +vop_query_offset(struct vop_vdev *vdev, unsigned long offset, + unsigned long *size, unsigned long *pa) +{ + struct vop_device *vpdev = vdev->vpdev; + unsigned long start = MIC_DP_SIZE; + int i; + + /* + * MMAP interface is as follows: + * offset region + * 0x0 virtio device_page + * 0x1000 first vring + * 0x1000 + size of 1st vring second vring + * .... + */ + if (!offset) { + *pa = virt_to_phys(vpdev->hw_ops->get_dp(vpdev)); + *size = MIC_DP_SIZE; + return 0; + } + + for (i = 0; i < vdev->dd->num_vq; i++) { + struct vop_vringh *vvr = &vdev->vvr[i]; + + if (offset == start) { + *pa = virt_to_phys(vvr->vring.va); + *size = vvr->vring.len; + return 0; + } + start += vvr->vring.len; + } + return -1; +} + +/* + * Maps the device page and virtio rings to user space for readonly access. + */ +static int vop_mmap(struct file *f, struct vm_area_struct *vma) +{ + struct vop_vdev *vdev = f->private_data; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long pa, size = vma->vm_end - vma->vm_start, size_rem = size; + int i, err; + + err = vop_vdev_inited(vdev); + if (err) + goto ret; + if (vma->vm_flags & VM_WRITE) { + err = -EACCES; + goto ret; + } + while (size_rem) { + i = vop_query_offset(vdev, offset, &size, &pa); + if (i < 0) { + err = -EINVAL; + goto ret; + } + err = remap_pfn_range(vma, vma->vm_start + offset, + pa >> PAGE_SHIFT, size, + vma->vm_page_prot); + if (err) + goto ret; + size_rem -= size; + offset += size; + } +ret: + return err; +} + +static const struct file_operations vop_fops = { + .open = vop_open, + .release = vop_release, + .unlocked_ioctl = vop_ioctl, + .poll = vop_poll, + .mmap = vop_mmap, + .owner = THIS_MODULE, +}; + +int vop_host_init(struct vop_info *vi) +{ + int rc; + struct miscdevice *mdev; + struct vop_device *vpdev = vi->vpdev; + + INIT_LIST_HEAD(&vi->vdev_list); + vi->dma_ch = vpdev->dma_ch; + mdev = &vi->miscdev; + mdev->minor = MISC_DYNAMIC_MINOR; + snprintf(vi->name, sizeof(vi->name), "vop_virtio%d", vpdev->index); + mdev->name = vi->name; + mdev->fops = &vop_fops; + mdev->parent = &vpdev->dev; + + rc = misc_register(mdev); + if (rc) + dev_err(&vpdev->dev, "%s failed rc %d\n", __func__, rc); + return rc; +} + +void vop_host_uninit(struct vop_info *vi) +{ + struct list_head *pos, *tmp; + struct vop_vdev *vdev; + + mutex_lock(&vi->vop_mutex); + vop_virtio_reset_devices(vi); + list_for_each_safe(pos, tmp, &vi->vdev_list) { + vdev = list_entry(pos, struct vop_vdev, list); + list_del(pos); + reinit_completion(&vdev->destroy); + mutex_unlock(&vi->vop_mutex); + mutex_lock(&vdev->vdev_mutex); + vop_virtio_del_device(vdev); + vdev->deleted = true; + mutex_unlock(&vdev->vdev_mutex); + complete(&vdev->destroy); + mutex_lock(&vi->vop_mutex); + } + mutex_unlock(&vi->vop_mutex); + misc_deregister(&vi->miscdev); +} -- cgit v1.2.3 From c1becd2849681e8be1043d2ce9034a9d9bb3d540 Mon Sep 17 00:00:00 2001 From: Ashutosh Dixit Date: Mon, 8 Feb 2016 15:48:16 -0800 Subject: misc: mic: Enable VOP card side functionality This patch moves virtio functionality from the MIC card driver into a separate hardware independent Virtio Over PCIe (VOP) driver. This functionality was introduced in commit 2141c7c5ee67 ("Intel MIC Card Driver Changes for Virtio Devices.") in drivers/misc/mic/card/mic_virtio.c. Apart from being moved into a separate driver the functionality is essentially unchanged. See the above mentioned commit for a description of this functionality. Signed-off-by: Sudeep Dutt Signed-off-by: Ashutosh Dixit Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/vop/vop_main.c | 755 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 755 insertions(+) create mode 100644 drivers/misc/mic/vop/vop_main.c (limited to 'drivers') diff --git a/drivers/misc/mic/vop/vop_main.c b/drivers/misc/mic/vop/vop_main.c new file mode 100644 index 000000000000..1a2b67f3183d --- /dev/null +++ b/drivers/misc/mic/vop/vop_main.c @@ -0,0 +1,755 @@ +/* + * Intel MIC Platform Software Stack (MPSS) + * + * Copyright(c) 2016 Intel Corporation. + * + * 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. + * + * 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. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Adapted from: + * + * virtio for kvm on s390 + * + * Copyright IBM Corp. 2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2 only) + * as published by the Free Software Foundation. + * + * Author(s): Christian Borntraeger + * + * Intel Virtio Over PCIe (VOP) driver. + * + */ +#include +#include +#include +#include + +#include "vop_main.h" + +#define VOP_MAX_VRINGS 4 + +/* + * _vop_vdev - Allocated per virtio device instance injected by the peer. + * + * @vdev: Virtio device + * @desc: Virtio device page descriptor + * @dc: Virtio device control + * @vpdev: VOP device which is the parent for this virtio device + * @vr: Buffer for accessing the VRING + * @used: Buffer for used + * @used_size: Size of the used buffer + * @reset_done: Track whether VOP reset is complete + * @virtio_cookie: Cookie returned upon requesting a interrupt + * @c2h_vdev_db: The doorbell used by the guest to interrupt the host + * @h2c_vdev_db: The doorbell used by the host to interrupt the guest + * @dnode: The destination node + */ +struct _vop_vdev { + struct virtio_device vdev; + struct mic_device_desc __iomem *desc; + struct mic_device_ctrl __iomem *dc; + struct vop_device *vpdev; + void __iomem *vr[VOP_MAX_VRINGS]; + dma_addr_t used[VOP_MAX_VRINGS]; + int used_size[VOP_MAX_VRINGS]; + struct completion reset_done; + struct mic_irq *virtio_cookie; + int c2h_vdev_db; + int h2c_vdev_db; + int dnode; +}; + +#define to_vopvdev(vd) container_of(vd, struct _vop_vdev, vdev) + +#define _vop_aligned_desc_size(d) __mic_align(_vop_desc_size(d), 8) + +/* Helper API to obtain the parent of the virtio device */ +static inline struct device *_vop_dev(struct _vop_vdev *vdev) +{ + return vdev->vdev.dev.parent; +} + +static inline unsigned _vop_desc_size(struct mic_device_desc __iomem *desc) +{ + return sizeof(*desc) + + ioread8(&desc->num_vq) * sizeof(struct mic_vqconfig) + + ioread8(&desc->feature_len) * 2 + + ioread8(&desc->config_len); +} + +static inline struct mic_vqconfig __iomem * +_vop_vq_config(struct mic_device_desc __iomem *desc) +{ + return (struct mic_vqconfig __iomem *)(desc + 1); +} + +static inline u8 __iomem * +_vop_vq_features(struct mic_device_desc __iomem *desc) +{ + return (u8 __iomem *)(_vop_vq_config(desc) + ioread8(&desc->num_vq)); +} + +static inline u8 __iomem * +_vop_vq_configspace(struct mic_device_desc __iomem *desc) +{ + return _vop_vq_features(desc) + ioread8(&desc->feature_len) * 2; +} + +static inline unsigned +_vop_total_desc_size(struct mic_device_desc __iomem *desc) +{ + return _vop_aligned_desc_size(desc) + sizeof(struct mic_device_ctrl); +} + +/* This gets the device's feature bits. */ +static u64 vop_get_features(struct virtio_device *vdev) +{ + unsigned int i, bits; + u32 features = 0; + struct mic_device_desc __iomem *desc = to_vopvdev(vdev)->desc; + u8 __iomem *in_features = _vop_vq_features(desc); + int feature_len = ioread8(&desc->feature_len); + + bits = min_t(unsigned, feature_len, sizeof(vdev->features)) * 8; + for (i = 0; i < bits; i++) + if (ioread8(&in_features[i / 8]) & (BIT(i % 8))) + features |= BIT(i); + + return features; +} + +static int vop_finalize_features(struct virtio_device *vdev) +{ + unsigned int i, bits; + struct mic_device_desc __iomem *desc = to_vopvdev(vdev)->desc; + u8 feature_len = ioread8(&desc->feature_len); + /* Second half of bitmap is features we accept. */ + u8 __iomem *out_features = + _vop_vq_features(desc) + feature_len; + + /* Give virtio_ring a chance to accept features. */ + vring_transport_features(vdev); + + memset_io(out_features, 0, feature_len); + bits = min_t(unsigned, feature_len, + sizeof(vdev->features)) * 8; + for (i = 0; i < bits; i++) { + if (__virtio_test_bit(vdev, i)) + iowrite8(ioread8(&out_features[i / 8]) | (1 << (i % 8)), + &out_features[i / 8]); + } + return 0; +} + +/* + * Reading and writing elements in config space + */ +static void vop_get(struct virtio_device *vdev, unsigned int offset, + void *buf, unsigned len) +{ + struct mic_device_desc __iomem *desc = to_vopvdev(vdev)->desc; + + if (offset + len > ioread8(&desc->config_len)) + return; + memcpy_fromio(buf, _vop_vq_configspace(desc) + offset, len); +} + +static void vop_set(struct virtio_device *vdev, unsigned int offset, + const void *buf, unsigned len) +{ + struct mic_device_desc __iomem *desc = to_vopvdev(vdev)->desc; + + if (offset + len > ioread8(&desc->config_len)) + return; + memcpy_toio(_vop_vq_configspace(desc) + offset, buf, len); +} + +/* + * The operations to get and set the status word just access the status + * field of the device descriptor. set_status also interrupts the host + * to tell about status changes. + */ +static u8 vop_get_status(struct virtio_device *vdev) +{ + return ioread8(&to_vopvdev(vdev)->desc->status); +} + +static void vop_set_status(struct virtio_device *dev, u8 status) +{ + struct _vop_vdev *vdev = to_vopvdev(dev); + struct vop_device *vpdev = vdev->vpdev; + + if (!status) + return; + iowrite8(status, &vdev->desc->status); + vpdev->hw_ops->send_intr(vpdev, vdev->c2h_vdev_db); +} + +/* Inform host on a virtio device reset and wait for ack from host */ +static void vop_reset_inform_host(struct virtio_device *dev) +{ + struct _vop_vdev *vdev = to_vopvdev(dev); + struct mic_device_ctrl __iomem *dc = vdev->dc; + struct vop_device *vpdev = vdev->vpdev; + int retry; + + iowrite8(0, &dc->host_ack); + iowrite8(1, &dc->vdev_reset); + vpdev->hw_ops->send_intr(vpdev, vdev->c2h_vdev_db); + + /* Wait till host completes all card accesses and acks the reset */ + for (retry = 100; retry--;) { + if (ioread8(&dc->host_ack)) + break; + msleep(100); + }; + + dev_dbg(_vop_dev(vdev), "%s: retry: %d\n", __func__, retry); + + /* Reset status to 0 in case we timed out */ + iowrite8(0, &vdev->desc->status); +} + +static void vop_reset(struct virtio_device *dev) +{ + struct _vop_vdev *vdev = to_vopvdev(dev); + + dev_dbg(_vop_dev(vdev), "%s: virtio id %d\n", + __func__, dev->id.device); + + vop_reset_inform_host(dev); + complete_all(&vdev->reset_done); +} + +/* + * The virtio_ring code calls this API when it wants to notify the Host. + */ +static bool vop_notify(struct virtqueue *vq) +{ + struct _vop_vdev *vdev = vq->priv; + struct vop_device *vpdev = vdev->vpdev; + + vpdev->hw_ops->send_intr(vpdev, vdev->c2h_vdev_db); + return true; +} + +static void vop_del_vq(struct virtqueue *vq, int n) +{ + struct _vop_vdev *vdev = to_vopvdev(vq->vdev); + struct vring *vr = (struct vring *)(vq + 1); + struct vop_device *vpdev = vdev->vpdev; + + dma_unmap_single(&vpdev->dev, vdev->used[n], + vdev->used_size[n], DMA_BIDIRECTIONAL); + free_pages((unsigned long)vr->used, get_order(vdev->used_size[n])); + vring_del_virtqueue(vq); + vpdev->hw_ops->iounmap(vpdev, vdev->vr[n]); + vdev->vr[n] = NULL; +} + +static void vop_del_vqs(struct virtio_device *dev) +{ + struct _vop_vdev *vdev = to_vopvdev(dev); + struct virtqueue *vq, *n; + int idx = 0; + + dev_dbg(_vop_dev(vdev), "%s\n", __func__); + + list_for_each_entry_safe(vq, n, &dev->vqs, list) + vop_del_vq(vq, idx++); +} + +/* + * This routine will assign vring's allocated in host/io memory. Code in + * virtio_ring.c however continues to access this io memory as if it were local + * memory without io accessors. + */ +static struct virtqueue *vop_find_vq(struct virtio_device *dev, + unsigned index, + void (*callback)(struct virtqueue *vq), + const char *name) +{ + struct _vop_vdev *vdev = to_vopvdev(dev); + struct vop_device *vpdev = vdev->vpdev; + struct mic_vqconfig __iomem *vqconfig; + struct mic_vqconfig config; + struct virtqueue *vq; + void __iomem *va; + struct _mic_vring_info __iomem *info; + void *used; + int vr_size, _vr_size, err, magic; + struct vring *vr; + u8 type = ioread8(&vdev->desc->type); + + if (index >= ioread8(&vdev->desc->num_vq)) + return ERR_PTR(-ENOENT); + + if (!name) + return ERR_PTR(-ENOENT); + + /* First assign the vring's allocated in host memory */ + vqconfig = _vop_vq_config(vdev->desc) + index; + memcpy_fromio(&config, vqconfig, sizeof(config)); + _vr_size = vring_size(le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN); + vr_size = PAGE_ALIGN(_vr_size + sizeof(struct _mic_vring_info)); + va = vpdev->hw_ops->ioremap(vpdev, le64_to_cpu(config.address), + vr_size); + if (!va) + return ERR_PTR(-ENOMEM); + vdev->vr[index] = va; + memset_io(va, 0x0, _vr_size); + vq = vring_new_virtqueue( + index, + le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN, + dev, + false, + (void __force *)va, vop_notify, callback, name); + if (!vq) { + err = -ENOMEM; + goto unmap; + } + info = va + _vr_size; + magic = ioread32(&info->magic); + + if (WARN(magic != MIC_MAGIC + type + index, "magic mismatch")) { + err = -EIO; + goto unmap; + } + + /* Allocate and reassign used ring now */ + vdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 + + sizeof(struct vring_used_elem) * + le16_to_cpu(config.num)); + used = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, + get_order(vdev->used_size[index])); + if (!used) { + err = -ENOMEM; + dev_err(_vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, err); + goto del_vq; + } + vdev->used[index] = dma_map_single(&vpdev->dev, used, + vdev->used_size[index], + DMA_BIDIRECTIONAL); + if (dma_mapping_error(&vpdev->dev, vdev->used[index])) { + err = -ENOMEM; + dev_err(_vop_dev(vdev), "%s %d err %d\n", + __func__, __LINE__, err); + goto free_used; + } + writeq(vdev->used[index], &vqconfig->used_address); + /* + * To reassign the used ring here we are directly accessing + * struct vring_virtqueue which is a private data structure + * in virtio_ring.c. At the minimum, a BUILD_BUG_ON() in + * vring_new_virtqueue() would ensure that + * (&vq->vring == (struct vring *) (&vq->vq + 1)); + */ + vr = (struct vring *)(vq + 1); + vr->used = used; + + vq->priv = vdev; + return vq; +free_used: + free_pages((unsigned long)used, + get_order(vdev->used_size[index])); +del_vq: + vring_del_virtqueue(vq); +unmap: + vpdev->hw_ops->iounmap(vpdev, vdev->vr[index]); + return ERR_PTR(err); +} + +static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs, + struct virtqueue *vqs[], + vq_callback_t *callbacks[], + const char * const names[]) +{ + struct _vop_vdev *vdev = to_vopvdev(dev); + struct vop_device *vpdev = vdev->vpdev; + struct mic_device_ctrl __iomem *dc = vdev->dc; + int i, err, retry; + + /* We must have this many virtqueues. */ + if (nvqs > ioread8(&vdev->desc->num_vq)) + return -ENOENT; + + for (i = 0; i < nvqs; ++i) { + dev_dbg(_vop_dev(vdev), "%s: %d: %s\n", + __func__, i, names[i]); + vqs[i] = vop_find_vq(dev, i, callbacks[i], names[i]); + if (IS_ERR(vqs[i])) { + err = PTR_ERR(vqs[i]); + goto error; + } + } + + iowrite8(1, &dc->used_address_updated); + /* + * Send an interrupt to the host to inform it that used + * rings have been re-assigned. + */ + vpdev->hw_ops->send_intr(vpdev, vdev->c2h_vdev_db); + for (retry = 100; --retry;) { + if (!ioread8(&dc->used_address_updated)) + break; + msleep(100); + }; + + dev_dbg(_vop_dev(vdev), "%s: retry: %d\n", __func__, retry); + if (!retry) { + err = -ENODEV; + goto error; + } + + return 0; +error: + vop_del_vqs(dev); + return err; +} + +/* + * The config ops structure as defined by virtio config + */ +static struct virtio_config_ops vop_vq_config_ops = { + .get_features = vop_get_features, + .finalize_features = vop_finalize_features, + .get = vop_get, + .set = vop_set, + .get_status = vop_get_status, + .set_status = vop_set_status, + .reset = vop_reset, + .find_vqs = vop_find_vqs, + .del_vqs = vop_del_vqs, +}; + +static irqreturn_t vop_virtio_intr_handler(int irq, void *data) +{ + struct _vop_vdev *vdev = data; + struct vop_device *vpdev = vdev->vpdev; + struct virtqueue *vq; + + vpdev->hw_ops->ack_interrupt(vpdev, vdev->h2c_vdev_db); + list_for_each_entry(vq, &vdev->vdev.vqs, list) + vring_interrupt(0, vq); + + return IRQ_HANDLED; +} + +static void vop_virtio_release_dev(struct device *_d) +{ + /* + * No need for a release method similar to virtio PCI. + * Provide an empty one to avoid getting a warning from core. + */ +} + +/* + * adds a new device and register it with virtio + * appropriate drivers are loaded by the device model + */ +static int _vop_add_device(struct mic_device_desc __iomem *d, + unsigned int offset, struct vop_device *vpdev, + int dnode) +{ + struct _vop_vdev *vdev; + int ret; + u8 type = ioread8(&d->type); + + vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); + if (!vdev) + return -ENOMEM; + + vdev->vpdev = vpdev; + vdev->vdev.dev.parent = &vpdev->dev; + vdev->vdev.dev.release = vop_virtio_release_dev; + vdev->vdev.id.device = type; + vdev->vdev.config = &vop_vq_config_ops; + vdev->desc = d; + vdev->dc = (void __iomem *)d + _vop_aligned_desc_size(d); + vdev->dnode = dnode; + vdev->vdev.priv = (void *)(u64)dnode; + init_completion(&vdev->reset_done); + + vdev->h2c_vdev_db = vpdev->hw_ops->next_db(vpdev); + vdev->virtio_cookie = vpdev->hw_ops->request_irq(vpdev, + vop_virtio_intr_handler, "virtio intr", + vdev, vdev->h2c_vdev_db); + if (IS_ERR(vdev->virtio_cookie)) { + ret = PTR_ERR(vdev->virtio_cookie); + goto kfree; + } + iowrite8((u8)vdev->h2c_vdev_db, &vdev->dc->h2c_vdev_db); + vdev->c2h_vdev_db = ioread8(&vdev->dc->c2h_vdev_db); + + ret = register_virtio_device(&vdev->vdev); + if (ret) { + dev_err(_vop_dev(vdev), + "Failed to register vop device %u type %u\n", + offset, type); + goto free_irq; + } + writeq((u64)vdev, &vdev->dc->vdev); + dev_dbg(_vop_dev(vdev), "%s: registered vop device %u type %u vdev %p\n", + __func__, offset, type, vdev); + + return 0; + +free_irq: + vpdev->hw_ops->free_irq(vpdev, vdev->virtio_cookie, vdev); +kfree: + kfree(vdev); + return ret; +} + +/* + * match for a vop device with a specific desc pointer + */ +static int vop_match_desc(struct device *dev, void *data) +{ + struct virtio_device *_dev = dev_to_virtio(dev); + struct _vop_vdev *vdev = to_vopvdev(_dev); + + return vdev->desc == (void __iomem *)data; +} + +static void _vop_handle_config_change(struct mic_device_desc __iomem *d, + unsigned int offset, + struct vop_device *vpdev) +{ + struct mic_device_ctrl __iomem *dc + = (void __iomem *)d + _vop_aligned_desc_size(d); + struct _vop_vdev *vdev = (struct _vop_vdev *)readq(&dc->vdev); + + if (ioread8(&dc->config_change) != MIC_VIRTIO_PARAM_CONFIG_CHANGED) + return; + + dev_dbg(&vpdev->dev, "%s %d\n", __func__, __LINE__); + virtio_config_changed(&vdev->vdev); + iowrite8(1, &dc->guest_ack); +} + +/* + * removes a virtio device if a hot remove event has been + * requested by the host. + */ +static int _vop_remove_device(struct mic_device_desc __iomem *d, + unsigned int offset, struct vop_device *vpdev) +{ + struct mic_device_ctrl __iomem *dc + = (void __iomem *)d + _vop_aligned_desc_size(d); + struct _vop_vdev *vdev = (struct _vop_vdev *)readq(&dc->vdev); + u8 status; + int ret = -1; + + if (ioread8(&dc->config_change) == MIC_VIRTIO_PARAM_DEV_REMOVE) { + dev_dbg(&vpdev->dev, + "%s %d config_change %d type %d vdev %p\n", + __func__, __LINE__, + ioread8(&dc->config_change), ioread8(&d->type), vdev); + status = ioread8(&d->status); + reinit_completion(&vdev->reset_done); + unregister_virtio_device(&vdev->vdev); + vpdev->hw_ops->free_irq(vpdev, vdev->virtio_cookie, vdev); + iowrite8(-1, &dc->h2c_vdev_db); + if (status & VIRTIO_CONFIG_S_DRIVER_OK) + wait_for_completion(&vdev->reset_done); + kfree(vdev); + iowrite8(1, &dc->guest_ack); + dev_dbg(&vpdev->dev, "%s %d guest_ack %d\n", + __func__, __LINE__, ioread8(&dc->guest_ack)); + iowrite8(-1, &d->type); + ret = 0; + } + return ret; +} + +#define REMOVE_DEVICES true + +static void _vop_scan_devices(void __iomem *dp, struct vop_device *vpdev, + bool remove, int dnode) +{ + s8 type; + unsigned int i; + struct mic_device_desc __iomem *d; + struct mic_device_ctrl __iomem *dc; + struct device *dev; + int ret; + + for (i = sizeof(struct mic_bootparam); + i < MIC_DP_SIZE; i += _vop_total_desc_size(d)) { + d = dp + i; + dc = (void __iomem *)d + _vop_aligned_desc_size(d); + /* + * This read barrier is paired with the corresponding write + * barrier on the host which is inserted before adding or + * removing a virtio device descriptor, by updating the type. + */ + rmb(); + type = ioread8(&d->type); + + /* end of list */ + if (type == 0) + break; + + if (type == -1) + continue; + + /* device already exists */ + dev = device_find_child(&vpdev->dev, (void __force *)d, + vop_match_desc); + if (dev) { + if (remove) + iowrite8(MIC_VIRTIO_PARAM_DEV_REMOVE, + &dc->config_change); + put_device(dev); + _vop_handle_config_change(d, i, vpdev); + ret = _vop_remove_device(d, i, vpdev); + if (remove) { + iowrite8(0, &dc->config_change); + iowrite8(0, &dc->guest_ack); + } + continue; + } + + /* new device */ + dev_dbg(&vpdev->dev, "%s %d Adding new virtio device %p\n", + __func__, __LINE__, d); + if (!remove) + _vop_add_device(d, i, vpdev, dnode); + } +} + +static void vop_scan_devices(struct vop_info *vi, + struct vop_device *vpdev, bool remove) +{ + void __iomem *dp = vpdev->hw_ops->get_remote_dp(vpdev); + + if (!dp) + return; + mutex_lock(&vi->vop_mutex); + _vop_scan_devices(dp, vpdev, remove, vpdev->dnode); + mutex_unlock(&vi->vop_mutex); +} + +/* + * vop_hotplug_device tries to find changes in the device page. + */ +static void vop_hotplug_devices(struct work_struct *work) +{ + struct vop_info *vi = container_of(work, struct vop_info, + hotplug_work); + + vop_scan_devices(vi, vi->vpdev, !REMOVE_DEVICES); +} + +/* + * Interrupt handler for hot plug/config changes etc. + */ +static irqreturn_t vop_extint_handler(int irq, void *data) +{ + struct vop_info *vi = data; + struct mic_bootparam __iomem *bp; + struct vop_device *vpdev = vi->vpdev; + + bp = vpdev->hw_ops->get_remote_dp(vpdev); + dev_dbg(&vpdev->dev, "%s %d hotplug work\n", + __func__, __LINE__); + vpdev->hw_ops->ack_interrupt(vpdev, ioread8(&bp->h2c_config_db)); + schedule_work(&vi->hotplug_work); + return IRQ_HANDLED; +} + +static int vop_driver_probe(struct vop_device *vpdev) +{ + struct vop_info *vi; + int rc; + + vi = kzalloc(sizeof(*vi), GFP_KERNEL); + if (!vi) { + rc = -ENOMEM; + goto exit; + } + dev_set_drvdata(&vpdev->dev, vi); + vi->vpdev = vpdev; + + mutex_init(&vi->vop_mutex); + INIT_WORK(&vi->hotplug_work, vop_hotplug_devices); + if (vpdev->dnode) { + rc = vop_host_init(vi); + if (rc < 0) + goto free; + } else { + struct mic_bootparam __iomem *bootparam; + + vop_scan_devices(vi, vpdev, !REMOVE_DEVICES); + + vi->h2c_config_db = vpdev->hw_ops->next_db(vpdev); + vi->cookie = vpdev->hw_ops->request_irq(vpdev, + vop_extint_handler, + "virtio_config_intr", + vi, vi->h2c_config_db); + if (IS_ERR(vi->cookie)) { + rc = PTR_ERR(vi->cookie); + goto free; + } + bootparam = vpdev->hw_ops->get_remote_dp(vpdev); + iowrite8(vi->h2c_config_db, &bootparam->h2c_config_db); + } + vop_init_debugfs(vi); + return 0; +free: + kfree(vi); +exit: + return rc; +} + +static void vop_driver_remove(struct vop_device *vpdev) +{ + struct vop_info *vi = dev_get_drvdata(&vpdev->dev); + + if (vpdev->dnode) { + vop_host_uninit(vi); + } else { + struct mic_bootparam __iomem *bootparam = + vpdev->hw_ops->get_remote_dp(vpdev); + if (bootparam) + iowrite8(-1, &bootparam->h2c_config_db); + vpdev->hw_ops->free_irq(vpdev, vi->cookie, vi); + flush_work(&vi->hotplug_work); + vop_scan_devices(vi, vpdev, REMOVE_DEVICES); + } + vop_exit_debugfs(vi); + kfree(vi); +} + +static struct vop_device_id id_table[] = { + { VOP_DEV_TRNSP, VOP_DEV_ANY_ID }, + { 0 }, +}; + +static struct vop_driver vop_driver = { + .driver.name = KBUILD_MODNAME, + .driver.owner = THIS_MODULE, + .id_table = id_table, + .probe = vop_driver_probe, + .remove = vop_driver_remove, +}; + +module_vop_driver(vop_driver); + +MODULE_DEVICE_TABLE(mbus, id_table); +MODULE_AUTHOR("Intel Corporation"); +MODULE_DESCRIPTION("Intel(R) Virtio Over PCIe (VOP) driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 8810df37762746657cfe84014a8f30758e8f366a Mon Sep 17 00:00:00 2001 From: Sudeep Dutt Date: Mon, 8 Feb 2016 15:48:17 -0800 Subject: misc: mic: Enable VOP debugfs and driver build This patch moves the virtio specific debugfs hooks previously in mic_debugfs.c in the MIC host driver into the VOP driver. The Kconfig/Makefile is also updated to allow building the VOP driver. Reviewed-by: Ashutosh Dixit Signed-off-by: Sudeep Dutt Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/Kconfig | 20 ++++ drivers/misc/mic/Makefile | 1 + drivers/misc/mic/vop/Makefile | 9 ++ drivers/misc/mic/vop/vop_debugfs.c | 232 +++++++++++++++++++++++++++++++++++++ 4 files changed, 262 insertions(+) create mode 100644 drivers/misc/mic/vop/Makefile create mode 100644 drivers/misc/mic/vop/vop_debugfs.c (limited to 'drivers') diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig index 840f7ef1a141..b03bb17cae77 100644 --- a/drivers/misc/mic/Kconfig +++ b/drivers/misc/mic/Kconfig @@ -124,3 +124,23 @@ config MIC_COSM More information about the Intel MIC family as well as the Linux OS and tools for MIC to use with this driver are available from . + +comment "VOP Driver" + +config VOP + tristate "VOP Driver" + depends on 64BIT && PCI && X86 && VOP_BUS + select VHOST_RING + help + This enables VOP (Virtio over PCIe) Driver support for the Intel + Many Integrated Core (MIC) family of PCIe form factor coprocessor + devices. The VOP driver allows virtio drivers, e.g. net, console + and block drivers, on the card connect to user space virtio + devices on the host. + + If you are building a host kernel with an Intel MIC device then + say M (recommended) or Y, else say N. If unsure say N. + + More information about the Intel MIC family as well as the Linux + OS and tools for MIC to use with this driver are available from + . diff --git a/drivers/misc/mic/Makefile b/drivers/misc/mic/Makefile index e288a1106738..f2b1323ff96c 100644 --- a/drivers/misc/mic/Makefile +++ b/drivers/misc/mic/Makefile @@ -8,3 +8,4 @@ obj-y += bus/ obj-$(CONFIG_SCIF) += scif/ obj-$(CONFIG_MIC_COSM) += cosm/ obj-$(CONFIG_MIC_COSM) += cosm_client/ +obj-$(CONFIG_VOP) += vop/ diff --git a/drivers/misc/mic/vop/Makefile b/drivers/misc/mic/vop/Makefile new file mode 100644 index 000000000000..78819c8999f1 --- /dev/null +++ b/drivers/misc/mic/vop/Makefile @@ -0,0 +1,9 @@ +# +# Makefile - Intel MIC Linux driver. +# Copyright(c) 2016, Intel Corporation. +# +obj-m := vop.o + +vop-objs += vop_main.o +vop-objs += vop_debugfs.o +vop-objs += vop_vringh.o diff --git a/drivers/misc/mic/vop/vop_debugfs.c b/drivers/misc/mic/vop/vop_debugfs.c new file mode 100644 index 000000000000..ab43884e5cd7 --- /dev/null +++ b/drivers/misc/mic/vop/vop_debugfs.c @@ -0,0 +1,232 @@ +/* + * Intel MIC Platform Software Stack (MPSS) + * + * Copyright(c) 2016 Intel Corporation. + * + * 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. + * + * 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. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Intel Virtio Over PCIe (VOP) driver. + * + */ +#include +#include + +#include "vop_main.h" + +static int vop_dp_show(struct seq_file *s, void *pos) +{ + struct mic_device_desc *d; + struct mic_device_ctrl *dc; + struct mic_vqconfig *vqconfig; + __u32 *features; + __u8 *config; + struct vop_info *vi = s->private; + struct vop_device *vpdev = vi->vpdev; + struct mic_bootparam *bootparam = vpdev->hw_ops->get_dp(vpdev); + int j, k; + + seq_printf(s, "Bootparam: magic 0x%x\n", + bootparam->magic); + seq_printf(s, "Bootparam: h2c_config_db %d\n", + bootparam->h2c_config_db); + seq_printf(s, "Bootparam: node_id %d\n", + bootparam->node_id); + seq_printf(s, "Bootparam: c2h_scif_db %d\n", + bootparam->c2h_scif_db); + seq_printf(s, "Bootparam: h2c_scif_db %d\n", + bootparam->h2c_scif_db); + seq_printf(s, "Bootparam: scif_host_dma_addr 0x%llx\n", + bootparam->scif_host_dma_addr); + seq_printf(s, "Bootparam: scif_card_dma_addr 0x%llx\n", + bootparam->scif_card_dma_addr); + + for (j = sizeof(*bootparam); + j < MIC_DP_SIZE; j += mic_total_desc_size(d)) { + d = (void *)bootparam + j; + dc = (void *)d + mic_aligned_desc_size(d); + + /* end of list */ + if (d->type == 0) + break; + + if (d->type == -1) + continue; + + seq_printf(s, "Type %d ", d->type); + seq_printf(s, "Num VQ %d ", d->num_vq); + seq_printf(s, "Feature Len %d\n", d->feature_len); + seq_printf(s, "Config Len %d ", d->config_len); + seq_printf(s, "Shutdown Status %d\n", d->status); + + for (k = 0; k < d->num_vq; k++) { + vqconfig = mic_vq_config(d) + k; + seq_printf(s, "vqconfig[%d]: ", k); + seq_printf(s, "address 0x%llx ", + vqconfig->address); + seq_printf(s, "num %d ", vqconfig->num); + seq_printf(s, "used address 0x%llx\n", + vqconfig->used_address); + } + + features = (__u32 *)mic_vq_features(d); + seq_printf(s, "Features: Host 0x%x ", features[0]); + seq_printf(s, "Guest 0x%x\n", features[1]); + + config = mic_vq_configspace(d); + for (k = 0; k < d->config_len; k++) + seq_printf(s, "config[%d]=%d\n", k, config[k]); + + seq_puts(s, "Device control:\n"); + seq_printf(s, "Config Change %d ", dc->config_change); + seq_printf(s, "Vdev reset %d\n", dc->vdev_reset); + seq_printf(s, "Guest Ack %d ", dc->guest_ack); + seq_printf(s, "Host ack %d\n", dc->host_ack); + seq_printf(s, "Used address updated %d ", + dc->used_address_updated); + seq_printf(s, "Vdev 0x%llx\n", dc->vdev); + seq_printf(s, "c2h doorbell %d ", dc->c2h_vdev_db); + seq_printf(s, "h2c doorbell %d\n", dc->h2c_vdev_db); + } + schedule_work(&vi->hotplug_work); + return 0; +} + +static int vop_dp_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, vop_dp_show, inode->i_private); +} + +static int vop_dp_debug_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static const struct file_operations dp_ops = { + .owner = THIS_MODULE, + .open = vop_dp_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = vop_dp_debug_release +}; + +static int vop_vdev_info_show(struct seq_file *s, void *unused) +{ + struct vop_info *vi = s->private; + struct list_head *pos, *tmp; + struct vop_vdev *vdev; + int i, j; + + mutex_lock(&vi->vop_mutex); + list_for_each_safe(pos, tmp, &vi->vdev_list) { + vdev = list_entry(pos, struct vop_vdev, list); + seq_printf(s, "VDEV type %d state %s in %ld out %ld in_dma %ld out_dma %ld\n", + vdev->virtio_id, + vop_vdevup(vdev) ? "UP" : "DOWN", + vdev->in_bytes, + vdev->out_bytes, + vdev->in_bytes_dma, + vdev->out_bytes_dma); + for (i = 0; i < MIC_MAX_VRINGS; i++) { + struct vring_desc *desc; + struct vring_avail *avail; + struct vring_used *used; + struct vop_vringh *vvr = &vdev->vvr[i]; + struct vringh *vrh = &vvr->vrh; + int num = vrh->vring.num; + + if (!num) + continue; + desc = vrh->vring.desc; + seq_printf(s, "vring i %d avail_idx %d", + i, vvr->vring.info->avail_idx & (num - 1)); + seq_printf(s, " vring i %d avail_idx %d\n", + i, vvr->vring.info->avail_idx); + seq_printf(s, "vrh i %d weak_barriers %d", + i, vrh->weak_barriers); + seq_printf(s, " last_avail_idx %d last_used_idx %d", + vrh->last_avail_idx, vrh->last_used_idx); + seq_printf(s, " completed %d\n", vrh->completed); + for (j = 0; j < num; j++) { + seq_printf(s, "desc[%d] addr 0x%llx len %d", + j, desc->addr, desc->len); + seq_printf(s, " flags 0x%x next %d\n", + desc->flags, desc->next); + desc++; + } + avail = vrh->vring.avail; + seq_printf(s, "avail flags 0x%x idx %d\n", + vringh16_to_cpu(vrh, avail->flags), + vringh16_to_cpu(vrh, + avail->idx) & (num - 1)); + seq_printf(s, "avail flags 0x%x idx %d\n", + vringh16_to_cpu(vrh, avail->flags), + vringh16_to_cpu(vrh, avail->idx)); + for (j = 0; j < num; j++) + seq_printf(s, "avail ring[%d] %d\n", + j, avail->ring[j]); + used = vrh->vring.used; + seq_printf(s, "used flags 0x%x idx %d\n", + vringh16_to_cpu(vrh, used->flags), + vringh16_to_cpu(vrh, used->idx) & (num - 1)); + seq_printf(s, "used flags 0x%x idx %d\n", + vringh16_to_cpu(vrh, used->flags), + vringh16_to_cpu(vrh, used->idx)); + for (j = 0; j < num; j++) + seq_printf(s, "used ring[%d] id %d len %d\n", + j, vringh32_to_cpu(vrh, + used->ring[j].id), + vringh32_to_cpu(vrh, + used->ring[j].len)); + } + } + mutex_unlock(&vi->vop_mutex); + + return 0; +} + +static int vop_vdev_info_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, vop_vdev_info_show, inode->i_private); +} + +static int vop_vdev_info_debug_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static const struct file_operations vdev_info_ops = { + .owner = THIS_MODULE, + .open = vop_vdev_info_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = vop_vdev_info_debug_release +}; + +void vop_init_debugfs(struct vop_info *vi) +{ + char name[16]; + + snprintf(name, sizeof(name), "%s%d", KBUILD_MODNAME, vi->vpdev->dnode); + vi->dbg = debugfs_create_dir(name, NULL); + if (!vi->dbg) { + pr_err("can't create debugfs dir vop\n"); + return; + } + debugfs_create_file("dp", 0444, vi->dbg, vi, &dp_ops); + debugfs_create_file("vdev_info", 0444, vi->dbg, vi, &vdev_info_ops); +} + +void vop_exit_debugfs(struct vop_info *vi) +{ + debugfs_remove_recursive(vi->dbg); +} -- cgit v1.2.3 From c74c9318a3a76c3714785bc06147dd207a9d0aa3 Mon Sep 17 00:00:00 2001 From: Sudeep Dutt Date: Mon, 8 Feb 2016 15:48:18 -0800 Subject: misc: mic: MIC host and card driver changes to enable VOP This patch modifies the MIC host and card drivers to start using the VOP driver. The MIC host and card drivers now implement the VOP bus operations and register a VOP device on the VOP bus. MIC driver stack documentation is also updated to include the new VOP driver. Reviewed-by: Ashutosh Dixit Signed-off-by: Sudeep Dutt Signed-off-by: Greg Kroah-Hartman --- Documentation/mic/mic_overview.txt | 54 ++++++++-------- Documentation/mic/mpssd/mpss | 2 +- Documentation/mic/mpssd/mpssd.c | 2 +- drivers/misc/mic/Kconfig | 7 ++- drivers/misc/mic/card/mic_device.c | 84 ++++++++++++++++++++++++- drivers/misc/mic/card/mic_device.h | 3 + drivers/misc/mic/card/mic_x100.c | 1 + drivers/misc/mic/host/mic_boot.c | 123 ++++++++++++++++++++++++++++++++++++- drivers/misc/mic/host/mic_device.h | 3 + drivers/misc/mic/host/mic_main.c | 1 + 10 files changed, 247 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/Documentation/mic/mic_overview.txt b/Documentation/mic/mic_overview.txt index 73f44fc3e715..074adbdf83a4 100644 --- a/Documentation/mic/mic_overview.txt +++ b/Documentation/mic/mic_overview.txt @@ -12,10 +12,19 @@ for the X100 devices. Since it is a PCIe card, it does not have the ability to host hardware devices for networking, storage and console. We provide these devices -on X100 coprocessors thus enabling a self-bootable equivalent environment -for applications. A key benefit of our solution is that it leverages -the standard virtio framework for network, disk and console devices, -though in our case the virtio framework is used across a PCIe bus. +on X100 coprocessors thus enabling a self-bootable equivalent +environment for applications. A key benefit of our solution is that it +leverages the standard virtio framework for network, disk and console +devices, though in our case the virtio framework is used across a PCIe +bus. A Virtio Over PCIe (VOP) driver allows creating user space +backends or devices on the host which are used to probe virtio drivers +for these devices on the MIC card. The existing VRINGH infrastructure +in the kernel is used to access virtio rings from the host. The card +VOP driver allows card virtio drivers to communicate with their user +space backends on the host via a device page. Ring 3 apps on the host +can add, remove and configure virtio devices. A thin MIC specific +virtio_config_ops is implemented which is borrowed heavily from +previous similar implementations in lguest and s390. MIC PCIe card has a dma controller with 8 channels. These channels are shared between the host s/w and the card s/w. 0 to 3 are used by host @@ -38,7 +47,6 @@ single threaded performance for the host compared to MIC, the ability of the host to initiate DMA's to/from the card using the MIC DMA engine and the fact that the virtio block storage backend can only be on the host. - | +----------+ | +----------+ | Card OS | | | Host OS | +----------+ | +----------+ @@ -47,27 +55,25 @@ the fact that the virtio block storage backend can only be on the host. | Virtio| |Virtio | |Virtio| | |Virtio | |Virtio | |Virtio | | Net | |Console | |Block | | |Net | |Console | |Block | | Driver| |Driver | |Driver| | |backend | |backend | |backend | - +-------+ +--------+ +------+ | +---------+ +--------+ +--------+ + +---+---+ +---+----+ +--+---+ | +---------+ +----+---+ +--------+ | | | | | | | | | | |User | | | - | | | |------|------------|---------|------- - +-------------------+ |Kernel +--------------------------+ - | | | Virtio over PCIe IOCTLs | - | | +--------------------------+ -+-----------+ | | | +-----------+ -| MIC DMA | | +------+ | +------+ +------+ | | MIC DMA | -| Driver | | | SCIF | | | SCIF | | COSM | | | Driver | -+-----------+ | +------+ | +------+ +--+---+ | +-----------+ - | | | | | | | | -+---------------+ | +------+ | +--+---+ +--+---+ | +----------------+ -|MIC virtual Bus| | |SCIF | | |SCIF | | COSM | | |MIC virtual Bus | -+---------------+ | |HW Bus| | |HW Bus| | Bus | | +----------------+ - | | +------+ | +--+---+ +------+ | | - | | | | | | | | - | +-----------+---+ | | | +---------------+ | - | |Intel MIC | | | | |Intel MIC | | - +---|Card Driver | | | | |Host Driver | | - +------------+--------+ | +----+---------------+-----+ + | | | |------|------------|--+------|------- + +---------+---------+ |Kernel | + | | | + +---------+ +---+----+ +------+ | +------+ +------+ +--+---+ +-------+ + |MIC DMA | | VOP | | SCIF | | | SCIF | | COSM | | VOP | |MIC DMA| + +---+-----+ +---+----+ +--+---+ | +--+---+ +--+---+ +------+ +----+--+ + | | | | | | | + +---+-----+ +---+----+ +--+---+ | +--+---+ +--+---+ +------+ +----+--+ + |MIC | | VOP | |SCIF | | |SCIF | | COSM | | VOP | | MIC | + |HW Bus | | HW Bus| |HW Bus| | |HW Bus| | Bus | |HW Bus| |HW Bus | + +---------+ +--------+ +--+---+ | +--+---+ +------+ +------+ +-------+ + | | | | | | | + | +-----------+--+ | | | +---------------+ | + | |Intel MIC | | | | |Intel MIC | | + | |Card Driver | | | | |Host Driver | | + +---+--------------+------+ | +----+---------------+-----+ | | | +-------------------------------------------------------------+ | | diff --git a/Documentation/mic/mpssd/mpss b/Documentation/mic/mpssd/mpss index 09ea90931649..5fcf9fa4b082 100755 --- a/Documentation/mic/mpssd/mpss +++ b/Documentation/mic/mpssd/mpss @@ -35,7 +35,7 @@ exec=/usr/sbin/mpssd sysfs="/sys/class/mic" -mic_modules="mic_host mic_x100_dma scif" +mic_modules="mic_host mic_x100_dma scif vop" start() { diff --git a/Documentation/mic/mpssd/mpssd.c b/Documentation/mic/mpssd/mpssd.c index aaeafa18d99b..518dece71578 100644 --- a/Documentation/mic/mpssd/mpssd.c +++ b/Documentation/mic/mpssd/mpssd.c @@ -926,7 +926,7 @@ add_virtio_device(struct mic_info *mic, struct mic_device_desc *dd) char path[PATH_MAX]; int fd, err; - snprintf(path, PATH_MAX, "/dev/mic%d", mic->id); + snprintf(path, PATH_MAX, "/dev/vop_virtio%d", mic->id); fd = open(path, O_RDWR); if (fd < 0) { mpsslog("Could not open %s %s\n", path, strerror(errno)); diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig index b03bb17cae77..2e4f3ba75c8e 100644 --- a/drivers/misc/mic/Kconfig +++ b/drivers/misc/mic/Kconfig @@ -53,8 +53,8 @@ comment "Intel MIC Host Driver" config INTEL_MIC_HOST tristate "Intel MIC Host Driver" - depends on 64BIT && PCI && X86 && INTEL_MIC_BUS && SCIF_BUS && MIC_COSM - select VHOST_RING + depends on 64BIT && PCI && X86 + depends on INTEL_MIC_BUS && SCIF_BUS && MIC_COSM && VOP_BUS help This enables Host Driver support for the Intel Many Integrated Core (MIC) family of PCIe form factor coprocessor devices that @@ -73,7 +73,8 @@ comment "Intel MIC Card Driver" config INTEL_MIC_CARD tristate "Intel MIC Card Driver" - depends on 64BIT && X86 && INTEL_MIC_BUS && SCIF_BUS && MIC_COSM + depends on 64BIT && X86 + depends on INTEL_MIC_BUS && SCIF_BUS && MIC_COSM && VOP_BUS select VIRTIO help This enables card driver support for the Intel Many Integrated diff --git a/drivers/misc/mic/card/mic_device.c b/drivers/misc/mic/card/mic_device.c index ff03c633541c..e749af48f736 100644 --- a/drivers/misc/mic/card/mic_device.c +++ b/drivers/misc/mic/card/mic_device.c @@ -249,12 +249,82 @@ static struct scif_hw_ops scif_hw_ops = { .iounmap = ___mic_iounmap, }; +static inline struct mic_driver *vpdev_to_mdrv(struct vop_device *vpdev) +{ + return dev_get_drvdata(vpdev->dev.parent); +} + +static struct mic_irq * +__mic_request_irq(struct vop_device *vpdev, + irqreturn_t (*func)(int irq, void *data), + const char *name, void *data, int intr_src) +{ + return mic_request_card_irq(func, NULL, name, data, intr_src); +} + +static void __mic_free_irq(struct vop_device *vpdev, + struct mic_irq *cookie, void *data) +{ + return mic_free_card_irq(cookie, data); +} + +static void __mic_ack_interrupt(struct vop_device *vpdev, int num) +{ + struct mic_driver *mdrv = vpdev_to_mdrv(vpdev); + + mic_ack_interrupt(&mdrv->mdev); +} + +static int __mic_next_db(struct vop_device *vpdev) +{ + return mic_next_card_db(); +} + +static void __iomem *__mic_get_remote_dp(struct vop_device *vpdev) +{ + struct mic_driver *mdrv = vpdev_to_mdrv(vpdev); + + return mdrv->dp; +} + +static void __mic_send_intr(struct vop_device *vpdev, int db) +{ + struct mic_driver *mdrv = vpdev_to_mdrv(vpdev); + + mic_send_intr(&mdrv->mdev, db); +} + +static void __iomem *__mic_ioremap(struct vop_device *vpdev, + dma_addr_t pa, size_t len) +{ + struct mic_driver *mdrv = vpdev_to_mdrv(vpdev); + + return mic_card_map(&mdrv->mdev, pa, len); +} + +static void __mic_iounmap(struct vop_device *vpdev, void __iomem *va) +{ + struct mic_driver *mdrv = vpdev_to_mdrv(vpdev); + + mic_card_unmap(&mdrv->mdev, va); +} + +static struct vop_hw_ops vop_hw_ops = { + .request_irq = __mic_request_irq, + .free_irq = __mic_free_irq, + .ack_interrupt = __mic_ack_interrupt, + .next_db = __mic_next_db, + .get_remote_dp = __mic_get_remote_dp, + .send_intr = __mic_send_intr, + .ioremap = __mic_ioremap, + .iounmap = __mic_iounmap, +}; + static int mic_request_dma_chans(struct mic_driver *mdrv) { dma_cap_mask_t mask; struct dma_chan *chan; - request_module("mic_x100_dma"); dma_cap_zero(mask); dma_cap_set(DMA_MEMCPY, mask); @@ -308,6 +378,13 @@ int __init mic_driver_init(struct mic_driver *mdrv) rc = -ENODEV; goto irq_uninit; } + mdrv->vpdev = vop_register_device(mdrv->dev, VOP_DEV_TRNSP, + NULL, &vop_hw_ops, 0, + NULL, mdrv->dma_ch[0]); + if (IS_ERR(mdrv->vpdev)) { + rc = PTR_ERR(mdrv->vpdev); + goto dma_free; + } bootparam = mdrv->dp; node_id = ioread8(&bootparam->node_id); mdrv->scdev = scif_register_device(mdrv->dev, MIC_SCIF_DEV, @@ -317,11 +394,13 @@ int __init mic_driver_init(struct mic_driver *mdrv) mdrv->num_dma_ch, true); if (IS_ERR(mdrv->scdev)) { rc = PTR_ERR(mdrv->scdev); - goto dma_free; + goto vop_remove; } mic_create_card_debug_dir(mdrv); done: return rc; +vop_remove: + vop_unregister_device(mdrv->vpdev); dma_free: mic_free_dma_chans(mdrv); irq_uninit: @@ -342,6 +421,7 @@ void mic_driver_uninit(struct mic_driver *mdrv) { mic_delete_card_debug_dir(mdrv); scif_unregister_device(mdrv->scdev); + vop_unregister_device(mdrv->vpdev); mic_free_dma_chans(mdrv); mic_uninit_irq(); mic_dp_uninit(); diff --git a/drivers/misc/mic/card/mic_device.h b/drivers/misc/mic/card/mic_device.h index 1dbf83c41289..333dbed972f6 100644 --- a/drivers/misc/mic/card/mic_device.h +++ b/drivers/misc/mic/card/mic_device.h @@ -32,6 +32,7 @@ #include #include #include "../bus/scif_bus.h" +#include "../bus/vop_bus.h" /** * struct mic_intr_info - Contains h/w specific interrupt sources info @@ -76,6 +77,7 @@ struct mic_device { * @dma_ch - Array of DMA channels * @num_dma_ch - Number of DMA channels available * @scdev: SCIF device on the SCIF virtual bus. + * @vpdev: Virtio over PCIe device on the VOP virtual bus. */ struct mic_driver { char name[20]; @@ -90,6 +92,7 @@ struct mic_driver { struct dma_chan *dma_ch[MIC_MAX_DMA_CHAN]; int num_dma_ch; struct scif_hw_dev *scdev; + struct vop_device *vpdev; }; /** diff --git a/drivers/misc/mic/card/mic_x100.c b/drivers/misc/mic/card/mic_x100.c index b2958ce2368c..b9f0710ffa6b 100644 --- a/drivers/misc/mic/card/mic_x100.c +++ b/drivers/misc/mic/card/mic_x100.c @@ -326,6 +326,7 @@ static int __init mic_init(void) goto done; } + request_module("mic_x100_dma"); mic_init_card_debugfs(); ret = platform_device_register(&mic_platform_dev); if (ret) { diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c index 3df305f6282c..8c91c9950b54 100644 --- a/drivers/misc/mic/host/mic_boot.c +++ b/drivers/misc/mic/host/mic_boot.c @@ -25,10 +25,118 @@ #include #include #include "../bus/scif_bus.h" +#include "../bus/vop_bus.h" #include "../common/mic_dev.h" #include "mic_device.h" #include "mic_smpt.h" +static inline struct mic_device *vpdev_to_mdev(struct device *dev) +{ + return dev_get_drvdata(dev->parent); +} + +static dma_addr_t +_mic_dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction dir, struct dma_attrs *attrs) +{ + void *va = phys_to_virt(page_to_phys(page)) + offset; + struct mic_device *mdev = vpdev_to_mdev(dev); + + return mic_map_single(mdev, va, size); +} + +static void _mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, + size_t size, enum dma_data_direction dir, + struct dma_attrs *attrs) +{ + struct mic_device *mdev = vpdev_to_mdev(dev); + + mic_unmap_single(mdev, dma_addr, size); +} + +static const struct dma_map_ops _mic_dma_ops = { + .map_page = _mic_dma_map_page, + .unmap_page = _mic_dma_unmap_page, +}; + +static struct mic_irq * +__mic_request_irq(struct vop_device *vpdev, + irqreturn_t (*func)(int irq, void *data), + const char *name, void *data, int intr_src) +{ + struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev); + + return mic_request_threaded_irq(mdev, func, NULL, name, data, + intr_src, MIC_INTR_DB); +} + +static void __mic_free_irq(struct vop_device *vpdev, + struct mic_irq *cookie, void *data) +{ + struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev); + + return mic_free_irq(mdev, cookie, data); +} + +static void __mic_ack_interrupt(struct vop_device *vpdev, int num) +{ + struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev); + + mdev->ops->intr_workarounds(mdev); +} + +static int __mic_next_db(struct vop_device *vpdev) +{ + struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev); + + return mic_next_db(mdev); +} + +static void *__mic_get_dp(struct vop_device *vpdev) +{ + struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev); + + return mdev->dp; +} + +static void __iomem *__mic_get_remote_dp(struct vop_device *vpdev) +{ + return NULL; +} + +static void __mic_send_intr(struct vop_device *vpdev, int db) +{ + struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev); + + mdev->ops->send_intr(mdev, db); +} + +static void __iomem *__mic_ioremap(struct vop_device *vpdev, + dma_addr_t pa, size_t len) +{ + struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev); + + return mdev->aper.va + pa; +} + +static void __mic_iounmap(struct vop_device *vpdev, void __iomem *va) +{ + /* nothing to do */ +} + +static struct vop_hw_ops vop_hw_ops = { + .request_irq = __mic_request_irq, + .free_irq = __mic_free_irq, + .ack_interrupt = __mic_ack_interrupt, + .next_db = __mic_next_db, + .get_dp = __mic_get_dp, + .get_remote_dp = __mic_get_remote_dp, + .send_intr = __mic_send_intr, + .ioremap = __mic_ioremap, + .iounmap = __mic_iounmap, +}; + static inline struct mic_device *scdev_to_mdev(struct scif_hw_dev *scdev) { return dev_get_drvdata(scdev->dev.parent); @@ -314,7 +422,6 @@ static int mic_request_dma_chans(struct mic_device *mdev) dma_cap_mask_t mask; struct dma_chan *chan; - request_module("mic_x100_dma"); dma_cap_zero(mask); dma_cap_set(DMA_MEMCPY, mask); @@ -386,9 +493,18 @@ static int _mic_start(struct cosm_device *cdev, int id) goto dma_free; } + mdev->vpdev = vop_register_device(&mdev->pdev->dev, + VOP_DEV_TRNSP, &_mic_dma_ops, + &vop_hw_ops, id + 1, &mdev->aper, + mdev->dma_ch[0]); + if (IS_ERR(mdev->vpdev)) { + rc = PTR_ERR(mdev->vpdev); + goto scif_remove; + } + rc = mdev->ops->load_mic_fw(mdev, NULL); if (rc) - goto scif_remove; + goto vop_remove; mic_smpt_restore(mdev); mic_intr_restore(mdev); mdev->intr_ops->enable_interrupts(mdev); @@ -396,6 +512,8 @@ static int _mic_start(struct cosm_device *cdev, int id) mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32); mdev->ops->send_firmware_intr(mdev); goto unlock_ret; +vop_remove: + vop_unregister_device(mdev->vpdev); scif_remove: scif_unregister_device(mdev->scdev); dma_free: @@ -422,6 +540,7 @@ static void _mic_stop(struct cosm_device *cdev, bool force) * will be the first to be registered and the last to be * unregistered. */ + vop_unregister_device(mdev->vpdev); scif_unregister_device(mdev->scdev); mic_free_dma_chans(mdev); mbus_unregister_device(mdev->dma_mbdev); diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h index 8460de122929..52b12b22f4ae 100644 --- a/drivers/misc/mic/host/mic_device.h +++ b/drivers/misc/mic/host/mic_device.h @@ -29,6 +29,7 @@ #include #include #include "../bus/scif_bus.h" +#include "../bus/vop_bus.h" #include "../bus/cosm_bus.h" #include "mic_intr.h" @@ -68,6 +69,7 @@ extern struct cosm_hw_ops cosm_hw_ops; * @dma_ch - Array of DMA channels * @num_dma_ch - Number of DMA channels available * @scdev: SCIF device on the SCIF virtual bus. + * @vpdev: Virtio over PCIe device on the VOP virtual bus. * @cosm_dev: COSM device */ struct mic_device { @@ -92,6 +94,7 @@ struct mic_device { struct dma_chan *dma_ch[MIC_MAX_DMA_CHAN]; int num_dma_ch; struct scif_hw_dev *scdev; + struct vop_device *vpdev; struct cosm_device *cosm_dev; }; diff --git a/drivers/misc/mic/host/mic_main.c b/drivers/misc/mic/host/mic_main.c index 400def2106e7..035be3e9ceba 100644 --- a/drivers/misc/mic/host/mic_main.c +++ b/drivers/misc/mic/host/mic_main.c @@ -317,6 +317,7 @@ static int __init mic_init(void) { int ret; + request_module("mic_x100_dma"); mic_init_debugfs(); ida_init(&g_mic_ida); ret = pci_register_driver(&mic_driver); -- cgit v1.2.3 From 75f3e8e47f381074801d0034874d20c638d9e3d9 Mon Sep 17 00:00:00 2001 From: Gabriel Somlo Date: Thu, 28 Jan 2016 09:23:11 -0500 Subject: firmware: introduce sysfs driver for QEMU's fw_cfg device Make fw_cfg entries of type "file" available via sysfs. Entries are listed under /sys/firmware/qemu_fw_cfg/by_key, in folders named after each entry's selector key. Filename, selector value, and size read-only attributes are included for each entry. Also, a "raw" attribute allows retrieval of the full binary content of each entry. The fw_cfg device can be instantiated automatically from ACPI or the Device Tree, or manually by using a kernel module (or command line) parameter, with a syntax outlined in the documentation file. Signed-off-by: Gabriel Somlo Signed-off-by: Greg Kroah-Hartman --- .../ABI/testing/sysfs-firmware-qemu_fw_cfg | 58 ++ drivers/firmware/Kconfig | 19 + drivers/firmware/Makefile | 1 + drivers/firmware/qemu_fw_cfg.c | 648 +++++++++++++++++++++ 4 files changed, 726 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg create mode 100644 drivers/firmware/qemu_fw_cfg.c (limited to 'drivers') diff --git a/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg b/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg new file mode 100644 index 000000000000..e9e58d4ea60a --- /dev/null +++ b/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg @@ -0,0 +1,58 @@ +What: /sys/firmware/qemu_fw_cfg/ +Date: August 2015 +Contact: Gabriel Somlo +Description: + Several different architectures supported by QEMU (x86, arm, + sun4*, ppc/mac) are provisioned with a firmware configuration + (fw_cfg) device, originally intended as a way for the host to + provide configuration data to the guest firmware. Starting + with QEMU v2.4, arbitrary fw_cfg file entries may be specified + by the user on the command line, which makes fw_cfg additionally + useful as an out-of-band, asynchronous mechanism for providing + configuration data to the guest userspace. + + The authoritative guest-side hardware interface documentation + to the fw_cfg device can be found in "docs/specs/fw_cfg.txt" + in the QEMU source tree. + + === SysFS fw_cfg Interface === + + The fw_cfg sysfs interface described in this document is only + intended to display discoverable blobs (i.e., those registered + with the file directory), as there is no way to determine the + presence or size of "legacy" blobs (with selector keys between + 0x0002 and 0x0018) programmatically. + + All fw_cfg information is shown under: + + /sys/firmware/qemu_fw_cfg/ + + The only legacy blob displayed is the fw_cfg device revision: + + /sys/firmware/qemu_fw_cfg/rev + + --- Discoverable fw_cfg blobs by selector key --- + + All discoverable blobs listed in the fw_cfg file directory are + displayed as entries named after their unique selector key + value, e.g.: + + /sys/firmware/qemu_fw_cfg/by_key/32 + /sys/firmware/qemu_fw_cfg/by_key/33 + /sys/firmware/qemu_fw_cfg/by_key/34 + ... + + Each such fw_cfg sysfs entry has the following values exported + as attributes: + + name : The 56-byte nul-terminated ASCII string used as the + blob's 'file name' in the fw_cfg directory. + size : The length of the blob, as given in the fw_cfg + directory. + key : The value of the blob's selector key as given in the + fw_cfg directory. This value is the same as used in + the parent directory name. + raw : The raw bytes of the blob, obtained by selecting the + entry via the control register, and reading a number + of bytes equal to the blob size from the data + register. diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 49a3a1185bb6..5130f74ae3bd 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -161,6 +161,25 @@ config RASPBERRYPI_FIRMWARE This option enables support for communicating with the firmware on the Raspberry Pi. +config FW_CFG_SYSFS + tristate "QEMU fw_cfg device support in sysfs" + depends on SYSFS && (ARM || ARM64 || PPC_PMAC || SPARC || X86) + default n + help + Say Y or M here to enable the exporting of the QEMU firmware + configuration (fw_cfg) file entries via sysfs. Entries are + found under /sys/firmware/fw_cfg when this option is enabled + and loaded. + +config FW_CFG_SYSFS_CMDLINE + bool "QEMU fw_cfg device parameter parsing" + depends on FW_CFG_SYSFS + help + Allow the qemu_fw_cfg device to be initialized via the kernel + command line or using a module parameter. + WARNING: Using incorrect parameters (base address in particular) + may crash your system. + config QCOM_SCM bool depends on ARM || ARM64 diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 48dd4175297e..474bada56fcd 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o +obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o obj-$(CONFIG_QCOM_SCM) += qcom_scm.o obj-$(CONFIG_QCOM_SCM_64) += qcom_scm-64.o obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c new file mode 100644 index 000000000000..83e8a5c8f887 --- /dev/null +++ b/drivers/firmware/qemu_fw_cfg.c @@ -0,0 +1,648 @@ +/* + * drivers/firmware/qemu_fw_cfg.c + * + * Copyright 2015 Carnegie Mellon University + * + * Expose entries from QEMU's firmware configuration (fw_cfg) device in + * sysfs (read-only, under "/sys/firmware/qemu_fw_cfg/..."). + * + * The fw_cfg device may be instantiated via either an ACPI node (on x86 + * and select subsets of aarch64), a Device Tree node (on arm), or using + * a kernel module (or command line) parameter with the following syntax: + * + * [fw_cfg.]ioport=@[::] + * or + * [fw_cfg.]mmio=@[::] + * + * where: + * := size of ioport or mmio range + * := physical base address of ioport or mmio range + * := (optional) offset of control register + * := (optional) offset of data register + * + * e.g.: + * fw_cfg.ioport=2@0x510:0:1 (the default on x86) + * or + * fw_cfg.mmio=0xA@0x9020000:8:0 (the default on arm) + */ + +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Gabriel L. Somlo "); +MODULE_DESCRIPTION("QEMU fw_cfg sysfs support"); +MODULE_LICENSE("GPL"); + +/* selector key values for "well-known" fw_cfg entries */ +#define FW_CFG_SIGNATURE 0x00 +#define FW_CFG_ID 0x01 +#define FW_CFG_FILE_DIR 0x19 + +/* size in bytes of fw_cfg signature */ +#define FW_CFG_SIG_SIZE 4 + +/* fw_cfg "file name" is up to 56 characters (including terminating nul) */ +#define FW_CFG_MAX_FILE_PATH 56 + +/* fw_cfg file directory entry type */ +struct fw_cfg_file { + u32 size; + u16 select; + u16 reserved; + char name[FW_CFG_MAX_FILE_PATH]; +}; + +/* fw_cfg device i/o register addresses */ +static bool fw_cfg_is_mmio; +static phys_addr_t fw_cfg_p_base; +static resource_size_t fw_cfg_p_size; +static void __iomem *fw_cfg_dev_base; +static void __iomem *fw_cfg_reg_ctrl; +static void __iomem *fw_cfg_reg_data; + +/* atomic access to fw_cfg device (potentially slow i/o, so using mutex) */ +static DEFINE_MUTEX(fw_cfg_dev_lock); + +/* pick appropriate endianness for selector key */ +static inline u16 fw_cfg_sel_endianness(u16 key) +{ + return fw_cfg_is_mmio ? cpu_to_be16(key) : cpu_to_le16(key); +} + +/* read chunk of given fw_cfg blob (caller responsible for sanity-check) */ +static inline void fw_cfg_read_blob(u16 key, + void *buf, loff_t pos, size_t count) +{ + mutex_lock(&fw_cfg_dev_lock); + iowrite16(fw_cfg_sel_endianness(key), fw_cfg_reg_ctrl); + while (pos-- > 0) + ioread8(fw_cfg_reg_data); + ioread8_rep(fw_cfg_reg_data, buf, count); + mutex_unlock(&fw_cfg_dev_lock); +} + +/* clean up fw_cfg device i/o */ +static void fw_cfg_io_cleanup(void) +{ + if (fw_cfg_is_mmio) { + iounmap(fw_cfg_dev_base); + release_mem_region(fw_cfg_p_base, fw_cfg_p_size); + } else { + ioport_unmap(fw_cfg_dev_base); + release_region(fw_cfg_p_base, fw_cfg_p_size); + } +} + +/* arch-specific ctrl & data register offsets are not available in ACPI, DT */ +#if !(defined(FW_CFG_CTRL_OFF) && defined(FW_CTRL_DATA_OFF)) +# if (defined(CONFIG_ARM) || defined(CONFIG_ARM64)) +# define FW_CFG_CTRL_OFF 0x08 +# define FW_CFG_DATA_OFF 0x00 +# elif (defined(CONFIG_PPC_PMAC) || defined(CONFIG_SPARC32)) /* ppc/mac,sun4m */ +# define FW_CFG_CTRL_OFF 0x00 +# define FW_CFG_DATA_OFF 0x02 +# elif (defined(CONFIG_X86) || defined(CONFIG_SPARC64)) /* x86, sun4u */ +# define FW_CFG_CTRL_OFF 0x00 +# define FW_CFG_DATA_OFF 0x01 +# else +# warning "QEMU FW_CFG may not be available on this architecture!" +# define FW_CFG_CTRL_OFF 0x00 +# define FW_CFG_DATA_OFF 0x01 +# endif +#endif + +/* initialize fw_cfg device i/o from platform data */ +static int fw_cfg_do_platform_probe(struct platform_device *pdev) +{ + char sig[FW_CFG_SIG_SIZE]; + struct resource *range, *ctrl, *data; + + /* acquire i/o range details */ + fw_cfg_is_mmio = false; + range = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!range) { + fw_cfg_is_mmio = true; + range = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!range) + return -EINVAL; + } + fw_cfg_p_base = range->start; + fw_cfg_p_size = resource_size(range); + + if (fw_cfg_is_mmio) { + if (!request_mem_region(fw_cfg_p_base, + fw_cfg_p_size, "fw_cfg_mem")) + return -EBUSY; + fw_cfg_dev_base = ioremap(fw_cfg_p_base, fw_cfg_p_size); + if (!fw_cfg_dev_base) { + release_mem_region(fw_cfg_p_base, fw_cfg_p_size); + return -EFAULT; + } + } else { + if (!request_region(fw_cfg_p_base, + fw_cfg_p_size, "fw_cfg_io")) + return -EBUSY; + fw_cfg_dev_base = ioport_map(fw_cfg_p_base, fw_cfg_p_size); + if (!fw_cfg_dev_base) { + release_region(fw_cfg_p_base, fw_cfg_p_size); + return -EFAULT; + } + } + + /* were custom register offsets provided (e.g. on the command line)? */ + ctrl = platform_get_resource_byname(pdev, IORESOURCE_REG, "ctrl"); + data = platform_get_resource_byname(pdev, IORESOURCE_REG, "data"); + if (ctrl && data) { + fw_cfg_reg_ctrl = fw_cfg_dev_base + ctrl->start; + fw_cfg_reg_data = fw_cfg_dev_base + data->start; + } else { + /* use architecture-specific offsets */ + fw_cfg_reg_ctrl = fw_cfg_dev_base + FW_CFG_CTRL_OFF; + fw_cfg_reg_data = fw_cfg_dev_base + FW_CFG_DATA_OFF; + } + + /* verify fw_cfg device signature */ + fw_cfg_read_blob(FW_CFG_SIGNATURE, sig, 0, FW_CFG_SIG_SIZE); + if (memcmp(sig, "QEMU", FW_CFG_SIG_SIZE) != 0) { + fw_cfg_io_cleanup(); + return -ENODEV; + } + + return 0; +} + +/* fw_cfg revision attribute, in /sys/firmware/qemu_fw_cfg top-level dir. */ +static u32 fw_cfg_rev; + +static ssize_t fw_cfg_showrev(struct kobject *k, struct attribute *a, char *buf) +{ + return sprintf(buf, "%u\n", fw_cfg_rev); +} + +static const struct { + struct attribute attr; + ssize_t (*show)(struct kobject *k, struct attribute *a, char *buf); +} fw_cfg_rev_attr = { + .attr = { .name = "rev", .mode = S_IRUSR }, + .show = fw_cfg_showrev, +}; + +/* fw_cfg_sysfs_entry type */ +struct fw_cfg_sysfs_entry { + struct kobject kobj; + struct fw_cfg_file f; + struct list_head list; +}; + +/* get fw_cfg_sysfs_entry from kobject member */ +static inline struct fw_cfg_sysfs_entry *to_entry(struct kobject *kobj) +{ + return container_of(kobj, struct fw_cfg_sysfs_entry, kobj); +} + +/* fw_cfg_sysfs_attribute type */ +struct fw_cfg_sysfs_attribute { + struct attribute attr; + ssize_t (*show)(struct fw_cfg_sysfs_entry *entry, char *buf); +}; + +/* get fw_cfg_sysfs_attribute from attribute member */ +static inline struct fw_cfg_sysfs_attribute *to_attr(struct attribute *attr) +{ + return container_of(attr, struct fw_cfg_sysfs_attribute, attr); +} + +/* global cache of fw_cfg_sysfs_entry objects */ +static LIST_HEAD(fw_cfg_entry_cache); + +/* kobjects removed lazily by kernel, mutual exclusion needed */ +static DEFINE_SPINLOCK(fw_cfg_cache_lock); + +static inline void fw_cfg_sysfs_cache_enlist(struct fw_cfg_sysfs_entry *entry) +{ + spin_lock(&fw_cfg_cache_lock); + list_add_tail(&entry->list, &fw_cfg_entry_cache); + spin_unlock(&fw_cfg_cache_lock); +} + +static inline void fw_cfg_sysfs_cache_delist(struct fw_cfg_sysfs_entry *entry) +{ + spin_lock(&fw_cfg_cache_lock); + list_del(&entry->list); + spin_unlock(&fw_cfg_cache_lock); +} + +static void fw_cfg_sysfs_cache_cleanup(void) +{ + struct fw_cfg_sysfs_entry *entry, *next; + + list_for_each_entry_safe(entry, next, &fw_cfg_entry_cache, list) { + /* will end up invoking fw_cfg_sysfs_cache_delist() + * via each object's release() method (i.e. destructor) + */ + kobject_put(&entry->kobj); + } +} + +/* default_attrs: per-entry attributes and show methods */ + +#define FW_CFG_SYSFS_ATTR(_attr) \ +struct fw_cfg_sysfs_attribute fw_cfg_sysfs_attr_##_attr = { \ + .attr = { .name = __stringify(_attr), .mode = S_IRUSR }, \ + .show = fw_cfg_sysfs_show_##_attr, \ +} + +static ssize_t fw_cfg_sysfs_show_size(struct fw_cfg_sysfs_entry *e, char *buf) +{ + return sprintf(buf, "%u\n", e->f.size); +} + +static ssize_t fw_cfg_sysfs_show_key(struct fw_cfg_sysfs_entry *e, char *buf) +{ + return sprintf(buf, "%u\n", e->f.select); +} + +static ssize_t fw_cfg_sysfs_show_name(struct fw_cfg_sysfs_entry *e, char *buf) +{ + return sprintf(buf, "%s\n", e->f.name); +} + +static FW_CFG_SYSFS_ATTR(size); +static FW_CFG_SYSFS_ATTR(key); +static FW_CFG_SYSFS_ATTR(name); + +static struct attribute *fw_cfg_sysfs_entry_attrs[] = { + &fw_cfg_sysfs_attr_size.attr, + &fw_cfg_sysfs_attr_key.attr, + &fw_cfg_sysfs_attr_name.attr, + NULL, +}; + +/* sysfs_ops: find fw_cfg_[entry, attribute] and call appropriate show method */ +static ssize_t fw_cfg_sysfs_attr_show(struct kobject *kobj, struct attribute *a, + char *buf) +{ + struct fw_cfg_sysfs_entry *entry = to_entry(kobj); + struct fw_cfg_sysfs_attribute *attr = to_attr(a); + + return attr->show(entry, buf); +} + +static const struct sysfs_ops fw_cfg_sysfs_attr_ops = { + .show = fw_cfg_sysfs_attr_show, +}; + +/* release: destructor, to be called via kobject_put() */ +static void fw_cfg_sysfs_release_entry(struct kobject *kobj) +{ + struct fw_cfg_sysfs_entry *entry = to_entry(kobj); + + fw_cfg_sysfs_cache_delist(entry); + kfree(entry); +} + +/* kobj_type: ties together all properties required to register an entry */ +static struct kobj_type fw_cfg_sysfs_entry_ktype = { + .default_attrs = fw_cfg_sysfs_entry_attrs, + .sysfs_ops = &fw_cfg_sysfs_attr_ops, + .release = fw_cfg_sysfs_release_entry, +}; + +/* raw-read method and attribute */ +static ssize_t fw_cfg_sysfs_read_raw(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t count) +{ + struct fw_cfg_sysfs_entry *entry = to_entry(kobj); + + if (pos > entry->f.size) + return -EINVAL; + + if (count > entry->f.size - pos) + count = entry->f.size - pos; + + fw_cfg_read_blob(entry->f.select, buf, pos, count); + return count; +} + +static struct bin_attribute fw_cfg_sysfs_attr_raw = { + .attr = { .name = "raw", .mode = S_IRUSR }, + .read = fw_cfg_sysfs_read_raw, +}; + +/* kobjects representing top-level and by_key folders */ +static struct kobject *fw_cfg_top_ko; +static struct kobject *fw_cfg_sel_ko; + +/* register an individual fw_cfg file */ +static int fw_cfg_register_file(const struct fw_cfg_file *f) +{ + int err; + struct fw_cfg_sysfs_entry *entry; + + /* allocate new entry */ + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + /* set file entry information */ + memcpy(&entry->f, f, sizeof(struct fw_cfg_file)); + + /* register entry under "/sys/firmware/qemu_fw_cfg/by_key/" */ + err = kobject_init_and_add(&entry->kobj, &fw_cfg_sysfs_entry_ktype, + fw_cfg_sel_ko, "%d", entry->f.select); + if (err) + goto err_register; + + /* add raw binary content access */ + err = sysfs_create_bin_file(&entry->kobj, &fw_cfg_sysfs_attr_raw); + if (err) + goto err_add_raw; + + /* success, add entry to global cache */ + fw_cfg_sysfs_cache_enlist(entry); + return 0; + +err_add_raw: + kobject_del(&entry->kobj); +err_register: + kfree(entry); + return err; +} + +/* iterate over all fw_cfg directory entries, registering each one */ +static int fw_cfg_register_dir_entries(void) +{ + int ret = 0; + u32 count, i; + struct fw_cfg_file *dir; + size_t dir_size; + + fw_cfg_read_blob(FW_CFG_FILE_DIR, &count, 0, sizeof(count)); + count = be32_to_cpu(count); + dir_size = count * sizeof(struct fw_cfg_file); + + dir = kmalloc(dir_size, GFP_KERNEL); + if (!dir) + return -ENOMEM; + + fw_cfg_read_blob(FW_CFG_FILE_DIR, dir, sizeof(count), dir_size); + + for (i = 0; i < count; i++) { + dir[i].size = be32_to_cpu(dir[i].size); + dir[i].select = be16_to_cpu(dir[i].select); + ret = fw_cfg_register_file(&dir[i]); + if (ret) + break; + } + + kfree(dir); + return ret; +} + +/* unregister top-level or by_key folder */ +static inline void fw_cfg_kobj_cleanup(struct kobject *kobj) +{ + kobject_del(kobj); + kobject_put(kobj); +} + +static int fw_cfg_sysfs_probe(struct platform_device *pdev) +{ + int err; + + /* NOTE: If we supported multiple fw_cfg devices, we'd first create + * a subdirectory named after e.g. pdev->id, then hang per-device + * by_key subdirectories underneath it. However, only + * one fw_cfg device exist system-wide, so if one was already found + * earlier, we might as well stop here. + */ + if (fw_cfg_sel_ko) + return -EBUSY; + + /* create by_key subdirectory of /sys/firmware/qemu_fw_cfg/ */ + err = -ENOMEM; + fw_cfg_sel_ko = kobject_create_and_add("by_key", fw_cfg_top_ko); + if (!fw_cfg_sel_ko) + goto err_sel; + + /* initialize fw_cfg device i/o from platform data */ + err = fw_cfg_do_platform_probe(pdev); + if (err) + goto err_probe; + + /* get revision number, add matching top-level attribute */ + fw_cfg_read_blob(FW_CFG_ID, &fw_cfg_rev, 0, sizeof(fw_cfg_rev)); + fw_cfg_rev = le32_to_cpu(fw_cfg_rev); + err = sysfs_create_file(fw_cfg_top_ko, &fw_cfg_rev_attr.attr); + if (err) + goto err_rev; + + /* process fw_cfg file directory entry, registering each file */ + err = fw_cfg_register_dir_entries(); + if (err) + goto err_dir; + + /* success */ + pr_debug("fw_cfg: loaded.\n"); + return 0; + +err_dir: + fw_cfg_sysfs_cache_cleanup(); + sysfs_remove_file(fw_cfg_top_ko, &fw_cfg_rev_attr.attr); +err_rev: + fw_cfg_io_cleanup(); +err_probe: + fw_cfg_kobj_cleanup(fw_cfg_sel_ko); +err_sel: + return err; +} + +static int fw_cfg_sysfs_remove(struct platform_device *pdev) +{ + pr_debug("fw_cfg: unloading.\n"); + fw_cfg_sysfs_cache_cleanup(); + fw_cfg_kobj_cleanup(fw_cfg_sel_ko); + fw_cfg_io_cleanup(); + return 0; +} + +static const struct of_device_id fw_cfg_sysfs_mmio_match[] = { + { .compatible = "qemu,fw-cfg-mmio", }, + {}, +}; +MODULE_DEVICE_TABLE(of, fw_cfg_sysfs_mmio_match); + +#ifdef CONFIG_ACPI +static const struct acpi_device_id fw_cfg_sysfs_acpi_match[] = { + { "QEMU0002", }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, fw_cfg_sysfs_acpi_match); +#endif + +static struct platform_driver fw_cfg_sysfs_driver = { + .probe = fw_cfg_sysfs_probe, + .remove = fw_cfg_sysfs_remove, + .driver = { + .name = "fw_cfg", + .of_match_table = fw_cfg_sysfs_mmio_match, + .acpi_match_table = ACPI_PTR(fw_cfg_sysfs_acpi_match), + }, +}; + +#ifdef CONFIG_FW_CFG_SYSFS_CMDLINE + +static struct platform_device *fw_cfg_cmdline_dev; + +/* this probably belongs in e.g. include/linux/types.h, + * but right now we are the only ones doing it... + */ +#ifdef CONFIG_PHYS_ADDR_T_64BIT +#define __PHYS_ADDR_PREFIX "ll" +#else +#define __PHYS_ADDR_PREFIX "" +#endif + +/* use special scanf/printf modifier for phys_addr_t, resource_size_t */ +#define PH_ADDR_SCAN_FMT "@%" __PHYS_ADDR_PREFIX "i%n" \ + ":%" __PHYS_ADDR_PREFIX "i" \ + ":%" __PHYS_ADDR_PREFIX "i%n" + +#define PH_ADDR_PR_1_FMT "0x%" __PHYS_ADDR_PREFIX "x@" \ + "0x%" __PHYS_ADDR_PREFIX "x" + +#define PH_ADDR_PR_3_FMT PH_ADDR_PR_1_FMT \ + ":%" __PHYS_ADDR_PREFIX "u" \ + ":%" __PHYS_ADDR_PREFIX "u" + +static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp) +{ + struct resource res[3] = {}; + char *str; + phys_addr_t base; + resource_size_t size, ctrl_off, data_off; + int processed, consumed = 0; + + /* only one fw_cfg device can exist system-wide, so if one + * was processed on the command line already, we might as + * well stop here. + */ + if (fw_cfg_cmdline_dev) { + /* avoid leaking previously registered device */ + platform_device_unregister(fw_cfg_cmdline_dev); + return -EINVAL; + } + + /* consume "" portion of command line argument */ + size = memparse(arg, &str); + + /* get "@[::]" chunks */ + processed = sscanf(str, PH_ADDR_SCAN_FMT, + &base, &consumed, + &ctrl_off, &data_off, &consumed); + + /* sscanf() must process precisely 1 or 3 chunks: + * is mandatory, optionally followed by + * and ; + * there must be no extra characters after the last chunk, + * so str[consumed] must be '\0'. + */ + if (str[consumed] || + (processed != 1 && processed != 3)) + return -EINVAL; + + res[0].start = base; + res[0].end = base + size - 1; + res[0].flags = !strcmp(kp->name, "mmio") ? IORESOURCE_MEM : + IORESOURCE_IO; + + /* insert register offsets, if provided */ + if (processed > 1) { + res[1].name = "ctrl"; + res[1].start = ctrl_off; + res[1].flags = IORESOURCE_REG; + res[2].name = "data"; + res[2].start = data_off; + res[2].flags = IORESOURCE_REG; + } + + /* "processed" happens to nicely match the number of resources + * we need to pass in to this platform device. + */ + fw_cfg_cmdline_dev = platform_device_register_simple("fw_cfg", + PLATFORM_DEVID_NONE, res, processed); + if (IS_ERR(fw_cfg_cmdline_dev)) + return PTR_ERR(fw_cfg_cmdline_dev); + + return 0; +} + +static int fw_cfg_cmdline_get(char *buf, const struct kernel_param *kp) +{ + /* stay silent if device was not configured via the command + * line, or if the parameter name (ioport/mmio) doesn't match + * the device setting + */ + if (!fw_cfg_cmdline_dev || + (!strcmp(kp->name, "mmio") ^ + (fw_cfg_cmdline_dev->resource[0].flags == IORESOURCE_MEM))) + return 0; + + switch (fw_cfg_cmdline_dev->num_resources) { + case 1: + return snprintf(buf, PAGE_SIZE, PH_ADDR_PR_1_FMT, + resource_size(&fw_cfg_cmdline_dev->resource[0]), + fw_cfg_cmdline_dev->resource[0].start); + case 3: + return snprintf(buf, PAGE_SIZE, PH_ADDR_PR_3_FMT, + resource_size(&fw_cfg_cmdline_dev->resource[0]), + fw_cfg_cmdline_dev->resource[0].start, + fw_cfg_cmdline_dev->resource[1].start, + fw_cfg_cmdline_dev->resource[2].start); + } + + /* Should never get here */ + WARN(1, "Unexpected number of resources: %d\n", + fw_cfg_cmdline_dev->num_resources); + return 0; +} + +static const struct kernel_param_ops fw_cfg_cmdline_param_ops = { + .set = fw_cfg_cmdline_set, + .get = fw_cfg_cmdline_get, +}; + +device_param_cb(ioport, &fw_cfg_cmdline_param_ops, NULL, S_IRUSR); +device_param_cb(mmio, &fw_cfg_cmdline_param_ops, NULL, S_IRUSR); + +#endif /* CONFIG_FW_CFG_SYSFS_CMDLINE */ + +static int __init fw_cfg_sysfs_init(void) +{ + /* create /sys/firmware/qemu_fw_cfg/ top level directory */ + fw_cfg_top_ko = kobject_create_and_add("qemu_fw_cfg", firmware_kobj); + if (!fw_cfg_top_ko) + return -ENOMEM; + + return platform_driver_register(&fw_cfg_sysfs_driver); +} + +static void __exit fw_cfg_sysfs_exit(void) +{ + platform_driver_unregister(&fw_cfg_sysfs_driver); + +#ifdef CONFIG_FW_CFG_SYSFS_CMDLINE + platform_device_unregister(fw_cfg_cmdline_dev); +#endif + + /* clean up /sys/firmware/qemu_fw_cfg/ */ + fw_cfg_kobj_cleanup(fw_cfg_top_ko); +} + +module_init(fw_cfg_sysfs_init); +module_exit(fw_cfg_sysfs_exit); -- cgit v1.2.3 From 246c46ebaeaef17814dc5a8830d16e7f1b01116b Mon Sep 17 00:00:00 2001 From: Gabriel Somlo Date: Thu, 28 Jan 2016 09:23:13 -0500 Subject: firmware: create directory hierarchy for sysfs fw_cfg entries Each fw_cfg entry of type "file" has an associated 56-char, nul-terminated ASCII string which represents its name. While the fw_cfg device doesn't itself impose any specific naming convention, QEMU developers have traditionally used path name semantics (i.e. "etc/acpi/rsdp") to descriptively name the various fw_cfg "blobs" passed into the guest. This patch attempts, on a best effort basis, to create a directory hierarchy representing the content of fw_cfg file names, under /sys/firmware/qemu_fw_cfg/by_name. Upon successful creation of all directories representing the "dirname" portion of a fw_cfg file, a symlink will be created to represent the "basename", pointing at the appropriate /sys/firmware/qemu_fw_cfg/by_key entry. If a file name is not suitable for this procedure (e.g., if its basename or dirname components collide with an already existing dirname component or basename, respectively) the corresponding fw_cfg blob is skipped and will remain available in sysfs only by its selector key value. Signed-off-by: Gabriel Somlo Cc: Andy Lutomirski Signed-off-by: Greg Kroah-Hartman --- .../ABI/testing/sysfs-firmware-qemu_fw_cfg | 42 ++++++++ drivers/firmware/qemu_fw_cfg.c | 109 ++++++++++++++++++++- 2 files changed, 148 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg b/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg index e9e58d4ea60a..011dda4f8e8a 100644 --- a/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg +++ b/Documentation/ABI/testing/sysfs-firmware-qemu_fw_cfg @@ -56,3 +56,45 @@ Description: entry via the control register, and reading a number of bytes equal to the blob size from the data register. + + --- Listing fw_cfg blobs by file name --- + + While the fw_cfg device does not impose any specific naming + convention on the blobs registered in the file directory, + QEMU developers have traditionally used path name semantics + to give each blob a descriptive name. For example: + + "bootorder" + "genroms/kvmvapic.bin" + "etc/e820" + "etc/boot-fail-wait" + "etc/system-states" + "etc/table-loader" + "etc/acpi/rsdp" + "etc/acpi/tables" + "etc/smbios/smbios-tables" + "etc/smbios/smbios-anchor" + ... + + In addition to the listing by unique selector key described + above, the fw_cfg sysfs driver also attempts to build a tree + of directories matching the path name components of fw_cfg + blob names, ending in symlinks to the by_key entry for each + "basename", as illustrated below (assume current directory is + /sys/firmware): + + qemu_fw_cfg/by_name/bootorder -> ../by_key/38 + qemu_fw_cfg/by_name/etc/e820 -> ../../by_key/35 + qemu_fw_cfg/by_name/etc/acpi/rsdp -> ../../../by_key/41 + ... + + Construction of the directory tree and symlinks is done on a + "best-effort" basis, as there is no guarantee that components + of fw_cfg blob names are always "well behaved". I.e., there is + the possibility that a symlink (basename) will conflict with + a dirname component of another fw_cfg blob, in which case the + creation of the offending /sys/firmware/qemu_fw_cfg/by_name + entry will be skipped. + + The authoritative list of entries will continue to be found + under the /sys/firmware/qemu_fw_cfg/by_key directory. diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c index 83e8a5c8f887..19f6851be87f 100644 --- a/drivers/firmware/qemu_fw_cfg.c +++ b/drivers/firmware/qemu_fw_cfg.c @@ -334,9 +334,103 @@ static struct bin_attribute fw_cfg_sysfs_attr_raw = { .read = fw_cfg_sysfs_read_raw, }; -/* kobjects representing top-level and by_key folders */ +/* + * Create a kset subdirectory matching each '/' delimited dirname token + * in 'name', starting with sysfs kset/folder 'dir'; At the end, create + * a symlink directed at the given 'target'. + * NOTE: We do this on a best-effort basis, since 'name' is not guaranteed + * to be a well-behaved path name. Whenever a symlink vs. kset directory + * name collision occurs, the kernel will issue big scary warnings while + * refusing to add the offending link or directory. We follow up with our + * own, slightly less scary error messages explaining the situation :) + */ +static int fw_cfg_build_symlink(struct kset *dir, + struct kobject *target, const char *name) +{ + int ret; + struct kset *subdir; + struct kobject *ko; + char *name_copy, *p, *tok; + + if (!dir || !target || !name || !*name) + return -EINVAL; + + /* clone a copy of name for parsing */ + name_copy = p = kstrdup(name, GFP_KERNEL); + if (!name_copy) + return -ENOMEM; + + /* create folders for each dirname token, then symlink for basename */ + while ((tok = strsep(&p, "/")) && *tok) { + + /* last (basename) token? If so, add symlink here */ + if (!p || !*p) { + ret = sysfs_create_link(&dir->kobj, target, tok); + break; + } + + /* does the current dir contain an item named after tok ? */ + ko = kset_find_obj(dir, tok); + if (ko) { + /* drop reference added by kset_find_obj */ + kobject_put(ko); + + /* ko MUST be a kset - we're about to use it as one ! */ + if (ko->ktype != dir->kobj.ktype) { + ret = -EINVAL; + break; + } + + /* descend into already existing subdirectory */ + dir = to_kset(ko); + } else { + /* create new subdirectory kset */ + subdir = kzalloc(sizeof(struct kset), GFP_KERNEL); + if (!subdir) { + ret = -ENOMEM; + break; + } + subdir->kobj.kset = dir; + subdir->kobj.ktype = dir->kobj.ktype; + ret = kobject_set_name(&subdir->kobj, "%s", tok); + if (ret) { + kfree(subdir); + break; + } + ret = kset_register(subdir); + if (ret) { + kfree(subdir); + break; + } + + /* descend into newly created subdirectory */ + dir = subdir; + } + } + + /* we're done with cloned copy of name */ + kfree(name_copy); + return ret; +} + +/* recursively unregister fw_cfg/by_name/ kset directory tree */ +static void fw_cfg_kset_unregister_recursive(struct kset *kset) +{ + struct kobject *k, *next; + + list_for_each_entry_safe(k, next, &kset->list, entry) + /* all set members are ksets too, but check just in case... */ + if (k->ktype == kset->kobj.ktype) + fw_cfg_kset_unregister_recursive(to_kset(k)); + + /* symlinks are cleanly and automatically removed with the directory */ + kset_unregister(kset); +} + +/* kobjects & kset representing top-level, by_key, and by_name folders */ static struct kobject *fw_cfg_top_ko; static struct kobject *fw_cfg_sel_ko; +static struct kset *fw_cfg_fname_kset; /* register an individual fw_cfg file */ static int fw_cfg_register_file(const struct fw_cfg_file *f) @@ -363,6 +457,9 @@ static int fw_cfg_register_file(const struct fw_cfg_file *f) if (err) goto err_add_raw; + /* try adding "/sys/firmware/qemu_fw_cfg/by_name/" symlink */ + fw_cfg_build_symlink(fw_cfg_fname_kset, &entry->kobj, entry->f.name); + /* success, add entry to global cache */ fw_cfg_sysfs_cache_enlist(entry); return 0; @@ -417,18 +514,21 @@ static int fw_cfg_sysfs_probe(struct platform_device *pdev) /* NOTE: If we supported multiple fw_cfg devices, we'd first create * a subdirectory named after e.g. pdev->id, then hang per-device - * by_key subdirectories underneath it. However, only + * by_key (and by_name) subdirectories underneath it. However, only * one fw_cfg device exist system-wide, so if one was already found * earlier, we might as well stop here. */ if (fw_cfg_sel_ko) return -EBUSY; - /* create by_key subdirectory of /sys/firmware/qemu_fw_cfg/ */ + /* create by_key and by_name subdirs of /sys/firmware/qemu_fw_cfg/ */ err = -ENOMEM; fw_cfg_sel_ko = kobject_create_and_add("by_key", fw_cfg_top_ko); if (!fw_cfg_sel_ko) goto err_sel; + fw_cfg_fname_kset = kset_create_and_add("by_name", NULL, fw_cfg_top_ko); + if (!fw_cfg_fname_kset) + goto err_name; /* initialize fw_cfg device i/o from platform data */ err = fw_cfg_do_platform_probe(pdev); @@ -457,6 +557,8 @@ err_dir: err_rev: fw_cfg_io_cleanup(); err_probe: + fw_cfg_kset_unregister_recursive(fw_cfg_fname_kset); +err_name: fw_cfg_kobj_cleanup(fw_cfg_sel_ko); err_sel: return err; @@ -466,6 +568,7 @@ static int fw_cfg_sysfs_remove(struct platform_device *pdev) { pr_debug("fw_cfg: unloading.\n"); fw_cfg_sysfs_cache_cleanup(); + fw_cfg_kset_unregister_recursive(fw_cfg_fname_kset); fw_cfg_kobj_cleanup(fw_cfg_sel_ko); fw_cfg_io_cleanup(); return 0; -- cgit v1.2.3 From 9e5b3d6f7f946a3fb4d83ac2ab6d2bfefcdafffb Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Mon, 4 Jan 2016 22:36:40 +0100 Subject: drivers: dma-coherent: simplify dma_init_coherent_memory return value Since only dma_declare_coherent_memory cares about dma_init_coherent_memory returning part of flags as it return value, move the condition to the former and simplify the latter. This in turn makes rmem_dma_device_init less confusing. Reported-by: Fugang Duan Signed-off-by: Michal Nazarewicz Acked-by: Marek Szyprowski Signed-off-by: Greg Kroah-Hartman --- drivers/base/dma-coherent.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index 55b83983a9c0..87b808374888 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c @@ -17,9 +17,9 @@ struct dma_coherent_mem { spinlock_t spinlock; }; -static int dma_init_coherent_memory(phys_addr_t phys_addr, dma_addr_t device_addr, - size_t size, int flags, - struct dma_coherent_mem **mem) +static bool dma_init_coherent_memory( + phys_addr_t phys_addr, dma_addr_t device_addr, size_t size, int flags, + struct dma_coherent_mem **mem) { struct dma_coherent_mem *dma_mem = NULL; void __iomem *mem_base = NULL; @@ -50,17 +50,13 @@ static int dma_init_coherent_memory(phys_addr_t phys_addr, dma_addr_t device_add spin_lock_init(&dma_mem->spinlock); *mem = dma_mem; - - if (flags & DMA_MEMORY_MAP) - return DMA_MEMORY_MAP; - - return DMA_MEMORY_IO; + return true; out: kfree(dma_mem); if (mem_base) iounmap(mem_base); - return 0; + return false; } static void dma_release_coherent_memory(struct dma_coherent_mem *mem) @@ -88,15 +84,13 @@ int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, dma_addr_t device_addr, size_t size, int flags) { struct dma_coherent_mem *mem; - int ret; - ret = dma_init_coherent_memory(phys_addr, device_addr, size, flags, - &mem); - if (ret == 0) + if (!dma_init_coherent_memory(phys_addr, device_addr, size, flags, + &mem)) return 0; if (dma_assign_coherent_memory(dev, mem) == 0) - return ret; + return flags & DMA_MEMORY_MAP ? DMA_MEMORY_MAP : DMA_MEMORY_IO; dma_release_coherent_memory(mem); return 0; @@ -281,9 +275,9 @@ static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev) struct dma_coherent_mem *mem = rmem->priv; if (!mem && - dma_init_coherent_memory(rmem->base, rmem->base, rmem->size, - DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE, - &mem) != DMA_MEMORY_MAP) { + !dma_init_coherent_memory(rmem->base, rmem->base, rmem->size, + DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE, + &mem)) { pr_err("Reserved memory: failed to init DMA memory pool at %pa, size %ld MiB\n", &rmem->base, (unsigned long)rmem->size / SZ_1M); return -ENODEV; -- cgit v1.2.3 From 4877bb91786e41426bcbec0e151c048a9bd8a1ce Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Tue, 2 Feb 2016 12:57:53 +0530 Subject: component: remove impossible condition We will be evaluating this condition only if match->num == match->alloc and that means we have already dereferenced match which implies match can not be NULL at this point. Moreover we have done a NULL check on match just before this. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/base/component.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/component.c b/drivers/base/component.c index 89f5cf68d80a..2085b234f7c8 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c @@ -265,7 +265,7 @@ void component_match_add_release(struct device *master, } if (match->num == match->alloc) { - size_t new_size = match ? match->alloc + 16 : 15; + size_t new_size = match->alloc + 16; int ret; ret = component_match_realloc(master, match, new_size); -- cgit v1.2.3 From 67d02a1bbb334558e9380409a3cd426b36d4578b Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 13 Nov 2015 09:14:20 +0100 Subject: driver-core: platform: probe of-devices only using list of compatibles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are several indications that make a platform device match a platform driver. For devices that are instantiated by a device tree matching by name, id table or acpi mechanisms doesn't make sense and might result in surprising effects. So limit matching to use the driver's of_match_table for these. Acked-by: Thierry Reding Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index f437afa17f2b..1b5b7b5b50c0 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -949,8 +949,8 @@ static int platform_match(struct device *dev, struct device_driver *drv) return !strcmp(pdev->driver_override, drv->name); /* Attempt an OF style match first */ - if (of_driver_match_device(dev, drv)) - return 1; + if (pdev->dev.of_node) + return of_driver_match_device(dev, drv); /* Then try ACPI style match */ if (acpi_driver_match_device(dev, drv)) -- cgit v1.2.3 From 990162f038400bd229685316beea1155be095125 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 16:54:25 +0100 Subject: char: nwbutton: avoid unused variable warning When CONFIG_NWBUTTON_REBOOT is disabled, we get a warning about an unused variable: drivers/char/nwbutton.c:37:12: warning: 'reboot_count' defined but not used [-Wunused-variable] static int reboot_count = NUM_PRESSES_REBOOT; /* Number of presses to reboot */ Using if(IS_ENABLED()) instead of #ifdef around the user makes the code nicer to read and avoids the warning. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/char/nwbutton.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c index 76c490fa0511..0e184426db98 100644 --- a/drivers/char/nwbutton.c +++ b/drivers/char/nwbutton.c @@ -129,10 +129,9 @@ static void button_consume_callbacks (int bpcount) static void button_sequence_finished (unsigned long parameters) { -#ifdef CONFIG_NWBUTTON_REBOOT /* Reboot using button is enabled */ - if (button_press_count == reboot_count) + if (IS_ENABLED(CONFIG_NWBUTTON_REBOOT) && + button_press_count == reboot_count) kill_cad_pid(SIGINT, 1); /* Ask init to reboot us */ -#endif /* CONFIG_NWBUTTON_REBOOT */ button_consume_callbacks (button_press_count); bcount = sprintf (button_output_buffer, "%d\n", button_press_count); button_press_count = 0; /* Reset the button press counter */ -- cgit v1.2.3 From ca026a3504c2033821b672a09b26d467ae017eb2 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 9 Feb 2016 01:28:10 +0530 Subject: Staging:wlan-ng:Merged two lines into one The last two lines of these functions are compressed into one. Also removed the variable ret as it is now not used. Found using coccinelle: @@ expression e, ret; @@ -ret = +return e; -return ret; Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 682de77e7561..fda8a95cb721 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -1012,7 +1012,6 @@ int hfa384x_cmd_initialize(hfa384x_t *hw) ----------------------------------------------------------------*/ int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport) { - int result = 0; hfa384x_metacmd_t cmd; cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DISABLE) | @@ -1021,9 +1020,7 @@ int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport) cmd.parm1 = 0; cmd.parm2 = 0; - result = hfa384x_docmd_wait(hw, &cmd); - - return result; + return hfa384x_docmd_wait(hw, &cmd); } /*---------------------------------------------------------------- @@ -1048,7 +1045,6 @@ int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport) ----------------------------------------------------------------*/ int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport) { - int result = 0; hfa384x_metacmd_t cmd; cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | @@ -1057,9 +1053,7 @@ int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport) cmd.parm1 = 0; cmd.parm2 = 0; - result = hfa384x_docmd_wait(hw, &cmd); - - return result; + return hfa384x_docmd_wait(hw, &cmd); } /*---------------------------------------------------------------- @@ -1093,7 +1087,6 @@ int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport) ----------------------------------------------------------------*/ int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable) { - int result = 0; hfa384x_metacmd_t cmd; cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_MONITOR) | @@ -1102,9 +1095,7 @@ int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable) cmd.parm1 = 0; cmd.parm2 = 0; - result = hfa384x_docmd_wait(hw, &cmd); - - return result; + return hfa384x_docmd_wait(hw, &cmd); } /*---------------------------------------------------------------- @@ -1148,7 +1139,6 @@ int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable) int hfa384x_cmd_download(hfa384x_t *hw, u16 mode, u16 lowaddr, u16 highaddr, u16 codelen) { - int result = 0; hfa384x_metacmd_t cmd; pr_debug("mode=%d, lowaddr=0x%04x, highaddr=0x%04x, codelen=%d\n", @@ -1161,9 +1151,7 @@ int hfa384x_cmd_download(hfa384x_t *hw, u16 mode, u16 lowaddr, cmd.parm1 = highaddr; cmd.parm2 = codelen; - result = hfa384x_docmd_wait(hw, &cmd); - - return result; + return hfa384x_docmd_wait(hw, &cmd); } /*---------------------------------------------------------------- -- cgit v1.2.3 From 9a66d05d82db0404cf39669052a1cb0da608873c Mon Sep 17 00:00:00 2001 From: Haneen Mohammed Date: Tue, 9 Feb 2016 23:03:05 +0300 Subject: Staging: rts5208: fix check for dma mapping error use dma_mapping_error() instead of comparing the returned address with zero after dma_map_single(). Signed-off-by: Haneen Mohammed Acked-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_transport.c b/drivers/staging/rts5208/rtsx_transport.c index f27491e802ed..0c9549bae986 100644 --- a/drivers/staging/rts5208/rtsx_transport.c +++ b/drivers/staging/rts5208/rtsx_transport.c @@ -653,7 +653,7 @@ static int rtsx_transfer_buf(struct rtsx_chip *chip, u8 card, void *buf, return -ENXIO; addr = dma_map_single(&(rtsx->pci->dev), buf, len, dma_dir); - if (!addr) + if (dma_mapping_error(&rtsx->pci->dev, addr)) return -ENOMEM; if (card == SD_CARD) -- cgit v1.2.3 From b3232842dbef8e6356af75b3a98ea7f752879bc8 Mon Sep 17 00:00:00 2001 From: Haneen Mohammed Date: Tue, 9 Feb 2016 23:06:40 +0300 Subject: Staging: rts5208: remove unnecessary parantheses This patch removes unnecessary parantheses around rtsx->pci->dev. Signed-off-by: Haneen Mohammed Acked-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx_transport.c b/drivers/staging/rts5208/rtsx_transport.c index 0c9549bae986..f2eb18e8dd96 100644 --- a/drivers/staging/rts5208/rtsx_transport.c +++ b/drivers/staging/rts5208/rtsx_transport.c @@ -652,7 +652,7 @@ static int rtsx_transfer_buf(struct rtsx_chip *chip, u8 card, void *buf, else return -ENXIO; - addr = dma_map_single(&(rtsx->pci->dev), buf, len, dma_dir); + addr = dma_map_single(&rtsx->pci->dev, buf, len, dma_dir); if (dma_mapping_error(&rtsx->pci->dev, addr)) return -ENOMEM; -- cgit v1.2.3 From 5a267953baca23c49f78a2e365aa0f44f762b0c1 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Tue, 9 Feb 2016 17:06:27 -0500 Subject: staging: rdma: Use kcalloc instead of kzalloc Use kcalloc rather than kzalloc when multiplied by size to prevent integer overflows. This change also makes code nicer to read. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rdma/hfi1/efivar.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rdma/hfi1/efivar.c b/drivers/staging/rdma/hfi1/efivar.c index 7dc5bae220e0..e569f9f456c5 100644 --- a/drivers/staging/rdma/hfi1/efivar.c +++ b/drivers/staging/rdma/hfi1/efivar.c @@ -83,8 +83,7 @@ static int read_efi_var(const char *name, unsigned long *size, if (!efi_enabled(EFI_RUNTIME_SERVICES)) return -EOPNOTSUPP; - uni_name = kzalloc(sizeof(efi_char16_t) * (strlen(name) + 1), - GFP_KERNEL); + uni_name = kcalloc(strlen(name) + 1, sizeof(efi_char16_t), GFP_KERNEL); temp_buffer = kzalloc(EFI_DATA_SIZE, GFP_KERNEL); if (!uni_name || !temp_buffer) { -- cgit v1.2.3 From 3f2f28b392505a3dfbff76013416944f35abea32 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Tue, 9 Feb 2016 17:51:03 -0500 Subject: staging: goldfish: Change form of NULL comparisons Change null comparisons of the form x == NULL to !x. This was suggested by checkpatch. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/goldfish/goldfish_audio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/goldfish/goldfish_audio.c b/drivers/staging/goldfish/goldfish_audio.c index b0927e49d0a8..891dfaaf1593 100644 --- a/drivers/staging/goldfish/goldfish_audio.c +++ b/drivers/staging/goldfish/goldfish_audio.c @@ -280,12 +280,12 @@ static int goldfish_audio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (r == NULL) { + if (!r) { dev_err(&pdev->dev, "platform_get_resource failed\n"); return -ENODEV; } data->reg_base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE); - if (data->reg_base == NULL) + if (!data->reg_base) return -ENOMEM; data->irq = platform_get_irq(pdev, 0); @@ -295,7 +295,7 @@ static int goldfish_audio_probe(struct platform_device *pdev) } data->buffer_virt = dmam_alloc_coherent(&pdev->dev, COMBINED_BUFFER_SIZE, &buf_addr, GFP_KERNEL); - if (data->buffer_virt == NULL) { + if (!data->buffer_virt) { dev_err(&pdev->dev, "allocate buffer failed\n"); return -ENOMEM; } -- cgit v1.2.3 From fa882033e04ddd1fbda2b6ab620eb6590e0f5b02 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Tue, 9 Feb 2016 14:52:51 -0500 Subject: staging: nvec: Remove unneeded comment Remove this comment as it does not have a meaning here. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/nvec/nvec.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index dba17660a4c5..82f7600fead3 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -14,8 +14,6 @@ * */ -/* #define DEBUG */ - #include #include #include -- cgit v1.2.3 From 8c79c49c803da7e1bd21da0374cf02083becae04 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Tue, 9 Feb 2016 13:40:28 -0500 Subject: staging: iio: Remove parantheses around right hand side of assignment Remove parantheses on the right hand side of assignments as they are not needed. Coccinelle patch used: @@ expression a, b, c, d; @@ ( a = (c == d) | a = - ( b - ) ) Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/ad7280a.c | 4 ++-- drivers/staging/iio/light/tsl2x7x_core.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index f45ebedb7a05..62e5ecacf634 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -214,8 +214,8 @@ static int __ad7280_read32(struct ad7280_state *st, unsigned *val) static int ad7280_write(struct ad7280_state *st, unsigned devaddr, unsigned addr, bool all, unsigned val) { - unsigned reg = (devaddr << 27 | addr << 21 | - (val & 0xFF) << 13 | all << 12); + unsigned reg = devaddr << 27 | addr << 21 | + (val & 0xFF) << 13 | all << 12; reg |= ad7280_calc_crc8(st->crc_tab, reg >> 11) << 3 | 0x2; st->buf[0] = cpu_to_be32(reg); diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c index 5b1c1650a0e4..2a627181a358 100644 --- a/drivers/staging/iio/light/tsl2x7x_core.c +++ b/drivers/staging/iio/light/tsl2x7x_core.c @@ -687,9 +687,9 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) /* Set the gain based on tsl2x7x_settings struct */ chip->tsl2x7x_config[TSL2X7X_GAIN] = - (chip->tsl2x7x_settings.als_gain | + chip->tsl2x7x_settings.als_gain | (TSL2X7X_mA100 | TSL2X7X_DIODE1) - | ((chip->tsl2x7x_settings.prox_gain) << 2)); + | ((chip->tsl2x7x_settings.prox_gain) << 2); /* set chip struct re scaling and saturation */ chip->als_saturation = als_count * 922; /* 90% of full scale */ @@ -983,7 +983,7 @@ static ssize_t tsl2x7x_als_time_store(struct device *dev, result.fract /= 3; chip->tsl2x7x_settings.als_time = - (TSL2X7X_MAX_TIMER_CNT - (u8)result.fract); + TSL2X7X_MAX_TIMER_CNT - (u8)result.fract; dev_info(&chip->client->dev, "%s: als time = %d", __func__, chip->tsl2x7x_settings.als_time); -- cgit v1.2.3 From fb2d65d28918ef4f0caa1de3d8c7416949c28b41 Mon Sep 17 00:00:00 2001 From: Todd Fujinaka Date: Tue, 9 Feb 2016 21:02:07 -0500 Subject: SCSI: Add Marvell configuration device to VPD blacklist The Marvell 91xx configuration device also needs to be on the VPD blacklist. [mkp: Match all revisions] Signed-off-by: Todd Fujinaka Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_devinfo.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 820416665324..a63099f2aae4 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -206,6 +206,7 @@ static struct { {"iRiver", "iFP Mass Driver", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36}, {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN}, {"Marvell", "Console", NULL, BLIST_SKIP_VPD_PAGES}, + {"Marvell", "91xx Config", "1.01", BLIST_SKIP_VPD_PAGES}, {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, {"MATSHITA", "DMC-LC5", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36}, {"MATSHITA", "DMC-LC40", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36}, -- cgit v1.2.3 From e5be990c2fc3c2682ab7cfbc4f0e6c8cdad2b40d Mon Sep 17 00:00:00 2001 From: Jerry Snitselaar Date: Mon, 4 Jan 2016 12:19:43 -0700 Subject: tpm: remove unneeded include of actbl2.h tpm_tis.c already gets actbl2.h via linux/acpi.h -> acpi/acpi.h -> acpi/actbl.h -> acpi/actbl2.h, so the direct include in tpm_tis.c is not needed. Signed-off-by: Jerry Snitselaar Acked-by: Jarkko Sakkinen Acked-by: Peter Huewe --- drivers/char/tpm/tpm_tis.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 8a3509cb10da..b89d125eec7f 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -28,7 +28,6 @@ #include #include #include -#include #include "tpm.h" enum tis_access { -- cgit v1.2.3 From f3c82ade7c59303167d56b0be3e0707751fc45e2 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Wed, 6 Jan 2016 16:43:30 +0200 Subject: tpm: fix checks for policy digest existence in tpm2_seal_trusted() In my original patch sealing with policy was done with dynamically allocated buffer that I changed later into an array so the checks in tpm2-cmd.c became invalid. This patch fixes the issue. Fixes: 5beb0c435bdd ("keys, trusted: seal with a TPM2 authorization policy") Reported-by: Dan Carpenter Signed-off-by: Jarkko Sakkinen Acked-by: Peter Huewe --- drivers/char/tpm/tpm2-cmd.c | 12 ++++-------- include/keys/trusted-type.h | 2 +- security/keys/trusted.c | 11 +++++------ 3 files changed, 10 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 45a634016f95..66e04b41a73d 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -478,20 +478,16 @@ int tpm2_seal_trusted(struct tpm_chip *chip, tpm_buf_append_u8(&buf, payload->migratable); /* public */ - if (options->policydigest) - tpm_buf_append_u16(&buf, 14 + options->digest_len); - else - tpm_buf_append_u16(&buf, 14); - + tpm_buf_append_u16(&buf, 14 + options->policydigest_len); tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH); tpm_buf_append_u16(&buf, hash); /* policy */ - if (options->policydigest) { + if (options->policydigest_len) { tpm_buf_append_u32(&buf, 0); - tpm_buf_append_u16(&buf, options->digest_len); + tpm_buf_append_u16(&buf, options->policydigest_len); tpm_buf_append(&buf, options->policydigest, - options->digest_len); + options->policydigest_len); } else { tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH); tpm_buf_append_u16(&buf, 0); diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h index 42cf2d991bf4..4ea7e55f20b0 100644 --- a/include/keys/trusted-type.h +++ b/include/keys/trusted-type.h @@ -38,7 +38,7 @@ struct trusted_key_options { unsigned char pcrinfo[MAX_PCRINFO_SIZE]; int pcrlock; uint32_t hash; - uint32_t digest_len; + uint32_t policydigest_len; unsigned char policydigest[MAX_DIGEST_SIZE]; uint32_t policyhandle; }; diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 0dcab20cdacd..90d61751ff12 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c @@ -744,6 +744,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay, unsigned long handle; unsigned long lock; unsigned long token_mask = 0; + unsigned int digest_len; int i; int tpm2; @@ -752,7 +753,6 @@ static int getoptions(char *c, struct trusted_key_payload *pay, return tpm2; opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1; - opt->digest_len = hash_digest_size[opt->hash]; while ((p = strsep(&c, " \t"))) { if (*p == '\0' || *p == ' ' || *p == '\t') @@ -812,8 +812,6 @@ static int getoptions(char *c, struct trusted_key_payload *pay, for (i = 0; i < HASH_ALGO__LAST; i++) { if (!strcmp(args[0].from, hash_algo_name[i])) { opt->hash = i; - opt->digest_len = - hash_digest_size[opt->hash]; break; } } @@ -825,13 +823,14 @@ static int getoptions(char *c, struct trusted_key_payload *pay, } break; case Opt_policydigest: - if (!tpm2 || - strlen(args[0].from) != (2 * opt->digest_len)) + digest_len = hash_digest_size[opt->hash]; + if (!tpm2 || strlen(args[0].from) != (2 * digest_len)) return -EINVAL; res = hex2bin(opt->policydigest, args[0].from, - opt->digest_len); + digest_len); if (res < 0) return -EINVAL; + opt->policydigest_len = digest_len; break; case Opt_policyhandle: if (!tpm2) -- cgit v1.2.3 From 55a889c2cb138f8f10164539c6d290a1cefaa863 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Thu, 7 Jan 2016 17:36:20 -0700 Subject: tpm_crb: Use the common ACPI definition of struct acpi_tpm2 include/acpi/actbl2.h is the proper place for these definitions and the needed TPM2 ones have been there since commit 413d4a6defe0 ("ACPICA: Update TPM2 ACPI table") This also drops a couple of le32_to_cpu's for members of this table, the existing swapping was not done consistently, and the standard used by other Linux callers of acpi_get_table is unswapped. Signed-off-by: Jason Gunthorpe Tested-by: Wilck, Martin Tested-by: Jarkko Sakkinen Reviewed-by: Jarkko Sakkinen Acked-by: Peter Huewe --- drivers/char/tpm/tpm.h | 7 ------- drivers/char/tpm/tpm_crb.c | 31 +++++++++---------------------- drivers/char/tpm/tpm_tis.c | 2 +- 3 files changed, 10 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 542a80cbfd9c..28b477e8da6a 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -128,13 +128,6 @@ enum tpm2_startup_types { TPM2_SU_STATE = 0x0001, }; -enum tpm2_start_method { - TPM2_START_ACPI = 2, - TPM2_START_FIFO = 6, - TPM2_START_CRB = 7, - TPM2_START_CRB_WITH_ACPI = 8, -}; - struct tpm_chip; struct tpm_vendor_specific { diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 8342cf51ffdc..8dd70696ebe8 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c @@ -34,14 +34,6 @@ enum crb_defaults { CRB_ACPI_START_INDEX = 1, }; -struct acpi_tpm2 { - struct acpi_table_header hdr; - u16 platform_class; - u16 reserved; - u64 control_area_pa; - u32 start_method; -} __packed; - enum crb_ca_request { CRB_CA_REQ_GO_IDLE = BIT(0), CRB_CA_REQ_CMD_READY = BIT(1), @@ -207,7 +199,7 @@ static const struct tpm_class_ops tpm_crb = { static int crb_acpi_add(struct acpi_device *device) { struct tpm_chip *chip; - struct acpi_tpm2 *buf; + struct acpi_table_tpm2 *buf; struct crb_priv *priv; struct device *dev = &device->dev; acpi_status status; @@ -217,13 +209,14 @@ static int crb_acpi_add(struct acpi_device *device) status = acpi_get_table(ACPI_SIG_TPM2, 1, (struct acpi_table_header **) &buf); - if (ACPI_FAILURE(status)) { - dev_err(dev, "failed to get TPM2 ACPI table\n"); + if (ACPI_FAILURE(status) || buf->header.length < sizeof(*buf)) { + dev_err(dev, FW_BUG "failed to get TPM2 ACPI table\n"); return -ENODEV; } /* Should the FIFO driver handle this? */ - if (buf->start_method == TPM2_START_FIFO) + sm = buf->start_method; + if (sm == ACPI_TPM2_MEMORY_MAPPED) return -ENODEV; chip = tpmm_chip_alloc(dev, &tpm_crb); @@ -232,11 +225,6 @@ static int crb_acpi_add(struct acpi_device *device) chip->flags = TPM_CHIP_FLAG_TPM2; - if (buf->hdr.length < sizeof(struct acpi_tpm2)) { - dev_err(dev, "TPM2 ACPI table has wrong size"); - return -EINVAL; - } - priv = (struct crb_priv *) devm_kzalloc(dev, sizeof(struct crb_priv), GFP_KERNEL); if (!priv) { @@ -244,21 +232,20 @@ static int crb_acpi_add(struct acpi_device *device) return -ENOMEM; } - sm = le32_to_cpu(buf->start_method); - /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs * report only ACPI start but in practice seems to require both * ACPI start and CRB start. */ - if (sm == TPM2_START_CRB || sm == TPM2_START_FIFO || + if (sm == ACPI_TPM2_COMMAND_BUFFER || sm == ACPI_TPM2_MEMORY_MAPPED || !strcmp(acpi_device_hid(device), "MSFT0101")) priv->flags |= CRB_FL_CRB_START; - if (sm == TPM2_START_ACPI || sm == TPM2_START_CRB_WITH_ACPI) + if (sm == ACPI_TPM2_START_METHOD || + sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) priv->flags |= CRB_FL_ACPI_START; priv->cca = (struct crb_control_area __iomem *) - devm_ioremap_nocache(dev, buf->control_area_pa, 0x1000); + devm_ioremap_nocache(dev, buf->control_address, 0x1000); if (!priv->cca) { dev_err(dev, "ioremap of the control area failed\n"); return -ENOMEM; diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index b89d125eec7f..eb31644111a6 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -134,7 +134,7 @@ static inline int is_fifo(struct acpi_device *dev) return 0; } - if (le32_to_cpu(tbl->start_method) != TPM2_START_FIFO) + if (tbl->start_method != ACPI_TPM2_MEMORY_MAPPED) return 0; /* TPM 2.0 FIFO */ -- cgit v1.2.3 From ef7b81dc78642e1a33c890acf3214d1e04c90a8f Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Thu, 7 Jan 2016 17:36:21 -0700 Subject: tpm_tis: Disable interrupt auto probing on a per-device basis Instead of clearing the global interrupts flag when any device does not have an interrupt just pass -1 through tpm_info.irq. The only thing that asks for autoprobing is the force=1 path. Signed-off-by: Jason Gunthorpe Tested-by: Wilck, Martin Tested-by: Jarkko Sakkinen Reviewed-by: Jarkko Sakkinen Acked-by: Peter Huewe --- drivers/char/tpm/tpm_tis.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index eb31644111a6..d993fed51f23 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -68,7 +68,11 @@ enum tis_defaults { struct tpm_info { unsigned long start; unsigned long len; - unsigned int irq; + /* irq > 0 means: use irq $irq; + * irq = 0 means: autoprobe for an irq; + * irq = -1 means: no irq support + */ + int irq; }; static struct tpm_info tis_default_info = { @@ -806,7 +810,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info, /* INTERRUPT Setup */ init_waitqueue_head(&chip->vendor.read_queue); init_waitqueue_head(&chip->vendor.int_queue); - if (interrupts) { + if (interrupts && tpm_info->irq != -1) { if (tpm_info->irq) { tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED, tpm_info->irq); @@ -894,9 +898,9 @@ static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume); #ifdef CONFIG_PNP static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, - const struct pnp_device_id *pnp_id) + const struct pnp_device_id *pnp_id) { - struct tpm_info tpm_info = tis_default_info; + struct tpm_info tpm_info = {}; acpi_handle acpi_dev_handle = NULL; tpm_info.start = pnp_mem_start(pnp_dev, 0); @@ -905,7 +909,7 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, if (pnp_irq_valid(pnp_dev, 0)) tpm_info.irq = pnp_irq(pnp_dev, 0); else - interrupts = false; + tpm_info.irq = -1; #ifdef CONFIG_ACPI if (pnp_acpi_device(pnp_dev)) { @@ -983,6 +987,7 @@ static int tpm_tis_acpi_init(struct acpi_device *acpi_dev) return -ENODEV; INIT_LIST_HEAD(&resources); + tpm_info.irq = -1; ret = acpi_dev_get_resources(acpi_dev, &resources, tpm_check_resource, &tpm_info); if (ret < 0) @@ -990,9 +995,6 @@ static int tpm_tis_acpi_init(struct acpi_device *acpi_dev) acpi_dev_free_resource_list(&resources); - if (!tpm_info.irq) - interrupts = false; - if (is_itpm(acpi_dev)) itpm = true; -- cgit v1.2.3 From 4d627e672bd0e8af4e734fef93e806499d1e1277 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Thu, 7 Jan 2016 17:36:22 -0700 Subject: tpm_tis: Do not fall back to a hardcoded address for TPM2 If the ACPI tables do not declare a memory resource for the TPM2 then do not just fall back to the x86 default base address. Also be stricter when checking the ancillary TPM2 ACPI data and error out if any of this data is wrong rather than blindly assuming TPM1. Fixes: 399235dc6e95 ("tpm, tpm_tis: fix tpm_tis ACPI detection issue with TPM 2.0") Signed-off-by: Jason Gunthorpe Tested-by: Wilck, Martin Tested-by: Jarkko Sakkinen Reviewed-by: Jarkko Sakkinen Acked-by: Peter Huewe --- drivers/char/tpm/tpm_tis.c | 48 +++++++++++++++++----------------------------- 1 file changed, 18 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index d993fed51f23..2ccad8a8177f 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -121,39 +121,11 @@ static inline int is_itpm(struct acpi_device *dev) { return has_hid(dev, "INTC0102"); } - -static inline int is_fifo(struct acpi_device *dev) -{ - struct acpi_table_tpm2 *tbl; - acpi_status st; - - /* TPM 1.2 FIFO */ - if (!has_hid(dev, "MSFT0101")) - return 1; - - st = acpi_get_table(ACPI_SIG_TPM2, 1, - (struct acpi_table_header **) &tbl); - if (ACPI_FAILURE(st)) { - dev_err(&dev->dev, "failed to get TPM2 ACPI table\n"); - return 0; - } - - if (tbl->start_method != ACPI_TPM2_MEMORY_MAPPED) - return 0; - - /* TPM 2.0 FIFO */ - return 1; -} #else static inline int is_itpm(struct acpi_device *dev) { return 0; } - -static inline int is_fifo(struct acpi_device *dev) -{ - return 1; -} #endif /* Before we attempt to access the TPM we must see that the valid bit is set. @@ -979,11 +951,21 @@ static int tpm_check_resource(struct acpi_resource *ares, void *data) static int tpm_tis_acpi_init(struct acpi_device *acpi_dev) { + struct acpi_table_tpm2 *tbl; + acpi_status st; struct list_head resources; - struct tpm_info tpm_info = tis_default_info; + struct tpm_info tpm_info = {}; int ret; - if (!is_fifo(acpi_dev)) + st = acpi_get_table(ACPI_SIG_TPM2, 1, + (struct acpi_table_header **) &tbl); + if (ACPI_FAILURE(st) || tbl->header.length < sizeof(*tbl)) { + dev_err(&acpi_dev->dev, + FW_BUG "failed to get TPM2 ACPI table\n"); + return -EINVAL; + } + + if (tbl->start_method != ACPI_TPM2_MEMORY_MAPPED) return -ENODEV; INIT_LIST_HEAD(&resources); @@ -995,6 +977,12 @@ static int tpm_tis_acpi_init(struct acpi_device *acpi_dev) acpi_dev_free_resource_list(&resources); + if (tpm_info.start == 0 && tpm_info.len == 0) { + dev_err(&acpi_dev->dev, + FW_BUG "TPM2 ACPI table does not define a memory resource\n"); + return -EINVAL; + } + if (is_itpm(acpi_dev)) itpm = true; -- cgit v1.2.3 From 51dd43dff74b0547ad844638f6910ca29c956819 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Thu, 7 Jan 2016 17:36:23 -0700 Subject: tpm_tis: Use devm_ioremap_resource This does a request_resource under the covers which means tis holds a lock on the memory range it is using so other drivers cannot grab it. When doing probing it is important to ensure that other drivers are not using the same range before tis starts touching it. To do this flow the actual struct resource from the device right through to devm_ioremap_resource. This ensures all the proper resource meta-data is carried down. Signed-off-by: Jason Gunthorpe Tested-by: Wilck, Martin Tested-by: Jarkko Sakkinen Reviewed-by: Jarkko Sakkinen Acked-by: Peter Huewe --- drivers/char/tpm/tpm_tis.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 2ccad8a8177f..7407835791ef 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -66,8 +66,7 @@ enum tis_defaults { }; struct tpm_info { - unsigned long start; - unsigned long len; + struct resource res; /* irq > 0 means: use irq $irq; * irq = 0 means: autoprobe for an irq; * irq = -1 means: no irq support @@ -76,8 +75,11 @@ struct tpm_info { }; static struct tpm_info tis_default_info = { - .start = TIS_MEM_BASE, - .len = TIS_MEM_LEN, + .res = { + .start = TIS_MEM_BASE, + .end = TIS_MEM_BASE + TIS_MEM_LEN - 1, + .flags = IORESOURCE_MEM, + }, .irq = 0, }; @@ -691,9 +693,9 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info, chip->acpi_dev_handle = acpi_dev_handle; #endif - chip->vendor.iobase = devm_ioremap(dev, tpm_info->start, tpm_info->len); - if (!chip->vendor.iobase) - return -EIO; + chip->vendor.iobase = devm_ioremap_resource(dev, &tpm_info->res); + if (IS_ERR(chip->vendor.iobase)) + return PTR_ERR(chip->vendor.iobase); /* Maximum timeouts */ chip->vendor.timeout_a = TIS_TIMEOUT_A_MAX; @@ -874,9 +876,12 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, { struct tpm_info tpm_info = {}; acpi_handle acpi_dev_handle = NULL; + struct resource *res; - tpm_info.start = pnp_mem_start(pnp_dev, 0); - tpm_info.len = pnp_mem_len(pnp_dev, 0); + res = pnp_get_resource(pnp_dev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + tpm_info.res = *res; if (pnp_irq_valid(pnp_dev, 0)) tpm_info.irq = pnp_irq(pnp_dev, 0); @@ -939,12 +944,10 @@ static int tpm_check_resource(struct acpi_resource *ares, void *data) struct tpm_info *tpm_info = (struct tpm_info *) data; struct resource res; - if (acpi_dev_resource_interrupt(ares, 0, &res)) { + if (acpi_dev_resource_interrupt(ares, 0, &res)) tpm_info->irq = res.start; - } else if (acpi_dev_resource_memory(ares, &res)) { - tpm_info->start = res.start; - tpm_info->len = resource_size(&res); - } + else if (acpi_dev_resource_memory(ares, &res)) + tpm_info->res = res; return 1; } @@ -977,7 +980,7 @@ static int tpm_tis_acpi_init(struct acpi_device *acpi_dev) acpi_dev_free_resource_list(&resources); - if (tpm_info.start == 0 && tpm_info.len == 0) { + if (resource_type(&tpm_info.res) != IORESOURCE_MEM) { dev_err(&acpi_dev->dev, FW_BUG "TPM2 ACPI table does not define a memory resource\n"); return -EINVAL; -- cgit v1.2.3 From 00194826e6be333083ba9ddbd6e83fb423206f8a Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Thu, 7 Jan 2016 17:36:24 -0700 Subject: tpm_tis: Clean up the force=1 module parameter The TPM core has long assumed that every device has a driver attached, however the force path was attaching the TPM core outside of a driver context. This isn't generally reliable as the user could detatch the driver using sysfs or something, but commit b8b2c7d845d5 ("base/platform: assert that dev_pm_domain callbacks are called unconditionally") forced the issue by leaving the driver pointer NULL if there is no probe. Rework the TPM setup to create a platform device with resources and then allow the driver core to naturally bind and probe it through the normal mechanisms. All this structure is needed anyhow to enable TPM for OF environments. Finally, since the entire flow is changing convert the init/exit to use the modern ifdef-less coding style when possible Reported-by: "Wilck, Martin" Signed-off-by: Jason Gunthorpe Tested-by: Wilck, Martin Tested-by: Jarkko Sakkinen Reviewed-by: Jarkko Sakkinen Acked-by: Peter Huewe --- drivers/char/tpm/tpm_tis.c | 169 ++++++++++++++++++++++++++++----------------- 1 file changed, 104 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 7407835791ef..ca137b5b7c24 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -59,7 +59,6 @@ enum tis_int_flags { }; enum tis_defaults { - TIS_MEM_BASE = 0xFED40000, TIS_MEM_LEN = 0x5000, TIS_SHORT_TIMEOUT = 750, /* ms */ TIS_LONG_TIMEOUT = 2000, /* 2 sec */ @@ -74,15 +73,6 @@ struct tpm_info { int irq; }; -static struct tpm_info tis_default_info = { - .res = { - .start = TIS_MEM_BASE, - .end = TIS_MEM_BASE + TIS_MEM_LEN - 1, - .flags = IORESOURCE_MEM, - }, - .irq = 0, -}; - /* Some timeout values are needed before it is known whether the chip is * TPM 1.0 or TPM 2.0. */ @@ -824,7 +814,6 @@ out_err: return rc; } -#ifdef CONFIG_PM_SLEEP static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) { u32 intmask; @@ -866,11 +855,9 @@ static int tpm_tis_resume(struct device *dev) return 0; } -#endif static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume); -#ifdef CONFIG_PNP static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, const struct pnp_device_id *pnp_id) { @@ -888,14 +875,12 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, else tpm_info.irq = -1; -#ifdef CONFIG_ACPI if (pnp_acpi_device(pnp_dev)) { if (is_itpm(pnp_acpi_device(pnp_dev))) itpm = true; - acpi_dev_handle = pnp_acpi_device(pnp_dev)->handle; + acpi_dev_handle = ACPI_HANDLE(&pnp_dev->dev); } -#endif return tpm_tis_init(&pnp_dev->dev, &tpm_info, acpi_dev_handle); } @@ -936,7 +921,6 @@ static struct pnp_driver tis_pnp_driver = { module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); -#endif #ifdef CONFIG_ACPI static int tpm_check_resource(struct acpi_resource *ares, void *data) @@ -1023,80 +1007,135 @@ static struct acpi_driver tis_acpi_driver = { }; #endif +static struct platform_device *force_pdev; + +static int tpm_tis_plat_probe(struct platform_device *pdev) +{ + struct tpm_info tpm_info = {}; + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no memory resource defined\n"); + return -ENODEV; + } + tpm_info.res = *res; + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res) { + tpm_info.irq = res->start; + } else { + if (pdev == force_pdev) + tpm_info.irq = -1; + else + /* When forcing auto probe the IRQ */ + tpm_info.irq = 0; + } + + return tpm_tis_init(&pdev->dev, &tpm_info, NULL); +} + +static int tpm_tis_plat_remove(struct platform_device *pdev) +{ + struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); + + tpm_chip_unregister(chip); + tpm_tis_remove(chip); + + return 0; +} + static struct platform_driver tis_drv = { + .probe = tpm_tis_plat_probe, + .remove = tpm_tis_plat_remove, .driver = { .name = "tpm_tis", .pm = &tpm_tis_pm, }, }; -static struct platform_device *pdev; - static bool force; +#ifdef CONFIG_X86 module_param(force, bool, 0444); MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry"); +#endif + +static int tpm_tis_force_device(void) +{ + struct platform_device *pdev; + static const struct resource x86_resources[] = { + { + .start = 0xFED40000, + .end = 0xFED40000 + TIS_MEM_LEN - 1, + .flags = IORESOURCE_MEM, + }, + }; + + if (!force) + return 0; + + /* The driver core will match the name tpm_tis of the device to + * the tpm_tis platform driver and complete the setup via + * tpm_tis_plat_probe + */ + pdev = platform_device_register_simple("tpm_tis", -1, x86_resources, + ARRAY_SIZE(x86_resources)); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + force_pdev = pdev; + + return 0; +} + static int __init init_tis(void) { int rc; -#ifdef CONFIG_PNP - if (!force) { - rc = pnp_register_driver(&tis_pnp_driver); - if (rc) - return rc; - } -#endif + + rc = tpm_tis_force_device(); + if (rc) + goto err_force; + + rc = platform_driver_register(&tis_drv); + if (rc) + goto err_platform; + #ifdef CONFIG_ACPI - if (!force) { - rc = acpi_bus_register_driver(&tis_acpi_driver); - if (rc) { -#ifdef CONFIG_PNP - pnp_unregister_driver(&tis_pnp_driver); -#endif - return rc; - } - } + rc = acpi_bus_register_driver(&tis_acpi_driver); + if (rc) + goto err_acpi; #endif - if (!force) - return 0; - rc = platform_driver_register(&tis_drv); - if (rc < 0) - return rc; - pdev = platform_device_register_simple("tpm_tis", -1, NULL, 0); - if (IS_ERR(pdev)) { - rc = PTR_ERR(pdev); - goto err_dev; + if (IS_ENABLED(CONFIG_PNP)) { + rc = pnp_register_driver(&tis_pnp_driver); + if (rc) + goto err_pnp; } - rc = tpm_tis_init(&pdev->dev, &tis_default_info, NULL); - if (rc) - goto err_init; + return 0; -err_init: - platform_device_unregister(pdev); -err_dev: - platform_driver_unregister(&tis_drv); + +err_pnp: +#ifdef CONFIG_ACPI + acpi_bus_unregister_driver(&tis_acpi_driver); +err_acpi: +#endif + platform_device_unregister(force_pdev); +err_platform: + if (force_pdev) + platform_device_unregister(force_pdev); +err_force: return rc; } static void __exit cleanup_tis(void) { - struct tpm_chip *chip; -#if defined(CONFIG_PNP) || defined(CONFIG_ACPI) - if (!force) { + pnp_unregister_driver(&tis_pnp_driver); #ifdef CONFIG_ACPI - acpi_bus_unregister_driver(&tis_acpi_driver); -#endif -#ifdef CONFIG_PNP - pnp_unregister_driver(&tis_pnp_driver); -#endif - return; - } + acpi_bus_unregister_driver(&tis_acpi_driver); #endif - chip = dev_get_drvdata(&pdev->dev); - tpm_chip_unregister(chip); - tpm_tis_remove(chip); - platform_device_unregister(pdev); platform_driver_unregister(&tis_drv); + + if (force_pdev) + platform_device_unregister(force_pdev); } module_init(init_tis); -- cgit v1.2.3 From 1e3ed59d6200eb31b554dbdcfdde62d1e3d91f0c Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Thu, 7 Jan 2016 17:36:25 -0700 Subject: tpm_crb: Drop le32_to_cpu(ioread32(..)) ioread32 and readl are defined to read from PCI style memory, ie little endian and return the result in host order. On platforms where a swap is required ioread32/readl do the swap internally (eg see ppc). Signed-off-by: Jason Gunthorpe Tested-by: Jarkko Sakkinen Reviewed-by: Jarkko Sakkinen Acked-by: Peter Huewe --- drivers/char/tpm/tpm_crb.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 8dd70696ebe8..0237006dc4d8 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c @@ -89,7 +89,7 @@ static u8 crb_status(struct tpm_chip *chip) struct crb_priv *priv = chip->vendor.priv; u8 sts = 0; - if ((le32_to_cpu(ioread32(&priv->cca->start)) & CRB_START_INVOKE) != + if ((ioread32(&priv->cca->start) & CRB_START_INVOKE) != CRB_START_INVOKE) sts |= CRB_STS_COMPLETE; @@ -105,7 +105,7 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count) if (count < 6) return -EIO; - if (le32_to_cpu(ioread32(&priv->cca->sts)) & CRB_CA_STS_ERROR) + if (ioread32(&priv->cca->sts) & CRB_CA_STS_ERROR) return -EIO; memcpy_fromio(buf, priv->rsp, 6); @@ -141,11 +141,11 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len) struct crb_priv *priv = chip->vendor.priv; int rc = 0; - if (len > le32_to_cpu(ioread32(&priv->cca->cmd_size))) { + if (len > ioread32(&priv->cca->cmd_size)) { dev_err(&chip->dev, "invalid command count value %x %zx\n", (unsigned int) len, - (size_t) le32_to_cpu(ioread32(&priv->cca->cmd_size))); + (size_t) ioread32(&priv->cca->cmd_size)); return -E2BIG; } @@ -181,7 +181,7 @@ static void crb_cancel(struct tpm_chip *chip) static bool crb_req_canceled(struct tpm_chip *chip, u8 status) { struct crb_priv *priv = chip->vendor.priv; - u32 cancel = le32_to_cpu(ioread32(&priv->cca->cancel)); + u32 cancel = ioread32(&priv->cca->cancel); return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE; } @@ -251,10 +251,10 @@ static int crb_acpi_add(struct acpi_device *device) return -ENOMEM; } - pa = ((u64) le32_to_cpu(ioread32(&priv->cca->cmd_pa_high)) << 32) | - (u64) le32_to_cpu(ioread32(&priv->cca->cmd_pa_low)); - priv->cmd = devm_ioremap_nocache(dev, pa, - ioread32(&priv->cca->cmd_size)); + pa = ((u64)ioread32(&priv->cca->cmd_pa_high) << 32) | + (u64)ioread32(&priv->cca->cmd_pa_low); + priv->cmd = + devm_ioremap_nocache(dev, pa, ioread32(&priv->cca->cmd_size)); if (!priv->cmd) { dev_err(dev, "ioremap of the command buffer failed\n"); return -ENOMEM; @@ -262,8 +262,8 @@ static int crb_acpi_add(struct acpi_device *device) memcpy_fromio(&pa, &priv->cca->rsp_pa, 8); pa = le64_to_cpu(pa); - priv->rsp = devm_ioremap_nocache(dev, pa, - ioread32(&priv->cca->rsp_size)); + priv->rsp = + devm_ioremap_nocache(dev, pa, ioread32(&priv->cca->rsp_size)); if (!priv->rsp) { dev_err(dev, "ioremap of the response buffer failed\n"); return -ENOMEM; -- cgit v1.2.3 From 1bd047be37d95bf65a219f4931215f71878ac060 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Thu, 7 Jan 2016 17:36:26 -0700 Subject: tpm_crb: Use devm_ioremap_resource To support the force mode in tpm_tis we need to use resource locking in tpm_crb as well, via devm_ioremap_resource. The light restructuring better aligns crb and tis and makes it easier to see the that new changes make sense. The control area and its associated buffers do not always fall in the range of the iomem resource given by the ACPI object. This patch fixes the issue by mapping the buffers if this is the case. [jarkko.sakkinen@linux.intel.com: squashed update described in the last paragraph.] Signed-off-by: Jason Gunthorpe Tested-by: Jarkko Sakkinen Reviewed-by: Jarkko Sakkinen Acked-by: Peter Huewe Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm_crb.c | 151 ++++++++++++++++++++++++++++++--------------- 1 file changed, 102 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 0237006dc4d8..916332c9d906 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c @@ -77,6 +77,8 @@ enum crb_flags { struct crb_priv { unsigned int flags; + struct resource res; + void __iomem *iobase; struct crb_control_area __iomem *cca; u8 __iomem *cmd; u8 __iomem *rsp; @@ -196,22 +198,115 @@ static const struct tpm_class_ops tpm_crb = { .req_complete_val = CRB_STS_COMPLETE, }; -static int crb_acpi_add(struct acpi_device *device) +static int crb_init(struct acpi_device *device, struct crb_priv *priv) { struct tpm_chip *chip; + int rc; + + chip = tpmm_chip_alloc(&device->dev, &tpm_crb); + if (IS_ERR(chip)) + return PTR_ERR(chip); + + chip->vendor.priv = priv; + chip->acpi_dev_handle = device->handle; + chip->flags = TPM_CHIP_FLAG_TPM2; + + rc = tpm_get_timeouts(chip); + if (rc) + return rc; + + rc = tpm2_do_selftest(chip); + if (rc) + return rc; + + return tpm_chip_register(chip); +} + +static int crb_check_resource(struct acpi_resource *ares, void *data) +{ + struct crb_priv *priv = data; + struct resource res; + + if (acpi_dev_resource_memory(ares, &res)) + priv->res = res; + + return 1; +} + +static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv, + u64 start, u32 size) +{ + struct resource new_res = { + .start = start, + .end = start + size - 1, + .flags = IORESOURCE_MEM, + }; + + /* Detect a 64 bit address on a 32 bit system */ + if (start != new_res.start) + return ERR_PTR(-EINVAL); + + if (!resource_contains(&priv->res, &new_res)) + return devm_ioremap_resource(dev, &new_res); + + return priv->iobase + (new_res.start - priv->res.start); +} + +static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, + struct acpi_table_tpm2 *buf) +{ + struct list_head resources; + struct device *dev = &device->dev; + u64 pa; + int ret; + + INIT_LIST_HEAD(&resources); + ret = acpi_dev_get_resources(device, &resources, crb_check_resource, + priv); + if (ret < 0) + return ret; + acpi_dev_free_resource_list(&resources); + + if (resource_type(&priv->res) != IORESOURCE_MEM) { + dev_err(dev, + FW_BUG "TPM2 ACPI table does not define a memory resource\n"); + return -EINVAL; + } + + priv->iobase = devm_ioremap_resource(dev, &priv->res); + if (IS_ERR(priv->iobase)) + return PTR_ERR(priv->iobase); + + priv->cca = crb_map_res(dev, priv, buf->control_address, 0x1000); + if (IS_ERR(priv->cca)) + return PTR_ERR(priv->cca); + + pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) | + (u64) ioread32(&priv->cca->cmd_pa_low); + priv->cmd = crb_map_res(dev, priv, pa, ioread32(&priv->cca->cmd_size)); + if (IS_ERR(priv->cmd)) + return PTR_ERR(priv->cmd); + + memcpy_fromio(&pa, &priv->cca->rsp_pa, 8); + pa = le64_to_cpu(pa); + priv->rsp = crb_map_res(dev, priv, pa, ioread32(&priv->cca->rsp_size)); + return PTR_ERR_OR_ZERO(priv->rsp); +} + +static int crb_acpi_add(struct acpi_device *device) +{ struct acpi_table_tpm2 *buf; struct crb_priv *priv; struct device *dev = &device->dev; acpi_status status; u32 sm; - u64 pa; int rc; status = acpi_get_table(ACPI_SIG_TPM2, 1, (struct acpi_table_header **) &buf); if (ACPI_FAILURE(status) || buf->header.length < sizeof(*buf)) { dev_err(dev, FW_BUG "failed to get TPM2 ACPI table\n"); - return -ENODEV; + return -EINVAL; } /* Should the FIFO driver handle this? */ @@ -219,18 +314,9 @@ static int crb_acpi_add(struct acpi_device *device) if (sm == ACPI_TPM2_MEMORY_MAPPED) return -ENODEV; - chip = tpmm_chip_alloc(dev, &tpm_crb); - if (IS_ERR(chip)) - return PTR_ERR(chip); - - chip->flags = TPM_CHIP_FLAG_TPM2; - - priv = (struct crb_priv *) devm_kzalloc(dev, sizeof(struct crb_priv), - GFP_KERNEL); - if (!priv) { - dev_err(dev, "failed to devm_kzalloc for private data\n"); + priv = devm_kzalloc(dev, sizeof(struct crb_priv), GFP_KERNEL); + if (!priv) return -ENOMEM; - } /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs * report only ACPI start but in practice seems to require both @@ -244,44 +330,11 @@ static int crb_acpi_add(struct acpi_device *device) sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) priv->flags |= CRB_FL_ACPI_START; - priv->cca = (struct crb_control_area __iomem *) - devm_ioremap_nocache(dev, buf->control_address, 0x1000); - if (!priv->cca) { - dev_err(dev, "ioremap of the control area failed\n"); - return -ENOMEM; - } - - pa = ((u64)ioread32(&priv->cca->cmd_pa_high) << 32) | - (u64)ioread32(&priv->cca->cmd_pa_low); - priv->cmd = - devm_ioremap_nocache(dev, pa, ioread32(&priv->cca->cmd_size)); - if (!priv->cmd) { - dev_err(dev, "ioremap of the command buffer failed\n"); - return -ENOMEM; - } - - memcpy_fromio(&pa, &priv->cca->rsp_pa, 8); - pa = le64_to_cpu(pa); - priv->rsp = - devm_ioremap_nocache(dev, pa, ioread32(&priv->cca->rsp_size)); - if (!priv->rsp) { - dev_err(dev, "ioremap of the response buffer failed\n"); - return -ENOMEM; - } - - chip->vendor.priv = priv; - - rc = tpm_get_timeouts(chip); + rc = crb_map_io(device, priv, buf); if (rc) return rc; - chip->acpi_dev_handle = device->handle; - - rc = tpm2_do_selftest(chip); - if (rc) - return rc; - - return tpm_chip_register(chip); + return crb_init(device, priv); } static int crb_acpi_remove(struct acpi_device *device) -- cgit v1.2.3 From 72c91ce8523ae5828fe5e4417ae0aaab53707a08 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Fri, 29 Jan 2016 09:47:22 -0800 Subject: tpm: fix the rollback in tpm_chip_register() Fixed the rollback and gave more self-documenting names for the functions. Fixes: d972b0523f ("tpm: fix call order in tpm-chip.c") Signed-off-by: Jarkko Sakkinen cc: stable@vger.kernel.org Reviewed-by: Jason Gunthorpe --- drivers/char/tpm/tpm-chip.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 45cc39aabeee..1a9dcee8da5a 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -140,7 +140,7 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, } EXPORT_SYMBOL_GPL(tpmm_chip_alloc); -static int tpm_dev_add_device(struct tpm_chip *chip) +static int tpm_add_char_device(struct tpm_chip *chip) { int rc; @@ -151,7 +151,6 @@ static int tpm_dev_add_device(struct tpm_chip *chip) chip->devname, MAJOR(chip->dev.devt), MINOR(chip->dev.devt), rc); - device_unregister(&chip->dev); return rc; } @@ -162,13 +161,14 @@ static int tpm_dev_add_device(struct tpm_chip *chip) chip->devname, MAJOR(chip->dev.devt), MINOR(chip->dev.devt), rc); + cdev_del(&chip->cdev); return rc; } return rc; } -static void tpm_dev_del_device(struct tpm_chip *chip) +static void tpm_del_char_device(struct tpm_chip *chip) { cdev_del(&chip->cdev); device_unregister(&chip->dev); @@ -222,7 +222,7 @@ int tpm_chip_register(struct tpm_chip *chip) tpm_add_ppi(chip); - rc = tpm_dev_add_device(chip); + rc = tpm_add_char_device(chip); if (rc) goto out_err; @@ -274,6 +274,6 @@ void tpm_chip_unregister(struct tpm_chip *chip) sysfs_remove_link(&chip->pdev->kobj, "ppi"); tpm1_chip_unregister(chip); - tpm_dev_del_device(chip); + tpm_del_char_device(chip); } EXPORT_SYMBOL_GPL(tpm_chip_unregister); -- cgit v1.2.3 From 8e0ee3c9faed7ca68807ea45141775856c438ac0 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Mon, 8 Feb 2016 22:31:08 +0200 Subject: tpm: fix the cleanup of struct tpm_chip If the initialization fails before tpm_chip_register(), put_device() will be not called, which causes release callback not to be called. This patch fixes the issue by adding put_device() to devres list of the parent device. Fixes: 313d21eeab ("tpm: device class for tpm") Signed-off-by: Jarkko Sakkinen cc: stable@vger.kernel.org Reviewed-by: Jason Gunthorpe --- drivers/char/tpm/tpm-chip.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 1a9dcee8da5a..252142524ff2 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -136,6 +136,8 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, chip->cdev.owner = chip->pdev->driver->owner; chip->cdev.kobj.parent = &chip->dev.kobj; + devm_add_action(dev, (void (*)(void *)) put_device, &chip->dev); + return chip; } EXPORT_SYMBOL_GPL(tpmm_chip_alloc); @@ -171,7 +173,7 @@ static int tpm_add_char_device(struct tpm_chip *chip) static void tpm_del_char_device(struct tpm_chip *chip) { cdev_del(&chip->cdev); - device_unregister(&chip->dev); + device_del(&chip->dev); } static int tpm1_chip_register(struct tpm_chip *chip) -- cgit v1.2.3 From b82fcabe212a11698fd4b3e604d2f81d929d22f6 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Thu, 28 Jan 2016 16:14:18 +0800 Subject: phy: core: fix wrong err handle for phy_power_on If phy_pm_runtime_get_sync failed but we already enable regulator, current code return directly without doing regulator_disable. This patch fix this problem and cleanup err handle of phy_power_on to be more readable. Fixes: 3be88125d85d ("phy: core: Support regulator ...") Cc: # v3.18+ Cc: Roger Quadros Cc: Axel Lin Signed-off-by: Shawn Lin Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-core.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 8c7f27db6ad3..e7e574dc667a 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -275,20 +275,21 @@ EXPORT_SYMBOL_GPL(phy_exit); int phy_power_on(struct phy *phy) { - int ret; + int ret = 0; if (!phy) - return 0; + goto out; if (phy->pwr) { ret = regulator_enable(phy->pwr); if (ret) - return ret; + goto out; } ret = phy_pm_runtime_get_sync(phy); if (ret < 0 && ret != -ENOTSUPP) - return ret; + goto err_pm_sync; + ret = 0; /* Override possible ret == -ENOTSUPP */ mutex_lock(&phy->mutex); @@ -296,19 +297,20 @@ int phy_power_on(struct phy *phy) ret = phy->ops->power_on(phy); if (ret < 0) { dev_err(&phy->dev, "phy poweron failed --> %d\n", ret); - goto out; + goto err_pwr_on; } } ++phy->power_count; mutex_unlock(&phy->mutex); return 0; -out: +err_pwr_on: mutex_unlock(&phy->mutex); phy_pm_runtime_put_sync(phy); +err_pm_sync: if (phy->pwr) regulator_disable(phy->pwr); - +out: return ret; } EXPORT_SYMBOL_GPL(phy_power_on); -- cgit v1.2.3 From b241d31ef2f6a289d33dcaa004714b26e06f476f Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 30 Nov 2015 21:39:53 -0800 Subject: phy: twl4030-usb: Relase usb phy on unload Otherwise rmmod omap2430; rmmod phy-twl4030-usb; modprobe omap2430 will try to use a non-existing phy and oops: Unable to handle kernel paging request at virtual address b6f7c1f0 ... [] (devm_usb_get_phy_by_node) from [] (omap2430_musb_init+0x44/0x2b4 [omap2430]) [] (omap2430_musb_init [omap2430]) from [] (musb_init_controller+0x194/0x878 [musb_hdrc]) Cc: stable@vger.kernel.org Cc: Bin Liu Cc: Felipe Balbi Cc: Kishon Vijay Abraham I Cc: NeilBrown Signed-off-by: Tony Lindgren Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-twl4030-usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index 4a3fc6e59f8e..fe5538ff380f 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c @@ -750,6 +750,7 @@ static int twl4030_usb_remove(struct platform_device *pdev) struct twl4030_usb *twl = platform_get_drvdata(pdev); int val; + usb_remove_phy(&twl->phy); pm_runtime_get_sync(twl->dev); cancel_delayed_work(&twl->id_workaround_work); device_remove_file(twl->dev, &dev_attr_vbus); -- cgit v1.2.3 From 58a66dba1beac2121d931cda4682ae4d40816af5 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 30 Nov 2015 21:39:54 -0800 Subject: phy: twl4030-usb: Fix unbalanced pm_runtime_enable on module reload If we reload phy-twl4030-usb, we get a warning about unbalanced pm_runtime_enable. Let's fix the issue and also fix idling of the device on unload before we attempt to shut it down. If we don't properly idle the PHY before shutting it down on removal, the twl4030 ends up consuming about 62mW of extra power compared to running idle with the module loaded. Cc: stable@vger.kernel.org Cc: Bin Liu Cc: Felipe Balbi Cc: Kishon Vijay Abraham I Cc: NeilBrown Signed-off-by: Tony Lindgren Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-twl4030-usb.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index fe5538ff380f..840f3eae428b 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c @@ -715,6 +715,7 @@ static int twl4030_usb_probe(struct platform_device *pdev) pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, 2000); pm_runtime_enable(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); /* Our job is to use irqs and status from the power module * to keep the transceiver disabled when nothing's connected. @@ -758,6 +759,13 @@ static int twl4030_usb_remove(struct platform_device *pdev) /* set transceiver mode to power on defaults */ twl4030_usb_set_mode(twl, -1); + /* idle ulpi before powering off */ + if (cable_present(twl->linkstat)) + pm_runtime_put_noidle(twl->dev); + pm_runtime_mark_last_busy(twl->dev); + pm_runtime_put_sync_suspend(twl->dev); + pm_runtime_disable(twl->dev); + /* autogate 60MHz ULPI clock, * clear dpll clock request for i2c access, * disable 32KHz @@ -772,11 +780,6 @@ static int twl4030_usb_remove(struct platform_device *pdev) /* disable complete OTG block */ twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); - if (cable_present(twl->linkstat)) - pm_runtime_put_noidle(twl->dev); - pm_runtime_mark_last_busy(twl->dev); - pm_runtime_put(twl->dev); - return 0; } -- cgit v1.2.3 From 52dfa12e45510fce566fb240135420d7a0b5d0e6 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 9 Feb 2016 21:11:12 +0100 Subject: drm/gma500: fix error path in gma_intel_setup_gmbus() The current code fails to call i2c_del_adapter on dev_prev->gmbus[0].adapter, and if the for loop above failed already at i==0, all hell breaks loose when we do the loop body for i = -1,-2,... Signed-off-by: Rasmus Villemoes Link: http://patchwork.freedesktop.org/patch/msgid/1455048677-19882-2-git-send-email-linux@rasmusvillemoes.dk Reviewed-by: Andy Shevchenko Signed-off-by: Daniel Vetter --- drivers/gpu/drm/gma500/intel_gmbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/gma500/intel_gmbus.c b/drivers/gpu/drm/gma500/intel_gmbus.c index 566d330aaeea..e7e22187c539 100644 --- a/drivers/gpu/drm/gma500/intel_gmbus.c +++ b/drivers/gpu/drm/gma500/intel_gmbus.c @@ -436,7 +436,7 @@ int gma_intel_setup_gmbus(struct drm_device *dev) return 0; err: - while (--i) { + while (i--) { struct intel_gmbus *bus = &dev_priv->gmbus[i]; i2c_del_adapter(&bus->adapter); } -- cgit v1.2.3 From da3b891b0fb88605bb2d16adaf1ef2a1f16403ba Mon Sep 17 00:00:00 2001 From: Lyude Date: Thu, 4 Feb 2016 10:43:21 -0500 Subject: drm/i915/skl: Fix typo in DPLL_CFGCR1 definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We accidentally point both cfgcr registers for the second shared DPLL to the same location in i915_reg.h. This results in a lot of hw pipe state mismatches whenever we try to do a modeset that requires allocating the DPLL to a CRTC: [drm:intel_pipe_config_compare [i915]] *ERROR* mismatch in dpll_hw_state.cfgcr1 (expected 0x80000168, found 0x000004a5) [drm:intel_pipe_config_compare [i915]] *ERROR* mismatch in base.adjusted_mode.crtc_clock (expected 108000, found 49500) [drm:intel_pipe_config_compare [i915]] *ERROR* mismatch in port_clock (expected 108000, found 49500) This usually ends up causing blank monitors, since the DPLL never can get set to the right clock. Fixes: 086f8e84a085 ("drm/i915: Prefix raw register defines with underscore") Signed-off-by: Lyude Cc: drm-intel-fixes@lists.freedesktop.org Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1454600601-21900-1-git-send-email-cpaul@redhat.com --- 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 188ad5de020f..665ae4846731 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7545,7 +7545,7 @@ enum skl_disp_power_wells { #define DPLL_CFGCR2_PDIV_7 (4<<2) #define DPLL_CFGCR2_CENTRAL_FREQ_MASK (3) -#define DPLL_CFGCR1(id) _MMIO_PIPE((id) - SKL_DPLL1, _DPLL1_CFGCR1, _DPLL2_CFGCR2) +#define DPLL_CFGCR1(id) _MMIO_PIPE((id) - SKL_DPLL1, _DPLL1_CFGCR1, _DPLL2_CFGCR1) #define DPLL_CFGCR2(id) _MMIO_PIPE((id) - SKL_DPLL1, _DPLL1_CFGCR2, _DPLL2_CFGCR2) /* BXT display engine PLL */ -- cgit v1.2.3 From 8c448cadd4dd1bb3a8f34a93eaceb464d6e7a1db Mon Sep 17 00:00:00 2001 From: Gabriel Feceoru Date: Fri, 22 Jan 2016 13:28:45 +0200 Subject: drm/i915: Handle PipeC fused off on IVB/HSW/BDW Some Gen7/8 production parts may have the Display Pipe C fused off. In this case, the display hardware will prevent the enable bit in PIPE_CONF register (for Pipe C) from being set to 1. Fixed by adjusting pipe_count to reflect this. v2: Rename HSW_PIPE_C_DISABLE to IVB_PIPE_C_DISABLE as it already exists on ivybridge (Ville) v3: Remove unnecessary MMIO read, correct the description (Damien) v4: Be more specific in description (Patrick) Signed-off-by: Gabriel Feceoru Reviewed-by: Patrik Jakobsson Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453462125-21519-1-git-send-email-gabriel.feceoru@intel.com --- drivers/gpu/drm/i915/i915_dma.c | 3 +++ drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index a42eb58f7c41..35c2b33560b4 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -808,6 +808,9 @@ static void intel_device_info_runtime_init(struct drm_device *dev) !(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) { DRM_INFO("Display fused off, disabling\n"); info->num_pipes = 0; + } else if (fuse_strap & IVB_PIPE_C_DISABLE) { + DRM_INFO("PipeC fused off\n"); + info->num_pipes -= 1; } } else if (info->num_pipes > 0 && INTEL_INFO(dev)->gen == 9) { u32 dfsm = I915_READ(SKL_DFSM); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 665ae4846731..144586ee74d5 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5949,6 +5949,7 @@ enum skl_disp_power_wells { #define ILK_INTERNAL_GRAPHICS_DISABLE (1 << 31) #define ILK_INTERNAL_DISPLAY_DISABLE (1 << 30) #define ILK_DISPLAY_DEBUG_DISABLE (1 << 29) +#define IVB_PIPE_C_DISABLE (1 << 28) #define ILK_HDCP_DISABLE (1 << 25) #define ILK_eDP_A_DISABLE (1 << 24) #define HSW_CDCLK_LIMIT (1 << 24) -- cgit v1.2.3 From 1b39a917a9e00378c02c50ad86632ed3d872bfad Mon Sep 17 00:00:00 2001 From: Nick Hoath Date: Fri, 22 Jan 2016 23:10:06 +0000 Subject: drm/i915: fix context/engine cleanup order Swap the order of context & engine cleanup, so that contexts are cleaned up first, and *then* engines. This is a more sensible order anyway, but in particular has become necessary since the 'intel_ring_initialized() must be simple and inline' patch, which now uses ring->dev as an 'initialised' flag, so it can now be NULL after engine teardown. This in turn can cause a problem in the context code, which (used to) check the ring->dev->struct_mutex -- causing a fault if ring->dev was NULL. Also rename the cleanup function to reflect what it actually does (cleanup engines, not a ringbuffer), and fix an annoying whitespace issue. v2: Also make the fix in i915_load_modeset_init, not just in i915_driver_unload (Chris Wilson) v3: Had extra stuff in it. v4: Reverted extra stuff (so we're back to v2). Rebased and updated commentary above (Dave Gordon). Signed-off-by: Nick Hoath Signed-off-by: David Gordon Reviewed-by: Chris Wilson Cc: Mika Kuoppala Cc: Daniel Vetter Cc: Chris Wilson Signed-off-by: Dave Gordon Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453504211-7982-2-git-send-email-david.s.gordon@intel.com --- drivers/gpu/drm/i915/i915_dma.c | 4 ++-- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 23 ++++++++++++----------- 3 files changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 35c2b33560b4..571d7e62953b 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -444,8 +444,8 @@ static int i915_load_modeset_init(struct drm_device *dev) cleanup_gem: mutex_lock(&dev->struct_mutex); - i915_gem_cleanup_ringbuffer(dev); i915_gem_context_fini(dev); + i915_gem_cleanup_engines(dev); mutex_unlock(&dev->struct_mutex); cleanup_irq: intel_guc_ucode_fini(dev); @@ -1256,8 +1256,8 @@ int i915_driver_unload(struct drm_device *dev) intel_guc_ucode_fini(dev); mutex_lock(&dev->struct_mutex); - i915_gem_cleanup_ringbuffer(dev); i915_gem_context_fini(dev); + i915_gem_cleanup_engines(dev); mutex_unlock(&dev->struct_mutex); intel_fbc_cleanup_cfb(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8216665405eb..e11eef1e5134 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3058,7 +3058,7 @@ int i915_gem_init_rings(struct drm_device *dev); int __must_check i915_gem_init_hw(struct drm_device *dev); int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice); void i915_gem_init_swizzling(struct drm_device *dev); -void i915_gem_cleanup_ringbuffer(struct drm_device *dev); +void i915_gem_cleanup_engines(struct drm_device *dev); int __must_check i915_gpu_idle(struct drm_device *dev); int __must_check i915_gem_suspend(struct drm_device *dev); void __i915_add_request(struct drm_i915_gem_request *req, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e9b19bca1383..de57e7f0be0f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4913,7 +4913,7 @@ i915_gem_init_hw(struct drm_device *dev) req = i915_gem_request_alloc(ring, NULL); if (IS_ERR(req)) { ret = PTR_ERR(req); - i915_gem_cleanup_ringbuffer(dev); + i915_gem_cleanup_engines(dev); goto out; } @@ -4926,7 +4926,7 @@ i915_gem_init_hw(struct drm_device *dev) if (ret && ret != -EIO) { DRM_ERROR("PPGTT enable ring #%d failed %d\n", i, ret); i915_gem_request_cancel(req); - i915_gem_cleanup_ringbuffer(dev); + i915_gem_cleanup_engines(dev); goto out; } @@ -4934,7 +4934,7 @@ i915_gem_init_hw(struct drm_device *dev) if (ret && ret != -EIO) { DRM_ERROR("Context enable ring #%d failed %d\n", i, ret); i915_gem_request_cancel(req); - i915_gem_cleanup_ringbuffer(dev); + i915_gem_cleanup_engines(dev); goto out; } @@ -5009,7 +5009,7 @@ out_unlock: } void -i915_gem_cleanup_ringbuffer(struct drm_device *dev) +i915_gem_cleanup_engines(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *ring; @@ -5018,13 +5018,14 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev) for_each_ring(ring, dev_priv, i) dev_priv->gt.cleanup_ring(ring); - if (i915.enable_execlists) - /* - * Neither the BIOS, ourselves or any other kernel - * expects the system to be in execlists mode on startup, - * so we need to reset the GPU back to legacy mode. - */ - intel_gpu_reset(dev); + if (i915.enable_execlists) { + /* + * Neither the BIOS, ourselves or any other kernel + * expects the system to be in execlists mode on startup, + * so we need to reset the GPU back to legacy mode. + */ + intel_gpu_reset(dev); + } } static void -- cgit v1.2.3 From 06e6ff8f10513ae863adeddf21510c99171a6283 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Thu, 28 Jan 2016 17:18:41 +0000 Subject: drm/i915: Capture PCI revision and subsytem details in error state Revision id along with device id is useful in better identification of the HW and its limitations so include this detail in error state. v2: make it clear that it is PCI revision and We might as well dump PCI subsystem details while we update this (Ville, Chris). Cc: Chris Wilson Signed-off-by: Arun Siluvery Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1454001521-7701-1-git-send-email-arun.siluvery@linux.intel.com --- drivers/gpu/drm/i915/i915_gpu_error.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 7eeb24427785..978c026963b8 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -365,6 +365,10 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, err_printf(m, "Reset count: %u\n", error->reset_count); err_printf(m, "Suspend count: %u\n", error->suspend_count); err_printf(m, "PCI ID: 0x%04x\n", dev->pdev->device); + err_printf(m, "PCI Revision: 0x%02x\n", dev->pdev->revision); + err_printf(m, "PCI Subsystem: %04x:%04x\n", + dev->pdev->subsystem_vendor, + dev->pdev->subsystem_device); err_printf(m, "IOMMU enabled?: %d\n", error->iommu); if (HAS_CSR(dev)) { -- cgit v1.2.3 From 9f5ac8ed4013c616bd3b29147808c8b2f057c251 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 27 Jan 2016 14:37:58 +0100 Subject: agp/intel-gtt: Don't leak the scratch page Recently discovered by enabling CONFIG_DMA_API_DEBUG in our CI. By the looks of it broken since forever. v2: Don't forget to set the scratch page back to wb (Chris). Reuse intel_gtt_teardown_scratch_page for that (and fix it up to treat needs_dmar y/n correctly). Cc: Chris Wilson Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93793 Signed-off-by: Daniel Vetter Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453901881-26425-1-git-send-email-daniel.vetter@ffwll.ch --- drivers/char/agp/intel-gtt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 1341a94cc779..e657f989745e 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -555,8 +555,10 @@ static unsigned int intel_gtt_mappable_entries(void) static void intel_gtt_teardown_scratch_page(void) { set_pages_wb(intel_private.scratch_page, 1); - pci_unmap_page(intel_private.pcidev, intel_private.scratch_page_dma, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + if (intel_private.needs_dmar) + pci_unmap_page(intel_private.pcidev, + intel_private.scratch_page_dma, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); __free_page(intel_private.scratch_page); } @@ -1430,6 +1432,8 @@ void intel_gmch_remove(void) if (--intel_private.refcount) return; + if (intel_private.scratch_page) + intel_gtt_teardown_scratch_page(); if (intel_private.pcidev) pci_dev_put(intel_private.pcidev); if (intel_private.bridge_dev) -- cgit v1.2.3 From 3e99a6b9561402909fdb3b0028764d42557e0103 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 27 Jan 2016 14:37:59 +0100 Subject: drm/i915: Stop depending upon CONFIG_AGP_INTEL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The AGP_INTEL driver provides an interface for very old userspace to control the GART (though the GART itself was only ever emulated on Intel systems). The pci bridge discovery code is also used by the i915.ko driver to set up the GTT on old systems, but it does not require the old userspace interface. When i915.ko selects the old interface, it binds another user to the core GTT routines, and in particular creates a second reference to the scratch pages allocated. This hinders resource leak debugging for when we unload i915.ko as we want to assert that all DMA pages have been released, but we appear to leak because of the secondary interface which persists after i915.ko unloads. All i915.ko users do not require the old /dev/agpgart interface so stop selecting it and simplify our debugging by dropping the historical baggage. Note that by selecting AGP=n it was already possible to unselect AGP_INTEL. But since we've dropped support for any of the AGP stuff long ago there's really no point for this any more. Also note that we still need INTEL_GTT, which is the underlying, shared, driver for the graphics GART on gen1-5. v2: Entirely new commit message (Chris, Ville). Cc: Ville Syrjälä Cc: Chris Wilson Signed-off-by: Daniel Vetter Reviewed-by: Ville Syrjälä Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453901881-26425-2-git-send-email-daniel.vetter@ffwll.ch --- drivers/gpu/drm/i915/Kconfig | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 051eab33e4c7..4c59793c4ccb 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -2,9 +2,7 @@ config DRM_I915 tristate "Intel 8xx/9xx/G3x/G4x/HD Graphics" depends on DRM depends on X86 && PCI - depends on (AGP || AGP=n) select INTEL_GTT - select AGP_INTEL if AGP select INTERVAL_TREE # we need shmfs for the swappable backing store, and in particular # the shmem_readpage() which depends upon tmpfs -- cgit v1.2.3 From fe0e2304f560f81c1673711ac3f9a8c7c3cbb8be Mon Sep 17 00:00:00 2001 From: Stephan Olbrich Date: Tue, 9 Feb 2016 19:10:32 +0100 Subject: spi: bcm2835aux: fix bitmask defines The bitmasks for txempty and idle interrupts were interchanged. Signed-off-by: Stephan Olbrich Reviewed-by: Eric Anholt Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835aux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index 7de6f8472a81..ecc73c0a97cf 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -73,8 +73,8 @@ /* Bitfields in CNTL1 */ #define BCM2835_AUX_SPI_CNTL1_CSHIGH 0x00000700 -#define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000080 -#define BCM2835_AUX_SPI_CNTL1_TXEMPTY 0x00000040 +#define BCM2835_AUX_SPI_CNTL1_TXEMPTY 0x00000080 +#define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000040 #define BCM2835_AUX_SPI_CNTL1_MSBF_IN 0x00000002 #define BCM2835_AUX_SPI_CNTL1_KEEP_IN 0x00000001 -- cgit v1.2.3 From f00ab14c252ac459e86194747a1f580ab503c954 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Tue, 9 Feb 2016 09:34:30 -0800 Subject: mmc: block: return error on failed mmc_blk_get() This used to return -EFAULT, but the function above returns -EINVAL on the same condition so let's stick to that. The removal of error return on this path was introduced with b093410c9aef ('mmc: block: copy resp[] data on err for MMC_IOC_MULTI_CMD'). Fixes: b093410c9aef ('mmc: block: copy resp[] data on err for MMC_IOC_MULTI_CMD'). Signed-off-by: Olof Johansson Cc: Grant Grundler Signed-off-by: Ulf Hansson --- drivers/mmc/card/block.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 5914263090fc..951641a96806 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -655,8 +655,10 @@ static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev, } md = mmc_blk_get(bdev->bd_disk); - if (!md) + if (!md) { + err = -EINVAL; goto cmd_err; + } card = md->queue.card; if (IS_ERR(card)) { -- cgit v1.2.3 From 2417c8c03f508841b85bf61acc91836b7b0e2560 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Tue, 9 Feb 2016 21:11:13 +0100 Subject: drm/i915: fix error path in intel_setup_gmbus() This fails to undo the setup for pin==0; moreover, something interesting happens if the setup failed already at pin==0. Signed-off-by: Rasmus Villemoes Fixes: f899fc64cda8 ("drm/i915: use GMBUS to manage i2c links") Cc: stable@vger.kernel.org Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1455048677-19882-3-git-send-email-linux@rasmusvillemoes.dk --- drivers/gpu/drm/i915/intel_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 25254b5c1ac5..deb8282c26d8 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -683,7 +683,7 @@ int intel_setup_gmbus(struct drm_device *dev) return 0; err: - while (--pin) { + while (pin--) { if (!intel_gmbus_is_valid_pin(dev_priv, pin)) continue; -- cgit v1.2.3 From 54d0dbac1266d2b9a6b5a87316162a068ad545bf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 07:02:43 -0200 Subject: [media] v4l2-mc: add a generic function to create the media graph The em28xx_v4l2_create_media_graph() is almost generic enough to be at the core, as an ancillary function. Make it even more generic, by getting rid of em28xx-specific code, relying only at the media_device, in order to discover all entities found on PC-customer's hardware and add it at the V4L2 core. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/Makefile | 1 + drivers/media/v4l2-core/v4l2-mc.c | 186 ++++++++++++++++++++++++++++++++++++++ include/media/v4l2-mc.h | 25 +++++ 3 files changed, 212 insertions(+) create mode 100644 drivers/media/v4l2-core/v4l2-mc.c (limited to 'drivers') diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile index 1dc8bba2b198..795a5352761d 100644 --- a/drivers/media/v4l2-core/Makefile +++ b/drivers/media/v4l2-core/Makefile @@ -16,6 +16,7 @@ endif ifeq ($(CONFIG_TRACEPOINTS),y) videodev-objs += vb2-trace.o v4l2-trace.o endif +videodev-$(CONFIG_MEDIA_CONTROLLER) += v4l2-mc.o obj-$(CONFIG_VIDEO_V4L2) += videodev.o obj-$(CONFIG_VIDEO_V4L2) += v4l2-common.o diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c new file mode 100644 index 000000000000..e6d2a711bb0b --- /dev/null +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -0,0 +1,186 @@ +/* + * Media Controller ancillary functions + * + * (c) 2016 Mauro Carvalho Chehab + * + * 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. + */ + +#include +#include +#include + +int v4l2_mc_create_media_graph(struct media_device *mdev) + +{ + struct media_entity *entity; + struct media_entity *if_vid = NULL, *if_aud = NULL, *sensor = NULL; + struct media_entity *tuner = NULL, *decoder = NULL; + struct media_entity *io_v4l = NULL, *io_vbi = NULL, *io_swradio = NULL; + bool is_webcam = false; + u32 flags; + int ret; + + if (!mdev) + return 0; + + media_device_for_each_entity(entity, mdev) { + switch (entity->function) { + case MEDIA_ENT_F_IF_VID_DECODER: + if_vid = entity; + break; + case MEDIA_ENT_F_IF_AUD_DECODER: + if_aud = entity; + break; + case MEDIA_ENT_F_TUNER: + tuner = entity; + break; + case MEDIA_ENT_F_ATV_DECODER: + decoder = entity; + break; + case MEDIA_ENT_F_IO_V4L: + io_v4l = entity; + break; + case MEDIA_ENT_F_IO_VBI: + io_vbi = entity; + break; + case MEDIA_ENT_F_IO_SWRADIO: + io_swradio = entity; + break; + case MEDIA_ENT_F_CAM_SENSOR: + sensor = entity; + is_webcam = true; + break; + } + } + + /* It should have at least one I/O entity */ + if (!io_v4l && !io_vbi && !io_swradio) + return -EINVAL; + + /* + * Here, webcams are modelled on a very simple way: the sensor is + * connected directly to the I/O entity. All dirty details, like + * scaler and crop HW are hidden. While such mapping is not enough + * for mc-centric hardware, it is enough for v4l2 interface centric + * PC-consumer's hardware. + */ + if (is_webcam) { + if (!io_v4l) + return -EINVAL; + + media_device_for_each_entity(entity, mdev) { + if (entity->function != MEDIA_ENT_F_CAM_SENSOR) + continue; + ret = media_create_pad_link(entity, 0, + io_v4l, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + if (!decoder) + return 0; + } + + /* The device isn't a webcam. So, it should have a decoder */ + if (!decoder) + return -EINVAL; + + /* Link the tuner and IF video output pads */ + if (tuner) { + if (if_vid) { + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, + if_vid, + IF_VID_DEC_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT, + decoder, DEMOD_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } else { + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, + decoder, DEMOD_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + if (if_aud) { + ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT, + if_aud, + IF_AUD_DEC_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } else { + if_aud = tuner; + } + + } + + /* Create demod to V4L, VBI and SDR radio links */ + if (io_v4l) { + ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT, + io_v4l, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + if (io_swradio) { + ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT, + io_swradio, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + if (io_vbi) { + ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT, + io_vbi, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + /* Create links for the media connectors */ + flags = MEDIA_LNK_FL_ENABLED; + media_device_for_each_entity(entity, mdev) { + switch (entity->function) { + case MEDIA_ENT_F_CONN_RF: + if (!tuner) + continue; + + ret = media_create_pad_link(entity, 0, tuner, + TUNER_PAD_RF_INPUT, + flags); + break; + case MEDIA_ENT_F_CONN_SVIDEO: + case MEDIA_ENT_F_CONN_COMPOSITE: + case MEDIA_ENT_F_CONN_TEST: + ret = media_create_pad_link(entity, 0, decoder, + DEMOD_PAD_IF_INPUT, + flags); + break; + default: + continue; + } + if (ret) + return ret; + + flags = 0; + } + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_mc_create_media_graph); diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index df115195690e..aed9e9b87f82 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -14,6 +14,8 @@ * GNU General Public License for more details. */ +#include + /** * enum tuner_pad_index - tuner pad index for MEDIA_ENT_F_TUNER * @@ -89,3 +91,26 @@ enum demod_pad_index { DEMOD_PAD_VBI_OUT, DEMOD_NUM_PADS }; + +/** + * v4l2_mc_create_media_graph() - create Media Controller links at the graph. + * + * @mdev: pointer to the &media_device struct. + * + * Add links between the entities commonly found on PC customer's hardware at + * the V4L2 side: camera sensors, audio and video PLL-IF decoders, tuners, + * analog TV decoder and I/O entities (video, VBI and Software Defined Radio). + * NOTE: webcams are modelled on a very simple way: the sensor is + * connected directly to the I/O entity. All dirty details, like + * scaler and crop HW are hidden. While such mapping is enough for v4l2 + * interface centric PC-consumer's hardware, V4L2 subdev centric camera + * hardware should not use this routine, as it will not build the right graph. + */ +#ifdef CONFIG_MEDIA_CONTROLLER +int v4l2_mc_create_media_graph(struct media_device *mdev); +#else +static inline int v4l2_mc_create_media_graph(struct media_device *mdev) +{ + return 0; +} +#endif -- cgit v1.2.3 From de39078779cb08b21e7e3d2daa7d3b64a53a8d20 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 07:08:25 -0200 Subject: [media] em2xx: use v4l2_mc_create_media_graph() Now that the core has a function to create the media graph, we can get rid of the specialized code at em28xx. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 131 +------------------------------- 1 file changed, 1 insertion(+), 130 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 16a2d4039330..e7fd0bac4a08 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -883,135 +883,6 @@ static void em28xx_v4l2_media_release(struct em28xx *dev) * Media Controller helper functions */ -static int em28xx_v4l2_create_media_graph(struct em28xx *dev) -{ -#ifdef CONFIG_MEDIA_CONTROLLER - struct em28xx_v4l2 *v4l2 = dev->v4l2; - struct media_device *mdev = dev->media_dev; - struct media_entity *entity; - struct media_entity *if_vid = NULL, *if_aud = NULL; - struct media_entity *tuner = NULL, *decoder = NULL; - int i, ret; - - if (!mdev) - return 0; - - /* Webcams are really simple */ - if (dev->board.is_webcam) { - media_device_for_each_entity(entity, mdev) { - if (entity->function != MEDIA_ENT_F_CAM_SENSOR) - continue; - ret = media_create_pad_link(entity, 0, - &v4l2->vdev.entity, 0, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - } - return 0; - } - - /* Non-webcams have analog TV decoder and other complexities */ - - media_device_for_each_entity(entity, mdev) { - switch (entity->function) { - case MEDIA_ENT_F_IF_VID_DECODER: - if_vid = entity; - break; - case MEDIA_ENT_F_IF_AUD_DECODER: - if_aud = entity; - break; - case MEDIA_ENT_F_TUNER: - tuner = entity; - break; - case MEDIA_ENT_F_ATV_DECODER: - decoder = entity; - break; - } - } - - /* Analog setup, using tuner as a link */ - - /* Something bad happened! */ - if (!decoder) - return -EINVAL; - - if (tuner) { - if (if_vid) { - ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, - if_vid, - IF_VID_DEC_PAD_IF_INPUT, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT, - decoder, DEMOD_PAD_IF_INPUT, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - } else { - ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, - decoder, DEMOD_PAD_IF_INPUT, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - } - - if (if_aud) { - ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT, - if_aud, - IF_AUD_DEC_PAD_IF_INPUT, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - } else { - if_aud = tuner; - } - - } - ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT, - &v4l2->vdev.entity, 0, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - - if (em28xx_vbi_supported(dev)) { - ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT, - &v4l2->vbi_dev.entity, 0, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - } - - for (i = 0; i < MAX_EM28XX_INPUT; i++) { - struct media_entity *ent = &dev->input_ent[i]; - - if (!INPUT(i)->type) - break; - - switch (INPUT(i)->type) { - case EM28XX_VMUX_COMPOSITE: - case EM28XX_VMUX_SVIDEO: - ret = media_create_pad_link(ent, 0, decoder, - DEMOD_PAD_IF_INPUT, 0); - if (ret) - return ret; - break; - default: /* EM28XX_VMUX_TELEVISION or EM28XX_RADIO */ - if (!tuner) - break; - - ret = media_create_pad_link(ent, 0, tuner, - TUNER_PAD_RF_INPUT, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - break; - } - } -#endif - return 0; -} - static int em28xx_enable_analog_tuner(struct em28xx *dev) { #ifdef CONFIG_MEDIA_CONTROLLER @@ -2842,7 +2713,7 @@ static int em28xx_v4l2_init(struct em28xx *dev) /* Init entities at the Media Controller */ em28xx_v4l2_create_entities(dev); - ret = em28xx_v4l2_create_media_graph(dev); + ret = v4l2_mc_create_media_graph(dev->media_dev); if (ret) { em28xx_errdev("failed to create media graph\n"); em28xx_v4l2_media_release(dev); -- cgit v1.2.3 From 2773b0e9baa68beed1f93d04a8ae8ca04b35a60d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 08:35:50 -0200 Subject: [media] add media controller support to videobuf2-dvb Allow devices to pass an optional argument to register the DVB driver at the media controller. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx23885/cx23885-dvb.c | 3 ++- drivers/media/pci/cx88/cx88-dvb.c | 3 ++- drivers/media/pci/netup_unidvb/netup_unidvb_core.c | 4 ++-- drivers/media/pci/saa7134/saa7134-dvb.c | 2 +- drivers/media/v4l2-core/videobuf2-dvb.c | 13 +++++++++++-- include/media/videobuf2-dvb.h | 5 +++++ 6 files changed, 23 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index 80319bb73d94..5131c9f555fb 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -2301,7 +2301,8 @@ static int dvb_register(struct cx23885_tsport *port) /* register everything */ ret = vb2_dvb_register_bus(&port->frontends, THIS_MODULE, port, - &dev->pci->dev, adapter_nr, mfe_shared); + &dev->pci->dev, NULL, + adapter_nr, mfe_shared); if (ret) goto frontend_detach; diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c index afb20756d7a5..851d2a9caed3 100644 --- a/drivers/media/pci/cx88/cx88-dvb.c +++ b/drivers/media/pci/cx88/cx88-dvb.c @@ -1642,7 +1642,8 @@ static int dvb_register(struct cx8802_dev *dev) /* register everything */ res = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, - &dev->pci->dev, adapter_nr, mfe_shared); + &dev->pci->dev, NULL, adapter_nr, + mfe_shared); if (res) goto frontend_detach; return res; diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c index c94cecd2aa40..2b667b315913 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c @@ -462,8 +462,8 @@ static int netup_unidvb_dvb_init(struct netup_unidvb_dev *ndev, } if (vb2_dvb_register_bus(&ndev->frontends[num], - THIS_MODULE, NULL, - &ndev->pci_dev->dev, adapter_nr, 1)) { + THIS_MODULE, NULL, + &ndev->pci_dev->dev, NULL, adapter_nr, 1)) { dev_dbg(&ndev->pci_dev->dev, "%s(): unable to register DVB bus %d\n", __func__, num); diff --git a/drivers/media/pci/saa7134/saa7134-dvb.c b/drivers/media/pci/saa7134/saa7134-dvb.c index 101ba8729416..ed84f7dea94c 100644 --- a/drivers/media/pci/saa7134/saa7134-dvb.c +++ b/drivers/media/pci/saa7134/saa7134-dvb.c @@ -1884,7 +1884,7 @@ static int dvb_init(struct saa7134_dev *dev) /* register everything else */ ret = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, - &dev->pci->dev, adapter_nr, 0); + &dev->pci->dev, NULL, adapter_nr, 0); /* this sequence is necessary to make the tda1004x load its firmware * and to enter analog mode of hybrid boards diff --git a/drivers/media/v4l2-core/videobuf2-dvb.c b/drivers/media/v4l2-core/videobuf2-dvb.c index d09269846b7e..9f38b4218c0d 100644 --- a/drivers/media/v4l2-core/videobuf2-dvb.c +++ b/drivers/media/v4l2-core/videobuf2-dvb.c @@ -77,6 +77,7 @@ static int vb2_dvb_register_adapter(struct vb2_dvb_frontends *fe, struct module *module, void *adapter_priv, struct device *device, + struct media_device *mdev, char *adapter_name, short *adapter_nr, int mfe_shared) @@ -94,7 +95,10 @@ static int vb2_dvb_register_adapter(struct vb2_dvb_frontends *fe, } fe->adapter.priv = adapter_priv; fe->adapter.mfe_shared = mfe_shared; - +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + if (mdev) + fe->adapter.mdev = mdev; +#endif return result; } @@ -193,6 +197,7 @@ int vb2_dvb_register_bus(struct vb2_dvb_frontends *f, struct module *module, void *adapter_priv, struct device *device, + struct media_device *mdev, short *adapter_nr, int mfe_shared) { @@ -207,7 +212,7 @@ int vb2_dvb_register_bus(struct vb2_dvb_frontends *f, } /* Bring up the adapter */ - res = vb2_dvb_register_adapter(f, module, adapter_priv, device, + res = vb2_dvb_register_adapter(f, module, adapter_priv, device, mdev, fe->dvb.name, adapter_nr, mfe_shared); if (res < 0) { pr_warn("vb2_dvb_register_adapter failed (errno = %d)\n", res); @@ -224,7 +229,11 @@ int vb2_dvb_register_bus(struct vb2_dvb_frontends *f, fe->dvb.name, res); goto err; } + res = dvb_create_media_graph(&f->adapter, false); + if (res < 0) + goto err; } + mutex_unlock(&f->lock); return 0; diff --git a/include/media/videobuf2-dvb.h b/include/media/videobuf2-dvb.h index 5b64c9eac2c9..87b559024b4a 100644 --- a/include/media/videobuf2-dvb.h +++ b/include/media/videobuf2-dvb.h @@ -8,6 +8,10 @@ #include #include + +/* We don't actually need to include media-device.h here */ +struct media_device; + /* * TODO: This header file should be replaced with videobuf2-core.h * Currently, vb2_thread is not a stuff of videobuf2-core, @@ -50,6 +54,7 @@ int vb2_dvb_register_bus(struct vb2_dvb_frontends *f, struct module *module, void *adapter_priv, struct device *device, + struct media_device *mdev, short *adapter_nr, int mfe_shared); -- cgit v1.2.3 From 8fc3486783f1571c7d836d397c8ff4fa2ca6457c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 10:24:37 -0200 Subject: [media] saa7134: use input types, instead of hardcoding strings Currently, the saa7134 driver is hardcoding input names on each board entry. More modern drivers define, instead, an enum for each input type. While the current logic works, it adds extra complexity at the driver, as it needs to discover the type of the input using some euristics. Instead, let's standardize the input types and use a type, instead of a name on all places. That will allow further patches to properly report the input type via VIDIOC_G_INPUT and to remove an extra field from the struct to identify if the input is for TV. Please notice that several boards define an input for receiving composite signals via a S-Video connector. The name of such input was inconsistent, so this patch cleans it and make it to be properly reported the same way for all boards. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-cards.c | 1619 ++++++++++++++------------- drivers/media/pci/saa7134/saa7134-core.c | 2 +- drivers/media/pci/saa7134/saa7134-tvaudio.c | 13 +- drivers/media/pci/saa7134/saa7134-video.c | 11 +- drivers/media/pci/saa7134/saa7134.h | 33 +- 5 files changed, 853 insertions(+), 825 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c index 29d2094c42a0..19975cec5da7 100644 --- a/drivers/media/pci/saa7134/saa7134-cards.c +++ b/drivers/media/pci/saa7134/saa7134-cards.c @@ -36,17 +36,23 @@ #include "xc5000.h" #include "s5h1411.h" -/* commly used strings */ -static char name_mute[] = "mute"; -static char name_radio[] = "Radio"; -static char name_tv[] = "Television"; -static char name_tv_mono[] = "TV (mono only)"; -static char name_comp[] = "Composite"; -static char name_comp1[] = "Composite1"; -static char name_comp2[] = "Composite2"; -static char name_comp3[] = "Composite3"; -static char name_comp4[] = "Composite4"; -static char name_svideo[] = "S-Video"; +/* Input names */ +const char * const saa7134_input_name[] = { + [SAA7134_INPUT_MUTE] = "mute", + [SAA7134_INPUT_RADIO] = "Radio", + [SAA7134_INPUT_TV] = "Television", + [SAA7134_INPUT_TV_MONO] = "TV (mono only)", + [SAA7134_INPUT_COMPOSITE] = "Composite", + [SAA7134_INPUT_COMPOSITE0] = "Composite0", + [SAA7134_INPUT_COMPOSITE1] = "Composite1", + [SAA7134_INPUT_COMPOSITE2] = "Composite2", + [SAA7134_INPUT_COMPOSITE3] = "Composite3", + [SAA7134_INPUT_COMPOSITE4] = "Composite4", + [SAA7134_INPUT_SVIDEO] = "S-Video", + [SAA7134_INPUT_SVIDEO0] = "S-Video0", + [SAA7134_INPUT_SVIDEO1] = "S-Video1", + [SAA7134_INPUT_COMPOSITE_OVER_SVIDEO] = "Composite over S-Video", +}; /* ------------------------------------------------------------------ */ /* board config info */ @@ -69,7 +75,7 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .inputs = {{ - .name = "default", + .type = SAA7134_INPUT_COMPOSITE, .vmux = 0, .amux = LINE1, }}, @@ -84,22 +90,22 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -114,40 +120,40 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 0xe000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x8000, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, .gpio = 0x4000, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, .gpio = 0x4000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x4000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x2000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x8000, }, @@ -163,34 +169,34 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 0xe000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .gpio = 0x0000, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, .gpio = 0x4000, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, .gpio = 0x4000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x4000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x2000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE2, .gpio = 0x8000, }, @@ -205,20 +211,20 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, /* Composite signal on S-Video input */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -235,40 +241,40 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 0x1E000, /* Set GP16 and unused 15,14,13 to Output */ .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x10000, /* GP16=1 selects TV input */ .tv = 1, },{ -/* .name = name_tv_mono, +/* .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, .tv = 1, },{ -*/ .name = name_comp1, /* Composite signal on S-Video input */ +*/ .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE2, /* .gpio = 0x4000, */ },{ - .name = name_comp2, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, .amux = LINE2, /* .gpio = 0x4000, */ },{ - .name = name_svideo, /* S-Video signal on S-Video input */ + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, /* .gpio = 0x4000, */ }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x00000, /* GP16=0 selects FM radio antenna */ }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x10000, }, @@ -285,40 +291,40 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0xe000, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x8000, .tv = 1, }, { - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, .gpio = 0x4000, }, { - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, .gpio = 0x4000, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x4000, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x2000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x8000, }, @@ -334,21 +340,21 @@ struct saa7134_board saa7134_boards[] = { .empress_addr = 0x20, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, .mpeg = SAA7134_MPEG_EMPRESS, @@ -364,21 +370,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -390,35 +396,35 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ /* workaround for problems with normal TV sound */ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, }, }, @@ -432,32 +438,32 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = "CVid over SVid", + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -472,24 +478,24 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x820000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x20000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x20000, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x20000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x20000, }, @@ -504,20 +510,20 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 4, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp2, /* CVideo over SVideo Connector */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE1, }} @@ -531,31 +537,31 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ /* workaround for problems with normal TV sound */ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -567,15 +573,15 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, @@ -590,25 +596,25 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp2, /* CVideo over SVideo Connector */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -622,25 +628,25 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, }, }, @@ -655,21 +661,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -681,15 +687,15 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 4, .amux = LINE2, .tv = 1, @@ -703,16 +709,16 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 7, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 8, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 8, .amux = LINE2, .tv = 1, @@ -726,21 +732,21 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 4, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 6, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 7, .amux = LINE1, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, }, }, @@ -753,21 +759,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, }, }, @@ -780,29 +786,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x0000, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE2, .gpio = 0x0000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE2, .gpio = 0x0000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x200000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .gpio = 0x0000, }, @@ -815,15 +821,15 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, @@ -839,34 +845,34 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0xe000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .gpio = 0x0000, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, .gpio = 0x4000, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, .gpio = 0x4000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x4000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x2000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE2, .gpio = 0x8000, }, @@ -881,23 +887,23 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .empress_addr = 0x20, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE1, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE1, },{ - .name = name_comp3, + .type = SAA7134_INPUT_COMPOSITE3, .vmux = 0, .amux = LINE1, },{ - .name = name_comp4, + .type = SAA7134_INPUT_COMPOSITE4, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -912,15 +918,15 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, @@ -935,17 +941,17 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x06c00012, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x0ac20012, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .gpio = 0x08c20012, @@ -968,23 +974,23 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0xcf00, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .gpio = 2 << 14, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .gpio = 1 << 14, },{ - .name = name_comp3, + .type = SAA7134_INPUT_COMPOSITE3, .vmux = 0, .gpio = 0 << 14, },{ - .name = name_comp4, + .type = SAA7134_INPUT_COMPOSITE4, .vmux = 0, .gpio = 3 << 14, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .gpio = 2 << 14, }}, @@ -999,34 +1005,34 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x03, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x00, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x02, }, { - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE1, .gpio = 0x02, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x02, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, .gpio = 0x01, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x00, }, @@ -1041,15 +1047,15 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .empress_addr = 0x20, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, @@ -1068,22 +1074,22 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, }, }, @@ -1096,20 +1102,20 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_INACTIVE, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 1, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -1123,21 +1129,21 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -1150,21 +1156,21 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -1177,16 +1183,16 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -1199,30 +1205,30 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = "CVid over SVid", + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -1234,30 +1240,30 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = "CVid over SVid", + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -1270,30 +1276,30 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = "CVid over SVid", + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -1306,30 +1312,30 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x200000, }, @@ -1343,10 +1349,10 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, }}, }, @@ -1360,7 +1366,7 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, @@ -1375,15 +1381,15 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, }}, }, @@ -1396,29 +1402,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -1432,29 +1438,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, }, { - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -1467,12 +1473,12 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 7, .amux = TV, .tv = 1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 7, .amux = LINE1, }}, @@ -1486,21 +1492,21 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -1512,25 +1518,25 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp2, /* CVideo over SVideo Connector */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE1, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE2, }, }, @@ -1544,29 +1550,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x808c0080, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x00080, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x00080, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2_LEFT, .tv = 1, .gpio = 0x00080, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x80000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE2, .gpio = 0x40000, }, @@ -1580,21 +1586,21 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -1607,15 +1613,15 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, @@ -1631,29 +1637,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x4000, .inputs = {{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x8000, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x8000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, .gpio = 0x8000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, .gpio = 0x8000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio =0x8000, } @@ -1672,29 +1678,29 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x03, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x00, },{ - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, .amux = LINE1, .gpio = 0x02, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x02, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, .gpio = 0x01, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, .gpio = 0x00, }, @@ -1709,29 +1715,29 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 0x00300003, /* .gpiomask = 0x8c240003, */ .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x01, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, .gpio = 0x02, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, .gpio = 0x02, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x00300001, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x01, }, @@ -1745,21 +1751,21 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, }, }, @@ -1774,24 +1780,24 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x08000000, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x08000000, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x08000000, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x08000000, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x00000000, }, @@ -1805,21 +1811,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -1834,25 +1840,25 @@ struct saa7134_board saa7134_boards[] = { .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp2, /* CVideo over SVideo Connector */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -1866,29 +1872,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x1ce780, .inputs = {{ - .name = name_svideo, - .vmux = 0, /* CVideo over SVideo Connector - ok? */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, + .vmux = 0, .amux = LINE1, .gpio = 0x008080, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x008080, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x008080, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x80000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE2, .gpio = 0x0c8000, }, @@ -1903,20 +1909,20 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_INACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 1, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -1931,22 +1937,22 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -1961,25 +1967,25 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -1995,26 +2001,26 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 0x00200000, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x200000, /* GPIO21=High for TV input */ .tv = 1, },{ - .name = name_comp1, /* Composite signal on S-Video input */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, /* S-Video signal on S-Video input */ + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ }, @@ -2028,11 +2034,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -2049,20 +2055,20 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -2075,16 +2081,16 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -2098,29 +2104,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x0700, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x000, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x200, /* gpio by DScaler */ },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 0, .amux = LINE1, .gpio = 0x200, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, .gpio = 0x100, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x000, }, @@ -2135,26 +2141,26 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x00200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x200000, /* GPIO21=High for TV input */ .tv = 1, },{ - .name = name_svideo, /* S-Video signal on S-Video input */ + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, },{ - .name = name_comp1, /* Composite signal on S-Video input */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ }, @@ -2168,29 +2174,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = 0x60, .gpiomask = 0x8c1880, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 0, .amux = LINE1, .gpio = 0x800800, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x801000, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x800000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x880000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE2, .gpio = 0x840000, }, @@ -2213,29 +2219,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = 0x60, .gpiomask = 0x0700, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x000, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x200, /* gpio by DScaler */ },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 0, .amux = LINE1, .gpio = 0x200, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, .gpio = 0x100, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x000, }, @@ -2248,30 +2254,30 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .radio = { - .name = name_radio, /* radio unconfirmed */ + .type = SAA7134_INPUT_RADIO, /* radio unconfirmed */ .amux = LINE2, }, }, @@ -2286,24 +2292,24 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 1 << 21, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x0000000, .tv = 1, },{ - .name = name_comp1, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, .gpio = 0x0000000, },{ - .name = name_svideo, /* S-Video input */ + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x0000000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -2322,29 +2328,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr= ADDR_UNSET, .gpiomask = 0x00010003, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x01, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, .gpio = 0x02, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE2, .gpio = 0x02, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, .gpio = 0x00010003, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x01, }, @@ -2362,21 +2368,21 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -2392,34 +2398,34 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00200003, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x00200003, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x00200003, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x00200003, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x00200003, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x00200003, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x00200003, }, @@ -2434,16 +2440,16 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -2458,16 +2464,16 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -2481,11 +2487,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -2499,27 +2505,28 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .empress_addr = 0x21, .inputs = {{ - .name = "Composite 0", + .type = SAA7134_INPUT_COMPOSITE0, .vmux = 0, .amux = LINE1, },{ - .name = "Composite 1", + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE2, },{ - .name = "Composite 2", + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 2, .amux = LINE1, },{ - .name = "Composite 3", + .type = SAA7134_INPUT_COMPOSITE3, .vmux = 3, .amux = LINE2, },{ - .name = "S-Video 0", + .type = SAA7134_INPUT_SVIDEO0, + .vmux = 8, .amux = LINE1, },{ - .name = "S-Video 1", + .type = SAA7134_INPUT_SVIDEO1, .vmux = 9, .amux = LINE2, }}, @@ -2538,27 +2545,27 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = "Composite 0", + .type = SAA7134_INPUT_COMPOSITE0, .vmux = 0, .amux = LINE1, },{ - .name = "Composite 1", + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE2, },{ - .name = "Composite 2", + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 2, .amux = LINE1, },{ - .name = "Composite 3", + .type = SAA7134_INPUT_COMPOSITE3, .vmux = 3, .amux = LINE2, },{ - .name = "S-Video 0", + .type = SAA7134_INPUT_SVIDEO0, .vmux = 8, .amux = LINE1, },{ - .name = "S-Video 1", + .type = SAA7134_INPUT_SVIDEO1, .vmux = 9, .amux = LINE2, }}, @@ -2572,20 +2579,20 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, /* Composite signal on S-Video input */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -2604,11 +2611,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -2622,16 +2629,16 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, }}, @@ -2645,25 +2652,25 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x080200000, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 4, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE2, }, { - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -2678,29 +2685,29 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 1 << 21, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x0000000, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, .gpio = 0x0200000, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE2, .gpio = 0x0200000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x0200000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -2717,21 +2724,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0xe880c0, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -2745,16 +2752,16 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -2770,21 +2777,21 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x0200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -2798,25 +2805,25 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 1 << 21, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, .amux = LINE2, /* unconfirmed, taken from Philips driver */ },{ - .name = name_comp2, - .vmux = 0, /* untested, Composite over S-Video */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, + .vmux = 0, /* untested */ .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -2834,17 +2841,17 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x80200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_svideo, /* NOT tested */ + .type = SAA7134_INPUT_SVIDEO, /* NOT tested */ .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -2861,26 +2868,26 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 0x00200000, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, /* Analog broadcast/cable TV */ + .type = SAA7134_INPUT_TV, /* Analog broadcast/cable TV */ .vmux = 1, .amux = TV, .gpio = 0x200000, /* GPIO21=High for TV input */ .tv = 1, },{ - .name = name_svideo, /* S-Video signal on S-Video input */ + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, },{ - .name = name_comp1, /* Composite signal on S-Video input */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ }, @@ -2894,11 +2901,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -2914,11 +2921,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_comp1, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, /* S-Video signal on S-Video input */ + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -2933,7 +2940,7 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x00600000, /* Bit 21 0=Radio, Bit 22 0=TV */ .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, @@ -2950,25 +2957,25 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 1 << 21, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -2983,21 +2990,21 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 1 << 21, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -3012,16 +3019,16 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -3052,17 +3059,17 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0xca60000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 4, .amux = TV, .tv = 1, .gpio = 0x04a61000, },{ - .name = name_comp2, /* Composite SVIDEO (B/W if signal is carried with SVIDEO) */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 1, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 9, /* 9 is correct as S-VIDEO1 according to a169.inf! */ .amux = LINE1, }}, @@ -3086,26 +3093,26 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x00600000, /* Bit 21 0=Radio, Bit 22 0=TV */ .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x200000, /* GPIO21=High for TV input */ .tv = 1, },{ - .name = name_svideo, /* S-Video signal on S-Video input */ + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, },{ - .name = name_comp1, /* Composite signal on S-Video input */ + .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ }, @@ -3121,40 +3128,40 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 0xe000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .gpio = 0x8000, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, .gpio = 0x4000, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, .gpio = 0x4000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x4000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x2000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x8000, }, @@ -3168,16 +3175,16 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -3193,11 +3200,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_comp1, /* Composite input */ + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, /* S-Video signal on S-Video input */ + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -3211,25 +3218,25 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -3244,21 +3251,21 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, }, }, @@ -3272,21 +3279,21 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT| TDA9887_PORT1_ACTIVE | TDA9887_PORT2_ACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, }, }, @@ -3301,25 +3308,25 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x000200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 4, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE2, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -3335,34 +3342,34 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x03, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x00, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, .gpio = 0x00, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, .gpio = 0x00, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x00, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x01, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, .gpio = 0x00, }, @@ -3378,16 +3385,16 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, }}, @@ -3405,22 +3412,22 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x0200100, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x0000100, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200100, }, @@ -3438,22 +3445,22 @@ struct saa7134_board saa7134_boards[] = { .ts_force_val = 1, .gpiomask = 0x0800100, /* GPIO 21 is an INPUT */ .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x0000100, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0800100, /* GPIO 23 HI for FM */ }, @@ -3470,22 +3477,22 @@ struct saa7134_board saa7134_boards[] = { .ts_type = SAA7134_MPEG_TS_SERIAL, .gpiomask = 0x0800100, /* GPIO 21 is an INPUT */ .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x0000100, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0800100, /* GPIO 23 HI for FM */ }, @@ -3499,16 +3506,16 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, }}, @@ -3523,33 +3530,33 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = 3, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 7, .amux = 4, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = 2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 0, .amux = 2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, /* .gpio = 0x00300001,*/ .gpio = 0x20000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = 0, }, }, @@ -3562,32 +3569,32 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = 3, .tv = 1, },{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 7, .amux = 4, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = 2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 0, .amux = 2, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x20000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = 0, }, }, @@ -3600,29 +3607,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x7000, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = 1, .tv = 1, .gpio = 0x50000, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = 2, .gpio = 0x2000, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = 2, .gpio = 0x2000, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .vmux = 1, .amux = 1, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .gpio = 0xf000, .amux = 0, }, @@ -3635,26 +3642,26 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = 0x61, .radio_addr = 0x60, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .vmux = 1, .amux = LINE1, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, .gpio = 0x43000, }, @@ -3668,16 +3675,16 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, }}, @@ -3693,21 +3700,21 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x0200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -3721,16 +3728,16 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 1<<21, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE2, }}, @@ -3746,7 +3753,7 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x0200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, @@ -3764,29 +3771,29 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 1 << 21, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x0000000, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, .gpio = 0x0200000, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE2, .gpio = 0x0200000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x0200000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -3800,26 +3807,26 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 1 << 21, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x0000000, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, }, { - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -3832,25 +3839,25 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, }, }, @@ -3864,24 +3871,24 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x7000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .gpio = 0x0000, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x2000, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x2000, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE2, .gpio = 0x3000, }, @@ -3896,7 +3903,7 @@ struct saa7134_board saa7134_boards[] = { .tda829x_conf = { .lna_cfg = TDA8290_LNA_OFF }, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, /* FIXME: analog tv untested */ + .type = SAA7134_INPUT_TV, /* FIXME: analog tv untested */ .vmux = 1, .amux = TV, .tv = 1, @@ -3912,26 +3919,26 @@ struct saa7134_board saa7134_boards[] = { .tda829x_conf = { .lna_cfg = TDA8290_LNA_GP0_HIGH_OFF }, .gpiomask = 0x020200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x00200000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x01, }, @@ -3946,26 +3953,26 @@ struct saa7134_board saa7134_boards[] = { .tda829x_conf = { .lna_cfg = TDA8290_LNA_OFF }, .gpiomask = 0x020200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x00200000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x01, }, @@ -3981,21 +3988,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x00008000, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -4010,15 +4017,15 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x00008000, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, @@ -4035,21 +4042,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x00008000, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4065,15 +4072,15 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, @@ -4092,21 +4099,21 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4122,17 +4129,17 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0xc0c000, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, .gpio = 0xc0c000, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, @@ -4151,24 +4158,24 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0xc0c000, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, .gpio = 0xc0c000, },{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, .gpio = 0xc0c000, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0xc0c000, }, @@ -4185,16 +4192,16 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, @@ -4211,25 +4218,25 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4246,25 +4253,25 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4280,21 +4287,21 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4311,21 +4318,21 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4342,21 +4349,21 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4372,24 +4379,24 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x000A8004, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, .gpio = 0x000A8004, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, .gpio = 0x000A8000, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x000A8000, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x000A8000, }, @@ -4404,21 +4411,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4432,21 +4439,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4460,21 +4467,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4488,21 +4495,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4517,21 +4524,21 @@ struct saa7134_board saa7134_boards[] = { .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4546,21 +4553,21 @@ struct saa7134_board saa7134_boards[] = { .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4575,21 +4582,21 @@ struct saa7134_board saa7134_boards[] = { .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4604,21 +4611,21 @@ struct saa7134_board saa7134_boards[] = { .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, },{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, },{ - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }}, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -4636,21 +4643,21 @@ struct saa7134_board saa7134_boards[] = { .empress_addr = 0x20, .tda9887_conf = TDA9887_PRESENT, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, .mpeg = SAA7134_MPEG_EMPRESS, @@ -4673,21 +4680,21 @@ struct saa7134_board saa7134_boards[] = { .empress_addr = 0x20, .tda9887_conf = TDA9887_PRESENT, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, .mpeg = SAA7134_MPEG_EMPRESS, @@ -4712,21 +4719,21 @@ struct saa7134_board saa7134_boards[] = { .empress_addr = 0x20, .tda9887_conf = TDA9887_PRESENT, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, .mpeg = SAA7134_MPEG_EMPRESS, @@ -4747,21 +4754,21 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x0200000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, /* untested */ .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -4776,30 +4783,30 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0xf000, .inputs = {{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x2000, .tv = 1 }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x2000, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x1000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE2, .gpio = 0x6000, }, @@ -4813,11 +4820,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, @@ -4832,16 +4839,16 @@ struct saa7134_board saa7134_boards[] = { .tda829x_conf = { .lna_cfg = TDA8290_LNA_OFF }, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, @@ -4857,21 +4864,21 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x0200000, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -4885,21 +4892,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, }, }, @@ -4912,21 +4919,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, }, { - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 0, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, }, }, @@ -4938,16 +4945,16 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, @@ -4962,21 +4969,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, } }, @@ -4990,11 +4997,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = { { - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, } }, @@ -5009,21 +5016,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 4, .amux = TV, .tv = 1, }, { - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, }, }, @@ -5038,21 +5045,21 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -5067,21 +5074,21 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 1 << 21, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 0, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -5097,21 +5104,21 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 1 << 21, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 0, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -5125,29 +5132,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x801a8087, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, .gpio = 0x624000, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, .gpio = 0x624000, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 1, .amux = LINE1, .gpio = 0x624000, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x624001, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, }, }, @@ -5161,16 +5168,16 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .mpeg = SAA7134_MPEG_DVB, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 4, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, @@ -5186,25 +5193,25 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .gpiomask = 0x0200000, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, }, { - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 0, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0200000, }, @@ -5218,30 +5225,30 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = 0x60, .gpiomask = 0x80000700, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, .gpio = 0x100, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x200, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x200, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .vmux = 1, .amux = LINE1, .gpio = 0x100, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .vmux = 8, .amux = 2, }, @@ -5257,18 +5264,18 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .ts_type = SAA7134_MPEG_TS_PARALLEL, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, #if 0 /* FIXME */ }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x200, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x200, @@ -5276,14 +5283,14 @@ struct saa7134_board saa7134_boards[] = { } }, #if 0 .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .vmux = 1, .amux = LINE1, .gpio = 0x100, }, #endif .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .vmux = 0, .amux = TV, }, @@ -5298,24 +5305,24 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 0x00300003, /* .gpiomask = 0x8c240003, */ .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x01, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, .gpio = 0x02, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x00300001, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, .gpio = 0x01, }, @@ -5331,29 +5338,29 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x03, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x00, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x00, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x00, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, .gpio = 0x01, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, .gpio = 0x00, }, @@ -5368,11 +5375,11 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = { { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, /* Not tested */ .amux = LINE1 } }, @@ -5387,21 +5394,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 2, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 9, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, }, }, @@ -5416,13 +5423,13 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .ts_type = SAA7134_MPEG_TS_PARALLEL, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, } }, .radio = { /* untested */ - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, }, }, @@ -5436,16 +5443,16 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, @@ -5459,10 +5466,10 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = { { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, } }, }, @@ -5479,25 +5486,25 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE2, }, }, @@ -5512,7 +5519,7 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x389c00, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x01fc00, @@ -5529,21 +5536,21 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .ts_type = SAA7134_MPEG_TS_PARALLEL, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 2, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 9, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, }, }, @@ -5556,21 +5563,21 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 2, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 9, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, }, }, @@ -5584,16 +5591,16 @@ struct saa7134_board saa7134_boards[] = { .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, @@ -5607,25 +5614,25 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = 0x60, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = TV, }, }, @@ -5642,29 +5649,29 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .ts_type = SAA7134_MPEG_TS_PARALLEL, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, .gpio = 0x00050000, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x00050000, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, .gpio = 0x00050000, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x00050000, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .vmux = 0, .amux = TV, .gpio = 0x00050000, @@ -5681,21 +5688,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x00008000, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -5710,21 +5717,21 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x00008000, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -5736,15 +5743,15 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE1, }, { - .name = name_comp3, + .type = SAA7134_INPUT_COMPOSITE3, .vmux = 2, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, @@ -5760,21 +5767,21 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 1 << 21, .ts_type = SAA7134_MPEG_TS_PARALLEL, .inputs = { { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0000000, }, @@ -5790,7 +5797,7 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x618E700, .inputs = {{ - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x6010000, @@ -5809,21 +5816,21 @@ struct saa7134_board saa7134_boards[] = { .gpiomask = 1 << 11, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, .tv = 1, }, { - .name = name_comp, + .type = SAA7134_INPUT_COMPOSITE, .vmux = 4, .amux = LINE1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE1, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = TV, .gpio = 0x0000800, }, @@ -5837,16 +5844,16 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_GO7007, .inputs = { { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, }, { - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, .tv = 1, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 6, .amux = LINE1, } }, @@ -5862,25 +5869,25 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ - .name = name_tv, + .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, .amux = LINE2, }, { - .name = name_comp2, + .type = SAA7134_INPUT_COMPOSITE2, .vmux = 3, .amux = LINE2, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, } }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, }, }, @@ -5893,29 +5900,29 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 0x0d, .inputs = {{ - .name = name_tv_mono, + .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE1, .gpio = 0x00, .tv = 1, }, { - .name = name_comp1, + .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE2, .gpio = 0x08, }, { - .name = name_svideo, + .type = SAA7134_INPUT_SVIDEO, .vmux = 8, .amux = LINE2, .gpio = 0x08, } }, .radio = { - .name = name_radio, + .type = SAA7134_INPUT_RADIO, .amux = LINE1, .gpio = 0x04, }, .mute = { - .name = name_mute, + .type = SAA7134_INPUT_MUTE, .amux = LINE1, .gpio = 0x08, }, diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c index e227b02cc122..31048f9b516a 100644 --- a/drivers/media/pci/saa7134/saa7134-core.c +++ b/drivers/media/pci/saa7134/saa7134-core.c @@ -112,7 +112,7 @@ int (*saa7134_dmasound_exit)(struct saa7134_dev *dev); printk(KERN_DEBUG pr_fmt("irq: " fmt), ## arg); \ } while (0) -void saa7134_track_gpio(struct saa7134_dev *dev, char *msg) +void saa7134_track_gpio(struct saa7134_dev *dev, const char *msg) { unsigned long mode,status; diff --git a/drivers/media/pci/saa7134/saa7134-tvaudio.c b/drivers/media/pci/saa7134/saa7134-tvaudio.c index 21a579309575..38f94b742e28 100644 --- a/drivers/media/pci/saa7134/saa7134-tvaudio.c +++ b/drivers/media/pci/saa7134/saa7134-tvaudio.c @@ -192,7 +192,7 @@ static void mute_input_7134(struct saa7134_dev *dev) in = dev->input; mute = (dev->ctl_mute || (dev->automute && (&card(dev).radio) != in)); - if (card(dev).mute.name) { + if (card(dev).mute.type) { /* * 7130 - we'll mute using some unconnected audio input * 7134 - we'll probably should switch external mux with gpio @@ -204,13 +204,14 @@ static void mute_input_7134(struct saa7134_dev *dev) if (dev->hw_mute == mute && dev->hw_input == in && !dev->insuspend) { audio_dbg(1, "mute/input: nothing to do [mute=%d,input=%s]\n", - mute, in->name); + mute, saa7134_input_name[in->type]); return; } audio_dbg(1, "ctl_mute=%d automute=%d input=%s => mute=%d input=%s\n", dev->ctl_mute, dev->automute, - dev->input->name, mute, in->name); + saa7134_input_name[dev->input->type], mute, + saa7134_input_name[in->type]); dev->hw_mute = mute; dev->hw_input = in; @@ -245,7 +246,7 @@ static void mute_input_7134(struct saa7134_dev *dev) mask = card(dev).gpiomask; saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio); - saa7134_track_gpio(dev,in->name); + saa7134_track_gpio(dev, saa7134_input_name[in->type]); } static void tvaudio_setmode(struct saa7134_dev *dev, @@ -756,14 +757,14 @@ static int mute_input_7133(struct saa7134_dev *dev) if (0 != card(dev).gpiomask) { mask = card(dev).gpiomask; - if (card(dev).mute.name && dev->ctl_mute) + if (card(dev).mute.type && dev->ctl_mute) in = &card(dev).mute; else in = dev->input; saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio); - saa7134_track_gpio(dev,in->name); + saa7134_track_gpio(dev, saa7134_input_name[in->type]); } return 0; diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 7a42d3ae3ac9..ae52ef019e43 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -409,7 +409,8 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) static void video_mux(struct saa7134_dev *dev, int input) { - video_dbg("video input = %d [%s]\n", input, card_in(dev, input).name); + video_dbg("video input = %d [%s]\n", + input, saa7134_input_name[card_in(dev, input).type]); dev->ctl_input = input; set_tvnorm(dev, dev->tvnorm); saa7134_tvaudio_setinput(dev, &card_in(dev, input)); @@ -1381,11 +1382,11 @@ int saa7134_enum_input(struct file *file, void *priv, struct v4l2_input *i) n = i->index; if (n >= SAA7134_INPUT_MAX) return -EINVAL; - if (NULL == card_in(dev, i->index).name) + if (card_in(dev, i->index).type == SAA7134_NO_INPUT) return -EINVAL; i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(i->name, card_in(dev, n).name); + strcpy(i->name, saa7134_input_name[card_in(dev, n).type]); if (card_in(dev, n).tv) i->type = V4L2_INPUT_TYPE_TUNER; if (n == dev->ctl_input) { @@ -1419,7 +1420,7 @@ int saa7134_s_input(struct file *file, void *priv, unsigned int i) if (i >= SAA7134_INPUT_MAX) return -EINVAL; - if (NULL == card_in(dev, i).name) + if (card_in(dev, i).type == SAA7134_NO_INPUT) return -EINVAL; video_mux(dev, i); return 0; @@ -1661,7 +1662,7 @@ int saa7134_g_tuner(struct file *file, void *priv, } if (n == SAA7134_INPUT_MAX) return -EINVAL; - if (NULL != card_in(dev, n).name) { + if (card_in(dev, n).type != SAA7134_NO_INPUT) { strcpy(t->name, "Television"); t->type = V4L2_TUNER_ANALOG_TV; saa_call_all(dev, tuner, g_tuner, t); diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index 5938bc781999..274a472e7d6b 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -361,12 +361,30 @@ struct saa7134_card_ir { #define SET_CLOCK_INVERTED (1 << 2) #define SET_VSYNC_OFF (1 << 3) +enum saa7134_input_types { + SAA7134_NO_INPUT = 0, + SAA7134_INPUT_MUTE, + SAA7134_INPUT_RADIO, + SAA7134_INPUT_TV, + SAA7134_INPUT_TV_MONO, + SAA7134_INPUT_COMPOSITE, + SAA7134_INPUT_COMPOSITE0, + SAA7134_INPUT_COMPOSITE1, + SAA7134_INPUT_COMPOSITE2, + SAA7134_INPUT_COMPOSITE3, + SAA7134_INPUT_COMPOSITE4, + SAA7134_INPUT_SVIDEO, + SAA7134_INPUT_SVIDEO0, + SAA7134_INPUT_SVIDEO1, + SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, +}; + struct saa7134_input { - char *name; - unsigned int vmux; - enum saa7134_audio_in amux; - unsigned int gpio; - unsigned int tv:1; + enum saa7134_input_types type; + unsigned int vmux; + enum saa7134_audio_in amux; + unsigned int gpio; + unsigned int tv:1; }; enum saa7134_mpeg_type { @@ -410,7 +428,7 @@ struct saa7134_board { unsigned int ts_force_val:1; }; -#define card_has_radio(dev) (NULL != saa7134_boards[dev->board].radio.name) +#define card_has_radio(dev) (SAA7134_NO_INPUT != saa7134_boards[dev->board].radio.type) #define card_is_empress(dev) (SAA7134_MPEG_EMPRESS == saa7134_boards[dev->board].mpeg) #define card_is_dvb(dev) (SAA7134_MPEG_DVB == saa7134_boards[dev->board].mpeg) #define card_is_go7007(dev) (SAA7134_MPEG_GO7007 == saa7134_boards[dev->board].mpeg) @@ -727,7 +745,7 @@ extern struct mutex saa7134_devlist_lock; extern int saa7134_no_overlay; extern bool saa7134_userptr; -void saa7134_track_gpio(struct saa7134_dev *dev, char *msg); +void saa7134_track_gpio(struct saa7134_dev *dev, const char *msg); void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value); #define SAA7134_PGTABLE_SIZE 4096 @@ -760,6 +778,7 @@ extern int (*saa7134_dmasound_exit)(struct saa7134_dev *dev); /* saa7134-cards.c */ extern struct saa7134_board saa7134_boards[]; +extern const char * const saa7134_input_name[]; extern const unsigned int saa7134_bcount; extern struct pci_device_id saa7134_pci_tbl[]; -- cgit v1.2.3 From 568b2febeeb139879efe93756aa58e2e42559f90 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 11:14:05 -0200 Subject: [media] saa7134: unconditionlally update TV standard at demod It doesn't make any sense to only update the TV standard for TV, as composite and S-Video inputs also need it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-video.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index ae52ef019e43..59781755247a 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -479,8 +479,7 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev) { saa7134_set_decoder(dev); - if (card_in(dev, dev->ctl_input).tv) - saa_call_all(dev, video, s_std, dev->tvnorm->id); + saa_call_all(dev, video, s_std, dev->tvnorm->id); /* Set the correct norm for the saa6752hs. This function does nothing if there is no saa6752hs. */ saa_call_empress(dev, video, s_std, dev->tvnorm->id); -- cgit v1.2.3 From 8bf77f9e7013e46ca08151189357532f027c47e8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 10:37:18 -0200 Subject: [media] saa7134: Get rid of struct saa7134_input.tv field The saa7134_input.tv field was used to indicate if an input had a RF signal for TV input. This is not needed anymore, as the input type can be checked directly by the driver. Also, due to a past bug when setting the TV standard at the demod, all inputs should have this field set, with is wrong. This reduces the size of the saa7134_boards by about 8KB, on i386 (and probably twice on 64 bits), with is a nice colateral effect: text data bss dec hex filename 241047 136831 66356 444234 6c74a drivers/media/pci/saa7134/saa7134.o.old 240851 128895 66292 436038 6a746 drivers/media/pci/saa7134/saa7134.o Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-cards.c | 194 ------------------------------ drivers/media/pci/saa7134/saa7134-video.c | 13 +- drivers/media/pci/saa7134/saa7134.h | 1 - 3 files changed, 10 insertions(+), 198 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c index 19975cec5da7..9a2fdc78eb85 100644 --- a/drivers/media/pci/saa7134/saa7134-cards.c +++ b/drivers/media/pci/saa7134/saa7134-cards.c @@ -97,12 +97,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, }}, .radio = { .type = SAA7134_INPUT_RADIO, @@ -124,13 +122,11 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x8000, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -173,7 +169,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = LINE2, .gpio = 0x0000, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -214,7 +209,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, @@ -245,13 +239,11 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x10000, /* GP16=1 selects TV input */ - .tv = 1, },{ /* .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, - .tv = 1, },{ */ .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, @@ -295,13 +287,11 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x8000, - .tv = 1, }, { .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -351,7 +341,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, }}, .radio = { .type = SAA7134_INPUT_RADIO, @@ -373,7 +362,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -399,13 +387,11 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ /* workaround for problems with normal TV sound */ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -441,12 +427,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_SVIDEO, @@ -481,7 +465,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x20000, },{ .type = SAA7134_INPUT_SVIDEO, @@ -513,7 +496,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE, .vmux = 4, @@ -540,13 +522,11 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ /* workaround for problems with normal TV sound */ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -584,7 +564,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, }}, }, [SAA7134_BOARD_CINERGY600] = { @@ -599,7 +578,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, @@ -631,7 +609,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -664,7 +641,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -698,7 +674,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 4, .amux = LINE2, - .tv = 1, }}, }, [SAA7134_BOARD_ELSA_500TV] = { @@ -716,12 +691,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 8, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 8, .amux = LINE2, - .tv = 1, }}, }, [SAA7134_BOARD_ELSA_700TV] = { @@ -735,7 +708,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 4, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 6, @@ -762,7 +734,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, @@ -790,7 +761,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x0000, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, @@ -832,7 +802,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, }}, }, [SAA7134_BOARD_10MOONSTVMASTER] = { @@ -849,7 +818,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = LINE2, .gpio = 0x0000, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -929,7 +897,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, }}, }, [SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS] = { @@ -955,7 +922,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = LINE2, .gpio = 0x08c20012, - .tv = 1, }}, /* radio and probably mute is missing */ }, [SAA7134_BOARD_CRONOS_PLUS] = { @@ -1008,7 +974,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x00, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -1058,7 +1023,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }}, .mpeg = SAA7134_MPEG_EMPRESS, .video_out = CCIR656, @@ -1077,7 +1041,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, @@ -1105,7 +1068,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -1140,7 +1102,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }}, .radio = { .type = SAA7134_INPUT_RADIO, @@ -1167,7 +1128,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }}, .mute = { .type = SAA7134_INPUT_MUTE, @@ -1186,7 +1146,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -1208,12 +1167,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -1243,12 +1200,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -1279,12 +1234,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -1315,12 +1268,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -1369,7 +1320,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, } }, }, [SAA7134_BOARD_NOVAC_PRIMETV7133] = { @@ -1387,7 +1337,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_SVIDEO, .vmux = 8, @@ -1405,7 +1354,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -1441,7 +1389,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -1476,7 +1423,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 7, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_SVIDEO, .vmux = 7, @@ -1495,7 +1441,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -1521,7 +1466,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, @@ -1563,7 +1507,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2_LEFT, - .tv = 1, .gpio = 0x00080, }}, .radio = { @@ -1593,7 +1536,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_SVIDEO, .vmux = 8, @@ -1624,7 +1566,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, }}, }, [SAA7134_BOARD_EMPIRE_PCI_TV_RADIO_LE] = { @@ -1641,7 +1582,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = LINE2, .gpio = 0x8000, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -1681,7 +1621,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x00, },{ .type = SAA7134_INPUT_COMPOSITE, @@ -1718,7 +1657,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x01, },{ .type = SAA7134_INPUT_COMPOSITE1, @@ -1754,7 +1692,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -1783,7 +1720,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x08000000, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -1814,12 +1750,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -1843,7 +1777,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, @@ -1885,7 +1818,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x008080, }}, .radio = { @@ -1912,7 +1844,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -1944,12 +1875,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, }}, .radio = { .type = SAA7134_INPUT_RADIO, @@ -1970,7 +1899,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -2005,7 +1933,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x200000, /* GPIO21=High for TV input */ - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, @@ -2058,7 +1985,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -2084,7 +2010,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -2107,7 +2032,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x000, },{ .type = SAA7134_INPUT_COMPOSITE1, @@ -2145,7 +2069,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x200000, /* GPIO21=High for TV input */ - .tv = 1, },{ .type = SAA7134_INPUT_SVIDEO, .vmux = 8, @@ -2187,7 +2110,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x800000, }}, .radio = { @@ -2222,7 +2144,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x000, },{ .type = SAA7134_INPUT_COMPOSITE1, @@ -2257,12 +2178,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -2296,7 +2215,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x0000000, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -2331,7 +2249,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x01, },{ .type = SAA7134_INPUT_COMPOSITE1, @@ -2371,7 +2288,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -2401,7 +2317,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x00200003, },{ .type = SAA7134_INPUT_TV_MONO, @@ -2443,7 +2358,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -2467,7 +2381,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -2582,7 +2495,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, .vmux = 0, @@ -2632,7 +2544,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -2655,7 +2566,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 4, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -2688,7 +2598,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x0000000, },{ .type = SAA7134_INPUT_COMPOSITE1, @@ -2727,7 +2636,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -2755,7 +2663,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -2780,7 +2687,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -2808,7 +2714,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, @@ -2844,7 +2749,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_SVIDEO, /* NOT tested */ .vmux = 8, @@ -2872,7 +2776,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x200000, /* GPIO21=High for TV input */ - .tv = 1, },{ .type = SAA7134_INPUT_SVIDEO, .vmux = 8, @@ -2943,7 +2846,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x00200000, }}, }, @@ -2960,7 +2862,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -2993,7 +2894,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3022,7 +2922,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3062,7 +2961,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 4, .amux = TV, - .tv = 1, .gpio = 0x04a61000, },{ .type = SAA7134_INPUT_COMPOSITE_OVER_SVIDEO, @@ -3097,7 +2995,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x200000, /* GPIO21=High for TV input */ - .tv = 1, },{ .type = SAA7134_INPUT_SVIDEO, .vmux = 8, @@ -3132,13 +3029,11 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x8000, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 1, .amux = LINE2, .gpio = 0x0000, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -3178,7 +3073,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -3221,7 +3115,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -3254,7 +3147,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3282,7 +3174,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, @@ -3311,7 +3202,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 4, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -3345,7 +3235,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x00, },{ .type = SAA7134_INPUT_COMPOSITE1, @@ -3388,7 +3277,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -3415,7 +3303,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x0000100, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -3448,7 +3335,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x0000100, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -3480,7 +3366,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x0000100, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -3509,7 +3394,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -3533,12 +3417,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = 3, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 7, .amux = 4, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3572,12 +3454,10 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = 3, - .tv = 1, },{ .type = SAA7134_INPUT_TV_MONO, .vmux = 7, .amux = 4, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3610,7 +3490,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = 1, - .tv = 1, .gpio = 0x50000, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -3645,7 +3524,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3678,7 +3556,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -3703,7 +3580,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3731,7 +3607,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -3756,7 +3631,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x0200000, }}, }, @@ -3774,7 +3648,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x0000000, },{ .type = SAA7134_INPUT_COMPOSITE1, @@ -3810,7 +3683,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x0000000, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -3842,7 +3714,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3875,7 +3746,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = LINE2, .gpio = 0x0000, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3906,7 +3776,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, /* FIXME: analog tv untested */ .vmux = 1, .amux = TV, - .tv = 1, }}, }, [SAA7134_BOARD_AVERMEDIA_M135A] = { @@ -3922,7 +3791,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3956,7 +3824,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -3999,7 +3866,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }}, .mute = { .type = SAA7134_INPUT_MUTE, @@ -4028,7 +3894,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }}, }, [SAA7134_BOARD_BEHOLD_403FM] = { @@ -4053,7 +3918,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }}, .radio = { .type = SAA7134_INPUT_RADIO, @@ -4083,7 +3947,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }}, }, [SAA7134_BOARD_BEHOLD_405FM] = { @@ -4110,7 +3973,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }}, .radio = { .type = SAA7134_INPUT_RADIO, @@ -4142,7 +4004,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, .gpio = 0xc0c000, }}, }, @@ -4171,7 +4032,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, .gpio = 0xc0c000, }}, .radio = { @@ -4195,7 +4055,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4221,7 +4080,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4256,7 +4114,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4290,7 +4147,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4321,7 +4177,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4352,7 +4207,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4382,7 +4236,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, .gpio = 0x000A8004, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -4414,7 +4267,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4442,7 +4294,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4470,7 +4321,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4498,7 +4348,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4527,7 +4376,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4556,7 +4404,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4585,7 +4432,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4614,7 +4460,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, },{ .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4646,7 +4491,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4683,7 +4527,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4722,7 +4565,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -4757,7 +4599,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -4787,13 +4628,11 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = LINE2, .gpio = 0x0000, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, .amux = LINE1, .gpio = 0x2000, - .tv = 1 }, { .type = SAA7134_INPUT_SVIDEO, .vmux = 8, @@ -4842,7 +4681,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -4867,7 +4705,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -4895,7 +4732,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -4922,7 +4758,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_SVIDEO, .vmux = 8, @@ -4948,7 +4783,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -4972,7 +4806,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -5019,7 +4852,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 4, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE, .vmux = 1, @@ -5048,7 +4880,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -5077,7 +4908,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE, .vmux = 0, @@ -5107,7 +4937,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE, .vmux = 0, @@ -5135,7 +4964,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, .gpio = 0x624000, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -5171,7 +4999,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE, .vmux = 4, @@ -5196,7 +5023,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -5228,7 +5054,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, .gpio = 0x100, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -5267,7 +5092,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, #if 0 /* FIXME */ }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -5308,7 +5132,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x01, }, { .type = SAA7134_INPUT_SVIDEO, @@ -5341,7 +5164,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x00, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -5397,7 +5219,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 2, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -5426,7 +5247,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, } }, .radio = { /* untested */ .type = SAA7134_INPUT_RADIO, @@ -5446,7 +5266,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 4, @@ -5489,7 +5308,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -5539,7 +5357,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 2, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -5566,7 +5383,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 2, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -5594,7 +5410,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -5617,7 +5432,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, @@ -5652,7 +5466,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, .gpio = 0x00050000, }, { .type = SAA7134_INPUT_COMPOSITE1, @@ -5691,7 +5504,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -5720,7 +5532,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = LINE2, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 1, @@ -5770,7 +5581,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE, .vmux = 3, @@ -5819,7 +5629,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE, .vmux = 4, @@ -5851,7 +5660,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 3, .amux = TV, - .tv = 1, }, { .type = SAA7134_INPUT_SVIDEO, .vmux = 6, @@ -5872,7 +5680,6 @@ struct saa7134_board saa7134_boards[] = { .type = SAA7134_INPUT_TV, .vmux = 1, .amux = LINE2, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 0, @@ -5904,7 +5711,6 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = LINE1, .gpio = 0x00, - .tv = 1, }, { .type = SAA7134_INPUT_COMPOSITE1, .vmux = 3, diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 59781755247a..9debfb549887 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1384,10 +1384,16 @@ int saa7134_enum_input(struct file *file, void *priv, struct v4l2_input *i) if (card_in(dev, i->index).type == SAA7134_NO_INPUT) return -EINVAL; i->index = n; - i->type = V4L2_INPUT_TYPE_CAMERA; strcpy(i->name, saa7134_input_name[card_in(dev, n).type]); - if (card_in(dev, n).tv) + switch (card_in(dev, n).type) { + case SAA7134_INPUT_TV: + case SAA7134_INPUT_TV_MONO: i->type = V4L2_INPUT_TYPE_TUNER; + break; + default: + i->type = V4L2_INPUT_TYPE_CAMERA; + break; + } if (n == dev->ctl_input) { int v1 = saa_readb(SAA7134_STATUS_VIDEO1); int v2 = saa_readb(SAA7134_STATUS_VIDEO2); @@ -1656,7 +1662,8 @@ int saa7134_g_tuner(struct file *file, void *priv, return -EINVAL; memset(t, 0, sizeof(*t)); for (n = 0; n < SAA7134_INPUT_MAX; n++) { - if (card_in(dev, n).tv) + if (card_in(dev, n).type == SAA7134_INPUT_TV || + card_in(dev, n).type == SAA7134_INPUT_TV_MONO) break; } if (n == SAA7134_INPUT_MAX) diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index 274a472e7d6b..e3e2392f87d6 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -384,7 +384,6 @@ struct saa7134_input { unsigned int vmux; enum saa7134_audio_in amux; unsigned int gpio; - unsigned int tv:1; }; enum saa7134_mpeg_type { -- cgit v1.2.3 From 7047f2982a223e0ecca480c11a37bd9edf62b65a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 13:16:18 -0200 Subject: [media] v4l2-mc: add an ancillary routine for PCI-based MC Instead of copyping the same code on all PCI devices that would have a media controller, add a core ancillary routine. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-mc.c | 35 +++++++++++++++++++++++++++++++++++ include/media/v4l2-mc.h | 24 +++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index e6d2a711bb0b..b6cf6dbd4cd5 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -15,9 +15,44 @@ */ #include +#include #include #include + +struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, + char *name) +{ +#ifdef CONFIG_PCI + struct media_device *mdev; + + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return NULL; + + mdev->dev = &pci_dev->dev; + + if (name) + strlcpy(mdev->model, name, sizeof(mdev->model)); + else + strlcpy(mdev->model, pci_name(pci_dev), sizeof(mdev->model)); + + sprintf(mdev->bus_info, "PCI:%s", pci_name(pci_dev)); + + mdev->hw_revision = pci_dev->subsystem_vendor << 16 + || pci_dev->subsystem_device; + + mdev->driver_version = LINUX_VERSION_CODE; + + media_device_init(mdev); + + return mdev; +#else + return NULL; +#endif +} +EXPORT_SYMBOL_GPL(v4l2_mc_pci_media_device_init); + int v4l2_mc_create_media_graph(struct media_device *mdev) { diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index aed9e9b87f82..6fad97277a0b 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -92,6 +92,10 @@ enum demod_pad_index { DEMOD_NUM_PADS }; + +struct pci_dev; /* We don't need to include pci.h here */ + +#ifdef CONFIG_MEDIA_CONTROLLER /** * v4l2_mc_create_media_graph() - create Media Controller links at the graph. * @@ -106,11 +110,29 @@ enum demod_pad_index { * interface centric PC-consumer's hardware, V4L2 subdev centric camera * hardware should not use this routine, as it will not build the right graph. */ -#ifdef CONFIG_MEDIA_CONTROLLER int v4l2_mc_create_media_graph(struct media_device *mdev); + +/** + * v4l2_mc_pci_media_device_init() - create and initialize a + * struct &media_device from a PCI device. + * + * @pci_dev: pointer to struct pci_dev + * @name: media device name. If %NULL, the routine will use the default + * name for the pci device, given by pci_name() macro. + */ +struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, + char *name); + + #else static inline int v4l2_mc_create_media_graph(struct media_device *mdev) { return 0; } + +struct media_device *v4l2_mc_pci_media_device_init(struct pci_dev *pci_dev, + char *name) { + return NULL; +} + #endif -- cgit v1.2.3 From ac90aa02d5b9a9bde6bcd9ac3ee181a4d212d355 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Feb 2016 08:33:04 -0200 Subject: [media] saa7134: add media controller support Register saa7134 at the media controller core and provide support for both analog TV and DVB. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-core.c | 191 +++++++++++++++++++++++++++++- drivers/media/pci/saa7134/saa7134-dvb.c | 9 +- drivers/media/pci/saa7134/saa7134-video.c | 60 ++++++++++ drivers/media/pci/saa7134/saa7134.h | 13 ++ 4 files changed, 268 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c index 31048f9b516a..42bc4172febd 100644 --- a/drivers/media/pci/saa7134/saa7134-core.c +++ b/drivers/media/pci/saa7134/saa7134-core.c @@ -806,6 +806,153 @@ static void must_configure_manually(int has_eeprom) } } +static void saa7134_unregister_media_device(struct saa7134_dev *dev) +{ + +#ifdef CONFIG_MEDIA_CONTROLLER + if (!dev->media_dev) + return; + media_device_unregister(dev->media_dev); + media_device_cleanup(dev->media_dev); + kfree(dev->media_dev); + dev->media_dev = NULL; +#endif +} + +static void saa7134_media_release(struct saa7134_dev *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + int i; + + for (i = 0; i < SAA7134_INPUT_MAX + 1; i++) + media_device_unregister_entity(&dev->input_ent[i]); +#endif +} + +static void saa7134_create_entities(struct saa7134_dev *dev) +{ +#if defined(CONFIG_MEDIA_CONTROLLER) + int ret, i; + struct media_entity *entity; + struct media_entity *decoder = NULL; + + /* Check if it is using an external analog TV demod */ + media_device_for_each_entity(entity, dev->media_dev) { + if (entity->function == MEDIA_ENT_F_ATV_DECODER) + decoder = entity; + break; + } + + /* + * saa713x is not using an external ATV demod. + * Register the internal one + */ + if (!decoder) { + dev->demod.name = "saa713x"; + dev->demod_pad[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + dev->demod_pad[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; + dev->demod_pad[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; + dev->demod.function = MEDIA_ENT_F_ATV_DECODER; + + ret = media_entity_pads_init(&dev->demod, DEMOD_NUM_PADS, + dev->demod_pad); + if (ret < 0) + pr_err("failed to initialize demod pad!\n"); + + ret = media_device_register_entity(dev->media_dev, &dev->demod); + if (ret < 0) + pr_err("failed to register demod entity!\n"); + + dev->decoder = &dev->demod; + } else { + dev->decoder = decoder; + } + + /* Initialize Video, VBI and Radio pads */ + dev->video_pad.flags = MEDIA_PAD_FL_SINK; + ret = media_entity_pads_init(&dev->video_dev->entity, 1, + &dev->video_pad); + if (ret < 0) + pr_err("failed to initialize video media entity!\n"); + + dev->vbi_pad.flags = MEDIA_PAD_FL_SINK; + ret = media_entity_pads_init(&dev->vbi_dev->entity, 1, + &dev->vbi_pad); + if (ret < 0) + pr_err("failed to initialize vbi media entity!\n"); + + /* Create entities for each input connector */ + for (i = 0; i < SAA7134_INPUT_MAX; i++) { + struct media_entity *ent = &dev->input_ent[i]; + struct saa7134_input *in = &card_in(dev, i); + + if (in->type == SAA7134_NO_INPUT) + break; + + /* This input uses the S-Video connector */ + if (in->type == SAA7134_INPUT_COMPOSITE_OVER_SVIDEO) + continue; + + ent->name = saa7134_input_name[in->type]; + ent->flags = MEDIA_ENT_FL_CONNECTOR; + dev->input_pad[i].flags = MEDIA_PAD_FL_SOURCE; + + switch (in->type) { + case SAA7134_INPUT_COMPOSITE: + case SAA7134_INPUT_COMPOSITE0: + case SAA7134_INPUT_COMPOSITE1: + case SAA7134_INPUT_COMPOSITE2: + case SAA7134_INPUT_COMPOSITE3: + case SAA7134_INPUT_COMPOSITE4: + ent->function = MEDIA_ENT_F_CONN_COMPOSITE; + break; + case SAA7134_INPUT_SVIDEO: + case SAA7134_INPUT_SVIDEO0: + case SAA7134_INPUT_SVIDEO1: + ent->function = MEDIA_ENT_F_CONN_SVIDEO; + break; + default: + /* + * SAA7134_INPUT_TV and SAA7134_INPUT_TV_MONO. + * + * Please notice that neither SAA7134_INPUT_MUTE or + * SAA7134_INPUT_RADIO are defined at + * saa7134_board.input. + */ + ent->function = MEDIA_ENT_F_CONN_RF; + break; + } + + ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]); + if (ret < 0) + pr_err("failed to initialize input pad[%d]!\n", i); + + ret = media_device_register_entity(dev->media_dev, ent); + if (ret < 0) + pr_err("failed to register input entity %d!\n", i); + } + + /* Create input for Radio RF connector */ + if (card_has_radio(dev)) { + struct saa7134_input *in = &saa7134_boards[dev->board].radio; + struct media_entity *ent = &dev->input_ent[i]; + + ent->name = saa7134_input_name[in->type]; + ent->flags = MEDIA_ENT_FL_CONNECTOR; + dev->input_pad[i].flags = MEDIA_PAD_FL_SOURCE; + ent->function = MEDIA_ENT_F_CONN_RF; + + ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]); + if (ret < 0) + pr_err("failed to initialize input pad[%d]!\n", i); + + ret = media_device_register_entity(dev->media_dev, ent); + if (ret < 0) + pr_err("failed to register input entity %d!\n", i); + } +#endif +} + static struct video_device *vdev_init(struct saa7134_dev *dev, struct video_device *template, char *type) @@ -826,6 +973,8 @@ static struct video_device *vdev_init(struct saa7134_dev *dev, static void saa7134_unregister_video(struct saa7134_dev *dev) { + saa7134_media_release(dev); + if (dev->video_dev) { if (video_is_registered(dev->video_dev)) video_unregister_device(dev->video_dev); @@ -889,6 +1038,18 @@ static int saa7134_initdev(struct pci_dev *pci_dev, if (NULL == dev) return -ENOMEM; + dev->nr = saa7134_devcount; + sprintf(dev->name, "saa%x[%d]", pci_dev->device, dev->nr); + +#ifdef CONFIG_MEDIA_CONTROLLER + dev->media_dev = v4l2_mc_pci_media_device_init(pci_dev, dev->name); + if (!dev->media_dev) { + err = -ENOMEM; + goto fail0; + } + dev->v4l2_dev.mdev = dev->media_dev; +#endif + err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev); if (err) goto fail0; @@ -900,9 +1061,6 @@ static int saa7134_initdev(struct pci_dev *pci_dev, goto fail1; } - dev->nr = saa7134_devcount; - sprintf(dev->name,"saa%x[%d]",pci_dev->device,dev->nr); - /* pci quirks */ if (pci_pci_problems) { if (pci_pci_problems & PCIPCI_TRITON) @@ -1102,6 +1260,15 @@ static int saa7134_initdev(struct pci_dev *pci_dev, dev->name, video_device_node_name(dev->radio_dev)); } +#ifdef CONFIG_MEDIA_CONTROLLER + saa7134_create_entities(dev); + + err = v4l2_mc_create_media_graph(dev->media_dev); + if (err) { + pr_err("failed to create media graph\n"); + goto fail5; + } +#endif /* everything worked */ saa7134_devcount++; @@ -1109,6 +1276,18 @@ static int saa7134_initdev(struct pci_dev *pci_dev, saa7134_dmasound_init(dev); request_submodules(dev); + + /* + * Do it at the end, to reduce dynamic configuration changes during + * the device init. Yet, as request_modules() can be async, the + * topology will likely change after load the saa7134 subdrivers. + */ +#ifdef CONFIG_MEDIA_CONTROLLER + err = media_device_register(dev->media_dev); + if (err) + goto fail5; +#endif + return 0; fail5: @@ -1126,6 +1305,9 @@ static int saa7134_initdev(struct pci_dev *pci_dev, fail1: v4l2_device_unregister(&dev->v4l2_dev); fail0: +#ifdef CONFIG_MEDIA_CONTROLLER + kfree(dev->media_dev); +#endif kfree(dev); return err; } @@ -1188,9 +1370,10 @@ static void saa7134_finidev(struct pci_dev *pci_dev) release_mem_region(pci_resource_start(pci_dev,0), pci_resource_len(pci_dev,0)); - v4l2_device_unregister(&dev->v4l2_dev); + saa7134_unregister_media_device(dev); + /* free memory */ kfree(dev); } diff --git a/drivers/media/pci/saa7134/saa7134-dvb.c b/drivers/media/pci/saa7134/saa7134-dvb.c index ed84f7dea94c..db987e5b93eb 100644 --- a/drivers/media/pci/saa7134/saa7134-dvb.c +++ b/drivers/media/pci/saa7134/saa7134-dvb.c @@ -1883,8 +1883,15 @@ static int dvb_init(struct saa7134_dev *dev) fe0->dvb.frontend->callback = saa7134_tuner_callback; /* register everything else */ +#ifndef CONFIG_MEDIA_CONTROLLER_DVB ret = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, - &dev->pci->dev, NULL, adapter_nr, 0); + &dev->pci->dev, NULL, + adapter_nr, 0); +#else + ret = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, + &dev->pci->dev, dev->media_dev, + adapter_nr, 0); +#endif /* this sequence is necessary to make the tda1004x load its firmware * and to enter analog mode of hybrid boards diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 9debfb549887..0403b34624c1 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -785,6 +785,63 @@ static int stop_preview(struct saa7134_dev *dev) return 0; } +/* + * Media Controller helper functions + */ + +static int saa7134_enable_analog_tuner(struct saa7134_dev *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *mdev = dev->media_dev; + struct media_entity *source; + struct media_link *link, *found_link = NULL; + int ret, active_links = 0; + + if (!mdev || !dev->decoder) + return 0; + + /* + * This will find the tuner that is connected into the decoder. + * Technically, this is not 100% correct, as the device may be + * using an analog input instead of the tuner. However, as we can't + * do DVB streaming while the DMA engine is being used for V4L2, + * this should be enough for the actual needs. + */ + list_for_each_entry(link, &dev->decoder->links, list) { + if (link->sink->entity == dev->decoder) { + found_link = link; + if (link->flags & MEDIA_LNK_FL_ENABLED) + active_links++; + break; + } + } + + if (active_links == 1 || !found_link) + return 0; + + source = found_link->source->entity; + list_for_each_entry(link, &source->links, list) { + struct media_entity *sink; + int flags = 0; + + sink = link->sink->entity; + + if (sink == dev->decoder) + flags = MEDIA_LNK_FL_ENABLED; + + ret = media_entity_setup_link(link, flags); + if (ret) { + pr_err("Couldn't change link %s->%s to %s. Error %d\n", + source->name, sink->name, + flags ? "enabled" : "disabled", + ret); + return ret; + } + } +#endif + return 0; +} + /* ------------------------------------------------------------------ */ static int buffer_activate(struct saa7134_dev *dev, @@ -924,6 +981,9 @@ static int queue_setup(struct vb2_queue *q, *nplanes = 1; sizes[0] = size; alloc_ctxs[0] = dev->alloc_ctx; + + saa7134_enable_analog_tuner(dev); + return 0; } diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index e3e2392f87d6..8936568fab94 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -671,6 +671,19 @@ struct saa7134_dev { /* I2C keyboard data */ struct IR_i2c_init_data init_data; +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *media_dev; + + struct media_entity input_ent[SAA7134_INPUT_MAX + 1]; + struct media_pad input_pad[SAA7134_INPUT_MAX + 1]; + + struct media_entity demod; + struct media_pad demod_pad[DEMOD_NUM_PADS]; + + struct media_pad video_pad, vbi_pad; + struct media_entity *decoder; +#endif + #if IS_ENABLED(CONFIG_VIDEO_SAA7134_DVB) /* SAA7134_MPEG_DVB only */ struct vb2_dvb_frontends frontends; -- cgit v1.2.3 From 9bf4f005672073f6bae2edf84e6cb5c4fb16ffc6 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Tue, 9 Feb 2016 18:29:25 -0600 Subject: EDAC: Use edac_debugfs_remove_recursive() in edac_debugfs_exit() debugfs_remove() is used to remove a file or a directory from the debugfs filesystem on an EDAC device exit. However edac_debugfs might not be empty. This is similar to 30f84a891bf6 ("EDAC: Use edac_debugfs_remove_recursive()") which changed the EDAC MCI code to use edac_debugfs_remove_recursive(). Suggested-by: Borislav Petkov Signed-off-by: Thor Thayer Cc: linux-edac Link: http://lkml.kernel.org/r/1455064165-3816-1-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- drivers/edac/debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/debugfs.c b/drivers/edac/debugfs.c index 54d2f668cb0a..92dbb7e2320c 100644 --- a/drivers/edac/debugfs.c +++ b/drivers/edac/debugfs.c @@ -53,7 +53,7 @@ int __init edac_debugfs_init(void) void edac_debugfs_exit(void) { - debugfs_remove(edac_debugfs); + debugfs_remove_recursive(edac_debugfs); } int edac_create_debugfs_nodes(struct mem_ctl_info *mci) -- cgit v1.2.3 From d2f79f223f931dfadf98c42a9d426999d5e3397c Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Sun, 17 Jan 2016 15:12:23 +0100 Subject: reset: ath79: Make reset_control_ops const The ath79_reset_ops structure is never modified. Make it const. Signed-off-by: Philipp Zabel Acked-by: Alban Bedel --- drivers/reset/reset-ath79.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/reset/reset-ath79.c b/drivers/reset/reset-ath79.c index 692fc890e94b..ccb940a8d9fb 100644 --- a/drivers/reset/reset-ath79.c +++ b/drivers/reset/reset-ath79.c @@ -70,7 +70,7 @@ static int ath79_reset_status(struct reset_controller_dev *rcdev, return !!(val & BIT(id)); } -static struct reset_control_ops ath79_reset_ops = { +static const struct reset_control_ops ath79_reset_ops = { .assert = ath79_reset_assert, .deassert = ath79_reset_deassert, .status = ath79_reset_status, -- cgit v1.2.3 From 0e18e60e1bded4b3c8c0eb29ac297ff7336ba5c7 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Sun, 17 Jan 2016 15:11:59 +0100 Subject: reset: hi6220: Make reset_control_ops const The hi6220_reset_ops structure is never modified. Make it const. Signed-off-by: Philipp Zabel --- drivers/reset/hisilicon/hi6220_reset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/reset/hisilicon/hi6220_reset.c b/drivers/reset/hisilicon/hi6220_reset.c index 744b2e796442..8f55fd4a2630 100644 --- a/drivers/reset/hisilicon/hi6220_reset.c +++ b/drivers/reset/hisilicon/hi6220_reset.c @@ -57,7 +57,7 @@ static int hi6220_reset_deassert(struct reset_controller_dev *rc_dev, return 0; } -static struct reset_control_ops hi6220_reset_ops = { +static const struct reset_control_ops hi6220_reset_ops = { .assert = hi6220_reset_assert, .deassert = hi6220_reset_deassert, }; -- cgit v1.2.3 From 387eb3f3d574ebf43b3afe83da59a99481866b78 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Sun, 17 Jan 2016 15:13:41 +0100 Subject: reset: socfpga: Make reset_control_ops const The socfpga_reset_ops structure is never modified. Make it const. Signed-off-by: Philipp Zabel --- drivers/reset/reset-socfpga.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c index b7d773d9248c..cd05a7032b17 100644 --- a/drivers/reset/reset-socfpga.c +++ b/drivers/reset/reset-socfpga.c @@ -90,7 +90,7 @@ static int socfpga_reset_status(struct reset_controller_dev *rcdev, return !(reg & BIT(offset)); } -static struct reset_control_ops socfpga_reset_ops = { +static const struct reset_control_ops socfpga_reset_ops = { .assert = socfpga_reset_assert, .deassert = socfpga_reset_deassert, .status = socfpga_reset_status, -- cgit v1.2.3 From 356d108f8780b58a6aa966e17d64f332f1917730 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Sun, 17 Jan 2016 15:14:52 +0100 Subject: reset: zynq: Make reset_control_ops const The zynq_reset_ops structure is never modified. Make it const. Signed-off-by: Philipp Zabel --- drivers/reset/reset-zynq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/reset/reset-zynq.c b/drivers/reset/reset-zynq.c index c6b3cd8b40ad..a7e87bc45885 100644 --- a/drivers/reset/reset-zynq.c +++ b/drivers/reset/reset-zynq.c @@ -86,7 +86,7 @@ static int zynq_reset_status(struct reset_controller_dev *rcdev, return !!(reg & BIT(offset)); } -static struct reset_control_ops zynq_reset_ops = { +static const struct reset_control_ops zynq_reset_ops = { .assert = zynq_reset_assert, .deassert = zynq_reset_deassert, .status = zynq_reset_status, -- cgit v1.2.3 From f673ed4d5fdc123b1552525de30741cd8dfde53f Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Sun, 17 Jan 2016 15:15:13 +0100 Subject: reset: sti: Make reset_control_ops const The syscfg_reset_ops structure is never modified. Make it const. Signed-off-by: Philipp Zabel --- drivers/reset/sti/reset-syscfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/reset/sti/reset-syscfg.c b/drivers/reset/sti/reset-syscfg.c index 1600cc7557f5..9bd57a5eee72 100644 --- a/drivers/reset/sti/reset-syscfg.c +++ b/drivers/reset/sti/reset-syscfg.c @@ -134,7 +134,7 @@ static int syscfg_reset_status(struct reset_controller_dev *rcdev, return rst->active_low ? !ret_val : !!ret_val; } -static struct reset_control_ops syscfg_reset_ops = { +static const struct reset_control_ops syscfg_reset_ops = { .reset = syscfg_reset_dev, .assert = syscfg_reset_assert, .deassert = syscfg_reset_deassert, -- cgit v1.2.3 From aac7e974ebbd2b8c3ce2d9874ca6a60ce0528281 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 31 Jan 2016 22:32:51 +0900 Subject: pinctrl: uniphier: add COMPILE_TEST option Add COMPILE_TEST for the compilation test coverage. Signed-off-by: Masahiro Yamada Signed-off-by: Linus Walleij --- drivers/pinctrl/uniphier/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/uniphier/Kconfig b/drivers/pinctrl/uniphier/Kconfig index 7abd614dc383..43f689ff446b 100644 --- a/drivers/pinctrl/uniphier/Kconfig +++ b/drivers/pinctrl/uniphier/Kconfig @@ -1,6 +1,6 @@ menuconfig PINCTRL_UNIPHIER bool "UniPhier SoC pinctrl drivers" - depends on ARCH_UNIPHIER + depends on ARCH_UNIPHIER || COMPILE_TEST depends on OF && MFD_SYSCON default y select PINMUX -- cgit v1.2.3 From 310a7e60435151ccab6dc4bc64b4b3a93b89c0d1 Mon Sep 17 00:00:00 2001 From: Keerthy Date: Thu, 28 Jan 2016 19:08:50 +0530 Subject: gpio: davinci: Add the missing of-node pointer Currently the first parameter of irq_domain_add_legacy is NULL. irq_find_host function returns NULL when we do not populate the of_node and hence irq_of_parse_and_map call fails whenever we want to request a gpio irq. This fixes the request_irq failures for gpio interrupts. Signed-off-by: Keerthy Reviewed-by: Grygorii Strashko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-davinci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index ec58f4288649..c889f3166205 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -511,7 +511,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) return irq; } - irq_domain = irq_domain_add_legacy(NULL, ngpio, irq, 0, + irq_domain = irq_domain_add_legacy(dev->of_node, ngpio, irq, 0, &davinci_gpio_irq_ops, chips); if (!irq_domain) { -- cgit v1.2.3 From 6ec9249a83b00a754af435ed57ad02ffed105d93 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Thu, 28 Jan 2016 19:08:51 +0530 Subject: gpio: davinci: Fix the number of controllers allocated Driver only needs to allocate for [ngpio / 32] controllers, as each controller handles 32 gpios. But the current driver allocates for ngpio of which the extra allocated are unused. Fix it be registering only the required number of controllers. Signed-off-by: Lokesh Vutla Signed-off-by: Keerthy Reviewed-by: Grygorii Strashko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-davinci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index c889f3166205..cd007a67b302 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -195,7 +195,7 @@ static int davinci_gpio_of_xlate(struct gpio_chip *gc, static int davinci_gpio_probe(struct platform_device *pdev) { int i, base; - unsigned ngpio; + unsigned ngpio, nbank; struct davinci_gpio_controller *chips; struct davinci_gpio_platform_data *pdata; struct davinci_gpio_regs __iomem *regs; @@ -224,8 +224,9 @@ static int davinci_gpio_probe(struct platform_device *pdev) if (WARN_ON(ARCH_NR_GPIOS < ngpio)) ngpio = ARCH_NR_GPIOS; + nbank = DIV_ROUND_UP(ngpio, 32); chips = devm_kzalloc(dev, - ngpio * sizeof(struct davinci_gpio_controller), + nbank * sizeof(struct davinci_gpio_controller), GFP_KERNEL); if (!chips) return -ENOMEM; -- cgit v1.2.3 From 82e92f4cad6e0c42f8dbe7497b39dec7b3eb7b11 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 9 Feb 2016 13:46:05 -0200 Subject: [media] au0828: only create V4L2 graph if V4L2 is registered It doesn't make sense to try to create the analog TV graph, if the device fails to register at V4L2, or if it doesn't have V4L2 support. Thanks to Shuah for pointing this issue. Reported-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-core.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index df2bc3f732b6..0a8afbf181c9 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -419,8 +419,21 @@ static int au0828_usb_probe(struct usb_interface *interface, #ifdef CONFIG_VIDEO_AU0828_V4L2 /* Analog TV */ - if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) - au0828_analog_register(dev, interface); + if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) { + retval = au0828_analog_register(dev, interface); + if (retval) { + pr_err("%s() au0282_dev_register failed to register on V4L2\n", + __func__); + goto done; + } + + retval = au0828_create_media_graph(dev); + if (retval) { + pr_err("%s() au0282_dev_register failed to create graph\n", + __func__); + goto done; + } + } #endif /* Digital TV */ @@ -443,13 +456,6 @@ static int au0828_usb_probe(struct usb_interface *interface, mutex_unlock(&dev->lock); - retval = au0828_create_media_graph(dev); - if (retval) { - pr_err("%s() au0282_dev_register failed to create graph\n", - __func__); - goto done; - } - #ifdef CONFIG_MEDIA_CONTROLLER retval = media_device_register(dev->media_dev); #endif -- cgit v1.2.3 From ab32770ec8d64254503d85128ba05de41d792ff2 Mon Sep 17 00:00:00 2001 From: Alban Bedel Date: Thu, 28 Jan 2016 20:44:29 +0100 Subject: gpio: ath79: Move to the generic GPIO driver Drop most of the code in favor of the generic MMIO GPIO driver. As the driver now depend on CONFIG_GPIO_GENERIC also add a Kconfig entry to make the driver optional. We leave the base pointer and lock in the data struct because they are needed for the IRQ support. Signed-off-by: Alban Bedel Acked-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 9 ++++ drivers/gpio/Makefile | 2 +- drivers/gpio/gpio-ath79.c | 126 ++++++---------------------------------------- 3 files changed, 24 insertions(+), 113 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 77df86635480..020a44a52331 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -126,6 +126,15 @@ config GPIO_AMDPT driver for GPIO functionality on Promontory IOHub Require ACPI ASL code to enumerate as a platform device. +config GPIO_ATH79 + tristate "Atheros AR71XX/AR724X/AR913X GPIO support" + default y if ATH79 + depends on ATH79 + select GPIO_GENERIC + help + Select this option to enable GPIO driver for + Atheros AR71XX/AR724X/AR913X SoC devices. + config GPIO_BCM_KONA bool "Broadcom Kona GPIO" depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST) diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 2f5852daab0d..30ff7de0f6d5 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -24,7 +24,7 @@ obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o -obj-$(CONFIG_ATH79) += gpio-ath79.o +obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index d13dd133a907..13d96480a3b2 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -19,115 +19,11 @@ #include struct ath79_gpio_ctrl { - struct gpio_chip chip; + struct gpio_chip gc; void __iomem *base; spinlock_t lock; }; -static void ath79_gpio_set_value(struct gpio_chip *chip, - unsigned gpio, int value) -{ - struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip); - - if (value) - __raw_writel(BIT(gpio), ctrl->base + AR71XX_GPIO_REG_SET); - else - __raw_writel(BIT(gpio), ctrl->base + AR71XX_GPIO_REG_CLEAR); -} - -static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned gpio) -{ - struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip); - - return (__raw_readl(ctrl->base + AR71XX_GPIO_REG_IN) >> gpio) & 1; -} - -static int ath79_gpio_direction_input(struct gpio_chip *chip, - unsigned offset) -{ - struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip); - unsigned long flags; - - spin_lock_irqsave(&ctrl->lock, flags); - - __raw_writel( - __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & ~BIT(offset), - ctrl->base + AR71XX_GPIO_REG_OE); - - spin_unlock_irqrestore(&ctrl->lock, flags); - - return 0; -} - -static int ath79_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip); - unsigned long flags; - - spin_lock_irqsave(&ctrl->lock, flags); - - if (value) - __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_SET); - else - __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_CLEAR); - - __raw_writel( - __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) | BIT(offset), - ctrl->base + AR71XX_GPIO_REG_OE); - - spin_unlock_irqrestore(&ctrl->lock, flags); - - return 0; -} - -static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip); - unsigned long flags; - - spin_lock_irqsave(&ctrl->lock, flags); - - __raw_writel( - __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) | BIT(offset), - ctrl->base + AR71XX_GPIO_REG_OE); - - spin_unlock_irqrestore(&ctrl->lock, flags); - - return 0; -} - -static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset, - int value) -{ - struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip); - unsigned long flags; - - spin_lock_irqsave(&ctrl->lock, flags); - - if (value) - __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_SET); - else - __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_CLEAR); - - __raw_writel( - __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & ~BIT(offset), - ctrl->base + AR71XX_GPIO_REG_OE); - - spin_unlock_irqrestore(&ctrl->lock, flags); - - return 0; -} - -static const struct gpio_chip ath79_gpio_chip = { - .label = "ath79", - .get = ath79_gpio_get_value, - .set = ath79_gpio_set_value, - .direction_input = ath79_gpio_direction_input, - .direction_output = ath79_gpio_direction_output, - .base = 0, -}; - static const struct of_device_id ath79_gpio_of_match[] = { { .compatible = "qca,ar7100-gpio" }, { .compatible = "qca,ar9340-gpio" }, @@ -174,15 +70,21 @@ static int ath79_gpio_probe(struct platform_device *pdev) return -ENOMEM; spin_lock_init(&ctrl->lock); - memcpy(&ctrl->chip, &ath79_gpio_chip, sizeof(ctrl->chip)); - ctrl->chip.parent = &pdev->dev; - ctrl->chip.ngpio = ath79_gpio_count; - if (oe_inverted) { - ctrl->chip.direction_input = ar934x_gpio_direction_input; - ctrl->chip.direction_output = ar934x_gpio_direction_output; + err = bgpio_init(&ctrl->gc, &pdev->dev, 4, + ctrl->base + AR71XX_GPIO_REG_IN, + ctrl->base + AR71XX_GPIO_REG_SET, + ctrl->base + AR71XX_GPIO_REG_CLEAR, + oe_inverted ? NULL : ctrl->base + AR71XX_GPIO_REG_OE, + oe_inverted ? ctrl->base + AR71XX_GPIO_REG_OE : NULL, + 0); + if (err) { + dev_err(&pdev->dev, "bgpio_init failed\n"); + return err; } + /* Use base 0 to stay compatible with legacy platforms */ + ctrl->gc.base = 0; - err = gpiochip_add_data(&ctrl->chip, ctrl); + err = gpiochip_add_data(&ctrl->gc, ctrl); if (err) { dev_err(&pdev->dev, "cannot add AR71xx GPIO chip, error=%d", err); -- cgit v1.2.3 From 409d87838d5755b471933fb2a43f2dfc514ccd2d Mon Sep 17 00:00:00 2001 From: Alban Bedel Date: Thu, 28 Jan 2016 20:44:30 +0100 Subject: gpio: ath79: Allow building in compile tests To allow building the driver in compile tests we must drop the dependency on asm/mach-ath79/ar71xx_regs.h. For this we replace the include with local definition of the registers needed for this driver. Signed-off-by: Alban Bedel Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-ath79.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 020a44a52331..3c1bb917dd72 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -129,7 +129,7 @@ config GPIO_AMDPT config GPIO_ATH79 tristate "Atheros AR71XX/AR724X/AR913X GPIO support" default y if ATH79 - depends on ATH79 + depends on ATH79 || COMPILE_TEST select GPIO_GENERIC help Select this option to enable GPIO driver for diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index 13d96480a3b2..afb535eef9f3 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -16,7 +16,10 @@ #include #include -#include +#define AR71XX_GPIO_REG_OE 0x00 +#define AR71XX_GPIO_REG_IN 0x04 +#define AR71XX_GPIO_REG_SET 0x0c +#define AR71XX_GPIO_REG_CLEAR 0x10 struct ath79_gpio_ctrl { struct gpio_chip gc; -- cgit v1.2.3 From 2f890cf0dfe421ecd2095d8cabb89e7207b499ee Mon Sep 17 00:00:00 2001 From: Alban Bedel Date: Thu, 28 Jan 2016 20:44:31 +0100 Subject: gpio: ath79: Make the driver removable As we now allow the driver to be built as a module it should be removable. Signed-off-by: Alban Bedel Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ath79.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index afb535eef9f3..6b157925e16e 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -46,6 +46,7 @@ static int ath79_gpio_probe(struct platform_device *pdev) ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL); if (!ctrl) return -ENOMEM; + platform_set_drvdata(pdev, ctrl); if (np) { err = of_property_read_u32(np, "ngpios", &ath79_gpio_count); @@ -97,12 +98,21 @@ static int ath79_gpio_probe(struct platform_device *pdev) return 0; } +static int ath79_gpio_remove(struct platform_device *pdev) +{ + struct ath79_gpio_ctrl *ctrl = platform_get_drvdata(pdev); + + gpiochip_remove(&ctrl->gc); + return 0; +} + static struct platform_driver ath79_gpio_driver = { .driver = { .name = "ath79-gpio", .of_match_table = ath79_gpio_of_match, }, .probe = ath79_gpio_probe, + .remove = ath79_gpio_remove, }; module_platform_driver(ath79_gpio_driver); -- cgit v1.2.3 From 2b8f89e19b6d83d97019358328cbed22bbb0505e Mon Sep 17 00:00:00 2001 From: Alban Bedel Date: Thu, 28 Jan 2016 20:44:32 +0100 Subject: gpio: ath79: Add support for the interrupt controller Add support for the interrupt controller using GPIOLIB_IRQCHIP. Both edges isn't supported by the chip and has to be emulated by switching the polarity on each interrupt. Signed-off-by: Alban Bedel Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-ath79.c | 205 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3c1bb917dd72..f52b25964bc6 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -131,6 +131,7 @@ config GPIO_ATH79 default y if ATH79 depends on ATH79 || COMPILE_TEST select GPIO_GENERIC + select GPIOLIB_IRQCHIP help Select this option to enable GPIO driver for Atheros AR71XX/AR724X/AR913X SoC devices. diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index 6b157925e16e..0d94c0bd764a 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -15,18 +15,205 @@ #include #include #include +#include +#include #define AR71XX_GPIO_REG_OE 0x00 #define AR71XX_GPIO_REG_IN 0x04 #define AR71XX_GPIO_REG_SET 0x0c #define AR71XX_GPIO_REG_CLEAR 0x10 +#define AR71XX_GPIO_REG_INT_ENABLE 0x14 +#define AR71XX_GPIO_REG_INT_TYPE 0x18 +#define AR71XX_GPIO_REG_INT_POLARITY 0x1c +#define AR71XX_GPIO_REG_INT_PENDING 0x20 +#define AR71XX_GPIO_REG_INT_MASK 0x24 + struct ath79_gpio_ctrl { struct gpio_chip gc; void __iomem *base; spinlock_t lock; + unsigned long both_edges; +}; + +static struct ath79_gpio_ctrl *irq_data_to_ath79_gpio(struct irq_data *data) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + + return container_of(gc, struct ath79_gpio_ctrl, gc); +} + +static u32 ath79_gpio_read(struct ath79_gpio_ctrl *ctrl, unsigned reg) +{ + return readl(ctrl->base + reg); +} + +static void ath79_gpio_write(struct ath79_gpio_ctrl *ctrl, + unsigned reg, u32 val) +{ + return writel(val, ctrl->base + reg); +} + +static bool ath79_gpio_update_bits( + struct ath79_gpio_ctrl *ctrl, unsigned reg, u32 mask, u32 bits) +{ + u32 old_val, new_val; + + old_val = ath79_gpio_read(ctrl, reg); + new_val = (old_val & ~mask) | (bits & mask); + + if (new_val != old_val) + ath79_gpio_write(ctrl, reg, new_val); + + return new_val != old_val; +} + +static void ath79_gpio_irq_unmask(struct irq_data *data) +{ + struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data); + u32 mask = BIT(irqd_to_hwirq(data)); + unsigned long flags; + + spin_lock_irqsave(&ctrl->lock, flags); + ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask); + spin_unlock_irqrestore(&ctrl->lock, flags); +} + +static void ath79_gpio_irq_mask(struct irq_data *data) +{ + struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data); + u32 mask = BIT(irqd_to_hwirq(data)); + unsigned long flags; + + spin_lock_irqsave(&ctrl->lock, flags); + ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0); + spin_unlock_irqrestore(&ctrl->lock, flags); +} + +static void ath79_gpio_irq_enable(struct irq_data *data) +{ + struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data); + u32 mask = BIT(irqd_to_hwirq(data)); + unsigned long flags; + + spin_lock_irqsave(&ctrl->lock, flags); + ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask); + ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask); + spin_unlock_irqrestore(&ctrl->lock, flags); +} + +static void ath79_gpio_irq_disable(struct irq_data *data) +{ + struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data); + u32 mask = BIT(irqd_to_hwirq(data)); + unsigned long flags; + + spin_lock_irqsave(&ctrl->lock, flags); + ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0); + ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, 0); + spin_unlock_irqrestore(&ctrl->lock, flags); +} + +static int ath79_gpio_irq_set_type(struct irq_data *data, + unsigned int flow_type) +{ + struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data); + u32 mask = BIT(irqd_to_hwirq(data)); + u32 type = 0, polarity = 0; + unsigned long flags; + bool disabled; + + switch (flow_type) { + case IRQ_TYPE_EDGE_RISING: + polarity |= mask; + case IRQ_TYPE_EDGE_FALLING: + case IRQ_TYPE_EDGE_BOTH: + break; + + case IRQ_TYPE_LEVEL_HIGH: + polarity |= mask; + case IRQ_TYPE_LEVEL_LOW: + type |= mask; + break; + + default: + return -EINVAL; + } + + spin_lock_irqsave(&ctrl->lock, flags); + + if (flow_type == IRQ_TYPE_EDGE_BOTH) { + ctrl->both_edges |= mask; + polarity = ~ath79_gpio_read(ctrl, AR71XX_GPIO_REG_IN); + } else { + ctrl->both_edges &= ~mask; + } + + /* As the IRQ configuration can't be loaded atomically we + * have to disable the interrupt while the configuration state + * is invalid. + */ + disabled = ath79_gpio_update_bits( + ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, 0); + + ath79_gpio_update_bits( + ctrl, AR71XX_GPIO_REG_INT_TYPE, mask, type); + ath79_gpio_update_bits( + ctrl, AR71XX_GPIO_REG_INT_POLARITY, mask, polarity); + + if (disabled) + ath79_gpio_update_bits( + ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask); + + spin_unlock_irqrestore(&ctrl->lock, flags); + + return 0; +} + +static struct irq_chip ath79_gpio_irqchip = { + .name = "gpio-ath79", + .irq_enable = ath79_gpio_irq_enable, + .irq_disable = ath79_gpio_irq_disable, + .irq_mask = ath79_gpio_irq_mask, + .irq_unmask = ath79_gpio_irq_unmask, + .irq_set_type = ath79_gpio_irq_set_type, }; +static void ath79_gpio_irq_handler(struct irq_desc *desc) +{ + struct gpio_chip *gc = irq_desc_get_handler_data(desc); + struct irq_chip *irqchip = irq_desc_get_chip(desc); + struct ath79_gpio_ctrl *ctrl = + container_of(gc, struct ath79_gpio_ctrl, gc); + unsigned long flags, pending; + u32 both_edges, state; + int irq; + + chained_irq_enter(irqchip, desc); + + spin_lock_irqsave(&ctrl->lock, flags); + + pending = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_INT_PENDING); + + /* Update the polarity of the both edges irqs */ + both_edges = ctrl->both_edges & pending; + if (both_edges) { + state = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_IN); + ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_POLARITY, + both_edges, ~state); + } + + spin_unlock_irqrestore(&ctrl->lock, flags); + + if (pending) { + for_each_set_bit(irq, &pending, gc->ngpio) + generic_handle_irq( + irq_linear_revmap(gc->irqdomain, irq)); + } + + chained_irq_exit(irqchip, desc); +} + static const struct of_device_id ath79_gpio_of_match[] = { { .compatible = "qca,ar7100-gpio" }, { .compatible = "qca,ar9340-gpio" }, @@ -95,7 +282,25 @@ static int ath79_gpio_probe(struct platform_device *pdev) return err; } + if (np && !of_property_read_bool(np, "interrupt-controller")) + return 0; + + err = gpiochip_irqchip_add(&ctrl->gc, &ath79_gpio_irqchip, 0, + handle_simple_irq, IRQ_TYPE_NONE); + if (err) { + dev_err(&pdev->dev, "failed to add gpiochip_irqchip\n"); + goto gpiochip_remove; + } + + gpiochip_set_chained_irqchip(&ctrl->gc, &ath79_gpio_irqchip, + platform_get_irq(pdev, 0), + ath79_gpio_irq_handler); + return 0; + +gpiochip_remove: + gpiochip_remove(&ctrl->gc); + return err; } static int ath79_gpio_remove(struct platform_device *pdev) -- cgit v1.2.3 From bfb61abfc860c5a64be6be7f7277655d4d36a129 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Tue, 9 Feb 2016 13:55:04 +0100 Subject: HID: lg: fix a typo in descriptors comments s/Joystik/Joystick/ Signed-off-by: Antonio Ospite Signed-off-by: Jiri Kosina --- drivers/hid/hid-lg.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index c690fae02cf8..feb2be71f77c 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -61,7 +61,7 @@ */ static __u8 df_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ -0x09, 0x04, /* Usage (Joystik), */ +0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x02, /* Collection (Logical), */ 0x95, 0x01, /* Report Count (1), */ @@ -127,7 +127,7 @@ static __u8 df_rdesc_fixed[] = { static __u8 dfp_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ -0x09, 0x04, /* Usage (Joystik), */ +0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x02, /* Collection (Logical), */ 0x95, 0x01, /* Report Count (1), */ @@ -175,7 +175,7 @@ static __u8 dfp_rdesc_fixed[] = { static __u8 fv_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ -0x09, 0x04, /* Usage (Joystik), */ +0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x02, /* Collection (Logical), */ 0x95, 0x01, /* Report Count (1), */ @@ -242,7 +242,7 @@ static __u8 fv_rdesc_fixed[] = { static __u8 momo_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ -0x09, 0x04, /* Usage (Joystik), */ +0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x02, /* Collection (Logical), */ 0x95, 0x01, /* Report Count (1), */ @@ -288,7 +288,7 @@ static __u8 momo_rdesc_fixed[] = { static __u8 momo2_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ -0x09, 0x04, /* Usage (Joystik), */ +0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x02, /* Collection (Logical), */ 0x95, 0x01, /* Report Count (1), */ -- cgit v1.2.3 From 09593e3888a9b041f9f9a728a56893915e2fbeda Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Tue, 9 Feb 2016 13:55:06 +0100 Subject: HID: sony: fix errors from scripts/checkpatch.pl ./scripts/checkpatch.pl \ --types "SPACING,TRAILING_WHITESPACE,POINTER_LOCATION,CODE_INDENT" \ -f drivers/hid/hid-sony.c ERROR: trailing whitespace #933: FILE: drivers/hid/hid-sony.c:933: +^I * $ ERROR: space prohibited after that open square bracket '[' #947: FILE: drivers/hid/hid-sony.c:947: + [ 1] = BTN_TRIGGER_HAPPY1, ERROR: space prohibited after that open square bracket '[' #948: FILE: drivers/hid/hid-sony.c:948: + [ 2] = BTN_TRIGGER_HAPPY2, ERROR: space prohibited after that open square bracket '[' #949: FILE: drivers/hid/hid-sony.c:949: + [ 3] = BTN_TRIGGER_HAPPY3, ERROR: space prohibited after that open square bracket '[' #950: FILE: drivers/hid/hid-sony.c:950: + [ 4] = BTN_TRIGGER_HAPPY4, ERROR: space prohibited after that open square bracket '[' #951: FILE: drivers/hid/hid-sony.c:951: + [ 5] = BTN_TRIGGER_HAPPY5, ERROR: space prohibited after that open square bracket '[' #952: FILE: drivers/hid/hid-sony.c:952: + [ 6] = BTN_TRIGGER_HAPPY6, ERROR: space prohibited after that open square bracket '[' #953: FILE: drivers/hid/hid-sony.c:953: + [ 7] = BTN_TRIGGER_HAPPY7, ERROR: space prohibited after that open square bracket '[' #954: FILE: drivers/hid/hid-sony.c:954: + [ 8] = BTN_TRIGGER_HAPPY8, ERROR: space prohibited after that open square bracket '[' #955: FILE: drivers/hid/hid-sony.c:955: + [ 9] = BTN_TRIGGER_HAPPY9, ERROR: "(foo*)" should be "(foo *)" #1032: FILE: drivers/hid/hid-sony.c:1032: + void(*send_output_report)(struct sony_sc*); WARNING: missing space after return type #1032: FILE: drivers/hid/hid-sony.c:1032: + void(*send_output_report)(struct sony_sc*); ERROR: "(foo*)" should be "(foo *)" #2261: FILE: drivers/hid/hid-sony.c:2261: + void(*send_output_report)(struct sony_sc*)) WARNING: missing space after return type #2261: FILE: drivers/hid/hid-sony.c:2261: + void(*send_output_report)(struct sony_sc*)) ERROR: code indent should use tabs where possible #2449: FILE: drivers/hid/hid-sony.c:2449: + */$ total: 13 errors, 2 warnings, 2570 lines checked Signed-off-by: Antonio Ospite Acked-by: Frank Praznik Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 173af01ca080..c71dbe0fe526 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -930,7 +930,7 @@ static const unsigned int buzz_keymap[] = { /* * The controller has 4 remote buzzers, each with one LED and 5 * buttons. - * + * * We use the mapping chosen by the controller, which is: * * Key Offset @@ -944,15 +944,15 @@ static const unsigned int buzz_keymap[] = { * So, for example, the orange button on the third buzzer is mapped to * BTN_TRIGGER_HAPPY14 */ - [ 1] = BTN_TRIGGER_HAPPY1, - [ 2] = BTN_TRIGGER_HAPPY2, - [ 3] = BTN_TRIGGER_HAPPY3, - [ 4] = BTN_TRIGGER_HAPPY4, - [ 5] = BTN_TRIGGER_HAPPY5, - [ 6] = BTN_TRIGGER_HAPPY6, - [ 7] = BTN_TRIGGER_HAPPY7, - [ 8] = BTN_TRIGGER_HAPPY8, - [ 9] = BTN_TRIGGER_HAPPY9, + [1] = BTN_TRIGGER_HAPPY1, + [2] = BTN_TRIGGER_HAPPY2, + [3] = BTN_TRIGGER_HAPPY3, + [4] = BTN_TRIGGER_HAPPY4, + [5] = BTN_TRIGGER_HAPPY5, + [6] = BTN_TRIGGER_HAPPY6, + [7] = BTN_TRIGGER_HAPPY7, + [8] = BTN_TRIGGER_HAPPY8, + [9] = BTN_TRIGGER_HAPPY9, [10] = BTN_TRIGGER_HAPPY10, [11] = BTN_TRIGGER_HAPPY11, [12] = BTN_TRIGGER_HAPPY12, @@ -1029,7 +1029,7 @@ struct sony_sc { struct led_classdev *leds[MAX_LEDS]; unsigned long quirks; struct work_struct state_worker; - void(*send_output_report)(struct sony_sc*); + void (*send_output_report)(struct sony_sc *); struct power_supply *battery; struct power_supply_desc battery_desc; int device_id; @@ -2259,7 +2259,7 @@ static void sony_release_device_id(struct sony_sc *sc) } static inline void sony_init_output_report(struct sony_sc *sc, - void(*send_output_report)(struct sony_sc*)) + void (*send_output_report)(struct sony_sc *)) { sc->send_output_report = send_output_report; @@ -2447,7 +2447,7 @@ static int sony_suspend(struct hid_device *hdev, pm_message_t message) /* * On suspend save the current LED state, * stop running force-feedback and blank the LEDS. - */ + */ if (SONY_LED_SUPPORT || SONY_FF_SUPPORT) { struct sony_sc *sc = hid_get_drvdata(hdev); -- cgit v1.2.3 From ef916ef5ef75fe0206b2c0cfcd696b32aa1ea872 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Tue, 9 Feb 2016 13:55:07 +0100 Subject: HID: sony: fix some warnings from scripts/checkpatch.pl WARNING: Block comments use a trailing */ on a separate line #822: FILE: drivers/hid/hid-sony.c:822: + * number but it's not needed for correct operation */ WARNING: Block comments use a trailing */ on a separate line #828: FILE: drivers/hid/hid-sony.c:828: + * buttons multiple keypresses are allowed */ WARNING: Block comments use a trailing */ on a separate line #854: FILE: drivers/hid/hid-sony.c:854: + * 0xff and 11th is for press indication */ WARNING: Missing a blank line after declarations #1930: FILE: drivers/hid/hid-sony.c:1930: + struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); + sc->send_output_report(sc); WARNING: Block comments use a trailing */ on a separate line #2510: FILE: drivers/hid/hid-sony.c:2510: + * Logitech joystick from the device descriptor. */ Signed-off-by: Antonio Ospite Acked-by: Frank Praznik Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index c71dbe0fe526..145579666f18 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -818,14 +818,18 @@ static __u8 ps3remote_rdesc[] = { /* Use collection 1 for joypad buttons */ 0xA1, 0x02, /* MCollection Logical (interrelated data) */ - /* Ignore the 1st byte, maybe it is used for a controller - * number but it's not needed for correct operation */ + /* + * Ignore the 1st byte, maybe it is used for a controller + * number but it's not needed for correct operation + */ 0x75, 0x08, /* GReportSize 0x08 [8] */ 0x95, 0x01, /* GReportCount 0x01 [1] */ 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ - /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these - * buttons multiple keypresses are allowed */ + /* + * Bytes from 2nd to 4th are a bitmap for joypad buttons, for these + * buttons multiple keypresses are allowed + */ 0x05, 0x09, /* GUsagePage Button */ 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */ 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */ @@ -850,8 +854,10 @@ static __u8 ps3remote_rdesc[] = { 0x95, 0x01, /* GReportCount 0x01 [1] */ 0x80, /* MInput */ - /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at - * 0xff and 11th is for press indication */ + /* + * Ignore bytes from 6th to 11th, 6th to 10th are always constant at + * 0xff and 11th is for press indication + */ 0x75, 0x08, /* GReportSize 0x08 [8] */ 0x95, 0x06, /* GReportCount 0x06 [6] */ 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ @@ -1928,6 +1934,7 @@ static inline void sony_send_output_report(struct sony_sc *sc) static void sony_state_worker(struct work_struct *work) { struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); + sc->send_output_report(sc); } @@ -2507,8 +2514,10 @@ static const struct hid_device_id sony_devices[] = { .driver_data = VAIO_RDESC_CONSTANT }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE), .driver_data = VAIO_RDESC_CONSTANT }, - /* Wired Buzz Controller. Reported as Sony Hub from its USB ID and as - * Logitech joystick from the device descriptor. */ + /* + * Wired Buzz Controller. Reported as Sony Hub from its USB ID and as + * Logitech joystick from the device descriptor. + */ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER), .driver_data = BUZZ_CONTROLLER }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER), -- cgit v1.2.3 From 1adf904e90059a5b577dbf49b57c27da29b1e69e Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 9 Feb 2016 13:55:08 +0100 Subject: HID: sony: underscores are unnecessary for u8, u16, s32 Double-underscore prefixed types are unnecessary in pure kernel code, replace them with the non prefixed equivalents. Signed-off-by: Pavel Machek Signed-off-by: Antonio Ospite Acked-by: Frank Praznik Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 114 ++++++++++++++++++++++++------------------------- 1 file changed, 57 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 145579666f18..ccf7ef2d0b5e 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -75,7 +75,7 @@ * axis values. Additionally, the controller only has 20 actual, physical axes * so there are several unused axes in between the used ones. */ -static __u8 sixaxis_rdesc[] = { +static u8 sixaxis_rdesc[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ @@ -153,7 +153,7 @@ static __u8 sixaxis_rdesc[] = { }; /* PS/3 Motion controller */ -static __u8 motion_rdesc[] = { +static u8 motion_rdesc[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ @@ -250,7 +250,7 @@ static __u8 motion_rdesc[] = { }; /* PS/3 Navigation controller */ -static __u8 navigation_rdesc[] = { +static u8 navigation_rdesc[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x04, /* Usage (Joystik), */ 0xA1, 0x01, /* Collection (Application), */ @@ -810,7 +810,7 @@ static u8 dualshock4_bt_rdesc[] = { 0xC0 /* End Collection */ }; -static __u8 ps3remote_rdesc[] = { +static u8 ps3remote_rdesc[] = { 0x05, 0x01, /* GUsagePage Generic Desktop */ 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */ @@ -980,33 +980,33 @@ static enum power_supply_property sony_battery_props[] = { }; struct sixaxis_led { - __u8 time_enabled; /* the total time the led is active (0xff means forever) */ - __u8 duty_length; /* how long a cycle is in deciseconds (0 means "really fast") */ - __u8 enabled; - __u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */ - __u8 duty_on; /* % of duty_length the led is on (0xff mean 100%) */ + u8 time_enabled; /* the total time the led is active (0xff means forever) */ + u8 duty_length; /* how long a cycle is in deciseconds (0 means "really fast") */ + u8 enabled; + u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */ + u8 duty_on; /* % of duty_length the led is on (0xff mean 100%) */ } __packed; struct sixaxis_rumble { - __u8 padding; - __u8 right_duration; /* Right motor duration (0xff means forever) */ - __u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */ - __u8 left_duration; /* Left motor duration (0xff means forever) */ - __u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */ + u8 padding; + u8 right_duration; /* Right motor duration (0xff means forever) */ + u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */ + u8 left_duration; /* Left motor duration (0xff means forever) */ + u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */ } __packed; struct sixaxis_output_report { - __u8 report_id; + u8 report_id; struct sixaxis_rumble rumble; - __u8 padding[4]; - __u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */ + u8 padding[4]; + u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */ struct sixaxis_led led[4]; /* LEDx at (4 - x) */ struct sixaxis_led _reserved; /* LED5, not actually soldered */ } __packed; union sixaxis_output_report_01 { struct sixaxis_output_report data; - __u8 buf[36]; + u8 buf[36]; }; struct motion_output_report_02 { @@ -1039,26 +1039,26 @@ struct sony_sc { struct power_supply *battery; struct power_supply_desc battery_desc; int device_id; - __u8 *output_report_dmabuf; + u8 *output_report_dmabuf; #ifdef CONFIG_SONY_FF - __u8 left; - __u8 right; + u8 left; + u8 right; #endif - __u8 mac_address[6]; - __u8 worker_initialized; - __u8 cable_state; - __u8 battery_charging; - __u8 battery_capacity; - __u8 led_state[MAX_LEDS]; - __u8 resume_led_state[MAX_LEDS]; - __u8 led_delay_on[MAX_LEDS]; - __u8 led_delay_off[MAX_LEDS]; - __u8 led_count; + u8 mac_address[6]; + u8 worker_initialized; + u8 cable_state; + u8 battery_charging; + u8 battery_capacity; + u8 led_state[MAX_LEDS]; + u8 resume_led_state[MAX_LEDS]; + u8 led_delay_on[MAX_LEDS]; + u8 led_delay_off[MAX_LEDS]; + u8 led_count; }; -static __u8 *sixaxis_fixup(struct hid_device *hdev, __u8 *rdesc, +static u8 *sixaxis_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *rsize) { *rsize = sizeof(sixaxis_rdesc); @@ -1079,7 +1079,7 @@ static u8 *navigation_fixup(struct hid_device *hdev, u8 *rdesc, return navigation_rdesc; } -static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, +static u8 *ps3remote_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *rsize) { *rsize = sizeof(ps3remote_rdesc); @@ -1120,7 +1120,7 @@ static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, return 1; } -static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *rsize) { struct sony_sc *sc = hid_get_drvdata(hdev); @@ -1174,12 +1174,12 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, return rdesc; } -static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size) +static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size) { - static const __u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 }; + static const u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 }; unsigned long flags; int offset; - __u8 cable_state, battery_capacity, battery_charging; + u8 cable_state, battery_capacity, battery_charging; /* * The sixaxis is charging if the battery value is 0xee @@ -1194,7 +1194,7 @@ static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size) battery_charging = !(rd[offset] & 0x01); cable_state = 1; } else { - __u8 index = rd[offset] <= 5 ? rd[offset] : 5; + u8 index = rd[offset] <= 5 ? rd[offset] : 5; battery_capacity = sixaxis_battery_capacity[index]; battery_charging = 0; cable_state = 0; @@ -1207,14 +1207,14 @@ static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size) spin_unlock_irqrestore(&sc->lock, flags); } -static void dualshock4_parse_report(struct sony_sc *sc, __u8 *rd, int size) +static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) { struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, struct hid_input, list); struct input_dev *input_dev = hidinput->input; unsigned long flags; int n, offset; - __u8 cable_state, battery_capacity, battery_charging; + u8 cable_state, battery_capacity, battery_charging; /* * Battery and touchpad data starts at byte 30 in the USB report and @@ -1264,7 +1264,7 @@ static void dualshock4_parse_report(struct sony_sc *sc, __u8 *rd, int size) * follows the data for the first. */ for (n = 0; n < 2; n++) { - __u16 x, y; + u16 x, y; x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8); y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4); @@ -1280,7 +1280,7 @@ static void dualshock4_parse_report(struct sony_sc *sc, __u8 *rd, int size) } static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, - __u8 *rd, int size) + u8 *rd, int size) { struct sony_sc *sc = hid_get_drvdata(hdev); @@ -1404,7 +1404,7 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev) { const int buf_size = max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE); - __u8 *buf; + u8 *buf; int ret; buf = kmalloc(buf_size, GFP_KERNEL); @@ -1443,8 +1443,8 @@ out: static int sixaxis_set_operational_bt(struct hid_device *hdev) { - static const __u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; - __u8 *buf; + static const u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; + u8 *buf; int ret; buf = kmemdup(report, sizeof(report), GFP_KERNEL); @@ -1465,7 +1465,7 @@ static int sixaxis_set_operational_bt(struct hid_device *hdev) */ static int dualshock4_set_operational_bt(struct hid_device *hdev) { - __u8 *buf; + u8 *buf; int ret; buf = kmalloc(DS4_REPORT_0x02_SIZE, GFP_KERNEL); @@ -1482,7 +1482,7 @@ static int dualshock4_set_operational_bt(struct hid_device *hdev) static void sixaxis_set_leds_from_id(struct sony_sc *sc) { - static const __u8 sixaxis_leds[10][4] = { + static const u8 sixaxis_leds[10][4] = { { 0x01, 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x00, 0x00 }, { 0x00, 0x00, 0x01, 0x00 }, @@ -1509,7 +1509,7 @@ static void sixaxis_set_leds_from_id(struct sony_sc *sc) static void dualshock4_set_leds_from_id(struct sony_sc *sc) { /* The first 4 color/index entries match what the PS4 assigns */ - static const __u8 color_code[7][3] = { + static const u8 color_code[7][3] = { /* Blue */ { 0x00, 0x00, 0x01 }, /* Red */ { 0x01, 0x00, 0x00 }, /* Green */ { 0x00, 0x01, 0x00 }, @@ -1537,7 +1537,7 @@ static void buzz_set_leds(struct sony_sc *sc) &hdev->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - __s32 *value = report->field[0]->value; + s32 *value = report->field[0]->value; BUILD_BUG_ON(MAX_LEDS < 4); @@ -1631,7 +1631,7 @@ static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on, struct hid_device *hdev = to_hid_device(dev); struct sony_sc *drv_data = hid_get_drvdata(hdev); int n; - __u8 new_on, new_off; + u8 new_on, new_off; if (!drv_data) { hid_err(hdev, "No device data\n"); @@ -1702,8 +1702,8 @@ static int sony_leds_init(struct sony_sc *sc) const char *name_fmt; static const char * const ds4_name_str[] = { "red", "green", "blue", "global" }; - __u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 }; - __u8 use_hw_blink[MAX_LEDS] = { 0 }; + u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 }; + u8 use_hw_blink[MAX_LEDS] = { 0 }; BUG_ON(!(sc->quirks & SONY_LED_SUPPORT)); @@ -1731,7 +1731,7 @@ static int sony_leds_init(struct sony_sc *sc) name_len = 0; name_fmt = "%s:%s"; } else if (sc->quirks & NAVIGATION_CONTROLLER) { - static const __u8 navigation_leds[4] = {0x01, 0x00, 0x00, 0x00}; + static const u8 navigation_leds[4] = {0x01, 0x00, 0x00, 0x00}; memcpy(sc->led_state, navigation_leds, sizeof(navigation_leds)); sc->led_count = 1; @@ -1854,7 +1854,7 @@ static void sixaxis_send_output_report(struct sony_sc *sc) } } - hid_hw_raw_request(sc->hdev, report->report_id, (__u8 *)report, + hid_hw_raw_request(sc->hdev, report->report_id, (u8 *)report, sizeof(struct sixaxis_output_report), HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); } @@ -1862,7 +1862,7 @@ static void sixaxis_send_output_report(struct sony_sc *sc) static void dualshock4_send_output_report(struct sony_sc *sc) { struct hid_device *hdev = sc->hdev; - __u8 *buf = sc->output_report_dmabuf; + u8 *buf = sc->output_report_dmabuf; int offset; if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { @@ -1922,7 +1922,7 @@ static void motion_send_output_report(struct sony_sc *sc) report->rumble = max(sc->right, sc->left); #endif - hid_hw_output_report(hdev, (__u8 *)report, MOTION_REPORT_0x02_SIZE); + hid_hw_output_report(hdev, (u8 *)report, MOTION_REPORT_0x02_SIZE); } static inline void sony_send_output_report(struct sony_sc *sc) @@ -2155,7 +2155,7 @@ static int sony_get_bt_devaddr(struct sony_sc *sc) static int sony_check_add(struct sony_sc *sc) { - __u8 *buf = NULL; + u8 *buf = NULL; int n, ret; if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) || -- cgit v1.2.3 From 568b3ce7a8efdc23ad2f0b9ca8d82899cf68972d Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 10 Feb 2016 01:37:44 +0300 Subject: ravb: factor out register bit twiddling code The driver has often repeated pattern of reading a register, AND'ing and/or OR'ing some bits and writing the value back. Factor the pattern out into ravb_modify() -- this saves 260 bytes of code with ARM gcc 4.7.3. While at it, update Cogent Embedded's copyrights. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/ravb.h | 4 +- drivers/net/ethernet/renesas/ravb_main.c | 68 +++++++++++++------------------- drivers/net/ethernet/renesas/ravb_ptp.c | 25 +++--------- 3 files changed, 36 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h index 9fbe92ac225b..b2160d1b9c71 100644 --- a/drivers/net/ethernet/renesas/ravb.h +++ b/drivers/net/ethernet/renesas/ravb.h @@ -2,7 +2,7 @@ * * Copyright (C) 2014-2015 Renesas Electronics Corporation * Copyright (C) 2015 Renesas Solutions Corp. - * Copyright (C) 2015 Cogent Embedded, Inc. + * Copyright (C) 2015-2016 Cogent Embedded, Inc. * * Based on the SuperH Ethernet driver * @@ -837,6 +837,8 @@ static inline void ravb_write(struct net_device *ndev, u32 data, iowrite32(data, priv->addr + reg); } +void ravb_modify(struct net_device *ndev, enum ravb_reg reg, u32 clear, + u32 set); int ravb_wait(struct net_device *ndev, enum ravb_reg reg, u32 mask, u32 value); irqreturn_t ravb_ptp_interrupt(struct net_device *ndev); diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index ac43ed914fcf..c936682aae68 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -2,7 +2,7 @@ * * Copyright (C) 2014-2015 Renesas Electronics Corporation * Copyright (C) 2015 Renesas Solutions Corp. - * Copyright (C) 2015 Cogent Embedded, Inc. + * Copyright (C) 2015-2016 Cogent Embedded, Inc. * * Based on the SuperH Ethernet driver * @@ -42,6 +42,12 @@ NETIF_MSG_RX_ERR | \ NETIF_MSG_TX_ERR) +void ravb_modify(struct net_device *ndev, enum ravb_reg reg, u32 clear, + u32 set) +{ + ravb_write(ndev, (ravb_read(ndev, reg) & ~clear) | set, reg); +} + int ravb_wait(struct net_device *ndev, enum ravb_reg reg, u32 mask, u32 value) { int i; @@ -59,8 +65,7 @@ static int ravb_config(struct net_device *ndev) int error; /* Set config mode */ - ravb_write(ndev, (ravb_read(ndev, CCC) & ~CCC_OPC) | CCC_OPC_CONFIG, - CCC); + ravb_modify(ndev, CCC, CCC_OPC, CCC_OPC_CONFIG); /* Check if the operating mode is changed to the config mode */ error = ravb_wait(ndev, CSR, CSR_OPS, CSR_OPS_CONFIG); if (error) @@ -72,13 +77,8 @@ static int ravb_config(struct net_device *ndev) static void ravb_set_duplex(struct net_device *ndev) { struct ravb_private *priv = netdev_priv(ndev); - u32 ecmr = ravb_read(ndev, ECMR); - if (priv->duplex) /* Full */ - ecmr |= ECMR_DM; - else /* Half */ - ecmr &= ~ECMR_DM; - ravb_write(ndev, ecmr, ECMR); + ravb_modify(ndev, ECMR, ECMR_DM, priv->duplex ? ECMR_DM : 0); } static void ravb_set_rate(struct net_device *ndev) @@ -131,13 +131,8 @@ static void ravb_mdio_ctrl(struct mdiobb_ctrl *ctrl, u32 mask, int set) { struct ravb_private *priv = container_of(ctrl, struct ravb_private, mdiobb); - u32 pir = ravb_read(priv->ndev, PIR); - if (set) - pir |= mask; - else - pir &= ~mask; - ravb_write(priv->ndev, pir, PIR); + ravb_modify(priv->ndev, PIR, mask, set ? mask : 0); } /* MDC pin control */ @@ -393,9 +388,9 @@ static int ravb_dmac_init(struct net_device *ndev) ravb_ring_format(ndev, RAVB_NC); #if defined(__LITTLE_ENDIAN) - ravb_write(ndev, ravb_read(ndev, CCC) & ~CCC_BOC, CCC); + ravb_modify(ndev, CCC, CCC_BOC, 0); #else - ravb_write(ndev, ravb_read(ndev, CCC) | CCC_BOC, CCC); + ravb_modify(ndev, CCC, CCC_BOC, CCC_BOC); #endif /* Set AVB RX */ @@ -418,8 +413,7 @@ static int ravb_dmac_init(struct net_device *ndev) ravb_write(ndev, TIC_FTE0 | TIC_FTE1 | TIC_TFUE, TIC); /* Setting the control will start the AVB-DMAC process. */ - ravb_write(ndev, (ravb_read(ndev, CCC) & ~CCC_OPC) | CCC_OPC_OPERATION, - CCC); + ravb_modify(ndev, CCC, CCC_OPC, CCC_OPC_OPERATION); return 0; } @@ -493,7 +487,7 @@ static void ravb_get_tx_tstamp(struct net_device *ndev) break; } } - ravb_write(ndev, ravb_read(ndev, TCCR) | TCCR_TFR, TCCR); + ravb_modify(ndev, TCCR, TCCR_TFR, TCCR_TFR); } } @@ -613,13 +607,13 @@ static bool ravb_rx(struct net_device *ndev, int *quota, int q) static void ravb_rcv_snd_disable(struct net_device *ndev) { /* Disable TX and RX */ - ravb_write(ndev, ravb_read(ndev, ECMR) & ~(ECMR_RE | ECMR_TE), ECMR); + ravb_modify(ndev, ECMR, ECMR_RE | ECMR_TE, 0); } static void ravb_rcv_snd_enable(struct net_device *ndev) { /* Enable TX and RX */ - ravb_write(ndev, ravb_read(ndev, ECMR) | ECMR_RE | ECMR_TE, ECMR); + ravb_modify(ndev, ECMR, ECMR_RE | ECMR_TE, ECMR_RE | ECMR_TE); } /* function for waiting dma process finished */ @@ -812,8 +806,8 @@ static int ravb_poll(struct napi_struct *napi, int budget) /* Re-enable RX/TX interrupts */ spin_lock_irqsave(&priv->lock, flags); - ravb_write(ndev, ravb_read(ndev, RIC0) | mask, RIC0); - ravb_write(ndev, ravb_read(ndev, TIC) | mask, TIC); + ravb_modify(ndev, RIC0, mask, mask); + ravb_modify(ndev, TIC, mask, mask); mmiowb(); spin_unlock_irqrestore(&priv->lock, flags); @@ -852,8 +846,7 @@ static void ravb_adjust_link(struct net_device *ndev) ravb_set_rate(ndev); } if (!priv->link) { - ravb_write(ndev, ravb_read(ndev, ECMR) & ~ECMR_TXF, - ECMR); + ravb_modify(ndev, ECMR, ECMR_TXF, 0); new_state = true; priv->link = phydev->link; if (priv->no_avb_link) @@ -1393,7 +1386,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) desc--; desc->die_dt = DT_FSTART; - ravb_write(ndev, ravb_read(ndev, TCCR) | (TCCR_TSRQ0 << q), TCCR); + ravb_modify(ndev, TCCR, TCCR_TSRQ0 << q, TCCR_TSRQ0 << q); priv->cur_tx[q] += NUM_TX_DESC; if (priv->cur_tx[q] - priv->dirty_tx[q] > @@ -1468,15 +1461,10 @@ static void ravb_set_rx_mode(struct net_device *ndev) { struct ravb_private *priv = netdev_priv(ndev); unsigned long flags; - u32 ecmr; spin_lock_irqsave(&priv->lock, flags); - ecmr = ravb_read(ndev, ECMR); - if (ndev->flags & IFF_PROMISC) - ecmr |= ECMR_PRM; - else - ecmr &= ~ECMR_PRM; - ravb_write(ndev, ecmr, ECMR); + ravb_modify(ndev, ECMR, ECMR_PRM, + ndev->flags & IFF_PROMISC ? ECMR_PRM : 0); mmiowb(); spin_unlock_irqrestore(&priv->lock, flags); } @@ -1804,14 +1792,12 @@ static int ravb_probe(struct platform_device *pdev) /* Set AVB config mode */ if (chip_id == RCAR_GEN2) { - ravb_write(ndev, (ravb_read(ndev, CCC) & ~CCC_OPC) | - CCC_OPC_CONFIG, CCC); + ravb_modify(ndev, CCC, CCC_OPC, CCC_OPC_CONFIG); /* Set CSEL value */ - ravb_write(ndev, (ravb_read(ndev, CCC) & ~CCC_CSEL) | - CCC_CSEL_HPB, CCC); + ravb_modify(ndev, CCC, CCC_CSEL, CCC_CSEL_HPB); } else { - ravb_write(ndev, (ravb_read(ndev, CCC) & ~CCC_OPC) | - CCC_OPC_CONFIG | CCC_GAC | CCC_CSEL_HPB, CCC); + ravb_modify(ndev, CCC, CCC_OPC, CCC_OPC_CONFIG | + CCC_GAC | CCC_CSEL_HPB); } /* Set CSEL value */ @@ -1824,7 +1810,7 @@ static int ravb_probe(struct platform_device *pdev) goto out_release; /* Request GTI loading */ - ravb_write(ndev, ravb_read(ndev, GCCR) | GCCR_LTI, GCCR); + ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI); /* Allocate descriptor base address table */ priv->desc_bat_size = sizeof(struct ravb_desc) * DBAT_ENTRY_NUM; diff --git a/drivers/net/ethernet/renesas/ravb_ptp.c b/drivers/net/ethernet/renesas/ravb_ptp.c index 7a8ce920c49e..57992ccc4657 100644 --- a/drivers/net/ethernet/renesas/ravb_ptp.c +++ b/drivers/net/ethernet/renesas/ravb_ptp.c @@ -2,7 +2,7 @@ * * Copyright (C) 2013-2015 Renesas Electronics Corporation * Copyright (C) 2015 Renesas Solutions Corp. - * Copyright (C) 2015 Cogent Embedded, Inc. + * Copyright (C) 2015-2016 Cogent Embedded, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,7 +21,7 @@ static int ravb_ptp_tcr_request(struct ravb_private *priv, u32 request) if (error) return error; - ravb_write(ndev, ravb_read(ndev, GCCR) | request, GCCR); + ravb_modify(ndev, GCCR, request, request); return ravb_wait(ndev, GCCR, GCCR_TCR, GCCR_TCR_NOREQ); } @@ -185,7 +185,6 @@ static int ravb_ptp_extts(struct ptp_clock_info *ptp, ptp.info); struct net_device *ndev = priv->ndev; unsigned long flags; - u32 gic; if (req->index) return -EINVAL; @@ -195,12 +194,7 @@ static int ravb_ptp_extts(struct ptp_clock_info *ptp, priv->ptp.extts[req->index] = on; spin_lock_irqsave(&priv->lock, flags); - gic = ravb_read(ndev, GIC); - if (on) - gic |= GIC_PTCE; - else - gic &= ~GIC_PTCE; - ravb_write(ndev, gic, GIC); + ravb_modify(ndev, GIC, GIC_PTCE, on ? GIC_PTCE : 0); mmiowb(); spin_unlock_irqrestore(&priv->lock, flags); @@ -216,7 +210,6 @@ static int ravb_ptp_perout(struct ptp_clock_info *ptp, struct ravb_ptp_perout *perout; unsigned long flags; int error = 0; - u32 gic; if (req->index) return -EINVAL; @@ -248,9 +241,7 @@ static int ravb_ptp_perout(struct ptp_clock_info *ptp, error = ravb_ptp_update_compare(priv, (u32)start_ns); if (!error) { /* Unmask interrupt */ - gic = ravb_read(ndev, GIC); - gic |= GIC_PTME; - ravb_write(ndev, gic, GIC); + ravb_modify(ndev, GIC, GIC_PTME, GIC_PTME); } } else { spin_lock_irqsave(&priv->lock, flags); @@ -259,9 +250,7 @@ static int ravb_ptp_perout(struct ptp_clock_info *ptp, perout->period = 0; /* Mask interrupt */ - gic = ravb_read(ndev, GIC); - gic &= ~GIC_PTME; - ravb_write(ndev, gic, GIC); + ravb_modify(ndev, GIC, GIC_PTME, 0); } mmiowb(); spin_unlock_irqrestore(&priv->lock, flags); @@ -331,7 +320,6 @@ void ravb_ptp_init(struct net_device *ndev, struct platform_device *pdev) { struct ravb_private *priv = netdev_priv(ndev); unsigned long flags; - u32 gccr; priv->ptp.info = ravb_ptp_info; @@ -340,8 +328,7 @@ void ravb_ptp_init(struct net_device *ndev, struct platform_device *pdev) spin_lock_irqsave(&priv->lock, flags); ravb_wait(ndev, GCCR, GCCR_TCR, GCCR_TCR_NOREQ); - gccr = ravb_read(ndev, GCCR) & ~GCCR_TCSS; - ravb_write(ndev, gccr | GCCR_TCSS_ADJGPTP, GCCR); + ravb_modify(ndev, GCCR, GCCR_TCSS, GCCR_TCSS_ADJGPTP); mmiowb(); spin_unlock_irqrestore(&priv->lock, flags); -- cgit v1.2.3 From b2b14d2f57df89fc2d57099ce13c5b513061d3a1 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 10 Feb 2016 01:38:28 +0300 Subject: sh_eth: factor out register bit twiddling code The driver has often repeated pattern of reading a register, AND'ing and/or OR'ing some bits and writing the value back. Factor the pattern out into sh_eth_modify() -- this saves 84 bytes of code with ARM gcc 4.7.3. While at it, update Cogent Embedded's copyright. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 53 ++++++++++++++++------------------- 1 file changed, 24 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index dfa9e59c9442..0a150b228914 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -3,7 +3,7 @@ * Copyright (C) 2014 Renesas Electronics Corporation * Copyright (C) 2006-2012 Nobuhiro Iwamatsu * Copyright (C) 2008-2014 Renesas Solutions Corp. - * Copyright (C) 2013-2014 Cogent Embedded, Inc. + * Copyright (C) 2013-2016 Cogent Embedded, Inc. * Copyright (C) 2014 Codethink Limited * * This program is free software; you can redistribute it and/or modify it @@ -428,6 +428,13 @@ static u32 sh_eth_read(struct net_device *ndev, int enum_index) return ioread32(mdp->addr + offset); } +static void sh_eth_modify(struct net_device *ndev, int enum_index, u32 clear, + u32 set) +{ + sh_eth_write(ndev, (sh_eth_read(ndev, enum_index) & ~clear) | set, + enum_index); +} + static bool sh_eth_is_gether(struct sh_eth_private *mdp) { return mdp->reg_offset == sh_eth_offset_gigabit; @@ -467,10 +474,7 @@ static void sh_eth_set_duplex(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); - if (mdp->duplex) /* Full */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR); - else /* Half */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR); + sh_eth_modify(ndev, ECMR, ECMR_DM, mdp->duplex ? ECMR_DM : 0); } static void sh_eth_chip_reset(struct net_device *ndev) @@ -583,10 +587,10 @@ static void sh_eth_set_rate_r8a777x(struct net_device *ndev) switch (mdp->speed) { case 10: /* 10BASE */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_ELB, ECMR); + sh_eth_modify(ndev, ECMR, ECMR_ELB, 0); break; case 100:/* 100BASE */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_ELB, ECMR); + sh_eth_modify(ndev, ECMR, ECMR_ELB, ECMR_ELB); break; default: break; @@ -649,10 +653,10 @@ static void sh_eth_set_rate_sh7724(struct net_device *ndev) switch (mdp->speed) { case 10: /* 10BASE */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR); + sh_eth_modify(ndev, ECMR, ECMR_RTM, 0); break; case 100:/* 100BASE */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR); + sh_eth_modify(ndev, ECMR, ECMR_RTM, ECMR_RTM); break; default: break; @@ -924,8 +928,7 @@ static int sh_eth_reset(struct net_device *ndev) if (sh_eth_is_gether(mdp) || sh_eth_is_rz_fast_ether(mdp)) { sh_eth_write(ndev, EDSR_ENALL, EDSR); - sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, - EDMR); + sh_eth_modify(ndev, EDMR, EDMR_SRST_GETHER, EDMR_SRST_GETHER); ret = sh_eth_check_reset(ndev); if (ret) @@ -949,11 +952,9 @@ static int sh_eth_reset(struct net_device *ndev) if (mdp->cd->select_mii) sh_eth_select_mii(ndev); } else { - sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER, - EDMR); + sh_eth_modify(ndev, EDMR, EDMR_SRST_ETHER, EDMR_SRST_ETHER); mdelay(3); - sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER, - EDMR); + sh_eth_modify(ndev, EDMR, EDMR_SRST_ETHER, 0); } return ret; @@ -1285,7 +1286,7 @@ static int sh_eth_dev_init(struct net_device *ndev, bool start) sh_eth_write(ndev, ndev->mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN, RFLR); - sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR); + sh_eth_modify(ndev, EESR, 0, 0); if (start) { mdp->irq_enabled = true; sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR); @@ -1532,15 +1533,13 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) static void sh_eth_rcv_snd_disable(struct net_device *ndev) { /* disable tx and rx */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & - ~(ECMR_RE | ECMR_TE), ECMR); + sh_eth_modify(ndev, ECMR, ECMR_RE | ECMR_TE, 0); } static void sh_eth_rcv_snd_enable(struct net_device *ndev) { /* enable tx and rx */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | - (ECMR_RE | ECMR_TE), ECMR); + sh_eth_modify(ndev, ECMR, ECMR_RE | ECMR_TE, ECMR_RE | ECMR_TE); } /* error control function */ @@ -1569,13 +1568,11 @@ static void sh_eth_error(struct net_device *ndev, u32 intr_status) sh_eth_rcv_snd_disable(ndev); } else { /* Link Up */ - sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) & - ~DMAC_M_ECI, EESIPR); + sh_eth_modify(ndev, EESIPR, DMAC_M_ECI, 0); /* clear int */ - sh_eth_write(ndev, sh_eth_read(ndev, ECSR), - ECSR); - sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) | - DMAC_M_ECI, EESIPR); + sh_eth_modify(ndev, ECSR, 0, 0); + sh_eth_modify(ndev, EESIPR, DMAC_M_ECI, + DMAC_M_ECI); /* enable tx and rx */ sh_eth_rcv_snd_enable(ndev); } @@ -1765,9 +1762,7 @@ static void sh_eth_adjust_link(struct net_device *ndev) mdp->cd->set_rate(ndev); } if (!mdp->link) { - sh_eth_write(ndev, - sh_eth_read(ndev, ECMR) & ~ECMR_TXF, - ECMR); + sh_eth_modify(ndev, ECMR, ECMR_TXF, 0); new_state = 1; mdp->link = phydev->link; if (mdp->cd->no_psr || mdp->no_ether_link) -- cgit v1.2.3 From 28be55dfed57a487c5cf40c77faa71bdf05e6ebb Mon Sep 17 00:00:00 2001 From: Alban Bedel Date: Thu, 28 Jan 2016 20:44:33 +0100 Subject: gpio: ath79: Update the copyright notice Add myself to the copyright list and remove the reference to Atheros' BSP as nothing is left of this code. Signed-off-by: Alban Bedel Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ath79.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index 0d94c0bd764a..018ea9d33b54 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -1,12 +1,11 @@ /* * Atheros AR71XX/AR724X/AR913X GPIO API support * + * Copyright (C) 2015 Alban Bedel * Copyright (C) 2010-2011 Jaiganesh Narayanan * Copyright (C) 2008-2011 Gabor Juhos * Copyright (C) 2008 Imre Kaloz * - * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP - * * 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. -- cgit v1.2.3 From 72564b59ffc438ea103b0727a921aaddce766728 Mon Sep 17 00:00:00 2001 From: David Wragg Date: Wed, 10 Feb 2016 00:05:55 +0000 Subject: vxlan: Relax MTU constraints Allow the MTU of vxlan devices without an underlying device to be set to larger values (up to a maximum based on IP packet limits and vxlan overhead). Previously, their MTUs could not be set to higher than the conventional ethernet value of 1500. This is a very arbitrary value in the context of vxlan, and prevented vxlan devices from being able to take advantage of jumbo frames etc. The default MTU remains 1500, for compatibility. Signed-off-by: David Wragg Acked-by: Roopa Prabhu Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 65439188c582..e992c6a05f86 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2367,29 +2367,43 @@ static void vxlan_set_multicast_list(struct net_device *dev) { } -static int vxlan_change_mtu(struct net_device *dev, int new_mtu) +static int __vxlan_change_mtu(struct net_device *dev, + struct net_device *lowerdev, + struct vxlan_rdst *dst, int new_mtu, bool strict) { - struct vxlan_dev *vxlan = netdev_priv(dev); - struct vxlan_rdst *dst = &vxlan->default_dst; - struct net_device *lowerdev; - int max_mtu; + int max_mtu = IP_MAX_MTU; - lowerdev = __dev_get_by_index(vxlan->net, dst->remote_ifindex); - if (lowerdev == NULL) - return eth_change_mtu(dev, new_mtu); + if (lowerdev) + max_mtu = lowerdev->mtu; if (dst->remote_ip.sa.sa_family == AF_INET6) - max_mtu = lowerdev->mtu - VXLAN6_HEADROOM; + max_mtu -= VXLAN6_HEADROOM; else - max_mtu = lowerdev->mtu - VXLAN_HEADROOM; + max_mtu -= VXLAN_HEADROOM; - if (new_mtu < 68 || new_mtu > max_mtu) + if (new_mtu < 68) return -EINVAL; + if (new_mtu > max_mtu) { + if (strict) + return -EINVAL; + + new_mtu = max_mtu; + } + dev->mtu = new_mtu; return 0; } +static int vxlan_change_mtu(struct net_device *dev, int new_mtu) +{ + struct vxlan_dev *vxlan = netdev_priv(dev); + struct vxlan_rdst *dst = &vxlan->default_dst; + struct net_device *lowerdev = __dev_get_by_index(vxlan->net, + dst->remote_ifindex); + return __vxlan_change_mtu(dev, lowerdev, dst, new_mtu, true); +} + static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb, struct ip_tunnel_info *info, __be16 sport, __be16 dport) -- cgit v1.2.3 From 55e5bfb53cff286c1c1ff49f51325dc15c7fea63 Mon Sep 17 00:00:00 2001 From: David Wragg Date: Wed, 10 Feb 2016 00:05:57 +0000 Subject: geneve: Relax MTU constraints Allow the MTU of geneve devices to be set to large values, in order to exploit underlying networks with larger frame sizes. GENEVE does not have a fixed encapsulation overhead (an openvswitch rule can add variable length options), so there is no relevant maximum MTU to enforce. A maximum of IP_MAX_MTU is used instead. Encapsulated packets that are too big for the underlying network will get dropped on the floor. Signed-off-by: David Wragg Signed-off-by: David S. Miller --- drivers/net/geneve.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 0b14ac3b8d11..d2031ce8baea 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1039,6 +1039,17 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) return geneve_xmit_skb(skb, dev, info); } +static int geneve_change_mtu(struct net_device *dev, int new_mtu) +{ + /* GENEVE overhead is not fixed, so we can't enforce a more + * precise max MTU. + */ + if (new_mtu < 68 || new_mtu > IP_MAX_MTU) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) { struct ip_tunnel_info *info = skb_tunnel_info(skb); @@ -1083,7 +1094,7 @@ static const struct net_device_ops geneve_netdev_ops = { .ndo_stop = geneve_stop, .ndo_start_xmit = geneve_xmit, .ndo_get_stats64 = ip_tunnel_get_stats64, - .ndo_change_mtu = eth_change_mtu, + .ndo_change_mtu = geneve_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, .ndo_fill_metadata_dst = geneve_fill_metadata_dst, -- cgit v1.2.3 From 7e059158d57b79159eaf1f504825d19866ef2c42 Mon Sep 17 00:00:00 2001 From: David Wragg Date: Wed, 10 Feb 2016 00:05:58 +0000 Subject: vxlan, gre, geneve: Set a large MTU on ovs-created tunnel devices Prior to 4.3, openvswitch tunnel vports (vxlan, gre and geneve) could transmit vxlan packets of any size, constrained only by the ability to send out the resulting packets. 4.3 introduced netdevs corresponding to tunnel vports. These netdevs have an MTU, which limits the size of a packet that can be successfully encapsulated. The default MTU values are low (1500 or less), which is awkwardly small in the context of physical networks supporting jumbo frames, and leads to a conspicuous change in behaviour for userspace. Instead, set the MTU on openvswitch-created netdevs to be the relevant maximum (i.e. the maximum IP packet size minus any relevant overhead), effectively restoring the behaviour prior to 4.3. Signed-off-by: David Wragg Signed-off-by: David S. Miller --- drivers/net/geneve.c | 18 ++++++++++++++---- drivers/net/vxlan.c | 11 ++++++++--- include/net/ip_tunnels.h | 1 + net/ipv4/ip_gre.c | 8 ++++++++ net/ipv4/ip_tunnel.c | 20 +++++++++++++++++--- net/openvswitch/vport-vxlan.c | 2 ++ 6 files changed, 50 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index d2031ce8baea..028e3873c310 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1453,11 +1453,21 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name, err = geneve_configure(net, dev, &geneve_remote_unspec, 0, 0, 0, htons(dst_port), true, 0); - if (err) { - free_netdev(dev); - return ERR_PTR(err); - } + if (err) + goto err; + + /* openvswitch users expect packet sizes to be unrestricted, + * so set the largest MTU we can. + */ + err = geneve_change_mtu(dev, IP_MAX_MTU); + if (err) + goto err; + return dev; + + err: + free_netdev(dev); + return ERR_PTR(err); } EXPORT_SYMBOL_GPL(geneve_dev_create_fb); diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index e992c6a05f86..a31cd954b308 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2779,6 +2779,7 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, int err; bool use_ipv6 = false; __be16 default_port = vxlan->cfg.dst_port; + struct net_device *lowerdev = NULL; vxlan->net = src_net; @@ -2799,9 +2800,7 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, } if (conf->remote_ifindex) { - struct net_device *lowerdev - = __dev_get_by_index(src_net, conf->remote_ifindex); - + lowerdev = __dev_get_by_index(src_net, conf->remote_ifindex); dst->remote_ifindex = conf->remote_ifindex; if (!lowerdev) { @@ -2825,6 +2824,12 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, needed_headroom = lowerdev->hard_header_len; } + if (conf->mtu) { + err = __vxlan_change_mtu(dev, lowerdev, dst, conf->mtu, false); + if (err) + return err; + } + if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA) needed_headroom += VXLAN6_HEADROOM; else diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 6db96ea0144f..dda9abf6b89c 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -230,6 +230,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd); int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t, u8 *protocol, struct flowi4 *fl4); +int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict); int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu); struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev, diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 7c51c4e1661f..56fdf4e0dce4 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1240,6 +1240,14 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name, err = ipgre_newlink(net, dev, tb, NULL); if (err < 0) goto out; + + /* openvswitch users expect packet sizes to be unrestricted, + * so set the largest MTU we can. + */ + err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false); + if (err) + goto out; + return dev; out: free_netdev(dev); diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index c7bd72e9b544..89e8861e05fc 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -943,17 +943,31 @@ done: } EXPORT_SYMBOL_GPL(ip_tunnel_ioctl); -int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu) +int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict) { struct ip_tunnel *tunnel = netdev_priv(dev); int t_hlen = tunnel->hlen + sizeof(struct iphdr); + int max_mtu = 0xFFF8 - dev->hard_header_len - t_hlen; - if (new_mtu < 68 || - new_mtu > 0xFFF8 - dev->hard_header_len - t_hlen) + if (new_mtu < 68) return -EINVAL; + + if (new_mtu > max_mtu) { + if (strict) + return -EINVAL; + + new_mtu = max_mtu; + } + dev->mtu = new_mtu; return 0; } +EXPORT_SYMBOL_GPL(__ip_tunnel_change_mtu); + +int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu) +{ + return __ip_tunnel_change_mtu(dev, new_mtu, true); +} EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu); static void ip_tunnel_dev_free(struct net_device *dev) diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c index 1605691d9414..de9cb19efb6a 100644 --- a/net/openvswitch/vport-vxlan.c +++ b/net/openvswitch/vport-vxlan.c @@ -91,6 +91,8 @@ static struct vport *vxlan_tnl_create(const struct vport_parms *parms) struct vxlan_config conf = { .no_share = true, .flags = VXLAN_F_COLLECT_METADATA, + /* Don't restrict the packets that can be sent by MTU */ + .mtu = IP_MAX_MTU, }; if (!options) { -- cgit v1.2.3 From 7b606ffd65730bca6eaa45f74e0bdf70dbe8a854 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 9 Feb 2016 15:53:39 -0200 Subject: [media] au0828: move V4L2-specific code to au0828-core.c Instead of having lots of #ifdefs inside au0828-core due to V4L2, move the dependencies to au0828-video.c. That allows removing all those ifdefs, as au0828-video is only compiled if CONFIG_VIDEO_AU0828_V4L2. This fixes the following warnings reported by Kbuild test with a random config with au0828 enabled, but V4L2 is disabled. All warnings (new ones prefixed by >>): drivers/media/usb/au0828/au0828-core.c: In function 'au0828_usb_probe': >> drivers/media/usb/au0828/au0828-core.c:463:1: warning: label 'done' defined but not used [-Wunused-label] done: ^ drivers/media/usb/au0828/au0828-core.c: At top level: drivers/media/usb/au0828/au0828-core.c:250:12: warning: 'au0828_create_media_graph' defined but not used [-Wunused-function] static int au0828_create_media_graph(struct au0828_dev *dev) ^ Tested with a WinTV HVR 950Q (USB ID: 2040:7200) Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-core.c | 157 ++----------------------------- drivers/media/usb/au0828/au0828-video.c | 162 +++++++++++++++++++++++++++++++- drivers/media/usb/au0828/au0828.h | 20 +++- 3 files changed, 187 insertions(+), 152 deletions(-) (limited to 'drivers') diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index 0a8afbf181c9..f23da7e7984b 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -143,7 +143,7 @@ static void au0828_unregister_media_device(struct au0828_dev *dev) #endif } -static void au0828_usb_release(struct au0828_dev *dev) +void au0828_usb_release(struct au0828_dev *dev) { au0828_unregister_media_device(dev); @@ -153,33 +153,6 @@ static void au0828_usb_release(struct au0828_dev *dev) kfree(dev); } -#ifdef CONFIG_VIDEO_AU0828_V4L2 - -static void au0828_usb_v4l2_media_release(struct au0828_dev *dev) -{ -#ifdef CONFIG_MEDIA_CONTROLLER - int i; - - for (i = 0; i < AU0828_MAX_INPUT; i++) { - if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) - return; - media_device_unregister_entity(&dev->input_ent[i]); - } -#endif -} - -static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev) -{ - struct au0828_dev *dev = - container_of(v4l2_dev, struct au0828_dev, v4l2_dev); - - v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl); - v4l2_device_unregister(&dev->v4l2_dev); - au0828_usb_v4l2_media_release(dev); - au0828_usb_release(dev); -} -#endif - static void au0828_usb_disconnect(struct usb_interface *interface) { struct au0828_dev *dev = usb_get_intfdata(interface); @@ -202,18 +175,13 @@ static void au0828_usb_disconnect(struct usb_interface *interface) mutex_lock(&dev->mutex); dev->usbdev = NULL; mutex_unlock(&dev->mutex); -#ifdef CONFIG_VIDEO_AU0828_V4L2 - if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) { - au0828_analog_unregister(dev); - v4l2_device_disconnect(&dev->v4l2_dev); - v4l2_device_put(&dev->v4l2_dev); + if (au0828_analog_unregister(dev)) { /* * No need to call au0828_usb_release() if V4L2 is enabled, * as this is already called via au0828_usb_v4l2_release() */ return; } -#endif au0828_usb_release(dev); } @@ -247,83 +215,6 @@ static int au0828_media_device_init(struct au0828_dev *dev, } -static int au0828_create_media_graph(struct au0828_dev *dev) -{ -#ifdef CONFIG_MEDIA_CONTROLLER - struct media_device *mdev = dev->media_dev; - struct media_entity *entity; - struct media_entity *tuner = NULL, *decoder = NULL; - int i, ret; - - if (!mdev) - return 0; - - media_device_for_each_entity(entity, mdev) { - switch (entity->function) { - case MEDIA_ENT_F_TUNER: - tuner = entity; - break; - case MEDIA_ENT_F_ATV_DECODER: - decoder = entity; - break; - } - } - - /* Analog setup, using tuner as a link */ - - /* Something bad happened! */ - if (!decoder) - return -EINVAL; - - if (tuner) { - ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, - decoder, 0, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - } - ret = media_create_pad_link(decoder, 1, &dev->vdev.entity, 0, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - ret = media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - - for (i = 0; i < AU0828_MAX_INPUT; i++) { - struct media_entity *ent = &dev->input_ent[i]; - - if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) - break; - - switch (AUVI_INPUT(i).type) { - case AU0828_VMUX_CABLE: - case AU0828_VMUX_TELEVISION: - case AU0828_VMUX_DVB: - if (!tuner) - break; - - ret = media_create_pad_link(ent, 0, tuner, - TUNER_PAD_RF_INPUT, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - break; - case AU0828_VMUX_COMPOSITE: - case AU0828_VMUX_SVIDEO: - default: /* AU0828_VMUX_DEBUG */ - /* FIXME: fix the decoder PAD */ - ret = media_create_pad_link(ent, 0, decoder, 0, 0); - if (ret) - return ret; - break; - } - } -#endif - return 0; -} - static int au0828_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -378,32 +269,13 @@ static int au0828_usb_probe(struct usb_interface *interface, return retval; } -#ifdef CONFIG_VIDEO_AU0828_V4L2 - dev->v4l2_dev.release = au0828_usb_v4l2_release; - - /* Create the v4l2_device */ -#ifdef CONFIG_MEDIA_CONTROLLER - dev->v4l2_dev.mdev = dev->media_dev; -#endif - retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); + retval = au0828_v4l2_device_register(interface, dev); if (retval) { - pr_err("%s() v4l2_device_register failed\n", - __func__); + au0828_usb_v4l2_media_release(dev); mutex_unlock(&dev->lock); kfree(dev); return retval; } - /* This control handler will inherit the controls from au8522 */ - retval = v4l2_ctrl_handler_init(&dev->v4l2_ctrl_hdl, 4); - if (retval) { - pr_err("%s() v4l2_ctrl_handler_init failed\n", - __func__); - mutex_unlock(&dev->lock); - kfree(dev); - return retval; - } - dev->v4l2_dev.ctrl_handler = &dev->v4l2_ctrl_hdl; -#endif /* Power Up the bridge */ au0828_write(dev, REG_600, 1 << 4); @@ -417,24 +289,13 @@ static int au0828_usb_probe(struct usb_interface *interface, /* Setup */ au0828_card_setup(dev); -#ifdef CONFIG_VIDEO_AU0828_V4L2 /* Analog TV */ - if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) { - retval = au0828_analog_register(dev, interface); - if (retval) { - pr_err("%s() au0282_dev_register failed to register on V4L2\n", - __func__); - goto done; - } - - retval = au0828_create_media_graph(dev); - if (retval) { - pr_err("%s() au0282_dev_register failed to create graph\n", - __func__); - goto done; - } + retval = au0828_analog_register(dev, interface); + if (retval) { + pr_err("%s() au0282_dev_register failed to register on V4L2\n", + __func__); + goto done; } -#endif /* Digital TV */ retval = au0828_dvb_register(dev); diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 8c54fd21022e..4164302dd8ac 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -638,6 +638,144 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) return rc; } +void au0828_usb_v4l2_media_release(struct au0828_dev *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + int i; + + for (i = 0; i < AU0828_MAX_INPUT; i++) { + if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) + return; + media_device_unregister_entity(&dev->input_ent[i]); + } +#endif +} + +static int au0828_create_media_graph(struct au0828_dev *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *mdev = dev->media_dev; + struct media_entity *entity; + struct media_entity *tuner = NULL, *decoder = NULL; + int i, ret; + + if (!mdev) + return 0; + + media_device_for_each_entity(entity, mdev) { + switch (entity->function) { + case MEDIA_ENT_F_TUNER: + tuner = entity; + break; + case MEDIA_ENT_F_ATV_DECODER: + decoder = entity; + break; + } + } + + /* Analog setup, using tuner as a link */ + + /* Something bad happened! */ + if (!decoder) + return -EINVAL; + + if (tuner) { + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, + decoder, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + ret = media_create_pad_link(decoder, 1, &dev->vdev.entity, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + ret = media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + + for (i = 0; i < AU0828_MAX_INPUT; i++) { + struct media_entity *ent = &dev->input_ent[i]; + + if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED) + break; + + switch (AUVI_INPUT(i).type) { + case AU0828_VMUX_CABLE: + case AU0828_VMUX_TELEVISION: + case AU0828_VMUX_DVB: + if (!tuner) + break; + + ret = media_create_pad_link(ent, 0, tuner, + TUNER_PAD_RF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + break; + case AU0828_VMUX_COMPOSITE: + case AU0828_VMUX_SVIDEO: + default: /* AU0828_VMUX_DEBUG */ + /* FIXME: fix the decoder PAD */ + ret = media_create_pad_link(ent, 0, decoder, 0, 0); + if (ret) + return ret; + break; + } + } +#endif + return 0; +} + +static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev) +{ + struct au0828_dev *dev = + container_of(v4l2_dev, struct au0828_dev, v4l2_dev); + + v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl); + v4l2_device_unregister(&dev->v4l2_dev); + au0828_usb_v4l2_media_release(dev); + au0828_usb_release(dev); +} + +int au0828_v4l2_device_register(struct usb_interface *interface, + struct au0828_dev *dev) +{ + int retval; + + if (AUVI_INPUT(0).type == AU0828_VMUX_UNDEFINED) + return 0; + + /* Create the v4l2_device */ +#ifdef CONFIG_MEDIA_CONTROLLER + dev->v4l2_dev.mdev = dev->media_dev; +#endif + retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); + if (retval) { + pr_err("%s() v4l2_device_register failed\n", + __func__); + mutex_unlock(&dev->lock); + kfree(dev); + return retval; + } + + dev->v4l2_dev.release = au0828_usb_v4l2_release; + + /* This control handler will inherit the controls from au8522 */ + retval = v4l2_ctrl_handler_init(&dev->v4l2_ctrl_hdl, 4); + if (retval) { + pr_err("%s() v4l2_ctrl_handler_init failed\n", + __func__); + mutex_unlock(&dev->lock); + kfree(dev); + return retval; + } + dev->v4l2_dev.ctrl_handler = &dev->v4l2_ctrl_hdl; + + return 0; +} + static int au0828_enable_analog_tuner(struct au0828_dev *dev) { #ifdef CONFIG_MEDIA_CONTROLLER @@ -949,13 +1087,23 @@ static struct vb2_ops au0828_video_qops = { * au0828_analog_unregister * unregister v4l2 devices */ -void au0828_analog_unregister(struct au0828_dev *dev) +int au0828_analog_unregister(struct au0828_dev *dev) { dprintk(1, "au0828_analog_unregister called\n"); + + /* No analog TV */ + if (AUVI_INPUT(0).type == AU0828_VMUX_UNDEFINED) + return 0; + mutex_lock(&au0828_sysfs_lock); video_unregister_device(&dev->vdev); video_unregister_device(&dev->vbi_dev); mutex_unlock(&au0828_sysfs_lock); + + v4l2_device_disconnect(&dev->v4l2_dev); + v4l2_device_put(&dev->v4l2_dev); + + return 1; } /* This function ensures that video frames continue to be delivered even if @@ -1871,6 +2019,10 @@ int au0828_analog_register(struct au0828_dev *dev, dprintk(1, "au0828_analog_register called for intf#%d!\n", interface->cur_altsetting->desc.bInterfaceNumber); + /* No analog TV */ + if (AUVI_INPUT(0).type == AU0828_VMUX_UNDEFINED) + return 0; + /* set au0828 usb interface0 to as5 */ retval = usb_set_interface(dev->usbdev, interface->cur_altsetting->desc.bInterfaceNumber, 5); @@ -1976,6 +2128,14 @@ int au0828_analog_register(struct au0828_dev *dev, ret = -ENODEV; goto err_reg_vbi_dev; } + retval = au0828_create_media_graph(dev); + if (retval) { + pr_err("%s() au0282_dev_register failed to create graph\n", + __func__); + ret = -ENODEV; + goto err_reg_vbi_dev; + } + dprintk(1, "%s completed!\n", __func__); diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h index 8276072bc55a..19fd6a841988 100644 --- a/drivers/media/usb/au0828/au0828.h +++ b/drivers/media/usb/au0828/au0828.h @@ -301,6 +301,7 @@ struct au0828_dev { /* au0828-core.c */ extern u32 au0828_read(struct au0828_dev *dev, u16 reg); extern u32 au0828_write(struct au0828_dev *dev, u16 reg, u32 val); +extern void au0828_usb_release(struct au0828_dev *dev); extern int au0828_debug; /* ----------------------------------------------------------- */ @@ -319,16 +320,29 @@ extern int au0828_i2c_unregister(struct au0828_dev *dev); /* ----------------------------------------------------------- */ /* au0828-video.c */ -extern int au0828_analog_register(struct au0828_dev *dev, - struct usb_interface *interface); -extern void au0828_analog_unregister(struct au0828_dev *dev); extern int au0828_start_analog_streaming(struct vb2_queue *vq, unsigned int count); extern void au0828_stop_vbi_streaming(struct vb2_queue *vq); #ifdef CONFIG_VIDEO_AU0828_V4L2 +extern int au0828_v4l2_device_register(struct usb_interface *interface, + struct au0828_dev *dev); + +extern int au0828_analog_register(struct au0828_dev *dev, + struct usb_interface *interface); +extern int au0828_analog_unregister(struct au0828_dev *dev); +extern void au0828_usb_v4l2_media_release(struct au0828_dev *dev); extern void au0828_v4l2_suspend(struct au0828_dev *dev); extern void au0828_v4l2_resume(struct au0828_dev *dev); #else +static inline int au0828_v4l2_device_register(struct usb_interface *interface, + struct au0828_dev *dev) +{ return 0; }; +static inline int au0828_analog_register(struct au0828_dev *dev, + struct usb_interface *interface) +{ return 0; }; +static inline int au0828_analog_unregister(struct au0828_dev *dev) +{ return 0; }; +static inline void au0828_usb_v4l2_media_release(struct au0828_dev *dev) { }; static inline void au0828_v4l2_suspend(struct au0828_dev *dev) { }; static inline void au0828_v4l2_resume(struct au0828_dev *dev) { }; #endif -- cgit v1.2.3 From aaa5672052cb0f18a5ab0ab19e9ef71c50e018a8 Mon Sep 17 00:00:00 2001 From: Jean Sacren Date: Tue, 9 Feb 2016 20:47:17 -0700 Subject: sxgbe: remove unused code Remove the unused code of sxgbe_xpcs. Reported-by: Julia Lawall Suggested-by: David S. Miller Signed-off-by: Jean Sacren Cc: Byungho An Cc: Girish K S Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1601191918470.2531@hadrien Signed-off-by: David S. Miller --- drivers/net/ethernet/samsung/sxgbe/Makefile | 2 +- drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.c | 91 ------------------------- drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.h | 38 ----------- 3 files changed, 1 insertion(+), 130 deletions(-) delete mode 100644 drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.c delete mode 100644 drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.h (limited to 'drivers') diff --git a/drivers/net/ethernet/samsung/sxgbe/Makefile b/drivers/net/ethernet/samsung/sxgbe/Makefile index dcc80b9d4370..31e968561d5c 100644 --- a/drivers/net/ethernet/samsung/sxgbe/Makefile +++ b/drivers/net/ethernet/samsung/sxgbe/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_SXGBE_ETH) += samsung-sxgbe.o samsung-sxgbe-objs:= sxgbe_platform.o sxgbe_main.o sxgbe_desc.o \ sxgbe_dma.o sxgbe_core.o sxgbe_mtl.o sxgbe_mdio.o \ - sxgbe_ethtool.o sxgbe_xpcs.o $(samsung-sxgbe-y) + sxgbe_ethtool.o $(samsung-sxgbe-y) diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.c deleted file mode 100644 index 51c32194ba88..000000000000 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.c +++ /dev/null @@ -1,91 +0,0 @@ -/* 10G controller driver for Samsung SoCs - * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Author: Siva Reddy Kallam - * - * 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 -#include -#include -#include -#include "sxgbe_common.h" -#include "sxgbe_xpcs.h" - -static int sxgbe_xpcs_read(struct net_device *ndev, unsigned int reg) -{ - u32 value; - struct sxgbe_priv_data *priv = netdev_priv(ndev); - - value = readl(priv->ioaddr + XPCS_OFFSET + reg); - - return value; -} - -static int sxgbe_xpcs_write(struct net_device *ndev, int reg, int data) -{ - struct sxgbe_priv_data *priv = netdev_priv(ndev); - - writel(data, priv->ioaddr + XPCS_OFFSET + reg); - - return 0; -} - -int sxgbe_xpcs_init(struct net_device *ndev) -{ - u32 value; - - value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1); - /* 10G XAUI mode */ - sxgbe_xpcs_write(ndev, SR_PCS_CONTROL2, XPCS_TYPE_SEL_X); - sxgbe_xpcs_write(ndev, VR_PCS_MMD_XAUI_MODE_CONTROL, XPCS_XAUI_MODE); - sxgbe_xpcs_write(ndev, VR_PCS_MMD_XAUI_MODE_CONTROL, value | BIT(13)); - sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value | BIT(11)); - - do { - value = sxgbe_xpcs_read(ndev, VR_PCS_MMD_DIGITAL_STATUS); - } while ((value & XPCS_QSEQ_STATE_MPLLOFF) == XPCS_QSEQ_STATE_STABLE); - - value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1); - sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value & ~BIT(11)); - - do { - value = sxgbe_xpcs_read(ndev, VR_PCS_MMD_DIGITAL_STATUS); - } while ((value & XPCS_QSEQ_STATE_MPLLOFF) != XPCS_QSEQ_STATE_STABLE); - - return 0; -} - -int sxgbe_xpcs_init_1G(struct net_device *ndev) -{ - int value; - - /* 10GBASE-X PCS (1G) mode */ - sxgbe_xpcs_write(ndev, SR_PCS_CONTROL2, XPCS_TYPE_SEL_X); - sxgbe_xpcs_write(ndev, VR_PCS_MMD_XAUI_MODE_CONTROL, XPCS_XAUI_MODE); - value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1); - sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value & ~BIT(13)); - - value = sxgbe_xpcs_read(ndev, SR_MII_MMD_CONTROL); - sxgbe_xpcs_write(ndev, SR_MII_MMD_CONTROL, value | BIT(6)); - sxgbe_xpcs_write(ndev, SR_MII_MMD_CONTROL, value & ~BIT(13)); - value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1); - sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value | BIT(11)); - - do { - value = sxgbe_xpcs_read(ndev, VR_PCS_MMD_DIGITAL_STATUS); - } while ((value & XPCS_QSEQ_STATE_MPLLOFF) != XPCS_QSEQ_STATE_STABLE); - - value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1); - sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value & ~BIT(11)); - - /* Auto Negotiation cluase 37 enable */ - value = sxgbe_xpcs_read(ndev, SR_MII_MMD_CONTROL); - sxgbe_xpcs_write(ndev, SR_MII_MMD_CONTROL, value | BIT(12)); - - return 0; -} diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.h deleted file mode 100644 index 6b26a50724d3..000000000000 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.h +++ /dev/null @@ -1,38 +0,0 @@ -/* 10G controller driver for Samsung SoCs - * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Author: Byungho An - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef __SXGBE_XPCS_H__ -#define __SXGBE_XPCS_H__ - -/* XPCS Registers */ -#define XPCS_OFFSET 0x1A060000 -#define SR_PCS_MMD_CONTROL1 0x030000 -#define SR_PCS_CONTROL2 0x030007 -#define VR_PCS_MMD_XAUI_MODE_CONTROL 0x038004 -#define VR_PCS_MMD_DIGITAL_STATUS 0x038010 -#define SR_MII_MMD_CONTROL 0x1F0000 -#define SR_MII_MMD_AN_ADV 0x1F0004 -#define SR_MII_MMD_AN_LINK_PARTNER_BA 0x1F0005 -#define VR_MII_MMD_AN_CONTROL 0x1F8001 -#define VR_MII_MMD_AN_INT_STATUS 0x1F8002 - -#define XPCS_QSEQ_STATE_STABLE 0x10 -#define XPCS_QSEQ_STATE_MPLLOFF 0x1c -#define XPCS_TYPE_SEL_R 0x00 -#define XPCS_TYPE_SEL_X 0x01 -#define XPCS_TYPE_SEL_W 0x02 -#define XPCS_XAUI_MODE 0x00 -#define XPCS_RXAUI_MODE 0x01 - -int sxgbe_xpcs_init(struct net_device *ndev); -int sxgbe_xpcs_init_1G(struct net_device *ndev); - -#endif /* __SXGBE_XPCS_H__ */ -- cgit v1.2.3 From 4f388a9210e2a2c1cd83a5580b74aa13876dbf14 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 5 Feb 2016 11:52:00 -0200 Subject: [media] media: davinci_vpfe: fix missing unlock on error in vpfe_prepare_pipeline() Add the missing unlock before return from function vpfe_prepare_pipeline() in the error handling case. video->lock is lock/unlock in function vpfe_open(), and no need to unlock it here, so remove unlock video->lock. Signed-off-by: Wei Yongjun Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/davinci_vpfe/vpfe_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index 3ec7e65a3ffa..db49af90217e 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c @@ -147,7 +147,7 @@ static int vpfe_prepare_pipeline(struct vpfe_video_device *video) mutex_lock(&mdev->graph_mutex); ret = media_entity_graph_walk_init(&graph, entity->graph_obj.mdev); if (ret) { - mutex_unlock(&video->lock); + mutex_unlock(&mdev->graph_mutex); return -ENOMEM; } media_entity_graph_walk_start(&graph, entity); -- cgit v1.2.3 From b888d232142c0ac111c7e82d1731c6fbd56fc1fe Mon Sep 17 00:00:00 2001 From: Anton Protopopov Date: Sun, 7 Feb 2016 02:27:32 -0200 Subject: [media] media: i2c/adp1653: probe: fix erroneous return value The adp1653_probe() function may return positive value EINVAL which is obviously wrong. Signed-off-by: Anton Protopopov Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adp1653.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c index 7e9cbf757e95..fb7ed730d932 100644 --- a/drivers/media/i2c/adp1653.c +++ b/drivers/media/i2c/adp1653.c @@ -497,7 +497,7 @@ static int adp1653_probe(struct i2c_client *client, if (!client->dev.platform_data) { dev_err(&client->dev, "Neither DT not platform data provided\n"); - return EINVAL; + return -EINVAL; } flash->platform_data = client->dev.platform_data; } -- cgit v1.2.3 From e295b3d603fb02aaf602e5edc846647688df8301 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 19 Jan 2016 09:12:48 -0200 Subject: [media] V4L: ov9650: fix control clusters Auto-gain and auto-exposure clusters in the ov9650 driver have both a size of 2, not 3 controls. Fix this. Signed-off-by: Guennadi Liakhovetski Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov9650.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c index a0b3c9bde53d..be5a7fd4f076 100644 --- a/drivers/media/i2c/ov9650.c +++ b/drivers/media/i2c/ov9650.c @@ -1046,8 +1046,8 @@ static int ov965x_initialize_controls(struct ov965x *ov965x) ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE; v4l2_ctrl_auto_cluster(3, &ctrls->auto_wb, 0, false); - v4l2_ctrl_auto_cluster(3, &ctrls->auto_gain, 0, true); - v4l2_ctrl_auto_cluster(3, &ctrls->auto_exp, 1, true); + v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true); + v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true); v4l2_ctrl_cluster(2, &ctrls->hflip); ov965x->sd.ctrl_handler = hdl; -- cgit v1.2.3 From b292394d4f1909ecad42150bf8782c3000d101b7 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Tue, 26 Jan 2016 16:39:14 -0200 Subject: [media] media: platform: vivid: vivid-osd: Remove unnecessary cast to kfree Remove an unnecassary cast in the argument to kfree. Found using Coccinelle. The semantic patch used to find this is as follows: // @@ type T; expression *f; @@ - kfree((T *)(f)); + kfree(f); // Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-osd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/platform/vivid/vivid-osd.c b/drivers/media/platform/vivid/vivid-osd.c index e15eef6a94e5..bdc380b14e0c 100644 --- a/drivers/media/platform/vivid/vivid-osd.c +++ b/drivers/media/platform/vivid/vivid-osd.c @@ -360,7 +360,7 @@ void vivid_fb_release_buffers(struct vivid_dev *dev) /* Release pseudo palette */ kfree(dev->fb_info.pseudo_palette); - kfree((void *)dev->video_vbase); + kfree(dev->video_vbase); } /* Initialize the specified card */ -- cgit v1.2.3 From bd3e275f3ec095eccc3b3c655b83e1b577848f92 Mon Sep 17 00:00:00 2001 From: Jean-Michel Hautbois Date: Wed, 27 Jan 2016 09:04:50 -0200 Subject: [media] media: i2c: adv7604: Use v4l2-dv-timings helpers Use the helper to enumerate and set DV timings instead of a custom code. This will ease debugging too, as it is consistent with other drivers. Signed-off-by: Jean-Michel Hautbois Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 178 ++++++++++++++++---------------------------- 1 file changed, 65 insertions(+), 113 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 801a9b09d5e5..e427cacde527 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -207,71 +207,22 @@ static bool adv76xx_has_afe(struct adv76xx_state *state) return state->info->has_afe; } -/* Supported CEA and DMT timings */ -static const struct v4l2_dv_timings adv76xx_timings[] = { - V4L2_DV_BT_CEA_720X480P59_94, - V4L2_DV_BT_CEA_720X576P50, - V4L2_DV_BT_CEA_1280X720P24, - V4L2_DV_BT_CEA_1280X720P25, - V4L2_DV_BT_CEA_1280X720P50, - V4L2_DV_BT_CEA_1280X720P60, - V4L2_DV_BT_CEA_1920X1080P24, - V4L2_DV_BT_CEA_1920X1080P25, - V4L2_DV_BT_CEA_1920X1080P30, - V4L2_DV_BT_CEA_1920X1080P50, - V4L2_DV_BT_CEA_1920X1080P60, - - /* sorted by DMT ID */ - V4L2_DV_BT_DMT_640X350P85, - V4L2_DV_BT_DMT_640X400P85, - V4L2_DV_BT_DMT_720X400P85, - V4L2_DV_BT_DMT_640X480P60, - V4L2_DV_BT_DMT_640X480P72, - V4L2_DV_BT_DMT_640X480P75, - V4L2_DV_BT_DMT_640X480P85, - V4L2_DV_BT_DMT_800X600P56, - V4L2_DV_BT_DMT_800X600P60, - V4L2_DV_BT_DMT_800X600P72, - V4L2_DV_BT_DMT_800X600P75, - V4L2_DV_BT_DMT_800X600P85, - V4L2_DV_BT_DMT_848X480P60, - V4L2_DV_BT_DMT_1024X768P60, - V4L2_DV_BT_DMT_1024X768P70, - V4L2_DV_BT_DMT_1024X768P75, - V4L2_DV_BT_DMT_1024X768P85, - V4L2_DV_BT_DMT_1152X864P75, - V4L2_DV_BT_DMT_1280X768P60_RB, - V4L2_DV_BT_DMT_1280X768P60, - V4L2_DV_BT_DMT_1280X768P75, - V4L2_DV_BT_DMT_1280X768P85, - V4L2_DV_BT_DMT_1280X800P60_RB, - V4L2_DV_BT_DMT_1280X800P60, - V4L2_DV_BT_DMT_1280X800P75, - V4L2_DV_BT_DMT_1280X800P85, - V4L2_DV_BT_DMT_1280X960P60, - V4L2_DV_BT_DMT_1280X960P85, - V4L2_DV_BT_DMT_1280X1024P60, - V4L2_DV_BT_DMT_1280X1024P75, - V4L2_DV_BT_DMT_1280X1024P85, - V4L2_DV_BT_DMT_1360X768P60, - V4L2_DV_BT_DMT_1400X1050P60_RB, - V4L2_DV_BT_DMT_1400X1050P60, - V4L2_DV_BT_DMT_1400X1050P75, - V4L2_DV_BT_DMT_1400X1050P85, - V4L2_DV_BT_DMT_1440X900P60_RB, - V4L2_DV_BT_DMT_1440X900P60, - V4L2_DV_BT_DMT_1600X1200P60, - V4L2_DV_BT_DMT_1680X1050P60_RB, - V4L2_DV_BT_DMT_1680X1050P60, - V4L2_DV_BT_DMT_1792X1344P60, - V4L2_DV_BT_DMT_1856X1392P60, - V4L2_DV_BT_DMT_1920X1200P60_RB, - V4L2_DV_BT_DMT_1366X768P60_RB, - V4L2_DV_BT_DMT_1366X768P60, - V4L2_DV_BT_DMT_1920X1080P60, - { }, +/* Unsupported timings. This device cannot support 720p30. */ +static const struct v4l2_dv_timings adv76xx_timings_exceptions[] = { + V4L2_DV_BT_CEA_1280X720P30, + { } }; +static bool adv76xx_check_dv_timings(const struct v4l2_dv_timings *t, void *hdl) +{ + int i; + + for (i = 0; adv76xx_timings_exceptions[i].bt.width; i++) + if (v4l2_match_dv_timings(t, adv76xx_timings_exceptions + i, 0, false)) + return false; + return true; +} + struct adv76xx_video_standards { struct v4l2_dv_timings timings; u8 vid_std; @@ -806,6 +757,36 @@ static inline bool is_digital_input(struct v4l2_subdev *sd) state->selected_input == ADV7604_PAD_HDMI_PORT_D; } +static const struct v4l2_dv_timings_cap adv7604_timings_cap_analog = { + .type = V4L2_DV_BT_656_1120, + /* keep this initialization for compatibility with GCC < 4.4.6 */ + .reserved = { 0 }, + V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 170000000, + V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | + V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, + V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING | + V4L2_DV_BT_CAP_CUSTOM) +}; + +static const struct v4l2_dv_timings_cap adv76xx_timings_cap_digital = { + .type = V4L2_DV_BT_656_1120, + /* keep this initialization for compatibility with GCC < 4.4.6 */ + .reserved = { 0 }, + V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 225000000, + V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | + V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, + V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING | + V4L2_DV_BT_CAP_CUSTOM) +}; + +static inline const struct v4l2_dv_timings_cap * +adv76xx_get_dv_timings_cap(struct v4l2_subdev *sd) +{ + return is_digital_input(sd) ? &adv76xx_timings_cap_digital : + &adv7604_timings_cap_analog; +} + + /* ----------------------------------------------------------------------- */ #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -1330,17 +1311,23 @@ static int stdi2dv_timings(struct v4l2_subdev *sd, u32 pix_clk; int i; - for (i = 0; adv76xx_timings[i].bt.height; i++) { - if (vtotal(&adv76xx_timings[i].bt) != stdi->lcf + 1) + for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) { + const struct v4l2_bt_timings *bt = &v4l2_dv_timings_presets[i].bt; + + if (!v4l2_valid_dv_timings(&v4l2_dv_timings_presets[i], + adv76xx_get_dv_timings_cap(sd), + adv76xx_check_dv_timings, NULL)) + continue; + if (vtotal(bt) != stdi->lcf + 1) continue; - if (adv76xx_timings[i].bt.vsync != stdi->lcvs) + if (bt->vsync != stdi->lcvs) continue; - pix_clk = hfreq * htotal(&adv76xx_timings[i].bt); + pix_clk = hfreq * htotal(bt); - if ((pix_clk < adv76xx_timings[i].bt.pixelclock + 1000000) && - (pix_clk > adv76xx_timings[i].bt.pixelclock - 1000000)) { - *timings = adv76xx_timings[i]; + if ((pix_clk < bt->pixelclock + 1000000) && + (pix_clk > bt->pixelclock - 1000000)) { + *timings = v4l2_dv_timings_presets[i]; return 0; } } @@ -1425,15 +1412,11 @@ static int adv76xx_enum_dv_timings(struct v4l2_subdev *sd, { struct adv76xx_state *state = to_state(sd); - if (timings->index >= ARRAY_SIZE(adv76xx_timings) - 1) - return -EINVAL; - if (timings->pad >= state->source_pad) return -EINVAL; - memset(timings->reserved, 0, sizeof(timings->reserved)); - timings->timings = adv76xx_timings[timings->index]; - return 0; + return v4l2_enum_dv_timings_cap(timings, + adv76xx_get_dv_timings_cap(sd), adv76xx_check_dv_timings, NULL); } static int adv76xx_dv_timings_cap(struct v4l2_subdev *sd, @@ -1444,29 +1427,7 @@ static int adv76xx_dv_timings_cap(struct v4l2_subdev *sd, if (cap->pad >= state->source_pad) return -EINVAL; - cap->type = V4L2_DV_BT_656_1120; - cap->bt.max_width = 1920; - cap->bt.max_height = 1200; - cap->bt.min_pixelclock = 25000000; - - switch (cap->pad) { - case ADV76XX_PAD_HDMI_PORT_A: - case ADV7604_PAD_HDMI_PORT_B: - case ADV7604_PAD_HDMI_PORT_C: - case ADV7604_PAD_HDMI_PORT_D: - cap->bt.max_pixelclock = 225000000; - break; - case ADV7604_PAD_VGA_RGB: - case ADV7604_PAD_VGA_COMP: - default: - cap->bt.max_pixelclock = 170000000; - break; - } - - cap->bt.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | - V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT; - cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | - V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM; + *cap = *adv76xx_get_dv_timings_cap(sd); return 0; } @@ -1475,15 +1436,9 @@ static int adv76xx_dv_timings_cap(struct v4l2_subdev *sd, static void adv76xx_fill_optional_dv_timings_fields(struct v4l2_subdev *sd, struct v4l2_dv_timings *timings) { - int i; - - for (i = 0; adv76xx_timings[i].bt.width; i++) { - if (v4l2_match_dv_timings(timings, &adv76xx_timings[i], - is_digital_input(sd) ? 250000 : 1000000, false)) { - *timings = adv76xx_timings[i]; - break; - } - } + v4l2_find_dv_timings_cap(timings, adv76xx_get_dv_timings_cap(sd), + is_digital_input(sd) ? 250000 : 1000000, + adv76xx_check_dv_timings, NULL); } static unsigned int adv7604_read_hdmi_pixelclock(struct v4l2_subdev *sd) @@ -1651,12 +1606,9 @@ static int adv76xx_s_dv_timings(struct v4l2_subdev *sd, bt = &timings->bt; - if ((is_analog_input(sd) && bt->pixelclock > 170000000) || - (is_digital_input(sd) && bt->pixelclock > 225000000)) { - v4l2_dbg(1, debug, sd, "%s: pixelclock out of range %d\n", - __func__, (u32)bt->pixelclock); + if (!v4l2_valid_dv_timings(timings, adv76xx_get_dv_timings_cap(sd), + adv76xx_check_dv_timings, NULL)) return -ERANGE; - } adv76xx_fill_optional_dv_timings_fields(sd, timings); -- cgit v1.2.3 From 45cc29afb47f229014257068a3153276b2fb4c38 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 27 Jan 2016 11:31:39 -0200 Subject: [media] v4l2-ctrls: add V4L2_CID_DV_RX/TX_IT_CONTENT_TYPE controls HDMI and DisplayPort both support IT Content Type information that tells the receiver what type of material the video is, graphics such as from a PC desktop, Photo, Cinema or Game (low-latency). This patch adds controls for receivers and transmitters to get/set this information. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ctrls.c | 16 ++++++++++++++++ include/uapi/linux/v4l2-controls.h | 10 ++++++++++ 2 files changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index c9d5537b6af7..bed04b1fdd0a 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -462,6 +462,14 @@ const char * const *v4l2_ctrl_get_menu(u32 id) "RGB full range (0-255)", NULL, }; + static const char * const dv_it_content_type[] = { + "Graphics", + "Photo", + "Cinema", + "Game", + "No IT Content", + NULL, + }; static const char * const detect_md_mode[] = { "Disabled", "Global", @@ -560,6 +568,9 @@ const char * const *v4l2_ctrl_get_menu(u32 id) case V4L2_CID_DV_TX_RGB_RANGE: case V4L2_CID_DV_RX_RGB_RANGE: return dv_rgb_range; + case V4L2_CID_DV_TX_IT_CONTENT_TYPE: + case V4L2_CID_DV_RX_IT_CONTENT_TYPE: + return dv_it_content_type; case V4L2_CID_DETECT_MD_MODE: return detect_md_mode; @@ -881,8 +892,10 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_DV_TX_EDID_PRESENT: return "EDID Present"; case V4L2_CID_DV_TX_MODE: return "Transmit Mode"; case V4L2_CID_DV_TX_RGB_RANGE: return "Tx RGB Quantization Range"; + case V4L2_CID_DV_TX_IT_CONTENT_TYPE: return "Tx IT Content Type"; case V4L2_CID_DV_RX_POWER_PRESENT: return "Power Present"; case V4L2_CID_DV_RX_RGB_RANGE: return "Rx RGB Quantization Range"; + case V4L2_CID_DV_RX_IT_CONTENT_TYPE: return "Rx IT Content Type"; case V4L2_CID_FM_RX_CLASS: return "FM Radio Receiver Controls"; case V4L2_CID_TUNE_DEEMPHASIS: return "De-Emphasis"; @@ -1038,7 +1051,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_SCENE_MODE: case V4L2_CID_DV_TX_MODE: case V4L2_CID_DV_TX_RGB_RANGE: + case V4L2_CID_DV_TX_IT_CONTENT_TYPE: case V4L2_CID_DV_RX_RGB_RANGE: + case V4L2_CID_DV_RX_IT_CONTENT_TYPE: case V4L2_CID_TEST_PATTERN: case V4L2_CID_TUNE_DEEMPHASIS: case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: @@ -1185,6 +1200,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_DV_TX_RXSENSE: case V4L2_CID_DV_TX_EDID_PRESENT: case V4L2_CID_DV_RX_POWER_PRESENT: + case V4L2_CID_DV_RX_IT_CONTENT_TYPE: case V4L2_CID_RDS_RX_PTY: case V4L2_CID_RDS_RX_PS_NAME: case V4L2_CID_RDS_RX_RADIO_TEXT: diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 2d225bcdb831..2ae5c3ea179b 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -912,8 +912,18 @@ enum v4l2_dv_rgb_range { V4L2_DV_RGB_RANGE_FULL = 2, }; +#define V4L2_CID_DV_TX_IT_CONTENT_TYPE (V4L2_CID_DV_CLASS_BASE + 6) +enum v4l2_dv_it_content_type { + V4L2_DV_IT_CONTENT_TYPE_GRAPHICS = 0, + V4L2_DV_IT_CONTENT_TYPE_PHOTO = 1, + V4L2_DV_IT_CONTENT_TYPE_CINEMA = 2, + V4L2_DV_IT_CONTENT_TYPE_GAME = 3, + V4L2_DV_IT_CONTENT_TYPE_NO_ITC = 4, +}; + #define V4L2_CID_DV_RX_POWER_PRESENT (V4L2_CID_DV_CLASS_BASE + 100) #define V4L2_CID_DV_RX_RGB_RANGE (V4L2_CID_DV_CLASS_BASE + 101) +#define V4L2_CID_DV_RX_IT_CONTENT_TYPE (V4L2_CID_DV_CLASS_BASE + 102) #define V4L2_CID_FM_RX_CLASS_BASE (V4L2_CTRL_CLASS_FM_RX | 0x900) #define V4L2_CID_FM_RX_CLASS (V4L2_CTRL_CLASS_FM_RX | 1) -- cgit v1.2.3 From 297a41448a006def6b87aef5383837c3130a41e4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 27 Jan 2016 11:31:41 -0200 Subject: [media] adv7604: add support to for the content type control This receiver now supports reading the IT content type of the incoming video. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index e427cacde527..d35e0ba8b269 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -1197,6 +1197,20 @@ static int adv76xx_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } +static int adv76xx_g_volatile_ctrl(struct v4l2_ctrl *ctrl) +{ + struct v4l2_subdev *sd = + &container_of(ctrl->handler, struct adv76xx_state, hdl)->sd; + + if (ctrl->id == V4L2_CID_DV_RX_IT_CONTENT_TYPE) { + ctrl->val = V4L2_DV_IT_CONTENT_TYPE_NO_ITC; + if ((io_read(sd, 0x60) & 1) && (infoframe_read(sd, 0x03) & 0x80)) + ctrl->val = (infoframe_read(sd, 0x05) >> 4) & 3; + return 0; + } + return -EINVAL; +} + /* ----------------------------------------------------------------------- */ static inline bool no_power(struct v4l2_subdev *sd) @@ -2353,6 +2367,7 @@ static int adv76xx_subscribe_event(struct v4l2_subdev *sd, static const struct v4l2_ctrl_ops adv76xx_ctrl_ops = { .s_ctrl = adv76xx_s_ctrl, + .g_volatile_ctrl = adv76xx_g_volatile_ctrl, }; static const struct v4l2_subdev_core_ops adv76xx_core_ops = { @@ -2988,6 +3003,7 @@ static int adv76xx_probe(struct i2c_client *client, V4L2_DV_BT_CEA_640X480P59_94; struct adv76xx_state *state; struct v4l2_ctrl_handler *hdl; + struct v4l2_ctrl *ctrl; struct v4l2_subdev *sd; unsigned int i; unsigned int val, val2; @@ -3119,6 +3135,11 @@ static int adv76xx_probe(struct i2c_client *client, V4L2_CID_SATURATION, 0, 255, 1, 128); v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops, V4L2_CID_HUE, 0, 128, 1, 0); + ctrl = v4l2_ctrl_new_std_menu(hdl, &adv76xx_ctrl_ops, + V4L2_CID_DV_RX_IT_CONTENT_TYPE, V4L2_DV_IT_CONTENT_TYPE_NO_ITC, + 0, V4L2_DV_IT_CONTENT_TYPE_NO_ITC); + if (ctrl) + ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; /* private controls */ state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL, -- cgit v1.2.3 From e89792740d769cd30cc296289b00fb9ff7a762e8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 27 Jan 2016 11:31:42 -0200 Subject: [media] adv7842: add support to for the content type control This receiver now supports reading the IT content type of the incoming video. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7842.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index 5fbb788e7b59..7ccb85d45224 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -1359,6 +1359,19 @@ static int adv7842_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } +static int adv7842_g_volatile_ctrl(struct v4l2_ctrl *ctrl) +{ + struct v4l2_subdev *sd = to_sd(ctrl); + + if (ctrl->id == V4L2_CID_DV_RX_IT_CONTENT_TYPE) { + ctrl->val = V4L2_DV_IT_CONTENT_TYPE_NO_ITC; + if ((io_read(sd, 0x60) & 1) && (infoframe_read(sd, 0x03) & 0x80)) + ctrl->val = (infoframe_read(sd, 0x05) >> 4) & 3; + return 0; + } + return -EINVAL; +} + static inline bool no_power(struct v4l2_subdev *sd) { return io_read(sd, 0x0c) & 0x24; @@ -3022,6 +3035,7 @@ static int adv7842_subscribe_event(struct v4l2_subdev *sd, static const struct v4l2_ctrl_ops adv7842_ctrl_ops = { .s_ctrl = adv7842_s_ctrl, + .g_volatile_ctrl = adv7842_g_volatile_ctrl, }; static const struct v4l2_subdev_core_ops adv7842_core_ops = { @@ -3196,6 +3210,7 @@ static int adv7842_probe(struct i2c_client *client, V4L2_DV_BT_CEA_640X480P59_94; struct adv7842_platform_data *pdata = client->dev.platform_data; struct v4l2_ctrl_handler *hdl; + struct v4l2_ctrl *ctrl; struct v4l2_subdev *sd; u16 rev; int err; @@ -3261,6 +3276,11 @@ static int adv7842_probe(struct i2c_client *client, V4L2_CID_SATURATION, 0, 255, 1, 128); v4l2_ctrl_new_std(hdl, &adv7842_ctrl_ops, V4L2_CID_HUE, 0, 128, 1, 0); + ctrl = v4l2_ctrl_new_std_menu(hdl, &adv7842_ctrl_ops, + V4L2_CID_DV_RX_IT_CONTENT_TYPE, V4L2_DV_IT_CONTENT_TYPE_NO_ITC, + 0, V4L2_DV_IT_CONTENT_TYPE_NO_ITC); + if (ctrl) + ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; /* custom controls */ state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL, -- cgit v1.2.3 From df0e57754e29493bf9c53333ece7df172dd18a10 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 27 Jan 2016 11:31:43 -0200 Subject: [media] adv7511: add support to for the content type control This transmitter now supports configuring the IT content type of the incoming video. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7511.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c index 471fd23b5c5c..a9ed5337df2d 100644 --- a/drivers/media/i2c/adv7511.c +++ b/drivers/media/i2c/adv7511.c @@ -103,12 +103,14 @@ struct adv7511_state { u32 ycbcr_enc; u32 quantization; u32 xfer_func; + u32 content_type; /* controls */ struct v4l2_ctrl *hdmi_mode_ctrl; struct v4l2_ctrl *hotplug_ctrl; struct v4l2_ctrl *rx_sense_ctrl; struct v4l2_ctrl *have_edid0_ctrl; struct v4l2_ctrl *rgb_quantization_range_ctrl; + struct v4l2_ctrl *content_type_ctrl; struct i2c_client *i2c_edid; struct i2c_client *i2c_pktmem; struct adv7511_state_edid edid; @@ -400,6 +402,16 @@ static int adv7511_s_ctrl(struct v4l2_ctrl *ctrl) } if (state->rgb_quantization_range_ctrl == ctrl) return adv7511_set_rgb_quantization_mode(sd, ctrl); + if (state->content_type_ctrl == ctrl) { + u8 itc, cn; + + state->content_type = ctrl->val; + itc = state->content_type != V4L2_DV_IT_CONTENT_TYPE_NO_ITC; + cn = itc ? state->content_type : V4L2_DV_IT_CONTENT_TYPE_GRAPHICS; + adv7511_wr_and_or(sd, 0x57, 0x7f, itc << 7); + adv7511_wr_and_or(sd, 0x59, 0xcf, cn << 4); + return 0; + } return -EINVAL; } @@ -1002,6 +1014,8 @@ static int adv7511_set_fmt(struct v4l2_subdev *sd, u8 y = HDMI_COLORSPACE_RGB; u8 q = HDMI_QUANTIZATION_RANGE_DEFAULT; u8 yq = HDMI_YCC_QUANTIZATION_RANGE_LIMITED; + u8 itc = state->content_type != V4L2_DV_IT_CONTENT_TYPE_NO_ITC; + u8 cn = itc ? state->content_type : V4L2_DV_IT_CONTENT_TYPE_GRAPHICS; if (format->pad != 0) return -EINVAL; @@ -1115,8 +1129,8 @@ static int adv7511_set_fmt(struct v4l2_subdev *sd, adv7511_wr_and_or(sd, 0x4a, 0xbf, 0); adv7511_wr_and_or(sd, 0x55, 0x9f, y << 5); adv7511_wr_and_or(sd, 0x56, 0x3f, c << 6); - adv7511_wr_and_or(sd, 0x57, 0x83, (ec << 4) | (q << 2)); - adv7511_wr_and_or(sd, 0x59, 0x3f, yq << 6); + adv7511_wr_and_or(sd, 0x57, 0x83, (ec << 4) | (q << 2) | (itc << 7)); + adv7511_wr_and_or(sd, 0x59, 0x0f, (yq << 6) | (cn << 4)); adv7511_wr_and_or(sd, 0x4a, 0xff, 1); return 0; @@ -1470,6 +1484,10 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id * v4l2_ctrl_new_std_menu(hdl, &adv7511_ctrl_ops, V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, 0, V4L2_DV_RGB_RANGE_AUTO); + state->content_type_ctrl = + v4l2_ctrl_new_std_menu(hdl, &adv7511_ctrl_ops, + V4L2_CID_DV_TX_IT_CONTENT_TYPE, V4L2_DV_IT_CONTENT_TYPE_NO_ITC, + 0, V4L2_DV_IT_CONTENT_TYPE_NO_ITC); sd->ctrl_handler = hdl; if (hdl->error) { err = hdl->error; -- cgit v1.2.3 From 8ddc2dd0832e062bbb36e965e5a202a7d0b584a0 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Tue, 3 Nov 2015 21:50:23 -0200 Subject: [media] v4l2-ctrls: remove unclaimed v4l2_ctrl_add_ctrl() interface v4l2_ctrl_add_ctrl() interface has no users since its introduction in commit 0996517cf8ea ("V4L/DVB: v4l2: Add new control handling framework") and its functionality is covered by v4l2_ctrl_new() and derivative interfaces, so it is safe to remove the interface from the kernel. Signed-off-by: Vladimir Zapolskiy Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-controls.txt | 1 - drivers/media/v4l2-core/v4l2-ctrls.c | 16 ---------------- include/media/v4l2-ctrls.h | 12 ------------ 3 files changed, 29 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/v4l2-controls.txt b/Documentation/video4linux/v4l2-controls.txt index 5517db602f37..5e759cab4538 100644 --- a/Documentation/video4linux/v4l2-controls.txt +++ b/Documentation/video4linux/v4l2-controls.txt @@ -647,7 +647,6 @@ Or you can add specific controls to a handler: volume = v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_AUDIO_VOLUME, ...); v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_BRIGHTNESS, ...); v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_CONTRAST, ...); - v4l2_ctrl_add_ctrl(&radio_ctrl_handler, volume); What you should not do is make two identical controls for two handlers. For example: diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index bed04b1fdd0a..130e5badd599 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -2227,22 +2227,6 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, } EXPORT_SYMBOL(v4l2_ctrl_new_int_menu); -/* Add a control from another handler to this handler */ -struct v4l2_ctrl *v4l2_ctrl_add_ctrl(struct v4l2_ctrl_handler *hdl, - struct v4l2_ctrl *ctrl) -{ - if (hdl == NULL || hdl->error) - return NULL; - if (ctrl == NULL) { - handler_set_err(hdl, -EINVAL); - return NULL; - } - if (ctrl->handler == hdl) - return ctrl; - return handler_new_ref(hdl, ctrl) ? NULL : ctrl; -} -EXPORT_SYMBOL(v4l2_ctrl_add_ctrl); - /* Add the controls from another handler to our own. */ int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl, struct v4l2_ctrl_handler *add, diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index da6fe9802fee..0bc9b35b8f3e 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -534,18 +534,6 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, u8 max, u8 def, const s64 *qmenu_int); -/** - * v4l2_ctrl_add_ctrl() - Add a control from another handler to this handler. - * @hdl: The control handler. - * @ctrl: The control to add. - * - * It will return NULL if it was unable to add the control reference. - * If the control already belonged to the handler, then it will do - * nothing and just return @ctrl. - */ -struct v4l2_ctrl *v4l2_ctrl_add_ctrl(struct v4l2_ctrl_handler *hdl, - struct v4l2_ctrl *ctrl); - /** * v4l2_ctrl_add_handler() - Add all controls from handler @add to * handler @hdl. -- cgit v1.2.3 From 0e2a706b04c1d117c77ee47a41fd978afa25d67e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 18 Dec 2015 18:32:00 -0200 Subject: [media] tea575x: convert to library The module is used only as a library for now. Remove module init and exit routines to show this. While here, remove FSF snail address and attach EXPORT_SYMBOL() macros to corresponding functions. Signed-off-by: Andy Shevchenko Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/tea575x.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c index 3e08475af579..4dc2067bce14 100644 --- a/drivers/media/radio/tea575x.c +++ b/drivers/media/radio/tea575x.c @@ -14,10 +14,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * */ #include @@ -226,6 +222,7 @@ void snd_tea575x_set_freq(struct snd_tea575x *tea) snd_tea575x_write(tea, tea->val); tea->freq = snd_tea575x_val_to_freq(tea, tea->val); } +EXPORT_SYMBOL(snd_tea575x_set_freq); /* * Linux Video interface @@ -582,25 +579,11 @@ int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner) return 0; } +EXPORT_SYMBOL(snd_tea575x_init); void snd_tea575x_exit(struct snd_tea575x *tea) { video_unregister_device(&tea->vd); v4l2_ctrl_handler_free(tea->vd.ctrl_handler); } - -static int __init alsa_tea575x_module_init(void) -{ - return 0; -} - -static void __exit alsa_tea575x_module_exit(void) -{ -} - -module_init(alsa_tea575x_module_init) -module_exit(alsa_tea575x_module_exit) - -EXPORT_SYMBOL(snd_tea575x_init); EXPORT_SYMBOL(snd_tea575x_exit); -EXPORT_SYMBOL(snd_tea575x_set_freq); -- cgit v1.2.3 From 7c3e1ec1f772c1f740fce3180bf419018582977f Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:52 -0200 Subject: [media] v4l2-async: call registered_async after subdev registration V4L2 sub-devices might need to do initialization that depends on being registered with a V4L2 device. As an example, sub-devices with Media Controller support may need to register entities and create pad links. Execute the registered_async callback after the sub-device has been registered with the V4L2 device so the driver can do any needed init. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-async.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 5bada202b2d3..716bfd47daab 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -119,6 +119,13 @@ static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, return ret; } + ret = v4l2_subdev_call(sd, core, registered_async); + if (ret < 0) { + if (notifier->unbind) + notifier->unbind(notifier, sd, asd); + return ret; + } + if (list_empty(¬ifier->waiting) && notifier->complete) return notifier->complete(notifier); -- cgit v1.2.3 From 2bd5e4375aec8731c9818b2ac86ac035d3aebe86 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:53 -0200 Subject: [media] tvp5150: put endpoint node on error If the parallel mbus configuration is not correct, the endpoint device node isn't currently put again in the error path. Fix it. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 19b52736b24e..c7eeb59a999b 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1268,8 +1268,10 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL && !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH && flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH && - flags & V4L2_MBUS_FIELD_EVEN_LOW)) - return -EINVAL; + flags & V4L2_MBUS_FIELD_EVEN_LOW)) { + ret = -EINVAL; + goto err; + } decoder->mbus_type = bus_cfg.bus_type; -- cgit v1.2.3 From 82275133cc52e201e44de08a9471357fa2823b0c Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:54 -0200 Subject: [media] tvp5150: store dev id and rom version Not all tvp5150 variants support the same, for example some have an internal signal generator that can output a black screen. So the device id and rom version have to be stored in the driver's state to know what variant is a given device. While being there, remove some redundant comments about the device version since there is already calls to v4l2_info() with that info. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index c7eeb59a999b..093ff80f944c 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -49,6 +49,9 @@ struct tvp5150 { u32 output; int enable; + u16 dev_id; + u16 rom_ver; + enum v4l2_mbus_type mbus_type; }; @@ -1180,8 +1183,6 @@ static int tvp5150_detect_version(struct tvp5150 *core) struct v4l2_subdev *sd = &core->sd; struct i2c_client *c = v4l2_get_subdevdata(sd); unsigned int i; - u16 dev_id; - u16 rom_ver; u8 regs[4]; int res; @@ -1196,23 +1197,25 @@ static int tvp5150_detect_version(struct tvp5150 *core) regs[i] = res; } - dev_id = (regs[0] << 8) | regs[1]; - rom_ver = (regs[2] << 8) | regs[3]; + core->dev_id = (regs[0] << 8) | regs[1]; + core->rom_ver = (regs[2] << 8) | regs[3]; v4l2_info(sd, "tvp%04x (%u.%u) chip found @ 0x%02x (%s)\n", - dev_id, regs[2], regs[3], c->addr << 1, c->adapter->name); + core->dev_id, regs[2], regs[3], c->addr << 1, + c->adapter->name); - if (dev_id == 0x5150 && rom_ver == 0x0321) { /* TVP51510A */ + if (core->dev_id == 0x5150 && core->rom_ver == 0x0321) { v4l2_info(sd, "tvp5150a detected.\n"); - } else if (dev_id == 0x5150 && rom_ver == 0x0400) { /* TVP5150AM1 */ + } else if (core->dev_id == 0x5150 && core->rom_ver == 0x0400) { v4l2_info(sd, "tvp5150am1 detected.\n"); /* ITU-T BT.656.4 timing */ tvp5150_write(sd, TVP5150_REV_SELECT, 0); - } else if (dev_id == 0x5151 && rom_ver == 0x0100) { /* TVP5151 */ + } else if (core->dev_id == 0x5151 && core->rom_ver == 0x0100) { v4l2_info(sd, "tvp5151 detected.\n"); } else { - v4l2_info(sd, "*** unknown tvp%04x chip detected.\n", dev_id); + v4l2_info(sd, "*** unknown tvp%04x chip detected.\n", + core->dev_id); } return 0; -- cgit v1.2.3 From e0d64e6a880e64545ad7d55786aa84ab76bac475 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Mon, 8 Feb 2016 14:48:12 -0500 Subject: efi: Use ucs2_as_utf8 in efivarfs instead of open coding a bad version Translate EFI's UCS-2 variable names to UTF-8 instead of just assuming all variable names fit in ASCII. Signed-off-by: Peter Jones Acked-by: Matthew Garrett Tested-by: Lee, Chun-Yi Signed-off-by: Matt Fleming --- drivers/firmware/efi/efivars.c | 30 +++++++++++------------------- fs/efivarfs/super.c | 7 +++---- 2 files changed, 14 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c index 756eca8c4cf8..f4ff8abc5f3e 100644 --- a/drivers/firmware/efi/efivars.c +++ b/drivers/firmware/efi/efivars.c @@ -540,38 +540,30 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, static int efivar_create_sysfs_entry(struct efivar_entry *new_var) { - int i, short_name_size; + int short_name_size; char *short_name; - unsigned long variable_name_size; - efi_char16_t *variable_name; + unsigned long utf8_name_size; + efi_char16_t *variable_name = new_var->var.VariableName; int ret; - variable_name = new_var->var.VariableName; - variable_name_size = ucs2_strlen(variable_name) * sizeof(efi_char16_t); - /* - * Length of the variable bytes in ASCII, plus the '-' separator, + * Length of the variable bytes in UTF8, plus the '-' separator, * plus the GUID, plus trailing NUL */ - short_name_size = variable_name_size / sizeof(efi_char16_t) - + 1 + EFI_VARIABLE_GUID_LEN + 1; - - short_name = kzalloc(short_name_size, GFP_KERNEL); + utf8_name_size = ucs2_utf8size(variable_name); + short_name_size = utf8_name_size + 1 + EFI_VARIABLE_GUID_LEN + 1; + short_name = kmalloc(short_name_size, GFP_KERNEL); if (!short_name) return -ENOMEM; - /* Convert Unicode to normal chars (assume top bits are 0), - ala UTF-8 */ - for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) { - short_name[i] = variable_name[i] & 0xFF; - } + ucs2_as_utf8(short_name, variable_name, short_name_size); + /* This is ugly, but necessary to separate one vendor's private variables from another's. */ - - *(short_name + strlen(short_name)) = '-'; + short_name[utf8_name_size] = '-'; efi_guid_to_str(&new_var->var.VendorGuid, - short_name + strlen(short_name)); + short_name + utf8_name_size + 1); new_var->kobj.kset = efivars_kset; diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c index b8a564f29107..8651ac28ec0d 100644 --- a/fs/efivarfs/super.c +++ b/fs/efivarfs/super.c @@ -118,7 +118,7 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor, struct dentry *dentry, *root = sb->s_root; unsigned long size = 0; char *name; - int len, i; + int len; int err = -ENOMEM; entry = kzalloc(sizeof(*entry), GFP_KERNEL); @@ -128,15 +128,14 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor, memcpy(entry->var.VariableName, name16, name_size); memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t)); - len = ucs2_strlen(entry->var.VariableName); + len = ucs2_utf8size(entry->var.VariableName); /* name, plus '-', plus GUID, plus NUL*/ name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL); if (!name) goto fail; - for (i = 0; i < len; i++) - name[i] = entry->var.VariableName[i] & 0xFF; + ucs2_as_utf8(name, entry->var.VariableName, len); name[len] = '-'; -- cgit v1.2.3 From 4cacf91fcb1d7118e93caf9cb6651d7f7b56e58d Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 24 Feb 2015 11:34:01 +0100 Subject: drm: add drm_of_encoder_active_endpoint helpers This patch adds a helper to parse the encoder endpoint connected to the encoder's crtc and two helpers to return its id and port id. This can be used to determine input mux setting from endpoint or port ids. Suggested-by: Daniel Kurtz Reviewed-by: Daniel Kurtz Signed-off-by: Philipp Zabel --- drivers/gpu/drm/drm_of.c | 34 ++++++++++++++++++++++++++++++++++ include/drm/drm_of.h | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c index 493c05c9ce4f..bc98bb94264d 100644 --- a/drivers/gpu/drm/drm_of.c +++ b/drivers/gpu/drm/drm_of.c @@ -149,3 +149,37 @@ int drm_of_component_probe(struct device *dev, return component_master_add_with_match(dev, m_ops, match); } EXPORT_SYMBOL(drm_of_component_probe); + +/* + * drm_of_encoder_active_endpoint - return the active encoder endpoint + * @node: device tree node containing encoder input ports + * @encoder: drm_encoder + * + * Given an encoder device node and a drm_encoder with a connected crtc, + * parse the encoder endpoint connecting to the crtc port. + */ +int drm_of_encoder_active_endpoint(struct device_node *node, + struct drm_encoder *encoder, + struct of_endpoint *endpoint) +{ + struct device_node *ep; + struct drm_crtc *crtc = encoder->crtc; + struct device_node *port; + int ret; + + if (!node || !crtc) + return -EINVAL; + + for_each_endpoint_of_node(node, ep) { + port = of_graph_get_remote_port(ep); + of_node_put(port); + if (port == crtc->port) { + ret = of_graph_parse_endpoint(ep, endpoint); + of_node_put(ep); + return ret; + } + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint); diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h index 8544665ee4f4..3fd87b386ed7 100644 --- a/include/drm/drm_of.h +++ b/include/drm/drm_of.h @@ -1,9 +1,12 @@ #ifndef __DRM_OF_H__ #define __DRM_OF_H__ +#include + struct component_master_ops; struct device; struct drm_device; +struct drm_encoder; struct device_node; #ifdef CONFIG_OF @@ -12,6 +15,9 @@ extern uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, extern int drm_of_component_probe(struct device *dev, int (*compare_of)(struct device *, void *), const struct component_master_ops *m_ops); +extern int drm_of_encoder_active_endpoint(struct device_node *node, + struct drm_encoder *encoder, + struct of_endpoint *endpoint); #else static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, struct device_node *port) @@ -26,6 +32,33 @@ drm_of_component_probe(struct device *dev, { return -EINVAL; } + +static inline int drm_of_encoder_active_endpoint(struct device_node *node, + struct drm_encoder *encoder, + struct of_endpoint *endpoint) +{ + return -EINVAL; +} #endif +static inline int drm_of_encoder_active_endpoint_id(struct device_node *node, + struct drm_encoder *encoder) +{ + struct of_endpoint endpoint; + int ret = drm_of_encoder_active_endpoint(node, encoder, + &endpoint); + + return ret ?: endpoint.id; +} + +static inline int drm_of_encoder_active_port_id(struct device_node *node, + struct drm_encoder *encoder) +{ + struct of_endpoint endpoint; + int ret = drm_of_encoder_active_endpoint(node, encoder, + &endpoint); + + return ret ?: endpoint.port; +} + #endif /* __DRM_OF_H__ */ -- cgit v1.2.3 From 3dcb1f55dfc7631695e69df4a0d589ce5274bd07 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Mon, 8 Feb 2016 14:48:13 -0500 Subject: efi: Do variable name validation tests in utf8 Actually translate from ucs2 to utf8 before doing the test, and then test against our other utf8 data, instead of fudging it. Signed-off-by: Peter Jones Acked-by: Matthew Garrett Tested-by: Lee, Chun-Yi Signed-off-by: Matt Fleming --- drivers/firmware/efi/vars.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c index 70a0fb10517f..5c5fde3e6c37 100644 --- a/drivers/firmware/efi/vars.c +++ b/drivers/firmware/efi/vars.c @@ -189,10 +189,19 @@ static const struct variable_validate variable_validate[] = { }; bool -efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long len) +efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long data_size) { int i; - u16 *unicode_name = var_name; + unsigned long utf8_size; + u8 *utf8_name; + + utf8_size = ucs2_utf8size(var_name); + utf8_name = kmalloc(utf8_size + 1, GFP_KERNEL); + if (!utf8_name) + return false; + + ucs2_as_utf8(utf8_name, var_name, utf8_size); + utf8_name[utf8_size] = '\0'; for (i = 0; variable_validate[i].validate != NULL; i++) { const char *name = variable_validate[i].name; @@ -200,28 +209,29 @@ efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long len) for (match = 0; ; match++) { char c = name[match]; - u16 u = unicode_name[match]; - - /* All special variables are plain ascii */ - if (u > 127) - return true; + char u = utf8_name[match]; /* Wildcard in the matching name means we've matched */ - if (c == '*') + if (c == '*') { + kfree(utf8_name); return variable_validate[i].validate(var_name, - match, data, len); + match, data, data_size); + } /* Case sensitive match */ if (c != u) break; /* Reached the end of the string while matching */ - if (!c) + if (!c) { + kfree(utf8_name); return variable_validate[i].validate(var_name, - match, data, len); + match, data, data_size); + } } } + kfree(utf8_name); return true; } EXPORT_SYMBOL_GPL(efivar_validate); -- cgit v1.2.3 From 17e0521750399205f432966e602e125294879cdd Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 4 Jan 2016 17:32:26 +0100 Subject: gpu: ipu-v3: Do not bail out on missing optional port nodes The port nodes are documented as optional, treat them accordingly. Reported-by: Martin Fuzzey Reported-by: Chris Healy Signed-off-by: Philipp Zabel Fixes: 304e6be652e2 ("gpu: ipu-v3: Assign of_node of child platform devices to corresponding ports") --- drivers/gpu/ipu-v3/ipu-common.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index f2e13eb8339f..a0e28f3a278d 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c @@ -1050,6 +1050,17 @@ static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base) for (i = 0; i < ARRAY_SIZE(client_reg); i++) { const struct ipu_platform_reg *reg = &client_reg[i]; struct platform_device *pdev; + struct device_node *of_node; + + /* Associate subdevice with the corresponding port node */ + of_node = of_graph_get_port_by_id(dev->of_node, i); + if (!of_node) { + dev_info(dev, + "no port@%d node in %s, not using %s%d\n", + i, dev->of_node->full_name, + (i / 2) ? "DI" : "CSI", i % 2); + continue; + } pdev = platform_device_alloc(reg->name, id++); if (!pdev) { @@ -1057,17 +1068,9 @@ static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base) goto err_register; } + pdev->dev.of_node = of_node; pdev->dev.parent = dev; - /* Associate subdevice with the corresponding port node */ - pdev->dev.of_node = of_graph_get_port_by_id(dev->of_node, i); - if (!pdev->dev.of_node) { - dev_err(dev, "missing port@%d node in %s\n", i, - dev->of_node->full_name); - ret = -ENODEV; - goto err_register; - } - ret = platform_device_add_data(pdev, ®->pdata, sizeof(reg->pdata)); if (!ret) -- cgit v1.2.3 From 596a65d152fdc777ee7a2c7cbea9a7916350bed1 Mon Sep 17 00:00:00 2001 From: David Jander Date: Thu, 2 Jul 2015 16:21:57 +0200 Subject: gpu: ipu-v3: Reset IPU before activating IRQ If we don't come out of a clean reset, make sure no IRQ is fired before everything is setup by resetting the IPU before activating the interrupt handlers. Signed-off-by: David Jander Signed-off-by: Philipp Zabel --- drivers/gpu/ipu-v3/ipu-common.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index a0e28f3a278d..e00db3f510dd 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c @@ -1292,10 +1292,6 @@ static int ipu_probe(struct platform_device *pdev) ipu->irq_sync = irq_sync; ipu->irq_err = irq_err; - ret = ipu_irq_init(ipu); - if (ret) - goto out_failed_irq; - ret = device_reset(&pdev->dev); if (ret) { dev_err(&pdev->dev, "failed to reset: %d\n", ret); @@ -1305,6 +1301,10 @@ static int ipu_probe(struct platform_device *pdev) if (ret) goto out_failed_reset; + ret = ipu_irq_init(ipu); + if (ret) + goto out_failed_irq; + /* Set MCU_T to divide MCU access window into 2 */ ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18), IPU_DISP_GEN); @@ -1327,9 +1327,9 @@ static int ipu_probe(struct platform_device *pdev) failed_add_clients: ipu_submodules_exit(ipu); failed_submodules_init: -out_failed_reset: ipu_irq_exit(ipu); out_failed_irq: +out_failed_reset: clk_disable_unprepare(ipu->clk); return ret; } -- cgit v1.2.3 From 6c8b66ed0aaf888bfa2545796bf769c1c4593d58 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Tue, 3 Nov 2015 12:02:17 +0100 Subject: drm/imx: notify DRM core about CRTC vblank state Make sure the DRM core is aware that there will be no vblank interrupts incoming if the CRTC is disabled. That way the core will reject any attempts from userspace to wait on a vblank event on a disabled CRTC. Signed-off-by: Lucas Stach Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/ipuv3-crtc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index 30a57185bdb4..287226311413 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -64,6 +64,7 @@ static void ipu_fb_enable(struct ipu_crtc *ipu_crtc) /* Start DC channel and DI after IDMAC */ ipu_dc_enable_channel(ipu_crtc->dc); ipu_di_enable(ipu_crtc->di); + drm_crtc_vblank_on(&ipu_crtc->base); ipu_crtc->enabled = 1; } @@ -80,6 +81,7 @@ static void ipu_fb_disable(struct ipu_crtc *ipu_crtc) ipu_di_disable(ipu_crtc->di); ipu_plane_disable(ipu_crtc->plane[0]); ipu_dc_disable(ipu); + drm_crtc_vblank_off(&ipu_crtc->base); ipu_crtc->enabled = 0; } -- cgit v1.2.3 From 33bee520cbaee22118fb96ab500ba4cd4e8cb749 Mon Sep 17 00:00:00 2001 From: Enrico Jorns Date: Tue, 24 Nov 2015 16:29:22 +0100 Subject: drm/imx: Add missing DRM_FORMAT_RGB565 to ipu_plane_formats DRM_FORMAT_RGB565 is missing from ipu_plane_formats. The support is there, just need to make it available to userspace. Signed-off-by: Enrico Jorns Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/ipuv3-plane.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 591ba2f1ae03..26bb1b626fe3 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -42,6 +42,7 @@ static const uint32_t ipu_plane_formats[] = { DRM_FORMAT_YVYU, DRM_FORMAT_YUV420, DRM_FORMAT_YVU420, + DRM_FORMAT_RGB565, }; int ipu_plane_irq(struct ipu_plane *ipu_plane) -- cgit v1.2.3 From 8e22d79240d95c92b6cbc4c4e4139848de458927 Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Thu, 2 Apr 2015 19:48:39 +0100 Subject: drm: Add support for ARM's HDLCD controller. The HDLCD controller is a display controller that supports resolutions up to 4096x4096 pixels. It is present on various development boards produced by ARM Ltd and emulated by the latest Fast Models from the company. Cc: David Airlie Cc: Robin Murphy Signed-off-by: Liviu Dudau [Kconfig cleanup and !CONFIG_PM fixes] Signed-off-by: Arnd Bergmann Acked-by: Daniel Vetter --- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/arm/Kconfig | 27 ++ drivers/gpu/drm/arm/Makefile | 2 + drivers/gpu/drm/arm/hdlcd_crtc.c | 327 +++++++++++++++++++++++ drivers/gpu/drm/arm/hdlcd_drv.c | 550 +++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/arm/hdlcd_drv.h | 42 +++ drivers/gpu/drm/arm/hdlcd_regs.h | 87 +++++++ 8 files changed, 1038 insertions(+) create mode 100644 drivers/gpu/drm/arm/Kconfig create mode 100644 drivers/gpu/drm/arm/Makefile create mode 100644 drivers/gpu/drm/arm/hdlcd_crtc.c create mode 100644 drivers/gpu/drm/arm/hdlcd_drv.c create mode 100644 drivers/gpu/drm/arm/hdlcd_drv.h create mode 100644 drivers/gpu/drm/arm/hdlcd_regs.h (limited to 'drivers') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 8ae7ab68cb97..438e92d4c389 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -106,6 +106,8 @@ config DRM_TDFX Choose this option if you have a 3dfx Banshee or Voodoo3 (or later), graphics card. If M is selected, the module will be called tdfx. +source "drivers/gpu/drm/arm/Kconfig" + config DRM_R128 tristate "ATI Rage 128" depends on DRM && PCI diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 61766dec6a8d..f80fdbaeb641 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -33,6 +33,7 @@ CFLAGS_drm_trace_points.o := -I$(src) obj-$(CONFIG_DRM) += drm.o obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o +obj-$(CONFIG_DRM_ARM) += arm/ obj-$(CONFIG_DRM_TTM) += ttm/ obj-$(CONFIG_DRM_TDFX) += tdfx/ obj-$(CONFIG_DRM_R128) += r128/ diff --git a/drivers/gpu/drm/arm/Kconfig b/drivers/gpu/drm/arm/Kconfig new file mode 100644 index 000000000000..eaed454e043c --- /dev/null +++ b/drivers/gpu/drm/arm/Kconfig @@ -0,0 +1,27 @@ +config DRM_ARM + bool + help + Choose this option to select drivers for ARM's devices + +config DRM_HDLCD + tristate "ARM HDLCD" + depends on DRM && OF && (ARM || ARM64) + depends on COMMON_CLK + select DRM_ARM + select DRM_KMS_HELPER + select DRM_KMS_FB_HELPER + select DRM_KMS_CMA_HELPER + help + Choose this option if you have an ARM High Definition Colour LCD + controller. + + If M is selected the module will be called hdlcd. + +config DRM_HDLCD_SHOW_UNDERRUN + bool "Show underrun conditions" + depends on DRM_HDLCD + default n + help + Enable this option to show in red colour the pixels that the + HDLCD device did not fetch from framebuffer due to underrun + conditions. diff --git a/drivers/gpu/drm/arm/Makefile b/drivers/gpu/drm/arm/Makefile new file mode 100644 index 000000000000..89dcb7bab93a --- /dev/null +++ b/drivers/gpu/drm/arm/Makefile @@ -0,0 +1,2 @@ +hdlcd-y := hdlcd_drv.o hdlcd_crtc.o +obj-$(CONFIG_DRM_HDLCD) += hdlcd.o diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c new file mode 100644 index 000000000000..fef1b04c2aab --- /dev/null +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2013-2015 ARM Limited + * Author: Liviu Dudau + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Implementation of a CRTC class for the HDLCD driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include